diff --git a/data_object/bundle.json b/data_object/bundle.json index 5af3608a925ebc2b01c675213c26fdf9ae7409fa..ff06c9e8822f8933c4eaabd5a7384a1a1f260a62 100644 --- a/data_object/bundle.json +++ b/data_object/bundle.json @@ -3,9 +3,9 @@ "version": "3.1.0", "description": "The distributed data object management framework is an object-oriented in-memory data management framework", "homePage": "https://gitee.com/openharmony", - "license": "Apache V2", - "repository": "https://gitee.com/openharmony/distributeddatamgr_data_object ", - "domain": "ohos", + "license": "Apache-2.0", + "repository": "https://gitee.com/openharmony/distributeddatamgr_data_object", + "domain": "os", "language": "", "publishAs": "code-segment", "private": false, @@ -61,12 +61,14 @@ "dmsfwk", "hisysevent" ], - "third_party": [] + "third_party": [ + "ffmpeg", + "libexif" + ] }, "build": { "sub_component": [ - "//foundation/distributeddatamgr/data_object/interfaces/jskits:build_module", - "//foundation/distributeddatamgr/data_object/frameworks/jskitsimpl/collaboration_edit:collaborationeditobject" + "//foundation/distributeddatamgr/data_object/interfaces/jskits:build_module" ], "inner_kits": [ { diff --git a/data_object/frameworks/innerkitsimpl/collaboration_edit/include/cloud_db_proxy.h b/data_object/frameworks/innerkitsimpl/collaboration_edit/include/cloud_db_proxy.h index 20a378e9fb6cc2b00f63a6d66938c3270f1f0406..db878ba4d1fb1e44dd2da7201a65491bf7f00554 100644 --- a/data_object/frameworks/innerkitsimpl/collaboration_edit/include/cloud_db_proxy.h +++ b/data_object/frameworks/innerkitsimpl/collaboration_edit/include/cloud_db_proxy.h @@ -26,7 +26,7 @@ typedef struct ExtendRecordField { GRD_CloudFieldTypeE type; std::string fieldName; std::string fieldValue_str; - const void *valuePtr; + const void *valuePtr = nullptr; uint32_t valueLen; } ExtendRecordFieldT; @@ -34,6 +34,7 @@ typedef void (*ExtendFieldParser)(CloudParamsAdapterT &extend, ExtendRecordField class CloudDbProxy { public: + ~CloudDbProxy(); static int32_t BatchInsert(void *cloudDB, GRD_CloudParamsT *cloudParams); static int32_t Query(void *cloudDB, GRD_CloudParamsT *cloudParams); static int32_t DownloadAsset(void *cloudDB, const char *equipId, char *path); @@ -63,8 +64,9 @@ private: static int32_t ParseExtendField(CloudParamsAdapterT &extend, uint32_t index, GRD_CloudRecordT *records, uint32_t maxRecordSize); static void FreeExtendFields(GRD_CloudFieldT *fields, uint8_t fieldSize); + static int64_t GetCursorValue(GRD_CloudFieldT &field); - NapiCloudDb *napiCloudDb_; + NapiCloudDb *napiCloudDb_ = nullptr; }; } // namespace OHOS::CollaborationEdit #endif // COLLABORATION_EDIT_CLOUD_DB_PROXY_H diff --git a/data_object/frameworks/innerkitsimpl/collaboration_edit/include/db_store.h b/data_object/frameworks/innerkitsimpl/collaboration_edit/include/db_store.h index 0c1e798d4692aa73406d1576bd420ff4115ee782..c199a592a0e1e0d4fe86ceaa48a659589c3fe6bb 100644 --- a/data_object/frameworks/innerkitsimpl/collaboration_edit/include/db_store.h +++ b/data_object/frameworks/innerkitsimpl/collaboration_edit/include/db_store.h @@ -16,6 +16,7 @@ #ifndef COLLABORATION_EDIT_DB_STORE_H #define COLLABORATION_EDIT_DB_STORE_H +#include "cloud_db_proxy.h" #include "db_store_config.h" #include "grd_type_export.h" @@ -33,10 +34,15 @@ public: int WriteUpdate(const char *equipId, const uint8_t *data, uint32_t size, const std::string &watermark); int GetRelativePos(const char *tableName, const char *nodeSize, uint32_t pos, std::string &relPos); int GetAbsolutePos(const char *tableName, const char *relPos, const char *nodeSize, uint32_t *pos); + void SetCloudDbProxy(CloudDbProxy* proxy, GRD_ICloudDBT *cloudDB); + GRD_ICloudDBT *GetCloudDB(); + void FreeCloudDB(); private: - GRD_DB *db_; + GRD_DB *db_ = nullptr; std::string name_; std::shared_ptr localId_; + CloudDbProxy* proxy_ = nullptr; + GRD_ICloudDBT *cloudDB_ = nullptr; }; } // namespace OHOS::CollaborationEdit #endif // COLLABORATION_EDIT_DB_STORE_H diff --git a/data_object/frameworks/innerkitsimpl/collaboration_edit/src/cloud_db_proxy.cpp b/data_object/frameworks/innerkitsimpl/collaboration_edit/src/cloud_db_proxy.cpp index 0da7cca9d3cfac44fa7998a9b563d7c8167695f0..f267070640ee439f64498809efe5d683e2722730 100644 --- a/data_object/frameworks/innerkitsimpl/collaboration_edit/src/cloud_db_proxy.cpp +++ b/data_object/frameworks/innerkitsimpl/collaboration_edit/src/cloud_db_proxy.cpp @@ -43,6 +43,8 @@ const std::string CURSOR = "cursor"; const std::string SYNC_LOG_EVENT = "syncLogEvent"; const std::string TIMESTAMP = "timestamp"; +constexpr int CURSOR_BASE = 10; + static const std::map PREDICATE_MAP = { {GRD_QUERY_CONDITION_TYPE_EQUAL_TO, EQUAL_TO}, {GRD_QUERY_CONDITION_TYPE_NOT_EQUAL_TO, NOT_EQUAL_TO}, @@ -59,6 +61,14 @@ static const std::map QRY_RSP_PARSER_MAP = { {QRY_RSP_CURSOR_IDX, CloudDbProxy::CursorParseFunc} }; +CloudDbProxy::~CloudDbProxy() +{ + if (napiCloudDb_ != nullptr) { + delete napiCloudDb_; + napiCloudDb_ = nullptr; + } +} + void CloudDbProxy::SetNapiCloudDb(NapiCloudDb *napiCloudDb) { napiCloudDb_ = napiCloudDb; @@ -254,14 +264,11 @@ int32_t CloudDbProxy::GetQueryParams(GRD_CloudParamsT *cloudParams, std::vector< queryConditions.push_back(condition); continue; } - std::string tmpString; - tmpString.resize(field.valueLen); - errno_t errNo = memcpy_s(&tmpString[0], field.valueLen, field.value, field.valueLen); - if (errNo != EOK) { - LOG_ERROR("copy cursor value wrong"); - return E_MEMORY_OPERATION_ERROR; + condition.fieldValue_num = GetCursorValue(field); + if (condition.fieldValue_num < 0) { + queryConditions.clear(); + return E_INVALID_ARGS; } - condition.fieldValue_num = std::stoi(tmpString); } else if (condition.fieldName == EQUIP_ID) { condition.fieldValue_str = std::string(static_cast(field.value)); } else { @@ -274,6 +281,33 @@ int32_t CloudDbProxy::GetQueryParams(GRD_CloudParamsT *cloudParams, std::vector< return E_OK; } +int64_t CloudDbProxy::GetCursorValue(GRD_CloudFieldT &field) +{ + int64_t cursor = -1; + if (field.value == nullptr) { + LOG_ERROR("field value is null"); + return cursor; + } + std::string tmpString; + tmpString.resize(field.valueLen); + errno_t errNo = memcpy_s(&tmpString[0], field.valueLen, field.value, field.valueLen); + if (errNo != EOK) { + LOG_ERROR("copy cursor value wrong"); + return cursor; + } + errno = 0; + cursor = std::strtol(tmpString.c_str(), nullptr, CURSOR_BASE); + if (errno == EINVAL) { + LOG_ERROR("cursor field is not integer"); + cursor = -1; + } + if (errno == ERANGE) { + LOG_ERROR("cursor is too long"); + cursor = -1; + } + return cursor; +} + void CloudDbProxy::CursorParseFunc(CloudParamsAdapterT &extend, ExtendRecordFieldT &destField) { destField.type = GRD_CLOUD_FIELD_TYPE_STRING; diff --git a/data_object/frameworks/innerkitsimpl/collaboration_edit/src/db_store.cpp b/data_object/frameworks/innerkitsimpl/collaboration_edit/src/db_store.cpp index 7e9dde5c50f07dcfa3c7ce99c8e7019577c01228..ad5327b4e486ae6f52516916318629ad04222aa2 100644 --- a/data_object/frameworks/innerkitsimpl/collaboration_edit/src/db_store.cpp +++ b/data_object/frameworks/innerkitsimpl/collaboration_edit/src/db_store.cpp @@ -36,6 +36,19 @@ DBStore::DBStore(GRD_DB *db, std::string name) : db_(db), name_(name) DBStore::~DBStore() {} +void DBStore::FreeCloudDB() +{ + if (cloudDB_ != nullptr) { + free(cloudDB_->assetLoader); + free(cloudDB_); + cloudDB_ = nullptr; + } + if (proxy_ != nullptr) { + delete proxy_; + proxy_ = nullptr; + } +} + std::string DBStore::GetLocalId() { if (localId_) { @@ -95,6 +108,17 @@ GRD_DB *DBStore::GetDB() return db_; } +GRD_ICloudDBT* DBStore::GetCloudDB() +{ + return cloudDB_; +} + +void DBStore::SetCloudDbProxy(CloudDbProxy *proxy, GRD_ICloudDBT *cloudDB) +{ + proxy_ = proxy; + cloudDB_ = cloudDB; +} + int DBStore::ApplyUpdate(std::string &applyInfo) { char *retStr = nullptr; diff --git a/data_object/frameworks/innerkitsimpl/collaboration_edit/src/db_store_manager.cpp b/data_object/frameworks/innerkitsimpl/collaboration_edit/src/db_store_manager.cpp index 3cd0e16b4c755c74faf16cf624751198a79469cb..955be6fcf6c50fb83dfaae5224efd90229c1c7ca 100644 --- a/data_object/frameworks/innerkitsimpl/collaboration_edit/src/db_store_manager.cpp +++ b/data_object/frameworks/innerkitsimpl/collaboration_edit/src/db_store_manager.cpp @@ -109,6 +109,7 @@ int DBStoreManager::DeleteDBStore(const DBStoreConfig &config) LOG_ERROR("[DeleteDBStore] db close go wrong, err = %{public}d", errCode); return -1; } + dbStorePtr->FreeCloudDB(); } int ret = RemoveDir(dbPath.c_str()); if (ret != 0) { @@ -204,6 +205,7 @@ int DBStoreManager::SetCloudDb(std::shared_ptr dbStore, NapiCloudDb *na delete cloudDbProxy; return -1; } + dbStore->SetCloudDbProxy(cloudDbProxy, cloudDB); return 0; } diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/asset_change_timer.h b/data_object/frameworks/innerkitsimpl/include/adaptor/asset_change_timer.h index fd45e258f8dfc50a8997cf9a2a66ca2b6b1cff4f..9ccff883e471cc10def372a34942dcf7d4286efd 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/asset_change_timer.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/asset_change_timer.h @@ -30,7 +30,7 @@ private: ~AssetChangeTimer() = default; AssetChangeTimer(const AssetChangeTimer &) = delete; AssetChangeTimer &operator=(const AssetChangeTimer &) = delete; - AssetChangeTimer(FlatObjectStore *flatObjectStore); + explicit AssetChangeTimer(FlatObjectStore *flatObjectStore); void StartTimer(const std::string &sessionId, const std::string &assetKey, std::shared_ptr watcher); void StopTimer(const std::string &sessionId, const std::string &assetKey); std::function ProcessTask( diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/client_adaptor.h b/data_object/frameworks/innerkitsimpl/include/adaptor/client_adaptor.h index 6fa8b1c63abbcca2453dcd464fb2cf0b77a04ec2..46e1d7fe46f33a48158cbf42568315b89c04b0d1 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/client_adaptor.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/client_adaptor.h @@ -33,6 +33,9 @@ private: void OnRemoteDied(const wptr &remote) override; }; + static constexpr int32_t DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID = 1301; + static constexpr int32_t GET_SA_RETRY_TIMES = 3; + static constexpr int32_t RETRY_INTERVAL = 1; static std::shared_ptr distributedDataMgr_; static std::shared_ptr GetDistributedDataManager(); static std::mutex mutex_; diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/distributed_objectstore_impl.h b/data_object/frameworks/innerkitsimpl/include/adaptor/distributed_objectstore_impl.h index a191f6c343849598cce0f6af73d1242f2860a0d0..829b336d027462ab9940eb957d61e4b7673bb165 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/distributed_objectstore_impl.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/distributed_objectstore_impl.h @@ -38,7 +38,9 @@ public: uint32_t Watch(DistributedObject *object, std::shared_ptr watcher) override; uint32_t UnWatch(DistributedObject *object) override; uint32_t SetStatusNotifier(std::shared_ptr notifier) override; + uint32_t SetProgressNotifier(std::shared_ptr notifier) override; void NotifyCachedStatus(const std::string &sessionId) override; + void NotifyProgressStatus(const std::string &sessionId) override; private: DistributedObject *CacheObject(const std::string &sessionId, FlatObjectStore *flatObjectStore); @@ -59,6 +61,17 @@ public: private: std::shared_ptr notifier; }; + +class ProgressNotifierProxy : public ProgressWatcher { +public: + virtual ~ProgressNotifierProxy(); + ProgressNotifierProxy(const std::shared_ptr ¬ifier); + void OnChanged(const std::string &sessionId, int32_t progress) override; + +private: + std::shared_ptr notifier; +}; + class WatcherProxy : public FlatObjectWatcher { public: using AssetChangeCallback = std::function watcher) override; uint32_t UnRegisterObserver(const std::string &key) override; uint32_t SetStatusNotifier(std::shared_ptr watcher) override; + uint32_t SetProgressNotifier(std::shared_ptr watcher) override; uint32_t SyncAllData(const std::string &sessionId, const std::vector &deviceIds, const std::function &)> &onComplete); void OnComplete(const std::string &key, const std::map &devices, @@ -42,13 +43,18 @@ public: bool isOpened_ = false; void NotifyStatus(const std::string &sessionId, const std::string &deviceId, const std::string &status); void NotifyChange(const std::string &sessionId, const std::map> &changedData); + bool NotifyProgress(const std::string &sessionId, int32_t progress); + private: + constexpr static const char *DISTRIBUTED_DATASYNC = "ohos.permission.DISTRIBUTED_DATASYNC"; std::mutex operationMutex_{}; std::mutex watcherMutex_{}; + std::mutex progressMutex_{}; std::shared_ptr storeManager_; std::map delegates_; std::map> observerMap_; std::shared_ptr statusWatcher_ = nullptr; + std::shared_ptr progressWatcher_ = nullptr; }; } // namespace OHOS::ObjectStore #endif diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/flat_object_store.h b/data_object/frameworks/innerkitsimpl/include/adaptor/flat_object_store.h index e06449fd24bda779744788767642a59267d13152..71d74cb9090871774d20f31a64e7f591e8e0ae62 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/flat_object_store.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/flat_object_store.h @@ -41,6 +41,9 @@ public: int32_t SubscribeDataChange(const std::string &bundleName, const std::string &sessionId, std::function> &data, bool allReady)> &callback); int32_t UnregisterDataChange(const std::string &bundleName, const std::string &sessionId); + int32_t SubscribeProgressChange( + const std::string &bundleName, const std::string &sessionId, std::function &callback); + int32_t UnregisterProgressChange(const std::string &bundleName, const std::string &sessionId); int32_t DeleteSnapshot(const std::string &bundleName, const std::string &sessionId); bool IsContinue(); private: @@ -50,6 +53,7 @@ private: int32_t RevokeSaveObject( const std::string &bundleName, const std::string &sessionId, const std::function &callback); std::mutex mutex_; + static constexpr uint32_t WAIT_TIME = 5; }; class FlatObjectStore { @@ -60,15 +64,17 @@ public: uint32_t CreateObject(const std::string &sessionId); void ResumeObject(const std::string &sessionId); void SubscribeDataChange(const std::string &sessionId); + void SubscribeProgressChange(const std::string &sessionId); uint32_t Delete(const std::string &objectId); uint32_t Watch(const std::string &objectId, std::shared_ptr watcher); uint32_t UnWatch(const std::string &objectId); uint32_t SetStatusNotifier(std::shared_ptr sharedPtr); + uint32_t SetProgressNotifier(std::shared_ptr sharedPtr); uint32_t Save(const std::string &sessionId, const std::string &deviceId); uint32_t RevokeSave(const std::string &sessionId); void CheckRetrieveCache(const std::string &sessionId); - void FilterData(const std::string &sessionId, - std::map> &data); + void CheckProgressCache(const std::string &sessionId); + void FilterData(const std::string &sessionId, std::map> &data); uint32_t PutDouble(const std::string &sessionId, const std::string &key, double value); uint32_t PutBoolean(const std::string &sessionId, const std::string &key, bool value); uint32_t PutString(const std::string &sessionId, const std::string &key, const std::string &value); @@ -83,10 +89,13 @@ private: uint32_t Put(const std::string &sessionId, const std::string &key, std::vector value); uint32_t Get(const std::string &sessionId, const std::string &key, Bytes &value); + static constexpr const char* DISTRIBUTED_DATASYNC = "ohos.permission.DISTRIBUTED_DATASYNC"; std::shared_ptr storageEngine_; - CacheManager *cacheManager_; + CacheManager *cacheManager_ = nullptr; std::mutex mutex_; + std::mutex progressInfoMutex_; std::vector retrievedCache_ {}; + std::map progressInfoCache_; std::string bundleName_; }; } // namespace OHOS::ObjectStore diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/hitrace.h b/data_object/frameworks/innerkitsimpl/include/adaptor/hitrace.h index 447ff538b314877dad7197a205467a7b4ab5be1b..5c2dd287f0c6d3d103b4993c33c6a13015baee07 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/hitrace.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/hitrace.h @@ -23,12 +23,12 @@ class DataObjectHiTrace final { public: inline DataObjectHiTrace(const std::string &value) { - StartTrace(HITRACE_TAG_DISTRIBUTEDDATA, value); + StartTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_TAG_DISTRIBUTEDDATA, value.c_str(), ""); } inline ~DataObjectHiTrace() { - FinishTrace(HITRACE_TAG_DISTRIBUTEDDATA); + FinishTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_TAG_DISTRIBUTEDDATA); } }; } // namespace ObjectStore diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/object_callback_impl.h b/data_object/frameworks/innerkitsimpl/include/adaptor/object_callback_impl.h index f61b0594394616e1962e6c1f7b6c894a0e5c1d38..16f50d091d6788069ed680393fb2fbf2130b1c98 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/object_callback_impl.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/object_callback_impl.h @@ -58,6 +58,15 @@ public: private: const std::function> &, bool)> callback_; }; + +class ObjectProgressCallback : public ObjectProgressCallbackStub { +public: + ObjectProgressCallback(const std::function &callback); + void Completed(int32_t progress) override; + +private: + const std::function callback_; +}; } // namespace ObjectStore } // namespace OHOS diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/object_service.h b/data_object/frameworks/innerkitsimpl/include/adaptor/object_service.h index 3898d7188d1846ceb32ff24b2f8ec235f5963721..0385d6b5b7a9a669af3baa7f039fb3004f5b67a4 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/object_service.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/object_service.h @@ -28,6 +28,8 @@ public: const std::string &bundleName, const std::string &sessionId, sptr callback) = 0; virtual int32_t RegisterDataObserver( const std::string &bundleName, const std::string &sessionId, sptr callback) = 0; + virtual int32_t RegisterProgressObserver( + const std::string &bundleName, const std::string &sessionId, sptr callback) = 0; }; } // namespace OHOS::ObjectStore #endif diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/object_storage_engine.h b/data_object/frameworks/innerkitsimpl/include/adaptor/object_storage_engine.h index 7678e60108d72c1c79907f111df065f97f880767..8b6d5ac5df9c29028c942dfa2f3ff2f032c0ad30 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/object_storage_engine.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/object_storage_engine.h @@ -38,6 +38,11 @@ public: const std::string &sessionId, const std::string &networkId, const std::string &onlineStatus) = 0; }; +class ProgressWatcher { +public: + virtual void OnChanged(const std::string &sessionId, int32_t progress) = 0; +}; + class ObjectStorageEngine { public: ObjectStorageEngine(const ObjectStorageEngine &) = delete; @@ -58,6 +63,7 @@ public: virtual uint32_t RegisterObserver(const std::string &key, std::shared_ptr watcher) = 0; virtual uint32_t UnRegisterObserver(const std::string &key) = 0; virtual uint32_t SetStatusNotifier(std::shared_ptr watcher) = 0; + virtual uint32_t SetProgressNotifier(std::shared_ptr watcher) = 0; }; } // namespace OHOS::ObjectStore #endif \ No newline at end of file diff --git a/data_object/frameworks/innerkitsimpl/include/common/bytes.h b/data_object/frameworks/innerkitsimpl/include/common/bytes.h index ecfcbc25c6c6b921af7db77c279aff067be09a3f..2648f5316181730fb1484bf3ea3418c8fea7dba4 100644 --- a/data_object/frameworks/innerkitsimpl/include/common/bytes.h +++ b/data_object/frameworks/innerkitsimpl/include/common/bytes.h @@ -15,6 +15,7 @@ #ifndef BYTES_H #define BYTES_H + #include #include diff --git a/data_object/frameworks/innerkitsimpl/include/common/common_types.h b/data_object/frameworks/innerkitsimpl/include/common/common_types.h index 67d4e2e7081f375eba0310428bbb7448ed7b69a7..50dbc05c2c7aee49345973fd18a9f8a8a9e2b6f1 100644 --- a/data_object/frameworks/innerkitsimpl/include/common/common_types.h +++ b/data_object/frameworks/innerkitsimpl/include/common/common_types.h @@ -13,12 +13,11 @@ * limitations under the License. */ -#ifndef OHOS_DATA_OBJECT_COMMON_TYPES_H -#define OHOS_DATA_OBJECT_COMMON_TYPES_H +#ifndef OHOS_COMMON_TYPES_H +#define OHOS_COMMON_TYPES_H #include #include #include -#include namespace OHOS::CommonType { struct AssetValue { enum Status : int32_t { diff --git a/data_object/frameworks/innerkitsimpl/include/common/logger.h b/data_object/frameworks/innerkitsimpl/include/common/logger.h index ef712797619375504ddbc8675abdf726fdfe03f2..ae209ff85855b2c6f3dbe0f565621723679754b4 100644 --- a/data_object/frameworks/innerkitsimpl/include/common/logger.h +++ b/data_object/frameworks/innerkitsimpl/include/common/logger.h @@ -70,10 +70,8 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() } // namespace OHOS::ObjectStore #else -#include -#include -#define __FILE_NAME__ __FILE__ +#define __FILE_NAME__ __FILE__ #define LOG_DEBUG(fmt, ...) \ printf("[D][ObjectStore]%s:%d %s: " fmt "\n", __FILE_NAME__, __LINE__, __FUNCTION__, ##__VA_ARGS__) #define LOG_ERROR(fmt, ...) \ 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 ea4922fc9b12d40baa98762ed4c2732a10f81216..0803b5ffa52eed0c7ad8bb40a87088f8bec05339 100644 --- a/data_object/frameworks/innerkitsimpl/include/common/object_radar_reporter.h +++ b/data_object/frameworks/innerkitsimpl/include/common/object_radar_reporter.h @@ -64,6 +64,9 @@ enum ErrorCode : int32_t { GETKV_FAILED = OFFSET + 6, DB_NOT_INIT = OFFSET + 7, }; +constexpr char DOMAIN[] = "DISTDATAMGR"; +constexpr char EVENT_NAME[] = "DISTRIBUTED_DATA_OBJECT_BEHAVIOR"; +constexpr char ORG_PKG[] = "distributeddata"; class API_EXPORT RadarReporter { public: diff --git a/data_object/frameworks/innerkitsimpl/include/communicator/block_data.h b/data_object/frameworks/innerkitsimpl/include/communicator/block_data.h new file mode 100644 index 0000000000000000000000000000000000000000..faee9187106a9d53b00829a1b03f54e4e396f373 --- /dev/null +++ b/data_object/frameworks/innerkitsimpl/include/communicator/block_data.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025 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_BLOCK_DATA_H +#define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_BLOCK_DATA_H +#include +#include + +namespace OHOS { +template +class BlockData { +public: + explicit BlockData(uint32_t interval, const T &invalid = T()) : INTERVAL(interval), data_(invalid) {} + + ~BlockData() {} + + void SetValue(const T &data) + { + std::lock_guard lock(mutex_); + data_ = data; + isSet_ = true; + cv_.notify_one(); + } + + T GetValue() + { + std::unique_lock lock(mutex_); + cv_.wait_for(lock, Dur(INTERVAL), [this]() { + return isSet_; + }); + T data = data_; + cv_.notify_one(); + return data; + } + + void Clear(const T &invalid = T()) + { + std::lock_guard lock(mutex_); + isSet_ = false; + data_ = invalid; + cv_.notify_one(); + } + +private: + bool isSet_ = false; + const uint32_t INTERVAL; + T data_; + std::mutex mutex_; + std::condition_variable cv_; +}; +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_BLOCK_DATA_H \ No newline at end of file diff --git a/data_object/frameworks/innerkitsimpl/include/communicator/communication_provider.h b/data_object/frameworks/innerkitsimpl/include/communicator/communication_provider.h index e91f6b27a50be5299ae3e18fad4da0e6ca8cdd13..d5540868b47f318f2dd6ec379c57ef7f0eed0ce8 100644 --- a/data_object/frameworks/innerkitsimpl/include/communicator/communication_provider.h +++ b/data_object/frameworks/innerkitsimpl/include/communicator/communication_provider.h @@ -15,8 +15,6 @@ #ifndef DISTRIBUTEDDATA_COMMUNICATION_PROVIDER_H #define DISTRIBUTEDDATA_COMMUNICATION_PROVIDER_H - -#include #include #include "app_data_change_listener.h" diff --git a/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h b/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h index a4be9d5827c2c0ea7fd3e5675adbd917a20e3901..0ddbb02afe62652053ede12a8f58e204d27909fa 100644 --- a/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h +++ b/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h @@ -41,7 +41,6 @@ public: DeviceInfo GetLocalBasicInfo() const; // get all remote connected device's node information; std::vector GetRemoteNodesBasicInfo() const; - static std::string ToBeAnonymous(const std::string &name); // add DataChangeListener to watch data change; Status StartWatchDataChange(const AppDataChangeListener *observer, const PipeInfo &pipeInfo); diff --git a/data_object/frameworks/innerkitsimpl/include/communicator/task_scheduler.h b/data_object/frameworks/innerkitsimpl/include/communicator/task_scheduler.h new file mode 100644 index 0000000000000000000000000000000000000000..f46da8c9a0ac05c574fce28d7c49d47690652e2f --- /dev/null +++ b/data_object/frameworks/innerkitsimpl/include/communicator/task_scheduler.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2025 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_TASK_SCHEDULER_H +#define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_TASK_SCHEDULER_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace OHOS { +class TaskScheduler { +public: + using TaskId = uint64_t; + using Time = std::chrono::steady_clock::time_point; + using Duration = std::chrono::steady_clock::duration; + using Clock = std::chrono::steady_clock; + using Task = std::function; + inline static constexpr TaskId INVALID_TASK_ID = static_cast(0l); + inline static constexpr Duration INVALID_INTERVAL = std::chrono::milliseconds(0); + inline static constexpr uint64_t UNLIMITED_TIMES = std::numeric_limits::max(); + TaskScheduler(size_t capacity, const std::string &name) + { + capacity_ = capacity; + isRunning_ = true; + taskId_ = INVALID_TASK_ID; + running_ = InnerTask(); + thread_ = std::make_unique([this, name]() { + auto realName = std::string("scheduler_") + name; + pthread_setname_np(pthread_self(), realName.c_str()); + Loop(); + }); + } + TaskScheduler(const std::string &name) : TaskScheduler(std::numeric_limits::max(), name) {} + TaskScheduler(size_t capacity = std::numeric_limits::max()) : TaskScheduler(capacity, "") {} + ~TaskScheduler() + { + isRunning_ = false; + Clean(); + Execute([]() {}); + thread_->join(); + } + // execute task at specific time + TaskId At(const Time &begin, Task task, Duration interval = INVALID_INTERVAL, uint64_t times = UNLIMITED_TIMES) + { + std::unique_lock lock(mutex_); + if (tasks_.size() >= capacity_) { + return INVALID_TASK_ID; + } + InnerTask innerTask; + innerTask.times = times; + innerTask.taskId = GenTaskId(); + innerTask.interval = interval; + innerTask.exec = std::move(task); + auto it = tasks_.insert({ begin, innerTask}); + if (it == tasks_.begin()) { + condition_.notify_one(); + } + indexes_[innerTask.taskId] = it; + return innerTask.taskId; + } + TaskId Reset(TaskId taskId, const Duration &interval) + { + std::unique_lock lock(mutex_); + if (running_.taskId == taskId && running_.interval != INVALID_INTERVAL) { + running_.interval = interval; + return running_.taskId; + } + auto index = indexes_.find(taskId); + if (index == indexes_.end()) { + return INVALID_TASK_ID; + } + auto &innerTask = index->second->second; + if (innerTask.interval != INVALID_INTERVAL) { + innerTask.interval = interval; + } + auto it = tasks_.insert({ std::chrono::steady_clock::now() + interval, std::move(innerTask) }); + if (it == tasks_.begin() || index->second == tasks_.begin()) { + condition_.notify_one(); + } + tasks_.erase(index->second); + indexes_[taskId] = it; + return taskId; + } + void Clean() + { + std::unique_lock lock(mutex_); + indexes_.clear(); + tasks_.clear(); + } + // execute task periodically with duration + TaskId Every(Duration interval, Task task) + { + return At(std::chrono::steady_clock::now() + interval, task, interval); + } + // remove task in SchedulerTask + void Remove(TaskId taskId, bool wait = false) + { + std::unique_lock lock(mutex_); + cond_.wait(lock, [this, taskId, wait]() { + return (!wait || running_.taskId != taskId); + }); + auto index = indexes_.find(taskId); + if (index == indexes_.end()) { + return; + } + tasks_.erase(index->second); + indexes_.erase(index); + condition_.notify_one(); + } + // execute task periodically with duration after delay + TaskId Every(Duration delay, Duration interval, Task task) + { + return At(std::chrono::steady_clock::now() + delay, task, interval); + } + // execute task for some times periodically with duration after delay + TaskId Every(int32_t times, Duration delay, Duration interval, Task task) + { + return At(std::chrono::steady_clock::now() + delay, task, interval, times); + } + TaskId Execute(Task task) + { + return At(std::chrono::steady_clock::now(), std::move(task)); + } +private: + struct InnerTask { + TaskId taskId = INVALID_TASK_ID; + Duration interval = INVALID_INTERVAL; + uint64_t times = UNLIMITED_TIMES; + std::function exec; + }; + void Loop() + { + while (isRunning_) { + std::function exec; + { + std::unique_lock lock(mutex_); + condition_.wait(lock, [this] { + return !tasks_.empty(); + }); + if (tasks_.begin()->first > std::chrono::steady_clock::now()) { + auto time = tasks_.begin()->first; + condition_.wait_until(lock, time); + continue; + } + auto it = tasks_.begin(); + running_ = it->second; + exec = running_.exec; + indexes_.erase(running_.taskId); + tasks_.erase(it); + running_.times--; + } + if (exec) { + exec(); + } + { + std::unique_lock lock(mutex_); + if (running_.interval != INVALID_INTERVAL && running_.times > 0) { + auto it = tasks_.insert({ std::chrono::steady_clock::now() + running_.interval, running_ }); + indexes_[running_.taskId] = it; + } + running_ = InnerTask(); + cond_.notify_all(); + } + } + } + + TaskId GenTaskId() + { + auto taskId = ++taskId_; + if (taskId == INVALID_TASK_ID) { + return ++taskId_; + } + return taskId; + } + + volatile bool isRunning_; + size_t capacity_; + std::multimap tasks_; + std::map indexes_; + InnerTask running_; + std::mutex mutex_; + std::unique_ptr thread_; + std::condition_variable condition_; + std::condition_variable cond_; + std::atomic taskId_; +}; +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_TASK_SCHEDULER_H diff --git a/data_object/frameworks/innerkitsimpl/include/distributeddata_object_store_ipc_interface_code.h b/data_object/frameworks/innerkitsimpl/include/distributeddata_object_store_ipc_interface_code.h index 0523098b55dcda33198b02eda882e03865ae679f..1d3d3f04256d794ea07a05e262f6840ba16f7c9b 100644 --- a/data_object/frameworks/innerkitsimpl/include/distributeddata_object_store_ipc_interface_code.h +++ b/data_object/frameworks/innerkitsimpl/include/distributeddata_object_store_ipc_interface_code.h @@ -30,6 +30,8 @@ enum class ObjectServiceInterfaceCode : int8_t { OBJECTSTORE_BIND_ASSET_STORE, OBJECTSTORE_DELETE_SNAPSHOT, OBJECTSTORE_IS_CONTINUE, + OBJECTSTORE_REGISTER_PROGRESS, + OBJECTSTORE_UNREGISTER_PROGRESS, OBJECTSTORE_SERVICE_CMD_MAX }; @@ -37,7 +39,7 @@ enum class KvStoreServiceInterfaceCode : int8_t { GET_FEATURE_INTERFACE = 0, REGISTERCLIENTDEATHOBSERVER, }; -} -} // namespace OHOS +} // namespace ObjectStoreService +} // namespace OHOS::DistributedObject #endif // DISTRIBUTEDDATA_OBJECT_STORE_IPC_INTERFACE_H \ No newline at end of file diff --git a/data_object/frameworks/innerkitsimpl/include/object_callback.h b/data_object/frameworks/innerkitsimpl/include/object_callback.h index 9279a0adfee965f306098c40789bef62ae819c85..3e6787bf0d553699b22373d9d0875f68bf4f8ee4 100644 --- a/data_object/frameworks/innerkitsimpl/include/object_callback.h +++ b/data_object/frameworks/innerkitsimpl/include/object_callback.h @@ -43,6 +43,11 @@ class IObjectChangeCallback { public: virtual void Completed(const std::map> &results, bool allReady) = 0; }; + +class IObjectProgressCallback { +public: + virtual void Completed(int32_t progress) = 0; +}; } // namespace DistributedObject } // namespace OHOS diff --git a/data_object/frameworks/innerkitsimpl/include/object_callback_stub.h b/data_object/frameworks/innerkitsimpl/include/object_callback_stub.h index 8a7c7109b645fa7034897002c777ea1bc5c76eba..d446132f704eb062b83896f7c41d5cb404aa957e 100644 --- a/data_object/frameworks/innerkitsimpl/include/object_callback_stub.h +++ b/data_object/frameworks/innerkitsimpl/include/object_callback_stub.h @@ -59,6 +59,16 @@ class ObjectChangeCallbackStub : public IRemoteStub public: int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; }; + +class ObjectProgressCallbackBroker : public IObjectProgressCallback, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedObject.IObjectProgressCallback"); +}; + +class ObjectProgressCallbackStub : public IRemoteStub { +public: + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +}; } // namespace DistributedObject } // namespace OHOS diff --git a/data_object/frameworks/innerkitsimpl/include/object_service.h b/data_object/frameworks/innerkitsimpl/include/object_service.h index d59cc95b0c58e62af7e02d7414bedb7570d73e9b..78a0b13c57fc593cb9b4ee07f29d1f2397224526 100644 --- a/data_object/frameworks/innerkitsimpl/include/object_service.h +++ b/data_object/frameworks/innerkitsimpl/include/object_service.h @@ -31,6 +31,9 @@ public: virtual int32_t RegisterDataObserver( const std::string &bundleName, const std::string &sessionId, sptr callback) = 0; virtual int32_t UnregisterDataChangeObserver(const std::string &bundleName, const std::string &sessionId) = 0; + virtual int32_t RegisterProgressObserver( + const std::string &bundleName, const std::string &sessionId, sptr callback) = 0; + virtual int32_t UnregisterProgressObserver(const std::string &bundleName, const std::string &sessionId) = 0; virtual int32_t OnAssetChanged(const std::string &bundleName, const std::string &sessionId, const std::string &deviceId, const ObjectStore::Asset &assetValue) = 0; virtual int32_t BindAssetStore(const std::string &bundleName, const std::string &sessionId, diff --git a/data_object/frameworks/innerkitsimpl/include/object_service_proxy.h b/data_object/frameworks/innerkitsimpl/include/object_service_proxy.h index 724aa6888253e58ddd6fd270ce43b282a052c352..6403bc6829c33ba31952ace8e913f0a62e9bfeef 100644 --- a/data_object/frameworks/innerkitsimpl/include/object_service_proxy.h +++ b/data_object/frameworks/innerkitsimpl/include/object_service_proxy.h @@ -34,6 +34,9 @@ public: int32_t RegisterDataObserver(const std::string &bundleName, const std::string &sessionId, sptr callback) override; int32_t UnregisterDataChangeObserver(const std::string &bundleName, const std::string &sessionId) override; + int32_t RegisterProgressObserver(const std::string &bundleName, const std::string &sessionId, + sptr callback) override; + int32_t UnregisterProgressObserver(const std::string &bundleName, const std::string &sessionId) override; int32_t OnAssetChanged(const std::string &bundleName, const std::string &sessionId, const std::string &deviceId, const ObjectStore::Asset &assetValue) override; diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/asset_change_timer.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/asset_change_timer.cpp index c65ad97c6347640e06f0e01286e33d488e1619bf..8ded3967c0de85f605abaf8c52393d77b22dbb6c 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/asset_change_timer.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/asset_change_timer.cpp @@ -15,6 +15,7 @@ #define LOG_TAG "AssetChangeTimer" #include "asset_change_timer.h" +#include "anonymous.h" #include "client_adaptor.h" #include "logger.h" #include "objectstore_errors.h" @@ -38,10 +39,9 @@ AssetChangeTimer *AssetChangeTimer::GetInstance(FlatObjectStore *flatObjectStore return instance; } -AssetChangeTimer::AssetChangeTimer(FlatObjectStore *flatObjectStore) +AssetChangeTimer::AssetChangeTimer(FlatObjectStore *flatObjectStore) : flatObjectStore_(flatObjectStore) { - flatObjectStore_ = flatObjectStore; - executor_ = std::make_shared(MAX_THREADS, MIN_THREADS); + executor_ = std::make_shared(MAX_THREADS, MIN_THREADS, "OBJECT_TASK"); } void AssetChangeTimer::OnAssetChanged( @@ -67,13 +67,13 @@ std::function AssetChangeTimer::ProcessTask( const std::string &sessionId, const std::string &assetKey, std::shared_ptr watcher) { return [=]() { - LOG_DEBUG("Start working on a task, sessionId: %{public}s, assetKey: %{public}s", sessionId.c_str(), - assetKey.c_str()); + LOG_DEBUG("Start working on a task, sessionId: %{public}s, assetKey: %{public}s", + Anonymous::Change(sessionId).c_str(), assetKey.c_str()); StopTimer(sessionId, assetKey); uint32_t status = HandleAssetChanges(sessionId, assetKey); if (status == SUCCESS) { LOG_DEBUG("Asset change task end, start callback, sessionId: %{public}s, assetKey: %{public}s", - sessionId.c_str(), assetKey.c_str()); + Anonymous::Change(sessionId).c_str(), assetKey.c_str()); watcher->OnChanged(sessionId, { assetKey }); } }; @@ -92,7 +92,7 @@ uint32_t AssetChangeTimer::HandleAssetChanges(const std::string &sessionId, cons Asset assetValue; if (!GetAssetValue(sessionId, assetKey, assetValue)) { LOG_ERROR("GetAssetValue assetValue is not complete, sessionId: %{public}s, assetKey: %{public}s", - sessionId.c_str(), assetKey.c_str()); + Anonymous::Change(sessionId).c_str(), assetKey.c_str()); return ERR_DB_GET_FAIL; } @@ -111,7 +111,7 @@ uint32_t AssetChangeTimer::HandleAssetChanges(const std::string &sessionId, cons int32_t res = proxy->OnAssetChanged(flatObjectStore_->GetBundleName(), sessionId, deviceId, assetValue); if (res != SUCCESS) { LOG_ERROR("OnAssetChanged failed status: %{public}d, sessionId: %{public}s, assetKey: %{public}s", status, - sessionId.c_str(), assetKey.c_str()); + Anonymous::Change(sessionId).c_str(), assetKey.c_str()); } return res; } diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/client_adaptor.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/client_adaptor.cpp index 633d44ff13919150a966b38be291df7f2c9239cb..9b3c689fcc9344d0d4aa3b348c2dc9e7def7e411 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/client_adaptor.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/client_adaptor.cpp @@ -25,9 +25,6 @@ namespace OHOS::ObjectStore { std::shared_ptr ClientAdaptor::distributedDataMgr_ = nullptr; std::mutex ClientAdaptor::mutex_; -static constexpr int32_t DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID = 1301; -static constexpr int32_t GET_SA_RETRY_TIMES = 3; -static constexpr int32_t RETRY_INTERVAL = 1; using KvStoreCode = OHOS::DistributedObject::ObjectStoreService::KvStoreServiceInterfaceCode; @@ -187,7 +184,7 @@ uint32_t ObjectStoreDataServiceProxy::RegisterClientDeathObserver( int32_t error = remoteObject->SendRequest(static_cast(KvStoreCode::REGISTERCLIENTDEATHOBSERVER), data, reply, mo); if (error != 0) { - LOG_WARN("failed during IPC. errCode %d", error); + LOG_WARN("failed during IPC. errCode %{public}d", error); return ERR_IPC; } return static_cast(reply.ReadInt32()); 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 22cf1f78697d3de5459cdfcfc97f7bcb961a7b61..fb6ddd891721f399fe445fce502e369484fd55a4 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 @@ -13,8 +13,8 @@ * limitations under the License. */ -#include #include +#include #include "hitrace.h" #include "distributed_object_impl.h" @@ -199,15 +199,26 @@ uint32_t DistributedObjectStoreImpl::SetStatusNotifier(std::shared_ptrSetStatusNotifier(watcherProxy); } -void DistributedObjectStoreImpl::NotifyCachedStatus(const std::string &sessionId) +uint32_t DistributedObjectStoreImpl::SetProgressNotifier(std::shared_ptr notifier) { if (flatObjectStore_ == nullptr) { - LOG_ERROR("NotifyCachedStatus sync flatObjectStore err "); - return; + LOG_ERROR("flatObjectStore_ is nullptr"); + return ERR_NULL_OBJECTSTORE; } + std::shared_ptr watcherProxy = std::make_shared(notifier); + return flatObjectStore_->SetProgressNotifier(watcherProxy); +} + +void DistributedObjectStoreImpl::NotifyCachedStatus(const std::string &sessionId) +{ flatObjectStore_->CheckRetrieveCache(sessionId); } +void DistributedObjectStoreImpl::NotifyProgressStatus(const std::string &sessionId) +{ + flatObjectStore_->CheckProgressCache(sessionId); +} + WatcherProxy::WatcherProxy(const std::shared_ptr objectWatcher, const std::string &sessionId) : FlatObjectWatcher(sessionId), objectWatcher_(objectWatcher) { @@ -307,4 +318,20 @@ StatusNotifierProxy::~StatusNotifierProxy() LOG_ERROR("destroy"); notifier = nullptr; } + +void ProgressNotifierProxy::OnChanged(const std::string &sessionId, int32_t progress) +{ + if (notifier != nullptr) { + notifier->OnChanged(sessionId, progress); + } +} + +ProgressNotifierProxy::ProgressNotifierProxy(const std::shared_ptr ¬ifier) : notifier(notifier) +{ +} + +ProgressNotifierProxy::~ProgressNotifierProxy() +{ + notifier = nullptr; +} } // namespace OHOS::ObjectStore 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 911234881d276181a2df49e5fc1fdc48b2b93bc8..58c7fc3479df648cb9f48fdf16de2adc55345a12 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,7 @@ */ #include "flat_object_storage_engine.h" +#include "anonymous.h" #include "accesstoken_kit.h" #include "ipc_skeleton.h" #include "objectstore_errors.h" @@ -23,8 +24,6 @@ #include "object_radar_reporter.h" namespace OHOS::ObjectStore { -constexpr static const char *DISTRIBUTED_DATASYNC = "ohos.permission.DISTRIBUTED_DATASYNC"; - FlatObjectStorageEngine::~FlatObjectStorageEngine() { if (!isOpened_) { @@ -99,7 +98,7 @@ uint32_t FlatObjectStorageEngine::CreateTable(const std::string &key) { std::lock_guard lock(operationMutex_); if (delegates_.count(key) != 0) { - LOG_ERROR("FlatObjectStorageEngine::CreateTable %{public}s already created", key.c_str()); + LOG_ERROR("table: %{public}s already created", Anonymous::Change(key).c_str()); RadarReporter::ReportStateError(std::string(__FUNCTION__), CREATE, CREATE_TABLE, RADAR_FAILED, DUPLICATE_CREATE, FINISHED); return ERR_EXIST; @@ -116,7 +115,7 @@ uint32_t FlatObjectStorageEngine::CreateTable(const std::string &key) LOG_INFO("create table result %{public}d", status); }); if (status != DistributedDB::DBStatus::OK || kvStore == nullptr) { - LOG_ERROR("FlatObjectStorageEngine::CreateTable %{public}s getkvstore fail[%{public}d]", key.c_str(), status); + LOG_ERROR("GetKvStore fail[%{public}d], store:%{public}s", status, Anonymous::Change(key).c_str()); RadarReporter::ReportStateError(std::string(__FUNCTION__), CREATE, CREATE_TABLE, RADAR_FAILED, status, FINISHED); return ERR_DB_GETKV_FAIL; @@ -126,12 +125,12 @@ uint32_t FlatObjectStorageEngine::CreateTable(const std::string &key) LOG_INFO("start Pragma"); 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); + LOG_ERROR("Set Pragma fail[%{public}d], store:%{public}s", status, Anonymous::Change(key).c_str()); 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()); + LOG_INFO("create table %{public}s success", Anonymous::Change(key).c_str()); { std::lock_guard lock(operationMutex_); delegates_.insert_or_assign(key, kvStore); @@ -361,8 +360,8 @@ uint32_t FlatObjectStorageEngine::SetStatusNotifier(std::shared_ptr &devices) { for (auto item : devices) { LOG_INFO("%{public}s pull data result %{public}d in device %{public}s", - SoftBusAdapter::ToBeAnonymous(storeId).c_str(), item.second, - SoftBusAdapter::ToBeAnonymous(SoftBusAdapter::GetInstance()->ToNodeID(item.first)).c_str()); + Anonymous::Change(storeId).c_str(), item.second, + Anonymous::Change(SoftBusAdapter::GetInstance()->ToNodeID(item.first)).c_str()); } if (statusWatcher_ != nullptr) { for (auto item : devices) { @@ -383,13 +382,24 @@ uint32_t FlatObjectStorageEngine::SetStatusNotifier(std::shared_ptr watcher) +{ + if (!isOpened_) { + LOG_ERROR("FlatObjectStorageEngine::SetProgressNotifier has not init"); + return ERR_DB_NOT_INIT; + } + std::lock_guard lock(progressMutex_); + progressWatcher_ = watcher; + return SUCCESS; +} + uint32_t FlatObjectStorageEngine::SyncAllData(const std::string &sessionId, const std::vector &deviceIds, const std::function &)> &onComplete) { LOG_INFO("start"); std::lock_guard lock(operationMutex_); if (delegates_.count(sessionId) == 0) { - LOG_ERROR("FlatObjectStorageEngine::SyncAllData %{public}s already deleted", sessionId.c_str()); + LOG_ERROR("%{public}s already deleted", Anonymous::Change(sessionId).c_str()); return ERR_DB_NOT_EXIST; } DistributedDB::KvStoreNbDelegate *kvstore = delegates_.at(sessionId); @@ -397,28 +407,28 @@ uint32_t FlatObjectStorageEngine::SyncAllData(const std::string &sessionId, cons LOG_INFO("single device,no need sync"); return ERR_SINGLE_DEVICE; } - LOG_INFO("start sync %{public}s", sessionId.c_str()); + LOG_INFO("start sync %{public}s", Anonymous::Change(sessionId).c_str()); DistributedDB::DBStatus status = kvstore->Sync(deviceIds, DistributedDB::SyncMode::SYNC_MODE_PULL_ONLY, onComplete); if (status != DistributedDB::DBStatus::OK) { LOG_ERROR("FlatObjectStorageEngine::UnRegisterObserver unRegister err %{public}d", status); return ERR_UNRIGSTER; } - LOG_INFO("end sync %{public}s", sessionId.c_str()); + LOG_INFO("end sync %{public}s", Anonymous::Change(sessionId).c_str()); return SUCCESS; } uint32_t FlatObjectStorageEngine::GetItems(const std::string &key, std::map> &data) { if (!isOpened_) { - LOG_ERROR("FlatObjectStorageEngine::GetItems %{public}s not init", key.c_str()); + LOG_ERROR("GetItems %{public}s not init", Anonymous::Change(key).c_str()); return ERR_DB_NOT_INIT; } std::lock_guard lock(operationMutex_); if (delegates_.count(key) == 0) { - LOG_ERROR("FlatObjectStorageEngine::GetItems %{public}s not exist", key.c_str()); + LOG_ERROR("GetItems %{public}s not exist", Anonymous::Change(key).c_str()); return ERR_DB_NOT_EXIST; } - LOG_INFO("start Get %{public}s", key.c_str()); + LOG_INFO("start Get %{public}s", Anonymous::Change(key).c_str()); std::vector entries; DistributedDB::DBStatus status = delegates_.at(key)->GetEntries(StringUtils::StrToBytes(""), entries); if (status != DistributedDB::DBStatus::OK) { @@ -428,7 +438,7 @@ uint32_t FlatObjectStorageEngine::GetItems(const std::string &key, std::mapOnChanged(sessionId, deviceId, status); } -void FlatObjectStorageEngine::NotifyChange(const std::string &sessionId, - const std::map> &changedData) +bool FlatObjectStorageEngine::NotifyProgress(const std::string &sessionId, int32_t progress) +{ + std::lock_guard lock(progressMutex_); + if (progressWatcher_ == nullptr) { + return false; + } + progressWatcher_->OnChanged(sessionId, progress); + return true; +} + +void FlatObjectStorageEngine::NotifyChange( + const std::string &sessionId, const std::map> &changedData) { std::lock_guard lock(operationMutex_); if (observerMap_.count(sessionId) == 0) { 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 4d257080875a137c3d653eebf949588da900ea1a..26fadf8ab5b5fd98b30dfbaa74f4ab52ed1da344 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_store.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_store.cpp @@ -25,9 +25,6 @@ #include "string_utils.h" namespace OHOS::ObjectStore { -static constexpr uint32_t WAIT_TIME = 5; -static constexpr const char* DISTRIBUTED_DATASYNC = "ohos.permission.DISTRIBUTED_DATASYNC"; - FlatObjectStore::FlatObjectStore(const std::string &bundleName) { bundleName_ = bundleName; @@ -69,6 +66,7 @@ uint32_t FlatObjectStore::CreateObject(const std::string &sessionId) } SubscribeDataChange(sessionId); ResumeObject(sessionId); + SubscribeProgressChange(sessionId); return SUCCESS; } @@ -122,6 +120,18 @@ void FlatObjectStore::SubscribeDataChange(const std::string &sessionId) cacheManager_->SubscribeDataChange(bundleName_, sessionId, remoteResumeCallback); } +void FlatObjectStore::SubscribeProgressChange(const std::string &sessionId) +{ + std::function remoteResumeCallback = [sessionId, this](int32_t progress) { + LOG_INFO("asset progress = %{public}d", progress); + if (!storageEngine_->NotifyProgress(sessionId, progress)) { + std::lock_guard lck(progressInfoMutex_); + progressInfoCache_.insert_or_assign(sessionId, progress); + } + }; + cacheManager_->SubscribeProgressChange(bundleName_, sessionId, remoteResumeCallback); +} + uint32_t FlatObjectStore::Delete(const std::string &sessionId) { if (!storageEngine_->isOpened_ && storageEngine_->Open(bundleName_) != SUCCESS) { @@ -135,6 +145,7 @@ uint32_t FlatObjectStore::Delete(const std::string &sessionId) } cacheManager_->UnregisterDataChange(bundleName_, sessionId); cacheManager_->DeleteSnapshot(bundleName_, sessionId); + cacheManager_->UnregisterProgressChange(bundleName_, sessionId); return SUCCESS; } @@ -191,6 +202,14 @@ uint32_t FlatObjectStore::SetStatusNotifier(std::shared_ptr notif return storageEngine_->SetStatusNotifier(notifier); } +uint32_t FlatObjectStore::SetProgressNotifier(std::shared_ptr notifier) +{ + if (!storageEngine_->isOpened_ && storageEngine_->Open(bundleName_) != SUCCESS) { + LOG_ERROR("FlatObjectStore::DB has not inited"); + return ERR_DB_NOT_INIT; + } + return storageEngine_->SetProgressNotifier(notifier); +} uint32_t FlatObjectStore::Save(const std::string &sessionId, const std::string &deviceId) { RadarReporter::ReportStateStart(std::string(__FUNCTION__), SAVE, SAVE_TO_SERVICE, IDLE, START, bundleName_); @@ -245,8 +264,19 @@ void FlatObjectStore::CheckRetrieveCache(const std::string &sessionId) } } -void FlatObjectStore::FilterData(const std::string &sessionId, - std::map> &data) +void FlatObjectStore::CheckProgressCache(const std::string &sessionId) +{ + std::lock_guard lck(progressInfoMutex_); + auto it = progressInfoCache_.find(sessionId); + if (it != progressInfoCache_.end()) { + auto ret = storageEngine_->NotifyProgress(sessionId, it->second); + if (ret) { + progressInfoCache_.erase(sessionId); + } + } +} + +void FlatObjectStore::FilterData(const std::string &sessionId, std::map> &data) { std::map> allData {}; storageEngine_->GetItems(sessionId, allData); @@ -445,7 +475,7 @@ int32_t CacheManager::SaveObject(const std::string &bundleName, const std::strin 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)); + LOG_ERROR("object save failed code=%{public}d.", static_cast(status)); RadarReporter::ReportStateError(std::string(__FUNCTION__), SAVE, SAVE_TO_SERVICE, RADAR_FAILED, IPC_ERROR, FINISHED); } else { @@ -471,7 +501,7 @@ int32_t CacheManager::RevokeSaveObject( int32_t status = proxy->ObjectStoreRevokeSave( bundleName, sessionId, objectRevokeSaveCallback->AsObject().GetRefPtr()); if (status != SUCCESS) { - LOG_ERROR("object revoke save failed code=%d.", static_cast(status)); + LOG_ERROR("object revoke save failed code=%{public}d.", static_cast(status)); } LOG_INFO("object revoke save successful"); return status; @@ -493,7 +523,7 @@ int32_t CacheManager::ResumeObject(const std::string &bundleName, const std::str int32_t status = proxy->ObjectStoreRetrieve( bundleName, sessionId, objectRetrieveCallback->AsObject().GetRefPtr()); if (status != SUCCESS) { - LOG_ERROR("object resume failed code=%d.", static_cast(status)); + LOG_ERROR("object resume failed code=%{public}d.", static_cast(status)); } LOG_INFO("object resume successful"); return status; @@ -516,12 +546,32 @@ int32_t CacheManager::SubscribeDataChange(const std::string &bundleName, const s int32_t status = proxy->RegisterDataObserver( bundleName, sessionId, objectRemoteResumeCallback->AsObject().GetRefPtr()); if (status != SUCCESS) { - LOG_ERROR("object remote resume failed code=%d.", static_cast(status)); + LOG_ERROR("object remote resume failed code=%{public}d.", static_cast(status)); } LOG_INFO("object remote resume successful"); return status; } +int32_t CacheManager::SubscribeProgressChange( + const std::string &bundleName, const std::string &sessionId, std::function &callback) +{ + sptr proxy = ClientAdaptor::GetObjectService(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr."); + return ERR_NULL_PTR; + } + sptr objectRemoteResumeCallback = new (std::nothrow) ObjectProgressCallback(callback); + if (objectRemoteResumeCallback == nullptr) { + LOG_ERROR("CacheManager::SubscribeProgressChange no memory for ObjectProgressCallback malloc!"); + return ERR_NULL_PTR; + } + int32_t status = + proxy->RegisterProgressObserver(bundleName, sessionId, objectRemoteResumeCallback->AsObject().GetRefPtr()); + if (status != SUCCESS) { + LOG_ERROR("object remote resume failed code=%{public}d.", static_cast(status)); + } + return status; +} int32_t CacheManager::UnregisterDataChange(const std::string &bundleName, const std::string &sessionId) { sptr proxy = ClientAdaptor::GetObjectService(); @@ -531,12 +581,27 @@ int32_t CacheManager::UnregisterDataChange(const std::string &bundleName, const } int32_t status = proxy->UnregisterDataChangeObserver(bundleName, sessionId); if (status != SUCCESS) { - LOG_ERROR("object remote resume failed code=%d.", static_cast(status)); + LOG_ERROR("object remote resume failed code=%{public}d.", static_cast(status)); } LOG_INFO("object unregister data change observer successful"); return status; } +int32_t CacheManager::UnregisterProgressChange(const std::string &bundleName, const std::string &sessionId) +{ + sptr proxy = ClientAdaptor::GetObjectService(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr."); + return ERR_NULL_PTR; + } + int32_t status = proxy->UnregisterProgressObserver(bundleName, sessionId); + if (status != SUCCESS) { + LOG_ERROR("object remote resume failed code=%{public}d.", static_cast(status)); + } + LOG_INFO("object unregister progress change observer successful"); + return status; +} + int32_t CacheManager::DeleteSnapshot(const std::string &bundleName, const std::string &sessionId) { sptr proxy = ClientAdaptor::GetObjectService(); @@ -546,7 +611,7 @@ int32_t CacheManager::DeleteSnapshot(const std::string &bundleName, const std::s } int32_t status = proxy->DeleteSnapshot(bundleName, sessionId); if (status != SUCCESS) { - LOG_ERROR("object delete snapshot failed code=%d.", static_cast(status)); + LOG_ERROR("object delete snapshot failed code=%{public}d.", static_cast(status)); } LOG_INFO("object delete snapshot successful"); return status; diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/object_callback_impl.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/object_callback_impl.cpp index 9cf4d9a5f213d590cf05f09fb8683d1fe32b79de..3a168cb3946b8ac19c4284ee84b4847c4feb2535 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/object_callback_impl.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/object_callback_impl.cpp @@ -55,4 +55,11 @@ ObjectChangeCallback::ObjectChangeCallback( : callback_(callback) { } -} // namespace OHOS::DistributedKv +void ObjectProgressCallback::Completed(int32_t progress) +{ + callback_(progress); +} +ObjectProgressCallback::ObjectProgressCallback(const std::function &callback) : callback_(callback) +{ +} +} // namespace OHOS::ObjectStore diff --git a/data_object/frameworks/innerkitsimpl/src/communicator/dev_manager.cpp b/data_object/frameworks/innerkitsimpl/src/communicator/dev_manager.cpp index 94522125a8cdd850569a2d0d3236e7c73dcd1c35..3b33264c490eb8df375cf7786b2d72d3172a3d2f 100644 --- a/data_object/frameworks/innerkitsimpl/src/communicator/dev_manager.cpp +++ b/data_object/frameworks/innerkitsimpl/src/communicator/dev_manager.cpp @@ -16,6 +16,7 @@ #include +#include "anonymous.h" #include "device_manager.h" #include "softbus_adapter.h" @@ -42,7 +43,7 @@ private: void DMStateCallback::OnDeviceOnline(const DmDeviceInfo &deviceInfo) { std::string uuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(deviceInfo.networkId)); - LOG_INFO("[Online] id:%{public}s, name:%{public}s, typeId:%{public}d", SoftBusAdapter::ToBeAnonymous(uuid).c_str(), + LOG_INFO("[Online] id:%{public}s, name:%{public}s, typeId:%{public}d", Anonymous::Change(uuid).c_str(), deviceInfo.deviceName, deviceInfo.deviceTypeId); NotifyAll(deviceInfo, DeviceChangeType::DEVICE_ONLINE); } @@ -50,16 +51,15 @@ void DMStateCallback::OnDeviceOnline(const DmDeviceInfo &deviceInfo) void DMStateCallback::OnDeviceOffline(const DmDeviceInfo &deviceInfo) { std::string uuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(deviceInfo.networkId)); - LOG_INFO("[Offline] id:%{public}s, name:%{public}s, typeId:%{public}d", - SoftBusAdapter::ToBeAnonymous(uuid).c_str(), deviceInfo.deviceName, deviceInfo.deviceTypeId); + LOG_INFO("[Offline] id:%{public}s, name:%{public}s, typeId:%{public}d", Anonymous::Change(uuid).c_str(), + deviceInfo.deviceName, deviceInfo.deviceTypeId); NotifyAll(deviceInfo, DeviceChangeType::DEVICE_OFFLINE); } void DMStateCallback::OnDeviceChanged(const DmDeviceInfo &deviceInfo) { std::string uuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(deviceInfo.networkId)); - LOG_INFO("[InfoChange] id:%{public}s, name:%{public}s", SoftBusAdapter::ToBeAnonymous(uuid).c_str(), - deviceInfo.deviceName); + LOG_INFO("[InfoChange] id:%{public}s, name:%{public}s", Anonymous::Change(uuid).c_str(), deviceInfo.deviceName); } void DMStateCallback::OnDeviceReady(const DmDeviceInfo &deviceInfo) @@ -139,7 +139,7 @@ std::string DevManager::GetUuidByNodeId(const std::string &nodeId) const int32_t ret = DistributedHardware::DeviceManager::GetInstance().GetEncryptedUuidByNetworkId( "ohos.objectstore", nodeId.c_str(), uuid); if (ret != DM_OK) { - LOG_WARN("GetEncryptedUuidByNetworkId error, nodeId:%{public}s", SoftBusAdapter::ToBeAnonymous(nodeId).c_str()); + LOG_WARN("GetEncryptedUuidByNetworkId error, nodeId:%{public}s", Anonymous::Change(nodeId).c_str()); return ""; } return uuid; 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 04f9c381bf01e3ad52ee2418ac7ffd4e5bd8f046..d0f845fddd1ffede4cc058e8e405e94f9edc52e0 100644 --- a/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp +++ b/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp @@ -25,16 +25,11 @@ namespace OHOS { namespace ObjectStore { -constexpr int32_t HEAD_SIZE = 3; -constexpr int32_t END_SIZE = 3; -constexpr int32_t MIN_SIZE = HEAD_SIZE + END_SIZE + 3; -constexpr const char *REPLACE_CHAIN = "***"; -constexpr const char *DEFAULT_ANONYMOUS = "******"; constexpr int32_t SOFTBUS_OK = 0; constexpr int32_t INVALID_SOCKET_ID = 0; constexpr size_t TASK_CAPACITY_MAX = 15; constexpr const char *PKG_NAME = "ohos.objectstore"; -SoftBusAdapter *AppDataListenerWrap::softBusAdapter_; +SoftBusAdapter *AppDataListenerWrap::softBusAdapter_ = nullptr; std::shared_ptr SoftBusAdapter::instance_; SoftBusAdapter::SoftBusAdapter() @@ -59,6 +54,16 @@ SoftBusAdapter::~SoftBusAdapter() taskQueue_->Clean(); taskQueue_ = nullptr; } + std::lock_guard lock(deviceDataLock_); + for (auto &deviceData : dataCaches_) { + for (auto &bytesMsg : deviceData.second) { + if (bytesMsg.ptr != nullptr) { + delete[] bytesMsg.ptr; + bytesMsg.ptr = nullptr; + } + } + } + dataCaches_.clear(); sockets_.clear(); } @@ -111,7 +116,7 @@ void SoftBusAdapter::NotifyAll(const DeviceInfo &deviceInfo, const DeviceChangeT } LOG_DEBUG("high"); std::string uuid = DevManager::GetInstance()->GetUuidByNodeId(deviceInfo.deviceId); - LOG_DEBUG("[Notify] to DB from: %{public}s, type:%{public}hhd", ToBeAnonymous(uuid).c_str(), type); + LOG_DEBUG("[Notify] to DB from: %{public}s, type:%{public}hhd", Anonymous::Change(uuid).c_str(), type); UpdateRelationship(deviceInfo.deviceId, type); for (const auto &device : listeners) { if (device == nullptr) { @@ -193,7 +198,7 @@ DeviceInfo SoftBusAdapter::GetLocalDevice() return DeviceInfo(); } std::string uuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(info.networkId)); - LOG_DEBUG("[LocalDevice] id:%{private}s, name:%{private}s, type:%{private}d", ToBeAnonymous(uuid).c_str(), + LOG_DEBUG("[LocalDevice] id:%{public}s, name:%{public}s, type:%{public}d", Anonymous::Change(uuid).c_str(), info.deviceName, info.deviceTypeId); localInfo_ = { uuid, std::string(info.deviceName), std::to_string(info.deviceTypeId) }; return localInfo_; @@ -208,9 +213,8 @@ DeviceInfo SoftBusAdapter::GetLocalBasicInfo() const LOG_ERROR("GetLocalNodeDeviceInfo error"); return DeviceInfo(); } - LOG_DEBUG("[LocalBasicInfo] networkId:%{private}s, name:%{private}s, " - "type:%{private}d", - ToBeAnonymous(std::string(info.networkId)).c_str(), info.deviceName, info.deviceTypeId); + LOG_DEBUG("[LocalBasicInfo] networkId:%{public}s, name:%{public}s, type:%{public}d", + Anonymous::Change(std::string(info.networkId)).c_str(), info.deviceName, info.deviceTypeId); DeviceInfo localInfo = { std::string(info.networkId), std::string(info.deviceName), std::to_string(info.deviceTypeId) }; return localInfo; @@ -301,19 +305,6 @@ std::string SoftBusAdapter::ToNodeID(const std::string &nodeId) const return networkId; } -std::string SoftBusAdapter::ToBeAnonymous(const std::string &name) -{ - if (name.length() <= HEAD_SIZE) { - return DEFAULT_ANONYMOUS; - } - - if (name.length() < MIN_SIZE) { - return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN); - } - - return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE)); -} - std::shared_ptr SoftBusAdapter::GetInstance() { static std::once_flag onceFlag; @@ -561,7 +552,7 @@ void SoftBusAdapter::NotifyDataListeners( auto it = dataChangeListeners_.find(pipeInfo.pipeId); if (it != dataChangeListeners_.end()) { LOG_DEBUG("ready to notify, pipeName:%{public}s, deviceId:%{public}s.", pipeInfo.pipeId.c_str(), - ToBeAnonymous(deviceId).c_str()); + Anonymous::Change(deviceId).c_str()); DeviceInfo deviceInfo = { deviceId, "", "" }; it->second->OnMessage(deviceInfo, ptr, size, pipeInfo); return; @@ -606,7 +597,7 @@ void AppDataListenerWrap::OnServerBind(int32_t socket, PeerSocketInfo info) { softBusAdapter_->OnBind(socket, info); LOG_INFO("Server on bind, socket: %{public}d, peer networkId: %{public}s", socket, - SoftBusAdapter::ToBeAnonymous(info.networkId).c_str()); + Anonymous::Change(info.networkId).c_str()); } void AppDataListenerWrap::OnServerShutdown(int32_t socket, ShutdownReason reason) diff --git a/data_object/frameworks/innerkitsimpl/src/object_callback_stub.cpp b/data_object/frameworks/innerkitsimpl/src/object_callback_stub.cpp index 754be02c3c63836bd28398e222846a5b155e1c8d..e81f0a187e95aae2cd660fec4ae6887522641fbf 100644 --- a/data_object/frameworks/innerkitsimpl/src/object_callback_stub.cpp +++ b/data_object/frameworks/innerkitsimpl/src/object_callback_stub.cpp @@ -110,5 +110,27 @@ int ObjectChangeCallbackStub::OnRemoteRequest( } return IPCObjectStub::OnRemoteRequest(code, data, reply, option); } + +int ObjectProgressCallbackStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + ZLOGI("code:%{public}u, callingPid:%{public}d", code, IPCSkeleton::GetCallingPid()); + auto localDescriptor = GetDescriptor(); + auto remoteDescriptor = data.ReadInterfaceToken(); + if (remoteDescriptor != localDescriptor) { + ZLOGE("interface token is not equal"); + return -1; + } + if (code == COMPLETED) { + int32_t progress; + if (!ITypesUtil::Unmarshal(data, progress)) { + ZLOGE("Unmarshal failed"); + return -1; + } + Completed(progress); + return 0; + } + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} } // namespace DistributedObject } // namespace OHOS diff --git a/data_object/frameworks/innerkitsimpl/src/object_radar_reporter.cpp b/data_object/frameworks/innerkitsimpl/src/object_radar_reporter.cpp index e363a8fb15f4c5b57dc43018cbd0b8dad4414a69..319a6b46997236c76aab95432de94b8e57fc4624 100644 --- a/data_object/frameworks/innerkitsimpl/src/object_radar_reporter.cpp +++ b/data_object/frameworks/innerkitsimpl/src/object_radar_reporter.cpp @@ -17,10 +17,6 @@ namespace OHOS::ObjectStore { using namespace ObjectStore; -constexpr char DOMAIN[] = "DISTDATAMGR"; -constexpr char EVENT_NAME[] = "DISTRIBUTED_DATA_OBJECT_BEHAVIOR"; -constexpr char ORG_PKG[] = "distributeddata"; - void RadarReporter::ReportStateFinished(std::string func, int32_t scene, int32_t stage, int32_t stageRes, int32_t state) { struct HiSysEventParam params[] = { diff --git a/data_object/frameworks/innerkitsimpl/src/object_service_proxy.cpp b/data_object/frameworks/innerkitsimpl/src/object_service_proxy.cpp index 934b033377a55c3f99be49deaaa4ea90d71f8d55..d3b6fb6e25de851392ce80e84ae379058c706834 100644 --- a/data_object/frameworks/innerkitsimpl/src/object_service_proxy.cpp +++ b/data_object/frameworks/innerkitsimpl/src/object_service_proxy.cpp @@ -53,7 +53,7 @@ int32_t ObjectServiceProxy::ObjectStoreSave(const std::string &bundleName, const } int32_t error = remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_SAVE), data, reply, mo); if (error != 0) { - ZLOGE("SendRequest returned %d", error); + ZLOGE("SendRequest returned %{public}d", error); return ERR_IPC; } return reply.ReadInt32(); @@ -85,7 +85,7 @@ int32_t ObjectServiceProxy::OnAssetChanged(const std::string &bundleName, const int32_t error = remoteObject->SendRequest( static_cast(ObjectCode::OBJECTSTORE_ON_ASSET_CHANGED), data, reply, mo); if (error != 0) { - ZLOGE("SendRequest returned %d", error); + ZLOGE("SendRequest returned %{public}d", error); return ERR_IPC; } return reply.ReadInt32(); @@ -115,7 +115,7 @@ int32_t ObjectServiceProxy::ObjectStoreRevokeSave( int32_t error = remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_REVOKE_SAVE), data, reply, mo); if (error != 0) { - ZLOGE("SendRequest returned %d", error); + ZLOGE("SendRequest returned %{public}d", error); return ERR_IPC; } return reply.ReadInt32(); @@ -145,7 +145,7 @@ int32_t ObjectServiceProxy::ObjectStoreRetrieve( int32_t error = remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_RETRIEVE), data, reply, mo); if (error != 0) { - ZLOGE("SendRequest returned %d", error); + ZLOGE("SendRequest returned %{public}d", error); return ERR_IPC; } return reply.ReadInt32(); @@ -175,7 +175,7 @@ int32_t ObjectServiceProxy::RegisterDataObserver(const std::string &bundleName, int32_t error = remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_REGISTER_OBSERVER), data, reply, mo); if (error != 0) { - ZLOGE("SendRequest returned %d", error); + ZLOGE("SendRequest returned %{public}d", error); return ERR_IPC; } return reply.ReadInt32(); @@ -204,12 +204,71 @@ int32_t ObjectServiceProxy::UnregisterDataChangeObserver(const std::string &bund int32_t error = remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_UNREGISTER_OBSERVER), data, reply, mo); if (error != 0) { - ZLOGE("SendRequest returned %d", error); + ZLOGE("SendRequest returned %{public}d", error); return ERR_IPC; } return reply.ReadInt32(); } +int32_t ObjectServiceProxy::RegisterProgressObserver(const std::string &bundleName, + const std::string &sessionId, sptr callback) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(ObjectServiceProxy::GetDescriptor())) { + ZLOGE("write descriptor failed"); + return ERR_IPC; + } + + if (!ITypesUtil::Marshal(data, bundleName, sessionId, callback)) { + ZLOGE("Marshalling failed, bundleName = %{public}s", bundleName.c_str()); + return ERR_IPC; + } + + MessageParcel reply; + MessageOption mo { MessageOption::TF_SYNC }; + sptr remoteObject = Remote(); + if (remoteObject == nullptr) { + LOG_ERROR("RegisterProgressObserver remoteObject is nullptr."); + return ERR_IPC; + } + int32_t error = + remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_REGISTER_PROGRESS), data, reply, mo); + if (error != 0) { + ZLOGE("SendRequest returned %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int32_t ObjectServiceProxy::UnregisterProgressObserver(const std::string &bundleName, const std::string &sessionId) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(ObjectServiceProxy::GetDescriptor())) { + ZLOGE("write descriptor failed"); + return ERR_IPC; + } + + if (!ITypesUtil::Marshal(data, bundleName, sessionId)) { + ZLOGE("Marshalling failed, bundleName = %{public}s", bundleName.c_str()); + return ERR_IPC; + } + + MessageParcel reply; + MessageOption mo { MessageOption::TF_SYNC }; + sptr remoteObject = Remote(); + if (remoteObject == nullptr) { + LOG_ERROR("UnregisterProgressObserver remoteObject is nullptr."); + return ERR_IPC; + } + int32_t error = + remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_UNREGISTER_PROGRESS), data, reply, mo); + if (error != 0) { + ZLOGE("SendRequest returned %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + int32_t ObjectServiceProxy::BindAssetStore(const std::string &bundleName, const std::string &sessionId, Asset &asset, AssetBindInfo &bindInfo) { @@ -234,7 +293,7 @@ int32_t ObjectServiceProxy::BindAssetStore(const std::string &bundleName, const int32_t error = remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_BIND_ASSET_STORE), data, reply, mo); if (error != 0) { - ZLOGE("SendRequest returned %d", error); + ZLOGE("SendRequest returned %{public}d", error); return ERR_IPC; } return reply.ReadInt32(); @@ -263,7 +322,7 @@ int32_t ObjectServiceProxy::DeleteSnapshot(const std::string &bundleName, const int32_t error = remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_DELETE_SNAPSHOT), data, reply, mo); if (error != 0) { - ZLOGE("SendRequest returned %d", error); + ZLOGE("SendRequest returned %{public}d", error); return ERR_IPC; } return reply.ReadInt32(); 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 42477193be9047c17123d2975bc6a951aa3257af..51c578a000b0c2a4ccb8161d305eb4be3d1bf2cc 100644 --- a/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/BUILD.gn +++ b/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/BUILD.gn @@ -36,10 +36,15 @@ ohos_fuzztest("ObjectStoreFuzzTest") { configs = [ ":module_private_config" ] deps = [ "//foundation/distributeddatamgr/data_object/interfaces/innerkits:distributeddataobject_static", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", ] - external_deps = [ "hilog:libhilog" ] + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "access_token:libtokensetproc_shared", + "hilog:libhilog", + "kv_store:distributeddb", + ] } ############################################################################### diff --git a/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/objectstore_fuzzer.cpp b/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/objectstore_fuzzer.cpp index d75d55a29b44c60bb24405dfec28d2a43cd65563..530cf4794c40ea935691e586a351363e38294fcd 100644 --- a/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/objectstore_fuzzer.cpp +++ b/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/objectstore_fuzzer.cpp @@ -15,12 +15,18 @@ #include "objectstore_fuzzer.h" +#include +#include #include #include + +#include "accesstoken_kit.h" #include "distributed_object.h" #include "distributed_objectstore.h" #include "flat_object_storage_engine.h" +#include "nativetoken_kit.h" #include "objectstore_errors.h" +#include "token_setproc.h" using namespace OHOS::ObjectStore; namespace OHOS { @@ -28,20 +34,61 @@ static DistributedObject *object_ = nullptr; static DistributedObjectStore *objectStore_ = nullptr; constexpr const char *SESSIONID = "123456"; constexpr const char *TABLESESSIONID = "654321"; +constexpr const char *BUNDLENAME = "com.example.myapplication"; +bool g_hasPermission = false; class TableWatcherImpl : public TableWatcher { public: - explicit TableWatcherImpl(const std::string &sessionId) : TableWatcher(sessionId) {} - void OnChanged( - const std::string &sessionid, const std::vector &changedData, bool enableTransfer) override; + explicit TableWatcherImpl(const std::string &sessionId) : TableWatcher(sessionId) + { + } + void OnChanged(const std::string &sessionid, const std::vector &changedData, + bool enableTransfer) override; virtual ~TableWatcherImpl(); }; -TableWatcherImpl::~TableWatcherImpl() {} -void TableWatcherImpl::OnChanged( - const std::string &sessionid, const std::vector &changedData, bool enableTransfer) {} +TableWatcherImpl::~TableWatcherImpl() +{ +} +void TableWatcherImpl::OnChanged(const std::string &sessionid, const std::vector &changedData, + bool enableTransfer) +{ +} + +class TestObjectWatcher : public ObjectWatcher { +public: + void OnChanged(const std::string &sessionid, const std::vector &changedData) override + { + } + virtual ~TestObjectWatcher() + { + } +}; + +class TestStatusNotifier : public StatusNotifier { +public: + void OnChanged(const std::string &sessionId, const std::string &networkId, const std::string &onlineStatus) override + { + } + virtual ~TestStatusNotifier() + { + } +}; + +std::string FilterSessionId(const std::string &input) +{ + std::string result; + std::copy_if(input.begin(), input.end(), std::back_inserter(result), [](char c) { + // Reservations: Numbers (0-9), letters (a-z, A-Z), underscores (_) + return std::isalnum(static_cast(c)) || c == '_'; + }); + if (result.empty()) { + result = "default_session_id"; + } + return result; +} uint32_t SetUpTestCase() { - std::string bundleName = "com.example.myapplication"; + std::string bundleName = BUNDLENAME; DistributedObjectStore *objectStore = nullptr; DistributedObject *object = nullptr; objectStore = DistributedObjectStore::GetInstance(bundleName); @@ -59,330 +106,380 @@ uint32_t SetUpTestCase() } } -bool PutDoubleFuzz(const uint8_t *data, size_t size) +void FuzzTestGetPermission() +{ + if (!g_hasPermission) { + uint64_t tokenId; + constexpr int perNum = 1; + const char *perms[perNum] = { "ohos.permission.DISTRIBUTED_DATASYNC" }; + + NativeTokenInfoParams infoInstance = { + .dcapsNum = 0, + .permsNum = 1, + .aclsNum = 0, + .dcaps = nullptr, + .perms = perms, + .acls = nullptr, + .processName = "objectfuzztest", + .aplStr = "normal", + }; + tokenId = GetAccessTokenId(&infoInstance); + SetSelfTokenID(tokenId); + OHOS::Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo(); + g_hasPermission = true; + } +} + +bool PutDoubleFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - double sval = static_cast(size); - std::string skey(data, data + size); - uint32_t ret = object_->PutDouble(skey, sval); - if (!ret) { - result = true; - } + double sval = provider.ConsumeFloatingPoint(); + std::string skey = provider.ConsumeRandomLengthString(10); + object_->PutDouble(skey, sval); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool PutBooleanFuzz(const uint8_t *data, size_t size) +bool PutBooleanFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - std::string skey(data, data + size); - uint32_t ret = object_->PutBoolean(skey, true); - if (!ret) { - result = true; - } - ret = object_->PutBoolean(skey, false); - if (ret != SUCCESS) { - result = false; - } + std::string skey = provider.ConsumeRandomLengthString(10); + bool val = provider.ConsumeBool(); + object_->PutBoolean(skey, val); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool PutStringFuzz(const uint8_t *data, size_t size) +bool PutStringFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - std::string skey(data, data + size); - std::string sval(data, data + size); - uint32_t ret = object_->PutString(skey, sval); - if (!ret) { - result = true; - } + std::string skey = provider.ConsumeRandomLengthString(10); + std::string sval = provider.ConsumeRandomLengthString(10); + object_->PutString(skey, sval); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool PutComplexFuzz(const uint8_t *data, size_t size) +bool PutComplexFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - size_t sum = 10; - std::string skey(data, data + size); + size_t sum = provider.ConsumeIntegralInRange(0, 100); + std::string skey = provider.ConsumeRandomLengthString(10); std::vector value; for (size_t i = 0; i < sum; i++) { - value.push_back(*data + i); - } - uint32_t ret = object_->PutComplex(skey, value); - if (!ret) { - result = true; + uint8_t val = 0; + value.push_back(val); } + object_->PutComplex(skey, value); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool GetDoubleFuzz(const uint8_t *data, size_t size) +bool GetDoubleFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - double sval = static_cast(size); - double val; - std::string skey(data, data + size); - if (SUCCESS == object_->PutDouble(skey, sval)) { - uint32_t ret = object_->GetDouble(skey, val); - if (!ret) { - result = true; - } - } + double sval = provider.ConsumeFloatingPoint(); + std::string skey = provider.ConsumeRandomLengthString(10); + object_->PutDouble(skey, sval); + double val = 0; + object_->GetDouble(skey, val); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool GetBooleanFuzz(const uint8_t *data, size_t size) +bool GetBooleanFuzz(FuzzedDataProvider &provider) { - bool val, result = false; if (SUCCESS != SetUpTestCase()) { return false; } - std::string skey(data, data + size); - if (SUCCESS == object_->PutBoolean(skey, true)) { - uint32_t ret = object_->GetBoolean(skey, val); - if (!ret) { - result = true; - } - } + std::string skey = provider.ConsumeRandomLengthString(10); + bool value = provider.ConsumeBool(); + object_->PutBoolean(skey, value); + bool val = false; + object_->GetBoolean(skey, val); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool GetStringFuzz(const uint8_t *data, size_t size) +bool GetStringFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - std::string skey(data, data + size); - std::string sval(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(10); + std::string sval = provider.ConsumeRandomLengthString(10); std::string val; - if (SUCCESS == object_->PutString(skey, sval)) { - uint32_t ret = object_->GetString(skey, val); - if (!ret) { - result = true; - } - } + object_->PutString(skey, sval); + object_->GetString(skey, val); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool GetComplexFuzz(const uint8_t *data, size_t size) +bool GetComplexFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - size_t sum = 10; - std::string skey(data, data + size); + + size_t sum = provider.ConsumeIntegralInRange(0, 10); + std::string skey = provider.ConsumeRandomLengthString(10); std::vector svalue; std::vector val; for (size_t i = 0; i < sum; i++) { - svalue.push_back(*data + i); - } - if (SUCCESS == object_->PutComplex(skey, svalue)) { - uint32_t ret = object_->GetComplex(skey, val); - if (!ret) { - result = true; - } + uint8_t val = 0; + svalue.push_back(val); } + object_->PutComplex(skey, svalue); + object_->GetComplex(skey, val); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool GetTypeFuzz(const uint8_t *data, size_t size) +bool GetTypeFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - std::string skey(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(10); Type val; - uint32_t ret = object_->GetType(skey, val); - if (!ret) { - result = true; - } + object_->GetType(skey, val); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool SaveFuzz(const uint8_t *data, size_t size) +bool SaveFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - std::string skey(data, data + size); - uint32_t ret = object_->Save(skey); - if (!ret) { - result = true; - } + std::string skey = provider.ConsumeRandomLengthString(10); + object_->Save(skey); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool SaveAndRevokeSaveFuzz(const uint8_t *data, size_t size) +bool SaveAndRevokeSaveFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - std::string skey(data, data + size); - if (SUCCESS == object_->PutDouble(skey, static_cast(size))) { - uint32_t ret = object_->Save(skey); - if (!ret) { - result = false; - } - - if (object_->RevokeSave()) { - return false; - } - result = true; - } + std::string skey = provider.ConsumeRandomLengthString(10); + double sval = provider.ConsumeFloatingPoint(); + object_->PutDouble(skey, sval); + object_->Save(skey); + object_->RevokeSave(); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool CreateObjectV9Fuzz(const uint8_t *data, size_t size) +bool CreateObjectV9Fuzz(FuzzedDataProvider &provider) { - bool result = false; - std::string bundleName = "com.example.myapplication"; - DistributedObject *object = nullptr; + std::string bundleName = provider.ConsumeRandomLengthString(10); objectStore_ = DistributedObjectStore::GetInstance(bundleName); - uint32_t status = 0; - std::string skey(data, data + size); if (objectStore_ == nullptr) { return false; } - object = objectStore_->CreateObject(skey, status); - if (object == nullptr || status != SUCCESS) { - return false; - } - double val = static_cast(size); - if (SUCCESS == object->PutDouble(skey, val)) { - double getResult; - if (object->GetDouble(skey, getResult)) { - result = true; - } + uint32_t status = provider.ConsumeIntegral(); + std::string skey = FilterSessionId(provider.ConsumeRandomLengthString(10)); + auto object = objectStore_->CreateObject(skey, status); + if (object != nullptr) { + double val = provider.ConsumeFloatingPoint(); + object->PutDouble(skey, val); + double getResult = 0; + object->GetDouble(skey, getResult); } objectStore_->DeleteObject(skey); - return result; + return true; } -bool GetFuzz(const uint8_t *data, size_t size) +bool GetFuzz(FuzzedDataProvider &provider) { - std::string bundleName = "default1"; + std::string bundleName = provider.ConsumeRandomLengthString(10); objectStore_ = DistributedObjectStore::GetInstance(bundleName); if (objectStore_ == nullptr) { return false; } - uint32_t status = 0; - DistributedObject *object = objectStore_->CreateObject(SESSIONID, status); - if (object == nullptr) { - return false; - } - - DistributedObject *object2 = nullptr; - std::string skey(data, data + size); - if (!objectStore_->Get(skey, &object2)) { - return false; - } - - if (object != object2) { - return false; - } - objectStore_->DeleteObject(SESSIONID); + uint32_t status = provider.ConsumeIntegral(); + std::string skey = FilterSessionId(provider.ConsumeRandomLengthString(10)); + objectStore_->CreateObject(skey, status); + DistributedObject *object = nullptr; + objectStore_->Get(skey, &object); + objectStore_->DeleteObject(skey); return true; } -bool GetTableFuzz(const uint8_t *data, size_t size) +bool GetTableFuzz(FuzzedDataProvider &provider) { - bool result = false; - std::string skey(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(10); std::shared_ptr storageEngine = std::make_shared(); - storageEngine->Open("com.myapplication"); + storageEngine->Open(BUNDLENAME); storageEngine->CreateTable(TABLESESSIONID); std::map tableResult; - uint32_t ret = storageEngine->GetTable(skey, tableResult); - if (ret != SUCCESS) { - result = false; - } + storageEngine->GetTable(skey, tableResult); storageEngine->DeleteTable(TABLESESSIONID); - return result; + return true; } -bool NotifyStatusAndNotifyChangeFuzz(const uint8_t *data, size_t size) +bool NotifyStatusAndNotifyChangeFuzz(FuzzedDataProvider &provider) { std::shared_ptr storageEngine = std::make_shared(); - storageEngine->Open("com.example.myapplication"); - uint32_t ret = storageEngine->CreateTable(TABLESESSIONID); - if (ret != SUCCESS) { - return false; - } + storageEngine->Open(BUNDLENAME); + storageEngine->CreateTable(TABLESESSIONID); std::map> filteredData; - std::string skey(data, data + size); + std::string skey = FilterSessionId(provider.ConsumeRandomLengthString(10)); storageEngine->NotifyChange(skey, filteredData); storageEngine->NotifyStatus(skey, skey, skey); storageEngine->DeleteTable(TABLESESSIONID); return true; } -bool RegisterObserverAndUnRegisterObserverFuzz(const uint8_t *data, size_t size) +bool RegisterObserverAndUnRegisterObserverFuzz(FuzzedDataProvider &provider) { - bool result = true; std::shared_ptr storageEngine = std::make_shared(); - storageEngine->Open("com.example.myapplication"); - std::string skey(data, data + size); + storageEngine->Open(BUNDLENAME); + std::string skey = provider.ConsumeRandomLengthString(10); auto tableWatcherPtr = std::make_shared(SESSIONID); - uint32_t ret = storageEngine->RegisterObserver(skey, tableWatcherPtr); - if (ret != SUCCESS) { - result = false; + storageEngine->RegisterObserver(skey, tableWatcherPtr); + storageEngine->UnRegisterObserver(skey); + return true; +} + +bool BindAssetStoreFuzz(FuzzedDataProvider &provider) +{ + std::string bundleName = provider.ConsumeRandomLengthString(10); + objectStore_ = DistributedObjectStore::GetInstance(bundleName); + if (objectStore_ == nullptr) { + return false; } - ret = storageEngine->UnRegisterObserver(skey); - if (ret != SUCCESS) { - result = false; + uint32_t status = provider.ConsumeIntegral(); + std::string skey = FilterSessionId(provider.ConsumeRandomLengthString(10)); + auto object = objectStore_->CreateObject(skey, status); + if (object == nullptr) { + return false; } - return result; + AssetBindInfo bindInfo = { .storeName = provider.ConsumeRandomLengthString(10), + .tableName = provider.ConsumeRandomLengthString(10), + .primaryKey = { { "data1", 123 }, { "data2", "test1" } }, + .field = provider.ConsumeRandomLengthString(10), + .assetName = provider.ConsumeRandomLengthString(10) }; + object->BindAssetStore(skey, bindInfo); + objectStore_->DeleteObject(skey); + return true; +} + +bool GetSessionIdFuzz(FuzzedDataProvider &provider) +{ + std::string bundleName = provider.ConsumeRandomLengthString(10); + objectStore_ = DistributedObjectStore::GetInstance(bundleName); + if (objectStore_ == nullptr) { + return false; + } + uint32_t status = provider.ConsumeIntegral(); + std::string skey = FilterSessionId(provider.ConsumeRandomLengthString(10)); + auto object = objectStore_->CreateObject(skey, status); + if (object != nullptr) { + object->GetSessionId(); + } + objectStore_->DeleteObject(skey); + return true; +} + +bool WatchAndUnWatchFuzz(FuzzedDataProvider &provider) +{ + std::string bundleName = provider.ConsumeRandomLengthString(10); + objectStore_ = DistributedObjectStore::GetInstance(bundleName); + if (objectStore_ == nullptr) { + return false; + } + std::string skey = FilterSessionId(provider.ConsumeRandomLengthString(10)); + auto object = objectStore_->CreateObject(skey); + if (object == nullptr) { + return false; + } + objectStore_->Watch(object, std::make_shared()); + double sval = provider.ConsumeFloatingPoint(); + object->PutDouble(skey, sval); + objectStore_->UnWatch(object); + objectStore_->DeleteObject(skey); + return true; +} + +bool StatusNotifierFuzz(FuzzedDataProvider &provider) +{ + std::string bundleName = provider.ConsumeRandomLengthString(10); + objectStore_ = DistributedObjectStore::GetInstance(bundleName); + if (objectStore_ == nullptr) { + return false; + } + std::string skey = FilterSessionId(provider.ConsumeRandomLengthString(10)); + auto object = objectStore_->CreateObject(skey); + if (object == nullptr) { + return false; + } + objectStore_->SetStatusNotifier(std::make_shared()); + objectStore_->NotifyCachedStatus(skey); + objectStore_->DeleteObject(skey); + return true; } + +bool RandomSessionIdFuzz(FuzzedDataProvider &provider) +{ + std::string bundleName = provider.ConsumeRandomLengthString(10); + objectStore_ = DistributedObjectStore::GetInstance(bundleName); + if (objectStore_ == nullptr) { + return false; + } + std::string skey = provider.ConsumeRandomLengthString(); + auto object = objectStore_->CreateObject(skey); + if (object == nullptr) { + return false; + } + objectStore_->DeleteObject(skey); + return true; +} +} // namespace OHOS + +extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) +{ + OHOS::FuzzTestGetPermission(); + return 0; } /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - OHOS::PutDoubleFuzz(data, size); - OHOS::PutBooleanFuzz(data, size); - OHOS::PutStringFuzz(data, size); - OHOS::PutComplexFuzz(data, size); - OHOS::GetDoubleFuzz(data, size); - OHOS::GetBooleanFuzz(data, size); - OHOS::GetStringFuzz(data, size); - OHOS::GetComplexFuzz(data, size); - OHOS::GetTypeFuzz(data, size); - OHOS::SaveFuzz(data, size); - OHOS::SaveAndRevokeSaveFuzz(data, size); - OHOS::CreateObjectV9Fuzz(data, size); - OHOS::GetFuzz(data, size); - OHOS::GetTableFuzz(data, size); - OHOS::NotifyStatusAndNotifyChangeFuzz(data, size); - OHOS::RegisterObserverAndUnRegisterObserverFuzz(data, size); + FuzzedDataProvider provider(data, size); + OHOS::PutDoubleFuzz(provider); + OHOS::PutBooleanFuzz(provider); + OHOS::PutStringFuzz(provider); + OHOS::PutComplexFuzz(provider); + OHOS::GetDoubleFuzz(provider); + OHOS::GetBooleanFuzz(provider); + OHOS::GetStringFuzz(provider); + OHOS::GetComplexFuzz(provider); + OHOS::GetTypeFuzz(provider); + OHOS::SaveFuzz(provider); + OHOS::SaveAndRevokeSaveFuzz(provider); + OHOS::CreateObjectV9Fuzz(provider); + OHOS::GetFuzz(provider); + OHOS::GetTableFuzz(provider); + OHOS::NotifyStatusAndNotifyChangeFuzz(provider); + OHOS::RegisterObserverAndUnRegisterObserverFuzz(provider); + OHOS::BindAssetStoreFuzz(provider); + OHOS::GetSessionIdFuzz(provider); + OHOS::WatchAndUnWatchFuzz(provider); + OHOS::StatusNotifierFuzz(provider); + OHOS::RandomSessionIdFuzz(provider); /* Run your code on data */ return 0; } \ No newline at end of file diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/BUILD.gn b/data_object/frameworks/innerkitsimpl/test/unittest/BUILD.gn index 4f3f4b898bbc21426e1a439d2a4a839aef9829e7..eeb8c3633f1992d80025c902cbe6006457701809 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/BUILD.gn +++ b/data_object/frameworks/innerkitsimpl/test/unittest/BUILD.gn @@ -38,14 +38,17 @@ config("module_private_config") { common_external_deps = [ "ability_base:want", "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "access_token:libtoken_setproc", "bundle_framework:appexecfwk_core", "c_utils:utils", + "cJSON:cjson", "device_manager:devicemanagersdk", "dmsfwk:distributed_sdk", "dsoftbus:softbus_client", "ffmpeg:libohosffmpeg", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", @@ -83,10 +86,12 @@ ohos_unittest("NativeObjectStoreTest") { external_deps = common_external_deps + defines = [ + "private=public", + ] + deps = [ "//foundation/distributeddatamgr/data_object/interfaces/innerkits:distributeddataobject_static", - "//third_party/googletest:gmock", - "//third_party/googletest:gtest_main", ] } @@ -99,8 +104,8 @@ ohos_unittest("ObjectTypesUtilTest") { ] configs = [ ":module_private_config" ] - external_deps = common_external_deps deps = [ "${data_object_base_path}/interfaces/innerkits:distributeddataobject_static" ] + external_deps = common_external_deps } ohos_unittest("ObjectServiceProxyTest") { @@ -113,8 +118,8 @@ ohos_unittest("ObjectServiceProxyTest") { ] configs = [ ":module_private_config" ] - external_deps = common_external_deps deps = [ "${data_object_base_path}/interfaces/innerkits:distributeddataobject_static" ] + external_deps = common_external_deps } ohos_unittest("ObjectCallbackStubTest") { @@ -155,6 +160,7 @@ ohos_unittest("AssetChangeTimerTest") { "${data_object_base_path}/frameworks/jskitsimpl/src/adaptor/notifier_impl.cpp", "${data_object_base_path}/frameworks/jskitsimpl/src/common/js_util.cpp", "${data_object_base_path}/frameworks/jskitsimpl/src/common/uv_queue.cpp", + "${data_object_base_path}/frameworks/jskitsimpl/src/adaptor/progress_notifier_impl.cpp", ] cflags_cc = [ "-DHILOG_ENABLE" ] @@ -190,14 +196,32 @@ ohos_unittest("ClientAdaptorTest") { "private = public", "protected = public", ] - deps = [ "${data_object_base_path}/interfaces/innerkits:distributeddataobject_static" ] } ohos_unittest("DistributedObjectStoreImplTest") { module_out_path = module_output_path sources = [ + "${data_object_base_path}/frameworks/innerkitsimpl/src/adaptor/asset_change_timer.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/adaptor/client_adaptor.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/adaptor/distributed_object_impl.cpp", "${data_object_base_path}/frameworks/innerkitsimpl/src/adaptor/distributed_object_store_impl.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/adaptor/flat_object_storage_engine.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/adaptor/flat_object_store.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/adaptor/object_callback_impl.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/app_device_handler.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/app_pipe_handler.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/app_pipe_mgr.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/ark_communication_provider.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/communication_provider.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/communication_provider_impl.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/dev_manager.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/process_communicator_impl.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/object_callback_stub.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/object_radar_reporter.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/object_service_proxy.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/object_types_util.cpp", "${data_object_base_path}/frameworks/innerkitsimpl/test/unittest/src/distributed_object_store_impl_test.cpp", ] @@ -211,7 +235,6 @@ ohos_unittest("DistributedObjectStoreImplTest") { "private = public", "protected = public", ] - deps = [ "${data_object_base_path}/interfaces/innerkits:distributeddataobject_static" ] } ohos_unittest("FlatObjectStoreTest") { @@ -278,6 +301,21 @@ ohos_unittest("AppDeviceHandlerTest") { deps = [ "${data_object_base_path}/interfaces/innerkits:distributeddataobject_static" ] } +ohos_unittest("ObjectTaskSchedulerTest") { + module_out_path = module_output_path + + sources = [ "${data_object_base_path}/frameworks/innerkitsimpl/test/unittest/src/task_scheduler_test.cpp", ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "c_utils:utils", + "googletest:gtest", + "hilog:libhilog", + ] + +} + group("unittest") { testonly = true deps = [] @@ -292,5 +330,6 @@ group("unittest") { ":ObjectCallbackStubTest", ":ObjectServiceProxyTest", ":ObjectTypesUtilTest", + ":ObjectTaskSchedulerTest", ] } diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/client_adaptor_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/client_adaptor_test.cpp index db0b1a067fff57190bd44d88861c1b164bd242e2..039fc51573e6d50d6642c9eedf7246b45534c747 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/src/client_adaptor_test.cpp +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/client_adaptor_test.cpp @@ -106,6 +106,5 @@ HWTEST_F(ClientAdaptorTest, RegisterClientDeathListener_002, TestSize.Level1) sptr remoteObject = new IPCObjectStub(); uint32_t ret = clientAdaptor.RegisterClientDeathListener(appId, remoteObject); EXPECT_EQ(ret, SUCCESS); - delete remoteObject; } } diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/communicator_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/communicator_test.cpp index 31fbf9022b53a573128884cf02b9c46c8dfde4fa..8945aefa4d784e4a94962b974ad1ec80447bdf9e 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/src/communicator_test.cpp +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/communicator_test.cpp @@ -37,10 +37,6 @@ using namespace OHOS::Security::AccessToken; using namespace OHOS::ObjectStore; namespace { -constexpr int32_t HEAD_SIZE = 3; -constexpr const char *REPLACE_CHAIN = "***"; -constexpr const char *DEFAULT_ANONYMOUS = "******"; - class NativeCommunicatorTest : public testing::Test { public: static void SetUpTestCase(void); @@ -305,32 +301,6 @@ HWTEST_F(NativeCommunicatorTest, SoftBusAdapter_StopWatchDataChange_002, TestSiz EXPECT_EQ(Status::ERROR, ret); } -/** - * @tc.name: SoftBusAdapter_ToBeAnonymous_001 - * @tc.desc: test SoftBusAdapter ToBeAnonymous. - * @tc.type: FUNC - */ -HWTEST_F(NativeCommunicatorTest, SoftBusAdapter_ToBeAnonymous_001, TestSize.Level1) -{ - std::string name = "na"; - SoftBusAdapter softBusAdapter; - auto ret = softBusAdapter.ToBeAnonymous(name); - EXPECT_EQ(DEFAULT_ANONYMOUS, ret); -} - -/** - * @tc.name: SoftBusAdapter_ToBeAnonymous_002 - * @tc.desc: test SoftBusAdapter ToBeAnonymous. - * @tc.type: FUNC - */ -HWTEST_F(NativeCommunicatorTest, SoftBusAdapter_ToBeAnonymous_002, TestSize.Level1) -{ - std::string name = "name"; - SoftBusAdapter softBusAdapter; - auto ret = softBusAdapter.ToBeAnonymous(name); - EXPECT_EQ(name.substr(0, HEAD_SIZE) + REPLACE_CHAIN, ret); -} - /** * @tc.name: SoftBusAdapter_GetLocalBasicInfo_001 * @tc.desc: test SoftBusAdapter GetLocalBasicInfo. @@ -569,4 +539,32 @@ HWTEST_F(NativeCommunicatorTest, DevManager_GetLocalDevice_001, TestSize.Level1) DevManager::DetailInfo detailInfo = devManager->GetLocalDevice(); EXPECT_EQ(detailInfo.networkId, ""); } + +/** +* @tc.name: DestructedSoftBusAdapter001 +* @tc.desc: Test that the destructor cleans the dataCaches when bytesMsg.ptr is not nullptr. +* @tc.type: FUNC +*/ +HWTEST_F(NativeCommunicatorTest, DestructedSoftBusAdapter001, TestSize.Level1) +{ + auto softBusAdapter = std::make_shared(); + uint32_t length = 10; + uint8_t *data = new uint8_t[length]; + SoftBusAdapter::BytesMsg bytesMsg = { data, length }; + softBusAdapter->dataCaches_["device1"] = { bytesMsg }; + EXPECT_FALSE(softBusAdapter->dataCaches_.empty()); +} + +/** +* @tc.name: DestructedSoftBusAdapter002 +* @tc.desc: Test that the destructor does not clean the dataCaches when bytesMsg.ptr is nullptr. +* @tc.type: FUNC +*/ +HWTEST_F(NativeCommunicatorTest, DestructedSoftBusAdapter002, TestSize.Level1) +{ + auto softBusAdapter = std::make_shared(); + SoftBusAdapter::BytesMsg bytesMsg = { nullptr, 0 }; + softBusAdapter->dataCaches_["device2"] = { bytesMsg }; + EXPECT_FALSE(softBusAdapter->dataCaches_.empty()); +} } diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/distributed_object_store_impl_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/distributed_object_store_impl_test.cpp index 6d2791d39417472437ae67ebd40f231b15c4d427..4892a2a2d6a09d4c920aa3a9bbe8151a7b7dc939 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/src/distributed_object_store_impl_test.cpp +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/distributed_object_store_impl_test.cpp @@ -96,4 +96,20 @@ HWTEST_F(DistributedObjectStoreImplTest, FindChangedAssetKey_001, TestSize.Level bool ret = watcherProxy.FindChangedAssetKey(changedKey, assetKey); EXPECT_EQ(ret, false); } + +/** + * @tc.name: SetProgressNotifier001 + * @tc.desc: test SetProgressNotifier. + * @tc.type: FUNC + */ + +HWTEST_F(DistributedObjectStoreImplTest, SetProgressNotifier001, TestSize.Level1) +{ + std::string bundleName = "default"; + std::string sessionId = "123456"; + auto objectStore = new DistributedObjectStoreImpl(nullptr); + auto progressNotifierPtr = std::shared_ptr(); + bool ret = objectStore->SetProgressNotifier(progressNotifierPtr); + EXPECT_EQ(ret, true); +} } diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/object_callback_stub_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/object_callback_stub_test.cpp index 548ce8fd50b3d2164aecc50a0d2c34913e63104f..75753ad6d15cf8c7c7b66a81922a56ec63181324 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/src/object_callback_stub_test.cpp +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/object_callback_stub_test.cpp @@ -75,4 +75,52 @@ HWTEST_F(ObjectCallbackStubTest, OnRemoteRequest_001, TestSize.Level1) int ret = objectChangeCallback.OnRemoteRequest(code, data, reply, option); EXPECT_EQ(ret, -1); } + +/** + * @tc.name: OnRemoteRequest_002 + * @tc.desc: Abnormal test for OnRemoteRequest, code is 0 + * @tc.type: FUNC + */ + +HWTEST_F(ObjectCallbackStubTest, OnRemoteRequest_002, TestSize.Level1) +{ + uint32_t code = 0; + OHOS::MessageParcel data; + OHOS::MessageParcel reply; + OHOS::MessageOption option; + const std::function callback; + ObjectProgressCallback objectProgressCallback(callback); + OHOS::IPCObjectStub objectStub; + int ret = objectProgressCallback.OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(ret, -1); + std::u16string dataObjectInterfaceToken = u"OHOS.DistributedObject.IObjectProgressCallback"; + data.WriteInterfaceToken(dataObjectInterfaceToken); + ret = objectProgressCallback.OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(ret, -1); +} + +/** + * @tc.name: OnRemoteRequest_003 + * @tc.desc: OnRemoteRequest test + * @tc.type: FUNC + */ + +HWTEST_F(ObjectCallbackStubTest, OnRemoteRequest_003, TestSize.Level1) +{ + uint32_t code = 0; + OHOS::MessageParcel data; + OHOS::MessageParcel reply; + OHOS::MessageOption option; + const std::function callback; + ObjectProgressCallback objectProgressCallback(callback); + OHOS::IPCObjectStub objectStub; + std::u16string dataObjectInterfaceToken = u"OHOS.DistributedObject.IObjectProgressCallback"; + data.WriteInterfaceToken(dataObjectInterfaceToken); + uint32_t code_1 = 1; + auto ret = objectProgressCallback.OnRemoteRequest(code_1, data, reply, option); + int32_t progress = 100; + OHOS::ITypesUtil::Marshal(data, progress); + ret = objectProgressCallback.OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(ret, -1); +} } diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/object_service_proxy_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/object_service_proxy_test.cpp index 4d736b42eb6fc7b0ca8721eaf7cc0f57389bfb54..fd8896c3266469956d7d564ce6290ad7eebafc9e 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/src/object_service_proxy_test.cpp +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/object_service_proxy_test.cpp @@ -117,4 +117,34 @@ HWTEST_F(ObjectServiceProxyTest, BindAssetStore_001, TestSize.Level1) int32_t ret = objectServiceProxy.BindAssetStore(bundleName, sessionId, asset, bindInfo); EXPECT_EQ(ret, OHOS::ObjectStore::ERR_IPC); } + +/** + * @tc.name: RegisterProgressObserver_001 + * @tc.desc: Abnormal test for RegisterProgressObserver, impl is nullptr + * @tc.type: FUNC + */ +HWTEST_F(ObjectServiceProxyTest, RegisterProgressObserver_001, TestSize.Level1) +{ + string bundleName = "com.example.myapplication"; + string sessionId = "123456"; + sptr impl; + ObjectServiceProxy objectServiceProxy(impl); + int32_t ret = objectServiceProxy.RegisterProgressObserver(bundleName, sessionId, impl); + EXPECT_EQ(ret, OHOS::ObjectStore::ERR_IPC); +} + +/** + * @tc.name: UnregisterProgressObserver_001 + * @tc.desc: Abnormal test for UnregisterProgressObserver, impl is nullptr + * @tc.type: FUNC + */ +HWTEST_F(ObjectServiceProxyTest, UnregisterProgressObserver_001, TestSize.Level1) +{ + string bundleName = "com.example.myapplication"; + string sessionId = "123456"; + sptr impl; + ObjectServiceProxy objectServiceProxy(impl); + int32_t ret = objectServiceProxy.UnregisterProgressObserver(bundleName, sessionId); + EXPECT_EQ(ret, OHOS::ObjectStore::ERR_IPC); +} } diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/object_store_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/object_store_test.cpp index 55c04bdcf92c6840b2b1b6cb7a5896768b2ecc22..d14b88614fa9b253cb0a9fa9e9e5ce56679abd4a 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/src/object_store_test.cpp +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/object_store_test.cpp @@ -28,6 +28,7 @@ #include "nativetoken_kit.h" #include "object_storage_engine.h" #include "objectstore_errors.h" +#include "store_errno.h" #include "token_setproc.h" using namespace testing::ext; @@ -69,6 +70,18 @@ void StatusNotifierImpl::OnChanged(const std::string &sessionId, { } +class ProgressNotifierImpl : public ProgressWatcher { +public: +void OnChanged(const std::string &sessionId, int32_t progress) override; +virtual ~ProgressNotifierImpl(); +}; +ProgressNotifierImpl::~ProgressNotifierImpl() +{ +} + +void ProgressNotifierImpl::OnChanged(const std::string &sessionId, int32_t progress) +{ +} void GrantPermissionNative() { const char **perms = new const char *[3]; @@ -129,10 +142,10 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStore_Create_Destroy_001, TestS std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = objectStore->DeleteObject(sessionId); EXPECT_EQ(SUCCESS, ret); @@ -163,10 +176,10 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStore_Create_Destroy_003, TestS std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); DistributedObject *object2 = objectStore->CreateObject(sessionId); EXPECT_EQ(nullptr, object2); @@ -185,11 +198,11 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStore_Create_Destroy_004, TestS std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); uint32_t status = -1; DistributedObject *object = objectStore->CreateObject(sessionId, status); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); EXPECT_EQ(SUCCESS, status); uint32_t ret = objectStore->DeleteObject(sessionId); @@ -206,7 +219,7 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStoreImpl_CreateObject_001, Tes std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(""); EXPECT_EQ(nullptr, object); @@ -240,7 +253,7 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStoreImpl_CreateObject_003, Tes std::string bundleName = "default"; std::string sessionId = ""; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); uint32_t status = -1; DistributedObject *object = objectStore->CreateObject(sessionId, status); @@ -261,10 +274,10 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStoreImpl_Get_001, TestSize.Lev std::string bundleName = "default"; std::string sessionId = "sessionId"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); DistributedObject *Object1 = nullptr; uint32_t status = objectStore->Get("", &Object1); @@ -312,10 +325,10 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStoreImpl_Watch_002, TestSize.L std::string bundleName = "default"; std::string sessionId = "sessionId"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); std::shared_ptr watcher = std::make_shared(); uint32_t status = objectStore->Watch(object, watcher); @@ -353,10 +366,10 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStore_Get_001, TestSize.Level1) std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); DistributedObject *object2 = nullptr; uint32_t ret = objectStore->Get(sessionId, &object2); @@ -377,10 +390,10 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStore_Watch_UnWatch_001, TestSi std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); auto watcherPtr = std::shared_ptr(); uint32_t ret = objectStore->Watch(object, watcherPtr); @@ -403,9 +416,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStore_SetStatusNotifier_001, Te std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); auto notifierPtr = std::shared_ptr(); uint32_t ret = objectStore->SetStatusNotifier(notifierPtr); @@ -426,9 +439,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_Double_001, TestSize.Level1) std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = object->PutDouble("salary", SALARY); EXPECT_EQ(ret, 0); @@ -452,9 +465,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetDouble_001, TestSize.Level1 std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); double value = 0.0; uint32_t ret = object->GetDouble("salary", value); @@ -475,9 +488,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_Boolean_001, TestSize.Level1) std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = object->PutBoolean("isTrue", true); EXPECT_EQ(SUCCESS, ret); @@ -501,9 +514,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetBoolean_001, TestSize.Level std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); bool value = false; uint32_t ret = object->GetBoolean("isTrue", value); @@ -524,9 +537,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_String_001, TestSize.Level1) std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = object->PutString("name", "zhangsan"); EXPECT_EQ(SUCCESS, ret); @@ -550,9 +563,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetString_001, TestSize.Level1 std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); std::string value = ""; uint32_t ret = object->GetString("name", value); @@ -573,9 +586,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetSessionId_001, TestSize.Lev std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); std::string getSessionId = object->GetSessionId(); EXPECT_EQ(sessionId, getSessionId); uint32_t ret = objectStore->DeleteObject(sessionId); @@ -592,9 +605,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_PutComplex_001, TestSize.Level std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); std::vector value = {'z', 'h'}; uint32_t ret = object->PutComplex("name", value); @@ -613,9 +626,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetComplex_001, TestSize.Level std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); std::vector value = {'z', 'h'}; uint32_t ret = object->PutComplex("name", value); @@ -636,9 +649,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetComplex_002, TestSize.Level std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); std::vector value = {'z', 'h'}; uint32_t ret = object->GetComplex("name", value); @@ -657,9 +670,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_SetAsset_001, TestSize.Level1) std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = object->PutString("attachment.name", "1.txt"); EXPECT_EQ(SUCCESS, ret); @@ -687,9 +700,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_TestSetSessionId_001, TestSize { auto testSetSessionId = [] (std::string bundleName, std::string sessionId) { DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = objectStore->DeleteObject(sessionId); EXPECT_EQ(SUCCESS, ret); @@ -712,9 +725,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetType_001, TestSize.Level1) std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = object->PutString("name", "zhangsan"); EXPECT_EQ(SUCCESS, ret); @@ -749,9 +762,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetType_002, TestSize.Level1) std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); Type type; uint32_t ret = object->GetType("name", type); @@ -772,9 +785,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_Save_RevokeSave_001, TestSize. std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = object->PutString("name", "zhangsan"); @@ -802,9 +815,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_Save_RevokeSave_002, TestSize. { auto testSaveAndRevokeSave = [](std::string bundleName, std::string sessionId) { DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = object->PutString("name", "zhangsan"); EXPECT_EQ(SUCCESS, ret); @@ -839,9 +852,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_Save_RevokeSave_003, TestSize. std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = object->RevokeSave(); EXPECT_EQ(SUCCESS, ret); @@ -1226,7 +1239,7 @@ HWTEST_F(NativeObjectStoreTest, CacheManager_Save_001, TestSize.Level1) std::map> objectData; CacheManager cacheManager; auto ret = cacheManager.Save(bundleName, sessionId, deviceId, objectData); - EXPECT_EQ(OBJECT_PERMISSION_DENIED, ret); + EXPECT_EQ(OHOS::DistributedKv::Status::INVALID_ARGUMENT, ret); } /** @@ -1240,7 +1253,7 @@ HWTEST_F(NativeObjectStoreTest, CacheManager_RevokeSave_001, TestSize.Level1) std::string sessionId = ""; CacheManager cacheManager; auto ret = cacheManager.RevokeSave(bundleName, sessionId); - EXPECT_EQ(OBJECT_PERMISSION_DENIED, ret); + EXPECT_EQ(SUCCESS, ret); } /** @@ -1256,7 +1269,7 @@ HWTEST_F(NativeObjectStoreTest, CacheManager_ResumeObject_001, TestSize.Level1) std::function> &data, bool allReady)> callback = [](const std::map> &data, bool allReady) {}; auto ret = cacheManager.ResumeObject(bundleName, sessionId, callback); - EXPECT_EQ(OBJECT_PERMISSION_DENIED, ret); + EXPECT_EQ(OHOS::DistributedKv::Status::KEY_NOT_FOUND, ret); } /** @@ -1272,7 +1285,7 @@ HWTEST_F(NativeObjectStoreTest, CacheManager_SubscribeDataChange_001, TestSize.L std::function> &data, bool allReady)> callback = [](const std::map> &data, bool allReady) {}; auto ret = cacheManager.SubscribeDataChange(bundleName, sessionId, callback); - EXPECT_EQ(OBJECT_PERMISSION_DENIED, ret); + EXPECT_EQ(SUCCESS, ret); } /** @@ -1286,7 +1299,7 @@ HWTEST_F(NativeObjectStoreTest, CacheManager_UnregisterDataChange_001, TestSize. std::string sessionId = ""; CacheManager cacheManager; auto ret = cacheManager.UnregisterDataChange(bundleName, sessionId); - EXPECT_EQ(OBJECT_PERMISSION_DENIED, ret); + EXPECT_EQ(SUCCESS, ret); } /** @@ -1311,10 +1324,10 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_NotifyCachedStatus_001, TestSi std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); uint32_t status = 0; DistributedObject *object = objectStore->CreateObject(sessionId, status); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); EXPECT_EQ(SUCCESS, status); objectStore->NotifyCachedStatus(sessionId); uint32_t ret = objectStore->DeleteObject(sessionId); @@ -1331,9 +1344,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_UnWatch_001, TestSize.Level1) std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = objectStore->UnWatch(nullptr); EXPECT_EQ(ERR_NULL_OBJECT, ret); ret = objectStore->DeleteObject(sessionId); @@ -1669,4 +1682,196 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_UpdateItem_002, TestSize.Level ret = storageEngine->DeleteTable(sessionId); EXPECT_EQ(SUCCESS, ret); } + +/** + * @tc.name: DistributedObjectStore_SetProgressNotifier_001 + * @tc.desc: test DistributedObjectStore SetProgressNotifier. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, DistributedObjectStore_SetProgressNotifier_001, TestSize.Level1) +{ + std::string bundleName = "default"; + std::string sessionId = "123456"; + DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); + ASSERT_NE(nullptr, objectStore); + DistributedObject *object = objectStore->CreateObject(sessionId); + ASSERT_NE(nullptr, object); + objectStore->NotifyProgressStatus(sessionId); + auto progressNotifierPtr = std::shared_ptr(); + auto ret = objectStore->SetProgressNotifier(progressNotifierPtr); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: DistributedObject_SetProgressNotifier_002 + * @tc.desc: test FlatObjectStorageEngine SetProgressNotifier. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, DistributedObject_SetProgressNotifier_002, TestSize.Level1) +{ + std::string bundleName = "default"; + std::string sessionId = "123456"; + std::shared_ptr storageEngine = std::make_shared(); + storageEngine->isOpened_ = true; + auto progressNotifier = std::make_shared(); + uint32_t ret = storageEngine->SetProgressNotifier(progressNotifier); + EXPECT_EQ(SUCCESS, ret); +} + +/** + * @tc.name: DistributedObject_SetProgressNotifier_003 + * @tc.desc: test FlatObjectStorageEngine SetProgressNotifier, storageEngine is not open. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, DistributedObject_SetProgressNotifier_003, TestSize.Level1) +{ + std::shared_ptr storageEngine = std::make_shared(); + auto progressNotifier = std::make_shared(); + storageEngine->isOpened_ = false; + uint32_t ret = storageEngine->SetProgressNotifier(progressNotifier); + EXPECT_EQ(ERR_DB_NOT_INIT, ret); +} + +/** + * @tc.name: DistributedObject_NotifyProgress_001 + * @tc.desc: test FlatObjectStorageEngine NotifyProgress. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, DistributedObject_NotifyProgress_001, TestSize.Level1) +{ + std::shared_ptr storageEngine = std::make_shared(); + std::string sessionId = "123456"; + int32_t progress = 100; + auto ret = storageEngine->NotifyProgress(sessionId, progress); + EXPECT_EQ(ret, false); + auto progressNotifier = std::make_shared(); + storageEngine->isOpened_ = true; + ret = storageEngine->SetProgressNotifier(progressNotifier); + ret = storageEngine->NotifyProgress(sessionId, progress); + EXPECT_EQ(ret, true); +} + +/** + * @tc.name: CacheManager_SubscribeProgressChange_001 + * @tc.desc: test CacheManager SubscribeProgressChange. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, CacheManager_SubscribeProgressChange_001, TestSize.Level1) +{ + std::string bundleName = ""; + std::string sessionId = ""; + CacheManager cacheManager; + std::function callback = [sessionId, this](int32_t progress) {}; + auto ret = cacheManager.SubscribeProgressChange(bundleName, sessionId, callback); + EXPECT_EQ(SUCCESS, ret); +} + +/** + * @tc.name: CacheManager_UnregisterProgressChange_001 + * @tc.desc: test CacheManager UnregisterProgressChange. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, CacheManager_UnregisterProgressChange_001, TestSize.Level1) +{ + std::string bundleName = ""; + std::string sessionId = ""; + CacheManager cacheManager; + auto ret = cacheManager.UnregisterProgressChange(bundleName, sessionId); + EXPECT_EQ(SUCCESS, ret); +} + +/** + * @tc.name: FlatObjectStore_CheckProgressCache_001 + * @tc.desc: test FlatObjectStore CheckProgressCache. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, FlatObjectStore_CheckProgressCache_001, TestSize.Level1) +{ + std::string sessionId = "session001"; + std::string bundleName = "default001"; + std::shared_ptr flatObjectStore = std::make_shared(bundleName); + uint32_t ret = flatObjectStore->CreateObject(sessionId); + EXPECT_EQ(SUCCESS, ret); + flatObjectStore->CheckProgressCache(sessionId); + flatObjectStore->SubscribeProgressChange(sessionId); + flatObjectStore->CheckProgressCache(sessionId); + int32_t progress = 100; + flatObjectStore->progressInfoCache_[sessionId] = progress; + flatObjectStore->CheckProgressCache(sessionId); + auto progressNotifier = std::make_shared(); + std::shared_ptr storageEngine = std::make_shared(); + storageEngine->isOpened_ = true; + ret = storageEngine->SetProgressNotifier(progressNotifier); + ret = storageEngine->NotifyProgress(sessionId, progress); + EXPECT_EQ(ret, true); + flatObjectStore->CheckProgressCache(sessionId); + ret = flatObjectStore->Delete(sessionId); + EXPECT_EQ(SUCCESS, ret); +} + +/** + * @tc.name: FlatObjectStore_SubscribeProgressChange_001 + * @tc.desc: test FlatObjectStore SubscribeProgressChange. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, FlatObjectStore_SubscribeProgressChange_001, TestSize.Level1) +{ + std::string sessionId = "session001"; + std::string bundleName = "default001"; + std::shared_ptr flatObjectStore = std::make_shared(bundleName); + uint32_t ret = flatObjectStore->CreateObject(sessionId); + EXPECT_EQ(SUCCESS, ret); + flatObjectStore->SubscribeProgressChange(sessionId); + ret = flatObjectStore->Delete(sessionId); + EXPECT_EQ(SUCCESS, ret); +} + +/** + * @tc.name: FlatObjectStore_SetProgressNotifier_001 + * @tc.desc: test FlatObjectStore SetProgressNotifier. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, FlatObjectStore_SetProgressNotifier_001, TestSize.Level1) +{ + std::string sessionId = "session001"; + std::string bundleName = "default001"; + std::shared_ptr flatObjectStore = std::make_shared(bundleName); + uint32_t ret = flatObjectStore->CreateObject(sessionId); + EXPECT_EQ(SUCCESS, ret); + auto progressNotifier = std::make_shared(); + std::shared_ptr storageEngine = std::make_shared(); + flatObjectStore->storageEngine_->isOpened_ = true; + flatObjectStore->SetProgressNotifier(progressNotifier); + flatObjectStore->storageEngine_->isOpened_ = false; + flatObjectStore->SetProgressNotifier(progressNotifier); + ret = flatObjectStore->Delete(sessionId); + EXPECT_EQ(SUCCESS, ret); +} + +/** + * @tc.name: FlatObjectStore_SetProgressNotifier_002 + * @tc.desc: test FlatObjectStore SetProgressNotifier,storageEngine is not open. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, FlatObjectStore_SetProgressNotifier_002, TestSize.Level1) +{ + std::string sessionId = "session001"; + std::string bundleName = "default001"; + std::shared_ptr flatObjectStore = std::make_shared(bundleName); + uint32_t ret = flatObjectStore->CreateObject(sessionId); + EXPECT_EQ(SUCCESS, ret); + auto progressNotifier = std::make_shared(); + std::shared_ptr storageEngine = std::make_shared(); + auto notifier = std::shared_ptr(); + std::shared_ptr progressNotifierProxy = std::make_shared(notifier); + int32_t progress = 100; + progressNotifierProxy->OnChanged(sessionId, progress); + progressNotifierProxy->notifier = notifier; + progressNotifierProxy->OnChanged(sessionId, progress); + storageEngine->isOpened_ = false; + flatObjectStore->SetProgressNotifier(progressNotifier); + EXPECT_EQ(SUCCESS, ret); + ret = flatObjectStore->Delete(sessionId); + EXPECT_EQ(SUCCESS, ret); +} } // namespace diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/task_scheduler_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/task_scheduler_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..11f7f4e02bbf43efe905c0083742e8e91f8305b7 --- /dev/null +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/task_scheduler_test.cpp @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2025 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 "task_scheduler.h" + +#include + +#include "block_data.h" +namespace OHOS::Test { +using namespace testing::ext; +using namespace OHOS; +using duration = std::chrono::steady_clock::duration; +class TaskSchedulerTest : public testing::Test { +public: + static constexpr uint32_t SHORT_INTERVAL = 100; // ms + static constexpr uint32_t LONG_INTERVAL = 1; // s + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() { } +}; + +/** + * @tc.name: At + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: ht + */ +HWTEST_F(TaskSchedulerTest, At, TestSize.Level0) +{ + TaskScheduler taskScheduler("atTest"); + auto expiredTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(SHORT_INTERVAL); + int testData = 10; + auto blockData = std::make_shared>(LONG_INTERVAL, testData); + auto atTaskId1 = taskScheduler.At(expiredTime, [blockData]() { + int testData = 11; + blockData->SetValue(testData); + }); + ASSERT_EQ(blockData->GetValue(), 11); + blockData->Clear(); + expiredTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(SHORT_INTERVAL); + auto atTaskId2 = taskScheduler.At(expiredTime, [blockData]() { + int testData = 12; + blockData->SetValue(testData); + }); + ASSERT_EQ(blockData->GetValue(), 12); + ASSERT_NE(atTaskId1, atTaskId2); +} + +/** + * @tc.name: Every + * @tc.desc:execute task periodically with duration + * @tc.type: FUNC + * @tc.require: + * @tc.author: ht + */ +HWTEST_F(TaskSchedulerTest, ExecuteDuration, TestSize.Level0) +{ + TaskScheduler taskScheduler("everyTest"); + auto blockData = std::make_shared>(LONG_INTERVAL, 0); + int testData = 0; + taskScheduler.Every(std::chrono::milliseconds(SHORT_INTERVAL), [blockData, &testData]() { + testData++; + blockData->SetValue(testData); + }); + for (int i = 1; i < 10; ++i) { + ASSERT_EQ(blockData->GetValue(), i); + blockData->Clear(0); + } +} + +/** + * @tc.name: Reset + * @tc.desc: Reset before task execution and the task is tasks_.begin() or not + * @tc.type: FUNC + * @tc.require: + * @tc.author: ht + */ +HWTEST_F(TaskSchedulerTest, Reset1, TestSize.Level0) +{ + TaskScheduler taskScheduler("reset1Test"); + auto expiredTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(SHORT_INTERVAL); + auto atTaskId1 = taskScheduler.At(expiredTime, []() {}); + ASSERT_EQ(atTaskId1, 1); + expiredTime += std::chrono::milliseconds(LONG_INTERVAL); + auto atTaskId2 = taskScheduler.At(expiredTime, []() {}); + ASSERT_EQ(atTaskId2, 2); + + auto resetTaskId1 = taskScheduler.Reset(atTaskId1, std::chrono::milliseconds(SHORT_INTERVAL)); + ASSERT_EQ(resetTaskId1, atTaskId1); + + auto resetTaskId2 = taskScheduler.Reset(atTaskId2, std::chrono::milliseconds(SHORT_INTERVAL)); + ASSERT_EQ(resetTaskId2, atTaskId2); +} + +/** + * @tc.name: Reset + * @tc.desc: Reset during task execution + * @tc.type: FUNC + * @tc.require: + * @tc.author: ht + */ +HWTEST_F(TaskSchedulerTest, Reset2, TestSize.Level0) +{ + TaskScheduler taskScheduler("reset2Test"); + int testData = 10; + auto blockData = std::make_shared>(LONG_INTERVAL, testData); + auto expiredTime = std::chrono::steady_clock::now(); + auto atTaskId = taskScheduler.At(expiredTime, [blockData]() { + blockData->GetValue(); + }); + ASSERT_EQ(atTaskId, 1); + std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_INTERVAL)); + auto resetTaskId = taskScheduler.Reset(atTaskId, std::chrono::milliseconds(0)); + ASSERT_EQ(resetTaskId, TaskScheduler::INVALID_TASK_ID); + blockData->SetValue(testData); +} + +/** + * @tc.name: Reset + * @tc.desc: Reset after task execution + * @tc.type: FUNC + * @tc.require: + * @tc.author: ht + */ +HWTEST_F(TaskSchedulerTest, Reset3, TestSize.Level0) +{ + TaskScheduler taskScheduler("reset3Test"); + auto expiredTime = std::chrono::steady_clock::now(); + int testData = 10; + auto blockData = std::make_shared>(LONG_INTERVAL, testData); + auto atTaskId = taskScheduler.At(expiredTime, [blockData]() { + blockData->GetValue(); + }); + ASSERT_EQ(atTaskId, 1); + blockData->SetValue(testData); + blockData->SetValue(testData); + ASSERT_EQ(blockData->GetValue(), testData); + std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_INTERVAL)); + auto resetTaskId = taskScheduler.Reset(atTaskId, std::chrono::milliseconds(0)); + ASSERT_EQ(resetTaskId, TaskScheduler::INVALID_TASK_ID); +} + +/** + * @tc.name: Every + * @tc.desc: execute task for some times periodically with duration. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zuojiangjiang + */ +HWTEST_F(TaskSchedulerTest, EveryExecuteTimes, TestSize.Level0) +{ + TaskScheduler taskScheduler("everyTimes"); + auto blockData = std::make_shared>(LONG_INTERVAL, 0); + int testData = 0; + int times = 5; + auto taskId = taskScheduler.Every(times, std::chrono::milliseconds(0), std::chrono::milliseconds(SHORT_INTERVAL), + [blockData, times, &testData]() { + testData++; + if (testData < times) { + blockData->Clear(testData); + return; + } + blockData->SetValue(testData); + }); + ASSERT_EQ(blockData->GetValue(), times); + auto resetId = taskScheduler.Reset(taskId, std::chrono::milliseconds(SHORT_INTERVAL)); + ASSERT_EQ(resetId, TaskScheduler::INVALID_TASK_ID); + ASSERT_EQ(blockData->GetValue(), times); +} + +/** + * @tc.name: Remove + * @tc.desc: remove task before execute. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zuojiangjiang + */ +HWTEST_F(TaskSchedulerTest, RemoveBeforeExecute, TestSize.Level0) +{ + TaskScheduler taskScheduler("RemoveBeforeExecute"); + auto expiredTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(SHORT_INTERVAL); + auto blockData = std::make_shared>(LONG_INTERVAL, 0); + int testData = 0; + auto taskId = taskScheduler.At( + expiredTime, + [blockData, testData]() { + int tmpData = testData + 1; + blockData->SetValue(tmpData); + }, + std::chrono::milliseconds(SHORT_INTERVAL)); + taskScheduler.Remove(taskId); + auto resetId = taskScheduler.Reset(taskId, std::chrono::milliseconds(SHORT_INTERVAL)); + ASSERT_EQ(resetId, TaskScheduler::INVALID_TASK_ID); + ASSERT_EQ(blockData->GetValue(), testData); +} + +/** + * @tc.name: Remove + * @tc.desc: remove task during execute, and waiting. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zuojiangjiang + */ +HWTEST_F(TaskSchedulerTest, RemoveWaitExecute, TestSize.Level0) +{ + TaskScheduler taskScheduler("RemoveWaitExecute"); + auto expiredTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(0); + auto blockDataTest = std::make_shared>(LONG_INTERVAL, 0); + auto blockDataWait = std::make_shared>(LONG_INTERVAL, 0); + int testData = 1; + auto taskId = taskScheduler.At( + expiredTime, + [blockDataTest, blockDataWait, &testData]() { + blockDataTest->SetValue(testData); + blockDataWait->GetValue(); + int tmpData = testData + 1; + blockDataTest->SetValue(tmpData); + }, + std::chrono::milliseconds(SHORT_INTERVAL)); + ASSERT_EQ(blockDataTest->GetValue(), testData); + auto resetId = taskScheduler.Reset(taskId, std::chrono::milliseconds(SHORT_INTERVAL)); + ASSERT_EQ(taskId, resetId); + taskScheduler.Remove(taskId, true); + ASSERT_EQ(blockDataTest->GetValue(), testData + 1); +} + +/** + * @tc.name: Remove + * @tc.desc: remove task during execute, but no wait. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zuojiangjiang + */ +HWTEST_F(TaskSchedulerTest, RemoveNoWaitExecute, TestSize.Level0) +{ + TaskScheduler taskScheduler("RemoveNoWaitExecute"); + auto expiredTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(0); + auto blockDataTest = std::make_shared>(LONG_INTERVAL, 0); + auto blockDataWait = std::make_shared>(LONG_INTERVAL, 0); + int testData = 1; + auto taskId = taskScheduler.At(expiredTime, [blockDataTest, blockDataWait, &testData]() { + blockDataTest->SetValue(testData); + blockDataWait->GetValue(); + int tmpData = testData + 1; + blockDataTest->SetValue(tmpData); + }); + ASSERT_EQ(blockDataTest->GetValue(), testData); + blockDataTest->Clear(0); + taskScheduler.Remove(taskId); + blockDataWait->SetValue(testData); + ASSERT_EQ(blockDataTest->GetValue(), testData + 1); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/BUILD.gn b/data_object/frameworks/jskitsimpl/collaboration_edit/BUILD.gn index 0a942f35a8b6beaaab7785f8bc214734b539651b..43d8e1e5a58fdc28d9323c7d136cc01ba8684ce6 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/BUILD.gn +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/BUILD.gn @@ -16,7 +16,11 @@ import("//build/ohos/ace/ace.gni") config("collaboration_edit_config") { visibility = [ ":*" ] - cflags = [ "-DHILOG_ENABLE" ] + cflags = [ + "-DHILOG_ENABLE", + "-fvisibility=hidden", + "-Oz", + ] include_dirs = [ "include", diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/include/napi_async_call.h b/data_object/frameworks/jskitsimpl/collaboration_edit/include/napi_async_call.h index 10dc29beb4521a9b113c029670d336045792aa1b..b216c0ca08dd1815ae135466806e78a9321b331a 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/include/napi_async_call.h +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/include/napi_async_call.h @@ -1,83 +1,86 @@ -/* - * Copyright (c) 2025 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 DATA_OBJ_NAPI_ASYNC_CALL_H -#define DATA_OBJ_NAPI_ASYNC_CALL_H - -#include - -#include "db_store.h" -#include "napi_errno.h" -#include "napi_utils.h" -#include "napi/native_api.h" -#include "napi/native_common.h" -#include "rd_type.h" - -namespace OHOS::CollaborationEdit { -struct ProgressDetailT { - ProgressCode code; -}; - -struct SyncCallbackParamT { - std::promise promise; - ProgressDetailT detail; -}; - -using InputAction = std::function; -using OutputAction = std::function; -using ExecuteAction = std::function; - -constexpr const char *SYNC_FUNCTION_NAME = "CollaborationAsyncCall"; -constexpr std::chrono::seconds TIME_THRESHOLD = std::chrono::seconds(30); - -class SyncContext { -public: - int SetAll(napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output); - void ReleaseInnerReference(); - virtual ~SyncContext(); - - napi_env env_ = nullptr; - napi_ref self_ = nullptr; - void *boundObj = nullptr; // unwrapped collaborationEdit object - const char *fun = nullptr; // function name in napi queue - - napi_async_work work_ = nullptr; - napi_value result_ = nullptr; - - int execCode_ = OK; - OutputAction output_ = nullptr; - ExecuteAction exec_ = nullptr; - std::shared_ptr keep_; // keep self alive - - uint64_t syncId = 0u; - std::mutex callbackMutex_; - napi_threadsafe_function callback_ = nullptr; - - int32_t syncMode_; - std::shared_ptr dbStore_ = nullptr; -}; - -class AsyncCall final { -public: - static int Call(napi_env env, std::shared_ptr context, const char *fun); - static void CloudSyncCallback(napi_env env, napi_value js_cb, void *context, void *data); - -private: - static void OnExecute(napi_env env, void *data); - static void OnComplete(napi_env env, void *data); - static void OnReturn(napi_env env, napi_status status, void *data); - static void OnComplete(napi_env env, napi_status status, void *data); -}; -} // namespace OHOS::CollaborationEdit -#endif \ No newline at end of file +/* + * Copyright (c) 2025 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 DATA_OBJ_NAPI_ASYNC_CALL_H +#define DATA_OBJ_NAPI_ASYNC_CALL_H + +#include + +#include "db_store.h" +#include "napi_errno.h" +#include "napi_utils.h" +#include "napi/native_api.h" +#include "napi/native_common.h" +#include "rd_type.h" + +namespace OHOS::CollaborationEdit { +using InputAction = std::function; +using OutputAction = std::function; +using ExecuteAction = std::function; + +constexpr const char *SYNC_FUNCTION_NAME = "CollaborationAsyncCall"; +constexpr std::chrono::seconds TIME_THRESHOLD = std::chrono::seconds(30); + +class SyncContext { +public: + int SetAll(napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output); + void ReleaseInnerReference(); + void Release(); + virtual ~SyncContext(); + + napi_env env_ = nullptr; + napi_ref self_ = nullptr; + void *boundObj = nullptr; // unwrapped collaborationEdit object + const char *fun = nullptr; // function name in napi queue + + napi_async_work work_ = nullptr; + napi_value result_ = nullptr; + + int execCode_ = OK; + OutputAction output_ = nullptr; + ExecuteAction exec_ = nullptr; + std::shared_ptr keep_; // keep self alive + + uint64_t syncId = 0u; + std::mutex callbackMutex_; + napi_threadsafe_function callback_ = nullptr; + + int32_t syncMode_; + std::shared_ptr dbStore_ = nullptr; +}; + +struct ProgressDetailT { + ProgressCode code; +}; + +struct SyncCallbackParamT { + std::promise promise; + ProgressDetailT detail; + std::shared_ptr syncContext; +}; + +class AsyncCall final { +public: + static int Call(napi_env env, std::shared_ptr context, const char *fun); + static void CloudSyncCallback(napi_env env, napi_value js_cb, void *context, void *data); + +private: + static void OnExecute(napi_env env, void *data); + static void OnComplete(napi_env env, void *data); + static void OnReturn(napi_env env, napi_status status, void *data); + static void OnComplete(napi_env env, napi_status status, void *data); + static void ReleaseSyncContext(std::shared_ptr syncContext); +}; +} // namespace OHOS::CollaborationEdit +#endif diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/include/napi_collaboration_edit_object.h b/data_object/frameworks/jskitsimpl/collaboration_edit/include/napi_collaboration_edit_object.h index d7be9b21cb43f3941052be4de4ad1cd5ca3407b4..fd6aba0435c04f4c39baa3dd0bcdbeb7061eb899 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/include/napi_collaboration_edit_object.h +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/include/napi_collaboration_edit_object.h @@ -43,7 +43,6 @@ private: static napi_value Initialize(napi_env env, napi_callback_info info); static napi_status CreateHandlerFunc(napi_env env, std::vector &cloudDbFunc, NapiCloudDb *napiCloudDb); - static void ReleaseHandlerFunc(NapiCloudDb *napiCloudDb); static napi_value GetEditUnit(napi_env env, napi_callback_info info); static napi_value GetUndoRedoManager(napi_env env, napi_callback_info info); static napi_value DeleteUndoRedoManager(napi_env env, napi_callback_info info); diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_async_call.cpp b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_async_call.cpp index 0ed5c8dec7c422536a1a94638ec84201d2fa4dd2..26e78807f0fc41015629289c5a41b6fa934d5615 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_async_call.cpp +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_async_call.cpp @@ -57,6 +57,9 @@ void SyncContext::ReleaseInnerReference() } SyncContext::~SyncContext() +{} + +void SyncContext::Release() { LOG_DEBUG("SyncContext freed."); if (env_ == nullptr) { @@ -140,6 +143,8 @@ void AsyncCall::CloudSyncCallback(napi_env env, napi_value js_cb, void *context, napi_status status = napi_create_object(env, ¶m); if (status != napi_ok) { LOG_ERROR("create param object wrong, status: %{public}" PRIi32, static_cast(status)); + ReleaseSyncContext(callbackParam->syncContext); + callbackParam->syncContext.reset(); callbackParam->promise.set_value(0); return; } @@ -149,6 +154,8 @@ void AsyncCall::CloudSyncCallback(napi_env env, napi_value js_cb, void *context, status = napi_set_named_property(env, param, "code", pCode); if (status != napi_ok) { LOG_ERROR("set named property wrong, status: %{public}" PRIi32, static_cast(status)); + ReleaseSyncContext(callbackParam->syncContext); + callbackParam->syncContext.reset(); callbackParam->promise.set_value(0); return; } @@ -164,6 +171,17 @@ void AsyncCall::CloudSyncCallback(napi_env env, napi_value js_cb, void *context, if (status != napi_ok) { LOG_ERROR("napi call js function wrong, status: %{public}" PRIi32, static_cast(status)); } + // need to release sync context in js thread + ReleaseSyncContext(callbackParam->syncContext); + callbackParam->syncContext.reset(); callbackParam->promise.set_value(0); } + +void AsyncCall::ReleaseSyncContext(std::shared_ptr syncContext) +{ + if (syncContext == nullptr) { + return; + } + syncContext->Release(); +} } // namespace CollaborationEdit diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_cloud_db.cpp b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_cloud_db.cpp index c60593002e01bdda4f2591e525e8132b4c5afb6d..86c4539aac4d1e7c76433c838f83d687ff884014 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_cloud_db.cpp +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_cloud_db.cpp @@ -57,7 +57,22 @@ struct QueryInfo { NapiCloudDb::NapiCloudDb() {} -NapiCloudDb::~NapiCloudDb() {} +NapiCloudDb::~NapiCloudDb() +{ + napi_release_threadsafe_function(batchInsertInnerFunc_, napi_tsfn_release); + napi_release_threadsafe_function(queryInnerFunc_, napi_tsfn_release); + napi_release_threadsafe_function(downloadAssetInnerFunc_, napi_tsfn_release); + napi_release_threadsafe_function(uploadAssetInnerFunc_, napi_tsfn_release); + napi_release_threadsafe_function(deleteAssetInnerFunc_, napi_tsfn_release); + napi_release_threadsafe_function(deleteLocalAssetInnerFunc_, napi_tsfn_release); + + batchInsertInnerFunc_ = nullptr; + queryInnerFunc_ = nullptr; + downloadAssetInnerFunc_ = nullptr; + uploadAssetInnerFunc_ = nullptr; + deleteAssetInnerFunc_ = nullptr; + deleteLocalAssetInnerFunc_ = nullptr; +} int32_t NapiCloudDb::BatchInsert(const std::vector &cloudParamsAdapter) { diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_collaboration_edit_object.cpp b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_collaboration_edit_object.cpp index 6370df8acc1273929eb5a025b185b1f349d3c867..4a580fdde8a986bd570a5197eaf84cc1ef886293 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_collaboration_edit_object.cpp +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_collaboration_edit_object.cpp @@ -57,7 +57,6 @@ napi_value CollaborationEditObject::Initialize(napi_env env, napi_callback_info ContextParam context; napi_status status = NapiUtils::GetValue(env, argv[0], context); ASSERT_THROW_BASE(env, status == napi_ok, Status::INVALID_ARGUMENT, "read context param go wrong", self); - ASSERT_THROW_BASE(env, context.isSystemApp, Status::NOT_SYSTEM_APP, "Not a system app", self); std::string docName; status = NapiUtils::GetNamedProperty(env, argv[1], "name", docName); ASSERT_THROW_BASE(env, status == napi_ok, Status::INVALID_ARGUMENT, "read docName param go wrong", self); @@ -77,7 +76,12 @@ napi_value CollaborationEditObject::Initialize(napi_env env, napi_callback_info CollaborationEditObject *editObject = reinterpret_cast(data); delete editObject; }; - napi_wrap(env, self, editObject, finalize, nullptr, nullptr); + status = napi_wrap(env, self, editObject, finalize, nullptr, nullptr); + if (status != napi_ok) { + LOG_ERROR("napi_wrap failed. code:%{public}d", status); + delete editObject; + return nullptr; + } return self; } @@ -198,6 +202,22 @@ napi_value CollaborationEditObject::SetCloudDb(napi_env env, napi_callback_info napi_value self = nullptr; NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); + CollaborationEditObject *editObject = nullptr; + napi_status status = napi_unwrap(env, self, reinterpret_cast(&editObject)); + if (status != napi_ok) { + ThrowNapiError(env, Status::INTERNAL_ERROR, "unwrap editObject go wrong."); + return nullptr; + } + std::shared_ptr dbStore = editObject->GetDBStore(); + if (dbStore == nullptr) { + ThrowNapiError(env, Status::INVALID_ARGUMENT, "dbStore is null."); + return nullptr; + } + if (dbStore->GetCloudDB() != nullptr) { + LOG_INFO("cloudDB already set"); + return nullptr; + } + std::vector cloudDbFunc; int ret = Parser::ParseCloudDbFields(env, argv[0], cloudDbFunc); if (ret != OK) { @@ -206,25 +226,15 @@ napi_value CollaborationEditObject::SetCloudDb(napi_env env, napi_callback_info } NapiCloudDb *napiCloudDb = new (std::nothrow) NapiCloudDb(); ASSERT_THROW(env, napiCloudDb != nullptr, Status::INTERNAL_ERROR, "new cloud db instance go wrong."); - napi_status status = CollaborationEditObject::CreateHandlerFunc(env, cloudDbFunc, napiCloudDb); + status = CollaborationEditObject::CreateHandlerFunc(env, cloudDbFunc, napiCloudDb); if (status != napi_ok) { - ReleaseHandlerFunc(napiCloudDb); delete napiCloudDb; ThrowNapiError(env, Status::INTERNAL_ERROR, "create handler func go wrong."); return nullptr; } - CollaborationEditObject *editObject = nullptr; - status = napi_unwrap(env, self, reinterpret_cast(&editObject)); - if (status != napi_ok) { - ReleaseHandlerFunc(napiCloudDb); - delete napiCloudDb; - ThrowNapiError(env, Status::INTERNAL_ERROR, "unwrap editObject go wrong."); - return nullptr; - } - ret = DBStoreManager::GetInstance().SetCloudDb(editObject->GetDBStore(), napiCloudDb); + ret = DBStoreManager::GetInstance().SetCloudDb(dbStore, napiCloudDb); if (ret != 0) { - ReleaseHandlerFunc(napiCloudDb); delete napiCloudDb; ThrowNapiError(env, ret, "set cloud db go wrong."); } @@ -278,27 +288,6 @@ napi_status CollaborationEditObject::CreateHandlerFunc(napi_env env, std::vector return napi_ok; } -void CollaborationEditObject::ReleaseHandlerFunc(NapiCloudDb *napiCloudDb) -{ - if (napiCloudDb == nullptr) { - return; - } - napi_release_threadsafe_function(napiCloudDb->batchInsertInnerFunc_, napi_tsfn_release); - napi_release_threadsafe_function(napiCloudDb->queryInnerFunc_, napi_tsfn_release); - napi_release_threadsafe_function(napiCloudDb->downloadAssetInnerFunc_, napi_tsfn_release); - napi_release_threadsafe_function(napiCloudDb->uploadAssetInnerFunc_, napi_tsfn_release); - napi_release_threadsafe_function(napiCloudDb->deleteAssetInnerFunc_, napi_tsfn_release); - napi_release_threadsafe_function(napiCloudDb->deleteLocalAssetInnerFunc_, napi_tsfn_release); - - napiCloudDb->batchInsertInnerFunc_ = nullptr; - napiCloudDb->queryInnerFunc_ = nullptr; - napiCloudDb->downloadAssetInnerFunc_ = nullptr; - napiCloudDb->downloadAssetInnerFunc_ = nullptr; - napiCloudDb->uploadAssetInnerFunc_ = nullptr; - napiCloudDb->deleteAssetInnerFunc_ = nullptr; - napiCloudDb->deleteLocalAssetInnerFunc_ = nullptr; -} - napi_value CollaborationEditObject::Delete(napi_env env, napi_callback_info info) { size_t argc = 2; @@ -308,7 +297,6 @@ napi_value CollaborationEditObject::Delete(napi_env env, napi_callback_info info ContextParam context; napi_status status = NapiUtils::GetValue(env, argv[0], context); ASSERT_THROW_BASE(env, status == napi_ok, Status::INVALID_ARGUMENT, "read context param go wrong", self); - ASSERT_THROW_BASE(env, context.isSystemApp, Status::NOT_SYSTEM_APP, "Not a system app", self); std::string docName; status = NapiUtils::GetNamedProperty(env, argv[1], "name", docName); ASSERT_THROW_BASE(env, status == napi_ok, Status::INVALID_ARGUMENT, "read docName param go wrong", self); @@ -328,7 +316,7 @@ int CollaborationEditObject::ParseCloudSyncMode(const napi_env env, const napi_v int32_t mode = 0; napi_status status = NapiUtils::GetValue(env, arg, mode); if (status != napi_ok || mode < 0 || mode > SyncMode::PULL_PUSH) { - LOG_ERROR("CloudSync parse syncMode go wrong, mode: %d", mode); + LOG_ERROR("CloudSync parse syncMode go wrong, mode: %{public}d", mode); return ERR; } context->syncMode_ = mode; @@ -468,9 +456,10 @@ void CollaborationEditObject::SyncCallbackFunc(GRD_SyncProcessT *syncProcess) return; } napi_threadsafe_function js_cb = context->callback_; + context->callback_ = nullptr; + context->ReleaseInnerReference(); if (js_cb == nullptr) { LOG_ERROR("callback is null"); - context->ReleaseInnerReference(); return; } @@ -478,20 +467,18 @@ void CollaborationEditObject::SyncCallbackFunc(GRD_SyncProcessT *syncProcess) if (ret != napi_ok) { LOG_ERROR("acquire thread safe function failed, ret: %{public}d", static_cast(ret)); napi_release_threadsafe_function(js_cb, napi_tsfn_release); - context->callback_ = nullptr; - context->ReleaseInnerReference(); return; } SyncCallbackParamT param = {}; param.detail.code = CollaborationEditObject::GetProgressCode(syncProcess->errCode); + param.syncContext = context; + context.reset(); std::future future = param.promise.get_future(); ret = napi_call_threadsafe_function(js_cb, ¶m, napi_tsfn_blocking); if (ret != napi_ok) { LOG_ERROR("call function go wrong, ret=%{public}d", static_cast(ret)); napi_release_threadsafe_function(js_cb, napi_tsfn_release); - context->callback_ = nullptr; - context->ReleaseInnerReference(); return; } std::future_status fstatus = future.wait_for(std::chrono::duration_cast(TIME_THRESHOLD)); @@ -502,8 +489,6 @@ void CollaborationEditObject::SyncCallbackFunc(GRD_SyncProcessT *syncProcess) } napi_release_threadsafe_function(js_cb, napi_tsfn_release); - context->callback_ = nullptr; - context->ReleaseInnerReference(); LOG_INFO("syncCallback end"); } diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_edit_unit.cpp b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_edit_unit.cpp index 183d849aa1fbbad14ef824c9150f4dde9aba5b43..237d07ea620a1c6fc5eed212fe4b781be87c57d5 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_edit_unit.cpp +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_edit_unit.cpp @@ -49,7 +49,12 @@ napi_value EditUnit::Initialize(napi_env env, napi_callback_info info) EditUnit *editUnit = reinterpret_cast(data); delete editUnit; }; - napi_wrap(env, self, editUnit, finalize, nullptr, nullptr); + status = napi_wrap(env, self, editUnit, finalize, nullptr, nullptr); + if (status != napi_ok) { + LOG_ERROR("napi_wrap failed. code:%{public}d", status); + delete editUnit; + return nullptr; + } return self; } diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_node.cpp b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_node.cpp index 685339afc3314094da7084f6c4a102d0a851ac7c..cf928ecc49093129ad5f2b4ac3d77aed30a2cfd0 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_node.cpp +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_node.cpp @@ -84,7 +84,12 @@ napi_value Node::New(napi_env env, napi_callback_info info) Node *node = reinterpret_cast(data); delete node; }; - napi_wrap(env, self, node, finalize, nullptr, nullptr); + napi_status status = napi_wrap(env, self, node, finalize, nullptr, nullptr); + if (status != napi_ok) { + LOG_ERROR("napi_wrap failed. code:%{public}d", status); + delete node; + return nullptr; + } return self; } diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_text.cpp b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_text.cpp index 69579ebd7ac8bf9c7065795c03f0df43490f8f5d..5fad6b836ed7a23e0ce2ba58cac6efad1c7a012c 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_text.cpp +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_text.cpp @@ -69,7 +69,12 @@ napi_value Text::New(napi_env env, napi_callback_info info) Text *text = reinterpret_cast(data); delete text; }; - napi_wrap(env, self, text, finalize, nullptr, nullptr); + napi_status status = napi_wrap(env, self, text, finalize, nullptr, nullptr); + if (status != napi_ok) { + LOG_ERROR("napi_wrap failed. code:%{public}d", status); + delete text; + return nullptr; + } return self; } diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_undo_manager.cpp b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_undo_manager.cpp index f8b4a21db6026346d49ceb5427be8ddc1517e653..ea5cdefae00b6d831c9cf29eea54e03eb2cca9d5 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_undo_manager.cpp +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_undo_manager.cpp @@ -53,7 +53,12 @@ napi_value UndoManager::Initialize(napi_env env, napi_callback_info info) UndoManager *undoManager = reinterpret_cast(data); delete undoManager; }; - napi_wrap(env, self, undoManager, finalize, nullptr, nullptr); + status = napi_wrap(env, self, undoManager, finalize, nullptr, nullptr); + if (status != napi_ok) { + LOG_ERROR("napi_wrap failed. code:%{public}d", status); + delete undoManager; + return nullptr; + } return self; } diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/Application/AbilityStage.ts b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/Application/AbilityStage.ts index 13d01e2400b7afc26a0ff81d609390ee234269ab..69cecf24ac9e12a0f6f8aa053eb1ea9237b32684 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/Application/AbilityStage.ts +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/Application/AbilityStage.ts @@ -12,12 +12,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import AbilityStage from "@ohos.app.ability.AbilityStage" +import AbilityStage from "@ohos.app.ability.AbilityStage"; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; export default class MyAbilityStage extends AbilityStage { onCreate() { console.log('[Demo] MyAbilityStage onCreate'); globalThis.stageOnCreateRun = 1; globalThis.stageContext = this.context; + globalThis.abilityContext = this.context; } } diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/EditUnit.ets b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/EditUnit.ets index a3df06da31260e8308d0d4928d07bcb4d424dd84..7f5e202a7d46878e88a0b3e3e7eaf82a68f901a2 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/EditUnit.ets +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/EditUnit.ets @@ -62,7 +62,7 @@ export default function collaborationEditUnitTest() { * 1. getEditUnit by empty input string * 2. check 401 error code */ - it("CollaborationEdit_EditUnit_0001", Level.LEVEL0, () => { + it("CollaborationEdit_EditUnit_0001", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_EditUnit_0001 Start*****************"); expect(editObject !== undefined).assertTrue(); let editUnit: collaboration_edit.EditUnit | undefined; @@ -83,7 +83,7 @@ export default function collaborationEditUnitTest() { * 1. check EditUnit.getName * 2. insert null node array and check 401 error code */ - it("CollaborationEdit_EditUnit_0002", Level.LEVEL0, () => { + it("CollaborationEdit_EditUnit_0002", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_EditUnit_0002 Start*****************"); expect(editUnit !== undefined).assertTrue(); expect(EDIT_UNIT_NAME).assertEqual(editUnit?.getName()); @@ -107,7 +107,7 @@ export default function collaborationEditUnitTest() { * 4. EditUnit.getChildren and check result * 5. EditUnit.getJsonResult and check result */ - it("CollaborationEdit_EditUnit_0003", Level.LEVEL0, () => { + it("CollaborationEdit_EditUnit_0003", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_EditUnit_0003 Start*****************"); expect(editUnit !== undefined).assertTrue(); try { diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/List.test.ets b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/List.test.ets index 1da6e6c622e6a580a71824bc635054f18633a63f..8c333c4e977c7970bf653ae73a0979728a97eeb9 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/List.test.ets +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/List.test.ets @@ -13,18 +13,8 @@ * limitations under the License. */ -import collaborationGetEditObjectTest from './GetEditObject.ets'; -import collaborationEditUnitTest from './EditUnit.ets'; -import collaborationNodeTest from './Node.ets'; -import collaborationTextTest from './Text.ets'; -import collaborationUndoRedoTest from './UndoRedo.ets'; -import collaborationSetCloudDbTest from './SetCloudDb.ets'; +import collaborationrunTextTest from './RunTest.ets'; export default function testsuite() { - collaborationGetEditObjectTest(); - collaborationEditUnitTest(); - collaborationNodeTest(); - collaborationTextTest(); - collaborationUndoRedoTest(); - collaborationSetCloudDbTest(); + collaborationrunTextTest(); } diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/Node.ets b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/Node.ets index 6bb407a8d9698c6f9ead7e7ea425baf0c3647261..32b0a865e53116a4d746d06c4348418c41574934 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/Node.ets +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/Node.ets @@ -107,7 +107,7 @@ export default function collaborationNodeTest() { * 6. delete the first child * 7. again check result by getChildren and getJsonResult */ - it("CollaborationEdit_Node_0002", Level.LEVEL0, () => { + it("CollaborationEdit_Node_0002", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Node_0002 Start*****************"); expect(editUnit !== undefined).assertTrue(); try { @@ -159,7 +159,7 @@ export default function collaborationNodeTest() { * 6. delete the second child * 7. again check result by getChildren and getJsonResult */ - it("CollaborationEdit_Node_0003", Level.LEVEL0, () => { + it("CollaborationEdit_Node_0003", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Node_0003 Start*****************"); expect(editUnit !== undefined).assertTrue(); try { @@ -210,7 +210,7 @@ export default function collaborationNodeTest() { * 4. getChildren if start and end are out of range * 5. check error code */ - it("CollaborationEdit_Node_0004", Level.LEVEL0, () => { + it("CollaborationEdit_Node_0004", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Node_0004 Start*****************"); expect(editUnit !== undefined).assertTrue(); let errCode: string = ""; @@ -244,7 +244,7 @@ export default function collaborationNodeTest() { * 2. call getId/setAttributes of the node * 3. check the invalid operation error code */ - it("CollaborationEdit_Node_0005", Level.LEVEL0, () => { + it("CollaborationEdit_Node_0005", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Node_0005 Start*****************"); let node = new collaboration_edit.Node("p1"); let errCode: string = ""; @@ -280,7 +280,7 @@ export default function collaborationNodeTest() { * 5. getChildren - start is negative * 6. getChildren - start is greater than end */ - it("CollaborationEdit_Node_0006", 0, async () => { + it("CollaborationEdit_Node_0006", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Node_0006 Start*****************"); let node: collaboration_edit.Node | undefined = undefined; try { @@ -341,7 +341,7 @@ export default function collaborationNodeTest() { console.log(TAG + "*****************CollaborationEdit_Node_0006 End*****************"); }) - it("CollaborationEdit_Node_0007", Level.LEVEL0, () => { + it("CollaborationEdit_Node_0007", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Node_0007 Start*****************"); expect(editUnit !== undefined).assertTrue(); try { @@ -372,7 +372,7 @@ export default function collaborationNodeTest() { console.log(TAG + "*****************CollaborationEdit_Node_0007 End*****************"); }) - it("CollaborationEdit_Node_0008", Level.LEVEL0, () => { + it("CollaborationEdit_Node_0008", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Node_0008 Start*****************"); expect(editUnit !== undefined).assertTrue(); try { @@ -395,7 +395,7 @@ export default function collaborationNodeTest() { console.log(TAG + "*****************CollaborationEdit_Node_0008 End*****************"); }) - it("CollaborationEdit_Node_0009", Level.LEVEL0, () => { + it("CollaborationEdit_Node_0009", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Node_0009 Start*****************"); expect(editUnit !== undefined).assertTrue(); try { diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/RunTest.ets b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/RunTest.ets new file mode 100644 index 0000000000000000000000000000000000000000..1ab458140df29aae9c7926188c68f4f1a1503e38 --- /dev/null +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/RunTest.ets @@ -0,0 +1,651 @@ +/* + * Copyright (c) 2025 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 { describe, beforeEach, afterEach, beforeAll, it, afterAll, expect, Level } from '@ohos/hypium' +import common from '@ohos.app.ability.common'; +import commonType from '@ohos.data.commonType'; +import DataObject from '@ohos.data.distributedDataObject'; +import abilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import UIAbility from '@ohos.app.ability.UIAbility'; + + +const TAG = "[CollaborationEdit_JsTest_Text]" +let context: common.Context = globalThis.abilityContext; + + +class Note { + title: string | undefined + text: string | undefined + attachment: commonType.Asset | undefined + + constructor(title: string | undefined, text: string | undefined, + attachment: commonType.Asset | undefined) { + this.title = title; + this.text = text; + this.attachment = attachment; + } +} + +let attachment: commonType.Asset = { + name: 'test_img.jpg', + uri: 'file://com.example.myapplication/data/storage/el2/distributedfiles/dir/test_img.jpg', + path: '/dir/test_img.jpg', + createTime: '2024-01-02 10:00:00', + modifyTime: '2024-01-02 10:00:00', + size: '5', + status: commonType.AssetStatus.ASSET_NORMAL +} + +const bindInfo: DataObject.BindInfo = { + storeName: 'notepad', + tableName: 'note_t', + primaryKey: { + 'uuid': '00000000-0000-0000-0000-000000000000' + }, + field: 'attachment', + assetName: attachment.name as string +} + +let note: Note = new Note('test', 'test', attachment); + +function statusCallBack(sessionId: string, networkId: string, status: string) { +} + +function changeCallBack(sessionId: string, fields: Array) { +} + +function progressCallBack(sessionId: string, progress: number) { +} + +let sleep = (ms:number) => { + return new Promise(resolve => setTimeout(resolve, ms)); +} +export default function collaborationrunTextTest() { + describe('collaborationrunTextTest', () => { + beforeAll(async(done:Function) => { + + let abilityDelegator:abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator() + try{ + abilityDelegator.addAbilityMonitor({ + abilityName: "EntryAbility", + moduleName:"entry", + onAbilityCreate: (abilitys : UIAbility) : void => { + context = abilitys.context; + // hilog.info(domain, tag, '%{public}s', 'onAbilityCreate end'); + + }, + }, (err) : void => { + + }); + } catch (err){ + } + + abilityDelegator.executeShellCommand("aa start -a EntryAbility -b com.example.myapplication") + await sleep(2000) + + done(); + }) + + beforeEach(() => { + + }) + + afterEach(() => { + }) + + afterAll(() => { + }) + + /** + * @tc.number : CollaborationEdit_Text_0001 + * @tc.name : Monitor data changes + * @tc.desc : Test the interface function for monitoring data changes + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0001', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("change", changeCallBack); + expect(true).assertTrue() + + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + + /** + * @tc.number : CollaborationEdit_Text_0002 + * @tc.name : Monitor data changes + * @tc.desc : Test the interface function for monitoring data changes, callback is closure + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + + it('CollaborationEdit_Text_0002', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("change", () => { + }); + expect(true).assertTrue() + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0003 + * @tc.name : Remove monitoring of data changes + * @tc.desc : Test the interface function for remove monitoring of data changes + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0003', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("change",changeCallBack); + g_object.off("change", changeCallBack); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0004 + * @tc.name : Remove monitoring of data changes + * @tc.desc : Test the interface function for remove of all data changes + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0004', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("change",changeCallBack); + g_object.off("change"); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0005 + * @tc.name : Monitor data object online/offline + * @tc.desc : Test the interface function for monitoring of data object online/offline + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0005', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("status", statusCallBack); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0006 + * @tc.name : Monitor data object online/offline + * @tc.desc : Test the interface function for monitoring of data object online/offline , no callback + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0006', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("status", null); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + + /** + * @tc.number : CollaborationEdit_Text_0007 + * @tc.name : Remove monitor of data object online/offline + * @tc.desc : Test the interface function for removing monitor of data object online/offline + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + + it('CollaborationEdit_Text_0007', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("status",statusCallBack); + g_object.off("status", statusCallBack); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0008 + * @tc.name : Remove monitor of data object online/offline + * @tc.desc : Test the interface function for removing monitor of all data object online/offline + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0008', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("status",statusCallBack); + g_object.off("status"); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0010 + * @tc.name : Set a single asset + * @tc.desc : Test the interface function for setting a single asset, property parameter is null + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0010', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + let uri = "file:1.txt"; + g_object.setAsset(null, uri); + } catch (err) { + expect(err.code == 15400002).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0011 + * @tc.name : Set a single asset + * @tc.desc : Test the interface function for setting a single asset, property parameter is empty string + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0011', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + let uri = "file:1.txt"; + g_object.setAsset("", uri); + } catch (err) { + expect(err.code == 15400002).assertEqual(true); + } + }) + + + /** + * @tc.number : CollaborationEdit_Text_0012 + * @tc.name : Set a single asset + * @tc.desc : Test the interface function for setting a single asset, uri is null + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0012', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + let uri = ""; + g_object.setAsset("file", uri); + } catch (err) { + expect(err.code == 15400002).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0014 + * @tc.name : Set a single asset + * @tc.desc : Test the interface function for setting asset array, property parameter is null + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0014', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + let uris = ["file:1.txt"]; + g_object.setAssets(null, uris); + } catch (err) { + expect(err.code == 15400002).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0015 + * @tc.name : Set a single asset + * @tc.desc : Test the interface function for setting asset array, property parameter is empty string + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0015', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + let uris = ["file:1.txt"]; + g_object.setAssets("", uris); + } catch (err) { + expect(err.code == 15400002).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0016 + * @tc.name : Set a single asset + * @tc.desc : Test the interface function for setting asset array, asset array is empty + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0016', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.setAssets("file", []); + } catch (err) { + expect(err.code == 15400002).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0017 + * @tc.name : Set a single asset + * @tc.desc : Test the interface function for setting asset array, number of asset more than 50 + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0017', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + const uris: string[] = []; + for (let index = 0; index < 55; index++) { + let uri = `file${index + 1}:${index + 1}.txt`; + uris.push(uri); + } + g_object.setAssets("file", uris); + } catch (err) { + expect(err.code == 15400002).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0017 + * @tc.name : Set a single asset + * @tc.desc : Test the interface function for setting asset array, apart of assets are invalid + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0018', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + let uris = ["file:1.txt", null]; + g_object.setAssets("file", uris); + } catch (err) { + expect(err.code == 15400002).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0019 + * @tc.name : Monitor asset progress + * @tc.desc : Test the interface function for monitoring asset progress + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0019', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged", progressCallBack); + expect(true).assertTrue() + + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + + /** + * @tc.number : CollaborationEdit_Text_0020 + * @tc.name : Monitor asset progress + * @tc.desc : Test the interface function for monitoring asset progress, callback is closure + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + + it('CollaborationEdit_Text_0020', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged", () => { + }); + expect(true).assertTrue() + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0021 + * @tc.name : Remove monitoring of asset progress + * @tc.desc : Test the interface function for remove monitoring of asset progress + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0021', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged",progressCallBack); + g_object.off("progressChanged", progressCallBack); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0022 + * @tc.name : Remove monitoring of asset progress + * @tc.desc : Test the interface function for remove of all asset progress + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0022', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged",progressCallBack); + g_object.off("progressChanged"); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0023 + * @tc.name : Monitor data object online/offline + * @tc.desc : Test the interface function for monitoring of data object online/offline + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0023', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged", progressCallBack); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0024 + * @tc.name : Monitor data object online/offline + * @tc.desc : Test the interface function for monitoring of data object online/offline , no callback + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0024', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged", null); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + + /** + * @tc.number : CollaborationEdit_Text_0025 + * @tc.name : Remove monitor of data object online/offline + * @tc.desc : Test the interface function for removing monitor of data object online/offline + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + + it('CollaborationEdit_Text_0025', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged",progressCallBack); + g_object.off("progressChanged", progressCallBack); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0026 + * @tc.name : Remove monitor of data object online/offline + * @tc.desc : Test the interface function for removing monitor of all data object online/offline + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0026', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged",progressCallBack); + g_object.off("progressChanged"); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0027 + * @tc.name : Remove monitor of data object + * @tc.desc : Test the interface function for removing monitor of all data object + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0027', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged",()=>{}); + g_object.on("progressChanged",progressCallBack); + g_object.off("progressChanged",()=>{}); + } catch (err) { + expect().assertFail(); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0028 + * @tc.name : Remove monitor of data object + * @tc.desc : Test the interface function for removing monitor of all data object + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0028', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged",progressCallBack); + g_object.on("progressChanged",progressCallBack); + g_object.off("progressChanged",()=>{}); + } catch (err) { + expect().assertFail(); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0029 + * @tc.name : Remove monitor of data object + * @tc.desc : Test the interface function for removing monitor of all data object + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0029', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged",progressCallBack); + g_object.on("progressChanged",progressCallBack); + g_object.off("progressChanged",undefined); + } catch (err) { + expect().assertFail(); + } + }) + }) +} \ No newline at end of file diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/SetCloudDb.ets b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/SetCloudDb.ets index 3fa52a73b2a1cea8a0f9984a9ad8b4e613107c0f..e93a4d22d621d1177b9457765c7cfded9c07c7a4 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/SetCloudDb.ets +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/SetCloudDb.ets @@ -20,7 +20,7 @@ import common from '@ohos.app.ability.common'; import CloudDbMock from "./CloudDbMock"; import TestUtils from './TestUtils'; -const TAG = "[CollaborationEdit_JsTest_UndoRedo]" +const TAG = "[CollaborationEdit_JsTest_SetCloudDb]" const DOC_CONFIG_A: collaboration_edit.CollaborationConfig = {name: "doc_test_A"} const DOC_CONFIG_B: collaboration_edit.CollaborationConfig = {name: "doc_test_B"} let context: common.UIAbilityContext = globalThis.abilityContext; @@ -206,7 +206,7 @@ export default function collaborationSetCloudDbTest() { * 2. equip A push to cloud * 3. verify cloud record */ - it("CollaborationEdit_SetCloudDb_0002", 0, async () => { + it("CollaborationEdit_SetCloudDb_0002", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_SetCloudDb_002 Start*****************"); try { expect(editObject_A !== undefined).assertTrue(); @@ -247,7 +247,7 @@ export default function collaborationSetCloudDbTest() { * 5. equip B delete asset node, then sync * 6. equip A reads updated data */ - it("CollaborationEdit_SetCloudDb_0003", 0, async () => { + it("CollaborationEdit_SetCloudDb_0003", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_SetCloudDb_003 Start*****************"); try { expect(editObject_A !== undefined).assertTrue(); @@ -366,7 +366,7 @@ export default function collaborationSetCloudDbTest() { * 3. write cloud records to equip B * 4. equip B contains equip A's data */ - it("CollaborationEdit_SetCloudDb_0005", 0, async () => { + it("CollaborationEdit_SetCloudDb_0005", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_SetCloudDb_005 Start*****************"); try { expect(editObject_A !== undefined).assertTrue(); @@ -413,7 +413,7 @@ export default function collaborationSetCloudDbTest() { * 1. equip A insert 1 node and push to cloud * 2. get CLOUD_NOT_SET error code in callback */ - it("CollaborationEdit_SetCloudDb_0006", 0, async () => { + it("CollaborationEdit_SetCloudDb_0006", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_SetCloudDb_006 Start*****************"); try { expect(editObject_A !== undefined).assertTrue(); diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/Text.ets b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/Text.ets index 75f1d31b596aecaac0f41b6aded3e6699226a8d0..396f3733d942abdf26dda565dae477576731c224 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/Text.ets +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/Text.ets @@ -66,7 +66,7 @@ export default function collaborationTextTest() { * 5. format some characters and check result by getJsonResult * 6. delete some characters and check result by getPlainText and getJsonResult */ - it("CollaborationEdit_Text_0001", Level.LEVEL0, () => { + it("CollaborationEdit_Text_0001", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Text_0001 Start*****************"); expect(editUnit !== undefined).assertTrue(); try { diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/UndoRedo.ets b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/UndoRedo.ets index aae7d63e79682050eaee6eeda943b7a502308b46..c0ba2ade4c93d0a9931aaf9ad343dc75b113d636 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/UndoRedo.ets +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/UndoRedo.ets @@ -64,7 +64,7 @@ export default function collaborationUndoRedoTest() { * 1. editUnitName is any non-empty string * 2. captureTimeout is float */ - it("CollaborationEdit_UndoRedo_0001", Level.LEVEL0, () => { + it("CollaborationEdit_UndoRedo_0001", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_UndoRedo_0001 Start*****************"); expect(editUnit !== undefined).assertTrue(); let undoManager: collaboration_edit.UndoRedoManager | undefined; @@ -83,7 +83,7 @@ export default function collaborationUndoRedoTest() { * @tc.desc * 1. captureTimeout is negative, then check 401 error code */ - it("CollaborationEdit_UndoRedo_0002", Level.LEVEL0, () => { + it("CollaborationEdit_UndoRedo_0002", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_UndoRedo_0002 Start*****************"); expect(editUnit !== undefined).assertTrue(); let undoManager: collaboration_edit.UndoRedoManager | undefined; @@ -282,7 +282,7 @@ export default function collaborationUndoRedoTest() { * 1. get undo redo manager * 2. delete undo redo manager */ - it("CollaborationEdit_UndoRedo_0006", 0, async () => { + it("CollaborationEdit_UndoRedo_0006", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_UndoRedo_0006 Start*****************"); expect(editUnit !== undefined).assertTrue(); let undoManager: collaboration_edit.UndoRedoManager | undefined; diff --git a/data_object/frameworks/jskitsimpl/include/adaptor/js_common.h b/data_object/frameworks/jskitsimpl/include/adaptor/js_common.h index b4d3d3486433df88fe5747f3af02dcca82d31e78..678e3df9bb316f3a0fdf383bacb4c0239dc6c730 100644 --- a/data_object/frameworks/jskitsimpl/include/adaptor/js_common.h +++ b/data_object/frameworks/jskitsimpl/include/adaptor/js_common.h @@ -20,6 +20,7 @@ class Constants { public: static constexpr const char *CHANGE = "change"; static constexpr const char *STATUS = "status"; + static constexpr const char *PROGRESS = "progressChanged"; }; #define OBJECT_REVT_NOTHING diff --git a/data_object/frameworks/jskitsimpl/include/adaptor/js_distributedobject.h b/data_object/frameworks/jskitsimpl/include/adaptor/js_distributedobject.h index c0b6f0b54f6d7e5eafdbdc39fe776d8153d97720..951665b6b87093dbfa210f70c22b6b75301b849d 100644 --- a/data_object/frameworks/jskitsimpl/include/adaptor/js_distributedobject.h +++ b/data_object/frameworks/jskitsimpl/include/adaptor/js_distributedobject.h @@ -19,8 +19,8 @@ #include "js_object_wrapper.h" namespace OHOS::ObjectStore { struct ConstructContext { - DistributedObjectStore *objectStore; - DistributedObject *object; + DistributedObjectStore *objectStore = nullptr; + DistributedObject *object = nullptr; }; class JSDistributedObject { 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 3730ec8be2004af9e54b5fd1f944e54e41a7861b..cf56d94e61f7278c4722fca8a5dac3273a07ab06 100644 --- a/data_object/frameworks/jskitsimpl/include/adaptor/js_object_wrapper.h +++ b/data_object/frameworks/jskitsimpl/include/adaptor/js_object_wrapper.h @@ -34,8 +34,8 @@ public: std::string GetObjectId(); private: - DistributedObjectStore *objectStore_; - DistributedObject *object_; + DistributedObjectStore *objectStore_ = nullptr; + DistributedObject *object_ = nullptr; std::shared_ptr watcher_ = nullptr; std::shared_mutex watchMutex_{}; std::mutex mutex_; diff --git a/data_object/frameworks/jskitsimpl/include/adaptor/js_watcher.h b/data_object/frameworks/jskitsimpl/include/adaptor/js_watcher.h index f37827965f8a720f9410d52f95d161df386ac692..81e46dffa9899364bf19d520027a8cec54331de7 100644 --- a/data_object/frameworks/jskitsimpl/include/adaptor/js_watcher.h +++ b/data_object/frameworks/jskitsimpl/include/adaptor/js_watcher.h @@ -48,7 +48,7 @@ public: virtual void Clear(napi_env env); EventHandler *Find(napi_env env, napi_value handler); - EventHandler *handlers_; + EventHandler *handlers_ = nullptr; }; class ChangeEventListener : public EventListener { @@ -63,8 +63,8 @@ public: void Clear(napi_env env) override; private: bool isWatched_ = false; - DistributedObjectStore *objectStore_; - DistributedObject *object_; + DistributedObjectStore *objectStore_ = nullptr; + DistributedObject *object_ = nullptr; std::weak_ptr watcher_; }; @@ -81,6 +81,20 @@ private: std::string sessionId_; }; +class ProgressEventListener : public EventListener { +public: + ProgressEventListener(std::weak_ptr watcher, const std::string &sessionId); + bool Add(napi_env env, napi_value handler) override; + + bool Del(napi_env env, napi_value handler) override; + + void Clear(napi_env env) override; + +private: + std::weak_ptr watcher_; + std::string sessionId_; +}; + class JSWatcher : public UvQueue { public: JSWatcher(const napi_env env, DistributedObjectStore *objectStore, DistributedObject *object); @@ -95,9 +109,13 @@ public: void Emit(const char *type, const std::string &sessionId, const std::string &networkId, const std::string &status); + void Emit(const char *type, const std::string &sessionId, int32_t progress); + bool IsEmpty(); - void SetListener(ChangeEventListener *changeEventListener, StatusEventListener *statusEventListener); + void SetListener(ChangeEventListener *changeEventListener, StatusEventListener *statusEventListener, + ProgressEventListener *progressEventListener); + private: struct ChangeArgs { ChangeArgs(const napi_ref callback, const std::string &sessionId, const std::vector &changeData); @@ -113,12 +131,20 @@ private: const std::string networkId_; const std::string status_; }; + struct ProgressArgs { + ProgressArgs(const napi_ref callback, const std::string &sessionId, int32_t progress); + napi_ref callback_; + const std::string sessionId_; + int32_t progress_ = 0; + }; EventListener *Find(const char *type); static void ProcessChange(napi_env env, std::list &args); static void ProcessStatus(napi_env env, std::list &args); + static void ProcessProgress(napi_env env, std::list &args); napi_env env_; - ChangeEventListener *changeEventListener_; - StatusEventListener *statusEventListener_; + ChangeEventListener *changeEventListener_ = nullptr; + StatusEventListener *statusEventListener_ = nullptr; + ProgressEventListener *progressEventListener_ = nullptr; }; class WatcherImpl : public ObjectWatcher { diff --git a/data_object/frameworks/jskitsimpl/include/adaptor/progress_notifier_impl.h b/data_object/frameworks/jskitsimpl/include/adaptor/progress_notifier_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..9867745c0cebf0189c76ffe85c5c24fd4580d8b4 --- /dev/null +++ b/data_object/frameworks/jskitsimpl/include/adaptor/progress_notifier_impl.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 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 PROGRESS_NOTIFIER_IMPL_H +#define PROGRESS_NOTIFIER_IMPL_H + +#include "js_watcher.h" +#include + +namespace OHOS::ObjectStore { +class ProgressNotifierImpl : public ProgressNotifier { +public: + static std::shared_ptr GetInstance(); + virtual ~ProgressNotifierImpl(); + + void AddWatcher(const std::string &sessionId, std::weak_ptr watcher); + void DelWatcher(const std::string &sessionId); + void OnChanged(const std::string &sessionId, int32_t progress) override; + +private: + std::mutex mutex_; + std::map> watchers_; +}; +} // namespace OHOS::ObjectStore + +#endif // PROGRESS_NOTIFIER_IMPL_H \ No newline at end of file diff --git a/data_object/frameworks/jskitsimpl/include/common/napi_queue.h b/data_object/frameworks/jskitsimpl/include/common/napi_queue.h index 2e5b0d9b580a49ac04a7b3de36c5f1b7697482b5..c177f269fc56bb5ae36a5a528403deb165458d55 100644 --- a/data_object/frameworks/jskitsimpl/include/common/napi_queue.h +++ b/data_object/frameworks/jskitsimpl/include/common/napi_queue.h @@ -14,9 +14,8 @@ */ #ifndef NAPI_QUEUE_H #define NAPI_QUEUE_H -#include + #include -#include #include "napi/native_node_api.h" #include "object_error.h" @@ -25,7 +24,7 @@ namespace OHOS::ObjectStore { using NapiCbInfoParser = std::function; using NapiAsyncExecute = std::function; using NapiAsyncComplete = std::function; - +static constexpr size_t ARGC_MAX = 6; struct ContextBase { virtual ~ContextBase(); void GetCbInfo( diff --git a/data_object/frameworks/jskitsimpl/include/common/uv_queue.h b/data_object/frameworks/jskitsimpl/include/common/uv_queue.h index 7cc84ff5d63e299bab80c8ec57f4e56488435a9c..d72fc4b7e587f94379ee5c0555840ccc923be28b 100644 --- a/data_object/frameworks/jskitsimpl/include/common/uv_queue.h +++ b/data_object/frameworks/jskitsimpl/include/common/uv_queue.h @@ -16,8 +16,8 @@ #define UV_QUEUE_H #include #include -#include #include +#include #include "napi/native_node_api.h" @@ -28,7 +28,7 @@ public: UvQueue(napi_env env); virtual ~UvQueue(); - void CallFunction(Process process, void *argv); + bool CallFunction(Process process, void *argv); private: struct UvEntry { diff --git a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp index 96aedc2d9d2ec6531995e997507a8ce432a8df78..6ac158bbca53a909688e75991ab22e69e9990870 100644 --- a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp +++ b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp @@ -16,7 +16,6 @@ #include "js_distributedobject.h" #include - #include "js_common.h" #include "js_util.h" #include "logger.h" @@ -309,7 +308,9 @@ napi_value JSDistributedObject::GetSaveResultCons( napi_env env, std::string &sessionId, double version, std::string deviceId) { const char *objectName = "SaveResult"; - napi_value napiSessionId, napiVersion, napiDeviceId; + napi_value napiSessionId; + napi_value napiVersion; + napi_value napiDeviceId; napi_value result; napi_status status = JSUtil::SetValue(env, sessionId, napiSessionId); diff --git a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp index 2ea6174d9c278c825c24c4741bf5cc2ed9f490b0..298a753061e4d22420ca19c5b3d1ff125ce6ade5 100644 --- a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp +++ b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp @@ -17,6 +17,7 @@ #include +#include "application_context.h" #include "accesstoken_kit.h" #include "js_ability.h" #include "js_common.h" @@ -27,9 +28,11 @@ #include "objectstore_errors.h" namespace OHOS::ObjectStore { -constexpr size_t TYPE_SIZE = 10; +constexpr size_t TYPE_SIZE = 20; +constexpr size_t PARAM_COUNT_MAX = 3; static ConcurrentMap> g_statusCallBacks; static ConcurrentMap> g_changeCallBacks; +static ConcurrentMap> g_progressCallBacks; bool JSDistributedObjectStore::AddCallback(napi_env env, ConcurrentMap> &callbacks, const std::string &objectId, napi_value callback) { @@ -137,6 +140,7 @@ napi_value JSDistributedObjectStore::NewDistributedObject( RestoreWatchers(env, objectWrapper, objectId); objectStore->NotifyCachedStatus(object->GetSessionId()); + objectStore->NotifyProgressStatus(object->GetSessionId()); NOT_MATCH_RETURN_NULL(status == napi_ok); return result; } @@ -214,6 +218,7 @@ napi_value JSDistributedObjectStore::JSDestroyObjectSync(napi_env env, napi_call objectWrapper->DeleteWatch(env, Constants::CHANGE); objectWrapper->DeleteWatch(env, Constants::STATUS); + objectWrapper->DeleteWatch(env, Constants::PROGRESS); objectInfo->DeleteObject(objectWrapper->GetObject()->GetSessionId()); objectWrapper->DestroyObject(); return nullptr; @@ -330,9 +335,9 @@ bool JSDistributedObjectStore::GetBundleNameWithContext(napi_env env, napi_value std::string JSDistributedObjectStore::GetBundleName(napi_env env) { static std::string bundleName; -// if (bundleName.empty()) { -// bundleName = AbilityRuntime::Context::GetApplicationContext()->GetBundleName(); -// } + if (bundleName.empty()) { + bundleName = AbilityRuntime::Context::GetApplicationContext()->GetBundleName(); + } return bundleName; } @@ -370,6 +375,21 @@ void JSDistributedObjectStore::RestoreWatchers(napi_env env, JSObjectWrapper *wr if (!watchResult) { LOG_INFO("no status %{public}s", objectId.c_str()); } + watchResult = + g_progressCallBacks.ComputeIfPresent(objectId, [&](const std::string &key, std::list &lists) { + for (auto callback : lists) { + status = napi_get_reference_value(env, callback, &callbackValue); + if (status != napi_ok) { + LOG_ERROR("error! %{public}d", status); + continue; + } + wrapper->AddWatch(env, Constants::PROGRESS, callbackValue); + } + return true; + }); + if (!watchResult) { + LOG_INFO("no status %{public}s", objectId.c_str()); + } } // function recordCallback(version: number, type: 'change', objectId: string, @@ -409,9 +429,11 @@ napi_value JSDistributedObjectStore::JSRecordCallback(napi_env env, napi_callbac bool addResult = true; if (!strcmp(Constants::CHANGE, type)) { - addResult = AddCallback(env, g_changeCallBacks, objectId, argv[3]); + addResult = AddCallback(env, g_changeCallBacks, objectId, argv[PARAM_COUNT_MAX]); } else if (!strcmp(Constants::STATUS, type)) { - addResult = AddCallback(env, g_statusCallBacks, objectId, argv[3]); + addResult = AddCallback(env, g_statusCallBacks, objectId, argv[PARAM_COUNT_MAX]); + } else if (!strcmp(Constants::PROGRESS, type)) { + addResult = AddCallback(env, g_progressCallBacks, objectId, argv[PARAM_COUNT_MAX]); } NAPI_ASSERT_ERRCODE_V9(env, addResult, version, innerError); napi_value result = nullptr; @@ -456,6 +478,8 @@ napi_value JSDistributedObjectStore::JSDeleteCallback(napi_env env, napi_callbac delResult = DelCallback(env, g_changeCallBacks, objectId); } else if (!strcmp(Constants::STATUS, type)) { delResult = DelCallback(env, g_statusCallBacks, objectId); + } else if (!strcmp(Constants::PROGRESS, type)) { + delResult = DelCallback(env, g_progressCallBacks, objectId); } } else { napi_valuetype callbackType = napi_undefined; @@ -463,9 +487,11 @@ napi_value JSDistributedObjectStore::JSDeleteCallback(napi_env env, napi_callbac NAPI_ASSERT_ERRCODE_V9(env, status == napi_ok && callbackType == napi_function, version, std::make_shared("callback", "function")); if (!strcmp(Constants::CHANGE, type)) { - delResult = DelCallback(env, g_changeCallBacks, objectId, argv[3]); + delResult = DelCallback(env, g_changeCallBacks, objectId, argv[PARAM_COUNT_MAX]); } else if (!strcmp(Constants::STATUS, type)) { - delResult = DelCallback(env, g_statusCallBacks, objectId, argv[3]); + delResult = DelCallback(env, g_statusCallBacks, objectId, argv[PARAM_COUNT_MAX]); + } else if (!strcmp(Constants::PROGRESS, type)) { + delResult = DelCallback(env, g_progressCallBacks, objectId, argv[PARAM_COUNT_MAX]); } } NAPI_ASSERT_ERRCODE_V9(env, delResult, version, innerError); @@ -488,11 +514,11 @@ napi_value JSDistributedObjectStore::JSEquenceNum(napi_env env, napi_callback_in // don't create distributed data object while this application is sandbox bool JSDistributedObjectStore::IsSandBox() { -// int32_t dlpFlag = Security::AccessToken::AccessTokenKit::GetHapDlpFlag( -// AbilityRuntime::Context::GetApplicationContext()->GetApplicationInfo()->accessTokenId); -// if (dlpFlag != 0) { -// return true; -// } + int32_t dlpFlag = Security::AccessToken::AccessTokenKit::GetHapDlpFlag( + AbilityRuntime::Context::GetApplicationContext()->GetApplicationInfo()->accessTokenId); + if (dlpFlag != 0) { + return true; + } return false; } } // namespace OHOS::ObjectStore 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 cfa505f8231bc4b64fabfd551abf51852a92bd12..b6331a36738a5f346992111397627125cd0ff209 100644 --- a/data_object/frameworks/jskitsimpl/src/adaptor/js_object_wrapper.cpp +++ b/data_object/frameworks/jskitsimpl/src/adaptor/js_object_wrapper.cpp @@ -12,10 +12,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #include "js_object_wrapper.h" -#include #include "logger.h" namespace OHOS::ObjectStore { JSObjectWrapper::JSObjectWrapper(DistributedObjectStore *objectStore, DistributedObject *object) @@ -46,7 +46,8 @@ bool JSObjectWrapper::AddWatch(napi_env env, const char *type, napi_value handle std::weak_ptr watcher = watcher_; auto changeEventListener = new ChangeEventListener(watcher, objectStore_, object_); auto statusEventListener = new StatusEventListener(watcher, object_->GetSessionId()); - watcher_->SetListener(changeEventListener, statusEventListener); + auto progressEventListener = new ProgressEventListener(watcher, object_->GetSessionId()); + watcher_->SetListener(changeEventListener, statusEventListener, progressEventListener); } return watcher_->On(type, handler); } diff --git a/data_object/frameworks/jskitsimpl/src/adaptor/js_watcher.cpp b/data_object/frameworks/jskitsimpl/src/adaptor/js_watcher.cpp index ee612ca077d66574ac030dcc9d56c2a2016ed5ee..d738b850028918db19cba66fd4fce2ec266724a4 100644 --- a/data_object/frameworks/jskitsimpl/src/adaptor/js_watcher.cpp +++ b/data_object/frameworks/jskitsimpl/src/adaptor/js_watcher.cpp @@ -13,20 +13,19 @@ * limitations under the License. */ -#include "js_watcher.h" - -#include - +#include #include "anonymous.h" #include "js_common.h" #include "js_util.h" #include "logger.h" #include "notifier_impl.h" #include "objectstore_errors.h" +#include "progress_notifier_impl.h" namespace OHOS::ObjectStore { JSWatcher::JSWatcher(const napi_env env, DistributedObjectStore *objectStore, DistributedObject *object) - : UvQueue(env), env_(env), changeEventListener_(nullptr), statusEventListener_(nullptr) + : UvQueue(env), env_(env), changeEventListener_(nullptr), statusEventListener_(nullptr), + progressEventListener_(nullptr) { } @@ -34,8 +33,10 @@ JSWatcher::~JSWatcher() { delete changeEventListener_; delete statusEventListener_; + delete progressEventListener_; changeEventListener_ = nullptr; statusEventListener_ = nullptr; + progressEventListener_ = nullptr; } bool JSWatcher::On(const char *type, napi_value handler) @@ -78,9 +79,11 @@ void JSWatcher::ProcessChange(napi_env env, std::list &args) NOT_MATCH_GOTO_ERROR(status == napi_ok); JSUtil::SetValue(env, changeArgs->changeData_, param[1]); NOT_MATCH_GOTO_ERROR(status == napi_ok); - LOG_INFO("start %{public}s, %{public}zu", changeArgs->sessionId_.c_str(), changeArgs->changeData_.size()); + LOG_INFO("start %{public}s, %{public}zu", Anonymous::Change(changeArgs->sessionId_).c_str(), + changeArgs->changeData_.size()); status = napi_call_function(env, global, callback, ARGV_SIZE, param, &result); - LOG_INFO("end %{public}s, %{public}zu", changeArgs->sessionId_.c_str(), changeArgs->changeData_.size()); + LOG_INFO("end %{public}s, %{public}zu", Anonymous::Change(changeArgs->sessionId_).c_str(), + changeArgs->changeData_.size()); NOT_MATCH_GOTO_ERROR(status == napi_ok); } ERROR: @@ -96,7 +99,7 @@ void JSWatcher::Emit(const char *type, const std::string &sessionId, const std:: LOG_ERROR("empty change"); return; } - LOG_INFO("start %{public}s, %{public}s", sessionId.c_str(), changeData.at(0).c_str()); + LOG_INFO("start %{public}s, %{public}s", Anonymous::Change(sessionId).c_str(), changeData.at(0).c_str()); EventListener *listener = Find(type); if (listener == nullptr) { LOG_ERROR("error type %{public}s", type); @@ -109,7 +112,10 @@ void JSWatcher::Emit(const char *type, const std::string &sessionId, const std:: LOG_ERROR("JSWatcher::Emit no memory for changeArgs malloc!"); return; } - CallFunction(ProcessChange, changeArgs); + if (!CallFunction(ProcessChange, changeArgs)) { + delete changeArgs; + changeArgs = nullptr; + } } } @@ -121,6 +127,9 @@ EventListener *JSWatcher::Find(const char *type) if (!strcmp(Constants::STATUS, type)) { return statusEventListener_; } + if (!strcmp(Constants::PROGRESS, type)) { + return progressEventListener_; + } return nullptr; } @@ -143,10 +152,10 @@ void JSWatcher::ProcessStatus(napi_env env, std::list &args) NOT_MATCH_GOTO_ERROR(status == napi_ok); status = JSUtil::SetValue(env, statusArgs->status_, param[2]); NOT_MATCH_GOTO_ERROR(status == napi_ok); - LOG_INFO("start %{public}s, %{public}s, %{public}s", statusArgs->sessionId_.c_str(), + LOG_INFO("start %{public}s, %{public}s, %{public}s", Anonymous::Change(statusArgs->sessionId_).c_str(), Anonymous::Change(statusArgs->networkId_).c_str(), statusArgs->status_.c_str()); status = napi_call_function(env, global, callback, ARGV_SIZE, param, &result); - LOG_INFO("end %{public}s, %{public}s, %{public}s", statusArgs->sessionId_.c_str(), + LOG_INFO("end %{public}s, %{public}s, %{public}s", Anonymous::Change(statusArgs->sessionId_).c_str(), Anonymous::Change(statusArgs->networkId_).c_str(), statusArgs->status_.c_str()); NOT_MATCH_GOTO_ERROR(status == napi_ok); } @@ -163,10 +172,12 @@ void JSWatcher::Emit( const char *type, const std::string &sessionId, const std::string &networkId, const std::string &status) { if (sessionId.empty() || networkId.empty()) { - LOG_ERROR("empty %{public}s %{public}s", sessionId.c_str(), Anonymous::Change(networkId).c_str()); + LOG_ERROR("empty %{public}s %{public}s", Anonymous::Change(sessionId).c_str(), + Anonymous::Change(networkId).c_str()); return; } - LOG_INFO("status change %{public}s %{public}s", sessionId.c_str(), Anonymous::Change(networkId).c_str()); + LOG_INFO("status change %{public}s %{public}s", Anonymous::Change(sessionId).c_str(), + Anonymous::Change(networkId).c_str()); EventListener *listener = Find(type); if (listener == nullptr) { LOG_ERROR("error type %{public}s", type); @@ -179,23 +190,88 @@ void JSWatcher::Emit( LOG_ERROR("JSWatcher::Emit no memory for StatusArgs malloc!"); return; } - CallFunction(ProcessStatus, changeArgs); + if (!CallFunction(ProcessStatus, changeArgs)) { + delete changeArgs; + changeArgs = nullptr; + } + } + return; +} + +void JSWatcher::ProcessProgress(napi_env env, std::list &args) +{ + constexpr static int8_t ARGV_SIZE = 2; + napi_value callback = nullptr; + napi_value global = nullptr; + napi_value param[ARGV_SIZE]; + napi_value result; + napi_status status = napi_get_global(env, &global); + NOT_MATCH_GOTO_ERROR(status == napi_ok); + for (auto item : args) { + ProgressArgs *progressArgs = static_cast(item); + status = napi_get_reference_value(env, progressArgs->callback_, &callback); + NOT_MATCH_GOTO_ERROR(status == napi_ok); + status = JSUtil::SetValue(env, progressArgs->sessionId_, param[0]); + NOT_MATCH_GOTO_ERROR(status == napi_ok); + status = JSUtil::SetValue(env, static_cast(progressArgs->progress_), param[1]); + NOT_MATCH_GOTO_ERROR(status == napi_ok); + LOG_INFO("start %{public}s, %{public}d", Anonymous::Change(progressArgs->sessionId_).c_str(), + progressArgs->progress_); + status = napi_call_function(env, global, callback, ARGV_SIZE, param, &result); + LOG_INFO("end %{public}s, %{public}d", Anonymous::Change(progressArgs->sessionId_).c_str(), + progressArgs->progress_); + NOT_MATCH_GOTO_ERROR(status == napi_ok); + } +ERROR: + LOG_DEBUG("do clear"); + for (auto item : args) { + ProgressArgs *progressArgs = static_cast(item); + delete progressArgs; + } + args.clear(); +} + +void JSWatcher::Emit(const char *type, const std::string &sessionId, int32_t progress) +{ + if (sessionId.empty()) { + LOG_ERROR("empty sessionId %{public}s", Anonymous::Change(sessionId).c_str()); + return; + } + LOG_INFO("progress change %{public}s %{public}d", Anonymous::Change(sessionId).c_str(), progress); + EventListener *listener = Find(type); + if (listener == nullptr) { + LOG_ERROR("error type %{public}s", type); + return; + } + + for (EventHandler *handler = listener->handlers_; handler != nullptr; handler = handler->next) { + ProgressArgs *progressArgs = new (std::nothrow) ProgressArgs(handler->callbackRef, sessionId, progress); + if (progressArgs == nullptr) { + LOG_ERROR("JSWatcher::Emit no memory for ProgressArgs malloc!"); + return; + } + if (!CallFunction(ProcessProgress, progressArgs)) { + delete progressArgs; + progressArgs = nullptr; + } } return; } bool JSWatcher::IsEmpty() { - if (changeEventListener_->IsEmpty() && statusEventListener_->IsEmpty()) { + if (changeEventListener_->IsEmpty() && statusEventListener_->IsEmpty() && progressEventListener_->IsEmpty()) { return true; } return false; } -void JSWatcher::SetListener(ChangeEventListener *changeEventListener, StatusEventListener *statusEventListener) +void JSWatcher::SetListener(ChangeEventListener *changeEventListener, StatusEventListener *statusEventListener, + ProgressEventListener *progressEventListener) { changeEventListener_ = changeEventListener; statusEventListener_ = statusEventListener; + progressEventListener_ = progressEventListener; } EventHandler *EventListener::Find(napi_env env, napi_value handler) @@ -301,9 +377,9 @@ bool ChangeEventListener::Add(napi_env env, napi_value handler) std::shared_ptr watcher = std::make_shared(watcher_); uint32_t ret = objectStore_->Watch(object_, watcher); if (ret != SUCCESS) { - LOG_ERROR("Watch %{public}s error", object_->GetSessionId().c_str()); + LOG_ERROR("Watch %{public}s error", Anonymous::Change(object_->GetSessionId()).c_str()); } else { - LOG_INFO("Watch %{public}s success", object_->GetSessionId().c_str()); + LOG_INFO("Watch %{public}s success", Anonymous::Change(object_->GetSessionId()).c_str()); isWatched_ = true; } } @@ -316,9 +392,9 @@ bool ChangeEventListener::Del(napi_env env, napi_value handler) if (isEmpty && isWatched_ && object_ != nullptr) { uint32_t ret = objectStore_->UnWatch(object_); if (ret != SUCCESS) { - LOG_ERROR("UnWatch %{public}s error", object_->GetSessionId().c_str()); + LOG_ERROR("UnWatch %{public}s error", Anonymous::Change(object_->GetSessionId()).c_str()); } else { - LOG_INFO("UnWatch %{public}s success", object_->GetSessionId().c_str()); + LOG_INFO("UnWatch %{public}s success", Anonymous::Change(object_->GetSessionId()).c_str()); isWatched_ = false; } } @@ -331,9 +407,9 @@ void ChangeEventListener::Clear(napi_env env) if (isWatched_ && object_ != nullptr) { uint32_t ret = objectStore_->UnWatch(object_); if (ret != SUCCESS) { - LOG_ERROR("UnWatch %{public}s error", object_->GetSessionId().c_str()); + LOG_ERROR("UnWatch %{public}s error", Anonymous::Change(object_->GetSessionId()).c_str()); } else { - LOG_INFO("UnWatch %{public}s success", object_->GetSessionId().c_str()); + LOG_INFO("UnWatch %{public}s success", Anonymous::Change(object_->GetSessionId()).c_str()); isWatched_ = false; } } @@ -347,7 +423,7 @@ ChangeEventListener::ChangeEventListener( bool StatusEventListener::Add(napi_env env, napi_value handler) { - LOG_INFO("Add status watch %{public}s", sessionId_.c_str()); + LOG_INFO("Add status watch %{public}s", Anonymous::Change(sessionId_).c_str()); NotifierImpl::GetInstance()->AddWatcher(sessionId_, watcher_); return EventListener::Add(env, handler); } @@ -355,7 +431,7 @@ bool StatusEventListener::Add(napi_env env, napi_value handler) bool StatusEventListener::Del(napi_env env, napi_value handler) { if (EventListener::Del(env, handler)) { - LOG_INFO("Del status watch %{public}s", sessionId_.c_str()); + LOG_INFO("Del status watch %{public}s", Anonymous::Change(sessionId_).c_str()); NotifierImpl::GetInstance()->DelWatcher(sessionId_); return true; } @@ -373,6 +449,34 @@ StatusEventListener::StatusEventListener(std::weak_ptr watcher, const { } +bool ProgressEventListener::Add(napi_env env, napi_value handler) +{ + LOG_INFO("Add progress watch %{public}s", Anonymous::Change(sessionId_).c_str()); + ProgressNotifierImpl::GetInstance()->AddWatcher(sessionId_, watcher_); + return EventListener::Add(env, handler); +} + +bool ProgressEventListener::Del(napi_env env, napi_value handler) +{ + if (EventListener::Del(env, handler)) { + LOG_INFO("Del progress watch %{public}s", Anonymous::Change(sessionId_).c_str()); + ProgressNotifierImpl::GetInstance()->DelWatcher(sessionId_); + return true; + } + return false; +} + +void ProgressEventListener::Clear(napi_env env) +{ + ProgressNotifierImpl::GetInstance()->DelWatcher(sessionId_); + EventListener::Clear(env); +} + +ProgressEventListener::ProgressEventListener(std::weak_ptr watcher, const std::string &sessionId) + : watcher_(watcher), sessionId_(sessionId) +{ +} + JSWatcher::ChangeArgs::ChangeArgs( const napi_ref callback, const std::string &sessionId, const std::vector &changeData) : callback_(callback), sessionId_(sessionId), changeData_(changeData) @@ -384,4 +488,9 @@ JSWatcher::StatusArgs::StatusArgs( : callback_(callback), sessionId_(sessionId), networkId_(networkId), status_(status) { } + +JSWatcher::ProgressArgs::ProgressArgs(const napi_ref callback, const std::string &sessionId, int32_t progress) + : callback_(callback), sessionId_(sessionId), progress_(progress) +{ +} } // namespace OHOS::ObjectStore diff --git a/data_object/frameworks/jskitsimpl/src/adaptor/progress_notifier_impl.cpp b/data_object/frameworks/jskitsimpl/src/adaptor/progress_notifier_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a1c7286d7f0be142d297aa30867f241a3f2aa736 --- /dev/null +++ b/data_object/frameworks/jskitsimpl/src/adaptor/progress_notifier_impl.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2025 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 "progress_notifier_impl.h" + +#include "anonymous.h" +#include "logger.h" +#include "objectstore_errors.h" + +namespace OHOS::ObjectStore { + +std::shared_ptr ProgressNotifierImpl::GetInstance() +{ + static std::shared_ptr instance; + static std::mutex instanceLock; + std::lock_guard lockGuard(instanceLock); + if (instance == nullptr) { + instance = std::make_shared(); + DistributedObjectStore *storeInstance = DistributedObjectStore::GetInstance(); + if (storeInstance == nullptr) { + LOG_ERROR("Get store instance nullptr"); + return instance; + } + auto ret = storeInstance->SetProgressNotifier(instance); + if (ret != SUCCESS) { + LOG_ERROR("SetProgressNotifier %{public}d error", ret); + } else { + LOG_INFO("SetProgressNotifier success"); + } + } + return instance; +} + +void ProgressNotifierImpl::AddWatcher(const std::string &sessionId, std::weak_ptr watcher) +{ + std::lock_guard lock(mutex_); + watchers_.insert_or_assign(sessionId, watcher); +} + +void ProgressNotifierImpl::DelWatcher(const std::string &sessionId) +{ + std::lock_guard lock(mutex_); + watchers_.erase(sessionId); +} + +void ProgressNotifierImpl::OnChanged(const std::string &sessionId, int32_t progress) +{ + std::lock_guard lock(mutex_); + if (watchers_.count(sessionId) != 0) { + LOG_INFO("start emit %{public}s %{public}d", Anonymous::Change(sessionId).c_str(), progress); + std::shared_ptr lockedWatcher = watchers_.at(sessionId).lock(); + if (lockedWatcher) { + lockedWatcher->Emit("progressChanged", sessionId, progress); + LOG_INFO("end emit %{public}s %{public}d", Anonymous::Change(sessionId).c_str(), progress); + } else { + LOG_ERROR("watcher expired"); + } + } +} + +ProgressNotifierImpl::~ProgressNotifierImpl() +{ +} + +} // namespace OHOS::ObjectStore diff --git a/data_object/frameworks/jskitsimpl/src/common/js_util.cpp b/data_object/frameworks/jskitsimpl/src/common/js_util.cpp index f3360b466871a6af1a22eabe59b0398a8d27676a..51d043698299b27108b4a6020e5769265d052c4a 100644 --- a/data_object/frameworks/jskitsimpl/src/common/js_util.cpp +++ b/data_object/frameworks/jskitsimpl/src/common/js_util.cpp @@ -19,7 +19,7 @@ #include "logger.h" namespace OHOS::ObjectStore { -constexpr int32_t STR_MAX_LENGTH = 4096; +constexpr int32_t STR_MAX_LENGTH = 500 * 1024; constexpr size_t STR_TAIL_LENGTH = 1; /* napi_value <-> bool */ @@ -75,7 +75,8 @@ napi_status JSUtil::GetValue(napi_env env, napi_value in, std::string &out) { size_t maxLen = STR_MAX_LENGTH; napi_status status = napi_get_value_string_utf8(env, in, NULL, 0, &maxLen); - if (status != napi_ok || maxLen <= 0) { + if (status != napi_ok || maxLen <= 0 || maxLen > STR_MAX_LENGTH) { + LOG_ERROR("napi_get_value_string_utf8 failed! status=%{public}d, maxLen=%{public}zu", status, maxLen); return napi_generic_failure; } char *buf = new (std::nothrow) char[maxLen + STR_TAIL_LENGTH]; diff --git a/data_object/frameworks/jskitsimpl/src/common/napi_queue.cpp b/data_object/frameworks/jskitsimpl/src/common/napi_queue.cpp index ad34819142c74f24d65cdcd5b16cc847c9392deb..50722f4228b4a1483ac6bc86d1291b4bbead5d7a 100644 --- a/data_object/frameworks/jskitsimpl/src/common/napi_queue.cpp +++ b/data_object/frameworks/jskitsimpl/src/common/napi_queue.cpp @@ -19,8 +19,6 @@ #include "logger.h" namespace OHOS::ObjectStore { -static constexpr size_t ARGC_MAX = 6; - ContextBase::~ContextBase() { LOG_DEBUG("no memory leak after callback or promise[resolved/rejected]"); @@ -72,7 +70,7 @@ napi_value NapiQueue::AsyncWork(napi_env env, std::shared_ptr conte { AsyncContext *aCtx = new (std::nothrow) AsyncContext; if (aCtx == nullptr) { - LOG_ERROR("create aysnc context failed"); + LOG_ERROR("create async context failed"); return nullptr; } aCtx->ctxt = std::move(contextBase); diff --git a/data_object/frameworks/jskitsimpl/src/common/object_error.cpp b/data_object/frameworks/jskitsimpl/src/common/object_error.cpp index 3440ca83b1d690f044df693153b79b005696d4b7..08a0186533e081df1498e22c0546ce94c0951794 100644 --- a/data_object/frameworks/jskitsimpl/src/common/object_error.cpp +++ b/data_object/frameworks/jskitsimpl/src/common/object_error.cpp @@ -55,7 +55,8 @@ int DatabaseError::GetCode() std::string DatabaseError::GetMessage() { - return "Failed to create the in-memory database."; + return "Failed to create the in-memory database. The possible reason is that other distributed data object" + " has already set the same sessionId."; } int PermissionError::GetCode() diff --git a/data_object/frameworks/jskitsimpl/src/common/uv_queue.cpp b/data_object/frameworks/jskitsimpl/src/common/uv_queue.cpp index bad8316238e84aa81ce964f0bfcb9177b484f980..82a617f7a29d9a1c4e2408d3bdf8dbc5d49ea791 100644 --- a/data_object/frameworks/jskitsimpl/src/common/uv_queue.cpp +++ b/data_object/frameworks/jskitsimpl/src/common/uv_queue.cpp @@ -12,9 +12,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "uv_queue.h" - #include + +#include "uv_queue.h" #include "logger.h" namespace OHOS::ObjectStore { @@ -46,38 +46,41 @@ void UvQueue::ExecUvWork(UvEntry *entry) entry = nullptr; } -void UvQueue::CallFunction(Process process, void *argv) +bool UvQueue::CallFunction(Process process, void *argv) { if (process == nullptr || argv == nullptr) { LOG_ERROR("nullptr"); - return; + return false; } - auto *uvEntry = new (std::nothrow)UvEntry { weak_from_this() }; + auto *uvEntry = new (std::nothrow) UvEntry{ weak_from_this() }; if (uvEntry == nullptr) { LOG_ERROR("no memory for UvEntry"); - return; + return false; } + auto rollbackAddition = [this, process, argv]() { + std::unique_lock lock(mutex_); + auto it = args_.find(process); + if (it != args_.end() && !it->second.empty()) { + it->second.pop_back(); + if (it->second.empty()) { + args_.erase(it); + } + } + }; { std::unique_lock cacheLock(mutex_); - if (args_.count(process) != 0) { - std::list newData = args_.at(process); - newData.push_back(argv); - args_.insert_or_assign(process, newData); - } else { - std::list data; - data.push_back(argv); - args_.insert_or_assign(process, data); - } + auto &processList = args_[process]; + processList.push_back(argv); } - auto task = [uvEntry]() { - UvQueue::ExecUvWork(uvEntry); - }; - if (napi_send_event(env_, task, napi_eprio_high) != 0) { - if (uvEntry != nullptr) { - delete uvEntry; - uvEntry = nullptr; - } + auto task = [uvEntry]() { UvQueue::ExecUvWork(uvEntry); }; + auto ret = napi_send_event(env_, task, napi_eprio_high); + if (ret != 0) { + LOG_ERROR("napi_send_event failed, ret: %{public}d.", ret); + rollbackAddition(); + delete uvEntry; + return false; } + return true; } } // namespace OHOS::ObjectStore diff --git a/data_object/interfaces/innerkits/BUILD.gn b/data_object/interfaces/innerkits/BUILD.gn index 8dcded7cffe32dbcbc2cae84b2dab2545e629315..b791b2751eeb66f2b632f7b7036175de824aff74 100644 --- a/data_object/interfaces/innerkits/BUILD.gn +++ b/data_object/interfaces/innerkits/BUILD.gn @@ -15,10 +15,7 @@ import("//foundation/distributeddatamgr/data_object/data_object.gni") config("objectstore_config") { visibility = [ ":*" ] - cflags = [ - "-DHILOG_ENABLE", - "-Oz", - ] + cflags = [ "-DHILOG_ENABLE" ] include_dirs = [ "../../frameworks/innerkitsimpl/include/adaptor", diff --git a/data_object/interfaces/innerkits/distributed_object.h b/data_object/interfaces/innerkits/distributed_object.h index a17b0597f6b9898c0e49c4592c669eba0828c743..edc4377811c8beefa2a514e15a045626f5215736 100644 --- a/data_object/interfaces/innerkits/distributed_object.h +++ b/data_object/interfaces/innerkits/distributed_object.h @@ -15,8 +15,7 @@ #ifndef DISTRIBUTED_OBJECT_H #define DISTRIBUTED_OBJECT_H -#include -#include + #include #include #include "object_types.h" diff --git a/data_object/interfaces/innerkits/distributed_objectstore.h b/data_object/interfaces/innerkits/distributed_objectstore.h index 305a4772af20b9cb61d880a43812a58facce1a3a..0b21c1960492be30116ae7b6879897df850b773a 100644 --- a/data_object/interfaces/innerkits/distributed_objectstore.h +++ b/data_object/interfaces/innerkits/distributed_objectstore.h @@ -16,6 +16,7 @@ #ifndef DISTRIBUTED_OBJECTSTORE_H #define DISTRIBUTED_OBJECTSTORE_H #include +#include #include "distributed_object.h" @@ -25,6 +26,10 @@ public: virtual void OnChanged( const std::string &sessionId, const std::string &networkId, const std::string &onlineStatus) = 0; }; +class ProgressNotifier { +public: + virtual void OnChanged(const std::string &sessionId, int32_t progress) = 0; +}; class DistributedObjectStore { public: virtual ~DistributedObjectStore(){}; @@ -112,6 +117,23 @@ public: * */ virtual void NotifyCachedStatus(const std::string &sessionId) = 0; + + /** + * @brief Set listening for progress. + * + * @param notifier Indicates callback function for progress. + * + * @return Returns 0 for success, others for failure. + */ + virtual uint32_t SetProgressNotifier(std::shared_ptr notifier) = 0; + + /** + * @brief Notify the status of the progress from the cached callback function according to the sessionId. + * + * @param sessionId Indicates the sessionId. + * + */ + virtual void NotifyProgressStatus(const std::string &sessionId) = 0; }; } // namespace OHOS::ObjectStore diff --git a/data_object/interfaces/innerkits/object_types.h b/data_object/interfaces/innerkits/object_types.h index 9328674391cd123e2db8058661079ab4df761587..093fb636e4ff29bf87832774ff2b0de8096c007e 100644 --- a/data_object/interfaces/innerkits/object_types.h +++ b/data_object/interfaces/innerkits/object_types.h @@ -16,7 +16,6 @@ #ifndef OHOS_OBJECT_ASSET_VALUE_H #define OHOS_OBJECT_ASSET_VALUE_H -#include #include "common_types.h" namespace OHOS { diff --git a/data_object/interfaces/jskits/BUILD.gn b/data_object/interfaces/jskits/BUILD.gn index bbca12dd3aa544eabbde32049f63cbb01f7411fa..374b6e543fc8edb44a98294c670618c3f04634c3 100644 --- a/data_object/interfaces/jskits/BUILD.gn +++ b/data_object/interfaces/jskits/BUILD.gn @@ -32,10 +32,7 @@ es2abc_gen_abc("gen_distributed_data_object_abc") { config("objectstore_config") { visibility = [ ":*" ] - cflags = [ - "-DHILOG_ENABLE", - "-Oz", - ] + cflags = [ "-DHILOG_ENABLE" ] include_dirs = [ "../../frameworks/jskitsimpl/include/adaptor", @@ -96,6 +93,7 @@ ohos_shared_library("distributeddataobject") { "../../frameworks/jskitsimpl/src/common/napi_queue.cpp", "../../frameworks/jskitsimpl/src/common/object_error.cpp", "../../frameworks/jskitsimpl/src/common/uv_queue.cpp", + "../../frameworks/jskitsimpl/src/adaptor/progress_notifier_impl.cpp", ] configs = [ ":objectstore_config" ] @@ -114,6 +112,7 @@ ohos_shared_library("distributeddataobject") { "bounds_checking_function:libsec_shared", "common_event_service:cesfwk_innerkits", "hilog:libhilog", + "ipc:ipc_single", "kv_store:distributeddata_inner", "kv_store:distributeddb", "libuv:uv", diff --git a/data_object/interfaces/jskits/distributed_data_object.js b/data_object/interfaces/jskits/distributed_data_object.js index e707ebb25fc8b51013991028c569302d1b5d27bb..a021eaaf3bbcfffa64fcc5242ecdaa5cf38b2955 100644 --- a/data_object/interfaces/jskits/distributed_data_object.js +++ b/data_object/interfaces/jskits/distributed_data_object.js @@ -14,6 +14,7 @@ */ const distributedObject = requireInternal('data.distributedDataObject'); +const fs = requireInternal('file.fs'); const SESSION_ID = '__sessionId'; const VERSION = '__version'; const COMPLEX_TYPE = '[COMPLEX]'; @@ -27,6 +28,12 @@ const SDK_VERSION_8 = 8; const SDK_VERSION_9 = 9; const SESSION_ID_REGEX = /^\w+$/; const SESSION_ID_MAX_LENGTH = 128; +const ASSETS_MAX_NUMBER = 50; +const HEAD_SIZE = 3; +const END_SIZE = 3; +const MIN_SIZE = HEAD_SIZE + END_SIZE + 3; +const REPLACE_CHAIN = '***'; +const DEFAULT_ANONYMOUS = '******'; class Distributed { constructor(obj) { @@ -305,15 +312,28 @@ function leaveSession(version, obj) { delete obj[SESSION_ID]; } +function toBeAnonymous(name) { + if (name == null || name === undefined || name === '') { + return ''; + } + if (name.length <= HEAD_SIZE) { + return DEFAULT_ANONYMOUS; + } + if (name.length < MIN_SIZE) { + return name.substring(0, HEAD_SIZE) + REPLACE_CHAIN; + } + return name.substring(0, HEAD_SIZE) + REPLACE_CHAIN + name.substring(name.length - END_SIZE); +} + function onWatch(version, type, obj, callback) { - console.info('start on ' + obj[SESSION_ID]); + console.info('start on ' + toBeAnonymous(obj[SESSION_ID])); if (obj[SESSION_ID] != null && obj[SESSION_ID] !== undefined && obj[SESSION_ID].length > 0) { distributedObject.on(version, type, obj, callback); } } function offWatch(version, type, obj, callback = undefined) { - console.info('start off ' + obj[SESSION_ID] + ' ' + callback); + console.info('start off ' + toBeAnonymous(obj[SESSION_ID]) + ' ' + callback); if (obj[SESSION_ID] != null && obj[SESSION_ID] !== undefined && obj[SESSION_ID].length > 0) { if (callback !== undefined || callback != null) { distributedObject.off(version, type, obj, callback); @@ -343,6 +363,55 @@ function newDistributedV9(context, obj) { return new DistributedV9(obj, context); } +function appendPropertyToObj(result, obj) { + result.__proxy = Object.assign(result.__proxy, obj); + Object.keys(obj).forEach(key => { + Object.defineProperty(result, key, { + enumerable: true, + configurable: true, + get: function () { + return result.__proxy[key]; + }, + set: function (newValue) { + result.__proxy[key] = newValue; + } + }); + }); +} + +function getDefaultAsset(uri, distributedDir) { + if (uri == null) { + throw { + code: 15400002, + message: 'The asset uri to be set is null.' + }; + } + const fileName = uri.substring(uri.lastIndexOf('/') + 1); + const filePath = distributedDir + '/' + fileName; + let stat; + try { + stat = fs.statSync(filePath); + return { + name: fileName, + uri: uri, + path: filePath, + createTime: stat.ctime.toString(), + modifyTime: stat.mtime.toString(), + size: stat.size.toString() + }; + } catch (error) { + console.error(error); + return { + name: '', + uri: '', + path: '', + createTime: 0, + modifyTime: 0, + size: 0 + }; + } +} + class DistributedV9 { constructor(obj, context) { @@ -430,6 +499,70 @@ class DistributedV9 { return this.__proxy.bindAssetStore(assetkey, bindInfo, callback); } + setAsset(assetKey, uri) { + if (this.__proxy[SESSION_ID] != null && this.__proxy[SESSION_ID] !== '') { + throw { + code: 15400003, + message: 'SessionId has been set, and asset cannot be set.' + }; + } + if (!assetKey || !uri) { + throw { + code: 15400002, + message: 'The property or uri of the asset is invalid.' + }; + } + + let assetObj = {}; + const distributedDir = this.__context.distributedFilesDir; + const asset = getDefaultAsset(uri, distributedDir); + assetObj[assetKey] = [asset]; + assetObj[assetKey + '0'] = asset; + appendPropertyToObj(this, assetObj); + return Promise.resolve(); + } + + setAssets(assetsKey, uris) { + if (this.__proxy[SESSION_ID] != null && this.__proxy[SESSION_ID] !== '') { + throw { + code: 15400003, + message: 'SessionId has been set, and assets cannot be set.' + }; + } + if (!assetsKey) { + throw { + code: 15400002, + message: 'The property of the assets is invalid.' + }; + } + if (!Array.isArray(uris) || uris.length <= 0 || uris.length > ASSETS_MAX_NUMBER) { + throw { + code: 15400002, + message: 'The uri array of the set assets is not an array or the length is invalid.' + }; + } + for (let index = 0; index < uris.length; index++) { + if (!uris[index]) { + throw { + code: 15400002, + message: 'Uri in assets array is invalid.' + }; + } + } + + let assetObj = {}; + let assets = []; + const distributedDir = this.__context.distributedFilesDir; + for (let index = 0; index < uris.length; index++) { + const asset = getDefaultAsset(uris[index], distributedDir); + assets.push(asset); + assetObj[assetsKey + index] = asset; + } + assetObj[assetsKey] = assets; + appendPropertyToObj(this, assetObj); + return Promise.resolve(); + } + __context; __proxy; __objectId; diff --git a/data_share/CMakeLists.txt b/data_share/CMakeLists.txt index 7f729357b71941205778a3d7576a5fef2b2c6b86..5e7abaf57d0d2e53a68ad569b23f3fb9fdfff7a3 100644 --- a/data_share/CMakeLists.txt +++ b/data_share/CMakeLists.txt @@ -18,6 +18,7 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/common/src da aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/consumer/controller/provider/src data_share_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/consumer/controller/service/src data_share_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/consumer/src data_share_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/dfx/src data_share_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/permission/src data_share_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/provider/src data_share_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/proxy/src data_share_src) @@ -30,6 +31,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/consumer/contr include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/consumer/controller/provider/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/consumer/controller/service/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/consumer/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/dfx/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/permission/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/provider/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/proxy/include) diff --git a/data_share/CODEOWNERS b/data_share/CODEOWNERS index f59cc39e886e93147a9dbb62933fd7e497482ead..2d35b09cf90c92714ce7e4285dbd79b7c7baccc9 100644 --- a/data_share/CODEOWNERS +++ b/data_share/CODEOWNERS @@ -13,5 +13,5 @@ # any change to # frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h -# needs to be reviewed by @leonchan5 -frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h @leonchan5 \ No newline at end of file +# needs to be reviewed by @leonchan5 liubao6@huawei.com +frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h @leonchan5 liubao6@huawei.com \ No newline at end of file diff --git a/data_share/README_zh.md b/data_share/README_zh.md index 6bc5b6ea5aec5c03ab02a1ce25f5d605a2398f55..9bc85fa1442f2b1e3bcf0dc657c52bc1fbb3d594 100644 --- a/data_share/README_zh.md +++ b/data_share/README_zh.md @@ -48,8 +48,8 @@ │   │   └── napi # NAPI代码存放目录 │   │   ├── common # 公用NAPI代码存放目录 │   │   ├── dataShare # 客户端NAPI代码存放目录 -│   │   ├── datashare_ext_ability # DataShareExtentionAbility模块JS代码存放目录 -│   │   └── datashare_ext_ability_context # DataShareExtentionAbilityContext模块JS代码存放目录 +│   │   ├── datashare_ext_ability # DataShareextensionAbility模块JS代码存放目录 +│   │   └── datashare_ext_ability_context # DataShareextensionAbilityContext模块JS代码存放目录 │   └── native │   ├── common │   ├── consumer diff --git a/data_share/bundle.json b/data_share/bundle.json index cdf403463a375b087f14510d16a07c5296800204..04a2115157633af312b45c7b53c9c8a477c5eb31 100644 --- a/data_share/bundle.json +++ b/data_share/bundle.json @@ -64,6 +64,7 @@ "libuv", "napi", "relational_store", + "runtime_core", "samgr" ], "third_party": [] @@ -79,7 +80,8 @@ "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common:datashare_common", "//foundation/distributeddatamgr/data_share/interfaces/inner_api:datashare_ext_ability_module", "//foundation/distributeddatamgr/data_share/frameworks/js/napi:datashare_napi_packages", - "//foundation/distributeddatamgr/data_share/frameworks/cj/ffi:datashare_cj_ffi_packages" + "//foundation/distributeddatamgr/data_share/frameworks/cj/ffi:datashare_cj_ffi_packages", + "//foundation/distributeddatamgr/data_share/frameworks/js/ani:datashare_ani_packages" ], "service_group": [ ] @@ -101,6 +103,7 @@ "header": { "header_files": [ "datashare_helper.h", + "dataproxy_handle.h", "datashare_result_set.h" ], "header_base": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/consumer/include" @@ -139,11 +142,53 @@ ], "header_base": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common/include" } + }, + { + "name": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common:datashare_common_lite", + "header": { + "header_files": [ + "datashare_abs_predicates.h", + "datashare_predicates_def.h", + "datashare_predicates_object.h" + ], + "header_base": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common/include" + } + }, + { + "name": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common:datashare_common_lite", + "header": { + "header_files": [ + "result_set_bridge.h" + ], + "header_base": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/provider/include" + } + }, + { + "name": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common:datashare_common_lite", + "header": { + "header_files": [ + "datashare_result_set.h" + ], + "header_base": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/consumer/include" + } + }, + { + "name": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common:datashare_common_lite", + "header": { + "header_files": [ + "datashare_radar_reporter.h", + "ishared_result_set.h" + ], + "header_base": "//foundation/distributeddatamgr/data_share/frameworks/native/common/include" + } } ], "test": [ "//foundation/distributeddatamgr/data_share/test/native:unittest", - "//foundation/distributeddatamgr/data_share/test/js/data_share:unittest" + "//foundation/distributeddatamgr/data_share/test/js/data_share:unittest", + "//foundation/distributeddatamgr/data_share/test/unittest/native:unittest", + "//foundation/distributeddatamgr/data_share/test/ets/data_share_ets:stage_unittest", + "//foundation/distributeddatamgr/data_share/test/fuzztest:fuzztest" ] } } diff --git a/data_share/cfi_blocklist.txt b/data_share/cfi_blocklist.txt new file mode 100644 index 0000000000000000000000000000000000000000..fddb4e5f3be6b00f44955b887fd9f1446e6f1e34 --- /dev/null +++ b/data_share/cfi_blocklist.txt @@ -0,0 +1,2 @@ +src:*/third_party/googletest/googletest/include/gtest/* +src:*/third_party/googletest/googlemock/include/gmock/* \ No newline at end of file diff --git a/data_share/datashare.gni b/data_share/datashare.gni index c825769d127a8b7935afb08150ddedad09524356..3bdbbb59c5e798e484b0e4302c7b44e31cb0a86c 100644 --- a/data_share/datashare.gni +++ b/data_share/datashare.gni @@ -20,6 +20,7 @@ datashare_common_napi_path = "${datashare_base_path}/frameworks/js/napi/common" datashare_napi_path = "${datashare_base_path}/frameworks/js/napi" datashare_cj_ffi_path = "${datashare_base_path}/frameworks/cj/ffi" +datashare_ani_path = "${datashare_base_path}/frameworks/js/ani" datashare_innerapi_path = "${datashare_base_path}/interfaces/inner_api" @@ -32,6 +33,9 @@ datashare_native_consumer_path = datashare_native_permission_path = "${datashare_base_path}/frameworks/native/permission" +datashare_native_dfx_path = + "${datashare_base_path}/frameworks/native/dfx" + datashare_native_proxy_path = "${datashare_base_path}/frameworks/native/proxy" foundation_path = "//foundation" diff --git a/data_share/frameworks/cj/ffi/data_share_predicates/BUILD.gn b/data_share/frameworks/cj/ffi/data_share_predicates/BUILD.gn index 718abfcec47d4ac4d983d8757649e514bad6ac00..7aae918a24fcab24fa726e5ba4e9177c3e8efca5 100644 --- a/data_share/frameworks/cj/ffi/data_share_predicates/BUILD.gn +++ b/data_share/frameworks/cj/ffi/data_share_predicates/BUILD.gn @@ -46,6 +46,7 @@ ohos_shared_library("cj_data_share_predicates_ffi") { external_deps = [ "c_utils:utils", "hilog:libhilog", + "ipc:ipc_single", "napi:ace_napi", "napi:cj_bind_ffi", "napi:cj_bind_native", diff --git a/data_share/frameworks/js/ani/BUILD.gn b/data_share/frameworks/js/ani/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..f05a81c896af65072a8d301fb8880aee387dc1cf --- /dev/null +++ b/data_share/frameworks/js/ani/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright (c) 2025 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/data_share/datashare.gni") + +group("datashare_ani_packages") { + deps = [ + "${datashare_ani_path}/dataShare:data_share", + "${datashare_ani_path}/dataShare:data_share_predicates", + "${datashare_ani_path}/dataShareResultSet:datashareresultset", + ] +} diff --git a/data_share/frameworks/js/ani/common/include/ani_util_class.h b/data_share/frameworks/js/ani/common/include/ani_util_class.h new file mode 100644 index 0000000000000000000000000000000000000000..98a830f84e9662c6ccb5bafc9293dd12c01c2374 --- /dev/null +++ b/data_share/frameworks/js/ani/common/include/ani_util_class.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2025 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 ANI_UTIL_CLASS_H +#define ANI_UTIL_CLASS_H + +#include + +#include + +#include "ani_util_common.h" + +class AniTypeFinder { +public: + AniTypeFinder(ani_env* env) : env_(env) + { + } + + Expected FindNamespace(const char* nsName) + { + ani_namespace ns; + if (env_ == nullptr) { + return ANI_ERROR; + } + + ani_status status = env_->FindNamespace(nsName, &ns); + if (ANI_OK != status) { + return status; + } + return ns; + } + + template + Expected FindNamespace(const char* firstNs, const char* nextNs, Names... restNs) + { + ani_namespace ns; + if (env_ == nullptr) { + return ANI_ERROR; + } + + ani_status status = env_->FindNamespace(firstNs, &ns); + if (ANI_OK != status) { + return status; + } + return FindNamespace(ns, nextNs, restNs...); + } + + Expected FindClass(const char* clsName) + { + ani_class cls; + if (env_ == nullptr) { + return ANI_ERROR; + } + + ani_status status = env_->FindClass(clsName, &cls); + if (ANI_OK != status) { + return status; + } + return cls; + } + + Expected FindClass(const char* nsName, const char* clsName) + { + auto ns = FindNamespace(nsName, clsName); + if (!ns.has_value()) { + return ns.error(); + } + return FindClass(ns.value(), clsName); + } + + template + Expected FindClass(const char* firstNs, const char* secondNs, Names... restNs, + const char* clsName) + { + auto ns = FindNamespace(firstNs, secondNs, restNs...); + if (!ns.has_value()) { + return ns.error(); + } + return FindClass(ns.value(), clsName); + } + + Expected FindClass(ani_namespace ns, const char* clsName) + { + ani_class cls; + if (env_ == nullptr) { + return ANI_ERROR; + } + + ani_status status = env_->Namespace_FindClass(ns, clsName, &cls); + if (ANI_OK != status) { + return status; + } + return cls; + } + + Expected FindEnum(ani_namespace ns, const char* enumName) + { + ani_enum aniEnum{}; + if (env_ == nullptr) { + return ANI_ERROR; + } + + ani_status status = env_->Namespace_FindEnum(ns, enumName, &aniEnum); + if (ANI_OK != status) { + return status; + } + return aniEnum; + } + +private: + template + Expected FindNamespace(ani_namespace currentNs, const char *nextNs, Names... restNs) + { + ani_namespace ns; + if (env_ == nullptr) { + return ANI_ERROR; + } + + ani_status status = env_->Namespace_FindNamespace(currentNs, nextNs, &ns); + if (ANI_OK != status) { + return status; + } + return FindNamespace(ns, restNs...); + } + + Expected FindNamespace(ani_namespace currentNs) + { + return currentNs; + } + +private: + ani_env* env_ = nullptr; +}; + + +class AniObjectFactory { +public: + AniObjectFactory(ani_env *env) + : env_(env) + { + } + + Expected Create(const char* clsName, ...) + { + auto cls = AniTypeFinder(env_).FindClass(clsName); + if (!cls.has_value()) { + return cls.error(); + } + + va_list args; + va_start(args, clsName); + auto obj = CreateV(cls.value(), args); + va_end(args); + return obj; + } + + template + Expected Create(const char* nsName, Names... restNs, const char* clsName, ...) + { + auto cls = AniTypeFinder(env_).FindClass(nsName, restNs..., clsName); + if (!cls.has_value()) { + return cls.error(); + } + + va_list args; + va_start(args, clsName); + auto obj = CreateV(cls.value(), args); + va_end(args); + return obj; + } + + Expected Create(ani_class cls, ...) + { + va_list args; + va_start(args, cls); + auto obj = CreateV(cls, args); + va_end(args); + return obj; + } + +private: + Expected CreateV(ani_class cls, va_list args) + { + ani_method ctor; + if (env_ == nullptr) { + return ANI_ERROR; + } + ani_status status = env_->Class_FindMethod(cls, "", nullptr, &ctor); + if (ANI_OK != status) { + return status; + } + + ani_object obj; + status = env_->Object_New_V(cls, ctor, &obj, args); + if (ANI_OK != status) { + return status; + } + return obj; + } + +private: + ani_env *env_ = nullptr; +}; +#endif // ANI_UTIL_CLASS_H \ No newline at end of file diff --git a/data_share/frameworks/js/ani/common/include/ani_util_common.h b/data_share/frameworks/js/ani/common/include/ani_util_common.h new file mode 100644 index 0000000000000000000000000000000000000000..a535aadf19895b58e4c7a7c06175624f5574ab9e --- /dev/null +++ b/data_share/frameworks/js/ani/common/include/ani_util_common.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2025 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 ANI_UTIL_COMMON_H +#define ANI_UTIL_COMMON_H + +#include +#include +#include +#include +#include + +template +class Expected { +public: + Expected(const T &value) + : data_(value), has_value_(true) + { + } + + Expected(T &&value) + : data_(std::move(value)), has_value_(true) + { + } + + Expected(const E &error) + : data_(error), has_value_(false) + { + } + + Expected(E &&error) + : data_(std::move(error)), has_value_(false) + { + } + + bool has_value() const noexcept + { + return has_value_; + } + + explicit operator bool() const noexcept + { + return has_value(); + } + + T &value() & + { + if (!has_value()) { + std::terminate(); + } + return std::get(data_); + } + + const T &value() const & + { + if (!has_value()) { + std::terminate(); + } + return std::get(data_); + } + + T &&value() && + { + if (!has_value()) { + std::terminate(); + } + return std::get(std::move(data_)); + } + + E &error() & + { + if (has_value()) { + std::terminate(); + } + return std::get(data_); + } + + const E &error() const & + { + if (has_value()) { + std::terminate(); + } + return std::get(data_); + } + + E &&error() && + { + if (has_value()) { + std::terminate(); + } + return std::get(std::move(data_)); + } + + T &operator*() & + { + return value(); + } + + const T &operator*() const & + { + return value(); + } + + T &&operator*() && + { + return std::move(*this).value(); + } + + T *operator->() + { + return &value(); + } + + const T *operator->() const + { + return &value(); + } + + template + T value_or(U &&default_value) const & + { + return has_value() ? value() : static_cast(std::forward(default_value)); + } + + template + T value_or(U &&default_value) && + { + return has_value() ? std::move(*this).value() : static_cast(std::forward(default_value)); + } + +private: + std::variant data_; + bool has_value_; +}; + +template +class FinalAction { +public: + explicit FinalAction(F func) : func_(std::move(func)) + { + } + + ~FinalAction() noexcept(noexcept(func_())) + { + if (!dismissed_) { + func_(); + } + } + + FinalAction(const FinalAction&) = delete; + FinalAction& operator=(const FinalAction&) = delete; + + FinalAction(FinalAction&& other) noexcept + : func_(std::move(other.func_)), + dismissed_(other.dismissed_) + { + other.dismissed_ = true; + } + + void dismiss() noexcept + { + dismissed_ = true; + } + +private: + F func_; + bool dismissed_ = false; +}; + +template +inline FinalAction finally(F&& func) +{ + return FinalAction(std::forward(func)); +} + +#endif // ANI_UTIL_COMMON_H \ No newline at end of file diff --git a/data_share/frameworks/js/ani/common/include/ani_util_native_ptr.h b/data_share/frameworks/js/ani/common/include/ani_util_native_ptr.h new file mode 100644 index 0000000000000000000000000000000000000000..1b65adfdc18d106e71260ff99902f6bd6f26453d --- /dev/null +++ b/data_share/frameworks/js/ani/common/include/ani_util_native_ptr.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2025 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 ANI_UTIL_OBJECT_H +#define ANI_UTIL_OBJECT_H + +#include + +#include +#include + +class NativeObject { +public: + virtual ~NativeObject() = default; +}; + + +template +class SharedPtrHolder : public NativeObject { +public: + SharedPtrHolder(const std::shared_ptr &sptr) : sptr_(sptr) + { + } + + std::shared_ptr Get() + { + return sptr_; + } + + std::shared_ptr GetOrDefault() + { + if (!sptr_) { + sptr_ = std::make_shared(); + } + return sptr_; + } + +private: + std::shared_ptr sptr_; +}; + + +class NativePtrWrapper { +public: + NativePtrWrapper(ani_env *env, ani_object object, const char* propName = "nativePtr") + : env_(env), obj_(object), propName_(propName) + { + } + + template + ani_status Wrap(T* nativePtr) + { + return env_->Object_SetFieldByName_Long(obj_, propName_.c_str(), reinterpret_cast(nativePtr)); + } + + template + T* Unwrap() + { + ani_long nativePtr; + if (env_ == nullptr) { + return nullptr; + } + + if (ANI_OK != env_->Object_GetFieldByName_Long(obj_, propName_.c_str(), &nativePtr)) { + return nullptr; + } + return reinterpret_cast(nativePtr); + } + +private: + ani_env *env_ = nullptr; + ani_object obj_ = nullptr; + std::string propName_; +}; + + +class NativePtrCleaner { +public: + static void Clean([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) + { + ani_long ptr = 0; + if (env == nullptr) { + return; + } + + if (ANI_OK != env->Object_GetFieldByName_Long(object, "targetPtr", &ptr)) { + return; + } + delete reinterpret_cast(ptr); + } + + NativePtrCleaner(ani_env *env) + : env_(env) + { + } + + ani_status Bind(ani_class cls) + { + std::array methods = { + ani_native_function { "clean", nullptr, reinterpret_cast(NativePtrCleaner::Clean) }, + }; + + if (env_ == nullptr) { + return (ani_status)ANI_ERROR; + } + + if (ANI_OK != env_->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + return (ani_status)ANI_ERROR; + }; + + return ANI_OK; + } + +private: + ani_env *env_ = nullptr; +}; + +#endif // ANI_UTIL_OBJECT_H \ No newline at end of file diff --git a/data_share/frameworks/js/ani/common/include/ani_utils.h b/data_share/frameworks/js/ani/common/include/ani_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..7a4384a28377cf697773d621385190b8196d1d0f --- /dev/null +++ b/data_share/frameworks/js/ani/common/include/ani_utils.h @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2025 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 ANI_UTILS_H +#define ANI_UTILS_H + +#include +#include +#include +#include +#include +#include +#include "ani_util_class.h" +#include "ani_util_native_ptr.h" + +namespace OHOS { +namespace DataShare { +class AniObjectUtils { +public: + static ani_object Create(ani_env *env, const char* nsName, const char* clsName, ...); + static ani_object Create(ani_env *env, const char* clsName, ...); + static ani_object Create(ani_env *env, ani_class cls, ...); + static ani_object From(ani_env *env, bool value); + template + static ani_status Wrap(ani_env *env, ani_object object, T* nativePtr, const char* propName = "nativePtr") + { + if (env == nullptr) { + return ANI_ERROR; + } + + if (nativePtr == nullptr) { + return ANI_ERROR; + } + return env->Object_SetFieldByName_Long(object, propName, reinterpret_cast(nativePtr)); + } + + template + static T* Unwrap(ani_env *env, ani_object object, const char* propName = "nativePtr") + { + if (env == nullptr) { + return nullptr; + } + + ani_long nativePtr; + if (ANI_OK != env->Object_GetFieldByName_Long(object, propName, &nativePtr)) { + return nullptr; + } + + return reinterpret_cast(nativePtr); + } +}; + +class AniStringUtils { +public: + static std::string ToStd(ani_env *env, ani_string ani_str); + static ani_string ToAni(ani_env* env, const std::string& str); +}; + +class UnionAccessor { +public: + UnionAccessor(ani_env *env, ani_object &obj); + bool IsInstanceOf(const std::string& cls_name); + bool IsInstanceOf(const std::string& cls_name, ani_object obj); + template bool IsInstanceOfType(); + template bool TryConvert(T &value); + template bool TryConvertArray(std::vector &value); + +private: + ani_env *env_; + ani_object obj_; +}; +class OptionalAccessor { +public: + OptionalAccessor(ani_env *env, ani_object &obj); + bool IsUndefined(); + bool IsNull(); + template std::optional Convert(); + +private: + ani_env *env_; + ani_object obj_; +}; + +template +struct Converter { + static std::string convert(const T& value) + { + std::ostringstream oss; + oss << value; + return oss.str(); + } +}; + +template<> +struct Converter { + static std::string convert(const bool& value) + { + return value ? "true" : "false"; + } +}; + + +template<> +struct Converter { + static std::string convert(const double& value) + { + std::ostringstream buf; + buf << value; + std::string str = buf.str(); + return str; + } +}; + +template +std::vector convertVector(const std::vector& input) +{ + std::vector result; + result.reserve(input.size()); + + for (const auto& elem : input) { + result.push_back(Converter::convert(elem)); + } + return result; +} + +template using convertCallback = bool(*)(ani_env*, ani_ref&, ani_ref&, std::shared_ptr); + +template +bool forEachMapEntry(ani_env *env, ani_object map_object, F &&callback, std::shared_ptr records) +{ + if (env == nullptr) { + return false; + } + ani_ref iter; + if (ANI_OK != env->Object_CallMethodByName_Ref(map_object, "$_iterator", nullptr, &iter)) { + std::cout << "Failed to get keys iterator" << std::endl; + return false; + } + + ani_ref next; + ani_boolean done; + while (ANI_OK == env->Object_CallMethodByName_Ref(static_cast(iter), "next", nullptr, &next)) { + if (ANI_OK != env->Object_GetFieldByName_Boolean(static_cast(next), "done", &done)) { + std::cout << "Failed to check iterator done" << std::endl; + return false; + } + + if (done) { + std::cout << "[forEachMapEntry] done break" << std::endl; + return true; + } + + ani_ref key_value; + if (ANI_OK != env->Object_GetFieldByName_Ref(static_cast(next), "value", &key_value)) { + std::cout << "Failed to get key value" << std::endl; + return false; + } + + ani_ref ani_key; + if (ANI_OK != env->TupleValue_GetItem_Ref(static_cast(key_value), 0, &ani_key)) { + std::cout << "Failed to get key value" << std::endl; + return false; + } + + ani_ref ani_val; + if (ANI_OK != env->TupleValue_GetItem_Ref(static_cast(key_value), 1, &ani_val)) { + std::cout << "Failed to get key value" << std::endl; + return false; + } + + if (!callback(env, ani_key, ani_val, records)) { + return false; + } + } + + std::cout << "Failed to get next key" << std::endl; + return false; +} + +ani_object DoubleToObject(ani_env *env, double value); +ani_object BoolToObject(ani_env *env, bool value); +ani_object StringToObject(ani_env *env, std::string value); +ani_object Uint8ArrayToObject(ani_env *env, const std::vector &values); +} +} +#endif // ANI_UTILS_H diff --git a/data_share/frameworks/js/ani/common/include/datashare_predicates_cleaner.h b/data_share/frameworks/js/ani/common/include/datashare_predicates_cleaner.h new file mode 100644 index 0000000000000000000000000000000000000000..261c70c5ff39157d0b5fb0d76021d7d6cc1d6181 --- /dev/null +++ b/data_share/frameworks/js/ani/common/include/datashare_predicates_cleaner.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025 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_PREDICATES_CLEANER_H +#define DATASHARE_PREDICATES_CLEANER_H + +#include + +#include +#include +#include "datashare_predicates.h" + +class DataSharePredicatesCleaner { + public: + static void Clean([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) + { + ani_long ptr = 0; + if (env == nullptr) { + return; + } + if (ANI_OK != env->Object_GetFieldByName_Long(object, "targetPtr", &ptr)) { + return; + } + delete reinterpret_cast(ptr); + } + + DataSharePredicatesCleaner(ani_env *env) + : env_(env) + { + } + + ani_status Bind(ani_class cls) + { + std::array methods = { + ani_native_function { "clean", nullptr, reinterpret_cast(DataSharePredicatesCleaner::Clean) }, + }; + + if (env_ == nullptr) { + return static_cast(ANI_ERROR); + } + + if (ANI_OK != env_->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + return static_cast(ANI_ERROR); + }; + + return ANI_OK; + } + + private: + ani_env *env_ = nullptr; + }; + +#endif // DATASHARE_PREDICATES_CLEANER_H \ No newline at end of file diff --git a/data_share/frameworks/js/ani/common/src/ani_utils.cpp b/data_share/frameworks/js/ani/common/src/ani_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d4fddcf9fbff9aba7231a248e6a6a067e22fde4d --- /dev/null +++ b/data_share/frameworks/js/ani/common/src/ani_utils.cpp @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2025 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 +#include +#include +#include +#include +#include + +#include "datashare_log.h" +#include "ani_utils.h" + +namespace OHOS::DataShare { +ani_object AniObjectUtils::Create(ani_env *env, const char* nsName, const char* clsName, ...) +{ + ani_object nullobj{}; + if (env == nullptr) { + return nullobj; + } + ani_namespace ns; + if (ANI_OK != env->FindNamespace(nsName, &ns)) { + LOG_ERROR("[ANI] Not found namespace %{public}s", nsName); + return nullobj; + } + + ani_class cls; + if (ANI_OK != env->Namespace_FindClass(ns, clsName, &cls)) { + LOG_ERROR("[ANI] Not found class %{public}s", clsName); + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + LOG_ERROR("[ANI] Not found for class %{public}s", clsName); + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + LOG_ERROR("[ANI] Failed to Object_New for class %{public}s", clsName); + return nullobj; + } + + return obj; +} + + +ani_object AniObjectUtils::Create(ani_env *env, const char* clsName, ...) +{ + ani_object nullobj{}; + if (env == nullptr) { + return nullobj; + } + ani_class cls; + if (ANI_OK != env->FindClass(clsName, &cls)) { + LOG_ERROR("[ANI] Not found class %{public}s", clsName); + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + LOG_ERROR("[ANI] Not found for class %{public}s", clsName); + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + LOG_ERROR("[ANI] Failed to Object_New for class %{public}s", clsName); + return nullobj; + } + + return obj; +} + +ani_object AniObjectUtils::Create(ani_env *env, ani_class cls, ...) +{ + ani_object nullobj{}; + if (env == nullptr) { + return nullobj; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + LOG_ERROR("[ANI] Not found for class"); + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, cls); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + LOG_ERROR("[ANI] Failed to Object_New for class"); + return nullobj; + } + + return obj; +} + +ani_object AniObjectUtils::From(ani_env *env, bool value) +{ + return Create(env, "Lstd/core/Boolean;", static_cast(value)); +} + +std::string AniStringUtils::ToStd(ani_env *env, ani_string ani_str) +{ + ani_size strSize; + env->String_GetUTF8Size(ani_str, &strSize); + + std::vector buffer(strSize + 1); // +1 for null terminator + char* utf8_buffer = buffer.data(); + + //String_GetUTF8 Supportted by https://gitee.com/openharmony/arkcompiler_runtime_core/pulls/3416 + ani_size bytes_written = 0; + env->String_GetUTF8(ani_str, utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + + return content; +} + +ani_string AniStringUtils::ToAni(ani_env* env, const std::string& str) +{ + ani_string aniStr = nullptr; + if (ANI_OK != env->String_NewUTF8(str.data(), str.size(), &aniStr)) { + LOG_ERROR("[ANI] Unsupported ANI_VERSION_1"); + return nullptr; + } + + return aniStr; +} + +UnionAccessor::UnionAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) +{ +} + +bool UnionAccessor::IsInstanceOf(const std::string& clsName) +{ + ani_class cls; + env_->FindClass(clsName.c_str(), &cls); + + ani_boolean ret; + env_->Object_InstanceOf(obj_, cls, &ret); + + return ret; +} + +bool UnionAccessor::IsInstanceOf(const std::string& clsName, ani_object obj) +{ + ani_class cls; + env_->FindClass(clsName.c_str(), &cls); + + ani_boolean ret; + env_->Object_InstanceOf(obj, cls, &ret); + return ret; +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Boolean;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Int;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Double;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/String;"); +} + +template<> +bool UnionAccessor::TryConvert(bool &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_boolean aniValue; + auto ret = env_->Object_CallMethodByName_Boolean(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + + value = static_cast(aniValue); + + return true; +} + +template<> +bool UnionAccessor::TryConvert(int &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_int aniValue; + auto ret = env_->Object_CallMethodByName_Int(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + + value = static_cast(aniValue); + + return true; +} + +template<> +bool UnionAccessor::TryConvert(double &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + + value = static_cast(aniValue); + + return true; +} + +template<> +bool UnionAccessor::TryConvert(std::string &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + value = AniStringUtils::ToStd(env_, static_cast(obj_)); + + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_GetPropertyByName_Ref failed"); + return false; + } + + if (!IsInstanceOf("Lstd/core/Boolean;", static_cast(ref))) { + LOG_ERROR("Not found 'Lstd/core/Boolean;'"); + return false; + } + + ani_boolean val; + if (ANI_OK != env_->Object_CallMethodByName_Boolean(static_cast(ref), "unboxed", nullptr, &val)) { + LOG_ERROR("Object_CallMethodByName_Double unbox failed"); + return false; + } + + value.push_back(static_cast(val)); + } + + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_GetPropertyByName_Ref failed"); + return false; + } + + if (!IsInstanceOf("Lstd/core/Int;", static_cast(ref))) { + LOG_ERROR("Not found 'Lstd/core/Double;'"); + return false; + } + + ani_int intValue; + if (ANI_OK != env_->Object_CallMethodByName_Int(static_cast(ref), "unboxed", nullptr, &intValue)) { + LOG_ERROR("Object_CallMethodByName_Double unbox failed"); + return false; + } + + value.push_back(static_cast(intValue)); + } + + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_GetPropertyByName_Ref failed"); + return false; + } + + if (!IsInstanceOf("Lstd/core/Double;", static_cast(ref))) { + LOG_ERROR("Not found 'Lstd/core/Double;'"); + return false; + } + + ani_double val; + if (ANI_OK != env_->Object_CallMethodByName_Double(static_cast(ref), "unboxed", nullptr, &val)) { + LOG_ERROR("Object_CallMethodByName_Double unbox failed"); + return false; + } + + value.push_back(static_cast(val)); + } + + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + LOG_INFO("TryConvertArray std::vector"); + ani_ref buffer; + if (ANI_OK != env_->Object_GetFieldByName_Ref(obj_, "buffer", &buffer)) { + LOG_INFO("Object_GetFieldByName_Ref failed"); + return false; + } + + void* data; + size_t length; + if (ANI_OK != env_->ArrayBuffer_GetInfo(static_cast(buffer), &data, &length)) { + LOG_ERROR("ArrayBuffer_GetInfo failed"); + return false; + } + + LOG_INFO("Length of buffer is %{public}zu", length); + for (size_t i = 0; i < length; i++) { + value.push_back(static_cast(data)[i]); + } + + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + + if (!IsInstanceOf("Lstd/core/String;", static_cast(ref))) { + LOG_ERROR("Not found 'Lstd/core/String;'"); + return false; + } + + value.push_back(AniStringUtils::ToStd(env_, static_cast(ref))); + } + + return true; +} + +OptionalAccessor::OptionalAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) +{ +} + +bool OptionalAccessor::IsUndefined() +{ + ani_boolean isUndefined; + env_->Reference_IsUndefined(obj_, &isUndefined); + + return isUndefined; +} + +bool OptionalAccessor::IsNull() +{ + ani_boolean isNull; + env_->Reference_IsNull(obj_, &isNull); + + return isNull; +} + +template<> +std::optional OptionalAccessor::Convert() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_boolean aniValue; + auto ret = env_->Object_CallMethodByName_Boolean(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return std::nullopt; + } + + auto value = static_cast(aniValue); + + return value; +} + +template<> +std::optional OptionalAccessor::Convert() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "doubleValue", nullptr, &aniValue); + if (ret != ANI_OK) { + return std::nullopt; + } + + auto value = static_cast(aniValue); + + return value; +} + +template<> +std::optional OptionalAccessor::Convert() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_size strSize; + env_->String_GetUTF8Size(static_cast(obj_), &strSize); + + std::vector buffer(strSize + 1); + char* utf8_buffer = buffer.data(); + + ani_size bytes_written = 0; + env_->String_GetUTF8(static_cast(obj_), utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + + return content; +} + +ani_object DoubleToObject(ani_env *env, double value) +{ + ani_object aniObject = nullptr; + ani_double doubleValue = static_cast(value); + const char *className = "Lstd/core/Double;"; + ani_class aniClass; + if (ANI_OK != env->FindClass(className, &aniClass)) { + LOG_ERROR("Not found '%{public}s'.", className); + return aniObject; + } + ani_method personInfoCtor; + if (ANI_OK != env->Class_FindMethod(aniClass, "", "D:V", &personInfoCtor)) { + LOG_ERROR("Class_GetMethod Failed '%{public}s .'", className); + return aniObject; + } + + if (ANI_OK != env->Object_New(aniClass, personInfoCtor, &aniObject, doubleValue)) { + LOG_ERROR("Object_New Failed '%{public}s. ", className); + return aniObject; + } + return aniObject; +} + +ani_object BoolToObject(ani_env *env, bool value) +{ + ani_object aniObject = nullptr; + ani_boolean boolValue = static_cast(value); + const char *className = "Lstd/core/Boolean;"; + ani_class aniClass; + if (ANI_OK != env->FindClass(className, &aniClass)) { + LOG_ERROR("Not found '%{public}s.'", className); + return aniObject; + } + + ani_method personInfoCtor; + if (ANI_OK != env->Class_FindMethod(aniClass, "", "Z:V", &personInfoCtor)) { + LOG_ERROR("Class_GetMethod Failed '%{public}s' .", className); + return aniObject; + } + + if (ANI_OK != env->Object_New(aniClass, personInfoCtor, &aniObject, boolValue)) { + LOG_ERROR("Object_New Failed '%{public}s' .", className); + } + + return aniObject; +} + +ani_object StringToObject(ani_env *env, std::string value) +{ + return static_cast(AniStringUtils::ToAni(env, value)); +} + +ani_object Uint8ArrayToObject(ani_env *env, const std::vector &values) +{ + ani_object aniObject = nullptr; + ani_class arrayClass; + if (values.size() == 0) { + LOG_ERROR("values is empty"); + return aniObject; + } + ani_status retCode = env->FindClass("Lescompat/Uint8Array;", &arrayClass); + if (retCode != ANI_OK) { + LOG_ERROR("Failed: env->FindClass()"); + return aniObject; + } + + ani_method arrayCtor; + retCode = env->Class_FindMethod(arrayClass, "", "I:V", &arrayCtor); + if (retCode != ANI_OK) { + LOG_ERROR("Failed: env->Class_FindMethod()"); + return aniObject; + } + + auto valueSize = values.size(); + retCode = env->Object_New(arrayClass, arrayCtor, &aniObject, valueSize); + if (retCode != ANI_OK) { + LOG_ERROR("Failed: env->Object_New()"); + return aniObject; + } + + ani_ref buffer; + env->Object_GetFieldByName_Ref(aniObject, "buffer", &buffer); + void *bufData; + size_t bufLength; + retCode = env->ArrayBuffer_GetInfo(static_cast(buffer), &bufData, &bufLength); + if (retCode != ANI_OK) { + LOG_INFO("Failed: env->ArrayBuffer_GetInfo()"); + } + + auto ret = memcpy_s(bufData, bufLength, values.data(), values.size()); + if (ret != 0) { + return nullptr; + } + + return aniObject; +} // namespace DataShare +} // namespace OHOS diff --git a/data_share/frameworks/js/ani/dataShare/BUILD.gn b/data_share/frameworks/js/ani/dataShare/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..9544c5d8ee7412f4b37ca3325996aee720df7a1a --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/BUILD.gn @@ -0,0 +1,145 @@ +# Copyright (c) 2025 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/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/distributeddatamgr/data_share/datashare.gni") + +ohos_shared_library("datashare_ani") { + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + sources = [ + "src/ani_datashare_helper.cpp", + "src/ani_datashare_inner_observer.cpp", + "src/ani_datashare_observer.cpp", + "${datashare_ani_path}/common/src/ani_utils.cpp", + ] + + include_dirs = [ + "include/", + "${datashare_base_path}/interfaces/inner_api/common/include", + "${datashare_ani_path}/common/include", + ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer", + "${datashare_innerapi_path}/common:datashare_common", + ] + + external_deps = [ + "ability_runtime:ani_base_context", + "ability_runtime:ani_common", + "ability_runtime:app_context", + "access_token:libtokenid_sdk", + "c_utils:utils", + "hilog:libhilog", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "runtime_core:ani", + ] + + subsystem_name = "distributeddatamgr" + part_name = "data_share" + output_extension = "so" +} + +generate_static_abc("datashare_abc") { + base_url = "ets" + files = [ "ets/@ohos.data.dataShare.ets" ] + dst_file = "$target_out_dir/datashare.abc" + out_puts = [ "$target_out_dir/datashare.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/datashare.abc" +} + +ohos_prebuilt_etc("datashare_abc_etc") { + source = "$target_out_dir/datashare.abc" + module_install_dir = "framework" + subsystem_name = "distributeddatamgr" + part_name = "data_share" + deps = [ ":datashare_abc" ] +} + +group("data_share") { + deps = [ + ":datashare_ani", + ":datashare_abc_etc", + ] +} + +ohos_shared_library("datasharepredicates_ani") { + sanitize = { + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + sources = [ + "src/data_share_predicates.cpp", + "${datashare_ani_path}/common/src/ani_utils.cpp", + ] + + include_dirs = [ + "include", + "${datashare_common_native_path}/include", + "${datashare_ani_path}/common/include", + ] + + deps = [ "${datashare_innerapi_path}/common:datashare_common" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "runtime_core:ani", + ] + + subsystem_name = "distributeddatamgr" + part_name = "data_share" + output_extension = "so" +} + +generate_static_abc("data_share_predicates_abc") { + base_url = "ets" + files = [ "ets/@ohos.data.dataSharePredicates.ets" ] + dst_file = "$target_out_dir/data_share_predicates.abc" + out_puts = [ "$target_out_dir/data_share_predicates.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/data_share_predicates.abc" +} + +ohos_prebuilt_etc("data_share_predicates_abc_etc") { + source = "$target_out_dir/data_share_predicates.abc" + module_install_dir = "framework" + subsystem_name = "distributeddatamgr" + part_name = "data_share" + deps = [ ":data_share_predicates_abc" ] +} + +group("data_share_predicates") { + deps = [ + ":data_share_predicates_abc_etc", + ":datasharepredicates_ani", + ] +} diff --git a/data_share/frameworks/js/ani/dataShare/ets/@ohos.data.dataShare.ets b/data_share/frameworks/js/ani/dataShare/ets/@ohos.data.dataShare.ets new file mode 100644 index 0000000000000000000000000000000000000000..9e66a417d1cee1ab0305e186b90d2cf4d783b648 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/ets/@ohos.data.dataShare.ets @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2025 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. + */ + +/** + * @file + * @kit ArkData + */ + +import hilog from '@ohos.hilog' +import { BusinessError } from '@ohos.base' +import type { AsyncCallback } from '@ohos.base' +import Context from 'application.Context' +import DataShareResultSet from '@ohos.data.DataShareResultSet' +import dataSharePredicates from '@ohos.data.dataSharePredicates' +import { ValuesBucket } from '@ohos.data.ValuesBucket' + +export namespace dataShare { + loadLibrary("datashare_ani") + + export interface DataShareHelperOptions { + isProxy?: boolean; + } + + enum ChangeType { + INSERT = 0, + DELETE, + UPDATE + } + + export enum SubscriptionType { + SUBSCRIPTION_TYPE_EXACT_URI = 0, + } + + export interface ChangeInfo { + type: ChangeType + uri: string + values: Array + } + + export interface DataShareHelper { + on(type: 'dataChange', uri: string, callback: AsyncCallback): void + off(type: 'dataChange', uri: string, callback?: AsyncCallback): void + on(event: 'dataChange', type: SubscriptionType, uri: string, callback: AsyncCallback): void + off(event: 'dataChange', type: SubscriptionType, uri: string, callback?: AsyncCallback): void + query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array, callback: AsyncCallback): void + query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array): Promise + update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket, callback: AsyncCallback): void + update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket): Promise + } + + export native function create(context: Context, uri: string, options?: DataShareHelperOptions): DataShareHelper + + export function createDataShareHelper(context: Context, uri: string, callback: AsyncCallback): void { + let p = taskpool.execute(create, context, uri, undefined) + p.then((e: NullishType) => { + let r = e as DataShareHelper + let err: BusinessError + callback(err, r) + }).catch((error: NullishType) => { + let r = new DataShareHelperInner(0) + let err = error as BusinessError + hilog.error(0x0000, 'DataShareHelper', "create failed:" + err) + callback(err, r) + }) + } + + export function createDataShareHelper(context: Context, uri: string, options: DataShareHelperOptions, callback: AsyncCallback): void { + let p = taskpool.execute(create, context, uri, options) + p.then((e: NullishType) => { + let r = e as DataShareHelper + let err: BusinessError + callback(err, r) + }).catch((error: NullishType) => { + let r = new DataShareHelperInner(0) + let err = error as BusinessError + hilog.error(0x0000, 'DataShareHelper', "create failed:" + err) + callback(err, r) + }) + } + + export function createDataShareHelper(context: Context, uri: string, options?: DataShareHelperOptions): Promise { + console.println("createDataShareHelper enter") + return new Promise((resolve: (v: DataShareHelper) => void, reject: (error: Error) => void) => { + let p = taskpool.execute(create, context, uri, options) + p.then((e: NullishType) => { + let r = e as DataShareHelper + resolve(r) + }).catch((e: Error): void => { + hilog.error(0x0000, 'DataShareHelper', "create failed:" + e) + reject(e) + }) + }) + } + + class ChangeInfoInner implements ChangeInfo { + type: ChangeType + uri: string + values: Array + } + + class Cleaner { + static callback(cleaner: Cleaner): void { + console.println("enter Cleaner.callback"); + cleaner.clean() + } + + constructor(targetPtr: long) { + this.targetPtr = targetPtr + } + + native clean(): void + + private targetPtr: long = 0 + } + + class FinalizationAgent { + constructor(obj: T, ptr: long) { + this.register(obj, ptr); + } + + register(obj: T, ptr: long): void { + this.unregisterToken = {}; + this.cleaner = new Cleaner(ptr); + finalizer.register(obj, this.cleaner!, this.unregisterToken); + } + + unregister(): void { + finalizer.unregister(this.unregisterToken); + } + + private cleaner: Cleaner | null = null; + private unregisterToken: object; + } + + let finalizer = new FinalizationRegistry(Cleaner.callback) + + class DataShareHelperInner implements DataShareHelper { + private nativePtr: long = 0 + private fzAgent: FinalizationAgent; + private onCallback: AsyncCallback = () => {} + private offCallback?: AsyncCallback + private onEventCallback: AsyncCallback = () => {} + private offEventCallback?: AsyncCallback + + constructor(nativePtr:long) { + hilog.info(0x0000, 'DataShareHelper', "in constructor, context :" + nativePtr) + this.nativePtr = nativePtr + this.fzAgent = new FinalizationAgent(this, this.nativePtr); + } + + unregisterCleaner(): void { + this.fzAgent.unregister(); + } + + getNativePtr(): long { + return this.nativePtr + } + + native on(type: 'dataChange', uri: string, callback: AsyncCallback): void + native off(type: 'dataChange', uri: string, callback?: AsyncCallback): void + native on(event: 'dataChange', type: SubscriptionType, uri: string, callback: AsyncCallback): void + native off(event: 'dataChange', type: SubscriptionType, uri: string, callback?: AsyncCallback): void + native ani_query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array): DataShareResultSet + native ani_update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket): number + + query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array, callback: AsyncCallback): void { + let p = taskpool.execute(this.ani_query, uri, predicates, columns) + p.then((e: NullishType) => { + let r = e as DataShareResultSet + let err: BusinessError + callback(err, r) + }).catch((error: NullishType) => { + let err = error as BusinessError + hilog.error(0x0000, 'DataShareHelper', "query failed:" + err) + }) + } + + query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array): Promise { + return new Promise((resolve: (v: DataShareResultSet) => void, reject: (error: Error) => void) => { + let p = taskpool.execute(this.ani_query, uri, predicates, columns) + p.then((e: NullishType) => { + let r = e as DataShareResultSet + resolve(r) + }).catch((e: Error): void => { + hilog.error(0x0000, 'DataShareHelper', "query failed:" + e) + reject(e) + }) + }) + } + + update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket, callback: AsyncCallback): void { + let p = taskpool.execute(this.ani_update, uri, predicates, value) + p.then((e: NullishType) => { + let r = e as number + let err: BusinessError + callback(err, r) + }).catch((error: NullishType) => { + let err = error as BusinessError + hilog.error(0x0000, 'DataShareHelper', "create failed:" + err) + }) + } + + update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket): Promise { + return new Promise((resolve: (v: number) => void, reject: (error: Error) => void) => { + let p = taskpool.execute(this.ani_update, uri, predicates, value) + p.then((e: NullishType) => { + let r = e as number + resolve(r) + }).catch((e: Error): void => { + hilog.error(0x0000, 'DataShareHelper', "update failed:" + e) + reject(e) + }) + }) + } + } +} diff --git a/data_share/frameworks/js/ani/dataShare/ets/@ohos.data.dataSharePredicates.ets b/data_share/frameworks/js/ani/dataShare/ets/@ohos.data.dataSharePredicates.ets new file mode 100644 index 0000000000000000000000000000000000000000..91623f45d3bf005dec185fdf98432479b1338b32 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/ets/@ohos.data.dataSharePredicates.ets @@ -0,0 +1,98 @@ + +/* + * Copyright (c) 2025 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 { ValueType } from "@ohos.data.ValuesBucket" + +export default namespace dataSharePredicates{ + +class Cleaner { + static callback(cleaner: Cleaner): void { + console.println("enter Cleaner.callback"); + cleaner.clean() + } + + constructor(targetPtr: long) { + this.targetPtr = targetPtr + } + + native clean(): void + + private targetPtr: long = 0 +} + +class FinalizationAgent { + constructor(obj: T, ptr: long) { + this.register(obj, ptr); + } + + register(obj: T, ptr: long): void { + this.unregisterToken = {}; + this.cleaner = new Cleaner(ptr); + finalizer.register(obj, this.cleaner!, this.unregisterToken); + } + + unregister(): void { + finalizer.unregister(this.unregisterToken); + } + + private cleaner: Cleaner | null = null; + private unregisterToken: object; +} + +let finalizer = new FinalizationRegistry(Cleaner.callback) + +export class DataSharePredicates{ + static { loadLibrary("datasharepredicates_ani") } + private nativePtr:long = 0; + private fzAgent: FinalizationAgent; + + constructor() { + console.log("enter constructor") + if (this.nativePtr == 0) { + console.log("start create") + this.nativePtr = DataSharePredicates.create(); + console.log("stop create") + } + this.fzAgent = new FinalizationAgent(this, this.nativePtr); + } + + unregisterCleaner(): void { + this.fzAgent.unregister(); + } + + getNativePtr():long { + return this.nativePtr; + } + native static create(): long; + native equalTo(field: string, value: ValueType):DataSharePredicates; + native notEqualTo(field: string, value: ValueType):DataSharePredicates; + native orderByDesc(field: string):DataSharePredicates; + native orderByAsc(field: string):DataSharePredicates; + native and():DataSharePredicates; + native limit(total: number, offset: number):DataSharePredicates; + native lessThan(field: string, value: ValueType): DataSharePredicates; + native like(field: string, value: string): DataSharePredicates; + native endWrap(): DataSharePredicates; + native greaterThanOrEqualTo(field: string, value: ValueType): DataSharePredicates; + native contains(field: string, value: string): DataSharePredicates; + native or(): DataSharePredicates; + native beginWrap(): DataSharePredicates; + native greaterThan(field: string, value: ValueType): DataSharePredicates; + native groupBy(fields:Array): DataSharePredicates; + native in(field: string, value: Array): DataSharePredicates; + native notIn(field: string, value: Array): DataSharePredicates; +} +} diff --git a/data_share/frameworks/js/ani/dataShare/include/ani_datashare_helper.h b/data_share/frameworks/js/ani/dataShare/include/ani_datashare_helper.h new file mode 100644 index 0000000000000000000000000000000000000000..0350fe7fd4772f53ab7df236758a2aa2932bf7be --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/include/ani_datashare_helper.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 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 ANI_DATASHARE_HELPER_H +#define ANI_DATASHARE_HELPER_H + +#include "datashare_helper.h" +#include "ani_datashare_observer.h" + +namespace OHOS { +namespace DataShare { +} // namespace DataShare +} // namespace OHOS +#endif /* ANI_DATASHARE_HELPER_H */ diff --git a/data_share/frameworks/js/ani/dataShare/include/ani_datashare_inner_observer.h b/data_share/frameworks/js/ani/dataShare/include/ani_datashare_inner_observer.h new file mode 100644 index 0000000000000000000000000000000000000000..8afcb8191a86d95dd20b940f8393198751e892c1 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/include/ani_datashare_inner_observer.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025 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 ANI_DATASHARE_INNER_OBSERVER_H +#define ANI_DATASHARE_INNER_OBSERVER_H + +#include + +#include "datashare_log.h" +#include "datashare_helper.h" + +namespace OHOS { +namespace DataShare { +class ANIInnerObserver : public std::enable_shared_from_this { +public: + ANIInnerObserver(ani_vm *vm, ani_ref callback); + virtual ~ANIInnerObserver(); + void OnChange(const DataShareObserver::ChangeInfo &changeInfo = {}, bool isNotifyDetails = false); + ani_ref GetCallback(); + +private: + ani_object GetNewChangeInfo(ani_env *env); + ani_enum_item GetEnumItem(ani_env *env, int32_t type); + ani_object Convert2TSValue(ani_env *env, const std::monostate &value = {}); + ani_object Convert2TSValue(ani_env *env, int64_t value); + ani_object Convert2TSValue(ani_env *env, double value); + ani_object Convert2TSValue(ani_env *env, bool value); + ani_object Convert2TSValue(ani_env *env, const std::string &value); + ani_object Convert2TSValue(ani_env *env, const std::vector &values); + template + ani_object Convert2TSValue(ani_env *env, const std::variant &value); + ani_object Convert2TSValue(ani_env *env, const DataShareValuesBucket &valueBucket); + template + ani_object Convert2TSValue(ani_env *env, const std::vector &values); + ani_object Convert2TSValue(ani_env *env, const DataShareObserver::ChangeInfo& changeInfo); + template + ani_object ReadVariant(ani_env *env, size_t step, size_t index, const _VTp &value); + template + ani_object ReadVariant(ani_env *env, size_t step, size_t index, const _VTp &value); + +private: + ani_vm *vm_; + ani_ref callback_; +}; +} // namespace DataShare +} // namespace OHOS +#endif //ANI_DATASHARE_INNER_OBSERVER_H \ No newline at end of file diff --git a/data_share/frameworks/js/ani/dataShare/include/ani_datashare_observer.h b/data_share/frameworks/js/ani/dataShare/include/ani_datashare_observer.h new file mode 100644 index 0000000000000000000000000000000000000000..d1370ae80fe58c65d0698d02a494c2ccdaa27c56 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/include/ani_datashare_observer.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 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 ANI_DATASHARE_OBSERVER_H +#define ANI_DATASHARE_OBSERVER_H + +#include "data_ability_observer_stub.h" +#include "ani_datashare_inner_observer.h" + +namespace OHOS { +namespace DataShare { +class ANIDataShareObserver : public AAFwk::DataAbilityObserverStub, + public DataShareObserver { +public: + explicit ANIDataShareObserver(const std::shared_ptr observer) : observer_(observer){}; + virtual ~ANIDataShareObserver(); + void OnChange() override; + void OnChange(const ChangeInfo &changeInfo) override; + std::shared_ptr observer_ = nullptr; +}; +} // namespace DataShare +} // namespace OHOS +#endif /* ANI_DATASHARE_OBSERVER_H */ + \ No newline at end of file diff --git a/data_share/frameworks/js/ani/dataShare/src/ani_datashare_helper.cpp b/data_share/frameworks/js/ani/dataShare/src/ani_datashare_helper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2cd0880413327ee1d5f4658913c573ab5ddd3166 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/src/ani_datashare_helper.cpp @@ -0,0 +1,683 @@ +/* + * Copyright (c) 2025 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 +#include + +#include "uri.h" +#include "ani_utils.h" +#include "datashare_predicates.h" +#include "datashare_template.h" +#include "ani_base_context.h" +#include "ani_datashare_helper.h" +#include "datashare_business_error.h" +#include "ipc_skeleton.h" +#include "tokenid_kit.h" + +using namespace OHOS; +using namespace OHOS::DataShare; +using namespace OHOS::Security::AccessToken; +using Uri = OHOS::Uri; + +static constexpr int EXCEPTION_SYSTEMAPP_CHECK = 202; +static std::map>> observerMap_; + +static bool IsSystemApp() +{ + uint64_t tokenId = IPCSkeleton::GetSelfTokenID(); + return TokenIdKit::IsSystemAppByFullTokenID(tokenId); +} + +static void ThrowBusinessError(ani_env *env, int errCode, std::string&& errMsg) +{ + LOG_DEBUG("Begin ThrowBusinessError."); + static const char *errorClsName = "L@ohos/base/BusinessError;"; + ani_class cls {}; + if (ANI_OK != env->FindClass(errorClsName, &cls)) { + LOG_ERROR("find class BusinessError %{public}s failed", errorClsName); + return; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", ":V", &ctor)) { + LOG_ERROR("find method BusinessError.constructor failed"); + return; + } + ani_object errorObject; + if (ANI_OK != env->Object_New(cls, ctor, &errorObject)) { + LOG_ERROR("create BusinessError object failed"); + return; + } + ani_double aniErrCode = static_cast(errCode); + ani_string errMsgStr; + if (ANI_OK != env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &errMsgStr)) { + LOG_ERROR("convert errMsg to ani_string failed"); + return; + } + if (ANI_OK != env->Object_SetFieldByName_Double(errorObject, "code", aniErrCode)) { + LOG_ERROR("set error code failed"); + return; + } + if (ANI_OK != env->Object_SetPropertyByName_Ref(errorObject, "message", errMsgStr)) { + LOG_ERROR("set error message failed"); + return; + } + env->ThrowError(static_cast(errorObject)); + return; +} + +static bool getNameSpace(ani_env *env, ani_namespace &ns) +{ + const char *spaceName = "L@ohos/data/dataShare/dataShare;"; + if (ANI_OK != env->FindNamespace(spaceName, &ns)) { + LOG_ERROR("Not found space name '%{public}s'", spaceName); + return false; + } + + return true; +} + +static bool getClass(ani_env *env, ani_class &cls) +{ + ani_namespace ns; + if (!getNameSpace(env, ns)) { + return false; + } + + const char *className = "LDataShareHelperInner;"; + if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) { + LOG_ERROR("Not found class name '%{public}s'", className); + return false; + } + + return true; +} + +static bool getUri(ani_env *env, ani_string uri, std::string &strUri) +{ + strUri = AniStringUtils::ToStd(env, uri); + if (strUri.empty()) { + LOG_ERROR("uri is empty"); + return false; + } + + return true; +} + +static bool getType(ani_env *env, ani_string type, std::string &strType) +{ + strType = AniStringUtils::ToStd(env, type); + if (strType.empty()) { + LOG_ERROR("type is empty"); + return false; + } + + return true; +} + +static bool getEvent(ani_env *env, ani_string event, std::string &strEvent) +{ + strEvent = AniStringUtils::ToStd(env, event); + if (strEvent.empty()) { + LOG_ERROR("event is empty"); + return false; + } + + return true; +} + +static bool getDataShareHelper(ani_env *env, ani_object object, DataShareHelper *&helper) +{ + ani_long nativePtr; + if (ANI_OK != env->Object_GetFieldByName_Long(object, "nativePtr", &nativePtr)) { + LOG_ERROR("nativePtr is nullptr"); + return false; + } + + auto helperHolder = reinterpret_cast *>(nativePtr); + if (helperHolder == nullptr) { + LOG_ERROR("SharedPtrHolder is nullptr"); + return false; + } + + helper = helperHolder->Get().get(); + if (helper == nullptr) { + LOG_ERROR("DataShareHelper is nullptr"); + return false; + } + + return true; +} + +static ani_status GetIsProxy(ani_env *env, ani_object options, bool &isProxy) +{ + ani_ref proxyObj; + ani_status result = env->Object_GetPropertyByName_Ref(options, "isProxy", &proxyObj); + if (ANI_OK != result) { + LOG_ERROR("options Failed to get property named type: %{public}d", result); + return result; + } + + ani_boolean isUndefined; + result = env->Reference_IsUndefined(static_cast(proxyObj), &isUndefined); + if (ANI_OK != result) { + LOG_ERROR("options Object_GetFieldByName_Ref isProxyField Failed"); + return result; + } + + if (isUndefined) { + LOG_ERROR("options isProxyField is Undefined Now"); + isProxy = false; + return ANI_OK; + } + + ani_boolean proxy; + result = env->Object_CallMethodByName_Boolean(static_cast(proxyObj), "unboxed", nullptr, &proxy); + if (ANI_OK != result) { + LOG_ERROR("options Failed to get property named isProxy: %{public}d", result); + return result; + } + + isProxy = proxy; + return ANI_OK; +} + +static std::shared_ptr CreateDataShareHelper(ani_env *env, ani_object options, std::string &strUri, + std::shared_ptr &ctx) +{ + bool isProxy = false; + if (GetIsProxy(env, options, isProxy) != ANI_OK) { + LOG_ERROR("Get isProxy Failed"); + return nullptr; + } + CreateOptions opts = { + isProxy, + ctx->GetToken(), + Uri(strUri).GetScheme() == "datashareproxy", + }; + + return DataShareHelper::Creator(strUri, opts); +} + +static ani_object ANI_Create([[maybe_unused]] ani_env *env, ani_object context, ani_string uri, ani_object options) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return nullptr; + } + + if (!IsSystemApp()) { + ThrowBusinessError(env, EXCEPTION_SYSTEMAPP_CHECK, "not system app"); + } + + std::string strUri; + ani_class cls; + if (!getUri(env, uri, strUri) || !getClass(env, cls)) { + return nullptr; + } + + ani_boolean isUndefined; + if (ANI_OK != env->Reference_IsUndefined(options, &isUndefined)) { + LOG_ERROR("Get is undefined Failed"); + return nullptr; + } + + auto ctx = AbilityRuntime::GetStageModeContext(env, context); + if (ctx == nullptr) { + LOG_ERROR("Get Context Failed"); + return nullptr; + } + std::shared_ptr dataShareHelper; + if (isUndefined) { + dataShareHelper = DataShareHelper::Creator(ctx->GetToken(), strUri); + } else { + dataShareHelper = CreateDataShareHelper(env, options, strUri, ctx); + } + + if (dataShareHelper == nullptr) { + LOG_ERROR("Create Object DataShareHelper is null"); + return nullptr; + } + + auto shareptrData = new (std::nothrow) SharedPtrHolder(dataShareHelper); + if (shareptrData == nullptr) { + LOG_ERROR("Create Object SharedPtrHolder is null"); + return nullptr; + } + + const char *spaceName = "L@ohos/data/dataShare/dataShare;"; + const char *className = "LDataShareHelperInner;"; + ani_object dataShareObj = AniObjectUtils::Create(env, spaceName, className, + reinterpret_cast(shareptrData)); + + return dataShareObj; +} + +static void ANI_OnType([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_string type, ani_string uri, ani_object callback) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return; + } + std::string strType; + std::string strUri; + DataShareHelper *helper = nullptr; + if (!getType(env, type, strType) || !getUri(env, uri, strUri) || !getDataShareHelper(env, object, helper)) { + return; + } + + ani_ref callbackRef; + if (ANI_OK != env->GlobalReference_Create(callback, &callbackRef)) { + LOG_ERROR("Create callback failed"); + return; + } + + if (strType == "dataChange") { + observerMap_.try_emplace(strUri); + + auto &list = observerMap_.find(strUri)->second; + for (auto &it : list) { + if (callbackRef == it->observer_->GetCallback()) { + LOG_ERROR("The observer has already subscribed."); + return; + } + } + + ani_vm *vm = nullptr; + if (ANI_OK != env->GetVM(&vm)) { + LOG_ERROR("GetVM failed."); + return; + } + + auto innerObserver = std::make_shared(vm, callbackRef); + sptr observer(new (std::nothrow) ANIDataShareObserver(innerObserver)); + if (observer == nullptr) { + LOG_ERROR("observer is nullptr"); + return; + } + + helper->RegisterObserver(Uri(strUri), observer); + list.push_back(observer); + } +} + +static void DataChangeOffEvent(ani_env *env, ani_ref &callbackRef, std::string &strUri, DataShareHelper *&helper) +{ + auto obs = observerMap_.find(strUri); + if (obs == observerMap_.end()) { + LOG_ERROR("this uri hasn't been registered"); + return; + } + + auto &list = obs->second; + auto it = list.begin(); + while (it != list.end()) { + ani_boolean isEquals = false; + if (ANI_OK != env->Reference_StrictEquals(callbackRef, (*it)->observer_->GetCallback(), &isEquals)) { + LOG_ERROR("%{public}s: check observer equal failed!", __func__); + return; + } + + if (callbackRef != nullptr && !isEquals) { + ++it; + continue; + } + + helper->UnregisterObserverExt(Uri(strUri), + std::shared_ptr((*it).GetRefPtr(), [holder = *it](const auto*) {})); + it = list.erase(it); + } + + if (list.empty()) { + observerMap_.erase(strUri); + } +} + +static void DataChangeOffType(ani_env *env, ani_ref &callbackRef, std::string &strUri, DataShareHelper *&helper) +{ + auto obs = observerMap_.find(strUri); + if (obs == observerMap_.end()) { + LOG_ERROR("this uri hasn't been registered"); + return; + } + + auto &list = obs->second; + auto it = list.begin(); + while (it != list.end()) { + ani_boolean isEquals = false; + if (ANI_OK != env->Reference_StrictEquals(callbackRef, (*it)->observer_->GetCallback(), &isEquals)) { + LOG_ERROR("%{public}s: check observer equal failed!", __func__); + return; + } + + if (callbackRef != nullptr && !isEquals) { + ++it; + continue; + } + + helper->UnregisterObserver(Uri(strUri), *it); + it = list.erase(it); + } + + if (list.empty()) { + observerMap_.erase(strUri); + } +} + +static void ANI_OffType([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_string type, ani_string uri, ani_object callback) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return; + } + std::string strType; + std::string strUri; + DataShareHelper *helper = nullptr; + if (!getType(env, type, strType) || !getUri(env, uri, strUri) || !getDataShareHelper(env, object, helper)) { + return; + } + + ani_boolean isUndefined; + if (ANI_OK != env->Reference_IsUndefined(callback, &isUndefined)) { + LOG_ERROR("Call Reference_IsUndefined failed"); + return; + } + + ani_ref callbackRef; + if (isUndefined) { + LOG_ERROR("%{public}s: callback is undefined", __func__); + callbackRef = nullptr; + } else { + if (ANI_OK != env->GlobalReference_Create(callback, &callbackRef)) { + LOG_ERROR("Create callback failed"); + return; + } + } + + if (strType == "dataChange") { + DataChangeOffType(env, callbackRef, strUri, helper); + } +} + +static void ANI_OnEvent([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_string event, ani_enum_item subscriptionType, ani_string uri, ani_object callback) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return; + } + std::string strEvent; + std::string strUri; + DataShareHelper *helper = nullptr; + if (!getEvent(env, event, strEvent) || !getUri(env, uri, strUri) || !getDataShareHelper(env, object, helper)) { + return; + } + + ani_ref callbackRef; + if (ANI_OK != env->GlobalReference_Create(callback, &callbackRef)) { + LOG_ERROR("Create callback failed"); + return; + } + + if (strEvent == "dataChange") { + observerMap_.try_emplace(strUri); + + auto &list = observerMap_.find(strUri)->second; + for (auto &it : list) { + if (callbackRef == it->observer_->GetCallback()) { + LOG_ERROR("The observer has already subscribed."); + return; + } + } + + ani_vm *vm = nullptr; + if (ANI_OK != env->GetVM(&vm)) { + LOG_ERROR("GetVM failed."); + return; + } + + auto innerObserver = std::make_shared(vm, callbackRef); + sptr observer(new (std::nothrow) ANIDataShareObserver(innerObserver)); + if (observer == nullptr) { + LOG_ERROR("observer is nullptr"); + return; + } + + helper->RegisterObserverExt(Uri(strUri), + std::shared_ptr(observer.GetRefPtr(), [holder = observer](const auto*) {}), false); + list.push_back(observer); + } +} + +static void ANI_OffEvent([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_string event, ani_enum_item subscriptionType, ani_string uri, ani_object callback) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return; + } + std::string strEvent; + std::string strUri; + DataShareHelper *helper = nullptr; + if (!getEvent(env, event, strEvent) || !getUri(env, uri, strUri) || !getDataShareHelper(env, object, helper)) { + return; + } + + ani_boolean isUndefined; + if (ANI_OK != env->Reference_IsUndefined(callback, &isUndefined)) { + LOG_ERROR("Call Reference_IsUndefined failed"); + return; + } + + ani_ref callbackRef; + if (isUndefined) { + LOG_ERROR("%{public}s: callback is undefined", __func__); + callbackRef = nullptr; + } else { + if (ANI_OK != env->GlobalReference_Create(callback, &callbackRef)) { + LOG_ERROR("Create callback failed"); + return; + } + } + + if (strEvent == "dataChange") { + DataChangeOffEvent(env, callbackRef, strUri, helper); + } +} + +static ani_object ANI_Query([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_string uri, ani_object predicates, ani_object columns) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return nullptr; + } + std::string strUri; + ani_class cls; + DataShareHelper *helper = nullptr; + if (!getUri(env, uri, strUri) || !getClass(env, cls) || !getDataShareHelper(env, object, helper)) { + return nullptr; + } + + auto pred = AniObjectUtils::Unwrap(env, predicates); + if (pred == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr : %{public}d", pred == nullptr); + return nullptr; + } + + std::vector strings; + if (!UnionAccessor(env, columns).TryConvertArray(strings)) { + LOG_ERROR("TryConvertArray columns Failed"); + return nullptr; + } + + Uri uriObj(strUri); + DatashareBusinessError businessError; + auto resultObject = helper->Query(uriObj, *pred, strings, &businessError); + if (resultObject == nullptr) { + LOG_ERROR("query failed, result is null!"); + return nullptr; + } + + if (businessError.GetCode() != 0) { + LOG_ERROR("query failed, errorCode : %{public}d", businessError.GetCode()); + return nullptr; + } + + auto shareptrData = new (std::nothrow) SharedPtrHolder(resultObject); + if (shareptrData == nullptr) { + LOG_ERROR("Create Object SharedPtrHolder is null"); + return nullptr; + } + + const char *className = "L@ohos/data/DataShareResultSet/DataShareResultSetImpl;"; + ani_object resultSetObj = AniObjectUtils::Create(env, className, + reinterpret_cast(shareptrData)); + + return resultSetObj; +} + +using BucketMap = std::map; +using BucketPtr = std::shared_ptr; +using CallbackType = convertCallback; + +auto g_convertValuesBucket = [](ani_env *env, ani_ref &ani_key, ani_ref &object, BucketPtr records) { + auto key = AniStringUtils::ToStd(env, static_cast(ani_key)); + auto unionObject = static_cast(object); + UnionAccessor unionAccessor(env, unionObject); + if (unionAccessor.IsInstanceOf("Lstd/core/Double;")) { + double value; + unionAccessor.TryConvert(value); + records->emplace(key, value); + return true; + } + + if (unionAccessor.IsInstanceOf("Lstd/core/String;")) { + std::string value; + unionAccessor.TryConvert(value); + records->emplace(key, value); + return true; + } + + if (unionAccessor.IsInstanceOf("Lstd/core/Boolean;")) { + bool value; + unionAccessor.TryConvert(value); + records->emplace(key, value); + return true; + } + + std::vector arrayUint8Values; + if (unionAccessor.TryConvertArray(arrayUint8Values)) { + records->emplace(key, arrayUint8Values); + return true; + } + + if (OptionalAccessor(env, unionObject).IsNull()) { + records->emplace(key, nullptr); + return true; + } + + LOG_ERROR("Unexpected object type"); + return false; +}; + +static ani_double ANI_Update([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_string uri, ani_object predicates, ani_object value) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return ani_double(DATA_SHARE_ERROR); + } + std::string strUri; + ani_class cls; + DataShareHelper *helper = nullptr; + if (!getUri(env, uri, strUri) || !getClass(env, cls) || !getDataShareHelper(env, object, helper)) { + return ani_double(DATA_SHARE_ERROR); + } + + auto pred = AniObjectUtils::Unwrap(env, predicates); + if (pred == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr : %{public}d", pred == nullptr); + return ani_double(DATA_SHARE_ERROR); + } + + auto bucket = std::make_shared(); + if (!forEachMapEntry(env, value, g_convertValuesBucket, bucket)) { + LOG_ERROR("Is bucket null: %{public}d", bucket->empty()); + return ani_double(DATA_SHARE_ERROR); + } + + Uri uriObj(strUri); + DataShareValuesBucket dataShareValuesBucket(*bucket); + + return static_cast(helper->Update(uriObj, *pred, dataShareValuesBucket)); +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + LOG_ERROR("Unsupported ANI_VERSION_1"); + return ANI_ERROR; + } + + ani_namespace ns; + if (!getNameSpace(env, ns)) { + return ANI_ERROR; + } + + std::array functions = { + ani_native_function {"create", nullptr, reinterpret_cast(ANI_Create)}, + }; + + if (ANI_OK != env->Namespace_BindNativeFunctions(ns, functions.data(), functions.size())) { + LOG_ERROR("Cannot bind native functions to namespace"); + return ANI_ERROR; + } + + std::array methods = { + ani_native_function {"on", "Lstd/core/String;Lstd/core/String;Lstd/core/Function2;:V", + reinterpret_cast(ANI_OnType)}, + ani_native_function {"off", "Lstd/core/String;Lstd/core/String;Lstd/core/Function2;:V", + reinterpret_cast(ANI_OffType)}, + ani_native_function {"on", + "Lstd/core/String;L@ohos/data/dataShare/dataShare/SubscriptionType;Lstd/core/String;Lstd/core/Function2;:V", + reinterpret_cast(ANI_OnEvent)}, + ani_native_function {"off", + "Lstd/core/String;L@ohos/data/dataShare/dataShare/SubscriptionType;Lstd/core/String;Lstd/core/Function2;:V", + reinterpret_cast(ANI_OffEvent)}, + ani_native_function {"ani_query", nullptr, reinterpret_cast(ANI_Query)}, + ani_native_function {"ani_update", nullptr, reinterpret_cast(ANI_Update)}, + }; + + ani_class cls; + if (!getClass(env, cls)) { + return ANI_ERROR; + } + + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + LOG_ERROR("Cannot bind native methods to class"); + return ANI_ERROR; + } + + static const char *cleanerName = "LCleaner;"; + auto cleanerCls = AniTypeFinder(env).FindClass(ns, cleanerName); + NativePtrCleaner(env).Bind(cleanerCls.value()); + + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/data_share/frameworks/js/ani/dataShare/src/ani_datashare_inner_observer.cpp b/data_share/frameworks/js/ani/dataShare/src/ani_datashare_inner_observer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b81867b912ebf28c76870032a248095fd3660f57 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/src/ani_datashare_inner_observer.cpp @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2025 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 +#include + +#include "ani_utils.h" +#include "datashare_valuebucket_convert.h" +#include "ani_datashare_observer.h" + +namespace OHOS { +namespace DataShare { +using namespace std::chrono; +ANIInnerObserver::ANIInnerObserver(ani_vm *vm, ani_ref callback) : vm_(vm), callback_(callback) +{ +} + +ANIInnerObserver::~ANIInnerObserver() +{ + vm_->DetachCurrentThread(); +} + +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, const std::monostate &value) +{ + (void)env; + (void)value; + return nullptr; +} + +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, const std::string &value) +{ + return StringToObject(env, value); +} + +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, const std::vector &values) +{ + return Uint8ArrayToObject(env, values); +} + +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, int64_t value) +{ + return DoubleToObject(env, value); +} + +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, double value) +{ + return DoubleToObject(env, value); +} + +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, bool value) +{ + return BoolToObject(env, value); +} + +template +ani_object ANIInnerObserver::ReadVariant(ani_env *env, size_t step, size_t index, const _VTp &value) +{ + return nullptr; +} + +template +ani_object ANIInnerObserver::ReadVariant(ani_env *env, size_t step, size_t index, const _VTp &value) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return nullptr; + } + if (step == index) { + auto *realValue = std::get_if<_First>(&value); + if (realValue == nullptr) { + return nullptr; + } + + return Convert2TSValue(env, *realValue); + } + + return ReadVariant<_VTp, _Rest...>(env, step + 1, index, value); +} + +template +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, const std::variant &value) +{ + return ReadVariant(env, 0, value.index(), value); +} + +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, const DataShareValuesBucket &valueBucket) +{ + ani_object valuesBucketList = nullptr; + static const char *className = "Lescompat/Record;"; + + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + LOG_ERROR("Not found '%{public}s'.", className); + return valuesBucketList; + } + + ani_method aniCtor; + if (ANI_OK != env->Class_FindMethod(cls, "", ":V", &aniCtor)) { + LOG_ERROR("Class_GetMethod Failed '%{public}s'.", className); + return valuesBucketList; + } + + if (ANI_OK != env->Object_New(cls, aniCtor, &valuesBucketList)) { + LOG_ERROR("Object_New Failed '%{public}s'.", className); + return valuesBucketList; + } + + ani_method setter; + if (ANI_OK != env->Class_FindMethod(cls, "$_set", nullptr, &setter)) { + LOG_ERROR("Class_GetMethod set Failed '%{public}s'.", className); + return valuesBucketList; + } + + const auto &valuesMap = valueBucket.valuesMap; + for (auto& value : valuesMap) { + ani_string aniKey = AniStringUtils::ToAni(env, value.first); + ani_object aniObjVal = Convert2TSValue(env, value.second); + if (ANI_OK != env->Object_CallMethod_Void(valuesBucketList, setter, aniKey, aniObjVal)) { + LOG_ERROR("Object_CallMethodByName_Void $_set Faild "); + break; + } + } + + return valuesBucketList; +} + +template +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, const std::vector &values) +{ + ani_class arrayCls; + if (ANI_OK != env->FindClass("Lescompat/Array;", &arrayCls)) { + LOG_ERROR("FindClass Lescompat/Array; Failed"); + return nullptr; + } + + ani_method arrayCtor; + if (ANI_OK != env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor)) { + LOG_ERROR("Class_FindMethod Failed"); + return nullptr; + } + + ani_object arrayObj; + if (ANI_OK != env->Object_New(arrayCls, arrayCtor, &arrayObj, values.size())) { + LOG_ERROR("Object_New Array Faild"); + return nullptr; + } + + ani_size index = 0; + for (auto value : values) { + if (ANI_OK != env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, + Convert2TSValue(env, value))) { + LOG_ERROR("Object_CallMethodByName_Void $_set Faild "); + break; + } + + index++; + } + + return arrayObj; +} + +ani_enum_item ANIInnerObserver::GetEnumItem(ani_env *env, int32_t type) +{ + ani_namespace ns; + static const char *namespaceName = "L@ohos/data/dataShare/dataShare;"; + if (ANI_OK != env->FindNamespace(namespaceName, &ns)) { + LOG_ERROR("Not found '%{public}s'", namespaceName); + return nullptr; + } + + ani_enum aniEnum{}; + const char *enumName = "LChangeType;"; + if (ANI_OK != env->Namespace_FindEnum(ns, enumName, &aniEnum)) { + LOG_ERROR("Not found '%{public}s'", enumName); + return nullptr; + } + + int32_t index = 0U; + ani_enum_item enumItem{}; + while (ANI_OK == env->Enum_GetEnumItemByIndex(aniEnum, index++, &enumItem)) { + ani_int intValue = -1; + if (ANI_OK != env->EnumItem_GetValue_Int(enumItem, &intValue)) { + LOG_ERROR("EnumItem_GetValue_Int failed."); + return nullptr; + } + + if (intValue == type) { + return enumItem; + } + } + + LOG_ERROR("Get enumItem by %{public}d failed.", type); + return nullptr; +} + +ani_object ANIInnerObserver::GetNewChangeInfo(ani_env *env) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return nullptr; + } + ani_namespace ns; + const char *spaceName = "L@ohos/data/dataShare/dataShare;"; + if (ANI_OK != env->FindNamespace(spaceName, &ns)) { + LOG_ERROR("Not found space name '%{public}s'", spaceName); + return nullptr; + } + + ani_class cls; + const char *className = "LChangeInfoInner;"; + if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) { + LOG_ERROR("Not found class name '%{public}s'", className); + return nullptr; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + LOG_ERROR("Get ctor Failed"); + return nullptr; + } + + ani_object object; + if (ANI_OK != env->Object_New(cls, ctor, &object)) { + LOG_ERROR("Create GetNewChangeInfo Object Failed"); + return nullptr; + } + + return object; +} + +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, const DataShareObserver::ChangeInfo& changeInfo) +{ + ani_object infoObj = GetNewChangeInfo(env); + if (infoObj == nullptr) { + LOG_ERROR("Create ts new ChangeInfo object failed!"); + return nullptr; + } + + ani_enum_item aniType = GetEnumItem(env, ANIDataShareObserver::UPDATE); + if (aniType == nullptr) { + LOG_ERROR("GetEnumItem failed"); + return nullptr; + } + + ani_status status = env->Object_SetPropertyByName_Ref(infoObj, "type", aniType); + if (ANI_OK != status) { + LOG_ERROR("Object_SetFieldByName_Int failed status : %{public}d", status); + return nullptr; + } + + ani_string uri; + env->String_NewUTF8(changeInfo.uris_.front().ToString().c_str(), changeInfo.uris_.front().ToString().size(), &uri); + status = env->Object_SetPropertyByName_Ref(infoObj, "uri", uri); + if (ANI_OK != status) { + LOG_ERROR("Object_SetPropertyByName_Ref failed status : %{public}d", status); + return nullptr; + } + + auto &valBucket = const_cast(changeInfo); + std::vector VBuckets = ValueProxy::Convert(std::move(valBucket.valueBuckets_)); + ani_object valueBuckets = Convert2TSValue(env, VBuckets); + status = env->Object_SetPropertyByName_Ref(infoObj, "values", valueBuckets); + if (ANI_OK != status) { + LOG_ERROR("Object_SetPropertyByName_Ref failed status : %{public}d", status); + return nullptr; + } + + return infoObj; +} + +void ANIInnerObserver::OnChange(const DataShareObserver::ChangeInfo& changeInfo, bool isNotifyDetails) +{ + auto time = static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); + LOG_INFO("ANIInnerObserver datashare callback start, times %{public}" PRIu64 ".", time); + if (callback_ == nullptr) { + LOG_ERROR("callback_ is nullptr"); + return; + } + + ani_env *env = nullptr; + ani_options aniArgs {0, nullptr}; + if (ANI_ERROR == vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env)) { + if (ANI_OK != vm_->GetEnv(ANI_VERSION_1, &env)) { + LOG_ERROR("GetEnv failed"); + return; + } + } + + ani_ref result; + auto fnObj = reinterpret_cast(callback_); + if (fnObj == nullptr) { + LOG_ERROR("%{public}s: fnObj == nullptr", __func__); + return; + } + + std::vector args = { nullptr }; + if (isNotifyDetails) { + auto argsObj = Convert2TSValue(env, changeInfo); + if (argsObj == nullptr) { + LOG_ERROR("%{public}s: argsObj is null", __func__); + return; + } + + args.push_back(argsObj); + } + + ani_status callStatus = env->FunctionalObject_Call(fnObj, args.size(), args.data(), &result); + if (ANI_OK != callStatus) { + LOG_ERROR("ani_call_function failed status : %{public}d", callStatus); + return; + } + + LOG_INFO("ANIInnerObserver datashare callback end, times %{public}" PRIu64 ".", time); +} + +ani_ref ANIInnerObserver::GetCallback() +{ + return callback_; +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/js/ani/dataShare/src/ani_datashare_observer.cpp b/data_share/frameworks/js/ani/dataShare/src/ani_datashare_observer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c2e8c761ed6b4fcb72292aa11591d7b87bcf69fb --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/src/ani_datashare_observer.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 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 "ANIDataShareObserver" + +#include "ani_datashare_observer.h" + +#include "adaptor.h" +#include +#include "datashare_log.h" + +namespace OHOS { +namespace DataShare { +ANIDataShareObserver::~ANIDataShareObserver() {} + +void ANIDataShareObserver::OnChange() +{ + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); + observer_->OnChange(); +} + +void ANIDataShareObserver::OnChange(const ChangeInfo &changeInfo) +{ + LOG_DEBUG("ANIDataShareObserver ChangeInfo Start"); + observer_->OnChange(changeInfo, true); +} +} // namespace DataShare +} // namespace OHOS diff --git a/data_share/frameworks/js/ani/dataShare/src/data_share_predicates.cpp b/data_share/frameworks/js/ani/dataShare/src/data_share_predicates.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04a2df09b1e7b3331570412b5c0ebeb7efaec469 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/src/data_share_predicates.cpp @@ -0,0 +1,431 @@ +/* + * Copyright (c) 2025 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 +#include +#include "ani_utils.h" +#include "datashare_log.h" +#include "datashare_predicates_cleaner.h" + +using namespace OHOS::DataShare; + +static DataSharePredicates* unwrapp(ani_env *env, ani_object object) +{ + DataSharePredicates *holder = AniObjectUtils::Unwrap(env, object); + if (holder == nullptr) { + LOG_ERROR("holder is nullptr"); + return nullptr; + } + return holder; +} + +static ani_long Create([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class clazz) +{ + auto holder = new DataSharePredicates(); + return reinterpret_cast(holder); +} + +static ani_object EqualTo([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_string field, + ani_object value) +{ + auto stringContentOne = AniStringUtils::ToStd(env, field); + + auto dataSharePredicates = unwrapp(env, object); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + UnionAccessor unionAccessor(env, value); + double fValue = 0.0; + if (unionAccessor.TryConvert(fValue)) { + dataSharePredicates->EqualTo(stringContentOne, fValue); + } + + std::string strValue = ""; + if (unionAccessor.TryConvert(strValue)) { + dataSharePredicates->EqualTo(stringContentOne, strValue); + } + + bool boolValue = false; + if (unionAccessor.TryConvert(boolValue)) { + dataSharePredicates->EqualTo(stringContentOne, boolValue); + } + + return object; +} + +static ani_object NotEqualTo([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_string field, + ani_object value) +{ + auto stringContentOne = AniStringUtils::ToStd(env, field); + + auto dataSharePredicates = unwrapp(env, object); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + UnionAccessor unionAccessor(env, value); + double fValue = 0.0; + if (unionAccessor.TryConvert(fValue)) { + dataSharePredicates->NotEqualTo(stringContentOne, fValue); + } + + std::string strValue = ""; + if (unionAccessor.TryConvert(strValue)) { + dataSharePredicates->NotEqualTo(stringContentOne, strValue); + } + + bool boolValue = false; + if (unionAccessor.TryConvert(boolValue)) { + dataSharePredicates->NotEqualTo(stringContentOne, boolValue); + } + return object; +} + +static ani_object OrderByDesc([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_string field) +{ + auto stringContent = AniStringUtils::ToStd(env, field); + auto dataSharePredicates = unwrapp(env, object); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->OrderByDesc(stringContent); + return object; +} + +static ani_object OrderByAsc([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_string field) +{ + auto stringContent = AniStringUtils::ToStd(env, field); + auto dataSharePredicates = unwrapp(env, object); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->OrderByAsc(stringContent); + return object; +} + +static ani_object And([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) +{ + auto dataSharePredicates = unwrapp(env, object); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->And(); + return object; +} + +static ani_object Limit([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_double total, + ani_double offset) +{ + auto dataSharePredicates = unwrapp(env, object); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->Limit(total, offset); + return object; +} + +static ani_object LessThan([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_string field, + ani_object value) +{ + auto fieldStr = AniStringUtils::ToStd(env, field); + + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + UnionAccessor unionAccessor(env, value); + double fValue = 0.0; + if (unionAccessor.TryConvert(fValue)) { + dataSharePredicates->LessThan(fieldStr, fValue); + } + + std::string strValue = ""; + if (unionAccessor.TryConvert(strValue)) { + dataSharePredicates->LessThan(fieldStr, strValue); + } + + bool boolValue = false; + if (unionAccessor.TryConvert(boolValue)) { + dataSharePredicates->LessThan(fieldStr, boolValue); + } + return obj; +} + +static ani_object Like([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_string field, + ani_string value) +{ + auto fieldStr = AniStringUtils::ToStd(env, field); + auto valueStr = AniStringUtils::ToStd(env, value); + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->Like(fieldStr, valueStr); + return obj; +} + +static ani_object EndWrap([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj) +{ + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->EndWrap(); + return obj; +} + +static ani_object GreaterThanOrEqualTo([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, + ani_string field, ani_object value) +{ + auto fieldStr = AniStringUtils::ToStd(env, field); + + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + UnionAccessor unionAccessor(env, value); + double fValue = 0.0; + if (unionAccessor.TryConvert(fValue)) { + std::cout << "Double value is " << fValue << std::endl; + dataSharePredicates->GreaterThanOrEqualTo(fieldStr, fValue); + } + + std::string strValue = ""; + if (unionAccessor.TryConvert(strValue)) { + std::cout << "String value is " << strValue << std::endl; + dataSharePredicates->GreaterThanOrEqualTo(fieldStr, strValue); + } + + bool boolValue = false; + if (unionAccessor.TryConvert(boolValue)) { + std::cout << "Boolean value is " << boolValue << std::endl; + dataSharePredicates->GreaterThanOrEqualTo(fieldStr, boolValue); + } + return obj; +} + +static ani_object Contains([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_string field, + ani_string value) +{ + auto fieldStr = AniStringUtils::ToStd(env, field); + auto valueStr = AniStringUtils::ToStd(env, value); + + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->Contains(fieldStr, valueStr); + return obj; +} + +static ani_object Or([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj) +{ + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->Or(); + return obj; +} + +static ani_object BeginWrap([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj) +{ + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->BeginWrap(); + return obj; +} + +static ani_object GreaterThan([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_string field, + ani_object value) +{ + auto fieldStr = AniStringUtils::ToStd(env, field); + + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + UnionAccessor unionAccessor(env, value); + ani_double valueD = 0.0; + if (unionAccessor.TryConvert(valueD)) { + dataSharePredicates->GreaterThan(fieldStr, static_cast(valueD)); + } + + ani_string strValue = nullptr; + if (unionAccessor.IsInstanceOf("Lstd/core/String;")) { + dataSharePredicates->GreaterThan(fieldStr, AniStringUtils::ToStd(env, strValue)); + } + + ani_boolean boolValue = 0; + if (unionAccessor.IsInstanceOf("Lstd/core/Boolean;")) { + if (ANI_OK != env->Object_CallMethodByName_Boolean(value, "unboxed", nullptr, &boolValue)) { + dataSharePredicates->GreaterThan(fieldStr, static_cast(boolValue)); + } + } + + return obj; +} + +static ani_object GroupBy([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_object arrayObj) +{ + ani_double length; + + if (ANI_OK != env->Object_GetPropertyByName_Double(arrayObj, "length", &length)) { + return obj; + } + + std::vector strings; + for (int i = 0; i < int(length); i++) { + ani_ref stringEntryRef; + if (ANI_OK != env->Object_CallMethodByName_Ref(arrayObj, "$_get", "I:Lstd/core/Object;", &stringEntryRef, + (ani_int)i)) { + return obj; + } + strings.emplace_back(AniStringUtils::ToStd(env, static_cast(stringEntryRef))); + } + + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->GroupBy(strings); + return obj; +} + +static ani_object In([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_string fieldStr, + ani_object arrayObj) +{ + UnionAccessor unionAccessor(env, arrayObj); + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + auto stringContent = AniStringUtils::ToStd(env, static_cast(fieldStr)); + std::vector arrayDoubleValues = {}; + if (unionAccessor.TryConvertArray(arrayDoubleValues) && arrayDoubleValues.size() > 0) { + std::vector values = convertVector(arrayDoubleValues); + dataSharePredicates->In(stringContent, values); + } + std::vector arrayStringValues = {}; + if (unionAccessor.TryConvertArray(arrayStringValues) && arrayStringValues.size() > 0) { + dataSharePredicates->In(stringContent, arrayStringValues); + } + std::vector arrayBoolValues = {}; + if (unionAccessor.TryConvertArray(arrayBoolValues) && arrayBoolValues.size() > 0) { + std::vector values = convertVector(arrayBoolValues); + dataSharePredicates->In(stringContent, values); + } + return obj; +} + +static ani_object NotIn([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_string fieldStr, + ani_object arrayObj) +{ + UnionAccessor unionAccessor(env, arrayObj); + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + auto stringContent = AniStringUtils::ToStd(env, static_cast(fieldStr)); + std::vector arrayDoubleValues = {}; + if (unionAccessor.TryConvertArray(arrayDoubleValues) && arrayDoubleValues.size() > 0) { + std::vector values = convertVector(arrayDoubleValues); + dataSharePredicates->NotIn(stringContent, values); + } + std::vector arrayStringValues = {}; + if (unionAccessor.TryConvertArray(arrayStringValues) && arrayStringValues.size() > 0) { + dataSharePredicates->NotIn(stringContent, arrayStringValues); + } + std::vector arrayBoolValues = {}; + if (unionAccessor.TryConvertArray(arrayBoolValues) && arrayBoolValues.size() > 0) { + std::vector values = convertVector(arrayBoolValues); + dataSharePredicates->NotIn(stringContent, values); + } + return obj; +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + LOG_INFO("ANI_Constructor enter "); + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + std::cerr << "Unsupported ANI_VERSION_1" << std::endl; + return ANI_ERROR; + } + ani_namespace ns; + if (env->FindNamespace("L@ohos/data/dataSharePredicates/dataSharePredicates;", &ns) != ANI_OK) { + LOG_ERROR("Namespace not found"); + return ANI_ERROR; + }; + + ani_class cls; + static const char *className = "LDataSharePredicates;"; + if (env->Namespace_FindClass(ns, className, &cls) != ANI_OK) { + LOG_ERROR("Class not found"); + return ANI_ERROR; + } + + std::array methods = { + ani_native_function {"create", nullptr, reinterpret_cast(Create) }, + ani_native_function {"equalTo", nullptr, reinterpret_cast(EqualTo)}, + ani_native_function {"notEqualTo", nullptr, reinterpret_cast(NotEqualTo)}, + ani_native_function {"orderByDesc", nullptr, reinterpret_cast(OrderByDesc)}, + ani_native_function {"orderByAsc", nullptr, reinterpret_cast(OrderByAsc)}, + ani_native_function {"and", nullptr, reinterpret_cast(And)}, + ani_native_function {"limit", nullptr, reinterpret_cast(Limit)}, + ani_native_function {"lessThan", nullptr, reinterpret_cast(LessThan)}, + ani_native_function {"like", nullptr, reinterpret_cast(Like)}, + ani_native_function {"endWrap", nullptr, reinterpret_cast(EndWrap)}, + ani_native_function {"greaterThanOrEqualTo", nullptr, reinterpret_cast(GreaterThanOrEqualTo)}, + ani_native_function {"contains", nullptr, reinterpret_cast(Contains)}, + ani_native_function {"or", nullptr, reinterpret_cast(Or)}, + ani_native_function {"beginWrap", nullptr, reinterpret_cast(BeginWrap)}, + ani_native_function {"greaterThan", nullptr, reinterpret_cast(GreaterThan)}, + ani_native_function {"groupBy", nullptr, reinterpret_cast(GroupBy)}, + ani_native_function {"in", nullptr, reinterpret_cast(In)}, + ani_native_function {"notIn", nullptr, reinterpret_cast(NotIn)}, + }; + + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + LOG_ERROR("Cannot bind native methods to %{public}s", className); + return ANI_ERROR; + }; + + static const char *cleanerName = "LCleaner;"; + auto cleanerCls = AniTypeFinder(env).FindClass(ns, cleanerName); + DataSharePredicatesCleaner(env).Bind(cleanerCls.value()); + + *result = ANI_VERSION_1; + return ANI_OK; +} diff --git a/data_share/frameworks/js/ani/dataShareResultSet/BUILD.gn b/data_share/frameworks/js/ani/dataShareResultSet/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..e0ef78712a95f70b23b9626ef1fd8ef75c8fac45 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShareResultSet/BUILD.gn @@ -0,0 +1,71 @@ +# Copyright (c) 2025 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/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/distributeddatamgr/data_share/datashare.gni") + +ohos_shared_library("data_share_result_set") { + sanitize = { + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + sources = [ + "${datashare_ani_path}/common/src/ani_utils.cpp", + "./src/data_share_result_set.cpp" + ] + include_dirs = [ + "${datashare_ani_path}/common/include", + "${datashare_innerapi_path}/consumer/include", + "${datashare_innerapi_path}/provider/include", + "${datashare_common_native_path}/include", + ] + deps = [ "${datashare_innerapi_path}/common:datashare_common" ] + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "runtime_core:ani", + ] + subsystem_name = "distributeddatamgr" + part_name = "data_share" + output_extension = "so" +} + +generate_static_abc("data_share_result_set_abc") { + base_url = "./ets" + files = [ "./ets/@ohos.data.DataShareResultSet.ets" ] + dst_file = "$target_out_dir/data_share_result_set.abc" + out_puts = [ "$target_out_dir/data_share_result_set.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/data_share_result_set.abc" +} + +ohos_prebuilt_etc("data_share_result_set_abc_etc") { + source = "$target_out_dir/data_share_result_set.abc" + module_install_dir = "framework" + subsystem_name = "distributeddatamgr" + part_name = "data_share" + deps = [ ":data_share_result_set_abc" ] +} + +group("datashareresultset") { + deps = [ + ":data_share_result_set", + ":data_share_result_set_abc_etc", + ] +} diff --git a/data_share/frameworks/js/ani/dataShareResultSet/ets/@ohos.data.DataShareResultSet.ets b/data_share/frameworks/js/ani/dataShareResultSet/ets/@ohos.data.DataShareResultSet.ets new file mode 100644 index 0000000000000000000000000000000000000000..5443da0087c7b49431c33aaf9192ec78b6ac6e15 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShareResultSet/ets/@ohos.data.DataShareResultSet.ets @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 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. + */ + + + +export default interface DataShareResultSet { + close(): void + getColumnIndex(columnName: string): number; + getString(columnIndex: number): string; + goToFirstRow(): boolean; + rowCount:number; +} + +class DataShareResultSetImpl implements DataShareResultSet { + + static {loadLibrary("data_share_result_set")} + private nativePtr: long = 0; + + private clearNativePtr(): void { + this.nativePtr = 0; + } + + constructor(nativePtr: long) { + this.nativePtr = nativePtr; + } + native close(): void; + native getColumnIndex(columnName: string): number; + native getString(columnIndex: number): string; + native goToFirstRow(): boolean; + native getRowCount(): number; + get rowCount(): number { + return this.getRowCount(); + } + + set rowCount(value: number) { + this.rowCount = value; + } +} diff --git a/data_share/frameworks/js/ani/dataShareResultSet/src/data_share_result_set.cpp b/data_share/frameworks/js/ani/dataShareResultSet/src/data_share_result_set.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ada79057aa131c459747a799433236406afcb388 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShareResultSet/src/data_share_result_set.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2025 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 +#include +#include +#include +#include +#include + +#include "datashare_errno.h" +#include "datashare_log.h" +#include "datashare_result_set.h" + +using namespace OHOS::DataShare; + +static std::shared_ptr GetResultSet(ani_env *env, ani_object obj) +{ + auto holder = AniObjectUtils::Unwrap>(env, obj); + if (holder == nullptr) { + LOG_ERROR("SharedPtrHolder is NULL"); + return nullptr; + } + if (holder->Get() == nullptr) { + LOG_ERROR("Holder shared_ptr is NULL"); + return nullptr; + } + + return holder->Get(); +} + +static void Close([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj) +{ + static const char *className = "L@ohos/data/DataShareResultSet/DataShareResultSetImpl;"; + auto classObj = GetResultSet(env, obj); + if (classObj == nullptr) { + LOG_ERROR("DataShareResultSet is NULL"); + return; + } + int errCode = classObj->Close(); + if (errCode != E_OK) { + LOG_ERROR("failed code:%{public}d", errCode); + } + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + LOG_ERROR("[ANI] Not found class %{public}s", className); + return; + } + + ani_method setNaptr; + if (ANI_OK != env->Class_FindMethod(cls, "clearNativePtr", nullptr, &setNaptr)) { + LOG_ERROR("[ANI] Not found clearNativePtr for class %{public}s", className); + return; + } + + if (ANI_OK != env->Object_CallMethod_Void(obj, setNaptr)) { + LOG_ERROR("[ANI] Object_CallMethod_Void failed"); + return; + } + return; +} + +static ani_double GetColumnIndex([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_string columnName) +{ + int32_t columnIndex = -1; + if (columnName == nullptr) { + return static_cast(columnIndex); + } + auto columnNameStr = AniStringUtils::ToStd(env, columnName); + + auto classObj = GetResultSet(env, obj); + if (classObj == nullptr) { + LOG_ERROR("DataShareResultSet is NULL"); + return static_cast(columnIndex); + } + int errCode = classObj->GetColumnIndex(columnNameStr, columnIndex); + if (errCode != E_OK) { + auto time = static_cast(std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count()); + LOG_ERROR("failed code:%{public}d columnIndex: %{public}d. times %{public}" PRIu64 ".", errCode, columnIndex, + time); + } + return static_cast(columnIndex); +} + +static ani_string GetString([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_double columnIndex) +{ + std::string value; + double columnIndexD = static_cast(columnIndex); + auto classObj = GetResultSet(env, obj); + if (classObj == nullptr) { + LOG_ERROR("DataShareResultSet is NULL"); + return nullptr; + } + classObj->GetString(columnIndexD, value); + return AniStringUtils::ToAni(env, value); +} + +static bool GoToFirstRow([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj) +{ + auto classObj = GetResultSet(env, obj); + if (classObj == nullptr) { + LOG_ERROR("DataShareResultSet is NULL"); + return false; + } + + int errCode = classObj->GoToFirstRow(); + if (errCode != E_OK) { + LOG_ERROR("failed code:%{public}d", errCode); + return false; + } + return true; +} + +static ani_double GetRowCount([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj) +{ + int32_t count = -1; + auto classObj = GetResultSet(env, obj); + if (classObj == nullptr) { + LOG_ERROR("DataShareResultSet is NULL"); + return static_cast(count); + } + classObj->GetRowCount(count); + return static_cast(count); +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + LOG_INFO("enter ANI_Constructor func"); + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + LOG_ERROR("Unsupported ANI_VERSION_1"); + return ANI_ERROR; + } + + ani_class cls; + static const char *className = "L@ohos/data/DataShareResultSet/DataShareResultSetImpl;"; + if (ANI_OK != env->FindClass(className, &cls)) { + LOG_ERROR("Not found class:%{public}s", className); + return ANI_ERROR; + } + + std::array methods = { + ani_native_function {"close", nullptr, reinterpret_cast(Close)}, + ani_native_function {"getColumnIndex", nullptr, reinterpret_cast(GetColumnIndex)}, + ani_native_function {"getString", nullptr, reinterpret_cast(GetString)}, + ani_native_function {"goToFirstRow", nullptr, reinterpret_cast(GoToFirstRow)}, + ani_native_function {"getRowCount", nullptr, reinterpret_cast(GetRowCount)}, + }; + + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + LOG_ERROR("Cannot bind native methods to {%public}s", className); + return ANI_ERROR; + }; + + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/data_share/frameworks/js/napi/common/include/datashare_error.h b/data_share/frameworks/js/napi/common/include/datashare_error.h index 44855d27ce7ab9d8e14a394a03570c88f422bfa5..cf537a37d3828b471625a2e6de2ae0da4ad3d71d 100644 --- a/data_share/frameworks/js/napi/common/include/datashare_error.h +++ b/data_share/frameworks/js/napi/common/include/datashare_error.h @@ -29,6 +29,7 @@ public: static const int EXCEPTION_URI_NOT_EXIST = 15700011; static const int EXCEPTION_DATA_AREA_NOT_EXIST = 15700012; static const int EXCEPTION_HELPER_CLOSED = 15700013; + static const int EXCEPTION_PROXY_PARAMETER_CHECK = 15700014; virtual ~Error() {}; virtual std::string GetMessage() const = 0; virtual int GetCode() const = 0; diff --git a/data_share/frameworks/js/napi/common/include/datashare_error_impl.h b/data_share/frameworks/js/napi/common/include/datashare_error_impl.h index f98ba0fcbbda02feeef5145555d311bd9a1f5f69..e948be3d90b21e7ec067c8f5e2ba2d100d7b7e92 100644 --- a/data_share/frameworks/js/napi/common/include/datashare_error_impl.h +++ b/data_share/frameworks/js/napi/common/include/datashare_error_impl.h @@ -39,6 +39,13 @@ private: std::string wantNum; }; +class DataProxyHandleParamError : public Error { +public: + DataProxyHandleParamError() = default; + std::string GetMessage() const override; + int GetCode() const override; +}; + class DataShareHelperInitError : public Error { public: DataShareHelperInitError() = default; diff --git a/data_share/frameworks/js/napi/common/include/datashare_js_utils.h b/data_share/frameworks/js/napi/common/include/datashare_js_utils.h index 406c3ccf16de399e5a49391710e7ff25c1314eee..2daab378e6aa59b52673b8584e0b56a6cfafab43 100644 --- a/data_share/frameworks/js/napi/common/include/datashare_js_utils.h +++ b/data_share/frameworks/js/napi/common/include/datashare_js_utils.h @@ -27,6 +27,7 @@ #include "datashare_template.h" #include "datashare_value_object.h" #include "napi/native_api.h" +#include "dataproxy_handle_common.h" #define NAPI_ASSERT_ERRCODE(env, assertion, error) \ do { \ @@ -85,6 +86,7 @@ public: static int32_t Convert2Value(napi_env env, napi_value input, DataShareValuesBucket &valueBucket); static int32_t Convert2Value(napi_env env, napi_value input, UpdateOperation &operation); static int32_t Convert2Value(napi_env env, napi_value input, DataShareObserver::ChangeInfo &changeInfo); + static int32_t Convert2Value(napi_env env, napi_value input, DataProxyType &proxyType); static std::string Convert2String(napi_env env, napi_value jsStr, size_t max = DEFAULT_BUF_SIZE); static std::vector Convert2StrVector(napi_env env, napi_value value, size_t strMax); static std::vector Convert2U8Vector(napi_env env, napi_value jsValue); @@ -94,6 +96,7 @@ public: static Template Convert2Template(napi_env env, napi_value value); static TemplateId Convert2TemplateId(napi_env env, napi_value value); static Data Convert2PublishedData(napi_env env, napi_value value); + static std::vector Convert2ProxyData(napi_env env, napi_value value); static napi_value Convert2JSValue(napi_env env, const std::monostate &value = {}); static napi_value Convert2JSValue(napi_env env, const std::vector &value); @@ -114,6 +117,12 @@ public: static napi_value Convert2JSValue(napi_env env, PublishedDataChangeNode &changeNode); static napi_value Convert2JSValue(napi_env env, const OperationResult &results); static napi_value Convert2JSValue(napi_env env, const std::vector &results); + static napi_value Convert2JSValue(napi_env env, const DataProxyResult &result); + static napi_value Convert2JSValue(napi_env env, const std::vector &results); + static napi_value Convert2JSValue(napi_env env, const DataProxyGetResult &result); + static napi_value Convert2JSValue(napi_env env, const std::vector &results); + static napi_value Convert2JSValue(napi_env env, const DataShareValueObject &valueObject); + static napi_value Convert2JSValue(napi_env env, const DataProxyChangeInfo &changeInfo); static napi_value Convert2JSValue(napi_env env, const DataShareValuesBucket &valueBucket); static std::vector ConvertU8Vector(napi_env env, napi_value jsValue); static napi_value Convert2JSValue(napi_env env, const DataShareObserver::ChangeInfo &changeInfo); @@ -128,6 +137,10 @@ public: std::vector &predicates); static bool UnwrapStringByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, std::string &value); + static bool UnwrapDataProxyValue(napi_env env, napi_value jsObject, DataProxyValue &value, bool &isValueUndefined); + static bool UnwrapProxyDataItem(napi_env env, napi_value jsObject, DataShareProxyData &proxyData); + static bool UnwrapProxyDataItemVector(napi_env env, napi_value value, std::vector &proxyDatas); + static bool UnwrapDataProxyConfig(napi_env env, napi_value value, DataProxyConfig &config); static bool IsArrayForNapiValue(napi_env env, napi_value param, uint32_t &arraySize); private: template @@ -156,7 +169,7 @@ private: template napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const std::variant &value) { - return ReadVariant(env, 0, value.index(), value); + return ReadVariant(env, 0, static_cast(value.index()), value); } template diff --git a/data_share/frameworks/js/napi/common/include/napi_callbacks_manager.h b/data_share/frameworks/js/napi/common/include/napi_callbacks_manager.h index 1cf38af51975854be9a432a3ede86bdf1241be98..0b7190accc627266eb45b47c43bbdd8abcc5eed7 100644 --- a/data_share/frameworks/js/napi/common/include/napi_callbacks_manager.h +++ b/data_share/frameworks/js/napi/common/include/napi_callbacks_manager.h @@ -21,6 +21,7 @@ #include "datashare_errno.h" #include "datashare_template.h" +#include "dataproxy_handle_common.h" namespace OHOS::DataShare { template @@ -31,11 +32,20 @@ public: std::function &, const std::shared_ptr &observer, std::vector &)>); + std::vector AddObservers(const std::vector &keys, const std::shared_ptr observer, + std::function &, const std::shared_ptr &observer, + std::vector &)>); + std::vector DelObservers(const std::vector &keys, const std::shared_ptr observer = nullptr, std::function &, const std::shared_ptr &observer, std::vector &)> processOnLastDel = NapiCallbacksManager::DefaultProcess); + std::vector DelObservers(const std::vector &keys, + const std::shared_ptr observer, + std::function &, const std::shared_ptr &observer, + std::vector &)> processOnLastDel); + std::vector> GetEnabledObservers(const Key &); int GetEnabledSubscriberSize(); @@ -93,6 +103,35 @@ std::vector NapiCallbacksManager::AddObservers( return result; } +template +std::vector NapiCallbacksManager::AddObservers( + const std::vector &keys, const std::shared_ptr observer, + std::function &, const std::shared_ptr &observer, + std::vector &)> processOnFirstAdd) +{ + std::vector result; + std::vector firstRegisterKey; + { + std::lock_guard lck(mutex_); + for (auto &key : keys) { + std::vector> enabledObservers = GetEnabledObservers(key); + if (enabledObservers.empty()) { + callbacks_[key].emplace_back(ObserverNode(observer)); + firstRegisterKey.emplace_back(key); + continue; + } + if (IsRegistered(*observer, callbacks_[key])) { + result.emplace_back(static_cast(key), SUCCESS); + continue; + } + callbacks_[key].emplace_back(observer); + result.emplace_back(key, SUCCESS); + } + } + processOnFirstAdd(firstRegisterKey, observer, result); + return result; +} + template bool NapiCallbacksManager::IsRegistered(const Observer &observer, const std::vector &observers) @@ -160,6 +199,61 @@ std::vector NapiCallbacksManager::DelObservers( return result; } +template +std::vector NapiCallbacksManager::DelObservers( + const std::vector &keys, const std::shared_ptr observer, + std::function &, const std::shared_ptr &, std::vector &)> + processOnLastDel) +{ + std::vector result; + std::vector lastDelKeys; + { + std::lock_guard lck(mutex_); + if (keys.empty() && observer == nullptr) { + for (auto &it : callbacks_) { + lastDelKeys.emplace_back(it.first); + } + callbacks_.clear(); + } + for (auto &key : keys) { + auto it = callbacks_.find(key); + if (it == callbacks_.end()) { + result.emplace_back(key, URI_NOT_EXIST); + continue; + } + if (observer == nullptr) { + callbacks_.erase(key); + lastDelKeys.emplace_back(key); + continue; + } + if (!IsRegistered(*observer, it->second)) { + result.emplace_back(key, URI_NOT_EXIST); + continue; + } + std::vector &callbacks = it->second; + auto callbackIt = callbacks.begin(); + while (callbackIt != callbacks.end()) { + if (!(*(callbackIt->observer_) == *observer)) { + callbackIt++; + continue; + } + callbackIt = callbacks.erase(callbackIt); + } + if (!it->second.empty()) { + result.emplace_back(key, SUCCESS); + continue; + } + callbacks_.erase(key); + lastDelKeys.emplace_back(key); + } + if (lastDelKeys.empty()) { + return result; + } + } + processOnLastDel(lastDelKeys, observer, result); + return result; +} + template std::vector> NapiCallbacksManager::GetEnabledObservers(const Key &inputKey) { diff --git a/data_share/frameworks/js/napi/common/src/datashare_error_impl.cpp b/data_share/frameworks/js/napi/common/src/datashare_error_impl.cpp index 93a46c733122b6cb39ac36d84dc44552e03622f2..913bf6b76c8010415a7ba6b4686f7185cc196c4a 100644 --- a/data_share/frameworks/js/napi/common/src/datashare_error_impl.cpp +++ b/data_share/frameworks/js/napi/common/src/datashare_error_impl.cpp @@ -14,6 +14,7 @@ */ #include "datashare_error_impl.h" +#include namespace OHOS { namespace DataShare { @@ -37,6 +38,17 @@ int ParametersNumError::GetCode() const return EXCEPTION_PARAMETER_CHECK; } +std::string DataProxyHandleParamError::GetMessage() const +{ + return "Parameter error. Possible causes: 1.The size of parameter is over limit; " + "2.The length of array is over limit; 3.The format of uri is incorrect."; +} + +int DataProxyHandleParamError::GetCode() const +{ + return EXCEPTION_PROXY_PARAMETER_CHECK; +} + std::string DataShareHelperInitError::GetMessage() const { return "The DataShareHelper is not initialized successfully."; @@ -49,7 +61,8 @@ int DataShareHelperInitError::GetCode() const std::string InnerError::GetMessage() const { - return "Inner error."; + return "Inner error. Possible causes: 1.The internal status is abnormal; 2.The interface is incorrectly used; " + "3.Permission configuration error; 4.A system error."; } int InnerError::GetCode() const diff --git a/data_share/frameworks/js/napi/common/src/datashare_js_utils.cpp b/data_share/frameworks/js/napi/common/src/datashare_js_utils.cpp index 3b0471bfcf700ce311e2bcf756421900aec4d11f..8dbaf805f8da33839157f9b502d3ef28f1d41bcd 100644 --- a/data_share/frameworks/js/napi/common/src/datashare_js_utils.cpp +++ b/data_share/frameworks/js/napi/common/src/datashare_js_utils.cpp @@ -14,10 +14,15 @@ */ #include "datashare_js_utils.h" +#include +#include "dataproxy_handle_common.h" #include "datashare_log.h" #include "datashare_predicates_proxy.h" +#include "datashare_string_utils.h" #include "datashare_valuebucket_convert.h" +#include "js_native_api.h" +#include "js_native_api_types.h" #include "napi/native_common.h" #include "napi_datashare_values_bucket.h" #include "securec.h" @@ -67,7 +72,6 @@ std::vector DataShareJSUtils::Convert2U8Vector(napi_env env, napi_value if (!isTypedArray) { napi_is_arraybuffer(env, input_array, &isArrayBuffer); if (!isArrayBuffer) { - LOG_ERROR("unknow type"); return {}; } } @@ -303,6 +307,39 @@ std::string DataShareJSUtils::UnwrapStringFromJS(napi_env env, napi_value param, return value; } +napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const DataShareValueObject &valueObject) +{ + napi_value jsValue = nullptr; + switch (valueObject.value.index()) { + case DataShareValueObjectType::TYPE_INT: { + int64_t val = std::get(valueObject.value); + jsValue = Convert2JSValue(env, val); + break; + } + case DataShareValueObjectType::TYPE_DOUBLE: { + double val = std::get(valueObject.value); + jsValue = Convert2JSValue(env, val); + break; + } + case DataShareValueObjectType::TYPE_STRING: { + std::string val = std::get(valueObject.value); + jsValue = Convert2JSValue(env, val); + break; + } + case DataShareValueObjectType::TYPE_BOOL: { + bool val = std::get(valueObject.value); + jsValue = Convert2JSValue(env, val); + break; + } + default: { + LOG_ERROR("Marshal ValueObject: unknown typeId"); + return nullptr; + } + } + + return jsValue; +} + napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const DataShareValuesBucket &valueBucket) { napi_value res = NewInstance(env, valueBucket); @@ -498,6 +535,117 @@ napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const std::vector &results) +{ + napi_value jsValue; + napi_status status = napi_create_array_with_length(env, results.size(), &jsValue); + if (status != napi_ok) { + return nullptr; + } + + for (size_t i = 0; i < results.size(); ++i) { + napi_set_element(env, jsValue, i, Convert2JSValue(env, results[i])); + } + return jsValue; +} + +napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const DataProxyGetResult &result) +{ + napi_value jsDataProxyGetResult = nullptr; + napi_create_object(env, &jsDataProxyGetResult); + + napi_value uri = Convert2JSValue(env, result.uri_); + if (uri == nullptr) { + return nullptr; + } + + napi_value errCode = Convert2JSValue(env, result.result_); + if (errCode == nullptr) { + return nullptr; + } + + // when failed to get proxyData, value and allowList in getResult is undefined + napi_value value = nullptr; + if (result.result_ == SUCCESS) { + value = Convert2JSValue(env, result.value_); + if (value == nullptr) { + return nullptr; + } + } + + napi_value allowList = nullptr; + if (result.result_ == SUCCESS) { + allowList = Convert2JSValue(env, result.allowList_); + if (allowList == nullptr) { + return nullptr; + } + } + + napi_set_named_property(env, jsDataProxyGetResult, "uri", uri); + napi_set_named_property(env, jsDataProxyGetResult, "result", errCode); + napi_set_named_property(env, jsDataProxyGetResult, "value", value); + napi_set_named_property(env, jsDataProxyGetResult, "allowList", allowList); + return jsDataProxyGetResult; +} + +napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const std::vector &results) +{ + napi_value jsValue; + napi_status status = napi_create_array_with_length(env, results.size(), &jsValue); + if (status != napi_ok) { + return nullptr; + } + + for (size_t i = 0; i < results.size(); ++i) { + napi_set_element(env, jsValue, i, Convert2JSValue(env, results[i])); + } + return jsValue; +} + +napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const DataProxyChangeInfo &changeInfo) +{ + napi_value jsDataProxyChangeInfo = nullptr; + napi_create_object(env, &jsDataProxyChangeInfo); + + napi_value type = nullptr; + type = Convert2JSValue(env, changeInfo.changeType_); + if (type == nullptr) { + return nullptr; + } + napi_value uri = nullptr; + uri = Convert2JSValue(env, changeInfo.uri_); + if (uri == nullptr) { + return nullptr; + } + napi_value value = Convert2JSValue(env, changeInfo.value_); + if (value == nullptr) { + return nullptr; + } + napi_set_named_property(env, jsDataProxyChangeInfo, "type", type); + napi_set_named_property(env, jsDataProxyChangeInfo, "uri", uri); + napi_set_named_property(env, jsDataProxyChangeInfo, "value", value); + return jsDataProxyChangeInfo; +} + bool DataShareJSUtils::UnwrapTemplatePredicates(napi_env env, napi_value jsPredicates, std::vector &predicates) { @@ -666,6 +814,171 @@ bool DataShareJSUtils::UnwrapPublishedDataItemVector(napi_env env, napi_value va return true; } +bool DataShareJSUtils::UnwrapDataProxyValue(napi_env env, napi_value jsObject, + DataProxyValue &value, bool &isValueUndefined) +{ + napi_valuetype valueType = napi_undefined; + napi_typeof(env, jsObject, &valueType); + if (valueType != napi_object) { + LOG_ERROR("UnwrapDataProxyValue error, value is not object"); + return false; + } + + std::string keyStr = "value"; + napi_value jsDataKey = Convert2JSValue(env, keyStr); + napi_value jsDataValue = nullptr; + napi_get_property(env, jsObject, jsDataKey, &jsDataValue); + napi_typeof(env, jsDataValue, &valueType); + switch (valueType) { + case napi_number: { + double valueNumber; + napi_get_value_double(env, jsDataValue, &valueNumber); + value = valueNumber; + break; + } + case napi_string: { + value = Convert2String(env, jsDataValue); + break; + } + case napi_boolean: { + bool valueBool; + napi_get_value_bool(env, jsDataValue, &valueBool); + value = valueBool; + break; + } + case napi_undefined: { + value = ""; + isValueUndefined = true; + break; + } + case napi_null: { + value = ""; + isValueUndefined = true; + break; + } + default: { + LOG_ERROR("Convert dataValue failed, type is %{public}d", valueType); + return false; + } + } + return true; +} + +bool DataShareJSUtils::UnwrapProxyDataItem(napi_env env, napi_value jsObject, DataShareProxyData &proxyData) +{ + napi_valuetype valueType = napi_undefined; + napi_typeof(env, jsObject, &valueType); + if (valueType != napi_object) { + LOG_ERROR("UnwrapPublishedDataItem error, value is not object"); + return false; + } + + if (!UnwrapStringByPropertyName(env, jsObject, "uri", proxyData.uri_)) { + LOG_ERROR("Convert uri failed"); + return false; + } + + bool isValueUndefined = false; + if (!UnwrapDataProxyValue(env, jsObject, proxyData.value_, isValueUndefined)) { + LOG_ERROR("Convert dataproxy value failed"); + return false; + } + proxyData.isValueUndefined = isValueUndefined; + + std::string keyStr = "allowList"; + napi_value jsDataKey = Convert2JSValue(env, keyStr); + napi_value jsDataValue = nullptr; + napi_get_property(env, jsObject, jsDataKey, &jsDataValue); + napi_typeof(env, jsDataValue, &valueType); + if (valueType != napi_object) { + if (valueType == napi_undefined || valueType == napi_null) { + proxyData.isAllowListUndefined = true; + } else { + LOG_ERROR("Convert allowList failed"); + return false; + } + } + Convert2Value(env, jsDataValue, proxyData.allowList_); + auto it = proxyData.allowList_.begin(); + while (it != proxyData.allowList_.end()) { + if (it->size() > APPIDENTIFIER_MAX_SIZE) { + LOG_WARN("appIdentifier is over limit"); + it = proxyData.allowList_.erase(it); + } else { + it++; + } + } + if (proxyData.allowList_.size() > ALLOW_LIST_MAX_COUNT) { + LOG_WARN("ProxyData's allowList is over limit, uri: %{public}s", + DataShareStringUtils::Anonymous(proxyData.uri_).c_str()); + proxyData.allowList_.resize(ALLOW_LIST_MAX_COUNT); + } + return true; +} + +bool DataShareJSUtils::UnwrapProxyDataItemVector(napi_env env, napi_value value, + std::vector &proxyDatas) +{ + uint32_t arraySize = 0; + if (!IsArrayForNapiValue(env, value, arraySize)) { + LOG_ERROR("IsArrayForNapiValue is false"); + return false; + } + + for (uint32_t i = 0; i < arraySize; i++) { + napi_value jsValue = nullptr; + if (napi_get_element(env, value, i, &jsValue) != napi_ok) { + LOG_ERROR("napi_get_element is false"); + return false; + } + + DataShareProxyData proxyDataItem; + if (!UnwrapProxyDataItem(env, jsValue, proxyDataItem)) { + LOG_ERROR("UnwrapPublishedDataItem failed"); + return false; + } + proxyDatas.emplace_back(std::move(proxyDataItem)); + } + return true; +} + +std::vector DataShareJSUtils::Convert2ProxyData(napi_env env, napi_value value) +{ + napi_valuetype valueType = napi_undefined; + napi_typeof(env, value, &valueType); + if (valueType != napi_object) { + LOG_ERROR("Convert2PublishedData error, value is not object"); + return {}; + } + std::vector proxyDatas; + if (!UnwrapProxyDataItemVector(env, value, proxyDatas)) { + LOG_ERROR("UnwrapPublishedDataItems failed"); + return {}; + } + return proxyDatas; +} + +bool DataShareJSUtils::UnwrapDataProxyConfig(napi_env env, napi_value value, DataProxyConfig &config) +{ + napi_value jsResult = nullptr; + napi_status status = napi_get_named_property(env, value, "type", &jsResult); + if ((status != napi_ok) || (jsResult == nullptr)) { + LOG_ERROR("Convert DataProxyType failed"); + return false; + } + napi_valuetype valueType = napi_undefined; + napi_typeof(env, jsResult, &valueType); + if (valueType != napi_number) { + LOG_ERROR("Convert DataProxyType error, value is not number"); + return false; + } + if (Convert2Value(env, jsResult, config.type_) != napi_ok) { + LOG_ERROR("Convert DataProxyType failed"); + return false; + } + return true; +} + Data DataShareJSUtils::Convert2PublishedData(napi_env env, napi_value value) { napi_valuetype valueType = napi_undefined; @@ -799,6 +1112,14 @@ int32_t DataShareJSUtils::Convert2Value(napi_env env, napi_value input, DataShar return napi_ok; } +int32_t DataShareJSUtils::Convert2Value(napi_env env, napi_value input, DataProxyType &proxyType) +{ + uint32_t number = 0; + napi_status status = napi_get_value_uint32(env, input, &number); + proxyType = static_cast(number); + return status; +} + napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const DataShareObserver::ChangeInfo &changeInfo) { napi_value napiValue = nullptr; 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 e748ff4ffd0f20b6fcce6cf52e9749d3bdced889..0373e926df55c1c62d8325d7821502cf4278db79 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,8 +15,8 @@ #include "datashare_predicates_proxy.h" -#include #include +#include #include "datashare_log.h" #include "datashare_js_utils.h" @@ -218,6 +218,9 @@ napi_value DataSharePredicatesProxy::EqualTo(napi_env env, napi_callback_info in napi_get_cb_info(env, info, &argc, args, &thiz, nullptr); NAPI_ASSERT(env, argc > 1, "Invalid argvs!"); std::string field = DataShareJSUtils::Convert2String(env, args[0], DataShareJSUtils::DEFAULT_BUF_SIZE); + if (field.empty()) { + LOG_WARN("The field is empty."); + } napi_valuetype valueType = napi_undefined; napi_status status = napi_typeof(env, args[1], &valueType); if (status != napi_ok) { @@ -248,6 +251,7 @@ napi_value DataSharePredicatesProxy::EqualTo(napi_env env, napi_callback_info in break; } default: + LOG_ERROR("Invalid argument! Wrong argument Type"); break; } return thiz; @@ -687,6 +691,9 @@ napi_value DataSharePredicatesProxy::OrderByAsc(napi_env env, napi_callback_info napi_get_cb_info(env, info, &argc, args, &thiz, nullptr); NAPI_ASSERT(env, argc > 0, "Invalid argvs!"); std::string field = DataShareJSUtils::Convert2String(env, args[0], DataShareJSUtils::DEFAULT_BUF_SIZE); + if (field.empty()) { + LOG_WARN("The field is empty."); + } auto nativePredicates = GetNativePredicates(env, info); if (nativePredicates == nullptr) { LOG_ERROR("GetNativePredicates failed."); @@ -704,6 +711,9 @@ napi_value DataSharePredicatesProxy::OrderByDesc(napi_env env, napi_callback_inf napi_get_cb_info(env, info, &argc, args, &thiz, nullptr); NAPI_ASSERT(env, argc > 0, "Invalid argvs!"); std::string field = DataShareJSUtils::Convert2String(env, args[0], DataShareJSUtils::DEFAULT_BUF_SIZE); + if (field.empty()) { + LOG_WARN("The field is empty."); + } auto nativePredicates = GetNativePredicates(env, info); if (nativePredicates == nullptr) { LOG_ERROR("GetNativePredicates failed."); @@ -789,6 +799,9 @@ napi_value DataSharePredicatesProxy::In(napi_env env, napi_callback_info info) napi_get_cb_info(env, info, &argc, args, &thiz, nullptr); NAPI_ASSERT(env, argc > 1, "Invalid argvs!"); std::string field = DataShareJSUtils::Convert2String(env, args[0], DataShareJSUtils::DEFAULT_BUF_SIZE); + if (field.empty()) { + LOG_WARN("The field is empty."); + } std::vector values = DataShareJSUtils::Convert2StrVector(env, args[1], DataShareJSUtils::DEFAULT_BUF_SIZE); auto nativePredicates = GetNativePredicates(env, info); diff --git a/data_share/frameworks/js/napi/common/src/datashare_result_set_proxy.cpp b/data_share/frameworks/js/napi/common/src/datashare_result_set_proxy.cpp index 14e53a8f6f79df40f9455a2658adb000b72f8915..e762fc78595b72c8ce3a7b52f1d2453735a2cc88 100644 --- a/data_share/frameworks/js/napi/common/src/datashare_result_set_proxy.cpp +++ b/data_share/frameworks/js/napi/common/src/datashare_result_set_proxy.cpp @@ -398,10 +398,8 @@ napi_value DataShareResultSetProxy::GetColumnIndex(napi_env env, napi_callback_i if (innerResultSet != nullptr) { int errCode = innerResultSet->GetColumnIndex(columnName, columnIndex); if (errCode != E_OK) { - auto time = static_cast(duration_cast( - system_clock::now().time_since_epoch()).count()); - LOG_ERROR("failed code:%{public}d columnIndex: %{public}d. times %{public}" PRIu64 ".", - errCode, columnIndex, time); + LOG_ERROR("code:%{public}d idx: %{public}d.", + errCode, columnIndex); } } else { LOG_ERROR("GetInnerResultSet failed."); diff --git a/data_share/frameworks/js/napi/dataShare/BUILD.gn b/data_share/frameworks/js/napi/dataShare/BUILD.gn index 6a2e9ef4cb30dbde6a42b591fad83b29410fd02f..c7f7d6ed0ddb53816f74b9e4dd48c1c54dfc9cd2 100644 --- a/data_share/frameworks/js/napi/dataShare/BUILD.gn +++ b/data_share/frameworks/js/napi/dataShare/BUILD.gn @@ -32,6 +32,7 @@ ohos_shared_library("datashare_jscommon") { "${datashare_common_napi_path}/src/datashare_js_utils.cpp", "${datashare_common_napi_path}/src/datashare_predicates_proxy.cpp", "${datashare_common_napi_path}/src/napi_datashare_values_bucket.cpp", + "${datashare_common_native_path}/src/datashare_string_utils.cpp", ] deps = [ "${datashare_innerapi_path}/common:datashare_common" ] @@ -74,9 +75,11 @@ ohos_shared_library("datashare") { sources = [ "${datashare_common_napi_path}/src/datashare_error_impl.cpp", "${datashare_common_napi_path}/src/datashare_result_set_proxy.cpp", + "${datashare_common_native_path}/src/datashare_string_utils.cpp", "${datashare_napi_path}/dataShare/src/async_call.cpp", "${datashare_napi_path}/dataShare/src/napi_datashare_const_properties.cpp", "${datashare_napi_path}/dataShare/src/napi_datashare_helper.cpp", + "${datashare_napi_path}/dataShare/src/napi_dataproxy_handle.cpp", "${datashare_napi_path}/dataShare/src/napi_datashare_inner_observer.cpp", "${datashare_napi_path}/dataShare/src/napi_datashare_observer.cpp", "${datashare_napi_path}/dataShare/src/native_datashare_module.cpp", diff --git a/data_share/frameworks/js/napi/dataShare/include/napi_dataproxy_handle.h b/data_share/frameworks/js/napi/dataShare/include/napi_dataproxy_handle.h new file mode 100644 index 0000000000000000000000000000000000000000..1bdc423e29a6c127eb82800f410689d4cc2331ad --- /dev/null +++ b/data_share/frameworks/js/napi/dataShare/include/napi_dataproxy_handle.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2025 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 NAPI_DATAPROXY_HANDLE_H +#define NAPI_DATAPROXY_HANDLE_H + +#include "async_call.h" +#include "dataproxy_handle.h" +#include "data_share_common.h" +#include "hap_module_info.h" +#include "dataproxy_handle_common.h" +#include "napi_datashare_observer.h" +#include "napi_subscriber_manager.h" + +namespace OHOS { +namespace DataShare { +class NapiDataProxyHandle { +public: + static napi_value Napi_CreateDataProxyHandle(napi_env env, napi_callback_info info); + static napi_value Napi_Publish(napi_env env, napi_callback_info info); + static napi_value Napi_Delete(napi_env env, napi_callback_info info); + static napi_value Napi_Get(napi_env env, napi_callback_info info); + static napi_value Napi_On(napi_env env, napi_callback_info info); + static napi_value Napi_Off(napi_env env, napi_callback_info info); +private: + static napi_value GetConstructor(napi_env env); + static napi_value Initialize(napi_env env, napi_callback_info info); + static napi_value Napi_SubscribeProxyData(napi_env env, size_t argc, napi_value *argv, napi_value self); + static napi_value Napi_UnSubscribeProxyData(napi_env env, size_t argc, napi_value *argv, napi_value self); + std::vector SubscribeProxyData(napi_env env, const std::vector &uris, + napi_value callback, std::shared_ptr handle); + std::vector UnsubscribeProxyData(napi_env env, const std::vector &uris, + napi_value callback, std::shared_ptr handle); + void SetHandle(std::shared_ptr dataProxyHandle); + std::shared_ptr GetHandle(); + static bool CheckIsParameterExceed(const std::vector &proxyDatas); + static bool CheckIsParameterExceed(const std::vector &uris); + std::shared_ptr dataProxyHandle_ = nullptr; + std::shared_mutex mutex_; + std::shared_ptr jsProxyDataObsManager_ = nullptr; + + struct HandleContextInfo : public AsyncCall::Context { + napi_env env = nullptr; + napi_ref ref = nullptr; + bool isStageMode = true; + std::string strUri; + std::shared_ptr dataProxyHandle = nullptr; + + HandleContextInfo() : Context(nullptr, nullptr) {}; + HandleContextInfo(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; + ~HandleContextInfo() + { + if (env != nullptr && ref != nullptr) { + napi_delete_reference(env, ref); + } + } + }; + + struct ContextInfo : public AsyncCall::Context { + NapiDataProxyHandle *proxy = nullptr; + napi_status status = napi_generic_failure; + + DatashareBusinessError businessError; + std::vector proxyDatas; + DataProxyConfig config; + std::string bundleName; + std::vector uris; + std::vector proxyResult; + std::vector proxyGetResult; + int32_t resultNumber = 0; + + ContextInfo() : Context(nullptr, nullptr) + { + config.type_ = DataProxyType::SHARED_CONFIG; + }; + ContextInfo(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; + virtual ~ContextInfo() {}; + + napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override + { + NAPI_ASSERT_BASE(env, self != nullptr, "self is nullptr", napi_invalid_arg); + NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast(&proxy)), napi_invalid_arg); + NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no native upload task", napi_invalid_arg); + return Context::operator()(env, argc, argv, self); + } + napi_status operator()(napi_env env, napi_value *result) override + { + if (status != napi_ok) { + return status; + } + return Context::operator()(env, result); + } + }; +}; +} // namespace DataShare +} // namespace OHOS +#endif /* NAPI_DATAPROXY_HANDLE_H */ \ No newline at end of file diff --git a/data_share/frameworks/js/napi/dataShare/include/napi_datashare_helper.h b/data_share/frameworks/js/napi/dataShare/include/napi_datashare_helper.h index 8ab5c2497f36ddc4e3de58f5b58bed2438599a69..e4f017280577b8d4a7d2fbb1d53a407bb822f01f 100644 --- a/data_share/frameworks/js/napi/dataShare/include/napi_datashare_helper.h +++ b/data_share/frameworks/js/napi/dataShare/include/napi_datashare_helper.h @@ -142,6 +142,8 @@ private: static void Notify(const std::shared_ptr context, std::shared_ptr helper); static void ExecuteCreator(std::shared_ptr ctxInfo); + static napi_status ValidateCreateParam(napi_env env, size_t argc, napi_value *argv, + std::shared_ptr ctxInfo); }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/js/napi/dataShare/include/napi_datashare_inner_observer.h b/data_share/frameworks/js/napi/dataShare/include/napi_datashare_inner_observer.h index 1f8abe2c70c13c45b34ea4df50908029cdd9084b..c5f0d6ff04f0bfdd34664973a6c3b5e02c5082fa 100644 --- a/data_share/frameworks/js/napi/dataShare/include/napi_datashare_inner_observer.h +++ b/data_share/frameworks/js/napi/dataShare/include/napi_datashare_inner_observer.h @@ -28,8 +28,10 @@ namespace DataShare { class NAPIInnerObserver : public std::enable_shared_from_this { public: NAPIInnerObserver(napi_env env, napi_value callback); + ~NAPIInnerObserver(); void OnChange(const DataShareObserver::ChangeInfo &changeInfo = {}, bool isNotifyDetails = false); void DeleteReference(); + void RegisterEnvCleanHook(); napi_ref GetCallback(); protected: @@ -40,10 +42,18 @@ protected: ObserverWorker(std::shared_ptr observerIn, DataShareObserver::ChangeInfo resultIn = {}) : observer_(observerIn), result_(resultIn) {} }; + + struct ObserverEnvHookWorker { + std::weak_ptr observer_; + ObserverEnvHookWorker(std::shared_ptr observerIn): observer_(observerIn) {} + }; static void OnComplete(ObserverWorker* observerWorker); + static void CleanEnv(void *obj); napi_env env_ = nullptr; napi_ref ref_ = nullptr; uv_loop_s *loop_ = nullptr; + std::mutex envMutex_{}; + ObserverEnvHookWorker* observerEnvHookWorker_ = nullptr;; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/js/napi/dataShare/src/napi_dataproxy_handle.cpp b/data_share/frameworks/js/napi/dataShare/src/napi_dataproxy_handle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dac70e65e7c6eb666ea2ae8f323a691d79b52fb6 --- /dev/null +++ b/data_share/frameworks/js/napi/dataShare/src/napi_dataproxy_handle.cpp @@ -0,0 +1,429 @@ +/* + * Copyright (c) 2025 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 "napi_dataproxy_handle.h" +#include "dataproxy_handle_common.h" +#include "datashare_error_impl.h" +#include "datashare_js_utils.h" +#include "datashare_log.h" +#include "datashare_string_utils.h" +#include "js_native_api_types.h" + +namespace OHOS { +namespace DataShare { +static thread_local napi_ref constructor_ = nullptr; +static constexpr int MAX_ARGC = 4; +using DataProxyHandle = OHOS::DataShare::DataProxyHandle; +napi_value NapiDataProxyHandle::GetConstructor(napi_env env) +{ + napi_value cons = nullptr; + if (constructor_ != nullptr) { + napi_status status = napi_get_reference_value(env, constructor_, &cons); + if (status != napi_ok) { + LOG_ERROR("napi get reference value failed. napi_status: %{public}d", status); + } + return cons; + } + napi_property_descriptor clzDes[] = { + DECLARE_NAPI_FUNCTION("publish", Napi_Publish), + DECLARE_NAPI_FUNCTION("delete", Napi_Delete), + DECLARE_NAPI_FUNCTION("get", Napi_Get), + DECLARE_NAPI_FUNCTION("on", Napi_On), + DECLARE_NAPI_FUNCTION("off", Napi_Off), + }; + NAPI_CALL(env, napi_define_class(env, "DataProxyHandle", NAPI_AUTO_LENGTH, Initialize, nullptr, + sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons)); + napi_status status = napi_create_reference(env, cons, 1, &constructor_); + if (status != napi_ok) { + LOG_ERROR("napi create reference failed. napi_status: %{public}d", status); + } + return cons; +} + +napi_value NapiDataProxyHandle::Initialize(napi_env env, napi_callback_info info) +{ + LOG_INFO("Start"); + napi_value self = nullptr; + size_t argc = ARGS_MAX_COUNT; + napi_value argv[ARGS_MAX_COUNT] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); + + auto *proxy = new (std::nothrow) NapiDataProxyHandle(); + if (proxy == nullptr) { + return nullptr; + } + auto finalize = [](napi_env env, void *data, void *hint) { + NapiDataProxyHandle *proxy = reinterpret_cast(data); + delete proxy; + }; + if (napi_wrap(env, self, proxy, finalize, nullptr, nullptr) != napi_ok) { + finalize(env, proxy, nullptr); + return nullptr; + } + return self; +} + +napi_value NapiDataProxyHandle::Napi_CreateDataProxyHandle(napi_env env, napi_callback_info info) +{ + auto ctxInfo = std::make_shared(); + auto input = [ctxInfo](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + napi_value handleProxy = nullptr; + napi_status status = napi_new_instance(env, GetConstructor(env), argc, argv, &handleProxy); + if (status != napi_ok) { + LOG_ERROR("napi new instance failed. napi_status: %{public}d", status); + } + NAPI_ASSERT_CALL_ERRCODE(env, handleProxy != nullptr && status == napi_ok, + ctxInfo->error = std::make_shared(), napi_generic_failure); + napi_create_reference(env, handleProxy, 1, &(ctxInfo->ref)); + ctxInfo->env = env; + return napi_ok; + }; + auto output = [ctxInfo](napi_env env, napi_value *result) -> napi_status { + NAPI_ASSERT_CALL_ERRCODE(env, ctxInfo->dataProxyHandle != nullptr, + ctxInfo->error = std::make_shared(), napi_generic_failure); + napi_status status = napi_get_reference_value(env, ctxInfo->ref, result); + NAPI_ASSERT_CALL_ERRCODE(env, result != nullptr, + ctxInfo->error = std::make_shared(), napi_generic_failure); + NapiDataProxyHandle *proxy = nullptr; + status = napi_unwrap(env, *result, reinterpret_cast(&proxy)); + NAPI_ASSERT_CALL_ERRCODE(env, proxy != nullptr, ctxInfo->error = std::make_shared(), + status); + proxy->jsProxyDataObsManager_ = std::make_shared(ctxInfo->dataProxyHandle); + proxy->SetHandle(std::move(ctxInfo->dataProxyHandle)); + return status; + }; + auto exec = [ctxInfo](AsyncCall::Context *ctx) { + auto ret = DataProxyHandle::Create(); + ctxInfo->dataProxyHandle = ret.second; + }; + ctxInfo->SetAction(std::move(input), std::move(output)); + AsyncCall asyncCall(env, info, ctxInfo); + return asyncCall.Call(env, exec); +} + +bool NapiDataProxyHandle::CheckIsParameterExceed(const std::vector &proxyDatas) +{ + if (proxyDatas.size() > PROXY_DATA_MAX_COUNT || proxyDatas.empty()) { + return false; + } + for (const auto &data : proxyDatas) { + // value's limit is 4096 bytes + if (data.value_.index() == DataProxyValueType::VALUE_STRING) { + std::string valStr = std::get(data.value_); + if (valStr.size() > VALUE_MAX_SIZE) { + LOG_ERROR("ProxyData's value is over limit, uri: %{public}s", + DataShareStringUtils::Anonymous(data.uri_).c_str()); + return false; + } + } + if (data.uri_.size() > URI_MAX_SIZE) { + LOG_ERROR("the size of uri %{public}s is over limit", DataShareStringUtils::Anonymous(data.uri_).c_str()); + return false; + } + } + return true; +} + +bool NapiDataProxyHandle::CheckIsParameterExceed(const std::vector &uris) +{ + for (const auto &uri : uris) { + if (uri.size() > URI_MAX_SIZE) { + LOG_ERROR("the size of uri %{public}s is over limit", DataShareStringUtils::Anonymous(uri).c_str()); + return false; + } + } + return true; +} + +napi_value NapiDataProxyHandle::Napi_Publish(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + if (argc != 2) { + context->error = std::make_shared("2"); + return napi_invalid_arg; + } + napi_valuetype valueType; + NAPI_CALL_BASE(env, napi_typeof(env, argv[0], &valueType), napi_invalid_arg); + + NAPI_ASSERT_CALL_ERRCODE(env, valueType == napi_object, + context->error = std::make_shared("proxyData", "Array"), napi_invalid_arg); + context->proxyDatas = DataShareJSUtils::Convert2ProxyData(env, argv[0]); + NAPI_ASSERT_CALL_ERRCODE(env, CheckIsParameterExceed(context->proxyDatas), context->error = + std::make_shared(), napi_invalid_arg); + NAPI_CALL_BASE(env, napi_typeof(env, argv[1], &valueType), napi_invalid_arg); + NAPI_ASSERT_CALL_ERRCODE(env, valueType == napi_object, + context->error = std::make_shared("config", "DataProxyConfig"), napi_invalid_arg); + DataShareJSUtils::UnwrapDataProxyConfig(env, argv[1], context->config); + return napi_ok; + }; + auto output = [context](napi_env env, napi_value *result) -> napi_status { + NAPI_ASSERT_BASE(env, context->status == napi_ok, "exec failed", napi_generic_failure); + *result = DataShareJSUtils::Convert2JSValue(env, context->proxyResult); + context->proxyResult.clear(); + return napi_ok; + }; + auto exec = [context](AsyncCall::Context *ctx) { + auto handle = context->proxy->GetHandle(); + NAPI_ASSERT_CALL_ERRCODE(env, handle != nullptr, + context->error = std::make_shared(), napi_generic_failure); + + context->proxyResult = handle->PublishProxyData(context->proxyDatas, context->config); + context->status = napi_ok; + return napi_ok; + }; + context->SetAction(std::move(input), std::move(output)); + AsyncCall asyncCall(env, info, context); + return asyncCall.Call(env, exec); +} + +napi_value NapiDataProxyHandle::Napi_Delete(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + if (argc != 2) { + context->error = std::make_shared("2"); + return napi_invalid_arg; + } + + napi_valuetype valueType; + NAPI_CALL_BASE(env, napi_typeof(env, argv[0], &valueType), napi_invalid_arg); + NAPI_ASSERT_CALL_ERRCODE(env, valueType == napi_object, + context->error = std::make_shared("uris", "Array"), napi_invalid_arg); + context->uris = + DataShareJSUtils::Convert2StrVector(env, argv[0], DataShareJSUtils::DEFAULT_BUF_SIZE); + NAPI_ASSERT_CALL_ERRCODE(env, !(context->uris.empty()), + context->error = std::make_shared("uris", "not empty"), napi_invalid_arg); + NAPI_ASSERT_CALL_ERRCODE(env, context->uris.size() <= URI_MAX_COUNT && + CheckIsParameterExceed(context->uris), context->error = + std::make_shared(), napi_invalid_arg); + NAPI_CALL_BASE(env, napi_typeof(env, argv[1], &valueType), napi_invalid_arg); + NAPI_ASSERT_CALL_ERRCODE(env, valueType == napi_object, + context->error = std::make_shared("config", "DataProxyConfig"), napi_invalid_arg); + if (!DataShareJSUtils::UnwrapDataProxyConfig(env, argv[1], context->config)) { + context->error = std::make_shared("config", "DataProxyConfig"); + return napi_invalid_arg; + } + return napi_ok; + }; + auto output = [context](napi_env env, napi_value *result) -> napi_status { + NAPI_ASSERT_BASE(env, context->status == napi_ok, "exec failed", napi_generic_failure); + *result = DataShareJSUtils::Convert2JSValue(env, context->proxyResult); + context->proxyResult.clear(); + return napi_ok; + }; + auto exec = [context](AsyncCall::Context *ctx) { + auto handle = context->proxy->GetHandle(); + NAPI_ASSERT_CALL_ERRCODE(env, handle != nullptr, + context->error = std::make_shared(), napi_generic_failure); + + context->proxyResult = handle->DeleteProxyData(context->uris, context->config); + context->status = napi_ok; + return napi_ok; + }; + context->SetAction(std::move(input), std::move(output)); + AsyncCall asyncCall(env, info, context); + return asyncCall.Call(env, exec); +} + +napi_value NapiDataProxyHandle::Napi_Get(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + if (argc != 2) { + context->error = std::make_shared("2"); + return napi_invalid_arg; + } + + napi_valuetype valueType; + NAPI_CALL_BASE(env, napi_typeof(env, argv[0], &valueType), napi_invalid_arg); + NAPI_ASSERT_CALL_ERRCODE(env, valueType == napi_object, + context->error = std::make_shared("uris", "Array"), napi_invalid_arg); + context->uris = + DataShareJSUtils::Convert2StrVector(env, argv[0], DataShareJSUtils::DEFAULT_BUF_SIZE); + NAPI_ASSERT_CALL_ERRCODE(env, !(context->uris.empty()), + context->error = std::make_shared("uris", "not empty"), napi_invalid_arg); + NAPI_ASSERT_CALL_ERRCODE(env, context->uris.size() <= URI_MAX_COUNT && + CheckIsParameterExceed(context->uris), context->error = + std::make_shared(), napi_invalid_arg); + if (!DataShareJSUtils::UnwrapDataProxyConfig(env, argv[1], context->config)) { + context->error = std::make_shared("config", "DataProxyConfig"); + return napi_invalid_arg; + } + return napi_ok; + }; + auto output = [context](napi_env env, napi_value *result) -> napi_status { + NAPI_ASSERT_BASE(env, context->status == napi_ok, "exec failed", napi_generic_failure); + *result = DataShareJSUtils::Convert2JSValue(env, context->proxyGetResult); + context->proxyResult.clear(); + return napi_ok; + }; + auto exec = [context](AsyncCall::Context *ctx) { + auto handle = context->proxy->GetHandle(); + NAPI_ASSERT_CALL_ERRCODE(env, handle != nullptr, + context->error = std::make_shared(), napi_generic_failure); + + context->proxyGetResult = handle->GetProxyData(context->uris, context->config); + context->status = napi_ok; + return napi_ok; + }; + context->SetAction(std::move(input), std::move(output)); + AsyncCall asyncCall(env, info, context); + return asyncCall.Call(env, exec); +} + +napi_value NapiDataProxyHandle::Napi_On(napi_env env, napi_callback_info info) +{ + napi_value self = nullptr; + size_t argc = MAX_ARGC; + napi_value argv[MAX_ARGC] = { nullptr }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); + std::shared_ptr error = nullptr; + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, argc == ARGS_FOUR, + error = std::make_shared("4"), error, nullptr); + napi_valuetype valueType; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_string, + error = std::make_shared("event", "string"), error, nullptr); + std::string type = DataShareJSUtils::Convert2String(env, argv[0]); + if (type == "dataChange") { + return Napi_SubscribeProxyData(env, argc, argv, self); + } + LOG_ERROR("wrong register type : %{public}s", type.c_str()); + return nullptr; +} + +napi_value NapiDataProxyHandle::Napi_Off(napi_env env, napi_callback_info info) +{ + napi_value self = nullptr; + size_t argc = MAX_ARGC; + napi_value argv[MAX_ARGC] = { nullptr }; + std::shared_ptr error = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, argc == ARGS_THREE || argc == ARGS_FOUR, + error = std::make_shared("3 or 4"), error, nullptr); + + napi_valuetype valueType; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_string, + error = std::make_shared("event", "string"), error, nullptr); + std::string type = DataShareJSUtils::Convert2String(env, argv[0]); + if (type == "dataChange") { + return Napi_UnSubscribeProxyData(env, argc, argv, self); + } + LOG_ERROR("wrong register type : %{public}s", type.c_str()); + return nullptr; +} + +void NapiDataProxyHandle::NapiDataProxyHandle::SetHandle(std::shared_ptr dataProxyHandle) +{ + std::unique_lock lock(mutex_); + dataProxyHandle_ = std::move(dataProxyHandle); +} + +std::shared_ptr NapiDataProxyHandle::GetHandle() +{ + std::shared_lock lock(mutex_); + return dataProxyHandle_; +} + +napi_value NapiDataProxyHandle::Napi_SubscribeProxyData(napi_env env, size_t argc, napi_value *argv, napi_value self) +{ + std::vector results; + napi_value jsResults = DataShareJSUtils::Convert2JSValue(env, results); + std::shared_ptr error = nullptr; + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, argc == ARGS_FOUR, error = std::make_shared("4"), error, + jsResults); + + NapiDataProxyHandle *proxy = nullptr; + NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast(&proxy)), jsResults); + NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataProxyHandle instance", jsResults); + auto handle = proxy->GetHandle(); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, handle != nullptr, error = std::make_shared(), error, + jsResults); + + napi_valuetype valueType; + NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valueType)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_object, + error = std::make_shared("uris", "Array"), error, jsResults); + std::vector uris = + DataShareJSUtils::Convert2StrVector(env, argv[PARAM1], DataShareJSUtils::DEFAULT_BUF_SIZE); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, !(uris.empty()), + error = std::make_shared("uris", "not empty"), error, jsResults); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, uris.size() <= URI_MAX_COUNT && + CheckIsParameterExceed(uris), error = std::make_shared(), error, jsResults); + + NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_object, + error = std::make_shared("config", "DataProxyConfig"), error, jsResults); + DataProxyConfig config; + DataShareJSUtils::UnwrapDataProxyConfig(env, argv[PARAM2], config); + + NAPI_CALL(env, napi_typeof(env, argv[PARAM3], &valueType)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_function, + error = std::make_shared("callback", "function"), error, jsResults); + + if (proxy->jsProxyDataObsManager_ == nullptr) { + LOG_ERROR("proxy->jsManager_ is nullptr"); + return jsResults; + } + results = proxy->jsProxyDataObsManager_->AddObservers(env, argv[PARAM3], uris); + return DataShareJSUtils::Convert2JSValue(env, results); +} + +napi_value NapiDataProxyHandle::Napi_UnSubscribeProxyData(napi_env env, size_t argc, napi_value *argv, napi_value self) +{ + std::vector results; + napi_value jsResults = DataShareJSUtils::Convert2JSValue(env, results); + std::shared_ptr error = nullptr; + NapiDataProxyHandle* proxy = nullptr; + napi_valuetype valueType; + NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast(&proxy)), nullptr); + NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataProxyHandle instance", nullptr); + auto handle = proxy->GetHandle(); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, handle != nullptr, error = std::make_shared(), error, + nullptr); + NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valueType)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_object, + error = std::make_shared("uris", "Array"), error, nullptr); + auto uris = DataShareJSUtils::Convert2StrVector(env, argv[PARAM1], DataShareJSUtils::DEFAULT_BUF_SIZE); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, !(uris.empty()), + error = std::make_shared("uris", "not empty"), error, jsResults); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, uris.size() <= URI_MAX_COUNT && + CheckIsParameterExceed(uris), error = std::make_shared(), error, jsResults); + + NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_object, + error = std::make_shared("config", "DataProxyConfig"), error, jsResults); + DataProxyConfig config; + DataShareJSUtils::UnwrapDataProxyConfig(env, argv[PARAM2], config); + if (proxy->jsProxyDataObsManager_ == nullptr) { + LOG_ERROR("proxy->jsManager_ is nullptr"); + return jsResults; + } + + if (argc == ARGS_FOUR) { + NAPI_CALL(env, napi_typeof(env, argv[PARAM3], &valueType)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, + valueType == napi_function || valueType == napi_undefined || valueType == napi_null, + error = std::make_shared("callback", "function"), error, nullptr); + results = proxy->jsProxyDataObsManager_->DelObservers(env, argv[PARAM3], uris); + } + + results = proxy->jsProxyDataObsManager_->DelObservers(env, nullptr, uris); + return DataShareJSUtils::Convert2JSValue(env, results); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_const_properties.cpp b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_const_properties.cpp index 588347fff06c79474ea9e05c4cfc32c022c19951..d20b1b07d5966664e794a2f0bd8187d0dee1169e 100644 --- a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_const_properties.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_const_properties.cpp @@ -20,6 +20,7 @@ #include #include "datashare_helper.h" +#include "dataproxy_handle_common.h" #include "napi_base_context.h" #include "napi_common_util.h" @@ -54,11 +55,35 @@ static napi_value ExportSubscriptionType(napi_env env) napi_object_freeze(env, SubscriptionType); return SubscriptionType; } + +static napi_value ExportDataProxyType(napi_env env) +{ + napi_value dataProxyType = nullptr; + napi_create_object(env, &dataProxyType); + SetNamedProperty(env, dataProxyType, "SHARED_CONFIG", static_cast(DataProxyType::SHARED_CONFIG)); + napi_object_freeze(env, dataProxyType); + return dataProxyType; +} + +static napi_value ExportDataProxyErrorCode(napi_env env) +{ + napi_value dataProxyErrorCode = nullptr; + napi_create_object(env, &dataProxyErrorCode); + SetNamedProperty(env, dataProxyErrorCode, "SUCCESS", static_cast(DataProxyErrorCode::SUCCESS)); + SetNamedProperty(env, dataProxyErrorCode, "URI_NOT_EXIST", static_cast(DataProxyErrorCode::URI_NOT_EXIST)); + SetNamedProperty(env, dataProxyErrorCode, "NO_PERMISSION", static_cast(DataProxyErrorCode::NO_PERMISSION)); + SetNamedProperty(env, dataProxyErrorCode, "OVER_LIMIT", static_cast(DataProxyErrorCode::OVER_LIMIT)); + napi_object_freeze(env, dataProxyErrorCode); + return dataProxyErrorCode; +} + napi_status InitConstProperties(napi_env env, napi_value exports) { const napi_property_descriptor properties[] = { DECLARE_NAPI_PROPERTY("ChangeType", ExportChangeType(env)), DECLARE_NAPI_PROPERTY("SubscriptionType", ExportSubscriptionType(env)), + DECLARE_NAPI_PROPERTY("DataProxyType", ExportDataProxyType(env)), + DECLARE_NAPI_PROPERTY("DataProxyErrorCode", ExportDataProxyErrorCode(env)), }; size_t count = sizeof(properties) / sizeof(properties[0]); 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 531c5a8de646d507983feaeb2214336c947ce2a9..5774c506c4c66d9d1a58f4ba12537824eb7171c6 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 @@ -154,30 +154,47 @@ void NapiDataShareHelper::ExecuteCreator(std::shared_ptr ctxI } } +napi_status NapiDataShareHelper::ValidateCreateParam(napi_env env, size_t argc, napi_value *argv, + std::shared_ptr ctxInfo) +{ + NAPI_ASSERT_CALL_ERRCODE(env, IsSystemApp(), + ctxInfo->error = std::make_shared(EXCEPTION_SYSTEMAPP_CHECK, "not system app"), + napi_generic_failure); + // Check the number of arguments given to match CreateDataShareHelper founction with 2 or 3 or 4 args. + NAPI_ASSERT_CALL_ERRCODE(env, argc == 2 || argc == 3 || argc == 4, + ctxInfo->error = std::make_shared("2 or 3 or 4"), napi_invalid_arg); + ctxInfo->contextS = OHOS::AbilityRuntime::GetStageModeContext(env, argv[0]); + NAPI_ASSERT_CALL_ERRCODE(env, ctxInfo->contextS != nullptr, + ctxInfo->error = std::make_shared("contextS", "not nullptr"), napi_invalid_arg); + NAPI_ASSERT_CALL_ERRCODE(env, GetUri(env, argv[1], ctxInfo->strUri), + ctxInfo->error = std::make_shared("uri", "string"), napi_invalid_arg); + Uri uri(ctxInfo->strUri); + // If there is more then 2 napi args, then the third arg options and uri format needs to be checked. + if (argc != 2) { + // The napi input argument at index 2 is optional config. + NAPI_ASSERT_CALL_ERRCODE(env, GetOptions(env, argv[2], ctxInfo->options, uri), + ctxInfo->error = std::make_shared("option", "CreateOption"), napi_invalid_arg); + } else { + NAPI_ASSERT_CALL_ERRCODE(env, uri.GetScheme() != "datashareproxy", + ctxInfo->error = std::make_shared("3 or 4"), napi_invalid_arg); + } + return napi_ok; +} + napi_value NapiDataShareHelper::Napi_CreateDataShareHelper(napi_env env, napi_callback_info info) { auto ctxInfo = std::make_shared(); auto input = [ctxInfo](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { - NAPI_ASSERT_CALL_ERRCODE(env, IsSystemApp(), - ctxInfo->error = std::make_shared(EXCEPTION_SYSTEMAPP_CHECK, "not system app"), - napi_generic_failure); - NAPI_ASSERT_CALL_ERRCODE(env, argc == 2 || argc == 3 || argc == 4, - ctxInfo->error = std::make_shared("2 or 3 or 4"), napi_invalid_arg); - ctxInfo->contextS = OHOS::AbilityRuntime::GetStageModeContext(env, argv[0]); - NAPI_ASSERT_CALL_ERRCODE(env, ctxInfo->contextS != nullptr, - ctxInfo->error = std::make_shared("contextS", "not nullptr"), napi_invalid_arg); - NAPI_ASSERT_CALL_ERRCODE(env, GetUri(env, argv[1], ctxInfo->strUri), - ctxInfo->error = std::make_shared("uri", "string"), napi_invalid_arg); - Uri uri(ctxInfo->strUri); - if (argc != 2) { - NAPI_ASSERT_CALL_ERRCODE(env, GetOptions(env, argv[2], ctxInfo->options, uri), - ctxInfo->error = std::make_shared("option", "CreateOption"), napi_invalid_arg); - } else { - NAPI_ASSERT_CALL_ERRCODE(env, uri.GetScheme() != "datashareproxy", - ctxInfo->error = std::make_shared("3 or 4"), napi_invalid_arg); + napi_status status = ValidateCreateParam(env, argc, argv, ctxInfo); + if (status != napi_ok) { + return status; } napi_value helperProxy = nullptr; - napi_status status = napi_new_instance(env, GetConstructor(env), argc, argv, &helperProxy); + status = napi_new_instance(env, GetConstructor(env), argc, argv, &helperProxy); + if (status != napi_ok) { + LOG_ERROR("napi new instance failed. napi_status: %{public}d uri: %{public}s", + status, ctxInfo->strUri.c_str()); + } NAPI_ASSERT_CALL_ERRCODE(env, helperProxy != nullptr && status == napi_ok, ctxInfo->error = std::make_shared(), napi_generic_failure); napi_create_reference(env, helperProxy, 1, &(ctxInfo->ref)); @@ -211,7 +228,10 @@ napi_value NapiDataShareHelper::GetConstructor(napi_env env) { napi_value cons = nullptr; if (constructor_ != nullptr) { - napi_get_reference_value(env, constructor_, &cons); + napi_status status = napi_get_reference_value(env, constructor_, &cons); + if (status != napi_ok) { + LOG_ERROR("napi get reference value failed. napi_status: %{public}d", status); + } return cons; } napi_property_descriptor clzDes[] = { @@ -234,7 +254,10 @@ 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_); + napi_status status = napi_create_reference(env, cons, 1, &constructor_); + if (status != napi_ok) { + LOG_ERROR("napi create reference failed. napi_status: %{public}d", status); + } return cons; } @@ -629,7 +652,7 @@ void NapiDataShareHelper::Notify(const std::shared_ptrerror = std::make_shared("uri", "not empty"); return; } - helper->NotifyChangeExt(context->changeInfo); + helper->NotifyChangeExt(context->changeInfo, true); context->status = napi_ok; return; } @@ -1039,6 +1062,7 @@ void NapiDataShareHelper::RegisteredObserver(napi_env env, const std::string &ur return; } auto innerObserver = std::make_shared(env, callback); + innerObserver->RegisterEnvCleanHook(); sptr observer(new (std::nothrow) NAPIDataShareObserver(innerObserver)); if (observer == nullptr) { LOG_ERROR("observer is nullptr"); @@ -1048,7 +1072,8 @@ void NapiDataShareHelper::RegisteredObserver(napi_env env, const std::string &ur helper->RegisterObserver(Uri(uri), observer); } else { helper->RegisterObserverExt(Uri(uri), - std::shared_ptr(observer.GetRefPtr(), [holder = observer](const auto*) {}), false); + std::shared_ptr(observer.GetRefPtr(), [holder = observer](const auto*) {}), + false, true); } list.push_back(observer); } @@ -1073,7 +1098,7 @@ void NapiDataShareHelper::UnRegisteredObserver(napi_env env, const std::string & helper->UnregisterObserver(Uri(uri), *it); } else { helper->UnregisterObserverExt(Uri(uri), - std::shared_ptr((*it).GetRefPtr(), [holder = *it](const auto*) {})); + std::shared_ptr((*it).GetRefPtr(), [holder = *it](const auto*) {}), true); } (*it)->observer_->DeleteReference(); it = list.erase(it); @@ -1100,7 +1125,7 @@ void NapiDataShareHelper::UnRegisteredObserver(napi_env env, const std::string & helper->UnregisterObserver(Uri(uri), *it); } else { helper->UnregisterObserverExt(Uri(uri), - std::shared_ptr((*it).GetRefPtr(), [holder = *it](const auto*) {})); + std::shared_ptr((*it).GetRefPtr(), [holder = *it](const auto*) {}), true); } (*it)->observer_->DeleteReference(); it = list.erase(it); diff --git a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_inner_observer.cpp b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_inner_observer.cpp index 3b02fd5c4ebdfabb883945e6e63ec8e4d0194582..e4cf6fec550d23e2e9d2e8565042af2ffb2c2e21 100644 --- a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_inner_observer.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_inner_observer.cpp @@ -31,6 +31,36 @@ NAPIInnerObserver::NAPIInnerObserver(napi_env env, napi_value callback) napi_get_uv_event_loop(env, &loop_); } +NAPIInnerObserver::~NAPIInnerObserver() +{ + if (env_ == nullptr) { + LOG_ERROR("env_ is nullptr"); + return; + } + // SAFETY: observerEnvHookWorker will not be accessed in napi_remove_env_cleanup_hook + auto task = [env = env_, observerEnvHookWorker = observerEnvHookWorker_]() { + napi_remove_env_cleanup_hook(env, &CleanEnv, observerEnvHookWorker); + }; + int ret = napi_send_event(env_, task, napi_eprio_immediate); + if (ret != 0) { + LOG_ERROR("napi_send_event failed: %{public}d", ret); + } + if (observerEnvHookWorker_ != nullptr) { + delete observerEnvHookWorker_; + observerEnvHookWorker_ = nullptr; + } +} + +void NAPIInnerObserver::RegisterEnvCleanHook() +{ + observerEnvHookWorker_ = new (std::nothrow) ObserverEnvHookWorker(shared_from_this()); + if (observerEnvHookWorker_ == nullptr) { + LOG_ERROR("Failed to create observerEnvHookWorker_"); + return; + } + napi_add_env_cleanup_hook(env_, &CleanEnv, observerEnvHookWorker_); +} + void NAPIInnerObserver::OnComplete(ObserverWorker* observerWorker) { LOG_DEBUG("napi_send_event start"); @@ -40,6 +70,12 @@ void NAPIInnerObserver::OnComplete(ObserverWorker* observerWorker) delete observerWorker; return; } + std::lock_guard lck(observer->envMutex_); + if (observer->env_ == nullptr) { + LOG_ERROR("innerWorker->observer_->env_ is nullptr"); + delete observerWorker; + return; + } napi_handle_scope scope = nullptr; napi_open_handle_scope(observer->env_, &scope); if (scope == nullptr) { @@ -74,6 +110,12 @@ void NAPIInnerObserver::OnChange(const DataShareObserver::ChangeInfo& changeInfo LOG_ERROR("ref_ is nullptr"); return; } + std::lock_guard lck(envMutex_); + if (env_ == nullptr) { + LOG_ERROR("env_ is nullptr"); + return; + } + ObserverWorker* observerWorker = new (std::nothrow) ObserverWorker(shared_from_this(), changeInfo); if (observerWorker == nullptr) { LOG_ERROR("Failed to create observerWorker"); @@ -103,5 +145,21 @@ napi_ref NAPIInnerObserver::GetCallback() { return ref_; } + +void NAPIInnerObserver::CleanEnv(void *obj) +{ + LOG_INFO("Napi env cleanup hook is executed, env is about to exit"); + auto observerEnvHookWorker = reinterpret_cast(obj); + // Prevent concurrency with NAPIInnerObserver destructors + auto observer = observerEnvHookWorker->observer_.lock(); + if (observer == nullptr) { + LOG_ERROR("observer is nullptr"); + return; + } + std::lock_guard lck(observer->envMutex_); + observer->DeleteReference(); + observer->env_ = nullptr; +} + } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/js/napi/dataShare/src/native_datashare_module.cpp b/data_share/frameworks/js/napi/dataShare/src/native_datashare_module.cpp index 13485c213dbe9b7ebc5def78c8454d8b1ee1f7d0..802c0278ec6581ec6a8f95b8bfca9f946e2f6064 100644 --- a/data_share/frameworks/js/napi/dataShare/src/native_datashare_module.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/native_datashare_module.cpp @@ -18,6 +18,7 @@ #include "napi/native_node_api.h" #include "napi_datashare_const_properties.h" #include "napi_datashare_helper.h" +#include "napi_dataproxy_handle.h" namespace OHOS { namespace DataShare { @@ -31,6 +32,7 @@ static napi_value Init(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("createDataShareHelper", NapiDataShareHelper::Napi_CreateDataShareHelper), DECLARE_NAPI_FUNCTION("enableSilentProxy", NapiDataShareHelper::EnableSilentProxy), DECLARE_NAPI_FUNCTION("disableSilentProxy", NapiDataShareHelper::DisableSilentProxy), + DECLARE_NAPI_FUNCTION("createDataProxyHandle", NapiDataProxyHandle::Napi_CreateDataProxyHandle), }; napi_status status = napi_define_properties(env, exports, sizeof(desc) / sizeof(napi_property_descriptor), desc); LOG_DEBUG("napi_define_properties status : %{public}d", status); diff --git a/data_share/frameworks/js/napi/observer/include/napi_observer.h b/data_share/frameworks/js/napi/observer/include/napi_observer.h index d5d2cca27ba6d71c2b236253e62573055dab052f..5edc516fad1343f2f7ab99d8a2f5acb6a14999b3 100644 --- a/data_share/frameworks/js/napi/observer/include/napi_observer.h +++ b/data_share/frameworks/js/napi/observer/include/napi_observer.h @@ -22,12 +22,14 @@ #include "napi/native_api.h" #include "napi/native_common.h" #include "napi/native_node_api.h" +#include "dataproxy_handle_common.h" namespace OHOS { namespace DataShare { -class NapiObserver { +class NapiObserver : public std::enable_shared_from_this { public: NapiObserver(napi_env env, napi_value callback); + void RegisterEnvCleanHook(); virtual ~NapiObserver(); virtual bool operator==(const NapiObserver &rhs) const; virtual bool operator!=(const NapiObserver &rhs) const; @@ -38,23 +40,36 @@ protected: std::function getParam; explicit ObserverWorker(std::shared_ptr observerIn) : observer_(observerIn) {} }; + struct ObserverEnvHookWorker { + std::weak_ptr observer_; + ObserverEnvHookWorker(std::shared_ptr observerIn): observer_(observerIn) {} + }; static void CallbackFunc(ObserverWorker *observerWorker); + static void CleanEnv(void *obj); napi_env env_ = nullptr; napi_ref ref_ = nullptr; uv_loop_s *loop_ = nullptr; + std::unique_ptr envMutexPtr_; + ObserverEnvHookWorker* observerEnvHookWorker_ = nullptr; }; -class NapiRdbObserver final: public NapiObserver, public std::enable_shared_from_this { +class NapiRdbObserver final: public NapiObserver { public: NapiRdbObserver(napi_env env, napi_value callback) : NapiObserver(env, callback) {}; void OnChange(const RdbChangeNode &changeNode); }; -class NapiPublishedObserver final: public NapiObserver, public std::enable_shared_from_this { +class NapiPublishedObserver final: public NapiObserver { public: NapiPublishedObserver(napi_env env, napi_value callback) : NapiObserver(env, callback) {}; void OnChange(PublishedDataChangeNode &changeNode); }; + +class NapiProxyDataObserver final: public NapiObserver { +public: + NapiProxyDataObserver(napi_env env, napi_value callback) : NapiObserver(env, callback) {}; + void OnChange(const std::vector &changeNode); +}; } // namespace DataShare } // namespace OHOS #endif //NAPI_RDB_OBSERVER_H diff --git a/data_share/frameworks/js/napi/observer/include/napi_subscriber_manager.h b/data_share/frameworks/js/napi/observer/include/napi_subscriber_manager.h index 3c06ef060805abe852926be183470411aed03552..552c92368527b3c06382c28fc772feead885de4f 100644 --- a/data_share/frameworks/js/napi/observer/include/napi_subscriber_manager.h +++ b/data_share/frameworks/js/napi/observer/include/napi_subscriber_manager.h @@ -26,6 +26,8 @@ #include "napi/native_common.h" #include "napi/native_node_api.h" #include "napi_observer.h" +#include "dataproxy_handle.h" +#include "dataproxy_handle_common.h" namespace OHOS { namespace DataShare { @@ -117,6 +119,42 @@ private: std::weak_ptr dataShareHelper_; ConcurrentMap lastChangeNodeMap_; }; + +struct NapiProxyDataObserverMapKey { + std::string uri_; + NapiProxyDataObserverMapKey(const std::string &uri) : uri_(uri) {}; + bool operator==(const NapiProxyDataObserverMapKey &node) const + { + return uri_ == node.uri_; + } + bool operator!=(const NapiProxyDataObserverMapKey &node) const + { + return !(node == *this); + } + bool operator<(const NapiProxyDataObserverMapKey &node) const + { + return uri_ < node.uri_; + } + operator std::string() const + { + return uri_; + } +}; + +class NapiProxyDataSubscriberManager : public NapiCallbacksManager { +public: + using Key = NapiProxyDataObserverMapKey; + using Observer = NapiProxyDataObserver; + using BaseCallbacks = NapiCallbacksManager; + explicit NapiProxyDataSubscriberManager(std::weak_ptr dataProxyHandle) + : dataProxyHandle_(dataProxyHandle){}; + std::vector AddObservers(napi_env env, napi_value callback, const std::vector &uris); + std::vector DelObservers(napi_env env, napi_value callback, const std::vector &uris); + void Emit(const std::vector &changeNode); + +private: + std::weak_ptr dataProxyHandle_; +}; } // namespace DataShare } // namespace OHOS #endif //NAPI_RDB_SUBSCRIBER_MANAGER_H diff --git a/data_share/frameworks/js/napi/observer/src/napi_observer.cpp b/data_share/frameworks/js/napi/observer/src/napi_observer.cpp index 3b5fbfcfe99a3e7441e4c577f6a1c739bfba8f7c..c99a4410d0da1ca04da4cabaa35c917cdfdc5c03 100644 --- a/data_share/frameworks/js/napi/observer/src/napi_observer.cpp +++ b/data_share/frameworks/js/napi/observer/src/napi_observer.cpp @@ -15,6 +15,7 @@ #include "napi_observer.h" +#include "dataproxy_handle_common.h" #include "datashare_js_utils.h" #include "datashare_log.h" @@ -22,6 +23,7 @@ namespace OHOS { namespace DataShare { NapiObserver::NapiObserver(napi_env env, napi_value callback) : env_(env) { + envMutexPtr_ = std::make_unique(); napi_create_reference(env, callback, 1, &ref_); napi_get_uv_event_loop(env, &loop_); } @@ -30,11 +32,17 @@ void NapiObserver::CallbackFunc(ObserverWorker *observerWorker) { LOG_DEBUG("ObsCallbackFunc start"); std::shared_ptr observer = observerWorker->observer_.lock(); - if (observer == nullptr || observer->ref_ == nullptr) { + if (observer == nullptr || observer->ref_ == nullptr || observer->envMutexPtr_ == nullptr) { LOG_ERROR("rdbObserver->ref_ is nullptr"); delete observerWorker; return; } + std::lock_guard lck(*observer->envMutexPtr_); + if (observer->env_ == nullptr) { + LOG_ERROR("rdbObserver->env_ is nullptr"); + delete observerWorker; + return; + } napi_handle_scope scope = nullptr; napi_open_handle_scope(observer->env_, &scope); if (scope == nullptr) { @@ -61,9 +69,15 @@ void NapiObserver::CallbackFunc(ObserverWorker *observerWorker) NapiObserver::~NapiObserver() { + if (env_ == nullptr) { + LOG_ERROR("env_ is nullptr"); + return; + } + if (ref_ != nullptr) { - auto task = [env = env_, ref = ref_]() { + auto task = [env = env_, ref = ref_, observerEnvHookWorker = observerEnvHookWorker_]() { napi_delete_reference(env, ref); + napi_remove_env_cleanup_hook(env, &CleanEnv, observerEnvHookWorker); }; int ret = napi_send_event(env_, task, napi_eprio_immediate); if (ret != 0) { @@ -71,6 +85,10 @@ NapiObserver::~NapiObserver() } ref_ = nullptr; } + if (observerEnvHookWorker_ != nullptr) { + delete observerEnvHookWorker_; + observerEnvHookWorker_ = nullptr; + } } bool NapiObserver::operator==(const NapiObserver &rhs) const @@ -95,11 +113,45 @@ bool NapiObserver::operator!=(const NapiObserver &rhs) const return !(rhs == *this); } +void NapiObserver::RegisterEnvCleanHook() +{ + observerEnvHookWorker_ = new (std::nothrow) ObserverEnvHookWorker(shared_from_this()); + if (observerEnvHookWorker_ == nullptr) { + LOG_ERROR("Failed to create observerEnvHookWorker_"); + return; + } + napi_add_env_cleanup_hook(env_, &CleanEnv, observerEnvHookWorker_); +} + +void NapiObserver::CleanEnv(void *obj) +{ + LOG_INFO("Napi env cleanup hook is executed, env is about to exit"); + auto observerEnvHookWorker = reinterpret_cast(obj); + // Prevent concurrency with NAPIInnerObserver destructors + auto observer = observerEnvHookWorker->observer_.lock(); + if (observer == nullptr || observer->envMutexPtr_ == nullptr) { + LOG_ERROR("observer or observer->envMutexPtr_ is nullptr"); + delete observerEnvHookWorker; + return; + } + std::lock_guard lck(*observer->envMutexPtr_); + if (observer->ref_ != nullptr) { + napi_delete_reference(observer->env_, observer->ref_); + observer->ref_ = nullptr; + } + observer->env_ = nullptr; +} + void NapiRdbObserver::OnChange(const RdbChangeNode &changeNode) { LOG_DEBUG("NapiRdbObserver onchange Start"); - if (ref_ == nullptr) { - LOG_ERROR("ref_ is nullptr"); + if (ref_ == nullptr || envMutexPtr_ == nullptr) { + LOG_ERROR("ref_ or envMutexPtr_ is nullptr"); + return; + } + std::lock_guard lck(*envMutexPtr_); + if (env_ == nullptr) { + LOG_ERROR("env_ is nullptr"); return; } ObserverWorker *observerWorker = new (std::nothrow) ObserverWorker(shared_from_this()); @@ -125,8 +177,13 @@ void NapiRdbObserver::OnChange(const RdbChangeNode &changeNode) void NapiPublishedObserver::OnChange(PublishedDataChangeNode &changeNode) { LOG_DEBUG("NapiPublishedObserver onchange Start"); - if (ref_ == nullptr) { - LOG_ERROR("ref_ is nullptr"); + if (ref_ == nullptr || envMutexPtr_ == nullptr) { + LOG_ERROR("ref_ or envMutexPtr_ is nullptr"); + return; + } + std::lock_guard lck(*envMutexPtr_); + if (env_ == nullptr) { + LOG_ERROR("env_ is nullptr"); return; } ObserverWorker *observerWorker = new (std::nothrow) ObserverWorker(shared_from_this()); @@ -149,5 +206,39 @@ void NapiPublishedObserver::OnChange(PublishedDataChangeNode &changeNode) } LOG_DEBUG("NapiRdbObserver onchange End: %{public}d", ret); } + +void NapiProxyDataObserver::OnChange(const std::vector &changeNode) +{ + LOG_INFO("NapiProxyDataObserver onchange Start"); + if (ref_ == nullptr || envMutexPtr_ == nullptr) { + LOG_ERROR("ref_ or envMutexPtr_ is nullptr"); + return; + } + std::lock_guard lck(*envMutexPtr_); + if (env_ == nullptr) { + LOG_ERROR("env_ is nullptr"); + return; + } + ObserverWorker *observerWorker = new (std::nothrow) ObserverWorker(shared_from_this()); + if (observerWorker == nullptr) { + LOG_ERROR("Failed to create observerWorker"); + return; + } + std::shared_ptr> node = + std::make_shared>(std::move(changeNode)); + observerWorker->getParam = [node](napi_env env) { + return DataShareJSUtils::Convert2JSValue(env, *node); + }; + + auto task = [observerWorker]() { + NapiObserver::CallbackFunc(observerWorker); + }; + int ret = napi_send_event(env_, task, napi_eprio_immediate); + if (ret != 0) { + LOG_ERROR("napi_send_event failed: %{public}d", ret); + delete observerWorker; + } + LOG_INFO("NapiProxyDataObserver onchange End: %{public}d", ret); +} } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/js/napi/observer/src/napi_subscriber_manager.cpp b/data_share/frameworks/js/napi/observer/src/napi_subscriber_manager.cpp index 493d45442aa0001d9e8153c6c2ba20743bd6908d..34a0af836323f37db19f905cb62155a86f0ccae4 100644 --- a/data_share/frameworks/js/napi/observer/src/napi_subscriber_manager.cpp +++ b/data_share/frameworks/js/napi/observer/src/napi_subscriber_manager.cpp @@ -14,7 +14,10 @@ */ #include "napi_subscriber_manager.h" +#include +#include +#include "dataproxy_handle_common.h" #include "datashare_log.h" namespace OHOS { @@ -32,8 +35,10 @@ std::vector NapiRdbSubscriberManager::AddObservers(napi_env env std::for_each(uris.begin(), uris.end(), [&keys, &templateId](auto &uri) { keys.emplace_back(uri, templateId); }); + auto rdbObserver = std::make_shared(env, callback); + rdbObserver->RegisterEnvCleanHook(); return BaseCallbacks::AddObservers( - keys, std::make_shared(env, callback), + keys, rdbObserver, [this](const std::vector &localRegisterKeys, const std::shared_ptr observer) { Emit(localRegisterKeys, observer); }, @@ -133,8 +138,10 @@ std::vector NapiPublishedSubscriberManager::AddObservers(napi_e std::for_each(uris.begin(), uris.end(), [&keys, &subscriberId](auto &uri) { keys.emplace_back(uri, subscriberId); }); + auto publishedObserver = std::make_shared(env, callback); + publishedObserver->RegisterEnvCleanHook(); return BaseCallbacks::AddObservers( - keys, std::make_shared(env, callback), + keys, publishedObserver, [this](const std::vector &localRegisterKeys, const std::shared_ptr observer) { Emit(localRegisterKeys, observer); }, @@ -239,5 +246,98 @@ void NapiPublishedSubscriberManager::Emit(const std::vector &keys, const st } observer->OnChange(node); } + +std::vector NapiProxyDataSubscriberManager::AddObservers(napi_env env, napi_value callback, + const std::vector &uris) +{ + std::vector result = {}; + auto dataProxyHandle = dataProxyHandle_.lock(); + if (dataProxyHandle == nullptr) { + LOG_ERROR("dataProxyHandle is nullptr"); + return result; + } + + std::vector keys; + std::for_each(uris.begin(), uris.end(), [&keys](auto &uri) { + keys.emplace_back(uri); + }); + auto proxyDataObserver = std::make_shared(env, callback); + proxyDataObserver->RegisterEnvCleanHook(); + return BaseCallbacks::AddObservers( + keys, proxyDataObserver, + [&dataProxyHandle, this](const std::vector &firstAddKeys, + const std::shared_ptr observer, std::vector &opResult) { + std::vector firstAddUris; + std::for_each(firstAddKeys.begin(), firstAddKeys.end(), [&firstAddUris](auto &result) { + firstAddUris.emplace_back(result); + }); + if (firstAddUris.empty()) { + return; + } + auto subResults = dataProxyHandle->SubscribeProxyData(firstAddUris, + [this](const std::vector &changeInfo) { + Emit(changeInfo); + }); + std::vector failedKeys; + for (auto &subResult : subResults) { + opResult.emplace_back(subResult); + if (subResult.result_ != SUCCESS) { + failedKeys.emplace_back(subResult.uri_); + LOG_WARN("registered failed, uri is %{public}s", subResult.uri_.c_str()); + } + } + if (failedKeys.size() > 0) { + BaseCallbacks::DelObservers(failedKeys, observer); + } + }); +} + +std::vector NapiProxyDataSubscriberManager::DelObservers(napi_env env, napi_value callback, + const std::vector &uris) +{ + std::vector result = {}; + auto dataProxyHandle = dataProxyHandle_.lock(); + if (dataProxyHandle == nullptr) { + LOG_ERROR("dataProxyHandle is nullptr"); + return result; + } + + std::vector keys; + std::for_each(uris.begin(), uris.end(), [&keys](auto &uri) { + keys.emplace_back(uri); + }); + return BaseCallbacks::DelObservers(keys, callback == nullptr ? nullptr : std::make_shared(env, callback), + [&dataProxyHandle, &callback, &uris, this](const std::vector &lastDelKeys, + const std::shared_ptr &observer, std::vector &opResult) { + std::vector lastDelUris; + std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [&lastDelUris, this](auto &result) { + lastDelUris.emplace_back(result); + }); + if (lastDelUris.empty()) { + return; + } + auto unsubResult = dataProxyHandle->UnsubscribeProxyData(lastDelUris); + opResult.insert(opResult.end(), unsubResult.begin(), unsubResult.end()); + }); +} + +void NapiProxyDataSubscriberManager::Emit(const std::vector &changeInfo) +{ + std::map, std::vector> results; + for (const auto &info : changeInfo) { + Key key(info.uri_); + auto callbacks = BaseCallbacks::GetEnabledObservers(key); + if (callbacks.empty()) { + LOG_WARN("emit but nobody subscribe"); + continue; + } + for (const auto &obs : callbacks) { + results[obs].emplace_back(info); + } + } + for (const auto &[callback, infos] : results) { + callback->OnChange(infos); + } +} } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/common/include/call_reporter.h b/data_share/frameworks/native/common/include/call_reporter.h index 52b83e91c8285ffa09d36238939ed36ab70c76e3..f40f84ed9deffaa5f48b9b5f9460f5881de10e5b 100644 --- a/data_share/frameworks/native/common/include/call_reporter.h +++ b/data_share/frameworks/native/common/include/call_reporter.h @@ -26,13 +26,21 @@ public: DataShareCallReporter() = default; struct CallInfo { int count = 0; + // total count for silent access threshold + int totalCount = 0; std::chrono::system_clock::time_point firstTime; + // start time of ervery 30s + std::chrono::system_clock::time_point startTime; + // print err log only once by using flag + bool logPrintFlag = false; }; - void Count(const std::string &funcName, const std::string &uri); + bool Count(const std::string &funcName, const std::string &uri); private: - ConcurrentMap callCounts; + ConcurrentMap callCounts_; static constexpr int RESET_COUNT_THRESHOLD = 100; + static constexpr int ACCESS_COUNT_THRESHOLD = 3000; // silent access threshold static constexpr std::chrono::milliseconds TIME_THRESHOLD = std::chrono::milliseconds(30000); + void UpdateCallCounts(const std::string &funcName, int &overCount, int64_t &firstCallTime, bool &isOverThreshold); }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/common/include/callbacks_manager.h b/data_share/frameworks/native/common/include/callbacks_manager.h index 3c7fcd3f8f93216bfcec5f3d0e46873ef5ceba8b..3a3998313cbe96f0835746859a54481153985a7a 100644 --- a/data_share/frameworks/native/common/include/callbacks_manager.h +++ b/data_share/frameworks/native/common/include/callbacks_manager.h @@ -22,6 +22,7 @@ #include "datashare_errno.h" #include "datashare_log.h" #include "datashare_template.h" +#include "dataproxy_handle_common.h" namespace OHOS::DataShare { template @@ -40,31 +41,49 @@ public: std::function &, const std::shared_ptr &observer, std::vector &)>); + std::vector AddObservers(const std::vector &keys, void *subscriber, + const std::shared_ptr observer, + std::function &, const std::shared_ptr &observer, + std::vector &)>); + std::vector DelObservers(const std::vector &keys, void *subscriber, std::function &, std::vector &)> processOnLastDel = CallbacksManager::DefaultProcess); + std::vector DelProxyDataObservers(const std::vector &keys, void *subscriber, + std::function &, std::vector &)> processOnLastDel = + CallbacksManager::ProxyDataDefaultProcess); + std::vector DelObservers(void *subscriber, std::function &, std::vector &)> processOnLastDel = CallbacksManager::DefaultProcess); + std::vector DelObservers(void *subscriber, + std::function &, std::vector &)> processOnLastDel); + std::vector EnableObservers(const std::vector &keys, void *subscriber, - std::function> &)> processOnLocalEnabled, - std::function &, std::vector &)>); + std::function> &)> processOnLocalEnabled = + CallbacksManager::DefaultProcessOnLocalEnabled, + std::function &, std::vector &)> processOnFirstAdd = + CallbacksManager::DefaultProcess); std::vector DisableObservers(const std::vector &keys, void *subscriber, std::function &, std::vector &)> processOnLastDel = CallbacksManager::DefaultProcess); std::vector> GetEnabledObservers(const Key &); + std::vector> GetObserversAndSetNotifiedOn(const Key &); int GetAllSubscriberSize(); int GetAllSubscriberSize(const Key &key); std::vector GetKeys(); void SetObserversNotifiedOnEnabled(const Key &key); + bool IsObserversNotifiedOnEnabled(const Key &key, std::shared_ptr &observer); private: static void DefaultProcess(const std::vector &, std::vector &){}; + static void ProxyDataDefaultProcess(const std::vector &, std::vector &){}; + static void DefaultProcessOnLocalEnabled(std::map> &){}; struct ObserverNode { std::shared_ptr observer_; bool enabled_; @@ -79,7 +98,10 @@ private: }; void DelLocalObservers(const Key &key, void *subscriber, std::vector &lastDelKeys, std::vector &result); + void DelLocalObservers(const Key &key, void *subscriber, std::vector &lastDelKeys, + std::vector &result); void DelLocalObservers(void *subscriber, std::vector &lastDelKeys, std::vector &result); + void DelLocalObservers(void *subscriber, std::vector &lastDelKeys, std::vector &result); std::recursive_mutex mutex_{}; std::map> callbacks_; }; @@ -115,6 +137,23 @@ std::vector CallbacksManager::AddObservers(const return result; } +template +std::vector CallbacksManager::AddObservers(const std::vector &keys, + void *subscriber, const std::shared_ptr observer, + std::function &, + const std::shared_ptr &observer, std::vector &)> processOnFirstAdd) +{ + std::vector result; + { + std::lock_guard lck(mutex_); + for (auto &key : keys) { + callbacks_[key].emplace_back(observer, subscriber); + } + } + processOnFirstAdd(keys, observer, result); + return result; +} + template std::vector CallbacksManager::GetKeys() { @@ -137,6 +176,15 @@ void CallbacksManager::DelLocalObservers(void *subscriber, std::v } } +template +void CallbacksManager::DelLocalObservers(void *subscriber, std::vector &lastDelKeys, + std::vector &result) +{ + for (auto &it : callbacks_) { + DelLocalObservers(it.first, subscriber, lastDelKeys, result); + } +} + template void CallbacksManager::DelLocalObservers(const Key &key, void *subscriber, std::vector &lastDelKeys, std::vector &result) @@ -162,6 +210,31 @@ void CallbacksManager::DelLocalObservers(const Key &key, void *su lastDelKeys.emplace_back(key); } +template +void CallbacksManager::DelLocalObservers(const Key &key, void *subscriber, + std::vector &lastDelKeys, std::vector &result) +{ + auto it = callbacks_.find(key); + if (it == callbacks_.end()) { + result.emplace_back(key, INNER_ERROR); + return; + } + std::vector &callbacks = it->second; + auto callbackIt = callbacks.begin(); + while (callbackIt != callbacks.end()) { + if (callbackIt->subscriber_ != subscriber) { + callbackIt++; + continue; + } + callbackIt = callbacks.erase(callbackIt); + } + if (!it->second.empty()) { + result.emplace_back(key, INNER_ERROR); + return; + } + lastDelKeys.emplace_back(key); +} + template std::vector CallbacksManager::DelObservers(void *subscriber, std::function &, std::vector &)> processOnLastDel) @@ -204,6 +277,48 @@ std::vector CallbacksManager::DelObservers(const return result; } +template +std::vector CallbacksManager::DelObservers(void *subscriber, + std::function &, std::vector &)> processOnLastDel) +{ + std::vector result; + std::vector lastDelKeys; + { + std::lock_guard lck(mutex_); + DelLocalObservers(subscriber, lastDelKeys, result); + if (lastDelKeys.empty()) { + return result; + } + for (auto &key : lastDelKeys) { + callbacks_.erase(key); + } + } + processOnLastDel(lastDelKeys, result); + return result; +} + +template +std::vector CallbacksManager::DelProxyDataObservers(const std::vector &keys, + void *subscriber, std::function &, std::vector &)> processOnLastDel) +{ + std::vector result; + std::vector lastDelKeys; + { + std::lock_guard lck(mutex_); + for (auto &key : keys) { + DelLocalObservers(key, subscriber, lastDelKeys, result); + } + if (lastDelKeys.empty()) { + return result; + } + for (auto &key : lastDelKeys) { + callbacks_.erase(key); + } + } + processOnLastDel(lastDelKeys, result); + return result; +} + template std::vector> CallbacksManager::GetEnabledObservers(const Key &inputKey) { @@ -221,6 +336,34 @@ std::vector> CallbacksManager::GetEnabl return results; } +template +std::vector> CallbacksManager::GetObserversAndSetNotifiedOn( + const Key &inputKey) +{ + std::lock_guard lck(mutex_); + auto it = callbacks_.find(inputKey); + if (it == callbacks_.end()) { + return std::vector>(); + } + std::vector> results; + uint32_t num = 0; + std::vector &callbacks = it->second; + for (auto &value : callbacks) { + if ((value.enabled_ && value.observer_ != nullptr)) { + results.emplace_back(value.observer_); + // if get this enabled observer and notify, it's isNotifyOnEnabled flag should be reset to false + value.isNotifyOnEnabled_ = false; + } else { + num++; + value.isNotifyOnEnabled_ = true; + } + } + if (num > 0) { + LOG_INFO("total %{public}zu, not refreshed %{public}u", callbacks.size(), num); + } + return results; +} + template std::vector CallbacksManager::EnableObservers( const std::vector &keys, void *subscriber, @@ -293,7 +436,10 @@ std::vector CallbacksManager::DisableObservers(c bool hasDisabled = false; for (auto &item : callbacks_[key]) { if (item.subscriber_ == subscriber) { - item.enabled_ = false; + if (item.enabled_) { + item.enabled_ = false; + item.isNotifyOnEnabled_ = false; + } hasDisabled = true; } } @@ -355,5 +501,22 @@ void CallbacksManager::SetObserversNotifiedOnEnabled(const Key &k LOG_INFO("total %{public}zu, not refreshed %{public}u", callbacks.size(), num); } } + +template +bool CallbacksManager::IsObserversNotifiedOnEnabled(const Key &key, std::shared_ptr &observer) +{ + std::lock_guard lck(mutex_); + auto it = callbacks_.find(key); + if (it == callbacks_.end()) { + return false; + } + std::vector &callbacks = it->second; + for (auto &node : callbacks) { + if (node.observer_ == observer) { + return node.isNotifyOnEnabled_; + } + } + return false; +} } // namespace OHOS::DataShare #endif // DATA_SHARE_CALLBACKS_MANAGER_H diff --git a/data_share/frameworks/native/common/include/datashare_common.h b/data_share/frameworks/native/common/include/datashare_common.h new file mode 100644 index 0000000000000000000000000000000000000000..8f0324a76422ee6a3b9e047a0b88339516407bcc --- /dev/null +++ b/data_share/frameworks/native/common/include/datashare_common.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 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_COMMON_H +#define DATASHARE_COMMON_H + +#include "datashare_option.h" + +namespace OHOS::DataShare { +constexpr int MAX_THREADS = 2; +constexpr int MIN_THREADS = 0; +constexpr const char *DATASHARE_EXECUTOR_NAME = "DShare_Executor"; + +struct UriInfo { + std::string uri; + std::string extUri; + DataShareOption option; +}; +} +#endif // DATASHARE_COMMON_H \ No newline at end of file diff --git a/data_share/frameworks/native/common/include/datashare_itypes_utils.h b/data_share/frameworks/native/common/include/datashare_itypes_utils.h index 61c566dd7e80c767e2670999e50cfcc1a8e72be2..1475a72b67fc254ba823020ece674af4bf15d03f 100644 --- a/data_share/frameworks/native/common/include/datashare_itypes_utils.h +++ b/data_share/frameworks/native/common/include/datashare_itypes_utils.h @@ -16,9 +16,12 @@ #ifndef DATASHARE_COMMON_ITYPES_UTIL_H #define DATASHARE_COMMON_ITYPES_UTIL_H +#include "dataproxy_handle_common.h" #include "datashare_operation_statement.h" +#include "datashare_common.h" #include "datashare_predicates.h" #include "datashare_template.h" +#include "datashare_value_object.h" #include "datashare_values_bucket.h" #include "itypes_util.h" #include "uri.h" @@ -40,6 +43,17 @@ using ExecResult = DataShare::ExecResult; using ExecResultSet = DataShare::ExecResultSet; using UpdateOperation = DataShare::UpdateOperation; using BatchUpdateResult = DataShare::BatchUpdateResult; +using DataShareProxyData = DataShare::DataShareProxyData; +using DataProxyConfig = DataShare::DataProxyConfig; +using DataProxyType = DataShare::DataProxyType; +using DataProxyResult = DataShare::DataProxyResult; +using DataProxyErrorCode = DataShare::DataProxyErrorCode; +using DataShareValueObject = DataShare::DataShareValueObject; +using DataProxyValue = DataShare::DataProxyValue; +using DataProxyGetResult = DataShare::DataProxyGetResult; +using DataProxyChangeInfo = DataShare::DataProxyChangeInfo; +using UriInfo = DataShare::UriInfo; +using RegisterOption = DataShare::RegisterOption; template<> bool Marshalling(const BatchUpdateResult &result, MessageParcel &parcel); @@ -159,5 +173,59 @@ bool UnmarshalPredicates(Predicates &predicates, MessageParcel &parcel); bool MarshalValuesBucketVec(const std::vector &values, MessageParcel &parcel); bool UnmarshalValuesBucketVec(std::vector &values, MessageParcel &parcel); + +template<> +bool Marshalling(const DataShareProxyData &proxyData, MessageParcel &parcel); + +template<> +bool Unmarshalling(DataShareProxyData &proxyData, MessageParcel &parcel); + +template<> +bool Marshalling(const DataProxyConfig &proxyData, MessageParcel &parcel); + +template<> +bool Unmarshalling(DataProxyConfig &proxyData, MessageParcel &parcel); + +template<> +bool Marshalling(const DataProxyResult &result, MessageParcel &parcel); + +template<> +bool Unmarshalling(DataProxyResult &result, MessageParcel &parcel); + +template<> +bool Marshalling(const DataShareValueObject &result, MessageParcel &parcel); + +template<> +bool Unmarshalling(DataShareValueObject &result, MessageParcel &parcel); + +template<> +bool Marshalling(const DataProxyValue &result, MessageParcel &parcel); + +template<> +bool Unmarshalling(DataProxyValue &result, MessageParcel &parcel); + +template<> +bool Marshalling(const DataProxyGetResult &result, MessageParcel &parcel); + +template<> +bool Unmarshalling(DataProxyGetResult &result, MessageParcel &parcel); + +template<> +bool Marshalling(const DataProxyChangeInfo &result, MessageParcel &parcel); + +template<> +bool Unmarshalling(DataProxyChangeInfo &result, MessageParcel &parcel); + +template<> +bool Marshalling(const UriInfo &result, MessageParcel &parcel); + +template<> +bool Unmarshalling(UriInfo &result, MessageParcel &parcel); + +template<> +bool Marshalling(const RegisterOption &option, MessageParcel &parcel); + +template<> +bool Unmarshalling(RegisterOption &option, MessageParcel &parcel); } #endif 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 2b35d14c24d53f1fffaf84dfe4d69d3d317afee6..877838923b11f39884682f0abbccca9ff18f6d16 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 @@ -41,7 +41,11 @@ enum class IDataShareInterfaceCode { CMD_INSERT_EX, CMD_UPDATE_EX, CMD_DELETE_EX, - CMD_USER_DEFINE_FUNC + CMD_USER_DEFINE_FUNC, + CMD_REGISTER_OBSERVEREXT_PROVIDER, + CMD_UNREGISTER_OBSERVEREXT_PROVIDER, + CMD_NOTIFY_CHANGEEXT_PROVIDER, + CMD_OPEN_FILE_WITH_ERR_CODE, }; enum class ISharedResultInterfaceCode { @@ -99,6 +103,11 @@ enum class DataShareServiceInterfaceCode { DATA_SHARE_SERVICE_CMD_INSERTEX, DATA_SHARE_SERVICE_CMD_DELETEEX, DATA_SHARE_SERVICE_CMD_UPDATEEX, + DATA_SHARE_SERVICE_CMD_PROXY_PUBLISH, + DATA_SHARE_SERVICE_CMD_PROXY_DELETE, + DATA_SHARE_SERVICE_CMD_PROXY_GET, + DATA_SHARE_SERVICE_CMD_SUBSCRIBE_PROXY_DATA, + DATA_SHARE_SERVICE_CMD_UNSUBSCRIBE_PROXY_DATA, DATA_SHARE_SERVICE_CMD_MAX, DATA_SHARE_SERVICE_CMD_QUERY_SYSTEM = DATA_SHARE_CMD_SYSTEM_CODE, DATA_SHARE_SERVICE_CMD_ADD_TEMPLATE_SYSTEM, diff --git a/data_share/frameworks/native/common/include/hitrace.h b/data_share/frameworks/native/common/include/hitrace.h index 11a09b7f8cee9f7266251712a351717b907e2437..053c1bb0b1c38408cb55b7ff0c999906e9efd9f4 100644 --- a/data_share/frameworks/native/common/include/hitrace.h +++ b/data_share/frameworks/native/common/include/hitrace.h @@ -26,12 +26,12 @@ class HiTrace final { public: inline HiTrace(const std::string &value) { - StartTrace(HITRACE_TAG_DISTRIBUTEDDATA, value); + StartTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_TAG_DISTRIBUTEDDATA, value.c_str(), ""); } inline ~HiTrace() { - FinishTrace(HITRACE_TAG_DISTRIBUTEDDATA); + FinishTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_TAG_DISTRIBUTEDDATA); } }; } // namespace DataShare 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 538e1c0fcc2a0f1300b16d188c4263251c351bac..deb8c21ac2ae0e016df73b2917262f25242fad60 100644 --- a/data_share/frameworks/native/common/include/idata_share_service.h +++ b/data_share/frameworks/native/common/include/idata_share_service.h @@ -22,12 +22,14 @@ #include "datashare_errno.h" #include "data_proxy_observer.h" #include "datashare_business_error.h" +#include "datashare_common.h" #include "datashare_predicates.h" #include "datashare_result_set.h" #include "datashare_template.h" #include "datashare_values_bucket.h" #include "distributeddata_data_share_ipc_interface_code.h" #include "uri.h" +#include "dataproxy_handle_common.h" namespace OHOS::DataShare { class IDataShareService : public IRemoteBroker { @@ -97,6 +99,20 @@ public: virtual std::pair DeleteEx(const Uri &uri, const Uri &extUri, const DataSharePredicates &predicates) = 0; + + virtual std::vector PublishProxyData(const std::vector &proxyData, + const DataProxyConfig &proxyConfig) = 0; + + virtual std::vector DeleteProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) = 0; + + virtual std::vector GetProxyData(const std::vector uris, + const DataProxyConfig &proxyConfig) = 0; + + virtual std::vector SubscribeProxyData(const std::vector &uris, + const sptr &observer) = 0; + + virtual std::vector UnsubscribeProxyData(const std::vector &uris) = 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 a5300a02631767f075031219e94dd3a3bb71c024..a64a39416b7aa5751fd7493cd84012bbce648aee 100644 --- a/data_share/frameworks/native/common/include/idatashare.h +++ b/data_share/frameworks/native/common/include/idatashare.h @@ -18,6 +18,7 @@ #include +#include "data_ability_observer_interface.h" #include "datashare_business_error.h" #include "datashare_operation_statement.h" #include "datashare_predicates.h" @@ -32,6 +33,7 @@ class IDataAbilityObserver; } namespace DataShare { +using ChangeInfo = AAFwk::ChangeInfo; class IDataShare : public IRemoteBroker { public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DataShare.IDataShare"); @@ -66,6 +68,14 @@ public: virtual bool NotifyChange(const Uri &uri) = 0; + virtual int RegisterObserverExtProvider(const Uri &uri, const sptr &dataObserver, + bool isDescendants, RegisterOption option) = 0; + + virtual int UnregisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver) = 0; + + virtual int NotifyChangeExtProvider(const ChangeInfo &changeInfo) = 0; + virtual Uri NormalizeUri(const Uri &uri) = 0; virtual Uri DenormalizeUri(const Uri &uri) = 0; diff --git a/data_share/frameworks/native/common/include/serializable.h b/data_share/frameworks/native/common/include/serializable.h new file mode 100644 index 0000000000000000000000000000000000000000..49f3083f905e5f4329a96ba2fbf4a444f4860d4a --- /dev/null +++ b/data_share/frameworks/native/common/include/serializable.h @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2025 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_SERIALIZABLE_H +#define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_SERIALIZABLE_H +#include +#include +#include "visibility.h" +#ifndef JSON_NOEXCEPTION +#define JSON_NOEXCEPTION +#endif +#include +#include +namespace OHOS { +namespace DataShare { +#ifndef GET_NAME +#define GET_NAME(value) #value +#endif +struct Serializable { +public: + using json = nlohmann::json; + using size_type = nlohmann::json::size_type; + using error_handler_t = nlohmann::detail::error_handler_t; + + API_EXPORT json Marshall() const; + template + static std::string Marshall(T &values) + { + json root; + SetValue(root, values); + return root.dump(-1, ' ', false, error_handler_t::replace); + } + + API_EXPORT bool Unmarshall(const std::string &jsonStr); + template + static bool Unmarshall(const std::string &body, T &values) + { + return GetValue(ToJson(body), "", values); + } + API_EXPORT static json ToJson(const std::string &jsonStr); + API_EXPORT static bool IsJson(const std::string &jsonStr); + virtual bool Marshal(json &node) const = 0; + virtual bool Unmarshal(const json &node) = 0; + API_EXPORT static bool GetValue(const json &node, const std::string &name, std::string &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, uint32_t &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, int32_t &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, int64_t &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, uint64_t &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, uint16_t &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, bool &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, std::vector &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, Serializable &value); + API_EXPORT static bool SetValue(json &node, const std::string &value); + API_EXPORT static bool SetValue(json &node, const uint32_t &value); + API_EXPORT static bool SetValue(json &node, const int32_t &value); + API_EXPORT static bool SetValue(json &node, const int64_t &value); + API_EXPORT static bool SetValue(json &node, const double &value); + API_EXPORT static bool SetValue(json &node, const uint64_t &value); + API_EXPORT static bool SetValue(json &node, const uint16_t &value); + // Use bool & to forbid the const T * auto convert to bool, const bool will convert to const uint32_t &value; + template + API_EXPORT static std::enable_if_t, bool> SetValue(json &node, const T &value) + { + node = static_cast(value); + return true; + } + + API_EXPORT static bool SetValue(json &node, const std::vector &value); + API_EXPORT static bool SetValue(json &node, const Serializable &value); + + template + API_EXPORT static bool SetValue(json &node, const std::variant<_Types...> &input); + + template + API_EXPORT static bool GetValue(const json &node, const std::string &name, std::variant<_Types...> &value); +protected: + API_EXPORT ~Serializable() = default; + + template + static bool GetValue(const json &node, const std::string &name, std::vector &values); + + template + static bool SetValue(json &node, const std::vector &values); + + template + static bool GetValue(const json &node, const std::string &name, std::map &values); + + template + static bool SetValue(json &node, const std::map &values); + + template + static bool GetValue(const json &node, const std::string &name, T *&value); + + template + static bool SetValue(json &node, const T *value); + + template + static bool ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output); + + template + static bool ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output); + + template + static bool WriteVariant(json &node, uint32_t step, const _InTp &input); + + template + static bool WriteVariant(json &node, uint32_t step, const _InTp &input); + API_EXPORT static const json &GetSubNode(const json &node, const std::string &name); +}; + +template +bool Serializable::GetValue(const json &node, const std::string &name, std::vector &values) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_array()) { + return false; + } + bool result = true; + values.resize(subNode.size()); + for (size_type i = 0; i < subNode.size(); ++i) { + result = GetValue(subNode[i], "", values[i]) && result; + } + return result; +} + +template +bool Serializable::SetValue(json &node, const std::vector &values) +{ + bool result = true; + size_type i = 0; + node = json::value_t::array; + for (const auto &value : values) { + result = SetValue(node[i], value) && result; + i++; + } + return result; +} + +template +bool Serializable::GetValue(const json &node, const std::string &name, std::map &values) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_object()) { + return false; + } + bool result = true; + for (auto object = subNode.begin(); object != subNode.end(); ++object) { + result = GetValue(object.value(), "", values[object.key()]) && result; + } + return result; +} + +template +bool Serializable::SetValue(json &node, const std::map &values) +{ + bool result = true; + node = json::value_t::object; + for (const auto &[key, value] : values) { + result = SetValue(node[key], value) && result; + } + return result; +} + +template +bool Serializable::GetValue(const json &node, const std::string &name, T *&value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null()) { + return false; + } + value = new(std::nothrow) T(); + if (value == nullptr) { + return false; + } + bool result = GetValue(subNode, "", *value); + if (!result) { + delete value; + value = nullptr; + } + return result; +} + +template +bool Serializable::SetValue(json &node, const T *value) +{ + if (value == nullptr) { + return false; + } + return SetValue(node, *value); +} + +template +bool Serializable::SetValue(json &node, const std::variant<_Types...> &input) +{ + bool ret = SetValue(node[GET_NAME(type)], input.index()); + if (!ret) { + return ret; + } + return WriteVariant(node[GET_NAME(value)], 0, input); +} + +template +bool Serializable::GetValue(const json &node, const std::string &name, std::variant<_Types...> &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null()) { + return false; + } + uint32_t index; + bool ret = GetValue(subNode, GET_NAME(type), index); + if (!ret) { + return ret; + } + + return Serializable::ReadVariant(subNode, GET_NAME(value), 0, index, value); +} + +template +bool Serializable::WriteVariant(json &node, uint32_t step, const _InTp &input) +{ + return false; +} + +template +bool Serializable::ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output) +{ + if (step == index) { + _First result; + if (!Serializable::GetValue(node, name, result)) { + return false; + } + output = result; + return true; + } + return Serializable::ReadVariant<_OutTp, _Rest...>(node, name, step + 1, index, output); +} + +template +bool Serializable::WriteVariant(json &node, uint32_t step, const _InTp &input) +{ + if (step == input.index()) { + return Serializable::SetValue(node, std::get<_First>(input)); + } + return WriteVariant<_InTp, _Rest...>(node, step + 1, input); +} + +template +bool Serializable::ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output) +{ + return false; +} +} // namespace DistributedData +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_SERIALIZABLE_H diff --git a/data_share/frameworks/native/common/src/call_reporter.cpp b/data_share/frameworks/native/common/src/call_reporter.cpp index af25b9e67725a1ad5ddd8575369371fbb8cbbd19..bf7bc65719766f500c72790af60db05a1d76632c 100644 --- a/data_share/frameworks/native/common/src/call_reporter.cpp +++ b/data_share/frameworks/native/common/src/call_reporter.cpp @@ -21,20 +21,62 @@ namespace OHOS { namespace DataShare { -void DataShareCallReporter::Count(const std::string &funcName, const std::string &uri) +// count the func call and check if the funcCount exceeds the threshold +bool 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; + // isOverThreshold means that the call count of the funcName over threshold, true means exceeded + // if exceeds the threshold, the current 30s time window will return 'true' + // and the funcCount will be reseted in the next 30s time window + bool isOverThreshold = false; + + UpdateCallCounts(funcName, overCount, firstCallTime, isOverThreshold); + + 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()); + } + // error log for over threshold and only print once + if (isOverThreshold) { + callCounts_.Compute(funcName, [funcName, now, uri](auto &key, CallInfo &callInfo) { + if (!callInfo.logPrintFlag) { + int64_t thresholdStartTime = std::chrono::duration_cast( + callInfo.startTime.time_since_epoch()).count(); + + callInfo.logPrintFlag = true; + LOG_ERROR("Over threshold, func: %{public}s, first:%{public}" PRIi64 "ms, now:%{public}" PRIi64 + "ms, uri:%{public}s", funcName.c_str(), thresholdStartTime, now, + DataShareStringUtils::Anonymous(uri).c_str()); + } + return true; + }); + } + return isOverThreshold; +} + +void DataShareCallReporter::UpdateCallCounts(const std::string &funcName, int &overCount, int64_t &firstCallTime, + bool &isOverThreshold) +{ + callCounts_.Compute(funcName, [&overCount, &firstCallTime, &isOverThreshold](auto &key, CallInfo &callInfo) { + int callCount = callInfo.count; + // totalCallCount is the call count of funcName in 30s + int totalCallCount = callInfo.totalCount; + std::chrono::system_clock::time_point nowTimeStamp = std::chrono::system_clock::now(); + int64_t now = std::chrono::duration_cast( + nowTimeStamp.time_since_epoch()).count(); if (callCount == 0) { - callInfo.firstTime = std::chrono::system_clock::now(); + callInfo.firstTime = nowTimeStamp; } 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()) { @@ -43,18 +85,27 @@ void DataShareCallReporter::Count(const std::string &funcName, const std::string callCount = 0; } callInfo.count = callCount; + + // update access control count + if (totalCallCount == 0) { + callInfo.startTime = nowTimeStamp; + } + int64_t thresholdStartTime = std::chrono::duration_cast( + callInfo.startTime.time_since_epoch()).count(); + // reset callInfo when time >= 30s + if (now - thresholdStartTime >= TIME_THRESHOLD.count()) { + callInfo.startTime = nowTimeStamp; + callInfo.totalCount = 0; + callInfo.logPrintFlag = false; + totalCallCount = 0; + } + // isOverThreshold return true when callCount >= 3000 in 30s + if (++totalCallCount >= ACCESS_COUNT_THRESHOLD) { + isOverThreshold = true; + } + callInfo.totalCount = totalCallCount; 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_itypes_utils.cpp b/data_share/frameworks/native/common/src/datashare_itypes_utils.cpp index a59643b7ef27d9507901a7be648297db73fa2660..47f231f38814ce1c95b947d393d27ef39e47ab71 100644 --- a/data_share/frameworks/native/common/src/datashare_itypes_utils.cpp +++ b/data_share/frameworks/native/common/src/datashare_itypes_utils.cpp @@ -18,7 +18,11 @@ #include #include #include +#include +#include "dataproxy_handle_common.h" #include "datashare_log.h" +#include "datashare_value_object.h" +#include "itypes_util.h" namespace OHOS::ITypesUtil { using namespace OHOS::DataShare; @@ -296,6 +300,237 @@ bool Unmarshalling(ExecResultSet &execResultSet, MessageParcel &parcel) return ITypesUtil::Unmarshal(parcel, execResultSet.results); } +template<> +bool Marshalling(const DataShareProxyData &proxyData, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, proxyData.uri_, + proxyData.value_, proxyData.isValueUndefined, proxyData.allowList_, proxyData.isAllowListUndefined); +} + +template<> +bool Unmarshalling(DataShareProxyData &proxyData, MessageParcel &parcel) +{ + return ITypesUtil::Unmarshal(parcel, proxyData.uri_, + proxyData.value_, proxyData.isValueUndefined, proxyData.allowList_, proxyData.isAllowListUndefined); +} + +template<> +bool Marshalling(const DataProxyConfig &config, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, static_cast(config.type_)); +} + +template<> +bool Unmarshalling(DataProxyConfig &config, MessageParcel &parcel) +{ + int type; + if (!ITypesUtil::Unmarshalling(type, parcel)) { + return false; + } + config.type_ = static_cast(type); + return true; +} + +template<> +bool Marshalling(const DataProxyResult &result, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, static_cast(result.result_), result.uri_); +} + +template<> +bool Unmarshalling(DataProxyResult &result, MessageParcel &parcel) +{ + int errorCode; + if (!ITypesUtil::Unmarshalling(errorCode, parcel)) { + return false; + } + result.result_ = static_cast(errorCode); + return ITypesUtil::Unmarshal(parcel, result.uri_); +} + +template<> +bool Marshalling(const DataShareValueObject &value, MessageParcel &parcel) +{ + if (!ITypesUtil::Marshal(parcel, value.value.index())) { + return false; + } + switch (value.value.index()) { + case DataShareValueObjectType::TYPE_INT: { + return ITypesUtil::Marshal(parcel, std::get(value.value)); + } + case DataShareValueObjectType::TYPE_DOUBLE: { + return ITypesUtil::Marshal(parcel, std::get(value.value)); + } + case DataShareValueObjectType::TYPE_STRING: { + return ITypesUtil::Marshal(parcel, std::get(value.value)); + } + case DataShareValueObjectType::TYPE_BOOL: { + return ITypesUtil::Marshal(parcel, std::get(value.value)); + } + default: { + LOG_ERROR("Marshal ValueObject: unknown typeId"); + return false; + } + } +} + +template<> +bool Unmarshalling(DataShareValueObject &value, MessageParcel &parcel) +{ + int32_t index; + if (!ITypesUtil::Unmarshal(parcel, index)) { + return false; + } + bool ret = true; + switch (index) { + case static_cast(DataShareValueObjectType::TYPE_INT): { + int64_t val; + ret = ITypesUtil::Unmarshal(parcel, val); + value = val; + break; + } + case static_cast(DataShareValueObjectType::TYPE_DOUBLE): { + double val; + ret = ITypesUtil::Unmarshal(parcel, val); + value = val; + break; + } + case static_cast(DataShareValueObjectType::TYPE_STRING): { + std::string val; + ret = ITypesUtil::Unmarshal(parcel, val); + value = val; + break; + } + case static_cast(DataShareValueObjectType::TYPE_BOOL): { + bool val; + ret = ITypesUtil::Unmarshal(parcel, val); + value = val; + break; + } + default: { + LOG_ERROR("Unmarshal ValueObject: unknown typeId"); + ret = false; + } + } + return ret; +} + +template<> +bool Marshalling(const DataProxyValue &value, MessageParcel &parcel) +{ + int32_t index = value.index(); + if (!ITypesUtil::Marshal(parcel, index)) { + return false; + } + switch (value.index()) { + case static_cast(DataProxyValueType::VALUE_INT): { + return ITypesUtil::Marshal(parcel, std::get(value)); + } + case static_cast(DataProxyValueType::VALUE_DOUBLE): { + return ITypesUtil::Marshal(parcel, std::get(value)); + } + case static_cast(DataProxyValueType::VALUE_STRING): { + return ITypesUtil::Marshal(parcel, std::get(value)); + } + case static_cast(DataProxyValueType::VALUE_BOOL): { + return ITypesUtil::Marshal(parcel, std::get(value)); + } + default: { + LOG_ERROR("Marshal ValueObject: unknown typeId"); + return false; + } + } +} + +template<> +bool Unmarshalling(DataProxyValue &value, MessageParcel &parcel) +{ + int32_t index; + if (!ITypesUtil::Unmarshal(parcel, index)) { + return false; + } + bool ret = true; + switch (index) { + case static_cast(DataProxyValueType::VALUE_INT): { + int64_t val; + ret = ITypesUtil::Unmarshal(parcel, val); + value = val; + break; + } + case static_cast(DataProxyValueType::VALUE_DOUBLE): { + double val; + ret = ITypesUtil::Unmarshal(parcel, val); + value = val; + break; + } + case static_cast(DataProxyValueType::VALUE_STRING): { + std::string val; + ret = ITypesUtil::Unmarshal(parcel, val); + value = val; + break; + } + case static_cast(DataProxyValueType::VALUE_BOOL): { + bool val; + ret = ITypesUtil::Unmarshal(parcel, val); + value = val; + break; + } + default: { + LOG_ERROR("Unmarshal DataProxyValue: unknown typeId"); + ret = false; + } + } + return ret; +} + +template<> +bool Marshalling(const DataProxyGetResult &result, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, static_cast(result.result_), + result.uri_, result.value_, result.allowList_); +} + +template<> +bool Unmarshalling(DataProxyGetResult &result, MessageParcel &parcel) +{ + int errorCode; + if (!ITypesUtil::Unmarshalling(errorCode, parcel)) { + return false; + } + result.result_ = static_cast(errorCode); + return ITypesUtil::Unmarshal(parcel, result.uri_, result.value_, result.allowList_); +} + +template<> +bool Marshalling(const DataProxyChangeInfo &changeInfo, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, static_cast(changeInfo.changeType_), + changeInfo.uri_, changeInfo.value_); +} + +template<> +bool Unmarshalling(DataProxyChangeInfo &changeInfo, MessageParcel &parcel) +{ + int errorCode; + if (!ITypesUtil::Unmarshalling(errorCode, parcel)) { + return false; + } + changeInfo.changeType_ = static_cast(errorCode); + return ITypesUtil::Unmarshal(parcel, changeInfo.uri_, changeInfo.value_); +} + +template<> +bool Marshalling(const UriInfo &result, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, result.uri, result.extUri, result.option.timeout); +} + +template<> +bool Unmarshalling(UriInfo &result, MessageParcel &parcel) +{ + return ITypesUtil::Unmarshal(parcel, result.uri, result.extUri, result.option.timeout); +} + template bool MarshalBasicTypeToBuffer(std::ostringstream &oss, const T &value) { @@ -974,4 +1209,17 @@ bool UnmarshalValuesBucketVec(std::vector &values, Messag std::istringstream iss(std::string(buffer, length)); return UnmarshalValuesBucketVecToBuffer(iss, values); } + +template<> +bool Marshalling(const RegisterOption &option, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, option.isReconnect); +} + +template<> +bool Unmarshalling(RegisterOption &option, MessageParcel &parcel) +{ + return ITypesUtil::Unmarshal(parcel, option.isReconnect); +} + } // namespace OHOS::ITypesUtil \ No newline at end of file diff --git a/data_share/frameworks/native/common/src/datashare_predicates.cpp b/data_share/frameworks/native/common/src/datashare_predicates.cpp new file mode 100644 index 0000000000000000000000000000000000000000..32f692128bbc7608d46971b0845d1a28a2112b14 --- /dev/null +++ b/data_share/frameworks/native/common/src/datashare_predicates.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 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 "datashare_predicates.h" +#include "datashare_itypes_utils.h" + +namespace OHOS { +namespace DataShare { + +bool DataSharePredicates::Unmarshal(DataSharePredicates &predicates, MessageParcel &parcel) +{ + return ITypesUtil::UnmarshalPredicates(predicates, parcel); +} + +bool DataSharePredicates::Marshal(const DataSharePredicates &predicates, MessageParcel &parcel) +{ + return ITypesUtil::MarshalPredicates(predicates, parcel); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file 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 196741830dfc67ea1cf5daa2c7f6781c731515da..f136874990c518613b2d547938f85206f3354f47 100644 --- a/data_share/frameworks/native/common/src/datashare_result_set.cpp +++ b/data_share/frameworks/native/common/src/datashare_result_set.cpp @@ -16,8 +16,6 @@ #include #include -#include -#include #include "adaptor.h" #include "datashare_block_writer_impl.h" @@ -26,13 +24,14 @@ #include "parcel.h" #include "shared_block.h" #include "string_ex.h" +#include "ishared_result_set.h" namespace OHOS { namespace DataShare { namespace { - // The default position of the cursor - static const int INITIAL_POS = -1; - static const size_t DEFAULT_SHARE_BLOCK_SIZE = 2 * 1024 * 1024; +// The default position of the cursor +static const int INITIAL_POS = -1; +static const size_t DEFAULT_SHARE_BLOCK_SIZE = 2 * 1024 * 1024; } // namespace int DataShareResultSet::blockId_ = 0; DataShareResultSet::DataShareResultSet() @@ -462,5 +461,18 @@ bool DataShareResultSet::Unmarshalling(MessageParcel &parcel) } return true; } -} // namespace DataShare -} // namespace OHOS \ No newline at end of file + +bool DataShareResultSet::Marshal(const std::shared_ptr resultSet, MessageParcel &parcel) +{ + if (resultSet == nullptr || !DataShare::ISharedResultSet::WriteToParcel(resultSet, parcel)) { + return false; + } + return true; +} + +std::shared_ptr DataShareResultSet::Unmarshal(MessageParcel &parcel) +{ + return DataShare::ISharedResultSet::ReadFromParcel(parcel); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/common/src/serializable.cpp b/data_share/frameworks/native/common/src/serializable.cpp new file mode 100644 index 0000000000000000000000000000000000000000..31f58670eeb972864bf13b4f674977b4c8a76321 --- /dev/null +++ b/data_share/frameworks/native/common/src/serializable.cpp @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2025 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 "serializable.h" +namespace OHOS { +namespace DataShare { +Serializable::json Serializable::Marshall() const +{ + json root; + Marshal(root); + return root; +} + +bool Serializable::Unmarshall(const std::string &jsonStr) +{ + json jsonObj = json::parse(jsonStr, nullptr, false); + if (jsonObj.is_discarded()) { + // if the string size is less than 1, means the string is invalid. + if (jsonStr.empty()) { + return false; + } + jsonObj = json::parse(jsonStr.substr(1), nullptr, false); // drop first char to adapt A's value; + if (jsonObj.is_discarded()) { + return false; + } + } + return Unmarshal(jsonObj); +} + +Serializable::json Serializable::ToJson(const std::string &jsonStr) +{ + json jsonObj = json::parse(jsonStr, nullptr, false); + if (jsonObj.is_discarded()) { + // if the string size is less than 1, means the string is invalid. + if (jsonStr.empty()) { + return {}; + } + jsonObj = json::parse(jsonStr.substr(1), nullptr, false); // drop first char to adapt A's value; + if (jsonObj.is_discarded()) { + return {}; + } + } + return jsonObj; +} + +bool Serializable::IsJson(const std::string &jsonStr) +{ + if (!json::accept(jsonStr)) { + return json::accept(jsonStr.begin() + 1, jsonStr.end()); + } + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, std::string &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_string()) { + return false; + } + value = subNode; + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, uint32_t &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_number_unsigned()) { + return false; + } + subNode.get_to(value); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, int32_t &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_number_integer()) { + return false; + } + subNode.get_to(value); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, int64_t &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_number_integer()) { + return false; + } + subNode.get_to(value); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, uint64_t &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_number_unsigned()) { + return false; + } + subNode.get_to(value); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, uint16_t &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_number_unsigned()) { + return false; + } + subNode.get_to(value); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, bool &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_boolean()) { + subNode.get_to(value); + return true; + } + + if (subNode.is_number_unsigned()) { + uint32_t number = 0; + subNode.get_to(number); + value = number != 0; + return true; + } + + return false; +} + +bool Serializable::GetValue(const json &node, const std::string &name, std::vector &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_array()) { + return false; + } + value = std::vector(subNode); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, Serializable &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_object()) { + return false; + } + return value.Unmarshal(subNode); +} + +bool Serializable::SetValue(json &node, const std::string &value) +{ + node = value; + return true; +} + +bool Serializable::SetValue(json &node, const uint32_t &value) +{ + node = value; + return true; +} + +bool Serializable::SetValue(json &node, const int32_t &value) +{ + node = value; + return true; +} + +bool Serializable::SetValue(json &node, const int64_t &value) +{ + node = value; + return true; +} + +bool Serializable::SetValue(json &node, const double &value) +{ + node = value; + return true; +} + +bool Serializable::SetValue(json &node, const uint64_t &value) +{ + node = value; + return true; +} + +bool Serializable::SetValue(json &node, const uint16_t &value) +{ + node = value; + return true; +} + +bool Serializable::SetValue(json &node, const std::vector &value) +{ + node = value; + return true; +} + +bool Serializable::SetValue(json &node, const Serializable &value) +{ + return value.Marshal(node); +} + +const Serializable::json &Serializable::GetSubNode(const json &node, const std::string &name) +{ + static const json jsonNull = json::value_t::null; + if (node.is_discarded() || node.is_null()) { + return jsonNull; + } + + if (name.empty()) { + return node; + } + + auto it = node.find(name); + if (it == node.end()) { + return jsonNull; + } + return *it; +} +} // namespace DistributedData +} // namespace OHOS diff --git a/data_share/frameworks/native/common/src/shared_block.cpp b/data_share/frameworks/native/common/src/shared_block.cpp index 2264f2ad733505a167206c1ad8b49d2d6ae4cea1..10d5e60cb47d7fe0c2d794bd80cbf6deeae3d5ee 100644 --- a/data_share/frameworks/native/common/src/shared_block.cpp +++ b/data_share/frameworks/native/common/src/shared_block.cpp @@ -66,7 +66,7 @@ bool SharedBlock::Init() int SharedBlock::CreateSharedBlock(const std::string &name, size_t size, sptr ashmem, SharedBlock *&outSharedBlock) { - outSharedBlock = new SharedBlock(name, ashmem, size, false); + outSharedBlock = new (std::nothrow)SharedBlock(name, ashmem, size, false); if (outSharedBlock == nullptr) { LOG_ERROR("CreateSharedBlock: new SharedBlock error."); return SHARED_BLOCK_BAD_VALUE; 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 6a554b17bd02a9673aa05126d9904d3500046bc3..9af3945b86717eac44332d9cb85c6ae578e6464a 100644 --- a/data_share/frameworks/native/consumer/controller/common/general_controller.h +++ b/data_share/frameworks/native/consumer/controller/common/general_controller.h @@ -19,6 +19,7 @@ #include #include +#include "data_ability_observer_interface.h" #include "datashare_business_error.h" #include "datashare_errno.h" #include "datashare_predicates.h" @@ -32,6 +33,7 @@ class IDataAbilityObserver; } namespace DataShare { +using ChangeInfo = AAFwk::ChangeInfo; class GeneralController { public: virtual ~GeneralController() = default; @@ -43,7 +45,7 @@ public: virtual int Delete(const Uri &uri, const DataSharePredicates &predicates) = 0; virtual std::shared_ptr Query(const Uri &uri, const DataSharePredicates &predicates, - std::vector &columns, DatashareBusinessError &businessError) = 0; + std::vector &columns, DatashareBusinessError &businessError, DataShareOption &option) = 0; virtual int RegisterObserver(const Uri &uri, const sptr &dataObserver) = 0; @@ -51,6 +53,29 @@ public: virtual void NotifyChange(const Uri &uri) = 0; + /** + * Registers an observer specified by the given Uri to the provider. This function is supported only when using + * non-silent DataShareHelper, and there is no default implemention in the provider side. It needs to be handled by + * the user. Otherwise, the provider side will do nothing but simply return error. + */ + virtual int RegisterObserverExtProvider(const Uri &uri, const sptr &dataObserver, + bool isDescendants) = 0; + + /** + * Deregisters an observer specified by the given Uri to the provider. This function is supported only when using + * non-silent DataShareHelper, and there is no default implemention in the provider side. It needs to be handled by + * the user. Otherwise, the provider side will do nothing but simply return error. + */ + virtual int UnregisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver) = 0; + + /** + * Notifies the registered observers of a change to the data resource specified by Uris. This function is supported + * only when using non-silent DataShareHelper, and there is no default implemention in the provider side. It needs + * to be handled by the user. Otherwise, the provider side will do nothing but simply return true. + */ + virtual int NotifyChangeExtProvider(const ChangeInfo &changeInfo) = 0; + virtual std::pair InsertEx(const Uri &uri, const DataShareValuesBucket &value) = 0; virtual std::pair UpdateEx( diff --git a/data_share/frameworks/native/consumer/controller/provider/include/ext_special_controller.h b/data_share/frameworks/native/consumer/controller/provider/include/ext_special_controller.h index 547a9186e5dd3dc73cb38c5ea3e1da3b3e99e812..028378b22aca24633f4735d7b39193f99abb181a 100644 --- a/data_share/frameworks/native/consumer/controller/provider/include/ext_special_controller.h +++ b/data_share/frameworks/native/consumer/controller/provider/include/ext_special_controller.h @@ -31,6 +31,8 @@ public: int OpenFile(const Uri &uri, const std::string &mode); + int OpenFileWithErrCode(const Uri &uri, const std::string &mode, int32_t &errCode); + int OpenRawFile(const Uri &uri, const std::string &mode); int BatchUpdate(const UpdateOperations &operations, std::vector &results); 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 04031a892308626498eaeee3e051899606002ee0..c2b9ce3edb68653e69861d2ce9a6f5b4822bd6a3 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 @@ -17,6 +17,7 @@ #define GENERAL_CONTROLLER_PORVIDER_IMPL_H #include "datashare_connection.h" +#include "datashare_option.h" #include "general_controller.h" namespace OHOS { @@ -25,6 +26,7 @@ class IDataAbilityObserver; } namespace DataShare { +using ChangeInfo = AAFwk::ChangeInfo; class GeneralControllerProviderImpl : public GeneralController { public: GeneralControllerProviderImpl(std::shared_ptr connection, @@ -39,7 +41,7 @@ public: int Delete(const Uri &uri, const DataSharePredicates &predicates) override; std::shared_ptr Query(const Uri &uri, const DataSharePredicates &predicates, - std::vector &columns, DatashareBusinessError &businessError) override; + std::vector &columns, DatashareBusinessError &businessError, DataShareOption &option) override; int RegisterObserver(const Uri &uri, const sptr &dataObserver) override; @@ -54,6 +56,13 @@ public: std::pair DeleteEx(const Uri &uri, const DataSharePredicates &predicates) override; + int RegisterObserverExtProvider(const Uri &uri, const sptr &dataObserver, + bool isDescendants) override; + + int UnregisterObserverExtProvider(const Uri &uri, const sptr &dataObserver) override; + + int NotifyChangeExtProvider(const ChangeInfo &changeInfo) override; + private: std::shared_ptr connection_ = nullptr; sptr token_ = {}; diff --git a/data_share/frameworks/native/consumer/controller/provider/src/ext_special_controller.cpp b/data_share/frameworks/native/consumer/controller/provider/src/ext_special_controller.cpp index 97781b3b04f231fb7681d9382cd320b7727dfac0..0fd6780d445c7375c4a1a36f2b6cedee01989d5e 100644 --- a/data_share/frameworks/native/consumer/controller/provider/src/ext_special_controller.cpp +++ b/data_share/frameworks/native/consumer/controller/provider/src/ext_special_controller.cpp @@ -34,6 +34,21 @@ int ExtSpecialController::OpenFile(const Uri &uri, const std::string &mode) return proxy->OpenFile(uri, mode); } +int ExtSpecialController::OpenFileWithErrCode(const Uri &uri, const std::string &mode, int32_t &errCode) +{ + auto connection = connection_; + if (connection == nullptr) { + LOG_ERROR("connection is nullptr"); + return INVALID_VALUE; + } + auto proxy = connection->GetDataShareProxy(uri_, token_); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return INVALID_VALUE; + } + return proxy->OpenFileWithErrCode(uri, mode, errCode); +} + int ExtSpecialController::OpenRawFile(const Uri &uri, const std::string &mode) { auto connection = connection_; 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 fa19b05c03b75dc83ccaae4e6546bd8614fd734d..d15f60e92cb977bec2aea0bc0603a5e3d2671bb8 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 @@ -115,8 +115,10 @@ std::pair GeneralControllerProviderImpl::DeleteEx(const Uri &u } std::shared_ptr GeneralControllerProviderImpl::Query(const Uri &uri, - const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError &businessError) + const DataSharePredicates &predicates, std::vector &columns, + DatashareBusinessError &businessError, DataShareOption &option) { + (void)option; auto connection = connection_; if (connection == nullptr) { LOG_ERROR("connection is nullptr"); @@ -143,7 +145,8 @@ int GeneralControllerProviderImpl::RegisterObserver(const Uri &uri, LOG_ERROR("proxy is nullptr"); return E_PROVIDER_NOT_CONNECTED; } - int ret = proxy->RegisterObserver(uri, dataObserver); + // the non-silent proxy's RegisterObserver returns bool while this function returns int and 0 means ok + int ret = proxy->RegisterObserver(uri, dataObserver) ? E_OK : E_REGISTER_ERROR; LOG_INFO("Register non-silent observer ret: %{public}d, uri: %{public}s", ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); return ret; @@ -162,7 +165,8 @@ int GeneralControllerProviderImpl::UnregisterObserver(const Uri &uri, LOG_ERROR("proxy is nullptr"); return E_PROVIDER_NOT_CONNECTED; } - int ret = proxy->UnregisterObserver(uri, dataObserver); + // the non-silent proxy's UnregisterObserver returns bool while this function returns int and 0 means ok + int ret = proxy->UnregisterObserver(uri, dataObserver) ? E_OK : E_REGISTER_ERROR; LOG_INFO("Unregister non-silent observer ret: %{public}d, uri: %{public}s", ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); return ret; @@ -183,6 +187,75 @@ void GeneralControllerProviderImpl::NotifyChange(const Uri &uri) proxy->NotifyChange(uri); } +// This function is supported only when using non-silent DataShareHelper +int GeneralControllerProviderImpl::RegisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver, bool isDescendants) +{ + auto connection = connection_; + if (connection == nullptr) { + LOG_ERROR("connection is nullptr"); + return E_PROVIDER_CONN_NULL; + } + auto proxy = connection->GetDataShareProxy(uri_, token_); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return E_PROVIDER_NOT_CONNECTED; + } + // the non-silent proxy's RegisterObserverExtProvider returns int and 0 means ok + int ret = proxy->RegisterObserverExtProvider(uri, dataObserver, isDescendants, { false }); + LOG_INFO("Register non-silent observerExt provider ret: %{public}d, uri: %{public}s", ret, + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + // store the observer when successfully registered. + if (ret == E_OK) { + connection->UpdateObserverExtsProviderMap(uri, dataObserver, isDescendants); + } + return ret; +} + +// This function is supported only when using non-silent DataShareHelper +int GeneralControllerProviderImpl::UnregisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver) +{ + auto connection = connection_; + if (connection == nullptr) { + LOG_ERROR("connection is nullptr"); + return E_PROVIDER_CONN_NULL; + } + auto proxy = connection->GetDataShareProxy(uri_, token_); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return E_PROVIDER_NOT_CONNECTED; + } + // the non-silent proxy's UnregisterObserverExtProvider returns int and 0 means ok + int ret = proxy->UnregisterObserverExtProvider(uri, dataObserver); + LOG_INFO("Unregister non-silent observerExt provider ret: %{public}d, uri: %{public}s", ret, + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + // remove the observer from storage when successfully unregistered. + if (ret == E_OK) { + connection->DeleteObserverExtsProviderMap(uri, dataObserver); + } + return ret; +} + +// This function is supported only when using non-silent DataShareHelper +int GeneralControllerProviderImpl::NotifyChangeExtProvider(const ChangeInfo &changeInfo) +{ + auto connection = connection_; + if (connection == nullptr) { + LOG_ERROR("connection is nullptr"); + return E_PROVIDER_CONN_NULL; + } + auto proxy = connection->GetDataShareProxy(uri_, token_); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return E_PROVIDER_NOT_CONNECTED; + } + // the non-silent proxy's NotifyChangeExtProvider returns int and 0 means ok + int ret = proxy->NotifyChangeExtProvider(changeInfo); + LOG_INFO("NotifyChangeExtProvider ret: %{public}d", ret); + return ret; +} + GeneralControllerProviderImpl::GeneralControllerProviderImpl(std::shared_ptr connection, const Uri &uri, const sptr &token) : connection_(connection), token_(token), uri_(uri) { 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 d4e9a9186e2f1b74a4799ac07f6cc3badea2e58f..f1c752db32e5012db207e6263de70409b70e47e5 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 @@ -20,6 +20,7 @@ #include "concurrent_map.h" #include "data_share_manager_impl.h" +#include "executor_pool.h" #include "general_controller.h" #include "uri.h" @@ -29,6 +30,18 @@ class IDataAbilityObserver; } namespace DataShare { +using ChangeInfo = AAFwk::ChangeInfo; + +struct TimedQueryResult { + bool isFinish_; + DatashareBusinessError businessError_; + std::shared_ptr resultSet_; + + explicit TimedQueryResult(bool isFinish, DatashareBusinessError businessError, + std::shared_ptr resultSet) : isFinish_(isFinish), + businessError_(businessError), resultSet_(resultSet) {} +}; + class GeneralControllerServiceImpl : public GeneralController { public: GeneralControllerServiceImpl(const std::string &ext); @@ -42,7 +55,7 @@ public: int Delete(const Uri &uri, const DataSharePredicates &predicates) override; std::shared_ptr Query(const Uri &uri, const DataSharePredicates &predicates, - std::vector &columns, DatashareBusinessError &businessError) override; + std::vector &columns, DatashareBusinessError &businessError, DataShareOption &option) override; int RegisterObserver(const Uri &uri, const sptr &dataObserver) override; @@ -50,6 +63,13 @@ public: void NotifyChange(const Uri &uri) override; + int RegisterObserverExtProvider(const Uri &uri, const sptr &dataObserver, + bool isDescendants) override; + + int UnregisterObserverExtProvider(const Uri &uri, const sptr &dataObserver) override; + + int NotifyChangeExtProvider(const ChangeInfo &changeInfo) override; + std::pair InsertEx(const Uri &uri, const DataShareValuesBucket &value) override; std::pair UpdateEx( @@ -62,10 +82,16 @@ private: void SetRegisterCallback(); + std::pair, DatashareBusinessError> TimedQuery( + std::shared_ptr proxy, const UriInfo ¶mSet, + const DataSharePredicates &predicates, const std::vector &columns); + ConcurrentMap, std::list> observers_; std::string extUri_; + std::shared_ptr pool_; + static constexpr int MAX_RETRY_COUNT = 3; static constexpr int RANDOM_MIN = 50; 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 5b3a7064b25288cf6884efb843706cdb3ba8af61..41fdbfb04bc16cd7320d83952347492abe64a5c4 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 @@ -16,6 +16,8 @@ #include "general_controller_service_impl.h" #include +#include "block_data.h" +#include "datashare_common.h" #include "dataobs_mgr_client.h" #include "dataobs_mgr_errors.h" #include "datashare_log.h" @@ -26,6 +28,7 @@ namespace DataShare { GeneralControllerServiceImpl::GeneralControllerServiceImpl(const std::string &ext) { extUri_ = ext; + pool_ = std::make_shared(MAX_THREADS, MIN_THREADS, DATASHARE_EXECUTOR_NAME); } GeneralControllerServiceImpl::~GeneralControllerServiceImpl() @@ -41,7 +44,10 @@ int GeneralControllerServiceImpl::Insert(const Uri &uri, const DataShareValuesBu LOG_ERROR("Manager is nullptr"); return DATA_SHARE_ERROR; } - manager->SetCallCount(__FUNCTION__, uri.ToString()); + // the ret of SetCallCount indicates whether the current call exceeds the access threshold, true means excced + if (manager->SetCallCount(__FUNCTION__, uri.ToString())) { + return DATA_SHARE_ERROR; + } auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); @@ -58,7 +64,10 @@ int GeneralControllerServiceImpl::Update(const Uri &uri, const DataSharePredicat LOG_ERROR("Manager is nullptr"); return DATA_SHARE_ERROR; } - manager->SetCallCount(__FUNCTION__, uri.ToString()); + // the ret of SetCallCount indicates whether the current call exceeds the access threshold, true means excced + if (manager->SetCallCount(__FUNCTION__, uri.ToString())) { + return DATA_SHARE_ERROR; + } auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); @@ -74,7 +83,10 @@ int GeneralControllerServiceImpl::Delete(const Uri &uri, const DataSharePredicat LOG_ERROR("Manager is nullptr"); return DATA_SHARE_ERROR; } - manager->SetCallCount(__FUNCTION__, uri.ToString()); + // the ret of SetCallCount indicates whether the current call exceeds the access threshold, true means excced + if (manager->SetCallCount(__FUNCTION__, uri.ToString())) { + return DATA_SHARE_ERROR; + } auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); @@ -90,7 +102,10 @@ std::pair GeneralControllerServiceImpl::InsertEx(const Uri &ur LOG_ERROR("Manager is nullptr"); return std::make_pair(DATA_SHARE_ERROR, 0); } - manager->SetCallCount(__FUNCTION__, uri.ToString()); + // the ret of SetCallCount indicates whether the current call exceeds the access threshold, true means excced + if (manager->SetCallCount(__FUNCTION__, uri.ToString())) { + return std::make_pair(DATA_SHARE_ERROR, 0); + } auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); @@ -107,7 +122,10 @@ std::pair GeneralControllerServiceImpl::UpdateEx( LOG_ERROR("Manager is nullptr"); return std::make_pair(DATA_SHARE_ERROR, 0); } - manager->SetCallCount(__FUNCTION__, uri.ToString()); + // the ret of SetCallCount indicates whether the current call exceeds the access threshold, true means excced + if (manager->SetCallCount(__FUNCTION__, uri.ToString())) { + return std::make_pair(DATA_SHARE_ERROR, 0); + } auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); @@ -124,7 +142,10 @@ std::pair GeneralControllerServiceImpl::DeleteEx(const Uri &ur LOG_ERROR("Manager is nullptr"); return std::make_pair(DATA_SHARE_ERROR, 0); } - manager->SetCallCount(__FUNCTION__, uri.ToString()); + // the ret of SetCallCount indicates whether the current call exceeds the access threshold, true means excced + if (manager->SetCallCount(__FUNCTION__, uri.ToString())) { + return std::make_pair(DATA_SHARE_ERROR, 0); + } auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); @@ -134,19 +155,36 @@ std::pair GeneralControllerServiceImpl::DeleteEx(const Uri &ur } std::shared_ptr GeneralControllerServiceImpl::Query(const Uri &uri, - const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError &businessError) + const DataSharePredicates &predicates, std::vector &columns, + DatashareBusinessError &businessError, DataShareOption &option) { auto manager = DataShareManagerImpl::GetInstance(); if (manager == nullptr) { LOG_ERROR("Manager is nullptr"); return nullptr; } - manager->SetCallCount(__FUNCTION__, uri.ToString()); + // the ret of SetCallCount indicates whether the current call exceeds the access threshold, true means excced + if (manager->SetCallCount(__FUNCTION__, uri.ToString())) { + return nullptr; + } auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return nullptr; } + + if (option.timeout > 0) { + UriInfo uriInfo = { + .uri = uri.ToString(), + .extUri = extUri_, + .option = { .timeout = option.timeout }, + }; + + auto [resultSet, err] = TimedQuery(proxy, uriInfo, predicates, columns); + businessError = err; + return resultSet; + } + 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) { @@ -172,7 +210,8 @@ int GeneralControllerServiceImpl::RegisterObserver(const Uri &uri, LOG_ERROR("get DataObsMgrClient failed"); return E_DATA_OBS_NOT_READY; } - ErrCode ret = obsMgrClient->RegisterObserver(uri, dataObserver); + bool isSystem = DataShareServiceProxy::IsSystem(); + ErrCode ret = obsMgrClient->RegisterObserver(uri, dataObserver, -1, AAFwk::DataObsOption(isSystem)); LOG_INFO("Register silent observer ret: %{public}d, uri: %{public}s", ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); return ret; @@ -186,7 +225,8 @@ int GeneralControllerServiceImpl::UnregisterObserver(const Uri &uri, LOG_ERROR("get DataObsMgrClient failed"); return E_DATA_OBS_NOT_READY; } - ErrCode ret = obsMgrClient->UnregisterObserver(uri, dataObserver); + bool isSystem = DataShareServiceProxy::IsSystem(); + ErrCode ret = obsMgrClient->UnregisterObserver(uri, dataObserver, -1, AAFwk::DataObsOption(isSystem)); LOG_INFO("Unregister silent observer ret: %{public}d, uri: %{public}s", ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); return ret; @@ -202,6 +242,26 @@ void GeneralControllerServiceImpl::NotifyChange(const Uri &uri) proxy->Notify(uri.ToString()); } +// This function is supported only when using non-silent DataShareHelper +int GeneralControllerServiceImpl::RegisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver, bool isDescendants) +{ + return DATA_SHARE_ERROR; +} + +// This function is supported only when using non-silent DataShareHelper +int GeneralControllerServiceImpl::UnregisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver) +{ + return DATA_SHARE_ERROR; +} + +// This function is supported only when using non-silent DataShareHelper +int GeneralControllerServiceImpl::NotifyChangeExtProvider(const ChangeInfo &changeInfo) +{ + return DATA_SHARE_ERROR; +} + void GeneralControllerServiceImpl::SetRegisterCallback() { auto manager = DataShareManagerImpl::GetInstance(); @@ -227,5 +287,49 @@ void GeneralControllerServiceImpl::ReRegisterObserver() return false; }); } + +std::pair, DatashareBusinessError> GeneralControllerServiceImpl::TimedQuery( + std::shared_ptr proxy, const UriInfo &uriInfo, + const DataSharePredicates &predicates, const std::vector &columns) +{ + DatashareBusinessError businessError; + if (pool_ == nullptr) { + LOG_ERROR("pool is nullptr"); + businessError.SetCode(E_EXECUTOR_POOL_IS_NULL); + businessError.SetMessage("pool is nullptr"); + return std::make_pair(nullptr, businessError); + } + + auto timedQueryResult = std::make_shared>( + uriInfo.option.timeout, TimedQueryResult{false, DatashareBusinessError(), nullptr}); + + auto task = [proxy, uriInfo, predicates, columns, timedQueryResult]() { + DatashareBusinessError businessError; + auto ncolumns = columns; + auto resultSet = proxy->Query(Uri(uriInfo.uri), Uri(uriInfo.extUri), predicates, + ncolumns, 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(uriInfo.uri).c_str()); + std::this_thread::sleep_for(std::chrono::milliseconds( + DataShareStringUtils::GetRandomNumber(RANDOM_MIN, RANDOM_MAX))); + resultSet = proxy->Query(Uri(uriInfo.uri), Uri(uriInfo.extUri), predicates, + ncolumns, businessError); + } + + timedQueryResult->SetValue(TimedQueryResult{true, businessError, std::move(resultSet)}); + }; + auto taskId = pool_->Execute(task); + auto res = timedQueryResult->GetValue(); + if (!res.isFinish_) { + LOG_ERROR("query time out, waited time: %{public}d, uri: %{public}s", uriInfo.option.timeout, + DataShareStringUtils::Anonymous(uriInfo.uri).c_str()); + pool_->Remove(taskId); + businessError.SetCode(E_TIMEOUT_ERROR); + businessError.SetMessage("query time out"); + return std::make_pair(nullptr, businessError); + } + return std::make_pair(res.resultSet_, res.businessError_); +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/consumer/include/datashare_connection.h b/data_share/frameworks/native/consumer/include/datashare_connection.h index 6e1fa9965c1b9e57e76517f4cd32ef3adce0f05f..5748f41206bdb6c8c91e2fbac5c3248806401ee7 100644 --- a/data_share/frameworks/native/consumer/include/datashare_connection.h +++ b/data_share/frameworks/native/consumer/include/datashare_connection.h @@ -21,8 +21,8 @@ #include #include "ability_connect_callback_stub.h" +#include "data_ability_observer_interface.h" #include "datashare_proxy.h" -#include "event_handler.h" #include "executor_pool.h" #include "want.h" @@ -73,6 +73,11 @@ public: void SetConnectInvalid(); + void UpdateObserverExtsProviderMap(const Uri &uri, const sptr &dataObserver, + bool isDescendants); + + void DeleteObserverExtsProviderMap(const Uri &uri, const sptr &dataObserver); + private: struct DataShareConnectionInfo { int count = 0; @@ -81,13 +86,13 @@ private: }; 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); + void ReRegisterObserverExtProvider(); std::mutex mutex_{}; std::shared_ptr dataShareProxy_; ConnectCondition condition_; @@ -101,7 +106,16 @@ private: static constexpr std::chrono::milliseconds MAX_RECONNECT_TIME_INTERVAL = std::chrono::milliseconds(70000); std::shared_ptr pool_; DataShareConnectionInfo reConnects_; + struct Param { + Param(const Uri &uri, bool isDescendants) : uri(uri), isDescendants(isDescendants){}; + Uri uri; + bool isDescendants; + }; + // Store observers that have been successfully registered, allowing them to be re-registered during reconnection. + ConcurrentMap, std::list> observerExtsProvider_; int32_t waitTime_ = 0; + // An atomic variable used to identify the re-registration status. + std::atomic isReconnect_ = false; }; } // 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 d26fc000a433aef2944ffd5f3ba04c369b9fac8c..51bb7c9267fbc4610a8fbac7ed769ff8ab3ee29e 100644 --- a/data_share/frameworks/native/consumer/include/datashare_helper_impl.h +++ b/data_share/frameworks/native/consumer/include/datashare_helper_impl.h @@ -16,6 +16,8 @@ #ifndef DATA_SHARE_HELPER_IMPL_H #define DATA_SHARE_HELPER_IMPL_H +#include "concurrent_map.h" +#include "data_ability_observer_stub.h" #include "datashare_helper.h" #include "ext_special_controller.h" #include "general_controller.h" @@ -23,6 +25,26 @@ #include "published_data_controller.h" namespace OHOS::DataShare { +class ObserverImpl : public AAFwk::DataAbilityObserverStub { +public: + explicit ObserverImpl(const std::shared_ptr dataShareObserver) + : dataShareObserver_(dataShareObserver){}; + void OnChange(); + void OnChangeExt(const AAFwk::ChangeInfo &info); + static DataShareObserver::ChangeInfo ConvertInfo(const AAFwk::ChangeInfo &info); + static AAFwk::ChangeInfo ConvertInfo(const DataShareObserver::ChangeInfo &info); + static sptr GetObserver(const Uri& uri, const std::shared_ptr &observer); + static bool FindObserver(const Uri& uri, const std::shared_ptr &observer); + static bool DeleteObserver(const Uri& uri, const std::shared_ptr &observer); +private: + struct ObserverParam { + sptr obs_; + std::list uris_; + }; + std::shared_ptr dataShareObserver_; + static ConcurrentMap observers_; +}; + class DataShareHelperImpl : public DataShareHelper { public: DataShareHelperImpl(const Uri &uri, const sptr &token, @@ -37,6 +59,8 @@ public: int OpenFile(Uri &uri, const string &mode) override; + int OpenFileWithErrCode(Uri &uri, const string &mode, int32_t &errCode) override; + int OpenRawFile(Uri &uri, const string &mode) override; int Insert(Uri &uri, const DataShareValuesBucket &value) override; @@ -52,6 +76,9 @@ public: std::shared_ptr Query(Uri &uri, const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError *businessError) override; + std::shared_ptr Query(Uri &uri, const DataSharePredicates &predicates, + std::vector &columns, DataShareOption &option, DatashareBusinessError *businessError) override; + string GetType(Uri &uri) override; int BatchInsert(Uri &uri, const std::vector &values) override; @@ -64,6 +91,13 @@ public: void NotifyChange(const Uri &uri) override; + int RegisterObserverExtProvider(const Uri &uri, std::shared_ptr dataObserver, + bool isDescendants) override; + + int UnregisterObserverExtProvider(const Uri &uri, std::shared_ptr dataObserver) override; + + void NotifyChangeExtProvider(const DataShareObserver::ChangeInfo &changeInfo) override; + Uri NormalizeUri(Uri &uri) override; Uri DenormalizeUri(Uri &uri) override; diff --git a/data_share/frameworks/native/consumer/include/datashare_proxy.h b/data_share/frameworks/native/consumer/include/datashare_proxy.h index 0a696e1a18bc5afc22ac06ee26706cf2838ecff4..f630763e3d31bb5183592346bdbfe5b2f0e4be41 100644 --- a/data_share/frameworks/native/consumer/include/datashare_proxy.h +++ b/data_share/frameworks/native/consumer/include/datashare_proxy.h @@ -19,10 +19,13 @@ #include #include +#include "concurrent_map.h" +#include "dataobs_mgr_changeinfo.h" #include "idatashare.h" namespace OHOS { namespace DataShare { +using ChangeInfo = AAFwk::ChangeInfo; class DataShareProxy final : public IRemoteProxy { public: explicit DataShareProxy(const sptr& remote) : IRemoteProxy(remote) {} @@ -33,6 +36,8 @@ public: virtual int OpenFile(const Uri &uri, const std::string &mode) override; + int OpenFileWithErrCode(const Uri &uri, const std::string &mode, int32_t &errCode); + virtual int OpenRawFile(const Uri &uri, const std::string &mode) override; virtual int Insert(const Uri &uri, const DataShareValuesBucket &value) override; @@ -61,6 +66,14 @@ public: virtual bool NotifyChange(const Uri &uri) override; + virtual int RegisterObserverExtProvider(const Uri &uri, const sptr &dataObserver, + bool isDescendants, RegisterOption option) override; + + virtual int UnregisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver) override; + + virtual int NotifyChangeExtProvider(const ChangeInfo &changeInfo) override; + virtual Uri NormalizeUri(const Uri &uri) override; virtual Uri DenormalizeUri(const Uri &uri) override; @@ -77,6 +90,7 @@ public: private: bool CheckSize(const UpdateOperations &operations); + int OpenFileInner(const Uri &uri, const std::string &mode, uint32_t requestCode, int32_t &errCode); static inline BrokerDelegator delegator_; static const size_t MTU_SIZE = 921600; // 900k static const size_t MAX_SIZE = 4000; diff --git a/data_share/frameworks/native/consumer/src/dataproxy_handle.cpp b/data_share/frameworks/native/consumer/src/dataproxy_handle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..85fb58ca996370939d005ba3a4f31dda98042cf8 --- /dev/null +++ b/data_share/frameworks/native/consumer/src/dataproxy_handle.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2025 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 "DataProxyHandle" + +#include +#include "dataproxy_handle.h" + +#include "adaptor.h" +#include "datashare_errno.h" +#include "datashare_log.h" +#include "data_share_manager_impl.h" +#include "proxy_data_subscriber_manager.h" + +namespace OHOS { +namespace DataShare { + +std::pair> DataProxyHandle::Create() +{ + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); + auto manager = DataShareManagerImpl::GetInstance(); + if (manager == nullptr) { + LOG_ERROR("Manager is nullptr"); + return std::make_pair(E_ERROR, nullptr); + } + if (DataShareManagerImpl::GetServiceProxy() == nullptr) { + LOG_ERROR("Service proxy is nullptr."); + return std::make_pair(E_ERROR, nullptr); + } + auto handler = std::make_shared(); + if (handler != nullptr) { + return std::make_pair(E_OK, handler); + } + return std::make_pair(E_ERROR, nullptr); +} + +std::vector DataProxyHandle::PublishProxyData( + const std::vector &proxyData, const DataProxyConfig &proxyConfig) +{ + auto proxy = DataShareManagerImpl::GetServiceProxy(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return std::vector(); + } + return proxy->PublishProxyData(proxyData, proxyConfig); +} + +std::vector DataProxyHandle::DeleteProxyData( + const std::vector &uris, const DataProxyConfig &proxyConfig) +{ + auto proxy = DataShareManagerImpl::GetServiceProxy(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return std::vector(); + } + return proxy->DeleteProxyData(uris, proxyConfig); +} + +std::vector DataProxyHandle::GetProxyData( + const std::vector uris, const DataProxyConfig &proxyConfig) +{ + auto proxy = DataShareManagerImpl::GetServiceProxy(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return std::vector(); + } + return proxy->GetProxyData(uris, proxyConfig); +} + +std::vector DataProxyHandle::SubscribeProxyData(const std::vector &uris, + const std::function &changeNode)> &callback) +{ + auto proxy = DataShareManagerImpl::GetServiceProxy(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return std::vector(); + } + return ProxyDataSubscriberManager::GetInstance().AddObservers(this, proxy, uris, callback); +} + +std::vector DataProxyHandle::UnsubscribeProxyData(const std::vector &uris) +{ + auto proxy = DataShareManagerImpl::GetServiceProxy(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return std::vector(); + } + return ProxyDataSubscriberManager::GetInstance().DelObservers(this, proxy, uris); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/consumer/src/datashare_connection.cpp b/data_share/frameworks/native/consumer/src/datashare_connection.cpp index a6080c1ea6bfe472239a67785249b52c9e1106de..6a3419bcf3104b62e7a9f49c03b60bf33bbb2e0d 100644 --- a/data_share/frameworks/native/consumer/src/datashare_connection.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_connection.cpp @@ -13,9 +13,11 @@ * limitations under the License. */ +#include #include "datashare_connection.h" #include "ams_mgr_proxy.h" +#include "datashare_common.h" #include "datashare_errno.h" #include "datashare_log.h" #include "datashare_proxy.h" @@ -25,6 +27,7 @@ namespace OHOS { namespace DataShare { using namespace AppExecFwk; +const std::chrono::milliseconds TIME_THRESHOLD = std::chrono::milliseconds(200); /** * @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. @@ -57,6 +60,11 @@ void DataShareConnection::OnAbilityConnectDone( DataShareStringUtils::Change(element.GetURI()).c_str(), resultCode); Disconnect(); } + // re-register when re-connect successed + if (isReconnect_.load()) { + ReRegisterObserverExtProvider(); + isReconnect_.store(false); + } } /** @@ -85,7 +93,7 @@ void DataShareConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName if (pool_ == nullptr) { std::lock_guard lock(mutex_); if (pool_ == nullptr) { - pool_ = std::make_shared(MAX_THREADS, MIN_THREADS); + pool_ = std::make_shared(MAX_THREADS, MIN_THREADS, DATASHARE_EXECUTOR_NAME); } } ReconnectExtAbility(uri); @@ -107,6 +115,8 @@ void DataShareConnection::ReconnectExtAbility(const std::string &uri) reConnects_.count = 1; reConnects_.firstTime = std::chrono::duration_cast(curr).count(); reConnects_.prevTime = std::chrono::duration_cast(curr).count(); + // set status true + isReconnect_.store(true); } return; } @@ -145,6 +155,7 @@ void DataShareConnection::DelayConnectExtAbility(const std::string &uri) selfSharedPtr->reConnects_.count++; selfSharedPtr->reConnects_.prevTime = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()).count(); + selfSharedPtr->isReconnect_.store(true); } } }); @@ -156,6 +167,49 @@ void DataShareConnection::DelayConnectExtAbility(const std::string &uri) return; } +// store observer when it was successfully registered +void DataShareConnection::UpdateObserverExtsProviderMap(const Uri &uri, + const sptr &dataObserver, bool isDescendants) +{ + observerExtsProvider_.Compute(dataObserver, [&uri, isDescendants](const auto &key, auto &value) { + value.emplace_back(uri, isDescendants); + return true; + }); +} + +// remove observer when it was successfully unregistered +void DataShareConnection::DeleteObserverExtsProviderMap(const Uri &uri, + const sptr &dataObserver) +{ + observerExtsProvider_.Compute(dataObserver, [&uri](const auto &key, auto &value) { + value.remove_if([&uri](const auto ¶m) { + return uri == param.uri; + }); + return !value.empty(); + }); +} + +// re-register observer by dataShareProxy +void DataShareConnection::ReRegisterObserverExtProvider() +{ + LOG_INFO("ReRegisterObserverExtProvider start"); + decltype(observerExtsProvider_) observerExtsProvider(std::move(observerExtsProvider_)); + observerExtsProvider_.Clear(); + observerExtsProvider.ForEach([this](const auto &key, const auto &value) { + for (const auto ¶m : value) { + auto ret = dataShareProxy_->RegisterObserverExtProvider(param.uri, key, param.isDescendants, { true }); + if (ret != E_OK) { + LOG_ERROR( + "RegisterObserverExt failed, param.uri:%{public}s, ret:%{public}d, param.isDescendants:%{public}d", + DataShareStringUtils::Anonymous(param.uri.ToString()).c_str(), ret, param.isDescendants + ); + } else { + UpdateObserverExtsProviderMap(param.uri, key, param.isDescendants); + } + } + return false; + }); +} /** * @brief connect remote ability of DataShareExtAbility. */ @@ -181,14 +235,26 @@ std::shared_ptr DataShareConnection::ConnectDataShareExtAbility( if (ret != ERR_OK) { return nullptr; } - std::unique_lock condLock(condition_.mutex); + std::unique_lock condLock(mutex_); + std::shared_ptr proxy = dataShareProxy_; + if (proxy != nullptr) { + return proxy; + } + auto start = std::chrono::steady_clock::now(); if (condition_.condition.wait_for(condLock, std::chrono::seconds(waitTime_), [this] { return dataShareProxy_ != nullptr; })) { + auto finish = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(finish - start); + if (duration >= TIME_THRESHOLD) { + int64_t milliseconds = duration.count(); + LOG_WARN("over time connecting ability, uri:%{public}s, time:%{public}" PRIi64 "ms", + DataShareStringUtils::Change(reqUri).c_str(), milliseconds); + } LOG_DEBUG("connect ability ended successfully uri:%{public}s", DataShareStringUtils::Change(reqUri).c_str()); } else { LOG_WARN("connect timeout uri:%{public}s", DataShareStringUtils::Change(reqUri).c_str()); } - return GetDataShareProxy(); + return dataShareProxy_; } /** diff --git a/data_share/frameworks/native/consumer/src/datashare_helper.cpp b/data_share/frameworks/native/consumer/src/datashare_helper.cpp index f0243cb7f7f577d3fd92eaaa8c7e82bf66fafcfa..ef1dfa553bf22afc0333fc90ef5f87b9785747be 100644 --- a/data_share/frameworks/native/consumer/src/datashare_helper.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_helper.cpp @@ -18,9 +18,6 @@ #include "datashare_helper_impl.h" #include "adaptor.h" -#include "concurrent_map.h" -#include "data_ability_observer_interface.h" -#include "data_ability_observer_stub.h" #include "dataobs_mgr_client.h" #include "datashare_errno.h" #include "datashare_log.h" @@ -33,25 +30,6 @@ namespace { static constexpr const char *DATA_SHARE_PREFIX = "datashare:///"; static constexpr const char *FILE_PREFIX = "file://"; } // namespace -class ObserverImpl : public AAFwk::DataAbilityObserverStub { -public: - explicit ObserverImpl(const std::shared_ptr dataShareObserver) - : dataShareObserver_(dataShareObserver){}; - void OnChange(); - void OnChangeExt(const AAFwk::ChangeInfo &info); - static DataShareObserver::ChangeInfo ConvertInfo(const AAFwk::ChangeInfo &info); - static AAFwk::ChangeInfo ConvertInfo(const DataShareObserver::ChangeInfo &info); - static sptr GetObserver(const Uri& uri, const std::shared_ptr &observer); - static bool FindObserver(const Uri& uri, const std::shared_ptr &observer); - static bool DeleteObserver(const Uri& uri, const std::shared_ptr &observer); -private: - struct ObserverParam { - sptr obs_; - std::list uris_; - }; - std::shared_ptr dataShareObserver_; - static ConcurrentMap observers_; -}; ConcurrentMap ObserverImpl::observers_; @@ -82,7 +60,6 @@ std::shared_ptr DataShareHelper::Creator(const sptr helper = nullptr; @@ -111,8 +88,12 @@ std::shared_ptr DataShareHelper::Creator(const string &strUri, LOG_ERROR("token is nullptr"); return nullptr; } - return options.isProxy_ ? CreateServiceHelper("", bundleName, isSystem) - : CreateExtHelper(uri, options.token_, waitTime, isSystem); + if (options.isProxy_) { + int ret = GetSilentProxyStatus(strUri, isSystem); + return (ret == E_OK || ret == E_METADATA_NOT_EXISTS) ? CreateServiceHelper("", bundleName, isSystem) : nullptr; + } else { + return CreateExtHelper(uri, options.token_, waitTime, isSystem); + } } std::pair> DataShareHelper::Create(const sptr &token, @@ -219,7 +200,7 @@ std::shared_ptr DataShareHelper::CreateExtHelper(Uri &uri, cons * @param isDescendants, Indicates the Whether to note the change of descendants. */ void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptr dataObserver, - bool isDescendants) + bool isDescendants, bool isSystem) { if (dataObserver == nullptr) { LOG_ERROR("dataObserver is nullptr"); @@ -235,7 +216,7 @@ void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptrRegisterObserverExt(uri, obs, isDescendants); + ErrCode ret = obsMgrClient->RegisterObserverExt(uri, obs, isDescendants, AAFwk::DataObsOption(isSystem)); if (ret != ERR_OK) { ObserverImpl::DeleteObserver(uri, dataObserver); } @@ -249,7 +230,8 @@ void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptr dataObserver) +void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptr dataObserver, + bool isSystem) { if (dataObserver == nullptr) { LOG_ERROR("dataObserver is nullptr"); @@ -271,7 +253,7 @@ void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptrUnregisterObserverExt(uri, obs); + ErrCode ret = obsMgrClient->UnregisterObserverExt(uri, obs, AAFwk::DataObsOption(isSystem)); LOG_INFO("Unregister observerExt, ret:%{public}d, uri:%{public}s", ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); if (ret != ERR_OK) { @@ -285,7 +267,7 @@ void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptrNotifyChangeExt(ObserverImpl::ConvertInfo(changeInfo)); + ErrCode ret = obsMgrClient->NotifyChangeExt(ObserverImpl::ConvertInfo(changeInfo), + AAFwk::DataObsOption(isSystem)); LOG_INFO("Notify changeExt, ret:%{public}d", ret); } 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 a205f452bb2172b4e72e937e2a97125daa68fe89..7674e001851d42b3730c09dbc5ae8e998173b436 100644 --- a/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp @@ -13,17 +13,16 @@ * limitations under the License. */ #define LOG_TAG "DataShareHelperImpl" - +#include #include "datashare_helper_impl.h" #include "adaptor.h" -#include "concurrent_map.h" -#include "data_ability_observer_interface.h" #include "dataobs_mgr_client.h" #include "datashare_log.h" +#include "datashare_string_utils.h" #include "datashare_radar_reporter.h" #include "datashare_result_set.h" - +#include "datashare_string_utils.h" #include "general_controller_provider_impl.h" #include "general_controller_service_impl.h" @@ -85,6 +84,16 @@ int DataShareHelperImpl::OpenFile(Uri &uri, const std::string &mode) return extSpCtl->OpenFile(uri, mode); } +int DataShareHelperImpl::OpenFileWithErrCode(Uri &uri, const std::string &mode, int32_t &errCode) +{ + auto extSpCtl = extSpCtl_; + if (extSpCtl == nullptr) { + LOG_ERROR("extSpCtl is nullptr"); + return DATA_SHARE_ERROR; + } + return extSpCtl->OpenFileWithErrCode(uri, mode, errCode); +} + int DataShareHelperImpl::OpenRawFile(Uri &uri, const std::string &mode) { auto extSpCtl = extSpCtl_; @@ -212,6 +221,26 @@ std::pair DataShareHelperImpl::DeleteEx(Uri &uri, const DataSh std::shared_ptr DataShareHelperImpl::Query(Uri &uri, const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError *businessError) +{ + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); + auto generalCtl = generalCtl_; + if (generalCtl == nullptr) { + LOG_ERROR("generalCtl is nullptr"); + return nullptr; + } + DataShareOption option; + DatashareBusinessError error; + DataShareServiceProxy::SetSystem(isSystem_); + auto resultSet = generalCtl->Query(uri, predicates, columns, error, option); + DataShareServiceProxy::CleanSystem(); + if (businessError != nullptr) { + *businessError = error; + } + return resultSet; +} + +std::shared_ptr DataShareHelperImpl::Query(Uri &uri, const DataSharePredicates &predicates, + std::vector &columns, DataShareOption &option, DatashareBusinessError *businessError) { DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); auto generalCtl = generalCtl_; @@ -221,7 +250,7 @@ std::shared_ptr DataShareHelperImpl::Query(Uri &uri, const D } DatashareBusinessError error; DataShareServiceProxy::SetSystem(isSystem_); - auto resultSet = generalCtl->Query(uri, predicates, columns, error); + auto resultSet = generalCtl->Query(uri, predicates, columns, error, option); DataShareServiceProxy::CleanSystem(); if (businessError != nullptr) { *businessError = error; @@ -275,7 +304,10 @@ int DataShareHelperImpl::RegisterObserver(const Uri &uri, const sptrRegisterObserver(uri, dataObserver); + DataShareServiceProxy::SetSystem(isSystem_); + int ret = generalCtl->RegisterObserver(uri, dataObserver); + DataShareServiceProxy::CleanSystem(); + return ret; } int DataShareHelperImpl::UnregisterObserver(const Uri &uri, const sptr &dataObserver) @@ -293,7 +325,10 @@ int DataShareHelperImpl::UnregisterObserver(const Uri &uri, const sptrUnregisterObserver(uri, dataObserver); + DataShareServiceProxy::SetSystem(isSystem_); + int ret = generalCtl->UnregisterObserver(uri, dataObserver); + DataShareServiceProxy::CleanSystem(); + return ret; } void DataShareHelperImpl::NotifyChange(const Uri &uri) @@ -310,6 +345,102 @@ void DataShareHelperImpl::NotifyChange(const Uri &uri) return; } +/** + * Registers an observer to DataObsMgr specified by the given Uri. Only non-silent is supported, and there is no + * default implemention for the provider. It needs to be handled by the user. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the DataShareObserver object. + * @param isDescendants, Indicates the Whether to note the change of descendants. + */ +int DataShareHelperImpl::RegisterObserverExtProvider(const Uri &uri, std::shared_ptr dataObserver, + bool isDescendants) +{ + if (dataObserver == nullptr) { + LOG_ERROR("dataObserver is nullptr"); + return E_NULL_OBSERVER; + } + sptr obs = ObserverImpl::GetObserver(uri, dataObserver); + if (obs == nullptr) { + LOG_ERROR("new ObserverImpl failed"); + return E_NULL_OBSERVER; + } + auto generalCtl = generalCtl_; + if (generalCtl == nullptr) { + LOG_ERROR("generalCtl is nullptr"); + return E_HELPER_DIED; + } + DataShareServiceProxy::SetSystem(isSystem_); + // only support non-silent access + ErrCode ret = generalCtl->RegisterObserverExtProvider(uri, obs, isDescendants); + DataShareServiceProxy::CleanSystem(); + LOG_INFO("Register observerExt, ret:%{public}d, uri:%{public}s", + ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + if (ret != E_OK) { + ObserverImpl::DeleteObserver(uri, dataObserver); + } + return ret; +} + +/** + * Deregisters an observer used for DataObsMgr specified by the given Uri. Only non-silent is supported, and there is + * no default implemention for the provider. It needs to be handled by the user. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the DataShareObserver object. + */ +int DataShareHelperImpl::UnregisterObserverExtProvider(const Uri &uri, std::shared_ptr dataObserver) +{ + if (dataObserver == nullptr) { + LOG_ERROR("dataObserver is nullptr"); + return E_NULL_OBSERVER; + } + if (!ObserverImpl::FindObserver(uri, dataObserver)) { + LOG_ERROR("observer not exit!"); + return E_NULL_OBSERVER; + } + sptr obs = ObserverImpl::GetObserver(uri, dataObserver); + if (obs == nullptr) { + LOG_ERROR("new ObserverImpl failed"); + return E_NULL_OBSERVER; + } + auto generalCtl = generalCtl_; + if (generalCtl == nullptr) { + LOG_ERROR("generalCtl is nullptr"); + return E_HELPER_DIED; + } + DataShareServiceProxy::SetSystem(isSystem_); + // only support non-silent access + ErrCode ret = generalCtl->UnregisterObserverExtProvider(uri, obs); + DataShareServiceProxy::CleanSystem(); + if (ret != E_OK) { + return ret; + } + ObserverImpl::DeleteObserver(uri, dataObserver); + return E_OK; +} + +/** + * Notifies the registered observers of a change to the data resource specified by Uris. Only non-silent is supported, + * and there is no default implemention for the provider. It needs to be handled by the user. + * + * @param changeInfo Indicates the info of the data to operate. + */ +void DataShareHelperImpl::NotifyChangeExtProvider(const DataShareObserver::ChangeInfo &changeInfo) +{ + auto generalCtl = generalCtl_; + if (generalCtl == nullptr) { + LOG_ERROR("extSpCtl is nullptr"); + return; + } + DataShareServiceProxy::SetSystem(isSystem_); + // only support non-silent access + ErrCode ret = generalCtl->NotifyChangeExtProvider(ObserverImpl::ConvertInfo(changeInfo)); + DataShareServiceProxy::CleanSystem(); + LOG_INFO("Notify changeExt, ret:%{public}d", ret); + return; +} + Uri DataShareHelperImpl::NormalizeUri(Uri &uri) { DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); @@ -432,6 +563,12 @@ std::vector DataShareHelperImpl::EnableRdbSubs(const std::vecto const TemplateId &templateId) { LOG_DEBUG("Start EnableSubscribeRdbData"); + std::string uriAll = ""; + for (auto uri : uris) { + uriAll += (DataShareStringUtils::Anonymous(uri) + ","); + } + LOG_INFO("uri is %{public}s bundleName is %{public}s, subscriberId is %{public}" PRId64 "", + DataShareStringUtils::Anonymous(uriAll).c_str(), templateId.bundleName_.c_str(), templateId.subscriberId_); auto persistentDataCtl = persistentDataCtl_; if (persistentDataCtl == nullptr) { LOG_ERROR("persistentDataCtl is nullptr"); @@ -447,6 +584,12 @@ std::vector DataShareHelperImpl::DisableRdbSubs(const std::vect const TemplateId &templateId) { LOG_DEBUG("Start DisableSubscribeRdbData"); + std::string uriAll = ""; + for (auto uri : uris) { + uriAll += (DataShareStringUtils::Anonymous(uri) + ","); + } + LOG_INFO("uri is %{public}s bundleName is %{public}s, subscriberId is %{public}" PRId64 "", + DataShareStringUtils::Anonymous(uriAll).c_str(), templateId.bundleName_.c_str(), templateId.subscriberId_); auto persistentDataCtl = persistentDataCtl_; if (persistentDataCtl == nullptr) { LOG_ERROR("persistentDataCtl is nullptr"); @@ -498,6 +641,12 @@ std::vector DataShareHelperImpl::EnablePubSubs(const std::vecto int64_t subscriberId) { LOG_DEBUG("Start enablePubSubs"); + std::string uriAll = ""; + for (auto uri : uris) { + uriAll += (DataShareStringUtils::Anonymous(uri) + ","); + } + LOG_INFO("uri is %{public}s subscriberId is %{public}" PRId64 "", + DataShareStringUtils::Anonymous(uriAll).c_str(), subscriberId); auto publishedDataCtl = publishedDataCtl_; if (publishedDataCtl == nullptr) { LOG_ERROR("publishedDataCtl is nullptr"); @@ -513,6 +662,12 @@ std::vector DataShareHelperImpl::DisablePubSubs(const std::vect int64_t subscriberId) { LOG_DEBUG("Start disablePubSubs"); + std::string uriAll = ""; + for (auto uri : uris) { + uriAll += (DataShareStringUtils::Anonymous(uri) + ","); + } + LOG_INFO("uri is %{public}s subscriberId is %{public}" PRId64 "", + DataShareStringUtils::Anonymous(uriAll).c_str(), subscriberId); auto publishedDataCtl = publishedDataCtl_; if (publishedDataCtl == nullptr) { LOG_ERROR("publishedDataCtl is nullptr"); diff --git a/data_share/frameworks/native/consumer/src/datashare_proxy.cpp b/data_share/frameworks/native/consumer/src/datashare_proxy.cpp index 8ce36b324ed609bd9b79dd43dd96efdf4be8ab33..37bddd733df31995661c84925775073dc911d9f3 100644 --- a/data_share/frameworks/native/consumer/src/datashare_proxy.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_proxy.cpp @@ -67,7 +67,7 @@ std::vector DataShareProxy::GetFileTypes(const Uri &uri, const std: return types; } -int DataShareProxy::OpenFile(const Uri &uri, const std::string &mode) +int DataShareProxy::OpenFileInner(const Uri &uri, const std::string &mode, uint32_t requestCode, int32_t &errCode) { int fd = -1; MessageParcel data; @@ -88,10 +88,10 @@ int DataShareProxy::OpenFile(const Uri &uri, const std::string &mode) MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest( - static_cast(IDataShareInterfaceCode::CMD_OPEN_FILE), data, reply, option); + int32_t err = Remote()->SendRequest(requestCode, data, reply, option); if (err != E_OK) { LOG_ERROR("OpenFile fail to SendRequest. err: %{public}d", err); + errCode = err; return fd; } @@ -104,6 +104,19 @@ int DataShareProxy::OpenFile(const Uri &uri, const std::string &mode) return fd; } +int DataShareProxy::OpenFile(const Uri &uri, const std::string &mode) +{ + int32_t errCode = 0; + uint32_t requestCode = static_cast(IDataShareInterfaceCode::CMD_OPEN_FILE); + return OpenFileInner(uri, mode, requestCode, errCode); +} + +int DataShareProxy::OpenFileWithErrCode(const Uri &uri, const std::string &mode, int32_t &errCode) +{ + uint32_t requestCode = static_cast(IDataShareInterfaceCode::CMD_OPEN_FILE_WITH_ERR_CODE); + return OpenFileInner(uri, mode, requestCode, errCode); +} + int DataShareProxy::OpenRawFile(const Uri &uri, const std::string &mode) { int fd = -1; @@ -246,8 +259,8 @@ int DataShareProxy::BatchUpdate(const UpdateOperations &operations, std::vector< int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_BATCH_UPDATE), data, reply, option); if (err != E_OK) { - LOG_ERROR("fail to SendRequest. err: %{public}d", err); - return err; + LOG_ERROR("BatchUpdate fail to SendRequest. err: %{public}d", err); + return err == PERMISSION_ERR ? PERMISSION_ERR_CODE : ret; } if (!ITypesUtil::Unmarshal(reply, results)) { LOG_ERROR("fail to Unmarshal result"); @@ -385,14 +398,17 @@ std::shared_ptr DataShareProxy::Query(const Uri &uri, const MessageParcel data; if (!data.WriteInterfaceToken(DataShareProxy::GetDescriptor())) { LOG_ERROR("WriteInterfaceToken failed"); + businessError.SetCode(E_WRITE_TO_PARCE_ERROR); return nullptr; } if (!ITypesUtil::Marshal(data, uri, columns)) { LOG_ERROR("Marshalling uri and columns to data failed"); + businessError.SetCode(E_MARSHAL_ERROR); return nullptr; } if (!ITypesUtil::MarshalPredicates(predicates, data)) { LOG_ERROR("Marshalling predicates to shared-memory failed"); + businessError.SetCode(E_MARSHAL_ERROR); return nullptr; } MessageParcel reply; @@ -400,12 +416,13 @@ std::shared_ptr DataShareProxy::Query(const Uri &uri, const int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_QUERY), data, reply, option); auto result = ISharedResultSet::ReadFromParcel(reply); - businessError.SetCode(reply.ReadInt32()); - businessError.SetMessage(reply.ReadString()); if (err != E_OK) { LOG_ERROR("Query fail to SendRequest. err: %{public}d", err); + businessError.SetCode(err); return nullptr; } + businessError.SetCode(reply.ReadInt32()); + businessError.SetMessage(reply.ReadString()); return result; } @@ -524,7 +541,8 @@ bool DataShareProxy::RegisterObserver(const Uri &uri, const sptr &dataObserver) @@ -547,7 +565,8 @@ bool DataShareProxy::UnregisterObserver(const Uri &uri, const sptr &dataObserver, + bool isDescendants, RegisterOption registerOption) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(DataShareProxy::GetDescriptor())) { + LOG_ERROR("WriteInterfaceToken failed"); + return E_WRITE_TO_PARCE_ERROR; + } + + if (!ITypesUtil::Marshal(data, uri, dataObserver->AsObject(), isDescendants, registerOption)) { + LOG_ERROR("fail to Marshalling"); + return E_MARSHAL_ERROR; + } + + MessageParcel reply; + MessageOption option; + int32_t result = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_REGISTER_OBSERVEREXT_PROVIDER), data, reply, option); + if (result != ERR_NONE) { + LOG_ERROR("SendRequest error, result=%{public}d", result); + return DATA_SHARE_ERROR; + } + // the stub write int value to reply + return reply.ReadInt32(); +} + +// send IPC request, and there is no default implemention for the provider. It needs to be handled by the user. +int DataShareProxy::UnregisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(DataShareProxy::GetDescriptor())) { + LOG_ERROR("WriteInterfaceToken failed"); + return E_WRITE_TO_PARCE_ERROR; + } + + if (!ITypesUtil::Marshal(data, uri, dataObserver->AsObject())) { + LOG_ERROR("fail to Marshalling"); + return E_MARSHAL_ERROR; + } + + MessageParcel reply; + MessageOption option; + int32_t result = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_UNREGISTER_OBSERVEREXT_PROVIDER), data, reply, option); + if (result != ERR_NONE) { + LOG_ERROR("SendRequest error, result=%{public}d", result); + return DATA_SHARE_ERROR; + } + // the stub writeint value to reply + return reply.ReadInt32(); +} + +// send IPC request, and there is no default implemention for the provider. It needs to be handled by the user. +int DataShareProxy::NotifyChangeExtProvider(const ChangeInfo &changeInfo) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(DataShareProxy::GetDescriptor())) { + LOG_ERROR("WriteInterfaceToken failed"); + return E_WRITE_TO_PARCE_ERROR; + } + if (!ChangeInfo::Marshalling(changeInfo, data)) { + LOG_ERROR("changeInfo marshalling failed, changeType:%{public}ud, num:%{public}zu," + "null data:%{public}d, size:%{public}ud", + changeInfo.changeType_, changeInfo.uris_.size(), changeInfo.data_ == nullptr, changeInfo.size_); + return E_MARSHAL_ERROR; + } + + MessageParcel reply; + MessageOption option; + int32_t result = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_NOTIFY_CHANGEEXT_PROVIDER), data, reply, option); + if (result != ERR_NONE) { + LOG_ERROR("SendRequest error, result=%{public}d", result); + return DATA_SHARE_ERROR; + } + // the stub write int value to reply + return reply.ReadInt32(); +} + Uri DataShareProxy::NormalizeUri(const Uri &uri) { MessageParcel data; @@ -643,15 +743,14 @@ bool DataShareProxy::CheckSize(const UpdateOperations &operations) } return true; } + int32_t DataShareProxy::UserDefineFunc( MessageParcel &data, MessageParcel &reply, MessageOption &option) { - int32_t errCode = -1; int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_USER_DEFINE_FUNC), data, reply, option); if (err != E_OK) { - LOG_ERROR("UserDefineFunc fail to SendRequest. err: %{public}d", err); - return err == PERMISSION_ERR ? PERMISSION_ERR_CODE : errCode; + LOG_ERROR("UserDefineFunc SendRequest fails. err: %{public}d", err); } return err; } diff --git a/data_share/frameworks/native/dfx/include/hiview_datashare.h b/data_share/frameworks/native/dfx/include/hiview_datashare.h new file mode 100644 index 0000000000000000000000000000000000000000..a3f5b7dfe926e0313e60b815d82100ab0e24a44d --- /dev/null +++ b/data_share/frameworks/native/dfx/include/hiview_datashare.h @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2025 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 DATASHARESERVICE_HIVIEW_ADAPTER_H +#define DATASHARESERVICE_HIVIEW_ADAPTER_H + +#include "executor_pool.h" +#include "hisysevent_c.h" + +namespace OHOS { +namespace DataShare { + +struct DataShareFaultInfo { + std::string faultType; + std::string bundleName; + std::string moduleName; + std::string storeName; + std::string businessType; + int32_t errorCode; + std::string appendix; +}; + +class HiViewFaultAdapter { +public: + static constexpr const char* extensionFailed = "EXT_FAILED"; + static constexpr const char* silentFailed = "SILENT_FAILED"; + static constexpr const char* trustsFailed = "TRUSTS_FAILED"; + static void ReportDataFault(const DataShareFaultInfo &faultInfo); + static std::pair GetCallingName(uint32_t callingTokenid); +}; + +} // namespace DataShare +} // namespace OHOS +#endif // DATASHARESERVICE_HIVIEW_ADAPTER_H \ No newline at end of file diff --git a/data_share/frameworks/native/dfx/src/hiview_datashare.cpp b/data_share/frameworks/native/dfx/src/hiview_datashare.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f73cc87500f0b69404df21f0bcd255e2f1fae00d --- /dev/null +++ b/data_share/frameworks/native/dfx/src/hiview_datashare.cpp @@ -0,0 +1,97 @@ +/* +* Copyright (c) 2025 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 "HiViewAdapter" + +#include "hiview_datashare.h" + +#include +#include +#include +#include "access_token.h" +#include "accesstoken_kit.h" +#include "log_print.h" + +namespace OHOS { +namespace DataShare { + +using namespace std::chrono; + +namespace { + constexpr char DOMAIN[] = "DISTDATAMGR"; + constexpr const char *EVENT_NAME = "DISTRIBUTED_DATA_SHARE_FAULT"; + constexpr const size_t PARAMS_SIZE = 8; + // digits for milliseconds + constexpr uint8_t MILLSECOND_DIGIT = 3; +} + +void HiViewFaultAdapter::ReportDataFault(const DataShareFaultInfo &faultInfo) +{ + auto now = std::chrono::system_clock::now(); + auto t = std::chrono::system_clock::to_time_t(now); + std::stringstream ss; + ss << std::put_time(std::localtime(&t), "%F %T"); + // get milliseconds + auto ms = std::chrono::duration_cast(now.time_since_epoch()) % 1000; + ss << '.' << std::setfill('0') << std::setw(MILLSECOND_DIGIT) << ms.count(); + auto time = ss.str(); + HiSysEventParam faultTime = { .name = "FAULT_TIME", .t = HISYSEVENT_STRING, + .v = { .s = const_cast(time.c_str()) }, .arraySize = 0 }; + HiSysEventParam faultType = { .name = "FAULT_TYPE", .t = HISYSEVENT_STRING, + .v = { .s = const_cast(faultInfo.faultType.c_str()) }, .arraySize = 0 }; + HiSysEventParam bundleName = { .name = "BUNDLE_NAME", .t = HISYSEVENT_STRING, + .v = { .s = const_cast(faultInfo.bundleName.c_str()) }, .arraySize = 0 }; + HiSysEventParam moduleName = { .name = "MODULE_NAME", .t = HISYSEVENT_STRING, + .v = { .s = const_cast(faultInfo.moduleName.c_str()) }, .arraySize = 0 }; + HiSysEventParam storeName = { .name = "STORE_NAME", .t = HISYSEVENT_STRING, + .v = { .s = const_cast(faultInfo.storeName.c_str()) }, .arraySize = 0 }; + HiSysEventParam businessType = { .name = "BUSINESS_TYPE", .t = HISYSEVENT_STRING, + .v = { .s = const_cast(faultInfo.businessType.c_str()) }, .arraySize = 0 }; + HiSysEventParam errorCode = { .name = "ERROR_CODE", .t = HISYSEVENT_INT32, + .v = { .i32 = faultInfo.errorCode }, .arraySize = 0 }; + HiSysEventParam appendix = { .name = "APPENDIX", .t = HISYSEVENT_STRING, + .v = { .s = const_cast(faultInfo.appendix.c_str()) }, .arraySize = 0 }; + HiSysEventParam params[] = { faultTime, faultType, bundleName, moduleName, + storeName, businessType, errorCode, appendix }; + int res = OH_HiSysEvent_Write(DOMAIN, EVENT_NAME, HISYSEVENT_FAULT, params, PARAMS_SIZE); + if (res != 0) { + ZLOGI("OH_HiSysEvent_Write fail, res = %{public}d", res); + } +} + +std::pair HiViewFaultAdapter::GetCallingName(uint32_t callingTokenid) +{ + std::string callingName; + auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(callingTokenid); + int result = -1; + if (tokenType == Security::AccessToken::TOKEN_HAP) { + Security::AccessToken::HapTokenInfo tokenInfo; + result = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(callingTokenid, tokenInfo); + if (result == Security::AccessToken::RET_SUCCESS) { + callingName = tokenInfo.bundleName; + } + } else if (tokenType == Security::AccessToken::TOKEN_NATIVE || tokenType == Security::AccessToken::TOKEN_SHELL) { + Security::AccessToken::NativeTokenInfo tokenInfo; + result = Security::AccessToken::AccessTokenKit::GetNativeTokenInfo(callingTokenid, tokenInfo); + if (result == Security::AccessToken::RET_SUCCESS) { + callingName = tokenInfo.processName; + } + } else { + ZLOGE("tokenType is invalid, tokenType:%{public}d, Tokenid:%{public}x", tokenType, callingTokenid); + } + return std::make_pair(callingName, result); +} + +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/permission/include/data_share_called_config.h b/data_share/frameworks/native/permission/include/data_share_called_config.h index c265c3f26b7e45cc859584208ed57467b19ffb5e..4000536bde321c03f56e9cc108702854d5de4331 100644 --- a/data_share/frameworks/native/permission/include/data_share_called_config.h +++ b/data_share/frameworks/native/permission/include/data_share_called_config.h @@ -32,19 +32,25 @@ public: struct ProviderInfo { std::string uri; + std::string schema; std::string bundleName; std::string moduleName; std::string readPermission; std::string writePermission; int32_t currentUserId = -1; + bool isExtension = false; }; - std::pair GetProviderInfo(uint32_t tokenId); + std::pair GetProviderInfo(int32_t user); + static std::pair GetBundleInfoFromBMS(std::string bundleName, int32_t user); + static std::pair GetExtensionInfoFromBMS(std::string &uri, int32_t user); + static int32_t GetUserByToken(uint32_t tokenId); + std::string BundleName(); private: int GetFromProxyData(); - int32_t GetUserByToken(uint32_t tokenId); - std::pair GetBundleInfoFromBMS(); - ProviderInfo providerInfo_; static constexpr const char *PROXY_URI_SCHEMA = "datashareproxy"; + static constexpr const char *PROXY_URI_SCHEMA_SEPARATOR = "datashareproxy://"; + static constexpr const char *EXT_URI_SCHEMA_SEPARATOR = "datashare://"; + ProviderInfo providerInfo_; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/permission/include/data_share_config.h b/data_share/frameworks/native/permission/include/data_share_config.h new file mode 100644 index 0000000000000000000000000000000000000000..ffd252c53b4e48cc66dd6abf524945cb0fd54b84 --- /dev/null +++ b/data_share/frameworks/native/permission/include/data_share_config.h @@ -0,0 +1,71 @@ +/* + * 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 OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_CONFIG_FACTORY_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_CONFIG_FACTORY_H +#include +#include +#include +#include "serializable.h" +#include "visibility.h" +namespace OHOS { +namespace DataShare { + +class DataShareConfig final : public Serializable { +public: + struct Bundle final : public Serializable { + std::string name; + std::string appIdentifier; + bool Marshal(Serializable::json &node) const override; + bool Unmarshal(const Serializable::json &node) override; + }; + struct ConsumerProvider final : public Serializable { + std::vector consumer; + Bundle provider; + bool Marshal(Serializable::json &node) const override; + bool Unmarshal(const Serializable::json &node) override; + }; + bool Marshal(Serializable::json &node) const override; + bool Unmarshal(const Serializable::json &node) override; + std::vector dataShareExtNames; + std::vector uriTrusts; + std::vector extensionObsTrusts; +}; + +class GlobalConfig final : public Serializable { +public: + DataShareConfig *dataShare = nullptr; + ~GlobalConfig(); + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; +}; + +class ConfigFactory { +public: + API_EXPORT static ConfigFactory &GetInstance(); + API_EXPORT int32_t Initialize(); + API_EXPORT DataShareConfig *GetDataShareConfig(); +private: + static constexpr const char *CONF_PATH = "/system/etc/distributeddata/conf"; + ConfigFactory(); + ~ConfigFactory(); + + std::string file_; + GlobalConfig config_; + bool isInited = false; +}; +} // namespace DistributedData +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_CONFIG_FACTORY_H \ No newline at end of file diff --git a/data_share/frameworks/native/permission/src/data_share_called_config.cpp b/data_share/frameworks/native/permission/src/data_share_called_config.cpp index 3b3631d3d56283719058b7afc20d6230d14204ac..a2a04dd7d15921376ac0167fb18dd5b5a389ce21 100644 --- a/data_share/frameworks/native/permission/src/data_share_called_config.cpp +++ b/data_share/frameworks/native/permission/src/data_share_called_config.cpp @@ -25,8 +25,11 @@ #include "datashare_errno.h" #include "datashare_log.h" #include "datashare_string_utils.h" +#include "data_share_permission.h" +#include "hiview_datashare.h" #include "if_system_ability_manager.h" #include "iservice_registry.h" +#include "ipc_skeleton.h" #include "system_ability_definition.h" namespace OHOS::DataShare { @@ -35,6 +38,23 @@ using namespace OHOS::Security::AccessToken; DataShareCalledConfig::DataShareCalledConfig(const std::string &uri) { providerInfo_.uri = uri; + Uri uriTemp(providerInfo_.uri); + providerInfo_.schema = uriTemp.GetScheme(); + auto isProxyData = PROXY_URI_SCHEMA == providerInfo_.schema; + std::string bundleName = uriTemp.GetAuthority(); + if (!isProxyData) { + std::vector pathSegments; + uriTemp.GetPathSegments(pathSegments); + if (pathSegments.size() != 0) { + bundleName = pathSegments[0]; + } + } + providerInfo_.bundleName = bundleName; +} + +std::string DataShareCalledConfig::BundleName() +{ + return providerInfo_.bundleName; } int32_t DataShareCalledConfig::GetUserByToken(uint32_t tokenId) @@ -46,8 +66,8 @@ int32_t DataShareCalledConfig::GetUserByToken(uint32_t tokenId) HapTokenInfo tokenInfo; auto result = AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo); if (result != RET_SUCCESS) { - LOG_ERROR("Get user failed!token:0x%{public}x, result:%{public}d, uri:%{public}s", - tokenId, result, DataShareStringUtils::Anonymous(providerInfo_.uri).c_str()); + LOG_ERROR("Get user failed!token:0x%{public}x, result:%{public}d", + tokenId, result); return -1; } return tokenInfo.userID; @@ -55,7 +75,7 @@ int32_t DataShareCalledConfig::GetUserByToken(uint32_t tokenId) int DataShareCalledConfig::GetFromProxyData() { - auto [success, bundleInfo] = GetBundleInfoFromBMS(); + auto [success, bundleInfo] = GetBundleInfoFromBMS(providerInfo_.bundleName, providerInfo_.currentUserId); if (!success) { LOG_ERROR("Get bundleInfo failed! bundleName:%{public}s, userId:%{public}d, uri:%{public}s", providerInfo_.bundleName.c_str(), providerInfo_.currentUserId, @@ -68,9 +88,14 @@ int DataShareCalledConfig::GetFromProxyData() if (schemePos != uriWithoutQuery.npos) { uriWithoutQuery.replace(schemePos, Constants::PARAM_URI_SEPARATOR_LEN, Constants::URI_SEPARATOR); } + schemePos = uriWithoutQuery.find(EXT_URI_SCHEMA_SEPARATOR); + if (schemePos != uriWithoutQuery.npos) { + uriWithoutQuery.replace(schemePos, strlen(EXT_URI_SCHEMA_SEPARATOR), PROXY_URI_SCHEMA_SEPARATOR); + } for (auto &hapModuleInfo : bundleInfo.hapModuleInfos) { for (auto &data : hapModuleInfo.proxyDatas) { - if (data.uri != uriWithoutQuery) { + if (data.uri.length() > uriWithoutQuery.length() || + uriWithoutQuery.compare(0, data.uri.length(), data.uri) != 0) { continue; } providerInfo_.readPermission = std::move(data.requiredReadPermission); @@ -79,53 +104,78 @@ int DataShareCalledConfig::GetFromProxyData() return E_OK; } } + LOG_ERROR("E_URI_NOT_EXIST uriWithoutQuery %{public}s", uriWithoutQuery.c_str()); return E_URI_NOT_EXIST; } -std::pair DataShareCalledConfig::GetProviderInfo(uint32_t tokenId) +std::pair DataShareCalledConfig::GetProviderInfo(int32_t user) { - Uri uriTemp(providerInfo_.uri); - auto isProxyData = PROXY_URI_SCHEMA == uriTemp.GetScheme(); - std::string bundleName = uriTemp.GetAuthority(); - if (!isProxyData) { - std::vector pathSegments; - uriTemp.GetPathSegments(pathSegments); - if (pathSegments.size() != 0) { - bundleName = pathSegments[0]; - } - } - if (bundleName.empty()) { - LOG_ERROR("BundleName not exist!, tokenId:0x%{public}x, uri:%{public}s", - tokenId, DataShareStringUtils::Anonymous(providerInfo_.uri).c_str()); + if (providerInfo_.bundleName.empty()) { + LOG_ERROR("BundleName not exist!, user:%{public}d, uri:%{public}s", + user, DataShareStringUtils::Anonymous(providerInfo_.uri).c_str()); return std::make_pair(E_BUNDLE_NAME_NOT_EXIST, DataShareCalledConfig::ProviderInfo{}); } - providerInfo_.bundleName = bundleName; - providerInfo_.currentUserId = GetUserByToken(tokenId); + providerInfo_.currentUserId = user; auto ret = GetFromProxyData(); if (ret != E_OK) { - LOG_ERROR("Failed! isProxyData:%{public}d,ret:%{public}d,tokenId:0x%{public}x,uri:%{public}s", - isProxyData, ret, tokenId, DataShareStringUtils::Anonymous(providerInfo_.uri).c_str()); + LOG_ERROR("GetFromProxyData Failed! ret:%{public}d,user:%{public}d,uri:%{public}s", + ret, user, providerInfo_.uri.c_str()); } return std::make_pair(ret, providerInfo_); } -std::pair DataShareCalledConfig::GetBundleInfoFromBMS() +std::pair DataShareCalledConfig::GetBundleInfoFromBMS(std::string bundleName, int32_t user) { BundleInfo bundleInfo; auto bmsHelper = DelayedSingleton::GetInstance(); if (bmsHelper == nullptr) { LOG_ERROR("BmsHelper is nullptr!.uri: %{public}s", - DataShareStringUtils::Anonymous(providerInfo_.uri).c_str()); + DataShareStringUtils::Anonymous(bundleName).c_str()); return std::make_pair(false, bundleInfo); } - bool ret = bmsHelper->GetBundleInfo(providerInfo_.bundleName, - BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo, providerInfo_.currentUserId); + + if (user == 0) { + user = Constants::ANY_USERID; + } + // because BMS and obs are in the same process. + // set IPCSkeleton tokenid to this process's tokenid. + // otherwise BMS may check permission failed. + std::string identity = IPCSkeleton::ResetCallingIdentity(); + bool ret = bmsHelper->GetBundleInfo(bundleName, + BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo, user); + IPCSkeleton::SetCallingIdentity(identity); if (!ret) { - LOG_ERROR("Get BundleInfo failed! bundleName:%{public}s, userId:%{public}d,uri:%{public}s", - providerInfo_.bundleName.c_str(), providerInfo_.currentUserId, - DataShareStringUtils::Anonymous(providerInfo_.uri).c_str()); + LOG_ERROR("Get BundleInfo failed! bundleName:%{public}s, userId:%{public}d", + bundleName.c_str(), user); return std::make_pair(false, bundleInfo); } return std::make_pair(true, bundleInfo); } + +std::pair DataShareCalledConfig::GetExtensionInfoFromBMS(std::string &uri, int32_t user) +{ + ExtensionAbilityInfo info; + auto bmsHelper = DelayedSingleton::GetInstance(); + if (bmsHelper == nullptr) { + LOG_ERROR("BmsHelper is nullptr!.uri: %{public}s", + DataShareStringUtils::Anonymous(uri).c_str()); + return std::make_pair(false, info); + } + + if (user == 0) { + user = Constants::ANY_USERID; + } + // because BMS and obs are in the same process. + // set IPCSkeleton tokenid to this process's tokenid. + // otherwise BMS may check permission failed. + std::string identity = IPCSkeleton::ResetCallingIdentity(); + bool ret = bmsHelper->QueryExtensionAbilityInfoByUri(uri, user, info); + IPCSkeleton::SetCallingIdentity(identity); + if (!ret) { + LOG_ERROR("QueryExtensionAbilityInfoByUri failed! uri:%{public}s, userId:%{public}d", + uri.c_str(), user); + return std::make_pair(false, info); + } + return std::make_pair(true, info); +} } // namespace OHOS::DataShare \ No newline at end of file diff --git a/data_share/frameworks/native/permission/src/data_share_config.cpp b/data_share/frameworks/native/permission/src/data_share_config.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42cc4e9ce124464615f0ef497a31e7bf5f1b0e38 --- /dev/null +++ b/data_share/frameworks/native/permission/src/data_share_config.cpp @@ -0,0 +1,127 @@ +/* + * 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 +#include +#include "data_share_config.h" +#include "datashare_log.h" +namespace OHOS { +namespace DataShare { +ConfigFactory::ConfigFactory() : file_(std::string(CONF_PATH) + "/config.json") +{ +} + +ConfigFactory::~ConfigFactory() +{ +} + +ConfigFactory &ConfigFactory::GetInstance() +{ + static std::mutex mutex; + static ConfigFactory factory; + if (factory.isInited) { + return factory; + } + std::lock_guard lock(mutex); + factory.Initialize(); + return factory; +} + +int32_t ConfigFactory::Initialize() +{ + std::string jsonStr; + std::ifstream fin(file_); + if (!fin.is_open()) { + LOG_ERROR("ConfigFactory open file failed"); + return -1; + } + while (fin.good()) { + std::string line; + std::getline(fin, line); + jsonStr += line; + } + config_.Unmarshall(jsonStr); + isInited = true; + return 0; +} + +DataShareConfig *ConfigFactory::GetDataShareConfig() +{ + return config_.dataShare; +} + +bool DataShareConfig::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(dataShareExtNames)], dataShareExtNames); + SetValue(node[GET_NAME(uriTrusts)], uriTrusts); + SetValue(node[GET_NAME(extensionObsTrusts)], extensionObsTrusts); + return true; +} + +bool DataShareConfig::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(dataShareExtNames), dataShareExtNames); + GetValue(node, GET_NAME(uriTrusts), uriTrusts); + GetValue(node, GET_NAME(extensionObsTrusts), extensionObsTrusts); + return true; +} + +bool DataShareConfig::ConsumerProvider::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(consumer)], consumer); + SetValue(node[GET_NAME(provider)], provider); + return true; +} + +bool DataShareConfig::ConsumerProvider::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(consumer), consumer); + GetValue(node, GET_NAME(provider), provider); + return true; +} + +bool DataShareConfig::Bundle::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(name)], name); + SetValue(node[GET_NAME(appIdentifier)], appIdentifier); + return true; +} + +bool DataShareConfig::Bundle::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(name), name); + GetValue(node, GET_NAME(appIdentifier), appIdentifier); + return true; +} + +bool GlobalConfig::Marshal(json &node) const +{ + SetValue(node[GET_NAME(dataShare)], dataShare); + return true; +} + +bool GlobalConfig::Unmarshal(const json &node) +{ + GetValue(node, GET_NAME(dataShare), dataShare); + return true; +} + +GlobalConfig::~GlobalConfig() +{ + if (dataShare != nullptr) { + delete dataShare; + } +} +} // namespace DistributedData +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/permission/src/data_share_permission.cpp b/data_share/frameworks/native/permission/src/data_share_permission.cpp index b0862a2295ef475908cd18fb26ad5ef6a4770011..896ffafddf3612df317dae663817b8e571c8b608 100644 --- a/data_share/frameworks/native/permission/src/data_share_permission.cpp +++ b/data_share/frameworks/native/permission/src/data_share_permission.cpp @@ -12,20 +12,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "datashare_uri_utils.h" #define LOG_TAG "DataSharePermission" #include "data_share_permission.h" #include +#include "access_token.h" +#include "bundle_mgr_helper.h" #include "data_share_called_config.h" #include "datashare_errno.h" #include "datashare_log.h" #include "datashare_string_utils.h" +#include "data_share_config.h" +#include "hiview_datashare.h" +#include "ipc_skeleton.h" namespace OHOS { namespace DataShare { using namespace AppExecFwk; +static constexpr const char *NO_PERMISSION = "noPermission"; int DataSharePermission::VerifyPermission(Security::AccessToken::AccessTokenID tokenID, const Uri &uri, bool isRead) { if (uri.ToString().empty()) { @@ -33,7 +40,8 @@ int DataSharePermission::VerifyPermission(Security::AccessToken::AccessTokenID t return ERR_INVALID_VALUE; } DataShareCalledConfig calledConfig(uri.ToString()); - auto [errCode, providerInfo] = calledConfig.GetProviderInfo(tokenID); + int32_t user = DataShareCalledConfig::GetUserByToken(tokenID); + auto [errCode, providerInfo] = calledConfig.GetProviderInfo(user); if (errCode != E_OK) { LOG_ERROR("ProviderInfo failed! token:0x%{public}x, errCode:%{public}d,uri:%{public}s", tokenID, errCode, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); @@ -54,5 +62,250 @@ int DataSharePermission::VerifyPermission(Security::AccessToken::AccessTokenID t } return E_OK; } + +bool IsInUriTrusts(Uri &uri) +{ + auto config = ConfigFactory::GetInstance().GetDataShareConfig(); + if (config == nullptr) { + LOG_ERROR("GetDataShareConfig null"); + return false; + } + std::string uriStr = uri.ToString(); + for (std::string& item : config->uriTrusts) { + if (item.length() > uriStr.length() || + uriStr.compare(0, item.length(), item) != 0) { + continue; + } + return true; + } + return false; +} + +bool CheckAppIdentifier(std::string &name, std::string &appIdentifier) +{ + auto [isSuccess, bundleInfo] = DataShareCalledConfig::GetBundleInfoFromBMS(name, 0); + if (!isSuccess) { + return false; + } + if (bundleInfo.signatureInfo.appIdentifier == appIdentifier) { + return true; + } + return false; +} + +bool IsInExtensionTrusts(std::string& consumer, std::string& provider) +{ + auto config = ConfigFactory::GetInstance().GetDataShareConfig(); + if (config == nullptr) { + LOG_ERROR("GetDataShareConfig is null"); + return false; + } + std::string appIdentifier; + for (DataShareConfig::ConsumerProvider& item : config->extensionObsTrusts) { + if (item.provider.name != provider) { + continue; + } + if (!CheckAppIdentifier(item.provider.name, item.provider.appIdentifier)) { + return false; + } + for (auto item : item.consumer) { + if (item.name == consumer) { + appIdentifier = item.appIdentifier; + break; + } + } + } + if (consumer == provider) { + return true; + } + if (CheckAppIdentifier(consumer, appIdentifier)) { + return true; + } + return false; +} + +int32_t DataSharePermission::UriIsTrust(Uri &uri) +{ + std::string schema = uri.GetScheme(); + if (schema == SCHEMA_PREFERENCE || schema == SCHEMA_RDB || schema == SCHEMA_FILE) { + return E_OK; + } + if (IsInUriTrusts(uri)) { + return E_OK; + } + if (!schema.empty() && schema != SCHEMA_DATASHARE && schema != SCHEMA_DATASHARE_PROXY) { + LOG_ERROR("invalid uri %{public}s, schema %{public}s", + uri.ToString().c_str(), uri.GetScheme().c_str()); + return E_DATASHARE_INVALID_URI; + } + return E_ERROR; +} + +std::pair DataSharePermission::GetExtensionUriPermission(Uri &uri, + int32_t user, bool isRead) +{ + std::string uriStr = uri.ToString(); + std::string permission; + auto [isSuccess, extensionInfo] = DataShareCalledConfig::GetExtensionInfoFromBMS(uriStr, user); + if (isSuccess) { + permission = isRead ? extensionInfo.readPermission : extensionInfo.writePermission; + LOG_ERROR("GetExtensionUriPermission uri %{public}s %{public}s %{public}s", + extensionInfo.uri.c_str(), extensionInfo.readPermission.c_str(), extensionInfo.writePermission.c_str()); + return std::make_pair(E_OK, permission); + } + return std::make_pair(E_URI_NOT_EXIST, ""); +} + +std::pair DataSharePermission::GetUriPermission(Uri &uri, int32_t user, bool isRead, bool isExtension) +{ + std::string uriStr = uri.ToString(); + if (uriStr.empty()) { + return std::make_pair(E_EMPTY_URI, ""); + } + int32_t ret = UriIsTrust(uri); + if (ret == E_OK) { + return std::make_pair(E_OK, NO_PERMISSION); + } else if (ret == E_DATASHARE_INVALID_URI) { + return std::make_pair(E_DATASHARE_INVALID_URI, ""); + } + std::string permission; + if (isExtension) { + std::tie(ret, permission) = GetExtensionUriPermission(uri, user, isRead); + } else { + std::tie(ret, permission) = GetSilentUriPermission(uri, user, isRead); + } + if (ret == E_OK) { + return std::make_pair(E_OK, permission); + } + return std::make_pair(ret, ""); +} + +void DataSharePermission::ReportExcuteFault(int32_t errCode, std::string &consumer, std::string &provider) +{ + DataShareFaultInfo faultInfo = {HiViewFaultAdapter::trustsFailed, consumer, provider, + "", "", errCode, ""}; + HiViewFaultAdapter::ReportDataFault(faultInfo); +} + +void DataSharePermission::ReportExtensionFault(int32_t errCode, uint32_t tokenId, + std::string &uri, std::string &bussinessType) +{ + auto [bundleName, ret] = HiViewFaultAdapter::GetCallingName(tokenId); + DataShareFaultInfo faultInfo = {HiViewFaultAdapter::extensionFailed, bundleName, "", + "", bussinessType, errCode, uri}; + HiViewFaultAdapter::ReportDataFault(faultInfo); +} + +std::pair DataSharePermission::GetSilentUriPermission(Uri &uri, int32_t user, bool isRead) +{ + std::string uriStr = uri.ToString(); + DataShareCalledConfig calledConfig(uriStr); + + auto [errCode, providerInfo] = calledConfig.GetProviderInfo(user); + if (errCode != E_OK) { + LOG_ERROR("ProviderInfo failed! user:%{public}d, errCode:%{public}d,uri:%{public}s", user, + errCode, uri.ToString().c_str()); + return std::make_pair(errCode, ""); + } + auto permission = isRead ? providerInfo.readPermission : providerInfo.writePermission; + return std::make_pair(E_OK, permission); +} + +int DataSharePermission::CheckExtensionTrusts(uint32_t consumerToken, uint32_t providerToken) +{ + auto [consumer, ret1] = HiViewFaultAdapter::GetCallingName(consumerToken); + auto [provider, ret2] = HiViewFaultAdapter::GetCallingName(providerToken); + if (ret1 != E_OK || ret2 != E_OK) { + LOG_ERROR("GetCallingName failed, consumer %{public}d %{public}s provider %{public}d " + "%{public}s", consumerToken, consumer.c_str(), providerToken, provider.c_str()); + return E_GET_CALLER_NAME_FAILED; + } + if (IsInExtensionTrusts(consumer, provider)) { + return E_OK; + } + LOG_ERROR("CheckExtensionTrusts failed, consumer %{public}d %{public}s provider %{public}d " + "%{public}s", consumerToken, consumer.c_str(), providerToken, provider.c_str()); + ReportExcuteFault(E_NOT_IN_TRUSTS, consumer, provider); + return E_NOT_IN_TRUSTS; +} + +bool DataSharePermission::VerifyPermission(uint32_t tokenID, std::string &permission) +{ + if (permission.empty() || permission == NO_PERMISSION) { + return true; + } + int status = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenID, permission); + if (status != Security::AccessToken::PermissionState::PERMISSION_GRANTED) { + return false; + } + return true; +} + +bool DataSharePermission::VerifyPermission(Uri &uri, uint32_t tokenID, std::string &permission, bool isExtension) +{ + if (permission == NO_PERMISSION) { + return true; + } + + std::string uriStr = uri.ToString(); + DataShareCalledConfig calledConfig(uriStr); + std::string providerName = calledConfig.BundleName(); + + auto [callingName, ret] = HiViewFaultAdapter::GetCallingName(tokenID); + if (ret != E_OK) { + LOG_WARN("GetCallingName failed, ret %{public}d", ret); + } + if (permission.empty() && isExtension) { + return true; + } + + if (permission.empty() && !isExtension) { + LOG_INFO("Permission empty! token: %{public}d", tokenID); + Security::AccessToken::HapTokenInfo tokenInfo; + auto result = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenID, tokenInfo); + if (result == Security::AccessToken::RET_SUCCESS && tokenInfo.bundleName == providerName) { + return true; + } + LOG_ERROR("Permission denied! uri %{public}s callingName %{public}s token %{public}d", + uri.ToString().c_str(), providerName.c_str(), tokenID); + return false; + } + + int status = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenID, permission); + if (status != Security::AccessToken::PermissionState::PERMISSION_GRANTED) { + return false; + } + return true; +} + +int32_t DataSharePermission::IsExtensionValid(uint32_t tokenId, uint32_t fullToken, int32_t user) +{ + Security::AccessToken::ATokenTypeEnum tokenType = + Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId); + if (tokenType != Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) { + return E_NOT_HAP; + } + if (Security::AccessToken::AccessTokenKit::IsSystemAppByFullTokenID(fullToken)) { + return E_OK; + } + auto [bundleName, ret] = HiViewFaultAdapter::GetCallingName(tokenId); + if (ret != 0) { + return ret; + } + + auto [success, bundleInfo] = DataShareCalledConfig::GetBundleInfoFromBMS(bundleName, user); + if (!success) { + LOG_ERROR("Get bundleInfo failed! bundleName:%{public}s, userId:%{public}d", + bundleName.c_str(), user); + return E_GET_BUNDLEINFO_FAILED; + } + for (auto &item : bundleInfo.extensionInfos) { + if (item.type == AppExecFwk::ExtensionAbilityType::DATASHARE) { + return E_OK; + } + } + return E_NOT_DATASHARE_EXTENSION; +} + } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/provider/include/datashare_ext_ability.h b/data_share/frameworks/native/provider/include/datashare_ext_ability.h index 46528426f6f2636384deb467dfa681385f14515e..9e69e2d1154f888fac87a0f9efc512367f9fba50 100644 --- a/data_share/frameworks/native/provider/include/datashare_ext_ability.h +++ b/data_share/frameworks/native/provider/include/datashare_ext_ability.h @@ -18,6 +18,7 @@ #include #include "extension_base.h" +#include "data_ability_observer_interface.h" #include "datashare_business_error.h" #include "datashare_values_bucket.h" #include "datashare_predicates.h" @@ -36,6 +37,7 @@ using namespace AbilityRuntime; class DataShareExtAbilityContext; class DataShareExtAbility; using CreatorFunc = std::function& runtime)>; +using ChangeInfo = AAFwk::ChangeInfo; /** * @brief Basic datashare extension ability components. */ @@ -223,6 +225,35 @@ public: */ virtual bool NotifyChange(const Uri &uri); + /** + * @brief Registers an observer to DataObsMgr specified by the given Uri. + * Return true, need override by users. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ + virtual bool RegisterObserverExtProvider(const Uri &uri, const sptr &dataObserver, + bool isDescendants); + + /** + * @brief Deregisters an observer used for DataObsMgr specified by the given Uri. + * Return true, need override by users. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ + virtual bool UnregisterObserverExtProvider(const Uri &uri, const sptr &dataObserver); + + /** + * @brief Notifies the registered observers of a change to the data resource specified by Uri. + * Return true, need override by users. + * + * @param uri, Indicates the path of the data to operate. + * + * @return Return true if success. otherwise return false. + */ + virtual bool NotifyChangeExtProvider(const ChangeInfo changeInfo); + /** * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if diff --git a/data_share/frameworks/native/provider/include/datashare_stub.h b/data_share/frameworks/native/provider/include/datashare_stub.h index 5e91786a0e306c26eb7180d45b122d064075fd9f..8137c924298b365bf688b122f1fa3ea2f271a906 100644 --- a/data_share/frameworks/native/provider/include/datashare_stub.h +++ b/data_share/frameworks/native/provider/include/datashare_stub.h @@ -34,6 +34,7 @@ public: private: ErrCode CmdGetFileTypes(MessageParcel &data, MessageParcel &reply); ErrCode CmdOpenFile(MessageParcel &data, MessageParcel &reply); + ErrCode CmdOpenFileWithErrCode(MessageParcel &data, MessageParcel &reply); ErrCode CmdOpenRawFile(MessageParcel &data, MessageParcel &reply); ErrCode CmdInsert(MessageParcel &data, MessageParcel &reply); ErrCode CmdUpdate(MessageParcel &data, MessageParcel &reply); @@ -53,6 +54,10 @@ private: ErrCode CmdUpdateEx(MessageParcel &data, MessageParcel &reply); ErrCode CmdDeleteEx(MessageParcel &data, MessageParcel &reply); ErrCode CmdUserDefineFunc(MessageParcel &data, MessageParcel &reply, MessageOption &option); + ErrCode CmdRegisterObserverExtProvider(MessageParcel &data, MessageParcel &reply); + ErrCode CmdUnregisterObserverExtProvider(MessageParcel &data, MessageParcel &reply); + ErrCode CmdNotifyChangeExtProvider(MessageParcel &data, MessageParcel &reply); + ErrCode OpenFileInner(MessageParcel &data, MessageParcel &reply, int &fd); virtual int ExecuteBatch(const std::vector &statements, ExecResultSet &result) override; virtual int InsertExt(const Uri &uri, const DataShareValuesBucket &value, std::string &result) override; @@ -63,6 +68,14 @@ private: virtual std::pair DeleteEx(const Uri &uri, const DataSharePredicates &predicates) override; virtual int32_t UserDefineFunc( MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + // default return true, need override by users + virtual int RegisterObserverExtProvider(const Uri &uri, const sptr &dataObserver, + bool isDescendants, RegisterOption option) override; + // default return true, need override by users + virtual int UnregisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver) override; + // default return true, need override by users + virtual int NotifyChangeExtProvider(const ChangeInfo &changeInfo) 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 42b4cc32e16c7ce2a04e0ca885ca4dabea89979d..c77b620cbf865606041dbf73285b41b065e5fcfd 100644 --- a/data_share/frameworks/native/provider/include/datashare_stub_impl.h +++ b/data_share/frameworks/native/provider/include/datashare_stub_impl.h @@ -74,6 +74,8 @@ public: std::pair DeleteEx(const Uri &uri, const DataSharePredicates &predicates) override; + static int32_t GetCallingUserId(); + private: std::shared_ptr GetOwner(); bool CheckCallingPermission(const std::string &permission); diff --git a/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h b/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h index 06582fe5bfedf3fe4fc745483a741485d6d09fc4..de803be4c20164fe3b925b71c3869bd0366dca61 100644 --- a/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h +++ b/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h @@ -270,6 +270,15 @@ public: */ bool NotifyChange(const Uri &uri) override; + /** + * @brief Notifies the registered observers of a change to the data resource specified by Uri. + * + * @param uri, Indicates the path of the data to operate. + * + * @return Return true if success. otherwise return false. + */ + bool NotifyChangeWithUser(const Uri &uri, int32_t userId); + /** * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if diff --git a/data_share/frameworks/native/provider/src/datashare_ext_ability.cpp b/data_share/frameworks/native/provider/src/datashare_ext_ability.cpp index 284d49bea388390778b194f1e628f96aad30ae83..c2e49011c7d81e524493fa8e5b0c13ee3aed53d9 100644 --- a/data_share/frameworks/native/provider/src/datashare_ext_ability.cpp +++ b/data_share/frameworks/native/provider/src/datashare_ext_ability.cpp @@ -49,7 +49,7 @@ DataShareExtAbility* DataShareExtAbility::Create(const std::unique_ptr& return JsDataShareExtAbility::Create(runtime); default: - return new DataShareExtAbility(); + return new (std::nothrow)DataShareExtAbility(); } } @@ -140,6 +140,23 @@ bool DataShareExtAbility::NotifyChange(const Uri &uri) return true; } +bool DataShareExtAbility::RegisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver, bool isDescendants) +{ + return true; +} + +bool DataShareExtAbility::UnregisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver) +{ + return true; +} + +bool DataShareExtAbility::NotifyChangeExtProvider(const ChangeInfo changeInfo) +{ + return true; +} + Uri DataShareExtAbility::NormalizeUri(const Uri &uri) { Uri urivalue(""); diff --git a/data_share/frameworks/native/provider/src/datashare_stub.cpp b/data_share/frameworks/native/provider/src/datashare_stub.cpp index 2f1466dcfe021f5f9fa5a67679fe54143fab25e8..be1b6dde8ac5c21ef715da4352c7e5e3d1e502ad 100644 --- a/data_share/frameworks/native/provider/src/datashare_stub.cpp +++ b/data_share/frameworks/native/provider/src/datashare_stub.cpp @@ -37,6 +37,8 @@ DataShareStub::DataShareStub() { stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_GET_FILE_TYPES)] = &DataShareStub::CmdGetFileTypes; stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_OPEN_FILE)] = &DataShareStub::CmdOpenFile; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_OPEN_FILE_WITH_ERR_CODE)] = + &DataShareStub::CmdOpenFileWithErrCode; stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_OPEN_RAW_FILE)] = &DataShareStub::CmdOpenRawFile; stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_INSERT)] = &DataShareStub::CmdInsert; stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_UPDATE)] = &DataShareStub::CmdUpdate; @@ -58,6 +60,12 @@ DataShareStub::DataShareStub() 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; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_REGISTER_OBSERVEREXT_PROVIDER)] = + &DataShareStub::CmdRegisterObserverExtProvider; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_UNREGISTER_OBSERVEREXT_PROVIDER)] = + &DataShareStub::CmdUnregisterObserverExtProvider; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_NOTIFY_CHANGEEXT_PROVIDER)] = + &DataShareStub::CmdNotifyChangeExtProvider; } DataShareStub::~DataShareStub() @@ -122,7 +130,7 @@ ErrCode DataShareStub::CmdGetFileTypes(MessageParcel &data, MessageParcel &reply return E_OK; } -ErrCode DataShareStub::CmdOpenFile(MessageParcel &data, MessageParcel &reply) +ErrCode DataShareStub::OpenFileInner(MessageParcel &data, MessageParcel &reply, int &fd) { Uri uri(""); std::string mode; @@ -134,7 +142,18 @@ ErrCode DataShareStub::CmdOpenFile(MessageParcel &data, MessageParcel &reply) LOG_ERROR("mode is nullptr"); return ERR_INVALID_VALUE; } - int fd = OpenFile(uri, mode); + fd = OpenFile(uri, mode); + return E_OK; +} + +ErrCode DataShareStub::CmdOpenFile(MessageParcel &data, MessageParcel &reply) +{ + int fd = -1; + int ret = OpenFileInner(data, reply, fd); + if (ret != E_OK) { + return ret; + } + if (fd < 0) { return ERR_INVALID_DATA; } @@ -147,6 +166,26 @@ ErrCode DataShareStub::CmdOpenFile(MessageParcel &data, MessageParcel &reply) return E_OK; } +ErrCode DataShareStub::CmdOpenFileWithErrCode(MessageParcel &data, MessageParcel &reply) +{ + int fd = -1; + int ret = OpenFileInner(data, reply, fd); + if (ret != E_OK) { + return ret; + } + + if (fd < 0) { + return fd; + } + if (!reply.WriteFileDescriptor(fd)) { + LOG_ERROR("fail to WriteFileDescriptor fd"); + close(fd); + return ERR_INVALID_VALUE; + } + close(fd); + return E_OK; +} + ErrCode DataShareStub::CmdOpenRawFile(MessageParcel &data, MessageParcel &reply) { Uri uri(""); @@ -219,9 +258,12 @@ ErrCode DataShareStub::CmdBatchUpdate(OHOS::MessageParcel &data, OHOS::MessagePa } std::vector results; int ret = BatchUpdate(updateOperations, results); - if (ret != E_OK) { + if (ret == DEFAULT_NUMBER) { LOG_ERROR("BatchUpdate inner error, ret is %{public}d.", ret); - return ret; + return ERR_INVALID_VALUE; + } else if (ret == PERMISSION_ERROR_NUMBER) { + LOG_ERROR("BatchUpdate permission error"); + return ERR_PERMISSION_DENIED; } if (!ITypesUtil::Marshal(reply, results)) { LOG_ERROR("marshalling updateOperations is failed"); @@ -460,6 +502,68 @@ ErrCode DataShareStub::CmdNotifyChange(MessageParcel &data, MessageParcel &reply return E_OK; } +ErrCode DataShareStub::CmdRegisterObserverExtProvider(MessageParcel &data, MessageParcel &reply) +{ + Uri uri(""); + sptr observer; + bool isDescendants = false; + RegisterOption option; + if (!ITypesUtil::Unmarshal(data, uri, observer, isDescendants, option)) { + LOG_ERROR("Unmarshalling uri and observer failed"); + return ERR_INVALID_VALUE; + } + auto obServer = iface_cast(observer); + if (obServer == nullptr) { + LOG_ERROR("obServer is nullptr"); + return ERR_INVALID_VALUE; + } + + int ret = RegisterObserverExtProvider(uri, obServer, isDescendants, option); + if (!reply.WriteInt32(ret)) { + LOG_ERROR("fail to WriteInt32 ret"); + return ERR_INVALID_VALUE; + } + return E_OK; +} + +ErrCode DataShareStub::CmdUnregisterObserverExtProvider(MessageParcel &data, MessageParcel &reply) +{ + Uri uri(""); + sptr observer; + if (!ITypesUtil::Unmarshal(data, uri, observer)) { + LOG_ERROR("Unmarshalling uri and observer failed"); + return ERR_INVALID_VALUE; + } + auto obServer = iface_cast(observer); + if (obServer == nullptr) { + LOG_ERROR("obServer is nullptr"); + return ERR_INVALID_VALUE; + } + + int ret = UnregisterObserverExtProvider(uri, obServer); + if (!reply.WriteInt32(ret)) { + LOG_ERROR("fail to WriteInt32 ret"); + return ERR_INVALID_VALUE; + } + return E_OK; +} + +ErrCode DataShareStub::CmdNotifyChangeExtProvider(MessageParcel &data, MessageParcel &reply) +{ + ChangeInfo changeInfo; + if (!ChangeInfo::Unmarshalling(changeInfo, data)) { + LOG_ERROR("Failed to unmarshall changeInfo."); + return ERR_INVALID_VALUE; + } + + int ret = NotifyChangeExtProvider(changeInfo); + if (!reply.WriteInt32(ret)) { + LOG_ERROR("fail to WriteInt32 ret"); + return ERR_INVALID_VALUE; + } + return E_OK; +} + ErrCode DataShareStub::CmdNormalizeUri(MessageParcel &data, MessageParcel &reply) { Uri uri(""); @@ -566,5 +670,20 @@ int32_t DataShareStub::UserDefineFunc( LOG_ERROR("UserDefineFunc excuted."); return 0; } + +int DataShareStub::RegisterObserverExtProvider(const Uri &uri, const sptr &dataObserver, + bool isDescendants, RegisterOption option) +{ + return 0; +} + +int DataShareStub::UnregisterObserverExtProvider(const Uri &uri, const sptr &dataObserver) +{ + return 0; +} +int DataShareStub::NotifyChangeExtProvider(const ChangeInfo &changeInfo) +{ + return 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 49dafcef4289d91b91384621b4dcc68d5d9c36e4..95d5b0fb8ee5a08d08f14682bd19efe8ab8afa2c 100644 --- a/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp +++ b/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp @@ -14,11 +14,17 @@ */ #include "datashare_stub_impl.h" -#include +#include #include "accesstoken_kit.h" +#include "bundle_constants.h" +#include "bundle_mgr_helper.h" +#include "dataobs_mgr_client.h" +#include "data_share_config.h" +#include "datashare_errno.h" #include "datashare_log.h" #include "datashare_string_utils.h" +#include "hiview_datashare.h" #include "ipc_skeleton.h" namespace OHOS { @@ -35,14 +41,30 @@ std::shared_ptr DataShareStubImpl::GetOwner() return extension_; } +int CheckTrusts(uint32_t consumerToken, uint32_t providerToken) +{ + auto obsMgrClient = AAFwk::DataObsMgrClient::GetInstance(); + if (obsMgrClient == nullptr) { + LOG_ERROR("obsMgrClient is nullptr"); + return E_DATA_OBS_NOT_READY; + } + ErrCode ret = obsMgrClient->CheckTrusts(consumerToken, providerToken); + if (ret != E_OK) { + LOG_ERROR("CheckTrusts error return %{public}d", ret); + return ret; + } + return E_OK; +} + bool DataShareStubImpl::CheckCallingPermission(const std::string &permission) { - if (!permission.empty() && AccessTokenKit::VerifyAccessToken(IPCSkeleton::GetCallingTokenID(), permission) - != AppExecFwk::Constants::PERMISSION_GRANTED) { - LOG_ERROR("permission not granted."); - return false; + uint32_t token = IPCSkeleton::GetCallingTokenID(); + if (permission.empty() || AccessTokenKit::VerifyAccessToken(token, permission) + == AppExecFwk::Constants::PERMISSION_GRANTED) { + return true; } - return true; + LOG_WARN("permission not granted. permission %{public}s, token %{public}d", permission.c_str(), token); + return false; } std::vector DataShareStubImpl::GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) @@ -210,24 +232,25 @@ int DataShareStubImpl::BatchUpdate(const UpdateOperations &operations, std::vect return PERMISSION_ERROR_NUMBER; } auto result = std::make_shared(); - std::shared_ptr ret = std::make_shared(0); - std::function syncTaskFunc = [extension, ret, operations, info, result]() { + int ret = 0; + std::function syncTaskFunc = [extension, operations, info, result]() { extension->SetCallingInfo(info); extension->InitResult(result); std::vector tmp; - *ret = extension->BatchUpdate(operations, tmp); + extension->BatchUpdate(operations, tmp); }; - std::function getRetFunc = [&results, result]() -> bool { + std::function getRetFunc = [&results, result, &ret]() -> bool { if (result == nullptr) { return false; } bool isRecvReply = result->GetRecvReply(); result->GetResult(results); + result->GetResult(ret); return isRecvReply; }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); - return *ret; + return ret; } int DataShareStubImpl::Delete(const Uri &uri, const DataSharePredicates &predicates) @@ -480,16 +503,34 @@ int DataShareStubImpl::BatchInsert(const Uri &uri, const std::vector &dataObserver) { auto extension = GetOwner(); if (extension == nullptr) { return false; } - if (!CheckCallingPermission(extension->abilityInfo_->readPermission)) { - LOG_ERROR("Register observer check permission failed. uri: %{public}s", - DataShareStringUtils::Anonymous(uri.ToString()).c_str()); - return false; + int32_t callingToken = IPCSkeleton::GetCallingTokenID(); + bool isSuccess = CheckCallingPermission(extension->abilityInfo_->readPermission); + if (!isSuccess) { + int selfToken = IPCSkeleton::GetSelfTokenID(); + if (CheckTrusts(callingToken, selfToken) != E_OK) { + LOG_ERROR("Register observer check permission failed. uri: %{public}s, token:%{public}d", + DataShareStringUtils::Anonymous(uri.ToString()).c_str(), callingToken); + // just log + } } return extension->RegisterObserver(uri, dataObserver); } @@ -500,11 +541,17 @@ bool DataShareStubImpl::UnregisterObserver(const Uri &uri, const sptrabilityInfo_->readPermission)) { - LOG_ERROR("UnRegister observer check permission failed. uri: %{public}s", - DataShareStringUtils::Anonymous(uri.ToString()).c_str()); - return false; + int32_t callingToken = IPCSkeleton::GetCallingTokenID(); + bool isSuccess = CheckCallingPermission(extension->abilityInfo_->readPermission); + if (!isSuccess) { + int selfToken = IPCSkeleton::GetSelfTokenID(); + if (CheckTrusts(callingToken, selfToken) != E_OK) { + LOG_ERROR("UnRegister observer check permission failed. uri: %{public}s, token:%{public}d", + DataShareStringUtils::Anonymous(uri.ToString()).c_str(), callingToken); + // just log + } } + return extension->UnregisterObserver(uri, dataObserver); } @@ -516,9 +563,20 @@ bool DataShareStubImpl::NotifyChange(const Uri &uri) if (extension == nullptr) { return *ret; } + int32_t callingToken = IPCSkeleton::GetCallingTokenID(); + bool isSuccess = CheckCallingPermission(extension->abilityInfo_->writePermission); + if (!isSuccess) { + int selfToken = IPCSkeleton::GetSelfTokenID(); + if (CheckTrusts(callingToken, selfToken) != E_OK) { + LOG_ERROR("extension NotifyChange check permission failed. uri: %{public}s token %{public}d", + uri.ToString().c_str(), IPCSkeleton::GetCallingTokenID()); + // just log + } + } - std::function syncTaskFunc = [extension, ret, uri]() { - *ret = extension->NotifyChange(uri); + int32_t callingUserId = GetCallingUserId(); + std::function syncTaskFunc = [extension, ret, uri, callingUserId]() { + *ret = extension->NotifyChangeWithUser(uri, callingUserId); }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc); diff --git a/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp b/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp index 638125c3a5a232a5094471867a82d13b06e6f711..788fc19506ce296b455e9a3943a64ace7f1aba7b 100644 --- a/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp +++ b/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp @@ -52,7 +52,11 @@ void DataShareUvQueue::LambdaForWork(TaskEntry* taskEntry) void DataShareUvQueue::SyncCall(NapiVoidFunc func, NapiBoolFunc retFunc) { - auto *taskEntry = new TaskEntry {env_, std::move(func), false, {}, {}, std::atomic(1)}; + auto *taskEntry = new (std::nothrow)TaskEntry {env_, std::move(func), false, {}, {}, std::atomic(1)}; + if (taskEntry == nullptr) { + LOG_ERROR("invalid taskEntry."); + return; + } { std::unique_lock lock(taskEntry->mutex); taskEntry->count.fetch_add(1); @@ -69,7 +73,7 @@ void DataShareUvQueue::SyncCall(NapiVoidFunc func, NapiBoolFunc retFunc) [taskEntry] { return taskEntry->done; })) { auto time = static_cast(duration_cast( system_clock::now().time_since_epoch()).count()); - LOG_INFO("function ended successfully. times %{public}" PRIu64 ".", time); + LOG_WARN("function ended successfully. times %{public}" PRIu64 ".", time); } } CheckFuncAndExec(retFunc); diff --git a/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp b/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp index 9260f69e3174f6b7a35888963e2bbc9f038b71de..a3691030b5a54b1fced8a5b1ded20f70bacb2c4f 100644 --- a/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp +++ b/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp @@ -23,6 +23,7 @@ #include "datashare_stub_impl.h" #include "ikvstore_data_service.h" #include "idata_share_service.h" +#include "ipc_skeleton.h" #include "iservice_registry.h" #include "js_datashare_ext_ability_context.h" #include "js_proxy.h" @@ -64,6 +65,7 @@ void JsResult::SetAsyncResult(napi_env env, DatashareBusinessError &businessErro napi_unwrap(env, result, reinterpret_cast(&proxy)); if (proxy == nullptr) { if (UnwrapBatchUpdateResult(env, result, updateResults_)) { + callbackResultNumber_ = E_OK; isRecvReply_ = true; return; } @@ -120,7 +122,7 @@ using DataObsMgrClient = OHOS::AAFwk::DataObsMgrClient; JsDataShareExtAbility* JsDataShareExtAbility::Create(const std::unique_ptr& runtime) { - return new JsDataShareExtAbility(static_cast(*runtime)); + return new (std::nothrow)JsDataShareExtAbility(static_cast(*runtime)); } JsDataShareExtAbility::JsDataShareExtAbility(JsRuntime& jsRuntime) : jsRuntime_(jsRuntime) {} @@ -175,11 +177,15 @@ void JsDataShareExtAbility::Init(const std::shared_ptr &reco contextObj = contextRef->GetNapiValue(); context->Bind(jsRuntime_, contextRef.release()); napi_set_named_property(env, obj, "context", contextObj); - napi_wrap(env, contextObj, new std::weak_ptr(context), + napi_status status = napi_wrap(env, contextObj, new (std::nothrow)std::weak_ptr(context), [](napi_env, void *data, void *) { LOG_INFO("Finalizer for weak_ptr datashare extension ability context is called"); delete static_cast*>(data); }, nullptr, nullptr); + if (status != napi_ok) { + LOG_ERROR("napi_wrap failed. code:%{public}d", status); + return; + } } void JsDataShareExtAbility::OnStart(const AAFwk::Want &want) @@ -315,13 +321,17 @@ napi_value JsDataShareExtAbility::CallObjectMethod( args[i] = argv[i]; } - napi_create_function(env, ASYNC_CALLBACK_NAME, CALLBACK_LENGTH, - JsDataShareExtAbility::AsyncCallbackWithContext, point, &args[argc]); + if (napi_create_function(env, ASYNC_CALLBACK_NAME, CALLBACK_LENGTH, + JsDataShareExtAbility::AsyncCallbackWithContext, point, &args[argc]) != napi_ok) { + LOG_ERROR("napi_create_function error."); + delete point; + delete []args; + return nullptr; + } napi_value callResult = nullptr; napi_call_function(env, obj, method, count, args, &callResult); auto result = handleEscape.Escape(callResult); - napi_add_finalizer(env, args[argc], point, - [](napi_env env, void* point, void* finalize_hint) { + napi_add_finalizer(env, args[argc], point, [](napi_env env, void* point, void* finalize_hint) { delete static_cast(point); }, nullptr, nullptr); delete []args; @@ -414,8 +424,13 @@ int32_t JsDataShareExtAbility::InitAsyncCallParams(size_t argc, napi_env &env, n } point->result = std::move(result_); - napi_create_function(env, ASYNC_CALLBACK_NAME, CALLBACK_LENGTH, + napi_status status = napi_create_function(env, ASYNC_CALLBACK_NAME, CALLBACK_LENGTH, JsDataShareExtAbility::AsyncCallback, point, &args[argc]); + if (status != napi_ok) { + LOG_ERROR("napi_create_function error: %{public}d.", status); + delete point; + return E_ERROR; + } napi_add_finalizer(env, args[argc], point, [](napi_env env, void* point, void* finalize_hint) { delete static_cast(point); @@ -808,7 +823,12 @@ bool JsDataShareExtAbility::RegisterObserver(const Uri &uri, const sptrRegisterObserver(uri, dataObserver); + int32_t callingUserId = DataShareStubImpl::GetCallingUserId(); + uint32_t token = IPCSkeleton::GetCallingTokenID(); + DataObsOption opt; + opt.SetFirstCallerTokenID(token); + Uri innerUri = uri; + ErrCode ret = obsMgrClient->RegisterObserverFromExtension(innerUri, dataObserver, callingUserId); if (ret != ERR_OK) { LOG_ERROR("obsMgrClient->RegisterObserver error return %{public}d", ret); return false; @@ -825,7 +845,8 @@ bool JsDataShareExtAbility::UnregisterObserver(const Uri &uri, const sptrUnregisterObserver(uri, dataObserver); + int32_t callingUserId = DataShareStubImpl::GetCallingUserId(); + ErrCode ret = obsMgrClient->UnregisterObserver(uri, dataObserver, callingUserId); if (ret != ERR_OK) { LOG_ERROR("obsMgrClient->UnregisterObserver error return %{public}d", ret); return false; @@ -850,6 +871,22 @@ bool JsDataShareExtAbility::NotifyChange(const Uri &uri) return true; } +bool JsDataShareExtAbility::NotifyChangeWithUser(const Uri &uri, int32_t userId) +{ + auto obsMgrClient = DataObsMgrClient::GetInstance(); + if (obsMgrClient == nullptr) { + LOG_ERROR("obsMgrClient is nullptr"); + return false; + } + Uri innerUri = uri; + ErrCode ret = obsMgrClient->NotifyChangeFromExtension(innerUri, userId); + if (ret != ERR_OK) { + LOG_ERROR("obsMgrClient->NotifyChange error return %{public}d", ret); + return false; + } + return true; +} + Uri JsDataShareExtAbility::NormalizeUri(const Uri &uri) { auto ret = DataShareExtAbility::NormalizeUri(uri); diff --git a/data_share/frameworks/native/provider/src/js_datashare_ext_ability_context.cpp b/data_share/frameworks/native/provider/src/js_datashare_ext_ability_context.cpp index 0aa892b01eae84513769fa4cd695385b672dea56..7073d5a9a3112ae33c40285a1cb893f062322c64 100644 --- a/data_share/frameworks/native/provider/src/js_datashare_ext_ability_context.cpp +++ b/data_share/frameworks/native/provider/src/js_datashare_ext_ability_context.cpp @@ -53,7 +53,13 @@ napi_value CreateJsDataShareExtAbilityContext(napi_env env, LOG_DEBUG("CreateJsDataShareExtAbilityContext begin"); napi_value objValue = CreateJsExtensionContext(env, context); std::unique_ptr jsContext = std::make_unique(context); - napi_wrap(env, objValue, jsContext.release(), JsDataShareExtAbilityContext::Finalizer, nullptr, nullptr); + napi_status status = napi_wrap(env, objValue, jsContext.release(), JsDataShareExtAbilityContext::Finalizer, + nullptr, nullptr); + if (status != napi_ok) { + LOG_ERROR("napi_wrap failed. code:%{public}d", status); + jsContext.release(); + return nullptr; + } return objValue; } } // namespace DataShare diff --git a/data_share/frameworks/native/proxy/include/data_proxy_observer.h b/data_share/frameworks/native/proxy/include/data_proxy_observer.h index 8de56535c43a2ad35afb390de323baaae4ea644b..1b7477f1e8eb9388b6e869a2cf6503e138a02612 100644 --- a/data_share/frameworks/native/proxy/include/data_proxy_observer.h +++ b/data_share/frameworks/native/proxy/include/data_proxy_observer.h @@ -29,6 +29,11 @@ class IDataProxyPublishedDataObserver : public OHOS::IRemoteBroker { public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DataShare.IDataProxyPublishedDataObserver"); }; + +class IProxyDataObserver : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DataShare.IProxyDataObserver"); +}; } // namespace DataShare } // namespace OHOS #endif // DATA_PROXY_OBSERVER_H diff --git a/data_share/frameworks/native/proxy/include/data_proxy_observer_stub.h b/data_share/frameworks/native/proxy/include/data_proxy_observer_stub.h index 9de980ae21a25d1abcdce3f26882f851325a5dec..63f1890e131dad0f1dbea20b47a3fc08bc5bc79e 100644 --- a/data_share/frameworks/native/proxy/include/data_proxy_observer_stub.h +++ b/data_share/frameworks/native/proxy/include/data_proxy_observer_stub.h @@ -17,6 +17,7 @@ #define DATA_PROXY_OBSERVER_STUB_H #include "data_proxy_observer.h" +#include "dataproxy_handle_common.h" #include "datashare_template.h" #include "iremote_stub.h" @@ -50,6 +51,19 @@ private: std::mutex mutex_; PublishedDataCallback callback_; }; + +using ProxyDataCallback = std::function &changeInfo)>; +class ProxyDataObserverStub : public IRemoteStub { +public: + virtual ~ProxyDataObserverStub(); + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + explicit ProxyDataObserverStub(ProxyDataCallback callback) : callback_(callback){}; + void OnChangeFromProxyData(std::vector &changeInfo); + void ClearCallback(); +private: + std::mutex mutex_; + ProxyDataCallback callback_; +}; } // namespace DataShare } // namespace OHOS #endif //DATA_PROXY_OBSERVER_STUB_H 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 8ff96ca25dd5ebc997e7168e915f41f476127c10..a4ad397abdac481e14d64ff78ebafc1cbac7de0a 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 @@ -90,7 +90,7 @@ public: void OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId); - void SetCallCount(const std::string &funcName, const std::string &uri); + bool SetCallCount(const std::string &funcName, const std::string &uri); private: DataShareManagerImpl(); 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 75f1d3d11679d0442f749752a21a978b5afd5759..b010a5c243ea56aa1be4f6b408c014d827d9c624 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 @@ -23,7 +23,7 @@ #include "idata_share_service.h" namespace OHOS::DataShare { -class DataShareServiceProxy final : public IRemoteProxy { +class DataShareServiceProxy : public IRemoteProxy { public: explicit DataShareServiceProxy(const sptr &object); int Insert(const Uri &uri, const Uri &extUri, const DataShareValuesBucket &valuesBucket) override; @@ -90,6 +90,20 @@ public: static void SetSystem(bool isSystem); + std::vector PublishProxyData( + const std::vector &proxyData, const DataProxyConfig &proxyConfig) override; + + std::vector DeleteProxyData( + const std::vector &uris, const DataProxyConfig &proxyConfig) override; + + std::vector GetProxyData( + const std::vector uris, const DataProxyConfig &proxyConfig) override; + + std::vector SubscribeProxyData(const std::vector &uris, + const sptr &observer) override; + + std::vector UnsubscribeProxyData(const std::vector &uris) override; + static bool IsSystem(); static bool& GetSystem(); diff --git a/data_share/frameworks/native/proxy/include/proxy_data_subscriber_manager.h b/data_share/frameworks/native/proxy/include/proxy_data_subscriber_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..6a5d7fde36a66d4780c39869ff8d84915c8fb2f7 --- /dev/null +++ b/data_share/frameworks/native/proxy/include/proxy_data_subscriber_manager.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023 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 PROXY_DATA_SUBSCRIBER_MANAGER_H +#define PROXY_DATA_SUBSCRIBER_MANAGER_H +#include + +#include "callbacks_manager.h" +#include "concurrent_map.h" +#include "data_proxy_observer.h" +#include "data_proxy_observer_stub.h" +#include "dataproxy_handle.h" +#include "dataproxy_handle_common.h" +#include "idatashare.h" +#include "iremote_stub.h" +#include "data_share_service_proxy.h" + +namespace OHOS { +namespace DataShare { +struct ProxyDataObserverMapKey { + std::string uri_; + ProxyDataObserverMapKey(const std::string &uri) : uri_(uri) {}; + bool operator==(const ProxyDataObserverMapKey &node) const + { + return uri_ == node.uri_; + } + bool operator!=(const ProxyDataObserverMapKey &node) const + { + return !(node == *this); + } + bool operator<(const ProxyDataObserverMapKey &node) const + { + return uri_ < node.uri_; + } + operator std::string() const + { + return uri_; + } +}; + +class ProxyDataObserver { +public: + explicit ProxyDataObserver(const ProxyDataCallback &callback); + void OnChange(std::vector &changeNode); + bool operator==(const ProxyDataObserver &rhs) const; + bool operator!=(const ProxyDataObserver &rhs) const; + +private: + ProxyDataCallback callback_; +}; + +class ProxyDataSubscriberManager : public CallbacksManager { +public: + using Key = ProxyDataObserverMapKey; + using Observer = ProxyDataObserver; + using BaseCallbacks = CallbacksManager; + static ProxyDataSubscriberManager &GetInstance(); + + std::vector AddObservers(void *subscriber, std::shared_ptr proxy, + const std::vector &uris, const ProxyDataCallback &callback); + std::vector DelObservers(void *subscriber, std::shared_ptr proxy, + const std::vector &uris); + std::vector DelObservers(void *subscriber, std::shared_ptr proxy); + + void RecoverObservers(std::shared_ptr proxy); + void Emit(std::vector &changeInfo); + +private: + void Emit(const std::vector &keys, const std::shared_ptr &observer); + ProxyDataSubscriberManager(); + std::map> callbacks_; + sptr serviceCallback_; + std::recursive_mutex mutex_{}; +}; +} // namespace DataShare +} // namespace OHOS +#endif //PROXY_DATA_SUBSCRIBER_MANAGER_H 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 35af165325061b5b44690424ba6f6656de90881d..25bc0e04c05a8f19c27a931ad3d58fbfc0bf89d9 100644 --- a/data_share/frameworks/native/proxy/src/ams_mgr_proxy.cpp +++ b/data_share/frameworks/native/proxy/src/ams_mgr_proxy.cpp @@ -52,7 +52,7 @@ AmsMgrProxy* AmsMgrProxy::GetInstance() if (proxy != nullptr) { return proxy; } - proxy = new AmsMgrProxy(); + proxy = new (std::nothrow)AmsMgrProxy(); if (proxy == nullptr) { LOG_ERROR("new proxy failed"); } diff --git a/data_share/frameworks/native/proxy/src/data_proxy_observer_stub.cpp b/data_share/frameworks/native/proxy/src/data_proxy_observer_stub.cpp index d2d1981bddcf744b120dad1ac0b026f5ce4bed92..f970e4a6a8a2a10a4bba87b9953d0f7a0d0d9f52 100644 --- a/data_share/frameworks/native/proxy/src/data_proxy_observer_stub.cpp +++ b/data_share/frameworks/native/proxy/src/data_proxy_observer_stub.cpp @@ -15,11 +15,13 @@ #include "data_proxy_observer_stub.h" +#include "dataproxy_handle_common.h" #include "datashare_itypes_utils.h" #include "datashare_log.h" namespace OHOS { namespace DataShare { +static constexpr int MAX_VEC_SIZE = 1024; static constexpr int REQUEST_CODE = 0; int RdbObserverStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { @@ -84,7 +86,10 @@ int RdbObserverStub::DeserializeDataFromAshmem(RdbChangeNode &changeNode) return E_ERROR; } int vecLen = *vecLenRead; - + if (vecLen > MAX_VEC_SIZE || vecLen < 0) { + LOG_ERROR("vecLen is invalid: %{public}d", vecLen); + return E_ERROR; + } // Read data for (int i = 0; i < vecLen; i++) { const int *dataLenRead; @@ -193,5 +198,46 @@ PublishedDataObserverStub::~PublishedDataObserverStub() { ClearCallback(); } + +int ProxyDataObserverStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, + MessageOption &option) +{ + std::u16string descriptor = PublishedDataObserverStub::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (descriptor != remoteDescriptor) { + LOG_ERROR("local descriptor is not equal to remote"); + return ERR_INVALID_STATE; + } + if (code != REQUEST_CODE) { + LOG_ERROR("not support code:%u", code); + return ERR_INVALID_STATE; + } + std::vector changeInfo; + if (!ITypesUtil::Unmarshal(data, changeInfo)) { + LOG_ERROR("Unmarshalling is nullptr"); + return ERR_INVALID_VALUE; + } + OnChangeFromProxyData(changeInfo); + return ERR_OK; +} + +void ProxyDataObserverStub::OnChangeFromProxyData(std::vector &changeInfo) +{ + std::lock_guard lock(mutex_); + if (callback_) { + callback_(changeInfo); + } +} + +void ProxyDataObserverStub::ClearCallback() +{ + std::lock_guard lock(mutex_); + callback_ = nullptr; +} + +ProxyDataObserverStub::~ProxyDataObserverStub() +{ + ClearCallback(); +} } // namespace DataShare } // namespace OHOS 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 1cb704af6532ebf4fc21916909b64df38699d64f..802a4606642011a9893abbb03bc9d27af841ca77 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 @@ -24,6 +24,7 @@ #include "iservice_registry.h" #include "system_ability_definition.h" #include "rdb_subscriber_manager.h" +#include "proxy_data_subscriber_manager.h" #include "published_data_subscriber_manager.h" namespace OHOS { @@ -38,7 +39,7 @@ DataShareManagerImpl* DataShareManagerImpl::GetInstance() if (manager_ != nullptr) { return manager_; } - manager_ = new DataShareManagerImpl(); + manager_ = new (std::nothrow)DataShareManagerImpl(); if (manager_ == nullptr) { LOG_ERROR("DataShareManagerImpl: GetInstance failed"); } @@ -47,7 +48,7 @@ DataShareManagerImpl* DataShareManagerImpl::GetInstance() LOG_ERROR("Failed to get saMgrProxy."); return manager_; } - sptr callback(new DataShareClientStatusChangeStub(manager_)); + sptr callback(new (std::nothrow)DataShareClientStatusChangeStub(manager_)); saManager->SubscribeSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID, callback); return manager_; } @@ -130,6 +131,7 @@ DataShareManagerImpl::DataShareManagerImpl() LOG_INFO("RecoverObs start"); RdbSubscriberManager::GetInstance().RecoverObservers(proxy); PublishedDataSubscriberManager::GetInstance().RecoverObservers(proxy); + ProxyDataSubscriberManager::GetInstance().RecoverObservers(proxy); }); } @@ -219,9 +221,9 @@ void DataShareManagerImpl::OnAddSystemAbility(int32_t systemAbilityId, const std } } -void DataShareManagerImpl::SetCallCount(const std::string &funcName, const std::string &uri) +bool DataShareManagerImpl::SetCallCount(const std::string &funcName, const std::string &uri) { - dataShareCallReporter_.Count(funcName, uri); + return 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 ff0a2859e609cc7314e9f4feaa12b4f5c9e5684c..086e73b967e279d4e7b8def0e24c451b271bb0da 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 @@ -17,6 +17,7 @@ #include #include "data_ability_observer_interface.h" +#include "dataproxy_handle_common.h" #include "datashare_errno.h" #include "datashare_itypes_utils.h" #include "datashare_log.h" @@ -201,11 +202,13 @@ std::shared_ptr DataShareServiceProxy::Query(const Uri &uri, MessageParcel data; if (!data.WriteInterfaceToken(IDataShareService::GetDescriptor())) { LOG_ERROR("WriteInterfaceToken failed!"); + businessError.SetCode(E_WRITE_TO_PARCE_ERROR); return nullptr; } if (!ITypesUtil::Marshal(data, uriStr, extUri.ToString(), predicates, columns)) { LOG_ERROR("Write to message parcel failed!"); + businessError.SetCode(E_MARSHAL_ERROR); return nullptr; } @@ -215,12 +218,13 @@ std::shared_ptr DataShareServiceProxy::Query(const Uri &uri, CastIPCCode(InterfaceCode::DATA_SHARE_SERVICE_CMD_QUERY), data, reply, option); auto result = ISharedResultSet::ReadFromParcel(reply); - businessError.SetCode(reply.ReadInt32()); if (err != NO_ERROR) { LOG_ERROR("Query fail to sendRequest. uri: %{public}s, err: %{public}d", DataShareStringUtils::Anonymous(uriStr).c_str(), err); + businessError.SetCode(err); return nullptr; } + businessError.SetCode(reply.ReadInt32()); return result; } @@ -691,5 +695,147 @@ int DataShareServiceProxy::UnRegisterObserver(const Uri &uri, const sptr DataShareServiceProxy::PublishProxyData( + const std::vector &proxyDatas, const DataProxyConfig &proxyConfig) +{ + std::vector results; + MessageParcel parcel; + if (!parcel.WriteInterfaceToken(IDataShareService::GetDescriptor())) { + LOG_ERROR("Write descriptor failed!"); + return results; + } + if (!ITypesUtil::Marshal(parcel, proxyDatas, proxyConfig)) { + LOG_ERROR("Marshal failed!"); + return results; + } + + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_PROXY_PUBLISH), parcel, reply, option); + if (err != NO_ERROR) { + LOG_ERROR("PublishProxyData fail to sendRequest. err: %{public}d", err); + return results; + } + + ITypesUtil::Unmarshal(reply, results); + return results; +} + +std::vector DataShareServiceProxy::DeleteProxyData( + const std::vector &uris, const DataProxyConfig &proxyConfig) +{ + std::vector results; + MessageParcel parcel; + if (!parcel.WriteInterfaceToken(IDataShareService::GetDescriptor())) { + LOG_ERROR("Write descriptor failed!"); + return results; + } + if (!ITypesUtil::Marshal(parcel, uris, proxyConfig)) { + LOG_ERROR("Marshal failed!"); + return results; + } + + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_PROXY_DELETE), parcel, reply, option); + if (err != NO_ERROR) { + LOG_ERROR("DeleteProxyData fail to sendRequest. err: %{public}d", err); + return results; + } + + ITypesUtil::Unmarshal(reply, results); + return results; +} + +std::vector DataShareServiceProxy::GetProxyData(const std::vector uris, + const DataProxyConfig &proxyConfig) +{ + std::vector results; + MessageParcel parcel; + if (!parcel.WriteInterfaceToken(IDataShareService::GetDescriptor())) { + LOG_ERROR("Write descriptor failed!"); + return results; + } + if (!ITypesUtil::Marshal(parcel, uris, proxyConfig)) { + LOG_ERROR("Marshal failed!"); + return results; + } + + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_PROXY_GET), parcel, reply, option); + if (err != NO_ERROR) { + LOG_ERROR("GetProxyData fail to sendRequest. err: %{public}d", err); + return results; + } + + ITypesUtil::Unmarshal(reply, results); + return results; +} + +std::vector DataShareServiceProxy::SubscribeProxyData(const std::vector &uris, + const sptr &observer) +{ + std::vector results; + if (observer == nullptr) { + LOG_ERROR("Observer is nullptr"); + return results; + } + MessageParcel data; + if (!data.WriteInterfaceToken(IDataShareService::GetDescriptor())) { + LOG_ERROR("Write descriptor failed!"); + return results; + } + + if (!ITypesUtil::Marshal(data, uris)) { + LOG_ERROR("Write to message parcel failed!"); + return results; + } + if (!data.WriteRemoteObject(observer->AsObject())) { + LOG_ERROR("Failed to write parcelable dataObserver "); + return results; + } + + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_SUBSCRIBE_PROXY_DATA), data, reply, option); + if (err != NO_ERROR) { + LOG_ERROR("SubscribeRdbData fail to sendRequest. err: %{public}d", err); + return results; + } + ITypesUtil::Unmarshal(reply, results); + return results; +} + +std::vector DataShareServiceProxy::UnsubscribeProxyData(const std::vector &uris) +{ + std::vector results; + MessageParcel data; + if (!data.WriteInterfaceToken(IDataShareService::GetDescriptor())) { + LOG_ERROR("Write descriptor failed!"); + return results; + } + + if (!ITypesUtil::Marshal(data, uris)) { + LOG_ERROR("Write to message parcel failed!"); + return results; + } + + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_UNSUBSCRIBE_PROXY_DATA), data, reply, option); + if (err != NO_ERROR) { + LOG_ERROR("Fail to sendRequest. err: %{public}d", err); + return results; + } + ITypesUtil::Unmarshal(reply, results); + return results; +} } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/proxy/src/proxy_data_subscriber_manager.cpp b/data_share/frameworks/native/proxy/src/proxy_data_subscriber_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b10bb457b08a246ecf65a6fe7e635763d3b64418 --- /dev/null +++ b/data_share/frameworks/native/proxy/src/proxy_data_subscriber_manager.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2023 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 "proxy_data_subscriber_manager.h" + +#include + +#include "data_proxy_observer_stub.h" +#include "dataproxy_handle_common.h" +#include "datashare_log.h" +#include "datashare_string_utils.h" + +namespace OHOS { +namespace DataShare { +std::vector ProxyDataSubscriberManager::AddObservers(void *subscriber, + std::shared_ptr proxy, const std::vector &uris, + const ProxyDataCallback &callback) +{ + std::vector result = {}; + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return result; + } + std::vector keys; + std::for_each(uris.begin(), uris.end(), [&keys](auto &uri) { + keys.emplace_back(uri); + }); + return BaseCallbacks::AddObservers( + keys, subscriber, std::make_shared(callback), + [&proxy, subscriber, this](const std::vector &firstAddKeys, + const std::shared_ptr observer, std::vector &opResult) { + std::vector firstAddUris; + std::for_each(firstAddKeys.begin(), firstAddKeys.end(), [&firstAddUris](auto &result) { + firstAddUris.emplace_back(result); + }); + if (firstAddUris.empty()) { + return; + } + + auto subResults = proxy->SubscribeProxyData(firstAddUris, serviceCallback_); + std::vector failedKeys; + for (auto &subResult : subResults) { + opResult.emplace_back(subResult); + if (subResult.result_ != SUCCESS) { + failedKeys.emplace_back(subResult.uri_); + LOG_WARN("registered failed, uri is %{public}s, errCode", + DataShareStringUtils::Anonymous(subResult.uri_).c_str()); + } + } + + if (failedKeys.size() > 0) { + BaseCallbacks::DelProxyDataObservers(failedKeys, subscriber); + } + }); +} + +std::vector ProxyDataSubscriberManager::DelObservers(void *subscriber, + std::shared_ptr proxy) +{ + std::vector result = {}; + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return result; + } + return BaseCallbacks::DelObservers(subscriber, + [&proxy, this](const std::vector &lastDelKeys, std::vector &opResult) { + // delete all obs by subscriber + std::vector uris; + std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [&uris](const Key &key) { + uris.emplace_back(key.uri_); + }); + auto results = proxy->UnsubscribeProxyData(uris); + opResult.insert(opResult.end(), results.begin(), results.end()); + }); +} + +std::vector ProxyDataSubscriberManager::DelObservers(void *subscriber, + std::shared_ptr proxy, const std::vector &uris) +{ + std::vector result = {}; + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return result; + } + if (uris.empty()) { + return DelObservers(subscriber, proxy); + } + + std::vector keys; + std::for_each(uris.begin(), uris.end(), [&keys](auto &uri) { + keys.emplace_back(uri); + }); + return BaseCallbacks::DelProxyDataObservers(keys, subscriber, + [&proxy, this](const std::vector &lastDelKeys, std::vector &opResult) { + std::vector lastDelUris; + std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [&lastDelUris, this](auto &result) { + lastDelUris.emplace_back(result); + }); + if (lastDelUris.empty()) { + return; + } + auto unsubResult = proxy->UnsubscribeProxyData(lastDelUris); + opResult.insert(opResult.end(), unsubResult.begin(), unsubResult.end()); + }); +} + +void ProxyDataSubscriberManager::RecoverObservers(std::shared_ptr proxy) +{ + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return; + } + + std::vector uris; + std::vector keys = CallbacksManager::GetKeys(); + for (const auto& key : keys) { + uris.emplace_back(key.uri_); + } + auto results = proxy->SubscribeProxyData(uris, serviceCallback_); + for (const auto& result : results) { + if (result.result_ != SUCCESS) { + LOG_WARN("RecoverObservers failed, uri is %{public}s, errCode is %{public}d", + DataShareStringUtils::Anonymous(result.uri_).c_str(), result.result_); + } + } +} + +void ProxyDataSubscriberManager::Emit(std::vector &changeInfo) +{ + std::map, std::vector> results; + for (auto &data : changeInfo) { + ProxyDataObserverMapKey key(data.uri_); + auto callbacks = BaseCallbacks::GetEnabledObservers(key); + for (auto const &obs : callbacks) { + results[obs].emplace_back(data.changeType_, data.uri_, data.value_); + } + } + for (auto &[callback, node] : results) { + callback->OnChange(node); + } +} + +ProxyDataSubscriberManager &ProxyDataSubscriberManager::GetInstance() +{ + static ProxyDataSubscriberManager manager; + return manager; +} + +ProxyDataSubscriberManager::ProxyDataSubscriberManager() +{ + serviceCallback_ = new ProxyDataObserverStub([this](std::vector &changeInfo) { + Emit(changeInfo); + }); +} + +ProxyDataObserver::ProxyDataObserver(const ProxyDataCallback &callback) : callback_(callback) {} + +void ProxyDataObserver::OnChange(std::vector &changeInfo) +{ + callback_(changeInfo); +} + +bool ProxyDataObserver::operator==(const ProxyDataObserver &rhs) const +{ + return false; +} + +bool ProxyDataObserver::operator!=(const ProxyDataObserver &rhs) const +{ + return !(rhs == *this); +} +} // namespace DataShare +} // namespace OHOS diff --git a/data_share/frameworks/native/proxy/src/published_data_subscriber_manager.cpp b/data_share/frameworks/native/proxy/src/published_data_subscriber_manager.cpp index 9ecc186693f65f1aee8ac193ba4365eade32a672..08e7f812912113e7cc389fd41573dfdbc0c1d0b4 100644 --- a/data_share/frameworks/native/proxy/src/published_data_subscriber_manager.cpp +++ b/data_share/frameworks/native/proxy/src/published_data_subscriber_manager.cpp @@ -56,7 +56,8 @@ std::vector PublishedDataSubscriberManager::AddObservers(void * opResult.emplace_back(subResult); if (subResult.errCode_ != E_OK) { failedKeys.emplace_back(subResult.key_, subscriberId); - LOG_WARN("registered failed, uri is %{public}s", subResult.key_.c_str()); + LOG_WARN("registered failed, uri is %{public}s", + DataShareStringUtils::Anonymous(subResult.key_).c_str()); } } if (failedKeys.size() > 0) { @@ -147,7 +148,8 @@ std::vector PublishedDataSubscriberManager::EnableObservers(voi opResult.emplace_back(subResult); if (subResult.errCode_ != E_OK) { failedKeys.emplace_back(subResult.key_, subscriberId); - LOG_WARN("registered failed, uri is %{public}s", subResult.key_.c_str()); + LOG_WARN("registered failed, uri is %{public}s", + DataShareStringUtils::Anonymous(subResult.key_).c_str()); } } if (failedKeys.size() > 0) { @@ -168,7 +170,7 @@ std::vector PublishedDataSubscriberManager::DisableObservers(vo keys.emplace_back(uri, subscriberId); }); return BaseCallbacks::DisableObservers(keys, subscriber, - [&proxy, &subscriberId, this](const std::vector &lastDisabledKeys, + [&proxy, &subscriberId, subscriber, this](const std::vector &lastDisabledKeys, std::vector &opResult) { std::vector lastDisabledUris; std::for_each(lastDisabledKeys.begin(), lastDisabledKeys.end(), [&lastDisabledUris](auto &result) { @@ -179,7 +181,18 @@ std::vector PublishedDataSubscriberManager::DisableObservers(vo } auto results = proxy->DisableSubscribePublishedData(lastDisabledUris, subscriberId); - opResult.insert(opResult.end(), results.begin(), results.end()); + std::vector failedKeys; + for (auto &result : results) { + opResult.emplace_back(result); + if (result.errCode_ != E_OK) { + failedKeys.emplace_back(result.key_, subscriberId); + LOG_WARN("DisableObservers failed, uri is %{public}s, errCode is %{public}d", + DataShareStringUtils::Anonymous(result.key_).c_str(), result.errCode_); + } + } + if (failedKeys.size() > 0) { + BaseCallbacks::EnableObservers(failedKeys, subscriber); + } }); } @@ -200,7 +213,7 @@ void PublishedDataSubscriberManager::RecoverObservers(std::shared_ptr, PublishedDataChangeNode> results; for (auto &data : changeNode.datas_) { PublishedObserverMapKey key(data.key_, data.subscriberId_); + // Still set observer was notified flag and store data if there is no enabled observer. + BaseCallbacks::SetObserversNotifiedOnEnabled(key); auto callbacks = BaseCallbacks::GetEnabledObservers(key); - if (callbacks.empty()) { - LOG_WARN("%{private}s nobody subscribe, but still notify", data.key_.c_str()); - continue; - } lastChangeNodeMap_.Compute(key, [&data, &changeNode](const Key &, PublishedDataChangeNode &value) { + value.datas_.clear(); value.datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); value.ownerBundleName_ = changeNode.ownerBundleName_; return true; }); + + if (callbacks.empty()) { + LOG_WARN("%{public}s nobody subscribe, but still notify", + DataShareStringUtils::Anonymous(data.key_).c_str()); + continue; + } for (auto const &obs : callbacks) { results[obs].datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); } - BaseCallbacks::SetObserversNotifiedOnEnabled(key); } for (auto &[callback, node] : results) { node.ownerBundleName_ = changeNode.ownerBundleName_; @@ -268,7 +278,6 @@ void PublishedDataSubscriberManager::EmitOnEnable(std::map RdbSubscriberManager::AddObservers(void *subscriber opResult.emplace_back(subResult); if (subResult.errCode_ != E_OK) { failedKeys.emplace_back(subResult.key_, templateId); - LOG_WARN("registered failed, uri is %{public}s", subResult.key_.c_str()); + LOG_WARN("registered failed, uri is %{public}s", + DataShareStringUtils::Anonymous(subResult.key_).c_str()); } } if (!failedKeys.empty()) { @@ -156,7 +157,8 @@ std::vector RdbSubscriberManager::EnableObservers(void *subscri opResult.emplace_back(subResult); if (subResult.errCode_ != E_OK) { failedKeys.emplace_back(subResult.key_, templateId); - LOG_WARN("registered failed, uri is %{public}s", subResult.key_.c_str()); + LOG_WARN("registered failed, uri is %{public}s", + DataShareStringUtils::Anonymous(subResult.key_).c_str()); } } if (!failedKeys.empty()) { @@ -177,7 +179,8 @@ std::vector RdbSubscriberManager::DisableObservers(void *subscr keys.emplace_back(uri, templateId); }); return BaseCallbacks::DisableObservers(keys, subscriber, - [&proxy, &templateId, this](const std::vector &lastDisabledKeys, std::vector &opResult) { + [&proxy, subscriber, &templateId, this](const std::vector &lastDisabledKeys, + std::vector &opResult) { std::vector lastDisabledUris; std::for_each(lastDisabledKeys.begin(), lastDisabledKeys.end(), [&lastDisabledUris](auto &result) { lastDisabledUris.emplace_back(result); @@ -187,7 +190,18 @@ std::vector RdbSubscriberManager::DisableObservers(void *subscr } auto results = proxy->DisableSubscribeRdbData(lastDisabledUris, templateId); - opResult.insert(opResult.end(), results.begin(), results.end()); + std::vector failedKeys; + for (auto &result : results) { + opResult.emplace_back(result); + if (result.errCode_ != E_OK) { + failedKeys.emplace_back(result.key_, templateId); + LOG_WARN("DisableObservers failed, uri is %{public}s, errCode is %{public}d", + DataShareStringUtils::Anonymous(result.key_).c_str(), result.errCode_); + } + } + if (!failedKeys.empty()) { + BaseCallbacks::EnableObservers(failedKeys, subscriber); + } }); } @@ -206,8 +220,8 @@ void RdbSubscriberManager::RecoverObservers(std::shared_ptrSubscribeRdbData(uris, templateId, serviceCallback_); for (const auto& result : results) { if (result.errCode_ != E_OK) { - LOG_WARN("RecoverObservers failed, uri is %{public}s, errCode is %{public}d", result.key_.c_str(), - result.errCode_); + LOG_WARN("RecoverObservers failed, uri is %{public}s, errCode is %{public}d", + DataShareStringUtils::Anonymous(result.key_).c_str(), result.errCode_); } } } @@ -217,7 +231,7 @@ void RdbSubscriberManager::Emit(const RdbChangeNode &changeNode) { RdbObserverMapKey key(changeNode.uri_, changeNode.templateId_); lastChangeNodeMap_.InsertOrAssign(key, changeNode); - auto callbacks = BaseCallbacks::GetEnabledObservers(key); + auto callbacks = BaseCallbacks::GetObserversAndSetNotifiedOn(key); for (auto &obs : callbacks) { if (obs != nullptr) { LOG_INFO("Client send data to form, uri is %{public}s, subscriberId is %{public}" PRId64, @@ -225,7 +239,6 @@ void RdbSubscriberManager::Emit(const RdbChangeNode &changeNode) obs->OnChange(changeNode); } } - BaseCallbacks::SetObserversNotifiedOnEnabled(key); } void RdbSubscriberManager::Emit(const std::vector &keys, const std::shared_ptr &observer) @@ -258,8 +271,9 @@ void RdbSubscriberManager::EmitOnEnable(std::mapOnChange(node); } } diff --git a/data_share/interfaces/inner_api/BUILD.gn b/data_share/interfaces/inner_api/BUILD.gn index 7452123b0f222ca23501f917c040ed860cf3f026..0c62798f8e1b587727bfa4b2ac2b1df252b4f6e4 100644 --- a/data_share/interfaces/inner_api/BUILD.gn +++ b/data_share/interfaces/inner_api/BUILD.gn @@ -59,6 +59,7 @@ datashare_consumer_sources = [ "${datashare_native_consumer_path}/src/datashare_connection.cpp", "${datashare_native_consumer_path}/src/datashare_helper.cpp", "${datashare_native_consumer_path}/src/datashare_helper_impl.cpp", + "${datashare_native_consumer_path}/src/dataproxy_handle.cpp", "${datashare_native_consumer_path}/src/datashare_proxy.cpp", "${datashare_native_proxy_path}/src/ams_mgr_proxy.cpp", "${datashare_native_proxy_path}/src/data_proxy_observer_stub.cpp", @@ -67,6 +68,7 @@ datashare_consumer_sources = [ "${datashare_native_proxy_path}/src/idata_share_client_death_observer.cpp", "${datashare_native_proxy_path}/src/published_data_subscriber_manager.cpp", "${datashare_native_proxy_path}/src/rdb_subscriber_manager.cpp", + "${datashare_native_proxy_path}/src/proxy_data_subscriber_manager.cpp", ] datashare_consumer_external_deps = [ @@ -89,6 +91,7 @@ config("permission_config") { visibility = [ ":*" ] include_dirs = [ "common/include", + "dfx/include", "permission/include", "${datashare_common_native_path}/include", "${datashare_native_permission_path}/include", @@ -145,12 +148,15 @@ ohos_shared_library("datashare_permission") { cfi_cross_dso = true debug = false } - include_dirs = [] + include_dirs = [ "${datashare_native_dfx_path}/include" ] sources = [ "${datashare_common_native_path}/src/datashare_string_utils.cpp", + "${datashare_common_native_path}/src/serializable.cpp", "${datashare_native_permission_path}/src/data_share_called_config.cpp", "${datashare_native_permission_path}/src/data_share_permission.cpp", + "${datashare_native_permission_path}/src/data_share_config.cpp", + "${datashare_native_dfx_path}/src/hiview_datashare.cpp", ] configs = [ ":permission_config" ] public_configs = [ ":permission_public_config" ] @@ -168,6 +174,8 @@ ohos_shared_library("datashare_permission") { "bundle_framework:libappexecfwk_common", "c_utils:utils", "common_event_service:cesfwk_innerkits", + "hisysevent:libhisysevent", + "kv_store:distributeddata_inner", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -186,10 +194,15 @@ ohos_shared_library("datashare_provider") { cfi_cross_dso = true debug = false } - include_dirs = [ "${datashare_common_napi_path}/include" ] + include_dirs = [ + "${datashare_common_napi_path}/include", + "${datashare_native_dfx_path}/include", + "${datashare_native_permission_path}/include", + ] sources = [ "${datashare_common_native_path}/src/datashare_string_utils.cpp", + "${datashare_common_native_path}/src/serializable.cpp", "${datashare_native_provider_path}/src/datashare_ext_ability.cpp", "${datashare_native_provider_path}/src/datashare_ext_ability_context.cpp", "${datashare_native_provider_path}/src/datashare_stub.cpp", @@ -197,6 +210,8 @@ ohos_shared_library("datashare_provider") { "${datashare_native_provider_path}/src/datashare_uv_queue.cpp", "${datashare_native_provider_path}/src/js_datashare_ext_ability.cpp", "${datashare_native_provider_path}/src/js_datashare_ext_ability_context.cpp", + "${datashare_native_permission_path}/src/data_share_config.cpp", + "${datashare_native_dfx_path}/src/hiview_datashare.cpp", ] configs = [ ":ability_config" ] public_configs = [ ":datashare_public_config" ] diff --git a/data_share/interfaces/inner_api/common/BUILD.gn b/data_share/interfaces/inner_api/common/BUILD.gn index dd28c64e98a709985d5617c439d58f8b2834a52b..ad3f46262befc596896985ebe60c1a35ba9c2d17 100644 --- a/data_share/interfaces/inner_api/common/BUILD.gn +++ b/data_share/interfaces/inner_api/common/BUILD.gn @@ -42,6 +42,7 @@ datashare_common_sources = [ "${datashare_common_native_path}/src/datashare_abs_result_set.cpp", "${datashare_common_native_path}/src/datashare_block_writer_impl.cpp", "${datashare_common_native_path}/src/datashare_itypes_utils.cpp", + "${datashare_common_native_path}/src/datashare_predicates.cpp", "${datashare_common_native_path}/src/datashare_result_set.cpp", "${datashare_common_native_path}/src/datashare_template.cpp", "${datashare_common_native_path}/src/datashare_valuebucket_convert.cpp", @@ -59,6 +60,7 @@ datashare_common_external_deps = [ "hisysevent:libhisysevent", "hitrace:hitrace_meter", "hitrace:libhitracechain", + "ipc:ipc_core", "ipc:ipc_single", "kv_store:distributeddata_inner", ] @@ -119,3 +121,31 @@ ohos_static_library("datashare_common_static") { subsystem_name = "distributeddatamgr" part_name = "data_share" } + +config("datashare_common_lite_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${datashare_base_path}/interfaces/inner_api/common/include", + "${datashare_base_path}/interfaces/inner_api/provider/include", + "${datashare_base_path}/interfaces/inner_api/consumer/include", + "${datashare_base_path}/frameworks/native/common/include", + ] +} + +ohos_static_library("datashare_common_lite") { + branch_protector_ret = "pac_ret" + sanitize = { + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + configs = [ ":ability_config" ] + public_configs = [ ":datashare_common_lite_config" ] + + subsystem_name = "distributeddatamgr" + part_name = "data_share" +} diff --git a/data_share/interfaces/inner_api/common/include/dataproxy_handle_common.h b/data_share/interfaces/inner_api/common/include/dataproxy_handle_common.h new file mode 100644 index 0000000000000000000000000000000000000000..b609547f6ba954986d6bf3213cdedc4136bc8918 --- /dev/null +++ b/data_share/interfaces/inner_api/common/include/dataproxy_handle_common.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2022 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_PROXY_COMMON_H +#define DATASHARE_PROXY_COMMON_H + +#include "datashare_observer.h" + +namespace OHOS { +namespace DataShare { +static constexpr int32_t URI_MAX_SIZE = 256; +static constexpr int32_t VALUE_MAX_SIZE = 4096; +static constexpr int32_t APPIDENTIFIER_MAX_SIZE = 128; +static constexpr int32_t URI_MAX_COUNT = 32; +static constexpr int32_t PROXY_DATA_MAX_COUNT = 32; +static constexpr int32_t ALLOW_LIST_MAX_COUNT = 256; +constexpr const char* ALLOW_ALL = "all"; +constexpr const char* DATA_PROXY_SCHEMA = "datashareproxy://"; + +enum DataProxyErrorCode { + SUCCESS = 0, + URI_NOT_EXIST, + NO_PERMISSION, + OVER_LIMIT, + INNER_ERROR, +}; + +/** + * @brief DataProxy Value Type . + */ +enum DataProxyValueType : int32_t { + /** DataProxy Value Types is int.*/ + VALUE_INT = 0, + /** DataProxy Value Types is double.*/ + VALUE_DOUBLE, + /** DataProxy Value Types is string.*/ + VALUE_STRING, + /** DataProxy Value Types is bool.*/ + VALUE_BOOL, +}; + +using DataProxyValue = std::variant; + +enum DataProxyType { + SHARED_CONFIG = 0, +}; + +struct DataProxyConfig { + DataProxyType type_; +}; + +struct DataShareProxyData { + /** + * @brief Constructor. + */ + DataShareProxyData() = default; + + /** + * @brief Destructor. + */ + ~DataShareProxyData() = default; + + DataShareProxyData(const std::string &uri, const DataProxyValue &value, + const std::vector &allowList = {}) : uri_(uri), value_(value), allowList_(allowList) {} + + std::string uri_; + DataProxyValue value_ = ""; + std::vector allowList_; + bool isValueUndefined = false; + bool isAllowListUndefined = false; +}; + +struct DataProxyResult { + DataProxyResult() = default; + DataProxyResult(const std::string &uri, const DataProxyErrorCode &result) : uri_(uri), result_(result) {} + std::string uri_; + DataProxyErrorCode result_; +}; + +struct DataProxyGetResult { + DataProxyGetResult() = default; + DataProxyGetResult(const std::string &uri, const DataProxyErrorCode &result, + const DataProxyValue &value = {}, const std::vector allowList = {}) + : uri_(uri), result_(result), value_(value), allowList_(allowList) {} + std::string uri_; + DataProxyErrorCode result_; + DataProxyValue value_; + std::vector allowList_; +}; + +struct DataProxyChangeInfo { + DataProxyChangeInfo() = default; + DataProxyChangeInfo(const DataShareObserver::ChangeType &changeType, + const std::string &uri, const DataProxyValue &value) + : changeType_(changeType), uri_(uri), value_(value) {} + DataShareObserver::ChangeType changeType_ = DataShareObserver::INVAILD; + std::string uri_; + DataProxyValue value_; +}; +} // namespace DataShare +} // namespace OHOS +#endif // DATASHARE_PROXY_COMMON_H \ No newline at end of file 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 d0e4bb047a77434999ccb6521722b29ec983d681..090d50ffeea02e8dee0918a78464861d6c7eff2d 100644 --- a/data_share/interfaces/inner_api/common/include/datashare_errno.h +++ b/data_share/interfaces/inner_api/common/include/datashare_errno.h @@ -16,6 +16,7 @@ #ifndef DATASHARE_ERRNO_H #define DATASHARE_ERRNO_H +#include "errors.h" namespace OHOS { namespace DataShare { /** @@ -193,6 +194,77 @@ constexpr int E_INVALID_USER_ID = (E_BASE + 68); * @brief The error code for not system app. */ constexpr int E_NOT_SYSTEM_APP = (E_BASE + 69); + +/** +* @brief The error code for register observer inner error. +*/ +constexpr int E_REGISTER_ERROR = (E_BASE + 70); + +/** +* @brief The error code for notify change inner error. +*/ +constexpr int E_NOTIFYCHANGE_ERROR = (E_BASE + 71); + +/** +* @brief The error code for timeout inner error. +*/ +constexpr int E_TIMEOUT_ERROR = (E_BASE + 72); + +/** +* @brief This error code indicates that the timeout interface is busy. +*/ +constexpr int E_ERROR_OVER_LIMIT_TASK = (E_BASE + 73); + +/** +* @brief The error code for pool is null. +*/ +constexpr int E_EXECUTOR_POOL_IS_NULL = (E_BASE + 74); + +/** +* @brief The error code for not hap. +*/ +constexpr int E_NOT_HAP = (E_BASE + 75); + +/** +* @brief The error code for get bundle info failed. +*/ +constexpr int E_GET_BUNDLEINFO_FAILED = (E_BASE + 76); + +/** +* @brief The error code for not datashare extension. +*/ +constexpr int E_NOT_DATASHARE_EXTENSION = (E_BASE + 77); + +/** +* @brief The error code for invalid uri. +*/ +constexpr int E_DATASHARE_INVALID_URI = (E_BASE + 78); + +/** +* @brief The error code for verify failed. +*/ +constexpr int E_VERIFY_FAILED = (E_BASE + 79); + +/** +* @brief The error code for permission denied. +*/ +constexpr int E_DATASHARE_PERMISSION_DENIED = (E_BASE + 80); + +/** +* @brief The error code for empty uri. +*/ +constexpr int E_EMPTY_URI = (E_BASE + 81); + +/** +* @brief The error code for uri not trust. +*/ +constexpr int E_NOT_IN_TRUSTS = (E_BASE + 82); + +/** +* @brief The error code for get caller failed. +*/ +constexpr int E_GET_CALLER_NAME_FAILED = (E_BASE + 83); + } // namespace DataShare } // namespace OHOS diff --git a/data_share/interfaces/inner_api/common/include/datashare_observer.h b/data_share/interfaces/inner_api/common/include/datashare_observer.h index dbfce03e873fb9b1c6cb90e1c4ce6ba39d2e5ecd..25e19bd412f8041340c98dd3bbab8e421abecf46 100644 --- a/data_share/interfaces/inner_api/common/include/datashare_observer.h +++ b/data_share/interfaces/inner_api/common/include/datashare_observer.h @@ -19,6 +19,7 @@ #include #include #include +#include #include "uri.h" diff --git a/data_share/interfaces/inner_api/common/include/datashare_operation_statement.h b/data_share/interfaces/inner_api/common/include/datashare_operation_statement.h index a4688bca674bb8c73ea452d7af9f4543c8cdff3c..90de3c0c09d039e196e755fdc2049c26bd2683c1 100644 --- a/data_share/interfaces/inner_api/common/include/datashare_operation_statement.h +++ b/data_share/interfaces/inner_api/common/include/datashare_operation_statement.h @@ -61,6 +61,10 @@ struct ExecResultSet { ExecErrorCode errorCode; std::vector results; }; + +struct RegisterOption { + bool isReconnect; +}; } } #endif // DATASHARE_OPERATION_STATEMENT_H diff --git a/data_share/interfaces/inner_api/common/include/datashare_option.h b/data_share/interfaces/inner_api/common/include/datashare_option.h new file mode 100644 index 0000000000000000000000000000000000000000..fb94c0d4d0f519deae3c4868375def788d5771a8 --- /dev/null +++ b/data_share/interfaces/inner_api/common/include/datashare_option.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 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_OPTION_H +#define DATASHARE_OPTION_H + +namespace OHOS::DataShare { + +struct DataShareOption { + uint32_t timeout = 0; +}; +} +#endif // DATASHARE_OPTION_H diff --git a/data_share/interfaces/inner_api/common/include/datashare_predicates.h b/data_share/interfaces/inner_api/common/include/datashare_predicates.h index 69350d5d69a43f87ba4814a21c2381754692e68b..ce00c068ef7199f9448988a5c13768391efcc8a3 100644 --- a/data_share/interfaces/inner_api/common/include/datashare_predicates.h +++ b/data_share/interfaces/inner_api/common/include/datashare_predicates.h @@ -22,6 +22,7 @@ #include "datashare_errno.h" #include "datashare_predicates_object.h" #include "datashare_predicates_objects.h" +#include "message_parcel.h" namespace OHOS { namespace DataShare { @@ -559,6 +560,16 @@ public: settingMode_ = settingMode; } + /** + * @brief The following four functions are used for serializing and deserializing objects + * to and from shared memory during Query and BatchInsert operations, + * which has a 128M upper limit. The upper limit of other method is 200k. + * Other methods remain unchanged. + */ + static bool Marshal(const DataSharePredicates &predicates, MessageParcel &parcel); + + static bool Unmarshal(DataSharePredicates &predicates, MessageParcel &parcel); + private: void SetOperationList(OperationType operationType, const MutliValue ¶m) { diff --git a/data_share/interfaces/inner_api/consumer/include/dataproxy_handle.h b/data_share/interfaces/inner_api/consumer/include/dataproxy_handle.h new file mode 100644 index 0000000000000000000000000000000000000000..4b4065c73306abad57b4ebc9219f81bb4e6ae8ba --- /dev/null +++ b/data_share/interfaces/inner_api/consumer/include/dataproxy_handle.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2025 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 DATAPROXY_HANDLE_H +#define DATAPROXY_HANDLE_H + +#include +#include + +#include "datashare_business_error.h" +#include "datashare_errno.h" +#include "dataproxy_handle_common.h" +#include "datashare_observer.h" + +namespace OHOS { + +namespace DataShare { +class DataProxyHandle : public std::enable_shared_from_this { +public: + /** + * @brief Destructor. + */ + ~DataProxyHandle() = default; + + /** + * @brief Creates a DataProxyHandle instance. + * + * @return Returns the created DataProxyHandle instance. + */ + static std::pair> Create(); + + std::vector PublishProxyData( + const std::vector &proxyData, const DataProxyConfig &proxyConfig); + + std::vector DeleteProxyData( + const std::vector &uris, const DataProxyConfig &proxyConfig); + + static std::vector GetProxyData( + const std::vector uris, const DataProxyConfig &proxyConfig); + + std::vector SubscribeProxyData(const std::vector &uris, + const std::function &changeNode)> &callback); + + std::vector UnsubscribeProxyData(const std::vector &uris); +}; +} // namespace DataShare +} // namespace OHOS +#endif // DATAPROXY_HANDLE_H \ No newline at end of file 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 9d1a7c597327a296fd8d1e6fdda77abb145548e6..208150b544a26b68907c31015d070a773fd2af74 100644 --- a/data_share/interfaces/inner_api/consumer/include/datashare_helper.h +++ b/data_share/interfaces/inner_api/consumer/include/datashare_helper.h @@ -22,17 +22,19 @@ #include #include -#include "data_ability_observer_interface.h" +#include "data_ability_observer_stub.h" #include "datashare_business_error.h" #include "datashare_errno.h" #include "datashare_observer.h" #include "datashare_operation_statement.h" +#include "datashare_option.h" #include "datashare_predicates.h" #include "datashare_result_set.h" #include "datashare_template.h" #include "datashare_values_bucket.h" #include "uri.h" + using Uri = OHOS::Uri; namespace OHOS { @@ -125,6 +127,20 @@ public: */ virtual int OpenFile(Uri &uri, const std::string &mode) = 0; + /** + * @brief Opens a file in a specified remote path. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, + * or "rwt" for read and write access that truncates any existing file. + * @param errCode real error code. + * + * @return Returns the file descriptor. + */ + virtual int OpenFileWithErrCode(Uri &uri, const std::string &mode, int32_t &errCode) = 0; + /** * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets * inside of their .hap. @@ -207,6 +223,21 @@ public: virtual std::shared_ptr Query(Uri &uri, const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError *businessError = nullptr) = 0; + /** + * @brief Query records from the database with timeout. + * + * @param uri Indicates the path of data to query. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. + * @param option Indicates the query options. The option includes a timeout period, in milliseconds. + * @param businessError Indicates the error by query. + * + * @return Returns the query result. + */ + virtual std::shared_ptr Query(Uri &uri, const DataSharePredicates &predicates, + std::vector &columns, DataShareOption &option, + DatashareBusinessError *businessError = nullptr) { return nullptr; } + /** * @brief Obtains the MIME type matching the data specified by the URI of the Data share. This method should be * implemented by a Data share. Data abilities supports general data types, including text, HTML, and JPEG. @@ -273,7 +304,20 @@ public: * @param dataObserver, Indicates the IDataAbilityObserver object. * @param isDescendants, Indicates the Whether to note the change of descendants. */ - void RegisterObserverExt(const Uri &uri, std::shared_ptr dataObserver, bool isDescendants); + void RegisterObserverExt(const Uri &uri, std::shared_ptr dataObserver, + bool isDescendants, bool isSystem = false); + + /** + * Registers an observer specified by the given Uri to the provider. This function is supported only when using + * non-silent DataShareHelper, and there is no default implemention in the provider side. It needs to be handled by + * the user. Otherwise, the provider side will do nothing but simply return error. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + * @param isDescendants, Indicates the Whether to note the change of descendants. + */ + virtual int RegisterObserverExtProvider(const Uri &uri, std::shared_ptr dataObserver, + bool isDescendants) = 0; /** * Deregisters an observer used for DataObsMgr specified by the given Uri. @@ -281,14 +325,33 @@ public: * @param uri, Indicates the path of the data to operate. * @param dataObserver, Indicates the IDataAbilityObserver object */ - void UnregisterObserverExt(const Uri &uri, std::shared_ptr dataObserver); + void UnregisterObserverExt(const Uri &uri, std::shared_ptr dataObserver, bool isSystem = false); + + /** + * Deregisters an observer specified by the given Uri to the provider. This function is supported only when using + * non-silent DataShareHelper, and there is no default implemention in the provider side. It needs to be handled by + * the user. Otherwise, the provider side will do nothing but simply return error. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object + */ + virtual int UnregisterObserverExtProvider(const Uri &uri, std::shared_ptr dataObserver) = 0; /** * Notifies the registered observers of a change to the data resource specified by Uris. * * @param changeInfo Indicates the info of the data to operate. */ - void NotifyChangeExt(const DataShareObserver::ChangeInfo &changeInfo); + void NotifyChangeExt(const DataShareObserver::ChangeInfo &changeInfo, bool isSystem = false); + + /** + * Notifies the registered observers of a change to the data resource specified by Uris. This function is supported + * only when using non-silent DataShareHelper, and there is no default implemention in the provider side. It needs + * to be handled by the user. Otherwise, the provider side will do nothing but simply return true. + * + * @param changeInfo Indicates the info of the data to operate. + */ + virtual void NotifyChangeExtProvider(const DataShareObserver::ChangeInfo &changeInfo) = 0; /** * @brief Converts the given uri that refer to the Data share into a normalized URI. A normalized URI can be used @@ -467,12 +530,15 @@ public: * @brief UserDefineFunc supports user-defined serialization of data and deserialization of reply. * It directly passes IPC parameters without any processing. * Through this interface, users can implement their own business logic. + * When implementing user customized logic, it is recommended to not send errCode using return. Instead, use the + * reply parameter to carry the errCode to avoid conflicts with IPC error codes. Return is intended to be used + * only to return the results of the IPC call. * * @param data Data sent from the consumer to the provider * @param reply Data returned from the provider to the consumer, including errCode * @param option The options of IPC call * - * @return Returns int32_t, the errCode of IPC call. + * @return Returns int32_t, the errCode returnd by IPC call to provider. */ virtual int32_t UserDefineFunc(MessageParcel &data, MessageParcel &reply, MessageOption &option); 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 9a2a94d4979c71c7063cb29180274ac791edfc4c..4f91e7740c681ebd0b90dba17efb1f8a9b944db8 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 @@ -163,6 +163,11 @@ public: bool HasBlock(); std::shared_ptr GetBridge(); + + static bool Marshal(const std::shared_ptr resultSet, MessageParcel &parcel); + + static std::shared_ptr Unmarshal(MessageParcel &parcel); + protected: int CheckState(int columnIndex); void ClosedBlockAndBridge(); @@ -181,7 +186,7 @@ private: int endRowPos_ = -1; // The SharedBlock owned by this DataShareResultSet std::shared_mutex mutex_; - std::shared_ptr sharedBlock_ = nullptr; + std::shared_ptr sharedBlock_ = nullptr; std::shared_ptr blockWriter_ = nullptr; std::shared_ptr bridge_ = nullptr; }; diff --git a/data_share/interfaces/inner_api/consumer/libdatashare_consumer.map b/data_share/interfaces/inner_api/consumer/libdatashare_consumer.map index 198530350c0762dab372ae5d23f5f68280fd9f2a..2bca178e0f493f90c9c2965883bb0a26595ee98e 100644 --- a/data_share/interfaces/inner_api/consumer/libdatashare_consumer.map +++ b/data_share/interfaces/inner_api/consumer/libdatashare_consumer.map @@ -14,6 +14,7 @@ 1.0 { global: *DataShareHelper*; + *DataProxyHandle*; *DataShareResultSet*; *DataShareAbsResultSet*; *DataShareSharedResultSet*; diff --git a/data_share/interfaces/inner_api/permission/include/data_share_permission.h b/data_share/interfaces/inner_api/permission/include/data_share_permission.h index 2b03231a29f25d086a40c110fc296f4f65ab499c..96228f4ca3ef6c1f7bc9ed7326e2bee391757fb1 100644 --- a/data_share/interfaces/inner_api/permission/include/data_share_permission.h +++ b/data_share/interfaces/inner_api/permission/include/data_share_permission.h @@ -30,15 +30,49 @@ public: DataSharePermission() = default; ~DataSharePermission() = default; /** - * @brief Verify if tokenId has access perimission to uri. + * @brief Verify if tokenId has access permission to uri. * @param tokenId Unique identification of application. - * @param uri, Indicates the path of data to verify perimission. + * @param uri, Indicates the path of data to verify permission. * @param isRead, Obtain read permission for true and write permission for false. * @return Returns the error code. */ static int VerifyPermission(Security::AccessToken::AccessTokenID tokenId, const Uri &uri, bool isRead); + + static std::pair GetExtensionUriPermission(Uri &uri, + int32_t user, bool isRead); + static std::pair GetDataShareSilentUriPermission(uint32_t tokenId, + int32_t user, std::string &extUri, bool isRead); + + static int CheckExtensionTrusts(uint32_t consumerToken, uint32_t providerToken); + + static void ReportExtensionFault(int32_t errCode, uint32_t tokenId, + std::string &uri, std::string &bussinessType); + + static bool VerifyPermission(uint32_t tokenId, std::string &permission); + + static bool VerifyPermission(Uri &uri, uint32_t tokenId, std::string &permission, bool isExtension); + + static std::pair GetSilentUriPermission(Uri &uri, int32_t user, bool isRead); + + static int32_t UriIsTrust(Uri &uri); + + static std::pair GetUriPermission(Uri &uri, int32_t user, bool isRead, bool isExtension); + + static int32_t IsExtensionValid(uint32_t tokenId, uint32_t fullToken, int32_t user); +private: + + static constexpr const char *SCHEMA_DATASHARE = "datashare"; + static constexpr const char *SCHEMA_DATASHARE_PROXY = "datashareproxy"; + static constexpr const char *SCHEMA_PREFERENCE = "sharepreferences"; + static constexpr const char *SCHEMA_RDB = "rdb"; + static constexpr const char *SCHEMA_FILE = "file"; + + static void ReportExcuteFault(int32_t errCode, std::string &consumer, std::string &provider); + + static int VerifyDataObsPermissionInner(Security::AccessToken::AccessTokenID tokenID, + Uri &uri, bool isRead, bool &isTrust); }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/test/ets/data_share_ets/AppScope/app.json b/data_share/test/ets/data_share_ets/AppScope/app.json new file mode 100644 index 0000000000000000000000000000000000000000..d20832378281e69084f56f872348abdb9d249bb5 --- /dev/null +++ b/data_share/test/ets/data_share_ets/AppScope/app.json @@ -0,0 +1,21 @@ +{ + "app":{ + "bundleName":"com.example.myapplication", + "vendor":"example", + "versionCode":1000000, + "versionName":"1.0.0", + "debug":false, + "icon":"$media:icon", + "label":"$string:app_name", + "description":"$string:description_application", + "distributedNotificationEnabled":true, + "keepAlive":true, + "singleUser":true, + "minAPIVersion":8, + "targetAPIVersion":8, + "car":{ + "apiCompatibleVersion":8, + "singleUser":false + } + } +} diff --git a/data_share/test/ets/data_share_ets/AppScope/resources/base/element/string.json b/data_share/test/ets/data_share_ets/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..ee69f9a861d9dc269ed6638735d52674583498e1 --- /dev/null +++ b/data_share/test/ets/data_share_ets/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string":[ + { + "name":"app_name", + "value":"ohosProject" + } + ] +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/corpus/init b/data_share/test/ets/data_share_ets/BUILD.gn similarity index 39% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/corpus/init rename to data_share/test/ets/data_share_ets/BUILD.gn index bc977bd9738ee9a70b362067f57a9c63d3adb801..42ebd7bf6081a6246aa3cb2ec59ce4a66c39d9b1 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/corpus/init +++ b/data_share/test/ets/data_share_ets/BUILD.gn @@ -11,4 +11,35 @@ # See the License for the specific language governing permissions and # limitations under the License. -FUZZ \ No newline at end of file +import("//build/test.gni") + +ohos_js_stage_unittest("ActsDataShareEtsTest") { + hap_profile = "entry/src/main/module.json" + deps = [ + ":stageprejstest_js_assets", + ":stageprejstest_resources", + ] + ets2abc = true + certificate_profile = "signature/openharmony_sx.p7b" + hap_name = "ActsDataShareEtsTest" + subsystem_name = "distributeddatamgr" + part_name = "data_share" + module_out_path = "data_share/data_share/data_share_ets" +} +ohos_app_scope("stageprejstest_app_profile") { + app_profile = "AppScope/app.json" + sources = [ "AppScope/resources" ] +} +ohos_js_assets("stageprejstest_js_assets") { + source_dir = "entry/src/main/ets" +} +ohos_resources("stageprejstest_resources") { + sources = [ "entry/src/main/resources" ] + deps = [ ":stageprejstest_app_profile" ] + hap_profile = "entry/src/main/module.json" +} +group("stage_unittest") { + testonly = true + deps = [] + deps += [ ":ActsDataShareEtsTest" ] +} diff --git a/data_share/test/ets/data_share_ets/Test.json b/data_share/test/ets/data_share_ets/Test.json new file mode 100644 index 0000000000000000000000000000000000000000..a8d9564be1ea9504bd4b722ec0495a9a8fdcb75b --- /dev/null +++ b/data_share/test/ets/data_share_ets/Test.json @@ -0,0 +1,27 @@ +{ + "description": "Configuration for hjunit demo Tests", + "driver": { + "type": "OHJSUnitTest", + "test-timeout": "180000", + "bundle-name": "com.example.myapplication", + "module-name": "testModule", + "shell-timeout": "600000", + "testcase-timeout": 70000 + }, + "kits": [ + { + "test-file-name": [ + "ActsDataShareEtsTest.hap" + ], + "type": "AppInstallKit", + "cleanup-apps": true + }, + { + "type": "ShellKit", + "teardown-command":[ + "bm uninstall -n com.example.myapplication" + ] + } + ] +} + diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/Application/AbilityStage.ts b/data_share/test/ets/data_share_ets/entry/src/main/ets/Application/AbilityStage.ts new file mode 100644 index 0000000000000000000000000000000000000000..e0732e916f734443f2a2457ef55192842fbd00ad --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/Application/AbilityStage.ts @@ -0,0 +1,22 @@ +// Copyright (c) 2023 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 AbilityStage from "@ohos.app.ability.AbilityStage" + +export default class MyAbilityStage extends AbilityStage { + onCreate() { + console.log('[Demo] MyAbilityStage onCreate'); + globalThis.stageOnCreateRun = 1; + globalThis.stageContext = this.context; + } +} diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/DataShareExtensionAbility/DataShareExtAbility.ts b/data_share/test/ets/data_share_ets/entry/src/main/ets/DataShareExtensionAbility/DataShareExtAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..983f1199e7994545e75cddf7c2bf74a51d0aa066 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/DataShareExtensionAbility/DataShareExtAbility.ts @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2025 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 Extension from '@ohos.application.DataShareExtensionAbility'; +import { UpdateOperation } from '@ohos.application.DataShareExtensionAbility'; +import rdb from '@ohos.data.relationalStore'; +import rpc from '@ohos.rpc'; + +let DB_NAME = "DB00.db"; +let TBL_NAME = "TBL00"; +let DDL_TBL_CREATE = "CREATE TABLE IF NOT EXISTS " ++ TBL_NAME ++ " (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, phoneNumber DOUBLE, isStudent BOOLEAN, Binary BINARY, number INTEGER)"; +let DDL_TABLE_USER_SQL = "CREATE TABLE IF NOT EXISTS user (userId INTEGER PRIMARY KEY AUTOINCREMENT, firstName TEXT, lastName TEXT, age INTEGER , balance DOUBLE NOT NULL)"; +let DDL_TABLE_BOOK_SQL = "CREATE TABLE IF NOT EXISTS book (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, userId INTEGER, FOREIGN KEY (userId) REFERENCES user (userId) ON UPDATE NO ACTION ON DELETE CASCADE)"; +let DDL_TABLE_PERMISSION1_SQL = "CREATE TABLE IF NOT EXISTS permission1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, phoneNumber DOUBLE, isStudent BOOLEAN, Binary BINARY, number INTEGER)"; +let DDL_TABLE_PERMISSION2_SQL = "CREATE TABLE IF NOT EXISTS permission2 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, phoneNumber DOUBLE, isStudent BOOLEAN, Binary BINARY, number INTEGER)"; + +let rdbStore; + +export default class +extends Extension { + async onCreate(want, callback) { + console.log('[ttt] [DataShareTest] DataShareExtAbility onCreate, want:' + want.abilityName); + console.log("[ttt] [DataShareTest] DataShareExtAbility onCreate this.context.databaseDir:" + this.context.databaseDir); + rdbStore = await rdb.getRdbStore(this.context, { name: DB_NAME, securityLevel: rdb.SecurityLevel.S1 }); + console.log('[ttt] [DataShareTest] DataShareExtAbility getRdbStore done'); + await rdbStore.executeSql(DDL_TBL_CREATE, []); + await rdbStore.executeSql(DDL_TABLE_USER_SQL, []); + await rdbStore.executeSql(DDL_TABLE_BOOK_SQL, []); + await rdbStore.executeSql(DDL_TABLE_PERMISSION1_SQL, []); + await rdbStore.executeSql(DDL_TABLE_PERMISSION2_SQL, []); + console.log('[ttt] [DataShareTest] DataShareExtAbility executeSql multiple tables done'); + let err = {"code":0}; + callback(err); + console.log('[ttt] [DataShareTest] DataShareExtAbility onCreate end'); + } + + async insert(uri, value, callback) { + console.info('[ttt] [DataShareTest] [insert] enter'); + if (value == null) { + console.info('[ttt] [DataShareTest] [insert] invalid valueBuckets'); + return; + } + + console.info('[ttt] [DataShareTest] [insert] getCallingTokenId:' + rpc.IPCSkeleton.getCallingTokenId()); + console.info('[ttt] [DataShareTest] [insert] value = ' + value); + console.info('[ttt] [DataShareTest] [insert] value = ' + JSON.stringify(value)); + await rdbStore.insert(TBL_NAME, value, function (err, ret) { + console.info('[ttt] [DataShareTest] [insert] callback ret:' + ret); + + if (callback != undefined) { + callback(err, ret); + } + }); + 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) { + console.info('[ttt] [DataShareTest] [update] invalid predicates'); + return; + } + console.info('[ttt] [DataShareTest] [update] values = ' + value); + console.info('[ttt] [DataShareTest] [update] values = ' + JSON.stringify(value)); + console.info('[ttt] [DataShareTest] [update] predicates = ' + predicates); + console.info('[ttt] [DataShareTest] [update] predicates = ' + JSON.stringify(predicates)); + try { + await rdbStore.update(TBL_NAME,value, predicates, function (err, ret) { + console.info('[ttt] [DataShareTest] [update] callback ret:' + ret); + console.info('[ttt] [DataShareTest] [update] callback err:' + err); + if (callback != undefined) { + callback(err, ret); + } + }); + } catch (err) { + console.error('[ttt] [DataShareTest] [update] error' + err); + } + console.info('[ttt] [DataShareTest] [update] leave'); + } + + async delete(uri, predicates, callback) { + console.info('[ttt] [DataShareTest] [delete] enter'); + if (predicates == null || predicates == undefined) { + console.info('[ttt] [DataShareTest] [delete] invalid predicates'); + return; + } + console.info('[ttt] [DataShareTest] [delete] predicates = ' + predicates); + console.info('[ttt] [DataShareTest] [delete] predicates = ' + JSON.stringify(predicates)); + try { + await rdbStore.delete(TBL_NAME,predicates, function (err, ret) { + console.info('[ttt] [DataShareTest] [delete] ret:' + ret); + if (callback != undefined) { + callback(err, ret); + } + }); + } catch (err) { + console.error('[ttt] [DataShareTest] [delete] error' + err); + } + console.info('[ttt] [DataShareTest] [delete] leave'); + } + + async query(uri, predicates, columns, callback) { + console.info('[ttt] [DataShareTest] [query] enter'); + if (predicates == null || predicates == undefined) { + console.info('[ttt] [DataShareTest] [query] invalid predicates'); + } + console.info('[ttt] [DataShareTest] [query] values = ' + columns); + console.info('[ttt] [DataShareTest] [query] values = ' + JSON.stringify(columns)); + console.info('[ttt] [DataShareTest] [query] predicates = ' + predicates); + console.info('[ttt] [DataShareTest] [query] predicates = ' + JSON.stringify(predicates)); + try { + await rdbStore.query(TBL_NAME, predicates, columns, function (err, resultSet) { + console.info('[ttt] [DataShareTest] [query] ret: ' + resultSet); + if (resultSet != undefined) { + console.info('[ttt] [DataShareTest] [query] resultSet.rowCount: ' + resultSet.rowCount); + } + if (callback != undefined) { + callback(err, resultSet); + } + }); + } catch (err) { + console.error(`[ttt] [DataShareTest] [query] error: code: ${err.code}, message: ${err.message} `); + callback(err, undefined); + } + console.info('[ttt] [DataShareTest] [query] leave'); + } + + async batchInsert(uri: string, valueBuckets, callback) { + console.info('[ttt] [DataShareTest] [batchInsert] enter'); + if (valueBuckets == null || valueBuckets.length == undefined) { + console.info('[ttt] [DataShareTest] [batchInsert] invalid valueBuckets'); + return; + } + console.info('[ttt] [DataShareTest] [batchInsert] valueBuckets.length:' + valueBuckets.length); + let resultNum = valueBuckets.length + await rdbStore.batchInsert(TBL_NAME, valueBuckets, function (err, ret) { + console.info('[ttt] [DataShareTest] [batchInsert] callback ret:' + ret); + if (callback != undefined) { + callback(err, ret); + } + }); + + console.info('[ttt] [DataShareTest] [batchInsert] leave'); + } + + async normalizeUri(uri: string, callback) { + console.info('[ttt] [DataShareTest] [normalizeUri] enter'); + let ret = "normalize+" + uri; + let err = {"code":0}; + await callback(err, ret); + console.info('[ttt] [DataShareTest] [normalizeUri] leave, ret:' + ret); + } + + async denormalizeUri(uri: string, callback) { + console.info('[ttt] [DataShareTest] [denormalizeUri] enter'); + let ret = "denormalize+" + uri; + let err = {"code":0}; + await callback(err, ret); + console.info('[ttt] [DataShareTest] [denormalizeUri] leave, ret:' + ret); + } +}; \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/MainAbility.ts b/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/MainAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..fc92e47db90312464266c4cb485e000354883d38 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/MainAbility.ts @@ -0,0 +1,51 @@ +// Copyright (c) 2023 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 Ability from '@ohos.app.ability.UIAbility' +import common from '@ohos.app.ability.common' + +export default class MainAbility extends Ability { + onCreate(want, launchParam){ + // Ability is creating, initialize resources for this ability + AppStorage.setOrCreate('TestAbilityContext', this.context); + console.log('[Demo] MainAbility onCreate'); + globalThis.abilityWant = want; + } + + onDestroy() { + // Ability is destroying, release resources for this ability + console.log('[Demo] MainAbility onDestroy'); + } + + onWindowStageCreate(windowStage) { + // Main window is created, set main page for this ability + console.log('[Demo] MainAbility onWindowStageCreate'); + globalThis.abilityContext = this.context; + windowStage.setUIContent(this.context, "MainAbility/pages/index/index", null); + } + + onWindowStageDestroy() { + //Main window is destroyed, release UI related resources + console.log('[Demo] MainAbility onWindowStageDestroy'); + } + + onForeground() { + // Ability has brought to foreground + console.log('[Demo] MainAbility onForeground'); + } + + onBackground() { + // Ability has back to background + console.log('[Demo] MainAbility onBackground'); + } +}; \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/pages/index/index.ets b/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/pages/index/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..10b38297d768376945f91f3024577e62b8f37289 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/pages/index/index.ets @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022 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 router from '@ohos.router'; + +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' +import { Hypium } from '@ohos/hypium' +import testsuite from '../../../test/List.test' + + +@Entry +@Component +struct Index { + + aboutToAppear(){ + console.info("start run testcase!!!!") + let abilityDelegator: any + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + let abilityDelegatorArguments: any + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + console.info('start run testcase!!!') + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) + } + + build() { + Flex({ direction:FlexDirection.Column, alignItems:ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('Hello World') + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(25) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(() => { + + }) + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/pages/second/second.ets b/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/pages/second/second.ets new file mode 100644 index 0000000000000000000000000000000000000000..33d9ae45245db03fd252ef7c1a85c9e284028e0d --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/pages/second/second.ets @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 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 router from '@system.router'; + +@Entry +@Component +struct Second { + private content: string = "Second Page" + + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text(`${this.content}`) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('back to index') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(() => { + router.back() + }) + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/TestAbility/TestAbility.ts b/data_share/test/ets/data_share_ets/entry/src/main/ets/TestAbility/TestAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..f89a5dd5fc0f1af335e373b3fe75d8e8c3338cb8 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/TestAbility/TestAbility.ts @@ -0,0 +1,44 @@ +// Copyright (c) 2023 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 Ability from '@ohos.app.ability.UIAbility' + +export default class TestAbility extends Ability { + onCreate(want, launchParam) { + console.log('TestAbility onCreate'); + AppStorage.SetOrCreate("TestAbilityContext",this.context); + } + + onDestroy() { + console.log('TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage) { + console.log('TestAbility onWindowStageCreate'); + windowStage.setUIContent(this.context, 'TestAbility/pages/index', null); + + globalThis.abilityContext = this.context; + } + + onWindowStageDestroy() { + console.log('TestAbility onWindowStageDestroy'); + } + + onForeground() { + console.log('TestAbility onForeground'); + } + + onBackground() { + console.log('TestAbility onBackground'); + } +}; \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/TestAbility/pages/index.ets b/data_share/test/ets/data_share_ets/entry/src/main/ets/TestAbility/pages/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..b93567f962921124b282f78c8ef123965d1460c9 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/TestAbility/pages/index.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022 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 router from '@ohos.router'; + +@Entry +@Component +struct Index { + aboutToAppear() { + console.info('TestAbility index aboutToAppear') + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts b/data_share/test/ets/data_share_ets/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts new file mode 100644 index 0000000000000000000000000000000000000000..13026c5df99e51f36b6ac5a5804af8602f731ac8 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,71 @@ +// Copyright (c) 2023 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 TestRunner from '@ohos.application.testRunner' +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +function translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s it', + '-s level', '-s testType', '-s size', '-s timeout' + ]) + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams = `${targetParams} ${key} ${parameters[key]}` + } + } + return targetParams.trim() +} + +async function onAbilityCreateCallback() { + console.log('onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + console.info('addAbilityMonitorCallback : ' + JSON.stringify(err)); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + console.info("OpenHarmonyTestRunner OnPrepare "); + } + + async onRun() { + console.log('OpenHarmonyTestRunner onRun run') + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.MainAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a com.example.myapplication.MainAbility' + ' -b ' + abilityDelegatorArguments.bundleName + cmd += ' '+translateParamsToString(abilityDelegatorArguments.parameters) + console.info('cmd : '+ cmd) + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + console.info('executeShellCommand : err : ' + JSON.stringify(err)); + console.info('executeShellCommand : data : ' + d.stdResult); + console.info('executeShellCommand : data : ' + d.exitCode); + }) + console.info('OpenHarmonyTestRunner onRun end'); + } +}; \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/rddbopen_fuzzer.h b/data_share/test/ets/data_share_ets/entry/src/main/ets/test/List.test.ets similarity index 71% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/rddbopen_fuzzer.h rename to data_share/test/ets/data_share_ets/entry/src/main/ets/test/List.test.ets index 6ec5dc5d03685ab632e4426c842ea311f8eb48d0..c71f850a46f6a3898f96b25c52fd29d54d829971 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/rddbopen_fuzzer.h +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/test/List.test.ets @@ -13,9 +13,10 @@ * limitations under the License. */ -#ifndef TRANSFERGRDTYPETOCOLTYPE_FUZZER_H -#define TRANSFERGRDTYPETOCOLTYPE_FUZZER_H +import DataSharePredicatesEtsTest from './dataSharePredicate.test.ets'; +import DataShareSubscribeTest from './dataShareSubscribe.test.ets'; -#define FUZZ_PROJECT_NAME "transfergrdtypetocoltype_fuzzer" - -#endif // TRANSFERGRDTYPETOCOLTYPE_FUZZER_H \ No newline at end of file +export default function testsuite() { + DataSharePredicatesEtsTest(); + DataShareSubscribeTest(); +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/test/dataSharePredicate.test.ets b/data_share/test/ets/data_share_ets/entry/src/main/ets/test/dataSharePredicate.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1e062b37f09f4b361be01562303f7037b077186b --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/test/dataSharePredicate.test.ets @@ -0,0 +1,352 @@ + +/* + * Copyright (C) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level, Size, TestType } from "@ohos/hypium"; +import relationalStore from "@ohos.data.relationalStore"; +import dataSharePredicates from "@ohos.data.dataSharePredicates"; +import common from '@ohos.app.ability.common'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { BusinessError } from "@ohos.base"; + + +const STORE_CONFIG: relationalStore.StoreConfig = { + name: "rdbStore.db", + securityLevel: relationalStore.SecurityLevel.S1 +} +let rdbStore:relationalStore.RdbStore | undefined = undefined; +let table_name = "test"; +let DROP_TBL = "DROP TABLE IF EXISTS " + table_name; +let CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS " + + table_name + + " (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, isStudent BOOLEAN)"; +let TAG = "[dataSharePredicate_test]"; + +const delegator = AbilityDelegatorRegistry.getAbilityDelegator(); +const context = delegator.getAppContext().getApplicationContext(); + +async function generateTable() { + console.info(TAG + 'generateTable') + if (rdbStore != undefined) { + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: relationalStore.ValuesBucket = { + name: "ZhangSan", + age: 20, + 'isStudent': true, + } + await rdbStore.insert("test", valueBucket1) + const valueBucket2: relationalStore.ValuesBucket = { + name: "LiSi", + age: 21, + 'isStudent': true, + } + await rdbStore.insert("test", valueBucket2) + const valueBucket3: relationalStore.ValuesBucket = { + name: "WangWu", + age: 22, + 'isStudent': false, + } + await rdbStore.insert("test", valueBucket3) + const valueBucket4: relationalStore.ValuesBucket = { + name: "SunLiu", + age: 23, + 'isStudent': false, + } + await rdbStore.insert("test", valueBucket4) + const valueBucket5: relationalStore.ValuesBucket = { + name: "MaQi", + age: 24, + 'isStudent': true, + } + await rdbStore.insert("test", valueBucket5) + console.info(TAG + 'generateTable end') + } +} + +async function insertMoreData() { + console.info(TAG + 'insertMoreData') + if (rdbStore != undefined) { + const valueBucket1: relationalStore.ValuesBucket = { + name: "Steven", + age: 17, + 'isStudent': true, + } + await rdbStore.insert("test", valueBucket1) + const valueBucket2: relationalStore.ValuesBucket = { + name: "Jax", + age: 17, + 'isStudent': true, + } + await rdbStore.insert("test", valueBucket2) + const valueBucket3: relationalStore.ValuesBucket = { + name: "Green", + age: 17, + 'isStudent': false, + } + await rdbStore.insert("test", valueBucket3) + const valueBucket4: relationalStore.ValuesBucket = { + name: "List", + age: 14, + 'isStudent': false, + } + await rdbStore.insert("test", valueBucket4) + const valueBucket5: relationalStore.ValuesBucket = { + name: "Alice", + age: 24, + 'isStudent': true, + } + await rdbStore.insert("test", valueBucket5) + const valueBucket6: relationalStore.ValuesBucket = { + name: "Chary", + age: 24, + 'isStudent': true, + } + await rdbStore.insert("test", valueBucket6) + console.info(TAG + 'insertMoreData end') + } +} + +export default function DataSharePredicatesEtsTest() { + describe('DataSharePredicatesEtsTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll'); + await relationalStore.getRdbStore(context, STORE_CONFIG).then(async (store: relationalStore.RdbStore) => { + rdbStore = store; + console.info('ttt Get RdbStore successfully.') + }).catch((err: BusinessError) => { + console.error(`ttt Get RdbStore failed, code is ${err.code},message is ${err.message}`); + }) + }); + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + console.info(TAG + 'createTest data start'); + await generateTable(); + console.info(TAG + 'createTest data end'); + }) + afterEach(async () => { + console.info(TAG + 'afterEach'); + if (rdbStore != undefined) { + await rdbStore.executeSql(DROP_TBL); + } + }) + afterAll(async () => { + console.info(TAG + 'afterAll'); + relationalStore.deleteRdbStore(context, STORE_CONFIG.name).then(() => { + rdbStore = undefined; + console.info(TAG + 'Delete RdbStore successfully.'); + }).catch((err: BusinessError) => { + console.error(TAG + `Delete RdbStore failed, code is ${err.code},message is ${err.message}`); + }) + }); + + + + it('testDataSharePredicate_0001', 0, async () => { + console.log(TAG + "************* testDataSharePredicate_0001 start *************"); + const valueBucket: relationalStore.ValuesBucket = { + 'name': 'Steven', + 'age': 28, + 'isStudent': false, + }; + await rdbStore?.insert(table_name, valueBucket); + try { + let dp = new dataSharePredicates.DataSharePredicates(); + dp.equalTo("age", 28); + let resultSets = await (rdbStore as relationalStore.RdbStore).query(table_name, dp, ["*"]); + console.log(TAG + "rowCount is : " + resultSets.rowCount); + expect(resultSets.goToFirstRow()).assertEqual(true); + const id = resultSets.getLong(resultSets.getColumnIndex("id")); + const name = resultSets.getString(resultSets.getColumnIndex("name")); + const age = resultSets.getLong(resultSets.getColumnIndex("age")); + const isStudent = resultSets.getValue(resultSets.getColumnIndex("isStudent")); + expect(id).assertEqual(6); + expect(name).assertEqual("Steven"); + expect(age).assertEqual(28); + expect(isStudent).assertEqual(0); + + resultSets.close(); + } catch (err) { + console.error(TAG + `Query failed, code is ${err.code},message is ${err.message}`); + } + + console.log(TAG + "************* testDataSharePredicate_0001 end *************"); + }) + + it('testDataSharePredicate_0002', 0, async () => { + console.log(TAG + "************* testDataSharePredicate_0002 start *************"); + const valueBucket: relationalStore.ValuesBucket = { + 'name': 'Steven', + 'age': 20, + 'isStudent': false, + }; + let rowId = await rdbStore?.insert(table_name, valueBucket); + try { + let dp = new dataSharePredicates.DataSharePredicates(); + dp.equalTo("age", 20).orderByAsc("name"); + let resultSets = await (rdbStore as relationalStore.RdbStore).query(table_name, dp, ["*"]); + + expect(resultSets.rowCount).assertEqual(2); + expect(resultSets.goToRow(0)).assertEqual(true); + let id = resultSets.getLong(resultSets.getColumnIndex("id")); + let name = resultSets.getString(resultSets.getColumnIndex("name")); + let age = resultSets.getLong(resultSets.getColumnIndex("age")); + let isStudent = resultSets.getValue(resultSets.getColumnIndex("isStudent")); + expect(id).assertEqual(6); + expect(name).assertEqual("Steven"); + expect(age).assertEqual(20); + expect(isStudent).assertEqual(0); + expect(resultSets.goToNextRow()).assertEqual(true); + id = resultSets.getLong(resultSets.getColumnIndex("id")); + name = resultSets.getString(resultSets.getColumnIndex("name")); + age = resultSets.getLong(resultSets.getColumnIndex("age")); + isStudent = resultSets.getValue(resultSets.getColumnIndex("isStudent")); + expect(id).assertEqual(1); + expect(name).assertEqual("ZhangSan"); + expect(age).assertEqual(20); + expect(isStudent).assertEqual(1); + resultSets.close(); + } catch (err) { + console.error(TAG + `Query failed, code is ${err.code},message is ${err.message}`); + } + + console.log(TAG + "************* testDataSharePredicate_0002 end *************"); + }) + + it('testDataSharePredicate_0003', 0, async () => { + console.log(TAG + "************* testDataSharePredicate_0003 start *************"); + let dp = new dataSharePredicates.DataSharePredicates(); + dp.equalTo("name", "LiSi").and(); + const valueBucket: relationalStore.ValuesBucket = { + 'name': 'Steven', + 'age': 20, + 'isStudent': false, + }; + const valueBucket1: relationalStore.ValuesBucket = { + 'name': 'Steven', + 'age': 24, + 'isStudent': true, + }; + if (rdbStore != undefined) { + await rdbStore.update(table_name, valueBucket, dp); + await rdbStore.insert(table_name, valueBucket1); + } + + try { + dp = new dataSharePredicates.DataSharePredicates(); + dp.equalTo("name", "Steven").and().equalTo("age", 24); + let resultSets = await (rdbStore as relationalStore.RdbStore).query(table_name, dp, ["*"]); + + expect(resultSets.rowCount).assertEqual(1); + expect(resultSets.goToRow(0)).assertEqual(true); + let id = resultSets.getLong(resultSets.getColumnIndex("id")); + let name = resultSets.getString(resultSets.getColumnIndex("name")); + let age = resultSets.getLong(resultSets.getColumnIndex("age")); + let isStudent = resultSets.getValue(resultSets.getColumnIndex("isStudent")); + expect(id).assertEqual(6); + expect(name).assertEqual("Steven"); + expect(age).assertEqual(24); + expect(isStudent).assertEqual(1); + } catch (err) { + console.error(TAG + `Query failed, code is ${err.code},message is ${err.message}`); + } + + console.log(TAG + "************* testDataSharePredicate_0003 end *************"); + }) + + it('testDataSharePredicate_0004', 0, async () => { + console.log(TAG + "************* testDataSharePredicate_0004 start *************"); + try { + let dp = new dataSharePredicates.DataSharePredicates(); + dp.in("isStudent", [true, false]).limit(0, -1); + let resultSets = await (rdbStore as relationalStore.RdbStore).query(table_name, dp, ["*"]); + + expect(resultSets.rowCount).assertEqual(5); + } catch (err) { + console.error(TAG + `Query failed, code is ${err.code},message is ${err.message}`); + } + + console.log(TAG + "************* testDataSharePredicate_0004 end *************"); + }) + + it('testDataSharePredicate_0005', 0, async () => { + console.log(TAG + "************* testDataSharePredicate_0005 start *************"); + if (rdbStore != undefined) { + await insertMoreData; + } + try { + let dp = new dataSharePredicates.DataSharePredicates(); + dp.limit(1, -1); + let resultSets = await (rdbStore as relationalStore.RdbStore).query(table_name, dp, ["*"]); + expect(resultSets.rowCount).assertEqual(1); + expect(resultSets.goToRow(0)).assertEqual(true); + let id = resultSets.getLong(resultSets.getColumnIndex("id")); + let name = resultSets.getString(resultSets.getColumnIndex("name")); + let age = resultSets.getLong(resultSets.getColumnIndex("age")); + let isStudent = resultSets.getValue(resultSets.getColumnIndex("isStudent")); + expect(id).assertEqual(1); + expect(name).assertEqual("ZhangSan"); + expect(age).assertEqual(20); + expect(isStudent).assertEqual(1); + } catch (err) { + console.error(TAG + `Query failed, code is ${err.code},message is ${err.message}`); + } + + console.log(TAG + "************* testDataSharePredicate_0005 end *************"); + }) + + it('testDataSharePredicate_0006', 0, async () => { + console.log(TAG + "************* testDataSharePredicate_0006 start *************"); + if (rdbStore != undefined) { + await insertMoreData; + } + try { + let dp = new dataSharePredicates.DataSharePredicates(); + dp.limit(1, 3); + let resultSets = await (rdbStore as relationalStore.RdbStore).query(table_name, dp, ["*"]); + expect(resultSets.rowCount).assertEqual(1); + expect(resultSets.goToRow(0)).assertEqual(true); + let id = resultSets.getLong(resultSets.getColumnIndex("id")); + let name = resultSets.getString(resultSets.getColumnIndex("name")); + let age = resultSets.getLong(resultSets.getColumnIndex("age")); + let isStudent = resultSets.getValue(resultSets.getColumnIndex("isStudent")); + expect(id).assertEqual(4); + expect(name).assertEqual("SunLiu"); + expect(age).assertEqual(23); + expect(isStudent).assertEqual(0); + } catch (err) { + console.error(TAG + `Query failed, code is ${err.code},message is ${err.message}`); + } + + console.log(TAG + "************* testDataSharePredicate_0006 end *************"); + }) + + it('testDataSharePredicate_0007', 0, async () => { + console.log(TAG + "************* testDataSharePredicate_0007 start *************"); + if (rdbStore != undefined) { + await insertMoreData; + } + try { + let dp = new dataSharePredicates.DataSharePredicates(); + dp.limit(1, 12); + let resultSets = await (rdbStore as relationalStore.RdbStore).query(table_name, dp, ["*"]); + expect(resultSets.rowCount).assertEqual(0); + } catch (err) { + console.error(TAG + `Query failed, code is ${err.code},message is ${err.message}`); + } + + console.log(TAG + "************* testDataSharePredicate_0007 end *************"); + }) + }) +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/test/dataShareSubscribe.test.ets b/data_share/test/ets/data_share_ets/entry/src/main/ets/test/dataShareSubscribe.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..fd3451df031ecba6b505627bff31e3bcf56cb2de --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/test/dataShareSubscribe.test.ets @@ -0,0 +1,615 @@ + +/* + * Copyright (C) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level, Size, TestType } from "@ohos/hypium"; +import relationalStore from "@ohos.data.relationalStore"; +import dataSharePredicates from "@ohos.data.dataSharePredicates"; +import common from '@ohos.app.ability.common'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { BusinessError } from "@ohos.base"; +import dataShare from '@ohos.data.dataShare' +import { ValuesBucket } from '@ohos.data.ValuesBucket'; + +let TAG = "[dataShareSubscribeTest_test]"; +let context: common.UIAbilityContext; +let uri1 = ("datashare:///com.example.myapplication/test"); +let uri2 = ("datashareproxy://com.example.myapplication/entry/DB00/TBL00"); +let dataShareHelper: dataShare.DataShareHelper | undefined = undefined +let da = new dataSharePredicates.DataSharePredicates(); +da.equalTo("name", "WangWu"); +let va: ValuesBucket = { + "name": "WangWu", + "age": 20 +} + +let va_change: ValuesBucket = { + "name": "LiSi", + "age": 18 +} +let people: Array = new Array(1); +people[0] = { + name: 'ZhangSan', age: 31 +}; +let changeData: dataShare.ChangeInfo = { + type: dataShare.ChangeType.DELETE, uri: uri1, values: people +}; +let TEST_TIMEOUT = 2000 //means 2000ms.timeout occurs,testcases failed + +export default function DataShareSubscribeTest() { + describe('DataShareSubscribeTest', () => { + beforeAll(async () => { + context = AppStorage.get('TestAbilityContext') as common.UIAbilityContext; + console.info(TAG + 'beforeAll'); + }) + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + }) + afterEach(async () => { + console.info(TAG + 'afterEach'); + }) + afterAll(async () => { + console.info(TAG + 'afterAll'); + }) + + /** + * @tc.name: testNonSilentSubscribe001 + * @tc.desc: test Non-silent subscribe, then notifyChange uri + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: trigger the callback + */ + it('testNonSilentSubscribe001', 0, async (done:Function) => { + console.log(TAG + "************* testNonSilentSubscribe001 start *************"); + const timeoutTimer = setTimeout(() => { + console.log(TAG + "************* testNonSilentSubscribe001 timeout *************"); + try { + expect(false).assertTrue(); + } catch (err) { + done(err); + } + }, TEST_TIMEOUT); + let onCallback: () => void = (): void => { + console.log(TAG + "************* testNonSilentSubscribe001 callback *************"); + clearTimeout(timeoutTimer); + expect(true).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri1); + await dataShareHelper.on("dataChange", uri1, onCallback); + await dataShareHelper.notifyChange(uri1); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testNonSilentSubscribe001 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testNonSilentSubscribe001 end *************"); + }) + + /** + * @tc.name: testNonSilentSubscribe002 + * @tc.desc: test Non-silent subscribe with info, then notifyChange uri + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: trigger the callback with info + */ + it('testNonSilentSubscribe002', 0, async (done:Function) => { + console.log(TAG + "************* testNonSilentSubscribe002 start *************"); + const timeoutTimer = setTimeout(() => { + try { + expect(false).assertTrue(); + } catch (err) { + done(err); + } + }, TEST_TIMEOUT); + let onCallback = (error:BusinessError, ChangeInfo:dataShare.ChangeInfo) => { + console.log(TAG + "************* testNonSilentSubscribe002 callback *************"); + clearTimeout(timeoutTimer); + expect(true).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri1); + await dataShareHelper.on('dataChange', dataShare.SubscriptionType.SUBSCRIPTION_TYPE_EXACT_URI, uri1, onCallback); + await dataShareHelper.notifyChange(changeData); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testNonSilentSubscribe002 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testNonSilentSubscribe002 end *************"); + }) + + /** + * @tc.name: testNonSilentSubscribe003 + * @tc.desc: test Non-silent subscribe then cancel, and then notifyChange uri + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: no trigger the callback + */ + it('testNonSilentSubscribe003', 0, async (done:Function) => { + console.log(TAG + "************* testNonSilentSubscribe003 start *************"); + const timeoutTimer = setTimeout(() => { + expect(true).assertTrue(); + done(); + }, TEST_TIMEOUT); + let onCallback: () => void = (): void => { + console.log(TAG + "************* testNonSilentSubscribe003 callback *************"); + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri1); + await dataShareHelper.on("dataChange", uri1, onCallback); + await dataShareHelper.off("dataChange", uri1, onCallback); + await dataShareHelper.notifyChange(uri1); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testNonSilentSubscribe003 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testNonSilentSubscribe003 end *************"); + }) + + /** + * @tc.name: testNonSilentSubscribe004 + * @tc.desc: test Non-silent subscribe with info then cancel, and then notifyChange uri + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: no trigger the callback + */ + it('testNonSilentSubscribe004', 0, async (done:Function) => { + console.log(TAG + "************* testNonSilentSubscribe004 start *************"); + const timeoutTimer = setTimeout(() => { + expect(true).assertTrue(); + done(); + }, TEST_TIMEOUT); + let onCallback = (error:BusinessError, ChangeInfo:dataShare.ChangeInfo) => { + console.log(TAG + "************* testNonSilentSubscribe004 callback *************"); + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri1); + await dataShareHelper.on('dataChange', dataShare.SubscriptionType.SUBSCRIPTION_TYPE_EXACT_URI, uri1, onCallback); + await dataShareHelper.off('dataChange', dataShare.SubscriptionType.SUBSCRIPTION_TYPE_EXACT_URI, uri1, onCallback); + await dataShareHelper.notifyChange(changeData); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testNonSilentSubscribe004 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testNonSilentSubscribe004 end *************"); + }) + + /** + * @tc.name: testNonSilentSubscribe005 + * @tc.desc: test Non-silent subscribe with info and without info, and then notifyChange uri + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: trigger the callback + */ + it('testNonSilentSubscribe005', 0, async (done:Function) => { + console.log(TAG + "************* testNonSilentSubscribe005 start *************"); + const timeoutTimer = setTimeout(() => { + try { + expect(false).assertTrue(); + } catch (err) { + done(err); + } + }, TEST_TIMEOUT); + let onCallback1: () => void = (): void => { + clearTimeout(timeoutTimer); + console.log(TAG + "************* testNonSilentSubscribe005 callback *************"); + expect(true).assertTrue(); + done(); + } + let onCallback2 = (error:BusinessError, ChangeInfo:dataShare.ChangeInfo) => { + console.log(TAG + "************* testNonSilentSubscribe005 callback *************"); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri1); + await dataShareHelper.on("dataChange", uri1, onCallback1); + await dataShareHelper.on('dataChange', dataShare.SubscriptionType.SUBSCRIPTION_TYPE_EXACT_URI, uri1, onCallback2); + await dataShareHelper.notifyChange(uri1); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testNonSilentSubscribe005 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testNonSilentSubscribe005 end *************"); + }) + + /** + * @tc.name: testNonSilentSubscribe005 + * @tc.desc: test Non-silent subscribe with info and without info, and then notifyChange uri + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: trigger the callback whit info + */ + it('testNonSilentSubscribe006', 0, async (done:Function) => { + console.log(TAG + "************* testNonSilentSubscribe006 start *************"); + const timeoutTimer = setTimeout(() => { + try { + expect(false).assertTrue(); + } catch (err) { + done(err); + } + }, TEST_TIMEOUT); + let onCallback1: () => void = (): void => { + expect(true).assertTrue(); + } + let onCallback2 = (error:BusinessError, ChangeInfo:dataShare.ChangeInfo) => { + clearTimeout(timeoutTimer); + console.error(`**** Observer callback **** type: ${ChangeInfo.type}, uri: ${ChangeInfo.uri},values: ${ChangeInfo.values} `); + expect(ChangeInfo.type).assertEqual(1); + expect(ChangeInfo.uri).assertEqual(uri1); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri1); + await dataShareHelper.on("dataChange", uri1, onCallback1); + await dataShareHelper.on('dataChange', dataShare.SubscriptionType.SUBSCRIPTION_TYPE_EXACT_URI, uri1, onCallback2); + await dataShareHelper.notifyChange(changeData); + } catch (err) { + console.error(`testNonSilentSubscribe006 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + } + console.log(TAG + "************* testNonSilentSubscribe006 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe001 + * @tc.desc: test silent subscribe, and then insert data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: trigger the callback + */ + it('testSilentSubscribe001', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe001 start *************"); + const timeoutTimer = setTimeout(() => { + try { + expect(false).assertTrue(); + } catch (err) { + done(err); + } + }, TEST_TIMEOUT); + let onCallback: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(true).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.on("dataChange", uri2, onCallback); + await dataShareHelper.insert(uri2, va); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe001 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe001 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe002 + * @tc.desc: test silent subscribe, and then update data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: trigger the callback + */ + it('testSilentSubscribe002', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe002 start *************"); + const timeoutTimer = setTimeout(() => { + try { + expect(false).assertTrue(); + } catch (err) { + done(err); + } + }, TEST_TIMEOUT); + let onCallback: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(true).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.insert(uri2, va); + await dataShareHelper.on("dataChange", uri2, onCallback); + await dataShareHelper.update(uri2, da, va); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe002 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe002 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe003 + * @tc.desc: test silent subscribe, and then delete data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: trigger the callback + */ + it('testSilentSubscribe003', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe003 start *************"); + const timeoutTimer = setTimeout(() => { + try { + expect(false).assertTrue(); + } catch (err) { + done(err); + } + }, TEST_TIMEOUT); + let onCallback: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(true).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.insert(uri2, va); + await dataShareHelper.on("dataChange", uri2, onCallback); + await dataShareHelper.delete(uri2, da); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe003 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe003 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe004 + * @tc.desc: test silent subscribe then cancel, and then insert data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: no trigger the callback + */ + it('testSilentSubscribe004', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe004 start *************"); + const timeoutTimer = setTimeout(() => { + expect(true).assertTrue(); + done(); + }, TEST_TIMEOUT); + let onCallback: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.on("dataChange", uri2, onCallback); + await dataShareHelper.off("dataChange", uri2, onCallback); + await dataShareHelper.insert(uri2, va); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe004 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe004 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe005 + * @tc.desc: test silent subscribe then cancel, and then update data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: no trigger the callback + */ + it('testSilentSubscribe005', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe005 start *************"); + const timeoutTimer = setTimeout(() => { + expect(true).assertTrue(); + done(); + }, TEST_TIMEOUT); + let onCallback: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.insert(uri2, va); + await dataShareHelper.on("dataChange", uri2, onCallback); + await dataShareHelper.off("dataChange", uri2, onCallback); + await dataShareHelper.update(uri2, da, va); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe005 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe005 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe006 + * @tc.desc: test silent subscribe then cancel, and then delete data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: no trigger the callback + */ + it('testSilentSubscribe006', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe006 start *************"); + const timeoutTimer = setTimeout(() => { + expect(true).assertTrue(); + done(); + }, TEST_TIMEOUT); + let onCallback: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.insert(uri2, va); + await dataShareHelper.on("dataChange", uri2, onCallback); + await dataShareHelper.off("dataChange", uri2, onCallback); + await dataShareHelper.delete(uri2, da); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe006 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe006 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe007 + * @tc.desc: test silent subscribe whit info and without info then cancel, and then insert data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: no trigger the callback + */ + it('testSilentSubscribe007', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe007 start *************"); + const timeoutTimer = setTimeout(() => { + expect(true).assertTrue(); + done(); + }, TEST_TIMEOUT); + let onCallback1: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + let onCallback2: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.on("dataChange", uri2, onCallback1); + await dataShareHelper.on("dataChange", uri2, onCallback2); + await dataShareHelper.off("dataChange", uri2); + await dataShareHelper.insert(uri2, va); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe007 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe007 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe008 + * @tc.desc: test silent subscribe whit info and without info then cancel, and then updata data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: no trigger the callback + */ + it('testSilentSubscribe008', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe008 start *************"); + const timeoutTimer = setTimeout(() => { + expect(true).assertTrue(); + done(); + }, TEST_TIMEOUT); + let onCallback1: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + let onCallback2: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.insert(uri2, va); + await dataShareHelper.on("dataChange", uri2, onCallback1); + await dataShareHelper.on("dataChange", uri2, onCallback2); + await dataShareHelper.off("dataChange", uri2); + await dataShareHelper.update(uri2, da, va); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe008 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe008 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe009 + * @tc.desc: test silent subscribe whit info and without info then cancel, and then delete data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: no trigger the callback + */ + it('testSilentSubscribe009', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe009 start *************"); + const timeoutTimer = setTimeout(() => { + expect(true).assertTrue(); + done(); + }, TEST_TIMEOUT); + let onCallback1: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + let onCallback2: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.insert(uri2, va); + await dataShareHelper.on("dataChange", uri2, onCallback1); + await dataShareHelper.on("dataChange", uri2, onCallback2); + await dataShareHelper.off("dataChange", uri2); + await dataShareHelper.delete(uri2, da); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe009 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe009 end *************"); + }) + + }) +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/module.json b/data_share/test/ets/data_share_ets/entry/src/main/module.json new file mode 100644 index 0000000000000000000000000000000000000000..11028f0ac32bbfd01673314ad687897baee826af --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/module.json @@ -0,0 +1,92 @@ +{ + "module": { + "name": "testModule", + "type": "entry", + "srcEntrance": "./ets/Application/AbilityStage.ts", + "description": "$string:testModule_entry_dsc", + "mainElement": "com.example.myapplication.MainAbility", + "deviceTypes": [ + "default", + "tablet", + "2in1", + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "uiSyntax": "ets", + "pages": "$profile:main_pages", + "metadata": [ + { + "name": "MetaData1", + "value": "MetaDataValue", + "resource": "$profile:shortcuts_config" + } + ], + "abilities": [ + { + "name": "com.example.myapplication.MainAbility", + "srcEntrance": "./ets/MainAbility/MainAbility.ts", + "description": "$string:testModule_entry_main", + "icon": "$media:icon", + "label": "$string:entry_label", + "visible": true, + "launchType": "singleton", + "orientation": "portrait", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.GET_BUNDLE_INFO", + "reason": "$string:permission_reason", + "usedScene": { + "abilities": [ + "MainAbility" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.READ_CALENDAR", + "reason": "$string:permission_reason", + "usedScene": { + "abilities": [ + "MainAbility" + ], + "when": "inuse" + } + } + ], + "proxyData": [ + { + "uri": "datashareproxy://com.example.myapplication/entry/DB00/TBL00", + "requiredReadPermission": "ohos.permission.GET_BUNDLE_INFO", + "requiredWritePermission": "ohos.permission.GET_BUNDLE_INFO", + "metadata": { + "name": "dataProperties", + "resource": "$profile:test" + } + } + ], + "extensionAbilities": [ + { + "srcEntry": "./ets/DataShareExtensionAbility/DataShareExtAbility.ts", + "name": "DataShareExtAbility", + "icon": "$media:icon", + "description": "$string:description_application", + "type": "dataShare", + "uri": "datashare://com.example.myapplication", + "visible": true + } + ] + } +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/resources/base/element/string.json b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..a4e9ba5b8d282aa4e86eb9389bf7c535226fd1c4 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/element/string.json @@ -0,0 +1,44 @@ +{ + "string": [ + { + "name": "testModule_entry_dsc", + "value": "i am an entry for testModule" + }, + { + "name": "testModule_entry_main", + "value": "the testModule entry ability" + }, + { + "name": "entry_label", + "value": "ActsContextTest" + }, + { + "name": "form_description", + "value": "my form" + }, + { + "name": "serviceability_description", + "value": "my whether" + }, + { + "name": "description_application", + "value": "demo for test" + }, + { + "name": "app_name", + "value": "Demo" + }, + { + "name": "form_FormAbility_desc", + "value": "form_description" + }, + { + "name": "form_FormAbility_label", + "value": "form_label" + }, + { + "name": "permission_reason", + "value": "Need permission" + } + ] +} diff --git a/data_share/test/ets/data_share_ets/entry/src/main/resources/base/media/icon.png b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..474a55588fd7216113dd42073aadf254d4dba023 Binary files /dev/null and b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/media/icon.png differ diff --git a/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/form_config.json b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/form_config.json new file mode 100644 index 0000000000000000000000000000000000000000..e892d44722d9e5b09ff78cb069ccc15d1fac872e --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/form_config.json @@ -0,0 +1,6 @@ +{ + "src": [ + "MainAbility/pages/index/index", + "MainAbility/pages/second/second" + ] +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/form_config1.txt b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/form_config1.txt new file mode 100644 index 0000000000000000000000000000000000000000..32f9ff7dc213b28017875b2e4679071350a74d1d --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/form_config1.txt @@ -0,0 +1 @@ +{"src": ["MainAbility/pages/index/index","MainAbility/pages/second/second"]} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/invalid.txt b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/invalid.txt new file mode 100644 index 0000000000000000000000000000000000000000..cdca51a17bcbc5128c3b424ef9467ecd68b98737 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/invalid.txt @@ -0,0 +1,5 @@ +{ + "src": [ + "MainAbility/pages/index/index", + "MainAbility/pages/second/second" +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/main_pages.json b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..02221db61d317863114ff0ca4dd2b33586abff12 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,6 @@ +{ + "src": [ + "MainAbility/pages/index/index", + "MainAbility/pages/second/second" + ] +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/shortcuts_config.json b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/shortcuts_config.json new file mode 100644 index 0000000000000000000000000000000000000000..02221db61d317863114ff0ca4dd2b33586abff12 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/shortcuts_config.json @@ -0,0 +1,6 @@ +{ + "src": [ + "MainAbility/pages/index/index", + "MainAbility/pages/second/second" + ] +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/test.json b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/test.json new file mode 100644 index 0000000000000000000000000000000000000000..41973bba9bdc0a546129fad29ae3617230a877b2 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/test.json @@ -0,0 +1,4 @@ +{ +"path": "DB00/TBL00", +"type": "rdb" +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/signature/openharmony_sx.p7b b/data_share/test/ets/data_share_ets/signature/openharmony_sx.p7b new file mode 100644 index 0000000000000000000000000000000000000000..4109bba52aad41a4ac4fdaf811c8e328d648db26 Binary files /dev/null and b/data_share/test/ets/data_share_ets/signature/openharmony_sx.p7b differ diff --git a/relational_store/test/js/gdb/unittest/src/BUILD.gn b/data_share/test/fuzztest/BUILD.gn similarity index 65% rename from relational_store/test/js/gdb/unittest/src/BUILD.gn rename to data_share/test/fuzztest/BUILD.gn index 5ae4e3233429a1b1f2249050e6e410969c2f0d2f..2f688c02202c36c18be92ef5fc2ba41a2d8b3d5b 100644 --- a/relational_store/test/js/gdb/unittest/src/BUILD.gn +++ b/data_share/test/fuzztest/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (C) 2024 Huawei Device Co., Ltd. +# Copyright (c) 2025 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 @@ -12,18 +12,12 @@ # limitations under the License. import("//build/test.gni") +import("//foundation/distributeddatamgr/data_share/datashare.gni") -module_output_path = "relational_store/relational_store/gdb" - -ohos_js_unittest("GdbJsTest") { - module_out_path = module_output_path - - hap_profile = "../config.json" - - certificate_profile = "../openharmony_sx.p7b" -} - -group("unittest") { +group("fuzztest") { testonly = true - deps = [ ":GdbJsTest" ] -} + deps = [] + deps += [ + "//foundation/distributeddatamgr/data_share/test/fuzztest/datasharehelp_fuzzer:fuzztest", + ] +} \ No newline at end of file diff --git a/data_share/test/fuzztest/datasharehelp_fuzzer/BUILD.gn b/data_share/test/fuzztest/datasharehelp_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..11df5c1f55f8cacb2b7a489b2b600a62b585beea --- /dev/null +++ b/data_share/test/fuzztest/datasharehelp_fuzzer/BUILD.gn @@ -0,0 +1,78 @@ +# Copyright (c) 2025 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. + +##############################hydra-fuzz######################################## +import("//build/test.gni") +import("//build/config/features.gni") +import("//foundation/distributeddatamgr/data_share/datashare.gni") + +import("//build/ohos.gni") +import("//build/ohos_var.gni") +##############################fuzztest########################################## +ohos_fuzztest("DataShareHelpFuzzTest") { + module_out_path = "data_share/data_share" + fuzz_config_file = "//foundation/distributeddatamgr/data_share/test/fuzztest/datasharehelp_fuzzer" + + include_dirs = [ + "${datashare_innerapi_path}/consumer/include", + "${datashare_innerapi_path}/common/include", + "${datashare_common_native_path}/include", + "${datashare_native_proxy_path}/include", + ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ + "${datashare_common_native_path}/src/datashare_string_utils.cpp", + "${datashare_native_proxy_path}/src/data_share_service_proxy.cpp", + "datasharehelp_fuzzer.cpp", + ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer", + "${datashare_innerapi_path}/common:datashare_common", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_base:session_info", + "ability_runtime:extension_manager", + "c_utils:utils", + "hilog:libhilog", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "ipc:rpc", + "samgr:samgr_proxy", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + + deps += [ + # deps file + ":DataShareHelpFuzzTest", + ] +} +############################################################################### \ No newline at end of file diff --git a/kv_store/test/fuzztest/distributedkvdataservice_fuzzer/corpus/init b/data_share/test/fuzztest/datasharehelp_fuzzer/corpus/init similarity index 92% rename from kv_store/test/fuzztest/distributedkvdataservice_fuzzer/corpus/init rename to data_share/test/fuzztest/datasharehelp_fuzzer/corpus/init index 6198079a28e860189d4294f6598f8ac6804c0dff..7ade8a0faafeaedba7241e7d4a97b8e1f9691932 100644 --- a/kv_store/test/fuzztest/distributedkvdataservice_fuzzer/corpus/init +++ b/data_share/test/fuzztest/datasharehelp_fuzzer/corpus/init @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 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 diff --git a/data_share/test/fuzztest/datasharehelp_fuzzer/datasharehelp_fuzzer.cpp b/data_share/test/fuzztest/datasharehelp_fuzzer/datasharehelp_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d0c25516740b756be9d22a93888dce9108e385c2 --- /dev/null +++ b/data_share/test/fuzztest/datasharehelp_fuzzer/datasharehelp_fuzzer.cpp @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2025 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 "datasharehelp_fuzzer.h" +#include "datashare_helper.h" +#include "datashare_helper_impl.h" +#include "datashare_observer.h" + +#include +#include + +using namespace OHOS::DataShare; +namespace OHOS { + +template +class ConditionLock { +public: + explicit ConditionLock() {} + ~ConditionLock() {} +public: + void Notify(const T &data) + { + std::lock_guard lock(mutex_); + data_ = data; + isSet_ = true; + cv_.notify_one(); + } + + T Wait() + { + std::unique_lock lock(mutex_); + cv_.wait_for(lock, std::chrono::seconds(interval), [this]() { return isSet_; }); + T data = data_; + cv_.notify_one(); + return data; + } + + void Clear() + { + std::lock_guard lock(mutex_); + isSet_ = false; + cv_.notify_one(); + } + +private: + bool isSet_ = false; + T data_; + std::mutex mutex_; + std::condition_variable cv_; + static constexpr int64_t interval = 2; +}; + +class DataShareObserverTest : public DataShare::DataShareObserver { +public: + explicit DataShareObserverTest(std::string uri) + { + uri_ = uri; + } + ~DataShareObserverTest() {} + + void OnChange(const ChangeInfo &changeInfo) override + { + changeInfo_ = changeInfo; + data.Notify(changeInfo); + } + + void Clear() + { + changeInfo_.changeType_ = INVAILD; + changeInfo_.uris_.clear(); + changeInfo_.data_ = nullptr; + changeInfo_.size_ = 0; + changeInfo_.valueBuckets_ = {}; + data.Clear(); + } + + ChangeInfo changeInfo_; + ConditionLock data; + std::string uri_; +}; + +void CreateFuzz(FuzzedDataProvider &provider) +{ + sptr token = nullptr; + std::string strUri = provider.ConsumeRandomLengthString(); + std::string extUri = provider.ConsumeRandomLengthString(); + int waitTime = provider.ConsumeIntegral(); + DataShareHelper::Create(token, strUri, extUri, waitTime); +} + +void GetFileTypesFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + std::string mimeTypeFilter = provider.ConsumeRandomLengthString(); + dataShareHelperImpl.GetFileTypes(uri, mimeTypeFilter); +} + +void OpenFileFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + std::string mode = provider.ConsumeRandomLengthString(); + dataShareHelperImpl.OpenFile(uri, mode); +} + +void OpenRawFileFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + std::string mode = provider.ConsumeRandomLengthString(); + dataShareHelperImpl.OpenRawFile(uri, mode); +} + +void InsertExtFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + DataShareValuesBucket value; + std::string result = provider.ConsumeRandomLengthString(); + dataShareHelperImpl.InsertExt(uri, value, result); +} + +void BatchUpdateFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + UpdateOperations operations; + std::vector results = {}; + dataShareHelperImpl.BatchUpdate(operations, results); +} + +void QueryFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + DataSharePredicates predicates; + std::vector bytes; + const std::string bytes1 = provider.ConsumeRandomLengthString(); + const std::string bytes2 = provider.ConsumeRandomLengthString(); + bytes.emplace_back(bytes1); + bytes.emplace_back(bytes2); + DatashareBusinessError businessError; + dataShareHelperImpl.Query(uri, predicates, bytes, &businessError); +} + +void GetTypeFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + dataShareHelperImpl.GetType(uri); +} + +void BatchInsertFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + std::vector values = {}; + dataShareHelperImpl.BatchInsert(uri, values); +} + +void ExecuteBatchFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::vector statements = {}; + ExecResultSet result; + dataShareHelperImpl.ExecuteBatch(statements, result); +} + +void RegisterObserverFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + sptr dataObserver; + dataShareHelperImpl.RegisterObserver(uri, dataObserver); +} + +void UnregisterObserverFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + sptr dataObserver; + dataShareHelperImpl.UnregisterObserver(uri, dataObserver); +} + +void NotifyChangeFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + dataShareHelperImpl.NotifyChange(uri); +} + +void RegisterObserverExtProviderFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + bool isDescendants = provider.ConsumeBool(); + std::string observerUri = provider.ConsumeRandomLengthString(); + std::shared_ptr dataObserver = std::make_shared(observerUri); + dataShareHelperImpl.RegisterObserverExtProvider(uri, dataObserver, isDescendants); +} + +void UnregisterObserverExtProviderFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + std::string observerUri = provider.ConsumeRandomLengthString(); + std::shared_ptr dataObserver = std::make_shared(observerUri); + dataShareHelperImpl.UnregisterObserverExtProvider(uri, dataObserver); +} + +void NotifyChangeExtProviderFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + DataShareObserver::ChangeInfo changeInfo; + // changeInfo.changeType_ = provider.ConsumeEnum(); + dataShareHelperImpl.NotifyChangeExtProvider(changeInfo); +} + +void NormalizeUriFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + dataShareHelperImpl.NormalizeUri(uri); +} + +void DenormalizeUriFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + dataShareHelperImpl.DenormalizeUri(uri); +} + +void AddQueryTemplateFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uri = provider.ConsumeRandomLengthString(); + int64_t subscriberId = provider.ConsumeIntegral(); + Template tpl = Template(); + dataShareHelperImpl.AddQueryTemplate(uri, subscriberId, tpl); +} + +void DelQueryTemplateFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uri = provider.ConsumeRandomLengthString(); + int64_t subscriberId = provider.ConsumeIntegral(); + dataShareHelperImpl.DelQueryTemplate(uri, subscriberId); +} + +void GetPublishedDataFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uri = provider.ConsumeRandomLengthString(); + int64_t subscriberId = provider.ConsumeIntegral(); + dataShareHelperImpl.DelQueryTemplate(uri, subscriberId); +} + +void SubscribeRdbDataFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uri = provider.ConsumeRandomLengthString(); + std::vector uris; + const std::string uri1 = provider.ConsumeRandomLengthString(); + const std::string uei2 = provider.ConsumeRandomLengthString(); + TemplateId templateId; + std::function callback; + dataShareHelperImpl.SubscribeRdbData(uris, templateId, callback); +} + +void UnsubscribeRdbDataFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uri = provider.ConsumeRandomLengthString(); + std::vector uris; + const std::string uri1 = provider.ConsumeRandomLengthString(); + const std::string uei2 = provider.ConsumeRandomLengthString(); + TemplateId templateId; + dataShareHelperImpl.UnsubscribeRdbData(uris, templateId); +} + +void EnableRdbSubsFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uri = provider.ConsumeRandomLengthString(); + std::vector uris; + const std::string uri1 = provider.ConsumeRandomLengthString(); + const std::string uei2 = provider.ConsumeRandomLengthString(); + TemplateId templateId; + dataShareHelperImpl.EnableRdbSubs(uris, templateId); +} + +void DisableRdbSubsFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uri = provider.ConsumeRandomLengthString(); + std::vector uris; + const std::string uri1 = provider.ConsumeRandomLengthString(); + const std::string uei2 = provider.ConsumeRandomLengthString(); + TemplateId templateId; + dataShareHelperImpl.DisableRdbSubs(uris, templateId); +} + +void SubscribePublishedDataFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::vector uris; + const std::string uri1 = provider.ConsumeRandomLengthString(); + const std::string uei2 = provider.ConsumeRandomLengthString(); + int subscriberId = provider.ConsumeIntegral(); + std::function callback; + dataShareHelperImpl.SubscribePublishedData(uris, subscriberId, callback); +} + +void UnsubscribePublishedDataFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::vector uris; + const std::string uri1 = provider.ConsumeRandomLengthString(); + const std::string uei2 = provider.ConsumeRandomLengthString(); + int subscriberId = provider.ConsumeIntegral(); + dataShareHelperImpl.UnsubscribePublishedData(uris, subscriberId); +} + +void EnablePubSubsFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::vector uris; + const std::string uri1 = provider.ConsumeRandomLengthString(); + const std::string uei2 = provider.ConsumeRandomLengthString(); + int subscriberId = provider.ConsumeIntegral(); + dataShareHelperImpl.EnablePubSubs(uris, subscriberId); +} + +void DisablePubSubsFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::vector uris; + const std::string uri1 = provider.ConsumeRandomLengthString(); + const std::string uei2 = provider.ConsumeRandomLengthString(); + int subscriberId = provider.ConsumeIntegral(); + dataShareHelperImpl.DisablePubSubs(uris, subscriberId); +} + +void SetSilentSwitchFuzz(FuzzedDataProvider &provider) +{ + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + bool enable = provider.ConsumeBool(); + bool isSystem = provider.ConsumeBool(); + DataShareHelper::SetSilentSwitch(uri, enable, isSystem); +} + +void InsertExFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + DataShareValuesBucket value; + dataShareHelperImpl.InsertEx(uri, value); +} + +void UpdateExFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + DataSharePredicates predicates; + DataShareValuesBucket value; + dataShareHelperImpl.UpdateEx(uri, predicates, value); +} + +void DeleteExFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + DataSharePredicates predicates; + DataShareValuesBucket value; + dataShareHelperImpl.DeleteEx(uri, predicates); +} + +void UserDefineFuncFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + MessageParcel data; + MessageParcel reply; + MessageOption option; + dataShareHelperImpl.UserDefineFunc(data, reply, option); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::CreateFuzz(provider); + OHOS::GetFileTypesFuzz(provider); + OHOS::OpenFileFuzz(provider); + OHOS::OpenRawFileFuzz(provider); + OHOS::InsertExtFuzz(provider); + OHOS::BatchUpdateFuzz(provider); + OHOS::QueryFuzz(provider); + OHOS::GetTypeFuzz(provider); + OHOS::BatchInsertFuzz(provider); + OHOS::ExecuteBatchFuzz(provider); + OHOS::RegisterObserverFuzz(provider); + OHOS::UnregisterObserverFuzz(provider); + OHOS::NotifyChangeFuzz(provider); + OHOS::RegisterObserverExtProviderFuzz(provider); + OHOS::UnregisterObserverExtProviderFuzz(provider); + OHOS::NotifyChangeExtProviderFuzz(provider); + OHOS::NormalizeUriFuzz(provider); + OHOS::DenormalizeUriFuzz(provider); + OHOS::AddQueryTemplateFuzz(provider); + OHOS::DelQueryTemplateFuzz(provider); + OHOS::GetPublishedDataFuzz(provider); + OHOS::SubscribeRdbDataFuzz(provider); + OHOS::UnsubscribeRdbDataFuzz(provider); + OHOS::EnableRdbSubsFuzz(provider); + OHOS::DisableRdbSubsFuzz(provider); + OHOS::SubscribePublishedDataFuzz(provider); + OHOS::UnsubscribePublishedDataFuzz(provider); + OHOS::EnablePubSubsFuzz(provider); + OHOS::DisablePubSubsFuzz(provider); + OHOS::SetSilentSwitchFuzz(provider); + OHOS::InsertExFuzz(provider); + OHOS::UpdateExFuzz(provider); + OHOS::DeleteExFuzz(provider); + OHOS::UserDefineFuncFuzz(provider); + return 0; +} \ No newline at end of file diff --git a/data_share/test/fuzztest/datasharehelp_fuzzer/datasharehelp_fuzzer.h b/data_share/test/fuzztest/datasharehelp_fuzzer/datasharehelp_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..709233957270d15fc6786b0d6fd289c203370e43 --- /dev/null +++ b/data_share/test/fuzztest/datasharehelp_fuzzer/datasharehelp_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 DATA_SHARE_HELP_FUZZER_H +#define DATA_SHARE_HELP_FUZZER_H + +#define FUZZ_PROJECT_NAME "datasharehelp_fuzzer" + +#endif // DATA_SHARE_HELP_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/project.xml b/data_share/test/fuzztest/datasharehelp_fuzzer/project.xml similarity index 64% rename from relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/project.xml rename to data_share/test/fuzztest/datasharehelp_fuzzer/project.xml index 6d3e765c7dc1097ac2fb92d825dfad6b0b08636d..a37a23b1533f07ab59744732b0f46b2b5fd958d8 100644 --- a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/project.xml +++ b/data_share/test/fuzztest/datasharehelp_fuzzer/project.xml @@ -1,5 +1,5 @@ - - - - 1000 - - 300 - - 4096 - + + + 1000 + + 300 + + 4096 + \ No newline at end of file diff --git a/data_share/test/native/BUILD.gn b/data_share/test/native/BUILD.gn index d0f24cd319bdb3997ee831be3508a4d463b432f9..fb41ffa142c19d7255c8e331192c241f23865c9e 100644 --- a/data_share/test/native/BUILD.gn +++ b/data_share/test/native/BUILD.gn @@ -21,7 +21,16 @@ group("unittest") { deps += [ ":AbnormalBranchTest", ":ControllerTest", + ":DataProxyHandleTest", + ":DataShareAccessThresholdTest", + ":DataShareBlockWriterImplTest", + ":DataShareCommonTest", + ":DataShareConnectionTest", ":DataShareHelperImplTest", + ":DataShareHelperTest", + ":DataShareProxyTest", + ":DataShareStubTest", + ":DatashareItypesUtilsTest", ":ErrorCodeTest", ":JoinTest", ":NativeDataShareTest", @@ -53,23 +62,12 @@ config("permission_config") { } ohos_unittest("NativeDataShareTest") { - module_out_path = "data_share/native_datashare" + module_out_path = "data_share/data_share/inner_tests" visibility = [ ":*" ] include_dirs = [ - "//foundation/ability/ability_runtime/interfaces/inner_api/ability_manager/include", - "//foundation/ability/ability_runtime/interfaces/inner_api/app_manager/include/appmgr", - "//foundation/ability/ability_runtime/interfaces/inner_api/dataobs_manager/include", - "//foundation/ability/ability_runtime/interfaces/kits/native/ability/native", "./unittest/mediadatashare_test/include", - "//base/security/access_token/frameworks/common/include", - "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", - "//foundation/aafwk/standard/interfaces/innerkits/uri/include", - "//commonlibrary/c_utils/base/include", - "//utils/system/safwk/native/include", - "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", - "//third_party/json/include", "${datashare_native_proxy_path}/include", ] @@ -98,7 +96,6 @@ ohos_unittest("NativeDataShareTest") { "hitrace:hitrace_meter", "ipc:ipc_single", "relational_store:rdb_data_ability_adapter", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] @@ -110,16 +107,7 @@ ohos_unittest("NativeDataShareTest") { } ohos_unittest("PermissionTest") { - module_out_path = "data_share/native_datashare" - - include_dirs = [ - "${access_token_path}/frameworks/common/include", - "${base_hiviewdfx_hilog_path}/interfaces/native/innerkits/include", - "${commonlibrary_cutils_path}/base/include", - "${foundation_path}/aafwk/standard/interfaces/innerkits/uri/include", - "${foundation_path}/communication/ipc/interfaces/innerkits/ipc_core/include", - "${utils_system_safwk_path}/native/include", - ] + module_out_path = "data_share/data_share/inner_tests" sources = [ "./unittest/mediadatashare_test/src/permission_test.cpp" ] configs = [ ":permission_config" ] @@ -142,22 +130,12 @@ ohos_unittest("PermissionTest") { "common_event_service:cesfwk_innerkits", "hilog:libhilog", "ipc:ipc_single", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] } ohos_unittest("SlientAccessTest") { - module_out_path = "data_share/native_datashare" - - include_dirs = [ - "//base/security/access_token/frameworks/common/include", - "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", - "//foundation/aafwk/standard/interfaces/innerkits/uri/include", - "//commonlibrary/c_utils/base/include", - "//utils/system/safwk/native/include", - "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", - ] + module_out_path = "data_share/data_share/inner_tests" sources = [ "./unittest/mediadatashare_test/src/slientaccess_test.cpp" ] @@ -179,13 +157,12 @@ ohos_unittest("SlientAccessTest") { "common_event_service:cesfwk_innerkits", "hilog:libhilog", "ipc:ipc_single", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] } ohos_unittest("SlientSwitchTest") { - module_out_path = "data_share/native_datashare" + module_out_path = "data_share/data_share/inner_tests" sources = [ "./unittest/mediadatashare_test/src/slientswitch_test.cpp" ] @@ -206,22 +183,12 @@ ohos_unittest("SlientSwitchTest") { "common_event_service:cesfwk_innerkits", "hilog:libhilog", "ipc:ipc_single", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] } ohos_unittest("ErrorCodeTest") { - module_out_path = "data_share/native_datashare" - - include_dirs = [ - "//base/security/access_token/frameworks/common/include", - "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", - "//foundation/aafwk/standard/interfaces/innerkits/uri/include", - "//commonlibrary/c_utils/base/include", - "//utils/system/safwk/native/include", - "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", - ] + module_out_path = "data_share/data_share/inner_tests" sources = [ "./unittest/mediadatashare_test/src/errorcode_test.cpp" ] @@ -242,22 +209,12 @@ ohos_unittest("ErrorCodeTest") { "common_event_service:cesfwk_innerkits", "hilog:libhilog", "ipc:ipc_single", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] } ohos_unittest("JoinTest") { - module_out_path = "data_share/native_datashare" - - include_dirs = [ - "//base/security/access_token/frameworks/common/include", - "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", - "//foundation/aafwk/standard/interfaces/innerkits/uri/include", - "//commonlibrary/c_utils/base/include", - "//utils/system/safwk/native/include", - "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", - ] + module_out_path = "data_share/data_share/inner_tests" sources = [ "./unittest/mediadatashare_test/src/join_test.cpp" ] @@ -278,22 +235,12 @@ ohos_unittest("JoinTest") { "common_event_service:cesfwk_innerkits", "hilog:libhilog", "ipc:ipc_single", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] } ohos_unittest("ProxyDatasTest") { - module_out_path = "data_share/native_datashare" - - include_dirs = [ - "//base/security/access_token/frameworks/common/include", - "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", - "//foundation/aafwk/standard/interfaces/innerkits/uri/include", - "//commonlibrary/c_utils/base/include", - "//utils/system/safwk/native/include", - "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", - ] + module_out_path = "data_share/data_share/inner_tests" sources = [ "./unittest/datashareproxy_test/proxydatas_with_permission_test.cpp" ] @@ -314,22 +261,14 @@ ohos_unittest("ProxyDatasTest") { "c_utils:utils", "hilog:libhilog", "ipc:ipc_single", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] } ohos_unittest("ControllerTest") { - module_out_path = "data_share/native_datashare" + module_out_path = "data_share/data_share/inner_tests" include_dirs = [ - "${access_token_path}/frameworks/common/include", - "${base_hiviewdfx_hilog_path}/interfaces/native/innerkits/include", - "${foundation_path}/aafwk/standard/interfaces/innerkits/uri/include", - "${commonlibrary_cutils_path}/base/include", - "${utils_system_safwk_path}/native/include", - "${foundation_path}/communication/ipc/interfaces/innerkits/ipc_core/include", - "${thirdparty_json_path}/include", "${datashare_innerapi_path}/consumer/include", "${datashare_native_consumer_path}/controller/common", "${datashare_native_consumer_path}/controller/provider/include", @@ -362,24 +301,34 @@ ohos_unittest("ControllerTest") { "hitrace:hitrace_meter", "ipc:ipc_single", "relational_store:rdb_data_ability_adapter", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] } ohos_unittest("AbnormalBranchTest") { - module_out_path = "data_share/native_datashare" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "../../cfi_blocklist.txt" + } + + module_out_path = "data_share/data_share/inner_tests" include_dirs = [ - "${access_token_path}/frameworks/common/include", - "${base_hiviewdfx_hilog_path}/interfaces/native/innerkits/include", - "${foundation_path}/aafwk/standard/interfaces/innerkits/uri/include", - "${commonlibrary_cutils_path}/base/include", - "${utils_system_safwk_path}/native/include", - "${foundation_path}/communication/ipc/interfaces/innerkits/ipc_core/include", "//foundation/distributeddatamgr/data_share/frameworks/native/proxy/include/", "//foundation/distributeddatamgr/data_share/frameworks/native/common/include/", "${datashare_native_proxy_path}/include", + "${datashare_base_path}/test/native/unittest/mock", ] sources = [ "./unittest/mediadatashare_test/src/abnormal_branch_test.cpp" ] @@ -401,11 +350,11 @@ ohos_unittest("AbnormalBranchTest") { "access_token:libtoken_setproc", "c_utils:utils", "common_event_service:cesfwk_innerkits", + "googletest:gmock_main", "hilog:libhilog", "hitrace:hitrace_meter", "ipc:ipc_single", "relational_store:rdb_data_ability_adapter", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] @@ -417,7 +366,7 @@ ohos_unittest("AbnormalBranchTest") { } ohos_unittest("ValueProxyTest") { - module_out_path = "data_share/native_datashare" + module_out_path = "data_share/data_share/inner_tests" include_dirs = [ "${datashare_base_path}/frameworks/native/common/include/" ] @@ -435,7 +384,7 @@ ohos_unittest("ValueProxyTest") { } ohos_unittest("URIUtilsTest") { - module_out_path = "data_share/native_datashare" + module_out_path = "data_share/data_share/inner_tests" include_dirs = [ "${datashare_base_path}/frameworks/native/common/include/" ] @@ -456,7 +405,7 @@ ohos_unittest("URIUtilsTest") { } ohos_unittest("DataShareHelperImplTest") { - module_out_path = "data_share/native_datashare" + module_out_path = "data_share/data_share/inner_tests" include_dirs = [ "${datashare_native_consumer_path}/include", @@ -496,6 +445,7 @@ ohos_unittest("DataShareHelperImplTest") { "${datashare_native_proxy_path}/src/idata_share_client_death_observer.cpp", "${datashare_native_proxy_path}/src/published_data_subscriber_manager.cpp", "${datashare_native_proxy_path}/src/rdb_subscriber_manager.cpp", + "${datashare_native_proxy_path}/src/proxy_data_subscriber_manager.cpp", "./unittest/mediadatashare_test/src/datashare_helper_impl_test.cpp", ] @@ -515,11 +465,11 @@ ohos_unittest("DataShareHelperImplTest") { "hitrace:libhitracechain", "ipc:ipc_single", "ipc:rpc", + "kv_store:distributeddata_inner", + "relational_store:native_appdatafwk", "samgr:samgr_proxy", ] - public_external_deps = [ "kv_store:distributeddata_inner" ] - cflags = [ "-fvisibility=hidden", "-Dprivate=public", @@ -528,7 +478,7 @@ ohos_unittest("DataShareHelperImplTest") { } ohos_unittest("SharedBlockTest") { - module_out_path = "data_share/native_datashare" + module_out_path = "data_share/data_share/inner_tests" include_dirs = [ "${datashare_common_native_path}/include" ] @@ -540,6 +490,146 @@ ohos_unittest("SharedBlockTest") { "c_utils:utils", "googletest:gmock_main", "hilog:libhilog", + "ipc:ipc_single", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DataShareBlockWriterImplTest") { + module_out_path = "data_share/data_share/inner_tests" + + include_dirs = [ + "${datashare_native_consumer_path}/include", + "${datashare_common_native_path}/include", + "${datashare_innerapi_path}/consumer/include", + "${datashare_innerapi_path}/common/include", + "${datashare_innerapi_path}/provider/include", + "${datashare_native_consumer_path}/controller/provider/include", + "${datashare_native_consumer_path}/controller/common", + "${datashare_native_consumer_path}/controller/service/include", + "${datashare_native_proxy_path}/include", + ] + + sources = [ + "./unittest/mediadatashare_test/src/datashare_block_writer_impl_test.cpp", + ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:zuri", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "kv_store:distributeddata_inner", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DataShareHelperTest") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "../../cfi_blocklist.txt" + } + + module_out_path = "data_share/data_share/inner_tests" + + include_dirs = [ + "${datashare_base_path}/frameworks/native/common/include/", + "${datashare_base_path}/test/native/unittest/mock", + ] + + sources = [ "./unittest/mediadatashare_test/src/datashare_helper_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "googletest:gmock_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "ipc:rpc", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DataShareCommonTest") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "../../cfi_blocklist.txt" + } + + module_out_path = "data_share/data_share/inner_tests" + + include_dirs = [ "${datashare_base_path}/frameworks/native/common/include/" ] + + sources = [ "./unittest/mediadatashare_test/src/datashare_common_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "googletest:gmock_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_core", + "ipc:ipc_single", + "ipc:rpc", + "samgr:samgr_proxy", ] cflags = [ @@ -548,3 +638,278 @@ ohos_unittest("SharedBlockTest") { "-Dprotected=public", ] } + +ohos_unittest("DataShareProxyTest") { + module_out_path = "data_share/data_share/inner_tests" + + include_dirs = [ + "${datashare_innerapi_path}/consumer/include", + "${datashare_native_consumer_path}/controller/common", + "${datashare_native_consumer_path}/controller/provider/include", + "${datashare_native_consumer_path}/controller/service/include", + "${datashare_native_consumer_path}/include", + "${datashare_innerapi_path}/common/include", + "${datashare_native_proxy_path}/include", + ] + + sources = [ "./unittest/mediadatashare_test/src/datashare_proxy_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_single", + "relational_store:rdb_data_ability_adapter", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + } +} + +ohos_unittest("DataShareConnectionTest") { + module_out_path = "data_share/data_share/inner_tests" + + include_dirs = [ + "${datashare_innerapi_path}/consumer/include", + "${datashare_native_consumer_path}/controller/common", + "${datashare_native_consumer_path}/controller/provider/include", + "${datashare_native_consumer_path}/controller/service/include", + "${datashare_native_consumer_path}/include", + "${datashare_innerapi_path}/common/include", + "${datashare_native_proxy_path}/include", + ] + + sources = + [ "./unittest/mediadatashare_test/src/datashare_connection_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_single", + "relational_store:rdb_data_ability_adapter", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + } +} + +ohos_unittest("DataShareStubTest") { + module_out_path = "data_share/data_share/inner_tests" + + include_dirs = [ + "${datashare_innerapi_path}/consumer/include", + "${datashare_innerapi_path}/common/include", + "${datashare_native_provider_path}/include", + "${datashare_native_proxy_path}/include", + ] + + sources = [ "./unittest/mediadatashare_test/src/datashare_stub_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}:datashare_provider", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_single", + "ipc:ipc_napi", + "relational_store:rdb_data_ability_adapter", + "samgr:samgr_proxy", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "../../cfi_blocklist.txt" + } + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DatashareItypesUtilsTest") { + module_out_path = "data_share/data_share/inner_tests" + + include_dirs = [ "${datashare_common_native_path}/include" ] + + sources = + [ "./unittest/datashare_common_test/datashare_itypes_utils_test.cpp" ] + + deps = [ "${datashare_innerapi_path}/common:datashare_common_static" ] + + external_deps = [ + "ability_base:zuri", + "c_utils:utils", + "googletest:gmock_main", + "hilog:libhilog", + "ipc:ipc_single", + "kv_store:distributeddata_inner", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DataShareAccessThresholdTest") { + module_out_path = "data_share/data_share/inner_tests" + + sources = [ "./unittest/datashare_access_threshold_test/datashare_threshold_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer", + "${datashare_innerapi_path}/common:datashare_common", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "ipc:ipc_single", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DataProxyHandleTest") { + module_out_path = "data_share/data_share/inner_tests" + + include_dirs = [ "${datashare_base_path}/frameworks/native/common/include/" ] + + sources = [ "./unittest/dataproxy_handle_test/dataproxy_handle_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer", + "${datashare_innerapi_path}/common:datashare_common", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "googletest:gmock_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "ipc:rpc", + "samgr:samgr_proxy", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "../../cfi_blocklist.txt" + } + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/app.json5 b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c347ece5a13c320919810a099075b322c24ad355 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ +{ + "app": { + "bundleName": "com.acts.ohos.data.datasharetestclient1", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/resources/base/element/string.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..1080233f01384411ec684b58955cb8808746fdd3 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "MyApplication" + } + ] +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/resources/base/media/app_icon.png b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/resources/base/media/app_icon.png differ diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/entryability/EntryAbility.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..c82fc37d18c42bcae033248c962ff60f29fec0d7 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,45 @@ +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import hilog from '@ohos.hilog'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import Want from '@ohos.app.ability.Want'; +import window from '@ohos.window'; +import common from '@ohos.app.ability.common'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + AppStorage.setOrCreate("TestAbilityContext",this.context) + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/pages/Index.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..054f5d745797c2144acf0eea6080dd69f2550a0e --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,520 @@ +import { + connectDataShareExtAbility001, + connectDataShareExtAbility002, + disconnectDataShareExtAbility, + onRdb, + offRdb, + queryTest1, + queryTest2, + insertTest1, + insertTest2, + // queryTest, + // insertTest, + updateTest, + deleteTest, + offPublishData, + onPublishData, + getPublishedData, + publishTest, + publishTest2, + publishTest3, + offPublishDataErr1, + offPublishDataErr2, + GetCloneBundleInfoTest, + GetSelfBundleInfoTest +} from './myClient.test' +let result = undefined; +@Entry +@Component +struct Index { + @State message: string = "Main thread message filed" + + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('DataShareClient1 Ability Test') + .fontSize(20) + .fontWeight(FontWeight.Bold) + + Text(`${this.message}`) + .fontSize(25) + .height('15%') + .width('100%') + .textAlign(TextAlign.Center) + + Row() { + Button() { + Text('Connect') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Connect onclick enter') + this.message = 'Connect onclick' + await connectDataShareExtAbility001() + console.info('[ttt] [DataShareClientTest] <> Connect onclick leave') + }) + + Button() { + Text('Disconnect') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Disconnect onclick enter') + this.message = 'Disconnect onclick' + await disconnectDataShareExtAbility() + console.info('[ttt] [DataShareClientTest] <> Disconnect onclick leave') + }) + } + + // Row() { + // Button() { + // Text('Connect1') + // .fontSize(20) + // .fontWeight(FontWeight.Bold) + // }.type(ButtonType.Capsule) + // .margin({ + // top: 8 + // }) + // .width('45%') + // .height('8%') + // .backgroundColor('#0ddffb') + // .onClick(async () => { + // console.info('[ttt] [DataShareClientTest] <> Connect1 onclick enter') + // this.message = 'Connect1 onclick' + // await connectDataShareExtAbility001() + // console.info('[ttt] [DataShareClientTest] <> Connect1 onclick leave') + // }) + // + // Button() { + // Text('Connect2') + // .fontSize(20) + // .fontWeight(FontWeight.Bold) + // }.type(ButtonType.Capsule) + // .margin({ + // top: 8 + // }) + // .width('45%') + // .height('8%') + // .backgroundColor('#0ddffb') + // .onClick(async () => { + // console.info('[ttt] [DataShareClientTest] <> Connect2 onclick enter') + // this.message = 'Connect2 onclick' + // await connectDataShareExtAbility002() + // console.info('[ttt] [DataShareClientTest] <> Connect2 onclick leave') + // }) + // } + + Row() { + Button() { + Text('On') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> addTemplate onclick enter') + this.message = '~ addTemplate onclick' + try { + await onRdb(); + } catch (err) { + console.error('[ttt] [DataAbilityTest] Observer on catch(err)====>:' + err); + } + console.info('[ttt] [DataShareClientTest] <> addTemplate onclick leave') + }) + + Button() { + Text('Off') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Off onclick enter') + this.message = '~ Off onclick' + try { + await offRdb(); + } catch (err) { + console.error('[ttt] [DataAbilityTest] Observer Off catch(err)====>:' + err); + } + console.info('[ttt] [DataShareClientTest] <> Off onclick leave') + }) + // Button() { + // Text('Clone') + // .fontSize(20) + // .fontWeight(FontWeight.Bold) + // }.type(ButtonType.Capsule) + // .margin({ + // top: 8 + // }) + // .width('45%') + // .height('8%') + // .backgroundColor('#0ddffb') + // .onClick(async () => { + // console.info('[ttt] [DataShareClientTest] <> GetCloneBundleInfo onclick enter') + // this.message = '~ Off onclick' + // try { + // await GetCloneBundleInfoTest(); + // } catch (err) { + // console.error('[ttt] [DataAbilityTest] Observer GetCloneBundleInfo catch(err)====>:' + err); + // } + // console.info('[ttt] [DataShareClientTest] <> GetCloneBundleInfo onclick leave') + // }) + + } + + Row() { + Button() { + Text('Query1') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Query1 onclick enter') + this.message = '~ Query1 onclick' + try { + await queryTest1(); + } catch (err) { + console.error('[ttt] [DataAbilityTest] Observer Query1 catch(err)====>:' + err); + } + console.info('[ttt] [DataShareClientTest] <> Query1 onclick leave') + }) + + Button() { + Text('Query2') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Query2 onclick enter') + this.message = '~ Query2 onclick' + try { + await queryTest2(); + } catch (err) { + console.error('[ttt] [DataAbilityTest] Observer Query2 catch(err)====>:' + err); + } + console.info('[ttt] [DataShareClientTest] <> Query2 onclick leave') + }) + } + + Row() { + Button() { + Text('Insert1') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Insert1 onclick enter') + this.message = 'insert1 onclick' + let ret = await insertTest1() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> Insert1 onclick leave') + }) + + Button() { + Text('Insert2') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Insert2 onclick enter') + this.message = 'Insert2 onclick' + let ret = await insertTest2() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> Insert2 onclick leave') + }) + } + + // Row() { + // Button() { + // Text('Query') + // .fontSize(20) + // .fontWeight(FontWeight.Bold) + // }.type(ButtonType.Capsule) + // .margin({ + // top: 8 + // }) + // .width('45%') + // .height('8%') + // .backgroundColor('#0ddffb') + // .onClick(async () => { + // console.info('[ttt] [DataShareServerTest] <> Query onclick enter') + // this.message = 'Query onclick' + // let ret = await queryTest() + // this.message += "\n\n Test Result: " + ret; + // console.info('[ttt] [DataShareServerTest] <> Query onclick leave') + // }) + // + // Button() { + // Text('Insert') + // .fontSize(20) + // .fontWeight(FontWeight.Bold) + // }.type(ButtonType.Capsule) + // .margin({ + // top: 8 + // }) + // .width('45%') + // .height('8%') + // .backgroundColor('#0ddffb') + // .onClick(async () => { + // console.info('[ttt] [DataShareServerTest] <> Insert onclick enter') + // this.message = 'Insert onclick' + // let ret = await insertTest() + // this.message += "\n\n Test Result: " + ret; + // console.info('[ttt] [DataShareServerTest] <> Insert onclick leave') + // }) + // } + + Row() { + Button() { + Text('Update') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Update onclick enter') + this.message = 'Update onclick' + let ret = await updateTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> Update onclick leave') + }) + + Button() { + Text('Delete') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Delete onclick enter') + this.message = 'Delete onclick' + let ret = await deleteTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> Delete onclick leave') + }) + } + + Row() { + Button() { + Text('OffPublishData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> OffPublishData onclick enter') + this.message = 'OffPublishData onclick' + await offPublishData() + console.info('[ttt] [DataShareClientTest] <> OffPublishData onclick leave') + }) + + + Button() { + Text('OnPublishData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> OnPublishData onclick enter') + this.message = 'OnPublishData onclick' + onPublishData() + offPublishData() + console.info('[ttt] [DataShareClientTest] <> OnPublishData onclick leave') + }) + } + + Row() { + Button() { + Text('getPublishedData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> getPublishedData onclick enter') + this.message = 'getPublishedData onclick' + let ret = await getPublishedData() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> getPublishedData onclick leave') + }) + + Button() { + Text('Publish') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> publish onclick enter') + this.message = 'publish onclick' + let ret = await publishTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> publish onclick leave') + }) + } + + + // Row() { + // Button() { + // Text('Publish2.0') + // .fontSize(20) + // .fontWeight(FontWeight.Bold) + // }.type(ButtonType.Capsule) + // .margin({ + // top: 8 + // }) + // .width('45%') + // .height('8%') + // .backgroundColor('#0ddffb') + // .onClick(async () => { + // console.info('[ttt] [DataShareClientTest] <> Publish2.0 onclick enter') + // this.message = 'Publish2.0 onclick' + // let ret = await publishTest2() + // this.message += "\n\n Test Result: " + ret; + // console.info('[ttt] [DataShareClientTest] <> Publish2.0 onclick leave') + // }) + // + // + // Button() { + // Text('Publish3.0') + // .fontSize(20) + // .fontWeight(FontWeight.Bold) + // }.type(ButtonType.Capsule) + // .margin({ + // top: 8 + // }) + // .width('45%') + // .height('8%') + // .backgroundColor('#0ddffb') + // .onClick(async () => { + // console.info('[ttt] [DataShareClientTest] <> Publish3.0 onclick enter') + // this.message = 'Publish3.0 onclick' + // let ret = await publishTest3() + // this.message += "\n\n Test Result: " + ret; + // console.info('[ttt] [DataShareClientTest] <> Publish3.0 onclick leave') + // }) + // } + + Row() { + Button() { + Text('offPublishDataErr1') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> offPublishDataErr1 onclick enter') + this.message = 'offPublishDataErr1 onclick' + await offPublishDataErr1() + console.info('[ttt] [DataShareClientTest] <> offPublishDataErr1 onclick leave') + }) + + + Button() { + Text('offPublishDataErr2') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> offPublishDataErr2 onclick enter') + this.message = 'offPublishDataErr2 onclick' + await offPublishDataErr2() + console.info('[ttt] [DataShareClientTest] <> offPublishDataErr2 onclick leave') + }) + } + + } + .width('100%') + .height('100%') + } +} + diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/pages/myClient.test.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/pages/myClient.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..35cf84fc59896cf3aea4702a7f04b0e264893036 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/pages/myClient.test.ets @@ -0,0 +1,452 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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 dataShare from '@ohos.data.dataShare' +import dataSharePredicates from '@ohos.data.dataSharePredicates' +import { BusinessError } from '@ohos.base'; +import { ValuesBucket } from '@ohos.data.ValuesBucket'; +import rpc from '@ohos.rpc'; +import common from "@ohos.app.ability.common" +import bundleManager from '@ohos.bundle.bundleManager'; + +let cardUri = ("datashareproxy://com.acts.ohos.data.datasharetest/test"); +let cloneUri = ("datashareproxy://com.acts.ohos.data.datasharetest/test?appIndex=abcd"); + +let dsProxyHelper: dataShare.DataShareHelper | undefined = undefined +let dsProxyHelper2: dataShare.DataShareHelper | undefined = undefined + + +let context: common.UIAbilityContext +context = AppStorage.get("TestAbilityContext") as common.UIAbilityContext + +export async function connectDataShareExtAbility001() { + console.log("[ttt] [DataShareClientTest] <> connectDataShareExtAbility1 begin "); + dsProxyHelper = await dataShare.createDataShareHelper(context, cardUri, {isProxy : true}); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> DSHelper1 is null"); + } + console.log("[ttt] [DataShareClientTest] <> dsProxyHelper1 " + JSON.stringify(dsProxyHelper)); +} + +export async function connectDataShareExtAbility002() { + console.log("[ttt] [DataShareClientTest] <> connectDataShareExtAbility2 begin "); + dsProxyHelper2 = await dataShare.createDataShareHelper(context, cloneUri, {isProxy : true}); + if (dsProxyHelper2 == null) { + console.log("[ttt] [DataShareClientTest] <> DSHelper2 is null"); + } + console.log("[ttt] [DataShareClientTest] <> dsProxyHelper2 " + JSON.stringify(dsProxyHelper2)); +} + +export async function disconnectDataShareExtAbility() { + console.log("[ttt] [DataShareClientTest] <> disconnectDataShareExtAbility begin"); + dsProxyHelper = undefined; + console.log("[ttt] [DataShareClientTest] <> disconnectDataShareExtAbility end"); +} + + +export async function onRdb() { + console.log("[ttt] [DataShareClientTest] <> on begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> on end, DSHelper is null"); + return; + } + let template: dataShare.Template = { + predicates: { + "p1": "select name0 as name from TBL00", + "p2": "select name1 as name from TBL00", + }, + scheduler: "select remindTimer(strftime('%s', 'now', '+10 seconds'))" + } + dsProxyHelper.addTemplate(cardUri, "111", template); + let templateId: dataShare.TemplateId = { + subscriberId: "111", bundleNameOfOwner: "com.acts.ohos.data.datasharetestclient" + } + let result: Array = dsProxyHelper.on("rdbDataChange", [cardUri], templateId, onCallback); + console.log("[ttt] [DataShareClientTest] <> on end " + JSON.stringify(result)); +} + +export function onCallback(err:BusinessError, node:dataShare.RdbDataChangeNode) { + console.info("[ttt] [DataShareClientTest] [callback] rdb change ININ"); + // console.info("[ttt] [DataShareClientTest] [callback] " + JSON.stringify(node.uri)); + // console.info("[ttt] [DataShareClientTest] [callback] " + JSON.stringify(node.templateId)); + // console.info("[ttt] [DataShareClientTest] [callback] insert length is " + node.data.length); + for (let i = 0; i < node.data.length; i++) { + // console.info("[ttt] [DataShareClientTest] [callback] " + typeof node.data[i]); + console.info("[ttt] [DataShareClientTest] [callback] " + node.data[i]); + } + +} + +export async function offRdb() { + console.log("[ttt] [DataShareClientTest] <> off begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> off end, DSHelper is null"); + return; + } + let templateId:dataShare.TemplateId = {subscriberId:"111", bundleNameOfOwner:"com.acts.ohos.data.datasharetestclient"} + let result:Array = dsProxyHelper.off("rdbDataChange", [cardUri], templateId); + console.log("[ttt] [DataShareClientTest] <> off end " + JSON.stringify(result)); +} + +export async function queryTest1() { + console.log("[ttt] [DataShareClientTest] <> query1 begin"); + let da = new dataSharePredicates.DataSharePredicates(); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + let count = 0; + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> query1 end, DSHelper1 is null"); + return; + } + let result = await dsProxyHelper.query(cardUri, da, ["*"]); + if (result != undefined) { + count = result.rowCount; + console.log("[ttt] [DataShareClientTest] <> query1 end, result:" + JSON.stringify(result)); + } + console.log("[ttt] [DataShareClientTest] <> query1 end, count222:" + count); + return count; +} + +export async function queryTest2() { + console.log("[ttt] [DataShareClientTest] <> query2 begin"); + let da = new dataSharePredicates.DataSharePredicates(); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + let count = 0; + if (dsProxyHelper2 == null) { + console.log("[ttt] [DataShareClientTest] <> query2 end, DSHelper2 is null"); + return; + } + let result = await dsProxyHelper2.query(cloneUri, da, ["*"]); + if (result != undefined) { + count = result.rowCount; + console.log("[ttt] [DataShareClientTest] <> query2 end, result:" + JSON.stringify(result)); + } + console.log("[ttt] [DataShareClientTest] <> query2 end, count222:" + count); + return count; +} + +export async function insertTest1() { + console.log("[ttt] [DataShareClientTest] <> insert1 begin"); + // dsProxyHelper = await dataShare.createDataShareHelper(context, cardUri, {isProxy : true}); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> insert1 end, DSHelper is null"); + return; + } + + let i = 0; + let ret = 0; + for (i = 0; i < 2; i++) { + let vb: ValuesBucket = { + "name0": "name0" + i, + "name1": "name1" + i, + "name2": "name2" + i, + "name3": "name3" + i, + "name4": "name4" + i, + "name5": "name5" + i, + "name6": "name6" + i, + "name7": "name7" + i, + "name8": "name8" + i, + "name9": "name9" + i, + }; + ret = await dsProxyHelper.insert(cardUri, vb); + console.log("[ttt] [DataShareClientTest] <> insert1 end rowNum is " + ret); + } + return ret; +} + +export async function insertTest2() { + console.log("[ttt] [DataShareClientTest] <> insert2 begin"); + if (dsProxyHelper2 == null) { + console.log("[ttt] [DataShareClientTest] <> insert2 end, DSHelper2 is null"); + return; + } + + let i = 0; + let ret = 0; + for (i = 0; i < 2; i++) { + let vb: ValuesBucket = { + "name0": "name0" + i, + "name1": "name1" + i, + "name2": "name2" + i, + "name3": "name3" + i, + "name4": "name4" + i, + "name5": "name5" + i, + "name6": "name6" + i, + "name7": "name7" + i, + "name8": "name8" + i, + "name9": "name9" + i, + }; + ret = await dsProxyHelper2.insert(cloneUri, vb); + console.log("[ttt] [DataShareClientTest] <> insert2 end rowNum is " + ret); + } + return ret; +} + +export async function updateTest() { + console.log("[ttt] [DataShareClientTest] <> update begin"); + if (dsProxyHelper2 == null) { + console.log("[ttt] [DataShareClientTest] <> update end, DSHelper is null"); + return; + } + console.log("[ttt] [DataShareClientTest] <> update begin RPF666"); + let da = new dataSharePredicates.DataSharePredicates(); + console.log("[ttt] [DataShareClientTest] <> update begin RPF777"); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + let ret = dsProxyHelper2.update(cloneUri, da, { "name0": "ZhangSan" }); + console.log("[ttt] [DataShareClientTest] <> update end, result:" + ret); + return ret; +} + +export async function batchUpdate() { + console.log("[ttt] [DataShareClientTest] <> update begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> update end, DSHelper is null"); + return; + } + + console.log("[ttt] [DataShareClientTest] <> update begin RPF666"); + let da = new dataSharePredicates.DataSharePredicates(); + console.log("[ttt] [DataShareClientTest] <> update begin RPF777"); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + // let ret = dsProxyHelper.update(cardUri, da, { "name0": "ZhangSan" }); + // console.log("[ttt] [DataShareClientTest] <> update end, result:" + ret); + // return ret; +} + +export async function deleteTest() { + console.log("[ttt] [DataShareClientTest] <> delete begin"); + if (dsProxyHelper2 == null) { + console.log("[ttt] [DataShareClientTest] <> delete end, DSHelper is null"); + return; + } + let da = new dataSharePredicates.DataSharePredicates(); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + let ret = await dsProxyHelper2.delete(cloneUri, da); + console.log("[ttt] [DataShareClientTest] <> delete end, result:" + ret); + return ret; +} + +export async function offPublishData() { + console.log("[ttt] [DataShareClientTest] <> offPublishData begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> on end, DSHelper is null"); + return; + } + + try{ + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", "datashareproxy://com.acts.ohos.data.datasharetest/test"]; + let result: Array = dsProxyHelper.off("publishedDataChange", + uris, + "11", onPublishCallback); + console.log("[ttt] [DataShareClientTest] <> off end " + JSON.stringify(result)); + }catch(err){ + console.error(` [ttt] offPublishData error: code: ${err.code}, message: ${err.message} `); + } +} + +export async function offPublishDataErr1() { + console.log("[ttt] [DataShareClientTest] <> offPublishDataErr1 begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> on end, DSHelper is null"); + return; + } + + try{ + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", "datashareproxy://com.acts.ohos.data.datasharetest/test"]; + let result: Array = dsProxyHelper.off("publishedDataChange", + uris, + "11", undefined); + console.log("[ttt] [DataShareClientTest] <> off end " + JSON.stringify(result)); + }catch(err){ + console.error(` [ttt] offPublishDataErr1 error: code: ${err.code}, message: ${err.message} `); + } +} + + +export async function offPublishDataErr2() { + console.log("[ttt] [DataShareClientTest] <> off begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> off end, DSHelper is null"); + return; + } + let templateId:dataShare.TemplateId = {subscriberId:"111", bundleNameOfOwner:"com.acts.ohos.data.datasharetestclient"} + try{ + let result:Array = dsProxyHelper.off("rdbDataChange", [cardUri], templateId,undefined); + console.log("[ttt] [DataShareClientTest] <> off end " + JSON.stringify(result)); + }catch(err){ + console.error(` [ttt] offPublishDataErr2 error: code: ${err.code}, message: ${err.message} `); + } + + +} + +export function onPublishCallback(err:BusinessError, node:dataShare.PublishedDataChangeNode) { + console.info("[ttt] [DataShareClientTest] [callback] publishedData change ININ"); + // console.info("[ttt] [DataShareClientTest] [callback] bundleName " + JSON.stringify(node.bundleName)); + console.info("[ttt] [DataShareClientTest] [callback] data size" + node.data.length); + for (let i = 0; i < node.data.length; i++) { + // console.info("[ttt] [DataShareClientTest] [callback]" + typeof node.data[i].data); + console.info("[ttt] [DataShareClientTest] [callback] data " + i + " " + JSON.stringify(node.data[i])); + } +} + +export async function onPublishData() { + console.log("[ttt] [DataShareClientTest] <> onPublishData begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> on end, DSHelper is null"); + return; + } + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", "datashareproxy://com.acts.ohos.data.datasharetest/test"]; + try { + console.log("[ttt] [DataShareClientTest] <> on begin"); + let result: Array = dsProxyHelper.on("publishedDataChange", uris, "11", onPublishCallback); + console.log("[ttt] [DataShareClientTest] <> on end " + JSON.stringify(result)); + } catch (e) { + console.log("[ttt] [DataShareClientTest] <> on err " + JSON.stringify(e)); + + } +} + +export async function getPublishedData() { + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> getPublishedData end, DSHelper is null"); + return; + } + console.log("[ttt] [DataShareClientTest] <> getPublishedData begin"); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + let ret = publishedData.length; + console.log("[ttt] [DataShareClientTest] <> getPublishedData end dataSize is " + ret); + console.log("[ttt] [DataShareClientTest] <> getPublishedData end data is " + JSON.stringify(publishedData)); + return ret; +} + + +export async function publishTest() { + console.log("[ttt] [DataShareClientTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key: "city", subscriberId: "11", data: "xian" + Math.random()}, + {key: "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key: "empty", subscriberId: "11", data: "nobody sub" + Math.random()}, + {key: "datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub " + Math.random()}]; + + let nums:number[] = [1,2,3]; + try { + // let ashmem = rpc.Ashmem.create("ashmem", (nums.length) * 4); + // console.log("[ttt] [DataShareClientTest] <> " + JSON.stringify(ashmem)); + // ashmem.mapReadWriteAshmem(); + // console.log("[ttt] [DataShareClientTest] <> "); + // console.log("[ttt] [DataShareClientTest] <> " + JSON.stringify(nums)); + // ashmem.writeAshmem(nums, nums.length, 0); + // console.log("[ttt] [DataShareClientTest] <> "); + + console.log("[ttt] [DataShareClientTest] <> data length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest"); + console.log("[ttt] [DataShareClientTest] <> publish end " + JSON.stringify(result)); + // ashmem.closeAshmem(); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareClientTest] <> getPublishedData end " + JSON.stringify(publishedData)); + // for (let i = 0; i < publishedData.length; i++) { + // console.info("[ttt][callback] " + typeof publishedData[i].data); + // if (typeof publishedData[i].data != 'string') { + // let ash:rpc.Ashmem = publishedData[i].data; + // ash.mapReadonlyAshmem(); + // console.info("[ttt][callback] " + JSON.stringify(ash.readAshmem(ash.getAshmemSize()/4, 0))); + // ash.closeAshmem(); + // } + // } + } catch (e) { + console.log("[ttt] [DataShareClientTest] <> publish error " + JSON.stringify(e)); + } +} + +export async function publishTest2() { + console.log("[ttt] [DataShareClientTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key:"city", subscriberId:"11", data:"xianServer22222"}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key:"empty", subscriberId:"11", data:"nobody sub Server"+222222}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub Server"+Math.random()}]; + + let nums:number[] = [1,2,3]; + try { + console.log("[ttt] [DataShareClientTest] <> datasss length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest",2); + console.log("[ttt] [DataShareClientTest] <> publish end " + JSON.stringify(result)); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareClientTest] <> getPublishedData end " + JSON.stringify(publishedData)); + } catch (e) { + console.log("[ttt] [DataShareClientTest] <> publish error " + JSON.stringify(e)); + } +} + +export async function publishTest3() { + console.log("[ttt] [DataShareClientTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key:"city", subscriberId:"11", data:"xianClient3333333"}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key:"empty", subscriberId:"11", data:"nobody sub Client"+33333}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub Server"+Math.random()}]; + + try { + console.log("[ttt] [DataShareClientTest] <> datasss length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest",3); + console.log("[ttt] [DataShareClientTest] <> publish end " + JSON.stringify(result)); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareClientTest] <> getPublishedData end " + JSON.stringify(publishedData)); + } catch (e) { + console.log("[ttt] [DataShareClientTest] <> publish error " + JSON.stringify(e)); + } +} + +export async function GetCloneBundleInfoTest() { + console.log("[ttt] [DataShareClientTest] <> GetCloneBundleInfoTest begin"); + let bundleName = ("com.acts.ohos.data.datasharetest"); + let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_EXTENSION_ABILITY | + bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_HAP_MODULE; + let appIndex = 1; + try { + bundleManager.getAppCloneBundleInfo(bundleName, appIndex, bundleFlags) .then((data) => { + console.log("[ttt] [DataShareClientTest] <> hapModuleInfos is:", JSON.stringify(data)); + }) + } catch (err) { + console.log("[ttt] [DataShareClientTest] <> publish error " + JSON.stringify(err)); + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/module.json5 b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..211c03c8dab7ce97142b79d87a31e55d1f43a8a8 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/module.json5 @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ + { + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:icon", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED" + } + ] + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/element/color.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..82f853ffef34a3b56ced931281ad3b76ef7f3025 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/element/string.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..7ff1694425d455890bdb2767a4dec4ee3053549a --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/media/icon.png b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/media/icon.png differ diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/media/startlcon.png b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/media/startlcon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/media/startlcon.png differ diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/profile/main_pages.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/en_US/element/string.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..7ff1694425d455890bdb2767a4dec4ee3053549a --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/zh_CN/element/string.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..ccec2cf1b1bc163bf02190852c28712ef46d161e --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/test/Ability.test.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..6e4fa69a95210d55773396d99d25cca40b5f189a --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,35 @@ +import hilog from '@ohos.hilog'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/test/List.test.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..5be61a34201c29a43f6ceb6cefa817819b567262 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,5 @@ +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testability/TestAbility.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testability/TestAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..5f77ecd9125b1b768f2fa7c557b79382cb159e59 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testability/TestAbility.ets @@ -0,0 +1,50 @@ +import UIAbility from '@ohos.app.ability.UIAbility'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import hilog from '@ohos.hilog'; +import { Hypium } from '@ohos/hypium'; +import testsuite from '../test/List.test'; +import window from '@ohos.window'; +import Want from '@ohos.app.ability.Want'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; + +export default class TestAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate'); + hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? ''); + hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? ''); + let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator; + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs; + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments(); + hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!'); + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite); + } + + onDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate'); + windowStage.loadContent('testability/pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', + JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); + } + + onForeground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); + } + + onBackground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testability/pages/Index.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testability/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..2477432359278ee01f295d036fe4f7306c9e5912 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testability/pages/Index.ets @@ -0,0 +1,17 @@ +@Entry +@Component +struct Index { + @State message: string = 'Hello World'; + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets new file mode 100644 index 0000000000000000000000000000000000000000..1e10d5b9788de31cfd99c8f96e864537061d7692 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets @@ -0,0 +1,47 @@ +import hilog from '@ohos.hilog'; +import TestRunner from '@ohos.application.testRunner'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import Want from '@ohos.app.ability.Want'; + +let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator | undefined = undefined +let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs | undefined = undefined + +async function onAbilityCreateCallback() { + hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err : Error) { + hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? ''); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare '); + } + + async onRun() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run'); + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + const bundleName = abilityDelegatorArguments.bundleName; + const testAbilityName = 'TestAbility'; + let lMonitor: AbilityDelegatorRegistry.AbilityMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + const want: Want = { + bundleName: bundleName, + abilityName: testAbilityName + }; + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + abilityDelegator.startAbility(want, (err, data) => { + hilog.info(0x0000, 'testTag', 'startAbility : err : %{public}s', JSON.stringify(err) ?? ''); + hilog.info(0x0000, 'testTag', 'startAbility : data : %{public}s',JSON.stringify(data) ?? ''); + }) + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end'); + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/module.json5 b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..26ca5ed16328fa4b6c28dd61db802fb6a194705e --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/module.json5 @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ +{ + "module": { + "name": "entry_test", + "type": "feature", + "description": "$string:module_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:test_pages", + "abilities": [ + { + "name": "TestAbility", + "srcEntry": "./ets/testability/TestAbility.ets", + "description": "$string:TestAbility_desc", + "icon": "$media:icon", + "label": "$string:TestAbility_label", + "exported": true, + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ] + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/element/color.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..82f853ffef34a3b56ced931281ad3b76ef7f3025 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/element/string.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..039de6a76ac7a8526662df74d443e16dee29764a --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_test_desc", + "value": "test ability description" + }, + { + "name": "TestAbility_desc", + "value": "the test ability" + }, + { + "name": "TestAbility_label", + "value": "test label" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/media/icon.png b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/media/icon.png differ diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/profile/test_pages.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/profile/test_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..b7e7343cacb32ce982a45e76daad86e435e054fe --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/profile/test_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "testability/pages/Index" + ] +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/test/List.test.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..fb01f7322d950848059aca8f3ab5a6e1bcdb0195 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/test/List.test.ets @@ -0,0 +1,5 @@ +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/test/LocalUnit.test.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..3711b5233ab3d6b772ef3896f6eae4826ba1962f --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,33 @@ +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest',() => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/src/db_helper.cpp b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/hvigor/hvigor-config.json5 similarity index 35% rename from relational_store/frameworks/native/gdb/src/db_helper.cpp rename to data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/hvigor/hvigor-config.json5 index 4446592020756adf020db9386eec256f3d4ca7d2..cc3ef51a3b22ba480542fe88ce5c78110faaf9e1 100644 --- a/relational_store/frameworks/native/gdb/src/db_helper.cpp +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/hvigor/hvigor-config.json5 @@ -1,7 +1,7 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (C) 2025 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 not \tuse 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 @@ -12,24 +12,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include - -#include "gdb_errors.h" -#include "db_store_manager.h" -#include "db_trace.h" -#include "gdb_helper.h" - -namespace OHOS::DistributedDataAip { - -std::shared_ptr GDBHelper::GetDBStore(const StoreConfig &config, int &errCode) { - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - return StoreManager::GetInstance().GetDBStore(config, errCode); + "modelVersion": "5.0.0", + "dependencies": { + "@ohos/hvigor-ohos-online-sign-plugin": "4.0.1", + }, + "execution": { + // "daemon": true, /* Enable daemon compilation. Default: true */ + // "incremental": true, /* Enable incremental compilation. Default: true */ + // "parallel": true, /* Enable parallel compilation. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Default: false */ + } } - -int GDBHelper::DeleteDBStore(const StoreConfig &config) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - return StoreManager::GetInstance().Delete(config.GetFullPath()) ? E_OK : E_ERROR; -} -} // namespace OHOS::DistributedDataAip \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/sign/openharmony_sx.p7b b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/sign/openharmony_sx.p7b new file mode 100644 index 0000000000000000000000000000000000000000..4512fc0e7c36f20aa275736dce5631c304a80dc0 Binary files /dev/null and b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/sign/openharmony_sx.p7b differ diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/AppScope/app.json5 b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..24b4376adb2d4d56911cf5965713920f5eed37d5 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/AppScope/app.json5 @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ +{ + "app": { + "bundleName": "com.acts.ohos.data.datasharetest", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name", + "multiAppMode": { + "multiAppModeType": "appClone", + "maxCount": 2 + } + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/AppScope/resources/base/element/string.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..1080233f01384411ec684b58955cb8808746fdd3 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "MyApplication" + } + ] +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/AppScope/resources/base/media/app_icon.png b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/AppScope/resources/base/media/app_icon.png differ diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/DataShareExtAbility/DataShareExtAbility.ts b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/DataShareExtAbility/DataShareExtAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..aaf4fb83bb3bbf03c25c840501808344dc87a44f --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/DataShareExtAbility/DataShareExtAbility.ts @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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 Extension from '@ohos.application.DataShareExtensionAbility' +import rdb from '@ohos.data.relationalStore'; + +const STORE_CONFIG = { + name: "DB00.db", + securityLevel: rdb.SecurityLevel.S1, +} +let TBL_NAME = "TBL00"; +let DROP_TBL = "DROP TABLE IF EXISTS " + TBL_NAME; +let DDL_TBL_CREATE = "CREATE TABLE IF NOT EXISTS " ++ TBL_NAME ++ " (id INTEGER PRIMARY KEY AUTOINCREMENT, name0 TEXT, name1 TEXT, name2 TEXT, name3 TEXT, name4 TEXT, name5 TEXT, name6 TEXT, " + +"name7 TEXT, name8 TEXT, name9 TEXT, age INTEGER, phoneNumber DOUBLE, isStudent BOOLEAN, Binary BINARY)"; + +let rdbStore; + +export default class DataShareExtAbility extends Extension { + + async onCreate(want, callback) { + console.log("[ttt] [DataShareTest] DataShareExtAbility onCreate this.context.databaseDir:" + this.context.databaseDir); + rdbStore = await rdb.getRdbStore(this.context.getApplicationContext(), STORE_CONFIG); + await rdbStore.executeSql(DROP_TBL, []); + await rdbStore.executeSql(DDL_TBL_CREATE, []); + let err = {"code":0}; + callback(err); + } +}; \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/entryability/EntryAbility.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..dc337eb7295d0192c47510865054351260999f11 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,72 @@ +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import hilog from '@ohos.hilog'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import Want from '@ohos.app.ability.Want'; +import window from '@ohos.window'; +import common from '@ohos.app.ability.common'; +import rdb from '@ohos.data.relationalStore'; + +interface GeneratedObjectLiteralInterface_1 { + name: string; + securityLevel: rdb.SecurityLevel; +} + +const STORE_CONFIG: GeneratedObjectLiteralInterface_1 = { + name: "DB00.db", + securityLevel: rdb.SecurityLevel.S1, +} + +let TBL_NAME = "TBL00"; +let DROP_TBL = "DROP TABLE IF EXISTS " + TBL_NAME; +let DDL_TBL_CREATE = "CREATE TABLE IF NOT EXISTS " + + TBL_NAME + + " (id INTEGER PRIMARY KEY AUTOINCREMENT, name0 TEXT, name1 TEXT, name2 TEXT, name3 TEXT, name4 TEXT, name5 TEXT, name6 TEXT, " + + "name7 TEXT, name8 TEXT, name9 TEXT, age INTEGER, phoneNumber DOUBLE, isStudent BOOLEAN, Binary BINARY)"; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + console.log("[ttt] [DataShareServerTest]" + this.context.databaseDir); + AppStorage.setOrCreate("TestAbilityContext",this.context) + this.onCreate1(); + } + + async onCreate1() { + console.log("[ttt] [DataShareTest] DataShareExtAbility onCreate this.context.databaseDir:" + this.context.databaseDir); + let rdbStore = await rdb.getRdbStore(this.context.getApplicationContext(), STORE_CONFIG); + await rdbStore.executeSql(DROP_TBL, []); + await rdbStore.executeSql(DDL_TBL_CREATE, []); + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/pages/Index.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..722c2e9cf76e168746a5a2974ad0c1439e856b36 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,364 @@ +import { + connectDataShareExtAbility001, + disconnectDataShareExtAbility, + onRdb, + offRdb, + queryTest, + insertTest, + updateTest, + deleteTest, + offPublishData, + onPublishData, + getPublishedData, + onPublishData3, + publishTest, + publishTest2, + publishTest3 +} from './myServer.test' + +@Entry +@Component +struct Index { + @State message: string = "Main thread message filed" + + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('DataShareServer Ability Test') + .fontSize(20) + .fontWeight(FontWeight.Bold) + + Text(`${this.message}`) + .fontSize(25) + .height('15%') + .width('100%') + .textAlign(TextAlign.Center) + + Row() { + Button() { + Text('Connect') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Connect onclick enter') + this.message = 'Connect onclick' + await connectDataShareExtAbility001() + console.info('[ttt] [DataShareServerTest] <> Connect onclick leave') + }) + + Button() { + Text('Disconnect') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Disconnect onclick enter') + this.message = 'Disconnect onclick' + await disconnectDataShareExtAbility() + console.info('[ttt] [DataShareServerTest] <> Disconnect onclick leave') + }) + } + + Row() { + Button() { + Text('On') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> On onclick enter') + this.message = '~ On onclick' + try { + await onRdb(); + } catch (err) { + console.error('[ttt] [DataAbilityTest] Observer on catch(err)====>:' + err); + } + console.info('[ttt] [DataShareServerTest] <> On onclick leave') + }) + + Button() { + Text('Off') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Off onclick enter') + this.message = '~ Off onclick' + try { + await offRdb(); + } catch (err) { + console.error('[ttt] [DataAbilityTest] Observer Off catch(err)====>:' + err); + } + console.info('[ttt] [DataShareServerTest] <> Off onclick leave') + }) + + } + + Row() { + Button() { + Text('Query') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Query onclick enter') + this.message = 'Query onclick' + let ret = await queryTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> Query onclick leave') + }) + + Button() { + Text('Insert') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Insert onclick enter') + this.message = 'Insert onclick' + let ret = await insertTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> Insert onclick leave') + }) + } + + Row() { + Button() { + Text('Update') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Update onclick enter') + this.message = 'Update onclick' + let ret = await updateTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> Update onclick leave') + }) + + Button() { + Text('Delete') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Delete onclick enter') + this.message = 'Delete onclick' + let ret = await deleteTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> Delete onclick leave') + }) + } + + Row() { + Button() { + Text('OffPublishData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> OffPublishData onclick enter') + this.message = 'OffPublishData onclick' + await offPublishData() + console.info('[ttt] [DataShareServerTest] <> OffPublishData onclick leave') + }) + + Button() { + Text('OnPublishData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> OnPublishData onclick enter') + this.message = 'OnPublishData onclick' + await onPublishData() + console.info('[ttt] [DataShareServerTest] <> OnPublishData onclick leave') + }) + } + + Row() { + Button() { + Text('getPublishedData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> getPublishedData onclick enter') + this.message = 'getPublishedData onclick' + let ret = await getPublishedData() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> getPublishedData onclick leave') + }) + + Button() { + Text('OnPublishData3') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> OnPublishData3 onclick enter') + this.message = 'OnPublishData3 onclick' + await onPublishData3() + console.info('[ttt] [DataShareServerTest] <> OnPublishData3 onclick leave') + }) + } + + Row() { + Button() { + Text('Publish') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> publish onclick enter') + this.message = 'publish onclick' + let ret = await publishTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> publish onclick leave') + }) + + + Button() { + Text('GetFileTypes') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> GetFileTypes onclick enter') + this.message = 'GetFileTypes onclick' + // let ret = await globalThis.getFileTypes() + // this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> GetFileTypes onclick leave') + }) + } + + Row() { + Button() { + Text('Publish2.0') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Publish2.0 onclick enter') + this.message = 'Publish2.0 onclick' + let ret = await publishTest2() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> Publish2.0 onclick leave') + }) + + + Button() { + Text('Publish3.0') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Publish3.0 onclick enter') + this.message = 'Publish3.0 onclick' + let ret = await publishTest3() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> Publish3.0 onclick leave') + }) + } + + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/pages/myServer.test.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/pages/myServer.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..5ccb02ce32085f92b09bb7d6da3e6196dd06dcb7 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/pages/myServer.test.ets @@ -0,0 +1,375 @@ +import dataShare from '@ohos.data.dataShare' +import dataSharePredicates from '@ohos.data.dataSharePredicates' +import { BusinessError } from '@ohos.base'; +import { ValuesBucket } from '@ohos.data.ValuesBucket'; +import rpc from '@ohos.rpc'; +import common from "@ohos.app.ability.common" + +let cardUri = ("datashareproxy://com.acts.ohos.data.datasharetest/test"); +let dsProxyHelper: dataShare.DataShareHelper | undefined = undefined +let dsProxyHelper1:dataShare.DataShareHelper; +let context: common.UIAbilityContext +context = AppStorage.get("TestAbilityContext") as common.UIAbilityContext + +export async function connectDataShareExtAbility001() { + console.log("[ttt] [DataShareServerTest] <> connectDataShareExtAbility begin "); + try{ + dsProxyHelper = await dataShare.createDataShareHelper(context, cardUri, {isProxy : true}); + // dsProxyHelper1 = await dataShare.createDataShareHelper(context, cardUri, {isProxy : true}); + console.log("[ttt] [DataShareServerTest] <> dsProxyHelper " + JSON.stringify(dsProxyHelper)); + } catch (e) { + console.log("[ttt] [DataShareServerTest] createDataShareHelper failed :" + e); + } +} + +export async function disconnectDataShareExtAbility() { + console.log("[ttt] [DataShareServerTest] <> disconnectDataShareExtAbility begin"); + dsProxyHelper = undefined; + console.log("[ttt] [DataShareServerTest] <> disconnectDataShareExtAbility end"); +} + +export async function onRdb() { + console.log("[ttt] [DataShareServerTest] <> on begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> on end, DSHelper is null"); + return; + } + let template: dataShare.Template = { + predicates : { + "p1" : "select name0 as name from TBL00", + "p2" : "select name1 as name from TBL00", + }, + scheduler : "select remindTimer(strftime('%s', 'now', '+30 seconds')) from TBL00" + } + dsProxyHelper.addTemplate(cardUri, "111", template); + let templateId:dataShare.TemplateId = {subscriberId:"111", bundleNameOfOwner:"com.acts.ohos.data.datasharetest"} + let result:Array = dsProxyHelper.on("rdbDataChange", [cardUri], templateId, onCallback); + console.log("[ttt] [DataShareServerTest] <> on end " + JSON.stringify(result)); +} + +export function onCallback(err:BusinessError, node:dataShare.RdbDataChangeNode) { + console.info("[ttt] [callback] rdb change ININ"); + // console.info("[ttt][callback] " + JSON.stringify(node.uri)); + // console.info("[ttt][callback] " + JSON.stringify(node.templateId)); + // console.info("[ttt][callback] " + node.data.length); + for (let i = 0; i < node.data.length; i++) { + // console.info("[ttt][callback] " + typeof node.data[i]); + console.info("[ttt][callback] " + node.data[i]); + } +} + +export async function offRdb() { + console.log("[ttt] [DataShareServerTest] <> off begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> off end, DSHelper is null"); + return; + } + let templateId:dataShare.TemplateId = {subscriberId:"111", bundleNameOfOwner:"com.acts.ohos.data.datasharetest"} + let result:Array = dsProxyHelper.off("rdbDataChange", [cardUri], templateId); + console.log("[ttt] [DataShareServerTest] <> off end " + JSON.stringify(result)); +} + +export async function queryTest() { + console.log("[ttt] [DataShareServerTest] <> query begin"); + let da = new dataSharePredicates.DataSharePredicates(); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareServerTest] <> da is null or undefined"); + return; + } + let count = 0; + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> query end, DSHelper is null"); + return; + } + let result = await dsProxyHelper.query(cardUri, da, ["*"]); + if (result != undefined) { + count = result.rowCount; + console.log("[ttt] [DataShareServerTest] <> hanlu query end, result:" + JSON.stringify(result)); + } + console.log("[ttt] [DataShareServerTest] <> query end, count222:" + count); + return count; +} + +export async function insertTest() { + console.log("[ttt] [DataShareServerTest] <> insert begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> insert end, DSHelper is null"); + return; + } + let i = 0; + let ret = 0; + for (i = 0; i < 20; i++) { + let vb: ValuesBucket = { + "name0": "name0" + i, + "name1": "name1" + i, + "name2": "name2" + i, + "name3": "name3" + i, + "name4": "name4" + i, + "name5": "name5" + i, + "name6": "name6" + i, + "name7": "name7" + i, + "name8": "name8" + i, + "name9": "name9" + i, + }; + await dsProxyHelper.insert(cardUri, vb).then((number)=>{ + ret =number; + }).catch((err: BusinessError) => { + console.error(`[ttt] insert error: code: ${err.code}, message: ${err.message} `); + }); + console.log("[ttt] [DataShareServerTest] <> insert ret is " + ret); + console.log("[ttt] [DataShareServerTest] <> insert end " + cardUri); + } + return ret; +} + +export async function updateTest() { + console.log("[ttt] [DataShareServerTest] <> update begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> update end, DSHelper is null"); + return; + } + console.log("[ttt] [DataShareServerTest] <> update begin RPF666"); + let da = new dataSharePredicates.DataSharePredicates(); + console.log("[ttt] [DataShareServerTest] <> update begin RPF777"); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareServerTest] <> da is null or undefined"); + return; + } + let ret = dsProxyHelper.update(cardUri, da, { "name0": "ZhangSan" }); + console.log("[ttt] [DataShareServerTest] <> update end, result:" + ret); + return ret; +} + +export async function deleteTest() { + console.log("[ttt] [DataShareServerTest] <> delete begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> delete end, DSHelper is null"); + return; + } + let da = new dataSharePredicates.DataSharePredicates(); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareServerTest] <> da is null or undefined"); + return; + } + let ret = await dsProxyHelper.delete(cardUri, da); + console.log("[ttt] [DataShareServerTest] <> delete end, result:" + ret); + return ret; +} + +export async function offPublishData() { + console.log("[ttt] [DataShareServerTest] <> offPublishData begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> on end, DSHelper is null"); + return; + } + + try{ + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/test", "key2"]; + let result: Array = dsProxyHelper.off("publishedDataChange", + uris, + "11", onPublishCallback); + console.log("[ttt] [DataShareServerTest] <> off end " + JSON.stringify(result)); + }catch(err){ + console.error(` [ttt] offPublishData error: code: ${err.code}, message: ${err.message} `); + } +} + +export function onPublishCallback(err:BusinessError, node:dataShare.PublishedDataChangeNode) { + console.info("[ttt] [serverCallback] published change ININ"); + console.info("[ttt][serverCallback] bundleName " + JSON.stringify(node.bundleName)); + console.info("[ttt][serverCallback] data size" + node.data.length); + for (let i = 0; i < node.data.length; i++) { + console.info("[ttt][serverCallback] " + typeof node.data[i].data); + // if (typeof node.data[i].data != 'string') { + // let ash:rpc.Ashmem = node.data[i].data; + // ash.mapReadonlyAshmem(); + // console.info("[ttt][serverCallback] " + JSON.stringify(ash.readAshmem(ash.getAshmemSize()/4, 0))); + // + // } + console.info("[ttt][serverCallback] data " + i + " " + JSON.stringify(node.data[i])); + } +} + +export async function onPublishData() { + console.log("[ttt] [DataShareServerTest] <> onPublishData begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> on end, DSHelper is null"); + return; + } + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", "datashareproxy://com.acts.ohos.data.datasharetest/test"]; + try { + console.log("[ttt] [DataShareServerTest] <> on begin"); + let result: Array = dsProxyHelper.on("publishedDataChange", uris, "11", onPublishCallback); + console.log("[ttt] [DataShareServerTest] <> on end " + JSON.stringify(result)); + // return result.length; + } catch (e) { + console.log("[ttt] [DataShareServerTest] <> on err " + JSON.stringify(e)); + + } +} + +export async function getPublishedData() { + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> getPublishedData end, DSHelper is null"); + return; + } + console.log("[ttt] [DataShareServerTest] <> getPublishedData begin"); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + let ret = publishedData.length; + console.log("[ttt] [DataShareServerTest] <> getPublishedData end dataSize is " + ret); + console.log("[ttt] [DataShareServerTest] <> getPublishedData end data is " + JSON.stringify(publishedData)); + return ret; +} + +export async function onPublishData3() { + console.log("[ttt] [DataShareServerTest] <> onPublishData3 begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> on end, DSHelper is null"); + return; + } + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", "datashareproxy://com.acts.ohos.data.datasharetest/test"]; + try { + console.log("[ttt] [DataShareServerTest] <> on begin"); + let result: Array = dsProxyHelper1.on("publishedDataChange", uris, "11", onPublishCallback3); + console.log("[ttt] [DataShareServerTest] <> on end " + JSON.stringify(result)); + // return result.length; + } catch (e) { + console.log("[ttt] [DataShareServerTest] <> on err " + JSON.stringify(e)); + + } +} + +export function onPublishCallback3(err:BusinessError, node:dataShare.PublishedDataChangeNode) { + console.info("[ttt] [callback] server published change ININ 3333"); + console.info("[ttt][callback] bundleName 3333" + JSON.stringify(node.bundleName)); + console.info("[ttt][callback] data size" + node.data.length); + for (let i = 0; i < node.data.length; i++) { + console.info("[ttt][callback] " + typeof node.data[i].data); + // if (typeof node.data[i].data != 'string') { + // let ash:rpc.Ashmem = node.data[i].data; + // ash.mapReadonlyAshmem(); + // console.info("[ttt][callback] " + JSON.stringify(ash.readAshmem(ash.getAshmemSize()/4, 0))); + // + // } + console.info("[ttt][callback] data " + i + " " + JSON.stringify(node.data[i])); + } + +} + +export async function publishTest() { + console.log("[ttt] [DataShareServerTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key:"city", subscriberId:"11", data:"xianServer"+Math.random()}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key:"empty", subscriberId:"11", data:"nobody sub Server"+Math.random()}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub Server"+Math.random()}]; + console.log("[ttt] [DataShareServerTest] <> publish begin"); + + let nums:number[] = [1,2,3]; + try { + let ashmem = rpc.Ashmem.create("ashmem", (nums.length) * 4); + console.log("[ttt] [DataShareServerTest] <> hanlu222 " + JSON.stringify(ashmem)); + ashmem.mapReadWriteAshmem(); + console.log("[ttt] [DataShareServerTest] <> hanlu333"); + //nums.fill(6, 0 ,1024); + console.log("[ttt] [DataShareServerTest] <> hanlu444 " + JSON.stringify(nums)); + ashmem.writeAshmem(nums, nums.length, 0); + console.log("[ttt] [DataShareServerTest] <> hanlu555"); + // data.push({ + // "key" : "key2", + // "data" : ashmem, + // "subscriberId" : "11", + // }); + console.log("[ttt] [DataShareServerTest] <> datasss length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest"); + console.log("[ttt] [DataShareServerTest] <> publish end " + JSON.stringify(result)); + ashmem.closeAshmem(); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareServerTest] <> getPublishedData end " + JSON.stringify(publishedData)); + // for (let i = 0; i < publishedData.length; i++) { + // console.info("[ttt][callback] " + typeof publishedData[i].data); + // if (typeof publishedData[i].data != 'string') { + // let ash:rpc.Ashmem = publishedData[i].data; + // ash.mapReadonlyAshmem(); + // console.info("[ttt][callback] " + JSON.stringify(ash.readAshmem(ash.getAshmemSize()/4, 0))); + // ash.closeAshmem(); + // } + // } + } catch (e) { + console.log("[ttt] [DataShareServerTest] <> publish error " + JSON.stringify(e)); + } +} + +export async function publishTest2() { + console.log("[ttt] [DataShareServerTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key:"city", subscriberId:"11", data:"xianServer22222"}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key:"empty", subscriberId:"11", data:"nobody sub Server"+222222}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub Server"+Math.random()}]; + console.log("[ttt] [DataShareServerTest] <> publish begin"); + + let nums:number[] = [1,2,3]; + try { + let ashmem = rpc.Ashmem.create("ashmem", (nums.length) * 4); + console.log("[ttt] [DataShareServerTest] <> hanlu222 " + JSON.stringify(ashmem)); + ashmem.mapReadWriteAshmem(); + console.log("[ttt] [DataShareServerTest] <> hanlu333"); + //nums.fill(6, 0 ,1024); + console.log("[ttt] [DataShareServerTest] <> hanlu444 " + JSON.stringify(nums)); + ashmem.writeAshmem(nums, nums.length, 0); + console.log("[ttt] [DataShareServerTest] <> hanlu555"); + + console.log("[ttt] [DataShareServerTest] <> datasss length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest",2); + console.log("[ttt] [DataShareServerTest] <> publish end " + JSON.stringify(result)); + ashmem.closeAshmem(); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareServerTest] <> getPublishedData end " + JSON.stringify(publishedData)); + } catch (e) { + console.log("[ttt] [DataShareServerTest] <> publish error " + JSON.stringify(e)); + } +} + +export async function publishTest3() { + console.log("[ttt] [DataShareServerTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key:"city", subscriberId:"11", data:"xianServer3333333"}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key:"empty", subscriberId:"11", data:"nobody sub Server"+33333}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub Server"+Math.random()}]; + console.log("[ttt] [DataShareServerTest] <> publish begin"); + + let nums:number[] = [1,2,3]; + try { + let ashmem = rpc.Ashmem.create("ashmem", (nums.length) * 4); + console.log("[ttt] [DataShareServerTest] <> hanlu222 " + JSON.stringify(ashmem)); + ashmem.mapReadWriteAshmem(); + console.log("[ttt] [DataShareServerTest] <> hanlu333"); + //nums.fill(6, 0 ,1024); + console.log("[ttt] [DataShareServerTest] <> hanlu444 " + JSON.stringify(nums)); + ashmem.writeAshmem(nums, nums.length, 0); + console.log("[ttt] [DataShareServerTest] <> hanlu555"); + + console.log("[ttt] [DataShareServerTest] <> datasss length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest",3); + console.log("[ttt] [DataShareServerTest] <> publish end " + JSON.stringify(result)); + ashmem.closeAshmem(); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareServerTest] <> getPublishedData end " + JSON.stringify(publishedData)); + } catch (e) { + console.log("[ttt] [DataShareServerTest] <> publish error " + JSON.stringify(e)); + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/module.json5 b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..9fda83202d9ce712e50a706cd4b5135e3c7aa070 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/module.json5 @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ + { + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:icon", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.GET_BUNDLE_INFO" + } + ], + "extensionAbilities": [ + { + "srcEntrance": "./ets/DataShareExtAbility/DataShareExtAbility.ts", + "name": "DataShareExtAbility", + "icon": "$media:icon", + "type": "dataShare", +// "readPermission": "ohos.permission.GET_BUNDLE_INFO", +// "writePermission": "ohos.permission.GET_BUNDLE_INFO", + "uri": "datashareproxy://com.acts.ohos.data.datasharetest/test", + "exported": true, + } + ], + + "proxyData":[ + { + "uri": "datashareproxy://com.acts.ohos.data.datasharetest/test", + "requiredReadPermission":"ohos.permission.GET_BUNDLE_INFO_PRIVILEGED", + "requiredWritePermission":"ohos.permission.GET_BUNDLE_INFO_PRIVILEGED", + "metadata": { + "name": "dataProperties", + "resource": "$profile:test" + } + } + ] + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/element/color.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..82f853ffef34a3b56ced931281ad3b76ef7f3025 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/element/string.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..7ff1694425d455890bdb2767a4dec4ee3053549a --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/media/icon.png b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/media/icon.png differ diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/media/startlcon.png b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/media/startlcon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/media/startlcon.png differ diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/profile/main_pages.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/profile/test.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/profile/test.json new file mode 100644 index 0000000000000000000000000000000000000000..e17e14e1a54d5b705961023bf36b499457c6ddcf --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/profile/test.json @@ -0,0 +1,5 @@ +{ + "path": "DB00/TBL00", + "type": "rdb", + "scope": "application" +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/en_US/element/string.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..7ff1694425d455890bdb2767a4dec4ee3053549a --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/zh_CN/element/string.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..ccec2cf1b1bc163bf02190852c28712ef46d161e --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/test/Ability.test.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..8aa3749775f69d9055a9b87cb15f8905acd989bc --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,35 @@ +import hilog from '@ohos.hilog'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/test/List.test.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..5be61a34201c29a43f6ceb6cefa817819b567262 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,5 @@ +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testability/TestAbility.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testability/TestAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..9484761ccb050eef78e0468e36be45f045964d51 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testability/TestAbility.ets @@ -0,0 +1,50 @@ +import UIAbility from '@ohos.app.ability.UIAbility'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import hilog from '@ohos.hilog'; +import { Hypium } from '@ohos/hypium'; +import testsuite from '../test/List.test'; +import window from '@ohos.window'; +import Want from '@ohos.app.ability.Want'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; + +export default class TestAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate'); + hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? ''); + hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? ''); + let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator; + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs; + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments(); + hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!'); + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite); + } + + onDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate'); + windowStage.loadContent('testability/pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', + JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); + } + + onForeground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); + } + + onBackground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testability/pages/Index.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testability/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..2477432359278ee01f295d036fe4f7306c9e5912 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testability/pages/Index.ets @@ -0,0 +1,17 @@ +@Entry +@Component +struct Index { + @State message: string = 'Hello World'; + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets new file mode 100644 index 0000000000000000000000000000000000000000..917d27a5e8db0f45eb0a88fbe33e1225492fef0b --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets @@ -0,0 +1,47 @@ +import hilog from '@ohos.hilog'; +import TestRunner from '@ohos.application.testRunner'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import Want from '@ohos.app.ability.Want'; + +let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator | undefined = undefined +let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs | undefined = undefined + +async function onAbilityCreateCallback() { + hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err : Error) { + hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? ''); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare '); + } + + async onRun() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run'); + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + const bundleName = abilityDelegatorArguments.bundleName; + const testAbilityName = 'TestAbility'; + let lMonitor: AbilityDelegatorRegistry.AbilityMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + const want: Want = { + bundleName: bundleName, + abilityName: testAbilityName + }; + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + abilityDelegator.startAbility(want, (err, data) => { + hilog.info(0x0000, 'testTag', 'startAbility : err : %{public}s', JSON.stringify(err) ?? ''); + hilog.info(0x0000, 'testTag', 'startAbility : data : %{public}s',JSON.stringify(data) ?? ''); + }) + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end'); + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/module.json5 b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..1634e9b5bb65be7e0ec9eff1db5feb23d9dc9814 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/module.json5 @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ + { + "module": { + "name": "entry_test", + "type": "feature", + "description": "$string:module_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:test_pages", + "abilities": [ + { + "name": "TestAbility", + "srcEntry": "./ets/testability/TestAbility.ets", + "description": "$string:TestAbility_desc", + "icon": "$media:icon", + "label": "$string:TestAbility_label", + "exported": true, + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ] + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/element/color.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..82f853ffef34a3b56ced931281ad3b76ef7f3025 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/element/string.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..039de6a76ac7a8526662df74d443e16dee29764a --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_test_desc", + "value": "test ability description" + }, + { + "name": "TestAbility_desc", + "value": "the test ability" + }, + { + "name": "TestAbility_label", + "value": "test label" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/media/icon.png b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/media/icon.png differ diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/profile/test_pages.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/profile/test_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..b7e7343cacb32ce982a45e76daad86e435e054fe --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/profile/test_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "testability/pages/Index" + ] +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/test/List.test.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..bb5b5c3731e283dd507c847560ee59bde477bbc7 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/test/List.test.ets @@ -0,0 +1,5 @@ +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/test/LocalUnit.test.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..ed22d4dca5aebd6d638755a5ec15df57dc3c1ac0 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,33 @@ +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest',() => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/hvigor/hvigor-config.json5 b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..649526377e1e3e82d18f6b58e76673a3e9eec721 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/hvigor/hvigor-config.json5 @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ + { + "modelVersion": "5.0.0", + "dependencies": { + "@ohos/hvigor-ohos-online-sign-plugin": "4.0.1", + }, + "execution": { + // "daemon": true, /* Enable daemon compilation. Default: true */ + // "incremental": true, /* Enable incremental compilation. Default: true */ + // "parallel": true, /* Enable parallel compilation. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Default: false */ + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/sign/openharmony_sx.p7b b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/sign/openharmony_sx.p7b new file mode 100644 index 0000000000000000000000000000000000000000..4512fc0e7c36f20aa275736dce5631c304a80dc0 Binary files /dev/null and b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/sign/openharmony_sx.p7b differ diff --git a/data_share/test/native/resource/datashare_ext_bundle/entry/src/main/module.json b/data_share/test/native/resource/datashare_ext_bundle/entry/src/main/module.json index cbaf5d9d6fc129cb1d4dc54b4ec1350f662d4fbc..394cdc64795ef9c61ac4709897f7b0129baaee14 100644 --- a/data_share/test/native/resource/datashare_ext_bundle/entry/src/main/module.json +++ b/data_share/test/native/resource/datashare_ext_bundle/entry/src/main/module.json @@ -44,6 +44,33 @@ "description": "$string:description_datashareextability", "type": "dataShare", "uri": "datashare://com.acts.datasharetest", + "readPermission": "ohos.permission.WIFI", + "writePermission": "ohos.permission.WIFI", + "exported": true, + "visible": true + }, + { + "srcEntrance": "./ets/DataShareExtAbility/DataShareExtAbility.ts", + "name": "DataShareExtAbility2", + "icon": "$media:icon", + "description": "$string:description_datashareextability", + "type": "dataShare", + "uri": "datashare://com.acts.datasharetest2", + "readPermission": "ohos.permission.WRITE_CONTACTS", + "writePermission": "ohos.permission.GET_BUNDLE_INFO", + "exported": true, + "visible": true + }, + { + "srcEntrance": "./ets/DataShareExtAbility/DataShareExtAbility.ts", + "name": "DataShareExtAbility3", + "icon": "$media:icon", + "description": "$string:description_datashareextability", + "type": "dataShare", + "uri": "datashare://com.acts.testddd", + "exported": true, + "readPermission": "ohos.permission.WIFI", + "writePermission": "ohos.permission.WIFI", "visible": true } ], @@ -58,7 +85,7 @@ } }, { - "uri": "datashare://com.acts.datasharetest/test", + "uri": "datashareproxy://com.acts.datasharetest/readtest", "requiredReadPermission":"ohos.permission.READ_CALL_LOG", "metadata": { "name": "dataProperties", @@ -66,7 +93,7 @@ } }, { - "uri": "datashare://com.acts.datasharetest/test/permission", + "uri": "datashareproxy://com.acts.datasharetest/permissiontest/permission", "requiredWritePermission":"ohos.permission.WRITE_CALL_LOG", "metadata": { "name": "dataProperties", diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/AppScope/app.json5 b/data_share/test/native/resource/datashareclient_normal_bundle/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c347ece5a13c320919810a099075b322c24ad355 --- /dev/null +++ b/data_share/test/native/resource/datashareclient_normal_bundle/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ +{ + "app": { + "bundleName": "com.acts.ohos.data.datasharetestclient1", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/AppScope/resources/base/element/string.json b/data_share/test/native/resource/datashareclient_normal_bundle/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..1080233f01384411ec684b58955cb8808746fdd3 --- /dev/null +++ b/data_share/test/native/resource/datashareclient_normal_bundle/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "MyApplication" + } + ] +} diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/AppScope/resources/base/media/app_icon.png b/data_share/test/native/resource/datashareclient_normal_bundle/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/data_share/test/native/resource/datashareclient_normal_bundle/AppScope/resources/base/media/app_icon.png differ diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/entryability/EntryAbility.ets b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..4b6ffb475dc97837f18b7d2d1840b2157a19613e --- /dev/null +++ b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,40 @@ +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import hilog from '@ohos.hilog'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import Want from '@ohos.app.ability.Want'; +import window from '@ohos.window'; +import common from '@ohos.app.ability.common'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + AppStorage.setOrCreate("TestAbilityContext",this.context) + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + windowStage.loadContent('pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/pages/Index.ets b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..1c307e1fa2d6189d042eca974301fde651adfcd1 --- /dev/null +++ b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,362 @@ +import { + connectDataShareExtAbility001, + disconnectDataShareExtAbility, + onRdb, + offRdb, + queryTest, + insertTest, + updateTest, + deleteTest, + offPublishData, + onPublishData, + getPublishedData, + publishTest, + publishTest2, + publishTest3, + offPublishDataErr1, + offPublishDataErr2, + enable, + disable +} from './myClient.test' + +@Entry +@Component +struct Index { + @State message: string = "Main thread message filed" + + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('DataShareClient1 Ability Test') + .fontSize(20) + .fontWeight(FontWeight.Bold) + + Text(`${this.message}`) + .fontSize(25) + .height('15%') + .width('100%') + .textAlign(TextAlign.Center) + + Row() { + Button() { + Text('Connect') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Connect onclick enter') + this.message = 'Connect onclick' + await connectDataShareExtAbility001() + console.info('[ttt] [DataShareClientTest] <> Connect onclick leave') + }) + + Button() { + Text('Disconnect') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Disconnect onclick enter') + this.message = 'Disconnect onclick' + await disconnectDataShareExtAbility() + console.info('[ttt] [DataShareClientTest] <> Disconnect onclick leave') + }) + } + + Row() { + Button() { + Text('On') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> On onclick enter') + this.message = '~ On onclick' + try { + await onRdb(); + } catch (err) { + console.error('[ttt] [DataAbilityTest] Observer on catch(err)====>:' + err); + } + console.info('[ttt] [DataShareClientTest] <> On onclick leave') + }) + + Button() { + Text('Off') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Off onclick enter') + this.message = '~ Off onclick' + try { + await offRdb(); + } catch (err) { + console.error('[ttt] [DataAbilityTest] Observer Off catch(err)====>:' + err); + } + console.info('[ttt] [DataShareClientTest] <> Off onclick leave') + }) + + } + + Row() { + Button() { + Text('Query') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Query onclick enter') + this.message = 'Query onclick' + let ret = await queryTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> Query onclick leave') + }) + + Button() { + Text('Insert') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Insert onclick enter') + this.message = 'Insert onclick' + let ret = await insertTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> Insert onclick leave') + }) + } + + Row() { + Button() { + Text('Update') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Update onclick enter') + this.message = 'Update onclick' + let ret = await updateTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> Update onclick leave') + }) + + Button() { + Text('Delete') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Delete onclick enter') + this.message = 'Delete onclick' + let ret = await deleteTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> Delete onclick leave') + }) + } + + Row() { + Button() { + Text('OffPublishData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> OffPublishData onclick enter') + this.message = 'OffPublishData onclick' + await offPublishData() + console.info('[ttt] [DataShareClientTest] <> OffPublishData onclick leave') + }) + + Button() { + Text('OnPublishData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> OnPublishData onclick enter') + this.message = 'OnPublishData onclick' + await onPublishData() + console.info('[ttt] [DataShareClientTest] <> OnPublishData onclick leave') + }) + } + + Row() { + Button() { + Text('getPublishedData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> getPublishedData onclick enter') + this.message = 'getPublishedData onclick' + let ret = await getPublishedData() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> getPublishedData onclick leave') + }) + + Button() { + Text('Publish') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> publish onclick enter') + this.message = 'publish onclick' + let ret = await publishTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> publish onclick leave') + }) + } + + Row() { + Button() { + Text('offPublishDataErr1') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> offPublishDataErr1 onclick enter') + this.message = 'offPublishDataErr1 onclick' + await offPublishDataErr1() + console.info('[ttt] [DataShareClientTest] <> offPublishDataErr1 onclick leave') + }) + + Button() { + Text('offPublishDataErr2') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> offPublishDataErr2 onclick enter') + this.message = 'offPublishDataErr2 onclick' + await offPublishDataErr2() + console.info('[ttt] [DataShareClientTest] <> offPublishDataErr2 onclick leave') + }) + } + + Row() { + Button() { + Text('enable') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> enable onclick enter') + this.message = 'offPublishDataErr1 onclick' + await enable() + console.info('[ttt] [DataShareClientTest] <> enable onclick leave') + }) + + Button() { + Text('disable') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> disable onclick enter') + this.message = 'offPublishDataErr2 onclick' + await disable() + console.info('[ttt] [DataShareClientTest] <> disable onclick leave') + }) + } + + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/pages/myClient.test.ets b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/pages/myClient.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..690a654f5add67c47c11d957392439d1141f7ecc --- /dev/null +++ b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/pages/myClient.test.ets @@ -0,0 +1,396 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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 dataShare from '@ohos.data.dataShare' +import dataSharePredicates from '@ohos.data.dataSharePredicates' +import { BusinessError } from '@ohos.base'; +import { ValuesBucket } from '@ohos.data.ValuesBucket'; +import rpc from '@ohos.rpc'; +import common from "@ohos.app.ability.common" + +let cardUri = ("datashareproxy://com.acts.ohos.data.datasharetest/test"); +let dsProxyHelper: dataShare.DataShareHelper | undefined = undefined + + +let context: common.UIAbilityContext +context = AppStorage.get("TestAbilityContext") as common.UIAbilityContext + +export async function connectDataShareExtAbility001() { + try { + console.log("[ttt] [DataShareClientTest] <> connectDataShareExtAbility begin "); + dsProxyHelper = await dataShare.createDataShareHelper(context, cardUri, { isProxy: true }); + console.log("[ttt] [DataShareClientTest] <> dsProxyHelper " + JSON.stringify(dsProxyHelper)); + } + catch(err){ + console.error(` [ttt] createdatashare error: code: ${err.code}, message: ${err.message} `); + } +} + +export async function disconnectDataShareExtAbility() { + console.log("[ttt] [DataShareClientTest] <> disconnectDataShareExtAbility begin"); + dsProxyHelper = undefined; + console.log("[ttt] [DataShareClientTest] <> disconnectDataShareExtAbility end"); +} + +export async function enable() { + try { + + console.log("[ttt] [DataShareClientTest] <> enable begin"); + await dataShare.enableSilentProxy(context, cardUri); + console.log("[ttt] [DataShareClientTest] <> enable end"); + } + catch(err){ + console.error(` [ttt] enable error: code: ${err.code}, message: ${err.message} `); + } +} + +export async function disable() { + try { + console.log("[ttt] [DataShareClientTest] <> disable begin"); + await dataShare.disableSilentProxy(context, cardUri); + console.log("[ttt] [DataShareClientTest] <> disable end"); + } + catch(err){ + console.error(` [ttt] disable error: code: ${err.code}, message: ${err.message} `); + } +} + + +export async function onRdb() { + console.log("[ttt] [DataShareClientTest] <> on begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> on end, DSHelper is null"); + return; + } + let template: dataShare.Template = { + predicates: { + "p1": "select name0 as name from TBL00", + "p2": "select name1 as name from TBL00", + }, + scheduler: "select remindTimer(strftime('%s', 'now', '+10 seconds'))" + } + dsProxyHelper.addTemplate(cardUri, "111", template); + let templateId: dataShare.TemplateId = { + subscriberId: "111", bundleNameOfOwner: "com.acts.ohos.data.datasharetestclient" + } + let result: Array = dsProxyHelper.on("rdbDataChange", [cardUri], templateId, onCallback); + console.log("[ttt] [DataShareClientTest] <> on end " + JSON.stringify(result)); +} + +export function onCallback(err:BusinessError, node:dataShare.RdbDataChangeNode) { + console.info("[ttt] [DataShareClientTest] [callback] rdb change ININ"); + for (let i = 0; i < node.data.length; i++) { + // console.info("[ttt] [DataShareClientTest] [callback] " + typeof node.data[i]); + console.info("[ttt] [DataShareClientTest] [callback] " + node.data[i]); + } + +} + +export async function offRdb() { + console.log("[ttt] [DataShareClientTest] <> off begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> off end, DSHelper is null"); + return; + } + let templateId:dataShare.TemplateId = {subscriberId:"111", bundleNameOfOwner:"com.acts.ohos.data.datasharetestclient"} + let result:Array = dsProxyHelper.off("rdbDataChange", [cardUri], templateId); + console.log("[ttt] [DataShareClientTest] <> off end " + JSON.stringify(result)); +} + +export async function queryTest() { + console.log("[ttt] [DataShareClientTest] <> query begin"); + let da = new dataSharePredicates.DataSharePredicates(); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + let count = 0; + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> query end, DSHelper is null"); + return; + } + let result = await dsProxyHelper.query(cardUri, da, ["*"]); + if (result != undefined) { + count = result.rowCount; + console.log("[ttt] [DataShareClientTest] <> query end, result:" + JSON.stringify(result)); + result.close(); + } + console.log("[ttt] [DataShareClientTest] <> query end, count222:" + count); + return count; +} + +export async function queryTest2() { + console.log("[ttt] [DataShareClientTest] <> query begin"); + let da = new dataSharePredicates.DataSharePredicates(); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + let count = 0; + dsProxyHelper = await dataShare.createDataShareHelper(context, cardUri, {isProxy : true}); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> query end, DSHelper is null"); + return; + } + let result = await dsProxyHelper.query(cardUri, da, ["*"]); + if (result != undefined) { + count = result.rowCount; + console.log("[ttt] [DataShareClientTest] <> query end, result:" + JSON.stringify(result)); + result.close(); + } + console.log("[ttt] [DataShareClientTest] <> query end, count222:" + count); + return count; +} + +export async function insertTest() { + console.log("[ttt] [DataShareClientTest] <> insert begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> insert end, DSHelper is null"); + return; + } + + let i = 0; + let ret = 0; + for (i = 0; i < 2; i++) { + let vb: ValuesBucket = { + "name0": "name0" + i, + "name1": "name1" + i, + "name2": "name2" + i, + "name3": "name3" + i, + "name4": "name4" + i, + "name5": "name5" + i, + "name6": "name6" + i, + "name7": "name7" + i, + "name8": "name8" + i, + "name9": "name9" + i, + }; + ret = await dsProxyHelper.insert(cardUri, vb); + console.log("[ttt] [DataShareClientTest] <> insert end rowNum is " + ret); + } + return ret; +} + +export async function updateTest() { + console.log("[ttt] [DataShareClientTest] <> update begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> update end, DSHelper is null"); + return; + } + console.log("[ttt] [DataShareClientTest] <> update begin RPF666"); + let da = new dataSharePredicates.DataSharePredicates(); + console.log("[ttt] [DataShareClientTest] <> update begin RPF777"); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + let ret = dsProxyHelper.update(cardUri, da, { "name0": "ZhangSan" }); + console.log("[ttt] [DataShareClientTest] <> update end, result:" + ret); + return ret; +} + +export async function batchUpdate() { + console.log("[ttt] [DataShareClientTest] <> update begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> update end, DSHelper is null"); + return; + } + + console.log("[ttt] [DataShareClientTest] <> update begin RPF666"); + let da = new dataSharePredicates.DataSharePredicates(); + console.log("[ttt] [DataShareClientTest] <> update begin RPF777"); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } +} + +export async function deleteTest() { + console.log("[ttt] [DataShareClientTest] <> delete begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> delete end, DSHelper is null"); + return; + } + let da = new dataSharePredicates.DataSharePredicates(); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + let ret = await dsProxyHelper.delete(cardUri, da); + console.log("[ttt] [DataShareClientTest] <> delete end, result:" + ret); + return ret; +} + +export async function offPublishData() { + console.log("[ttt] [DataShareClientTest] <> offPublishData begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> on end, DSHelper is null"); + return; + } + try{ + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", "datashareproxy://com.acts.ohos.data.datasharetest/test"]; + let result: Array = dsProxyHelper.off("publishedDataChange", + uris, + "11", onPublishCallback); + console.log("[ttt] [DataShareClientTest] <> off end " + JSON.stringify(result)); + }catch(err){ + console.error(` [ttt] offPublishData error: code: ${err.code}, message: ${err.message} `); + } +} + +export async function offPublishDataErr1() { + console.log("[ttt] [DataShareClientTest] <> offPublishDataErr1 begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> on end, DSHelper is null"); + return; + } + + try{ + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", "datashareproxy://com.acts.ohos.data.datasharetest/test"]; + let result: Array = dsProxyHelper.off("publishedDataChange", + uris, + "11", undefined); + console.log("[ttt] [DataShareClientTest] <> off end " + JSON.stringify(result)); + }catch(err){ + console.error(` [ttt] offPublishDataErr1 error: code: ${err.code}, message: ${err.message} `); + } +} + + +export async function offPublishDataErr2() { + console.log("[ttt] [DataShareClientTest] <> off begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> off end, DSHelper is null"); + return; + } + let templateId:dataShare.TemplateId = {subscriberId:"111", bundleNameOfOwner:"com.acts.ohos.data.datasharetestclient"} + try{ + let result:Array = dsProxyHelper.off("rdbDataChange", [cardUri], templateId,undefined); + console.log("[ttt] [DataShareClientTest] <> off end " + JSON.stringify(result)); + }catch(err){ + console.error(` [ttt] offPublishDataErr2 error: code: ${err.code}, message: ${err.message} `); + } +} + +export function onPublishCallback(err:BusinessError, node:dataShare.PublishedDataChangeNode) { + console.info("[ttt] [DataShareClientTest] [callback] publishedData change ININ"); + // console.info("[ttt] [DataShareClientTest] [callback] bundleName " + JSON.stringify(node.bundleName)); + console.info("[ttt] [DataShareClientTest] [callback] data size" + node.data.length); + for (let i = 0; i < node.data.length; i++) { + // console.info("[ttt] [DataShareClientTest] [callback]" + typeof node.data[i].data); + console.info("[ttt] [DataShareClientTest] [callback] data " + i + " " + JSON.stringify(node.data[i])); + } +} + +export async function onPublishData() { + console.log("[ttt] [DataShareClientTest] <> onPublishData begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> on end, DSHelper is null"); + return; + } + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", "datashareproxy://com.acts.ohos.data.datasharetest/test"]; + try { + console.log("[ttt] [DataShareClientTest] <> on begin"); + let result: Array = dsProxyHelper.on("publishedDataChange", uris, "11", onPublishCallback); + console.log("[ttt] [DataShareClientTest] <> on end " + JSON.stringify(result)); + } catch (e) { + console.log("[ttt] [DataShareClientTest] <> on err " + JSON.stringify(e)); + + } +} + +export async function getPublishedData() { + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> getPublishedData end, DSHelper is null"); + return; + } + console.log("[ttt] [DataShareClientTest] <> getPublishedData begin"); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + let ret = publishedData.length; + console.log("[ttt] [DataShareClientTest] <> getPublishedData end dataSize is " + ret); + console.log("[ttt] [DataShareClientTest] <> getPublishedData end data is " + JSON.stringify(publishedData)); + return ret; +} + + +export async function publishTest() { + console.log("[ttt] [DataShareClientTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key: "city", subscriberId: "11", data: "xian" + Math.random()}, + {key: "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key: "empty", subscriberId: "11", data: "nobody sub" + Math.random()}, + {key: "datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub " + Math.random()}]; + + let nums:number[] = [1,2,3]; + try { + console.log("[ttt] [DataShareClientTest] <> data length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest"); + console.log("[ttt] [DataShareClientTest] <> publish end " + JSON.stringify(result)); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareClientTest] <> getPublishedData end " + JSON.stringify(publishedData)); + } catch (e) { + console.log("[ttt] [DataShareClientTest] <> publish error " + JSON.stringify(e)); + } +} + +export async function publishTest2() { + console.log("[ttt] [DataShareClientTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key:"city", subscriberId:"11", data:"xianServer22222"}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key:"empty", subscriberId:"11", data:"nobody sub Server"+222222}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub Server"+Math.random()}]; + + let nums:number[] = [1,2,3]; + try { + console.log("[ttt] [DataShareClientTest] <> datasss length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest",2); + console.log("[ttt] [DataShareClientTest] <> publish end " + JSON.stringify(result)); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareClientTest] <> getPublishedData end " + JSON.stringify(publishedData)); + } catch (e) { + console.log("[ttt] [DataShareClientTest] <> publish error " + JSON.stringify(e)); + } +} + +export async function publishTest3() { + console.log("[ttt] [DataShareClientTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key:"city", subscriberId:"11", data:"xianClient3333333"}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key:"empty", subscriberId:"11", data:"nobody sub Client"+33333}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub Server"+Math.random()}]; + + try { + console.log("[ttt] [DataShareClientTest] <> datasss length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest",3); + console.log("[ttt] [DataShareClientTest] <> publish end " + JSON.stringify(result)); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareClientTest] <> getPublishedData end " + JSON.stringify(publishedData)); + } catch (e) { + console.log("[ttt] [DataShareClientTest] <> publish error " + JSON.stringify(e)); + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/module.json5 b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..211c03c8dab7ce97142b79d87a31e55d1f43a8a8 --- /dev/null +++ b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/module.json5 @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ + { + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:icon", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED" + } + ] + } +} diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/element/color.json b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..82f853ffef34a3b56ced931281ad3b76ef7f3025 --- /dev/null +++ b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/element/string.json b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..7ff1694425d455890bdb2767a4dec4ee3053549a --- /dev/null +++ b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/media/icon.png b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/media/icon.png differ diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/media/startlcon.png b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/media/startlcon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/media/startlcon.png differ diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/profile/main_pages.json b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/en_US/element/string.json b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..7ff1694425d455890bdb2767a4dec4ee3053549a --- /dev/null +++ b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/zh_CN/element/string.json b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..ccec2cf1b1bc163bf02190852c28712ef46d161e --- /dev/null +++ b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/sign/openharmony_sx.p7b b/data_share/test/native/resource/datashareclient_normal_bundle/sign/openharmony_sx.p7b new file mode 100644 index 0000000000000000000000000000000000000000..4512fc0e7c36f20aa275736dce5631c304a80dc0 Binary files /dev/null and b/data_share/test/native/resource/datashareclient_normal_bundle/sign/openharmony_sx.p7b differ diff --git a/data_share/test/native/resource/ohos_test/ohos_test.xml b/data_share/test/native/resource/ohos_test/ohos_test.xml index 2bb7aad9e057985c643af1b822e4b5b0f6b2130f..2bb73c7d3161fc129a13d7ff730b8d214fb005b4 100644 --- a/data_share/test/native/resource/ohos_test/ohos_test.xml +++ b/data_share/test/native/resource/ohos_test/ohos_test.xml @@ -26,10 +26,13 @@ @@ -78,4 +81,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/corpus/init b/data_share/test/native/resource/ohos_test_new/BUILD.gn similarity index 69% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/corpus/init rename to data_share/test/native/resource/ohos_test_new/BUILD.gn index bc977bd9738ee9a70b362067f57a9c63d3adb801..42e1a9560ed4f773ac684672847cf995a9f8cf23 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/corpus/init +++ b/data_share/test/native/resource/ohos_test_new/BUILD.gn @@ -11,4 +11,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -FUZZ \ No newline at end of file +import("//build/ohos.gni") + +ohos_copy("copy_ohos_test_new") { + sources = [ "./ohos_test_new.xml" ] + outputs = [ "$root_out_dir/tests/unittest/data_share/resource/ohos_test_new.xml" ] + + subsystem_name = "distributeddatamgr" + part_name = "data_share" +} \ No newline at end of file diff --git a/data_share/test/native/resource/ohos_test_new/ohos_test_new.xml b/data_share/test/native/resource/ohos_test_new/ohos_test_new.xml new file mode 100644 index 0000000000000000000000000000000000000000..f1436c7f856f5357474b0c34f924b9db0cd678a1 --- /dev/null +++ b/data_share/test/native/resource/ohos_test_new/ohos_test_new.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/AppScope/app.json5 b/data_share/test/native/resource/systemapp_verify_bundle/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c347ece5a13c320919810a099075b322c24ad355 --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ +{ + "app": { + "bundleName": "com.acts.ohos.data.datasharetestclient1", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/data_share/test/native/resource/systemapp_verify_bundle/AppScope/resources/base/element/string.json b/data_share/test/native/resource/systemapp_verify_bundle/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..1080233f01384411ec684b58955cb8808746fdd3 --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "MyApplication" + } + ] +} diff --git a/data_share/test/native/resource/systemapp_verify_bundle/AppScope/resources/base/media/app_icon.png b/data_share/test/native/resource/systemapp_verify_bundle/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/data_share/test/native/resource/systemapp_verify_bundle/AppScope/resources/base/media/app_icon.png differ diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/AssetUtil.ets b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/AssetUtil.ets new file mode 100644 index 0000000000000000000000000000000000000000..4c5f7f0afef3828bf42775589367936e21806a99 --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/AssetUtil.ets @@ -0,0 +1,314 @@ +import { dataSharePredicates } from '@kit.ArkData'; +import photoAccessHelper from '@ohos.file.photoAccessHelper'; + +let context = getContext(this) +let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context) + +export class AssetUtil { + async GetAssets(field: string, value: string) { + let predicates = new dataSharePredicates.DataSharePredicates() + if (field.length != 0 && value.length != 0) { + if (field == photoAccessHelper.PhotoKeys.TITLE) { + predicates.like(field, value) + } else { + predicates.equalTo(field, value) + } + } + let fetchOptions: photoAccessHelper.FetchOptions = { + fetchColumns: ['title'], + predicates: predicates + } + let result: photoAccessHelper.PhotoAsset[] | undefined + try { + let fetchResult = await phAccessHelper.getAssets(fetchOptions) + if (!fetchResult) { + console.error('GetAssets FAILED') + return result + } + result = await fetchResult.getAllObjects() + console.info('GetAssets SUCCESS Count:' + fetchResult.getCount()) + } catch (err) { + console.error(`GetAssets error: ${err.code}, ${err.message}`) + } + return result; + } + + async CreateAsset(titleName: string) { + console.info('CreateAsset start') + let result: string | undefined + let options: photoAccessHelper.CreateOptions = { + title: titleName + } + try { + result = await phAccessHelper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg', options) + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + console.info('CreateAsset end') + return result + } + + async CreateAssetWithShortTermPermission(titleName: string) { + console.info('CreateAssetWithShortTermPermission Start') + let result: string | undefined + let config: photoAccessHelper.PhotoCreationConfig = { + title: titleName, + fileNameExtension: 'jpg', + photoType: photoAccessHelper.PhotoType.IMAGE, + subtype: photoAccessHelper.PhotoSubtype.DEFAULT, + } + try { + result = await phAccessHelper.createAssetWithShortTermPermission(config) + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + console.info('CreateAssetWithShortTermPermission End') + return result + } + + async DeleteAssets(assets: photoAccessHelper.PhotoAsset[]) { + console.info('DeleteAssets Start'); + for (let i = 0; assets && i < assets.length; i++) { + try { + let asset = assets[i] + if (i == 0) { + console.info('phAccessHelper.createDeleteRequest uri: ' + asset.uri) + await phAccessHelper.createDeleteRequest([asset.uri]) + } else { + console.info('MediaAssetChangeRequest.deleteAssets uri: ' + asset.uri) + await photoAccessHelper.MediaAssetChangeRequest.deleteAssets(context, [asset.uri]) + } + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + } + console.info('DeleteAssets End') + } + + async ModifyAsset(asset: photoAccessHelper.PhotoAsset) { + console.info('ModifyAsset Start') + try { + let title = asset.get(photoAccessHelper.PhotoKeys.TITLE) + asset.set(photoAccessHelper.PhotoKeys.TITLE, 'modify_' + title) + asset.commitModify() + console.info('asset title:' + asset.get(photoAccessHelper.PhotoKeys.TITLE)) + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + console.info('ModifyAsset end') + } + + async CloneAsset(asset: photoAccessHelper.PhotoAsset) { + console.info('CloneAsset Start') + try { + let title = asset.get(photoAccessHelper.PhotoKeys.TITLE) + let clone = await asset.clone('clone_' + title) + console.info('asset uri:' + clone.uri) + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + console.info('CloneAsset end') + } + + async GetAlbums(type: photoAccessHelper.AlbumType, subtype: photoAccessHelper.AlbumSubtype) { + let result: photoAccessHelper.Album[] | undefined + try { + let fetchResult = await phAccessHelper.getAlbums(type, subtype) + if (!fetchResult) { + console.error('GetAlbums FAILED') + return result + } + result = await fetchResult.getAllObjects() + console.info('GetAlbums SUCCESS Count:' + fetchResult.getCount()) + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + return result + } + + async GetAlbumAssets(album: photoAccessHelper.Album) { + let predicates = new dataSharePredicates.DataSharePredicates() + let fetchOption: photoAccessHelper.FetchOptions = { + fetchColumns: ['title'], + predicates: predicates + } + let result: photoAccessHelper.PhotoAsset[] | undefined + try { + let fetchResult = await album.getAssets(fetchOption) + if (!fetchResult) { + console.error('GetAlbumAssets FAILED') + return result + } + result = await fetchResult.getAllObjects(); + console.info('GetAlbumAssets SUCCESS Count:' + fetchResult.getCount()) + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + return result + } + + async RemoveAlbumAssets(album: photoAccessHelper.Album) { + console.info('RemoveAlbumAssets Start albumName:' + album.albumName + ' albumUri:' + album.albumUri) + let assets = await this.GetAlbumAssets(album) + for (let i = 0; assets && i < assets.length; i++) { + try { + let asset = assets[i] + if (i == 0) { + console.info('Album.removeAssets uri:' + asset.uri) + await album.removeAssets([asset]); + } else { + console.info('MediaAlbumChangeRequest.removeAssets uri:' + asset.uri) + let request = new photoAccessHelper.MediaAlbumChangeRequest(album) + request.removeAssets([asset]); + await phAccessHelper.applyChanges(request) + } + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + } + console.info('RemoveAlbumAssets End') + } + + async SystemRecoverAlbumAssets(album: photoAccessHelper.Album) { + console.info('SystemAlbumRecoverAssets Start albumName:' + album.albumName + ' albumUri:' + album.albumUri) + let assets = await this.GetAlbumAssets(album) + for (let i = 0; assets && i < assets.length; i++) { + try { + let asset = assets[i] + if (i == 0) { + console.info('Album.recoverAssets uri:' + asset.uri) + await album.recoverAssets([asset]) + } else { + console.info('MediaAlbumChangeRequest.recoverAssets uri:' + asset.uri) + let request = new photoAccessHelper.MediaAlbumChangeRequest(album) + request.recoverAssets([asset]); + await phAccessHelper.applyChanges(request) + } + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + } + console.info('SystemAlbumRecoverAssets End') + } + + async SystemDeleteAlbumAssets(album: photoAccessHelper.Album) { + console.info('SystemAlbumDeleteAsset Start albumName:' + album.albumName + ' albumUri:' + album.albumUri) + let assets = await this.GetAlbumAssets(album) + for (let i = 0; assets && i < assets.length; i++) { + try { + let asset = assets[i] + if (i == 0) { + console.info('Album.deleteAssets uri:' + asset.uri) + await album.deleteAssets([asset]) + } else { + console.info('MediaAlbumChangeRequest.deleteAssets uri:' + asset.uri) + let request = new photoAccessHelper.MediaAlbumChangeRequest(album) + request.deleteAssets([asset]) + await phAccessHelper.applyChanges(request); + } + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`); + } + } + console.info('SystemAlbumDeleteAsset End'); + } + + async SystemDeleteAlbum(index: number, album: photoAccessHelper.Album) { + console.info('SystemDeleteAlbum Start') + try { + if (index == 0) { + console.info('photoAccessHelper.deleteAlbums albumName:' + album.albumName) + await phAccessHelper.deleteAlbums([album]) + } else { + console.info('MediaAlbumChangeRequest.deleteAlbums albumName:' + album.albumName) + await photoAccessHelper.MediaAlbumChangeRequest.deleteAlbums(context, [album]) + } + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + console.info('SystemDeleteAlbum end') + } + + async SystemDeleteAsset(asset: photoAccessHelper.PhotoAsset) { + console.info('SystemDeleteAsset Start') + try { + console.info('phAccessHelper.deleteAssets uri:' + asset.uri) + await phAccessHelper.deleteAssets([asset.uri]) + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + console.info('SystemDeleteAsset End') + } + + async SystemCreateAsset(titleName: string) { + console.info('SystemCreateAsset Start') + let result: string | undefined + try { + let asset = await phAccessHelper.createAsset(titleName + '.jpg') + result = asset.uri + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + console.info('SystemCreateAsset End') + return result + } + + async SystemCreateAssetSubType(titleName: string, subType: photoAccessHelper.PhotoSubtype) { + console.info('SystemCreateAssetSubType Start') + let result: string | undefined + let createOption: photoAccessHelper.PhotoCreateOptions = { + subtype: subType + } + try { + let asset = await phAccessHelper.createAsset(titleName + '.jpg', createOption); + result = asset.uri + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + console.info('SystemCreateAssetSubType End') + return result + } + + async SystemCreateAssetForApp(titleName: string, appName: string, bundleName: string, appId: string) { + console.info('SystemCreateAssetForApp Start') + let result: string | undefined + let configs: Array = [ + { + title: titleName, + fileNameExtension: 'jpg', + photoType: photoAccessHelper.PhotoType.IMAGE, + subtype: photoAccessHelper.PhotoSubtype.DEFAULT, + } + ] + try { + let uris = await phAccessHelper.createAssetsForApp(bundleName, appName, appId, configs) + result = uris[0] + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + console.info('SystemCreateAssetForApp End') + return result + } + + async SystemCreateAssetForAppWithMode(titleName: string, appName: string, bundleName: string, appId: string, tokenId: number) { + console.info('SystemCreateAssetForAppWithMode Start') + let result: string | undefined + let configs: Array = [ + { + title: titleName, + fileNameExtension: 'jpg', + photoType: photoAccessHelper.PhotoType.IMAGE, + subtype: photoAccessHelper.PhotoSubtype.DEFAULT, + } + ] + try { + let mode = photoAccessHelper.AuthorizationMode.SHORT_TIME_AUTHORIZATION; + let uris = await phAccessHelper.createAssetsForAppWithMode(bundleName, appName, appId, tokenId, mode, configs) + result = uris[0] + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + console.info('SystemCreateAssetForAppWithMode End') + return result + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/FileUtil.ets b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/FileUtil.ets new file mode 100644 index 0000000000000000000000000000000000000000..2e9b779e0d7e8abe521edf5cb79e7817a88ed8d1 --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/FileUtil.ets @@ -0,0 +1,27 @@ +import fs from '@ohos.file.fs'; + +export function ReadPhotoData(uri: string) { + console.info('ReadPhotoData:' + uri) + try { + let src = fs.openSync(uri, fs.OpenMode.READ_ONLY) + let data: ArrayBuffer = new ArrayBuffer(100) + fs.readSync(src.fd, data) + fs.closeSync(src) + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } +} + +export function CopyPhotoData(srcUri: string, dstUri: string) { + console.info('CopyPhotoData srcUri: ' + srcUri) + console.info(' => dstUri: ' + dstUri) + try { + let dst = fs.openSync(dstUri, fs.OpenMode.WRITE_ONLY) + let src = fs.openSync(srcUri, fs.OpenMode.READ_ONLY) + fs.copyFileSync(src.fd, dst.fd, 0) + fs.closeSync(src) + fs.closeSync(dst) + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } +} diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/entryability/EntryAbility.ets b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..c34fa296123a32587be9dc3619705048f8af165a --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,63 @@ +import { window } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { abilityAccessCtrl, AbilityConstant, Permissions, UIAbility, Want } from '@kit.AbilityKit'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + const permissions: Array = [ + 'ohos.permission.READ_IMAGEVIDEO','ohos.permission.WRITE_IMAGEVIDEO', + 'ohos.permission.READ_MEDIA','ohos.permission.WRITE_MEDIA', + 'ohos.permission.SHORT_TERM_WRITE_IMAGEVIDEO' + ]; + let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager(); + // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗 + atManager.requestPermissionsFromUser(this.context, permissions).then((data) => { + let grantStatus: Array = data.authResults; + let length: number = grantStatus.length; + for (let i = 0; i < length; i++) { + if (grantStatus[i] === 0) { + // 用户授权,可以继续访问目标操作 + } else { + // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限 + return; + } + } + // 授权成功 + }).catch((err: BusinessError) => { + console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`); + }) + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..6995da571c55c6a253d78bd5de181c1db26e8a47 --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,12 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class EntryBackupAbility extends BackupExtensionAbility { +async onBackup() { +hilog.info(0x0000, 'testTag', 'onBackup ok'); +} + +async onRestore(bundleVersion: BundleVersion) { +hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); +} +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/DataShare.ets b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/DataShare.ets new file mode 100644 index 0000000000000000000000000000000000000000..5ac77d9271829f3a4f9fe3c0eaa1b23c2e441cb9 --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/DataShare.ets @@ -0,0 +1,60 @@ +import { BusinessError } from '@kit.BasicServicesKit'; +import dataShare from '@ohos.data.dataShare'; +import { dataSharePredicates, ValuesBucket } from '@kit.ArkData'; +import photoAccessHelper from '@ohos.file.photoAccessHelper'; + +let context = getContext(this); + +function DataShareDelete(operation: string, field: string, value: string) { + console.info('DataShareDelete Demo Start:' + operation + ',' + field + '=' + value); + let uri: string = 'datashare:///media/' + operation + '/delete?api_version=10'; + dataShare.createDataShareHelper(context, uri).then((helper: dataShare.DataShareHelper) => { + let predicates = new dataSharePredicates.DataSharePredicates(); + predicates.equalTo(field, value); + helper.delete(uri, predicates); + console.info('DataShareHelper.delete successfully'); + }).catch ((err: BusinessError) => { + console.error(`error: ${err.code}, ${err.message}`); + }) + console.info('DataShareDelete Demo End:'); +} + +function DataShareMove(assetUri: string, oldAlbumId: string, newAlbumId: number) { + console.info('DataShareMove Demo Start: ' + assetUri); + let uri: string = 'datashare:///media/phaccess_photo_operation/batch_update_owner_album_id?api_version=10'; + dataShare.createDataShareHelper(context, uri).then((helper: dataShare.DataShareHelper) => { + let values: ValuesBucket = {}; + let predicates = new dataSharePredicates.DataSharePredicates(); + predicates.equalTo('owner_album_id', oldAlbumId); + predicates.and().in('file_id', [assetUri]); + values['owner_album_id'] = newAlbumId; + helper.update(uri, predicates, values); + console.info('DataShareHelper.update successfully'); + }).catch ((err: BusinessError) => { + console.error(`error: ${err.code}, ${err.message}`); + }) + console.info('DataShareMove Demo End:'); +} + +@Entry +@Component +struct DataShare { + build() { + Row() { + Column() { + Text('DataShare').margin(6).fontWeight(FontWeight.Bold) + + Button("DataShareMoveAsset").margin(6).onClick(()=>{ + DataShareMove('', '11', 13); + }) + + Button('DataShareDeleteAlbum').margin(6).onClick(()=> { + DataShareDelete('phaccess_album_operation', photoAccessHelper.AlbumKeys.ALBUM_NAME, 'test1'); + DataShareDelete('photo_album_v10_operation', photoAccessHelper.AlbumKeys.ALBUM_NAME, 'test2'); + }) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/Index.ets b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..86850263feda5c9896f93d97df231c7b5461d7f3 --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,116 @@ +import { router } from '@kit.ArkUI' +import { AssetUtil } from '../AssetUtil' +import { CopyPhotoData, ReadPhotoData } from '../FileUtil' +import photoAccessHelper from '@ohos.file.photoAccessHelper' + +let assetUtil: AssetUtil = new AssetUtil() + +@Entry +@Component +struct Index { + build() { + Row() { + Column() { + Text('Public').margin(6).fontWeight(FontWeight.Bold) + + Button('System').margin(6).onClick(() => { + try { + router.pushUrl({ url: 'pages/SystemApi' }) + } catch (err) { + console.error(`failed to ${err.code} ${err.message}`); + } + }) + + Button('DataShare').margin(6).onClick(() => { + try { + router.pushUrl({ url: 'pages/DataShare' }) + } catch (err) { + console.error(`failed to ${err.code} ${err.message}`); + } + }) + + Button('ReadPhotoData').margin(6).onClick(async ()=> { + let uri = 'file://media/Photo/35/IMG_1742786685_034/sys_test3.jpg' + let result = await assetUtil.GetAssets(photoAccessHelper.PhotoKeys.URI, uri) + for (let i = 0; result && i < result.length; i++) { + console.info('GetAssets uri:' + result[i].uri + ' displayName:' + result[i].displayName) + } + ReadPhotoData(uri) + }) + + Button('PublicAssetTest').margin(6).onClick(async () => { + console.info('=======GetAssets All=======') + let result = await assetUtil.GetAssets(photoAccessHelper.PhotoKeys.TITLE, '') + if (!result || result.length <= 0) { + console.error('=======PublicAssetTest======= End') + return + } + + let uris: Array = new Array() + console.info('=======CreateAsset pub_test1=======') + let uri = await assetUtil.CreateAsset('pub_test1') + if (uri) { + uris.push(uri) + } + + console.info('=======CreateAsset pub_test2=======') + uri = await assetUtil.CreateAssetWithShortTermPermission('pub_test2') + if (uri) { + uris.push(uri) + } + + console.info('=======CopyPhotoData=======') + for (let i = 0; i < uris.length; i++) { + CopyPhotoData(result[0].uri, uris[i]) + } + + console.info('=======ReadPhotoData=======') + for (let i = 0; i < uris.length; i++) { + ReadPhotoData(uris[i]) + } + + console.info('=======GetAssets pub_%=======') + result = await assetUtil.GetAssets(photoAccessHelper.PhotoKeys.TITLE, 'pub_%') + for (let i = 0; result && i < result.length; i++) { + await assetUtil.CloneAsset(result[i]) + await assetUtil.ModifyAsset(result[i]) + } + + console.info('=======GetAssets clone_%=======') + result = await assetUtil.GetAssets(photoAccessHelper.PhotoKeys.TITLE, 'clone_%') + if (result) { + await assetUtil.DeleteAssets(result) + } + + console.info('=======GetAssets modify_%=======') + result = await assetUtil.GetAssets(photoAccessHelper.PhotoKeys.TITLE, 'modify_%') + if (result) { + await assetUtil.DeleteAssets(result) + } + + console.info('=======PublicAssetTest======= End') + }) + + Button('PublicAlbumTest').margin(6).onClick(async ()=> { + console.info('=======PublicAlbumTest======= GetAlbums USER_GENERIC') + let result = await assetUtil.GetAlbums(photoAccessHelper.AlbumType.USER, + photoAccessHelper.AlbumSubtype.USER_GENERIC) + for (let i = 0; result && i < result.length; i++) { + await assetUtil.RemoveAlbumAssets(result[i]) + } + + console.info('=======PublicAlbumTest======= GetAlbums TRASH') + result = await assetUtil.GetAlbums(photoAccessHelper.AlbumType.SYSTEM, + photoAccessHelper.AlbumSubtype.TRASH) + for (let i = 0; result && i < result.length; i++) { + console.info('albumName:' + result[i].albumName + ' albumUri:' + result[i].albumUri) + } + + console.info('=======PublicAssetTest======= End') + }) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/SystemApi.ets b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/SystemApi.ets new file mode 100644 index 0000000000000000000000000000000000000000..f386007a66ae3ddfb3110642e707dd68d9522c6f --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/SystemApi.ets @@ -0,0 +1,88 @@ +import { AssetUtil } from '../AssetUtil' +import { CopyPhotoData, ReadPhotoData } from '../FileUtil' +import photoAccessHelper from '@ohos.file.photoAccessHelper' +let assetUtil: AssetUtil = new AssetUtil() + +@Entry +@Component +struct SystemApi { + build() { + Row() { + Column() { + Text('System').margin(6).fontWeight(FontWeight.Bold) + Button('SystemAssetTest').margin(6).onClick(async () => { + console.info('=======GetAssets All=======') + let result = await assetUtil.GetAssets(photoAccessHelper.PhotoKeys.TITLE, '') + if (!result || result.length <= 0) { + console.error('=======SystemAssetTest======= End') + return + } + + let uris: Array = new Array() + console.info('=======SystemCreateAsset sys_test1=======') + let uri = await assetUtil.SystemCreateAsset('sys_test1') + if (uri) { + uris.push(uri) + } + + console.info('=======SystemCreateAsset sys_test2=======') + uri = await assetUtil.SystemCreateAssetSubType('sys_test2', photoAccessHelper.PhotoSubtype.DEFAULT) + if (uri) { + uris.push(uri) + } + + console.info('=======SystemCreateAsset sys_test3=======') + uri = await assetUtil.SystemCreateAssetForApp('sys_test3', 'testAppName', 'testBundleName','testAppId') + if (uri) { + uris.push(uri) + } + + console.info('=======CopyPhotoData=======') + for (let i = 0; i < uris.length; i++) { + CopyPhotoData(result[0].uri, uris[i]) + } + + console.info('=======ReadPhotoData=======') + for (let i = 0; i < uris.length; i++) { + ReadPhotoData(uris[i]) + } + + console.info('=======GetAssets sys_%=======') + result = await assetUtil.GetAssets(photoAccessHelper.PhotoKeys.TITLE, 'sys_%') + for (let i = 0; result && i < result.length; i++) { + await assetUtil.SystemDeleteAsset(result[i]) + } + console.info('=======SystemAssetTest======= End') + }) + + Button('SystemAlbumTest').margin(6).onClick(async ()=> { + console.info('=======SystemRecoverAlbumAssets======= GetAlbums TRASH') + let result = await assetUtil.GetAlbums(photoAccessHelper.AlbumType.SYSTEM, + photoAccessHelper.AlbumSubtype.TRASH) + for (let i = 0; result && i < result.length; i++) { + await assetUtil.SystemRecoverAlbumAssets(result[i]) + } + console.info('=======SystemRecoverAlbumAssets======= END') + + console.info('=======SystemDeleteAlbum======= GetAlbums USER_GENERIC') + result = await assetUtil.GetAlbums(photoAccessHelper.AlbumType.USER, + photoAccessHelper.AlbumSubtype.USER_GENERIC) + for (let i = 0; result && i < result.length; i++) { + await assetUtil.SystemDeleteAlbum(i, result[i]) + } + console.info('=======SystemDeleteAlbum======= END') + + console.info('=======SystemDeleteAlbumAssets======= GetAlbums TRASH') + result = await assetUtil.GetAlbums(photoAccessHelper.AlbumType.SYSTEM, + photoAccessHelper.AlbumSubtype.TRASH) + for (let i = 0; result && i < result.length; i++) { + await assetUtil.SystemDeleteAlbumAssets(result[i]) + } + console.info('=======SystemDeleteAlbumAssets======= END') + }) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/module.json5 b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a0cf8c1671bbcef5e6a56c50285e3b536126bee1 --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/module.json5 @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + + "requestPermissions": [ + { + "name" : "ohos.permission.READ_MEDIA", + "reason" : "$string:reason", + "usedScene": { + } + }, + { + "name" : "ohos.permission.WRITE_MEDIA", + "reason" : "$string:reason", + "usedScene": { + } + }, + { + "name" : "ohos.permission.READ_IMAGEVIDEO", + "reason" : "$string:reason", + "usedScene": { + } + }, + { + "name" : "ohos.permission.WRITE_IMAGEVIDEO", + "reason" : "$string:reason", + "usedScene": { + } + }, + { + "name" : "ohos.permission.SHORT_TERM_WRITE_IMAGEVIDEO", + "reason" : "$string:reason", + "usedScene": { + } + } + ], + + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ] + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/element/color.json b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..82f853ffef34a3b56ced931281ad3b76ef7f3025 --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/element/string.json b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..7ff1694425d455890bdb2767a4dec4ee3053549a --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/media/icon.png b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/media/icon.png differ diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/media/startlcon.png b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/media/startlcon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/media/startlcon.png differ diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/profile/main_pages.json b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/en_US/element/string.json b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..7ff1694425d455890bdb2767a4dec4ee3053549a --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/zh_CN/element/string.json b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..ccec2cf1b1bc163bf02190852c28712ef46d161e --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} diff --git a/data_share/test/native/resource/systemapp_verify_bundle/sign/openharmony_sx.p7b b/data_share/test/native/resource/systemapp_verify_bundle/sign/openharmony_sx.p7b new file mode 100644 index 0000000000000000000000000000000000000000..4512fc0e7c36f20aa275736dce5631c304a80dc0 Binary files /dev/null and b/data_share/test/native/resource/systemapp_verify_bundle/sign/openharmony_sx.p7b differ diff --git a/data_share/test/native/unittest/dataproxy_handle_test/dataproxy_handle_test.cpp b/data_share/test/native/unittest/dataproxy_handle_test/dataproxy_handle_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03a08dc7666e8af33617edd3370d586e15222fcc --- /dev/null +++ b/data_share/test/native/unittest/dataproxy_handle_test/dataproxy_handle_test.cpp @@ -0,0 +1,670 @@ +/* + * Copyright (C) 2023 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 + +#include "accesstoken_kit.h" +#include "dataproxy_handle.h" +#include "dataproxy_handle_common.h" +#include "datashare_log.h" +#include "hap_token_info.h" +#include "token_setproc.h" +#include "datashare_errno.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::Security::AccessToken; +std::string TEST_URI1 = "datashareproxy://com.acts.datasharetest/test1"; +std::string TEST_URI2 = "datashareproxy://com.acts.datasharetest.other/test1"; +std::string TEST_UNUSED_URI = "datashareproxy://com.acts.datasharetest/unused"; +std::atomic_int g_callbackTimes = 0; + +class ProxyHandleTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void ProxyHandleTest::SetUpTestCase(void) +{ + LOG_INFO("SetUpTestCase invoked"); + int sleepTime = 1; + sleep(sleepTime); + + HapInfoParams info = { .userID = 100, + .bundleName = "com.acts.datasharetest", + .instIndex = 0, + .appIDDesc = "com.acts.datasharetest", + .isSystemApp = true }; + HapPolicyParams policy = { .apl = APL_SYSTEM_BASIC, + .domain = "test.domain", + .permList = { { .permissionName = "ohos.permission.GET_BUNDLE_INFO", + .bundleName = "com.acts.datasharetest", + .grantMode = 1, + .availableLevel = APL_SYSTEM_BASIC, + .label = "label", + .labelId = 1, + .description = "com.acts.datasharetest", + .descriptionId = 1 } }, + .permStateList = { { .permissionName = "ohos.permission.GET_BUNDLE_INFO", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } } } }; + AccessTokenKit::AllocHapToken(info, policy); + auto testTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenIDEx( + info.userID, info.bundleName, info.instIndex); + SetSelfTokenID(testTokenId.tokenIDEx); + + LOG_INFO("SetUpTestCase end"); +} + +void ProxyHandleTest::TearDownTestCase(void) +{ + auto tokenId = AccessTokenKit::GetHapTokenID(100, "com.acts.datasharetest", 0); + AccessTokenKit::DeleteToken(tokenId); +} + +void ProxyHandleTest::SetUp(void) +{ +} + +void ProxyHandleTest::TearDown(void) +{ +} + +/** + * @tc.name: ProxyHandleTest_Publish_Test_001 + * @tc.desc: Verify DataProxyHandle successfully publishing string data + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the publish parameters to SHARED_CONFIG type + 3. Prepare string-type test data and publish it + 4. Retrieve the data via the same URI + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data publish operation returns a SUCCESS status code + 3. The retrieved data matches the originally published data + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Publish_Test_001, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Publish_Test_001::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + EXPECT_NE(handle, nullptr); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish and get string + DataProxyValue value = "hello"; + DataShareProxyData data(TEST_URI1, value); + std::vector proxyData; + proxyData.push_back(data); + + LOG_INFO("PublishProxyData::Start"); + auto ret2 = handle->PublishProxyData(proxyData, proxyConfig); + EXPECT_EQ(ret2[0].result_, DataProxyErrorCode::SUCCESS); + + std::vector uris; + uris.push_back(TEST_URI1); + LOG_INFO("GetProxyData::Start"); + auto ret3 = handle->GetProxyData(uris, proxyConfig); + EXPECT_EQ(ret3[0].value_, value); + + LOG_INFO("ProxyHandleTest_Publish_Test_001::End"); +} + +/** + * @tc.name: ProxyHandleTest_Publish_Test_002 + * @tc.desc: Verify DataProxyHandle successfully publishing integer data + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the publish parameters to SHARED_CONFIG type + 3. Prepare integer-type test data and publish it + 4. Retrieve the data via the same URI + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data publish operation returns a SUCCESS status code + 3. The retrieved data matches the originally published data + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Publish_Test_002, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Publish_Test_002::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish and get int + DataProxyValue value = 123456; + DataShareProxyData data(TEST_URI1, value); + std::vector proxyData; + proxyData.push_back(data); + + auto ret2 = handle->PublishProxyData(proxyData, proxyConfig); + EXPECT_EQ(ret2[0].result_, DataProxyErrorCode::SUCCESS); + + std::vector uris; + uris.push_back(TEST_URI1); + auto ret3 = handle->GetProxyData(uris, proxyConfig); + EXPECT_EQ(ret3[0].value_, value); + + LOG_INFO("ProxyHandleTest_Publish_Test_002::End"); +} + +/** + * @tc.name: ProxyHandleTest_Publish_Test_003 + * @tc.desc: Verify DataProxyHandle successfully + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the publish parameters to SHARED_CONFIG type + 3. Prepare double-precision floating-point test data and publish it + 4. Retrieve the data via the same URI + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data publish operation returns a SUCCESS status code + 3. The retrieved data matches the originally published data + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Publish_Test_003, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Publish_Test_003::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish and get double + DataProxyValue value = 123456.123456; + DataShareProxyData data(TEST_URI1, value); + std::vector proxyData; + proxyData.push_back(data); + + auto ret2 = handle->PublishProxyData(proxyData, proxyConfig); + EXPECT_EQ(ret2[0].result_, DataProxyErrorCode::SUCCESS); + + std::vector uris; + uris.push_back(TEST_URI1); + auto ret3 = handle->GetProxyData(uris, proxyConfig); + EXPECT_EQ(ret3[0].value_, value); + + LOG_INFO("ProxyHandleTest_Publish_Test_003::End"); +} + +/** + * @tc.name: ProxyHandleTest_Publish_Test_004 + * @tc.desc: Verify DataProxyHandle successfully publishing boolean data + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the publish parameters to SHARED_CONFIG type + 3. Prepare boolean-type test data and publish it + 4. Retrieve the data via the same URI + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data publish operation returns a SUCCESS status code + 3. The retrieved data matches the originally published data + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Publish_Test_004, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Publish_Test_004::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish and get bool + DataProxyValue value = true; + DataShareProxyData data(TEST_URI1, value); + std::vector proxyData; + proxyData.push_back(data); + + auto ret2 = handle->PublishProxyData(proxyData, proxyConfig); + EXPECT_EQ(ret2[0].result_, DataProxyErrorCode::SUCCESS); + + std::vector uris; + uris.push_back(TEST_URI1); + auto ret3 = handle->GetProxyData(uris, proxyConfig); + EXPECT_EQ(ret3[0].value_, value); + + LOG_INFO("ProxyHandleTest_Publish_Test_004::End"); +} + +/** + * @tc.name: ProxyHandleTest_Publish_Test_005 + * @tc.desc: Verify that DataProxyHandle fails to publish data from another bundlename + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the publish parameters to SHARED_CONFIG type + 3. Prepare test data pointing to another application's bundlename and attempt to publish it + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data publish operation returns a NO_PERMISSION status code + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Publish_Test_005, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Publish_Test_005::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish and get bool + DataProxyValue value = true; + DataShareProxyData data(TEST_URI2, value); + std::vector proxyData; + proxyData.push_back(data); + + // Publish other bundle name, failed because of no permission. + auto ret2 = handle->PublishProxyData(proxyData, proxyConfig); + EXPECT_EQ(ret2[0].result_, DataProxyErrorCode::NO_PERMISSION); + + LOG_INFO("ProxyHandleTest_Publish_Test_005::End"); +} + +/** + * @tc.name: ProxyHandleTest_Delete_Test_001 + * @tc.desc: Verify the functionality of DataProxyHandle successfully deleting published data + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the operation parameters to SHARED_CONFIG type + 3. Publish test data + 4. Verify that the data can be retrieved normally + 5. Delete the published data + 6. Attempt to retrieve the deleted data again + * @tc.expect: + 1. The data publish operation returns a SUCCESS status code + 2. The data retrieval operation returns data that matches the published data + 3. The data deletion operation returns a SUCCESS status code + 4. Attempting to retrieve the data after deletion returns a URI_NOT_EXIST status code + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Delete_Test_001, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Delete_Test_001::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish and get bool + DataProxyValue value = true; + DataShareProxyData data(TEST_URI1, value); + std::vector proxyData; + proxyData.push_back(data); + + auto ret2 = handle->PublishProxyData(proxyData, proxyConfig); + EXPECT_EQ(ret2[0].result_, DataProxyErrorCode::SUCCESS); + + std::vector uris; + uris.push_back(TEST_URI1); + auto ret3 = handle->GetProxyData(uris, proxyConfig); + EXPECT_EQ(ret3[0].value_, value); + + // delete the data success + auto ret4 = handle->DeleteProxyData(uris, proxyConfig); + EXPECT_EQ(ret4[0].result_, DataProxyErrorCode::SUCCESS); + + // get data failed + auto ret5 = handle->GetProxyData(uris, proxyConfig); + EXPECT_EQ(ret5[0].result_, DataProxyErrorCode::URI_NOT_EXIST); + + LOG_INFO("ProxyHandleTest_Delete_Test_001::End"); +} + +/** + * @tc.name: ProxyHandleTest_Delete_Test_002 + * @tc.desc: Verify that DataProxyHandle fails to delete data from another bundlename + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the operation parameters to SHARED_CONFIG type + 3. Attempt to delete test data pointing to another application's bundle name + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data deletion operation returns a NO_PERMISSION status code + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Delete_Test_002, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Delete_Test_002::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + std::vector uris; + uris.push_back(TEST_URI2); + + // delete data of other bundle name, failed because of no permission. + auto ret4 = handle->DeleteProxyData(uris, proxyConfig); + EXPECT_EQ(ret4[0].result_, DataProxyErrorCode::NO_PERMISSION); + + LOG_INFO("ProxyHandleTest_Delete_Test_002::End"); +} + +/** + * @tc.name: ProxyHandleTest_Delete_Test_003 + * @tc.desc: Verify that DataProxyHandle fails to delete unpublished data + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the operation parameters to SHARED_CONFIG type + 3. Attempt to delete unpublished test data + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data deletion operation returns a URI_NOT_EXIST status code + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Delete_Test_003, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Delete_Test_003::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + std::vector uris; + uris.push_back(TEST_UNUSED_URI); + + // delete unpublished data failed + auto ret4 = handle->DeleteProxyData(uris, proxyConfig); + EXPECT_EQ(ret4[0].result_, DataProxyErrorCode::URI_NOT_EXIST); + + LOG_INFO("ProxyHandleTest_Delete_Test_003::End"); +} + +/** + * @tc.name: ProxyHandleTest_Get_Test_001 + * @tc.desc: Verify that DataProxyHandle fails to retrieve unpublished data + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the operation parameters to SHARED_CONFIG type + 3. Attempt to retrieve unpublished test data + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data retrieval operation returns a URI_NOT_EXIST status code + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Get_Test_001, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Get_Test_001::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + std::vector uris; + uris.push_back(TEST_UNUSED_URI); + + // delete unpublished data failed + auto ret4 = handle->GetProxyData(uris, proxyConfig); + EXPECT_EQ(ret4[0].result_, DataProxyErrorCode::URI_NOT_EXIST); + + LOG_INFO("ProxyHandleTest_Get_Test_001::End"); +} + +/** + * @tc.name: ProxyHandleTest_Subscribe_Test_001 + * @tc.desc: Verify the functionality of DataProxyHandle successfully subscribing + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the operation parameters to SHARED_CONFIG type + 3. Publish initial test data + 4. Subscribe to data change events + 5. Update the subscribed data + * @tc.expect: + 1. The data publish operation returns a SUCCESS status code + 2. The data subscription operation returns a SUCCESS status code + 3. The callback function is triggered once after the data is updated + 4. The number of change notifications received by the callback function is correct + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Subscribe_Test_001, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Subscribe_Test_001::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish data first + DataProxyValue value1 = "hello"; + DataShareProxyData data1(TEST_URI1, value1); + std::vector proxyData1; + proxyData1.push_back(data1); + handle->PublishProxyData(proxyData1, proxyConfig); + + std::vector uris; + uris.push_back(TEST_URI1); + // subscribe data + g_callbackTimes = 0; + auto ret4 = handle->SubscribeProxyData(uris, [](const std::vector &changeNode) { + LOG_INFO("ProxyHandleTest_Subscribe_Test_001::CallBack success"); + g_callbackTimes++; + EXPECT_EQ(changeNode.size(), 1); + }); + EXPECT_EQ(ret4[0].result_, DataProxyErrorCode::SUCCESS); + + // publish data and do callback + DataProxyValue value2 = "world"; + DataShareProxyData data2(TEST_URI1, value2); + std::vector proxyData2; + proxyData2.push_back(data2); + handle->PublishProxyData(proxyData2, proxyConfig); + EXPECT_EQ(g_callbackTimes, 1); + LOG_INFO("ProxyHandleTest_Subscribe_Test_001::End"); +} + +/** + * @tc.name: ProxyHandleTest_Subscribe_Test_002 + * @tc.desc: Verify that DataProxyHandle fails to subscribe to unpublished data + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the operation parameters to SHARED_CONFIG type + 3. Attempt to subscribe to unpublished test data + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data subscription operation returns a URI_NOT_EXIST status code + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Subscribe_Test_002, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Subscribe_Test_002::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + std::vector uris; + uris.push_back(TEST_UNUSED_URI); + // subscribe data + g_callbackTimes = 0; + auto ret4 = handle->SubscribeProxyData(uris, [](const std::vector &changeNode) { + LOG_INFO("ProxyHandleTest_Subscribe_Test_002::CallBack success"); + g_callbackTimes++; + EXPECT_EQ(changeNode.size(), 1); + }); + EXPECT_EQ(ret4[0].result_, DataProxyErrorCode::URI_NOT_EXIST); + + LOG_INFO("ProxyHandleTest_Subscribe_Test_002::End"); +} + +/** + * @tc.name: ProxyHandleTest_Unsubscribe_Test_001 + * @tc.desc: Verify the functionality of DataProxyHandle successfully unsubscribing from data changes + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the operation parameters to SHARED_CONFIG type + 3. Publish initial test data + 4. Subscribe to data change events + 5. Update the data to verify that the callback function is triggered + 6. Unsubscribe from the data + 7. Update the data again + * @tc.expect: + 1. The data publish operation returns a SUCCESS status code + 2. The data subscription operation returns a SUCCESS status code + 3. The callback function is triggered after the first data update + 4. The unsubscribe operation is successful + 5. The callback function is not triggered after the second data update + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Unsubscribe_Test_001, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Unsubscribe_Test_001::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish data first + DataProxyValue value1 = "hello"; + DataShareProxyData data1(TEST_URI1, value1); + std::vector proxyData1; + proxyData1.push_back(data1); + handle->PublishProxyData(proxyData1, proxyConfig); + + std::vector uris; + uris.push_back(TEST_URI1); + // subscribe data + g_callbackTimes = 0; + auto ret4 = handle->SubscribeProxyData(uris, [](const std::vector &changeNode) { + LOG_INFO("ProxyHandleTest_Unsubscribe_Test_001::CallBack success"); + g_callbackTimes++; + EXPECT_EQ(changeNode.size(), 1); + }); + EXPECT_EQ(ret4[0].result_, DataProxyErrorCode::SUCCESS); + + // publish data and do callback + DataProxyValue value2 = "world"; + DataShareProxyData data2(TEST_URI1, value2); + std::vector proxyData2; + proxyData2.push_back(data2); + handle->PublishProxyData(proxyData2, proxyConfig); + + // unsubscribe data success + ret4 = handle->UnsubscribeProxyData(uris); + + + // publish data and not do callback + handle->PublishProxyData(proxyData2, proxyConfig); + LOG_INFO("ProxyHandleTest_Unsubscribe_Test_001::End"); +} + +/** + * @tc.name: ProxyHandleTest_Unsubscribe_Test_002 + * @tc.desc: Verify the functionality of DataProxyHandle successfully unsubscribing + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the operation parameters to SHARED_CONFIG type + 3. Publish initial test data + 4. Subscribe to data change events + 5. Update the data to verify that the callback function is triggered + 6. Call the unsubscribe interface with no parameters to unsubscribe from all subscriptions + 7. Update the data again + * @tc.expect: + 1. The data publish operation returns a SUCCESS status code + 2. The data subscription operation returns a SUCCESS status code + 3. The callback function is triggered after the first data update + 4. The operation to unsubscribe from all subscriptions is successful + 5. The callback function is not triggered after the second data update + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Unsubscribe_Test_002, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Unsubscribe_Test_002::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish data first + DataProxyValue value1 = "hello"; + DataShareProxyData data1(TEST_URI1, value1); + std::vector proxyData1; + proxyData1.push_back(data1); + handle->PublishProxyData(proxyData1, proxyConfig); + + std::vector uris; + uris.push_back(TEST_URI1); + // subscribe data + g_callbackTimes = 0; + auto ret4 = handle->SubscribeProxyData(uris, [](const std::vector &changeNode) { + LOG_INFO("ProxyHandleTest_Unsubscribe_Test_002::CallBack success"); + g_callbackTimes++; + EXPECT_EQ(changeNode.size(), 1); + }); + EXPECT_EQ(ret4[0].result_, DataProxyErrorCode::SUCCESS); + + // publish data and do callback + DataProxyValue value2 = "world"; + DataShareProxyData data2(TEST_URI1, value2); + std::vector proxyData2; + proxyData2.push_back(data2); + handle->PublishProxyData(proxyData2, proxyConfig); + + // unsubscribe all uris success + std::vector emptyUris; + auto ret2 = handle->UnsubscribeProxyData(emptyUris); + + // publish data and not do callback + handle->PublishProxyData(proxyData2, proxyConfig); + LOG_INFO("ProxyHandleTest_Unsubscribe_Test_002::End"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/datashare_access_threshold_test/datashare_threshold_test.cpp b/data_share/test/native/unittest/datashare_access_threshold_test/datashare_threshold_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ea24c43830242b13ab059123be183351b8781a7 --- /dev/null +++ b/data_share/test/native/unittest/datashare_access_threshold_test/datashare_threshold_test.cpp @@ -0,0 +1,762 @@ +/* + * Copyright (C) 2025 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 "datashare_helper.h" + +#include + +#include "accesstoken_kit.h" +#include "data_ability_observer_stub.h" +#include "datashare_log.h" +#include "hap_token_info.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "token_setproc.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::Security::AccessToken; +using ChangeInfo = DataShareObserver::ChangeInfo; +constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::string SLIENT_ACCESS_URI = "datashareproxy://com.acts.datasharetest/test?Proxy=true"; +std::string TBL_STU_NAME = "name"; +std::string TBL_STU_AGE = "age"; +std::shared_ptr g_exHelper; + +class DataShareThresholdTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +class IDataShareAbilityObserverTest : public AAFwk::DataAbilityObserverStub { +public: + explicit IDataShareAbilityObserverTest(int code) + { + code_ = code; + } + + ~IDataShareAbilityObserverTest() + {} + + void OnChange() {} + + int code_; +}; + +std::shared_ptr CreateDataShareHelper(int32_t systemAbilityId, std::string uri) +{ + LOG_INFO("CreateDataShareHelper start"); + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saManager == nullptr) { + LOG_ERROR("GetSystemAbilityManager get samgr failed."); + return nullptr; + } + auto remoteObj = saManager->GetSystemAbility(systemAbilityId); + if (remoteObj == nullptr) { + LOG_ERROR("GetSystemAbility service failed."); + return nullptr; + } + return DataShare::DataShareHelper::Creator(remoteObj, uri); +} + + +std::vector GetPermissionStateFulls() +{ + std::vector permissionStateFulls = { + { + .permissionName = "ohos.permission.WRITE_CONTACTS", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + }, + { + .permissionName = "ohos.permission.WRITE_CALL_LOG", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + }, + { + .permissionName = "ohos.permission.GET_BUNDLE_INFO", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + } + }; + return permissionStateFulls; +} + +void DataShareThresholdTest::SetUpTestCase(void) +{ + LOG_INFO("SetUpTestCase invoked"); + auto dataShareHelper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, DATA_SHARE_URI); + ASSERT_TRUE(dataShareHelper != nullptr); + int sleepTime = 3; + sleep(sleepTime); + + HapInfoParams info = { + .userID = 100, + .bundleName = "ohos.datashareclienttest.demo", + .instIndex = 0, + .appIDDesc = "ohos.datashareclienttest.demo" + }; + auto permStateList = GetPermissionStateFulls(); + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.datashareclienttest.demo", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "ohos.datashareclienttest.demo", + .descriptionId = 1 + } + }, + .permStateList = permStateList + }; + AccessTokenKit::AllocHapToken(info, policy); + auto testTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenIDEx( + info.userID, info.bundleName, info.instIndex); + SetSelfTokenID(testTokenId.tokenIDEx); + + g_exHelper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, DATA_SHARE_URI); + ASSERT_TRUE(g_exHelper != nullptr); + LOG_INFO("SetUpTestCase end"); +} + +void DataShareThresholdTest::TearDownTestCase(void) +{ + auto tokenId = AccessTokenKit::GetHapTokenIDEx(100, "ohos.datashareclienttest.demo", 0); + AccessTokenKit::DeleteToken(tokenId.tokenIDEx); + g_exHelper = nullptr; +} + +void DataShareThresholdTest::SetUp(void) {} +void DataShareThresholdTest::TearDown(void) {} + +/** + * @tc.name: Insert_Threshold_Test001 + * @tc.desc: Verify silent access Insert operation behavior when exceeding and not exceeding the threshold + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataShareHelper instance with silent access configuration + 2. Prepare test data (name and age) in a DataShareValuesBucket + 3. Perform initial Insert operation and verify success + 4. Perform 2998 additional Insert operations (not exceeding threshold) and verify success + 5. Perform 10 more Insert operations (exceeding threshold) and check results + * @tc.expect: + 1. DataShareHelper is created successfully (not nullptr) + 2. All Insert operations before threshold return positive values (success) + 3. All Insert operations after threshold return DATA_SHARE_ERROR(-1) + */ +HWTEST_F(DataShareThresholdTest, Insert_Threshold_Test001, TestSize.Level1) +{ + LOG_INFO("Insert_Threshold_Test001::Start"); + auto helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, SLIENT_ACCESS_URI); + ASSERT_TRUE(helper != nullptr); + + Uri uri(SLIENT_ACCESS_URI); + + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "zhangsan"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 18; + valuesBucket.Put(TBL_STU_AGE, age); + int retVal = helper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal > 0), true); + + DataShare::DataShareValuesBucket valuesBucket1; + std::string value1 = "lisi"; + valuesBucket1.Put(TBL_STU_NAME, value1); + age = 25; + valuesBucket1.Put(TBL_STU_AGE, age); + // not over threshold, insert success + for (int i = 0; i < 2998; i++) { + retVal = helper->Insert(uri, valuesBucket1); + EXPECT_EQ((retVal > 0), true); + } + + // over threshold, insert ret DATA_SHARE_ERROR(-1) + for (int i = 0; i < 10; i++) { + retVal = helper->Insert(uri, valuesBucket1); + EXPECT_EQ(retVal, -1); + } + LOG_INFO("Insert_Threshold_Test001::End"); +} + +/** +* @tc.name: Update_Threshold_Test001 +* @tc.desc: Verify silent access Update operation behavior when exceeding and not exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Create a DataShareHelper instance with silent access configuration + 2. Define update predicates to target specific data + 3. Prepare update data in a DataShareValuesBucket + 4. Perform 2999 Update operations (not exceeding threshold) and verify success + 5. Perform 10 more Update operations (exceeding threshold) and check results +* @tc.expect: + 1. DataShareHelper is created successfully (not nullptr) + 2. All Update operations before threshold return 1 (success) + 3. All Update operations after threshold return DATA_SHARE_ERROR(-1) +*/ +HWTEST_F(DataShareThresholdTest, Update_Threshold_Test001, TestSize.Level1) +{ + LOG_INFO("Update_Threshold_Test001::Start"); + auto helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, SLIENT_ACCESS_URI); + ASSERT_TRUE(helper != nullptr); + + Uri uri(SLIENT_ACCESS_URI); + + DataShare::DataSharePredicates predicates; + std::string selections = TBL_STU_NAME + " = 'zhangsan'"; + predicates.SetWhereClause(selections); + + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put(TBL_STU_AGE, 10); + // not over threshold, update success + for (int i = 0; i < 2999; i++) { + int retVal = helper->Update(uri, predicates, valuesBucket); + EXPECT_EQ(retVal, 1); + } + + // over threshold, update ret DATA_SHARE_ERROR(-1) + for (int i = 0; i < 10; i++) { + int retVal = helper->Update(uri, predicates, valuesBucket); + EXPECT_EQ(retVal, -1); + } + LOG_INFO("Update_Threshold_Test001::End"); +} + +/** +* @tc.name: Query_Threshold_Test001 +* @tc.desc: Verify silent access Query operation behavior when exceeding and not exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Create a DataShareHelper instance with silent access configuration + 2. Define query predicates to target specific data + 3. Perform 2999 Query operations (not exceeding threshold) and verify results + 4. Perform 10 more Query operations (exceeding threshold) and check results +* @tc.expect: + 1. DataShareHelper is created successfully (not nullptr) + 2. All Query operations before threshold return valid result sets with 1 row + 3. All Query operations after threshold return nullptr (DATA_SHARE_ERROR) +*/ +HWTEST_F(DataShareThresholdTest, Query_Threshold_Test001, TestSize.Level1) +{ + LOG_INFO("Query_Threshold_Test001::Start"); + auto helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, SLIENT_ACCESS_URI); + ASSERT_TRUE(helper != nullptr); + + Uri uri(SLIENT_ACCESS_URI); + + DataShare::DataSharePredicates predicates; + predicates.EqualTo(TBL_STU_NAME, "zhangsan"); + vector columns; + int result = 0; + + // not over threshold, query success + for (int i = 0; i < 2999; i++) { + auto resultSet = helper->Query(uri, predicates, columns); + ASSERT_NE(resultSet, nullptr); + resultSet->GetRowCount(result); + EXPECT_EQ(result, 1); + resultSet->Close(); + } + + // over threshold, query ret DATA_SHARE_ERROR(-1) + for (int i = 0; i < 10; i++) { + auto resultSet = helper->Query(uri, predicates, columns); + ASSERT_EQ(resultSet, nullptr); + } + LOG_INFO("Query_Threshold_Test001::End"); +} + +/** +* @tc.name: Delete_Threshold_Test001 +* @tc.desc: Verify silent access Delete operation behavior when exceeding and not exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Create a DataShareHelper instance with silent access configuration + 2. Define delete predicates targeting non-existent data + 3. Perform 2999 Delete operations (not exceeding threshold) and verify results + 4. Perform 10 more Delete operations (exceeding threshold) and check results +* @tc.expect: + 1. DataShareHelper is created successfully (not nullptr) + 2. All Delete operations before threshold return 0 (no data deleted) + 3. All Delete operations after threshold return DATA_SHARE_ERROR(-1) +*/ +HWTEST_F(DataShareThresholdTest, Delete_Threshold_Test001, TestSize.Level1) +{ + LOG_INFO("Delete_Threshold_Test001::Start"); + auto helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, SLIENT_ACCESS_URI); + ASSERT_TRUE(helper != nullptr); + + Uri uri(SLIENT_ACCESS_URI); + + DataShare::DataSharePredicates deletePredicates; + std::string selections = TBL_STU_NAME + " = 'lisan'"; + deletePredicates.SetWhereClause(selections); + + // not over threshold, delete data not exists return 0 + for (int i = 0; i < 2999; i++) { + int retVal = helper->Delete(uri, deletePredicates); + EXPECT_EQ(retVal, 0); + } + + // over threshold, delete ret -1 + for (int i = 0; i < 10; i++) { + int retVal = helper->Delete(uri, deletePredicates); + EXPECT_EQ(retVal, -1); + } + LOG_INFO("Delete_Threshold_Test001::End"); +} + +/** +* @tc.name: InsertEx_Threshold_Test001 +* @tc.desc: Verify silent access InsertEx operation behavior when exceeding and not exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Create a DataShareHelper instance with silent access configuration + 2. Prepare test data (name and age) in a DataShareValuesBucket + 3. Perform 2999 InsertEx operations (not exceeding threshold) and verify success + 4. Perform 10 more InsertEx operations (exceeding threshold) and check results +* @tc.expect: + 1. DataShareHelper is created successfully (not nullptr) + 2. All InsertEx operations before threshold return (0, positive value) indicating success + 3. All InsertEx operations after threshold return (DATA_SHARE_ERROR(-1), 0) +*/ +HWTEST_F(DataShareThresholdTest, InsertEx_Threshold_Test001, TestSize.Level1) +{ + LOG_INFO("InsertEx_Threshold_Test001::Start"); + + auto helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, SLIENT_ACCESS_URI); + ASSERT_TRUE(helper != nullptr); + + 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); + // not over threshold, insertEx success + for (int i = 0; i < 2999; i++) { + auto [errCode, retVal] = helper->InsertEx(uri, valuesBucket); + EXPECT_EQ(errCode, 0); + EXPECT_EQ((retVal > 0), true); + } + + // over threshold, insertEx ret pair(DATA_SHARE_ERROR, 0) + for (int i = 0; i < 10; i++) { + auto [errCode, retVal] = helper->InsertEx(uri, valuesBucket); + EXPECT_EQ(errCode, -1); + EXPECT_EQ(retVal, 0); + } + LOG_INFO("InsertEx_Threshold_Test001::End"); +} + +/** +* @tc.name: UpdateEx_Threshold_Test001 +* @tc.desc: Verify silent access UpdateEx operation behavior when exceeding and not exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Create a DataShareHelper instance with silent access configuration + 2. Define update predicates to target specific data + 3. Prepare update data in a DataShareValuesBucket + 4. Perform 2999 UpdateEx operations (not exceeding threshold) and verify success + 5. Perform 10 more UpdateEx operations (exceeding threshold) and check results +* @tc.expect: + 1. DataShareHelper is created successfully (not nullptr) + 2. All UpdateEx operations before threshold return (0, 1) indicating success + 3. All UpdateEx operations after threshold return (DATA_SHARE_ERROR(-1), 0) +*/ +HWTEST_F(DataShareThresholdTest, UpdateEx_Threshold_Test001, TestSize.Level1) +{ + LOG_INFO("UpdateEx_Threshold_Test001::Start"); + + auto helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, SLIENT_ACCESS_URI); + ASSERT_TRUE(helper != nullptr); + + Uri uri(SLIENT_ACCESS_URI); + + DataShare::DataSharePredicates predicates; + std::string selections = TBL_STU_NAME + " = 'zhangsan'"; + predicates.SetWhereClause(selections); + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put(TBL_STU_AGE, 10); + + // not over threshold, updateEx success + for (int i = 0; i < 2999; i++) { + auto [errCode, retVal] = helper->UpdateEx(uri, predicates, valuesBucket); + EXPECT_EQ(errCode, 0); + EXPECT_EQ(retVal, 1); + } + + // over threshold, updateEx ret pair(DATA_SHARE_ERROR, 0) + for (int i = 0; i < 10; i++) { + auto [errCode, retVal] = helper->UpdateEx(uri, predicates, valuesBucket); + EXPECT_EQ(errCode, -1); + EXPECT_EQ(retVal, 0); + } + LOG_INFO("UpdateEx_Threshold_Test001::End"); +} + +/** +* @tc.name: DeleteEx_Threshold_Test001 +* @tc.desc: Verify silent access DeleteEx operation behavior when exceeding and not exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Create a DataShareHelper instance with silent access configuration + 2. Define delete predicates targeting non-existent data + 3. Perform 2999 DeleteEx operations (not exceeding threshold) and verify results + 4. Perform 10 more DeleteEx operations (exceeding threshold) and check results +* @tc.expect: + 1. DataShareHelper is created successfully (not nullptr) + 2. All DeleteEx operations before threshold return (0, 0) indicating no data deleted + 3. All DeleteEx operations after threshold return (DATA_SHARE_ERROR(-1), 0) +*/ +HWTEST_F(DataShareThresholdTest, DeleteEx_Threshold_Test001, TestSize.Level1) +{ + LOG_INFO("DeleteEx_Threshold_Test001::Start"); + + auto helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, SLIENT_ACCESS_URI); + ASSERT_TRUE(helper != nullptr); + + Uri uri(SLIENT_ACCESS_URI); + + DataShare::DataSharePredicates deletePredicates; + std::string selections = TBL_STU_NAME + " = 'lisan'"; + deletePredicates.SetWhereClause(selections); + // not over threshold, deleteEx data not exists return pair(0, 0) + for (int i = 0; i < 2999; i++) { + auto [errCode, retVal] = helper->DeleteEx(uri, deletePredicates); + EXPECT_EQ(errCode, 0); + EXPECT_EQ(retVal, 0); + } + + // over threshold, deleteEx ret pair(DATA_SHARE_ERROR, 0) + for (int i = 0; i < 10; i++) { + auto [errCode, retVal] = helper->DeleteEx(uri, deletePredicates); + EXPECT_EQ(errCode, -1); + EXPECT_EQ(retVal, 0); + } + LOG_INFO("DeleteEx_Threshold_Test001::End"); +} + +/** +* @tc.name: Insert_Threshold_Test002 +* @tc.desc: Verify non-silent access Insert operation behavior when exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Prepare test data (name and age) in a DataShareValuesBucket + 2. Perform 2999 Insert operations (not exceeding threshold) and verify success + 3. Perform 10 more Insert operations (exceeding threshold) and check results +* @tc.expect: + 1. All Insert operations before and after threshold return positive values (success) + 2. No failure occurs when exceeding threshold for non-silent access +*/ +HWTEST_F(DataShareThresholdTest, Insert_Threshold_Test002, TestSize.Level1) +{ + LOG_INFO("Insert_Threshold_Test002::Start"); + + Uri uri(DATA_SHARE_URI); + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "lisi"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 25; + valuesBucket.Put(TBL_STU_AGE, age); + // not over threshold, insert success + for (int i = 0; i < 2999; i++) { + int retVal = g_exHelper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal > 0), true); + } + + // over threshold, insert ret success + for (int i = 0; i < 10; i++) { + int retVal = g_exHelper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal > 0), true); + } + LOG_INFO("Insert_Threshold_Test002::End"); +} + +/** +* @tc.name: Update_Threshold_Test002 +* @tc.desc: Verify non-silent access Update operation behavior when exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Define update predicates to target specific data + 2. Prepare update data in a DataShareValuesBucket + 3. Perform 2999 Update operations (not exceeding threshold) and verify success + 4. Perform 10 more Update operations (exceeding threshold) and check results +* @tc.expect: + 1. All Update operations before and after threshold return 1 (success) + 2. No failure occurs when exceeding threshold for non-silent access +*/ +HWTEST_F(DataShareThresholdTest, Update_Threshold_Test002, TestSize.Level1) +{ + LOG_INFO("Update_Threshold_Test002::Start"); + + Uri uri(DATA_SHARE_URI); + + DataShare::DataSharePredicates predicates; + std::string selections = TBL_STU_NAME + " = 'zhangsan'"; + predicates.SetWhereClause(selections); + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put(TBL_STU_AGE, 10); + // not over threshold, update success + for (int i = 0; i < 2999; i++) { + int retVal = g_exHelper->Update(uri, predicates, valuesBucket); + EXPECT_EQ(retVal, 1); + } + + // over threshold, update success + for (int i = 0; i < 10; i++) { + int retVal = g_exHelper->Update(uri, predicates, valuesBucket); + EXPECT_EQ(retVal, 1); + } + LOG_INFO("Update_Threshold_Test002::End"); +} + +/** +* @tc.name: Query_Threshold_Test002 +* @tc.desc: Verify non-silent access Query operation behavior when exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Define query predicates to target specific data + 2. Perform 2999 Query operations (not exceeding threshold) and verify results + 3. Perform 10 more Query operations (exceeding threshold) and check results +* @tc.expect: + 1. All Query operations before and after threshold return valid result sets with 1 row + 2. No failure occurs when exceeding threshold for non-silent access +*/ +HWTEST_F(DataShareThresholdTest, Query_Threshold_Test002, TestSize.Level1) +{ + LOG_INFO("Query_Threshold_Test002::Start"); + + Uri uri(DATA_SHARE_URI); + DataShare::DataSharePredicates predicates; + predicates.EqualTo(TBL_STU_NAME, "zhangsan"); + vector columns; + int result = 0; + + // not over threshold, query success + for (int i = 0; i < 2999; i++) { + auto resultSet = g_exHelper->Query(uri, predicates, columns); + ASSERT_NE(resultSet, nullptr); + resultSet->GetRowCount(result); + EXPECT_EQ(result, 1); + resultSet->Close(); + } + + // over threshold, query success + for (int i = 0; i < 10; i++) { + auto resultSet = g_exHelper->Query(uri, predicates, columns); + ASSERT_NE(resultSet, nullptr); + resultSet->GetRowCount(result); + EXPECT_EQ(result, 1); + resultSet->Close(); + } + LOG_INFO("Query_Threshold_Test002::End"); +} + +/** +* @tc.name: Delete_Threshold_Test002 +* @tc.desc: Verify non-silent access Delete operation behavior when exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Define delete predicates targeting non-existent data + 2. Perform 2999 Delete operations (not exceeding threshold) and verify results + 3. Perform 10 more Delete operations (exceeding threshold) and check results +* @tc.expect: + 1. All Delete operations before and after threshold return 0 (no data deleted) + 2. No failure occurs when exceeding threshold for non-silent access +*/ +HWTEST_F(DataShareThresholdTest, Delete_Threshold_Test002, TestSize.Level1) +{ + LOG_INFO("Delete_Threshold_Test002::Start"); + + Uri uri(DATA_SHARE_URI); + + DataShare::DataSharePredicates deletePredicates; + std::string selections = TBL_STU_NAME + " = 'lisan'"; + deletePredicates.SetWhereClause(selections); + + // not over threshold, delete data not exists return 0 + for (int i = 0; i < 2999; i++) { + int retVal = g_exHelper->Delete(uri, deletePredicates); + EXPECT_EQ(retVal, 0); + } + + // over threshold, delete data not exists return 0 + for (int i = 0; i < 10; i++) { + int retVal = g_exHelper->Delete(uri, deletePredicates); + EXPECT_EQ(retVal, 0); + } + LOG_INFO("Delete_Threshold_Test002::End"); +} + +/** +* @tc.name: InsertEx_Threshold_Test002 +* @tc.desc: Verify non-silent access InsertEx operation behavior when exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Prepare test data (name and age) in a DataShareValuesBucket + 2. Perform 2999 InsertEx operations (not exceeding threshold) and verify success + 3. Perform 10 more InsertEx operations (exceeding threshold) and check results +* @tc.expect: + 1. All InsertEx operations before and after threshold return (0, positive value) indicating success + 2. No failure occurs when exceeding threshold for non-silent access +*/ +HWTEST_F(DataShareThresholdTest, InsertEx_Threshold_Test002, TestSize.Level1) +{ + LOG_INFO("InsertEx_Threshold_Test002::Start"); + + Uri uri(DATA_SHARE_URI); + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "lisi"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 25; + valuesBucket.Put(TBL_STU_AGE, age); + // not over threshold, insertEx success + for (int i = 0; i < 2999; i++) { + auto [errCode, retVal] = g_exHelper->InsertEx(uri, valuesBucket); + EXPECT_EQ(errCode, 0); + EXPECT_EQ((retVal > 0), true); + } + + // over threshold, insertEx success + for (int i = 0; i < 10; i++) { + auto [errCode, retVal] = g_exHelper->InsertEx(uri, valuesBucket); + EXPECT_EQ(errCode, 0); + EXPECT_EQ((retVal > 0), true); + } + LOG_INFO("InsertEx_Threshold_Test002::End"); +} + +/** +* @tc.name: UpdateEx_Threshold_Test002 +* @tc.desc: Verify non-silent access UpdateEx operation behavior when exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Define update predicates to target specific data + 2. Prepare update data in a DataShareValuesBucket + 3. Perform 2999 UpdateEx operations (not exceeding threshold) and verify success + 4. Perform 10 more UpdateEx operations (exceeding threshold) and check results +* @tc.expect: + 1. All UpdateEx operations before and after threshold return (0, 1) indicating success + 2. No failure occurs when exceeding threshold for non-silent access +*/ +HWTEST_F(DataShareThresholdTest, UpdateEx_Threshold_Test002, TestSize.Level1) +{ + LOG_INFO("UpdateEx_Threshold_Test002::Start"); + + Uri uri(DATA_SHARE_URI); + + DataShare::DataSharePredicates predicates; + std::string selections = TBL_STU_NAME + " = 'zhangsan'"; + predicates.SetWhereClause(selections); + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put(TBL_STU_AGE, 10); + // not over threshold, updateEx sccuess + for (int i = 0; i < 2999; i++) { + auto [errCode, retVal] = g_exHelper->UpdateEx(uri, predicates, valuesBucket); + EXPECT_EQ(errCode, 0); + EXPECT_EQ(retVal, 1); + } + + // over threshold, updateEx ret success + for (int i = 0; i < 10; i++) { + auto [errCode, retVal] = g_exHelper->UpdateEx(uri, predicates, valuesBucket); + EXPECT_EQ(errCode, 0); + EXPECT_EQ(retVal, 1); + } + LOG_INFO("UpdateEx_Threshold_Test002::End"); +} + +/** +* @tc.name: DeleteEx_Threshold_Test002 +* @tc.desc: Verify non-silent access DeleteEx operation behavior when exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Define delete predicates targeting non-existent data + 2. Perform 2999 DeleteEx operations (not exceeding threshold) and verify results + 3. Perform 10 more DeleteEx operations (exceeding threshold) and check results +* @tc.expect: + 1. All DeleteEx operations before and after threshold return (0, 0) indicating no data deleted + 2. No failure occurs when exceeding threshold for non-silent access +*/ +HWTEST_F(DataShareThresholdTest, DeleteEx_Threshold_Test002, TestSize.Level1) +{ + LOG_INFO("DeleteEx_Threshold_Test002::Start"); + + Uri uri(DATA_SHARE_URI); + + DataShare::DataSharePredicates deletePredicates; + std::string selections = TBL_STU_NAME + " = 'lisan'"; + deletePredicates.SetWhereClause(selections); + // not over threshold, deleteEx data not exists return pair(0, 0) + for (int i = 0; i < 2999; i++) { + auto [errCode, retVal] = g_exHelper->DeleteEx(uri, deletePredicates); + EXPECT_EQ(errCode, 0); + EXPECT_EQ(retVal, 0); + } + + // over threshold, deleteEx data not exists return pair(0, 0) + for (int i = 0; i < 10; i++) { + auto [errCode, retVal] = g_exHelper->DeleteEx(uri, deletePredicates); + EXPECT_EQ(errCode, 0); + EXPECT_EQ(retVal, 0); + } + LOG_INFO("DeleteEx_Threshold_Test002::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/native/unittest/datashare_common_test/datashare_itypes_utils_test.cpp b/data_share/test/native/unittest/datashare_common_test/datashare_itypes_utils_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1bcde613a37f76e597a9d93927fdb501c00a3af3 --- /dev/null +++ b/data_share/test/native/unittest/datashare_common_test/datashare_itypes_utils_test.cpp @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2025 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 "DatashareItypesUtilsTest" + +#include +#include + +#include "datashare_itypes_utils.h" +#include "log_print.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::DataShare; +using namespace OHOS::ITypesUtil; +class DatashareItypesUtilsTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +RdbChangeNode CreateRdbChangeNode() +{ + TemplateId templateId = TemplateId{123, "com.acts.datasharetest"}; + RdbChangeNode changeNode = RdbChangeNode{ + "datashare:///com.acts.datasharetest", + templateId, + {"deleted", "inserted", "updated"}, + false, + nullptr, + 8 + }; + return changeNode; +} + +bool operator==(const RdbChangeNode node1, const RdbChangeNode node2) +{ + bool firstPart = node1.uri_ == node2.uri_ + && node1.templateId_ == node2.templateId_ + && node1.data_ == node2.data_ + && node1.isSharedMemory_ == node2.isSharedMemory_ + && node1.size_ == node2.size_; + if (node1.memory_ == nullptr && node2.memory_ == nullptr) { + return firstPart && true; + } else if (node1.memory_ != nullptr && node2.memory_ != nullptr) { + return firstPart; + } + return false; +} + +/** + * @tc.name: Marshal_BatchUpdateResult_001 + * @tc.desc: Verify BatchUpdateResult marshal and unmarshal with marshalable data. + * This test case checks if the BatchUpdateResult object can be + * orrectly marshaled and unmarshaled. + * @tc.expect: The test expects that the marshaled and unmarshaled + * BatchUpdateResult objects are equal. + * @tc.step: + * 1. Create a BatchUpdateResult object and set its uri and codes. + * 2. Marshal the BatchUpdateResult object into a MessageParcel. + * 3. Unmarshal the BatchUpdateResult object from the MessageParcel. + * 4. Compare the original and unmarshaled BatchUpdateResult objects. + * @tc.type: FUNC + * @tc.precon: The test requires that the BatchUpdateResult object is initialized. + * @tc.require:issueIBYE9X + */ +HWTEST_F(DatashareItypesUtilsTest, Marshal_BatchUpdateResult_001, TestSize.Level0) +{ + ZLOGI("Marshal_BatchUpdateResult_001 starts"); + // Initialize the BatchUpdateResult object + BatchUpdateResult result; + BatchUpdateResult unmashalResult; + result.uri = "datashare:///com.acts.datasharetest"; + result.codes = {12, 2, 4}; + + MessageParcel parcel; + bool res = ITypesUtil::Marshalling(result, parcel); + EXPECT_TRUE(res); + + res = ITypesUtil::Unmarshalling(unmashalResult, parcel); + EXPECT_TRUE(res); + + // Compare the original and unmarshalled results + EXPECT_EQ(result.uri, unmashalResult.uri); + EXPECT_EQ(result.codes, unmashalResult.codes); + ZLOGI("Marshal_BatchUpdateResult_001 ends"); +} + +/** + * @tc.name: Marshal_RdbChangeNode_001 + * @tc.desc: Test the marshalling function of RdbChangeNode with isSharedMemory_ set to false. + * @tc.expect: The marshalling and unmarshalling process should succeed and the original + * RdbChangeNode object should be equal to the unmarshalled one. + * @tc.step: + * 1. Create a RdbChangeNode object with isSharedMemory_ set to false and a MessageParcel object. + * 2. Use the ITypesUtil::Marshalling function to marshal the RdbChangeNode object into + * the MessageParcel object. + * 3. Use the ITypesUtil::Unmarshalling function to unmarshal the RdbChangeNode object from + * the MessageParcel object. + * 4. Compare the original RdbChangeNode object with the unmarshalled one. + * @tc.type: FUNC + * @tc.precon: The test requires that the BatchUpdateResult object is initialized and isSharedMemory_ + * is set to false. + * @tc.require:issueIBYE9X + */ +HWTEST_F(DatashareItypesUtilsTest, Marshal_RdbChangeNode_001, TestSize.Level0) +{ + ZLOGI("Marshal_RdbChangeNode_001 starts"); + + RdbChangeNode unmashalchangeNode; + MessageParcel parcel; + RdbChangeNode changeNode = CreateRdbChangeNode(); + + bool res = ITypesUtil::Marshalling(changeNode, parcel); + EXPECT_TRUE(res); + res = ITypesUtil::Unmarshalling(unmashalchangeNode, parcel); + EXPECT_TRUE(res); + + EXPECT_TRUE(changeNode == unmashalchangeNode); + ZLOGI("Marshal_RdbChangeNode_001 ends"); +} + +/** + * @tc.name: Marshal_RdbChangeNode_002 + * @tc.desc: Test the marshalling function of RdbChangeNode with isSharedMemory_ set to + * true and memory_ set to nullptr. + * @tc.expect: The test expects the marshalling operation to fail due to the + * memory_ member being set to nullptr. + * @tc.step: + * 1. Create an RdbChangeNode instance and set its isSharedMemory_ flag to true. + * 2: Set the memory_ member of the RdbChangeNode instance to nullptr. + * 3: Attempt to marshalling the RdbChangeNode instance into a MessageParcel using + * the ITypesUtil::Marshalling method. + * 4: Verify that the marshalling operation fails by checking the return value of + * the ITypesUtil::Marshalling method, which should be false. + * @tc.type: FUNC + * @tc.precon: The test requires that the BatchUpdateResult object is initialized, while isSharedMemory_ + * is set to true, and memory_ set to nullptr. + * @tc.require:issueIBYE9X + */ +HWTEST_F(DatashareItypesUtilsTest, Marshal_RdbChangeNode_002, TestSize.Level0) +{ + ZLOGI("Marshal_RdbChangeNode_002 starts"); + + RdbChangeNode unmashalchangeNode; + MessageParcel parcel; + RdbChangeNode changeNode = CreateRdbChangeNode(); + changeNode.isSharedMemory_ = true; + changeNode.memory_ = nullptr; + + bool res = ITypesUtil::Marshalling(changeNode, parcel); + EXPECT_FALSE(res); + ZLOGI("Marshal_RdbChangeNode_002 ends"); +} + +/** + * @tc.name: Marshal_RdbChangeNode_003 + * @tc.desc: Test the marshalling and unmarshalling functionality of RdbChangeNode + * @tc.expect: The marshalling and unmarshalling process should succeed, + * data correctness and consistency should be ensured. + * @tc.step: + * 1. Create a RdbChangeNode object and set isSharedMemory_ flag to true. + * 2. Use CreateAshmem to create a shared memory object and set it to the memory_ member + * of the RdbChangeNode object. + * 3. Use ashmem to write data into the shared memory of the RdbChangeNode object. + * 3. Use the Unmarshalling method of ITypesUtil to deserialize the MessageParcel object + * into another RdbChangeNode object. + * 4. Verify that the original RdbChangeNode object and the deserialized RdbChangeNode objects + * are consistent with each other and the unmarshalling procress is successful. + * 5. Close the ashmem of the RdbChangeNode objects. + * @tc.type: FUNC + * @tc.precon: The test requires that the BatchUpdateResult object is initialized, while isSharedMemory_ + * is set to true, and use CreateAshmem to create a shared memory object to put in memory_. + * @tc.require:issueIBYE9X + */ +HWTEST_F(DatashareItypesUtilsTest, Marshal_RdbChangeNode_003, TestSize.Level0) +{ + ZLOGI("Marshal_RdbChangeNode_003 starts"); + + RdbChangeNode unmashalchangeNode; + MessageParcel parcel; + RdbChangeNode changeNode = CreateRdbChangeNode(); + changeNode.isSharedMemory_ = true; + changeNode.memory_ = Ashmem::CreateAshmem("testd", 8); + bool mapRet = changeNode.memory_->MapReadAndWriteAshmem(); + EXPECT_TRUE(mapRet); + + int32_t data = 123; + bool writeRet = changeNode.memory_->WriteToAshmem(&data, sizeof(data), 0); + EXPECT_TRUE(writeRet); + bool res = ITypesUtil::Marshalling(changeNode, parcel); + EXPECT_TRUE(res); + res = ITypesUtil::Unmarshalling(unmashalchangeNode, parcel); + EXPECT_TRUE(res); + mapRet = unmashalchangeNode.memory_->MapReadAndWriteAshmem(); + EXPECT_TRUE(mapRet); + + auto changeNodeData = changeNode.memory_->ReadFromAshmem(sizeof(data), 0); + EXPECT_NE(changeNodeData, nullptr); + auto unmashalchangeNodeData = unmashalchangeNode.memory_->ReadFromAshmem(sizeof(data), 0); + EXPECT_NE(unmashalchangeNodeData, nullptr); + + int32_t changeNodeValue = *(reinterpret_cast(changeNodeData)); + int32_t unmashalchangeNodeValue = *(reinterpret_cast(unmashalchangeNodeData)); + EXPECT_TRUE(changeNode == unmashalchangeNode && changeNodeValue == unmashalchangeNodeValue); + changeNode.memory_->CloseAshmem(); + unmashalchangeNode.memory_->CloseAshmem(); + ZLOGI("Marshal_RdbChangeNode_003 ends"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file 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 1a5de881546d380707d18efb2af3c690d81d8c8c..08beecead0432ee0dbd8990e357343022a8c0bad 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 @@ -31,6 +31,7 @@ using namespace testing::ext; using namespace OHOS::Security::AccessToken; std::string DATA_SHARE_PROXY_URI = "datashareproxy://com.acts.ohos.data.datasharetest/test"; std::shared_ptr dataShareHelper; +std::shared_ptr dataShareHelper2; // for another subscriber std::string TBL_NAME0 = "name0"; std::string TBL_NAME1 = "name1"; constexpr int SUBSCRIBER_ID = 100; @@ -53,7 +54,8 @@ void ProxyDatasTest::SetUpTestCase(void) HapInfoParams info = { .userID = 100, .bundleName = "ohos.datashareproxyclienttest.demo", .instIndex = 0, - .appIDDesc = "ohos.datashareproxyclienttest.demo" }; + .appIDDesc = "ohos.datashareproxyclienttest.demo", + .isSystemApp = true }; HapPolicyParams policy = { .apl = APL_SYSTEM_BASIC, .domain = "test.domain", .permList = { { .permissionName = "ohos.permission.GET_BUNDLE_INFO", @@ -70,14 +72,16 @@ void ProxyDatasTest::SetUpTestCase(void) .grantStatus = { PermissionState::PERMISSION_GRANTED }, .grantFlags = { 1 } } } }; AccessTokenKit::AllocHapToken(info, policy); - auto testTokenId = - Security::AccessToken::AccessTokenKit::GetHapTokenID(info.userID, info.bundleName, info.instIndex); - SetSelfTokenID(testTokenId); + auto testTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenIDEx( + info.userID, info.bundleName, info.instIndex); + SetSelfTokenID(testTokenId.tokenIDEx); CreateOptions options; options.enabled_ = true; dataShareHelper = DataShare::DataShareHelper::Creator(DATA_SHARE_PROXY_URI, options); ASSERT_TRUE(dataShareHelper != nullptr); + dataShareHelper2 = DataShare::DataShareHelper::Creator(DATA_SHARE_PROXY_URI, options); + ASSERT_TRUE(dataShareHelper2 != nullptr); LOG_INFO("SetUpTestCase end"); } @@ -86,6 +90,7 @@ void ProxyDatasTest::TearDownTestCase(void) auto tokenId = AccessTokenKit::GetHapTokenID(100, "ohos.datashareclienttest.demo", 0); AccessTokenKit::DeleteToken(tokenId); dataShareHelper = nullptr; + dataShareHelper2 = nullptr; } void ProxyDatasTest::SetUp(void) @@ -95,7 +100,21 @@ void ProxyDatasTest::TearDown(void) { } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Insert_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_Insert_Test_001 + * @tc.desc: Verify the functionality of DataShareHelper successfully inserting data into the data share proxy + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create a Uri object using the data share proxy URI + 3. Prepare a DataShareValuesBucket and add string data to it + 4. Call the Insert method of DataShareHelper with the Uri and ValuesBucket + * @tc.expect: + 1. The return value of the Insert method is greater than 0, indicating successful data insertion + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Insert_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Insert_Test_001::Start"); auto helper = dataShareHelper; @@ -111,7 +130,23 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Insert_Test_001, TestSize.Level0) LOG_INFO("ProxyDatasTest_Insert_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_QUERY_Test_001, TestSize.Level0) +/** +* @tc.name: ProxyDatasTest_QUERY_Test_001 +* @tc.desc: Verify basic query functionality with specific equality condition +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: Test data containing record with TBL_NAME0 value "wang" exists +* @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI + 3. Create DataSharePredicates with condition: TBL_NAME0 equals "wang" + 4. Execute query with empty columns list + 5. Check the returned result set and its row count +* @tc.expect: + 1. Query returns a non-null result set + 2. Result set contains exactly 1 record (row count = 1) +*/ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_QUERY_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_QUERY_Test_001::Start"); auto helper = dataShareHelper; @@ -127,7 +162,261 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_QUERY_Test_001, TestSize.Level0) LOG_INFO("ProxyDatasTest_QUERY_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_ResultSet_Test_001, TestSize.Level0) +/** +* @tc.name: ProxyDatasTest_QueryTimout_Test_001 +* @tc.desc: Verify query timeout functionality with zero timeout configuration +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: Test data containing record with TBL_NAME0 value "wang" exists +* @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI + 3. Create DataSharePredicates with condition: TBL_NAME0 equals "wang" + 4. Configure DataShareOption with timeout set to 0 + 5. Execute QueryTimeout with specified parameters and business error pointer + 6. Verify result set and error code +* @tc.expect: + 1. Query returns a non-null result set + 2. Business error code is E_OK (success status) +*/ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_QueryTimeout_Test_001, TestSize.Level1) +{ + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_001::Start"); + auto helper = dataShareHelper; + Uri uri(DATA_SHARE_PROXY_URI); + DataShare::DataSharePredicates predicates; + predicates.EqualTo(TBL_NAME0, "wang"); + std::vector columns; + DataShareOption option; + option.timeout = 0; + DatashareBusinessError businessError; + auto resultSet = helper->Query(uri, predicates, columns, option, &businessError); + EXPECT_NE(resultSet, nullptr); + EXPECT_EQ(businessError.GetCode(), E_OK); + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_001::End"); +} + +/** +* @tc.name: ProxyDatasTest_QueryTimeout_Test_002 +* @tc.desc: Verify query timeout stability and performance with multiple executions +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: Test data containing record with TBL_NAME0 value "wang" exists +* @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI + 3. Create DataSharePredicates with condition: TBL_NAME0 equals "wang" + 4. Configure DataShareOption with 4000ms timeout + 5. Execute QueryTimeout 100 times in sequence + 6. Measure execution time for each query + 7. Verify result set, error code and row count for each execution +* @tc.expect: + 1. Each query returns a non-null result set + 2. Each query completes within 1000ms + 3. Each query returns business error code E_OK + 4. Each result set contains exactly 1 record +*/ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_QueryTimeout_Test_002, TestSize.Level1) +{ + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_002::Start"); + auto helper = dataShareHelper; + Uri uri(DATA_SHARE_PROXY_URI); + DataShare::DataSharePredicates predicates; + predicates.EqualTo(TBL_NAME0, "wang"); + std::vector columns; + DataShareOption option; + option.timeout = 4000; // 4000 is the query timeout time. + auto limitTime = 1000; // 1000 is used to detect whether the query timeout waiting logic is abnormal. + int repeatTimes = 100; // 100 is the number of times the query is executed. + DatashareBusinessError businessError; + for (int i = 0; i < repeatTimes; i++) { + auto start = std::chrono::steady_clock::now(); + auto resultSet = helper->Query(uri, predicates, columns, option, &businessError); + auto finish = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(finish - start); + EXPECT_TRUE(duration < std::chrono::milliseconds(limitTime)); + EXPECT_NE(resultSet, nullptr); + EXPECT_EQ(businessError.GetCode(), E_OK); + int result = 0; + resultSet->GetRowCount(result); + EXPECT_EQ(result, 1); + } + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_002::End"); +} + +/** +* @tc.name: ProxyDatasTest_QueryTimeout_Test_003 +* @tc.desc: Verify query timeout stability under multi-threaded concurrent access +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: Test data containing record with TBL_NAME0 value "wang" exists +* @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI + 3. Create DataSharePredicates with condition: TBL_NAME0 equals "wang" + 4. Configure DataShareOption with 4000ms timeout + 5. Define query function that executes QueryTimeout 100 times + 6. Create 10 threads to run the query function concurrently + 7. Wait for all threads to complete execution + 8. Verify each query's execution time, result set and error code +* @tc.expect: + 1. All threads complete without execution errors + 2. Each query returns a non-null result set + 3. Each query completes within 1000ms + 4. Each query returns business error code E_OK + 5. Each result set contains exactly 1 record +*/ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_QueryTimeout_Test_003, TestSize.Level1) +{ + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_003::Start"); + auto helper = dataShareHelper; + Uri uri(DATA_SHARE_PROXY_URI); + DataShare::DataSharePredicates predicates; + predicates.EqualTo(TBL_NAME0, "wang"); + std::vector columns; + DataShareOption option; + option.timeout = 4000; // 4000 is the query timeout time. + auto limitTime = 1000; // 1000 is used to detect whether the query timeout waiting logic is abnormal. + int repeatTimes = 100; // 100 is the number of times the query is executed. + DatashareBusinessError businessError; + + std::function func = [&option, &helper, &uri, &predicates, &columns, &businessError, + &limitTime, &repeatTimes]() { + for (int i = 0; i < repeatTimes; i++) { + auto start = std::chrono::steady_clock::now(); + auto resultSet = helper->Query(uri, predicates, columns, option, &businessError); + auto finish = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(finish - start); + EXPECT_TRUE(duration < std::chrono::milliseconds(limitTime)); + EXPECT_NE(resultSet, nullptr); + EXPECT_EQ(businessError.GetCode(), E_OK); + int result = 0; + resultSet->GetRowCount(result); + EXPECT_EQ(result, 1); + } + }; + int threadNum = 10; // 10 is the number of threads. + std::thread threads[threadNum]; + for (int i = 0; i < threadNum; ++i) { + threads[i] = std::thread(func); + } + + for (int i = 0; i < threadNum; ++i) { + threads[i].join(); + } + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_003::End"); +} + +/** +* @tc.name: ProxyDatasTest_QueryTimeout_Test_004 +* @tc.require: issueIC8OCN +* @tc.desc: Verify query timeout behavior when threshold is intentionally exceeded +* @tc.type: FUNC +* @tc.precon: Data store has sufficient capacity for test data insertion +* @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI + 3. Insert 500 test records with TBL_NAME0 values "query0" to "query499" + 4. Create DataSharePredicates with LIKE condition for TBL_NAME0 containing "query" + 5. Configure DataShareOption with 1ms timeout (intentionally short) + 6. Execute QueryTimeout 10 times and count timeout errors + 7. Delete all inserted test records using cleanup predicate + 8. Verify insertion success, timeout occurrences and cleanup success +* @tc.expect: + 1. All 500 test records are inserted successfully + 2. At least one query execution results in E_TIMEOUT_ERROR + 3. Cleanup delete operation removes all inserted records successfully +*/ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_QueryTimeout_Test_004, TestSize.Level1) +{ + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_004::Start"); + auto helper = dataShareHelper; + Uri uri(DATA_SHARE_PROXY_URI); + std::string name = "timeout"; + int retVal = 0; + int insertTimes = 500; // 500 is the number of times the insert is executed. + for (int i = 0; i < insertTimes; i++) { + DataShare::DataShareValuesBucket valuesBucket; + std::string name0 = "query" + std::to_string(i); + valuesBucket.Put(TBL_NAME0, name0); + valuesBucket.Put(TBL_NAME1, name); + retVal = helper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal > 0), true); + } + + DataShare::DataSharePredicates predicates; + predicates.Like(TBL_NAME0, "query"); + std::vector columns; + DataShareOption option; + option.timeout = 1; // 1 is the query timeout time. + int count = 0; + int queryTimes = 10; // 10 is the number of times the query is executed. + for (int i = 0; i < queryTimes; i++) { + DatashareBusinessError businessError; + auto resultSet = helper->Query(uri, predicates, columns, option, &businessError); + if (businessError.GetCode() == E_TIMEOUT_ERROR) { + count++; + } + } + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_004 Query Timeout %{public}d times", count); + EXPECT_TRUE(count > 0); + DataShare::DataSharePredicates delPredicates; + delPredicates.EqualTo(TBL_NAME1, name); + retVal = helper->Delete(uri, delPredicates); + EXPECT_EQ((retVal > 0), true); + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_004::End"); +} + + +/** +* @tc.name: ProxyDatasTest_QueryTimeout_Test_005 +* @tc.desc: test QueryTimeout function +* @tc.type: FUNC +* @tc.require: issueICS05H +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareHelper class + 2.call QueryTimeout function +* @tc.experct: QueryTimeout return nullptr when The function of the parent class was called +*/ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_QueryTimeout_Test_005, TestSize.Level1) +{ + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_005::Start"); + auto helper = dataShareHelper; + Uri uri(DATA_SHARE_PROXY_URI); + DataShare::DataSharePredicates predicates; + predicates.EqualTo(TBL_NAME0, "wang"); + std::vector columns; + DataShareOption option; + option.timeout = 0; // The function has no specific implementation, timeoutis meaningless + DatashareBusinessError businessError; + auto resultSet = helper->DataShareHelper::Query(uri, predicates, columns, option, &businessError); + EXPECT_EQ(resultSet, nullptr); + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_005::End"); +} + +/** +* @tc.name: ProxyDatasTest_ResultSet_Test_001 +* @tc.desc: Verify result set functionality and error handling for invalid operations +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: Test data containing record with TBL_NAME0 value "wang" exists +* @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI + 3. Execute query to get result set for TBL_NAME0 equals "wang" + 4. Verify basic result set properties and row count + 5. Check block management functionality (HasBlock, GetBlock) + 6. Test error handling with invalid column index for GetBlob + 7. Nullify block and verify subsequent value retrieval errors +* @tc.expect: + 1. Query returns non-null result set with row count = 1 + 2. Result set reports HasBlock = true and non-null block + 3. GetBlob with invalid column index returns E_INVALID_COLUMN_INDEX + 4. After SetBlock(nullptr), GetBlock returns null + 5. GetString and GetInt operations after nullifying block return E_ERROR +*/ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_ResultSet_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_ResultSet_Test_001::Start"); auto helper = dataShareHelper; @@ -159,7 +448,23 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_ResultSet_Test_001, TestSize.Level0) LOG_INFO("ProxyDatasTest_ResultSet_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_Template_Test_001 + * @tc.desc: Verify the functionality of adding and deleting query templates in the data share proxy + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create PredicateTemplateNode objects with SQL queries + 3. Assemble the nodes into a Template object + 4. Call AddQueryTemplate to register the template with the proxy URI and subscriber ID + 5. Call DelQueryTemplate to remove the registered template + * @tc.expect: + 1. AddQueryTemplate returns 0, indicating successful template registration + 2. DelQueryTemplate returns 0, indicating successful template deletion + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Template_Test_001::Start"); auto helper = dataShareHelper; @@ -177,7 +482,22 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_001, TestSize.Level0) LOG_INFO("ProxyDatasTest_Template_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_002, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_Template_Test_002 + * @tc.desc: Verify that adding and deleting query templates with an invalid URI fails as expected + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create PredicateTemplateNode objects and assemble them into a Template + 3. Call AddQueryTemplate with an invalid URI and subscriber ID + 4. Call DelQueryTemplate with the same invalid URI and subscriber ID + * @tc.expect: + 1. AddQueryTemplate returns E_URI_NOT_EXIST, indicating failure due to invalid URI + 2. DelQueryTemplate returns E_URI_NOT_EXIST, indicating failure due to invalid URI + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_002, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Template_Test_002::Start"); auto helper = dataShareHelper; @@ -197,12 +517,24 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_002, TestSize.Level0) } /** -* @tc.name: ProxyDatasTest_Template_Test_003 -* @tc.desc: test Template update function -* @tc.type: FUNC -* @tc.require: -*/ -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_003, TestSize.Level0) + * @tc.name: ProxyDatasTest_Template_Test_003 + * @tc.desc: Verify the update functionality of query templates in the data share proxy + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a Template with an update SQL statement and register it via AddQueryTemplate + 2. Subscribe to RDB data changes using the template ID + 3. Insert new data that triggers the template's update condition + 4. Query the data to verify the update was applied + 5. Unsubscribe from RDB data changes + * @tc.expect: + 1. Template registration returns 0 (success) + 2. Subscription and unsubscription operations return 0 (success) + 3. Insert operation succeeds (return value > 0) + 4. Query returns a result set with 1 row, confirming the update was applied + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_003, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Template_Test_003::Start"); auto helper = dataShareHelper; @@ -253,12 +585,21 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_003, TestSize.Level0) } /** -* @tc.name: ProxyDatasTest_Template_Test_004 -* @tc.desc: test add template with parameter update function -* @tc.type: FUNC -* @tc.require: -*/ -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_004, TestSize.Level0) + * @tc.name: ProxyDatasTest_Template_Test_004 + * @tc.desc: Verify adding and deleting query templates with parameterized update functions + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a Template with predicate nodes and register it via AddQueryTemplate + 2. Delete the registered template via DelQueryTemplate + 3. Create another Template with an explicit update SQL statement and register it + 4. Delete the second template + * @tc.expect: + 1. All AddQueryTemplate calls return 0 (success) + 2. All DelQueryTemplate calls return 0 (success) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_004, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Template_Test_004::Start"); auto helper = dataShareHelper; @@ -283,12 +624,20 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_004, TestSize.Level0) } /** -* @tc.name: ProxyDatasTest_Template_Test_005 -* @tc.desc: test add template with wrong parameter update function -* @tc.type: FUNC -* @tc.require: -*/ -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_005, TestSize.Level0) + * @tc.name: ProxyDatasTest_Template_Test_005 + * @tc.desc: Verify that adding a template with an invalid parameterized update function (non-update SQL) fails + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a Template with an insert SQL statement as the update function + 2. Attempt to register the template via AddQueryTemplate + 3. Attempt to delete the (unregistered) template via DelQueryTemplate + * @tc.expect: + 1. AddQueryTemplate returns -1 (failure) due to invalid update SQL + 2. DelQueryTemplate returns 0 (success) (no error if template does not exist) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_005, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Template_Test_005::Start"); auto helper = dataShareHelper; @@ -306,7 +655,56 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_005, TestSize.Level0) LOG_INFO("ProxyDatasTest_Template_Test_005::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_Template_Test_006 + * @tc.desc: Verify adding and deleting query templates using a URI with a user ID parameter + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a URI by appending "?user=100" to the base data share proxy URI + 2. Create a Template with predicate nodes and register it using the new URI + 3. Delete the registered template using the same URI + * @tc.expect: + 1. AddQueryTemplate returns E_OK (success) + 2. DelQueryTemplate returns E_OK (success) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_006, TestSize.Level1) +{ + LOG_INFO("ProxyDatasTest_Template_Test_006::Start"); + auto helper = dataShareHelper; + PredicateTemplateNode node1("p1", "select name0 as name from TBL00"); + PredicateTemplateNode node2("p2", "select name1 as name from TBL00"); + std::vector nodes; + nodes.emplace_back(node1); + nodes.emplace_back(node2); + Template tpl(nodes, "select name1 as name from TBL00"); + + std::string uri = DATA_SHARE_PROXY_URI + "?user=100"; + auto result = helper->AddQueryTemplate(uri, SUBSCRIBER_ID, tpl); + EXPECT_EQ(result, E_OK); + result = helper->DelQueryTemplate(uri, SUBSCRIBER_ID); + EXPECT_EQ(result, E_OK); + LOG_INFO("ProxyDatasTest_Template_Test_006::End"); +} + +/** + * @tc.name: ProxyDatasTest_Publish_Test_001 + * @tc.desc: Verify the functionality of publishing string data via the data share proxy and retrieving it + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a Data object containing a URI, subscriber ID, and string value + 2. Publish the data using Publish method with the target bundle name + 3. Retrieve the published data using GetPublishedData + 4. Verify the retrieved data matches the published data + * @tc.expect: + 1. Publish returns OperationResult with errCode_ 0 (success) + 2. GetPublishedData returns errCode_ 0 (success) + 3. Retrieved data has the same size, subscriber ID, key, and value as published data + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Publish_Test_001::Start"); auto helper = dataShareHelper; @@ -334,7 +732,21 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_001, TestSize.Level0) LOG_INFO("ProxyDatasTest_Publish_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_002, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_Publish_Test_002 + * @tc.desc: Verify that publishing data with a non-existent bundle name fails as expected + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a Data object with a URI, subscriber ID, and string value + 2. Attempt to publish the data using a non-existent bundle name + 3. Attempt to retrieve published data using the same invalid bundle name + * @tc.expect: + 1. Publish returns OperationResult with errCode_ E_BUNDLE_NAME_NOT_EXIST (failure) + 2. GetPublishedData returns errCode_ E_BUNDLE_NAME_NOT_EXIST (failure) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_002, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Publish_Test_002::Start"); auto helper = dataShareHelper; @@ -353,7 +765,23 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_002, TestSize.Level0) LOG_INFO("ProxyDatasTest_Publish_Test_002::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_003, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_Publish_Test_003 + * @tc.desc: Verify the functionality of publishing binary data (ashmem) via the data share proxy and retrieving it + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a Data object containing a URI, subscriber ID, and binary buffer + 2. Publish the data using Publish method with the target bundle name + 3. Retrieve the published data using GetPublishedData + 4. Verify the retrieved binary data matches the published data + * @tc.expect: + 1. Publish returns OperationResult with errCode_ 0 (success) + 2. GetPublishedData returns errCode_ 0 (success) + 3. Retrieved data has the same size, subscriber ID, and binary content as published data + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_003, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Publish_Test_003::Start"); auto helper = dataShareHelper; @@ -381,7 +809,25 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_003, TestSize.Level0) LOG_INFO("ProxyDatasTest_Publish_Test_003::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationRdbData_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_CombinationRdbData_Test_001 + * @tc.desc: Verify combination functionality of RDB data subscription, enabling/disabling, and unsubscription + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Register a query template and subscribe to RDB data changes with a callback + 2. Enable RDB subscriptions + 3. Insert data to trigger the subscription callback + 4. Verify the callback is invoked the expected number of times + 5. Unsubscribe from RDB data changes and insert more data + * @tc.expect: + 1. Template registration, subscription, and enabling return 0 (success) + 2. Insert operations return values > 0 (success) + 3. Callback is invoked 2 times before unsubscription + 4. No additional callback invocations after unsubscription + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationRdbData_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_CombinationRdbData_Test_001::Start"); auto helper = dataShareHelper; @@ -432,7 +878,220 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationRdbData_Test_001, TestSize.Le LOG_INFO("ProxyDatasTest_CombinationRdbData_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_SubscribePublishedData_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_CombinationRdbData_Test_002 + * @tc.desc: Verify combination functionality of RDB data subscription, multiple disable operations, and re-enable + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Register a template and subscribe to RDB data changes with two helpers + 2. Disable subscriptions, insert data, and disable again + 3. Re-enable subscriptions and verify callback behavior + 4. Unsubscribe from both helpers + * @tc.expect: + 1. Template registration, subscriptions, disable/enable return 0 (success) + 2. Insert operation returns value > 0 (success) + 3. Callback is invoked 2 times total (1 before disable, 1 after re-enable) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationRdbData_Test_002, TestSize.Level1) +{ + auto helper = dataShareHelper; + auto helper2 = dataShareHelper2; + std::vector nodes; + Template tpl(nodes, "select name1 as name from TBL00"); + auto result = helper->AddQueryTemplate(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID, tpl); + EXPECT_EQ(result, 0); + + std::vector uris = {DATA_SHARE_PROXY_URI}; + TemplateId tplId; + tplId.subscriberId_ = SUBSCRIBER_ID; + tplId.bundleName_ = "ohos.datashareproxyclienttest.demo"; + std::atomic_int callbackTimes = 0; + std::mutex mutex; + std::condition_variable cv; + auto timeout = std::chrono::seconds(2); + std::vector results = + helper->SubscribeRdbData(uris, tplId, [&callbackTimes, &mutex, &cv](const RdbChangeNode &changeNode) { + std::lock_guard lock(mutex); + callbackTimes++; + cv.notify_all(); + }); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &result : results) EXPECT_EQ(result.errCode_, 0); + // if there is only one subscriber in a key, the subscriber can't be disabled twice + results = helper2->SubscribeRdbData(uris, tplId, [](const RdbChangeNode &changeNode) { + }); + + std::unique_lock lock(mutex); + cv.wait_for(lock, timeout); + EXPECT_EQ(callbackTimes, 1); + lock.unlock(); + results = helper->DisableRdbSubs(uris, tplId); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &result : results) EXPECT_EQ(result.errCode_, 0); + + Uri uri(DATA_SHARE_PROXY_URI); + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put(TBL_NAME1, 1); + int retVal = helper->Insert(uri, valuesBucket); + EXPECT_GT(retVal, 0); + + results = helper->DisableRdbSubs(uris, tplId); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &result : results) EXPECT_EQ(result.errCode_, 0); + results = helper->EnableRdbSubs(uris, tplId); + for (auto const &result : results) EXPECT_EQ(result.errCode_, 0); + EXPECT_EQ(callbackTimes, 2); + helper->UnsubscribeRdbData(uris, tplId); + helper2->UnsubscribeRdbData(uris, tplId); +} + +/** + * @tc.name: ProxyDatasTest_CombinationRdbData_Test_003 + * @tc.desc: Verify combination functionality of RDB data subscription, disable, re-enable, and unsubscription + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Register a template and subscribe to RDB data changes with a callback + 2. Disable subscriptions, then re-enable them + 3. Unsubscribe from RDB data changes + * @tc.expect: + 1. Template registration, subscription, disable/enable, and unsubscription return 0 (success) + 2. Callback is invoked 1 time (initial subscription) + 3. No additional callback invocations after disable/re-enable + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationRdbData_Test_003, TestSize.Level1) +{ + LOG_INFO("ProxyDatasTest_CombinationRdbData_Test_003::Start"); + auto helper = dataShareHelper; + std::vector nodes; + Template tpl(nodes, "select name1 as name from TBL00"); + auto result = helper->AddQueryTemplate(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID, tpl); + EXPECT_EQ(result, E_OK); + + std::vector uris = {DATA_SHARE_PROXY_URI}; + TemplateId tplId; + tplId.subscriberId_ = SUBSCRIBER_ID; + tplId.bundleName_ = "ohos.datashareproxyclienttest.demo"; + std::atomic_int callbackTimes = 0; + std::mutex mutex; + std::condition_variable cv; + auto timeout = std::chrono::seconds(2); + std::vector results = + helper->SubscribeRdbData(uris, tplId, [&callbackTimes, &mutex, &cv](const RdbChangeNode &changeNode) { + std::lock_guard lock(mutex); + callbackTimes++; + cv.notify_all(); + }); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &result : results) { + EXPECT_EQ(result.errCode_, E_OK); + } + + std::unique_lock lock(mutex); + cv.wait_for(lock, timeout); + EXPECT_EQ(callbackTimes, 1); + lock.unlock(); + results = helper->DisableRdbSubs(uris, tplId); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &result : results) { + EXPECT_EQ(result.errCode_, 0); + } + results = helper->EnableRdbSubs(uris, tplId); + for (auto const &result : results) { + EXPECT_EQ(result.errCode_, 0); + } + EXPECT_EQ(callbackTimes, 1); + results = helper->UnsubscribeRdbData(uris, tplId); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &result : results) { + EXPECT_EQ(result.errCode_, E_OK); + } + LOG_INFO("ProxyDatasTest_CombinationRdbData_Test_003::End"); +} + +/** + * @tc.name: ProxyDatasTest_CombinationPublishedData_Test_001 + * @tc.desc: Verify combination functionality of published data subscription, disable, re-enable, and unsubscription + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Publish data and subscribe to published data changes with two helpers + 2. Disable subscriptions, republish data, then disable again + 3. Re-enable subscriptions and verify callback behavior + 4. Unsubscribe from both helpers + * @tc.expect: + 1. Publish, subscription, disable/enable return 0 (success) + 2. Callback is invoked 2 times total (1 before disable, 1 after re-enable) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationPublishedData_Test_001, TestSize.Level1) +{ + LOG_INFO("ProxyDatasTest_CombinationPublishedData_Test_001::Start"); + auto helper = dataShareHelper; + auto helper2 = dataShareHelper2; + std::string bundleName = "com.acts.ohos.data.datasharetest"; + Data data; + data.datas_.emplace_back(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID, "value1"); + std::vector results = helper->Publish(data, bundleName); + EXPECT_EQ(results.size(), data.datas_.size()); + for (auto const &result : results) EXPECT_EQ(result.errCode_, 0); + std::vector uris = {DATA_SHARE_PROXY_URI}; + std::atomic_int callbackTimes = 0; + std::mutex mutex; + std::condition_variable cv; + auto timeout = std::chrono::seconds(2); + results = helper->SubscribePublishedData(uris, SUBSCRIBER_ID, + [&callbackTimes, &mutex, &cv](const PublishedDataChangeNode &changeNode) { + std::lock_guard lock(mutex); + callbackTimes++; + cv.notify_all(); + }); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &operationResult : results) EXPECT_EQ(operationResult.errCode_, 0); + // if there is only one subscriber in a key, the subscriber can't be disabled twice + results = helper2->SubscribePublishedData(uris, SUBSCRIBER_ID, [](const PublishedDataChangeNode &changeNode) {}); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &operationResult : results) { + EXPECT_EQ(operationResult.errCode_, 0); + } + std::unique_lock lock(mutex); + cv.wait_for(lock, timeout); + EXPECT_EQ(callbackTimes, 1); + lock.unlock(); + results = helper->DisablePubSubs(uris, SUBSCRIBER_ID); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &operationResult : results) EXPECT_EQ(operationResult.errCode_, 0); + + results = helper->Publish(data, bundleName); + EXPECT_EQ(results.size(), data.datas_.size()); + for (auto const &result : results) EXPECT_EQ(result.errCode_, 0); + results = helper->DisablePubSubs(uris, SUBSCRIBER_ID); + for (auto const &operationResult : results) EXPECT_EQ(operationResult.errCode_, 0); + results = helper->EnablePubSubs(uris, SUBSCRIBER_ID); + for (auto const &operationResult : results) EXPECT_EQ(operationResult.errCode_, 0); + EXPECT_EQ(callbackTimes, 2); + helper->UnsubscribePublishedData(uris, SUBSCRIBER_ID); + helper2->UnsubscribePublishedData(uris, SUBSCRIBER_ID); + LOG_INFO("ProxyDatasTest_CombinationPublishedData_Test_001::End"); +} + +/** + * @tc.name: ProxyDatasTest_SubscribePublishedData_Test_001 + * @tc.desc: Verify the functionality of subscribing to published data changes + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a list of URIs to subscribe to + 2. Call SubscribePublishedData with the URIs, subscriber ID, and a verification callback + * @tc.expect: + 1. Subscription returns OperationResult with errCode_ 0 (success) + 2. Callback verifies the owner bundle name when triggered + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_SubscribePublishedData_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_SubscribePublishedData_Test_001::Start"); auto helper = dataShareHelper; @@ -449,7 +1108,19 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_SubscribePublishedData_Test_001, TestSiz LOG_INFO("ProxyDatasTest_SubscribePublishedData_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_DisablePubSubs_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_DisablePubSubs_Test_001 + * @tc.desc: Verify the functionality of disabling published data subscriptions + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a list of URIs with active subscriptions + 2. Call DisablePubSubs with the URIs and subscriber ID + * @tc.expect: + 1. DisablePubSubs returns OperationResult with errCode_ 0 (success) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_DisablePubSubs_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_DisablePubSubs_Test_001::Start"); auto helper = dataShareHelper; @@ -462,7 +1133,19 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_DisablePubSubs_Test_001, TestSize.Level0 LOG_INFO("ProxyDatasTest_DisablePubSubs_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_EnablePubSubs_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_EnablePubSubs_Test_001 + * @tc.desc: Verify the functionality of enabling published data subscriptions + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a list of URIs with disabled subscriptions + 2. Call EnablePubSubs with the URIs and subscriber ID + * @tc.expect: + 1. EnablePubSubs returns OperationResult with errCode_ 0 (success) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_EnablePubSubs_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_EnablePubSubs_Test_001::Start"); auto helper = dataShareHelper; @@ -475,7 +1158,19 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_EnablePubSubs_Test_001, TestSize.Level0) LOG_INFO("ProxyDatasTest_EnablePubSubs_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_UnsubscribePublishedData_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_UnsubscribePublishedData_Test_001 + * @tc.desc: Verify the functionality of unsubscribing from published data changes + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a list of URIs with active subscriptions + 2. Call UnsubscribePublishedData with the URIs and subscriber ID + * @tc.expect: + 1. UnsubscribePublishedData returns OperationResult with errCode_ 0 (success) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_UnsubscribePublishedData_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_UnsubscribePublishedData_Test_001::Start"); auto helper = dataShareHelper; @@ -489,7 +1184,22 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_UnsubscribePublishedData_Test_001, TestS LOG_INFO("ProxyDatasTest_UnsubscribePublishedData_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_extSpCtl_Null_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_extSpCtl_Null_Test_001 + * @tc.desc: Verify extended special control operations after releasing the helper + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Release the DataShareHelper instance + 2. Call GetFileTypes with an empty URI and string + 3. Call OpenFile and OpenRawFile with an empty URI and string + * @tc.expect: + 1. Release returns true (success) + 2. GetFileTypes returns an empty list + 3. OpenFile and OpenRawFile return -1 (failure) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_extSpCtl_Null_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_extSpCtl_Null_Test_001::Start"); auto helper = dataShareHelper; @@ -506,7 +1216,20 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_extSpCtl_Null_Test_001, TestSize.Level0) LOG_INFO("ProxyDatasTest_extSpCtl_Null_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_extSpCtl_Null_Test_002, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_extSpCtl_Null_Test_002 + * @tc.desc: Verify NormalizeUri and DenormalizeUri operations after releasing the helper + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Release the DataShareHelper instance + 2. Call NormalizeUri and DenormalizeUri with an empty URI + * @tc.expect: + 1. Release returns true (success) + 2. NormalizeUri and DenormalizeUri return the input empty URI unchanged + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_extSpCtl_Null_Test_002, TestSize.Level1) { LOG_INFO("ProxyDatasTest_extSpCtl_Null_Test_002::Start"); auto helper = dataShareHelper; diff --git a/data_share/test/native/unittest/long_time/concurrent_test/BUILD.gn b/data_share/test/native/unittest/long_time/concurrent_test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..4f1e1ea8b0d0c95144f0d6dd884bea0a1fa87c22 --- /dev/null +++ b/data_share/test/native/unittest/long_time/concurrent_test/BUILD.gn @@ -0,0 +1,52 @@ +# Copyright (C) 2025 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/test.gni") +import("//foundation/distributeddatamgr/data_share/datashare.gni") + +ohos_unittest("ConcurrentTest") { + module_out_path = "data_share/native_datashare" + + include_dirs = [ + "${datashare_native_proxy_path}/include", + "${datashare_common_native_path}/include", + ] + + sources = [ + "${datashare_common_native_path}/src/datashare_itypes_utils.cpp", + "${datashare_common_native_path}/src/datashare_string_utils.cpp", + "${datashare_native_proxy_path}/src/data_proxy_observer_stub.cpp", + "${datashare_native_proxy_path}/src/data_share_service_proxy.cpp", + "${datashare_native_proxy_path}/src/published_data_subscriber_manager.cpp", + "${datashare_native_proxy_path}/src/rdb_subscriber_manager.cpp", + "concurrent_subscriber_test.cpp", + ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer", + "${datashare_innerapi_path}/common:datashare_common", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} diff --git a/data_share/test/native/unittest/long_time/concurrent_test/concurrent_subscriber_test.cpp b/data_share/test/native/unittest/long_time/concurrent_test/concurrent_subscriber_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e85386589423b87c6fc2d48bee7153386cde1916 --- /dev/null +++ b/data_share/test/native/unittest/long_time/concurrent_test/concurrent_subscriber_test.cpp @@ -0,0 +1,501 @@ +/* + * Copyright (C) 2025 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 + +#include "callbacks_manager.h" +#include "data_ability_observer_stub.h" +#include "datashare_errno.h" +#include "datashare_helper.h" +#include "datashare_log.h" +#include "datashare_template.h" +#include "datashare_string_utils.h" +#include "iservice_registry.h" +#include "published_data_subscriber_manager.h" +#include "rdb_subscriber_manager.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using RdbBaseCallbacks = CallbacksManager; +using RdbCallback = std::function; +RdbCallback g_rbdCallback = [](const RdbChangeNode &changeNode) {}; +RdbChangeNode g_rdbChangeNode; +using PublishedBaseCallbacks = CallbacksManager; +using PublishedDataCallback = std::function; +PublishedDataCallback g_publishedCallback = [](const PublishedDataChangeNode &changeNode) {}; +PublishedDataChangeNode g_publishedChangeNode; +constexpr int TEST_TIME = 20; +void *g_subscriber; + +/** + * @Usage: add long_time/concurrent_test/ConcurrentTest to unittest.deps of file + * foundation/distributeddatamgr/data_share/test/native/BUILD.gn + */ +class ConcurrentSubscriberTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void ConcurrentSubscriberTest::SetUpTestCase(void) +{ +} + +void ConcurrentSubscriberTest::TearDownTestCase(void) +{ +} + +void ConcurrentSubscriberTest::SetUp(void) +{ + // input testCase setup step,setup invoked before each testCase + testing::UnitTest *test = testing::UnitTest::GetInstance(); + ASSERT_NE(test, nullptr); + const testing::TestInfo *testInfo = test->current_test_info(); + ASSERT_NE(testInfo, nullptr); + string testCaseName = string(testInfo->name()); + LOG_INFO("[SetUp] %{public}s start", testCaseName.c_str()); + GTEST_LOG_(INFO) << testCaseName.append(" start"); +} +void ConcurrentSubscriberTest::TearDown(void) +{ + // input testCase teardown step,teardown invoked after each testCase + testing::UnitTest *test = testing::UnitTest::GetInstance(); + ASSERT_NE(test, nullptr); + const testing::TestInfo *testInfo = test->current_test_info(); + ASSERT_NE(testInfo, nullptr); + string testCaseName = string(testInfo->name()); + LOG_INFO("[SetUp] %{public}s end", testCaseName.c_str()); + GTEST_LOG_(INFO) << testCaseName.append(" end"); +} + +class RdbSubscriberManagerTest : public CallbacksManager { +public: + using Key = RdbObserverMapKey; + using Observer = RdbObserver; + void AddObservers(int64_t subscriberId, std::string &bundleName, std::string &uri, std::atomic &stop); + void DelObservers(int64_t subscriberId, std::string &bundleName, std::string &uri, std::atomic &stop); +}; + +void RdbSubscriberManagerTest::AddObservers( + int64_t subscriberId, std::string &bundleName, std::string &uri, std::atomic &stop) +{ + void *subscriber = g_subscriber; + RdbChangeNode *changeNode = &g_rdbChangeNode; + DataShare::TemplateId templateId; + templateId.subscriberId_ = subscriberId, templateId.bundleName_ = bundleName; + std::vector uris; + uris.emplace_back(uri); + Key rdbKey(uri, templateId); + std::vector keys; + std::for_each(uris.begin(), uris.end(), [&keys, &templateId](auto &uri) { keys.emplace_back(uri, templateId); }); + while (!stop.load()) { + LOG_INFO("Rdb AddObservers start, subscriberId: %{public}d", static_cast(subscriberId)); + RdbBaseCallbacks::AddObservers( + keys, subscriber, std::make_shared(g_rbdCallback), + [](const std::vector &localRegisterKeys, const std::shared_ptr observer) {}, + [&subscriber, &templateId, &rdbKey, &changeNode](const std::vector &firstAddKeys, + const std::shared_ptr observer, std::vector &opResult) { + std::vector firstAddUris; + std::for_each(firstAddKeys.begin(), firstAddKeys.end(), + [&firstAddUris](auto &result) { firstAddUris.emplace_back(result); }); + if (firstAddUris.empty()) { + return; + } + RdbSubscriberManager::GetInstance().lastChangeNodeMap_.InsertOrAssign(rdbKey, *changeNode); + }); + LOG_INFO("Rdb AddObservers end, subscriberId: %{public}d", static_cast(subscriberId)); + } +} + +void RdbSubscriberManagerTest::DelObservers( + int64_t subscriberId, std::string &bundleName, std::string &uri, std::atomic &stop) +{ + void *subscriber = g_subscriber; + DataShare::TemplateId templateId; + templateId.subscriberId_ = subscriberId, templateId.bundleName_ = bundleName; + std::vector uris; + uris.emplace_back(uri); + std::vector keys; + std::for_each(uris.begin(), uris.end(), [&keys, &templateId](auto &uri) { keys.emplace_back(uri, templateId); }); + while (!stop.load()) { + LOG_INFO("Rdb DelObservers start, subscriberId: %{public}d", static_cast(subscriberId)); + RdbBaseCallbacks::DelObservers( + keys, subscriber, [](const std::vector &lastDelKeys, std::vector &opResult) { + std::for_each(lastDelKeys.begin(), lastDelKeys.end(), + [](auto &result) { RdbSubscriberManager::GetInstance().lastChangeNodeMap_.Erase(result); }); + }); + LOG_INFO("Rdb DelObservers end, subscriberId: %{public}d", static_cast(subscriberId)); + } +} + +/** + * @tc.name: ConcurrentRdbObserverTest + * @tc.desc: Verify concurrent SubscribeRdbData and UnsubscribeRdbData operations + * @tc.type: concurrent + * @tc.require: None + * @tc.precon: RdbSubscriberManager is properly initialized + * @tc.step: + 1. Create an instance of RdbSubscriberManagerTest + 2. Define two URIs and two bundle names for testing + 3. Create four threads to concurrently perform: + - Add observers for URI0 with bundleName0 + - Delete observers for URI0 with bundleName0 + - Add observers for URI1 with bundleName1 + - Delete observers for URI1 with bundleName1 + 4. Run the concurrent operations for a specified test duration + 5. Stop all threads and wait for their completion + * @tc.expect: + 1. All concurrent operations complete without crashes + 2. No deadlocks occur during concurrent subscription management + 3. Observer management maintains internal consistency + */ +HWTEST_F(ConcurrentSubscriberTest, ConcurrentRdbObserverTest, TestSize.Level0) +{ + std::atomic stop = false; + int testTime = TEST_TIME; + RdbSubscriberManagerTest instance; + std::string uri0 = "uri0"; + std::string uri1 = "uri1"; + std::string bundleName0 = "bundleName0"; + std::string bundleName1 = "bundleName1"; + std::function func1 = [&instance, &bundleName0, &uri0, &stop]() { + instance.AddObservers(0, bundleName0, uri0, stop); + }; + std::function func2 = [&instance, &bundleName0, &uri0, &stop]() { + instance.DelObservers(0, bundleName0, uri0, stop); + }; + std::function func3 = [&instance, &bundleName1, &uri1, &stop]() { + instance.AddObservers(1, bundleName1, uri1, stop); + }; + std::function func4 = [&instance, &bundleName1, &uri1, &stop]() { + instance.DelObservers(1, bundleName1, uri1, stop); + }; + std::thread t1(func1); + std::thread t2(func2); + std::thread t3(func3); + std::thread t4(func4); + while (testTime > 0) { + sleep(1); + testTime--; + } + stop = true; + t1.join(); + t2.join(); + t3.join(); + t4.join(); +} + +class PublishedDataSubscriberManagerTest : public CallbacksManager { +public: + using Callback = std::function; + using Key = PublishedObserverMapKey; + using Observer = PublishedDataObserver; + void AddObservers(int64_t subscriberId, std::string &uri, std::atomic &stop); + void DelObservers(int64_t subscriberId, std::string &uri, std::atomic &stop); +}; + +void PublishedDataSubscriberManagerTest::AddObservers(int64_t subscriberId, std::string &uri, std::atomic &stop) +{ + void *subscriber = g_subscriber; + PublishedDataChangeNode *changeNode = &g_publishedChangeNode; + std::vector uris; + uris.emplace_back(uri); + Key publishedKey(uri, subscriberId); + std::vector keys; + std::for_each( + uris.begin(), uris.end(), [&keys, &subscriberId](auto &uri) { keys.emplace_back(uri, subscriberId); }); + while (!stop.load()) { + LOG_INFO("Published AddObservers start, subscriberId: %{public}d", static_cast(subscriberId)); + PublishedBaseCallbacks::AddObservers( + keys, subscriber, std::make_shared(g_publishedCallback), + [](const std::vector &localRegisterKeys, const std::shared_ptr observer) {}, + [&subscriber, &publishedKey, &changeNode](const std::vector &firstAddKeys, + const std::shared_ptr observer, std::vector &opResult) { + std::vector firstAddUris; + std::for_each(firstAddKeys.begin(), firstAddKeys.end(), + [&firstAddUris](auto &result) { firstAddUris.emplace_back(result); }); + if (firstAddUris.empty()) { + return; + } + PublishedDataSubscriberManager::GetInstance().lastChangeNodeMap_.Compute( + publishedKey, [](const Key &, PublishedDataChangeNode &value) { + value.datas_.clear(); + return true; + }); + PublishedDataSubscriberManager::GetInstance().lastChangeNodeMap_.Compute( + publishedKey, [&publishedKey](const Key &, PublishedDataChangeNode &value) { + value.datas_.emplace_back(publishedKey.uri_, publishedKey.subscriberId_, "data"); + value.ownerBundleName_ = ""; + return true; + }); + }); + LOG_INFO("Published AddObservers end, subscriberId: %{public}d", static_cast(subscriberId)); + } +} + +void PublishedDataSubscriberManagerTest::DelObservers(int64_t subscriberId, std::string &uri, std::atomic &stop) +{ + void *subscriber = g_subscriber; + std::vector uris; + uris.emplace_back(uri); + std::vector keys; + std::for_each( + uris.begin(), uris.end(), [&keys, &subscriberId](auto &uri) { keys.emplace_back(uri, subscriberId); }); + while (!stop.load()) { + LOG_INFO("Published DelObservers start, subscriberId: %{public}d", static_cast(subscriberId)); + PublishedBaseCallbacks::DelObservers( + keys, subscriber, [](const std::vector &lastDelKeys, std::vector &opResult) { + std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [](auto &result) { + PublishedDataSubscriberManager::GetInstance().lastChangeNodeMap_.Erase(result); + }); + }); + LOG_INFO("Published DelObservers end, subscriberId: %{public}d", static_cast(subscriberId)); + } +} + +/** + * @tc.name: ConcurrentPublishObserverTest + * @tc.desc: Verify concurrent SubscribePublishedData and UnsubscribePublishedData operations + * @tc.type: concurrent + * @tc.require: None + * @tc.precon: PublishedDataSubscriberManager is properly initialized + * @tc.step: + 1. Create an instance of PublishedDataSubscriberManagerTest + 2. Define two URIs for testing + 3. Create four threads to concurrently perform: + - Add observers for URI0 with subscriber ID 0 + - Delete observers for URI0 with subscriber ID 0 + - Add observers for URI1 with subscriber ID 1 + - Delete observers for URI1 with subscriber ID 1 + 4. Run the concurrent operations for a specified test duration + 5. Stop all threads and wait for their completion + * @tc.expect: + 1. All concurrent operations complete without crashes + 2. No deadlocks occur during concurrent subscription management + 3. Published data observer map maintains internal consistency + 4. Change node data is properly managed during concurrent access + */ +HWTEST_F(ConcurrentSubscriberTest, ConcurrentPublishObserverTest, TestSize.Level0) +{ + std::atomic stop = false; + int testTime = TEST_TIME; + PublishedDataSubscriberManagerTest instance; + std::string uri0 = "uri0"; + std::string uri1 = "uri1"; + std::function func1 = [&instance, &uri0, &stop]() { instance.AddObservers(0, uri0, stop); }; + std::function func2 = [&instance, &uri0, &stop]() { instance.DelObservers(0, uri0, stop); }; + std::function func3 = [&instance, &uri1, &stop]() { instance.AddObservers(1, uri1, stop); }; + std::function func4 = [&instance, &uri1, &stop]() { instance.DelObservers(1, uri1, stop); }; + std::thread t1(func1); + std::thread t2(func2); + std::thread t3(func3); + std::thread t4(func4); + while (testTime > 0) { + sleep(1); + testTime--; + } + stop = true; + t1.join(); + t2.join(); + t3.join(); + t4.join(); +} + +template +class ConditionLock { +public: + explicit ConditionLock() {} + ~ConditionLock() {} +public: + void Notify(const T &data) + { + std::lock_guard lock(mutex_); + data_ = data; + isSet_ = true; + cv_.notify_one(); + } + + T Wait() + { + std::unique_lock lock(mutex_); + cv_.wait_for(lock, std::chrono::seconds(INTERVAL), [this]() { return isSet_; }); + T data = data_; + cv_.notify_one(); + return data; + } + + void Clear() + { + std::lock_guard lock(mutex_); + isSet_ = false; + cv_.notify_one(); + } + +private: + bool isSet_ = false; + T data_; + std::mutex mutex_; + std::condition_variable cv_; + static constexpr int64_t INTERVAL = 2; +}; + +class DataShareObserverTest : public DataShare::DataShareObserver { +public: + explicit DataShareObserverTest(std::string uri) + { + uri_ = uri; + } + ~DataShareObserverTest() {} + + void OnChange(const ChangeInfo &changeInfo) override + { + changeInfo_ = changeInfo; + data.Notify(changeInfo); + } + + void Clear() + { + changeInfo_.changeType_ = INVAILD; + changeInfo_.uris_.clear(); + changeInfo_.data_ = nullptr; + changeInfo_.size_ = 0; + changeInfo_.valueBuckets_ = {}; + data.Clear(); + } + + ChangeInfo changeInfo_; + ConditionLock data; + std::string uri_; +}; + +class ConcurrentRegisterObserverExtProvider { +public: + void RegisterObserverExtProvider(std::shared_ptr helper, const Uri &uri, + std::shared_ptr dataObserver, std::atomic &stop) + { + while (!stop.load()) { + LOG_INFO("RegisterObserverExtProvider start, uri: %{public}s", + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + + helper->RegisterObserverExtProvider(uri, dataObserver, true); + + LOG_INFO("RegisterObserverExtProvider end, uri: %{public}s", + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + } + } + + void UnregisterObserverExtProvider(std::shared_ptr helper, const Uri &uri, + std::shared_ptr dataObserver, std::atomic &stop) + { + while (!stop.load()) { + LOG_INFO("UnregisterObserverExtProvider start, uri: %{public}s", + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + + helper->UnregisterObserverExtProvider(uri, dataObserver); + + LOG_INFO("UnregisterObserverExtProvider end, uri: %{public}s", + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + } + } +}; + +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::string DATA_SHARE_URI1 = "datashare:///com.acts.datasharetest1"; +std::string DATA_SHARE_URI2 = "datashare:///com.acts.datasharetest2"; +constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; + +std::shared_ptr CreateDataShareHelper(int32_t systemAbilityId) +{ + LOG_INFO("CreateDataShareHelper start"); + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saManager == nullptr) { + LOG_ERROR("GetSystemAbilityManager get samgr failed."); + return nullptr; + } + auto remoteObj = saManager->GetSystemAbility(systemAbilityId); + if (remoteObj == nullptr) { + LOG_ERROR("GetSystemAbility service failed."); + return nullptr; + } + return DataShare::DataShareHelper::Creator(remoteObj, DATA_SHARE_URI); +} + +/** + * @tc.name: ConcurrentRegisterObserverExtProviderTest + * @tc.desc: Verify concurrent RegisterObserverExtProvider and UnregisterObserverExtProvider operations + * @tc.type: concurrent + * @tc.require: None + * @tc.precon: + 1. DataShare service is properly initialized + 2. STORAGE_MANAGER_MANAGER_ID system ability is available + * @tc.step: + 1. Create a DataShareHelper instance using STORAGE_MANAGER_MANAGER_ID + 2. Define two URIs for testing (DATA_SHARE_URI1 and DATA_SHARE_URI2) + 3. Create two DataShareObserverTest instances for the URIs + 4. Create four threads to concurrently perform: + - Register observer for URI1 + - Unregister observer for URI1 + - Register observer for URI2 + - Unregister observer for URI2 + 5. Run the concurrent operations for a specified test duration + 6. Stop all threads and wait for their completion + * @tc.expect: + 1. DataShareHelper is created successfully (not nullptr) + 2. All concurrent registration and unregistration operations complete without crashes + 3. No deadlocks occur during concurrent observer management + 4. Observer registration state remains consistent during concurrent access + */ +HWTEST_F(ConcurrentSubscriberTest, ConcurrentRegisterObserverExtProviderTest, TestSize.Level0) +{ + LOG_INFO("ConcurrentRegisterObserverExtProviderTest::Start"); + std::atomic stop = false; + int testTime = TEST_TIME; + ConcurrentRegisterObserverExtProvider instance; + Uri uri1(DATA_SHARE_URI1); + Uri uri2(DATA_SHARE_URI2); + std::shared_ptr dataObserver1 = std::make_shared(DATA_SHARE_URI1); + std::shared_ptr dataObserver2 = std::make_shared(DATA_SHARE_URI2); + std::shared_ptr helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID); + ASSERT_NE(helper, nullptr); + + std::function func1 = [&instance, &helper, &uri1, &dataObserver1, &stop]() { + instance.RegisterObserverExtProvider(helper, uri1, dataObserver1, stop); + }; + std::function func2 = [&instance, &helper, &uri1, &dataObserver1, &stop]() { + instance.UnregisterObserverExtProvider(helper, uri1, dataObserver1, stop); + }; + std::function func3 = [&instance, &helper, &uri2, &dataObserver2, &stop]() { + instance.RegisterObserverExtProvider(helper, uri2, dataObserver2, stop); + }; + std::function func4 = [&instance, &helper, &uri2, &dataObserver2, &stop]() { + instance.UnregisterObserverExtProvider(helper, uri2, dataObserver2, stop); + }; + std::thread t1(func1); + std::thread t2(func2); + std::thread t3(func3); + std::thread t4(func4); + sleep(testTime); + stop = true; + t1.join(); + t2.join(); + t3.join(); + t4.join(); + LOG_INFO("ConcurrentRegisterObserverExtProviderTest::end"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/include/mediadatashare_unit_test.h b/data_share/test/native/unittest/mediadatashare_test/include/mediadatashare_unit_test.h index 3ca808d228100979bacb273d70ffc2cbec64d3ac..98760f7c6382b89dbd072542f85a09e6e6347921 100644 --- a/data_share/test/native/unittest/mediadatashare_test/include/mediadatashare_unit_test.h +++ b/data_share/test/native/unittest/mediadatashare_test/include/mediadatashare_unit_test.h @@ -48,7 +48,7 @@ public: class IDataAbilityObserverTest : public AAFwk::DataAbilityObserverStub { public: - IDataAbilityObserverTest(); + IDataAbilityObserverTest() {} ~IDataAbilityObserverTest() {} diff --git a/data_share/test/native/unittest/mediadatashare_test/src/abnormal_branch_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/abnormal_branch_test.cpp index 7cb1c84e486cbab81f5364675db9170b0bb6325c..24c1667daee61645b2bcd2ec1573915cda763239 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/abnormal_branch_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/abnormal_branch_test.cpp @@ -14,7 +14,11 @@ */ #include #include +#include #include "accesstoken_kit.h" +#include "ams_mgr_proxy.h" +#include "data_share_manager_impl.h" +#include "data_share_service_proxy.h" #include "datashare_helper.h" #include "datashare_log.h" #include "datashare_template.h" @@ -31,11 +35,16 @@ #include "shared_block.h" #include "datashare_block_writer_impl.h" #include "datashare_connection.h" +#include "ikvstore_data_service_mock.h" +#include "general_controller_service_impl.h" +#include "persistent_data_controller.h" +#include "published_data_controller.h" namespace OHOS { namespace DataShare { using namespace testing::ext; using namespace OHOS::Security::AccessToken; +constexpr int INVALID_VALUE = -1; class AbnormalBranchTest : public testing::Test { public: @@ -58,6 +67,34 @@ void AbnormalBranchTest::TearDown(void) { } +// Used for mock DataShareKvServiceProxy in order to +// cover the situation that DataShareManagerImpl::GetServiceProxy() == nullptr; +void DataShareManagerImplHelper() +{ + auto helper = DataShareManagerImpl::GetInstance(); + helper->dataShareService_ = nullptr; + auto manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + auto remoteObject = manager->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); + sptr mockProxy = sptr + (new MockDataShareKvServiceProxy(remoteObject)); + EXPECT_CALL(*mockProxy, GetFeatureInterface(testing::_)) + .WillOnce(testing::Return(nullptr)); + + helper->dataMgrService_ = (sptr)mockProxy; +} + +/** + * @tc.name: AbnormalBranchTest_shareBlock_Null_Test_001 + * @tc.desc: Verify operations on DataShareBlockWriterImpl when share block is null + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create DataShareBlockWriterImpl instance + 2. Call various write operations (AllocRow, Write with different types) + 3. Check return values of all operations + * @tc.expect: + 1. All operations return E_ERROR + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_shareBlock_Null_Test_001, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_shareBlock_Null_Test_001::Start"); @@ -81,6 +118,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_shareBlock_Null_Test_001, TestSi LOG_INFO("AbnormalBranchTest_shareBlock_Null_Test_001::End"); } +/** + * @tc.name: AbnormalBranchTest_ResultSetStubNull_Test_001 + * @tc.desc: Verify ISharedResultSetStub behavior when input parameters are null + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create ISharedResultSetStub instance with null parameter + 2. Call CreateStub method with null result and valid parcel + 3. Check returned ISharedResultSet pointer + * @tc.expect: + 1. CreateStub returns nullptr + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_ResultSetStubNull_Test_001, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_ResultSetStubNull_Test_001::Start"); @@ -92,6 +141,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_ResultSetStubNull_Test_001, Test LOG_INFO("AbnormalBranchTest_ResultSetStubNull_Test_001::End"); } +/** + * @tc.name: AbnormalBranchTest_RegisterClientDeathObserverNull_Test_001 + * @tc.desc: Verify RegisterClientDeathObserver with null observer + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create DataShareKvServiceProxy with null parameter + 2. Call RegisterClientDeathObserver with empty appId and null observer + 3. Check return value + * @tc.expect: + 1. Method returns -1 (failure) + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_RegisterClientDeathObserverNull_Test_001, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_RegisterClientDeathObserverNull_Test_001::Start"); @@ -102,14 +163,31 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_RegisterClientDeathObserverNull_ LOG_INFO("AbnormalBranchTest_RegisterClientDeathObserverNull_Test_001::End"); } +/** + * @tc.name: AbnormalBranchTest_mReadOnlyInvalid_Test_001 + * @tc.desc: Verify invalid operations on read-only SharedBlock + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create read-only SharedBlock instance + 2. Attempt modification operations (Clear, SetColumnNum, AllocRow, etc.) + 3. Check return values of all operations + * @tc.expect: + 1. All modification operations return SHARED_BLOCK_INVALID_OPERATION + 2. Init operation succeeds + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_mReadOnlyInvalid_Test_001, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_mReadOnlyInvalid_Test_001::Start"); - std::string name; - size_t size = 0; + std::string name = "Test Shared\0"; bool readOnly = true; - AppDataFwk::SharedBlock temp(name, nullptr, size, readOnly); - int result = temp.Clear(); + int32_t size = 1024; + sptr ashmem = Ashmem::CreateAshmem(name.c_str(), size); + ashmem->MapReadAndWriteAshmem(); + AppDataFwk::SharedBlock temp(name, ashmem, size, readOnly); + int result = temp.Init(); + EXPECT_TRUE(result); + result = temp.Clear(); EXPECT_EQ(result, AppDataFwk::SharedBlock::SHARED_BLOCK_INVALID_OPERATION); result = temp.SetColumnNum(1); EXPECT_EQ(result, AppDataFwk::SharedBlock::SHARED_BLOCK_INVALID_OPERATION); @@ -125,11 +203,23 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_mReadOnlyInvalid_Test_001, TestS EXPECT_EQ(result, AppDataFwk::SharedBlock::SHARED_BLOCK_INVALID_OPERATION); result = temp.PutNull(1, 1); EXPECT_EQ(result, AppDataFwk::SharedBlock::SHARED_BLOCK_INVALID_OPERATION); - result = temp.SetRawData(nullptr, size); + result = temp.SetRawData(nullptr, 0); EXPECT_EQ(result, AppDataFwk::SharedBlock::SHARED_BLOCK_INVALID_OPERATION); LOG_INFO("AbnormalBranchTest_mReadOnlyInvalid_Test_001::End"); } +/** + * @tc.name: AbnormalBranchTest_CreatorPossibleNull_Test_002 + * @tc.desc: Verify DataShareHelper::Creator with invalid parameters + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare CreateOptions with null token + 2. Call DataShareHelper::Creator with empty URI and prepared options + 3. Check returned DataShareHelper pointer + * @tc.expect: + 1. Creator returns nullptr (failure to create helper) + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_CreatorPossibleNull_Test_002, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_CreatorPossibleNull_Test_002::Start"); @@ -143,6 +233,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_CreatorPossibleNull_Test_002, Te LOG_INFO("AbnormalBranchTest_CreatorPossibleNull_Test_002::End"); } +/** + * @tc.name: AbnormalBranchTest_AddObserversProxyNull_Test_001 + * @tc.desc: Verify PublishedDataSubscriberManager::AddObservers with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null proxy and empty URIs list + 2. Call AddObservers with null subscriber, proxy and empty URIs + 3. Check size of returned results + * @tc.expect: + 1. Results size equals URIs size (0 in this case) + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_AddObserversProxyNull_Test_001, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_AddObserversProxyNull_Test_001::Start"); @@ -157,6 +259,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_AddObserversProxyNull_Test_001, LOG_INFO("AbnormalBranchTest_AddObserversProxyNull_Test_001::End"); } +/** + * @tc.name: AbnormalBranchTest_AddObserversProxyNull_Test_002 + * @tc.desc: Verify RdbSubscriberManager::AddObservers with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null proxy and empty URIs list + 2. Call AddObservers with null subscriber, proxy and empty URIs + 3. Check size of returned results + * @tc.expect: + 1. Results size equals URIs size (0 in this case) + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_AddObserversProxyNull_Test_002, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_AddObserversProxyNull_Test_002::Start"); @@ -171,6 +285,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_AddObserversProxyNull_Test_002, LOG_INFO("AbnormalBranchTest_AddObserversProxyNull_Test_002::End"); } +/** + * @tc.name: AbnormalBranchTest_DelObserversProxyNull_Test_001 + * @tc.desc: Verify PublishedDataSubscriberManager::DelObservers with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null proxy and empty URIs list + 2. Call DelObservers with null subscriber and proxy (both overloads) + 3. Check size of returned results + * @tc.expect: + 1. Results size equals URIs size (0 in this case) for both overloads + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_DelObserversProxyNull_Test_001, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_DelObserversProxyNull_Test_001::Start"); @@ -186,6 +312,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_DelObserversProxyNull_Test_001, LOG_INFO("AbnormalBranchTest_DelObserversProxyNull_Test_001::End"); } +/** + * @tc.name: AbnormalBranchTest_DelObserversProxyNull_Test_002 + * @tc.desc: Verify RdbSubscriberManager::DelObservers with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null proxy and empty URIs list + 2. Call DelObservers with null subscriber and proxy (both overloads) + 3. Check size of returned results + * @tc.expect: + 1. Results size equals URIs size (0 in this case) for both overloads + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_DelObserversProxyNull_Test_002, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_DelObserversProxyNull_Test_002::Start"); @@ -201,6 +339,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_DelObserversProxyNull_Test_002, LOG_INFO("AbnormalBranchTest_DelObserversProxyNull_Test_002::End"); } +/** + * @tc.name: AbnormalBranchTest_EnableObserversProxyNull_Test_001 + * @tc.desc: Verify PublishedDataSubscriberManager::EnableObservers with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null proxy and empty URIs list + 2. Call EnableObservers with null subscriber, proxy and empty URIs + 3. Check size of returned results + * @tc.expect: + 1. Results size equals URIs size (0 in this case) + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_EnableObserversProxyNull_Test_001, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_EnableObserversProxyNull_Test_001::Start"); @@ -214,6 +364,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_EnableObserversProxyNull_Test_00 LOG_INFO("AbnormalBranchTest_EnableObserversProxyNull_Test_001::End"); } +/** + * @tc.name: AbnormalBranchTest_EnableObserversProxyNull_Test_002 + * @tc.desc: Verify RdbSubscriberManager::EnableObservers with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null proxy and empty URIs list + 2. Call EnableObservers with null subscriber, proxy and empty URIs + 3. Check size of returned results + * @tc.expect: + 1. Results size equals URIs size (0 in this case) + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_EnableObserversProxyNull_Test_002, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_EnableObserversProxyNull_Test_002::Start"); @@ -227,6 +389,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_EnableObserversProxyNull_Test_00 LOG_INFO("AbnormalBranchTest_EnableObserversProxyNull_Test_002::End"); } +/** + * @tc.name: AbnormalBranchTest_DisableObserversProxyNull_Test_001 + * @tc.desc: Verify PublishedDataSubscriberManager::DisableObservers with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null proxy and empty URIs list + 2. Call DisableObservers with null subscriber, proxy and empty URIs + 3. Check size of returned results + * @tc.expect: + 1. Results size equals URIs size (0 in this case) + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_DisableObserversProxyNull_Test_001, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_DisableObserversProxyNull_Test_001::Start"); @@ -240,6 +414,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_DisableObserversProxyNull_Test_0 LOG_INFO("AbnormalBranchTest_DisableObserversProxyNull_Test_001::End"); } +/** + * @tc.name: AbnormalBranchTest_DisableObserversProxyNull_Test_002 + * @tc.desc: Verify RdbSubscriberManager::DisableObservers with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null proxy and empty URIs list + 2. Call DisableObservers with null subscriber, proxy and empty URIs + 3. Check size of returned results + * @tc.expect: + 1. Results size equals URIs size (0 in this case) + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_DisableObserversProxyNull_Test_002, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_DisableObserversProxyNull_Test_002::Start"); @@ -252,5 +438,899 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_DisableObserversProxyNull_Test_0 EXPECT_EQ(results.size(), uris.size()); LOG_INFO("AbnormalBranchTest_DisableObserversProxyNull_Test_002::End"); } + +/** + * @tc.name: PublishDelObserversTest001 + * @tc.desc: Verify PublishedDataSubscriberManager observer operations with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null subscriber and valid proxy + 2. Call DisableObservers with null proxy and valid URIs + 3. Call DelObservers with valid proxy and URIs + 4. Call RecoverObservers with null proxy + 5. Check results sizes + * @tc.expect: + 1. DisableObservers with null proxy returns 0 results + 2. DelObservers with valid proxy returns results matching URIs size + */ +HWTEST_F(AbnormalBranchTest, PublishDelObserversTest001, TestSize.Level0) +{ + LOG_INFO("PublishDelObserversTest001::Start"); + void *subscriber = nullptr; + auto proxy = DataShareManagerImpl::GetServiceProxy(); + std::vector uris = {}; + std::string uri = "datashare:///com.test/db0/tbl0"; + uris.push_back(uri); + int64_t subscriberId = 0; + std::vector results = PublishedDataSubscriberManager::GetInstance().DisableObservers(subscriber, + nullptr, uris, subscriberId); + EXPECT_EQ(results.size(), 0); + results = PublishedDataSubscriberManager::GetInstance().DelObservers(subscriber, + proxy, uris, subscriberId); + EXPECT_EQ(results.size(), uris.size()); + proxy = nullptr; + PublishedDataSubscriberManager::GetInstance().RecoverObservers(proxy); + LOG_INFO("PublishDelObserversTest001::End"); +} + +/** + * @tc.name: PublishedDataSubscriberManagerOperatorTest001 + * @tc.desc: Verify PublishedDataObserver comparison operators + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create two PublishedDataObserver instances with identical callbacks + 2. Compare them using != and == operators + 3. Check comparison results + * @tc.expect: + 1. != operator returns true (observers are distinct) + 2. == operator returns false (observers are distinct) + */ +HWTEST_F(AbnormalBranchTest, PublishedDataSubscriberManagerOperatorTest001, TestSize.Level0) +{ + LOG_INFO("PublishedDataSubscriberManagerOperatorTest001::Start"); + const PublishedDataCallback callback = [](const PublishedDataChangeNode &changeNode){}; + PublishedDataObserver ob(callback); + PublishedDataObserver obCompare(callback); + EXPECT_TRUE(ob != obCompare); + EXPECT_FALSE(ob == obCompare); + LOG_INFO("PublishedDataSubscriberManagerOperatorTest001::End"); +} + +/** + * @tc.name: RdbDelObserversTest001 + * @tc.desc: Verify RdbSubscriberManager::DelObservers with valid and null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null subscriber and valid proxy + 2. Call DelObservers with valid proxy and URIs + 3. Call RecoverObservers with null proxy + 4. Check results size + * @tc.expect: + 1. DelObservers returns results matching URIs size + */ +HWTEST_F(AbnormalBranchTest, RdbDelObserversTest001, TestSize.Level0) +{ + LOG_INFO("RdbDelObserversTest001::Start"); + void *subscriber = nullptr; + auto proxy = DataShareManagerImpl::GetServiceProxy(); + std::vector uris = {}; + std::string uri = "datashare:///com.test/db0/tbl0"; + uris.push_back(uri); + TemplateId templateId; + std::vector results = RdbSubscriberManager::GetInstance().DelObservers(subscriber, + proxy, uris, templateId); + EXPECT_EQ(results.size(), uris.size()); + proxy = nullptr; + PublishedDataSubscriberManager::GetInstance().RecoverObservers(proxy); + LOG_INFO("RdbDelObserversTest001::End"); +} + +/** + * @tc.name: RdbDisableObserversTest001 + * @tc.desc: Verify RdbSubscriberManager::DisableObservers with valid and null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null subscriber and valid proxy + 2. Call DisableObservers with null proxy and valid URIs + 3. Call DisableObservers with valid proxy and URIs + 4. Call RecoverObservers with null proxy + 5. Check results sizes + * @tc.expect: + 1. DisableObservers with null proxy returns 0 results + 2. DisableObservers with valid proxy returns results matching URIs size + */ +HWTEST_F(AbnormalBranchTest, RdbDisableObserversTest001, TestSize.Level0) +{ + LOG_INFO("RdbDisableObserversTest001::Start"); + void *subscriber = nullptr; + auto proxy = DataShareManagerImpl::GetServiceProxy(); + std::vector uris = {}; + std::string uri = "datashare:///com.test/db0/tbl0"; + uris.push_back(uri); + TemplateId templateId; + std::vector results = RdbSubscriberManager::GetInstance().DisableObservers(subscriber, + nullptr, uris, templateId); + EXPECT_EQ(results.size(), 0); + results = RdbSubscriberManager::GetInstance().DisableObservers(subscriber, + proxy, uris, templateId); + EXPECT_EQ(results.size(), uris.size()); + proxy = nullptr; + RdbSubscriberManager::GetInstance().RecoverObservers(proxy); + LOG_INFO("RdbDisableObserversTest001::End"); +} + +/** + * @tc.name: RdbSubscriberManagerOperatorTest001 + * @tc.desc: Verify RdbObserver comparison operators + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create two RdbObserver instances with identical callbacks + 2. Compare them using != and == operators + 3. Check comparison results + * @tc.expect: + 1. != operator returns true (observers are distinct) + 2. == operator returns false (observers are distinct) + */ +HWTEST_F(AbnormalBranchTest, RdbSubscriberManagerOperatorTest001, TestSize.Level0) +{ + LOG_INFO("RdbSubscriberManagerOperatorTest001::Start"); + const RdbCallback callback = [](const RdbChangeNode &changeNode){}; + RdbObserver ob(callback); + RdbObserver obCompare(callback); + EXPECT_TRUE(ob != obCompare); + EXPECT_FALSE(ob == obCompare); + LOG_INFO("RdbSubscriberManagerOperatorTest001::End"); +} + +/** + * @tc.name: RegisterClientDeathObserverTest001 + * @tc.desc: Verify DataShareManagerImpl::RegisterClientDeathObserver under various conditions + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create DataShareManagerImpl instance with null service and empty bundle name + 2. Call RegisterClientDeathObserver + 3. Set valid service proxy and call again + 4. Set valid bundle name and call again + 5. Check clientDeathObserverPtr_ state + * @tc.expect: + 1. Observer remains null with empty bundle name + 2. Observer is created when valid bundle name is provided + */ +HWTEST_F(AbnormalBranchTest, RegisterClientDeathObserverTest001, TestSize.Level0) +{ + LOG_INFO("RegisterClientDeathObserverTest001::Start"); + auto datashareManager = new DataShareManagerImpl(); + datashareManager->dataMgrService_ = nullptr; + datashareManager->bundleName_ = ""; + datashareManager->clientDeathObserverPtr_ = nullptr; + datashareManager->RegisterClientDeathObserver(); + datashareManager->dataMgrService_ = datashareManager->GetDistributedDataManager(); + EXPECT_NE(datashareManager->dataMgrService_, nullptr); + datashareManager->RegisterClientDeathObserver(); + EXPECT_EQ(datashareManager->clientDeathObserverPtr_, nullptr); + datashareManager->bundleName_ = "com.testbundlename"; + datashareManager->RegisterClientDeathObserver(); + EXPECT_NE(datashareManager->clientDeathObserverPtr_, nullptr); + datashareManager->RegisterClientDeathObserver(); + LOG_INFO("RegisterClientDeathObserverTest001::End"); +} + +/** +* @tc.name: RegisterClientDeathObserverTest002 +* @tc.desc: Check the main process of RegisterClientDeathObserver +* @tc.type: FUNC +* @tc.precon: None +* @tc.expect: Successfully register client death observer +* @tc.step: 1. Create a DataShareManagerImpl instance; + 2. Try to use the instance to get datashare service proxy; + 3. Check whether all member functions of the object are successfully constructed. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, RegisterClientDeathObserverTest002, TestSize.Level0) +{ + LOG_INFO("RegisterClientDeathObserverTest002::Start"); + auto datashareManager = DataShareManagerImpl::GetInstance(); + datashareManager->SetBundleName("com.testbundlename"); + datashareManager->GetDataShareServiceProxy(); + EXPECT_NE(datashareManager->dataMgrService_, nullptr); + EXPECT_NE(datashareManager->bundleName_, ""); + EXPECT_NE(datashareManager->clientDeathObserverPtr_, nullptr); + LOG_INFO("RegisterClientDeathObserverTest002::End"); +} + +/** +* @tc.name: OnRemoteDiedTest001 +* @tc.desc: Check the main process of OnRemoteDied and the reset process ResetServiceHandle +* @tc.type: FUNC +* @tc.precon: None +* @tc.expect: Successfully process OnRemoteDied +* @tc.step: 1. Create a DataShareManagerImpl instance; + 2. Call the OnRemoteDied() function; + 3. Check whether datashareManager is successfully deconstructed. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, OnRemoteDiedTest001, TestSize.Level0) +{ + LOG_INFO("OnRemoteDiedTest001::Start"); + auto datashareManager = DataShareManagerImpl::GetInstance(); + datashareManager->SetBundleName("com.testbundlename"); + datashareManager->GetDataShareServiceProxy(); + EXPECT_NE(datashareManager->dataMgrService_, nullptr); + EXPECT_NE(datashareManager->bundleName_, ""); + EXPECT_NE(datashareManager->clientDeathObserverPtr_, nullptr); + + datashareManager->OnRemoteDied(); + EXPECT_EQ(datashareManager->dataMgrService_, nullptr); + EXPECT_EQ(datashareManager->dataShareService_, nullptr); + LOG_INFO("OnRemoteDiedTest001::End"); +} + +/** +* @tc.name: SetRegisterCallbackTest001 +* @tc.desc: Check the main process of SetRegisterCallback +* @tc.type: FUNC +* @tc.precon: None +* @tc.expect: Successfully process SetRegisterCallback +* @tc.step: 1. Create a DataShareManagerImpl instance; + 2. Call the SetRegisterCallback() function; + 3. Check whether datashareManager is successfully deconstructed. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, SetRegisterCallbackTest001, TestSize.Level0) +{ + LOG_INFO("SetRegisterCallbackTest001::Start"); + auto datashareManager = DataShareManagerImpl::GetInstance(); + std::function callback = [](){}; + datashareManager->SetRegisterCallback(nullptr, callback); + LOG_INFO("SetRegisterCallbackTest001::End"); +} + +/** + * @tc.name: AmsMgrProxyOnProxyDiedTest001 + * @tc.desc: Verify AmsMgrProxy behavior when proxy dies + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create AmsMgrProxy with null service and proxy + 2. Call OnProxyDied and verify state + 3. Create new proxy, connect to SA, verify initialization + 4. Call OnProxyDied again and verify cleanup + * @tc.expect: + 1. OnProxyDied handles null pointers gracefully + 2. Proxy initializes properly after ConnectSA + 3. OnProxyDied cleans up resources + */ +HWTEST_F(AbnormalBranchTest, AmsMgrProxyOnProxyDiedTest001, TestSize.Level0) +{ + LOG_INFO("AmsMgrProxyOnProxyDiedTest001::Start"); + AmsMgrProxy* proxy = new AmsMgrProxy(); + proxy->sa_ = nullptr; + proxy->proxy_ = nullptr; + proxy->OnProxyDied(); + delete proxy; + proxy = new AmsMgrProxy(); + proxy->sa_ = nullptr; + proxy->proxy_ = nullptr; + proxy->ConnectSA(); + EXPECT_NE(proxy->sa_, nullptr); + EXPECT_NE(proxy->proxy_, nullptr); + EXPECT_NE(proxy->deathRecipient_, nullptr); + proxy->OnProxyDied(); + delete proxy; + LOG_INFO("AmsMgrProxyOnProxyDiedTest001::End"); +} + +/** +* @tc.name: AmsMgrProxyOnProxyDiedTest002 +* @tc.desc: Test sa_ with nullptr and destructor of AmsMgrProxy +* @tc.type: FUNC +* @tc.precon: None +* @tc.expect: Successfully process SetRegisterCallback +* @tc.step: 1. Create a AmsMgrProxy instance; + 2. Clear the proxy; + 3. After clear, try to connect SA; + 4. Check if this proxy can be connected successfully. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, AmsMgrProxyOnProxyDiedTest002, TestSize.Level0) +{ + LOG_INFO("AmsMgrProxyOnProxyDiedTest002::Start"); + AmsMgrProxy* proxy = AmsMgrProxy::GetInstance(); + proxy->OnProxyDied(); + proxy->ConnectSA(); + EXPECT_NE(proxy->sa_, nullptr); + EXPECT_NE(proxy->proxy_, nullptr); + EXPECT_NE(proxy->deathRecipient_, nullptr); + LOG_INFO("AmsMgrProxyOnProxyDiedTest002::End"); +} + +/** + * @tc.name: DataShareServiceProxySubscribeRdbDataTest001 + * @tc.desc: Verify DataShareServiceProxy subscription behavior after proxy death + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create AmsMgrProxy with null service and proxy + 2. Call OnProxyDied and verify cleanup + 3. Create new proxy, connect to SA, verify initialization + 4. Call OnProxyDied again and verify cleanup + * @tc.expect: + 1. Proxy handles null states gracefully + 2. Proxy initializes properly after ConnectSA + 3. Resources are cleaned up after OnProxyDied + */ +HWTEST_F(AbnormalBranchTest, DataShareServiceProxySubscribeRdbDataTest001, TestSize.Level0) +{ + LOG_INFO("DataShareServiceProxySubscribeRdbDataTest001::Start"); + AmsMgrProxy* proxy = new AmsMgrProxy(); + proxy->sa_ = nullptr; + proxy->proxy_ = nullptr; + proxy->OnProxyDied(); + delete proxy; + proxy = new AmsMgrProxy(); + proxy->sa_ = nullptr; + proxy->proxy_ = nullptr; + proxy->ConnectSA(); + EXPECT_NE(proxy->sa_, nullptr); + EXPECT_NE(proxy->proxy_, nullptr); + EXPECT_NE(proxy->deathRecipient_, nullptr); + proxy->OnProxyDied(); + delete proxy; + LOG_INFO("DataShareServiceProxySubscribeRdbDataTest001::End"); +} + +/** + * @tc.name: SubscribeRdbDataTest001 + * @tc.desc: Verify SubscribeRdbData with empty URIs and null observer + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare empty URIs list and null observer + 2. Call SubscribeRdbData with valid proxy + 3. Check size of returned result set + * @tc.expect: + 1. Result set size is 0 (matches empty URIs list) + */ +HWTEST_F(AbnormalBranchTest, SubscribeRdbDataTest001, TestSize.Level0) +{ + LOG_INFO("EnableSubscribePublishedDataTest001::Start"); + std::vector uris = {}; + TemplateId templateId; + sptr observer = OHOS::sptr(nullptr); + auto proxy = DataShareManagerImpl::GetServiceProxy(); + auto resultset = proxy->SubscribeRdbData(uris, templateId, observer); + EXPECT_EQ(resultset.size(), 0); + LOG_INFO("EnableSubscribePublishedDataTest001::End"); +} + +/** + * @tc.name: SubscribePublishedDataTest001 + * @tc.desc: Verify SubscribePublishedData with empty URIs and null observer + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare empty URIs list and null observer + 2. Call SubscribePublishedData with valid proxy + 3. Check size of returned result set + * @tc.expect: + 1. Result set size is 0 (matches empty URIs list) + */ +HWTEST_F(AbnormalBranchTest, SubscribePublishedDataTest001, TestSize.Level0) +{ + LOG_INFO("SubscribePublishedDataTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 1; + sptr observer = OHOS::sptr(nullptr); + auto proxy = DataShareManagerImpl::GetServiceProxy(); + auto resultset = proxy->SubscribePublishedData(uris, subscriberId, observer); + EXPECT_EQ(resultset.size(), 0); + LOG_INFO("SubscribePublishedDataTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplInsertTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return an DATA_SHARE_ERROR. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call Insert() in GeneralControllerServiceImpl; + 3. Check if the function return DATA_SHARE_ERROR. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplInsertTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplInsertTest001::Start"); + DataShareManagerImplHelper(); + DataShare::DataShareValuesBucket valuesBucket; + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + Uri uri(proxyUri); + auto generalCtl = std::make_shared(proxyUri); + int ret = generalCtl->Insert(uri, valuesBucket); + EXPECT_EQ(ret, DATA_SHARE_ERROR); + LOG_INFO("GeneralControllerServiceImplInsertTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplUpdateTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return an DATA_SHARE_ERROR. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call Update() in GeneralControllerServiceImpl; + 3. Check if the function return DATA_SHARE_ERROR. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplUpdateTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplUpdateTest001::Start"); + DataShareManagerImplHelper(); + DataShare::DataSharePredicates predicates; + DataShare::DataShareValuesBucket valuesBucket; + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + Uri uri(proxyUri); + auto generalCtl = std::make_shared(proxyUri); + int ret = generalCtl->Update(uri, predicates, valuesBucket); + EXPECT_EQ(ret, DATA_SHARE_ERROR); + LOG_INFO("GeneralControllerServiceImplUpdateTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplDeleteTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return an DATA_SHARE_ERROR. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call Update() in GeneralControllerServiceImpl; + 3. Check if the function return DATA_SHARE_ERROR. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplDeleteTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplDeleteTest001::Start"); + DataShareManagerImplHelper(); + DataShare::DataSharePredicates predicates; + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + Uri uri(proxyUri); + auto generalCtl = std::make_shared(proxyUri); + int ret = generalCtl->Delete(uri, predicates); + EXPECT_EQ(ret, DATA_SHARE_ERROR); + LOG_INFO("GeneralControllerServiceImplDeleteTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplInsertExTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code + and return pair of DATA_SHARE_ERROR and 0. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call InsertEx() in GeneralControllerServiceImpl; + 3. Check if the function return pair of DATA_SHARE_ERROR and 0. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplInsertExTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplInsertExTest001::Start"); + DataShareManagerImplHelper(); + DataShare::DataShareValuesBucket valuesBucket; + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + Uri uri(proxyUri); + auto generalCtl = std::make_shared(proxyUri); + auto ret = generalCtl->InsertEx(uri, valuesBucket); + EXPECT_EQ(ret, std::make_pair(DATA_SHARE_ERROR, 0)); + LOG_INFO("GeneralControllerServiceImplInsertExTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplUpdateExTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code + and return pair of DATA_SHARE_ERROR and 0. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call UpdateEx() in GeneralControllerServiceImpl; + 3. Check if the function return pair of DATA_SHARE_ERROR and 0. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplUpdateExTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplUpdateExTest001::Start"); + DataShareManagerImplHelper(); + DataShare::DataSharePredicates predicates; + DataShare::DataShareValuesBucket valuesBucket; + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + Uri uri(proxyUri); + auto generalCtl = std::make_shared(proxyUri); + auto ret = generalCtl->UpdateEx(uri, predicates, valuesBucket); + EXPECT_EQ(ret, std::make_pair(DATA_SHARE_ERROR, 0)); + LOG_INFO("GeneralControllerServiceImplUpdateExTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplDeleteExTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code + and return pair of DATA_SHARE_ERROR and 0. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call DeleteEx() in GeneralControllerServiceImpl; + 3. Check if the function return pair of DATA_SHARE_ERROR and 0. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplDeleteExTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplDeleteExTest001::Start"); + DataShareManagerImplHelper(); + DataShare::DataSharePredicates predicates; + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + Uri uri(proxyUri); + auto generalCtl = std::make_shared(proxyUri); + auto ret = generalCtl->DeleteEx(uri, predicates); + EXPECT_EQ(ret, std::make_pair(DATA_SHARE_ERROR, 0)); + LOG_INFO("GeneralControllerServiceImplDeleteExTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplQueryTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return a nullptr. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call Query() in GeneralControllerServiceImpl; + 3. Check if the function return nullptr. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplQueryTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplQueryTest001::Start"); + DataShareManagerImplHelper(); + DataShare::DataSharePredicates predicates; + std::vector columns; + DatashareBusinessError error; + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + Uri uri(proxyUri); + auto generalCtl = std::make_shared(proxyUri); + DataShareOption option; + auto ret = generalCtl->Query(uri, predicates, columns, error, option); + EXPECT_EQ(ret, nullptr); + LOG_INFO("GeneralControllerServiceImplQueryTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplNotifyChangeTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call NotifyChange() in GeneralControllerServiceImpl; + 3. Check if the function return. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplNotifyChangeTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplNotifyChangeTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + Uri uri(proxyUri); + auto generalCtl = std::make_shared(proxyUri); + generalCtl->NotifyChange(uri); + LOG_INFO("GeneralControllerServiceImplNotifyChangeTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplSetRegisterCallbackTest001 +* @tc.desc: Check the main process +* @tc.type: FUNC +* @tc.precon: None +* @tc.expect: Enter the DataShareManagerImpl::GetInstance() branch in the code. +* @tc.step: 1. Call SetRegisterCallback() in GeneralControllerServiceImpl; + 2. Check if the function return. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplSetRegisterCallbackTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplSetRegisterCallbackTest001::Start"); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + auto generalCtl = std::make_shared(proxyUri); + generalCtl->SetRegisterCallback(); + LOG_INFO("GeneralControllerServiceImplSetRegisterCallbackTest001::End"); +} + +/** +* @tc.name: PersistentDataControllerAddQueryTemplateTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return INVALID_VALUE +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call AddQueryTemplate() in PersistentDataController; + 3. Check if the function return INVALID_VALUE. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PersistentDataControllerAddQueryTemplateTest001, TestSize.Level1) +{ + LOG_INFO("PersistentDataControllerAddQueryTemplateTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector nodes; + Template tpl(nodes, "select name1 as name from TBL00"); + auto controller = PersistentDataController(); + auto ret = controller.AddQueryTemplate(proxyUri, 0, tpl); + EXPECT_EQ(ret, INVALID_VALUE); + LOG_INFO("PersistentDataControllerAddQueryTemplateTest001::End"); +} + +/** +* @tc.name: PersistentDataControllerDelQueryTemplateTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return INVALID_VALUE +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call DelQueryTemplate() in PersistentDataController; + 3. Check if the function return INVALID_VALUE. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PersistentDataControllerDelQueryTemplateTest001, TestSize.Level1) +{ + LOG_INFO("PersistentDataControllerDelQueryTemplateTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + auto controller = PersistentDataController(); + auto ret = controller.DelQueryTemplate(proxyUri, 0); + EXPECT_EQ(ret, INVALID_VALUE); + LOG_INFO("PersistentDataControllerDelQueryTemplateTest001::End"); +} + +/** +* @tc.name: PersistentDataControllerSubscribeRdbDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call SubscribeRdbData() in PersistentDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PersistentDataControllerSubscribeRdbDataTest001, TestSize.Level1) +{ + LOG_INFO("PersistentDataControllerSubscribeRdbDataTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector uris = {proxyUri}; + TemplateId tplId; + auto callback = std::function(); + auto controller = PersistentDataController(); + auto ret = controller.SubscribeRdbData(nullptr, uris, tplId, callback); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PersistentDataControllerSubscribeRdbDataTest001::End"); +} + +/** +* @tc.name: PersistentDataControllerUnSubscribeRdbDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call UnSubscribeRdbData() in PersistentDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PersistentDataControllerUnSubscribeRdbDataTest001, TestSize.Level1) +{ + LOG_INFO("PersistentDataControllerUnSubscribeRdbDataTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector uris = {proxyUri}; + TemplateId tplId; + auto controller = PersistentDataController(); + auto ret = controller.UnSubscribeRdbData(nullptr, uris, tplId); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PersistentDataControllerUnSubscribeRdbDataTest001::End"); +} + +/** +* @tc.name: PersistentDataControllerEnableSubscribeRdbDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call EnableSubscribeRdbData() in PersistentDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PersistentDataControllerEnableSubscribeRdbDataTest001, TestSize.Level1) +{ + LOG_INFO("PersistentDataControllerEnableSubscribeRdbDataTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector uris = {proxyUri}; + TemplateId tplId; + auto controller = PersistentDataController(); + auto ret = controller.EnableSubscribeRdbData(nullptr, uris, tplId); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PersistentDataControllerEnableSubscribeRdbDataTest001::End"); +} + +/** +* @tc.name: PersistentDataControllerDisableSubscribeRdbDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call DisableSubscribeRdbData() in PersistentDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PersistentDataControllerDisableSubscribeRdbDataTest001, TestSize.Level1) +{ + LOG_INFO("PersistentDataControllerDisableSubscribeRdbDataTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector uris = {proxyUri}; + TemplateId tplId; + auto controller = PersistentDataController(); + auto ret = controller.DisableSubscribeRdbData(nullptr, uris, tplId); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PersistentDataControllerDisableSubscribeRdbDataTest001::End"); +} + +/** +* @tc.name: PublishedDataControllerPublishTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call Publish() in PublishedDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PublishedDataControllerPublishTest001, TestSize.Level1) +{ + LOG_INFO("PublishedDataControllerPublishTest001::Start"); + DataShareManagerImplHelper(); + Data data; + std::string bundleName = "com.acts.ohos.data.datasharetest"; + auto controller = PublishedDataController(); + auto ret = controller.Publish(data, bundleName); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PublishedDataControllerPublishTest001::End"); +} + +/** +* @tc.name: PublishedDataControllerGetPublishedDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code + and return empty datas_ vector in Data. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call GetPublishedData() in PublishedDataController; + 3. Check if the function return empty datas_ vector in Data. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PublishedDataControllerGetPublishedDataTest001, TestSize.Level1) +{ + LOG_INFO("PublishedDataControllerGetPublishedDataTest001::Start"); + DataShareManagerImplHelper(); + std::string bundleName = "com.acts.ohos.data.datasharetest"; + int errCode = 0; + auto controller = PublishedDataController(); + auto ret = controller.GetPublishedData(bundleName, errCode); + EXPECT_EQ(ret.datas_.size(), 0); + LOG_INFO("PublishedDataControllerGetPublishedDataTest001::End"); +} + +/** +* @tc.name: PublishedDataControllerSubscribePublishedDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call SubscribePublishedData() in PublishedDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PublishedDataControllerSubscribePublishedDataTest001, TestSize.Level1) +{ + LOG_INFO("PublishedDataControllerSubscribePublishedDataTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector uris = {proxyUri}; + auto callback = std::function(); + auto controller = PublishedDataController(); + auto ret = controller.SubscribePublishedData(nullptr, uris, 0, callback); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PublishedDataControllerSubscribePublishedDataTest001::End"); +} + +/** +* @tc.name: PublishedDataControllerSubscribeUnSubscribePublishedDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call UnSubscribePublishedData() in PublishedDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PublishedDataControllerSubscribeUnSubscribePublishedDataTest001, TestSize.Level1) +{ + LOG_INFO("PublishedDataControllerSubscribeUnSubscribePublishedDataTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector uris = {proxyUri}; + auto controller = PublishedDataController(); + auto ret = controller.UnSubscribePublishedData(nullptr, uris, 0); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PublishedDataControllerSubscribeUnSubscribePublishedDataTest001::End"); +} + +/** +* @tc.name: PublishedDataControllerSubscribeEnableSubscribePublishedDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call EnableSubscribePublishedData() in PublishedDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PublishedDataControllerSubscribeEnableSubscribePublishedDataTest001, TestSize.Level1) +{ + LOG_INFO("PublishedDataControllerSubscribeEnableSubscribePublishedDataTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector uris = {proxyUri}; + auto controller = PublishedDataController(); + auto ret = controller.EnableSubscribePublishedData(nullptr, uris, 0); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PublishedDataControllerSubscribeEnableSubscribePublishedDataTest001::End"); +} + +/** +* @tc.name: PublishedDataControllerSubscribeDisableSubscribePublishedDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call DisableSubscribePublishedData() in PublishedDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PublishedDataControllerSubscribeDisableSubscribePublishedDataTest001, TestSize.Level1) +{ + LOG_INFO("PublishedDataControllerSubscribeDisableSubscribePublishedDataTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector uris = {proxyUri}; + auto controller = PublishedDataController(); + auto ret = controller.DisableSubscribePublishedData(nullptr, uris, 0); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PublishedDataControllerSubscribeDisableSubscribePublishedDataTest001::End"); +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/controller_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/controller_test.cpp index 2f8a4590023326a8ceca7d130eebf18ebf0ca35e..09b1d881203641f97bf0e2583c802f4cb1c4eb3f 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/controller_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/controller_test.cpp @@ -22,12 +22,14 @@ #include "data_ability_observer_interface.h" #include "dataobs_mgr_changeinfo.h" #include "datashare_connection.h" +#include "datashare_errno.h" #include "datashare_helper.h" #include "datashare_log.h" #include "ext_special_controller.h" #include "extension_manager_proxy.h" #include "general_controller.h" #include "general_controller_provider_impl.h" +#include "general_controller_service_impl.h" #include "hap_token_info.h" #include "iservice_registry.h" #include "rdb_data_ability_utils.h" @@ -52,6 +54,19 @@ void ControllerTest::TearDownTestCase(void) {} void ControllerTest::SetUp(void) {} void ControllerTest::TearDown(void) {} +/** +* @tc.name: ControllerTest_ProviderImplInsertTest_001 +* @tc.desc: Verify Insert operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Prepare DataShareValuesBucket with test data + 3. Call Insert method with empty URI and values bucket + 4. Check if returned result is negative (indicating failure) +* @tc.expect: + 1. Insert operation returns negative value +*/ HWTEST_F(ControllerTest, ControllerTest_ProviderImplInsertTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_ProviderImplInsertTest_001::Start"); @@ -66,6 +81,20 @@ HWTEST_F(ControllerTest, ControllerTest_ProviderImplInsertTest_001, TestSize.Lev LOG_INFO("ControllerTest_ProviderImplInsertTest_001::End"); } +/** +* @tc.name: ControllerTest_ProviderImplInsertTest_002 +* @tc.desc: Verify Insert operation with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Prepare DataShareValuesBucket with test data + 4. Call Insert method with empty URI and values bucket + 5. Check if returned result is negative (indicating failure) +* @tc.expect: + 1. Insert operation returns negative value +*/ HWTEST_F(ControllerTest, ControllerTest_ProviderImplInsertTest_002, TestSize.Level0) { LOG_INFO("ControllerTest_ProviderImplInsertTest_002::Start"); @@ -86,6 +115,19 @@ HWTEST_F(ControllerTest, ControllerTest_ProviderImplInsertTest_002, TestSize.Lev LOG_INFO("ControllerTest_ProviderImplInsertTest_002::End"); } +/** +* @tc.name: ControllerTest_ProviderImplUpdateTest_001 +* @tc.desc: Verify Update operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Prepare DataSharePredicates and DataShareValuesBucket with test data + 3. Call Update method with empty URI, predicates and values bucket + 4. Check if returned result is negative (indicating failure) +* @tc.expect: + 1. Update operation returns negative value +*/ HWTEST_F(ControllerTest, ControllerTest_ProviderImplUpdateTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_ProviderImplUpdateTest_001::Start"); @@ -101,6 +143,20 @@ HWTEST_F(ControllerTest, ControllerTest_ProviderImplUpdateTest_001, TestSize.Lev LOG_INFO("ControllerTest_ProviderImplUpdateTest_001::End"); } +/** +* @tc.name: ControllerTest_ProviderImplUpdateTest_002 +* @tc.desc: Verify Update operation with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Prepare DataSharePredicates and DataShareValuesBucket with test data + 4. Call Update method with empty URI, predicates and values bucket + 5. Check if returned result is negative (indicating failure) +* @tc.expect: + 1. Update operation returns negative value +*/ HWTEST_F(ControllerTest, ControllerTest_ProviderImplUpdateTest_002, TestSize.Level0) { LOG_INFO("ControllerTest_ProviderImplUpdateTest_002::Start"); @@ -122,6 +178,19 @@ HWTEST_F(ControllerTest, ControllerTest_ProviderImplUpdateTest_002, TestSize.Lev LOG_INFO("ControllerTest_ProviderImplUpdateTest_002::End"); } +/** +* @tc.name: ControllerTest_ProviderImplDeleteTest_001 +* @tc.desc: Verify Delete operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Prepare DataSharePredicates with test conditions + 3. Call Delete method with empty URI and predicates + 4. Check if returned result is negative (indicating failure) +* @tc.expect: + 1. Delete operation returns negative value +*/ HWTEST_F(ControllerTest, ControllerTest_ProviderImplDeleteTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_ProviderImplDeleteTest_001::Start"); @@ -135,6 +204,20 @@ HWTEST_F(ControllerTest, ControllerTest_ProviderImplDeleteTest_001, TestSize.Lev LOG_INFO("ControllerTest_ProviderImplDeleteTest_001::End"); } +/** +* @tc.name: ControllerTest_ProviderImplDeleteTest_002 +* @tc.desc: Verify Delete operation with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Prepare DataSharePredicates with test conditions + 4. Call Delete method with empty URI and predicates + 5. Check if returned result is negative (indicating failure) +* @tc.expect: + 1. Delete operation returns negative value +*/ HWTEST_F(ControllerTest, ControllerTest_ProviderImplDeleteTest_002, TestSize.Level0) { LOG_INFO("ControllerTest_ProviderImplDeleteTest_002::Start"); @@ -154,6 +237,210 @@ HWTEST_F(ControllerTest, ControllerTest_ProviderImplDeleteTest_002, TestSize.Lev LOG_INFO("ControllerTest_ProviderImplDeleteTest_002::End"); } +/** +* @tc.name: Generalcontroller_ServiceImplInsertExTest_001 +* @tc.desc: Verify InsertEx operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Prepare DataShareValuesBucket with test data + 3. Call InsertEx method with empty URI and values bucket + 4. Check if returned result is (DATA_SHARE_ERROR, 0) +* @tc.expect: + 1. InsertEx operation returns pair(DATA_SHARE_ERROR, 0) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplInsertExTest_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplInsertExTest_001::Start"); + Uri uri(""); + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + DataShare::DataShareValuesBucket valuesBucket; + double valueD1 = 20.07; + valuesBucket.Put("phoneNumber", valueD1); + std::pair result = tempGenConProImp->InsertEx(uri, valuesBucket); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + LOG_INFO("Generalcontroller_ServiceImplInsertExTest_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplInsertExTest_002 +* @tc.desc: Verify InsertEx operation with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Prepare DataShareValuesBucket with test data + 4. Call InsertEx method with empty URI and values bucket + 5. Check if returned result is (DATA_SHARE_ERROR, 0) +* @tc.expect: + 1. InsertEx operation returns pair(DATA_SHARE_ERROR, 0) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplInsertExTest_002, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplInsertExTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + DataShare::DataShareValuesBucket valuesBucket; + double valueD1 = 20.07; + valuesBucket.Put("phoneNumber", valueD1); + std::pair result = tempGenConProImp->InsertEx(uri, valuesBucket); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + LOG_INFO("Generalcontroller_ServiceImplInsertExTest_002::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplUpdateExTest_001 +* @tc.desc: Verify UpdateEx operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Prepare DataSharePredicates and DataShareValuesBucket with test data + 3. Call UpdateEx method with empty URI, predicates and values bucket + 4. Check if returned result is (DATA_SHARE_ERROR, 0) +* @tc.expect: + 1. UpdateEx operation returns pair(DATA_SHARE_ERROR, 0) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplUpdateExTest_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplUpdateExTest_001::Start"); + Uri uri(""); + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + DataShare::DataSharePredicates predicates; + predicates.EqualTo("name", "Controller_Test001"); + DataShare::DataShareValuesBucket valuesBucket; + double valueD1 = 20.07; + valuesBucket.Put("phoneNumber", valueD1); + std::pair result = tempGenConProImp->UpdateEx(uri, predicates, valuesBucket); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + LOG_INFO("Generalcontroller_ServiceImplUpdateExTest_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplUpdateExTest_002 +* @tc.desc: Verify UpdateEx operation with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Prepare DataSharePredicates and DataShareValuesBucket with test data + 4. Call UpdateEx method with empty URI, predicates and values bucket + 5. Check if returned result is (DATA_SHARE_ERROR, 0) +* @tc.expect: + 1. UpdateEx operation returns pair(DATA_SHARE_ERROR, 0) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplUpdateExTest_002, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplUpdateExTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + DataShare::DataSharePredicates predicates; + predicates.EqualTo("name", "Controller_Test001"); + DataShare::DataShareValuesBucket valuesBucket; + double valueD1 = 20.07; + valuesBucket.Put("phoneNumber", valueD1); + std::pair result = tempGenConProImp->UpdateEx(uri, predicates, valuesBucket); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + LOG_INFO("Generalcontroller_ServiceImplUpdateExTest_002::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplDeleteExTest_001 +* @tc.desc: Verify DeleteEx operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Prepare DataSharePredicates with test conditions + 3. Call DeleteEx method with empty URI and predicates + 4. Check if returned result is (DATA_SHARE_ERROR, 0) +* @tc.expect: + 1. DeleteEx operation returns pair(DATA_SHARE_ERROR, 0) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplDeleteExTest_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplDeleteExTest_001::Start"); + Uri uri(""); + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + DataShare::DataSharePredicates predicates; + predicates.EqualTo("name", "Controller_Test001"); + std::pair result = tempGenConProImp->DeleteEx(uri, predicates); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + LOG_INFO("Generalcontroller_ServiceImplDeleteExTest_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplDeleteExTest_002 +* @tc.desc: Verify DeleteEx operation with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Prepare DataSharePredicates with test conditions + 4. Call DeleteEx method with empty URI and predicates + 5. Check if returned result is (DATA_SHARE_ERROR, 0) +* @tc.expect: + 1. DeleteEx operation returns pair(DATA_SHARE_ERROR, 0) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplDeleteExTest_002, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplDeleteExTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + DataShare::DataSharePredicates predicates; + predicates.EqualTo("name", "Controller_Test001"); + std::pair result = tempGenConProImp->DeleteEx(uri, predicates); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + LOG_INFO("Generalcontroller_ServiceImplDeleteExTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ProviderImplQueryTest_001 +* @tc.desc: Verify Query operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Prepare DataSharePredicates and column list + 3. Call Query method with empty URI, predicates and columns + 4. Check if returned result is nullptr +* @tc.expect: + 1. Query operation returns nullptr +*/ HWTEST_F(ControllerTest, ControllerTest_ProviderImplQueryTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_ProviderImplQueryTest_001::Start"); @@ -164,11 +451,26 @@ HWTEST_F(ControllerTest, ControllerTest_ProviderImplQueryTest_001, TestSize.Leve predicates.EqualTo("name", "Controller_Test001"); vector columns; DatashareBusinessError error; - auto result = tempGenConProImp->Query(uri, predicates, columns, error); + DataShareOption option; + auto result = tempGenConProImp->Query(uri, predicates, columns, error, option); EXPECT_EQ(result, nullptr); LOG_INFO("ControllerTest_ProviderImplQueryTest_001::End"); } +/** +* @tc.name: ControllerTest_ProviderImplQueryTest_002 +* @tc.desc: Verify Query operation with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Prepare DataSharePredicates and column list + 4. Call Query method with empty URI, predicates and columns + 5. Check if returned result is nullptr +* @tc.expect: + 1. Query operation returns nullptr +*/ HWTEST_F(ControllerTest, ControllerTest_ProviderImplQueryTest_002, TestSize.Level0) { LOG_INFO("ControllerTest_ProviderImplQueryTest_002::Start"); @@ -185,11 +487,631 @@ HWTEST_F(ControllerTest, ControllerTest_ProviderImplQueryTest_002, TestSize.Leve predicates.EqualTo("name", "Controller_Test001"); vector columns; DatashareBusinessError error; - auto result = tempGenConProImp->Query(uri, predicates, columns, error); + DataShareOption option; + auto result = tempGenConProImp->Query(uri, predicates, columns, error, option); EXPECT_EQ(result, nullptr); LOG_INFO("ControllerTest_ProviderImplQueryTest_002::End"); } +/** +* @tc.name: Generalcontroller_ServiceImplRegisterObserverTest_001 +* @tc.desc: Verify RegisterObserver operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Call RegisterObserver method with empty URI and null observer + 3. Verify URI remains empty +* @tc.expect: + 1. URI remains empty after operation +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplRegisterObserverTest_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplRegisterObserverTest_001::Start"); + Uri uri(""); + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + sptr dataObserver; + tempGenConProImp->RegisterObserver(uri, dataObserver); + EXPECT_EQ(uri, Uri("")); + LOG_INFO("Generalcontroller_ServiceImplRegisterObserverTest_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplRegisterObserverTest_002 +* @tc.desc: Verify RegisterObserver with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Call RegisterObserver method with empty URI and null observer + 4. Verify URI remains empty +* @tc.expect: + 1. URI remains empty after operation +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplRegisterObserverTest_002, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplRegisterObserverTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + sptr dataObserver; + tempGenConProImp->RegisterObserver(uri, dataObserver); + EXPECT_EQ(uri, Uri("")); + LOG_INFO("Generalcontroller_ServiceImplRegisterObserverTest_002::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplUnregisterObserverTest_001 +* @tc.desc: Verify UnregisterObserver operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Call UnregisterObserver method with empty URI and null observer + 3. Verify URI remains empty +* @tc.expect: + 1. URI remains empty after operation +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplUnregisterObserverTest_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplUnregisterObserverTest_001::Start"); + Uri uri(""); + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + sptr dataObserver; + tempGenConProImp->UnregisterObserver(uri, dataObserver); + EXPECT_EQ(uri, Uri("")); + LOG_INFO("Generalcontroller_ServiceImplUnregisterObserverTest_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplUnregisterObserverTest_002 +* @tc.desc: Verify UnregisterObserver with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Call UnregisterObserver method with empty URI and null observer + 4. Verify URI remains empty +* @tc.expect: + 1. URI remains empty after operation +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplUnregisterObserverTest_002, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplUnregisterObserverTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + sptr dataObserver; + tempGenConProImp->UnregisterObserver(uri, dataObserver); + EXPECT_EQ(uri, Uri("")); + LOG_INFO("Generalcontroller_ServiceImplUnregisterObserverTest_002::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplNotifyChangeTest_001 +* @tc.desc: Verify NotifyChange operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Call NotifyChange method with empty URI + 3. Verify URI remains empty +* @tc.expect: + 1. URI remains empty after operation +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplNotifyChangeTest_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplNotifyChangeTest_001::Start"); + Uri uri(""); + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + tempGenConProImp->NotifyChange(uri); + EXPECT_EQ(uri, Uri("")); + LOG_INFO("Generalcontroller_ServiceImplNotifyChangeTest_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplNotifyChangeTest_002 +* @tc.desc: Verify NotifyChange with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Call NotifyChange method with empty URI + 4. Verify URI remains empty +* @tc.expect: + 1. URI remains empty after operation +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplNotifyChangeTest_002, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplNotifyChangeTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + tempGenConProImp->NotifyChange(uri); + EXPECT_EQ(uri, Uri("")); + LOG_INFO("Generalcontroller_ServiceImplNotifyChangeTest_002::End"); +} + +/** +* @tc.name: Generalcontroller_ProviderImpl_RegisterObserverExtProvider_Test_001 +* @tc.desc: Verify RegisterObserverExtProvider with null connection and unconnected state +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create provider with null connection and call RegisterObserverExtProvider + 2. Create provider with valid but unconnected connection and call RegisterObserverExtProvider + 3. Check return codes for both cases +* @tc.expect: + 1. First call returns E_PROVIDER_CONN_NULL + 2. Second call returns E_PROVIDER_NOT_CONNECTED +*/ +HWTEST_F(ControllerTest, Generalcontroller_ProviderImpl_RegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ProviderImpl_RegisterObserverExtProvider_Test_001::Start"); + + Uri uri(""); + // connection is nullptr + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + ASSERT_NE(tempGenConProImp, nullptr); + sptr dataObserver; + // make isDescendants false + int ret = tempGenConProImp->RegisterObserverExtProvider(uri, dataObserver, false); + EXPECT_EQ(ret, E_PROVIDER_CONN_NULL); + + // connection not null + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + ASSERT_NE(connection, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + ret = tempGenConProImp->RegisterObserverExtProvider(uri, dataObserver, false); + EXPECT_EQ(ret, E_PROVIDER_NOT_CONNECTED); + + LOG_INFO("Generalcontroller_ProviderImpl_RegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: Generalcontroller_ProviderImpl_UnregisterObserverExtProvider_Test_001 +* @tc.desc: Verify UnregisterObserverExtProvider with null connection and unconnected state +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create provider with null connection and call UnregisterObserverExtProvider + 2. Create provider with valid but unconnected connection and call UnregisterObserverExtProvider + 3. Check return codes for both cases +* @tc.expect: + 1. First call returns E_PROVIDER_CONN_NULL + 2. Second call returns E_PROVIDER_NOT_CONNECTED +*/ +HWTEST_F(ControllerTest, Generalcontroller_ProviderImpl_UnregisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ProviderImpl_UnregisterObserverExtProvider_Test_001::Start"); + + Uri uri(""); + // connection is nullptr + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + ASSERT_NE(tempGenConProImp, nullptr); + sptr dataObserver; + // make isDescendants false + int ret = tempGenConProImp->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(ret, E_PROVIDER_CONN_NULL); + + // connection not null but dataShareProxy is nullptr + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + ASSERT_NE(connection, nullptr); + connection->dataShareProxy_ = nullptr; + ASSERT_EQ(connection->dataShareProxy_, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + ret = tempGenConProImp->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(ret, E_PROVIDER_NOT_CONNECTED); + + LOG_INFO("Generalcontroller_ProviderImpl_UnregisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: Generalcontroller_ProviderImpl_NotifyChangeExtProvider_Test_001 +* @tc.desc: Verify NotifyChangeExtProvider with null connection and unconnected state +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create provider with null connection and call NotifyChangeExtProvider + 2. Create provider with valid but unconnected connection and call NotifyChangeExtProvider + 3. Check return codes for both cases +* @tc.expect: + 1. First call returns E_PROVIDER_CONN_NULL + 2. Second call returns E_PROVIDER_NOT_CONNECTED +*/ +HWTEST_F(ControllerTest, Generalcontroller_ProviderImpl_NotifyChangeExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ProviderImpl_NotifyChangeExtProvider_Test_001::Start"); + + Uri uri(""); + // connection is nullptr + ChangeInfo changeInfo = { ChangeInfo::ChangeType::INSERT, { uri } }; + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + sptr dataObserver; + // make isDescendants false + int ret = tempGenConProImp->NotifyChangeExtProvider(changeInfo); + EXPECT_EQ(ret, E_PROVIDER_CONN_NULL); + + // connection not null + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + ret = tempGenConProImp->NotifyChangeExtProvider(changeInfo); + EXPECT_EQ(ret, E_PROVIDER_NOT_CONNECTED); + + LOG_INFO("Generalcontroller_ProviderImpl_NotifyChangeExtProvider_Test_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImpl_RegisterObserverExtProvider_Test_001 +* @tc.desc: Verify RegisterObserverExtProvider operation in GeneralControllerServiceImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerServiceImpl with test URI + 2. Call RegisterObserverExtProvider with empty URI and null observer + 3. Check return code +* @tc.expect: + 1. Operation returns -1 (failure) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImpl_RegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImpl_RegisterObserverExtProvider_Test_001::Start"); + + Uri uri(""); + std::string extUri = "GeneralControllerServiceImpl"; + + std::shared_ptr tempGenConProImp = + std::make_shared(extUri); + ASSERT_NE(tempGenConProImp, nullptr); + sptr dataObserver; + + int ret = tempGenConProImp->RegisterObserverExtProvider(uri, dataObserver, false); + EXPECT_EQ(ret, -1); + + LOG_INFO("Generalcontroller_ServiceImpl_RegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImpl_UnregisterObserverExtProvider_Test_001 +* @tc.desc: Verify UnregisterObserverExtProvider operation in GeneralControllerServiceImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerServiceImpl with test URI + 2. Call UnregisterObserverExtProvider with empty URI and null observer + 3. Check return code +* @tc.expect: + 1. Operation returns -1 (failure) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImpl_UnregisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImpl_UnregisterObserverExtProvider_Test_001::Start"); + + Uri uri(""); + std::string extUri = "GeneralControllerServiceImpl"; + + std::shared_ptr tempGenConProImp = + std::make_shared(extUri); + ASSERT_NE(tempGenConProImp, nullptr); + sptr dataObserver; + + int ret = tempGenConProImp->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(ret, -1); + + LOG_INFO("Generalcontroller_ServiceImpl_UnregisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImpl_NotifyChangeExtProvider_Test_001 +* @tc.desc: Verify NotifyChangeExtProvider operation in GeneralControllerServiceImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerServiceImpl with test URI + 2. Prepare ChangeInfo with empty URI + 3. Call NotifyChangeExtProvider with the change info + 4. Check return code +* @tc.expect: + 1. Operation returns -1 (failure) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImpl_NotifyChangeExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImpl_NotifyChangeExtProvider_Test_001::Start"); + + Uri uri(""); + std::string extUri = "GeneralControllerServiceImpl"; + + ChangeInfo changeInfo = { ChangeInfo::ChangeType::INSERT, { uri } }; + // connection is nullptr + std::shared_ptr tempGenConProImp = + std::make_shared(extUri); + ASSERT_NE(tempGenConProImp, nullptr); + sptr dataObserver; + + int ret = tempGenConProImp->NotifyChangeExtProvider(changeInfo); + EXPECT_EQ(ret, -1); + + LOG_INFO("Generalcontroller_ServiceImpl_NotifyChangeExtProvider_Test_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerOpenFileTest_001 +* @tc.desc: Verify OpenFile operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Call OpenFile with empty URI and test mode + 3. Check if returned result is negative +* @tc.expect: + 1. OpenFile operation returns negative value +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerOpenFileTest_001, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerOpenFileTest_001::Start"); + Uri uri(""); + std::shared_ptr tempExtSpeCon = + std::make_shared(nullptr, uri, nullptr); + std::string mode = "test001"; + int result = tempExtSpeCon->OpenFile(uri, mode); + EXPECT_EQ((result < 0), true); + LOG_INFO("ControllerTest_ExtSpecialControllerOpenFileTest_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerOpenFileTest_002 +* @tc.desc: Verify OpenFile operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Call OpenFile with empty URI and test mode + 4. Check if returned result is negative +* @tc.expect: + 1. OpenFile operation returns negative value +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerOpenFileTest_002, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerOpenFileTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempExtSpeCon = + std::make_shared(dataShareConnection, uri, nullptr); + std::string mode = "test001"; + int result = tempExtSpeCon->OpenFile(uri, mode); + EXPECT_EQ((result < 0), true); + LOG_INFO("ControllerTest_ExtSpecialControllerOpenFileTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerOpenFileWithErrCodeTest_001 +* @tc.desc: Verify OpenFileWithErrCode function with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Call OpenFileWithErrCode with empty URI, test mode and error code + 3. Check if returned file descriptor is -1 +* @tc.expect: + 1. OpenFileWithErrCode returns -1 +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerOpenFileWithErrCodeTest_001, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerOpenFileWithErrCodeTest_001::Start"); + Uri uri(""); + std::shared_ptr tempExtSpeCon = + std::make_shared(nullptr, uri, nullptr); + std::string mode = "test001"; + int32_t errCode = 0; + int fd = tempExtSpeCon->OpenFileWithErrCode(uri, mode, errCode); + EXPECT_EQ(fd, -1); + LOG_INFO("ControllerTest_ExtSpecialControllerOpenFileWithErrCodeTest_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerOpenFileWithErrCodeTest_002 +* @tc.desc: Verify OpenFileWithErrCode function with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Call OpenFileWithErrCode with empty URI, test mode and error code + 4. Check if returned file descriptor is -1 +* @tc.expect: + 1. OpenFileWithErrCode returns -1 +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerOpenFileWithErrCodeTest_002, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerOpenFileWithErrCodeTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempExtSpeCon = + std::make_shared(dataShareConnection, uri, nullptr); + std::string mode = "test001"; + int32_t errCode = 0; + int fd = tempExtSpeCon->OpenFileWithErrCode(uri, mode, errCode); + EXPECT_EQ(fd, -1); + LOG_INFO("ControllerTest_ExtSpecialControllerOpenFileWithErrCodeTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerOpenRawFileTest_001 +* @tc.desc: Verify OpenRawFile operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Call OpenRawFile with empty URI and test mode + 3. Check if returned result is negative +* @tc.expect: + 1. OpenRawFile operation returns negative value +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerOpenRawFileTest_001, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerOpenRawFileTest_001::Start"); + Uri uri(""); + std::shared_ptr tempExtSpeCon = + std::make_shared(nullptr, uri, nullptr); + std::string mode = "test001"; + int result = tempExtSpeCon->OpenRawFile(uri, mode); + EXPECT_EQ((result < 0), true); + LOG_INFO("ControllerTest_ExtSpecialControllerOpenRawFileTest_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControlleOpenRawFileTest_002 +* @tc.desc: Verify OpenRawFile operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Call OpenRawFile with empty URI and test mode + 4. Check if returned result is negative +* @tc.expect: + 1. OpenRawFile operation returns negative value +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControlleOpenRawFileTest_002, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerOpenRawFileTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempExtSpeCon = + std::make_shared(dataShareConnection, uri, nullptr); + std::string mode = "test001"; + int result = tempExtSpeCon->OpenRawFile(uri, mode); + EXPECT_EQ((result < 0), true); + LOG_INFO("ControllerTest_ExtSpecialControllerOpenRawFileTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerGetTypeTest_001 +* @tc.desc: Verify GetType operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Call GetType with empty URI + 3. Check if returned result is empty string +* @tc.expect: + 1. GetType operation returns empty string +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerGetTypeTest_001, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerGetTypeTest_001::Start"); + Uri uri(""); + std::shared_ptr tempExtSpeCon = + std::make_shared(nullptr, uri, nullptr); + std::string result = tempExtSpeCon->GetType(uri); + EXPECT_EQ(result, ""); + LOG_INFO("ControllerTest_ExtSpecialControllerGetTypeTest_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControlleGetTypeTest_002 +* @tc.desc: Verify GetType operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Call GetType with empty URI + 4. Check if returned result is empty string +* @tc.expect: + 1. GetType operation returns empty string +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControlleGetTypeTest_002, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerGetTypeTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempExtSpeCon = + std::make_shared(dataShareConnection, uri, nullptr); + std::string result = tempExtSpeCon->GetType(uri); + EXPECT_EQ(result, ""); + LOG_INFO("ControllerTest_ExtSpecialControllerGetTypeTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerBatchInsertTest_001 +* @tc.desc: Verify BatchInsert operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Prepare vector of DataShareValuesBucket with test data + 3. Call BatchInsert with empty URI and values vector + 4. Check if returned result is negative +* @tc.expect: + 1. BatchInsert operation returns negative value +*/ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerBatchInsertTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_ExtSpecialControllerBatchInsertTest_001::Start"); @@ -210,6 +1132,20 @@ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerBatchInsertTest_001, LOG_INFO("ControllerTest_ExtSpecialControllerBatchInsertTest_001::End"); } +/** +* @tc.name: ControllerTest_ExtSpecialControllerBatchInsertTest_002 +* @tc.desc: Verify BatchInsert operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Prepare vector of DataShareValuesBucket with test data + 4. Call BatchInsert with empty URI and values vector + 5. Check if returned result is negative +* @tc.expect: + 1. BatchInsert operation returns negative value +*/ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerBatchInsertTest_002, TestSize.Level0) { LOG_INFO("ControllerTest_ExtSpecialControllerBatchInsertTest_002::Start"); @@ -236,6 +1172,256 @@ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerBatchInsertTest_002, LOG_INFO("ControllerTest_ExtSpecialControllerBatchInsertTest_002::End"); } +/** +* @tc.name: ControllerTest_ExtSpecialControllerBatchUpdateTest_001 +* @tc.desc: Verify BatchUpdate operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Prepare empty UpdateOperations and results vector + 3. Call BatchUpdate with operations and results + 4. Check if returned result is -1 +* @tc.expect: + 1. BatchUpdate operation returns -1 +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerBatchUpdateTest_001, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerBatchUpdateTest_001::Start"); + Uri uri(""); + std::shared_ptr tempExtSpeCon = + std::make_shared(nullptr, uri, nullptr); + DataShare::UpdateOperations operations; + std::vector results; + int result = tempExtSpeCon->BatchUpdate(operations, results); + EXPECT_EQ(result, -1); + LOG_INFO("ControllerTest_ExtSpecialControllerBatchUpdateTest_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerBatchUpdateTest_002 +* @tc.desc: Verify BatchUpdate operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Prepare empty UpdateOperations and results vector + 4. Call BatchUpdate with operations and results + 5. Check if returned result is -1 +* @tc.expect: + 1. BatchUpdate operation returns -1 +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerBatchUpdateTest_002, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerBatchUpdateTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempExtSpeCon = + std::make_shared(dataShareConnection, uri, nullptr); + DataShare::UpdateOperations operations; + std::vector results; + int result = tempExtSpeCon->BatchUpdate(operations, results); + EXPECT_EQ(result, -1); + LOG_INFO("ControllerTest_ExtSpecialControllerBatchUpdateTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerInsertExtTest_001 +* @tc.desc: Verify InsertExt operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Prepare DataShareValuesBucket with test data and result string + 3. Call InsertExt with empty URI, values bucket and result string + 4. Check if returned result is -1 +* @tc.expect: + 1. InsertExt operation returns -1 +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerInsertExtTest_001, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerInsertExtTest_001::Start"); + Uri uri(""); + std::shared_ptr tempExtSpeCon = + std::make_shared(nullptr, uri, nullptr); + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put("name", "dataShareTest006"); + valuesBucket.Put("phoneNumber", 20.6); + std::string result1 = "test001"; + int result = tempExtSpeCon->InsertExt(uri, valuesBucket, result1); + EXPECT_EQ(result, -1); + LOG_INFO("ControllerTest_ExtSpecialControllerInsertExtTest_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerInsertExtTest_002 +* @tc.desc: Verify InsertExt operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Prepare DataShareValuesBucket with test data and result string + 4. Call InsertExt with empty URI, values bucket and result string + 5. Check if returned result is -1 +* @tc.expect: + 1. InsertExt operation returns -1 +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerInsertExtTest_002, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerInsertExtTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempExtSpeCon = + std::make_shared(dataShareConnection, uri, nullptr); + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put("name", "dataShareTest006"); + valuesBucket.Put("phoneNumber", 20.6); + std::string result1 = "test001"; + int result = tempExtSpeCon->InsertExt(uri, valuesBucket, result1); + EXPECT_EQ(result, -1); + LOG_INFO("ControllerTest_ExtSpecialControllerInsertExtTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerExecuteBatchTest_001 +* @tc.desc: Verify ExecuteBatch operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Prepare empty OperationStatement vector and ExecResultSet + 3. Call ExecuteBatch with statements and result set + 4. Check if returned result is -1 +* @tc.expect: + 1. ExecuteBatch operation returns -1 +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerExecuteBatchTest_001, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerExecuteBatchTest_001::Start"); + Uri uri(""); + std::shared_ptr tempExtSpeCon = + std::make_shared(nullptr, uri, nullptr); + std::vector statements; + std::vector results; + ExecResultSet result1; + int result = tempExtSpeCon->ExecuteBatch(statements, result1); + EXPECT_EQ(result, -1); + LOG_INFO("ControllerTest_ExtSpecialControllerExecuteBatchTest_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerExecuteBatchTest_002 +* @tc.desc: Verify ExecuteBatch operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Prepare empty OperationStatement vector and ExecResultSet + 4. Call ExecuteBatch with statements and result set + 5. Check if returned result is -1 +* @tc.expect: + 1. ExecuteBatch operation returns -1 +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerExecuteBatchTest_002, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerExecuteBatchTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempExtSpeCon = + std::make_shared(dataShareConnection, uri, nullptr); + std::vector statements; + std::vector results; + ExecResultSet result1; + int result = tempExtSpeCon->ExecuteBatch(statements, result1); + EXPECT_EQ(result, -1); + LOG_INFO("ControllerTest_ExtSpecialControllerExecuteBatchTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerGetFileTypesTest_001 +* @tc.desc: Verify GetFileTypes operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Call GetFileTypes with empty URI and test type string + 3. Check if returned result is empty vector +* @tc.expect: + 1. GetFileTypes operation returns empty vector +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerGetFileTypesTest_001, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerGetFileTypesTest_001::Start"); + Uri uri(""); + std::shared_ptr tempExtSpeCon = + std::make_shared(nullptr, uri, nullptr); + std::string getFileTypes = "test001"; + std::vector result = tempExtSpeCon->GetFileTypes(uri, getFileTypes); + EXPECT_EQ(result, std::vector()); + LOG_INFO("ControllerTest_ExtSpecialControllerGetFileTypesTest_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControlleGetFileTypesTest_002 +* @tc.desc: Verify GetFileTypes operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Call GetFileTypes with empty URI and test type string + 4. Check if returned result is empty vector +* @tc.expect: + 1. GetFileTypes operation returns empty vector +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControlleGetFileTypesTest_002, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerGetFileTypesTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempExtSpeCon = + std::make_shared(dataShareConnection, uri, nullptr); + std::string getFileTypes = "test001"; + std::vector result = tempExtSpeCon->GetFileTypes(uri, getFileTypes); + EXPECT_EQ(result, std::vector()); + LOG_INFO("ControllerTest_ExtSpecialControllerGetFileTypesTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerNormalizeUriTest_001 +* @tc.desc: Verify NormalizeUri operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Call NormalizeUri with empty URI + 3. Check if returned result is empty URI +* @tc.expect: + 1. NormalizeUri operation returns empty URI +*/ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerNormalizeUriTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_ExtSpecialControllerNormalizeUriTest_001::Start"); @@ -247,6 +1433,19 @@ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerNormalizeUriTest_001 LOG_INFO("ControllerTest_ExtSpecialControllerNormalizeUriTest_001::End"); } +/** +* @tc.name: ControllerTest_ExtSpecialControllerNormalizeUriTest_002 +* @tc.desc: Verify NormalizeUri operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Call NormalizeUri with empty URI + 4. Check if returned result is empty URI +* @tc.expect: + 1. NormalizeUri operation returns empty URI +*/ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerNormalizeUriTest_002, TestSize.Level0) { LOG_INFO("ControllerTest_ExtSpecialControllerNormalizeUriTest_002::Start"); @@ -264,6 +1463,18 @@ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerNormalizeUriTest_002 LOG_INFO("ControllerTest_ExtSpecialControllerNormalizeUriTest_002::End"); } +/** +* @tc.name: ControllerTest_ExtSpecialControllerDenormalizeUriTest_001 +* @tc.desc: Verify DenormalizeUri operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Call DenormalizeUri with empty URI + 3. Check if returned result is empty URI +* @tc.expect: + 1. DenormalizeUri operation returns empty URI +*/ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerDenormalizeUriTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_ExtSpecialControllerDenormalizeUriTest_001::Start"); @@ -275,6 +1486,19 @@ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerDenormalizeUriTest_0 LOG_INFO("ControllerTest_ExtSpecialControllerDenormalizeUriTest_001::End"); } +/** +* @tc.name: ControllerTest_ExtSpecialControllerDenormalizeUriTest_002 +* @tc.desc: Verify DenormalizeUri operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Call DenormalizeUri with empty URI + 4. Check if returned result is empty URI +* @tc.expect: + 1. DenormalizeUri operation returns empty URI +*/ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerDenormalizeUriTest_002, TestSize.Level0) { LOG_INFO("ControllerTest_ExtSpecialControllerDenormalizeUriTest_002::Start"); diff --git a/data_share/test/native/unittest/mediadatashare_test/src/datashare_block_writer_impl_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/datashare_block_writer_impl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3b206690bd2c323aa1f645e2fa473045a431d93e --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/datashare_block_writer_impl_test.cpp @@ -0,0 +1,193 @@ +/* +* Copyright (C) 2025 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 + +#include "datashare_block_writer_impl.h" +#include "datashare_log.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +class DataShareBlockWriterImplTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +/** +* @tc.name: AllocRowTest001 +* @tc.desc: test AllocRow function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call AllocRow function and check the result +* @tc.experct: AllocRow failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, AllocRowTest001, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest AllocRowTest001::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + auto result = dataShareBlockWriterImpl.AllocRow(); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest AllocRowTest001::End"); +} + +/** +* @tc.name: WriteTest001 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest001, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest001::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + auto result = dataShareBlockWriterImpl.Write(column); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest001::End"); +} + +/** +* @tc.name: WriteTest002 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest002, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest002::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + int64_t value = 1; + auto result = dataShareBlockWriterImpl.Write(column, value); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest002::End"); +} + +/** +* @tc.name: WriteTest003 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest003, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest003::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + double value = 1; + auto result = dataShareBlockWriterImpl.Write(column, value); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest003::End"); +} + +/** +* @tc.name: WriteTest004 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest004, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest004::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + uint8_t value[3] = {1}; + size_t size = 1; + auto result = dataShareBlockWriterImpl.Write(column, value, size); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest004::End"); +} + +/** +* @tc.name: WriteTest005 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest005, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest005::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + const char* value = "test"; + size_t sizeIncludingNull = 1; + auto result = dataShareBlockWriterImpl.Write(column, value, sizeIncludingNull); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest005::End"); +} + +/** +* @tc.name: GetCurrentRowIndexTest001 +* @tc.desc: test GetCurrentRowIndex function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call GetCurrentRowIndex function and check the result +* @tc.experct: GetCurrentRowIndex failed and reutrn false +*/ +HWTEST_F(DataShareBlockWriterImplTest, GetCurrentRowIndexTest001, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest GetCurrentRowIndexTest001::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t rowIndex = 1; + auto result = dataShareBlockWriterImpl.GetCurrentRowIndex(rowIndex); + EXPECT_EQ(result, false); + LOG_INFO("DataShareBlockWriterImplTest GetCurrentRowIndexTest001::End"); +} + +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/datashare_common_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/datashare_common_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eed7d3aa6231d23386f8c972ce68dd78134ca9a3 --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/datashare_common_test.cpp @@ -0,0 +1,725 @@ +/* + * Copyright (C) 2025 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 +#include + +#include "datashare_errno.h" +#include "datashare_itypes_utils.h" +#include "datashare_log.h" +#include "datashare_abs_result_set.h" +#include "datashare_result_set.h" +#include "ikvstore_data_service.h" +#include "ipc_types.h" +#include "ishared_result_set_stub.h" +#include "itypes_util.h" +#include "message_parcel.h" +#include "gmock/gmock.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +class DataShareCommonTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +class ResultSetBridgeTest : public OHOS::DataShare::ResultSetBridge { +public: + int GetAllColumnNames(std::vector &columnNames) override + { + return 0; + } + + int GetRowCount(int32_t &count) override + { + return 0; + } + + int OnGo(int32_t startRowIndex, int32_t targetRowIndex, Writer &writer) override + { + return 0; + } +}; + +class MockDataShareAbsResultSet : public DataShareAbsResultSet { +public: + MOCK_METHOD1(GoToRow, int(int)); + MOCK_METHOD1(GetRowCount, int(int &)); + MOCK_METHOD1(GetAllColumnNames, int(std::vector &)); + MOCK_METHOD1(GetColumnCount, int(int &)); +}; + +class MockDataShareAbsResultSet2 : public DataShareAbsResultSet { +public: + MOCK_METHOD1(GetAllColumnNames, int(std::vector &)); +}; + +/** +* @tc.name: CreateStubTestTest001 +* @tc.desc: test CreateStub function when resuletset_ = nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and resuletset_ = nullptr + 2.call CreateStub function and check the result +* @tc.experct: CreateStub failed and reutrn nullptr +*/ +HWTEST_F(DataShareCommonTest, CreateStubTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest CreateStubTest001::Start"); + std::shared_ptr resultset; + MessageParcel parcel; + ISharedResultSetStub stub(resultset); + auto result = stub.CreateStub(resultset, parcel); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareCommonTest CreateStubTest001::End"); +} + +/** +* @tc.name: CreateStubTestTest002 +* @tc.desc: test CreateStub function when resuletset_ is not nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and resuletset_ is not nullptr + 2.call CreateStub function and check the result +* @tc.experct: CreateStub succees and not reutrn nullptr +*/ +HWTEST_F(DataShareCommonTest, CreateStubTestTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest CreateStubTestTest002::Start"); + std::shared_ptr resultset = std::make_shared(); + MessageParcel parcel; + ISharedResultSetStub stub(resultset); + auto result = stub.CreateStub(resultset, parcel); + EXPECT_NE(result, nullptr); + LOG_INFO("DataShareCommonTest CreateStubTestTest002::End"); +} + +/** +* @tc.name: OnRemoteRequestTest001 +* @tc.desc: test OnRemoteRequest function when resuletset_ = nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and resuletset_ = nullptr + 2.call OnRemoteRequest function and check the result +* @tc.experct: OnRemoteRequest failed and reutrn INVALID_FD +*/ +HWTEST_F(DataShareCommonTest, OnRemoteRequestTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest OnRemoteRequestTest001::Start"); + std::shared_ptr resultset; + ISharedResultSetStub stub(resultset); + uint32_t code = 0; + MessageParcel data; + MessageParcel parcel; + MessageOption option; + auto result = stub.OnRemoteRequest(code, data, parcel, option); + EXPECT_EQ(result, INVALID_FD); + LOG_INFO("DataShareCommonTest OnRemoteRequestTest001::End"); +} + +/** +* @tc.name: HandleGetRowCountRequestTest001 +* @tc.desc: test HandleGetRowCountRequest function when bridge = nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is nullptr + 2.call HandleGetRowCountRequest function and check the result +* @tc.experct: HandleGetRowCountRequest success and write E_ERROR into reply +*/ +HWTEST_F(DataShareCommonTest, HandleGetRowCountRequestTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest HandleGetRowCountRequestTest001::Start"); + std::shared_ptr resultset = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleGetRowCountRequest(data, reply); + EXPECT_EQ(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("DataShareCommonTest HandleGetRowCountRequestTest001::End"); +} + +/** +* @tc.name: HandleGetRowCountRequestTest002 +* @tc.desc: test HandleGetRowCountRequest function when bridge is not nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is not nullptr + 2.call HandleGetRowCountRequest function and check the result +* @tc.experct: HandleGetRowCountRequest success and write count into reply +*/ +HWTEST_F(DataShareCommonTest, HandleGetRowCountRequestTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest HandleGetRowCountRequestTest002::Start"); + std::shared_ptr resultset = std::make_shared(); + resultset->bridge_ = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleGetRowCountRequest(data, reply); + EXPECT_NE(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("DataShareCommonTest HandleGetRowCountRequestTest002::End"); +} + +/** +* @tc.name: HandleGetAllColumnNamesRequestTest001 +* @tc.desc: test HandleGetAllColumnNamesRequest function when bridge is nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is nullptr + 2.call HandleGetAllColumnNamesRequest function and check the result +* @tc.experct: HandleGetAllColumnNamesRequest success and write E_ERROR into reply +*/ +HWTEST_F(DataShareCommonTest, HandleGetAllColumnNamesRequestTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest HandleGetAllColumnNamesRequestTest001::Start"); + std::shared_ptr resultset = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleGetAllColumnNamesRequest(data, reply); + EXPECT_EQ(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("DataShareCommonTest HandleGetAllColumnNamesRequestTest001::End"); +} + +/** +* @tc.name: HandleGetAllColumnNamesRequestTest002 +* @tc.desc: test HandleGetAllColumnNamesRequest function when bridge is not nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is not nullptr + 2.call HandleGetAllColumnNamesRequest function and check the result +* @tc.experct: HandleGetAllColumnNamesRequest success and write count into reply +*/ +HWTEST_F(DataShareCommonTest, HandleGetAllColumnNamesRequestTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest HandleGetAllColumnNamesRequestTest002::Start"); + std::shared_ptr resultset = std::make_shared(); + resultset->bridge_ = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleGetAllColumnNamesRequest(data, reply); + EXPECT_NE(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("DataShareCommonTest HandleGetAllColumnNamesRequestTest002::End"); +} + +/** +* @tc.name: HandleOnGoRequestTest001 +* @tc.desc: test HandleOnGoRequest function when bridge is nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is nullptr + 2.call HandleOnGoRequest function and check the result +* @tc.experct: HandleOnGoRequest success and write -1 into reply +*/ +HWTEST_F(DataShareCommonTest, HandleOnGoRequestTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest HandleOnGoRequestTest001::Start"); + std::shared_ptr resultset = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleOnGoRequest(data, reply); + EXPECT_EQ(reply.ReadInt32(), -1); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("DataShareCommonTest HandleOnGoRequestTest001::End"); +} + +/** +* @tc.name: HandleOnGoRequestTest002 +* @tc.desc: test HandleOnGoRequest function when bridge is not nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is not nullptr + 2.call HandleOnGoRequest function and check the result +* @tc.experct: HandleOnGoRequest success and write count into reply +*/ +HWTEST_F(DataShareCommonTest, HandleOnGoRequestTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest HandleOnGoRequestTest002::Start"); + std::shared_ptr resultset = std::make_shared(); + resultset->bridge_ = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleOnGoRequest(data, reply); + EXPECT_NE(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("DataShareCommonTest HandleOnGoRequestTest002::End"); +} + +/** +* @tc.name: GetDataTypeTest001 +* @tc.desc: test GetDataType function when sharedBlock_ is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object and sharedBlock_ is nullptr + 2.call GetDataType function and check the result +* @tc.experct: GetDataType failed and return E_ERROR +*/ +HWTEST_F(DataShareCommonTest, GetDataTypeTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest GetDataTypeTest001::Start"); + DataShareResultSet dataShareResultSet; + int columnIndex = 1; + DataShare::DataType dataType; + auto result = dataShareResultSet.GetDataType(columnIndex, dataType); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareCommonTest GetDataTypeTest001::End"); +} + +/** +* @tc.name: CheckStateTest001 +* @tc.desc: test CheckState function when columnIndex >= 0 +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object + 2.call CheckState function when columnIndex >= 0 and check the result +* @tc.experct: CheckState failed and return E_INVALID_COLUMN_INDEX +*/ +HWTEST_F(DataShareCommonTest, CheckStateTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest CheckStateTest001::Start"); + DataShareResultSet dataShareResultSet; + int columnIndex = 1; + auto result = dataShareResultSet.CheckState(columnIndex); + EXPECT_EQ(result, E_INVALID_COLUMN_INDEX); + LOG_INFO("DataShareCommonTest CheckStateTest001::End"); +} + +/** +* @tc.name: CheckStateTest002 +* @tc.desc: test CheckState function when columnIndex < 0 +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object + 2.call CheckState function when columnIndex < 0 and check the result +* @tc.experct: CheckState failed and return E_INVALID_COLUMN_INDEX +*/ +HWTEST_F(DataShareCommonTest, CheckStateTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest CheckState002::Start"); + DataShareResultSet dataShareResultSet; + int columnIndex = -1; + auto result = dataShareResultSet.CheckState(columnIndex); + EXPECT_EQ(result, E_INVALID_COLUMN_INDEX); + LOG_INFO("DataShareCommonTest CheckState002::End"); +} + +/** +* @tc.name: MarshalTest001 +* @tc.desc: test Marshal function when resultset = nullptr +* @tc.type: FUNC +* @tc.require: issueICCAXH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object when resultset = nullptr + 2.call Marshal function and check the result +* @tc.experct: Marshal failed and return false +*/ +HWTEST_F(DataShareCommonTest, MarshalTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest MarshalTest001::Start"); + DataShareResultSet dataShareResultSet; + std::shared_ptr resultset = nullptr; + MessageParcel parcel; + auto result = dataShareResultSet.Marshal(resultset, parcel); + EXPECT_FALSE(result); + LOG_INFO("DataShareCommonTest MarshalTest001::End"); +} + +/** +* @tc.name: UnmarshalTest001 +* @tc.desc: test Unmarshal function +* @tc.type: FUNC +* @tc.require: issueICCAXH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object + 2.call Unmarshal function and check the result +* @tc.experct: Unmarshal failed and return nullptr +*/ +HWTEST_F(DataShareCommonTest, UnmarshalTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest UnmarshalTest001::Start"); + DataShareResultSet dataShareResultSet; + MessageParcel parcel; + auto result = dataShareResultSet.Unmarshal(parcel); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareCommonTest UnmarshalTest001::End"); +} + +/** +* @tc.name: UnmarshallingTest001 +* @tc.desc: test Unmarshalling function when parcel is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a ITypesUtil object and parcel is nullptr + 2.call Unmarshalling function and check the result +* @tc.experct: Unmarshalling failed and return false +*/ +HWTEST_F(DataShareCommonTest, UnmarshallingTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest UnmarshallingTest001::Start"); + ITypesUtil::Predicates predicates; + MessageParcel parcel; + auto result = ITypesUtil::Unmarshalling(predicates, parcel); + EXPECT_FALSE(result); + LOG_INFO("DataShareCommonTest UnmarshallingTest001::End"); +} + +/** +* @tc.name: UnmarshallingTest002 +* @tc.desc: test Unmarshalling function when parcel is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a ITypesUtil object and parcel is nullptr + 2.call Unmarshalling function and check the result +* @tc.experct: Unmarshalling failed and return false +*/ +HWTEST_F(DataShareCommonTest, UnmarshallingTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest UnmarshallingTest002::Start"); + OperationStatement operationStatement; + MessageParcel parcel; + auto result = ITypesUtil::Unmarshalling(operationStatement, parcel); + EXPECT_FALSE(result); + LOG_INFO("DataShareCommonTest UnmarshallingTest002::End"); +} + +/** +* @tc.name: UnmarshallingTest003 +* @tc.desc: test Unmarshalling function when parcel is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a ITypesUtil object and parcel is nullptr + 2.call Unmarshalling function and check the result +* @tc.experct: Unmarshalling failed and return false +*/ +HWTEST_F(DataShareCommonTest, UnmarshallingTest003, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest UnmarshallingTest003::Start"); + ExecResult execResult; + MessageParcel parcel; + auto result = ITypesUtil::Unmarshalling(execResult, parcel); + EXPECT_FALSE(result); + LOG_INFO("DataShareCommonTest UnmarshallingTest003::End"); +} + +/** +* @tc.name: UnmarshallingTest004 +* @tc.desc: test Unmarshalling function when parcel is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a ITypesUtil object and parcel is nullptr + 2.call Unmarshalling function and check the result +* @tc.experct: Unmarshalling failed and return false +*/ +HWTEST_F(DataShareCommonTest, UnmarshallingTest004, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest UnmarshallingTest004::Start"); + ExecResultSet execResultSet; + MessageParcel parcel; + auto result = ITypesUtil::Unmarshalling(execResultSet, parcel); + EXPECT_FALSE(result); + LOG_INFO("DataShareCommonTest UnmarshallingTest004::End"); +} + +/** +* @tc.name: MarshallingTest001 +* @tc.desc: test Marshalling function when parcel is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a ITypesUtil object and parcel is nullptr + 2.call Marshalling function and check the result +* @tc.experct: Marshalling success and return ture +*/ +HWTEST_F(DataShareCommonTest, MarshallingTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest MarshallingTest001::Start"); + ITypesUtil::RdbChangeNode changeNode; + MessageParcel parcel; + auto result = ITypesUtil::Marshalling(changeNode, parcel); + EXPECT_TRUE(result); + LOG_INFO("DataShareCommonTest MarshallingTest001::End"); +} + +/** +* @tc.name: MarshallingTest002 +* @tc.desc: test Marshalling function when sharedBlock_ is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object + 2.call Marshalling function when sharedBlock_ is nullptr and check the result +* @tc.experct: Marshalling failed and return false +*/ +HWTEST_F(DataShareCommonTest, MarshallingTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest MarshallingTest002::Start"); + DataShareResultSet dataShareResultSet; + MessageParcel parcel; + auto result = dataShareResultSet.Marshalling(parcel); + EXPECT_FALSE(result); + LOG_INFO("DataShareCommonTest MarshallingTest002::End"); +} + +/** +* @tc.name: GoToTest001 +* @tc.desc: test GoTo function when GoToRow return E_ERROR +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GoTo function when GoToRow return E_ERROR and check the result +* @tc.experct: GoTo failed and return E_ERROR +*/ +HWTEST_F(DataShareCommonTest, GoToTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest GoToTest001::Start"); + MockDataShareAbsResultSet mockResultSet; + int offset = 1; + EXPECT_CALL(mockResultSet, GoToRow(testing::_)) + .WillOnce(testing::Return(E_ERROR)); + auto result = mockResultSet.GoTo(offset); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareCommonTest GoToTest001::End"); +} + +/** +* @tc.name: GoToTest002 +* @tc.desc: test GoTo function +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GoTo function and check the result +* @tc.experct: GoTo success and return E_OK +*/ +HWTEST_F(DataShareCommonTest, GoToTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest GoToTest002::Start"); + DataShareAbsResultSet dataShareAbsResultSet; + int offset = 1; + auto result = dataShareAbsResultSet.GoTo(offset); + EXPECT_EQ(result, E_OK); + LOG_INFO("DataShareCommonTest GoToTest002::End"); +} + +/** +* @tc.name: IsEndedTest001 +* @tc.desc: test IsEnded function when GetRowCount return E_ERROR +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call IsEnded function when GetRowCount return E_ERROR and check the result +* @tc.experct: IsEnded failed and return E_ERROR +*/ +HWTEST_F(DataShareCommonTest, IsEndedTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest IsEndedTest001::Start"); + MockDataShareAbsResultSet mockResultSet; + EXPECT_CALL(mockResultSet, GetRowCount(testing::_)) + .WillOnce(testing::Return(E_ERROR)); + bool test = true; + auto result = mockResultSet.IsEnded(test); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareCommonTest IsEndedTest001::End"); +} + +/** +* @tc.name: IsEndedTest002 +* @tc.desc: test IsEnded function +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call IsEnded function and check the result +* @tc.experct: IsEnded success and return E_OK +*/ +HWTEST_F(DataShareCommonTest, IsEndedTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest IsEndedTest002::Start"); + DataShareAbsResultSet dataShareAbsResultSet; + bool test = true; + auto result = dataShareAbsResultSet.IsEnded(test); + EXPECT_EQ(result, E_OK); + LOG_INFO("DataShareCommonTest IsEndedTest002::End"); +} + +/** +* @tc.name: GetColumnCountTest001 +* @tc.desc: test GetColumnCount function when GetAllColumnNames return E_ERROR +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet2 object + 2.call GetColumnCount function when GetAllColumnNames return E_ERROR and check the result +* @tc.experct: GetColumnCount failed and return E_ERROR +*/ +HWTEST_F(DataShareCommonTest, GetColumnCountTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest GetColumnCountTest001::Start"); + MockDataShareAbsResultSet2 mockResultSet; + int offset = -1; + mockResultSet.count_ = -1; + EXPECT_CALL(mockResultSet, GetAllColumnNames(testing::_)) + .WillOnce(testing::Return(E_ERROR)); + auto result = mockResultSet.GetColumnCount(offset); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareCommonTest GetColumnCountTest001::End"); +} + +/** +* @tc.name: GetColumnName001 +* @tc.desc: test GetColumnName function when GetColumnCount return E_ERROR +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GetColumnName function when GetColumnCount return E_ERROR and check the result +* @tc.experct: GetColumnName failed and return E_ERROR +*/ +HWTEST_F(DataShareCommonTest, GetColumnName001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest GetColumnName001::Start"); + MockDataShareAbsResultSet mockResultSet; + int columnIndex = 1; + std::string columnName = "test"; + EXPECT_CALL(mockResultSet, GetColumnCount(testing::_)) + .WillOnce(testing::Return(E_ERROR)); + auto result = mockResultSet.GetColumnName(columnIndex, columnName); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareCommonTest GetColumnName001::End"); +} + +/** +* @tc.name: GetColumnName002 +* @tc.desc: test GetColumnName function when columnIndex >= 0 +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GetColumnName function when columnIndex >= 0 and check the result +* @tc.experct: GetColumnName failed and return E_INVALID_COLUMN_INDEX +*/ +HWTEST_F(DataShareCommonTest, GetColumnName002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest MarshallingTest002::Start"); + DataShareAbsResultSet dataShareAbsResultSet; + int columnIndex = 1; + std::string columnName = "test"; + auto result = dataShareAbsResultSet.GetColumnName(columnIndex, columnName); + EXPECT_EQ(result, E_INVALID_COLUMN_INDEX); + LOG_INFO("DataShareCommonTest MarshallingTest002::End"); +} + +/** +* @tc.name: GetColumnName003 +* @tc.desc: test GetColumnName function when columnIndex < 0 +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GetColumnName function when columnIndex < 0 and check the result +* @tc.experct: GetColumnName failed and return E_INVALID_COLUMN_INDEX +*/ +HWTEST_F(DataShareCommonTest, GetColumnName003, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest MarshallingTest002::Start"); + DataShareAbsResultSet dataShareAbsResultSet; + int columnIndex = -1; + std::string columnName = "test"; + auto result = dataShareAbsResultSet.GetColumnName(columnIndex, columnName); + EXPECT_EQ(result, E_INVALID_COLUMN_INDEX); + LOG_INFO("DataShareCommonTest MarshallingTest002::End"); +} + +/** +* @tc.name: RegisterClientDeathObserver001 +* @tc.desc: test RegisterClientDeathObserver function when observer = nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object when observer = nullptr + 2.call RegisterClientDeathObserver function and check the result +* @tc.experct: RegisterClientDeathObserver failed and return -1 +*/ +HWTEST_F(DataShareCommonTest, RegisterClientDeathObserver001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest RegisterClientDeathObserver001::Start"); + sptr observer = nullptr; + std::string appId = "testAppid"; + DataShareKvServiceProxy dataShareKvServiceProxy(observer); + auto result = dataShareKvServiceProxy.RegisterClientDeathObserver(appId, observer); + EXPECT_EQ(result, -1); + LOG_INFO("DataShareCommonTest RegisterClientDeathObserver001::End"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/datashare_connection_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/datashare_connection_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a3b19c11ba75764e24957f6d6c5c0a13f1dd1ce0 --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/datashare_connection_test.cpp @@ -0,0 +1,345 @@ +/* + * Copyright (C) 2025 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 "datashare_connection.h" + +#include + +#include "accesstoken_kit.h" +#include "data_ability_observer_interface.h" +#include "datashare_errno.h" +#include "datashare_helper.h" +#include "datashare_log.h" +#include "datashare_proxy.h" +#include "extension_manager_proxy.h" +#include "general_controller.h" +#include "general_controller_provider_impl.h" +#include "general_controller_service_impl.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::AAFwk; +class DataShareConnectionTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + bool UrisEqual(std::list uri1, std::list uri2) + { + if (uri1.size() != uri2.size()) { + return false; + } + auto cmp = [](const Uri &first, const Uri &second) { + return first.ToString() < second.ToString(); + }; + uri1.sort(cmp); + uri2.sort(cmp); + auto it1 = uri1.begin(); + auto it2 = uri2.begin(); + for (; it1 != uri1.end() && it2 != uri2.end(); it1++, it2++) { + if (!it1->Equals(*it2)) { + return false; + } + } + return true; + } +}; + +class RemoteObjectTest : public IRemoteObject { +public: + explicit RemoteObjectTest(std::u16string descriptor) : IRemoteObject(descriptor) {} + ~RemoteObjectTest() {} + + int32_t GetObjectRefCount() + { + return 0; + } + int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + return 0; + } + bool AddDeathRecipient(const sptr &recipient) + { + return true; + } + bool RemoveDeathRecipient(const sptr &recipient) + { + return true; + } + int Dump(int fd, const std::vector &args) + { + return 0; + } +}; + +class IDataAbilityObserverTest : public DataAbilityObserverStub { +public: + explicit IDataAbilityObserverTest(std::string uri) {uri_ = uri;} + ~IDataAbilityObserverTest() + {} + + void OnChange() + { + GTEST_LOG_(INFO) << "OnChange enter"; + } + std::string uri_; +}; + +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::string DATA_SHARE_URI1 = "datashare:///com.acts.datasharetest1"; + +void DataShareConnectionTest::SetUpTestCase(void) {} +void DataShareConnectionTest::TearDownTestCase(void) {} +void DataShareConnectionTest::SetUp(void) {} +void DataShareConnectionTest::TearDown(void) {} + +/** +* @tc.name: DataShareConnection_UpdateObserverExtsProviderMap_Test_001 +* @tc.desc: Verify normal functionality of UpdateObserverExtsProviderMap method +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with test URI and token + 2. Verify observer map is initially empty + 3. Add two observers with different URIs using UpdateObserverExtsProviderMap + 4. Check that observer map size is correctly updated +* @tc.expect: + 1. Observer map is empty initially + 2. After adding observers, map size becomes 2 +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_UpdateObserverExtsProviderMap_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareConnection_UpdateObserverExtsProviderMap_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // insert data + EXPECT_TRUE(connection->observerExtsProvider_.Empty()); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI); + ASSERT_NE(dataObserver, nullptr); + connection->UpdateObserverExtsProviderMap(uri, dataObserver, true); + + Uri uri1(DATA_SHARE_URI1); + sptr dataObserver1 = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI1); + ASSERT_NE(dataObserver1, nullptr); + connection->UpdateObserverExtsProviderMap(uri1, dataObserver1, true); + + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 2); + connection = nullptr; + + LOG_INFO("DataShareConnection_UpdateObserverExtsProviderMap_Test_001::End"); +} + +/** +* @tc.name: DataShareConnection_DeleteObserverExtsProviderMap_001 +* @tc.desc: Verify DeleteObserverExtsProviderMap functionality for removing observers +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection and add two observers + 2. Verify initial map size is 2 + 3. Delete one valid observer and check map size + 4. Attempt to delete an invalid observer and check map size remains unchanged +* @tc.expect: + 1. After first deletion, map size is 1 + 2. After second deletion attempt, map size remains 1 +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_DeleteObserverExtsProviderMap_001, TestSize.Level0) +{ + LOG_INFO("DataShareConnection_DeleteObserverExtsProviderMap_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // insert data + EXPECT_TRUE(connection->observerExtsProvider_.Empty()); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI); + connection->UpdateObserverExtsProviderMap(uri, dataObserver, true); + + Uri uri1(DATA_SHARE_URI1); + sptr dataObserver1 = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI1); + connection->UpdateObserverExtsProviderMap(uri1, dataObserver1, true); + + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 2); + + // delete data that uri can match observer + connection->DeleteObserverExtsProviderMap(uri1, dataObserver1); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 1); + + // delete data that uri can not match observer + connection->DeleteObserverExtsProviderMap(uri1, dataObserver); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 1); + connection = nullptr; + + LOG_INFO("DataShareConnection_DeleteObserverExtsProviderMap_001::End"); +} + +/** +* @tc.name: DataShareConnection_ReRegisterObserverExtProvider_Test_001 +* @tc.desc: Verify ReRegisterObserverExtProvider can re-register existing observers +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with valid proxy + 2. Add two observers to the map + 3. Call ReRegisterObserverExtProvider method + 4. Verify observer map remains populated after re-registration +* @tc.expect: + 1. Observer map remains non-empty after re-registration +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_ReRegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareConnection_ReRegisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + connection->dataShareProxy_ = tokenProxy; + + // insert data + EXPECT_TRUE(connection->observerExtsProvider_.Empty()); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI); + connection->UpdateObserverExtsProviderMap(uri, dataObserver, true); + + Uri uri1(DATA_SHARE_URI1); + sptr dataObserver1 = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI1); + connection->UpdateObserverExtsProviderMap(uri1, dataObserver1, true); + + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 2); + + // test ReRegister func + connection->ReRegisterObserverExtProvider(); + // reRegister success, update observer map + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + connection = nullptr; + + LOG_INFO("DataShareConnection_ReRegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareConnection_OnAbilityConnectDone_Test_001 +* @tc.desc: Verify OnAbilityConnectDone handles reconnection and observer reregistration +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with valid proxy and observers + 2. Set isReconnect_ flag to true + 3. Call OnAbilityConnectDone with test parameters + 4. Verify observer map remains intact after connection +* @tc.expect: + 1. Observer map remains non-empty after connection completes +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_OnAbilityConnectDone_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareConnection_OnAbilityConnectDone_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + connection->dataShareProxy_ = tokenProxy; + + // insert data + EXPECT_TRUE(connection->observerExtsProvider_.Empty()); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI); + connection->UpdateObserverExtsProviderMap(uri, dataObserver, true); + + Uri uri1(DATA_SHARE_URI1); + sptr dataObserver1 = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI1); + connection->UpdateObserverExtsProviderMap(uri1, dataObserver1, true); + + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 2); + + // test ReRegister func + connection->isReconnect_.store(true); + std::string deviceId = "deviceId"; + std::string bundleName = "bundleName"; + std::string abilityName = "abilityName"; + AppExecFwk::ElementName element(deviceId, bundleName, abilityName); + int resultCode = 0; + connection->OnAbilityConnectDone(element, token, resultCode); + + // reRegister success, update observer map + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + connection = nullptr; + + LOG_INFO("DataShareConnection_OnAbilityConnectDone_Test_001::End"); +} + +/** +* @tc.name: DataShareConnection_OnAbilityDisconnectDone_Test_001 +* @tc.desc: Verify thread name is correctly set after disconnection +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection and set isReconnect_ to true + 2. Call OnAbilityDisconnectDone with test parameters + 3. Check that the thread name in the connection pool is correct +* @tc.expect: + 1. Thread name is set to "DShare_Connect" +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_OnAbilityDisconnectDone_Test_001, TestSize.Level1) +{ + LOG_INFO("DataShareConnection_OnAbilityDisconnectDone_Test_001::Start"); + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + + connection->isReconnect_.store(true); + std::string deviceId = "deviceId"; + std::string bundleName = "bundleName"; + std::string abilityName = "abilityName"; + AppExecFwk::ElementName element(deviceId, bundleName, abilityName); + int resultCode = 0; + connection->OnAbilityDisconnectDone(element, resultCode); + EXPECT_EQ(connection->pool_->pool_.threadName_, DATASHARE_EXECUTOR_NAME); + LOG_INFO("DataShareConnection_OnAbilityDisconnectDone_Test_001::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/datashare_helper_impl_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/datashare_helper_impl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ef3aa57cbef54f6d5568f0f7869ed4c31b5b9573 --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/datashare_helper_impl_test.cpp @@ -0,0 +1,662 @@ +/* + * 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 "datashare_helper_impl.h" +#include "general_controller_service_impl.h" + +#include + +#include + +#include "datashare_log.h" +#include "gmock/gmock.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; + +class MockGeneralController : public GeneralController { +public: + MOCK_METHOD(int, Insert, (const Uri &uri, const DataShareValuesBucket &value), (override)); + MOCK_METHOD(int, Update, + (const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value), (override)); + MOCK_METHOD(int, Delete, (const Uri &uri, const DataSharePredicates &predicates), (override)); + MOCK_METHOD((std::shared_ptr), Query, + (const Uri &uri, const DataSharePredicates &predicates, (std::vector & columns), + DatashareBusinessError &businessError, DataShareOption &option), (override)); + MOCK_METHOD( + int, RegisterObserver, (const Uri &uri, const sptr &dataObserver), (override)); + MOCK_METHOD(int32_t, UnregisterObserver, (const Uri &uri, const sptr &dataObserver), + (override)); + MOCK_METHOD(void, NotifyChange, (const Uri &uri), (override)); + MOCK_METHOD( + int, RegisterObserverExtProvider, (const Uri &uri, const sptr &dataObserver, + bool isDescendants), (override)); + MOCK_METHOD(int32_t, UnregisterObserverExtProvider, (const Uri &uri, + const sptr &dataObserver), (override)); + MOCK_METHOD(int32_t, NotifyChangeExtProvider, (const ChangeInfo &changeInfo), (override)); + MOCK_METHOD( + (std::pair), InsertEx, (const Uri &uri, const DataShareValuesBucket &value), (override)); + MOCK_METHOD((std::pair), UpdateEx, + (const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value), (override)); + MOCK_METHOD( + (std::pair), DeleteEx, (const Uri &uri, const DataSharePredicates &predicates), (override)); +}; + +class DataShareHelperImplTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static std::shared_ptr GetInstance(std::shared_ptr instance = nullptr); + static std::shared_ptr GetController( + std::shared_ptr instance = nullptr); +}; + +void DataShareHelperImplTest::SetUpTestCase(void) +{ + DataShareHelperImplTest::GetInstance(std::make_shared("datashare://datasharehelperimpl")); + EXPECT_NE(DataShareHelperImplTest::GetInstance(), nullptr); + DataShareHelperImplTest::GetController(std::make_shared()); + EXPECT_NE(DataShareHelperImplTest::GetController(), nullptr); + DataShareHelperImplTest::GetInstance()->generalCtl_ = DataShareHelperImplTest::GetController(); + EXPECT_NE(DataShareHelperImplTest::GetInstance()->generalCtl_, nullptr); + EXPECT_EQ(DataShareHelperImplTest::GetInstance()->extSpCtl_, nullptr); + DataShareHelperImplTest::GetInstance()->persistentDataCtl_ = nullptr; + DataShareHelperImplTest::GetInstance()->publishedDataCtl_ = nullptr; +} +void DataShareHelperImplTest::TearDownTestCase(void) +{ +} +void DataShareHelperImplTest::SetUp(void) +{ +} +void DataShareHelperImplTest::TearDown(void) +{ +} +std::shared_ptr DataShareHelperImplTest::GetInstance(std::shared_ptr instance) +{ + static std::shared_ptr helperInstance = nullptr; + if (instance != nullptr) { + helperInstance = instance; + } + return helperInstance; +} +std::shared_ptr DataShareHelperImplTest::GetController( + std::shared_ptr instance) +{ + static std::shared_ptr controllerInstance = nullptr; + if (instance != nullptr) { + controllerInstance = instance; + } + return controllerInstance; +} + +/** +* @tc.name: QueryTest001 +* @tc.desc: Verify Query function behavior under different controller states +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: DataShareHelperImpl instance is properly initialized +* @tc.step: + 1. Create test URI and empty predicates/columns + 2. Set general controller to null and execute Query + 3. Initialize mock controller and set it as general controller + 4. Verify Query returns expected result set with mock controller + 5. Verify Query works with business error parameter +* @tc.expect: + 1. Query returns nullptr when controller is null + 2. Query returns expected result set when using mock controller + 3. Query works correctly with business error parameter +*/ +HWTEST_F(DataShareHelperImplTest, QueryTest001, TestSize.Level0) +{ + LOG_INFO("QueryTest001::Start"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataSharePredicates predicates; + std::vector columns; + DataShareHelperImplTest::GetInstance()->generalCtl_ = nullptr; + auto result = DataShareHelperImplTest::GetInstance()->Query(uri, predicates, columns, nullptr); + EXPECT_EQ(result, nullptr); + auto expectResult = std::make_shared(); + std::shared_ptr controller = DataShareHelperImplTest::GetController(); + DataShareHelperImplTest::GetInstance()->generalCtl_ = controller; + EXPECT_CALL(*controller, Query(testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(expectResult)); + result = DataShareHelperImplTest::GetInstance()->Query(uri, predicates, columns, nullptr); + EXPECT_EQ(result, expectResult); + DatashareBusinessError error; + EXPECT_CALL(*controller, Query(testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(expectResult)); + result = DataShareHelperImplTest::GetInstance()->Query(uri, predicates, columns, &error); + EXPECT_EQ(result, expectResult); + LOG_INFO("QueryTest001::End"); +} + +/** +* @tc.name: QueryTimeoutTest001 +* @tc.desc: Verify QueryTimeout function behavior under different controller states +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: DataShareHelperImpl instance is properly initialized +* @tc.step: + 1. Create test URI, empty predicates/columns and default option + 2. Set general controller to null and execute QueryTimeout + 3. Initialize mock controller and set it as general controller + 4. Verify QueryTimeout returns expected result set with mock controller + 5. Verify QueryTimeout works with business error parameter +* @tc.expect: + 1. QueryTimeout returns nullptr when controller is null + 2. QueryTimeout returns expected result set when using mock controller + 3. QueryTimeout works correctly with business error parameter +*/ +HWTEST_F(DataShareHelperImplTest, QueryTimeoutTest001, TestSize.Level0) +{ + LOG_INFO("QueryTimeoutTest001::Start"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataSharePredicates predicates; + std::vector columns; + DataShareOption option; + DataShareHelperImplTest::GetInstance()->generalCtl_ = nullptr; + auto result = DataShareHelperImplTest::GetInstance()->Query(uri, predicates, columns, option, nullptr); + EXPECT_EQ(result, nullptr); + auto expectResult = std::make_shared(); + std::shared_ptr controller = DataShareHelperImplTest::GetController(); + DataShareHelperImplTest::GetInstance()->generalCtl_ = controller; + EXPECT_CALL(*controller, Query(testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(expectResult)); + result = DataShareHelperImplTest::GetInstance()->Query(uri, predicates, columns, option, nullptr); + EXPECT_EQ(result, expectResult); + DatashareBusinessError error; + EXPECT_CALL(*controller, Query(testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(expectResult)); + result = DataShareHelperImplTest::GetInstance()->Query(uri, predicates, columns, option, &error); + EXPECT_EQ(result, expectResult); + LOG_INFO("QueryTimeoutTest001::End"); +} + +/** +* @tc.name: BatchUpdateTest001 +* @tc.desc: Verify BatchUpdate function behavior with empty operations +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: DataShareHelperImpl instance is properly initialized +* @tc.step: + 1. Create empty update operations and results vector + 2. Execute BatchUpdate with empty parameters + 3. Check return error code +* @tc.expect: + 1. BatchUpdate returns DATA_SHARE_ERROR when given empty operations +*/ +HWTEST_F(DataShareHelperImplTest, BatchUpdateTest001, TestSize.Level0) +{ + LOG_INFO("BatchUpdateTest001::Start"); + UpdateOperations operations; + std::vector results = {}; + int result = DataShareHelperImplTest::GetInstance()->BatchUpdate(operations, results); + EXPECT_EQ(result, DATA_SHARE_ERROR); + LOG_INFO("BatchUpdateTest001::End"); +} + +/** +* @tc.name: InsertExTest001 +* @tc.desc: Verify InsertEx handles null controller and error responses +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Set general controller to null and call InsertEx + 2. Restore mock controller and set expectation for error response + 3. Call InsertEx again with valid parameters + 4. Check returned results in both cases +* @tc.expect: + 1. First call returns DATA_SHARE_ERROR + 2. Second call returns E_REGISTERED_REPEATED error +*/ +HWTEST_F(DataShareHelperImplTest, InsertExTest001, TestSize.Level0) +{ + LOG_INFO("InsertExTest001::Start"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataShareValuesBucket value; + DataShareHelperImplTest::GetInstance()->generalCtl_ = nullptr; + std::pair result = DataShareHelperImplTest::GetInstance()->InsertEx(uri, value); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + std::shared_ptr controller = DataShareHelperImplTest::GetController(); + DataShareHelperImplTest::GetInstance()->generalCtl_ = controller; + EXPECT_CALL(*controller, InsertEx(testing::_, testing::_)) + .WillOnce(testing::Return(std::make_pair(E_REGISTERED_REPEATED, 0))); + result = DataShareHelperImplTest::GetInstance()->InsertEx(uri, value); + EXPECT_EQ(result.first, E_REGISTERED_REPEATED); + EXPECT_EQ(result.second, 0); + LOG_INFO("InsertExTest001::End"); +} + +/** +* @tc.name: UpdateExTest001 +* @tc.desc: Verify UpdateEx handles null controller and error responses +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Set general controller to null and call UpdateEx + 2. Restore mock controller and set expectation for error response + 3. Call UpdateEx again with valid parameters + 4. Check returned results in both cases +* @tc.expect: + 1. First call returns DATA_SHARE_ERROR + 2. Second call returns E_REGISTERED_REPEATED error +*/ +HWTEST_F(DataShareHelperImplTest, UpdateExTest001, TestSize.Level0) +{ + LOG_INFO("UpdateExTest001::Start"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataShareValuesBucket value; + DataSharePredicates predicates; + DataShareHelperImplTest::GetInstance()->generalCtl_ = nullptr; + std::pair result = DataShareHelperImplTest::GetInstance()->UpdateEx(uri, predicates, value); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + std::shared_ptr controller = DataShareHelperImplTest::GetController(); + DataShareHelperImplTest::GetInstance()->generalCtl_ = controller; + EXPECT_CALL(*controller, UpdateEx(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(std::make_pair(E_REGISTERED_REPEATED, 0))); + result = DataShareHelperImplTest::GetInstance()->UpdateEx(uri, predicates, value); + EXPECT_EQ(result.first, E_REGISTERED_REPEATED); + EXPECT_EQ(result.second, 0); + LOG_INFO("UpdateExTest001::End"); +} + +/** +* @tc.name: DeleteExTest001 +* @tc.desc: Verify DeleteEx handles null controller and error responses +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Set general controller to null and call DeleteEx + 2. Restore mock controller and set expectation for error response + 3. Call DeleteEx again with valid parameters + 4. Check returned results in both cases +* @tc.expect: + 1. First call returns DATA_SHARE_ERROR + 2. Second call returns E_REGISTERED_REPEATED error +*/ +HWTEST_F(DataShareHelperImplTest, DeleteExTest001, TestSize.Level0) +{ + LOG_INFO("DeleteExTest001::Start"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataSharePredicates predicates; + DataShareHelperImplTest::GetInstance()->generalCtl_ = nullptr; + std::pair result = DataShareHelperImplTest::GetInstance()->DeleteEx(uri, predicates); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + std::shared_ptr controller = DataShareHelperImplTest::GetController(); + DataShareHelperImplTest::GetInstance()->generalCtl_ = controller; + EXPECT_CALL(*controller, DeleteEx(testing::_, testing::_)) + .WillOnce(testing::Return(std::make_pair(E_REGISTERED_REPEATED, 0))); + result = DataShareHelperImplTest::GetInstance()->DeleteEx(uri, predicates); + EXPECT_EQ(result.first, E_REGISTERED_REPEATED); + EXPECT_EQ(result.second, 0); + LOG_INFO("DeleteExTest001::End"); +} + +/** +* @tc.name: DelQueryTemplateTest001 +* @tc.desc: Verify DelQueryTemplate returns error with valid parameters +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Call DelQueryTemplate with test URI and subscriber ID + 2. Check returned result code +* @tc.expect: + 1. DelQueryTemplate returns DATA_SHARE_ERROR +*/ +HWTEST_F(DataShareHelperImplTest, DelQueryTemplateTest001, TestSize.Level0) +{ + LOG_INFO("DelQueryTemplateTest001::Start"); + std::string uri("datashare:///com.datasharehelperimpl.test"); + int64_t subscriberId = 0; + int result = DataShareHelperImplTest::GetInstance()->DelQueryTemplate(uri, subscriberId); + EXPECT_EQ(result, DATA_SHARE_ERROR); + LOG_INFO("DelQueryTemplateTest001::End"); +} + +/** +* @tc.name: PublishTest001 +* @tc.desc: Verify Publish returns empty result with valid parameters +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create empty Data object and test bundle name + 2. Call Publish with these parameters + 3. Check size of returned result vector +* @tc.expect: + 1. Returned result vector is empty +*/ +HWTEST_F(DataShareHelperImplTest, PublishTest001, TestSize.Level0) +{ + LOG_INFO("PublishTest001::Start"); + Data data; + std::string bundleName("datashare:///com.datasharehelperimpl.test"); + std::vector result = DataShareHelperImplTest::GetInstance()->Publish(data, bundleName); + EXPECT_EQ(result.size(), 0); + LOG_INFO("PublishTest001::End"); +} + +/** +* @tc.name: GetPublishedDataTest001 +* @tc.desc: Verify GetPublishedData returns empty data with valid parameters +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create test bundle name and result code variable + 2. Call GetPublishedData with these parameters + 3. Check version and size of returned Data object +* @tc.expect: + 1. Returned Data object has version 0 and empty data vector +*/ +HWTEST_F(DataShareHelperImplTest, GetPublishedDataTest001, TestSize.Level0) +{ + LOG_INFO("GetPublishedDataTest001::Start"); + int resultCode = 0; + std::string bundleName("datashare:///com.datasharehelperimpl.test"); + Data result = DataShareHelperImplTest::GetInstance()->GetPublishedData(bundleName, resultCode); + EXPECT_EQ(result.version_, 0); + EXPECT_EQ(result.datas_.size(), 0); + LOG_INFO("GetPublishedDataTest001::End"); +} + +/** +* @tc.name: SubscribeRdbDataTest001 +* @tc.desc: Verify SubscribeRdbData returns empty result with empty URIs +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create empty URIs vector, template ID and callback + 2. Call SubscribeRdbData with these parameters + 3. Check size of returned result vector +* @tc.expect: + 1. Returned result vector is empty +*/ +HWTEST_F(DataShareHelperImplTest, SubscribeRdbDataTest001, TestSize.Level0) +{ + LOG_INFO("SubscribeRdbDataTest001::Start"); + std::vector uris = {}; + TemplateId templateId; + std::function callback; + std::vector result = + DataShareHelperImplTest::GetInstance()->SubscribeRdbData(uris, templateId, callback); + EXPECT_EQ(result.size(), 0); + LOG_INFO("SubscribeRdbDataTest001::End"); +} + +/** +* @tc.name: UnsubscribeRdbDataTest001 +* @tc.desc: Verify UnsubscribeRdbData returns empty result with empty URIs +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create empty URIs vector and template ID + 2. Call UnsubscribeRdbData with these parameters + 3. Check size of returned result vector +* @tc.expect: + 1. Returned result vector is empty +*/ +HWTEST_F(DataShareHelperImplTest, UnsubscribeRdbDataTest001, TestSize.Level0) +{ + LOG_INFO("UnsubscribeRdbDataTest001::Start"); + std::vector uris = {}; + TemplateId templateId; + std::vector result = DataShareHelperImplTest::GetInstance()->UnsubscribeRdbData(uris, templateId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("UnsubscribeRdbDataTest001::End"); +} + +/** +* @tc.name: DisableRdbSubsTest001 +* @tc.desc: Verify DisableRdbSubs returns empty result with empty URIs +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create empty URIs vector and template ID + 2. Call DisableRdbSubs with these parameters + 3. Check size of returned result vector +* @tc.expect: + 1. Returned result vector is empty +*/ +HWTEST_F(DataShareHelperImplTest, DisableRdbSubsTest001, TestSize.Level0) +{ + LOG_INFO("DisableRdbSubsTest001::Start"); + std::vector uris = {}; + TemplateId templateId; + std::vector result = DataShareHelperImplTest::GetInstance()->DisableRdbSubs(uris, templateId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("DisableRdbSubsTest001::End"); +} + +/** +* @tc.name: SubscribePublishedDataTest001 +* @tc.desc: Verify SubscribePublishedData returns empty result with empty URIs +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create empty URIs vector, subscriber ID and callback + 2. Call SubscribePublishedData with these parameters + 3. Check size of returned result vector +* @tc.expect: + 1. Returned result vector is empty +*/ +HWTEST_F(DataShareHelperImplTest, SubscribePublishedDataTest001, TestSize.Level0) +{ + LOG_INFO("SubscribePublishedDataTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 0; + std::function callback; + std::vector result = + DataShareHelperImplTest::GetInstance()->SubscribePublishedData(uris, subscriberId, callback); + EXPECT_EQ(result.size(), 0); + LOG_INFO("SubscribePublishedDataTest001::End"); +} + +/** +* @tc.name: UnsubscribePublishedDataTest001 +* @tc.desc: Verify UnsubscribePublishedData returns empty result with empty URIs +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create empty URIs vector and subscriber ID + 2. Call UnsubscribePublishedData with these parameters + 3. Check size of returned result vector +* @tc.expect: + 1. Returned result vector is empty +*/ +HWTEST_F(DataShareHelperImplTest, UnsubscribePublishedDataTest001, TestSize.Level0) +{ + LOG_INFO("UnsubscribePublishedDataTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 0; + std::vector result = + DataShareHelperImplTest::GetInstance()->UnsubscribePublishedData(uris, subscriberId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("UnsubscribePublishedDataTest001::End"); +} + +/** +* @tc.name: EnablePubSubsTest001 +* @tc.desc: Verify EnablePubSubs returns empty result with empty URIs +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create empty URIs vector and subscriber ID + 2. Call EnablePubSubs with these parameters + 3. Check size of returned result vector +* @tc.expect: + 1. Returned result vector is empty +*/ +HWTEST_F(DataShareHelperImplTest, EnablePubSubsTest001, TestSize.Level0) +{ + LOG_INFO("EnablePubSubsTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 0; + std::vector result = DataShareHelperImplTest::GetInstance()->EnablePubSubs(uris, subscriberId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("EnablePubSubsTest001::End"); +} + +/** +* @tc.name: DisablePubSubsTest001 +* @tc.desc: Verify DisablePubSubs returns empty result with empty URIs +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create empty URIs vector and subscriber ID + 2. Call DisablePubSubs with these parameters + 3. Check size of returned result vector +* @tc.expect: + 1. Returned result vector is empty +*/ +HWTEST_F(DataShareHelperImplTest, DisablePubSubsTest001, TestSize.Level0) +{ + LOG_INFO("DisablePubSubsTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 0; + std::vector result = DataShareHelperImplTest::GetInstance()->DisablePubSubs(uris, subscriberId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("DisablePubSubsTest001::End"); +} + +/** +* @tc.name: User_Define_func_No_ExtSpCtl_Test001 +* @tc.desc: Verify UserDefineFunc returns error when extSpCtl_ is null +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Set extSpCtl_ to null + 2. Create empty MessageParcel objects and MessageOption + 3. Call UserDefineFunc with these parameters + 4. Check returned result code +* @tc.expect: + 1. UserDefineFunc returns DATA_SHARE_ERROR +*/ +HWTEST_F(DataShareHelperImplTest, User_Define_func_No_ExtSpCtl_Test001, TestSize.Level0) +{ + LOG_INFO("User_Define_func_No_ExtSpCtl_Test001::Start"); + DataShareHelperImplTest::GetInstance()->extSpCtl_ = nullptr; + MessageParcel data; + MessageParcel reply; + MessageOption option; + auto result = DataShareHelperImplTest::GetInstance()->UserDefineFunc(data, reply, option); + EXPECT_EQ(result, DATA_SHARE_ERROR); + LOG_INFO("User_Define_func_No_ExtSpCtl_Test001::End"); +} + +class MockDataShareServiceProxy : public DataShareServiceProxy { +public: + explicit MockDataShareServiceProxy(const sptr& impl) : DataShareServiceProxy(impl) {} + ~MockDataShareServiceProxy() = default; + + std::shared_ptr Query(const Uri &uri, const Uri &extUri, const DataSharePredicates &predicates, + std::vector &columns, DatashareBusinessError &businessError) + { + businessError.SetCode(E_OK); + std::this_thread::sleep_for(std::chrono::seconds(3)); // sleep 3s + return nullptr; + } +}; + +/** +* @tc.name: QueryTimeoutTest002 +* @tc.desc: Test Query function with timeout option +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerServiceImpl and call Query with default option + 2. Set option timeout to 1 and call Query function again + 3. Set pool_ to nullptr and call Query function the third time +* @tc.experct: All Query calls return nullptr +*/ +HWTEST_F(DataShareHelperImplTest, QueryTimeoutTest002, TestSize.Level0) +{ + LOG_INFO("QueryTimeoutTest002::Start"); + sptr remoteObject; + std::shared_ptr service = std::make_shared(remoteObject); + auto manager = DataShareManagerImpl::GetInstance(); + manager->dataShareService_ = static_cast>(service); + auto generalCtl = GeneralControllerServiceImpl("datashare://datasharehelperimpl"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataSharePredicates predicates; + std::vector columns; + DataShareOption option; + DatashareBusinessError businessError; + auto res = generalCtl.Query(uri, predicates, columns, businessError, option); + EXPECT_EQ(res, nullptr); + + option.timeout = 1; + res = generalCtl.Query(uri, predicates, columns, businessError, option); + EXPECT_EQ(businessError.GetCode(), E_TIMEOUT_ERROR); + + option.timeout = 4000; // time out lager than task execute time + res = generalCtl.Query(uri, predicates, columns, businessError, option); + EXPECT_EQ(businessError.GetCode(), E_OK); + + generalCtl.pool_ = nullptr; + res = generalCtl.Query(uri, predicates, columns, businessError, option); + EXPECT_EQ(businessError.GetCode(), E_EXECUTOR_POOL_IS_NULL); + LOG_INFO("QueryTimeoutTest002::End"); +} + +/** +* @tc.name: QueryTimeoutTest003 +* @tc.desc: Test Query function timeout scenarios with different timeout values +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Set up MockDataShareServiceProxy and GeneralControllerServiceImpl + 2. Call Query with timeout less than task execute time + 3. Call Query with timeout larger than task execute time +* @tc.experct: First call returns E_TIMEOUT_ERROR, second call returns E_OK +*/ +HWTEST_F(DataShareHelperImplTest, QueryTimeoutTest003, TestSize.Level0) +{ + LOG_INFO("QueryTimeoutTest003::Start"); + sptr remoteObject; + std::shared_ptr service = std::make_shared(remoteObject); + auto manager = DataShareManagerImpl::GetInstance(); + manager->dataShareService_ = static_cast>(service); + + auto generalCtl = std::make_shared("datashare://datasharehelperimpl"); + auto helper = DataShareHelperImplTest::GetInstance(); + helper->generalCtl_ = generalCtl; + + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataSharePredicates predicates; + std::vector columns; + DataShareOption option; + option.timeout = 2000; // time out less than task execute time + DatashareBusinessError businessError; + auto res = helper->Query(uri, predicates, columns, option, &businessError); + EXPECT_EQ(businessError.GetCode(), E_TIMEOUT_ERROR); + + option.timeout = 4000; // time out lager than task execute time + res = helper->Query(uri, predicates, columns, option, &businessError); + EXPECT_EQ(businessError.GetCode(), E_OK); + + option.timeout = 0; + res = helper->Query(uri, predicates, columns, option, &businessError); + EXPECT_EQ(businessError.GetCode(), E_OK); + LOG_INFO("QueryTimeoutTest003::End"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/datashare_helper_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/datashare_helper_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7fecb5d7f3ad0f379c0182163b667b7ec55e7268 --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/datashare_helper_test.cpp @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2025 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 + +#include "datashare_helper.h" +#include "datashare_helper_impl.h" +#include "datashare_log.h" +#include "datashare_uri_utils.h" +#include "iservice_registry.h" +#include "ikvstore_data_service_mock.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; + +constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; +std::string NON_SILENT_ACCESS_URI = "datashare:///com.acts.datasharetest"; +std::string NON_SILENT_ACCESS_ERROR_URI = "datashare:///com.acts.test"; +constexpr int DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID = 1301; + +class DataShareHelperTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +void DataShareManagerImplHelper() +{ + auto helper = DataShareManagerImpl::GetInstance(); + helper->dataShareService_ = nullptr; + auto manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + auto remoteObject = manager->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); + sptr mockProxy = sptr + (new MockDataShareKvServiceProxy(remoteObject)); + EXPECT_CALL(*mockProxy, GetFeatureInterface(testing::_)) + .WillOnce(testing::Return(nullptr)); + helper->dataMgrService_ = (sptr)mockProxy; +} + +/** + * @tc.name: + * @tc.desc: test Creator function when options.isProxy_ = false and options.token_ = nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what options.isProxy_ = false and options.token_ = nullptr + 2.call Creator function and check the result + * @tc.experct: Creator failed and reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreatorTest001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreatorTest001::Start"); + std::string strUri = "testUri"; + CreateOptions options; + options.isProxy_ = false; + options.token_ = nullptr; + std::string bundleName = "testBundle"; + int waitTime = 1; + bool isSystem = true; + auto result = DataShareHelper::Creator(strUri, options, bundleName, waitTime, isSystem); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreatorTest001::End"); +} + +/** + * @tc.name: + * @tc.desc: test Creator function when options.isProxy_ = true and options.token_ = nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what options.isProxy_ = true and options.token_ = nullptr + 2.call Creator function and check the result + * @tc.experct: Creator failed and reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreatorTest002, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreatorTest002::Start"); + std::string strUri = "testUri"; + CreateOptions options; + options.isProxy_ = true; + options.token_ = nullptr; + std::string bundleName = "testBundle"; + int waitTime = 1; + bool isSystem = true; + auto result = DataShareHelper::Creator(strUri, options, bundleName, waitTime, isSystem); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreatorTest002::End"); +} + +/** + * @tc.name: + * @tc.desc: test Creator function when options.isProxy_ = false and options.token_ != nullptr + * @tc.type: FUNC + * @tc.require:issueICDSBD + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what options.isProxy_ = false and options.token_ != nullptr + 2.call Creator function and check the result + * @tc.experct: Creator success and not reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreatorTest003, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreatorTest003::Start"); + CreateOptions options; + options.isProxy_ = false; + +auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); +EXPECT_NE(saManager, nullptr); +auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID); +EXPECT_NE(remoteObj, nullptr); +options.token_ = remoteObj; +auto result = DataShareHelper::Creator(NON_SILENT_ACCESS_URI, options); +EXPECT_NE(result, nullptr); +LOG_INFO("DataShareHelperTest CreatorTest003::End"); +} + +/** + * @tc.name: + * @tc.desc: test Creator function when options.isProxy_ = true and options.token_ != nullptr + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what options.isProxy_ = true and options.token_ != nullptr + 2.call Creator function and check the result + * @tc.experct: Creator failed and not reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreatorTest004, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreatorTest004::Start"); + CreateOptions options; + options.isProxy_ = true; + + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + EXPECT_NE(saManager, nullptr); + auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID); + EXPECT_NE(remoteObj, nullptr); + options.token_ = remoteObj; + auto result = DataShareHelper::Creator(NON_SILENT_ACCESS_ERROR_URI, options); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreatorTest004::End"); +} + +/** + * @tc.name: + * @tc.desc: test CreateExtHelper function when Uri contains "appIndex=" + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what Uri contains "appIndex=" + 2.call CreateExtHelper function and check the result + * @tc.experct: CreateExtHelper failed and reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreateExtHelper001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreateExtHelper001::Start"); + OHOS::Uri uri("datashareproxy://com.acts.ohos.data.datasharetest/test?appIndex=abcd"); + uri.query_ = ("appIndex=abcd"); + sptr token = nullptr; + int waitTime = 1000; + bool isSystem = false; + auto result = DataShareHelper::CreateExtHelper(uri, token, waitTime, isSystem); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreateExtHelper001::End"); +} + +/** + * @tc.name: SetSilentSwitch001 + * @tc.desc: test SetSilentSwitch function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object + 2.call SetSilentSwitch function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.experct: SetSilentSwitch failed and reutrn DATA_SHARE_ERROR + */ +HWTEST_F(DataShareHelperTest, SetSilentSwitch001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest SetSilentSwitch001::Start"); + DataShareManagerImplHelper(); + OHOS::Uri uri("datashareproxy://com.acts.ohos.data.datasharetest/test?appIndex=abcd"); + uri.query_ = ("appIndex=abcd"); + bool enable = false; + bool isSystem = false; + auto result = DataShareHelper::SetSilentSwitch(uri, enable, isSystem); + EXPECT_EQ(result, DATA_SHARE_ERROR); + LOG_INFO("DataShareHelperTest SetSilentSwitch001::End"); +} + +/** + * @tc.name: GetSilentProxyStatus001 + * @tc.desc: test GetSilentProxyStatus function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object + 2.call GetSilentProxyStatus function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.experct: GetSilentProxyStatus failed and reutrn E_ERROR + */ +HWTEST_F(DataShareHelperTest, GetSilentProxyStatus001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest GetSilentProxyStatus001::Start"); + DataShareManagerImplHelper(); + std::string uri = "datashareproxy://com.acts.ohos.data.datasharetest/test?appIndex=abcd"; + bool isSystem = false; + auto result = DataShareHelper::GetSilentProxyStatus(uri, isSystem); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareHelperTest GetSilentProxyStatus001::End"); +} + +/** + * @tc.name: CreateServiceHelper001 + * @tc.desc: test CreateExtHelper function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object + 2.call CreateServiceHelper function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.experct: CreateServiceHelper failed and reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreateServiceHelper001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreateServiceHelper001::Start"); + DataShareManagerImplHelper(); + std::string exuri = "testExuri"; + std::string bundleName = "bundleName"; + bool isSystem = false; + auto result = DataShareHelper::CreateServiceHelper(exuri, bundleName, isSystem); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreateServiceHelper001::End"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/datashare_proxy_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/datashare_proxy_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..132ba33a52970728ec71562eef3d9df7bf97fbda --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/datashare_proxy_test.cpp @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2025 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 "datashare_proxy.h" + +#include + +#include "accesstoken_kit.h" +#include "data_ability_observer_interface.h" +#include "datashare_connection.h" +#include "datashare_errno.h" +#include "datashare_helper.h" +#include "datashare_log.h" +#include "extension_manager_proxy.h" +#include "general_controller.h" +#include "general_controller_provider_impl.h" +#include "general_controller_service_impl.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::AAFwk; +class DataShareProxyTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +class RemoteObjectTest : public IRemoteObject { +public: + explicit RemoteObjectTest(std::u16string descriptor) : IRemoteObject(descriptor) {} + ~RemoteObjectTest() {} + + int32_t GetObjectRefCount() + { + return 0; + } + int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + return 0; + } + bool AddDeathRecipient(const sptr &recipient) + { + return true; + } + bool RemoveDeathRecipient(const sptr &recipient) + { + return true; + } + int Dump(int fd, const std::vector &args) + { + return 0; + } +}; + +class IDataAbilityObserverTest : public DataAbilityObserverStub { +public: + IDataAbilityObserverTest() {} + ~IDataAbilityObserverTest() + {} + + void OnChange() + { + GTEST_LOG_(INFO) << "OnChange enter"; + } +}; + +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; + +void DataShareProxyTest::SetUpTestCase(void) {} +void DataShareProxyTest::TearDownTestCase(void) {} +void DataShareProxyTest::SetUp(void) {} +void DataShareProxyTest::TearDown(void) {} + +/** +* @tc.name: DataShareProxy_RegisterObserverExtProvider_Test_001 +* @tc.desc: Verify basic functionality of RegisterObserverExtProvider method +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with test URI and token + 2. Initialize DataShareProxy and assign to connection + 3. Get proxy instance and verify it's not null + 4. Create test observer and call RegisterObserverExtProvider + 5. Check returned result code +* @tc.expect: + 1. All objects are successfully initialized + 2. RegisterObserverExtProvider returns 0 (E_OK) +*/ +HWTEST_F(DataShareProxyTest, DataShareProxy_RegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareProxy_RegisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + + connection->dataShareProxy_ = tokenProxy; + ASSERT_NE(connection->dataShareProxy_, nullptr); + auto proxy = connection->GetDataShareProxy(uri, token); + ASSERT_NE(proxy, nullptr); + + // Observer not null + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + ASSERT_NE(dataObserver, nullptr); + // datashare_stub returns default 0(E_OK) + int ret = proxy->RegisterObserverExtProvider(uri, dataObserver, true, { false }); + EXPECT_EQ(ret, 0); + + LOG_INFO("DataShareProxy_RegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareProxy_UnregisterObserverExtProvider_Test_001 +* @tc.desc: Verify basic functionality of UnregisterObserverExtProvider method +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with test URI and token + 2. Initialize DataShareProxy and assign to connection + 3. Get proxy instance and verify it's not null + 4. Create test observer and call UnregisterObserverExtProvider + 5. Check returned result code +* @tc.expect: + 1. All objects are successfully initialized + 2. UnregisterObserverExtProvider returns 0 (E_OK) +*/ +HWTEST_F(DataShareProxyTest, DataShareProxy_UnregisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareProxy_UnregisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + connection->dataShareProxy_ = tokenProxy; + auto proxy = connection->GetDataShareProxy(uri, token); + ASSERT_NE(proxy, nullptr); + + // observer not null + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + ASSERT_NE(dataObserver, nullptr); + // datashare_stub returns default 0(E_OK) + int ret = proxy->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(ret, 0); + + LOG_INFO("DataShareProxy_UnregisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareProxy_NotifyChangeExtProvider_Test_001 +* @tc.desc: Verify basic functionality of NotifyChangeExtProvider method +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with test URI and token + 2. Initialize DataShareProxy and assign to connection + 3. Get proxy instance and verify it's not null + 4. Create test ChangeInfo object and call NotifyChangeExtProvider + 5. Check returned result code +* @tc.expect: + 1. All objects are successfully initialized + 2. NotifyChangeExtProvider returns 0 (E_OK) +*/ +HWTEST_F(DataShareProxyTest, DataShareProxy_NotifyChangeExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareProxy_NotifyChangeExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + connection->dataShareProxy_ = tokenProxy; + auto proxy = connection->GetDataShareProxy(uri, token); + ASSERT_NE(proxy, nullptr); + + ChangeInfo changeInfo = { ChangeInfo::ChangeType::INSERT, { uri } }; + // datashare_stub returns default 0(E_OK) + int ret = proxy->NotifyChangeExtProvider(changeInfo); + EXPECT_EQ(ret, 0); + + LOG_INFO("DataShareProxy_NotifyChangeExtProvider_Test_001::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/datashare_stub_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/datashare_stub_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29d320504aa85ce821637f601a08a9be51406aa6 --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/datashare_stub_test.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2025 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 "datashare_stub.h" + +#include + +#include "accesstoken_kit.h" +#include "data_ability_observer_stub.h" +#include "datashare_business_error.h" +#include "datashare_errno.h" +#include "datashare_itypes_utils.h" +#include "datashare_log.h" +#include "datashare_operation_statement.h" +#include "datashare_stub_impl.h" +#include "extension_manager_proxy.h" +#include "idatashare.h" +#include "ipc_skeleton.h" +#include "ipc_types.h" +#include "ishared_result_set.h" + + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace DistributedShare::DataShare; +using namespace OHOS::AAFwk; +using ChangeInfo = AAFwk::ChangeInfo; +class DataShareStubTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + + +class IDataAbilityObserverTest : public DataAbilityObserverStub { +public: + IDataAbilityObserverTest() {} + ~IDataAbilityObserverTest() + {} + + void OnChange() + { + GTEST_LOG_(INFO) << "OnChange enter"; + } +}; + +class TestDataShareStub : public DataShareStub { +public: + TestDataShareStub() {} + ~TestDataShareStub() {} + int OpenFile(const Uri &uri, const std::string &mode) + { + return 0; + } + int OpenRawFile(const Uri &uri, const std::string &mode) + { + return 0; + } + int Insert(const Uri &uri, const DataShareValuesBucket &value) + { + return 0; + } + int Update(const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) + { + return 0; + } + int Delete(const Uri &uri, const DataSharePredicates &predicates) + { + return 0; + } + std::shared_ptr Query(const Uri &uri, const DataSharePredicates &predicates, + std::vector &columns, DatashareBusinessError &businessError) + { + return nullptr; + } + std::string GetType(const Uri &uri) + { + return ""; + } + int BatchInsert(const Uri &uri, const std::vector &values) + { + return 0; + } + bool RegisterObserver(const Uri &uri, const sptr &dataObserver) + { + return true; + } + bool UnregisterObserver(const Uri &uri, const sptr &dataObserver) + { + return true; + } + bool NotifyChange(const Uri &uri) + { + return true; + } + Uri NormalizeUri(const Uri &uri) + { + return uri; + } + Uri DenormalizeUri(const Uri &uri) + { + return uri; + } + std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) + { + return {}; + } +}; + +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::shared_ptr dataShareStub = std::make_shared(); +std::u16string InterfaceToken = u"OHOS.DataShare.IDataShare"; + +void DataShareStubTest::SetUpTestCase(void) {} +void DataShareStubTest::TearDownTestCase(void) {} +void DataShareStubTest::SetUp(void) {} +void DataShareStubTest::TearDown(void) {} + +/** +* @tc.name: DataShareStub_CmdRegisterObserverExtProvider_Test_001 +* @tc.desc: Verify functionality of CMD_REGISTER_OBSERVEREXT_PROVIDER command handling +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create test URI and IDataAbilityObserverTest instance + 2. Prepare message parcel with interface token and parameters + 3. Call OnRemoteRequest with REGISTER_OBSERVEREXT_PROVIDER command + 4. Check returned error code and unmarshal result +* @tc.expect: + 1. All objects are successfully initialized + 2. OnRemoteRequest returns 0 (success) + 3. Unmarshaled result code is 0 (E_OK) +*/ +HWTEST_F(DataShareStubTest, DataShareStub_CmdRegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareStub_CmdRegisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + ASSERT_NE(dataObserver, nullptr); + uint32_t code = static_cast(IDataShareInterfaceCode::CMD_REGISTER_OBSERVEREXT_PROVIDER); + + MessageParcel data; + data.WriteInterfaceToken(InterfaceToken); + RegisterOption registerOption; + bool ret = ITypesUtil::Marshal(data, uri, dataObserver->AsObject(), true, registerOption); + EXPECT_TRUE(ret); + + MessageParcel reply; + MessageOption option; + ASSERT_NE(dataShareStub, nullptr); + int errCode = dataShareStub->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(errCode, 0); + ret = ITypesUtil::Unmarshal(reply, errCode); + EXPECT_TRUE(ret); + // return default errCode 0(E_OK) + EXPECT_EQ(errCode, 0); + + LOG_INFO("DataShareStub_CmdRegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareStub_CmdUnregisterObserverExtProvider_Test_001 +* @tc.desc: Verify functionality of CMD_UNREGISTER_OBSERVEREXT_PROVIDER command handling +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create test URI and IDataAbilityObserverTest instance + 2. Prepare message parcel with interface token and parameters + 3. Call OnRemoteRequest with UNREGISTER_OBSERVEREXT_PROVIDER command + 4. Check returned error code and unmarshal result +* @tc.expect: + 1. All objects are successfully initialized + 2. OnRemoteRequest returns 0 (success) + 3. Unmarshaled result code is 0 (E_OK) +*/ +HWTEST_F(DataShareStubTest, DataShareStub_CmdUnregisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareStub_CmdUnregisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + ASSERT_NE(dataObserver, nullptr); + uint32_t code = static_cast(IDataShareInterfaceCode::CMD_UNREGISTER_OBSERVEREXT_PROVIDER); + + MessageParcel data; + data.WriteInterfaceToken(InterfaceToken); + bool ret = ITypesUtil::Marshal(data, uri, dataObserver->AsObject()); + EXPECT_TRUE(ret); + + MessageParcel reply; + MessageOption option; + int errCode = dataShareStub->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(errCode, 0); + ret = ITypesUtil::Unmarshal(reply, errCode); + EXPECT_TRUE(ret); + // return default errCode 0(E_OK) + EXPECT_EQ(errCode, 0); + + LOG_INFO("DataShareStub_CmdUnregisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareStub_CmdNotifyChangeExtProvider_Test_001 +* @tc.desc: Verify functionality of CMD_NOTIFY_CHANGEEXT_PROVIDER command handling +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create test URI and ChangeInfo object + 2. Prepare message parcel with interface token and marshaled ChangeInfo + 3. Call OnRemoteRequest with NOTIFY_CHANGEEXT_PROVIDER command + 4. Check returned error code and unmarshal result +* @tc.expect: + 1. All objects are successfully initialized + 2. OnRemoteRequest returns 0 (success) + 3. Unmarshaled result code is 0 (E_OK) +*/ +HWTEST_F(DataShareStubTest, DataShareStub_CmdNotifyChangeExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareStub_CmdNotifyChangeExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + ChangeInfo changeInfo = { ChangeInfo::ChangeType::INSERT, { uri } }; + uint32_t code = static_cast(IDataShareInterfaceCode::CMD_NOTIFY_CHANGEEXT_PROVIDER); + + MessageParcel data; + data.WriteInterfaceToken(InterfaceToken); + bool ret = ChangeInfo::Marshalling(changeInfo, data); + EXPECT_TRUE(ret); + + MessageParcel reply; + MessageOption option; + int errCode = dataShareStub->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(errCode, 0); + ret = ITypesUtil::Unmarshal(reply, errCode); + EXPECT_TRUE(ret); + // return default errCode 0(E_OK) + EXPECT_EQ(errCode, 0); + + LOG_INFO("DataShareStub_CmdNotifyChangeExtProvider_Test_001::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/errorcode_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/errorcode_test.cpp index 9b8841b20c60a00856e4d50417af0e074fbc9d8a..2a99cc2e877a53d674402956d1e593fbd4b0a395 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/errorcode_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/errorcode_test.cpp @@ -29,26 +29,22 @@ namespace DataShare { using namespace testing::ext; using namespace OHOS::Security::AccessToken; constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; +std::string DATA_SHARE_URI = "datashare:///com.acts.errorcodetest"; +std::string SLIENT_ACCESS_URI = "datashare:///com.acts.errorcodetest/entry/DB00/TBL00?Proxy=true"; +std::string TBL_STU_NAME = "name"; +std::string TBL_STU_AGE = "age"; +std::shared_ptr g_slientAccessHelper; +std::shared_ptr dataShareHelper; + class ErrorCodeTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); void SetUp(); void TearDown(); - -protected: - static std::shared_ptr CreateDataShareHelper(int32_t saId, std::string uri); - static inline std::string DATA_SHARE_URI = "datashare:///com.acts.errorcodetest"; - static inline std::string SLIENT_ACCESS_URI = "datashare:///com.acts.errorcodetest/entry/DB00/TBL00?Proxy=true"; - std::string TBL_STU_NAME = "name"; - std::string TBL_STU_AGE = "age"; - static std::shared_ptr g_slientAccessHelper; - static std::shared_ptr dataShareHelper; }; -std::shared_ptr ErrorCodeTest::g_slientAccessHelper; -std::shared_ptr ErrorCodeTest::dataShareHelper; -std::shared_ptr ErrorCodeTest::CreateDataShareHelper(int32_t saId, std::string uri) +std::shared_ptr CreateDataShareHelper(int32_t systemAbilityId, std::string uri) { LOG_INFO("CreateDataShareHelper start"); auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); @@ -56,8 +52,8 @@ std::shared_ptr ErrorCodeTest::CreateDataShareHelper LOG_ERROR("GetSystemAbilityManager get samgr failed."); return nullptr; } - auto remoteObj = saManager->GetSystemAbility(saId); - while (remoteObj == nullptr) { + auto remoteObj = saManager->GetSystemAbility(systemAbilityId); + if (remoteObj == nullptr) { LOG_ERROR("GetSystemAbility service failed."); return nullptr; } @@ -124,6 +120,19 @@ void ErrorCodeTest::TearDownTestCase(void) void ErrorCodeTest::SetUp(void) {} void ErrorCodeTest::TearDown(void) {} +/** +* @tc.name: ErrorCodeTest_Insert_Test_001 +* @tc.desc: Verify successful insertion operation returns positive ID +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get slient access helper instance + 2. Create test URI and DataShareValuesBucket with student data + 3. Call Insert method with URI and values bucket + 4. Check if returned ID is positive +* @tc.experct: Insert operation succeeds and returns positive ID +*/ HWTEST_F(ErrorCodeTest, ErrorCodeTest_Insert_Test_001, TestSize.Level0) { LOG_INFO("ErrorCodeTest_Insert_Test_001::Start"); @@ -140,6 +149,21 @@ HWTEST_F(ErrorCodeTest, ErrorCodeTest_Insert_Test_001, TestSize.Level0) LOG_INFO("ErrorCodeTest_Insert_Test_001::End"); } +/** +* @tc.name: ErrorCodeTest_QUERY_Test_001 +* @tc.desc: Verify query operations return correct error codes for valid and invalid URIs +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Query existing data with valid URI and check for success + 2. Verify row count is 1 for existing data + 3. Query with invalid URI and check error code + 4. Verify result set is null for invalid URI +* @tc.experct: + 1. Valid query returns 0 error code and 1 row + 2. Invalid query returns E_DB_NOT_EXIST error and null result set +*/ HWTEST_F(ErrorCodeTest, ErrorCodeTest_QUERY_Test_001, TestSize.Level0) { LOG_INFO("ErrorCodeTest_QUERY_Test_001::Start"); @@ -166,6 +190,22 @@ HWTEST_F(ErrorCodeTest, ErrorCodeTest_QUERY_Test_001, TestSize.Level0) LOG_INFO("ErrorCodeTest_QUERY_Test_001::End"); } +/** +* @tc.name: ErrorCodeTest_QUERY_Test_002 +* @tc.desc: Verify unauthorized query returns correct error code +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Insert test data using dataShareHelper + 2. Query inserted data with predicates + 3. Check error code and result set for unauthorized access + 4. Clean up by deleting inserted data +* @tc.experct: + 1. Insert succeeds with positive ID + 2. Query returns 401 error code and null result set + 3. Delete operation succeeds with positive count +*/ HWTEST_F(ErrorCodeTest, ErrorCodeTest_QUERY_Test_002, TestSize.Level0) { LOG_INFO("ErrorCodeTest_QUERY_Test_002::Start"); diff --git a/data_share/test/native/unittest/mediadatashare_test/src/join_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/join_test.cpp index a8563cd9fbedc70f45bbf8b10c9cc7b28f2ccdf9..6b3b35c3ad5e6abeeb7d822f381d15846b8c2a30 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/join_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/join_test.cpp @@ -29,6 +29,14 @@ namespace DataShare { using namespace testing::ext; using namespace OHOS::Security::AccessToken; constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::string SLIENT_ACCESS_URI = "datashare:///com.acts.datasharetest?Proxy=true"; +std::string USER_URI = "datashare:///com.acts.datasharetest/entry/DB00/user?Proxy=true"; +std::string BOOK_URI = "datashare:///com.acts.datasharetest/entry/DB00/book?Proxy=true"; +std::string TBL_STU_NAME = "name"; +std::string TBL_STU_AGE = "age"; +std::shared_ptr g_slientAccessHelper; + class JoinTest : public testing::Test { public: static void SetUpTestCase(void); @@ -38,20 +46,9 @@ public: static void InsertUserDates(); static void InsertBookDates(); int ResultSize(std::shared_ptr &resultSet); - -protected: - static constexpr const char *DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; - static constexpr const char *SLIENT_ACCESS_URI = "datashare:///com.acts.datasharetest?Proxy=true"; - static constexpr const char *USER_URI = "datashare:///com.acts.datasharetest/entry/DB00/user?Proxy=true"; - static constexpr const char *BOOK_URI = "datashare:///com.acts.datasharetest/entry/DB00/book?Proxy=true"; - static std::shared_ptr CreateDataShareHelper(int32_t saId, std::string uri); - static std::shared_ptr g_slientAccessHelper; - std::string TBL_STU_NAME = "name"; - std::string TBL_STU_AGE = "age"; }; -std::shared_ptr JoinTest::g_slientAccessHelper; -std::shared_ptr JoinTest::CreateDataShareHelper(int32_t saId, std::string uri) +std::shared_ptr CreateDataShareHelper(int32_t systemAbilityId, std::string uri) { LOG_INFO("CreateDataShareHelper start"); auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); @@ -59,8 +56,8 @@ std::shared_ptr JoinTest::CreateDataShareHelper(int3 LOG_ERROR("GetSystemAbilityManager get samgr failed."); return nullptr; } - auto remoteObj = saManager->GetSystemAbility(saId); - while (remoteObj == nullptr) { + auto remoteObj = saManager->GetSystemAbility(systemAbilityId); + if (remoteObj == nullptr) { LOG_ERROR("GetSystemAbility service failed."); return nullptr; } @@ -207,6 +204,21 @@ int JoinTest::ResultSize(std::shared_ptr &resultSet) return count; } +/** +* @tc.name: Join_CrossJoin_001 +* @tc.desc: Verify cross join operation returns correct results +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create cross join predicate with "user.userId = book.userId" condition + 2. Execute query on user table with join predicate + 3. Verify row count is 3 + 4. Check first row data matches expected values +* @tc.experct: + 1. Query returns 3 rows + 2. First row contains correct user and book data for userId = 1 +*/ HWTEST_F(JoinTest, Join_CrossJoin_001, TestSize.Level0) { auto helper = g_slientAccessHelper; @@ -256,6 +268,22 @@ HWTEST_F(JoinTest, Join_CrossJoin_001, TestSize.Level0) EXPECT_EQ(1, userId_1); } +/** +* @tc.name: Join_InnerJoin_001 +* @tc.require: None +* @tc.desc: Verify inner join with filter returns correct single result +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create inner join predicate with "user.userId = book.userId" condition + 2. Add filter for book.name = "SanGuo" + 3. Execute query on user table with join predicate + 4. Verify row count is 1 + 5. Check row data matches expected values for "SanGuo" book +* @tc.experct: + 1. Query returns 1 row + 2. Row contains correct user and book data for "SanGuo" book +*/ HWTEST_F(JoinTest, Join_InnerJoin_001, TestSize.Level0) { auto helper = g_slientAccessHelper; @@ -306,6 +334,22 @@ HWTEST_F(JoinTest, Join_InnerJoin_001, TestSize.Level0) EXPECT_EQ(1, userId_1); } +/** +* @tc.name: Join_LeftOuterJoin_001 +* @tc.desc: Verify left outer join with Using clause returns correct result +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create left outer join predicate using "userId" column + 2. Add filter for name = "SanGuo" + 3. Execute query on user table with join predicate + 4. Verify row count is 1 + 5. Check row data matches expected values +* @tc.experct: + 1. Query returns 1 row + 2. Row contains correct user and book data for matching record +*/ HWTEST_F(JoinTest, Join_LeftOuterJoin_001, TestSize.Level0) { auto helper = g_slientAccessHelper; @@ -352,6 +396,20 @@ HWTEST_F(JoinTest, Join_LeftOuterJoin_001, TestSize.Level0) EXPECT_EQ("SanGuo", name); } +/** +* @tc.name: Join_LeftOuterJoin_002 +* @tc.desc: Verify left outer join returns all user records with matching books +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create left outer join predicate with "user.userId = book.userId" condition + 2. Execute query on user table with join predicate + 3. Verify row count is 5 (all users including those without books) +* @tc.experct: + 1. Query returns 5 rows + 2. All user records are included in results +*/ HWTEST_F(JoinTest, Join_LeftOuterJoin_002, TestSize.Level0) { auto helper = g_slientAccessHelper; 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 93ffe659e9ad26b41ff3258d95a48efcab1ce356..99b69215aaadc7d30480dd600533f8b30b7c6cc7 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 @@ -249,6 +249,18 @@ void MediaDataShareUnitTest::TearDownTestCase(void) void MediaDataShareUnitTest::SetUp(void) {} void MediaDataShareUnitTest::TearDown(void) {} +/** +* @tc.name: MediaDataShare_Predicates_Test_001 +* @tc.desc: Verify query with Equals and Limit predicates returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with Equals("name", "dataShareTest003") and Limit(1, 0) + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 1 row +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_001::Start"); @@ -267,6 +279,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_001, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_001, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_002 +* @tc.desc: Verify query with NotEqualTo predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with NotEqualTo("name", "dataShareTest003") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 2 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_002, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_002::Start"); @@ -284,6 +308,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_002, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_002, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_003 +* @tc.desc: Verify query with Contains predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with Contains("name", "dataShareTest") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 3 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_003, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_003::Start"); @@ -301,6 +337,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_003, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_003, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_004 +* @tc.desc: Verify query with BeginsWith predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with BeginsWith("name", "dataShare") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 3 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_004, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_004::Start"); @@ -318,6 +366,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_004, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_004, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_005 +* @tc.desc: Verify query with EndsWith predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with EndsWith("name", "003") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 1 row +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_005, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_005::Start"); @@ -335,6 +395,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_005, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_005, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_006 +* @tc.desc: Verify query with IsNull predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with IsNull("name") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 0 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_006, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_006::Start"); @@ -352,6 +424,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_006, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_006, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_007 +* @tc.desc: Verify query with IsNotNull predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with IsNotNull("name") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 3 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_007, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_007::Start"); @@ -369,6 +453,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_007, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_007, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_008 +* @tc.desc: Verify query with Like predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with Like("name", "%Test003") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 1 row +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_008, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_008::Start"); @@ -386,6 +482,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_008, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_008, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_009 +* @tc.desc: Verify query with Glob predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with Glob("name", "dataShareTes?003") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 1 row +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_009, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_009::Start"); @@ -403,6 +511,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_009, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_009, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_010 +* @tc.desc: Verify query with Between predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with Between("age", "0", "999") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 1 row +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_010, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_010::Start"); @@ -420,6 +540,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_010, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_010, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_011 +* @tc.desc: Verify query with NotBetween predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with NotBetween("age", "0", "999") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 2 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_011, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_011::Start"); @@ -437,6 +569,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_011, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_011, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_012 +* @tc.desc: Verify query with GreaterThan predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with GreaterThan("age", 999) + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 2 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_012, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_012::Start"); @@ -454,6 +598,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_012, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_012, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_013 +* @tc.desc: Verify query with LessThan predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with LessThan("age", 1000) + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 1 row +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_013, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_013::Start"); @@ -471,6 +627,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_013, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_013, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_014 +* @tc.desc: Verify query with GreaterThanOrEqualTo predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with GreaterThanOrEqualTo("age", 1000) + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 2 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_014, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_014::Start"); @@ -488,6 +656,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_014, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_014, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_015 +* @tc.desc: Verify query with LessThanOrEqualTo predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with LessThanOrEqualTo("age", 1000) + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 2 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_015, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_015::Start"); @@ -505,6 +685,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_015, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_015, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_016 +* @tc.desc: Verify query with combined predicates (AND/OR) returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create complex predicates with nested conditions + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 1 row +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_016, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_016::Start"); @@ -527,6 +719,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_016, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_016, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_017 +* @tc.desc: Verify query with AND combined predicates returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates combining two EqualTo conditions with AND + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 1 row +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_017, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_017::Start"); @@ -544,6 +748,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_017, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_017, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_018 +* @tc.desc: Verify query with ascending order predicate returns correctly ordered results +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with OrderByAsc("age") + 2. Execute query with these predicates + 3. Check the name of the first row in results +* @tc.expected: First row contains name "dataShareTest005" +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_018, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_018::Start"); @@ -564,6 +780,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_018, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_018, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_019 +* @tc.desc: Verify query with descending order predicate returns correctly ordered results +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with OrderByDesc("phoneNumber") + 2. Execute query with these predicates + 3. Check the name of the first row in results +* @tc.expected: First row contains name "dataShareTest005" +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_019, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_019::Start"); @@ -584,6 +812,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_019, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_019, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_020 +* @tc.desc: Verify predicate setting mode can be set and retrieved correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create empty predicates + 2. Set setting mode to PREDICATES_METHOD + 3. Retrieve and check the setting mode +* @tc.expected: Retrieved setting mode matches PREDICATES_METHOD +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_020, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_020::Start"); @@ -594,6 +834,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_020, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_020, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_021 +* @tc.desc: Verify predicate operation list is correctly generated +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with Equals("name", "dataShareTest003") + 2. Retrieve the operation list + 3. Verify operation type and parameters +* @tc.expected: Operation list contains correct type and parameters +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_021, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_021::Start"); @@ -612,6 +864,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_021, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_021, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_022 +* @tc.desc: Verify where clause can be set and retrieved correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create empty predicates + 2. Set where clause to "`data2` > ?" + 3. Retrieve and verify the where clause +* @tc.expected: Retrieved where clause matches the set value +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_022, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_023::Start"); @@ -623,6 +887,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_022, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_023, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_023 +* @tc.desc: Verify where arguments can be set and retrieved correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create empty predicates + 2. Set where arguments with vector containing "-5" + 3. Retrieve and verify the where arguments +* @tc.expected: Retrieved where arguments match the set values +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_023, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_024::Start"); @@ -634,6 +910,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_023, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_024, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_024 +* @tc.desc: Verify order clause can be set and retrieved correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create empty predicates + 2. Set order clause to "data3" + 3. Retrieve and verify the order clause +* @tc.expected: Retrieved order clause matches the set value +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_024, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_025::Start"); @@ -645,6 +933,19 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_024, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_025, End"); } +/** +* @tc.name: MediaDataShare_ValuesBucket_Test_001 +* @tc.desc: Verify DataShareValuesBucket basic operations work correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create empty ValuesBucket and verify it's empty + 2. Add a value and verify it's no longer empty + 3. Retrieve and verify the value + 4. Clear the bucket and verify it's empty again +* @tc.expected: All operations work as expected with correct values +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ValuesBucket_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_ValuesBucket_Test_001::Start"); @@ -664,6 +965,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ValuesBucket_Test_001, TestSize. LOG_INFO("MediaDataShare_ValuesBucket_Test_001 End"); } +/** +* @tc.name: MediaDataShare_ValueObject_Test_001 +* @tc.desc: Verify DataShareValueObject handles various data types correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create ValueObjects with different data types (int, int64, double, bool, vector) + 2. Verify copy and move operations + 3. Check that retrieved values match original values +* @tc.expected: All value types are stored and retrieved correctly +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ValueObject_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_ValueObject_Test_001::Start"); @@ -704,6 +1017,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ValueObject_Test_001, TestSize.L LOG_INFO("MediaDataShare_ValueObject_Test_001 End"); } +/** +* @tc.name: MediaDataShare_batchInsert_Test_001 +* @tc.desc: Verify batch insert operation correctly inserts multiple records +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create two ValuesBuckets with test data + 2. Perform batch insert with these buckets + 3. Verify the number of inserted records +* @tc.expected: Batch insert returns 2 indicating successful insertion of both records +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_batchInsert_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_batchInsert_Test_001::Start"); @@ -724,6 +1049,17 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_batchInsert_Test_001, TestSize.L LOG_INFO("MediaDataShare_batchInsert_Test_001 End"); } +/** +* @tc.name: MediaDataShare_NormalizeUri_Test_001 +* @tc.desc: Verify URI normalization function works correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Call NormalizeUri with media library URI + 2. Compare result with expected normalized URI +* @tc.expected: Normalized URI matches the expected value +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_NormalizeUri_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_NormalizeUri_Test_001::Start"); @@ -735,6 +1071,17 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_NormalizeUri_Test_001, TestSize. LOG_INFO("MediaDataShare_NormalizeUri_Test_001 End"); } +/** +* @tc.name: MediaDataShare_DenormalizeUri_Test_001 +* @tc.desc: Verify URI denormalization function works correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Call DenormalizeUri with media library URI + 2. Compare result with expected denormalized URI +* @tc.expected: Denormalized URI matches the expected value +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_DenormalizeUri_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_DenormalizeUri_Test_001::Start"); @@ -746,6 +1093,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_DenormalizeUri_Test_001, TestSiz LOG_INFO("MediaDataShare_DenormalizeUri_Test_001 End"); } +/** +* @tc.name: MediaDataShare_SingleValue_Test_001 +* @tc.desc: Verify SingleValue handles various data types correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create SingleValue objects with different data types + 2. Verify copy and move operations + 3. Check that retrieved values match original values +* @tc.expected: All value types are stored and retrieved correctly +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_SingleValue_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_SingleValue_Test_001::Start"); @@ -784,6 +1143,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_SingleValue_Test_001, TestSize.L LOG_INFO("MediaDataShare_SingleValue_Test_001 End"); } +/** +* @tc.name: MediaDataShare_MutliValue_Test_001 +* @tc.desc: Verify MutliValue handles various collection types correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create MutliValue objects with different collection types + 2. Verify copy and move operations + 3. Check that retrieved values match original values +* @tc.expected: All collections are stored and retrieved correctly +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_MutliValue_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_MutliValue_Test_001::Start"); @@ -821,6 +1192,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_MutliValue_Test_001, TestSize.Le LOG_INFO("MediaDataShare_MutliValue_Test_001 End"); } +/** +* @tc.name: MediaDataShare_ResultSet_Test_001 +* @tc.desc: Verify default ResultSet behavior with no data +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create empty ResultSet + 2. Attempt various operations (get columns, row count, move to row, get values) + 3. Verify operations return appropriate error codes +* @tc.expected: All operations on empty ResultSet return errors +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_ResultSet_Test_005::Start"); @@ -854,6 +1237,19 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_001, TestSize.Lev LOG_INFO("MediaDataShare_ResultSet_Test_005, End"); } +/** +* @tc.name: MediaDataShare_ResultSet_Test_002 +* @tc.require: None +* @tc.desc: Verify ResultSet column operations work correctly +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Query data for "dataShareTest003" + 2. Verify column name retrieval + 3. Check blob retrieval from result set + 4. Verify all column names can be retrieved +* @tc.expected: All column operations return valid results +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_002, TestSize.Level0) { LOG_INFO("MediaDataShare_ResultSet_Test_002::Start"); @@ -885,6 +1281,19 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_002, TestSize.Lev LOG_INFO("MediaDataShare_ResultSet_Test_002, End"); } +/** +* @tc.name: MediaDataShare_ResultSet_Test_003 +* @tc.desc: Verify ResultSet block operations work correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Query data for "dataShareTest003" + 2. Check if result set has a block + 3. Retrieve, set and fill block + 4. Verify block operations maintain correct reference +* @tc.expected: All block operations work as expected +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_003, TestSize.Level0) { LOG_INFO("MediaDataShare_ResultSet_Test_003::Start"); @@ -909,6 +1318,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_003, TestSize.Lev LOG_INFO("MediaDataShare_ResultSet_Test_003, End"); } +/** +* @tc.name: MediaDataShare_ResultSet_Test_004 +* @tc.desc: Verify ResultSet navigation works correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Query data with names containing "dataShareTest" + 2. Move to first row + 3. Attempt navigation with OnGo method +* @tc.expected: Navigation operation returns true indicating success +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_004, TestSize.Level0) { LOG_INFO("MediaDataShare_ResultSet_Test_004::Start"); @@ -927,6 +1348,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_004, TestSize.Lev LOG_INFO("MediaDataShare_ResultSet_Test_004, End"); } +/** +* @tc.name: MediaDataShare_ResultSet_Test_005 +* @tc.desc: Verify empty ResultSet operations return appropriate errors +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create empty ResultSet + 2. Attempt various operations without data + 3. Verify error codes and return values +* @tc.expected: All operations on empty ResultSet return errors +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_005, TestSize.Level0) { LOG_INFO("MediaDataShare_ResultSet_Test_005::Start"); @@ -957,6 +1390,19 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_005, TestSize.Lev LOG_INFO("MediaDataShare_ResultSet_Test_005, End"); } +/** +* @tc.name: MediaDataShare_ResultSet_Test_006 +* @tc.desc: Verify ResultSet data type and value retrieval +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Insert test data with specific age value + 2. Query for the inserted data + 3. Verify data type and value match expectations + 4. Clean up test data +* @tc.expected: Data type is INTEGER and retrieved value matches inserted value +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_006, TestSize.Level0) { LOG_INFO("MediaDataShare_ResultSet_Test_006::Start"); @@ -991,6 +1437,17 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_006, TestSize.Lev LOG_INFO("MediaDataShare_ResultSet_Test_006, End"); } +/** +* @tc.name: Creator_IRemoteObjectNull_Test_001 +* @tc.desc: Verify Creator handles null remote object correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Attempt to create DataShareHelper with null IRemoteObject + 2. Check if returned helper is null +* @tc.expected: Creator returns nullptr when remote object is null +*/ HWTEST_F(MediaDataShareUnitTest, Creator_IRemoteObjectNull_Test_001, TestSize.Level0) { LOG_INFO("Creator_IRemoteObjectNull_Test_001::Start"); @@ -1000,6 +1457,18 @@ HWTEST_F(MediaDataShareUnitTest, Creator_IRemoteObjectNull_Test_001, TestSize.Le LOG_INFO("Creator_IRemoteObjectNull_Test_001 End"); } +/** +* @tc.name: Creator_UriError_Test_001 +* @tc.desc: Verify Creator handles invalid URI correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get valid remote object from system ability manager + 2. Attempt to create DataShareHelper with invalid URI + 3. Check if returned helper is null +* @tc.expected: Creator returns nullptr when URI is invalid +*/ HWTEST_F(MediaDataShareUnitTest, Creator_UriError_Test_001, TestSize.Level0) { LOG_INFO("Creator_UriError_Test_001::Start"); @@ -1012,6 +1481,19 @@ HWTEST_F(MediaDataShareUnitTest, Creator_UriError_Test_001, TestSize.Level0) LOG_INFO("Creator_UriError_Test_001 End"); } +/** +* @tc.name: Insert_ConnectionNull_Test_001 +* @tc.desc: Verify operations fail correctly when connection is released +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create DataShareHelper and immediately release it + 2. Attempt insert operation with released connection + 3. Attempt get type operation + 4. Verify error results +* @tc.expected: Insert returns -1 and GetType returns empty string +*/ HWTEST_F(MediaDataShareUnitTest, Insert_ConnectionNull_Test_001, TestSize.Level0) { LOG_INFO("Insert_ConnectionNull_Test_001::Start"); @@ -1037,6 +1519,23 @@ HWTEST_F(MediaDataShareUnitTest, Insert_ConnectionNull_Test_001, TestSize.Level0 LOG_INFO("Insert_ConnectionNull_Test_001 End"); } +/** +* @tc.name: MediaDataShare_CRUD_Test_001 +* @tc.desc: Verify basic CRUD operations (Create, Read, Update, Delete) work correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Insert a new record with name "Datashare_CRUD_Test001" + 2. Update the record to name "Datashare_CRUD_Test002" using predicates + 3. Query for the updated record to verify the change + 4. Delete the record using predicates +* @tc.expected: + 1.Insert returns a positive ID indicating success + 2.Update returns non-negative value indicating success + 3.Query returns exactly 1 row for the updated record + 4.Delete returns non-negative value indicating success +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_CRUD_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_CRUD_Test_001::Start"); @@ -1073,6 +1572,23 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_CRUD_Test_001, TestSize.Level0) LOG_INFO("MediaDataShare_CRUD_Test_001, End"); } +/** +* @tc.name: MediaDataShare_CRUDEX_Test_001 +* @tc.desc: Verify extended CRUD operations with error code returns work correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Insert a new record using InsertEx and verify error code and return value + 2. Update the record using UpdateEx with predicates and verify results + 3. Query for the updated record to confirm changes + 4. Delete the record using DeleteEx and verify results +* @tc.expected: + 1.InsertEx returns error code 0 and non-negative ID + 2.UpdateEx returns error code 0 and non-negative affected rows + 3.Query returns exactly 1 row for the updated record + 4.DeleteEx returns error code 0 and non-negative affected rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_CRUDEX_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_CRUDEX_Test_001::Start"); @@ -1110,6 +1626,22 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_CRUDEX_Test_001, TestSize.Level0 LOG_INFO("MediaDataShare_CRUDEX_Test_001, End"); } +/** +* @tc.name: MediaDataShare_ImplPredicates_Test_001 +* @tc.desc: Verify In predicate generates correct operation items +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with In("name", {1, 2, 3}) condition + 2. Retrieve the operation items from predicates + 3. Verify operation type, parameters, and values +* @tc.expected: + 1.Exactly 1 operation item is generated + 2.Operation type is correct for In condition + 3.Parameters contain "name" and the correct integer values + 4.Variant indices match expected types (string and integer vector) +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ImplPredicates_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_ImplPredicates_Test_001::Start"); @@ -1124,7 +1656,8 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ImplPredicates_Test_001, TestSiz std::string str = std::get(operationItems[0].singleParams[0]); std::vector ret = std::get>(operationItems[0].multiParams[0]); EXPECT_EQ(operationItems.size(), 1); - EXPECT_EQ(operationItems[0].singleParams[0].index(), 4); + // index of variant, 3 is string + EXPECT_EQ(operationItems[0].singleParams[0].index(), 3); EXPECT_EQ(str, "name"); EXPECT_EQ(operationItems[0].multiParams[0].index(), 1); for (int i = 0; i < ret.size(); i++) { @@ -1134,6 +1667,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ImplPredicates_Test_001, TestSiz LOG_INFO("MediaDataShare_ImplPredicates_Test_001, End"); } +/** +* @tc.name: MediaDataShare_NotImplPredicates_Test_001 +* @tc.desc: Verify multiple predicate combinations generate correct number of operation items +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with multiple conditions: In, NotIn, Unlike, GroupBy, Distinct, IndexedBy, KeyPrefix, InKeys + 2. Retrieve the operation items from predicates + 3. Verify the total number of operation items +* @tc.expected: Exactly 8 operation items are generated matching the number of conditions +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_NotImplPredicates_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_NotImplPredicates_Test_001::Start"); @@ -1162,30 +1707,119 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_NotImplPredicates_Test_001, Test LOG_INFO("MediaDataShare_NotImplPredicates_Test_001, End"); } +/** +* @tc.name: MediaDataShare_Observer_001 +* @tc.desc: Verify normal registration and operation of non-silent data observer +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Register a data observer for the media library URI + 2. Insert a new record and trigger notification + 3. Delete the record and trigger notification + 4. Unregister the observer +* @tc.expected: + 1.Registration returns 0 indicating success + 2.Insert returns positive ID and notification is triggered + 3.Delete returns positive value and notification is triggered + 4.Unregistration returns 0 indicating success +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Observer_001, TestSize.Level0) { LOG_INFO("MediaDataShare_Observer_001 start"); std::shared_ptr helper = g_dataShareHelper; ASSERT_TRUE(helper != nullptr); Uri uri(MEDIALIBRARY_DATA_URI); - sptr dataObserver; - helper->RegisterObserver(uri, dataObserver); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + int retVal = helper->RegisterObserver(uri, dataObserver); + EXPECT_EQ(retVal, 0); DataShare::DataShareValuesBucket valuesBucket; valuesBucket.Put("name", "Datashare_Observer_Test001"); - int retVal = helper->Insert(uri, valuesBucket); - EXPECT_EQ((retVal > 0), true); + retVal = helper->Insert(uri, valuesBucket); + EXPECT_GT(retVal, 0); helper->NotifyChange(uri); DataShare::DataSharePredicates deletePredicates; deletePredicates.EqualTo("name", "Datashare_Observer_Test001"); retVal = helper->Delete(uri, deletePredicates); - EXPECT_EQ((retVal >= 0), true); + EXPECT_GT(retVal, 0); helper->NotifyChange(uri); - helper->UnregisterObserver(uri, dataObserver); + retVal = helper->UnregisterObserver(uri, dataObserver); + EXPECT_EQ(retVal, 0); LOG_INFO("MediaDataShare_Observer_001 end"); } +/** +* @tc.name: MediaDataShare_ReregisterObserver_001 +* @tc.desc: Verify error handling when re-registering an existing observer +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Register a data observer for the media library URI + 2. Attempt to register the same observer again + 3. Perform insert and delete operations with notifications + 4. Unregister the observer +* @tc.expected: + 1.First registration returns 0 indicating success + 2.Second registration returns E_REGISTER_ERROR + 3.Insert and delete operations complete successfully + 4.Unregistration returns 0 indicating success +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ReregisterObserver_001, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_ReregisterObserver_001 start"); + std::shared_ptr helper = g_dataShareHelper; + EXPECT_NE(helper, nullptr); + Uri uri(MEDIALIBRARY_DATA_URI); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + int retVal = helper->RegisterObserver(uri, dataObserver); + EXPECT_EQ(retVal, 0); + retVal = helper->RegisterObserver(uri, dataObserver); + EXPECT_EQ(retVal, E_REGISTER_ERROR); + + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put("name", "MediaDataShare_ReregisterObserver_001"); + retVal = helper->Insert(uri, valuesBucket); + EXPECT_GT(retVal, 0); + helper->NotifyChange(uri); + + DataShare::DataSharePredicates deletePredicates; + deletePredicates.EqualTo("name", "MediaDataShare_ReregisterObserver_001"); + retVal = helper->Delete(uri, deletePredicates); + EXPECT_GT(retVal, 0); + helper->NotifyChange(uri); + retVal = helper->UnregisterObserver(uri, dataObserver); + EXPECT_EQ(retVal, 0); + LOG_INFO("MediaDataShare_ReregisterObserver_001 end"); +} + +/** +* @tc.name: MediaDataShare_ObserverExt_001 +* @tc.desc: Verify observer extension functionality for data change notifications +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: DataShareHelper instance is properly initialized and MEDIALIBRARY_DATA_URI is accessible +* @tc.step: + 1. Get DataShareHelper instance and verify it's not null + 2. Create test URI and DataShareObserverTest instance + 3. Register observer extension with the URI + 4. Insert test data and notify INSERT change + 5. Verify observer receives correct INSERT change information + 6. Insert data to descendant URI and notify INSERT change + 7. Verify observer receives correct descendant INSERT change information + 8. Delete test data and notify DELETE change with additional data + 9. Verify observer receives correct DELETE change information + 10. Unregister the observer +* @tc.expect: + 1. DataShareHelper instance is successfully obtained + 2. Test data is inserted successfully (retVal > 0) + 3. Observer receives accurate INSERT change information for main URI + 4. Observer receives accurate INSERT change information for descendant URI + 5. Observer receives accurate DELETE change information including additional data + 6. All operations complete without errors +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_001, TestSize.Level0) { LOG_INFO("MediaDataShare_ObserverExt_001 start"); @@ -1231,6 +1865,28 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_001, TestSize.Level0 LOG_INFO("MediaDataShare_ObserverExt_001 end"); } +/** +* @tc.name: MediaDataShare_UnregisterObserverExt_001 +* @tc.desc: Verify unregister functionality of observer extension +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: DataShareHelper instance is properly initialized and MEDIALIBRARY_DATA_URI is accessible +* @tc.step: + 1. Get DataShareHelper instance and verify it's not null + 2. Create test URI and DataShareObserverTest instance + 3. Register observer extension with the URI + 4. Insert test data and notify INSERT change + 5. Verify observer receives correct change information + 6. Unregister the observer from the URI + 7. Notify another DELETE change + 8. Verify observer no longer receives change information +* @tc.expect: + 1. DataShareHelper instance is successfully obtained + 2. Test data is inserted successfully (retVal > 0) + 3. Observer receives accurate change information before unregistration + 4. After unregistration, observer does NOT receive change notifications + 5. All operations complete without errors +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_UnregisterObserverExt_001, TestSize.Level0) { LOG_INFO("MediaDataShare_UnregisterObserverExt_001 start"); @@ -1260,6 +1916,22 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_UnregisterObserverExt_001, TestS LOG_INFO("MediaDataShare_UnregisterObserverExt_001 end"); } +/** +* @tc.name: MediaDataShare_ToAbsSharedResultSet_Test_001 +* @tc.desc: Test conversion of DataShare query result to AbsSharedResultSet +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance + 2. Create predicates to filter data by name "dataShareTest003" + 3. Query the media library URI with the predicates and empty columns + 4. Convert the query result to AbsSharedResultSet using RdbDataAbilityUtils + 5. Get the row count from the converted result set +* @tc.expect: + 1.The converted AbsSharedResultSet is not null + 2.The row count of the result set is 1 (matches the expected test data) +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ToAbsSharedResultSet_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_ToAbsSharedResultSet_Test_001::Start"); @@ -1279,6 +1951,20 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ToAbsSharedResultSet_Test_001, T LOG_INFO("MediaDataShare_ToAbsSharedResultSet_Test_001 End"); } +/** +* @tc.name: MediaDataShare_ExecuteBatch_Test_001 +* @tc.desc: Test batch execution of INSERT and DELETE operations via DataShare helper +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance + 2. Create an INSERT operation statement with test data and predicates + 3. Create a DELETE operation statement with test data and predicates + 4. Add both statements to a batch list + 5. Execute the batch operation using helper->ExecuteBatch() +* @tc.expect: Batch execution returns 0 (success status) +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ExecuteBatch_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_ExecuteBatch_Test_001::Start"); @@ -1314,6 +2000,19 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ExecuteBatch_Test_001, TestSize. LOG_INFO("MediaDataShare_ExecuteBatch_Test_001 End"); } +/** +* @tc.name: MediaDataShare_InsertExt_Test_001 +* @tc.desc: Test extended insertion functionality (InsertExt) of DataShare helper +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance and verify it is not null + 2. Create a URI for media library data + 3. Create a ValuesBucket with test data (name="Datashare_CRUD_Test001") + 4. Call InsertExt with the URI, ValuesBucket, and result string +* @tc.expect: InsertExt returns 0 (success status) +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_InsertExt_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_InsertExt_Test_001::Start"); @@ -1328,6 +2027,22 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_InsertExt_Test_001, TestSize.Lev LOG_INFO("MediaDataShare_InsertExt_Test_001 End"); } +/** +* @tc.name: MediaDataShare_TransferUri_Test_001 +* @tc.desc: Test URI transfer functionality and DataShare helper creation for file data URI +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a file data URI + 2. Get the SystemAbilityManager instance and verify it is not null + 3. Get the Storage Manager system ability remote object and verify it is not null + 4. Create a DataShare helper using the remote object and file data URI +* @tc.expect: + 1.SystemAbilityManager instance is not null + 2.Storage Manager remote object is not null + 3.DataShare helper instance is successfully created (not null) +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_TransferUri_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_TransferUri_Test_001::Start"); @@ -1348,6 +2063,19 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_TransferUri_Test_001, TestSize.L LOG_INFO("MediaDataShare_TransferUri_Test_001 End"); } +/** +* @tc.name: ControllerTest_HelperInsertExtControllerNullTest_001 +* @tc.desc: Test InsertExt operation when DataShare controller is released (null) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Create a test URI and release the helper's controller + 3. Create a ValuesBucket with test data (phoneNumber=20.07, name="dataShareTest003", age=1001) + 4. Call InsertExt with the URI, ValuesBucket, and result string +* @tc.expect: InsertExt returns a negative value (failure due to released controller) +*/ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperInsertExtControllerNullTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_HelperInsertExtControllerNullTest_001::Start"); @@ -1367,6 +2095,20 @@ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperInsertExtControllerNullTes LOG_INFO("ControllerTest_HelperInsertExtControllerNullTest_001::End"); } +/** +* @tc.name: ControllerTest_HelperUpdateControllerNullTest_001 +* @tc.desc: Test Update operation when DataShare controller is released (null) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Create a test URI and release the helper's controller + 3. Create predicates to filter data by name "Datashare_CRUD_Test001" + 4. Create a ValuesBucket to update name to "Datashare_CRUD_Test002" + 5. Call Update with the URI, predicates, and ValuesBucket +* @tc.expect: Update returns a negative value (failure due to released controller) +*/ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperUpdateControllerNullTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_HelperUpdateControllerNullTest_001::Start"); @@ -1383,6 +2125,19 @@ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperUpdateControllerNullTest_0 LOG_INFO("ControllerTest_HelperUpdateControllerNullTest_001::End"); } +/** +* @tc.name: ControllerTest_HelperDeleteControllerNullTest_001 +* @tc.desc: Test Delete operation when DataShare controller is released (null) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Create a test URI and release the helper's controller + 3. Create predicates to filter data by age=1112 + 4. Call Delete with the URI and predicates +* @tc.expect: Delete returns a negative value (failure due to released controller) +*/ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperDeleteControllerNullTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_HelperDeleteControllerNullTest_001::Start"); @@ -1397,6 +2152,19 @@ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperDeleteControllerNullTest_0 LOG_INFO("ControllerTest_HelperDeleteControllerNullTest_001::End"); } +/** +* @tc.name: ControllerTest_HelperQueryControllerNullTest_001 +* @tc.desc: Test Query operation when DataShare controller is released (null) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Create a test URI and release the helper's controller + 3. Create predicates to filter data by name "dataShareTest003" with limit 1 + 4. Call Query with the URI, predicates, and empty columns +* @tc.expect: Query returns a null result set (failure due to released controller) +*/ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperQueryControllerNullTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_HelperQueryControllerNullTest_001::Start"); @@ -1413,6 +2181,20 @@ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperQueryControllerNullTest_00 LOG_INFO("ControllerTest_HelperQueryControllerNullTest_001::End"); } +/** +* @tc.name: ControllerTest_HelperBatchInsertControllerNullTest_001 +* @tc.desc: Test BatchInsert operation when DataShare controller is released (null) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Create a test URI and release the helper's controller + 3. Create two ValuesBuckets with test data (name and phoneNumber) + 4. Add both buckets to a batch list + 5. Call BatchInsert with the URI and batch list +* @tc.expect: BatchInsert returns a negative value (failure due to released controller) +*/ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperBatchInsertControllerNullTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_HelperBatchInsertControllerNullTest_001::Start"); @@ -1434,6 +2216,21 @@ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperBatchInsertControllerNullT LOG_INFO("ControllerTest_HelperBatchInsertControllerNullTest_001::End"); } +/** +* @tc.name: ControllerTest_HelperExecuteBatchControllerNullTest_001 +* @tc.desc: Test ExecuteBatch operation when DataShare controller is released (null) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Create a test URI and release the helper's controller + 3. Create an INSERT operation statement with test data and predicates + 4. Create a DELETE operation statement with test data and predicates + 5. Add both statements to a batch list + 6. Call ExecuteBatch with the batch list and result set +* @tc.expect: ExecuteBatch returns a negative value (failure due to released controller) +*/ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperExecuteBatchControllerNullTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_HelperExecuteBatchControllerNullTest_001::Start"); @@ -1471,6 +2268,28 @@ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperExecuteBatchControllerNull LOG_INFO("ControllerTest_HelperExecuteBatchControllerNullTest_001::End"); } +/** +* @tc.name: ControllerTest_HelperRegisterObserverControllerNullTest_001 +* @tc.desc: Test RegisterObserver, Insert, NotifyChange, Delete +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Create a media library URI and release the helper's controller + 3. Create an IDataAbilityObserverTest instance + 4. Call RegisterObserver with the URI and observer, check the return value + 5. Insert test data into the URI and check the return value + 6. Notify a change for the URI + 7. Delete the test data using predicates and check the return value + 8. Notify a change again for the URI + 9. Call UnregisterObserver with the URI and observer, check the return value +* @tc.expect: + 1.RegisterObserver returns E_HELPER_DIED + 2.Insert returns a negative value (failure) + 3.Delete returns a negative value (failure) + 4.UnregisterObserver returns E_HELPER_DIED +*/ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperRegisterObserverControllerNullTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_HelperRegisterObserverControllerNullTest_001 start"); @@ -1478,12 +2297,13 @@ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperRegisterObserverController ASSERT_TRUE(helper != nullptr); Uri uri(MEDIALIBRARY_DATA_URI); helper->Release(); - sptr dataObserver; - helper->RegisterObserver(uri, dataObserver); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + int retVal = helper->RegisterObserver(uri, dataObserver); + EXPECT_EQ(retVal, E_HELPER_DIED); DataShare::DataShareValuesBucket valuesBucket; valuesBucket.Put("name", "Datashare_Observer_Test001"); - int retVal = helper->Insert(uri, valuesBucket); + retVal = helper->Insert(uri, valuesBucket); EXPECT_EQ((retVal < 0), true); helper->NotifyChange(uri); @@ -1492,10 +2312,30 @@ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperRegisterObserverController retVal = helper->Delete(uri, deletePredicates); EXPECT_EQ((retVal < 0), true); helper->NotifyChange(uri); - helper->UnregisterObserver(uri, dataObserver); + retVal = helper->UnregisterObserver(uri, dataObserver); + EXPECT_EQ(retVal, E_HELPER_DIED); LOG_INFO("ControllerTest_HelperRegisterObserverControllerNullTest_001 end"); } +/** +* @tc.name: MediaDataShare_ObserverExt_002 +* @tc.desc: Test DataShare observer extension for batch INSERT operation notification with extended data +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance and verify it is not null + 2. Create a media library URI and a DataShareObserverTest instance + 3. Register the observer extension with the URI + 4. Create two ValuesBuckets with test data and batch insert them + 5. Convert the batch data to extended format for change info + 6. Notify an INSERT change with the extended data + 7. Wait for observer notification and verify the change info matches + 8. Unregister the observer extension +* @tc.expect: + 1.Batch insertion returns a positive value (success) + 2.Observer correctly receives and matches INSERT change info with extended data +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_002, TestSize.Level0) { LOG_INFO("MediaDataShare_ObserverExt_002 start"); @@ -1524,6 +2364,26 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_002, TestSize.Level0 LOG_INFO("MediaDataShare_ObserverExt_002 end"); } +/** +* @tc.name: MediaDataShare_ObserverExt_003 +* @tc.desc: Test DataShare observer extension for UPDATE operation notification with extended data +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance and verify it is not null + 2. Create a media library URI and a DataShareObserverTest instance + 3. Register the observer extension with the URI + 4. Create a ValuesBucket with update data (name="Datashare_Observer_Test003") + 5. Update existing data filtered by predicates (name="Datashare_Observer_Test002") + 6. Convert the update data to extended format for change info + 7. Notify an UPDATE change with the extended data + 8. Wait for observer notification and verify the change info matches + 9. Unregister the observer extension +* @tc.expect: + 1.Update operation returns a positive value (success) + 2.Observer correctly receives and matches UPDATE change info with extended data +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_003, TestSize.Level0) { LOG_INFO("MediaDataShare_ObserverExt_003 start"); @@ -1552,6 +2412,26 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_003, TestSize.Level0 LOG_INFO("MediaDataShare_ObserverExt_003 end"); } +/** +* @tc.name: MediaDataShare_ObserverExt_004 +* @tc.desc: Test DataShare observer extension for DELETE operation notification with extended data +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance and verify it is not null + 2. Create a media library URI and a DataShareObserverTest instance + 3. Register the observer extension with the URI + 4. Create predicates to filter data by name "Datashare_Observer_Test003" + 5. Delete the filtered data and verify success + 6. Convert the deleted data info to extended format for change info + 7. Notify a DELETE change with the extended data + 8. Wait for observer notification and verify the change info matches + 9. Unregister the observer extension +* @tc.expect: + 1.Delete operation returns a positive value (success) + 2.Observer correctly receives and matches DELETE change info with extended data +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_004, TestSize.Level0) { LOG_INFO("MediaDataShare_ObserverExt_004 start"); @@ -1580,6 +2460,26 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_004, TestSize.Level0 LOG_INFO("MediaDataShare_ObserverExt_004 end"); } +/** +* @tc.name: MediaDataShare_UnregisterObserverExt_002 +* @tc.desc: Test that unregistered DataShare observer no longer receives notifications with extended data +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance and verify it is not null + 2. Create a media library URI and a DataShareObserverTest instance + 3. Register the observer extension with the URI + 4. Insert test data into the URI and verify success + 5. Convert the inserted data to extended format, notify an INSERT change, and verify observer receives it + 6. Unregister the observer extension + 7. Notify a DELETE change with the same extended data + 8. Wait for observer notification and verify the change info does not match +* @tc.expect: + 1.Data insertion returns a positive value (success) + 2.Registered observer correctly receives INSERT change info with extended data + 3.Unregistered observer does not receive DELETE change info (change info mismatch) +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_UnregisterObserverExt_002, TestSize.Level0) { LOG_INFO("MediaDataShare_UnregisterObserverExt_002 start"); @@ -1612,6 +2512,27 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_UnregisterObserverExt_002, TestS LOG_INFO("MediaDataShare_UnregisterObserverExt_002 end"); } +/** +* @tc.name: MediaDataShare_BatchUpdate_Test_001 +* @tc.desc: Test batch update functionality of DataShare helper with multiple operations and URIs +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance and verify it is not null + 2. Create a media library URI and insert test data (name="batchUpdateTest") + 3. Create batch update operations: + - For "uri1": Update existing test data to "batchUpdateTested"; Update non-existent data to "undefined1" + - For "uri2": Update non-existent data to "undefined1" + 4. Execute batch update and get results + 5. Delete the test data to clean up +* @tc.expect: + 1.Initial insertion returns a positive value (success) + 2.Batch update returns success, with results size 2 + 3.Results for "uri1" contain [1, 0] (1 success, 1 no match) + 4.Results for "uri2" contain [0] (no match) + 5.Cleanup deletion returns a positive value (success) +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_BatchUpdate_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_BatchUpdate_Test_001::Start"); @@ -1652,6 +2573,21 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_BatchUpdate_Test_001, TestSize.L LOG_INFO("MediaDataShare_BatchUpdate_Test_001 End"); } +/** +* @tc.name: MediaDataShare_BatchUpdateThanLimit_Test_001 +* @tc.desc: Test batch update functionality when operation count exceeds the limit +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance and verify it is not null + 2. Create a media library URI + 3. Create a batch update operation list with 4001 identical update operations (exceeding limit) + 4. Execute batch update and check the return value and results +* @tc.expect: + 1.Batch update returns -1 (failure due to exceeding limit) + 2.Results list is empty +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_BatchUpdateThanLimit_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_BatchUpdateThanLimit_Test_001::Start"); @@ -1715,9 +2651,20 @@ void PrepareNodeContent(RdbChangeNode &node) /** * @tc.name: ReadAshmem -* @tc.desc: test ReadAshmem function. +* @tc.desc: Test ReadAshmem function for normal read operations and error scenarios * @tc.type: FUNC -* @tc.require: +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create an Ashmem instance and map it for read/write + 2. Write test data (string length and URI string) into Ashmem + 3. Use RdbObserverStub to read the length from Ashmem and verify it matches + 4. Read the URI string from Ashmem and verify it matches the original + 5. Test error path: attempt to read data exceeding Ashmem size +* @tc.expect: + 1.Normal read of length returns E_OK and matches written length + 2.Normal read of string returns E_OK and matches original URI + 3.Error read (exceeding size) returns E_ERROR */ HWTEST_F(MediaDataShareUnitTest, ReadAshmem, TestSize.Level1) { @@ -1760,9 +2707,18 @@ HWTEST_F(MediaDataShareUnitTest, ReadAshmem, TestSize.Level1) /** * @tc.name: DeserializeDataFromAshmem001 -* @tc.desc: test DeserializeDataFromAshmem function. +* @tc.desc: Test DeserializeDataFromAshmem function for successful data deserialization from Ashmem * @tc.type: FUNC -* @tc.require: +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Prepare an RdbChangeNode with Ashmem containing serialized data (2 URIs) using PrepareNodeContent + 2. Create an RdbObserverStub with OnChangeCallback + 3. Call DeserializeDataFromAshmem on the stub with the node + 4. Verify the deserialized data in the node +* @tc.expect: + 1.Deserialization returns E_OK + 2.Node contains 2 URIs, both matching DATA_SHARE_URI */ HWTEST_F(MediaDataShareUnitTest, DeserializeDataFromAshmem001, TestSize.Level1) { @@ -1782,9 +2738,16 @@ HWTEST_F(MediaDataShareUnitTest, DeserializeDataFromAshmem001, TestSize.Level1) /** * @tc.name: DeserializeDataFromAshmem002 -* @tc.desc: test DeserializeDataFromAshmem function, error tests. +* @tc.desc: Test DeserializeDataFromAshmem function for error scenarios (invalid Ashmem data) * @tc.type: FUNC -* @tc.require: +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Test with null Ashmem: call deserialization on a node with no memory_ + 2. Test with invalid string length: write Ashmem with excessive string length and call deserialization + 3. Test with insufficient size for vector length: create small Ashmem and call deserialization + 4. Test with insufficient size for string length: create Ashmem with partial data and call deserialization +* @tc.expect: All error scenarios return E_ERROR */ HWTEST_F(MediaDataShareUnitTest, DeserializeDataFromAshmem002, TestSize.Level1) { @@ -1842,9 +2805,21 @@ HWTEST_F(MediaDataShareUnitTest, DeserializeDataFromAshmem002, TestSize.Level1) /** * @tc.name: RecoverRdbChangeNodeData001 -* @tc.desc: test RecoverRdbChangeNodeData function +* @tc.desc: Test RecoverRdbChangeNodeData function for normal recovery and non-recovery scenarios * @tc.type: FUNC -* @tc.require: +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Prepare an RdbChangeNode with shared memory containing 2 URIs using PrepareNodeContent + 2. Create an RdbObserverStub with OnChangeCallback + 3. Call RecoverRdbChangeNodeData on the stub with the node and verify return value + 4. Check that node data is correctly recovered, memory is nullified, and size is 0 + 5. Prepare a second RdbChangeNode with shared memory but set isSharedMemory_ to false + 6. Call RecoverRdbChangeNodeData on the second node and verify return value + 7. Check that node data remains empty, memory is retained, and size is unchanged +* @tc.expect: + 1.First recovery returns E_OK, node contains 2 URIs, memory is null, size is 0, and isSharedMemory_ is false + 2.non-recovery returns E_OK, node data is empty, memory is not null, size is 82, and isSharedMemory_ is false */ HWTEST_F(MediaDataShareUnitTest, RecoverRdbChangeNodeData001, TestSize.Level0) { @@ -1880,9 +2855,18 @@ HWTEST_F(MediaDataShareUnitTest, RecoverRdbChangeNodeData001, TestSize.Level0) /** * @tc.name: RecoverRdbChangeNodeData002 -* @tc.desc: test RecoverRdbChangeNodeData function with error +* @tc.desc: Test RecoverRdbChangeNodeData function with error scenario (null shared memory) * @tc.type: FUNC -* @tc.require: +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create an RdbChangeNode with isSharedMemory_ set to true but no memory allocated + 2. Create an RdbObserverStub with OnChangeCallback + 3. Call RecoverRdbChangeNodeData on the stub with the node + 4. Verify the return value and node state after recovery +* @tc.expect: + 1.Recovery returns E_ERROR + 2.Node data is empty, memory is null, size is 0, and isSharedMemory_ is false */ HWTEST_F(MediaDataShareUnitTest, RecoverRdbChangeNodeData002, TestSize.Level0) { @@ -1902,9 +2886,18 @@ HWTEST_F(MediaDataShareUnitTest, RecoverRdbChangeNodeData002, TestSize.Level0) /** * @tc.name: OnChangeFromRdb001 -* @tc.desc: test OnChangeFromRdb function +* @tc.desc: Test OnChangeFromRdb function for normal data processing * @tc.type: FUNC -* @tc.require: +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Prepare an RdbChangeNode with shared memory containing 2 URIs using PrepareNodeContent + 2. Create an RdbObserverStub with OnChangeCallback + 3. Call OnChangeFromRdb on the stub with the node + 4. Verify the node's data, memory, size, and isSharedMemory_ state +* @tc.expect: + 1.Node contains 2 URIs matching DATA_SHARE_URI + 2.Node memory is null, size is 0, and isSharedMemory_ is false */ HWTEST_F(MediaDataShareUnitTest, OnChangeFromRdb001, TestSize.Level0) { @@ -1926,9 +2919,18 @@ HWTEST_F(MediaDataShareUnitTest, OnChangeFromRdb001, TestSize.Level0) /** * @tc.name: OnChangeFromRdb002 -* @tc.desc: test OnChangeFromRdb function with error +* @tc.desc: Test OnChangeFromRdb function with error scenario (null shared memory) * @tc.type: FUNC -* @tc.require: +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create an RdbChangeNode with isSharedMemory_ set to true but no memory allocated + 2. Create an RdbObserverStub with OnChangeCallback + 3. Call OnChangeFromRdb on the stub with the node + 4. Verify the node's data, memory, size, and isSharedMemory_ state +* @tc.expect: + 1.Node data is empty + 2.Node memory is null, size is 0, and isSharedMemory_ is false */ HWTEST_F(MediaDataShareUnitTest, OnChangeFromRdb002, TestSize.Level0) { @@ -1943,5 +2945,372 @@ HWTEST_F(MediaDataShareUnitTest, OnChangeFromRdb002, TestSize.Level0) ASSERT_FALSE(node.isSharedMemory_); LOG_INFO("OnChangeFromRdb002::End"); } + +/** +* @tc.name: OnremoteRequestTest001 +* @tc.desc: Test OnRemoteRequest function with invalid and valid interface tokens and request codes +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create an RdbObserverStub with OnChangeCallback + 2. Prepare MessageParcel, reply, and option objects + 3. Write an invalid interface token to the parcel and call OnRemoteRequest with code 0 + 4. Write the correct interface token and call OnRemoteRequest with code 1 + 5. Call OnRemoteRequest with the correct token and code 0 + 6. Verify the return values for each scenario +* @tc.expect: + 1.Request with invalid token returns ERR_INVALID_STATE + 2.Request with valid token and invalid code (1) returns ERR_INVALID_STATE + 3.Request with valid token and code 0 returns ERR_INVALID_VALUE +*/ +HWTEST_F(MediaDataShareUnitTest, OnremoteRequestTest001, TestSize.Level0) +{ + LOG_INFO("OnremoteRequestTest001::Start"); + RdbObserverStub stub(OnChangeCallback); + MessageParcel data; + MessageParcel reply; + MessageOption option; + std::u16string descriptorError = u"ERROR"; + std::u16string descriptorCorrect = RdbObserverStub::GetDescriptor(); + data.WriteInterfaceToken(descriptorError); + std::u16string descriptor; + int ret = stub.OnRemoteRequest(0, data, reply, option); + EXPECT_EQ(ret, ERR_INVALID_STATE); + data.WriteInterfaceToken(descriptorCorrect); + ret = stub.OnRemoteRequest(1, data, reply, option); + EXPECT_EQ(ret, ERR_INVALID_STATE); + data.WriteInterfaceToken(descriptorCorrect); + ret = stub.OnRemoteRequest(0, data, reply, option); + EXPECT_EQ(ret, ERR_INVALID_VALUE); + LOG_INFO("OnremoteRequestTest001::End"); +} + +/** +* @tc.name: ReadAshmemTest001 +* @tc.desc: Test ReadAshmem function with null shared memory +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create an RdbObserverStub with OnChangeCallback + 2. Create an RdbChangeNode with a null Ashmem pointer + 3. Call ReadAshmem on the stub with the node, null data pointer, size 0, and undefined offset + 4. Verify the return value +* @tc.expect: ReadAshmem returns E_ERROR +*/ +HWTEST_F(MediaDataShareUnitTest, ReadAshmemTest001, TestSize.Level0) +{ + LOG_INFO("ReadAshmemTest001::Start"); + RdbObserverStub stub(OnChangeCallback); + RdbChangeNode changeNode; + changeNode.memory_ = OHOS::sptr(nullptr); + const void *data = nullptr; + int size = 0; + int offset; + int ret = stub.ReadAshmem(changeNode, &data, size, offset); + EXPECT_EQ(ret, E_ERROR); + LOG_INFO("ReadAshmemTest001::End"); +} + +/** +* @tc.name: MediaDataShare_User_Define_Func_Test_001 +* @tc.desc: Test UserDefineFunc with no interface descriptor +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance + 2. Prepare empty MessageParcel, reply, and option objects (no descriptor written) + 3. Call UserDefineFunc on the helper + 4. Verify the error code +* @tc.expect: UserDefineFunc returns -1 (failure due to missing descriptor) +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_User_Define_Func_Test_001, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_User_Define_Func_Test_001::Start"); + std::shared_ptr helper = g_dataShareHelper; + MessageParcel data; + MessageParcel reply; + MessageOption option; + auto errCode = helper->UserDefineFunc(data, reply, option); + // 10 is IPC error ERR_INVALID_STATE + EXPECT_EQ(errCode, 10); + LOG_INFO("MediaDataShare_User_Define_Func_Test_001 End"); +} + +/** +* @tc.name: MediaDataShare_User_Define_Func_Test_002 +* @tc.desc: Test UserDefineFunc with a valid interface descriptor +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance + 2. Prepare MessageParcel, reply, and option objects + 3. Write the valid interface descriptor ("OHOS.DataShare.IDataShare") to the parcel + 4. Call UserDefineFunc on the helper + 5. Verify the error code +* @tc.expect: UserDefineFunc returns 0 (success with valid descriptor) +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_User_Define_Func_Test_002, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_User_Define_Func_Test_002::Start"); + std::shared_ptr helper = g_dataShareHelper; + MessageParcel data; + std::u16string descriptor = u"OHOS.DataShare.IDataShare"; + MessageParcel reply; + MessageOption option; + if (data.WriteInterfaceToken(descriptor)) { + auto errCode = helper->UserDefineFunc(data, reply, option); + EXPECT_EQ(errCode, 0); + } + LOG_INFO("MediaDataShare_User_Define_Func_Test_002 End"); +} + +/** +* @tc.name: MediaDataShare_RegisterObserverExtProvider_Test_001 +* @tc.desc: Test RegisterObserverExtProvider with null observer and null controller scenarios +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Attempt to register a null observer with an empty URI, check error code + 3. Create a valid observer and use a media library URI + 4. Release the helper's controller and attempt to register the observer, check error code +* @tc.expect: + 1.Registering null observer returns E_NULL_OBSERVER + 2.Registering with released (null) controller returns E_HELPER_DIED +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_RegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_RegisterObserverExtProvider_Test_001::Start"); + + Uri uri(""); + // GetObserver return not nullptr + std::shared_ptr dataObserver = nullptr; + std::shared_ptr helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID); + ASSERT_NE(helper, nullptr); + int errCode = helper->RegisterObserverExtProvider(uri, dataObserver, false); + EXPECT_EQ(errCode, E_NULL_OBSERVER); + + // GetObserver return is not nullptr but controller is nullptr + uri = Uri(MEDIALIBRARY_DATA_URI); + dataObserver = std::make_shared(); + ASSERT_NE(dataObserver, nullptr); + bool ret = helper->Release(); + EXPECT_TRUE(ret); + errCode = helper->RegisterObserverExtProvider(uri, dataObserver, false); + EXPECT_EQ(errCode, E_HELPER_DIED); + + LOG_INFO("MediaDataShare_RegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: MediaDataShare_RegisterObserverExtProvider_Test_002 +* @tc.desc: Test normal functionality of RegisterObserverExtProvider +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a media library URI and a valid DataShareObserverTest instance + 2. Create a DataShare helper instance and verify it is not null + 3. Call RegisterObserverExtProvider with the URI, observer, and false flag + 4. Verify the error code +* @tc.expect: RegisterObserverExtProvider returns E_OK (success) +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_RegisterObserverExtProvider_Test_002, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_RegisterObserverExtProvider_Test_002::Start"); + + Uri uri(MEDIALIBRARY_DATA_URI); + std::shared_ptr dataObserver = std::make_shared(); + std::shared_ptr helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID); + int errCode = helper->RegisterObserverExtProvider(uri, dataObserver, false); + ASSERT_NE(helper, nullptr); + EXPECT_EQ(errCode, E_OK); + + LOG_INFO("MediaDataShare_RegisterObserverExtProvider_Test_002::End"); +} + +/** +* @tc.name: MediaDataShare_UnregisterObserverExtProvider_Test_001 +* @tc.desc: Test UnregisterObserverExtProvider with null observer, unregistered observer, and null controller +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Attempt to unregister a null observer, check error code + 3. Create a valid observer and attempt to unregister it (not previously registered), check error code + 4. Register the observer, release the helper's controller, then attempt to unregister, check error code +* @tc.expect: + - Unregistering null observer returns E_NULL_OBSERVER + - Unregistering unregistered observer returns E_NULL_OBSERVER + - Unregistering with released (null) controller returns E_HELPER_DIED +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_UnregisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_UnregisterObserverExtProvider_Test_001::Start"); + + Uri uri(MEDIALIBRARY_DATA_URI); + // dataObserver is nullptr + std::shared_ptr dataObserver = nullptr; + std::shared_ptr helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID); + ASSERT_NE(helper, nullptr); + int errCode = helper->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(errCode, E_NULL_OBSERVER); + + // FindObserver return false + dataObserver = std::make_shared(); + ASSERT_NE(dataObserver, nullptr); + errCode = helper->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(errCode, E_NULL_OBSERVER); + + // FindObserver return true and general controller is nullptr + errCode = helper->RegisterObserverExtProvider(uri, dataObserver, false); + EXPECT_EQ(errCode, E_OK); + bool ret = helper->Release(); + EXPECT_TRUE(ret); + errCode = helper->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(errCode, E_HELPER_DIED); + + LOG_INFO("MediaDataShare_UnregisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: MediaDataShare_UnregisterObserverExtProvider_Test_002 +* @tc.desc: Test normal functionality of UnregisterObserverExtProvider +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a media library URI and a valid DataShareObserverTest instance + 2. Create a DataShare helper instance and verify it is not null + 3. Register the observer using RegisterObserverExtProvider and verify success + 4. Unregister the observer using UnregisterObserverExtProvider + 5. Verify the error code of unregistration +* @tc.expect: + 1.Registration returns E_OK + 2.Unregistration returns E_OK (success) +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_UnregisterObserverExtProvider_Test_002, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_UnregisterObserverExtProvider_Test_002::Start"); + + Uri uri(MEDIALIBRARY_DATA_URI); + // dataObserver is not nullptr + std::shared_ptr dataObserver = std::make_shared(); + ASSERT_NE(dataObserver, nullptr); + std::shared_ptr helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID); + ASSERT_NE(helper, nullptr); + + // FindObserver return true and general controller is not nullptr + int errCode = helper->RegisterObserverExtProvider(uri, dataObserver, true); + EXPECT_EQ(errCode, E_OK); + + errCode = helper->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(errCode, E_OK); + + LOG_INFO("MediaDataShare_UnregisterObserverExtProvider_Test_002::End"); +} + +/** +* @tc.name: MediaDataShare_NotifyChangeExtProvider_Test_001 +* @tc.desc: Test NotifyChangeExtProvider with null controller (released helper) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a media library URI and a valid DataShareObserverTest instance + 2. Create a DataShare helper instance, register the observer, and verify registration success + 3. Release the helper's controller to make it null + 4. Create an INSERT-type ChangeInfo and call NotifyChangeExtProvider with it +* @tc.expect: NotifyChangeExtProvider executes without crashing (no explicit error code check in test) +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_NotifyChangeExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_NotifyChangeExtProvider_Test_001::Start"); + + Uri uri(MEDIALIBRARY_DATA_URI); + std::shared_ptr dataObserver = std::make_shared(); + std::shared_ptr helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID); + ASSERT_NE(helper, nullptr); + ASSERT_NE(dataObserver, nullptr); + + int errCode = helper->RegisterObserverExtProvider(uri, dataObserver, false); + EXPECT_EQ(errCode, E_OK); + // generalCtl is nullptr + bool ret = helper->Release(); + EXPECT_TRUE(ret); + + ChangeInfo changeInfo = { DataShareObserver::ChangeType::INSERT, { uri } }; + helper->NotifyChangeExtProvider(changeInfo); + LOG_INFO("MediaDataShare_NotifyChangeExtProvider_Test_001::End"); +} + +/** +* @tc.name: MediaDataShare_NotifyChangeExtProvider_Test_002 +* @tc.desc: Test normal functionality of NotifyChangeExtProvider with valid controller +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a media library URI and a valid DataShareObserverTest instance + 2. Create a DataShare helper instance, register the observer, and verify registration success + 3. Create an INSERT-type ChangeInfo and call NotifyChangeExtProvider with it +* @tc.expect: NotifyChangeExtProvider executes successfully (no errors) +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_NotifyChangeExtProvider_Test_002, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_NotifyChangeExtProvider_Test_002::Start"); + + Uri uri(MEDIALIBRARY_DATA_URI); + // generalCtl is not nullptr + std::shared_ptr dataObserver = std::make_shared(); + std::shared_ptr helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID); + ASSERT_NE(helper, nullptr); + ASSERT_NE(dataObserver, nullptr); + + int errCode = helper->RegisterObserverExtProvider(uri, dataObserver, false); + EXPECT_EQ(errCode, E_OK); + + ChangeInfo changeInfo = { DataShareObserver::ChangeType::INSERT, { uri } }; + helper->NotifyChangeExtProvider(changeInfo); + LOG_INFO("MediaDataShare_NotifyChangeExtProvider_Test_002::End"); +} + +/** +* @tc.name: MediaDataShare_OpenFileWithErrCode_Test_001 +* @tc.desc: Test OpenFileWithErrCode function for file opening scenario +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Create a media library URI and specify "rw" mode + 3. Call OpenFileWithErrCode with the URI, mode, and error code pointer + 4. Verify the returned file descriptor (fd) and error code +* @tc.expect: + 1.File descriptor (fd) is negative (failure to open) + 2.Error code is -1 +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_OpenFileWithErrCode_Test_001, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_OpenFileWithErrCode_Test_001::Start"); + + std::shared_ptr helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID); + ASSERT_NE(helper, nullptr); + + Uri uri(MEDIALIBRARY_DATA_URI); + std::string mode = "rw"; + + int32_t errCode = 0; + int fd = helper->OpenFileWithErrCode(uri, mode, errCode); + EXPECT_LT(fd, 0); + EXPECT_EQ(errCode, -1); + LOG_INFO("MediaDataShare_OpenFileWithErrCode_Test_001::End"); +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/permission_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/permission_test.cpp index 2809b076894256a8812e9eaef76a59260aaf2250..0f5498292a3c324b6b388ddf26ec7ab0409db3ab 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/permission_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/permission_test.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #include +#include #include "access_token.h" #include "accesstoken_kit.h" @@ -28,6 +29,16 @@ namespace DataShare { using namespace testing::ext; using namespace OHOS::Security::AccessToken; static int USER_100 = 100; +static const std::string EMPTY_URI = ""; +static const std::string PROXY_ERROR_BUNDLE_URI = "datashareproxy://com.acts.datasharetest.error/test"; +static const std::string URI_DIFF_PROXY_DATA = "datashareproxy://com.acts.datasharetest/test/error"; +static const std::string PROXY_URI_OK = "datashareproxy://com.acts.datasharetest/test"; +static const std::string PROXY_URI_HAVA_QUERY = "datashareproxy://com.acts.datasharetest/test?table=user&key=zhangsan"; +static const std::string DATA_SHARE_ERROR_BUNDLE_URI = "datashare:///error.bundle.name/test"; +static const std::string DATA_SHARE_URI = "datashareproxy://com.acts.datasharetest/readtest"; +static const std::string DATA_SHARE_WRITEURI = "datashareproxy://com.acts.datasharetest/permissiontest/permission"; +static const std::string DATA_SHARE_EXTENSION_URI = "datashare:///com.acts.datasharetest"; +static const std::string DATA_SHARE_SELF_URI = "datashareproxy://ohos.datashareclienttest.demo"; class PermissionTest : public testing::Test { public: @@ -35,16 +46,6 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); - -protected: - std::string EMPTY_URI = ""; - std::string PROXY_ERROR_BUNDLE_URI = "datashareproxy://com.acts.datasharetest.error/test"; - std::string URI_DIFF_PROXY_DATA = "datashareproxy://com.acts.datasharetest/test/error"; - std::string PROXY_URI_OK = "datashareproxy://com.acts.datasharetest/test"; - std::string PROXY_URI_HAVA_QUERY = "datashareproxy://com.acts.datasharetest/test?table=user&key=zhangsan"; - std::string DATA_SHARE_ERROR_BUNDLE_URI = "datashare:///error.bundle.name/test"; - std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest/test"; - std::string DATA_SHARE_WRITEURI = "datashare:///com.acts.datasharetest/test/permission"; }; void PermissionTest::SetUpTestCase(void) @@ -56,9 +57,9 @@ void PermissionTest::SetUpTestCase(void) .userID = USER_100, .bundleName = "ohos.datashareclienttest.demo", .instIndex = 0, - .appIDDesc = "ohos.datashareclienttest.demo", + .isSystemApp = true, .apiVersion = 8, - .isSystemApp = true + .appIDDesc = "ohos.datashareclienttest.demo" }; HapPolicyParams policy = { .apl = APL_SYSTEM_CORE, @@ -103,6 +104,18 @@ void PermissionTest::TearDownTestCase(void) void PermissionTest::SetUp(void) {} void PermissionTest::TearDown(void) {} +/** +* @tc.name: PermissionTest_Uri_Empty_Test_001 +* @tc.desc: Verify permission check with empty URI returns error +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create empty URI object + 2. Call VerifyPermission with empty URI and read operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns ERR_INVALID_VALUE +*/ HWTEST_F(PermissionTest, PermissionTest_Uri_Empty_Test_001, TestSize.Level0) { LOG_INFO("PermissionTest_Uri_Scheme_Error_Test_001::Start"); @@ -113,6 +126,18 @@ HWTEST_F(PermissionTest, PermissionTest_Uri_Empty_Test_001, TestSize.Level0) LOG_INFO("PermissionTest_Uri_Scheme_Error_Test_001::End"); } +/** +* @tc.name: PermissionTest_Bundle_Name_Error_Test_001 +* @tc.desc: Verify permission check with invalid bundle name in URI returns error +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create URI with invalid bundle name + 2. Call VerifyPermission with this URI and read operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns E_BUNDLE_NAME_NOT_EXIST +*/ HWTEST_F(PermissionTest, PermissionTest_Bundle_Name_Error_Test_001, TestSize.Level0) { LOG_INFO("PermissionTest_Bundle_Name_Error_Test_001::Start"); @@ -123,17 +148,41 @@ HWTEST_F(PermissionTest, PermissionTest_Bundle_Name_Error_Test_001, TestSize.Lev LOG_INFO("PermissionTest_Bundle_Name_Error_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_Uri_Diff_ProxyData_Test_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_Uri_Diff_ProxyData_Test_001 +* @tc.desc: Verify permission check with non-existent proxy data URI returns error +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create URI pointing to non-existent proxy data + 2. Call VerifyPermission with this URI and read operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns E_URI_NOT_EXIST +*/ +HWTEST_F(PermissionTest, PermissionTest_Uri_Diff_ProxyData_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_Uri_Diff_ProxyData_Test_001::Start"); auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); Uri uri(URI_DIFF_PROXY_DATA); auto ret = DataShare::DataSharePermission::VerifyPermission(tokenId.tokenIDEx, uri, true); - EXPECT_EQ(ret, E_URI_NOT_EXIST); + EXPECT_EQ(ret, E_OK); LOG_INFO("PermissionTest_Uri_Diff_ProxyData_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_ProxyUri_OK_Test_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_ProxyUri_OK_Test_001 +* @tc.desc: Verify permission check with valid proxy URI for read operation succeeds +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create valid proxy URI + 2. Call VerifyPermission with this URI and read operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns E_OK +*/ +HWTEST_F(PermissionTest, PermissionTest_ProxyUri_OK_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_ProxyUri_OK_Test_001::Start"); auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); @@ -143,7 +192,19 @@ HWTEST_F(PermissionTest, PermissionTest_ProxyUri_OK_Test_001, TestSize.Level0) LOG_INFO("PermissionTest_ProxyUri_OK_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_ProxyUri_OK_Write_Permission_Error_Test_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_ProxyUri_OK_Write_Permission_Error_Test_001 +* @tc.desc: Verify permission check with valid proxy URI for write operation without permission fails +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create valid proxy URI + 2. Call VerifyPermission with this URI and write operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns ERR_PERMISSION_DENIED +*/ +HWTEST_F(PermissionTest, PermissionTest_ProxyUri_OK_Write_Permission_Error_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_ProxyUri_OK_Write_Permission_Error_Test_001::Start"); auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); @@ -154,6 +215,18 @@ HWTEST_F(PermissionTest, PermissionTest_ProxyUri_OK_Write_Permission_Error_Test_ LOG_INFO("PermissionTest_ProxyUri_OK_Write_Permission_Error_Test_001::End"); } +/** +* @tc.name: PermissionTest_Error_Bundle_Name_Test_001 +* @tc.desc: Verify permission check with invalid bundle name in datashare URI returns error +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create datashare URI with invalid bundle name + 2. Call VerifyPermission with this URI and read operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns E_BUNDLE_NAME_NOT_EXIST +*/ HWTEST_F(PermissionTest, PermissionTest_Error_Bundle_Name_Test_001, TestSize.Level0) { LOG_INFO("PermissionTest_Error_Bundle_Name_Test_001::Start"); @@ -164,7 +237,19 @@ HWTEST_F(PermissionTest, PermissionTest_Error_Bundle_Name_Test_001, TestSize.Lev LOG_INFO("PermissionTest_Error_Bundle_Name_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_No_Read_Permission_Test_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_No_Read_Permission_Test_001 +* @tc.desc: Verify permission check for read operation without required permission fails +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create valid datashare URI requiring specific read permission + 2. Call VerifyPermission with this URI and read operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns ERR_PERMISSION_DENIED +*/ +HWTEST_F(PermissionTest, PermissionTest_No_Read_Permission_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_No_Read_Permission_Test_001::Start"); auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); @@ -175,7 +260,19 @@ HWTEST_F(PermissionTest, PermissionTest_No_Read_Permission_Test_001, TestSize.Le LOG_INFO("PermissionTest_No_Read_Permission_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_Have_Write_Permission_Test_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_Have_Write_Permission_Test_001 +* @tc.desc: Verify permission check for write operation with required permission succeeds +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create valid datashare URI requiring specific write permission + 2. Call VerifyPermission with this URI and write operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns E_OK +*/ +HWTEST_F(PermissionTest, PermissionTest_Have_Write_Permission_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_HAVA_WRITE_PERMISSION_Test_001::Start"); auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); @@ -186,7 +283,19 @@ HWTEST_F(PermissionTest, PermissionTest_Have_Write_Permission_Test_001, TestSize LOG_INFO("PermissionTest_HAVA_WRITE_PERMISSION_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_Empty_Read_Permission_Test_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_Empty_Read_Permission_Test_001 +* @tc.desc: Verify permission check for read operation with unconfigured read permission fails +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create datashare URI with unconfigured read permission + 2. Call VerifyPermission with this URI and read operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns ERR_PERMISSION_DENIED +*/ +HWTEST_F(PermissionTest, PermissionTest_Empty_Read_Permission_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_Empty_Read_Permission_Test_001::Start"); auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); @@ -197,7 +306,19 @@ HWTEST_F(PermissionTest, PermissionTest_Empty_Read_Permission_Test_001, TestSize LOG_INFO("PermissionTest_Empty_Read_Permission_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_Empty_Write_Permission_Test_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_Empty_Write_Permission_Test_001 +* @tc.desc: Verify permission check for write operation with unconfigured write permission fails +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create datashare URI with unconfigured write permission + 2. Call VerifyPermission with this URI and write operation + 3. Check returned error code +* @tc.expected: VerifyPermission returns ERR_PERMISSION_DENIED +*/ +HWTEST_F(PermissionTest, PermissionTest_Empty_Write_Permission_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_Empty_Write_Permission_Test_001::Start"); auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); @@ -208,7 +329,19 @@ HWTEST_F(PermissionTest, PermissionTest_Empty_Write_Permission_Test_001, TestSiz LOG_INFO("PermissionTest_Empty_Write_Permission_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_Have_Query_Param_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_Have_Query_Param_001 +* @tc.desc: Verify permission check with URI containing query parameters succeeds +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create valid proxy URI with query parameters + 2. Call VerifyPermission with this URI and read operation + 3. Check returned error code +* @tc.expected: VerifyPermission returns E_OK +*/ +HWTEST_F(PermissionTest, PermissionTest_Have_Query_Param_001, TestSize.Level1) { LOG_INFO("PermissionTest_Have_Query_Param_001::Start"); auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); @@ -218,16 +351,173 @@ HWTEST_F(PermissionTest, PermissionTest_Have_Query_Param_001, TestSize.Level0) LOG_INFO("PermissionTest_Have_Query_Param_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_Have_Write_Test_001, TestSize.Level0) +HWTEST_F(PermissionTest, PermissionTest_DataObs_GetUriPermission_Uri_Empty_Test_001, TestSize.Level0) +{ + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_Empty_Test_001::Start"); + Uri uri(EMPTY_URI); + auto [ret, permission] = DataShare::DataSharePermission::GetUriPermission(uri, USER_100, true, false); + EXPECT_EQ(ret, E_EMPTY_URI); + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_Empty_Test_001::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_GetUriPermission_Uri_Error_Test_001, TestSize.Level0) +{ + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_Error_Test_001::Start"); + Uri uri(PROXY_ERROR_BUNDLE_URI); + auto [ret, permission] = DataShare::DataSharePermission::GetUriPermission(uri, USER_100, true, false); + EXPECT_EQ(ret, E_BUNDLE_NAME_NOT_EXIST); + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_Error_Test_001::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_001, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_001::Start"); + Uri uri(PROXY_URI_OK); + auto [ret, permission] = DataShare::DataSharePermission::GetUriPermission(uri, USER_100, true, false); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(permission, "ohos.permission.GET_BUNDLE_INFO"); + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_001::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_002, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_002::Start"); + Uri uri(PROXY_URI_OK); + auto [ret, permission] = DataShare::DataSharePermission::GetUriPermission(uri, USER_100, false, false); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(permission, "ohos.permission.WRITE_CONTACTS"); + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_002::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_003, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_003::Start"); + Uri uri(DATA_SHARE_EXTENSION_URI); + auto [ret, permission] = DataShare::DataSharePermission::GetUriPermission(uri, USER_100, true, true); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(permission, ""); + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_003::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_004, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_004::Start"); + Uri uri(DATA_SHARE_EXTENSION_URI); + auto [ret, permission] = DataShare::DataSharePermission::GetUriPermission(uri, USER_100, false, true); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(permission, ""); + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_004::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_VerifyPermission_Test_001, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_001::Start"); + auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); + Uri uri(PROXY_URI_OK); + std::string permission = "ohos.permission.GET_BUNDLE_INFO"; + auto ret = DataShare::DataSharePermission::VerifyPermission(uri, tokenId.tokenIDEx, permission, true); + EXPECT_EQ(ret, true); + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_001::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_VerifyPermission_Test_002, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_002::Start"); + auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); + Uri uri(PROXY_URI_OK); + std::string permission = "ohos.permission.WIFI"; + auto ret = DataShare::DataSharePermission::VerifyPermission(uri, tokenId.tokenIDEx, permission, true); + EXPECT_EQ(ret, false); + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_002::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_VerifyPermission_Test_003, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_003::Start"); + auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); + Uri uri(DATA_SHARE_SELF_URI); + std::string permission = ""; + auto ret = DataShare::DataSharePermission::VerifyPermission(uri, tokenId.tokenIDEx, permission, false); + EXPECT_EQ(ret, true); + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_003::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_VerifyPermission_Test_004, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_004::Start"); + auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); + Uri uri(DATA_SHARE_SELF_URI); + std::string permission = ""; + auto ret = DataShare::DataSharePermission::VerifyPermission(uri, tokenId.tokenIDEx, permission, true); + EXPECT_EQ(ret, true); + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_004::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_VerifyPermission_Test_005, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_005::Start"); + auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); + Uri uri(DATA_SHARE_SELF_URI); + std::string permission = ""; + auto ret = DataShare::DataSharePermission::VerifyPermission(uri, tokenId.tokenIDEx, permission, false); + EXPECT_EQ(ret, true); + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_005::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_VerifyPermission_Test_006, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_006::Start"); + auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); + Uri uri(PROXY_URI_OK); + std::string permission = ""; + auto ret = DataShare::DataSharePermission::VerifyPermission(uri, tokenId.tokenIDEx, permission, false); + EXPECT_EQ(ret, false); + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_006::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_IsExtensionValid_001, TestSize.Level1) +{ + LOG_INFO("PermissionTest_IsExtensionValid_001::Start"); + auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "com.acts.datasharetest", 0); + auto ret = DataShare::DataSharePermission::IsExtensionValid(tokenId.tokenIDEx, tokenId.tokenIDEx, USER_100); + EXPECT_EQ(ret, E_OK); + LOG_INFO("PermissionTest_IsExtensionValid_001::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_IsExtensionValid_002, TestSize.Level1) +{ + LOG_INFO("PermissionTest_IsExtensionValid_002::Start"); + auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "com.acts.ohos.data.datasharetest", 0); + auto ret = DataShare::DataSharePermission::IsExtensionValid(tokenId.tokenIDEx, tokenId.tokenIDEx, USER_100); + EXPECT_EQ(ret, E_NOT_DATASHARE_EXTENSION); + LOG_INFO("PermissionTest_IsExtensionValid_002::End"); +} + +/** +* @tc.name: PermissionTest_Have_Write_Test_001 +* @tc.desc: Verify permission check for write operation with correct permission succeeds +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create new HAP info with write permission configuration + 2. Allocate access token with required write permission + 3. Set the new token as current process token + 4. Call VerifyPermission with valid URI and write operation + 5. Check returned error code + 6. Clean up the created token +* @tc.expected: VerifyPermission returns E_OK +*/ +HWTEST_F(PermissionTest, PermissionTest_Have_Write_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_Have_Write_Test_001::Start"); HapInfoParams info = { .userID = USER_100, .bundleName = "ohos.permission.write.demo", .instIndex = 0, - .appIDDesc = "ohos.permission.write.demo", + .isSystemApp = true, .apiVersion = 8, - .isSystemApp = true + .appIDDesc = "ohos.permission.write.demo" }; HapPolicyParams policy = { .apl = APL_SYSTEM_CORE, @@ -261,16 +551,31 @@ HWTEST_F(PermissionTest, PermissionTest_Have_Write_Test_001, TestSize.Level0) LOG_INFO("PermissionTest_Have_Write_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_Hava_Read_Permission_Test_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_Hava_Read_Permission_Test_001 +* @tc.desc: Verify permission check for read operation with correct permission succeeds +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create new HAP info with read permission configuration + 2. Allocate access token with required read permission + 3. Set the new token as current process token + 4. Call VerifyPermission with valid URI and read operation + 5. Check returned error code + 6. Clean up the created token +* @tc.expected: VerifyPermission returns E_OK +*/ +HWTEST_F(PermissionTest, PermissionTest_Hava_Read_Permission_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_Hava_Read_Permission_Test_001::Start"); HapInfoParams info = { .userID = USER_100, .bundleName = "ohos.permission.demo", .instIndex = 0, - .appIDDesc = "ohos.permission.demo", + .isSystemApp = true, .apiVersion = 8, - .isSystemApp = true + .appIDDesc = "ohos.permission.demo" }; HapPolicyParams policy = { .apl = APL_SYSTEM_CORE, @@ -303,5 +608,6 @@ HWTEST_F(PermissionTest, PermissionTest_Hava_Read_Permission_Test_001, TestSize. AccessTokenKit::DeleteToken(testTokenId.tokenIDEx); LOG_INFO("PermissionTest_Hava_Read_Permission_Test_001::End"); } + } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/shared_block_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/shared_block_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..64525b5a832268847f29b391d185feba5c12317c --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/shared_block_test.cpp @@ -0,0 +1,549 @@ +/* + * 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 "shared_block.h" + +#include + +#include +#include +#include + +#include "ashmem.h" +#include "datashare_log.h" +#include "refbase.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::AppDataFwk; + +class SharedBlockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void SharedBlockTest::SetUpTestCase(void) +{ +} +void SharedBlockTest::TearDownTestCase(void) +{ +} +void SharedBlockTest::SetUp(void) +{ +} +void SharedBlockTest::TearDown(void) +{ +} + +/** +* @tc.name: InitTest001 +* @tc.desc: Test SharedBlock Init function when Ashmem start address is null +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create an Ashmem instance named "ahsmem" with size equal to SharedBlockHeader + 2. Set Ashmem's startAddr_ to nullptr + 3. Create a SharedBlock instance with the Ashmem, name "name", offset 0, and read-only flag true + 4. Call Init() on the SharedBlock instance + 5. Check the return value of Init() +* @tc.expect: SharedBlock::Init() returns false (initialization fails due to null Ashmem start address) +*/ +HWTEST_F(SharedBlockTest, InitTest001, TestSize.Level0) +{ + LOG_INFO("InitTest001::Start"); + sptr ashmem = Ashmem::CreateAshmem("ahsmem", sizeof(SharedBlock::SharedBlockHeader)); + EXPECT_NE(ashmem, nullptr); + ashmem->startAddr_ = nullptr; + SharedBlock *sharedBlock = new SharedBlock("name", ashmem, 0, true); + EXPECT_EQ(sharedBlock->Init(), false); + LOG_INFO("InitTest001::End"); +} + +/** +* @tc.name: CreateSharedBlockTest001 +* @tc.desc: Test CreateSharedBlock function when Ashmem start address is null +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create an Ashmem instance named "ahsmem" with size equal to SharedBlockHeader + 2. Set Ashmem's startAddr_ to nullptr + 3. Declare a null SharedBlock pointer + 4. Call CreateSharedBlock with name "name", size equal to SharedBlockHeader, the Ashmem, and the null pointer + 5. Check the return error code +* @tc.expect: CreateSharedBlock returns SharedBlock::SHARED_BLOCK_ASHMEM_ERROR +*/ +HWTEST_F(SharedBlockTest, CreateSharedBlockTest001, TestSize.Level0) +{ + LOG_INFO("CreateSharedBlockTest001::Start"); + sptr ashmem = Ashmem::CreateAshmem("ahsmem", sizeof(SharedBlock::SharedBlockHeader)); + EXPECT_NE(ashmem, nullptr); + ashmem->startAddr_ = nullptr; + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(sharedBlock->CreateSharedBlock("name", sizeof(SharedBlock::SharedBlockHeader), ashmem, sharedBlock), + SharedBlock::SHARED_BLOCK_ASHMEM_ERROR); + LOG_INFO("CreateSharedBlockTest001::End"); +} + +/** +* @tc.name: CreateTest001 +* @tc.desc: Test SharedBlock::Create function with negative size parameter +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Declare a null SharedBlock pointer + 2. Call SharedBlock::Create with name "name", negative size (-1), and the null pointer + 3. Check the return error code +* @tc.expect: SharedBlock::Create returns SharedBlock::SHARED_BLOCK_ASHMEM_ERROR +*/ +HWTEST_F(SharedBlockTest, CreateTest001, TestSize.Level0) +{ + LOG_INFO("CreateTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", -1, sharedBlock), SharedBlock::SHARED_BLOCK_ASHMEM_ERROR); + LOG_INFO("CreateTest001::End"); +} + +/** +* @tc.name: ReadMessageParcelTest001 +* @tc.desc: Test SharedBlock::ReadMessageParcel function with valid parcel data +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a MessageParcel instance + 2. Write a string16 ("string") and the Ashmem instance to the parcel + 3. Declare a null SharedBlock pointer + 4. Call SharedBlock::ReadMessageParcel with the parcel and the null pointer + 5. Check the return error code +* @tc.expect: SharedBlock::ReadMessageParcel returns SharedBlock::SHARED_BLOCK_OK (successfully reads parcel data) +*/ +HWTEST_F(SharedBlockTest, ReadMessageParcelTest001, TestSize.Level0) +{ + LOG_INFO("ReadMessageParcelTest001::Start"); + MessageParcel parcel; + std::u16string str = u"string"; + SharedBlock *block = nullptr; + sptr ashmem = Ashmem::CreateAshmem("ahsmem", sizeof(SharedBlock::SharedBlockHeader)); + EXPECT_NE(ashmem, nullptr); + ashmem->startAddr_ = nullptr; + parcel.WriteString16(str); + parcel.WriteAshmem(ashmem); + EXPECT_EQ(SharedBlock::ReadMessageParcel(parcel, block), SharedBlock::SHARED_BLOCK_OK); + + LOG_INFO("ReadMessageParcelTest001::End"); +} + +/** +* @tc.name: ClearTest001 +* @tc.desc: Test SharedBlock Clear function under different states (read-only, insufficient size, normal) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance with valid size, verify it is not null + 2. Set the SharedBlock to read-only mode, call Clear() and check return code + 3. Set the SharedBlock to read-write mode, set mSize to SharedBlockHeader size, call Clear and check return code + 4. Restore mSize to original valid size, call Clear() and check return code +* @tc.expect: + - Clear() returns SHARED_BLOCK_INVALID_OPERATION when read-only + - Clear() returns SHARED_BLOCK_BAD_VALUE when size is insufficient + - Clear() returns SHARED_BLOCK_OK when in read-write mode with valid size +*/ +HWTEST_F(SharedBlockTest, ClearTest001, TestSize.Level0) +{ + LOG_INFO("ClearTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + sharedBlock->mReadOnly = true; + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mReadOnly = false; + sharedBlock->mSize = sizeof(SharedBlock::SharedBlockHeader); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_BAD_VALUE); + sharedBlock->mSize = sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("ClearTest001::End"); +} + +/** +* @tc.name: SetColumnNumTest001 +* @tc.desc: Test SetColumnNum function under various conditions (read-only, invalid values, max limit) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Set to read-only mode, call SetColumnNum(1) and check return code + 3. Set to read-write mode, configure header with conflicting row/column nums, call SetColumnNum(0) and check + 4. Test with max column num (32768) and conflicting row nums, check return code + 5. Test valid configuration (matching row/column nums), check return code + 6. Test setting column num to 0 with no rows, check return code +* @tc.expect: + - Returns SHARED_BLOCK_INVALID_OPERATION in read-only mode + - Returns SHARED_BLOCK_INVALID_OPERATION for invalid value combinations + - Returns SHARED_BLOCK_OK for valid configurations +*/ +HWTEST_F(SharedBlockTest, SetColumnNumTest001, TestSize.Level0) +{ + LOG_INFO("SetColumnNumTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + sharedBlock->mReadOnly = true; + uint32_t numColumns = 1; + EXPECT_EQ(sharedBlock->SetColumnNum(numColumns), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mReadOnly = false; + sharedBlock->mHeader->columnNums = numColumns; + sharedBlock->mHeader->rowNums = numColumns; + EXPECT_EQ(sharedBlock->SetColumnNum(0), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mHeader->columnNums = 0; + sharedBlock->mHeader->rowNums = numColumns; + EXPECT_EQ(sharedBlock->SetColumnNum(numColumns), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mHeader->columnNums = numColumns; + sharedBlock->mHeader->rowNums = 0; + EXPECT_EQ(sharedBlock->SetColumnNum(0), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + numColumns = 32768; // 32768 is max_num + sharedBlock->mHeader->columnNums = numColumns; + sharedBlock->mHeader->rowNums = numColumns; + EXPECT_EQ(sharedBlock->SetColumnNum(numColumns), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + numColumns = 1; + sharedBlock->mHeader->columnNums = numColumns; + sharedBlock->mHeader->rowNums = numColumns; + EXPECT_EQ(sharedBlock->SetColumnNum(numColumns), SharedBlock::SHARED_BLOCK_OK); + sharedBlock->mHeader->columnNums = 0; + sharedBlock->mHeader->rowNums = 0; + EXPECT_EQ(sharedBlock->SetColumnNum(0), SharedBlock::SHARED_BLOCK_OK); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("SetColumnNumTest001::End"); +} + +/** +* @tc.name: AllocRowTest001 +* @tc.desc: Test AllocRow function under read-only mode and insufficient memory +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Set to read-only mode, call AllocRow() and check return code + 3. Set to read-write mode, set mSize to 0 (insufficient memory), call AllocRow() and check return code + 4. Restore mSize to valid value, call Clear() to clean up +* @tc.expect: + - AllocRow() returns SHARED_BLOCK_INVALID_OPERATION in read-only mode + - AllocRow() returns SHARED_BLOCK_NO_MEMORY when size is insufficient + - Clear() returns SHARED_BLOCK_OK after restoring size +*/ +HWTEST_F(SharedBlockTest, AllocRow, TestSize.Level0) +{ + LOG_INFO("AllocRowTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + sharedBlock->mReadOnly = true; + EXPECT_EQ(sharedBlock->AllocRow(), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mReadOnly = false; + sharedBlock->mSize = 0; + EXPECT_EQ(sharedBlock->AllocRow(), SharedBlock::SHARED_BLOCK_NO_MEMORY); + sharedBlock->mSize = sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("AllocRowTest001::End"); +} + +/** +* @tc.name: FreeLastRowTest001 +* @tc.desc: Test FreeLastRow function under read-only mode and with different row counts +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Set to read-only mode, call FreeLastRow() and check return code + 3. Set to read-write mode, set rowNums to 0, call FreeLastRow() and check return code + 4. Set rowNums to a positive value, call FreeLastRow() and check return code + 5. Call Clear() to clean up +* @tc.expect: + - FreeLastRow() returns SHARED_BLOCK_INVALID_OPERATION in read-only mode + - FreeLastRow() returns SHARED_BLOCK_OK when rowNums is 0 + - FreeLastRow() returns SHARED_BLOCK_OK when rowNums is positive + - Clear() returns SHARED_BLOCK_OK +*/ +HWTEST_F(SharedBlockTest, FreeLastRowTest001, TestSize.Level0) +{ + LOG_INFO("FreeLastRowTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + sharedBlock->mReadOnly = true; + EXPECT_EQ(sharedBlock->FreeLastRow(), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mReadOnly = false; + auto temp = sharedBlock->mHeader->rowNums + 1; + sharedBlock->mHeader->rowNums = 0; + EXPECT_EQ(sharedBlock->FreeLastRow(), SharedBlock::SHARED_BLOCK_OK); + sharedBlock->mHeader->rowNums = temp; + EXPECT_EQ(sharedBlock->FreeLastRow(), SharedBlock::SHARED_BLOCK_OK); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("FreeLastRowTest001::End"); +} + +/** +* @tc.name: AllocRowOffsetTest001 +* @tc.desc: Test AllocRowOffset function with insufficient memory +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Save original mSize, set mSize to 0 (insufficient memory) + 3. Call AllocRowOffset() and check return value + 4. Restore mSize to original value, call Clear() to clean up +* @tc.expect: + - AllocRowOffset() returns nullptr when mSize is 0 (insufficient memory) + - Clear() returns SHARED_BLOCK_OK after restoring size +*/ +HWTEST_F(SharedBlockTest, AllocRowOffsetTest001, TestSize.Level0) +{ + LOG_INFO("AllocRowOffsetTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + auto temp = sharedBlock->mSize; + sharedBlock->mSize = 0; + EXPECT_EQ(sharedBlock->AllocRowOffset(), nullptr); + sharedBlock->mSize = temp; + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("AllocRowOffsetTest001::End"); +} + +/** +* @tc.name: GetCellUnitTest001 +* @tc.desc: Test GetCellUnit function with invalid row/column indices and insufficient memory +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Save original rowNums, columnNums, and mSize + 3. Set rowNums=1, columnNums=1, mSize=0 (insufficient memory) + 4. Call GetCellUnit with invalid row (1) and valid column (0), check return value + 5. Call GetCellUnit with valid row (0) and invalid column (1), check return value + 6. Call GetCellUnit with valid row/column (0,0), check return value + 7. Restore original values, call Clear() to clean up +* @tc.expect: All GetCellUnit calls return nullptr under invalid conditions +*/ +HWTEST_F(SharedBlockTest, GetCellUnitTest001, TestSize.Level0) +{ + LOG_INFO("GetCellUnitTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + auto rowTemp = sharedBlock->mHeader->rowNums; + auto culTemp = sharedBlock->mHeader->columnNums; + auto sizeTemp = sharedBlock->mSize; + sharedBlock->mHeader->rowNums = 1; + sharedBlock->mHeader->columnNums = 1; + sharedBlock->mSize = 0; + EXPECT_EQ(sharedBlock->GetCellUnit(1, 0), nullptr); + EXPECT_EQ(sharedBlock->GetCellUnit(0, 1), nullptr); + EXPECT_EQ(sharedBlock->GetCellUnit(0, 0), nullptr); + sharedBlock->mHeader->rowNums = rowTemp; + sharedBlock->mHeader->columnNums = culTemp; + sharedBlock->mSize = sizeTemp; + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("GetCellUnitTest001::End"); +} + +/** +* @tc.name: PutBlobOrStringTest001 +* @tc.desc: Test PutBlobOrString function under read-only mode and invalid indices +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Set to read-only mode, call PutBlobOrString with valid parameters and check return code + 3. Set to read-write mode, call PutBlobOrString with invalid row index and check return code + 4. Call Clear() to clean up +* @tc.expect: + - Returns SHARED_BLOCK_INVALID_OPERATION in read-only mode + - Returns SHARED_BLOCK_BAD_VALUE with invalid row index + - Clear() returns SHARED_BLOCK_OK +*/ +HWTEST_F(SharedBlockTest, PutBlobOrStringTest001, TestSize.Level0) +{ + LOG_INFO("PutBlobOrStringTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + sharedBlock->mReadOnly = true; + std::string str = "string"; + EXPECT_EQ(sharedBlock->PutBlobOrString(sharedBlock->mHeader->rowNums, 1, &str, str.size(), 1), + SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mReadOnly = false; + EXPECT_EQ(sharedBlock->PutBlobOrString(sharedBlock->mHeader->rowNums, 1, &str, str.size(), 1), + SharedBlock::SHARED_BLOCK_BAD_VALUE); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("PutBlobOrStringTest001::End"); +} + +/** +* @tc.name: PutLongTest001 +* @tc.desc: Test PutLong function under read-only mode and invalid indices +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Set to read-only mode, call PutLong with invalid indices and check return code + 3. Set to read-write mode, call PutLong with invalid indices and check return code + 4. Call Clear() to clean up +* @tc.expect: + - Returns SHARED_BLOCK_INVALID_OPERATION in read-only mode + - Returns SHARED_BLOCK_BAD_VALUE with invalid indices + - Clear() returns SHARED_BLOCK_OK +*/ +HWTEST_F(SharedBlockTest, PutLongTest001, TestSize.Level0) +{ + LOG_INFO("PutLongTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + int64_t temp = 0; + sharedBlock->mReadOnly = true; + EXPECT_EQ( + sharedBlock->PutLong(sharedBlock->mHeader->rowNums, 1, temp), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mReadOnly = false; + EXPECT_EQ(sharedBlock->PutLong(sharedBlock->mHeader->rowNums, 1, temp), SharedBlock::SHARED_BLOCK_BAD_VALUE); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("PutLongTest001::End"); +} + +/** +* @tc.name: PutDoubleTest001 +* @tc.desc: Test PutDouble function under read-only mode and invalid indices +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Set to read-only mode, call PutDouble with invalid indices and check return code + 3. Set to read-write mode, call PutDouble with invalid indices and check return code + 4. Call Clear() to clean up +* @tc.expect: + - Returns SHARED_BLOCK_INVALID_OPERATION in read-only mode + - Returns SHARED_BLOCK_BAD_VALUE with invalid indices + - Clear() returns SHARED_BLOCK_OK +*/ +HWTEST_F(SharedBlockTest, PutDoubleTest001, TestSize.Level0) +{ + LOG_INFO("PutDoubleTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + double temp = 0; + sharedBlock->mReadOnly = true; + EXPECT_EQ( + sharedBlock->PutDouble(sharedBlock->mHeader->rowNums, 1, temp), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mReadOnly = false; + EXPECT_EQ(sharedBlock->PutDouble(sharedBlock->mHeader->rowNums, 1, temp), SharedBlock::SHARED_BLOCK_BAD_VALUE); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("PutDoubleTest001::End"); +} + +/** +* @tc.name: PutNullTest001 +* @tc.desc: Test PutNull function under read-only mode and invalid indices +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Set to read-only mode, call PutNull with invalid indices and check return code + 3. Set to read-write mode, call PutNull with invalid indices and check return code + 4. Call Clear() to clean up +* @tc.expect: + - Returns SHARED_BLOCK_INVALID_OPERATION in read-only mode + - Returns SHARED_BLOCK_BAD_VALUE with invalid indices + - Clear() returns SHARED_BLOCK_OK +*/ +HWTEST_F(SharedBlockTest, PutNullTest001, TestSize.Level0) +{ + LOG_INFO("PutNullTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + sharedBlock->mReadOnly = true; + EXPECT_EQ(sharedBlock->PutNull(sharedBlock->mHeader->rowNums, 1), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mReadOnly = false; + EXPECT_EQ(sharedBlock->PutNull(sharedBlock->mHeader->rowNums, 1), SharedBlock::SHARED_BLOCK_BAD_VALUE); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("PutNullTest001::End"); +} + +/** +* @tc.name: SetRawDataTest001 +* @tc.desc: Test SetRawData function with invalid size and insufficient memory +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Save original mSize, set mSize to 0 (insufficient memory) + 3. Call SetRawData with header data and size 0, check return code + 4. Call SetRawData with header data and valid size, check return code + 5. Restore mSize to original value, call SetRawData with valid size, check return code + 6. Call Clear() to clean up +* @tc.expect: + - Returns SHARED_BLOCK_INVALID_OPERATION when size is 0 + - Returns SHARED_BLOCK_NO_MEMORY when mSize is 0 + - Returns SHARED_BLOCK_OK when mSize is valid + - Clear() returns SHARED_BLOCK_OK +*/ +HWTEST_F(SharedBlockTest, SetRawDataTest001, TestSize.Level0) +{ + LOG_INFO("SetRawDataTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + auto sizeTemp = sharedBlock->mSize; + sharedBlock->mSize = 0; + SharedBlock::SharedBlockHeader mHeader; + int result = memcpy_s(&mHeader, sizeof(mHeader), sharedBlock->mHeader, sizeof(mHeader)); + EXPECT_EQ(result, 0); + EXPECT_EQ(sharedBlock->SetRawData(&mHeader, 0), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + EXPECT_EQ(sharedBlock->SetRawData(&mHeader, sizeof(mHeader)), SharedBlock::SHARED_BLOCK_NO_MEMORY); + sharedBlock->mSize = sizeTemp; + EXPECT_EQ(sharedBlock->SetRawData(&mHeader, sizeof(mHeader)), SharedBlock::SHARED_BLOCK_OK); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("SetRawDataTest001::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 bc6a74f65ee96fe640f4e15fc8eb448d530f4d35..e2150d7ba3b9aaec0a7bc30ec35f7eded9584900 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 @@ -15,7 +15,6 @@ #include #include #include -#include #include "accesstoken_kit.h" #include "data_ability_observer_stub.h" @@ -30,8 +29,23 @@ namespace OHOS { namespace DataShare { using namespace testing::ext; using namespace OHOS::Security::AccessToken; +using ChangeInfo = DataShareObserver::ChangeInfo; constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; static int USER_100 = 100; +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::string DATA_SHARE_ERROR_URI = "datashare:///com.acts.datasharetest000"; +std::string SLIENT_ACCESS_URI = "datashare:///com.acts.datasharetest/entry/DB00/TBL00?Proxy=true"; +std::string SLIENT_ERROR_URI = "datashare:///com.acts.datashare/entry/DB00/TBL00?Proxy=true"; +std::string SLIENT_ERROR_DATABASE_URI = "datashare:///com.acts.datasharetest/entry/DB6666/TBL00?Proxy=true"; +std::string SLIENT_REGISTER_URI = "datashare:///com.acts.datasharetest/entry/DB00/TBL02?Proxy=true"; +std::string SLIENT_ACCESS_PERMISSION1_URI = "datashare:///com.acts.datasharetest/entry/DB00/permission1?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"; +std::string TBL_STU_NAME = "name"; +std::string TBL_STU_AGE = "age"; +std::shared_ptr g_slientAccessHelper; + template class ConditionLock { public: @@ -74,21 +88,6 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); - -protected: - static constexpr const char *DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; - static constexpr const char *SLIENT_ACCESS_URI = "datashare:///com.acts.datasharetest/entry/DB00/TBL00?Proxy=true"; - static constexpr const char *SLIENT_REGISTER_URI = "datashare:///com.acts.datasharetest/entry/DB00/" - "TBL02?Proxy=true"; - 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"; - static std::shared_ptr CreateDataShareHelper(int32_t saId, std::string uri); - static std::shared_ptr g_slientAccessHelper; }; class IDataShareAbilityObserverTest : public AAFwk::DataAbilityObserverStub { @@ -122,8 +121,33 @@ public: private: std::string name; }; -std::shared_ptr SlientAccessTest::g_slientAccessHelper; -std::shared_ptr SlientAccessTest::CreateDataShareHelper(int32_t saId, std::string uri) + +class DataShareObserverTest : public DataShare::DataShareObserver { +public: + DataShareObserverTest() {} + ~DataShareObserverTest() {} + + void OnChange(const ChangeInfo &changeInfo) override + { + changeInfo_ = changeInfo; + data.Notify(); + } + + void Clear() + { + changeInfo_.changeType_ = INVAILD; + changeInfo_.uris_.clear(); + changeInfo_.data_ = nullptr; + changeInfo_.size_ = 0; + changeInfo_.valueBuckets_ = {}; + data.Clear(); + } + + ChangeInfo changeInfo_; + ConditionLock data; +}; + +std::shared_ptr CreateDataShareHelper(int32_t systemAbilityId, std::string uri) { LOG_INFO("CreateDataShareHelper start"); auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); @@ -131,8 +155,8 @@ std::shared_ptr SlientAccessTest::CreateDataShareHel LOG_ERROR("GetSystemAbilityManager get samgr failed."); return nullptr; } - auto remoteObj = saManager->GetSystemAbility(saId); - while (remoteObj == nullptr) { + auto remoteObj = saManager->GetSystemAbility(systemAbilityId); + if (remoteObj == nullptr) { LOG_ERROR("GetSystemAbility service failed."); return nullptr; } @@ -219,6 +243,21 @@ void SlientAccessTest::TearDownTestCase(void) void SlientAccessTest::SetUp(void) {} void SlientAccessTest::TearDown(void) {} +/** +* @tc.name: SlientAccess_Creator_Errorcode_Test_001 +* @tc.desc: Test DataShareHelper creation with valid parameters +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Get SystemAbilityManager instance +* 2. Get remote object for STORAGE_MANAGER_MANAGER_ID +* 3. Call DataShareHelper::Create() with valid remote object and URIs +* 4. Check return code and helper instance +* @tc.expect: +* 1. Return code is E_OK +* 2. Helper instance is not null +*/ HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Creator_Errorcode_Test_001::Start"); @@ -239,6 +278,19 @@ HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_001, TestSize.Lev LOG_INFO("SlientAccess_Creator_Errorcode_Test_001::End"); } +/** +* @tc.name: SlientAccess_Creator_Errorcode_Test_002 +* @tc.desc: Test DataShareHelper creation with null remote object +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Call DataShareHelper::Create() with null remote object and valid URIs +* 2. Check return code and helper instance +* @tc.expect: +* 1. Return code is E_TOKEN_EMPTY +* 2. Helper instance is null +*/ HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_002, TestSize.Level0) { LOG_INFO("SlientAccess_Creator_Errorcode_Test_002::Start"); @@ -250,11 +302,26 @@ HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_002, TestSize.Lev LOG_INFO("SlientAccess_Creator_Errorcode_Test_002::End"); } +/** +* @tc.name: SlientAccess_Creator_Errorcode_Test_003 +* @tc.desc: Test DataShareHelper creation with invalid URIs +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Get SystemAbilityManager instance +* 2. Get remote object for STORAGE_MANAGER_MANAGER_ID +* 3. Call DataShareHelper::Create() with valid remote object, error URI and empty URI +* 4. Check return code and helper instance +* @tc.expect: +* 1. Return code is E_EXT_URI_INVALID +* 2. Helper instance is null +*/ 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); + std::string uriStr2 (""); auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (saManager == nullptr) { LOG_ERROR("GetSystemAbilityManager get samgr failed."); @@ -263,13 +330,29 @@ HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_003, TestSize.Lev if (remoteObj == nullptr) { LOG_ERROR("GetSystemAbility service failed."); } + // slientUri is error bundle name, extUri is empty, slient access can't find the bundle name auto [ret, helper] = DataShare::DataShareHelper::Create(remoteObj, uriStr1, uriStr2); - EXPECT_EQ(ret, DataShare::E_BUNDLE_NAME_NOT_EXIST); + EXPECT_EQ(ret, DataShare::E_EXT_URI_INVALID); EXPECT_EQ(helper, nullptr); helper = nullptr; LOG_INFO("SlientAccess_Creator_Errorcode_Test_003::End"); } +/** +* @tc.name: SlientAccess_Creator_Errorcode_Test_004 +* @tc.desc: Test DataShareHelper creation with same valid URIs +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Get SystemAbilityManager instance +* 2. Get remote object for STORAGE_MANAGER_MANAGER_ID +* 3. Call DataShareHelper::Create() with valid remote object and same URIs +* 4. Check return code and helper instance +* @tc.expect: +* 1. Return code is E_OK +* 2. Helper instance is not null +*/ HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_004, TestSize.Level0) { LOG_INFO("SlientAccess_Creator_Errorcode_Test_004::Start"); @@ -290,6 +373,20 @@ HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_004, TestSize.Lev LOG_INFO("SlientAccess_Creator_Errorcode_Test_004::End"); } +/** +* @tc.name: SlientAccess_InsertEx_Test_001 +* @tc.desc: Test InsertEx operation with valid data +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 2. Call InsertEx() with SLIENT_ACCESS_URI and values bucket +* 3. Check error code and return value +* @tc.expect: +* 1. Error code is 0 (success) +* 2. Return value is greater than 0 (valid row ID) +*/ HWTEST_F(SlientAccessTest, SlientAccess_InsertEx_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_InsertEx_Test_001::Start"); @@ -307,6 +404,48 @@ HWTEST_F(SlientAccessTest, SlientAccess_InsertEx_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_InsertEx_Test_001::End"); } +/** +* @tc.name: SlientAccess_InsertEx_Test_002 +* @tc.desc: Test base class InsertEx operation +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 2. Call base class InsertEx() with SLIENT_ACCESS_URI and values bucket +* 3. Check return pair +* @tc.expect: The return pair is (0, 0) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_InsertEx_Test_002, TestSize.Level0) +{ + LOG_INFO("SilentAccess_InsertEx_Test_002::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); + + EXPECT_EQ(helper->DataShareHelper::InsertEx(uri, valuesBucket), std::make_pair(0, 0)); + LOG_INFO("SilentAccess_InsertEx_Test_002::End"); +} + +/** +* @tc.name: SlientAccess_UpdateEx_Test_001 +* @tc.desc: Test UpdateEx operation with valid data +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with update data (age=50) +* 2. Create DataSharePredicates to select record with name="lisi" +* 3. Call UpdateEx() with SLIENT_ACCESS_URI, predicates and values bucket +* 4. Check error code and return value +* @tc.expect: +* 1. Error code is 0 (success) +* 2. Return value is greater than 0 (number of affected rows) +*/ HWTEST_F(SlientAccessTest, SlientAccess_UpdateEx_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_UpdateEx_Test_001::Start"); @@ -324,6 +463,49 @@ HWTEST_F(SlientAccessTest, SlientAccess_UpdateEx_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_UpdateEx_Test_001::End"); } +/** +* @tc.name: SlientAccess_UpdateEx_Test_002 +* @tc.desc: Test base class UpdateEx operation +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with update data (age=50) +* 2. Create DataSharePredicates to select record with name="lisi" +* 3. Call base class UpdateEx() with SLIENT_ACCESS_URI, predicates and values bucket +* 4. Check return pair +* @tc.expect: The return pair is (0, 0) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_UpdateEx_Test_002, TestSize.Level0) +{ + LOG_INFO("SilentAccess_UpdateEx_Test_002::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); + + EXPECT_EQ(helper->DataShareHelper::UpdateEx(uri, predicates, valuesBucket), std::make_pair(0, 0)); + LOG_INFO("SilentAccess_UpdateEx_Test_002::End"); +} + +/** +* @tc.name: SlientAccess_DeleteEx_Test_001 +* @tc.desc: Test DeleteEx operation with valid parameters +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create DataSharePredicates to select record with name="lisi" +* 2. Call DeleteEx() with SLIENT_ACCESS_URI and predicates +* 3. Check error code and return value +* @tc.expect: +* 1. Error code is 0 (success) +* 2. Return value is greater than 0 (number of deleted rows) +*/ HWTEST_F(SlientAccessTest, SlientAccess_DeleteEx_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_DeleteEx_Test_001::Start"); @@ -339,6 +521,43 @@ HWTEST_F(SlientAccessTest, SlientAccess_DeleteEx_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_DeleteEx_Test_001::End"); } +/** +* @tc.name: SlientAccess_DeleteEx_Test_002 +* @tc.desc: Test base class DeleteEx operation +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create DataSharePredicates to select record with name="lisi" +* 2. Call base class DeleteEx() with SLIENT_ACCESS_URI and predicates +* 3. Check return pair +* @tc.expect: The return pair is (0, 0) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_DeleteEx_Test_002, TestSize.Level0) +{ + LOG_INFO("SilentAccess_DeleteEx_Test_002::Start"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ACCESS_URI); + DataShare::DataSharePredicates deletePredicates; + std::string selections = TBL_STU_NAME + " = 'lisi'"; + deletePredicates.SetWhereClause(selections); + + EXPECT_EQ(helper->DataShareHelper::DeleteEx(uri, deletePredicates), std::make_pair(0, 0)); + LOG_INFO("SilentAccess_DeleteEx_Test_002::End"); +} + +/** +* @tc.name: SlientAccess_Insert_Test_001 +* @tc.desc: Test Insert operation with valid data +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 2. Call Insert() with SLIENT_ACCESS_URI and values bucket +* 3. Check return value +* @tc.expect: Return value is greater than 0 (valid row ID) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Insert_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Insert_Test_001::Start"); @@ -355,6 +574,19 @@ HWTEST_F(SlientAccessTest, SlientAccess_Insert_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_Insert_Test_001::End"); } +/** +* @tc.name: SlientAccess_Update_Test_001 +* @tc.desc: Test Update operation with valid data +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with update data (age=50) +* 2. Create DataSharePredicates to select record with name="lisi" +* 3. Call Update() with SLIENT_ACCESS_URI, predicates and values bucket +* 4. Check return value +* @tc.expect: Return value is greater than 0 (number of affected rows) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Update_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Update_Test_001::Start"); @@ -371,6 +603,18 @@ HWTEST_F(SlientAccessTest, SlientAccess_Update_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_Update_Test_001::End"); } +/** +* @tc.name: SlientAccess_Query_Test_001 +* @tc.desc: Test Query operation with valid parameters +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create DataSharePredicates to select record with name="lisi" +* 2. Call Query() with SLIENT_ACCESS_URI, predicates and empty columns list +* 3. Check row count of the result set +* @tc.expect: Query returns 1 record +*/ HWTEST_F(SlientAccessTest, SlientAccess_Query_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Query_Test_001::Start"); @@ -388,6 +632,18 @@ HWTEST_F(SlientAccessTest, SlientAccess_Query_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_Query_Test_001::End"); } +/** +* @tc.name: SlientAccess_Delete_Test_001 +* @tc.desc: Test Delete operation with valid parameters +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create DataSharePredicates to select record with name="lisi" +* 2. Call Delete() with SLIENT_ACCESS_URI and predicates +* 3. Check return value +* @tc.expect: Return value is greater than 0 (number of deleted rows) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Delete_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Delete_Test_001::Start"); @@ -402,6 +658,24 @@ HWTEST_F(SlientAccessTest, SlientAccess_Delete_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_Delete_Test_001::End"); } +/** +* @tc.name: SlientAccess_Register_Test_001 +* @tc.desc: Test observer registration and notification in silent access mode +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create IDataShareAbilityObserverTest instance and set initial name "zhangsan" +* 2. Register observer with SLIENT_ACCESS_URI +* 3. Insert test data (name="lisi", age=25) using helper +* 4. Wait for observer notification +* 5. Verify observer name changes to "OnChangeName" +* 6. Delete test data and unregister observer +* @tc.expect: +* 1. Insert operation succeeds (retVal > 0) +* 2. Observer is notified and name updates to "OnChangeName" +* 3. Delete operation succeeds (retVal >= 0) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Register_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Register_Test_001::Start"); @@ -430,6 +704,23 @@ HWTEST_F(SlientAccessTest, SlientAccess_Register_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_Register_Test_001::End"); } +/** +* @tc.name: SlientAccess_RegisterErrorUri_Test_001 +* @tc.desc: Test observer registration with incorrect URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create IDataShareAbilityObserverTest instance and set name "zhangsan" +* 2. Register observer with incorrect URI (SLIENT_REGISTER_URI) +* 3. Insert test data (name="lisi", age=25) to SLIENT_ACCESS_URI +* 4. Check if observer is notified +* 5. Delete test data and unregister observer +* @tc.expect: +* 1. Insert operation succeeds (retVal > 0) +* 2. Observer is NOT notified (name remains "zhangsan") +* 3. Delete operation succeeds (retVal >= 0) +*/ HWTEST_F(SlientAccessTest, SlientAccess_RegisterErrorUri_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_RegisterErrorUri_Test_001::Start"); @@ -457,6 +748,22 @@ HWTEST_F(SlientAccessTest, SlientAccess_RegisterErrorUri_Test_001, TestSize.Leve LOG_INFO("SlientAccess_RegisterErrorUri_Test_001::End"); } +/** +* @tc.name: SlientAccess_NoRegister_Test_001 +* @tc.desc: Test data operation without observer registration +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create IDataShareAbilityObserverTest instance but do NOT register it +* 2. Insert test data (name="lisi", age=25) using helper +* 3. Check if observer is notified +* 4. Delete test data +* @tc.expect: +* 1. Insert operation succeeds (retVal > 0) +* 2. Observer is NOT notified (name remains "zhangsan") +* 3. Delete operation succeeds (retVal >= 0) +*/ HWTEST_F(SlientAccessTest, SlientAccess_NoRegister_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_NoRegister_Test_001::Start"); @@ -482,6 +789,23 @@ HWTEST_F(SlientAccessTest, SlientAccess_NoRegister_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_NoRegister_Test_001::End"); } +/** +* @tc.name: SlientAccess_NoRegister_Test_002 +* @tc.desc: Test data operation after unregistering observer +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create IDataShareAbilityObserverTest instance and register it +* 2. Immediately unregister the observer +* 3. Insert test data (name="lisi", age=25) using helper +* 4. Check if observer is notified +* 5. Delete test data +* @tc.expect: +* 1. Insert operation succeeds (retVal > 0) +* 2. Observer is NOT notified (name remains "zhangsan") +* 3. Delete operation succeeds (retVal >= 0) +*/ HWTEST_F(SlientAccessTest, SlientAccess_NoRegister_Test_002, TestSize.Level0) { LOG_INFO("SlientAccess_NoRegister_Test_002::Start"); @@ -508,6 +832,18 @@ HWTEST_F(SlientAccessTest, SlientAccess_NoRegister_Test_002, TestSize.Level0) LOG_INFO("SlientAccess_NoRegister_Test_002::End"); } +/** +* @tc.name: SlientAccess_Permission_Insert_Test_001 +* @tc.desc: Test insert operation with proper permissions +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 2. Call Insert() with SLIENT_ACCESS_URI +* 3. Check return value +* @tc.expect: Insert operation succeeds (retVal > 0) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Insert_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Permission_Insert_Test_001::Start"); @@ -524,6 +860,18 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Insert_Test_001, TestSize.Lev LOG_INFO("SlientAccess_Permission_Insert_Test_001::End"); } +/** +* @tc.name: SlientAccess_Permission_Insert_Test_003 +* @tc.desc: Test insert operation with proxy permission URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 2. Call Insert() with SLIENT_PROXY_PERMISSION1_URI +* 3. Check return value +* @tc.expect: Insert operation succeeds (retVal > 0) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Insert_Test_003, TestSize.Level0) { LOG_INFO("SlientAccess_Permission_Insert_Test_003::Start"); @@ -540,6 +888,19 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Insert_Test_003, TestSize.Lev LOG_INFO("SlientAccess_Permission_Insert_Test_003::End"); } +/** +* @tc.name: SlientAccess_Permission_Update_Test_001 +* @tc.require: NA +* @tc.desc: Test update operation with proxy permission URI +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with update data (age=50) +* 2. Create predicates to select record with name="lisi" +* 3. Call Update() with SLIENT_PROXY_PERMISSION1_URI +* 4. Check return value +* @tc.expect: Update operation succeeds (retVal > 0) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Update_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Permission_Update_Test_001::Start"); @@ -556,6 +917,22 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Update_Test_001, TestSize.Lev LOG_INFO("SlientAccess_Permission_Update_Test_001::End"); } +/** +* @tc.name: SlientAccess_Permission_Query_Test_002 +* @tc.desc: Test query operation with proxy permission URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Insert test data (name="lisi", age=25) into SLIENT_PROXY_PERMISSION2_URI +* 2. Create predicates to select inserted record +* 3. Call Query() with SLIENT_PROXY_PERMISSION2_URI +* 4. Check result set row count and business error code +* @tc.expect: +* 1. Insert operation succeeds (retVal > 0) +* 2. Query returns 1 record +* 3. Business error code is 0 (no error) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Query_Test_002, TestSize.Level0) { LOG_INFO("SlientAccess_Permission_Query_Test_002::Start"); @@ -584,6 +961,18 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Query_Test_002, TestSize.Leve LOG_INFO("SlientAccess_Permission_Query_Test_002::End"); } +/** +* @tc.name: SlientAccess_Permission_Delete_Test_001 +* @tc.desc: Test delete operation with proxy permission URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create predicates to select record with name="lisi" +* 2. Call Delete() with SLIENT_PROXY_PERMISSION2_URI +* 3. Check return value +* @tc.expect: Delete operation succeeds and deletes 1 record (retVal = 1) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Delete_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Permission_Delete_Test_001::Start"); @@ -598,6 +987,20 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Delete_Test_001, TestSize.Lev LOG_INFO("SlientAccess_Permission_Delete_Test_001::End"); } +/** +* @tc.name: SlientAccess_Permission_Insert_Test_002 +* @tc.desc: Test insert operation without required permissions +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create HAP token with limited permissions +* 2. Set token ID for current process +* 3. Create DataShareHelper instance +* 4. Try to insert data into SLIENT_ACCESS_PERMISSION1_URI +* 5. Clean up token +* @tc.expect: Insert operation fails (retVal = -2) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Insert_Test_002, TestSize.Level0) { LOG_INFO("SlientAccess_Permission_Insert_Test_002::Start"); @@ -605,9 +1008,9 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Insert_Test_002, TestSize.Lev .userID = USER_100, .bundleName = "ohos.permission.write.demo", .instIndex = 0, - .appIDDesc = "ohos.permission.write.demo", + .isSystemApp = true, .apiVersion = 8, - .isSystemApp = true + .appIDDesc = "ohos.permission.write.demo" }; HapPolicyParams policy = { .apl = APL_SYSTEM_CORE, @@ -641,6 +1044,20 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Insert_Test_002, TestSize.Lev LOG_INFO("SlientAccess_Permission_Insert_Test_002::End"); } +/** +* @tc.name: SlientAccess_Permission_Update_Test_002 +* @tc.desc: Test update operation without required permissions +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create HAP token with limited permissions +* 2. Set token ID for current process +* 3. Create DataShareHelper instance +* 4. Try to update data in SLIENT_ACCESS_PERMISSION1_URI +* 5. Clean up token +* @tc.expect: Update operation fails (retVal = -2) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Update_Test_002, TestSize.Level0) { LOG_INFO("SlientAccess_Permission_Update_Test_002::Start"); @@ -648,9 +1065,9 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Update_Test_002, TestSize.Lev .userID = USER_100, .bundleName = "ohos.permission.write.demo", .instIndex = 0, - .appIDDesc = "ohos.permission.write.demo", + .isSystemApp = true, .apiVersion = 8, - .isSystemApp = true + .appIDDesc = "ohos.permission.write.demo" }; HapPolicyParams policy = { .apl = APL_SYSTEM_CORE, @@ -685,6 +1102,24 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Update_Test_002, TestSize.Lev LOG_INFO("SlientAccess_Permission_Update_Test_002::End"); } +/** +* @tc.name: SlientAccess_Permission_Query_Test_001 +* @tc.desc: Test query operation without required permissions +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create HAP token with limited permissions (only WRITE_CONTACTS granted) +* 2. Set token ID for current process +* 3. Create DataShareHelper instance +* 4. Try to query data from SLIENT_ACCESS_PERMISSION2_URI with predicates for "lisi" +* 5. Check result set, row count and business error code +* 6. Clean up token +* @tc.expect: +* 1. Result set is nullptr +* 2. Row count is 0 +* 3. Business error code is -2 (permission denied) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Query_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Permission_Query_Test_001::Start"); @@ -692,9 +1127,9 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Query_Test_001, TestSize.Leve .userID = USER_100, .bundleName = "ohos.permission.write.demo", .instIndex = 0, - .appIDDesc = "ohos.permission.write.demo", + .isSystemApp = true, .apiVersion = 8, - .isSystemApp = true + .appIDDesc = "ohos.permission.write.demo" }; HapPolicyParams policy = { .apl = APL_SYSTEM_CORE, @@ -732,5 +1167,329 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Query_Test_001, TestSize.Leve AccessTokenKit::DeleteToken(testTokenId.tokenIDEx); LOG_INFO("SlientAccess_Permission_Query_Test_001::End"); } + +/** +* @tc.name: SlientAccess_Access_When_Uri_Error_Test_001 +* @tc.desc: Test data insertion with invalid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 2. Call Insert() with invalid URI (SLIENT_ERROR_URI) +* 3. Check return value +* @tc.expect: Insert operation fails (retVal < 0) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_Access_When_Uri_Error_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Permission_Access_When_URI_ERROR_Test_001::Begin"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ERROR_URI); + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "lisi"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 25; + valuesBucket.Put(TBL_STU_AGE, age); + + int retVal = helper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal < 0), true); + LOG_INFO("SlientAccess_Permission_Access_When_URI_ERROR_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_Access_With_Uncreated_DataBase_Test_001 +* @tc.desc: Test data insertion to uncreated database +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 2. Call Insert() with URI pointing to uncreated database (SLIENT_ERROR_DATABASE_URI) +* 3. Check return value +* @tc.expect: Insert operation fails (retVal < 0) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_Access_With_Uncreated_DataBase_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Access_With_Uncreated_DataBase_Test_001::Begin"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ERROR_DATABASE_URI); + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "lisi"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 25; + valuesBucket.Put(TBL_STU_AGE, age); + + int retVal = helper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal < 0), true); + LOG_INFO("SlientAccess_Access_With_Uncreated_DataBase_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_Creator_With_Uri_Error_Test_001 +* @tc.desc: Test DataShareHelper creation with invalid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Get SystemAbilityManager instance and remote object for STORAGE_MANAGER_MANAGER_ID +* 2. Try to create DataShareHelper with invalid URI (DATA_SHARE_ERROR_URI) +* 3. Check helper instance +* @tc.expect: Helper creation fails (helper == nullptr) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_Creator_With_Uri_Error_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Creator_With_Uri_Error_Test_001::Begin"); + 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."); + } + std::string uriStr(DATA_SHARE_ERROR_URI); + auto helper = DataShare::DataShareHelper::Creator(remoteObj, uriStr, uriStr, 2); + EXPECT_EQ(helper, nullptr); + LOG_INFO("SlientAccess_Creator_With_Uri_Error_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_Creator_When_TimeOut_Test_001 +* @tc.desc: Test DataShareHelper creation with timeout +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Get SystemAbilityManager instance and remote object for STORAGE_MANAGER_MANAGER_ID +* 2. Try to create DataShareHelper with valid URI but timeout parameter 0 +* 3. Check helper instance +* @tc.expect: Helper creation fails due to timeout (helper == nullptr) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_Creator_When_TimeOut_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Creator_With_Uri_Error_Test_001::Begin"); + 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."); + } + std::string uriStr(DATA_SHARE_URI); + auto helper = DataShare::DataShareHelper::Creator(remoteObj, uriStr, uriStr, 0); + EXPECT_EQ(helper, nullptr); + LOG_INFO("SlientAccess_Creator_With_Uri_Error_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_UserDefineFunc_Test_001 +* @tc.desc: Test custom user-defined function in DataShareHelper +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create empty MessageParcel objects for data and reply +* 2. Create default MessageOption +* 3. Call UserDefineFunc() on the helper +* 4. Check return value +* @tc.expect: User-defined function returns 0 (success) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_UserDefineFunc_Test_001, TestSize.Level0) +{ + LOG_INFO("SilentAccess_UserDefineFunc_Test_001::Start"); + auto helper = g_slientAccessHelper; + MessageParcel data; + MessageParcel reply; + MessageOption option; + auto result = helper->DataShareHelper::UserDefineFunc(data, reply, option); + EXPECT_EQ(result, 0); + LOG_INFO("SilentAccess_UserDefineFunc_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_Creator_ErrorBundle_Test_001 +* @tc.desc: Test DataShareHelper creation with invalid bundle name in URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create URI with invalid bundle name ("com.acts.error.bundleName") +* 2. Try to create DataShareHelper with this URI +* 3. Check helper instance +* @tc.expect: Helper creation fails (helper == nullptr) due to invalid bundle name +*/ +HWTEST_F(SlientAccessTest, SlientAccess_Creator_ErrorBundle_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Creator_ErrorBundle_Test_001::Start"); + std::string uriStr1("datashareproxy://com.acts.error.bundleName/test"); + // slientUri is error bundle name, slient access can't find the bundle name, return nullptr + auto helperSilent = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, uriStr1); + EXPECT_EQ(helperSilent, nullptr); + LOG_INFO("SlientAccess_Creator_ErrorBundle_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_Creator_ErrorBundle_ExtSuccess_Test_001 +* @tc.desc: Test DataShareHelper creation with invalid silent URI but valid ext URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Get SystemAbilityManager instance and remote object for STORAGE_MANAGER_MANAGER_ID +* 2. Try to create DataShareHelper with invalid silent URI but valid ext URI +* 3. Check return code and helper instance +* @tc.expect: +* 1. Return code is E_OK +* 2. Helper instance is not null (success due to valid ext URI) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_Creator_ErrorBundle_ExtSuccess_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Creator_ErrorBundle_ExtSuccess_Test_001::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."); + } + // slientUri is error bundleName, extUri is effective, slient access can't find the bundleName, but ext success + 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_ErrorBundle_ExtSuccess_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_Create_With_Invalid_AppIndex_Test_001 +* @tc.desc: Test DataShareHelper creation with invalid appIndex in URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create URI with invalid appIndex parameter ("appIndex=-1") +* 2. Try to create DataShareHelper using Create() method +* 3. Try to create DataShareHelper using Creator() method +* 4. Try to create DataShareHelper with CreateOptions +* 5. Check return code and helper instances +* @tc.expect: +* 1. Create() returns E_EXT_URI_INVALID with null helper +* 2. Both Creator() methods return null helper +*/ +HWTEST_F(SlientAccessTest, SlientAccess_Create_With_Invalid_AppIndex_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Create_With_Invalid_AppIndex_Test_001::Start"); + std::string uri("datashareproxy://com.acts.datasharetest/test?Proxy=true&appIndex=-1"); + std::string extUri(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, uri, ""); + EXPECT_EQ(ret, E_EXT_URI_INVALID); + EXPECT_EQ(helper, nullptr); + + helper = DataShare::DataShareHelper::Creator(remoteObj, uri); + EXPECT_EQ(helper, nullptr); + + CreateOptions options; + options.isProxy_ = true; + helper = DataShare::DataShareHelper::Creator(uri, options); + EXPECT_EQ(helper, nullptr); + LOG_INFO("SlientAccess_Create_With_Invalid_AppIndex_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_RegisterObserverExtProvider_Test_001 +* @tc.desc: Test RegisterObserverExtProvider with invalid URI (covers generalCtl == nullptr branch) +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create invalid URI (SLIENT_ERROR_URI) +* 2. Create DataShareObserverTest instance +* 3. Call RegisterObserverExtProvider with invalid URI and observer +* @tc.expect: No crash occurs, method executes without errors +*/ +HWTEST_F(SlientAccessTest, SlientAccess_RegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_RegisterObserverExtProvider_Test_001::Begin"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ERROR_URI); + std::shared_ptr dataObserver = std::make_shared(); + ASSERT_NE(helper, nullptr); + ASSERT_NE(dataObserver, nullptr); + + helper->RegisterObserverExtProvider(uri, dataObserver, false); + + LOG_INFO("SlientAccess_RegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_UnregisterObserverExtProvider_Test_001 +* @tc.desc: Test UnregisterObserverExtProvider with invalid URI (covers generalCtl == nullptr branch) +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create invalid URI (SLIENT_ERROR_URI) +* 2. Create DataShareObserverTest instance +* 3. Call UnregisterObserverExtProvider with invalid URI and observer +* 4. Create dummy ChangeInfo object +* @tc.expect: No crash occurs, method executes without errors +*/ +HWTEST_F(SlientAccessTest, SlientAccess_UnregisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_UnregisterObserverExtProvider_Test_001::Begin"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ERROR_URI); + std::shared_ptr dataObserver = std::make_shared(); + ASSERT_NE(helper, nullptr); + ASSERT_NE(dataObserver, nullptr); + + helper->UnregisterObserverExtProvider(uri, dataObserver); + + ChangeInfo changeInfo = { DataShareObserver::ChangeType::INSERT, { uri } }; + LOG_INFO("SlientAccess_UnregisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_NotifyChangeExtProvider_Test_001 +* @tc.desc: Test NotifyChangeExtProvider with invalid URI (covers generalCtl == nullptr branch) +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create invalid URI (SLIENT_ERROR_URI) +* 2. Create DataShareObserverTest instance +* 3. Register observer with invalid URI +* 4. Create ChangeInfo object for INSERT operation +* 5. Call NotifyChangeExtProvider with ChangeInfo +* @tc.expect: No crash occurs, notification process executes without errors +*/ +HWTEST_F(SlientAccessTest, SlientAccess_NotifyChangeExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_NotifyChangeExtProvider_Test_001::Begin"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ERROR_URI); + std::shared_ptr dataObserver = std::make_shared(); + ASSERT_NE(helper, nullptr); + ASSERT_NE(dataObserver, nullptr); + + helper->RegisterObserverExtProvider(uri, dataObserver, true); + + ChangeInfo changeInfo = { DataShareObserver::ChangeType::INSERT, { uri } }; + helper->NotifyChangeExtProvider(changeInfo); + + LOG_INFO("SlientAccess_NotifyChangeExtProvider_Test_001::End"); +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/slientswitch_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/slientswitch_test.cpp index a0c083811d32626e86b6301866977d84cb12d5eb..ac9842b8e84ace87ab7e0d08d2cdeba3cee737d1 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/slientswitch_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/slientswitch_test.cpp @@ -28,8 +28,14 @@ namespace DataShare { using namespace testing::ext; using namespace OHOS::Security::AccessToken; constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::string SLIENT_ACCESS_URI = "datashare:///com.acts.datasharetest/entry/DB00/TBL00?Proxy=true"; +std::string DATA_SHARE_PROXY_URI = "datashare:///com.acts.ohos.data.datasharetest/test"; constexpr int SUBSCRIBER_ID = 1000; +std::string TBL_STU_NAME = "name"; +std::string TBL_STU_AGE = "age"; int32_t ERROR = -1; +std::shared_ptr g_slientAccessHelper; class SlientSwitchTest : public testing::Test { public: @@ -37,21 +43,10 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); - -protected: - static inline std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; - static inline std::string SLIENT_ACCESS_URI = "datashare:///com.acts.datasharetest/entry/DB00/TBL00?Proxy=true"; - static inline std::string DATA_SHARE_PROXY_URI = "datashare:///com.acts.ohos.data.datasharetest/test"; - static inline std::string TBL_STU_NAME = "name"; - static inline std::string TBL_STU_AGE = "age"; - static std::shared_ptr CreateDataShareHelper(int32_t systemAbilityId, - const std::string &silentProxyUri, const std::string &providerUri = ""); - static std::shared_ptr g_slientAccessHelper; }; -std::shared_ptr SlientSwitchTest::g_slientAccessHelper; -std::shared_ptr SlientSwitchTest::CreateDataShareHelper(int32_t systemAbilityId, - const std::string &silentProxyUri, const std::string &providerUri) +std::shared_ptr CreateDataShareHelper(int32_t systemAbilityId, + const std::string &silentProxyUri, const std::string &providerUri = "") { LOG_INFO("CreateDataShareHelper start"); auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); @@ -126,6 +121,18 @@ void SlientSwitchTest::TearDownTestCase(void) void SlientSwitchTest::SetUp(void) {} void SlientSwitchTest::TearDown(void) {} +/** +* @tc.name: SlientSwitch_SetSilentSwitch_Test_001 +* @tc.desc: Test enabling silent switch with valid access URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Call DataShareHelper::SetSilentSwitch() with URI and true (enable) +* 3. Verify the return value +* @tc.expect: The operation succeeds with return value E_OK +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SetSilentSwitch_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SetSilentSwitch_Test_001::Start"); @@ -135,6 +142,18 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SetSilentSwitch_Test_001, TestSize.Level LOG_INFO("SlientSwitch_SetSilentSwitch_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SetSilentSwitch_Test_002 +* @tc.desc: Test disabling silent switch with valid access URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Call DataShareHelper::SetSilentSwitch() with URI and false (disable) +* 3. Verify the return value +* @tc.expect: The operation succeeds with return value E_OK +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SetSilentSwitch_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SetSilentSwitch_Test_002::Start"); @@ -144,6 +163,18 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SetSilentSwitch_Test_002, TestSize.Level LOG_INFO("SlientSwitch_SetSilentSwitch_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SetSilentSwitch_Test_003 +* @tc.desc: Test disabling silent switch with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create empty Uri object +* 2. Call DataShareHelper::SetSilentSwitch() with empty URI and false (disable) +* 3. Verify the return value +* @tc.expect: The operation succeeds with return value E_OK +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SetSilentSwitch_Test_003, TestSize.Level0) { LOG_INFO("SlientSwitch_SetSilentSwitch_Test_003::Start"); @@ -153,6 +184,18 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SetSilentSwitch_Test_003, TestSize.Level LOG_INFO("SlientSwitch_SetSilentSwitch_Test_003::End"); } +/** +* @tc.name: SlientSwitch_SetSilentSwitch_Test_004 +* @tc.desc: Test enabling silent switch with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create empty Uri object +* 2. Call DataShareHelper::SetSilentSwitch() with empty URI and true (enable) +* 3. Verify the return value +* @tc.expect: The operation succeeds with return value E_OK +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SetSilentSwitch_Test_004, TestSize.Level0) { LOG_INFO("SlientSwitch_SetSilentSwitch_Test_004::Start"); @@ -162,6 +205,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SetSilentSwitch_Test_004, TestSize.Level LOG_INFO("SlientSwitch_SetSilentSwitch_Test_004::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_Insert_Test_001 +* @tc.desc: Test data insertion when silent switch is disabled with valid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Disable silent switch using SetSilentSwitch() with URI +* 3. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 4. Call Insert() method with URI and values bucket +* 5. Verify the return value +* @tc.expect: Insert operation fails (return value <= 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Insert_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_Insert_Test_001::Start"); @@ -181,6 +238,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Insert_Test_001, TestSize. LOG_INFO("SlientSwitch_SwitchDisable_Insert_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_Insert_Test_002 +* @tc.desc: Test data insertion when silent switch is disabled with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Disable silent switch using SetSilentSwitch() with empty URI +* 2. Prepare DataShareValuesBucket with test data (name="wangwu", age=25) +* 3. Create Uri object with SLIENT_ACCESS_URI +* 4. Call Insert() method with URI and values bucket +* 5. Verify the return value +* @tc.expect: Insert operation fails (return value <= 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Insert_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_Insert_Test_002::Start"); @@ -200,6 +271,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Insert_Test_002, TestSize. LOG_INFO("SlientSwitch_SwitchDisable_Insert_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_Insert_Test_001 +* @tc.desc: Test data insertion when silent switch is enabled with valid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Enable silent switch using SetSilentSwitch() with URI +* 3. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 4. Call Insert() method with URI and values bucket +* 5. Verify the return value +* @tc.expect: Insert operation succeeds (return value > 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Insert_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_Insert_Test_001::Start"); @@ -219,6 +304,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Insert_Test_001, TestSize.L LOG_INFO("SlientSwitch_SwitchEnable_Insert_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_Insert_Test_002 +* @tc.desc: Test data insertion when silent switch is enabled with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Enable silent switch using SetSilentSwitch() with empty URI +* 2. Prepare DataShareValuesBucket with test data (name="wangwu", age=25) +* 3. Create Uri object with SLIENT_ACCESS_URI +* 4. Call Insert() method with URI and values bucket +* 5. Verify the return value +* @tc.expect: Insert operation succeeds (return value > 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Insert_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_Insert_Test_002::Start"); @@ -238,6 +337,21 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Insert_Test_002, TestSize.L LOG_INFO("SlientSwitch_SwitchEnable_Insert_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_Update_Test_001 +* @tc.desc: Test data update when silent switch is disabled with valid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Disable silent switch using SetSilentSwitch() with URI +* 3. Prepare DataShareValuesBucket with update data (age=50) +* 4. Create DataSharePredicates to select record with name="lisi" +* 5. Call Update() method with URI, predicates and values bucket +* 6. Verify the return value +* @tc.expect: Update operation fails (return value <= 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Update_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_Update_Test_001::Start"); @@ -257,6 +371,21 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Update_Test_001, TestSize. LOG_INFO("SlientSwitch_SwitchDisable_Update_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_Update_Test_002 +* @tc.desc: Test data update when silent switch is disabled with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Disable silent switch using SetSilentSwitch() with empty URI +* 2. Prepare DataShareValuesBucket with update data (age=50) +* 3. Create DataSharePredicates to select record with name="wangwu" +* 4. Create Uri object with SLIENT_ACCESS_URI +* 5. Call Update() method with URI, predicates and values bucket +* 6. Verify the return value +* @tc.expect: Update operation fails (return value <= 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Update_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_Update_Test_002::Start"); @@ -277,6 +406,21 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Update_Test_002, TestSize. LOG_INFO("SlientSwitch_SwitchDisable_Update_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_Update_Test_001 +* @tc.desc: Test data update when silent switch is enabled with valid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Enable silent switch using SetSilentSwitch() with URI +* 3. Prepare DataShareValuesBucket with update data (age=50) +* 4. Create DataSharePredicates to select record with name="lisi" +* 5. Call Update() method with URI, predicates and values bucket +* 6. Verify the return value +* @tc.expect: Update operation succeeds (return value > 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Update_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_Update_Test_001::Start"); @@ -296,6 +440,21 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Update_Test_001, TestSize.L LOG_INFO("SlientSwitch_SwitchEnable_Update_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_Update_Test_002 +* @tc.desc: Test data update when silent switch is enabled with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Enable silent switch using SetSilentSwitch() with empty URI +* 2. Prepare DataShareValuesBucket with update data (age=50) +* 3. Create DataSharePredicates to select record with name="wangwu" +* 4. Create Uri object with SLIENT_ACCESS_URI +* 5. Call Update() method with URI, predicates and values bucket +* 6. Verify the return value +* @tc.expect: Update operation succeeds (return value > 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Update_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_Update_Test_002::Start"); @@ -316,6 +475,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Update_Test_002, TestSize.L LOG_INFO("SlientSwitch_SwitchEnable_Update_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_Query_Test_001 +* @tc.desc: Test data query when silent switch is disabled with valid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Disable silent switch using SetSilentSwitch() with URI +* 3. Create DataSharePredicates to select record with name="lisi" +* 4. Call Query() method with URI, predicates and empty columns list +* 5. Verify the result set +* @tc.expect: Query operation fails (resultSet is nullptr) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Query_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_Query_Test_001::Start"); @@ -332,6 +505,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Query_Test_001, TestSize.L LOG_INFO("SlientSwitch_SwitchDisable_Query_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_Query_Test_002 +* @tc.desc: Test data query when silent switch is disabled with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Disable silent switch using SetSilentSwitch() with empty URI +* 2. Create DataSharePredicates to select record with name="wangwu" +* 3. Create Uri object with SLIENT_ACCESS_URI +* 4. Call Query() method with URI, predicates and empty columns list +* 5. Verify the result set +* @tc.expect: Query operation fails (resultSet is nullptr) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Query_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_Query_Test_002::Start"); @@ -349,6 +536,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Query_Test_002, TestSize.L LOG_INFO("SlientSwitch_SwitchDisable_Query_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_Query_Test_001 +* @tc.desc: Test data query when silent switch is enabled with valid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Enable silent switch using SetSilentSwitch() with URI +* 3. Create DataSharePredicates to select record with name="lisi" +* 4. Call Query() method with URI, predicates and empty columns list +* 5. Check row count of the result set +* @tc.expect: Query operation succeeds and returns 1 record +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Query_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_Query_Test_001::Start"); @@ -369,6 +570,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Query_Test_001, TestSize.Le LOG_INFO("SlientSwitch_SwitchEnable_Query_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_Query_Test_002 +* @tc.desc: Test data query when silent switch is enabled with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Enable silent switch using SetSilentSwitch() with empty URI +* 2. Create DataSharePredicates to select record with name="wangwu" +* 3. Create Uri object with SLIENT_ACCESS_URI +* 4. Call Query() method with URI, predicates and empty columns list +* 5. Check row count of the result set +* @tc.expect: Query operation succeeds and returns 1 record +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Query_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_Query_Test_002::Start"); @@ -390,6 +605,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Query_Test_002, TestSize.Le LOG_INFO("SlientSwitch_SwitchEnable_Query_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_Delete_Test_001 +* @tc.desc: Test data deletion when silent switch is disabled with valid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Disable silent switch using SetSilentSwitch() with URI +* 3. Create DataSharePredicates to select record with name="lisi" +* 4. Call Delete() method with URI and predicates +* 5. Verify the return value +* @tc.expect: Delete operation fails (return value <= 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Delete_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_Delete_Test_001::Start"); @@ -406,6 +635,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Delete_Test_001, TestSize. LOG_INFO("SlientSwitch_SwitchDisable_Delete_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_Delete_Test_002 +* @tc.desc: Test data deletion when silent switch is disabled with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Disable silent switch using SetSilentSwitch() with empty URI +* 2. Create DataSharePredicates to select record with name="wangwu" +* 3. Create Uri object with SLIENT_ACCESS_URI +* 4. Call Delete() method with URI and predicates +* 5. Verify the return value +* @tc.expect: Delete operation fails (return value <= 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Delete_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_Delete_Test_002::Start"); @@ -423,6 +666,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Delete_Test_002, TestSize. LOG_INFO("SlientSwitch_SwitchDisable_Delete_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_Delete_Test_001 +* @tc.desc: Test data deletion when silent switch is enabled with valid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Enable silent switch using SetSilentSwitch() with URI +* 3. Create DataSharePredicates to select record with name="lisi" +* 4. Call Delete() method with URI and predicates +* 5. Verify the return value +* @tc.expect: Delete operation succeeds (return value > 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Delete_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_Delete_Test_001::Start"); @@ -439,6 +696,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Delete_Test_001, TestSize.L LOG_INFO("SlientSwitch_SwitchEnable_Delete_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_Delete_Test_002 +* @tc.desc: Test data deletion when silent switch is enabled with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Enable silent switch using SetSilentSwitch() with empty URI +* 2. Create DataSharePredicates to select record with name="wangwu" +* 3. Create Uri object with SLIENT_ACCESS_URI +* 4. Call Delete() method with URI and predicates +* 5. Verify the return value +* @tc.expect: Delete operation succeeds (return value > 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Delete_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_Delete_Test_002::Start"); @@ -456,6 +727,22 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Delete_Test_002, TestSize.L LOG_INFO("SlientSwitch_SwitchEnable_Delete_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_CreateHelper_Test_001 +* @tc.desc: Test DataShareHelper creation when silent switch is disabled +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: + 1. Create initial DataShareHelper with valid parameters (should succeed) + 2. Disable silent switch using SetSilentSwitch() with empty URI + 3. Try to create another DataShareHelper with same parameters + 4. Re-enable silent switch +* @tc.expect: + 1. First helper creation succeeds (helper != nullptr) + 2. Second helper creation fails (helper == nullptr) + 3. Re-enabling switch returns E_OK +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_CreateHelper_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_CreateHelper_Test_001::Start"); @@ -484,6 +771,23 @@ Template GetTemplate() return tpl; } +/** +* @tc.name: SlientSwitch_SwitchDisable_CreateHelper_Test_002 +* @tc.desc: Test AddQueryTemplate when silent switch is disabled +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Disable silent switch using SetSilentSwitch() with empty URI +* 2. Create DataShareHelper with valid parameters +* 3. Get query template using GetTemplate() +* 4. Call AddQueryTemplate with proxy URI, subscriber ID and template +* 5. Re-enable silent switch +* @tc.expect: +* 1. Helper creation succeeds (helper != nullptr) +* 2. AddQueryTemplate returns ERROR (-1) +* 3. Re-enabling switch returns E_OK +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_CreateHelper_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_CreateHelper_Test_002::Start"); @@ -502,6 +806,21 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_CreateHelper_Test_002, Tes LOG_INFO("SlientSwitch_SwitchDisable_CreateHelper_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_CreateHelper_Test_001 +* @tc.desc: Test AddQueryTemplate when silent switch is enabled (without provider URI) +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Enable silent switch using SetSilentSwitch() with empty URI +* 2. Create DataShareHelper with valid parameters (without provider URI) +* 3. Get query template using GetTemplate() +* 4. Call AddQueryTemplate with proxy URI, subscriber ID and template +* @tc.expect: +* 1. Helper creation succeeds (helper != nullptr) +* 2. AddQueryTemplate returns E_BUNDLE_NAME_NOT_EXIST +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_CreateHelper_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_CreateHelper_Test_001::Start"); @@ -518,6 +837,21 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_CreateHelper_Test_001, Test LOG_INFO("SlientSwitch_SwitchEnable_CreateHelper_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_CreateHelper_Test_002 +* @tc.desc: Test AddQueryTemplate when silent switch is enabled (with provider URI) +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Enable silent switch using SetSilentSwitch() with empty URI +* 2. Create DataShareHelper with valid parameters (including provider URI) +* 3. Get query template using GetTemplate() +* 4. Call AddQueryTemplate with proxy URI, subscriber ID and template +* @tc.expect: +* 1. Helper creation succeeds (helper != nullptr) +* 2. AddQueryTemplate returns E_BUNDLE_NAME_NOT_EXIST +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_CreateHelper_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_CreateHelper_Test_002::Start"); diff --git a/data_share/test/native/unittest/mediadatashare_test/src/uri_utils_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/uri_utils_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..febe91be5be11de8c742c0cb77da29075069a637 --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/uri_utils_test.cpp @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2025 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 "URIUtilsTest" + +#include +#include + +#include "datashare_uri_utils.h" +#include "log_print.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::DataShare; +class URIUtilsTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +/** +* @tc.name: GetUserFromUri_001 +* @tc.desc: Test getting user from URI without user parameter +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest" without user parameter +* 2. Call DataShareURIUtils::GetUserFromUri() with the URI +* 3. Check the return result and user value +* @tc.expect: +* 1. The result is true +* 2. The user value is -1 (default) +*/ +HWTEST_F(URIUtilsTest, GetUserFromUri_001, TestSize.Level0) +{ + ZLOGI("GetUserFromUri_001 starts"); + std::string uri = "datashare:///com.acts.datasharetest"; + auto [res, user] = DataShareURIUtils::GetUserFromUri(uri); + EXPECT_EQ(res, true); + EXPECT_EQ(user, -1); + ZLOGI("GetUserFromUri_001 ends"); +} + +/** +* @tc.name: GetUserFromUri_002 +* @tc.desc: Test getting valid positive user from URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest?user=100" with valid user parameter +* 2. Call DataShareURIUtils::GetUserFromUri() with the URI +* 3. Check the return result and user value +* @tc.expect: +* 1. The result is true +* 2. The user value is 100 +*/ +HWTEST_F(URIUtilsTest, GetUserFromUri_002, TestSize.Level0) +{ + ZLOGI("GetUserFromUri_002 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user=100"; + auto [res, user] = DataShareURIUtils::GetUserFromUri(uri); + EXPECT_EQ(res, true); + EXPECT_EQ(user, 100); + ZLOGI("GetUserFromUri_002 ends"); +} + +/** +* @tc.name: GetUserFromUri_003 +* @tc.desc: Test getting user from URI with non-numeric user parameter +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest?user=f" with invalid user parameter +* 2. Call DataShareURIUtils::GetUserFromUri() with the URI +* 3. Check the return result and user value +* @tc.expect: +* 1. The result is false +* 2. The user value is -1 +*/ +HWTEST_F(URIUtilsTest, GetUserFromUri_003, TestSize.Level0) +{ + ZLOGI("GetUserFromUri_003 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user=f"; + auto [res, user] = DataShareURIUtils::GetUserFromUri(uri); + EXPECT_EQ(res, false); + EXPECT_EQ(user, -1); + ZLOGI("GetUserFromUri_003 ends"); +} + +/** +* @tc.name: GetUserFromUri_004 +* @tc.desc: Test getting user from URI with negative user parameter +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest?user=-1" with negative user parameter +* 2. Call DataShareURIUtils::GetUserFromUri() with the URI +* 3. Check the return result and user value +* @tc.expect: +* 1. The result is false +* 2. The user value is -1 +*/ +HWTEST_F(URIUtilsTest, GetUserFromUri_004, TestSize.Level0) +{ + ZLOGI("GetUserFromUri_004 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user=-1"; + auto [res, user] = DataShareURIUtils::GetUserFromUri(uri); + EXPECT_EQ(res, false); + EXPECT_EQ(user, -1); + ZLOGI("GetUserFromUri_004 ends"); +} + +/** +* @tc.name: GetUserFromUri_005 +* @tc.desc: Test getting user from URI with empty user parameter +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest?user=" with empty user parameter +* 2. Call DataShareURIUtils::GetUserFromUri() with the URI +* 3. Check the return result and user value +* @tc.expect: +* 1. The result is true +* 2. The user value is -1 +*/ +HWTEST_F(URIUtilsTest, GetUserFromUri_005, TestSize.Level0) +{ + ZLOGI("GetUserFromUri_005 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user="; + auto [res, user] = DataShareURIUtils::GetUserFromUri(uri); + EXPECT_EQ(res, true); + EXPECT_EQ(user, -1); + ZLOGI("GetUserFromUri_005 ends"); +} + +/** +* @tc.name: GetUserFromUri_006 +* @tc.desc: Test getting user from URI with whitespace user parameter +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest?user= " with whitespace user parameter +* 2. Call DataShareURIUtils::GetUserFromUri() with the URI +* 3. Check the return result and user value +* @tc.expect: +* 1. The result is false +* 2. The user value is -1 +*/ +HWTEST_F(URIUtilsTest, GetUserFromUri_006, TestSize.Level0) +{ + ZLOGI("GetUserFromUri_006 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user= "; + auto [res, user] = DataShareURIUtils::GetUserFromUri(uri); + EXPECT_EQ(res, false); + EXPECT_EQ(user, -1); + ZLOGI("GetUserFromUri_006 ends"); +} + +/** +* @tc.name: GetUserFromUri_007 +* @tc.desc: Test getting user from URI with overflow user parameter +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: + 1. Create URI "datashare:///com.acts.datasharetest?user=2147483648" with overflow user parameter + 2. Call DataShareURIUtils::GetUserFromUri() with the URI + 3. Check the return result and user value +* @tc.expect: + 1. The result is false + 2. The user value is -1 +*/ +HWTEST_F(URIUtilsTest, GetUserFromUri_007, TestSize.Level0) +{ + ZLOGI("GetUserFromUri_007 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user=2147483648"; + auto [res, user] = DataShareURIUtils::GetUserFromUri(uri); + EXPECT_EQ(res, false); + EXPECT_EQ(user, -1); + ZLOGI("GetUserFromUri_007 ends"); +} + +/** +* @tc.name: GetUserFromUri_008 +* @tc.desc: Test getting user from URI with multiple user parameters +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest?user=100&user=111" with multiple user parameters +* 2. Call DataShareURIUtils::GetUserFromUri() with the URI +* 3. Check the return result and user value +* @tc.expect: +* 1. The result is true +* 2. The user value is 111 (last occurrence) +*/ +HWTEST_F(URIUtilsTest, GetUserFromUri_008, TestSize.Level0) +{ + ZLOGI("GetUserFromUri_008 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user=100&user=111"; + auto [res, user] = DataShareURIUtils::GetUserFromUri(uri); + EXPECT_EQ(res, true); + EXPECT_EQ(user, 111); + ZLOGI("GetUserFromUri_008 ends"); +} + +/** +* @tc.name: GetQueryParams_001 +* @tc.desc: Test getting query parameters from URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest?user=100&srcToken=12345" with query parameters +* 2. Call DataShareURIUtils::GetQueryParams() with the URI +* 3. Check if the result is not empty +* @tc.expect:The returned query parameters are not empty +*/ +HWTEST_F(URIUtilsTest, GetQueryParams_001, TestSize.Level0) +{ + ZLOGI("GetQueryParams_001 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user=100&srcToken=12345"; + auto res = DataShareURIUtils::GetQueryParams(uri); + EXPECT_EQ(res.empty(), false); + ZLOGI("GetQueryParams_001 ends"); +} + +/** +* @tc.name: Strtoul_001 +* @tc.desc: Test converting empty string to unsigned integer +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create empty string +* 2. Call DataShareURIUtils::Strtoul() with the empty string +* 3. Check the return result and converted value +* @tc.expect: +* 1. The result is false +* 2. The converted value is 0 +*/ +HWTEST_F(URIUtilsTest, Strtoul_001, TestSize.Level0) +{ + ZLOGI("Strtoul_001 starts"); + std::string str = ""; + std::pair res = DataShareURIUtils::Strtoul(str); + EXPECT_EQ(res.first, false); + EXPECT_EQ(res.second, 0); + ZLOGI("Strtoul_001 ends"); +} + +/** +* @tc.name: FormatUri_001 +* @tc.desc: Test formatting URI by removing query parameters +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest?user=100&srcToken=12345" with query parameters +* 2. Call DataShareURIUtils::FormatUri() with the URI +* 3. Check the formatted URI +* @tc.expect:The formatted URI is "datashare:///com.acts.datasharetest" without query parameters +*/ +HWTEST_F(URIUtilsTest, FormatUri_001, TestSize.Level0) +{ + ZLOGI("FormatUri_001 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user=100&srcToken=12345"; + std::string res = DataShareURIUtils::FormatUri(uri); + EXPECT_EQ(res, "datashare:///com.acts.datasharetest"); + ZLOGI("FormatUri_001 ends"); +} + +/** +* @tc.name: FormatUri_002 +* @tc.desc: Test formatting URI without query parameters +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest" without query parameters +* 2. Call DataShareURIUtils::FormatUri() with the URI +* 3. Check the formatted URI +* @tc.expect:The formatted URI is the same as input "datashare:///com.acts.datasharetest" +*/ +HWTEST_F(URIUtilsTest, FormatUri_002, TestSize.Level0) +{ + ZLOGI("FormatUri_002 starts"); + std::string uri = "datashare:///com.acts.datasharetest"; + std::string res = DataShareURIUtils::FormatUri(uri); + EXPECT_EQ(res, "datashare:///com.acts.datasharetest"); + ZLOGI("FormatUri_002 ends"); +} +} // namespace DataShare +} \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/valueproxy_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/valueproxy_test.cpp index ade97386a84c049c90884f1e717dda8bcd0c66e7..950d26d0533819bc57f9841e040682b6616a6471 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/valueproxy_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/valueproxy_test.cpp @@ -22,6 +22,20 @@ namespace DataShare { using namespace testing::ext; class ValueProxyTest : public testing::Test { }; + +/** +* @tc.name: VBucketsDataShare2Normal +* @tc.desc: Test conversion from DataShareValuesBucket vector to normal VBuckets +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create two DataShareValuesBucket objects and add key-value pairs +* 2. Put the buckets into a vector +* 3. Convert the vector using ValueProxy::Convert() +* 4. Verify the converted VBuckets size is 2 +* @tc.expect: The converted VBuckets has size 2, matching original vector size +*/ HWTEST_F(ValueProxyTest, VBucketsDataShare2Normal, TestSize.Level0) { using DataShareBucket = OHOS::DataShare::DataShareValuesBucket; @@ -35,6 +49,19 @@ HWTEST_F(ValueProxyTest, VBucketsDataShare2Normal, TestSize.Level0) extends = ValueProxy::Convert(std::move(VBuckets)); ASSERT_EQ(extends.size(), 2); } + +/** +* @tc.name: VBucketsNormal2DataShare +* @tc.desc: Test conversion from normal VBuckets to DataShareValuesBucket vector +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create a VBuckets object with two entries containing key-value pairs +* 2. Convert the VBuckets using ValueProxy::Convert() +* 3. Verify the converted DataShareValuesBucket vector size is 2 +* @tc.expect: The converted vector has size 2, matching original VBuckets size +*/ HWTEST_F(ValueProxyTest, VBucketsNormal2DataShare, TestSize.Level0) { using DataShareBucket = OHOS::DataShare::DataShareValuesBucket; diff --git a/data_share/test/native/unittest/mock/ikvstore_data_service_mock.h b/data_share/test/native/unittest/mock/ikvstore_data_service_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..22eb89f400e821cf7e6dff85fdcd088727cafce2 --- /dev/null +++ b/data_share/test/native/unittest/mock/ikvstore_data_service_mock.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 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 IKVSTORE_DATA_SERVICE_MOCK_H +#define IKVSTORE_DATA_SERVICE_MOCK_H + +#include +#include "gmock/gmock.h" +#include "ikvstore_data_service.h" + +namespace OHOS { +namespace DataShare { +class MockDataShareKvServiceProxy : public DataShareKvServiceProxy { +public: + explicit MockDataShareKvServiceProxy(const sptr &impl) + : DataShareKvServiceProxy(impl) {} + ~MockDataShareKvServiceProxy() = default; + MOCK_METHOD(sptr, GetFeatureInterface, (const std::string &name), (override)); + MOCK_METHOD(uint32_t, RegisterClientDeathObserver, (const std::string &appId, sptr observer), + (override)); +}; +} +} +#endif // IKVSTORE_DATA_SERVICE_MOCK_H \ No newline at end of file diff --git a/relational_store/test/js/gdb/BUILD.gn b/data_share/test/unittest/native/BUILD.gn similarity index 58% rename from relational_store/test/js/gdb/BUILD.gn rename to data_share/test/unittest/native/BUILD.gn index 903b0e9ffc53f5be249ab2a867bd4cfb77676304..0fc82db364ec1aacde455842e03f5761457ed4c0 100644 --- a/relational_store/test/js/gdb/BUILD.gn +++ b/data_share/test/unittest/native/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2024 Huawei Device Co., Ltd. +# Copyright (C) 2025 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 @@ -12,24 +12,20 @@ # limitations under the License. import("//build/test.gni") -import("//foundation/distributeddatamgr/relational_store/relational_store.gni") -#################################group######################################### +################################################################## group("unittest") { testonly = true deps = [] - if (arkdata_db_core_is_exists) { - deps += [ "unittest/src:unittest" ] - } + deps += [ + "consumer:unittest", + "common:unittest", + "provider:unittest", + "../../native/resource/datashare_ext_bundle:datashare_ext", + "../../native/resource/datashareproxy_bundle/proxydatas_with_permission:proxydatas_with_permission", + "../../native/resource/errorcode_ext_bundle:errorcode_ext", + "../../native/resource/ohos_test_new:copy_ohos_test_new", + ] } - -group("performancetest") { - testonly = true - deps = [] - - if (arkdata_db_core_is_exists) { - deps += [ "performance/src:GdbPerfJsTest" ] - } -} -############################################################################### +################################################################## \ No newline at end of file diff --git a/data_share/test/unittest/native/common/BUILD.gn b/data_share/test/unittest/native/common/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..9024aadc772d405e3d7738e5337df0a236d35355 --- /dev/null +++ b/data_share/test/unittest/native/common/BUILD.gn @@ -0,0 +1,235 @@ +# Copyright (C) 2025 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/test.gni") +import("//foundation/distributeddatamgr/data_share/datashare.gni") + +group("unittest") { + testonly = true + deps = [] + + deps += [ + ":DataShareAbsResultSetTest", + ":DataShareBlockWriterImplTest", + ":DatashareResultSetTest", + ":ValueProxyTest", + ":IsharedResultSetStubTest", + ] +} + +config("permission_config") { + visibility = [ ":*" ] + include_dirs = [ + "${datashare_common_native_path}/include", + "${datashare_native_permission_path}/include", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } +} + +ohos_unittest("DataShareAbsResultSetTest") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "${datashare_base_path}/cfi_blocklist.txt" + } + + module_out_path = "data_share/data_share/native/common" + + include_dirs = [ "${datashare_base_path}/frameworks/native/common/include/" ] + + sources = [ "${datashare_base_path}/test/unittest/native/common/src/datashare_abs_result_set_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "googletest:gmock_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "ipc:rpc", + "ipc:ipc_core", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DataShareBlockWriterImplTest") { + module_out_path = "data_share/data_share/native/common" + + include_dirs = [ + "${datashare_native_consumer_path}/include", + "${datashare_common_native_path}/include", + "${datashare_innerapi_path}/consumer/include", + "${datashare_innerapi_path}/common/include", + "${datashare_innerapi_path}/provider/include", + "${datashare_native_consumer_path}/controller/provider/include", + "${datashare_native_consumer_path}/controller/common", + "${datashare_native_consumer_path}/controller/service/include", + "${datashare_native_proxy_path}/include", + ] + + sources = [ + "${datashare_base_path}/test/unittest/native/common/src/datashare_block_writer_impl_test.cpp", + ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:zuri", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "kv_store:distributeddata_inner", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DatashareResultSetTest") { + module_out_path = "data_share/data_share/native/common" + + include_dirs = [ "${datashare_base_path}/frameworks/native/common/include/" ] + + sources = [ "${datashare_base_path}/test/unittest/native/common/src/datashare_result_set_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "ipc:rpc", + "ipc:ipc_core", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + + +ohos_unittest("ValueProxyTest") { + module_out_path = "data_share/data_share/native/common" + + include_dirs = [ "${datashare_base_path}/frameworks/native/common/include/" ] + + sources = [ "${datashare_base_path}/test/unittest/native/common/src/datashare_valuebucket_convert_test.cpp" ] + + deps = [ "${datashare_innerapi_path}/common:datashare_common_static" ] + + external_deps = [ + "ability_base:zuri", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "kv_store:distributeddata_inner", + ] +} + + +ohos_unittest("IsharedResultSetStubTest") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "${datashare_base_path}/cfi_blocklist.txt" + } + + module_out_path = "data_share/data_share/native/common" + + include_dirs = [ "${datashare_base_path}/frameworks/native/common/include/" ] + + sources = [ "${datashare_base_path}/test/unittest/native/common/src/ishared_result_set_stub_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "ipc:rpc", + "ipc:ipc_core", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} \ No newline at end of file diff --git a/data_share/test/unittest/native/common/src/datashare_abs_result_set_test.cpp b/data_share/test/unittest/native/common/src/datashare_abs_result_set_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f6565c375758232256620035993bbd5ab5f7418 --- /dev/null +++ b/data_share/test/unittest/native/common/src/datashare_abs_result_set_test.cpp @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2025 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 + +#include "datashare_errno.h" +#include "datashare_itypes_utils.h" +#include "datashare_log.h" +#include "datashare_abs_result_set.h" +#include "datashare_result_set.h" +#include "ikvstore_data_service.h" +#include "ipc_types.h" +#include "ishared_result_set_stub.h" +#include "itypes_util.h" +#include "message_parcel.h" +#include "gmock/gmock.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +class DataShareAbsResultSetTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +class MockDataShareAbsResultSet : public DataShareAbsResultSet { +public: + MOCK_METHOD1(GoToRow, int(int)); + MOCK_METHOD1(GetRowCount, int(int &)); + MOCK_METHOD1(GetAllColumnNames, int(std::vector &)); + MOCK_METHOD1(GetColumnCount, int(int &)); +}; + +class MockDataShareAbsResultSet2 : public DataShareAbsResultSet { +public: + MOCK_METHOD1(GetAllColumnNames, int(std::vector &)); +}; + +/** +* @tc.name: GoToTest001 +* @tc.desc: test GoTo function when GoToRow return E_ERROR +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GoTo function when GoToRow return E_ERROR and check the result +* @tc.experct: GoTo failed and return E_ERROR +*/ +HWTEST_F(DataShareAbsResultSetTest, GoToTest001, TestSize.Level0) +{ + LOG_INFO("DataShareAbsResultSetTest GoToTest001::Start"); + MockDataShareAbsResultSet mockResultSet; + int offset = 1; + EXPECT_CALL(mockResultSet, GoToRow(testing::_)) + .WillOnce(testing::Return(E_ERROR)); + auto result = mockResultSet.GoTo(offset); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareAbsResultSetTest GoToTest001::End"); +} + +/** +* @tc.name: GoToTest002 +* @tc.desc: test GoTo function +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GoTo function and check the result +* @tc.experct: GoTo success and return E_OK +*/ +HWTEST_F(DataShareAbsResultSetTest, GoToTest002, TestSize.Level0) +{ + LOG_INFO("DataShareAbsResultSetTest GoToTest002::Start"); + DataShareAbsResultSet dataShareAbsResultSet; + int offset = 1; + auto result = dataShareAbsResultSet.GoTo(offset); + EXPECT_EQ(result, E_OK); + LOG_INFO("DataShareAbsResultSetTest GoToTest002::End"); +} + +/** +* @tc.name: IsEndedTest001 +* @tc.desc: test IsEnded function when GetRowCount return E_ERROR +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call IsEnded function when GetRowCount return E_ERROR and check the result +* @tc.experct: IsEnded failed and return E_ERROR +*/ +HWTEST_F(DataShareAbsResultSetTest, IsEndedTest001, TestSize.Level0) +{ + LOG_INFO("DataShareAbsResultSetTest IsEndedTest001::Start"); + MockDataShareAbsResultSet mockResultSet; + EXPECT_CALL(mockResultSet, GetRowCount(testing::_)) + .WillOnce(testing::Return(E_ERROR)); + bool test = true; + auto result = mockResultSet.IsEnded(test); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareAbsResultSetTest IsEndedTest001::End"); +} + +/** +* @tc.name: IsEndedTest002 +* @tc.desc: test IsEnded function +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call IsEnded function and check the result +* @tc.experct: IsEnded success and return E_OK +*/ +HWTEST_F(DataShareAbsResultSetTest, IsEndedTest002, TestSize.Level0) +{ + LOG_INFO("DataShareAbsResultSetTest IsEndedTest002::Start"); + DataShareAbsResultSet dataShareAbsResultSet; + bool test = true; + auto result = dataShareAbsResultSet.IsEnded(test); + EXPECT_EQ(result, E_OK); + LOG_INFO("DataShareAbsResultSetTest IsEndedTest002::End"); +} + +/** +* @tc.name: GetColumnCountTest001 +* @tc.desc: test GetColumnCount function when GetAllColumnNames return E_ERROR +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet2 object + 2.call GetColumnCount function when GetAllColumnNames return E_ERROR and check the result +* @tc.experct: GetColumnCount failed and return E_ERROR +*/ +HWTEST_F(DataShareAbsResultSetTest, GetColumnCountTest001, TestSize.Level0) +{ + LOG_INFO("DataShareAbsResultSetTest GetColumnCountTest001::Start"); + MockDataShareAbsResultSet2 mockResultSet; + int offset = -1; + mockResultSet.count_ = -1; + EXPECT_CALL(mockResultSet, GetAllColumnNames(testing::_)) + .WillOnce(testing::Return(E_ERROR)); + auto result = mockResultSet.GetColumnCount(offset); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareAbsResultSetTest GetColumnCountTest001::End"); +} + +/** +* @tc.name: GetColumnName001 +* @tc.desc: test GetColumnName function when GetColumnCount return E_ERROR +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GetColumnName function when GetColumnCount return E_ERROR and check the result +* @tc.experct: GetColumnName failed and return E_ERROR +*/ +HWTEST_F(DataShareAbsResultSetTest, GetColumnName001, TestSize.Level0) +{ + LOG_INFO("DataShareAbsResultSetTest GetColumnName001::Start"); + MockDataShareAbsResultSet mockResultSet; + int columnIndex = 1; + std::string columnName = "test"; + EXPECT_CALL(mockResultSet, GetColumnCount(testing::_)) + .WillOnce(testing::Return(E_ERROR)); + auto result = mockResultSet.GetColumnName(columnIndex, columnName); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareAbsResultSetTest GetColumnName001::End"); +} + +/** +* @tc.name: GetColumnName002 +* @tc.desc: test GetColumnName function when columnIndex >= 0 +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GetColumnName function when columnIndex >= 0 and check the result +* @tc.experct: GetColumnName failed and return E_INVALID_COLUMN_INDEX +*/ +HWTEST_F(DataShareAbsResultSetTest, GetColumnName002, TestSize.Level0) +{ + LOG_INFO("DataShareAbsResultSetTest MarshallingTest002::Start"); + DataShareAbsResultSet dataShareAbsResultSet; + int columnIndex = 1; + std::string columnName = "test"; + auto result = dataShareAbsResultSet.GetColumnName(columnIndex, columnName); + EXPECT_EQ(result, E_INVALID_COLUMN_INDEX); + LOG_INFO("DataShareAbsResultSetTest MarshallingTest002::End"); +} + +/** +* @tc.name: GetColumnName003 +* @tc.desc: test GetColumnName function when columnIndex < 0 +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GetColumnName function when columnIndex < 0 and check the result +* @tc.experct: GetColumnName failed and return E_INVALID_COLUMN_INDEX +*/ +HWTEST_F(DataShareAbsResultSetTest, GetColumnName003, TestSize.Level0) +{ + LOG_INFO("DataShareAbsResultSetTest MarshallingTest002::Start"); + DataShareAbsResultSet dataShareAbsResultSet; + int columnIndex = -1; + std::string columnName = "test"; + auto result = dataShareAbsResultSet.GetColumnName(columnIndex, columnName); + EXPECT_EQ(result, E_INVALID_COLUMN_INDEX); + LOG_INFO("DataShareAbsResultSetTest MarshallingTest002::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/unittest/native/common/src/datashare_block_writer_impl_test.cpp b/data_share/test/unittest/native/common/src/datashare_block_writer_impl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3b206690bd2c323aa1f645e2fa473045a431d93e --- /dev/null +++ b/data_share/test/unittest/native/common/src/datashare_block_writer_impl_test.cpp @@ -0,0 +1,193 @@ +/* +* Copyright (C) 2025 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 + +#include "datashare_block_writer_impl.h" +#include "datashare_log.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +class DataShareBlockWriterImplTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +/** +* @tc.name: AllocRowTest001 +* @tc.desc: test AllocRow function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call AllocRow function and check the result +* @tc.experct: AllocRow failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, AllocRowTest001, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest AllocRowTest001::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + auto result = dataShareBlockWriterImpl.AllocRow(); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest AllocRowTest001::End"); +} + +/** +* @tc.name: WriteTest001 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest001, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest001::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + auto result = dataShareBlockWriterImpl.Write(column); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest001::End"); +} + +/** +* @tc.name: WriteTest002 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest002, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest002::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + int64_t value = 1; + auto result = dataShareBlockWriterImpl.Write(column, value); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest002::End"); +} + +/** +* @tc.name: WriteTest003 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest003, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest003::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + double value = 1; + auto result = dataShareBlockWriterImpl.Write(column, value); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest003::End"); +} + +/** +* @tc.name: WriteTest004 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest004, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest004::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + uint8_t value[3] = {1}; + size_t size = 1; + auto result = dataShareBlockWriterImpl.Write(column, value, size); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest004::End"); +} + +/** +* @tc.name: WriteTest005 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest005, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest005::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + const char* value = "test"; + size_t sizeIncludingNull = 1; + auto result = dataShareBlockWriterImpl.Write(column, value, sizeIncludingNull); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest005::End"); +} + +/** +* @tc.name: GetCurrentRowIndexTest001 +* @tc.desc: test GetCurrentRowIndex function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call GetCurrentRowIndex function and check the result +* @tc.experct: GetCurrentRowIndex failed and reutrn false +*/ +HWTEST_F(DataShareBlockWriterImplTest, GetCurrentRowIndexTest001, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest GetCurrentRowIndexTest001::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t rowIndex = 1; + auto result = dataShareBlockWriterImpl.GetCurrentRowIndex(rowIndex); + EXPECT_EQ(result, false); + LOG_INFO("DataShareBlockWriterImplTest GetCurrentRowIndexTest001::End"); +} + +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/unittest/native/common/src/datashare_result_set_test.cpp b/data_share/test/unittest/native/common/src/datashare_result_set_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6f767dfadefadc32c5a936882847a8a5bc1c7856 --- /dev/null +++ b/data_share/test/unittest/native/common/src/datashare_result_set_test.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2025 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 + +#include "datashare_errno.h" +#include "datashare_itypes_utils.h" +#include "datashare_log.h" +#include "datashare_abs_result_set.h" +#include "datashare_result_set.h" +#include "ikvstore_data_service.h" +#include "ipc_types.h" +#include "ishared_result_set_stub.h" +#include "itypes_util.h" +#include "message_parcel.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +class DatashareResultSetTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +/** +* @tc.name: GetDataTypeTest001 +* @tc.desc: test GetDataType function when sharedBlock_ is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object and sharedBlock_ is nullptr + 2.call GetDataType function and check the result +* @tc.experct: GetDataType failed and return E_ERROR +*/ +HWTEST_F(DatashareResultSetTest, GetDataTypeTest001, TestSize.Level0) +{ + LOG_INFO("DatashareResultSetTest GetDataTypeTest001::Start"); + DataShareResultSet dataShareResultSet; + int columnIndex = 1; + DataShare::DataType dataType; + auto result = dataShareResultSet.GetDataType(columnIndex, dataType); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DatashareResultSetTest GetDataTypeTest001::End"); +} + +/** +* @tc.name: CheckStateTest001 +* @tc.desc: test CheckState function when columnIndex >= 0 +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object + 2.call CheckState function when columnIndex >= 0 and check the result +* @tc.experct: CheckState failed and return E_INVALID_COLUMN_INDEX +*/ +HWTEST_F(DatashareResultSetTest, CheckStateTest001, TestSize.Level0) +{ + LOG_INFO("DatashareResultSetTest CheckStateTest001::Start"); + DataShareResultSet dataShareResultSet; + int columnIndex = 1; + auto result = dataShareResultSet.CheckState(columnIndex); + EXPECT_EQ(result, E_INVALID_COLUMN_INDEX); + LOG_INFO("DatashareResultSetTest CheckStateTest001::End"); +} + +/** +* @tc.name: CheckStateTest002 +* @tc.desc: test CheckState function when columnIndex < 0 +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object + 2.call CheckState function when columnIndex < 0 and check the result +* @tc.experct: CheckState failed and return E_INVALID_COLUMN_INDEX +*/ +HWTEST_F(DatashareResultSetTest, CheckStateTest002, TestSize.Level0) +{ + LOG_INFO("DatashareResultSetTest CheckState002::Start"); + DataShareResultSet dataShareResultSet; + int columnIndex = -1; + auto result = dataShareResultSet.CheckState(columnIndex); + EXPECT_EQ(result, E_INVALID_COLUMN_INDEX); + LOG_INFO("DatashareResultSetTest CheckState002::End"); +} + +/** +* @tc.name: MarshalTest001 +* @tc.desc: test Marshal function when resultset = nullptr +* @tc.type: FUNC +* @tc.require: issueICCAXH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object when resultset = nullptr + 2.call Marshal function and check the result +* @tc.experct: Marshal failed and return false +*/ +HWTEST_F(DatashareResultSetTest, MarshalTest001, TestSize.Level0) +{ + LOG_INFO("DatashareResultSetTest MarshalTest001::Start"); + DataShareResultSet dataShareResultSet; + std::shared_ptr resultset = nullptr; + MessageParcel parcel; + auto result = dataShareResultSet.Marshal(resultset, parcel); + EXPECT_FALSE(result); + LOG_INFO("DatashareResultSetTest MarshalTest001::End"); +} + +/** +* @tc.name: UnmarshalTest001 +* @tc.desc: test Unmarshal function +* @tc.type: FUNC +* @tc.require: issueICCAXH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object + 2.call Unmarshal function and check the result +* @tc.experct: Unmarshal failed and return nullptr +*/ +HWTEST_F(DatashareResultSetTest, UnmarshalTest001, TestSize.Level0) +{ + LOG_INFO("DatashareResultSetTest UnmarshalTest001::Start"); + DataShareResultSet dataShareResultSet; + MessageParcel parcel; + auto result = dataShareResultSet.Unmarshal(parcel); + EXPECT_EQ(result, nullptr); + LOG_INFO("DatashareResultSetTest UnmarshalTest001::End"); +} + +/** +* @tc.name: MarshallingTest001 +* @tc.desc: test Marshalling function when sharedBlock_ is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object + 2.call Marshalling function when sharedBlock_ is nullptr and check the result +* @tc.experct: Marshalling failed and return false +*/ +HWTEST_F(DatashareResultSetTest, MarshallingTest001, TestSize.Level0) +{ + LOG_INFO("DatashareResultSetTest MarshallingTest001::Start"); + DataShareResultSet dataShareResultSet; + MessageParcel parcel; + auto result = dataShareResultSet.Marshalling(parcel); + EXPECT_FALSE(result); + LOG_INFO("DatashareResultSetTest MarshallingTest001::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/unittest/native/common/src/datashare_valuebucket_convert_test.cpp b/data_share/test/unittest/native/common/src/datashare_valuebucket_convert_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ade97386a84c049c90884f1e717dda8bcd0c66e7 --- /dev/null +++ b/data_share/test/unittest/native/common/src/datashare_valuebucket_convert_test.cpp @@ -0,0 +1,50 @@ +/* + * 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 +#include "datashare_valuebucket_convert.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +class ValueProxyTest : public testing::Test { +}; +HWTEST_F(ValueProxyTest, VBucketsDataShare2Normal, TestSize.Level0) +{ + using DataShareBucket = OHOS::DataShare::DataShareValuesBucket; + DataShareBucket valuesBucket1; + DataShareBucket valuesBucket2; + valuesBucket1.Put("phoneNumber", 20.07); + valuesBucket1.Put("name", "dataShareTest003"); + valuesBucket2.Put("age", 1001); + std::vector VBuckets = {valuesBucket1, valuesBucket2}; + DataShareObserver::ChangeInfo::VBuckets extends; + extends = ValueProxy::Convert(std::move(VBuckets)); + ASSERT_EQ(extends.size(), 2); +} +HWTEST_F(ValueProxyTest, VBucketsNormal2DataShare, TestSize.Level0) +{ + using DataShareBucket = OHOS::DataShare::DataShareValuesBucket; + std::vector VBuckets; + DataShareObserver::ChangeInfo::VBuckets extends = { + {{"phoneNumber", 20.07}, {"name", "dataShareTest003"}}, + {{"age", 1001}} + }; + VBuckets = ValueProxy::Convert(std::move(extends)); + ASSERT_EQ(VBuckets.size(), 2); +} +} // namespace DataShare +} \ No newline at end of file diff --git a/data_share/test/unittest/native/common/src/ishared_result_set_stub_test.cpp b/data_share/test/unittest/native/common/src/ishared_result_set_stub_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8a5661d4037b48cf2c7af55aa9cfb3ec8534064b --- /dev/null +++ b/data_share/test/unittest/native/common/src/ishared_result_set_stub_test.cpp @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2025 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 +#include + +#include "datashare_errno.h" +#include "datashare_itypes_utils.h" +#include "datashare_log.h" +#include "datashare_abs_result_set.h" +#include "datashare_result_set.h" +#include "ikvstore_data_service.h" +#include "ipc_types.h" +#include "ishared_result_set_stub.h" +#include "itypes_util.h" +#include "message_parcel.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +class IsharedResultSetStubTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +class ResultSetBridgeTest : public OHOS::DataShare::ResultSetBridge { +public: + int GetAllColumnNames(std::vector &columnNames) override + { + return 0; + } + + int GetRowCount(int32_t &count) override + { + return 0; + } + + int OnGo(int32_t startRowIndex, int32_t targetRowIndex, Writer &writer) override + { + return 0; + } +}; + +/** +* @tc.name: CreateStubTestTest001 +* @tc.desc: test CreateStub function when resuletset_ = nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and resuletset_ = nullptr + 2.call CreateStub function and check the result +* @tc.experct: CreateStub failed and reutrn nullptr +*/ +HWTEST_F(IsharedResultSetStubTest, CreateStubTest001, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest CreateStubTest001::Start"); + std::shared_ptr resultset; + MessageParcel parcel; + ISharedResultSetStub stub(resultset); + auto result = stub.CreateStub(resultset, parcel); + EXPECT_EQ(result, nullptr); + LOG_INFO("IsharedResultSetStubTest CreateStubTest001::End"); +} + +/** +* @tc.name: CreateStubTestTest002 +* @tc.desc: test CreateStub function when resuletset_ is not nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and resuletset_ is not nullptr + 2.call CreateStub function and check the result +* @tc.experct: CreateStub succees and not reutrn nullptr +*/ +HWTEST_F(IsharedResultSetStubTest, CreateStubTestTest002, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest CreateStubTestTest002::Start"); + std::shared_ptr resultset = std::make_shared(); + MessageParcel parcel; + ISharedResultSetStub stub(resultset); + auto result = stub.CreateStub(resultset, parcel); + EXPECT_NE(result, nullptr); + LOG_INFO("IsharedResultSetStubTest CreateStubTestTest002::End"); +} + +/** +* @tc.name: OnRemoteRequestTest001 +* @tc.desc: test OnRemoteRequest function when resuletset_ = nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and resuletset_ = nullptr + 2.call OnRemoteRequest function and check the result +* @tc.experct: OnRemoteRequest failed and reutrn INVALID_FD +*/ +HWTEST_F(IsharedResultSetStubTest, OnRemoteRequestTest001, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest OnRemoteRequestTest001::Start"); + std::shared_ptr resultset; + ISharedResultSetStub stub(resultset); + uint32_t code = 0; + MessageParcel data; + MessageParcel parcel; + MessageOption option; + auto result = stub.OnRemoteRequest(code, data, parcel, option); + EXPECT_EQ(result, INVALID_FD); + LOG_INFO("IsharedResultSetStubTest OnRemoteRequestTest001::End"); +} + +/** +* @tc.name: HandleGetRowCountRequestTest001 +* @tc.desc: test HandleGetRowCountRequest function when bridge = nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is nullptr + 2.call HandleGetRowCountRequest function and check the result +* @tc.experct: HandleGetRowCountRequest success and write E_ERROR into reply +*/ +HWTEST_F(IsharedResultSetStubTest, HandleGetRowCountRequestTest001, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest HandleGetRowCountRequestTest001::Start"); + std::shared_ptr resultset = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleGetRowCountRequest(data, reply); + EXPECT_EQ(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("IsharedResultSetStubTest HandleGetRowCountRequestTest001::End"); +} + +/** +* @tc.name: HandleGetRowCountRequestTest002 +* @tc.desc: test HandleGetRowCountRequest function when bridge is not nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is not nullptr + 2.call HandleGetRowCountRequest function and check the result +* @tc.experct: HandleGetRowCountRequest success and write count into reply +*/ +HWTEST_F(IsharedResultSetStubTest, HandleGetRowCountRequestTest002, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest HandleGetRowCountRequestTest002::Start"); + std::shared_ptr resultset = std::make_shared(); + resultset->bridge_ = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleGetRowCountRequest(data, reply); + EXPECT_NE(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("IsharedResultSetStubTest HandleGetRowCountRequestTest002::End"); +} + +/** +* @tc.name: HandleGetAllColumnNamesRequestTest001 +* @tc.desc: test HandleGetAllColumnNamesRequest function when bridge is nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is nullptr + 2.call HandleGetAllColumnNamesRequest function and check the result +* @tc.experct: HandleGetAllColumnNamesRequest success and write E_ERROR into reply +*/ +HWTEST_F(IsharedResultSetStubTest, HandleGetAllColumnNamesRequestTest001, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest HandleGetAllColumnNamesRequestTest001::Start"); + std::shared_ptr resultset = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleGetAllColumnNamesRequest(data, reply); + EXPECT_EQ(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("IsharedResultSetStubTest HandleGetAllColumnNamesRequestTest001::End"); +} + +/** +* @tc.name: HandleGetAllColumnNamesRequestTest002 +* @tc.desc: test HandleGetAllColumnNamesRequest function when bridge is not nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is not nullptr + 2.call HandleGetAllColumnNamesRequest function and check the result +* @tc.experct: HandleGetAllColumnNamesRequest success and write count into reply +*/ +HWTEST_F(IsharedResultSetStubTest, HandleGetAllColumnNamesRequestTest002, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest HandleGetAllColumnNamesRequestTest002::Start"); + std::shared_ptr resultset = std::make_shared(); + resultset->bridge_ = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleGetAllColumnNamesRequest(data, reply); + EXPECT_NE(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("IsharedResultSetStubTest HandleGetAllColumnNamesRequestTest002::End"); +} + +/** +* @tc.name: HandleOnGoRequestTest001 +* @tc.desc: test HandleOnGoRequest function when bridge is nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is nullptr + 2.call HandleOnGoRequest function and check the result +* @tc.experct: HandleOnGoRequest success and write -1 into reply +*/ +HWTEST_F(IsharedResultSetStubTest, HandleOnGoRequestTest001, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest HandleOnGoRequestTest001::Start"); + std::shared_ptr resultset = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleOnGoRequest(data, reply); + EXPECT_EQ(reply.ReadInt32(), -1); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("IsharedResultSetStubTest HandleOnGoRequestTest001::End"); +} + +/** +* @tc.name: HandleOnGoRequestTest002 +* @tc.desc: test HandleOnGoRequest function when bridge is not nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is not nullptr + 2.call HandleOnGoRequest function and check the result +* @tc.experct: HandleOnGoRequest success and write count into reply +*/ +HWTEST_F(IsharedResultSetStubTest, HandleOnGoRequestTest002, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest HandleOnGoRequestTest002::Start"); + std::shared_ptr resultset = std::make_shared(); + resultset->bridge_ = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleOnGoRequest(data, reply); + EXPECT_NE(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("IsharedResultSetStubTest HandleOnGoRequestTest002::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/unittest/native/consumer/BUILD.gn b/data_share/test/unittest/native/consumer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..076d51e4e27b6fd0155c67ccd2fc0409b6149318 --- /dev/null +++ b/data_share/test/unittest/native/consumer/BUILD.gn @@ -0,0 +1,275 @@ +# Copyright (C) 2025 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/test.gni") +import("//foundation/distributeddatamgr/data_share/datashare.gni") + +group("unittest") { + testonly = true + deps = [] + + deps += [ + ":DataShareHelperImplTest", + ":DataShareHelperTest", + ":DataShareProxyTest", + ":DataShareConnectionTest", + ] +} + +config("permission_config") { + visibility = [ ":*" ] + include_dirs = [ + "${datashare_common_native_path}/include", + "${datashare_native_permission_path}/include", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } +} + +ohos_unittest("DataShareConnectionTest") { + module_out_path = "data_share/data_share/native/consumer" + + include_dirs = [ + "${datashare_innerapi_path}/consumer/include", + "${datashare_native_consumer_path}/controller/common", + "${datashare_native_consumer_path}/controller/provider/include", + "${datashare_native_consumer_path}/controller/service/include", + "${datashare_native_consumer_path}/include", + "${datashare_innerapi_path}/common/include", + "${datashare_native_proxy_path}/include", + ] + + sources = + [ "${datashare_base_path}/test/unittest/native/consumer/src/datashare_connection_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_single", + "relational_store:rdb_data_ability_adapter", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + } +} + +ohos_unittest("DataShareHelperImplTest") { + module_out_path = "data_share/data_share/native/consumer" + + include_dirs = [ + "${datashare_native_consumer_path}/include", + "${datashare_common_native_path}/include", + "${datashare_innerapi_path}/consumer/include", + "${datashare_innerapi_path}/common/include", + "${datashare_innerapi_path}/provider/include", + "${datashare_native_consumer_path}/controller/provider/include", + "${datashare_native_consumer_path}/controller/common", + "${datashare_native_consumer_path}/controller/service/include", + "${datashare_native_proxy_path}/include", + ] + + sources = [ + "${datashare_common_native_path}/src/call_reporter.cpp", + "${datashare_common_native_path}/src/datashare_abs_result_set.cpp", + "${datashare_common_native_path}/src/datashare_itypes_utils.cpp", + "${datashare_common_native_path}/src/datashare_result_set.cpp", + "${datashare_common_native_path}/src/datashare_string_utils.cpp", + "${datashare_common_native_path}/src/datashare_template.cpp", + "${datashare_common_native_path}/src/datashare_uri_utils.cpp", + "${datashare_common_native_path}/src/ikvstore_data_service.cpp", + "${datashare_common_native_path}/src/ishared_result_set.cpp", + "${datashare_common_native_path}/src/ishared_result_set_proxy.cpp", + "${datashare_native_consumer_path}/controller/provider/src/ext_special_controller.cpp", + "${datashare_native_consumer_path}/controller/service/src/general_controller_service_impl.cpp", + "${datashare_native_consumer_path}/controller/service/src/persistent_data_controller.cpp", + "${datashare_native_consumer_path}/controller/service/src/published_data_controller.cpp", + "${datashare_native_consumer_path}/src/datashare_connection.cpp", + "${datashare_native_consumer_path}/src/datashare_helper.cpp", + "${datashare_native_consumer_path}/src/datashare_helper_impl.cpp", + "${datashare_native_consumer_path}/src/datashare_proxy.cpp", + "${datashare_native_proxy_path}/src/ams_mgr_proxy.cpp", + "${datashare_native_proxy_path}/src/data_proxy_observer_stub.cpp", + "${datashare_native_proxy_path}/src/data_share_manager_impl.cpp", + "${datashare_native_proxy_path}/src/data_share_service_proxy.cpp", + "${datashare_native_proxy_path}/src/idata_share_client_death_observer.cpp", + "${datashare_native_proxy_path}/src/published_data_subscriber_manager.cpp", + "${datashare_native_proxy_path}/src/rdb_subscriber_manager.cpp", + "${datashare_native_proxy_path}/src/proxy_data_subscriber_manager.cpp", + "${datashare_base_path}/test/unittest/native/consumer/src/datashare_helper_impl_test.cpp", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "googletest:gmock_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "ipc:rpc", + "kv_store:distributeddata_inner", + "relational_store:native_appdatafwk", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DataShareHelperTest") { + module_out_path = "data_share/data_share/native/consumer" + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "${datashare_base_path}/cfi_blocklist.txt" + } + + include_dirs = [ + "${datashare_base_path}/frameworks/native/common/include/", + "${datashare_base_path}/test/unittest/native/consumer/include/", + ] + + sources = [ "${datashare_base_path}/test/unittest/native/consumer/src/datashare_helper_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "googletest:gmock_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "ipc:rpc", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DataShareProxyTest") { + module_out_path = "data_share/data_share/native/consumer" + + include_dirs = [ + "${datashare_innerapi_path}/consumer/include", + "${datashare_native_consumer_path}/controller/common", + "${datashare_native_consumer_path}/controller/provider/include", + "${datashare_native_consumer_path}/controller/service/include", + "${datashare_native_consumer_path}/include", + "${datashare_innerapi_path}/common/include", + "${datashare_native_proxy_path}/include", + ] + + sources = [ "${datashare_base_path}/test/unittest/native/consumer/src/datashare_proxy_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_single", + "relational_store:rdb_data_ability_adapter", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + } +} \ No newline at end of file diff --git a/data_share/test/unittest/native/consumer/include/ikvstore_data_service_mock.h b/data_share/test/unittest/native/consumer/include/ikvstore_data_service_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..22eb89f400e821cf7e6dff85fdcd088727cafce2 --- /dev/null +++ b/data_share/test/unittest/native/consumer/include/ikvstore_data_service_mock.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 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 IKVSTORE_DATA_SERVICE_MOCK_H +#define IKVSTORE_DATA_SERVICE_MOCK_H + +#include +#include "gmock/gmock.h" +#include "ikvstore_data_service.h" + +namespace OHOS { +namespace DataShare { +class MockDataShareKvServiceProxy : public DataShareKvServiceProxy { +public: + explicit MockDataShareKvServiceProxy(const sptr &impl) + : DataShareKvServiceProxy(impl) {} + ~MockDataShareKvServiceProxy() = default; + MOCK_METHOD(sptr, GetFeatureInterface, (const std::string &name), (override)); + MOCK_METHOD(uint32_t, RegisterClientDeathObserver, (const std::string &appId, sptr observer), + (override)); +}; +} +} +#endif // IKVSTORE_DATA_SERVICE_MOCK_H \ No newline at end of file diff --git a/data_share/test/unittest/native/consumer/src/datashare_connection_test.cpp b/data_share/test/unittest/native/consumer/src/datashare_connection_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b1e839b2d124346b03be04c922699faf4013aef9 --- /dev/null +++ b/data_share/test/unittest/native/consumer/src/datashare_connection_test.cpp @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2025 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 "datashare_connection.h" + +#include + +#include "accesstoken_kit.h" +#include "data_ability_observer_interface.h" +#include "datashare_errno.h" +#include "datashare_helper.h" +#include "datashare_log.h" +#include "datashare_proxy.h" +#include "extension_manager_proxy.h" +#include "general_controller.h" +#include "general_controller_provider_impl.h" +#include "general_controller_service_impl.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::AAFwk; +class DataShareConnectionTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + bool UrisEqual(std::list uri1, std::list uri2) + { + if (uri1.size() != uri2.size()) { + return false; + } + auto cmp = [](const Uri &first, const Uri &second) { + return first.ToString() < second.ToString(); + }; + uri1.sort(cmp); + uri2.sort(cmp); + auto it1 = uri1.begin(); + auto it2 = uri2.begin(); + for (; it1 != uri1.end() && it2 != uri2.end(); it1++, it2++) { + if (!it1->Equals(*it2)) { + return false; + } + } + return true; + } +}; + +class RemoteObjectTest : public IRemoteObject { +public: + explicit RemoteObjectTest(std::u16string descriptor) : IRemoteObject(descriptor) {} + ~RemoteObjectTest() {} + + int32_t GetObjectRefCount() + { + return 0; + } + int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + return 0; + } + bool AddDeathRecipient(const sptr &recipient) + { + return true; + } + bool RemoveDeathRecipient(const sptr &recipient) + { + return true; + } + int Dump(int fd, const std::vector &args) + { + return 0; + } +}; + +class IDataAbilityObserverTest : public DataAbilityObserverStub { +public: + explicit IDataAbilityObserverTest(std::string uri) {uri_ = uri;} + ~IDataAbilityObserverTest() + {} + + void OnChange() + { + GTEST_LOG_(INFO) << "OnChange enter"; + } + std::string uri_; +}; + +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::string DATA_SHARE_URI1 = "datashare:///com.acts.datasharetest1"; + +void DataShareConnectionTest::SetUpTestCase(void) {} +void DataShareConnectionTest::TearDownTestCase(void) {} +void DataShareConnectionTest::SetUp(void) {} +void DataShareConnectionTest::TearDown(void) {} + +/** +* @tc.name: DataShareConnection_UpdateObserverExtsProviderMap_Test_001 +* @tc.desc: test UpdateObserverExtsProviderMap normal func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_UpdateObserverExtsProviderMap_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareConnection_UpdateObserverExtsProviderMap_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // insert data + EXPECT_TRUE(connection->observerExtsProvider_.Empty()); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI); + ASSERT_NE(dataObserver, nullptr); + connection->UpdateObserverExtsProviderMap(uri, dataObserver, true); + + Uri uri1(DATA_SHARE_URI1); + sptr dataObserver1 = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI1); + ASSERT_NE(dataObserver1, nullptr); + connection->UpdateObserverExtsProviderMap(uri1, dataObserver1, true); + + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 2); + connection = nullptr; + + LOG_INFO("DataShareConnection_UpdateObserverExtsProviderMap_Test_001::End"); +} + +/** +* @tc.name: DataShareConnection_DeleteObserverExtsProviderMap_001 +* @tc.desc: test DeleteObserverExtsProviderMap default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_DeleteObserverExtsProviderMap_001, TestSize.Level0) +{ + LOG_INFO("DataShareConnection_DeleteObserverExtsProviderMap_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // insert data + EXPECT_TRUE(connection->observerExtsProvider_.Empty()); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI); + connection->UpdateObserverExtsProviderMap(uri, dataObserver, true); + + Uri uri1(DATA_SHARE_URI1); + sptr dataObserver1 = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI1); + connection->UpdateObserverExtsProviderMap(uri1, dataObserver1, true); + + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 2); + + // delete data that uri can match observer + connection->DeleteObserverExtsProviderMap(uri1, dataObserver1); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 1); + + // delete data that uri can not match observer + connection->DeleteObserverExtsProviderMap(uri1, dataObserver); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 1); + connection = nullptr; + + LOG_INFO("DataShareConnection_DeleteObserverExtsProviderMap_001::End"); +} + +/** +* @tc.name: DataShareConnection_ReRegisterObserverExtProvider_Test_001 +* @tc.desc: test ReRegisterObserverExtProvider default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_ReRegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareConnection_ReRegisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + connection->dataShareProxy_ = tokenProxy; + + // insert data + EXPECT_TRUE(connection->observerExtsProvider_.Empty()); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI); + connection->UpdateObserverExtsProviderMap(uri, dataObserver, true); + + Uri uri1(DATA_SHARE_URI1); + sptr dataObserver1 = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI1); + connection->UpdateObserverExtsProviderMap(uri1, dataObserver1, true); + + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 2); + + // test ReRegister func + connection->ReRegisterObserverExtProvider(); + // reRegister success, update observer map + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + connection = nullptr; + + LOG_INFO("DataShareConnection_ReRegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareConnection_OnAbilityConnectDone_Test_001 +* @tc.desc: test ReRegisterObserverExtProvider default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_OnAbilityConnectDone_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareConnection_OnAbilityConnectDone_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + connection->dataShareProxy_ = tokenProxy; + + // insert data + EXPECT_TRUE(connection->observerExtsProvider_.Empty()); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI); + connection->UpdateObserverExtsProviderMap(uri, dataObserver, true); + + Uri uri1(DATA_SHARE_URI1); + sptr dataObserver1 = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI1); + connection->UpdateObserverExtsProviderMap(uri1, dataObserver1, true); + + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 2); + + // test ReRegister func + connection->isReconnect_.store(true); + std::string deviceId = "deviceId"; + std::string bundleName = "bundleName"; + std::string abilityName = "abilityName"; + AppExecFwk::ElementName element(deviceId, bundleName, abilityName); + int resultCode = 0; + connection->OnAbilityConnectDone(element, token, resultCode); + + // reRegister success, update observer map + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + connection = nullptr; + + LOG_INFO("DataShareConnection_OnAbilityConnectDone_Test_001::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/unittest/native/consumer/src/datashare_helper_impl_test.cpp b/data_share/test/unittest/native/consumer/src/datashare_helper_impl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9b7a555f15d1dd2c365c97ef38f7f7a4683e6e1c --- /dev/null +++ b/data_share/test/unittest/native/consumer/src/datashare_helper_impl_test.cpp @@ -0,0 +1,293 @@ +/* + * 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 +#include "datashare_helper_impl.h" +#include "datashare_log.h" +#include "gmock/gmock.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; + +class MockGeneralController : public GeneralController { +public: + MOCK_METHOD(int, Insert, (const Uri &uri, const DataShareValuesBucket &value), (override)); + MOCK_METHOD(int, Update, + (const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value), (override)); + MOCK_METHOD(int, Delete, (const Uri &uri, const DataSharePredicates &predicates), (override)); + MOCK_METHOD((std::shared_ptr), Query, + (const Uri &uri, const DataSharePredicates &predicates, (std::vector & columns), + DatashareBusinessError &businessError, DataShareOption &option), (override)); + MOCK_METHOD( + int, RegisterObserver, (const Uri &uri, const sptr &dataObserver), (override)); + MOCK_METHOD(int32_t, UnregisterObserver, (const Uri &uri, const sptr &dataObserver), + (override)); + MOCK_METHOD(void, NotifyChange, (const Uri &uri), (override)); + MOCK_METHOD( + int, RegisterObserverExtProvider, (const Uri &uri, const sptr &dataObserver, + bool isDescendants), (override)); + MOCK_METHOD(int32_t, UnregisterObserverExtProvider, (const Uri &uri, + const sptr &dataObserver), (override)); + MOCK_METHOD(int32_t, NotifyChangeExtProvider, (const ChangeInfo &changeInfo), (override)); + MOCK_METHOD( + (std::pair), InsertEx, (const Uri &uri, const DataShareValuesBucket &value), (override)); + MOCK_METHOD((std::pair), UpdateEx, + (const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value), (override)); + MOCK_METHOD( + (std::pair), DeleteEx, (const Uri &uri, const DataSharePredicates &predicates), (override)); +}; + +class DataShareHelperImplTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static std::shared_ptr GetInstance(std::shared_ptr instance = nullptr); + static std::shared_ptr GetController( + std::shared_ptr instance = nullptr); +}; + +void DataShareHelperImplTest::SetUpTestCase(void) +{ + DataShareHelperImplTest::GetInstance(std::make_shared("datashare://datasharehelperimpl")); + EXPECT_NE(DataShareHelperImplTest::GetInstance(), nullptr); + DataShareHelperImplTest::GetController(std::make_shared()); + EXPECT_NE(DataShareHelperImplTest::GetController(), nullptr); + DataShareHelperImplTest::GetInstance()->generalCtl_ = DataShareHelperImplTest::GetController(); + EXPECT_NE(DataShareHelperImplTest::GetInstance()->generalCtl_, nullptr); + EXPECT_EQ(DataShareHelperImplTest::GetInstance()->extSpCtl_, nullptr); + DataShareHelperImplTest::GetInstance()->persistentDataCtl_ = nullptr; + DataShareHelperImplTest::GetInstance()->publishedDataCtl_ = nullptr; +} +void DataShareHelperImplTest::TearDownTestCase(void) +{ +} +void DataShareHelperImplTest::SetUp(void) +{ +} +void DataShareHelperImplTest::TearDown(void) +{ +} +std::shared_ptr DataShareHelperImplTest::GetInstance(std::shared_ptr instance) +{ + static std::shared_ptr helperInstance = nullptr; + if (instance != nullptr) { + helperInstance = instance; + } + return helperInstance; +} +std::shared_ptr DataShareHelperImplTest::GetController( + std::shared_ptr instance) +{ + static std::shared_ptr controllerInstance = nullptr; + if (instance != nullptr) { + controllerInstance = instance; + } + return controllerInstance; +} + +HWTEST_F(DataShareHelperImplTest, BatchUpdateTest001, TestSize.Level0) +{ + LOG_INFO("BatchUpdateTest001::Start"); + UpdateOperations operations; + std::vector results = {}; + int result = DataShareHelperImplTest::GetInstance()->BatchUpdate(operations, results); + EXPECT_EQ(result, DATA_SHARE_ERROR); + LOG_INFO("BatchUpdateTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, InsertExTest001, TestSize.Level0) +{ + LOG_INFO("InsertExTest001::Start"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataShareValuesBucket value; + DataShareHelperImplTest::GetInstance()->generalCtl_ = nullptr; + std::pair result = DataShareHelperImplTest::GetInstance()->InsertEx(uri, value); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + std::shared_ptr controller = DataShareHelperImplTest::GetController(); + DataShareHelperImplTest::GetInstance()->generalCtl_ = controller; + EXPECT_CALL(*controller, InsertEx(testing::_, testing::_)) + .WillOnce(testing::Return(std::make_pair(E_REGISTERED_REPEATED, 0))); + result = DataShareHelperImplTest::GetInstance()->InsertEx(uri, value); + EXPECT_EQ(result.first, E_REGISTERED_REPEATED); + EXPECT_EQ(result.second, 0); + LOG_INFO("InsertExTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, UpdateExTest001, TestSize.Level0) +{ + LOG_INFO("UpdateExTest001::Start"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataShareValuesBucket value; + DataSharePredicates predicates; + DataShareHelperImplTest::GetInstance()->generalCtl_ = nullptr; + std::pair result = DataShareHelperImplTest::GetInstance()->UpdateEx(uri, predicates, value); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + std::shared_ptr controller = DataShareHelperImplTest::GetController(); + DataShareHelperImplTest::GetInstance()->generalCtl_ = controller; + EXPECT_CALL(*controller, UpdateEx(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(std::make_pair(E_REGISTERED_REPEATED, 0))); + result = DataShareHelperImplTest::GetInstance()->UpdateEx(uri, predicates, value); + EXPECT_EQ(result.first, E_REGISTERED_REPEATED); + EXPECT_EQ(result.second, 0); + LOG_INFO("UpdateExTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, DeleteExTest001, TestSize.Level0) +{ + LOG_INFO("DeleteExTest001::Start"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataSharePredicates predicates; + DataShareHelperImplTest::GetInstance()->generalCtl_ = nullptr; + std::pair result = DataShareHelperImplTest::GetInstance()->DeleteEx(uri, predicates); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + std::shared_ptr controller = DataShareHelperImplTest::GetController(); + DataShareHelperImplTest::GetInstance()->generalCtl_ = controller; + EXPECT_CALL(*controller, DeleteEx(testing::_, testing::_)) + .WillOnce(testing::Return(std::make_pair(E_REGISTERED_REPEATED, 0))); + result = DataShareHelperImplTest::GetInstance()->DeleteEx(uri, predicates); + EXPECT_EQ(result.first, E_REGISTERED_REPEATED); + EXPECT_EQ(result.second, 0); + LOG_INFO("DeleteExTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, DelQueryTemplateTest001, TestSize.Level0) +{ + LOG_INFO("DelQueryTemplateTest001::Start"); + std::string uri("datashare:///com.datasharehelperimpl.test"); + int64_t subscriberId = 0; + int result = DataShareHelperImplTest::GetInstance()->DelQueryTemplate(uri, subscriberId); + EXPECT_EQ(result, DATA_SHARE_ERROR); + LOG_INFO("DelQueryTemplateTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, PublishTest001, TestSize.Level0) +{ + LOG_INFO("PublishTest001::Start"); + Data data; + std::string bundleName("datashare:///com.datasharehelperimpl.test"); + std::vector result = DataShareHelperImplTest::GetInstance()->Publish(data, bundleName); + EXPECT_EQ(result.size(), 0); + LOG_INFO("PublishTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, GetPublishedDataTest001, TestSize.Level0) +{ + LOG_INFO("GetPublishedDataTest001::Start"); + int resultCode = 0; + std::string bundleName("datashare:///com.datasharehelperimpl.test"); + Data result = DataShareHelperImplTest::GetInstance()->GetPublishedData(bundleName, resultCode); + EXPECT_EQ(result.version_, 0); + EXPECT_EQ(result.datas_.size(), 0); + LOG_INFO("GetPublishedDataTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, SubscribeRdbDataTest001, TestSize.Level0) +{ + LOG_INFO("SubscribeRdbDataTest001::Start"); + std::vector uris = {}; + TemplateId templateId; + std::function callback; + std::vector result = + DataShareHelperImplTest::GetInstance()->SubscribeRdbData(uris, templateId, callback); + EXPECT_EQ(result.size(), 0); + LOG_INFO("SubscribeRdbDataTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, UnsubscribeRdbDataTest001, TestSize.Level0) +{ + LOG_INFO("UnsubscribeRdbDataTest001::Start"); + std::vector uris = {}; + TemplateId templateId; + std::vector result = DataShareHelperImplTest::GetInstance()->UnsubscribeRdbData(uris, templateId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("UnsubscribeRdbDataTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, DisableRdbSubsTest001, TestSize.Level0) +{ + LOG_INFO("DisableRdbSubsTest001::Start"); + std::vector uris = {}; + TemplateId templateId; + std::vector result = DataShareHelperImplTest::GetInstance()->DisableRdbSubs(uris, templateId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("DisableRdbSubsTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, SubscribePublishedDataTest001, TestSize.Level0) +{ + LOG_INFO("SubscribePublishedDataTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 0; + std::function callback; + std::vector result = + DataShareHelperImplTest::GetInstance()->SubscribePublishedData(uris, subscriberId, callback); + EXPECT_EQ(result.size(), 0); + LOG_INFO("SubscribePublishedDataTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, UnsubscribePublishedDataTest001, TestSize.Level0) +{ + LOG_INFO("UnsubscribePublishedDataTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 0; + std::vector result = + DataShareHelperImplTest::GetInstance()->UnsubscribePublishedData(uris, subscriberId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("UnsubscribePublishedDataTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, EnablePubSubsTest001, TestSize.Level0) +{ + LOG_INFO("EnablePubSubsTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 0; + std::vector result = DataShareHelperImplTest::GetInstance()->EnablePubSubs(uris, subscriberId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("EnablePubSubsTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, DisablePubSubsTest001, TestSize.Level0) +{ + LOG_INFO("DisableRdbSubsTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 0; + std::vector result = DataShareHelperImplTest::GetInstance()->DisablePubSubs(uris, subscriberId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("DisablePubSubsTest001::End"); +} + +/* +* @tc.desc: test UserDefineFunc with no extSpCtl_ +* @tc.require: Null +*/ +HWTEST_F(DataShareHelperImplTest, User_Define_func_No_ExtSpCtl_Test001, TestSize.Level0) +{ + LOG_INFO("User_Define_func_No_ExtSpCtl_Test001::Start"); + DataShareHelperImplTest::GetInstance()->extSpCtl_ = nullptr; + MessageParcel data; + MessageParcel reply; + MessageOption option; + auto result = DataShareHelperImplTest::GetInstance()->UserDefineFunc(data, reply, option); + EXPECT_EQ(result, DATA_SHARE_ERROR); + LOG_INFO("User_Define_func_No_ExtSpCtl_Test001::End"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/unittest/native/consumer/src/datashare_helper_test.cpp b/data_share/test/unittest/native/consumer/src/datashare_helper_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b01721c0ef45682471fff9bb8290e89e358b1221 --- /dev/null +++ b/data_share/test/unittest/native/consumer/src/datashare_helper_test.cpp @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2025 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 + +#include "datashare_helper.h" +#include "datashare_helper_impl.h" +#include "datashare_log.h" +#include "datashare_uri_utils.h" +#include "iservice_registry.h" +#include "ikvstore_data_service_mock.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; + +constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; +std::string NON_SILENT_ACCESS_URI = "datashare:///com.acts.datasharetest"; +std::string NON_SILENT_ACCESS_ERROR_URI = "datashare:///com.acts.test"; +constexpr int DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID = 1301; + +class DataShareHelperTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +void DataShareManagerImplHelper() +{ + auto helper = DataShareManagerImpl::GetInstance(); + helper->dataShareService_ = nullptr; + auto manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + auto remoteObject = manager->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); + sptr mockProxy = sptr + (new MockDataShareKvServiceProxy(remoteObject)); + EXPECT_CALL(*mockProxy, GetFeatureInterface(testing::_)) + .WillOnce(testing::Return(nullptr)); + helper->dataMgrService_ = (sptr)mockProxy; +} + +/** + * @tc.name: + * @tc.desc: test Creator function when options.isProxy_ = false and options.token_ = nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what options.isProxy_ = false and options.token_ = nullptr + 2.call Creator function and check the result + * @tc.experct: Creator failed and reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreatorTest001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreatorTest001::Start"); + std::string strUri = "testUri"; + CreateOptions options; + options.isProxy_ = false; + options.token_ = nullptr; + std::string bundleName = "testBundle"; + int waitTime = 1; + bool isSystem = true; + auto result = DataShareHelper::Creator(strUri, options, bundleName, waitTime, isSystem); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreatorTest001::End"); +} + +/** + * @tc.name: + * @tc.desc: test Creator function when options.isProxy_ = true and options.token_ = nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what options.isProxy_ = true and options.token_ = nullptr + 2.call Creator function and check the result + * @tc.experct: Creator failed and reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreatorTest002, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreatorTest002::Start"); + std::string strUri = "testUri"; + CreateOptions options; + options.isProxy_ = true; + options.token_ = nullptr; + std::string bundleName = "testBundle"; + int waitTime = 1; + bool isSystem = true; + auto result = DataShareHelper::Creator(strUri, options, bundleName, waitTime, isSystem); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreatorTest002::End"); +} + +/** + * @tc.name: + * @tc.desc: test Creator function when options.isProxy_ = true and options.token_ != nullptr + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what options.isProxy_ = true and options.token_ != nullptr + 2.call Creator function and check the result + * @tc.experct: Creator failed and not reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreatorTest004, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreatorTest004::Start"); + CreateOptions options; + options.isProxy_ = true; + + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + EXPECT_NE(saManager, nullptr); + auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID); + EXPECT_NE(remoteObj, nullptr); + options.token_ = remoteObj; + auto result = DataShareHelper::Creator(NON_SILENT_ACCESS_ERROR_URI, options); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreatorTest004::End"); +} + +/** + * @tc.name: + * @tc.desc: test CreateExtHelper function when Uri contains "appIndex=" + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what Uri contains "appIndex=" + 2.call CreateExtHelper function and check the result + * @tc.experct: CreateExtHelper failed and reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreateExtHelper001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreateExtHelper001::Start"); + OHOS::Uri uri("datashareproxy://com.acts.ohos.data.datasharetest/test?appIndex=abcd"); + uri.query_ = ("appIndex=abcd"); + sptr token = nullptr; + int waitTime = 1000; + bool isSystem = false; + auto result = DataShareHelper::CreateExtHelper(uri, token, waitTime, isSystem); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreateExtHelper001::End"); +} + +/** + * @tc.name: SetSilentSwitch001 + * @tc.desc: test SetSilentSwitch function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object + 2.call SetSilentSwitch function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.experct: SetSilentSwitch failed and reutrn DATA_SHARE_ERROR + */ +HWTEST_F(DataShareHelperTest, SetSilentSwitch001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest SetSilentSwitch001::Start"); + DataShareManagerImplHelper(); + OHOS::Uri uri("datashareproxy://com.acts.ohos.data.datasharetest/test?appIndex=abcd"); + uri.query_ = ("appIndex=abcd"); + bool enable = false; + bool isSystem = false; + auto result = DataShareHelper::SetSilentSwitch(uri, enable, isSystem); + EXPECT_EQ(result, DATA_SHARE_ERROR); + LOG_INFO("DataShareHelperTest SetSilentSwitch001::End"); +} + +/** + * @tc.name: GetSilentProxyStatus001 + * @tc.desc: test GetSilentProxyStatus function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object + 2.call GetSilentProxyStatus function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.experct: GetSilentProxyStatus failed and reutrn E_ERROR + */ +HWTEST_F(DataShareHelperTest, GetSilentProxyStatus001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest GetSilentProxyStatus001::Start"); + DataShareManagerImplHelper(); + std::string uri = "datashareproxy://com.acts.ohos.data.datasharetest/test?appIndex=abcd"; + bool isSystem = false; + auto result = DataShareHelper::GetSilentProxyStatus(uri, isSystem); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareHelperTest GetSilentProxyStatus001::End"); +} + +/** + * @tc.name: CreateServiceHelper001 + * @tc.desc: test CreateExtHelper function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object + 2.call CreateServiceHelper function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.experct: CreateServiceHelper failed and reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreateServiceHelper001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreateServiceHelper001::Start"); + DataShareManagerImplHelper(); + std::string exuri = "testExuri"; + std::string bundleName = "bundleName"; + bool isSystem = false; + auto result = DataShareHelper::CreateServiceHelper(exuri, bundleName, isSystem); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreateServiceHelper001::End"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/unittest/native/consumer/src/datashare_proxy_test.cpp b/data_share/test/unittest/native/consumer/src/datashare_proxy_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5702a7932eb8d3554b9443a430cc68052b4b3d3f --- /dev/null +++ b/data_share/test/unittest/native/consumer/src/datashare_proxy_test.cpp @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2025 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 "datashare_proxy.h" + +#include + +#include "accesstoken_kit.h" +#include "data_ability_observer_interface.h" +#include "datashare_connection.h" +#include "datashare_errno.h" +#include "datashare_helper.h" +#include "datashare_log.h" +#include "extension_manager_proxy.h" +#include "general_controller.h" +#include "general_controller_provider_impl.h" +#include "general_controller_service_impl.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::AAFwk; +class DataShareProxyTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +class RemoteObjectTest : public IRemoteObject { +public: + explicit RemoteObjectTest(std::u16string descriptor) : IRemoteObject(descriptor) {} + ~RemoteObjectTest() {} + + int32_t GetObjectRefCount() + { + return 0; + } + int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + return 0; + } + bool AddDeathRecipient(const sptr &recipient) + { + return true; + } + bool RemoveDeathRecipient(const sptr &recipient) + { + return true; + } + int Dump(int fd, const std::vector &args) + { + return 0; + } +}; + +class IDataAbilityObserverTest : public DataAbilityObserverStub { +public: + IDataAbilityObserverTest() {} + ~IDataAbilityObserverTest() + {} + + void OnChange() + { + GTEST_LOG_(INFO) << "OnChange enter"; + } +}; + +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; + +void DataShareProxyTest::SetUpTestCase(void) {} +void DataShareProxyTest::TearDownTestCase(void) {} +void DataShareProxyTest::SetUp(void) {} +void DataShareProxyTest::TearDown(void) {} + +/** +* @tc.name: DataShareProxy_RegisterObserverExtProvider_Test_001 +* @tc.desc: test RegisterObserverExtProvider default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareProxyTest, DataShareProxy_RegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareProxy_RegisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + + connection->dataShareProxy_ = tokenProxy; + ASSERT_NE(connection->dataShareProxy_, nullptr); + auto proxy = connection->GetDataShareProxy(uri, token); + ASSERT_NE(proxy, nullptr); + + // Observer not null + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + ASSERT_NE(dataObserver, nullptr); + // datashare_stub returns default 0(E_OK) + int ret = proxy->RegisterObserverExtProvider(uri, dataObserver, true, { false }); + EXPECT_EQ(ret, 0); + + LOG_INFO("DataShareProxy_RegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareProxy_UnregisterObserverExtProvider_Test_001 +* @tc.desc: test UnregisterObserverExtProvider default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareProxyTest, DataShareProxy_UnregisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareProxy_UnregisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + connection->dataShareProxy_ = tokenProxy; + auto proxy = connection->GetDataShareProxy(uri, token); + ASSERT_NE(proxy, nullptr); + + // observer not null + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + ASSERT_NE(dataObserver, nullptr); + // datashare_stub returns default 0(E_OK) + int ret = proxy->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(ret, 0); + + LOG_INFO("DataShareProxy_UnregisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareProxy_NotifyChangeExtProvider_Test_001 +* @tc.desc: test NotifyChangeExtProvider default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareProxyTest, DataShareProxy_NotifyChangeExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareProxy_NotifyChangeExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + connection->dataShareProxy_ = tokenProxy; + auto proxy = connection->GetDataShareProxy(uri, token); + ASSERT_NE(proxy, nullptr); + + ChangeInfo changeInfo = { ChangeInfo::ChangeType::INSERT, { uri } }; + // datashare_stub returns default 0(E_OK) + int ret = proxy->NotifyChangeExtProvider(changeInfo); + EXPECT_EQ(ret, 0); + + LOG_INFO("DataShareProxy_NotifyChangeExtProvider_Test_001::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/unittest/native/provider/BUILD.gn b/data_share/test/unittest/native/provider/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..6eeadc3e09593a29fc90d2f3933e02a6f35e5cf7 --- /dev/null +++ b/data_share/test/unittest/native/provider/BUILD.gn @@ -0,0 +1,92 @@ +# Copyright (C) 2025 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/test.gni") +import("//foundation/distributeddatamgr/data_share/datashare.gni") + +group("unittest") { + testonly = true + deps = [] + + deps += [ + ":DataShareStubTest", + ] +} + +config("permission_config") { + visibility = [ ":*" ] + include_dirs = [ + "${datashare_common_native_path}/include", + "${datashare_native_permission_path}/include", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } +} + +ohos_unittest("DataShareStubTest") { + module_out_path = "data_share/data_share/native/provider" + + include_dirs = [ + "${datashare_innerapi_path}/consumer/include", + "${datashare_innerapi_path}/common/include", + "${datashare_native_provider_path}/include", + "${datashare_native_proxy_path}/include", + ] + + sources = [ "${datashare_base_path}/test/unittest/native/provider/src/datashare_stub_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}:datashare_provider", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_single", + "ipc:ipc_napi", + "relational_store:rdb_data_ability_adapter", + "samgr:samgr_proxy", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "${datashare_base_path}/cfi_blocklist.txt" + } + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} \ No newline at end of file diff --git a/data_share/test/unittest/native/provider/src/datashare_stub_test.cpp b/data_share/test/unittest/native/provider/src/datashare_stub_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7cd067af9cc917718b9bd2a32565b17c7562db0b --- /dev/null +++ b/data_share/test/unittest/native/provider/src/datashare_stub_test.cpp @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2025 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 "datashare_stub.h" + +#include + +#include "accesstoken_kit.h" +#include "data_ability_observer_stub.h" +#include "datashare_business_error.h" +#include "datashare_errno.h" +#include "datashare_itypes_utils.h" +#include "datashare_log.h" +#include "datashare_operation_statement.h" +#include "datashare_stub_impl.h" +#include "extension_manager_proxy.h" +#include "idatashare.h" +#include "ipc_skeleton.h" +#include "ipc_types.h" +#include "ishared_result_set.h" + + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace DistributedShare::DataShare; +using namespace OHOS::AAFwk; +using ChangeInfo = AAFwk::ChangeInfo; +class DataShareStubTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + + +class IDataAbilityObserverTest : public DataAbilityObserverStub { +public: + IDataAbilityObserverTest() {} + ~IDataAbilityObserverTest() + {} + + void OnChange() + { + GTEST_LOG_(INFO) << "OnChange enter"; + } +}; + +class TestDataShareStub : public DataShareStub { +public: + TestDataShareStub() {} + ~TestDataShareStub() {} + int OpenFile(const Uri &uri, const std::string &mode) + { + return 0; + } + int OpenRawFile(const Uri &uri, const std::string &mode) + { + return 0; + } + int Insert(const Uri &uri, const DataShareValuesBucket &value) + { + return 0; + } + int Update(const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) + { + return 0; + } + int Delete(const Uri &uri, const DataSharePredicates &predicates) + { + return 0; + } + std::shared_ptr Query(const Uri &uri, const DataSharePredicates &predicates, + std::vector &columns, DatashareBusinessError &businessError) + { + return nullptr; + } + std::string GetType(const Uri &uri) + { + return ""; + } + int BatchInsert(const Uri &uri, const std::vector &values) + { + return 0; + } + bool RegisterObserver(const Uri &uri, const sptr &dataObserver) + { + return true; + } + bool UnregisterObserver(const Uri &uri, const sptr &dataObserver) + { + return true; + } + bool NotifyChange(const Uri &uri) + { + return true; + } + Uri NormalizeUri(const Uri &uri) + { + return uri; + } + Uri DenormalizeUri(const Uri &uri) + { + return uri; + } + std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) + { + return {}; + } +}; + +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::shared_ptr dataShareStub = std::make_shared(); +std::u16string InterfaceToken = u"OHOS.DataShare.IDataShare"; + +void DataShareStubTest::SetUpTestCase(void) {} +void DataShareStubTest::TearDownTestCase(void) {} +void DataShareStubTest::SetUp(void) {} +void DataShareStubTest::TearDown(void) {} + +/** +* @tc.name: DataShareStub_CmdRegisterObserverExtProvider_Test_001 +* @tc.desc: test CmdRegisterObserverExtProvideroteRequest default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareStubTest, DataShareStub_CmdRegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareStub_CmdRegisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + ASSERT_NE(dataObserver, nullptr); + uint32_t code = static_cast(IDataShareInterfaceCode::CMD_REGISTER_OBSERVEREXT_PROVIDER); + + MessageParcel data; + data.WriteInterfaceToken(InterfaceToken); + RegisterOption registerOption; + bool ret = ITypesUtil::Marshal(data, uri, dataObserver->AsObject(), true, registerOption); + EXPECT_TRUE(ret); + + MessageParcel reply; + MessageOption option; + ASSERT_NE(dataShareStub, nullptr); + int errCode = dataShareStub->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(errCode, 0); + ret = ITypesUtil::Unmarshal(reply, errCode); + EXPECT_TRUE(ret); + // return default errCode 0(E_OK) + EXPECT_EQ(errCode, 0); + + LOG_INFO("DataShareStub_CmdRegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareStub_CmdUnregisterObserverExtProvider_Test_001 +* @tc.desc: test CmdUnregisterObserverExtProvideroteRequest default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareStubTest, DataShareStub_CmdUnregisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareStub_CmdUnregisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + ASSERT_NE(dataObserver, nullptr); + uint32_t code = static_cast(IDataShareInterfaceCode::CMD_UNREGISTER_OBSERVEREXT_PROVIDER); + + MessageParcel data; + data.WriteInterfaceToken(InterfaceToken); + bool ret = ITypesUtil::Marshal(data, uri, dataObserver->AsObject()); + EXPECT_TRUE(ret); + + MessageParcel reply; + MessageOption option; + int errCode = dataShareStub->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(errCode, 0); + ret = ITypesUtil::Unmarshal(reply, errCode); + EXPECT_TRUE(ret); + // return default errCode 0(E_OK) + EXPECT_EQ(errCode, 0); + + LOG_INFO("DataShareStub_CmdUnregisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareStub_CmdNotifyChangeExtProvider_Test_001 +* @tc.desc: test CmdNotifyChangeExtProvider default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareStubTest, DataShareStub_CmdNotifyChangeExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareStub_CmdNotifyChangeExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + ChangeInfo changeInfo = { ChangeInfo::ChangeType::INSERT, { uri } }; + uint32_t code = static_cast(IDataShareInterfaceCode::CMD_NOTIFY_CHANGEEXT_PROVIDER); + + MessageParcel data; + data.WriteInterfaceToken(InterfaceToken); + bool ret = ChangeInfo::Marshalling(changeInfo, data); + EXPECT_TRUE(ret); + + MessageParcel reply; + MessageOption option; + int errCode = dataShareStub->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(errCode, 0); + ret = ITypesUtil::Unmarshal(reply, errCode); + EXPECT_TRUE(ret); + // return default errCode 0(E_OK) + EXPECT_EQ(errCode, 0); + + LOG_INFO("DataShareStub_CmdNotifyChangeExtProvider_Test_001::End"); +} +} +} \ No newline at end of file diff --git a/datamgr_service/BUILD.gn b/datamgr_service/BUILD.gn index 71f3ee228b6dc2bbbb2dea9533512794a2d15b60..4bffdf8623639e6e9445daa171e55f581da2ec19 100644 --- a/datamgr_service/BUILD.gn +++ b/datamgr_service/BUILD.gn @@ -19,6 +19,7 @@ group("build_native_test") { "services/distributeddataservice/app/test:unittest", "services/distributeddataservice/framework/test:unittest", "services/distributeddataservice/service/test:unittest", + "services/distributeddataservice/rust/test:unittest", ] } @@ -31,6 +32,7 @@ group("fuzztest") { "services/distributeddataservice/adapter/test:fuzztest", "services/distributeddataservice/app/test/fuzztest:fuzztest", "services/distributeddataservice/service/test/fuzztest:fuzztest", + "services/distributeddataservice/framework/test/fuzztest:fuzztest", ] } ############################################################################### diff --git a/datamgr_service/bundle.json b/datamgr_service/bundle.json index b1a8472dba866d162bf31c03216e699c14086ab1..f726ee71c84c0c228f6dba4f83660ed9992b734b 100644 --- a/datamgr_service/bundle.json +++ b/datamgr_service/bundle.json @@ -81,6 +81,7 @@ "napi", "netmanager_base", "os_account", + "qos_manager", "relational_store", "resource_management", "safwk", @@ -129,6 +130,8 @@ "cloud/schema_meta.h", "cloud/subscription.h", "cloud/sync_event.h", + "crypto/crypto_manager.h", + "device_manager/device_manager_delegate.h", "dfx/dfx_types.h", "dfx/reporter.h", "directory/directory_manager.h", diff --git a/datamgr_service/datamgr_service.gni b/datamgr_service/datamgr_service.gni index da3e7a494d5e4474f2f5e30387cab6d3a8465cfd..7b327ccea5c69ef499da3dbd5991d35f004b2ed9 100644 --- a/datamgr_service/datamgr_service.gni +++ b/datamgr_service/datamgr_service.gni @@ -38,6 +38,8 @@ udmf_path = "//foundation/distributeddatamgr/udmf" dataobject_path = "//foundation/distributeddatamgr/data_object" +datamgr_service_path = "//foundation/distributeddatamgr/datamgr_service" + declare_args() { datamgr_service_power = true if (!defined(global_parts_info.power_manager_native_powermgr_client) || diff --git a/datamgr_service/services/distributeddataservice/adapter/CMakeLists.txt b/datamgr_service/services/distributeddataservice/adapter/CMakeLists.txt index 83d331188b9dd0e889b3236b36b3b593e8e33fa5..a0bbef983e05d8b50e09028d4d348f12ce5e0f47 100644 --- a/datamgr_service/services/distributeddataservice/adapter/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/adapter/CMakeLists.txt @@ -11,7 +11,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=0 -fpermissive -Wattributes") set(MOCK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../mock") set(KV_STORE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../kv_store") add_definitions(-DCONFIG_PUBLIC_VERSION) +add_definitions(-D__CJSON_USE_INT64) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/account/src adapterSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/bundle_mgr adapterSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/broadcaster/src adapterSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/communicator/src adapterSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/dfx/src/behaviour adapterSrc) @@ -20,13 +22,14 @@ 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}/network/src adapterSrc) list(REMOVE_ITEM adapterSrc "${CMAKE_CURRENT_SOURCE_DIR}/network/src/network_delegate_default_impl.cpp") -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/schema_helper/src adapterSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/screenlock/src adapterSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/schema_helper adapterSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/screenlock 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") include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../framework/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/account/src) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/bundle_mgr) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/broadcaster/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/communicator/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/dfx/src/behaviour) @@ -37,13 +40,6 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/network/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/schema_helper/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/screenlock/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/utils/src) -#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) -#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/account) -#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/broadcaster) -#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/communicator) -#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/dfx) -#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/permission) -#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/utils) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../utils_native/base/include) include(${MOCK_DIR}/include/CMakeLists.txt OPTIONAL) include(${KV_STORE_DIR}/interfaces/CMakeLists.txt OPTIONAL) @@ -51,9 +47,12 @@ set(links secure mock distributeddb crypto svcFwk) add_library(adapter SHARED ${adapterSrc}) target_link_libraries(adapter ${links}) +target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/bundle_mgr) +target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/network) +target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/schema_helper) target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/account) -target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/broadcaster) 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) diff --git a/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn index fc643f9961f0813eab2f499778d5a38191f63b7b..85697b11bb8a77ac94f247ab311261b84b487ac6 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn @@ -35,10 +35,7 @@ ohos_source_set("distributeddata_account") { "${data_service_path}/framework/include/account", ] - cflags_cc = [ - "-fvisibility=hidden", - "-fstack-protector-strong", - ] + cflags_cc = [ "-fvisibility=hidden" ] remove_configs = [ "//build/config/compiler:no_exceptions" ] 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 ddcb50026b7bc5fef52c51d1c9bf480feaf72d3a..fdd363d42b4a1c2e940a097a1b3a7343284103b3 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 @@ -20,9 +20,9 @@ namespace OHOS { namespace DistributedData { -namespace { -constexpr const char *DEFAULT_OHOS_ACCOUNT_UID = ""; // default UID -} +static constexpr int32_t FOREGROUND_USER = 100; +static constexpr const char *DEFAULT_OHOS_ACCOUNT_UID = "default"; // default UID + __attribute__((used)) static bool g_isInit = AccountDelegateDefaultImpl::Init(); std::string AccountDelegateDefaultImpl::GetCurrentAccountId() const @@ -31,6 +31,12 @@ std::string AccountDelegateDefaultImpl::GetCurrentAccountId() const return DEFAULT_OHOS_ACCOUNT_UID; } +std::string AccountDelegateDefaultImpl::GetUnencryptedAccountId(int32_t userId) const +{ + (void)userId; + return DEFAULT_OHOS_ACCOUNT_UID; +} + int32_t AccountDelegateDefaultImpl::GetUserByToken(uint32_t tokenId) const { (void)tokenId; @@ -89,6 +95,18 @@ void AccountDelegateDefaultImpl::BindExecutor(std::shared_ptr exec ZLOGD("no account part"); } +bool AccountDelegateDefaultImpl::QueryForegroundUserId(int &foregroundUserId) +{ + foregroundUserId = FOREGROUND_USER; + return true; +} + +bool AccountDelegateDefaultImpl::IsUserForeground(int32_t userId) +{ + (void)userId; + return true; +} + bool AccountDelegateDefaultImpl::Init() { static AccountDelegateDefaultImpl defaultAccountDelegate; 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 6d2b5408e9da85e16ec2ef80b6f71b9913f9ec4b..a8b709adaa0a0ea45a666bd18e9744292f04bcc1 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 @@ -22,6 +22,7 @@ namespace DistributedData { class AccountDelegateDefaultImpl final : public AccountDelegateImpl { public: std::string GetCurrentAccountId() const override; + std::string GetUnencryptedAccountId(int32_t userId = 0) const override; int32_t GetUserByToken(uint32_t tokenId) const override; bool QueryUsers(std::vector &users) override; bool QueryForegroundUsers(std::vector &users) override; @@ -31,6 +32,8 @@ public: void SubscribeAccountEvent() override; void UnsubscribeAccountEvent() override; void BindExecutor(std::shared_ptr executors) override; + bool QueryForegroundUserId(int &foregroundUserId) override; + bool IsUserForeground(int32_t userId) override; static bool Init(); private: diff --git a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_impl.h b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_impl.h index e8fc5d5c3b1129d34fac04a1199621253cffef0a..86874e0e12e1edb667d627c31f4f9ef7b481ace5 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_impl.h @@ -19,7 +19,7 @@ #include #include -#include "account_delegate.h" +#include "account/account_delegate.h" #include "concurrent_map.h" #include "log_print.h" diff --git a/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn index 39c09ee550b4fef1467c7acf6d978b25fc53b72d..e1549dccf1bcb2f911206622e31ffcf4c95b4e6f 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn @@ -40,7 +40,7 @@ ohos_unittest("AccountDelegateTest") { "ability_base:base", "ability_base:want", "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "access_token:libtoken_setproc", "bundle_framework:appexecfwk_base", "c_utils:utils", diff --git a/datamgr_service/services/distributeddataservice/service/crypto/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/BUILD.gn similarity index 71% rename from datamgr_service/services/distributeddataservice/service/crypto/BUILD.gn rename to datamgr_service/services/distributeddataservice/adapter/bundle_mgr/BUILD.gn index 18b166a9655d4b7cd3dcede5d6887c457a6dce9f..7ca4db4f9b288cedeba3f80ced2ab196aa1e3cfb 100644 --- a/datamgr_service/services/distributeddataservice/service/crypto/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2024 Huawei Device Co., Ltd. +# Copyright (c) 2025 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,12 +13,12 @@ import("//build/ohos.gni") import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") -config("crypto_public_config") { +config("module_public_config") { visibility = [ ":*" ] - include_dirs = [ "include" ] + include_dirs = [ "${data_service_path}/adapter" ] } -ohos_source_set("distributeddata_crypto") { +ohos_source_set("distributeddata_bundle_mgr") { branch_protector_ret = "pac_ret" sanitize = { cfi = true @@ -27,17 +27,17 @@ ohos_source_set("distributeddata_crypto") { boundary_sanitize = true ubsan = true } - sources = [ "src/crypto_manager.cpp" ] - + sources = [ "bundle_mgr_adapter.cpp" ] cflags_cc = [ "-fvisibility=hidden", "-Oz", "-fstack-protector-strong", ] - include_dirs = [ "include" ] - + public_configs = [ ":module_public_config" ] cflags = [ + "-fdata-sections", + "-ffunction-sections", "-Werror", "-Wno-multichar", "-Wno-c99-designator", @@ -45,13 +45,12 @@ ohos_source_set("distributeddata_crypto") { "-Oz", "-fstack-protector-strong", ] - configs = [ ":crypto_public_config" ] - public_configs = [ ":crypto_public_config" ] - deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] - external_deps = [ - "dmsfwk:distributed_sdk", + + external_deps = [ "kv_store:datamgr_common" ] + external_deps += [ + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", "hilog:libhilog", - "huks:libhukssdk", ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" diff --git a/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/bundle_mgr_adapter.cpp b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/bundle_mgr_adapter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..555473d9bd0c6af10b4e7d24bbe5cc80a80d2ea3 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/bundle_mgr_adapter.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2025 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 "BundleMgrAdapter" +#include "bundle_mgr/bundle_mgr_adapter.h" +#include "bundle_mgr_client.h" +#include "log_print.h" +using namespace OHOS::AppExecFwk; +namespace OHOS::DistributedData { +BundleFlag Convert(int32_t type) +{ + switch (type) { + case BundleMgrAdapter::BUNDLE_DEFAULT: + return GET_BUNDLE_DEFAULT; + case BundleMgrAdapter::BUNDLE_WITH_ABILITIES: + return GET_BUNDLE_WITH_ABILITIES; + case BundleMgrAdapter::BUNDLE_WITH_REQUESTED_PERMISSION: + return GET_BUNDLE_WITH_REQUESTED_PERMISSION; + case BundleMgrAdapter::BUNDLE_WITH_EXTENSION_INFO: + return GET_BUNDLE_WITH_EXTENSION_INFO; + case BundleMgrAdapter::BUNDLE_WITH_HASH_VALUE: + return GET_BUNDLE_WITH_HASH_VALUE; + case BundleMgrAdapter::BUNDLE_WITH_MENU: + return GET_BUNDLE_WITH_MENU; + case BundleMgrAdapter::BUNDLE_WITH_ROUTER_MAP: + return GET_BUNDLE_WITH_ROUTER_MAP; + case BundleMgrAdapter::BUNDLE_WITH_SKILL: + return GET_BUNDLE_WITH_SKILL; + } + ZLOGW("invalid type:%{public}d", type); + return GET_BUNDLE_DEFAULT; +} + +BundleMgrAdapter::HapModuleInfo Convert(AppExecFwk::HapModuleInfo &&info) +{ + BundleMgrAdapter::HapModuleInfo res; + res.hapPath = std::move(info.hapPath); + return res; +} + +BundleMgrAdapter::BundleInfo Convert(AppExecFwk::BundleInfo &&info) +{ + BundleMgrAdapter::BundleInfo res; + res.moduleDirs = info.moduleDirs; + res.hapModuleInfos.reserve(info.hapModuleInfos.size()); + for (auto &moduleInfo : info.hapModuleInfos) { + res.hapModuleInfos.push_back(Convert(std::move(moduleInfo))); + } + return res; +} + +BundleMgrAdapter &BundleMgrAdapter::GetInstance() +{ + static BundleMgrAdapter instance; + return instance; +} + +std::pair BundleMgrAdapter::GetBundleInfo(const std::string &bundleName, + BundleType type, int32_t user) +{ + AppExecFwk::BundleInfo info; + BundleMgrClient client; + bool res = client.GetBundleInfo(bundleName, Convert(type), info, user == 0 ? Constants::UNSPECIFIED_USERID : user); + if (!res) { + return { res, {} }; + } + BundleInfo bundleInfo = Convert(std::move(info)); + return { res, bundleInfo }; +} + +std::string BundleMgrAdapter::GetBundleName(int32_t uid) +{ + BundleMgrClient client; + std::string bundleName; + auto code = client.GetNameForUid(uid, bundleName); + if (code != 0) { + ZLOGE("failed. uid:%{public}d, code:%{public}d", uid, code); + return ""; + } + return bundleName; +} + +std::string BundleMgrAdapter::GetAppId(int32_t user, const std::string &bundleName) +{ + if (bundleName.empty()) { + ZLOGE("invalid args. user:%{public}d, bundleName:%{public}s", user, bundleName.c_str()); + return ""; + } + AppExecFwk::BundleInfo info; + BundleMgrClient client; + auto code = client.GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_DEFAULT, info, + user == 0 ? Constants::UNSPECIFIED_USERID : user); + if (code != 0) { + ZLOGE("failed. user:%{public}d, bundleName:%{public}s", user, bundleName.c_str()); + } + return info.appId; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/bundle_mgr_adapter.h b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/bundle_mgr_adapter.h new file mode 100644 index 0000000000000000000000000000000000000000..fa0d4b9554ed059b95d3b924a3e988a8bc75c0cf --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/bundle_mgr_adapter.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 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_DATAMGR_BUNDLE_MANAGER_ADAPTER_H +#define DISTRIBUTEDDATAMGR_DATAMGR_BUNDLE_MANAGER_ADAPTER_H + +#include +#include +#include "visibility.h" + +namespace OHOS { +namespace DistributedData { +class API_EXPORT BundleMgrAdapter { +public: + struct HapModuleInfo { + std::string hapPath; + }; + struct BundleInfo { + std::vector hapModuleInfos; + std::vector moduleDirs; + }; + enum BundleType { + // get bundle info except abilityInfos + BUNDLE_DEFAULT = 0x00000000, + // get bundle info include abilityInfos + BUNDLE_WITH_ABILITIES = 0x00000001, + // get bundle info include request permissions + BUNDLE_WITH_REQUESTED_PERMISSION = 0x00000010, + // get bundle info include extension info + BUNDLE_WITH_EXTENSION_INFO = 0x00000020, + // get bundle info include hash value + BUNDLE_WITH_HASH_VALUE = 0x00000030, + // get bundle info include menu, only for dump usage + BUNDLE_WITH_MENU = 0x00000040, + // get bundle info include router map, only for dump usage + BUNDLE_WITH_ROUTER_MAP = 0x00000080, + // get bundle info include skill info + BUNDLE_WITH_SKILL = 0x00000800, + }; + static BundleMgrAdapter &GetInstance(); + std::pair GetBundleInfo(const std::string &bundleName, BundleType type, int32_t user = 0); + std::string GetBundleName(int32_t uid); + std::string GetAppId(int32_t user, const std::string &bundleName); +}; +} // namespace DistributedData +} // namespace OHOS +#endif //DISTRIBUTEDDATAMGR_DATAMGR_BUNDLE_MANAGER_ADAPTER_H diff --git a/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..193ada6a489bf4e54c0691a5d990d522fe664973 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/BUILD.gn @@ -0,0 +1,42 @@ +# Copyright (c) 2025 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/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") +module_output_path = "datamgr_service/datamgr_service/distributeddatafwk" + +############################################################################### +ohos_unittest("BundleMgrTest") { + module_out_path = module_output_path + + sources = [ "bundle_mgr_test.cpp" ] + + cflags = [ "-Werror" ] + deps = [ "${data_service_path}/adapter/bundle_mgr:distributeddata_bundle_mgr" ] + + external_deps = [ + "googletest:gtest_main", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + ] +} + +############################################################################### +group("unittest") { + testonly = true + + deps = [] + + deps += [ ":BundleMgrTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/bundle_mgr_client.h b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/bundle_mgr_client.h new file mode 100644 index 0000000000000000000000000000000000000000..3759fdfe5353dfe850221e21ad229c705d3d12af --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/bundle_mgr_client.h @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2025 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_DATAMGR_BUNDLE_MANAGER_ADAPTER_MOCK_H +#define DISTRIBUTEDDATAMGR_DATAMGR_BUNDLE_MANAGER_ADAPTER_MOCK_H + +#include "parcel.h" + +namespace OHOS { +namespace AppExecFwk { +enum BundleFlag { + // get bundle info except abilityInfos + GET_BUNDLE_DEFAULT = 0x00000000, + // get bundle info include abilityInfos + GET_BUNDLE_WITH_ABILITIES = 0x00000001, + // get bundle info include request permissions + GET_BUNDLE_WITH_REQUESTED_PERMISSION = 0x00000010, + // get bundle info include extension info + GET_BUNDLE_WITH_EXTENSION_INFO = 0x00000020, + // get bundle info include hash value + GET_BUNDLE_WITH_HASH_VALUE = 0x00000030, + // get bundle info inlcude menu, only for dump usage + GET_BUNDLE_WITH_MENU = 0x00000040, + // get bundle info inlcude router map, only for dump usage + GET_BUNDLE_WITH_ROUTER_MAP = 0x00000080, + // get bundle info include skill info + GET_BUNDLE_WITH_SKILL = 0x00000800, +}; +enum class GetBundleInfoFlag { + GET_BUNDLE_INFO_DEFAULT = 0x00000000, + GET_BUNDLE_INFO_WITH_APPLICATION = 0x00000001, + GET_BUNDLE_INFO_WITH_HAP_MODULE = 0x00000002, + GET_BUNDLE_INFO_WITH_ABILITY = 0x00000004, + GET_BUNDLE_INFO_WITH_EXTENSION_ABILITY = 0x00000008, + GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION = 0x00000010, + GET_BUNDLE_INFO_WITH_METADATA = 0x00000020, + GET_BUNDLE_INFO_WITH_DISABLE = 0x00000040, + GET_BUNDLE_INFO_WITH_SIGNATURE_INFO = 0x00000080, + GET_BUNDLE_INFO_WITH_MENU = 0x00000100, + GET_BUNDLE_INFO_WITH_ROUTER_MAP = 0x00000200, + GET_BUNDLE_INFO_WITH_SKILL = 0x00000800, + GET_BUNDLE_INFO_ONLY_WITH_LAUNCHER_ABILITY = 0x00001000, + GET_BUNDLE_INFO_OF_ANY_USER = 0x00002000, + GET_BUNDLE_INFO_EXCLUDE_CLONE = 0x00004000, +}; + +struct RequestPermissionUsedScene : public Parcelable { + std::string when; + std::vector abilities; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static RequestPermissionUsedScene *Unmarshalling(Parcel &parcel); +}; + +struct RequestPermission : public Parcelable { + uint32_t reasonId = 0; + std::string name; + std::string moduleName; + std::string reason; + RequestPermissionUsedScene usedScene; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static RequestPermission *Unmarshalling(Parcel &parcel); +}; + +struct SignatureInfo : public Parcelable { + std::string appId; + std::string fingerprint; + std::string appIdentifier; + std::string certificate; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static SignatureInfo *Unmarshalling(Parcel &parcel); +}; + +struct SimpleAppInfo : public Parcelable { + int32_t uid = -1; + std::string bundleName; + int32_t appIndex = -1; + int32_t ret = 0; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static SimpleAppInfo *Unmarshalling(Parcel &parcel); + std::string ToString() const; +}; + +// configuration information about a bundle +struct BundleInfo : public Parcelable { + bool isNewVersion = false; + bool isKeepAlive = false; + bool singleton = false; + bool isPreInstallApp = false; + + bool isNativeApp = false; + + bool entryInstallationFree = false; // application : false; atomic service : true + bool isDifferentName = false; + + uint32_t versionCode = 0; + uint32_t minCompatibleVersionCode = 0; + + uint32_t compatibleVersion = 0; + uint32_t targetVersion = 0; + int32_t appIndex = 0; // index for sandbox app + int32_t minSdkVersion = -1; + int32_t maxSdkVersion = -1; + // int32_t overlayType = NON_OVERLAY_TYPE; + + // user related fields, assign when calling the get interface + int uid = -1; + int gid = -1; + int64_t installTime = 0; + int64_t updateTime = 0; + int64_t firstInstallTime = 0; + std::string name; + std::string versionName; + + std::string vendor; + std::string releaseType; + std::string mainEntry; // modulePackage + std::string entryModuleName; // moduleName + std::string appId; + + std::string cpuAbi; + std::string seInfo; + std::string label; + std::string description; + std::string jointUserId; + SignatureInfo signatureInfo; + std::vector oldAppIds; // used for appId changed + + std::vector hapModuleNames; // the "module.package" in each config.json + std::vector moduleNames; // the "module.name" in each config.json + std::vector modulePublicDirs; // the public paths of all modules of the application. + std::vector moduleDirs; // the paths of all modules of the application. + std::vector moduleResPaths; // the paths of all resources paths. + + std::vector reqPermissions; + std::vector defPermissions; + std::vector reqPermissionStates; + std::vector reqPermissionDetails; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static BundleInfo *Unmarshalling(Parcel &parcel); +}; +class BundleMgrClient { +public: + static constexpr const char *BUNDLE_NAME = "com.ohos.BundleMock"; + static inline int uid_ = -1; + int userID_ = -1; + std::string name_; + BundleFlag flag_ = GET_BUNDLE_DEFAULT; + BundleMgrClient(); + virtual ~BundleMgrClient(); + + int32_t GetNameForUid(const int uid, std::string &name) + { + uid_ = uid; + name = BUNDLE_NAME; + return true; + } + bool GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo, + int32_t userId = -1) + { + name_ = bundleName; + flag_ = flag; + userID_ = userId; + return true; + } +}; +} // namespace AppExecFwk +} // namespace OHOS + +#endif // DISTRIBUTEDDATAMGR_DATAMGR_BUNDLE_MANAGER_ADAPTER_MOCK_H diff --git a/relational_store/interfaces/inner_api/gdb/include/result.h b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/bundle_mgr_test.cpp similarity index 41% rename from relational_store/interfaces/inner_api/gdb/include/result.h rename to datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/bundle_mgr_test.cpp index b4b17ed8baf1f588e42321087070a73913b0a28d..bf5590727434022a7006a8a80de655e9be5ab1e2 100644 --- a/relational_store/interfaces/inner_api/gdb/include/result.h +++ b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/bundle_mgr_test.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2024 Huawei Device Co., Ltd. +* Copyright (c) 2025 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,28 +13,33 @@ * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_RESULT_H -#define OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_RESULT_H +#include -#include -#include -#include -#include -#include -#include +#include "bundle_mgr/bundle_mgr_adapter.h" +#include "ipc_skeleton.h" +namespace { +using namespace OHOS; +using namespace OHOS::DistributedData; +using namespace testing::ext; -#include "edge.h" -#include "path.h" -#include "vertex.h" -#include "rdb_visibility.h" - -namespace OHOS::DistributedDataAip { -using GraphValue = std::variant, - std::shared_ptr, std::shared_ptr, std::shared_ptr, std::nullptr_t>; - -class Result { +class BundleMgrTest : public testing::Test { public: - API_EXPORT virtual std::vector> GetAllData() const = 0; + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} + void SetUp() {} + void TearDown() {} }; -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_RESULT_H \ No newline at end of file + +/** +* @tc.name: GetBundleName +* @tc.desc: GetBundleName test +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(BundleMgrTest, GetBundleName, TestSize.Level0) +{ + auto bundleName = BundleMgrAdapter::GetInstance().GetBundleName(0); + EXPECT_TRUE(bundleName.empty()); +} +} // namespace \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn index 522a20c219c7fef45b01f0636fdeee52314ace4b..44098bb6e316d0a46d79137b9787a70ba55803fb 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn @@ -12,6 +12,11 @@ # limitations under the License. import("//build/ohos.gni") import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +config("module_public_config") { + visibility = [ ":*" ] + include_dirs = [ "${data_service_path}/adapter/include/communicator" ] +} ohos_source_set("distributeddata_communicator") { branch_protector_ret = "pac_ret" sanitize = { @@ -42,25 +47,19 @@ ohos_source_set("distributeddata_communicator") { ] include_dirs = [ - "../include/communicator", - "../include/utils", - "${data_service_path}/adapter/include/communicator", - "${data_service_path}/framework/include/dfx", - "${data_service_path}/framework/include/utils", + "${data_service_path}/adapter/include/utils", ] - cflags_cc = [ - "-fvisibility=hidden", - "-fstack-protector-strong", - ] + cflags_cc = [ "-fvisibility=hidden" ] + public_configs = [ ":module_public_config" ] deps = [ "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", - "../dfx:distributeddata_dfx", ] external_deps = [ + "access_token:libaccesstoken_sdk", "c_utils:utils", "device_manager:devicemanagersdk", "dsoftbus:softbus_client", diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_handler.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_handler.cpp index 40d6f8bbb0af21f0b259d838b15c84f6faf10c41..3677ffdd8c8c55860d78cf3c9cd3511e36cced0b 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_handler.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_handler.cpp @@ -15,11 +15,7 @@ #include "app_pipe_handler.h" #include -#include -#include -#include #include "log_print.h" -#include "dfx/reporter.h" #ifdef LOG_TAG #undef LOG_TAG @@ -46,44 +42,68 @@ AppPipeHandler::AppPipeHandler(const PipeInfo &pipeInfo) std::pair AppPipeHandler::SendData(const PipeInfo &pipeInfo, const DeviceId &deviceId, const DataInfo &dataInfo, uint32_t totalLength, const MessageInfo &info) { + if (softbusAdapter_ == nullptr) { + return std::make_pair(Status::ERROR, 0); + } return softbusAdapter_->SendData(pipeInfo, deviceId, dataInfo, totalLength, info); } Status AppPipeHandler::StartWatchDataChange(const AppDataChangeListener *observer, const PipeInfo &pipeInfo) { + if (softbusAdapter_ == nullptr) { + return Status::ERROR; + } return softbusAdapter_->StartWatchDataChange(observer, pipeInfo); } Status AppPipeHandler::StopWatchDataChange(__attribute__((unused))const AppDataChangeListener *observer, - const PipeInfo &pipeInfo) + const PipeInfo &pipeInfo) { + if (softbusAdapter_ == nullptr) { + return Status::ERROR; + } return softbusAdapter_->StopWatchDataChange(observer, pipeInfo); } bool AppPipeHandler::IsSameStartedOnPeer(const struct PipeInfo &pipeInfo, - __attribute__((unused))const struct DeviceId &peer) + __attribute__((unused))const struct DeviceId &peer) { + if (softbusAdapter_ == nullptr) { + return false; + } return softbusAdapter_->IsSameStartedOnPeer(pipeInfo, peer); } void AppPipeHandler::SetMessageTransFlag(const PipeInfo &pipeInfo, bool flag) { + if (softbusAdapter_ == nullptr) { + return; + } return softbusAdapter_->SetMessageTransFlag(pipeInfo, flag); } int AppPipeHandler::CreateSessionServer(const std::string &sessionName) const { + if (softbusAdapter_ == nullptr) { + return -1; + } return softbusAdapter_->CreateSessionServerAdapter(sessionName); } int AppPipeHandler::RemoveSessionServer(const std::string &sessionName) const { + if (softbusAdapter_ == nullptr) { + return -1; + } return softbusAdapter_->RemoveSessionServerAdapter(sessionName); } -Status AppPipeHandler::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId) +Status AppPipeHandler::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, const ExtraDataInfo &extraInfo) { - return softbusAdapter_->ReuseConnect(pipeInfo, deviceId); + if (softbusAdapter_ == nullptr) { + return Status::ERROR; + } + return softbusAdapter_->ReuseConnect(pipeInfo, deviceId, extraInfo); } } // namespace AppDistributedKv } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_handler.h b/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_handler.h index 6a9dc009a00ff3a043ea61d9004fbc088af12d9c..3cd90cb6191899d6f026f3282f57a19099658983 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_handler.h +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_handler.h @@ -16,20 +16,9 @@ #ifndef DISTRIBUTEDDATAFWK_SRC_PIPE_HANDLER_H #define DISTRIBUTEDDATAFWK_SRC_PIPE_HANDLER_H -#include -#include -#include -#include -#include "dfx/reporter.h" -#include "log_print.h" #include "app_data_change_listener.h" #include "softbus_adapter.h" -#ifdef LOG_TAG - #undef LOG_TAG -#endif -#define LOG_TAG "AppPipeHandler" - namespace OHOS { namespace AppDistributedKv { class AppPipeHandler { @@ -52,12 +41,11 @@ public: int RemoveSessionServer(const std::string &sessionName) const; - Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId); + Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, const ExtraDataInfo &extraInfo); private: PipeInfo pipeInfo_; - std::shared_ptr softbusAdapter_ {}; + std::shared_ptr softbusAdapter_; }; } // namespace AppDistributedKv } // namespace OHOS -#undef LOG_TAG -#endif /* DISTRIBUTEDDATAFWK_SRC_PIPE_HANDLER_H */ +#endif // DISTRIBUTEDDATAFWK_SRC_PIPE_HANDLER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_mgr.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_mgr.cpp index fb62e8a48446bf7280bf071bf409653476826585..c444ade1d11ad3a6047b2854ae32bf218b26ea79 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_mgr.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_mgr.cpp @@ -13,16 +13,19 @@ * limitations under the License. */ -#include "app_pipe_mgr.h" -#include "kvstore_utils.h" -#include "dfx/reporter.h" - +#ifdef LOG_TAG #undef LOG_TAG +#endif #define LOG_TAG "AppPipeMgr" +#include "app_pipe_mgr.h" + +#include "utils/anonymous.h" + namespace OHOS { namespace AppDistributedKv { using namespace OHOS::DistributedKv; +using namespace OHOS::DistributedData; Status AppPipeMgr::StartWatchDataChange(const AppDataChangeListener *observer, const PipeInfo &pipeInfo) { ZLOGI("begin"); @@ -32,7 +35,7 @@ Status AppPipeMgr::StartWatchDataChange(const AppDataChangeListener *observer, c } std::lock_guard lock(dataBusMapMutex_); auto it = dataBusMap_.find(pipeInfo.pipeId); - if (it == dataBusMap_.end()) { + if (it == dataBusMap_.end() || it->second == nullptr) { ZLOGE("pipeid not found"); return Status::ERROR; } @@ -50,7 +53,7 @@ Status AppPipeMgr::StopWatchDataChange(const AppDataChangeListener *observer, co } std::lock_guard lock(dataBusMapMutex_); auto it = dataBusMap_.find(pipeInfo.pipeId); - if (it == dataBusMap_.end()) { + if (it == dataBusMap_.end() || it->second == nullptr) { ZLOGE("pipeid not found"); return Status::ERROR; } @@ -62,18 +65,26 @@ Status AppPipeMgr::StopWatchDataChange(const AppDataChangeListener *observer, co std::pair AppPipeMgr::SendData(const PipeInfo &pipeInfo, const DeviceId &deviceId, const DataInfo &dataInfo, uint32_t totalLength, const MessageInfo &info) { - if (dataInfo.length > DataBuffer::MAX_TRANSFER_SIZE || dataInfo.length == 0 || dataInfo.data == nullptr || - pipeInfo.pipeId.empty() || deviceId.deviceId.empty()) { - ZLOGW("Input is invalid, maxSize:%u, current size:%u", DataBuffer::MAX_TRANSFER_SIZE, dataInfo.length); + if (pipeInfo.pipeId.empty() || deviceId.deviceId.empty() || dataInfo.length > DataBuffer::MAX_TRANSFER_SIZE || + dataInfo.length == 0 || dataInfo.data == nullptr) { + ZLOGE("Input is invalid, maxSize:%{public}u, current size:%{public}u", DataBuffer::MAX_TRANSFER_SIZE, + dataInfo.length); + return std::make_pair(Status::ERROR, 0); + } + if (dataInfo.extraInfo.userId.empty() || dataInfo.extraInfo.appId.empty() || dataInfo.extraInfo.storeId.empty()) { + ZLOGE("access info is empty, userId:%{public}s, appId:%{public}s, storeId:%{public}s", + dataInfo.extraInfo.userId.c_str(), dataInfo.extraInfo.appId.c_str(), + Anonymous::Change(dataInfo.extraInfo.storeId).c_str()); return std::make_pair(Status::ERROR, 0); } - ZLOGD("pipeInfo:%s ,size:%u, total length:%u", pipeInfo.pipeId.c_str(), dataInfo.length, totalLength); + ZLOGD("pipeInfo:%{public}s ,size:%{public}u, total length:%{public}u", pipeInfo.pipeId.c_str(), + dataInfo.length, totalLength); std::shared_ptr appPipeHandler; { std::lock_guard lock(dataBusMapMutex_); auto it = dataBusMap_.find(pipeInfo.pipeId); - if (it == dataBusMap_.end()) { - ZLOGW("pipeInfo:%s not found", pipeInfo.pipeId.c_str()); + if (it == dataBusMap_.end() || it->second == nullptr) { + ZLOGE("pipeInfo:%{public}s not found", pipeInfo.pipeId.c_str()); return std::make_pair(Status::KEY_NOT_FOUND, 0); } appPipeHandler = it->second; @@ -90,7 +101,7 @@ Status AppPipeMgr::Start(const PipeInfo &pipeInfo) } std::lock_guard lock(dataBusMapMutex_); auto it = dataBusMap_.find(pipeInfo.pipeId); - if (it != dataBusMap_.end()) { + if (it != dataBusMap_.end() && it->second != nullptr) { ZLOGW("repeated start, pipeInfo:%{public}s.", pipeInfo.pipeId.c_str()); return Status::SUCCESS; } @@ -101,8 +112,7 @@ Status AppPipeMgr::Start(const PipeInfo &pipeInfo) ZLOGW("Start pipeInfo:%{public}s, failed ret:%{public}d.", pipeInfo.pipeId.c_str(), ret); return Status::ILLEGAL_STATE; } - - dataBusMap_.insert(std::pair>(pipeInfo.pipeId, handler)); + dataBusMap_.insert_or_assign(pipeInfo.pipeId, handler); return Status::SUCCESS; } @@ -111,7 +121,7 @@ Status AppPipeMgr::Stop(const PipeInfo &pipeInfo) { std::lock_guard lock(dataBusMapMutex_); auto it = dataBusMap_.find(pipeInfo.pipeId); - if (it == dataBusMap_.end()) { + if (it == dataBusMap_.end() || it->second == nullptr) { ZLOGW("pipeInfo:%s not found", pipeInfo.pipeId.c_str()); return Status::KEY_NOT_FOUND; } @@ -137,7 +147,7 @@ bool AppPipeMgr::IsSameStartedOnPeer(const struct PipeInfo &pipeInfo, const stru { std::lock_guard lock(dataBusMapMutex_); auto it = dataBusMap_.find(pipeInfo.pipeId); - if (it == dataBusMap_.end()) { + if (it == dataBusMap_.end() || it->second == nullptr) { ZLOGE("pipeInfo:%s not found. Return false.", pipeInfo.pipeId.c_str()); return false; } @@ -155,7 +165,7 @@ void AppPipeMgr::SetMessageTransFlag(const PipeInfo &pipeInfo, bool flag) { std::lock_guard lock(dataBusMapMutex_); auto it = dataBusMap_.find(pipeInfo.pipeId); - if (it == dataBusMap_.end()) { + if (it == dataBusMap_.end() || it->second == nullptr) { ZLOGW("pipeInfo:%s not found", pipeInfo.pipeId.c_str()); return; } @@ -164,25 +174,32 @@ void AppPipeMgr::SetMessageTransFlag(const PipeInfo &pipeInfo, bool flag) appPipeHandler->SetMessageTransFlag(pipeInfo, flag); } -Status AppPipeMgr::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId) +Status AppPipeMgr::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, const ExtraDataInfo &extraInfo) { if (pipeInfo.pipeId.empty() || deviceId.deviceId.empty()) { - ZLOGW("Input is invalid, pipeId:%{public}s, deviceId:%{public}s", pipeInfo.pipeId.c_str(), - KvStoreUtils::ToBeAnonymous(deviceId.deviceId).c_str()); + ZLOGE("Input is invalid, pipeId:%{public}s, deviceId:%{public}s", pipeInfo.pipeId.c_str(), + Anonymous::Change(deviceId.deviceId).c_str()); return Status::INVALID_ARGUMENT; } - ZLOGD("pipeInfo:%s", pipeInfo.pipeId.c_str()); + if (extraInfo.userId.empty() || extraInfo.bundleName.empty() || extraInfo.storeId.empty() || + extraInfo.tokenId == 0) { + ZLOGE("access info is empty, userId:%{public}s, bundleName:%{public}s, storeId:%{public}s, tokenId:%{public}d", + extraInfo.userId.c_str(), extraInfo.bundleName.c_str(), Anonymous::Change(extraInfo.storeId).c_str(), + extraInfo.tokenId); + return Status::ERROR; + } + ZLOGD("pipeInfo:%{public}s", pipeInfo.pipeId.c_str()); std::shared_ptr appPipeHandler; { std::lock_guard lock(dataBusMapMutex_); auto it = dataBusMap_.find(pipeInfo.pipeId); - if (it == dataBusMap_.end()) { - ZLOGW("pipeInfo:%s not found", pipeInfo.pipeId.c_str()); - return Status::INVALID_ARGUMENT; + if (it == dataBusMap_.end() || it->second == nullptr) { + ZLOGE("pipeInfo:%{public}s not found", pipeInfo.pipeId.c_str()); + return Status::KEY_NOT_FOUND; } appPipeHandler = it->second; } - return appPipeHandler->ReuseConnect(pipeInfo, deviceId); + return appPipeHandler->ReuseConnect(pipeInfo, deviceId, extraInfo); } } // namespace AppDistributedKv -} // namespace OHOS +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_mgr.h b/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_mgr.h index d7c35057cf6f81450200a5b8267b388ef98cf9bf..ac70d6b991b38b825a8d71df90e492b09d44cd9a 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_mgr.h +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_mgr.h @@ -47,7 +47,7 @@ public: void SetMessageTransFlag(const PipeInfo &pipeInfo, bool flag); - Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId); + Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, const ExtraDataInfo &extraInfo); private: std::mutex dataBusMapMutex_ {}; std::map> dataBusMap_ {}; diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/communication_provider_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/communication_provider_impl.cpp index 25cb6c74241547f7089d01f0e8e7f2105f29d52e..25ae31cbbefe6e5fe1ecc3f70894ae7a22d63cdd 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/communication_provider_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/communication_provider_impl.cpp @@ -85,9 +85,10 @@ int32_t CommunicationProviderImpl::ListenBroadcastMsg(const PipeInfo &pipeInfo, return SoftBusAdapter::GetInstance()->ListenBroadcastMsg(pipeInfo, std::move(listener)); } -Status CommunicationProviderImpl::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId) +Status CommunicationProviderImpl::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, + const ExtraDataInfo &extraInfo) { - return appPipeMgr_.ReuseConnect(pipeInfo, deviceId); + return appPipeMgr_.ReuseConnect(pipeInfo, deviceId, extraInfo); } } // namespace AppDistributedKv } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/communication_provider_impl.h b/datamgr_service/services/distributeddataservice/adapter/communicator/src/communication_provider_impl.h index 1fb5a62016d87aeade237bac915e9a6afa1ad1bc..cdc672975995273e9ae4a14ad8377a5d2c416f2a 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/communication_provider_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/communication_provider_impl.h @@ -52,7 +52,7 @@ public: int32_t ListenBroadcastMsg(const PipeInfo &pipeInfo, std::function listener) override; - Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId) override; + Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, const ExtraDataInfo &extraInfo) override; protected: virtual Status Initialize(); diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/communicator_context.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/communicator_context.cpp index 76f63db9f18f27dedcacf9e5f37ec6601c610d08..b5415a6b7614e4ba8b48af5eb1d51b5f0b0c607c 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/communicator_context.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/communicator_context.cpp @@ -14,13 +14,14 @@ */ #define LOG_TAG "CommunicatorContext" + #include "communicator_context.h" + #include "log_print.h" -#include "kvstore_utils.h" #include "softbus_error_code.h" +#include "utils/anonymous.h" namespace OHOS::DistributedData { -using KvUtils = OHOS::DistributedKv::KvStoreUtils; using Status = OHOS::DistributedKv::Status; CommunicatorContext &CommunicatorContext::GetInstance() @@ -92,7 +93,7 @@ void CommunicatorContext::NotifySessionReady(const std::string &deviceId, int32_ } } ZLOGI("Notify session begin, deviceId:%{public}s, observer count:%{public}zu", - KvUtils::ToBeAnonymous(deviceId).c_str(), observers_.size()); + Anonymous::Change(deviceId).c_str(), observers_.size()); } if (errCode == SOFTBUS_OK) { std::lock_guard sessionLockGard(sessionMutex_); 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 b9b0078f6d5f718b9d66135bb3c7ea8d28d5c678..ea4915cf92b30b23b56078c8ecced2ade3fd2c5a 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 @@ -14,20 +14,20 @@ */ #define LOG_TAG "DeviceManagerAdapter" -#include "device_manager_adapter.h" -#include +#include "device_manager_adapter.h" -#include "kvstore_utils.h" #include "log_print.h" #include "serializable/serializable.h" +#include "utils/anonymous.h" namespace OHOS::DistributedData { using namespace OHOS::DistributedHardware; using namespace OHOS::AppDistributedKv; -using KvStoreUtils = OHOS::DistributedKv::KvStoreUtils; constexpr int32_t DM_OK = 0; constexpr const char *PKG_NAME = "ohos.distributeddata.service"; +__attribute__((used)) static bool g_delegateInit = + DeviceManagerDelegate::RegisterInstance(&DeviceManagerAdapter::GetInstance()); class DataMgrDmStateCall final : public DistributedHardware::DeviceStateCallback { public: explicit DataMgrDmStateCall(DeviceManagerAdapter &dmAdapter) : dmAdapter_(dmAdapter) {} @@ -173,7 +173,7 @@ void DeviceManagerAdapter::Online(const DmDeviceInfo &info) return; } ZLOGI("[online] uuid:%{public}s, name:%{public}s, type:%{public}d, authForm:%{public}d, osType:%{public}d", - KvStoreUtils::ToBeAnonymous(dvInfo.uuid).c_str(), dvInfo.deviceName.c_str(), dvInfo.deviceType, + Anonymous::Change(dvInfo.uuid).c_str(), Anonymous::Change(dvInfo.deviceName).c_str(), dvInfo.deviceType, static_cast(dvInfo.authForm), dvInfo.osType); SaveDeviceInfo(dvInfo, DeviceChangeType::DEVICE_ONLINE); syncTask_.Insert(dvInfo.uuid, dvInfo.uuid); @@ -217,7 +217,7 @@ void DeviceManagerAdapter::NotifyReadyEvent(const std::string &uuid) if (uuid == CLOUD_DEVICE_UUID) { return; } - ZLOGI("[NotifyReadyEvent] uuid:%{public}s", KvStoreUtils::ToBeAnonymous(uuid).c_str()); + ZLOGI("[NotifyReadyEvent] uuid:%{public}s", Anonymous::Change(uuid).c_str()); std::string event = R"({"extra": {"deviceId":")" + uuid + R"(" } })"; DeviceManager::GetInstance().NotifyEvent(PKG_NAME, DmNotifyEvent::DM_NOTIFY_EVENT_ONDEVICEREADY, event); } @@ -242,7 +242,7 @@ void DeviceManagerAdapter::Offline(const DmDeviceInfo &info) } syncTask_.Erase(dvInfo.uuid); ZLOGI("[offline] uuid:%{public}s, name:%{public}s, type:%{public}d, authForm:%{public}d, osType:%{public}d", - KvStoreUtils::ToBeAnonymous(dvInfo.uuid).c_str(), dvInfo.deviceName.c_str(), dvInfo.deviceType, + Anonymous::Change(dvInfo.uuid).c_str(), Anonymous::Change(dvInfo.deviceName).c_str(), dvInfo.deviceType, static_cast(dvInfo.authForm), dvInfo.osType); SaveDeviceInfo(dvInfo, DeviceChangeType::DEVICE_OFFLINE); auto task = [this, dvInfo]() { @@ -263,8 +263,9 @@ void DeviceManagerAdapter::OnChanged(const DmDeviceInfo &info) ZLOGE("get device info fail"); return; } - ZLOGI("[OnChanged] uuid:%{public}s, name:%{public}s, type:%{public}d", - KvStoreUtils::ToBeAnonymous(dvInfo.uuid).c_str(), dvInfo.deviceName.c_str(), dvInfo.deviceType); + ZLOGI("[OnChanged] uuid:%{public}s, name:%{public}s, type:%{public}d, authForm:%{public}d osType:%{public}d", + Anonymous::Change(dvInfo.uuid).c_str(), Anonymous::Change(dvInfo.deviceName).c_str(), dvInfo.deviceType, + static_cast(dvInfo.authForm), dvInfo.osType); } void DeviceManagerAdapter::OnReady(const DmDeviceInfo &info) @@ -275,8 +276,9 @@ void DeviceManagerAdapter::OnReady(const DmDeviceInfo &info) return; } readyDevices_.InsertOrAssign(dvInfo.uuid, std::make_pair(DeviceState::DEVICE_ONREADY, dvInfo)); - ZLOGI("[OnReady] uuid:%{public}s, name:%{public}s, type:%{public}d", - KvStoreUtils::ToBeAnonymous(dvInfo.uuid).c_str(), dvInfo.deviceName.c_str(), dvInfo.deviceType); + ZLOGI("[OnReady] uuid:%{public}s, name:%{public}s, type:%{public}d, authForm:%{public}d, osType:%{public}d", + Anonymous::Change(dvInfo.uuid).c_str(), Anonymous::Change(dvInfo.deviceName).c_str(), dvInfo.deviceType, + static_cast(dvInfo.authForm), dvInfo.osType); auto task = [this, dvInfo]() { observers_.ForEachCopies([&dvInfo](const auto &key, auto &value) { if (value != nullptr) { @@ -326,6 +328,11 @@ void DeviceManagerAdapter::SaveDeviceInfo(const DeviceInfo &dvInfo, const Device deviceInfos_.Set(dvInfo.uuid, dvInfo); deviceInfos_.Set(dvInfo.udid, dvInfo); readyDevices_.InsertOrAssign(dvInfo.uuid, std::make_pair(DeviceState::DEVICE_ONLINE, dvInfo)); + if (dvInfo.osType != OH_OS_TYPE) { + otherDeviceInfos_.Set(dvInfo.networkId, dvInfo); + otherDeviceInfos_.Set(dvInfo.uuid, dvInfo); + otherDeviceInfos_.Set(dvInfo.udid, dvInfo); + } break; } case DeviceChangeType::DEVICE_OFFLINE: { @@ -333,6 +340,11 @@ void DeviceManagerAdapter::SaveDeviceInfo(const DeviceInfo &dvInfo, const Device deviceInfos_.Delete(dvInfo.uuid); deviceInfos_.Delete(dvInfo.udid); readyDevices_.Erase(dvInfo.uuid); + if (dvInfo.osType != OH_OS_TYPE) { + otherDeviceInfos_.Delete(dvInfo.networkId); + otherDeviceInfos_.Delete(dvInfo.uuid); + otherDeviceInfos_.Delete(dvInfo.udid); + } break; } default: { @@ -409,7 +421,7 @@ bool DeviceManagerAdapter::IsOHOSType(const std::string &id) int32_t DeviceManagerAdapter::GetAuthType(const std::string &id) { DeviceInfo dvInfo; - if (!deviceInfos_.Get(id, dvInfo)) { + if (!otherDeviceInfos_.Get(id, dvInfo) && !deviceInfos_.Get(id, dvInfo)) { InitDeviceInfo(); deviceInfos_.Get(id, dvInfo); } @@ -434,7 +446,7 @@ DeviceInfo DeviceManagerAdapter::GetDeviceInfoFromCache(const std::string &id) deviceInfos_.Get(id, dvInfo); } if (dvInfo.uuid.empty()) { - ZLOGE("invalid id:%{public}s", KvStoreUtils::ToBeAnonymous(id).c_str()); + ZLOGE("invalid id:%{public}s", Anonymous::Change(id).c_str()); } return dvInfo; } @@ -451,7 +463,7 @@ void DeviceManagerAdapter::InitDeviceInfo(bool onlyCache) for (const auto &info : dvInfos) { if (info.networkId.empty() || info.uuid.empty() || info.udid.empty()) { ZLOGE("networkId:%{public}s, uuid:%{public}d, udid:%{public}d", - KvStoreUtils::ToBeAnonymous(info.networkId).c_str(), info.uuid.empty(), info.udid.empty()); + Anonymous::Change(info.networkId).c_str(), info.uuid.empty(), info.udid.empty()); continue; } deviceInfos_.Set(info.networkId, info); @@ -487,7 +499,8 @@ DeviceInfo DeviceManagerAdapter::GetLocalDeviceInfo() return {}; } ZLOGI("[LocalDevice] uuid:%{public}s, name:%{public}s, type:%{public}d, osType:%{public}d", - KvStoreUtils::ToBeAnonymous(uuid).c_str(), info.deviceName, info.deviceTypeId, deviceExtraInfo.OS_TYPE); + Anonymous::Change(uuid).c_str(), Anonymous::Change(info.deviceName).c_str(), info.deviceTypeId, + deviceExtraInfo.OS_TYPE); return { std::move(uuid), std::move(udid), std::move(networkId), std::string(info.deviceName), info.deviceTypeId, deviceExtraInfo.OS_TYPE, static_cast(info.authForm) }; } @@ -507,9 +520,12 @@ std::string DeviceManagerAdapter::GetUuidByNetworkId(const std::string &networkI std::string uuid; auto ret = DeviceManager::GetInstance().GetUuidByNetworkId(PKG_NAME, networkId, uuid); if (ret != DM_OK || uuid.empty()) { - ZLOGE("failed, result:%{public}d, networkId:%{public}s", ret, KvStoreUtils::ToBeAnonymous(networkId).c_str()); + ZLOGE("failed, result:%{public}d, networkId:%{public}s", ret, Anonymous::Change(networkId).c_str()); return ""; } + dvInfo.uuid = uuid; + dvInfo.networkId = networkId; + deviceInfos_.Set(uuid, dvInfo); return uuid; } @@ -528,7 +544,7 @@ std::string DeviceManagerAdapter::GetUdidByNetworkId(const std::string &networkI std::string udid; auto ret = DeviceManager::GetInstance().GetUdidByNetworkId(PKG_NAME, networkId, udid); if (ret != DM_OK || udid.empty()) { - ZLOGE("failed, result:%{public}d, networkId:%{public}s", ret, KvStoreUtils::ToBeAnonymous(networkId).c_str()); + ZLOGE("failed, result:%{public}d, networkId:%{public}s", ret, Anonymous::Change(networkId).c_str()); return ""; } return udid; diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/process_communicator_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/process_communicator_impl.cpp index 5d7edbdd276b5e20ac3d56381cf20ae85e844fd1..4eedaa7bc9b4a98b66af2d8a75a4c3d2041892a3 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/process_communicator_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/process_communicator_impl.cpp @@ -143,9 +143,10 @@ DBStatus ProcessCommunicatorImpl::SendData(const DeviceInfos &dstDevInfo, const uint32_t totalLength) { PipeInfo pi = {thisProcessLabel_, ""}; - const DataInfo dataInfo = { const_cast(data), length}; - DeviceId destination; - destination.deviceId = dstDevInfo.identifier; + ExtraDataInfo extraInfo = { .userId = dstDevInfo.callee.userId, .appId = dstDevInfo.callee.appId, + .storeId = dstDevInfo.callee.storeId }; + DataInfo dataInfo = { .data = const_cast(data), .length = length, .extraInfo = extraInfo }; + DeviceId destination = { .deviceId = dstDevInfo.identifier }; auto [errCode, softBusErrCode] = CommunicationProvider::GetInstance().SendData(pi, destination, dataInfo, totalLength); if (errCode == Status::RATE_LIMIT) { @@ -251,7 +252,7 @@ std::shared_ptr ProcessCommunicatorImpl::GetExtendHeaderHand return {}; } -DBStatus ProcessCommunicatorImpl::GetDataHeadInfo(const uint8_t *data, uint32_t totalLen, uint32_t &headLength) +DBStatus ProcessCommunicatorImpl::GetDataHeadInfo(DataHeadInfo dataHeadInfo, uint32_t &headLength) { if (routeHeadHandlerCreator_ == nullptr) { ZLOGE("header handler creator not registered"); @@ -262,16 +263,16 @@ DBStatus ProcessCommunicatorImpl::GetDataHeadInfo(const uint8_t *data, uint32_t ZLOGE("failed to get header handler"); return DBStatus::DB_ERROR; } - auto ret = handler->ParseHeadDataLen(data, totalLen, headLength); + auto ret = handler->ParseHeadDataLen(dataHeadInfo.data, dataHeadInfo.totalLen, headLength, dataHeadInfo.device); if (!ret) { - ZLOGE("illegal head format, dataLen:%{public}u, headLength:%{public}u", totalLen, headLength); + ZLOGE("illegal head format, dataLen:%{public}u, headLength:%{public}u, device:%{public}s", + dataHeadInfo.totalLen, headLength, Anonymous::Change(dataHeadInfo.device).c_str()); return DBStatus::INVALID_FORMAT; } return DBStatus::OK; } -DBStatus ProcessCommunicatorImpl::GetDataUserInfo(const uint8_t *data, uint32_t totalLen, const std::string &label, - std::vector &userInfos) +DBStatus ProcessCommunicatorImpl::GetDataUserInfo(DataUserInfo dataUserInfo, std::vector &userInfos) { if (routeHeadHandlerCreator_ == nullptr) { ZLOGE("header handler creator not registered"); @@ -282,9 +283,11 @@ DBStatus ProcessCommunicatorImpl::GetDataUserInfo(const uint8_t *data, uint32_t ZLOGE("failed to get header handler"); return DBStatus::DB_ERROR; } - auto ret = handler->ParseHeadDataUser(data, totalLen, label, userInfos); + auto ret = handler->ParseHeadDataUser(dataUserInfo.data, dataUserInfo.totalLen, dataUserInfo.label, userInfos); if (!ret) { - ZLOGD("illegal head format, dataLen:%{public}u, label:%{public}s", totalLen, Anonymous::Change(label).c_str()); + ZLOGE("illegal head format, dataLen:%{public}u, label:%{public}s, device:%{public}s", + dataUserInfo.totalLen, Anonymous::Change(dataUserInfo.label).c_str(), + Anonymous::Change(dataUserInfo.device).c_str()); return DBStatus::INVALID_FORMAT; } if (userInfos.empty()) { @@ -295,10 +298,10 @@ DBStatus ProcessCommunicatorImpl::GetDataUserInfo(const uint8_t *data, uint32_t return DBStatus::OK; } -Status ProcessCommunicatorImpl::ReuseConnect(const DeviceId &deviceId) +Status ProcessCommunicatorImpl::ReuseConnect(const DeviceId &deviceId, const ExtraDataInfo &extraInfo) { PipeInfo pi = {thisProcessLabel_, ""}; - return CommunicationProvider::GetInstance().ReuseConnect(pi, deviceId); + return CommunicationProvider::GetInstance().ReuseConnect(pi, deviceId, extraInfo); } } // namespace AppDistributedKv } // namespace OHOS \ No newline at end of file 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 08c572812639eef7555921feb2c7259d6562c21a..637df5016d012ae1a8494a36c7370ffcd9dcc9b2 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h @@ -15,6 +15,7 @@ #ifndef DISTRIBUTEDDATAFWK_SRC_SOFTBUS_ADAPTER_H #define DISTRIBUTEDDATAFWK_SRC_SOFTBUS_ADAPTER_H + #include #include #include @@ -28,23 +29,24 @@ #include "app_data_change_listener.h" #include "app_device_change_listener.h" #include "block_data.h" +#include "executor_pool.h" #include "socket.h" -#include "softbus_bus_center.h" #include "softbus_client.h" + namespace OHOS { namespace AppDistributedKv { -class SoftBusAdapter : public AppDistributedKv::AppDeviceChangeListener { +class SoftBusAdapter { public: - SoftBusAdapter(); - ~SoftBusAdapter(); - static std::shared_ptr GetInstance(); - struct ServerSocketInfo { std::string name; /**< Peer socket name */ std::string networkId; /**< Peer network ID */ std::string pkgName; /**< Peer package name */ }; + SoftBusAdapter(); + ~SoftBusAdapter(); + static std::shared_ptr GetInstance(); + // add DataChangeListener to watch data change; Status StartWatchDataChange(const AppDataChangeListener *observer, const PipeInfo &pipeInfo); @@ -81,26 +83,24 @@ public: uint32_t GetMtuSize(const DeviceId &deviceId); uint32_t GetTimeout(const DeviceId &deviceId); - void OnDeviceChanged(const AppDistributedKv::DeviceInfo &info, - const AppDistributedKv::DeviceChangeType &type) const override; - - Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId); + Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, const ExtraDataInfo &extraInfo); private: using Time = std::chrono::steady_clock::time_point; using Duration = std::chrono::steady_clock::duration; using Task = ExecutorPool::Task; + std::string DelConnect(int32_t socket, bool isForce); void StartCloseSessionTask(const std::string &deviceId); Task GetCloseSessionTask(); bool CloseSession(const std::string &networkId); void GetExpireTime(std::shared_ptr &conn); std::pair OpenConnect(const std::shared_ptr &conn, const DeviceId &deviceId); - std::shared_ptr GetConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, uint32_t qosType); - static constexpr const char *PKG_NAME = "distributeddata-default"; + bool ConfigSessionAccessInfo(const ExtraDataInfo &extraInfo, SessionAccessInfo &sessionAccessInfo); + std::shared_ptr GetConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, + const ExtraDataInfo &extraInfo); + static constexpr Time INVALID_NEXT = std::chrono::steady_clock::time_point::max(); - static constexpr uint32_t QOS_COUNT = 3; - static constexpr QosTV Qos[QOS_COUNT] = { { .qos = QOS_TYPE_MIN_BW, .value = 64 * 1024 }, - { .qos = QOS_TYPE_MAX_LATENCY, .value = 15000 }, { .qos = QOS_TYPE_MIN_LATENCY, .value = 1600 } }; + static std::shared_ptr instance_; ConcurrentMap dataChangeListeners_{}; ConcurrentMap>> connects_; 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 6fbbcb8011974030e8423a5049008cd5834055b4..c0a5a6d8de203530031d733cd99e998abb0ea246 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 @@ -12,37 +12,42 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include -#include -#include +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "SoftBusAdapter" + +#include "softbus_adapter.h" +#include "accesstoken_kit.h" +#include "account/account_delegate.h" #include "communication/connect_manager.h" #include "communicator_context.h" #include "data_level.h" #include "device_manager_adapter.h" -#include "dfx/dfx_types.h" -#include "dfx/reporter.h" -#include "kvstore_utils.h" #include "log_print.h" -#include "securec.h" -#include "session.h" -#include "softbus_adapter.h" -#include "softbus_bus_center.h" +#include "metadata/appid_meta_data.h" +#include "metadata/meta_data_manager.h" +#include "metadata/store_meta_data.h" #include "softbus_error_code.h" -#ifdef LOG_TAG -#undef LOG_TAG -#endif -#define LOG_TAG "SoftBusAdapter" +#include "trans_type.h" +#include "utils/anonymous.h" namespace OHOS { namespace AppDistributedKv { -using Context = DistributedData::CommunicatorContext; -constexpr uint32_t DEFAULT_MTU_SIZE = 4096 * 1024u; -constexpr uint32_t DEFAULT_TIMEOUT = 30 * 1000; using namespace std; -using namespace OHOS::DistributedDataDfx; using namespace OHOS::DistributedKv; -using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; +using namespace OHOS::DistributedData; +using namespace OHOS::Security::AccessToken; + +static constexpr const char *DEFAULT_USER = "default"; +static constexpr const char *SYSTEM_USER = "0"; +static constexpr const char *PKG_NAME = "distributeddata-default"; +static constexpr uint32_t DEFAULT_MTU_SIZE = 4096 * 1024u; +static constexpr uint32_t DEFAULT_TIMEOUT = 30 * 1000; +static constexpr uint32_t QOS_COUNT = 3; +static constexpr QosTV Qos[QOS_COUNT] = { { .qos = QOS_TYPE_MIN_BW, .value = 64 * 1024 }, + { .qos = QOS_TYPE_MAX_LATENCY, .value = 15000 }, { .qos = QOS_TYPE_MIN_LATENCY, .value = 1600 } }; class AppDataListenerWrap { public: @@ -55,12 +60,16 @@ public: static void OnServerBind(int32_t socket, PeerSocketInfo info); static void OnServerShutdown(int32_t socket, ShutdownReason reason); static void OnServerBytesReceived(int32_t socket, const void *data, uint32_t dataLen); + static bool OnServerAccessCheck(int32_t socket, PeerSocketInfo info, SocketAccessInfo *peerInfo, + SocketAccessInfo *localInfo); private: // notify all listeners when received message static void NotifyDataListeners(const uint8_t *data, const int size, const std::string &deviceId, const PipeInfo &pipeInfo); static std::string GetPipeId(const std::string &name); + static std::pair LoadMetaData(const std::string &bundleName, const std::string &storeId, + int32_t userId); static SoftBusAdapter *softBusAdapter_; }; @@ -69,7 +78,7 @@ SoftBusAdapter *AppDataListenerWrap::softBusAdapter_; std::shared_ptr SoftBusAdapter::instance_; namespace { -void OnDataLevelChanged(const char *networkId, const DataLevel dataLevel) +void OnDataLevelChanged(const char* networkId, const DataLevel dataLevel) { if (networkId == nullptr) { return; @@ -80,7 +89,7 @@ void OnDataLevelChanged(const char *networkId, const DataLevel dataLevel) .switches = dataLevel.switchLevel, .switchesLen = dataLevel.switchLength, }; - auto uuid = DmAdapter::GetInstance().GetUuidByNetworkId(networkId); + auto uuid = DeviceManagerAdapter::GetInstance().GetUuidByNetworkId(networkId); SoftBusAdapter::GetInstance()->OnBroadcast({ uuid }, std::move(level)); } @@ -88,6 +97,7 @@ IDataLevelCb g_callback = { .onDataLevelChanged = OnDataLevelChanged, }; } // namespace + SoftBusAdapter::SoftBusAdapter() { ZLOGI("begin"); @@ -102,23 +112,20 @@ SoftBusAdapter::SoftBusAdapter() serverListener_.OnShutdown = AppDataListenerWrap::OnServerShutdown; serverListener_.OnBytes = AppDataListenerWrap::OnServerBytesReceived; serverListener_.OnMessage = AppDataListenerWrap::OnServerBytesReceived; + serverListener_.OnNegotiate2 = AppDataListenerWrap::OnServerAccessCheck; - auto status = DmAdapter::GetInstance().StartWatchDeviceChange(this, { "softBusAdapter" }); - if (status != Status::SUCCESS) { - ZLOGW("register device change failed, status:%d", static_cast(status)); - } - - Context::GetInstance().SetSessionListener([this](const std::string &deviceId) { + CommunicatorContext::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()->RegisterSessionCloseListener("CommunicatorContext", + [](const std::string &networkId) { + auto uuid = DeviceManagerAdapter::GetInstance().GetUuidByNetworkId(networkId); + CommunicatorContext::GetInstance().NotifySessionClose(uuid); + }); ConnectManager::GetInstance()->OnStart(); } @@ -174,7 +181,7 @@ void SoftBusAdapter::GetExpireTime(std::shared_ptr &conn) 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); + taskId_ = CommunicatorContext::GetInstance().GetThreadPool()->Reset(taskId_, expireTime - now); next_ = expireTime; } } @@ -182,9 +189,7 @@ void SoftBusAdapter::GetExpireTime(std::shared_ptr &conn) std::pair SoftBusAdapter::SendData(const PipeInfo &pipeInfo, const DeviceId &deviceId, const DataInfo &dataInfo, uint32_t length, const MessageInfo &info) { - bool isOHOSType = DmAdapter::GetInstance().IsOHOSType(deviceId.deviceId); - uint32_t qosType = isOHOSType ? SoftBusClient::QOS_HML : SoftBusClient::QOS_BR; - std::shared_ptr conn = GetConnect(pipeInfo, deviceId, qosType); + std::shared_ptr conn = GetConnect(pipeInfo, deviceId, dataInfo.extraInfo); if (conn == nullptr) { return std::make_pair(Status::ERROR, 0); } @@ -195,7 +200,7 @@ std::pair SoftBusAdapter::SendData(const PipeInfo &pipeInfo, co if (status != Status::SUCCESS) { return OpenConnect(conn, deviceId); } - status = conn->SendData(dataInfo, &clientListener_); + status = conn->SendData(dataInfo); if ((status != Status::NETWORK_ERROR) && (status != Status::RATE_LIMIT)) { GetExpireTime(conn); } @@ -203,12 +208,65 @@ std::pair SoftBusAdapter::SendData(const PipeInfo &pipeInfo, co return std::make_pair(status, errCode); } +bool SoftBusAdapter::ConfigSessionAccessInfo(const ExtraDataInfo &extraInfo, SessionAccessInfo &sessionAccessInfo) +{ + if (extraInfo.userId.empty() || (extraInfo.bundleName.empty() && extraInfo.appId.empty()) || + extraInfo.storeId.empty()) { + ZLOGE("extraInfo is empty, userId:%{public}s, bundleName:%{public}s, appId:%{public}s, storeId:%{public}s", + extraInfo.userId.c_str(), extraInfo.bundleName.c_str(), extraInfo.appId.c_str(), + Anonymous::Change(extraInfo.storeId).c_str()); + return false; + } + AppIDMetaData appIdMeta; + if (extraInfo.bundleName.empty() && !MetaDataManager::GetInstance().LoadMeta(extraInfo.appId, appIdMeta, true)) { + ZLOGE("load appIdMeta fail, appId:%{public}s", extraInfo.appId.c_str()); + return false; + } + StoreMetaData metaData; + metaData.deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + metaData.user = extraInfo.userId == DEFAULT_USER ? SYSTEM_USER : extraInfo.userId; + metaData.bundleName = extraInfo.bundleName.empty() ? appIdMeta.bundleName : extraInfo.bundleName; + metaData.storeId = extraInfo.storeId; + if ((extraInfo.tokenId == 0) && !MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)) { + ZLOGE("get meta data fail, metaKey:%{public}s", Anonymous::Change(metaData.GetKeyWithoutPath()).c_str()); + return false; + } + sessionAccessInfo.bundleName = metaData.bundleName; + sessionAccessInfo.storeId = metaData.storeId; + sessionAccessInfo.tokenId = (extraInfo.tokenId != 0) ? extraInfo.tokenId : metaData.tokenId; + int foregroundUserId = 0; + auto ret = AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + if (!ret) { + return false; + } + sessionAccessInfo.userId = foregroundUserId; + auto accountId = AccountDelegate::GetInstance()->GetCurrentAccountId(); + if (accountId.empty()) { + return false; + } + sessionAccessInfo.accountId = accountId; + return true; +} + std::shared_ptr SoftBusAdapter::GetConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, - uint32_t qosType) + const ExtraDataInfo &extraInfo) { + std::string networkId = DeviceManagerAdapter::GetInstance().ToNetworkID(deviceId.deviceId); + if (networkId.empty()) { + ZLOGE("networkId is empty, deviceId:%{public}s", Anonymous::Change(deviceId.deviceId).c_str()); + return nullptr; + } std::shared_ptr conn; + auto isOHType = DeviceManagerAdapter::GetInstance().IsOHOSType(deviceId.deviceId); + SessionAccessInfo sessionAccessInfo = { .isOHType = isOHType }; + if (isOHType && !ConfigSessionAccessInfo(extraInfo, sessionAccessInfo)) { + ZLOGE("peer device is not oh device or config accessInfo fail, deviceId:%{public}s", + Anonymous::Change(deviceId.deviceId).c_str()); + return nullptr; + } + uint32_t qosType = isOHType ? SoftBusClient::QOS_HML : SoftBusClient::QOS_BR; connects_.Compute(deviceId.deviceId, - [&pipeInfo, &deviceId, &conn, qosType](const auto &key, + [&pipeInfo, &deviceId, &sessionAccessInfo, &conn, qosType, &networkId](const auto &key, std::vector> &connects) -> bool { for (auto &connect : connects) { if (connect == nullptr) { @@ -219,7 +277,7 @@ std::shared_ptr SoftBusAdapter::GetConnect(const PipeInfo &pipeIn return true; } } - auto connect = std::make_shared(pipeInfo, deviceId, qosType); + auto connect = std::make_shared(pipeInfo, deviceId, networkId, qosType, sessionAccessInfo); connects.emplace_back(connect); conn = connect; return true; @@ -230,21 +288,32 @@ std::shared_ptr SoftBusAdapter::GetConnect(const PipeInfo &pipeIn std::pair SoftBusAdapter::OpenConnect(const std::shared_ptr &conn, const DeviceId &deviceId) { - auto task = [this, connect = std::weak_ptr(conn)]() { + auto networkId = DeviceManagerAdapter::GetInstance().ToNetworkID(deviceId.deviceId); + if (conn != nullptr) { + auto oldNetworkId = conn->GetNetworkId(); + if (networkId != oldNetworkId) { + ZLOGI("peer networkId changed, %{public}s->%{public}s", Anonymous::Change(oldNetworkId).c_str(), + Anonymous::Change(networkId).c_str()); + conn->UpdateNetworkId(networkId); + } + } + auto applyTask = [deviceId](int32_t errcode) { + CommunicatorContext::GetInstance().NotifySessionReady(deviceId.deviceId, errcode); + }; + auto connectTask = [this, connect = std::weak_ptr(conn)]() { auto conn = connect.lock(); if (conn != nullptr) { conn->OpenConnect(&clientListener_); } }; - auto networkId = DmAdapter::GetInstance().GetDeviceInfo(deviceId.deviceId).networkId; - ConnectManager::GetInstance()->ApplyConnect(networkId, task); + ConnectManager::GetInstance()->ApplyConnect(networkId, applyTask, connectTask); return std::make_pair(Status::RATE_LIMIT, 0); } void SoftBusAdapter::StartCloseSessionTask(const std::string &deviceId) { std::shared_ptr conn; - bool isOHOSType = DmAdapter::GetInstance().IsOHOSType(deviceId); + bool isOHOSType = DeviceManagerAdapter::GetInstance().IsOHOSType(deviceId); uint32_t qosType = isOHOSType ? SoftBusClient::QOS_HML : SoftBusClient::QOS_BR; auto connects = connects_.Find(deviceId); if (!connects.first) { @@ -263,8 +332,8 @@ void SoftBusAdapter::StartCloseSessionTask(const std::string &deviceId) auto expireTime = conn->GetExpireTime() > now ? conn->GetExpireTime() : now; lock_guard lock(taskMutex_); if (taskId_ == ExecutorPool::INVALID_TASK_ID) { - ZLOGI("Start close session, deviceId:%{public}s", KvStoreUtils::ToBeAnonymous(deviceId).c_str()); - taskId_ = Context::GetInstance().GetThreadPool()->Schedule(expireTime - now, GetCloseSessionTask()); + ZLOGI("Start close session, deviceId:%{public}s", Anonymous::Change(deviceId).c_str()); + taskId_ = CommunicatorContext::GetInstance().GetThreadPool()->Schedule(expireTime - now, GetCloseSessionTask()); next_ = expireTime; } } @@ -293,7 +362,7 @@ SoftBusAdapter::Task SoftBusAdapter::GetCloseSessionTask() }); connects_.EraseIf([](const auto &key, const auto &conn) -> bool { if (conn.empty()) { - ConnectManager::GetInstance()->OnSessionClose(DmAdapter::GetInstance().GetDeviceInfo(key).networkId); + ConnectManager::GetInstance()->OnSessionClose(DeviceManagerAdapter::GetInstance().ToNetworkID(key)); } return conn.empty(); }); @@ -315,9 +384,8 @@ SoftBusAdapter::Task SoftBusAdapter::GetCloseSessionTask() taskId_ = ExecutorPool::INVALID_TASK_ID; return; } - taskId_ = - Context::GetInstance().GetThreadPool()->Schedule(next > now ? next - now : ExecutorPool::INVALID_DELAY, - GetCloseSessionTask()); + taskId_ = CommunicatorContext::GetInstance().GetThreadPool()->Schedule( + next > now ? next - now : ExecutorPool::INVALID_DELAY, GetCloseSessionTask()); next_ = next; }; } @@ -331,8 +399,8 @@ uint32_t SoftBusAdapter::GetMtuSize(const DeviceId &deviceId) if (conn == nullptr) { continue; } - if (mtu < conn->GetMtuSize()) { - mtu = conn->GetMtuSize(); + if (mtu < conn->GetMtuBuffer()) { + mtu = conn->GetMtuBuffer(); } } if (mtu != 0) { @@ -353,26 +421,27 @@ std::string SoftBusAdapter::DelConnect(int32_t socket, bool isForce) std::string name; std::set closedConnect; connects_.EraseIf([socket, isForce, &name, &closedConnect](const auto &deviceId, auto &connects) -> bool { - if (!isForce && DmAdapter::GetInstance().IsOHOSType(deviceId)) { + if (!isForce && DeviceManagerAdapter::GetInstance().IsOHOSType(deviceId)) { return false; } + std::string networkId; for (auto iter = connects.begin(); iter != connects.end();) { if (*iter != nullptr && **iter == socket) { name += deviceId; name += " "; + networkId = (*iter)->GetNetworkId(); iter = connects.erase(iter); } else { iter++; } } - if (connects.empty()) { - closedConnect.insert(deviceId); + if (connects.empty() && !networkId.empty()) { + closedConnect.insert(std::move(networkId)); return true; } return false; }); - for (const auto &deviceId : closedConnect) { - auto networkId = DmAdapter::GetInstance().GetDeviceInfo(deviceId).networkId; + for (const auto &networkId : closedConnect) { ConnectManager::GetInstance()->OnSessionClose(networkId); } return name; @@ -387,13 +456,13 @@ bool SoftBusAdapter::IsSameStartedOnPeer(const struct PipeInfo &pipeInfo, __attribute__((unused)) const struct DeviceId &peer) { ZLOGI("pipeInfo:%{public}s deviceId:%{public}s", pipeInfo.pipeId.c_str(), - KvStoreUtils::ToBeAnonymous(peer.deviceId).c_str()); + Anonymous::Change(peer.deviceId).c_str()); return true; } void SoftBusAdapter::SetMessageTransFlag(const PipeInfo &pipeInfo, bool flag) { - ZLOGI("pipeInfo: %s flag: %d", pipeInfo.pipeId.c_str(), flag); + ZLOGI("pipeInfo:%{public}s, flag:%{public}d", pipeInfo.pipeId.c_str(), flag); flag_ = flag; } @@ -423,11 +492,9 @@ void SoftBusAdapter::NotifyDataListeners(const uint8_t *data, int size, const st auto ret = dataChangeListeners_.ComputeIfPresent(pipeInfo.pipeId, [&data, &size, &deviceId, &pipeInfo](const auto &key, const AppDataChangeListener *&value) { ZLOGD("ready to notify, pipeName:%{public}s, deviceId:%{public}s.", pipeInfo.pipeId.c_str(), - KvStoreUtils::ToBeAnonymous(deviceId).c_str()); - DeviceInfo deviceInfo = DmAdapter::GetInstance().GetDeviceInfo(deviceId); + Anonymous::Change(deviceId).c_str()); + DeviceInfo deviceInfo = DeviceManagerAdapter::GetInstance().GetDeviceInfo(deviceId); value->OnMessage(deviceInfo, data, size, pipeInfo); - TrafficStat ts{ pipeInfo.pipeId, deviceId, 0, size }; - Reporter::GetInstance()->TrafficStatistic()->Report(ts); return true; }); if (!ret) { @@ -447,14 +514,14 @@ Status SoftBusAdapter::Broadcast(const PipeInfo &pipeInfo, const LevelInfo &leve if (status == SOFTBUS_FUNC_NOT_SUPPORT) { return Status::NOT_SUPPORT_BROADCAST; } - return status ? Status::ERROR : Status::SUCCESS; + return status != SOFTBUS_OK ? Status::ERROR : Status::SUCCESS; } void SoftBusAdapter::OnBroadcast(const DeviceId &device, const LevelInfo &levelInfo) { - ZLOGI("device:%{public}s", KvStoreUtils::ToBeAnonymous(device.deviceId).c_str()); + ZLOGI("device:%{public}s", Anonymous::Change(device.deviceId).c_str()); if (!onBroadcast_) { - ZLOGW("no listener device:%{public}s", KvStoreUtils::ToBeAnonymous(device.deviceId).c_str()); + ZLOGW("no listener device:%{public}s", Anonymous::Change(device.deviceId).c_str()); return; } onBroadcast_(device.deviceId, levelInfo); @@ -481,7 +548,7 @@ void AppDataListenerWrap::OnClientShutdown(int32_t socket, ShutdownReason reason // when the local close the session, this callback function will not be triggered; // when the current function is called, soft bus has released the session resource, only connId is valid; std::string name = softBusAdapter_->OnClientShutdown(socket); - ZLOGI("[shutdown] socket:%{public}d, name:%{public}s", socket, KvStoreUtils::ToBeAnonymous(name).c_str()); + ZLOGI("[shutdown] socket:%{public}d, name:%{public}s", socket, Anonymous::Change(name).c_str()); } void AppDataListenerWrap::OnClientBytesReceived(int32_t socket, const void *data, uint32_t dataLen) {} @@ -490,17 +557,17 @@ void AppDataListenerWrap::OnClientSocketChanged(int32_t socket, QoSEvent eventId { if (eventId == QoSEvent::QOS_SATISFIED && qos != nullptr && qos[0].qos == QOS_TYPE_MIN_BW && qosCount == 1) { auto name = softBusAdapter_->OnClientShutdown(socket, false); - ZLOGI("[SocketChanged] socket:%{public}d, name:%{public}s", socket, KvStoreUtils::ToBeAnonymous(name).c_str()); + ZLOGI("[SocketChanged] socket:%{public}d, name:%{public}s", socket, Anonymous::Change(name).c_str()); } } void AppDataListenerWrap::OnServerBind(int32_t socket, PeerSocketInfo info) { softBusAdapter_->OnBind(socket, info); - std::string peerDevUuid = DmAdapter::GetInstance().GetUuidByNetworkId(std::string(info.networkId)); + std::string peerDevUuid = DeviceManagerAdapter::GetInstance().GetUuidByNetworkId(std::string(info.networkId)); ZLOGI("[OnServerBind] socket:%{public}d, peer name:%{public}s, peer devId:%{public}s", socket, info.name, - KvStoreUtils::ToBeAnonymous(peerDevUuid).c_str()); + Anonymous::Change(peerDevUuid).c_str()); } void AppDataListenerWrap::OnServerShutdown(int32_t socket, ShutdownReason reason) @@ -516,9 +583,9 @@ void AppDataListenerWrap::OnServerBytesReceived(int32_t socket, const void *data ZLOGE("Get peer socket info failed, socket id %{public}d", socket); return; }; - std::string peerDevUuid = DmAdapter::GetInstance().GetUuidByNetworkId(std::string(info.networkId)); + std::string peerDevUuid = DeviceManagerAdapter::GetInstance().GetUuidByNetworkId(std::string(info.networkId)); ZLOGD("[OnBytesReceived] socket:%{public}d, peer name:%{public}s, peer devId:%{public}s, data len:%{public}u", - socket, info.name.c_str(), KvStoreUtils::ToBeAnonymous(peerDevUuid).c_str(), dataLen); + socket, info.name.c_str(), Anonymous::Change(peerDevUuid).c_str(), dataLen); std::string pipeId = GetPipeId(info.name); if (pipeId.empty()) { @@ -529,6 +596,69 @@ void AppDataListenerWrap::OnServerBytesReceived(int32_t socket, const void *data NotifyDataListeners(reinterpret_cast(data), dataLen, peerDevUuid, { pipeId, "" }); } +std::pair AppDataListenerWrap::LoadMetaData(const std::string &bundleName, + const std::string &storeId, int32_t userId) +{ + StoreMetaData metaData; + metaData.deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + metaData.bundleName = bundleName; + metaData.storeId = storeId; + metaData.user = std::to_string(userId); + auto ret = MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData); + if (!ret) { + metaData.user = SYSTEM_USER; + ret = MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData); + } + return { ret, metaData }; +} + +bool AppDataListenerWrap::OnServerAccessCheck(int32_t socket, PeerSocketInfo info, SocketAccessInfo *peerInfo, + SocketAccessInfo *localInfo) +{ + ZLOGI("receive bind request, socket:%{public}d", socket); + if (peerInfo == nullptr || localInfo == nullptr) { + ZLOGE("peerInfo or localInfo is nullptr, peerInfo:%{public}d, localInfo:%{public}d", peerInfo == nullptr, + localInfo == nullptr); + return false; + } + SoftBusClient::AccessExtraInfo peerExtraInfo; + if (!DistributedData::Serializable::Unmarshall(peerInfo->extraAccessInfo, peerExtraInfo)) { + ZLOGE("Unmarshall failed, peer extraAccessInfo:%{public}s", peerInfo->extraAccessInfo); + return false; + } + int foregroundUserId = 0; + if (!AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId)) { + return false; + } + localInfo->userId = foregroundUserId; + auto resultPair = LoadMetaData(peerExtraInfo.bundleName, peerExtraInfo.storeId, foregroundUserId); + if (!resultPair.first) { + ZLOGE("local device has no store, bundleName:%{public}s", peerExtraInfo.bundleName.c_str()); + return false; + } + localInfo->localTokenId = resultPair.second.tokenId; + auto type = AccessTokenKit::GetTokenTypeFlag(resultPair.second.tokenId); + if (type == TOKEN_NATIVE || type == TOKEN_SHELL) { + ZLOGW("this is system service sync, bundleName:%{public}s", peerExtraInfo.bundleName.c_str()); + return true; + } + AclParams aclParams; + aclParams.accCaller.bundleName = peerExtraInfo.bundleName; + aclParams.accCaller.accountId = AccountDelegate::GetInstance()->GetCurrentAccountId(); + aclParams.accCaller.userId = foregroundUserId; + aclParams.accCaller.networkId = DeviceManagerAdapter::GetInstance().GetLocalDevice().networkId; + aclParams.accCallee.accountId = peerExtraInfo.accountId; + aclParams.accCallee.userId = peerInfo->userId; + aclParams.accCallee.networkId = std::string(info.networkId); + bool accessFlag = false; + if (resultPair.second.authType == AuthType::IDENTICAL_ACCOUNT) { + accessFlag = DeviceManagerAdapter::GetInstance().IsSameAccount(aclParams.accCaller, aclParams.accCallee); + } else { + accessFlag = DeviceManagerAdapter::GetInstance().CheckAccessControl(aclParams.accCaller, aclParams.accCallee); + } + return accessFlag; +} + std::string AppDataListenerWrap::GetPipeId(const std::string &name) { auto pos = name.find('_'); @@ -557,9 +687,9 @@ bool SoftBusAdapter::GetPeerSocketInfo(int32_t socket, ServerSocketInfo &info) void SoftBusAdapter::OnBind(int32_t socket, PeerSocketInfo info) { ServerSocketInfo socketInfo; - socketInfo.name = info.name; - socketInfo.networkId = info.networkId; - socketInfo.pkgName = info.pkgName; + socketInfo.name = std::string(info.name); + socketInfo.networkId = std::string(info.networkId); + socketInfo.pkgName = std::string(info.pkgName); peerSocketInfos_.Insert(socket, socketInfo); } @@ -568,15 +698,9 @@ void SoftBusAdapter::OnServerShutdown(int32_t socket) peerSocketInfos_.Erase(socket); } -void SoftBusAdapter::OnDeviceChanged(const AppDistributedKv::DeviceInfo &info, - const AppDistributedKv::DeviceChangeType &type) const -{ - return; -} - bool SoftBusAdapter::CloseSession(const std::string &networkId) { - auto uuid = DmAdapter::GetInstance().GetUuidByNetworkId(networkId); + auto uuid = DeviceManagerAdapter::GetInstance().GetUuidByNetworkId(networkId); auto ret = connects_.Erase(uuid); if (ret != 0) { ConnectManager::GetInstance()->OnSessionClose(networkId); @@ -584,14 +708,13 @@ bool SoftBusAdapter::CloseSession(const std::string &networkId) return ret != 0; } -Status SoftBusAdapter::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId) +Status SoftBusAdapter::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, const ExtraDataInfo &extraInfo) { - bool isOHOSType = DmAdapter::GetInstance().IsOHOSType(deviceId.deviceId); + bool isOHOSType = DeviceManagerAdapter::GetInstance().IsOHOSType(deviceId.deviceId); if (!isOHOSType) { return Status::NOT_SUPPORT; } - uint32_t qosType = SoftBusClient::QOS_HML; - std::shared_ptr conn = GetConnect(pipeInfo, deviceId, qosType); + std::shared_ptr conn = GetConnect(pipeInfo, deviceId, extraInfo); if (conn == nullptr) { return Status::ERROR; } @@ -599,20 +722,21 @@ Status SoftBusAdapter::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &de if (status != Status::SUCCESS) { return status; } + uint32_t qosType = SoftBusClient::QOS_HML; // Avoid being cleared by scheduled tasks - connects_.Compute(deviceId.deviceId, - [&conn, qosType](const auto &key, std::vector> &connects) -> bool { - for (auto &connect : connects) { - if (connect == nullptr) { - continue; - } - if (connect->GetQoSType() == qosType) { - return true; - } + connects_.Compute(deviceId.deviceId, [&conn, qosType](const auto &key, + std::vector> &connects) -> bool { + for (auto &connect : connects) { + if (connect == nullptr) { + continue; } - connects.emplace_back(conn); - return true; - }); + if (connect->GetQoSType() == qosType) { + return true; + } + } + connects.emplace_back(conn); + return true; + }); StartCloseSessionTask(deviceId.deviceId); return Status::SUCCESS; } 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 f4451869fc0dd6eb479961ce84b27b9aaed1e225..67ec7146de386b65adebddd35fcc9d16ca2acb19 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp @@ -14,30 +14,30 @@ */ #define LOG_TAG "SoftBusClient" + #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" #include "log_print.h" #include "softbus_error_code.h" +#include "utils/anonymous.h" namespace OHOS::AppDistributedKv { using namespace OHOS::DistributedKv; -using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; -using Context = DistributedData::CommunicatorContext; -SoftBusClient::SoftBusClient(const PipeInfo& pipeInfo, const DeviceId& deviceId, uint32_t type) - : type_(type), pipe_(pipeInfo), device_(deviceId) +using namespace OHOS::DistributedData; + +SoftBusClient::SoftBusClient(const PipeInfo& pipeInfo, const DeviceId& deviceId, const std::string& networkId, + uint32_t type, const SessionAccessInfo &accessInfo) : type_(type), pipe_(pipeInfo), device_(deviceId), + networkId_(networkId), accessInfo_(accessInfo) { mtu_ = DEFAULT_MTU_SIZE; } SoftBusClient::~SoftBusClient() { - ZLOGI("Shutdown socket:%{public}d, deviceId:%{public}s", socket_, - KvStoreUtils::ToBeAnonymous(device_.deviceId).c_str()); + ZLOGI("Shutdown socket:%{public}d, deviceId:%{public}s", socket_, Anonymous::Change(device_.deviceId).c_str()); if (socket_ > 0) { Shutdown(socket_); } @@ -53,7 +53,7 @@ bool SoftBusClient::operator==(const std::string &deviceId) const return device_.deviceId == deviceId; } -uint32_t SoftBusClient::GetMtuSize() const +uint32_t SoftBusClient::GetMtuBuffer() const { ZLOGD("get mtu size socket:%{public}d mtu:%{public}d", socket_, mtu_); return mtu_; @@ -64,7 +64,7 @@ uint32_t SoftBusClient::GetTimeout() const return DEFAULT_TIMEOUT; } -Status SoftBusClient::SendData(const DataInfo &dataInfo, const ISocketListener *listener) +Status SoftBusClient::SendData(const DataInfo &dataInfo) { std::lock_guard lock(mutex_); auto result = CheckStatus(); @@ -111,12 +111,16 @@ Status SoftBusClient::OpenConnect(const ISocketListener *listener) return; } ZLOGI("Bind Start, device:%{public}s socket:%{public}d type:%{public}u", - KvStoreUtils::ToBeAnonymous(client->device_.deviceId).c_str(), clientSocket, type); + Anonymous::Change(client->device_.deviceId).c_str(), clientSocket, type); int32_t status = client->Open(clientSocket, type, listener); - Context::GetInstance().NotifySessionReady(client->device_.deviceId, status); + CommunicatorContext::GetInstance().NotifySessionReady(client->device_.deviceId, status); client->isOpening_.store(false); }; - Context::GetInstance().GetThreadPool()->Execute(task); + auto executorPool = CommunicatorContext::GetInstance().GetThreadPool(); + if (executorPool == nullptr) { + return Status::NETWORK_ERROR; + } + executorPool->Execute(task); return Status::RATE_LIMIT; } @@ -125,7 +129,7 @@ int32_t SoftBusClient::CreateSocket() const SocketInfo socketInfo; std::string peerName = pipe_.pipeId; socketInfo.peerName = const_cast(peerName.c_str()); - std::string networkId = DmAdapter::GetInstance().ToNetworkID(device_.deviceId); + auto networkId = GetNetworkId(); socketInfo.peerNetworkId = const_cast(networkId.c_str()); std::string clientName = pipe_.pipeId; socketInfo.name = const_cast(clientName.c_str()); @@ -135,6 +139,29 @@ int32_t SoftBusClient::CreateSocket() const int32_t socket = Socket(socketInfo); if (socket <= 0) { ZLOGE("Create the client Socket:%{public}d failed, peerName:%{public}s", socket, socketInfo.peerName); + return socket; + } + if (accessInfo_.isOHType) { + SocketAccessInfo info; + info.userId = accessInfo_.userId; + info.localTokenId = accessInfo_.tokenId; + AccessExtraInfo extraInfo; + extraInfo.bundleName = accessInfo_.bundleName; + extraInfo.accountId = accessInfo_.accountId; + extraInfo.storeId = accessInfo_.storeId; + std::string extraInfoStr = Serializable::Marshall(extraInfo); + if (extraInfoStr.empty()) { + ZLOGE("Marshall access info fail"); + return INVALID_SOCKET_ID; + } + info.extraAccessInfo = const_cast(extraInfoStr.c_str()); + auto status = SetAccessInfo(socket, info); + if (status != SOFTBUS_OK) { + ZLOGE("SetAccessInfo fail, status:%{public}d, userId:%{public}d, bundleName:%{public}s," + "accountId:%{public}s, storeId:%{public}s", status, info.userId, extraInfo.bundleName.c_str(), + Anonymous::Change(extraInfo.accountId).c_str(), Anonymous::Change(extraInfo.storeId).c_str()); + return INVALID_SOCKET_ID; + } } return socket; } @@ -155,29 +182,31 @@ Status SoftBusClient::CheckStatus() int32_t SoftBusClient::Open(int32_t socket, uint32_t type, const ISocketListener *listener, bool async) { - int32_t status = ::Bind(socket, QOS_INFOS[type % QOS_BUTT], QOS_COUNTS[type % QOS_BUTT], listener); - ZLOGI("Bind %{public}s,session:%{public}s,socketId:%{public}d", - KvStoreUtils::ToBeAnonymous(device_.deviceId).c_str(), pipe_.pipeId.c_str(), socket); - - if (status != 0) { - ZLOGE("[Bind] device:%{public}s socket failed, session:%{public}s,result:%{public}d", - KvStoreUtils::ToBeAnonymous(device_.deviceId).c_str(), pipe_.pipeId.c_str(), status); - ::Shutdown(socket); + auto networkId = GetNetworkId(); + ZLOGI("Bind start, device:%{public}s, networkId:%{public}s, session:%{public}s, socketId:%{public}d", + Anonymous::Change(device_.deviceId).c_str(), Anonymous::Change(networkId).c_str(), + pipe_.pipeId.c_str(), socket); + int32_t status = Bind(socket, QOS_INFOS[type % QOS_BUTT], QOS_COUNTS[type % QOS_BUTT], listener); + if (status != SOFTBUS_OK) { + ZLOGE("Bind fail, device:%{public}s, networkId:%{public}s, socketId:%{public}d, result:%{public}d", + Anonymous::Change(device_.deviceId).c_str(), Anonymous::Change(networkId).c_str(), socket, status); + Shutdown(socket); return status; } - UpdateExpireTime(async); uint32_t mtu = 0; std::tie(status, mtu) = GetMtu(socket); if (status != SOFTBUS_OK) { ZLOGE("GetMtu failed, session:%{public}s, socket:%{public}d, status:%{public}d", pipe_.pipeId.c_str(), socket_, status); - ::Shutdown(socket); + Shutdown(socket); return status; } UpdateBindInfo(socket, mtu, status, async); - 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); + expireTime_ = CalcExpireTime(); + ZLOGI("Bind success, device:%{public}s, networkId:%{public}s, session:%{public}s, socketId:%{public}d", + Anonymous::Change(device_.deviceId).c_str(), Anonymous::Change(networkId).c_str(), + pipe_.pipeId.c_str(), socket); + ConnectManager::GetInstance()->OnSessionOpen(networkId); return status; } @@ -192,21 +221,6 @@ int32_t SoftBusClient::GetSocket() const return socket_; } -void SoftBusClient::UpdateExpireTime(bool async) -{ - auto expireTime = CalcExpireTime(); - if (async) { - std::lock_guard lock(mutex_); - if (expireTime > expireTime_) { - expireTime_ = expireTime; - } - } else { - if (expireTime > expireTime_) { - expireTime_ = expireTime; - } - } -} - void SoftBusClient::UpdateBindInfo(int32_t socket, uint32_t mtu, int32_t status, bool async) { if (async) { @@ -224,7 +238,7 @@ void SoftBusClient::UpdateBindInfo(int32_t socket, uint32_t mtu, int32_t status, std::pair SoftBusClient::GetMtu(int32_t socket) { uint32_t mtu = 0; - auto ret = ::GetMtuSize(socket, &mtu); + auto ret = GetMtuSize(socket, &mtu); return { ret, mtu }; } @@ -244,7 +258,7 @@ Status SoftBusClient::ReuseConnect(const ISocketListener *listener) std::lock_guard lock(mutex_); auto checkStatus = CheckStatus(); if (checkStatus == Status::SUCCESS) { - UpdateExpireTime(false); + expireTime_ = CalcExpireTime(); return Status::SUCCESS; } int32_t socket = CreateSocket(); @@ -252,8 +266,20 @@ Status SoftBusClient::ReuseConnect(const ISocketListener *listener) return Status::NETWORK_ERROR; } ZLOGI("Reuse Start, device:%{public}s session:%{public}s socket:%{public}d", - KvStoreUtils::ToBeAnonymous(device_.deviceId).c_str(), pipe_.pipeId.c_str(), socket); + Anonymous::Change(device_.deviceId).c_str(), pipe_.pipeId.c_str(), socket); int32_t status = Open(socket, QOS_REUSE, listener, false); return status == SOFTBUS_OK ? Status::SUCCESS : Status::NETWORK_ERROR; } + +std::string SoftBusClient::GetNetworkId() const +{ + std::lock_guard lock(networkIdMutex_); + return networkId_; +} + +void SoftBusClient::UpdateNetworkId(const std::string& networkId) +{ + std::lock_guard lock(networkIdMutex_); + networkId_ = networkId; +} } // namespace OHOS::AppDistributedKv \ No newline at end of file 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 67709bf9007d755123e27b8bfc25033dae199c50..f6851c974b4df13995f530039e9f1ab145c204c5 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h @@ -17,40 +17,65 @@ #define DISTRIBUTEDDATAMGR_DATAMGR_SERVICE_SOFTBUS_CLIENT_H #include -#include #include #include "commu_types.h" -#include "executor_pool.h" +#include "serializable/serializable.h" #include "socket.h" -#include "softbus_bus_center.h" + namespace OHOS::AppDistributedKv { class SoftBusClient : public std::enable_shared_from_this { public: + struct AccessExtraInfo final : public DistributedData::Serializable { + std::string bundleName = ""; + std::string accountId = ""; + std::string storeId = ""; + + AccessExtraInfo() {}; + ~AccessExtraInfo() {}; + bool Marshal(json &node) const override + { + SetValue(node[GET_NAME(bundleName)], bundleName); + SetValue(node[GET_NAME(accountId)], accountId); + SetValue(node[GET_NAME(storeId)], storeId); + return true; + }; + bool Unmarshal(const json &node) override + { + GetValue(node, GET_NAME(bundleName), bundleName); + GetValue(node, GET_NAME(accountId), accountId); + GetValue(node, GET_NAME(storeId), storeId); + return true; + }; + }; + enum QoSType { QOS_BR, QOS_HML, QOS_REUSE, QOS_BUTT }; - SoftBusClient(const PipeInfo &pipeInfo, const DeviceId &deviceId, uint32_t type = QOS_HML); + + SoftBusClient(const PipeInfo &pipeInfo, const DeviceId &deviceId, const std::string& networkId, + uint32_t type = QOS_HML, const SessionAccessInfo &accessInfo = {}); ~SoftBusClient(); 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); + Status SendData(const DataInfo &dataInfo); bool operator==(int32_t socket) const; bool operator==(const std::string &deviceId) const; - uint32_t GetMtuSize() const; + uint32_t GetMtuBuffer() const; uint32_t GetTimeout() const; Time GetExpireTime() const; int32_t GetSocket() const; uint32_t GetQoSType() const; - void UpdateExpireTime(bool async = true); int32_t GetSoftBusError(); Status ReuseConnect(const ISocketListener *listener); + std::string GetNetworkId() const; + void UpdateNetworkId(const std::string &networkId); private: int32_t Open(int32_t socket, uint32_t type, const ISocketListener *listener, bool async = true); @@ -86,6 +111,7 @@ private: static constexpr uint32_t QOS_COUNTS[QOS_BUTT] = { BR_QOS_COUNT, HML_QOS_COUNT, REUSE_QOS_COUNT }; std::atomic_bool isOpening_ = false; mutable std::mutex mutex_; + mutable std::mutex networkIdMutex_; uint32_t type_ = QOS_HML; PipeInfo pipe_; DeviceId device_; @@ -95,7 +121,8 @@ private: int32_t socket_ = INVALID_SOCKET_ID; int32_t bindState_ = -1; int32_t softBusError_ = 0; + std::string networkId_; + SessionAccessInfo accessInfo_; }; } // namespace OHOS::AppDistributedKv - #endif // DISTRIBUTEDDATAMGR_DATAMGR_SERVICE_SOFTBUS_CLIENT_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/communicator/test/BUILD.gn index 5e5a3489d5438eaa917185bec97fa6ec43cf30bd..e236f8d51af004a7287d89f66de67cdda8945083 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/BUILD.gn @@ -26,14 +26,17 @@ ohos_unittest("CommunicationProviderTest") { "../src", ] external_deps = [ + "access_token:libaccesstoken_sdk", "dsoftbus:softbus_client", "hilog:libhilog", "ipc:ipc_core", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", ] deps = [ "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } @@ -54,11 +57,13 @@ ohos_unittest("CommunicatorContextTest") { "../../include/communicator", ] external_deps = [ + "access_token:libaccesstoken_sdk", "c_utils:utils", "device_manager:devicemanagersdk", "dsoftbus:softbus_client", "googletest:gtest_main", "hilog:libhilog", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddb", ] @@ -68,6 +73,7 @@ ohos_unittest("CommunicatorContextTest") { ] deps = [ "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } @@ -78,11 +84,13 @@ ohos_unittest("CommunicatorDataBufferTest") { sources = [ "unittest/data_buffer_test.cpp" ] include_dirs = [ "../src" ] external_deps = [ + "access_token:libaccesstoken_sdk", "c_utils:utils", "device_manager:devicemanagersdk", "dsoftbus:softbus_client", "googletest:gtest_main", "hilog:libhilog", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", ] cflags = [ @@ -106,13 +114,14 @@ ohos_unittest("DeviceManagerAdapterTest") { ] external_deps = [ "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "access_token:libtoken_setproc", "c_utils:utils", "device_manager:devicemanagersdk", "dsoftbus:softbus_client", "hilog:libhilog", "ipc:ipc_core", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", ] cflags = [ @@ -121,6 +130,7 @@ ohos_unittest("DeviceManagerAdapterTest") { ] deps = [ "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } @@ -153,12 +163,10 @@ ohos_unittest("ProcessCommunicatorImplTest") { "../src", "../../include/communicator", "../../include/utils", - "${data_service_path}/adapter/include/communicator", - "${data_service_path}/framework/include/dfx", - "${data_service_path}/framework/include/utils", ] external_deps = [ + "access_token:libaccesstoken_sdk", "c_utils:utils", "device_manager:devicemanagersdk", "dsoftbus:softbus_client", @@ -166,6 +174,7 @@ ohos_unittest("ProcessCommunicatorImplTest") { "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "json:nlohmann_json_static", "kv_store:datamgr_common", "kv_store:distributeddata_inner", "kv_store:distributeddb", @@ -180,52 +189,42 @@ ohos_unittest("ProcessCommunicatorImplTest") { "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "../../dfx:distributeddata_dfx", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } ohos_unittest("SoftbusAdapterStandardTest") { module_out_path = module_output_path - - sources = [ - "../src/app_pipe_handler.cpp", - "../src/app_pipe_handler.h", - "../src/app_pipe_mgr.cpp", - "../src/app_pipe_mgr.h", - "../src/ark_communication_provider.cpp", - "../src/communication_provider.cpp", - "../src/communication_provider_impl.cpp", - "../src/communicator_context.cpp", - "../src/data_buffer.cpp", - "../src/device_manager_adapter.cpp", - "../src/process_communicator_impl.cpp", - "../src/softbus_adapter.h", - "../src/softbus_client.cpp", - "../src/softbus_client.h", - "unittest/softbus_adapter_standard_test.cpp", - ] - include_dirs = [ + "${data_service_path}/adapter/account/src", + "${data_service_path}/adapter/communicator/src", + "${data_service_path}/adapter/communicator/test/mock/device_manager", + "${data_service_path}/adapter/communicator/test/mock/softbus", "${data_service_path}/adapter/include/communicator", - "${data_service_path}/framework/include/dfx", - "../src", - "../../include/communicator", - "../../include/utils", - "${data_service_path}/framework/include/utils", + "${data_service_path}/service/test/mock", + ] + sources = [ + "${data_service_path}/adapter/account/src/account_delegate_default_impl.cpp", + "${data_service_path}/adapter/account/src/account_delegate_impl.cpp", + "${data_service_path}/adapter/communicator/src/communicator_context.cpp", + "${data_service_path}/adapter/communicator/src/data_buffer.cpp", + "${data_service_path}/adapter/communicator/src/device_manager_adapter.cpp", + "${data_service_path}/adapter/communicator/src/softbus_adapter_standard.cpp", + "${data_service_path}/adapter/communicator/src/softbus_client.cpp", + "${data_service_path}/adapter/communicator/test/mock/device_manager/device_manager.cpp", + "${data_service_path}/adapter/communicator/test/mock/softbus/data_level.cpp", + "${data_service_path}/adapter/communicator/test/mock/softbus/inner_socket.cpp", + "${data_service_path}/adapter/communicator/test/mock/softbus/socket.cpp", + "${data_service_path}/adapter/communicator/test/unittest/softbus_adapter_standard_test.cpp", + "${data_service_path}/service/test/mock/db_store_mock.cpp", + "${data_service_path}/service/test/mock/db_change_data_mock.cpp", ] external_deps = [ "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", - "access_token:libtoken_setproc", "c_utils:utils", - "device_manager:devicemanagersdk", - "dsoftbus:softbus_client", "hilog:libhilog", - "ipc:ipc_core", "json:nlohmann_json_static", "kv_store:datamgr_common", - "kv_store:distributeddata_inner", "kv_store:distributeddb", ] cflags = [ @@ -233,38 +232,38 @@ ohos_unittest("SoftbusAdapterStandardTest") { "-Dprotected=public", ] deps = [ - "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", - "../../dfx:distributeddata_dfx", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } ohos_unittest("SoftbusClientTest") { module_out_path = module_output_path - - sources = [ "unittest/softbus_client_test.cpp" ] include_dirs = [ - "${data_service_path}/adapter/include/autils", + "${data_service_path}/adapter/communicator/src", + "${data_service_path}/adapter/communicator/test/mock/softbus", "${data_service_path}/adapter/include/communicator", - "${data_service_path}/adapter/include/dfx", - "../src", + ] + sources = [ + "${data_service_path}/adapter/communicator/src/communicator_context.cpp", + "${data_service_path}/adapter/communicator/src/softbus_client.cpp", + "${data_service_path}/adapter/communicator/test/mock/softbus/inner_socket.cpp", + "${data_service_path}/adapter/communicator/test/mock/softbus/socket.cpp", + "${data_service_path}/adapter/communicator/test/unittest/softbus_client_test.cpp", ] external_deps = [ + "access_token:libaccesstoken_sdk", "c_utils:utils", - "device_manager:devicemanagersdk", - "dsoftbus:softbus_client", - "googletest:gtest_main", "hilog:libhilog", - "kv_store:distributeddata_inner", - "kv_store:distributeddb", + "json:nlohmann_json_static", + "kv_store:datamgr_common", ] cflags = [ "-Dprivate=public", "-Dprotected=public", ] deps = [ - "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } @@ -272,29 +271,38 @@ ohos_unittest("SoftbusClientTest") { ohos_unittest("AppPipeMgrServiceTest") { module_out_path = module_output_path include_dirs = [ - "${data_service_path}/adapter/include/autils", + "${data_service_path}/adapter/communicator/src", + "${data_service_path}/adapter/communicator/test/mock/device_manager", + "${data_service_path}/adapter/communicator/test/mock/softbus", "${data_service_path}/adapter/include/communicator", - "${data_service_path}/adapter/include/dfx", - "${data_service_path}/adapter/include/utils", - "${data_service_path}/framework/include/dfx", - "../src", ] - sources = [ "unittest/app_pipe_mgr_service_test.cpp" ] + sources = [ + "${data_service_path}/adapter/communicator/src/app_pipe_handler.cpp", + "${data_service_path}/adapter/communicator/src/app_pipe_mgr.cpp", + "${data_service_path}/adapter/communicator/src/communicator_context.cpp", + "${data_service_path}/adapter/communicator/src/data_buffer.cpp", + "${data_service_path}/adapter/communicator/src/device_manager_adapter.cpp", + "${data_service_path}/adapter/communicator/src/softbus_adapter_standard.cpp", + "${data_service_path}/adapter/communicator/src/softbus_client.cpp", + "${data_service_path}/adapter/communicator/test/mock/device_manager/device_manager.cpp", + "${data_service_path}/adapter/communicator/test/mock/softbus/data_level.cpp", + "${data_service_path}/adapter/communicator/test/mock/softbus/inner_socket.cpp", + "${data_service_path}/adapter/communicator/test/mock/softbus/socket.cpp", + "${data_service_path}/adapter/communicator/test/unittest/app_pipe_mgr_service_test.cpp", + ] external_deps = [ + "access_token:libaccesstoken_sdk", "c_utils:utils", - "device_manager:devicemanagersdk", - "dsoftbus:softbus_client", - "googletest:gtest_main", "hilog:libhilog", - "kv_store:distributeddata_inner", - "kv_store:distributeddb", + "json:nlohmann_json_static", + "kv_store:datamgr_common", ] cflags = [ "-Dprivate=public", "-Dprotected=public", ] deps = [ - "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } 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 cc55d56d702a143fab0574016e5261455a4ff86f..b3c1e72797f90adad5c737f907a0601ae34be7a2 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 @@ -35,14 +35,27 @@ ohos_fuzztest("SoftBusAdapterFuzzTest") { "-fno-omit-frame-pointer", ] - sources = [ "softbusadapter_fuzzer.cpp" ] + sources = [ + "${data_service_path}/adapter/communicator/src/communicator_context.cpp", + "${data_service_path}/adapter/communicator/src/device_manager_adapter.cpp", + "${data_service_path}/adapter/communicator/src/softbus_client.cpp", + "softbusadapter_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/adapter/utils:distributeddata_utils", + "${data_service_path}/framework:distributeddatasvcfwk", + ] external_deps = [ + "access_token:libaccesstoken_sdk", "c_utils:utils", "datamgr_service:distributeddatasvcfwk", "device_manager:devicemanagersdk", "dsoftbus:softbus_client", "hilog:libhilog", + "ipc:ipc_single", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddb", ] diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/softbusadapter_fuzzer.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/softbusadapter_fuzzer.cpp index 6420589afdd61e62bb47defb6645247b673118b4..03e0db5714d2844ec11dea029cb0d897f7c8bc1d 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/softbusadapter_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/softbusadapter_fuzzer.cpp @@ -13,23 +13,26 @@ * limitations under the License. */ +#include + #include "softbusadapter_fuzzer.h" #include #include -#include "softbus_adapter_standard.cpp" #include "message_parcel.h" #include "securec.h" +#include "softbus_adapter_standard.cpp" using namespace OHOS::AppDistributedKv; namespace OHOS { -bool OnBytesReceivedFuzz(const uint8_t *data, size_t size) +bool OnBytesReceivedFuzz(FuzzedDataProvider &provider) { - int connId = static_cast(*data); - unsigned int dataLen = static_cast(size); - AppDataListenerWrap::OnClientBytesReceived(connId, data, dataLen); + int connId = provider.ConsumeIntegral(); + std::vector remainingData = provider.ConsumeRemainingBytes(); + AppDataListenerWrap::OnClientBytesReceived(connId, static_cast(remainingData.data()), + remainingData.size()); return true; } } // namespace OHOS @@ -37,11 +40,7 @@ bool OnBytesReceivedFuzz(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::OnBytesReceivedFuzz(data, size); - + FuzzedDataProvider provider(data, size); + OHOS::OnBytesReceivedFuzz(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0e6a938fa8e7a5b137786809ff0f681ccb572082 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2025 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 "device_manager.h" + +#include "securec.h" + +namespace OHOS::DistributedHardware { +static constexpr const char *LOCAL_DEVICE_NAME = "local_device_name"; +static constexpr const char *LOCAL_NETWORK_ID = "local_network_id"; +static constexpr const char *LOCAL_UUID = "local_uuid"; +static constexpr const char *LOCAL_UDID = "local_udid"; +static constexpr const char *REMOTE_DEVICE_NAME = "remote_device_name"; +static constexpr const char *REMOTE_NETWORK_ID = "remote_network_id"; +static constexpr const char *REMOTE_UUID = "remote_uuid"; +static constexpr const char *REMOTE_UDID = "remote_udid"; + +DeviceManager &DeviceManager::GetInstance() +{ + static DeviceManager dmManager; + return dmManager; +} + +int32_t DeviceManager::InitDeviceManager(const std::string &pkgName, std::shared_ptr dmInitCallback) +{ + (void)pkgName; + (void)dmInitCallback; + return 0; +} + +int32_t DeviceManager::RegisterDevStateCallback(const std::string &pkgName, const std::string &extra, + std::shared_ptr callback) +{ + (void)pkgName; + (void)extra; + (void)callback; + return 0; +} + +int32_t DeviceManager::NotifyEvent(const std::string &pkgName, const int32_t eventId, const std::string &event) +{ + (void)pkgName; + (void)eventId; + (void)event; + return 0; +} + +int32_t DeviceManager::GetTrustedDeviceList(const std::string &pkgName, const std::string &extra, + std::vector &deviceList) +{ + (void)pkgName; + (void)extra; + DeviceExtraInfo extraInfo; + DmDeviceInfo remoteDeviceInfo = { .extraData = DistributedData::Serializable::Marshall(extraInfo) }; + (void)strcpy_s(remoteDeviceInfo.deviceName, DM_MAX_DEVICE_ID_LEN, REMOTE_DEVICE_NAME); + (void)strcpy_s(remoteDeviceInfo.networkId, DM_MAX_DEVICE_ID_LEN, REMOTE_NETWORK_ID); + deviceList.emplace_back(std::move(remoteDeviceInfo)); + return 0; +} + +int32_t DeviceManager::GetLocalDeviceInfo(const std::string &pkgName, DmDeviceInfo &deviceInfo) +{ + (void)pkgName; + (void)strcpy_s(deviceInfo.deviceName, DM_MAX_DEVICE_ID_LEN, LOCAL_DEVICE_NAME); + (void)strcpy_s(deviceInfo.networkId, DM_MAX_DEVICE_ID_LEN, LOCAL_NETWORK_ID); + DeviceExtraInfo extraInfo; + deviceInfo.extraData = DistributedData::Serializable::Marshall(extraInfo); + return 0; +} + +int32_t DeviceManager::GetUuidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &uuid) +{ + (void)pkgName; + if (networkId == LOCAL_NETWORK_ID) { + uuid = LOCAL_UUID; + } + if (networkId == REMOTE_NETWORK_ID) { + uuid = REMOTE_UUID; + } + return 0; +} + +int32_t DeviceManager::GetUdidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &udid) +{ + (void)pkgName; + if (networkId == LOCAL_NETWORK_ID) { + udid = LOCAL_UDID; + } + if (networkId == REMOTE_NETWORK_ID) { + udid = REMOTE_UDID; + } + return 0; +} + +int32_t DeviceManager::GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, + const std::string &appId, std::string &encryptedUuid) +{ + (void)pkgName; + (void)uuid; + (void)appId; + (void)encryptedUuid; + return 0; +} + +int32_t DeviceManager::GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, + std::string &uuid) +{ + (void)pkgName; + (void)networkId; + (void)uuid; + return 0; +} + +bool DeviceManager::IsSameAccount(const std::string &networkId) +{ + (void)networkId; + return true; +} + +bool DeviceManager::CheckAccessControl(const DmAccessCaller &caller, const DmAccessCallee &callee) +{ + (void)caller; + (void)callee; + return true; +} + +bool DeviceManager::CheckIsSameAccount(const DmAccessCaller &caller, const DmAccessCallee &callee) +{ + (void)caller; + (void)callee; + return true; +} +} // namespace OHOS::DistributedHardware \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager.h b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..63840264d14e50ceed54ca6f7163df20acf375d9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 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 MOCK_DEVICE_MANAGER_H +#define MOCK_DEVICE_MANAGER_H + +#include + +#include "device_manager_callback.h" +#include "dm_device_info.h" + +namespace OHOS::DistributedHardware { +class DeviceManager { +public: + static DeviceManager &GetInstance(); + + int32_t InitDeviceManager(const std::string &pkgName, std::shared_ptr dmInitCallback); + int32_t RegisterDevStateCallback(const std::string &pkgName, const std::string &extra, + std::shared_ptr callback); + int32_t NotifyEvent(const std::string &pkgName, const int32_t eventId, const std::string &event); + int32_t GetTrustedDeviceList(const std::string &pkgName, const std::string &extra, + std::vector &deviceList); + int32_t GetLocalDeviceInfo(const std::string &pkgName, DmDeviceInfo &deviceInfo); + int32_t GetUuidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &uuid); + int32_t GetUdidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &udid); + int32_t GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, const std::string &appId, + std::string &encryptedUuid); + int32_t GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &uuid); + bool IsSameAccount(const std::string &networkId); + bool CheckAccessControl(const DmAccessCaller &caller, const DmAccessCallee &callee); + bool CheckIsSameAccount(const DmAccessCaller &caller, const DmAccessCallee &callee); + +private: + DeviceManager() = default; + ~DeviceManager() = default; +}; +} // namespace OHOS::DistributedHardware +#endif // MOCK_DEVICE_MANAGER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager_callback.h b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager_callback.h new file mode 100644 index 0000000000000000000000000000000000000000..2ba425aebd2677e22fa175aa9398d1ece5a913c6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager_callback.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 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 MOCK_DEVICE_MANAGER_CALLBACK_H +#define MOCK_DEVICE_MANAGER_CALLBACK_H + +#include "dm_device_info.h" + +namespace OHOS::DistributedHardware { +class DmInitCallback { +public: + virtual ~DmInitCallback() {} + virtual void OnRemoteDied() = 0; +}; + +class DeviceStateCallback { +public: + virtual ~DeviceStateCallback() {} + virtual void OnDeviceOnline(const DmDeviceInfo &deviceInfo) = 0; + virtual void OnDeviceOffline(const DmDeviceInfo &deviceInfo) = 0; + virtual void OnDeviceChanged(const DmDeviceInfo &deviceInfo) = 0; + virtual void OnDeviceReady(const DmDeviceInfo &deviceInfo) = 0; +}; +} // namespace OHOS::DistributedHardware +#endif // MOCK_DEVICE_MANAGER_CALLBACK_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/dm_device_info.h b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/dm_device_info.h new file mode 100644 index 0000000000000000000000000000000000000000..ad9a9de9becce9446b2f4188c14e8ef8688f462a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/dm_device_info.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2025 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 MOCK_DM_DEVICE_INFO_H +#define MOCK_DM_DEVICE_INFO_H + +#include "serializable/serializable.h" + +#define DM_MAX_DEVICE_ID_LEN (97) + +namespace OHOS::DistributedHardware { +struct DeviceExtraInfo final : public DistributedData::Serializable { + static constexpr int32_t OH_OS_TYPE = 10; + + int32_t OS_TYPE = OH_OS_TYPE; + + DeviceExtraInfo() {}; + ~DeviceExtraInfo() {}; + bool Marshal(json &node) const override + { + return SetValue(node[GET_NAME(OS_TYPE)], OS_TYPE); + }; + bool Unmarshal(const json &node) override + { + return GetValue(node, GET_NAME(OS_TYPE), OS_TYPE); + }; +}; + +struct DmDeviceInfo { + char deviceId[DM_MAX_DEVICE_ID_LEN] = {0}; + char deviceName[DM_MAX_DEVICE_ID_LEN] = {0}; + uint16_t deviceTypeId; + char networkId[DM_MAX_DEVICE_ID_LEN] = {0}; + int32_t range; + int32_t networkType; + int32_t authForm; + std::string extraData; +}; + +struct DmAccessCaller { + std::string accountId; + std::string pkgName; + std::string networkId; + int32_t userId; + uint64_t tokenId = 0; + std::string extra; +}; + +struct DmAccessCallee { + std::string accountId; + std::string networkId; + std::string peerId; + std::string pkgName; + int32_t userId; + uint64_t tokenId = 0; + std::string extra; +}; + +enum DmNotifyEvent { + DM_NOTIFY_EVENT_ONDEVICEREADY, +}; +} // namespace OHOS::DistributedHardware +#endif // MOCK_DM_DEVICE_INFO_H \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/transfergrdtypetocoltype_fuzzer.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/data_level.cpp similarity index 43% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/transfergrdtypetocoltype_fuzzer.cpp rename to datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/data_level.cpp index 5fc3b633b35861a1cec0681d991da1a097dbfd78..c621b08bcc46694ab6af9f721007ba73c700e143 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/transfergrdtypetocoltype_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/data_level.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2025 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,34 +13,36 @@ * limitations under the License. */ -#include "rdb_store_config.h" -#include "rdb_errno.h" -#include "rdb_store_impl.h" -#include "rd_utils.h" -using namespace OHOS; -using namespace OHOS::NativeRdb; -namespace OHOS { +#include "data_level.h" -uint32_t ConvertToUint32(const uint8_t *ptr, size_t size) +static constexpr const char *REMOTE_NETWORK_ID = "remote_network_id"; + +SoftBusErrNo errCode_; +IDataLevelCb *callback_ = nullptr; + +void ConfigReturnCode(SoftBusErrNo errorCode) { - if (ptr == nullptr || (size < sizeof(uint32_t))) { - return 0; - } - return *(reinterpret_cast(ptr)); + errCode_ = errorCode; } -void transferGrdTypeToColTypeFuzzer(const uint8_t *data, size_t size) +int32_t RegDataLevelChangeCb(const char *pkgName, IDataLevelCb *callback) { - int err = ConvertToUint32(data, size); - RdUtils::TransferGrdTypeToColType(err); -} + (void)pkgName; + callback_ = callback; + return errCode_; } -/* Fuzzer entry point */ -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +int32_t UnregDataLevelChangeCb(const char *pkgName) { - /* Run your code on data */ - OHOS::transferGrdTypeToColTypeFuzzer(data, size); - return 0; + (void)pkgName; + callback_ = nullptr; + return SoftBusErrNo::SOFTBUS_OK; } +int32_t SetDataLevel(const DataLevel *dataLevel) +{ + if (errCode_ == SoftBusErrNo::SOFTBUS_OK && callback_ != nullptr) { + callback_->onDataLevelChanged(REMOTE_NETWORK_ID, *dataLevel); + } + return errCode_; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/data_level.h b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/data_level.h new file mode 100644 index 0000000000000000000000000000000000000000..fdd246507c5275458ba82c469978f2b679de7d6e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/data_level.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025 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 MOCK_SOFTBUS_DATA_LEVEL_H +#define MOCK_SOFTBUS_DATA_LEVEL_H + +#include + +#include "softbus_error_code.h" + +struct DataLevel { + uint16_t dynamicLevel; + uint16_t staticLevel; + uint32_t switchLevel; + uint16_t switchLength; +}; + +struct IDataLevelCb { + void (*onDataLevelChanged)(const char *networkId, const DataLevel dataLevel); +}; + +void ConfigReturnCode(SoftBusErrNo errorCode); + +int32_t RegDataLevelChangeCb(const char *pkgName, IDataLevelCb *callback); + +int32_t UnregDataLevelChangeCb(const char *pkgName); + +int32_t SetDataLevel(const DataLevel *dataLevel); + +#endif // MOCK_SOFTBUS_DATA_LEVEL_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/inner_socket.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/inner_socket.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a2bc12a6d4af75258ffeefd04d9e182d7582f1a3 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/inner_socket.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 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 "inner_socket.h" + +#include "socket.h" + +static constexpr uint32_t MTU_SIZE = 4 * 1024u; + +int32_t GetMtuSize(int32_t socket, uint32_t *mtuSize) +{ + if (socket <= INVALID_MTU_SOCKET) { + return -1; + } + *mtuSize = MTU_SIZE; + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/inner_socket.h b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/inner_socket.h new file mode 100644 index 0000000000000000000000000000000000000000..5db024db30d14ec5dca4ffe97fd1fb194915d2d7 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/inner_socket.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 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 MOCK_SOFTBUS_INNER_SESSION_SOCKET_H +#define MOCK_SOFTBUS_INNER_SESSION_SOCKET_H + +#include + +int32_t GetMtuSize(int32_t socket, uint32_t *mtuSize); + +#endif // MOCK_SOFTBUS_INNER_SESSION_SOCKET_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/socket.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/socket.cpp new file mode 100644 index 0000000000000000000000000000000000000000..02ddf200d247244ef7d52781ec3a8110f1f31f5d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/socket.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2025 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 "socket.h" + +#include "securec.h" +#include "softbus_error_code.h" + +static constexpr uint32_t EXTRA_INFO_LENGTH = 100; +static constexpr const char *SOCKET_NAME = "socket_test"; +static constexpr const char *PKG_NAME = "ddms_test"; +static constexpr const char *REMOTE_NETWORK_ID = "remote_network_id"; + +int32_t socketId_ = DEFAULT_SOCKET; +ISocketListener *clientListener_ = nullptr; +ISocketListener *serverListener_ = nullptr; +SocketAccessInfo accessInfo_; + +void ConfigSocketId(int32_t socketId) +{ + socketId_ = socketId; +} + +int32_t Socket(SocketInfo info) +{ + (void)info; + return socketId_; +} + +int32_t SetAccessInfo(int32_t socket, SocketAccessInfo accessInfo) +{ + if (socket == INVALID_SET_SOCKET) { + return SoftBusErrNo::SOFTBUS_ERROR; + } + accessInfo_.userId = accessInfo.userId; + accessInfo_.localTokenId = accessInfo.localTokenId; + accessInfo_.extraAccessInfo = new char[EXTRA_INFO_LENGTH]; + (void)strcpy_s(accessInfo_.extraAccessInfo, EXTRA_INFO_LENGTH, accessInfo.extraAccessInfo); + return SoftBusErrNo::SOFTBUS_OK; +} + +int32_t Bind(int32_t socket, const QosTV qos[], uint32_t qosCount, const ISocketListener *listener) +{ + (void)qos; + (void)qosCount; + if (socket <= INVALID_BIND_SOCKET) { + return SoftBusErrNo::SOFTBUS_ERROR; + } + if (serverListener_ != nullptr) { + PeerSocketInfo info; + info.name = const_cast(SOCKET_NAME); + info.pkgName = const_cast(PKG_NAME); + info.networkId = const_cast(REMOTE_NETWORK_ID); + SocketAccessInfo localInfo; + if (!serverListener_->OnNegotiate2(socket, info, &accessInfo_, &localInfo)) { + return SoftBusErrNo::SOFTBUS_ERROR; + } + serverListener_->OnBind(socket, info); + } + clientListener_ = const_cast(listener); + return SoftBusErrNo::SOFTBUS_OK; +} + +void Shutdown(int32_t socket) +{ + if (socket <= INVALID_MTU_SOCKET) { + return; + } + ShutdownReason reason = ShutdownReason::UN_KNOWN; + if (clientListener_ != nullptr && clientListener_->OnShutdown != nullptr) { + clientListener_->OnShutdown(socket, reason); + } + if (serverListener_ != nullptr && serverListener_->OnShutdown != nullptr) { + serverListener_->OnShutdown(socket, reason); + } +} + +int32_t SendBytes(int32_t socket, const void *data, uint32_t len) +{ + if (socket <= INVALID_SEND_SOCKET) { + return SoftBusErrNo::SOFTBUS_ERROR; + } + if (clientListener_ == nullptr) { + return SoftBusErrNo::SOFTBUS_OK; + } + if (clientListener_->OnBytes != nullptr) { + clientListener_->OnBytes(socket, data, len); + } + if (clientListener_->OnMessage != nullptr) { + clientListener_->OnMessage(socket, data, len); + } + return SoftBusErrNo::SOFTBUS_OK; +} + +int32_t Listen(int32_t socket, const QosTV qos[], uint32_t qosCount, const ISocketListener *listener) +{ + (void)qos; + (void)qosCount; + if (socket < VALID_SOCKET) { + return SoftBusErrNo::SOFTBUS_ERROR; + } + serverListener_ = const_cast(listener); + return SoftBusErrNo::SOFTBUS_OK; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/socket.h b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/socket.h new file mode 100644 index 0000000000000000000000000000000000000000..03efd188641c611d4aeed5a601d7be247ec4c778 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/socket.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2025 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 MOCK_SOFTBUS_SESSION_SOCKET_H +#define MOCK_SOFTBUS_SESSION_SOCKET_H + +#include + +enum TransDataType { + DATA_TYPE_BYTES, +}; + +enum ShutdownReason { + UN_KNOWN, +}; + +enum QoSEvent { + QOS_SATISFIED, + QOS_NOT_SATISFIED, +}; + +enum QosType { + QOS_TYPE_MIN_BW, + QOS_TYPE_MAX_LATENCY, + QOS_TYPE_MIN_LATENCY, + QOS_TYPE_REUSE_BE, +}; + +struct QosTV { + QosType qos; + int32_t value; +}; + +struct PeerSocketInfo { + char *name; + char *networkId; + char *pkgName; + TransDataType dataType = TransDataType::DATA_TYPE_BYTES; +}; + +struct SocketInfo { + char *name; + char *peerName; + char *peerNetworkId; + char *pkgName; + TransDataType dataType; +}; + +struct SocketAccessInfo { + int32_t userId; + uint64_t localTokenId; + char *businessAccountId; + char *extraAccessInfo; +}; + +struct ISocketListener { + void (*OnBind)(int32_t socket, PeerSocketInfo info); + void (*OnShutdown)(int32_t socket, ShutdownReason reason); + void (*OnBytes)(int32_t socket, const void *data, uint32_t dataLen); + void (*OnMessage)(int32_t socket, const void *data, uint32_t dataLen); + void (*OnQos)(int32_t socket, QoSEvent eventId, const QosTV *qos, uint32_t qosCount); + bool (*OnNegotiate2)(int32_t socket, PeerSocketInfo info, SocketAccessInfo *peerInfo, SocketAccessInfo *localInfo); +}; + +static constexpr int32_t DEFAULT_SOCKET = -1; +static constexpr int32_t INVALID_SOCKET = 0; +static constexpr int32_t INVALID_SET_SOCKET = 1; +static constexpr int32_t INVALID_BIND_SOCKET = 2; +static constexpr int32_t INVALID_MTU_SOCKET = 3; +static constexpr int32_t INVALID_SEND_SOCKET = 4; +static constexpr int32_t VALID_SOCKET = 5; + +void ConfigSocketId(int32_t socketId); + +int32_t Socket(SocketInfo info); + +int32_t Listen(int32_t socket, const QosTV qos[], uint32_t qosCount, const ISocketListener *listener); + +int32_t SetAccessInfo(int32_t socket, SocketAccessInfo accessInfo); + +int32_t Bind(int32_t socket, const QosTV qos[], uint32_t qosCount, const ISocketListener *listener); + +void Shutdown(int32_t socket); + +int32_t SendBytes(int32_t socket, const void *data, uint32_t len); +#endif // MOCK_SOFTBUS_SESSION_SOCKET_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/softbus_error_code.h b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/softbus_error_code.h new file mode 100644 index 0000000000000000000000000000000000000000..7925f943854f804e07abf1903fc7b3e79298d380 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/softbus_error_code.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 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 MOCK_SOFTBUS_ERROR_CODE_H +#define MOCK_SOFTBUS_ERROR_CODE_H + +enum SoftBusErrNo { + SOFTBUS_OK = 0, + SOFTBUS_ERROR = 1, + SOFTBUS_FUNC_NOT_SUPPORT = 2, + SOFTBUS_ALREADY_EXISTED = 3, +}; +#endif // MOCK_SOFTBUS_ERROR_CODE_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/app_pipe_mgr_service_test.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/app_pipe_mgr_service_test.cpp index f9ebce1af44231ce74ead67f6ac13048e6de2f9b..97b3c6a34e1396b9cb001a674d2c1e7436134d0a 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/app_pipe_mgr_service_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/app_pipe_mgr_service_test.cpp @@ -12,26 +12,47 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define LOG_TAG "AppPipeMgrServiceTest" #include "app_pipe_mgr.h" -#include "kvstore_utils.h" -#include "log_print.h" -#include "dfx/reporter.h" -#include "types.h" + #include +#include "socket.h" + namespace OHOS::Test { using namespace testing::ext; using namespace OHOS::AppDistributedKv; + +static constexpr int32_t DEFAULT_SOCKET = -1; +static constexpr int32_t INVALID_SOCKET = 0; +static constexpr int32_t INVALID_SET_SOCKET = 1; +static constexpr int32_t INVALID_BIND_SOCKET = 2; +static constexpr int32_t INVALID_MTU_SOCKET = 3; +static constexpr int32_t INVALID_SEND_SOCKET = 4; +static constexpr int32_t VALID_SOCKET = 5; +static constexpr uint32_t INVALID_TRANSFER_SIZE = 5 * 1024 * 1024; +static constexpr uint32_t VALID_TRANSFER_SIZE = 1024; +static constexpr uint32_t DATA_LENGTH = 8; +static constexpr uint32_t TOKEN_ID = 1111; +static constexpr const char *PIPE_ID = "AppPipeMgrServiceTest"; +static constexpr const char *DEVICE_ID = "deviceId"; +static constexpr const char *DATA_INFO = "DataInfo"; +static constexpr const char *USER_ID = "100"; +static constexpr const char *BUNDLE_NAME = "bundleName"; +static constexpr const char *STORE_ID = "storeId"; + class AppDataChangeListenerMock : public AppDataChangeListener { void OnMessage(const DeviceInfo &info, const uint8_t *ptr, const int size, - const struct PipeInfo &id) const override; + const struct PipeInfo &id) const override; }; void AppDataChangeListenerMock::OnMessage(const DeviceInfo &info, const uint8_t *ptr, const int size, const struct PipeInfo &id) const { + (void)info; + (void)ptr; + (void)size; + (void)id; return; } @@ -40,251 +61,312 @@ public: static void SetUpTestCase(void) {}; static void TearDownTestCase(void) {}; void SetUp() {}; - void TearDown() {}; + void TearDown(); + + static PipeInfo pipeInfo_; + static DeviceId deviceId_; + static DataInfo dataInfo_; + static MessageInfo msgInfo_; + static ExtraDataInfo extraInfo_; }; -/** -* @tc.name: StopWatchDataChange001 -* @tc.desc: StopWatchDataChange test -* @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, StopWatchDataChange001, TestSize.Level0) +PipeInfo AppPipeMgrServiceTest::pipeInfo_; +DeviceId AppPipeMgrServiceTest::deviceId_; +DataInfo AppPipeMgrServiceTest::dataInfo_; +MessageInfo AppPipeMgrServiceTest::msgInfo_; +ExtraDataInfo AppPipeMgrServiceTest::extraInfo_; + +void AppPipeMgrServiceTest::TearDown() { - AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - const AppDataChangeListener* observer = nullptr; - auto status = appPipeMgr.StopWatchDataChange(observer, pipeInfo); - EXPECT_EQ(Status::INVALID_ARGUMENT, status); - - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - status = appPipeMgr.StopWatchDataChange(observer, pipeInfo); - EXPECT_EQ(Status::INVALID_ARGUMENT, status); - - PipeInfo pipeInfoNull; - const AppDataChangeListener* observerListener = new AppDataChangeListenerMock(); - status = appPipeMgr.StopWatchDataChange(observerListener, pipeInfoNull); - EXPECT_EQ(Status::INVALID_ARGUMENT, status); + pipeInfo_.pipeId = ""; + deviceId_.deviceId = ""; + dataInfo_.length = 0; + dataInfo_.data = nullptr; + extraInfo_.userId = ""; + extraInfo_.bundleName = ""; + extraInfo_.storeId = ""; + dataInfo_.extraInfo = extraInfo_; } /** -* @tc.name: StopWatchDataChange002 -* @tc.desc: StopWatchDataChange test +* @tc.name: StartWatchDataChangeTest001 +* @tc.desc: StartWatchDataChange test * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, StopWatchDataChange002, TestSize.Level0) +*/ +HWTEST_F(AppPipeMgrServiceTest, StartWatchDataChangeTest001, TestSize.Level0) { AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - const AppDataChangeListener* observer = new AppDataChangeListenerMock(); - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - auto status = appPipeMgr.StopWatchDataChange(observer, pipeInfo); - EXPECT_EQ(Status::ERROR, status); - - auto handler = std::make_shared(pipeInfo); - std::map> dataBusMap = {{"pipeId", handler}}; - appPipeMgr.dataBusMap_ = dataBusMap; - status = appPipeMgr.StopWatchDataChange(observer, pipeInfo); - EXPECT_EQ(Status::ERROR, status); + auto status = appPipeMgr.StartWatchDataChange(nullptr, pipeInfo_); + ASSERT_EQ(status, Status::INVALID_ARGUMENT); + + AppDataChangeListenerMock* dataChangeListener = new AppDataChangeListenerMock(); + status = appPipeMgr.StartWatchDataChange(dataChangeListener, pipeInfo_); + ASSERT_EQ(status, Status::INVALID_ARGUMENT); + + pipeInfo_.pipeId = PIPE_ID; + status = appPipeMgr.StartWatchDataChange(dataChangeListener, pipeInfo_); + ASSERT_EQ(status, Status::ERROR); + + appPipeMgr.dataBusMap_.insert({ PIPE_ID, nullptr }); + status = appPipeMgr.StartWatchDataChange(dataChangeListener, pipeInfo_); + ASSERT_EQ(status, Status::ERROR); + + appPipeMgr.dataBusMap_.erase(PIPE_ID); + appPipeMgr.dataBusMap_.insert({ PIPE_ID, std::make_shared(pipeInfo_) }); + status = appPipeMgr.StartWatchDataChange(dataChangeListener, pipeInfo_); + ASSERT_EQ(status, Status::SUCCESS); + + delete dataChangeListener; } /** -* @tc.name: SendData001 -* @tc.desc: SendData test +* @tc.name: StopWatchDataChangeTest001 +* @tc.desc: StopWatchDataChange test * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, SendData001, TestSize.Level0) +*/ +HWTEST_F(AppPipeMgrServiceTest, StopWatchDataChangeTest001, TestSize.Level0) { AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - DeviceId deviceId = {"deviceId"}; - std::string content = "Helloworlds"; - const uint8_t *t = reinterpret_cast(content.c_str()); - DataInfo dataInfo = { const_cast(t), static_cast(content.length())}; - uint32_t totalLength = 0; - MessageInfo info; - auto handler = std::make_shared(pipeInfo); - std::map> dataBusMap = {{"pipeId", handler}}; - appPipeMgr.dataBusMap_ = dataBusMap; - auto status = appPipeMgr.SendData(pipeInfo, deviceId, dataInfo, totalLength, info); - EXPECT_EQ(std::make_pair(Status::RATE_LIMIT, 0), status); + auto status = appPipeMgr.StopWatchDataChange(nullptr, pipeInfo_); + ASSERT_EQ(status, Status::INVALID_ARGUMENT); + + AppDataChangeListenerMock* dataChangeListener = new AppDataChangeListenerMock(); + status = appPipeMgr.StopWatchDataChange(dataChangeListener, pipeInfo_); + ASSERT_EQ(status, Status::INVALID_ARGUMENT); + + pipeInfo_.pipeId = PIPE_ID; + status = appPipeMgr.StopWatchDataChange(dataChangeListener, pipeInfo_); + ASSERT_EQ(status, Status::ERROR); + + appPipeMgr.dataBusMap_.insert({ PIPE_ID, nullptr }); + status = appPipeMgr.StopWatchDataChange(dataChangeListener, pipeInfo_); + ASSERT_EQ(status, Status::ERROR); + + appPipeMgr.dataBusMap_.erase(PIPE_ID); + appPipeMgr.dataBusMap_.insert({ PIPE_ID, std::make_shared(pipeInfo_) }); + status = appPipeMgr.StopWatchDataChange(dataChangeListener, pipeInfo_); + ASSERT_EQ(status, Status::SUCCESS); + + delete dataChangeListener; } /** -* @tc.name: Start001 -* @tc.desc: Start test +* @tc.name: IsSameStartedOnPeerTest001 +* @tc.desc: IsSameStartedOnPeer test * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, Start001, TestSize.Level0) +*/ +HWTEST_F(AppPipeMgrServiceTest, IsSameStartedOnPeerTest001, TestSize.Level0) { AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - auto handler = std::make_shared(pipeInfo); - std::map> dataBusMap = {{"pipeId", handler}}; - appPipeMgr.dataBusMap_ = dataBusMap; - auto status = appPipeMgr.Start(pipeInfo); - EXPECT_EQ(Status::SUCCESS, status); + auto result = appPipeMgr.IsSameStartedOnPeer(pipeInfo_, deviceId_); + appPipeMgr.SetMessageTransFlag(pipeInfo_, true); + ASSERT_FALSE(result); + + pipeInfo_.pipeId = PIPE_ID; + result = appPipeMgr.IsSameStartedOnPeer(pipeInfo_, deviceId_); + ASSERT_FALSE(result); + + deviceId_.deviceId = DEVICE_ID; + result = appPipeMgr.IsSameStartedOnPeer(pipeInfo_, deviceId_); + appPipeMgr.SetMessageTransFlag(pipeInfo_, true); + ASSERT_FALSE(result); + + appPipeMgr.dataBusMap_.insert({ PIPE_ID, nullptr }); + result = appPipeMgr.IsSameStartedOnPeer(pipeInfo_, deviceId_); + appPipeMgr.SetMessageTransFlag(pipeInfo_, true); + ASSERT_FALSE(result); + + appPipeMgr.dataBusMap_.erase(PIPE_ID); + appPipeMgr.dataBusMap_.insert({ PIPE_ID, std::make_shared(pipeInfo_) }); + result = appPipeMgr.IsSameStartedOnPeer(pipeInfo_, deviceId_); + appPipeMgr.SetMessageTransFlag(pipeInfo_, true); + ASSERT_TRUE(result); } /** -* @tc.name: Stop001 -* @tc.desc: Stop test +* @tc.name: StartTest001 +* @tc.desc: test start function with all branch * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, Stop001, TestSize.Level0) -{ - AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - auto status = appPipeMgr.Stop(pipeInfo); - EXPECT_EQ(Status::KEY_NOT_FOUND, status); - - auto handler = std::make_shared(pipeInfo); - std::map> dataBusMap = {{"pipeId", handler}}; - appPipeMgr.dataBusMap_ = dataBusMap; - status = appPipeMgr.Stop(pipeInfo); - EXPECT_EQ(Status::SUCCESS, status); -} +*/ +//HWTEST_F(AppPipeMgrServiceTest, StartTest001, TestSize.Level0) +//{ +// AppPipeMgr appPipeMgr; +// auto status = appPipeMgr.Start(pipeInfo_); +// ASSERT_EQ(status, Status::INVALID_ARGUMENT); +// +// pipeInfo_.pipeId = PIPE_ID; +// ConfigSocketId(INVALID_SOCKET); +// status = appPipeMgr.Start(pipeInfo_); +// ASSERT_EQ(status, Status::ILLEGAL_STATE); +// +// ConfigSocketId(VALID_SOCKET); +// status = appPipeMgr.Start(pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +// +// status = appPipeMgr.Start(pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +//} /** -* @tc.name: IsSameStartedOnPeer001 -* @tc.desc: IsSameStartedOnPeer test +* @tc.name: StopTest001 +* @tc.desc: test stop function with all branch * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, IsSameStartedOnPeer001, TestSize.Level0) -{ - AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - DeviceId deviceId; - auto status = appPipeMgr.IsSameStartedOnPeer(pipeInfo, deviceId); - EXPECT_EQ(false, status); - - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - status = appPipeMgr.IsSameStartedOnPeer(pipeInfo, deviceId); - EXPECT_EQ(false, status); - - PipeInfo pipeInfoNull; - deviceId.deviceId = "deviceId"; - status = appPipeMgr.IsSameStartedOnPeer(pipeInfoNull, deviceId); - EXPECT_EQ(false, status); -} +*/ +//HWTEST_F(AppPipeMgrServiceTest, StopTest001, TestSize.Level0) +//{ +// AppPipeMgr appPipeMgr; +// pipeInfo_.pipeId = PIPE_ID; +// auto status = appPipeMgr.Stop(pipeInfo_); +// ASSERT_EQ(status, Status::KEY_NOT_FOUND); +// +// ConfigSocketId(VALID_SOCKET); +// status = appPipeMgr.Start(pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +// +// status = appPipeMgr.Stop(pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +//} /** -* @tc.name: IsSameStartedOnPeer002 -* @tc.desc: IsSameStartedOnPeer test +* @tc.name: SendDataTest001 +* @tc.desc: send data fail with all exception branch * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, IsSameStartedOnPeer002, TestSize.Level0) +*/ +HWTEST_F(AppPipeMgrServiceTest, SendDataTest001, TestSize.Level0) { AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - DeviceId deviceId; - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - deviceId.deviceId = "deviceId"; - auto status = appPipeMgr.IsSameStartedOnPeer(pipeInfo, deviceId); - EXPECT_EQ(false, status); - - auto handler = std::make_shared(pipeInfo); - std::map> dataBusMap = {{"pipeId", handler}}; - appPipeMgr.dataBusMap_ = dataBusMap; - status = appPipeMgr.IsSameStartedOnPeer(pipeInfo, deviceId); - EXPECT_EQ(true, status); + auto result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + pipeInfo_.pipeId = PIPE_ID; + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + deviceId_.deviceId = DEVICE_ID; + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + dataInfo_.length = 0; + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + dataInfo_.length = INVALID_TRANSFER_SIZE; + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + dataInfo_.length = VALID_TRANSFER_SIZE; + dataInfo_.data = nullptr; + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + dataInfo_.length = DATA_LENGTH; + dataInfo_.data = const_cast(reinterpret_cast(DATA_INFO)); + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + extraInfo_.userId = USER_ID; + dataInfo_.extraInfo = extraInfo_; + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + extraInfo_.appId = BUNDLE_NAME; + dataInfo_.extraInfo = extraInfo_; + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + extraInfo_.storeId = STORE_ID; + dataInfo_.extraInfo = extraInfo_; + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::KEY_NOT_FOUND); } /** -* @tc.name: SetMessageTransFlag001 -* @tc.desc: SetMessageTransFlag test +* @tc.name: SendDataTest002 +* @tc.desc: send data trigger success * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, SetMessageTransFlag001, TestSize.Level0) -{ - AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - bool flag = true; - EXPECT_NO_FATAL_FAILURE( - appPipeMgr.SetMessageTransFlag(pipeInfo, flag)); - - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - auto handler = std::make_shared(pipeInfo); - std::map> dataBusMap = {{"pipeId", handler}}; - appPipeMgr.dataBusMap_ = dataBusMap; - EXPECT_NO_FATAL_FAILURE( - appPipeMgr.SetMessageTransFlag(pipeInfo, flag)); -} +*/ +//HWTEST_F(AppPipeMgrServiceTest, SendDataTest002, TestSize.Level0) +//{ +// AppPipeMgr appPipeMgr; +// pipeInfo_.pipeId = PIPE_ID; +// +// ConfigSocketId(VALID_SOCKET); +// auto status = appPipeMgr.Start(pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +// +// deviceId_.deviceId = DEVICE_ID; +// dataInfo_.length = DATA_LENGTH; +// dataInfo_.data = const_cast(reinterpret_cast(DATA_INFO)); +// extraInfo_.userId = USER_ID; +// extraInfo_.appId = BUNDLE_NAME; +// extraInfo_.storeId = STORE_ID; +// dataInfo_.extraInfo = extraInfo_; +// auto result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::ERROR); +// +// status = appPipeMgr.Stop(pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +//} /** -* @tc.name: ReuseConnect001 -* @tc.desc: ReuseConnect test +* @tc.name: ReuseConnectTest001 +* @tc.desc: reuse connect fail with all exception branch * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, ReuseConnect001, TestSize.Level0) +*/ +HWTEST_F(AppPipeMgrServiceTest, ReuseConnectTest001, TestSize.Level0) { AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - DeviceId deviceId; - auto status = appPipeMgr.ReuseConnect(pipeInfo, deviceId); - EXPECT_EQ(Status::INVALID_ARGUMENT, status); - - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - status = appPipeMgr.ReuseConnect(pipeInfo, deviceId); - EXPECT_EQ(Status::INVALID_ARGUMENT, status); - - PipeInfo pipeInfoNull; - deviceId.deviceId = "deviceId"; - status = appPipeMgr.ReuseConnect(pipeInfoNull, deviceId); - EXPECT_EQ(Status::INVALID_ARGUMENT, status); + auto status = appPipeMgr.ReuseConnect(pipeInfo_, deviceId_, extraInfo_); + ASSERT_EQ(status, Status::INVALID_ARGUMENT); + + pipeInfo_.pipeId = PIPE_ID; + status = appPipeMgr.ReuseConnect(pipeInfo_, deviceId_, extraInfo_); + ASSERT_EQ(status, Status::INVALID_ARGUMENT); + + deviceId_.deviceId = DEVICE_ID; + status = appPipeMgr.ReuseConnect(pipeInfo_, deviceId_, extraInfo_); + ASSERT_EQ(status, Status::ERROR); + + extraInfo_.userId = USER_ID; + status = appPipeMgr.ReuseConnect(pipeInfo_, deviceId_, extraInfo_); + ASSERT_EQ(status, Status::ERROR); + + extraInfo_.bundleName = BUNDLE_NAME; + status = appPipeMgr.ReuseConnect(pipeInfo_, deviceId_, extraInfo_); + ASSERT_EQ(status, Status::ERROR); + + extraInfo_.storeId = STORE_ID; + status = appPipeMgr.ReuseConnect(pipeInfo_, deviceId_, extraInfo_); + ASSERT_EQ(status, Status::ERROR); + + extraInfo_.tokenId = TOKEN_ID; + status = appPipeMgr.ReuseConnect(pipeInfo_, deviceId_, extraInfo_); + ASSERT_EQ(status, Status::KEY_NOT_FOUND); } /** -* @tc.name: ReuseConnect002 -* @tc.desc: ReuseConnect test +* @tc.name: ReuseConnectTest002 +* @tc.desc: reuse connect trigger success * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, ReuseConnect002, TestSize.Level0) -{ - AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - DeviceId deviceId; - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - deviceId.deviceId = "deviceId"; - auto status = appPipeMgr.ReuseConnect(pipeInfo, deviceId); - EXPECT_EQ(Status::INVALID_ARGUMENT, status); - - auto handler = std::make_shared(pipeInfo); - std::map> dataBusMap = {{"pipeId", handler}}; - appPipeMgr.dataBusMap_ = dataBusMap; - status = appPipeMgr.ReuseConnect(pipeInfo, deviceId); - EXPECT_EQ(Status::NOT_SUPPORT, status); -} +*/ +//HWTEST_F(AppPipeMgrServiceTest, ReuseConnectTest002, TestSize.Level0) +//{ +// AppPipeMgr appPipeMgr; +// pipeInfo_.pipeId = PIPE_ID; +// +// ConfigSocketId(VALID_SOCKET); +// auto status = appPipeMgr.Start(pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +// +// deviceId_.deviceId = DEVICE_ID; +// extraInfo_.userId = USER_ID; +// extraInfo_.bundleName = BUNDLE_NAME; +// extraInfo_.storeId = STORE_ID; +// extraInfo_.tokenId = TOKEN_ID; +// status = appPipeMgr.ReuseConnect(pipeInfo_, deviceId_, extraInfo_); +// ASSERT_EQ(status, Status::NOT_SUPPORT); +// +// status = appPipeMgr.Stop(pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +//} } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/device_manager_adapter_test.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/device_manager_adapter_test.cpp index a813fb8a0e8c2cf1c2973583e2ab7f7f913d4fe2..f08d3153b29341fecb6934cd3cd029a1e53cc6bb 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/device_manager_adapter_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/device_manager_adapter_test.cpp @@ -14,6 +14,7 @@ */ #include "device_manager_adapter.h" +#include "device_manager/device_manager_delegate.h" #include "gtest/gtest.h" #include "accesstoken_kit.h" #include "executor_pool.h" @@ -622,4 +623,17 @@ HWTEST_F(DeviceManagerAdapterTest, IsSameAccount01, TestSize.Level0) auto status = DeviceManagerAdapter::GetInstance().IsSameAccount(networkId); EXPECT_EQ(status, false); } + +/** +* @tc.name: RegisterDelegateInstance +* @tc.desc: test DeviceManagerDelegate::RegisterInstance function +* @tc.type: FUNC +*/ +HWTEST_F(DeviceManagerAdapterTest, RegisterDelegateInstance, TestSize.Level0) +{ + DeviceManagerDelegate::RegisterInstance(&DeviceManagerAdapter::GetInstance()); + // Repeated registration + DeviceManagerDelegate::RegisterInstance(&DeviceManagerAdapter::GetInstance()); + EXPECT_NE(nullptr, DeviceManagerDelegate::GetInstance()); +} } // namespace \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/process_communicator_impl_test.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/process_communicator_impl_test.cpp index f5c4cc30cc37bfaf066e57ce6dbbd0408689a40a..cf282fc94edad73fa7920344ad287b5fae6b88c7 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/process_communicator_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/process_communicator_impl_test.cpp @@ -1,506 +1,475 @@ -/* - * Copyright (c) 2025 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 -#include -#include -#include -#include -#include "communication_provider.h" -#include "device_manager_adapter_mock.h" -#include "process_communicator_impl.h" -#include "softbus_adapter.h" -#include "softbus_error_code.h" - -using namespace testing; -using namespace testing::ext; -using namespace OHOS::AppDistributedKv; -using namespace OHOS::DistributedData; -using OnDeviceChange = DistributedDB::OnDeviceChange; -using OnDataReceive = DistributedDB::OnDataReceive; -using OnSendAble = DistributedDB::OnSendAble; -using DeviceInfos = DistributedDB::DeviceInfos; -using DeviceInfoo = OHOS::AppDistributedKv::DeviceInfo; -using UserInfo = DistributedDB::UserInfo; - -namespace OHOS::AppDistributedKv { -class MockCommunicationProvider : public CommunicationProvider { -public: - ~MockCommunicationProvider() = default; - static MockCommunicationProvider& Init() - { - static MockCommunicationProvider instance; - return instance; - } - MOCK_METHOD(Status, StartWatchDataChange, (const AppDataChangeListener *, const PipeInfo &), (override)); - MOCK_METHOD(Status, StopWatchDataChange, (const AppDataChangeListener *, const PipeInfo &), (override)); - MOCK_METHOD(Status, Start, (const PipeInfo&), (override)); - MOCK_METHOD(Status, Stop, (const PipeInfo&), (override)); - MOCK_METHOD((std::pair), SendData, (const PipeInfo&, const DeviceId&, - const DataInfo&, uint32_t, const MessageInfo &), (override)); - MOCK_METHOD(bool, IsSameStartedOnPeer, (const PipeInfo &, const DeviceId &), (const)); - MOCK_METHOD(Status, ReuseConnect, (const PipeInfo&, const DeviceId&), (override)); - MOCK_METHOD(void, SetDeviceQuery, (std::shared_ptr), (override)); - MOCK_METHOD(void, SetMessageTransFlag, (const PipeInfo &, bool), (override)); - MOCK_METHOD(Status, Broadcast, (const PipeInfo &, const LevelInfo &), (override)); - MOCK_METHOD(int32_t, ListenBroadcastMsg, (const PipeInfo &, - std::function), (override)); -}; - -CommunicationProvider& CommunicationProvider::GetInstance() -{ - return MockCommunicationProvider::Init(); -} - -std::shared_ptr CommunicationProvider::MakeCommunicationProvider() -{ - static std::shared_ptr instance( - &MockCommunicationProvider::Init(), - [](void*) { - } - ); - return instance; -} -} - -class ProcessCommunicatorImplTest : public testing::Test { -public: - static inline std::shared_ptr deviceManagerAdapterMock = nullptr; - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - - ProcessCommunicatorImpl* communicator_; - MockCommunicationProvider* mockProvider; -}; - -namespace OHOS::DistributedData { -class ConcreteRouteHeadHandler : public RouteHeadHandler { - public: - bool ParseHeadDataLen(const uint8_t *data, uint32_t totalLen, uint32_t &headSize) - { - if (totalLen == 0) { - return true; - } - return false; - } - - bool ParseHeadDataUser(const uint8_t *data, uint32_t totalLen, const std::string &label, - std::vector &userInfos) - { - if (totalLen == 0) { - return true; - } - return false; - } -}; -} - -void ProcessCommunicatorImplTest::SetUp(void) -{ - communicator_ = ProcessCommunicatorImpl::GetInstance(); - communicator_->Stop(); - mockProvider = &MockCommunicationProvider::Init(); -} - -void ProcessCommunicatorImplTest::TearDown(void) -{ - mockProvider = nullptr; -} - -void ProcessCommunicatorImplTest::SetUpTestCase(void) -{ - deviceManagerAdapterMock = std::make_shared(); - BDeviceManagerAdapter::deviceManagerAdapter = deviceManagerAdapterMock; -} - -void ProcessCommunicatorImplTest::TearDownTestCase() -{ - deviceManagerAdapterMock = nullptr; - BDeviceManagerAdapter::deviceManagerAdapter = nullptr; -} - -/** -* @tc.name: StartTest01 -* @tc.desc: StartTest01 test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, StartTest01, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - EXPECT_CALL(*mockProvider, Start(_)).WillOnce(Return(Status::SUCCESS)); - auto status = communicator_->Start("test_process"); - EXPECT_EQ(status, DistributedDB::OK); - EXPECT_CALL(*mockProvider, Start(_)).WillOnce(Return(Status::INVALID_ARGUMENT)); - status = communicator_->Start("test_process"); - EXPECT_EQ(status, DistributedDB::DB_ERROR); -} - -/** -* @tc.name: StopTest01 -* @tc.desc: StopTest01 test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, StopTest01, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - EXPECT_CALL(*mockProvider, Stop(_)).WillOnce(Return(Status::SUCCESS)); - auto status = communicator_->Stop(); - EXPECT_EQ(status, DistributedDB::OK); - EXPECT_CALL(*mockProvider, Stop(_)).WillRepeatedly(Return(Status::INVALID_ARGUMENT)); - status = communicator_->Stop(); - EXPECT_EQ(status, DistributedDB::DB_ERROR); -} - -/** -* @tc.name: RegOnDeviceChange -* @tc.desc: RegOnDeviceChange test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, RegOnDeviceChange, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - EXPECT_CALL(*deviceManagerAdapterMock, StartWatchDeviceChange(_, _)).WillOnce(Return(Status::SUCCESS)) - .WillRepeatedly(Return(Status::SUCCESS)); - EXPECT_CALL(*deviceManagerAdapterMock, StopWatchDeviceChange(_, _)).WillOnce(Return(Status::SUCCESS)) - .WillRepeatedly(Return(Status::SUCCESS)); - auto myOnDeviceChange = [](const DeviceInfos &devInfo, bool isOnline) {}; - OnDeviceChange callback; - callback = myOnDeviceChange; - auto status = communicator_->RegOnDeviceChange(callback); - EXPECT_EQ(status, DistributedDB::OK); - callback = nullptr; - status = communicator_->RegOnDeviceChange(callback); - EXPECT_EQ(status, DistributedDB::OK); - - EXPECT_CALL(*deviceManagerAdapterMock, StartWatchDeviceChange(_, _)).WillOnce(Return(Status::INVALID_ARGUMENT)) - .WillRepeatedly(Return(Status::SUCCESS)); - EXPECT_CALL(*deviceManagerAdapterMock, StopWatchDeviceChange(_, _)).WillOnce(Return(Status::INVALID_ARGUMENT)) - .WillRepeatedly(Return(Status::SUCCESS)); - status = communicator_->RegOnDeviceChange(callback); - EXPECT_EQ(status, DistributedDB::DB_ERROR); - callback = myOnDeviceChange; - status = communicator_->RegOnDeviceChange(callback); - EXPECT_EQ(status, DistributedDB::DB_ERROR); -} - -/** -* @tc.name: RegOnDataReceive -* @tc.desc: RegOnDataReceive test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, RegOnDataReceive, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - auto myOnDeviceChange = [](const DeviceInfos &devInfo, const uint8_t *data, uint32_t length) {}; - OnDataReceive callback; - callback = myOnDeviceChange; - EXPECT_CALL(*mockProvider, StartWatchDataChange(_, _)).WillRepeatedly(Return(Status::SUCCESS)); - auto status = communicator_->RegOnDataReceive(callback); - EXPECT_EQ(status, DistributedDB::OK); - EXPECT_CALL(*mockProvider, StartWatchDataChange(_, _)).WillRepeatedly(Return(Status::ERROR)); - status = communicator_->RegOnDataReceive(callback); - EXPECT_EQ(status, DistributedDB::DB_ERROR); - - callback = nullptr; - EXPECT_CALL(*mockProvider, StopWatchDataChange(_, _)).WillRepeatedly(Return(Status::SUCCESS)); - status = communicator_->RegOnDataReceive(callback); - EXPECT_EQ(status, DistributedDB::OK); - EXPECT_CALL(*mockProvider, StopWatchDataChange(_, _)).WillRepeatedly(Return(Status::ERROR)); - status = communicator_->RegOnDataReceive(callback); - EXPECT_EQ(status, DistributedDB::DB_ERROR); -} - -/** -* @tc.name: RegOnSendAble -* @tc.desc: RegOnSendAble test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, RegOnSendAble, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - OnSendAble sendAbleCallback = nullptr; - EXPECT_NO_FATAL_FAILURE(communicator_->RegOnSendAble(sendAbleCallback)); -} - -/** -* @tc.name: SendData -* @tc.desc: SendData test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, SendData, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - DeviceInfos deviceInfos = {"SendDataTest"}; - const uint8_t *data; - uint8_t exampleData[] = {0x01, 0x02, 0x03, 0x04}; - data = exampleData; - uint32_t length = 1; - uint32_t totalLength = 1; - std::pair myPair = std::make_pair(Status::RATE_LIMIT, 1); - EXPECT_CALL(*mockProvider, SendData(_, _, _, _, _)).WillRepeatedly(Return(myPair)); - auto status = communicator_->SendData(deviceInfos, data, length, totalLength); - EXPECT_EQ(status, DistributedDB::RATE_LIMIT); - myPair = {Status::SUCCESS, 1}; - EXPECT_CALL(*mockProvider, SendData(_, _, _, _, _)).WillRepeatedly(Return(myPair)); - status = communicator_->SendData(deviceInfos, data, length, totalLength); - EXPECT_EQ(status, DistributedDB::OK); - myPair = {Status::ERROR, static_cast(DistributedDB::BUSY)}; - EXPECT_CALL(*mockProvider, SendData(_, _, _, _, _)).WillRepeatedly(Return(myPair)); - status = communicator_->SendData(deviceInfos, data, length, totalLength); - EXPECT_EQ(status, DistributedDB::BUSY); - myPair = {Status::ERROR, 0}; - EXPECT_CALL(*mockProvider, SendData(_, _, _, _, _)).WillRepeatedly(Return(myPair)); - status = communicator_->SendData(deviceInfos, data, length, totalLength); - EXPECT_EQ(status, DistributedDB::DB_ERROR); -} - -/** -* @tc.name: GetRemoteOnlineDeviceInfosList -* @tc.desc: GetRemoteOnlineDeviceInfosList test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, GetRemoteOnlineDeviceInfosList, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - auto remoteDevInfos = communicator_->GetRemoteOnlineDeviceInfosList(); - EXPECT_EQ(remoteDevInfos.empty(), true); - - DeviceInfoo deviceInfo; - deviceInfo.uuid = "GetRemoteOnlineDeviceInfosList"; - std::vector devInfos; - devInfos.push_back(deviceInfo); - EXPECT_CALL(*deviceManagerAdapterMock, GetRemoteDevices()).WillRepeatedly(Return(devInfos)); - remoteDevInfos = communicator_->GetRemoteOnlineDeviceInfosList(); - EXPECT_EQ(remoteDevInfos[0].identifier, deviceInfo.uuid); -} - -/** -* @tc.name: OnMessage -* @tc.desc: OnMessage test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, OnMessage, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - DeviceInfoo deviceInfo; - deviceInfo.uuid = "OnMessageTest"; - uint8_t data[] = {0x10, 0x20, 0x30, 0x40, 0x50}; - uint8_t *ptr = data; - int size = 1; - PipeInfo pipeInfo; - pipeInfo.pipeId = "OnMessageTest01"; - pipeInfo.userId = "OnMessageTest02"; - auto myOnDeviceChange = [](const DeviceInfos &devInfo, const uint8_t *data, uint32_t length) {}; - communicator_->onDataReceiveHandler_ = nullptr; - EXPECT_NO_FATAL_FAILURE(communicator_->OnMessage(deviceInfo, ptr, size, pipeInfo)); - communicator_->onDataReceiveHandler_ = myOnDeviceChange; - EXPECT_NO_FATAL_FAILURE(communicator_->OnMessage(deviceInfo, ptr, size, pipeInfo)); -} - -/** -* @tc.name: OnDeviceChanged -* @tc.desc: OnDeviceChanged test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, OnDeviceChanged, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - DeviceInfoo deviceInfo; - deviceInfo.uuid = "cloudDeviceUuid"; - EXPECT_NO_FATAL_FAILURE(communicator_->OnDeviceChanged(deviceInfo, DeviceChangeType::DEVICE_ONREADY)); - EXPECT_NO_FATAL_FAILURE(communicator_->OnDeviceChanged(deviceInfo, DeviceChangeType::DEVICE_OFFLINE)); - deviceInfo.uuid = "OnDeviceChangedTest"; - communicator_->onDeviceChangeHandler_ = nullptr; - EXPECT_NO_FATAL_FAILURE(communicator_->OnDeviceChanged(deviceInfo, DeviceChangeType::DEVICE_OFFLINE)); - auto myOnDeviceChange = [](const DeviceInfos &devInfo, bool isOnline) {}; - communicator_->onDeviceChangeHandler_ = myOnDeviceChange; - EXPECT_NO_FATAL_FAILURE(communicator_->OnDeviceChanged(deviceInfo, DeviceChangeType::DEVICE_OFFLINE)); -} - -/** -* @tc.name: OnSessionReady -* @tc.desc: OnSessionReady test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, OnSessionReady, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - DeviceInfoo deviceInfo; - deviceInfo.uuid = "OnSessionReadyTest"; - communicator_->sessionListener_ = nullptr; - EXPECT_NO_FATAL_FAILURE(communicator_->OnSessionReady(deviceInfo, 1)); - auto myOnSendAble = [](const DeviceInfos &deviceInfo, int deviceCommErrCode) {}; - communicator_->sessionListener_ = myOnSendAble; - EXPECT_NO_FATAL_FAILURE(communicator_->OnSessionReady(deviceInfo, 1)); -} - -/** -* @tc.name: GetExtendHeaderHandle -* @tc.desc: GetExtendHeaderHandle test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, GetExtendHeaderHandle, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - communicator_->routeHeadHandlerCreator_ = nullptr; - DistributedDB::ExtendInfo info; - auto handle = communicator_->GetExtendHeaderHandle(info); - EXPECT_EQ(handle, nullptr); - communicator_->routeHeadHandlerCreator_ = [](const DistributedDB::ExtendInfo &info) -> - std::shared_ptr { - return std::make_shared(); - }; - handle = communicator_->GetExtendHeaderHandle(info); - EXPECT_NE(handle, nullptr); -} - -/** -* @tc.name: GetDataHeadInfo -* @tc.desc: GetDataHeadInfo test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, GetDataHeadInfo, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - uint8_t data[] = {0x10, 0x20, 0x30, 0x40, 0x50}; - uint8_t *ptr = data; - uint32_t totalLen = 1; - uint32_t headLength = 1; - communicator_->routeHeadHandlerCreator_ = nullptr; - auto status = communicator_->GetDataHeadInfo(ptr, totalLen, headLength); - EXPECT_EQ(status, DistributedDB::DB_ERROR); - - communicator_->routeHeadHandlerCreator_ = [](const DistributedDB::ExtendInfo &info) -> - std::shared_ptr { - return std::make_shared(); - }; - status = communicator_->GetDataHeadInfo(ptr, totalLen, headLength); - EXPECT_EQ(status, DistributedDB::INVALID_FORMAT); - totalLen = 0; - status = communicator_->GetDataHeadInfo(ptr, totalLen, headLength); - EXPECT_EQ(status, DistributedDB::OK); -} - -/** -* @tc.name: GetDataUserInfo -* @tc.desc: GetDataUserInfo test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, GetDataUserInfo, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - uint8_t data[] = {0x10, 0x20, 0x30, 0x40, 0x50}; - uint8_t *ptr = data; - uint32_t totalLen = 1; - std::string label = "GetDataUserInfoTest"; - std::vector userInfos; - UserInfo user1{"GetDataUserInfo01"}; - UserInfo user2{"GetDataUserInfo02"}; - UserInfo user3{"GetDataUserInfo03"}; - communicator_->routeHeadHandlerCreator_ = nullptr; - auto status = communicator_->GetDataUserInfo(ptr, totalLen, label, userInfos); - EXPECT_EQ(status, DistributedDB::DB_ERROR); - - communicator_->routeHeadHandlerCreator_ = [](const DistributedDB::ExtendInfo &info) -> - std::shared_ptr { - return std::make_shared(); - }; - status = communicator_->GetDataUserInfo(ptr, totalLen, label, userInfos); - EXPECT_EQ(status, DistributedDB::INVALID_FORMAT); - totalLen = 0; - EXPECT_EQ(userInfos.empty(), true); - status = communicator_->GetDataUserInfo(ptr, totalLen, label, userInfos); - EXPECT_EQ(status, DistributedDB::NO_PERMISSION); - userInfos.push_back(user1); - userInfos.push_back(user2); - userInfos.push_back(user3); - status = communicator_->GetDataUserInfo(ptr, totalLen, label, userInfos); - EXPECT_EQ(status, DistributedDB::OK); -} - -/** -* @tc.name: ReuseConnect01 -* @tc.desc: reuse connect -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, ReuseConnect01, TestSize.Level0) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo pipe; - pipe.pipeId = "appId"; - pipe.userId = "groupId"; - DeviceId device = {"DeviceId"}; - auto status = SoftBusAdapter::GetInstance()->ReuseConnect(pipe, device); - EXPECT_EQ(status, Status::NOT_SUPPORT); - EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(testing::_)).WillOnce(testing::Return(true)) - .WillRepeatedly(testing::Return(true)); - status = SoftBusAdapter::GetInstance()->ReuseConnect(pipe, device); - EXPECT_EQ(status, Status::NETWORK_ERROR); -} - -/** -* @tc.name: CloseSession -* @tc.desc: close session -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(ProcessCommunicatorImplTest, CloseSession, TestSize.Level1) -{ - std::string networkId = "networkId"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - std::string uuid = "CloseSessionTest"; - EXPECT_CALL(*deviceManagerAdapterMock, GetUuidByNetworkId(testing::_)).WillOnce(testing::Return(uuid)) - .WillRepeatedly(testing::Return(uuid)); - std::shared_ptr conn = nullptr; - std::vector> clients; - clients.emplace_back(conn); - auto result = SoftBusAdapter::GetInstance()->connects_.Insert(uuid, clients); - EXPECT_EQ(result, true); - auto status = SoftBusAdapter::GetInstance()->CloseSession(networkId); - SoftBusAdapter::GetInstance()->connects_.Clear(); - EXPECT_EQ(status, true); -} \ No newline at end of file +///* +// * Copyright (c) 2025 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 +//#include +//#include +//#include +//#include +//#include "communication_provider.h" +//#include "device_manager_adapter_mock.h" +//#include "process_communicator_impl.h" +//#include "softbus_adapter.h" +//#include "softbus_error_code.h" +// +//using namespace testing; +//using namespace testing::ext; +//using namespace OHOS::AppDistributedKv; +//using namespace OHOS::DistributedData; +//using OnDeviceChange = DistributedDB::OnDeviceChange; +//using OnDataReceive = DistributedDB::OnDataReceive; +//using OnSendAble = DistributedDB::OnSendAble; +//using DeviceInfos = DistributedDB::DeviceInfos; +//using DeviceInfoo = OHOS::AppDistributedKv::DeviceInfo; +//using UserInfo = DistributedDB::UserInfo; +//using DataHeadInfo = DistributedDB::DataHeadInfo; +//using DataUserInfo = DistributedDB::DataUserInfo; +//namespace OHOS::AppDistributedKv { +//class MockCommunicationProvider : public CommunicationProvider { +//public: +// ~MockCommunicationProvider() = default; +// static MockCommunicationProvider& Init() +// { +// static MockCommunicationProvider instance; +// return instance; +// } +// MOCK_METHOD(Status, StartWatchDataChange, (const AppDataChangeListener *, const PipeInfo &), (override)); +// MOCK_METHOD(Status, StopWatchDataChange, (const AppDataChangeListener *, const PipeInfo &), (override)); +// MOCK_METHOD(Status, Start, (const PipeInfo&), (override)); +// MOCK_METHOD(Status, Stop, (const PipeInfo&), (override)); +// MOCK_METHOD((std::pair), SendData, (const PipeInfo&, const DeviceId&, +// const DataInfo&, uint32_t, const MessageInfo &), (override)); +// MOCK_METHOD(bool, IsSameStartedOnPeer, (const PipeInfo &, const DeviceId &), (const)); +// MOCK_METHOD(Status, ReuseConnect, (const PipeInfo&, const DeviceId&, const ExtraDataInfo&), (override)); +// MOCK_METHOD(void, SetDeviceQuery, (std::shared_ptr), (override)); +// MOCK_METHOD(void, SetMessageTransFlag, (const PipeInfo &, bool), (override)); +// MOCK_METHOD(Status, Broadcast, (const PipeInfo &, const LevelInfo &), (override)); +// MOCK_METHOD(int32_t, ListenBroadcastMsg, (const PipeInfo &, +// std::function), (override)); +//}; +// +//CommunicationProvider& CommunicationProvider::GetInstance() +//{ +// return MockCommunicationProvider::Init(); +//} +// +//std::shared_ptr CommunicationProvider::MakeCommunicationProvider() +//{ +// static std::shared_ptr instance( +// &MockCommunicationProvider::Init(), +// [](void*) { +// } +// ); +// return instance; +//} +//} +// +//class ProcessCommunicatorImplTest : public testing::Test { +//public: +// static inline std::shared_ptr deviceManagerAdapterMock = nullptr; +// static void SetUpTestCase(void); +// static void TearDownTestCase(void); +// void SetUp(); +// void TearDown(); +// +// ProcessCommunicatorImpl* communicator_; +// MockCommunicationProvider* mockProvider; +//}; +// +//namespace OHOS::DistributedData { +//class ConcreteRouteHeadHandler : public RouteHeadHandler { +// public: +// bool ParseHeadDataLen(const uint8_t *data, uint32_t totalLen, uint32_t &headSize, const std::string &device) +// { +// if (totalLen == 0) { +// return true; +// } +// return false; +// } +// +// bool ParseHeadDataUser(const uint8_t *data, uint32_t totalLen, const std::string &label, +// std::vector &userInfos) +// { +// if (totalLen == 0) { +// return true; +// } +// return false; +// } +//}; +//} +// +//void ProcessCommunicatorImplTest::SetUp(void) +//{ +// communicator_ = ProcessCommunicatorImpl::GetInstance(); +// communicator_->Stop(); +// mockProvider = &MockCommunicationProvider::Init(); +//} +// +//void ProcessCommunicatorImplTest::TearDown(void) +//{ +// mockProvider = nullptr; +//} +// +//void ProcessCommunicatorImplTest::SetUpTestCase(void) +//{ +// deviceManagerAdapterMock = std::make_shared(); +// BDeviceManagerAdapter::deviceManagerAdapter = deviceManagerAdapterMock; +//} +// +//void ProcessCommunicatorImplTest::TearDownTestCase() +//{ +// deviceManagerAdapterMock = nullptr; +// BDeviceManagerAdapter::deviceManagerAdapter = nullptr; +//} +// +///** +//* @tc.name: StartTest01 +//* @tc.desc: StartTest01 test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, StartTest01, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// EXPECT_CALL(*mockProvider, Start(_)).WillOnce(Return(Status::SUCCESS)); +// auto status = communicator_->Start("test_process"); +// EXPECT_EQ(status, DistributedDB::OK); +// EXPECT_CALL(*mockProvider, Start(_)).WillOnce(Return(Status::INVALID_ARGUMENT)); +// status = communicator_->Start("test_process"); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +//} +// +///** +//* @tc.name: StopTest01 +//* @tc.desc: StopTest01 test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, StopTest01, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// EXPECT_CALL(*mockProvider, Stop(_)).WillOnce(Return(Status::SUCCESS)); +// auto status = communicator_->Stop(); +// EXPECT_EQ(status, DistributedDB::OK); +// EXPECT_CALL(*mockProvider, Stop(_)).WillRepeatedly(Return(Status::INVALID_ARGUMENT)); +// status = communicator_->Stop(); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +//} +// +///** +//* @tc.name: RegOnDeviceChange +//* @tc.desc: RegOnDeviceChange test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, RegOnDeviceChange, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// EXPECT_CALL(*deviceManagerAdapterMock, StartWatchDeviceChange(_, _)).WillOnce(Return(Status::SUCCESS)) +// .WillRepeatedly(Return(Status::SUCCESS)); +// EXPECT_CALL(*deviceManagerAdapterMock, StopWatchDeviceChange(_, _)).WillOnce(Return(Status::SUCCESS)) +// .WillRepeatedly(Return(Status::SUCCESS)); +// auto myOnDeviceChange = [](const DeviceInfos &devInfo, bool isOnline) {}; +// OnDeviceChange callback; +// callback = myOnDeviceChange; +// auto status = communicator_->RegOnDeviceChange(callback); +// EXPECT_EQ(status, DistributedDB::OK); +// callback = nullptr; +// status = communicator_->RegOnDeviceChange(callback); +// EXPECT_EQ(status, DistributedDB::OK); +// +// EXPECT_CALL(*deviceManagerAdapterMock, StartWatchDeviceChange(_, _)).WillOnce(Return(Status::INVALID_ARGUMENT)) +// .WillRepeatedly(Return(Status::SUCCESS)); +// EXPECT_CALL(*deviceManagerAdapterMock, StopWatchDeviceChange(_, _)).WillOnce(Return(Status::INVALID_ARGUMENT)) +// .WillRepeatedly(Return(Status::SUCCESS)); +// status = communicator_->RegOnDeviceChange(callback); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +// callback = myOnDeviceChange; +// status = communicator_->RegOnDeviceChange(callback); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +//} +// +///** +//* @tc.name: RegOnDataReceive +//* @tc.desc: RegOnDataReceive test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, RegOnDataReceive, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// auto myOnDeviceChange = [](const DeviceInfos &devInfo, const uint8_t *data, uint32_t length) {}; +// OnDataReceive callback; +// callback = myOnDeviceChange; +// EXPECT_CALL(*mockProvider, StartWatchDataChange(_, _)).WillRepeatedly(Return(Status::SUCCESS)); +// auto status = communicator_->RegOnDataReceive(callback); +// EXPECT_EQ(status, DistributedDB::OK); +// EXPECT_CALL(*mockProvider, StartWatchDataChange(_, _)).WillRepeatedly(Return(Status::ERROR)); +// status = communicator_->RegOnDataReceive(callback); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +// +// callback = nullptr; +// EXPECT_CALL(*mockProvider, StopWatchDataChange(_, _)).WillRepeatedly(Return(Status::SUCCESS)); +// status = communicator_->RegOnDataReceive(callback); +// EXPECT_EQ(status, DistributedDB::OK); +// EXPECT_CALL(*mockProvider, StopWatchDataChange(_, _)).WillRepeatedly(Return(Status::ERROR)); +// status = communicator_->RegOnDataReceive(callback); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +//} +// +///** +//* @tc.name: RegOnSendAble +//* @tc.desc: RegOnSendAble test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, RegOnSendAble, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// OnSendAble sendAbleCallback = nullptr; +// EXPECT_NO_FATAL_FAILURE(communicator_->RegOnSendAble(sendAbleCallback)); +//} +// +///** +//* @tc.name: SendData +//* @tc.desc: SendData test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, SendData, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// DeviceInfos deviceInfos = {"SendDataTest"}; +// const uint8_t *data; +// uint8_t exampleData[] = {0x01, 0x02, 0x03, 0x04}; +// data = exampleData; +// uint32_t length = 1; +// uint32_t totalLength = 1; +// std::pair myPair = std::make_pair(Status::RATE_LIMIT, 1); +// EXPECT_CALL(*mockProvider, SendData(_, _, _, _, _)).WillRepeatedly(Return(myPair)); +// auto status = communicator_->SendData(deviceInfos, data, length, totalLength); +// EXPECT_EQ(status, DistributedDB::RATE_LIMIT); +// myPair = {Status::SUCCESS, 1}; +// EXPECT_CALL(*mockProvider, SendData(_, _, _, _, _)).WillRepeatedly(Return(myPair)); +// status = communicator_->SendData(deviceInfos, data, length, totalLength); +// EXPECT_EQ(status, DistributedDB::OK); +// myPair = {Status::ERROR, static_cast(DistributedDB::BUSY)}; +// EXPECT_CALL(*mockProvider, SendData(_, _, _, _, _)).WillRepeatedly(Return(myPair)); +// status = communicator_->SendData(deviceInfos, data, length, totalLength); +// EXPECT_EQ(status, DistributedDB::BUSY); +// myPair = {Status::ERROR, 0}; +// EXPECT_CALL(*mockProvider, SendData(_, _, _, _, _)).WillRepeatedly(Return(myPair)); +// status = communicator_->SendData(deviceInfos, data, length, totalLength); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +//} +// +///** +//* @tc.name: GetRemoteOnlineDeviceInfosList +//* @tc.desc: GetRemoteOnlineDeviceInfosList test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, GetRemoteOnlineDeviceInfosList, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// auto remoteDevInfos = communicator_->GetRemoteOnlineDeviceInfosList(); +// EXPECT_EQ(remoteDevInfos.empty(), true); +// +// DeviceInfoo deviceInfo; +// deviceInfo.uuid = "GetRemoteOnlineDeviceInfosList"; +// std::vector devInfos; +// devInfos.push_back(deviceInfo); +// EXPECT_CALL(*deviceManagerAdapterMock, GetRemoteDevices()).WillRepeatedly(Return(devInfos)); +// remoteDevInfos = communicator_->GetRemoteOnlineDeviceInfosList(); +// EXPECT_EQ(remoteDevInfos[0].identifier, deviceInfo.uuid); +//} +// +///** +//* @tc.name: OnMessage +//* @tc.desc: OnMessage test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, OnMessage, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// DeviceInfoo deviceInfo; +// deviceInfo.uuid = "OnMessageTest"; +// uint8_t data[] = {0x10, 0x20, 0x30, 0x40, 0x50}; +// uint8_t *ptr = data; +// int size = 1; +// PipeInfo pipeInfo; +// pipeInfo.pipeId = "OnMessageTest01"; +// pipeInfo.userId = "OnMessageTest02"; +// auto myOnDeviceChange = [](const DeviceInfos &devInfo, const uint8_t *data, uint32_t length) {}; +// communicator_->onDataReceiveHandler_ = nullptr; +// EXPECT_NO_FATAL_FAILURE(communicator_->OnMessage(deviceInfo, ptr, size, pipeInfo)); +// communicator_->onDataReceiveHandler_ = myOnDeviceChange; +// EXPECT_NO_FATAL_FAILURE(communicator_->OnMessage(deviceInfo, ptr, size, pipeInfo)); +//} +// +///** +//* @tc.name: OnDeviceChanged +//* @tc.desc: OnDeviceChanged test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, OnDeviceChanged, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// DeviceInfoo deviceInfo; +// deviceInfo.uuid = "cloudDeviceUuid"; +// EXPECT_NO_FATAL_FAILURE(communicator_->OnDeviceChanged(deviceInfo, DeviceChangeType::DEVICE_ONREADY)); +// EXPECT_NO_FATAL_FAILURE(communicator_->OnDeviceChanged(deviceInfo, DeviceChangeType::DEVICE_OFFLINE)); +// deviceInfo.uuid = "OnDeviceChangedTest"; +// communicator_->onDeviceChangeHandler_ = nullptr; +// EXPECT_NO_FATAL_FAILURE(communicator_->OnDeviceChanged(deviceInfo, DeviceChangeType::DEVICE_OFFLINE)); +// auto myOnDeviceChange = [](const DeviceInfos &devInfo, bool isOnline) {}; +// communicator_->onDeviceChangeHandler_ = myOnDeviceChange; +// EXPECT_NO_FATAL_FAILURE(communicator_->OnDeviceChanged(deviceInfo, DeviceChangeType::DEVICE_OFFLINE)); +//} +// +///** +//* @tc.name: OnSessionReady +//* @tc.desc: OnSessionReady test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, OnSessionReady, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// DeviceInfoo deviceInfo; +// deviceInfo.uuid = "OnSessionReadyTest"; +// communicator_->sessionListener_ = nullptr; +// EXPECT_NO_FATAL_FAILURE(communicator_->OnSessionReady(deviceInfo, 1)); +// auto myOnSendAble = [](const DeviceInfos &deviceInfo, int deviceCommErrCode) {}; +// communicator_->sessionListener_ = myOnSendAble; +// EXPECT_NO_FATAL_FAILURE(communicator_->OnSessionReady(deviceInfo, 1)); +//} +// +///** +//* @tc.name: GetExtendHeaderHandle +//* @tc.desc: GetExtendHeaderHandle test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, GetExtendHeaderHandle, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// communicator_->routeHeadHandlerCreator_ = nullptr; +// DistributedDB::ExtendInfo info; +// auto handle = communicator_->GetExtendHeaderHandle(info); +// EXPECT_EQ(handle, nullptr); +// communicator_->routeHeadHandlerCreator_ = [](const DistributedDB::ExtendInfo &info) -> +// std::shared_ptr { +// return std::make_shared(); +// }; +// handle = communicator_->GetExtendHeaderHandle(info); +// EXPECT_NE(handle, nullptr); +//} +// +///** +//* @tc.name: GetDataHeadInfo +//* @tc.desc: GetDataHeadInfo test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, GetDataHeadInfo, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// uint8_t data[] = {0x10, 0x20, 0x30, 0x40, 0x50}; +// uint8_t *ptr = data; +// uint32_t headLength = 1; +// DataHeadInfo dataHeadInfo { ptr, 1, "" }; +// communicator_->routeHeadHandlerCreator_ = nullptr; +// auto status = communicator_->GetDataHeadInfo(dataHeadInfo, headLength); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +// +// communicator_->routeHeadHandlerCreator_ = [](const DistributedDB::ExtendInfo &info) -> +// std::shared_ptr { +// return std::make_shared(); +// }; +// status = communicator_->GetDataHeadInfo(dataHeadInfo, headLength); +// EXPECT_EQ(status, DistributedDB::INVALID_FORMAT); +// dataHeadInfo.totalLen = 0; +// status = communicator_->GetDataHeadInfo(dataHeadInfo, headLength); +// EXPECT_EQ(status, DistributedDB::OK); +//} +// +///** +//* @tc.name: GetDataUserInfo +//* @tc.desc: GetDataUserInfo test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, GetDataUserInfo, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// uint8_t data[] = {0x10, 0x20, 0x30, 0x40, 0x50}; +// uint8_t *ptr = data; +// DataUserInfo dataUserInfo { ptr, 1, "GetDataUserInfoTest", "" }; +// std::vector userInfos; +// UserInfo user1{"GetDataUserInfo01"}; +// UserInfo user2{"GetDataUserInfo02"}; +// UserInfo user3{"GetDataUserInfo03"}; +// communicator_->routeHeadHandlerCreator_ = nullptr; +// auto status = communicator_->GetDataUserInfo(dataUserInfo, userInfos); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +// +// communicator_->routeHeadHandlerCreator_ = [](const DistributedDB::ExtendInfo &info) -> +// std::shared_ptr { +// return std::make_shared(); +// }; +// status = communicator_->GetDataUserInfo(dataUserInfo, userInfos); +// EXPECT_EQ(status, DistributedDB::INVALID_FORMAT); +//} +// +///** +//* @tc.name: CloseSession +//* @tc.desc: close session +//* @tc.type: FUNC +//* @tc.author: nhj +//*/ +//HWTEST_F(ProcessCommunicatorImplTest, CloseSession, TestSize.Level1) +//{ +// std::string networkId = "networkId"; +// auto flag = SoftBusAdapter::GetInstance(); +// ASSERT_NE(flag, nullptr); +// std::string uuid = "CloseSessionTest"; +// EXPECT_CALL(*deviceManagerAdapterMock, GetUuidByNetworkId(testing::_)).WillOnce(testing::Return(uuid)) +// .WillRepeatedly(testing::Return(uuid)); +// std::shared_ptr conn = nullptr; +// std::vector> clients; +// clients.emplace_back(conn); +// auto result = SoftBusAdapter::GetInstance()->connects_.Insert(uuid, clients); +// EXPECT_EQ(result, true); +// auto status = SoftBusAdapter::GetInstance()->CloseSession(networkId); +// SoftBusAdapter::GetInstance()->connects_.Clear(); +// EXPECT_EQ(status, true); +//} \ No newline at end of file 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 4666457e4901efa0867603f6d3cdb4e22f470e26..21b8ccc0fd4e1bf8005facdfe55d720759dbc0f5 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 @@ -1,651 +1,469 @@ -/* - * Copyright (c) 2022 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 "app_device_change_listener.h" -#include -#include "gtest/gtest.h" -#include -#include "softbus_adapter.h" -#include "softbus_adapter_standard.cpp" -#include "softbus_error_code.h" -#include "types.h" -#include -#include - -namespace OHOS::Test { -using namespace testing::ext; -using namespace OHOS::AppDistributedKv; -using namespace OHOS::DistributedData; -using DeviceInfo = OHOS::AppDistributedKv::DeviceInfo; -class AppDataChangeListenerImpl : public AppDataChangeListener { - struct ServerSocketInfo { - std::string name; /**< Peer socket name */ - std::string networkId; /**< Peer network ID */ - std::string pkgName; /**< Peer package name */ - }; - - void OnMessage(const OHOS::AppDistributedKv::DeviceInfo &info, const uint8_t *ptr, const int size, - const struct PipeInfo &id) const override; -}; - -void AppDataChangeListenerImpl::OnMessage(const OHOS::AppDistributedKv::DeviceInfo &info, - const uint8_t *ptr, const int size, const struct PipeInfo &id) const -{} - -class SoftbusAdapterStandardTest : public testing::Test { -public: - static void SetUpTestCase(void) {} - static void TearDownTestCase(void) {} - void SetUp() {} - void TearDown() {} -protected: - static constexpr uint32_t DEFAULT_MTU_SIZE = 4096 * 1024u; - static constexpr uint32_t DEFAULT_TIMEOUT = 30 * 1000; -}; - -/** -* @tc.name: StartWatchDeviceChange -* @tc.desc: start watch data change -* @tc.type: FUNC -* @tc.require: -* @tc.author: nhj - */ -HWTEST_F(SoftbusAdapterStandardTest, StartWatchDeviceChange, TestSize.Level0) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - auto status = SoftBusAdapter::GetInstance()->StartWatchDataChange(nullptr, {}); - EXPECT_EQ(status, Status::INVALID_ARGUMENT); -} - -/** -* @tc.name: StartWatchDeviceChange -* @tc.desc: start watch data change -* @tc.type: FUNC -* @tc.require: -* @tc.author: nhj - */ -HWTEST_F(SoftbusAdapterStandardTest, StartWatchDeviceChange01, TestSize.Level0) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo appId; - appId.pipeId = "appId"; - appId.userId = "groupId"; - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - auto status = SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, appId); - EXPECT_EQ(status, Status::SUCCESS); - status = SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, appId); - delete dataListener; - EXPECT_EQ(status, Status::ERROR); -} - -/** -* @tc.name: StartWatchDeviceChange -* @tc.desc: start watch data change -* @tc.type: FUNC -* @tc.require: -* @tc.author: nhj - */ -HWTEST_F(SoftbusAdapterStandardTest, StartWatchDeviceChange02, TestSize.Level0) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo appId; - appId.pipeId = ""; - appId.userId = "groupId"; - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - auto status = SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, appId); - delete dataListener; - EXPECT_EQ(status, Status::SUCCESS); -} - -/** -* @tc.name: StartWatchDeviceChange03 -* @tc.desc:the observer is nullptr -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, StartWatchDeviceChange03, TestSize.Level1) -{ - PipeInfo appId; - appId.pipeId = "appId06"; - appId.userId = "groupId06"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - SoftBusAdapter::GetInstance()->StartWatchDataChange(nullptr, appId); - auto status = SoftBusAdapter::GetInstance()->StartWatchDataChange(nullptr, appId); - EXPECT_EQ(Status::INVALID_ARGUMENT, status); -} - -/** -* @tc.name: StopWatchDataChange -* @tc.desc: stop watch data change -* @tc.type: FUNC -* @tc.require: -* @tc.author: nhj - */ -HWTEST_F(SoftbusAdapterStandardTest, StopWatchDataChange, TestSize.Level0) -{ - PipeInfo appId; - appId.pipeId = "appId"; - appId.userId = "groupId"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - auto status = SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, appId); - EXPECT_EQ(status, Status::SUCCESS); - status = SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, appId); - delete dataListener; - EXPECT_EQ(status, Status::ERROR); -} - -/** -* @tc.name: StopWatchDataChange -* @tc.desc: stop watch data change -* @tc.type: FUNC -* @tc.require: -* @tc.author: nhj - */ -HWTEST_F(SoftbusAdapterStandardTest, StopWatchDataChange01, TestSize.Level0) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo appId; - appId.pipeId = ""; - appId.userId = "groupId"; - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - auto status = SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, appId); - delete dataListener; - EXPECT_EQ(status, Status::SUCCESS); -} - -/** -* @tc.name: GetExpireTime -* @tc.desc: GetExpireTime Test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(SoftbusAdapterStandardTest, GetExpireTime, TestSize.Level0) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo appId; - appId.pipeId = "appId"; - appId.userId = "groupId"; - DeviceId id = {"DeviceId"}; - std::shared_ptr conn = std::make_shared(appId, id, SoftBusClient::QoSType::QOS_HML); - EXPECT_NO_FATAL_FAILURE(SoftBusAdapter::GetInstance()->GetExpireTime(conn)); -} - -/** -* @tc.name: SendData -* @tc.desc: parse sent data -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, SendData, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - PipeInfo id; - id.pipeId = "appId"; - id.userId = "groupId"; - auto secRegister = SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, id); - EXPECT_EQ(Status::SUCCESS, secRegister); - std::string content = "Helloworlds"; - const uint8_t *t = reinterpret_cast(content.c_str()); - DeviceId di = {"DeviceId"}; - DataInfo data = { const_cast(t), static_cast(content.length())}; - auto status = SoftBusAdapter::GetInstance()->SendData(id, di, data, 11, { MessageType::DEFAULT }); - EXPECT_NE(status.first, Status::SUCCESS); - SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, id); - delete dataListener; -} - -/** -* @tc.name: SendData01 -* @tc.desc: parse sent data -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, SendData01, TestSize.Level1) -{ - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - PipeInfo pipe01; - pipe01.pipeId = "appId"; - pipe01.userId = "groupId"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - auto secRegister = SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, pipe01); - EXPECT_EQ(Status::SUCCESS, secRegister); - std::string content = ""; - const uint8_t *t = reinterpret_cast(content.c_str()); - DeviceId di = {"DeviceId"}; - DataInfo data = { const_cast(t), static_cast(content.length())}; - auto status = SoftBusAdapter::GetInstance()->SendData(pipe01, di, data, 10, { MessageType::FILE }); - EXPECT_NE(status.first, Status::ERROR); - EXPECT_EQ(status.first, Status::RATE_LIMIT); - SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, pipe01); - delete dataListener; -} - -/** -* @tc.name: StartCloseSessionTask -* @tc.desc: StartCloseSessionTask tests -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, StartCloseSessionTask, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - std::shared_ptr conn = nullptr; - std::vector> clients; - clients.emplace_back(conn); - auto status = SoftBusAdapter::GetInstance()->connects_.Insert("deviceId01", clients); - EXPECT_EQ(status, true); - SoftBusAdapter::GetInstance()->connects_.Clear(); - EXPECT_NO_FATAL_FAILURE(SoftBusAdapter::GetInstance()->StartCloseSessionTask("deviceId02")); -} - -/** -* @tc.name: OnClientShutdown -* @tc.desc: DelConnect tests -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, OnClientShutdown, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo appId; - appId.pipeId = "appId"; - appId.userId = "groupId"; - DeviceId id = {"DeviceId"}; - std::shared_ptr conn1 = std::make_shared(appId, id, SoftBusClient::QoSType::QOS_HML); - std::shared_ptr conn2 = nullptr; - std::vector> clients; - clients.emplace_back(conn1); - clients.emplace_back(conn2); - auto status = SoftBusAdapter::GetInstance()->connects_.Insert("deviceId01", clients); - EXPECT_EQ(status, true); - status = SoftBusAdapter::GetInstance()->connects_.Insert("deviceId02", {}); - EXPECT_EQ(status, true); - auto name = SoftBusAdapter::GetInstance()->OnClientShutdown(-1, true); - EXPECT_EQ(name, "deviceId01 "); - name = SoftBusAdapter::GetInstance()->OnClientShutdown(-1, false); - EXPECT_EQ(name, ""); - name = SoftBusAdapter::GetInstance()->OnClientShutdown(1, true); - SoftBusAdapter::GetInstance()->connects_.Clear(); - EXPECT_EQ(name, ""); -} - -/** -* @tc.name: NotifyDataListeners -* @tc.desc: NotifyDataListeners tests -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, NotifyDataListeners, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo appId; - appId.pipeId = "appId"; - appId.userId = "groupId"; - std::string content = "Helloworlds"; - const uint8_t *t = reinterpret_cast(content.c_str()); - SoftBusAdapter::GetInstance()->dataChangeListeners_.Clear(); - EXPECT_NO_FATAL_FAILURE(SoftBusAdapter::GetInstance()->NotifyDataListeners(t, 1, "deviceId", appId)); - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - SoftBusAdapter::GetInstance()->dataChangeListeners_.Insert(appId.pipeId, dataListener); - delete dataListener; - SoftBusAdapter::GetInstance()->dataChangeListeners_.Clear(); - EXPECT_NO_FATAL_FAILURE(SoftBusAdapter::GetInstance()->NotifyDataListeners(t, 1, "deviceId", appId)); -} - -/** -* @tc.name: ListenBroadcastMsg -* @tc.desc: ListenBroadcastMsg tests -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, ListenBroadcastMsg, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - SoftBusAdapter::GetInstance()->onBroadcast_= nullptr; - PipeInfo appId; - appId.pipeId = "appId"; - appId.userId = "groupId"; - auto result = SoftBusAdapter::GetInstance()->ListenBroadcastMsg(appId, nullptr); - EXPECT_EQ(result, SoftBusErrNo::SOFTBUS_INVALID_PARAM); - - auto listener = [](const std::string &message, const LevelInfo &info) {}; - result = SoftBusAdapter::GetInstance()->ListenBroadcastMsg(appId, listener); - EXPECT_EQ(result, SoftBusErrNo::SOFTBUS_INVALID_PARAM); - result = SoftBusAdapter::GetInstance()->ListenBroadcastMsg(appId, listener); - EXPECT_EQ(result, SoftBusErrNo::SOFTBUS_ALREADY_EXISTED); -} - -/** -* @tc.name: OnBroadcast -* @tc.desc: OnBroadcast tests -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, OnBroadcast, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - DeviceId id = {"DeviceId"}; - LevelInfo level; - level.dynamic = 1; - level.statics = 1; - level.switches = 1; - level.switchesLen = 1; - EXPECT_NE(SoftBusAdapter::GetInstance()->onBroadcast_, nullptr); - EXPECT_NO_FATAL_FAILURE(SoftBusAdapter::GetInstance()->OnBroadcast(id, level)); - SoftBusAdapter::GetInstance()->onBroadcast_ = nullptr; - EXPECT_NO_FATAL_FAILURE(SoftBusAdapter::GetInstance()->OnBroadcast(id, level)); -} - -/** -* @tc.name: OnClientSocketChanged -* @tc.desc: OnClientSocketChanged tests -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, OnClientSocketChanged, TestSize.Level1) -{ - QosTV qosTv; - qosTv.qos = QosType::QOS_TYPE_MIN_BW; - qosTv.value = 1; - EXPECT_NO_FATAL_FAILURE(AppDataListenerWrap::OnClientSocketChanged(1, QoSEvent::QOS_SATISFIED, &qosTv, 1)); - EXPECT_NO_FATAL_FAILURE(AppDataListenerWrap::OnClientSocketChanged(1, QoSEvent::QOS_SATISFIED, &qosTv, 0)); - qosTv.qos = QosType::QOS_TYPE_MAX_WAIT_TIMEOUT; - EXPECT_NO_FATAL_FAILURE(AppDataListenerWrap::OnClientSocketChanged(1, QoSEvent::QOS_SATISFIED, &qosTv, 0)); - EXPECT_NO_FATAL_FAILURE(AppDataListenerWrap::OnClientSocketChanged(1, QoSEvent::QOS_SATISFIED, nullptr, 0)); - EXPECT_NO_FATAL_FAILURE(AppDataListenerWrap::OnClientSocketChanged(1, QoSEvent::QOS_NOT_SATISFIED, nullptr, 0)); -} - -/** -* @tc.name: OnServerBytesReceived -* @tc.desc: OnServerBytesReceived tests -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, OnServerBytesReceived, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PeerSocketInfo info; - info.name = strdup(""); - info.networkId = strdup("peertest01"); - info.pkgName = strdup("ohos.kv.test"); - info.dataType = TransDataType::DATA_TYPE_MESSAGE; - AppDistributedKv::SoftBusAdapter::ServerSocketInfo serinfo; - auto result = SoftBusAdapter::GetInstance()->GetPeerSocketInfo(1, serinfo); - EXPECT_EQ(result, false); - char str[] = "Hello"; - const void* data = static_cast(str); - EXPECT_NO_FATAL_FAILURE(AppDataListenerWrap::OnServerBytesReceived(1, data, 10)); - SoftBusAdapter::GetInstance()->OnBind(1, info); - result = SoftBusAdapter::GetInstance()->GetPeerSocketInfo(1, serinfo); - EXPECT_EQ(result, true); - EXPECT_NO_FATAL_FAILURE(AppDataListenerWrap::OnServerBytesReceived(1, data, 10)); - info.name = strdup("name"); - SoftBusAdapter::GetInstance()->OnBind(2, info); - result = SoftBusAdapter::GetInstance()->GetPeerSocketInfo(2, serinfo); - EXPECT_EQ(result, true); - EXPECT_NO_FATAL_FAILURE(AppDataListenerWrap::OnServerBytesReceived(2, data, 10)); -} - -/** -* @tc.name: GetPipeId -* @tc.desc: GetPipeId tests -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, GetPipeId, TestSize.Level1) -{ - std::string names = "GetPipeId"; - auto name = AppDataListenerWrap::GetPipeId(names); - EXPECT_EQ(name, names); - names = "test01_GetPipeId"; - name = AppDataListenerWrap::GetPipeId(names); - EXPECT_EQ(name, "test01"); -} - -/** -* @tc.name: GetMtuSize -* @tc.desc: get size -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, GetMtuSize, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - PipeInfo id; - id.pipeId = "appId"; - id.userId = "groupId"; - SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, id); - DeviceId di = {"DeviceId"}; - auto size = SoftBusAdapter::GetInstance()->GetMtuSize(di); - EXPECT_EQ(size, DEFAULT_MTU_SIZE); - SoftBusAdapter::GetInstance()->GetCloseSessionTask(); - SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, id); - delete dataListener; -} - -/** -* @tc.name: GetTimeout -* @tc.desc: get timeout -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, GetTimeout, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - PipeInfo id; - id.pipeId = "appId01"; - id.userId = "groupId01"; - SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, id); - DeviceId di = {"DeviceId"}; - auto time = SoftBusAdapter::GetInstance()->GetTimeout(di); - EXPECT_EQ(time, DEFAULT_TIMEOUT); - SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, id); - delete dataListener; -} - -/** -* @tc.name: IsSameStartedOnPeer -* @tc.desc: get size -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, IsSameStartedOnPeer, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo id; - id.pipeId = "appId01"; - id.userId = "groupId01"; - DeviceId di = {"DeviceId"}; - SoftBusAdapter::GetInstance()->SetMessageTransFlag(id, true); - auto status = SoftBusAdapter::GetInstance()->IsSameStartedOnPeer(id, di); - EXPECT_EQ(status, true); -} - -/** -* @tc.name: ReuseConnect -* @tc.desc: reuse connect -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, ReuseConnect, TestSize.Level1) -{ - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - PipeInfo pipe; - pipe.pipeId = "appId"; - pipe.userId = "groupId"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, pipe); - DeviceId device = {"DeviceId"}; - auto reuse = SoftBusAdapter::GetInstance()->ReuseConnect(pipe, device); - EXPECT_EQ(reuse, Status::NOT_SUPPORT); - SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, pipe); - delete dataListener; -} - -/** -* @tc.name: ReuseConnect01 -* @tc.desc: reuse connect -* @tc.type: FUNC -* @tc.author: wangbin -*/ -HWTEST_F(SoftbusAdapterStandardTest, ReuseConnect01, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo pipe; - pipe.pipeId = "appId"; - pipe.userId = "groupId"; - DeviceId device = {"DeviceId"}; - auto status = SoftBusAdapter::GetInstance()->ReuseConnect(pipe, device); - EXPECT_EQ(status, Status::NOT_SUPPORT); -} - -/** -* @tc.name: GetConnect -* @tc.desc: get connect -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, GetConnect, TestSize.Level1) -{ - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - PipeInfo pipe; - pipe.pipeId = "appId01"; - pipe.userId = "groupId01"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, pipe); - DeviceId device = {"DeviceId01"}; - std::shared_ptr conn = nullptr; - auto reuse = SoftBusAdapter::GetInstance()->GetConnect(pipe, device, 1); - EXPECT_NE(reuse, nullptr); - SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, pipe); - delete dataListener; -} - -/** -* @tc.name: Broadcast -* @tc.desc: broadcast -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, Broadcast, TestSize.Level1) -{ - PipeInfo id; - id.pipeId = "appId"; - id.userId = "groupId"; - LevelInfo level; - level.dynamic = 1; - level.statics = 1; - level.switches = 1; - level.switchesLen = 1; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - SoftBusAdapter::GetInstance()->SetMessageTransFlag(id, true); - auto status = SoftBusAdapter::GetInstance()->Broadcast(id, level); - EXPECT_EQ(status, Status::ERROR); -} - -/** -* @tc.name: OpenConnect -* @tc.desc: open connect -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, OpenConnect, TestSize.Level1) -{ - DeviceId device = {"DeviceId"}; - std::shared_ptr conn = nullptr; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - auto status = SoftBusAdapter::GetInstance()->OpenConnect(conn, device); - EXPECT_NE(status.first, Status::SUCCESS); - EXPECT_EQ(status.first, Status::RATE_LIMIT); - EXPECT_EQ(status.second, 0); -} - -/** -* @tc.name: CloseSession -* @tc.desc: close session -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, CloseSession, TestSize.Level1) -{ - std::string networkId = "networkId"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - auto status = SoftBusAdapter::GetInstance()->CloseSession(networkId); - EXPECT_EQ(status, false); -} - -/** -* @tc.name: CloseSession01 -* @tc.desc: close session -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, CloseSession01, TestSize.Level1) -{ - std::string networkId = ""; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - auto status = SoftBusAdapter::GetInstance()->CloseSession(networkId); - EXPECT_EQ(status, false); -} - -/** -* @tc.name: GetPeerSocketInfo -* @tc.desc: get socket info -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, GetPeerSocketInfo, TestSize.Level1) -{ - AppDistributedKv::SoftBusAdapter::ServerSocketInfo info; - info.name = "kv"; - info.networkId= "192.168.1.1"; - info.pkgName = "test"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - auto status = SoftBusAdapter::GetInstance()->GetPeerSocketInfo(-1, info); - EXPECT_EQ(status, false); -} - -/** -* @tc.name: GetPeerSocketInfo -* @tc.desc: get socket info -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, GetPeerSocketInfo01, TestSize.Level1) -{ - AppDistributedKv::SoftBusAdapter::ServerSocketInfo info; - info.name = "service"; - info.networkId= "192.168.1.1"; - info.pkgName = "test"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - auto status = SoftBusAdapter::GetInstance()->GetPeerSocketInfo(1, info); - EXPECT_EQ(status, true); -} -} // namespace OHOS::Test \ No newline at end of file +///* +// * Copyright (c) 2022 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 "softbus_adapter.h" +// +//#include +// +//#include "account/account_delegate.h" +//#include "app_data_change_listener.h" +//#include "app_device_change_listener.h" +//#include "communication/connect_manager.h" +//#include "communicator_context.h" +//#include "data_level.h" +//#include "db_store_mock.h" +//#include "device_manager_adapter.h" +//#include "executor_pool.h" +//#include "inner_socket.h" +//#include "metadata/appid_meta_data.h" +//#include "metadata/meta_data_manager.h" +//#include "metadata/store_meta_data.h" +//#include "types.h" +// +//namespace OHOS::Test { +//using namespace testing::ext; +//using namespace OHOS::AppDistributedKv; +//using namespace OHOS::DistributedData; +// +//static constexpr size_t THREAD_MIN = 0; +//static constexpr size_t THREAD_MAX = 3; +//static constexpr uint16_t DYNAMIC_LEVEL = 0xFFFF; +//static constexpr uint16_t STATIC_LEVEL = 0x1111; +//static constexpr uint32_t SWITCH_VALUE = 0x00000001; +//static constexpr uint16_t SWITCH_LENGTH = 1; +//static constexpr const char *TEST_BUNDLE_NAME = "TestApplication"; +//static constexpr const char *TEST_STORE_NAME = "TestStore"; +// +//class DeviceChangeListenerTest : public AppDeviceChangeListener { +//public: +// void OnDeviceChanged(const DeviceInfo &info, const DeviceChangeType &type) const override {} +// void OnSessionReady(const DeviceInfo &info, int32_t errCode) const override; +// void ResetReadyFlag(); +// +// mutable int32_t bindResult_; +// mutable bool isReady_ = false; +//}; +// +//void DeviceChangeListenerTest::OnSessionReady(const DeviceInfo &info, int32_t errCode) const +//{ +// (void)info; +// bindResult_ = errCode; +// isReady_ = true; +//} +// +//void DeviceChangeListenerTest::ResetReadyFlag() +//{ +// isReady_ = false; +//} +// +//class AppDataChangeListenerTest : public AppDataChangeListener { +//public: +// void OnMessage(const DeviceInfo &info, const uint8_t *ptr, const int size, const PipeInfo &pipeInfo) const override +// { +// } +//}; +// +//class SoftBusAdapterStandardTest : public testing::Test { +//public: +// static void SetUpTestCase(void); +// static void TearDownTestCase(void); +// void SetUp() {} +// void TearDown(); +// +// void ProcessBroadcastMsg(const std::string &device, const LevelInfo &levelInfo); +// static void ConfigSendParameters(bool isCancel); +// +// mutable bool dataLevelResult_ = false; +// +// static std::shared_ptr executors_; +// static std::shared_ptr softBusAdapter_; +// static std::shared_ptr connectManager_; +// static DeviceChangeListenerTest deviceListener_; +// static AppDataChangeListenerTest dataChangeListener_; +// static PipeInfo pipeInfo_; +// static DeviceId deviceId_; +// static ExtraDataInfo extraInfo_; +// static DataInfo dataInfo_; +// static MessageInfo msgInfo_; +// static LevelInfo sendLevelInfo_; +// static LevelInfo receiveLevelInfo_; +// static std::string foregroundUserId_; +// static DeviceInfo localDeviceInfo_; +// static DeviceInfo remoteDeviceInfo_; +// static std::shared_ptr dbStoreMock_; +//}; +// +//std::shared_ptr SoftBusAdapterStandardTest::executors_; +//std::shared_ptr SoftBusAdapterStandardTest::softBusAdapter_; +//std::shared_ptr SoftBusAdapterStandardTest::connectManager_; +//DeviceChangeListenerTest SoftBusAdapterStandardTest::deviceListener_; +//AppDataChangeListenerTest SoftBusAdapterStandardTest::dataChangeListener_; +//PipeInfo SoftBusAdapterStandardTest::pipeInfo_; +//DeviceId SoftBusAdapterStandardTest::deviceId_; +//ExtraDataInfo SoftBusAdapterStandardTest::extraInfo_; +//DataInfo SoftBusAdapterStandardTest::dataInfo_; +//MessageInfo SoftBusAdapterStandardTest::msgInfo_; +//LevelInfo SoftBusAdapterStandardTest::sendLevelInfo_; +//LevelInfo SoftBusAdapterStandardTest::receiveLevelInfo_; +//std::string SoftBusAdapterStandardTest::foregroundUserId_; +//DeviceInfo SoftBusAdapterStandardTest::localDeviceInfo_; +//DeviceInfo SoftBusAdapterStandardTest::remoteDeviceInfo_; +//std::shared_ptr SoftBusAdapterStandardTest::dbStoreMock_; +// +//void SoftBusAdapterStandardTest::SetUpTestCase(void) +//{ +// connectManager_ = ConnectManager::GetInstance(); +// softBusAdapter_ = SoftBusAdapter::GetInstance(); +// +// CommunicatorContext::GetInstance().RegSessionListener(&deviceListener_); +// +// executors_ = std::make_shared(THREAD_MAX, THREAD_MIN); +// CommunicatorContext::GetInstance().SetThreadPool(executors_); +// +// dbStoreMock_ = std::make_shared(); +// MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); +// +// localDeviceInfo_ = DeviceManagerAdapter::GetInstance().GetLocalDevice(); +// auto remoteDeviceInfos = DeviceManagerAdapter::GetInstance().GetRemoteDevices(); +// if (!remoteDeviceInfos.empty()) { +// remoteDeviceInfo_ = remoteDeviceInfos[0]; +// } +// +// int userId = 0; +// AccountDelegate::GetInstance()->QueryForegroundUserId(userId); +// foregroundUserId_ = std::to_string(userId); +//} +// +//void SoftBusAdapterStandardTest::TearDownTestCase(void) +//{ +// CommunicatorContext::GetInstance().UnRegSessionListener(&deviceListener_); +//} +// +//void SoftBusAdapterStandardTest::TearDown() +//{ +// softBusAdapter_->connects_.Clear(); +// ConfigSendParameters(true); +//} +// +//void SoftBusAdapterStandardTest::ConfigSendParameters(bool isCancel) +//{ +// deviceId_.deviceId = isCancel ? "" : remoteDeviceInfo_.uuid; +// +// extraInfo_.userId = isCancel ? "" : foregroundUserId_; +// extraInfo_.bundleName = isCancel ? "" : TEST_BUNDLE_NAME; +// extraInfo_.storeId = isCancel ? "" : TEST_STORE_NAME; +// +// dataInfo_.extraInfo.userId = isCancel ? "" : foregroundUserId_; +// dataInfo_.extraInfo.appId = isCancel ? "" : TEST_BUNDLE_NAME; +// dataInfo_.extraInfo.storeId = isCancel ? "" : TEST_STORE_NAME; +// +// StoreMetaData localMetaData; +// localMetaData.deviceId = localDeviceInfo_.uuid; +// localMetaData.user = foregroundUserId_; +// localMetaData.bundleName = TEST_BUNDLE_NAME; +// localMetaData.storeId = TEST_STORE_NAME; +// +// StoreMetaData remoteMetaData; +// remoteMetaData.deviceId = remoteDeviceInfo_.uuid; +// remoteMetaData.user = foregroundUserId_; +// remoteMetaData.bundleName = TEST_BUNDLE_NAME; +// remoteMetaData.storeId = TEST_STORE_NAME; +// +// if (isCancel) { +// MetaDataManager::GetInstance().DelMeta(TEST_BUNDLE_NAME, true); +// MetaDataManager::GetInstance().DelMeta(localMetaData.GetKeyWithoutPath()); +// MetaDataManager::GetInstance().DelMeta(remoteMetaData.GetKeyWithoutPath()); +// } else { +// AppIDMetaData appIdMeta; +// appIdMeta.appId = TEST_BUNDLE_NAME; +// appIdMeta.bundleName = TEST_BUNDLE_NAME; +// MetaDataManager::GetInstance().SaveMeta(TEST_BUNDLE_NAME, appIdMeta, true); +// MetaDataManager::GetInstance().SaveMeta(localMetaData.GetKeyWithoutPath(), localMetaData); +// MetaDataManager::GetInstance().SaveMeta(remoteMetaData.GetKeyWithoutPath(), remoteMetaData); +// } +//} +// +//void SoftBusAdapterStandardTest::ProcessBroadcastMsg(const std::string &device, const LevelInfo &levelInfo) +//{ +// (void)device; +// receiveLevelInfo_ = levelInfo; +// dataLevelResult_ = true; +//} +// +///** +//* @tc.name: SessionServerTest001 +//* @tc.desc: create and remove session server +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, SessionServerTest001, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_SOCKET); +// auto result = softBusAdapter_->CreateSessionServerAdapter(""); +// ASSERT_NE(result, 0); +// +// ConfigSocketId(VALID_SOCKET); +// result = softBusAdapter_->CreateSessionServerAdapter(""); +// ASSERT_EQ(result, 0); +// +// result = softBusAdapter_->RemoveSessionServerAdapter(""); +// ASSERT_EQ(result, 0); +//} +// +///** +//* @tc.name: WatchDataChangeTest001 +//* @tc.desc: watch and unwatch data change +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, WatchDataChangeTest001, TestSize.Level1) +//{ +// auto status = softBusAdapter_->StartWatchDataChange(nullptr, pipeInfo_); +// ASSERT_EQ(status, Status::INVALID_ARGUMENT); +// +// status = softBusAdapter_->StartWatchDataChange(&dataChangeListener_, pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +// +// status = softBusAdapter_->StartWatchDataChange(&dataChangeListener_, pipeInfo_); +// ASSERT_EQ(status, Status::ERROR); +// +// status = softBusAdapter_->StopWatchDataChange(nullptr, pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +// +// status = softBusAdapter_->StopWatchDataChange(nullptr, pipeInfo_); +// ASSERT_EQ(status, Status::ERROR); +//} +// +///** +//* @tc.name: SendDataTest001 +//* @tc.desc: send data fail with invalid param +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, SendDataTest001, TestSize.Level1) +//{ +// auto result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::ERROR); +// +// deviceId_.deviceId = remoteDeviceInfo_.uuid; +// result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::ERROR); +// +// dataInfo_.extraInfo.userId = foregroundUserId_; +// result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::ERROR); +// +// dataInfo_.extraInfo.appId = TEST_BUNDLE_NAME; +// result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::ERROR); +// +// dataInfo_.extraInfo.storeId = TEST_STORE_NAME; +// result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::ERROR); +// +// AppIDMetaData appIdMeta; +// appIdMeta.appId = TEST_BUNDLE_NAME; +// appIdMeta.bundleName = TEST_BUNDLE_NAME; +// MetaDataManager::GetInstance().SaveMeta(TEST_BUNDLE_NAME, appIdMeta, true); +// +// result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::ERROR); +//} +// +///** +//* @tc.name: SendDataTest002 +//* @tc.desc: send data with bind fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, SendDataTest002, TestSize.Level1) +//{ +// ConfigSendParameters(false); +// ConfigSocketId(INVALID_MTU_SOCKET); +// +// auto result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::RATE_LIMIT); +// while (!(deviceListener_.isReady_)) { +// std::this_thread::sleep_for(std::chrono::seconds(1)); +// } +// ASSERT_NE(deviceListener_.bindResult_, 0); +// +// deviceListener_.ResetReadyFlag(); +//} +// +///** +//* @tc.name: SendDataTest003 +//* @tc.desc: send data with bind success +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, SendDataTest003, TestSize.Level1) +//{ +// ConfigSendParameters(false); +// ConfigSocketId(VALID_SOCKET); +// +// auto res = softBusAdapter_->CreateSessionServerAdapter(""); +// ASSERT_EQ(res, 0); +// +// auto result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::RATE_LIMIT); +// while (!(deviceListener_.isReady_)) { +// std::this_thread::sleep_for(std::chrono::seconds(1)); +// } +// ASSERT_EQ(deviceListener_.bindResult_, 0); +// +// uint32_t mtuBuffer; +// GetMtuSize(VALID_SOCKET, &mtuBuffer); +// auto mtuSize = softBusAdapter_->GetMtuSize(deviceId_); +// ASSERT_EQ(mtuSize, mtuBuffer); +// +// auto timeOut = softBusAdapter_->GetTimeout(deviceId_); +// ASSERT_NE(timeOut, 0); +// +// result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::SUCCESS); +// +// std::this_thread::sleep_for(std::chrono::seconds(10)); +// mtuSize = softBusAdapter_->GetMtuSize(deviceId_); +// ASSERT_NE(mtuSize, mtuBuffer); +//} +// +///** +//* @tc.name: ReuseConnectTest001 +//* @tc.desc: reuse connect fail with invalid parameter +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, ReuseConnectTest001, TestSize.Level1) +//{ +// auto result = softBusAdapter_->ReuseConnect(pipeInfo_, deviceId_, extraInfo_); +// ASSERT_EQ(result, Status::NOT_SUPPORT); +// +// deviceId_.deviceId = remoteDeviceInfo_.uuid; +// extraInfo_.userId = foregroundUserId_; +// result = softBusAdapter_->ReuseConnect(pipeInfo_, deviceId_, extraInfo_); +// ASSERT_EQ(result, Status::ERROR); +// +// extraInfo_.bundleName = TEST_BUNDLE_NAME; +// result = softBusAdapter_->ReuseConnect(pipeInfo_, deviceId_, extraInfo_); +// ASSERT_EQ(result, Status::ERROR); +// +// extraInfo_.storeId = TEST_STORE_NAME; +// result = softBusAdapter_->ReuseConnect(pipeInfo_, deviceId_, extraInfo_); +// ASSERT_EQ(result, Status::ERROR); +//} +// +///** +//* @tc.name: ReuseConnectTest002 +//* @tc.desc: reuse connect fail with bind fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, ReuseConnectTest002, TestSize.Level1) +//{ +// ConfigSendParameters(false); +// ConfigSocketId(INVALID_MTU_SOCKET); +// +// auto result = softBusAdapter_->ReuseConnect(pipeInfo_, deviceId_, extraInfo_); +// ASSERT_EQ(result, Status::NETWORK_ERROR); +//} +// +///** +//* @tc.name: ReuseConnectTest003 +//* @tc.desc: reuse connect success +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, ReuseConnectTest003, TestSize.Level1) +//{ +// ConfigSendParameters(false); +// ConfigSocketId(VALID_SOCKET); +// +// auto res = softBusAdapter_->CreateSessionServerAdapter(""); +// ASSERT_EQ(res, 0); +// +// auto result = softBusAdapter_->ReuseConnect(pipeInfo_, deviceId_, extraInfo_); +// ASSERT_EQ(result, Status::SUCCESS); +// +// std::this_thread::sleep_for(std::chrono::seconds(10)); +//} +// +///** +//* @tc.name: IsSameStartedOnPeerTest001 +//* @tc.desc: test IsSameStartedOnPeer +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, IsSameStartedOnPeerTest001, TestSize.Level1) +//{ +// auto result = softBusAdapter_->IsSameStartedOnPeer(pipeInfo_, deviceId_); +// ASSERT_TRUE(result); +//} +// +///** +//* @tc.name: ListenBroadcastTest001 +//* @tc.desc: listen broadcast test +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, ListenBroadcastTest001, TestSize.Level1) +//{ +// ConfigReturnCode(SoftBusErrNo::SOFTBUS_ERROR); +// auto status = softBusAdapter_->ListenBroadcastMsg(pipeInfo_, nullptr); +// ASSERT_NE(status, 0); +// +// ConfigReturnCode(SoftBusErrNo::SOFTBUS_OK); +// auto dataLevelListener = [this](const std::string &device, const LevelInfo &levelInfo) { +// ProcessBroadcastMsg(device, levelInfo); +// }; +// status = softBusAdapter_->ListenBroadcastMsg(pipeInfo_, dataLevelListener); +// ASSERT_EQ(status, 0); +// +// status = softBusAdapter_->ListenBroadcastMsg(pipeInfo_, dataLevelListener); +// ASSERT_NE(status, 0); +//} +// +///** +//* @tc.name: BroadcastTest001 +//* @tc.desc: broadcast msg fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, BroadcastTest001, TestSize.Level1) +//{ +// ConfigReturnCode(SoftBusErrNo::SOFTBUS_FUNC_NOT_SUPPORT); +// auto status = softBusAdapter_->Broadcast(pipeInfo_, sendLevelInfo_); +// ASSERT_EQ(status, Status::NOT_SUPPORT_BROADCAST); +// +// ConfigReturnCode(SoftBusErrNo::SOFTBUS_ERROR); +// status = softBusAdapter_->Broadcast(pipeInfo_, sendLevelInfo_); +// ASSERT_EQ(status, Status::ERROR); +//} +// +///** +//* @tc.name: BroadcastTest002 +//* @tc.desc: broadcast msg success and receive msg +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, BroadcastTest002, TestSize.Level1) +//{ +// auto dataLevelListener = [this](const std::string &device, const LevelInfo &levelInfo) { +// ProcessBroadcastMsg(device, levelInfo); +// }; +// ConfigReturnCode(SoftBusErrNo::SOFTBUS_OK); +// (void)softBusAdapter_->ListenBroadcastMsg(pipeInfo_, dataLevelListener); +// +// sendLevelInfo_.dynamic = DYNAMIC_LEVEL; +// sendLevelInfo_.statics = STATIC_LEVEL; +// sendLevelInfo_.switches = SWITCH_VALUE; +// sendLevelInfo_.switchesLen = SWITCH_LENGTH; +// +// auto status = softBusAdapter_->Broadcast(pipeInfo_, sendLevelInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +// ASSERT_EQ(receiveLevelInfo_.dynamic, sendLevelInfo_.dynamic); +// ASSERT_EQ(receiveLevelInfo_.statics, sendLevelInfo_.statics); +// ASSERT_EQ(receiveLevelInfo_.switches, sendLevelInfo_.switches); +// ASSERT_EQ(receiveLevelInfo_.switchesLen, sendLevelInfo_.switchesLen); +//} +//} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/softbus_client_test.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/softbus_client_test.cpp index 3ba198442597f4c79adeaf845e4b802a0910dff3..f24a8bedeab74e999f373f08b28061a5b30fed45 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/softbus_client_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/softbus_client_test.cpp @@ -1,189 +1,371 @@ -/* - * Copyright (c) 2025 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 -#include -#include -#include -#include "softbus_client.h" -#include "types.h" - - -namespace OHOS::Test { -using namespace testing::ext; -using namespace OHOS::AppDistributedKv; -using PipeInfo = OHOS::AppDistributedKv::PipeInfo; -constexpr int32_t SOFTBUS_OK = 0; - -class SoftbusClientTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp() {} - void TearDown() {} - - static std::shared_ptr client; -}; - -std::shared_ptr SoftbusClientTest::client = nullptr; - -void SoftbusClientTest::SetUpTestCase(void) -{ - PipeInfo pipeInfo; - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - DeviceId id = {"DeviceId"}; - client = std::make_shared(pipeInfo, id); -} - -void SoftbusClientTest::TearDownTestCase(void) -{ - client = nullptr; -} - -/** -* @tc.name: SendData -* @tc.desc: SendData test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(SoftbusClientTest, SendData, TestSize.Level0) -{ - ASSERT_NE(client, nullptr); - std::string content = "Helloworlds"; - const uint8_t *data = reinterpret_cast(content.c_str()); - DataInfo info = { const_cast(data), static_cast(content.length())}; - ISocketListener *listener = nullptr; - auto status = client->SendData(info, listener); - EXPECT_EQ(status, Status::ERROR); - client->bindState_ = 0; - status = client->SendData(info, listener); - EXPECT_EQ(status, Status::ERROR); -} - -/** -* @tc.name: OpenConnect -* @tc.desc: OpenConnect test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(SoftbusClientTest, OpenConnect, TestSize.Level0) -{ - ASSERT_NE(client, nullptr); - ISocketListener *listener = nullptr; - client->bindState_ = 0; - auto status = client->OpenConnect(listener); - EXPECT_EQ(status, Status::SUCCESS); - client->bindState_ = 1; - client->isOpening_.store(true); - status = client->OpenConnect(listener); - EXPECT_EQ(status, Status::RATE_LIMIT); - client->isOpening_.store(false); - status = client->OpenConnect(listener); - EXPECT_EQ(status, Status::NETWORK_ERROR); -} - -/** -* @tc.name: CheckStatus -* @tc.desc: CheckStatus test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(SoftbusClientTest, CheckStatus, TestSize.Level0) -{ - ASSERT_NE(client, nullptr); - client->bindState_ = 0; - auto status = client->CheckStatus(); - EXPECT_EQ(status, Status::SUCCESS); - client->bindState_ = -1; - client->isOpening_.store(true); - status = client->CheckStatus(); - EXPECT_EQ(status, Status::RATE_LIMIT); - client->isOpening_.store(false); - status = client->CheckStatus(); - EXPECT_EQ(status, Status::ERROR); -} - -/** -* @tc.name: Open -* @tc.desc: Open test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(SoftbusClientTest, Open, TestSize.Level0) -{ - ASSERT_NE(client, nullptr); - ISocketListener *listener = nullptr; - auto status = client->Open(1, AppDistributedKv::SoftBusClient::QOS_BR, listener, false); - EXPECT_NE(status, SOFTBUS_OK); -} - -/** -* @tc.name: UpdateExpireTime -* @tc.desc: UpdateExpireTime test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(SoftbusClientTest, UpdateExpireTime, TestSize.Level0) -{ - ASSERT_NE(client, nullptr); - client->type_ = AppDistributedKv::SoftBusClient::QOS_BR; - auto expireTime = client->CalcExpireTime(); - EXPECT_NO_FATAL_FAILURE(client->UpdateExpireTime(true)); - EXPECT_LT(expireTime, client->expireTime_); - EXPECT_NO_FATAL_FAILURE(client->UpdateExpireTime(false)); - EXPECT_LT(expireTime, client->expireTime_); -} - -/** -* @tc.name: UpdateBindInfo -* @tc.desc: UpdateBindInfo test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(SoftbusClientTest, UpdateBindInfo, TestSize.Level0) -{ - ASSERT_NE(client, nullptr); - EXPECT_NO_FATAL_FAILURE(client->UpdateBindInfo(1, 1, AppDistributedKv::SoftBusClient::QOS_BR, false)); - EXPECT_NO_FATAL_FAILURE(client->UpdateBindInfo(1, 1, AppDistributedKv::SoftBusClient::QOS_BR, true)); -} - -/** -* @tc.name: ReuseConnect -* @tc.desc: ReuseConnect test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(SoftbusClientTest, ReuseConnect, TestSize.Level0) -{ - ASSERT_NE(client, nullptr); - ISocketListener *listener = nullptr; - client->bindState_ = 0; - auto status = client->ReuseConnect(listener); - EXPECT_EQ(status, Status::SUCCESS); - client->bindState_ = -1; - client->isOpening_.store(true); - status = client->ReuseConnect(listener); - EXPECT_EQ(status, Status::NETWORK_ERROR); -} -} // namespace OHOS::Test \ No newline at end of file +///* +// * Copyright (c) 2025 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 "softbus_client.h" +// +//#include +// +//#include "app_device_change_listener.h" +//#include "communicator_context.h" +//#include "executor_pool.h" +// +//namespace OHOS::Test { +//using namespace testing::ext; +//using namespace OHOS::AppDistributedKv; +//using namespace OHOS::DistributedData; +// +//static constexpr int32_t DEFAULT_SOCKET = -1; +//static constexpr int32_t INVALID_SOCKET = 0; +//static constexpr int32_t INVALID_SET_SOCKET = 1; +//static constexpr int32_t INVALID_BIND_SOCKET = 2; +//static constexpr int32_t INVALID_MTU_SOCKET = 3; +//static constexpr int32_t INVALID_SEND_SOCKET = 4; +//static constexpr int32_t VALID_SOCKET = 5; +//static constexpr size_t THREAD_MIN = 0; +//static constexpr size_t THREAD_MAX = 1; +//static constexpr const char* PIP_ID = "SoftBusClientTest"; +//static constexpr const char* UUID = "uuid"; +//static constexpr const char* NETWORK_ID = "network_id"; +//static constexpr const char* INVALID_NETWORK_ID = "invalid_network_id"; +// +//class DeviceChangeListenerTest : public AppDeviceChangeListener { +//public: +// void OnDeviceChanged(const DeviceInfo &info, const DeviceChangeType &type) const override {} +// void OnSessionReady(const DeviceInfo &info, int32_t errCode) const override; +// void ResetReadyFlag(); +// +// mutable int32_t bindResult_; +// mutable bool isReady_ = false; +//}; +// +//void DeviceChangeListenerTest::OnSessionReady(const DeviceInfo &info, int32_t errCode) const +//{ +// (void)info; +// bindResult_ = errCode; +// isReady_ = true; +//} +// +//void DeviceChangeListenerTest::ResetReadyFlag() +//{ +// isReady_ = false; +//} +// +//class SoftBusClientTest : public testing::Test { +//public: +// static void SetUpTestCase(void); +// static void TearDownTestCase(void); +// void SetUp(); +// void TearDown() {} +// +// static PipeInfo pipeInfo_; +// static DeviceId deviceId_; +// static SessionAccessInfo accessInfo_; +// static DeviceChangeListenerTest deviceListener_; +// static std::shared_ptr executors_; +//}; +// +//PipeInfo SoftBusClientTest::pipeInfo_; +//DeviceId SoftBusClientTest::deviceId_; +//SessionAccessInfo SoftBusClientTest::accessInfo_; +//DeviceChangeListenerTest SoftBusClientTest::deviceListener_; +//std::shared_ptr SoftBusClientTest::executors_; +// +//void SoftBusClientTest::SetUpTestCase(void) +//{ +// pipeInfo_.pipeId = PIP_ID; +// deviceId_.deviceId = UUID; +// CommunicatorContext::GetInstance().RegSessionListener(&deviceListener_); +// executors_ = std::make_shared(THREAD_MAX, THREAD_MIN); +//} +// +//void SoftBusClientTest::TearDownTestCase(void) +//{ +// CommunicatorContext::GetInstance().UnRegSessionListener(&deviceListener_); +//} +// +//void SoftBusClientTest::SetUp() +//{ +// CommunicatorContext::GetInstance().SetThreadPool(executors_); +//} +// +///** +//* @tc.name: OperatorTest001 +//* @tc.desc: operator test +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, OperatorTest001, TestSize.Level1) +//{ +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_HML, +// accessInfo_); +// ASSERT_TRUE(*connect == UUID); +// ASSERT_TRUE(*connect == DEFAULT_SOCKET); +// ASSERT_EQ(connect->GetSocket(), DEFAULT_SOCKET); +//} +// +///** +//* @tc.name: NetworkIdTest001 +//* @tc.desc: network id test +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, NetworkIdTest001, TestSize.Level1) +//{ +// auto connect = std::make_shared(pipeInfo_, deviceId_, INVALID_NETWORK_ID, SoftBusClient::QOS_HML, +// accessInfo_); +// auto networkId = connect->GetNetworkId(); +// ASSERT_EQ(networkId, INVALID_NETWORK_ID); +// connect->UpdateNetworkId(NETWORK_ID); +// networkId = connect->GetNetworkId(); +// ASSERT_EQ(networkId, NETWORK_ID); +//} +// +///** +//* @tc.name: OpenConnectTest001 +//* @tc.desc: open connect fail and socketId is invalid +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, OpenConnectTest001, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_HML, +// accessInfo_); +// auto status = connect->OpenConnect(nullptr); +// ASSERT_EQ(status, Status::NETWORK_ERROR); +//} +// +///** +//* @tc.name: OpenConnectTest002 +//* @tc.desc: open connect fail and socket is valid but set access info fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, OpenConnectTest002, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_SET_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_HML, +// accessInfo_); +// auto status = connect->OpenConnect(nullptr); +// ASSERT_EQ(status, Status::NETWORK_ERROR); +//} +// +///** +//* @tc.name: OpenConnectTest003 +//* @tc.desc: open connect fail and executor pool is nullptr +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, OpenConnectTest003, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_BIND_SOCKET); +// CommunicatorContext::GetInstance().SetThreadPool(nullptr); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_HML, +// accessInfo_); +// auto status = connect->OpenConnect(nullptr); +// ASSERT_EQ(status, Status::NETWORK_ERROR); +//} +// +///** +//* @tc.name: OpenConnectTest004 +//* @tc.desc: open connect fail and socket is valid but bind fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, OpenConnectTest004, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_BIND_SOCKET); +// +// accessInfo_.isOHType = false; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_BR, +// accessInfo_); +// auto status = connect->OpenConnect(nullptr); +// ASSERT_EQ(status, Status::RATE_LIMIT); +// while (!(deviceListener_.isReady_)) { +// sleep(1); +// } +// deviceListener_.ResetReadyFlag(); +// auto result = deviceListener_.bindResult_; +// ASSERT_NE(result, 0); +// +// accessInfo_.isOHType = true; +// auto ohConnect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_HML, +// accessInfo_); +// status = ohConnect->OpenConnect(nullptr); +// ASSERT_EQ(status, Status::RATE_LIMIT); +// while (!(deviceListener_.isReady_)) { +// sleep(1); +// } +// deviceListener_.ResetReadyFlag(); +// result = deviceListener_.bindResult_; +// ASSERT_NE(result, 0); +//} +// +///** +//* @tc.name: OpenConnectTest005 +//* @tc.desc: open connect fail and bind success but get mtu fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, OpenConnectTest005, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_MTU_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_HML, +// accessInfo_); +// auto status = connect->OpenConnect(nullptr); +// ASSERT_EQ(status, Status::RATE_LIMIT); +// while (!(deviceListener_.isReady_)) { +// sleep(1); +// } +// deviceListener_.ResetReadyFlag(); +// auto result = deviceListener_.bindResult_; +// ASSERT_NE(result, 0); +//} +// +///** +//* @tc.name: OpenConnectTest006 +//* @tc.desc: open connect success +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, OpenConnectTest006, TestSize.Level1) +//{ +// ConfigSocketId(VALID_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_HML, +// accessInfo_); +// auto status = connect->OpenConnect(nullptr); +// ASSERT_EQ(status, Status::RATE_LIMIT); +// while (!(deviceListener_.isReady_)) { +// sleep(1); +// } +// deviceListener_.ResetReadyFlag(); +// auto result = deviceListener_.bindResult_; +// ASSERT_EQ(result, 0); +// status = connect->CheckStatus(); +// ASSERT_EQ(status, Status::SUCCESS); +// +// status = connect->OpenConnect(nullptr); +// ASSERT_EQ(status, Status::SUCCESS); +//} +// +///** +//* @tc.name: ReuseConnectTest001 +//* @tc.desc: reuse connect fail and socketId is invalid +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, ReuseConnectTest001, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_REUSE, +// accessInfo_); +// auto status = connect->ReuseConnect(nullptr); +// ASSERT_EQ(status, Status::NETWORK_ERROR); +//} +// +///** +//* @tc.name: ReuseConnectTest002 +//* @tc.desc: reuse connect fail and socket is valid but set access info fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, ReuseConnectTest002, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_SET_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_REUSE, +// accessInfo_); +// auto status = connect->ReuseConnect(nullptr); +// ASSERT_EQ(status, Status::NETWORK_ERROR); +//} +// +///** +//* @tc.name: ReuseConnectTest003 +//* @tc.desc: reuse connect fail and socket is valid but bind fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, ReuseConnectTest003, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_BIND_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_REUSE, +// accessInfo_); +// auto status = connect->ReuseConnect(nullptr); +// ASSERT_EQ(status, Status::NETWORK_ERROR); +//} +// +///** +//* @tc.name: ReuseConnectTest004 +//* @tc.desc: reuse connect fail and bind success but get mtu fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, ReuseConnectTest004, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_MTU_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_REUSE, +// accessInfo_); +// auto status = connect->ReuseConnect(nullptr); +// ASSERT_EQ(status, Status::NETWORK_ERROR); +//} +// +///** +//* @tc.name: ReuseConnectTest005 +//* @tc.desc: reuse connect success +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, ReuseConnectTest005, TestSize.Level1) +//{ +// ConfigSocketId(VALID_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_REUSE, +// accessInfo_); +// auto status = connect->ReuseConnect(nullptr); +// ASSERT_EQ(status, Status::SUCCESS); +//} +// +///** +//* @tc.name: SendDataTest001 +//* @tc.desc: send data fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, SendDataTest001, TestSize.Level1) +//{ +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_REUSE, +// accessInfo_); +// DataInfo dataInfo; +// auto status = connect->SendData(dataInfo); +// ASSERT_NE(status, Status::SUCCESS); +// +// ConfigSocketId(INVALID_SEND_SOCKET); +// status = connect->ReuseConnect(nullptr); +// ASSERT_EQ(status, Status::SUCCESS); +// status = connect->SendData(dataInfo); +// ASSERT_NE(status, Status::SUCCESS); +//} +// +///** +//* @tc.name: SendDataTest002 +//* @tc.desc: send data success +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, SendDataTest002, TestSize.Level1) +//{ +// ConfigSocketId(VALID_SOCKET); +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_REUSE, +// accessInfo_); +// DataInfo dataInfo; +// auto status = connect->ReuseConnect(nullptr); +// ASSERT_EQ(status, Status::SUCCESS); +// status = connect->SendData(dataInfo); +// ASSERT_EQ(status, Status::SUCCESS); +//} +//} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/dfx/BUILD.gn index 483c454494fc72c8e4bb1717599f87747a83ce5c..1b2cc6e710114435a2a0126c4628a91ae23ddab8 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/BUILD.gn @@ -43,18 +43,14 @@ ohos_source_set("distributeddata_dfx") { "./src/fault", "./src/statistic", "../include/dfx", - "../include/log", - "../include/utils", - "../include/communicator", - "${data_service_path}/framework/include/dfx", - "${data_service_path}/framework/include/utils", ] - cflags_cc = [ - "-fvisibility=hidden", - "-fstack-protector-strong", - ] + cflags_cc = [ "-fvisibility=hidden" ] + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/adapter/communicator:distributeddata_communicator", + ] external_deps = [ "c_utils:utils", "device_manager:devicemanagersdk", diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/cloud_sync_fault_impl.h b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/cloud_sync_fault_impl.h index 89ee3d5b4100f0f554615722b1b6a2537f5b0716..54e6b60b11a3aeaf5490cd6aaefeb34b1176d9f2 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/cloud_sync_fault_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/cloud_sync_fault_impl.h @@ -16,9 +16,9 @@ #ifndef DISTRIBUTEDDATAMGR_DATAMGR_SERVICE_CLOUD_SYNC_FAULT_IMPL_H #define DISTRIBUTEDDATAMGR_DATAMGR_SERVICE_CLOUD_SYNC_FAULT_IMPL_H +#include "dfx/dfx_types.h" #include "dfx/fault_reporter.h" #include "hiview_adapter.h" -#include "dfx/dfx_types.h" namespace OHOS { namespace DistributedDataDfx { @@ -43,6 +43,6 @@ public: private: std::shared_ptr executors_; }; -} // namespace DistributedDataDfx -} // namespace OHOS +} // namespace DistributedDataDfx +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_DATAMGR_SERVICE_CLOUD_SYNC_FAULT_IMPL_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/communication_fault_impl.h b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/communication_fault_impl.h index bf25665aad94f0f10dcba809c6147d642b881b6c..19673336e917fbd758beb6801d560e9106c560b5 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/communication_fault_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/communication_fault_impl.h @@ -16,9 +16,9 @@ #ifndef DISTRIBUTEDDATAMGR_COMMUNICATION_FAULT_IMPL_H #define DISTRIBUTEDDATAMGR_COMMUNICATION_FAULT_IMPL_H +#include "dfx/dfx_types.h" #include "dfx/fault_reporter.h" #include "hiview_adapter.h" -#include "dfx/dfx_types.h" namespace OHOS { namespace DistributedDataDfx { @@ -39,6 +39,6 @@ public: private: std::shared_ptr executors_; }; -} // namespace DistributedDataDfx -} // namespace OHOS +} // namespace DistributedDataDfx +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_COMMUNICATION_FAULT_IMPL_H diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/database_fault_impl.h b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/database_fault_impl.h index 755d031834a30d1f1778c6784008b9ed386f2edf..1185dce0e6bd0c470dad02751f4910bf04a2bfb3 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/database_fault_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/database_fault_impl.h @@ -38,7 +38,7 @@ public: private: std::shared_ptr executors_; }; -} // namespace DistributedDataDfx -} // namespace OHOS +} // namespace DistributedDataDfx +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_DATABASE_FAULT_IMPL_H diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/runtime_fault_impl.h b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/runtime_fault_impl.h index ce2fa7c634729ecd2b1cc136099a047bbb516e57..ae7f1a3e88a53f98f8e75bb202914bf98c626b01 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/runtime_fault_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/runtime_fault_impl.h @@ -15,8 +15,8 @@ #ifndef DISTRIBUTEDDATAMGR_RUNTIME_FAULT_IMPL_H #define DISTRIBUTEDDATAMGR_RUNTIME_FAULT_IMPL_H -#include "hiview_adapter.h" #include "dfx/fault_reporter.h" +#include "hiview_adapter.h" namespace OHOS { namespace DistributedDataDfx { @@ -37,6 +37,6 @@ public: private: std::shared_ptr executors_; }; -} // namespace DistributedDataDfx -} // namespace OHOS +} // namespace DistributedDataDfx +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_RUNTIME_FAULT_IMPL_H diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/service_fault_impl.h b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/service_fault_impl.h index c627f53ed2080b982aac626f9e2cb10f294d624e..df665d0c2418d755386b47860c4ab9f7dfac3b7e 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/service_fault_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/service_fault_impl.h @@ -16,8 +16,8 @@ #ifndef DISTRIBUTEDDATAMGR_SERVICE_FAULT_IMPL_H #define DISTRIBUTEDDATAMGR_SERVICE_FAULT_IMPL_H -#include "hiview_adapter.h" #include "dfx/fault_reporter.h" +#include "hiview_adapter.h" namespace OHOS { namespace DistributedDataDfx { @@ -38,6 +38,6 @@ public: private: std::shared_ptr executors_; }; -} // namespace DistributedDataDfx -} // namespace OHOS +} // namespace DistributedDataDfx +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_SERVICE_FAULT_IMPL_H diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/hiview_adapter.cpp b/datamgr_service/services/distributeddataservice/adapter/dfx/src/hiview_adapter.cpp index c27789c7725dc3ae54bdab9d9d73910bc5a9c029..35e0ceaff77ffcbcc0885856e928c5e7046bbd41 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/hiview_adapter.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/hiview_adapter.cpp @@ -21,11 +21,12 @@ #include #include "log_print.h" +#include "utils/anonymous.h" #include "utils/time_utils.h" - namespace OHOS { namespace DistributedDataDfx { using namespace DistributedKv; +using Anonymous = DistributedData::Anonymous; namespace { constexpr const char *DATAMGR_DOMAIN = "DISTDATAMGR"; // fault key @@ -134,6 +135,7 @@ void HiViewAdapter::ReportDBFault(int dfxCode, const DBFaultMsg &msg, std::share return; } ExecutorPool::Task task([dfxCode, msg]() { + std::string storeId = Anonymous::Change(msg.storeId); struct HiSysEventParam params[] = { { .name = { *APP_ID }, .t = HISYSEVENT_STRING, @@ -141,7 +143,7 @@ void HiViewAdapter::ReportDBFault(int dfxCode, const DBFaultMsg &msg, std::share .arraySize = 0 }, { .name = { *STORE_ID }, .t = HISYSEVENT_STRING, - .v = { .s = const_cast(msg.storeId.c_str()) }, + .v = { .s = const_cast(storeId.c_str()) }, .arraySize = 0 }, { .name = { *MODULE_NAME }, .t = HISYSEVENT_STRING, @@ -171,6 +173,7 @@ void HiViewAdapter::ReportCommFault(int dfxCode, const CommFaultMsg &msg, std::s } ExecutorPool ::Task task([dfxCode, msg]() { std::string message; + std::string storeId = Anonymous::Change(msg.storeId); for (size_t i = 0; i < msg.deviceId.size(); i++) { message.append("No: ").append(std::to_string(i)) .append(" sync to device: ").append(msg.deviceId[i]) @@ -187,7 +190,7 @@ void HiViewAdapter::ReportCommFault(int dfxCode, const CommFaultMsg &msg, std::s .arraySize = 0 }, { .name = { *STORE_ID }, .t = HISYSEVENT_STRING, - .v = { .s = const_cast(msg.storeId.c_str()) }, + .v = { .s = const_cast(storeId.c_str()) }, .arraySize = 0 }, { .name = { *SYNC_ERROR_INFO }, .t = HISYSEVENT_STRING, @@ -243,6 +246,7 @@ void HiViewAdapter::ReportBehaviour(int dfxCode, const BehaviourMsg &msg, std::s } ExecutorPool::Task task([dfxCode, msg]() { std::string message; + std::string storeId = Anonymous::Change(msg.storeId); message.append("Behaviour type : ").append(std::to_string(static_cast(msg.behaviourType))) .append(" behaviour info : ").append(msg.extensionInfo); struct HiSysEventParam params[] = { @@ -256,7 +260,7 @@ void HiViewAdapter::ReportBehaviour(int dfxCode, const BehaviourMsg &msg, std::s .arraySize = 0 }, { .name = { *STORE_ID }, .t = HISYSEVENT_STRING, - .v = { .s = const_cast(msg.storeId.c_str()) }, + .v = { .s = const_cast(storeId.c_str()) }, .arraySize = 0 }, { .name = { *BEHAVIOUR_INFO }, .t = HISYSEVENT_STRING, @@ -302,7 +306,7 @@ void HiViewAdapter::ReportDbSize(const StatisticWrap &stat) if (!vh.CalcValueHash(stat.val.userId, userId)) { return; } - + std::string storeId = Anonymous::Change(stat.val.storeId); struct HiSysEventParam params[] = { { .name = { *USER_ID }, .t = HISYSEVENT_STRING, @@ -314,7 +318,7 @@ void HiViewAdapter::ReportDbSize(const StatisticWrap &stat) .arraySize = 0 }, { .name = { *STORE_ID }, .t = HISYSEVENT_STRING, - .v = { .s = const_cast(stat.val.storeId.c_str()) }, + .v = { .s = const_cast(storeId.c_str()) }, .arraySize = 0 }, { .name = { *DB_SIZE }, .t = HISYSEVENT_UINT64, .v = { .ui64 = dbSize }, .arraySize = 0 }, }; @@ -383,6 +387,7 @@ void HiViewAdapter::InvokeTraffic() if (!vh.CalcValueHash(kv.second.val.deviceId, deviceId)) { continue; } + std::string devId = Anonymous::Change(deviceId); struct HiSysEventParam params[] = { { .name = { *TAG }, .t = HISYSEVENT_STRING, .v = { .s = const_cast(POWERSTATS) }, .arraySize = 0 }, { .name = { *APP_ID }, @@ -391,7 +396,7 @@ void HiViewAdapter::InvokeTraffic() .arraySize = 0 }, { .name = { *DEVICE_ID }, .t = HISYSEVENT_STRING, - .v = { .s = const_cast(deviceId.c_str()) }, + .v = { .s = const_cast(devId.c_str()) }, .arraySize = 0 }, { .name = { *SEND_SIZE }, .t = HISYSEVENT_INT64, diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/reporter_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/dfx/src/reporter_impl.cpp index a03d476100329909adc7ece081f8ef180ec663df..a8b142fa7df7ab4880b1447809c381c9f4055d63 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/reporter_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/reporter_impl.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "dfx/reporter_impl.h" +#include "reporter_impl.h" #include "behaviour/behaviour_reporter_impl.h" #include "fault/cloud_sync_fault_impl.h" diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/api_performance_statistic_impl.h b/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/api_performance_statistic_impl.h index 8c44d269fcc7dbb3589f9719bf92c92f851e71e9..f5cdff361f66c317378047c593e181a17ab2c368 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/api_performance_statistic_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/api_performance_statistic_impl.h @@ -16,9 +16,9 @@ #ifndef DISTRIBUTEDDATAMGR_API_PERFORMANCE_STATISTIC_IMPL_H #define DISTRIBUTEDDATAMGR_API_PERFORMANCE_STATISTIC_IMPL_H +#include "dfx/dfx_types.h" #include "dfx/statistic_reporter.h" #include "hiview_adapter.h" -#include "dfx/dfx_types.h" namespace OHOS { namespace DistributedDataDfx { @@ -31,7 +31,6 @@ public: private: std::shared_ptr executors_; }; -} // namespace DistributedDataDfx -} // namespace OHOS +} // namespace DistributedDataDfx +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_API_PERFORMANCE_STATISTIC_IMPL_H - diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/traffic_statistic_impl.h b/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/traffic_statistic_impl.h index b7cac17f421a0bfd0692f78b222cd5e7d1584c7f..85238d9db32626e7adcea69dcc314e9ffa027e2d 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/traffic_statistic_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/traffic_statistic_impl.h @@ -30,6 +30,6 @@ public: private: std::shared_ptr executors_; }; -} // namespace DistributedDataDfx -} // namespace OHOS +} // namespace DistributedDataDfx +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_TRAFFIC_STATISTIC_IMPL_H diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/visit_statistic_impl.h b/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/visit_statistic_impl.h index c193a6599d45e51b2a085d1fccf170f209b564b3..9898ad546e5621f05f56d5ed7b3adfd8d39073fa 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/visit_statistic_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/visit_statistic_impl.h @@ -30,6 +30,6 @@ public: private: std::shared_ptr executors_; }; -} // namespace DistributedDataDfx -} // namespace OHOS +} // namespace DistributedDataDfx +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_VISIT_STATISTIC_IMPL_H diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/dfx/test/BUILD.gn index 78a3fa45b61c20bd967c6e9e912f88d87d399501..67f11fddb9b0cbfe3ecc0de756c135f609152872 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/test/BUILD.gn @@ -36,6 +36,7 @@ ohos_unittest("DistributeddataDfxMSTTest") { external_deps = [ "c_utils:utils", "datamgr_service:distributeddatasvcfwk", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", @@ -43,11 +44,7 @@ ohos_unittest("DistributeddataDfxMSTTest") { "openssl:libcrypto_shared", ] ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps = [ - "${data_service_path}/adapter/dfx:distributeddata_dfx", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - ] + deps = [ "${data_service_path}/adapter/dfx:distributeddata_dfx" ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } @@ -77,6 +74,7 @@ ohos_unittest("DistributeddataDfxUTTest") { external_deps = [ "c_utils:utils", "datamgr_service:distributeddatasvcfwk", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", @@ -87,8 +85,6 @@ ohos_unittest("DistributeddataDfxUTTest") { deps = [ "${data_service_path}/adapter/dfx:distributeddata_dfx", "${data_service_path}/adapter/utils:distributeddata_utils", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/distributeddata_dfx_mst_test.cpp b/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/distributeddata_dfx_mst_test.cpp index c5a67afe6e9cc8201f02d047f6114852b0610c64..5c0065d8e93b26c83bad82eb46db0889b83a7817 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/distributeddata_dfx_mst_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/distributeddata_dfx_mst_test.cpp @@ -15,7 +15,7 @@ #include #include -#include "reporter.h" +#include "dfx/reporter.h" using namespace testing::ext; using namespace OHOS::DistributedDataDfx; diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/distributeddata_dfx_ut_test.cpp b/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/distributeddata_dfx_ut_test.cpp index d7fed644ccdfb6ca8cc764d811e02c8a663eda21..4530a0032a4e5e50af27ef2c8ca2e50bd253d91b 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/distributeddata_dfx_ut_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/distributeddata_dfx_ut_test.cpp @@ -15,7 +15,7 @@ #include #include -#include "reporter.h" +#include "dfx/reporter.h" #include "fake_hiview.h" #include "value_hash.h" diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/fake/hiview/fake_hiview.cpp b/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/fake/hiview/fake_hiview.cpp index 1f58aa6703f96885bafbdcd8eddf090d564b49a3..b49734e0f317a763ff89b7a31e4c362c9794e494 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/fake/hiview/fake_hiview.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/fake/hiview/fake_hiview.cpp @@ -13,5 +13,5 @@ * limitations under the License. */ -#include "./include/fake_hiview.h" +#include "include/fake_hiview.h" std::map FakeHivew::fakeCache_; diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/hiview_adapter_dfx_test.cpp b/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/hiview_adapter_dfx_test.cpp index f26e70e901ac9445ebc181e7bdf7680cb266081e..f2198e83f2d6ad06af72d8bc2e67a6dd0f1fabc7 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/hiview_adapter_dfx_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/hiview_adapter_dfx_test.cpp @@ -15,11 +15,11 @@ #define LOG_TAG "HiViewAdapterDfxTest" #include "device_manager_adapter.h" -#include "dfx_types.h" +#include "dfx/dfx_types.h" +#include "dfx/radar_reporter.h" #include "gtest/gtest.h" #include "hiview_adapter.h" #include "log_print.h" -#include "radar_reporter.h" using namespace OHOS; using namespace testing; diff --git a/datamgr_service/services/distributeddataservice/adapter/include/communicator/commu_types.h b/datamgr_service/services/distributeddataservice/adapter/include/communicator/commu_types.h index 6b1f1af696dcb9482181dea2df903ce5f51913a8..f64fa0dc1f9abbd4696de10392ac362abace9ec6 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/communicator/commu_types.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/communicator/commu_types.h @@ -16,19 +16,12 @@ #ifndef OHOS_DISTRIBUTED_DATA_ADAPTER_COMMUNICATOR_COMMU_TYPES_H #define OHOS_DISTRIBUTED_DATA_ADAPTER_COMMUNICATOR_COMMU_TYPES_H #include +#include "device_manager/device_manager_types.h" #include "store_errno.h" #include "visibility.h" namespace OHOS::AppDistributedKv { using Status = DistributedKv::Status; -struct API_EXPORT DeviceInfo { - std::string uuid; - std::string udid; - std::string networkId; - std::string deviceName; - uint32_t deviceType; - int32_t osType; - int32_t authForm; -}; +using DeviceInfo = DistributedData::DeviceInfo; struct API_EXPORT AccessCaller { std::string accountId; @@ -59,9 +52,18 @@ enum RouteType : int32_t { BUTT, }; +struct ExtraDataInfo { + std::string userId; + std::string appId; + std::string bundleName; + std::string storeId; + uint32_t tokenId = 0; +}; + struct DataInfo { uint8_t *data; uint32_t length; + ExtraDataInfo extraInfo; }; struct API_EXPORT PipeInfo { @@ -99,5 +101,14 @@ struct API_EXPORT LevelInfo { uint32_t switches; uint16_t switchesLen; }; + +struct API_EXPORT SessionAccessInfo { + int32_t userId = -1; + std::string bundleName; + std::string storeId; + std::string accountId; + uint32_t tokenId = 0; + bool isOHType = true; +}; } #endif // OHOS_DISTRIBUTED_DATA_ADAPTER_COMMUNICATOR_COMMU_TYPES_H diff --git a/datamgr_service/services/distributeddataservice/adapter/include/communicator/communication_provider.h b/datamgr_service/services/distributeddataservice/adapter/include/communicator/communication_provider.h index 07cfb231c2ea71d112c192ee5f263d7a082ed778..32c5b761f6deeba36c87ed3b40fcee7a3393cc69 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/communicator/communication_provider.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/communicator/communication_provider.h @@ -66,7 +66,7 @@ public: virtual int32_t ListenBroadcastMsg(const PipeInfo &pipeInfo, std::function listener) = 0; - virtual Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId) = 0; + virtual Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, const ExtraDataInfo &extraInfo) = 0; }; } // namespace AppDistributedKv } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/adapter/include/communicator/communicator_context.h b/datamgr_service/services/distributeddataservice/adapter/include/communicator/communicator_context.h index ce09ab58a92c4e58d37bf62b8f497cbb7af93ecb..7b9ea464183ec8f5b2bdc6be27416bac69079909 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/communicator/communicator_context.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/communicator/communicator_context.h @@ -21,7 +21,6 @@ #include "commu_types.h" #include "concurrent_map.h" #include "visibility.h" -#include "iprocess_communicator.h" namespace OHOS::DistributedData { class API_EXPORT CommunicatorContext { 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 a50783ae1d148c07b41d3a1286ddf56959fdef71..575a2f3931a8b3435f3492cec42cc0823803810d 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 @@ -24,13 +24,14 @@ #include "concurrent_map.h" #include "device_manager.h" #include "device_manager_callback.h" +#include "device_manager/device_manager_delegate.h" #include "dm_device_info.h" #include "executor_pool.h" #include "lru_bucket.h" namespace OHOS { namespace DistributedData { -class API_EXPORT DeviceManagerAdapter { +class API_EXPORT DeviceManagerAdapter : public DeviceManagerDelegate { public: enum DeviceState { DEVICE_ONLINE, @@ -52,7 +53,7 @@ public: void Init(std::shared_ptr executors); Status StartWatchDeviceChange(const AppDeviceChangeListener *observer, const PipeInfo &pipeInfo); Status StopWatchDeviceChange(const AppDeviceChangeListener *observer, const PipeInfo &pipeInfo); - DeviceInfo GetLocalDevice(); + DeviceInfo GetLocalDevice() override; std::vector GetRemoteDevices(); std::vector GetOnlineDevices(); bool IsDeviceReady(const std::string &id); @@ -103,6 +104,7 @@ private: const DmDeviceInfo cloudDmInfo; ConcurrentMap observers_ {}; LRUBucket deviceInfos_ {64}; + LRUBucket otherDeviceInfos_ {64}; static constexpr size_t TIME_TASK_CAPACITY = 50; static constexpr int32_t SYNC_TIMEOUT = 60 * 1000; // ms static constexpr int32_t OH_OS_TYPE = 10; diff --git a/datamgr_service/services/distributeddataservice/adapter/include/communicator/process_communicator_impl.h b/datamgr_service/services/distributeddataservice/adapter/include/communicator/process_communicator_impl.h index 41df2779ca613a79431125ec807a3954320a9ba6..4b326aa5cd9d85da7adafa1daa2630f0220575db 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/communicator/process_communicator_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/communicator/process_communicator_impl.h @@ -36,6 +36,8 @@ public: using UserInfo = DistributedDB::UserInfo; using RouteHeadHandlerCreator = std::function(const DistributedDB::ExtendInfo &info)>; + using DataHeadInfo = DistributedDB::DataHeadInfo; + using DataUserInfo = DistributedDB::DataUserInfo; API_EXPORT static ProcessCommunicatorImpl *GetInstance(); API_EXPORT void SetRouteHeadHandlerCreator(RouteHeadHandlerCreator handlerCreator); @@ -62,11 +64,10 @@ public: API_EXPORT std::shared_ptr GetExtendHeaderHandle( const DistributedDB::ExtendInfo &info) override; - API_EXPORT DBStatus GetDataHeadInfo(const uint8_t *data, uint32_t totalLen, uint32_t &headLength) override; - API_EXPORT DBStatus GetDataUserInfo(const uint8_t *data, uint32_t totalLen, const std::string &label, - std::vector &userInfos) override; + API_EXPORT DBStatus GetDataHeadInfo(DataHeadInfo dataHeadInfo, uint32_t &headLength) override; + API_EXPORT DBStatus GetDataUserInfo(DataUserInfo dataUserInfo, std::vector &userInfos) override; - Status ReuseConnect(const DeviceId &deviceId); + Status ReuseConnect(const DeviceId &deviceId, const ExtraDataInfo &extraInfo); private: void OnMessage(const DeviceInfo &info, const uint8_t *ptr, const int size, diff --git a/datamgr_service/services/distributeddataservice/adapter/include/communicator/route_head_handler.h b/datamgr_service/services/distributeddataservice/adapter/include/communicator/route_head_handler.h index 47596818d46374ad76acf0cdc8b2ac703e2d5d3d..c379ac097c610dd196454a285ed1b8464788015a 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/communicator/route_head_handler.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/communicator/route_head_handler.h @@ -26,7 +26,8 @@ public: using DBStatus = DistributedDB::DBStatus; using UserInfo = DistributedDB::UserInfo; - virtual bool ParseHeadDataLen(const uint8_t *data, uint32_t totalLen, uint32_t &headSize) = 0; + virtual bool ParseHeadDataLen(const uint8_t *data, uint32_t totalLen, uint32_t &headSize, + const std::string &device) = 0; virtual bool ParseHeadDataUser(const uint8_t *data, uint32_t totalLen, const std::string &label, std::vector &userInfos) = 0; }; diff --git a/datamgr_service/services/distributeddataservice/adapter/network/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/network/BUILD.gn index f120004b8130905d6a7235ba4f3ca269fdd67a49..6e2210db65d9615e3bc14678b5a888df973a6267 100644 --- a/datamgr_service/services/distributeddataservice/adapter/network/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/network/BUILD.gn @@ -13,15 +13,9 @@ import("//build/ohos.gni") import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") -config("network_public_config") { +config("module_public_config") { visibility = [ ":*" ] - include_dirs = [ - "${data_service_path}/adapter/network/src", - "${data_service_path}/framework/include/network", - ] - if (datamgr_service_cloud) { - include_dirs += [ "${data_service_path}/adapter/include/communicator" ] - } + include_dirs = [ "${data_service_path}/adapter" ] } ohos_source_set("distributeddata_network") { @@ -37,10 +31,9 @@ ohos_source_set("distributeddata_network") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] - configs = [ ":network_public_config" ] + configs = [ ":module_public_config" ] cflags = [ "-fdata-sections", "-ffunction-sections", @@ -49,19 +42,19 @@ ohos_source_set("distributeddata_network") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] external_deps = [ "kv_store:datamgr_common" ] if (datamgr_service_cloud) { sources += [ "src/network_delegate_normal_impl.cpp" ] - deps = [ - "${data_service_path}/adapter/communicator:distributeddata_communicator", - ] + deps += [ "${data_service_path}/adapter/communicator:distributeddata_communicator" ] external_deps += [ + "c_utils:utils", "device_manager:devicemanagersdk", "hilog:libhilog", + "ipc:ipc_single", "netmanager_base:net_conn_manager_if", ] } else { diff --git a/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_default_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_default_impl.cpp index 0372dc5b6d436b84d32075d9d81f714c7ceadcc2..192c32cb6b64126a102e150449a1f5de3457d68b 100644 --- a/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_default_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_default_impl.cpp @@ -40,6 +40,10 @@ NetworkDelegate::NetworkType NetworkDelegateDefaultImpl::GetNetworkType(bool ret return NetworkType::NONE; } +void NetworkDelegateDefaultImpl::BindExecutor(std::shared_ptr executors) +{ +} + bool NetworkDelegateDefaultImpl::Init() { static NetworkDelegateDefaultImpl delegate; diff --git a/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_default_impl.h b/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_default_impl.h index 5c7583f292f7d3f366fda46c1fb18941fc478f8f..16f3e258180f5b4b9cf2538438365ef8734e048a 100644 --- a/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_default_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_default_impl.h @@ -25,7 +25,7 @@ public: bool IsNetworkAvailable() override; void RegOnNetworkChange() override; NetworkType GetNetworkType(bool retrieve = false) override; - + void BindExecutor(std::shared_ptr executors) override; private: NetworkDelegateDefaultImpl(); ~NetworkDelegateDefaultImpl(); diff --git a/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_normal_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_normal_impl.cpp index 9389f8dcfbb4d6653f245cf95d52a37935523722..5f6d25db0d70b67be96e8117ea9c8e762fcdb5fb 100644 --- a/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_normal_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_normal_impl.cpp @@ -114,22 +114,42 @@ NetworkDelegateNormalImpl::~NetworkDelegateNormalImpl() void NetworkDelegateNormalImpl::RegOnNetworkChange() { - static std::atomic_bool flag = false; - if (flag.exchange(true)) { - ZLOGW("run only one"); - return; + if (executors_ != nullptr) { + executors_->Execute(GetTask(0)); } - sptr observer = new (std::nothrow) NetConnCallbackObserver(*this); - if (observer == nullptr) { - ZLOGE("new operator error.observer is nullptr"); - flag.store(false); - return; - } - auto nRet = NetConnClient::GetInstance().RegisterNetConnCallback(observer); - if (nRet != NETMANAGER_SUCCESS) { +} + +void NetworkDelegateNormalImpl::BindExecutor(std::shared_ptr executors) +{ + executors_ = std::move(executors); +} + +ExecutorPool::Task NetworkDelegateNormalImpl::GetTask(uint32_t retry) +{ + return [this, retry] { + static std::atomic_bool flag = false; + if (flag.exchange(true)) { + ZLOGW("run only one"); + return; + } + sptr observer = new (std::nothrow) NetConnCallbackObserver(*this); + if (observer == nullptr) { + ZLOGE("new operator error.observer is nullptr"); + flag.store(false); + return; + } + auto nRet = NetConnClient::GetInstance().RegisterNetConnCallback(observer); + if (nRet == NETMANAGER_SUCCESS) { + return; + } ZLOGE("RegisterNetConnCallback failed, ret = %{public}d", nRet); flag.store(false); - } + if (retry + 1 >= MAX_RETRY_TIME) { + ZLOGE("fail to register subscriber!"); + return; + } + executors_->Schedule(std::chrono::seconds(RETRY_WAIT_TIME_S), GetTask(retry + 1)); + }; } bool NetworkDelegateNormalImpl::IsNetworkAvailable() diff --git a/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_normal_impl.h b/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_normal_impl.h index 4000ef977b5e28cfa01baf1d0d334526a237a024..e5944270dc0ebbaf77786ba14d8e3bc995ab8fa3 100644 --- a/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_normal_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_normal_impl.h @@ -30,6 +30,7 @@ public: bool IsNetworkAvailable() override; NetworkType GetNetworkType(bool retrieve = false) override; void RegOnNetworkChange() override; + void BindExecutor(std::shared_ptr executors) override; friend class NetConnCallbackObserver; private: NetworkDelegateNormalImpl(); @@ -43,11 +44,15 @@ private: std::chrono::steady_clock::now().time_since_epoch()) .count(); } + ExecutorPool::Task GetTask(uint32_t retry); static constexpr int32_t EFFECTIVE_DURATION = 30 * 1000; // ms static constexpr int32_t NET_LOST_DURATION = 10 * 1000; // ms + static constexpr int32_t MAX_RETRY_TIME = 3; + static constexpr int32_t RETRY_WAIT_TIME_S = 1; NetworkType defaultNetwork_ = NONE; uint64_t expireTime_ = 0; uint64_t netLostTime_ = 0; + std::shared_ptr executors_; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_NETWORK_NORMAL_DELEGATE_IMPL_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..6dcd6a6d2dea9e5fa901a35b02b9cf03d3f41fa5 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright (c) 2025 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("NetworkDelegateNormalImplFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + fuzz_config_file = "${data_service_path}/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer" + + sources = [ + "${data_service_path}/framework/network/network_delegate.cpp", + "networkdelegatenormalimpl_fuzzer.cpp", + ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + include_dirs = [ + "${data_service_path}/adapter/include/communicator", + "${data_service_path}/framework/include/network", + "${data_service_path}/adapter/include/utils", + "${data_service_path}/framework/include", + "${data_service_path}/adapter/network/src", + "${data_service_path}/adapter/include", + ] + + deps = [ + "${data_service_path}/adapter/communicator:distributeddata_communicator", + ] + + external_deps = [ + "c_utils:utils", + "device_manager:devicemanagersdk", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + "netmanager_base:net_conn_manager_if", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":NetworkDelegateNormalImplFuzzTest" ] +} +############################################################################### diff --git a/kv_store/test/fuzztest/singlekvstorestub_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/corpus/init similarity index 92% rename from kv_store/test/fuzztest/singlekvstorestub_fuzzer/corpus/init rename to datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/corpus/init index 6198079a28e860189d4294f6598f8ac6804c0dff..7ade8a0faafeaedba7241e7d4a97b8e1f9691932 100644 --- a/kv_store/test/fuzztest/singlekvstorestub_fuzzer/corpus/init +++ b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/corpus/init @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 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 diff --git a/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/networkdelegatenormalimpl_fuzzer.cpp b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/networkdelegatenormalimpl_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f06ce4a59bdda377dc01029825f0fc0668e0b1fa --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/networkdelegatenormalimpl_fuzzer.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2025 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 "network_delegate.h" +#include "network_delegate_normal_impl.h" +#include "network_delegate_normal_impl.cpp" +#include + +using namespace OHOS::DistributedData; + +namespace OHOS { +void GetNetworkTypeFuzz(FuzzedDataProvider &provider) +{ + NetworkDelegateNormalImpl delegate; + delegate.Init(); + bool retrieve = provider.ConsumeIntegral(); + delegate.GetNetworkType(retrieve); + + sptr observer = new (std::nothrow) NetConnCallbackObserver(delegate); + sptr netHandle = new (std::nothrow) NetHandle(); + sptr netAllCap = new (std::nothrow) NetAllCapabilities(); + observer->NetCapabilitiesChange(netHandle, netAllCap); + netAllCap->netCaps_.insert(NetManagerStandard::NET_CAPABILITY_VALIDATED); + observer->NetCapabilitiesChange(netHandle, netAllCap); + observer->NetAvailable(netHandle); + observer->NetUnavailable(); +} + +void GetTaskFuzz(FuzzedDataProvider &provider) +{ + NetworkDelegateNormalImpl delegate; + delegate.Init(); + uint32_t retry = provider.ConsumeIntegral(); + delegate.GetTask(retry); + + sptr observer = new (std::nothrow) NetConnCallbackObserver(delegate); + sptr netHandle = new (std::nothrow) NetHandle(); + sptr info = new (std::nothrow) NetLinkInfo(); + observer->NetConnectionPropertiesChange(netHandle, info); + observer->NetLost(netHandle); + delegate.RegOnNetworkChange(); +} + +void BindExecutorFuzz(FuzzedDataProvider &provider) +{ + NetworkDelegateNormalImpl delegate; + delegate.Init(); + size_t max = provider.ConsumeIntegralInRange(12, 15); + size_t min = provider.ConsumeIntegralInRange(5, 8); + auto executor = std::make_shared(max, min); + delegate.BindExecutor(executor); + delegate.IsNetworkAvailable(); +} + +void NetBlockStatusChangeFuzz(FuzzedDataProvider &provider) +{ + NetworkDelegateNormalImpl delegate; + delegate.Init(); + sptr observer = new (std::nothrow) NetConnCallbackObserver(delegate); + sptr netHandle = nullptr; + bool blocked = provider.ConsumeIntegral(); + observer->NetBlockStatusChange(netHandle, blocked); + delegate.RefreshNet(); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::GetNetworkTypeFuzz(provider); + OHOS::GetTaskFuzz(provider); + OHOS::BindExecutorFuzz(provider); + OHOS::NetBlockStatusChangeFuzz(provider); + return 0; +} \ No newline at end of file diff --git a/kv_store/test/fuzztest/distributedkvdataservice_fuzzer/distributedkvdataservice_fuzzer.h b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/networkdelegatenormalimpl_fuzzer.h similarity index 70% rename from kv_store/test/fuzztest/distributedkvdataservice_fuzzer/distributedkvdataservice_fuzzer.h rename to datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/networkdelegatenormalimpl_fuzzer.h index 37eb9ac9f9bdc8d7032e75b7e79ab7a1d42b7ff1..1ae55e23e6200299ab8a9fd4d30c47ffc3c1af04 100644 --- a/kv_store/test/fuzztest/distributedkvdataservice_fuzzer/distributedkvdataservice_fuzzer.h +++ b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/networkdelegatenormalimpl_fuzzer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2025 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,10 +13,9 @@ * limitations under the License. */ -#ifndef DISTRIBUTEDKVDATASERVICE_FUZZER_H -#define DISTRIBUTEDKVDATASERVICE_FUZZER_H +#ifndef NETWORKDELEGATENORMALIMPL_FUZZER_H +#define NETWORKDELEGATENORMALIMPL_FUZZER_H -#define FUZZ_PROJECT_NAME "distributedkvdataservice_fuzzer" - -#endif // DISTRIBUTEDKVDATASERVICE_FUZZER_H +#define FUZZ_PROJECT_NAME "networkdelegatenormalimpl_fuzzer" +#endif // NETWORKDELEGATENORMALIMPL_FUZZER_H \ No newline at end of file diff --git a/kv_store/test/fuzztest/jsonservice_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/project.xml similarity index 63% rename from kv_store/test/fuzztest/jsonservice_fuzzer/project.xml rename to datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/project.xml index 73736f01a8820f5deb20590a5655e6fbe62b6aa6..a37a23b1533f07ab59744732b0f46b2b5fd958d8 100644 --- a/kv_store/test/fuzztest/jsonservice_fuzzer/project.xml +++ b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/project.xml @@ -1,5 +1,5 @@ - - - - 1000 - - 1800 - - 4096 - - + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/network/test/network_delegate_normal_impl_test.cpp b/datamgr_service/services/distributeddataservice/adapter/network/test/network_delegate_normal_impl_test.cpp index 9d4842a95ede26fa146b1b3ddc16f16a3b7b82ae..bf7df17cbefae269f6e46b4667d21ef29697729a 100644 --- a/datamgr_service/services/distributeddataservice/adapter/network/test/network_delegate_normal_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/network/test/network_delegate_normal_impl_test.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "network/network_delegate.h" +#include "network_delegate.h" #include "network_delegate_normal_impl.h" #include "network_delegate_normal_impl.cpp" #include diff --git a/datamgr_service/services/distributeddataservice/adapter/network/test/network_delegate_test.cpp b/datamgr_service/services/distributeddataservice/adapter/network/test/network_delegate_test.cpp index 391aa00841c31456d097b80283b0365ad9079bed..a5b575e1a5eb310490738d7ad394c8dd832ed85b 100644 --- a/datamgr_service/services/distributeddataservice/adapter/network/test/network_delegate_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/network/test/network_delegate_test.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ #define LOG_TAG "NetworkDelegateTest" -#include "network/network_delegate.h" +#include "network_delegate.h" #include #include diff --git a/datamgr_service/services/distributeddataservice/adapter/schema_helper/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/schema_helper/BUILD.gn index 4bfbe3be2aa8df29edca3657f376101433ca94ad..c3516c441a77a4c80451f2493c5568a9e1419b4a 100644 --- a/datamgr_service/services/distributeddataservice/adapter/schema_helper/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/schema_helper/BUILD.gn @@ -15,7 +15,7 @@ import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") config("module_public_config") { visibility = [ ":*" ] - include_dirs = [ "../include/schema_helper" ] + include_dirs = [ "." ] } ohos_source_set("distributeddata_schema_helper") { @@ -27,15 +27,13 @@ ohos_source_set("distributeddata_schema_helper") { boundary_sanitize = true ubsan = true } - sources = [ "src/get_schema_helper.cpp" ] + sources = [ "get_schema_helper.cpp" ] cflags_cc = [ "-fvisibility=hidden", "-fstack-protector-strong", ] - include_dirs = [ "../include/schema_helper" ] - public_configs = [ ":module_public_config" ] external_deps = [ "bundle_framework:appexecfwk_base", diff --git a/datamgr_service/services/distributeddataservice/adapter/schema_helper/src/get_schema_helper.cpp b/datamgr_service/services/distributeddataservice/adapter/schema_helper/get_schema_helper.cpp similarity index 98% rename from datamgr_service/services/distributeddataservice/adapter/schema_helper/src/get_schema_helper.cpp rename to datamgr_service/services/distributeddataservice/adapter/schema_helper/get_schema_helper.cpp index b5c847b38a0c3dd087d443e8898beb80c5b3069a..25ce22999748e3d43a7d21e921602a98dd3102b8 100644 --- a/datamgr_service/services/distributeddataservice/adapter/schema_helper/src/get_schema_helper.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/schema_helper/get_schema_helper.cpp @@ -14,7 +14,7 @@ */ #define LOG_TAG "SchemaHelper" -#include "schema_helper/get_schema_helper.h" +#include "get_schema_helper.h" #include "bundle_mgr_interface.h" #include "if_system_ability_manager.h" diff --git a/datamgr_service/services/distributeddataservice/adapter/include/schema_helper/get_schema_helper.h b/datamgr_service/services/distributeddataservice/adapter/schema_helper/get_schema_helper.h similarity index 100% rename from datamgr_service/services/distributeddataservice/adapter/include/schema_helper/get_schema_helper.h rename to datamgr_service/services/distributeddataservice/adapter/schema_helper/get_schema_helper.h diff --git a/datamgr_service/services/distributeddataservice/adapter/screenlock/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/screenlock/BUILD.gn index 28f3b0b788e8a6d85827b3c34bf82de846cad674..766eb3f9e9d0530888a346939f9609656e56ad60 100644 --- a/datamgr_service/services/distributeddataservice/adapter/screenlock/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/BUILD.gn @@ -13,6 +13,11 @@ import("//build/ohos.gni") import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") +config("module_public_config") { + visibility = [ ":*" ] + include_dirs = [ "${data_service_path}/adapter" ] +} + ohos_source_set("distributeddata_screenlock") { branch_protector_ret = "pac_ret" sanitize = { @@ -22,25 +27,24 @@ ohos_source_set("distributeddata_screenlock") { boundary_sanitize = true ubsan = true } - sources = [ "src/screen_lock.cpp" ] + sources = [ "screen_lock.cpp" ] cflags_cc = [ "-fvisibility=hidden", "-fstack-protector-strong", ] - include_dirs = [ - "../include/screenlock", - "../include/utils", - "${data_service_path}/framework/include", + public_configs = [ ":module_public_config" ] + deps = [ + "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/framework:distributeddatasvcfwk", ] - deps = [ "${data_service_path}/adapter/account:distributeddata_account" ] - external_deps = [ "c_utils:utils", "common_event_service:cesfwk_innerkits", "hilog:libhilog", + "ipc:ipc_core", "kv_store:datamgr_common", "screenlock_mgr:screenlock_client", ] diff --git a/datamgr_service/services/distributeddataservice/adapter/screenlock/src/screen_lock.cpp b/datamgr_service/services/distributeddataservice/adapter/screenlock/screen_lock.cpp similarity index 94% rename from datamgr_service/services/distributeddataservice/adapter/screenlock/src/screen_lock.cpp rename to datamgr_service/services/distributeddataservice/adapter/screenlock/screen_lock.cpp index 36c5d601a82c6dddbd24c3f151c530b34a092d3a..42d0ee8b8e99d8b48b076aa1ea80dccfbfdb01b3 100644 --- a/datamgr_service/services/distributeddataservice/adapter/screenlock/src/screen_lock.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/screen_lock.cpp @@ -14,7 +14,7 @@ */ #define LOG_TAG "ScreenLock" -#include "screenlock/screen_lock.h" +#include "screen_lock.h" #include "account/account_delegate.h" #include "log_print.h" @@ -94,7 +94,9 @@ void ScreenLock::SubscribeScreenEvent() NotifyScreenUnlocked(user); }); } - executors_->Execute(GetTask(0)); + if (executors_ != nullptr) { + executors_->Execute(GetTask(0)); + } } void ScreenLock::UnsubscribeScreenEvent() @@ -132,7 +134,9 @@ ExecutorPool::Task ScreenLock::GetTask(uint32_t retry) ZLOGE("fail to register subscriber!"); return; } - executors_->Schedule(std::chrono::seconds(RETRY_WAIT_TIME_S), GetTask(retry + 1)); + if (executors_ != nullptr) { + executors_->Schedule(std::chrono::seconds(RETRY_WAIT_TIME_S), GetTask(retry + 1)); + } }; } } // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/include/screenlock/screen_lock.h b/datamgr_service/services/distributeddataservice/adapter/screenlock/screen_lock.h similarity index 100% rename from datamgr_service/services/distributeddataservice/adapter/include/screenlock/screen_lock.h rename to datamgr_service/services/distributeddataservice/adapter/screenlock/screen_lock.h diff --git a/datamgr_service/services/distributeddataservice/adapter/screenlock/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/BUILD.gn index f1f16b53b97aa91b48e36de832466a7d197a9a9c..132dc9bdaf080518cc40d77b3962a5b0cc6cc2a0 100644 --- a/datamgr_service/services/distributeddataservice/adapter/screenlock/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/BUILD.gn @@ -18,30 +18,25 @@ module_output_path = "datamgr_service/datamgr_service/distributeddatafwk" ohos_unittest("ScreenLockTest") { module_out_path = module_output_path - sources = [ - "${data_service_path}/adapter/screenlock/src/screen_lock.cpp", - "${data_service_path}/framework/account/account_delegate.cpp", - "${data_service_path}/framework/screen/screen_manager.cpp", - "screen_lock_test.cpp", - ] - include_dirs = [ - "${data_service_path}/adapter/include/screenlock", - "${data_service_path}/framework/include", - "${data_service_path}/framework/include/account", - ] + sources = [ "screen_lock_test.cpp" ] + cflags = [ "-Dprivate=public", "-Dprotected=public", "-Werror", ] + deps = [ + "${data_service_path}/adapter/screenlock:distributeddata_screenlock", + "${data_service_path}/framework:distributeddatasvcfwk" + ] external_deps = [ "c_utils:utils", "common_event_service:cesfwk_innerkits", "googletest:gtest_main", "hilog:libhilog", - "kv_store:distributeddata_inner", - "screenlock_mgr:screenlock_client", + "ipc:ipc_core", + "kv_store:datamgr_common", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..cc14fd931183f913a2531f65760b0d41c0405cff --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/BUILD.gn @@ -0,0 +1,56 @@ +# Copyright (c) 2025 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("ScreenlockFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + fuzz_config_file = + "${data_service_path}/adapter/screenlock/test/fuzztest/screenlock_fuzzer" + + sources = [ "screenlock_fuzzer.cpp" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-Dprivate=public", + "-Dprotected=public", + ] + + deps = [ + "${data_service_path}/adapter/screenlock:distributeddata_screenlock", + "${data_service_path}/framework:distributeddatasvcfwk", + ] + + external_deps = [ + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":ScreenlockFuzzTest" ] +} +############################################################################### diff --git a/kv_store/test/fuzztest/jsonservice_fuzzer/jsonservice_fuzzer.h b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/corpus/init similarity index 78% rename from kv_store/test/fuzztest/jsonservice_fuzzer/jsonservice_fuzzer.h rename to datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/corpus/init index af5feb8c9cef1cfedaea4faa2da7f8a02d0e38e7..7ade8a0faafeaedba7241e7d4a97b8e1f9691932 100644 --- a/kv_store/test/fuzztest/jsonservice_fuzzer/jsonservice_fuzzer.h +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/corpus/init @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 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,9 +13,4 @@ * limitations under the License. */ -#ifndef JSON_FUZZER_H -#define JSON_FUZZER_H - -#define FUZZ_PROJECT_NAME "Json_fuzzer" - -#endif // JSON_FUZZER_H \ No newline at end of file +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a37a23b1533f07ab59744732b0f46b2b5fd958d8 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/screenlock_fuzzer.cpp b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/screenlock_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d6bb47b4c3207e5f275a7efdd53e118fd3a506a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/screenlock_fuzzer.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2025 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 "screenlock_fuzzer.h" +#include "screenlock/screen_lock.h" + +using namespace OHOS::DistributedData; +namespace OHOS { +class ScreenLockObserver : public ScreenManager::Observer { +public: + void OnScreenUnlocked(int32_t user) override + { + } + + std::string GetName() override + { + return name_; + } + + void SetName(const std::string &name) + { + name_ = name; + } + +private: + std::string name_ = "screenTestObserver"; +}; + +void SubscribeFuzz(FuzzedDataProvider &provider) +{ + auto screenLock = std::make_shared(); + screenLock->Subscribe(nullptr); + auto observer = std::make_shared(); + std::string name = provider.ConsumeRandomLengthString(); + observer->SetName(name); + screenLock->Subscribe(observer); + screenLock->IsLocked(); +} + +void UnsubscribeFuzz(FuzzedDataProvider &provider) +{ + auto screenLock = std::make_shared(); + auto observer = std::make_shared(); + std::string name = provider.ConsumeRandomLengthString(); + observer->SetName(name); + screenLock->Subscribe(observer); + screenLock->Unsubscribe(observer); + screenLock->UnsubscribeScreenEvent(); +} + +void GetTaskFuzz(FuzzedDataProvider &provider) +{ + auto screenLock = std::make_shared(); + int retry = provider.ConsumeIntegralInRange(1, 20); + screenLock->GetTask(retry); +} + +void NotifyScreenUnlockedFuzz(FuzzedDataProvider &provider) +{ + auto screenLock = std::make_shared(); + int user = provider.ConsumeIntegral(); + screenLock->NotifyScreenUnlocked(user); +} + +void OnReceiveEventFuzz(FuzzedDataProvider &provider) +{ + OHOS::EventFwk::MatchingSkills matchingSkills; + std::string reserved = provider.ConsumeRandomLengthString(); + matchingSkills.AddEvent(reserved); + OHOS::EventFwk::CommonEventSubscribeInfo info(matchingSkills); + int priority = provider.ConsumeIntegral(); + info.SetPriority(priority); + info.SetPermission("ohos.permission.SUBSCRIBE_SCREEN_LOCK"); + auto subscriber = std::make_shared(info); + OHOS::AAFwk::Want want; + want.SetAction(CommonEventSupport::COMMON_EVENT_HWID_LOGIN); + CommonEventData commonEventData(want); + CommonEventData event(want); + subscriber->OnReceiveEvent(event); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::SubscribeFuzz(provider); + OHOS::UnsubscribeFuzz(provider); + OHOS::GetTaskFuzz(provider); + OHOS::NotifyScreenUnlockedFuzz(provider); + OHOS::OnReceiveEventFuzz(provider); + return 0; +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/rddbrepair_fuzzer.h b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/screenlock_fuzzer.h similarity index 76% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/rddbrepair_fuzzer.h rename to datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/screenlock_fuzzer.h index 0a95b06c469c929051b4410701b1195aebfe4ffc..2ae3c12cd6073d42fc9c884f92f86f757ffd121f 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/rddbrepair_fuzzer.h +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/screenlock_fuzzer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2025 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,9 +13,9 @@ * limitations under the License. */ -#ifndef RDDBREPAIR_FUZZER_H -#define RDDBREPAIR_FUZZER_H +#ifndef SCREENLOCK_FUZZER_H +#define SCREENLOCK_FUZZER_H -#define FUZZ_PROJECT_NAME "rddbrepair_fuzzer" +#define FUZZ_PROJECT_NAME "screenlock_fuzzer" -#endif // RDDBREPAIR_FUZZER_H \ No newline at end of file +#endif // SCREENLOCK_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/screenlock/test/screen_lock_test.cpp b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/screen_lock_test.cpp index be5a5f5f1b1c174aa2bbd0ed270e72bb83a316a8..5384155bcb5dc94b87ca1164aa6286e4ddb4fe07 100644 --- a/datamgr_service/services/distributeddataservice/adapter/screenlock/test/screen_lock_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/screen_lock_test.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "screen_lock.h" +#include "screenlock/screen_lock.h" #include namespace { @@ -53,6 +53,8 @@ public: void TearDown() { } +protected: + static constexpr int32_t MAX_RETRY_TIME = 300; }; /** @@ -65,7 +67,6 @@ public: HWTEST_F(ScreenLockTest, Subscribe001, TestSize.Level0) { auto screenLock = std::make_shared(); - screenLock->ScreenManager::Subscribe(nullptr); screenLock->Subscribe(nullptr); EXPECT_TRUE(screenLock->observerMap_.Empty()); auto observer = std::make_shared(); @@ -101,7 +102,6 @@ HWTEST_F(ScreenLockTest, Subscribe002, TestSize.Level0) HWTEST_F(ScreenLockTest, Unsubscribe001, TestSize.Level0) { auto screenLock = std::make_shared(); - screenLock->ScreenManager::Unsubscribe(nullptr); auto observer = std::make_shared(); screenLock->Subscribe(observer); EXPECT_EQ(screenLock->observerMap_.Size(), 1); @@ -122,10 +122,62 @@ HWTEST_F(ScreenLockTest, SubscribeScreenEvent001, TestSize.Level0) screenLock->BindExecutor(executor); ASSERT_NE(screenLock->executors_, nullptr); EXPECT_EQ(screenLock->eventSubscriber_, nullptr); - screenLock->ScreenManager::SubscribeScreenEvent(); screenLock->SubscribeScreenEvent(); EXPECT_NE(screenLock->eventSubscriber_, nullptr); - screenLock->ScreenManager::UnsubscribeScreenEvent(); screenLock->UnsubscribeScreenEvent(); + screenLock->executors_ = nullptr; +} + +/** +* @tc.name: SubscribeScreenEvent002 +* @tc.desc: subscribe ScreenEvent +* @tc.type: FUNC +* @tc.author: +*/ +HWTEST_F(ScreenLockTest, SubscribeScreenEvent002, TestSize.Level0) +{ + auto screenLock = std::make_shared(); + EXPECT_EQ(screenLock->executors_, nullptr); + EXPECT_EQ(screenLock->eventSubscriber_, nullptr); + screenLock->SubscribeScreenEvent(); + EXPECT_NE(screenLock->eventSubscriber_, nullptr); + screenLock->UnsubscribeScreenEvent(); +} + +/** +* @tc.name: GetTask001 +* @tc.desc: subscribe ScreenEvent +* @tc.type: FUNC +* @tc.author: +*/ +HWTEST_F(ScreenLockTest, GetTask001, TestSize.Level0) +{ + auto screenLock = std::make_shared(); + EXPECT_EQ(screenLock->executors_, nullptr); + EXPECT_EQ(screenLock->eventSubscriber_, nullptr); + auto Task = screenLock->GetTask(0); + Task(); + auto executor = std::make_shared(12, 5); + screenLock->BindExecutor(executor); + ASSERT_NE(screenLock->executors_, nullptr); + Task = screenLock->GetTask(MAX_RETRY_TIME - 1); + Task(); +} + +/** +* @tc.name: GetTask002 +* @tc.desc: subscribe ScreenEvent +* @tc.type: FUNC +* @tc.author: +*/ +HWTEST_F(ScreenLockTest, GetTask002, TestSize.Level0) +{ + auto screenLock = std::make_shared(); + EXPECT_EQ(screenLock->executors_, nullptr); + EXPECT_EQ(screenLock->eventSubscriber_, nullptr); + screenLock->SubscribeScreenEvent(); + EXPECT_NE(screenLock->eventSubscriber_, nullptr); + auto Task = screenLock->GetTask(0); + Task(); } } // namespace \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/test/BUILD.gn index 6f6f3b435e02812d2ab6e46a46646c7a8683218b..4ccfd981ebc2af9a1a4f8956415b75f82657f72a 100644 --- a/datamgr_service/services/distributeddataservice/adapter/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/test/BUILD.gn @@ -22,9 +22,13 @@ group("unittest") { "../account/test:unittest", "../communicator/test:unittest", "../dfx/test:unittest", - "../screenlock/test:unittest", ] + if (defined(global_parts_info) && + defined(global_parts_info.theme_screenlock_mgr)) { + deps += [ "${data_service_path}/adapter/screenlock/test:unittest" ] + } + if (datamgr_service_cloud) { deps += [ "../network/test:unittest" ] } @@ -33,5 +37,13 @@ group("unittest") { group("fuzztest") { testonly = true - deps = [ "../communicator/test/fuzztest:fuzztest" ] + deps = [ + "../communicator/test/fuzztest:fuzztest", + "../network/test/fuzztest/networkdelegatenormalimpl_fuzzer:fuzztest", + ] + + if (defined(global_parts_info) && + defined(global_parts_info.theme_screenlock_mgr)) { + deps += [ "../screenlock/test/fuzztest/screenlock_fuzzer:fuzztest" ] + } } diff --git a/datamgr_service/services/distributeddataservice/adapter/utils/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/utils/BUILD.gn index 8325bf050a1f6e258054a788896228c468028a25..bf5b815f0bf6ffb9d0f4378d08ee79c5d808785b 100644 --- a/datamgr_service/services/distributeddataservice/adapter/utils/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/utils/BUILD.gn @@ -24,17 +24,14 @@ ohos_source_set("distributeddata_utils") { } sources = [ "src/kvstore_utils.cpp" ] - cflags_cc = [ - "-fvisibility=hidden", - "-fstack-protector-strong", - ] + cflags_cc = [ "-fvisibility=hidden" ] if (build_public_version) { cflags_cc += [ "-DCONFIG_PUBLIC_VERSION" ] } include_dirs = [ "../include/utils" ] - ldflags = [ "-Wl,-z,relro,-z,now,--exclude-libs,ALL" ] + ldflags = [ "-Wl,--exclude-libs,ALL" ] external_deps = [ "c_utils:utils", diff --git a/datamgr_service/services/distributeddataservice/app/BUILD.gn b/datamgr_service/services/distributeddataservice/app/BUILD.gn index b66d01341823a22d56fd211fdae05e81bd8ac4af..2415418df037b7c284bdc81fbd2ac9f8f1bccdcb 100644 --- a/datamgr_service/services/distributeddataservice/app/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/BUILD.gn @@ -38,9 +38,6 @@ ohos_sa_profile("distributeddata_profile") { config("module_private_config") { visibility = [ ":*" ] include_dirs = [ - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", "${data_service_path}/adapter/include/account", "${data_service_path}/adapter/include/permission", "${data_service_path}/adapter/include/screen", @@ -76,16 +73,14 @@ config("module_private_config") { "-Oz", "-fdata-sections", "-ffunction-sections", - "-fstack-protector-strong", ] cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] - ldflags = [ "-Wl,-z,relro,-z,now,--gc-sections" ] + ldflags = [ "-Wl,--gc-sections" ] } ohos_shared_library("distributeddataservice") { @@ -98,7 +93,6 @@ ohos_shared_library("distributeddataservice") { ubsan = true } sources = [ - "${data_service_path}/service/common/xcollie.cpp", "src/clone/clone_backup_info.cpp", "src/clone/secret_key_backup_data.cpp", "src/db_info_handle_impl.cpp", @@ -127,7 +121,6 @@ ohos_shared_library("distributeddataservice") { configs = [ ":module_private_config" ] deps = [ - "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/app/src/checker:distributeddata_checker", "${data_service_path}/app/src/installer:distributeddata_installer", "${data_service_path}/framework:distributeddatasvcfwk", @@ -170,4 +163,4 @@ ohos_shared_library("distributeddataservice") { subsystem_name = "distributeddatamgr" part_name = "datamgr_service" defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] -} +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/CMakeLists.txt b/datamgr_service/services/distributeddataservice/app/CMakeLists.txt index 0d383c1454642e57f07d546b408f794bba93d661..b885fb477e48352da0b43d2410c9c05dc88d5ede 100644 --- a/datamgr_service/services/distributeddataservice/app/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/app/CMakeLists.txt @@ -11,6 +11,7 @@ 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") add_definitions(-DPROCESS_LABEL="mytest") +add_definitions(-D__CJSON_USE_INT64) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src appSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/flowctrl_manager appSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/installer appSrc) diff --git a/datamgr_service/services/distributeddataservice/app/distributed_data.cfg b/datamgr_service/services/distributeddataservice/app/distributed_data.cfg index 65e8ac880c053d0127039baf03f077fdf5034fd0..0480668eb4b13c724ec8d9ef56e421d626c69549 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","data_reserve"], + "gid" : ["system","shell","readproc","ddms","dfs_share","data_reserve"], "writepid":[ "/dev/cpuset/foreground/tasks", "/dev/stune/foreground/tasks", diff --git a/datamgr_service/services/distributeddataservice/app/src/checker/BUILD.gn b/datamgr_service/services/distributeddataservice/app/src/checker/BUILD.gn index 6695b0d65044fd1e010ae19b4e3c117d38408dbd..f0fa8dd258432a3254d58b3173dd84958c6fa2d7 100644 --- a/datamgr_service/services/distributeddataservice/app/src/checker/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/src/checker/BUILD.gn @@ -30,7 +30,6 @@ ohos_source_set("distributeddata_checker") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ "${data_service_path}/framework/include" ] @@ -38,12 +37,9 @@ ohos_source_set("distributeddata_checker") { if (build_public_version) { cflags_cc += [ "-DCONFIG_PUBLIC_VERSION" ] } - ldflags = [ "-Wl,-z,relro,-z,now,--exclude-libs,ALL" ] + ldflags = [ "-Wl,--exclude-libs,ALL" ] deps = [ "${data_service_path}/adapter/utils:distributeddata_utils" ] - cflags = [ - "-Oz", - "-fstack-protector-strong", - ] + cflags = [ "-Oz" ] external_deps = [ "ability_base:base", "ability_base:want", diff --git a/datamgr_service/services/distributeddataservice/app/src/checker/bundle_checker.cpp b/datamgr_service/services/distributeddataservice/app/src/checker/bundle_checker.cpp index 674e09d5909e7d186dc098af80444a3263476676..b726ab915be6d6ba3efe6693eb0825b2b93122bb 100644 --- a/datamgr_service/services/distributeddataservice/app/src/checker/bundle_checker.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/checker/bundle_checker.cpp @@ -61,8 +61,26 @@ bool BundleChecker::SetSwitchesInfo(const CheckerManager::Switches &switches) return true; } +std::string BundleChecker::GetKey(const std::string &bundleName, int32_t userId) +{ + return bundleName + "###" + std::to_string(userId); +} + +std::string BundleChecker::GetAppidFromCache(const std::string &bundleName, int32_t userId) +{ + std::string appId; + std::string key = GetKey(bundleName, userId); + appIds_.Get(key, appId); + return appId; +} + std::string BundleChecker::GetBundleAppId(const CheckerManager::StoreInfo &info) { + int32_t userId = info.uid / OHOS::AppExecFwk::Constants::BASE_USER_RANGE; + std::string appId = GetAppidFromCache(info.bundleName, userId); + if (!appId.empty()) { + return appId; + } auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (samgrProxy == nullptr) { ZLOGE("Failed to get system ability mgr."); @@ -78,15 +96,28 @@ std::string BundleChecker::GetBundleAppId(const CheckerManager::StoreInfo &info) ZLOGE("Failed to get bundle manager"); return ""; } - int32_t userId = info.uid / OHOS::AppExecFwk::Constants::BASE_USER_RANGE; - std::string appId = bundleManager->GetAppIdByBundleName(info.bundleName, userId); + appId = bundleManager->GetAppIdByBundleName(info.bundleName, userId); if (appId.empty()) { ZLOGE("GetAppIdByBundleName failed appId:%{public}s, bundleName:%{public}s, uid:%{public}d", appId.c_str(), info.bundleName.c_str(), userId); + } else { + appIds_.Set(GetKey(info.bundleName, userId), appId); } return appId; } +void BundleChecker::DeleteCache(const std::string &bundleName, int32_t user, int32_t index) +{ + std::string key = GetKey(bundleName, user); + appIds_.Delete(key); +} + +void BundleChecker::ClearCache() +{ + appIds_.ResetCapacity(0); + appIds_.ResetCapacity(CACHE_SIZE); +} + std::string BundleChecker::GetAppId(const CheckerManager::StoreInfo &info) { if (AccessTokenKit::GetTokenTypeFlag(info.tokenId) != TOKEN_HAP) { @@ -114,7 +145,6 @@ bool BundleChecker::IsValid(const CheckerManager::StoreInfo &info) if (AccessTokenKit::GetHapTokenInfo(info.tokenId, tokenInfo) != RET_SUCCESS) { return false; } - return tokenInfo.bundleName == info.bundleName; } diff --git a/datamgr_service/services/distributeddataservice/app/src/checker/bundle_checker.h b/datamgr_service/services/distributeddataservice/app/src/checker/bundle_checker.h index 1eba18e54a2734ad944ad7da5662ec02d95ee521..d5c655bb92add0fc2b61a427e906c18e33c19c2a 100644 --- a/datamgr_service/services/distributeddataservice/app/src/checker/bundle_checker.h +++ b/datamgr_service/services/distributeddataservice/app/src/checker/bundle_checker.h @@ -16,6 +16,7 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CHECKER_BUNDLE_CHECKER_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CHECKER_BUNDLE_CHECKER_H #include "checker/checker_manager.h" +#include "lru_bucket.h" namespace OHOS { namespace DistributedData { class BundleChecker : public CheckerManager::Checker { @@ -36,8 +37,12 @@ public: std::vector GetStaticStores() override; bool IsDynamic(const CheckerManager::StoreInfo &info) override; bool IsStatic(const CheckerManager::StoreInfo &info) override; - + void DeleteCache(const std::string &bundleName, int32_t user, int32_t index) override; + void ClearCache() override; private: + static constexpr int32_t CACHE_SIZE = 32; + std::string GetAppidFromCache(const std::string &bundleName, int32_t userId); + std::string GetKey(const std::string &bundleName, int32_t userId); static BundleChecker instance_; std::map trusts_; std::map distrusts_; @@ -45,6 +50,7 @@ private: std::vector dynamicStores_; std::vector staticStores_; std::string GetBundleAppId(const CheckerManager::StoreInfo &info); + LRUBucket appIds_ { CACHE_SIZE }; }; } // namespace DistributedData } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.cpp b/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.cpp index e81ed5a8991f8957d348aacda04ce76771d6bd36..1cddeacfaafd54fa741de0602ef826303520e174 100644 --- a/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.cpp @@ -53,6 +53,14 @@ int32_t FeatureStubImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const return featureImpl_->OnAppExit(uid, pid, tokenId, bundleName); } +int32_t FeatureStubImpl::OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) +{ + if (featureImpl_ == nullptr) { + return -1; + } + return featureImpl_->OnFeatureExit(uid, pid, tokenId, bundleName); +} + int32_t FeatureStubImpl::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index) { if (featureImpl_ == nullptr) { diff --git a/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.h b/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.h index 77e90d58907c36c7c1674fd6c49e8c1da4d0b31d..7c2715a61b201112fc7e00951f7c6263048c4ebf 100644 --- a/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.h +++ b/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.h @@ -32,6 +32,7 @@ public: MessageOption &option) override; int32_t OnInitialize(std::shared_ptr executor); int32_t OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName); + int32_t OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName); int32_t OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index); int32_t OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index); int32_t OnAppInstall(const std::string &bundleName, int32_t user, int32_t index); diff --git a/datamgr_service/services/distributeddataservice/app/src/installer/BUILD.gn b/datamgr_service/services/distributeddataservice/app/src/installer/BUILD.gn index 49eb62d2fbe5e713cb2e711878cb9741c85edf87..0ccfc73e8fe9c2382692612068e4655193789158 100644 --- a/datamgr_service/services/distributeddataservice/app/src/installer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/src/installer/BUILD.gn @@ -40,13 +40,9 @@ ohos_source_set("distributeddata_installer") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] - cflags = [ - "-Oz", - "-fstack-protector-strong", - ] + cflags = [ "-Oz" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk", 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 6977b3ab9b2e3d74a184795f674f179edab58c39..ecb548549813bd18a01fa08902b1a2a459583e85 100644 --- a/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.cpp @@ -83,9 +83,9 @@ void InstallEventSubscriber::OnUninstall(const std::string &bundleName, int32_t } for (auto &meta : storeMetaData) { if (meta.instanceId == appIndex && !meta.appId.empty() && !meta.storeId.empty()) { - ZLOGI("uninstalled bundleName:%{public}s storeId:%{public}s, userId:%{public}d, appIndex:%{public}d", - bundleName.c_str(), Anonymous::Change(meta.storeId).c_str(), userId, appIndex); - MetaDataManager::GetInstance().DelMeta(meta.GetKey()); + ZLOGI("storeMetaData uninstalled bundleName:%{public}s storeId:%{public}s, userId:%{public}d, " + "appIndex:%{public}d", bundleName.c_str(), Anonymous::Change(meta.storeId).c_str(), userId, appIndex); + MetaDataManager::GetInstance().DelMeta(meta.GetKeyWithoutPath()); MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetKeyLocal(), true); MetaDataManager::GetInstance().DelMeta(meta.GetSecretKey(), true); @@ -96,7 +96,8 @@ void InstallEventSubscriber::OnUninstall(const std::string &bundleName, int32_t MetaDataManager::GetInstance().DelMeta(meta.GetDebugInfoKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetDfxInfoKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetCloneSecretKey(), true); - PermitDelegate::GetInstance().DelCache(meta.GetKey()); + MetaDataManager::GetInstance().DelMeta(StoreMetaMapping(meta).GetKey(), true); + PermitDelegate::GetInstance().DelCache(meta.GetKeyWithoutPath()); } } } diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_account_observer.h b/datamgr_service/services/distributeddataservice/app/src/kvstore_account_observer.h index d8ea3d153caafdf98e16a4c8f5e61faf36c650b9..bbc535088ddb3ceec9fe23e49749debefb58ff2f 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_account_observer.h +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_account_observer.h @@ -18,7 +18,7 @@ #include -#include "account_delegate.h" +#include "account/account_delegate.h" #include "executor_pool.h" namespace OHOS { 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 ac38e8a750e79415c7453edcb346c0071590053e..f7642bfa0ae8fcb58e86efd661c657c9f5cba6c9 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp @@ -33,7 +33,7 @@ #include "communication_provider.h" #include "communicator_context.h" #include "config_factory.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "db_info_handle_impl.h" #include "device_manager_adapter.h" #include "device_matrix.h" @@ -51,6 +51,8 @@ #include "mem_mgr_proxy.h" #include "metadata/appid_meta_data.h" #include "metadata/meta_data_manager.h" +#include "network/network_delegate.h" +#include "metadata/store_meta_data.h" #include "permission_validator.h" #include "permit_delegate.h" #include "process_communicator_impl.h" @@ -78,9 +80,9 @@ using namespace OHOS::Security::AccessToken; using KvStoreDelegateManager = DistributedDB::KvStoreDelegateManager; using SecretKeyMeta = DistributedData::SecretKeyMetaData; using DmAdapter = DistributedData::DeviceManagerAdapter; -constexpr const char *EXTENSION_BACKUP = "backup"; -constexpr const char *EXTENSION_RESTORE = "restore"; -constexpr const char *CLONE_KEY_ALIAS = "distributed_db_backup_key"; +constexpr const char* EXTENSION_BACKUP = "backup"; +constexpr const char* EXTENSION_RESTORE = "restore"; +constexpr const char* CLONE_KEY_ALIAS = "distributed_db_backup_key"; REGISTER_SYSTEM_ABILITY_BY_ID(KvStoreDataService, DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID, true); @@ -89,8 +91,10 @@ constexpr int MAX_DOWNLOAD_ASSETS_COUNT = 50; constexpr int MAX_DOWNLOAD_TASK = 5; constexpr int KEY_SIZE = 32; constexpr int AES_256_NONCE_SIZE = 32; +constexpr int MAX_CLIENT_DEATH_OBSERVER_SIZE = 16; -KvStoreDataService::KvStoreDataService(bool runOnCreate) : SystemAbility(runOnCreate), clients_() +KvStoreDataService::KvStoreDataService(bool runOnCreate) + : SystemAbility(runOnCreate), clients_() { ZLOGI("begin."); } @@ -136,18 +140,18 @@ void KvStoreDataService::Initialize() DmAdapter::GetInstance().StartWatchDeviceChange(deviceInnerListener_.get(), { "innerListener" }); CommunicatorContext::GetInstance().RegSessionListener(deviceInnerListener_.get()); auto translateCall = [](const std::string &oriDevId, const DistributedDB::StoreInfo &info) { - StoreMetaData meta; + StoreMetaMapping storeMetaMapping; AppIDMetaData appIdMeta; MetaDataManager::GetInstance().LoadMeta(info.appId, appIdMeta, true); - meta.bundleName = appIdMeta.bundleName; - meta.storeId = info.storeId; - meta.user = info.userId; - meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true); + storeMetaMapping.bundleName = appIdMeta.bundleName; + storeMetaMapping.storeId = info.storeId; + storeMetaMapping.user = info.userId; + storeMetaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + MetaDataManager::GetInstance().LoadMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); std::string uuid; - if (OHOS::Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(meta.tokenId) == + if (OHOS::Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(storeMetaMapping.tokenId) == OHOS::Security::AccessToken::TOKEN_HAP) { - uuid = DmAdapter::GetInstance().CalcClientUuid(meta.appId, oriDevId); + uuid = DmAdapter::GetInstance().CalcClientUuid(storeMetaMapping.appId, oriDevId); } else { uuid = DmAdapter::GetInstance().CalcClientUuid(" ", oriDevId); } @@ -202,7 +206,8 @@ void KvStoreDataService::LoadFeatures() } /* RegisterClientDeathObserver */ -Status KvStoreDataService::RegisterClientDeathObserver(const AppId &appId, sptr observer) +Status KvStoreDataService::RegisterClientDeathObserver(const AppId &appId, sptr observer, + const std::string &featureName) { ZLOGD("begin."); KVSTORE_ACCOUNT_EVENT_PROCESSING_CHECKER(Status::SYSTEM_ACCOUNT_EVENT_PROCESSING); @@ -222,18 +227,51 @@ Status KvStoreDataService::RegisterClientDeathObserver(const AppId &appId, sptr< } 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"); + [&appId, &info, pid, this, obs = std::move(observer), featureName](const auto tokenId, auto &clients) { + auto it = clients.find(pid); + if (it == clients.end()) { + auto res = clients.try_emplace(pid, appId, *this, std::move(obs), featureName); + ZLOGI("bundle:%{public}s, feature:%{public}s, uid:%{public}d, pid:%{public}d, emplace:%{public}s.", + appId.appId.c_str(), featureName.c_str(), info.uid, pid, res.second ? "success" : "failed"); + } else { + auto res = it->second.Insert(obs, featureName); + ZLOGI("bundle:%{public}s, feature:%{public}s, uid:%{public}d, pid:%{public}d, inserted:%{public}s.", + appId.appId.c_str(), featureName.c_str(), info.uid, pid, res ? "success" : "failed"); + } return !clients.empty(); }); return Status::SUCCESS; } +int32_t KvStoreDataService::Exit(const std::string &featureName) +{ + ZLOGI("FeatureExit:%{public}s", featureName.c_str()); + auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto pid = IPCSkeleton::GetCallingPid(); + std::string bundleName; + KvStoreClientDeathObserverImpl impl(*this); + bool removed = false; + clients_.ComputeIfPresent(tokenId, [pid, &featureName, &bundleName, &impl, &removed](auto &, auto &value) { + auto it = value.find(pid); + if (it == value.end()) { + return !value.empty(); + } + bundleName = it->second.GetAppId(); + removed = it->second.Delete(featureName); + if (it->second.Empty()) { + impl = std::move(it->second); + value.erase(it); + } + return !value.empty(); + }); + auto [exist, feature] = features_.Find(featureName); + if (removed && exist && feature != nullptr) { + feature->OnFeatureExit(IPCSkeleton::GetCallingUid(), pid, tokenId, bundleName); + } + return Status::SUCCESS; +} Status KvStoreDataService::AppExit(pid_t uid, pid_t pid, uint32_t token, const AppId &appId) { - ZLOGI("AppExit"); // memory of parameter appId locates in a member of clientDeathObserverMap_ and will be freed after // clientDeathObserverMap_ erase, so we have to take a copy if we want to use this parameter after erase operation. AppId appIdTmp = appId; @@ -297,6 +335,7 @@ void KvStoreDataService::OnStart() AccountDelegate::GetInstance()->RegisterHashFunc(Crypto::Sha256); DmAdapter::GetInstance().Init(executors_); AutoCache::GetInstance().Bind(executors_); + NetworkDelegate::GetInstance()->BindExecutor(executors_); static constexpr int32_t RETRY_TIMES = 50; static constexpr int32_t RETRY_INTERVAL = 500 * 1000; // unit is ms for (BlockInteger retry(RETRY_INTERVAL); retry < RETRY_TIMES; ++retry) { @@ -318,17 +357,20 @@ void KvStoreDataService::OnStart() } AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID); AddSystemAbilityListener(MEMORY_MANAGER_SA_ID); + AddSystemAbilityListener(COMM_NET_CONN_MANAGER_SYS_ABILITY_ID); + AddSystemAbilityListener(SUBSYS_ACCOUNT_SYS_ABILITY_ID_BEGIN); + AddSystemAbilityListener(CONCURRENT_TASK_SERVICE_ID); RegisterStoreInfo(); - Handler handlerStoreInfo = - std::bind(&KvStoreDataService::DumpStoreInfo, this, std::placeholders::_1, std::placeholders::_2); + Handler handlerStoreInfo = std::bind(&KvStoreDataService::DumpStoreInfo, this, std::placeholders::_1, + std::placeholders::_2); DumpManager::GetInstance().AddHandler("STORE_INFO", uintptr_t(this), handlerStoreInfo); RegisterUserInfo(); - Handler handlerUserInfo = - std::bind(&KvStoreDataService::DumpUserInfo, this, std::placeholders::_1, std::placeholders::_2); + Handler handlerUserInfo = std::bind(&KvStoreDataService::DumpUserInfo, this, std::placeholders::_1, + std::placeholders::_2); DumpManager::GetInstance().AddHandler("USER_INFO", uintptr_t(this), handlerUserInfo); RegisterBundleInfo(); - Handler handlerBundleInfo = - std::bind(&KvStoreDataService::DumpBundleInfo, this, std::placeholders::_1, std::placeholders::_2); + Handler handlerBundleInfo = std::bind(&KvStoreDataService::DumpBundleInfo, this, std::placeholders::_1, + std::placeholders::_2); DumpManager::GetInstance().AddHandler("BUNDLE_INFO", uintptr_t(this), handlerBundleInfo); StartService(); } @@ -345,6 +387,8 @@ void KvStoreDataService::LoadConfigs() Bootstrap::GetInstance().LoadBackup(executors_); Bootstrap::GetInstance().LoadCloud(); Bootstrap::GetInstance().LoadAppIdMappings(); + Bootstrap::GetInstance().LoadDeviceSyncAppWhiteLists(); + Bootstrap::GetInstance().LoadSyncTrustedApp(); } void KvStoreDataService::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) @@ -352,11 +396,15 @@ void KvStoreDataService::OnAddSystemAbility(int32_t systemAbilityId, const std:: ZLOGI("add system abilityid:%{public}d", systemAbilityId); (void)deviceId; if (systemAbilityId == COMMON_EVENT_SERVICE_ID) { - AccountDelegate::GetInstance()->SubscribeAccountEvent(); Installer::GetInstance().Init(this, executors_); ScreenManager::GetInstance()->SubscribeScreenEvent(); + } else if (systemAbilityId == SUBSYS_ACCOUNT_SYS_ABILITY_ID_BEGIN) { + AccountDelegate::GetInstance()->SubscribeAccountEvent(); } else if (systemAbilityId == MEMORY_MANAGER_SA_ID) { - Memory::MemMgrClient::GetInstance().NotifyProcessStatus(getpid(), 1, 1, DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); + Memory::MemMgrClient::GetInstance().NotifyProcessStatus(getpid(), 1, 1, + DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); + } else if (systemAbilityId == COMM_NET_CONN_MANAGER_SYS_ABILITY_ID) { + NetworkDelegate::GetInstance()->RegOnNetworkChange(); } return; } @@ -365,10 +413,12 @@ void KvStoreDataService::OnRemoveSystemAbility(int32_t systemAbilityId, const st { ZLOGI("remove system abilityid:%{public}d", systemAbilityId); (void)deviceId; + if (systemAbilityId == SUBSYS_ACCOUNT_SYS_ABILITY_ID_BEGIN) { + AccountDelegate::GetInstance()->UnsubscribeAccountEvent(); + } if (systemAbilityId != COMMON_EVENT_SERVICE_ID) { return; } - AccountDelegate::GetInstance()->UnsubscribeAccountEvent(); ScreenManager::GetInstance()->UnsubscribeScreenEvent(); Installer::GetInstance().UnsubscribeEvent(); } @@ -434,12 +484,14 @@ bool KvStoreDataService::WriteBackupInfo(const std::string &content, const std:: FILE *fp = fopen(backupPath.c_str(), "w"); if (!fp) { - ZLOGE("Secret key backup file fopen failed, path: %{public}s, errno: %{public}d", backupPath.c_str(), errno); + ZLOGE("Secret key backup file fopen failed, path: %{public}s, errno: %{public}d", + Anonymous::Change(backupPath).c_str(), errno); return false; } size_t ret = fwrite(content.c_str(), 1, content.length(), fp); if (ret != content.length()) { - ZLOGE("Secret key backup file fwrite failed, path: %{public}s, errno: %{public}d", backupPath.c_str(), errno); + ZLOGE("Secret key backup file fwrite failed, path: %{public}s, errno: %{public}d", + Anonymous::Change(backupPath).c_str(), errno); (void)fclose(fp); return false; } @@ -453,7 +505,8 @@ bool KvStoreDataService::WriteBackupInfo(const std::string &content, const std:: int32_t KvStoreDataService::OnBackup(MessageParcel &data, MessageParcel &reply) { CloneBackupInfo backupInfo; - if (!backupInfo.Unmarshal(data.ReadString()) || backupInfo.bundleInfos.empty() || backupInfo.userId.empty()) { + if (!backupInfo.Unmarshal(data.ReadString()) || + backupInfo.bundleInfos.empty() || backupInfo.userId.empty()) { std::fill(backupInfo.encryptionInfo.symkey.begin(), backupInfo.encryptionInfo.symkey.end(), '\0'); return -1; } @@ -471,11 +524,7 @@ int32_t KvStoreDataService::OnBackup(MessageParcel &data, MessageParcel &reply) return -1; } - std::string content; - if (!GetSecretKeyBackup(backupInfo.bundleInfos, backupInfo.userId, iv, content)) { - DeleteCloneKey(); - return -1; - }; + auto content = GetSecretKeyBackup(backupInfo.bundleInfos, backupInfo.userId, iv); DeleteCloneKey(); std::string backupPath = DirectoryManager::GetInstance().GetClonePath(backupInfo.userId); @@ -506,13 +555,14 @@ std::vector KvStoreDataService::ReEncryptKey(const std::string &key, Se if (!MetaDataManager::GetInstance().LoadMeta(key, secretKeyMeta, true)) { return {}; }; - std::vector password; - if (!CryptoManager::GetInstance().Decrypt(metaData, secretKeyMeta, password)) { + CryptoManager::CryptoParams decryptParams = { .area = secretKeyMeta.area, .userId = metaData.user, + .nonce = secretKeyMeta.nonce }; + auto password = CryptoManager::GetInstance().Decrypt(secretKeyMeta.sKey, decryptParams); + if (password.empty()) { return {}; - }; - + } auto cloneKeyAlias = std::vector(CLONE_KEY_ALIAS, CLONE_KEY_ALIAS + strlen(CLONE_KEY_ALIAS)); - CryptoManager::EncryptParams encryptParams = { .keyAlias = cloneKeyAlias, .nonce = iv }; + CryptoManager::CryptoParams encryptParams = { .keyAlias = cloneKeyAlias, .nonce = iv }; auto reEncryptedKey = CryptoManager::GetInstance().Encrypt(password, encryptParams); password.assign(password.size(), 0); if (reEncryptedKey.size() == 0) { @@ -521,12 +571,12 @@ std::vector KvStoreDataService::ReEncryptKey(const std::string &key, Se return reEncryptedKey; } -bool KvStoreDataService::GetSecretKeyBackup(const std::vector &bundleInfos, - const std::string &userId, const std::vector &iv, std::string &content) +std::string KvStoreDataService::GetSecretKeyBackup(const std::vector &bundleInfos, + const std::string &userId, const std::vector &iv) { SecretKeyBackupData backupInfos; std::string deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - for (const auto &bundleInfo : bundleInfos) { + for (const auto& bundleInfo : bundleInfos) { std::string metaPrefix = StoreMetaData::GetKey({ deviceId, userId, "default", bundleInfo.bundleName }); std::vector StoreMetas; if (!MetaDataManager::GetInstance().LoadMeta(metaPrefix, StoreMetas, true)) { @@ -554,8 +604,7 @@ bool KvStoreDataService::GetSecretKeyBackup(const std::vector &iv) { + auto sKey = DistributedData::Base64::Decode(item.sKey); + auto cloneKeyAlias = std::vector(CLONE_KEY_ALIAS, CLONE_KEY_ALIAS + strlen(CLONE_KEY_ALIAS)); + CryptoManager::CryptoParams decryptParams = { .keyAlias = cloneKeyAlias, .nonce = iv }; + auto rawKey = CryptoManager::GetInstance().Decrypt(sKey, decryptParams); + if (rawKey.empty()) { + ZLOGE("Decrypt failed, bundleName:%{public}s, storeName:%{public}s, storeType:%{public}d", + item.bundleName.c_str(), Anonymous::Change(item.dbName).c_str(), item.storeType); + sKey.assign(sKey.size(), 0); + rawKey.assign(rawKey.size(), 0); + return false; + } + StoreMetaData metaData; metaData.bundleName = item.bundleName; metaData.storeId = item.dbName; metaData.user = item.user == "0" ? "0" : userId; metaData.instanceId = item.instanceId; - auto sKey = DistributedData::Base64::Decode(item.sKey); - std::vector rawKey; - auto cloneKeyAlias = std::vector(CLONE_KEY_ALIAS, CLONE_KEY_ALIAS + strlen(CLONE_KEY_ALIAS)); - CryptoManager::EncryptParams encryptParams = { .keyAlias = cloneKeyAlias, .nonce = iv }; - if (!CryptoManager::GetInstance().Decrypt(sKey, rawKey, encryptParams)) { - ZLOGE("Decrypt failed, bundleName:%{public}s, storeName:%{public}s, storeType:%{public}d", + SecretKeyMetaData secretKey; + CryptoManager::CryptoParams encryptParams = { .area = item.area, .userId = metaData.user }; + secretKey.sKey = CryptoManager::GetInstance().Encrypt(rawKey, encryptParams); + if (secretKey.sKey.empty()) { + ZLOGE("Encrypt failed, bundleName:%{public}s, storeName:%{public}s, storeType:%{public}d", item.bundleName.c_str(), Anonymous::Change(item.dbName).c_str(), item.storeType); sKey.assign(sKey.size(), 0); rawKey.assign(rawKey.size(), 0); - return false; } - SecretKeyMetaData secretKey; secretKey.storeType = item.storeType; - if (item.area < 0) { - secretKey.sKey = CryptoManager::GetInstance().Encrypt(rawKey, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - } else { - secretKey.sKey = CryptoManager::GetInstance().Encrypt(rawKey, item.area, userId); - secretKey.area = item.area; - } + secretKey.nonce = encryptParams.nonce; + secretKey.area = item.area; secretKey.time = { item.time.begin(), item.time.end() }; + sKey.assign(sKey.size(), 0); rawKey.assign(rawKey.size(), 0); return MetaDataManager::GetInstance().SaveMeta(metaData.GetCloneSecretKey(), secretKey, true); @@ -689,8 +744,8 @@ void KvStoreDataService::StartService() ZLOGI("Start distributedata Success, Publish ret: %{public}d", static_cast(ret)); } -void KvStoreDataService::OnStoreMetaChanged(const std::vector &key, const std::vector &value, - CHANGE_FLAG flag) +void KvStoreDataService::OnStoreMetaChanged( + const std::vector &key, const std::vector &value, CHANGE_FLAG flag) { if (flag != CHANGE_FLAG::UPDATE) { return; @@ -718,19 +773,18 @@ void KvStoreDataService::OnStop() } KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreClientDeathObserverImpl(const AppId &appId, - KvStoreDataService &service, sptr observer) - : appId_(appId), dataService_(service), observerProxy_(std::move(observer)), - deathRecipient_(new KvStoreDeathRecipient(*this)) + KvStoreDataService &service, sptr observer, const std::string &featureName) + : appId_(appId), dataService_(service), deathRecipient_(new KvStoreDeathRecipient(*this)) { ZLOGD("KvStoreClientDeathObserverImpl"); uid_ = IPCSkeleton::GetCallingUid(); pid_ = IPCSkeleton::GetCallingPid(); token_ = IPCSkeleton::GetCallingTokenID(); - if (observerProxy_ != nullptr) { - ZLOGI("add death recipient"); - observerProxy_->AddDeathRecipient(deathRecipient_); + if (observer != nullptr) { + observer->AddDeathRecipient(deathRecipient_); + observerProxy_.insert_or_assign(featureName, std::move(observer)); } else { - ZLOGW("observerProxy_ is nullptr"); + ZLOGW("observer is nullptr"); } } KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreClientDeathObserverImpl(KvStoreDataService &service) @@ -760,10 +814,12 @@ KvStoreDataService::KvStoreClientDeathObserverImpl &KvStoreDataService::KvStoreC KvStoreDataService::KvStoreClientDeathObserverImpl::~KvStoreClientDeathObserverImpl() { - ZLOGI("~KvStoreClientDeathObserverImpl"); - if (deathRecipient_ != nullptr && observerProxy_ != nullptr) { - ZLOGI("remove death recipient"); - observerProxy_->RemoveDeathRecipient(deathRecipient_); + if (deathRecipient_ != nullptr && !observerProxy_.empty()) { + for (auto &[key, value] : observerProxy_) { + if (value != nullptr) { + value->RemoveDeathRecipient(deathRecipient_); + } + } } if (uid_ == INVALID_UID || pid_ == INVALID_PID || token_ == INVALID_TOKEN || !appId_.IsValid()) { return; @@ -793,11 +849,41 @@ void KvStoreDataService::KvStoreClientDeathObserverImpl::Reset() appId_.appId = ""; } +bool KvStoreDataService::KvStoreClientDeathObserverImpl::Insert(sptr observer, + const std::string &featureName) +{ + if (observer != nullptr && observerProxy_.size() < MAX_CLIENT_DEATH_OBSERVER_SIZE && + observerProxy_.insert({featureName, observer}).second) { + observer->AddDeathRecipient(deathRecipient_); + return true; + } + return false; +} + +bool KvStoreDataService::KvStoreClientDeathObserverImpl::Delete(const std::string &featureName) +{ + auto it = observerProxy_.find(featureName); + if (it != observerProxy_.end() && it->second != nullptr) { + it->second->RemoveDeathRecipient(deathRecipient_); + } + return observerProxy_.erase(featureName) != 0; +} + +std::string KvStoreDataService::KvStoreClientDeathObserverImpl::GetAppId() +{ + return appId_; +} + +bool KvStoreDataService::KvStoreClientDeathObserverImpl::Empty() +{ + return observerProxy_.empty(); +} + KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreDeathRecipient::KvStoreDeathRecipient( KvStoreClientDeathObserverImpl &kvStoreClientDeathObserverImpl) : kvStoreClientDeathObserverImpl_(kvStoreClientDeathObserverImpl) { - ZLOGI("KvStore Client Death Observer"); + ZLOGD("KvStore Client Death Observer"); } KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreDeathRecipient::~KvStoreDeathRecipient() @@ -808,9 +894,10 @@ KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreDeathRecipient::~KvSt void KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreDeathRecipient::OnRemoteDied( const wptr &remote) { - (void)remote; - ZLOGI("begin"); - kvStoreClientDeathObserverImpl_.NotifyClientDie(); + (void) remote; + if (!clientDead_.exchange(true)) { + kvStoreClientDeathObserverImpl_.NotifyClientDie(); + } } void KvStoreDataService::AccountEventChanged(const AccountEventInfo &eventInfo) @@ -822,13 +909,14 @@ void KvStoreDataService::AccountEventChanged(const AccountEventInfo &eventInfo) g_kvStoreAccountEventStatus = 1; // delete all kvstore meta belong to this user std::vector metaData; - MetaDataManager::GetInstance().LoadMeta(StoreMetaData::GetPrefix({ "" }), metaData, true); + MetaDataManager::GetInstance().LoadMeta(StoreMetaData::GetPrefix({""}), metaData, true); for (const auto &meta : metaData) { if (meta.user != eventInfo.userId) { continue; } - ZLOGI("bundleName:%{public}s, user:%{public}s", meta.bundleName.c_str(), meta.user.c_str()); - MetaDataManager::GetInstance().DelMeta(meta.GetKey()); + ZLOGI("StoreMetaData bundleName:%{public}s, user:%{public}s", meta.bundleName.c_str(), + meta.user.c_str()); + MetaDataManager::GetInstance().DelMeta(meta.GetKeyWithoutPath()); MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetKeyLocal(), true); MetaDataManager::GetInstance().DelMeta(meta.GetSecretKey(), true); @@ -839,8 +927,10 @@ void KvStoreDataService::AccountEventChanged(const AccountEventInfo &eventInfo) MetaDataManager::GetInstance().DelMeta(meta.GetDebugInfoKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetDfxInfoKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetCloneSecretKey(), true); - PermitDelegate::GetInstance().DelCache(meta.GetKey()); + MetaDataManager::GetInstance().DelMeta(StoreMetaMapping(meta).GetKey(), true); + PermitDelegate::GetInstance().DelCache(meta.GetKeyWithoutPath()); } + CheckerManager::GetInstance().ClearCache(); g_kvStoreAccountEventStatus = 0; break; } @@ -873,7 +963,7 @@ void KvStoreDataService::NotifyAccountEvent(const AccountEventInfo &eventInfo) AutoCache::GetInstance().CloseStore([&userIds](const StoreMetaData &meta) { if (userIds.count(atoi(meta.user.c_str())) == 0) { ZLOGW("Illegal use of database by user %{public}s, %{public}s:%{public}s", meta.user.c_str(), - meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); + meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); return true; } return false; @@ -904,13 +994,15 @@ void KvStoreDataService::InitSecurityAdapter(std::shared_ptr execu auto dbStatus = DistributedDB::RuntimeConfig::SetProcessSystemAPIAdapter(security_); ZLOGD("set distributed db system api adapter: %d.", static_cast(dbStatus)); - auto status = DmAdapter::GetInstance().StartWatchDeviceChange(security_.get(), { "security" }); + auto status = DmAdapter::GetInstance().StartWatchDeviceChange(security_.get(), {"security"}); if (status != Status::SUCCESS) { ZLOGD("security register device change failed, status:%d", static_cast(status)); } } -void KvStoreDataService::SetCompatibleIdentify(const AppDistributedKv::DeviceInfo &info) const {} +void KvStoreDataService::SetCompatibleIdentify(const AppDistributedKv::DeviceInfo &info) const +{ +} void KvStoreDataService::OnDeviceOnline(const AppDistributedKv::DeviceInfo &info) { @@ -958,8 +1050,9 @@ void KvStoreDataService::OnSessionReady(const AppDistributedKv::DeviceInfo &info int32_t KvStoreDataService::OnUninstall(const std::string &bundleName, int32_t user, int32_t index) { + CheckerManager::GetInstance().DeleteCache(bundleName, user, index); auto staticActs = FeatureSystem::GetInstance().GetStaticActs(); - staticActs.ForEachCopies([bundleName, user, index](const auto &, const std::shared_ptr &acts) { + staticActs.ForEachCopies([bundleName, user, index](const auto &, const std::shared_ptr& acts) { acts->OnAppUninstall(bundleName, user, index); return false; }); @@ -968,8 +1061,9 @@ int32_t KvStoreDataService::OnUninstall(const std::string &bundleName, int32_t u int32_t KvStoreDataService::OnUpdate(const std::string &bundleName, int32_t user, int32_t index) { + CheckerManager::GetInstance().DeleteCache(bundleName, user, index); auto staticActs = FeatureSystem::GetInstance().GetStaticActs(); - staticActs.ForEachCopies([bundleName, user, index](const auto &, const std::shared_ptr &acts) { + staticActs.ForEachCopies([bundleName, user, index](const auto &, const std::shared_ptr& acts) { acts->OnAppUpdate(bundleName, user, index); return false; }); @@ -978,8 +1072,9 @@ int32_t KvStoreDataService::OnUpdate(const std::string &bundleName, int32_t user int32_t KvStoreDataService::OnInstall(const std::string &bundleName, int32_t user, int32_t index) { + CheckerManager::GetInstance().DeleteCache(bundleName, user, index); auto staticActs = FeatureSystem::GetInstance().GetStaticActs(); - staticActs.ForEachCopies([bundleName, user, index](const auto &, const std::shared_ptr &acts) { + staticActs.ForEachCopies([bundleName, user, index](const auto &, const std::shared_ptr& acts) { acts->OnAppInstall(bundleName, user, index); return false; }); @@ -998,6 +1093,7 @@ int32_t KvStoreDataService::OnScreenUnlocked(int32_t user) int32_t KvStoreDataService::ClearAppStorage(const std::string &bundleName, int32_t userId, int32_t appIndex, int32_t tokenId) { + CheckerManager::GetInstance().DeleteCache(bundleName, userId, appIndex); auto callerToken = IPCSkeleton::GetCallingTokenID(); NativeTokenInfo nativeTokenInfo; if (AccessTokenKit::GetNativeTokenInfo(callerToken, nativeTokenInfo) != RET_SUCCESS || @@ -1025,9 +1121,9 @@ int32_t KvStoreDataService::ClearAppStorage(const std::string &bundleName, int32 for (auto &meta : metaData) { if (meta.instanceId == appIndex && !meta.appId.empty() && !meta.storeId.empty()) { - ZLOGI("data cleared bundleName:%{public}s, stordId:%{public}s, appIndex:%{public}d", bundleName.c_str(), - Anonymous::Change(meta.storeId).c_str(), appIndex); - MetaDataManager::GetInstance().DelMeta(meta.GetKey()); + ZLOGI("StoreMetaData data cleared bundleName:%{public}s, stordId:%{public}s, appIndex:%{public}d", + bundleName.c_str(), Anonymous::Change(meta.storeId).c_str(), appIndex); + MetaDataManager::GetInstance().DelMeta(meta.GetKeyWithoutPath()); MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetKeyLocal(), true); MetaDataManager::GetInstance().DelMeta(meta.GetSecretKey(), true); @@ -1037,7 +1133,8 @@ int32_t KvStoreDataService::ClearAppStorage(const std::string &bundleName, int32 MetaDataManager::GetInstance().DelMeta(meta.GetDebugInfoKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetDfxInfoKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetAutoLaunchKey(), true); - PermitDelegate::GetInstance().DelCache(meta.GetKey()); + MetaDataManager::GetInstance().DelMeta(StoreMetaMapping(meta).GetKey(), true); + PermitDelegate::GetInstance().DelCache(meta.GetKeyWithoutPath()); } } return SUCCESS; @@ -1116,58 +1213,25 @@ void KvStoreDataService::PrintfInfo(int fd, const std::vector &me } info.append(GetIndentation(indentation)) .append("--------------------------------------------------------------------------\n") - .append(GetIndentation(indentation)) - .append("StoreID : ") - .append(data.storeId) - .append("\n") - .append(GetIndentation(indentation)) - .append("UId : ") - .append(data.user) - .append("\n") - .append(GetIndentation(indentation)) - .append("BundleName : ") - .append(data.bundleName) - .append("\n") - .append(GetIndentation(indentation)) - .append("AppID : ") - .append(data.appId) - .append("\n") - .append(GetIndentation(indentation)) - .append("StorePath : ") - .append(data.dataDir) - .append("\n") - .append(GetIndentation(indentation)) - .append("StoreType : ") - .append(std::to_string(data.storeType)) - .append("\n") - .append(GetIndentation(indentation)) - .append("encrypt : ") - .append(std::to_string(data.isEncrypt)) - .append("\n") - .append(GetIndentation(indentation)) - .append("autoSync : ") - .append(std::to_string(data.isAutoSync)) - .append("\n") - .append(GetIndentation(indentation)) - .append("schema : ") - .append(data.schema) - .append("\n") - .append(GetIndentation(indentation)) - .append("securityLevel : ") - .append(std::to_string(data.securityLevel)) - .append("\n") - .append(GetIndentation(indentation)) - .append("area : ") - .append(std::to_string(data.area)) - .append("\n") - .append(GetIndentation(indentation)) - .append("instanceID : ") - .append(std::to_string(data.instanceId)) - .append("\n") - .append(GetIndentation(indentation)) - .append("version : ") - .append(version) - .append("\n"); + .append(GetIndentation(indentation)).append("StoreID : ").append(data.storeId).append("\n") + .append(GetIndentation(indentation)).append("UId : ").append(data.user).append("\n") + .append(GetIndentation(indentation)).append("BundleName : ").append(data.bundleName).append("\n") + .append(GetIndentation(indentation)).append("AppID : ").append(data.appId).append("\n") + .append(GetIndentation(indentation)).append("StorePath : ").append(data.dataDir).append("\n") + .append(GetIndentation(indentation)).append("StoreType : ") + .append(std::to_string(data.storeType)).append("\n") + .append(GetIndentation(indentation)).append("encrypt : ") + .append(std::to_string(data.isEncrypt)).append("\n") + .append(GetIndentation(indentation)).append("autoSync : ") + .append(std::to_string(data.isAutoSync)).append("\n") + .append(GetIndentation(indentation)).append("schema : ").append(data.schema).append("\n") + .append(GetIndentation(indentation)).append("securityLevel : ") + .append(std::to_string(data.securityLevel)).append("\n") + .append(GetIndentation(indentation)).append("area : ") + .append(std::to_string(data.area)).append("\n") + .append(GetIndentation(indentation)).append("instanceID : ") + .append(std::to_string(data.instanceId)).append("\n") + .append(GetIndentation(indentation)).append("version : ").append(version).append("\n"); } dprintf(fd, "--------------------------------------StoreInfo-------------------------------------\n%s\n", info.c_str()); @@ -1316,9 +1380,12 @@ void KvStoreDataService::PrintfInfo(int fd, const std::map #include -#include "account_delegate.h" +#include "account/account_delegate.h" #include "clone/clone_backup_info.h" #include "clone/secret_key_backup_data.h" #include "dfx/reporter.h" @@ -92,12 +92,15 @@ public: void PrintfInfo(int fd, const std::map &datas); void DumpBundleInfo(int fd, std::map> ¶ms); - Status RegisterClientDeathObserver(const AppId &appId, sptr observer) override; + Status RegisterClientDeathObserver(const AppId &appId, sptr observer, + const std::string &featureName) override; sptr GetFeatureInterface(const std::string &name) override; int32_t ClearAppStorage(const std::string &bundleName, int32_t userId, int32_t appIndex, int32_t tokenId) override; + int32_t Exit(const std::string &featureName) override; + void OnDump() override; int Dump(int fd, const std::vector &args) override; @@ -134,18 +137,22 @@ public: int32_t OnBackup(MessageParcel &data, MessageParcel &reply); int32_t OnRestore(MessageParcel &data, MessageParcel &reply); bool WriteBackupInfo(const std::string &content, const std::string &backupPath); - bool GetSecretKeyBackup(const std::vector &bundleInfos, - const std::string &userId, const std::vector &iv, std::string &content); + std::string GetSecretKeyBackup(const std::vector &bundleInfos, + const std::string &userId, const std::vector &iv); private: void NotifyAccountEvent(const AccountEventInfo &eventInfo); class KvStoreClientDeathObserverImpl { public: - KvStoreClientDeathObserverImpl(const AppId &appId, KvStoreDataService &service, sptr observer); + KvStoreClientDeathObserverImpl(const AppId &appId, KvStoreDataService &service, sptr observer, + const std::string &featureName); explicit KvStoreClientDeathObserverImpl(KvStoreDataService &service); explicit KvStoreClientDeathObserverImpl(KvStoreClientDeathObserverImpl &&impl); KvStoreClientDeathObserverImpl &operator=(KvStoreClientDeathObserverImpl &&impl); - + bool Insert(sptr observer, const std::string &featureName); + bool Delete(const std::string &featureName); + bool Empty(); + std::string GetAppId(); virtual ~KvStoreClientDeathObserverImpl(); pid_t GetPid() const; @@ -159,6 +166,7 @@ private: private: KvStoreClientDeathObserverImpl &kvStoreClientDeathObserverImpl_; + std::atomic_bool clientDead_ = false; }; void NotifyClientDie(); void Reset(); @@ -167,7 +175,7 @@ private: uint32_t token_; AppId appId_; KvStoreDataService &dataService_; - sptr observerProxy_; + std::map> observerProxy_; sptr deathRecipient_; }; @@ -196,7 +204,7 @@ private: const std::vector &iv); bool ImportCloneKey(const std::string &keyStr); void DeleteCloneKey(); - + std::string GetBackupReplyCode(int replyCode, const std::string &info = ""); int32_t ReplyForRestore(MessageParcel &reply, int32_t result); @@ -221,5 +229,5 @@ private: static constexpr pid_t INVALID_PID = -1; static constexpr uint32_t INVALID_TOKEN = 0; }; -} // namespace OHOS::DistributedKv -#endif // KVSTORE_DATASERVICE_H \ No newline at end of file +} +#endif // KVSTORE_DATASERVICE_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service_stub.cpp b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service_stub.cpp index 4d0a55fab62ca5d40d0feffecf56d77298f17a82..3b74cbee45d238d8a0067adc34d058275c0118e2 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service_stub.cpp @@ -37,7 +37,8 @@ int32_t KvStoreDataServiceStub::RegisterClientDeathObserverOnRemote(MessageParce if (kvStoreClientDeathObserverProxy == nullptr) { return -1; } - Status status = RegisterClientDeathObserver(appId, std::move(kvStoreClientDeathObserverProxy)); + std::string featureName = data.ReadString(); + Status status = RegisterClientDeathObserver(appId, std::move(kvStoreClientDeathObserverProxy), featureName); if (!reply.WriteInt32(static_cast(status))) { return -1; } @@ -67,8 +68,21 @@ int32_t KvStoreDataServiceStub::ClearAppStorageOnRemote(MessageParcel &data, Mes if (!ITypesUtil::Unmarshal(data, bundleName, userId, appIndex, tokenId)) { return -1; } - auto remoteObject = ClearAppStorage(bundleName, userId, appIndex, tokenId); - if (!ITypesUtil::Marshal(reply, remoteObject)) { + auto code = ClearAppStorage(bundleName, userId, appIndex, tokenId); + if (!ITypesUtil::Marshal(reply, code)) { + return -1; + } + return 0; +} + +int32_t KvStoreDataServiceStub::ExitOnRemote(MessageParcel &data, MessageParcel &reply) +{ + std::string featureName; + if (!ITypesUtil::Unmarshal(data, featureName)) { + return -1; + } + auto code = Exit(featureName); + if (!ITypesUtil::Marshal(reply, code)) { return -1; } return 0; diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service_stub.h b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service_stub.h index 08767f6d565dc6e45c6f8d0f74207fd4cd6c13bb..2e776bd01fd3238b1554a559c431cf935db560b0 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service_stub.h +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service_stub.h @@ -26,6 +26,7 @@ private: int32_t GetFeatureInterfaceOnRemote(MessageParcel &data, MessageParcel &reply); int32_t RegisterClientDeathObserverOnRemote(MessageParcel &data, MessageParcel &reply); int32_t ClearAppStorageOnRemote(MessageParcel &data, MessageParcel &reply); + int32_t ExitOnRemote(MessageParcel &data, MessageParcel &reply); using RequestHandler = int32_t (KvStoreDataServiceStub::*)(MessageParcel &, MessageParcel &); using code = KvStoreDataServiceInterfaceCode; @@ -33,6 +34,7 @@ private: &KvStoreDataServiceStub::GetFeatureInterfaceOnRemote, &KvStoreDataServiceStub::RegisterClientDeathObserverOnRemote, &KvStoreDataServiceStub::ClearAppStorageOnRemote, + &KvStoreDataServiceStub::ExitOnRemote, }; }; } // namespace OHOS::DistributedKv diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.cpp b/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.cpp index 06b07a9c13d315fac66ba9deddd407564016d629..1472fdd593d2239797847c6403e2162908e11bf3 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.cpp @@ -20,11 +20,10 @@ #include #include -#include "account_delegate.h" +#include "account/account_delegate.h" #include "bootstrap.h" -#include "cloud/change_event.h" #include "communication_provider.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter.h" #include "device_matrix.h" #include "directory/directory_manager.h" @@ -144,11 +143,40 @@ void KvStoreMetaManager::InitMetaData() return; } + StoreMetaData data = InitStoreMetaData(); + StoreMetaDataLocal localData; + localData.isAutoSync = false; + localData.isBackup = false; + localData.isEncrypt = false; + localData.dataDir = metaDBDirectory_; + localData.schema = ""; + localData.isPublic = true; + MetaDataManager::GetInstance().SaveMeta(data.GetKeyWithoutPath(), data); + MetaDataManager::GetInstance().SaveMeta(data.GetKey(), data, true); + MetaDataManager::GetInstance().SaveMeta(data.GetKeyLocal(), localData, true); + std::string localUuid; + DeviceMetaData deviceMeta; + if (MetaDataManager::GetInstance().LoadMeta(deviceMeta.GetKey(), deviceMeta, true)) { + localUuid = deviceMeta.newUuid; + } else { + localUuid = DmAdapter::GetInstance().GetLocalDevice().uuid; + } + if (localUuid.empty()) { + ZLOGE("get uuid failed"); + return; + } + UpdateMetaData(localUuid); CheckMetaDeviceId(); + SetCloudSyncer(); + ZLOGI("end."); +} + +StoreMetaData KvStoreMetaManager::InitStoreMetaData() +{ + StoreMetaData data; auto uid = getuid(); auto tokenId = IPCSkeleton::GetCallingTokenID(); auto userId = AccountDelegate::GetInstance()->GetUserByToken(tokenId); - StoreMetaData data; data.appId = label_; data.appType = "default"; data.bundleName = label_; @@ -169,46 +197,89 @@ void KvStoreMetaManager::InitMetaData() data.securityLevel = SecurityLevel::S1; data.area = EL1; data.tokenId = tokenId; - StoreMetaDataLocal localData; - localData.isAutoSync = false; - localData.isBackup = false; - localData.isEncrypt = false; - localData.dataDir = metaDBDirectory_; - localData.schema = ""; - localData.isPublic = true; - if (!(MetaDataManager::GetInstance().SaveMeta(data.GetKey(), data) && - MetaDataManager::GetInstance().SaveMeta(data.GetKey(), data, true) && - MetaDataManager::GetInstance().SaveMeta(data.GetKeyLocal(), localData, true))) { - ZLOGE("save meta fail"); - } - UpdateMetaData(); - SetCloudSyncer(); - ZLOGI("end."); + return data; } -void KvStoreMetaManager::UpdateMetaData() +void KvStoreMetaManager::UpdateMetaData(const std::string &uuid) { VersionMetaData versionMeta; - if (!MetaDataManager::GetInstance().LoadMeta(versionMeta.GetKey(), versionMeta, true) - || versionMeta.version < META_VERSION) { + bool isExist = MetaDataManager::GetInstance().LoadMeta(versionMeta.GetKey(), versionMeta, true); + if (isExist && versionMeta.version == VersionMetaData::CURRENT_VERSION) { + return; + } + bool syncMetaUpdateNeeded = !isExist || versionMeta.version < VersionMetaData::UPDATE_SYNC_META_VERSION; + bool storeMetaUpgradeNeeded = !isExist || versionMeta.version < VersionMetaData::UPDATE_STORE_META_KEY_VERSION; + if (syncMetaUpdateNeeded) { std::vector metaDataList; - std::string prefix = StoreMetaData::GetPrefix({ DmAdapter::GetInstance().GetLocalDevice().uuid }); + std::string prefix = StoreMetaData::GetPrefix({ uuid }); MetaDataManager::GetInstance().LoadMeta(prefix, metaDataList); - for (auto metaData : metaDataList) { + std::vector keys; + for (const auto &metaData : metaDataList) { MetaDataManager::GetInstance().SaveMeta(metaData.GetKey(), metaData, true); if (CheckerManager::GetInstance().IsDistrust(Converter::ConvertToStoreInfo(metaData)) || - (metaData.storeType >= StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN - && metaData.storeType <= StoreMetaData::StoreType::STORE_RELATIONAL_END)) { - MetaDataManager::GetInstance().DelMeta(metaData.GetKey()); + (metaData.storeType >= StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN && + metaData.storeType <= StoreMetaData::StoreType::STORE_RELATIONAL_END)) { + keys.push_back(metaData.GetKey()); } } + MetaDataManager::GetInstance().DelMeta(keys); + versionMeta.version = VersionMetaData::UPDATE_SYNC_META_VERSION; + MetaDataManager::GetInstance().SaveMeta(versionMeta.GetKey(), versionMeta, true); } - if (versionMeta.version != VersionMetaData::CURRENT_VERSION) { - versionMeta.version = VersionMetaData::CURRENT_VERSION; + if (storeMetaUpgradeNeeded && UpgradeStoreMeta(uuid)) { + versionMeta.version = VersionMetaData::UPDATE_STORE_META_KEY_VERSION; MetaDataManager::GetInstance().SaveMeta(versionMeta.GetKey(), versionMeta, true); } } +// The metadata database is upgraded. The suffix is added to the path. +bool KvStoreMetaManager::UpgradeStoreMeta(const std::string &uuid) +{ + std::vector metaDataList; + std::string prefix = StoreMetaData::GetPrefix({ uuid }); + if (!MetaDataManager::GetInstance().LoadMeta(prefix, metaDataList, true)) { + ZLOGE("load meta failed"); + return false; + } + size_t batchSize = 100; // The batch quantity is 100. + return Constant::BatchProcess(metaDataList, batchSize, [](const auto &begin, const auto &end) { + std::vector entries; + std::vector deleteKeys; + auto size = static_cast(std::distance(begin, end)); + entries.reserve(size * 3); // Expand the entries size by 3 times. + deleteKeys.reserve(size * 4); // Expand the deleteKeys size by 4 times. + auto it = begin; + do { + auto &meta = *it; + StoreMetaDataLocal localMeta; + bool isExist = MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocalWithoutPath(), localMeta, true); + if (isExist) { + deleteKeys.push_back(meta.GetKeyLocalWithoutPath()); + entries.push_back({ meta.GetKeyLocal(), Serializable::Marshall(localMeta) }); + } + SecretKeyMetaData secretKeyMetaData; + isExist = MetaDataManager::GetInstance().LoadMeta(meta.GetSecretKeyWithoutPath(), secretKeyMetaData, true); + if (isExist) { + deleteKeys.push_back(meta.GetSecretKeyWithoutPath()); + entries.push_back({ meta.GetSecretKey(), Serializable::Marshall(secretKeyMetaData) }); + } + deleteKeys.push_back(meta.GetKeyWithoutPath()); + deleteKeys.push_back(meta.GetDebugInfoKeyWithoutPath()); + deleteKeys.push_back(meta.GetDfxInfoKeyWithoutPath()); + StoreMetaMapping storeMetaMapping(meta); + auto key = storeMetaMapping.GetKey(); + entries.push_back({ std::move(key), Serializable::Marshall(storeMetaMapping) }); + entries.push_back({ meta.GetKey(), Serializable::Marshall(meta) }); + } while (++it != end); + + if (MetaDataManager::GetInstance().SaveMeta(entries, true)) { + MetaDataManager::GetInstance().DelMeta(deleteKeys, true); + return true; + } + return false; + }); +} + void KvStoreMetaManager::InitMetaParameter() { ZLOGI("start."); @@ -581,11 +652,10 @@ void KvStoreMetaManager::CheckMetaDeviceId() if (deviceMeta.newUuid != localUuid) { UpdateStoreMetaData(localUuid, deviceMeta.newUuid); UpdateMetaDatas(localUuid, deviceMeta.newUuid); - deviceMeta.oldUuid = deviceMeta.newUuid; + ZLOGI("meta changed! cur uuid:%{public}s, old uuid:%{public}s", Anonymous::Change(localUuid).c_str(), + Anonymous::Change(deviceMeta.newUuid).c_str()); deviceMeta.newUuid = localUuid; MetaDataManager::GetInstance().SaveMeta(deviceMeta.GetKey(), deviceMeta, true); - ZLOGI("meta changed! curruuid:%{public}s, olduuid:%{public}s", - deviceMeta.newUuid.c_str(), deviceMeta.oldUuid.c_str()); } } @@ -601,10 +671,10 @@ void KvStoreMetaManager::UpdateStoreMetaData(const std::string &newUuid, const s MetaDataManager::GetInstance().DelMeta(oldMeta.GetKey(), true); StoreMetaData syncStoreMeta; - if (MetaDataManager::GetInstance().LoadMeta(oldMeta.GetKey(), syncStoreMeta)) { + if (MetaDataManager::GetInstance().LoadMeta(oldMeta.GetKeyWithoutPath(), syncStoreMeta)) { syncStoreMeta.deviceId = newUuid; - MetaDataManager::GetInstance().SaveMeta(storeMeta.GetKey(), syncStoreMeta); - MetaDataManager::GetInstance().DelMeta(oldMeta.GetKey()); + MetaDataManager::GetInstance().SaveMeta(storeMeta.GetKeyWithoutPath(), syncStoreMeta); + MetaDataManager::GetInstance().DelMeta(oldMeta.GetKeyWithoutPath()); } StrategyMeta strategyMeta; @@ -635,6 +705,21 @@ void KvStoreMetaManager::UpdateStoreMetaData(const std::string &newUuid, const s MetaDataManager::GetInstance().DelMeta(storeMeta.GetSecretKey(), true); MetaDataManager::GetInstance().DelMeta(storeMeta.GetCloneSecretKey(), true); } + MetaDataManager::GetInstance().DelMeta(oldMeta.GetDebugInfoKey(), true); + MetaDataManager::GetInstance().DelMeta(oldMeta.GetDfxInfoKey(), true); + } + UpdateStoreMetaMapping(newUuid, oldUuid); +} + +void KvStoreMetaManager::UpdateStoreMetaMapping(const std::string &newUuid, const std::string &oldUuid) +{ + std::vector storeMetaMappings; + MetaDataManager::GetInstance().LoadMeta(StoreMetaMapping::GetPrefix({ oldUuid }), storeMetaMappings, true); + for (auto &meta : storeMetaMappings) { + auto oldKey = meta.GetKey(); + meta.deviceId = newUuid; + MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true); + MetaDataManager::GetInstance().DelMeta(oldKey, true); } } diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.h b/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.h index f7b28e1cd2a2a29dbccdb8d170800c051ba829c2..df3abc6614bedcbe18c1a143ec79146d63784dd1 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.h +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.h @@ -75,7 +75,9 @@ private: void InitMetaData(); - void UpdateMetaData(); + DistributedData::StoreMetaData InitStoreMetaData(); + + void UpdateMetaData(const std::string &uuid); void SubscribeMetaKvStore(); @@ -100,8 +102,12 @@ private: void UpdateStoreMetaData(const std::string &newUuid, const std::string &oldUuid); + void UpdateStoreMetaMapping(const std::string &newUuid, const std::string &oldUuid); + void UpdateMetaDatas(const std::string &newUuid, const std::string &oldUuid); + static bool UpgradeStoreMeta(const std::string &uuid); + static ExecutorPool::Task GetBackupTask( TaskQueue queue, std::shared_ptr executors, const NbDelegate store); @@ -137,7 +143,6 @@ private: std::mutex mutex_; std::shared_ptr executors_; TaskId delaySyncTaskId_ = ExecutorPool::INVALID_TASK_ID; - static constexpr int32_t META_VERSION = 4; static constexpr int32_t MAX_TASK_COUNT = 1; }; } // namespace DistributedKv 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 f52cde722d9237a3e8c28bf215cee5d9ca0bdb2e..2399a18eff94ca990525dc2ace5a8be6adfc64b8 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 @@ -19,6 +19,8 @@ #include #include "account/account_delegate.h" #include "auth_delegate.h" +#include "access_check/app_access_check_config_manager.h" +#include "app_id_mapping/app_id_mapping_config_manager.h" #include "device_manager_adapter.h" #include "kvstore_meta_manager.h" #include "log_print.h" @@ -37,6 +39,9 @@ using DmAdapter = DistributedData::DeviceManagerAdapter; using DBManager = DistributedDB::KvStoreDelegateManager; constexpr const int ALIGN_WIDTH = 8; constexpr const char *DEFAULT_USERID = "0"; +constexpr const char *DATA_OBJECT_STORE_ID = "distributedObject_"; +constexpr const char *UDMF_STORE_ID = "drag"; + std::shared_ptr RouteHeadHandlerImpl::Create(const ExtendInfo &info) { auto handler = std::make_shared(info); @@ -58,62 +63,86 @@ RouteHeadHandlerImpl::RouteHeadHandlerImpl(const ExtendInfo &info) void RouteHeadHandlerImpl::Init() { ZLOGD("begin"); - if (deviceId_.empty()) { + if (deviceId_.empty() || !DmAdapter::GetInstance().IsOHOSType(deviceId_)) { return; } if (userId_ != DEFAULT_USERID) { - if (!DmAdapter::GetInstance().IsOHOSType(deviceId_)) { + StoreMetaData metaData; + metaData.deviceId = deviceId_; + metaData.user = DEFAULT_USERID; + metaData.bundleName = appId_; + metaData.storeId = storeId_; + if (MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)) { userId_ = DEFAULT_USERID; - } else { - StoreMetaData metaData; - metaData.deviceId = deviceId_; - metaData.user = DEFAULT_USERID; - metaData.bundleName = appId_; - metaData.storeId = storeId_; - if (MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData)) { - userId_ = DEFAULT_USERID; - } } } + if (appId_ == Bootstrap::GetInstance().GetProcessLabel() && storeId_ != Bootstrap::GetInstance().GetMetaDBName()) { + int foregroundUserId = 0; + AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + userId_ = std::to_string(foregroundUserId); + } SessionPoint localPoint { DmAdapter::GetInstance().GetLocalDevice().uuid, - static_cast(atoi(userId_.c_str())), appId_, storeId_ }; + static_cast(atoi(userId_.c_str())), appId_, storeId_, + AccountDelegate::GetInstance()->GetCurrentAccountId() }; session_ = SessionManager::GetInstance().GetSession(localPoint, deviceId_); ZLOGD("valid session:appId:%{public}s, srcDevId:%{public}s, srcUser:%{public}u, trgDevId:%{public}s,", session_.appId.c_str(), Anonymous::Change(session_.sourceDeviceId).c_str(), session_.sourceUserId, Anonymous::Change(session_.targetDeviceId).c_str()); } +std::string RouteHeadHandlerImpl::GetTargetUserId() +{ + if (!session_.IsValid()) { + ZLOGE("session has no valid user to peer device, targetDeviceId:%{public}s", + Anonymous::Change(session_.targetDeviceId).c_str()); + return ""; + } + return std::to_string(session_.targetUserIds[0]); +} + DistributedDB::DBStatus RouteHeadHandlerImpl::GetHeadDataSize(uint32_t &headSize) { ZLOGD("begin"); headSize = 0; - if (appId_ == Bootstrap::GetInstance().GetProcessLabel()) { + if (appId_ == Bootstrap::GetInstance().GetProcessLabel() && storeId_ != UDMF_STORE_ID && + storeId_ != DATA_OBJECT_STORE_ID) { ZLOGI("meta data permitted"); return DistributedDB::OK; } - auto devInfo = DmAdapter::GetInstance().GetDeviceInfo(session_.targetDeviceId); - if (devInfo.osType != OH_OS_TYPE) { - ZLOGD("devicdId:%{public}s is not oh type", - Anonymous::Change(session_.targetDeviceId).c_str()); + if (!DmAdapter::GetInstance().IsOHOSType(session_.targetDeviceId)) { + ZLOGD("deviceId:%{public}s is not oh type", Anonymous::Change(session_.targetDeviceId).c_str()); + if (appId_.empty()) { + return DistributedDB::DB_ERROR; + } + if (!AppAccessCheckConfigManager::GetInstance().IsTrust( + AppIdMappingConfigManager::GetInstance().Convert(appId_))) { + return DistributedDB::DB_ERROR; + } return DistributedDB::OK; } bool flag = false; auto peerCap = UpgradeManager::GetInstance().GetCapability(session_.targetDeviceId, flag); if (!flag) { ZLOGI("get peer cap failed"); - return DistributedDB::DB_ERROR; - } - if (peerCap.version == CapMetaData::INVALID_VERSION) { + return (appId_ == Bootstrap::GetInstance().GetProcessLabel() && + (storeId_ == UDMF_STORE_ID || storeId_ == DATA_OBJECT_STORE_ID)) + ? DistributedDB::OK + : DistributedDB::DB_ERROR; + } + if ((appId_ == Bootstrap::GetInstance().GetProcessLabel() && storeId_ != Bootstrap::GetInstance().GetMetaDBName() + && peerCap.version < CapMetaData::UDMF_AND_OBJECT_VERSION) + || peerCap.version == CapMetaData::INVALID_VERSION) { // older versions ignore pack extend head - ZLOGI("ignore older version device"); + ZLOGI("ignore older version device, appId:%{public}s, version:%{public}d", appId_.c_str(), peerCap.version); return DistributedDB::OK; } if (!session_.IsValid()) { ZLOGI("no valid session to peer device"); return DistributedDB::DB_ERROR; } - size_t expectSize = sizeof(RouteHead) + sizeof(SessionDevicePair) + sizeof(SessionUserPair) - + session_.targetUserIds.size() * sizeof(int) + sizeof(SessionAppId) + session_.appId.size(); + size_t expectSize = sizeof(RouteHead) + sizeof(SessionDevicePair) + sizeof(SessionUserPair) + + session_.targetUserIds.size() * sizeof(int) + sizeof(SessionAppId) + session_.appId.size() + + sizeof(SessionStoreId) + session_.storeId.size() + sizeof(SessionAccountId) + session_.accountId.size(); // align message uint width headSize = GET_ALIGNED_SIZE(expectSize, ALIGN_WIDTH); @@ -127,6 +156,10 @@ DistributedDB::DBStatus RouteHeadHandlerImpl::GetHeadDataSize(uint32_t &headSize DistributedDB::DBStatus RouteHeadHandlerImpl::FillHeadData(uint8_t *data, uint32_t headSize, uint32_t totalLen) { ZLOGD("begin"); + if (data == nullptr) { + ZLOGE("data is nullptr"); + return DistributedDB::DB_ERROR; + } if (headSize != headSize_) { ZLOGI("size not match"); return DistributedDB::DB_ERROR; @@ -193,26 +226,82 @@ bool RouteHeadHandlerImpl::PackDataBody(uint8_t *data, uint32_t totalLen) } ptr += (sizeof(SessionUserPair) + session_.targetUserIds.size() * sizeof(int)); - SessionAppId *appPair = reinterpret_cast(ptr); - ptr += sizeof(SessionAppId); + const uint8_t *end = data + totalLen; + if (!PackAppId(&ptr, end) || !PackStoreId(&ptr, end) || !PackAccountId(&ptr, end)) { + return false; + } + return true; +} - uint8_t *end = data + totalLen; +bool RouteHeadHandlerImpl::PackAppId(uint8_t **data, const uint8_t *end) +{ + SessionAppId *appPair = reinterpret_cast(*data); uint32_t appIdSize = session_.appId.size(); - ret = memcpy_s(appPair->appId, end - ptr, session_.appId.data(), appIdSize); - if (ret != 0) { - ZLOGE("strcpy for app id failed, error:%{public}d", errno); + appPair->len = HostToNet(appIdSize); + *data += sizeof(SessionAppId); + auto ret = memcpy_s(appPair->appId, end - *data, session_.appId.c_str(), appIdSize); + if (ret != EOK) { + ZLOGE("memcpy for app id failed, ret is %{public}d, leftSize is %{public}u, appIdSize is %{public}u", + ret, static_cast(end - *data), appIdSize); return false; } - appPair->len = HostToNet(appIdSize); + *data += appIdSize; + return true; +} + +bool RouteHeadHandlerImpl::PackStoreId(uint8_t **data, const uint8_t *end) +{ + SessionStoreId *storePair = reinterpret_cast(*data); + uint32_t storeIdSize = session_.storeId.size(); + storePair->len = HostToNet(storeIdSize); + *data += sizeof(SessionStoreId); + auto ret = memcpy_s(storePair->storeId, end - *data, session_.storeId.data(), storeIdSize); + if (ret != EOK) { + ZLOGE("memcpy for store id failed, ret is %{public}d, leftSize is %{public}u, storeIdSize is %{public}u", + ret, static_cast(end - *data), storeIdSize); + return false; + } + *data += storeIdSize; return true; } -bool RouteHeadHandlerImpl::ParseHeadDataLen(const uint8_t *data, uint32_t totalLen, uint32_t &headSize) +bool RouteHeadHandlerImpl::PackAccountId(uint8_t **data, const uint8_t *end) +{ + SessionAccountId *accountPair = reinterpret_cast(*data); + uint32_t accountIdSize = session_.accountId.size(); + accountPair->len = HostToNet(accountIdSize); + *data += sizeof(SessionAccountId); + auto ret = memcpy_s(accountPair->accountId, end - *data, session_.accountId.data(), accountIdSize); + if (ret != EOK) { + ZLOGE("memcpy for account id failed, ret is %{public}d, leftSize is %{public}u, storeIdSize is %{public}u", + ret, static_cast(end - *data), accountIdSize); + return false; + } + return true; +} + +bool RouteHeadHandlerImpl::ParseHeadDataLen(const uint8_t *data, uint32_t totalLen, uint32_t &headSize, + const std::string &device) { if (data == nullptr) { ZLOGE("invalid input data, totalLen:%{public}d", totalLen); return false; } + if (!DmAdapter::GetInstance().IsOHOSType(device)) { + ZLOGI("other type device received. device:%{public}s", Anonymous::Change(device).c_str()); + return true; + } + + if (appId_ == Bootstrap::GetInstance().GetProcessLabel() && + (storeId_ == UDMF_STORE_ID || storeId_ == DATA_OBJECT_STORE_ID)) { + bool flag = false; + auto peerCap = UpgradeManager::GetInstance().GetCapability(device, flag); + if (flag && peerCap.version < CapMetaData::UDMF_AND_OBJECT_VERSION) { + ZLOGI("get peer cap success, peerCap's version is %{public}d, less than 3", peerCap.version); + return false; + } + } + RouteHead head = { 0 }; auto ret = UnPackDataHead(data, totalLen, head); headSize = ret ? sizeof(RouteHead) + head.dataLen : 0; @@ -222,6 +311,9 @@ bool RouteHeadHandlerImpl::ParseHeadDataLen(const uint8_t *data, uint32_t totalL std::string RouteHeadHandlerImpl::ParseStoreId(const std::string &deviceId, const std::string &label) { + if (!session_.storeId.empty()) { + return session_.storeId; + } std::vector metaData; auto prefix = StoreMetaData::GetPrefix({ deviceId }); if (!MetaDataManager::GetInstance().LoadMeta(prefix, metaData)) { @@ -255,11 +347,12 @@ bool RouteHeadHandlerImpl::ParseHeadDataUser(const uint8_t *data, uint32_t total metaData.deviceId = session_.targetDeviceId; metaData.user = DEFAULT_USERID; metaData.bundleName = session_.appId; - metaData.storeId = storeId; - if (!MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData)) { + metaData.storeId = std::move(storeId); + if (!MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)) { int foregroundUserId = 0; AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); - UserInfo userInfo = { .receiveUser = std::to_string(foregroundUserId) }; + UserInfo userInfo = { .receiveUser = std::to_string(foregroundUserId), + .sendUser = std::to_string(session_.sourceUserId) }; userInfos.emplace_back(userInfo); return true; } @@ -268,14 +361,22 @@ bool RouteHeadHandlerImpl::ParseHeadDataUser(const uint8_t *data, uint32_t total // flip the local and peer ends SessionPoint local { .deviceId = session_.targetDeviceId, .appId = session_.appId }; - SessionPoint peer { .deviceId = session_.sourceDeviceId, .userId = session_.sourceUserId, .appId = session_.appId }; + SessionPoint peer { .deviceId = session_.sourceDeviceId, .userId = session_.sourceUserId, .appId = session_.appId, + .accountId = session_.accountId }; ZLOGD("valid session:appId:%{public}s, srcDevId:%{public}s, srcUser:%{public}u, trgDevId:%{public}s,", session_.appId.c_str(), Anonymous::Change(session_.sourceDeviceId).c_str(), session_.sourceUserId, Anonymous::Change(session_.targetDeviceId).c_str()); + bool flag = false; + auto peerCap = UpgradeManager::GetInstance().GetCapability(session_.sourceDeviceId, flag); + if (!flag) { + ZLOGI("get peer cap failed, peer deviceId:%{public}s", Anonymous::Change(session_.sourceDeviceId).c_str()); + return false; + } + bool accountFlag = peerCap.version >= CapMetaData::ACCOUNT_VERSION; for (const auto &item : session_.targetUserIds) { local.userId = item; - if (SessionManager::GetInstance().CheckSession(local, peer)) { - UserInfo userInfo = { .receiveUser = std::to_string(item) }; + if (SessionManager::GetInstance().CheckSession(local, peer, accountFlag)) { + UserInfo userInfo = { .receiveUser = std::to_string(item), .sendUser = std::to_string(peer.userId) }; userInfos.emplace_back(userInfo); } } @@ -325,7 +426,7 @@ bool RouteHeadHandlerImpl::UnPackDataHead(const uint8_t *data, uint32_t totalLen bool RouteHeadHandlerImpl::UnPackDataBody(const uint8_t *data, uint32_t totalLen) { - const uint8_t *ptr = data; + uint8_t *ptr = const_cast(data); uint32_t leftSize = totalLen; if (leftSize < sizeof(SessionDevicePair)) { @@ -358,17 +459,71 @@ bool RouteHeadHandlerImpl::UnPackDataBody(const uint8_t *data, uint32_t totalLen ptr += userPairSize; leftSize -= userPairSize; + if (!UnPackAppId(&ptr, leftSize)) { + return false; + } + bool flag = false; + auto peerCap = UpgradeManager::GetInstance().GetCapability(session_.sourceDeviceId, flag); + if (!flag) { + ZLOGE("get peer cap failed, peer deviceId:%{public}s", Anonymous::Change(session_.sourceDeviceId).c_str()); + return false; + } + if (peerCap.version >= CapMetaData::ACCOUNT_VERSION && + (!UnPackStoreId(&ptr, leftSize) || !UnPackAccountId(&ptr, leftSize))) { + return false; + } + return true; +} + +bool RouteHeadHandlerImpl::UnPackAppId(uint8_t **data, uint32_t leftSize) +{ if (leftSize < sizeof(SessionAppId)) { - ZLOGE("failed to parse app id, leftSize : %{public}d", leftSize); + ZLOGE("failed to parse app id, leftSize:%{public}d.", leftSize); return false; } - const SessionAppId *appId = reinterpret_cast(ptr); + const SessionAppId *appId = reinterpret_cast(*data); auto appIdLen = NetToHost(appId->len); if (leftSize - sizeof(SessionAppId) < appIdLen) { ZLOGE("failed to parse app id, appIdLen:%{public}d, leftSize:%{public}d.", appIdLen, leftSize); return false; } - session_.appId.append(appId->appId, appIdLen); + session_.appId = std::string(appId->appId, appIdLen); + leftSize -= (sizeof(SessionAppId) + appIdLen); + *data += (sizeof(SessionAppId) + appIdLen); + return true; +} + +bool RouteHeadHandlerImpl::UnPackStoreId(uint8_t **data, uint32_t leftSize) +{ + if (leftSize < sizeof(SessionStoreId)) { + ZLOGE("failed to parse store id, leftSize:%{public}d.", leftSize); + return false; + } + const SessionStoreId *storeId = reinterpret_cast(*data); + auto storeIdLen = NetToHost(storeId->len); + if (leftSize - sizeof(SessionStoreId) < storeIdLen) { + ZLOGE("failed to parse store id, storeIdLen:%{public}d, leftSize:%{public}d.", storeIdLen, leftSize); + return false; + } + session_.storeId = std::string(storeId->storeId, storeIdLen); + leftSize -= (sizeof(SessionAppId) + storeIdLen); + *data += (sizeof(SessionAppId) + storeIdLen); + return true; +} + +bool RouteHeadHandlerImpl::UnPackAccountId(uint8_t **data, uint32_t leftSize) +{ + if (leftSize < sizeof(SessionAccountId)) { + ZLOGE("failed to parse account id, leftSize:%{public}d.", leftSize); + return false; + } + const SessionAccountId *accountId = reinterpret_cast(*data); + auto accountIdLen = NetToHost(accountId->len); + if (leftSize - sizeof(SessionAccountId) < accountIdLen) { + ZLOGE("failed to parse account id, accountIdLen:%{public}d, leftSize:%{public}d.", accountIdLen, leftSize); + return false; + } + session_.accountId = std::string(accountId->accountId, accountIdLen); return true; } } // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.h b/datamgr_service/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.h index f23360dd7341b4a6430c6d6a30099122b5c0ffc0..85611780bd5256677d1d59686296a4a67622bbbc 100644 --- a/datamgr_service/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.h +++ b/datamgr_service/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.h @@ -53,6 +53,16 @@ struct SessionAppId { uint32_t len; char appId[0]; }; + +struct SessionStoreId { + uint32_t len; + char storeId[0]; +}; + +struct SessionAccountId { + uint32_t len; + char accountId[0]; +}; #pragma pack() class RouteHeadHandlerImpl : public DistributedData::RouteHeadHandler { @@ -61,20 +71,27 @@ public: explicit RouteHeadHandlerImpl(const ExtendInfo &info); DBStatus GetHeadDataSize(uint32_t &headSize) override; DBStatus FillHeadData(uint8_t *data, uint32_t headSize, uint32_t totalLen) override; - bool ParseHeadDataLen(const uint8_t *data, uint32_t totalLen, uint32_t &headSize) override; + bool ParseHeadDataLen(const uint8_t *data, uint32_t totalLen, uint32_t &headSize, + const std::string &device) override; bool ParseHeadDataUser(const uint8_t *data, uint32_t totalLen, const std::string &label, std::vector &userInfos) override; + std::string GetTargetUserId() override; private: void Init(); bool PackData(uint8_t *data, uint32_t totalLen); bool PackDataHead(uint8_t *data, uint32_t totalLen); bool PackDataBody(uint8_t *data, uint32_t totalLen); + bool PackAppId(uint8_t **data, const uint8_t *end); + bool PackStoreId(uint8_t **data, const uint8_t *end); + bool PackAccountId(uint8_t **data, const uint8_t *end); bool UnPackData(const uint8_t *data, uint32_t totalLen, uint32_t &unpackedSize); bool UnPackDataHead(const uint8_t *data, uint32_t totalLen, RouteHead &routeHead); bool UnPackDataBody(const uint8_t *data, uint32_t totalLen); + bool UnPackAppId(uint8_t **data, uint32_t leftSize); + bool UnPackStoreId(uint8_t **data, uint32_t leftSize); + bool UnPackAccountId(uint8_t **data, uint32_t leftSize); std::string ParseStoreId(const std::string &deviceId, const std::string &label); - std::string userId_; std::string appId_; std::string storeId_; 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 e13e43579f07d20b031ee1df5dd331fb0346b4b3..cb435f6fb7e4e66e16f64ddff865e6b03bec3c9e 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 @@ -44,9 +44,11 @@ Session SessionManager::GetSession(const SessionPoint &local, const std::string ZLOGD("begin. peer device:%{public}s", Anonymous::Change(targetDeviceId).c_str()); Session session; session.appId = local.appId; + session.storeId = local.storeId; session.sourceUserId = local.userId; session.sourceDeviceId = local.deviceId; session.targetDeviceId = targetDeviceId; + session.accountId = local.accountId; auto users = UserDelegate::GetInstance().GetRemoteUserStatus(targetDeviceId); // system service if (local.userId == UserDelegate::SYSTEM_USER) { @@ -64,6 +66,8 @@ Session SessionManager::GetSession(const SessionPoint &local, const std::string aclParams.accCallee.userId = user.id; auto [isPermitted, isSameAccount] = AuthDelegate::GetInstance()->CheckAccess(local.userId, user.id, targetDeviceId, aclParams); + ZLOGD("targetDeviceId:%{public}s, user.id:%{public}d, isPermitted:%{public}d, isSameAccount: %{public}d", + Anonymous::Change(targetDeviceId).c_str(), user.id, isPermitted, isSameAccount); if (isPermitted) { auto it = std::find(session.targetUserIds.begin(), session.targetUserIds.end(), user.id); if (it == session.targetUserIds.end() && isSameAccount) { @@ -91,7 +95,7 @@ bool SessionManager::GetSendAuthParams(const SessionPoint &local, const std::str for (const auto &storeMeta : metaData) { if (storeMeta.appId == local.appId && storeMeta.storeId == local.storeId) { aclParams.accCaller.bundleName = storeMeta.bundleName; - aclParams.accCaller.accountId = AccountDelegate::GetInstance()->GetCurrentAccountId(); + aclParams.accCaller.accountId = local.accountId; aclParams.accCaller.userId = local.userId; aclParams.accCaller.networkId = DmAdapter::GetInstance().ToNetworkID(local.deviceId); @@ -106,13 +110,13 @@ bool SessionManager::GetSendAuthParams(const SessionPoint &local, const std::str return false; } -bool SessionManager::GetRecvAuthParams(const SessionPoint &local, const std::string &targetDeviceId, - AclParams &aclParams, int32_t peerUser) const +bool SessionManager::GetRecvAuthParams(const SessionPoint &local, const SessionPoint &peer, bool accountFlag, + AclParams &aclParams) const { std::vector metaData; - if (!MetaDataManager::GetInstance().LoadMeta(StoreMetaData::GetPrefix({ targetDeviceId }), metaData)) { - ZLOGE("load meta failed, deviceId:%{public}s, user:%{public}d", Anonymous::Change(targetDeviceId).c_str(), - peerUser); + if (!MetaDataManager::GetInstance().LoadMeta(StoreMetaData::GetPrefix({ peer.deviceId }), metaData)) { + ZLOGE("load meta failed, deviceId:%{public}s, user:%{public}d", Anonymous::Change(peer.deviceId).c_str(), + peer.userId); return false; } for (const auto &storeMeta : metaData) { @@ -123,28 +127,30 @@ bool SessionManager::GetRecvAuthParams(const SessionPoint &local, const std::str aclParams.accCaller.userId = local.userId; aclParams.accCaller.networkId = DmAdapter::GetInstance().ToNetworkID(local.deviceId); - aclParams.accCallee.accountId = accountId; - aclParams.accCallee.userId = peerUser; - aclParams.accCallee.networkId = DmAdapter::GetInstance().ToNetworkID(targetDeviceId); + aclParams.accCallee.accountId = accountFlag ? peer.accountId : accountId; + aclParams.accCallee.userId = peer.userId; + aclParams.accCallee.networkId = DmAdapter::GetInstance().ToNetworkID(peer.deviceId); aclParams.authType = storeMeta.authType; return true; } } ZLOGE("get params failed,appId:%{public}s,tarDevid:%{public}s,user:%{public}d,peer:%{public}d", - local.appId.c_str(), Anonymous::Change(targetDeviceId).c_str(), local.userId, peerUser); + local.appId.c_str(), Anonymous::Change(peer.deviceId).c_str(), local.userId, peer.userId); return false; } -bool SessionManager::CheckSession(const SessionPoint &local, const SessionPoint &peer) const +bool SessionManager::CheckSession(const SessionPoint &local, const SessionPoint &peer, bool accountFlag) const { AclParams aclParams; - if (!GetRecvAuthParams(local, peer.deviceId, aclParams, peer.userId)) { + if (!GetRecvAuthParams(local, peer, accountFlag, aclParams)) { ZLOGE("get recv auth params failed:%{public}s", Anonymous::Change(peer.deviceId).c_str()); return false; } auto [isPermitted, isSameAccount] = AuthDelegate::GetInstance()->CheckAccess(local.userId, peer.userId, peer.deviceId, aclParams); + ZLOGD("peer.deviceId:%{public}s, peer.userId:%{public}d, isPermitted:%{public}d, isSameAccount: %{public}d", + Anonymous::Change(peer.deviceId).c_str(), peer.userId, isPermitted, isSameAccount); if (isPermitted && local.userId != UserDelegate::SYSTEM_USER) { isPermitted = Account::GetInstance()->IsUserForeground(local.userId); } @@ -159,6 +165,8 @@ bool Session::Marshal(json &node) const ret = SetValue(node[GET_NAME(sourceUserId)], sourceUserId) && ret; ret = SetValue(node[GET_NAME(targetUserIds)], targetUserIds) && ret; ret = SetValue(node[GET_NAME(appId)], appId) && ret; + ret = SetValue(node[GET_NAME(storeId)], storeId) && ret; + ret = SetValue(node[GET_NAME(accountId)], accountId) && ret; return ret; } @@ -170,6 +178,8 @@ bool Session::Unmarshal(const json &node) ret = GetValue(node, GET_NAME(sourceUserId), sourceUserId) && ret; ret = GetValue(node, GET_NAME(targetUserIds), targetUserIds) && ret; ret = GetValue(node, GET_NAME(appId), appId) && ret; + ret = GetValue(node, GET_NAME(storeId), storeId) && ret; + ret = GetValue(node, GET_NAME(accountId), accountId) && ret; return ret; } } // namespace OHOS::DistributedData 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 ca83970bc6494277011ba7bdf0aa3f67f341404d..c41e30c2381316ba24f4d9d574b47d2245e6a143 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 @@ -30,6 +30,7 @@ struct SessionPoint { uint32_t userId; std::string appId; std::string storeId; + std::string accountId; }; class Session : public Serializable { @@ -39,6 +40,8 @@ public: uint32_t sourceUserId; std::vector targetUserIds; std::string appId; + std::string storeId; + std::string accountId; bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; inline bool IsValid() @@ -51,12 +54,12 @@ class SessionManager { public: static SessionManager &GetInstance(); Session GetSession(const SessionPoint &local, const std::string &targetDeviceId) const; - bool CheckSession(const SessionPoint &local, const SessionPoint &peer) const; + bool CheckSession(const SessionPoint &local, const SessionPoint &peer, bool accountFlag) const; private: bool GetSendAuthParams(const SessionPoint &local, const std::string &targetDeviceId, AclParams &aclParams) const; - bool GetRecvAuthParams(const SessionPoint &local, const std::string &targetDeviceId, - AclParams &aclParams, int peerUser) const; + bool GetRecvAuthParams(const SessionPoint &local, const SessionPoint &peer, bool accountFlag, + AclParams &aclParams) 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 4055f30f131ba62cb609b7d17a3bae9ae415bc51..7654c983cb7a38d1315096fc3bc08b4fd2bb5cd7 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 @@ -16,14 +16,10 @@ #include "upgrade_manager.h" -#include -#include "account_delegate.h" #include "device_manager_adapter.h" #include "log_print.h" #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; @@ -36,18 +32,42 @@ UpgradeManager &UpgradeManager::GetInstance() void UpgradeManager::Init(std::shared_ptr executors) { - if (executors_) { - return; + MetaDataManager::GetInstance().Subscribe( + CapMetaRow::KEY_PREFIX, [this](const std::string &key, const std::string &value, int32_t flag) -> auto { + CapMetaData capMeta; + if (value.empty()) { + MetaDataManager::GetInstance().LoadMeta(key, capMeta); + } else { + CapMetaData::Unmarshall(value, capMeta); + } + auto deviceId = CapMetaRow::GetDeviceId(key); + if (deviceId.empty()) { + ZLOGE("deviceId is empty, key:%{public}s, flag:%{public}d", Anonymous::Change(key).c_str(), flag); + return false; + } + if (deviceId == DmAdapter::GetInstance().GetLocalDevice().uuid) { + return true; + } + capMeta.deviceId = capMeta.deviceId.empty() ? deviceId : capMeta.deviceId; + ZLOGI("CapMetaData has change, deviceId:%{public}s, version:%{public}d, flag:%{public}d", + Anonymous::Change(capMeta.deviceId).c_str(), capMeta.version, flag); + if (flag == MetaDataManager::INSERT || flag == MetaDataManager::UPDATE) { + capabilities_.InsertOrAssign(capMeta.deviceId, capMeta); + } else if (flag == MetaDataManager::DELETE) { + capabilities_.Erase(capMeta.deviceId); + } + return true; + }); + if (executors != nullptr) { + executors_ = std::move(executors); + executors_->Execute(GetTask()); } - executors_ = std::move(executors); - executors_->Execute(GetTask()); } ExecutorPool::Task UpgradeManager::GetTask() { return [this] { - auto succ = InitLocalCapability(); - if (succ) { + if (InitLocalCapability() || executors_ == nullptr) { return; } executors_->Schedule(std::chrono::milliseconds(RETRY_INTERVAL), GetTask()); @@ -79,6 +99,7 @@ bool UpgradeManager::InitLocalCapability() auto localDeviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; CapMetaData capMetaData; capMetaData.version = CapMetaData::CURRENT_VERSION; + capMetaData.deviceId = localDeviceId; auto dbKey = CapMetaRow::GetKeyFor(localDeviceId); bool status = MetaDataManager::GetInstance().SaveMeta({ dbKey.begin(), dbKey.end() }, capMetaData); if (status) { 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 411181e38e372792d92b7b4dc7c30b57b9ae4730..fd4ec20f3d5e2db193f58573e47c1ef8afe5b960 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 @@ -15,18 +15,13 @@ #ifndef DISTRIBUTEDDATAMGR_UPGRADE_MANAGER_H #define DISTRIBUTEDDATAMGR_UPGRADE_MANAGER_H -#include -#include "auth_delegate.h" #include "concurrent_map.h" -#include "kvstore_meta_manager.h" #include "metadata/capability_meta_data.h" #include "executor_pool.h" #include "types.h" -namespace OHOS::DistributedData { -using DistributedDB::KvStoreNbDelegate; -using OHOS::DistributedKv::KvStoreTuple; +namespace OHOS::DistributedData { class UpgradeManager { public: static UpgradeManager &GetInstance(); @@ -39,10 +34,6 @@ private: ExecutorPool::Task GetTask(); ConcurrentMap capabilities_ {}; std::shared_ptr executors_; - - static constexpr int32_t NO_ACCOUNT = 0; - static constexpr int32_t IDENTICAL_ACCOUNT = 1; - static constexpr const char *defaultAccountId = "ohosAnonymousUid"; }; } // namespace OHOS::DistributedData #endif // DISTRIBUTEDDATAMGR_UPGRADE_MANAGER_H diff --git a/datamgr_service/services/distributeddataservice/app/test/BUILD.gn b/datamgr_service/services/distributeddataservice/app/test/BUILD.gn index f3f912893b8e5116624b87af6f4ac5a03609c808..d79c567b82e43464b623d1a8631c8cd23ef2f959 100644 --- a/datamgr_service/services/distributeddataservice/app/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/test/BUILD.gn @@ -19,12 +19,6 @@ module_output_path = "datamgr_service/datamgr_service/distributeddataservice" config("module_private_config") { visibility = [ ":*" ] include_dirs = [ - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/common", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/src", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_path}/interfaces/innerkits/distributeddata/include", "${data_service_path}/adapter/include/permission", "${data_service_path}/adapter/include/account", "${data_service_path}/adapter/include", @@ -41,9 +35,7 @@ config("module_private_config") { "${data_service_path}/app/src", "${data_service_path}/app/src/session_manager", "${data_service_path}/service/kvdb", - "${device_manager_path}/interfaces/inner_kits/native_cpp/include", - "//commonlibrary/c_utils/base/include", - "//utils/system/safwk/native/include", + "${data_service_path}/service/test/mock", "../include", "../src", "../src/security", @@ -52,7 +44,6 @@ config("module_private_config") { "../../service/backup/include", "../../../../interfaces/innerkits/distributeddata", "../../service/dumper/include", - "//third_party/json/single_include", "${data_service_path}/adapter/include/communicator", ] @@ -96,9 +87,22 @@ ohos_unittest("KvStoreDataServiceTest") { "${data_service_path}/app/src/session_manager/upgrade_manager.cpp", "${data_service_path}/app/src/task_manager.cpp", "${data_service_path}/app/test/unittest/kvstore_data_service_test.cpp", + "${data_service_path}/app/test/unittest/security_test.cpp", + "${data_service_path}/app/test/unittest/sensitive_test.cpp", "${data_service_path}/service/common/xcollie.cpp", ] + sanitize = { + ubsan = true + boundary_sanitize = true + integer_overflow = true + cfi_no_nvcall = true + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } + configs = [ ":module_private_config" ] external_deps = [ @@ -109,7 +113,9 @@ ohos_unittest("KvStoreDataServiceTest") { "common_event_service:cesfwk_innerkits", "dataclassification:data_transit_mgr", "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", "file_api:securitylabel", + "googletest:gtest_main", "hicollie:libhicollie", "hilog:libhilog", "hisysevent:libhisysevent", @@ -117,7 +123,9 @@ ohos_unittest("KvStoreDataServiceTest") { "hitrace:libhitracechain", "ipc:ipc_core", "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", "kv_store:distributeddb", + "kv_store:kvdb_inner_lite", "memmgr:memmgrclient", "safwk:system_ability_fwk", "samgr:samgr_proxy", @@ -133,7 +141,84 @@ ohos_unittest("KvStoreDataServiceTest") { deps = [ "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//third_party/googletest:gtest_main", + ] + part_name = "datamgr_service" +} + +ohos_unittest("KvStoreMetaManagerUpdateKeyTest") { + module_out_path = module_output_path + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } + sources = [ + "${data_service_path}/app/src/checker/bundle_checker.cpp", + "${data_service_path}/app/src/checker/system_checker.cpp", + "${data_service_path}/app/src/clone/clone_backup_info.cpp", + "${data_service_path}/app/src/clone/secret_key_backup_data.cpp", + "${data_service_path}/app/src/db_info_handle_impl.cpp", + "${data_service_path}/app/src/feature_stub_impl.cpp", + "${data_service_path}/app/src/installer/installer.cpp", + "${data_service_path}/app/src/installer/installer_impl.cpp", + "${data_service_path}/app/src/kvstore_account_observer.cpp", + "${data_service_path}/app/src/kvstore_data_service.cpp", + "${data_service_path}/app/src/kvstore_data_service_stub.cpp", + "${data_service_path}/app/src/kvstore_device_listener.cpp", + "${data_service_path}/app/src/kvstore_meta_manager.cpp", + "${data_service_path}/app/src/kvstore_screen_observer.cpp", + "${data_service_path}/app/src/security/security.cpp", + "${data_service_path}/app/src/security/sensitive.cpp", + "${data_service_path}/app/src/session_manager/route_head_handler_impl.cpp", + "${data_service_path}/app/src/session_manager/session_manager.cpp", + "${data_service_path}/app/src/session_manager/upgrade_manager.cpp", + "${data_service_path}/app/src/task_manager.cpp", + "${data_service_path}/app/test/unittest/kvstore_meta_manager_update_key_test.cpp", + "${data_service_path}/service/common/xcollie.cpp", + "${data_service_path}/service/test/mock/device_manager_adapter_mock.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:want", + "access_token:libaccesstoken_sdk", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "dataclassification:data_transit_mgr", + "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", + "file_api:securitylabel", + "googletest:gmock", + "googletest:gtest_main", + "hicollie:libhicollie", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "kv_store:kvdb_inner_lite", + "memmgr:memmgrclient", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + if (datamgr_service_power) { + external_deps += [ + "battery_manager:batterysrv_client", + "power_manager:powermgr_client", + ] + } + cflags = [ + "-fno-access-control", # Ignore Private Member Access Control + ] + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", ] part_name = "datamgr_service" } @@ -153,6 +238,7 @@ ohos_unittest("SessionManagerTest") { cfi = true cfi_cross_dso = true debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" } cflags_cc = [ "-DUT_TEST" ] @@ -160,15 +246,23 @@ ohos_unittest("SessionManagerTest") { external_deps = [ "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "access_token:libtoken_setproc", "c_utils:utils", "dataclassification:data_transit_mgr", "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", "file_api:securitylabel", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "ipc:ipc_core", + "json:nlohmann_json_static", + "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "kv_store:kvdb_inner_lite", "safwk:system_ability_fwk", "samgr:samgr_proxy", ] @@ -183,12 +277,9 @@ ohos_unittest("SessionManagerTest") { deps = [ "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/app/src/checker:distributeddata_checker", - "${kv_store_path}/interfaces/innerkits/distributeddatamgr:distributeddata_mgr", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/service:distributeddatasvc", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "${data_service_path}/service/test/mock:distributeddata_mock_static", ] part_name = "datamgr_service" @@ -233,16 +324,20 @@ ohos_unittest("KvStoreDataServiceClearTest") { "c_utils:utils", "dataclassification:data_transit_mgr", "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", "file_api:securitylabel", + "googletest:gtest_main", "hicollie:libhicollie", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", "hitrace:libhitracechain", "ipc:ipc_core", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", "kv_store:distributeddb", + "kv_store:kvdb_inner_lite", "memmgr:memmgrclient", "safwk:system_ability_fwk", "samgr:samgr_proxy", @@ -261,7 +356,6 @@ ohos_unittest("KvStoreDataServiceClearTest") { "${data_service_path}/app/src/installer:distributeddata_installer", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//third_party/googletest:gtest_main", ] part_name = "datamgr_service" @@ -298,6 +392,7 @@ ohos_unittest("FeatureStubImplTest") { "c_utils:utils", "dataclassification:data_transit_mgr", "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", "file_api:securitylabel", "googletest:gtest_main", "hilog:libhilog", @@ -329,6 +424,166 @@ ohos_unittest("FeatureStubImplTest") { part_name = "datamgr_service" } +ohos_unittest("UpgradeManagerTest") { + module_out_path = module_output_path + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + + include_dirs = [ + "${data_service_path}/app/src/session_manager", + "${data_service_path}/app/test/mock/capability", + "${data_service_path}/framework/include", + ] + + sources = [ + "${data_service_path}/app/test/mock/capability/metadata/meta_data_manager.cpp", + "${data_service_path}/app/test/mock/capability/device_manager_adapter.cpp", + "${data_service_path}/app/src/session_manager/upgrade_manager.cpp", + "${data_service_path}/framework/metadata/capability_meta_data.cpp", + "${data_service_path}/framework/serializable/serializable.cpp", + "${data_service_path}/framework/utils/anonymous.cpp", + "${data_service_path}/framework/utils/constant.cpp", + "${data_service_path}/app/test/unittest/upgrade_manager_test.cpp", + ] + + external_deps = [ + "c_utils:utils", + "googletest:gtest_main", + "hilog:libhilog", + "json:nlohmann_json_static", + "kv_store:distributeddata_inner", + ] + + part_name = "datamgr_service" +} + +ohos_unittest("RouteHeadHandlerImplTest") { + module_out_path = module_output_path + + include_dirs = [ + "${data_service_path}/adapter/include/permission", + "${data_service_path}/adapter/include/account", + "${data_service_path}/adapter/include", + "${data_service_path}/adapter/include/utils", + "${data_service_path}/framework/include", + "${data_service_path}/service/bootstrap/include", + "${data_service_path}/service/common", + "${data_service_path}/service/config/include", + "${data_service_path}/service/crypto/include", + "${data_service_path}/service/data_share/common", + "${data_service_path}/service/directory/include", + "${data_service_path}/service/permission/include", + "${data_service_path}/service/matrix/include", + "${data_service_path}/app/src", + "${data_service_path}/app/src/session_manager", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/test/mock", + "../include", + "../src", + "../src/security", + "unittest", + "../src/installer", + "../../service/backup/include", + "../../../../interfaces/innerkits/distributeddata", + "../../service/dumper/include", + "${data_service_path}/adapter/include/communicator", + ] + + sources = [ + "../src/kvstore_meta_manager.cpp", + "../src/session_manager/route_head_handler_impl.cpp", + "../src/session_manager/session_manager.cpp", + "../src/session_manager/upgrade_manager.cpp", + "unittest/route_head_handler_impl_test.cpp", + ] + + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } + + cflags_cc = [ "-DUT_TEST" ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "access_token:libtoken_setproc", + "c_utils:utils", + "dataclassification:data_transit_mgr", + "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", + "file_api:securitylabel", + "googletest:gmock", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "ipc:ipc_core", + "json:nlohmann_json_static", + "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + if (datamgr_service_power) { + external_deps += [ + "battery_manager:batterysrv_client", + "power_manager:powermgr_client", + ] + } + + deps = [ + "${data_service_path}/adapter/utils:distributeddata_utils", + "${data_service_path}/app/src/checker:distributeddata_checker", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "${data_service_path}/service/test/mock:distributeddata_mock_static", + ] + + cflags = [ + "-Werror", + "-Dprivate=public", + "-Dprotected=public", + ] + ldflags = [ "-Wl,--whole-archive" ] + defines = [ + "TEST_ON_DEVICE", + "OPENSSL_SUPPRESS_DEPRECATED", + ] + + part_name = "datamgr_service" +} + +ohos_unittest("BundleCheckerTest") { + module_out_path = module_output_path + sources = [ "unittest/bundle_checker_test.cpp" ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "c_utils:utils", + "googletest:gtest_main", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "openssl:libcrypto_shared", + ] + + deps = [ + "${data_service_path}/app/src/checker:distributeddata_checker", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + ] +} + ############################################################################### group("unittest") { @@ -336,24 +591,13 @@ group("unittest") { deps = [] deps += [ + ":BundleCheckerTest", ":FeatureStubImplTest", ":KvStoreDataServiceClearTest", ":KvStoreDataServiceTest", + ":KvStoreMetaManagerUpdateKeyTest", ":SessionManagerTest", + ":UpgradeManagerTest", + ":RouteHeadHandlerImplTest", ] -} - -############################################################################### -group("moduletest") { - testonly = true - deps = [ - "//third_party/googletest:gmock", - "//third_party/googletest:gtest_main", - "//third_party/sqlite:sqlite", - ] - - deps += [ - #":DistributedDataAccountEventModuleTest", - ] -} -############################################################################### +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/BUILD.gn index a04a1d620a19c27b38bf96374ceebea23cd0ea63..94d220992a5f20d4bb72642aae398a2a6073e554 100644 --- a/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/BUILD.gn @@ -20,9 +20,6 @@ ohos_fuzztest("DataServiceStubFuzzTest") { module_out_path = "datamgr_service/datamgr_service" include_dirs = [ - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", "${data_service_path}/service/bootstrap/include", "${data_service_path}/service/config/include", "${data_service_path}/service/crypto/include", @@ -46,8 +43,6 @@ ohos_fuzztest("DataServiceStubFuzzTest") { "${data_service_path}/adapter/include/installer", "${data_service_path}/adapter/include/utils", "${data_service_path}/adapter/include", - "${device_manager_path}/interfaces/inner_kits/native_cpp/include", - "//third_party/json/single_include", "${data_service_path}/adapter/include/communicator", ] @@ -89,7 +84,6 @@ ohos_fuzztest("DataServiceStubFuzzTest") { "${data_service_path}/app/src/installer:distributeddata_installer", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "${kv_store_distributeddb_path}:distributeddb", ] external_deps = [ @@ -100,6 +94,7 @@ ohos_fuzztest("DataServiceStubFuzzTest") { "bundle_framework:appexecfwk_core", "c_utils:utils", "dataclassification:data_transit_mgr", + "device_manager:devicemanagersdk", "file_api:securitylabel", "hicollie:libhicollie", "hilog:libhilog", @@ -109,6 +104,7 @@ ohos_fuzztest("DataServiceStubFuzzTest") { "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", + "kv_store:distributeddb", "memmgr:memmgrclient", "safwk:system_ability_fwk", "samgr:samgr_proxy", diff --git a/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/dataservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/dataservicestub_fuzzer.cpp index e5164c9424b81e5de3a566e98209b206d5520b4d..27f99656040b19dfdd07e8ecf194d0bac34c510d 100644 --- a/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/dataservicestub_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/dataservicestub_fuzzer.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "dataservicestub_fuzzer.h" #include @@ -29,12 +31,13 @@ const std::u16string INTERFACE_TOKEN = u"OHOS.DistributedKv.IKvStoreDataService" const uint32_t CODE_MIN = 0; const uint32_t CODE_MAX = 10; -bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { - uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + uint32_t code = provider.ConsumeIntegralInRange(CODE_MIN, CODE_MAX); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); - request.WriteBuffer(data, size); + std::vector remainingData = provider.ConsumeRemainingBytes(); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); request.RewindRead(0); MessageParcel reply; MessageOption option; @@ -47,11 +50,7 @@ bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::OnRemoteRequestFuzz(data, size); - + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/mock/capability/device_manager_adapter.cpp b/datamgr_service/services/distributeddataservice/app/test/mock/capability/device_manager_adapter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..76e30d2759644805e1f14b95131c4fad32298a92 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/mock/capability/device_manager_adapter.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 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 "device_manager_adapter.h" + +namespace OHOS::DistributedData { +static constexpr const char* LOCAL_DEVICE = "ABCDEF0123456789"; +DeviceManagerAdapter &DeviceManagerAdapter::GetInstance() +{ + static DeviceManagerAdapter dmAdapter; + return dmAdapter; +} + +DeviceInfo DeviceManagerAdapter::GetLocalDevice() +{ + return { .uuid = LOCAL_DEVICE }; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/mock/capability/device_manager_adapter.h b/datamgr_service/services/distributeddataservice/app/test/mock/capability/device_manager_adapter.h new file mode 100644 index 0000000000000000000000000000000000000000..ceb43b532bf2babbb97d826607e1b037cf93f8c5 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/mock/capability/device_manager_adapter.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 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 MOCK_META_DEVICE_MANAGER_H +#define MOCK_META_DEVICE_MANAGER_H + +#include + +namespace OHOS::DistributedData { +struct DeviceInfo { + std::string uuid; +}; + +class DeviceManagerAdapter { +public: + static DeviceManagerAdapter &GetInstance(); + DeviceInfo GetLocalDevice(); + +private: + DeviceManagerAdapter() = default; + ~DeviceManagerAdapter() = default; +}; +} // namespace OHOS::DistributedData +#endif // MOCK_META_DEVICE_MANAGER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/mock/capability/metadata/meta_data_manager.cpp b/datamgr_service/services/distributeddataservice/app/test/mock/capability/metadata/meta_data_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..867002fdb90ab82addd9300dcd4f6bd17538e41b --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/mock/capability/metadata/meta_data_manager.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2025 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 "meta_data_manager.h" + +namespace OHOS::DistributedData { +MetaDataManager &MetaDataManager::GetInstance() +{ + static MetaDataManager instance; + return instance; +} + +void MetaDataManager::Init(std::shared_ptr executors) +{ + executors_ = std::move(executors); +} + +bool MetaDataManager::SaveMeta(const std::string &key, const CapMetaData &value) +{ + capabilities_.InsertOrAssign(key, value); + executors_->Execute([this, key, value]() { + if (capObserver_ != nullptr) { + capObserver_(key, Serializable::Marshall(value), INSERT); + } + }); + return true; +} + +bool MetaDataManager::LoadMeta(const std::string &key, CapMetaData &value) +{ + auto index = capabilities_.Find(key); + if (index.first) { + value = index.second; + return true; + } + return false; +} + +bool MetaDataManager::Subscribe(std::string prefix, Observer observer) +{ + (void)prefix; + capObserver_ = observer; + return true; +} + +void MetaDataManager::UnSubscribe() +{ + capObserver_ = nullptr; +} + +bool MetaDataManager::UpdateMeta(const std::string &key, const CapMetaData &value) +{ + capabilities_.InsertOrAssign(key, value); + executors_->Execute([this, key, value]() { + if (capObserver_ != nullptr) { + capObserver_(key, Serializable::Marshall(value), UPDATE); + } + }); + return true; +} + +bool MetaDataManager::DeleteMeta(const std::string &key, const CapMetaData &value) +{ + capabilities_.Erase(key); + executors_->Execute([this, key, value]() { + if (capObserver_ != nullptr) { + capObserver_(key, Serializable::Marshall(value), DELETE); + } + }); + return true; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/include/rdb_fault_hiview_reporter.h b/datamgr_service/services/distributeddataservice/app/test/mock/capability/metadata/meta_data_manager.h similarity index 35% rename from relational_store/frameworks/native/gdb/include/rdb_fault_hiview_reporter.h rename to datamgr_service/services/distributeddataservice/app/test/mock/capability/metadata/meta_data_manager.h index c67b3c2773b5e45f0bba1b8d6679c57f202f2773..8fbf3814f1d1525ded5214d61f4038de0de9a52c 100644 --- a/relational_store/frameworks/native/gdb/include/rdb_fault_hiview_reporter.h +++ b/datamgr_service/services/distributeddataservice/app/test/mock/capability/metadata/meta_data_manager.h @@ -13,38 +13,42 @@ * limitations under the License. */ -#ifndef DISTRIBUTEDDATAMGR_GDB_FAULT_HIVIEW_REPORTER_H -#define DISTRIBUTEDDATAMGR_GDB_FAULT_HIVIEW_REPORTER_H +#ifndef MOCK_META_DATA_MANAGER_H +#define MOCK_META_DATA_MANAGER_H -#include -#include "rdb_store_config.h" +#include -namespace OHOS::NativeRdb { -// Fault Type Define -static constexpr const char *FT_OPEN = "OPEN_DB"; -static constexpr const char *FT_CURD = "CURD_DB"; -static constexpr const char *FT_EX_FILE = "EX_FILE"; -static constexpr const char *FT_EX_HUKS = "EX_HUKS"; -static constexpr const char *FT_CP = "CHECK_POINT"; +#include "metadata/capability_meta_data.h" +#include "concurrent_map.h" +#include "executor_pool.h" -class RdbFaultEvent { +namespace OHOS::DistributedData { +class MetaDataManager { public: - RdbFaultEvent(const std::string &faultType, int32_t errorCode, const std::string &bundleName, - const std::string &custLog) {}; -}; + enum Action : int32_t { + INSERT = 0, + UPDATE = 1, + DELETE = 2, + }; + + using Observer = std::function; + + static MetaDataManager &GetInstance(); + void Init(std::shared_ptr executors); + bool SaveMeta(const std::string &key, const CapMetaData &value); + bool LoadMeta(const std::string &key, CapMetaData &value); + bool Subscribe(std::string prefix, Observer observer); + void UnSubscribe(); + bool UpdateMeta(const std::string &key, const CapMetaData &value); + bool DeleteMeta(const std::string &key, const CapMetaData &value); -class RdbFaultDbFileEvent : public RdbFaultEvent { -public: - RdbFaultDbFileEvent(const std::string &faultType, int32_t errorCode, const RdbStoreConfig &config, - const std::string &custLog = "", bool printDbInfo = false) - : RdbFaultEvent(faultType, errorCode, "", custLog), config_(config) {} private: - RdbStoreConfig config_; -}; + MetaDataManager() = default; + ~MetaDataManager() = default; -class RdbFaultHiViewReporter { -public: - static void ReportFault(const RdbFaultEvent &faultEvent) {}; + Observer capObserver_; + ConcurrentMap capabilities_ {}; + std::shared_ptr executors_; }; -} // namespace OHOS::NativeRdb -#endif // DISTRIBUTEDDATAMGR_GDB_FAULT_HIVIEW_REPORTER_H \ No newline at end of file +} // namespace OHOS::DistributedData +#endif // MOCK_META_DATA_MANAGER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/bundle_checker_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/bundle_checker_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..deb5c7def0c2f786a65477ee618ac6e1146cd0b4 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/bundle_checker_test.cpp @@ -0,0 +1,118 @@ +/* +* Copyright (c) 2025 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 "accesstoken_kit.h" +#include "checker/bundle_checker.h" +#include "bootstrap.h" +#include "hap_token_info.h" +#include "nativetoken_kit.h" +#include "utils/crypto.h" +using namespace testing::ext; +using namespace OHOS::DistributedData; +using namespace OHOS::Security::AccessToken; +class BundleCheckerTest : public testing::Test { +public: + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} + void SetUp(); + void TearDown(); + NativeTokenInfoParams infoInstance{0}; +}; + +void BundleCheckerTest::SetUp(void) +{ + infoInstance.dcapsNum = 0; + infoInstance.permsNum = 0; + infoInstance.aclsNum = 0; + infoInstance.dcaps = nullptr; + infoInstance.perms = nullptr; + infoInstance.acls = nullptr; + infoInstance.processName = "BundleCheckerTest"; + infoInstance.aplStr = "system_core"; + + HapInfoParams info = { + .userID = 100, + .bundleName = "com.ohos.dlpmanager", + .instIndex = 0, + .appIDDesc = "com.ohos.dlpmanager" + }; + PermissionDef infoManagerTestPermDef = { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.test.demo", + .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); + + Bootstrap::GetInstance().LoadComponents(); + Bootstrap::GetInstance().LoadDirectory(); + Bootstrap::GetInstance().LoadCheckers(); + Bootstrap::GetInstance().LoadNetworks(); +} + +void BundleCheckerTest::TearDown() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(100, "com.ohos.dlpmanager", 0); + AccessTokenKit::DeleteToken(tokenId); +} + +/** +* @tc.name: GetAppIdTest001 +* @tc.desc: get appId from cache. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(BundleCheckerTest, GetAppIdTest001, TestSize.Level0) +{ + CheckerManager::StoreInfo info; + auto tokenId = AccessTokenKit::GetHapTokenID(100, "com.ohos.dlpmanager", 0); + info.uid = 100 * 200000; + info.tokenId = tokenId; + info.bundleName = "com.ohos.dlpmanager"; + BundleChecker checker; + std::string appIdInCache; + ASSERT_TRUE(!checker.GetAppId(info).empty()); + checker.appIds_.Get("com.ohos.dlpmanager###100", appIdInCache); + ASSERT_FALSE(appIdInCache.empty()); + ASSERT_EQ(Crypto::Sha256(appIdInCache), checker.GetAppId(info)); + + checker.DeleteCache(info.bundleName, 100, 0); + std::string appIdInCache1; + checker.appIds_.Get("com.ohos.dlpmanager###100", appIdInCache1); + ASSERT_TRUE(appIdInCache1.empty()); + + checker.GetAppId(info); + ASSERT_GE(checker.appIds_.Size(), 1); + checker.ClearCache(); + ASSERT_EQ(checker.appIds_.Size(), 0); +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/feature_stub_impl_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/feature_stub_impl_test.cpp index bae31a7d32306a371e1ceb4c1e5853e993a9c7b8..f4e870713113c283a5d85b74a9185a54398c326a 100644 --- a/datamgr_service/services/distributeddataservice/app/test/unittest/feature_stub_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/feature_stub_impl_test.cpp @@ -184,7 +184,6 @@ HWTEST_F(FeatureStubImplTest, OnAppExit001, TestSize.Level1) pid_t pid = 0; uint32_t tokenId = 0; std::string bundleName = "com.ohos.test"; - std::shared_ptr executor = std::make_shared(1, 0); auto result = featureStubImpl->OnAppExit(uid, pid, tokenId, bundleName); EXPECT_EQ(result, -1); } @@ -204,11 +203,46 @@ HWTEST_F(FeatureStubImplTest, OnAppExit002, TestSize.Level1) pid_t pid = 0; uint32_t tokenId = 0; std::string bundleName = "com.ohos.test"; - std::shared_ptr executor = std::make_shared(1, 0); auto result = featureStubImpl->OnAppExit(uid, pid, tokenId, bundleName); EXPECT_EQ(result, E_OK); } +/** +* @tc.name: OnFeatureExit001 +* @tc.desc: OnFeatureExit function test. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(FeatureStubImplTest, OnFeatureExit001, TestSize.Level1) +{ + std::shared_ptr feature = nullptr; + std::shared_ptr featureStubImpl = std::make_shared(feature); + pid_t uid = 0; + pid_t pid = 0; + uint32_t tokenId = 0; + std::string bundleName = "com.ohos.test"; + auto result = featureStubImpl->OnFeatureExit(uid, pid, tokenId, bundleName); + EXPECT_EQ(result, -1); +} + +/** +* @tc.name: OnFeatureExit002 +* @tc.desc: OnFeatureExit function test. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(FeatureStubImplTest, OnFeatureExit002, TestSize.Level1) +{ + std::shared_ptr feature = std::make_shared(); + std::shared_ptr featureStubImpl = std::make_shared(feature); + pid_t uid = 0; + pid_t pid = 0; + uint32_t tokenId = 0; + std::string bundleName = "com.ohos.test"; + auto result = featureStubImpl->OnFeatureExit(uid, pid, tokenId, bundleName); + EXPECT_EQ(result, E_OK); +} + /** * @tc.name: OnAppUninstall001 * @tc.desc: OnAppUninstall function test. diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_data_service_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_data_service_test.cpp index 7b9aeb3d2e66ccf9ae2e12c94008366ee4efd135..fcaec79835ac63af1c971838a56b02d92a48b727 100644 --- a/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_data_service_test.cpp +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_data_service_test.cpp @@ -15,7 +15,7 @@ #include "auth_delegate.h" #include "bootstrap.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter.h" #include "executor_pool.h" #include @@ -30,6 +30,7 @@ #include "system_ability.h" #include "system_ability_definition.h" #include "upgrade_manager.h" +#include "utils/base64_utils.h" using namespace testing::ext; using namespace OHOS; @@ -81,7 +82,6 @@ void KvStoreDataServiceTest::SetUpTestCase(void) KvStoreMetaManager::GetInstance().BindExecutor(executors); KvStoreMetaManager::GetInstance().InitMetaParameter(); KvStoreMetaManager::GetInstance().InitMetaListener(); - DeviceManagerAdapter::GetInstance().Init(executors); } void KvStoreDataServiceTest::TearDownTestCase(void) @@ -149,10 +149,45 @@ HWTEST_F(KvStoreDataServiceTest, RegisterClientDeathObserver001, TestSize.Level1 Bootstrap::GetInstance().LoadCheckers(); KvStoreMetaManager::GetInstance().BindExecutor(std::make_shared(12, 5)); KvStoreMetaManager::GetInstance().InitMetaParameter(); - Status status = kvDataService.RegisterClientDeathObserver(appId, new KvStoreClientDeathObserver()); + Status status = kvDataService.RegisterClientDeathObserver(appId, new KvStoreClientDeathObserver(), ""); EXPECT_EQ(status, Status::SUCCESS) << "RegisterClientDeathObserver failed"; } +/** +* @tc.name: RegisterClientDeathObserver002 +* @tc.desc: register client death observer +* @tc.type: FUNC +*/ +HWTEST_F(KvStoreDataServiceTest, RegisterClientDeathObserver002, TestSize.Level1) +{ + AppId appId; + appId.appId = "app0"; + KvStoreDataService kvDataService; + Bootstrap::GetInstance().LoadComponents(); + Bootstrap::GetInstance().LoadCheckers(); + KvStoreMetaManager::GetInstance().BindExecutor(std::make_shared(12, 5)); + KvStoreMetaManager::GetInstance().InitMetaParameter(); + Status status = kvDataService.RegisterClientDeathObserver(appId, nullptr, ""); + EXPECT_EQ(status, Status::SUCCESS) << "RegisterClientDeathObserver failed"; + for (int i = 0; i < 17; i++) { + auto featureName = std::to_string(i); + status = kvDataService.RegisterClientDeathObserver(appId, new KvStoreClientDeathObserver(), featureName); + EXPECT_EQ(status, Status::SUCCESS) << "RegisterClientDeathObserver failed"; + } +} + +/** +* @tc.name: Exit001 +* @tc.desc: feature Exit +* @tc.type: FUNC +*/ +HWTEST_F(KvStoreDataServiceTest, Exit001, TestSize.Level1) +{ + KvStoreDataService kvDataService; + EXPECT_EQ(kvDataService.Exit(""), Status::SUCCESS); +} + + /** * @tc.name: GetIndentation001 * @tc.desc: @@ -669,21 +704,19 @@ HWTEST_F(KvStoreDataServiceTest, DumpBundleInfo001, TestSize.Level0) } /** -* @tc.name: UpgradeManagerTest001 -* @tc.desc: test Init function +* @tc.name: OnExtensionRestore001 +* @tc.desc: restore with invalid fd * @tc.type: FUNC * @tc.require: -* @tc.author: SQL +* @tc.author: zhaojh */ -HWTEST_F(UpgradeManagerTest, UpgradeManagerTest001, TestSize.Level0) +HWTEST_F(KvStoreDataServiceTest, OnExtension001, TestSize.Level0) { - auto executors = std::make_shared(1, 0); - DistributedData::UpgradeManager instance; - instance.Init(executors); - EXPECT_TRUE(instance.executors_); - - instance.Init(executors); - EXPECT_TRUE(instance.executors_); + KvStoreDataService kvStoreDataServiceTest; + MessageParcel data; + MessageParcel reply; + data.WriteFileDescriptor(-1); + EXPECT_EQ(kvStoreDataServiceTest.OnExtension("invalid", data, reply), 0); } /** @@ -829,7 +862,7 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionRestore006, TestSize.Level0) * @tc.desc: test OnExtension function backup invalid json * @tc.type: FUNC * @tc.require: - * @tc.author: SQL + * @tc.author: zhaojh */ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup001, TestSize.Level0) { KvStoreDataService kvStoreDataServiceTest; @@ -845,7 +878,7 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup001, TestSize.Level0) { * @tc.desc: test OnExtension function backup application empty * @tc.type: FUNC * @tc.require: - * @tc.author: SQL + * @tc.author: zhaojh */ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup002, TestSize.Level0) { KvStoreDataService kvStoreDataServiceTest; @@ -863,7 +896,7 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup002, TestSize.Level0) { * @tc.desc: test OnExtension function backup no userInfo * @tc.type: FUNC * @tc.require: - * @tc.author: SQL + * @tc.author: zhaojh */ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup003, TestSize.Level0) { KvStoreDataService kvStoreDataServiceTest; @@ -882,7 +915,7 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup003, TestSize.Level0) { * @tc.desc: test OnExtension function backup userinfo empty * @tc.type: FUNC * @tc.require: - * @tc.author: SQL + * @tc.author: zhaojh */ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup004, TestSize.Level0) { KvStoreDataService kvStoreDataServiceTest; @@ -902,7 +935,7 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup004, TestSize.Level0) { * @tc.desc: test OnExtension function backup secret key length invalid * @tc.type: FUNC * @tc.require: - * @tc.author: SQL + * @tc.author: zhaojh */ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup005, TestSize.Level0) { KvStoreDataService kvStoreDataServiceTest; @@ -926,7 +959,7 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup005, TestSize.Level0) { * @tc.desc: test OnExtension function backup secret iv length invalid * @tc.type: FUNC * @tc.require: - * @tc.author: SQL + * @tc.author: zhaojh */ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup006, TestSize.Level0) { KvStoreDataService kvStoreDataServiceTest; @@ -950,7 +983,7 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup006, TestSize.Level0) { * @tc.desc: test OnExtension function backup no bundle * @tc.type: FUNC * @tc.require: - * @tc.author: SQL + * @tc.author: zhaojh */ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup007, TestSize.Level0) { KvStoreDataService kvStoreDataServiceTest; @@ -984,7 +1017,7 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup007, TestSize.Level0) { * @tc.desc: test OnExtension function backup no bundle * @tc.type: FUNC * @tc.require: - * @tc.author: SQL + * @tc.author: zhaojh */ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup008, TestSize.Level0) { KvStoreDataService kvStoreDataServiceTest; @@ -994,20 +1027,24 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup008, TestSize.Level0) { testMeta.bundleName = "com.example.restore_test"; testMeta.storeId = "Source"; testMeta.user = "100"; - testMeta.area = DEFAULT_ENCRYPTION_LEVEL; + testMeta.area = CryptoManager::Area::EL1; testMeta.instanceId = 0; testMeta.deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; testMeta.isEncrypt = true; + testMeta.dataDir = "TEST_DIR"; std::vector sKey{2, 249, 221, 119, 177, 216, 217, 134, 185, 139, 114, 38, 140, 64, 165, 35, 77, 169, 0, 226, 226, 166, 37, 73, 181, 229, 42, 88, 108, 111, 131, 104, 141, 43, 96, 119, 214, 34, 177, 129, 233, 96, 98, 164, 87, 115, 187, 170}; SecretKeyMetaData testSecret; - testSecret.sKey = CryptoManager::GetInstance().Encrypt(sKey, testMeta.area, testMeta.user); + CryptoManager::CryptoParams encryptParams = { .area = testMeta.area }; + testSecret.sKey = CryptoManager::GetInstance().Encrypt(sKey, encryptParams); testSecret.storeType = 10; testSecret.time = std::vector{233, 39, 137, 103, 0, 0, 0, 0}; + testSecret.nonce = encryptParams.nonce; + testSecret.area = encryptParams.area; EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(testMeta.GetKey(), testMeta, true), true); EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(testMeta.GetSecretKey(), testSecret, true), true); @@ -1036,4 +1073,280 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup008, TestSize.Level0) { EXPECT_TRUE(backupData.infos.size() == 1); } -} // namespace OHOS::Test \ No newline at end of file + +/** + * @tc.name: ReEncryptKey001 + * @tc.desc: test ReEncryptKey load meta failed + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(KvStoreDataServiceTest, ReEncryptKey001, TestSize.Level0) +{ + KvStoreDataService kvStoreDataServiceTest; + MessageParcel data; + MessageParcel reply; + + SecretKeyMetaData secretKeyMeta; + StoreMetaData storeMeta; + std::vector iv; + auto ret = kvStoreDataServiceTest.ReEncryptKey("", secretKeyMeta, storeMeta, iv); + EXPECT_TRUE(ret.empty()); +} + +/** + * @tc.name: ReEncryptKey002 + * @tc.desc: test ReEncryptKey failed when meta sKey is invalid + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(KvStoreDataServiceTest, ReEncryptKey002, TestSize.Level0) +{ + KvStoreDataService kvStoreDataServiceTest; + MessageParcel data; + MessageParcel reply; + + StoreMetaData testMeta; + testMeta.bundleName = "com.example.restore_test"; + testMeta.storeId = "Source"; + testMeta.user = "100"; + testMeta.area = CryptoManager::Area::EL1; + testMeta.instanceId = 0; + testMeta.deviceId = + DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + testMeta.isEncrypt = true; + testMeta.dataDir = "TEST_DIR"; + SecretKeyMetaData testSecret; + CryptoManager::CryptoParams encryptParams = { .area = testMeta.area }; + testSecret.storeType = 10; + testSecret.time = std::vector{233, 39, 137, 103, 0, 0, 0, 0}; + testSecret.nonce = encryptParams.nonce; + testSecret.area = encryptParams.area; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(testMeta.GetKey(), testMeta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(testMeta.GetSecretKey(), testSecret, true), true); + + SecretKeyMetaData secretKeyMeta; + std::vector iv; + auto ret = kvStoreDataServiceTest.ReEncryptKey(testMeta.GetSecretKey(), secretKeyMeta, testMeta, iv); + EXPECT_TRUE(ret.empty()); +} + +/** + * @tc.name: ReEncryptKey003 + * @tc.desc: test reEncryptKey failed when iv is invalid + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(KvStoreDataServiceTest, ReEncryptKey003, TestSize.Level0) +{ + KvStoreDataService kvStoreDataServiceTest; + MessageParcel data; + MessageParcel reply; + + StoreMetaData testMeta; + testMeta.bundleName = "com.example.restore_test"; + testMeta.storeId = "Source"; + testMeta.user = "100"; + testMeta.area = CryptoManager::Area::EL1; + testMeta.instanceId = 0; + testMeta.deviceId = + DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + testMeta.isEncrypt = true; + testMeta.dataDir = "TEST_DIR"; + std::vector sKey{2, 249, 221, 119, 177, 216, 217, 134, 185, 139, + 114, 38, 140, 64, 165, 35, 77, 169, 0, 226, + 226, 166, 37, 73, 181, 229, 42, 88, 108, 111, + 131, 104, 141, 43, 96, 119, 214, 34, 177, 129, + 233, 96, 98, 164, 87, 115, 187, 170}; + SecretKeyMetaData testSecret; + CryptoManager::CryptoParams encryptParams = { .area = testMeta.area }; + testSecret.sKey = CryptoManager::GetInstance().Encrypt(sKey, encryptParams); + testSecret.storeType = 10; + testSecret.time = std::vector{233, 39, 137, 103, 0, 0, 0, 0}; + testSecret.nonce = encryptParams.nonce; + testSecret.area = encryptParams.area; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(testMeta.GetKey(), testMeta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(testMeta.GetSecretKey(), testSecret, true), true); + + SecretKeyMetaData secretKeyMeta; + std::vector iv; + auto ret = kvStoreDataServiceTest.ReEncryptKey(testMeta.GetSecretKey(), secretKeyMeta, testMeta, iv); + EXPECT_TRUE(ret.empty()); +} + +/** + * @tc.name: OnExtensionRestore_InvalidUserId + * @tc.desc: Test OnRestore returns -1 when userId is empty + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(KvStoreDataServiceTest, OnExtensionRestore_InvalidUserId, TestSize.Level0) +{ + KvStoreDataService kvStoreDataServiceTest; + MessageParcel data; + MessageParcel reply; + // Prepare a valid backup file (content doesn't matter, as IV size will fail first) + EXPECT_EQ(WriteContentToFile(SECRETKEY_BACKUP_FILE, NORMAL_BACKUP_DATA), 0); + int32_t fd = open(SECRETKEY_BACKUP_FILE.c_str(), O_RDONLY); + ASSERT_GE(fd, 0); + data.WriteFileDescriptor(fd); + + std::string cloneInfoStr = + "[{\"type\":\"encryption_info\",\"detail\":{\"encryption_symkey\":\"27," + "145,118,212,62,156,133,135,50,68,188,239,20,170,227,190,37,142,218," + "158,177,32,5,160,13,114,186,141,59,91,44,200\",\"encryption_algname\":" + "\"AES256\",\"gcmParams_iv\":\"1,2,3,4,5,6,7,8,9,10\"}},{\"type\":\"userId\",\"detail\":\"\"}]"; + data.WriteString(cloneInfoStr); + + // Should return -1 due to IV size error + EXPECT_EQ(kvStoreDataServiceTest.OnExtension("restore", data, reply), -1); + close(fd); +} + +/** + * @tc.name: OnExtensionRestore_InvalidIvSize + * @tc.desc: Test OnRestore returns -1 when IV size is incorrect + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(KvStoreDataServiceTest, OnExtensionRestore_InvalidIvSize, TestSize.Level0) +{ + KvStoreDataService kvStoreDataServiceTest; + MessageParcel data; + MessageParcel reply; + + EXPECT_EQ(WriteContentToFile(SECRETKEY_BACKUP_FILE, NORMAL_BACKUP_DATA), 0); + int32_t fd = open(SECRETKEY_BACKUP_FILE.c_str(), O_RDONLY); + ASSERT_GE(fd, 0); + data.WriteFileDescriptor(fd); + + // Prepare cloneInfoStr with invalid IV (length != AES_256_NONCE_SIZE) + std::string cloneInfoStr = + "[{\"type\":\"encryption_info\",\"detail\":{\"encryption_symkey\":\"27," + "145,118,212,62,156,133,135,50,68,188,239,20,170,227,190,37,142,218," + "158,177,32,5,160,13,114,186,141,59,91,44,200\",\"encryption_algname\":" + "\"AES256\",\"gcmParams_iv\":\"1,2,3,4,5,6,7,8,9,10\"}},{\"type\":\"userId\",\"detail\":\"100\"}]"; + data.WriteString(cloneInfoStr); + + // Should return -1 due to IV size error + EXPECT_EQ(kvStoreDataServiceTest.OnExtension("restore", data, reply), -1); + close(fd); +} + +/** + * @tc.name: OnExtensionRestore_ImportCloneKeyFailed + * @tc.desc: Test OnRestore returns -1 when ImportCloneKey fails (invalid key size) + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(KvStoreDataServiceTest, OnExtensionRestore_ImportCloneKeyFailed, TestSize.Level0) +{ + KvStoreDataService kvStoreDataServiceTest; + MessageParcel data; + MessageParcel reply; + + // Prepare a valid backup file (content doesn't matter, as ImportCloneKey will fail first) + EXPECT_EQ(WriteContentToFile(SECRETKEY_BACKUP_FILE, NORMAL_BACKUP_DATA), 0); + int32_t fd = open(SECRETKEY_BACKUP_FILE.c_str(), O_RDONLY); + ASSERT_GE(fd, 0); + data.WriteFileDescriptor(fd); + + // Prepare cloneInfoStr with invalid encryption_symkey (too short, so ImportCloneKey fails) + std::string cloneInfoStr = + "[{\"type\":\"encryption_info\",\"detail\":{\"encryption_symkey\":\"1,2,3\",\"encryption_algname\":\"AES256\"," + "\"gcmParams_iv\":\"97,160,201,177,46,37,129,18,112,220,107,106,25,231,15,15,""58,85,31,83,123,216,211,2,222," + "49,122,72,21,251,83,16\"}},{\"type\":\"userId\",\"detail\":\"100\"}]"; + data.WriteString(cloneInfoStr); + + // Should return -1 due to ImportCloneKey failure + EXPECT_EQ(kvStoreDataServiceTest.OnExtension("restore", data, reply), -1); + close(fd); +} + +/** + * @tc.name: OnExtensionRestore_RestoreSuccess + * @tc.desc: Test OnRestore returns 0 when ImportCloneKey succeeds + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(KvStoreDataServiceTest, OnExtensionRestore_RestoreSuccess, TestSize.Level0) +{ + KvStoreDataService kvStoreDataServiceTest; + MessageParcel data; + MessageParcel reply; + + StoreMetaData testMeta; + testMeta.bundleName = "com.myapp.example"; + testMeta.storeId = "storeId"; + testMeta.user = "100"; + testMeta.area = CryptoManager::Area::EL1; + testMeta.instanceId = 0; + testMeta.deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + testMeta.isEncrypt = true; + testMeta.dataDir = "TEST_DIR"; + std::vector sKey(32, 0); + SecretKeyMetaData testSecret; + CryptoManager::CryptoParams encryptParams = { .area = testMeta.area }; + testSecret.sKey = CryptoManager::GetInstance().Encrypt(sKey, encryptParams); + testSecret.storeType = 10; + testSecret.time = std::vector{ 233, 39, 137, 103, 0, 0, 0, 0 }; + testSecret.nonce = encryptParams.nonce; + testSecret.area = encryptParams.area; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(testMeta.GetKey(), testMeta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(testMeta.GetSecretKey(), testSecret, true), true); + + std::string symKey = "27,145,118,212,62,156,133,135,50,68,188,239,20,170,227,190,37,142," + "218,158,177,32,5,160,13,114,186,141,59,91,44,200"; + std::vector iv{ 97, 160, 201, 177, 46, 37, 129, 18, 112, 220, 107, 106, 25, 231, 15, 15, 58, 85, 31, 83, + 123, 216, 211, 2, 222, 49, 122, 72, 21, 251, 83, 16 }; + + ASSERT_EQ(kvStoreDataServiceTest.ImportCloneKey(symKey), true); + + SecretKeyMetaData secretKeyMeta; + auto reEncryptedKey = kvStoreDataServiceTest.ReEncryptKey(testMeta.GetSecretKey(), secretKeyMeta, testMeta, iv); + kvStoreDataServiceTest.DeleteCloneKey(); + auto encodeEncryptedKey = DistributedData::Base64::Encode(reEncryptedKey); + + const std::string backupData = + std::string("{\"infos\":[{\"bundleName\":\"com.myapp.example\",\"dbName\":\"storeId\"," + "\"instanceId\":0,\"storeType\":\"10\",\"user\":\"100\",\"sKey\":\"") + + encodeEncryptedKey + std::string("\",\"time\":[50,180,137,103,0,0,0,0]}]}"); + + EXPECT_EQ(WriteContentToFile(SECRETKEY_BACKUP_FILE, backupData), 0); + int32_t fd = open(SECRETKEY_BACKUP_FILE.c_str(), O_RDONLY); + ASSERT_GE(fd, 0); + data.WriteFileDescriptor(fd); + + std::string cloneInfoStr = + std::string("[{\"type\":\"encryption_info\",\"detail\":{\"encryption_symkey\":\"") + symKey + + std::string("\",\"encryption_algname\":\"AES256\",\"gcmParams_iv\":\"97,160,201,177,46,37,129,18,112,220,107," + "106,25,231,15,15,58,85,31,83,123,216,211,2,222,49,122,72,21,251,83,16\"}}," + "{\"type\":\"userId\",\"detail\":\"100\"}]"); + data.WriteString(cloneInfoStr); + + EXPECT_EQ(kvStoreDataServiceTest.OnExtension("restore", data, reply), 0); + close(fd); +} + +/** + * @tc.name: WriteBackupInfo_FwriteFail + * @tc.desc: Test WriteBackupInfo returns false when fwrite fails + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(KvStoreDataServiceTest, WriteBackupInfo_FwriteFail, TestSize.Level0) +{ + KvStoreDataService kvStoreDataServiceTest; + std::string content = "test_content"; + // Try to open a directory as a file, which should fail at fopen + bool result = kvStoreDataServiceTest.WriteBackupInfo(content, "/"); + EXPECT_FALSE(result); +} +} // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_meta_manager_update_key_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_meta_manager_update_key_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a520cfb6e81e036d1f92170e750ca8bd3728abbe --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_meta_manager_update_key_test.cpp @@ -0,0 +1,337 @@ +/* +* Copyright (c) 2025 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 "KvstoreMetaManagerUpdateKeyTest" + +#include "bootstrap.h" +#include "device_manager_adapter.h" +#include "device_manager_adapter_mock.h" +#include "executor_pool.h" +#include "gtest/gtest.h" +#include "kvstore_meta_manager.h" +#include "log_print.h" +#include "metadata/device_meta_data.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 "metadata/version_meta_data.h" +#include "semaphore_ex.h" +#include "store_types.h" +namespace { +using namespace testing::ext; +using namespace testing; +using namespace OHOS::DistributedData; +using KvStoreMetaManager = OHOS::DistributedKv::KvStoreMetaManager; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; +class KvstoreMetaManagerUpdateKeyTest : public testing::Test { +public: + static void SetUpTestCase() + { + deviceManagerAdapterMock = std::make_shared(); + BDeviceManagerAdapter::deviceManagerAdapter = deviceManagerAdapterMock; + DeviceInfo deviceInfo; + deviceInfo.uuid = "ABCD"; + EXPECT_CALL(*deviceManagerAdapterMock, GetLocalDevice()).WillRepeatedly(Return(deviceInfo)); + EXPECT_CALL(*deviceManagerAdapterMock, GetUuidByNetworkId(_)).WillRepeatedly(Return(deviceInfo.uuid)); + EXPECT_CALL(*deviceManagerAdapterMock, CalcClientUuid(_, _)).WillRepeatedly(Return(deviceInfo.uuid)); + EXPECT_CALL(*deviceManagerAdapterMock, ToUUID(deviceInfo.uuid)).WillRepeatedly(Return(deviceInfo.uuid)); + auto executors = std::make_shared(1, 0); + Bootstrap::GetInstance().LoadComponents(); + Bootstrap::GetInstance().LoadDirectory(); + DeviceManagerAdapter::GetInstance().Init(executors); + KvStoreMetaManager::GetInstance().BindExecutor(executors); + KvStoreMetaManager::GetInstance().InitMetaParameter(); + } + + static void TearDownTestCase() + { + deviceManagerAdapterMock = nullptr; + BDeviceManagerAdapter::deviceManagerAdapter = nullptr; + } + + void SetUp() + { + } + + void TearDown() + { + } + + static inline std::shared_ptr deviceManagerAdapterMock = nullptr; +}; + +/** +* @tc.name: keyUpdataTestWithUuid +* @tc.desc: key updata test +* @tc.type: FUNC +* @tc.require: +* @tc.author: cjx +*/ +HWTEST_F(KvstoreMetaManagerUpdateKeyTest, KeyUpdataTest001, TestSize.Level1) +{ + auto store = KvStoreMetaManager::GetInstance().GetMetaKvStore(); + DeviceMetaData deviceMetaData; + deviceMetaData.newUuid = "KeyUpdataTest001_oldUuid"; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(deviceMetaData.GetKey(), deviceMetaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(deviceMetaData.GetKey(), deviceMetaData, true)); + + StoreMetaData metaData; + metaData.deviceId = "KeyUpdataTest001_oldUuid"; + metaData.user = "KeyUpdataTest001_user"; + metaData.bundleName = "KeyUpdataTest001_bundleName"; + metaData.storeId = "KeyUpdataTest001_storeId"; + metaData.dataDir = "KeyUpdataTest001_dataDir"; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + StoreMetaDataLocal metaDataLocal; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + SecretKeyMetaData secretKeymetaData; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetSecretKeyWithoutPath(), secretKeymetaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetSecretKeyWithoutPath(), secretKeymetaData, true)); + + VersionMetaData versionMeta; + versionMeta.version = VersionMetaData::UPDATE_SYNC_META_VERSION; + MetaDataManager::GetInstance().SaveMeta(versionMeta.GetKey(), versionMeta, true); + + KvStoreMetaManager::GetInstance().InitMetaData(); + metaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocal(), metaDataLocal, true)); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetSecretKeyWithoutPath(), secretKeymetaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetSecretKey(), secretKeymetaData, true)); + + StoreMetaMapping storeMetaMapping(metaData); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKey(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath())); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyLocal(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetSecretKey(), true)); +} + +/** +* @tc.name: KeyUpdataTest +* @tc.desc: key updata test +* @tc.type: FUNC +* @tc.require: +* @tc.author: cjx +*/ +HWTEST_F(KvstoreMetaManagerUpdateKeyTest, KeyUpdataTest002, TestSize.Level1) +{ + auto store = KvStoreMetaManager::GetInstance().GetMetaKvStore(); + StoreMetaData metaData; + metaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData.user = "KeyUpdataTest002_user"; + metaData.bundleName = "KeyUpdataTest002_bundleName"; + metaData.storeId = "KeyUpdataTest002_storeId"; + metaData.dataDir = "KeyUpdataTest002_dataDir"; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + StoreMetaDataLocal metaDataLocal; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + SecretKeyMetaData secretKeymetaData; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetSecretKeyWithoutPath(), secretKeymetaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetSecretKeyWithoutPath(), secretKeymetaData, true)); + + VersionMetaData versionMeta; + versionMeta.version = VersionMetaData::UPDATE_SYNC_META_VERSION; + MetaDataManager::GetInstance().SaveMeta(versionMeta.GetKey(), versionMeta, true); + KvStoreMetaManager::GetInstance().InitMetaData(); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocal(), metaDataLocal, true)); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetSecretKeyWithoutPath(), secretKeymetaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetSecretKey(), secretKeymetaData, true)); + + StoreMetaMapping storeMetaMapping(metaData); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKey(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath())); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyLocal(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetSecretKey(), true)); +} + +/** +* @tc.name: KeyUpdataTest +* @tc.desc: key updata test +* @tc.type: FUNC +* @tc.require: +* @tc.author: cjx +*/ +HWTEST_F(KvstoreMetaManagerUpdateKeyTest, KeyUpdataTest003, TestSize.Level1) +{ + auto store = KvStoreMetaManager::GetInstance().GetMetaKvStore(); + StoreMetaData metaData; + metaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData.user = "KeyUpdataTest003_user"; + metaData.bundleName = "KeyUpdataTest003_bundleName"; + metaData.storeId = "KeyUpdataTest003_storeId"; + metaData.dataDir = "KeyUpdataTest003_dataDir"; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + + KvStoreMetaManager::GetInstance().InitMetaData(); + + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKey(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath())); +} + +/** +* @tc.name: KeyUpdataTest +* @tc.desc: key updata test +* @tc.type: FUNC +* @tc.require: +* @tc.author: my +*/ +HWTEST_F(KvstoreMetaManagerUpdateKeyTest, KeyUpdataTest004, TestSize.Level1) +{ + auto store = KvStoreMetaManager::GetInstance().GetMetaKvStore(); + StoreMetaData metaData; + metaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData.user = "KeyUpdataTest004_user"; + metaData.bundleName = "KeyUpdataTest004_bundleName"; + metaData.storeId = "KeyUpdataTest004_storeId"; + metaData.dataDir = "KeyUpdataTest004_dataDir"; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + + VersionMetaData versionMeta; + MetaDataManager::GetInstance().DelMeta(versionMeta.GetKey(), true); + + KvStoreMetaManager::GetInstance().InitMetaData(); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKey(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath())); +} + +/** +* @tc.name: KeyUpdataTest +* @tc.desc: key updata test +* @tc.type: FUNC +* @tc.require: +* @tc.author: my +*/ +HWTEST_F(KvstoreMetaManagerUpdateKeyTest, KeyUpdataTest005, TestSize.Level1) +{ + auto store = KvStoreMetaManager::GetInstance().GetMetaKvStore(); + StoreMetaData metaData; + metaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData.user = "KeyUpdataTest005_user"; + metaData.bundleName = "KeyUpdataTest005_bundleName"; + metaData.storeId = "KeyUpdataTest005_storeId"; + metaData.dataDir = "KeyUpdataTest005_dataDir"; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + + VersionMetaData versionMeta; + versionMeta.version = 3; // Set version to 3. + MetaDataManager::GetInstance().SaveMeta(versionMeta.GetKey(), versionMeta, true); + KvStoreMetaManager::GetInstance().InitMetaData(); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKey(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath())); +} + +/** +* @tc.name: KeyUpdataTest +* @tc.desc: key updata test +* @tc.type: FUNC +* @tc.require: +* @tc.author: my +*/ +HWTEST_F(KvstoreMetaManagerUpdateKeyTest, KeyUpdataTest006, TestSize.Level1) +{ + auto store = KvStoreMetaManager::GetInstance().GetMetaKvStore(); + StoreMetaData metaData; + + VersionMetaData versionMeta; + versionMeta.version = VersionMetaData::UPDATE_SYNC_META_VERSION; + MetaDataManager::GetInstance().SaveMeta(versionMeta.GetKey(), versionMeta, true); + KvStoreMetaManager::GetInstance().InitMetaData(); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); +} + +/** +* @tc.name: KeyUpdataTest +* @tc.desc: key updata test +* @tc.type: FUNC +* @tc.require: +* @tc.author: my +*/ +HWTEST_F(KvstoreMetaManagerUpdateKeyTest, KeyUpdataTest007, TestSize.Level1) +{ + auto store = KvStoreMetaManager::GetInstance().GetMetaKvStore(); + + StoreMetaData metaData; + metaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData.user = "KeyUpdataTest007_user"; + metaData.bundleName = "KeyUpdataTest007_bundleName"; + metaData.storeId = "KeyUpdataTest007_storeId"; + metaData.dataDir = "KeyUpdataTest007_dataDir"; + StoreMetaDataLocal metaDataLocal; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + + VersionMetaData versionMeta; + versionMeta.version = VersionMetaData::UPDATE_SYNC_META_VERSION; + MetaDataManager::GetInstance().SaveMeta(versionMeta.GetKey(), versionMeta, true); + KvStoreMetaManager::GetInstance().InitMetaData(); + + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocal(), metaDataLocal, true)); + + StoreMetaMapping storeMetaMapping(metaData); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyLocal(), true)); +} +} // namespace \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/route_head_handler_impl_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/route_head_handler_impl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1edb109158121b45186029488aea5dc408cdceea --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/route_head_handler_impl_test.cpp @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2025 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 "session_manager/session_manager.h" + +#include + +#include "accesstoken_kit.h" +#include "account_delegate_mock.h" +#include "auth_delegate_mock.h" +#include "bootstrap.h" +#include "device_manager_adapter.h" +#include "device_manager_adapter_mock.h" +#include "gtest/gtest.h" +#include +#include "meta_data_manager_mock.h" +#include "metadata/meta_data_manager.h" +#include "metadata/store_meta_data.h" +#include "nativetoken_kit.h" +#include "session_manager/route_head_handler_impl.h" +#include "session_manager/upgrade_manager.h" +#include "token_setproc.h" +#include "user_delegate.h" +#include "user_delegate_mock.h" +#include "utils/endian_converter.h" + +namespace { +using namespace testing; +using namespace testing::ext; +using namespace OHOS::DistributedKv; +using namespace OHOS::DistributedData; +using namespace DistributedDB; +using namespace OHOS; +using namespace OHOS::Security::AccessToken; +using DeviceInfo = OHOS::AppDistributedKv::DeviceInfo; +using UserInfo = DistributedDB::UserInfo; +constexpr const char *PEER_DEVICE_ID = "PEER_DEVICE_ID"; +constexpr const char *PROCESSLABEL = "distributeddata"; +constexpr const char *META_DB = "service_meta"; +constexpr const char *DRAG = "drag"; +constexpr const char *OTHER_APP_ID = "test_app_id"; +constexpr const char *USER_ID = "100"; +static constexpr int32_t OH_OS_TYPE = 10; + +void GrantPermissionNative() +{ + const char **perms = new const char *[2]; + perms[0] = "ohos.permission.DISTRIBUTED_DATASYNC"; + perms[1] = "ohos.permission.ACCESS_SERVICE_DM"; + TokenInfoParams infoInstance = { + .dcapsNum = 0, + .permsNum = 2, + .aclsNum = 0, + .dcaps = nullptr, + .perms = perms, + .acls = nullptr, + .processName = "distributed_data_test", + .aplStr = "system_basic", + }; + uint64_t tokenId = GetAccessTokenId(&infoInstance); + SetSelfTokenID(tokenId); + AccessTokenKit::ReloadNativeTokenInfo(); + delete[] perms; +} + +class RouteHeadHandlerImplTest : public testing::Test { +public: + static void SetUpTestCase() + { + GrantPermissionNative(); + deviceManagerAdapterMock = std::make_shared(); + BDeviceManagerAdapter::deviceManagerAdapter = deviceManagerAdapterMock; + metaDataManagerMock = std::make_shared(); + BMetaDataManager::metaDataManager = metaDataManagerMock; + metaDataMock = std::make_shared>(); + BMetaData::metaDataManager = metaDataMock; + userDelegateMock = std::make_shared(); + BUserDelegate::userDelegate = userDelegateMock; + } + static void TearDownTestCase() + { + deviceManagerAdapterMock = nullptr; + BDeviceManagerAdapter::deviceManagerAdapter = nullptr; + metaDataManagerMock = nullptr; + BMetaDataManager::metaDataManager = nullptr; + metaDataMock = nullptr; + BMetaData::metaDataManager = nullptr; + userDelegateMock = nullptr; + BUserDelegate::userDelegate = nullptr; + } + void SetUp(){}; + void TearDown(){}; + static inline std::shared_ptr deviceManagerAdapterMock = nullptr; + static inline std::shared_ptr metaDataManagerMock = nullptr; + static inline std::shared_ptr> metaDataMock = nullptr; + static inline std::shared_ptr userDelegateMock = nullptr; +private: + bool CheckGetEmptyHeadDataLen(const DistributedDB::ExtendInfo& info); + bool CheckParseEmptyHeadDataLen(const DistributedDB::ExtendInfo& info); +}; + +bool RouteHeadHandlerImplTest::CheckGetEmptyHeadDataLen(const DistributedDB::ExtendInfo& info) +{ + DeviceInfo deviceInfo; + deviceInfo.osType = OH_OS_TYPE; + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + EXPECT_CALL(*deviceManagerAdapterMock, GetDeviceInfo(_)).WillRepeatedly(Return(deviceInfo)); + + auto sendHandler = RouteHeadHandlerImpl::Create(info); + if (sendHandler == nullptr) { + return false; + } + CapMetaData capMetaData; + capMetaData.version = CapMetaData::UDMF_AND_OBJECT_VERSION; + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillRepeatedly(DoAll(SetArgReferee<1>(capMetaData), Return(true))); + uint32_t headSize = 0; + auto status = sendHandler->GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::OK); + EXPECT_EQ(headSize, 0); + return true; +} + +bool RouteHeadHandlerImplTest::CheckParseEmptyHeadDataLen(const DistributedDB::ExtendInfo& info) +{ + DeviceInfo deviceInfo; + deviceInfo.osType = OH_OS_TYPE; + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + EXPECT_CALL(*deviceManagerAdapterMock, GetDeviceInfo(_)).WillRepeatedly(Return(deviceInfo)); + + auto recvHandler = RouteHeadHandlerImpl::Create(info); + if (recvHandler == nullptr) { + return false; + } + + CapMetaData capMetaData; + capMetaData.version = CapMetaData::UDMF_AND_OBJECT_VERSION; + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillRepeatedly(DoAll(SetArgReferee<1>(capMetaData), Return(true))); + + uint32_t routeHeadSize = 0; + std::unique_ptr data = std::make_unique(routeHeadSize); + uint32_t parseSize = 0; + auto status = recvHandler->ParseHeadDataLen(data.get(), routeHeadSize, parseSize, PEER_DEVICE_ID); + EXPECT_EQ(status, false); + EXPECT_EQ(parseSize, routeHeadSize); + return true; +} + +/** + * @tc.name: GetEmptyHeadDataLen_Test1 + * @tc.desc: test get udmf store + * @tc.type: FUNC + */ +HWTEST_F(RouteHeadHandlerImplTest, GetEmptyHeadDataLen_Test1, TestSize.Level0) +{ + const DistributedDB::ExtendInfo info = { + .appId = PROCESSLABEL, .storeId = DRAG, .userId = USER_ID, .dstTarget = PEER_DEVICE_ID + }; + EXPECT_TRUE(CheckParseEmptyHeadDataLen(info)); +} + +/** + * @tc.name: GetEmptyHeadDataLen_Test2 + * @tc.desc: test meta db + * @tc.type: FUNC + */ +HWTEST_F(RouteHeadHandlerImplTest, GetEmptyHeadDataLen_Test2, TestSize.Level0) +{ + const DistributedDB::ExtendInfo info = { + .appId = PROCESSLABEL, .storeId = META_DB, .userId = USER_ID, .dstTarget = PEER_DEVICE_ID + }; + EXPECT_TRUE(CheckParseEmptyHeadDataLen(info)); +} + +/** + * @tc.name: CheckParseEmptyHeadDataLen_Test1 + * @tc.desc: test get udmf store + * @tc.type: FUNC + */ +HWTEST_F(RouteHeadHandlerImplTest, CheckParseEmptyHeadDataLen_Test1, TestSize.Level0) +{ + const DistributedDB::ExtendInfo info = { + .appId = PROCESSLABEL, .storeId = DRAG, .userId = USER_ID, .dstTarget = PEER_DEVICE_ID + }; + EXPECT_TRUE(CheckParseEmptyHeadDataLen(info)); +} + +/** + * @tc.name: CheckParseEmptyHeadDataLen_Test2 + * @tc.desc: test get meta db + * @tc.type: FUNC + */ +HWTEST_F(RouteHeadHandlerImplTest, CheckParseEmptyHeadDataLen_Test2, TestSize.Level0) +{ + const DistributedDB::ExtendInfo info = { + .appId = PROCESSLABEL, .storeId = META_DB, .userId = USER_ID, .dstTarget = PEER_DEVICE_ID + }; + EXPECT_TRUE(CheckParseEmptyHeadDataLen(info)); +} + +/** + * @tc.name: CheckParseEmptyHeadDataLen_Test3 + * @tc.desc: test OTHER_APP_ID + * @tc.type: FUNC + */ +HWTEST_F(RouteHeadHandlerImplTest, CheckParseEmptyHeadDataLen_Test3, TestSize.Level0) +{ + const DistributedDB::ExtendInfo info = { + .appId = OTHER_APP_ID, .storeId = DRAG, .userId = USER_ID, .dstTarget = PEER_DEVICE_ID + }; + EXPECT_TRUE(CheckParseEmptyHeadDataLen(info)); +} + +/** + * @tc.name: CheckParseEmptyHeadDataLen_Test4 + * @tc.desc: test get OTHER_APP_ID and meta db + * @tc.type: FUNC + + */ +HWTEST_F(RouteHeadHandlerImplTest, CheckParseEmptyHeadDataLen_Test4, TestSize.Level0) +{ + const DistributedDB::ExtendInfo info = { + .appId = OTHER_APP_ID, .storeId = META_DB, .userId = USER_ID, .dstTarget = PEER_DEVICE_ID + }; + EXPECT_TRUE(CheckParseEmptyHeadDataLen(info)); +} +} // namespace \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/security_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/security_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6be236a03a9795ecaf251489b634817cd67ef5ab --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/security_test.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2025 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 "security.h" + +#include + +#include "device_manager_adapter.h" + +using namespace testing::ext; +using namespace OHOS::DistributedKv; +using namespace DistributedDB; +using SecurityOption = DistributedDB::SecurityOption; +using DBStatus = DistributedDB::DBStatus; +namespace OHOS::Test { +class SecurityTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + +protected: + static constexpr const char *FILE_TEST_PATH = "/data/test/KvStoreDataServiceTest"; + static constexpr const char *INVALID_FILE_PATH = "/data/test/invalidTest"; + static constexpr const char *DIR_PATH = "/data/test"; +}; + +void SecurityTest::SetUpTestCase(void) +{ +} + +void SecurityTest::TearDownTestCase(void) +{ +} + +void SecurityTest::SetUp(void) +{ +} + +void SecurityTest::TearDown(void) +{ +} + +/** + * @tc.name: IsXattrValueValid + * @tc.desc: Test for IsXattrValueValid value is empty. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, IsXattrValueValid001, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string value = ""; + auto res = security->IsXattrValueValid(value); + EXPECT_EQ(res, false); +} + +/** + * @tc.name: SetSecurityOption001 + * @tc.desc: Test for SetSecurityOption filePath is empty. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, SetSecurityOption001, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath; + SecurityOption option; + auto res = security->SetSecurityOption(filePath, option); + EXPECT_EQ(res, DBStatus::INVALID_ARGS); +} + +/** + * @tc.name: SetSecurityOption002 + * @tc.desc: Test for SetSecurityOption filePath is invalid. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, SetSecurityOption002, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath = INVALID_FILE_PATH; + SecurityOption option; + auto res = security->SetSecurityOption(filePath, option); + EXPECT_EQ(res, DBStatus::INVALID_ARGS); +} + +/** + * @tc.name: SetSecurityOption003 + * @tc.desc: Test for SetSecurityOption securityLabel is NOT_SET. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, SetSecurityOption003, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath = FILE_TEST_PATH; + SecurityOption option; + option.securityLabel = NOT_SET; + auto res = security->SetSecurityOption(filePath, option); + EXPECT_EQ(res, DBStatus::OK); +} + +/** + * @tc.name: SetSecurityOption004 + * @tc.desc: Test for SetSecurityOption securityLabel is invalid. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, SetSecurityOption004, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath = FILE_TEST_PATH; + SecurityOption option; + option.securityLabel = INVALID_SEC_LABEL; + auto res = security->SetSecurityOption(filePath, option); + EXPECT_EQ(res, DBStatus::INVALID_ARGS); +} + +/** + * @tc.name: SetSecurityOption005 + * @tc.desc: Test for SetSecurityOption securityLabel is normal. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, SetSecurityOption005, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath = FILE_TEST_PATH; + SecurityOption option; + option.securityLabel = S0; + auto res = security->SetSecurityOption(filePath, option); + EXPECT_EQ(res, DBStatus::OK); +} + +/** + * @tc.name: GetSecurityOption001 + * @tc.desc: Test for GetSecurityOption filePath is empty. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, GetSecurityOption001, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath; + SecurityOption option; + auto res = security->GetSecurityOption(filePath, option); + EXPECT_EQ(res, DBStatus::INVALID_ARGS); +} + +/** + * @tc.name: GetSecurityOption002 + * @tc.desc: Test for GetSecurityOption DIR_PATH is NOT_SUPPORT. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, GetSecurityOption002, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath = DIR_PATH; + SecurityOption option; + auto res = security->GetSecurityOption(filePath, option); + EXPECT_EQ(res, DBStatus::NOT_SUPPORT); +} + +/** + * @tc.name: GetSecurityOption003 + * @tc.desc: Test for GetSecurityOption filePath is invalid. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, GetSecurityOption003, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath = INVALID_FILE_PATH; + SecurityOption option; + auto res = security->GetSecurityOption(filePath, option); + EXPECT_EQ(res, DBStatus::OK); + EXPECT_EQ(option.securityLabel, NOT_SET); + EXPECT_EQ(option.securityFlag, ECE); +} + +/** + * @tc.name: GetSecurityOption005 + * @tc.desc: Test for GetSecurityOption file of securityLabel is S3. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, GetSecurityOption005, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath = FILE_TEST_PATH; + SecurityOption setOption; + setOption.securityLabel = S3; + auto res = security->SetSecurityOption(filePath, setOption); + EXPECT_EQ(res, DBStatus::OK); + SecurityOption getOption; + res = security->GetSecurityOption(filePath, getOption); + EXPECT_EQ(res, DBStatus::OK); + EXPECT_EQ(getOption.securityLabel, S3); + EXPECT_EQ(getOption.securityFlag, SECE); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/sensitive_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/sensitive_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..20105457a573bc5e887eff014e417359644b3338 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/sensitive_test.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2025 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 "sensitive.h" + +#include + +using namespace testing::ext; +using namespace OHOS::DistributedKv; +namespace OHOS::Test { +class SensitiveTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void SensitiveTest::SetUpTestCase(void) +{ +} + +void SensitiveTest::TearDownTestCase(void) +{ +} + +void SensitiveTest::SetUp(void) +{ +} + +void SensitiveTest::TearDown(void) +{ +} + +/** + * @tc.name: GetDeviceSecurityLevel001 + * @tc.desc: Test for GetDeviceSecurityLevel deviceId is empty. + * @tc.type: FUNC + */ +HWTEST_F(SensitiveTest, GetDeviceSecurityLevel001, TestSize.Level1) +{ + auto sensitive = std::make_shared(); + auto res = sensitive->GetDeviceSecurityLevel(); + EXPECT_EQ(res, DATA_SEC_LEVEL1); +} + +/** + * @tc.name: GetDeviceSecurityLevel002 + * @tc.desc: Test for GetDeviceSecurityLevel secruityLevel > DATA_SEC_LEVEL1. + * @tc.type: FUNC + */ +HWTEST_F(SensitiveTest, GetDeviceSecurityLevel002, TestSize.Level1) +{ + auto sensitive = std::make_shared(); + sensitive->securityLevel = DATA_SEC_LEVEL2; + auto res = sensitive->GetDeviceSecurityLevel(); + EXPECT_EQ(res, DATA_SEC_LEVEL2); +} + +/** + * @tc.name: Operator001 + * @tc.desc: Test for Operator securityLabel is NOT_SET. + * @tc.type: FUNC + */ +HWTEST_F(SensitiveTest, Operator001, TestSize.Level1) +{ + Sensitive sensitive; + DistributedDB::SecurityOption option; + option.securityLabel = DistributedDB::NOT_SET; + EXPECT_TRUE(sensitive >= option); +} + +/** + * @tc.name: Operator002 + * @tc.desc: Test for Operator securityLabel is S3. + * @tc.type: FUNC + */ +HWTEST_F(SensitiveTest, Operator002, TestSize.Level1) +{ + Sensitive sensitive; + DistributedDB::SecurityOption option; + option.securityLabel = DistributedDB::S3; + EXPECT_FALSE(sensitive >= option); +} + +/** + * @tc.name: Operator002 + * @tc.desc: Test for Operator securityLabel is S1. + * @tc.type: FUNC + */ +HWTEST_F(SensitiveTest, Operator003, TestSize.Level1) +{ + Sensitive sensitive; + DistributedDB::SecurityOption option; + option.securityLabel = DistributedDB::S1; + EXPECT_TRUE(sensitive >= option); +} + +/** + * @tc.name: Operator003 + * @tc.desc: Test for Operator securityLabel is S4. + * @tc.type: FUNC + */ +HWTEST_F(SensitiveTest, Operator004, TestSize.Level1) +{ + Sensitive sensitive; + sensitive.securityLevel = DATA_SEC_LEVEL2; + DistributedDB::SecurityOption option; + option.securityLabel = DistributedDB::S4; + EXPECT_FALSE(sensitive >= option); +} + +/** + * @tc.name: Operator004 + * @tc.desc: Test for Operator securityLabel is S1. + * @tc.type: FUNC + */ +HWTEST_F(SensitiveTest, Operator005, TestSize.Level1) +{ + Sensitive sensitive; + sensitive.securityLevel = DATA_SEC_LEVEL2; + DistributedDB::SecurityOption option; + option.securityLabel = DistributedDB::S1; + EXPECT_TRUE(sensitive >= option); +} +} // namespace OHOS::Test \ No newline at end of file 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 8031dc6c64107682bd434dfcaadd6fa5064d5933..f08136914b96789695d27479c26ea2aa7b88a1fe 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 @@ -13,10 +13,20 @@ * limitations under the License. */ +#include "session_manager/session_manager.h" + +#include + +#include "access_check/app_access_check_config_manager.h" #include "accesstoken_kit.h" +#include "account_delegate_mock.h" +#include "auth_delegate_mock.h" #include "bootstrap.h" +#include "db_store_mock.h" #include "device_manager_adapter.h" -#include "kvstore_meta_manager.h" +#include "device_manager_adapter_mock.h" +#include "gtest/gtest.h" +#include "meta_data_manager_mock.h" #include "metadata/meta_data_manager.h" #include "metadata/store_meta_data.h" #include "nativetoken_kit.h" @@ -24,18 +34,27 @@ #include "session_manager/upgrade_manager.h" #include "token_setproc.h" #include "user_delegate.h" -#include "gtest/gtest.h" +#include "user_delegate_mock.h" +#include "utils/endian_converter.h" namespace { +using namespace testing; using namespace testing::ext; using namespace OHOS::DistributedKv; using namespace OHOS::DistributedData; +using namespace DistributedDB; using namespace OHOS; using namespace OHOS::Security::AccessToken; +using DeviceInfo = OHOS::AppDistributedKv::DeviceInfo; +using UserInfo = DistributedDB::UserInfo; +using AppMappingInfo = OHOS::DistributedData::AppAccessCheckConfigManager::AppMappingInfo; constexpr const char *PEER_DEVICE_ID = "PEER_DEVICE_ID"; +constexpr const char *DEFAULT_USERID = "0"; constexpr int PEER_USER_ID1 = 101; constexpr int PEER_USER_ID2 = 100; +constexpr int32_t USER_MAXID = 4; constexpr int METADATA_UID = 2000000; +static constexpr int32_t OH_OS_TYPE = 10; void GrantPermissionNative() { @@ -55,20 +74,51 @@ void GrantPermissionNative() uint64_t tokenId = GetAccessTokenId(&infoInstance); SetSelfTokenID(tokenId); AccessTokenKit::ReloadNativeTokenInfo(); - delete []perms; + delete[] perms; } class SessionManagerTest : public testing::Test { public: + void CreateUserStatus(std::vector &users) + { + for (int32_t i = 0; i < USER_MAXID; i++) { + UserStatus stat; + stat.id = i; + users.push_back(stat); + } + } + + static void CreateStoreMetaData(std::vector &datas, SessionPoint local) + { + StoreMetaData data; + data.appId = local.appId; + data.storeId = local.storeId; + data.bundleName = "com.test.session"; + StoreMetaData data1; + data1.appId = local.appId; + data1.storeId = "local.storeId"; + data1.bundleName = "com.test.session1"; + StoreMetaData data2; + data2.appId = "local.appId"; + data2.storeId = local.storeId; + data2.bundleName = "com.test.session2"; + StoreMetaData data3; + data3.appId = "local.appId"; + data3.storeId = "local.storeId"; + data3.bundleName = "com.test.session3"; + datas.push_back(data); + datas.push_back(data1); + datas.push_back(data2); + datas.push_back(data3); + } + static void SetUpTestCase() { + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); auto executors = std::make_shared(12, 5); Bootstrap::GetInstance().LoadComponents(); Bootstrap::GetInstance().LoadDirectory(); Bootstrap::GetInstance().LoadCheckers(); - KvStoreMetaManager::GetInstance().BindExecutor(executors); - KvStoreMetaManager::GetInstance().InitMetaParameter(); - KvStoreMetaManager::GetInstance().InitMetaListener(); DeviceManagerAdapter::GetInstance().Init(executors); // init peer device @@ -90,51 +140,203 @@ public: auto peerCapMetaKey = CapMetaRow::GetKeyFor(userMetaData.deviceId); MetaDataManager::GetInstance().SaveMeta({ peerCapMetaKey.begin(), peerCapMetaKey.end() }, capMetaData); - - 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; - metaData.tokenId = AccessTokenKit::GetHapTokenID(PEER_USER_ID2, "ohos.test.demo", 0); - metaData.uid = METADATA_UID; - metaData.storeType = 1; - MetaDataManager::GetInstance().SaveMeta(metaData.GetKey(), metaData); + InitSystemMetaData(); + InitNormalMetaData(); GrantPermissionNative(); } + static void TearDownTestCase() { auto peerUserMetaKey = UserMetaRow::GetKeyFor(PEER_DEVICE_ID); MetaDataManager::GetInstance().DelMeta(std::string(peerUserMetaKey.begin(), peerUserMetaKey.end())); auto peerCapMetaKey = CapMetaRow::GetKeyFor(PEER_DEVICE_ID); 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; - metaData.tokenId = AccessTokenKit::GetHapTokenID(PEER_USER_ID2, "ohos.test.demo", 0); - metaData.uid = METADATA_UID; - metaData.storeType = 1; - MetaDataManager::GetInstance().DelMeta(metaData.GetKey()); } + void SetUp() { + deviceManagerAdapterMock = std::make_shared(); + BDeviceManagerAdapter::deviceManagerAdapter = deviceManagerAdapterMock; + userDelegateMock = std::make_shared(); + BUserDelegate::userDelegate = userDelegateMock; + ConstructValidData(); + auto res = MetaDataManager::GetInstance().SaveMeta(systemMetaData_.GetKey(), systemMetaData_); + EXPECT_EQ(res, true); + res = MetaDataManager::GetInstance().SaveMeta(normalMetaData_.GetKey(), normalMetaData_); + EXPECT_EQ(res, true); } + void TearDown() { + deviceManagerAdapterMock = nullptr; + BDeviceManagerAdapter::deviceManagerAdapter = nullptr; + userDelegateMock = nullptr; + BUserDelegate::userDelegate = nullptr; + MetaDataManager::GetInstance().DelMeta(systemMetaData_.GetKey()); + MetaDataManager::GetInstance().DelMeta(normalMetaData_.GetKey()); + } + + void ConstructValidData() + { + const std::string storeId = "test_store"; + InitializeBuffer(); + ConstructRouteHead(storeId); + ConstructSessionDevicePair(); + ConstructSessionUserPair(); + ConstructSessionAppId(); + ConstructSessionStoreId(storeId); + + const size_t validlLen = sizeof(RouteHead) + sizeof(SessionDevicePair) + sizeof(SessionUserPair) + + sizeof(uint32_t) * 1 + sizeof(SessionAppId) + APP_STR_LEN + sizeof(SessionStoreId) + + storeId.size(); + validTotalLen = validlLen; + } + + static void InitSystemMetaData(); + static void InitNormalMetaData(); + static std::shared_ptr dbStoreMock_; + static StoreMetaData systemMetaData_; + static StoreMetaData normalMetaData_; + + static inline std::shared_ptr deviceManagerAdapterMock = nullptr; + static inline std::shared_ptr userDelegateMock = nullptr; + +private: + void InitializeBuffer() + { + memset_s(dataBuffer, BUFFER_SIZE, 0, BUFFER_SIZE); + ptr = dataBuffer; + remaining = BUFFER_SIZE; } + + void ConstructRouteHead(const std::string &storeId) + { + RouteHead head{}; + head.magic = HostToNet(RouteHead::MAGIC_NUMBER); + head.version = HostToNet(RouteHead::VERSION); + head.dataLen = HostToNet(sizeof(SessionDevicePair) + sizeof(SessionUserPair) + sizeof(uint32_t) * 1 + + sizeof(SessionAppId) + APP_STR_LEN + sizeof(SessionStoreId) + storeId.size()); + head.checkSum = 0; + + errno_t err = memcpy_s(ptr, remaining, &head, sizeof(RouteHead)); + ASSERT_EQ(err, 0) << "Failed to copy RouteHead"; + ptr += sizeof(RouteHead); + remaining -= sizeof(RouteHead); + } + + void ConstructSessionDevicePair() + { + SessionDevicePair devPair{ .sourceId = "PEER_DEVICE_ID", .targetId = "PEER_DEVICE_ID" }; + constexpr size_t DEV_ID_SIZE = sizeof(devPair.sourceId); + + errno_t err = memset_s(devPair.sourceId, DEV_ID_SIZE, 'A', DEV_ID_SIZE - 1); + ASSERT_EQ(err, 0) << "Failed to init sourceId"; + devPair.sourceId[DEV_ID_SIZE - 1] = '\0'; + + err = memset_s(devPair.targetId, DEV_ID_SIZE, 'B', DEV_ID_SIZE - 1); + ASSERT_EQ(err, 0) << "Failed to init targetId"; + devPair.targetId[DEV_ID_SIZE - 1] = '\0'; + + err = memcpy_s(ptr, remaining, &devPair, sizeof(SessionDevicePair)); + ASSERT_EQ(err, 0) << "Failed to copy SessionDevicePair"; + ptr += sizeof(SessionDevicePair); + remaining -= sizeof(SessionDevicePair); + } + + void ConstructSessionUserPair() + { + SessionUserPair userPair{}; + userPair.sourceUserId = HostToNet(100U); + userPair.targetUserCount = HostToNet(1U); + + errno_t err = memcpy_s(ptr, remaining, &userPair, sizeof(SessionUserPair)); + ASSERT_EQ(err, 0) << "Failed to copy SessionUserPair"; + ptr += sizeof(SessionUserPair); + remaining -= sizeof(SessionUserPair); + + uint32_t targetUser = HostToNet(200U); + err = memcpy_s(ptr, remaining, &targetUser, sizeof(uint32_t)); + ASSERT_EQ(err, 0) << "Failed to copy targetUser"; + ptr += sizeof(uint32_t); + remaining -= sizeof(uint32_t); + } + + void ConstructSessionAppId() + { + SessionAppId appId{}; + const char *appStr = "test"; + appId.len = HostToNet(static_cast(APP_STR_LEN)); + + errno_t err = memcpy_s(ptr, remaining, &appId, sizeof(SessionAppId)); + ASSERT_EQ(err, 0) << "Failed to copy SessionAppId"; + ptr += sizeof(SessionAppId); + remaining -= sizeof(SessionAppId); + + err = memcpy_s(ptr, remaining, appStr, APP_STR_LEN); + ASSERT_EQ(err, 0) << "Failed to copy appId data"; + ptr += APP_STR_LEN; + remaining -= APP_STR_LEN; + } + + void ConstructSessionStoreId(const std::string &storeId) + { + SessionStoreId storeIdHeader{}; + storeIdHeader.len = HostToNet(static_cast(storeId.size())); + + errno_t err = memcpy_s(ptr, remaining, &storeIdHeader, sizeof(SessionStoreId)); + ASSERT_EQ(err, 0) << "Failed to copy storeId length"; + ptr += sizeof(SessionStoreId); + remaining -= sizeof(SessionStoreId); + + err = memcpy_s(ptr, remaining, storeId.c_str(), storeId.size()); + ASSERT_EQ(err, 0) << "Failed to copy storeId data"; + ptr += storeId.size(); + remaining -= storeId.size(); + } + + size_t validTotalLen; + uint8_t dataBuffer[1024]; + static constexpr size_t APP_STR_LEN = 4; + uint8_t *ptr = dataBuffer; + size_t remaining = BUFFER_SIZE; + static constexpr size_t BUFFER_SIZE = sizeof(dataBuffer); }; +std::shared_ptr SessionManagerTest::dbStoreMock_ = std::make_shared(); +StoreMetaData SessionManagerTest::systemMetaData_; +StoreMetaData SessionManagerTest::normalMetaData_; + +void SessionManagerTest::InitNormalMetaData() +{ + normalMetaData_.bundleName = "ohos.test.demo"; + normalMetaData_.appId = "ohos.test.demo"; + normalMetaData_.storeId = "test_store"; + normalMetaData_.user = "100"; + normalMetaData_.deviceId = "local_device"; + normalMetaData_.tokenId = AccessTokenKit::GetHapTokenID(PEER_USER_ID2, "ohos.test.demo", 0); + normalMetaData_.uid = METADATA_UID; + normalMetaData_.storeType = 1; +} + +void SessionManagerTest::InitSystemMetaData() +{ + systemMetaData_.bundleName = "ohos.test.demo"; + systemMetaData_.appId = "ohos.test.demo"; + systemMetaData_.storeId = "test_store"; + systemMetaData_.user = DEFAULT_USERID; + systemMetaData_.deviceId = "local_device"; + systemMetaData_.tokenId = AccessTokenKit::GetHapTokenID(PEER_USER_ID2, "ohos.test.demo", 0); + systemMetaData_.uid = METADATA_UID; + systemMetaData_.storeType = 1; +} + /** -* @tc.name: PackAndUnPack01 -* @tc.desc: test get db dir -* @tc.type: FUNC -* @tc.require: -* @tc.author: illybyy -*/ + * @tc.name: PackAndUnPack01 + * @tc.desc: test get db dir + * @tc.type: FUNC + * @tc.require: + * @tc.author: illybyy + */ HWTEST_F(SessionManagerTest, PackAndUnPack01, TestSize.Level2) { const DistributedDB::ExtendInfo info = { @@ -151,10 +353,584 @@ HWTEST_F(SessionManagerTest, PackAndUnPack01, TestSize.Level2) std::vector users; auto recvHandler = RouteHeadHandlerImpl::Create({}); ASSERT_NE(recvHandler, nullptr); - uint32_t parseSize = 1; - recvHandler->ParseHeadDataLen(data.get(), routeHeadSize, parseSize); + uint32_t parseSize = 0; + std::string device = ""; + recvHandler->ParseHeadDataLen(data.get(), routeHeadSize, parseSize, device); EXPECT_EQ(routeHeadSize, parseSize); recvHandler->ParseHeadDataUser(data.get(), routeHeadSize, "", users); ASSERT_EQ(users.size(), 0); } + +/** + * @tc.name: GetHeadDataSize_Test1 + * @tc.desc: test appId equal processLabel. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test1, TestSize.Level1) +{ + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t headSize = 0; + routeHeadHandlerImpl.appId_ = Bootstrap::GetInstance().GetProcessLabel(); + auto status = routeHeadHandlerImpl.GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::OK); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: GetHeadDataSize_Test2 + * @tc.desc: test appId not equal processLabel. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test2, TestSize.Level1) +{ + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t headSize = 0; + routeHeadHandlerImpl.appId_ = "otherAppId"; + auto status = routeHeadHandlerImpl.GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::DB_ERROR); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: GetHeadDataSize_Test3 + * @tc.desc: test devInfo.osType equal OH_OS_TYPE, appId not equal processLabel. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test3, TestSize.Level1) +{ + DeviceInfo deviceInfo; + deviceInfo.osType = OH_OS_TYPE; + EXPECT_CALL(*deviceManagerAdapterMock, GetDeviceInfo(_)).WillRepeatedly(Return(deviceInfo)); + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t headSize = 0; + routeHeadHandlerImpl.appId_ = "otherAppId"; + auto status = routeHeadHandlerImpl.GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::DB_ERROR); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: GetHeadDataSize_Test4 + * @tc.desc: test GetHeadDataSize + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test4, TestSize.Level1) +{ + DeviceInfo deviceInfo; + deviceInfo.osType = OH_OS_TYPE; + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + EXPECT_CALL(*deviceManagerAdapterMock, GetDeviceInfo(_)).WillRepeatedly(Return(deviceInfo)); + + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test_store", .userId = DEFAULT_USERID, .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + + auto userId = sendHandler->GetTargetUserId(); + EXPECT_EQ(userId, "0"); + + std::vector userStatus; + UserStatus userStat1; + UserStatus userStat2; + UserStatus userStat3; + userStat1.id = 1; + userStat2.id = 2; + userStat3.id = 3; + userStatus.push_back(userStat1); + userStatus.push_back(userStat2); + userStatus.push_back(userStat3); + EXPECT_CALL(*userDelegateMock, GetRemoteUserStatus(_)).WillRepeatedly(Return(userStatus)); + + uint32_t headSize = 0; + auto status = sendHandler->GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::OK); + EXPECT_EQ(headSize, 208); + + uint32_t routeHeadSize = 10; + std::unique_ptr data = std::make_unique(routeHeadSize); + status = sendHandler->FillHeadData(data.get(), routeHeadSize, routeHeadSize); + EXPECT_EQ(status, DistributedDB::DB_ERROR); +} + +/** + * @tc.name: GetHeadDataSize_Test5 + * @tc.desc: test device is not OH_OS_TYPE and appId is empty. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test5, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillOnce(Return(true)).WillOnce(Return(false)); + const DistributedDB::ExtendInfo info = { + .appId = "", .storeId = "test_store", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + uint32_t headSize; + auto status = sendHandler->GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::DB_ERROR); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: GetHeadDataSize_Test6 + * @tc.desc: test device != OH_OS_TYPE && appId.isNotEmpty && appId.isTrusted. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test6, TestSize.Level1) +{ + const DistributedDB::ExtendInfo info = { + .appId = "com.test.demo", .storeId = "test", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + std::vector mapper = { { .appId = info.appId, .bundleName = info.appId } }; + AppAccessCheckConfigManager::GetInstance().Initialize(mapper); + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + uint32_t headSize; + auto status = sendHandler->GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::OK); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: GetHeadDataSize_Test7 + * @tc.desc: test GetCapability is failed. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test7, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test", .userId = "100", .dstTarget = "10" + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + uint32_t headSize; + auto status = sendHandler->GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::DB_ERROR); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: GetHeadDataSize_Test8 + * @tc.desc: test peerCap.version != INALID_VERSION && session is invalid. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test8, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + uint32_t headSize; + auto status = sendHandler->GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::DB_ERROR); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: GetHeadDataSize_Test9 + * @tc.desc: test peerCap.version != INALID_VERSION && session is valid. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test9, TestSize.Level1) +{ + DeviceInfo deviceInfo; + deviceInfo.uuid = PEER_DEVICE_ID; + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + EXPECT_CALL(*deviceManagerAdapterMock, GetLocalDevice()).WillRepeatedly(Return(deviceInfo)); + const DistributedDB::ExtendInfo info = { + .appId = "test", .storeId = "test_store", .userId = DEFAULT_USERID, .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + uint32_t headSize; + auto status = sendHandler->GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::OK); + EXPECT_EQ(headSize, 200); + + uint32_t totalLen = 300; + std::unique_ptr data = std::make_unique(totalLen); + status = sendHandler->FillHeadData(data.get(), headSize, totalLen); + EXPECT_EQ(status, DistributedDB::OK); + uint32_t parseHeadSize; + auto res = sendHandler->ParseHeadDataLen(data.get(), totalLen, parseHeadSize, info.storeId); + EXPECT_EQ(res, true); + EXPECT_EQ(parseHeadSize, 200); + + std::vector userInfos; + std::string label; + res = sendHandler->ParseHeadDataUser(data.get(), totalLen, label, userInfos); + EXPECT_EQ(res, true); + EXPECT_EQ(label, ""); + EXPECT_EQ(userInfos.size(), 1); +} + +/** + * @tc.name: ParseHeadDataLenTest001 + * @tc.desc: test ParseHeadDataLen data is nullptr. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, ParseHeadDataLenTest001, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test_store", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + + uint32_t totalLen = 10; + uint32_t headSize; + std::string device = "device"; + + bool result = sendHandler->ParseHeadDataLen(nullptr, totalLen, headSize, device); + EXPECT_EQ(result, false); + + auto status = sendHandler->FillHeadData(nullptr, headSize, headSize); + EXPECT_EQ(status, DistributedDB::DB_ERROR); +} + +/** + * @tc.name: ParseHeadDataLenTest002 + * @tc.desc: test ParseHeadDataLen totalLen < sizeof(RouteHead). + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, ParseHeadDataLenTest002, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test_store", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + + uint32_t totalLen = 10; + uint32_t headSize; + std::string device = "device"; + + bool result = sendHandler->ParseHeadDataLen(dataBuffer, totalLen, headSize, device); + EXPECT_EQ(result, false); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: ParseHeadDataLenTest003 + * @tc.desc: test ParseHeadDataLen totalLen - sizeof(RouteHead) < routeHead.dataLen. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, ParseHeadDataLenTest003, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test_store", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + + uint32_t totalLen = 20; + uint32_t headSize; + std::string device = "device"; + + bool result = sendHandler->ParseHeadDataLen(dataBuffer, totalLen, headSize, device); + EXPECT_EQ(result, false); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: ParseHeadDataUserTest001 + * @tc.desc: test parse null data. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, ParseHeadDataUserTest001, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test_store", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + + auto userId = sendHandler->GetTargetUserId(); + EXPECT_EQ(userId, ""); + uint32_t totalLen = 10; + std::string label = "testLabel"; + std::vector userInfos; + + bool result = sendHandler->ParseHeadDataUser(nullptr, totalLen, label, userInfos); + + EXPECT_FALSE(result); + EXPECT_EQ(userInfos.size(), 0); +} + +/** + * @tc.name: ParseHeadDataUserTest002 + * @tc.desc: test totalLen < sizeof(RouteHead). + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, ParseHeadDataUserTest002, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test_store", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + + uint8_t data[10] = { 0 }; + std::string label = "testLabel"; + std::vector userInfos; + + bool result = sendHandler->ParseHeadDataUser(data, sizeof(RouteHead) - 1, label, userInfos); + + EXPECT_FALSE(result); + EXPECT_EQ(userInfos.size(), 0); +} + +/** + * @tc.name: ParseHeadDataUserTest003 + * @tc.desc: test totalLen < sizeof(RouteHead). + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, ParseHeadDataUserTest003, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test_store", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + + uint8_t data[10] = { 0 }; + std::string label = "testLabel"; + std::vector userInfos; + + RouteHead head = { 0 }; + head.version = RouteHead::VERSION; + head.dataLen = static_cast(sizeof(data) - sizeof(RouteHead)); + + bool result = sendHandler->ParseHeadDataUser(data, sizeof(RouteHead), label, userInfos); + + EXPECT_FALSE(result); + EXPECT_EQ(userInfos.size(), 0); +} + +/** + * @tc.name: PackDataTest1 + * @tc.desc: test headSize_ > totalLen. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, PackDataTest1, TestSize.Level1) +{ + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + routeHeadHandlerImpl.headSize_ = 1; + uint32_t totalLen = 0; + EXPECT_EQ(routeHeadHandlerImpl.PackData(dataBuffer, totalLen), false); +} + +/** + * @tc.name: PackDataTest2 + * @tc.desc: test headSize_ < sizeof(RouteHead). + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, PackDataTest2, TestSize.Level1) +{ + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + routeHeadHandlerImpl.headSize_ = 10; + uint32_t totalLen = 11; + EXPECT_EQ(routeHeadHandlerImpl.PackData(dataBuffer, totalLen), false); +} + +/** + * @tc.name: UnPackData_InvalidMagic + * @tc.desc: test invalid magic. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, UnPackData_InvalidMagic, TestSize.Level1) +{ + RouteHead *head = reinterpret_cast(dataBuffer); + head->magic = 0xFFFF; + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t unpackedSize; + EXPECT_FALSE(routeHeadHandlerImpl.UnPackData(dataBuffer, validTotalLen, unpackedSize)); +} + +/** + * @tc.name: UnPackData_VersionMismatch + * @tc.desc: test version mismatch. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, UnPackData_VersionMismatch, TestSize.Level1) +{ + RouteHead *head = reinterpret_cast(dataBuffer); + head->version = 0x00; + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t unpackedSize; + EXPECT_FALSE(routeHeadHandlerImpl.UnPackData(dataBuffer, validTotalLen, unpackedSize)); +} + +/** + * @tc.name: UnPackDataBody01 + * @tc.desc: test leftSize < sizeof(SessionDevicePair). + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, UnPackDataBody01, TestSize.Level1) +{ + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t totalLen = 100; + auto res = routeHeadHandlerImpl.UnPackDataBody(dataBuffer, totalLen); + EXPECT_EQ(res, false); +} + +/** + * @tc.name: UnPackDataBody02 + * @tc.desc: test leftSize < sizeof(SessionUserPair). + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, UnPackDataBody02, TestSize.Level1) +{ + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t totalLen = 133; + auto res = routeHeadHandlerImpl.UnPackDataBody(dataBuffer, totalLen); + EXPECT_EQ(res, false); +} + +/** + * @tc.name: UnPackDataBody03 + * @tc.desc: test leftSize < userPairSize. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, UnPackDataBody03, TestSize.Level1) +{ + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t totalLen = 136; + auto res = routeHeadHandlerImpl.UnPackDataBody(dataBuffer, totalLen); + EXPECT_EQ(res, false); +} + +/** + * @tc.name: UnPackDataBody05 + * @tc.desc: test leftSize < sizeof(SessionAppId). + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, UnPackDataBody05, TestSize.Level1) +{ + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t totalLen = 400; + auto res = routeHeadHandlerImpl.UnPackDataBody(dataBuffer, totalLen); + EXPECT_EQ(res, false); +} + +/** + * @tc.name: ShouldAddSystemUserWhenLocalUserIdIsSystem + * @tc.desc: test GetSession. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, ShouldAddSystemUserWhenLocalUserIdIsSystem, TestSize.Level1) +{ + SessionPoint local; + local.userId = UserDelegate::SYSTEM_USER; + local.appId = "ohos.test.demo"; + local.deviceId = "local_device"; + local.storeId = "test_store"; + + std::vector users; + CreateUserStatus(users); + EXPECT_CALL(*userDelegateMock, GetRemoteUserStatus(_)).WillOnce(Return(users)); + EXPECT_CALL(AuthHandlerMock::GetInstance(), CheckAccess(_, _, _, _)) + .WillOnce(Return(std::pair(true, true))) + .WillOnce(Return(std::pair(true, false))) + .WillOnce(Return(std::pair(false, true))) + .WillOnce(Return(std::pair(false, false))); + Session session = SessionManager::GetInstance().GetSession(local, local.deviceId); + ASSERT_EQ(2, session.targetUserIds.size()); + EXPECT_EQ(UserDelegate::SYSTEM_USER, session.targetUserIds[0]); +} + +/** + * @tc.name: ShouldReturnEarlyWhenGetSendAuthParamsFails + * @tc.desc: test GetSession. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, ShouldReturnEarlyWhenGetSendAuthParamsFails, TestSize.Level1) +{ + SessionPoint local; + local.userId = 100; + local.appId = "test_app"; + local.deviceId = "local_device"; + EXPECT_CALL(*userDelegateMock, GetRemoteUserStatus(_)).WillOnce(Return(std::vector{})); + + Session session = SessionManager::GetInstance().GetSession(local, "target_device"); + + EXPECT_TRUE(session.targetUserIds.empty()); +} + +/** + * @tc.name: CheckSession + * @tc.desc: test CheckSession. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, CheckSession, TestSize.Level1) +{ + SessionPoint localSys; + localSys.userId = UserDelegate::SYSTEM_USER; + localSys.appId = "ohos.test.demo"; + localSys.deviceId = "local_device"; + localSys.storeId = "test_store"; + SessionPoint localNormal; + localNormal.userId = 100; + localNormal.appId = "ohos.test.demo"; + localNormal.deviceId = "local_device"; + localNormal.storeId = "test_store"; + localNormal.accountId = "test_account"; + SessionPoint invalidPoint; + EXPECT_CALL(AuthHandlerMock::GetInstance(), CheckAccess(_, _, _, _)) + .WillOnce(Return(std::pair(false, true))) + .WillOnce(Return(std::pair(true, false))); + bool result = SessionManager::GetInstance().CheckSession(invalidPoint, invalidPoint, true); + EXPECT_FALSE(result); + result = SessionManager::GetInstance().CheckSession(localSys, localNormal, true); + EXPECT_FALSE(result); + result = SessionManager::GetInstance().CheckSession(localNormal, localSys, true); + EXPECT_TRUE(result); +} } // namespace \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/upgrade_manager_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/upgrade_manager_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..70164b93e9f9ae485bba17fd025dc55c66b99a7e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/upgrade_manager_test.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2025 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 "upgrade_manager.h" + +#include + +#include "device_manager_adapter.h" +#include "metadata/meta_data_manager.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::DistributedData; + +static constexpr size_t THREAD_MIN = 0; +static constexpr size_t THREAD_MAX = 2; +static constexpr const char* REMOTE_DEVICE = "0123456789ABCDEF"; + +class UpgradeManagerTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; + + static std::shared_ptr executors_; + static std::string localDevice_; +}; + +std::shared_ptr UpgradeManagerTest::executors_; +std::string UpgradeManagerTest::localDevice_; + +void UpgradeManagerTest::SetUpTestCase(void) +{ + localDevice_ = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + executors_ = std::make_shared(THREAD_MAX, THREAD_MIN); + MetaDataManager::GetInstance().Init(executors_); + UpgradeManager::GetInstance().Init(executors_); + sleep(1); +} + +/** +* @tc.name: GetCapabilityTest001 +* @tc.desc: get local device capability +* @tc.type: FUNC +*/ +HWTEST_F(UpgradeManagerTest, GetCapabilityTest001, TestSize.Level1) +{ + bool result = false; + auto capMeta = UpgradeManager::GetInstance().GetCapability(localDevice_, result); + ASSERT_EQ(result, true); + ASSERT_EQ(capMeta.version, CapMetaData::CURRENT_VERSION); + ASSERT_EQ(capMeta.deviceId, localDevice_); +} + +/** +* @tc.name: GetCapabilityTest002 +* @tc.desc: get non-exist remote device capability +* @tc.type: FUNC +*/ +HWTEST_F(UpgradeManagerTest, GetCapabilityTest002, TestSize.Level1) +{ + bool result = true; + auto capMeta = UpgradeManager::GetInstance().GetCapability(REMOTE_DEVICE, result); + ASSERT_EQ(result, false); + ASSERT_EQ(capMeta.version, CapMetaData::INVALID_VERSION); + ASSERT_EQ(capMeta.deviceId, ""); +} + +/** +* @tc.name: GetCapabilityTest003 +* @tc.desc: get remote device capability by callback of meta save-update-delete +* @tc.type: FUNC +*/ +HWTEST_F(UpgradeManagerTest, GetCapabilityTest003, TestSize.Level1) +{ + CapMetaData capMetaData; + capMetaData.version = CapMetaData::CURRENT_VERSION; + capMetaData.deviceId = REMOTE_DEVICE; + auto capKey = CapMetaRow::GetKeyFor(REMOTE_DEVICE); + (void)MetaDataManager::GetInstance().SaveMeta({ capKey.begin(), capKey.end() }, capMetaData); + sleep(1); + + bool result = false; + auto capMeta = UpgradeManager::GetInstance().GetCapability(REMOTE_DEVICE, result); + ASSERT_EQ(result, true); + ASSERT_EQ(capMeta.version, capMetaData.version); + ASSERT_EQ(capMeta.deviceId, REMOTE_DEVICE); + + capMetaData.version = CapMetaData::INVALID_VERSION; + (void)MetaDataManager::GetInstance().UpdateMeta({ capKey.begin(), capKey.end() }, capMetaData); + sleep(1); + + result = false; + capMeta = UpgradeManager::GetInstance().GetCapability(REMOTE_DEVICE, result); + ASSERT_EQ(result, true); + ASSERT_EQ(capMeta.version, capMetaData.version); + ASSERT_EQ(capMeta.deviceId, REMOTE_DEVICE); + + (void)MetaDataManager::GetInstance().DeleteMeta({ capKey.begin(), capKey.end() }, capMetaData); + sleep(1); + + capMeta = UpgradeManager::GetInstance().GetCapability(REMOTE_DEVICE, result); + ASSERT_EQ(result, false); + ASSERT_EQ(capMeta.version, CapMetaData::INVALID_VERSION); + ASSERT_EQ(capMeta.deviceId, ""); +} + +/** +* @tc.name: GetCapabilityTest004 +* @tc.desc: get remote device capability by meta store +* @tc.type: FUNC +*/ +HWTEST_F(UpgradeManagerTest, GetCapabilityTest004, TestSize.Level1) +{ + MetaDataManager::GetInstance().UnSubscribe(); + CapMetaData capMetaData; + capMetaData.version = CapMetaData::CURRENT_VERSION; + capMetaData.deviceId = REMOTE_DEVICE; + auto capKey = CapMetaRow::GetKeyFor(REMOTE_DEVICE); + (void)MetaDataManager::GetInstance().SaveMeta({ capKey.begin(), capKey.end() }, capMetaData); + + bool result = false; + auto capMeta = UpgradeManager::GetInstance().GetCapability(REMOTE_DEVICE, result); + ASSERT_EQ(result, true); + ASSERT_EQ(capMeta.version, capMetaData.version); + ASSERT_EQ(capMeta.deviceId, REMOTE_DEVICE); +} \ 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 9697057356d03b7b6838f18c6b26d3104b7cf44b..fc66642e0a8f4586a032d3870826c864e3eb8349 100644 --- a/datamgr_service/services/distributeddataservice/framework/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/framework/BUILD.gn @@ -21,12 +21,7 @@ config("module_config") { visibility = [ ":*" ] include_dirs = [ "include", - "include/utils", "${data_service_path}/adapter/include", - "${kv_store_path}/interfaces/innerkits/distributeddata/include", - "${kv_store_common_path}", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/include/", ] } @@ -34,10 +29,6 @@ config("module_public_config") { visibility = [ ":*" ] include_dirs = [ "include", - "${data_service_path}/framework/include/account", - "${data_service_path}/framework/include/dfx", - "${data_service_path}/framework/include/network", - "${kv_store_common_path}", ] } @@ -52,6 +43,7 @@ ohos_shared_library("distributeddatasvcfwk") { } sources = [ "account/account_delegate.cpp", + "access_check/app_access_check_config_manager.cpp", "app_id_mapping/app_id_mapping_config_manager.cpp", "backuprule/backup_rule_manager.cpp", "changeevent/remote_change_event.cpp", @@ -76,6 +68,9 @@ ohos_shared_library("distributeddatasvcfwk") { "cloud/sync_event.cpp", "cloud/sync_strategy.cpp", "communication/connect_manager.cpp", + "crypto/crypto_manager.cpp", + "device_manager/device_manager_delegate.cpp", + "device_sync_app/device_sync_app_manager.cpp", "dfx/reporter.cpp", "directory/directory_manager.cpp", "dump/dump_manager.cpp", @@ -92,6 +87,7 @@ ohos_shared_library("distributeddatasvcfwk") { "metadata/matrix_meta_data.cpp", "metadata/meta_data.cpp", "metadata/meta_data_manager.cpp", + "metadata/object_user_meta_data.cpp", "metadata/secret_key_meta_data.cpp", "metadata/store_debug_info.cpp", "metadata/store_meta_data.cpp", @@ -124,15 +120,11 @@ ohos_shared_library("distributeddatasvcfwk") { "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-fdata-sections", "-ffunction-sections", - "-fstack-protector-strong", ] - ldflags = [ "-Wl,-z,relro,-z,now,--gc-sections" ] + ldflags = [ "-Wl,--gc-sections" ] - cflags_cc = [ - "-fvisibility=hidden", - "-fstack-protector-strong", - ] + cflags_cc = [ "-fvisibility=hidden" ] configs = [ ":module_config" ] @@ -143,8 +135,11 @@ ohos_shared_library("distributeddatasvcfwk") { "c_utils:utils", "common_event_service:cesfwk_innerkits", "hilog:libhilog", + "huks:libhukssdk", "json:nlohmann_json_static", "openssl:libcrypto_shared", + "kv_store:datamgr_common", + "kv_store:distributeddb", ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt b/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt index 6b9b30cf784bc28983c7147b2cbacb69e65828db..e6e0e711f5711c5119f0c0e861d35873e24fc79d 100644 --- a/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt @@ -4,12 +4,14 @@ project(svcFwk) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -fno-rtti -fvisibility=default -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} -Wl,--no-as-needed -ldl -D__CJSON_USE_INT64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=0 -fpermissive -Wattributes") 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") +add_definitions(-D__CJSON_USE_INT64) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/access_check svcFwkSrc) 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) @@ -17,7 +19,10 @@ 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}/crypto svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/device_manager svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/directory svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/device_sync_app svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/dfx svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/dump svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/eventcenter svcFwkSrc) @@ -37,7 +42,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../relational_store/int include(${MOCK_DIR}/include/CMakeLists.txt OPTIONAL) include(${KV_STORE_DIR}/interfaces/CMakeLists.txt OPTIONAL) -set(links secure mock) +set(links secure mock distributeddb) set(LIBRARY_OUTPUT_PATH "${PROJECT_BINARY_DIR}/../../../../") add_library(svcFwk SHARED ${svcFwkSrc}) target_link_libraries(svcFwk ${links}) diff --git a/datamgr_service/services/distributeddataservice/framework/access_check/app_access_check_config_manager.cpp b/datamgr_service/services/distributeddataservice/framework/access_check/app_access_check_config_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d5b5f9ddf597da3d320023f32d64e1a5626f19b --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/access_check/app_access_check_config_manager.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 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 "AppAccessCheckConfigManager" +#include "access_check/app_access_check_config_manager.h" +#include "log_print.h" +#include "utils/anonymous.h" + +namespace OHOS::DistributedData { +AppAccessCheckConfigManager &AppAccessCheckConfigManager::GetInstance() +{ + static AppAccessCheckConfigManager instance; + return instance; +} + +void AppAccessCheckConfigManager::Initialize(const std::vector &mapper) +{ + for (const auto &info : mapper) { + appMapper_.insert_or_assign(info.bundleName, info.appId); + } +} + +bool AppAccessCheckConfigManager::IsTrust(const std::string &appId) +{ + auto it = appMapper_.find(appId); + if (it != appMapper_.end() && (it->second == appId)) { + return true; + } + ZLOGE("check access failed, appId:%{public}s", Anonymous::Change(appId).c_str()); + return false; +} + +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/account/account_delegate.cpp b/datamgr_service/services/distributeddataservice/framework/account/account_delegate.cpp index 2b77557d43bc96b5fbac2ab39e6c99824e6a8ada..6ef959548c5f4ffbd07d3f22fa34a72ac9e7c0f4 100644 --- a/datamgr_service/services/distributeddataservice/framework/account/account_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/framework/account/account_delegate.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "account_delegate.h" +#include "account/account_delegate.h" namespace OHOS { namespace DistributedData { 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 index 3d03d5246261b7ba873aa408d3454edf801dd335..2f903bbbb9dd6e678df63b11835c3fb87a4990fd 100644 --- 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 @@ -40,4 +40,13 @@ std::pair AppIdMappingConfigManager::Convert(const std return std::make_pair(it->second, "default"); } + +std::string AppIdMappingConfigManager::Convert(const std::string &appId) +{ + auto it = toDstMapper_.find(appId); + if (it == toDstMapper_.end()) { + return appId; + } + return it->second; +} } // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/checker/checker_manager.cpp b/datamgr_service/services/distributeddataservice/framework/checker/checker_manager.cpp index e02f50c64a219711e8456453445ac5c0bb8d33d3..739ff5ce6fec69087428a17f5ccc03e48ccf1093 100644 --- a/datamgr_service/services/distributeddataservice/framework/checker/checker_manager.cpp +++ b/datamgr_service/services/distributeddataservice/framework/checker/checker_manager.cpp @@ -47,6 +47,26 @@ void CheckerManager::RegisterPlugin(const std::string &checker, std::functionDeleteCache(bundleName, user, index); + } +} + +void CheckerManager::ClearCache() +{ + for (auto &[name, checker] : checkers_) { + if (checker == nullptr) { + continue; + } + checker->ClearCache(); + } +} + std::string CheckerManager::GetAppId(const StoreInfo &info) { for (auto &[name, checker] : checkers_) { diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp index 863475888ff457cd9be3f5886f66524197822fc5..3d916243ee02ca5b969453b05c26e6279643a478 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp @@ -40,14 +40,14 @@ int32_t CloudDB::BatchDelete(const std::string &table, VBuckets &extends) return E_NOT_SUPPORT; } -std::shared_ptr CloudDB::Query(const std::string &table, const VBucket &extend) +std::pair> CloudDB::Query(const std::string &table, const VBucket &extend) { - return nullptr; + return { E_NOT_SUPPORT, nullptr }; } -std::shared_ptr CloudDB::Query(GenQuery &query, const VBucket &extend) +std::pair> CloudDB::Query(GenQuery &query, const VBucket &extend) { - return nullptr; + return { E_NOT_SUPPORT, nullptr }; } int32_t CloudDB::PreSharing(const std::string &table, VBuckets &extend) diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp index 2841cf0b29aabee3ecd2b7e37b86428217946d42..5d718ee74ae1faf9e78e0e40505779549e15ddff 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp @@ -87,4 +87,9 @@ bool CloudServer::IsSupportCloud(int32_t userId) { return false; } + +bool CloudServer::CloudDriverUpdated(const std::string &bundleName) +{ + return false; +} } // 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 7844058ae4dd70581a94cfd14959407429546665..273fc6b48eed65f1b6859108100c7abeb218dec7 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp @@ -23,6 +23,7 @@ bool SchemaMeta::Marshal(Serializable::json &node) const SetValue(node[GET_NAME(version)], version); SetValue(node[GET_NAME(bundleName)], bundleName); SetValue(node[GET_NAME(databases)], databases); + SetValue(node[GET_NAME(e2eeEnable)], e2eeEnable); return true; } @@ -35,6 +36,7 @@ bool SchemaMeta::Unmarshal(const Serializable::json &node) GetValue(node, GET_NAME(bundleName), bundleName); GetValue(node, GET_NAME(databases), databases); GetValue(node, GET_NAME(dbSchema), databases); + GetValue(node, GET_NAME(e2eeEnable), e2eeEnable); return true; } diff --git a/datamgr_service/services/distributeddataservice/framework/communication/connect_manager.cpp b/datamgr_service/services/distributeddataservice/framework/communication/connect_manager.cpp index 74f8f70a88d4e0120b66cfc9e4eada414b975c55..d63ad3342ac40c75902433955dd8c63bbc6de630 100644 --- a/datamgr_service/services/distributeddataservice/framework/communication/connect_manager.cpp +++ b/datamgr_service/services/distributeddataservice/framework/communication/connect_manager.cpp @@ -129,9 +129,10 @@ void ConnectManager::OnDestory() { } -int32_t ConnectManager::ApplyConnect(__attribute__((unused)) const std::string &networkId, ConnectTask task) +int32_t ConnectManager::ApplyConnect(__attribute__((unused)) const std::string &networkId, + __attribute__((unused)) ApplyTask applyTask, ConnectTask connectTask) { - task(); + connectTask(); return 0; } } // OHOS::AppDistributedKv \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/crypto/src/crypto_manager.cpp b/datamgr_service/services/distributeddataservice/framework/crypto/crypto_manager.cpp similarity index 62% rename from datamgr_service/services/distributeddataservice/service/crypto/src/crypto_manager.cpp rename to datamgr_service/services/distributeddataservice/framework/crypto/crypto_manager.cpp index d36f34cb658e63de0f6e31fa079c5b2250ec0f89..9db85edeb5471c099f5e10a7be18deed791f2568 100644 --- a/datamgr_service/services/distributeddataservice/service/crypto/src/crypto_manager.cpp +++ b/datamgr_service/services/distributeddataservice/framework/crypto/crypto_manager.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ #define LOG_TAG "CryptoManager" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include #include @@ -23,7 +23,13 @@ #include "log_print.h" #include "metadata/meta_data_manager.h" #include "securec.h" + namespace OHOS::DistributedData { +static constexpr int32_t NONCE_SIZE = 12; +static constexpr const char *ROOT_KEY_ALIAS = "distributed_db_root_key"; +static constexpr const char *HKS_BLOB_TYPE_NONCE = "Z5s0Bo571KoqwIi6"; +static constexpr const char *HKS_BLOB_TYPE_AAD = "distributeddata"; + using system_clock = std::chrono::system_clock; CryptoManager::CryptoManager() @@ -33,7 +39,9 @@ CryptoManager::CryptoManager() vecAad_ = std::vector(HKS_BLOB_TYPE_AAD, HKS_BLOB_TYPE_AAD + strlen(HKS_BLOB_TYPE_AAD)); } -CryptoManager::~CryptoManager() {} +CryptoManager::~CryptoManager() +{ +} CryptoManager &CryptoManager::GetInstance() { @@ -49,19 +57,32 @@ struct HksParam aes256Param[] = { { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, }; -bool AddHksParams(HksParamSet *params, const CryptoManager::ParamConfig ¶mConfig, - const std::vector &vecAad) +bool AddHksParams(HksParamSet *params, CryptoManager::ParamConfig ¶mConfig) { - struct HksBlob blobAad = { uint32_t(vecAad.size()), const_cast(vecAad.data()) }; - struct HksBlob blobNonce = { uint32_t(paramConfig.nonce.size()), const_cast(paramConfig.nonce.data()) }; + if (paramConfig.nonce.empty()) { + uint8_t nonce[NONCE_SIZE] = {0}; + struct HksBlob blobNonce = { .size = NONCE_SIZE, .data = nonce }; + auto result = HksGenerateRandom(nullptr, &blobNonce); + if (result != HKS_SUCCESS) { + ZLOGE("HksGenerateRandom failed with error %{public}d", result); + return false; + } + std::vector nonceContent(blobNonce.data, blobNonce.data + blobNonce.size); + paramConfig.nonce = nonceContent; + } + struct HksBlob blobAad = { uint32_t(paramConfig.aadValue.size()), + const_cast(paramConfig.aadValue.data()) }; std::vector hksParam; - hksParam.push_back({ .tag = HKS_TAG_PURPOSE, .uint32Param = paramConfig.purpose }); - hksParam.push_back(HksParam{ .tag = HKS_TAG_NONCE, .blob = blobNonce }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_PURPOSE, .uint32Param = paramConfig.purpose }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_NONCE, + .blob = { uint32_t(paramConfig.nonce.size()), const_cast(paramConfig.nonce.data()) } }); hksParam.push_back(HksParam{ .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }); - hksParam.push_back({ .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = paramConfig.storageLevel }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = paramConfig.storageLevel }); + if (paramConfig.storageLevel > HKS_AUTH_STORAGE_LEVEL_DE) { - hksParam.push_back(HksParam{ .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = atoi(paramConfig.userId.c_str()) }); + hksParam.emplace_back( + HksParam { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = std::atoi(paramConfig.userId.c_str()) }); } auto ret = HksAddParams(params, aes256Param, sizeof(aes256Param) / sizeof(aes256Param[0])); @@ -87,17 +108,16 @@ int32_t GetRootKeyParams(HksParamSet *¶ms, uint32_t storageLevel, const std: return ret; } - std::vector hksParam = { - { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, - { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, - { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, - { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, - { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, - { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, - { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = storageLevel }, - }; + std::vector hksParam; + hksParam.push_back(HksParam{ .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_DIGEST, .uint32Param = 0 }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = storageLevel }); if (storageLevel > HKS_AUTH_STORAGE_LEVEL_DE) { - hksParam.emplace_back(HksParam{ .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = std::stoi(userId) }); + hksParam.emplace_back(HksParam { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = std::atoi(userId.c_str()) }); } ret = HksAddParams(params, hksParam.data(), hksParam.size()); @@ -137,8 +157,8 @@ int32_t CryptoManager::GenerateRootKey(uint32_t storageLevel, const std::string ZLOGI("GenerateRootKey Succeed. storageLevel:%{public}u, userId:%{public}s", storageLevel, userId.c_str()); return ErrCode::SUCCESS; } - ZLOGE("HksGenerateKey failed with error %{public}d, storageLevel:%{public}u, userId:%{public}s", ret, storageLevel, - userId.c_str()); + ZLOGE("HksGenerateKey failed with error %{public}d, storageLevel:%{public}u, userId:%{public}s", + ret, storageLevel, userId.c_str()); return ErrCode::ERROR; } @@ -198,42 +218,30 @@ int32_t CryptoManager::PrepareRootKey(uint32_t storageLevel, const std::string & userId.c_str(), status); return status; } -std::vector CryptoManager::Encrypt(const std::vector &key, int32_t area, const std::string &userId) -{ - EncryptParams encryptParams = { .keyAlias = vecRootKeyAlias_, .nonce = vecNonce_ }; - return Encrypt(key, area, userId, encryptParams); -} - -std::vector CryptoManager::Encrypt(const std::vector &key) -{ - EncryptParams encryptParams = { .keyAlias = vecRootKeyAlias_, .nonce = vecNonce_ }; - return Encrypt(key, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER, encryptParams); -} -std::vector CryptoManager::Encrypt(const std::vector &key, const EncryptParams &encryptParams) +std::vector CryptoManager::Encrypt(const std::vector &password, CryptoParams &encryptParams) { - return Encrypt(key, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER, encryptParams); -} - -std::vector CryptoManager::Encrypt(const std::vector &key, int32_t area, const std::string &userId, - const EncryptParams &encryptParams) -{ - uint32_t storageLevel = GetStorageLevel(area); - if (PrepareRootKey(storageLevel, userId) != ErrCode::SUCCESS) { + encryptParams.area = encryptParams.area < 0 ? Area::EL1 : encryptParams.area; + uint32_t storageLevel = GetStorageLevel(encryptParams.area); + if (PrepareRootKey(storageLevel, encryptParams.userId) != ErrCode::SUCCESS) { return {}; } struct HksParamSet *params = nullptr; int32_t ret = HksInitParamSet(¶ms); if (ret != HKS_SUCCESS) { - ZLOGE("HksInitParamSet() failed with error %{public}d", ret); + ZLOGE("HksInitParamSet failed with error %{public}d", ret); return {}; } - ParamConfig paramConfig = { .nonce = encryptParams.nonce, + + ParamConfig paramConfig = { .purpose = HKS_KEY_PURPOSE_ENCRYPT, .storageLevel = storageLevel, - .userId = userId }; - if (!AddHksParams(params, paramConfig, vecAad_)) { + .userId = encryptParams.userId, + .nonce = encryptParams.nonce, + .aadValue = vecAad_ + }; + if (!AddHksParams(params, paramConfig)) { return {}; } ret = HksBuildParamSet(¶ms); @@ -243,11 +251,14 @@ std::vector CryptoManager::Encrypt(const std::vector &key, int return {}; } + if (encryptParams.keyAlias.empty()) { + encryptParams.keyAlias = vecRootKeyAlias_; + } + struct HksBlob keyName = { uint32_t(encryptParams.keyAlias.size()), + const_cast(encryptParams.keyAlias.data())}; + struct HksBlob plainKey = { uint32_t(password.size()), const_cast(password.data()) }; uint8_t cipherBuf[256] = { 0 }; struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf }; - struct HksBlob keyName = { uint32_t(encryptParams.keyAlias.size()), - const_cast(encryptParams.keyAlias.data()) }; - struct HksBlob plainKey = { uint32_t(key.size()), const_cast(key.data()) }; ret = HksEncrypt(&keyName, params, &plainKey, &cipherText); (void)HksFreeParamSet(¶ms); if (ret != HKS_SUCCESS) { @@ -255,108 +266,83 @@ std::vector CryptoManager::Encrypt(const std::vector &key, int return {}; } + if (encryptParams.nonce.empty()) { + encryptParams.nonce = paramConfig.nonce; + } std::vector encryptedKey(cipherText.data, cipherText.data + cipherText.size); - (void)memset_s(cipherBuf, sizeof(cipherBuf), 0, sizeof(cipherBuf)); + std::fill(cipherBuf, cipherBuf + sizeof(cipherBuf), 0); return encryptedKey; } -bool CryptoManager::UpdateSecretKey(const StoreMetaData &meta, const std::vector &key, - SecretKeyType secretKeyType) -{ - if (!meta.isEncrypt) { - return false; - } - SecretKeyMetaData secretKey; - EncryptParams encryptParams = { .keyAlias = vecRootKeyAlias_, .nonce = vecNonce_ }; - secretKey.storeType = meta.storeType; - secretKey.area = meta.area; - secretKey.sKey = Encrypt(key, meta.area, meta.user, encryptParams); - auto time = system_clock::to_time_t(system_clock::now()); - secretKey.time = { reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time) }; - if (secretKeyType == LOCAL_SECRET_KEY) { - return MetaDataManager::GetInstance().SaveMeta(meta.GetSecretKey(), secretKey, true); - } else { - return MetaDataManager::GetInstance().SaveMeta(meta.GetCloneSecretKey(), secretKey, true); - } -} - -bool CryptoManager::Decrypt(const StoreMetaData &meta, SecretKeyMetaData &secretKeyMeta, std::vector &key, - SecretKeyType secretKeyType) +std::vector CryptoManager::Decrypt(const std::vector &source, CryptoParams &decryptParams) { - EncryptParams encryptParams = { .keyAlias = vecRootKeyAlias_, .nonce = vecNonce_ }; - if (secretKeyMeta.area < 0) { - ZLOGI("Decrypt old secret key"); - if (Decrypt(secretKeyMeta.sKey, key, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER, encryptParams)) { - StoreMetaData metaData; - if (MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), metaData, true)) { - ZLOGI("Upgrade secret key"); - UpdateSecretKey(metaData, key, secretKeyType); - } - return true; - } - } else { - return Decrypt(secretKeyMeta.sKey, key, secretKeyMeta.area, meta.user, encryptParams); + uint32_t storageLevel = GetStorageLevel(decryptParams.area); + if (PrepareRootKey(storageLevel, decryptParams.userId) != ErrCode::SUCCESS) { + return {}; } - return false; -} - -bool CryptoManager::Decrypt(std::vector &source, std::vector &key, int32_t area, - const std::string &userId) -{ - EncryptParams encryptParams = { .keyAlias = vecRootKeyAlias_, .nonce = vecNonce_ }; - return Decrypt(source, key, area, userId, encryptParams); -} - -bool CryptoManager::Decrypt(std::vector &source, std::vector &key, const EncryptParams &encryptParams) -{ - return Decrypt(source, key, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER, encryptParams); -} -bool CryptoManager::Decrypt(std::vector &source, std::vector &key, int32_t area, - const std::string &userId, const EncryptParams &encryptParams) -{ - uint32_t storageLevel = GetStorageLevel(area); - if (PrepareRootKey(storageLevel, userId) != ErrCode::SUCCESS) { - return false; - } struct HksParamSet *params = nullptr; int32_t ret = HksInitParamSet(¶ms); if (ret != HKS_SUCCESS) { - ZLOGE("HksInitParamSet() failed with error %{public}d", ret); - return false; + ZLOGE("HksInitParamSet failed with error %{public}d", ret); + return {}; } - ParamConfig paramConfig = { .nonce = encryptParams.nonce, + ParamConfig paramConfig = { .purpose = HKS_KEY_PURPOSE_DECRYPT, .storageLevel = storageLevel, - .userId = userId }; - if (!AddHksParams(params, paramConfig, vecAad_)) { - return false; + .userId = decryptParams.userId, + .nonce = decryptParams.nonce.empty() ? vecNonce_ : decryptParams.nonce, + .aadValue = vecAad_ + }; + if (!AddHksParams(params, paramConfig)) { + return {}; } - ret = HksBuildParamSet(¶ms); if (ret != HKS_SUCCESS) { ZLOGE("HksBuildParamSet failed with error %{public}d", ret); HksFreeParamSet(¶ms); - return false; + return {}; } + if (decryptParams.keyAlias.empty()) { + decryptParams.keyAlias = vecRootKeyAlias_; + } + struct HksBlob keyName = { uint32_t(decryptParams.keyAlias.size()), + const_cast(decryptParams.keyAlias.data()) }; + struct HksBlob encryptedKeyBlob = { uint32_t(source.size()), const_cast(source.data()) }; uint8_t plainBuf[256] = { 0 }; struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf }; - struct HksBlob encryptedKeyBlob = { uint32_t(source.size()), source.data() }; - struct HksBlob keyName = { uint32_t(encryptParams.keyAlias.size()), - const_cast(encryptParams.keyAlias.data()) }; ret = HksDecrypt(&keyName, params, &encryptedKeyBlob, &plainKeyBlob); (void)HksFreeParamSet(¶ms); if (ret != HKS_SUCCESS) { ZLOGE("HksDecrypt failed with error %{public}d", ret); - return false; + return {}; } + std::vector password(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size); + return password; +} - key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size); - (void)memset_s(plainBuf, sizeof(plainBuf), 0, sizeof(plainBuf)); - return true; +void CryptoManager::UpdateSecretMeta(const std::vector &password, const StoreMetaData &metaData, + const std::string &metaKey, SecretKeyMetaData &secretKey) +{ + if (password.empty() || (!secretKey.nonce.empty() && secretKey.area >= 0)) { + return; + } + CryptoParams encryptParams = { .area = metaData.area, .userId = metaData.user, + .nonce = secretKey.nonce }; + auto encryptKey = Encrypt(password, encryptParams); + if (encryptKey.empty()) { + return; + } + secretKey.sKey = encryptKey; + secretKey.nonce = encryptParams.nonce; + secretKey.area = metaData.area; + auto time = system_clock::to_time_t(system_clock::now()); + secretKey.time = { reinterpret_cast(&time), + reinterpret_cast(&time) + sizeof(time) }; + MetaDataManager::GetInstance().SaveMeta(metaKey, secretKey, true); } bool BuildImportKeyParams(struct HksParamSet *¶ms) @@ -367,10 +353,10 @@ bool BuildImportKeyParams(struct HksParamSet *¶ms) return false; } struct HksParam purposeParam[] = { - { .tag = HKS_TAG_IS_KEY_ALIAS, .boolParam = true }, - { .tag = HKS_TAG_KEY_GENERATE_TYPE, .uint32Param = HKS_KEY_GENERATE_TYPE_DEFAULT }, - { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, - { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, + {.tag = HKS_TAG_IS_KEY_ALIAS, .boolParam = true}, + {.tag = HKS_TAG_KEY_GENERATE_TYPE, .uint32Param = HKS_KEY_GENERATE_TYPE_DEFAULT}, + {.tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT}, + {.tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE}, }; ret = HksAddParams(params, aes256Param, sizeof(aes256Param) / sizeof(aes256Param[0])); if (ret != HKS_SUCCESS) { diff --git a/datamgr_service/services/distributeddataservice/framework/device_manager/device_manager_delegate.cpp b/datamgr_service/services/distributeddataservice/framework/device_manager/device_manager_delegate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e85b94b97de9961e7431731f25a6ae2ab634cc25 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/device_manager/device_manager_delegate.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 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 "device_manager/device_manager_delegate.h" + +namespace OHOS { +namespace DistributedData { +DeviceManagerDelegate *DeviceManagerDelegate::instance_ = nullptr; + +bool DeviceManagerDelegate::RegisterInstance(DeviceManagerDelegate *instance) +{ + if (instance_ != nullptr) { + return false; + } + instance_ = instance; + return true; +} + +DeviceManagerDelegate *DeviceManagerDelegate::GetInstance() +{ + return instance_; +} +} // namespace DistributedData +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/device_sync_app/device_sync_app_manager.cpp b/datamgr_service/services/distributeddataservice/framework/device_sync_app/device_sync_app_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e20ee46ef181dd261371ee36788e70cd6f83cc79 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/device_sync_app/device_sync_app_manager.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 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 "DeviceSyncAppManager" +#include "device_sync_app/device_sync_app_manager.h" + +namespace OHOS::DistributedData { +DeviceSyncAppManager::DeviceSyncAppManager() +{ +} + +DeviceSyncAppManager &DeviceSyncAppManager::GetInstance() +{ + static DeviceSyncAppManager instance; + return instance; +} + +void DeviceSyncAppManager::Initialize(const std::vector &lists) +{ + for (const auto &list : lists) { + whiteLists_.push_back(list); + } +} + +bool DeviceSyncAppManager::Check(const WhiteList &whiteList) +{ + for (const auto &info : whiteLists_) { + if (info.appId == whiteList.appId && (info.bundleName == whiteList.bundleName) && + (info.version == whiteList.version)) { + return true; + } + } + return false; +} + +} // namespace OHOS::DistributedData \ 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 9deb434e7e53ab00574384f758f933a5a7502350..1586511ce2cf210fad1741ba01b844ef82c1dc2e 100644 --- a/datamgr_service/services/distributeddataservice/framework/directory/directory_manager.cpp +++ b/datamgr_service/services/distributeddataservice/framework/directory/directory_manager.cpp @@ -107,7 +107,7 @@ std::string DirectoryManager::GetClonePath(const std::string &userId, uint32_t v return ""; } -void DirectoryManager::Initialize(const std::vector &strategies) +void DirectoryManager::Initialize(const std::vector &strategies, const std::vector &storeTypes) { strategies_.resize(strategies.size()); for (size_t i = 0; i < strategies.size(); ++i) { @@ -127,6 +127,8 @@ void DirectoryManager::Initialize(const std::vector &strategies) std::sort(strategies_.begin(), strategies_.end(), [](const StrategyImpl &curr, const StrategyImpl &prev) { return curr.version > prev.version; }); + + storeTypes_ = storeTypes; } std::string DirectoryManager::GetType(const StoreMetaData &metaData) const @@ -140,19 +142,10 @@ 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) { - return "kvdb"; - } - // rdb use empty session - 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) { - return "kvdb"; + for (const auto &storeType : storeTypes_) { + if (metaData.storeType >= storeType.range.front() && metaData.storeType <= storeType.range.back()) { + return storeType.type; + } } return "other"; } @@ -288,6 +281,7 @@ bool DirectoryManager::CreateDirectory(const std::string &path) const if (access(subPath.c_str(), F_OK) != 0) { if (mkdir(subPath.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0) { + ZLOGE("mkdir error:%{public}d", errno); return false; } } @@ -295,44 +289,4 @@ 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) { - closedir(dir); - 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) { - closedir(dir); - return false; - } - if (S_ISDIR(buf.st_mode)) { - DeleteDirectory(dirEntry->d_name); - continue; - } - if (remove(dirEntry->d_name) == -1) { - closedir(dir); - 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/framework/feature/feature_system.cpp b/datamgr_service/services/distributeddataservice/framework/feature/feature_system.cpp index 593a7c63bc7290a49184a48cc50809ab75229553..23b77e1650b50ab55a4133d11b98d638e7a2f071 100644 --- a/datamgr_service/services/distributeddataservice/framework/feature/feature_system.cpp +++ b/datamgr_service/services/distributeddataservice/framework/feature/feature_system.cpp @@ -76,6 +76,10 @@ int32_t FeatureSystem::Feature::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId return E_OK; } +int32_t FeatureSystem::Feature::OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) +{ + return E_OK; +} int32_t FeatureSystem::Feature::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index) { return E_OK; diff --git a/datamgr_service/services/distributeddataservice/framework/include/access_check/app_access_check_config_manager.h b/datamgr_service/services/distributeddataservice/framework/include/access_check/app_access_check_config_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..fecf73150eccf327675e4296af8b63d101a88878 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/access_check/app_access_check_config_manager.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 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_ACCESS_CHECK_CONFIG_MANAGER_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_APP_ACCESS_CHECK_CONFIG_MANAGER_H +#include +#include +#include +#include "visibility.h" +namespace OHOS { +namespace DistributedData { +class AppAccessCheckConfigManager { +public: + struct AppMappingInfo { + std::string appId; + std::string bundleName; + }; + API_EXPORT static AppAccessCheckConfigManager &GetInstance(); + API_EXPORT void Initialize(const std::vector &mapper); + API_EXPORT bool IsTrust(const std::string &appId); + +private: + std::map appMapper_; +}; + +} // namespace DistributedData +} // namespace OHOS +#endif //OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_APP_ACCESS_CHECK_CONFIG_MANAGER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/account/account_delegate.h b/datamgr_service/services/distributeddataservice/framework/include/account/account_delegate.h index 5636131fd819aaa82c778bf6c338bd26d690f8f2..c2ed384fe520a662b813a7ced2c5e9a139986caf 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/account/account_delegate.h +++ b/datamgr_service/services/distributeddataservice/framework/include/account/account_delegate.h @@ -67,8 +67,8 @@ public: API_EXPORT virtual void UnsubscribeAccountEvent() = 0; API_EXPORT virtual bool QueryUsers(std::vector &users) = 0; API_EXPORT virtual bool QueryForegroundUsers(std::vector &users) = 0; - API_EXPORT virtual bool IsLoginAccount() = 0; API_EXPORT virtual bool QueryForegroundUserId(int &foregroundUserId) = 0; + API_EXPORT virtual bool IsLoginAccount() = 0; API_EXPORT virtual bool IsVerified(int userId) = 0; API_EXPORT virtual bool RegisterHashFunc(HashFunc hash) = 0; API_EXPORT virtual bool IsDeactivating(int userId) = 0; 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 index 9799f9af673fa969a71d9d01cf57b249b6b09592..2133bcb0d4361929e587f715f5e9c2a240c911ff 100644 --- 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 @@ -30,7 +30,7 @@ public: API_EXPORT void Initialize(const std::vector &mapper); API_EXPORT std::pair Convert(const std::string &appId, const std::string &accountId); - + API_EXPORT std::string Convert(const std::string &appId); private: std::map toDstMapper_; }; 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 bf58f4328937a5fa76140409c8baf4be77ed95fe..aa6ca90dcb8f62a48310b321053719c4d0356c0b 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,8 +33,8 @@ public: std::string storeId; std::string deviceId; std::string bundleName; - int changeType = 0; // 0 means CLOUD_DATA_CHANGE std::vector tables; + int changeType = 0; // 0 means CLOUD_DATA_CHANGE }; RemoteChangeEvent(int32_t evtId, DataInfo&& info); diff --git a/datamgr_service/services/distributeddataservice/framework/include/checker/checker_manager.h b/datamgr_service/services/distributeddataservice/framework/include/checker/checker_manager.h index f532799490683bc98a9ee2bbea1bf09eaf36f519..f42f43c616b4a4f1b5626e6a8aa79f0ccf038270 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/checker/checker_manager.h +++ b/datamgr_service/services/distributeddataservice/framework/include/checker/checker_manager.h @@ -53,6 +53,8 @@ public: virtual std::vector GetStaticStores() = 0; virtual bool IsDynamic(const StoreInfo &info) = 0; virtual bool IsStatic(const StoreInfo &info) = 0; + virtual void DeleteCache(const std::string &bundleName, int32_t user, int32_t index){}; + virtual void ClearCache(){}; protected: API_EXPORT ~Checker() = default; }; @@ -68,6 +70,9 @@ public: API_EXPORT bool IsSwitches(const StoreInfo &info); API_EXPORT void LoadCheckers(std::vector &checkers); API_EXPORT Checker *GetChecker(const std::string &checker); + API_EXPORT void DeleteCache(const std::string &bundleName, int32_t user, int32_t index); + API_EXPORT void ClearCache(); + private: std::map checkers_; ConcurrentMap> getters_; 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 fcf7cfca5ca9daad3767417064e393b02a466ef2..58933563237ba73b5b47333cf274534de12f1819 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h @@ -40,9 +40,9 @@ public: virtual int32_t BatchDelete(const std::string &table, VBuckets &extends); - virtual std::shared_ptr Query(const std::string &table, const VBucket &extend); + virtual std::pair> Query(const std::string &table, const VBucket &extend); - virtual std::shared_ptr Query(GenQuery &query, const VBucket &extend); + virtual std::pair> Query(GenQuery &query, const VBucket &extend); virtual int32_t PreSharing(const std::string &table, VBuckets &extend); diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h index 9cb060c81f0b941b0356242c364dcf0d477df30a..0d87d02612e131aa0fba104d16696be18b85ca5d 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h @@ -43,6 +43,7 @@ public: virtual void ReleaseUserInfo(int32_t userId); virtual void Bind(std::shared_ptr executor); virtual bool IsSupportCloud(int32_t userId); + virtual bool CloudDriverUpdated(const std::string &bundleName); private: static CloudServer *instance_; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h index bc74d210b11676ad6a4835461066605d599ca8d8..889392199550eb6d11c11bbfba87f1beb4afdb3d 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h @@ -73,7 +73,8 @@ public: static constexpr const char *SHARING_RESOURCE = "#_sharing_resource"; static constexpr const char *HASH_KEY = "#_hash_key"; - static constexpr uint32_t CURRENT_VERSION = 0x10000; + static constexpr uint32_t CURRENT_VERSION = 0x10001; + static constexpr uint32_t CLEAN_WATER_VERSION = 0x10001; static inline uint32_t GetLowVersion(uint32_t metaVersion = CURRENT_VERSION) { return metaVersion & 0xFFFF; @@ -87,6 +88,7 @@ public: int32_t version = 0; std::string bundleName; std::vector databases; + bool e2eeEnable = false; bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; @@ -104,4 +106,4 @@ enum AutoSyncType { }; } // namespace OHOS::DistributedData -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SCHEMA_META_H +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SCHEMA_META_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 index 5e9093c75964e43dbd631edb5bbe67062129005e..eb0e07c167d1bbd9d6916250a31f840afdd1b963 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/communication/connect_manager.h +++ b/datamgr_service/services/distributeddataservice/framework/include/communication/connect_manager.h @@ -27,6 +27,7 @@ namespace OHOS { namespace AppDistributedKv { class API_EXPORT ConnectManager { public: + using ApplyTask = std::function; using ConnectTask = std::function; using CloseSessionTask = std::function; using SessionCloseListener = std::function; @@ -51,7 +52,7 @@ public: virtual void OnStart(); virtual void OnDestory(); - virtual int32_t ApplyConnect(const std::string &networkId, ConnectTask task); + virtual int32_t ApplyConnect(const std::string &networkId, ApplyTask applyTask, ConnectTask connectTask); private: static std::mutex mtx_; diff --git a/datamgr_service/services/distributeddataservice/service/crypto/include/crypto_manager.h b/datamgr_service/services/distributeddataservice/framework/include/crypto/crypto_manager.h similarity index 53% rename from datamgr_service/services/distributeddataservice/service/crypto/include/crypto_manager.h rename to datamgr_service/services/distributeddataservice/framework/include/crypto/crypto_manager.h index dca7f96da459f035d0973e3d25df3b205ba60a10..ec2b8c2a31973551139eb81ae4fa2448bb7e8065 100644 --- a/datamgr_service/services/distributeddataservice/service/crypto/include/crypto_manager.h +++ b/datamgr_service/services/distributeddataservice/framework/include/crypto/crypto_manager.h @@ -23,80 +23,71 @@ #include "visibility.h" namespace OHOS::DistributedData { -static constexpr int32_t DEFAULT_ENCRYPTION_LEVEL = 1; -static constexpr const char *DEFAULT_USER = "0"; class API_EXPORT CryptoManager { public: + static constexpr const char *DEFAULT_USER = "0"; + enum SecretKeyType { LOCAL_SECRET_KEY, CLONE_SECRET_KEY, }; - struct ParamConfig { - std::vector nonce; - uint32_t purpose; - uint32_t storageLevel; - std::string userId; - }; - struct EncryptParams { - std::vector keyAlias; - std::vector nonce; - }; + enum Area : int32_t { EL0, EL1, EL2, EL3, EL4, - EL5 + EL5, }; - static CryptoManager &GetInstance(); - int32_t GenerateRootKey(); - int32_t CheckRootKey(); - std::vector Encrypt(const std::vector &key); - std::vector Encrypt(const std::vector &key, const EncryptParams &encryptParams); - std::vector Encrypt(const std::vector &key, int32_t area, const std::string &userId); - std::vector Encrypt(const std::vector &key, - int32_t area, const std::string &userId, const EncryptParams &encryptParams - ); - bool Decrypt(std::vector &source, std::vector &key, const EncryptParams &encryptParams); - bool Decrypt(std::vector &source, std::vector &key, int32_t area, const std::string &userId); - bool Decrypt(std::vector &source, std::vector &key, - int32_t area, const std::string &userId, const EncryptParams &encryptParams - ); - bool ImportKey(const std::vector &key, const std::vector &keyAlias); - bool DeleteKey(const std::vector &keyAlias); - bool UpdateSecretKey(const StoreMetaData &meta, const std::vector &password, - SecretKeyType secretKeyType = LOCAL_SECRET_KEY); - bool Decrypt(const StoreMetaData &meta, SecretKeyMetaData &secretKeyMeta, std::vector &key, - SecretKeyType secretKeyType = LOCAL_SECRET_KEY); enum ErrCode : int32_t { SUCCESS, NOT_EXIST, ERROR, }; + + struct CryptoParams { + int32_t area = Area::EL1; + std::string userId = DEFAULT_USER; + std::vector keyAlias; + std::vector nonce; + }; + + struct ParamConfig { + uint32_t purpose; + uint32_t storageLevel; + std::string userId; + std::vector nonce; + std::vector aadValue; + }; + + static CryptoManager &GetInstance(); + + int32_t GenerateRootKey(); + int32_t CheckRootKey(); + + std::vector Encrypt(const std::vector &password, CryptoParams &encryptParams); + std::vector Decrypt(const std::vector &source, CryptoParams &decryptParams); + void UpdateSecretMeta(const std::vector &password, const StoreMetaData &metaData, + const std::string &metaKey, SecretKeyMetaData &secretKey); + + bool ImportKey(const std::vector &key, const std::vector &keyAlias); + bool DeleteKey(const std::vector &keyAlias); + private: - static constexpr const char *ROOT_KEY_ALIAS = "distributed_db_root_key"; - static constexpr const char *HKS_BLOB_TYPE_NONCE = "Z5s0Bo571KoqwIi6"; - static constexpr const char *HKS_BLOB_TYPE_AAD = "distributeddata"; - static constexpr int KEY_SIZE = 32; - static constexpr int AES_256_NONCE_SIZE = 32; - static constexpr int HOURS_PER_YEAR = (24 * 365); + CryptoManager(); + ~CryptoManager(); + uint32_t GetStorageLevel(int32_t area); int32_t GenerateRootKey(uint32_t storageLevel, const std::string &userId); int32_t CheckRootKey(uint32_t storageLevel, const std::string &userId); - uint32_t GetStorageLevel(int32_t area); int32_t PrepareRootKey(uint32_t storageLevel, const std::string &userId); - std::vector EncryptInner(const std::vector &key, const SecretKeyType type, int32_t area, - const std::string &userId); - bool DecryptInner(std::vector &source, std::vector &key, int32_t area, - const std::string &userId, std::vector &keyAlias, std::vector &nonce); - CryptoManager(); + + std::mutex mutex_; std::vector vecRootKeyAlias_{}; std::vector vecNonce_{}; std::vector vecAad_{}; - ~CryptoManager(); - std::mutex mutex_; }; } // namespace OHOS::DistributedData -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_SERVICE_CRYPTO_CRYPTO_MANAGER_H +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_SERVICE_CRYPTO_CRYPTO_MANAGER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/device_manager/device_manager_delegate.h b/datamgr_service/services/distributeddataservice/framework/include/device_manager/device_manager_delegate.h new file mode 100644 index 0000000000000000000000000000000000000000..0e7d5782993a1c720d6a30239d1f7ddd58d58338 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/device_manager/device_manager_delegate.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 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_DEVICE_MANAGER_DELEGATE_H +#define DISTRIBUTEDDATAMGR_DEVICE_MANAGER_DELEGATE_H + +#include "device_manager_types.h" +#include "visibility.h" + +namespace OHOS { +namespace DistributedData { +class DeviceManagerDelegate { +public: + virtual ~DeviceManagerDelegate() = default; + virtual DeviceInfo GetLocalDevice() = 0; + API_EXPORT static bool RegisterInstance(DeviceManagerDelegate *instance); + API_EXPORT static DeviceManagerDelegate *GetInstance(); +private: + static DeviceManagerDelegate *instance_; +}; +} // namespace DistributedData +} // namespace OHOS +#endif // DISTRIBUTEDDATAMGR_DEVICE_MANAGER_DELEGATE_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/device_manager/device_manager_types.h b/datamgr_service/services/distributeddataservice/framework/include/device_manager/device_manager_types.h new file mode 100644 index 0000000000000000000000000000000000000000..315e76c172891ea9d2ef0ad371eeb5776fd38816 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/device_manager/device_manager_types.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 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_FRAMEWORK_DEVICE_MANAGER_TYPES_H +#define OHOS_DISTRIBUTED_DATA_FRAMEWORK_DEVICE_MANAGER_TYPES_H +#include +#include "visibility.h" +namespace OHOS::DistributedData { +struct API_EXPORT DeviceInfo { + std::string uuid; + std::string udid; + std::string networkId; + std::string deviceName; + uint32_t deviceType; + int32_t osType; + int32_t authForm; +}; +} +#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORK_DEVICE_MANAGER_TYPES_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/device_sync_app/device_sync_app_manager.h b/datamgr_service/services/distributeddataservice/framework/include/device_sync_app/device_sync_app_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..664883bce41c938e7644226cef7392cd7daf0a88 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/device_sync_app/device_sync_app_manager.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 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_DEVICE_SYNC_APP_MANAGER_H +#define DISTRIBUTEDDATAMGR_DEVICE_SYNC_APP_MANAGER_H + +#include +#include +#include "visibility.h" +namespace OHOS::DistributedData { +class DeviceSyncAppManager { +public: + struct WhiteList { + std::string appId; + std::string bundleName; + uint32_t version; + }; + API_EXPORT static DeviceSyncAppManager &GetInstance(); + API_EXPORT void Initialize(const std::vector &lists); + API_EXPORT bool Check(const WhiteList &whiteList); + +private: + DeviceSyncAppManager(); + std::vector whiteLists_; +}; +} // namespace OHOS::DistributedData +#endif // DISTRIBUTEDDATAMGR_DEVICE_SYNC_APP_MANAGER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/dfx/dfx_types.h b/datamgr_service/services/distributeddataservice/framework/include/dfx/dfx_types.h index bb1a0e91d8307aca630b684b3b4ab65c9f0d6955..a83fd25292be9d924a942eaec6c381a5a6058594 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/dfx/dfx_types.h +++ b/datamgr_service/services/distributeddataservice/framework/include/dfx/dfx_types.h @@ -88,6 +88,7 @@ enum class Fault { CSF_DOWNLOAD_ASSETS = 82, CSF_GS_CREATE_DISTRIBUTED_TABLE = 83, CSF_GS_CLOUD_SYNC = 84, + CSF_GS_CLOUD_CLEAN = 85, }; enum class FaultType { 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 0570bcd62c1c4d14cbe7ea3fda36474ca3ed3b48..c7cc4253aa4a00568bc842f13ee55503a6e647c8 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/directory/directory_manager.h +++ b/datamgr_service/services/distributeddataservice/framework/include/directory/directory_manager.h @@ -32,6 +32,10 @@ public: std::string metaPath; std::string clonePath; }; + struct StoreType { + std::vector range; + std::string type; + }; API_EXPORT static DirectoryManager &GetInstance(); API_EXPORT std::string GetStorePath(const StoreMetaData &metaData, uint32_t version = INVALID_VERSION); API_EXPORT std::string GetSecretKeyPath(const StoreMetaData &metaData, uint32_t version = INVALID_VERSION); @@ -40,9 +44,8 @@ public: API_EXPORT std::string GetMetaStorePath(uint32_t version = INVALID_VERSION); API_EXPORT std::string GetMetaBackupPath(uint32_t version = INVALID_VERSION); API_EXPORT std::vector GetVersions(); - API_EXPORT void Initialize(const std::vector &strategies); + API_EXPORT void Initialize(const std::vector &strategies, const std::vector &storeTypes); 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; @@ -69,6 +72,7 @@ private: std::string GenPath(const StoreMetaData &metaData, uint32_t version, const std::string &exPath = "") const; const std::map actions_; std::vector strategies_; + std::vector storeTypes_; }; } // namespace OHOS::DistributedData #endif // DISTRIBUTEDDATAMGR_DIRECTORY_MANAGER_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/feature/feature_system.h b/datamgr_service/services/distributeddataservice/framework/include/feature/feature_system.h index 8f0d14241b55d5fdf58e29c7202379b86cdae65e..1fceb814515b6b6295668e911e387f7ae10bb2da 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/feature/feature_system.h +++ b/datamgr_service/services/distributeddataservice/framework/include/feature/feature_system.h @@ -47,6 +47,7 @@ public: virtual int32_t OnInitialize(); virtual int32_t OnBind(const BindInfo &bindInfo); virtual int32_t OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName); + virtual int32_t OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName); virtual int32_t OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index); virtual int32_t OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index); virtual int32_t OnAppInstall(const std::string &bundleName, int32_t user, int32_t index); diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/capability_meta_data.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/capability_meta_data.h index 702a362a110eca69b46c64fe9806de63836425a6..1c49339e1e239c9e451448fbabace292e2a59706 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/capability_meta_data.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/capability_meta_data.h @@ -20,9 +20,14 @@ namespace OHOS::DistributedData { class API_EXPORT CapMetaData final : public Serializable { public: - static constexpr int32_t CURRENT_VERSION = 1; + // 1->2 add accountId to session + // 2->3 udmf and object add to session + static constexpr int32_t CURRENT_VERSION = 3; static constexpr int32_t INVALID_VERSION = -1; + static constexpr int32_t ACCOUNT_VERSION = 2; + static constexpr int32_t UDMF_AND_OBJECT_VERSION = 3; int32_t version = INVALID_VERSION; + std::string deviceId = ""; API_EXPORT bool Marshal(json &node) const override; API_EXPORT bool Unmarshal(const json &node) override; @@ -32,6 +37,7 @@ class CapMetaRow { public: static constexpr const char *KEY_PREFIX = "CapabilityMeta"; API_EXPORT static std::vector GetKeyFor(const std::string &key); + API_EXPORT static const std::string GetDeviceId(const std::string &key); }; } // namespace OHOS::DistributedData #endif // DISTRIBUTEDDATAMGR_CAPABILITY_META_DATA_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/device_meta_data.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/device_meta_data.h index 7df8c5564c90f2f750cf90cdd569522bf1dc1d7a..a5dd8e61e17ac17a269284deaee8de4e685a29d0 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/device_meta_data.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/device_meta_data.h @@ -28,7 +28,6 @@ public: API_EXPORT std::string GetKey() const; std::string newUuid = ""; - std::string oldUuid = ""; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_METADATA_DEVICE_META_DATA_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/meta_data_manager.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/meta_data_manager.h index 08a2465c419156006a7e546a4fdc5f9e4e4b37af..dee2bf9fb44df799c95301024233d30553d0814b 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/meta_data_manager.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/meta_data_manager.h @@ -21,6 +21,7 @@ #include "concurrent_map.h" #include "serializable/serializable.h" +#include "lru_bucket.h" namespace DistributedDB { class KvStoreNbDelegate; } @@ -51,11 +52,16 @@ public: using Backup = std::function &)>; using Bytes = std::vector; using OnComplete = std::function &)>; + struct Entry { + std::string key; + std::string value; + }; API_EXPORT static MetaDataManager &GetInstance(); API_EXPORT void Initialize(std::shared_ptr metaStore, const Backup &backup, const std::string &storeId); API_EXPORT void SetSyncer(const Syncer &syncer); API_EXPORT void SetCloudSyncer(const CloudSyncer &cloudSyncer); API_EXPORT bool SaveMeta(const std::string &key, const Serializable &value, bool isLocal = false); + API_EXPORT bool SaveMeta(const std::vector &values, bool isLocal = false); API_EXPORT bool LoadMeta(const std::string &key, Serializable &value, bool isLocal = false); template API_EXPORT bool LoadMeta(const std::string &prefix, std::vector &values, bool isLocal = false) @@ -75,16 +81,48 @@ public: } API_EXPORT bool DelMeta(const std::string &key, bool isLocal = false); + API_EXPORT bool DelMeta(const std::vector &keys, bool isLocal = false); API_EXPORT bool Subscribe(std::shared_ptr filter, Observer observer); API_EXPORT bool Subscribe(std::string prefix, Observer observer, bool isLocal = false); API_EXPORT bool Unsubscribe(std::string filter); - API_EXPORT bool Sync(const std::vector &devices, OnComplete complete, bool wait = false); + API_EXPORT bool Sync(const std::vector &devices, OnComplete complete, bool wait = false, + bool isRetry = true); private: MetaDataManager(); ~MetaDataManager(); API_EXPORT bool GetEntries(const std::string &prefix, std::vector &entries, bool isLocal); + + void DelCacheMeta(const std::string &key, bool isLocal) + { + if (!isLocal) { + return; + } + localdata_.Delete(key); + } + + bool LoadCacheMeta(const std::string &key, Serializable &value, bool isLocal) + { + if (!isLocal) { + return false; + } + std::string data; + if (!localdata_.Get(key, data)) { + return false; + } + Serializable::Unmarshall(data, value); + return true; + } + + void SaveCacheMeta(const std::string &key, const std::string &data, bool isLocal) + { + if (!isLocal) { + return; + } + localdata_.Set(key, data); + } + void StopSA(); bool inited_ = false; @@ -95,6 +133,7 @@ private: Syncer syncer_; CloudSyncer cloudSyncer_; std::string storeId_; + LRUBucket localdata_ {64}; }; } // namespace OHOS::DistributedData -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_METADATA_META_DATA_MANAGER_H \ No newline at end of file +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_METADATA_META_DATA_MANAGER_H diff --git a/relational_store/test/native/gdb/unittest/gdb_store_config_test.cpp b/datamgr_service/services/distributeddataservice/framework/include/metadata/object_user_meta_data.h similarity index 49% rename from relational_store/test/native/gdb/unittest/gdb_store_config_test.cpp rename to datamgr_service/services/distributeddataservice/framework/include/metadata/object_user_meta_data.h index 306ddf92c2c925d6b117f3bc2cc7cbd5bfff6cd2..cd2dd38e44135a2569b93ff5821c623d3c014e77 100644 --- a/relational_store/test/native/gdb/unittest/gdb_store_config_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/object_user_meta_data.h @@ -13,29 +13,23 @@ * limitations under the License. */ -#include "gdb_store_config.h" -#include +#ifndef DISTRIBUTEDDATAMGR_OBJECT_USER_META_DATA_H +#define DISTRIBUTEDDATAMGR_OBJECT_USER_META_DATA_H -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; -class GdbStoreConfigTest : public testing::Test { +#include "serializable/serializable.h" +namespace OHOS::DistributedData { +class API_EXPORT ObjectUserMetaData final : public Serializable { public: - static void SetUpTestCase() {} - static void TearDownTestCase() {} - void SetUp() {} - void TearDown() {} -}; + std::string userId; -/** - * @tc.name: GdbStoreConfig_Test_SetWriteTime - * @tc.desc: test SetWriteTime - * @tc.type: FUNC - */ -HWTEST_F(GdbStoreConfigTest, GdbStoreConfig_Test_SetWriteTime, TestSize.Level1) -{ - StoreConfig storeCfg; - const int timeout = 10; - storeCfg.SetWriteTime(timeout); - int getTime = storeCfg.GetWriteTime(); - EXPECT_EQ(getTime, timeout); -} \ No newline at end of file + API_EXPORT bool Marshal(json &node) const override; + API_EXPORT bool Unmarshal(const json &node) override; + API_EXPORT ObjectUserMetaData(); + + API_EXPORT static std::string GetKey(); + +private: + static constexpr const char *KEY_PREFIX = "ObjectUserMetaData"; +}; +} // namespace OHOS::DistributedData +#endif // DISTRIBUTEDDATAMGR_OBJECT_USER_META_DATA_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/secret_key_meta_data.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/secret_key_meta_data.h index ed7537cd8df3df8de515064541612eaf1a806452..cb546472bfc129b8d9db2b7b895c4fc64475e88b 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/secret_key_meta_data.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/secret_key_meta_data.h @@ -21,8 +21,10 @@ namespace DistributedData { struct API_EXPORT SecretKeyMetaData final : public Serializable { std::vector time {}; std::vector sKey {}; + std::vector nonce {}; int32_t storeType = 0; int32_t area = -1; + API_EXPORT SecretKeyMetaData(); API_EXPORT ~SecretKeyMetaData(); API_EXPORT bool Marshal(json &node) const override; 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 2d17763414843203eae334f12a38925ddfec2c59..201fccc012261462b78233df92c347abfb934425 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 @@ -21,7 +21,7 @@ #include "store/store_info.h" namespace OHOS::DistributedData { -struct API_EXPORT StoreMetaData final : public Serializable { +struct API_EXPORT StoreMetaData : public Serializable { // record meta version for compatible, should update when modify store meta data structure. static constexpr uint32_t CURRENT_VERSION = 0x03000006; // UID -> uid, deviceAccountId -> userId, userId -> user @@ -69,30 +69,60 @@ struct API_EXPORT StoreMetaData final : public Serializable { STORE_RELATIONAL_END = 19, STORE_OBJECT_BEGIN = 20, STORE_OBJECT_END = 29, + STORE_GDB_BEGIN = 30, + STORE_GDB_END = 39, STORE_BUTT = 255 }; API_EXPORT StoreMetaData(); API_EXPORT StoreMetaData(const std::string &userId, const std::string &appId, const std::string &storeId); API_EXPORT explicit StoreMetaData(const StoreInfo &storeInfo); - API_EXPORT ~StoreMetaData(); + API_EXPORT virtual ~StoreMetaData(); API_EXPORT bool operator==(const StoreMetaData &metaData) const; API_EXPORT bool operator!=(const StoreMetaData &metaData) const; API_EXPORT bool Marshal(json &node) const override; API_EXPORT bool Unmarshal(const json &node) override; - API_EXPORT std::string GetKey() const; - API_EXPORT std::string GetKeyLocal() const; - API_EXPORT std::string GetSecretKey() const; - API_EXPORT std::string GetStrategyKey() const; - API_EXPORT std::string GetBackupSecretKey() const; - API_EXPORT std::string GetAutoLaunchKey() const; - API_EXPORT std::string GetDebugInfoKey() const; - API_EXPORT std::string GetDfxInfoKey() const; - API_EXPORT std::string GetStoreAlias() const; - API_EXPORT StoreInfo GetStoreInfo() const; + API_EXPORT virtual std::string GetKeyWithoutPath() const; + API_EXPORT virtual std::string GetKey() const; + API_EXPORT virtual std::string GetKeyLocalWithoutPath() const; + API_EXPORT virtual std::string GetKeyLocal() const; + API_EXPORT virtual std::string GetSecretKeyWithoutPath() const; + API_EXPORT virtual std::string GetSecretKey() const; + API_EXPORT virtual std::string GetStrategyKey() const; + API_EXPORT virtual std::string GetBackupSecretKey() const; + API_EXPORT virtual std::string GetAutoLaunchKey() const; + API_EXPORT virtual std::string GetDebugInfoKey() const; + API_EXPORT virtual std::string GetDebugInfoKeyWithoutPath() const; + API_EXPORT virtual std::string GetDfxInfoKey() const; + API_EXPORT virtual std::string GetDfxInfoKeyWithoutPath() const; + API_EXPORT virtual std::string GetStoreAlias() const; + API_EXPORT virtual StoreInfo GetStoreInfo() const; + API_EXPORT virtual std::string GetCloneSecretKey() const; API_EXPORT static std::string GetKey(const std::initializer_list &fields); API_EXPORT static std::string GetPrefix(const std::initializer_list &fields); - API_EXPORT std::string GetCloneSecretKey() const; +}; + +struct API_EXPORT StoreMetaMapping final : public StoreMetaData { + static constexpr const char *KEY_PREFIX = "StoreMetaMapping"; + std::string cloudPath; + std::string devicePath; + std::string searchPath; + + API_EXPORT StoreMetaMapping(); + API_EXPORT StoreMetaMapping(const StoreMetaData &storeMeta); + API_EXPORT explicit StoreMetaMapping(const StoreInfo &storeInfo); + API_EXPORT ~StoreMetaMapping(); + API_EXPORT bool Marshal(json &node) const override; + API_EXPORT bool Unmarshal(const json &node) override; + API_EXPORT std::string GetKey() const override; + API_EXPORT std::string GetCloudStoreMetaKey() const; + API_EXPORT std::string GetDeviceStoreMetaKey() const; + API_EXPORT static std::string GetPrefix(const std::initializer_list &fields); + API_EXPORT StoreMetaMapping& operator=(const StoreMetaData &meta); + +private: + static std::string GetKey(const std::initializer_list &fields); + std::string GetStoreMetaKeyWithPath(const std::string &path) const; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_METADATA_STORE_META_DATA_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/version_meta_data.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/version_meta_data.h index 75b64a1dd29c5e032934c8251a7cb7a9a436e4ae..3da3d359bb9a139ef8f0e206d2ce70c4632eb51a 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/version_meta_data.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/version_meta_data.h @@ -20,7 +20,9 @@ namespace OHOS::DistributedData { class API_EXPORT VersionMetaData final : public Serializable { public: - static constexpr int32_t CURRENT_VERSION = 4; + static constexpr int32_t CURRENT_VERSION = 5; + static constexpr int32_t UPDATE_STORE_META_KEY_VERSION = 5; + static constexpr int32_t UPDATE_SYNC_META_VERSION = 4; static constexpr int32_t INVALID_VERSION = -1; int32_t version = INVALID_VERSION; diff --git a/datamgr_service/services/distributeddataservice/framework/include/network/network_delegate.h b/datamgr_service/services/distributeddataservice/framework/include/network/network_delegate.h index ae7e9f94aba2dcff0a84aa721585ddb65e6ce35e..38763f58d68e1cff6b7d90c66b64709af52481b0 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/network/network_delegate.h +++ b/datamgr_service/services/distributeddataservice/framework/include/network/network_delegate.h @@ -19,7 +19,8 @@ #include #include -#include "types.h" +#include "executor_pool.h" +#include "visibility.h" namespace OHOS { namespace DistributedData { @@ -37,6 +38,7 @@ public: API_EXPORT static bool RegisterNetworkInstance(NetworkDelegate *instance); virtual bool IsNetworkAvailable() = 0; virtual void RegOnNetworkChange() = 0; + virtual void BindExecutor(std::shared_ptr executors) = 0; virtual NetworkType GetNetworkType(bool retrieve = false) = 0; private: diff --git a/datamgr_service/services/distributeddataservice/framework/include/serializable/serializable.h b/datamgr_service/services/distributeddataservice/framework/include/serializable/serializable.h index a0b6ad5a7c69514d7f2c405db3de745f5eaa0d76..93f88754476b9f4d8af1fa90ccd2083614477428 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/serializable/serializable.h +++ b/datamgr_service/services/distributeddataservice/framework/include/serializable/serializable.h @@ -62,6 +62,7 @@ public: API_EXPORT static bool GetValue(const json &node, const std::string &name, bool &value); API_EXPORT static bool GetValue(const json &node, const std::string &name, std::vector &value); API_EXPORT static bool GetValue(const json &node, const std::string &name, Serializable &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, double &value); API_EXPORT static bool SetValue(json &node, const std::string &value); API_EXPORT static bool SetValue(json &node, const uint32_t &value); API_EXPORT static bool SetValue(json &node, const int32_t &value); diff --git a/datamgr_service/services/distributeddataservice/framework/include/snapshot/snapshot.h b/datamgr_service/services/distributeddataservice/framework/include/snapshot/snapshot.h index 8a9fa7eef25338ffde134d0fa883dc2ffe32d085..8c1e46d5ed50e562157e0f894259365a24a283a1 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/snapshot/snapshot.h +++ b/datamgr_service/services/distributeddataservice/framework/include/snapshot/snapshot.h @@ -45,10 +45,6 @@ public: virtual bool IsBoundAsset(const Asset& asset) = 0; }; - -struct BindAssets { - std::shared_ptr>> bindAssets; -}; } // namespace DistributedData } // namespace OHOS #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_SNAPSHOT_SNAPSHOT_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 1549d0f1ffad71187ab332752b26d7380926b7a6..be03ada1becdf6aeb32e0414f58fd50d2b491482 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h @@ -52,24 +52,24 @@ public: API_EXPORT std::pair GetDBStore(const StoreMetaData &meta, const Watchers &watchers); - API_EXPORT Stores GetStoresIfPresent(uint32_t tokenId, const std::string &storeName = "", - const std::string &userId = ""); - - API_EXPORT void CloseStore(uint32_t tokenId, const std::string &storeId = "", const std::string &userId = ""); + API_EXPORT Stores GetStoresIfPresent( + uint32_t tokenId, const std::string &path = "", const std::string &storeId = ""); + API_EXPORT void CloseStore(uint32_t tokenId, const std::string &path = "", const std::string &storeId = ""); + API_EXPORT void CloseStore(const Filter &filter); - - API_EXPORT void SetObserver(uint32_t tokenId, const std::string &storeId, const Watchers &watchers, - const std::string &userId = ""); - - API_EXPORT void Enable(uint32_t tokenId, const std::string &storeId = "", const std::string &userId = ""); - - API_EXPORT void Disable(uint32_t tokenId, const std::string &storeId, const std::string &userId = ""); + + API_EXPORT void SetObserver( + uint32_t tokenId, const Watchers &watchers, const std::string &path, const std::string &storeId = ""); + + API_EXPORT void Enable(uint32_t tokenId, const std::string &path = "", const std::string &storeId = ""); + + API_EXPORT void Disable(uint32_t tokenId, const std::string &path = "", const std::string &storeId = ""); private: AutoCache(); ~AutoCache(); - std::string GenerateKey(const std::string &userId, const std::string &storeId) const; + std::string GenerateKey(const std::string &path, const std::string &storeId) const; void GarbageCollect(bool isForce); void StartTimer(); struct Delegate : public GeneralWatcher { 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 d50b1ab8c5311d308267e83b20f40954ad4a8293..47429abdb902a3240adecd8c34ebf570aa599e71 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h @@ -46,7 +46,7 @@ public: CLOUD_BEGIN = 4, CLOUD_TIME_FIRST = CLOUD_BEGIN, CLOUD_NATIVE_FIRST, - CLOUD_ClOUD_FIRST, + CLOUD_CLOUD_FIRST, CLOUD_END, NEARBY_SUBSCRIBE_REMOTE, NEARBY_UNSUBSCRIBE_REMOTE, @@ -62,6 +62,7 @@ public: CLOUD_DATA, CLOUD_INFO, LOCAL_DATA, + CLEAN_WATER, CLEAN_MODE_BUTT }; @@ -114,6 +115,7 @@ public: int32_t maxNumber = 30; int32_t maxSize = 1024 * 512 * 3; // 1.5M int32_t maxRetryConflictTimes = 3; // default max retry 3 times when version conflict + bool isSupportEncrypt = false; }; enum class DistributedTableMode : int { 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 e1f9b3a18a43b90e8756dfb92b7794276d4e437f..88ef5065ce6973e38627387cc4d89bd0d04b9650 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h @@ -101,6 +101,7 @@ struct SyncParam { std::string prepareTraceId; int32_t user; bool asyncDownloadAsset = false; + bool isRetry = true; }; enum SyncStage : int8_t { @@ -115,6 +116,7 @@ struct ReportParam { std::string prepareTraceId; SyncStage syncStage = SyncStage::PREPARE; int32_t errCode = 0; + std::string message = ""; }; using Assets = std::vector; diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/store_info.h b/datamgr_service/services/distributeddataservice/framework/include/store/store_info.h index 8c5d02b2bd2775da2e3035c68d255aa3a0fce251..3543cca5d78fee5fe4970675bf663860781caa50 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/store_info.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/store_info.h @@ -27,6 +27,7 @@ struct StoreInfo { int32_t user = 0; std::string deviceId; uint64_t syncId = 0; + std::string path; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_STORE_INFO_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/thread/thread_manager.h b/datamgr_service/services/distributeddataservice/framework/include/thread/thread_manager.h index c213d6c9891c89ebbe42bda0dc08d0c1b60b0dc1..c435b8ddcb4957056c8b5407b78568a4b2627292 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/thread/thread_manager.h +++ b/datamgr_service/services/distributeddataservice/framework/include/thread/thread_manager.h @@ -29,7 +29,7 @@ public: private: ThreadManager(); - uint32_t minThreadNum_ = 5; // default min executor pool thread num + uint32_t minThreadNum_ = 2; // default min executor pool thread num uint32_t maxThreadNum_ = 12; // default max executor pool thread num uint32_t ipcThreadNum_ = 16; // normal ipc num }; diff --git a/datamgr_service/services/distributeddataservice/framework/include/utils/constant.h b/datamgr_service/services/distributeddataservice/framework/include/utils/constant.h index bfeaee6b31e945ef1564d6847c8c4742d08a76ae..48aaf1547b6bfe6012bbf89f830a391b1ca9599f 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/utils/constant.h +++ b/datamgr_service/services/distributeddataservice/framework/include/utils/constant.h @@ -44,6 +44,20 @@ public: API_EXPORT static std::vector Split(const std::string &str, const std::string &delim); + template + API_EXPORT static bool BatchProcess(const std::vector &value, size_t batchSize, Action action) + { + auto it = value.begin(); + while (it != value.end()) { + auto end = it + std::min(batchSize, static_cast(std::distance(it, value.end()))); + if (!action(it, end)) { + return false; + } + it = end; + } + return true; + } + 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/capability_meta_data.cpp b/datamgr_service/services/distributeddataservice/framework/metadata/capability_meta_data.cpp index ab81aaeb816f2668dda522b4aaa898d31c3ea4c9..9e2d29478b3d64a9d6c9ddbf849d7c804b9640c8 100644 --- a/datamgr_service/services/distributeddataservice/framework/metadata/capability_meta_data.cpp +++ b/datamgr_service/services/distributeddataservice/framework/metadata/capability_meta_data.cpp @@ -20,10 +20,14 @@ namespace OHOS::DistributedData { constexpr int32_t CapMetaData::CURRENT_VERSION; constexpr int32_t CapMetaData::INVALID_VERSION; constexpr const char *CapMetaRow::KEY_PREFIX; +constexpr int32_t INDEX_NUM = 2; +constexpr int32_t INDEX_PREFIX = 0; +constexpr int32_t INDEX_DEVICE = 1; bool CapMetaData::Marshal(json &node) const { bool ret = true; ret = SetValue(node[GET_NAME(version)], version) && ret; + ret = SetValue(node[GET_NAME(deviceId)], deviceId) && ret; return ret; } @@ -31,6 +35,7 @@ bool CapMetaData::Unmarshal(const json &node) { bool ret = true; ret = GetValue(node, GET_NAME(version), version) && ret; + ret = GetValue(node, GET_NAME(deviceId), deviceId) && ret; return ret; } @@ -39,4 +44,13 @@ std::vector CapMetaRow::GetKeyFor(const std::string &key) std::string str = Constant::Concatenate({ KEY_PREFIX, Constant::KEY_SEPARATOR, key }); return { str.begin(), str.end() }; } + +const std::string CapMetaRow::GetDeviceId(const std::string &key) +{ + auto items = Constant::Split(key, Constant::KEY_SEPARATOR); + if (items.size() < INDEX_NUM || items[INDEX_PREFIX] != KEY_PREFIX) { + return ""; + } + return items[INDEX_DEVICE]; +} } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/framework/metadata/device_meta_data.cpp b/datamgr_service/services/distributeddataservice/framework/metadata/device_meta_data.cpp index c16c6400f140d94755c3ad0fe9497408e94a9a08..c3aa1e3fe91e3a2a6fd31056e83cebb14b91c8d6 100644 --- a/datamgr_service/services/distributeddataservice/framework/metadata/device_meta_data.cpp +++ b/datamgr_service/services/distributeddataservice/framework/metadata/device_meta_data.cpp @@ -20,14 +20,12 @@ static constexpr const char *KEY_PREFIX = "DeviceMeta"; bool DeviceMetaData::Marshal(json &node) const { SetValue(node[GET_NAME(newUuid)], newUuid); - SetValue(node[GET_NAME(oldUuid)], oldUuid); return true; } bool DeviceMetaData::Unmarshal(const json &node) { GetValue(node, GET_NAME(newUuid), newUuid); - GetValue(node, GET_NAME(oldUuid), oldUuid); 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 e7ade4b8299d3af1cef37f9c84077930cc5c5995..a5cc012ade281ad8bb3575405c8259b43d14d675 100644 --- a/datamgr_service/services/distributeddataservice/framework/metadata/meta_data_manager.cpp +++ b/datamgr_service/services/distributeddataservice/framework/metadata/meta_data_manager.cpp @@ -213,15 +213,51 @@ bool MetaDataManager::SaveMeta(const std::string &key, const Serializable &value ZLOGE("failed! status:%{public}d isLocal:%{public}d, key:%{public}s", status, isLocal, Anonymous::Change(key).c_str()); } + DelCacheMeta(key, isLocal); return status == DistributedDB::DBStatus::OK; } -bool MetaDataManager::LoadMeta(const std::string &key, Serializable &value, bool isLocal) +bool MetaDataManager::SaveMeta(const std::vector &values, bool isLocal) { if (!inited_) { return false; } + if (values.empty()) { + return true; + } + std::vector entries; + entries.reserve(values.size()); + for (const auto &[key, value] : values) { + entries.push_back({ { key.begin(), key.end() }, { value.begin(), value.end() } }); + DelCacheMeta(key, isLocal); + } + auto status = isLocal ? metaStore_->PutLocalBatch(entries) : metaStore_->PutBatch(entries); + if (status == DistributedDB::DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB) { + ZLOGE("db corrupted! status:%{public}d isLocal:%{public}d, size:%{public}zu", status, isLocal, values.size()); + CorruptReporter::CreateCorruptedFlag(DirectoryManager::GetInstance().GetMetaStorePath(), storeId_); + StopSA(); + return false; + } + if (status == DistributedDB::DBStatus::OK && backup_) { + backup_(metaStore_); + } + if (!isLocal && cloudSyncer_) { + cloudSyncer_(); + } + if (status != DistributedDB::DBStatus::OK) { + ZLOGE("failed! status:%{public}d isLocal:%{public}d, size:%{public}zu", status, isLocal, values.size()); + } + return status == DistributedDB::DBStatus::OK; +} +bool MetaDataManager::LoadMeta(const std::string &key, Serializable &value, bool isLocal) +{ + if (!inited_) { + return false; + } + if (LoadCacheMeta(key, value, isLocal)) { + return true; + } DistributedDB::Value data; auto status = isLocal ? metaStore_->GetLocal({ key.begin(), key.end() }, data) : metaStore_->Get({ key.begin(), key.end() }, data); @@ -235,7 +271,9 @@ bool MetaDataManager::LoadMeta(const std::string &key, Serializable &value, bool if (status != DistributedDB::DBStatus::OK) { return false; } - Serializable::Unmarshall({ data.begin(), data.end() }, value); + std::string tempdata(data.begin(), data.end()); + SaveCacheMeta(key, tempdata, isLocal); + Serializable::Unmarshall(tempdata, value); if (isLocal) { data.assign(data.size(), 0); } @@ -270,8 +308,7 @@ bool MetaDataManager::DelMeta(const std::string &key, bool isLocal) if (!inited_) { return false; } - - DistributedDB::Value data; + DelCacheMeta(key, isLocal); auto status = isLocal ? metaStore_->DeleteLocal({ key.begin(), key.end() }) : metaStore_->Delete({ key.begin(), key.end() }); if (status == DistributedDB::DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB) { @@ -290,18 +327,58 @@ bool MetaDataManager::DelMeta(const std::string &key, bool isLocal) return ((status == DistributedDB::DBStatus::OK) || (status == DistributedDB::DBStatus::NOT_FOUND)); } -bool MetaDataManager::Sync(const std::vector &devices, OnComplete complete, bool wait) +bool MetaDataManager::DelMeta(const std::vector &keys, bool isLocal) +{ + if (!inited_) { + return false; + } + if (keys.empty()) { + return true; + } + std::vector dbKeys; + dbKeys.reserve(keys.size()); + for (auto &key : keys) { + dbKeys.emplace_back(key.begin(), key.end()); + DelCacheMeta(key, isLocal); + } + auto status = isLocal ? metaStore_->DeleteLocalBatch(dbKeys) : metaStore_->DeleteBatch(dbKeys); + if (status == DistributedDB::DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB) { + ZLOGE("db corrupted! status:%{public}d isLocal:%{public}d, key size:%{public}zu", status, isLocal, + dbKeys.size()); + CorruptReporter::CreateCorruptedFlag(DirectoryManager::GetInstance().GetMetaStorePath(), storeId_); + StopSA(); + return false; + } + if (status == DistributedDB::DBStatus::OK && backup_) { + backup_(metaStore_); + } + if (!isLocal && cloudSyncer_) { + cloudSyncer_(); + } + return ((status == DistributedDB::DBStatus::OK) || (status == DistributedDB::DBStatus::NOT_FOUND)); +} + +bool MetaDataManager::Sync(const std::vector &devices, OnComplete complete, bool wait, bool isRetry) { if (!inited_ || devices.empty()) { return false; } - 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)); - } - complete(results); - }, wait); + DistributedDB::DeviceSyncOption syncOption; + syncOption.devices = devices; + syncOption.mode = DistributedDB::SyncMode::SYNC_MODE_PUSH_PULL; + syncOption.isWait = wait; + syncOption.isRetry = isRetry; + auto status = metaStore_->Sync(syncOption, + [complete](const std::map &dbResults) { + if (complete == nullptr) { + return; + } + std::map results; + for (auto &[uuid, status] : dbResults) { + results.insert_or_assign(uuid, static_cast(status)); + } + complete(results); + }); if (status == DistributedDB::DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB) { ZLOGE("db corrupted! status:%{public}d", status); CorruptReporter::CreateCorruptedFlag(DirectoryManager::GetInstance().GetMetaStorePath(), storeId_); diff --git a/datamgr_service/services/distributeddataservice/framework/metadata/object_user_meta_data.cpp b/datamgr_service/services/distributeddataservice/framework/metadata/object_user_meta_data.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c5d5d9e073ae8cd22c4799b1ca85bd8eeabf340f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/metadata/object_user_meta_data.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 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 "metadata/object_user_meta_data.h" + +namespace OHOS::DistributedData { +ObjectUserMetaData::ObjectUserMetaData() +{ +} +bool ObjectUserMetaData::Marshal(json &node) const +{ + return SetValue(node[GET_NAME(userId)], userId); +} + +bool ObjectUserMetaData::Unmarshal(const json &node) +{ + return GetValue(node, GET_NAME(userId), userId); +} + +std::string ObjectUserMetaData::GetKey() +{ + return KEY_PREFIX; +} +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/metadata/secret_key_meta_data.cpp b/datamgr_service/services/distributeddataservice/framework/metadata/secret_key_meta_data.cpp index 168844c454aab870e73fb746900566cdb86dc961..3af423fb1c686d09c1adc5454ed0e84d5fb55586 100644 --- a/datamgr_service/services/distributeddataservice/framework/metadata/secret_key_meta_data.cpp +++ b/datamgr_service/services/distributeddataservice/framework/metadata/secret_key_meta_data.cpp @@ -24,12 +24,14 @@ SecretKeyMetaData::SecretKeyMetaData() SecretKeyMetaData::~SecretKeyMetaData() { sKey.assign(sKey.size(), 0); + nonce.assign(nonce.size(), 0); } bool SecretKeyMetaData::Marshal(json &node) const { SetValue(node[GET_NAME(time)], time); SetValue(node[GET_NAME(sKey)], sKey); + SetValue(node[GET_NAME(nonce)], nonce); SetValue(node[GET_NAME(storeType)], storeType); SetValue(node[GET_NAME(area)], area); return true; @@ -39,6 +41,7 @@ bool SecretKeyMetaData::Unmarshal(const json &node) { GetValue(node, GET_NAME(time), time); GetValue(node, GET_NAME(sKey), sKey); + GetValue(node, GET_NAME(nonce), nonce); GetValue(node, GET_NAME(storeType), storeType); GetValue(node, GET_NAME(area), area); return true; 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 61d6785804a0bcdcc9553cbf4f829d08fd4d5031..3dba8c533027f644a21d44a3130f00e9bc748126 100644 --- a/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data.cpp +++ b/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data.cpp @@ -22,6 +22,7 @@ #include "metadata/strategy_meta_data.h" #include "utils/anonymous.h" #include "utils/constant.h" +#include "utils/crypto.h" namespace OHOS { namespace DistributedData { constexpr uint32_t StoreMetaData::CURRENT_VERSION; @@ -127,8 +128,8 @@ StoreMetaData::StoreMetaData(const std::string &userId, const std::string &appId } StoreMetaData::StoreMetaData(const StoreInfo &storeInfo) - : instanceId(storeInfo.instanceId), bundleName(storeInfo.bundleName), storeId(storeInfo.storeName), - user(std::to_string(storeInfo.user)) + : instanceId(storeInfo.instanceId), bundleName(storeInfo.bundleName), dataDir(storeInfo.path), + storeId(storeInfo.storeName), user(std::to_string(storeInfo.user)) { } @@ -160,25 +161,26 @@ bool StoreMetaData::operator!=(const StoreMetaData &metaData) const std::string StoreMetaData::GetKey() const { if (instanceId == 0) { - return GetKey({ deviceId, user, "default", bundleName, storeId }); + return GetKey({ deviceId, user, "default", bundleName, storeId, dataDir }); } - return GetKey({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId) }); + return GetKey({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId), dataDir }); } std::string StoreMetaData::GetKeyLocal() const { if (instanceId == 0) { - return StoreMetaDataLocal::GetKey({ deviceId, user, "default", bundleName, storeId }); + return StoreMetaDataLocal::GetKey({ deviceId, user, "default", bundleName, storeId, dataDir }); } - return StoreMetaDataLocal::GetKey({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId) }); + return StoreMetaDataLocal::GetKey( + { deviceId, user, "default", bundleName, storeId, std::to_string(instanceId), dataDir }); } std::string StoreMetaData::GetSecretKey() const { if (version < UUID_CHANGED_TAG) { - return SecretKeyMetaData::GetKey({ user, "default", bundleName, storeId }); + return SecretKeyMetaData::GetKey({ user, "default", bundleName, storeId, dataDir }); } - return SecretKeyMetaData::GetKey({ user, "default", bundleName, storeId, std::to_string(instanceId) }); + return SecretKeyMetaData::GetKey({ user, "default", bundleName, storeId, std::to_string(instanceId), dataDir }); } std::string StoreMetaData::GetBackupSecretKey() const @@ -195,11 +197,23 @@ std::string StoreMetaData::GetAutoLaunchKey() const } std::string StoreMetaData::GetDebugInfoKey() const +{ + return StoreDebugInfo::GetPrefix( + { deviceId, user, "default", bundleName, storeId, std::to_string(instanceId), dataDir }); +} + +std::string StoreMetaData::GetDebugInfoKeyWithoutPath() const { return StoreDebugInfo::GetPrefix({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId) }); } std::string StoreMetaData::GetDfxInfoKey() const +{ + return StoreDfxInfo::GetPrefix( + { deviceId, user, "default", bundleName, storeId, std::to_string(instanceId), dataDir }); +} + +std::string StoreMetaData::GetDfxInfoKeyWithoutPath() const { return StoreDfxInfo::GetPrefix({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId) }); } @@ -245,5 +259,101 @@ std::string StoreMetaData::GetCloneSecretKey() const { return SecretKeyMetaData::GetCloneKey({ user, "default", bundleName, storeId, std::to_string(instanceId) }); } + +std::string StoreMetaData::GetKeyWithoutPath() const +{ + if (instanceId == 0) { + return GetKey({ deviceId, user, "default", bundleName, storeId }); + } + return GetKey({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId) }); +} + +std::string StoreMetaData::GetKeyLocalWithoutPath() const +{ + if (instanceId == 0) { + return StoreMetaDataLocal::GetKey({ deviceId, user, "default", bundleName, storeId }); + } + return StoreMetaDataLocal::GetKey({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId) }); +} + +std::string StoreMetaData::GetSecretKeyWithoutPath() const +{ + if (version < UUID_CHANGED_TAG) { + return SecretKeyMetaData::GetKey({ user, "default", bundleName, storeId }); + } + return SecretKeyMetaData::GetKey({ user, "default", bundleName, storeId, std::to_string(instanceId) }); +} + +StoreMetaMapping::StoreMetaMapping() {} +StoreMetaMapping::StoreMetaMapping(const StoreMetaData &storeMeta) : StoreMetaData(storeMeta) {} +StoreMetaMapping::~StoreMetaMapping() {} + +bool StoreMetaMapping::Marshal(json &node) const +{ + StoreMetaData::Marshal(node); + SetValue(node[GET_NAME(cloudPath)], cloudPath); + SetValue(node[GET_NAME(devicePath)], devicePath); + SetValue(node[GET_NAME(searchPath)], searchPath); + return true; +} +bool StoreMetaMapping::Unmarshal(const Serializable::json &node) +{ + StoreMetaData::Unmarshal(node); + GetValue(node, GET_NAME(cloudPath), cloudPath); + GetValue(node, GET_NAME(devicePath), devicePath); + GetValue(node, GET_NAME(searchPath), searchPath); + return true; +} + +std::string StoreMetaMapping::GetKey() const +{ + if (instanceId == 0) { + return GetKey({ deviceId, user, "default", bundleName, storeId }); + } + return GetKey({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId) }); +} + +std::string StoreMetaMapping::GetCloudStoreMetaKey() const +{ + return GetStoreMetaKeyWithPath(cloudPath); +} + +std::string StoreMetaMapping::GetDeviceStoreMetaKey() const +{ + return GetStoreMetaKeyWithPath(devicePath); +} + +std::string StoreMetaMapping::GetPrefix(const std::initializer_list &fields) +{ + return GetKey(fields).append(Constant::KEY_SEPARATOR); +} + +StoreMetaMapping& StoreMetaMapping::operator=(const StoreMetaData &meta) +{ + if (this == &meta) { + return *this; + } + this->StoreMetaData::operator=(meta); + return *this; +} + +std::string StoreMetaMapping::GetStoreMetaKeyWithPath(const std::string &path) const +{ + if (instanceId == 0) { + return StoreMetaData::GetKey({ deviceId, user, "default", bundleName, storeId, path }); + } + return StoreMetaData::GetKey({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId), path }); +} + +std::string StoreMetaMapping::GetKey(const std::initializer_list &fields) +{ + std::string prefix = KEY_PREFIX; + for (const auto &field : fields) { + prefix.append(Constant::KEY_SEPARATOR).append(field); + } + return prefix; +} +StoreMetaMapping::StoreMetaMapping(const StoreInfo &storeInfo) : StoreMetaData(storeInfo) {} + } // namespace DistributedData } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp b/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp index 253a9323403fe89dbe727a858cf54a18c7f7f6c8..9eec3a3011c7ddcf0ce2939472fdbc02d6fd5918 100644 --- a/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp +++ b/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp @@ -141,6 +141,16 @@ bool Serializable::GetValue(const json &node, const std::string &name, bool &val return false; } +bool Serializable::GetValue(const json &node, const std::string &name, double &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_number_float()) { + return false; + } + subNode.get_to(value); + return true; +} + bool Serializable::GetValue(const json &node, const std::string &name, std::vector &value) { auto &subNode = GetSubNode(node, name); @@ -230,5 +240,6 @@ const Serializable::json &Serializable::GetSubNode(const json &node, const std:: } return *it; } + } // namespace DistributedData -} // namespace OHOS +} // namespace OHOS \ 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 0b17f5bc3e0e909a66038eb0237714dc63b178a7..4253619e56be45d32ff38c87bcd8ead55530fc25 100644 --- a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp +++ b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp @@ -17,11 +17,11 @@ #include -#include "account_delegate.h" +#include "account/account_delegate.h" #include "changeevent/remote_change_event.h" #include "eventcenter/event_center.h" #include "log_print.h" -#include "screenlock/screen_lock.h" +#include "screen/screen_manager.h" #include "utils/anonymous.h" namespace OHOS::DistributedData { using Account = AccountDelegate; @@ -61,24 +61,25 @@ AutoCache::~AutoCache() } } -std::string AutoCache::GenerateKey(const std::string &userId, const std::string &storeId) const +std::string AutoCache::GenerateKey(const std::string &path, const std::string &storeId) const { std::string key = ""; - if (userId.empty() || storeId.empty()) { + if (path.empty() || storeId.empty()) { return key; } - return key.append(userId).append(KEY_SEPARATOR).append(storeId); + return key.append(path).append(KEY_SEPARATOR).append(storeId); } std::pair AutoCache::GetDBStore(const StoreMetaData &meta, const Watchers &watchers) { Store store; - auto storeKey = GenerateKey(meta.user, meta.storeId); + auto storeKey = GenerateKey(meta.dataDir, meta.storeId); if (meta.storeType >= MAX_CREATOR_NUM || meta.storeType < 0 || !creators_[meta.storeType] || disables_.ContainIf(meta.tokenId, [&storeKey](const std::set &stores) -> bool { return stores.count(storeKey) != 0; })) { - ZLOGW("storeType is invalid or store is disabled,user:%{public}s,bundleName:%{public}s,storeName:%{public}s", - meta.user.c_str(), meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); + ZLOGW("storeType %{public}d is invalid or store is disabled, user:%{public}s, bundleName:%{public}s, " + "storeName:%{public}s", meta.storeType, meta.user.c_str(), meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); return { E_ERROR, store }; } if (meta.area == GeneralStore::EL4 && ScreenManager::GetInstance()->IsLocked()) { @@ -126,11 +127,10 @@ AutoCache::Store AutoCache::GetStore(const StoreMetaData &meta, const Watchers & return GetDBStore(meta, watchers).second; } -AutoCache::Stores AutoCache::GetStoresIfPresent(uint32_t tokenId, const std::string &storeName, - const std::string &userId) +AutoCache::Stores AutoCache::GetStoresIfPresent(uint32_t tokenId, const std::string &path, const std::string &storeName) { Stores stores; - auto storeKey = GenerateKey(userId, storeName); + auto storeKey = GenerateKey(path, storeName); stores_.ComputeIfPresent( tokenId, [&stores, &storeKey](auto &, std::map &delegates) -> bool { if (storeKey.empty()) { @@ -170,13 +170,13 @@ void AutoCache::StartTimer() ZLOGD("start timer,taskId: %{public}" PRIu64, taskId_); } -void AutoCache::CloseStore(uint32_t tokenId, const std::string &storeId, const std::string &userId) +void AutoCache::CloseStore(uint32_t tokenId, const std::string &path, const std::string &storeId) { 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(); - auto storeKey = GenerateKey(userId, storeId); + auto storeKey = GenerateKey(path, storeId); stores_.ComputeIfPresent(tokenId, [this, &storeKey, isScreenLocked, &storeIds, &closeStores](auto &, auto &delegates) { auto it = delegates.begin(); @@ -241,10 +241,10 @@ void AutoCache::CloseStore(const AutoCache::Filter &filter) }); } -void AutoCache::SetObserver(uint32_t tokenId, const std::string &storeId, const AutoCache::Watchers &watchers, - const std::string &userId) +void AutoCache::SetObserver(uint32_t tokenId, const AutoCache::Watchers &watchers, const std::string &path, + const std::string &storeId) { - auto storeKey = GenerateKey(userId, storeId); + auto storeKey = GenerateKey(path, storeId); stores_.ComputeIfPresent(tokenId, [&storeKey, &watchers](auto &key, auto &stores) { ZLOGD("tokenId:0x%{public}x storeId:%{public}s observers:%{public}zu", key, Anonymous::Change(storeKey).c_str(), watchers.size()); @@ -274,23 +274,23 @@ void AutoCache::GarbageCollect(bool isForce) }); } -void AutoCache::Enable(uint32_t tokenId, const std::string &storeId, const std::string &userId) +void AutoCache::Enable(uint32_t tokenId, const std::string &path, const std::string &storeId) { - auto storeKey = GenerateKey(userId, storeId); + auto storeKey = GenerateKey(path, storeId); disables_.ComputeIfPresent(tokenId, [&storeKey](auto key, std::set &stores) { stores.erase(storeKey); return !(stores.empty() || storeKey.empty()); }); } -void AutoCache::Disable(uint32_t tokenId, const std::string &storeId, const std::string &userId) +void AutoCache::Disable(uint32_t tokenId, const std::string &path, const std::string &storeId) { - auto storeKey = GenerateKey(userId, storeId); + auto storeKey = GenerateKey(path, storeId); disables_.Compute(tokenId, [&storeKey](auto key, std::set &stores) { stores.insert(storeKey); return !stores.empty(); }); - CloseStore(tokenId, storeId, userId); + CloseStore(tokenId, path, storeId); } AutoCache::Delegate::Delegate(GeneralStore *delegate, const Watchers &watchers, int32_t user, const StoreMetaData &meta) diff --git a/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn index 24a5a8d64aa22e7a104577b3e6f250b250e0a833..37a5bafddd07269758be7cb49b3601c027d7f709 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn @@ -21,30 +21,19 @@ config("module_private_config") { visibility = [ ":*" ] include_dirs = [ - "${device_manager_path}/interfaces/inner_kits/native_cpp/include", - "../include/", - "../../service/bootstrap/include/", - "../../service/common/", - "../../service/rdb/", - "../../../../../relational_store/interfaces/inner_api/rdb/include", - "../../../../../relational_store/interfaces/inner_api/common_type/include", - "${kv_store_distributeddb_path}/interfaces/include", - "${kv_store_distributeddb_path}/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/src", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_path}/interfaces/innerkits/distributeddata/include", + "${data_service_path}/service/bootstrap/include/", + "${data_service_path}/service/common/", + "${data_service_path}/service/rdb/", "${data_service_path}/adapter/include", "${data_service_path}/framework/include", "${data_service_path}/service/config/include", "${data_service_path}/app/src", "${data_service_path}/adapter/include/account", + "${data_service_path}/adapter/include/communicator", "${data_service_path}/app/src/security", "${data_service_path}/service/crypto/include", "${data_service_path}/service/matrix/include", - "//third_party/json/single_include", + "${data_service_path}/service/kvdb", ] cflags = [ "-Werror" ] ldflags = [ "-Wl,--whole-archive" ] @@ -59,19 +48,19 @@ ohos_unittest("CheckerManagerTest") { external_deps = [ "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddata_inner", + "openssl:libcrypto_shared", ] deps = [ "${data_service_path}/app/src/checker:distributeddata_checker", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/service:distributeddatasvc", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", ] } @@ -83,15 +72,13 @@ ohos_unittest("EventCenterTest") { external_deps = [ "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddata_inner", ] - deps = [ - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", - ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] } ohos_unittest("SerializableTest") { @@ -105,16 +92,14 @@ ohos_unittest("SerializableTest") { "ability_base:base", "ability_base:want", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddata_inner", + "openssl:libcrypto_shared", ] - deps = [ - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] } ohos_unittest("ServiceUtilsTest") { @@ -133,14 +118,14 @@ ohos_unittest("ServiceUtilsTest") { "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "json:nlohmann_json_static", + "kv_store:datamgr_common", ] - deps = [ - "${data_service_path}/framework:distributeddatasvcfwk", - "//third_party/googletest:gtest_main", - ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] } ohos_unittest("StoreTest") { @@ -170,6 +155,8 @@ ohos_unittest("StoreTest") { "access_token:libnativetoken", "c_utils:utils", "common_event_service:cesfwk_innerkits", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_inner", @@ -183,7 +170,6 @@ ohos_unittest("StoreTest") { "${data_service_path}/service:distributeddatasvc", "${data_service_path}/service/common:distributeddata_common", "${data_service_path}/service/test/mock:distributeddata_mock_static", - "//third_party/googletest:gtest_main", ] } @@ -192,6 +178,10 @@ ohos_unittest("AssetLoaderTest") { sources = [ "asset_loader_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + + external_deps = [ + "kv_store:datamgr_common", + ] } ohos_unittest("BackupRuleManagerTest") { @@ -199,6 +189,10 @@ ohos_unittest("BackupRuleManagerTest") { sources = [ "backup_rule_manager_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + + external_deps = [ + "kv_store:datamgr_common", + ] } ohos_unittest("BindEventTest") { @@ -206,6 +200,10 @@ ohos_unittest("BindEventTest") { sources = [ "bind_event_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + + external_deps = [ + "kv_store:datamgr_common", + ] } ohos_unittest("CloudInfoTest") { @@ -213,6 +211,12 @@ ohos_unittest("CloudInfoTest") { sources = [ "cloud_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + + external_deps = [ + "c_utils:utils", + "json:nlohmann_json_static", + "kv_store:datamgr_common", + ] } ohos_unittest("EventTest") { @@ -220,6 +224,10 @@ ohos_unittest("EventTest") { sources = [ "event_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + + external_deps = [ + "kv_store:datamgr_common", + ] } ohos_unittest("GeneralStoreTest") { @@ -227,6 +235,10 @@ ohos_unittest("GeneralStoreTest") { sources = [ "general_store_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + external_deps = [ + "c_utils:utils", + "kv_store:datamgr_common", + ] } ohos_unittest("SubscriptionTest") { @@ -234,35 +246,44 @@ ohos_unittest("SubscriptionTest") { sources = [ "subscription_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + external_deps = [ + "json:nlohmann_json_static", + "kv_store:datamgr_common", + ] } ohos_unittest("FeatureTest") { module_out_path = module_output_path sources = [ "feature_test.cpp" ] configs = [ ":module_private_config" ] - deps = [ - "${data_service_path}/framework:distributeddatasvcfwk", - "${kv_store_path}/interfaces/innerkits/distributeddata:distributeddata_inner", - ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + external_deps = [ "kv_store:distributeddata_inner" ] } ohos_unittest("MetaDataManagerTest") { module_out_path = module_output_path - sources = [ "meta_data_manager_test.cpp" ] + sources = [ + "meta_data_manager_test.cpp", + "mock/db_store_mock.cpp", + ] configs = [ ":module_private_config" ] external_deps = [ "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "json:nlohmann_json_static", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "kv_store:distributeddata_inner", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//third_party/googletest:gtest_main", ] } @@ -271,6 +292,13 @@ ohos_unittest("StoreMetaDataLocalTest") { sources = [ "store_meta_data_local_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + + external_deps = [ + "json:nlohmann_json_static", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "kv_store:distributeddata_inner", + ] } ohos_unittest("ConstantTest") { @@ -278,6 +306,10 @@ ohos_unittest("ConstantTest") { sources = [ "constant_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + + external_deps = [ + "kv_store:datamgr_common", + ] } ohos_unittest("CryptoTest") { @@ -285,6 +317,10 @@ ohos_unittest("CryptoTest") { sources = [ "crypto_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + + external_deps = [ + "kv_store:datamgr_common", + ] } ohos_unittest("ServiceMetaDataTest") { @@ -308,47 +344,22 @@ ohos_unittest("ServiceMetaDataTest") { configs = [ ":module_private_config" ] - include_dirs = [ - "${device_manager_path}/interfaces/inner_kits/native_cpp/include", - "../include/", - "../../service/bootstrap/include/", - "../../service/common/", - "../../service/rdb/", - "../../../../../relational_store/interfaces/inner_api/rdb/include", - "../../../../../relational_store/interfaces/inner_api/common_type/include", - "${kv_store_distributeddb_path}/interfaces/include", - "${kv_store_distributeddb_path}/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/src", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_path}/interfaces/innerkits/distributeddata/include", - "${data_service_path}/adapter/include", - "${data_service_path}/framework/include", - "${data_service_path}/service/config/include", - "${data_service_path}/app/src", - "${data_service_path}/adapter/include/account", - "${data_service_path}/app/src/security", - "${data_service_path}/service/crypto/include", - "${data_service_path}/service/matrix/include", - "${data_service_path}/service/kvdb", - "//third_party/json/single_include", - "${data_service_path}/adapter/include/communicator", - ] - external_deps = [ "c_utils:utils", "dataclassification:data_transit_mgr", "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", "hitrace:libhitracechain", "ipc:ipc_core", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", "kv_store:distributeddb", + "openssl:libcrypto_shared", "safwk:system_ability_fwk", "samgr:samgr_proxy", ] @@ -360,14 +371,42 @@ ohos_unittest("ServiceMetaDataTest") { "${data_service_path}/app/src/checker:distributeddata_checker", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/kvdb:distributeddata_kvdb", - "${kv_store_distributeddb_path}:distributeddb", - "${kv_store_path}/interfaces/innerkits/distributeddata:distributeddata_inner", - "${kv_store_path}/interfaces/innerkits/distributeddatamgr:distributeddata_mgr", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", ] } +ohos_unittest("ScreenManagerTest") { + module_out_path = module_output_path + sources = [ "screen_manager_test.cpp" ] + configs = [ ":module_private_config" ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + external_deps = [ "kv_store:datamgr_common" ] +} + +ohos_unittest("AppIdMappingConfigManagerTest") { + module_out_path = module_output_path + sources = [ "app_id_mapping_config_manager_test.cpp" ] + configs = [ ":module_private_config" ] + cflags = [ "-fno-access-control" ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + external_deps = [ "kv_store:datamgr_common" ] +} + +ohos_unittest("ConnectManagerTest") { + module_out_path = module_output_path + sources = [ "connect_manager_test.cpp" ] + configs = [ ":module_private_config" ] + cflags = [ "-fno-access-control" ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + external_deps = [ "kv_store:datamgr_common" ] +} + +ohos_unittest("DeviceSyncAppManagerTest") { + module_out_path = module_output_path + sources = [ "device_sync_app_manager_test.cpp" ] + configs = [ ":module_private_config" ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + external_deps = [ "kv_store:datamgr_common" ] +} ############################################################################### group("unittest") { testonly = true @@ -375,18 +414,22 @@ group("unittest") { deps = [] deps += [ + ":AppIdMappingConfigManagerTest", ":AssetLoaderTest", ":BackupRuleManagerTest", ":BindEventTest", ":CheckerManagerTest", ":CloudInfoTest", + ":ConnectManagerTest", ":ConstantTest", ":CryptoTest", + ":DeviceSyncAppManagerTest", ":EventCenterTest", ":EventTest", ":FeatureTest", ":GeneralStoreTest", ":MetaDataManagerTest", + ":ScreenManagerTest", ":SerializableTest", ":ServiceMetaDataTest", ":ServiceUtilsTest", diff --git a/datamgr_service/services/distributeddataservice/framework/test/app_id_mapping_config_manager_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/app_id_mapping_config_manager_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c441ba91092d0f02833e7407498dedaf0a90c818 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/app_id_mapping_config_manager_test.cpp @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2025 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 "app_id_mapping/app_id_mapping_config_manager.h" + +#include + +using namespace testing::ext; +using namespace OHOS::DistributedData; +namespace OHOS::Test { +class AppIdMappingConfigManagerTest : public testing::Test {}; + +/** +* @tc.name: Convert +* @tc.desc: Generate a pair based on the input appId and accountId. +* @tc.type: FUNC +*/ +HWTEST_F(AppIdMappingConfigManagerTest, Convert01, TestSize.Level1) +{ + std::vector mapper = { + {"src1", "dst1"}, + {"src2", "dst2"}, + {"src3", "dst3"} + }; + AppIdMappingConfigManager::GetInstance().Initialize(mapper); + auto result = AppIdMappingConfigManager::GetInstance().Convert("123", "123456789"); + EXPECT_EQ(result.first, "123"); + EXPECT_EQ(result.second, "123456789"); + result = AppIdMappingConfigManager::GetInstance().Convert("src1", "987654321"); + EXPECT_EQ(result.first, "dst1"); + EXPECT_EQ(result.second, "default"); +} + +/** +* @tc.name: Convert +* @tc.desc: Convert the input appId to another id. +* @tc.type: FUNC +*/ +HWTEST_F(AppIdMappingConfigManagerTest, Convert02, TestSize.Level1) +{ + std::vector mapper = { + {"src1", "dst1"}, + {"src2", "dst2"}, + {"src3", "dst3"} + }; + AppIdMappingConfigManager::GetInstance().Initialize(mapper); + auto result = AppIdMappingConfigManager::GetInstance().Convert("321"); + EXPECT_EQ(result, "321");; + result = AppIdMappingConfigManager::GetInstance().Convert("src1"); + EXPECT_EQ(result, "dst1"); +} +} // namespace OHOS::Test \ 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 1940f95fc3bf7f00f54b53f6d4c7e89d7f94f507..57e4ab7ec63550b492ef1a1d4add7825e2dce4bc 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/cloud_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/cloud_test.cpp @@ -22,7 +22,6 @@ #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" @@ -502,9 +501,9 @@ HWTEST_F(ServicesCloudDBTest, CloudDB, TestSize.Level0) EXPECT_EQ(result1, GeneralError::E_NOT_SUPPORT); auto result2 = cloudDB.Query(table, extend); - EXPECT_EQ(result2, nullptr); + EXPECT_EQ(result2.second, nullptr); result2 = cloudDB.Query(query, extend); - EXPECT_EQ(result2, nullptr); + EXPECT_EQ(result2.second, nullptr); auto result3 = cloudDB.AliveTime(); EXPECT_EQ(result3, -1); @@ -547,16 +546,4 @@ HWTEST_F(CloudEventTest, GetEventId, TestSize.Level0) 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/connect_manager_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/connect_manager_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7965d9eb07b9d5de5923044375c65058de10a64d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/connect_manager_test.cpp @@ -0,0 +1,70 @@ +/* +* Copyright (c) 2025 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 "communication/connect_manager.h" + +#include + +using namespace testing::ext; +using namespace OHOS::AppDistributedKv; +namespace OHOS::Test { +class ConnectManagerTest : public testing::Test {}; + +/** +* @tc.name: RegisterInstance +* @tc.desc: Register Instance. +* @tc.type: FUNC +*/ +HWTEST_F(ConnectManagerTest, RegisterInstance, TestSize.Level1) +{ + auto instance = ConnectManager::GetInstance(); + ASSERT_NE(instance, nullptr); + auto result = ConnectManager::RegisterInstance(std::make_shared()); + ASSERT_TRUE(result); + ASSERT_NE(ConnectManager::GetInstance(), nullptr); +} + +/** +* @tc.name: CloseSession +* @tc.desc: Close the session related to the networkid. +* @tc.type: FUNC +*/ +HWTEST_F(ConnectManagerTest, CloseSession, TestSize.Level1) +{ + auto ret = ConnectManager::GetInstance()->CloseSession(""); + ASSERT_FALSE(ret); + ConnectManager::GetInstance()->closeSessionTask_ = [](const std::string &networkId) { + return true; + }; + ret = ConnectManager::GetInstance()->CloseSession(""); + ASSERT_TRUE(ret); +} + +/** +* @tc.name: RegisterCloseSessionTask +* @tc.desc: Only one session closing task can be registered. +* @tc.type: FUNC +*/ +HWTEST_F(ConnectManagerTest, RegisterCloseSessionTask, TestSize.Level1) +{ + ConnectManager::GetInstance()->closeSessionTask_ = [](const std::string &networkId) { + return true; + }; + auto ret = ConnectManager::GetInstance()->RegisterCloseSessionTask([](const std::string &networkId) { + return true; + }); + ASSERT_FALSE(ret); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/device_sync_app_manager_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/device_sync_app_manager_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ae441b9f46f540bfcf026c3265783a4347eec9f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/device_sync_app_manager_test.cpp @@ -0,0 +1,98 @@ +/* +* Copyright (c) 2025 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 "device_sync_app/device_sync_app_manager.h" +#include + +using namespace testing::ext; +using namespace OHOS::DistributedData; + +namespace OHOS::Test { +class DeviceSyncAppManagerTest : public testing::Test { +public: + void SetUp() + { + whiteList1 = {"appId1", "bundleName1", 1}; + whiteList2 = {"appId2", "bundleName2", 2}; + whiteList3 = {"appId3", "bundleName3", 3}; + + std::vector lists = {whiteList1, whiteList2, whiteList3}; + DeviceSyncAppManager::GetInstance().Initialize(lists); + } + + DeviceSyncAppManager::WhiteList whiteList1; + DeviceSyncAppManager::WhiteList whiteList2; + DeviceSyncAppManager::WhiteList whiteList3; +}; + +/** +* @tc.name: Check001 +* @tc.desc: Checks that the given WhiteList object exists in whiteLists_ list. +* @tc.type: FUNC +*/ +HWTEST_F(DeviceSyncAppManagerTest, Check001, TestSize.Level1) +{ + DeviceSyncAppManager::WhiteList whiteList = {"appId1", "bundleName1", 1}; + bool result = DeviceSyncAppManager::GetInstance().Check(whiteList); + EXPECT_TRUE(result); +} + +/** +* @tc.name: Check002 +* @tc.desc: Check that the given appId object does not match. +* @tc.type: FUNC +*/ +HWTEST_F(DeviceSyncAppManagerTest, Check002, TestSize.Level1) +{ + DeviceSyncAppManager::WhiteList testList = {"appId2", "bundleName1", 1}; + bool result = DeviceSyncAppManager::GetInstance().Check(testList); + EXPECT_FALSE(result); +} + +/** +* @tc.name: Check003 +* @tc.desc: Check that the given bundleName object does not match. +* @tc.type: FUNC +*/ +HWTEST_F(DeviceSyncAppManagerTest, Check003, TestSize.Level1) +{ + DeviceSyncAppManager::WhiteList testList = {"appId1", "bundleName2", 1}; + bool result = DeviceSyncAppManager::GetInstance().Check(testList); + EXPECT_FALSE(result); +} + +/** +* @tc.name: Check004 +* @tc.desc: Check that the given version object does not match. +* @tc.type: FUNC +*/ +HWTEST_F(DeviceSyncAppManagerTest, Check004, TestSize.Level1) +{ + DeviceSyncAppManager::WhiteList testList = {"appId1", "bundleName1", 2}; + bool result = DeviceSyncAppManager::GetInstance().Check(testList); + EXPECT_FALSE(result); +} + +/** +* @tc.name: Check005 +* @tc.desc: Checks that the given WhiteList object does not exist in whiteLists_ list. +* @tc.type: FUNC +*/ +HWTEST_F(DeviceSyncAppManagerTest, Check005, TestSize.Level1) +{ + DeviceSyncAppManager::WhiteList whiteList = {"appId4", "bundleName4", 4}; + bool result = DeviceSyncAppManager::GetInstance().Check(whiteList); + EXPECT_FALSE(result); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..b35cb67af178f4630b3f50d1f4cbd1170d81ff2c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/BUILD.gn @@ -0,0 +1,25 @@ +# Copyright (c) 2025 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") + +######################################################################################### +group("fuzztest") { + testonly = true + + deps = [ + "storedebuginfo_fuzzer:fuzztest", + "screenmanager_fuzzer:fuzztest", + ] +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..f063faa15c3e8a5a0e1e28ad2119271ce4a6930b --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/BUILD.gn @@ -0,0 +1,55 @@ +# Copyright (c) 2025 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("ScreenManagerFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + include_dirs = [ + "${data_service_path}/framework/include", + ] + + fuzz_config_file = + "${data_service_path}/framework/test/fuzztest/screenmanager_fuzzer" + + sources = [ "screenmanager_fuzzer.cpp" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "kv_store:datamgr_common", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":ScreenManagerFuzzTest" ] +} +############################################################################### \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..7ade8a0faafeaedba7241e7d4a97b8e1f9691932 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a37a23b1533f07ab59744732b0f46b2b5fd958d8 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/rddbrepair_fuzzer.cpp b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/screenmanager_fuzzer.cpp similarity index 53% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/rddbrepair_fuzzer.cpp rename to datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/screenmanager_fuzzer.cpp index ce6c2faf58472e237df7ce0e78c3f7bf22cf913f..d944f95c32460f65b1dbaa5db93703e895cf2f26 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/rddbrepair_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/screenmanager_fuzzer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2025 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,24 +13,28 @@ * limitations under the License. */ -#include "rd_utils.h" -#include "rdb_errno.h" -#include "rdb_store_config.h" -#include "rdb_store_impl.h" -using namespace OHOS; -using namespace OHOS::NativeRdb; -namespace OHOS { +#include +#include "screenmanager_fuzzer.h" +#include "screen/screen_manager.h" + +using namespace OHOS::DistributedData; -void rddbrepairFuzzer(const uint8_t *data, size_t size) +namespace OHOS { +void TestScreenManager(FuzzedDataProvider &provider) { - RdUtils::RdDbRepair(reinterpret_cast(data), reinterpret_cast(data)); + ScreenManager::GetInstance()->Subscribe(nullptr); + ScreenManager::GetInstance()->Unsubscribe(nullptr); + ScreenManager::GetInstance()->BindExecutor(nullptr); + ScreenManager::GetInstance()->SubscribeScreenEvent(); + ScreenManager::GetInstance()->UnsubscribeScreenEvent(); } + } // namespace OHOS /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - /* Run your code on data */ - OHOS::rddbrepairFuzzer(data, size); + FuzzedDataProvider provider(data, size); + OHOS::TestScreenManager(provider); return 0; -} +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/screenmanager_fuzzer.h b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/screenmanager_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..ab2fe6fe3efc801f5bc6b74e8a7861e05babcbfb --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/screenmanager_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 SCREENMANAGER_FUZZER_H +#define SCREENMANAGER_FUZZER_H + +#define FUZZ_PROJECT_NAME "screenmanager_fuzzer" + +#endif // SCREENMANAGER_FUZZER_H diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..a44f574a0149d464abab8570140c7399d4e71bcd --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/BUILD.gn @@ -0,0 +1,56 @@ +# Copyright (c) 2025 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("StoreDebugInfoFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + include_dirs = [ + "${data_service_path}/framework/include", + ] + + fuzz_config_file = + "${data_service_path}/framework/test/fuzztest/storedebuginfo_fuzzer" + + sources = [ "storedebuginfo_fuzzer.cpp" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "json:nlohmann_json_static", + "kv_store:datamgr_common", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":StoreDebugInfoFuzzTest" ] +} +############################################################################### \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..7ade8a0faafeaedba7241e7d4a97b8e1f9691932 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a37a23b1533f07ab59744732b0f46b2b5fd958d8 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/storedebuginfo_fuzzer.cpp b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/storedebuginfo_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f497a3d16753eb0f3053784ba2cb012ca5b6d6b6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/storedebuginfo_fuzzer.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025 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 "storedebuginfo_fuzzer.h" +#include "metadata/store_debug_info.h" + +using namespace OHOS::DistributedData; + +namespace OHOS { + +void StoreDebugInfoFuzz(FuzzedDataProvider &provider) +{ + StoreDebugInfo::FileInfo fileInfo; + StoreDebugInfo debugInfo; + std::string fileName = "filename"; + debugInfo.fileInfos.insert(std::make_pair(fileName, fileInfo)); + Serializable::json node; + std::string key = provider.ConsumeRandomLengthString(); + std::string valueStr = provider.ConsumeRandomLengthString(); + int valueInt = provider.ConsumeIntegral(); + float valueFloat = provider.ConsumeFloatingPoint(); + bool valueBool = provider.ConsumeBool(); + int valueRange = provider.ConsumeIntegralInRange(0, 100); + node[key] = valueStr; + node["integer"] = valueInt; + node["float"] = valueFloat; + node["boolean"] = valueBool; + node["range"] = valueRange; + fileInfo.Marshal(node); + fileInfo.Unmarshal(node); + debugInfo.Marshal(node); + debugInfo.Unmarshal(node); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::StoreDebugInfoFuzz(provider); + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/storedebuginfo_fuzzer.h b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/storedebuginfo_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..152fe67a68dbd7930386bfa5a930bee2eb4bf3f7 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/storedebuginfo_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 STOREDEBUGINFO_FUZZER_H +#define STOREDEBUGINFO_FUZZER_H + +#define FUZZ_PROJECT_NAME "storedebuginfo_fuzzer" + +#endif // STOREDEBUGINFO_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/meta_data_manager_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/meta_data_manager_test.cpp index a733b88cb3c6710442135333dc975edd511b2868..da055af3dbda8ee5ac18b12dcb5f857b17f1b9bd 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/meta_data_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/meta_data_manager_test.cpp @@ -14,26 +14,61 @@ */ #define LOG_TAG "MetaDataManagerTest" -#include "log_print.h" #include "metadata/meta_data_manager.h" #include + +#include "log_print.h" +#include "mock/db_store_mock.h" using namespace OHOS; using namespace testing::ext; using namespace OHOS::DistributedData; using namespace OHOS::DistributedKv; namespace OHOS::Test { +class DBStoreMockImpl; class MetaDataManagerTest : public testing::Test { public: static const std::string INVALID_DEVICE_ID; - static const std::string EMPTY_DEVICE_ID; - static void SetUpTestCase(void) {}; + static void SetUpTestCase(void); static void TearDownTestCase(void) {}; void SetUp() {}; void TearDown() {}; + static std::shared_ptr metaStore; }; const std::string MetaDataManagerTest::INVALID_DEVICE_ID = "1234567890"; -const std::string MetaDataManagerTest::EMPTY_DEVICE_ID = ""; +std::shared_ptr MetaDataManagerTest::metaStore = nullptr; +class DBStoreMockImpl : public DBStoreMock { +public: + using PutLocalBatchFunc = std::function &)>; + PutLocalBatchFunc putLocalBatchFunc; + DBStatus PutLocalBatch(const std::vector &entries) override + { + if (putLocalBatchFunc) { + return putLocalBatchFunc(entries); + } + return DBStoreMock::PutLocalBatch(entries); + } + using DeleteLocalBatchFunc = std::function &)>; + DeleteLocalBatchFunc deleteLocalBatchFunc; + DBStatus DeleteLocalBatch(const std::vector &keys) override + { + if (deleteLocalBatchFunc) { + return deleteLocalBatchFunc(keys); + } + return DBStoreMock::DeleteLocalBatch(keys); + } +}; + +void MetaDataManagerTest::SetUpTestCase(void) +{ + metaStore = std::make_shared(); + MetaDataManager::GetInstance().Initialize( + metaStore, + [](const auto &store) { + return 0; + }, + "meta"); +}; /** * @tc.name: FilterConstructorAndGetKeyTest * @tc.desc: FilterConstructor and GetKey. @@ -79,7 +114,6 @@ HWTEST_F(MetaDataManagerTest, FilterOperatorTest, TestSize.Level1) HWTEST_F(MetaDataManagerTest, SyncTest001, TestSize.Level1) { std::vector devices; - devices.emplace_back(EMPTY_DEVICE_ID); MetaDataManager::OnComplete complete; auto result = MetaDataManager::GetInstance().Sync(devices, complete); EXPECT_FALSE(result); @@ -98,6 +132,113 @@ HWTEST_F(MetaDataManagerTest, SyncTest002, TestSize.Level1) devices.emplace_back(INVALID_DEVICE_ID); MetaDataManager::OnComplete complete; auto result = MetaDataManager::GetInstance().Sync(devices, complete); - EXPECT_FALSE(result); + EXPECT_TRUE(result); +} + +/** + * @tc.name: SyncTest003 + * @tc.desc: devices is invalid. + * @tc.type: FUNC + * @tc.require: + * @tc.author: SQL + */ +HWTEST_F(MetaDataManagerTest, SyncTest003, TestSize.Level1) +{ + std::vector devices; + devices.emplace_back(INVALID_DEVICE_ID); + MetaDataManager::OnComplete complete = [](auto &results) {}; + auto result = MetaDataManager::GetInstance().Sync(devices, complete); + EXPECT_TRUE(result); +} + +/** + * @tc.name: SaveMetaTest001 + * @tc.desc: Batch save empty. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(MetaDataManagerTest, SaveMetaTest001, TestSize.Level1) +{ + std::vector values; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(values, true)); +} + +/** + * @tc.name: SaveMetaTest002 + * @tc.desc: Return error code when saving. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(MetaDataManagerTest, SaveMetaTest002, TestSize.Level1) +{ + std::vector values; + values.push_back({ "SaveMetaTest002", "value" }); + metaStore->putLocalBatchFunc = [](auto &entries) { + return DistributedDB::DBStatus::DB_ERROR; + }; + EXPECT_FALSE(MetaDataManager::GetInstance().SaveMeta(values, true)); + metaStore->putLocalBatchFunc = nullptr; +} + +/** + * @tc.name: SaveMetaTest004 + * @tc.desc: Trigger sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(MetaDataManagerTest, SaveMetaTest003, TestSize.Level1) +{ + metaStore->putLocalBatchFunc = nullptr; + std::vector values; + values.push_back({ "SaveMetaTest004", "value" }); + bool flag = false; + MetaDataManager::GetInstance().SetCloudSyncer([&flag]() { + flag = true; + return; + }); + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(values, false)); + EXPECT_TRUE(flag); + MetaDataManager::GetInstance().SetCloudSyncer(nullptr); +} + +/** + * @tc.name: DelMetaTest001 + * @tc.desc: Return INVALID_PASSWD_OR_CORRUPTED_DB when del meta. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(MetaDataManagerTest, DelMetaTest001, TestSize.Level1) +{ + metaStore->deleteLocalBatchFunc = nullptr; + std::vector keys{ "DelMetaTest001" }; + metaStore->deleteLocalBatchFunc = [](auto &keys) { + return DistributedDB::DBStatus::DB_ERROR; + }; + EXPECT_FALSE(MetaDataManager::GetInstance().DelMeta(keys, true)); + metaStore->deleteLocalBatchFunc = nullptr; +} + +/** + * @tc.name: DelMetaTest003 + * @tc.desc: Trigger sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(MetaDataManagerTest, DelMetaTest002, TestSize.Level1) +{ + std::vector keys{ "DelMetaTest003" }; + bool flag = false; + MetaDataManager::GetInstance().SetCloudSyncer([&flag]() { + flag = true; + return; + }); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(keys, false)); + EXPECT_TRUE(flag); + MetaDataManager::GetInstance().SetCloudSyncer(nullptr); } } // 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 6ab4d6ce8637943fb3706b6ef13beab0374e1bc5..8d67bc0fb375ae96b88f3ca7198dfef172e1a354 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/meta_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/meta_data_test.cpp @@ -25,6 +25,7 @@ #include "metadata/matrix_meta_data.h" #include "metadata/meta_data.h" #include "metadata/meta_data_manager.h" +#include "metadata/object_user_meta_data.h" #include "metadata/secret_key_meta_data.h" #include "metadata/store_meta_data.h" #include "metadata/store_meta_data_local.h" @@ -34,7 +35,7 @@ #include "metadata/device_meta_data.h" #include "utils/constant.h" #include "gtest/gtest.h" -#include +#include "serializable/serializable.h" using namespace testing::ext; using namespace OHOS; using namespace OHOS::DistributedKv; @@ -224,12 +225,13 @@ HWTEST_F(ServiceMetaDataTest, SecretKeyMetaData002, TestSize.Level1) HWTEST_F(ServiceMetaDataTest, StoreMetaData001, TestSize.Level1) { StoreMetaData storeMetaData("100", "appid", "test_store"); + storeMetaData.dataDir = "testDir"; StoreMetaData storeMeta; std::string key = storeMetaData.GetKey(); - EXPECT_EQ(key, "KvStoreMetaData######100###default######test_store"); + EXPECT_EQ(key, "KvStoreMetaData######100###default######test_store###testDir"); std::string keylocal = storeMetaData.GetKeyLocal(); - EXPECT_EQ(keylocal, "KvStoreMetaDataLocal######100###default######test_store"); + EXPECT_EQ(keylocal, "KvStoreMetaDataLocal######100###default######test_store###testDir"); std::initializer_list fields = { "100", "appid", "test_store" }; std::string keyfields = storeMetaData.GetKey(fields); EXPECT_EQ(keyfields, "KvStoreMetaData###100###appid###test_store"); @@ -245,15 +247,16 @@ HWTEST_F(ServiceMetaDataTest, StoreMetaData001, TestSize.Level1) result = MetaDataManager::GetInstance().DelMeta(key, true); EXPECT_TRUE(result); - result = MetaDataManager::GetInstance().SaveMeta(key, storeMetaData); + std::string syncKey = storeMetaData.GetKeyWithoutPath(); + result = MetaDataManager::GetInstance().SaveMeta(syncKey, storeMetaData); EXPECT_TRUE(result); - result = MetaDataManager::GetInstance().LoadMeta(key, storeMeta); + result = MetaDataManager::GetInstance().LoadMeta(syncKey, storeMeta); EXPECT_TRUE(result); EXPECT_EQ(storeMetaData.GetKey(), storeMeta.GetKey()); EXPECT_EQ(storeMetaData.GetKeyLocal(), storeMeta.GetKeyLocal()); EXPECT_EQ(storeMetaData.GetKey(fields), storeMeta.GetKey(fields)); - result = MetaDataManager::GetInstance().DelMeta(key); + result = MetaDataManager::GetInstance().DelMeta(syncKey); EXPECT_TRUE(result); } @@ -267,10 +270,11 @@ HWTEST_F(ServiceMetaDataTest, StoreMetaData001, TestSize.Level1) HWTEST_F(ServiceMetaDataTest, StoreMetaData002, TestSize.Level1) { StoreMetaData storeMetaData("100", "appid", "test_store"); + storeMetaData.dataDir = "testDir"; StoreMetaData storeMeta; std::string secretkey = storeMetaData.GetSecretKey(); - EXPECT_EQ(secretkey, "SecretKey###100###default######test_store###0###SINGLE_KEY"); + EXPECT_EQ(secretkey, "SecretKey###100###default######test_store###0###testDir###SINGLE_KEY"); std::string backupsecretkey = storeMetaData.GetBackupSecretKey(); EXPECT_EQ(backupsecretkey, "BackupSecretKey###100###default######test_store###0###"); @@ -350,12 +354,13 @@ HWTEST_F(ServiceMetaDataTest, StoreMetaData004, TestSize.Level1) StoreMetaData storeMetaData("100", "appid", "test_store"); storeMetaData.version = TEST_CURRENT_VERSION; storeMetaData.instanceId = 1; + storeMetaData.dataDir = "testDir"; StoreMetaData storeMeta; std::string key = storeMetaData.GetKey(); - EXPECT_EQ(key, "KvStoreMetaData######100###default######test_store###1"); + EXPECT_EQ(key, "KvStoreMetaData######100###default######test_store###1###testDir"); std::string keylocal = storeMetaData.GetKeyLocal(); - EXPECT_EQ(keylocal, "KvStoreMetaDataLocal######100###default######test_store###1"); + EXPECT_EQ(keylocal, "KvStoreMetaDataLocal######100###default######test_store###1###testDir"); auto result = MetaDataManager::GetInstance().SaveMeta(key, storeMetaData, true); EXPECT_TRUE(result); @@ -367,14 +372,15 @@ HWTEST_F(ServiceMetaDataTest, StoreMetaData004, TestSize.Level1) result = MetaDataManager::GetInstance().DelMeta(key, true); EXPECT_TRUE(result); - result = MetaDataManager::GetInstance().SaveMeta(key, storeMetaData); + std::string syncKey = storeMetaData.GetKeyWithoutPath(); + result = MetaDataManager::GetInstance().SaveMeta(syncKey, storeMetaData); EXPECT_TRUE(result); - result = MetaDataManager::GetInstance().LoadMeta(key, storeMeta); + result = MetaDataManager::GetInstance().LoadMeta(syncKey, storeMeta); EXPECT_TRUE(result); EXPECT_EQ(storeMetaData.GetKey(), storeMeta.GetKey()); EXPECT_EQ(storeMetaData.GetKeyLocal(), storeMeta.GetKeyLocal()); - result = MetaDataManager::GetInstance().DelMeta(key); + result = MetaDataManager::GetInstance().DelMeta(syncKey); EXPECT_TRUE(result); } @@ -390,10 +396,11 @@ HWTEST_F(ServiceMetaDataTest, StoreMetaData005, TestSize.Level1) StoreMetaData storeMetaData("100", "appid", "test_store"); storeMetaData.version = TEST_CURRENT_VERSION; storeMetaData.instanceId = 1; + storeMetaData.dataDir = "testDir"; StoreMetaData storeMeta; std::string secretkey = storeMetaData.GetSecretKey(); - EXPECT_EQ(secretkey, "SecretKey###100###default######test_store###SINGLE_KEY"); + EXPECT_EQ(secretkey, "SecretKey###100###default######test_store###testDir###SINGLE_KEY"); std::string backupsecretkey = storeMetaData.GetBackupSecretKey(); EXPECT_EQ(backupsecretkey, "BackupSecretKey###100###default######test_store###"); std::string strategykey = storeMetaData.GetStrategyKey(); @@ -534,6 +541,44 @@ HWTEST_F(ServiceMetaDataTest, StoreMetaData007, TestSize.Level1) EXPECT_FALSE(storemetaData1 != storemetaData2); } +/** + * @tc.name: StoreMetaData + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: MY + */ +HWTEST_F(ServiceMetaDataTest, StoreMetaData008, TestSize.Level1) +{ + StoreMetaData storeMetaData("100", "appid", "test_store"); + storeMetaData.instanceId = 1; + storeMetaData.dataDir = "008_dataDir"; + storeMetaData.deviceId = "008_uuid"; + storeMetaData.bundleName = "008_bundleName"; + + std::string key = "KvStoreMetaDataLocal###008_uuid###100###default###008_bundleName###test_store###1"; + EXPECT_EQ(storeMetaData.GetKeyLocalWithoutPath(), key); +} + +/** + * @tc.name: StoreMetaData + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: MY + */ +HWTEST_F(ServiceMetaDataTest, StoreMetaData009, TestSize.Level1) +{ + StoreMetaData storeMetaData("100", "appid", "test_store"); + storeMetaData.instanceId = 1; + storeMetaData.dataDir = "009_dataDir"; + storeMetaData.deviceId = "009_uuid"; + storeMetaData.bundleName = "009_bundleName"; + + std::string key = "StoreDfxInfo###009_uuid###100###default###009_bundleName###test_store###1###"; + EXPECT_EQ(storeMetaData.GetDfxInfoKeyWithoutPath(), key); +} + /** * @tc.name: GetStoreInfo * @tc.desc: test StoreMetaData GetStoreInfo function @@ -651,6 +696,7 @@ HWTEST_F(ServiceMetaDataTest, StrategyMeta002, TestSize.Level1) HWTEST_F(ServiceMetaDataTest, MetaData, TestSize.Level1) { StoreMetaData storeMetaData("100", "appid", "test_store"); + storeMetaData.dataDir = "testDir1"; SecretKeyMetaData secretKeyMetaData; MetaData metaData; MetaData metaDataLoad; @@ -811,18 +857,14 @@ HWTEST_F(ServiceMetaDataTest, DeviceMetaData, TestSize.Level1) { DeviceMetaData metaData; std::string newUuid = "newuuid"; - std::string oldUuid = "olduuid"; metaData.newUuid = newUuid; - metaData.oldUuid = oldUuid; Serializable::json node1; metaData.Marshal(node1); EXPECT_EQ(node1["newUuid"], newUuid); - EXPECT_EQ(node1["oldUuid"], oldUuid); DeviceMetaData newMetaData; newMetaData.Unmarshal(node1); EXPECT_EQ(newMetaData.newUuid, newUuid); - EXPECT_EQ(newMetaData.oldUuid, oldUuid); } /** @@ -840,6 +882,7 @@ HWTEST_F(ServiceMetaDataTest, InitTestMeta, TestSize.Level1) oldMeta.bundleName = "test_appid_001"; oldMeta.storeId = "test_storeid_001"; oldMeta.isEncrypt = true; + oldMeta.dataDir = "testDir2"; bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKey(), oldMeta, true); EXPECT_TRUE(isSuccess); StoreMetaDataLocal metaDataLocal; @@ -857,7 +900,7 @@ HWTEST_F(ServiceMetaDataTest, InitTestMeta, TestSize.Level1) isSuccess = MetaDataManager::GetInstance().SaveMeta(MatrixMetaData::GetPrefix({"mockOldUuid"}), matrixMeta0, true); EXPECT_TRUE(isSuccess); - isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKey(), oldMeta); + isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKeyWithoutPath(), oldMeta); EXPECT_TRUE(isSuccess); MatrixMetaData matrixMeta; isSuccess = MetaDataManager::GetInstance().SaveMeta(MatrixMetaData::GetPrefix({"mockOldUuid"}), matrixMeta); @@ -890,11 +933,12 @@ HWTEST_F(ServiceMetaDataTest, UpdateStoreMetaData, TestSize.Level1) newMeta.user = "200"; newMeta.bundleName = "test_appid_001"; newMeta.storeId = "test_storeid_001"; + newMeta.dataDir = "testDir2"; KvStoreMetaManager::GetInstance().UpdateStoreMetaData(mockNewUuid, mockOldUuid); bool isSuccess = MetaDataManager::GetInstance().LoadMeta(newMeta.GetKey(), newMeta, true); EXPECT_TRUE(isSuccess); EXPECT_TRUE(newMeta.isNeedUpdateDeviceId); - isSuccess = MetaDataManager::GetInstance().LoadMeta(newMeta.GetKey(), newMeta); + isSuccess = MetaDataManager::GetInstance().LoadMeta(newMeta.GetKeyWithoutPath(), newMeta); EXPECT_TRUE(isSuccess); AutoLaunchMetaData autoLaunchMetaData; isSuccess = MetaDataManager::GetInstance().LoadMeta(AutoLaunchMetaData::GetPrefix({ newMeta.deviceId, newMeta.user, @@ -916,11 +960,6 @@ HWTEST_F(ServiceMetaDataTest, UpdateMetaDatas, TestSize.Level1) { std::string mockNewUuid = "mockNewUuid"; std::string mockOldUuid = "mockOldUuid"; - StoreMetaData newMeta; - newMeta.deviceId = "mockNewUuid"; - newMeta.user = "200"; - newMeta.bundleName = "test_appid_001"; - newMeta.storeId = "test_storeid_001"; KvStoreMetaManager::GetInstance().UpdateMetaDatas(mockNewUuid, mockOldUuid); MatrixMetaData matrixMeta; bool isSuccess = MetaDataManager::GetInstance().LoadMeta(MatrixMetaData::GetPrefix({ "mockNewUuid" }), @@ -955,6 +994,7 @@ HWTEST_F(ServiceMetaDataTest, DelTestMeta, TestSize.Level1) newMeta.user = "200"; newMeta.bundleName = "test_appid_001"; newMeta.storeId = "test_storeid_001"; + newMeta.dataDir = "testDir2"; bool isSuccess = MetaDataManager::GetInstance().DelMeta(newMeta.GetKey(), true); EXPECT_TRUE(isSuccess); isSuccess = MetaDataManager::GetInstance().DelMeta(newMeta.GetKeyLocal(), true); @@ -967,7 +1007,7 @@ HWTEST_F(ServiceMetaDataTest, DelTestMeta, TestSize.Level1) isSuccess = MetaDataManager::GetInstance().DelMeta(MatrixMetaData::GetPrefix({ "mockNewUuid" }), true); EXPECT_TRUE(isSuccess); - isSuccess = MetaDataManager::GetInstance().DelMeta(newMeta.GetKey()); + isSuccess = MetaDataManager::GetInstance().DelMeta(newMeta.GetKeyWithoutPath()); EXPECT_TRUE(isSuccess); isSuccess = MetaDataManager::GetInstance().DelMeta(MatrixMetaData::GetPrefix({"mockNewUuid"})); EXPECT_TRUE(isSuccess); @@ -994,4 +1034,17 @@ HWTEST_F(ServiceMetaDataTest, GetKey, TestSize.Level1) std::string prefix = metaData.GetKey(); EXPECT_EQ(prefix, expectedPrefix); } + +/** +* @tc.name: ObjectUserMetaDataGetKey +* @tc.desc: ObjectUserMetaDataGetKey +* @tc.type: FUNC +*/ +HWTEST_F(ServiceMetaDataTest, ObjectUserMetaDataGetKey, TestSize.Level1) +{ + ObjectUserMetaData metaData; + std::string expectedPrefix = "ObjectUserMetaData"; + std::string prefix = metaData.GetKey(); + EXPECT_EQ(prefix, expectedPrefix); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/mock/db_store_mock.cpp b/datamgr_service/services/distributeddataservice/framework/test/mock/db_store_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..53c1b35eff66e1f9ff1e3f98f16b42b7131df884 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/mock/db_store_mock.cpp @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2025 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 "db_store_mock.h" + +namespace OHOS { +namespace DistributedData { +using namespace DistributedDB; +DBStatus DBStoreMock::Get(const Key &key, Value &value) const +{ + return Get(entries_, key, value); +} + +DBStatus DBStoreMock::GetEntries(const Key &keyPrefix, std::vector &entries) const +{ + return GetEntries(entries_, keyPrefix, entries); +} + +DBStatus DBStoreMock::GetEntries(const Key &keyPrefix, KvStoreResultSet *&resultSet) const +{ + resultSet = nullptr; + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::GetEntries(const Query &query, std::vector &entries) const +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::GetEntries(const Query &query, KvStoreResultSet *&resultSet) const +{ + resultSet = nullptr; + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::GetCount(const Query &query, int &count) const +{ + count = 0; + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::CloseResultSet(KvStoreResultSet *&resultSet) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Put(const Key &key, const Value &value) +{ + return PutBatch(entries_, { { key, value } }); +} + +DBStatus DBStoreMock::PutBatch(const std::vector &entries) +{ + return PutBatch(entries_, entries); +} + +DBStatus DBStoreMock::DeleteBatch(const std::vector &keys) +{ + return DeleteBatch(entries_, keys); +} + +DBStatus DBStoreMock::Delete(const Key &key) +{ + return DeleteBatch(entries_, { key }); +} + +DBStatus DBStoreMock::GetLocal(const Key &key, Value &value) const +{ + return Get(localEntries_, key, value); +} + +DBStatus DBStoreMock::GetLocalEntries(const Key &keyPrefix, std::vector &entries) const +{ + return GetEntries(localEntries_, keyPrefix, entries); +} + +DBStatus DBStoreMock::PutLocal(const Key &key, const Value &value) +{ + return PutBatch(localEntries_, { { key, value } }); +} + +DBStatus DBStoreMock::DeleteLocal(const Key &key) +{ + return DeleteBatch(localEntries_, { key }); +} + +DBStatus DBStoreMock::PublishLocal(const Key &key, bool deleteLocal, bool updateTimestamp, + const KvStoreNbPublishOnConflict &onConflict) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::UnpublishToLocal(const Key &key, bool deletePublic, bool updateTimestamp) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::RegisterObserver(const Key &key, unsigned int mode, KvStoreObserver *observer) +{ + observers_.Compute(observer, [key](auto &, std::set &prefixes) { + prefixes.insert(key); + return !prefixes.empty(); + }); + return OK; +} + +DBStatus DBStoreMock::UnRegisterObserver(const KvStoreObserver *observer) +{ + KvStoreObserver *key = const_cast(observer); + observers_.Erase(key); + return OK; +} + +DBStatus DBStoreMock::RemoveDeviceData(const std::string &device) +{ + return NOT_SUPPORT; +} + +std::string DBStoreMock::GetStoreId() const +{ + return std::string(); +} + +DBStatus DBStoreMock::Sync(const std::vector &devices, SyncMode mode, + const std::function &)> &onComplete, bool wait) +{ + std::map result; + for (const auto &device : devices) { + result[device] = OK; + } + onComplete(result); + return OK; +} + +DBStatus DBStoreMock::Pragma(PragmaCmd cmd, PragmaData ¶mData) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::SetConflictNotifier(int conflictType, const KvStoreNbConflictNotifier ¬ifier) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Rekey(const CipherPassword &password) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Export(const std::string &filePath, const CipherPassword &passwd, bool force) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Import(const std::string &filePath, const CipherPassword &passwd, bool isNeedIntegrityCheck) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::StartTransaction() +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Commit() +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Rollback() +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::PutLocalBatch(const std::vector &entries) +{ + return PutBatch(localEntries_, entries); +} + +DBStatus DBStoreMock::DeleteLocalBatch(const std::vector &keys) +{ + return DeleteBatch(localEntries_, keys); +} + +DBStatus DBStoreMock::GetSecurityOption(SecurityOption &option) const +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::SetRemotePushFinishedNotify(const RemotePushFinishedNotifier ¬ifier) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Sync(const std::vector &devices, SyncMode mode, + const std::function &)> &onComplete, const Query &query, bool wait) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::CheckIntegrity() const +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::SetEqualIdentifier(const std::string &identifier, const std::vector &targets) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::SetPushDataInterceptor(const PushDataInterceptor &interceptor) +{ + return NOT_SUPPORT; +} +DBStatus DBStoreMock::SubscribeRemoteQuery(const std::vector &devices, + const std::function &)> &onComplete, const Query &query, bool wait) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::UnSubscribeRemoteQuery(const std::vector &devices, + const std::function &)> &onComplete, const Query &query, bool wait) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::RemoveDeviceData() +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::GetKeys(const Key &keyPrefix, std::vector &keys) const +{ + return NOT_SUPPORT; +} + +size_t DBStoreMock::GetSyncDataSize(const std::string &device) const +{ + return DEFAULT_SIZE; +} + +DBStatus DBStoreMock::Get(ConcurrentMap &store, const Key &key, Value &value) const +{ + auto it = store.Find(key); + value = std::move(it.second); + return it.first ? OK : NOT_FOUND; +} + +DBStatus DBStoreMock::GetEntries(ConcurrentMap &store, const Key &keyPrefix, + std::vector &entries) const +{ + 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}); + } + return false; + }); + return entries.size() > 0 ? OK : NOT_FOUND; +} + +DBStatus DBStoreMock::PutBatch(ConcurrentMap &store, const std::vector &entries) +{ + return OK; +} + +DBStatus DBStoreMock::DeleteBatch(ConcurrentMap &store, const std::vector &keys) +{ + return OK; +} + +DBStatus DBStoreMock::UpdateKey(const UpdateKeyCallback &callback) +{ + return NOT_SUPPORT; +} + +std::pair DBStoreMock::GetWatermarkInfo(const std::string &device) +{ + WatermarkInfo mark; + return { DBStatus::OK, mark }; +} + +DBStatus DBStoreMock::Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::SetCloudDB(const std::map> &cloudDBs) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::SetCloudDbSchema(const std::map &schema) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::RemoveDeviceData(const std::string &device, ClearMode mode) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::RemoveDeviceData(const std::string &device, const std::string &user, + ClearMode mode) +{ + return NOT_SUPPORT; +} + +int32_t DBStoreMock::GetTaskCount() +{ + return 0; +} + +void DBStoreMock::SetGenCloudVersionCallback(const GenerateCloudVersionCallback &callback) +{ +} + +std::pair> DBStoreMock::GetCloudVersion(const std::string &device) +{ + return { NOT_SUPPORT, {} }; +} + +DBStatus DBStoreMock::SetCloudSyncConfig(const CloudSyncConfig &config) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::SetReceiveDataInterceptor(const DataInterceptor &interceptor) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::GetDeviceEntries(const std::string &device, std::vector &entries) const +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Sync(const DeviceSyncOption &option, + const std::function &)> &onComplete) +{ + std::map result; + for (const auto &device : option.devices) { + result[device] = OK; + } + onComplete(result); + return OK; +} + +DBStatus DBStoreMock::CancelSync(uint32_t syncId) +{ + return NOT_SUPPORT; +}; + +KvStoreNbDelegate::DatabaseStatus DBStoreMock::GetDatabaseStatus() const +{ + return {}; +} +} // namespace DistributedData +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/mock/db_store_mock.h b/datamgr_service/services/distributeddataservice/framework/test/mock/db_store_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..c9246a8c82c2a9f2dc66cdfe22089406ee87ba94 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/mock/db_store_mock.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2025 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_DB_STORE_MOCK_H +#define OHOS_DISTRIBUTEDDATA_SERVICE_TEST_DB_STORE_MOCK_H +#include "concurrent_map.h" +#include "kv_store_nb_delegate.h" +#include "store_types.h" +namespace OHOS { +namespace DistributedData { +class DBStoreMock : public DistributedDB::KvStoreNbDelegate { +public: + using DBStatus = DistributedDB::DBStatus; + DBStatus Reset(); + using Entry = DistributedDB::Entry; + using Key = DistributedDB::Key; + using Value = DistributedDB::Value; + using KvStoreResultSet = DistributedDB::KvStoreResultSet; + using Query = DistributedDB::Query; + using KvStoreNbPublishOnConflict = DistributedDB::KvStoreNbPublishOnConflict; + using KvStoreObserver = DistributedDB::KvStoreObserver; + using SyncMode = DistributedDB::SyncMode; + using PragmaCmd = DistributedDB::PragmaCmd; + using PragmaData = DistributedDB::PragmaData; + using CipherPassword = DistributedDB::CipherPassword; + using KvStoreNbConflictNotifier = DistributedDB::KvStoreNbConflictNotifier; + using SecurityOption = DistributedDB::SecurityOption; + using RemotePushFinishedNotifier = DistributedDB::RemotePushFinishedNotifier; + using PushDataInterceptor = DistributedDB::PushDataInterceptor; + using UpdateKeyCallback = DistributedDB::UpdateKeyCallback; + using WatermarkInfo = DistributedDB::WatermarkInfo; + using ClearMode = DistributedDB::ClearMode; + using DataBaseSchema = DistributedDB::DataBaseSchema; + using ICloudDb = DistributedDB::ICloudDb; + using CloudSyncOption = DistributedDB::CloudSyncOption; + using SyncProcessCallback = DistributedDB::SyncProcessCallback; + using GenerateCloudVersionCallback = DistributedDB::GenerateCloudVersionCallback; + using CloudSyncConfig = DistributedDB::CloudSyncConfig; + using DataInterceptor = DistributedDB::DataInterceptor; + using DeviceSyncOption = DistributedDB::DeviceSyncOption; + using DeviceSyncProcessCallback = DistributedDB::DeviceSyncProcessCallback; + DBStatus Get(const Key &key, Value &value) const override; + DBStatus GetEntries(const Key &keyPrefix, std::vector &entries) const override; + DBStatus GetEntries(const Key &keyPrefix, KvStoreResultSet *&resultSet) const override; + DBStatus GetEntries(const Query &query, std::vector &entries) const override; + DBStatus GetEntries(const Query &query, KvStoreResultSet *&resultSet) const override; + DBStatus GetCount(const Query &query, int &count) const override; + DBStatus CloseResultSet(KvStoreResultSet *&resultSet) override; + DBStatus Put(const Key &key, const Value &value) override; + DBStatus PutBatch(const std::vector &entries) override; + DBStatus DeleteBatch(const std::vector &keys) override; + DBStatus Delete(const Key &key) override; + DBStatus GetLocal(const Key &key, Value &value) const override; + DBStatus GetLocalEntries(const Key &keyPrefix, std::vector &entries) const override; + DBStatus PutLocal(const Key &key, const Value &value) override; + DBStatus DeleteLocal(const Key &key) override; + DBStatus PublishLocal(const Key &key, bool deleteLocal, bool updateTimestamp, + const KvStoreNbPublishOnConflict &onConflict) override; + DBStatus UnpublishToLocal(const Key &key, bool deletePublic, bool updateTimestamp) override; + DBStatus RegisterObserver(const Key &key, unsigned int mode, KvStoreObserver *observer) override; + DBStatus UnRegisterObserver(const KvStoreObserver *observer) override; + DBStatus RemoveDeviceData(const std::string &device) override; + std::string GetStoreId() const override; + DBStatus Sync(const std::vector &devices, SyncMode mode, + const std::function &)> &onComplete, bool wait) override; + DBStatus Pragma(PragmaCmd cmd, PragmaData ¶mData) override; + DBStatus SetConflictNotifier(int conflictType, const KvStoreNbConflictNotifier ¬ifier) override; + DBStatus Rekey(const CipherPassword &password) override; + DBStatus Export(const std::string &filePath, const CipherPassword &passwd, bool force) override; + DBStatus Import(const std::string &filePath, const CipherPassword &passwd, bool isNeedIntegrityCheck) override; + DBStatus StartTransaction() override; + DBStatus Commit() override; + DBStatus Rollback() override; + DBStatus PutLocalBatch(const std::vector &entries) override; + DBStatus DeleteLocalBatch(const std::vector &keys) override; + DBStatus GetSecurityOption(SecurityOption &option) const override; + DBStatus SetRemotePushFinishedNotify(const RemotePushFinishedNotifier ¬ifier) override; + DBStatus Sync(const std::vector &devices, SyncMode mode, + const std::function &)> &onComplete, const Query &query, + bool wait) override; + DBStatus CheckIntegrity() const override; + DBStatus SetEqualIdentifier(const std::string &identifier, const std::vector &targets) override; + DBStatus SetPushDataInterceptor(const PushDataInterceptor &interceptor) override; + DBStatus SubscribeRemoteQuery(const std::vector &devices, + const std::function &)> &onComplete, const Query &query, + bool wait) override; + DBStatus UnSubscribeRemoteQuery(const std::vector &devices, + const std::function &)> &onComplete, const Query &query, + bool wait) override; + DBStatus RemoveDeviceData() override; + DBStatus GetKeys(const Key &keyPrefix, std::vector &keys) const override; + size_t GetSyncDataSize(const std::string &device) const override; + DBStatus UpdateKey(const UpdateKeyCallback &callback) override; + std::pair GetWatermarkInfo(const std::string &device) override; + DBStatus Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) override; + DBStatus SetCloudDB(const std::map> &cloudDBs) override; + DBStatus SetCloudDbSchema(const std::map &schema) override; + DBStatus RemoveDeviceData(const std::string &device, ClearMode mode) override; + DBStatus RemoveDeviceData(const std::string &device, const std::string &user, ClearMode mode) override; + int32_t GetTaskCount() override; + void SetGenCloudVersionCallback(const GenerateCloudVersionCallback &callback) override; + std::pair> GetCloudVersion(const std::string &device) 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 Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) override; + DBStatus Sync(const DeviceSyncOption &option, + const std::function &)> &onComplete) override; + DBStatus CancelSync(uint32_t syncId) override; + DatabaseStatus GetDatabaseStatus() const override; +private: + static const uint32_t DEFAULT_SIZE = 0; + DBStatus Get(ConcurrentMap &store, const Key &key, Value &value) const; + DBStatus GetEntries(ConcurrentMap &store, const Key &keyPrefix, std::vector &entries) const; + DBStatus PutBatch(ConcurrentMap &store, const std::vector &entries); + DBStatus DeleteBatch(ConcurrentMap &store, const std::vector &keys); + mutable ConcurrentMap entries_; + mutable ConcurrentMap localEntries_; + mutable ConcurrentMap> observers_; +}; +} // namespace DistributedData +} // namespace OHOS +#endif // OHOS_DISTRIBUTEDDATA_SERVICE_TEST_DB_STORE_MOCK_H diff --git a/datamgr_service/services/distributeddataservice/framework/test/screen_manager_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/screen_manager_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..32156d370e178f356f49db8d292e7ae175d98264 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/screen_manager_test.cpp @@ -0,0 +1,52 @@ +///* +//* Copyright (c) 2025 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 "ScreenManagerTest" +//#include +// +//#include "screen/screen_manager.h" +// +//using namespace testing::ext; +//using namespace OHOS::DistributedData; +//namespace OHOS::Test { +//class ScreenManagerTest : public testing::Test { +//public: +// static void SetUpTestCase(void); +// static void TearDownTestCase(void){}; +// void SetUp(){}; +// void TearDown(){}; +//}; +// +//void ScreenManagerTest::SetUpTestCase() +//{ +// ScreenManager::GetInstance()->BindExecutor(nullptr); +//} +// +///** +//* @tc.name: IsLocked +//* @tc.desc: test IsLocked function +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: +//*/ +//HWTEST_F(ScreenManagerTest, IsLocked, TestSize.Level1) +//{ +// EXPECT_NO_FATAL_FAILURE(ScreenManager::GetInstance()->Subscribe(nullptr)); +// EXPECT_NO_FATAL_FAILURE(ScreenManager::GetInstance()->Unsubscribe(nullptr)); +// EXPECT_NO_FATAL_FAILURE(ScreenManager::GetInstance()->SubscribeScreenEvent()); +// EXPECT_NO_FATAL_FAILURE(ScreenManager::GetInstance()->UnsubscribeScreenEvent()); +// ASSERT_FALSE(ScreenManager::GetInstance()->IsLocked()); +//} +//} // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp index 14a00bf91a0266ec90bec59962ead12d0fd43a31..dd162affffcde7c7dd9b85c863639c3cb91a2db6 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp @@ -128,10 +128,15 @@ HWTEST_F(SerializableTest, GetNormalVal, TestSize.Level2) normal.value = -56; normal.isClear = true; normal.cols = {"adfasdfas"}; + auto json = normal.Marshall(); auto jstr = to_string(normal.Marshall()); Normal normal1; normal1.Unmarshall(jstr); ASSERT_TRUE(normal == normal1) << normal1.name; + ASSERT_FALSE(normal1.Unmarshall("")); + ASSERT_FALSE(normal1.Unmarshall("{")); + std::vector testVec = {"adfasdfas", "banana"}; + ASSERT_FALSE(json["cols"] == testVec); } /** @@ -314,4 +319,302 @@ HWTEST_F(SerializableTest, IsJson, TestSize.Level1) ASSERT_FALSE(Serializable::IsJson(str)); ASSERT_TRUE(Serializable::IsJson(jsonStr)); } + +/** +* @tc.name: ToJson_01 +* @tc.desc: to json. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, ToJson_01, TestSize.Level1) +{ + std::string jsonStr = "{\"key\":\"value\"}"; + Serializable::json result = Serializable::ToJson(jsonStr); + ASSERT_FALSE(result.is_discarded()); +} + +/** +* @tc.name: ToJson_02 +* @tc.desc: to json. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, ToJson_02, TestSize.Level1) +{ + std::string jsonStr = "invalid_json"; + Serializable::json result = Serializable::ToJson(jsonStr); + ASSERT_FALSE(result.is_discarded()); +} + +/** +* @tc.name: ToJson_03 +* @tc.desc: to json. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, ToJson_03, TestSize.Level1) +{ + std::string jsonStr = ""; + Serializable::json result = Serializable::ToJson(jsonStr); + ASSERT_TRUE(result.empty()); +} + +/** +* @tc.name: ToJson_04 +* @tc.desc: to json. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, ToJson_04, TestSize.Level1) +{ + std::string jsonStr = "{invalid_json}"; + Serializable::json result = Serializable::ToJson(jsonStr); + ASSERT_FALSE(result.is_discarded()); +} + +/** +* @tc.name: ToJson_05 +* @tc.desc: test string to json of value with numeric type. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, ToJson_05, TestSize.Level1) +{ + std::string jsonStr = "{\"key\": 10}"; + Serializable::json result = Serializable::ToJson(jsonStr); + uint64_t uint64Value; + bool ret = Serializable::GetValue(result, "key", uint64Value); + ASSERT_TRUE(ret); + + std::string jsonStr2 = "{\"key\": 10.0}"; + Serializable::json result2 = Serializable::ToJson(jsonStr2); + double doubleValue; + ret = Serializable::GetValue(result2, "key", doubleValue); + ASSERT_TRUE(ret); +} + +/** +* @tc.name: GetValueTest001 +* @tc.desc: Test to json when type not match. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, GetValueTest001, TestSize.Level1) +{ + std::string jsonStr = "{\"key\": 10}"; + Serializable::json result = Serializable::ToJson(jsonStr); + + std::string value; + bool ret = Serializable::GetValue(result, "key", value); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(result, "notExist", value); + ASSERT_FALSE(ret); + + std::string jsonStr2 = "{\"key\": \"str\"}"; + Serializable::json strResult = Serializable::ToJson(jsonStr2); + int32_t intValue; + ret = Serializable::GetValue(strResult, "key", intValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", intValue); + ASSERT_FALSE(ret); + + uint32_t uintValue; + ret = Serializable::GetValue(strResult, "key", uintValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", uintValue); + ASSERT_FALSE(ret); + + uint64_t uint64Value; + ret = Serializable::GetValue(strResult, "key", uint64Value); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", uint64Value); + ASSERT_FALSE(ret); + + int64_t int64Value; + ret = Serializable::GetValue(strResult, "key", int64Value); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", int64Value); + ASSERT_FALSE(ret); + + bool boolValue; + ret = Serializable::GetValue(strResult, "key", boolValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", boolValue); + ASSERT_FALSE(ret); + + double doubleValue; + ret = Serializable::GetValue(strResult, "key", doubleValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", doubleValue); + ASSERT_FALSE(ret); + + std::vector arrayValue; + ret = Serializable::GetValue(strResult, "key", arrayValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", arrayValue); + ASSERT_FALSE(ret); +} + +/** +* @tc.name: SetUintValue +* @tc.desc: set value with uint param. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, SetUintValue, TestSize.Level2) +{ + struct TestUint final : public Serializable { + public: + std::vector testBytes = { 0x01, 0x02, 0x03, 0x04 }; + bool Marshal(json &node) const override + { + SetValue(node[GET_NAME(testBytes)], testBytes); + return true; + } + + bool Unmarshal(const json &node) override + { + bool success = true; + success = GetValue(node, GET_NAME(testBytes), testBytes) && success; + return success; + } + + bool operator==(const TestUint &other) const + { + return testBytes == other.testBytes; + } + }; + + std::string jsonStr2 = "{\"key\": \"str\"}"; + Serializable::json strResult = Serializable::ToJson(jsonStr2); + TestUint serialValue; + bool ret = Serializable::GetValue(strResult, "key", serialValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", serialValue); + ASSERT_FALSE(ret); +} + +/** +* @tc.name: SetStringMapValue +* @tc.desc: set map value with string param. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, SetStringMapValue, TestSize.Level2) +{ + struct TestStringMap final : public Serializable { + public: + std::map testMap = { + {"name", "John"}, + {"email", "john@example.com"} + }; + bool Marshal(json &node) const override + { + SetValue(node[GET_NAME(testMap)], testMap); + return true; + } + bool Unmarshal(const json &node) override + { + GetValue(node, GET_NAME(testMap), testMap); + return true; + } + bool operator==(const TestStringMap &other) const + { + return testMap == other.testMap; + } + }; + + TestStringMap in; + in.testMap["name"] = "New York"; + in.testMap["email"] = "john@sample.com"; + auto json = to_string(in.Marshall()); + TestStringMap out; + out.Unmarshall(json); + ASSERT_TRUE(in == out); +} + +/** +* @tc.name: SetStringMapValue +* @tc.desc: set map value with int param. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, SetMapValue, TestSize.Level2) +{ + struct TestMap final : public Serializable { + public: + std::map testMap = { + {"id", 123456}, + {"version", 42} + }; + bool Marshal(json &node) const override + { + SetValue(node[GET_NAME(testMap)], testMap); + return true; + } + bool Unmarshal(const json &node) override + { + GetValue(node, GET_NAME(testMap), testMap); + return true; + } + bool operator==(const TestMap &other) const + { + return testMap == other.testMap; + } + }; + + TestMap in; + in.testMap["version"] = 552; + auto json = to_string(in.Marshall()); + TestMap out; + out.Unmarshall(json); + ASSERT_TRUE(in == out); +} + +/** +* @tc.name: BoundaryTest +* @tc.desc: test boundary. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, BoundaryTest, TestSize.Level1) +{ + struct TestBoundary : public Serializable { + int32_t int32Val; + uint32_t uint32Val; + int64_t int64Val; + uint64_t uint64Val; + bool Marshal(json &node) const override + { + SetValue(node[GET_NAME(int32Val)], int32Val); + SetValue(node[GET_NAME(uint32Val)], uint32Val); + SetValue(node[GET_NAME(int64Val)], int64Val); + SetValue(node[GET_NAME(uint64Val)], uint64Val); + return true; + } + bool Unmarshal(const json &node) override + { + bool success = true; + success = GetValue(node, GET_NAME(int32Val), int32Val) && success; + success = GetValue(node, GET_NAME(uint32Val), uint32Val) && success; + success = GetValue(node, GET_NAME(int64Val), int64Val) && success; + success = GetValue(node, GET_NAME(uint64Val), uint64Val) && success; + return success; + } + }; + TestBoundary in, out; + in.int32Val = INT32_MIN; + in.uint32Val = 0; + in.int64Val = INT64_MIN; + in.uint64Val = 0; + + auto json = to_string(in.Marshall()); + out.Unmarshall(json); + EXPECT_EQ(out.int32Val, in.int32Val); + EXPECT_EQ(out.uint32Val, in.uint32Val); + EXPECT_EQ(out.int64Val, in.int64Val); + EXPECT_EQ(out.uint64Val, in.uint64Val); + + in.int32Val = INT32_MAX; + in.uint32Val = UINT32_MAX; + in.int64Val = INT64_MAX; + in.uint64Val = UINT64_MAX; + + json = to_string(in.Marshall()); + out.Unmarshall(json); + EXPECT_EQ(out.int32Val, in.int32Val); + EXPECT_EQ(out.uint32Val, in.uint32Val); + EXPECT_EQ(out.int64Val, in.int64Val); + EXPECT_EQ(out.uint64Val, in.uint64Val); +} } // 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 7bc31f25e4a6de819cff4fdb9f756785ad325c62..304b19bd2156500761c1b963fe68753bfcd8a0b0 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/store_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/store_test.cpp @@ -260,4 +260,62 @@ HWTEST_F(AutoCacheTest, GetDBStore, TestSize.Level2) meta.area = GeneralStore::EL5; EXPECT_NE(AutoCache::GetInstance().GetDBStore(meta, watchers).first, GeneralError::E_SCREEN_LOCKED); } + +/** +* @tc.name: CloseStore001 +* @tc.desc: AutoCache CloseStore001 +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(AutoCacheTest, CloseStore001, TestSize.Level2) +{ + GeneralStoreMock* store = new (std::nothrow) GeneralStoreMock(); + ASSERT_NE(store, nullptr); + AutoCache::Watchers watchers; + mock_->isLocked_ = true; + StoreMetaData meta; + meta.area = GeneralStore::EL1; + meta.dataDir = ""; + uint32_t tokenId = 123; + AutoCache autoCache; + autoCache.stores_.Compute(tokenId, + [this, &meta, &watchers, &store](auto &, std::map &stores) -> bool { + std::string storeKey = "key"; + stores.emplace(std::piecewise_construct, std::forward_as_tuple(storeKey), + std::forward_as_tuple(store, watchers, 0, meta)); + return !stores.empty(); + }); + autoCache.CloseStore(tokenId, meta.dataDir); + EXPECT_TRUE(autoCache.stores_.Empty()); +} + +/** +* @tc.name: CloseStore002 +* @tc.desc: AutoCache CloseStore002 +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(AutoCacheTest, CloseStore002, TestSize.Level2) +{ + GeneralStoreMock* store = new (std::nothrow) GeneralStoreMock(); + ASSERT_NE(store, nullptr); + AutoCache::Watchers watchers; + mock_->isLocked_ = true; + StoreMetaData meta; + meta.area = GeneralStore::EL4; + meta.dataDir = ""; + uint32_t tokenId = 123; + AutoCache autoCache; + autoCache.stores_.Compute(tokenId, + [this, &meta, &watchers, &store](auto &, std::map &stores) -> bool { + std::string storeKey = "key"; + stores.emplace(std::piecewise_construct, std::forward_as_tuple(storeKey), + std::forward_as_tuple(store, watchers, 0, meta)); + return !stores.empty(); + }); + autoCache.CloseStore(tokenId, meta.dataDir); + EXPECT_FALSE(autoCache.stores_.Empty()); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/utils/anonymous.cpp b/datamgr_service/services/distributeddataservice/framework/utils/anonymous.cpp index 4a1d3d0dec1c59cf4a46d6cee7d984b1aef73475..de87b5b241c3ccd70f76c79170aa4122a4778e92 100644 --- a/datamgr_service/services/distributeddataservice/framework/utils/anonymous.cpp +++ b/datamgr_service/services/distributeddataservice/framework/utils/anonymous.cpp @@ -67,7 +67,7 @@ std::string Anonymous::Change(const std::string &name) noAlnum.push_back(""); } if (!noAlnumStr.empty()) { - noAlnum.push_back(alnumStr); + noAlnum.push_back(noAlnumStr); alnum.push_back(""); } std::string res = ""; diff --git a/datamgr_service/services/distributeddataservice/framework/utils/constant.cpp b/datamgr_service/services/distributeddataservice/framework/utils/constant.cpp index 6fedf3f619ba5780cdf8efc664fd0909a11082a9..f0b40f544ef88b25e23c66a4db758a5dbe1930a3 100644 --- a/datamgr_service/services/distributeddataservice/framework/utils/constant.cpp +++ b/datamgr_service/services/distributeddataservice/framework/utils/constant.cpp @@ -15,7 +15,6 @@ #define LOG_TAG "Constant" #include "utils/constant.h" #include -#include "log_print.h" #include "securec.h" namespace OHOS { diff --git a/datamgr_service/services/distributeddataservice/framework/utils/corrupt_reporter.cpp b/datamgr_service/services/distributeddataservice/framework/utils/corrupt_reporter.cpp index 405e29913f0cf2a8fa647b0fce97a18a1e17672e..065ab01031d518aa481b9be85636905fbda3348c 100644 --- a/datamgr_service/services/distributeddataservice/framework/utils/corrupt_reporter.cpp +++ b/datamgr_service/services/distributeddataservice/framework/utils/corrupt_reporter.cpp @@ -27,7 +27,7 @@ constexpr const char *DB_CORRUPTED_POSTFIX = ".corruptedflg"; bool CorruptReporter::CreateCorruptedFlag(const std::string &path, const std::string &dbName) { if (path.empty() || dbName.empty()) { - ZLOGW("The path or dbName is empty, path:%{public}s, dbName:%{public}s", path.c_str(), + ZLOGW("The path or dbName is empty, path:%{public}s, dbName:%{public}s", Anonymous::Change(path).c_str(), Anonymous::Change(dbName).c_str()); return false; } @@ -35,7 +35,7 @@ bool CorruptReporter::CreateCorruptedFlag(const std::string &path, const std::st if (access(flagFileName.c_str(), F_OK) == 0) { return true; } - int fd = creat(flagFileName.c_str(), S_IRWXU | S_IRWXG); + int fd = creat(flagFileName.c_str(), S_IRUSR | S_IWUSR); if (fd == -1) { ZLOGW("Create corrupted flag fail, flagFileName:%{public}s, errno:%{public}d", Anonymous::Change(flagFileName).c_str(), errno); @@ -48,7 +48,7 @@ bool CorruptReporter::CreateCorruptedFlag(const std::string &path, const std::st bool CorruptReporter::HasCorruptedFlag(const std::string &path, const std::string &dbName) { if (path.empty() || dbName.empty()) { - ZLOGW("The path or dbName is empty, path:%{public}s, dbName:%{public}s", path.c_str(), + ZLOGW("The path or dbName is empty, path:%{public}s, dbName:%{public}s", Anonymous::Change(path).c_str(), Anonymous::Change(dbName).c_str()); return false; } @@ -59,7 +59,7 @@ bool CorruptReporter::HasCorruptedFlag(const std::string &path, const std::strin bool CorruptReporter::DeleteCorruptedFlag(const std::string &path, const std::string &dbName) { if (path.empty() || dbName.empty()) { - ZLOGW("The path or dbName is empty, path:%{public}s, dbName:%{public}s", path.c_str(), + ZLOGW("The path or dbName is empty, path:%{public}s, dbName:%{public}s", Anonymous::Change(path).c_str(), Anonymous::Change(dbName).c_str()); return false; } diff --git a/datamgr_service/services/distributeddataservice/rust/connect_adapter/BUILD.gn b/datamgr_service/services/distributeddataservice/rust/connect_adapter/BUILD.gn index 292dc20036993e5a0d436432dc6c7d1660486548..49162568bd6ea279da85d11bdb65a87a02544d91 100644 --- a/datamgr_service/services/distributeddataservice/rust/connect_adapter/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/rust/connect_adapter/BUILD.gn @@ -34,14 +34,8 @@ ohos_shared_library("conn_adapter") { "src/connect_wrapper.cpp", ] configs = [ ":export_connect" ] - cflags = [ - "-Werror", - "-fstack-protector-strong", - ] - cflags_cc = [ - "-fvisibility=hidden", - "-fstack-protector-strong", - ] + cflags = [ "-Werror" ] + cflags_cc = [ "-fvisibility=hidden" ] external_deps = [ "ability_base:want", diff --git a/datamgr_service/services/distributeddataservice/rust/connect_adapter/src/connect.cpp b/datamgr_service/services/distributeddataservice/rust/connect_adapter/src/connect.cpp index a61a79391061865615b4aec39a4c44c59971665b..9ec682c1d0dcb28ebc7ed34f19ae3273736653ac 100644 --- a/datamgr_service/services/distributeddataservice/rust/connect_adapter/src/connect.cpp +++ b/datamgr_service/services/distributeddataservice/rust/connect_adapter/src/connect.cpp @@ -68,7 +68,6 @@ void Connect::WaitConnect() cv_.wait_for(lock, std::chrono::seconds(CONNECT_TIMEOUT), [this] { return flag_; }); - cv_.notify_one(); } namespace ConnectInner { diff --git a/datamgr_service/services/distributeddataservice/rust/extension/BUILD.gn b/datamgr_service/services/distributeddataservice/rust/extension/BUILD.gn index 6730b9901480520e8bdefdd101521f3f1c5b950c..92cd41b85f41bcd129e990eb91872c5131a85b49 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/rust/extension/BUILD.gn @@ -23,7 +23,6 @@ config("module_public_config") { visibility = [ ":*" ] include_dirs = [ "../../framework/include", - "${kv_store_common_path}", ] } @@ -47,13 +46,9 @@ ohos_shared_library("opencloudextension") { cflags = [ "-Werror", "-Wno-multichar", - "-fstack-protector-strong", ] - cflags_cc = [ - "-fvisibility=hidden", - "-fstack-protector-strong", - ] + cflags_cc = [ "-fvisibility=hidden" ] configs = [ ":module_public_config" ] @@ -66,8 +61,9 @@ ohos_shared_library("opencloudextension") { "access_token:libaccesstoken_sdk", "hilog:libhilog", "json:nlohmann_json_static", + "c_utils:utils", "kv_store:datamgr_common", ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" -} +} \ No newline at end of file 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 da137619bfc423220f73d0095506c8fc6b57fc59..3b042ba2418a717b6aa5889562af9b1e912a6f58 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.cpp +++ b/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.cpp @@ -119,7 +119,7 @@ int32_t CloudDbImpl::BatchDelete(const std::string &table, DBVBuckets &extends) return ExtensionUtil::ConvertStatus(status); } -std::shared_ptr CloudDbImpl::Query(const std::string &table, const DBVBucket &extend) +std::pair> CloudDbImpl::Query(const std::string &table, const DBVBucket &extend) { std::string cursor; auto it = extend.find(DistributedData::SchemaMeta::CURSOR_FIELD); @@ -134,7 +134,11 @@ std::shared_ptr CloudDbImpl::Query(const std::string &table, const DBV }; OhCloudExtCloudDbData *cloudData = nullptr; auto status = OhCloudExtCloudDbBatchQuery(database_, &info, &cloudData); - return (status == ERRNO_SUCCESS && cloudData != nullptr) ? std::make_shared(cloudData) : nullptr; + if (status == ERRNO_SUCCESS && cloudData != nullptr) { + return std::make_pair(DBErr::E_OK, std::make_shared(cloudData)); + } + return status != ERRNO_SUCCESS ? std::make_pair(ExtensionUtil::ConvertStatus(status), nullptr) + : std::make_pair(DBErr::E_ERROR, nullptr); } int32_t CloudDbImpl::Lock() 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 099bfaad0ddf004cbdee4b887f02f6a62eaafb12..5351ebbb9d4b5f0b4f8d32736ecd8fad8769e5b9 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.h +++ b/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.h @@ -36,7 +36,7 @@ public: 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, DBVBuckets &extends) override; - std::shared_ptr Query(const std::string &table, const DBVBucket &extend) override; + std::pair> Query(const std::string &table, const DBVBucket &extend) override; int32_t Lock() override; int32_t Heartbeat() override; int32_t Unlock() override; diff --git a/datamgr_service/services/distributeddataservice/rust/extension/cloud_server_impl.cpp b/datamgr_service/services/distributeddataservice/rust/extension/cloud_server_impl.cpp index f47a26209787b06c9b2dcd049f4cd8fee9cd9e11..e5413cff2de360b5e1bdd0f94f13aadce5d7c206 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/cloud_server_impl.cpp +++ b/datamgr_service/services/distributeddataservice/rust/extension/cloud_server_impl.cpp @@ -28,11 +28,19 @@ #include "utils/anonymous.h" namespace OHOS::CloudData { -__attribute__((used)) static bool g_isInit = - DistributedData::CloudServer::RegisterCloudInstance(new (std::nothrow) CloudServerImpl()); +__attribute__((used)) static bool g_isInit = CloudServerImpl::Init(); using namespace Security::AccessToken; using DBMetaMgr = DistributedData::MetaDataManager; using Anonymous = DistributedData::Anonymous; + +bool CloudServerImpl::Init() +{ + static CloudServerImpl cloudServerInstance; + static std::once_flag onceFlag; + std::call_once(onceFlag, [&]() { DistributedData::CloudServer::RegisterCloudInstance(&cloudServerInstance); }); + return true; +} + std::pair CloudServerImpl::GetServerInfo(int32_t userId, bool needSpaceInfo) { DBCloudInfo result; @@ -544,7 +552,7 @@ int32_t CloudServerImpl::Unsubscribe(int32_t userId, const std::mapsecond); + uint32_t subId = static_cast(std::atoi(it->second.c_str())); if (OhCloudExtVectorPush(relation, &subId, sizeof(uint32_t)) != ERRNO_SUCCESS) { return DBErr::E_ERROR; } diff --git a/datamgr_service/services/distributeddataservice/rust/extension/cloud_server_impl.h b/datamgr_service/services/distributeddataservice/rust/extension/cloud_server_impl.h index bd7c185e7818e31a7879fd31f1a5fedc4a39aba1..debb7aadf00458b4b9f687a8c43f3abbe698f6fb 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/cloud_server_impl.h +++ b/datamgr_service/services/distributeddataservice/rust/extension/cloud_server_impl.h @@ -36,6 +36,7 @@ using DBRelation = DBSub::Relation; using DBErr = DistributedData::GeneralError; class CloudServerImpl : public DistributedData::CloudServer { public: + static bool Init(); std::pair GetServerInfo(int32_t userId, bool needSpaceInfo) override; std::pair GetAppSchema(int32_t userId, const std::string &bundleName) override; int32_t Subscribe(int32_t userId, const std::map> &dbs) override; diff --git a/datamgr_service/services/distributeddataservice/rust/extension/extension_util.cpp b/datamgr_service/services/distributeddataservice/rust/extension/extension_util.cpp index 6c6a46543d14f9a5d816c595526208ee935578b3..5f232141c5ec9b662d7aa9a387883d42b31a6290 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/extension_util.cpp +++ b/datamgr_service/services/distributeddataservice/rust/extension/extension_util.cpp @@ -424,8 +424,23 @@ DBInfo ExtensionUtil::ConvertAppInfo(OhCloudExtAppInfo *appInfo) return info; } +bool ExtensionUtil::ContainNullChar(const std::string &path) +{ + uint32_t pathLength = path.length(); + const char *cStrPath = path.c_str(); + uint32_t cStrLength = strlen(cStrPath); + if (pathLength != cStrLength) { + ZLOGW("The string contains null characters."); + return true; + } + return false; +} + std::pair ExtensionUtil::Convert(const DBAsset &dbAsset) { + if (ContainNullChar(dbAsset.path) || ContainNullChar(dbAsset.uri)) { + return { nullptr, 0 }; + } OhCloudExtCloudAssetBuilder builder { .version = dbAsset.version, .status = ConvertAssetStatus(static_cast(dbAsset.status)), diff --git a/datamgr_service/services/distributeddataservice/rust/extension/extension_util.h b/datamgr_service/services/distributeddataservice/rust/extension/extension_util.h index 71465ede28cbd369cbefd0d77fbcb4e3716d4d91..fc422f520f6ae19df8b37ba88324a6984a9d8434 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/extension_util.h +++ b/datamgr_service/services/distributeddataservice/rust/extension/extension_util.h @@ -58,6 +58,7 @@ public: static std::pair Convert(const DBAssets &dbAssets); static std::pair Convert(const DBTable &dbTable); static OhCloudExtAssetStatus ConvertAssetStatus(DBAssetStatus status); + static bool ContainNullChar(const std::string &path); private: static void ConvertAssetLeft(OhCloudExtCloudAsset *asset, DBAsset &dbAsset); diff --git a/datamgr_service/services/distributeddataservice/rust/test/BUILD.gn b/datamgr_service/services/distributeddataservice/rust/test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..42c0923958e559020ff9ea82c5b07116c65a2dad --- /dev/null +++ b/datamgr_service/services/distributeddataservice/rust/test/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2025 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/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +module_output_path = "datamgr_service/datamgr_service/distributeddatafwk" + +############################################################################### +config("module_private_config") { + visibility = [ ":*" ] + include_dirs = [ + "../extension", + "../ylong_cloud_extension/include", + ] + + cflags = [ "-Werror" ] + defines = [ + "TEST_ON_DEVICE", + "OPENSSL_SUPPRESS_DEPRECATED", + ] +} + +ohos_unittest("ExtensionUtilTest") { + module_out_path = module_output_path + sources = [ + "../extension/extension_util.cpp", + "unittest/extension_util_test.cpp" + ] + + configs = [ ":module_private_config" ] + + deps = [ + "${data_service_path}/rust/extension:opencloudextension", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/rust/ylong_cloud_extension:ylong_cloud_extension", + ] + external_deps = [ + "hilog:libhilog", + "json:nlohmann_json_static", + "kv_store:datamgr_common", + ] + + part_name = "datamgr_service" +} + +############################################################################### + +group("unittest") { + testonly = true + deps = [] + + deps += [ + ":ExtensionUtilTest", + ] +} diff --git a/datamgr_service/services/distributeddataservice/rust/test/unittest/extension_util_test.cpp b/datamgr_service/services/distributeddataservice/rust/test/unittest/extension_util_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d01643b9fbcdcd09910645c4f5e266830014bbc3 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/rust/test/unittest/extension_util_test.cpp @@ -0,0 +1,196 @@ +/* +* Copyright (c) 2025 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 "extension_util.h" +#include + +using namespace testing::ext; +using namespace OHOS::CloudData; + +namespace OHOS::Test { +class ExtensionUtilTest : public testing::Test {}; + +/** +* @tc.name: Convert001 +* @tc.desc: Check that the character string does not contain null characters. +* @tc.type: FUNC +*/ +HWTEST_F(ExtensionUtilTest, Convert001, TestSize.Level1) +{ + DBAsset dbAsset; + dbAsset.version = 1; + dbAsset.status = DBAsset::STATUS_NORMAL; + dbAsset.expiresTime = 1234567890; + dbAsset.id = "12345"; + dbAsset.name = "test_asset"; + dbAsset.createTime = "2025-07-03T00:00:00Z"; + dbAsset.modifyTime = "2025-07-04T00:00:00Z"; + dbAsset.size = "1024"; + dbAsset.hash = "abc123"; + dbAsset.uri = "http://example.com/path/to/file"; + dbAsset.path = "/path/to/file"; + + auto [asset, assetLen] = ExtensionUtil::Convert(dbAsset); + EXPECT_NE(asset, nullptr); + EXPECT_GT(assetLen, 0); + delete asset; +} + +/** +* @tc.name: Convert002 +* @tc.desc: Check whether the path contains null characters. +* @tc.type: FUNC +*/ +HWTEST_F(ExtensionUtilTest, Convert002, TestSize.Level1) +{ + const char data[] = "/path\0/to/file"; + std::string path(data, 13); + DBAsset dbAsset; + dbAsset.version = 1; + dbAsset.status = DBAsset::STATUS_NORMAL; + dbAsset.expiresTime = 1234567890; + dbAsset.id = "12345"; + dbAsset.name = "test_asset"; + dbAsset.createTime = "2025-07-03T00:00:00Z"; + dbAsset.modifyTime = "2025-07-04T00:00:00Z"; + dbAsset.size = "1024"; + dbAsset.hash = "abc123"; + dbAsset.uri = "http://example.com/path/to/file"; + dbAsset.path = path; + + auto [asset, assetLen] = ExtensionUtil::Convert(dbAsset); + EXPECT_EQ(asset, nullptr); + EXPECT_EQ(assetLen, 0); +} + +/** +* @tc.name: Convert003 +* @tc.desc: Check whether the URI contains null characters. +* @tc.type: FUNC +*/ +HWTEST_F(ExtensionUtilTest, Convert003, TestSize.Level1) +{ + const char data[] = "http://example.com/path\0to/file"; + std::string uri(data, 32); + DBAsset dbAsset; + dbAsset.version = 1; + dbAsset.status = DBAsset::STATUS_NORMAL; + dbAsset.expiresTime = 1234567890; + dbAsset.id = "12345"; + dbAsset.name = "test_asset"; + dbAsset.createTime = "2025-07-03T00:00:00Z"; + dbAsset.modifyTime = "2025-07-04T00:00:00Z"; + dbAsset.size = "1024"; + dbAsset.hash = "abc123"; + dbAsset.uri = uri; + dbAsset.path = "/path/to/file"; + + auto [asset, assetLen] = ExtensionUtil::Convert(dbAsset); + EXPECT_EQ(asset, nullptr); + EXPECT_EQ(assetLen, 0); +} + +/** +* @tc.name: Convert004 +* @tc.desc: Check whether the path and URI contain null characters. +* @tc.type: FUNC +*/ +HWTEST_F(ExtensionUtilTest, Convert004, TestSize.Level1) +{ + const char data1[] = "http://example.com/path\0to/file"; + std::string uri(data1, 32); + const char data2[] = "/path\0/to/file"; + std::string path(data2, 13); + DBAsset dbAsset; + dbAsset.version = 1; + dbAsset.status = DBAsset::STATUS_NORMAL; + dbAsset.expiresTime = 1234567890; + dbAsset.id = "12345"; + dbAsset.name = "test_asset"; + dbAsset.createTime = "2025-07-03T00:00:00Z"; + dbAsset.modifyTime = "2025-07-04T00:00:00Z"; + dbAsset.size = "1024"; + dbAsset.hash = "abc123"; + dbAsset.uri = uri; + dbAsset.path = path; + + auto [asset, assetLen] = ExtensionUtil::Convert(dbAsset); + EXPECT_EQ(asset, nullptr); + EXPECT_EQ(assetLen, 0); +} + +/** +* @tc.name: ConvertVBuckets001 +* @tc.desc: Test that convert DBVBuckets to empty. +* @tc.type: FUNC +*/ +HWTEST_F(ExtensionUtilTest, ConvertVBuckets001, TestSize.Level1) +{ + DBVBuckets buckets; + auto [result, size] = ExtensionUtil::Convert(std::move(buckets)); + EXPECT_NE(result, nullptr); + EXPECT_EQ(size, 0); +} + +/** +* @tc.name: ConvertVBuckets002 +* @tc.desc: Test that convert function DBVBucket is DBAsset type. +* @tc.type: FUNC +*/ +HWTEST_F(ExtensionUtilTest, ConvertVBuckets002, TestSize.Level1) +{ + DBVBuckets buckets; + DBVBucket bucket; + DBAsset dbAsset; + bucket["dbAsset"] = dbAsset; + buckets.push_back(bucket); + auto [result, size] = ExtensionUtil::Convert(std::move(buckets)); + EXPECT_NE(result, nullptr); + EXPECT_GT(size, 0); +} + +/** +* @tc.name: ConvertVBuckets003 +* @tc.desc: Test that convert function DBVBucket is DBAssets type. +* @tc.type: FUNC +*/ +HWTEST_F(ExtensionUtilTest, ConvertVBuckets003, TestSize.Level1) +{ + DBVBuckets buckets; + DBVBucket bucket; + DBAssets dbAssets; + bucket["dbAsset"] = dbAssets; + buckets.push_back(bucket); + auto [result, size] = ExtensionUtil::Convert(std::move(buckets)); + EXPECT_NE(result, nullptr); + EXPECT_GT(size, 0); +} + +/** +* @tc.name: ConvertVBuckets004 +* @tc.desc: Test that convert function DBVBucket is str type. +* @tc.type: FUNC +*/ +HWTEST_F(ExtensionUtilTest, ConvertVBuckets004, TestSize.Level1) +{ + DBVBuckets buckets; + DBVBucket bucket; + std::string key = "123"; + bucket["dbAsset"] = key; + buckets.push_back(bucket); + auto [result, size] = ExtensionUtil::Convert(std::move(buckets)); + EXPECT_NE(result, nullptr); + EXPECT_GT(size, 0); +} +} // namespace OHOS::Test \ No newline at end of file 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 4ac4309e2d1eaddbf0913f5d67b31a297be5cb77..a49b928bd44b27967fc384bfea40a6ae28c7167c 100644 --- a/datamgr_service/services/distributeddataservice/rust/ylong_cloud_extension/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/rust/ylong_cloud_extension/BUILD.gn @@ -44,7 +44,7 @@ if (use_clang_coverage) { } else { ohos_rust_unittest("rust_ylong_cloud_ext_unit_test") { module_out_path = - "distributeddatamgr/datamgr_service/services/rust/ylong_cloud_extension" + "datamgr_service/datamgr_service/services/rust/ylong_cloud_extension" sources = [ "src/lib.rs" ] external_deps = [ diff --git a/datamgr_service/services/distributeddataservice/service/BUILD.gn b/datamgr_service/services/distributeddataservice/service/BUILD.gn index b07724a03e42decbc73e18be988b9abb8efffbe6..799699962afa099106f9e7689d8452ef1fc65e57 100644 --- a/datamgr_service/services/distributeddataservice/service/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/BUILD.gn @@ -35,17 +35,8 @@ config("module_public_config") { "${data_service_path}/adapter/include", "${data_service_path}/app/src", "${data_service_path}/framework/include", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_distributeddb_path}/include/", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/interfaces/include/relational", - ] - cflags = [ - "-Wno-c99-designator", - "-fstack-protector-strong", ] + cflags = [ "-Wno-c99-designator" ] } ohos_shared_library("distributeddatasvc") { @@ -66,15 +57,13 @@ ohos_shared_library("distributeddatasvc") { "-Oz", "-fdata-sections", "-ffunction-sections", - "-fstack-protector-strong", ] - ldflags = [ "-Wl,-z,relro,-z,now,--gc-sections" ] + ldflags = [ "-Wl,--gc-sections" ] cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] configs = [ ":module_public_config" ] @@ -83,13 +72,14 @@ ohos_shared_library("distributeddatasvc") { deps = [ "${data_service_path}/adapter/account:distributeddata_account", "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/adapter/dfx:distributeddata_dfx", + "${data_service_path}/adapter/network:distributeddata_network", "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/backup:distributeddata_backup", "${data_service_path}/service/bootstrap:distributeddata_bootstrap", "${data_service_path}/service/common:distributeddata_common", "${data_service_path}/service/config:distributeddata_config", - "${data_service_path}/service/crypto:distributeddata_crypto", "${data_service_path}/service/dumper:distributeddata_dumper", "${data_service_path}/service/matrix:distributeddata_matrix", "${data_service_path}/service/permission:distributeddata_permit", diff --git a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt index c0bfb2f79cf52bded1fe719c6e7b3ffc61da2d42..f72e4548038788c539f30a1720a4519a6d41eb74 100644 --- a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt @@ -12,6 +12,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=deprecated-declarations -Wno- 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") +add_definitions(-D__CJSON_USE_INT64) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/backup/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/cloud serviceSrc) @@ -19,7 +20,6 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/cloud/sync_strategies serviceSr aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/common serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/config/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/config/src/model serviceSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/crypto/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/rdb serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/kvdb serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/matrix/src serviceSrc) @@ -46,7 +46,6 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/permission/src serviceSrc) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/backup/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/config/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/common) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/crypto/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/permission/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/matrix/include) diff --git a/datamgr_service/services/distributeddataservice/service/backup/BUILD.gn b/datamgr_service/services/distributeddataservice/service/backup/BUILD.gn index 6a492ef4b405b505637a25cd066608423e44e4fd..194f7a03c6870b9d64cb079571339dfc2859d0fe 100644 --- a/datamgr_service/services/distributeddataservice/service/backup/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/backup/BUILD.gn @@ -32,7 +32,6 @@ ohos_source_set("distributeddata_backup") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ @@ -47,18 +46,17 @@ ohos_source_set("distributeddata_backup") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk", - "${data_service_path}/service/crypto:distributeddata_crypto", ] external_deps = [ "device_manager:devicemanagersdk", "hilog:libhilog", "json:nlohmann_json_static", + "c_utils:utils", "kv_store:datamgr_common", ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/service/backup/include/backup_manager.h b/datamgr_service/services/distributeddataservice/service/backup/include/backup_manager.h index 7600155987f4f6f0a45ed17739220d187c5a77d9..e394d4a80579b9fbfe29d23019e4969f248e4676 100644 --- a/datamgr_service/services/distributeddataservice/service/backup/include/backup_manager.h +++ b/datamgr_service/services/distributeddataservice/service/backup/include/backup_manager.h @@ -43,7 +43,7 @@ public: void BackSchedule(std::shared_ptr executors); void SetBackupParam(const BackupParam &backupParam); void RegisterExporter(int32_t type, Exporter exporter); - bool GetPassWord(const StoreMetaData &meta, std::vector &password); + std::vector GetPassWord(const StoreMetaData &meta); private: BackupManager(); 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 ddbb23191c54b71393cca01020ef6661f52c2945..8c96a953ed566640e57e1d6f5ae5f0d8a021a334 100644 --- a/datamgr_service/services/distributeddataservice/service/backup/src/backup_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/backup/src/backup_manager.cpp @@ -21,11 +21,13 @@ #include #include "backuprule/backup_rule_manager.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter.h" #include "directory/directory_manager.h" #include "log_print.h" #include "metadata/meta_data_manager.h" +#include "types.h" +#include "utils/anonymous.h" namespace OHOS::DistributedData { namespace { constexpr const int COPY_SIZE = 1024; @@ -128,30 +130,24 @@ void BackupManager::BackSchedule(std::shared_ptr executors) void BackupManager::DoBackup(const StoreMetaData &meta) { - bool result = false; - auto key = meta.GetSecretKey(); - auto backupKey = meta.GetBackupSecretKey(); - std::vector decryptKey; - SecretKeyMetaData secretKey; - if (MetaDataManager::GetInstance().LoadMeta(key, secretKey, true)) { - CryptoManager::GetInstance().Decrypt(meta, secretKey, decryptKey); - if (secretKey.area < 0) { - MetaDataManager::GetInstance().LoadMeta(key, secretKey, true); - } + if (exporters_[meta.storeType] == nullptr) { + return; } auto backupPath = DirectoryManager::GetInstance().GetStoreBackupPath(meta); std::string backupFullPath = backupPath + "/" + AUTO_BACKUP_NAME; - KeepData(backupFullPath); - if (exporters_[meta.storeType] != nullptr) { - exporters_[meta.storeType](meta, backupFullPath + BACKUP_TMP_POSTFIX, result); - } - if (result) { - SaveData(backupFullPath, backupKey, secretKey); - } else { + bool result = false; + exporters_[meta.storeType](meta, backupFullPath + BACKUP_TMP_POSTFIX, result); + if (!result) { CleanData(backupFullPath); + return; } - decryptKey.assign(decryptKey.size(), 0); + SecretKeyMetaData secretKey; + result = MetaDataManager::GetInstance().LoadMeta(meta.GetSecretKey(), secretKey, true); + if (meta.isEncrypt && !result) { + return; + } + SaveData(backupFullPath, meta.GetBackupSecretKey(), secretKey); } bool BackupManager::CanBackup() @@ -279,7 +275,8 @@ BackupManager::ClearType BackupManager::GetClearType(const StoreMetaData &meta) void BackupManager::CopyFile(const std::string &oldPath, const std::string &newPath, bool isCreate) { - std::fstream fin, fout; + std::fstream fin; + std::fstream fout; if (!IsFileExist(oldPath)) { return; } @@ -298,13 +295,22 @@ void BackupManager::CopyFile(const std::string &oldPath, const std::string &newP fout.close(); } -bool BackupManager::GetPassWord(const StoreMetaData &meta, std::vector &password) +std::vector BackupManager::GetPassWord(const StoreMetaData &meta) { SecretKeyMetaData secretKey; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetBackupSecretKey(), secretKey, true)) { - return false; + auto metaKey = meta.GetBackupSecretKey(); + if (!MetaDataManager::GetInstance().LoadMeta(metaKey, secretKey, true) || secretKey.sKey.empty()) { + return {}; + } + CryptoManager::CryptoParams decryptParams = { .area = secretKey.area, .userId = meta.user, + .nonce = secretKey.nonce }; + auto password = CryptoManager::GetInstance().Decrypt(secretKey.sKey, decryptParams); + if (password.empty()) { + return password; } - return CryptoManager::GetInstance().Decrypt(meta, secretKey, password); + // update secret key of area or nonce + CryptoManager::GetInstance().UpdateSecretMeta(password, meta, metaKey, secretKey); + return password; } bool BackupManager::IsFileExist(const std::string &path) @@ -324,7 +330,7 @@ bool BackupManager::RemoveFile(const std::string &path) return true; } if (remove(path.c_str()) != 0) { - ZLOGE("remove error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("remove error:%{public}d, path:%{public}s", errno, Anonymous::Change(path).c_str()); return false; } return true; diff --git a/datamgr_service/services/distributeddataservice/service/bootstrap/BUILD.gn b/datamgr_service/services/distributeddataservice/service/bootstrap/BUILD.gn index 70b1c24c0963d6bc0ce45e4867730faf441d255e..f79f3c0c186d439192925cd24b71a1346edb8870 100644 --- a/datamgr_service/services/distributeddataservice/service/bootstrap/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/bootstrap/BUILD.gn @@ -32,7 +32,6 @@ ohos_source_set("distributeddata_bootstrap") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ "${data_service_path}/service/config/include" ] @@ -44,19 +43,18 @@ ohos_source_set("distributeddata_bootstrap") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/backup:distributeddata_backup", "${data_service_path}/service/config:distributeddata_config", - "${data_service_path}/service/crypto:distributeddata_crypto", ] external_deps = [ "hilog:libhilog", "json:nlohmann_json_static", + "c_utils:utils", "kv_store:datamgr_common", ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/service/bootstrap/include/bootstrap.h b/datamgr_service/services/distributeddataservice/service/bootstrap/include/bootstrap.h index 852d3af312c6970ab2e716b45753566c515728d9..eaf7672446ef568faff65715ef6c64451097de04 100644 --- a/datamgr_service/services/distributeddataservice/service/bootstrap/include/bootstrap.h +++ b/datamgr_service/services/distributeddataservice/service/bootstrap/include/bootstrap.h @@ -33,6 +33,8 @@ public: API_EXPORT void LoadBackup(std::shared_ptr executors); API_EXPORT void LoadAppIdMappings(); API_EXPORT void LoadThread(); + API_EXPORT void LoadDeviceSyncAppWhiteLists(); + API_EXPORT void LoadSyncTrustedApp(); private: static constexpr const char *DEFAULT_LABEL = "distributeddata"; static constexpr const char *DEFAULT_META = "service_meta"; @@ -40,4 +42,4 @@ private: }; } // namespace DistributedData } // namespace OHOS -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_BOOTSTRAP_BOOTSTRAP_H +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_BOOTSTRAP_BOOTSTRAP_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp b/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp index 1752431c82e88abffce834fb70174663ad173d4d..106363c184ef1411ddb50a9513a811abe7538f7c 100644 --- a/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp +++ b/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp @@ -17,12 +17,14 @@ #include +#include "access_check/app_access_check_config_manager.h" #include "app_id_mapping/app_id_mapping_config_manager.h" #include "backup_manager.h" #include "backuprule/backup_rule_manager.h" #include "checker/checker_manager.h" #include "cloud/cloud_config_manager.h" #include "config_factory.h" +#include "device_sync_app/device_sync_app_manager.h" #include "directory/directory_manager.h" #include "log_print.h" #include "thread/thread_manager.h" @@ -154,7 +156,12 @@ void Bootstrap::LoadDirectory() for (size_t i = 0; i < config->strategy.size(); ++i) { strategies[i] = config->strategy[i]; } - DirectoryManager::GetInstance().Initialize(strategies); + auto typeSize = config->storeTypes.size(); + std::vector storeTypes(typeSize); + for (size_t i = 0; i < typeSize; ++i) { + storeTypes[i] = config->storeTypes[i]; + } + DirectoryManager::GetInstance().Initialize(strategies, storeTypes); } void Bootstrap::LoadCloud() @@ -191,5 +198,31 @@ void Bootstrap::LoadThread() } ThreadManager::GetInstance().Initialize(config->minThreadNum, config->maxThreadNum, config->ipcThreadNum); } + +void Bootstrap::LoadDeviceSyncAppWhiteLists() +{ + auto *deviceSyncAppWhiteLists = ConfigFactory::GetInstance().GetDeviceSyncAppWhiteListConfig(); + if (deviceSyncAppWhiteLists == nullptr) { + return; + } + std::vector infos; + for (const auto &info : deviceSyncAppWhiteLists->whiteLists) { + infos.push_back({ info.appId, info.bundleName, info.version }); + } + DeviceSyncAppManager::GetInstance().Initialize(infos); +} + +void Bootstrap::LoadSyncTrustedApp() +{ + auto *config = ConfigFactory::GetInstance().GetSyncAppsConfig(); + if (config == nullptr) { + return; + } + std::vector infos; + for (const auto &info : config->trusts) { + infos.push_back({ info.bundleName, info.appId }); + } + AppAccessCheckConfigManager::GetInstance().Initialize(infos); +} } // namespace DistributedData -} // namespace OHOS +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/BUILD.gn b/datamgr_service/services/distributeddataservice/service/cloud/BUILD.gn index 3c592276db1dd2dca0cd9f9eed6053c0c244da19..1b874d23ae0d6ab7a22d91b0f3ec4c305adefa5d 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/cloud/BUILD.gn @@ -28,6 +28,7 @@ ohos_source_set("distributeddata_cloud") { } sources = [ "cloud_data_translate.cpp", + "cloud_notifier_proxy.cpp", "cloud_service_impl.cpp", "cloud_service_stub.cpp", "cloud_types_util.cpp", @@ -39,7 +40,6 @@ ohos_source_set("distributeddata_cloud") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ @@ -60,11 +60,9 @@ ohos_source_set("distributeddata_cloud") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ - "${data_service_path}/adapter/network:distributeddata_network", "${data_service_path}/adapter/schema_helper:distributeddata_schema_helper", ] @@ -72,6 +70,8 @@ ohos_source_set("distributeddata_cloud") { "access_token:libtokenid_sdk", "device_manager:devicemanagersdk", "hicollie:libhicollie", + "hilog:libhilog", + "ipc:ipc_single", "json:nlohmann_json_static", "kv_store:datamgr_common", "kv_store:distributeddb", diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_data_translate.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_data_translate.cpp index 80762e38753201781258eb3e455a9b9b3f4f2c19..b1e0983fe70b82a4dc7c03ddca301a061bb64a7b 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_data_translate.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_data_translate.cpp @@ -50,7 +50,7 @@ std::vector RdbCloudDataTranslate::AssetsToBlob(const Assets &assets) auto magicU8 = reinterpret_cast(const_cast(&leMagic)); rawData.insert(rawData.end(), magicU8, magicU8 + sizeof(ASSETS_MAGIC)); rawData.insert(rawData.end(), reinterpret_cast(&num), reinterpret_cast(&num) + sizeof(num)); - for (auto &asset : assets) { + for (const auto &asset : assets) { auto data = AssetToBlob(asset); rawData.insert(rawData.end(), data.begin(), data.end()); } diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_notifier_proxy.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_notifier_proxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0eb531b28b06eb57caae303d3195ee347539b5c9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_notifier_proxy.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025 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 "CloudNotifierProxy" + +#include "cloud_notifier_proxy.h" + +#include "cloud_service.h" +#include "itypes_util.h" +#include "log_print.h" +#include "utils/anonymous.h" + +namespace OHOS::CloudData { +using namespace DistributedRdb; +using NotifierCode = RelationalStore::ICloudNotifierInterfaceCode; + +CloudNotifierProxy::CloudNotifierProxy(const sptr &object) + : IRemoteProxy(object) +{} + +CloudNotifierProxy::~CloudNotifierProxy() noexcept {} + +int32_t CloudNotifierProxy::OnComplete(uint32_t seqNum, DistributedRdb::Details &&result) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor())) { + ZLOGE("write descriptor failed"); + return CloudService::IPC_PARCEL_ERROR; + } + if (!ITypesUtil::Marshal(data, seqNum, result)) { + return CloudService::IPC_PARCEL_ERROR; + } + + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + auto remote = Remote(); + if (remote == nullptr) { + ZLOGE("get remote failed, seqNum:%{public}u", seqNum); + return CloudService::IPC_ERROR; + } + auto status = remote->SendRequest(static_cast(NotifierCode::CLOUD_NOTIFIER_CMD_SYNC_COMPLETE), + data, reply, option); + if (status != CloudService::SUCCESS) { + ZLOGE("seqNum:%{public}u, send request failed, status:%{public}d", seqNum, status); + } + return status; +} +} // namespace OHOS::CloudData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_notifier_proxy.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_notifier_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..64a361dd195b43fc3731cabd0c5b28e2f0738377 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_notifier_proxy.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 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_CLOUD_CLOUD_NOTIFIER_PROXY_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_NOTIFIER_PROXY_H + +#include +#include + +#include "cloud_notifier.h" + +namespace OHOS::CloudData { +class CloudNotifierProxyBroker : public ICloudNotifier, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.CloudData.ICloudNotifier"); +}; + +class CloudNotifierProxy : public IRemoteProxy { +public: + explicit CloudNotifierProxy(const sptr& object); + virtual ~CloudNotifierProxy() noexcept; + + int32_t OnComplete(uint32_t seqNum, DistributedRdb::Details &&result) override; + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace OHOS::CloudData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_NOTIFIER_PROXY_H 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 88c7aa99ba93dcf6882220a51422ab7ee38afc99..3179ab11376288d127fe3f4e7c81c42f98aaa90b 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -23,6 +23,7 @@ #include "accesstoken_kit.h" #include "account/account_delegate.h" #include "checker/checker_manager.h" +#include "cloud/change_event.h" #include "cloud/cloud_last_sync_info.h" #include "cloud/cloud_mark.h" #include "cloud/cloud_server.h" @@ -33,25 +34,26 @@ #include "cloud_value_util.h" #include "device_manager_adapter.h" #include "dfx/radar_reporter.h" +#include "dfx/reporter.h" #include "eventcenter/event_center.h" +#include "get_schema_helper.h" #include "hap_token_info.h" #include "ipc_skeleton.h" #include "log_print.h" #include "metadata/meta_data_manager.h" +#include "metadata/store_meta_data.h" #include "network/network_delegate.h" #include "rdb_types.h" -#include "dfx/reporter.h" #include "relational_store_manager.h" #include "runtime_config.h" -#include "schema_helper/get_schema_helper.h" #include "store/auto_cache.h" #include "sync_manager.h" #include "sync_strategies/network_sync_strategy.h" #include "utils/anonymous.h" +#include "utils/constant.h" #include "values_bucket.h" #include "xcollie.h" - namespace OHOS::CloudData { using namespace DistributedData; using namespace std::chrono; @@ -66,12 +68,14 @@ static constexpr const char *FT_ENABLE_CLOUD = "ENABLE_CLOUD"; static constexpr const char *FT_DISABLE_CLOUD = "DISABLE_CLOUD"; static constexpr const char *FT_SWITCH_ON = "SWITCH_ON"; static constexpr const char *FT_SWITCH_OFF = "SWITCH_OFF"; +static constexpr const char *FT_CLOUD_CLEAN = "CLOUD_CLEAN"; static constexpr const char *FT_QUERY_INFO = "QUERY_SYNC_INFO"; static constexpr const char *FT_USER_CHANGE = "USER_CHANGE"; static constexpr const char *FT_USER_UNLOCK = "USER_UNLOCK"; static constexpr const char *FT_NETWORK_RECOVERY = "NETWORK_RECOVERY"; static constexpr const char *FT_SERVICE_INIT = "SERVICE_INIT"; static constexpr const char *FT_SYNC_TASK = "SYNC_TASK"; +static constexpr const char *FT_ENCRYPT_CHANGED = "ENCRYPT_CHANGED"; static constexpr const char *CLOUD_SCHEMA = "arkdata/cloud/cloud_schema.json"; __attribute__((used)) CloudServiceImpl::Factory CloudServiceImpl::factory_; const CloudServiceImpl::SaveStrategy CloudServiceImpl::STRATEGY_SAVERS[Strategy::STRATEGY_BUTT] = { @@ -246,6 +250,7 @@ int32_t CloudServiceImpl::DoClean(const CloudInfo &cloudInfo, const std::map(CloudEvent::CLEAN_DATA, storeInfo)); + storeInfo.path = meta.dataDir; + if (action != GeneralStore::CLEAN_WATER) { + EventCenter::GetInstance().PostEvent(std::make_unique(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()); + Report(FT_CLOUD_CLEAN, Fault::CSF_GS_CLOUD_CLEAN, meta.bundleName, "Clean:" + std::to_string(status) + + ", storeId=" + meta.GetStoreAlias() + ", action=" + std::to_string(action)); } else { ZLOGD("clean success, user:%{public}d, bundleName:%{public}s, storeId:%{public}s", static_cast(user), meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); @@ -290,20 +300,24 @@ void CloudServiceImpl::DoClean(int32_t user, const SchemaMeta &schemaMeta, int32 bool CloudServiceImpl::GetStoreMetaData(StoreMetaData &meta) { - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { - if (meta.user == "0") { - ZLOGE("failed, no store meta bundleName:%{public}s, storeId:%{public}s, user = %{public}s", - meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), meta.user.c_str()); - return false; - } - meta.user = "0"; - StoreMetaDataLocal localMeta; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMeta, true) || - !localMeta.isPublic || !MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { - ZLOGE("meta empty, not public store. bundleName:%{public}s, storeId:%{public}s, user = %{public}s", - meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), meta.user.c_str()); - return false; - } + StoreMetaMapping metaMapping(meta); + meta.dataDir = SyncManager::GetPath(meta); + if (!meta.dataDir.empty() && MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + return true; + } + meta.user = "0"; // check if it is a public store + meta.dataDir = SyncManager::GetPath(meta); + + if (meta.dataDir.empty() || !MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + ZLOGE("failed, no store meta. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return false; + } + StoreMetaDataLocal localMetaData; + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMetaData, true) || !localMetaData.isPublic) { + ZLOGE("meta empty, not public store. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return false; } return true; } @@ -315,16 +329,21 @@ int32_t CloudServiceImpl::Clean(const std::string &id, const std::map(cloudInfo.user)); + Report(FT_CLOUD_CLEAN, Fault::CSF_GS_CLOUD_CLEAN, "", + "get cloud info from meta failed=" + std::to_string(status)); return ERROR; } if (id != cloudInfo.id) { ZLOGE("different id, [server] id:%{public}s, [meta] id:%{public}s", Anonymous::Change(cloudInfo.id).c_str(), Anonymous::Change(id).c_str()); + Report(FT_CLOUD_CLEAN, Fault::CSF_GS_CLOUD_CLEAN, "", + "different id, new:" + Anonymous::Change(id) + ", old:" + Anonymous::Change(cloudInfo.id)); return ERROR; } auto dbActions = ConvertAction(actions); if (dbActions.empty()) { ZLOGE("invalid actions. id:%{public}s", Anonymous::Change(cloudInfo.id).c_str()); + Report(FT_CLOUD_CLEAN, Fault::CSF_GS_CLOUD_CLEAN, "", "convert action failed"); return ERROR; } return DoClean(cloudInfo, dbActions); @@ -489,21 +508,25 @@ std::map CloudServiceImpl::ExecuteStatistics(const { std::map result; for (auto &database : schemaMeta.databases) { - if (storeId.empty() || database.alias == storeId) { - StoreMetaData meta; - meta.bundleName = schemaMeta.bundleName; - meta.storeId = database.name; - meta.user = std::to_string(cloudInfo.user); - meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - auto it = cloudInfo.apps.find(schemaMeta.bundleName); - if (it == cloudInfo.apps.end()) { - ZLOGE("bundleName:%{public}s is not exist", schemaMeta.bundleName.c_str()); - break; - } - meta.instanceId = it->second.instanceId; - MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true); - result.insert_or_assign(database.alias, QueryStatistics(meta, database)); + if (!storeId.empty() && database.alias != storeId) { + continue; + } + auto it = cloudInfo.apps.find(schemaMeta.bundleName); + if (it == cloudInfo.apps.end()) { + ZLOGE("bundleName:%{public}s is not exist", schemaMeta.bundleName.c_str()); + break; + } + StoreMetaMapping meta; + meta.bundleName = schemaMeta.bundleName; + meta.storeId = database.name; + meta.user = std::to_string(cloudInfo.user); + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta.instanceId = it->second.instanceId; + MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true); + if (!meta.cloudPath.empty() && meta.cloudPath != meta.dataDir) { + MetaDataManager::GetInstance().LoadMeta(meta.GetCloudStoreMetaKey(), meta, true); } + result.insert_or_assign(database.alias, QueryStatistics(meta, database)); } return result; } @@ -668,12 +691,17 @@ std::pair CloudServiceImpl::QueryLastSyncInfo(const s int32_t CloudServiceImpl::OnInitialize() { XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY); - NetworkDelegate::GetInstance()->RegOnNetworkChange(); DistributedDB::RuntimeConfig::SetCloudTranslate(std::make_shared()); - Execute(GenTask(0, 0, CloudSyncScene::SERVICE_INIT, - { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_DO_CLOUD_SYNC, WORK_SUB })); std::vector users; Account::GetInstance()->QueryUsers(users); + for (auto user : users) { + if (user == DEFAULT_USER) { + continue; + } + CleanWaterVersion(user); + } + Execute(GenTask(0, 0, CloudSyncScene::SERVICE_INIT, + { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_DO_CLOUD_SYNC, WORK_SUB })); for (auto user : users) { if (user == DEFAULT_USER) { continue; @@ -688,6 +716,35 @@ int32_t CloudServiceImpl::OnInitialize() return E_OK; } +bool CloudServiceImpl::CleanWaterVersion(int32_t user) +{ + auto [status, cloudInfo] = GetCloudInfoFromMeta(user); + if (status != SUCCESS) { + return false; + } + auto stores = CheckerManager::GetInstance().GetDynamicStores(); + auto staticStores = CheckerManager::GetInstance().GetStaticStores(); + stores.insert(stores.end(), staticStores.begin(), staticStores.end()); + auto keys = cloudInfo.GetSchemaKey(); + for (const auto &[bundle, key] : keys) { + SchemaMeta schemaMeta; + if (MetaDataManager::GetInstance().LoadMeta(key, schemaMeta, true) && + schemaMeta.metaVersion < SchemaMeta::CLEAN_WATER_VERSION) { + bool found = std::any_of(stores.begin(), stores.end(), + [&schemaMeta](const CheckerManager::StoreInfo &storeInfo) { + return storeInfo.bundleName == schemaMeta.bundleName; + }); + if (!found) { + continue; + } + DoClean(user, schemaMeta, GeneralStore::CleanMode::CLEAN_WATER); + schemaMeta.metaVersion = SchemaMeta::CLEAN_WATER_VERSION; + } + MetaDataManager::GetInstance().SaveMeta(key, schemaMeta, true); + } + return true; +} + int32_t CloudServiceImpl::OnBind(const BindInfo &info) { if (executor_ != nullptr || info.executors == nullptr) { @@ -735,6 +792,10 @@ int32_t CloudServiceImpl::OnReady(const std::string &device) if (device != DeviceManagerAdapter::CLOUD_DEVICE_UUID) { return SUCCESS; } + if (!Account::GetInstance()->IsLoginAccount()) { + ZLOGW("current user is not logged in."); + return E_NOT_LOGIN; + } std::vector users; Account::GetInstance()->QueryForegroundUsers(users); if (users.empty()) { @@ -792,7 +853,8 @@ std::pair CloudServiceImpl::GetCloudInfoFromServer(int32_t u ZLOGD("cloud server is nullptr, user:%{public}d", userId); return { SERVER_UNAVAILABLE, cloudInfo }; } - return instance->GetServerInfo(cloudInfo.user, false); + auto [code, info] = instance->GetServerInfo(cloudInfo.user, false); + return { code != E_OK ? code : info.IsValid() ? E_OK : E_ERROR, info }; } int32_t CloudServiceImpl::UpdateCloudInfoFromServer(int32_t user) @@ -832,6 +894,8 @@ bool CloudServiceImpl::UpdateCloudInfo(int32_t user, CloudSyncScene scene) actions[bundle] = GeneralStore::CleanMode::CLOUD_INFO; } DoClean(oldInfo, actions); + Report(GetDfxFaultType(scene), Fault::CSF_CLOUD_INFO, "", + "Clean: different id, new:" + Anonymous::Change(cloudInfo.id) + ", old:" + Anonymous::Change(oldInfo.id)); } return true; } @@ -875,6 +939,54 @@ bool CloudServiceImpl::UpdateSchema(int32_t user, CloudSyncScene scene) return true; } +/** +* Will be called when 'cloudDriver' OnAppUpdate/OnAppInstall to get the newest 'e2eeEnable'. +*/ +int32_t CloudServiceImpl::UpdateSchemaFromServer(int32_t user) +{ + auto [status, cloudInfo] = GetCloudInfo(user); + if (status != SUCCESS) { + ZLOGW("get cloud info failed, user:%{public}d, status:%{public}d", user, status); + return status; + } + return UpdateSchemaFromServer(cloudInfo, user); +} + +int32_t CloudServiceImpl::UpdateSchemaFromServer(const CloudInfo &cloudInfo, int32_t user) +{ + auto keys = cloudInfo.GetSchemaKey(); + for (const auto &[bundle, key] : keys) { + auto [status, schemaMeta] = GetAppSchemaFromServer(user, bundle); + if (status == NOT_SUPPORT) { + ZLOGW("app not support, del cloudInfo! user:%{public}d, bundleName:%{public}s", user, bundle.c_str()); + MetaDataManager::GetInstance().DelMeta(cloudInfo.GetKey(), true); + return status; + } + if (status != SUCCESS) { + continue; + } + UpdateE2eeEnable(key, schemaMeta.e2eeEnable, bundle); + } + return SUCCESS; +} + +void CloudServiceImpl::UpdateE2eeEnable(const std::string &schemaKey, bool newE2eeEnable, + const std::string &bundleName) +{ + SchemaMeta oldMeta; + if (!MetaDataManager::GetInstance().LoadMeta(schemaKey, oldMeta, true)) { + return; + } + if (oldMeta.e2eeEnable == newE2eeEnable) { + return; + } + ZLOGI("Update e2eeEnable: %{public}d->%{public}d", oldMeta.e2eeEnable, newE2eeEnable); + Report(FT_ENCRYPT_CHANGED, Fault::CSF_APP_SCHEMA, bundleName, + "oldE2eeEnable=" + std::to_string(oldMeta.e2eeEnable) + ",newE2eeEnable=" + std::to_string(newE2eeEnable)); + oldMeta.e2eeEnable = newE2eeEnable; + MetaDataManager::GetInstance().SaveMeta(schemaKey, oldMeta, true); +} + std::pair CloudServiceImpl::GetAppSchemaFromServer(int32_t user, const std::string &bundleName) { SchemaMeta schemaMeta; @@ -1032,6 +1144,9 @@ int32_t CloudServiceImpl::CloudStatic::OnAppUninstall(const std::string &bundleN int32_t CloudServiceImpl::CloudStatic::OnAppInstall(const std::string &bundleName, int32_t user, int32_t index) { ZLOGI("bundleName:%{public}s,user:%{public}d,instanceId:%{public}d", bundleName.c_str(), user, index); + if (CloudDriverCheck(bundleName, user)) { + return SUCCESS; + } auto ret = UpdateCloudInfoFromServer(user); if (ret == E_OK) { StoreInfo info{.bundleName = bundleName, .instanceId = index, .user = user}; @@ -1043,11 +1158,29 @@ int32_t CloudServiceImpl::CloudStatic::OnAppInstall(const std::string &bundleNam int32_t CloudServiceImpl::CloudStatic::OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index) { ZLOGI("bundleName:%{public}s,user:%{public}d,instanceId:%{public}d", bundleName.c_str(), user, index); + if (CloudDriverCheck(bundleName, user)) { + return SUCCESS; + } HapInfo hapInfo{ .user = user, .instIndex = index, .bundleName = bundleName }; Execute([this, hapInfo]() { UpdateSchemaFromHap(hapInfo); }); return SUCCESS; } +bool CloudServiceImpl::CloudStatic::CloudDriverCheck(const std::string &bundleName, int32_t user) +{ + auto instance = CloudServer::GetInstance(); + if (instance == nullptr) { + return false; + } + if (instance->CloudDriverUpdated(bundleName)) { + // cloudDriver install, update schema(for update 'e2eeEnable') + ZLOGI("cloud driver check valid, bundleName:%{public}s, user:%{public}d", bundleName.c_str(), user); + Execute([this, user]() { UpdateSchemaFromServer(user); }); + return true; + } + return false; +} + int32_t CloudServiceImpl::UpdateSchemaFromHap(const HapInfo &hapInfo) { auto [status, cloudInfo] = GetCloudInfoFromMeta(hapInfo.user); @@ -1127,7 +1260,11 @@ void CloudServiceImpl::GetSchema(const Event &event) storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.instanceId); if (storeInfo.user == 0) { std::vector users; - AccountDelegate::GetInstance()->QueryUsers(users); + auto ret = AccountDelegate::GetInstance()->QueryUsers(users); + if (!ret || users.empty()) { + ZLOGE("failed to query os accounts, ret:%{public}d", ret); + return; + } GetSchemaMeta(users[0], storeInfo.bundleName, storeInfo.instanceId); } else { GetSchemaMeta(storeInfo.user, storeInfo.bundleName, storeInfo.instanceId); @@ -1169,9 +1306,15 @@ void CloudServiceImpl::DoSync(const Event &event) std::pair> CloudServiceImpl::PreShare( const StoreInfo &storeInfo, GenQuery &query) { - StoreMetaData meta(storeInfo); + StoreMetaMapping meta(storeInfo); meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + ZLOGE("failed, no store mapping bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return { GeneralError::E_ERROR, nullptr }; + } + if (!meta.cloudPath.empty() && meta.dataDir != meta.cloudPath && + !MetaDataManager::GetInstance().LoadMeta(meta.GetCloudStoreMetaKey(), meta, true)) { ZLOGE("failed, no store meta bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); return { GeneralError::E_ERROR, nullptr }; @@ -1195,6 +1338,76 @@ bool CloudServiceImpl::ReleaseUserInfo(int32_t user, CloudSyncScene scene) return true; } +int32_t CloudServiceImpl::InitNotifier(sptr notifier) +{ + if (notifier == nullptr) { + ZLOGE("no notifier."); + return INVALID_ARGUMENT; + } + auto notifierProxy = iface_cast(notifier); + uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.Compute(tokenId, [notifierProxy](auto, SyncAgent &agent) { + agent = SyncAgent(); + agent.notifier_ = notifierProxy; + return true; + }); + return SUCCESS; +} + +Details CloudServiceImpl::HandleGenDetails(const GenDetails &details) +{ + Details dbDetails; + for (const auto& [id, detail] : details) { + auto &dbDetail = dbDetails[id]; + dbDetail.progress = detail.progress; + dbDetail.code = detail.code; + for (auto &[name, table] : detail.details) { + auto &dbTable = dbDetail.details[name]; + Constant::Copy(&dbTable, &table); + } + } + return dbDetails; +} + +void CloudServiceImpl::OnAsyncComplete(uint32_t tokenId, uint32_t seqNum, Details &&result) +{ + ZLOGI("tokenId=%{public}x, seqnum=%{public}u", tokenId, seqNum); + sptr notifier = nullptr; + syncAgents_.ComputeIfPresent(tokenId, [¬ifier](auto, SyncAgent &syncAgent) { + notifier = syncAgent.notifier_; + return true; + }); + if (notifier != nullptr) { + notifier->OnComplete(seqNum, std::move(result)); + } +} + +int32_t CloudServiceImpl::CloudSync(const std::string &bundleName, const std::string &storeId, + const Option &option, const AsyncDetail &async) +{ + if (option.syncMode < DistributedData::GeneralStore::CLOUD_BEGIN || + option.syncMode >= DistributedData::GeneralStore::CLOUD_END) { + ZLOGE("not support cloud sync, syncMode = %{public}d", option.syncMode); + return INVALID_ARGUMENT; + } + StoreInfo storeInfo; + storeInfo.bundleName = bundleName; + storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); + storeInfo.user = AccountDelegate::GetInstance()->GetUserByToken(storeInfo.tokenId); + storeInfo.storeName = storeId; + GenAsync asyncCallback = + [this, tokenId = storeInfo.tokenId, seqNum = option.seqNum](const GenDetails &result) mutable { + OnAsyncComplete(tokenId, seqNum, HandleGenDetails(result)); + }; + auto highMode = GeneralStore::MANUAL_SYNC_MODE; + auto mixMode = static_cast(GeneralStore::MixMode(option.syncMode, highMode)); + SyncParam syncParam = { mixMode, 0, false }; + auto info = ChangeEvent::EventInfo(syncParam, false, nullptr, asyncCallback); + auto evt = std::make_unique(std::move(storeInfo), std::move(info)); + EventCenter::GetInstance().PostEvent(std::move(evt)); + return SUCCESS; +} + bool CloudServiceImpl::DoCloudSync(int32_t user, CloudSyncScene scene) { auto [status, cloudInfo] = GetCloudInfo(user); @@ -1387,6 +1600,10 @@ std::vector CloudServiceImpl::ConvertCursor(std::shared CloudServiceImpl::HapInfo CloudServiceImpl::GetHapInfo(uint32_t tokenId) { + if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) { + ZLOGE("TokenType is not TOKEN_HAP, tokenId:0x%{public}x", tokenId); + return { 0, 0, ""}; + } HapTokenInfo tokenInfo; int errCode = AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo); if (errCode != RET_SUCCESS) { 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 fb777f138745771b878dab8ac26297d29f165d8e..fbd5a97734c3a48801f6206153fb6fbc5d824411 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -22,6 +22,7 @@ #include "cloud/cloud_event.h" #include "cloud/cloud_extra_data.h" #include "cloud/cloud_info.h" +#include "cloud_notifier_proxy.h" #include "cloud/schema_meta.h" #include "cloud/sharing_center.h" #include "cloud/subscription.h" @@ -33,6 +34,7 @@ #include "values_bucket.h" namespace OHOS::CloudData { +using namespace DistributedRdb; class CloudServiceImpl : public CloudServiceStub { public: using CloudLastSyncInfo = DistributedData::CloudLastSyncInfo; @@ -51,6 +53,9 @@ public: std::pair QueryLastSyncInfo( const std::string &id, const std::string &bundleName, const std::string &storeId) override; int32_t SetGlobalCloudStrategy(Strategy strategy, const std::vector &values) override; + int32_t CloudSync(const std::string &bundleName, const std::string &storeId, const Option &option, + const AsyncDetail &async) override; + int32_t InitNotifier(sptr notifier) override; std::pair> AllocResourceAndShare(const std::string &storeId, const DistributedRdb::PredicatesMemo &predicates, const std::vector &columns, @@ -83,6 +88,8 @@ private: int32_t OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index) override; int32_t OnAppInstall(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; + private: + bool CloudDriverCheck(const std::string &bundleName, int32_t user); }; class Factory { public: @@ -126,6 +133,11 @@ private: std::string bundleName; }; + struct SyncAgent { + SyncAgent() = default; + sptr notifier_; + }; + static std::map ConvertAction(const std::map &actions); static HapInfo GetHapInfo(uint32_t tokenId); static std::string GetDfxFaultType(CloudSyncScene scene); @@ -145,13 +157,16 @@ private: bool ReleaseUserInfo(int32_t user, CloudSyncScene scene); bool DoCloudSync(int32_t user, CloudSyncScene scene); bool StopCloudSync(int32_t user, CloudSyncScene scene); + bool CleanWaterVersion(int32_t user); static std::pair GetCloudInfo(int32_t userId); static std::pair GetCloudInfoFromMeta(int32_t userId); static std::pair GetCloudInfoFromServer(int32_t userId); static int32_t UpdateCloudInfoFromServer(int32_t user); static std::pair GetAppSchemaFromServer(int32_t user, const std::string &bundleName); + static Details HandleGenDetails(const DistributedData::GenDetails &details); + void OnAsyncComplete(uint32_t tokenId, uint32_t seqNum, Details &&result); std::pair GetSchemaMeta(int32_t userId, const std::string &bundleName, int32_t instanceId); void UpgradeSchemaMeta(int32_t user, const SchemaMeta &schemaMeta); std::map ExecuteStatistics( @@ -184,15 +199,18 @@ private: using SaveStrategy = int32_t (*)(const std::vector &values, const HapInfo &hapInfo); static const SaveStrategy STRATEGY_SAVERS[Strategy::STRATEGY_BUTT]; static int32_t SaveNetworkStrategy(const std::vector &values, const HapInfo &hapInfo); - void Report(const std::string &faultType, DistributedDataDfx::Fault errCode, const std::string &bundleName, + static void Report(const std::string &faultType, DistributedDataDfx::Fault errCode, const std::string &bundleName, const std::string &appendix); + QueryLastResults AssembleLastResults(const std::vector &databases, + const std::map &lastSyncInfos); static std::pair GetSchemaFromHap(const HapInfo &hapInfo); static int32_t UpdateSchemaFromHap(const HapInfo &hapInfo); + static int32_t UpdateSchemaFromServer(int32_t user); + static int32_t UpdateSchemaFromServer(const CloudInfo &cloudInfo, int32_t user); + static void UpdateE2eeEnable(const std::string &schemaKey, bool newE2eeEnable, const std::string &bundleName); static void UpdateClearWaterMark( const HapInfo &hapInfo, const SchemaMeta &newSchemaMeta, const SchemaMeta &schemaMeta); - QueryLastResults AssembleLastResults(const std::vector &databases, - const std::map &lastSyncInfos); std::shared_ptr executor_; SyncManager syncManager_; @@ -202,6 +220,7 @@ private: uint64_t expireTime_ = static_cast( std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) .count()); + ConcurrentMap syncAgents_; static constexpr Handle WORK_CLOUD_INFO_UPDATE = &CloudServiceImpl::UpdateCloudInfo; static constexpr Handle WORK_SCHEMA_UPDATE = &CloudServiceImpl::UpdateSchema; 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 ace668b55e88bc646a91010ff1327d23a697f28a..f1a2fd85f4f115b69cf966026907cc98f0834040 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp @@ -36,6 +36,7 @@ const CloudServiceStub::Handler CloudServiceStub::HANDLERS[TRANS_BUTT] = { &CloudServiceStub::OnQueryStatistics, &CloudServiceStub::OnQueryLastSyncInfo, &CloudServiceStub::OnSetGlobalCloudStrategy, + &CloudServiceStub::OnCloudSync, &CloudServiceStub::OnAllocResourceAndShare, &CloudServiceStub::OnShare, &CloudServiceStub::OnUnshare, @@ -46,6 +47,7 @@ const CloudServiceStub::Handler CloudServiceStub::HANDLERS[TRANS_BUTT] = { &CloudServiceStub::OnConfirmInvitation, &CloudServiceStub::OnChangeConfirmation, &CloudServiceStub::OnSetCloudStrategy, + &CloudServiceStub::OnInitNotifier, }; int CloudServiceStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel &data, OHOS::MessageParcel &reply) @@ -326,4 +328,29 @@ int32_t CloudServiceStub::OnSetCloudStrategy(MessageParcel &data, MessageParcel auto status = SetCloudStrategy(strategy, values); return ITypesUtil::Marshal(reply, status) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } + +int32_t CloudServiceStub::OnCloudSync(MessageParcel &data, MessageParcel &reply) +{ + std::string bundleName; + std::string storeId; + Option option; + if (!ITypesUtil::Unmarshal(data, bundleName, storeId, option)) { + ZLOGE("Unmarshal failed, bundleName:%{public}s, storeId:%{public}s, syncMode:%{public}d, seqNum:%{public}u", + bundleName.c_str(), Anonymous::Change(storeId).c_str(), option.syncMode, option.seqNum); + return IPC_STUB_INVALID_DATA_ERR; + } + auto status = CloudSync(bundleName, storeId, option, nullptr); + return ITypesUtil::Marshal(reply, status) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; +} + +int32_t CloudServiceStub::OnInitNotifier(MessageParcel &data, MessageParcel &reply) +{ + sptr notifier = nullptr; + if (!ITypesUtil::Unmarshal(data, notifier) || notifier == nullptr) { + ZLOGE("Unmarshal failed, notifier is nullptr?[%{public}u]", notifier == nullptr); + return IPC_STUB_INVALID_DATA_ERR; + } + auto status = InitNotifier(notifier); + return ITypesUtil::Marshal(reply, status) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; +} } // namespace OHOS::CloudData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h index 5f51fe846ee8bb27c0e04e689e84d22d01f63b6a..ea1d57bd42974a5aee27dfc50ccb9eb42dac9601 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h @@ -37,6 +37,7 @@ private: int32_t OnQueryStatistics(MessageParcel &data, MessageParcel &reply); int32_t OnQueryLastSyncInfo(MessageParcel &data, MessageParcel &reply); int32_t OnSetGlobalCloudStrategy(MessageParcel &data, MessageParcel &reply); + int32_t OnCloudSync(MessageParcel &data, MessageParcel &reply); int32_t OnAllocResourceAndShare(MessageParcel &data, MessageParcel &reply); int32_t OnShare(MessageParcel &data, MessageParcel &reply); @@ -49,6 +50,7 @@ private: int32_t OnChangeConfirmation(MessageParcel &data, MessageParcel &reply); int32_t OnSetCloudStrategy(MessageParcel &data, MessageParcel &reply); + int32_t OnInitNotifier(MessageParcel &data, MessageParcel &reply); static const Handler HANDLERS[TRANS_BUTT]; }; } // namespace OHOS::CloudData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.cpp index 116d1b72eeb44a388b33462cfd699aeb6c8cd0bb..cc6aa141e21029c1480576d26e6437a6d31e3c4a 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.cpp @@ -109,4 +109,16 @@ bool Unmarshalling(CloudSyncInfo &output, MessageParcel &data) { return Unmarshal(data, output.startTime, output.finishTime, output.code, output.syncStatus); } + +template<> +bool Marshalling(const Option &input, MessageParcel &data) +{ + return Marshal(data, input.syncMode, input.seqNum); +} + +template<> +bool Unmarshalling(Option &output, MessageParcel &data) +{ + return Unmarshal(data, output.syncMode, output.seqNum); +} } // namespace OHOS::ITypesUtil \ No newline at end of file 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 7a53f6938a15cb195dd299992813811ab26295c3..e4c029956f4949532d459be215922d364e2bf525 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h @@ -17,6 +17,7 @@ #define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_TYPES_UTIL_H #include "cloud_types.h" +#include "cloud_service.h" #include "itypes_util.h" #include "values_bucket.h" @@ -32,6 +33,7 @@ using ValuesBucket = OHOS::NativeRdb::ValuesBucket; using StatisticInfo = OHOS::CloudData::StatisticInfo; using Strategy = OHOS::CloudData::Strategy; using CloudSyncInfo = OHOS::CloudData::CloudSyncInfo; +using Option = OHOS::CloudData::CloudService::Option; template<> bool Marshalling(const Participant &input, MessageParcel &data); @@ -68,5 +70,10 @@ template<> bool Marshalling(const CloudSyncInfo &input, MessageParcel &data); template<> bool Unmarshalling(CloudSyncInfo &output, MessageParcel &data); + +template<> +bool Marshalling(const Option &input, MessageParcel &data); +template<> +bool Unmarshalling(Option &output, MessageParcel &data); } // namespace OHOS::ITypesUtil #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/sync_manager.cpp b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp index aa29012866c15fe2b6e037c2b863c07fbb06cae1..d35bd45e87626780c474155eaf21e403ca03d144 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp @@ -49,8 +49,8 @@ std::atomic SyncManager::genId_ = 0; constexpr int32_t SYSTEM_USER_ID = 0; static constexpr const char *FT_GET_STORE = "GET_STORE"; static constexpr const char *FT_CALLBACK = "CALLBACK"; -SyncManager::SyncInfo::SyncInfo(int32_t user, const std::string &bundleName, const Store &store, const Tables &tables, - int32_t triggerMode) +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()) { @@ -176,13 +176,19 @@ std::function SyncManager::GetLockChangeHandler() return; } - StoreMetaData meta(storeInfo); + StoreMetaMapping 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.", + ZLOGE("no store mapping. bundleName: %{public}s, storeName: %{public}s, user: %{public}d.", storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.user); return; } + if (!meta.cloudPath.empty() && meta.dataDir != meta.cloudPath && + !MetaDataManager::GetInstance().LoadMeta(meta.GetCloudStoreMetaKey(), meta, true)) { + ZLOGE("failed, no store meta. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return; + } auto [status, store] = GetStore(meta, storeInfo.user); if (store == nullptr) { ZLOGE("failed to get store. bundleName: %{public}s, storeName: %{public}s, user: %{public}d.", @@ -201,8 +207,8 @@ std::function SyncManager::GetLockChangeHandler() SyncManager::SyncManager() { - EventCenter::GetInstance().Subscribe(CloudEvent::LOCK_CLOUD_CONTAINER, GetLockChangeHandler()); - EventCenter::GetInstance().Subscribe(CloudEvent::UNLOCK_CLOUD_CONTAINER, GetLockChangeHandler()); + EventCenter::GetInstance().Subscribe(CloudEvent::LOCK_CLOUD_CONTAINER, SyncManager::GetLockChangeHandler()); + EventCenter::GetInstance().Subscribe(CloudEvent::UNLOCK_CLOUD_CONTAINER, SyncManager::GetLockChangeHandler()); EventCenter::GetInstance().Subscribe(CloudEvent::LOCAL_CHANGE, GetClientChangeHandler()); syncStrategy_ = std::make_shared(); auto metaName = Bootstrap::GetInstance().GetProcessLabel(); @@ -299,15 +305,15 @@ std::function SyncManager::GetPostEventTask(const std::vectorsecond, SyncStage::END, E_ERROR }); + SyncManager::Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second, + SyncStage::END, E_ERROR, "!IsOn:" + schema.bundleName }); continue; } for (const auto &database : schema.databases) { if (!info.Contains(database.name)) { UpdateFinishSyncInfo({ cloud.user, cloud.id, schema.bundleName, database.name }, syncId, E_ERROR); - Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second, SyncStage::END, - E_ERROR }); + SyncManager::Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second, + SyncStage::END, E_ERROR, "!Contains:" + database.name }); continue; } StoreInfo storeInfo = { 0, schema.bundleName, database.name, cloud.apps[schema.bundleName].instanceId, @@ -317,8 +323,8 @@ std::function SyncManager::GetPostEventTask(const std::vectorsecond, SyncStage::END, - status }); + SyncManager::Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second, + SyncStage::END, status, "CheckSyncAction" }); info.SetError(status); continue; } @@ -353,13 +359,13 @@ ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount info.SetError(E_CLOUD_DISABLED); return; } - auto traceIds = GetPrepareTraceId(info, cloud); + auto traceIds = SyncManager::GetPrepareTraceId(info, cloud); BatchReport(info.user_, traceIds, SyncStage::PREPARE, E_OK); UpdateStartSyncInfo(cloudSyncInfos); auto code = IsValid(info, cloud); if (code != E_OK) { BatchUpdateFinishState(cloudSyncInfos, code); - BatchReport(info.user_, traceIds, SyncStage::END, code); + BatchReport(info.user_, traceIds, SyncStage::END, code, "!IsValid"); return; } @@ -373,7 +379,7 @@ ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount retryer(RETRY_INTERVAL, E_RETRY_TIMEOUT, GenStore::CLOUD_ERR_OFFSET + E_CLOUD_DISABLED, it == traceIds.end() ? "" : it->second); BatchUpdateFinishState(cloudSyncInfos, E_CLOUD_DISABLED); - BatchReport(info.user_, traceIds, SyncStage::END, E_CLOUD_DISABLED); + BatchReport(info.user_, traceIds, SyncStage::END, E_CLOUD_DISABLED, "empty schema:" + info.bundleName_); return; } } @@ -386,6 +392,34 @@ ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount }; } +void SyncManager::StartCloudSync(const DistributedData::SyncEvent &evt, const StoreMetaData &meta, + const AutoCache::Store &store, Retryer retryer, DistributedData::GenDetails &details) +{ + auto &storeInfo = evt.GetStoreInfo(); + GenAsync async = evt.GetAsyncDetail(); + auto prepareTraceId = evt.GetPrepareTraceId(); + auto user = evt.GetUser(); + auto &detail = details[SyncInfo::DEFAULT_ID]; + ReportSyncEvent(evt, BizState::BEGIN, E_OK); + SyncParam syncParam = { evt.GetMode(), evt.GetWait(), evt.IsCompensation(), MODE_DEFAULT, prepareTraceId }; + syncParam.asyncDownloadAsset = meta.asyncDownloadAsset; + auto [status, dbCode] = store->Sync({ SyncInfo::DEFAULT_ID }, *(evt.GetQuery()), + evt.AutoRetry() ? RetryCallback(storeInfo, retryer, evt.GetTriggerMode(), prepareTraceId, user) + : GetCallback(async, storeInfo, evt.GetTriggerMode(), prepareTraceId, user), syncParam); + if (status != E_OK) { + if (async) { + detail.code = ConvertValidGeneralCode(status); + async(std::move(details)); + } + UpdateFinishSyncInfo({ storeInfo.user, GetAccountId(storeInfo.user), storeInfo.bundleName, + storeInfo.storeName }, storeInfo.syncId, E_ERROR); + if (status != GeneralError::E_NOT_SUPPORT) { + auto code = dbCode == 0 ? GenStore::CLOUD_ERR_OFFSET + status : dbCode; + ReportSyncEvent(evt, BizState::END, code); + } + } +} + std::function SyncManager::GetSyncHandler(Retryer retryer) { return [this, retryer](const Event &event) { @@ -393,13 +427,13 @@ std::function SyncManager::GetSyncHandler(Retryer retryer) auto &storeInfo = evt.GetStoreInfo(); GenAsync async = evt.GetAsyncDetail(); auto prepareTraceId = evt.GetPrepareTraceId(); - auto user = evt.GetUser(); GenDetails details; auto &detail = details[SyncInfo::DEFAULT_ID]; detail.progress = GenProgress::SYNC_FINISH; auto [hasMeta, meta] = GetMetaData(storeInfo); if (!hasMeta) { - return DoExceptionalCallback(async, details, storeInfo, prepareTraceId); + return DoExceptionalCallback(async, details, storeInfo, + {0, "", prepareTraceId, SyncStage::END, GeneralError::E_ERROR, "no meta"}); } auto [code, store] = GetStore(meta, storeInfo.user); if (code == E_SCREEN_LOCKED) { @@ -408,60 +442,43 @@ std::function SyncManager::GetSyncHandler(Retryer retryer) if (store == nullptr) { ZLOGE("store null, storeId:%{public}s, prepareTraceId:%{public}s", meta.GetStoreAlias().c_str(), prepareTraceId.c_str()); - return DoExceptionalCallback(async, details, storeInfo, prepareTraceId); + return DoExceptionalCallback(async, details, storeInfo, + {0, "", prepareTraceId, SyncStage::END, GeneralError::E_ERROR, "store null"}); } if (!meta.enableCloud) { ZLOGW("meta.enableCloud is false, storeId:%{public}s, prepareTraceId:%{public}s", meta.GetStoreAlias().c_str(), prepareTraceId.c_str()); - return DoExceptionalCallback(async, details, storeInfo, prepareTraceId, E_CLOUD_DISABLED); + return DoExceptionalCallback(async, details, storeInfo, + {0, "", prepareTraceId, SyncStage::END, E_CLOUD_DISABLED, "disable cloud"}); } ZLOGI("database:<%{public}d:%{public}s:%{public}s:%{public}s> sync start, asyncDownloadAsset?[%{public}d]", - storeInfo.user, storeInfo.bundleName.c_str(), meta.GetStoreAlias().c_str(), prepareTraceId.c_str(), - meta.asyncDownloadAsset); - ReportSyncEvent(evt, BizState::BEGIN, E_OK); - SyncParam syncParam = { evt.GetMode(), evt.GetWait(), evt.IsCompensation(), MODE_DEFAULT, prepareTraceId }; - syncParam.asyncDownloadAsset = meta.asyncDownloadAsset; - auto [status, dbCode] = store->Sync({ SyncInfo::DEFAULT_ID }, *(evt.GetQuery()), - evt.AutoRetry() ? RetryCallback(storeInfo, retryer, evt.GetTriggerMode(), prepareTraceId, user) - : GetCallback(async, storeInfo, evt.GetTriggerMode(), prepareTraceId, user), - syncParam); - if (status != E_OK) { - if (async) { - detail.code = status; - async(std::move(details)); - } - UpdateFinishSyncInfo({ storeInfo.user, GetAccountId(storeInfo.user), storeInfo.bundleName, - storeInfo.storeName }, - storeInfo.syncId, E_ERROR); - if (status != GeneralError::E_NOT_SUPPORT) { - auto code = dbCode == 0 ? GenStore::CLOUD_ERR_OFFSET + status : dbCode; - ReportSyncEvent(evt, BizState::END, code); - } - } + storeInfo.user, storeInfo.bundleName.c_str(), meta.GetStoreAlias().c_str(), prepareTraceId.c_str(), + meta.asyncDownloadAsset); + StartCloudSync(evt, meta, store, retryer, details); }; } void SyncManager::ReportSyncEvent(const SyncEvent &evt, BizState bizState, int32_t code) { - SyncStage syncStage = SyncStage::START; auto &storeInfo = evt.GetStoreInfo(); if (bizState == BizState::BEGIN) { - syncStage = SyncStage::START; - RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, TRIGGER_SYNC, storeInfo.syncId, - evt.GetTriggerMode() }, - "GetSyncHandler", bizState); + RadarReporter::Report({storeInfo.bundleName.c_str(), CLOUD_SYNC, TRIGGER_SYNC, + storeInfo.syncId, evt.GetTriggerMode()}, "GetSyncHandler", bizState); } else { - syncStage = SyncStage::END; - RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, - evt.GetTriggerMode(), code }, - "GetSyncHandler", bizState); + RadarReporter::Report({storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, + storeInfo.syncId, evt.GetTriggerMode(), code}, "GetSyncHandler", bizState); } - Report({ evt.GetUser(), storeInfo.bundleName, evt.GetPrepareTraceId(), syncStage, code }); + SyncStage syncStage = (bizState == BizState::BEGIN) ? SyncStage::START : SyncStage::END; + SyncManager::Report({evt.GetUser(), storeInfo.bundleName, evt.GetPrepareTraceId(), syncStage, code, + "GetSyncHandler"}); } std::function SyncManager::GetClientChangeHandler() { return [this](const Event &event) { + if (executor_ == nullptr) { + return; + } auto &evt = static_cast(event); auto store = evt.GetStoreInfo(); SyncInfo syncInfo(store.user, store.bundleName, store.storeName); @@ -476,8 +493,8 @@ std::function SyncManager::GetClientChangeHandler() }; } -void SyncManager::Report(const std::string &faultType, const std::string &bundleName, int32_t errCode, - const std::string &appendix) +void SyncManager::Report( + const std::string &faultType, const std::string &bundleName, int32_t errCode, const std::string &appendix) { ArkDataFaultMsg msg = { .faultType = faultType, .bundleName = bundleName, @@ -487,23 +504,29 @@ void SyncManager::Report(const std::string &faultType, const std::string &bundle Reporter::GetInstance()->CloudSyncFault()->Report(msg); } +bool SyncManager::HandleRetryFinished(const SyncInfo &info, int32_t user, int32_t code, int32_t dbCode, + const std::string &prepareTraceId) +{ + if (code == E_OK || code == E_SYNC_TASK_MERGED) { + return true; + } + info.SetError(code); + RadarReporter::Report({ info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, info.triggerMode_, + dbCode }, + "GetRetryer", BizState::END); + SyncManager::Report({ user, info.bundleName_, prepareTraceId, SyncStage::END, + dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode, "GetRetryer finish" }); + Report(FT_CALLBACK, info.bundleName_, static_cast(Fault::CSF_GS_CLOUD_SYNC), + "code=" + std::to_string(code) + ",dbCode=" + std::to_string(static_cast(dbCode))); + return true; +} + SyncManager::Retryer SyncManager::GetRetryer(int32_t times, const SyncInfo &syncInfo, int32_t user) { if (times >= RETRY_TIMES) { return [this, user, info = SyncInfo(syncInfo)](Duration, int32_t code, int32_t dbCode, const std::string &prepareTraceId) mutable { - if (code == E_OK || code == E_SYNC_TASK_MERGED) { - return true; - } - info.SetError(code); - RadarReporter::Report({ info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, info.triggerMode_, - dbCode }, - "GetRetryer", BizState::END); - Report({ user, info.bundleName_, prepareTraceId, SyncStage::END, - dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode }); - Report(FT_CALLBACK, info.bundleName_, static_cast(Fault::CSF_GS_CLOUD_SYNC), - "code=" + std::to_string(code) + ",dbCode=" + std::to_string(static_cast(dbCode))); - return true; + return HandleRetryFinished(info, user, code, dbCode, prepareTraceId); }; } return [this, times, user, info = SyncInfo(syncInfo)](Duration interval, int32_t code, int32_t dbCode, @@ -514,15 +537,18 @@ 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_, info.triggerMode_, - dbCode }, + dbCode }, "GetRetryer", BizState::END); - Report({ user, info.bundleName_, prepareTraceId, SyncStage::END, - dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode }); + SyncManager::Report({ user, info.bundleName_, prepareTraceId, SyncStage::END, + dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode, "GetRetryer continue" }); Report(FT_CALLBACK, info.bundleName_, static_cast(Fault::CSF_GS_CLOUD_SYNC), - "code=" + std::to_string(code) + ",dbCode=" + std::to_string(static_cast(dbCode))); + "code=" + std::to_string(code) + ",dbCode=" + std::to_string(static_cast(dbCode))); return true; } + if (executor_ == nullptr) { + return false; + } activeInfos_.ComputeIfAbsent(info.syncId_, [this, times, interval, &info](uint64_t key) mutable { auto syncId = GenerateId(info.user_); auto ref = GenSyncRef(syncId); @@ -609,7 +635,6 @@ std::pair SyncManager::GetStore(const StoreMetaData & return { E_USER_UNLOCK, nullptr }; } if (CloudServer::GetInstance() == nullptr) { - ZLOGD("not support cloud sync"); return { E_NOT_SUPPORT, nullptr }; } auto [status, store] = AutoCache::GetInstance().GetDBStore(meta, {}); @@ -648,6 +673,7 @@ std::pair SyncManager::GetStore(const StoreMetaData & if (MetaDataManager::GetInstance().LoadMeta(info.GetKey(), info, true)) { config.maxNumber = info.maxNumber; config.maxSize = info.maxSize; + config.isSupportEncrypt = schemaMeta.e2eeEnable; } store->Bind(dbMeta, bindInfos, config); } @@ -727,7 +753,7 @@ std::pair SyncManager::GetLastResults(std::mapsecond.code != -1) { - return { SUCCESS, std::move(iter->second) }; + return { SUCCESS, iter->second }; } return { E_ERROR, {} }; } @@ -737,10 +763,7 @@ 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; + return kvApps_.find(queryKey.bundleName) == kvApps_.end(); } std::pair> SyncManager::QueryLastSyncInfo( @@ -750,8 +773,8 @@ std::pair> SyncManager::QueryL for (const auto &queryKey : queryKeys) { std::string storeId = queryKey.storeId; QueryKey key{ queryKey.user, queryKey.accountId, queryKey.bundleName, queryKey.storeId }; - lastSyncInfos_.ComputeIfPresent(key, - [&storeId, &lastSyncInfoMap](auto &key, std::map &vals) { + lastSyncInfos_.ComputeIfPresent( + key, [&storeId, &lastSyncInfoMap](auto &key, std::map &vals) { auto [status, syncInfo] = GetLastResults(vals); if (status == SUCCESS) { lastSyncInfoMap.insert(std::make_pair(std::move(storeId), std::move(syncInfo))); @@ -761,7 +784,7 @@ std::pair> SyncManager::QueryL if (lastSyncInfoMap.find(queryKey.storeId) != lastSyncInfoMap.end()) { continue; } - auto [status, syncInfo] = GetLastSyncInfoFromMeta(queryKey); + auto [status, syncInfo] = SyncManager::GetLastSyncInfoFromMeta(queryKey); if (status == SUCCESS) { lastSyncInfoMap.insert(std::make_pair(std::move(syncInfo.storeId), std::move(syncInfo))); } @@ -801,7 +824,7 @@ void SyncManager::UpdateFinishSyncInfo(const QueryKey &queryKey, uint64_t syncId iter = val.erase(iter); } else if (iter->first == syncId) { iter->second.finishTime = duration_cast(system_clock::now().time_since_epoch()).count(); - iter->second.code = code; + iter->second.code = ConvertValidGeneralCode(code); iter->second.syncStatus = SyncStatus::FINISHED; SaveLastSyncInfo(key, std::move(iter->second)); iter = val.erase(iter); @@ -818,7 +841,7 @@ std::function SyncManager::GetCallback(const Gen { return [this, async, storeInfo, triggerMode, prepareTraceId, user](const GenDetails &result) { if (async != nullptr) { - async(result); + async(ConvertGenDetailsCode(result)); } if (result.empty()) { @@ -832,9 +855,9 @@ std::function SyncManager::GetCallback(const Gen int32_t dbCode = (result.begin()->second.dbCode == GenStore::DB_ERR_OFFSET) ? 0 : result.begin()->second.dbCode; RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, triggerMode, - dbCode, result.begin()->second.changeCount }, + dbCode, result.begin()->second.changeCount }, "GetCallback", BizState::END); - Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::END, dbCode }); + SyncManager::Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::END, dbCode, "GetCallback" }); if (dbCode != 0) { Report(FT_CALLBACK, storeInfo.bundleName, static_cast(Fault::CSF_GS_CLOUD_SYNC), "callback failed, dbCode=" + std::to_string(dbCode)); @@ -881,15 +904,16 @@ std::vector SyncManager::GetSchemaMeta(const CloudInfo &cloud, const } void SyncManager::DoExceptionalCallback(const GenAsync &async, GenDetails &details, const StoreInfo &storeInfo, - const std::string &prepareTraceId, int32_t code) + const ReportParam ¶m) { if (async) { - details[SyncInfo::DEFAULT_ID].code = code; + details[SyncInfo::DEFAULT_ID].code = param.errCode; async(details); } QueryKey queryKey{ storeInfo.user, GetAccountId(storeInfo.user), storeInfo.bundleName, storeInfo.storeName }; - UpdateFinishSyncInfo(queryKey, storeInfo.syncId, code); - Report({ storeInfo.user, storeInfo.bundleName, prepareTraceId, SyncStage::END, code }); + UpdateFinishSyncInfo(queryKey, storeInfo.syncId, param.errCode); + SyncManager::Report({ storeInfo.user, storeInfo.bundleName, param.prepareTraceId, SyncStage::END, + param.errCode, param.message }); } bool SyncManager::InitDefaultUser(int32_t &user) @@ -921,10 +945,10 @@ std::function SyncManager::Retr UpdateFinishSyncInfo(queryKey, storeInfo.syncId, code); if (code == E_OK) { RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, - triggerMode, code, details.begin()->second.changeCount }, + triggerMode, code, details.begin()->second.changeCount }, "RetryCallback", BizState::END); - Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::END, - dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode }); + SyncManager::Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::END, + dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode, "RetryCallback" }); } } retryer(GetInterval(code), code, dbCode, prepareTraceId); @@ -939,26 +963,41 @@ void SyncManager::BatchUpdateFinishState(const std::vector SyncManager::GetMetaData(const StoreInfo &storeInfo) { StoreMetaData meta(storeInfo); meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { - meta.user = "0"; // check if it is a public store. - StoreMetaDataLocal localMetaData; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMetaData, true) || - !localMetaData.isPublic || !MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { - ZLOGE("failed, no store meta. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), - meta.GetStoreAlias().c_str()); - return { false, meta }; - } + meta.dataDir = GetPath(meta); + if (!meta.dataDir.empty() && MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + return { true, meta }; + } + meta.user = "0"; // check if it is a public store. + meta.dataDir = GetPath(meta); + if (meta.dataDir.empty() || !MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + ZLOGE("failed, no store meta. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return { false, meta }; + } + StoreMetaDataLocal localMetaData; + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMetaData, true) || !localMetaData.isPublic) { + ZLOGE("failed, no store LocalMeta. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return { false, meta }; } return { true, meta }; } @@ -995,7 +1034,7 @@ void SyncManager::CleanCompensateSync(int32_t userId) void SyncManager::AddCompensateSync(const StoreMetaData &meta) { - compensateSyncInfos_.Compute(std::stoi(meta.user), + compensateSyncInfos_.Compute(std::atoi(meta.user.c_str()), [&meta](auto &, std::map> &apps) { apps[meta.bundleName].insert(meta.storeId); return true; @@ -1006,14 +1045,13 @@ std::pair SyncManager::GetLastSyncInfoFromMeta(const { CloudLastSyncInfo lastSyncInfo; if (!MetaDataManager::GetInstance().LoadMeta(CloudLastSyncInfo::GetKey(queryKey.user, queryKey.bundleName, - queryKey.storeId), - lastSyncInfo, true)) { - ZLOGE("load last sync info fail, bundleName: %{public}s, user:%{public}d", queryKey.bundleName.c_str(), - queryKey.user); + queryKey.storeId), lastSyncInfo, true)) { + ZLOGE("load last sync info fail, bundleName: %{public}s, user:%{public}d", + queryKey.bundleName.c_str(), queryKey.user); return { E_ERROR, lastSyncInfo }; } - if (queryKey.accountId != lastSyncInfo.id || - (!queryKey.storeId.empty() && queryKey.storeId != lastSyncInfo.storeId)) { + if (queryKey.accountId != lastSyncInfo.id || (!queryKey.storeId.empty() && + queryKey.storeId != lastSyncInfo.storeId)) { return { E_ERROR, lastSyncInfo }; } return { SUCCESS, std::move(lastSyncInfo) }; @@ -1021,11 +1059,26 @@ std::pair SyncManager::GetLastSyncInfoFromMeta(const void SyncManager::SaveLastSyncInfo(const QueryKey &queryKey, CloudLastSyncInfo &&info) { - if (!MetaDataManager::GetInstance().SaveMeta(CloudLastSyncInfo::GetKey(queryKey.user, queryKey.bundleName, - queryKey.storeId), - info, true)) { - ZLOGE("save cloud last info fail, bundleName: %{public}s, user:%{public}d", queryKey.bundleName.c_str(), - queryKey.user); + if (!MetaDataManager::GetInstance().SaveMeta(CloudLastSyncInfo::GetKey(queryKey.user, + queryKey.bundleName, queryKey.storeId), info, true)) { + ZLOGE("save cloud last info fail, bundleName: %{public}s, user:%{public}d", + queryKey.bundleName.c_str(), queryKey.user); + } +} + +GenDetails SyncManager::ConvertGenDetailsCode(const GenDetails &details) +{ + GenDetails newDetails; + for (const auto &it : details) { + GenProgressDetail detail = it.second; + detail.code = ConvertValidGeneralCode(detail.code); + newDetails.emplace(std::make_pair(it.first, std::move(detail))); } + return newDetails; +} + +int32_t SyncManager::ConvertValidGeneralCode(int32_t code) +{ + return (code >= E_OK && code < E_BUSY) ? code : E_ERROR; } } // 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 6214a046b0a5cf217a9a56b7c0eea91b3c15c62b..a24f0ae6649a07bb18c8ec6dd8ea8882972cc0be 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h @@ -46,7 +46,6 @@ public: using TraceIds = std::map; using SyncStage = DistributedData::SyncStage; using ReportParam = DistributedData::ReportParam; - static std::pair GetStore(const StoreMetaData &meta, int32_t user, bool mustBind = true); class SyncInfo final { public: using Store = std::string; @@ -95,14 +94,16 @@ public: }; SyncManager(); ~SyncManager(); + static void Report(const ReportParam &reportParam); + static std::pair GetStore(const StoreMetaData &meta, int32_t user, bool mustBind = true); int32_t Bind(std::shared_ptr executor); int32_t DoCloudSync(SyncInfo syncInfo); int32_t StopCloudSync(int32_t user = 0); std::pair> QueryLastSyncInfo( const std::vector &queryKeys); - void Report(const ReportParam &reportParam); void OnScreenUnlocked(int32_t user); void CleanCompensateSync(int32_t userId); + static std::string GetPath(const StoreMetaData &meta); private: using Event = DistributedData::Event; @@ -137,6 +138,19 @@ private: static std::vector GetSchemaMeta(const CloudInfo &cloud, const std::string &bundleName); static bool NeedGetCloudInfo(CloudInfo &cloud); static GeneralError IsValid(SyncInfo &info, CloudInfo &cloud); + static std::function GetLockChangeHandler(); + static TraceIds GetPrepareTraceId(const SyncInfo &info, const CloudInfo &cloud); + static void Report( + const std::string &faultType, const std::string &bundleName, int32_t errCode, const std::string &appendix); + static std::pair GetLastResults(std::map &infos); + static std::pair GetLastSyncInfoFromMeta(const QueryKey &queryKey); + static void SaveLastSyncInfo(const QueryKey &queryKey, CloudLastSyncInfo &&info); + static void BatchReport(int32_t userId, const TraceIds &traceIds, SyncStage syncStage, int32_t errCode, + const std::string &message = ""); + static void ReportSyncEvent(const DistributedData::SyncEvent &evt, DistributedDataDfx::BizState bizState, + int32_t code); + static bool HandleRetryFinished(const SyncInfo &info, int32_t user, int32_t code, int32_t dbCode, + const std::string &prepareTraceId); Task GetSyncTask(int32_t times, bool retry, RefCount ref, SyncInfo &&syncInfo); void UpdateSchema(const SyncInfo &syncInfo); std::function GetSyncHandler(Retryer retryer); @@ -151,24 +165,18 @@ private: std::function GetPostEventTask(const std::vector &schemas, CloudInfo &cloud, SyncInfo &info, bool retry, const TraceIds &traceIds); void DoExceptionalCallback(const GenAsync &async, GenDetails &details, const StoreInfo &storeInfo, - const std::string &prepareTraceId, int32_t code = GeneralError::E_ERROR); + const ReportParam ¶m); bool InitDefaultUser(int32_t &user); std::function RetryCallback(const StoreInfo &storeInfo, Retryer retryer, int32_t triggerMode, const std::string &prepareTraceId, int32_t user); - static std::pair GetLastResults(std::map &infos); void BatchUpdateFinishState(const std::vector> &cloudSyncInfos, int32_t code); bool NeedSaveSyncInfo(const QueryKey &queryKey); - std::function GetLockChangeHandler(); - void BatchReport(int32_t userId, const TraceIds &traceIds, SyncStage syncStage, int32_t errCode); - TraceIds GetPrepareTraceId(const SyncInfo &info, const CloudInfo &cloud); + void StartCloudSync(const DistributedData::SyncEvent &evt, const StoreMetaData &meta, + const AutoCache::Store &store, Retryer retryer, DistributedData::GenDetails &details); std::pair GetMetaData(const StoreInfo &storeInfo); void AddCompensateSync(const StoreMetaData &meta); - static void Report( - const std::string &faultType, const std::string &bundleName, int32_t errCode, const std::string &appendix); - void ReportSyncEvent(const DistributedData::SyncEvent &evt, DistributedDataDfx::BizState bizState, int32_t code); - std::pair GetLastSyncInfoFromMeta(const QueryKey &queryKey); - static void SaveLastSyncInfo(const QueryKey &queryKey, CloudLastSyncInfo &&info); - + static DistributedData::GenDetails ConvertGenDetailsCode(const GenDetails &details); + static int32_t ConvertValidGeneralCode(int32_t code); static std::atomic genId_; std::shared_ptr executor_; ConcurrentMap actives_; diff --git a/datamgr_service/services/distributeddataservice/service/common/BUILD.gn b/datamgr_service/services/distributeddataservice/service/common/BUILD.gn index 7a493bd1b37c573cf2c0ab5e3987e29e6b3d30d5..50a08c56e6e2ee8ef72a754ae62274ca1a5c89fd 100644 --- a/datamgr_service/services/distributeddataservice/service/common/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/common/BUILD.gn @@ -31,7 +31,6 @@ ohos_source_set("distributeddata_common") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ "include" ] @@ -41,15 +40,16 @@ ohos_source_set("distributeddata_common") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] external_deps = [ "hicollie:libhicollie", "hilog:libhilog", + "ipc:ipc_single", "kv_store:distributeddb", "relational_store:native_rdb", + "kv_store:datamgr_common", ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" diff --git a/datamgr_service/services/distributeddataservice/service/common/xcollie.h b/datamgr_service/services/distributeddataservice/service/common/xcollie.h index 68f8436cef7a57a3fa2074e4472d65c75fe1b4b2..c5a880c0d6c9735fdeeb0032ad725f882f6a6c0e 100644 --- a/datamgr_service/services/distributeddataservice/service/common/xcollie.h +++ b/datamgr_service/services/distributeddataservice/service/common/xcollie.h @@ -18,6 +18,7 @@ #include #include "xcollie/xcollie.h" +#include "visibility.h" namespace OHOS::DistributedData { class XCollie { @@ -26,9 +27,9 @@ public: XCOLLIE_LOG = 0x1, XCOLLIE_RECOVERY = 0x2 }; - XCollie(const std::string &tag, uint32_t flag, uint32_t timeoutSeconds = RESTART_TIME_THRESHOLD, + API_EXPORT XCollie(const std::string &tag, uint32_t flag, uint32_t timeoutSeconds = RESTART_TIME_THRESHOLD, std::function func = nullptr, void *arg = nullptr); - ~XCollie(); + API_EXPORT ~XCollie(); private: int32_t id_ = -1; diff --git a/datamgr_service/services/distributeddataservice/service/config/BUILD.gn b/datamgr_service/services/distributeddataservice/service/config/BUILD.gn index 9349f811344a5e46253bd05d8c58ca2cd32f9036..99550fc4ad8c842d13eb27cb5aef5678a9e923d4 100644 --- a/datamgr_service/services/distributeddataservice/service/config/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/config/BUILD.gn @@ -24,11 +24,14 @@ ohos_source_set("distributeddata_config") { } sources = [ "src/config_factory.cpp", + "src/model/app_access_check_config.cpp", "src/model/app_id_mapping_config.cpp", "src/model/backup_config.cpp", "src/model/checker_config.cpp", "src/model/cloud_config.cpp", "src/model/component_config.cpp", + "src/model/datashare_config.cpp", + "src/model/device_sync_app_white_list_config.cpp", "src/model/directory_config.cpp", "src/model/global_config.cpp", "src/model/network_config.cpp", @@ -39,7 +42,6 @@ ohos_source_set("distributeddata_config") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ @@ -53,13 +55,13 @@ ohos_source_set("distributeddata_config") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] external_deps = [ "hilog:libhilog", "json:nlohmann_json_static", + "kv_store:datamgr_common", ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" 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 bce10b04a32c1579e11d31ab5f84100eb91a15a4..87fcb7e693fefc00a13d6a381dc446471cba8ab8 100644 --- a/datamgr_service/services/distributeddataservice/service/config/include/config_factory.h +++ b/datamgr_service/services/distributeddataservice/service/config/include/config_factory.h @@ -33,6 +33,9 @@ public: API_EXPORT CloudConfig *GetCloudConfig(); API_EXPORT std::vector *GetAppIdMappingConfig(); API_EXPORT ThreadConfig *GetThreadConfig(); + API_EXPORT DataShareConfig *GetDataShareConfig(); + API_EXPORT DeviceSyncAppWhiteListConfig *GetDeviceSyncAppWhiteListConfig(); + API_EXPORT AppAccessCheckConfig *GetSyncAppsConfig(); private: static constexpr const char *CONF_PATH = "/system/etc/distributeddata/conf"; ConfigFactory(); diff --git a/datamgr_service/services/distributeddataservice/service/config/include/model/app_access_check_config.h b/datamgr_service/services/distributeddataservice/service/config/include/model/app_access_check_config.h new file mode 100644 index 0000000000000000000000000000000000000000..5c3876f95cc030e61bc130dc8ba87a3ab48c83e4 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/config/include/model/app_access_check_config.h @@ -0,0 +1,35 @@ +/* +* Copyright (c) 2025 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_ACCESS_CHECK_CONFIG_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_APP_ACCESS_CHECK_CONFIG_H + +#include "serializable/serializable.h" +namespace OHOS { +namespace DistributedData { +class AppAccessCheckConfig final : public Serializable { +public: + struct TrustApp final : public Serializable { + std::string bundleName = ""; + std::string appId = ""; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + std::vector trusts; +}; +} // namespace DistributedData +} // namespace OHOS +#endif //OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_APP_ACCESS_CHECK_CONFIG_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/config/include/model/datashare_config.h b/datamgr_service/services/distributeddataservice/service/config/include/model/datashare_config.h new file mode 100644 index 0000000000000000000000000000000000000000..33d5f9b3b4f134275d469693282ec3be8c215d8d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/config/include/model/datashare_config.h @@ -0,0 +1,30 @@ +/* +* Copyright (c) 2025 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_DATASHARE_CONFIG_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_DATASHARE_CONFIG_H + +#include "serializable/serializable.h" +namespace OHOS { +namespace DistributedData { +class DataShareConfig final : public Serializable { +public: + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + std::vector dataShareExtNames; + std::vector updateLaunchNames; +}; +} // namespace DistributedData +} // namespace OHOS +#endif //OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_DATASHARE_CONFIG_H diff --git a/datamgr_service/services/distributeddataservice/service/config/include/model/device_sync_app_white_list_config.h b/datamgr_service/services/distributeddataservice/service/config/include/model/device_sync_app_white_list_config.h new file mode 100644 index 0000000000000000000000000000000000000000..03729b9c77c52dbdf74d6498087f7856f1e36953 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/config/include/model/device_sync_app_white_list_config.h @@ -0,0 +1,37 @@ +/* +* Copyright (c) 2025 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_DEVICE_SYNC_APP_WHITE_LIST_CONFIG_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_DEVICE_SYNC_APP_WHITE_LIST_CONFIG_H + +#include "serializable/serializable.h" +namespace OHOS { +namespace DistributedData { +class DeviceSyncAppWhiteListConfig final : public Serializable { +public: + struct WhiteList final : public Serializable { + std::string appId; + std::string bundleName; + uint32_t version; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + + std::vector whiteLists; +}; +} // namespace DistributedData +} // namespace OHOS +#endif //OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_DEVICE_SYNC_APP_WHITE_LIST_CONFIG_H diff --git a/datamgr_service/services/distributeddataservice/service/config/include/model/directory_config.h b/datamgr_service/services/distributeddataservice/service/config/include/model/directory_config.h index 034224999aea26e3220458857f877e2aa544cb5f..8d7f170d2bc6d1fc764aff75c0e2b7eb888837bd 100644 --- a/datamgr_service/services/distributeddataservice/service/config/include/model/directory_config.h +++ b/datamgr_service/services/distributeddataservice/service/config/include/model/directory_config.h @@ -25,7 +25,12 @@ public: bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; }; + struct StoreType final : public Serializable, public DirectoryManager::StoreType { + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; std::vector strategy; + std::vector storeTypes; bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; }; 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 91f5a237b3b7309f0e34444e1c4f2cebdb574a8f..4d7a9e531c067edd42a59e07e66385f3e07afc4c 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 @@ -15,14 +15,17 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_GLOBAL_CONFIG_H #define OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_GLOBAL_CONFIG_H +#include "model/app_access_check_config.h" #include "model/app_id_mapping_config.h" #include "model/backup_config.h" #include "model/checker_config.h" #include "model/cloud_config.h" #include "model/component_config.h" +#include "model/datashare_config.h" #include "model/directory_config.h" #include "model/network_config.h" #include "model/thread_config.h" +#include "model/device_sync_app_white_list_config.h" #include "serializable/serializable.h" namespace OHOS { namespace DistributedData { @@ -40,6 +43,9 @@ public: CloudConfig *cloud = nullptr; std::vector *appIdMapping = nullptr; ThreadConfig *thread = nullptr; + DataShareConfig *dataShare = nullptr; + DeviceSyncAppWhiteListConfig *deviceSyncAppWhiteList = nullptr; + AppAccessCheckConfig *syncAppList = 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 3b05fce80631bf9ee5ea0b5bad1b6a56172cf3c8..0f91cb6aaad97d053323787ce4f517d6ffff764e 100644 --- a/datamgr_service/services/distributeddataservice/service/config/src/config_factory.cpp +++ b/datamgr_service/services/distributeddataservice/service/config/src/config_factory.cpp @@ -91,5 +91,20 @@ ThreadConfig *ConfigFactory::GetThreadConfig() { return config_.thread; } + +DataShareConfig *ConfigFactory::GetDataShareConfig() +{ + return config_.dataShare; +} + +DeviceSyncAppWhiteListConfig *ConfigFactory::GetDeviceSyncAppWhiteListConfig() +{ + return config_.deviceSyncAppWhiteList; +} + +AppAccessCheckConfig *ConfigFactory::GetSyncAppsConfig() +{ + return config_.syncAppList; +} } // namespace DistributedData } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/config/src/model/app_access_check_config.cpp b/datamgr_service/services/distributeddataservice/service/config/src/model/app_access_check_config.cpp new file mode 100644 index 0000000000000000000000000000000000000000..41b658f967725423dfc05005fcbec68fb4a39b86 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/config/src/model/app_access_check_config.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 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_access_check_config.h" +namespace OHOS { +namespace DistributedData { +bool AppAccessCheckConfig::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(trusts)], trusts); + return true; +} + +bool AppAccessCheckConfig::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(trusts), trusts); + return true; +} + +bool AppAccessCheckConfig::TrustApp::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(bundleName)], bundleName); + SetValue(node[GET_NAME(appId)], appId); + return true; +} + +bool AppAccessCheckConfig::TrustApp::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(bundleName), bundleName); + GetValue(node, GET_NAME(appId), appId); + return true; +} + +} // namespace DistributedData +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/config/src/model/datashare_config.cpp b/datamgr_service/services/distributeddataservice/service/config/src/model/datashare_config.cpp new file mode 100644 index 0000000000000000000000000000000000000000..66f1049622f437e241904a045395c268eac1e23c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/config/src/model/datashare_config.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 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/datashare_config.h" +namespace OHOS { +namespace DistributedData { +bool DataShareConfig::Marshal(json &node) const +{ + SetValue(node[GET_NAME(dataShareExtNames)], dataShareExtNames); + SetValue(node[GET_NAME(updateLaunchNames)], updateLaunchNames); + return true; +} + +bool DataShareConfig::Unmarshal(const json &node) +{ + GetValue(node, GET_NAME(dataShareExtNames), dataShareExtNames); + GetValue(node, GET_NAME(updateLaunchNames), updateLaunchNames); + return true; +} +} // namespace DistributedData +} // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/config/src/model/device_sync_app_white_list_config.cpp b/datamgr_service/services/distributeddataservice/service/config/src/model/device_sync_app_white_list_config.cpp new file mode 100644 index 0000000000000000000000000000000000000000..594d3f2ae9159af93ae90a2e67edc9eabcc821ba --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/config/src/model/device_sync_app_white_list_config.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 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/device_sync_app_white_list_config.h" +namespace OHOS { +namespace DistributedData { +bool DeviceSyncAppWhiteListConfig::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(whiteLists)], whiteLists); + return true; +} +bool DeviceSyncAppWhiteListConfig::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(whiteLists), whiteLists); + return true; +} + +bool DeviceSyncAppWhiteListConfig::WhiteList::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(appId)], appId); + SetValue(node[GET_NAME(bundleName)], bundleName); + SetValue(node[GET_NAME(version)], version); + return true; +} +bool DeviceSyncAppWhiteListConfig::WhiteList::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(appId), appId); + GetValue(node, GET_NAME(bundleName), bundleName); + GetValue(node, GET_NAME(version), version); + return true; +} +} // namespace DistributedData +} // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/config/src/model/directory_config.cpp b/datamgr_service/services/distributeddataservice/service/config/src/model/directory_config.cpp index 9f01b1e70bdb22a951990ee9f792a0f945761a4c..58d4f493061c3d8aead0b6011dd510b2e97bc8fb 100644 --- a/datamgr_service/services/distributeddataservice/service/config/src/model/directory_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/config/src/model/directory_config.cpp @@ -36,15 +36,32 @@ bool DirectoryConfig::DirectoryStrategy::Unmarshal(const json &node) return true; } +bool DirectoryConfig::StoreType::Marshal(json &node) const +{ + SetValue(node[GET_NAME(range)], range); + SetValue(node[GET_NAME(type)], type); + return true; +} + +bool DirectoryConfig::StoreType::Unmarshal(const json &node) +{ + GetValue(node, GET_NAME(range), range); + GetValue(node, GET_NAME(type), type); + return true; +} + bool DirectoryConfig::Marshal(json &node) const { SetValue(node[GET_NAME(strategy)], strategy); + SetValue(node[GET_NAME(storeTypes)], storeTypes); return true; } bool DirectoryConfig::Unmarshal(const json &node) { - return GetValue(node, GET_NAME(strategy), strategy); + GetValue(node, GET_NAME(strategy), strategy); + GetValue(node, GET_NAME(storeTypes), storeTypes); + 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 e64b012260e566a811e6883f32ab5f12e90bce1b..51b12d61e8bab3ab1fc3a63fd4ee875e27d1c763 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 @@ -30,6 +30,9 @@ bool GlobalConfig::Marshal(json &node) const SetValue(node[GET_NAME(cloud)], cloud); SetValue(node[GET_NAME(appIdMapping)], appIdMapping); SetValue(node[GET_NAME(thread)], thread); + SetValue(node[GET_NAME(dataShare)], dataShare); + SetValue(node[GET_NAME(deviceSyncAppWhiteList)], deviceSyncAppWhiteList); + SetValue(node[GET_NAME(syncAppList)], syncAppList); return true; } @@ -47,6 +50,9 @@ bool GlobalConfig::Unmarshal(const json &node) GetValue(node, GET_NAME(cloud), cloud); GetValue(node, GET_NAME(appIdMapping), appIdMapping); GetValue(node, GET_NAME(thread), thread); + GetValue(node, GET_NAME(dataShare), dataShare); + GetValue(node, GET_NAME(deviceSyncAppWhiteList), deviceSyncAppWhiteList); + GetValue(node, GET_NAME(syncAppList), syncAppList); return true; } @@ -60,6 +66,9 @@ GlobalConfig::~GlobalConfig() delete cloud; delete appIdMapping; delete thread; + delete dataShare; + delete deviceSyncAppWhiteList; + delete syncAppList; } } // namespace DistributedData } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn b/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn index 2964c14db7e78cc89bed2489006c97293deb222c..788eceec20f2224e530a7c8ab12c7646d772dd0a 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn @@ -24,14 +24,15 @@ config("module_public_config") { "../../adapter/include", "../../app/src", "../../framework/include", - "${datashare_path}/frameworks/native/common/include", - "${datashare_path}/interfaces/inner_api/common/include", - "${datashare_path}/interfaces/inner_api/consumer/include", "${data_service_path}/adapter/include/communicator", + "${data_service_path}/service/config/include", "../common", "../crypto/include", "../permission/include", ] + if (is_emulator) { + defines = [ "IS_EMULATOR" ] + } } group("build_module") { deps = [ ":data_share_service" ] @@ -48,16 +49,18 @@ ohos_source_set("data_share_service") { sources = [ "common/app_connect_manager.cpp", "common/bundle_mgr_proxy.cpp", + "common/common_utils.cpp", "common/db_delegate.cpp", "common/div_strategy.cpp", "common/extension_ability_manager.cpp", "common/extension_connect_adaptor.cpp", "common/extension_mgr_proxy.cpp", "common/kv_delegate.cpp", + "common/proxy_data_manager.cpp", "common/rdb_delegate.cpp", "common/scheduler_manager.cpp", "common/seq_strategy.cpp", - "common/uri_utils.cpp", + "common/utils.cpp", "data/published_data.cpp", "data/resultset_json_formatter.cpp", "data/template_data.cpp", @@ -85,6 +88,7 @@ ohos_source_set("data_share_service") { "strategies/rdb_notify_strategy.cpp", "strategies/subscribe_strategy.cpp", "strategies/template_strategy.cpp", + "subscriber_managers/proxy_data_subscriber_manager.cpp", "subscriber_managers/published_data_subscriber_manager.cpp", "subscriber_managers/rdb_subscriber_manager.cpp", "sys_event_subscriber.cpp", @@ -94,13 +98,11 @@ ohos_source_set("data_share_service") { "-Wno-multichar", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] configs = [ ":module_public_config" ] @@ -123,6 +125,7 @@ ohos_source_set("data_share_service") { "bundle_framework:appexecfwk_core", "c_utils:utils", "data_share:datashare_common", + "data_share:datashare_common_lite", "device_manager:devicemanagersdk", "hicollie:libhicollie", "hilog:libhilog", @@ -132,6 +135,8 @@ ohos_source_set("data_share_service") { "json:nlohmann_json_static", "kv_store:datamgr_common", "kv_store:distributeddb", + "qos_manager:concurrent_task_client", + "qos_manager:qos", "relational_store:native_rdb", "relational_store:rdb_data_share_adapter", "samgr:samgr_proxy", @@ -140,4 +145,4 @@ ohos_source_set("data_share_service") { subsystem_name = "distributeddatamgr" part_name = "datamgr_service" -} +} \ No newline at end of file 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 410408bebdc46acdf66bf3aeaac84aff456fb54b..afd7e1f4f8523c9f76f3fdd4738ced256f1efcd3 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,13 +16,14 @@ #include "bundle_mgr_proxy.h" #include "account/account_delegate.h" +#include "common_utils.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" +#include "utils.h" #include "ipc_skeleton.h" #include "hiview_fault_adapter.h" @@ -114,6 +115,23 @@ int BundleMgrProxy::GetBundleInfoFromBMS( return E_OK; } +int BundleMgrProxy::GetBundleInfoFromBMSWithCheck( + const std::string &bundleName, int32_t userId, BundleConfig &bundleConfig, int32_t appIndex) +{ + int res = GetBundleInfoFromBMS(bundleName, userId, bundleConfig, appIndex); + if (res != E_OK) { + return res; + } + // Not allow normal app visit normal app. + if (!DataShareThreadLocal::IsFromSystemApp() && !bundleConfig.isSystemApp) { + ZLOGE("Not allow normal app visit normal app, bundle:%{public}s, callingPid:%{public}d", + bundleName.c_str(), IPCSkeleton::GetCallingPid()); + return E_NOT_SYSTEM_APP; + } + + return E_OK; +} + std::pair BundleMgrProxy::GetCallerAppIdentifier( const std::string &bundleName, int32_t userId) { @@ -179,7 +197,7 @@ void BundleMgrProxy::Delete(const std::string &bundleName, int32_t userId, int32 std::shared_ptr BundleMgrProxy::GetInstance() { - static std::shared_ptr proxy(new BundleMgrProxy()); + static std::shared_ptr proxy = std::make_shared(); return proxy; } @@ -199,6 +217,7 @@ std::pair BundleMgrProxy::ConvertToDataShareBundle(AppExecFwk return std::make_pair(err, bundleConfig); } bundleConfig.extensionInfos = extensionInfos; + bundleConfig.isSystemApp = bundleInfo.applicationInfo.isSystemApp; return std::make_pair(E_OK, bundleConfig); } @@ -243,6 +262,7 @@ std::pair> BundleMgrProxy::ConvertHapModuleInfo( hapModuleInfo.resourcePath = std::move(item.resourcePath); hapModuleInfo.hapPath = std::move(item.hapPath); hapModuleInfo.moduleName = std::move(item.moduleName); + hapModuleInfo.crossAppSharedConfig.resourcePath = std::move(item.crossAppSharedConfig); std::vector proxyDatas; for (auto &proxyData : item.proxyDatas) { ProxyData data; 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 71bcc496eb74f059dc2830fcd47a6aaa767bb735..7198715f13ab791ed66c14ba7dfca73b089f6d95 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 @@ -37,11 +37,17 @@ struct ProxyData { ProfileConfig profileInfo; }; +struct CrossAppSharedConfig { + std::string resourcePath; + ProxyDataProfileInfo profile; +}; + struct HapModuleInfo { std::string resourcePath; std::string hapPath; std::string moduleName; std::vector proxyDatas; + CrossAppSharedConfig crossAppSharedConfig; }; struct ExtensionAbilityInfo { @@ -57,21 +63,32 @@ struct ExtensionAbilityInfo { struct BundleConfig { std::string name; bool singleton = false; + bool isSystemApp = false; std::vector hapModuleInfos; std::vector extensionInfos; }; +struct BundleInfo { + std::string bundleName; + std::string appIdentifier; + int32_t userId; + int32_t appIndex; + uint32_t tokenId; +}; + class BundleMgrProxy final : public std::enable_shared_from_this { public: + BundleMgrProxy() = default; ~BundleMgrProxy(); static std::shared_ptr GetInstance(); int GetBundleInfoFromBMS(const std::string &bundleName, int32_t userId, BundleConfig &bundleConfig, int32_t appIndex = 0); + int GetBundleInfoFromBMSWithCheck(const std::string &bundleName, int32_t userId, + BundleConfig &bundleConfig, int32_t appIndex = 0); void Delete(const std::string &bundleName, int32_t userId, int32_t appIndex); sptr CheckBMS(); std::pair GetCallerAppIdentifier(const std::string &bundleName, int32_t userId); private: - BundleMgrProxy() = default; class ServiceDeathRecipient : public IRemoteObject::DeathRecipient { public: explicit ServiceDeathRecipient(std::weak_ptr owner) : owner_(owner) {} diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/common_utils.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/common_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..824008e7a65c473b56eeb9cb0e251f83bf946137 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/common_utils.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025 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 "CommonUtils" +#include "common_utils.h" + +#include "accesstoken_kit.h" +#include "config_factory.h" +#include "log_print.h" +#include "tokenid_kit.h" + +namespace OHOS::DataShare { + +bool& DataShareThreadLocal::GetFromSystemApp() +{ + static thread_local bool isFromSystemApp = true; + return isFromSystemApp; +} + +void DataShareThreadLocal::SetFromSystemApp(bool isFromSystemApp) +{ + GetFromSystemApp() = isFromSystemApp; +} + +bool DataShareThreadLocal::IsFromSystemApp() +{ + return GetFromSystemApp(); +} + +void DataShareThreadLocal::CleanFromSystemApp() +{ + SetFromSystemApp(true); +} + +bool CheckSystemAbility(uint32_t tokenId) +{ + Security::AccessToken::ATokenTypeEnum tokenType = + Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId); + return (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE || + tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL); +} + +// GetTokenType use tokenId, and IsSystemApp use fullTokenId, these are different +bool CheckSystemCallingPermission(uint32_t tokenId, uint64_t fullTokenId) +{ + if (CheckSystemAbility(tokenId)) { + return true; + } + // IsSystemAppByFullTokenID here is not IPC + return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId); +} + +} // namespace OHOS::DataShare diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/common_utils.h b/datamgr_service/services/distributeddataservice/service/data_share/common/common_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..58c5cbd3869459decc829158099b47534976f83a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/common_utils.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 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 DATASHARESERVICE_COMMON_UTILS_H +#define DATASHARESERVICE_COMMON_UTILS_H + +#include +#include +#include + +namespace OHOS::DataShare { +struct DataShareThreadLocal { + static bool& GetFromSystemApp(); + static void SetFromSystemApp(bool isFromSystemApp); + static bool IsFromSystemApp(); + static void CleanFromSystemApp(); +}; + +bool CheckSystemAbility(uint32_t tokenId); + +bool CheckSystemCallingPermission(uint32_t tokenId, uint64_t fullTokenId); + +inline int64_t GetSystemTime() +{ + return std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count(); +} + +} // namespace OHOS::DataShare +#endif // DATASHARESERVICE_COMMON_UTILS_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 62da611a254d8d44c04454d0a122c9623d542028..e7043d23f4e195b17ffe15d550135dbc0041b2de 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/context.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/context.h @@ -16,6 +16,7 @@ #ifndef DATASHARESERVICE_CONTEXT_H #define DATASHARESERVICE_CONTEXT_H +#include #include #include #include @@ -34,9 +35,16 @@ class Context { public: explicit Context() {} explicit Context(const std::string &uri) : uri(uri) {} - virtual ~Context() = default; + virtual ~Context() + { + if (secretMetaKey.size() > 0) { + std::fill(secretMetaKey.begin(), secretMetaKey.end(), '\0'); + } + } + std::string uri; int32_t currentUserId = -1; + int32_t visitedUserId = -1; int32_t appIndex = 0; int32_t haMode = 0; std::string permission; 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 50196297bc07fdfe60a94bcbc58ff6d62a6fbc46..9e77bcbb4dece55fc62f1ac907b7be2f95bbed01 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 @@ -16,7 +16,7 @@ #define LOG_TAG "DBAdaptor" #include "db_delegate.h" -#include "account_delegate.h" +#include "account/account_delegate.h" #include "kv_delegate.h" #include "log_print.h" #include "rdb_delegate.h" @@ -34,7 +34,7 @@ std::shared_ptr DBDelegate::Create(DistributedData::StoreMetaData &m { if (Account::GetInstance()->IsDeactivating(atoi(metaData.user.c_str()))) { ZLOGW("user %{public}s is deactivating, storeName: %{public}s", metaData.user.c_str(), - metaData.GetStoreAlias().c_str()); + StringUtils::GeneralAnonymous(metaData.GetStoreAlias()).c_str()); return nullptr; } std::shared_ptr store; @@ -46,12 +46,7 @@ std::shared_ptr DBDelegate::Create(DistributedData::StoreMetaData &m 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; - } + store = std::make_shared(); auto entity = std::make_shared(store, metaData); stores.emplace(metaData.storeId, entity); StartTimer(metaData.isEncrypt); @@ -62,7 +57,24 @@ std::shared_ptr DBDelegate::Create(DistributedData::StoreMetaData &m } else { stores_.Compute(metaData.tokenId, storeFunc); } - return store; + + // rdbStore is initialized outside the ConcurrentMap, because this maybe a time-consuming operation. + bool success = store->Init(metaData, NO_CHANGE_VERSION, true, extUri, backup); + if (success) { + return store; + } + ZLOGE("creator failed, storeName: %{public}s", StringUtils::GeneralAnonymous(metaData.GetStoreAlias()).c_str()); + auto eraseFunc = [&metaData] + (auto &, std::map> &stores) -> bool { + stores.erase(metaData.storeId); + return !stores.empty(); + }; + if (metaData.isEncrypt) { + storesEncrypt_.Compute(metaData.tokenId, eraseFunc); + } else { + stores_.Compute(metaData.tokenId, eraseFunc); + } + return nullptr; } void DBDelegate::SetExecutorPool(std::shared_ptr executor) @@ -155,13 +167,13 @@ void DBDelegate::EraseStoreCache(const int32_t tokenId) storesEncrypt_.Erase(tokenId); } -std::shared_ptr KvDBDelegate::GetInstance( - bool reInit, const std::string &dir, const std::shared_ptr &executors) +std::shared_ptr KvDBDelegate::GetInstance(const std::string &dir, + const std::shared_ptr &executors) { static std::shared_ptr delegate = nullptr; static std::mutex mutex; std::lock_guard lock(mutex); - if ((delegate == nullptr || reInit) && executors != nullptr) { + if (delegate == nullptr && executors != nullptr) { delegate = std::make_shared(dir, executors); } return delegate; @@ -203,4 +215,4 @@ const std::string &KvData::GetId() const } KvData::KvData(const Id &id) : id(DistributedData::Serializable::Marshall(id)) {} -} // namespace OHOS::DataShare \ No newline at end of file +} // namespace OHOS::DataShare 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 0cb36808d507731ba5dcdcff61549766c7fad631..804a6763347184e02025e585734ca5906355997c 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 @@ -37,6 +37,8 @@ public: using Filter = std::function; static std::shared_ptr Create(DistributedData::StoreMetaData &metaData, const std::string &extUri = "", const std::string &backup = ""); + virtual bool Init(const DistributedData::StoreMetaData &meta, int version, + bool registerFunction, const std::string &extUri, const std::string &backup) = 0; static void Close(const Filter &filter); virtual std::pair> Query(const std::string &tableName, const DataSharePredicates &predicates, const std::vector &columns, @@ -125,11 +127,12 @@ class KvDBDelegate { public: static constexpr const char *TEMPLATE_TABLE = "template_"; static constexpr const char *DATA_TABLE = "data_"; + static constexpr const char *PROXYDATA_TABLE = "proxydata_"; static std::shared_ptr GetInstance( - bool reInit = false, const std::string &dir = "", const std::shared_ptr &executors = nullptr); + const std::string &dir = "", const std::shared_ptr &executors = nullptr); virtual ~KvDBDelegate() = default; - virtual std::pair Upsert(const std::string &collectionName, const KvData &value) = 0; - virtual std::pair Delete(const std::string &collectionName, const std::string &filter) = 0; + virtual std::pair Upsert(const std::string &collectionName, const KvData &value) = 0; + virtual std::pair Delete(const std::string &collectionName, const std::string &filter) = 0; virtual int32_t Get(const std::string &collectionName, const Id &id, std::string &value) = 0; virtual int32_t Get(const std::string &collectionName, const std::string &filter, const std::string &projection, std::string &result) = 0; 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 2328285df370c1f67f2b2bcc51788ba1d3e28416..fa1011fde7489a4fadd8730809dbcad0c8f76169 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 @@ -19,7 +19,7 @@ #include "extension_mgr_proxy.h" #include "log_print.h" #include "datashare_errno.h" -#include "uri_utils.h" +#include "utils.h" namespace OHOS::DataShare { ExtensionAbilityManager &ExtensionAbilityManager::GetInstance() 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 6a48232a4598c1175220a89d5797bccdf2429b38..357b3560b4da4032a663e9967d169ecdb7f12468 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 @@ -24,7 +24,7 @@ #include "extension_ability_info.h" #include "extension_mgr_proxy.h" #include "log_print.h" -#include "uri_utils.h" +#include "utils.h" namespace OHOS::DataShare { ExtensionConnectAdaptor::ExtensionConnectAdaptor() : data_(std::make_shared>(1)) 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 dacd6ce8826dc757ba5b0839b4d41bc2d3ecd8c0..fce328cda61ba9d72c575d9dfe4a406eaba3b4f8 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 @@ -23,7 +23,7 @@ #include "log_print.h" #include "system_ability_definition.h" #include "want.h" -#include "uri_utils.h" +#include "utils.h" #include "datashare_errno.h" namespace OHOS::DataShare { 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 be360b40b615c146e1bcbf45acd12be84951b573..1c2375d436fc28151aa10bed469093ab6922e147 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 @@ -15,6 +15,7 @@ #define LOG_TAG "KvAdaptor" #include +#include #include #include #include @@ -23,14 +24,16 @@ #include "datashare_errno.h" #include "directory/directory_manager.h" +#include "hiview_fault_adapter.h" #include "grd_base/grd_error.h" #include "grd_document/grd_document_api.h" #include "ipc_skeleton.h" #include "log_print.h" #include "log_debug.h" +#include "time_service_client.h" namespace OHOS::DataShare { -constexpr int WAIT_TIME = 30; +constexpr int64_t TIME_LIMIT_BY_MILLISECONDS = 18 * 3600 * 1000; // 18 hours // If using multi-process access, back up dataShare.db.map as well. Check config file to see whether // using multi-process maccess @@ -126,6 +129,8 @@ bool KvDelegate::RestoreIfNeed(int32_t dbStatus) db_ = nullptr; isInitDone_ = false; } + DataShareFaultInfo faultInfo{HiViewFaultAdapter::kvDBCorrupt, "", "", "", __FUNCTION__, dbStatus, ""}; + HiViewFaultAdapter::ReportDataFault(faultInfo); // If db is NULL, it has been closed. Restore(); return true; @@ -185,11 +190,39 @@ std::pair KvDelegate::Delete(const std::string &collectionName return std::make_pair(E_OK, deleteCount); } +void KvDelegate::ScheduleBackup() +{ + auto currTime = MiscServices::TimeServiceClient::GetInstance()->GetBootTimeMs(); + if (currTime < 0) { + // Only do an error log print since schedule time does not rely on the time gets by GetBootTimeMs(). + ZLOGE("GetBootTimeMs failed, status %{public}" PRId64 "", currTime); + } else { + absoluteWaitTime_ = currTime + TIME_LIMIT_BY_MILLISECONDS; + } + + taskId_ = executors_->Schedule(std::chrono::seconds(waitTime_), [this]() { + std::lock_guard lock(mutex_); + GRD_DBClose(db_, GRD_DB_CLOSE); + db_ = nullptr; + isInitDone_ = false; + taskId_ = ExecutorPool::INVALID_TASK_ID; + Backup(); + }); +} + bool KvDelegate::Init() { if (isInitDone_) { if (executors_ != nullptr) { - executors_->Reset(taskId_, std::chrono::seconds(WAIT_TIME)); + auto currTime = MiscServices::TimeServiceClient::GetInstance()->GetBootTimeMs(); + if (currTime < 0) { + ZLOGE("GetBootTimeMs failed, status %{public}" PRId64 "", currTime); + // still return true since kv can work normally + return true; + } + if (currTime < absoluteWaitTime_) { + executors_->Reset(taskId_, std::chrono::seconds(waitTime_)); + } } return true; } @@ -201,14 +234,8 @@ bool KvDelegate::Init() return false; } if (executors_ != nullptr) { - taskId_ = executors_->Schedule(std::chrono::seconds(WAIT_TIME), [this]() { - std::lock_guard lock(mutex_); - GRD_DBClose(db_, GRD_DB_CLOSE); - db_ = nullptr; - isInitDone_ = false; - taskId_ = ExecutorPool::INVALID_TASK_ID; - Backup(); - }); + // schedule first backup task + ScheduleBackup(); } status = GRD_CreateCollection(db_, TEMPLATE_TABLE, nullptr, 0); if (status != GRD_OK) { @@ -225,6 +252,14 @@ bool KvDelegate::Init() RestoreIfNeed(status); return false; } + + status = GRD_CreateCollection(db_, PROXYDATA_TABLE, nullptr, 0); + if (status != GRD_OK) { + // 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; return true; } @@ -368,4 +403,4 @@ KvDelegate::KvDelegate(const std::string &path, const std::shared_ptr executors_ = nullptr; ExecutorPool::TaskId taskId_ = ExecutorPool::INVALID_TASK_ID; bool hasChange_ = false; + int64_t absoluteWaitTime_ = 0; + int64_t waitTime_ = 6 * 3600; // 6 hours }; } // namespace OHOS::DataShare #endif // DATASHARESERVICE_KV_DELEGATE_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/proxy_data_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/proxy_data_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..18a7b53638bba26d8af0210612673f6166ae8932 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/proxy_data_manager.cpp @@ -0,0 +1,490 @@ +/* + * Copyright (c) 2025 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 "ProxyDataManager" + +#include "datashare_observer.h" +#include "data_share_profile_config.h" +#include "dataproxy_handle_common.h" +#include "log_print.h" +#include "proxy_data_manager.h" +#include "utils.h" +#include "utils/anonymous.h" + +namespace OHOS::DataShare { + +ProxyDataManager &ProxyDataManager::GetInstance() +{ + static ProxyDataManager instance; + return instance; +} + +ProxyDataList::ProxyDataList(const ProxyDataListNode &node) + : KvData(Id(std::to_string(node.tokenId), node.userId)), value(node) +{ +} + +bool ProxyDataList::HasVersion() const +{ + return true; +} + +int ProxyDataList::GetVersion() const +{ + return value.GetVersion(); +} + +std::string ProxyDataList::GetValue() const +{ + return DistributedData::Serializable::Marshall(value); +} + +PublishedProxyData::PublishedProxyData(const ProxyDataNode &node) + : KvData(Id(node.proxyData.uri, node.userId)), value(node) +{ +} + +bool PublishedProxyData::HasVersion() const +{ + return true; +} + +int PublishedProxyData::GetVersion() const +{ + return value.GetVersion(); +} + +std::string PublishedProxyData::GetValue() const +{ + return DistributedData::Serializable::Marshall(value); +} + +ProxyDataListNode::ProxyDataListNode() : VersionData(-1) {} + +ProxyDataNode::ProxyDataNode() : VersionData(-1) {} + +bool ProxyDataNode::Marshal(DistributedData::Serializable::json &node) const +{ + bool ret = SetValue(node[GET_NAME(proxyData)], proxyData); + ret = ret && SetValue(node[GET_NAME(userId)], userId); + ret = ret && SetValue(node[GET_NAME(tokenId)], tokenId); + return ret && VersionData::Marshal(node); +} + +bool ProxyDataNode::Unmarshal(const DistributedData::Serializable::json &node) +{ + bool ret = GetValue(node, GET_NAME(proxyData), proxyData); + ret = ret && GetValue(node, GET_NAME(userId), userId); + return ret && GetValue(node, GET_NAME(tokenId), tokenId); +} + +bool ProxyDataListNode::Marshal(DistributedData::Serializable::json &node) const +{ + bool ret = SetValue(node[GET_NAME(uris)], uris); + ret = ret && SetValue(node[GET_NAME(userId)], userId); + ret = ret && SetValue(node[GET_NAME(tokenId)], tokenId); + return ret && VersionData::Marshal(node); +} + +bool ProxyDataListNode::Unmarshal(const DistributedData::Serializable::json &node) +{ + bool ret = GetValue(node, GET_NAME(uris), uris); + ret = ret && GetValue(node, GET_NAME(userId), userId); + ret = ret && GetValue(node, GET_NAME(tokenId), tokenId); + return ret; +} + +bool PublishedProxyData::VerifyPermission(const BundleInfo &callerBundleInfo, const ProxyDataNode &data) +{ + if (callerBundleInfo.tokenId == data.tokenId) { + return true; + } + + for (const auto &item : data.proxyData.allowList) { + if (callerBundleInfo.appIdentifier == item) { + return true; + } + } + return false; +} + +bool PublishedProxyData::CheckAndCorrectProxyData(DataShareProxyData &proxyData) +{ + // the upper limit of value is 4096 bytes, only string type is possible to exceed the limit + if (proxyData.value_.index() == DataProxyValueType::VALUE_STRING) { + std::string valueStr = std::get(proxyData.value_); + if (valueStr.size() > VALUE_MAX_SIZE) { + ZLOGE("value of proxyData %{public}s is over limit, size %{public}zu", + URIUtils::Anonymous(proxyData.uri_).c_str(), valueStr.size()); + return false; + } + } + if (proxyData.uri_.size() > URI_MAX_SIZE) { + ZLOGE("uri of proxyData %{public}s is over limit, size %{public}zu", + URIUtils::Anonymous(proxyData.uri_).c_str(), proxyData.uri_.size()); + return false; + } + int32_t allowListCount = 1; + auto it = proxyData.allowList_.begin(); + while (it != proxyData.allowList_.end()) { + if (it->size() > APPIDENTIFIER_MAX_SIZE) { + ZLOGW("appidentifier of proxyData %{public}s is over limit, size %{public}zu", + URIUtils::Anonymous(proxyData.uri_).c_str(), it->size()); + it = proxyData.allowList_.erase(it); + } else { + if (allowListCount++ > ALLOW_LIST_MAX_COUNT) { + break; + } + it++; + } + } + if (proxyData.allowList_.size() > ALLOW_LIST_MAX_COUNT) { + ZLOGW("allowList of proxyData %{public}s is over limit, size %{public}zu", + URIUtils::Anonymous(proxyData.uri_).c_str(), proxyData.allowList_.size()); + proxyData.allowList_.resize(ALLOW_LIST_MAX_COUNT); + } + return true; +} + +int32_t PublishedProxyData::PutIntoTable(std::shared_ptr kvDelegate, int32_t user, + uint32_t tokenId, const std::vector &proxyDataList, const DataShareProxyData &proxyData) +{ + if (kvDelegate == nullptr) { + ZLOGE("kv delegate is null!"); + return INNER_ERROR; + } + + SerialDataShareProxyData serialProxyData(proxyData.uri_, proxyData.value_, proxyData.allowList_); + auto ret = kvDelegate->Upsert(KvDBDelegate::PROXYDATA_TABLE, PublishedProxyData(ProxyDataNode( + serialProxyData, user, tokenId))); + if (ret.first != E_OK) { + ZLOGE("db Upsert failed, %{public}s %{public}d", + URIUtils::Anonymous(proxyData.uri_).c_str(), ret.first); + return INNER_ERROR; + } + + if (!proxyDataList.empty()) { + auto value = ProxyDataList(ProxyDataListNode( + proxyDataList, user, tokenId)); + ret = kvDelegate->Upsert(KvDBDelegate::PROXYDATA_TABLE, value); + if (ret.first != E_OK) { + ZLOGE("db Upsert failed, %{public}x %{public}d", tokenId, user); + return INNER_ERROR; + } + } + return SUCCESS; +} + +int32_t PublishedProxyData::InsertProxyData(std::shared_ptr kvDelegate, const std::string &bundleName, + const int32_t &user, const uint32_t &tokenId, const DataShareProxyData &proxyData) +{ + if (kvDelegate == nullptr) { + ZLOGE("kv delegate is null!"); + return INNER_ERROR; + } + + ProxyDataListNode proxyDataList; + std::string listFilter = Id(std::to_string(tokenId), user); + std::string listQueryResult; + kvDelegate->Get(KvDBDelegate::PROXYDATA_TABLE, listFilter, "{}", listQueryResult); + if (!listQueryResult.empty()) { + if (!ProxyDataListNode::Unmarshall(listQueryResult, proxyDataList)) { + ZLOGE("ProxyDataListNode unmarshall failed, %{public}s", + StringUtils::GeneralAnonymous(listQueryResult).c_str()); + return INNER_ERROR; + } + } + if (proxyDataList.uris.size() >= PROXY_DATA_MAX_COUNT) { + return OVER_LIMIT; + } + + std::string modifyBundle; + URIUtils::GetBundleNameFromProxyURI(proxyData.uri_, modifyBundle); + if (modifyBundle != bundleName) { + ZLOGE("only allowed to publish the proxyData of self bundle %{public}s, dest bundle %{public}s", + bundleName.c_str(), modifyBundle.c_str()); + return NO_PERMISSION; + } + + auto it = std::find(proxyDataList.uris.begin(), proxyDataList.uris.end(), proxyData.uri_); + if (it == proxyDataList.uris.end()) { + proxyDataList.uris.emplace_back(proxyData.uri_); + } + return PutIntoTable(kvDelegate, user, tokenId, proxyDataList.uris, proxyData); +} + +int32_t PublishedProxyData::UpdateProxyData(std::shared_ptr kvDelegate, const std::string &bundleName, + const int32_t &user, const uint32_t &tokenId, const DataShareProxyData &proxyData) +{ + if (kvDelegate == nullptr) { + ZLOGE("kv delegate is null!"); + return INNER_ERROR; + } + std::vector proxyDataList; + return PutIntoTable(kvDelegate, user, tokenId, proxyDataList, proxyData); +} + +int32_t PublishedProxyData::Query(const std::string &uri, const BundleInfo &callerBundleInfo, + DataShareProxyData &proxyData) +{ + auto delegate = KvDBDelegate::GetInstance(); + if (delegate == nullptr) { + ZLOGE("db open failed"); + return INNER_ERROR; + } + std::string filter = Id(uri, callerBundleInfo.userId); + std::string queryResult; + delegate->Get(KvDBDelegate::PROXYDATA_TABLE, filter, "{}", queryResult); + if (queryResult.empty()) { + return URI_NOT_EXIST; + } + ProxyDataNode data; + if (!ProxyDataNode::Unmarshall(queryResult, data)) { + ZLOGE("Unmarshall failed, %{public}s", StringUtils::GeneralAnonymous(queryResult).c_str()); + return INNER_ERROR; + } + DataShareProxyData tempProxyData(data.proxyData.uri, data.proxyData.value, data.proxyData.allowList); + if (callerBundleInfo.tokenId != data.tokenId) { + tempProxyData.allowList_ = {}; + } + if (!VerifyPermission(callerBundleInfo, data)) { + return NO_PERMISSION; + } + + proxyData = tempProxyData; + return SUCCESS; +} + +int32_t PublishedProxyData::Upsert(const DataShareProxyData &proxyData, const BundleInfo &callerBundleInfo, + DataShareObserver::ChangeType &type) +{ + type = DataShareObserver::ChangeType::INVAILD; + auto delegate = KvDBDelegate::GetInstance(); + if (delegate == nullptr) { + ZLOGE("db open failed"); + return INNER_ERROR; + } + + auto data = proxyData; + if (!CheckAndCorrectProxyData(data)) { + return OVER_LIMIT; + } + std::string filter = Id(data.uri_, callerBundleInfo.userId); + std::string queryResult; + delegate->Get(KvDBDelegate::PROXYDATA_TABLE, filter, "{}", queryResult); + if (queryResult.empty()) { + type = DataShareObserver::ChangeType::INSERT; + return InsertProxyData(delegate, callerBundleInfo.bundleName, + callerBundleInfo.userId, callerBundleInfo.tokenId, data); + } else { + ProxyDataNode oldData; + if (!ProxyDataNode::Unmarshall(queryResult, oldData)) { + ZLOGE("ProxyDataNode unmarshall failed, %{public}s", StringUtils::GeneralAnonymous(queryResult).c_str()); + return INNER_ERROR; + } + if (callerBundleInfo.tokenId != oldData.tokenId) { + ZLOGE("only allow to modify the proxyData of self bundle %{public}d, dest bundle %{public}d", + callerBundleInfo.tokenId, oldData.tokenId); + return NO_PERMISSION; + } + if (data.isValueUndefined) { + data.value_ = oldData.proxyData.value; + } + if (data.isAllowListUndefined) { + data.allowList_ = oldData.proxyData.allowList; + } + // only when value changed is need notify + if (oldData.proxyData.value != data.value_) { + type = DataShareObserver::ChangeType::UPDATE; + } + return UpdateProxyData(delegate, callerBundleInfo.bundleName, + callerBundleInfo.userId, callerBundleInfo.tokenId, data); + } +} + +int32_t PublishedProxyData::Delete(const std::string &uri, const BundleInfo &callerBundleInfo, + DataShareProxyData &oldProxyData, DataShareObserver::ChangeType &type) +{ + type = DataShareObserver::ChangeType::INVAILD; + auto delegate = KvDBDelegate::GetInstance(); + if (delegate == nullptr) { + ZLOGE("db open failed"); + return INNER_ERROR; + } + + std::string bundleName; + URIUtils::GetBundleNameFromProxyURI(uri, bundleName); + if (callerBundleInfo.bundleName != bundleName) { + return NO_PERMISSION; + } + std::string queryResult; + delegate->Get(KvDBDelegate::PROXYDATA_TABLE, Id(uri, callerBundleInfo.userId), "{}", queryResult); + if (queryResult.empty()) { + return URI_NOT_EXIST; + } + + ProxyDataNode oldData; + if (!ProxyDataNode::Unmarshall(queryResult, oldData)) { + ZLOGE("Unmarshall failed, %{private}s", queryResult.c_str()); + return INNER_ERROR; + } + if (callerBundleInfo.tokenId != oldData.tokenId) { + return NO_PERMISSION; + } + auto ret = delegate->Delete(KvDBDelegate::PROXYDATA_TABLE, Id(uri, callerBundleInfo.userId)); + if (ret.first != E_OK) { + ZLOGE("db Delete failed, %{public}s %{public}d", URIUtils::Anonymous(uri).c_str(), ret.first); + return INNER_ERROR; + } + std::vector uris; + auto count = ProxyDataList::Query(callerBundleInfo.tokenId, callerBundleInfo.userId, uris); + if (count <= 0) { + ZLOGI("get bundle %{public}s's proxyData failed", callerBundleInfo.bundleName.c_str()); + return INNER_ERROR; + } + auto it = std::find(uris.begin(), uris.end(), uri); + if (it != uris.end()) { + uris.erase(it); + } + ret = delegate->Upsert(KvDBDelegate::PROXYDATA_TABLE, ProxyDataList(ProxyDataListNode( + uris, callerBundleInfo.userId, callerBundleInfo.tokenId))); + if (ret.first != E_OK) { + ZLOGE("db Upsert failed, %{public}x %{public}d", callerBundleInfo.tokenId, ret.first); + return INNER_ERROR; + } + oldProxyData = DataShareProxyData(oldData.proxyData.uri, oldData.proxyData.value, oldData.proxyData.allowList); + type = DataShareObserver::ChangeType::DELETE; + return SUCCESS; +} + +int32_t ProxyDataList::Query(uint32_t tokenId, int32_t userId, std::vector &proxyDataList) +{ + int32_t invalidNum = -1; + auto delegate = KvDBDelegate::GetInstance(); + if (delegate == nullptr) { + ZLOGE("db open failed"); + return invalidNum; + } + std::string filter = Id(std::to_string(tokenId), userId); + std::string queryResult; + delegate->Get(KvDBDelegate::PROXYDATA_TABLE, filter, "{}", queryResult); + if (queryResult.empty()) { + return invalidNum; + } + ProxyDataListNode data; + if (!ProxyDataListNode::Unmarshall(queryResult, data)) { + ZLOGE("Unmarshall failed, %{public}s", StringUtils::GeneralAnonymous(queryResult).c_str()); + return invalidNum; + } + + proxyDataList = std::move(data.uris); + return proxyDataList.size(); +} + +bool ProxyDataManager::GetCrossAppSharedConfig(const std::string &bundleName, int32_t user, + int32_t index, std::vector &proxyDatas) +{ + BundleConfig bundleConfig; + auto ret = BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS(bundleName, user, bundleConfig, index); + if (ret != E_OK) { + ZLOGE("Get bundleInfo falied, ret : %{public}d", ret); + return false; + } + std::vector resourcePath; + std::vector datas; + std::for_each(bundleConfig.hapModuleInfos.begin(), + bundleConfig.hapModuleInfos.end(), [&datas](const HapModuleInfo hapModuleInfo) { + if (!hapModuleInfo.crossAppSharedConfig.resourcePath.empty()) { + auto [ret, data] = DataShareProfileConfig::GetCrossAppSharedConfig( + hapModuleInfo.crossAppSharedConfig.resourcePath, hapModuleInfo.resourcePath, hapModuleInfo.hapPath); + if (ret == SUCCESS) { + datas.insert(datas.end(), data.begin(), data.end()); + } else { + ZLOGE("get shareConfig failed, err: %{public}d", ret); + } + } + }); + std::for_each(datas.begin(), datas.end(), [&proxyDatas](auto &data) { + proxyDatas.emplace_back(std::move(data.uri), std::move(data.value), std::move(data.allowList)); + }); + return true; +} + +void ProxyDataManager::OnAppInstall(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId) +{ + std::vector proxyDatas; + BundleInfo callerBundleInfo; + callerBundleInfo.bundleName = bundleName; + callerBundleInfo.userId = user; + callerBundleInfo.appIndex = index; + callerBundleInfo.tokenId = tokenId; + if (!GetCrossAppSharedConfig(bundleName, user, index, proxyDatas)) { + ZLOGE("GetCrossAppSharedConfig after install failed"); + return; + } + DataShareObserver::ChangeType type; + std::for_each(proxyDatas.begin(), proxyDatas.end(), + [user, bundleName, callerBundleInfo, &type](const DataShareProxyData proxyData) { + PublishedProxyData::Upsert(proxyData, callerBundleInfo, type); + }); +} + +void ProxyDataManager::OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId) +{ + std::vector proxyDatas; + BundleInfo callerBundleInfo; + callerBundleInfo.bundleName = bundleName; + callerBundleInfo.userId = user; + callerBundleInfo.appIndex = index; + callerBundleInfo.tokenId = tokenId; + DataShareObserver::ChangeType type; + if (!GetCrossAppSharedConfig(bundleName, user, index, proxyDatas)) { + ZLOGE("GetCrossAppSharedConfig after install failed"); + return; + } + std::vector uris; + auto count = ProxyDataList::Query(tokenId, user, uris); + if (count <= 0) { + ZLOGI("bundle %{public}s has no proxyData", bundleName.c_str()); + } + DataShareProxyData oldProxyData; + for (const auto &uri : uris) { + PublishedProxyData::Delete(uri, callerBundleInfo, oldProxyData, type); + } + std::for_each(proxyDatas.begin(), proxyDatas.end(), + [user, bundleName, callerBundleInfo, &type](const DataShareProxyData proxyData) { + PublishedProxyData::Upsert(proxyData, callerBundleInfo, type); + }); +} + +void ProxyDataManager::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId) +{ + DataShareProxyData proxyData; + BundleInfo callerBundleInfo; + callerBundleInfo.bundleName = bundleName; + callerBundleInfo.userId = user; + callerBundleInfo.appIndex = index; + callerBundleInfo.tokenId = tokenId; + DataShareObserver::ChangeType type; + std::vector uris; + auto count = ProxyDataList::Query(tokenId, user, uris); + if (count <= 0) { + ZLOGI("bundle %{public}s has no proxyData", bundleName.c_str()); + } + for (const auto &uri : uris) { + PublishedProxyData::Delete(uri, callerBundleInfo, proxyData, type); + } +} +} // namespace OHOS::DataShare \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/proxy_data_manager.h b/datamgr_service/services/distributeddataservice/service/data_share/common/proxy_data_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..75da70ed1bc913251c817b7bd0286603d9e78b6a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/proxy_data_manager.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2025 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 DATASHARESERVICE_PROXY_DATA_MANAGER_H +#define DATASHARESERVICE_PROXY_DATA_MANAGER_H + +#include "bundle_mgr_proxy.h" +#include "dataproxy_handle_common.h" +#include "db_delegate.h" + +namespace OHOS::DataShare { + +class ProxyDataListNode final : public VersionData { +public: + ProxyDataListNode(); + ProxyDataListNode(const std::vector &uris, int32_t userId, uint32_t tokenId) + : VersionData(0), uris(uris), userId(userId), tokenId(tokenId) {} + ~ProxyDataListNode() = default; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + std::vector uris; + int32_t userId = Id::INVALID_USER; + uint32_t tokenId = 0; +}; + +class ProxyDataList final : public KvData { +public: + explicit ProxyDataList(const ProxyDataListNode &node); + ~ProxyDataList() = default; + static int32_t Query(uint32_t tokenId, int32_t userId, std::vector &proxyDataList); + bool HasVersion() const override; + int GetVersion() const override; + std::string GetValue() const override; + +private: + ProxyDataListNode value; +}; + +class ProxyDataNode final : public VersionData { +public: + ProxyDataNode(); + ProxyDataNode(const SerialDataShareProxyData proxyData, int32_t userId, uint32_t tokenId) + : VersionData(0), proxyData(proxyData), userId(userId), tokenId(tokenId) {} + ~ProxyDataNode() = default; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + SerialDataShareProxyData proxyData; + int32_t userId = Id::INVALID_USER; + uint32_t tokenId = 0; +}; + +class PublishedProxyData final : public KvData { +public: + explicit PublishedProxyData(const ProxyDataNode &node); + ~PublishedProxyData() = default; + static int32_t Query(const std::string &uri, const BundleInfo &callerBundleInfo, DataShareProxyData &proxyData); + static int32_t Delete(const std::string &uri, const BundleInfo &callerBundleInfo, DataShareProxyData &oldProxyData, + DataShareObserver::ChangeType &type); + static int32_t Upsert(const DataShareProxyData &proxyData, const BundleInfo &callerBundleInfo, + DataShareObserver::ChangeType &type); + static bool VerifyPermission(const BundleInfo &callerBundleInfo, const ProxyDataNode &data); + bool HasVersion() const override; + int GetVersion() const override; + std::string GetValue() const override; + +private: + static int32_t InsertProxyData(std::shared_ptr kvDelegate, const std::string &bundleName, + const int32_t &user, const uint32_t &tokenId, const DataShareProxyData &proxyData); + static int32_t UpdateProxyData(std::shared_ptr kvDelegate, const std::string &bundleName, + const int32_t &user, const uint32_t &tokenId, const DataShareProxyData &proxyData); + static int32_t PutIntoTable(std::shared_ptr kvDelegate, int32_t user, + uint32_t tokenId, const std::vector &proxyDataList, const DataShareProxyData &proxyData); + static bool CheckAndCorrectProxyData(DataShareProxyData &proxyData); + ProxyDataNode value; +}; + +class ProxyDataManager { +public: + static ProxyDataManager &GetInstance(); + void OnAppInstall(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId); + void OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId); + void OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId); + +private: + bool GetCrossAppSharedConfig(const std::string &bundleName, int32_t user, int32_t index, + std::vector &proxyDatas); +}; +} // namespace OHOS::DataShare +#endif // DATASHARESERVICE_PROXY_DATA_MANAGER_H \ No newline at end of file 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 de1036ff2b24476a28b4730fe59b0adbbbd37c79..940f599c448413ab291344275d46ff19207f4951 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 @@ -15,7 +15,7 @@ #define LOG_TAG "RdbAdaptor" #include "rdb_delegate.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "datashare_errno.h" #include "datashare_radar_reporter.h" #include "device_manager_adapter.h" @@ -35,6 +35,7 @@ #include "db_delegate.h" #include "log_debug.h" #include "ipc_skeleton.h" +#include "common_utils.h" namespace OHOS::DataShare { constexpr static int32_t MAX_RESULTSET_COUNT = 32; @@ -81,13 +82,19 @@ std::pair RdbDelegate::GetConfig(const DistributedData::Sto config.SetBundleName(meta.bundleName); if (meta.isEncrypt) { DistributedData::SecretKeyMetaData secretKeyMeta; - if (!DistributedData::MetaDataManager::GetInstance().LoadMeta(meta.GetSecretKey(), secretKeyMeta, true)) { + auto metaKey = meta.GetSecretKey(); + if (!DistributedData::MetaDataManager::GetInstance().LoadMeta(metaKey, secretKeyMeta, true) || + secretKeyMeta.sKey.empty()) { return std::make_pair(E_DB_NOT_EXIST, config); } - std::vector decryptKey; - if (!DistributedData::CryptoManager::GetInstance().Decrypt(meta, secretKeyMeta, decryptKey)) { + DistributedData::CryptoManager::CryptoParams decryptParams = { .area = secretKeyMeta.area, + .userId = meta.user, .nonce = secretKeyMeta.nonce }; + auto decryptKey = DistributedData::CryptoManager::GetInstance().Decrypt(secretKeyMeta.sKey, decryptParams); + if (decryptKey.empty()) { return std::make_pair(E_ERROR, config); - }; + } + // update secret key of area or nonce + DistributedData::CryptoManager::GetInstance().UpdateSecretMeta(decryptKey, meta, metaKey, secretKeyMeta); config.SetEncryptKey(decryptKey); std::fill(decryptKey.begin(), decryptKey.end(), 0); } @@ -97,16 +104,32 @@ std::pair RdbDelegate::GetConfig(const DistributedData::Sto return std::make_pair(E_OK, config); } -RdbDelegate::RdbDelegate(const DistributedData::StoreMetaData &meta, int version, +RdbDelegate::RdbDelegate() +{ +} + +bool RdbDelegate::Init(const DistributedData::StoreMetaData &meta, int version, bool registerFunction, const std::string &extUri, const std::string &backup) - : tokenId_(meta.tokenId), bundleName_(meta.bundleName), storeName_(meta.storeId), - haMode_(meta.haMode), extUri_(extUri), backup_(backup), user_(meta.user) { + if (isInited_) { + return true; + } + std::lock_guard lock(initMutex_); + if (isInited_) { + return true; + } + tokenId_ = meta.tokenId; + bundleName_ = meta.bundleName; + storeName_ = meta.storeId; + haMode_ = meta.haMode; + extUri_ = extUri; + backup_ = backup; + user_ = meta.user; auto [err, config] = GetConfig(meta, registerFunction); if (err != E_OK) { ZLOGW("Get rdbConfig failed, errCode is %{public}d, dir is %{public}s", err, - DistributedData::Anonymous::Change(meta.dataDir).c_str()); - return; + URIUtils::Anonymous(meta.dataDir).c_str()); + return false; } DefaultOpenCallback callback; TimeoutReport timeoutReport({meta.bundleName, "", meta.storeId, __FUNCTION__, 0}); @@ -115,22 +138,28 @@ RdbDelegate::RdbDelegate(const DistributedData::StoreMetaData &meta, int version timeoutReport.Report(meta.user, callingPid, -1, meta.instanceId); if (errCode_ != E_OK) { ZLOGW("GetRdbStore failed, errCode is %{public}d, dir is %{public}s", errCode_, - DistributedData::Anonymous::Change(meta.dataDir).c_str()); + URIUtils::Anonymous(meta.dataDir).c_str()); RdbDelegate::TryAndSend(errCode_); + return false; } + isInited_ = true; + return true; } + RdbDelegate::~RdbDelegate() { ZLOGI("Destruct. BundleName: %{public}s. StoreName: %{public}s. user: %{public}s", bundleName_.c_str(), - DistributedData::Anonymous::Change(storeName_).c_str(), user_.c_str()); + StringUtils::GeneralAnonymous(storeName_).c_str(), user_.c_str()); } + 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()); + bundleName_.c_str(), StringUtils::GeneralAnonymous(storeName_).c_str(), + URIUtils::Anonymous(extUri_).c_str()); AAFwk::WantParams params; params.SetParam("BundleName", AAFwk::String::Box(bundleName_)); params.SetParam("StoreName", AAFwk::String::Box(storeName_)); @@ -149,7 +178,7 @@ std::pair RdbDelegate::InsertEx(const std::string &tableName, ValuesBucket bucket = RdbDataShareAdapter::RdbUtils::ToValuesBucket(valuesBucket); int ret = store_->Insert(rowId, tableName, bucket); if (ret != E_OK) { - ZLOGE("Insert failed %{public}s %{public}d", tableName.c_str(), ret); + ZLOGE("Insert failed %{public}s %{public}d", StringUtils::GeneralAnonymous(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) { @@ -173,7 +202,7 @@ std::pair RdbDelegate::UpdateEx( RdbPredicates predicates = RdbDataShareAdapter::RdbUtils::ToPredicates(predicate, tableName); int ret = store_->Update(changeCount, bucket, predicates); if (ret != E_OK) { - ZLOGE("Update failed %{public}s %{public}d", tableName.c_str(), ret); + ZLOGE("Update failed %{public}s %{public}d", StringUtils::GeneralAnonymous(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) { @@ -195,7 +224,7 @@ std::pair RdbDelegate::DeleteEx(const std::string &tableName, RdbPredicates predicates = RdbDataShareAdapter::RdbUtils::ToPredicates(predicate, tableName); int ret = store_->Delete(changeCount, predicates); if (ret != E_OK) { - ZLOGE("Delete failed %{public}s %{public}d", tableName.c_str(), ret); + ZLOGE("Delete failed %{public}s %{public}d", StringUtils::GeneralAnonymous(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) { @@ -216,7 +245,6 @@ std::pair> RdbDelegate::Query(const std return std::make_pair(errCode_, nullptr); } int count = resultSetCount.fetch_add(1); - ZLOGD_MACRO("start query %{public}d", count); if (count >= MAX_RESULTSET_COUNT && IsLimit(count, callingPid, callingTokenId)) { resultSetCount--; return std::make_pair(E_RESULTSET_BUSY, nullptr); @@ -226,7 +254,7 @@ std::pair> RdbDelegate::Query(const std 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, pid: %{public}d", tableName.c_str(), callingPid); + ZLOGE("Query failed %{public}s, pid: %{public}d", StringUtils::GeneralAnonymous(tableName).c_str(), callingPid); resultSetCount--; return std::make_pair(E_ERROR, nullptr); } @@ -240,14 +268,15 @@ std::pair> RdbDelegate::Query(const std ++value; return true; }); - int64_t beginTime = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count(); + int64_t beginTime = GetSystemTime(); auto bridge = RdbDataShareAdapter::RdbUtils::ToResultSetBridge(resultSet); - std::shared_ptr result = { new DataShareResultSet(bridge), [callingPid, beginTime](auto p) { - ZLOGD_MACRO("release resultset"); + auto resultSetPtr = new (std::nothrow) DataShareResultSet(bridge); + if (resultSetPtr == nullptr) { + return std::make_pair(E_ERROR, nullptr); + } + auto result = std::shared_ptr(resultSetPtr, [callingPid, beginTime](auto p) { resultSetCount--; - int64_t endTime = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count(); + int64_t endTime = GetSystemTime(); if (endTime - beginTime > TIMEOUT_TIME) { ZLOGE("pid %{public}d query time is %{public}" PRId64 ", %{public}d resultSet is used.", callingPid, (endTime - beginTime), resultSetCount.load()); @@ -257,7 +286,7 @@ std::pair> RdbDelegate::Query(const std return value > 0; }); delete p; - }}; + }); return std::make_pair(E_OK, result); } 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 d7c3eedaf8d018549a28a9d2bd6097f29318fc1f..9c8fcd7dd04742a53219e763a77f9bd4f5f12576 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 @@ -24,16 +24,17 @@ #include "rdb_errno.h" #include "rdb_helper.h" #include "rdb_store.h" -#include "uri_utils.h" +#include "utils.h" #include "rdb_utils.h" namespace OHOS::DataShare { using namespace OHOS::NativeRdb; class RdbDelegate final : public DBDelegate { public: - explicit RdbDelegate(const DistributedData::StoreMetaData &meta, int version, - bool registerFunction, const std::string &extUri, const std::string &backup); + explicit RdbDelegate(); ~RdbDelegate(); + bool Init(const DistributedData::StoreMetaData &meta, int version, + bool registerFunction, const std::string &extUri, const std::string &backup) override; std::pair> Query(const std::string &tableName, const DataSharePredicates &predicates, const std::vector &columns, int32_t callingPid, uint32_t callingTokenId) override; @@ -59,13 +60,15 @@ private: 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_; - std::string user_; + uint32_t tokenId_ = 0; + std::string bundleName_ = ""; + std::string storeName_ = ""; + int32_t haMode_ = 0; + std::string extUri_ = ""; + std::string backup_ = ""; + std::string user_ = ""; + std::mutex initMutex_; + bool isInited_ = false; }; class DefaultOpenCallback : public RdbOpenCallback { public: diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.cpp index 79ca80155a6e32bfd36ac2af3417040ab57d13b1..fa7ec6a969581674ccc00a3ed10535173db59c8d 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.cpp @@ -20,7 +20,7 @@ #include "log_print.h" #include "timer_info.h" -#include "uri_utils.h" +#include "utils.h" #include "utils/anonymous.h" #include "log_debug.h" @@ -41,7 +41,7 @@ void SchedulerManager::Execute(const std::string &uri, const int32_t userId, Dis metaData.user = std::to_string(userId); auto delegate = DBDelegate::Create(metaData); if (delegate == nullptr) { - ZLOGE("malloc fail %{public}s", DistributedData::Anonymous::Change(uri).c_str()); + ZLOGE("malloc fail %{public}s", URIUtils::Anonymous(uri).c_str()); return; } std::vector keys = RdbSubscriberManager::GetInstance().GetKeysByUri(uri); @@ -57,7 +57,7 @@ void SchedulerManager::Execute(const Key &key, const int32_t userId, const Distr meta.user = std::to_string(userId); auto delegate = DBDelegate::Create(meta); if (delegate == nullptr) { - ZLOGE("malloc fail %{public}s", DistributedData::Anonymous::Change(key.uri).c_str()); + ZLOGE("malloc fail %{public}s", URIUtils::Anonymous(key.uri).c_str()); return; } ExecuteSchedulerSQL(userId, meta, key, delegate); @@ -87,12 +87,22 @@ void SchedulerManager::Stop(const Key &key) void SchedulerManager::Enable(const Key &key, int32_t userId, const DistributedData::StoreMetaData &metaData) { + Template tpl; + if (!TemplateManager::GetInstance().Get(key, userId, tpl) || + tpl.scheduler_.empty() || tpl.scheduler_.find(REMIND_TIMER_FUNC) == std::string::npos) { + ZLOGE("find template scheduler failed, %{public}s, %{public}" PRId64 ", %{public}s", + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); + return; + } bool isTimerStopped = false; { std::lock_guard lock(mutex_); auto it = schedulerStatusCache_.find(key); if (it != schedulerStatusCache_.end()) { it->second = true; + } else { + ZLOGW("enable key not found, %{public}s, %{public}" PRId64 ", %{public}s", + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); } auto timer = timerCache_.find(key); if (timer == timerCache_.end()) { @@ -111,6 +121,9 @@ void SchedulerManager::Disable(const Key &key) auto it = schedulerStatusCache_.find(key); if (it != schedulerStatusCache_.end()) { it->second = false; + } else { + ZLOGW("disable key not found, %{public}s, %{public}" PRId64 ", %{public}s", + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); } } @@ -160,9 +173,18 @@ bool SchedulerManager::GetSchedulerStatus(const Key &key) { bool enabled = false; std::lock_guard lock(mutex_); + uint32_t lastSize = lastStatusCacheSize_; + uint32_t nowSize = schedulerStatusCache_.size(); + if (nowSize != lastSize) { + lastStatusCacheSize_ = nowSize; + ZLOGI("size changed last %{public}d, now %{public}d", lastSize, nowSize); + } auto it = schedulerStatusCache_.find(key); if (it != schedulerStatusCache_.end()) { enabled = it->second; + } else { + ZLOGW("key not found, %{public}s, %{public}" PRId64 ", %{public}s", + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); } return enabled; } @@ -188,14 +210,14 @@ void SchedulerManager::SetTimer( auto it = timerCache_.find(key); if (it != timerCache_.end()) { ZLOGD_MACRO("has current taskId: %{private}s, subscriberId is %{public}" PRId64 ", bundleName is %{public}s", - DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); auto timerId = it->second; ResetTimerTask(timerId, reminderTime); return; } auto callback = [key, metaData, userId, this]() { ZLOGI("schedule notify start, uri is %{private}s, subscriberId is %{public}" PRId64 ", bundleName is " - "%{public}s", DistributedData::Anonymous::Change(key.uri).c_str(), + "%{public}s", URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); int64_t timerId = EraseTimerTaskId(key); DestoryTimerTask(timerId); @@ -210,7 +232,7 @@ void SchedulerManager::SetTimer( return; } ZLOGI("create new task success, uri is %{public}s, subscriberId is %{public}" PRId64 ", bundleName is %{public}s", - DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); timerCache_.emplace(key, timerId); } @@ -220,19 +242,19 @@ void SchedulerManager::ExecuteSchedulerSQL(const int32_t userId, DistributedData Template tpl; if (!TemplateManager::GetInstance().Get(key, userId, tpl)) { ZLOGE("template undefined, %{public}s, %{public}" PRId64 ", %{public}s", - DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); return; } if (tpl.scheduler_.empty()) { ZLOGW("template scheduler_ empty, %{public}s, %{public}" PRId64 ", %{public}s", - DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); return; } GenRemindTimerFuncParams(userId, metaData, key, tpl.scheduler_); auto resultSet = delegate->QuerySql(tpl.scheduler_); if (resultSet == nullptr) { ZLOGE("resultSet is nullptr, %{public}s, %{public}" PRId64 ", %{public}s", - DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); return; } int count; @@ -240,7 +262,7 @@ void SchedulerManager::ExecuteSchedulerSQL(const int32_t userId, DistributedData if (errCode != E_OK || count == 0) { ZLOGE("GetRowCount error, %{public}s, %{public}" PRId64 ", %{public}s, errorCode is %{public}d, count is " "%{public}d", - DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str(), errCode, + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str(), errCode, count); return; } @@ -251,7 +273,7 @@ void SchedulerManager::GenRemindTimerFuncParams( { auto index = schedulerSQL.find(REMIND_TIMER_FUNC); if (index == std::string::npos) { - ZLOGW("not find remindTimer, sql is %{public}s", schedulerSQL.c_str()); + ZLOGW("not find remindTimer, sql is %{public}s", URIUtils::Anonymous(schedulerSQL).c_str()); return; } index += REMIND_TIMER_FUNC_LEN; @@ -271,7 +293,7 @@ void SchedulerManager::RemoveTimer(const Key &key) auto it = timerCache_.find(key); if (it != timerCache_.end()) { ZLOGW("RemoveTimer %{public}s %{public}s %{public}" PRId64, - DistributedData::Anonymous::Change(key.uri).c_str(), key.bundleName.c_str(), key.subscriberId); + URIUtils::Anonymous(key.uri).c_str(), key.bundleName.c_str(), key.subscriberId); DestoryTimerTask(it->second); timerCache_.erase(key); } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.h b/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.h index 934f39757585d73ddb1c9c6b8af4a1ddfed6fde5..165551970bc54215ecbf7b2bfdb31636e252dfac 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.h @@ -41,6 +41,7 @@ public: private: static constexpr const char *REMIND_TIMER_FUNC = "remindTimer("; static constexpr int REMIND_TIMER_FUNC_LEN = 12; + uint32_t lastStatusCacheSize_ = 0; SchedulerManager() = default; ~SchedulerManager() = default; static void GenRemindTimerFuncParams(const int32_t userId, DistributedData::StoreMetaData &metaData, const Key &key, diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/utils.cpp similarity index 86% rename from datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.cpp rename to datamgr_service/services/distributeddataservice/service/data_share/common/utils.cpp index 1953824c43ad0b9d74eb4e98bdd35f61b3d48e7f..6f30af21c9b764f6936aa2dd313e9d25042df2c5 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/utils.cpp @@ -12,9 +12,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define LOG_TAG "URIUtils" +#define LOG_TAG "Utils" -#include "uri_utils.h" +#include "utils.h" #include @@ -24,6 +24,10 @@ #include "utils/anonymous.h" namespace OHOS::DataShare { +// Size of the characters that need to be left for both head and tail. +constexpr int32_t REVEAL_SIZE = 4; +constexpr const char *REPLACE_CHAIN = "***"; +constexpr const char *DEFAULT_ANONYMOUS = "******"; bool URIUtils::GetInfoFromURI(const std::string &uri, UriInfo &uriInfo) { Uri uriTemp(uri); @@ -36,7 +40,7 @@ bool URIUtils::GetInfoFromURI(const std::string &uri, UriInfo &uriInfo) if (splitUri[BUNDLE_NAME].empty() || splitUri[MODULE_NAME].empty() || splitUri[STORE_NAME].empty() || splitUri[TABLE_NAME].empty()) { ZLOGE("Uri has empty field! bundleName: %{public}s uri: %{public}s", splitUri[BUNDLE_NAME].c_str(), - DistributedData::Anonymous::Change(uri).c_str()); + URIUtils::Anonymous(uri).c_str()); return false; } @@ -147,7 +151,7 @@ std::pair URIUtils::Strtoul(const std::string &str) } char* end = nullptr; errno = 0; - data = strtoul(str.c_str(), &end, 10); + data = strtoul(str.c_str(), &end, END_LENGTH); if (errno == ERANGE || end == nullptr || end == str || *end != '\0') { return std::make_pair(false, data); } @@ -180,4 +184,20 @@ std::map URIUtils::GetQueryParams(const std::string& u } return params; } + +std::string StringUtils::GeneralAnonymous(const std::string &name) +{ + // To short to be partial anonymized + if (name.length() <= REVEAL_SIZE) { + return DEFAULT_ANONYMOUS; + } + + // only leave HEAD + if (name.length() <= (REVEAL_SIZE + REVEAL_SIZE)) { + return (name.substr(0, REVEAL_SIZE) + REPLACE_CHAIN); + } + // leave 4 char at head and tail respectively + return (name.substr(0, REVEAL_SIZE) + REPLACE_CHAIN + name.substr(name.length() - REVEAL_SIZE, REVEAL_SIZE)); +} + } // namespace OHOS::DataShare \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.h b/datamgr_service/services/distributeddataservice/service/data_share/common/utils.h similarity index 78% rename from datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.h rename to datamgr_service/services/distributeddataservice/service/data_share/common/utils.h index 8f2298506f8c454cfad95dd44f162a7aa23c181c..de55c6b0320315e59fcd5dc96dde027e19eba11a 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/utils.h @@ -35,6 +35,24 @@ struct UriConfig { std::string scheme; }; +class StringUtils { +public: + /** + * @brief Anonymizes the input string by preserving specified length at head/tail + * and replacing the middle part with placeholder + * @param name Original string to be processed (non-empty assumed) + * @return std::string Anonymized result according to length rules: + * 1. Length <= 4: Returns DEFAULT_ANONYMOUS ("******") + * 2. 4 < Length <= 8: Returns first 4 chars + REPLACE_CHAIN ("***") + * 3. Length > 8: Returns first 4 chars + REPLACE_CHAIN + last 4 chars + * @example + * "abcdefghi" -> "abcd***fghi" + * "12345" -> "1234***" + * "AB" -> "******" + */ + static std::string GeneralAnonymous(const std::string &name); +}; + class URIUtils { public: static bool GetInfoFromURI(const std::string &uri, UriInfo &uriInfo); @@ -67,7 +85,6 @@ private: PARAM_SIZE }; static constexpr int32_t END_LENGTH = 10; - static constexpr const char *DEFAULT_ANONYMOUS = "******"; }; } // namespace OHOS::DataShare #endif // DATASHARESERVICE_URI_UTILS_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data/published_data.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data/published_data.cpp index 0e73d871ae31b29bd78076c17e069de2bf0f77ed..d8c6960a2e0255638522dde7d11eca2f106e9f4e 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data/published_data.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data/published_data.cpp @@ -18,6 +18,7 @@ #include "log_print.h" #include "subscriber_managers/published_data_subscriber_manager.h" #include "utils/base64_utils.h" +#include "utils.h" namespace OHOS::DataShare { bool PublishedData::HasVersion() const @@ -151,7 +152,7 @@ int32_t PublishedData::Query(const std::string &filter, PublishedDataNode::Data } PublishedDataNode data; if (!PublishedDataNode::Unmarshall(queryResult, data)) { - ZLOGE("Unmarshall failed, %{private}s", queryResult.c_str()); + ZLOGE("Unmarshall failed, %{public}s", StringUtils::GeneralAnonymous(queryResult).c_str()); return E_ERROR; } publishedData = std::move(data.value); @@ -170,7 +171,7 @@ void PublishedData::Delete(const std::string &bundleName, const int32_t userId) ZLOGE("db open failed"); return; } - auto [status, count] = delegate->Delete(KvDBDelegate::DATA_TABLE, + auto [status, count] = delegate->Delete(KvDBDelegate::DATA_TABLE, "{\"bundleName\":\"" + bundleName + "\", \"userId\": " + std::to_string(userId) + "}"); if (status != E_OK) { ZLOGE("db Delete failed, %{public}s %{public}d", bundleName.c_str(), status); @@ -209,9 +210,9 @@ void PublishedData::ClearAging() } if (data.timestamp < lastValidTime && PublishedDataSubscriberManager::GetInstance() .GetCount(PublishedDataKey(data.key, data.bundleName, data.subscriberId)) == 0) { - auto [errorCode, count] = delegate->Delete(KvDBDelegate::DATA_TABLE, + auto [errorCode, count] = delegate->Delete(KvDBDelegate::DATA_TABLE, Id(PublishedData::GenId(data.key, data.bundleName, data.subscriberId), data.userId)); - if (errorCode != E_OK) { + if (errorCode != E_OK) { ZLOGE("db Delete failed, %{public}s %{public}s", data.key.c_str(), data.bundleName.c_str()); } agingSize++; @@ -235,12 +236,12 @@ void PublishedData::UpdateTimestamp( int32_t status = delegate->Get(KvDBDelegate::DATA_TABLE, Id(GenId(key, bundleName, subscriberId), userId), queryResult); if (status != E_OK) { - ZLOGE("db Get failed, %{private}s %{public}d", queryResult.c_str(), status); + ZLOGE("db Get failed, %{public}s %{public}d", StringUtils::GeneralAnonymous(queryResult).c_str(), status); return; } PublishedDataNode data; if (!PublishedDataNode::Unmarshall(queryResult, data)) { - ZLOGE("Unmarshall failed, %{private}s", queryResult.c_str()); + ZLOGE("Unmarshall failed, %{public}s", StringUtils::GeneralAnonymous(queryResult).c_str()); return; } auto now = time(nullptr); @@ -249,9 +250,9 @@ void PublishedData::UpdateTimestamp( return; } data.timestamp = now; - auto [errorCode, count] = delegate->Upsert(KvDBDelegate::DATA_TABLE, PublishedData(data)); - if (errorCode == E_OK) { - ZLOGI("update timestamp %{private}s", data.key.c_str()); + auto [errorCode, count] = delegate->Upsert(KvDBDelegate::DATA_TABLE, PublishedData(data)); + if (errorCode == E_OK) { + ZLOGI("update timestamp %{public}s", StringUtils::GeneralAnonymous(data.key).c_str()); } } 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 e713b4acb9a0df4e915dab75eff1218e662fa404..f6f13b3d3321c0d0d5cc30ff2659cf6ff9e5039e 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 @@ -20,11 +20,14 @@ #include "accesstoken_kit.h" #include "account/account_delegate.h" +#include "config_factory.h" #include "datashare_errno.h" #include "hap_token_info.h" +#include "ipc_skeleton.h" #include "log_print.h" #include "strategies/general/load_config_common_strategy.h" -#include "uri_utils.h" +#include "tokenid_kit.h" +#include "utils.h" #include "utils/anonymous.h" namespace OHOS::DataShare { @@ -39,6 +42,12 @@ DataProviderConfig::DataProviderConfig(const std::string &uri, uint32_t callerTo LoadConfigCommonStrategy::GetInfoFromProxyURI(providerInfo_.uri, providerInfo_.visitedUserId, callerTokenId, providerInfo_.bundleName); URIUtils::FormatUri(providerInfo_.uri); + // if visitedUserId is 0, set current foreground userId as visitedUserId + if (providerInfo_.visitedUserId == 0) { + if (!(AccountDelegate::GetInstance()->QueryForegroundUserId(providerInfo_.visitedUserId))) { + ZLOGE("Get foreground userId failed"); + } + } } else { auto [success, data] = URIUtils::GetUserFromProxyURI(providerInfo_.uri); if (success) { @@ -61,7 +70,7 @@ std::pair DataProviderConfig::GetBundleInfo() } providerInfo_.bundleName = uriConfig_.pathSegments[0]; } - auto ret = BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( + auto ret = BundleMgrProxy::GetInstance()->GetBundleInfoFromBMSWithCheck( providerInfo_.bundleName, providerInfo_.visitedUserId, bundleInfo, providerInfo_.appIndex); return std::make_pair(ret, bundleInfo); } @@ -155,7 +164,7 @@ int DataProviderConfig::GetFromExtension() return E_URI_NOT_EXIST; } BundleConfig bundleInfo; - auto ret = BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( + auto ret = BundleMgrProxy::GetInstance()->GetBundleInfoFromBMSWithCheck( providerInfo_.bundleName, providerInfo_.visitedUserId, bundleInfo, providerInfo_.appIndex); if (ret != E_OK) { ZLOGE("BundleInfo failed! bundleName: %{public}s", providerInfo_.bundleName.c_str()); @@ -225,6 +234,17 @@ std::pair DataProviderConfig::GetProvider GetMetaDataFromUri(); return std::make_pair(ret, providerInfo_); } + if (ret != E_URI_NOT_EXIST) { + return std::make_pair(ret, providerInfo_); + } + auto fullTokenId = IPCSkeleton::GetCallingFullTokenID(); + Security::AccessToken::HapTokenInfo tokenInfo; + auto result = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(IPCSkeleton::GetCallingTokenID(), tokenInfo); + if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId) + || (result == Security::AccessToken::RET_SUCCESS && !IsInExtList(tokenInfo.bundleName))) { + ZLOGE("The URI in the extension, is not allowed for silent access.! ret: %{public}d, bundleName: %{public}s," + "uri: %{public}s", ret, tokenInfo.bundleName.c_str(), URIUtils::Anonymous(providerInfo_.uri).c_str()); + } ret = GetFromExtension(); if (ret != E_OK) { ZLOGE("Get providerInfo failed! ret: %{public}d, uri: %{public}s", @@ -232,4 +252,14 @@ std::pair DataProviderConfig::GetProvider } return std::make_pair(ret, providerInfo_); } + +bool DataProviderConfig::IsInExtList(const std::string &bundleName) +{ + DataShareConfig *config = ConfigFactory::GetInstance().GetDataShareConfig(); + if (config == nullptr) { + return true; + } + std::vector& extNames = config->dataShareExtNames; + return std::find(extNames.begin(), extNames.end(), bundleName) != extNames.end(); +} } // namespace OHOS::DataShare 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 95d1c1cab811708b71bce9eb33eb21c5b7435035..c1acce432eccbe401c5da4c92b265f231335fac9 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,12 +18,11 @@ #include #include -#include "common/bundle_mgr_proxy.h" #include "account/account_delegate.h" #include "bundle_mgr_proxy.h" #include "data_share_profile_config.h" #include "hap_module_info.h" -#include "uri_utils.h" +#include "utils.h" namespace OHOS::DataShare { using ExtensionAbility = OHOS::AppExecFwk::ExtensionAbilityInfo; @@ -64,6 +63,7 @@ private: int GetFromExtensionProperties(const ProfileInfo &profileInfo, const std::string &moduleName); void GetMetaDataFromUri(); std::pair GetBundleInfo(); + bool IsInExtList(const std::string &bundleName); enum class PATH_PARAM : int32_t { BUNDLE_NAME = 0, MODULE_NAME, diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_proxy_observer.h b/datamgr_service/services/distributeddataservice/service/data_share/data_proxy_observer.h index 10a71f531ed0943322df524d2a3c77454b895d29..3c361f3675fe354384c672f1af75618add1a7f34 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_proxy_observer.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_proxy_observer.h @@ -18,6 +18,7 @@ #include #include "datashare_template.h" +#include "dataproxy_handle_common.h" namespace OHOS { namespace DataShare { @@ -32,6 +33,12 @@ public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DataShare.IDataProxyPublishedDataObserver"); virtual void OnChangeFromPublishedData(PublishedDataChangeNode &changeNode) = 0; }; + +class IProxyDataObserver : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DataShare.IProxyDataObserver"); + virtual void OnChangeFromProxyData(std::vector &changeNode) = 0; +}; } // namespace DataShare } // namespace OHOS #endif // DATA_PROXY_OBSERVER_H 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 544f887ff00a115aadddf6af10de60fff81ffa46..dc25bcafd6563eef8f8c4eb7154c761561db617e 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 @@ -25,7 +25,8 @@ #include "extension_connect_adaptor.h" #include "log_print.h" #include "metadata/meta_data_manager.h" -#include "uri_utils.h" +#include "metadata/store_meta_data.h" +#include "utils.h" #include "utils/anonymous.h" #include "ipc_skeleton.h" @@ -34,17 +35,18 @@ std::pair DataShareDbConfig::QueryMetaData const std::string &bundleName, const std::string &storeName, int32_t userId, int32_t appIndex) { TimeoutReport timeoutReport({bundleName, "", storeName, __FUNCTION__, 0}); - DistributedData::StoreMetaData meta; - meta.deviceId = DistributedData::DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; - meta.user = std::to_string(userId); - meta.bundleName = bundleName; - meta.storeId = storeName; - meta.instanceId = appIndex; - DistributedData::StoreMetaData metaData; - bool isCreated = DistributedData::MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), metaData, true); + DistributedData::StoreMetaMapping storeMetaMapping; + storeMetaMapping.deviceId = DistributedData::DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + storeMetaMapping.user = std::to_string(userId); + storeMetaMapping.bundleName = bundleName; + storeMetaMapping.storeId = storeName; + storeMetaMapping.instanceId = appIndex; + bool isCreated = + DistributedData::MetaDataManager::GetInstance().LoadMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); + auto callingPid = IPCSkeleton::GetCallingPid(); timeoutReport.Report(std::to_string(userId), callingPid, appIndex); - return std::make_pair(isCreated, metaData); + return std::make_pair(isCreated, storeMetaMapping); } std::pair DataShareDbConfig::GetMetaData(const DbConfig &dbConfig) @@ -72,8 +74,8 @@ std::tuple> Dat auto [errCode, metaData] = GetMetaData(dbConfig); if (errCode != E_OK) { ZLOGE("DB not exist,bundleName:%{public}s,storeName:%{public}s,user:%{public}d,err:%{public}d,uri:%{public}s", - dbConfig.bundleName.c_str(), dbConfig.storeName.c_str(), dbConfig.userId, errCode, - URIUtils::Anonymous(dbConfig.uri).c_str()); + dbConfig.bundleName.c_str(), StringUtils::GeneralAnonymous(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); 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 88efe930efe5fd4e58b9db46d822ad5f0f97d081..ff4e32b9f484bad50bf7745ca4f524407eaebbd3 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 @@ -23,7 +23,7 @@ #include "db_delegate.h" #include "extension_ability_info.h" #include "metadata/store_meta_data.h" -#include "uri_utils.h" +#include "utils.h" namespace OHOS::DataShare { class DataShareDbConfig { diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_obs_proxy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_obs_proxy.cpp index f63090f1f94462a8bb1f70c023fcd79901139dc1..db021d14d0b9a279cd960cf315f7ead6bcc4d180 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_obs_proxy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_obs_proxy.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "ObserverProxy" #include "data_share_obs_proxy.h" #include "datashare_errno.h" +#include "dataproxy_handle_common.h" #include "itypes_util.h" #include "datashare_itypes_utils.h" @@ -45,10 +46,7 @@ int RdbObserverProxy::CreateAshmem(RdbChangeNode &changeNode) return E_ERROR; } if (changeNode.memory_ != nullptr) { - ZLOGE( - "Unknown error: changeNode.memory_ should be null, but something is there %{public}p", - (void *)changeNode.memory_ - ); + ZLOGE("Unknown error: changeNode.memory_ should be null, but something is there."); return E_ERROR; } changeNode.memory_ = memory; @@ -201,6 +199,28 @@ void PublishedDataObserverProxy::OnChangeFromPublishedData(PublishedDataChangeNo return; } + MessageParcel reply; + MessageOption option; + int32_t result = Remote()->SendRequest(REQUEST_CODE, parcel, reply, option); + if (result != ERR_NONE) { + ZLOGE("SendRequest error, result=%{public}d", result); + return; + } + ZLOGD("SendRequest ok, retval is %{public}d", reply.ReadInt32()); +} + +void ProxyDataObserverProxy::OnChangeFromProxyData(std::vector &changeInfo) +{ + MessageParcel parcel; + if (!parcel.WriteInterfaceToken(PublishedDataObserverProxy::GetDescriptor())) { + return; + } + + if (!ITypesUtil::Marshal(parcel, changeInfo)) { + ZLOGE("failed to WriteParcelable changeNode "); + return; + } + MessageParcel reply; MessageOption option; int32_t result = Remote()->SendRequest(REQUEST_CODE, parcel, reply, option); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_obs_proxy.h b/datamgr_service/services/distributeddataservice/service/data_share/data_share_obs_proxy.h index c6726d591ea9f2488c2c820995ea5dc0542c68b8..81846c1cc5ccfaba4a5116906865d4c7b9e3708f 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_obs_proxy.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_obs_proxy.h @@ -45,5 +45,16 @@ public: private: static inline BrokerDelegator delegator_; }; + +class ProxyDataObserverProxy : public IRemoteProxy { +public: + explicit ProxyDataObserverProxy(const sptr& remote) + : IRemoteProxy(remote) {} + virtual ~ProxyDataObserverProxy() {} + void OnChangeFromProxyData(std::vector &changeNode) override; + +private: + static inline BrokerDelegator delegator_; +}; } // namespace OHOS::DataShare #endif // DATA_SHARE_OBS_PROXY_H 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 9787d9df1dc7c2db46c955850895215c386a399c..de4a8f65742af116556df812666f98303ae305bd 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 @@ -26,7 +26,7 @@ #include "bundle_mgr_proxy.h" #include "datashare_errno.h" #include "log_print.h" -#include "uri_utils.h" +#include "utils.h" #include "utils/anonymous.h" #include "log_debug.h" @@ -36,6 +36,7 @@ constexpr const char *PROFILE_FILE_PREFIX = "$profile:"; constexpr const char *SEPARATOR = "/"; static constexpr int PATH_SIZE = 2; static constexpr int MAX_ALLOWLIST_COUNT = 256; +static constexpr size_t MAX_FILE_SIZE = 10 * 1024 * 1024; const size_t PROFILE_PREFIX_LEN = strlen(PROFILE_FILE_PREFIX); bool Config::Marshal(json &node) const { @@ -134,6 +135,40 @@ bool ProfileInfo::Unmarshal(const json &node) return true; } +bool SerialDataShareProxyData::Marshal(json &node) const +{ + SetValue(node[GET_NAME(uri)], uri); + SetValue(node[GET_NAME(value)], value); + SetValue(node[GET_NAME(allowList)], allowList); + return true; +} + +bool SerialDataShareProxyData::Unmarshal(const json &node) +{ + bool ret = GetValue(node, GET_NAME(uri), uri); + // the value in profile can only be string, but the type of value which is published is variant, + // use type variant to unmarshal a string will fail, so use a string to try unmarshal again + if (!GetValue(node, GET_NAME(value), value)) { + std::string valueStr; + GetValue(node, GET_NAME(value), valueStr); + value = valueStr; + } + GetValue(node, GET_NAME(allowList), allowList); + return ret; +} + +bool ProxyDataProfileInfo::Marshal(json &node) const +{ + SetValue(node[GET_NAME(crossAppSharedConfig)], dataShareProxyDatas); + return true; +} + +bool ProxyDataProfileInfo::Unmarshal(const json &node) +{ + bool ret = GetValue(node, GET_NAME(crossAppSharedConfig), dataShareProxyDatas); + return ret; +} + std::pair DataShareProfileConfig::GetDataProperties( const std::vector &metadata, const std::string &resPath, const std::string &hapPath, const std::string &name) @@ -150,6 +185,27 @@ std::pair DataShareProfileConfig::GetDataProperties( return std::make_pair(SUCCESS, profileInfo); } +std::pair> DataShareProfileConfig::GetCrossAppSharedConfig( + const std::string &resource, const std::string &resPath, const std::string &hapPath) +{ + std::vector serialProxyDatas; + ProxyDataProfileInfo profileInfo; + std::string resourcePath = !hapPath.empty() ? hapPath : resPath; + + std::shared_ptr resMgr = InitResMgr(resourcePath); + if (resMgr == nullptr) { + return std::make_pair(ERROR, serialProxyDatas); + } + std::string info = GetResFromResMgr(resource, *resMgr, hapPath); + if (info.empty()) { + return std::make_pair(NOT_FOUND, serialProxyDatas); + } + if (!profileInfo.Unmarshall(info)) { + return std::make_pair(ERROR, serialProxyDatas); + } + return std::make_pair(SUCCESS, profileInfo.dataShareProxyDatas); +} + std::string DataShareProfileConfig::GetProfileInfoByMetadata(const std::vector &metadata, const std::string &resourcePath, const std::string &hapPath, const std::string &name) { @@ -173,7 +229,7 @@ std::string DataShareProfileConfig::GetProfileInfoByMetadata(const std::vector DataShareProfileConfig::InitResMgr(const std::string &resourcePath) { - std::shared_ptr resMgr(CreateResourceManager()); + std::shared_ptr resMgr(CreateResourceManager(false)); if (resMgr == nullptr) { return nullptr; } @@ -207,7 +263,7 @@ std::string DataShareProfileConfig::GetResFromResMgr( std::unique_ptr fileContent = nullptr; size_t len = 0; RState ret = resMgr.GetProfileDataByName(profileName.c_str(), len, fileContent); - if (ret != SUCCESS || fileContent == nullptr) { + if (ret != RState::SUCCESS || fileContent == nullptr) { ZLOGE("failed, ret is %{public}d, profileName is %{public}s", ret, profileName.c_str()); return profileInfo; } @@ -225,13 +281,14 @@ std::string DataShareProfileConfig::GetResFromResMgr( // hap is decompressed status, get file path then read file. std::string resPath; RState ret = resMgr.GetProfileByName(profileName.c_str(), resPath); - if (ret != SUCCESS) { - ZLOGE("profileName not found, ret is %{public}d, profileName is %{public}s", ret, profileName.c_str()); + if (ret != RState::SUCCESS) { + ZLOGE("profileName not found, ret is %{public}d, profileName is %{public}s", ret, + StringUtils::GeneralAnonymous(profileName).c_str()); return profileInfo; } std::string profile = ReadProfile(resPath); if (profile.empty()) { - ZLOGE("Read profile failed, resPath is %{public}s", resPath.c_str()); + ZLOGE("Read profile failed, resPath is %{public}s", URIUtils::Anonymous(resPath).c_str()); return profileInfo; } return profile; @@ -243,7 +300,8 @@ bool DataShareProfileConfig::IsFileExisted(const std::string &filePath) return false; } if (access(filePath.c_str(), F_OK) != 0) { - ZLOGE("can not access file, errno is %{public}d, filePath is %{public}s", errno, filePath.c_str()); + ZLOGE("can not access file, errno is %{public}d, filePath is %{public}s", errno, + URIUtils::Anonymous(filePath).c_str()); return false; } return true; @@ -264,7 +322,10 @@ std::string DataShareProfileConfig::ReadProfile(const std::string &resPath) tmp << in.rdbuf(); std::string content = tmp.str(); if (content.empty()) { - ZLOGE("the file is empty, resPath is %{public}s", resPath.c_str()); + ZLOGE("the file is empty, resPath is %{public}s", URIUtils::Anonymous(resPath).c_str()); + return ""; + } else if (content.length() > MAX_FILE_SIZE) { + ZLOGE("the file is too large, resPath is %{public}s,", URIUtils::Anonymous(resPath).c_str()); return ""; } return content; @@ -275,9 +336,9 @@ bool DataShareProfileConfig::GetProfileInfo(const std::string &calledBundleName, { BundleConfig bundleInfo; // profile is the same when app clone - if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS(calledBundleName, + if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMSWithCheck(calledBundleName, currentUserId, bundleInfo) != E_OK) { - ZLOGE("data share GetBundleInfoFromBMS failed! bundleName: %{public}s, currentUserId = %{public}d", + ZLOGE("data share GetBundleInfoFromBMSWithCheck failed! bundleName: %{public}s, currentUserId = %{public}d", calledBundleName.c_str(), currentUserId); return false; } 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 781cd5f348dbf2c3a5216d1aed336b841e947265..7f7d04459fe998308e1a14b61eac1fe78dc77321 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 @@ -22,6 +22,7 @@ #include #include "bundle_info.h" +#include "dataproxy_handle_common.h" #include "resource_manager.h" #include "serializable/serializable.h" @@ -68,6 +69,25 @@ struct ProfileInfo : public DistributedData::Serializable { bool Unmarshal(const json &node) override; }; +struct SerialDataShareProxyData : public DistributedData::Serializable { + SerialDataShareProxyData() = default; + SerialDataShareProxyData(const std::string &uri, const DataProxyValue &value, + const std::vector &allowList) + : uri(uri), value(value), allowList(allowList) {} + virtual ~SerialDataShareProxyData() = default; + std::string uri; + DataProxyValue value; + std::vector allowList; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; +}; + +struct ProxyDataProfileInfo : public DistributedData::Serializable { + std::vector dataShareProxyDatas; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; +}; + enum AccessCrossMode : uint8_t { USER_UNDEFINED, USER_SHARED, @@ -86,6 +106,8 @@ public: std::map &profileInfos); static std::pair GetDataProperties(const std::vector &metadata, const std::string &resPath, const std::string &hapPath, const std::string &name); + static std::pair> GetCrossAppSharedConfig(const std::string &resource, + const std::string &resPath, const std::string &hapPath); static AccessCrossMode GetAccessCrossMode(const ProfileInfo &profileInfo, const std::string &tableUri, const std::string &storeUri); private: 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 02b2ce8554547d6de47a248959dddfa92567aaa0..0b3e7c81b499d48ccdcf57dac0174ae10c8379ca 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 @@ -24,6 +24,8 @@ #include "app_connect_manager.h" #include "common_event_manager.h" #include "common_event_support.h" +#include "concurrent_task_client.h" +#include "config_factory.h" #include "data_ability_observer_interface.h" #include "data_share_profile_config.h" #include "dataobs_mgr_client.h" @@ -42,7 +44,7 @@ #include "ipc_skeleton.h" #include "iservice_registry.h" #include "log_print.h" -#include "common/uri_utils.h" +#include "common/utils.h" #include "metadata/auto_launch_meta_data.h" #include "metadata/meta_data_manager.h" #include "matching_skills.h" @@ -53,11 +55,16 @@ #include "sys_event_subscriber.h" #include "system_ability_definition.h" #include "system_ability_status_change_stub.h" +#include "task_executor.h" #include "template_data.h" #include "utils/anonymous.h" #include "xcollie.h" #include "log_debug.h" #include "parameters.h" +#include "dataproxy_handle_common.h" +#include "proxy_data_manager.h" +#include "datashare_observer.h" +#include "subscriber_managers/proxy_data_subscriber_manager.h" namespace OHOS::DataShare { using FeatureSystem = DistributedData::FeatureSystem; @@ -67,6 +74,7 @@ using namespace OHOS::DistributedData; __attribute__((used)) DataShareServiceImpl::Factory DataShareServiceImpl::factory_; // decimal base static constexpr int DECIMAL_BASE = 10; +DataShareServiceImpl::BindInfo DataShareServiceImpl::binderInfo_; class DataShareServiceImpl::SystemAbilityStatusChangeListener : public SystemAbilityStatusChangeStub { public: @@ -83,11 +91,17 @@ public: 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(); + ZLOGI("saId:%{public}d", systemAbilityId); + if (systemAbilityId == COMMON_EVENT_SERVICE_ID) { + InitSubEvent(); + } else if (systemAbilityId == CONCURRENT_TASK_SERVICE_ID) { + std::unordered_map payload; + // get current thread pid + payload["pid"] = std::to_string(getpid()); + // request qos auth for current pid + OHOS::ConcurrentTask::ConcurrentTaskClient::GetInstance().RequestAuth(payload); + } + return; } DataShareServiceImpl::Factory::Factory() @@ -118,9 +132,10 @@ std::pair DataShareServiceImpl::InsertEx(const std::string &ur callingTokenId}, true); auto [errCode, ret] = dbDelegate->InsertEx(providerInfo.tableName, valuesBucket); if (errCode == E_OK && ret > 0) { - NotifyChange(uri); + NotifyChange(uri, providerInfo.visitedUserId); RdbSubscriberManager::GetInstance().Emit(uri, providerInfo.visitedUserId, metaData); - } else { + } + if (errCode != E_OK) { ReportExcuteFault(callingTokenId, providerInfo, errCode, func); } timeoutReport.Report(); @@ -129,7 +144,7 @@ std::pair DataShareServiceImpl::InsertEx(const std::string &ur return ExecuteEx(uri, extUri, IPCSkeleton::GetCallingTokenID(), false, callBack); } -bool DataShareServiceImpl::NotifyChange(const std::string &uri) +bool DataShareServiceImpl::NotifyChange(const std::string &uri, int32_t userId) { RadarReporter::RadarReport report(RadarReporter::NOTIFY_OBSERVER_DATA_CHANGE, RadarReporter::NOTIFY_DATA_CHANGE, __FUNCTION__); @@ -139,8 +154,7 @@ bool DataShareServiceImpl::NotifyChange(const std::string &uri) report.SetError(RadarReporter::DATA_OBS_EMPTY_ERROR); return false; } - - ErrCode ret = obsMgrClient->NotifyChange(Uri(uri)); + ErrCode ret = obsMgrClient->NotifyChange(Uri(uri), userId); if (ret != ERR_OK) { ZLOGE("obsMgrClient->NotifyChange error return %{public}d", ret); report.SetError(RadarReporter::NOTIFY_ERROR); @@ -166,9 +180,10 @@ std::pair DataShareServiceImpl::UpdateEx(const std::string &ur callingTokenId}, true); auto [errCode, ret] = dbDelegate->UpdateEx(providerInfo.tableName, predicate, valuesBucket); if (errCode == E_OK && ret > 0) { - NotifyChange(uri); + NotifyChange(uri, providerInfo.visitedUserId); RdbSubscriberManager::GetInstance().Emit(uri, providerInfo.visitedUserId, metaData); - } else { + } + if (errCode != E_OK) { ReportExcuteFault(callingTokenId, providerInfo, errCode, func); } timeoutReport.Report(); @@ -194,9 +209,10 @@ std::pair DataShareServiceImpl::DeleteEx(const std::string &ur callingTokenId}, true); auto [errCode, ret] = dbDelegate->DeleteEx(providerInfo.tableName, predicate); if (errCode == E_OK && ret > 0) { - NotifyChange(uri); + NotifyChange(uri, providerInfo.visitedUserId); RdbSubscriberManager::GetInstance().Emit(uri, providerInfo.visitedUserId, metaData); - } else { + } + if (errCode != E_OK) { ReportExcuteFault(callingTokenId, providerInfo, errCode, func); } timeoutReport.Report(); @@ -243,7 +259,7 @@ int32_t DataShareServiceImpl::AddTemplate(const std::string &uri, const int64_t TemplateId tpltId; tpltId.subscriberId_ = subscriberId; if (!GetCallerBundleName(tpltId.bundleName_)) { - ZLOGE("get bundleName error, %{public}s", DistributedData::Anonymous::Change(uri).c_str()); + ZLOGE("get bundleName error, %{public}s", URIUtils::Anonymous(uri).c_str()); return ERROR; } ZLOGI("Add template, uri %{private}s, subscriberId %{public}" PRIi64 ", bundleName %{public}s," @@ -251,7 +267,7 @@ int32_t DataShareServiceImpl::AddTemplate(const std::string &uri, const int64_t uri.c_str(), subscriberId, tpltId.bundleName_.c_str(), tplt.predicates_.size()); return templateStrategy_.Execute(context, [&uri, &tpltId, &tplt, &context]() -> int32_t { auto result = TemplateManager::GetInstance().Add( - Key(uri, tpltId.subscriberId_, tpltId.bundleName_), context->currentUserId, tplt); + Key(uri, tpltId.subscriberId_, tpltId.bundleName_), context->visitedUserId, tplt); RdbSubscriberManager::GetInstance().Emit(context->uri, tpltId.subscriberId_, tpltId.bundleName_, context); return result; }); @@ -263,14 +279,14 @@ int32_t DataShareServiceImpl::DelTemplate(const std::string &uri, const int64_t TemplateId tpltId; tpltId.subscriberId_ = subscriberId; if (!GetCallerBundleName(tpltId.bundleName_)) { - ZLOGE("get bundleName error, %{public}s", DistributedData::Anonymous::Change(uri).c_str()); + ZLOGE("get bundleName error, %{public}s", URIUtils::Anonymous(uri).c_str()); return ERROR; } ZLOGI("Delete template, uri %{private}s, subscriberId %{public}" PRIi64 ", bundleName %{public}s.", - DistributedData::Anonymous::Change(uri).c_str(), subscriberId, tpltId.bundleName_.c_str()); + URIUtils::Anonymous(uri).c_str(), subscriberId, tpltId.bundleName_.c_str()); return templateStrategy_.Execute(context, [&uri, &tpltId, &context]() -> int32_t { return TemplateManager::GetInstance().Delete( - Key(uri, tpltId.subscriberId_, tpltId.bundleName_), context->currentUserId); + Key(uri, tpltId.subscriberId_, tpltId.bundleName_), context->visitedUserId); }); } @@ -335,11 +351,11 @@ std::vector DataShareServiceImpl::Publish(const Data &data, con int32_t result = publishStrategy_.Execute(context, item); results.emplace_back(item.key_, result); if (result != E_OK) { - ZLOGE("publish error, key is %{public}s", DistributedData::Anonymous::Change(item.key_).c_str()); + ZLOGE("publish error, key is %{public}s", URIUtils::Anonymous(item.key_).c_str()); continue; } publishedData.emplace_back(context->uri, context->calledBundleName, item.subscriberId_); - userId = context->currentUserId; + userId = context->visitedUserId; } if (!publishedData.empty()) { PublishedDataSubscriberManager::GetInstance().Emit(publishedData, userId, callerBundleName); @@ -369,7 +385,8 @@ std::vector DataShareServiceImpl::SubscribeRdbData( auto context = std::make_shared(uri); results.emplace_back(uri, subscribeStrategy_.Execute(context, [&id, &observer, &context, this]() { return RdbSubscriberManager::GetInstance().Add( - Key(context->uri, id.subscriberId_, id.bundleName_), observer, context, binderInfo_.executors); + Key(context->uri, id.subscriberId_, id.bundleName_), + observer, context, binderInfo_.executors); })); } return results; @@ -437,7 +454,7 @@ std::vector DataShareServiceImpl::SubscribePublishedData(const result = subscribeStrategy_.Execute(context, [&subscriberId, &observer, &context]() { return PublishedDataSubscriberManager::GetInstance().Add( PublishedDataKey(context->uri, context->callerBundleName, subscriberId), observer, - context->callerTokenId); + context->callerTokenId, context->visitedUserId); }); results.emplace_back(uri, result); if (result == E_OK) { @@ -445,10 +462,10 @@ std::vector DataShareServiceImpl::SubscribePublishedData(const if (binderInfo_.executors != nullptr) { binderInfo_.executors->Execute([context, subscriberId]() { PublishedData::UpdateTimestamp( - context->uri, context->calledBundleName, subscriberId, context->currentUserId); + context->uri, context->calledBundleName, subscriberId, context->visitedUserId); }); } - userId = context->currentUserId; + userId = context->visitedUserId; } } if (!publishedKeys.empty()) { @@ -477,7 +494,7 @@ std::vector DataShareServiceImpl::UnsubscribePublishedData(cons if (result == E_OK && binderInfo_.executors != nullptr) { binderInfo_.executors->Execute([context, subscriberId]() { PublishedData::UpdateTimestamp( - context->uri, context->calledBundleName, subscriberId, context->currentUserId); + context->uri, context->calledBundleName, subscriberId, context->visitedUserId); }); } return result; @@ -510,7 +527,7 @@ std::vector DataShareServiceImpl::EnablePubSubs(const std::vect if (result == E_OK && binderInfo_.executors != nullptr) { binderInfo_.executors->Execute([context, subscriberId]() { PublishedData::UpdateTimestamp( - context->uri, context->calledBundleName, subscriberId, context->currentUserId); + context->uri, context->calledBundleName, subscriberId, context->visitedUserId); }); } results.emplace_back(uri, result); @@ -519,7 +536,7 @@ std::vector DataShareServiceImpl::EnablePubSubs(const std::vect if (PublishedDataSubscriberManager::GetInstance().IsNotifyOnEnabled(pKey, context->callerTokenId)) { publishedKeys.emplace_back(pKey); } - userId = context->currentUserId; + userId = context->visitedUserId; } } if (!publishedKeys.empty()) { @@ -548,7 +565,7 @@ std::vector DataShareServiceImpl::DisablePubSubs(const std::vec if (result == E_OK && binderInfo_.executors != nullptr) { binderInfo_.executors->Execute([context, subscriberId]() { PublishedData::UpdateTimestamp( - context->uri, context->calledBundleName, subscriberId, context->currentUserId); + context->uri, context->calledBundleName, subscriberId, context->visitedUserId); }); } return result; @@ -583,12 +600,14 @@ int32_t DataShareServiceImpl::OnBind(const BindInfo &binderInfo) saveMeta.uid = IPCSkeleton::GetCallingUid(); saveMeta.storeType = DATA_SHARE_SINGLE_VERSION; saveMeta.dataDir = DistributedData::DirectoryManager::GetInstance().GetStorePath(saveMeta); - KvDBDelegate::GetInstance(false, saveMeta.dataDir, binderInfo.executors); + KvDBDelegate::GetInstance(saveMeta.dataDir, binderInfo.executors); SchedulerManager::GetInstance().SetExecutorPool(binderInfo.executors); + NativeRdb::TaskExecutor::GetInstance().SetExecutor(binderInfo.executors); ExtensionAbilityManager::GetInstance().SetExecutorPool(binderInfo.executors); DBDelegate::SetExecutorPool(binderInfo.executors); HiViewAdapter::GetInstance().SetThreadPool(binderInfo.executors); SubscribeCommonEvent(); + SubscribeConcurrentTask(); SubscribeTimeChanged(); SubscribeChange(); ZLOGI("end"); @@ -602,10 +621,29 @@ void DataShareServiceImpl::SubscribeCommonEvent() ZLOGE("System mgr is nullptr"); return; } - sptr callback(new SystemAbilityStatusChangeListener()); + sptr callback(new (std::nothrow)SystemAbilityStatusChangeListener()); + if (callback == nullptr) { + ZLOGE("new SystemAbilityStatusChangeListener failed! no memory"); + return; + } systemManager->SubscribeSystemAbility(COMMON_EVENT_SERVICE_ID, callback); } +void DataShareServiceImpl::SubscribeConcurrentTask() +{ + sptr systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemManager == nullptr) { + ZLOGE("System mgr is nullptr"); + return; + } + sptr callback(new (std::nothrow)SystemAbilityStatusChangeListener()); + if (callback == nullptr) { + ZLOGE("new SystemAbilityStatusChangeListener failed! no memory"); + return; + } + systemManager->SubscribeSystemAbility(CONCURRENT_TASK_SERVICE_ID, callback); +} + void DataShareServiceImpl::SubscribeChange() { EventCenter::GetInstance().Subscribe(RemoteChangeEvent::RDB_META_SAVE, [this](const Event &event) { @@ -773,6 +811,38 @@ int32_t DataShareServiceImpl::DataShareStatic::OnAppUpdate(const std::string &bu return E_OK; } +void DataShareServiceImpl::UpdateLaunchInfo() +{ + DataShareConfig *config = ConfigFactory::GetInstance().GetDataShareConfig(); + if (config == nullptr) { + ZLOGE("DataShareConfig is nullptr"); + return; + } + + ZLOGI("UpdateLaunchInfo begin."); + for (auto &bundleName : config->updateLaunchNames) { + std::string prefix = StoreMetaData::GetPrefix( + { DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid }); + std::vector storeMetaData; + MetaDataManager::GetInstance().LoadMeta(prefix, storeMetaData, true); + std::vector updateMetaData; + for (auto &meta : storeMetaData) { + if (meta.bundleName != bundleName) { + continue; + } + updateMetaData.push_back(meta); + } + for (auto &meta : updateMetaData) { + MetaDataManager::GetInstance().DelMeta(meta.GetAutoLaunchKey(), true); + } + for (auto &meta : updateMetaData) { + BundleMgrProxy::GetInstance()->Delete(bundleName, atoi(meta.user.c_str()), 0); + SaveLaunchInfo(meta.bundleName, meta.user, DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid); + } + ZLOGI("update bundleName %{public}s, size:%{public}zu.", bundleName.c_str(), storeMetaData.size()); + } +} + int32_t DataShareServiceImpl::DataShareStatic::OnClearAppStorage(const std::string &bundleName, int32_t user, int32_t index, int32_t tokenId) { @@ -800,15 +870,16 @@ int32_t DataShareServiceImpl::OnAppUpdate(const std::string &bundleName, int32_t void DataShareServiceImpl::NotifyObserver(const std::string &uri) { - ZLOGD_MACRO("%{private}s try notified", uri.c_str()); + auto anonymous = URIUtils::Anonymous(uri); + ZLOGD_MACRO("%{private}s try notified", anonymous.c_str()); auto context = std::make_shared(uri); if (!GetCallerBundleName(context->callerBundleName)) { - ZLOGE("get bundleName error, %{private}s", uri.c_str()); + ZLOGE("get bundleName error, %{private}s", anonymous.c_str()); return; } auto ret = rdbNotifyStrategy_.Execute(context); if (ret) { - ZLOGI("%{private}s start notified", uri.c_str()); + ZLOGI("%{private}s start notified", anonymous.c_str()); RdbSubscriberManager::GetInstance().Emit(uri, context); } } @@ -857,8 +928,9 @@ void DataShareServiceImpl::RegisterDataShareServiceInfo() void DataShareServiceImpl::RegisterHandler() { - Handler handler = - std::bind(&DataShareServiceImpl::DumpDataShareServiceInfo, this, std::placeholders::_1, std::placeholders::_2); + Handler handler = [] (int fd, std::map> ¶ms) { + DumpDataShareServiceInfo(fd, params); + }; DumpManager::GetInstance().AddHandler("FEATURE_INFO", uintptr_t(this), handler); } @@ -946,6 +1018,125 @@ int32_t DataShareServiceImpl::UnregisterObserver(const std::string &uri, return ERROR; } +bool DataShareServiceImpl::GetCallerBundleInfo(BundleInfo &callerBundleInfo) +{ + GetCallerInfo(callerBundleInfo.bundleName, callerBundleInfo.appIndex); + callerBundleInfo.userId = AccountDelegate::GetInstance()->GetUserByToken(IPCSkeleton::GetCallingTokenID()); + callerBundleInfo.tokenId = IPCSkeleton::GetCallingTokenID(); + auto [ret, callerAppIdentifier] = BundleMgrProxy::GetInstance()->GetCallerAppIdentifier( + callerBundleInfo.bundleName, callerBundleInfo.userId); + if (ret != 0) { + ZLOGE("Get caller appIdentifier failed, callerBundleName is %{public}s", callerBundleInfo.bundleName.c_str()); + return false; + } + callerBundleInfo.appIdentifier = callerAppIdentifier; + return true; +} + +std::vector DataShareServiceImpl::PublishProxyData(const std::vector &proxyDatas, + const DataProxyConfig &proxyConfig) +{ + std::vector result; + BundleInfo callerBundleInfo; + if (!GetCallerBundleInfo(callerBundleInfo)) { + ZLOGE("get callerBundleInfo failed"); + return result; + } + std::vector keys; + std::map> datas; + for (const auto &data : proxyDatas) { + DataShareObserver::ChangeType type; + auto ret = PublishedProxyData::Upsert(data, callerBundleInfo, type); + result.emplace_back(data.uri_, static_cast(ret)); + if (ret == SUCCESS && + (type == DataShareObserver::ChangeType::INSERT || type == DataShareObserver::ChangeType::UPDATE)) { + keys.emplace_back(data.uri_, callerBundleInfo.bundleName); + datas[type].emplace_back(data); + } + } + ProxyDataSubscriberManager::GetInstance().Emit(keys, datas, callerBundleInfo.userId); + return result; +} + +std::vector DataShareServiceImpl::DeleteProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) +{ + std::vector result; + BundleInfo callerBundleInfo; + if (!GetCallerBundleInfo(callerBundleInfo)) { + ZLOGE("get callerBundleInfo failed"); + return result; + } + std::vector keys; + std::map> datas; + for (const auto &uri : uris) { + DataShareProxyData oldProxyData; + DataShareObserver::ChangeType type; + auto ret = PublishedProxyData::Delete(uri, callerBundleInfo, oldProxyData, type); + result.emplace_back(uri, static_cast(ret)); + if (ret == SUCCESS && type == DataShareObserver::ChangeType::DELETE) { + keys.emplace_back(uri, callerBundleInfo.bundleName); + datas[type].emplace_back(oldProxyData); + } + } + ProxyDataSubscriberManager::GetInstance().Emit(keys, datas, callerBundleInfo.userId); + return result; +} + +std::vector DataShareServiceImpl::GetProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) +{ + std::vector result; + BundleInfo callerBundleInfo; + if (!GetCallerBundleInfo(callerBundleInfo)) { + ZLOGE("get callerBundleInfo failed"); + return result; + } + for (const auto &uri : uris) { + DataShareProxyData proxyData; + auto ret = PublishedProxyData::Query(uri, callerBundleInfo, proxyData); + result.emplace_back(uri, static_cast(ret), proxyData.value_, proxyData.allowList_); + } + return result; +} + +std::vector DataShareServiceImpl::SubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig, const sptr observer) +{ + std::vector results = {}; + BundleInfo callerBundleInfo; + if (!GetCallerBundleInfo(callerBundleInfo)) { + ZLOGE("get callerBundleInfo failed"); + return results; + } + for (const auto &uri : uris) { + DataShareProxyData proxyData; + DataProxyErrorCode ret = + static_cast(PublishedProxyData::Query(uri, callerBundleInfo, proxyData)); + if (ret == SUCCESS) { + ret = ProxyDataSubscriberManager::GetInstance().Add( + ProxyDataKey(uri, callerBundleInfo.bundleName), observer, callerBundleInfo.bundleName, + callerBundleInfo.appIdentifier, callerBundleInfo.userId); + } + results.emplace_back(uri, ret); + } + return results; +} + +std::vector DataShareServiceImpl::UnsubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) +{ + std::string bundleName; + GetCallerBundleName(bundleName); + int32_t userId = AccountDelegate::GetInstance()->GetUserByToken(IPCSkeleton::GetCallingTokenID()); + std::vector result = {}; + for (const auto &uri : uris) { + auto ret = ProxyDataSubscriberManager::GetInstance().Delete(ProxyDataKey(uri, bundleName), userId); + result.emplace_back(uri, ret); + } + return result; +} + bool DataShareServiceImpl::VerifyAcrossAccountsPermission(int32_t currentUserId, int32_t visitedUserId, const std::string &acrossAccountsPermission, uint32_t callerTokenId) { @@ -1003,7 +1194,7 @@ std::pair DataShareServiceImpl::ExecuteEx(const std::string &u 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", - providerInfo.bundleName.c_str(), providerInfo.tableName.c_str(), tokenId, + providerInfo.bundleName.c_str(), StringUtils::GeneralAnonymous(providerInfo.tableName).c_str(), tokenId, URIUtils::Anonymous(providerInfo.uri).c_str()); return std::make_pair(code, 0); } @@ -1072,7 +1263,7 @@ int32_t DataShareServiceImpl::GetBMSAndMetaDataStatus(const std::string &uri, co auto [code, metaData] = dbConfig.GetMetaData(dbArg); if (code != E_OK) { ZLOGE("Get metaData fail,bundleName:%{public}s,tableName:%{public}s,tokenId:0x%{public}x, uri:%{public}s", - calledInfo.bundleName.c_str(), calledInfo.tableName.c_str(), tokenId, + calledInfo.bundleName.c_str(), StringUtils::GeneralAnonymous(calledInfo.tableName).c_str(), tokenId, URIUtils::Anonymous(calledInfo.uri).c_str()); return E_METADATA_NOT_EXISTS; } @@ -1088,9 +1279,12 @@ void DataShareServiceImpl::InitSubEvent() } EventFwk::MatchingSkills matchingSkills; matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills); subscribeInfo.SetThreadMode(EventFwk::CommonEventSubscribeInfo::COMMON); - auto sysEventSubscriber = std::make_shared(subscribeInfo); + auto sysEventSubscriber = std::make_shared(subscribeInfo, binderInfo_.executors); if (!EventFwk::CommonEventManager::SubscribeCommonEvent(sysEventSubscriber)) { ZLOGE("Subscribe sys event failed."); alreadySubscribe = false; @@ -1150,13 +1344,13 @@ bool DataShareServiceImpl::VerifyPermission(const std::string &bundleName, const } } else { Security::AccessToken::HapTokenInfo tokenInfo; - auto result = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo); - if (result == Security::AccessToken::RET_SUCCESS && tokenInfo.bundleName == bundleName) { - return true; - } // Provider from ProxyData, which does not allow empty permissions and cannot be access without configured if (permission.empty()) { - ZLOGE("Permission empty! token:0x%{public}x, bundleName:%{public}s", tokenId, bundleName.c_str()); + auto result = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo); + if (result == Security::AccessToken::RET_SUCCESS && tokenInfo.bundleName == bundleName) { + return true; + } + ZLOGE("Permission denied! token:0x%{public}x, bundleName:%{public}s", tokenId, bundleName.c_str()); return false; } // If the permission is NO_PERMISSION, access is also allowed 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 e4d0a7d9d5d94a535750aa961947d451d9392512..41b2965e584bdcb1b660c8659e854106e9678da8 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 @@ -22,11 +22,11 @@ #include "accesstoken_kit.h" #include "bundle_mgr_proxy.h" +#include "changeevent/remote_change_event.h" #include "common_event_subscribe_info.h" #include "common_event_subscriber.h" -#include "changeevent/remote_change_event.h" -#include "data_proxy_observer.h" #include "data_provider_config.h" +#include "data_proxy_observer.h" #include "data_share_db_config.h" #include "data_share_service_stub.h" #include "data_share_silent_config.h" @@ -39,7 +39,7 @@ #include "rdb_notify_strategy.h" #include "subscribe_strategy.h" #include "template_strategy.h" -#include "uri_utils.h" +#include "utils.h" #include "visibility.h" namespace OHOS::DataShare { @@ -79,7 +79,7 @@ public: int32_t OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index) override; int32_t OnUserChange(uint32_t code, const std::string &user, const std::string &account) override; void NotifyObserver(const std::string &uri) override; - void DumpDataShareServiceInfo(int fd, std::map> ¶ms); + static void DumpDataShareServiceInfo(int fd, std::map> ¶ms); int32_t OnInitialize() override; int32_t EnableSilentProxy(const std::string &uri, bool enable) override; int32_t GetSilentProxyStatus(const std::string &uri, bool isCreateHelper) override; @@ -91,6 +91,17 @@ public: const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket) override; std::pair DeleteEx(const std::string &uri, const std::string &extUri, const DataSharePredicates &predicate) override; + std::vector PublishProxyData(const std::vector &proxyData, + const DataProxyConfig &proxyConfig) override; + std::vector DeleteProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) override; + std::vector GetProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) override; + std::vector SubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig, const sptr observer) override; + std::vector UnsubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) override; + static void UpdateLaunchInfo(); private: class SystemAbilityStatusChangeListener; using StaticActs = DistributedData::StaticActs; @@ -118,13 +129,14 @@ private: void RegisterDataShareServiceInfo(); void RegisterHandler(); bool SubscribeTimeChanged(); - bool NotifyChange(const std::string &uri); + bool NotifyChange(const std::string &uri, int32_t userId); bool GetCallerBundleName(std::string &bundleName); std::pair ExecuteEx(const std::string &uri, const std::string &extUri, const int32_t tokenId, bool isRead, ExecuteCallbackEx callback); std::pair GetCallerInfo(std::string &bundleName, int32_t &appIndex); int32_t GetBMSAndMetaDataStatus(const std::string &uri, const int32_t tokenId); void SubscribeCommonEvent(); + void SubscribeConcurrentTask(); static void InitSubEvent(); void AutoLaunch(const DistributedData::Event &event); void SubscribeChange(); @@ -141,6 +153,7 @@ private: const std::vector &allowLists); bool VerifyPermission(const std::string &bundleName, const std::string &permission, bool isFromExtension, const int32_t tokenId); + bool GetCallerBundleInfo(BundleInfo &callerBundleInfo); static Factory factory_; static constexpr int32_t ERROR = -1; static constexpr int32_t ERROR_PERMISSION_DENIED = -2; @@ -153,7 +166,7 @@ private: SubscribeStrategy subscribeStrategy_; TemplateStrategy templateStrategy_; RdbNotifyStrategy rdbNotifyStrategy_; - BindInfo binderInfo_; + static BindInfo binderInfo_; std::shared_ptr timerReceiver_ = nullptr; DataShareSilentConfig dataShareSilentConfig_; }; 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 d0b000ee9b29cf4fcc7639528bdded7bbc1d4d07..35586c108a1b1bb6fde39e2d8ab32bd896a37eac 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 @@ -13,13 +13,13 @@ * limitations under the License. */ +#include "datashare_errno.h" #define LOG_TAG "DataShareServiceStub" #include "data_share_service_stub.h" #include -#include "accesstoken_kit.h" -#include "tokenid_kit.h" +#include "common_utils.h" #include "data_share_obs_proxy.h" #include "hiview_adapter.h" #include "hiview_fault_adapter.h" @@ -27,10 +27,31 @@ #include "ishared_result_set.h" #include "itypes_util.h" #include "log_print.h" +#include "qos.h" +#include "utils.h" #include "utils/anonymous.h" +#include "dataproxy_handle_common.h" namespace OHOS { namespace DataShare { + +class DataShareServiceStub::QosManager { +public: + QosManager() + { +#ifndef IS_EMULATOR + // set thread qos QOS_USER_INTERACTIVE + QOS::SetThreadQos(QOS::QosLevel::QOS_USER_INTERACTIVE); +#endif + } + ~QosManager() + { +#ifndef IS_EMULATOR + QOS::ResetThreadQos(); +#endif + } +}; + bool DataShareServiceStub::CheckInterfaceToken(MessageParcel &data) { auto localDescriptor = IDataShareService::GetDescriptor(); @@ -48,11 +69,13 @@ int32_t DataShareServiceStub::OnInsertEx(MessageParcel &data, MessageParcel &rep std::string extUri; DataShareValuesBucket bucket; if (!ITypesUtil::Unmarshal(data, uri, extUri, bucket.valuesMap)) { - ZLOGE("Unmarshal uri:%{public}s bucket size:%{public}zu", DistributedData::Anonymous::Change(uri).c_str(), + ZLOGE("Unmarshal uri:%{public}s bucket size:%{public}zu", URIUtils::Anonymous(uri).c_str(), bucket.valuesMap.size()); return IPC_STUB_INVALID_DATA_ERR; } auto [errCode, status] = InsertEx(uri, extUri, bucket); + ZLOGI("Insert uri:%{public}s, e:%{public}x, s:%{public}x", + URIUtils::Anonymous(uri).c_str(), errCode, status); if (!ITypesUtil::Marshal(reply, errCode, status)) { ZLOGE("Marshal errCode: 0x%{public}x, status: 0x%{public}x", errCode, status); return IPC_STUB_WRITE_PARCEL_ERR; @@ -67,11 +90,13 @@ int32_t DataShareServiceStub::OnUpdateEx(MessageParcel &data, MessageParcel &rep DataSharePredicates predicate; DataShareValuesBucket bucket; if (!ITypesUtil::Unmarshal(data, uri, extUri, predicate, bucket.valuesMap)) { - ZLOGE("Unmarshal uri:%{public}s bucket size:%{public}zu", DistributedData::Anonymous::Change(uri).c_str(), + ZLOGE("Unmarshal uri:%{public}s bucket size:%{public}zu", URIUtils::Anonymous(uri).c_str(), bucket.valuesMap.size()); return IPC_STUB_INVALID_DATA_ERR; } auto [errCode, status] = UpdateEx(uri, extUri, predicate, bucket); + ZLOGI("Update uri:%{public}s, e:%{public}x, s:%{public}x", + URIUtils::Anonymous(uri).c_str(), errCode, status); if (!ITypesUtil::Marshal(reply, errCode, status)) { ZLOGE("Marshal errCode: 0x%{public}x, status: 0x%{public}x", errCode, status); return IPC_STUB_WRITE_PARCEL_ERR; @@ -85,10 +110,12 @@ int32_t DataShareServiceStub::OnDeleteEx(MessageParcel &data, MessageParcel &rep std::string extUri; DataSharePredicates predicate; if (!ITypesUtil::Unmarshal(data, uri, extUri, predicate)) { - ZLOGE("Unmarshal uri:%{public}s", DistributedData::Anonymous::Change(uri).c_str()); + ZLOGE("Unmarshal uri:%{public}s", URIUtils::Anonymous(uri).c_str()); return IPC_STUB_INVALID_DATA_ERR; } auto [errCode, status] = DeleteEx(uri, extUri, predicate); + ZLOGI("Delete uri:%{public}s, e:%{public}x, s:%{public}x", + URIUtils::Anonymous(uri).c_str(), errCode, status); if (!ITypesUtil::Marshal(reply, errCode, status)) { ZLOGE("Marshal errCode: 0x%{public}x, status: 0x%{public}x", errCode, status); return IPC_STUB_WRITE_PARCEL_ERR; @@ -103,7 +130,7 @@ int32_t DataShareServiceStub::OnQuery(MessageParcel &data, MessageParcel &reply) DataSharePredicates predicate; std::vector columns; if (!ITypesUtil::Unmarshal(data, uri, extUri, predicate, columns)) { - ZLOGE("Unmarshal uri:%{public}s columns size:%{public}zu", DistributedData::Anonymous::Change(uri).c_str(), + ZLOGE("Unmarshal uri:%{public}s columns size:%{public}zu", URIUtils::Anonymous(uri).c_str(), columns.size()); return IPC_STUB_INVALID_DATA_ERR; } @@ -327,36 +354,23 @@ int32_t DataShareServiceStub::OnNotifyConnectDone(MessageParcel &data, MessagePa return 0; } -bool DataShareServiceStub::CheckProxyCallingPermission(uint32_t tokenId) -{ - Security::AccessToken::ATokenTypeEnum tokenType = - Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId); - return (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE || - tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL); -} - -// GetTokenType use tokenId, and IsSystemApp use fullTokenId, these are different -bool DataShareServiceStub::CheckSystemUidCallingPermission(uint32_t tokenId, uint64_t fullTokenId) -{ - if (CheckProxyCallingPermission(tokenId)) { - return true; - } - // IsSystemAppByFullTokenID here is not IPC - return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId); -} - int DataShareServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply) { + // set thread qos + DataShareServiceStub::QosManager qos; + int tryTimes = TRY_TIMES; while (!isReady_.load() && tryTimes > 0) { tryTimes--; std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME)); } auto callingPid = IPCSkeleton::GetCallingPid(); + auto fullTokenId = IPCSkeleton::GetCallingFullTokenID(); + bool isSystemApp = CheckSystemCallingPermission(IPCSkeleton::GetCallingTokenID(), fullTokenId); + DataShareThreadLocal::SetFromSystemApp(isSystemApp); if (code >= DATA_SHARE_CMD_SYSTEM_CODE) { - auto fullTokenId = IPCSkeleton::GetCallingFullTokenID(); - if (!CheckSystemUidCallingPermission(IPCSkeleton::GetCallingTokenID(), fullTokenId)) { - ZLOGE("CheckSystemUidCallingPermission fail, token:%{public}" PRIx64 + if (!isSystemApp) { + ZLOGE("CheckSystemCallingPermission fail, token:%{public}" PRIx64 ", callingPid:%{public}d, code:%{public}u", fullTokenId, callingPid, code); return E_NOT_SYSTEM_APP; } @@ -366,6 +380,7 @@ int DataShareServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Me ZLOGI("code:%{public}u, callingPid:%{public}d", code, callingPid); } if (!CheckInterfaceToken(data)) { + DataShareThreadLocal::CleanFromSystemApp(); return DATA_SHARE_ERROR; } int res = -1; @@ -384,6 +399,7 @@ int DataShareServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Me } HiViewAdapter::GetInstance().ReportDataStatistic(callerInfo); } + DataShareThreadLocal::CleanFromSystemApp(); return res; } @@ -403,7 +419,7 @@ int32_t DataShareServiceStub::OnSetSilentSwitch(MessageParcel &data, MessageParc std::string uri; bool enable = false; if (!ITypesUtil::Unmarshal(data, uri, enable)) { - ZLOGE("Unmarshal set silent switch failed. uri: %{public}s", DistributedData::Anonymous::Change(uri).c_str()); + ZLOGE("Unmarshal set silent switch failed. uri: %{public}s", URIUtils::Anonymous(uri).c_str()); return IPC_STUB_INVALID_DATA_ERR; } int32_t status = EnableSilentProxy(uri, enable); @@ -418,7 +434,7 @@ int32_t DataShareServiceStub::OnGetSilentProxyStatus(MessageParcel &data, Messag { std::string uri; if (!ITypesUtil::Unmarshal(data, uri)) { - ZLOGE("Unmarshal silent enable failed. uri: %{public}s", DistributedData::Anonymous::Change(uri).c_str()); + ZLOGE("Unmarshal silent enable failed. uri: %{public}s", URIUtils::Anonymous(uri).c_str()); return IPC_STUB_INVALID_DATA_ERR; } int32_t enable = GetSilentProxyStatus(uri); @@ -443,5 +459,91 @@ void DataShareServiceStub::SetServiceReady() { isReady_.store(true); } + +int32_t DataShareServiceStub::OnPublishProxyData(MessageParcel& data, MessageParcel& reply) +{ + std::vector proxyDatas; + DataProxyConfig config; + if (!ITypesUtil::Unmarshal(data, proxyDatas, config)) { + ZLOGE("OnPublishProxyData unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + std::vector results = PublishProxyData(proxyDatas, config); + if (!ITypesUtil::Marshal(reply, results)) { + ZLOGE("OnPublishProxyData marshal reply failed."); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return E_OK; +} + +int32_t DataShareServiceStub::OnDeleteProxyData(MessageParcel& data, MessageParcel& reply) +{ + std::vector uris; + DataProxyConfig config; + if (!ITypesUtil::Unmarshal(data, uris, config)) { + ZLOGE("unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + std::vector results = DeleteProxyData(uris, config); + if (!ITypesUtil::Marshal(reply, results)) { + ZLOGE("OnPublishProxyData marshal reply failed."); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return E_OK; +} + +int32_t DataShareServiceStub::OnGetProxyData(MessageParcel& data, MessageParcel& reply) +{ + std::vector uris; + DataProxyConfig config; + if (!ITypesUtil::Unmarshal(data, uris, config)) { + ZLOGE("unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + std::vector results = GetProxyData(uris, config); + if (!ITypesUtil::Marshal(reply, results)) { + ZLOGE("OnPublishProxyData marshal reply failed."); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return E_OK; +} + +int32_t DataShareServiceStub::OnSubscribeProxyData(MessageParcel& data, MessageParcel& reply) +{ + std::vector uris; + DataProxyConfig config; + if (!ITypesUtil::Unmarshal(data, uris)) { + ZLOGE("unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + auto remoteObj = data.ReadRemoteObject(); + sptr observer = new (std::nothrow)ProxyDataObserverProxy(remoteObj); + if (observer == nullptr) { + ZLOGE("observer is nullptr"); + return DATA_SHARE_ERROR; + } + std::vector results = SubscribeProxyData(uris, config, observer); + if (!ITypesUtil::Marshal(reply, results)) { + ZLOGE("ITypesUtil::Marshal(reply, results) failed"); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return 0; +} + +int32_t DataShareServiceStub::OnUnsubscribeProxyData(MessageParcel& data, MessageParcel& reply) +{ + std::vector uris; + DataProxyConfig config; + if (!ITypesUtil::Unmarshal(data, uris)) { + ZLOGE("unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + std::vector results = UnsubscribeProxyData(uris, config); + if (!ITypesUtil::Marshal(reply, results)) { + ZLOGE("ITypesUtil::Marshal(reply, results) failed"); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return 0; +} } // namespace DataShare } // namespace OHOS \ No newline at end of file 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 b84c26967de53afab0711e617f19c33e16382f2f..27f1690ffd26da03bb24d1db51a9306c39490eab 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 @@ -27,10 +27,9 @@ public: void SetServiceReady(); private: + class QosManager; static constexpr std::chrono::milliseconds TIME_THRESHOLD = std::chrono::milliseconds(500); static bool CheckInterfaceToken(MessageParcel& data); - bool CheckProxyCallingPermission(uint32_t tokenId); - bool CheckSystemUidCallingPermission(uint32_t tokenId, uint64_t fullTokenId); int32_t OnQuery(MessageParcel& data, MessageParcel& reply); int32_t OnAddTemplate(MessageParcel& data, MessageParcel& reply); int32_t OnDelTemplate(MessageParcel& data, MessageParcel& reply); @@ -53,6 +52,11 @@ private: int32_t OnInsertEx(MessageParcel& data, MessageParcel& reply); int32_t OnUpdateEx(MessageParcel& data, MessageParcel& reply); int32_t OnDeleteEx(MessageParcel& data, MessageParcel& reply); + int32_t OnPublishProxyData(MessageParcel& data, MessageParcel& reply); + int32_t OnDeleteProxyData(MessageParcel& data, MessageParcel& reply); + int32_t OnGetProxyData(MessageParcel& data, MessageParcel& reply); + int32_t OnSubscribeProxyData(MessageParcel& data, MessageParcel& reply); + int32_t OnUnsubscribeProxyData(MessageParcel& data, MessageParcel& reply); using RequestHandle = int (DataShareServiceStub::*)(MessageParcel &, MessageParcel &); static constexpr RequestHandle HANDLERS[DATA_SHARE_SERVICE_CMD_MAX] = { &DataShareServiceStub::OnQuery, @@ -76,7 +80,12 @@ private: &DataShareServiceStub::OnUnregisterObserver, &DataShareServiceStub::OnInsertEx, &DataShareServiceStub::OnDeleteEx, - &DataShareServiceStub::OnUpdateEx}; + &DataShareServiceStub::OnUpdateEx, + &DataShareServiceStub::OnPublishProxyData, + &DataShareServiceStub::OnDeleteProxyData, + &DataShareServiceStub::OnGetProxyData, + &DataShareServiceStub::OnSubscribeProxyData, + &DataShareServiceStub::OnUnsubscribeProxyData}; 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/data_share_silent_config.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_silent_config.cpp index 18b221acb602f048b5c97bae1838ac09acdce8f1..eee4709aac1988c84b7a832e224acd352aaae53a 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_silent_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_silent_config.cpp @@ -23,7 +23,7 @@ #include "hap_token_info.h" #include "ipc_skeleton.h" #include "log_print.h" -#include "uri_utils.h" +#include "utils.h" #include "utils/anonymous.h" namespace OHOS::DataShare { @@ -59,7 +59,7 @@ bool DataShareSilentConfig::EnableSilentProxy(uint32_t callerTokenId, const std: uri = std::string(ALL_URI); } ZLOGI("Enable silent proxy, callerTokenId:%{public}u, enable:%{public}d, uri:%{public}s", - callerTokenId, enable, DistributedData::Anonymous::Change(uri).c_str()); + callerTokenId, enable, URIUtils::Anonymous(uri).c_str()); enableSilentUris_.Compute(callerTokenId, [&enable, &uri](const uint32_t &key, std::map &uris) { uris[uri] = enable; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/dfx/hiview_fault_adapter.h b/datamgr_service/services/distributeddataservice/service/data_share/dfx/hiview_fault_adapter.h index 3b001e62d850779a3add7862037264bfe148d9cf..bb4910033b8dd0d518a5e456771c78f2c1c2a757 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/dfx/hiview_fault_adapter.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/dfx/hiview_fault_adapter.h @@ -41,6 +41,7 @@ public: static constexpr const char* timeOut = "TIME_OUT"; static constexpr const char* resultsetFull = "RESULTSET_FULL"; static constexpr const char* curdFailed = "CURD_FAILED"; + static constexpr const char* kvDBCorrupt = "KVDB_CORRUPT"; static void ReportDataFault(const DataShareFaultInfo &faultInfo); static std::pair GetCallingName(uint32_t callingTokenid); }; 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 05e1fd15542f7e286c0d6ba77b36ed1f005d52a1..9f08d74c5100bcf571a738a69cb6253cde4adc52 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 @@ -25,6 +25,7 @@ #include "datashare_template.h" #include "data_proxy_observer.h" #include "iremote_object.h" +#include "dataproxy_handle_common.h" namespace OHOS::DataShare { class IDataShareService { @@ -53,6 +54,11 @@ public: DATA_SHARE_SERVICE_CMD_INSERTEX, DATA_SHARE_SERVICE_CMD_DELETEEX, DATA_SHARE_SERVICE_CMD_UPDATEEX, + DATA_SHARE_SERVICE_CMD_PROXY_PUBLISH, + DATA_SHARE_SERVICE_CMD_PROXY_DELETE, + DATA_SHARE_SERVICE_CMD_PROXY_GET, + DATA_SHARE_SERVICE_CMD_SUBSCRIBE_PROXY_DATA, + DATA_SHARE_SERVICE_CMD_UNSUBSCRIBE_PROXY_DATA, DATA_SHARE_SERVICE_CMD_MAX, DATA_SHARE_SERVICE_CMD_QUERY_SYSTEM = DATA_SHARE_CMD_SYSTEM_CODE, DATA_SHARE_SERVICE_CMD_ADD_TEMPLATE_SYSTEM, @@ -117,6 +123,16 @@ public: const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket) = 0; virtual std::pair DeleteEx(const std::string &uri, const std::string &extUri, const DataSharePredicates &predicate) = 0; -}; + virtual std::vector PublishProxyData(const std::vector &proxyData, + const DataProxyConfig &proxyConfig) = 0; + virtual std::vector DeleteProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) = 0; + virtual std::vector GetProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) = 0; + virtual std::vector SubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig, const sptr observer) = 0; + virtual std::vector UnsubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) = 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 c796152ca0fcd267f999c1d713a424cecacb7785..1810afacd486f4d77bd5968f8ac1f77bcc9a165b 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 @@ -17,7 +17,7 @@ #include "load_config_from_data_proxy_node_strategy.h" #include "bundle_mgr_proxy.h" -#include "common/uri_utils.h" +#include "common/utils.h" #include "data_share_profile_config.h" #include "datashare_errno.h" #include "log_print.h" @@ -30,9 +30,9 @@ bool LoadConfigFromDataProxyNodeStrategy::operator()(std::shared_ptr co return false; } context->type = PUBLISHED_DATA_TYPE; - if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( - context->calledBundleName, context->currentUserId, context->bundleInfo) != E_OK) { - ZLOGE("GetBundleInfoFromBMS failed! bundleName: %{public}s", context->calledBundleName.c_str()); + if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMSWithCheck( + context->calledBundleName, context->visitedUserId, context->bundleInfo) != E_OK) { + ZLOGE("GetBundleInfoFromBMSWithCheck failed! bundleName: %{public}s", context->calledBundleName.c_str()); context->errCode = E_BUNDLE_NAME_NOT_EXIST; return false; } @@ -40,10 +40,12 @@ bool LoadConfigFromDataProxyNodeStrategy::operator()(std::shared_ptr co context->permission = "reject"; return true; } + std::string uri = context->uri; + URIUtils::FormatUri(uri); for (auto const &hapModuleInfo : context->bundleInfo.hapModuleInfos) { auto proxyDatas = hapModuleInfo.proxyDatas; for (auto const &proxyData : proxyDatas) { - if (proxyData.uri != context->uri) { + if (proxyData.uri != uri) { continue; } context->permission = context->isRead ? proxyData.requiredReadPermission @@ -69,7 +71,7 @@ bool LoadConfigFromDataProxyNodeStrategy::operator()(std::shared_ptr co return true; } context->errCode = E_URI_NOT_EXIST; - ZLOGI("not find DataProperties! %{private}s is private", context->uri.c_str()); + ZLOGI("not find DataProperties! %{public}s is private", URIUtils::Anonymous(context->uri).c_str()); return false; } 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 16fe91511f8148f17850e1acccb70dd233a305e5..cd5a5aa8a67cc23eb16b5e46ff839e4e0ed5bbe3 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 @@ -20,7 +20,7 @@ #include "data_share_profile_config.h" #include "datashare_errno.h" #include "log_print.h" -#include "uri_utils.h" +#include "utils.h" #include "utils/anonymous.h" namespace OHOS::DataShare { @@ -80,9 +80,9 @@ bool LoadConfigFromDataShareBundleInfoStrategy::operator()(std::shared_ptrcalledBundleName.c_str()); return false; } - if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( - context->calledBundleName, context->currentUserId, context->bundleInfo) != E_OK) { - ZLOGE("GetBundleInfoFromBMS failed! bundleName: %{public}s", context->calledBundleName.c_str()); + if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMSWithCheck( + context->calledBundleName, context->visitedUserId, context->bundleInfo) != E_OK) { + ZLOGE("GetBundleInfoFromBMSWithCheck failed! bundleName: %{public}s", context->calledBundleName.c_str()); return false; } for (auto const &item : context->bundleInfo.extensionInfos) { @@ -107,7 +107,7 @@ bool LoadConfigFromDataShareBundleInfoStrategy::LoadConfigFromUri(std::shared_pt { UriInfo uriInfo; if (!URIUtils::GetInfoFromURI(context->uri, uriInfo)) { - ZLOGE("Invalid uri: %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + ZLOGE("Invalid uri: %{public}s", URIUtils::Anonymous(context->uri).c_str()); return false; } context->calledBundleName = std::move(uriInfo.bundleName); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/check_is_data_proxy_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/check_is_data_proxy_strategy.cpp index 6842ed8bb71f5fb0ebe57161196e3948276055ba..8d94c9e618ab823cf924aebe78049621bf272aae 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/check_is_data_proxy_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/check_is_data_proxy_strategy.cpp @@ -14,7 +14,7 @@ */ #include "check_is_data_proxy_strategy.h" -#include "uri_utils.h" +#include "utils.h" namespace OHOS::DataShare { bool CheckIsDataProxyStrategy::operator()(std::shared_ptr context) diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_common_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_common_strategy.cpp index b8dece0fd2173572ea22fdba2f9e0bd8c833205f..042ba77968aeb28bfcfb432b5c5e3323eeec004a 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_common_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_common_strategy.cpp @@ -20,7 +20,7 @@ #include "hap_token_info.h" #include "ipc_skeleton.h" #include "log_print.h" -#include "uri_utils.h" +#include "utils.h" namespace OHOS::DataShare { using namespace OHOS::DistributedData; @@ -33,13 +33,14 @@ bool LoadConfigCommonStrategy::operator()(std::shared_ptr context) context->callerTokenId = IPCSkeleton::GetCallingTokenID(); } context->currentUserId = AccountDelegate::GetInstance()->GetUserByToken(context->callerTokenId); + context->visitedUserId = context->currentUserId; if (!URIUtils::GetAppIndexFromProxyURI(context->uri, context->appIndex)) { return false; } // sa, userId is in uri, caller token id is from first caller tokenId if (context->currentUserId == 0) { GetInfoFromProxyURI( - context->uri, context->currentUserId, context->callerTokenId, context->calledBundleName); + context->uri, context->visitedUserId, context->callerTokenId, context->calledBundleName); URIUtils::FormatUri(context->uri); } if (context->needAutoLoadCallerBundleName && context->callerBundleName.empty()) { 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 d5283e4d3a82bffd0cea72b2d3e3d5ab236f2e03..d3966097e0bd75684099791dbc6ea6e46621c73e 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 @@ -22,7 +22,7 @@ #include "metadata/meta_data_manager.h" #include "metadata/store_meta_data.h" #include "rdb_errno.h" -#include "utils/anonymous.h" +#include "utils.h" namespace OHOS::DataShare { LoadConfigDataInfoStrategy::LoadConfigDataInfoStrategy() @@ -33,12 +33,14 @@ LoadConfigDataInfoStrategy::LoadConfigDataInfoStrategy() static bool QueryMetaData(const std::string &bundleName, const std::string &storeName, DistributedData::StoreMetaData &metaData, const int32_t userId, const int32_t appIndex) { - DistributedData::StoreMetaData meta; - meta.deviceId = DistributedData::DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; - meta.user = std::to_string(userId); - meta.bundleName = bundleName; - meta.storeId = storeName; - bool isCreated = DistributedData::MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), metaData, true); + DistributedData::StoreMetaMapping storeMetaMapping; + storeMetaMapping.deviceId = DistributedData::DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + storeMetaMapping.user = std::to_string(userId); + storeMetaMapping.bundleName = bundleName; + storeMetaMapping.storeId = storeName; + bool isCreated = DistributedData::MetaDataManager::GetInstance().LoadMeta( + storeMetaMapping.GetKey(), storeMetaMapping, true); + metaData = storeMetaMapping; if (!isCreated) { ZLOGE("DB not exist"); return false; @@ -53,13 +55,13 @@ bool LoadConfigNormalDataInfoStrategy::operator()(std::shared_ptr conte } DistributedData::StoreMetaData metaData; if (!QueryMetaData( - context->calledBundleName, context->calledStoreName, metaData, context->currentUserId, context->appIndex)) { + context->calledBundleName, context->calledStoreName, metaData, context->visitedUserId, context->appIndex)) { // connect extension and retry AAFwk::WantParams wantParams; ExtensionConnectAdaptor::TryAndWait(context->uri, context->calledBundleName, wantParams); if (!QueryMetaData( - context->calledBundleName, context->calledStoreName, metaData, context->currentUserId, context->appIndex)) { - ZLOGE("QueryMetaData fail, %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + context->calledBundleName, context->calledStoreName, metaData, context->visitedUserId, context->appIndex)) { + ZLOGE("QueryMetaData fail, %{public}s", URIUtils::Anonymous(context->uri).c_str()); context->errCode = NativeRdb::E_DB_NOT_EXIST; return false; } @@ -83,7 +85,7 @@ bool LoadConfigSingleDataInfoStrategy::operator()(std::shared_ptr conte AAFwk::WantParams wantParams; ExtensionConnectAdaptor::TryAndWait(context->uri, context->calledBundleName, wantParams); if (!QueryMetaData(context->calledBundleName, context->calledStoreName, metaData, 0, context->appIndex)) { - ZLOGE("QueryMetaData fail, %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + ZLOGE("QueryMetaData fail, %{public}s", URIUtils::Anonymous(context->uri).c_str()); context->errCode = NativeRdb::E_DB_NOT_EXIST; return false; } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/get_data_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/get_data_strategy.cpp index c32d5daff4c916213c3a2740683989dcf96b56a3..a532d7c52096ee13bbc7993a4fbb645bba4d45ce 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/get_data_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/get_data_strategy.cpp @@ -20,7 +20,7 @@ #include "data_proxy/load_config_from_data_proxy_node_strategy.h" #include "general/load_config_common_strategy.h" #include "log_print.h" -#include "utils/anonymous.h" +#include "utils.h" namespace OHOS::DataShare { Data GetDataStrategy::Execute(std::shared_ptr context, int &errorCode) @@ -32,15 +32,15 @@ Data GetDataStrategy::Execute(std::shared_ptr context, int &errorCode) return Data(); } if (!preProcess(context)) { - ZLOGE("pre process fail, uri: %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + ZLOGE("pre process fail, uri: %{public}s", URIUtils::Anonymous(context->uri).c_str()); errorCode = context->errCode; return Data(); } - auto result = PublishedData::Query(context->calledBundleName, context->currentUserId); + auto result = PublishedData::Query(context->calledBundleName, context->visitedUserId); Data data; for (auto &item : result) { if (!CheckPermission(context, item.value.key)) { - ZLOGI("uri: %{private}s not allowed", context->uri.c_str()); + ZLOGI("uri: %{public}s not allowed", URIUtils::Anonymous(context->uri).c_str()); continue; } if (item.GetVersion() > data.version_) { diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/publish_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/publish_strategy.cpp index b0b7ca77ac41597d694c7002b90f17a9338beeb0..10d4ecba208d6b62d809f9df9edf1775e13b010e 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/publish_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/publish_strategy.cpp @@ -22,7 +22,7 @@ #include "general/permission_strategy.h" #include "log_print.h" #include "published_data.h" -#include "utils/anonymous.h" +#include "utils.h" namespace OHOS::DataShare { int32_t PublishStrategy::Execute(std::shared_ptr context, const PublishedDataItem &item) @@ -33,7 +33,7 @@ int32_t PublishStrategy::Execute(std::shared_ptr context, const Publish return -1; } if (!preProcess(context)) { - ZLOGE("pre process fail, uri: %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + ZLOGE("pre process fail, uri: %{public}s", URIUtils::Anonymous(context->uri).c_str()); return context->errCode; } auto delegate = KvDBDelegate::GetInstance(); @@ -42,13 +42,13 @@ int32_t PublishStrategy::Execute(std::shared_ptr context, const Publish return -1; } PublishedDataItem::DataType value = item.GetData(); - PublishedDataNode node(context->uri, context->calledBundleName, item.subscriberId_, context->currentUserId, + PublishedDataNode node(context->uri, context->calledBundleName, item.subscriberId_, context->visitedUserId, PublishedDataNode::MoveTo(value)); PublishedData data(node, context->version); - auto [status, count] = delegate->Upsert(KvDBDelegate::DATA_TABLE, data); + auto [status, count] = delegate->Upsert(KvDBDelegate::DATA_TABLE, data); if (status != E_OK) { ZLOGE("db Upsert failed, %{public}s %{public}s %{public}d", context->calledBundleName.c_str(), - DistributedData::Anonymous::Change(context->uri).c_str(), status); + URIUtils::Anonymous(context->uri).c_str(), status); return status; } return E_OK; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/rdb_notify_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/rdb_notify_strategy.cpp index 95ca0ceba28026a55ec1659ca1849518053e6f24..a28760d0c82ec9178e481db4158d0f902d660510 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/rdb_notify_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/rdb_notify_strategy.cpp @@ -20,7 +20,7 @@ #include "general/load_config_data_info_strategy.h" #include "general/load_config_from_bundle_info_strategy.h" #include "log_print.h" -#include "utils/anonymous.h" +#include "utils.h" #include "log_debug.h" namespace OHOS::DataShare { @@ -32,7 +32,7 @@ bool RdbNotifyStrategy::Execute(std::shared_ptr context) return false; } if (!preProcess(context)) { - ZLOGE("pre process fail, uri: %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + ZLOGE("pre process fail, uri: %{public}s", URIUtils::Anonymous(context->uri).c_str()); return false; } if (context->callerBundleName != context->calledBundleName) { diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/subscribe_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/subscribe_strategy.cpp index 4b7314c88ba32cbdac295d6b30f14089464e8869..36b15b452334ab48dec9bdefeea9e6ea6e67ddf7 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/subscribe_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/subscribe_strategy.cpp @@ -21,7 +21,7 @@ #include "general/load_config_data_info_strategy.h" #include "general/permission_strategy.h" #include "log_print.h" -#include "utils/anonymous.h" +#include "utils.h" namespace OHOS::DataShare { int32_t SubscribeStrategy::Execute(std::shared_ptr context, std::function process) @@ -34,7 +34,7 @@ int32_t SubscribeStrategy::Execute(std::shared_ptr context, std::functi context->isRead = true; context->needAutoLoadCallerBundleName = true; if (!preProcess(context)) { - ZLOGE("pre process fail, uri: %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + ZLOGE("pre process fail, uri: %{public}s", URIUtils::Anonymous(context->uri).c_str()); return context->errCode; } return process(); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/template_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/template_strategy.cpp index fd33112a78621d6a1b38315cddd25083197b02af..e771c6151bba4880441be78385bfb0e6acb0a4af 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/template_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/template_strategy.cpp @@ -20,7 +20,7 @@ #include "datashare_errno.h" #include "general/load_config_common_strategy.h" #include "log_print.h" -#include "utils/anonymous.h" +#include "utils.h" namespace OHOS::DataShare { int32_t TemplateStrategy::Execute(std::shared_ptr context, std::function process) @@ -32,7 +32,7 @@ int32_t TemplateStrategy::Execute(std::shared_ptr context, std::functio } if (!preProcess(context)) { - ZLOGE("pre process fail, uri: %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + ZLOGE("pre process fail, uri: %{public}s", URIUtils::Anonymous(context->uri).c_str()); return context->errCode; } return process(); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cea47b58b666c23ec238416fe7896ac8a9e221d2 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2025 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 "ProxyDataSubscriberManager" + +#include "proxy_data_subscriber_manager.h" + +#include "dataproxy_handle_common.h" +#include "ipc_skeleton.h" +#include "log_print.h" +#include "proxy_data_manager.h" +#include "utils.h" +#include "utils/anonymous.h" + +namespace OHOS::DataShare { +ProxyDataSubscriberManager &ProxyDataSubscriberManager::GetInstance() +{ + static ProxyDataSubscriberManager manager; + return manager; +} + +DataProxyErrorCode ProxyDataSubscriberManager::Add(const ProxyDataKey &key, const sptr &observer, + const std::string &bundleName, const std::string &callerAppIdentifier, const int32_t &userId) +{ + auto callerTokenId = IPCSkeleton::GetCallingTokenID(); + ProxyDataCache_.Compute( + key, [&observer, callerTokenId, bundleName, callerAppIdentifier, userId](const ProxyDataKey &key, + std::vector &value) { + ZLOGI("add proxy data subscriber, uri %{public}s", + URIUtils::Anonymous(key.uri).c_str()); + value.emplace_back(observer, callerTokenId, bundleName, callerAppIdentifier, userId); + return true; + }); + return SUCCESS; +} + +DataProxyErrorCode ProxyDataSubscriberManager::Delete(const ProxyDataKey &key, const int32_t &userId) +{ + auto callerTokenId = IPCSkeleton::GetCallingTokenID(); + auto result = + ProxyDataCache_.ComputeIfPresent(key, [&userId, callerTokenId](const auto &key, + std::vector &value) { + for (auto it = value.begin(); it != value.end();) { + if (it->callerTokenId == callerTokenId && it->userId == userId) { + ZLOGI("delete proxy data subscriber, uri %{public}s", + URIUtils::Anonymous(key.uri).c_str()); + it = value.erase(it); + } else { + it++; + } + } + return !value.empty(); + }); + return result ? SUCCESS : URI_NOT_EXIST; +} + +bool ProxyDataSubscriberManager::CheckAllowList(const std::vector &allowList, + const std::string &callerAppIdentifier) +{ + for (const auto &item : allowList) { + if (callerAppIdentifier == item || item == ALLOW_ALL) { + return true; + } + } + return false; +} + +// if arg observer is not null, notify that observer only; otherwise notify all observers +void ProxyDataSubscriberManager::Emit(const std::vector &keys, + const std::map> &datas, const int32_t &userId) +{ + std::map, std::vector> callbacks; + for (auto typeIt = datas.begin(); typeIt != datas.end(); ++typeIt) { + auto type = typeIt->first; + for (const auto &data : typeIt->second) { + std::string bundleName; + URIUtils::GetBundleNameFromProxyURI(data.uri_, bundleName); + auto it = ProxyDataCache_.Find(ProxyDataKey(data.uri_, bundleName)); + if (!it.first) { + continue; + } + auto &observers = it.second; + std::for_each(observers.begin(), observers.end(), + [&callbacks, data, userId, bundleName, &type, this](const auto &obs) { + if ((CheckAllowList(data.allowList_, obs.callerAppIdentifier) || + bundleName == obs.bundleName) && obs.userId == userId) { + callbacks[obs.observer].emplace_back(type, data.uri_, data.value_); + } else { + ZLOGE("no permission to receive notification"); + } + }); + } + } + for (auto &[callback, changeInfo] : callbacks) { + if (callback != nullptr) { + callback->OnChangeFromProxyData(changeInfo); + } + } +} + +void ProxyDataSubscriberManager::Clear() +{ + ProxyDataCache_.Clear(); +} + +ProxyDataKey::ProxyDataKey(const std::string &uri, const std::string &bundle) + : uri(uri), bundleName(bundle) +{ + /* private published data can use key as simple uri */ + /* etc: datashareproxy://{bundleName}/meeting can use meeting replaced */ + /* if key is normal uri, bundleName is from uri */ + if (URIUtils::IsDataProxyURI(uri)) { + URIUtils::GetBundleNameFromProxyURI(uri, bundleName); + } +} + +bool ProxyDataKey::operator<(const ProxyDataKey &rhs) const +{ + return uri < rhs.uri; +} + +bool ProxyDataKey::operator>(const ProxyDataKey &rhs) const +{ + return rhs < *this; +} + +bool ProxyDataKey::operator<=(const ProxyDataKey &rhs) const +{ + return !(rhs < *this); +} + +bool ProxyDataKey::operator>=(const ProxyDataKey &rhs) const +{ + return !(*this < rhs); +} + +bool ProxyDataKey::operator==(const ProxyDataKey &rhs) const +{ + return uri == rhs.uri && bundleName == rhs.bundleName; +} + +bool ProxyDataKey::operator!=(const ProxyDataKey &rhs) const +{ + return !(rhs == *this); +} + +ProxyDataSubscriberManager::ObserverNode::ObserverNode(const sptr &observer, + const uint32_t &callerTokenId, const std::string &bundleName, + const std::string &callerAppIdentifier, const int32_t &userId) : observer(observer), + callerTokenId(callerTokenId), bundleName(bundleName), callerAppIdentifier(callerAppIdentifier), userId(userId) +{ +} +} // namespace OHOS::DataShare diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.h b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..e2e7135ffd3294656e10a7a4fa9c068c91a8710d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025 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 DATASHARESERVICE_PROXY_DATA_SUBSCRIBER_MANAGER_H +#define DATASHARESERVICE_PROXY_DATA_SUBSCRIBER_MANAGER_H + +#include "concurrent_map.h" +#include "data_proxy_observer.h" +#include "dataproxy_handle_common.h" + +namespace OHOS::DataShare { +struct ProxyDataKey { + ProxyDataKey(const std::string &uri, const std::string &bundleName); + bool operator<(const ProxyDataKey &rhs) const; + bool operator>(const ProxyDataKey &rhs) const; + bool operator<=(const ProxyDataKey &rhs) const; + bool operator>=(const ProxyDataKey &rhs) const; + bool operator==(const ProxyDataKey &rhs) const; + bool operator!=(const ProxyDataKey &rhs) const; + std::string uri; + std::string bundleName; +}; + +class ProxyDataSubscriberManager { +public: + static ProxyDataSubscriberManager &GetInstance(); + DataProxyErrorCode Add(const ProxyDataKey &key, const sptr &observer, + const std::string &bundleName, const std::string &callerAppIdentifier, const int32_t &userId); + DataProxyErrorCode Delete(const ProxyDataKey &key, const int32_t &userId); + void Emit(const std::vector &keys, const std::map> &datas, const int32_t &userId); + void Clear(); + +private: +struct ObserverNode { + ObserverNode(const sptr &observer, const uint32_t &callerTokenId, + const std::string &bundleName, const std::string &callerAppIdentifier, const int32_t &userId = 0); + sptr observer; + uint32_t callerTokenId; + std::string bundleName; + std::string callerAppIdentifier; + int32_t userId = 0; + }; + + bool CheckAllowList(const std::vector &allowList, + const std::string &callerAppIdentifier); + ProxyDataSubscriberManager() = default; + ConcurrentMap> ProxyDataCache_; +}; +} // namespace OHOS::DataShare +#endif // DATASHARESERVICE_PROXY_DATA_SUBSCRIBER_MANAGER_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp index 3df3c0164fb2c95a87478b0ee6d52dc87aa4e710..a1a3668515f69be7496efd5cda9f3e6ec4d6a8ae 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp @@ -22,7 +22,7 @@ #include "general/load_config_data_info_strategy.h" #include "log_print.h" #include "published_data.h" -#include "uri_utils.h" +#include "utils.h" #include "utils/anonymous.h" namespace OHOS::DataShare { @@ -32,15 +32,16 @@ PublishedDataSubscriberManager &PublishedDataSubscriberManager::GetInstance() return manager; } -int PublishedDataSubscriberManager::Add( - const PublishedDataKey &key, const sptr observer, uint32_t firstCallerTokenId) +int PublishedDataSubscriberManager::Add(const PublishedDataKey &key, + const sptr observer, uint32_t firstCallerTokenId, int32_t userId) { publishedDataCache_.Compute( - key, [&observer, &firstCallerTokenId, this](const PublishedDataKey &key, std::vector &value) { + key, [&observer, &firstCallerTokenId, userId, this](const PublishedDataKey &key, + std::vector &value) { ZLOGI("add publish subscriber, uri %{public}s tokenId 0x%{public}x", - DistributedData::Anonymous::Change(key.key).c_str(), firstCallerTokenId); + URIUtils::Anonymous(key.key).c_str(), firstCallerTokenId); value.emplace_back(observer, firstCallerTokenId, IPCSkeleton::GetCallingTokenID(), - IPCSkeleton::GetCallingPid()); + IPCSkeleton::GetCallingPid(), userId); return true; }); return E_OK; @@ -54,7 +55,7 @@ int PublishedDataSubscriberManager::Delete(const PublishedDataKey &key, uint32_t for (auto it = value.begin(); it != value.end();) { if (it->firstCallerTokenId == firstCallerTokenId) { ZLOGI("delete publish subscriber, uri %{public}s tokenId 0x%{public}x", - DistributedData::Anonymous::Change(key.key).c_str(), firstCallerTokenId); + URIUtils::Anonymous(key.key).c_str(), firstCallerTokenId); it = value.erase(it); } else { it++; @@ -71,7 +72,7 @@ void PublishedDataSubscriberManager::Delete(uint32_t callerTokenId, uint32_t cal for (auto it = value.begin(); it != value.end();) { if (it->callerTokenId == callerTokenId && it->callerPid == callerPid) { ZLOGI("erase start, uri is %{public}s, tokenId is 0x%{public}x, pid is %{public}d", - DistributedData::Anonymous::Change(key.key).c_str(), callerTokenId, callerPid); + URIUtils::Anonymous(key.key).c_str(), callerTokenId, callerPid); it = value.erase(it); } else { it++; @@ -83,7 +84,7 @@ void PublishedDataSubscriberManager::Delete(uint32_t callerTokenId, uint32_t cal int PublishedDataSubscriberManager::Disable(const PublishedDataKey &key, uint32_t firstCallerTokenId) { - auto result = + bool result = publishedDataCache_.ComputeIfPresent(key, [&firstCallerTokenId](const auto &key, std::vector &value) { for (auto it = value.begin(); it != value.end(); it++) { @@ -94,12 +95,16 @@ int PublishedDataSubscriberManager::Disable(const PublishedDataKey &key, uint32_ } return true; }); + if (!result) { + ZLOGE("disable failed, uri is %{public}s, bundleName is %{public}s, subscriberId is %{public}" PRId64, + URIUtils::Anonymous(key.key).c_str(), key.bundleName.c_str(), key.subscriberId); + } return result ? E_OK : E_SUBSCRIBER_NOT_EXIST; } int PublishedDataSubscriberManager::Enable(const PublishedDataKey &key, uint32_t firstCallerTokenId) { - auto result = + bool result = publishedDataCache_.ComputeIfPresent(key, [&firstCallerTokenId](const auto &key, std::vector &value) { for (auto it = value.begin(); it != value.end(); it++) { @@ -109,9 +114,14 @@ int PublishedDataSubscriberManager::Enable(const PublishedDataKey &key, uint32_t } return true; }); + if (!result) { + ZLOGE("enable failed, uri is %{public}s, bundleName is %{public}s, subscriberId is %{public}" PRId64, + URIUtils::Anonymous(key.key).c_str(), key.bundleName.c_str(), key.subscriberId); + } return result ? E_OK : E_SUBSCRIBER_NOT_EXIST; } +// if arg observer is not null, notify that observer only; otherwise notify all observers void PublishedDataSubscriberManager::Emit(const std::vector &keys, int32_t userId, const std::string &ownerBundleName, const sptr observer) { @@ -133,7 +143,7 @@ void PublishedDataSubscriberManager::Emit(const std::vector &k publishedResult.erase(key); continue; } - PutInto(callbacks, val, key, observer); + PutInto(callbacks, val, key, observer, userId); break; } return false; @@ -157,7 +167,7 @@ void PublishedDataSubscriberManager::Emit(const std::vector &k void PublishedDataSubscriberManager::PutInto( std::map, std::vector> &callbacks, const std::vector &val, const PublishedDataKey &key, - const sptr observer) + const sptr observer, int32_t userId) { for (auto const &callback : val) { if (callback.enabled && callback.observer != nullptr) { @@ -165,6 +175,10 @@ void PublishedDataSubscriberManager::PutInto( if (observer != nullptr && callback.observer != observer) { continue; } + if (callback.userId != 0 && callback.userId != userId && userId != 0) { + ZLOGE("Not across user publish, from %{public}d to %{public}d", userId, callback.userId); + continue; + } callbacks[callback.observer].emplace_back(key); } } @@ -267,8 +281,8 @@ bool PublishedDataKey::operator!=(const PublishedDataKey &rhs) const } PublishedDataSubscriberManager::ObserverNode::ObserverNode(const sptr &observer, - uint32_t firstCallerTokenId, uint32_t callerTokenId, uint32_t callerPid) - : observer(observer), firstCallerTokenId(firstCallerTokenId), callerTokenId(callerTokenId), callerPid(callerPid) + uint32_t firstCallerTokenId, uint32_t callerTokenId, uint32_t callerPid, int32_t userId): observer(observer), + firstCallerTokenId(firstCallerTokenId), callerTokenId(callerTokenId), callerPid(callerPid), userId(userId) { } } // namespace OHOS::DataShare diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.h b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.h index 81024cac574368b3b3c0f7dfee18bd669f3cea65..93295a29bd8a7dc6712e03f90c6af7f9b14e0f2c 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.h @@ -26,7 +26,8 @@ #include "executor_pool.h" namespace OHOS::DataShare { struct PublishedDataKey { - PublishedDataKey(const std::string &key, const std::string &bundleName, int64_t subscriberId); + PublishedDataKey(const std::string &key, const std::string &bundleName, + int64_t subscriberId); bool operator<(const PublishedDataKey &rhs) const; bool operator>(const PublishedDataKey &rhs) const; bool operator<=(const PublishedDataKey &rhs) const; @@ -42,7 +43,7 @@ class PublishedDataSubscriberManager { public: static PublishedDataSubscriberManager &GetInstance(); int Add(const PublishedDataKey &key, const sptr observer, - uint32_t firstCallerTokenId); + uint32_t firstCallerTokenId, int32_t userId); int Delete(const PublishedDataKey &key, uint32_t firstCallerTokenId); void Delete(uint32_t callerTokenId, uint32_t callerPid); int Disable(const PublishedDataKey &key, uint32_t firstCallerTokenId); @@ -58,18 +59,20 @@ public: private: struct ObserverNode { ObserverNode(const sptr &observer, uint32_t firstCallerTokenId, - uint32_t callerTokenId = 0, uint32_t callerPid = 0); + uint32_t callerTokenId = 0, uint32_t callerPid = 0, int32_t userId = 0); sptr observer; uint32_t firstCallerTokenId; uint32_t callerTokenId; uint32_t callerPid; bool enabled = true; bool isNotifyOnEnabled = false; + int32_t userId = 0; }; PublishedDataSubscriberManager() = default; void PutInto(std::map, std::vector> &, - const std::vector &, const PublishedDataKey &, const sptr); + const std::vector &, const PublishedDataKey &, const sptr, + int32_t userId); ConcurrentMap> publishedDataCache_; }; } // namespace OHOS::DataShare 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 de0d94af7385e335bd120951cbb94fde6bb8089d..ed4df8eae20cb7b087479ac3758131c53395164c 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 @@ -24,7 +24,7 @@ #include "log_print.h" #include "scheduler_manager.h" #include "template_data.h" -#include "uri_utils.h" +#include "utils.h" #include "utils/anonymous.h" namespace OHOS::DataShare { @@ -116,23 +116,24 @@ int RdbSubscriberManager::Add(const Key &key, const sptr { int result = E_OK; rdbCache_.Compute(key, [&observer, &context, executorPool, this](const auto &key, auto &value) { - ZLOGI("add subscriber, uri %{private}s tokenId 0x%{public}x", key.uri.c_str(), context->callerTokenId); + ZLOGI("add subscriber, uri %{public}s tokenId 0x%{public}x", + URIUtils::Anonymous(key.uri).c_str(), context->callerTokenId); auto callerTokenId = IPCSkeleton::GetCallingTokenID(); auto callerPid = IPCSkeleton::GetCallingPid(); - value.emplace_back(observer, context->callerTokenId, callerTokenId, callerPid); + value.emplace_back(observer, context->callerTokenId, callerTokenId, callerPid, context->visitedUserId); std::vector node; - node.emplace_back(observer, context->callerTokenId, callerTokenId, callerPid); + node.emplace_back(observer, context->callerTokenId, callerTokenId, callerPid, context->visitedUserId); ExecutorPool::Task task = [key, node, context, this]() { LoadConfigDataInfoStrategy loadDataInfo; if (!loadDataInfo(context)) { ZLOGE("loadDataInfo failed, uri %{public}s tokenId 0x%{public}x", - DistributedData::Anonymous::Change(key.uri).c_str(), context->callerTokenId); + URIUtils::Anonymous(key.uri).c_str(), context->callerTokenId); return; } DistributedData::StoreMetaData metaData = RdbSubscriberManager::GenMetaDataFromContext(context); - Notify(key, context->currentUserId, node, metaData); + Notify(key, context->visitedUserId, node, metaData); if (GetEnableObserverCount(key) == 1) { - SchedulerManager::GetInstance().Start(key, context->currentUserId, metaData); + SchedulerManager::GetInstance().Start(key, context->visitedUserId, metaData); } }; executorPool->Execute(task); @@ -147,7 +148,7 @@ int RdbSubscriberManager::Delete(const Key &key, uint32_t firstCallerTokenId) rdbCache_.ComputeIfPresent(key, [&firstCallerTokenId, this](const auto &key, std::vector &value) { ZLOGI("delete subscriber, uri %{public}s tokenId 0x%{public}x", - DistributedData::Anonymous::Change(key.uri).c_str(), firstCallerTokenId); + URIUtils::Anonymous(key.uri).c_str(), firstCallerTokenId); for (auto it = value.begin(); it != value.end();) { if (it->firstCallerTokenId == firstCallerTokenId) { ZLOGI("erase start"); @@ -177,7 +178,7 @@ void RdbSubscriberManager::Delete(uint32_t callerTokenId, uint32_t callerPid) if (value.empty()) { ZLOGI("delete timer, subId %{public}" PRId64 ", bundleName %{public}s, tokenId %{public}x, uri %{public}s.", key.subscriberId, key.bundleName.c_str(), callerTokenId, - DistributedData::Anonymous::Change(key.uri).c_str()); + URIUtils::Anonymous(key.uri).c_str()); SchedulerManager::GetInstance().Stop(key); } return value.empty(); @@ -187,7 +188,7 @@ void RdbSubscriberManager::Delete(uint32_t callerTokenId, uint32_t callerPid) int RdbSubscriberManager::Disable(const Key &key, uint32_t firstCallerTokenId) { bool isAllDisabled = true; - auto result = + bool result = rdbCache_.ComputeIfPresent(key, [&firstCallerTokenId, &isAllDisabled, this](const auto &key, std::vector &value) { for (auto it = value.begin(); it != value.end(); it++) { @@ -204,6 +205,10 @@ int RdbSubscriberManager::Disable(const Key &key, uint32_t firstCallerTokenId) if (isAllDisabled) { SchedulerManager::GetInstance().Disable(key); } + if (!result) { + ZLOGE("disable failed, uri is %{public}s, bundleName is %{public}s, subscriberId is %{public}" PRId64, + URIUtils::Anonymous(key.uri).c_str(), key.bundleName.c_str(), key.subscriberId); + } return result ? E_OK : E_SUBSCRIBER_NOT_EXIST; } @@ -211,7 +216,7 @@ int RdbSubscriberManager::Enable(const Key &key, std::shared_ptr contex { bool isChanged = false; DistributedData::StoreMetaData metaData; - auto result = rdbCache_.ComputeIfPresent(key, [&context, &metaData, &isChanged, this](const auto &key, + bool result = rdbCache_.ComputeIfPresent(key, [&context, &metaData, &isChanged, this](const auto &key, std::vector &value) { for (auto it = value.begin(); it != value.end(); it++) { if (it->firstCallerTokenId != context->callerTokenId) { @@ -227,13 +232,17 @@ int RdbSubscriberManager::Enable(const Key &key, std::shared_ptr contex if (it->isNotifyOnEnabled) { std::vector node; node.emplace_back(it->observer, context->callerTokenId); - Notify(key, context->currentUserId, node, metaData); + Notify(key, context->visitedUserId, node, metaData); } } return true; }); if (isChanged) { - SchedulerManager::GetInstance().Enable(key, context->currentUserId, metaData); + SchedulerManager::GetInstance().Enable(key, context->visitedUserId, metaData); + } + if (!result) { + ZLOGE("enable failed, uri is %{public}s, bundleName is %{public}s, subscriberId is %{public}" PRId64, + URIUtils::Anonymous(key.uri).c_str(), key.bundleName.c_str(), key.subscriberId); } return result ? E_OK : E_SUBSCRIBER_NOT_EXIST; } @@ -252,12 +261,12 @@ void RdbSubscriberManager::Emit(const std::string &uri, std::shared_ptr if (key.uri != uri) { return false; } - Notify(key, context->currentUserId, val, metaData); + Notify(key, context->visitedUserId, val, metaData); SetObserverNotifyOnEnabled(val); return false; }); SchedulerManager::GetInstance().Execute( - uri, context->currentUserId, metaData); + uri, context->visitedUserId, metaData); } void RdbSubscriberManager::Emit(const std::string &uri, int32_t userId, @@ -338,15 +347,14 @@ int RdbSubscriberManager::Notify(const Key &key, int32_t userId, const std::vect Template tpl; if (!TemplateManager::GetInstance().Get(key, userId, tpl)) { ZLOGE("template undefined, %{public}s, %{public}" PRId64 ", %{public}s", - DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); return E_TEMPLATE_NOT_EXIST; } DistributedData::StoreMetaData meta = metaData; - meta.bundleName = key.bundleName; meta.user = std::to_string(userId); auto delegate = DBDelegate::Create(meta, key.uri); if (delegate == nullptr) { - ZLOGE("Create fail %{public}s %{public}s", DistributedData::Anonymous::Change(key.uri).c_str(), + ZLOGE("Create fail %{public}s %{public}s", URIUtils::Anonymous(key.uri).c_str(), key.bundleName.c_str()); return E_ERROR; } @@ -365,13 +373,19 @@ int RdbSubscriberManager::Notify(const Key &key, int32_t userId, const std::vect auto [errCode, rowCount] = delegate->UpdateSql(tpl.update_); if (errCode != E_OK) { ZLOGE("Update failed, err:%{public}d, %{public}s, %{public}" PRId64 ", %{public}s", - errCode, DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); + errCode, URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); } } ZLOGI("emit, valSize: %{public}zu, dataSize:%{public}zu, uri:%{public}s,", - val.size(), changeNode.data_.size(), DistributedData::Anonymous::Change(changeNode.uri_).c_str()); + val.size(), changeNode.data_.size(), URIUtils::Anonymous(changeNode.uri_).c_str()); for (const auto &callback : val) { + // not notify across user + if (callback.userId != userId && userId != 0 && callback.userId != 0) { + ZLOGI("Not allow across notify, uri:%{public}s, from %{public}d to %{public}d.", + URIUtils::Anonymous(changeNode.uri_).c_str(), userId, callback.userId); + continue; + } if (callback.enabled && callback.observer != nullptr) { callback.observer->OnChangeFromRdb(changeNode); } @@ -399,12 +413,12 @@ void RdbSubscriberManager::Emit(const std::string &uri, int64_t subscriberId, if (key.uri != uri || key.subscriberId != subscriberId) { return false; } - Notify(key, context->currentUserId, val, metaData); + Notify(key, context->visitedUserId, val, metaData); SetObserverNotifyOnEnabled(val); return false; }); Key executeKey(uri, subscriberId, bundleName); - SchedulerManager::GetInstance().Start(executeKey, context->currentUserId, metaData); + SchedulerManager::GetInstance().Start(executeKey, context->visitedUserId, metaData); } DistributedData::StoreMetaData RdbSubscriberManager::GenMetaDataFromContext(const std::shared_ptr context) @@ -414,12 +428,14 @@ DistributedData::StoreMetaData RdbSubscriberManager::GenMetaDataFromContext(cons metaData.dataDir = context->calledSourceDir; metaData.storeId = context->calledStoreName; metaData.haMode = context->haMode; + metaData.isEncrypt = context->isEncryptDb; + metaData.bundleName = context->calledBundleName; return metaData; } RdbSubscriberManager::ObserverNode::ObserverNode(const sptr &observer, - uint32_t firstCallerTokenId, uint32_t callerTokenId, uint32_t callerPid) - : observer(observer), firstCallerTokenId(firstCallerTokenId), callerTokenId(callerTokenId), callerPid(callerPid) + uint32_t firstCallerTokenId, uint32_t callerTokenId, uint32_t callerPid, int32_t userId): observer(observer), + firstCallerTokenId(firstCallerTokenId), callerTokenId(callerTokenId), callerPid(callerPid), userId(userId) { } } // namespace OHOS::DataShare \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.h b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.h index 9379ed1aeee6c68d8c47a0fa57b43586b442b3dc..35c4a2b3868eea190275837981cf5126534cb05b 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.h @@ -73,13 +73,14 @@ public: private: struct ObserverNode { ObserverNode(const sptr &observer, uint32_t firstCallerTokenId, - uint32_t callerTokenId = 0, uint32_t callerPid = 0); + uint32_t callerTokenId = 0, uint32_t callerPid = 0, int32_t userId = 0); sptr observer; uint32_t firstCallerTokenId; uint32_t callerTokenId; uint32_t callerPid; bool enabled = true; bool isNotifyOnEnabled = false; + int32_t userId = 0; }; RdbSubscriberManager() = default; 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 b0fe15ee2318ac49b302c0b461f0fdd80de88cd6..afd50786200cc611a65faaa9ffd2fc97b75b6c26 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 @@ -18,19 +18,46 @@ #include "common_event_manager.h" #include "common_event_support.h" #include "log_print.h" +#include "proxy_data_manager.h" namespace OHOS::DataShare { -SysEventSubscriber::SysEventSubscriber(const EventFwk::CommonEventSubscribeInfo& info) - : CommonEventSubscriber(info) +SysEventSubscriber::SysEventSubscriber(const EventFwk::CommonEventSubscribeInfo& info, + std::shared_ptr executors): CommonEventSubscriber(info), executors_(executors) { - callbacks_ = { { EventFwk::CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED, - &SysEventSubscriber::OnBMSReady } }; + callbacks_ = { + { EventFwk::CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED, + &SysEventSubscriber::OnBMSReady } + }; + installCallbacks_ = { + { EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED, + &SysEventSubscriber::OnAppInstall }, + { EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED, + &SysEventSubscriber::OnAppUpdate }, + { EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED, + &SysEventSubscriber::OnAppUninstall } + }; } void SysEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData& event) { EventFwk::Want want = event.GetWant(); std::string action = want.GetAction(); + auto installEvent = installCallbacks_.find(action); + if (installEvent != installCallbacks_.end()) { + std::string bundleName = want.GetElement().GetBundleName(); + int32_t userId = want.GetIntParam(USER_ID, -1); + int32_t appIndex = want.GetIntParam(APP_INDEX, 0); + uint32_t tokenId = static_cast(want.GetIntParam(ACCESS_TOKEN_ID, 0)); + // when application updated, the tokenId in event's want is 0, so use other way to get tokenId + if (tokenId == 0) { + tokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(userId, bundleName, appIndex); + } + bool isCrossAppSharedConfig = want.GetBoolParam(CROSS_APP_SHARED_CONFIG, false); + ZLOGI("bundleName:%{public}s, user:%{public}d, appIndex:%{public}d, tokenId:%{public}d, " + "isCrossAppSharedConfig:%{public}d", bundleName.c_str(), userId, appIndex, tokenId, isCrossAppSharedConfig); + (this->*(installEvent->second))(bundleName, userId, appIndex, tokenId, isCrossAppSharedConfig); + } + auto it = callbacks_.find(action); if (it != callbacks_.end()) { (this->*(it->second))(); @@ -40,6 +67,42 @@ void SysEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData& event) void SysEventSubscriber::OnBMSReady() { NotifyDataShareReady(); + auto executors = executors_; + if (executors == nullptr) { + ZLOGE("executors is null."); + return; + } + executors->Execute([]() { + DataShareServiceImpl::UpdateLaunchInfo(); + }); +} + +void SysEventSubscriber::OnAppInstall(const std::string &bundleName, + int32_t userId, int32_t appIndex, uint32_t tokenId, bool isCrossAppSharedConfig) +{ + ZLOGI("%{public}s installed, userId: %{public}d, appIndex: %{public}d, tokenId: %{public}d", + bundleName.c_str(), userId, appIndex, tokenId); + if (isCrossAppSharedConfig) { + ProxyDataManager::GetInstance().OnAppInstall(bundleName, userId, appIndex, tokenId); + } +} + +void SysEventSubscriber::OnAppUpdate(const std::string &bundleName, + int32_t userId, int32_t appIndex, uint32_t tokenId, bool isCrossAppSharedConfig) +{ + ZLOGI("%{public}s updated, userId: %{public}d, appIndex: %{public}d, tokenId: %{public}d", + bundleName.c_str(), userId, appIndex, tokenId); + if (isCrossAppSharedConfig) { + ProxyDataManager::GetInstance().OnAppUpdate(bundleName, userId, appIndex, tokenId); + } +} + +void SysEventSubscriber::OnAppUninstall(const std::string &bundleName, + int32_t userId, int32_t appIndex, uint32_t tokenId, bool isCrossAppSharedConfig) +{ + ZLOGI("%{public}s uninstalled, userId: %{public}d, appIndex: %{public}d, tokenId: %{public}d", + bundleName.c_str(), userId, appIndex, tokenId); + ProxyDataManager::GetInstance().OnAppUninstall(bundleName, userId, appIndex, tokenId); } void SysEventSubscriber::NotifyDataShareReady() @@ -55,4 +118,4 @@ void SysEventSubscriber::NotifyDataShareReady() } ZLOGI("Notify dataShare ready succeed."); } -} +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/sys_event_subscriber.h b/datamgr_service/services/distributeddataservice/service/data_share/sys_event_subscriber.h index b266387ccec7bda71db1dd52c196ec8258a4be7b..0594044b556104ebc91ab11f5a5de14235abe289 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/sys_event_subscriber.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/sys_event_subscriber.h @@ -23,14 +23,29 @@ namespace OHOS::DataShare { class SysEventSubscriber : public EventFwk::CommonEventSubscriber { public: using SysEventCallback = void (SysEventSubscriber::*)(); - explicit SysEventSubscriber(const EventFwk::CommonEventSubscribeInfo &info); + using InstallEventCallback = void (SysEventSubscriber::*)(const std::string &bundleName, + int32_t userId, int32_t appIndex, uint32_t tokenId, bool isCrossAppSharedConfig); + explicit SysEventSubscriber(const EventFwk::CommonEventSubscribeInfo &info, + std::shared_ptr executors); ~SysEventSubscriber() {} void OnReceiveEvent(const EventFwk::CommonEventData& event) override; void OnBMSReady(); + void OnAppInstall(const std::string &bundleName, + int32_t userId, int32_t appIndex, uint32_t tokenId, bool isCrossAppSharedConfig); + void OnAppUpdate(const std::string &bundleName, + int32_t userId, int32_t appIndex, uint32_t tokenId, bool isCrossAppSharedConfig); + void OnAppUninstall(const std::string &bundleName, + int32_t userId, int32_t appIndex, uint32_t tokenId, bool isCrossAppSharedConfig); private: void NotifyDataShareReady(); std::map callbacks_; + std::map installCallbacks_; + static constexpr const char *USER_ID = "userId"; + static constexpr const char *APP_INDEX = "appIndex"; + static constexpr const char *ACCESS_TOKEN_ID = "accessTokenId"; + static constexpr const char *CROSS_APP_SHARED_CONFIG = "crossAppSharedConfig"; + std::shared_ptr executors_ = nullptr; }; } #endif \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/dumper/BUILD.gn b/datamgr_service/services/distributeddataservice/service/dumper/BUILD.gn index 9ba04db730065c7b59673957e5139b95ee97690e..72b194d7931caefdcea75bf011235bf903cb219b 100644 --- a/datamgr_service/services/distributeddataservice/service/dumper/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/dumper/BUILD.gn @@ -27,7 +27,6 @@ ohos_source_set("distributeddata_dumper") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ "include" ] @@ -38,7 +37,6 @@ ohos_source_set("distributeddata_dumper") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/BUILD.gn b/datamgr_service/services/distributeddataservice/service/kvdb/BUILD.gn index 9f1d96daecc06fe735cabe6849bc578bfa68b695..874dc361c3edfbe0a3cd345c7f8e1cf6998d0af9 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/kvdb/BUILD.gn @@ -55,7 +55,6 @@ ohos_source_set("distributeddata_kvdb") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] cflags = [ @@ -64,7 +63,6 @@ ohos_source_set("distributeddata_kvdb") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.cpp index 320db40c8e4213538be38e0985695fdbdfbcfc64..f76965451bf328bfd835be7706c169da18a5f590 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.cpp @@ -63,9 +63,6 @@ std::pair AuthHandlerStub::CheckAccess(int localUserId, int peerUser if (!CheckUsers(localUserId, peerUserId, peerDeviceId)) { return std::make_pair(false, false); } - if (!DmAdapter::GetInstance().IsOHOSType(peerDeviceId)) { - return std::make_pair(true, false); - } if (aclParams.authType == static_cast(DistributedKv::AuthType::DEFAULT)) { if (DmAdapter::GetInstance().IsSameAccount(aclParams.accCaller, aclParams.accCallee)) { return std::make_pair(true, true); diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.h b/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.h index 199b7e74599245cbd4f123389bfa89da1a534e75..29d9f551986f7277a162532360e57b6a37701d67 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.h @@ -34,11 +34,13 @@ enum AUTH_GROUP_TYPE { class AuthHandler { public: virtual std::pair CheckAccess(int localUserId, int peerUserId, - const std::string &peerDeviceId, const AclParams &aclParams); + const std::string &peerDeviceId, const AclParams &aclParams) = 0; + virtual ~AuthHandler() = default; }; class AuthDelegate { public: + AuthDelegate() = default; API_EXPORT static AuthHandler *GetInstance(); }; } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_exporter.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_exporter.cpp index b9b4f8c71905c7e5daaa7bed3e26a04e881beecd..41281f790a873b68860563810b1b29da5b7f5f6c 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_exporter.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_exporter.cpp @@ -16,10 +16,11 @@ #include "kvdb_exporter.h" #include "backup_manager.h" +#include "dfx/reporter.h" #include "directory/directory_manager.h" #include "kvdb_general_store.h" #include "log_print.h" -#include "dfx/reporter.h" +#include "utils/anonymous.h" namespace OHOS::DistributedKv { using namespace OHOS::DistributedData; using namespace OHOS::DistributedDataDfx; @@ -42,7 +43,8 @@ void KVDBExporter::Exporter(const StoreMetaData &meta, const std::string &backup } dbStatus = delegate->CheckIntegrity(); if (dbStatus != DistributedDB::DBStatus::OK) { - ZLOGE("CheckIntegrity fail, dbStatus:%{public}d, backupPath:%{public}s", dbStatus, backupPath.c_str()); + ZLOGE("CheckIntegrity fail, dbStatus:%{public}d, backupPath:%{public}s", dbStatus, + Anonymous::Change(backupPath).c_str()); result = false; return; } @@ -60,7 +62,7 @@ void KVDBExporter::Exporter(const StoreMetaData &meta, const std::string &backup .append(std::to_string(result)) .append("]"); Reporter::GetInstance()->GetBehaviourReporter()->Report( - { meta.account, meta.appId, meta.storeId, BehaviourType::DATABASE_BACKUP, message }); + { meta.account, meta.appId, Anonymous::Change(meta.storeId), BehaviourType::DATABASE_BACKUP, message }); } KVDBExporter::KVDBExporter() noexcept 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 da7a931e89ec2c750403b4ac097643ad8587f709..b825f970c85d4e4392cb8a82c523df6d05ec1819 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.cpp @@ -20,13 +20,15 @@ #include "app_id_mapping/app_id_mapping_config_manager.h" #include "bootstrap.h" #include "checker/checker_manager.h" +#include "cloud/cloud_sync_finished_event.h" #include "cloud/schema_meta.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter.h" #include "device_matrix.h" #include "dfx/dfx_types.h" #include "dfx/reporter.h" #include "directory/directory_manager.h" +#include "eventcenter/event_center.h" #include "kvdb_query.h" #include "log_print.h" #include "metadata/meta_data_manager.h" @@ -96,21 +98,26 @@ static DBSchema GetDBSchema(const Database &database) } return schema; } + KVDBGeneralStore::DBPassword KVDBGeneralStore::GetDBPassword(const StoreMetaData &data) { DBPassword dbPassword; if (!data.isEncrypt) { return dbPassword; } - SecretKeyMetaData secretKey; - secretKey.storeType = data.storeType; - auto storeKey = data.GetSecretKey(); - MetaDataManager::GetInstance().LoadMeta(storeKey, secretKey, true); - std::vector password; - StoreMetaData metaData; - MetaDataManager::GetInstance().LoadMeta(data.GetKey(), metaData, true); - CryptoManager::GetInstance().Decrypt(metaData, secretKey, password); + auto metaKey = data.GetSecretKey(); + if (!MetaDataManager::GetInstance().LoadMeta(metaKey, secretKey, true) || secretKey.sKey.empty()) { + return dbPassword; + } + CryptoManager::CryptoParams decryptParams = { .area = secretKey.area, .userId = data.user, + .nonce = secretKey.nonce }; + auto password = CryptoManager::GetInstance().Decrypt(secretKey.sKey, decryptParams); + if (password.empty()) { + return dbPassword; + } + // update secret key of area or nonce + CryptoManager::GetInstance().UpdateSecretMeta(password, data, metaKey, secretKey); dbPassword.SetValue(password.data(), password.size()); password.assign(password.size(), 0); return dbPassword; @@ -171,8 +178,8 @@ KVDBGeneralStore::KVDBGeneralStore(const StoreMetaData &meta) DBStatus status = DBStatus::NOT_FOUND; manager_.SetKvStoreConfig({ meta.dataDir }); std::unique_lock lock(rwMutex_); - manager_.GetKvStore(meta.storeId, GetDBOption(meta, GetDBPassword(meta)), - [&status, this](auto dbStatus, auto *tmpStore) { + manager_.GetKvStore( + meta.storeId, GetDBOption(meta, GetDBPassword(meta)), [&status, this](auto dbStatus, auto *tmpStore) { status = dbStatus; delegate_ = tmpStore; }); @@ -199,7 +206,7 @@ KVDBGeneralStore::KVDBGeneralStore(const StoreMetaData &meta) storeInfo_.bundleName = meta.bundleName; storeInfo_.storeName = meta.storeId; storeInfo_.instanceId = meta.instanceId; - storeInfo_.user = std::stoi(meta.user); + storeInfo_.user = std::atoi(meta.user.c_str()); enableCloud_ = meta.enableCloud; } @@ -229,8 +236,8 @@ int32_t KVDBGeneralStore::BindSnapshots(std::shared_ptr &bindInfos, - const CloudConfig &config) +int32_t KVDBGeneralStore::Bind( + const Database &database, const std::map &bindInfos, const CloudConfig &config) { if (bindInfos.empty()) { ZLOGW("No cloudDB!"); @@ -245,8 +252,8 @@ int32_t KVDBGeneralStore::Bind(const Database &database, const std::map(bindInfo.db_, nullptr) }); + dbClouds.insert({ std::to_string(userId), + std::make_shared(bindInfo.db_, nullptr) }); bindInfos_.insert(std::make_pair(userId, std::move(bindInfo))); schemas.insert({ std::to_string(userId), dbSchema }); } @@ -255,6 +262,7 @@ int32_t KVDBGeneralStore::Bind(const Database &database, const std::map lock(rwMutex_); if (delegate_ == nullptr) { return GeneralError::E_ALREADY_CLOSED; @@ -321,8 +329,8 @@ int32_t KVDBGeneralStore::Replace(const std::string &table, VBucket &&value) return GeneralError::E_NOT_SUPPORT; } -std::pair> KVDBGeneralStore::Query(__attribute__((unused)) const std::string &table, - const std::string &sql, Values &&args) +std::pair> KVDBGeneralStore::Query( + __attribute__((unused)) const std::string &table, const std::string &sql, Values &&args) { return { GeneralError::E_NOT_SUPPORT, nullptr }; } @@ -372,7 +380,11 @@ DBStatus KVDBGeneralStore::CloudSync(const Devices &devices, DistributedDB::Sync syncOption.lockAction = DistributedDB::LockAction::NONE; if (storeInfo_.user == 0) { std::vector users; - AccountDelegate::GetInstance()->QueryUsers(users); + auto ret = AccountDelegate::GetInstance()->QueryUsers(users); + if (!ret || users.empty()) { + ZLOGE("failed to query os accounts, ret:%{public}d", ret); + return DBStatus::DB_ERROR; + } syncOption.users.push_back(std::to_string(users[0])); } else { syncOption.users.push_back(std::to_string(storeInfo_.user)); @@ -431,11 +443,9 @@ std::pair KVDBGeneralStore::Sync(const Devices &devices, GenQu dbStatus = delegate_->UnSubscribeRemoteQuery(devices, GetDBSyncCompleteCB(std::move(async)), dbQuery, false); } else if (syncMode < NEARBY_END) { - if (kvQuery->IsEmpty()) { - dbStatus = delegate_->Sync(devices, dbMode, GetDBSyncCompleteCB(std::move(async)), false); - } else { - dbStatus = delegate_->Sync(devices, dbMode, GetDBSyncCompleteCB(std::move(async)), dbQuery, false); - } + DeviceSyncOption syncOption = { .devices = devices, .mode = dbMode, .query = dbQuery, .isWait = false, + .isRetry = syncParam.isRetry }; + dbStatus = delegate_->Sync(syncOption, GetDBSyncCompleteCB(std::move(async))); } else { ZLOGE("Err sync mode! sync mode:%{public}d", syncMode); dbStatus = DistributedDB::INVALID_ARGS; @@ -465,22 +475,24 @@ void KVDBGeneralStore::SetEqualIdentifier(const std::string &appId, const std::s auto accountId = account.empty() ? AccountDelegate::GetInstance()->GetUnencryptedAccountId() : account; 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", + ZLOGI("same account store:%{public}s, user:%{public}s, device:%{public}s, appId:%{public}s", Anonymous::Change(storeId).c_str(), Anonymous::Change(convertedIds.second).c_str(), - DistributedData::Serializable::Marshall(sameAccountDevs).c_str(), convertedIds.first.c_str()); + Anonymous::Change(DistributedData::Serializable::Marshall(sameAccountDevs)).c_str(), + convertedIds.first.c_str()); delegate_->SetEqualIdentifier(identifier, sameAccountDevs); } if (!defaultAccountDevs.empty()) { 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(), convertedIds.first.c_str()); + ZLOGI("no account store:%{public}s, device:%{public}s, appId:%{public}s", Anonymous::Change(storeId).c_str(), + Anonymous::Change(DistributedData::Serializable::Marshall(defaultAccountDevs)).c_str(), + convertedIds.first.c_str()); delegate_->SetEqualIdentifier(identifier, defaultAccountDevs); } } -void KVDBGeneralStore::GetIdentifierParams(std::vector &devices, const std::vector &uuids, - int32_t authType) +void KVDBGeneralStore::GetIdentifierParams( + std::vector &devices, const std::vector &uuids, int32_t authType) { for (const auto &devId : uuids) { if (DMAdapter::GetInstance().IsOHOSType(devId)) { @@ -511,14 +523,19 @@ int32_t KVDBGeneralStore::Clean(const std::vector &devices, int32_t return GeneralError::E_ALREADY_CLOSED; } DBStatus status = OK; + ClearKvMetaDataOption option; switch (mode) { case CLOUD_INFO: - status = delegate_->RemoveDeviceData("", - isPublic_ ? static_cast(CLOUD_DATA) : 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)); break; + case CLEAN_WATER: + option.type = ClearKvMetaOpType::CLEAN_CLOUD_WATERMARK; + status = delegate_->ClearMetaData(option); + break; case NEARBY_DATA: if (devices.empty()) { status = delegate_->RemoveDeviceData(); @@ -580,8 +597,8 @@ int32_t KVDBGeneralStore::AddRef() return ++ref_; } -int32_t KVDBGeneralStore::SetDistributedTables(const std::vector &tables, int32_t type, - const std::vector &references) +int32_t KVDBGeneralStore::SetDistributedTables( + const std::vector &tables, int32_t type, const std::vector &references) { return GeneralError::E_OK; } 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 f04980ccc167301f48916a6a907e72f745330e5e..c497a1288eb9c3d409f49d361888856b94368bbb 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp @@ -27,7 +27,6 @@ #include "cloud/cloud_server.h" #include "communication_provider.h" #include "communicator_context.h" -#include "crypto_manager.h" #include "device_manager_adapter.h" #include "directory/directory_manager.h" #include "dump/dump_manager.h" @@ -40,6 +39,7 @@ #include "matrix_event.h" #include "metadata/appid_meta_data.h" #include "metadata/capability_meta_data.h" +#include "metadata/store_meta_data.h" #include "metadata/switches_meta_data.h" #include "permit_delegate.h" #include "query_helper.h" @@ -101,7 +101,7 @@ void KVDBServiceImpl::Init() auto process = [this](const Event &event) { const auto &evt = static_cast(event); const auto &storeInfo = evt.GetStoreInfo(); - StoreMetaData meta(storeInfo); + StoreMetaMapping meta(storeInfo); meta.deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid; if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { if (meta.user == "0") { @@ -111,8 +111,8 @@ void KVDBServiceImpl::Init() } meta.user = "0"; StoreMetaDataLocal localMeta; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMeta, true) || !localMeta.isPublic || - !MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true) || + !MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMeta, true) || !localMeta.isPublic) { ZLOGE("meta empty, not public store. bundleName:%{public}s, storeId:%{public}s, user = %{public}s", meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), meta.user.c_str()); return; @@ -180,7 +180,7 @@ Status KVDBServiceImpl::GetStoreIds(const AppId &appId, int32_t subUser, std::ve Status KVDBServiceImpl::Delete(const AppId &appId, const StoreId &storeId, int32_t subUser) { - StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); + StoreMetaData metaData = LoadStoreMetaData(appId, storeId, subUser); if (metaData.instanceId < 0) { return ILLEGAL_STATE; } @@ -193,7 +193,9 @@ Status KVDBServiceImpl::Delete(const AppId &appId, const StoreId &storeId, int32 syncAgent.delayTimes_.erase(storeId); return true; }); - MetaDataManager::GetInstance().DelMeta(metaData.GetKey()); + StoreMetaMapping storeMetaMapping(metaData); + MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true); + MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath()); MetaDataManager::GetInstance().DelMeta(metaData.GetKey(), true); MetaDataManager::GetInstance().DelMeta(metaData.GetKeyLocal(), true); MetaDataManager::GetInstance().DelMeta(metaData.GetSecretKey(), true); @@ -202,8 +204,8 @@ Status KVDBServiceImpl::Delete(const AppId &appId, const StoreId &storeId, int32 MetaDataManager::GetInstance().DelMeta(metaData.GetAutoLaunchKey(), true); MetaDataManager::GetInstance().DelMeta(metaData.GetDebugInfoKey(), true); MetaDataManager::GetInstance().DelMeta(metaData.GetCloneSecretKey(), true); - PermitDelegate::GetInstance().DelCache(metaData.GetKey()); - AutoCache::GetInstance().CloseStore(metaData.tokenId, storeId, metaData.user); + PermitDelegate::GetInstance().DelCache(metaData.GetKeyWithoutPath()); + AutoCache::GetInstance().CloseStore(metaData.tokenId, metaData.dataDir); ZLOGD("appId:%{public}s storeId:%{public}s instanceId:%{public}d", appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), metaData.instanceId); return SUCCESS; @@ -211,11 +213,11 @@ Status KVDBServiceImpl::Delete(const AppId &appId, const StoreId &storeId, int32 Status KVDBServiceImpl::Close(const AppId &appId, const StoreId &storeId, int32_t subUser) { - StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); + StoreMetaData metaData = LoadStoreMetaData(appId, storeId, subUser); if (metaData.instanceId < 0) { return ILLEGAL_STATE; } - AutoCache::GetInstance().CloseStore(metaData.tokenId, storeId, metaData.user); + AutoCache::GetInstance().CloseStore(metaData.tokenId, metaData.dataDir, storeId); ZLOGD("appId:%{public}s storeId:%{public}s instanceId:%{public}d", appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), metaData.instanceId); return SUCCESS; @@ -223,7 +225,7 @@ Status KVDBServiceImpl::Close(const AppId &appId, const StoreId &storeId, int32_ Status KVDBServiceImpl::CloudSync(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo) { - StoreMetaData metaData = GetStoreMetaData(appId, storeId); + StoreMetaMapping metaData = GetStoreMetaData(appId, storeId); if (!MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true)) { ZLOGE("invalid, appId:%{public}s storeId:%{public}s", appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str()); @@ -243,8 +245,14 @@ void KVDBServiceImpl::OnAsyncComplete(uint32_t tokenId, uint64_t seqNum, Progres Status KVDBServiceImpl::Sync(const AppId &appId, const StoreId &storeId, int32_t subUser, SyncInfo &syncInfo) { + auto instanceId = GetInstIndex(IPCSkeleton::GetCallingTokenID(), appId); + if (instanceId != 0) { + ZLOGE("twin application not allow sync, instanceId:%{public}d, appId:%{public}s, storeId:%{public}s", + instanceId, appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str()); + return Status::NOT_SUPPORT; + } StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); - MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData); + MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData); auto delay = GetSyncDelayTime(syncInfo.delay, storeId, metaData.user); if (metaData.isAutoSync && syncInfo.seqId == std::numeric_limits::max()) { DeviceMatrix::GetInstance().OnChanged(metaData); @@ -269,7 +277,7 @@ Status KVDBServiceImpl::Sync(const AppId &appId, const StoreId &storeId, int32_t Status KVDBServiceImpl::NotifyDataChange(const AppId &appId, const StoreId &storeId, uint64_t delay) { StoreMetaData meta = GetStoreMetaData(appId, storeId); - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) { + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyWithoutPath(), meta)) { ZLOGE("invalid, appId:%{public}s storeId:%{public}s", appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str()); return Status::INVALID_ARGUMENT; @@ -527,7 +535,7 @@ Status KVDBServiceImpl::AddSubscribeInfo(const AppId &appId, const StoreId &stor const SyncInfo &syncInfo) { StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); - MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData); + MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData); auto delay = GetSyncDelayTime(syncInfo.delay, storeId, metaData.user); return KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(metaData.tokenId), delay, std::bind(&KVDBServiceImpl::DoSyncInOrder, this, metaData, syncInfo, std::placeholders::_1, ACTION_SUBSCRIBE), @@ -538,7 +546,7 @@ Status KVDBServiceImpl::RmvSubscribeInfo(const AppId &appId, const StoreId &stor const SyncInfo &syncInfo) { StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); - MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData); + MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData); auto delay = GetSyncDelayTime(syncInfo.delay, storeId, metaData.user); return KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(metaData.tokenId), delay, std::bind( @@ -552,7 +560,7 @@ Status KVDBServiceImpl::Subscribe(const AppId &appId, const StoreId &storeId, in if (observer == nullptr) { return INVALID_ARGUMENT; } - StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); + StoreMetaData metaData = LoadStoreMetaData(appId, storeId, subUser); ZLOGI("appId:%{public}s storeId:%{public}s tokenId:0x%{public}x", appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), metaData.tokenId); bool isCreate = false; @@ -568,8 +576,8 @@ Status KVDBServiceImpl::Subscribe(const AppId &appId, const StoreId &storeId, in return true; }); if (isCreate) { - AutoCache::GetInstance().SetObserver(metaData.tokenId, storeId, - GetWatchers(metaData.tokenId, storeId, metaData.user), metaData.user); + AutoCache::GetInstance().SetObserver(metaData.tokenId, + GetWatchers(metaData.tokenId, storeId, metaData.user), metaData.dataDir, storeId); } return SUCCESS; } @@ -577,7 +585,7 @@ Status KVDBServiceImpl::Subscribe(const AppId &appId, const StoreId &storeId, in Status KVDBServiceImpl::Unsubscribe(const AppId &appId, const StoreId &storeId, int32_t subUser, sptr observer) { - StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); + StoreMetaData metaData = LoadStoreMetaData(appId, storeId, subUser); ZLOGI("appId:%{public}s storeId:%{public}s tokenId:0x%{public}x", appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), metaData.tokenId); bool destroyed = false; @@ -600,40 +608,58 @@ Status KVDBServiceImpl::Unsubscribe(const AppId &appId, const StoreId &storeId, return true; }); if (destroyed) { - AutoCache::GetInstance().SetObserver(metaData.tokenId, storeId, - GetWatchers(metaData.tokenId, storeId, metaData.user), metaData.user); + AutoCache::GetInstance().SetObserver(metaData.tokenId, + GetWatchers(metaData.tokenId, storeId, metaData.user), metaData.dataDir, storeId); } return SUCCESS; } +std::vector KVDBServiceImpl::LoadSecretKey(const StoreMetaData &metaData, + CryptoManager::SecretKeyType secretKeyType) +{ + SecretKeyMetaData secretKey; + std::string metaKey; + if (secretKeyType == CryptoManager::SecretKeyType::LOCAL_SECRET_KEY) { + metaKey = metaData.GetSecretKey(); + } else if (secretKeyType == CryptoManager::SecretKeyType::CLONE_SECRET_KEY) { + metaKey = metaData.GetCloneSecretKey(); + } + if (!MetaDataManager::GetInstance().LoadMeta(metaKey, secretKey, true) || secretKey.sKey.empty()) { + return {}; + } + CryptoManager::CryptoParams decryptParams = { .area = secretKey.area, .userId = metaData.user, + .nonce = secretKey.nonce }; + auto password = CryptoManager::GetInstance().Decrypt(secretKey.sKey, decryptParams); + if (password.empty()) { + return {}; + } + // update secret key of area or nonce + CryptoManager::GetInstance().UpdateSecretMeta(password, metaData, metaKey, secretKey); + return password; +} + Status KVDBServiceImpl::GetBackupPassword(const AppId &appId, const StoreId &storeId, int32_t subUser, std::vector> &passwords, int32_t passwordType) { - StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); + StoreMetaData metaData = LoadStoreMetaData(appId, storeId, subUser); if (passwordType == KVDBService::PasswordType::BACKUP_SECRET_KEY) { - std::vector backupPwd; - bool res = BackupManager::GetInstance().GetPassWord(metaData, backupPwd); - if (res) { - passwords.emplace_back(backupPwd); + auto backupPwd = BackupManager::GetInstance().GetPassWord(metaData); + if (backupPwd.empty()) { + return ERROR; } + passwords.emplace_back(backupPwd); backupPwd.assign(backupPwd.size(), 0); - return res ? SUCCESS : ERROR; + return SUCCESS; } if (passwordType == KVDBService::PasswordType::SECRET_KEY) { passwords.reserve(SECRET_KEY_COUNT); - SecretKeyMetaData secretKey; - std::vector password; - if (MetaDataManager::GetInstance().LoadMeta(metaData.GetSecretKey(), secretKey, true) && - CryptoManager::GetInstance().Decrypt(metaData, secretKey, password)) { + auto password = LoadSecretKey(metaData, CryptoManager::SecretKeyType::LOCAL_SECRET_KEY); + if (!password.empty()) { passwords.emplace_back(password); - password.assign(password.size(), 0); } - - std::vector clonePwd; - if (MetaDataManager::GetInstance().LoadMeta(metaData.GetCloneSecretKey(), secretKey, true) && - CryptoManager::GetInstance().Decrypt(metaData, secretKey, clonePwd, CryptoManager::CLONE_SECRET_KEY)) { - passwords.emplace_back(clonePwd); - clonePwd.assign(clonePwd.size(), 0); + auto clonePassword = LoadSecretKey(metaData, CryptoManager::SecretKeyType::CLONE_SECRET_KEY); + if (!clonePassword.empty()) { + passwords.emplace_back(clonePassword); } return passwords.size() > 0 ? SUCCESS : ERROR; } @@ -645,6 +671,9 @@ Status KVDBServiceImpl::GetBackupPassword(const AppId &appId, const StoreId &sto Status KVDBServiceImpl::SetConfig(const AppId &appId, const StoreId &storeId, const StoreConfig &storeConfig) { StoreMetaData meta = GetStoreMetaData(appId, storeId); + StoreMetaMapping storeMetaMapping(meta); + MetaDataManager::GetInstance().LoadMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); + meta.dataDir = storeMetaMapping.dataDir; auto isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true); if (!isCreated) { return SUCCESS; @@ -654,15 +683,19 @@ Status KVDBServiceImpl::SetConfig(const AppId &appId, const StoreId &storeId, co if (!MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true)) { return Status::ERROR; } + storeMetaMapping = meta; + if (!MetaDataManager::GetInstance().SaveMeta(storeMetaMapping.GetKey(), storeMetaMapping, true)) { + return Status::ERROR; + } StoreMetaData syncMeta; - if (MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), syncMeta)) { + if (MetaDataManager::GetInstance().LoadMeta(meta.GetKeyWithoutPath(), syncMeta)) { syncMeta.enableCloud = storeConfig.cloudConfig.enableCloud; syncMeta.cloudAutoSync = storeConfig.cloudConfig.autoSync; - if (!MetaDataManager::GetInstance().SaveMeta(syncMeta.GetKey(), syncMeta)) { + if (!MetaDataManager::GetInstance().SaveMeta(syncMeta.GetKeyWithoutPath(), syncMeta)) { return Status::ERROR; } } - auto stores = AutoCache::GetInstance().GetStoresIfPresent(meta.tokenId, storeId, meta.user); + auto stores = AutoCache::GetInstance().GetStoresIfPresent(meta.tokenId, meta.dataDir, storeId); for (auto store : stores) { store->SetConfig({ storeConfig.cloudConfig.enableCloud }); } @@ -678,8 +711,8 @@ Status KVDBServiceImpl::BeforeCreate(const AppId &appId, const StoreId &storeId, StoreMetaData meta = GetStoreMetaData(appId, storeId, options.subUser); AddOptions(options, meta); - StoreMetaData old; - auto isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), old, true); + StoreMetaMapping old(meta); + auto isCreated = MetaDataManager::GetInstance().LoadMeta(old.GetKey(), old, true); if (!isCreated) { return SUCCESS; } @@ -717,6 +750,35 @@ Status KVDBServiceImpl::BeforeCreate(const AppId &appId, const StoreId &storeId, return dbStatus == DBStatus::OK ? SUCCESS : DB_ERROR; } +void KVDBServiceImpl::SaveSecretKeyMeta(const StoreMetaData &metaData, const std::vector &password) +{ + CryptoManager::CryptoParams encryptParams = { .area = metaData.area, .userId = metaData.user }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(password, encryptParams); + if (!encryptKey.empty() && !encryptParams.nonce.empty()) { + SecretKeyMetaData secretKey; + secretKey.storeType = metaData.storeType; + secretKey.area = metaData.area; + secretKey.sKey = encryptKey; + secretKey.nonce = encryptParams.nonce; + auto time = system_clock::to_time_t(system_clock::now()); + secretKey.time = { reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time) }; + MetaDataManager::GetInstance().SaveMeta(metaData.GetSecretKey(), secretKey, true); + } + SecretKeyMetaData cloneKey; + auto metaKey = metaData.GetCloneSecretKey(); + // update clone secret key with area + if (MetaDataManager::GetInstance().LoadMeta(metaKey, cloneKey, true) && !cloneKey.sKey.empty() && + (cloneKey.nonce.empty() || cloneKey.area < 0)) { + CryptoManager::CryptoParams decryptParams = { .area = cloneKey.area, .userId = metaData.user, + .nonce = cloneKey.nonce }; + auto clonePassword = CryptoManager::GetInstance().Decrypt(cloneKey.sKey, decryptParams); + if (!clonePassword.empty()) { + CryptoManager::GetInstance().UpdateSecretMeta(clonePassword, metaData, metaKey, cloneKey); + } + clonePassword.assign(clonePassword.size(), 0); + } +} + Status KVDBServiceImpl::AfterCreate( const AppId &appId, const StoreId &storeId, const Options &options, const std::vector &password) { @@ -729,15 +791,16 @@ Status KVDBServiceImpl::AfterCreate( StoreMetaData metaData = GetStoreMetaData(appId, storeId, options.subUser); AddOptions(options, metaData); - StoreMetaData oldMeta; - auto isCreated = MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), oldMeta, true); + StoreMetaMapping oldMeta(metaData); + auto isCreated = MetaDataManager::GetInstance().LoadMeta(oldMeta.GetKey(), oldMeta, true); Status status = SUCCESS; if (isCreated && oldMeta != metaData) { auto dbStatus = Upgrade::GetInstance().UpdateStore(oldMeta, metaData, password); ZLOGI("update status:%{public}d appId:%{public}s storeId:%{public}s inst:%{public}d " "type:%{public}d->%{public}d dir:%{public}s dataType:%{public}d->%{public}d", dbStatus, appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), metaData.instanceId, - oldMeta.storeType, metaData.storeType, metaData.dataDir.c_str(), oldMeta.dataType, metaData.dataType); + oldMeta.storeType, metaData.storeType, Anonymous::Change(metaData.dataDir).c_str(), + oldMeta.dataType, metaData.dataType); if (dbStatus != DBStatus::OK) { status = STORE_UPGRADE_FAILED; } @@ -745,28 +808,25 @@ Status KVDBServiceImpl::AfterCreate( if (!isCreated || oldMeta != metaData) { if (!CheckerManager::GetInstance().IsDistrust(Converter::ConvertToStoreInfo(metaData))) { - MetaDataManager::GetInstance().SaveMeta(metaData.GetKey(), metaData); + MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData); } MetaDataManager::GetInstance().SaveMeta(metaData.GetKey(), metaData, true); + oldMeta = metaData; + MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKey(), oldMeta, true); } AppIDMetaData appIdMeta; appIdMeta.bundleName = metaData.bundleName; appIdMeta.appId = metaData.appId; MetaDataManager::GetInstance().SaveMeta(appIdMeta.GetKey(), appIdMeta, true); SaveLocalMetaData(options, metaData); - if (metaData.isEncrypt && CryptoManager::GetInstance().UpdateSecretKey(metaData, password)) { - SecretKeyMetaData secretKey; - if (MetaDataManager::GetInstance().LoadMeta(metaData.GetCloneSecretKey(), secretKey, true) && - secretKey.area < 0) { - std::vector clonePwd; - // Update the encryption method for the key - CryptoManager::GetInstance().Decrypt(metaData, secretKey, clonePwd, CryptoManager::CLONE_SECRET_KEY); - clonePwd.assign(clonePwd.size(), 0); - } + + if (metaData.isEncrypt && !password.empty()) { + SaveSecretKeyMeta(metaData, password); } ZLOGI("appId:%{public}s storeId:%{public}s instanceId:%{public}d type:%{public}d dir:%{public}s " "isCreated:%{public}d dataType:%{public}d", appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), - metaData.instanceId, metaData.storeType, metaData.dataDir.c_str(), isCreated, metaData.dataType); + metaData.instanceId, metaData.storeType, Anonymous::Change(metaData.dataDir).c_str(), isCreated, + metaData.dataType); return status; } @@ -801,10 +861,9 @@ bool KVDBServiceImpl::CompareTripleIdentifier(const std::string &accountId, cons { std::vector accountIds { accountId, "ohosAnonymousUid", "default" }; for (auto &id : accountIds) { - auto convertedIds = - AppIdMappingConfigManager::GetInstance().Convert(storeMeta.appId, storeMeta.user); + auto appId = AppIdMappingConfigManager::GetInstance().Convert(storeMeta.appId); const std::string &tempTripleIdentifier = - DistributedDB::KvStoreDelegateManager::GetKvStoreIdentifier(id, convertedIds.first, + DistributedDB::KvStoreDelegateManager::GetKvStoreIdentifier(id, appId, storeMeta.storeId, false); if (tempTripleIdentifier == identifier) { ZLOGI("find triple identifier,storeId:%{public}s,id:%{public}s", @@ -917,6 +976,14 @@ void KVDBServiceImpl::SaveLocalMetaData(const Options &options, const StoreMetaD MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyLocal(), localMetaData, true); } +StoreMetaData KVDBServiceImpl::LoadStoreMetaData(const AppId &appId, const StoreId &storeId, int32_t subUser) +{ + StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); + StoreMetaMapping storeMetaMapping(metaData); + MetaDataManager::GetInstance().LoadMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); + return storeMetaMapping; +} + StoreMetaData KVDBServiceImpl::GetStoreMetaData(const AppId &appId, const StoreId &storeId, int32_t subUser) { StoreMetaData metaData; @@ -979,7 +1046,8 @@ Status KVDBServiceImpl::DoCloudSync(const StoreMetaData &meta, const SyncInfo &s if (instance == nullptr) { return Status::CLOUD_DISABLED; } - if (!NetworkDelegate::GetInstance()->IsNetworkAvailable()) { + auto network = NetworkDelegate::GetInstance(); + if (network == nullptr || !network->IsNetworkAvailable()) { return Status::NETWORK_ERROR; } std::vector users; @@ -1003,6 +1071,7 @@ Status KVDBServiceImpl::DoCloudSync(const StoreMetaData &meta, const SyncInfo &s storeInfo.user = atoi(meta.user.c_str()); storeInfo.tokenId = meta.tokenId; storeInfo.storeName = meta.storeId; + storeInfo.path = meta.dataDir; GenAsync syncCallback = [tokenId = storeInfo.tokenId, seqId = syncInfo.seqId, this](const GenDetails &details) { OnAsyncComplete(tokenId, seqId, HandleGenDetails(details)); }; @@ -1058,7 +1127,7 @@ Status KVDBServiceImpl::DoSyncInOrder( auto status = DoSyncBegin(ret.first, meta, info, complete, type); ZLOGD("data sync status:%{public}d appId:%{public}s, storeId:%{public}s", static_cast(status), meta.bundleName.c_str(), Anonymous::Change(meta.storeId).c_str()); - }); + }, false, info.isRetry); if (!result) { RADAR_REPORT(STANDARD_DEVICE_SYNC, STANDARD_META_SYNC, RADAR_FAILED, ERROR_CODE, Status::ERROR, BIZ_STATE, END, SYNC_STORE_ID, Anonymous::Change(meta.storeId), SYNC_APP_ID, meta.bundleName, @@ -1081,7 +1150,7 @@ bool KVDBServiceImpl::IsNeedMetaSync(const StoreMetaData &meta, const std::vecto 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)) { + !MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)) { isAfterMeta = true; break; } @@ -1106,7 +1175,7 @@ StoreMetaData KVDBServiceImpl::GetDistributedDataMeta(const std::string &deviceI meta.bundleName = Bootstrap::GetInstance().GetProcessLabel(); meta.storeId = Bootstrap::GetInstance().GetMetaDBName(); meta.user = DEFAULT_USER_ID; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) { + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyWithoutPath(), meta)) { ZLOGE("Load meta fail, device: %{public}s", Anonymous::Change(deviceId).c_str()); } return meta; @@ -1141,7 +1210,7 @@ Status KVDBServiceImpl::DoSyncBegin(const std::vector &devices, con if (store == nullptr) { ZLOGE("GetStore failed! appId:%{public}s storeId:%{public}s storeId length:%{public}zu dir:%{public}s", meta.bundleName.c_str(), Anonymous::Change(meta.storeId).c_str(), - meta.storeId.size(), meta.dataDir.c_str()); + meta.storeId.size(), Anonymous::Change(meta.dataDir).c_str()); RADAR_REPORT(STANDARD_DEVICE_SYNC, OPEN_STORE, RADAR_FAILED, ERROR_CODE, Status::ERROR, BIZ_STATE, END, SYNC_STORE_ID, Anonymous::Change(meta.storeId), SYNC_APP_ID, meta.bundleName, CONCURRENT_ID, std::to_string(info.syncId), DATA_TYPE, meta.dataType); @@ -1160,15 +1229,14 @@ Status KVDBServiceImpl::DoSyncBegin(const std::vector &devices, con } SyncParam syncParam{}; syncParam.mode = mode; + syncParam.isRetry = info.isRetry; RADAR_REPORT(STANDARD_DEVICE_SYNC, START_SYNC, RADAR_START, SYNC_STORE_ID, Anonymous::Change(meta.storeId), SYNC_APP_ID, meta.bundleName, CONCURRENT_ID, std::to_string(info.syncId), DATA_TYPE, meta.dataType); - auto ret = store->Sync( - devices, query, + auto ret = store->Sync(devices, query, [this, complete](const GenDetails &result) mutable { auto deviceStatus = HandleGenBriefDetails(result); complete(deviceStatus); - }, - syncParam); + }, syncParam); auto status = Status(ret.first); if (status != Status::SUCCESS) { RADAR_REPORT(STANDARD_DEVICE_SYNC, START_SYNC, RADAR_FAILED, ERROR_CODE, status, BIZ_STATE, END, @@ -1488,12 +1556,12 @@ Status KVDBServiceImpl::RemoveDeviceData(const AppId &appId, const StoreId &stor const std::string &device) { StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); - MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData); + MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData); auto watcher = GetWatchers(metaData.tokenId, metaData.storeId, metaData.user); 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()); + Anonymous::Change(metaData.storeId).c_str(), Anonymous::Change(metaData.dataDir).c_str()); return Status::ERROR; } 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 4604f8b56eac50623014bd56fe84f06167797057..dd185700db36228cfe8a58253e5a1babcd88b06d 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h @@ -19,6 +19,7 @@ #include #include "concurrent_map.h" +#include "crypto/crypto_manager.h" #include "device_matrix.h" #include "kv_store_delegate_manager.h" #include "kv_store_nb_delegate.h" @@ -95,6 +96,7 @@ private: using DBMode = DistributedDB::SyncMode; using Action = OHOS::DistributedData::MetaDataManager::Action; using GeneralError = DistributedData::GeneralError; + using CryptoManager = DistributedData::CryptoManager; enum SyncAction { ACTION_SYNC, ACTION_SUBSCRIBE, @@ -123,6 +125,7 @@ private: void Init(); void AddOptions(const Options &options, StoreMetaData &metaData); StoreMetaData GetStoreMetaData(const AppId &appId, const StoreId &storeId, int32_t subUser = 0); + StoreMetaData LoadStoreMetaData(const AppId &appId, const StoreId &storeId, int32_t subUser = 0); StoreMetaData GetDistributedDataMeta(const std::string &deviceId); StrategyMeta GetStrategyMeta(const AppId &appId, const StoreId &storeId, int32_t subUser = 0); int32_t GetInstIndex(uint32_t tokenId, const AppId &appId); @@ -161,6 +164,8 @@ private: bool CompareTripleIdentifier(const std::string &accountId, const std::string &identifier, const StoreMetaData &storeMeta); std::string GenerateKey(const std::string &userId, const std::string &storeId) const; + std::vector LoadSecretKey(const StoreMetaData &metaData, CryptoManager::SecretKeyType secretKeyType); + void SaveSecretKeyMeta(const StoreMetaData &metaData, const std::vector &password); static Factory factory_; ConcurrentMap syncAgents_; std::shared_ptr executors_; 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 37de89063cb67c628b7921dd146a531a5b2df219..acfa5fbdb03ae7970492bd34f73aabe8c7371b8e 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp @@ -22,6 +22,10 @@ #include "utils/constant.h" namespace OHOS::DistributedKv { using namespace OHOS::DistributedData; +static constexpr const char *SLASH = "/"; +static constexpr const char *BACK_SLASH = "\\"; +static constexpr const char *POINT = ".."; + const KVDBServiceStub::Handler KVDBServiceStub::HANDLERS[static_cast(KVDBServiceInterfaceCode::TRANS_BUTT)] = { &KVDBServiceStub::OnGetStoreIds, @@ -141,6 +145,9 @@ int32_t KVDBServiceStub::OnBeforeCreate( Anonymous::Change(storeId.storeId).c_str()); return IPC_STUB_INVALID_DATA_ERR; } + if (!IsValidField(appId.appId) || !IsValidField(storeId.storeId) || !IsValidField(options.hapName)) { + return IPC_STUB_INVALID_DATA_ERR; + } int32_t status = BeforeCreate(appId, storeId, options); if (!ITypesUtil::Marshal(reply, status)) { ZLOGE("Marshal status:0x%{public}x appId:%{public}s storeId:%{public}s", status, appId.appId.c_str(), @@ -160,6 +167,9 @@ int32_t KVDBServiceStub::OnAfterCreate( Anonymous::Change(storeId.storeId).c_str()); return IPC_STUB_INVALID_DATA_ERR; } + if (!IsValidField(appId.appId) || !IsValidField(storeId.storeId) || !IsValidField(options.hapName)) { + return IPC_STUB_INVALID_DATA_ERR; + } int32_t status = AfterCreate(appId, storeId, options, password); password.assign(password.size(), 0); if (!ITypesUtil::Marshal(reply, status)) { @@ -209,7 +219,7 @@ int32_t KVDBServiceStub::OnSync(const AppId &appId, const StoreId &storeId, Mess SyncInfo syncInfo; int32_t subUser; if (!ITypesUtil::Unmarshal(data, syncInfo.seqId, syncInfo.mode, syncInfo.devices, syncInfo.delay, syncInfo.query, - subUser)) { + subUser, syncInfo.isRetry)) { ZLOGE("Unmarshal appId:%{public}s storeId:%{public}s", appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str()); return IPC_STUB_INVALID_DATA_ERR; @@ -579,4 +589,13 @@ int32_t KVDBServiceStub::OnRemoveDeviceData(const AppId &appId, const StoreId &s } return ERR_NONE; } + +bool KVDBServiceStub::IsValidField(const std::string ¶m) +{ + if ((param.find(SLASH) != std::string::npos) || (param.find(BACK_SLASH) != std::string::npos) || (param == POINT)) { + ZLOGE("check failed, param is: %{public}s", Anonymous::Change(param).c_str()); + return false; + } + return true; +} } // 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 f26cb7c8325dfb1d5348c1f426379d8c340e7708..ab87da37dc09a8a58d2214a52fd2273510f23295 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h @@ -62,6 +62,7 @@ private: bool CheckPermission(uint32_t code, const StoreInfo &storeInfo); std::pair GetStoreInfo(uint32_t code, MessageParcel &data); + bool IsValidField(const std::string ¶m); }; } // namespace OHOS::DistributedKv #endif // OHOS_DISTRIBUTED_DATA_SERVICE_KVDB_SERVICE_STUB_H diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/query_helper.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/query_helper.cpp index f877df1f2a845ce36cc2878b0c2fbf21560d6ab4..c1bd2d6c0b554e168526edc179a9f84567b0c237 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/query_helper.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/query_helper.cpp @@ -21,6 +21,7 @@ #include "kvstore_utils.h" #include "log_print.h" #include "types.h" +#include "utils/anonymous.h" namespace OHOS::DistributedKv { constexpr int QUERY_SKIP_SIZE = 1; constexpr int QUERY_WORD_SIZE = 2; @@ -559,7 +560,7 @@ bool QueryHelper::HandleInKeys(const std::vector &words, int &point const std::vector inKeys = GetStringList(words, inkeyOffSet, end); std::set> inDbKeys; for (const std::string &inKey : inKeys) { - ZLOGI("inKey=%{public}s", inKey.c_str()); + ZLOGI("inKey=%{public}s", DistributedData::Anonymous::Change(inKey).c_str()); std::vector dbKey; dbKey.assign(inKey.begin(), inKey.end()); inDbKeys.insert(dbKey); diff --git a/datamgr_service/services/distributeddataservice/service/matrix/BUILD.gn b/datamgr_service/services/distributeddataservice/service/matrix/BUILD.gn index 3499cbe6c148cba7fc4e8ce0135d9e947fc946de..88c1d03a41e94bcd94836789c6d08e5be4b891a2 100644 --- a/datamgr_service/services/distributeddataservice/service/matrix/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/matrix/BUILD.gn @@ -35,7 +35,6 @@ ohos_source_set("distributeddata_matrix") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ @@ -50,7 +49,6 @@ ohos_source_set("distributeddata_matrix") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ @@ -61,6 +59,7 @@ ohos_source_set("distributeddata_matrix") { "device_manager:devicemanagersdk", "hilog:libhilog", "json:nlohmann_json_static", + "c_utils:utils", "kv_store:datamgr_common", ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/service/object/BUILD.gn b/datamgr_service/services/distributeddataservice/service/object/BUILD.gn index 29056fe07bb32af5805190b0fc8ad429f53572cd..b5bba90befa02cfc57ac579e272d1f9ac8a0f8e0 100644 --- a/datamgr_service/services/distributeddataservice/service/object/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/object/BUILD.gn @@ -18,6 +18,7 @@ config("object_public_config") { include_dirs = [ "${data_service_path}/service/common", + "${data_service_path}/service/matrix/include", "${data_service_path}/adapter/include/communicator", "${data_service_path}/adapter/include/utils", ] @@ -49,7 +50,6 @@ ohos_source_set("distributeddata_object") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ "include" ] @@ -62,7 +62,6 @@ ohos_source_set("distributeddata_object") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ @@ -77,6 +76,8 @@ ohos_source_set("distributeddata_object") { "dfs_service:cloudsync_asset_kit_inner", "dfs_service:distributed_file_daemon_kit_inner", "dmsfwk:distributed_sdk", + "hilog:libhilog", + "ipc:ipc_single", "hisysevent:libhisysevent", "kv_store:datamgr_common", "kv_store:distributeddb", diff --git a/datamgr_service/services/distributeddataservice/service/object/include/object_asset_loader.h b/datamgr_service/services/distributeddataservice/service/object/include/object_asset_loader.h index 44d3f8ab0f8d155c60d0697234b2d525408906eb..160539fafb77d9cbdf4aa21ddc7c6c2470b82d14 100644 --- a/datamgr_service/services/distributeddataservice/service/object/include/object_asset_loader.h +++ b/datamgr_service/services/distributeddataservice/service/object/include/object_asset_loader.h @@ -41,7 +41,7 @@ public: class ObjectAssetLoader { public: - static ObjectAssetLoader *GetInstance(); + static ObjectAssetLoader &GetInstance(); void SetThreadPool(std::shared_ptr executors); bool Transfer(const int32_t userId, const std::string& bundleName, const std::string& deviceId, const DistributedData::Asset& asset); diff --git a/datamgr_service/services/distributeddataservice/service/object/include/object_asset_machine.h b/datamgr_service/services/distributeddataservice/service/object/include/object_asset_machine.h index 14283191bd486b62b1e6e8db591ec5c5c2e23428..273c781eedadb0fedbbe600b82ca710ddbeec268 100644 --- a/datamgr_service/services/distributeddataservice/service/object/include/object_asset_machine.h +++ b/datamgr_service/services/distributeddataservice/service/object/include/object_asset_machine.h @@ -50,12 +50,8 @@ struct DFAAction { class ObjectAssetMachine { public: - ObjectAssetMachine(); - static int32_t DFAPostEvent(AssetEvent eventId, ChangedAssetInfo& changedAsset, Asset& asset, const std::pair& newAsset = std::pair()); - -private: }; } // namespace DistributedObject } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/object/include/object_callback_proxy.h b/datamgr_service/services/distributeddataservice/service/object/include/object_callback_proxy.h index e29908493e5d2e0fe57a3f33710ed8a158e64ef4..fabd1494186af829b9f377b09fe6fa4c10e7e358 100644 --- a/datamgr_service/services/distributeddataservice/service/object/include/object_callback_proxy.h +++ b/datamgr_service/services/distributeddataservice/service/object/include/object_callback_proxy.h @@ -80,6 +80,20 @@ public: private: static inline BrokerDelegator delegator_; }; + +class ObjectProgressCallbackProxyBroker : public IObjectProgressCallback, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedObject.IObjectProgressCallback"); +}; + +class ObjectProgressCallbackProxy : public IRemoteProxy { +public: + explicit ObjectProgressCallbackProxy(const sptr &impl); + ~ObjectProgressCallbackProxy() = default; + void Completed(int32_t progress) override; +private: + static inline BrokerDelegator delegator_; +}; } // namespace DistributedObject } // namespace OHOS #endif // DISTRIBUTEDDATAMGR_OBJECT_CALLBACK_PROXY_H diff --git a/datamgr_service/services/distributeddataservice/service/object/include/object_data_listener.h b/datamgr_service/services/distributeddataservice/service/object/include/object_data_listener.h index 3c1bfdea0dee7cf4dfb4303b42b3b5f2684d64a6..7c3140c7b0f33f3e8c307a09416d3146b8ebdd45 100644 --- a/datamgr_service/services/distributeddataservice/service/object/include/object_data_listener.h +++ b/datamgr_service/services/distributeddataservice/service/object/include/object_data_listener.h @@ -38,6 +38,9 @@ public: const std::string &dstBundleName) override; int32_t OnFinished(const std::string &srcNetworkId, const sptr &assetObj, int32_t result) override; + int32_t OnRecvProgress(const std::string &srcNetworkId, + const sptr &assetObj, + uint64_t totalBytes, uint64_t processBytes) override; }; } // namespace DistributedObject } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/object/include/object_manager.h b/datamgr_service/services/distributeddataservice/service/object/include/object_manager.h index 2f4f6302c177cd23197b245ffd2e8a056d3cfdc5..85dd81349dd67e928395a2e6977a696f35543d45 100644 --- a/datamgr_service/services/distributeddataservice/service/object/include/object_manager.h +++ b/datamgr_service/services/distributeddataservice/service/object/include/object_manager.h @@ -21,6 +21,7 @@ #include "device_manager_adapter.h" #include "kv_store_delegate_manager.h" #include "kvstore_sync_callback.h" +#include "metadata/store_meta_data.h" #include "object_asset_loader.h" #include "object_callback.h" #include "object_callback_proxy.h" @@ -64,6 +65,7 @@ class ObjectStoreManager { public: using DmAdaper = OHOS::DistributedData::DeviceManagerAdapter; using UriToSnapshot = std::shared_ptr>>; + using StoreMetaData = OHOS::DistributedData::StoreMetaData; enum RestoreStatus : int32_t { NONE = 0, @@ -76,9 +78,9 @@ public: ObjectStoreManager(); ~ObjectStoreManager(); - static ObjectStoreManager *GetInstance() + static ObjectStoreManager &GetInstance() { - static ObjectStoreManager *manager = new ObjectStoreManager(); + static ObjectStoreManager manager; return manager; } int32_t Save(const std::string &appId, const std::string &sessionId, const ObjectRecord &data, @@ -89,18 +91,21 @@ public: sptr callback, uint32_t tokenId); void SetData(const std::string &dataDir, const std::string &userId); int32_t Clear(); + int32_t InitUserMeta(); int32_t DeleteByAppId(const std::string &appId, int32_t user); void RegisterRemoteCallback(const std::string &bundleName, const std::string &sessionId, - pid_t pid, uint32_t tokenId, - sptr callback); + pid_t pid, uint32_t tokenId, sptr callback); void UnregisterRemoteCallback(const std::string &bundleName, pid_t pid, uint32_t tokenId, - const std::string &sessionId = ""); - void NotifyChange(ObjectRecord &changedData); + const std::string &sessionId = ""); + void RegisterProgressObserverCallback(const std::string &bundleName, const std::string &sessionId, + pid_t pid, uint32_t tokenId, sptr callback); + void UnregisterProgressObserverCallback(const std::string &bundleName, pid_t pid, uint32_t tokenId, + const std::string &sessionId = ""); + void NotifyChange(const ObjectRecord &changedData); 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(); + void NotifyAssetsRecvProgress(const std::string& objectKey, int32_t progress); void SetThreadPool(std::shared_ptr executors); UriToSnapshot GetSnapShots(const std::string &bundleName, const std::string &storeName); int32_t BindAsset(const uint32_t tokenId, const std::string& appId, const std::string& sessionId, @@ -108,6 +113,8 @@ public: int32_t OnAssetChanged(const uint32_t tokenId, const std::string& appId, const std::string& sessionId, const std::string& deviceId, const ObjectStore::Asset& asset); void DeleteSnapshot(const std::string &bundleName, const std::string &sessionId); + int32_t AutoLaunchStore(); + bool UnRegisterAssetsLister(); private: constexpr static const char *SEPERATOR = "_"; constexpr static const char *TIME_REGEX = "_\\d{10}_p_"; @@ -128,10 +135,15 @@ private: std::map> observers_; bool operator<(const CallbackInfo &it_) const { - if (pid < it_.pid) { - return true; - } - return false; + return pid < it_.pid; + } + }; + struct ProgressCallbackInfo { + pid_t pid; + std::map> observers_; + bool operator<(const ProgressCallbackInfo &it_) const + { + return pid < it_.pid; } }; struct SaveInfo : DistributedData::Serializable { @@ -150,6 +162,7 @@ private: DistributedDB::KvStoreNbDelegate *OpenObjectKvStore(); void FlushClosedStore(); void Close(); + void ForceClose(); int32_t SetSyncStatus(bool status); int32_t SaveToStore(const std::string &appId, const std::string &sessionId, const std::string &toDeviceId, const ObjectRecord &data); @@ -162,6 +175,8 @@ private: void ProcessSyncCallback(const std::map &results, const std::string &appId, const std::string &sessionId, const std::string &deviceId); void SaveUserToMeta(); + bool IsNeedMetaSync(const StoreMetaData &meta, const std::vector &networkIds); + int32_t DoSync(const std::string &prefix, const std::vector &deviceList, uint64_t sequenceId); std::string GetCurrentUser(); void DoNotify(uint32_t tokenId, const CallbackInfo& value, const std::map& data, bool allReady); @@ -182,6 +197,8 @@ private: void PullAssets(const std::map& data, const SaveInfo& saveInfo); std::map GetObjectData(const ObjectRecord& changedData, SaveInfo& saveInfo, bool& hasAsset); + void CloseAfterMinute(); + int32_t Open(); inline std::string GetPropertyPrefix(const std::string &appId, const std::string &sessionId) { return appId + SEPERATOR + sessionId + SEPERATOR + DmAdaper::GetInstance().GetLocalDevice().udid + SEPERATOR; @@ -201,24 +218,26 @@ private: return std::string(USERID) + SEPERATOR + userId + SEPERATOR + appId + SEPERATOR + DmAdaper::GetInstance().GetLocalDevice().udid; }; - std::recursive_mutex kvStoreMutex_; - std::mutex mutex_; - DistributedDB::KvStoreDelegateManager *kvStoreDelegateManager_ = nullptr; + mutable std::shared_timed_mutex rwMutex_; + std::shared_ptr kvStoreDelegateManager_ = nullptr; DistributedDB::KvStoreNbDelegate *delegate_ = nullptr; - ObjectDataListener *objectDataListener_ = nullptr; + ObjectDataListener objectDataListener_; sptr objectAssetsRecvListener_ = nullptr; sptr objectAssetsSendListener_ = nullptr; - uint32_t syncCount_ = 0; + std::atomic syncCount_{ 0 }; std::string userId_; - std::atomic isSyncing_ = false; + std::atomic isSyncing_{ false }; ConcurrentMap callbacks_; + ConcurrentMap processCallbacks_; std::shared_ptr executors_; DistributedData::AssetBindInfo ConvertBindInfo(ObjectStore::AssetBindInfo& bindInfo); - VBucket ConvertVBucket(ObjectStore::ValuesBucket &vBucket); ConcurrentMap> snapshots_; // key:bundleName_sessionId ConcurrentMap bindSnapshots_; // key:bundleName_storeName ConcurrentMap restoreStatus_; // key:bundleName+sessionId ConcurrentMap objectTimer_; // key:bundleName+sessionId + ConcurrentMap assetsRecvProgress_; // key:bundleName+sessionId + std::map progressInfo_; + std::mutex progressMutex_; }; } // namespace DistributedObject } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/object/include/object_service_impl.h b/datamgr_service/services/distributeddataservice/service/object/include/object_service_impl.h index 437d49e9e47f5cda46271b5cf91686ea797edfb9..98f0fcd616966ccde0ad575a327a4d0fbf01c540 100644 --- a/datamgr_service/services/distributeddataservice/service/object/include/object_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/object/include/object_service_impl.h @@ -17,6 +17,7 @@ #define DISTRIBUTEDDATASERVICE_OBJECT_SERVICE_H #include "feature/static_acts.h" +#include "metadata/store_meta_data.h" #include "object_manager.h" #include "object_service_stub.h" #include "visibility.h" @@ -37,10 +38,12 @@ public: int32_t RegisterDataObserver(const std::string &bundleName, const std::string &sessionId, sptr callback) override; int32_t UnregisterDataChangeObserver(const std::string &bundleName, const std::string &sessionId) override; + int32_t RegisterProgressObserver(const std::string &bundleName, const std::string &sessionId, + sptr callback) override; + int32_t UnregisterProgressObserver(const std::string &bundleName, const std::string &sessionId) override; int32_t DeleteSnapshot(const std::string &bundleName, const std::string &sessionId) override; int32_t IsBundleNameEqualTokenId( const std::string &bundleName, const std::string &sessionId, const uint32_t &tokenId); - void Clear(); int32_t ResolveAutoLaunch(const std::string &identifier, DistributedDB::AutoLaunchParam ¶m) override; int32_t OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &appId) override; int32_t OnInitialize() override; @@ -68,8 +71,12 @@ private: }; void RegisterObjectServiceInfo(); void RegisterHandler(); + int32_t SaveMetaData(StoreMetaData& saveMeta); + void UpdateMetaData(); + static Factory factory_; std::shared_ptr executors_; + static constexpr int64_t WAIT_ACCOUNT_SERVICE = 5; }; } // namespace OHOS::DistributedObject #endif diff --git a/datamgr_service/services/distributeddataservice/service/object/include/object_service_stub.h b/datamgr_service/services/distributeddataservice/service/object/include/object_service_stub.h index fef5c7ecaac6985175b2a45baf113ea1eaf075c4..e254a2bd1584eff386c236388ad3c9173f4e22a8 100644 --- a/datamgr_service/services/distributeddataservice/service/object/include/object_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/object/include/object_service_stub.h @@ -37,6 +37,8 @@ private: int32_t ObjectStoreBindAssetOnRemote(MessageParcel &data, MessageParcel &reply); int32_t OnDeleteSnapshot(MessageParcel &data, MessageParcel &reply); int32_t OnIsContinue(MessageParcel &data, MessageParcel &reply); + int32_t OnSubscribeProgress(MessageParcel &data, MessageParcel &reply); + int32_t OnUnsubscribeProgress(MessageParcel &data, MessageParcel &reply); using RequestHandle = int (ObjectServiceStub::*)(MessageParcel &, MessageParcel &); static constexpr RequestHandle HANDLERS[static_cast(ObjectCode::OBJECTSTORE_SERVICE_CMD_MAX)] = { &ObjectServiceStub::ObjectStoreSaveOnRemote, @@ -48,6 +50,8 @@ private: &ObjectServiceStub::ObjectStoreBindAssetOnRemote, &ObjectServiceStub::OnDeleteSnapshot, &ObjectServiceStub::OnIsContinue, + &ObjectServiceStub::OnSubscribeProgress, + &ObjectServiceStub::OnUnsubscribeProgress, }; }; } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/object/src/object_asset_loader.cpp b/datamgr_service/services/distributeddataservice/service/object/src/object_asset_loader.cpp index c3d582e6aef6ae46beef39d1bc06ae2c34d3794c..efabc95ba69400754d3fd6ab6e30816568d720d8 100644 --- a/datamgr_service/services/distributeddataservice/service/object/src/object_asset_loader.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/src/object_asset_loader.cpp @@ -24,9 +24,10 @@ #include "distributed_file_daemon_manager.h" namespace OHOS::DistributedObject { using namespace OHOS::FileManagement::CloudSync; -ObjectAssetLoader *ObjectAssetLoader::GetInstance() +using namespace OHOS::DistributedData; +ObjectAssetLoader &ObjectAssetLoader::GetInstance() { - static ObjectAssetLoader *loader = new ObjectAssetLoader(); + static ObjectAssetLoader loader; return loader; } @@ -42,7 +43,7 @@ bool ObjectAssetLoader::Transfer(const int32_t userId, const std::string& bundle assetInfo.uri = asset.uri; assetInfo.assetName = asset.name; ZLOGI("Start transfer, bundleName: %{public}s, deviceId: %{public}s, assetName: %{public}s", bundleName.c_str(), - DistributedData::Anonymous::Change(deviceId).c_str(), assetInfo.assetName.c_str()); + Anonymous::Change(deviceId).c_str(), Anonymous::Change(assetInfo.assetName).c_str()); auto block = std::make_shared>>(WAIT_TIME, std::tuple{ true, OBJECT_SUCCESS }); auto res = CloudSyncAssetManager::GetInstance().DownloadFile(userId, bundleName, deviceId, assetInfo, [block](const std::string& uri, int32_t status) { @@ -50,17 +51,17 @@ bool ObjectAssetLoader::Transfer(const int32_t userId, const std::string& bundle }); if (res != OBJECT_SUCCESS) { ZLOGE("fail, res: %{public}d, name: %{public}s, deviceId: %{public}s, bundleName: %{public}s", res, - asset.name.c_str(), DistributedData::Anonymous::Change(deviceId).c_str(), bundleName.c_str()); + Anonymous::Change(asset.name).c_str(), Anonymous::Change(deviceId).c_str(), bundleName.c_str()); return false; } auto [timeout, status] = block->GetValue(); if (timeout || status != OBJECT_SUCCESS) { ZLOGE("fail, timeout: %{public}d, status: %{public}d, name: %{public}s, deviceId: %{public}s ", timeout, - status, asset.name.c_str(), DistributedData::Anonymous::Change(deviceId).c_str()); + status, Anonymous::Change(asset.name).c_str(), Anonymous::Change(deviceId).c_str()); return false; } ZLOGD("Transfer end, bundleName: %{public}s, deviceId: %{public}s, assetName: %{public}s", bundleName.c_str(), - DistributedData::Anonymous::Change(deviceId).c_str(), assetInfo.assetName.c_str()); + Anonymous::Change(deviceId).c_str(), Anonymous::Change(assetInfo.assetName).c_str()); return true; } @@ -69,7 +70,7 @@ void ObjectAssetLoader::TransferAssetsAsync(const int32_t userId, const std::str { 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); + bundleName.c_str(), Anonymous::Change(deviceId).c_str(), userId); callback(false); return; } @@ -148,7 +149,7 @@ bool ObjectAssetLoader::IsDownloading(const DistributedData::Asset& asset) { auto [success, hash] = downloading_.Find(asset.uri); if (success && hash == asset.hash) { - ZLOGD("asset is downloading. assetName:%{public}s", asset.name.c_str()); + ZLOGD("asset is downloading. assetName:%{public}s", Anonymous::Change(asset.name).c_str()); return true; } return false; @@ -158,7 +159,7 @@ bool ObjectAssetLoader::IsDownloaded(const DistributedData::Asset& asset) { auto [success, hash] = downloaded_.Find(asset.uri); if (success && hash == asset.hash) { - ZLOGD("asset is downloaded. assetName:%{public}s", asset.name.c_str()); + ZLOGD("asset is downloaded. assetName:%{public}s", Anonymous::Change(asset.name).c_str()); return true; } return false; @@ -167,15 +168,21 @@ bool ObjectAssetLoader::IsDownloaded(const DistributedData::Asset& asset) int32_t ObjectAssetLoader::PushAsset(int32_t userId, const sptr &assetObj, const sptr &sendCallback) { + if (assetObj == nullptr) { + ZLOGE("PushAsset err, assetObj is null"); + return OBJECT_INNER_ERROR; + } 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()); + ZLOGI("PushAsset start, userId:%{public}d, asset size:%{public}zu, bundleName:%{public}s, sessionId:%{public}s", + userId, assetObj->uris_.size(), assetObj->dstBundleName_.c_str(), + Anonymous::Change(assetObj->sessionId_).c_str()); auto status = Storage::DistributedFile::DistributedFileDaemonManager::GetInstance().PushAsset(userId, assetObj, sendCallback); 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()); + status, assetObj->uris_.size(), assetObj->dstBundleName_.c_str(), + Anonymous::Change(assetObj->sessionId_).c_str()); ObjectStore::RadarReporter::ReportStateError(std::string(__FUNCTION__), ObjectStore::SAVE, ObjectStore::PUSH_ASSETS, ObjectStore::RADAR_FAILED, status, ObjectStore::FINISHED); } diff --git a/datamgr_service/services/distributeddataservice/service/object/src/object_asset_machine.cpp b/datamgr_service/services/distributeddataservice/service/object/src/object_asset_machine.cpp index dcb034ad95eaa4f57291a174169edf9d19d75fe7..690affe946ae6b98fe6e35e9f95d0e0ce027cabf 100644 --- a/datamgr_service/services/distributeddataservice/service/object/src/object_asset_machine.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/src/object_asset_machine.cpp @@ -57,12 +57,12 @@ static int32_t Recover(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& a static int32_t UpdateStore(ChangedAssetInfo& changedAsset); -static AutoCache::Store GetStore(ChangedAssetInfo& changedAsset); +static AutoCache::Store GetStore(const ChangedAssetInfo& changedAsset); static VBuckets GetMigratedData(AutoCache::Store& store, AssetBindInfo& assetBindInfo, const Asset& newAsset); static void MergeAssetData(VBucket& record, const Asset& newAsset, const AssetBindInfo& assetBindInfo); static void MergeAsset(Asset& oldAsset, const Asset& newAsset); static std::string BuildSql(const AssetBindInfo& bindInfo, Values& args); -static BindEvent::BindEventInfo MakeBindInfo(ChangedAssetInfo& changedAsset); +static BindEvent::BindEventInfo MakeBindInfo(const ChangedAssetInfo& changedAsset); static const DFAAction AssetDFA[STATUS_BUTT][EVENT_BUTT] = { { @@ -133,7 +133,8 @@ static const DFAAction AssetDFA[STATUS_BUTT][EVENT_BUTT] = { int32_t ObjectAssetMachine::DFAPostEvent(AssetEvent eventId, ChangedAssetInfo& changedAssetInfo, Asset& asset, const std::pair& newAsset) { - if (eventId < 0 || eventId >= EVENT_BUTT) { + if (eventId < 0 || eventId >= EVENT_BUTT || changedAssetInfo.status >= STATUS_BUTT) { + ZLOGE("invalid parameters, eventId: %{public}d, status:%{public}d", eventId, changedAssetInfo.status); return GeneralError::E_ERROR; } @@ -164,16 +165,16 @@ static int32_t DoTransfer(int32_t eventId, ChangedAssetInfo& changedAsset, Asset changedAsset.deviceId = newAsset.first; changedAsset.asset = newAsset.second; std::vector assets{ changedAsset.asset }; - ObjectAssetLoader::GetInstance()->TransferAssetsAsync(changedAsset.storeInfo.user, + ObjectAssetLoader::GetInstance().TransferAssetsAsync(changedAsset.storeInfo.user, changedAsset.storeInfo.bundleName, changedAsset.deviceId, assets, [&changedAsset](bool success) { if (success) { auto status = UpdateStore(changedAsset); if (status != E_OK) { ZLOGE("UpdateStore error, error:%{public}d, assetName:%{public}s, store:%{public}s, " "table:%{public}s", - status, changedAsset.asset.name.c_str(), + status, Anonymous::Change(changedAsset.asset.name).c_str(), Anonymous::Change(changedAsset.bindInfo.storeName).c_str(), - changedAsset.bindInfo.tableName.c_str()); + Anonymous::Change(changedAsset.bindInfo.tableName).c_str()); } } ObjectAssetMachine::DFAPostEvent(TRANSFER_FINISHED, changedAsset, changedAsset.asset); @@ -287,7 +288,7 @@ static void MergeAsset(Asset& oldAsset, const Asset& newAsset) oldAsset.path = newAsset.path; } -static AutoCache::Store GetStore(ChangedAssetInfo& changedAsset) +static AutoCache::Store GetStore(const ChangedAssetInfo& changedAsset) { StoreMetaData meta; meta.storeId = changedAsset.bindInfo.storeName; @@ -295,7 +296,7 @@ static AutoCache::Store GetStore(ChangedAssetInfo& changedAsset) meta.user = std::to_string(changedAsset.storeInfo.user); meta.instanceId = changedAsset.storeInfo.instanceId; meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) { + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyWithoutPath(), meta)) { ZLOGE("meta empty, bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); return nullptr; @@ -337,8 +338,8 @@ static int32_t ChangeAssetToNormal(int32_t eventId, ChangedAssetInfo& changedAss static int32_t Recover(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& asset, const std::pair& newAsset) { - ZLOGE("An abnormal event has occurred, eventId:%{public}d, status:%{public}d, assetName:%{public}s", eventId, - changedAsset.status, changedAsset.asset.name.c_str()); + ZLOGI("An abnormal event has occurred, eventId:%{public}d, status:%{public}d, assetName:%{public}s", eventId, + changedAsset.status, Anonymous::Change(changedAsset.asset.name).c_str()); BindEvent::BindEventInfo bindEventInfo = MakeBindInfo(changedAsset); changedAsset.status = TransferStatus::STATUS_STABLE; @@ -347,7 +348,7 @@ static int32_t Recover(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& a return E_OK; } -static BindEvent::BindEventInfo MakeBindInfo(ChangedAssetInfo& changedAsset) +static BindEvent::BindEventInfo MakeBindInfo(const ChangedAssetInfo& changedAsset) { BindEvent::BindEventInfo bindEventInfo; bindEventInfo.bundleName = changedAsset.storeInfo.bundleName; @@ -361,8 +362,5 @@ static BindEvent::BindEventInfo MakeBindInfo(ChangedAssetInfo& changedAsset) bindEventInfo.assetName = changedAsset.bindInfo.assetName; return bindEventInfo; } - -ObjectAssetMachine::ObjectAssetMachine() {} - } // namespace DistributedObject } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/object/src/object_callback_proxy.cpp b/datamgr_service/services/distributeddataservice/service/object/src/object_callback_proxy.cpp index 7e4c649a5cab95e7d7b400dfe3601688a38bf209..32fdda71506e171c72ef55766507d71a730d0d69 100644 --- a/datamgr_service/services/distributeddataservice/service/object/src/object_callback_proxy.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/src/object_callback_proxy.cpp @@ -42,6 +42,11 @@ ObjectChangeCallbackProxy::ObjectChangeCallbackProxy(const sptr & { } +ObjectProgressCallbackProxy::ObjectProgressCallbackProxy(const sptr &impl) + : IRemoteProxy(impl) +{ +} + void ObjectSaveCallbackProxy::Completed(const std::map &results) { MessageParcel data; @@ -57,7 +62,7 @@ void ObjectSaveCallbackProxy::Completed(const std::map &re MessageOption mo { MessageOption::TF_SYNC }; int error = Remote()->SendRequest(COMPLETED, data, reply, mo); if (error != 0) { - ZLOGW("SendRequest failed, error %d", error); + ZLOGW("SendRequest failed, error %{public}d", error); } } @@ -70,13 +75,13 @@ void ObjectRevokeSaveCallbackProxy::Completed(int32_t status) return; } if (!ITypesUtil::Marshal(data, status)) { - ZLOGE("write descriptor failed"); + ZLOGE("Marshalling failed, status:%{public}d", status); return; } MessageOption mo { MessageOption::TF_SYNC }; int error = Remote()->SendRequest(COMPLETED, data, reply, mo); if (error != 0) { - ZLOGW("SendRequest failed, error %d", error); + ZLOGW("SendRequest failed, error %{public}d", error); } } @@ -89,13 +94,13 @@ void ObjectRetrieveCallbackProxy::Completed(const std::mapSendRequest(COMPLETED, data, reply, mo); if (error != 0) { - ZLOGW("SendRequest failed, error %d", error); + ZLOGW("SendRequest failed, error %{public}d", error); } } @@ -108,13 +113,32 @@ void ObjectChangeCallbackProxy::Completed(const std::mapSendRequest(COMPLETED, data, reply, mo); if (error != 0) { - ZLOGW("SendRequest failed, error %d", error); + ZLOGW("SendRequest failed, error %{public}d", error); + } +} + +void ObjectProgressCallbackProxy::Completed(int32_t progress) +{ + MessageParcel data; + MessageParcel reply; + if (!data.WriteInterfaceToken(GetDescriptor())) { + ZLOGE("write descriptor failed"); + return; + } + if (!ITypesUtil::Marshal(data, progress)) { + ZLOGE("Marshal failed"); + return; + } + MessageOption mo { MessageOption::TF_ASYNC }; + int error = Remote()->SendRequest(COMPLETED, data, reply, mo); + if (error != 0) { + ZLOGW("SendRequest failed, error %{public}d", error); } } } // namespace DistributedObject diff --git a/datamgr_service/services/distributeddataservice/service/object/src/object_data_listener.cpp b/datamgr_service/services/distributeddataservice/service/object/src/object_data_listener.cpp index e7a7a5d0abcd44de8af8b2ac9b582c17ab887a3b..bdbdcb47fd5aa7022b7c8f53777e4580fc53fa26 100644 --- a/datamgr_service/services/distributeddataservice/service/object/src/object_data_listener.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/src/object_data_listener.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#include #define LOG_TAG "ObjectDataListener" #include "object_data_listener.h" @@ -22,6 +23,8 @@ #include "utils/anonymous.h" namespace OHOS { namespace DistributedObject { +constexpr int32_t PROGRESS_MAX = 100; +constexpr int32_t PROGRESS_INVALID = -1; ObjectDataListener::ObjectDataListener() { } @@ -43,15 +46,16 @@ void ObjectDataListener::OnChange(const DistributedDB::KvStoreChangedData &data) std::string key(entry.key.begin(), entry.key.end()); changedData.insert_or_assign(std::move(key), entry.value); } - DistributedObject::ObjectStoreManager::GetInstance()->NotifyChange(changedData); + DistributedObject::ObjectStoreManager::GetInstance().NotifyChange(changedData); } int32_t ObjectAssetsRecvListener::OnStart(const std::string &srcNetworkId, const std::string &dstNetworkId, const std::string &sessionId, const std::string &dstBundleName) { auto objectKey = dstBundleName + sessionId; - ZLOGI("OnStart, objectKey:%{public}s", objectKey.c_str()); - ObjectStoreManager::GetInstance()->NotifyAssetsStart(objectKey, srcNetworkId); + ZLOGI("OnStart, objectKey:%{public}s", DistributedData::Anonymous::Change(objectKey).c_str()); + ObjectStoreManager::GetInstance().NotifyAssetsStart(objectKey, srcNetworkId); + ObjectStoreManager::GetInstance().NotifyAssetsRecvProgress(objectKey, 0); return OBJECT_SUCCESS; } @@ -65,10 +69,35 @@ int32_t ObjectAssetsRecvListener::OnFinished(const std::string &srcNetworkId, co 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, assetObj->dstBundleName_, srcNetworkId); + auto objectKey = assetObj->dstBundleName_ + assetObj->sessionId_; + ZLOGI("OnFinished, status:%{public}d objectKey:%{public}s, asset size:%{public}zu", result, + DistributedData::Anonymous::Change(objectKey).c_str(), assetObj->uris_.size()); + ObjectStoreManager::GetInstance().NotifyAssetsReady(objectKey, assetObj->dstBundleName_, srcNetworkId); + if (result != OBJECT_SUCCESS) { + ObjectStoreManager::GetInstance().NotifyAssetsRecvProgress(objectKey, PROGRESS_INVALID); + } else { + ObjectStoreManager::GetInstance().NotifyAssetsRecvProgress(objectKey, PROGRESS_MAX); + } + return OBJECT_SUCCESS; +} + + +int32_t ObjectAssetsRecvListener::OnRecvProgress( + const std::string &srcNetworkId, const sptr &assetObj, uint64_t totalBytes, uint64_t processBytes) +{ + if (assetObj == nullptr || totalBytes == 0) { + ZLOGE("OnRecvProgress error! srcNetworkId:%{public}s, totalBytes: %{public}" PRIu64, + DistributedData::Anonymous::Change(srcNetworkId).c_str(), totalBytes); + return OBJECT_INNER_ERROR; + } + + auto objectKey = assetObj->dstBundleName_ + assetObj->sessionId_; + ZLOGI("srcNetworkId: %{public}s, objectKey:%{public}s, totalBytes: %{public}" PRIu64 + ", processBytes: %{public}" PRIu64 ".", + DistributedData::Anonymous::Change(srcNetworkId).c_str(), + DistributedData::Anonymous::Change(objectKey).c_str(), totalBytes, processBytes); + int32_t progress = static_cast((processBytes * 100.0 / totalBytes) * 0.9); + ObjectStoreManager::GetInstance().NotifyAssetsRecvProgress(objectKey, progress); return OBJECT_SUCCESS; } } // namespace DistributedObject diff --git a/datamgr_service/services/distributeddataservice/service/object/src/object_manager.cpp b/datamgr_service/services/distributeddataservice/service/object/src/object_manager.cpp index 3e3c554ffb209383f725c589651275c138d3d30d..66d35fd0c24e758978cf8d3906a190ad23e1ae9d 100644 --- a/datamgr_service/services/distributeddataservice/service/object/src/object_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/src/object_manager.cpp @@ -26,9 +26,13 @@ #include "common/string_utils.h" #include "datetime_ex.h" #include "distributed_file_daemon_manager.h" +#include "device_matrix.h" +#include "ipc_skeleton.h" +#include "metadata/capability_meta_data.h" #include "kvstore_utils.h" #include "log_print.h" #include "metadata/meta_data_manager.h" +#include "metadata/object_user_meta_data.h" #include "metadata/store_meta_data.h" #include "object_dms_handler.h" #include "object_radar_reporter.h" @@ -43,7 +47,12 @@ using Account = OHOS::DistributedData::AccountDelegate; using AccessTokenKit = Security::AccessToken::AccessTokenKit; using ValueProxy = OHOS::DistributedData::ValueProxy; using DistributedFileDaemonManager = Storage::DistributedFile::DistributedFileDaemonManager; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; + constexpr const char *SAVE_INFO = "p_###SAVEINFO###"; +constexpr int32_t PROGRESS_MAX = 100; +constexpr int32_t PROGRESS_INVALID = -1; +constexpr uint32_t LOCK_TIMEOUT = 3600; // second ObjectStoreManager::ObjectStoreManager() { ZLOGI("ObjectStoreManager construct"); @@ -52,13 +61,6 @@ ObjectStoreManager::ObjectStoreManager() ObjectStoreManager::~ObjectStoreManager() { - ZLOGI("ObjectStoreManager destroy"); - if (objectAssetsRecvListener_ != nullptr) { - auto status = DistributedFileDaemonManager::GetInstance().UnRegisterAssetCallback(objectAssetsRecvListener_); - if (status != DistributedDB::DBStatus::OK) { - ZLOGE("UnRegister assetsRecvListener err %{public}d", status); - } - } } DistributedDB::KvStoreNbDelegate *ObjectStoreManager::OpenObjectKvStore() @@ -68,9 +70,6 @@ DistributedDB::KvStoreNbDelegate *ObjectStoreManager::OpenObjectKvStore() option.createDirByStoreIdOnly = true; option.syncDualTupleMode = true; option.secOption = { DistributedDB::S1, DistributedDB::ECE }; - if (objectDataListener_ == nullptr) { - objectDataListener_ = new ObjectDataListener(); - } ZLOGD("start GetKvStore"); kvStoreDelegateManager_->GetKvStore(ObjectCommon::OBJECTSTORE_DB_STOREID, option, [&store, this](DistributedDB::DBStatus dbStatus, DistributedDB::KvStoreNbDelegate *kvStoreNbDelegate) { @@ -78,12 +77,16 @@ DistributedDB::KvStoreNbDelegate *ObjectStoreManager::OpenObjectKvStore() ZLOGE("GetKvStore fail %{public}d", dbStatus); return; } + if (kvStoreNbDelegate == nullptr) { + ZLOGE("GetKvStore kvStoreNbDelegate is nullptr"); + return; + } ZLOGI("GetKvStore successsfully"); store = kvStoreNbDelegate; std::vector tmpKey; DistributedDB::DBStatus status = store->RegisterObserver(tmpKey, DistributedDB::ObserverMode::OBSERVER_CHANGES_FOREIGN, - objectDataListener_); + &objectDataListener_); if (status != DistributedDB::DBStatus::OK) { ZLOGE("RegisterObserver err %{public}d", status); } @@ -107,6 +110,19 @@ bool ObjectStoreManager::RegisterAssetsLister() return true; } +bool ObjectStoreManager::UnRegisterAssetsLister() +{ + ZLOGI("ObjectStoreManager UnRegisterAssetsLister"); + if (objectAssetsRecvListener_ != nullptr) { + auto status = DistributedFileDaemonManager::GetInstance().UnRegisterAssetCallback(objectAssetsRecvListener_); + if (status != DistributedDB::DBStatus::OK) { + ZLOGE("UnRegister assetsRecvListener err %{public}d", status); + return false; + } + } + return true; +} + void ObjectStoreManager::ProcessSyncCallback(const std::map &results, const std::string &appId, const std::string &sessionId, const std::string &deviceId) { @@ -131,8 +147,13 @@ int32_t ObjectStoreManager::Save(const std::string &appId, const std::string &se const ObjectRecord &data, const std::string &deviceId, sptr callback) { auto proxy = iface_cast(callback); + if (proxy == nullptr) { + ZLOGE("proxy is nullptr, callback is %{public}s.", (callback == nullptr) ? "nullptr" : "not null"); + return INVALID_ARGUMENT; + } if (deviceId.size() == 0) { - ZLOGE("DeviceId empty, appId: %{public}s, sessionId: %{public}s", appId.c_str(), sessionId.c_str()); + ZLOGE("DeviceId empty, appId: %{public}s, sessionId: %{public}s", appId.c_str(), + Anonymous::Change(sessionId).c_str()); proxy->Completed(std::map()); return INVALID_ARGUMENT; } @@ -156,13 +177,13 @@ int32_t ObjectStoreManager::Save(const std::string &appId, const std::string &se return result; } ZLOGI("Sync data, bundleName: %{public}s, sessionId: %{public}s, deviceId: %{public}s", dstBundleName.c_str(), - sessionId.c_str(), Anonymous::Change(deviceId).c_str()); + Anonymous::Change(sessionId).c_str(), Anonymous::Change(deviceId).c_str()); SyncCallBack syncCallback = [proxy, dstBundleName, sessionId, deviceId, this](const std::map &results) { ProcessSyncCallback(results, dstBundleName, sessionId, deviceId); proxy->Completed(results); }; - result = SyncOnStore(GetPropertyPrefix(dstBundleName, sessionId, deviceId), {deviceId}, syncCallback); + result = SyncOnStore(GetPropertyPrefix(dstBundleName, sessionId, deviceId), { deviceId }, syncCallback); if (result != OBJECT_SUCCESS) { ZLOGE("Sync data failed, result: %{public}d", result); ObjectStore::RadarReporter::ReportStateError(std::string(__FUNCTION__), ObjectStore::SAVE, @@ -182,7 +203,11 @@ int32_t ObjectStoreManager::PushAssets(const std::string &srcBundleName, const s if (assets.empty() || data.find(ObjectStore::FIELDS_PREFIX + ObjectStore::DEVICEID_KEY) == data.end()) { return OBJECT_SUCCESS; } - sptr assetObj = new AssetObj(); + sptr assetObj = new (std::nothrow) AssetObj(); + if (assetObj == nullptr) { + ZLOGE("New AssetObj failed"); + return OBJECT_INNER_ERROR; + } assetObj->dstBundleName_ = dstBundleName; assetObj->srcBundleName_ = srcBundleName; assetObj->dstNetworkId_ = deviceId; @@ -194,7 +219,7 @@ int32_t ObjectStoreManager::PushAssets(const std::string &srcBundleName, const s objectAssetsSendListener_ = new ObjectAssetsSendListener(); } int userId = std::atoi(GetCurrentUser().c_str()); - auto status = ObjectAssetLoader::GetInstance()->PushAsset(userId, assetObj, objectAssetsSendListener_); + auto status = ObjectAssetLoader::GetInstance().PushAsset(userId, assetObj, objectAssetsSendListener_); return status; } @@ -202,6 +227,11 @@ int32_t ObjectStoreManager::RevokeSave( const std::string &appId, const std::string &sessionId, sptr callback) { auto proxy = iface_cast(callback); + if (proxy == nullptr) { + ZLOGE("proxy is nullptr, callback is %{public}s, appId: %{public}s, sessionId: %{public}s.", + (callback == nullptr) ? "nullptr" : "not null", appId.c_str(), Anonymous::Change(sessionId).c_str()); + return INVALID_ARGUMENT; + } int32_t result = Open(); if (result != OBJECT_SUCCESS) { ZLOGE("Open failed, errCode = %{public}d", result); @@ -241,6 +271,10 @@ int32_t ObjectStoreManager::Retrieve( const std::string &bundleName, const std::string &sessionId, sptr callback, uint32_t tokenId) { auto proxy = iface_cast(callback); + if (proxy == nullptr) { + ZLOGE("proxy is nullptr, callback is %{public}s.", (callback == nullptr) ? "nullptr" : "not null"); + return INVALID_ARGUMENT; + } int32_t result = Open(); if (result != OBJECT_SUCCESS) { ZLOGE("Open object kvstore failed, result: %{public}d", result); @@ -250,7 +284,7 @@ int32_t ObjectStoreManager::Retrieve( ObjectRecord results{}; int32_t status = RetrieveFromStore(bundleName, sessionId, results); if (status != OBJECT_SUCCESS) { - ZLOGI("Retrieve from store failed, status: %{public}d, close after one minute.", status); + ZLOGE("Retrieve from store failed, status: %{public}d, close after one minute.", status); CloseAfterMinute(); proxy->Completed(ObjectRecord(), false); return status; @@ -260,8 +294,7 @@ int32_t ObjectStoreManager::Retrieve( if (assets.empty() || results.find(ObjectStore::FIELDS_PREFIX + ObjectStore::DEVICEID_KEY) == results.end()) { allReady = true; } else { - auto objectKey = bundleName + sessionId; - restoreStatus_.ComputeIfPresent(objectKey, [&allReady](const auto &key, auto &value) { + restoreStatus_.ComputeIfPresent(bundleName + sessionId, [&allReady](const auto &key, auto &value) { if (value == RestoreStatus::ALL_READY) { allReady = true; return false; @@ -273,13 +306,12 @@ int32_t ObjectStoreManager::Retrieve( }); } status = RevokeSaveToStore(GetPrefixWithoutDeviceId(bundleName, sessionId)); + Close(); if (status != OBJECT_SUCCESS) { ZLOGE("Revoke save failed, status: %{public}d", status); - Close(); proxy->Completed(ObjectRecord(), false); return status; } - Close(); proxy->Completed(results, allReady); if (allReady) { ObjectStore::RadarReporter::ReportStateFinished(std::string(__FUNCTION__), ObjectStore::DATA_RESTORE, @@ -291,39 +323,64 @@ int32_t ObjectStoreManager::Retrieve( int32_t ObjectStoreManager::Clear() { ZLOGI("enter"); + DistributedData::ObjectUserMetaData userMeta; + if (!DistributedData::MetaDataManager::GetInstance().LoadMeta(userMeta.GetKey(), userMeta, true)) { + ZLOGE("load meta error"); + return OBJECT_INNER_ERROR; + } + if (userMeta.userId.empty()) { + ZLOGI("no object user meta, don't need clean"); + return OBJECT_SUCCESS; + } std::string userId = GetCurrentUser(); if (userId.empty()) { + ZLOGE("no user error"); return OBJECT_INNER_ERROR; } - std::vector metaData; - std::string appId = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); - std::string metaKey = GetMetaUserIdKey(userId, appId); - if (!DistributedData::MetaDataManager::GetInstance().LoadMeta(metaKey, metaData, true)) { - ZLOGE("no store of %{public}s", appId.c_str()); - return OBJECT_STORE_NOT_FOUND; - } - for (const auto &storeMeta : metaData) { - if (storeMeta.storeType < StoreMetaData::StoreType::STORE_OBJECT_BEGIN - || storeMeta.storeType > StoreMetaData::StoreType::STORE_OBJECT_END) { - continue; - } - if (storeMeta.user == userId) { - ZLOGI("user is same, not need to change, mate user:%{public}s::user:%{public}s.", - storeMeta.user.c_str(), userId.c_str()); - return OBJECT_SUCCESS; - } + if (userMeta.userId == userId) { + ZLOGI("user is same, don't need clear, user:%{public}s.", userId.c_str()); + return OBJECT_SUCCESS; } - ZLOGD("user is change, need to change"); + ZLOGI("user changed, need clear, userId:%{public}s", userId.c_str()); int32_t result = Open(); if (result != OBJECT_SUCCESS) { ZLOGE("Open failed, errCode = %{public}d", result); return STORE_NOT_OPEN; } result = RevokeSaveToStore(""); - Close(); + callbacks_.Clear(); + processCallbacks_.Clear(); + ForceClose(); return result; } +int32_t ObjectStoreManager::InitUserMeta() +{ + ObjectUserMetaData userMeta; + if (DistributedData::MetaDataManager::GetInstance().LoadMeta(userMeta.GetKey(), userMeta, true)) { + ZLOGI("userId has been set, don't need clean"); + return OBJECT_SUCCESS; + } + std::string userId = GetCurrentUser(); + if (userId.empty()) { + ZLOGI("get userId error"); + return OBJECT_INNER_ERROR; + } + userMeta.userId = userId; + std::string appId = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); + std::string metaKey = GetMetaUserIdKey(userId, appId); + if (!DistributedData::MetaDataManager::GetInstance().DelMeta(metaKey, true)) { + ZLOGE("delete old meta error, userId:%{public}s", userId.c_str()); + return OBJECT_INNER_ERROR; + } + if (!DistributedData::MetaDataManager::GetInstance().SaveMeta(DistributedData::ObjectUserMetaData::GetKey(), + userMeta, true)) { + ZLOGE("save meta error, userId:%{public}s", userId.c_str()); + return OBJECT_INNER_ERROR; + } + return OBJECT_SUCCESS; +} + int32_t ObjectStoreManager::DeleteByAppId(const std::string &appId, int32_t user) { int32_t result = Open(); @@ -338,12 +395,6 @@ int32_t ObjectStoreManager::DeleteByAppId(const std::string &appId, int32_t user appId.c_str(), user); } Close(); - std::string userId = std::to_string(user); - std::string metaKey = GetMetaUserIdKey(userId, appId); - auto status = DistributedData::MetaDataManager::GetInstance().DelMeta(metaKey, true); - if (!status) { - ZLOGE("Delete meta failed, userId: %{public}s, appId: %{public}s", userId.c_str(), appId.c_str()); - } return result; } @@ -357,6 +408,13 @@ void ObjectStoreManager::RegisterRemoteCallback(const std::string &bundleName, c } ZLOGD("ObjectStoreManager::RegisterRemoteCallback start"); auto proxy = iface_cast(callback); + if (proxy == nullptr) { + ZLOGE("proxy is nullptr, callback is %{public}s, bundleName: %{public}s, sessionId: %{public}s, pid: " + "%{public}d, tokenId: %{public}u.", + (callback == nullptr) ? "nullptr" : "not null", bundleName.c_str(), Anonymous::Change(sessionId).c_str(), + pid, tokenId); + return; + } std::string prefix = bundleName + sessionId; callbacks_.Compute(tokenId, ([pid, &proxy, &prefix](const uint32_t key, CallbackInfo &value) { if (value.pid != pid) { @@ -367,8 +425,8 @@ void ObjectStoreManager::RegisterRemoteCallback(const std::string &bundleName, c })); } -void ObjectStoreManager::UnregisterRemoteCallback(const std::string &bundleName, pid_t pid, uint32_t tokenId, - const std::string &sessionId) +void ObjectStoreManager::UnregisterRemoteCallback( + const std::string &bundleName, pid_t pid, uint32_t tokenId, const std::string &sessionId) { if (bundleName.empty()) { ZLOGD("bundleName is empty"); @@ -393,7 +451,81 @@ void ObjectStoreManager::UnregisterRemoteCallback(const std::string &bundleName, })); } -void ObjectStoreManager::NotifyChange(ObjectRecord &changedData) +void ObjectStoreManager::RegisterProgressObserverCallback(const std::string &bundleName, const std::string &sessionId, + pid_t pid, uint32_t tokenId, sptr callback) +{ + if (bundleName.empty() || sessionId.empty()) { + ZLOGD("ObjectStoreManager::RegisterProgressObserverCallback empty bundleName = %{public}s, sessionId = " + "%{public}s", + bundleName.c_str(), DistributedData::Anonymous::Change(sessionId).c_str()); + return; + } + auto proxy = iface_cast(callback); + if (proxy == nullptr) { + ZLOGE("proxy is nullptr, callback is %{public}s, bundleName: %{public}s, sessionId: %{public}s, pid: " + "%{public}d, tokenId: %{public}u.", + (callback == nullptr) ? "nullptr" : "not null", bundleName.c_str(), Anonymous::Change(sessionId).c_str(), + pid, tokenId); + return; + } + std::string objectKey = bundleName + sessionId; + sptr observer; + processCallbacks_.Compute( + tokenId, ([pid, &proxy, &objectKey, &observer](const uint32_t key, ProgressCallbackInfo &value) { + if (value.pid != pid) { + value = ProgressCallbackInfo{ pid }; + } + value.observers_.insert_or_assign(objectKey, proxy); + observer = value.observers_[objectKey]; + return !value.observers_.empty(); + })); + int32_t progress = PROGRESS_INVALID; + { + std::lock_guard lock(progressMutex_); + auto it = progressInfo_.find(objectKey); + if (it == progressInfo_.end()) { + return; + } + progress = it->second; + } + if (observer != nullptr && progress != PROGRESS_INVALID) { + observer->Completed(progress); + } + if (progress == PROGRESS_MAX) { + assetsRecvProgress_.Erase(objectKey); + std::lock_guard lock(progressMutex_); + progressInfo_.erase(objectKey); + } +} + +void ObjectStoreManager::UnregisterProgressObserverCallback( + const std::string &bundleName, pid_t pid, uint32_t tokenId, const std::string &sessionId) +{ + if (bundleName.empty()) { + ZLOGD("bundleName is empty"); + return; + } + processCallbacks_.Compute( + tokenId, ([pid, &sessionId, &bundleName](const uint32_t key, ProgressCallbackInfo &value) { + if (value.pid != pid) { + return true; + } + if (sessionId.empty()) { + return false; + } + std::string prefix = bundleName + sessionId; + for (auto it = value.observers_.begin(); it != value.observers_.end();) { + if ((*it).first == prefix) { + it = value.observers_.erase(it); + } else { + ++it; + } + } + return true; + })); +} + +void ObjectStoreManager::NotifyChange(const ObjectRecord &changedData) { ZLOGI("OnChange start, size:%{public}zu", changedData.size()); bool hasAsset = false; @@ -484,6 +616,34 @@ void ObjectStoreManager::ComputeStatus(const std::string& objectKey, const SaveI }); } +bool ObjectStoreManager::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); + bool flag = !MetaDataManager::GetInstance().LoadMeta(std::string(capKey.begin(), capKey.end()), capMeta) || + !MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData); + if (flag) { + isAfterMeta = true; + break; + } + auto [exist, mask] = DeviceMatrix::GetInstance().GetRemoteMask(uuid); + if ((mask & DeviceMatrix::META_STORE_MASK) == DeviceMatrix::META_STORE_MASK) { + isAfterMeta = true; + break; + } + auto [existLocal, localMask] = DeviceMatrix::GetInstance().GetMask(uuid); + if ((localMask & DeviceMatrix::META_STORE_MASK) == DeviceMatrix::META_STORE_MASK) { + isAfterMeta = true; + break; + } + } + return isAfterMeta; +} + void ObjectStoreManager::NotifyDataChanged(const std::map& data, const SaveInfo& saveInfo) { for (auto const& [objectKey, results] : data) { @@ -498,6 +658,10 @@ void ObjectStoreManager::NotifyDataChanged(const std::map& data) { + if (executors_ == nullptr) { + ZLOGE("executors_ is null"); + return OBJECT_INNER_ERROR; + } 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); @@ -520,7 +684,7 @@ void ObjectStoreManager::PullAssets(const std::map& d 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()), + ObjectAssetLoader::GetInstance().TransferAssetsAsync(std::atoi(GetCurrentUser().c_str()), saveInfo.bundleName, networkId, assets, [this, block](bool success) { block->SetValue({ false, success }); }); @@ -530,9 +694,47 @@ void ObjectStoreManager::PullAssets(const std::map& d } } -void ObjectStoreManager::NotifyAssetsReady(const std::string& objectKey, const std::string& bundleName, - const std::string& srcNetworkId) +void ObjectStoreManager::NotifyAssetsRecvProgress(const std::string &objectKey, int32_t progress) +{ + assetsRecvProgress_.InsertOrAssign(objectKey, progress); + std::list> observers; + bool flag = false; + processCallbacks_.ForEach( + [&objectKey, &observers, &flag](uint32_t tokenId, const ProgressCallbackInfo &value) { + if (value.observers_.empty()) { + flag = true; + return false; + } + auto it = value.observers_.find(objectKey); + if (it != value.observers_.end()) { + observers.push_back(it->second); + } + return false; + }); + if (flag) { + std::lock_guard lock(progressMutex_); + progressInfo_.insert_or_assign(objectKey, progress); + } + for (auto &observer : observers) { + if (observer == nullptr) { + continue; + } + observer->Completed(progress); + } + if (!observers.empty() && progress == PROGRESS_MAX) { + assetsRecvProgress_.Erase(objectKey); + std::lock_guard lock(progressMutex_); + progressInfo_.erase(objectKey); + } +} + +void ObjectStoreManager::NotifyAssetsReady( + const std::string &objectKey, const std::string &bundleName, const std::string &srcNetworkId) { + if (executors_ == nullptr) { + ZLOGE("executors_ is nullptr"); + return; + } restoreStatus_.ComputeIfAbsent( objectKey, [](const std::string& key) -> auto { return RestoreStatus::NONE; @@ -598,7 +800,9 @@ Assets ObjectStoreManager::GetAssetsFromDBRecords(const ObjectRecord& result) std::string assetPrefix = key.substr(0, key.find(ObjectStore::ASSET_DOT)); if (!IsAssetKey(key) || assetKey.find(assetPrefix) != assetKey.end() || result.find(assetPrefix + ObjectStore::NAME_SUFFIX) == result.end() || - result.find(assetPrefix + ObjectStore::URI_SUFFIX) == result.end()) { + result.find(assetPrefix + ObjectStore::URI_SUFFIX) == result.end() || + result.find(assetPrefix + ObjectStore::MODIFY_TIME_SUFFIX) == result.end() || + result.find(assetPrefix + ObjectStore::SIZE_SUFFIX) == result.end()) { continue; } Asset asset; @@ -654,6 +858,10 @@ void ObjectStoreManager::DoNotify(uint32_t tokenId, const CallbackInfo& value, void ObjectStoreManager::DoNotifyAssetsReady(uint32_t tokenId, const CallbackInfo& value, const std::string& objectKey, bool allReady) { + if (executors_ == nullptr) { + ZLOGE("executors_ is nullptr"); + return; + } for (const auto& observer : value.observers_) { if (objectKey != observer.first) { continue; @@ -674,6 +882,10 @@ void ObjectStoreManager::DoNotifyAssetsReady(uint32_t tokenId, const CallbackInf void ObjectStoreManager::DoNotifyWaitAssetTimeout(const std::string &objectKey) { + if (executors_ == nullptr) { + ZLOGE("executors_ is nullptr"); + return; + } 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) { @@ -697,11 +909,15 @@ void ObjectStoreManager::DoNotifyWaitAssetTimeout(const std::string &objectKey) void ObjectStoreManager::SetData(const std::string &dataDir, const std::string &userId) { - ZLOGI("enter %{public}s", dataDir.c_str()); - kvStoreDelegateManager_ = - new DistributedDB::KvStoreDelegateManager(DistributedData::Bootstrap::GetInstance().GetProcessLabel(), userId); + ZLOGI("enter, user: %{public}s", userId.c_str()); + kvStoreDelegateManager_ = std::make_shared + (DistributedData::Bootstrap::GetInstance().GetProcessLabel(), userId); DistributedDB::KvStoreConfig kvStoreConfig { dataDir }; - kvStoreDelegateManager_->SetKvStoreConfig(kvStoreConfig); + auto status = kvStoreDelegateManager_->SetKvStoreConfig(kvStoreConfig); + if (status != DistributedDB::OK) { + ZLOGE("Set kvstore config failed, status: %{public}d", status); + return; + } userId_ = userId; } @@ -711,7 +927,7 @@ int32_t ObjectStoreManager::Open() ZLOGE("Kvstore delegate manager not init"); return OBJECT_INNER_ERROR; } - std::lock_guard lock(kvStoreMutex_); + std::unique_lock lock(rwMutex_); if (delegate_ == nullptr) { delegate_ = OpenObjectKvStore(); if (delegate_ == nullptr) { @@ -722,25 +938,44 @@ int32_t ObjectStoreManager::Open() ZLOGI("Open object kvstore success"); } else { syncCount_++; - ZLOGI("Object kvstore syncCount: %{public}d", syncCount_); + ZLOGI("Object kvstore syncCount: %{public}d", syncCount_.load()); } return OBJECT_SUCCESS; } -void ObjectStoreManager::Close() +void ObjectStoreManager::ForceClose() { - std::lock_guard lock(kvStoreMutex_); + std::unique_lock lock(rwMutex_, std::chrono::seconds(LOCK_TIMEOUT)); if (delegate_ == nullptr) { return; } - int32_t taskCount = delegate_->GetTaskCount(); + auto status = kvStoreDelegateManager_->CloseKvStore(delegate_); + if (status != DistributedDB::DBStatus::OK) { + ZLOGE("CloseKvStore fail %{public}d", status); + return; + } + delegate_ = nullptr; + isSyncing_ = false; + syncCount_ = 0; +} + +void ObjectStoreManager::Close() +{ + int32_t taskCount = 0; + { + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + return; + } + 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_); + ZLOGI("closed a store, syncCount = %{public}d", syncCount_.load()); FlushClosedStore(); } @@ -750,7 +985,6 @@ void ObjectStoreManager::SyncCompleted( std::string userId; SequenceSyncManager::Result result = SequenceSyncManager::GetInstance()->Process(sequenceId, results, userId); if (result == SequenceSyncManager::SUCCESS_USER_HAS_FINISHED && userId == userId_) { - std::lock_guard lock(kvStoreMutex_); SetSyncStatus(false); FlushClosedStore(); } @@ -766,10 +1000,14 @@ void ObjectStoreManager::SyncCompleted( } } } - + void ObjectStoreManager::FlushClosedStore() { - std::lock_guard lock(kvStoreMutex_); + if (executors_ == nullptr) { + ZLOGE("executors_ is nullptr"); + return; + } + std::unique_lock lock(rwMutex_); if (!isSyncing_ && syncCount_ == 0 && delegate_ != nullptr) { ZLOGD("close store"); auto status = kvStoreDelegateManager_->CloseKvStore(delegate_); @@ -782,24 +1020,23 @@ void ObjectStoreManager::FlushClosedStore() return; } delegate_ = nullptr; - if (objectDataListener_ != nullptr) { - delete objectDataListener_; - objectDataListener_ = nullptr; - } } } void ObjectStoreManager::ProcessOldEntry(const std::string &appId) { std::vector entries; - auto status = delegate_->GetEntries(std::vector(appId.begin(), appId.end()), entries); - if (status != DistributedDB::DBStatus::NOT_FOUND) { - ZLOGI("Get old entries empty, bundleName: %{public}s", appId.c_str()); - return; - } - if (status != DistributedDB::DBStatus::OK) { - ZLOGE("Get old entries failed, bundleName: %{public}s, status %{public}d", appId.c_str(), status); - return; + { + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("delegate is nullptr."); + return; + } + auto status = delegate_->GetEntries(std::vector(appId.begin(), appId.end()), entries); + if (status != DistributedDB::DBStatus::OK) { + ZLOGE("Get old entries failed, bundleName: %{public}s, status %{public}d", appId.c_str(), status); + return; + } } std::map sessionIds; int64_t oldestTime = 0; @@ -847,21 +1084,30 @@ int32_t ObjectStoreManager::SaveToStore(const std::string &appId, const std::str saveInfoEntry.value = std::vector(saveInfoValue.begin(), saveInfoValue.end()); std::vector entries; entries.emplace_back(saveInfoEntry); - for (auto &item : data) { + for (const auto &item : data) { DistributedDB::Entry entry; std::string key = GetPropertyPrefix(appId, sessionId, toDeviceId) + timestamp + SEPERATOR + item.first; entry.key = std::vector(key.begin(), key.end()); entry.value = item.second; entries.emplace_back(entry); } - auto status = delegate_->PutBatch(entries); - if (status != DistributedDB::DBStatus::OK) { - ZLOGE("PutBatch failed, bundleName: %{public}s, sessionId: %{public}s, dstNetworkId: %{public}s, " - "status: %{public}d", appId.c_str(), sessionId.c_str(), Anonymous::Change(toDeviceId).c_str(), status); - return status; + { + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("delegate is nullptr."); + return E_DB_ERROR; + } + auto status = delegate_->PutBatch(entries); + if (status != DistributedDB::DBStatus::OK) { + ZLOGE("PutBatch failed, bundleName: %{public}s, sessionId: %{public}s, dstNetworkId: %{public}s, " + "status: %{public}d", + appId.c_str(), Anonymous::Change(sessionId).c_str(), Anonymous::Change(toDeviceId).c_str(), status); + return status; + } } ZLOGI("PutBatch success, bundleName: %{public}s, sessionId: %{public}s, dstNetworkId: %{public}s, " - "count: %{public}zu", appId.c_str(), sessionId.c_str(), Anonymous::Change(toDeviceId).c_str(), entries.size()); + "count: %{public}zu", + appId.c_str(), Anonymous::Change(sessionId).c_str(), Anonymous::Change(toDeviceId).c_str(), entries.size()); return OBJECT_SUCCESS; } @@ -869,9 +1115,9 @@ int32_t ObjectStoreManager::SyncOnStore( const std::string &prefix, const std::vector &deviceList, SyncCallBack &callback) { std::vector syncDevices; - for (auto &device : deviceList) { + for (auto const &device : deviceList) { if (device == LOCAL_DEVICE) { - ZLOGI("Save to local, do not need sync, prefix: %{public}s", prefix.c_str()); + ZLOGI("Save to local, do not need sync, prefix: %{public}s", Anonymous::Change(prefix).c_str()); callback({{LOCAL_DEVICE, OBJECT_SUCCESS}}); return OBJECT_SUCCESS; } @@ -883,10 +1129,35 @@ int32_t ObjectStoreManager::SyncOnStore( return OBJECT_SUCCESS; } uint64_t sequenceId = SequenceSyncManager::GetInstance()->AddNotifier(userId_, callback); + + int32_t id = AccountDelegate::GetInstance()->GetUserByToken(IPCSkeleton::GetCallingFullTokenID()); + StoreMetaData meta = StoreMetaData(std::to_string(id), Bootstrap::GetInstance().GetProcessLabel(), + DistributedObject::ObjectCommon::OBJECTSTORE_DB_STOREID); + auto uuids = DmAdapter::GetInstance().ToUUID(syncDevices); + bool isNeedMetaSync = IsNeedMetaSync(meta, uuids); + if (!isNeedMetaSync) { + return DoSync(prefix, syncDevices, sequenceId); + } + bool result = MetaDataManager::GetInstance().Sync(uuids, [this, prefix, syncDevices, sequenceId](auto &results) { + auto status = DoSync(prefix, syncDevices, sequenceId); + ZLOGI("Store sync after meta sync end, status:%{public}d", status); + }); + ZLOGI("prefix:%{public}s, meta sync end, result:%{public}d", Anonymous::Change(prefix).c_str(), result); + return result ? OBJECT_SUCCESS : DoSync(prefix, syncDevices, sequenceId); +} + +int32_t ObjectStoreManager::DoSync(const std::string &prefix, const std::vector &deviceList, + uint64_t sequenceId) +{ + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("db store was closed."); + return E_DB_ERROR; + } DistributedDB::Query dbQuery = DistributedDB::Query::Select(); dbQuery.PrefixKey(std::vector(prefix.begin(), prefix.end())); ZLOGI("Start sync data, sequenceId: 0x%{public}" PRIx64 "", sequenceId); - auto status = delegate_->Sync(syncDevices, DistributedDB::SyncMode::SYNC_MODE_PUSH_ONLY, + auto status = delegate_->Sync(deviceList, DistributedDB::SyncMode::SYNC_MODE_PUSH_ONLY, [this, sequenceId](const std::map &devicesMap) { ZLOGI("Sync data finished, sequenceId: 0x%{public}" PRIx64 "", sequenceId); std::map result; @@ -908,7 +1179,6 @@ int32_t ObjectStoreManager::SyncOnStore( int32_t ObjectStoreManager::SetSyncStatus(bool status) { - std::lock_guard lock(kvStoreMutex_); isSyncing_ = status; return OBJECT_SUCCESS; } @@ -916,6 +1186,11 @@ int32_t ObjectStoreManager::SetSyncStatus(bool status) int32_t ObjectStoreManager::RevokeSaveToStore(const std::string &prefix) { std::vector entries; + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("db store was closed."); + return E_DB_ERROR; + } auto status = delegate_->GetEntries(std::vector(prefix.begin(), prefix.end()), entries); if (status == DistributedDB::DBStatus::NOT_FOUND) { ZLOGI("Get entries empty, prefix: %{public}s", Anonymous::Change(prefix).c_str()); @@ -948,16 +1223,21 @@ int32_t ObjectStoreManager::RetrieveFromStore(const std::string &appId, const st { std::vector entries; std::string prefix = GetPrefixWithoutDeviceId(appId, sessionId); + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("db store was closed."); + return E_DB_ERROR; + } auto status = delegate_->GetEntries(std::vector(prefix.begin(), prefix.end()), entries); if (status == DistributedDB::DBStatus::NOT_FOUND) { - ZLOGI("Get entries empty, prefix: %{public}s, status: %{public}d", prefix.c_str(), status); + ZLOGI("Get entries empty, prefix: %{public}s, status: %{public}d", Anonymous::Change(prefix).c_str(), status); return KEY_NOT_FOUND; } if (status != DistributedDB::DBStatus::OK) { - ZLOGE("Get entries failed, prefix: %{public}s, status: %{public}d", prefix.c_str(), status); + ZLOGE("Get entries failed, prefix: %{public}s, status: %{public}d", Anonymous::Change(prefix).c_str(), status); return DB_ERROR; } - ZLOGI("Get entries success, prefix: %{public}s, count: %{public}zu", prefix.c_str(), entries.size()); + ZLOGI("GetEntries success,prefix:%{public}s,count:%{public}zu", Anonymous::Change(prefix).c_str(), entries.size()); for (const auto &entry : entries) { std::string key(entry.key.begin(), entry.key.end()); if (key.find(SAVE_INFO) != std::string::npos) { @@ -1056,8 +1336,9 @@ std::vector ObjectStoreManager::SplitEntryKey(const std::string &ke std::string ObjectStoreManager::GetCurrentUser() { std::vector users; - AccountDelegate::GetInstance()->QueryUsers(users); - if (users.empty()) { + auto ret = AccountDelegate::GetInstance()->QueryUsers(users); + if (!ret || users.empty()) { + ZLOGE("failed to query os accounts, ret:%{public}d", ret); return ""; } return std::to_string(users[0]); @@ -1071,20 +1352,24 @@ void ObjectStoreManager::SaveUserToMeta() return; } std::string appId = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); - StoreMetaData userMeta; - userMeta.storeId = DistributedObject::ObjectCommon::OBJECTSTORE_DB_STOREID; - userMeta.user = userId; - userMeta.storeType = ObjectDistributedType::OBJECT_SINGLE_VERSION; - std::string userMetaKey = GetMetaUserIdKey(userId, appId); - auto saved = DistributedData::MetaDataManager::GetInstance().SaveMeta(userMetaKey, userMeta, true); + DistributedData::ObjectUserMetaData userMeta; + userMeta.userId = userId; + auto saved = DistributedData::MetaDataManager::GetInstance().SaveMeta( + DistributedData::ObjectUserMetaData::GetKey(), userMeta, true); if (!saved) { - ZLOGE("userMeta save failed"); + ZLOGE("userMeta save failed, userId:%{public}s", userId.c_str()); } } void ObjectStoreManager::CloseAfterMinute() { - executors_->Schedule(std::chrono::minutes(INTERVAL), std::bind(&ObjectStoreManager::Close, this)); + if (executors_ == nullptr) { + ZLOGE("executors_ is nullptr."); + return; + } + executors_->Schedule(std::chrono::minutes(INTERVAL), [this]() { + Close(); + }); } void ObjectStoreManager::SetThreadPool(std::shared_ptr executors) @@ -1110,7 +1395,7 @@ SequenceSyncManager::Result SequenceSyncManager::Process( return ERR_SID_NOT_EXIST; } std::map syncResults; - for (auto &item : results) { + for (const auto &item : results) { syncResults[item.first] = item.second == DistributedDB::DBStatus::OK ? 0 : -1; } seqIdCallbackRelations_[sequenceId](syncResults); @@ -1170,6 +1455,10 @@ int32_t ObjectStoreManager::BindAsset(const uint32_t tokenId, const std::string& return true; }); + if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) { + ZLOGE("TokenType is not TOKEN_HAP, token:0x%{public}x, bundleName:%{public}s", tokenId, appId.c_str()); + return GeneralError::E_ERROR; + } HapTokenInfo tokenInfo; auto status = AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo); if (status != RET_SUCCESS) { @@ -1221,7 +1510,7 @@ int32_t ObjectStoreManager::OnAssetChanged(const uint32_t tokenId, const std::st } auto block = std::make_shared>>(WAIT_TIME, std::tuple{ true, true }); - ObjectAssetLoader::GetInstance()->TransferAssetsAsync(userId, appId, deviceId, { dataAsset }, [block](bool ret) { + ObjectAssetLoader::GetInstance().TransferAssetsAsync(userId, appId, deviceId, { dataAsset }, [block](bool ret) { block->SetValue({ false, ret }); }); auto [timeout, success] = block->GetValue(); @@ -1264,5 +1553,17 @@ void ObjectStoreManager::DeleteSnapshot(const std::string& bundleName, const std }); snapshots_.Erase(snapshotKey); } + +int32_t ObjectStoreManager::AutoLaunchStore() +{ + int32_t status = Open(); + if (status != OBJECT_SUCCESS) { + ZLOGE("Open fail %{public}d", status); + return status; + } + CloseAfterMinute(); + ZLOGI("Auto launch, close after a minute"); + return OBJECT_SUCCESS; +} } // namespace DistributedObject } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/object/src/object_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/object/src/object_service_impl.cpp index fdb08505e7ad12410d938f5807446a5666d7d9fc..ff6d5ee3af5e31e993f6ab2e0808f161c010aaba 100644 --- a/datamgr_service/services/distributeddataservice/service/object/src/object_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/src/object_service_impl.cpp @@ -43,7 +43,9 @@ using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; using StoreMetaData = OHOS::DistributedData::StoreMetaData; using FeatureSystem = OHOS::DistributedData::FeatureSystem; using DumpManager = OHOS::DistributedData::DumpManager; +using CheckerManager = OHOS::DistributedData::CheckerManager; __attribute__((used)) ObjectServiceImpl::Factory ObjectServiceImpl::factory_; +constexpr const char *METADATA_STORE_PATH = "/data/service/el1/public/database/distributeddata/kvdb"; ObjectServiceImpl::Factory::Factory() { FeatureSystem::GetInstance().RegisterCreator( @@ -72,7 +74,7 @@ int32_t ObjectServiceImpl::ObjectStoreSave(const std::string &bundleName, const if (status != OBJECT_SUCCESS) { return status; } - status = ObjectStoreManager::GetInstance()->Save(bundleName, sessionId, data, deviceId, callback); + status = ObjectStoreManager::GetInstance().Save(bundleName, sessionId, data, deviceId, callback); if (status != OBJECT_SUCCESS) { ZLOGE("save fail %{public}d", status); } @@ -89,7 +91,7 @@ int32_t ObjectServiceImpl::OnAssetChanged(const std::string &bundleName, const s if (status != OBJECT_SUCCESS) { return status; } - status = ObjectStoreManager::GetInstance()->OnAssetChanged(tokenId, bundleName, sessionId, deviceId, assetValue); + status = ObjectStoreManager::GetInstance().OnAssetChanged(tokenId, bundleName, sessionId, deviceId, assetValue); if (status != OBJECT_SUCCESS) { ZLOGE("file transfer failed fail %{public}d", status); } @@ -104,10 +106,10 @@ int32_t ObjectServiceImpl::BindAssetStore(const std::string &bundleName, const s if (status != OBJECT_SUCCESS) { return status; } - status = ObjectStoreManager::GetInstance()->BindAsset(tokenId, bundleName, sessionId, asset, bindInfo); + status = ObjectStoreManager::GetInstance().BindAsset(tokenId, bundleName, sessionId, asset, bindInfo); if (status != OBJECT_SUCCESS) { ZLOGE("bind asset fail %{public}d, bundleName:%{public}s, sessionId:%{public}s, assetName:%{public}s", status, - bundleName.c_str(), sessionId.c_str(), asset.name.c_str()); + bundleName.c_str(), Anonymous::Change(sessionId).c_str(), Anonymous::Change(asset.name).c_str()); } return status; } @@ -115,6 +117,10 @@ int32_t ObjectServiceImpl::BindAssetStore(const std::string &bundleName, const s int32_t ObjectServiceImpl::IsContinue(bool &result) { uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); + if (Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId) != Security::AccessToken::TOKEN_HAP) { + ZLOGE("TokenType is not TOKEN_HAP, tokenId: %{public}u", tokenId); + return OBJECT_INNER_ERROR; + } Security::AccessToken::HapTokenInfo tokenInfo; auto status = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo); if (status != 0) { @@ -133,10 +139,31 @@ int32_t ObjectServiceImpl::OnInitialize() ZLOGE("failed to get local device id"); return OBJECT_INNER_ERROR; } - auto token = IPCSkeleton::GetCallingTokenID(); - const std::string accountId = DistributedData::AccountDelegate::GetInstance()->GetCurrentAccountId(); - const auto userId = DistributedData::AccountDelegate::GetInstance()->GetUserByToken(token); - StoreMetaData saveMeta; + + if (executors_ == nullptr) { + ZLOGE("executors_ is nullptr"); + return OBJECT_INNER_ERROR; + } + executors_->Schedule(std::chrono::seconds(WAIT_ACCOUNT_SERVICE), [this]() { + StoreMetaData saveMeta; + SaveMetaData(saveMeta); + ObjectStoreManager::GetInstance().SetData(saveMeta.dataDir, saveMeta.user); + ObjectStoreManager::GetInstance().InitUserMeta(); + RegisterObjectServiceInfo(); + RegisterHandler(); + ObjectDmsHandler::GetInstance().RegisterDmsEvent(); + }); + + return OBJECT_SUCCESS; +} + +int32_t ObjectServiceImpl::SaveMetaData(StoreMetaData &saveMeta) +{ + auto localDeviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + if (localDeviceId.empty()) { + ZLOGE("failed to get local device id"); + return OBJECT_INNER_ERROR; + } saveMeta.appType = "default"; saveMeta.deviceId = localDeviceId; saveMeta.storeId = DistributedObject::ObjectCommon::OBJECTSTORE_DB_STOREID; @@ -145,17 +172,23 @@ int32_t ObjectServiceImpl::OnInitialize() saveMeta.isEncrypt = false; saveMeta.bundleName = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); saveMeta.appId = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); - saveMeta.user = std::to_string(userId); - saveMeta.account = accountId; - saveMeta.tokenId = token; + saveMeta.account = DistributedData::AccountDelegate::GetInstance()->GetCurrentAccountId(); + saveMeta.tokenId = IPCSkeleton::GetCallingTokenID(); saveMeta.securityLevel = DistributedKv::SecurityLevel::S1; saveMeta.area = DistributedKv::Area::EL1; saveMeta.uid = IPCSkeleton::GetCallingUid(); saveMeta.storeType = ObjectDistributedType::OBJECT_SINGLE_VERSION; saveMeta.dataType = DistributedKv::DataType::TYPE_DYNAMICAL; - saveMeta.dataDir = DistributedData::DirectoryManager::GetInstance().GetStorePath(saveMeta); - ObjectStoreManager::GetInstance()->SetData(saveMeta.dataDir, std::to_string(userId)); - bool isSaved = DistributedData::MetaDataManager::GetInstance().SaveMeta(saveMeta.GetKey(), saveMeta) && + saveMeta.authType = DistributedKv::AuthType::IDENTICAL_ACCOUNT; + int foregroundUserId = 0; + DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + saveMeta.user = std::to_string(foregroundUserId); + saveMeta.dataDir = METADATA_STORE_PATH; + if (!DistributedData::DirectoryManager::GetInstance().CreateDirectory(saveMeta.dataDir)) { + ZLOGE("Create directory error, dataDir: %{public}s.", Anonymous::Change(saveMeta.dataDir).c_str()); + return OBJECT_INNER_ERROR; + } + bool isSaved = DistributedData::MetaDataManager::GetInstance().SaveMeta(saveMeta.GetKeyWithoutPath(), saveMeta) && DistributedData::MetaDataManager::GetInstance().SaveMeta(saveMeta.GetKey(), saveMeta, true); if (!isSaved) { ZLOGE("SaveMeta failed"); @@ -168,18 +201,21 @@ int32_t ObjectServiceImpl::OnInitialize() if (!isSaved) { ZLOGE("Save appIdMeta failed"); } - ZLOGI("SaveMeta success appId %{public}s, storeId %{public}s", - saveMeta.appId.c_str(), saveMeta.GetStoreAlias().c_str()); - RegisterObjectServiceInfo(); - RegisterHandler(); - ObjectDmsHandler::GetInstance().RegisterDmsEvent(); + ZLOGI("SaveMeta success appId %{public}s, storeId %{public}s", saveMeta.appId.c_str(), + saveMeta.GetStoreAlias().c_str()); return OBJECT_SUCCESS; } int32_t ObjectServiceImpl::OnUserChange(uint32_t code, const std::string &user, const std::string &account) { if (code == static_cast(AccountStatus::DEVICE_ACCOUNT_SWITCHED)) { - Clear(); + int32_t status = ObjectStoreManager::GetInstance().Clear(); + if (status != OBJECT_SUCCESS) { + ZLOGE("Clear fail user:%{public}s, status: %{public}d", user.c_str(), status); + } + StoreMetaData saveMeta; + SaveMetaData(saveMeta); + ObjectStoreManager::GetInstance().SetData(saveMeta.dataDir, saveMeta.user); } return Feature::OnUserChange(code, user, account); } @@ -193,7 +229,7 @@ int32_t ObjectServiceImpl::ObjectStoreRevokeSave( if (status != OBJECT_SUCCESS) { return status; } - status = ObjectStoreManager::GetInstance()->RevokeSave(bundleName, sessionId, callback); + status = ObjectStoreManager::GetInstance().RevokeSave(bundleName, sessionId, callback); if (status != OBJECT_SUCCESS) { ZLOGE("revoke save fail %{public}d", status); return status; @@ -210,7 +246,7 @@ int32_t ObjectServiceImpl::ObjectStoreRetrieve( if (status != OBJECT_SUCCESS) { return status; } - status = ObjectStoreManager::GetInstance()->Retrieve(bundleName, sessionId, callback, tokenId); + status = ObjectStoreManager::GetInstance().Retrieve(bundleName, sessionId, callback, tokenId); if (status != OBJECT_SUCCESS) { ZLOGE("retrieve fail %{public}d", status); return status; @@ -228,7 +264,7 @@ int32_t ObjectServiceImpl::RegisterDataObserver( return status; } auto pid = IPCSkeleton::GetCallingPid(); - ObjectStoreManager::GetInstance()->RegisterRemoteCallback(bundleName, sessionId, pid, tokenId, callback); + ObjectStoreManager::GetInstance().RegisterRemoteCallback(bundleName, sessionId, pid, tokenId, callback); return OBJECT_SUCCESS; } @@ -241,7 +277,32 @@ int32_t ObjectServiceImpl::UnregisterDataChangeObserver(const std::string &bundl return status; } auto pid = IPCSkeleton::GetCallingPid(); - ObjectStoreManager::GetInstance()->UnregisterRemoteCallback(bundleName, pid, tokenId, sessionId); + ObjectStoreManager::GetInstance().UnregisterRemoteCallback(bundleName, pid, tokenId, sessionId); + return OBJECT_SUCCESS; +} + +int32_t ObjectServiceImpl::RegisterProgressObserver( + const std::string &bundleName, const std::string &sessionId, sptr callback) +{ + uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); + int32_t status = IsBundleNameEqualTokenId(bundleName, sessionId, tokenId); + if (status != OBJECT_SUCCESS) { + return status; + } + auto pid = IPCSkeleton::GetCallingPid(); + ObjectStoreManager::GetInstance().RegisterProgressObserverCallback(bundleName, sessionId, pid, tokenId, callback); + return OBJECT_SUCCESS; +} + +int32_t ObjectServiceImpl::UnregisterProgressObserver(const std::string &bundleName, const std::string &sessionId) +{ + uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); + int32_t status = IsBundleNameEqualTokenId(bundleName, sessionId, tokenId); + if (status != OBJECT_SUCCESS) { + return status; + } + auto pid = IPCSkeleton::GetCallingPid(); + ObjectStoreManager::GetInstance().UnregisterProgressObserverCallback(bundleName, pid, tokenId, sessionId); return OBJECT_SUCCESS; } @@ -252,7 +313,7 @@ int32_t ObjectServiceImpl::DeleteSnapshot(const std::string &bundleName, const s if (status != OBJECT_SUCCESS) { return status; } - ObjectStoreManager::GetInstance()->DeleteSnapshot(bundleName, sessionId); + ObjectStoreManager::GetInstance().DeleteSnapshot(bundleName, sessionId); return OBJECT_SUCCESS; } @@ -264,8 +325,7 @@ int32_t ObjectServiceImpl::IsBundleNameEqualTokenId( storeInfo.tokenId = tokenId; storeInfo.bundleName = bundleName; storeInfo.storeId = sessionId; - std::string appId = DistributedData::CheckerManager::GetInstance().GetAppId(storeInfo); - if (appId.empty()) { + if (!CheckerManager::GetInstance().IsValid(storeInfo)) { 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; @@ -273,18 +333,9 @@ int32_t ObjectServiceImpl::IsBundleNameEqualTokenId( return OBJECT_SUCCESS; } -void ObjectServiceImpl::Clear() -{ - ZLOGI("begin."); - int32_t status = ObjectStoreManager::GetInstance()->Clear(); - if (status != OBJECT_SUCCESS) { - ZLOGE("save fail %{public}d", status); - } -} - int32_t ObjectServiceImpl::ObjectStatic::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index) { - int32_t result = ObjectStoreManager::GetInstance()->DeleteByAppId(bundleName, user); + int32_t result = ObjectStoreManager::GetInstance().DeleteByAppId(bundleName, user); if (result != OBJECT_SUCCESS) { ZLOGE("Delete object data failed, result:%{public}d, bundleName:%{public}s, user:%{public}d, index:%{public}d", result, bundleName.c_str(), user, index); @@ -318,13 +369,10 @@ int32_t ObjectServiceImpl::ResolveAutoLaunch(const std::string &identifier, Dist continue; } if (storeMeta.bundleName == DistributedData::Bootstrap::GetInstance().GetProcessLabel()) { - int32_t status = DistributedObject::ObjectStoreManager::GetInstance()->Open(); + int32_t status = DistributedObject::ObjectStoreManager::GetInstance().AutoLaunchStore(); if (status != OBJECT_SUCCESS) { - ZLOGE("Open fail %{public}d", status); continue; } - DistributedObject::ObjectStoreManager::GetInstance()->CloseAfterMinute(); - ZLOGI("Auto launch, close after a minute"); return OBJECT_SUCCESS; } } @@ -335,7 +383,8 @@ int32_t ObjectServiceImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, con { ZLOGI("ObjectServiceImpl::OnAppExit uid=%{public}d, pid=%{public}d, tokenId=%{public}d, bundleName=%{public}s", uid, pid, tokenId, appId.c_str()); - ObjectStoreManager::GetInstance()->UnregisterRemoteCallback(appId, pid, tokenId); + ObjectStoreManager::GetInstance().UnregisterRemoteCallback(appId, pid, tokenId); + ObjectStoreManager::GetInstance().UnregisterProgressObserverCallback(appId, pid, tokenId); return FeatureSystem::STUB_SUCCESS; } @@ -349,7 +398,7 @@ ObjectServiceImpl::ObjectServiceImpl() meta.bundleName = eventInfo.bundleName; meta.user = std::to_string(eventInfo.user); meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) { + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyWithoutPath(), meta)) { ZLOGE("meta empty, bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); return; @@ -359,7 +408,7 @@ ObjectServiceImpl::ObjectServiceImpl() ZLOGE("store null, storeId:%{public}s", meta.GetStoreAlias().c_str()); return; } - auto bindAssets = ObjectStoreManager::GetInstance()->GetSnapShots(eventInfo.bundleName, eventInfo.storeName); + auto bindAssets = ObjectStoreManager::GetInstance().GetSnapShots(eventInfo.bundleName, eventInfo.storeName); store->BindSnapshots(bindAssets); }; EventCenter::GetInstance().Subscribe(BindEvent::BIND_SNAPSHOT, process); @@ -377,8 +426,9 @@ void ObjectServiceImpl::RegisterObjectServiceInfo() void ObjectServiceImpl::RegisterHandler() { - Handler handler = - std::bind(&ObjectServiceImpl::DumpObjectServiceInfo, this, std::placeholders::_1, std::placeholders::_2); + Handler handler = [this](int fd, std::map> ¶ms) { + DumpObjectServiceInfo(fd, params); + }; DumpManager::GetInstance().AddHandler("FEATURE_INFO", uintptr_t(this), handler); } @@ -392,13 +442,14 @@ void ObjectServiceImpl::DumpObjectServiceInfo(int fd, std::mapSetThreadPool(executors_); - ObjectAssetLoader::GetInstance()->SetThreadPool(executors_); + ObjectStoreManager::GetInstance().SetThreadPool(executors_); + ObjectAssetLoader::GetInstance().SetThreadPool(executors_); return 0; } } // namespace OHOS::DistributedObject diff --git a/datamgr_service/services/distributeddataservice/service/object/src/object_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/object/src/object_service_stub.cpp index 20255eab45911b9c02250c8a6bc9421e70040497..a5d521a390fe711e4a51577e87adf1876d4eea47 100644 --- a/datamgr_service/services/distributeddataservice/service/object/src/object_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/src/object_service_stub.cpp @@ -26,6 +26,7 @@ namespace OHOS::DistributedObject { using namespace DistributedKv; +using Anonymous = DistributedData::Anonymous; int32_t ObjectServiceStub::ObjectStoreSaveOnRemote(MessageParcel &data, MessageParcel &reply) { std::string sessionId; @@ -61,7 +62,7 @@ int32_t ObjectServiceStub::OnAssetChangedOnRemote(MessageParcel &data, MessagePa } ObjectStore::Asset assetValue; if (!ITypesUtil::Unmarshalling(assetValue, data)) { - ZLOGE("Unmarshal assetValue fail, asset name: %{public}s", assetValue.name.c_str()); + ZLOGE("Unmarshal assetValue fail, asset name: %{public}s", Anonymous::Change(assetValue.name).c_str()); return IPC_STUB_INVALID_DATA_ERR; } int32_t status = OnAssetChanged(bundleName, sessionId, deviceId, assetValue); @@ -80,8 +81,8 @@ int32_t ObjectServiceStub::ObjectStoreBindAssetOnRemote(MessageParcel &data, Mes ObjectStore::AssetBindInfo bindInfo; if (!ITypesUtil::Unmarshal(data, bundleName, sessionId, asset, bindInfo)) { ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s assetName:%{public}s bindStore:%{public}s", - DistributedData::Anonymous::Change(sessionId).c_str(), bundleName.c_str(), - asset.name.c_str(), bindInfo.storeName.c_str()); + Anonymous::Change(sessionId).c_str(), bundleName.c_str(), Anonymous::Change(asset.name).c_str(), + Anonymous::Change(bindInfo.storeName).c_str()); return IPC_STUB_INVALID_DATA_ERR; } @@ -164,6 +165,41 @@ int32_t ObjectServiceStub::OnUnsubscribeRequest(MessageParcel &data, MessageParc return 0; } +int32_t ObjectServiceStub::OnSubscribeProgress(MessageParcel &data, MessageParcel &reply) +{ + std::string sessionId; + std::string bundleName; + sptr obj; + if (!ITypesUtil::Unmarshal(data, bundleName, sessionId, obj) || obj == nullptr) { + ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s, callback is nullptr: %{public}d", + DistributedData::Anonymous::Change(sessionId).c_str(), bundleName.c_str(), obj == nullptr); + return IPC_STUB_INVALID_DATA_ERR; + } + int32_t status = RegisterProgressObserver(bundleName, sessionId, obj); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return status; +} + +int32_t ObjectServiceStub::OnUnsubscribeProgress(MessageParcel &data, MessageParcel &reply) +{ + std::string sessionId; + std::string bundleName; + if (!ITypesUtil::Unmarshal(data, bundleName, sessionId)) { + ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s", + DistributedData::Anonymous::Change(sessionId).c_str(), bundleName.c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + int32_t status = UnregisterProgressObserver(bundleName, sessionId); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return status; +} + int32_t ObjectServiceStub::OnDeleteSnapshot(MessageParcel &data, MessageParcel &reply) { std::string sessionId; diff --git a/datamgr_service/services/distributeddataservice/service/permission/BUILD.gn b/datamgr_service/services/distributeddataservice/service/permission/BUILD.gn index 0f28d27786dd61d36d339afb2b903a57ec682806..c6a4e1f1c45e94000d0795ecc862f7c0ba59ee93 100644 --- a/datamgr_service/services/distributeddataservice/service/permission/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/permission/BUILD.gn @@ -36,7 +36,6 @@ ohos_source_set("distributeddata_permit") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ @@ -52,12 +51,10 @@ ohos_source_set("distributeddata_permit") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk", - "${data_service_path}/service/crypto:distributeddata_crypto", ] external_deps = [ "access_token:libaccesstoken_sdk", diff --git a/datamgr_service/services/distributeddataservice/service/permission/src/permit_delegate.cpp b/datamgr_service/services/distributeddataservice/service/permission/src/permit_delegate.cpp index d3d020871aa37876f4d22cfe0f885792e3b23a8a..dd5b3c2cdee7d4f39042cb53eb4ca0a5b535153b 100644 --- a/datamgr_service/services/distributeddataservice/service/permission/src/permit_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/service/permission/src/permit_delegate.cpp @@ -102,13 +102,13 @@ bool PermitDelegate::VerifyPermission(const CheckParam ¶m, uint8_t flag) } return !value.empty(); }); - auto key = data.GetKey(); + auto key = data.GetKeyWithoutPath(); if (!metaDataBucket_.Get(key, data)) { if (!MetaDataManager::GetInstance().LoadMeta(key, data)) { - ZLOGE("load meta failed."); + ZLOGE("load meta failed, %{public}s", Anonymous::Change(data.storeId).c_str()); return false; } - metaDataBucket_.Set(data.GetKey(), data); + metaDataBucket_.Set(data.GetKeyWithoutPath(), data); } if (data.appType.compare("default") == 0) { ZLOGD("default, sync permission success."); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/BUILD.gn b/datamgr_service/services/distributeddataservice/service/rdb/BUILD.gn index ad693d92d8acab1c86f34e97d6b40bf44b1b5da8..4273bba4511c5bcb29e1359ba1d6c687e56f3c21 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/rdb/BUILD.gn @@ -63,13 +63,11 @@ ohos_source_set("distributeddata_rdb") { "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Werror", "-Oz", - "-fstack-protector-strong", ] deps = [ "${data_service_path}/service/bootstrap:distributeddata_bootstrap", "${data_service_path}/service/common:distributeddata_common", - "${data_service_path}/service/crypto:distributeddata_crypto", "${data_service_path}/service/matrix:distributeddata_matrix", "${data_service_path}/service/permission:distributeddata_permit", ] @@ -97,7 +95,6 @@ ohos_source_set("distributeddata_rdb") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.cpp b/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.cpp index 4c3b04d3ce9d2602735adcf60d3ffd68b4e04efe..e9ce03d3c3c1e30aeda7c836617e2b41d48cf5ec 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.cpp @@ -23,13 +23,13 @@ using namespace OHOS::DistributedData; CacheCursor::CacheCursor(std::vector &&records) : row_(0), maxCol_(0), records_(std::move(records)) { - maxRow_ = records_.size(); + maxRow_ = static_cast(records_.size()); if (maxRow_ > 0) { for (auto it = records_[0].begin(); it != records_[0].end(); it++) { colNames_.push_back(it->first); colTypes_.push_back(it->second.index()); } - maxCol_ = colNames_.size(); + maxCol_ = static_cast(colNames_.size()); } } diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp index 801af00ce94099cec643d0ade03a341ace4ead3f..00059689644670f3cd15b785bd2fea6558a7e5dc 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp @@ -27,8 +27,8 @@ using namespace DistributedDB; using ValueProxy = OHOS::DistributedData::ValueProxy; namespace OHOS::DistributedRdb { -RdbAssetLoader::RdbAssetLoader(std::shared_ptr cloudAssetLoader, BindAssets* bindAssets) - : assetLoader_(std::move(cloudAssetLoader)), snapshots_(bindAssets) +RdbAssetLoader::RdbAssetLoader(std::shared_ptr cloudAssetLoader, BindAssets bindAssets) + : assetLoader_(std::move(cloudAssetLoader)), snapshots_(std::move(bindAssets)) { } @@ -169,11 +169,11 @@ void RdbAssetLoader::PostEvent(DistributedData::AssetEvent eventId, DistributedD deleteAssets.insert(downLoadAsset.uri); continue; } - if (snapshots_ == nullptr || snapshots_->bindAssets == nullptr) { + if (snapshots_ == nullptr) { continue; } - auto it = snapshots_->bindAssets->find(downLoadAsset.uri); - if (it == snapshots_->bindAssets->end() || it->second == nullptr) { + auto it = snapshots_->find(downLoadAsset.uri); + if (it == snapshots_->end() || it->second == nullptr) { continue; } auto snapshot = it->second; @@ -185,7 +185,7 @@ void RdbAssetLoader::PostEvent(DistributedData::AssetEvent eventId, DistributedD } else { auto skipPos = skipAssets.find(downLoadAsset.uri); auto deletePos = deleteAssets.find(downLoadAsset.uri); - if (skipPos != skipAssets.end() || deletePos != skipAssets.end()) { + if (skipPos != skipAssets.end() || deletePos != deleteAssets.end()) { continue; } snapshot->Downloaded(downLoadAsset); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h index 1eb7b3e759c0146286eca196c37f8533d0debc1a..2e05a0abefed1cb21127b49bdf0f55ec45a9676f 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h @@ -23,18 +23,19 @@ #include "snapshot/snapshot.h" namespace OHOS::DistributedRdb { +using Snapshot = DistributedData::Snapshot; +using BindAssets = std::shared_ptr>>; class RdbAssetLoader : public DistributedDB::IAssetLoader { public: using Type = DistributedDB::Type; using Asset = DistributedDB::Asset; using DBStatus = DistributedDB::DBStatus; - using BindAssets = DistributedData::BindAssets; using AssetsRecord = DistributedData::AssetRecord; using AssetStatus = DistributedData::Asset::Status; using GeneralError = DistributedData::GeneralError; using VBucket = DistributedData::VBucket; - explicit RdbAssetLoader(std::shared_ptr cloudAssetLoader, BindAssets *bindAssets); + explicit RdbAssetLoader(std::shared_ptr cloudAssetLoader, BindAssets bindAssets); ~RdbAssetLoader() = default; @@ -61,7 +62,7 @@ private: std::set &skipAssets, std::set &deleteAssets); std::shared_ptr assetLoader_; - BindAssets *snapshots_; + const BindAssets snapshots_; }; } // namespace OHOS::DistributedRdb #endif // OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_ASSET_LOADER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp index 0a0726079f857ccfc3eb8c92431d0be84d47bcfa..13a509127d9243cb71ae111228382a639ba402c7 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp @@ -26,8 +26,8 @@ namespace OHOS::DistributedRdb { using namespace DistributedDB; using namespace DistributedData; -RdbCloud::RdbCloud(std::shared_ptr cloudDB, BindAssets* bindAssets) - : cloudDB_(std::move(cloudDB)), snapshots_(bindAssets) +RdbCloud::RdbCloud(std::shared_ptr cloudDB, BindAssets bindAssets) + : cloudDB_(std::move(cloudDB)), snapshots_(std::move(bindAssets)) { } @@ -76,17 +76,18 @@ DBStatus RdbCloud::Query(const std::string &tableName, DBVBucket &extend, std::v { auto [nodes, status] = ConvertQuery(extend); std::shared_ptr cursor = nullptr; + int32_t code = E_OK; if (status == GeneralError::E_OK && !nodes.empty()) { RdbQuery query; query.SetQueryNodes(tableName, std::move(nodes)); - cursor = cloudDB_->Query(query, ValueProxy::Convert(std::move(extend))); + std::tie(code, cursor) = cloudDB_->Query(query, ValueProxy::Convert(std::move(extend))); } else { - cursor = cloudDB_->Query(tableName, ValueProxy::Convert(std::move(extend))); + std::tie(code, cursor) = cloudDB_->Query(tableName, ValueProxy::Convert(std::move(extend))); } - if (cursor == nullptr) { + if (cursor == nullptr || code != E_OK) { ZLOGE("cursor is null, table:%{public}s, extend:%{public}zu", Anonymous::Change(tableName).c_str(), extend.size()); - return ConvertStatus(static_cast(E_ERROR)); + return ConvertStatus(static_cast(code != E_OK ? code : E_ERROR)); } int32_t count = cursor->GetCount(); data.reserve(count); @@ -305,11 +306,11 @@ void RdbCloud::PostEvent(DistributedData::Value& value, DataBucket& extend, std: void RdbCloud::PostEventAsset(DistributedData::Asset& asset, DataBucket& extend, std::set& skipAssets, DistributedData::AssetEvent eventId) { - if (snapshots_->bindAssets == nullptr) { + if (snapshots_ == nullptr) { return; } - auto it = snapshots_->bindAssets->find(asset.uri); - if (it == snapshots_->bindAssets->end() || it->second == nullptr) { + auto it = snapshots_->find(asset.uri); + if (it == snapshots_->end() || it->second == nullptr) { return; } diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h index 1a3f37e50aa9f8c49657065bf11939a2607d4c48..7901cd75d2186cdf7b9c08afa800228624b9cdce 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h @@ -25,6 +25,8 @@ #include "snapshot/snapshot.h" namespace OHOS::DistributedRdb { +using Snapshot = DistributedData::Snapshot; +using BindAssets = std::shared_ptr>>; class RdbCloud : public DistributedDB::ICloudDb { public: enum FLAG : uint8_t { @@ -35,10 +37,9 @@ public: 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); + explicit RdbCloud(std::shared_ptr cloudDB, BindAssets bindAssets); virtual ~RdbCloud() = default; DBStatus BatchInsert(const std::string &tableName, std::vector &&record, std::vector &extend) override; @@ -67,7 +68,7 @@ private: static void ConvertErrorField(DistributedData::VBuckets& extends); static constexpr int32_t TO_MS = 1000; // s > ms std::shared_ptr cloudDB_; - BindAssets* snapshots_; + const BindAssets snapshots_; uint8_t flag_ = 0; std::mutex mutex_; 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 87e15dacb36123d0f7e274cc81d2bc8772405d4a..d6b43d5beeecb7ad9944735e2aebfe4885c17e1f 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp @@ -26,10 +26,10 @@ #include "cloud/cloud_mark.h" #include "cloud/cloud_store_types.h" #include "cloud/schema_meta.h" +#include "device_sync_app/device_sync_app_manager.h" #include "cloud_service.h" #include "commonevent/data_sync_event.h" -#include "communicator/device_manager_adapter.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter.h" #include "dfx/dfx_types.h" #include "dfx/reporter.h" @@ -38,13 +38,12 @@ #include "metadata/meta_data_manager.h" #include "metadata/secret_key_meta_data.h" #include "rdb_cursor.h" -#include "rdb_helper.h" #include "rdb_query.h" -#include "rdb_result_set_impl.h" #include "relational_store_manager.h" #include "snapshot/bind_event.h" #include "utils/anonymous.h" #include "value_proxy.h" +#include "snapshot/snapshot.h" namespace OHOS::DistributedRdb { using namespace DistributedData; using namespace DistributedDB; @@ -62,6 +61,7 @@ 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 char *LOGOUT_RESERVE_FLAG = "RESERVE#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)); @@ -141,8 +141,9 @@ void RdbGeneralStore::InitStoreInfo(const StoreMetaData &meta) storeInfo_.bundleName = meta.bundleName; storeInfo_.storeName = meta.storeId; storeInfo_.instanceId = meta.instanceId; - storeInfo_.user = std::stoi(meta.user); + storeInfo_.user = std::atoi(meta.user.c_str()); storeInfo_.deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + storeInfo_.path = meta.dataDir; } RelationalStoreDelegate::Option GetOption(const StoreMetaData &meta) @@ -155,21 +156,37 @@ RelationalStoreDelegate::Option GetOption(const StoreMetaData &meta) return option; } +RdbGeneralStore::DBPassword RdbGeneralStore::GetDBPassword(const StoreMetaData &data) +{ + DBPassword dbPassword; + SecretKeyMetaData secretKey; + auto metaKey = data.GetSecretKey(); + if (!MetaDataManager::GetInstance().LoadMeta(metaKey, secretKey, true) || secretKey.sKey.empty()) { + return dbPassword; + } + CryptoManager::CryptoParams decryptParams = { .area = secretKey.area, .userId = data.user, + .nonce = secretKey.nonce }; + auto password = CryptoManager::GetInstance().Decrypt(secretKey.sKey, decryptParams); + if (password.empty()) { + return dbPassword; + } + // update secret key of area or nonce + CryptoManager::GetInstance().UpdateSecretMeta(password, data, metaKey, secretKey); + dbPassword.SetValue(password.data(), password.size()); + password.assign(password.size(), 0); + return dbPassword; +} + 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 = GetOption(meta); + option.isNeedCompressOnSync = true; option.observer = &observer_; if (meta.isEncrypt) { - std::string key = meta.GetSecretKey(); - SecretKeyMetaData secretKeyMeta; - MetaDataManager::GetInstance().LoadMeta(key, secretKeyMeta, true); - std::vector decryptKey; - CryptoManager::GetInstance().Decrypt(meta, secretKeyMeta, decryptKey); - option.passwd.SetValue(decryptKey.data(), decryptKey.size()); - std::fill(decryptKey.begin(), decryptKey.end(), 0); + option.passwd = GetDBPassword(meta); option.isEncryptedDb = meta.isEncrypt; option.cipher = CipherType::AES_256_GCM; for (uint32_t i = 0; i < ITERS_COUNT; ++i) { @@ -197,15 +214,15 @@ RdbGeneralStore::RdbGeneralStore(const StoreMetaData &meta) delegate_->Pragma(PragmaCmd::LOGIC_DELETE_SYNC_DATA, data); } ZLOGI("Get rdb store, tokenId:%{public}u, bundleName:%{public}s, storeName:%{public}s, user:%{public}s," - "isEncrypt:%{public}d, isManualClean:%{public}d, isSearchable:%{public}d, path:%{public}s", - meta.tokenId, meta.bundleName.c_str(), Anonymous::Change(meta.storeId).c_str(), meta.user.c_str(), - meta.isEncrypt, meta.isManualClean, meta.isSearchable, meta.dataDir.c_str()); + "isEncrypt:%{public}d, isManualClean:%{public}d, isSearchable:%{public}d", + meta.tokenId, meta.bundleName.c_str(), Anonymous::Change(meta.storeId).c_str(), meta.user.c_str(), + meta.isEncrypt, meta.isManualClean, meta.isSearchable); } RdbGeneralStore::~RdbGeneralStore() { - ZLOGI("Destruct. BundleName: %{public}s. StoreName: %{public}s. user: %{public}d", storeInfo_.bundleName.c_str(), - Anonymous::Change(storeInfo_.storeName).c_str(), storeInfo_.user); + ZLOGI("Destruct. BundleName: %{public}s. StoreName: %{public}s. user: %{public}d", + storeInfo_.bundleName.c_str(), Anonymous::Change(storeInfo_.storeName).c_str(), storeInfo_.user); manager_.CloseStore(delegate_); delegate_ = nullptr; bindInfo_.loader_ = nullptr; @@ -220,10 +237,10 @@ RdbGeneralStore::~RdbGeneralStore() executor_ = nullptr; } -int32_t RdbGeneralStore::BindSnapshots(std::shared_ptr>> bindAssets) +int32_t RdbGeneralStore::BindSnapshots(BindAssets bindAssets) { - if (snapshots_.bindAssets == nullptr) { - snapshots_.bindAssets = bindAssets; + if (snapshots_ == nullptr) { + snapshots_ = bindAssets; } return GenErr::E_OK; } @@ -255,14 +272,15 @@ int32_t RdbGeneralStore::Bind(const Database &database, const std::map lock(rdbCloudMutex_); - rdbCloud_ = std::make_shared(bindInfo_.db_, &snapshots_); - rdbLoader_ = std::make_shared(bindInfo_.loader_, &snapshots_); + rdbCloud_ = std::make_shared(bindInfo_.db_, snapshots_); + rdbLoader_ = std::make_shared(bindInfo_.loader_, snapshots_); } DistributedDB::CloudSyncConfig dbConfig; dbConfig.maxUploadCount = config.maxNumber; dbConfig.maxUploadSize = config.maxSize; dbConfig.maxRetryConflictTimes = config.maxRetryConflictTimes; + dbConfig.isSupportEncrypt = config.isSupportEncrypt; DBSchema schema = GetDBSchema(database); std::shared_lock lock(rwMutex_); if (delegate_ == nullptr) { @@ -295,7 +313,8 @@ int32_t RdbGeneralStore::Close(bool isForce) return GeneralError::E_OK; } auto [dbStatus, downloadCount] = delegate_->GetDownloadingAssetsCount(); - if (!isForce && (delegate_->GetCloudSyncTaskCount() > 0 || downloadCount > 0)) { + if (!isForce && + (delegate_->GetCloudSyncTaskCount() > 0 || downloadCount > 0 || delegate_->GetDeviceSyncTaskCount() > 0)) { return GeneralError::E_BUSY; } auto status = manager_.CloseStore(delegate_); @@ -331,7 +350,7 @@ int32_t RdbGeneralStore::Execute(const std::string &table, const std::string &sq auto status = delegate_->ExecuteSql({ sql, {}, false }, changedData); if (status != DBStatus::OK) { ZLOGE("Execute failed! ret:%{public}d, sql:%{public}s, data size:%{public}zu", status, - Anonymous::Change(sql).c_str(), changedData.size()); + Anonymous::Change(sql).c_str(), changedData.size()); if (status == DBStatus::BUSY) { return GeneralError::E_BUSY; } @@ -402,8 +421,8 @@ int32_t RdbGeneralStore::Insert(const std::string &table, VBuckets &&values) if (IsPrintLog(status)) { auto time = static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); - ZLOGE("Failed! ret:%{public}d, sql:%{public}s, data size:%{public}zu times %{public}" PRIu64 ".", status, - Anonymous::Change(sql).c_str(), changedData.size(), time); + ZLOGE("Failed! ret:%{public}d, sql:%{public}s, data size:%{public}zu times %{public}" PRIu64 ".", + status, Anonymous::Change(sql).c_str(), changedData.size(), time); } return GeneralError::E_ERROR; } @@ -463,8 +482,8 @@ int32_t RdbGeneralStore::Update(const std::string &table, const std::string &set } auto status = delegate_->ExecuteSql({ sqlIn, std::move(bindArgs), false }, changedData); if (status != DBStatus::OK) { - ZLOGE("Failed! ret:%{public}d, sql:%{public}s, data size:%{public}zu", status, - Anonymous::Change(sqlIn).c_str(), changedData.size()); + ZLOGE("Failed! ret:%{public}d, sql:%{public}s, data size:%{public}zu", status, Anonymous::Change(sqlIn).c_str(), + changedData.size()); return GeneralError::E_ERROR; } return GeneralError::E_OK; @@ -494,8 +513,8 @@ int32_t RdbGeneralStore::Replace(const std::string &table, VBucket &&value) } auto status = delegate_->ExecuteSql({ sql, std::move(bindArgs) }, changedData); if (status != DBStatus::OK) { - ZLOGE("Replace failed! ret:%{public}d, table:%{public}s, sql:%{public}s, fields:%{public}s", status, - Anonymous::Change(table).c_str(), Anonymous::Change(sql).c_str(), columnSql.c_str()); + ZLOGE("Replace failed! ret:%{public}d, table:%{public}s, sql:%{public}s, fields:%{public}s", + status, Anonymous::Change(table).c_str(), Anonymous::Change(sql).c_str(), columnSql.c_str()); if (status == DBStatus::BUSY) { return GeneralError::E_BUSY; } @@ -509,7 +528,7 @@ int32_t RdbGeneralStore::Delete(const std::string &table, const std::string &sql return 0; } -std::pair> 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_); @@ -541,7 +560,7 @@ std::pair> RdbGeneralStore::Query(const std::st return { GeneralError::E_ERROR, nullptr }; } auto cursor = RemoteQuery(*rdbQuery->GetDevices().begin(), rdbQuery->GetRemoteCondition()); - return { cursor != nullptr ? GeneralError::E_OK : GeneralError::E_ERROR, cursor }; + return { cursor != nullptr ? GeneralError::E_OK : GeneralError::E_ERROR, cursor}; } return { GeneralError::E_ERROR, nullptr }; } @@ -564,7 +583,7 @@ int32_t RdbGeneralStore::CleanTrackerData(const std::string &tableName, int64_t 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(tableName).c_str()); + Anonymous::Change(storeInfo_.storeName).c_str(), Anonymous::Change(tableName).c_str()); return GeneralError::E_ERROR; } @@ -629,9 +648,8 @@ std::pair RdbGeneralStore::Sync(const Devices &devices, GenQue std::shared_lock lock(rwMutex_); if (delegate_ == nullptr) { ZLOGE("store already closed! devices count:%{public}zu, the 1st:%{public}s, mode:%{public}d, " - "wait:%{public}d", - devices.size(), devices.empty() ? "null" : Anonymous::Change(*devices.begin()).c_str(), syncParam.mode, - syncParam.wait); + "wait:%{public}d", devices.size(), + devices.empty() ? "null" : Anonymous::Change(*devices.begin()).c_str(), syncParam.mode, syncParam.wait); return { GeneralError::E_ALREADY_CLOSED, DBStatus::OK }; } auto dbStatus = DistributedDB::INVALID_ARGS; @@ -702,8 +720,8 @@ VBuckets RdbGeneralStore::ExtractExtend(VBuckets &values) const return extends; } -std::string RdbGeneralStore::BuildSql(const std::string &table, const std::string &statement, - const std::vector &columns) const +std::string RdbGeneralStore::BuildSql( + const std::string &table, const std::string &statement, const std::vector &columns) const { std::string sql = "select "; sql.append(CLOUD_GID); @@ -790,7 +808,8 @@ RdbGeneralStore::DBBriefCB RdbGeneralStore::GetDBBriefCB(DetailAsync async) if (!async) { return [](auto &) {}; } - return [async = std::move(async)](const std::map> &result) { + return [async = std::move(async)]( + const std::map> &result) { DistributedData::GenDetails details; for (auto &[key, tables] : result) { auto &value = details[key]; @@ -811,7 +830,7 @@ RdbGeneralStore::DBProcessCB RdbGeneralStore::GetDBProcessCB(DetailAsync async, { std::shared_lock lock(asyncMutex_); return [async, autoAsync = async_, highMode, storeInfo = storeInfo_, flag = syncNotifyFlag_, syncMode, syncId, - rdbCloud = GetRdbCloud()](const std::map &processes) { + rdbCloud = GetRdbCloud()](const std::map &processes) { DistributedData::GenDetails details; for (auto &[id, process] : processes) { bool isDownload = false; @@ -833,9 +852,9 @@ RdbGeneralStore::DBProcessCB RdbGeneralStore::GetDBProcessCB(DetailAsync async, 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; + ? value.downLoadInfo.insertCount + value.downLoadInfo.updateCount + + value.downLoadInfo.deleteCount + : 0; totalCount += table.download.total; } if (process.process == FINISHED) { @@ -853,8 +872,8 @@ RdbGeneralStore::DBProcessCB RdbGeneralStore::GetDBProcessCB(DetailAsync async, async(details); } - if (highMode == AUTO_SYNC_MODE && autoAsync && - (details.empty() || details.begin()->second.code != E_SYNC_TASK_MERGED)) { + if (highMode == AUTO_SYNC_MODE && autoAsync + && (details.empty() || details.begin()->second.code != E_SYNC_TASK_MERGED)) { autoAsync(details); } }; @@ -897,6 +916,20 @@ void RdbGeneralStore::Report(const std::string &faultType, int32_t errCode, cons Reporter::GetInstance()->CloudSyncFault()->Report(msg); } +int32_t RdbGeneralStore::SetReference(const std::vector &references) +{ + std::vector properties; + for (const auto &reference : references) { + properties.push_back({reference.sourceTable, reference.targetTable, reference.refFields}); + } + auto status = delegate_->SetReference(properties); + if (status != DistributedDB::DBStatus::OK && status != DistributedDB::DBStatus::PROPERTY_CHANGED) { + ZLOGE("distributed table set reference failed, err:%{public}d", status); + return GeneralError::E_ERROR; + } + return GeneralError::E_OK; +} + int32_t RdbGeneralStore::SetDistributedTables(const std::vector &tables, int32_t type, const std::vector &references) { @@ -913,22 +946,24 @@ int32_t RdbGeneralStore::SetDistributedTables(const std::vector &ta ZLOGE("create distributed table failed, table:%{public}s, err:%{public}d", Anonymous::Change(table).c_str(), dBStatus); Report(FT_OPEN_STORE, static_cast(Fault::CSF_GS_CREATE_DISTRIBUTED_TABLE), - "SetDistributedTables ret=" + std::to_string(static_cast(dBStatus))); + "SetDistributedTables: set table(" + Anonymous::Change(table) + ") =" + + std::to_string(static_cast(dBStatus))); return GeneralError::E_ERROR; } } - std::vector properties; - for (const auto &reference : references) { - properties.push_back({ reference.sourceTable, reference.targetTable, reference.refFields }); - } - auto status = delegate_->SetReference(properties); - if (status != DistributedDB::DBStatus::OK && status != DistributedDB::DBStatus::PROPERTY_CHANGED) { - ZLOGE("distributed table set reference failed, err:%{public}d", status); - return GeneralError::E_ERROR; + if (type == DistributedTableType::DISTRIBUTED_CLOUD) { + auto status = SetReference(references); + if (status != GeneralError::E_OK) { + Report(FT_OPEN_STORE, static_cast(Fault::CSF_GS_CREATE_DISTRIBUTED_TABLE), + "SetDistributedTables: set reference=" + std::to_string(static_cast(status))); + return GeneralError::E_ERROR; + } } auto [exist, database] = GetDistributedSchema(observer_.meta_); - if (exist) { - delegate_->SetDistributedSchema(GetGaussDistributedSchema(database)); + if (exist && type == DistributedTableType::DISTRIBUTED_DEVICE) { + auto force = DeviceSyncAppManager::GetInstance().Check( + {observer_.meta_.appId, observer_.meta_.bundleName, database.version}); + delegate_->SetDistributedSchema(GetGaussDistributedSchema(database), force); } CloudMark metaData(storeInfo_); if (MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true) && metaData.isClearWaterMark) { @@ -950,9 +985,10 @@ int32_t RdbGeneralStore::SetDistributedTables(const std::vector &ta void RdbGeneralStore::SetConfig(const StoreConfig &storeConfig) { std::shared_lock lock(rwMutex_); - if (delegate_ == nullptr) { + if (delegate_ == nullptr) { ZLOGE("database already closed!, tableMode is :%{public}d", - storeConfig.tableMode.has_value() ? static_cast(storeConfig.tableMode.value()) : -1); + storeConfig.tableMode.has_value() ? static_cast(storeConfig.tableMode.value()) : -1); + return; } if (storeConfig.tableMode.has_value()) { RelationalStoreDelegate::StoreConfig config; @@ -981,8 +1017,8 @@ int32_t RdbGeneralStore::SetTrackerTable(const std::string &tableName, const std return GeneralError::E_WITH_INVENTORY_DATA; } if (status != DBStatus::OK) { - ZLOGE("Set tracker table failed! ret:%{public}d, database:%{public}s, tables name:%{public}s", status, - Anonymous::Change(storeInfo_.storeName).c_str(), Anonymous::Change(tableName).c_str()); + ZLOGE("Set tracker table failed! ret:%{public}d, database:%{public}s, tables name:%{public}s", + status, Anonymous::Change(storeInfo_.storeName).c_str(), Anonymous::Change(tableName).c_str()); return GeneralError::E_ERROR; } return GeneralError::E_OK; @@ -1083,8 +1119,8 @@ void RdbGeneralStore::OnSyncFinish(const StoreInfo &storeInfo, uint32_t flag, ui return; } StoreInfo info = storeInfo; - auto evt = - std::make_unique(std::move(info), syncMode, DataSyncEvent::DataSyncStatus::FINISH, traceId); + auto evt = std::make_unique(std::move(info), syncMode, DataSyncEvent::DataSyncStatus::FINISH, + traceId); EventCenter::GetInstance().PostEvent(std::move(evt)); } @@ -1116,15 +1152,16 @@ std::vector RdbGeneralStore::GetIntersection(std::vector res; for (auto &it : syncTables) { - if (localTables.count(it) && localTables.count(RelationalStoreManager::GetDistributedLogTableName(it))) { + if (localTables.count(it) && + localTables.count(RelationalStoreManager::GetDistributedLogTableName(it))) { res.push_back(std::move(it)); } } return res; } -void RdbGeneralStore::ObserverProxy::PostDataChange(const StoreMetaData &meta, const std::vector &tables, - ChangeType type) +void RdbGeneralStore::ObserverProxy::PostDataChange(const StoreMetaData &meta, + const std::vector &tables, ChangeType type) { RemoteChangeEvent::DataInfo info; info.userId = meta.user; @@ -1166,9 +1203,9 @@ void RdbGeneralStore::ObserverProxy::OnChange(DBOrigin origin, const std::string ZLOGD("store:%{public}s table:%{public}s data change from :%{public}s", Anonymous::Change(storeId_).c_str(), Anonymous::Change(data.tableName).c_str(), Anonymous::Change(originalId).c_str()); GenOrigin genOrigin; - genOrigin.origin = (origin == DBOrigin::ORIGIN_LOCAL) ? GenOrigin::ORIGIN_LOCAL - : (origin == DBOrigin::ORIGIN_CLOUD) ? GenOrigin::ORIGIN_CLOUD - : GenOrigin::ORIGIN_NEARBY; + genOrigin.origin = (origin == DBOrigin::ORIGIN_LOCAL) + ? GenOrigin::ORIGIN_LOCAL + : (origin == DBOrigin::ORIGIN_CLOUD) ? GenOrigin::ORIGIN_CLOUD : GenOrigin::ORIGIN_NEARBY; genOrigin.dataType = data.type == DistributedDB::ASSET ? GenOrigin::ASSET_DATA : GenOrigin::BASIC_DATA; genOrigin.id.push_back(originalId); genOrigin.store = storeId_; @@ -1190,8 +1227,8 @@ void RdbGeneralStore::ObserverProxy::OnChange(DBOrigin origin, const std::string info.push_back(std::move(value)); continue; } - auto deleteKey = std::get_if(&value); - if (deleteKey != nullptr && (*deleteKey == LOGOUT_DELETE_FLAG)) { + auto key = std::get_if(&value); + if (key != nullptr && (*key == LOGOUT_DELETE_FLAG || *key == LOGOUT_RESERVE_FLAG)) { // notify to start app notifyFlag = true; } @@ -1199,8 +1236,11 @@ void RdbGeneralStore::ObserverProxy::OnChange(DBOrigin origin, const std::string } } if (notifyFlag) { - ZLOGI("post data change for cleaning cloud data"); - PostDataChange(meta_, {}, CLOUD_DATA_CLEAN); + ZLOGI("post data change for cleaning cloud data. store:%{public}s table:%{public}s data change from " + ":%{public}s", + Anonymous::Change(storeId_).c_str(), Anonymous::Change(data.tableName).c_str(), + Anonymous::Change(originalId).c_str()); + PostDataChange(meta_, {}, CLOUD_LOGOUT); } if (!data.field.empty()) { fields[std::move(data.tableName)] = std::move(*(data.field.begin())); @@ -1264,7 +1304,7 @@ Executor::Task RdbGeneralStore::GetFinishTask(SyncId syncId) }); if (cb != nullptr) { ZLOGW("database:%{public}s syncId:%{public}" PRIu64 " miss finished. ", - Anonymous::Change(storeInfo_.storeName).c_str(), syncId); + Anonymous::Change(storeInfo_.storeName).c_str(), syncId); std::map result; result.insert({ "", { DistributedDB::FINISHED, DBStatus::DB_ERROR } }); cb(result); @@ -1289,7 +1329,7 @@ void RdbGeneralStore::RemoveTasks() tasks_->EraseIf([&cbs, &taskIds, store = storeInfo_.storeName](SyncId syncId, const FinishTask &task) { if (task.cb != nullptr) { ZLOGW("database:%{public}s syncId:%{public}" PRIu64 " miss finished. ", Anonymous::Change(store).c_str(), - syncId); + syncId); } cbs.push_back(std::move(task.cb)); taskIds.push_back(task.taskId); @@ -1305,7 +1345,7 @@ void RdbGeneralStore::RemoveTasks() } }; if (executor_ != nullptr) { - for (auto taskId : taskIds) { + for (auto taskId: taskIds) { executor_->Remove(taskId, true); } executor_->Execute([cbs, func]() { 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 98b5d2ed650938395fce3e01b7333fc7f07e821a..64296b5fbb443819e9160e088431566279d80cda 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h @@ -43,8 +43,9 @@ public: using GenErr = DistributedData::GeneralError; using RdbStore = OHOS::NativeRdb::RdbStore; using Reference = DistributedData::Reference; + using DBPassword = DistributedDB::CipherPassword; using Snapshot = DistributedData::Snapshot; - using BindAssets = DistributedData::BindAssets; + using BindAssets = std::shared_ptr>>; explicit RdbGeneralStore(const StoreMetaData &meta); ~RdbGeneralStore(); @@ -83,7 +84,7 @@ public: void SetConfig(const StoreConfig &storeConfig) override; int32_t AddRef() override; int32_t Release() override; - int32_t BindSnapshots(std::shared_ptr>> bindAssets) override; + int32_t BindSnapshots(BindAssets bindAssets) override; int32_t MergeMigratedData(const std::string &tableName, VBuckets&& values) override; int32_t CleanTrackerData(const std::string &tableName, int64_t cursor) override; std::pair LockCloudDB() override; @@ -93,6 +94,7 @@ public: private: RdbGeneralStore(const RdbGeneralStore& rdbGeneralStore); RdbGeneralStore& operator=(const RdbGeneralStore& rdbGeneralStore); + int32_t SetReference(const std::vector &references); using RdbDelegate = DistributedDB::RelationalStoreDelegate; using RdbManager = DistributedDB::RelationalStoreManager; using SyncProcess = DistributedDB::SyncProcess; @@ -130,7 +132,7 @@ private: private: enum ChangeType { CLOUD_DATA_CHANGE = 0, - CLOUD_DATA_CLEAN + CLOUD_LOGOUT, }; void PostDataChange(const StoreMetaData &meta, const std::vector &tables, ChangeType type); friend RdbGeneralStore; @@ -158,6 +160,7 @@ private: std::pair DoCloudSync(const Devices &devices, const DistributedDB::Query &dbQuery, const DistributedData::SyncParam &syncParam, bool isPriority, DetailAsync async); void Report(const std::string &faultType, int32_t errCode, const std::string &appendix); + DBPassword GetDBPassword(const StoreMetaData &data); ObserverProxy observer_; RdbManager manager_; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_schema_config.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_schema_config.cpp index 8bfff9e00c2b3b20a4da78bdfe07b7044d215df3..8c1337e639c39f1b145cce72c508f03bef9ee505 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_schema_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_schema_config.cpp @@ -39,7 +39,6 @@ bool RdbSchemaConfig::GetDistributedSchema(const StoreMetaData &meta, Database & if (!InitBundleInfo(meta.bundleName, std::atoi(meta.user.c_str()), bundleInfo)) { return false; } - std::string storeName = meta.storeId; auto ret = GetSchemaFromHap(bundleInfo, meta.storeId, database); if (ret) { database.user = meta.user; @@ -99,7 +98,7 @@ bool RdbSchemaConfig::GetSchemaFromHap( std::string jsonData(fileContent.get(), fileContent.get() + length); DbSchema databases; databases.Unmarshall(jsonData); - for (auto &schema : databases.databases) { + for (const auto &schema : databases.databases) { if (schema.name == storeName) { database = schema; return true; 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 886de4a0bd788d14b13c266698abc3c7d89304bb..43c0c7cfb7742388bdae43d9884de443089ea025 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -18,6 +18,7 @@ #include "abs_rdb_predicates.h" #include "accesstoken_kit.h" #include "account/account_delegate.h" +#include "bootstrap.h" #include "changeevent/remote_change_event.h" #include "checker/checker_manager.h" #include "cloud/change_event.h" @@ -26,7 +27,6 @@ #include "cloud/make_query_event.h" #include "cloud/schema_meta.h" #include "communicator/device_manager_adapter.h" -#include "crypto_manager.h" #include "device_matrix.h" #include "directory/directory_manager.h" #include "dump/dump_manager.h" @@ -40,11 +40,13 @@ #include "metadata/store_debug_info.h" #include "metadata/store_meta_data.h" #include "metadata/store_meta_data_local.h" +#include "permit_delegate.h" #include "rdb_general_store.h" +#include "rdb_hiview_adapter.h" #include "rdb_notifier_proxy.h" #include "rdb_query.h" -#include "rdb_schema_config.h" #include "rdb_result_set_impl.h" +#include "rdb_schema_config.h" #include "rdb_watcher.h" #include "store/general_store.h" #include "tokenid_kit.h" @@ -53,9 +55,7 @@ #include "utils/constant.h" #include "utils/converter.h" #include "xcollie.h" -#include "permit_delegate.h" -#include "bootstrap.h" -#include "rdb_hiview_adapter.h" +using OHOS::DistributedData::AccountDelegate; using OHOS::DistributedData::Anonymous; using OHOS::DistributedData::CheckerManager; using OHOS::DistributedData::MetaDataManager; @@ -71,6 +71,7 @@ using system_clock = std::chrono::system_clock; constexpr uint32_t ITERATE_TIMES = 10000; constexpr uint32_t ALLOW_ONLINE_AUTO_SYNC = 8; +constexpr int32_t VALID_PARAM_LENGTH = 2; const size_t KEY_COUNT = 2; namespace OHOS::DistributedRdb { __attribute__((used)) RdbServiceImpl::Factory RdbServiceImpl::factory_; @@ -102,7 +103,7 @@ RdbServiceImpl::RdbServiceImpl() { ZLOGI("construct"); DistributedDB::RelationalStoreManager::SetAutoLaunchRequestCallback( - [this](const std::string &identifier, DistributedDB::AutoLaunchParam ¶m) { + [this](const std::string& identifier, DistributedDB::AutoLaunchParam ¶m) { return ResolveAutoLaunch(identifier, param); }); RegisterEvent(); @@ -141,7 +142,6 @@ 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; - GetDBPassword(entry, param.option.passwd); } AutoCache::GetInstance().GetStore(entry, GetWatchers(entry.tokenId, entry.storeId)); return true; @@ -179,22 +179,63 @@ int32_t RdbServiceImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const return E_OK; } -bool RdbServiceImpl::CheckAccess(const std::string& bundleName, const std::string& storeName) +int32_t RdbServiceImpl::OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) +{ + ZLOGI("rdb exit, tokenId:%{public}d, pid:%{public}d, bundleName:%{public}s.", tokenId, pid, bundleName.c_str()); + 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 (!agents.empty()) { + return true; + } + destroyed = true; + return false; + }); + if (destroyed) { + auto stores = AutoCache::GetInstance().GetStoresIfPresent(tokenId); + for (auto store : stores) { + if (store != nullptr) { + store->UnregisterDetailProgressObserver(); + } + } + AutoCache::GetInstance().Enable(tokenId); + } + heartbeatTaskIds_.Erase(pid); + return E_OK; +} + +bool RdbServiceImpl::IsValidAccess(const std::string& bundleName, const std::string& storeName) { CheckerManager::StoreInfo storeInfo; storeInfo.uid = IPCSkeleton::GetCallingUid(); storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); storeInfo.bundleName = bundleName; storeInfo.storeId = RemoveSuffix(storeName); - return !CheckerManager::GetInstance().GetAppId(storeInfo).empty(); + + return CheckerManager::GetInstance().IsValid(storeInfo); } -std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device, const std::string &table) +std::string RdbServiceImpl::ObtainDistributedTableName(const RdbSyncerParam ¶m, const std::string &device, + const std::string &table) { - ZLOGI("device=%{public}s table=%{public}s", Anonymous::Change(device).c_str(), table.c_str()); - auto uuid = DmAdapter::GetInstance().GetUuidByNetworkId(device); + if (!IsValidAccess(param.bundleName_, "")) { + ZLOGE("bundleName:%{public}s. Permission error", param.bundleName_.c_str()); + return ""; + } + auto tokenId = IPCSkeleton::GetCallingTokenID(); + std::string appId = " "; + if (AccessTokenKit::GetTokenTypeFlag(tokenId) == Security::AccessToken::TOKEN_HAP) { + auto uid = IPCSkeleton::GetCallingUid(); + appId = CheckerManager::GetInstance().GetAppId({ uid, tokenId, param.bundleName_ }); + } + auto uuid = DmAdapter::GetInstance().CalcClientUuid(appId, DmAdapter::GetInstance().ToUUID(device)); if (uuid.empty()) { - ZLOGE("get uuid failed"); + ZLOGE("get uuid failed, bundle:%{public}s, deviceId:%{public}s, table:%{public}s", param.bundleName_.c_str(), + Anonymous::Change(device).c_str(), Anonymous::Change(table).c_str()); return ""; } return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table); @@ -203,7 +244,7 @@ std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device int32_t RdbServiceImpl::InitNotifier(const RdbSyncerParam ¶m, const sptr notifier) { XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY); - if (!CheckAccess(param.bundleName_, "")) { + if (!IsValidAccess(param.bundleName_, "")) { ZLOGE("bundleName:%{public}s. Permission error", param.bundleName_.c_str()); return RDB_ERROR; } @@ -242,13 +283,13 @@ std::shared_ptr RdbServiceImpl::GetStore(const Rd void RdbServiceImpl::UpdateMeta(const StoreMetaData &meta, const StoreMetaData &localMeta, AutoCache::Store store) { StoreMetaData syncMeta; - bool isCreatedSync = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), syncMeta); + bool isCreatedSync = MetaDataManager::GetInstance().LoadMeta(meta.GetKeyWithoutPath(), syncMeta); if (!isCreatedSync || localMeta != syncMeta) { ZLOGI("save sync meta. bundle:%{public}s store:%{public}s type:%{public}d->%{public}d " "encrypt:%{public}d->%{public}d , area:%{public}d->%{public}d", meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), syncMeta.storeType, meta.storeType, syncMeta.isEncrypt, meta.isEncrypt, syncMeta.area, meta.area); - MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), localMeta); + MetaDataManager::GetInstance().SaveMeta(meta.GetKeyWithoutPath(), localMeta); } Database dataBase; if (RdbSchemaConfig::GetDistributedSchema(localMeta, dataBase) && !dataBase.name.empty() && @@ -261,7 +302,7 @@ void RdbServiceImpl::UpdateMeta(const StoreMetaData &meta, const StoreMetaData & int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam ¶m, const std::vector &tables, const std::vector &references, bool isRebuild, int32_t type) { - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidParam(param) || !IsValidAccess(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; @@ -279,14 +320,16 @@ int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam ¶m, const Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; } - auto store = GetStore(param); + auto store = GetStore(meta); if (store == nullptr) { - ZLOGE("bundleName:%{public}s, storeName:%{public}s. GetStore failed", param.bundleName_.c_str(), - Anonymous::Change(param.storeName_).c_str()); + ZLOGE("bundle:%{public}s, %{public}s.", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; } + StoreMetaMapping metaMapping(localMeta); + MetaDataManager::GetInstance().LoadMeta(metaMapping.GetKey(), metaMapping, true); if (type == DistributedTableType::DISTRIBUTED_DEVICE) { UpdateMeta(meta, localMeta, store); + metaMapping.devicePath = meta.dataDir; } else if (type == DistributedTableType::DISTRIBUTED_CLOUD) { if (localMeta.asyncDownloadAsset != param.asyncDownloadAsset_ || localMeta.enableCloud != param.enableCloud_) { ZLOGI("update meta, bundleName:%{public}s, storeName:%{public}s, asyncDownloadAsset? [%{public}d -> " @@ -297,7 +340,10 @@ int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam ¶m, const localMeta.enableCloud = param.enableCloud_; MetaDataManager::GetInstance().SaveMeta(localMeta.GetKey(), localMeta, true); } + metaMapping.cloudPath = meta.dataDir; } + metaMapping = localMeta; + MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true); std::vector relationships; for (const auto &reference : references) { DistributedData::Reference relationship = { reference.sourceTable, reference.targetTable, reference.refFields }; @@ -377,20 +423,21 @@ RdbServiceImpl::DetailAsync RdbServiceImpl::GetCallbacks(uint32_t tokenId, const std::pair> RdbServiceImpl::RemoteQuery(const RdbSyncerParam& param, const std::string& device, const std::string& sql, const std::vector& selectionArgs) { - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidParam(param) || !IsValidAccess(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, nullptr }; } - auto store = GetStore(param); + StoreMetaData meta = GetStoreMetaData(param); + auto store = GetStore(meta); if (store == nullptr) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. GetStore failed", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return { RDB_ERROR, nullptr }; } - StoreMetaData meta = GetStoreMetaData(param); - std::vector devices = {DmAdapter::GetInstance().ToUUID(device)}; - if (IsNeedMetaSync(meta, devices) && !MetaDataManager::GetInstance().Sync(devices, [](auto &results) {}, true)) { + std::vector devices = { DmAdapter::GetInstance().ToUUID(device) }; + if (IsNeedMetaSync(meta, devices) && !MetaDataManager::GetInstance().Sync( + devices, [](auto &results) {}, true)) { ZLOGW("bundleName:%{public}s, storeName:%{public}s. meta sync failed", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); } @@ -406,7 +453,7 @@ std::pair> RdbServiceImpl::R int32_t RdbServiceImpl::Sync(const RdbSyncerParam ¶m, const Option &option, const PredicatesMemo &predicates, const AsyncDetail &async) { - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidParam(param) || !IsValidAccess(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; @@ -422,7 +469,8 @@ int32_t RdbServiceImpl::Sync(const RdbSyncerParam ¶m, const Option &option, int RdbServiceImpl::DoSync(const RdbSyncerParam ¶m, const RdbService::Option &option, const PredicatesMemo &predicates, const AsyncDetail &async) { - auto store = GetStore(param); + StoreMetaData meta = GetStoreMetaData(param); + auto store = GetStore(meta); if (store == nullptr) { return RDB_ERROR; } @@ -432,10 +480,9 @@ int RdbServiceImpl::DoSync(const RdbSyncerParam ¶m, const RdbService::Option : DmAdapter::ToUUID(rdbQuery.GetDevices()); 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]( + auto complete = [this, rdbQuery, store, pid, syncParam, tokenId, seq = option.seqNum]( const auto &results) mutable { auto ret = ProcessResult(results); store->Sync( @@ -466,7 +513,7 @@ bool RdbServiceImpl::IsNeedMetaSync(const StoreMetaData &meta, const std::vector CapMetaData capMeta; auto capKey = CapMetaRow::GetKeyFor(uuid); if (!MetaDataManager::GetInstance().LoadMeta(std::string(capKey.begin(), capKey.end()), capMeta) || - !MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData)) { + !MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)) { isAfterMeta = true; break; } @@ -551,7 +598,7 @@ void RdbServiceImpl::DoCloudSync(const RdbSyncerParam ¶m, const RdbService:: async(HandleGenDetails(details)); } }; - auto highMode = (!predicates.tables_.empty() && option.mode == DistributedData::GeneralStore::CLOUD_ClOUD_FIRST) + auto highMode = (!predicates.tables_.empty() && option.mode == DistributedData::GeneralStore::CLOUD_CLOUD_FIRST) ? GeneralStore::ASSETS_SYNC_MODE : (option.isAutoSync ? GeneralStore::AUTO_SYNC_MODE : GeneralStore::MANUAL_SYNC_MODE); auto mixMode = static_cast(GeneralStore::MixMode(option.mode, highMode)); @@ -566,7 +613,7 @@ void RdbServiceImpl::DoCloudSync(const RdbSyncerParam ¶m, const RdbService:: } int32_t RdbServiceImpl::Subscribe(const RdbSyncerParam ¶m, const SubscribeOption &option, - RdbStoreObserver *observer) + std::shared_ptr observer) { if (option.mode < 0 || option.mode >= SUBSCRIBE_MODE_MAX) { ZLOGE("mode:%{public}d error", option.mode); @@ -588,15 +635,14 @@ int32_t RdbServiceImpl::Subscribe(const RdbSyncerParam ¶m, const SubscribeOp return true; }); if (isCreate) { - auto subUser = GetSubUser(param.subUser_); - AutoCache::GetInstance().SetObserver(tokenId, RemoveSuffix(param.storeName_), - GetWatchers(tokenId, param.storeName_), subUser); + AutoCache::GetInstance().SetObserver(tokenId, GetWatchers(tokenId, param.storeName_), + GetPath(param), RemoveSuffix(param.storeName_)); } return RDB_OK; } int32_t RdbServiceImpl::UnSubscribe(const RdbSyncerParam ¶m, const SubscribeOption &option, - RdbStoreObserver *observer) + std::shared_ptr observer) { if (option.mode < 0 || option.mode >= SUBSCRIBE_MODE_MAX) { ZLOGE("mode:%{public}d error", option.mode); @@ -618,9 +664,8 @@ int32_t RdbServiceImpl::UnSubscribe(const RdbSyncerParam ¶m, const Subscribe return true; }); if (destroyed) { - auto subUser = GetSubUser(param.subUser_); - AutoCache::GetInstance().SetObserver(tokenId, RemoveSuffix(param.storeName_), - GetWatchers(tokenId, param.storeName_), subUser); + AutoCache::GetInstance().SetObserver(tokenId, GetWatchers(tokenId, param.storeName_), + GetPath(param), RemoveSuffix(param.storeName_)); } return RDB_OK; } @@ -672,15 +717,20 @@ int32_t RdbServiceImpl::UnregisterAutoSyncCallback(const RdbSyncerParam& param, int32_t RdbServiceImpl::Delete(const RdbSyncerParam ¶m) { XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY); + if (!IsValidAccess(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 tokenId = IPCSkeleton::GetCallingTokenID(); - auto subUser = GetSubUser(param.subUser_); - AutoCache::GetInstance().CloseStore(tokenId, RemoveSuffix(param.storeName_), subUser); - RdbSyncerParam tmpParam = param; - HapTokenInfo hapTokenInfo; - AccessTokenKit::GetHapTokenInfo(tokenId, hapTokenInfo); - tmpParam.bundleName_ = hapTokenInfo.bundleName; - auto storeMeta = GetStoreMetaData(tmpParam); - MetaDataManager::GetInstance().DelMeta(storeMeta.GetKey()); + auto storeMeta = GetStoreMetaData(param); + StoreMetaMapping storeMetaMapping(storeMeta); + MetaDataManager::GetInstance().LoadMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); + if (!MetaDataManager::GetInstance().LoadMeta(storeMeta.GetKey(), storeMeta, true)) { + storeMeta.dataDir = storeMetaMapping.dataDir; + } + AutoCache::GetInstance().CloseStore(tokenId, storeMeta.dataDir, RemoveSuffix(param.storeName_)); + MetaDataManager::GetInstance().DelMeta(storeMeta.GetKeyWithoutPath()); MetaDataManager::GetInstance().DelMeta(storeMeta.GetKey(), true); MetaDataManager::GetInstance().DelMeta(storeMeta.GetKeyLocal(), true); MetaDataManager::GetInstance().DelMeta(storeMeta.GetSecretKey(), true); @@ -690,13 +740,29 @@ int32_t RdbServiceImpl::Delete(const RdbSyncerParam ¶m) MetaDataManager::GetInstance().DelMeta(storeMeta.GetDebugInfoKey(), true); MetaDataManager::GetInstance().DelMeta(storeMeta.GetDfxInfoKey(), true); MetaDataManager::GetInstance().DelMeta(storeMeta.GetCloneSecretKey(), true); + std::vector metaList; + if (MetaDataManager::GetInstance().LoadMeta(storeMeta.GetKeyWithoutPath(), metaList, true) && !metaList.empty()) { + if (storeMetaMapping.cloudPath == storeMetaMapping.dataDir) { + storeMetaMapping.cloudPath = ""; + } + if (storeMetaMapping.searchPath == storeMetaMapping.dataDir) { + storeMetaMapping.searchPath = ""; + } + if (storeMetaMapping.devicePath == storeMetaMapping.dataDir) { + storeMetaMapping.devicePath = ""; + } + storeMetaMapping = metaList[0]; + MetaDataManager::GetInstance().SaveMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); + } else { + MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true); + } return RDB_OK; } std::pair> RdbServiceImpl::QuerySharingResource( const RdbSyncerParam& param, const PredicatesMemo& predicates, const std::vector& columns) { - if (!CheckAccess(param.bundleName_, param.storeName_) || + if (!IsValidAccess(param.bundleName_, param.storeName_) || !TokenIdKit::IsSystemAppByFullTokenID(IPCSkeleton::GetCallingFullTokenID())) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); @@ -737,17 +803,75 @@ std::pair> RdbServiceImpl::AllocResource(StoreI return result; } +bool RdbServiceImpl::IsValidPath(const std::string ¶m) +{ + if ((param.find("/") != std::string::npos) || (param.find("\\") != std::string::npos) || (param == "..")) { + return false; + } + return true; +} + +bool RdbServiceImpl::IsValidCustomDir(const std::string &customDir, int32_t upLimit) +{ + if (customDir.empty()) { + return true; + } + if (customDir[0] == '/') { + return false; + } + std::vector components = Constant::Split(customDir, "/"); + int32_t up = 0; + for (const auto &comp : components) { + if (comp.empty() || comp == ".") { + continue; + } + if (comp != "..") { + up--; + continue; + } + if (++up > upLimit) { + return false; + } + } + return true; +} + +bool RdbServiceImpl::IsValidParam(const RdbSyncerParam ¶m) +{ + if (param.storeName_.find("/") != std::string::npos) { + ZLOGE("storeName is Invalid, storeName is %{public}s.", Anonymous::Change(param.storeName_).c_str()); + return false; + } + if (!IsValidPath(param.bundleName_)) { + ZLOGE("bundleName is Invalid, bundleName is %{public}s.", param.bundleName_.c_str()); + return false; + } + if (!IsValidPath(param.user_)) { + ZLOGE("user is Invalid, user is %{public}s.", param.user_.c_str()); + return false; + } + if (!IsValidPath(param.hapName_)) { + ZLOGE("hapName is Invalid, hapName is %{public}s.", param.hapName_.c_str()); + return false; + } + int32_t upLimit = param.hapName_.empty() ? 1 : VALID_PARAM_LENGTH; + if (!IsValidCustomDir(param.customDir_, upLimit)) { + ZLOGE("customDir is Invalid, customDir is %{public}s.", Anonymous::Change(param.customDir_).c_str()); + return false; + } + return true; +} + int32_t RdbServiceImpl::BeforeOpen(RdbSyncerParam ¶m) { XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY); - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidParam(param) || !IsValidAccess(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); - auto isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true); - if (!isCreated) { + auto [exist, meta] = LoadStoreMetaData(param); + if (!exist) { ZLOGW("bundleName:%{public}s, storeName:%{public}s. no meta", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return RDB_NO_META; @@ -756,7 +880,7 @@ int32_t RdbServiceImpl::BeforeOpen(RdbSyncerParam ¶m) return RDB_OK; } -void RdbServiceImpl::SetReturnParam(StoreMetaData &metadata, RdbSyncerParam ¶m) +void RdbServiceImpl::SetReturnParam(const StoreMetaData &metadata, RdbSyncerParam ¶m) { param.bundleName_ = metadata.bundleName; param.type_ = metadata.storeType; @@ -770,10 +894,53 @@ void RdbServiceImpl::SetReturnParam(StoreMetaData &metadata, RdbSyncerParam &par param.haMode_ = metadata.haMode; } +void RdbServiceImpl::SaveLaunchInfo(StoreMetaData &meta) +{ + RemoteChangeEvent::DataInfo info; + info.bundleName = meta.bundleName; + info.deviceId = meta.deviceId; + info.userId = meta.user; + if (executors_ != nullptr) { + executors_->Schedule(ExecutorPool::INVALID_DELAY, [dataInfo = std::move(info)]() mutable { + auto evt = std::make_unique(RemoteChangeEvent::RDB_META_SAVE, std::move(dataInfo)); + EventCenter::GetInstance().PostEvent(std::move(evt)); + }); + } +} + +void RdbServiceImpl::SaveSecretKeyMeta(const StoreMetaData &metaData, const std::vector &password) +{ + CryptoManager::CryptoParams encryptParams = { .area = metaData.area, .userId = metaData.user }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(password, encryptParams); + if (!encryptKey.empty() && !encryptParams.nonce.empty()) { + SecretKeyMetaData secretKey; + secretKey.storeType = metaData.storeType; + secretKey.area = metaData.area; + secretKey.sKey = encryptKey; + secretKey.nonce = encryptParams.nonce; + auto time = system_clock::to_time_t(system_clock::now()); + secretKey.time = { reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time) }; + MetaDataManager::GetInstance().SaveMeta(metaData.GetSecretKey(), secretKey, true); + } + SecretKeyMetaData cloneKey; + auto metaKey = metaData.GetCloneSecretKey(); + // update clone secret key with area + if (MetaDataManager::GetInstance().LoadMeta(metaKey, cloneKey, true) && !cloneKey.sKey.empty() && + (cloneKey.nonce.empty() || cloneKey.area < 0)) { + CryptoManager::CryptoParams decryptParams = { .area = cloneKey.area, .userId = metaData.user, + .nonce = cloneKey.nonce }; + auto clonePassword = CryptoManager::GetInstance().Decrypt(cloneKey.sKey, decryptParams); + if (!clonePassword.empty()) { + CryptoManager::GetInstance().UpdateSecretMeta(clonePassword, metaData, metaKey, cloneKey); + } + clonePassword.assign(clonePassword.size(), 0); + } +} + int32_t RdbServiceImpl::AfterOpen(const RdbSyncerParam ¶m) { XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY); - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidParam(param) || !IsValidAccess(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; @@ -781,6 +948,7 @@ int32_t RdbServiceImpl::AfterOpen(const RdbSyncerParam ¶m) auto meta = GetStoreMetaData(param); StoreMetaData old; auto isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), old, true); + meta.enableCloud = isCreated ? old.enableCloud : meta.enableCloud; if (!isCreated || meta != old) { Upgrade(param, old); ZLOGI("meta bundle:%{public}s store:%{public}s type:%{public}d->%{public}d encrypt:%{public}d->%{public}d " @@ -790,19 +958,35 @@ int32_t RdbServiceImpl::AfterOpen(const RdbSyncerParam ¶m) MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true); AutoLaunchMetaData launchData; if (!MetaDataManager::GetInstance().LoadMeta(meta.GetAutoLaunchKey(), launchData, true)) { - RemoteChangeEvent::DataInfo info; - info.bundleName = meta.bundleName; - info.deviceId = meta.deviceId; - info.userId = meta.user; - auto evt = std::make_unique(RemoteChangeEvent::RDB_META_SAVE, std::move(info)); - EventCenter::GetInstance().PostEvent(std::move(evt)); + SaveLaunchInfo(meta); } } + StoreMetaMapping metaMapping(meta); + MetaDataManager::GetInstance().LoadMeta(metaMapping.GetKey(), metaMapping, true); + if (meta.isSearchable) { + metaMapping.searchPath = meta.dataDir; + } + metaMapping = meta; + MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true); + SaveDebugInfo(meta, param); SavePromiseInfo(meta, param); SaveDfxInfo(meta, param); + if (!SaveAppIDMeta(meta, old)) { + return RDB_ERROR; + } + + if (param.isEncrypt_ && !param.password_.empty()) { + SaveSecretKeyMeta(meta, param.password_); + } + GetSchema(param); + return RDB_OK; +} + +bool RdbServiceImpl::SaveAppIDMeta(const StoreMetaData &meta, const StoreMetaData &old) +{ AppIDMetaData appIdMeta; appIdMeta.bundleName = meta.bundleName; appIdMeta.appId = meta.appId; @@ -810,23 +994,14 @@ int32_t RdbServiceImpl::AfterOpen(const RdbSyncerParam ¶m) ZLOGE("meta bundle:%{public}s store:%{public}s type:%{public}d->%{public}d encrypt:%{public}d->%{public}d " "area:%{public}d->%{public}d", meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), old.storeType, meta.storeType, old.isEncrypt, meta.isEncrypt, old.area, meta.area); - return RDB_ERROR; - } - if (param.isEncrypt_ && !param.password_.empty()) { - if (SetSecretKey(param, meta) != RDB_OK) { - ZLOGE("Set secret key failed, bundle:%{public}s store:%{public}s", - meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); - return RDB_ERROR; - } - UpgradeCloneSecretKey(meta); + return false; } - GetSchema(param); - return RDB_OK; + return true; } int32_t RdbServiceImpl::ReportStatistic(const RdbSyncerParam& param, const RdbStatEvent &statEvent) { - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidAccess(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; @@ -846,6 +1021,8 @@ void RdbServiceImpl::GetSchema(const RdbSyncerParam ¶m) storeInfo.instanceId = instanceId; storeInfo.user = user; storeInfo.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + auto meta = GetStoreMetaData(param); + storeInfo.path = meta.dataDir; executors_->Execute([storeInfo]() { auto event = std::make_unique(CloudEvent::GET_SCHEMA, std::move(storeInfo)); EventCenter::GetInstance().PostEvent(move(event)); @@ -854,6 +1031,33 @@ void RdbServiceImpl::GetSchema(const RdbSyncerParam ¶m) } } +std::pair RdbServiceImpl::LoadStoreMetaData(const RdbSyncerParam ¶m) +{ + StoreMetaData metaData; + metaData.uid = IPCSkeleton::GetCallingUid(); + metaData.tokenId = IPCSkeleton::GetCallingTokenID(); + auto [instanceId, user] = GetInstIndexAndUser(metaData.tokenId, param.bundleName_); + metaData.instanceId = instanceId; + metaData.bundleName = param.bundleName_; + metaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData.storeId = RemoveSuffix(param.storeName_); + if (AccessTokenKit::GetTokenTypeFlag(metaData.tokenId) != TOKEN_HAP && param.subUser_ != 0) { + metaData.user = std::to_string(param.subUser_); + } else { + metaData.user = std::to_string(user); + } + metaData.storeType = param.type_; + metaData.securityLevel = param.level_; + metaData.area = param.area_; + metaData.appId = CheckerManager::GetInstance().GetAppId(Converter::ConvertToStoreInfo(metaData)); + metaData.appType = "harmony"; + metaData.hapName = param.hapName_; + metaData.customDir = param.customDir_; + metaData.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData) + "/" + param.storeName_; + auto exist = MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true); + return {exist, metaData}; +} + StoreMetaData RdbServiceImpl::GetStoreMetaData(const RdbSyncerParam ¶m) { StoreMetaData metaData; @@ -886,33 +1090,6 @@ StoreMetaData RdbServiceImpl::GetStoreMetaData(const RdbSyncerParam ¶m) return metaData; } -int32_t RdbServiceImpl::SetSecretKey(const RdbSyncerParam ¶m, const StoreMetaData &meta) -{ - SecretKeyMetaData newSecretKey; - newSecretKey.storeType = meta.storeType; - newSecretKey.area = meta.area; - newSecretKey.sKey = CryptoManager::GetInstance().Encrypt(param.password_, meta.area, meta.user); - if (newSecretKey.sKey.empty()) { - ZLOGE("encrypt work key error."); - return RDB_ERROR; - } - auto time = system_clock::to_time_t(system_clock::now()); - newSecretKey.time = { reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time) }; - return MetaDataManager::GetInstance().SaveMeta(meta.GetSecretKey(), newSecretKey, true) ? RDB_OK : RDB_ERROR; -} - -bool RdbServiceImpl::UpgradeCloneSecretKey(const StoreMetaData &meta) -{ - SecretKeyMetaData secretKey; - if (MetaDataManager::GetInstance().LoadMeta(meta.GetCloneSecretKey(), secretKey, true) && secretKey.area < 0) { - std::vector clonePwd; - // Update the encryption method for the key - CryptoManager::GetInstance().Decrypt(meta, secretKey, clonePwd, CryptoManager::CLONE_SECRET_KEY); - clonePwd.assign(clonePwd.size(), 0); - } - return true; -} - int32_t RdbServiceImpl::Upgrade(const RdbSyncerParam ¶m, const StoreMetaData &old) { if (old.storeType == RDB_DEVICE_COLLABORATION && old.version < StoreMetaData::UUID_CHANGED_TAG) { @@ -942,26 +1119,6 @@ Details RdbServiceImpl::HandleGenDetails(const GenDetails &details) return dbDetails; } -bool RdbServiceImpl::GetDBPassword(const StoreMetaData &metaData, DistributedDB::CipherPassword &password) -{ - if (!metaData.isEncrypt) { - return true; - } - - std::string key = metaData.GetSecretKey(); - DistributedData::SecretKeyMetaData secretKeyMeta; - MetaDataManager::GetInstance().LoadMeta(key, secretKeyMeta, true); - std::vector decryptKey; - CryptoManager::GetInstance().Decrypt(metaData, secretKeyMeta, decryptKey); - if (password.SetValue(decryptKey.data(), decryptKey.size()) != DistributedDB::CipherPassword::OK) { - std::fill(decryptKey.begin(), decryptKey.end(), 0); - ZLOGE("Set secret key value failed. len is (%{public}d)", int32_t(decryptKey.size())); - return false; - } - std::fill(decryptKey.begin(), decryptKey.end(), 0); - return true; -} - std::string RdbServiceImpl::RemoveSuffix(const std::string& name) { std::string suffix(".db"); @@ -998,20 +1155,23 @@ int32_t RdbServiceImpl::OnBind(const BindInfo &bindInfo) StoreMetaData RdbServiceImpl::GetStoreMetaData(const Database &dataBase) { - StoreMetaData storeMetaData; - storeMetaData.storeId = dataBase.name; - storeMetaData.bundleName = dataBase.bundleName; - storeMetaData.user = dataBase.user; - storeMetaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + StoreMetaMapping storeMetaMapping; + storeMetaMapping.storeId = dataBase.name; + storeMetaMapping.bundleName = dataBase.bundleName; + storeMetaMapping.user = dataBase.user; + storeMetaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; auto tokenId = IPCSkeleton::GetCallingTokenID(); - storeMetaData.tokenId = tokenId; - auto [instanceId, user] = GetInstIndexAndUser(storeMetaData.tokenId, storeMetaData.bundleName); - storeMetaData.instanceId = instanceId; - MetaDataManager::GetInstance().LoadMeta(storeMetaData.GetKey(), storeMetaData, true); + storeMetaMapping.tokenId = tokenId; + auto [instanceId, user] = GetInstIndexAndUser(storeMetaMapping.tokenId, storeMetaMapping.bundleName); + storeMetaMapping.instanceId = instanceId; + MetaDataManager::GetInstance().LoadMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); + StoreMetaData storeMetaData = storeMetaMapping; + if (storeMetaMapping.dataDir != storeMetaMapping.devicePath) { + MetaDataManager::GetInstance().LoadMeta(storeMetaMapping.GetDeviceStoreMetaKey(), storeMetaData, true); + } return storeMetaData; } - std::shared_ptr RdbServiceImpl::GetStore(const StoreMetaData &storeMetaData) { auto watchers = GetWatchers(storeMetaData.tokenId, storeMetaData.storeId); @@ -1019,12 +1179,16 @@ std::shared_ptr RdbServiceImpl::GetStore(const St return store; } -std::vector RdbServiceImpl::GetReuseDevice(const std::vector &devices) +std::vector RdbServiceImpl::GetReuseDevice(const std::vector &devices, + const StoreMetaData &metaData) { std::vector onDevices; auto instance = AppDistributedKv::ProcessCommunicatorImpl::GetInstance(); + AppDistributedKv::ExtraDataInfo extraInfo = { .userId = metaData.user, .bundleName = metaData.bundleName, + .storeId = metaData.storeId, .tokenId = metaData.tokenId }; for (auto &device : devices) { - if (instance->ReuseConnect({device}) == Status::SUCCESS) { + AppDistributedKv::DeviceId deviceId = { .deviceId = device }; + if (instance->ReuseConnect(deviceId, extraInfo) == Status::SUCCESS) { onDevices.push_back(device); } } @@ -1035,30 +1199,27 @@ int RdbServiceImpl::DoAutoSync( const std::vector &devices, const Database &dataBase, std::vector tables) { StoreMetaData storeMetaData = GetStoreMetaData(dataBase); - auto tokenId = storeMetaData.tokenId; auto store = GetStore(storeMetaData); if (store == nullptr) { ZLOGE("autosync store null, storeId:%{public}s", storeMetaData.GetStoreAlias().c_str()); return RDB_ERROR; } - SyncParam syncParam = {0, 0}; - auto pid = IPCSkeleton::GetCallingPid(); - DetailAsync async; if (executors_ == nullptr) { ZLOGE("autosync executors_ null, storeId:%{public}s", storeMetaData.GetStoreAlias().c_str()); return RDB_ERROR; } + SyncParam syncParam = { 0, 0 }; + DetailAsync async; for (auto &table : tables) { - executors_->Execute([this, table, store, pid, syncParam, tokenId, async, - devices, storeMetaData]() { + executors_->Execute([this, table, store, syncParam, async, devices, storeMetaData]() { RdbQuery rdbQuery; rdbQuery.MakeQuery(table); - std::vector onDevices = GetReuseDevice(devices); + std::vector onDevices = GetReuseDevice(devices, storeMetaData); if (onDevices.empty()) { ZLOGE("autosync ondevices null, storeId:%{public}s", storeMetaData.GetStoreAlias().c_str()); return; } - auto complete = [this, rdbQuery, store, pid, syncParam, tokenId, async, seq = 0]( + auto complete = [this, rdbQuery, store, syncParam, async]( const auto &results) mutable { auto ret = ProcessResult(results); store->Sync(ret.first, rdbQuery, async, syncParam); @@ -1099,8 +1260,8 @@ int32_t RdbServiceImpl::OnReady(const std::string &device) dataBase.autoSyncType == AutoSyncType::SYNC_ON_CHANGE_READY) && index > 0) { std::vector devices = {device}; - if (!DoOnlineSync(devices, dataBase)) { - ZLOGE("store online sync fail, storeId:%{public}s", dataBase.name.c_str()); + if (DoOnlineSync(devices, dataBase) != RDB_OK) { + ZLOGE("store online sync fail, storeId:%{public}s", Anonymous::Change(dataBase.name).c_str()); } index--; } @@ -1179,8 +1340,21 @@ int32_t RdbServiceImpl::RdbStatic::OnAppUpdate(const std::string &bundleName, in std::string prefix = Database::GetPrefix({std::to_string(user), "default", bundleName}); std::vector dataBase; if (MetaDataManager::GetInstance().LoadMeta(prefix, dataBase, true)) { - for (const auto &dataBase : dataBase) { - MetaDataManager::GetInstance().DelMeta(dataBase.GetKey(), true); + for (const auto &database : dataBase) { + MetaDataManager::GetInstance().DelMeta(database.GetKey(), true); + ZLOGD("del metadata store is: %{public}s; user is: %{public}s; bundleName is: %{public}s", + Anonymous::Change(database.name).c_str(), database.user.c_str(), database.bundleName.c_str()); + StoreMetaData meta; + meta.user = database.user; + meta.deviceId = database.deviceId; + meta.storeId = database.name; + meta.bundleName = bundleName; + Database base; + if (RdbSchemaConfig::GetDistributedSchema(meta, base) && !base.name.empty() && !base.bundleName.empty()) { + MetaDataManager::GetInstance().SaveMeta(base.GetKey(), base, true); + ZLOGD("save metadata store is: %{public}s; user is: %{public}s; bundleName is: %{public}s", + Anonymous::Change(base.name).c_str(), base.user.c_str(), base.bundleName.c_str()); + } } } return CloseStore(bundleName, user, index); @@ -1255,7 +1429,7 @@ int32_t RdbServiceImpl::NotifyDataChange( const RdbSyncerParam ¶m, const RdbChangedData &rdbChangedData, const RdbNotifyConfig &rdbNotifyConfig) { XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY); - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidParam(param) || !IsValidAccess(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; @@ -1264,14 +1438,15 @@ int32_t RdbServiceImpl::NotifyDataChange( storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); storeInfo.bundleName = param.bundleName_; storeInfo.storeName = RemoveSuffix(param.storeName_); + storeInfo.path = GetPath(param); auto [instanceId, user] = GetInstIndexAndUser(storeInfo.tokenId, param.bundleName_); storeInfo.instanceId = instanceId; storeInfo.user = user; storeInfo.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; DataChangeEvent::EventInfo eventInfo; eventInfo.isFull = rdbNotifyConfig.isFull_; - if (!DoDataChangeSync(storeInfo, rdbChangedData)) { - ZLOGE("store datachange sync fail, storeId:%{public}s", storeInfo.storeName.c_str()); + if (DoDataChangeSync(storeInfo, rdbChangedData) != RDB_OK) { + ZLOGE("store datachange sync fail, storeId:%{public}s", Anonymous::Change(storeInfo.storeName).c_str()); } for (const auto &[key, value] : rdbChangedData.tableData) { if (value.isTrackedDataChange) { @@ -1279,7 +1454,7 @@ int32_t RdbServiceImpl::NotifyDataChange( eventInfo.tableProperties.insert_or_assign(key, std::move(tableChangeProperties)); } } - if (IsPostImmediately(IPCSkeleton::GetCallingPid(), rdbNotifyConfig, storeInfo, eventInfo, param.storeName_)) { + if (IsPostImmediately(IPCSkeleton::GetCallingPid(), rdbNotifyConfig, storeInfo, eventInfo, storeInfo.path)) { auto evt = std::make_unique(std::move(storeInfo), std::move(eventInfo)); EventCenter::GetInstance().PostEvent(std::move(evt)); } @@ -1287,12 +1462,12 @@ int32_t RdbServiceImpl::NotifyDataChange( } bool RdbServiceImpl::IsPostImmediately(const int32_t callingPid, const RdbNotifyConfig &rdbNotifyConfig, - StoreInfo &storeInfo, DataChangeEvent::EventInfo &eventInfo, const std::string &storeName) + StoreInfo &storeInfo, DataChangeEvent::EventInfo &eventInfo, const std::string &path) { bool postImmediately = false; heartbeatTaskIds_.Compute(callingPid, [this, &postImmediately, &rdbNotifyConfig, &storeInfo, &eventInfo, - &storeName](const int32_t &key, std::map &tasks) { - auto iter = tasks.find(storeName); + &path](const int32_t &key, std::map &tasks) { + auto iter = tasks.find(path); ExecutorPool::TaskId taskId = ExecutorPool::INVALID_TASK_ID; if (iter != tasks.end()) { taskId = iter->second; @@ -1302,7 +1477,7 @@ bool RdbServiceImpl::IsPostImmediately(const int32_t callingPid, const RdbNotify executors_->Remove(taskId); } postImmediately = true; - tasks.erase(storeName); + tasks.erase(path); return !tasks.empty(); } @@ -1317,7 +1492,7 @@ bool RdbServiceImpl::IsPostImmediately(const int32_t callingPid, const RdbNotify taskId = executors_->Reset(taskId, std::chrono::milliseconds(rdbNotifyConfig.delay_)); } } - tasks.insert_or_assign(storeName, taskId); + tasks.insert_or_assign(path, taskId); return true; }); return postImmediately; @@ -1326,7 +1501,7 @@ bool RdbServiceImpl::IsPostImmediately(const int32_t callingPid, const RdbNotify int32_t RdbServiceImpl::SetSearchable(const RdbSyncerParam& param, bool isSearchable) { XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY); - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidAccess(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; @@ -1347,6 +1522,7 @@ int32_t RdbServiceImpl::PostSearchEvent(int32_t evtId, const RdbSyncerParam& par storeInfo.instanceId = instanceId; storeInfo.user = user; storeInfo.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + storeInfo.path = GetPath(param); auto evt = std::make_unique(std::move(storeInfo), std::move(eventInfo), evtId); EventCenter::GetInstance().PostEvent(std::move(evt)); @@ -1357,8 +1533,7 @@ int32_t RdbServiceImpl::Disable(const RdbSyncerParam ¶m) { auto tokenId = IPCSkeleton::GetCallingTokenID(); auto storeId = RemoveSuffix(param.storeName_); - auto userId = GetSubUser(param.subUser_); - AutoCache::GetInstance().Disable(tokenId, storeId, userId); + AutoCache::GetInstance().Disable(tokenId, GetPath(param), storeId); return RDB_OK; } @@ -1366,41 +1541,52 @@ int32_t RdbServiceImpl::Enable(const RdbSyncerParam ¶m) { auto tokenId = IPCSkeleton::GetCallingTokenID(); auto storeId = RemoveSuffix(param.storeName_); - auto userId = GetSubUser(param.subUser_); - AutoCache::GetInstance().Enable(tokenId, storeId, userId); + AutoCache::GetInstance().Enable(tokenId, GetPath(param), storeId); return RDB_OK; } +std::vector RdbServiceImpl::LoadSecretKey(const StoreMetaData &metaData, + CryptoManager::SecretKeyType secretKeyType) +{ + SecretKeyMetaData secretKey; + std::string metaKey; + if (secretKeyType == CryptoManager::SecretKeyType::LOCAL_SECRET_KEY) { + metaKey = metaData.GetSecretKey(); + } else if (secretKeyType == CryptoManager::SecretKeyType::CLONE_SECRET_KEY) { + metaKey = metaData.GetCloneSecretKey(); + } + if (!MetaDataManager::GetInstance().LoadMeta(metaKey, secretKey, true) || secretKey.sKey.empty()) { + return {}; + } + CryptoManager::CryptoParams decryptParams = { .area = secretKey.area, .userId = metaData.user, + .nonce = secretKey.nonce }; + auto password = CryptoManager::GetInstance().Decrypt(secretKey.sKey, decryptParams); + if (password.empty()) { + return {}; + } + // update secret key of area or nonce + CryptoManager::GetInstance().UpdateSecretMeta(password, metaData, metaKey, secretKey); + return password; +} + int32_t RdbServiceImpl::GetPassword(const RdbSyncerParam ¶m, std::vector> &password) { - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidAccess(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; } + password.reserve(KEY_COUNT); auto meta = GetStoreMetaData(param); - password.resize(KEY_COUNT); - SecretKeyMetaData secretKey; - SecretKeyMetaData cloneSecretKey; - bool keyMeta = MetaDataManager::GetInstance().LoadMeta(meta.GetSecretKey(), secretKey, true); - bool cloneKeyMeta = MetaDataManager::GetInstance().LoadMeta(meta.GetCloneSecretKey(), cloneSecretKey, true); - if (!keyMeta && !cloneKeyMeta) { - ZLOGE("bundleName:%{public}s, storeName:%{public}s. no meta", param.bundleName_.c_str(), - Anonymous::Change(param.storeName_).c_str()); - return RDB_NO_META; + auto key = LoadSecretKey(meta, CryptoManager::SecretKeyType::LOCAL_SECRET_KEY); + if (!key.empty()) { + password.emplace_back(key); } - bool key = CryptoManager::GetInstance().Decrypt(meta, secretKey, password.at(0)); - bool cloneKey = CryptoManager::GetInstance().Decrypt( - meta, cloneSecretKey, password.at(1), CryptoManager::CLONE_SECRET_KEY); - if (!key && !cloneKey) { - ZLOGE("bundleName:%{public}s, storeName:%{public}s. decrypt err", param.bundleName_.c_str(), - Anonymous::Change(param.storeName_).c_str()); - for (auto &item : password) { - item.assign(item.size(), 0); - } - return RDB_ERROR; + auto cloneKey = LoadSecretKey(meta, CryptoManager::SecretKeyType::CLONE_SECRET_KEY); + if (!cloneKey.empty()) { + password.emplace_back(cloneKey); } - return RDB_OK; + return password.size() > 0 ? RDB_OK : RDB_ERROR; } StoreInfo RdbServiceImpl::GetStoreInfo(const RdbSyncerParam ¶m) @@ -1410,13 +1596,15 @@ StoreInfo RdbServiceImpl::GetStoreInfo(const RdbSyncerParam ¶m) storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); storeInfo.user = AccountDelegate::GetInstance()->GetUserByToken(storeInfo.tokenId); storeInfo.storeName = RemoveSuffix(param.storeName_); + auto meta = GetStoreMetaData(param); + storeInfo.path = meta.dataDir; return storeInfo; } std::pair RdbServiceImpl::LockCloudContainer(const RdbSyncerParam ¶m) { std::pair result { RDB_ERROR, 0 }; - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidAccess(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; @@ -1438,7 +1626,7 @@ std::pair RdbServiceImpl::LockCloudContainer(const RdbSyncerP int32_t RdbServiceImpl::UnlockCloudContainer(const RdbSyncerParam ¶m) { int32_t result = RDB_ERROR; - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidAccess(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; @@ -1459,7 +1647,7 @@ int32_t RdbServiceImpl::UnlockCloudContainer(const RdbSyncerParam ¶m) int32_t RdbServiceImpl::GetDebugInfo(const RdbSyncerParam ¶m, std::map &debugInfo) { - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidAccess(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; @@ -1512,7 +1700,7 @@ int32_t RdbServiceImpl::SaveDebugInfo(const StoreMetaData &metaData, const RdbSy int32_t RdbServiceImpl::GetDfxInfo(const RdbSyncerParam ¶m, DistributedRdb::RdbDfxInfo &dfxInfo) { - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidAccess(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; @@ -1568,14 +1756,18 @@ int32_t RdbServiceImpl::VerifyPromiseInfo(const RdbSyncerParam ¶m) auto uid = IPCSkeleton::GetCallingUid(); meta.user = param.user_; StoreMetaDataLocal localMeta; - auto isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMeta, true); - if (!isCreated) { - ZLOGE("Store not exist. bundleName:%{public}s, storeName:%{public}s", meta.bundleName.c_str(), - meta.storeId.c_str()); - return RDB_ERROR; + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMeta, true)) { + StoreMetaMapping metaMapping(meta); + MetaDataManager::GetInstance().LoadMeta(metaMapping.GetKey(), metaMapping, true); + meta.dataDir = metaMapping.dataDir; + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMeta, true)) { + ZLOGE("Store not exist. bundleName:%{public}s, storeName:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return RDB_ERROR; + } } ATokenTypeEnum type = AccessTokenKit::GetTokenType(tokenId); - if (type == ATokenTypeEnum::TOKEN_NATIVE) { + if (type == ATokenTypeEnum::TOKEN_NATIVE || type == ATokenTypeEnum::TOKEN_SHELL) { auto tokenIdRet = std::find(localMeta.promiseInfo.tokenIds.begin(), localMeta.promiseInfo.tokenIds.end(), tokenId); auto uidRet = std::find(localMeta.promiseInfo.uids.begin(), localMeta.promiseInfo.uids.end(), uid); @@ -1587,15 +1779,18 @@ int32_t RdbServiceImpl::VerifyPromiseInfo(const RdbSyncerParam ¶m) !isPromise) { return RDB_ERROR; } - } - if (type == ATokenTypeEnum::TOKEN_HAP) { - for (const auto& permissionName : localMeta.promiseInfo.permissionNames) { + } else if (type == ATokenTypeEnum::TOKEN_HAP) { + for (const auto &permissionName : localMeta.promiseInfo.permissionNames) { if (PermitDelegate::VerifyPermission(permissionName, tokenId)) { return RDB_OK; } } ZLOGE("Permission denied! tokenId:0x%{public}x", tokenId); return RDB_ERROR; + } else { + ZLOGE("invalid type! bundleName:%{public}s, storeName:%{public}s, token_type is %{public}d.", + meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), type); + return RDB_ERROR; } return RDB_OK; } @@ -1615,7 +1810,7 @@ bool RdbServiceImpl::TryUpdateDeviceId(const RdbSyncerParam ¶m, const StoreM StoreMetaData syncMeta; if (oldMeta.isNeedUpdateDeviceId && oldMeta.storeType >= StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN && oldMeta.storeType <= StoreMetaData::StoreType::STORE_RELATIONAL_END && - MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), syncMeta)) { + MetaDataManager::GetInstance().LoadMeta(meta.GetKeyWithoutPath(), syncMeta)) { auto store = GetStore(param); if (store == nullptr) { ZLOGE("store is null, bundleName:%{public}s storeName:%{public}s", param.bundleName_.c_str(), @@ -1636,9 +1831,15 @@ void RdbServiceImpl::RegisterEvent() auto process = [this](const Event &event) { auto &evt = static_cast(event); auto &storeInfo = evt.GetStoreInfo(); - StoreMetaData meta(storeInfo); - meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + StoreMetaMapping mapping(storeInfo); + mapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + if (!MetaDataManager::GetInstance().LoadMeta(mapping.GetKey(), mapping, true)) { + ZLOGE("bundle:%{public}s, storeId:%{public}s", mapping.bundleName.c_str(), mapping.GetStoreAlias().c_str()); + return; + } + StoreMetaData meta = mapping; + if (!mapping.cloudPath.empty() && mapping.cloudPath != mapping.dataDir && + !MetaDataManager::GetInstance().LoadMeta(mapping.GetCloudStoreMetaKey(), meta, true)) { ZLOGE("meta empty, bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); return; @@ -1677,4 +1878,28 @@ void RdbServiceImpl::RegisterEvent() EventCenter::GetInstance().Subscribe(BindEvent::COMPENSATE_SYNC, compensateSyncProcess); EventCenter::GetInstance().Subscribe(BindEvent::RECOVER_SYNC, compensateSyncProcess); } + +std::string RdbServiceImpl::GetPath(const RdbSyncerParam ¶m) +{ + StoreMetaData metaData; + metaData.uid = IPCSkeleton::GetCallingUid(); + metaData.tokenId = IPCSkeleton::GetCallingTokenID(); + auto [instanceId, user] = GetInstIndexAndUser(metaData.tokenId, param.bundleName_); + metaData.instanceId = instanceId; + metaData.bundleName = param.bundleName_; + metaData.storeId = RemoveSuffix(param.storeName_); + if (AccessTokenKit::GetTokenTypeFlag(metaData.tokenId) != TOKEN_HAP && param.subUser_ != 0) { + metaData.user = std::to_string(param.subUser_); + } else { + metaData.user = std::to_string(user); + } + metaData.storeType = param.type_; + metaData.securityLevel = param.level_; + metaData.area = param.area_; + metaData.appType = "harmony"; + metaData.hapName = param.hapName_; + metaData.customDir = param.customDir_; + return DirectoryManager::GetInstance().GetStorePath(metaData) + "/" + param.storeName_; +} + } // 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 0c06e926bd2a2ad1a51d59554209c177342ab395..b7fe3c03c401819504d293ea15f227ef7ceed66d 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -24,6 +24,7 @@ #include "commonevent/data_change_event.h" #include "commonevent/set_searchable_event.h" #include "concurrent_map.h" +#include "crypto/crypto_manager.h" #include "feature/static_acts.h" #include "metadata/secret_key_meta_data.h" #include "metadata/store_meta_data.h" @@ -53,7 +54,8 @@ public: virtual ~RdbServiceImpl(); /* IPC interface */ - std::string ObtainDistributedTableName(const std::string& device, const std::string& table) override; + std::string ObtainDistributedTableName(const RdbSyncerParam ¶m, const std::string &device, + const std::string &table) override; int32_t InitNotifier(const RdbSyncerParam ¶m, sptr notifier) override; @@ -66,10 +68,12 @@ public: int32_t Sync(const RdbSyncerParam ¶m, const Option &option, const PredicatesMemo &predicates, const AsyncDetail &async) override; - int32_t Subscribe(const RdbSyncerParam ¶m, const SubscribeOption &option, RdbStoreObserver *observer) override; + int32_t Subscribe(const RdbSyncerParam ¶m, + const SubscribeOption &option, + std::shared_ptr observer) override; int32_t UnSubscribe(const RdbSyncerParam ¶m, const SubscribeOption &option, - RdbStoreObserver *observer) override; + std::shared_ptrobserver) override; int32_t RegisterAutoSyncCallback(const RdbSyncerParam& param, std::shared_ptr observer) override; @@ -81,6 +85,8 @@ public: int32_t OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) override; + int32_t OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) override; + int32_t Delete(const RdbSyncerParam ¶m) override; std::pair> QuerySharingResource(const RdbSyncerParam& param, @@ -122,6 +128,7 @@ private: using DBStatus = DistributedDB::DBStatus; using SyncResult = std::pair, std::map>; using AutoCache = DistributedData::AutoCache; + using CryptoManager = DistributedData::CryptoManager; struct SyncAgent { SyncAgent() = default; explicit SyncAgent(const std::string &bundleName); @@ -178,7 +185,7 @@ private: int DoAutoSync( const std::vector &devices, const Database &dataBase, std::vector tableNames); - std::vector GetReuseDevice(const std::vector &devices); + std::vector GetReuseDevice(const std::vector &devices, const StoreMetaData &metaData); int DoOnlineSync(const std::vector &devices, const Database &dataBase); int DoDataChangeSync(const StoreInfo &storeInfo, const RdbChangedData &rdbChangedData); @@ -187,23 +194,40 @@ private: DetailAsync GetCallbacks(uint32_t tokenId, const std::string &storeName); - bool CheckAccess(const std::string& bundleName, const std::string& storeName); - std::shared_ptr GetStore(const RdbSyncerParam& param); std::shared_ptr GetStore(const StoreMetaData &storeMetaData); void OnAsyncComplete(uint32_t tokenId, pid_t pid, uint32_t seqNum, Details &&result); - StoreMetaData GetStoreMetaData(const RdbSyncerParam ¶m); + int32_t Upgrade(const RdbSyncerParam ¶m, const StoreMetaData &old); + + void GetSchema(const RdbSyncerParam ¶m); + + bool IsPostImmediately(const int32_t callingPid, const RdbNotifyConfig &rdbNotifyConfig, StoreInfo &storeInfo, + DistributedData::DataChangeEvent::EventInfo &eventInfo, const std::string &storeName); + + bool TryUpdateDeviceId(const RdbSyncerParam ¶m, const StoreMetaData &oldMeta, StoreMetaData &meta); - StoreMetaData GetStoreMetaData(const Database &dataBase); + void SaveLaunchInfo(StoreMetaData &meta); - int32_t SetSecretKey(const RdbSyncerParam ¶m, const StoreMetaData &meta); + static bool IsValidAccess(const std::string& bundleName, const std::string& storeName); - int32_t Upgrade(const RdbSyncerParam ¶m, const StoreMetaData &old); + static bool IsValidPath(const std::string& param); + + static bool IsValidCustomDir(const std::string &customDir, int32_t upLimit); - std::pair> AllocResource( + static bool IsValidParam(const RdbSyncerParam ¶m); + + static StoreMetaData GetStoreMetaData(const RdbSyncerParam ¶m); + + static std::pair LoadStoreMetaData(const RdbSyncerParam ¶m); + + static std::string GetPath(const RdbSyncerParam ¶m); + + static StoreMetaData GetStoreMetaData(const Database &dataBase); + + static std::pair> AllocResource( StoreInfo& storeInfo, std::shared_ptr rdbQuery); static Details HandleGenDetails(const DistributedData::GenDetails &details); @@ -215,35 +239,31 @@ private: static std::pair GetInstIndexAndUser(uint32_t tokenId, const std::string &bundleName); static std::string GetSubUser(const int32_t subUser); + + static bool SaveAppIDMeta(const StoreMetaData &meta, const StoreMetaData &old); - static bool GetDBPassword(const StoreMetaData &metaData, DistributedDB::CipherPassword &password); + static void SetReturnParam(const StoreMetaData &metadata, RdbSyncerParam ¶m); - void GetSchema(const RdbSyncerParam ¶m); + static bool IsNeedMetaSync(const StoreMetaData &meta, const std::vector &uuids); - void SetReturnParam(StoreMetaData &metadata, RdbSyncerParam ¶m); + static SyncResult ProcessResult(const std::map &results); - bool IsNeedMetaSync(const StoreMetaData &meta, const std::vector &uuids); + static StoreInfo GetStoreInfo(const RdbSyncerParam ¶m); - SyncResult ProcessResult(const std::map &results); + static int32_t SaveDebugInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m); - StoreInfo GetStoreInfo(const RdbSyncerParam ¶m); + static int32_t SaveDfxInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m); - int32_t SaveDebugInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m); + static int32_t SavePromiseInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m); - int32_t SaveDfxInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m); - - int32_t SavePromiseInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m); - - int32_t PostSearchEvent(int32_t evtId, const RdbSyncerParam& param, + static int32_t PostSearchEvent(int32_t evtId, const RdbSyncerParam& param, DistributedData::SetSearchableEvent::EventInfo &eventInfo); - bool IsPostImmediately(const int32_t callingPid, const RdbNotifyConfig &rdbNotifyConfig, StoreInfo &storeInfo, - DistributedData::DataChangeEvent::EventInfo &eventInfo, const std::string &storeName); - void UpdateMeta(const StoreMetaData &meta, const StoreMetaData &localMeta, AutoCache::Store store); + static void UpdateMeta(const StoreMetaData &meta, const StoreMetaData &localMeta, AutoCache::Store store); - bool UpgradeCloneSecretKey(const StoreMetaData &meta); + std::vector LoadSecretKey(const StoreMetaData &metaData, CryptoManager::SecretKeyType secretKeyType); - bool TryUpdateDeviceId(const RdbSyncerParam ¶m, const StoreMetaData &oldMeta, StoreMetaData &meta); + void SaveSecretKeyMeta(const StoreMetaData &metaData, const std::vector &password); static Factory factory_; ConcurrentMap syncAgents_; 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 737b216bbe98d95f4e4363bb8181c2174c909dbe..f52549c1f7aee6a8e0bcd8f23b604a9ec7585fca 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp @@ -28,15 +28,17 @@ namespace OHOS::DistributedRdb { using Anonymous = DistributedData::Anonymous; int32_t RdbServiceStub::OnRemoteObtainDistributedTableName(MessageParcel &data, MessageParcel &reply) { + RdbSyncerParam param; std::string device; std::string table; - if (!ITypesUtil::Unmarshal(data, device, table)) { + if (!ITypesUtil::Unmarshal(data, param, device, table)) { ZLOGE("Unmarshal device:%{public}s table:%{public}s", Anonymous::Change(device).c_str(), table.c_str()); return IPC_STUB_INVALID_DATA_ERR; } - std::string distributedTableName = ObtainDistributedTableName(device, table); - if (!ITypesUtil::Marshal(reply, distributedTableName)) { + std::string distributedTableName = ObtainDistributedTableName(param, device, table); + int32_t status = distributedTableName.empty() ? RDB_ERROR : RDB_OK; + if (!ITypesUtil::Marshal(reply, status, distributedTableName)) { ZLOGE("Marshal distributedTableName:%{public}s", distributedTableName.c_str()); return IPC_STUB_WRITE_PARCEL_ERR; } diff --git a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn index 97804c0cd26dadbaaf09debac7ae9cdf4b933157..98c13fef7209ebd20d4b87ac18c56c8738452f45 100644 --- a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn @@ -21,7 +21,6 @@ config("module_private_config") { visibility = [ ":*" ] include_dirs = [ - "//foundation/distributedhardware/device_manager/interfaces/inner_kits/native_cpp/include", "${data_service_path}/adapter/include", "${data_service_path}/app/src", "${data_service_path}/framework/include", @@ -44,12 +43,6 @@ config("module_private_config") { "${data_service_path}/service/permission/include", "${data_service_path}/service/rdb/", "${data_service_path}/service/test/mock", - "${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", "${data_service_path}/adapter/include/communicator", ] cflags = [ "-Werror" ] @@ -64,52 +57,18 @@ ohos_unittest("CloudDataTest") { cfi = true cfi_cross_dso = true debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" } 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_data_translate.cpp", + "${data_service_path}/service/cloud/cloud_notifier_proxy.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/config/src/model/thread_config.cpp", - "${data_service_path}/service/crypto/src/crypto_manager.cpp", - "${data_service_path}/service/kvdb/user_delegate.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/permission_validator.cpp", - "${data_service_path}/service/permission/src/permit_delegate.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_cursor.cpp", - "${data_service_path}/service/rdb/rdb_general_store.cpp", - "${data_service_path}/service/rdb/rdb_hiview_adapter.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_schema_config.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", "cloud_data_test.cpp", ] @@ -117,35 +76,32 @@ ohos_unittest("CloudDataTest") { configs = [ ":module_private_config" ] external_deps = [ - "ability_base:base", - "ability_base:want", "access_token:libaccesstoken_sdk", "access_token:libtoken_setproc", "access_token:libtokenid_sdk", - "bundle_framework:appexecfwk_base", - "bundle_framework:appexecfwk_core", "c_utils:utils", "device_manager:devicemanagersdk", "hicollie:libhicollie", "hilog:libhilog", - "hisysevent:libhisysevent", - "huks:libhukssdk", - "ipc:ipc_core", + "googletest:gmock", + "googletest:gtest", + "ipc:ipc_single", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddb", - "netmanager_base:net_conn_manager_if", "relational_store:native_rdb", - "resource_management:global_resmgr", - "samgr:samgr_proxy", ] deps = [ "${data_service_path}/adapter/account:distributeddata_account", "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/adapter/dfx:distributeddata_dfx", "${data_service_path}/adapter/schema_helper:distributeddata_schema_helper", - "../../framework:distributeddatasvcfwk", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service/bootstrap:distributeddata_bootstrap", + "${data_service_path}/service/common:distributeddata_common", + "${data_service_path}/service/rdb:distributeddata_rdb", "mock:distributeddata_mock_static", - "//third_party/googletest:gtest_main", ] cflags = [ @@ -155,57 +111,81 @@ ohos_unittest("CloudDataTest") { cflags_cc = cflags } +ohos_unittest("CloudDataMockTest") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } + module_out_path = module_output_path + sources = [ + "${data_service_path}/service/cloud/cloud_data_translate.cpp", + "${data_service_path}/service/cloud/cloud_notifier_proxy.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/test/mock/checker_mock.cpp", + "mock/access_token_mock.cpp", + "mock/account_delegate_mock.cpp", + "cloud_data_mock_test.cpp", + ] + + configs = [ ":module_private_config" ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + + deps = [ + "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/adapter/dfx:distributeddata_dfx", + "${data_service_path}/adapter/schema_helper:distributeddata_schema_helper", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service/bootstrap:distributeddata_bootstrap", + "${data_service_path}/service/common:distributeddata_common", + "${data_service_path}/service/rdb:distributeddata_rdb", + "mock:distributeddata_mock_static", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "device_manager:devicemanagersdk", + "googletest:gmock", + "googletest:gtest", + "hicollie:libhicollie", + "hilog:libhilog", + "ipc:ipc_single", + "json:nlohmann_json_static", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "relational_store:native_rdb", + ] +} + + ohos_unittest("CloudServiceImplTest") { sanitize = { cfi = true cfi_cross_dso = true debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" } 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_data_translate.cpp", + "${data_service_path}/service/cloud/cloud_notifier_proxy.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/config/src/model/thread_config.cpp", - "${data_service_path}/service/crypto/src/crypto_manager.cpp", - "${data_service_path}/service/kvdb/user_delegate.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/permission_validator.cpp", - "${data_service_path}/service/permission/src/permit_delegate.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_cursor.cpp", - "${data_service_path}/service/rdb/rdb_general_store.cpp", - "${data_service_path}/service/rdb/rdb_hiview_adapter.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_schema_config.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", "cloud_service_impl_test.cpp", ] @@ -213,35 +193,31 @@ ohos_unittest("CloudServiceImplTest") { configs = [ ":module_private_config" ] external_deps = [ - "ability_base:base", - "ability_base:want", "access_token:libaccesstoken_sdk", "access_token:libtoken_setproc", - "access_token:libtokenid_sdk", - "bundle_framework:appexecfwk_base", - "bundle_framework:appexecfwk_core", + "json:nlohmann_json_static", "c_utils:utils", "device_manager:devicemanagersdk", + "googletest:gmock", + "googletest:gtest", "hicollie:libhicollie", "hilog:libhilog", - "hisysevent:libhisysevent", - "huks:libhukssdk", - "ipc:ipc_core", + "ipc:ipc_single", "kv_store:distributeddata_inner", "kv_store:distributeddb", - "netmanager_base:net_conn_manager_if", "relational_store:native_rdb", - "resource_management:global_resmgr", - "samgr:samgr_proxy", ] deps = [ "${data_service_path}/adapter/account:distributeddata_account", "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/adapter/dfx:distributeddata_dfx", "${data_service_path}/adapter/schema_helper:distributeddata_schema_helper", - "../../framework:distributeddatasvcfwk", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service/bootstrap:distributeddata_bootstrap", + "${data_service_path}/service/common:distributeddata_common", + "${data_service_path}/service/rdb:distributeddata_rdb", "mock:distributeddata_mock_static", - "//third_party/googletest:gtest_main", ] cflags = [ @@ -261,6 +237,7 @@ ohos_unittest("CloudTest") { "ability_base:base", "ability_base:want", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_inner", @@ -271,7 +248,6 @@ ohos_unittest("CloudTest") { "../../framework:distributeddatasvcfwk", "../../service:distributeddatasvc", "mock:distributeddata_mock_static", - "//third_party/googletest:gtest_main", ] } @@ -282,11 +258,6 @@ ohos_unittest("ValueProxyServiceTest") { "value_proxy_test.cpp", ] - include_dirs = [ - "../../../../../relational_store/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", - ] - configs = [ ":module_private_config" ] cflags = [ @@ -300,17 +271,17 @@ ohos_unittest("ValueProxyServiceTest") { "ability_base:base", "ability_base:want", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "relational_store:native_rdb", ] deps = [ - "${kv_store_distributeddb_path}:distributeddb", - "${relational_store_inner_api_path}:native_rdb_static", "../../framework:distributeddatasvcfwk", "../../service:distributeddatasvc", - "//third_party/googletest:gtest_main", ] } @@ -324,16 +295,16 @@ ohos_unittest("ConfigFactoryTest") { "ability_base:base", "ability_base:want", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddata_inner", + "openssl:libcrypto_shared", ] deps = [ "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/service:distributeddatasvc", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", ] } @@ -347,17 +318,17 @@ ohos_unittest("DirectoryManagerTest") { "ability_base:base", "ability_base:want", "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddata_inner", ] deps = [ "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/service:distributeddatasvc", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", ] } @@ -371,17 +342,19 @@ ohos_unittest("CryptoManagerTest") { "ability_base:base", "ability_base:want", "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", "access_token:libnativetoken", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", + "huks:libhukssdk", "ipc:ipc_core", + "kv_store:distributeddata_inner", ] deps = [ "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/service:distributeddatasvc", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", ] } @@ -407,16 +380,17 @@ ohos_unittest("DeviceMatrixTest") { "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "c_utils:utils", + "device_manager:devicemanagersdk", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", ] } @@ -425,10 +399,12 @@ ohos_unittest("KVDBGeneralStoreTest") { cfi = true cfi_cross_dso = true debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" } module_out_path = module_output_path sources = [ "kvdb_general_store_test.cpp", + "mock/account_delegate_mock.cpp", "mock/db_change_data_mock.cpp", "mock/db_store_mock.cpp", "mock/general_watcher_mock.cpp", @@ -439,9 +415,6 @@ ohos_unittest("KVDBGeneralStoreTest") { "${data_service_path}/service/common", "${data_service_path}/service/rdb", "${data_service_path}/service/kvdb", - "${relational_store_path}/interfaces/innerapi/clouddata/include", - "${relational_store_path}/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", ] configs = [ ":module_private_config" ] @@ -457,18 +430,20 @@ ohos_unittest("KVDBGeneralStoreTest") { "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "c_utils:utils", + "device_manager:devicemanagersdk", + "googletest:gmock_main", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "relational_store:native_rdb", ] deps = [ - "${data_service_path}/adapter/account:distributeddata_account", "${data_service_path}/adapter/communicator:distributeddata_communicator", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/kvdb:distributeddata_kvdb", - "${kv_store_distributeddb_path}:distributeddb", - "//third_party/googletest:gtest_main", ] } @@ -552,12 +527,7 @@ ohos_unittest("RdbResultSetImplTest") { "rdb_result_set_impl_test.cpp", ] - include_dirs = [ - "${data_service_path}/service/rdb", - "${relational_store_path}/interfaces/inner_api/cloud_data/include", - "${relational_store_path}/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", - ] + include_dirs = [ "${data_service_path}/service/rdb" ] configs = [ ":module_private_config" ] @@ -574,35 +544,33 @@ ohos_unittest("RdbResultSetImplTest") { "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "c_utils:utils", + "googletest:gmock_main", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddb", + "relational_store:native_rdb", + "kv_store:datamgr_common", ] deps = [ "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", - "${kv_store_distributeddb_path}:distributeddb", - "${relational_store_inner_api_path}:native_rdb_static", - "//third_party/googletest:gtest_main", ] } ohos_unittest("RdbServiceTest") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } module_out_path = module_output_path sources = [ - "${data_service_path}/service/common/value_proxy.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_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_watcher.cpp", "cache_cursor_test.cpp", "mock/general_watcher_mock.cpp", + "mock/relational_store_manager_mock.cpp", "rdb_asset_loader_test.cpp", "rdb_cloud_test.cpp", "rdb_cursor_test.cpp", @@ -611,17 +579,9 @@ ohos_unittest("RdbServiceTest") { "rdb_result_set_stub_test.cpp", ] - include_dirs = [ - "${relational_store_path}/interfaces/inner_api/cloud_data/include", - "${relational_store_path}/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", - ] - configs = [ ":module_private_config" ] cflags = [ - "-Dprivate=public", - "-Dprotected=public", "-Wno-multichar", "-Wno-c99-designator", "-fno-access-control", # Ignore Private Member Access Control @@ -633,82 +593,246 @@ ohos_unittest("RdbServiceTest") { "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "c_utils:utils", + "device_manager:devicemanagersdk", + "googletest:gmock_main", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddb", + "relational_store:native_rdb", ] deps = [ + "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/adapter/dfx:distributeddata_dfx", + "${data_service_path}/adapter/network:distributeddata_network", "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", - "${data_service_path}/service:distributeddatasvc", - "${kv_store_distributeddb_path}:distributeddb", - "${relational_store_inner_api_path}:native_rdb_static", - "//third_party/googletest:gtest_main", + "${data_service_path}/service/backup:distributeddata_backup", + "${data_service_path}/service/bootstrap:distributeddata_bootstrap", + "${data_service_path}/service/common:distributeddata_common", + "${data_service_path}/service/dumper:distributeddata_dumper", + "${data_service_path}/service/matrix:distributeddata_matrix", + "${data_service_path}/service/permission:distributeddata_permit", ] + + if (defined(global_parts_info) && + defined(global_parts_info.theme_screenlock_mgr)) { + deps += + [ "${data_service_path}/adapter/screenlock:distributeddata_screenlock" ] + } + + if (datamgr_service_cloud) { + deps += [ "${data_service_path}/service/cloud:distributeddata_cloud" ] + } + + if (datamgr_service_kvdb) { + deps += [ "${data_service_path}/service/kvdb:distributeddata_kvdb" ] + } + + if (datamgr_service_rdb) { + deps += [ "${data_service_path}/service/rdb:distributeddata_rdb" ] + } + + if (datamgr_service_object) { + deps += [ "${data_service_path}/service/object:distributeddata_object" ] + } } -ohos_unittest("ObjectAssetLoaderTest") { +ohos_unittest("RdbServiceImplTest") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } module_out_path = module_output_path sources = [ - "../object/src/object_asset_loader.cpp", - "../object/src/object_asset_machine.cpp", - "../object/src/object_snapshot.cpp", - "object_asset_loader_test.cpp", + "${data_service_path}/service/test/mock/general_store_mock.cpp", + "${data_service_path}/service/test/mock/cursor_mock.cpp", + "mock/device_manager_adapter_mock.cpp", + "mock/checker_mock.cpp", + "mock/db_change_data_mock.cpp", + "mock/db_store_mock.cpp", + "rdb_service_impl_test.cpp", ] include_dirs = [ - "${dataobject_path}/frameworks/innerkitsimpl/include/common", - "${dataobject_path}/interfaces/innerkits", - "${relational_store_path}/interfaces/inner_api/common_type/include", + "${data_service_path}/adapter/include/communicator", + "${data_service_path}/framework/include/eventcenter", + "${data_service_path}/service/test/mock", ] - configs = [ ":module_private_config" ] + defines = [ + "TEST_ON_DEVICE", + "OPENSSL_SUPPRESS_DEPRECATED", + ] + cflags = [ + "-Werror", + "-Dprivate=public", + "-Dprotected=public", + "-Wno-multichar", + "-Wno-c99-designator", + "-fno-access-control", # Ignore Private Member Access Control + ] external_deps = [ + "ability_base:base", + "ability_base:want", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtokenid_sdk", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", "c_utils:utils", - "dfs_service:cloudsync_asset_kit_inner", - "dfs_service:distributed_file_daemon_kit_inner", + "data_share:datashare_common", + "data_share:datashare_consumer", + "device_manager:devicemanagersdk", + "dsoftbus:softbus_client", + "googletest:gmock_main", + "googletest:gtest_main", + "hicollie:libhicollie", "hilog:libhilog", "hisysevent:libhisysevent", + "huks:libhukssdk", "ipc:ipc_core", - "json:nlohmann_json_static", + "kv_store:datamgr_common", "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "relational_store:native_rdb", + "resource_management:global_resmgr", ] deps = [ + "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//third_party/googletest:gtest_main", - ] - - cflags = [ - "-Dprivate=public", - "-Dprotected=public", + "${data_service_path}/service/rdb:distributeddata_rdb", ] } -ohos_unittest("ObjectAssetMachineTest") { +ohos_unittest("RdbServiceImplTokenTest") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } module_out_path = module_output_path sources = [ - "../object/src/object_asset_loader.cpp", - "../object/src/object_asset_machine.cpp", - "object_asset_machine_test.cpp", + "mock/access_token_mock.cpp", + "mock/checker_mock.cpp", + "mock/db_change_data_mock.cpp", + "mock/db_store_mock.cpp", + "rdb_service_impl_token_test.cpp", ] include_dirs = [ - "${dataobject_path}/frameworks/innerkitsimpl/include/common", - "${dataobject_path}/interfaces/innerkits", - "${relational_store_path}/interfaces/inner_api/common_type/include", + "${data_service_path}/adapter/include/communicator", + "${data_service_path}/framework/include/eventcenter", + "${data_service_path}/service/test/mock", + ] + + defines = [ + "TEST_ON_DEVICE", + "OPENSSL_SUPPRESS_DEPRECATED", + ] + cflags = [ + "-Werror", + "-Dprotected=public", + "-Wno-multichar", + "-Wno-c99-designator", + "-fno-access-control", # Ignore Private Member Access Control + ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtokenid_sdk", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "data_share:datashare_common", + "data_share:datashare_consumer", + "device_manager:devicemanagersdk", + "dsoftbus:softbus_client", + "googletest:gmock_main", + "googletest:gtest_main", + "hicollie:libhicollie", + "hilog:libhilog", + "hisysevent:libhisysevent", + "huks:libhukssdk", + "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "relational_store:native_rdb", + "resource_management:global_resmgr", + ] + + deps = [ + "${data_service_path}/adapter/utils:distributeddata_utils", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "${data_service_path}/service/rdb:distributeddata_rdb", + ] +} + +ohos_unittest("ObjectAssetLoaderTest") { + module_out_path = module_output_path + sources = [ + "../object/src/object_asset_loader.cpp", + "../object/src/object_asset_machine.cpp", + "../object/src/object_snapshot.cpp", + "object_asset_loader_test.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "c_utils:utils", + "data_object:data_object_inner", + "dfs_service:cloudsync_asset_kit_inner", + "dfs_service:distributed_file_daemon_kit_inner", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "ipc:ipc_core", + "json:nlohmann_json_static", + "kv_store:distributeddata_inner", + ] + + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("ObjectAssetMachineTest") { + module_out_path = module_output_path + sources = [ + "../object/src/object_asset_loader.cpp", + "../object/src/object_asset_machine.cpp", + "object_asset_machine_test.cpp", ] configs = [ ":module_private_config" ] external_deps = [ "c_utils:utils", + "data_object:data_object_inner", "dfs_service:cloudsync_asset_kit_inner", "dfs_service:distributed_file_daemon_kit_inner", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "ipc:ipc_core", @@ -719,7 +843,6 @@ ohos_unittest("ObjectAssetMachineTest") { deps = [ "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//third_party/googletest:gtest_main", ] } @@ -728,6 +851,7 @@ ohos_unittest("ObjectDmsHandlerTest") { cfi = true cfi_cross_dso = true debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" } module_out_path = module_output_path sources = [ @@ -741,7 +865,9 @@ ohos_unittest("ObjectDmsHandlerTest") { external_deps = [ "c_utils:utils", + "device_manager:devicemanagersdk", "dmsfwk:distributed_sdk", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_inner", @@ -750,7 +876,6 @@ ohos_unittest("ObjectDmsHandlerTest") { deps = [ "${data_service_path}/adapter/communicator:distributeddata_communicator", "${data_service_path}/framework:distributeddatasvcfwk", - "//third_party/googletest:gtest_main", ] cflags = [ @@ -762,6 +887,7 @@ ohos_unittest("ObjectDmsHandlerTest") { ohos_unittest("ObjectManagerTest") { module_out_path = module_output_path sources = [ + "${data_service_path}/app/src/kvstore_meta_manager.cpp", "${data_service_path}/service/common/common_types_utils.cpp", "${data_service_path}/service/common/value_proxy.cpp", "../object/src/object_asset_loader.cpp", @@ -774,6 +900,7 @@ ohos_unittest("ObjectManagerTest") { "../object/src/object_service_stub.cpp", "../object/src/object_snapshot.cpp", "../object/src/object_types_utils.cpp", + "mock/device_manager_adapter_mock.cpp", "mock/kv_store_nb_delegate_mock.cpp", "object_manager_test.cpp", "object_service_impl_test.cpp", @@ -781,11 +908,10 @@ ohos_unittest("ObjectManagerTest") { ] include_dirs = [ - "${dataobject_path}/frameworks/innerkitsimpl/include", - "${data_service_path}/service/common", - "${dataobject_path}/frameworks/innerkitsimpl/include/common", - "${dataobject_path}/interfaces/innerkits", "${data_service_path}/adapter/include/utils", + "${data_service_path}/app/src", + "${data_service_path}/service/common", + "${data_service_path}/service/test/mock", ] configs = [ ":module_private_config" ] @@ -795,23 +921,30 @@ ohos_unittest("ObjectManagerTest") { "access_token:libtoken_setproc", "access_token:libtokenid_sdk", "c_utils:utils", + "data_object:data_object_inner", "data_object:distributeddataobject_impl", + "dataclassification:data_transit_mgr", + "device_manager:devicemanagersdk", "dfs_service:cloudsync_asset_kit_inner", "dfs_service:distributed_file_daemon_kit_inner", "dmsfwk:distributed_sdk", + "googletest:gmock_main", + "googletest:gtest_main", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "ipc:ipc_core", "json:nlohmann_json_static", "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", "kv_store:distributeddb", "relational_store:native_rdb", + "safwk:system_ability_fwk", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//third_party/googletest:gtest_main", ] cflags = [ @@ -820,38 +953,104 @@ ohos_unittest("ObjectManagerTest") { ] } -ohos_unittest("ObjectSnapshotTest") { +ohos_unittest("ObjectManagerMockTest") { module_out_path = module_output_path sources = [ + "${data_service_path}/app/src/kvstore_meta_manager.cpp", + "${data_service_path}/service/common/common_types_utils.cpp", + "${data_service_path}/service/common/value_proxy.cpp", "../object/src/object_asset_loader.cpp", "../object/src/object_asset_machine.cpp", + "../object/src/object_callback_proxy.cpp", + "../object/src/object_data_listener.cpp", + "../object/src/object_dms_handler.cpp", + "../object/src/object_manager.cpp", + "../object/src/object_service_impl.cpp", + "../object/src/object_service_stub.cpp", "../object/src/object_snapshot.cpp", - "object_snapshot_test.cpp", + "../object/src/object_types_utils.cpp", + "mock/access_token_mock.cpp", + "mock/account_delegate_mock.cpp", + "mock/device_manager_adapter_mock.cpp", + "mock/kv_store_nb_delegate_mock.cpp", + "object_manager_mock_test.cpp", + "mock/meta_data_manager_mock.cpp", + "mock/device_matrix_mock.cpp", + "mock/distributed_file_daemon_manager_mock.cpp", ] include_dirs = [ - "${dataobject_path}/frameworks/innerkitsimpl/include/common", - "${dataobject_path}/interfaces/innerkits", - "${relational_store_path}/interfaces/inner_api/common_type/include", + "${data_service_path}/adapter/include/utils", + "${data_service_path}/app/src", + "${data_service_path}/service/common", + "${data_service_path}/service/test/mock", ] configs = [ ":module_private_config" ] external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", + "access_token:libtokenid_sdk", "c_utils:utils", + "data_object:distributeddataobject_impl", + "data_object:data_object_inner", + "dataclassification:data_transit_mgr", + "device_manager:devicemanagersdk", "dfs_service:cloudsync_asset_kit_inner", "dfs_service:distributed_file_daemon_kit_inner", + "dmsfwk:distributed_sdk", + "googletest:gmock_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "ipc:ipc_core", + "cJSON:cjson", + "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "relational_store:native_rdb", + "safwk:system_ability_fwk", + ] + + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("ObjectSnapshotTest") { + module_out_path = module_output_path + sources = [ + "../object/src/object_asset_loader.cpp", + "../object/src/object_asset_machine.cpp", + "../object/src/object_snapshot.cpp", + "object_snapshot_test.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "c_utils:utils", + "data_object:data_object_inner", + "dfs_service:cloudsync_asset_kit_inner", + "dfs_service:distributed_file_daemon_kit_inner", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "ipc:ipc_core", "json:nlohmann_json_static", "kv_store:distributeddata_inner", + "relational_store:native_rdb", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//third_party/googletest:gtest_main", ] } @@ -872,9 +1071,6 @@ ohos_unittest("MetaDataTest") { "${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", "${data_service_path}/adapter/include/communicator", ] @@ -882,15 +1078,21 @@ ohos_unittest("MetaDataTest") { external_deps = [ "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "access_token:libtoken_setproc", "c_utils:utils", "dataclassification:data_transit_mgr", + "device_manager:devicemanagersdk", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "ipc:ipc_core", "json:nlohmann_json_static", "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "kv_store:kvdb_inner_lite", + "safwk:system_ability_fwk", ] deps = [ @@ -898,12 +1100,17 @@ ohos_unittest("MetaDataTest") { "${data_service_path}/adapter/communicator:distributeddata_communicator", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/kvdb:distributeddata_kvdb", - "${kv_store_path}/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", ] } ohos_unittest("UdmfRunTimeStoreTest") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } + module_out_path = module_output_path sources = [ "${data_service_path}/app/src/kvstore_meta_manager.cpp", @@ -915,44 +1122,51 @@ ohos_unittest("UdmfRunTimeStoreTest") { "${data_service_path}/adapter/include/communicator", "${data_service_path}/app/src", "${data_service_path}/service/kvdb", + "${data_service_path}/service/matrix/include", "${data_service_path}/service/udmf", "${data_service_path}/service/udmf/store", "${data_service_path}/service/udmf/preprocess", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", + "${data_service_path}/framework/include/directory", ] configs = [ ":module_private_config" ] + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + external_deps = [ "ability_base:base", "ability_base:want", "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "access_token:libtoken_setproc", "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", "c_utils:utils", "dataclassification:data_transit_mgr", + "device_manager:devicemanagersdk", "dsoftbus:softbus_client", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "image_framework:image", "ipc:ipc_core", "kv_store:distributeddata_inner", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "kv_store:distributeddata_mgr", + "openssl:libcrypto_shared", "samgr:samgr_proxy", + "safwk:system_ability_fwk", "udmf:udmf_client", ] deps = [ - "${data_service_path}/adapter/communicator:distributeddata_communicator", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", "${data_service_path}/service/udmf:udmf_server", - "${kv_store_path}/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", ] defines = [ @@ -966,31 +1180,32 @@ ohos_unittest("DataShareServiceImplTest") { cfi = true cfi_cross_dso = true debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" } module_out_path = module_output_path include_dirs = [ - "${datashare_path}/frameworks/native/common/include", - "${datashare_path}/interfaces/inner_api/common/include", - "${datashare_path}/interfaces/inner_api/consumer/include", - "//third_party/json/single_include", + "${data_service_path}/service/config/include", + "${data_service_path}/framework/include/metadata", + "${data_service_path}/service/data_share/common", ] sources = [ "${data_service_path}/service/common/xcollie.cpp", - "${data_service_path}/service/crypto/src/crypto_manager.cpp", "${data_service_path}/service/data_share/common/app_connect_manager.cpp", "${data_service_path}/service/data_share/common/bundle_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/common_utils.cpp", "${data_service_path}/service/data_share/common/db_delegate.cpp", "${data_service_path}/service/data_share/common/div_strategy.cpp", "${data_service_path}/service/data_share/common/extension_ability_manager.cpp", "${data_service_path}/service/data_share/common/extension_connect_adaptor.cpp", "${data_service_path}/service/data_share/common/extension_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/proxy_data_manager.cpp", "${data_service_path}/service/data_share/common/kv_delegate.cpp", "${data_service_path}/service/data_share/common/rdb_delegate.cpp", "${data_service_path}/service/data_share/common/scheduler_manager.cpp", "${data_service_path}/service/data_share/common/seq_strategy.cpp", - "${data_service_path}/service/data_share/common/uri_utils.cpp", + "${data_service_path}/service/data_share/common/utils.cpp", "${data_service_path}/service/data_share/data/published_data.cpp", "${data_service_path}/service/data_share/data/resultset_json_formatter.cpp", "${data_service_path}/service/data_share/data/template_data.cpp", @@ -1018,6 +1233,7 @@ ohos_unittest("DataShareServiceImplTest") { "${data_service_path}/service/data_share/strategies/rdb_notify_strategy.cpp", "${data_service_path}/service/data_share/strategies/subscribe_strategy.cpp", "${data_service_path}/service/data_share/strategies/template_strategy.cpp", + "${data_service_path}/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp", "${data_service_path}/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp", "${data_service_path}/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp", "${data_service_path}/service/data_share/sys_event_subscriber.cpp", @@ -1032,6 +1248,8 @@ ohos_unittest("DataShareServiceImplTest") { "data_share_subscriber_managers_test.cpp", "data_share_types_util_test.cpp", "kv_dalegate_test.cpp", + "mock/account_delegate_mock.cpp", + "data_share_uri_utils_test.cpp", ] configs = [ ":module_private_config" ] @@ -1062,7 +1280,11 @@ ohos_unittest("DataShareServiceImplTest") { "c_utils:utils", "common_event_service:cesfwk_innerkits", "data_share:datashare_common", + "data_share:datashare_common_lite", + "data_share:datashare_consumer", "device_manager:devicemanagersdk", + "googletest:gmock_main", + "googletest:gtest_main", "hicollie:libhicollie", "hilog:libhilog", "hisysevent:libhisysevent", @@ -1072,6 +1294,8 @@ ohos_unittest("DataShareServiceImplTest") { "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddb", + "qos_manager:concurrent_task_client", + "qos_manager:qos", "relational_store:native_rdb", "relational_store:rdb_data_share_adapter", "resource_management:global_resmgr", @@ -1083,13 +1307,212 @@ ohos_unittest("DataShareServiceImplTest") { "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "${kv_store_distributeddb_path}:distributeddb", - "//third_party/googletest:gtest_main", + ] +} + +ohos_unittest("DataShareServiceImplMockTest") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } + module_out_path = module_output_path + + include_dirs = [ "${data_service_path}/service/config/include" ] + + sources = [ + "${data_service_path}/service/common/xcollie.cpp", + "${data_service_path}/service/config/src/model/app_access_check_config.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/datashare_config.cpp", + "${data_service_path}/service/config/src/model/device_sync_app_white_list_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/config/src/model/thread_config.cpp", + "${data_service_path}/service/data_share/common/app_connect_manager.cpp", + "${data_service_path}/service/data_share/common/bundle_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/common_utils.cpp", + "${data_service_path}/service/data_share/common/db_delegate.cpp", + "${data_service_path}/service/data_share/common/div_strategy.cpp", + "${data_service_path}/service/data_share/common/extension_ability_manager.cpp", + "${data_service_path}/service/data_share/common/extension_connect_adaptor.cpp", + "${data_service_path}/service/data_share/common/extension_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/proxy_data_manager.cpp", + "${data_service_path}/service/data_share/common/kv_delegate.cpp", + "${data_service_path}/service/data_share/common/rdb_delegate.cpp", + "${data_service_path}/service/data_share/common/scheduler_manager.cpp", + "${data_service_path}/service/data_share/common/seq_strategy.cpp", + "${data_service_path}/service/data_share/common/utils.cpp", + "${data_service_path}/service/data_share/data/published_data.cpp", + "${data_service_path}/service/data_share/data/resultset_json_formatter.cpp", + "${data_service_path}/service/data_share/data/template_data.cpp", + "${data_service_path}/service/data_share/data_provider_config.cpp", + "${data_service_path}/service/data_share/data_share_db_config.cpp", + "${data_service_path}/service/data_share/data_share_obs_proxy.cpp", + "${data_service_path}/service/data_share/data_share_profile_config.cpp", + "${data_service_path}/service/data_share/data_share_service_impl.cpp", + "${data_service_path}/service/data_share/data_share_service_stub.cpp", + "${data_service_path}/service/data_share/data_share_silent_config.cpp", + "${data_service_path}/service/data_share/dfx/hiview_adapter.cpp", + "${data_service_path}/service/data_share/dfx/hiview_fault_adapter.cpp", + "${data_service_path}/service/data_share/strategies/data_proxy/load_config_from_data_proxy_node_strategy.cpp", + "${data_service_path}/service/data_share/strategies/data_share/load_config_from_data_share_bundle_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/check_is_data_proxy_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/check_is_single_app_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/cross_permission_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_common_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_data_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_from_bundle_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/permission_strategy.cpp", + "${data_service_path}/service/data_share/strategies/get_data_strategy.cpp", + "${data_service_path}/service/data_share/strategies/publish_strategy.cpp", + "${data_service_path}/service/data_share/strategies/rdb_notify_strategy.cpp", + "${data_service_path}/service/data_share/strategies/subscribe_strategy.cpp", + "${data_service_path}/service/data_share/strategies/template_strategy.cpp", + "${data_service_path}/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp", + "${data_service_path}/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp", + "${data_service_path}/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp", + "${data_service_path}/service/data_share/sys_event_subscriber.cpp", + "data_share_sys_event_subscriber_test.cpp", + "data_share_scheduler_manager_test.cpp", + "mock/config_factory_mock.cpp", + ] + + configs = [ ":module_private_config" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-Wno-multichar", + "-Wno-c99-designator", + "-Dprivate=public", + "-Dprotected=public", + ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "ability_runtime:wantagent_innerkits", + "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", + "access_token:libtokenid_sdk", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "data_share:datashare_common", + "data_share:datashare_common_lite", + "data_share:datashare_consumer", + "device_manager:devicemanagersdk", + "googletest:gmock_main", + "googletest:gtest_main", + "hicollie:libhicollie", + "hilog:libhilog", + "hisysevent:libhisysevent", + "huks:libhukssdk", + "init:libbegetutil", + "ipc:ipc_core", + "cJSON:cjson", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "kv_store:distributeddb", + "qos_manager:concurrent_task_client", + "qos_manager:qos", + "relational_store:native_rdb", + "relational_store:rdb_data_share_adapter", + "resource_management:global_resmgr", + "samgr:samgr_proxy", + "time_service:time_client", + ] + + deps = [ + "${data_service_path}/adapter/utils:distributeddata_utils", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + ] +} + +ohos_unittest("KvdbServicePasswordTest") { + module_out_path = module_output_path + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } + sources = [ + "kvdb_service_password_test.cpp", + ] + + include_dirs = [ + "${data_service_path}/app/src", + "${data_service_path}/service/kvdb", + "${data_service_path}/adapter/include/account", + "${data_service_path}/framework/include", + "${data_service_path}/framework/include/cloud", + "${data_service_path}/framework/include/eventcenter", + "${data_service_path}/service/test/mock", + "${data_service_path}/adapter/include/communicator", + ] + + configs = [ ":module_private_config" ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "access_token:libtoken_setproc", + "c_utils:utils", + "dataclassification:data_transit_mgr", + "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "ipc:ipc_core", + "json:nlohmann_json_static", + "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "kv_store:kvdb_inner_lite", + "relational_store:native_rdb", + "safwk:system_ability_fwk", + ] + + deps = [ + "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service/kvdb:distributeddata_kvdb", + "mock:distributeddata_mock_static", ] } ohos_unittest("KvdbServiceImplTest") { module_out_path = module_output_path + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } sources = [ "${data_service_path}/app/src/kvstore_meta_manager.cpp", "kvdb_service_impl_test.cpp", @@ -1108,9 +1531,6 @@ ohos_unittest("KvdbServiceImplTest") { "${data_service_path}/framework/include/cloud", "${data_service_path}/framework/include/eventcenter", "${data_service_path}/service/test/mock", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", "${data_service_path}/adapter/include/communicator", ] @@ -1123,17 +1543,24 @@ ohos_unittest("KvdbServiceImplTest") { external_deps = [ "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "access_token:libtoken_setproc", "c_utils:utils", "dataclassification:data_transit_mgr", "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", "googletest:gmock_main", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "ipc:ipc_core", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "kv_store:kvdb_inner_lite", "relational_store:native_rdb", + "safwk:system_ability_fwk", ] deps = [ @@ -1141,9 +1568,7 @@ ohos_unittest("KvdbServiceImplTest") { "${data_service_path}/adapter/communicator:distributeddata_communicator", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/kvdb:distributeddata_kvdb", - "${kv_store_path}/frameworks/libs/distributeddb:distributeddb", "mock:distributeddata_mock_static", - "//third_party/googletest:gtest_main", ] } @@ -1165,7 +1590,9 @@ ohos_unittest("DumpHelperTest") { external_deps = [ "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddb", "relational_store:native_rdb", @@ -1174,21 +1601,93 @@ ohos_unittest("DumpHelperTest") { deps = [ "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//third_party/googletest:gtest_main", ] } ohos_unittest("UdmfServiceImplTest") { module_out_path = module_output_path + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } sources = [ "${data_service_path}/framework/feature/feature_system.cpp", + "${data_service_path}/app/src/kvstore_meta_manager.cpp", "udmf_service_impl_test.cpp", ] include_dirs = [ - "${data_service_path}/service/udmf/store", + "${data_service_path}/adapter/include/account", + "${data_service_path}/adapter/include/communicator", + "${data_service_path}/app/src", + "${data_service_path}/framework/include/account", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/matrix/include", "${data_service_path}/service/udmf", + "${data_service_path}/service/udmf/store", + "${data_service_path}/service/udmf/preprocess", + "${data_service_path}/service/udmf/permission", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "access_token:libtoken_setproc", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "dataclassification:data_transit_mgr", + "device_manager:devicemanagersdk", + "dsoftbus:softbus_client", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "image_framework:image", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "kv_store:distributeddata_mgr", + "openssl:libcrypto_shared", + "samgr:samgr_proxy", + "safwk:system_ability_fwk", + "udmf:udmf_client", + ] + + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "${data_service_path}/service/udmf:udmf_server", + ] + + defines = [ + "private=public", + "protected=public", + ] +} + +ohos_unittest("UdmfServiceImplMockTest") { + module_out_path = module_output_path + sources = [ + "${data_service_path}/framework/feature/feature_system.cpp", + "udmf_service_impl_mock_test.cpp", + ] + + include_dirs = [ + "${data_service_path}/adapter/include/account", + "${data_service_path}/adapter/include/communicator", "${data_service_path}/framework/include", + "${data_service_path}/service/matrix/include", + "${data_service_path}/service/udmf/preprocess", + "${data_service_path}/service/udmf/store", + "${data_service_path}/service/udmf", + "${data_service_path}/service/udmf/permission", + "${data_service_path}/service/test/mock", ] cflags = [ @@ -1199,25 +1698,39 @@ ohos_unittest("UdmfServiceImplTest") { deps = [ "${data_service_path}/service:distributeddatasvc", "${data_service_path}/service/udmf:udmf_server", + "mock:distributeddata_mock_static", ] external_deps = [ "ability_runtime:uri_permission_mgr", "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "access_token:libtoken_setproc", "app_file_service:remote_file_share_native", "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", "c_utils:utils", + "dataclassification:data_transit_mgr", "device_manager:devicemanagersdk", + "googletest:gmock_main", "googletest:gtest_main", "hilog:libhilog", + "hisysevent:libhisysevent", "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddb", + "kv_store:distributeddata_mgr", "relational_store:native_rdb", "samgr:samgr_proxy", + "safwk:system_ability_fwk", "udmf:udmf_client", ] + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } } ohos_unittest("UdmfServiceStubTest") { @@ -1225,9 +1738,12 @@ ohos_unittest("UdmfServiceStubTest") { sources = [ "udmf_service_stub_test.cpp" ] include_dirs = [ + "${data_service_path}/service/matrix/include", + "${data_service_path}/service/udmf/preprocess", "${data_service_path}/service/udmf/store", "${data_service_path}/service/udmf", "${data_service_path}/framework/include", + "${data_service_path}/service/udmf/permission", ] cflags = [ @@ -1236,6 +1752,7 @@ ohos_unittest("UdmfServiceStubTest") { ] deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", "${data_service_path}/service/udmf:udmf_server", ] @@ -1268,6 +1785,7 @@ ohos_unittest("UdmfServiceStubMockTest") { "${data_service_path}/framework/feature/feature_system.cpp", "${data_service_path}/framework/metadata/appid_meta_data.cpp", "${data_service_path}/framework/metadata/auto_launch_meta_data.cpp", + "${data_service_path}/framework/metadata/capability_meta_data.cpp", "${data_service_path}/framework/metadata/capability_range.cpp", "${data_service_path}/framework/metadata/meta_data_manager.cpp", "${data_service_path}/framework/metadata/secret_key_meta_data.cpp", @@ -1286,8 +1804,8 @@ ohos_unittest("UdmfServiceStubMockTest") { "${data_service_path}/service/udmf/permission/uri_permission_manager.cpp", "${data_service_path}/service/udmf/preprocess/data_handler.cpp", "${data_service_path}/service/udmf/preprocess/preprocess_utils.cpp", + "${data_service_path}/service/udmf/preprocess/udmf_notifier_proxy.cpp", "${data_service_path}/service/udmf/store/runtime_store.cpp", - "${data_service_path}/service/udmf/store/store_account_observer.cpp", "${data_service_path}/service/udmf/store/store_cache.cpp", "${data_service_path}/service/udmf/udmf_service_impl.cpp", "${data_service_path}/service/udmf/udmf_service_stub.cpp", @@ -1295,6 +1813,7 @@ ohos_unittest("UdmfServiceStubMockTest") { ] include_dirs = [ + "${data_service_path}/service/matrix/include", "${data_service_path}/service/udmf/store", "${data_service_path}/service/udmf", "${data_service_path}/framework/include", @@ -1326,6 +1845,7 @@ ohos_unittest("UdmfServiceStubMockTest") { "bundle_framework:appexecfwk_core", "c_utils:utils", "device_manager:devicemanagersdk", + "dfs_service:distributed_file_daemon_kit_inner", "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", @@ -1340,6 +1860,96 @@ ohos_unittest("UdmfServiceStubMockTest") { ] } +ohos_unittest("UdmfPreProcessUtilsTest") { + module_out_path = module_output_path + sources = [ "udmf_preprocess_utils_test.cpp" ] + + include_dirs = [ + "${data_service_path}/service/udmf/permission", + "${data_service_path}/service/udmf/preprocess", + ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + + deps = [ + "${data_service_path}/service:distributeddatasvc", + "${data_service_path}/service/udmf:udmf_server", + ] + + external_deps = [ + "ability_runtime:uri_permission_mgr", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "device_manager:devicemanagersdk", + "googletest:gtest_main", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "relational_store:native_rdb", + "udmf:udmf_client", + ] +} + +ohos_unittest("UdmfPreProcessUtilsMockTest") { + module_out_path = module_output_path + sources = [ + "${data_service_path}/service/test/mock/access_token_mock.cpp", + "${data_service_path}/service/udmf/preprocess/preprocess_utils.cpp", + "udmf_preprocess_utils_mock_test.cpp", + ] + + include_dirs = [ + "${data_service_path}/service/matrix/include", + "${data_service_path}/service/udmf/preprocess", + "${data_service_path}/service/test/mock", + "${data_service_path}/service/udmf/store", + "${data_service_path}/framework/include/account", + "${data_service_path}/adapter/include/communicator", + ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + + deps = [ + "${data_service_path}/service:distributeddatasvc", + "mock:distributeddata_mock_static", + ] + + external_deps = [ + "ability_runtime:uri_permission_mgr", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "access_token:libtokenid_sdk", + "app_file_service:remote_file_share_native", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "device_manager:devicemanagersdk", + "dfs_service:distributed_file_daemon_kit_inner", + "googletest:gmock_main", + "googletest:gtest_main", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "hilog:libhilog", + "ipc:ipc_single", + "kv_store:datamgr_common", + "samgr:samgr_proxy", + "udmf:udmf_client", + ] +} + ohos_unittest("UdmfCheckerManagerTest") { module_out_path = module_output_path sources = [ @@ -1524,11 +2134,14 @@ ohos_unittest("BootStrapMockTest") { module_out_path = module_output_path sources = [ "${data_service_path}/service/bootstrap/src/bootstrap.cpp", + "${data_service_path}/service/config/src/model/app_access_check_config.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/datashare_config.cpp", + "${data_service_path}/service/config/src/model/device_sync_app_white_list_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", @@ -1547,8 +2160,9 @@ ohos_unittest("BootStrapMockTest") { deps = [ "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/backup:distributeddata_backup", - "../../framework:distributeddatasvcfwk", ] cflags = [ @@ -1690,7 +2304,6 @@ ohos_unittest("UpgradeMockTest") { "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/bootstrap:distributeddata_bootstrap", - "${data_service_path}/service/crypto:distributeddata_crypto", "${data_service_path}/service/matrix:distributeddata_matrix", "${data_service_path}/service/rdb:distributeddata_rdb", "${data_service_path}/service/test/mock:distributeddata_mock_static", @@ -1787,6 +2400,7 @@ ohos_unittest("BackupManagerServiceTest") { "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", "kv_store:distributeddb", + "safwk:system_ability_fwk", ] deps = [ @@ -1798,6 +2412,93 @@ ohos_unittest("BackupManagerServiceTest") { ] } +ohos_unittest("UdmfServiceImplDbCorruptionMockTest") { + module_out_path = module_output_path + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } + sources = [ + "${data_service_path}/app/src/kvstore_meta_manager.cpp", + "${data_service_path}/service/udmf/lifecycle/clean_on_startup.cpp", + "${data_service_path}/service/udmf/lifecycle/clean_on_timeout.cpp", + "${data_service_path}/service/udmf/lifecycle/lifecycle_manager.cpp", + "${data_service_path}/service/udmf/lifecycle/lifecycle_policy.cpp", + "${data_service_path}/service/udmf/permission/checker_manager.cpp", + "${data_service_path}/service/udmf/permission/data_checker.cpp", + "${data_service_path}/service/udmf/permission/uri_permission_manager.cpp", + "${data_service_path}/service/udmf/preprocess/data_handler.cpp", + "${data_service_path}/service/udmf/preprocess/udmf_notifier_proxy.cpp", + "${data_service_path}/service/udmf/store/runtime_store.cpp", + "${data_service_path}/service/udmf/store/store_cache.cpp", + "${data_service_path}/service/udmf/udmf_service_impl.cpp", + "${data_service_path}/service/udmf/udmf_service_stub.cpp", + "mock/kv_store_nb_delegate_corruption_mock.cpp", + "mock/preprocess_utils_mock.cpp", + "udmf_db_corruption_mock_test.cpp", + ] + + include_dirs = [ + "${data_service_path}/adapter/include/account", + "${data_service_path}/adapter/include/communicator", + "${data_service_path}/app/src", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/matrix/include", + "${data_service_path}/service/udmf", + "${data_service_path}/service/udmf/store", + "${data_service_path}/service/udmf/preprocess", + "${data_service_path}/service/udmf/permission", + "${data_service_path}/service/test/mock", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "ability_base:zuri", + "ability_runtime:uri_permission_mgr", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "access_token:libtoken_setproc", + "access_token:libtokenid_sdk", + "app_file_service:remote_file_share_native", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "dataclassification:data_transit_mgr", + "device_manager:devicemanagersdk", + "dfs_service:distributed_file_daemon_kit_inner", + "dsoftbus:softbus_client", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "openssl:libcrypto_shared", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + "udmf:udmf_client", + ] + + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + ] + + defines = [ + "private=public", + "protected=public", + ] +} + ############################################################################### group("unittest") { testonly = true @@ -1811,6 +2512,7 @@ group("unittest") { if (datamgr_service_cloud) { deps += [ ":CloudDataTest", + ":CloudDataMockTest", ":CloudServiceImplTest", ":CloudTest", "ohos_test:copy_ohos_test", @@ -1821,8 +2523,12 @@ group("unittest") { if (datamgr_service_udmf) { deps += [ ":UdmfCheckerManagerTest", + ":UdmfPreProcessUtilsMockTest", + ":UdmfPreProcessUtilsTest", ":UdmfRunTimeStoreTest", + ":UdmfServiceImplMockTest", ":UdmfServiceImplTest", + ":UdmfServiceImplDbCorruptionMockTest", ":UdmfServiceStubMockTest", ":UdmfServiceStubTest", ] @@ -1835,12 +2541,15 @@ group("unittest") { ":ObjectDmsHandlerTest", ":ObjectManagerTest", ":ObjectSnapshotTest", + ":ObjectManagerMockTest", ] } if (datamgr_service_rdb) { deps += [ ":RdbResultSetImplTest", + ":RdbServiceImplTest", + ":RdbServiceImplTokenTest", ":RdbServiceTest", ] } @@ -1852,6 +2561,7 @@ group("unittest") { ":KVDBGeneralStoreAbnormalTest", ":KVDBGeneralStoreTest", ":KvdbServiceImplTest", + ":KvdbServicePasswordTest", ":QueryHelperUnitTest", ":UpgradeMockTest", ":UserDelegateMockTest", @@ -1859,7 +2569,10 @@ group("unittest") { } if (datamgr_service_data_share) { - deps += [ ":DataShareServiceImplTest" ] + deps += [ + ":DataShareServiceImplTest", + ":DataShareServiceImplMockTest", + ] } deps += [ diff --git a/datamgr_service/services/distributeddataservice/service/test/auth_delegate_mock_test.cpp b/datamgr_service/services/distributeddataservice/service/test/auth_delegate_mock_test.cpp index 1d6c08d7ef1b9c0b9fd7abd2a7b0923bcf752818..5b1b206b2f9f1dc1e3ca75860bcf775a9ee73658 100644 --- a/datamgr_service/services/distributeddataservice/service/test/auth_delegate_mock_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/auth_delegate_mock_test.cpp @@ -91,7 +91,7 @@ HWTEST_F(AuthDelegateMockTest, CheckAccess001, testing::ext::TestSize.Level0) EXPECT_CALL(*userDelegateMock, GetRemoteUserStatus(_)).WillOnce(Return(peerUsers)); EXPECT_CALL(*devMgrAdapterMock, IsOHOSType(_)).WillOnce(Return(false)); auto result = authHandler->CheckAccess(localUserId, peerUserId, peerDevId, aclParams); - EXPECT_TRUE(result.first); + EXPECT_FALSE(result.first); } /** diff --git a/datamgr_service/services/distributeddataservice/service/test/backup_manager_service_test.cpp b/datamgr_service/services/distributeddataservice/service/test/backup_manager_service_test.cpp index fac7bdbce0f5f5d902ae1a40dd7a9b8f13f86efc..654adadf5b5fb25a1f9277bbbc61c213a9500294 100644 --- a/datamgr_service/services/distributeddataservice/service/test/backup_manager_service_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/backup_manager_service_test.cpp @@ -20,9 +20,11 @@ #include "backup_manager.h" #include "backuprule/backup_rule_manager.h" #include "bootstrap.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter.h" #include "directory/directory_manager.h" +#include "file_ex.h" +#include "ipc_skeleton.h" #include "log_print.h" #include "metadata/meta_data_manager.h" #include "kvstore_meta_manager.h" @@ -33,10 +35,17 @@ using namespace std; using namespace OHOS::DistributedData; namespace OHOS::Test { namespace DistributedDataTest { +static constexpr int32_t LOOP_NUM = 2; static constexpr uint32_t SKEY_SIZE = 32; static constexpr int MICROSEC_TO_SEC_TEST = 1000; static constexpr const char *TEST_BACKUP_BUNDLE = "test_backup_bundleName"; static constexpr const char *TEST_BACKUP_STOREID = "test_backup_storeId"; +static constexpr const char *BASE_DIR = "/data/service/el1/public/database/test_backup_bundleName"; +static constexpr const char *DATA_DIR = "/data/service/el1/public/database/test_backup_bundleName/rdb"; +static constexpr const char *BACKUP_DIR = "/data/service/el1/public/database/test_backup_bundleName/rdb/backup"; +static constexpr const char *STORE_DIR = + "/data/service/el1/public/database/test_backup_bundleName/rdb/backup/test_backup_storeId"; +static constexpr const char *AUTO_BACKUP_NAME = "/autoBackup.bak"; class BackupManagerServiceTest : public testing::Test { public: class TestRule : public BackupRuleManager::BackupRule { @@ -57,10 +66,17 @@ public: void SetUp(); void TearDown(); static std::vector Random(uint32_t len); - void InitMetaData(); - StoreMetaData metaData_; + static void InitMetaData(); + static void Exporter(const StoreMetaData &meta, const std::string &backupPath, bool &result); + static void ConfigExport(bool flag); + + static StoreMetaData metaData_; + static bool isExport_; }; +StoreMetaData BackupManagerServiceTest::metaData_; +bool BackupManagerServiceTest::isExport_ = false; + void BackupManagerServiceTest::SetUpTestCase(void) { auto executors = std::make_shared(1, 0); @@ -71,6 +87,9 @@ void BackupManagerServiceTest::SetUpTestCase(void) DistributedKv::KvStoreMetaManager::GetInstance().BindExecutor(executors); DistributedKv::KvStoreMetaManager::GetInstance().InitMetaParameter(); DistributedKv::KvStoreMetaManager::GetInstance().InitMetaListener(); + InitMetaData(); + MetaDataManager::GetInstance().DelMeta(metaData_.GetSecretKey(), true); + MetaDataManager::GetInstance().DelMeta(metaData_.GetBackupSecretKey(), true); } void BackupManagerServiceTest::TearDownTestCase() @@ -94,10 +113,11 @@ void BackupManagerServiceTest::InitMetaData() metaData_.area = OHOS::DistributedKv::EL1; metaData_.instanceId = 0; metaData_.isAutoSync = true; - metaData_.storeType = DistributedKv::KvStoreType::SINGLE_VERSION; + metaData_.storeType = StoreMetaData::StoreType::STORE_KV_BEGIN; metaData_.storeId = TEST_BACKUP_STOREID; metaData_.dataDir = "/data/service/el1/public/database/" + std::string(TEST_BACKUP_BUNDLE) + "/kvdb"; metaData_.securityLevel = OHOS::DistributedKv::SecurityLevel::S2; + metaData_.tokenId = IPCSkeleton::GetSelfTokenID(); } std::vector BackupManagerServiceTest::Random(uint32_t len) @@ -111,6 +131,21 @@ std::vector BackupManagerServiceTest::Random(uint32_t len) return key; } +void BackupManagerServiceTest::ConfigExport(bool flag) +{ + isExport_ = flag; +} + +void BackupManagerServiceTest::Exporter(const StoreMetaData &meta, const std::string &backupPath, bool &result) +{ + (void)meta; + result = isExport_; + if (isExport_) { + std::vector content(TEST_BACKUP_BUNDLE, TEST_BACKUP_BUNDLE + std::strlen(TEST_BACKUP_BUNDLE)); + result = SaveBufferToFile(backupPath, content); + } +} + /** * @tc.name: Init * @tc.desc: Init testing exception branching scenarios. @@ -297,18 +332,134 @@ HWTEST_F(BackupManagerServiceTest, GetClearType002, TestSize.Level1) } /** -* @tc.name: GetPassWord -* @tc.desc: GetPassWord testing exception branching scenarios. +* @tc.name: GetPassWordTest001 +* @tc.desc: get password fail with exception branch * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong */ -HWTEST_F(BackupManagerServiceTest, GetPassWord, TestSize.Level1) +HWTEST_F(BackupManagerServiceTest, GetPassWordTest001, TestSize.Level1) { StoreMetaData meta; - std::vector password; - bool status = BackupManager::GetInstance().GetPassWord(meta, password); - EXPECT_FALSE(status); + auto password = BackupManager::GetInstance().GetPassWord(meta); + ASSERT_TRUE(password.empty()); + + SecretKeyMetaData secretKey; + secretKey.area = metaData_.area; + secretKey.storeType = metaData_.storeType; + auto result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetBackupSecretKey(), secretKey, true); + ASSERT_TRUE(result); + password = BackupManager::GetInstance().GetPassWord(metaData_); + ASSERT_TRUE(password.empty()); + + auto key = Random(SKEY_SIZE); + ASSERT_FALSE(key.empty()); + secretKey.sKey = key; + secretKey.nonce = key; + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetBackupSecretKey(), secretKey, true); + ASSERT_TRUE(result); + password = BackupManager::GetInstance().GetPassWord(metaData_); + ASSERT_TRUE(password.empty()); + + MetaDataManager::GetInstance().DelMeta(metaData_.GetBackupSecretKey(), true); +} + +/** +* @tc.name: GetPassWordTest002 +* @tc.desc: get backup password success +* @tc.type: FUNC +*/ +HWTEST_F(BackupManagerServiceTest, GetPassWordTest002, TestSize.Level1) +{ + auto key = Random(SKEY_SIZE); + ASSERT_FALSE(key.empty()); + CryptoManager::CryptoParams encryptParams; + auto encryptKey = CryptoManager::GetInstance().Encrypt(key, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + + SecretKeyMetaData secretKey; + secretKey.area = encryptParams.area; + secretKey.storeType = metaData_.storeType; + secretKey.sKey = encryptKey; + secretKey.nonce = encryptParams.nonce; + auto result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetBackupSecretKey(), secretKey, true); + ASSERT_TRUE(result); + + for (int32_t index = 0; index < LOOP_NUM; ++index) { + auto password = BackupManager::GetInstance().GetPassWord(metaData_); + ASSERT_FALSE(password.empty()); + ASSERT_EQ(password.size(), key.size()); + for (size_t i = 0; i < key.size(); ++i) { + ASSERT_EQ(password[i], key[i]); + } + } + + MetaDataManager::GetInstance().DelMeta(metaData_.GetBackupSecretKey(), true); +} + +/** +* @tc.name: DoBackupTest001 +* @tc.desc: do backup with every condition +* @tc.type: FUNC +*/ +HWTEST_F(BackupManagerServiceTest, DoBackupTest001, TestSize.Level1) +{ + metaData_.storeType = StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN; + mkdir(BASE_DIR, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + mkdir(DATA_DIR, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + mkdir(BACKUP_DIR, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + mkdir(STORE_DIR, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + + auto backupPath = DirectoryManager::GetInstance().GetStoreBackupPath(metaData_); + ASSERT_EQ(backupPath, STORE_DIR); + + std::string backupFilePath = backupPath + AUTO_BACKUP_NAME; + + std::shared_ptr testManager = std::make_shared(); + testManager->DoBackup(metaData_); + ASSERT_NE(access(backupFilePath.c_str(), F_OK), 0); + + testManager->RegisterExporter(metaData_.storeType, Exporter); + ConfigExport(false); + testManager->DoBackup(metaData_); + ASSERT_NE(access(backupFilePath.c_str(), F_OK), 0); + + ConfigExport(true); + metaData_.isEncrypt = false; + testManager->DoBackup(metaData_); + ASSERT_EQ(access(backupFilePath.c_str(), F_OK), 0); + (void)remove(backupFilePath.c_str()); + + MetaDataManager::GetInstance().DelMeta(metaData_.GetSecretKey(), true); + SecretKeyMetaData secretKey; + auto result = MetaDataManager::GetInstance().LoadMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_FALSE(result); + + metaData_.isEncrypt = true; + testManager->DoBackup(metaData_); + ASSERT_NE(access(backupFilePath.c_str(), F_OK), 0); + + SecretKeyMetaData backupSecretKey; + result = MetaDataManager::GetInstance().LoadMeta(metaData_.GetBackupSecretKey(), backupSecretKey, true); + ASSERT_FALSE(result); + + secretKey.area = metaData_.area; + secretKey.storeType = metaData_.storeType; + auto key = Random(SKEY_SIZE); + ASSERT_FALSE(key.empty()); + secretKey.sKey = key; + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_TRUE(result); + testManager->DoBackup(metaData_); + ASSERT_EQ(access(backupFilePath.c_str(), F_OK), 0); + result = MetaDataManager::GetInstance().LoadMeta(metaData_.GetBackupSecretKey(), backupSecretKey, true); + ASSERT_TRUE(result); + + MetaDataManager::GetInstance().DelMeta(metaData_.GetSecretKey(), true); + MetaDataManager::GetInstance().DelMeta(metaData_.GetBackupSecretKey(), true); + (void)remove(backupFilePath.c_str()); + (void)remove(STORE_DIR); + (void)remove(BACKUP_DIR); + (void)remove(DATA_DIR); + (void)remove(BASE_DIR); } /** diff --git a/datamgr_service/services/distributeddataservice/service/test/cloud_data_mock_test.cpp b/datamgr_service/services/distributeddataservice/service/test/cloud_data_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5f7e68b9da4d31b848c9918b60c254f2429eee94 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/cloud_data_mock_test.cpp @@ -0,0 +1,403 @@ +/* +* Copyright (c) 2025 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 "CloudDataMockTest" + +#include +#include + +#include "cloud/cloud_server.h" +#include "cloud_service_impl.h" +#include "communicator/device_manager_adapter.h" +#include "device_matrix.h" +#include "eventcenter/event_center.h" +#include "ipc_skeleton.h" +#include "log_print.h" +#include "metadata/meta_data_manager.h" +#include "mock/access_token_mock.h" +#include "mock/account_delegate_mock.h" +#include "mock/db_store_mock.h" +#include "network_delegate_mock.h" + +using namespace testing::ext; +using namespace testing; +using namespace DistributedDB; +using namespace OHOS::DistributedData; +using namespace OHOS::Security::AccessToken; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; + +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_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 *TEST_CLOUD_PATH = "/data/app/el2/100/database/test_cloud_bundleName/entry/rdb/" + "test_cloud_store"; +static constexpr const int32_t TEST_TOKEN_FLAG_CALL_COUNT = 3; +class CloudDataMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static inline std::shared_ptr accTokenMock = nullptr; + static SchemaMeta schemaMeta_; + static std::shared_ptr cloudServiceImpl_; + +protected: + static void InitMetaData(); + static void InitSchemaMeta(); + static void InitCloudInfo(); + static std::shared_ptr dbStoreMock_; + static StoreMetaData metaData_; + static CloudInfo cloudInfo_; + static NetworkDelegateMock delegate_; + static inline AccountDelegateMock *accountDelegateMock = nullptr; +}; + +class CloudServerMock : public CloudServer { +public: + std::pair GetServerInfo(int32_t userId, bool needSpaceInfo) override; + std::pair GetAppSchema(int32_t userId, const std::string &bundleName) override; + virtual ~CloudServerMock() = default; + static constexpr uint64_t REMAINSPACE = 1000; + static constexpr uint64_t TATALSPACE = 2000; + static constexpr int32_t INVALID_USER_ID = -1; +}; + +std::pair CloudServerMock::GetServerInfo(int32_t userId, bool needSpaceInfo) +{ + CloudInfo cloudInfo; + cloudInfo.user = userId; + cloudInfo.id = TEST_CLOUD_ID; + cloudInfo.remainSpace = REMAINSPACE; + cloudInfo.totalSpace = TATALSPACE; + 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); + return { E_OK, cloudInfo }; +} + +std::pair CloudServerMock::GetAppSchema(int32_t userId, const std::string &bundleName) +{ + if (userId == INVALID_USER_ID) { + return { E_ERROR, CloudDataMockTest::schemaMeta_ }; + } + + if (bundleName.empty()) { + SchemaMeta schemaMeta; + return { E_OK, schemaMeta }; + } + return { E_OK, CloudDataMockTest::schemaMeta_ }; +} + +std::shared_ptr CloudDataMockTest::dbStoreMock_ = std::make_shared(); +SchemaMeta CloudDataMockTest::schemaMeta_; +StoreMetaData CloudDataMockTest::metaData_; +CloudInfo CloudDataMockTest::cloudInfo_; +std::shared_ptr CloudDataMockTest::cloudServiceImpl_ = + std::make_shared(); +NetworkDelegateMock CloudDataMockTest::delegate_; + +void CloudDataMockTest::InitMetaData() +{ + metaData_.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData_.appId = TEST_CLOUD_APPID; + metaData_.bundleName = TEST_CLOUD_BUNDLE; + metaData_.tokenId = OHOS::IPCSkeleton::GetCallingTokenID(); + metaData_.user = std::to_string(AccountDelegate::GetInstance()->GetUserByToken(metaData_.tokenId)); + metaData_.area = OHOS::DistributedKv::EL1; + metaData_.instanceId = 0; + metaData_.isAutoSync = true; + metaData_.storeType = DistributedRdb::RDB_DEVICE_COLLABORATION; + metaData_.storeId = TEST_CLOUD_STORE; + metaData_.dataDir = TEST_CLOUD_PATH; + PolicyValue value; + value.type = OHOS::DistributedKv::PolicyType::IMMEDIATE_SYNC_ON_ONLINE; +} + +void CloudDataMockTest::InitSchemaMeta() +{ + SchemaMeta::Field field1; + field1.colName = "test_cloud_field_name1"; + field1.alias = "test_cloud_field_alias1"; + SchemaMeta::Field field2; + field2.colName = "test_cloud_field_name2"; + field2.alias = "test_cloud_field_alias2"; + + SchemaMeta::Table table; + table.name = "test_cloud_table_name"; + table.alias = "test_cloud_table_alias"; + table.fields.emplace_back(field1); + table.fields.emplace_back(field2); + + SchemaMeta::Database database; + database.name = TEST_CLOUD_STORE; + database.alias = TEST_CLOUD_DATABASE_ALIAS_1; + database.tables.emplace_back(table); + + schemaMeta_.version = 1; + schemaMeta_.bundleName = TEST_CLOUD_BUNDLE; + schemaMeta_.databases.emplace_back(database); + database.alias = TEST_CLOUD_DATABASE_ALIAS_2; + schemaMeta_.databases.emplace_back(database); + schemaMeta_.e2eeEnable = false; +} + +void CloudDataMockTest::InitCloudInfo() +{ + cloudInfo_.user = AccountDelegate::GetInstance()->GetUserByToken(IPCSkeleton::GetCallingTokenID()); + 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); +} + +void CloudDataMockTest::SetUpTestCase(void) +{ + accountDelegateMock = new (std::nothrow) AccountDelegateMock(); + if (accountDelegateMock != nullptr) { + AccountDelegate::instance_ = nullptr; + AccountDelegate::RegisterAccountInstance(accountDelegateMock); + } + // 2 means that the GetUserByToken interface will be called twice + EXPECT_CALL(*accountDelegateMock, GetUserByToken(_)).Times(2).WillRepeatedly(Return(0)); + + accTokenMock = std::make_shared(); + BAccessTokenKit::accessTokenkit = accTokenMock; + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(_)) + .Times(TEST_TOKEN_FLAG_CALL_COUNT) + .WillRepeatedly(Return(ATokenTypeEnum::TOKEN_HAP)); + + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + MetaDataManager::GetInstance().SetSyncer( + [](const auto &, auto) { DeviceMatrix::GetInstance().OnChanged(DeviceMatrix::META_STORE_MASK); }); + + auto cloudServerMock = new CloudServerMock(); + CloudServer::RegisterCloudInstance(cloudServerMock); + size_t max = 12; + size_t min = 5; + + auto executor = std::make_shared(max, min); + cloudServiceImpl_->OnBind( + { "CloudDataMockTest", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + auto dmExecutor = std::make_shared(max, min); + DeviceManagerAdapter::GetInstance().Init(dmExecutor); + NetworkDelegate::RegisterNetworkInstance(&delegate_); + delegate_.isNetworkAvailable_ = true; + InitCloudInfo(); + InitMetaData(); + InitSchemaMeta(); +} + +void CloudDataMockTest::TearDownTestCase() +{ + if (accountDelegateMock != nullptr) { + delete accountDelegateMock; + accountDelegateMock = nullptr; + } + accTokenMock = nullptr; + BAccessTokenKit::accessTokenkit = nullptr; +} + +void CloudDataMockTest::SetUp() +{ + MetaDataManager::GetInstance().SaveMeta(cloudInfo_.GetKey(), cloudInfo_, true); + MetaDataManager::GetInstance().SaveMeta(metaData_.GetKey(), metaData_, true); + StoreMetaMapping storeMetaMapping(metaData_); + MetaDataManager::GetInstance().SaveMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); + MetaDataManager::GetInstance().SaveMeta(cloudInfo_.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta_, true); +} + +void CloudDataMockTest::TearDown() +{ + EventCenter::GetInstance().Unsubscribe(CloudEvent::LOCAL_CHANGE); + MetaDataManager::GetInstance().DelMeta(cloudInfo_.GetKey(), true); + MetaDataManager::GetInstance().DelMeta(metaData_.GetKey(), true); + StoreMetaMapping storeMetaMapping(metaData_); + MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true); + MetaDataManager::GetInstance().DelMeta(cloudInfo_.GetSchemaKey(TEST_CLOUD_BUNDLE), true); +} + +/** +* @tc.name: GetSchema001 +* @tc.desc: Test the scenario where the QueryUsers users not empty and return true in the GetSchema function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(CloudDataMockTest, GetSchema001, TestSize.Level1) +{ + EXPECT_CALL(*accountDelegateMock, GetUserByToken(_)).WillOnce(Return(0)); + auto cloudServerMock = std::make_shared(); + auto user = AccountDelegate::GetInstance()->GetUserByToken(OHOS::IPCSkeleton::GetCallingTokenID()); + auto [status, cloudInfo] = cloudServerMock->GetServerInfo(user, true); + ASSERT_TRUE(MetaDataManager::GetInstance().DelMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), true)); + SchemaMeta schemaMeta; + ASSERT_FALSE(MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true)); + std::vector users = { 0, 1 }; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(users), Return(true))); + EXPECT_CALL(*accountDelegateMock, IsVerified(_)).Times(1).WillOnce(DoAll(Return(true))); + DistributedData::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)); + auto ret = MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true); + ASSERT_TRUE(ret); +} + +/** +* @tc.name: GetSchema002 +* @tc.desc: Test the scenario where the QueryUsers users empty in the GetSchema function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(CloudDataMockTest, GetSchema002, TestSize.Level1) +{ + EXPECT_CALL(*accountDelegateMock, GetUserByToken(_)).WillOnce(Return(0)); + auto cloudServerMock = std::make_shared(); + auto user = AccountDelegate::GetInstance()->GetUserByToken(OHOS::IPCSkeleton::GetCallingTokenID()); + auto [status, cloudInfo] = cloudServerMock->GetServerInfo(user, true); + ASSERT_TRUE(MetaDataManager::GetInstance().DelMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), true)); + SchemaMeta schemaMeta; + ASSERT_FALSE(MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true)); + + std::vector users; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)) + .Times(1) + .WillOnce( + DoAll(SetArgReferee<0>(users), Invoke([](std::vector &users) { users.clear(); }), Return(true))); + DistributedData::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)); + auto ret = MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true); + ASSERT_FALSE(ret); +} + +/** +* @tc.name: GetSchema003 +* @tc.desc: Test the scenario where the QueryUsers return false in the GetSchema function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(CloudDataMockTest, GetSchema003, TestSize.Level1) +{ + EXPECT_CALL(*accountDelegateMock, GetUserByToken(_)).WillOnce(Return(0)); + auto cloudServerMock = std::make_shared(); + auto user = AccountDelegate::GetInstance()->GetUserByToken(OHOS::IPCSkeleton::GetCallingTokenID()); + auto [status, cloudInfo] = cloudServerMock->GetServerInfo(user, true); + ASSERT_TRUE(MetaDataManager::GetInstance().DelMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), true)); + SchemaMeta schemaMeta; + ASSERT_FALSE(MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true)); + + std::vector users; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(users), Return(false))); + DistributedData::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)); + auto ret = MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true); + ASSERT_FALSE(ret); +} + +/** +* @tc.name: OnReadyTest_LoginAccount +* @tc.desc: Test OnReady function when IsLoginAccount is true or false +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataMockTest, OnReadyTest_LoginAccount, TestSize.Level0) +{ + ZLOGI("CloudDataMockTest OnReadyTest_LoginAccount start"); + std::string device = "test"; + EXPECT_CALL(*accountDelegateMock, QueryForegroundUsers(_)).WillRepeatedly(testing::Return(false)); + auto ret = cloudServiceImpl_->OnReady(device); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); + + EXPECT_CALL(*accountDelegateMock, IsLoginAccount()).Times(1).WillOnce(testing::Return(false)); + ret = cloudServiceImpl_->OnReady(DeviceManagerAdapter::CLOUD_DEVICE_UUID); + EXPECT_NE(ret, CloudData::CloudService::SUCCESS); + + EXPECT_CALL(*accountDelegateMock, IsLoginAccount()).Times(1).WillOnce(testing::Return(true)); + ret = cloudServiceImpl_->OnReady(DeviceManagerAdapter::CLOUD_DEVICE_UUID); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); + ZLOGI("CloudDataMockTest OnReadyTest_LoginAccount end"); +} + + +/** +* @tc.name: GetHapInfo001 +* @tc.desc: Test GetHapInfo function when GetTokenTypeFlag is not TOKEN_HAP. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataMockTest, GetHapInfo001, TestSize.Level1) +{ + ZLOGI("CloudDataMockTest GetHapInfo001 start"); + DistributedRdb::PredicatesMemo predicates; + predicates.tables_.push_back(TEST_CLOUD_BUNDLE); + std::vector columns; + CloudData::Participants participants; + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(_)) + .Times(1) + .WillOnce(Return(ATokenTypeEnum::TOKEN_NATIVE)); + auto [ret, _] = cloudServiceImpl_->AllocResourceAndShare(TEST_CLOUD_STORE, predicates, columns, participants); + EXPECT_EQ(ret, E_ERROR); + ZLOGI("CloudDataMockTest GetHapInfo001 end"); +} + +/** +* @tc.name: GetHapInfo002 +* @tc.desc: Test GetHapInfo function when GetTokenTypeFlag is TOKEN_HAP. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataMockTest, GetHapInfo002, TestSize.Level1) +{ + ZLOGI("CloudDataMockTest GetHapInfo002 start"); + DistributedRdb::PredicatesMemo predicates; + predicates.tables_.push_back(TEST_CLOUD_BUNDLE); + std::vector columns; + CloudData::Participants participants; + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(_)) + .Times(1) + .WillOnce(Return(ATokenTypeEnum::TOKEN_HAP)); + EXPECT_CALL(*accTokenMock, GetHapTokenInfo(_, _)) + .Times(1) + .WillOnce(Return(-1)); + auto [ret, _] = cloudServiceImpl_->AllocResourceAndShare(TEST_CLOUD_STORE, predicates, columns, participants); + EXPECT_EQ(ret, E_ERROR); + ZLOGI("CloudDataMockTest GetHapInfo002 end"); +} +} // 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 a41c6b732c4ae9faa45e6a18cc2fe078bc26b496..7e29955084907fb46dc304659c89580132cb0eb9 100644 --- a/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp @@ -105,6 +105,8 @@ static constexpr const char *PERMISSION_DISTRIBUTED_DATASYNC = "ohos.permission. static constexpr const char *PERMISSION_ACCESS_SERVICE_DM = "ohos.permission.ACCESS_SERVICE_DM"; static constexpr const char *PERMISSION_MANAGE_LOCAL_ACCOUNTS = "ohos.permission.MANAGE_LOCAL_ACCOUNTS"; static constexpr const char *PERMISSION_GET_BUNDLE_INFO = "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED"; +static constexpr const char *TEST_CLOUD_PATH = + "/data/app/el2/100/database/test_cloud_bundleName/entry/rdb/test_cloud_store"; PermissionDef GetPermissionDef(const std::string &permission) { PermissionDef def = { .permissionName = permission, @@ -211,6 +213,7 @@ void CloudDataTest::InitMetaData() metaData_.isAutoSync = true; metaData_.storeType = DistributedRdb::RDB_DEVICE_COLLABORATION; metaData_.storeId = TEST_CLOUD_STORE; + metaData_.dataDir = TEST_CLOUD_PATH; PolicyValue value; value.type = OHOS::DistributedKv::PolicyType::IMMEDIATE_SYNC_ON_ONLINE; } @@ -240,6 +243,7 @@ void CloudDataTest::InitSchemaMeta() schemaMeta_.databases.emplace_back(database); database.alias = TEST_CLOUD_DATABASE_ALIAS_2; schemaMeta_.databases.emplace_back(database); + schemaMeta_.e2eeEnable = false; } void CloudDataTest::InitCloudInfo() @@ -303,6 +307,8 @@ void CloudDataTest::SetUp() { MetaDataManager::GetInstance().SaveMeta(cloudInfo_.GetKey(), cloudInfo_, true); MetaDataManager::GetInstance().SaveMeta(metaData_.GetKey(), metaData_, true); + StoreMetaMapping storeMetaMapping(metaData_); + MetaDataManager::GetInstance().SaveMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); MetaDataManager::GetInstance().SaveMeta(cloudInfo_.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta_, true); } @@ -311,6 +317,8 @@ void CloudDataTest::TearDown() EventCenter::GetInstance().Unsubscribe(CloudEvent::LOCAL_CHANGE); MetaDataManager::GetInstance().DelMeta(cloudInfo_.GetKey(), true); MetaDataManager::GetInstance().DelMeta(metaData_.GetKey(), true); + StoreMetaMapping storeMetaMapping(metaData_); + MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true); MetaDataManager::GetInstance().DelMeta(cloudInfo_.GetSchemaKey(TEST_CLOUD_BUNDLE), true); } @@ -321,7 +329,7 @@ void CloudDataTest::TearDown() * @tc.require: * @tc.author: ht */ -HWTEST_F(CloudDataTest, GetSchema, TestSize.Level0) +HWTEST_F(CloudDataTest, GetSchema, TestSize.Level1) { auto cloudServerMock = std::make_shared(); auto user = AccountDelegate::GetInstance()->GetUserByToken(OHOS::IPCSkeleton::GetCallingTokenID()); @@ -384,7 +392,7 @@ HWTEST_F(CloudDataTest, QueryStatistics002, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, QueryStatistics003, TestSize.Level0) +HWTEST_F(CloudDataTest, QueryStatistics003, TestSize.Level1) { // Construct the statisticInfo data auto creator = [](const StoreMetaData &metaData) -> GeneralStore* { @@ -420,7 +428,7 @@ HWTEST_F(CloudDataTest, QueryStatistics003, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, QueryStatistics004, TestSize.Level0) +HWTEST_F(CloudDataTest, QueryStatistics004, TestSize.Level1) { // Construct the statisticInfo data auto creator = [](const StoreMetaData &metaData) -> GeneralStore* { @@ -494,11 +502,13 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo003, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, QueryLastSyncInfo004, TestSize.Level0) +HWTEST_F(CloudDataTest, QueryLastSyncInfo004, TestSize.Level1) { auto ret = cloudServiceImpl_->DisableCloud(TEST_CLOUD_ID); EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); - cloudServiceImpl_->OnReady(DeviceManagerAdapter::CLOUD_DEVICE_UUID); + auto user = AccountDelegate::GetInstance()->GetUserByToken(OHOS::IPCSkeleton::GetCallingTokenID()); + cloudServiceImpl_->OnUserChange( + static_cast(AccountStatus::DEVICE_ACCOUNT_SWITCHED), std::to_string(user), "accountId"); sleep(1); @@ -518,7 +528,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo004, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, QueryLastSyncInfo005, TestSize.Level0) +HWTEST_F(CloudDataTest, QueryLastSyncInfo005, TestSize.Level1) { std::map switches; switches.emplace(TEST_CLOUD_ID, true); @@ -526,7 +536,9 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo005, TestSize.Level0) 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); + auto user = AccountDelegate::GetInstance()->GetUserByToken(OHOS::IPCSkeleton::GetCallingTokenID()); + cloudServiceImpl_->OnUserChange( + static_cast(AccountStatus::DEVICE_ACCOUNT_SWITCHED), std::to_string(user), "accountId"); sleep(1); auto [status, result] = @@ -580,7 +592,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo007, TestSize.Level0) lastSyncInfo.syncStatus = 1; MetaDataManager::GetInstance().SaveMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_1), lastSyncInfo, true); - + std::vector lastSyncInfos; MetaDataManager::GetInstance().LoadMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_1), lastSyncInfos, true); @@ -626,7 +638,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo008, TestSize.Level0) lastSyncInfo1.code = 0; MetaDataManager::GetInstance().SaveMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_2), lastSyncInfo1, true); - + std::vector lastSyncInfos; MetaDataManager::GetInstance().LoadMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, ""), lastSyncInfos, true); @@ -679,7 +691,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo009, TestSize.Level0) lastSyncInfo1.code = 0; MetaDataManager::GetInstance().SaveMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_2), lastSyncInfo1, true); - + std::vector lastSyncInfos; MetaDataManager::GetInstance().LoadMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, ""), lastSyncInfos, true); @@ -725,7 +737,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo010, TestSize.Level0) lastSyncInfo1.code = 0; MetaDataManager::GetInstance().SaveMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_2), lastSyncInfo1, true); - + CloudData::SyncManager sync; CloudData::SyncManager::SyncInfo info(user, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_1); auto [status, result] = sync.QueryLastSyncInfo({ { user, TEST_CLOUD_ID, TEST_CLOUD_BUNDLE, "1234"} }); @@ -739,7 +751,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo010, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, QueryLastSyncInfo011, TestSize.Level0) +HWTEST_F(CloudDataTest, QueryLastSyncInfo011, TestSize.Level1) { schemaMeta_.databases[1].name = TEST_CLOUD_STORE_1; MetaDataManager::GetInstance().SaveMeta(cloudInfo_.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta_, true); @@ -785,7 +797,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo012, TestSize.Level0) lastSyncInfo.syncStatus = 1; MetaDataManager::GetInstance().SaveMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_1), lastSyncInfo, true); - + std::vector lastSyncInfos; MetaDataManager::GetInstance().LoadMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_1), lastSyncInfos, true); @@ -868,7 +880,7 @@ HWTEST_F(CloudDataTest, UpdateFinishSyncInfo, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, Share001, TestSize.Level0) +HWTEST_F(CloudDataTest, Share001, TestSize.Level1) { std::string sharingRes = ""; CloudData::Participants participants{}; @@ -883,7 +895,7 @@ HWTEST_F(CloudDataTest, Share001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, Unshare001, TestSize.Level0) +HWTEST_F(CloudDataTest, Unshare001, TestSize.Level1) { std::string sharingRes = ""; CloudData::Participants participants{}; @@ -898,7 +910,7 @@ HWTEST_F(CloudDataTest, Unshare001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, ChangePrivilege001, TestSize.Level0) +HWTEST_F(CloudDataTest, ChangePrivilege001, TestSize.Level1) { std::string sharingRes = ""; CloudData::Participants participants{}; @@ -913,7 +925,7 @@ HWTEST_F(CloudDataTest, ChangePrivilege001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, ChangeConfirmation001, TestSize.Level0) +HWTEST_F(CloudDataTest, ChangeConfirmation001, TestSize.Level1) { std::string sharingRes = ""; int32_t confirmation = 0; @@ -928,7 +940,7 @@ HWTEST_F(CloudDataTest, ChangeConfirmation001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, ConfirmInvitation001, TestSize.Level0) +HWTEST_F(CloudDataTest, ConfirmInvitation001, TestSize.Level1) { std::string sharingRes = ""; int32_t confirmation = 0; @@ -943,7 +955,7 @@ HWTEST_F(CloudDataTest, ConfirmInvitation001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, Exit001, TestSize.Level0) +HWTEST_F(CloudDataTest, Exit001, TestSize.Level1) { std::string sharingRes = ""; std::pair result; @@ -957,7 +969,7 @@ HWTEST_F(CloudDataTest, Exit001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, Query001, TestSize.Level0) +HWTEST_F(CloudDataTest, Query001, TestSize.Level1) { std::string sharingRes = ""; CloudData::QueryResults result; @@ -971,7 +983,7 @@ HWTEST_F(CloudDataTest, Query001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, QueryByInvitation001, TestSize.Level0) +HWTEST_F(CloudDataTest, QueryByInvitation001, TestSize.Level1) { std::string invitation = ""; CloudData::QueryResults result; @@ -1015,7 +1027,7 @@ HWTEST_F(CloudDataTest, AllocResourceAndShare001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, SetGlobalCloudStrategy001, TestSize.Level0) +HWTEST_F(CloudDataTest, SetGlobalCloudStrategy001, TestSize.Level1) { std::vector values; values.push_back(CloudData::NetWorkStrategy::WIFI); @@ -1033,7 +1045,7 @@ HWTEST_F(CloudDataTest, SetGlobalCloudStrategy001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, SetCloudStrategy001, TestSize.Level0) +HWTEST_F(CloudDataTest, SetCloudStrategy001, TestSize.Level1) { std::vector values; values.push_back(CloudData::NetWorkStrategy::WIFI); @@ -1045,6 +1057,126 @@ HWTEST_F(CloudDataTest, SetCloudStrategy001, TestSize.Level0) EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); } +/** +* @tc.name: CloudSync001 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync001, TestSize.Level0) +{ + int32_t syncMode = DistributedData::GeneralStore::NEARBY_BEGIN; + uint32_t seqNum = 10; + // invalid syncMode + auto ret = cloudServiceImpl_->CloudSync("bundleName", "storeId", { syncMode, seqNum }, nullptr); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); +} + +/** +* @tc.name: CloudSync002 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync002, TestSize.Level0) +{ + int32_t syncMode = DistributedData::GeneralStore::NEARBY_PULL_PUSH; + uint32_t seqNum = 10; + // invalid syncMode + auto ret = cloudServiceImpl_->CloudSync("bundleName", "storeId", { syncMode, seqNum }, nullptr); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); +} + +/** +* @tc.name: CloudSync003 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync003, TestSize.Level1) +{ + int32_t syncMode = DistributedData::GeneralStore::CLOUD_BEGIN; + uint32_t seqNum = 10; + auto ret = cloudServiceImpl_->CloudSync("bundleName", "storeId", { syncMode, seqNum }, nullptr); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: CloudSync004 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync004, TestSize.Level1) +{ + int32_t syncMode = DistributedData::GeneralStore::CLOUD_TIME_FIRST; + uint32_t seqNum = 10; + auto ret = cloudServiceImpl_->CloudSync("bundleName", "storeId", { syncMode, seqNum }, nullptr); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: CloudSync005 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync005, TestSize.Level1) +{ + int32_t syncMode = DistributedData::GeneralStore::CLOUD_NATIVE_FIRST; + uint32_t seqNum = 10; + auto ret = cloudServiceImpl_->CloudSync("bundleName", "storeId", { syncMode, seqNum }, nullptr); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: CloudSync006 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync006, TestSize.Level1) +{ + int32_t syncMode = DistributedData::GeneralStore::CLOUD_CLOUD_FIRST; + uint32_t seqNum = 10; + auto ret = cloudServiceImpl_->CloudSync("bundleName", "storeId", { syncMode, seqNum }, nullptr); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: CloudSync007 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync007, TestSize.Level0) +{ + int32_t syncMode = DistributedData::GeneralStore::CLOUD_END; + uint32_t seqNum = 10; + auto ret = cloudServiceImpl_->CloudSync("bundleName", "storeId", { syncMode, seqNum }, nullptr); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); + + CloudData::Details details{}; + uint32_t tokenId = 0; + cloudServiceImpl_->OnAsyncComplete(tokenId, seqNum, std::move(details)); +} + +/** +* @tc.name: InitNotifier001 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, InitNotifier001, TestSize.Level0) +{ + sptr notifier = nullptr; + auto ret = cloudServiceImpl_->InitNotifier(notifier); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); + + ret = cloudServiceImpl_->InitNotifier(notifier); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); +} + /** * @tc.name: Clean * @tc.desc: @@ -1148,7 +1280,7 @@ HWTEST_F(CloudDataTest, NotifyDataChange002, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, NotifyDataChange003, TestSize.Level0) +HWTEST_F(CloudDataTest, NotifyDataChange003, TestSize.Level1) { constexpr const int32_t userId = 100; constexpr const int32_t defaultUserId = 0; @@ -1167,21 +1299,6 @@ HWTEST_F(CloudDataTest, NotifyDataChange003, TestSize.Level0) 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: @@ -1300,7 +1417,7 @@ HWTEST_F(CloudDataTest, EnableCloud, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnEnableCloud, TestSize.Level0) +HWTEST_F(CloudDataTest, OnEnableCloud, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1321,7 +1438,7 @@ HWTEST_F(CloudDataTest, OnEnableCloud, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnDisableCloud, TestSize.Level0) +HWTEST_F(CloudDataTest, OnDisableCloud, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1340,7 +1457,7 @@ HWTEST_F(CloudDataTest, OnDisableCloud, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnChangeAppSwitch, TestSize.Level0) +HWTEST_F(CloudDataTest, OnChangeAppSwitch, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1361,7 +1478,7 @@ HWTEST_F(CloudDataTest, OnChangeAppSwitch, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnClean, TestSize.Level0) +HWTEST_F(CloudDataTest, OnClean, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1382,7 +1499,7 @@ HWTEST_F(CloudDataTest, OnClean, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnNotifyDataChange, TestSize.Level0) +HWTEST_F(CloudDataTest, OnNotifyDataChange, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1402,7 +1519,7 @@ HWTEST_F(CloudDataTest, OnNotifyDataChange, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnNotifyChange, TestSize.Level0) +HWTEST_F(CloudDataTest, OnNotifyChange, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1424,7 +1541,7 @@ HWTEST_F(CloudDataTest, OnNotifyChange, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnQueryStatistics, TestSize.Level0) +HWTEST_F(CloudDataTest, OnQueryStatistics, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1445,7 +1562,7 @@ HWTEST_F(CloudDataTest, OnQueryStatistics, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnQueryLastSyncInfo, TestSize.Level0) +HWTEST_F(CloudDataTest, OnQueryLastSyncInfo, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1466,7 +1583,7 @@ HWTEST_F(CloudDataTest, OnQueryLastSyncInfo, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnSetGlobalCloudStrategy, TestSize.Level0) +HWTEST_F(CloudDataTest, OnSetGlobalCloudStrategy, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1488,7 +1605,7 @@ HWTEST_F(CloudDataTest, OnSetGlobalCloudStrategy, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnAllocResourceAndShare, TestSize.Level0) +HWTEST_F(CloudDataTest, OnAllocResourceAndShare, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1512,7 +1629,7 @@ HWTEST_F(CloudDataTest, OnAllocResourceAndShare, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnShare, TestSize.Level0) +HWTEST_F(CloudDataTest, OnShare, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1534,7 +1651,7 @@ HWTEST_F(CloudDataTest, OnShare, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnUnshare, TestSize.Level0) +HWTEST_F(CloudDataTest, OnUnshare, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1556,7 +1673,7 @@ HWTEST_F(CloudDataTest, OnUnshare, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnExit, TestSize.Level0) +HWTEST_F(CloudDataTest, OnExit, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1577,7 +1694,7 @@ HWTEST_F(CloudDataTest, OnExit, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnChangePrivilege, TestSize.Level0) +HWTEST_F(CloudDataTest, OnChangePrivilege, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1599,7 +1716,7 @@ HWTEST_F(CloudDataTest, OnChangePrivilege, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnQuery, TestSize.Level0) +HWTEST_F(CloudDataTest, OnQuery, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1620,7 +1737,7 @@ HWTEST_F(CloudDataTest, OnQuery, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnQueryByInvitation, TestSize.Level0) +HWTEST_F(CloudDataTest, OnQueryByInvitation, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1641,7 +1758,7 @@ HWTEST_F(CloudDataTest, OnQueryByInvitation, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnConfirmInvitation, TestSize.Level0) +HWTEST_F(CloudDataTest, OnConfirmInvitation, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1663,7 +1780,7 @@ HWTEST_F(CloudDataTest, OnConfirmInvitation, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnChangeConfirmation, TestSize.Level0) +HWTEST_F(CloudDataTest, OnChangeConfirmation, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1700,6 +1817,51 @@ HWTEST_F(CloudDataTest, OnSetCloudStrategy, TestSize.Level0) EXPECT_EQ(ret, ERR_NONE); } +/** +* @tc.name: OnCloudSync +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnCloudSync, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_CLOUD_SYNC, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + std::string bundleName = "bundleName"; + std::string storeId = "storeId"; + CloudData::CloudService::Option option; + option.syncMode = 4; + option.seqNum = 1; + ITypesUtil::Marshal(data, bundleName, storeId, option); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_CLOUD_SYNC, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnInitNotifier +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnInitNotifier, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_INIT_NOTIFIER, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + std::string bundleName = "bundleName"; + sptr notifier = nullptr; + ITypesUtil::Marshal(data, bundleName, notifier); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_INIT_NOTIFIER, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); +} + /** * @tc.name: SharingUtil001 * @tc.desc: @@ -1837,12 +1999,12 @@ HWTEST_F(CloudDataTest, GetPostEventTask, TestSize.Level0) } /** -* @tc.name: GetRetryer +* @tc.name: GetRetryer001 * @tc.desc: Test the input parameters of different interfaces * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, GetRetryer, TestSize.Level0) +HWTEST_F(CloudDataTest, GetRetryer001, TestSize.Level0) { int32_t user = 100; CloudData::SyncManager::SyncInfo info(user); @@ -1860,6 +2022,28 @@ HWTEST_F(CloudDataTest, GetRetryer, TestSize.Level0) EXPECT_TRUE(ret); } +/** +* @tc.name: GetRetryer002 +* @tc.desc: Test the executor_ is nullptr scenarios. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, GetRetryer002, TestSize.Level0) +{ + int32_t user = 100; + std::string prepareTraceId; + CloudData::SyncManager sync; + sync.executor_ = nullptr; + int32_t evtId = 100; + auto event = std::make_unique(evtId); + auto handler = sync.GetClientChangeHandler(); + handler(*event); + CloudData::SyncManager::Duration duration; + CloudData::SyncManager::SyncInfo info(user); + auto ret = sync.GetRetryer(0, info, user)(duration, E_CLOUD_DISABLED, E_CLOUD_DISABLED, prepareTraceId); + EXPECT_FALSE(ret); +} + /** * @tc.name: GetCallback * @tc.desc: Test the processing logic of different progress callbacks @@ -1982,13 +2166,79 @@ HWTEST_F(CloudDataTest, UpdateCloudInfoFromServer, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, GetCloudInfo, TestSize.Level0) +HWTEST_F(CloudDataTest, GetCloudInfo, TestSize.Level1) { MetaDataManager::GetInstance().DelMeta(cloudInfo_.GetKey(), true); auto ret = cloudServiceImpl_->GetCloudInfo(cloudInfo_.user); EXPECT_EQ(ret.first, CloudData::SUCCESS); } +/** +* @tc.name: UpdateSchemaFromServer_001 +* @tc.desc: Test get UpdateSchemaFromServer +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, UpdateSchemaFromServer_001, TestSize.Level1) +{ + auto status = cloudServiceImpl_->UpdateSchemaFromServer(cloudInfo_.user); + EXPECT_EQ(status, CloudData::SUCCESS); +} + +/** + * @tc.name: OnAppInstallTest + * @tc.desc: Test the OnAppInstallTest + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, OnAppInstallTest, TestSize.Level1) +{ + ZLOGI("CloudDataTest OnAppInstallTest start"); + ASSERT_NE(cloudServiceImpl_, nullptr); + ASSERT_NE(cloudServiceImpl_->factory_.staticActs_, nullptr); + int32_t index = 0; + auto status = cloudServiceImpl_->factory_.staticActs_->OnAppInstall(TEST_CLOUD_BUNDLE, cloudInfo_.user, index); + EXPECT_EQ(status, GeneralError::E_OK); +} + +/** + * @tc.name: OnAppUpdateTest + * @tc.desc: Test the OnAppUpdateTest + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, OnAppUpdateTest, TestSize.Level1) +{ + ZLOGI("CloudDataTest OnAppUpdateTest start"); + ASSERT_NE(cloudServiceImpl_, nullptr); + ASSERT_NE(cloudServiceImpl_->factory_.staticActs_, nullptr); + int32_t index = 0; + auto status = cloudServiceImpl_->factory_.staticActs_->OnAppUpdate(TEST_CLOUD_BUNDLE, cloudInfo_.user, index); + EXPECT_EQ(status, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: UpdateE2eeEnableTest +* @tc.desc: Test the UpdateE2eeEnable +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(CloudDataTest, UpdateE2eeEnableTest, TestSize.Level1) +{ + SchemaMeta schemaMeta; + std::string schemaKey = CloudInfo::GetSchemaKey(cloudInfo_.user, TEST_CLOUD_BUNDLE, 0); + ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)); + EXPECT_EQ(schemaMeta.e2eeEnable, schemaMeta_.e2eeEnable); + + ASSERT_NE(cloudServiceImpl_, nullptr); + cloudServiceImpl_->UpdateE2eeEnable(schemaKey, false, TEST_CLOUD_BUNDLE); + ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)); + EXPECT_EQ(schemaMeta.e2eeEnable, schemaMeta_.e2eeEnable); + cloudServiceImpl_->UpdateE2eeEnable(schemaKey, true, TEST_CLOUD_BUNDLE); + ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)); + EXPECT_EQ(schemaMeta.e2eeEnable, true); +} + /** * @tc.name: SubTask * @tc.desc: Test the subtask execution logic @@ -2202,7 +2452,7 @@ HWTEST_F(CloudDataTest, OnAppUninstall, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, GetCloudInfo001, TestSize.Level0) +HWTEST_F(CloudDataTest, GetCloudInfo001, TestSize.Level1) { int32_t userId = 1000; auto [status, cloudInfo] = cloudServiceImpl_->GetCloudInfo(userId); @@ -2228,6 +2478,7 @@ HWTEST_F(CloudDataTest, PreShare, TestSize.Level0) info.bundleName = TEST_CLOUD_BUNDLE; info.storeName = TEST_CLOUD_BUNDLE; info.user = userId; + info.path = TEST_CLOUD_PATH; StoreMetaData meta(info); meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true); @@ -2425,7 +2676,7 @@ HWTEST_F(CloudDataTest, GetPriorityLevel001, TestSize.Level1) }); DistributedRdb::RdbServiceImpl rdbServiceImpl; DistributedRdb::RdbSyncerParam param{ .bundleName_ = TEST_CLOUD_BUNDLE, .storeName_ = TEST_CLOUD_STORE }; - DistributedRdb::RdbService::Option option{ .mode = GeneralStore::SyncMode::CLOUD_ClOUD_FIRST, .isAsync = true }; + DistributedRdb::RdbService::Option option{ .mode = GeneralStore::SyncMode::CLOUD_CLOUD_FIRST, .isAsync = true }; DistributedRdb::PredicatesMemo memo; memo.tables_ = { TEST_CLOUD_TABLE }; rdbServiceImpl.DoCloudSync(param, option, memo, nullptr); @@ -2469,7 +2720,7 @@ HWTEST_F(CloudDataTest, GetPriorityLevel003, TestSize.Level1) }); DistributedRdb::RdbServiceImpl rdbServiceImpl; DistributedRdb::RdbSyncerParam param{ .bundleName_ = TEST_CLOUD_BUNDLE, .storeName_ = TEST_CLOUD_STORE }; - DistributedRdb::RdbService::Option option{ .mode = GeneralStore::SyncMode::CLOUD_ClOUD_FIRST, .isAsync = true }; + DistributedRdb::RdbService::Option option{ .mode = GeneralStore::SyncMode::CLOUD_CLOUD_FIRST, .isAsync = true }; DistributedRdb::PredicatesMemo memo; rdbServiceImpl.DoCloudSync(param, option, memo, nullptr); } @@ -2490,7 +2741,7 @@ HWTEST_F(CloudDataTest, GetPriorityLevel004, TestSize.Level1) }); DistributedRdb::RdbServiceImpl rdbServiceImpl; DistributedRdb::RdbSyncerParam param{ .bundleName_ = TEST_CLOUD_BUNDLE, .storeName_ = TEST_CLOUD_STORE }; - DistributedRdb::RdbService::Option option{ .mode = GeneralStore::SyncMode::CLOUD_ClOUD_FIRST, + DistributedRdb::RdbService::Option option{ .mode = GeneralStore::SyncMode::CLOUD_CLOUD_FIRST, .seqNum = 0, .isAsync = true, .isAutoSync = true }; @@ -2504,10 +2755,10 @@ HWTEST_F(CloudDataTest, GetPriorityLevel004, TestSize.Level1) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, UpdateSchemaFromHap001, TestSize.Level0) +HWTEST_F(CloudDataTest, UpdateSchemaFromHap001, TestSize.Level1) { ASSERT_NE(cloudServiceImpl_, nullptr); - CloudData::CloudServiceImpl::HapInfo info = { .user = -1, .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE,}; + CloudData::CloudServiceImpl::HapInfo info = { .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE, .user = -1 }; auto ret = cloudServiceImpl_->UpdateSchemaFromHap(info); EXPECT_EQ(ret, Status::ERROR); } @@ -2518,10 +2769,10 @@ HWTEST_F(CloudDataTest, UpdateSchemaFromHap001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, UpdateSchemaFromHap002, TestSize.Level0) +HWTEST_F(CloudDataTest, UpdateSchemaFromHap002, TestSize.Level1) { ASSERT_NE(cloudServiceImpl_, nullptr); - CloudData::CloudServiceImpl::HapInfo info = { .user = cloudInfo_.user, .instIndex = 0, .bundleName = "", }; + CloudData::CloudServiceImpl::HapInfo info = { .instIndex = 0, .bundleName = "", .user = cloudInfo_.user }; auto ret = cloudServiceImpl_->UpdateSchemaFromHap(info); EXPECT_EQ(ret, Status::ERROR); } @@ -2532,11 +2783,11 @@ HWTEST_F(CloudDataTest, UpdateSchemaFromHap002, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, UpdateSchemaFromHap003, TestSize.Level0) +HWTEST_F(CloudDataTest, UpdateSchemaFromHap003, TestSize.Level1) { ASSERT_NE(cloudServiceImpl_, nullptr); CloudData::CloudServiceImpl::HapInfo info = { - .user = cloudInfo_.user, .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE, + .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE, .user = cloudInfo_.user }; auto ret = cloudServiceImpl_->UpdateSchemaFromHap(info); EXPECT_EQ(ret, Status::SUCCESS); @@ -2552,8 +2803,9 @@ HWTEST_F(CloudDataTest, UpdateSchemaFromHap003, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, UpdateSchemaFromHap004, TestSize.Level0) +HWTEST_F(CloudDataTest, UpdateSchemaFromHap004, TestSize.Level1) { + ZLOGI("CloudServiceImplTest UpdateSchemaFromHap004 start"); ASSERT_NE(cloudServiceImpl_, nullptr); CloudInfo::AppInfo exampleAppInfo; exampleAppInfo.bundleName = COM_EXAMPLE_TEST_CLOUD; @@ -2565,7 +2817,7 @@ HWTEST_F(CloudDataTest, UpdateSchemaFromHap004, TestSize.Level0) cloudInfo.apps[COM_EXAMPLE_TEST_CLOUD] = std::move(exampleAppInfo); MetaDataManager::GetInstance().SaveMeta(cloudInfo_.GetKey(), cloudInfo, true); CloudData::CloudServiceImpl::HapInfo info = { - .user = cloudInfo_.user, .instIndex = 0, .bundleName = COM_EXAMPLE_TEST_CLOUD, + .instIndex = 0, .bundleName = COM_EXAMPLE_TEST_CLOUD, .user = cloudInfo_.user }; auto ret = cloudServiceImpl_->UpdateSchemaFromHap(info); EXPECT_EQ(ret, Status::SUCCESS); @@ -2585,7 +2837,7 @@ HWTEST_F(CloudDataTest, UpdateClearWaterMark001, TestSize.Level0) { ASSERT_NE(cloudServiceImpl_, nullptr); CloudData::CloudServiceImpl::HapInfo hapInfo = { - .user = cloudInfo_.user, .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE + .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE, .user = cloudInfo_.user }; SchemaMeta::Database database; database.name = TEST_CLOUD_STORE; @@ -2593,7 +2845,7 @@ HWTEST_F(CloudDataTest, UpdateClearWaterMark001, TestSize.Level0) SchemaMeta schemaMeta; schemaMeta.version = 1; schemaMeta.databases.push_back(database); - + SchemaMeta::Database database1; database1.name = TEST_CLOUD_STORE_1; database1.version = 2; @@ -2621,7 +2873,7 @@ HWTEST_F(CloudDataTest, UpdateClearWaterMark002, TestSize.Level0) { ASSERT_NE(cloudServiceImpl_, nullptr); CloudData::CloudServiceImpl::HapInfo hapInfo = { - .user = cloudInfo_.user, .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE + .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE, .user = cloudInfo_.user }; SchemaMeta::Database database; database.name = TEST_CLOUD_STORE; @@ -2629,7 +2881,7 @@ HWTEST_F(CloudDataTest, UpdateClearWaterMark002, TestSize.Level0) SchemaMeta schemaMeta; schemaMeta.version = 1; schemaMeta.databases.push_back(database); - + SchemaMeta::Database database1; database1.name = TEST_CLOUD_STORE; database1.version = 1; @@ -2657,7 +2909,7 @@ HWTEST_F(CloudDataTest, UpdateClearWaterMark003, TestSize.Level0) { ASSERT_NE(cloudServiceImpl_, nullptr); CloudData::CloudServiceImpl::HapInfo hapInfo = { - .user = cloudInfo_.user, .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE + .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE, .user = cloudInfo_.user }; SchemaMeta::Database database; database.name = TEST_CLOUD_STORE; @@ -2665,7 +2917,7 @@ HWTEST_F(CloudDataTest, UpdateClearWaterMark003, TestSize.Level0) SchemaMeta schemaMeta; schemaMeta.version = 1; schemaMeta.databases.push_back(database); - + SchemaMeta::Database database1; database1.name = TEST_CLOUD_STORE; database1.version = 2; @@ -2722,14 +2974,14 @@ HWTEST_F(CloudDataTest, TryUpdateDeviceId001, TestSize.Level1) oldMeta.storeId = "test_storeid_001"; oldMeta.isNeedUpdateDeviceId = true; oldMeta.storeType = StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN; - bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKey(), oldMeta); + bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKeyWithoutPath(), oldMeta); EXPECT_EQ(isSuccess, true); StoreMetaData meta1 = oldMeta; auto ret = rdbServiceImpl.TryUpdateDeviceId(param, oldMeta, meta1); EXPECT_EQ(ret, true); - MetaDataManager::GetInstance().DelMeta(oldMeta.GetKey()); + MetaDataManager::GetInstance().DelMeta(oldMeta.GetKeyWithoutPath()); } - + /** * @tc.name: TryUpdateDeviceId002 * @tc.desc: TryUpdateDeviceId test @@ -2748,14 +3000,14 @@ HWTEST_F(CloudDataTest, TryUpdateDeviceId002, TestSize.Level1) oldMeta.storeId = "test_storeid_001"; oldMeta.isNeedUpdateDeviceId = false; oldMeta.storeType = StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN; - bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKey(), oldMeta); + bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKeyWithoutPath(), oldMeta); EXPECT_EQ(isSuccess, true); StoreMetaData meta1 = oldMeta; auto ret = rdbServiceImpl.TryUpdateDeviceId(param, oldMeta, meta1); EXPECT_EQ(ret, true); - MetaDataManager::GetInstance().DelMeta(oldMeta.GetKey()); + MetaDataManager::GetInstance().DelMeta(oldMeta.GetKeyWithoutPath()); } - + /** * @tc.name: TryUpdateDeviceId003 * @tc.desc: TryUpdateDeviceId test @@ -2774,14 +3026,14 @@ HWTEST_F(CloudDataTest, TryUpdateDeviceId003, TestSize.Level1) oldMeta.storeId = "test_storeid_001"; oldMeta.isNeedUpdateDeviceId = true; oldMeta.storeType = StoreMetaData::StoreType::STORE_RELATIONAL_END; - bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKey(), oldMeta); + bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKeyWithoutPath(), oldMeta); EXPECT_EQ(isSuccess, true); StoreMetaData meta1 = oldMeta; auto ret = rdbServiceImpl.TryUpdateDeviceId(param, oldMeta, meta1); EXPECT_EQ(ret, true); - MetaDataManager::GetInstance().DelMeta(oldMeta.GetKey()); + MetaDataManager::GetInstance().DelMeta(oldMeta.GetKeyWithoutPath()); } - + /** * @tc.name: TryUpdateDeviceId004 * @tc.desc: TryUpdateDeviceId test @@ -2800,12 +3052,120 @@ HWTEST_F(CloudDataTest, TryUpdateDeviceId004, TestSize.Level1) oldMeta.storeId = "test_storeid_001"; oldMeta.isNeedUpdateDeviceId = false; oldMeta.storeType = StoreMetaData::StoreType::STORE_RELATIONAL_END; - bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKey(), oldMeta); + bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKeyWithoutPath(), oldMeta); EXPECT_EQ(isSuccess, true); StoreMetaData meta1 = oldMeta; auto ret = rdbServiceImpl.TryUpdateDeviceId(param, oldMeta, meta1); EXPECT_EQ(ret, true); - MetaDataManager::GetInstance().DelMeta(oldMeta.GetKey()); + MetaDataManager::GetInstance().DelMeta(oldMeta.GetKeyWithoutPath()); +} + +/** +* @tc.name: OnInitialize +* @tc.desc: OnInitialize test +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(CloudDataTest, OnInitialize, TestSize.Level1) +{ + auto code = cloudServiceImpl_->OnInitialize(); + EXPECT_EQ(code, E_OK); +} + +/** +* @tc.name: CleanWaterVersion +* @tc.desc: CleanWaterVersion test +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(CloudDataTest, CleanWaterVersion, TestSize.Level1) +{ + auto ret = cloudServiceImpl_->CleanWaterVersion(200); + EXPECT_FALSE(ret); + ret = cloudServiceImpl_->CleanWaterVersion( + AccountDelegate::GetInstance()->GetUserByToken(IPCSkeleton::GetCallingTokenID())); + EXPECT_TRUE(ret); +} + +/** +* @tc.name: ConvertGenDetailsCode +* @tc.desc: Test ConvertGenDetailsCode function. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, ConvertGenDetailsCode, TestSize.Level0) +{ + DistributedData::GenDetails result; + GenProgressDetail detail; + detail.progress = GenProgress::SYNC_IN_PROGRESS; + detail.code = 100; + result.insert(std::make_pair("test", detail)); + auto details = CloudData::SyncManager::ConvertGenDetailsCode(result); + EXPECT_TRUE(details["test"].code == E_ERROR); + + DistributedData::GenDetails result1; + GenProgressDetail detail1; + detail1.progress = GenProgress::SYNC_IN_PROGRESS; + detail1.code = E_ERROR; + result1.insert(std::make_pair("test", detail1)); + details = CloudData::SyncManager::ConvertGenDetailsCode(result1); + EXPECT_TRUE(details["test"].code == E_ERROR); + + DistributedData::GenDetails result2; + GenProgressDetail detail2; + detail2.progress = GenProgress::SYNC_IN_PROGRESS; + detail2.code = E_OK; + result2.insert(std::make_pair("test", detail2)); + details = CloudData::SyncManager::ConvertGenDetailsCode(result2); + EXPECT_TRUE(details["test"].code == E_OK); + + DistributedData::GenDetails result3; + GenProgressDetail detail3; + detail3.progress = GenProgress::SYNC_IN_PROGRESS; + detail3.code = E_BLOCKED_BY_NETWORK_STRATEGY; + result3.insert(std::make_pair("test", detail3)); + details = CloudData::SyncManager::ConvertGenDetailsCode(result3); + EXPECT_TRUE(details["test"].code == E_BLOCKED_BY_NETWORK_STRATEGY); + + DistributedData::GenDetails result4; + GenProgressDetail detail4; + detail4.progress = GenProgress::SYNC_IN_PROGRESS; + detail4.code = E_BUSY; + result4.insert(std::make_pair("test", detail4)); + details = CloudData::SyncManager::ConvertGenDetailsCode(result4); + EXPECT_TRUE(details["test"].code == E_ERROR); +} + +/** +* @tc.name: ConvertValidGeneralCode +* @tc.desc: Test ConvertValidGeneralCode function. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, GetValidGeneralCode, TestSize.Level0) +{ + auto ret = CloudData::SyncManager::ConvertValidGeneralCode(E_OK); + EXPECT_TRUE(ret == E_OK); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_ERROR); + EXPECT_TRUE(ret == E_ERROR); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_NETWORK_ERROR); + EXPECT_TRUE(ret == E_NETWORK_ERROR); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_CLOUD_DISABLED); + EXPECT_TRUE(ret == E_CLOUD_DISABLED); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_LOCKED_BY_OTHERS); + EXPECT_TRUE(ret == E_LOCKED_BY_OTHERS); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_RECODE_LIMIT_EXCEEDED); + EXPECT_TRUE(ret == E_RECODE_LIMIT_EXCEEDED); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_NO_SPACE_FOR_ASSET); + EXPECT_TRUE(ret == E_NO_SPACE_FOR_ASSET); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_BLOCKED_BY_NETWORK_STRATEGY); + EXPECT_TRUE(ret == E_BLOCKED_BY_NETWORK_STRATEGY); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_BUSY); + EXPECT_TRUE(ret == E_ERROR); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_SYNC_TASK_MERGED); + EXPECT_TRUE(ret == E_ERROR); } } // 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 index bad6767dde43161a2c747cef2e9f87a0bf79e6f6..ed40cca5ad9eef4a73600c10d12b4b360a081ec5 100644 --- a/datamgr_service/services/distributeddataservice/service/test/cloud_service_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/cloud_service_impl_test.cpp @@ -19,31 +19,49 @@ #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 "mock/meta_data_manager_mock.h" #include "model/component_config.h" #include "network/network_delegate.h" #include "network_delegate_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" +#include "directory/directory_manager.h" using namespace testing::ext; +using namespace testing; using namespace OHOS::DistributedData; using namespace OHOS::Security::AccessToken; using Confirmation = OHOS::CloudData::Confirmation; using Status = OHOS::CloudData::CloudService::Status; using CloudSyncScene = OHOS::CloudData::CloudServiceImpl::CloudSyncScene; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; namespace OHOS::Test { namespace DistributedDataTest { @@ -58,12 +76,56 @@ public: void SetUp(); void TearDown(); + static void InitMetaData(); + static void CheckDelMeta(StoreMetaMapping &metaMapping, StoreMetaData &meta, StoreMetaData &meta1); static std::shared_ptr cloudServiceImpl_; static NetworkDelegateMock delegate_; +protected: + static std::shared_ptr dbStoreMock_; + static StoreMetaData metaData_; }; std::shared_ptr CloudServiceImplTest::cloudServiceImpl_ = std::make_shared(); NetworkDelegateMock CloudServiceImplTest::delegate_; +std::shared_ptr CloudServiceImplTest::dbStoreMock_ = std::make_shared(); +StoreMetaData CloudServiceImplTest::metaData_; + +void CloudServiceImplTest::CheckDelMeta(StoreMetaMapping &metaMapping, StoreMetaData &meta, StoreMetaData &meta1) +{ + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); + metaMapping.cloudPath = ""; + metaMapping.dataDir = DirectoryManager::GetInstance().GetStorePath(metaMapping) + "/" + metaMapping.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + meta.user = "100"; + auto res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); + metaMapping.dataDir = ""; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + meta.user = "100"; + res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); +} + +void CloudServiceImplTest::InitMetaData() +{ + metaData_.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData_.appId = "test_rdb_cloud_service_impl_appid"; + metaData_.bundleName = "test_rdb_cloud_service_impl_bundleName"; + metaData_.tokenId = OHOS::IPCSkeleton::GetCallingTokenID(); + metaData_.user = std::to_string(AccountDelegate::GetInstance()->GetUserByToken(metaData_.tokenId)); + metaData_.area = OHOS::DistributedKv::EL1; + metaData_.instanceId = 0; + metaData_.isAutoSync = true; + metaData_.storeType = DistributedRdb::RDB_DEVICE_COLLABORATION; + metaData_.storeId = "test_cloud_service_impl_store"; + metaData_.dataDir = "/test_cloud_service_impl_store"; +} void CloudServiceImplTest::SetUpTestCase(void) { @@ -71,14 +133,18 @@ void CloudServiceImplTest::SetUpTestCase(void) size_t min = 5; auto executor = std::make_shared(max, min); DeviceManagerAdapter::GetInstance().Init(executor); + Bootstrap::GetInstance().LoadCheckers(); + CryptoManager::GetInstance().GenerateRootKey(); + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); NetworkDelegate::RegisterNetworkInstance(&delegate_); + InitMetaData(); } -void CloudServiceImplTest::TearDownTestCase() {} +void CloudServiceImplTest::TearDownTestCase() { } -void CloudServiceImplTest::SetUp() {} +void CloudServiceImplTest::SetUp() { } -void CloudServiceImplTest::TearDown() {} +void CloudServiceImplTest::TearDown() { } /** * @tc.name: EnableCloud001 @@ -258,6 +324,23 @@ HWTEST_F(CloudServiceImplTest, GetCloudInfoFromServer001, TestSize.Level0) EXPECT_EQ(status, CloudData::CloudService::SERVER_UNAVAILABLE); } +/** + * @tc.name: GetCloudInfoFromServer002 + * @tc.desc: Test GetCloudInfoFromServer functions with cloudinfo is empty. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudServiceImplTest, GetCloudInfoFromServer002, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest GetCloudInfoFromServer002 start"); + CloudServer cloudServer; + CloudServer::RegisterCloudInstance(&cloudServer); + int user = 100; + auto [status, result] = cloudServiceImpl_->GetCloudInfoFromServer(user); + EXPECT_EQ(status, E_ERROR); + CloudServer::instance_ = nullptr; +} + /** * @tc.name: ReleaseUserInfo001 * @tc.desc: Test ReleaseUserInfo functions with invalid parameter. @@ -285,6 +368,120 @@ HWTEST_F(CloudServiceImplTest, DoSubscribe, TestSize.Level0) EXPECT_TRUE(status); } +/** + * @tc.name: OnAppInstallTest + * @tc.desc: Test the OnAppInstallTest + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudServiceImplTest, OnAppInstallTest, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest OnAppInstallTest start"); + ASSERT_NE(cloudServiceImpl_, nullptr); + ASSERT_NE(cloudServiceImpl_->factory_.staticActs_, nullptr); + int32_t user = 0; + int32_t index = 0; + auto status = cloudServiceImpl_->factory_.staticActs_->OnAppInstall(TEST_CLOUD_BUNDLE, user, index); + EXPECT_EQ(status, GeneralError::E_ERROR); +} + +/** + * @tc.name: OnAppUpdateTest + * @tc.desc: Test the OnAppUpdateTest + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudServiceImplTest, OnAppUpdateTest, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest OnAppUpdateTest start"); + ASSERT_NE(cloudServiceImpl_, nullptr); + ASSERT_NE(cloudServiceImpl_->factory_.staticActs_, nullptr); + int32_t user = 0; + int32_t index = 0; + auto status = cloudServiceImpl_->factory_.staticActs_->OnAppUpdate(TEST_CLOUD_BUNDLE, user, index); + EXPECT_EQ(status, CloudData::CloudService::SUCCESS); +} + +/** + * @tc.name: CloudDriverCheckTest + * @tc.desc: Test the CloudDriverCheck + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudServiceImplTest, CloudDriverCheckTest, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest CloudDriverCheckTest start"); + ASSERT_NE(cloudServiceImpl_, nullptr); + ASSERT_NE(cloudServiceImpl_->factory_.staticActs_, nullptr); + CloudServer cloudServer; + CloudServer::RegisterCloudInstance(&cloudServer); + int32_t user = 0; + auto result = cloudServiceImpl_->factory_.staticActs_->CloudDriverCheck(TEST_CLOUD_BUNDLE, user); + EXPECT_EQ(result, false); + CloudServer::instance_ = nullptr; +} + +/** + * @tc.name: UpdateSchemaFromServerTest_001 + * @tc.desc: Test UpdateSchemaFromServer functions + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudServiceImplTest, UpdateSchemaFromServerTest_001, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest UpdateSchemaFromServerTest_001 start"); + CloudServer cloudServer; + CloudServer::RegisterCloudInstance(&cloudServer); + int user = 100; + auto status = cloudServiceImpl_->UpdateSchemaFromServer(user); + EXPECT_EQ(status, E_ERROR); + CloudServer::instance_ = nullptr; +} + +/** + * @tc.name: UpdateSchemaFromServerTest_002 + * @tc.desc: Test UpdateSchemaFromServer functions. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudServiceImplTest, UpdateSchemaFromServerTest_002, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest UpdateSchemaFromServerTest_002 start"); + CloudServer cloudServer; + CloudServer::RegisterCloudInstance(&cloudServer); + int user = 0; + CloudInfo cloudInfo; + cloudInfo.user = user; + DistributedData::CloudInfo::AppInfo appInfo; + appInfo.bundleName = TEST_CLOUD_BUNDLE; + appInfo.appId = TEST_CLOUD_APPID; + appInfo.cloudSwitch = true; + cloudInfo.apps = {{ TEST_CLOUD_BUNDLE, appInfo }}; + auto status = cloudServiceImpl_->UpdateSchemaFromServer(cloudInfo, user); + EXPECT_EQ(status, CloudData::CloudService::SUCCESS); + CloudServer::instance_ = nullptr; +} + +/** + * @tc.name: UpdateE2eeEnableTest + * @tc.desc: Test UpdateE2eeEnable functions. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudServiceImplTest, UpdateE2eeEnableTest, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest UpdateE2eeEnableTest start"); + ASSERT_NE(cloudServiceImpl_, nullptr); + CloudServer cloudServer; + auto result = cloudServer.CloudDriverUpdated(TEST_CLOUD_BUNDLE); + EXPECT_EQ(result, false); + + std::string schemaKey = "schemaKey"; + cloudServiceImpl_->UpdateE2eeEnable(schemaKey, true, TEST_CLOUD_BUNDLE); + SchemaMeta schemaMeta; + ASSERT_FALSE(MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)); +} + /** * @tc.name: Share001 * @tc.desc: Test the Share with invalid parameters @@ -381,12 +578,229 @@ HWTEST_F(CloudServiceImplTest, QueryByInvitation001, TestSize.Level0) HWTEST_F(CloudServiceImplTest, ConfirmInvitation001, TestSize.Level0) { int32_t confirmation = 0; - std::tuple result{ 0, "", "" }; + std::tuple result { 0, "", "" }; std::string invitation; auto status = cloudServiceImpl_->ConfirmInvitation(invitation, confirmation, result); EXPECT_EQ(status, GeneralError::E_ERROR); } +/** + * @tc.name: GetStoreMetaData_001 + * @tc.desc: test GetStoreMetaData LoadMeta success. + * @tc.type: FUNC + */ +HWTEST_F(CloudServiceImplTest, GetStoreMetaData_001, TestSize.Level1) +{ + StoreMetaData meta; + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta.user = "0"; + meta.bundleName = "bundleName"; + meta.storeId = "storeName"; + meta.dataDir = DirectoryManager::GetInstance().GetStorePath(meta) + "/" + meta.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + bool res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); + meta.instanceId = 1; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); +} + +/** + * @tc.name: GetStoreMetaData_002 + * @tc.desc: test GetStoreMetaData LoadMeta failed and user is 0. + * @tc.type: FUNC + */ +HWTEST_F(CloudServiceImplTest, GetStoreMetaData_002, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + metaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaMapping.user = "0"; + metaMapping.bundleName = "bundleName"; + metaMapping.storeId = "storeName"; + metaMapping.cloudPath = DirectoryManager::GetInstance().GetStorePath(metaMapping) + "/" + metaMapping.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + StoreMetaData meta; + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta.user = "100"; + meta.bundleName = "bundleName"; + meta.storeId = "storeName"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + bool res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + meta.instanceId = 1; + metaMapping.instanceId = 1; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + meta.user = "100"; + res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + metaMapping.cloudPath = ""; + metaMapping.dataDir = DirectoryManager::GetInstance().GetStorePath(metaMapping) + "/" + metaMapping.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + meta.user = "100"; + res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + metaMapping.dataDir = ""; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + meta.user = "100"; + res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); +} + +/** + * @tc.name: GetStoreMetaData_003 + * @tc.desc: test GetStoreMetaData LoadMeta failed and user is not 0. + * @tc.type: FUNC + */ +HWTEST_F(CloudServiceImplTest, GetStoreMetaData_003, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + metaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaMapping.user = "0"; + metaMapping.bundleName = "bundleName"; + metaMapping.storeId = "storeName"; + metaMapping.cloudPath = DirectoryManager::GetInstance().GetStorePath(metaMapping) + "/" + metaMapping.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + StoreMetaData meta; + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta.user = "100"; + meta.bundleName = "bundleName"; + meta.storeId = "storeName"; + StoreMetaData meta1; + meta1.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta1.user = "0"; + meta1.bundleName = "bundleName"; + meta1.storeId = "storeName"; + meta1.dataDir = DirectoryManager::GetInstance().GetStorePath(meta) + "/" + meta.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + StoreMetaDataLocal localMetaData; + bool res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); +} + +/** + * @tc.name: GetStoreMetaData_004 + * @tc.desc: test GetStoreMetaData First load of metadata failed and the user is not 0, + * then the load of metadata succeeded. + * @tc.type: FUNC + */ +HWTEST_F(CloudServiceImplTest, GetStoreMetaData_004, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + metaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaMapping.user = "0"; + metaMapping.bundleName = "bundleName"; + metaMapping.storeId = "storeName"; + metaMapping.instanceId = 1; + metaMapping.cloudPath = DirectoryManager::GetInstance().GetStorePath(metaMapping) + "/" + metaMapping.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + StoreMetaData meta; + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta.user = "100"; + meta.bundleName = "bundleName"; + meta.storeId = "storeName"; + meta.instanceId = 1; + StoreMetaData meta1; + meta1.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta1.user = "0"; + meta1.bundleName = "bundleName"; + meta1.storeId = "storeName"; + meta1.instanceId = 1; + meta1.dataDir = DirectoryManager::GetInstance().GetStorePath(meta1) + "/" + meta1.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + StoreMetaDataLocal localMetaData; + bool res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); + CheckDelMeta(metaMapping, meta, meta1); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKeyLocal(), localMetaData, true), true); + meta.user = "100"; + res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKeyLocal(), true), true); + localMetaData.isPublic = true; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKeyLocal(), localMetaData, true), true); + meta.user = "100"; + metaMapping.cloudPath = DirectoryManager::GetInstance().GetStorePath(meta1) + "/" + meta1.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKeyLocal(), true), true); +} + +/** + * @tc.name: PreShare_001 + * @tc.desc: test PreShare is dataDir empty. + * @tc.type: FUNC + */ +HWTEST_F(CloudServiceImplTest, PreShare_001, TestSize.Level1) +{ + StoreInfo storeInfo; + storeInfo.bundleName = "bundleName"; + storeInfo.storeName = "storeName"; + storeInfo.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + storeInfo.user = 100; + StoreMetaMapping storeMetaMapping; + storeMetaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + storeMetaMapping.user = "100"; + storeMetaMapping.bundleName = "bundleName"; + storeMetaMapping.storeId = "storeName"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(storeMetaMapping.GetKey(), storeMetaMapping, true), true); + std::shared_ptr query; + auto [errCode, cursor] = cloudServiceImpl_->PreShare(storeInfo, *query); + EXPECT_EQ(errCode, E_ERROR); + ASSERT_EQ(cursor, nullptr); + storeInfo.path = "path"; + storeMetaMapping.cloudPath = "path1"; + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(storeMetaMapping.GetKey(), storeMetaMapping, true), true); + auto [errCode1, cursor1] = cloudServiceImpl_->PreShare(storeInfo, *query); + EXPECT_EQ(errCode1, E_ERROR); + ASSERT_EQ(cursor1, nullptr); + storeInfo.path = "path"; + storeMetaMapping.cloudPath = "path"; + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(storeMetaMapping.GetKey(), storeMetaMapping, true), true); + auto [errCode2, cursor2] = cloudServiceImpl_->PreShare(storeInfo, *query); + EXPECT_EQ(errCode2, E_ERROR); + ASSERT_EQ(cursor2, nullptr); + storeInfo.instanceId = 1; + storeMetaMapping.instanceId = 1; + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(storeMetaMapping.GetKey(), storeMetaMapping, true), true); + auto [errCode3, cursor3] = cloudServiceImpl_->PreShare(storeInfo, *query); + EXPECT_EQ(errCode3, E_ERROR); + ASSERT_EQ(cursor3, nullptr); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true), true); +} + /** * @tc.name: ChangeConfirmation001 * @tc.desc: Test the ChangeConfirmation with invalid parameters @@ -500,13 +914,13 @@ public: void TearDown(); }; -void ComponentConfigTest::SetUpTestCase(void) {} +void ComponentConfigTest::SetUpTestCase(void) { } -void ComponentConfigTest::TearDownTestCase() {} +void ComponentConfigTest::TearDownTestCase() { } -void ComponentConfigTest::SetUp() {} +void ComponentConfigTest::SetUp() { } -void ComponentConfigTest::TearDown() {} +void ComponentConfigTest::TearDown() { } /** * @tc.name: CapabilityRange diff --git a/datamgr_service/services/distributeddataservice/service/test/crypto_manager_test.cpp b/datamgr_service/services/distributeddataservice/service/test/crypto_manager_test.cpp index 4b42a2cb997c8152310f57076e98e1e3c1384062..fe4e537f1d7d69afe5b61a9c92dfdca343f050d5 100644 --- a/datamgr_service/services/distributeddataservice/service/test/crypto_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/crypto_manager_test.cpp @@ -13,48 +13,96 @@ * limitations under the License. */ -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include -#include "crypto_manager.h" #include "gtest/gtest.h" -#include "metadata/secret_key_meta_data.h" -#include "metadata/store_meta_data.h" -#include "types.h" + +#include "access_token.h" +#include "accesstoken_kit.h" +#include "hks_api.h" +#include "hks_param.h" +#include "nativetoken_kit.h" +#include "token_setproc.h" + +namespace OHOS::Test { using namespace testing::ext; using namespace OHOS::DistributedData; -namespace OHOS::Test { -namespace DistributedDataTest { +using namespace OHOS::Security::AccessToken; + +static constexpr int32_t KEY_LENGTH = 32; +static constexpr int32_t NONCE_SIZE = 12; +static constexpr int32_t INVALID_AREA = -1; +static constexpr int32_t TEST_USERID_NUM = 100; +static constexpr const char *TEST_USERID = "100"; +static constexpr const char *TEST_BUNDLE_NAME = "test_application"; +static constexpr const char *TEST_STORE_NAME = "test_store"; +static constexpr const char *ROOT_KEY_ALIAS = "distributed_db_root_key"; +static constexpr const char *PROCESS_NAME = "distributeddata"; + class CryptoManagerTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); - void SetUp(){}; - void TearDown(){}; - static std::vector Random(uint32_t len); + void SetUp() {} + void TearDown() {} + + static void SetNativeTokenIdFromProcess(const std::string &process); + static std::vector Random(int32_t len); + static void DeleteRootKey(int32_t area); + static uint32_t GetStorageLevel(int32_t area); -protected: static std::vector randomKey; + static std::vector vecRootKeyAlias; + static std::vector nonce; }; -static const uint32_t KEY_LENGTH = 32; -static const uint32_t ENCRYPT_KEY_LENGTH = 48; -static constexpr int32_t EL2 = 2; -static constexpr int32_t EL4 = 4; -static constexpr const char *TEST_USERID = "100"; std::vector CryptoManagerTest::randomKey; +std::vector CryptoManagerTest::vecRootKeyAlias; +std::vector CryptoManagerTest::nonce; + +void CryptoManagerTest::SetNativeTokenIdFromProcess(const std::string &process) +{ + std::string dumpInfo; + AtmToolsParamInfo info; + info.processName = process; + AccessTokenKit::DumpTokenInfo(info, dumpInfo); + size_t pos = dumpInfo.find("\"tokenID\": "); + if (pos == std::string::npos) { + return; + } + pos += std::string("\"tokenID\": ").length(); + std::string numStr; + while (pos < dumpInfo.length() && std::isdigit(dumpInfo[pos])) { + numStr += dumpInfo[pos]; + ++pos; + } + std::istringstream iss(numStr); + AccessTokenID tokenID; + iss >> tokenID; + SetSelfTokenID(tokenID); +} + void CryptoManagerTest::SetUpTestCase(void) { + SetNativeTokenIdFromProcess(PROCESS_NAME); + randomKey = Random(KEY_LENGTH); + vecRootKeyAlias = std::vector(ROOT_KEY_ALIAS, ROOT_KEY_ALIAS + strlen(ROOT_KEY_ALIAS)); + nonce = Random(NONCE_SIZE); } void CryptoManagerTest::TearDownTestCase(void) { randomKey.assign(randomKey.size(), 0); + nonce.assign(nonce.size(), 0); + DeleteRootKey(CryptoManager::Area::EL1); + DeleteRootKey(CryptoManager::Area::EL2); + DeleteRootKey(CryptoManager::Area::EL4); } -std::vector CryptoManagerTest::Random(uint32_t len) +std::vector CryptoManagerTest::Random(int32_t len) { std::random_device randomDevice; std::uniform_int_distribution distribution(0, std::numeric_limits::max()); @@ -65,235 +113,314 @@ std::vector CryptoManagerTest::Random(uint32_t len) return key; } -/** -* @tc.name: GenerateRootKey -* @tc.desc: generate the root key -* @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang -*/ -HWTEST_F(CryptoManagerTest, GenerateRootKey, TestSize.Level0) +uint32_t CryptoManagerTest::GetStorageLevel(int32_t area) { - auto errCode = CryptoManager::GetInstance().GenerateRootKey(); - EXPECT_EQ(errCode, CryptoManager::ErrCode::SUCCESS); + if (area >= CryptoManager::Area::EL4 && area <= CryptoManager::Area::EL5) { + return HKS_AUTH_STORAGE_LEVEL_ECE; + } + if (area >= CryptoManager::Area::EL2 && area <= CryptoManager::Area::EL3) { + return HKS_AUTH_STORAGE_LEVEL_CE; + } + return HKS_AUTH_STORAGE_LEVEL_DE; +} + +void CryptoManagerTest::DeleteRootKey(int32_t area) +{ + struct HksParamSet *params = nullptr; + if (HksInitParamSet(¶ms) != HKS_SUCCESS) { + return; + } + auto storageLevel = GetStorageLevel(area); + std::vector hksParam = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = storageLevel }, + }; + if (storageLevel > HKS_AUTH_STORAGE_LEVEL_DE) { + hksParam.emplace_back(HksParam { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = TEST_USERID_NUM }); + } + if (HksAddParams(params, hksParam.data(), hksParam.size()) != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return; + } + if (HksBuildParamSet(¶ms) != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return; + } + struct HksBlob keyName = { uint32_t(vecRootKeyAlias.size()), const_cast(vecRootKeyAlias.data()) }; + (void)HksDeleteKey(&keyName, params); + HksFreeParamSet(¶ms); } /** -* @tc.name: CheckRootKey -* @tc.desc: check root key exist; +* @tc.name: GenerateRootKeyTest001 +* @tc.desc: generate the root key of DE * @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang */ -HWTEST_F(CryptoManagerTest, CheckRootKey, TestSize.Level0) +HWTEST_F(CryptoManagerTest, GenerateRootKeyTest001, TestSize.Level0) { - auto errCode = CryptoManager::GetInstance().CheckRootKey(); + auto errCode = CryptoManager::GetInstance().GenerateRootKey(); EXPECT_EQ(errCode, CryptoManager::ErrCode::SUCCESS); + + errCode = CryptoManager::GetInstance().CheckRootKey(); + ASSERT_EQ(errCode, CryptoManager::ErrCode::SUCCESS); } /** -* @tc.name: Encrypt001 -* @tc.desc: encrypt random key; +* @tc.name: EncryptAndDecryptTest001 +* @tc.desc: encrypt random key and decrypt with EL1 * @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang */ -HWTEST_F(CryptoManagerTest, Encrypt001, TestSize.Level0) +HWTEST_F(CryptoManagerTest, EncryptAndDecryptTest001, TestSize.Level0) { - auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - EXPECT_EQ(encryptKey.size(), ENCRYPT_KEY_LENGTH); - encryptKey.assign(encryptKey.size(), 0); + auto errCode = CryptoManager::GetInstance().GenerateRootKey(); + ASSERT_EQ(errCode, CryptoManager::ErrCode::SUCCESS); + CryptoManager::CryptoParams encryptParams = { .area = CryptoManager::Area::EL1, .userId = TEST_USERID }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + ASSERT_FALSE(encryptParams.nonce.empty()); + + CryptoManager::CryptoParams decryptParams = { .area = CryptoManager::Area::EL1, .userId = TEST_USERID, + .nonce = encryptParams.nonce }; + auto decryptKey = CryptoManager::GetInstance().Decrypt(encryptKey, decryptParams); + ASSERT_FALSE(decryptKey.empty()); + for (auto i = 0; i < KEY_LENGTH; ++i) { + ASSERT_EQ(decryptKey[i], randomKey[i]); + } + decryptKey.assign(encryptKey.size(), 0); } /** -* @tc.name: Encrypt002 -* @tc.desc: encrypt empty key; +* @tc.name: EncryptAndDecryptTest002 +* @tc.desc: encrypt random key and decrypt with EL2 * @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang */ -HWTEST_F(CryptoManagerTest, Encrypt002, TestSize.Level0) +HWTEST_F(CryptoManagerTest, EncryptAndDecryptTest002, TestSize.Level0) { - auto encryptKey = CryptoManager::GetInstance().Encrypt({ }, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - EXPECT_TRUE(encryptKey.empty()); + CryptoManager::CryptoParams encryptParams = { .area = CryptoManager::Area::EL2, .userId = TEST_USERID }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + ASSERT_FALSE(encryptParams.nonce.empty()); + + CryptoManager::CryptoParams decryptParams = { .area = CryptoManager::Area::EL2, .userId = TEST_USERID, + .nonce = encryptParams.nonce }; + auto decryptKey = CryptoManager::GetInstance().Decrypt(encryptKey, decryptParams); + ASSERT_FALSE(decryptKey.empty()); + for (auto i = 0; i < KEY_LENGTH; ++i) { + ASSERT_EQ(decryptKey[i], randomKey[i]); + } + decryptKey.assign(encryptKey.size(), 0); } /** -* @tc.name: Encrypt003 -* @tc.desc: Check root key fail; +* @tc.name: EncryptAndDecryptTest003 +* @tc.desc: encrypt random key and decrypt with EL3 * @tc.type: FUNC -* @tc.require: -* @tc.author: yanhui */ -HWTEST_F(CryptoManagerTest, Encrypt003, TestSize.Level0) +HWTEST_F(CryptoManagerTest, EncryptAndDecryptTest003, TestSize.Level0) { - auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, EL2, DEFAULT_USER); - EXPECT_TRUE(encryptKey.empty()); - encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, EL4, DEFAULT_USER); - EXPECT_TRUE(encryptKey.empty()); - - encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, EL2, TEST_USERID); - // check interact across local accounts permission failed - EXPECT_TRUE(encryptKey.empty()); - encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, EL4, TEST_USERID); - // check interact across local accounts permission failed - EXPECT_TRUE(encryptKey.empty()); + CryptoManager::CryptoParams encryptParams = { .area = CryptoManager::Area::EL3, .userId = TEST_USERID }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + ASSERT_FALSE(encryptParams.nonce.empty()); + + CryptoManager::CryptoParams decryptParams = { .area = CryptoManager::Area::EL3, .userId = TEST_USERID, + .nonce = encryptParams.nonce }; + auto decryptKey = CryptoManager::GetInstance().Decrypt(encryptKey, decryptParams); + ASSERT_FALSE(decryptKey.empty()); + for (auto i = 0; i < KEY_LENGTH; ++i) { + ASSERT_EQ(decryptKey[i], randomKey[i]); + } + decryptKey.assign(encryptKey.size(), 0); } /** -* @tc.name: Encrypt004 -* @tc.desc: Encrypt clone key, but root key not imported; +* @tc.name: EncryptAndDecryptTest004 +* @tc.desc: encrypt random key and decrypt with EL4 * @tc.type: FUNC -* @tc.require: -* @tc.author: yanhui */ -HWTEST_F(CryptoManagerTest, Encrypt004, TestSize.Level0) +HWTEST_F(CryptoManagerTest, EncryptAndDecryptTest004, TestSize.Level0) { - const std::string str = "distributed_db_backup_key"; - auto cloneKey = std::vector(str.begin(), str.end()); - std::vector nonce{}; - CryptoManager::EncryptParams params = { .keyAlias = cloneKey, .nonce = nonce }; - auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, params); - EXPECT_TRUE(encryptKey.empty()); - std::vector key; - - auto result = CryptoManager::GetInstance().Decrypt(encryptKey, key, params); - ASSERT_FALSE(result); + CryptoManager::CryptoParams encryptParams = { .area = CryptoManager::Area::EL4, .userId = TEST_USERID }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + ASSERT_FALSE(encryptParams.nonce.empty()); + + CryptoManager::CryptoParams decryptParams = { .area = CryptoManager::Area::EL4, .userId = TEST_USERID, + .nonce = encryptParams.nonce }; + auto decryptKey = CryptoManager::GetInstance().Decrypt(encryptKey, decryptParams); + ASSERT_FALSE(decryptKey.empty()); + for (auto i = 0; i < KEY_LENGTH; ++i) { + ASSERT_EQ(decryptKey[i], randomKey[i]); + } + decryptKey.assign(encryptKey.size(), 0); } /** -* @tc.name: DecryptKey001 -* @tc.desc: decrypt the encrypt key; +* @tc.name: EncryptAndDecryptTest005 +* @tc.desc: encrypt random key and decrypt with INVALID_AREA * @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang */ -HWTEST_F(CryptoManagerTest, DecryptKey001, TestSize.Level0) +HWTEST_F(CryptoManagerTest, EncryptAndDecryptTest005, TestSize.Level0) { - auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - std::vector key; - auto result = CryptoManager::GetInstance().Decrypt(encryptKey, key, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - EXPECT_TRUE(result); - EXPECT_EQ(key.size(), KEY_LENGTH); - encryptKey.assign(encryptKey.size(), 0); + CryptoManager::CryptoParams encryptParams = { .area = INVALID_AREA, .userId = TEST_USERID }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + ASSERT_FALSE(encryptParams.nonce.empty()); + + CryptoManager::CryptoParams decryptParams = { .area = encryptParams.area, .userId = TEST_USERID, + .nonce = encryptParams.nonce }; + auto decryptKey = CryptoManager::GetInstance().Decrypt(encryptKey, decryptParams); + ASSERT_FALSE(decryptKey.empty()); + for (auto i = 0; i < KEY_LENGTH; ++i) { + ASSERT_EQ(decryptKey[i], randomKey[i]); + } + decryptKey.assign(encryptKey.size(), 0); } /** -* @tc.name: DecryptKey002 -* @tc.desc: decrypt the key, the source key is not encrypt; +* @tc.name: EncryptAndDecryptTest006 +* @tc.desc: encrypt random key and decrypt with EL1 and key alias * @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang */ -HWTEST_F(CryptoManagerTest, DecryptKey002, TestSize.Level0) +HWTEST_F(CryptoManagerTest, EncryptAndDecryptTest006, TestSize.Level0) { - std::vector key; - auto result = CryptoManager::GetInstance().Decrypt(randomKey, key, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - EXPECT_FALSE(result); - EXPECT_TRUE(key.empty()); + CryptoManager::CryptoParams encryptParams = { .area = CryptoManager::Area::EL1, .userId = TEST_USERID, + .keyAlias = vecRootKeyAlias }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + ASSERT_FALSE(encryptParams.nonce.empty()); + + CryptoManager::CryptoParams decryptParams = { .area = encryptParams.area, .userId = TEST_USERID, + .keyAlias = vecRootKeyAlias, .nonce = encryptParams.nonce }; + auto decryptKey = CryptoManager::GetInstance().Decrypt(encryptKey, decryptParams); + ASSERT_FALSE(decryptKey.empty()); + for (auto i = 0; i < KEY_LENGTH; ++i) { + ASSERT_EQ(decryptKey[i], randomKey[i]); + } + decryptKey.assign(encryptKey.size(), 0); } /** -* @tc.name: DecryptKey003 -* @tc.desc: decrypt the key, the source key is empty; +* @tc.name: EncryptAndDecryptTest007 +* @tc.desc: encrypt random key and decrypt with EL1 and nonce value * @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang */ -HWTEST_F(CryptoManagerTest, DecryptKey003, TestSize.Level0) +HWTEST_F(CryptoManagerTest, EncryptAndDecryptTest007, TestSize.Level0) { - std::vector srcKey {}; - std::vector key; - auto result = CryptoManager::GetInstance().Decrypt(srcKey, key, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - EXPECT_FALSE(result); - EXPECT_TRUE(key.empty()); + CryptoManager::CryptoParams encryptParams = { .area = CryptoManager::Area::EL1, .userId = TEST_USERID, + .nonce = nonce }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + + CryptoManager::CryptoParams decryptParams = { .area = encryptParams.area, .userId = TEST_USERID, + .keyAlias = vecRootKeyAlias, .nonce = encryptParams.nonce }; + auto decryptKey = CryptoManager::GetInstance().Decrypt(encryptKey, decryptParams); + ASSERT_FALSE(decryptKey.empty()); + for (auto i = 0; i < KEY_LENGTH; ++i) { + ASSERT_EQ(decryptKey[i], randomKey[i]); + } + decryptKey.assign(encryptKey.size(), 0); } /** -* @tc.name: DecryptKey004 -* @tc.desc: Check root key fail; +* @tc.name: UpdateSecretMetaTest001 +* @tc.desc: update meta with invalid params * @tc.type: FUNC -* @tc.require: -* @tc.author: yanhui */ -HWTEST_F(CryptoManagerTest, DecryptKey004, TestSize.Level0) +HWTEST_F(CryptoManagerTest, UpdateSecretMetaTest001, TestSize.Level0) { - std::vector key; - auto result = CryptoManager::GetInstance().Decrypt(randomKey, key, EL2, DEFAULT_USER); - EXPECT_FALSE(result); - EXPECT_TRUE(key.empty()); - result = CryptoManager::GetInstance().Decrypt(randomKey, key, EL4, DEFAULT_USER); - EXPECT_FALSE(result); - EXPECT_TRUE(key.empty()); + std::vector password; + StoreMetaData metaData; + SecretKeyMetaData secretKey; + CryptoManager::GetInstance().UpdateSecretMeta(password, metaData, "", secretKey); + ASSERT_TRUE(secretKey.sKey.empty()); + + secretKey.nonce = nonce; + secretKey.area = CryptoManager::Area::EL1; + CryptoManager::GetInstance().UpdateSecretMeta(randomKey, metaData, "", secretKey); + ASSERT_TRUE(secretKey.sKey.empty()); } /** -* @tc.name: Decrypt001 -* @tc.desc: SecretKeyMetaData is old. +* @tc.name: UpdateSecretMetaTest002 +* @tc.desc: update meta with area EL1 * @tc.type: FUNC -* @tc.require: -* @tc.author: yanhui */ -HWTEST_F(CryptoManagerTest, Decrypt001, TestSize.Level0) +HWTEST_F(CryptoManagerTest, UpdateSecretMetaTest002, TestSize.Level0) { - SecretKeyMetaData secretKeyMeta; + auto errCode = CryptoManager::GetInstance().GenerateRootKey(); + ASSERT_EQ(errCode, CryptoManager::ErrCode::SUCCESS); + SecretKeyMetaData secretKey; StoreMetaData metaData; - std::vector key; - secretKeyMeta.sKey = CryptoManager::GetInstance().Encrypt(randomKey, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - auto result = CryptoManager::GetInstance().Decrypt(metaData, secretKeyMeta, key); - EXPECT_TRUE(result); + metaData.bundleName = TEST_BUNDLE_NAME; + metaData.storeId = TEST_STORE_NAME; + metaData.user = TEST_USERID; + metaData.area = CryptoManager::Area::EL1; + CryptoManager::GetInstance().UpdateSecretMeta(randomKey, metaData, metaData.GetSecretKey(), secretKey); + ASSERT_FALSE(secretKey.sKey.empty()); + ASSERT_FALSE(secretKey.nonce.empty()); + ASSERT_EQ(secretKey.area, metaData.area); } /** -* @tc.name: Decrypt002 -* @tc.desc: SecretKeyMetaData is new. +* @tc.name: UpdateSecretMetaTest003 +* @tc.desc: update meta with area EL2 * @tc.type: FUNC -* @tc.require: -* @tc.author: yanhui */ -HWTEST_F(CryptoManagerTest, Decrypt002, TestSize.Level0) +HWTEST_F(CryptoManagerTest, UpdateSecretMetaTest003, TestSize.Level0) { - SecretKeyMetaData secretKeyMeta; - secretKeyMeta.area = 1; + SecretKeyMetaData secretKey; StoreMetaData metaData; - std::vector key; - secretKeyMeta.sKey = CryptoManager::GetInstance().Encrypt(randomKey, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - auto result = CryptoManager::GetInstance().Decrypt(metaData, secretKeyMeta, key); - EXPECT_TRUE(result); - for (int8_t i = 0; i < randomKey.size(); i++) { - EXPECT_EQ(randomKey[i], key[i]); - } + metaData.bundleName = TEST_BUNDLE_NAME; + metaData.storeId = TEST_STORE_NAME; + metaData.user = TEST_USERID; + metaData.area = CryptoManager::Area::EL2; + CryptoManager::GetInstance().UpdateSecretMeta(randomKey, metaData, metaData.GetSecretKey(), secretKey); + ASSERT_FALSE(secretKey.sKey.empty()); + ASSERT_FALSE(secretKey.nonce.empty()); + ASSERT_EQ(secretKey.area, metaData.area); } /** -* @tc.name: UpdatePassword001 -* @tc.desc: The data is unencrypted. +* @tc.name: UpdateSecretMetaTest004 +* @tc.desc: update meta with area EL3 * @tc.type: FUNC -* @tc.require: -* @tc.author: yanhui */ -HWTEST_F(CryptoManagerTest, UpdatePassword001, TestSize.Level0) +HWTEST_F(CryptoManagerTest, UpdateSecretMetaTest004, TestSize.Level0) { + SecretKeyMetaData secretKey; StoreMetaData metaData; - std::vector key; - EXPECT_FALSE(CryptoManager::GetInstance().UpdateSecretKey(metaData, key)); + metaData.bundleName = TEST_BUNDLE_NAME; + metaData.storeId = TEST_STORE_NAME; + metaData.user = TEST_USERID; + metaData.area = CryptoManager::Area::EL3; + CryptoManager::GetInstance().UpdateSecretMeta(randomKey, metaData, metaData.GetSecretKey(), secretKey); + ASSERT_FALSE(secretKey.sKey.empty()); + ASSERT_FALSE(secretKey.nonce.empty()); + ASSERT_EQ(secretKey.area, metaData.area); } /** -* @tc.name: UpdatePassword002 -* @tc.desc: The data is encrypted. +* @tc.name: UpdateSecretMetaTest005 +* @tc.desc: update meta with area EL4 * @tc.type: FUNC -* @tc.require: -* @tc.author: yanhui */ -HWTEST_F(CryptoManagerTest, UpdatePassword002, TestSize.Level0) +HWTEST_F(CryptoManagerTest, UpdateSecretMetaTest005, TestSize.Level0) { + SecretKeyMetaData secretKey; StoreMetaData metaData; - metaData.isEncrypt = true; - metaData.area = DEFAULT_ENCRYPTION_LEVEL; - // MetaDataManager not initialized - EXPECT_FALSE(CryptoManager::GetInstance().UpdateSecretKey(metaData, randomKey)); - EXPECT_FALSE(CryptoManager::GetInstance().UpdateSecretKey(metaData, randomKey, CryptoManager::CLONE_SECRET_KEY)); + metaData.bundleName = TEST_BUNDLE_NAME; + metaData.storeId = TEST_STORE_NAME; + metaData.user = TEST_USERID; + metaData.area = CryptoManager::Area::EL4; + CryptoManager::GetInstance().UpdateSecretMeta(randomKey, metaData, metaData.GetSecretKey(), secretKey); + ASSERT_FALSE(secretKey.sKey.empty()); + ASSERT_FALSE(secretKey.nonce.empty()); + ASSERT_EQ(secretKey.area, metaData.area); } -} // namespace DistributedDataTest -} // namespace OHOS::Test +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/data_proxy_handle_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_proxy_handle_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..20ca8dd81e2f52732192133e9c4ba494df0d84ee --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/data_proxy_handle_test.cpp @@ -0,0 +1,494 @@ +/* +* Copyright (c) 2025 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 "DataShareProxyHandleTest" + +#include "data_share_service_impl.h" + +#include + +#include "accesstoken_kit.h" +#include "dataproxy_handle_common.h" +#include "hap_token_info.h" +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "log_print.h" +#include "proxy_data_manager.h" +#include "system_ability_definition.h" +#include "token_setproc.h" + +using namespace testing::ext; +using namespace OHOS::DataShare; +using namespace OHOS::DistributedData; +using namespace OHOS::Security::AccessToken; + +namespace OHOS::Test { +using OHOS::DataShare::LogLabel; +class DataShareProxyHandleTest : public testing::Test { +public: + static constexpr int64_t USER_TEST = 100; + std::string TEST_URI1 = "datashareproxy://com.test.dataprxoyhandle/test1"; + std::string TEST_URI2 = "datashareproxy://com.test.dataprxoyhandle/test2"; + std::string TEST_URI3 = "datashareproxy://com.test.dataprxoyhandle/test3"; + std::string TEST_URI_OTHER = "datashareproxy://com.test.dataprxoyhandle.other/test"; + // value1, value2, value3 are the values in profile + DataProxyValue VALUE1 = "value1"; + DataProxyValue VALUE2 = "value2"; + DataProxyValue VALUE3 = "value3"; + std::string APPIDENTIFIER1 = "appIdentifier1"; + std::string APPIDENTIFIER2 = "appIdentifier2"; + std::string APPIDENTIFIER3 = "appIdentifier3"; + std::string BUNDLE_NAME = "com.test.dataprxoyhandle"; + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetSelfTokenInfo(int32_t user); + void SetUp(); + void TearDown(); +}; + +void DataShareProxyHandleTest::SetUp(void) +{ + HapInfoParams info = { + .userID = USER_TEST, + .bundleName = BUNDLE_NAME, + .instIndex = 0, + .appIDDesc = BUNDLE_NAME + }; + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED", + .bundleName = BUNDLE_NAME, + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = BUNDLE_NAME, + .descriptionId = 1 + } + }, + .permStateList = { + { + .permissionName = "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + } + } + }; + AccessTokenKit::AllocHapToken(info, policy); + auto testTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID( + info.userID, info.bundleName, info.instIndex); + SetSelfTokenID(testTokenId); +} + +void DataShareProxyHandleTest::TearDown(void) +{ + auto tokenId = AccessTokenKit::GetHapTokenID(USER_TEST, "com.test.dataprxoyhandle", 0); + AccessTokenKit::DeleteToken(tokenId); +} + +/** +* @tc.name: OnAppInstallTest001 +* @tc.desc: test receive app install event +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, OnAppInstallTest001, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest OnAppInstallTest001 start"); + auto testTokenId = GetSelfTokenID(); + ProxyDataManager::GetInstance().OnAppInstall(BUNDLE_NAME, USER_TEST, 0, testTokenId); + DataShareServiceImpl dataShareServiceImpl; + std::vector uris = { TEST_URI1, TEST_URI2 }; + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + for (auto const &result : getResults) { + EXPECT_EQ(result.result_, OHOS::DataShare::SUCCESS); + } + // see details in profile + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].value_, VALUE1); + EXPECT_EQ(getResults[0].allowList_.size(), 1); + + EXPECT_EQ(getResults[1].uri_, TEST_URI2); + EXPECT_EQ(getResults[1].value_, VALUE2); + EXPECT_EQ(getResults[1].allowList_.size(), 1); + + auto results = dataShareServiceImpl.DeleteProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[1].uri_, TEST_URI2); + for (auto const &result : results) { + EXPECT_EQ(result.result_, OHOS::DataShare::SUCCESS); + } + ZLOGI("DataShareProxyHandleTest OnAppInstallTest001 end"); +} + +/** +* @tc.name: OnAppInstallTest001 +* @tc.desc: test receive app uninstall event +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, OnAppUninstallTest001, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest OnAppUninstallTest001 start"); + DataShareServiceImpl dataShareServiceImpl; + std::vector proxyDatas; + std::vector allowList = { APPIDENTIFIER1 }; + proxyDatas.emplace_back(TEST_URI1, VALUE1, allowList); + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + auto results = dataShareServiceImpl.PublishProxyData(proxyDatas, config); + ASSERT_EQ(results.size(), proxyDatas.size()); + for (auto const &result : results) { + EXPECT_EQ(result.result_, OHOS::DataShare::SUCCESS); + } + EXPECT_EQ(results[0].uri_, TEST_URI1); + + std::vector uris = { TEST_URI1 }; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + for (auto const &result : getResults) { + EXPECT_EQ(result.result_, OHOS::DataShare::SUCCESS); + } + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].value_, VALUE1); + EXPECT_EQ(getResults[0].allowList_.size(), 1); + + auto testTokenId = GetSelfTokenID(); + ProxyDataManager::GetInstance().OnAppUninstall(BUNDLE_NAME, USER_TEST, 0, testTokenId); + + getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + for (auto const &result : getResults) { + EXPECT_EQ(result.result_, OHOS::DataShare::URI_NOT_EXIST); + } + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + ZLOGI("DataShareProxyHandleTest OnAppUninstallTest001 end"); +} + +/** +* @tc.name: OnAppUpdate001 +* @tc.desc: test receive app update event +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, OnAppUpdateTest001, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest OnAppUpdateTest001 start"); + DataShareServiceImpl dataShareServiceImpl; + std::vector proxyDatas; + std::vector allowList = { APPIDENTIFIER3 }; + proxyDatas.emplace_back(TEST_URI3, VALUE3, allowList); + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + auto results = dataShareServiceImpl.PublishProxyData(proxyDatas, config); + ASSERT_EQ(results.size(), proxyDatas.size()); + for (auto const &result : results) { + EXPECT_EQ(result.result_, OHOS::DataShare::SUCCESS); + } + EXPECT_EQ(results[0].uri_, TEST_URI3); + + std::vector uris = { TEST_URI3 }; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + for (auto const &result : getResults) { + EXPECT_EQ(result.result_, OHOS::DataShare::SUCCESS); + } + EXPECT_EQ(getResults[0].uri_, TEST_URI3); + EXPECT_EQ(getResults[0].value_, VALUE3); + EXPECT_EQ(getResults[0].allowList_.size(), 1); + + auto testTokenId = GetSelfTokenID(); + ProxyDataManager::GetInstance().OnAppUpdate(BUNDLE_NAME, USER_TEST, 0, testTokenId); + + std::vector urisAfterUpdate = { TEST_URI1, TEST_URI2, TEST_URI3 }; + getResults = dataShareServiceImpl.GetProxyData(urisAfterUpdate, config); + ASSERT_EQ(getResults.size(), urisAfterUpdate.size()); + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].result_, OHOS::DataShare::SUCCESS); + EXPECT_EQ(getResults[1].uri_, TEST_URI2); + EXPECT_EQ(getResults[1].result_, OHOS::DataShare::SUCCESS); + EXPECT_EQ(getResults[2].uri_, TEST_URI3); + EXPECT_EQ(getResults[2].result_, OHOS::DataShare::URI_NOT_EXIST); + + std::vector urisToDelete = { TEST_URI1, TEST_URI2 }; + results = dataShareServiceImpl.DeleteProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[1].uri_, TEST_URI2); + for (auto const &result : results) { + EXPECT_EQ(result.result_, OHOS::DataShare::SUCCESS); + } + ZLOGI("DataShareProxyHandleTest OnAppUpdateTest001 end"); +} + +/** +* @tc.name: PublishProxyData001 +* @tc.desc: test publish proxyData with string value function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, PublishProxyData001, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest PublishProxyData001 start"); + DataShareServiceImpl dataShareServiceImpl; + std::vector proxyDatas; + DataProxyValue strValue = "strValue"; + std::vector allowList = { APPIDENTIFIER1 }; + proxyDatas.emplace_back(TEST_URI1, strValue, allowList); + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + auto results = dataShareServiceImpl.PublishProxyData(proxyDatas, config); + ASSERT_EQ(results.size(), proxyDatas.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::SUCCESS); + + std::vector uris = { TEST_URI1 }; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].result_, OHOS::DataShare::SUCCESS); + EXPECT_EQ(getResults[0].value_, strValue); + EXPECT_EQ(getResults[0].allowList_.size(), 1); + + results = dataShareServiceImpl.DeleteProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::SUCCESS); + ZLOGI("DataShareProxyHandleTest PublishProxyData001 end"); +} + +/** +* @tc.name: PublishProxyData002 +* @tc.desc: test publish proxyData with int value function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, PublishProxyData002, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest PublishProxyData002 start"); + DataShareServiceImpl dataShareServiceImpl; + std::vector proxyDatas; + DataProxyValue intValue = 100; + std::vector allowList = { APPIDENTIFIER1 }; + proxyDatas.emplace_back(TEST_URI1, intValue, allowList); + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + auto results = dataShareServiceImpl.PublishProxyData(proxyDatas, config); + ASSERT_EQ(results.size(), proxyDatas.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::SUCCESS); + + std::vector uris = { TEST_URI1 }; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].result_, OHOS::DataShare::SUCCESS); + EXPECT_EQ(getResults[0].value_, intValue); + EXPECT_EQ(getResults[0].allowList_.size(), 1); + + results = dataShareServiceImpl.DeleteProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::SUCCESS); + ZLOGI("DataShareProxyHandleTest PublishProxyData002 end"); +} + +/** +* @tc.name: PublishProxyData003 +* @tc.desc: test publish proxyData with double value function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, PublishProxyData003, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest PublishProxyData003 start"); + DataShareServiceImpl dataShareServiceImpl; + std::vector proxyDatas; + DataProxyValue fValue = 100.00; + std::vector allowList = { APPIDENTIFIER1 }; + proxyDatas.emplace_back(TEST_URI1, fValue, allowList); + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + auto results = dataShareServiceImpl.PublishProxyData(proxyDatas, config); + ASSERT_EQ(results.size(), proxyDatas.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::SUCCESS); + + std::vector uris = { TEST_URI1 }; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].result_, OHOS::DataShare::SUCCESS); + EXPECT_EQ(getResults[0].value_, fValue); + EXPECT_EQ(getResults[0].allowList_.size(), 1); + + results = dataShareServiceImpl.DeleteProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::SUCCESS); + ZLOGI("DataShareProxyHandleTest PublishProxyData003 end"); +} + +/** +* @tc.name: PublishProxyData004 +* @tc.desc: test publish proxyData with bool value function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, PublishProxyData004, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest PublishProxyData004 start"); + DataShareServiceImpl dataShareServiceImpl; + std::vector proxyDatas; + DataProxyValue boolValue = true; + std::vector allowList = { APPIDENTIFIER1 }; + proxyDatas.emplace_back(TEST_URI1, boolValue, allowList); + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + auto results = dataShareServiceImpl.PublishProxyData(proxyDatas, config); + ASSERT_EQ(results.size(), proxyDatas.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::SUCCESS); + + std::vector uris = { TEST_URI1 }; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].result_, OHOS::DataShare::SUCCESS); + EXPECT_EQ(getResults[0].value_, boolValue); + EXPECT_EQ(getResults[0].allowList_.size(), 1); + + results = dataShareServiceImpl.DeleteProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::SUCCESS); + ZLOGI("DataShareProxyHandleTest PublishProxyData004 end"); +} + +/** +* @tc.name: PublishProxyData005 +* @tc.desc: test publish proxyData of other bundle function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, PublishProxyData005, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest PublishProxyData005 start"); + DataShareServiceImpl dataShareServiceImpl; + std::vector proxyDatas; + DataProxyValue boolValue = true; + std::vector allowList = { APPIDENTIFIER1 }; + proxyDatas.emplace_back(TEST_URI_OTHER, boolValue, allowList); + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + std::vector uris = { TEST_URI_OTHER }; + auto results = dataShareServiceImpl.PublishProxyData(proxyDatas, config); + ASSERT_EQ(results.size(), proxyDatas.size()); + EXPECT_EQ(results[0].uri_, TEST_URI_OTHER); + EXPECT_EQ(results[0].result_, OHOS::DataShare::NO_PERMISSION); + ZLOGI("DataShareProxyHandleTest PublishProxyData005 end"); +} + +/** +* @tc.name: DeleteProxyData001 +* @tc.desc: test delete proxyData which is not published function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, DeleteProxyData001, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest DeleteProxyData001 start"); + DataShareServiceImpl dataShareServiceImpl; + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + std::vector uris = { TEST_URI1 }; + auto results = dataShareServiceImpl.DeleteProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::URI_NOT_EXIST); + ZLOGI("DataShareProxyHandleTest DeleteProxyData001 end"); +} + +/** +* @tc.name: DeleteProxyData002 +* @tc.desc: test delete proxyData without permission function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, DeleteProxyData002, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest DeleteProxyData002 start"); + DataShareServiceImpl dataShareServiceImpl; + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + std::vector uris = { TEST_URI_OTHER }; + auto results = dataShareServiceImpl.DeleteProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + EXPECT_EQ(results[0].uri_, TEST_URI_OTHER); + EXPECT_EQ(results[0].result_, OHOS::DataShare::NO_PERMISSION); + ZLOGI("DataShareProxyHandleTest DeleteProxyData002 end"); +} + +/** +* @tc.name: GetProxyData001 +* @tc.desc: test get proxyData without permission function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, GetProxyData001, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest GetProxyData001 start"); + DataShareServiceImpl dataShareServiceImpl; + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + std::vector uris = { TEST_URI1 }; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].result_, OHOS::DataShare::URI_NOT_EXIST); + ZLOGI("DataShareProxyHandleTest GetProxyData001 end"); +} + +/** +* @tc.name: GetProxyData002 +* @tc.desc: test get proxyData without permission function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, GetProxyData002, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest GetProxyData002 start"); + auto tokenId = AccessTokenKit::GetHapTokenID(USER_TEST, BUNDLE_NAME, 0); + AccessTokenKit::DeleteToken(tokenId); + DataShareServiceImpl dataShareServiceImpl; + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + std::vector uris = { TEST_URI1 }; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].result_, OHOS::DataShare::NO_PERMISSION); + SetSelfTokenID(tokenId); + ZLOGI("DataShareProxyHandleTest GetProxyData002 end"); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/data_share_common_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_common_test.cpp index ad14f7d37ba77110f2a889a502c45604e026d21a..8a250b4eba8fe1ee022548d95f9853655a9725e4 100644 --- a/datamgr_service/services/distributeddataservice/service/test/data_share_common_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_common_test.cpp @@ -16,9 +16,14 @@ #include #include +#include "extension_connect_adaptor.h" #include "data_share_profile_config.h" #include "div_strategy.h" #include "log_print.h" +#include "rdb_delegate.h" +#include "rdb_subscriber_manager.h" +#include "scheduler_manager.h" +#include "seq_strategy.h" #include "strategy.h" namespace OHOS::Test { @@ -89,4 +94,519 @@ HWTEST_F(DataShareCommonTest, DivStrategy003, TestSize.Level1) EXPECT_EQ(result, false); ZLOGI("DataShareCommonTest DivStrategy003 end"); } + +/** +* @tc.name: SeqStrategyInit001 +* @tc.desc: test SeqStrategyInit function when item is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a seqStrategy object and strategy2 = nullptr + 2.call Init function +* @tc.experct: Init failed and return false +*/ +HWTEST_F(DataShareCommonTest, SeqStrategyInit001, TestSize.Level1) +{ + ZLOGI("SeqStrategyInit001 start"); + Strategy* strategy1 = new Strategy(); + Strategy* strategy2 = nullptr; + SeqStrategy seqStrategy; + bool result = seqStrategy.Init({strategy1, strategy2}); + EXPECT_FALSE(result); + delete strategy1; + ZLOGI("SeqStrategyInit001 end"); +} + +/** +* @tc.name: DoConnect001 +* @tc.desc: test DoConnect function when callback_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a ExtensionConnectAdaptor object and callback = nullptr + 2.call DoConnect function +* @tc.experct: DoConnect failed and return false +*/ +HWTEST_F(DataShareCommonTest, DoConnect001, TestSize.Level1) +{ + ZLOGI("DoConnect001 start"); + std::string uri = "testUri"; + std::string bundleName = "testBundle"; + AAFwk::WantParams wantParams; + ExtensionConnectAdaptor extensionConnectAdaptor; + bool result = extensionConnectAdaptor.DoConnect(uri, bundleName, wantParams); + EXPECT_FALSE(result); + ZLOGI("DoConnect001 end"); +} + +/** +* @tc.name: InsertEx001 +* @tc.desc: test InsertEx function when store_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a rdbDelegate object and store_ = nullptr + 2.call InsertEx function +* @tc.experct: InsertEx failed and return E_DB_ERROR +*/ +HWTEST_F(DataShareCommonTest, InsertEx001, TestSize.Level1) +{ + ZLOGI("InsertEx001 start"); + DistributedData::StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = "test"; + metaData.area = 1; + int version = 0; + bool registerFunction = false; + std::string extUri = "uri"; + std::string backup = "backup"; + RdbDelegate rdbDelegate; + rdbDelegate.Init(metaData, version, registerFunction, extUri, backup); + rdbDelegate.store_ = nullptr; + std::string tableName = ""; + DataShare::DataShareValuesBucket valuesBucket; + std::string name0 = ""; + valuesBucket.Put("", name0); + auto result = rdbDelegate.InsertEx(tableName, valuesBucket); + EXPECT_EQ(result.first, E_DB_ERROR); + ZLOGI("InsertEx001 end"); +} + +/** +* @tc.name: UpdateEx001 +* @tc.desc: test UpdateEx function when store_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a RdbDelegate object and store_ = nullptr + 2.call UpdateEx function +* @tc.experct: UpdateEx failed and return E_DB_ERROR +*/ +HWTEST_F(DataShareCommonTest, UpdateEx001, TestSize.Level1) +{ + ZLOGI("UpdateEx001 start"); + DistributedData::StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = "test"; + metaData.area = 1; + int version = 0; + bool registerFunction = false; + std::string extUri = "uri"; + std::string backup = "backup"; + RdbDelegate rdbDelegate; + rdbDelegate.Init(metaData, version, registerFunction, extUri, backup); + rdbDelegate.store_ = nullptr; + std::string tableName = ""; + DataShare::DataShareValuesBucket valuesBucket; + std::string name0 = ""; + valuesBucket.Put("", name0); + DataSharePredicates predicate; + auto result = rdbDelegate.UpdateEx(tableName, predicate, valuesBucket); + EXPECT_EQ(result.first, E_DB_ERROR); + ZLOGI("UpdateEx001 end"); +} + +/** +* @tc.name: DeleteEx001 +* @tc.desc: test DeleteEx function when store_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a RdbDelegate object and store_ = nullptr + 2.call DeleteEx function +* @tc.experct: DeleteEx failed and return E_DB_ERROR +*/ +HWTEST_F(DataShareCommonTest, DeleteEx001, TestSize.Level1) +{ + ZLOGI("DeleteEx001 start"); + DistributedData::StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = "test"; + metaData.area = 1; + int version = 0; + bool registerFunction = false; + std::string extUri = "uri"; + std::string backup = "backup"; + RdbDelegate rdbDelegate; + rdbDelegate.Init(metaData, version, registerFunction, extUri, backup); + rdbDelegate.store_ = nullptr; + std::string tableName = ""; + DataSharePredicates predicate; + auto result = rdbDelegate.DeleteEx(tableName, predicate); + EXPECT_EQ(result.first, E_DB_ERROR); + ZLOGI("DeleteEx001 end"); +} + +/** +* @tc.name: Query001 +* @tc.desc: test Query function when store_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a RdbDelegate object and store_ = nullptr + 2.call Query function +* @tc.experct: Query failed and return errCode +*/ +HWTEST_F(DataShareCommonTest, Query001, TestSize.Level1) +{ + ZLOGI("Query001 start"); + DistributedData::StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = "test"; + metaData.area = 1; + int version = 0; + bool registerFunction = false; + std::string extUri = "uri"; + std::string backup = "backup"; + RdbDelegate rdbDelegate; + rdbDelegate.Init(metaData, version, registerFunction, extUri, backup); + rdbDelegate.store_ = nullptr; + std::string tableName = ""; + DataSharePredicates predicate; + std::vector columns; + int32_t callingPid = 1; + uint32_t callingTokenId = 1; + auto result = rdbDelegate.Query(tableName, predicate, columns, callingPid, callingTokenId); + EXPECT_EQ(result.first, rdbDelegate.errCode_); + ZLOGI("Query001 end"); +} + +/** +* @tc.name: Query002 +* @tc.desc: test Query function when store_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a RdbDelegate object and store_ = nullptr + 2.call Query function +* @tc.experct: Query failed and return "" +*/ +HWTEST_F(DataShareCommonTest, Query002, TestSize.Level1) +{ + ZLOGI("Query002 start"); + DistributedData::StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = "test"; + metaData.area = 1; + int version = 0; + bool registerFunction = false; + std::string extUri = "uri"; + std::string backup = "backup"; + RdbDelegate rdbDelegate; + rdbDelegate.Init(metaData, version, registerFunction, extUri, backup); + rdbDelegate.store_ = nullptr; + std::string sql = "testsql"; + std::vector selectionArgs; + auto result = rdbDelegate.Query(sql, selectionArgs); + EXPECT_EQ(result, ""); + ZLOGI("Query002 end"); +} + +/** +* @tc.name: QuerySql001 +* @tc.desc: test QuerySql function when store_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a RdbDelegate object and store_ = nullptr + 2.call QuerySql function +* @tc.experct: QuerySql failed and return nullptr +*/ +HWTEST_F(DataShareCommonTest, QuerySql001, TestSize.Level1) +{ + ZLOGI("QuerySql001 start"); + DistributedData::StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = "test"; + metaData.area = 1; + int version = 0; + bool registerFunction = false; + std::string extUri = "uri"; + std::string backup = "backup"; + RdbDelegate rdbDelegate; + rdbDelegate.Init(metaData, version, registerFunction, extUri, backup); + rdbDelegate.store_ = nullptr; + std::string sql = "testsql"; + auto result = rdbDelegate.QuerySql(sql); + EXPECT_EQ(result, nullptr); + ZLOGI("QuerySql001 end"); +} + +/** +* @tc.name: UpdateSql001 +* @tc.desc: test UpdateSql function when store_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a RdbDelegate object and store_ = nullptr + 2.call UpdateSql function +* @tc.experct: UpdateSql failed and return E_ERROR +*/ +HWTEST_F(DataShareCommonTest, UpdateSql001, TestSize.Level1) +{ + ZLOGI("UpdateSql001 start"); + DistributedData::StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = "test"; + metaData.area = 1; + int version = 0; + bool registerFunction = false; + std::string extUri = "uri"; + std::string backup = "backup"; + RdbDelegate rdbDelegate; + rdbDelegate.Init(metaData, version, registerFunction, extUri, backup); + rdbDelegate.store_ = nullptr; + std::string sql = "testsql"; + auto result = rdbDelegate.UpdateSql(sql); + EXPECT_EQ(result.first, OHOS::DataShare::E_ERROR); + ZLOGI("UpdateSql001 end"); +} + +/** +* @tc.name: EraseTimerTaskId001 +* @tc.desc: test EraseTimerTaskId function when not find key +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object and timerCache_ is null + 2.call EraseTimerTaskId function +* @tc.experct: not find key, EraseTimerTaskId failed and return -1 +*/ +HWTEST_F(DataShareCommonTest, EraseTimerTaskId001, TestSize.Level1) +{ + ZLOGI("EraseTimerTaskId001 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + int64_t result = manager.EraseTimerTaskId(key); + EXPECT_EQ(result, -1); + ZLOGI("EraseTimerTaskId001 end"); +} + +/** +* @tc.name: EraseTimerTaskId002 +* @tc.desc: test EraseTimerTaskId function when find key +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object and timerCache_[key] = timeid + 2.call EraseTimerTaskId function +* @tc.experct: find key, EraseTimerTaskId success and return timeid +*/ +HWTEST_F(DataShareCommonTest, EraseTimerTaskId002, TestSize.Level1) +{ + ZLOGI("EraseTimerTaskId002 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + int64_t timeid = 1; + manager.timerCache_[key] = timeid; + int64_t result = manager.EraseTimerTaskId(key); + EXPECT_EQ(result, timeid); + ZLOGI("EraseTimerTaskId002 end"); +} + +/** +* @tc.name: GetSchedulerStatus001 +* @tc.desc: test GetSchedulerStatus function when not find key +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object and schedulerStatusCache_ is null + 2.call GetSchedulerStatus function +* @tc.experct: not find key, GetSchedulerStatus failed and return false +*/ +HWTEST_F(DataShareCommonTest, GetSchedulerStatus001, TestSize.Level1) +{ + ZLOGI("GetSchedulerStatus001 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + bool result = manager.GetSchedulerStatus(key); + EXPECT_FALSE(result); + ZLOGI("GetSchedulerStatus001 end"); +} + +/** +* @tc.name: GetSchedulerStatus002 +* @tc.desc: test GetSchedulerStatus function when find key +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object and schedulerStatusCache_[key] = true; + 2.call GetSchedulerStatus function +* @tc.experct: find key, GetSchedulerStatus success and return true +*/ +HWTEST_F(DataShareCommonTest, GetSchedulerStatus002, TestSize.Level1) +{ + ZLOGI("GetSchedulerStatus002 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + manager.schedulerStatusCache_[key] = true; + bool result = manager.GetSchedulerStatus(key); + EXPECT_TRUE(result); + ZLOGI("GetSchedulerStatus002 end"); +} + +/** +* @tc.name: RemoveTimer001 +* @tc.desc: test RemoveTimer function when executor_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object what timerCache_[key] = 1 and executor_ is nullptr + 2.call RemoveTimer function to remove timer +* @tc.experct: RemoveTimer failed and timerCache_ is not null +*/ +HWTEST_F(DataShareCommonTest, RemoveTimer001, TestSize.Level1) +{ + ZLOGI("RemoveTimer001 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + manager.executor_ = nullptr; + manager.timerCache_[key] = 1; + manager.RemoveTimer(key); + EXPECT_NE(manager.timerCache_.find(key), manager.timerCache_.end()); + ZLOGI("RemoveTimer001 end"); +} + +/** +* @tc.name: RemoveTimer002 +* @tc.desc: test RemoveTimer function when executor_ is not nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object and timerCache_[key] = 1 and executor_ is not nullptr + 2.call RemoveTimer function to remove timer +* @tc.experct: RemoveTimer success and timerCache_ is null +*/ +HWTEST_F(DataShareCommonTest, RemoveTimer002, TestSize.Level1) +{ + ZLOGI("RemoveTimer002 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + manager.executor_ = std::make_shared(5, 3); + manager.timerCache_[key] = 1; + manager.RemoveTimer(key); + EXPECT_EQ(manager.timerCache_.find(key), manager.timerCache_.end()); + ZLOGI("RemoveTimer002 end"); +} + +/** +* @tc.name: ClearTimer001 +* @tc.desc: test ClearTimer function when executor_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object what timerCache_[key] = 1 and executor_ is nullptr + 2.call ClearTimer function to clear timer +* @tc.experct: ClearTimer failed and timerCache_ is not empty +*/ +HWTEST_F(DataShareCommonTest, ClearTimer001, TestSize.Level1) +{ + ZLOGI("ClearTimer001 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + manager.executor_ = nullptr; + manager.timerCache_[key] = 1; + manager.ClearTimer(); + EXPECT_FALSE(manager.timerCache_.empty()); + ZLOGI("ClearTimer001 end"); +} + +/** +* @tc.name: ClearTimer002 +* @tc.desc: test ClearTimer function when executor_ is not nullptr and find key +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object and timerCache_[key] = 1 and executor_ is not nullptr + 2.call ClearTimer function to clear timer +* @tc.experct: ClearTimer success and timerCache_ is empty +*/ +HWTEST_F(DataShareCommonTest, ClearTimer002, TestSize.Level1) +{ + ZLOGI("ClearTimer002 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + manager.executor_ = std::make_shared(5, 3); + manager.timerCache_[key] = 1; + manager.ClearTimer(); + EXPECT_TRUE(manager.timerCache_.empty()); + ZLOGI("ClearTimer002 end"); +} + +/** +* @tc.name: ClearTimer003 +* @tc.desc: test ClearTimer function when executor_ is not nullptr and not find key +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object and timerCache_ is null + 2.call ClearTimer function +* @tc.experct: ClearTimer failed and timerCache_ is empty +*/ +HWTEST_F(DataShareCommonTest, ClearTimer003, TestSize.Level1) +{ + ZLOGI("ClearTimer003 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + manager.executor_ = std::make_shared(5, 3); + manager.ClearTimer(); + EXPECT_TRUE(manager.timerCache_.empty()); + ZLOGI("ClearTimer003 end"); +} + +/** + * @tc.name: DBDelegateTest001 + * @tc.desc: do nothing when delegate already inited + * @tc.type: FUNC + */ +HWTEST_F(DataShareCommonTest, DBDelegateTest001, TestSize.Level0) { + RdbDelegate delegate; + DistributedData::StoreMetaData meta; + meta.tokenId = 1; + + delegate.isInited_ = true; + delegate.Init({}, 0, false, "extUri", "backup"); + + EXPECT_TRUE(delegate.isInited_); + EXPECT_EQ(delegate.tokenId_, 0); + EXPECT_EQ(delegate.extUri_, ""); + EXPECT_EQ(delegate.backup_, ""); +} + +/** + * @tc.name : DBDelegateTest002 + * @tc.number: init members in delegate init + * @tc.type: FUNC + */ +HWTEST_F(DataShareCommonTest, DBDelegateTest002, TestSize.Level0) { + RdbDelegate delegate; + DistributedData::StoreMetaData meta; + meta.tokenId = 1; + + delegate.isInited_ = false; + delegate.Init(meta, 0, false, "extUri", "backup"); + + EXPECT_FALSE(delegate.isInited_); + EXPECT_EQ(delegate.tokenId_, meta.tokenId); + EXPECT_EQ(delegate.extUri_, "extUri"); + EXPECT_EQ(delegate.backup_, "backup"); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/data_share_scheduler_manager_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_scheduler_manager_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0a8be9583ae28dc2d6af481aa28bc34bc7b8230f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_scheduler_manager_test.cpp @@ -0,0 +1,160 @@ +/* +* Copyright (c) 2025 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 "DataShareSchedulerManagerTest" + +#include + +#include "log_print.h" +#include "db_delegate.h" +#include "template_data.h" +#include "scheduler_manager.h" + +namespace OHOS::Test { +using namespace OHOS::DataShare; +using namespace testing::ext; +class DataShareSchedulerManagerTest : public testing::Test { +public: + static constexpr int64_t USER_TEST = 100; + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +/** +* @tc.name: EnableScheduler001 +* @tc.desc: test EnableScheduler function when not find key +* @tc.type: FUNC +* @tc.require: +* @tc.precon: None +* @tc.step: + 1.Add a template + 2.Creat a SchedulerManager object + 3.call Enable Scheduler function +* @tc.expect: not find key, Enable SchedulerStatus and GetSchedulerStatus return false +*/ +HWTEST_F(DataShareSchedulerManagerTest, EnableScheduler001, TestSize.Level1) +{ + ZLOGI("EnableScheduler001 start"); + Key key("uri1", 12345, "name1"); + Template tplt; + tplt.predicates_.emplace_back("test", "predicate test"); + tplt.scheduler_ = "scheduler test"; + std::string dataDir = "/data/service/el1/public/database/distributeddata/kvdb"; + std::shared_ptr executors = std::make_shared(1, 1); + auto kvDelegate = KvDBDelegate::GetInstance(dataDir, executors); + ASSERT_NE(kvDelegate, nullptr); + TemplateData data(key.uri, key.bundleName, key.subscriberId, USER_TEST, tplt); + auto ret = kvDelegate->Upsert(KvDBDelegate::TEMPLATE_TABLE, data); + EXPECT_EQ(ret.first, OHOS::DataShare::E_OK); + EXPECT_GT(ret.second, 0); + + auto& manager = SchedulerManager::GetInstance(); + DistributedData::StoreMetaData metaData; + manager.Enable(key, USER_TEST, metaData); + bool status = manager.GetSchedulerStatus(key); + EXPECT_FALSE(status); + + ret = kvDelegate->Delete(KvDBDelegate::TEMPLATE_TABLE, + static_cast(Id(TemplateData::GenId(key.uri, key.bundleName, key.subscriberId), USER_TEST))); + EXPECT_EQ(ret.first, OHOS::DataShare::E_OK); + EXPECT_GT(ret.second, 0); + ZLOGI("EnableScheduler001 end"); +} + +/** +* @tc.name: DisableScheduler001 +* @tc.desc: test EnableScheduler function when not find key +* @tc.type: FUNC +* @tc.require: +* @tc.precon: None +* @tc.step: + 1.Add a template + 2.Creat a SchedulerManager object + 3.call Disable Scheduler function +* @tc.expect: not find key, Disable SchedulerStatus and GetSchedulerStatus return false +*/ +HWTEST_F(DataShareSchedulerManagerTest, DisableScheduler001, TestSize.Level1) +{ + ZLOGI("DisableScheduler001 start"); + Key key("uri1", 12345, "name1"); + Template tplt; + tplt.predicates_.emplace_back("test", "predicate test"); + tplt.scheduler_ = "scheduler test"; + std::string dataDir = "/data/service/el1/public/database/distributeddata/kvdb"; + std::shared_ptr executors = std::make_shared(1, 1); + auto kvDelegate = KvDBDelegate::GetInstance(dataDir, executors); + ASSERT_NE(kvDelegate, nullptr); + TemplateData data(key.uri, key.bundleName, key.subscriberId, USER_TEST, tplt); + auto ret = kvDelegate->Upsert(KvDBDelegate::TEMPLATE_TABLE, data); + EXPECT_EQ(ret.first, OHOS::DataShare::E_OK); + EXPECT_GT(ret.second, 0); + + auto& manager = SchedulerManager::GetInstance(); + manager.Disable(key); + bool status = manager.GetSchedulerStatus(key); + EXPECT_FALSE(status); + + ret = kvDelegate->Delete(KvDBDelegate::TEMPLATE_TABLE, + static_cast(Id(TemplateData::GenId(key.uri, key.bundleName, key.subscriberId), USER_TEST))); + EXPECT_EQ(ret.first, OHOS::DataShare::E_OK); + EXPECT_GT(ret.second, 0); + ZLOGI("DisableScheduler001 end"); +} + +/** +* @tc.name: ChangeStatusCacheSize001 +* @tc.desc: test statusCache size changed when getting scheduler status +* @tc.type: FUNC +* @tc.require: +* @tc.precon: None +* @tc.step: + 1.Add a template + 2.Creat a SchedulerManager object + 3.Change the size of statusCache + 4.call GetSchedulerStatus function +* @tc.expect: the size of SchedulerStatus changed and print log +*/ +HWTEST_F(DataShareSchedulerManagerTest, ChangeStatusCacheSize001, TestSize.Level1) +{ + ZLOGI("ChangeStatusCacheSize001 start"); + Key key("uri1", 12345, "name1"); + Template tplt; + tplt.predicates_.emplace_back("test", "predicate test"); + tplt.scheduler_ = "scheduler test"; + std::string dataDir = "/data/service/el1/public/database/distributeddata/kvdb"; + std::shared_ptr executors = std::make_shared(1, 1); + auto kvDelegate = KvDBDelegate::GetInstance(dataDir, executors); + ASSERT_NE(kvDelegate, nullptr); + TemplateData data(key.uri, key.bundleName, key.subscriberId, USER_TEST, tplt); + auto ret = kvDelegate->Upsert(KvDBDelegate::TEMPLATE_TABLE, data); + EXPECT_EQ(ret.first, OHOS::DataShare::E_OK); + EXPECT_GT(ret.second, 0); + + auto &manager = SchedulerManager::GetInstance(); + manager.Disable(key); + Key key2("testUri", 12345, "testName"); + manager.schedulerStatusCache_.emplace(key2, false); + bool status = manager.GetSchedulerStatus(key); + EXPECT_FALSE(status); + manager.schedulerStatusCache_.erase(key2); + + ret = kvDelegate->Delete(KvDBDelegate::TEMPLATE_TABLE, + static_cast(Id(TemplateData::GenId(key.uri, key.bundleName, key.subscriberId), USER_TEST))); + EXPECT_EQ(ret.first, OHOS::DataShare::E_OK); + EXPECT_GT(ret.second, 0); + ZLOGI("ChangeStatusCacheSize001 end"); +} +} // namespace OHOS::Test \ No newline at end of file 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 a14d505bb24ee442b2b9e2799bb6ae658586b7a0..4574112be7f437ef925904176beb88d4177963a5 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 @@ -20,12 +20,15 @@ #include #include "accesstoken_kit.h" +#include "account_delegate_mock.h" #include "data_share_service_stub.h" +#include "device_manager_adapter.h" #include "dump/dump_manager.h" #include "hap_token_info.h" #include "ipc_skeleton.h" #include "iservice_registry.h" #include "log_print.h" +#include "metadata/meta_data_manager.h" #include "system_ability_definition.h" #include "token_setproc.h" @@ -44,50 +47,58 @@ public: static constexpr int64_t USER_TEST = 100; static constexpr int64_t TEST_SUB_ID = 100; static constexpr uint32_t CUREEENT_USER_ID = 123; - static void SetUpTestCase(void){}; - static void TearDownTestCase(void){}; + static constexpr uint32_t NATIVE_USER_ID = 0; + static void SetUpTestCase(void) + { + accountDelegateMock = new (std::nothrow) AccountDelegateMock(); + if (accountDelegateMock != nullptr) { + AccountDelegate::instance_ = nullptr; + AccountDelegate::RegisterAccountInstance(accountDelegateMock); + } + } + static void TearDownTestCase(void) + { + if (accountDelegateMock != nullptr) { + delete accountDelegateMock; + accountDelegateMock = nullptr; + } + } + void SetSelfTokenInfo(int32_t user); void SetUp(); void TearDown(); + static inline AccountDelegateMock *accountDelegateMock = nullptr; }; -void DataShareServiceImplTest::SetUp(void) +void DataShareServiceImplTest::SetSelfTokenInfo(int32_t user) { - HapInfoParams info = { - .userID = USER_TEST, + HapInfoParams info = { .userID = user, .bundleName = "ohos.datasharetest.demo", .instIndex = 0, - .appIDDesc = "ohos.datasharetest.demo" - }; - HapPolicyParams policy = { - .apl = APL_NORMAL, + .appIDDesc = "ohos.datasharetest.demo" }; + HapPolicyParams policy = { .apl = APL_NORMAL, .domain = "test.domain", - .permList = { - { - .permissionName = "ohos.permission.test", - .bundleName = "ohos.datasharetest.demo", - .grantMode = 1, - .availableLevel = APL_NORMAL, - .label = "label", - .labelId = 1, - .description = "ohos.datasharetest.demo", - .descriptionId = 1 - } - }, - .permStateList = { - { - .permissionName = "ohos.permission.test", - .isGeneral = true, - .resDeviceID = { "local" }, - .grantStatus = { PermissionState::PERMISSION_GRANTED }, - .grantFlags = { 1 } - } - } - }; + .permList = { { .permissionName = "ohos.permission.test", + .bundleName = "ohos.datasharetest.demo", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "ohos.datasharetest.demo", + .descriptionId = 1 } }, + .permStateList = { { .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } } } }; AccessTokenKit::AllocHapToken(info, policy); - auto testTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID( - info.userID, info.bundleName, info.instIndex); + auto testTokenId = + Security::AccessToken::AccessTokenKit::GetHapTokenID(info.userID, info.bundleName, info.instIndex); SetSelfTokenID(testTokenId); } +void DataShareServiceImplTest::SetUp(void) +{ + SetSelfTokenInfo(USER_TEST); +} void DataShareServiceImplTest::TearDown(void) { @@ -146,10 +157,10 @@ HWTEST_F(DataShareServiceImplTest, NotifyChange001, TestSize.Level1) { DataShareServiceImpl dataShareServiceImpl; std::string uri = SLIENT_ACCESS_URI; - auto result = dataShareServiceImpl.NotifyChange(uri); + auto result = dataShareServiceImpl.NotifyChange(uri, USER_TEST); EXPECT_EQ(result, true); - result = dataShareServiceImpl.NotifyChange(""); + result = dataShareServiceImpl.NotifyChange("", USER_TEST); EXPECT_EQ(result, false); } @@ -324,13 +335,13 @@ HWTEST_F(DataShareServiceImplTest, SubscribePublishedData001, TestSize.Level1) auto tokenId = AccessTokenKit::GetHapTokenID(USER_TEST, "ohos.datasharetest.demo", 0); AccessTokenKit::DeleteToken(tokenId); - std::vector result = dataShareServiceImpl.SubscribePublishedData(uris, subscriberId, observer); + std::vector result = dataShareServiceImpl.SubscribePublishedData(uris, subscriberId, observer); EXPECT_NE(result.size(), uris.size()); for (auto const &operationResult : result) { EXPECT_EQ(operationResult.errCode_, 0); } - result = dataShareServiceImpl.UnsubscribePublishedData(uris, subscriberId); + result = dataShareServiceImpl.UnsubscribePublishedData(uris, subscriberId); EXPECT_NE(result.size(), uris.size()); for (auto const &operationResult : result) { EXPECT_EQ(operationResult.errCode_, 0); @@ -491,4 +502,65 @@ HWTEST_F(DataShareServiceImplTest, GetCallerInfo002, TestSize.Level1) EXPECT_EQ(result.first, false); ZLOGI("DataShareServiceImplTest GetCallerInfo002 end"); } + +/** +* @tc.name: GetSilentProxyStatus001 +* @tc.desc: test GetSilentProxyStatus001 function while creating helper +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(DataShareServiceImplTest, GetSilentProxyStatus001, TestSize.Level1) +{ + ZLOGI("DataShareServiceImplTest GetSilentProxyStatus001 start"); + SetSelfTokenInfo(NATIVE_USER_ID); + DataShareServiceImpl dataShareServiceImpl; + auto result = dataShareServiceImpl.GetSilentProxyStatus(SLIENT_ACCESS_URI, true); + EXPECT_EQ(result, OHOS::DataShare::E_OK); + + result = dataShareServiceImpl.GetSilentProxyStatus(SLIENT_ACCESS_URI + "?user=100", true); + EXPECT_EQ(result, OHOS::DataShare::E_OK); + SetSelfTokenInfo(USER_TEST); + ZLOGI("DataShareServiceImplTest GetSilentProxyStatus001 end"); +} + +/** +* @tc.name: DataProviderConfig001 +* @tc.desc: test get provider info function +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(DataShareServiceImplTest, DataProviderConfig001, TestSize.Level1) +{ + ZLOGI("DataShareServiceImplTest DataProviderConfig001 start"); + SetSelfTokenInfo(NATIVE_USER_ID); + auto testTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(NATIVE_USER_ID, BUNDLE_NAME, 0); + EXPECT_CALL(*accountDelegateMock, QueryForegroundUserId(testing::_)).Times(1).WillOnce(testing::Return(false)); + DataProviderConfig config(SLIENT_ACCESS_URI, testTokenId); + EXPECT_EQ(config.providerInfo_.uri, SLIENT_ACCESS_URI); + EXPECT_EQ(config.providerInfo_.currentUserId, NATIVE_USER_ID); + EXPECT_EQ(config.providerInfo_.visitedUserId, NATIVE_USER_ID); + SetSelfTokenInfo(USER_TEST); + ZLOGI("DataShareServiceImplTest DataProviderConfig001 end"); +} + +/** +* @tc.name: UpdateLaunchInfoMock001 +* @tc.desc: mock GetInstance return nullptr +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(DataShareServiceImplTest, UpdateLaunchInfo001, TestSize.Level1) +{ + ZLOGI("DataShareServiceImplTest UpdateLaunchInfo001 start"); + + DataShareServiceImpl dataShareServiceImpl; + // cover branch of config is nullptr + dataShareServiceImpl.UpdateLaunchInfo(); + + std::string prefix = StoreMetaData::GetPrefix({ DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid }); + std::vector storeMetaData; + MetaDataManager::GetInstance().LoadMeta(prefix, storeMetaData, true); + EXPECT_EQ(storeMetaData.size(), 0); + ZLOGI("DataShareServiceImplTest UpdateLaunchInfo001 end"); +} } // namespace OHOS::Test \ No newline at end of file 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 c5bccacf1a7e49954c7ce1ac0b1500ad974a0cc2..63406f3913181d059a8153af41ff8181a2fd9918 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 @@ -110,9 +110,9 @@ HWTEST_F(DataShareSubscriberManagersTest, Add, TestSize.Level1) nodes.emplace_back(node2); Template tpl(nodes, "select name1 as name from TBL00"); DataShare::Key key(DATA_SHARE_URI_TEST, tpltId.subscriberId_, tpltId.bundleName_); - auto result = TemplateManager::GetInstance().Add(key, context->currentUserId, tpl); + auto result = TemplateManager::GetInstance().Add(key, context->visitedUserId, tpl); EXPECT_EQ(result, DataShare::E_ERROR); - result = TemplateManager::GetInstance().Delete(key, context->currentUserId); + result = TemplateManager::GetInstance().Delete(key, context->visitedUserId); EXPECT_EQ(result, DataShare::E_ERROR); } @@ -210,7 +210,7 @@ HWTEST_F(DataShareSubscriberManagersTest, IsNotifyOnEnabled, TestSize.Level1) sptr observer; std::vector val; std::map, std::vector> callbacks; - PublishedDataSubscriberManager::GetInstance().PutInto(callbacks, val, key, observer); + PublishedDataSubscriberManager::GetInstance().PutInto(callbacks, val, key, observer, context->visitedUserId); std::vector publishedKeys; PublishedDataSubscriberManager::GetInstance().SetObserversNotifiedOnEnabled(publishedKeys); uint32_t tokenId = AccessTokenKit::GetHapTokenID(USER_TEST, BUNDLE_NAME_TEST, USER_TEST); diff --git a/datamgr_service/services/distributeddataservice/service/test/data_share_sys_event_subscriber_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_sys_event_subscriber_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e6097ef1fc4dbd80b550d8954c07ead96f58d8a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_sys_event_subscriber_test.cpp @@ -0,0 +1,67 @@ +/* +* Copyright (c) 2025 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 "DataShareSysEventSubscriberTest" + +#include "sys_event_subscriber.h" + +#include + +#include "data_share_service_impl.h" +#include "common_event_manager.h" +#include "common_event_support.h" +#include "log_print.h" +#include "mock/meta_data_manager_mock.h" +#include "proxy_data_manager.h" + +namespace OHOS::Test { +using namespace OHOS::DataShare; +using namespace testing::ext; +class DataShareSysEventSubscriberTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +/** +* @tc.name: OnBMSReady001 +* @tc.desc: test OnBMSReady func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareSysEventSubscriberTest, OnBMSReady001, TestSize.Level1) +{ + ZLOGI("DataShareSysEventSubscriberTest OnBMSReady001 start"); + EventFwk::MatchingSkills testMatchingSkills; + testMatchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED); + testMatchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED); + testMatchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); + EventFwk::CommonEventSubscribeInfo subscribeInfo(testMatchingSkills); + subscribeInfo.SetThreadMode(EventFwk::CommonEventSubscribeInfo::COMMON); + // executors not null + auto executors = std::make_shared(1, 0); + // make sysEventSubscriber not null + auto sysEventSubscriber = std::make_shared(subscribeInfo, executors);\ + ASSERT_NE(sysEventSubscriber, nullptr); + sysEventSubscriber->OnBMSReady(); + ASSERT_NE(sysEventSubscriber->executors_, nullptr); + + // cover executors == nullptr branch + sysEventSubscriber->executors_ = nullptr; + ASSERT_EQ(sysEventSubscriber->executors_, nullptr); + sysEventSubscriber->OnBMSReady(); + ZLOGI("DataShareSysEventSubscriberTest OnBMSReady001 end"); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_uri_utils_test.cpp similarity index 34% rename from relational_store/frameworks/native/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp rename to datamgr_service/services/distributeddataservice/service/test/data_share_uri_utils_test.cpp index 801ed84b983c4468b2397047ea34f1429bb86969..baccbc53a6dcb98faa05e8387a01bf2fbe995c46 100644 --- a/relational_store/frameworks/native/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_uri_utils_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (C) 2025 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 @@ -12,51 +12,52 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define LOG_TAG "DatashareURIUtilsTest" +#include "utils.h" -#include "rdb_device_manager_adapter.h" - +#include #include namespace OHOS { -namespace DeviceManagerAdaptor { -using namespace OHOS::DistributedHardware; -constexpr int32_t DM_OK = 0; -constexpr int32_t DM_ERROR = -1; -RdbDeviceManagerAdaptor::RdbDeviceManagerAdaptor(const std::string &packageName) - :packageName_(packageName) +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::DataShare; +class DatashareURIUtilsTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +HWTEST_F(DatashareURIUtilsTest, GeneralAnonymous_001, TestSize.Level0) { - Init(); + EXPECT_EQ(StringUtils::GeneralAnonymous("DataShareTable"), "Data***able"); } -RdbDeviceManagerAdaptor::~RdbDeviceManagerAdaptor() +HWTEST_F(DatashareURIUtilsTest, GeneralAnonymous_002, TestSize.Level0) { - UnInit(); + EXPECT_EQ(StringUtils::GeneralAnonymous("1bc"), "******"); } -RdbDeviceManagerAdaptor &RdbDeviceManagerAdaptor::GetInstance(const std::string &packageName) +HWTEST_F(DatashareURIUtilsTest, GeneralAnonymous_003, TestSize.Level0) { - static RdbDeviceManagerAdaptor instance(packageName); - return instance; + EXPECT_EQ(StringUtils::GeneralAnonymous("contact"), "cont***"); } -void RdbDeviceManagerAdaptor::Init() +HWTEST_F(DatashareURIUtilsTest, GeneralAnonymous_004, TestSize.Level0) { - auto callback = std::make_shared(); - DeviceManager::GetInstance().InitDeviceManager(packageName_, callback); + EXPECT_EQ(StringUtils::GeneralAnonymous("name"), "******"); } -void RdbDeviceManagerAdaptor::UnInit() +HWTEST_F(DatashareURIUtilsTest, GeneralAnonymous_005, TestSize.Level0) { - DeviceManager::GetInstance().UnInitDeviceManager(packageName_); + EXPECT_EQ(StringUtils::GeneralAnonymous(""), "******"); } -int RdbDeviceManagerAdaptor::GetEncryptedUuidByNetworkId(const std::string &networkId, std::string &uuid) +HWTEST_F(DatashareURIUtilsTest, GeneralAnonymous_006, TestSize.Level0) { - int ret = DeviceManager::GetInstance().GetEncryptedUuidByNetworkId(packageName_, networkId, uuid); - if (ret != DM_OK) { - return DM_ERROR; - } - return DM_OK; + EXPECT_EQ(StringUtils::GeneralAnonymous("store.db"), "stor***"); } -} // namespace DeviceManagerAdaptor +} // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/directory_manager_test.cpp b/datamgr_service/services/distributeddataservice/service/test/directory_manager_test.cpp index c763765ab1544cf3ab8e5df7d8b395f666eb94b1..96a433b954248e3b64d9369a51462bb77df1fafd 100644 --- a/datamgr_service/services/distributeddataservice/service/test/directory_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/directory_manager_test.cpp @@ -191,6 +191,33 @@ HWTEST_F(DirectoryManagerTest, GetKVDBBackupPath, TestSize.Level0) EXPECT_EQ(path, metaData.dataDir + "/backup/testStpre"); } +/** +* @tc.name: GetUdmfPath +* @tc.desc: test get udmf store path +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(DirectoryManagerTest, GetUdmfStorePath, TestSize.Level0) +{ + StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); + metaData.appId = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); + metaData.storeId = "drag"; + metaData.securityLevel = SecurityLevel::S2; + metaData.tokenId = GetAccessTokenId(&tokenParam_); + metaData.area = DistributedKv::Area::EL2; + metaData.uid = static_cast(getuid()); + metaData.storeType = DistributedKv::KvStoreType::SINGLE_VERSION; + metaData.dataType = DistributedKv::DataType::TYPE_DYNAMICAL; + metaData.authType = DistributedKv::AuthType::IDENTICAL_ACCOUNT; + metaData.dataDir = "/data/service/el2/100/database/distributeddata/kvdb"; + auto path = DirectoryManager::GetInstance().GetStorePath(metaData); + EXPECT_EQ(path, metaData.dataDir); + auto res = DistributedData::DirectoryManager::GetInstance().CreateDirectory(path); + EXPECT_EQ(res, true); +} + /** * @tc.name: GetStorageMetaPath * @tc.desc: test get meta store dir @@ -229,30 +256,32 @@ HWTEST_F(DirectoryManagerTest, GetSecretKeyPath, TestSize.Level0) } /** -* @tc.name: DeleteDirectory -* @tc.desc: test delete dir +* @tc.name: GetStoreTypePath +* @tc.desc: test get db dir * @tc.type: FUNC -* @tc.require: -* @tc.author: */ -HWTEST_F(DirectoryManagerTest, DeleteDirectory, TestSize.Level0) +HWTEST_F(DirectoryManagerTest, GetStoreTypePath, TestSize.Level0) { - std::string path = "/data/service/el1/public/database/bundle_manager_service/kvdb/100/data"; - bool ret = DirectoryManager::GetInstance().CreateDirectory(path); - EXPECT_TRUE(ret); - std::ofstream file( - "/data/service/el1/public/database/bundle_manager_service/kvdb/100/data/test.txt", std::ios::out); - if (file.is_open()) { - file << "test content" << std::endl; - file.close(); - } - std::ofstream file1("/data/service/el1/public/database/bundle_manager_service/kvdb/100/test.txt", std::ios::out); - if (file1.is_open()) { - file1 << "test content" << std::endl; - file1.close(); - } - std::string deleteDir = "/data/service/el1/public/database/bundle_manager_service/kvdb/100"; - bool ret1 = DirectoryManager::GetInstance().DeleteDirectory(deleteDir.c_str()); - EXPECT_TRUE(ret1); - EXPECT_EQ(access(deleteDir.c_str(), F_OK), -1); + StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = "ohos.test.demo"; + metaData.securityLevel = SecurityLevel::S2; + metaData.area = 1; + metaData.tokenId = AccessTokenKit::GetHapTokenID(100, "ohos.test.demo", 0); + metaData.appId = "ohos.test.demo_09AEF01D"; + + metaData.storeType = StoreMetaData::StoreType::STORE_KV_BEGIN; + metaData.dataDir = "/data/app/el1/100/database/ohos.test.demo/kvdb"; + auto path = DirectoryManager::GetInstance().GetStorePath(metaData); + EXPECT_EQ(path, metaData.dataDir); + + metaData.storeType = StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN; + metaData.dataDir = "/data/app/el1/100/database/ohos.test.demo/rdb"; + path = DirectoryManager::GetInstance().GetStorePath(metaData); + EXPECT_EQ(path, metaData.dataDir); + + metaData.storeType = StoreMetaData::StoreType::STORE_BUTT; + metaData.dataDir = "/data/app/el1/100/database/ohos.test.demo/other"; + path = DirectoryManager::GetInstance().GetStorePath(metaData); + EXPECT_EQ(path, metaData.dataDir); } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/BUILD.gn index efc92352430c137946660de49280abbe6e5ed71f..107fde072f00517c48d248546298c1d07c45abc9 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/BUILD.gn @@ -21,11 +21,18 @@ group("fuzztest") { deps = [ "dumphelper_fuzzer:fuzztest" ] if (datamgr_service_cloud) { - deps += [ "cloudservicestub_fuzzer:fuzztest" ] + deps += [ + "cloudservicestub_fuzzer:fuzztest", + "syncstrategies_fuzzer:fuzztest", + ] } if (datamgr_service_object) { - deps += [ "objectservicestub_fuzzer:fuzztest" ] + deps += [ + "objectservicestub_fuzzer:fuzztest", + "objectserviceimp_fuzzer:fuzztest", + "objectservicelistener_fuzzer:fuzztest", + ] } if (datamgr_service_rdb) { @@ -40,7 +47,11 @@ group("fuzztest") { } if (datamgr_service_data_share) { - deps += [ "datashareservicestub_fuzzer:fuzztest" ] + deps += [ + "datashareservicestub_fuzzer:fuzztest", + "datashareserviceimpl_fuzzer:fuzztest", + "datasharesubscriber_fuzzer:fuzztest", + ] } if (datamgr_service_udmf) { 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 3cb8f10bdf4a4f02757ff2f3dbfc594e0248ee1b..2618103ace822684639fc84ba74a3d5f944570bc 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 @@ -20,11 +20,6 @@ ohos_fuzztest("CloudServiceStubFuzzTest") { module_out_path = "datamgr_service/datamgr_service" include_dirs = [ - "${data_service_path}/adapter/include", - "${data_service_path}/app/src", - "${data_service_path}/framework/include", - "${data_service_path}/service/backup/include", - "${data_service_path}/service/bootstrap/include", "${data_service_path}/service/cloud", "${data_service_path}/service/common", "${data_service_path}/service/config/include", @@ -35,24 +30,10 @@ ohos_fuzztest("CloudServiceStubFuzzTest") { "${data_service_path}/service/object", "${data_service_path}/service/permission/include", "${data_service_path}/service/rdb", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_distributeddb_path}", - "${kv_store_distributeddb_path}/include/", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/interfaces/include/relational", - "${dataobject_path}/frameworks/innerkitsimpl/include", - "${relational_store_path}/interfaces/inner_api/cloud_data/include", - "${relational_store_path}/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", - "//third_party/json/single_include", "${data_service_path}/adapter/include/communicator", ] - fuzz_config_file = - "${data_service_path}/service/test/fuzztest/cloudservicestub_fuzzer" + fuzz_config_file = "${data_service_path}/service/test/fuzztest/cloudservicestub_fuzzer" cflags = [ "-g", @@ -64,65 +45,24 @@ ohos_fuzztest("CloudServiceStubFuzzTest") { sources = [ "${data_service_path}/app/src/checker/bundle_checker.cpp", "${data_service_path}/app/src/checker/system_checker.cpp", - "${data_service_path}/service/backup/src/backup_manager.cpp", - "${data_service_path}/service/bootstrap/src/bootstrap.cpp", - "${data_service_path}/service/cloud/cloud_data_translate.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/config/src/model/thread_config.cpp", - "${data_service_path}/service/crypto/src/crypto_manager.cpp", - "${data_service_path}/service/kvdb/user_delegate.cpp", - "${data_service_path}/service/permission/src/permission_validator.cpp", - "${data_service_path}/service/permission/src/permit_delegate.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_cursor.cpp", - "${data_service_path}/service/rdb/rdb_general_store.cpp", - "${data_service_path}/service/rdb/rdb_hiview_adapter.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_schema_config.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", "cloudservicestub_fuzzer.cpp", ] deps = [ "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/adapter/dfx:distributeddata_dfx", "${data_service_path}/adapter/network:distributeddata_network", "${data_service_path}/adapter/schema_helper:distributeddata_schema_helper", "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "${kv_store_distributeddb_path}:distributeddb", + "${data_service_path}/service/bootstrap:distributeddata_bootstrap", + "${data_service_path}/service/cloud:distributeddata_cloud", + "${data_service_path}/service/common:distributeddata_common", + "${data_service_path}/service/rdb:distributeddata_rdb", ] external_deps = [ - "ability_base:want", - "ability_base:zuri", - "ability_runtime:ability_manager", - "ability_runtime:dataobs_manager", "access_token:libaccesstoken_sdk", "access_token:libtoken_setproc", "access_token:libtokenid_sdk", @@ -136,8 +76,10 @@ ohos_fuzztest("CloudServiceStubFuzzTest") { "hisysevent:libhisysevent", "huks:libhukssdk", "ipc:ipc_core", + "kv_store:datamgr_common", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", + "kv_store:distributeddb", "relational_store:native_rdb", "resource_management:global_resmgr", "safwk:system_ability_fwk", diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/cloudservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/cloudservicestub_fuzzer.cpp index 1d11a9d364ddc97648aecde35e9d0b0fb7aa58fb..72904220550511427cc54f076b9f1b836de3bdf3 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/cloudservicestub_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/cloudservicestub_fuzzer.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "cloudservicestub_fuzzer.h" #include @@ -65,19 +67,22 @@ void AllocAndSetHapToken() SetSelfTokenID(tokenID.tokenIDEx); } -bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { - std::shared_ptr cloudServiceImpl = std::make_shared(); - std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); - cloudServiceImpl->OnBind( - { "CloudServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - - AllocAndSetHapToken(); + static std::shared_ptr cloudServiceImpl = std::make_shared(); + static std::once_flag onceFlag; + std::call_once(onceFlag, [&]() { + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + cloudServiceImpl->OnBind( + { "CloudServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + AllocAndSetHapToken(); + }); - uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + uint32_t code = provider.ConsumeIntegralInRange(CODE_MIN, CODE_MAX); + std::vector remainingData = provider.ConsumeRemainingBytes(); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); - request.WriteBuffer(data, size); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); request.RewindRead(0); MessageParcel reply; std::shared_ptr cloudServiceStub = cloudServiceImpl; @@ -89,11 +94,7 @@ bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::OnRemoteRequestFuzz(data, size); - + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..baa4fa6efdd1a20dfbe11b2d162431452b184ad8 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/BUILD.gn @@ -0,0 +1,151 @@ +# Copyright (c) 2025 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("DataShareServiceImplFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + include_dirs = [ + "${data_service_path}/adapter/include", + "${data_service_path}/app/src", + "${data_service_path}/framework/include", + "${data_service_path}/service/common", + "${data_service_path}/service/config/include", + "${data_service_path}/service/crypto/include", + "${data_service_path}/service/data_share/common", + "${data_service_path}/service/data_share/data", + "${data_service_path}/service/data_share/dfx", + "${data_service_path}/service/data_share/strategies", + "${data_service_path}/service/data_share/subscriber_managers", + "${data_service_path}/service/data_share", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/permission/include", + "${data_service_path}/adapter/include/communicator", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/datashareserviceimpl_fuzzer" + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ + "${data_service_path}/service/common/xcollie.cpp", + "${data_service_path}/service/data_share/common/app_connect_manager.cpp", + "${data_service_path}/service/data_share/common/bundle_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/common_utils.cpp", + "${data_service_path}/service/data_share/common/db_delegate.cpp", + "${data_service_path}/service/data_share/common/div_strategy.cpp", + "${data_service_path}/service/data_share/common/extension_ability_manager.cpp", + "${data_service_path}/service/data_share/common/extension_connect_adaptor.cpp", + "${data_service_path}/service/data_share/common/extension_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/kv_delegate.cpp", + "${data_service_path}/service/data_share/common/proxy_data_manager.cpp", + "${data_service_path}/service/data_share/common/rdb_delegate.cpp", + "${data_service_path}/service/data_share/common/scheduler_manager.cpp", + "${data_service_path}/service/data_share/common/seq_strategy.cpp", + "${data_service_path}/service/data_share/common/utils.cpp", + "${data_service_path}/service/data_share/data/published_data.cpp", + "${data_service_path}/service/data_share/data/resultset_json_formatter.cpp", + "${data_service_path}/service/data_share/data/template_data.cpp", + "${data_service_path}/service/data_share/data_provider_config.cpp", + "${data_service_path}/service/data_share/data_share_db_config.cpp", + "${data_service_path}/service/data_share/data_share_obs_proxy.cpp", + "${data_service_path}/service/data_share/data_share_profile_config.cpp", + "${data_service_path}/service/data_share/data_share_service_impl.cpp", + "${data_service_path}/service/data_share/data_share_service_stub.cpp", + "${data_service_path}/service/data_share/data_share_silent_config.cpp", + "${data_service_path}/service/data_share/data_share_types_util.cpp", + "${data_service_path}/service/data_share/dfx/hiview_adapter.cpp", + "${data_service_path}/service/data_share/dfx/hiview_fault_adapter.cpp", + "${data_service_path}/service/data_share/strategies/data_proxy/load_config_from_data_proxy_node_strategy.cpp", + "${data_service_path}/service/data_share/strategies/data_share/load_config_from_data_share_bundle_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/check_is_data_proxy_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/check_is_single_app_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/cross_permission_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_common_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_data_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_from_bundle_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/permission_strategy.cpp", + "${data_service_path}/service/data_share/strategies/get_data_strategy.cpp", + "${data_service_path}/service/data_share/strategies/publish_strategy.cpp", + "${data_service_path}/service/data_share/strategies/rdb_notify_strategy.cpp", + "${data_service_path}/service/data_share/strategies/subscribe_strategy.cpp", + "${data_service_path}/service/data_share/strategies/template_strategy.cpp", + "${data_service_path}/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp", + "${data_service_path}/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp", + "${data_service_path}/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp", + "${data_service_path}/service/data_share/sys_event_subscriber.cpp", + "${data_service_path}/service/kvdb/user_delegate.cpp", + "${data_service_path}/service/permission/src/permit_delegate.cpp", + "datashareserviceimpl_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "ability_runtime:wantagent_innerkits", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "data_share:datashare_common", + "data_share:datashare_consumer", + "device_manager:devicemanagersdk", + "hicollie:libhicollie", + "hilog:libhilog", + "hisysevent:libhisysevent", + "huks:libhukssdk", + "init:libbegetutil", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "qos_manager:concurrent_task_client", + "qos_manager:qos", + "relational_store:native_rdb", + "relational_store:rdb_data_share_adapter", + "resource_management:global_resmgr", + "samgr:samgr_proxy", + "time_service:time_client", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":DataShareServiceImplFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..7ade8a0faafeaedba7241e7d4a97b8e1f9691932 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/datashareserviceimpl_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/datashareserviceimpl_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..83644b248371376d72cb6b254448f89af95edfc3 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/datashareserviceimpl_fuzzer.cpp @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2025 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 "datashareserviceimpl_fuzzer.h" + +#include +#include + +#include "data_share_service_impl.h" +#include "ipc_skeleton.h" +#include "message_parcel.h" +#include "securec.h" + +using namespace OHOS::DataShare; +namespace OHOS { + +void NotifyChangeFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string uri = provider.ConsumeRandomLengthString(); + int32_t userId = provider.ConsumeIntegral(); + dataShareServiceImpl->NotifyChange(uri, userId); +} + +void GetCallerInfoFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string bundleName = "bundlename"; + int32_t appIndex = provider.ConsumeIntegral(); + dataShareServiceImpl->GetCallerInfo(bundleName, appIndex); +} + +void MakeMetaDataFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string bundleName = provider.ConsumeRandomLengthString(); + std::string userId = provider.ConsumeRandomLengthString(); + std::string deviceId = provider.ConsumeRandomLengthString(); + std::string storeId = provider.ConsumeRandomLengthString(); + dataShareServiceImpl->MakeMetaData(bundleName, userId, deviceId, storeId); +} + +void OnAppUninstallFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string bundleName = provider.ConsumeRandomLengthString(); + int32_t userId = provider.ConsumeIntegral(); + int32_t index = provider.ConsumeIntegral(); + dataShareServiceImpl->OnAppUninstall(bundleName, userId, index); +} + +void OnAppUpdateFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string bundleName = provider.ConsumeRandomLengthString(); + int32_t userId = provider.ConsumeIntegral(); + int32_t index = provider.ConsumeIntegral(); + dataShareServiceImpl->OnAppUpdate(bundleName, userId, index); +} + +void RegisterObserverFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string uri = provider.ConsumeRandomLengthString(); + sptr remoteObj = nullptr; + dataShareServiceImpl->RegisterObserver(uri, remoteObj); +} + +void UnregisterObserverFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string uri = provider.ConsumeRandomLengthString(); + sptr remoteObj = nullptr; + dataShareServiceImpl->UnregisterObserver(uri, remoteObj); +} + +void VerifyAcrossAccountsPermissionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + int32_t curId = provider.ConsumeIntegral(); + int32_t visId = provider.ConsumeIntegral(); + std::string permission = provider.ConsumeRandomLengthString(); + uint32_t tokenId = provider.ConsumeIntegral(); + dataShareServiceImpl->VerifyAcrossAccountsPermission(curId, visId, permission, tokenId); +} + +void CheckAllowListFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + uint32_t currentUserId = provider.ConsumeIntegral(); + uint32_t callerTokenId = provider.ConsumeIntegral(); + std::vector allowLists; + AllowList list1; + list1.appIdentifier = provider.ConsumeRandomLengthString(); + list1.onlyMain = provider.ConsumeBool(); + AllowList list2; + list2.appIdentifier = provider.ConsumeRandomLengthString(); + list2.onlyMain = provider.ConsumeBool(); + allowLists.push_back(list1); + allowLists.push_back(list2); + dataShareServiceImpl->CheckAllowList(currentUserId, callerTokenId, allowLists); +} + +void ReportExcuteFaultFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + uint32_t callingTokenId = provider.ConsumeIntegral(); + int32_t errCode = provider.ConsumeIntegral(); + std::string func = provider.ConsumeRandomLengthString(); + DataProviderConfig::ProviderInfo providerInfo; + providerInfo.moduleName = provider.ConsumeRandomLengthString(); + providerInfo.bundleName = provider.ConsumeRandomLengthString(); + providerInfo.storeName = provider.ConsumeRandomLengthString(); + dataShareServiceImpl->ReportExcuteFault(callingTokenId, providerInfo, errCode, func); +} + +void VerifyPermissionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string bundleName = provider.ConsumeRandomLengthString(); + std::string permission = provider.ConsumeRandomLengthString(); + bool isFromExtension = provider.ConsumeBool(); + int32_t tokenId = provider.ConsumeIntegral(); + dataShareServiceImpl->VerifyPermission(bundleName, permission, isFromExtension, tokenId); +} + +void OnAppExitFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + pid_t uid = provider.ConsumeIntegral(); + pid_t pid = provider.ConsumeIntegral(); + uint32_t tokenId = provider.ConsumeIntegral(); + std::string bundleName = provider.ConsumeRandomLengthString(); + dataShareServiceImpl->OnAppExit(uid, pid, tokenId, bundleName); +} + +void DumpDataShareServiceInfoFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + int fd = provider.ConsumeIntegral(); + std::map> params; + params["key1"] = {"value1", "value2"}; + params["key2"] = {"val_b1", "val_b2", "val_b3"}; + dataShareServiceImpl->DumpDataShareServiceInfo(fd, params); +} + +void DataShareStaticOnClearAppStorageFuzz(FuzzedDataProvider &provider) +{ + DataShareServiceImpl::DataShareStatic dataShareStatic; + std::string bundleName = provider.ConsumeRandomLengthString(); + int32_t userId = provider.ConsumeIntegral(); + int32_t index = provider.ConsumeIntegral(); + int32_t tokenId = provider.ConsumeIntegral(); + dataShareStatic.OnClearAppStorage(bundleName, userId, index, tokenId); +} + +void TimerReceiverOnReceiveEventFuzz(FuzzedDataProvider &provider) +{ + DataShareServiceImpl::TimerReceiver tmerReceiver; + EventFwk::Want want; + EventFwk::CommonEventData commonEventData(want); + commonEventData.SetWant(want); + tmerReceiver.OnReceiveEvent(commonEventData); +} + +void OnUserChangeFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + uint32_t code = provider.ConsumeIntegralInRange(0, 10); + std::string user = provider.ConsumeRandomLengthString(); + std::string account = provider.ConsumeRandomLengthString(); + dataShareServiceImpl->OnUserChange(code, user, account); +} + +void DataShareStaticOnAppUninstall(FuzzedDataProvider &provider) +{ + DataShareServiceImpl::DataShareStatic dataShareStatic; + std::string bundleName = provider.ConsumeRandomLengthString(); + int32_t user = provider.ConsumeIntegral(); + int32_t index = provider.ConsumeIntegral(); + dataShareStatic.OnAppUninstall(bundleName, user, index); +} + +void AllowCleanDataLaunchAppFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + int32_t evtId = provider.ConsumeIntegral(); + DistributedData::RemoteChangeEvent::DataInfo dataInfo; + dataInfo.userId = provider.ConsumeRandomLengthString(); + dataInfo.storeId = provider.ConsumeRandomLengthString(); + dataInfo.deviceId = provider.ConsumeRandomLengthString(); + dataInfo.bundleName = provider.ConsumeRandomLengthString(); + DistributedData::RemoteChangeEvent event(evtId, std::move(dataInfo)); + bool launchForCleanData = provider.ConsumeBool(); + dataShareServiceImpl->AllowCleanDataLaunchApp(event, launchForCleanData); +} + +void AutoLaunchFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + int32_t evtId = provider.ConsumeIntegral(); + DistributedData::RemoteChangeEvent::DataInfo dataInfo; + dataInfo.userId = provider.ConsumeRandomLengthString(); + dataInfo.storeId = provider.ConsumeRandomLengthString(); + dataInfo.deviceId = provider.ConsumeRandomLengthString(); + dataInfo.bundleName = provider.ConsumeRandomLengthString(); + DistributedData::RemoteChangeEvent event(evtId, std::move(dataInfo)); + dataShareServiceImpl->AutoLaunch(event); +} + +void UpdateExFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string uri = provider.ConsumeRandomLengthString(); + std::string extUri = provider.ConsumeRandomLengthString(); + DataSharePredicates predicates; + DataShareValuesBucket valuesBucket; + std::string key1 = provider.ConsumeRandomLengthString(); + std::string key2 = provider.ConsumeRandomLengthString(); + std::string key3 = provider.ConsumeRandomLengthString(); + std::string key4 = provider.ConsumeRandomLengthString(); + int valueInt = provider.ConsumeIntegral(); + float valueFloat = provider.ConsumeFloatingPoint(); + std::string valueStr = provider.ConsumeRandomLengthString(); + bool valueBool = provider.ConsumeBool(); + valuesBucket.valuesMap[key1] = valueInt; + valuesBucket.valuesMap[key2] = valueFloat; + valuesBucket.valuesMap[key3] = valueStr; + valuesBucket.valuesMap[key4] = valueBool; + dataShareServiceImpl->UpdateEx(uri, extUri, predicates, valuesBucket); +} + +void DeleteExFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string uri = provider.ConsumeRandomLengthString(); + std::string extUri = provider.ConsumeRandomLengthString(); + DataSharePredicates predicates; + dataShareServiceImpl->DeleteEx(uri, extUri, predicates); +} + +void DelTemplateFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string uri = provider.ConsumeRandomLengthString(); + int64_t subscriberId = provider.ConsumeIntegral(); + dataShareServiceImpl->DelTemplate(uri, subscriberId); +} + +void PublishFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + Data data; + std::string bundleNameOfProvider = provider.ConsumeRandomLengthString(); + dataShareServiceImpl->Publish(data, bundleNameOfProvider); +} + +void SubscribeRdbDataFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + uint8_t len = provider.ConsumeIntegral(); + std::vector uris(len); + for (int i = 0; i < len; i++) { + std::string uri = provider.ConsumeRandomLengthString(); + uris[i] = uri; + } + TemplateId id; + id.subscriberId_ = provider.ConsumeIntegral(); + id.bundleName_ = provider.ConsumeRandomLengthString(); + sptr observer; + dataShareServiceImpl->SubscribeRdbData(uris, id, observer); +} + +void EnableRdbSubsFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + uint8_t len = provider.ConsumeIntegral(); + std::vector uris(len); + for (int i = 0; i < len; i++) { + std::string uri = provider.ConsumeRandomLengthString(); + uris[i] = uri; + } + TemplateId id; + id.subscriberId_ = provider.ConsumeIntegral(); + id.bundleName_ = provider.ConsumeRandomLengthString(); + dataShareServiceImpl->EnableRdbSubs(uris, id); +} + +void SubscribePublishedDataFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + uint8_t len = provider.ConsumeIntegral(); + std::vector uris(len); + for (int i = 0; i < len; i++) { + std::string uri = provider.ConsumeRandomLengthString(); + uris[i] = uri; + } + int64_t subscriberId = provider.ConsumeIntegral(); + sptr observer; + dataShareServiceImpl->SubscribePublishedData(uris, subscriberId, observer); +} + +void DisablePubSubsFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + uint8_t len = provider.ConsumeIntegral(); + std::vector uris(len); + for (int i = 0; i < len; i++) { + std::string uri = provider.ConsumeRandomLengthString(); + uris[i] = uri; + } + int64_t subscriberId = provider.ConsumeIntegral(); + dataShareServiceImpl->DisablePubSubs(uris, subscriberId); +} + +void SaveLaunchInfoFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string userId = provider.ConsumeRandomLengthString(); + std::string deviceId = provider.ConsumeRandomLengthString(); + std::string bundleName = provider.ConsumeRandomLengthString(); + dataShareServiceImpl->SaveLaunchInfo(bundleName, userId, deviceId); +} + +void OnConnectDoneFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + dataShareServiceImpl->OnConnectDone(); +} + +void DataShareStaticOnAppUpdate(FuzzedDataProvider &provider) +{ + DataShareServiceImpl::DataShareStatic dataShareStatic; + std::string bundleName = provider.ConsumeRandomLengthString(); + int32_t user = provider.ConsumeIntegral(); + int32_t index = provider.ConsumeIntegral(); + dataShareStatic.OnAppUpdate(bundleName, user, index); +} + +void EnableSilentProxyFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string uri = provider.ConsumeRandomLengthString(); + bool enable = provider.ConsumeBool(); + dataShareServiceImpl->EnableSilentProxy(uri, enable); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::NotifyChangeFuzz(provider); + OHOS::GetCallerInfoFuzz(provider); + OHOS::MakeMetaDataFuzz(provider); + OHOS::OnAppUninstallFuzz(provider); + OHOS::OnAppUpdateFuzz(provider); + OHOS::RegisterObserverFuzz(provider); + OHOS::UnregisterObserverFuzz(provider); + OHOS::VerifyAcrossAccountsPermissionFuzz(provider); + OHOS::CheckAllowListFuzz(provider); + OHOS::ReportExcuteFaultFuzz(provider); + OHOS::VerifyPermissionFuzz(provider); + OHOS::OnAppExitFuzz(provider); + OHOS::DumpDataShareServiceInfoFuzz(provider); + OHOS::DataShareStaticOnClearAppStorageFuzz(provider); + OHOS::TimerReceiverOnReceiveEventFuzz(provider); + OHOS::OnUserChangeFuzz(provider); + OHOS::DataShareStaticOnAppUninstall(provider); + OHOS::AllowCleanDataLaunchAppFuzz(provider); + OHOS::AutoLaunchFuzz(provider); + OHOS::UpdateExFuzz(provider); + OHOS::DeleteExFuzz(provider); + OHOS::DelTemplateFuzz(provider); + OHOS::PublishFuzz(provider); + OHOS::SubscribeRdbDataFuzz(provider); + OHOS::EnableRdbSubsFuzz(provider); + OHOS::SubscribePublishedDataFuzz(provider); + OHOS::DisablePubSubsFuzz(provider); + OHOS::SaveLaunchInfoFuzz(provider); + OHOS::OnConnectDoneFuzz(provider); + OHOS::DataShareStaticOnAppUpdate(provider); + OHOS::EnableSilentProxyFuzz(provider); + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/datashareserviceimpl_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/datashareserviceimpl_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..24a855ff54a48dd0943d597808d19212c1357065 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/datashareserviceimpl_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 DATAMGR_SERVICE_DATA_SHARE_SERVICE_IMPL_FUZZER_H +#define DATAMGR_SERVICE_DATA_SHARE_SERVICE_IMPL_FUZZER_H + +#define FUZZ_PROJECT_NAME "datashareserviceimpl_fuzzer" + +#endif // DATAMGR_SERVICE_DATA_SHARE_SERVICE_IMPL_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a37a23b1533f07ab59744732b0f46b2b5fd958d8 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn index 67dd09415dd34bb43fbcf57b9e30b2ac55a2a287..5824983758ed23c0ab72fde32937e49601f7e9c2 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn @@ -24,6 +24,7 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "${data_service_path}/app/src", "${data_service_path}/framework/include", "${data_service_path}/service/common", + "${data_service_path}/service/config/include", "${data_service_path}/service/crypto/include", "${data_service_path}/service/data_share/common", "${data_service_path}/service/data_share/data", @@ -33,10 +34,6 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "${data_service_path}/service/data_share", "${data_service_path}/service/kvdb", "${data_service_path}/service/permission/include", - "${datashare_path}/frameworks/native/common/include", - "${datashare_path}/interfaces/inner_api/common/include", - "${datashare_path}/interfaces/inner_api/consumer/include", - "//third_party/json/single_include", "${data_service_path}/adapter/include/communicator", ] @@ -52,19 +49,20 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { sources = [ "${data_service_path}/service/common/xcollie.cpp", - "${data_service_path}/service/crypto/src/crypto_manager.cpp", "${data_service_path}/service/data_share/common/app_connect_manager.cpp", "${data_service_path}/service/data_share/common/bundle_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/common_utils.cpp", "${data_service_path}/service/data_share/common/db_delegate.cpp", "${data_service_path}/service/data_share/common/div_strategy.cpp", "${data_service_path}/service/data_share/common/extension_ability_manager.cpp", "${data_service_path}/service/data_share/common/extension_connect_adaptor.cpp", "${data_service_path}/service/data_share/common/extension_mgr_proxy.cpp", "${data_service_path}/service/data_share/common/kv_delegate.cpp", + "${data_service_path}/service/data_share/common/proxy_data_manager.cpp", "${data_service_path}/service/data_share/common/rdb_delegate.cpp", "${data_service_path}/service/data_share/common/scheduler_manager.cpp", "${data_service_path}/service/data_share/common/seq_strategy.cpp", - "${data_service_path}/service/data_share/common/uri_utils.cpp", + "${data_service_path}/service/data_share/common/utils.cpp", "${data_service_path}/service/data_share/data/published_data.cpp", "${data_service_path}/service/data_share/data/resultset_json_formatter.cpp", "${data_service_path}/service/data_share/data/template_data.cpp", @@ -92,6 +90,7 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "${data_service_path}/service/data_share/strategies/rdb_notify_strategy.cpp", "${data_service_path}/service/data_share/strategies/subscribe_strategy.cpp", "${data_service_path}/service/data_share/strategies/template_strategy.cpp", + "${data_service_path}/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp", "${data_service_path}/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp", "${data_service_path}/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp", "${data_service_path}/service/data_share/sys_event_subscriber.cpp", @@ -104,6 +103,7 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "${data_service_path}/adapter/account:distributeddata_account", "${data_service_path}/adapter/communicator:distributeddata_communicator", "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", ] external_deps = [ @@ -120,6 +120,7 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "c_utils:utils", "common_event_service:cesfwk_innerkits", "data_share:datashare_common", + "data_share:datashare_consumer", "device_manager:devicemanagersdk", "hicollie:libhicollie", "hilog:libhilog", @@ -129,6 +130,8 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddb", + "qos_manager:concurrent_task_client", + "qos_manager:qos", "relational_store:native_rdb", "relational_store:rdb_data_share_adapter", "resource_management:global_resmgr", diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/datashareservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/datashareservicestub_fuzzer.cpp index df4f212d0b29f305a3cb0b8fb20f65b8010b630f..ca846d3201f7a1230408fb276a4337f4c4b11393 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/datashareservicestub_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/datashareservicestub_fuzzer.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "datashareservicestub_fuzzer.h" #include @@ -28,37 +30,74 @@ using namespace OHOS::DataShare; namespace OHOS { const std::u16string INTERFACE_TOKEN = u"OHOS.DataShare.IDataShareService"; constexpr uint32_t CODE_MIN = 0; -constexpr uint32_t CODE_MAX = IDataShareService::DATA_SHARE_SERVICE_CMD_MAX + 1; +constexpr uint32_t CODE_MAX = static_cast(IDataShareService::DATA_SHARE_SERVICE_CMD_MAX) + 1; constexpr size_t NUM_MIN = 5; constexpr size_t NUM_MAX = 12; -bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { std::shared_ptr dataShareServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); dataShareServiceImpl->OnBind( { "DataShareServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + uint32_t code = provider.ConsumeIntegralInRange(CODE_MIN, CODE_MAX); + std::vector remainingData = provider.ConsumeRemainingBytes(); + MessageParcel request; + request.WriteInterfaceToken(INTERFACE_TOKEN); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); + request.RewindRead(0); + MessageParcel reply; + std::shared_ptr dataShareServiceStub = dataShareServiceImpl; + dataShareServiceStub->OnRemoteRequest(code, request, reply); + return true; +} + +bool OnRemoteRequestFuzz01(uint32_t code, FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + dataShareServiceImpl->OnBind( + { "DataShareServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + std::vector remainingData = provider.ConsumeRemainingBytes(); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); - request.WriteBuffer(data, size); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); request.RewindRead(0); MessageParcel reply; std::shared_ptr dataShareServiceStub = dataShareServiceImpl; dataShareServiceStub->OnRemoteRequest(code, request, reply); return true; } + +bool OnRemoteRequestFuzz02(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + dataShareServiceImpl->OnBind( + { "DataShareServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + std::vector remainingData = provider.ConsumeRemainingBytes(); + MessageParcel request; + request.WriteInterfaceToken(INTERFACE_TOKEN); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); + request.RewindRead(0); + MessageParcel reply; + std::shared_ptr dataShareServiceStub = dataShareServiceImpl; + dataShareServiceStub->OnRemoteRequest(IDataShareService::DATA_SHARE_CMD_SYSTEM_CODE, request, reply); + return true; +} } // namespace OHOS /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); + uint32_t codeTest = OHOS::CODE_MIN; + while (codeTest <= OHOS::CODE_MAX) { + OHOS::OnRemoteRequestFuzz01(codeTest, provider); + codeTest++; } - - OHOS::OnRemoteRequestFuzz(data, size); - + OHOS::OnRemoteRequestFuzz02(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..ddfb2cd7bb57b934d81490aeb75a9739e50a4f59 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/BUILD.gn @@ -0,0 +1,151 @@ +# Copyright (c) 2025 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("DataShareSubscriberFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + include_dirs = [ + "${data_service_path}/adapter/include", + "${data_service_path}/app/src", + "${data_service_path}/framework/include", + "${data_service_path}/service/common", + "${data_service_path}/service/config/include", + "${data_service_path}/service/crypto/include", + "${data_service_path}/service/data_share/common", + "${data_service_path}/service/data_share/data", + "${data_service_path}/service/data_share/dfx", + "${data_service_path}/service/data_share/strategies", + "${data_service_path}/service/data_share/subscriber_managers", + "${data_service_path}/service/data_share", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/permission/include", + "${data_service_path}/adapter/include/communicator", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/datasharesubscriber_fuzzer" + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ + "${data_service_path}/service/common/xcollie.cpp", + "${data_service_path}/service/data_share/common/app_connect_manager.cpp", + "${data_service_path}/service/data_share/common/bundle_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/common_utils.cpp", + "${data_service_path}/service/data_share/common/db_delegate.cpp", + "${data_service_path}/service/data_share/common/div_strategy.cpp", + "${data_service_path}/service/data_share/common/extension_ability_manager.cpp", + "${data_service_path}/service/data_share/common/extension_connect_adaptor.cpp", + "${data_service_path}/service/data_share/common/extension_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/kv_delegate.cpp", + "${data_service_path}/service/data_share/common/proxy_data_manager.cpp", + "${data_service_path}/service/data_share/common/rdb_delegate.cpp", + "${data_service_path}/service/data_share/common/scheduler_manager.cpp", + "${data_service_path}/service/data_share/common/seq_strategy.cpp", + "${data_service_path}/service/data_share/common/utils.cpp", + "${data_service_path}/service/data_share/data/published_data.cpp", + "${data_service_path}/service/data_share/data/resultset_json_formatter.cpp", + "${data_service_path}/service/data_share/data/template_data.cpp", + "${data_service_path}/service/data_share/data_provider_config.cpp", + "${data_service_path}/service/data_share/data_share_db_config.cpp", + "${data_service_path}/service/data_share/data_share_obs_proxy.cpp", + "${data_service_path}/service/data_share/data_share_profile_config.cpp", + "${data_service_path}/service/data_share/data_share_service_impl.cpp", + "${data_service_path}/service/data_share/data_share_service_stub.cpp", + "${data_service_path}/service/data_share/data_share_silent_config.cpp", + "${data_service_path}/service/data_share/data_share_types_util.cpp", + "${data_service_path}/service/data_share/dfx/hiview_adapter.cpp", + "${data_service_path}/service/data_share/dfx/hiview_fault_adapter.cpp", + "${data_service_path}/service/data_share/strategies/data_proxy/load_config_from_data_proxy_node_strategy.cpp", + "${data_service_path}/service/data_share/strategies/data_share/load_config_from_data_share_bundle_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/check_is_data_proxy_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/check_is_single_app_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/cross_permission_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_common_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_data_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_from_bundle_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/permission_strategy.cpp", + "${data_service_path}/service/data_share/strategies/get_data_strategy.cpp", + "${data_service_path}/service/data_share/strategies/publish_strategy.cpp", + "${data_service_path}/service/data_share/strategies/rdb_notify_strategy.cpp", + "${data_service_path}/service/data_share/strategies/subscribe_strategy.cpp", + "${data_service_path}/service/data_share/strategies/template_strategy.cpp", + "${data_service_path}/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp", + "${data_service_path}/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp", + "${data_service_path}/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp", + "${data_service_path}/service/data_share/sys_event_subscriber.cpp", + "${data_service_path}/service/kvdb/user_delegate.cpp", + "${data_service_path}/service/permission/src/permit_delegate.cpp", + "datasharesubscriber_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "ability_runtime:wantagent_innerkits", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "data_share:datashare_common", + "data_share:datashare_consumer", + "device_manager:devicemanagersdk", + "hicollie:libhicollie", + "hilog:libhilog", + "hisysevent:libhisysevent", + "huks:libhukssdk", + "init:libbegetutil", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "qos_manager:concurrent_task_client", + "qos_manager:qos", + "relational_store:native_rdb", + "relational_store:rdb_data_share_adapter", + "resource_management:global_resmgr", + "samgr:samgr_proxy", + "time_service:time_client", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":DataShareSubscriberFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..7ade8a0faafeaedba7241e7d4a97b8e1f9691932 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/datasharesubscriber_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/datasharesubscriber_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d55ec512f85ba94183ad69066b79050214d905e1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/datasharesubscriber_fuzzer.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2025 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 "DataShareSubscriberFuzzTest" +#include + +#include "datasharesubscriber_fuzzer.h" + +#include +#include + +#include "log_print.h" +#include "proxy_data_subscriber_manager.h" +#include "ipc_skeleton.h" +#include "message_parcel.h" +#include "securec.h" + +using namespace OHOS::DataShare; +namespace OHOS { + +void AddFuzz(FuzzedDataProvider &provider) +{ + std::string uri = provider.ConsumeRandomLengthString(); + std::string bundleName = provider.ConsumeRandomLengthString(); + ProxyDataKey key(uri, bundleName); + sptr observer; + std::string callerAppIdentifier = provider.ConsumeRandomLengthString(); + int32_t userId = provider.ConsumeIntegral(); + auto& manager = ProxyDataSubscriberManager::GetInstance(); + manager.Add(key, observer, bundleName, callerAppIdentifier, userId); +} + +void CheckAllowListFuzz(FuzzedDataProvider &provider) +{ + std::string callerAppIdentifier = provider.ConsumeRandomLengthString(); + uint8_t len = provider.ConsumeIntegralInRange(0, 20); + std::vector allowLists(len); + for (int i = 0; i < len; i++) { + std::string allowList = provider.ConsumeRandomLengthString(); + allowLists[i] = allowList; + } + auto& manager = ProxyDataSubscriberManager::GetInstance(); + manager.CheckAllowList(allowLists, callerAppIdentifier); +} + +void EmitFuzz(FuzzedDataProvider &provider) +{ + uint8_t keyNum = provider.ConsumeIntegralInRange(0, 20); + std::vector keys; + for (int i = 0; i < keyNum; i++) { + std::string uri = provider.ConsumeRandomLengthString(); + std::string bundleName = provider.ConsumeRandomLengthString(); + keys.push_back(ProxyDataKey(uri, bundleName)); + } + std::map> datas; + std::vector insertData; + DataShareProxyData data1; + insertData.push_back(data1); + datas[DataShareObserver::ChangeType::INSERT] = insertData; + int32_t userId = provider.ConsumeIntegral(); + auto& manager = ProxyDataSubscriberManager::GetInstance(); + manager.Emit(keys, datas, userId); +} + +void ObserverNodeFuzz(FuzzedDataProvider &provider) +{ + sptr observer; + uint32_t tokenId = provider.ConsumeIntegral(); + std::string name = provider.ConsumeRandomLengthString(); + std::string caller = provider.ConsumeRandomLengthString(); + int32_t userId = provider.ConsumeIntegral(); + ProxyDataSubscriberManager::ObserverNode observerNode(observer, tokenId, name, caller, userId); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::AddFuzz(provider); + OHOS::CheckAllowListFuzz(provider); + OHOS::EmitFuzz(provider); + OHOS::ObserverNodeFuzz(provider); + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/datasharesubscriber_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/datasharesubscriber_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..dfa8298bb8c0fc95a83928cfb18b43afa18daaad --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/datasharesubscriber_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 DATAMGR_SERVICE_DATA_SHARE_SUBSCRIBER_FUZZER_H +#define DATAMGR_SERVICE_DATA_SHARE_SUBSCRIBER_FUZZER_H + +#define FUZZ_PROJECT_NAME "datasharesubscriber_fuzzer" + +#endif // DATAMGR_SERVICE_DATA_SHARE_SUBSCRIBER_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a37a23b1533f07ab59744732b0f46b2b5fd958d8 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/dumphelper_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/dumphelper_fuzzer/BUILD.gn index 2fd165553fc82a02c25e2bec66fe165409078770..a9c5923adf166905d05da9184af41bb7b9a6f296 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/dumphelper_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/dumphelper_fuzzer/BUILD.gn @@ -19,22 +19,7 @@ import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") ohos_fuzztest("DumpHelperFuzzTest") { module_out_path = "datamgr_service/datamgr_service" - include_dirs = [ - "${data_service_path}/service/dumper/include", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_distributeddb_path}", - "${kv_store_distributeddb_path}/include/", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/interfaces/include/relational", - "${dataobject_path}/frameworks/innerkitsimpl/include", - "${relational_store_path}/interfaces/inner_api/cloud_data/include", - "${relational_store_path}/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", - "//third_party/json/single_include", - ] + include_dirs = [ "${data_service_path}/service/dumper/include" ] fuzz_config_file = "${data_service_path}/service/test/fuzztest/dumphelper_fuzzer" @@ -55,7 +40,6 @@ ohos_fuzztest("DumpHelperFuzzTest") { "${data_service_path}/adapter/account:distributeddata_account", "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", - "${kv_store_distributeddb_path}:distributeddb", ] external_deps = [ @@ -75,7 +59,9 @@ ohos_fuzztest("DumpHelperFuzzTest") { "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", + "kv_store:distributeddb", "relational_store:native_rdb", + "kv_store:distributeddb" ] } diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/dumphelper_fuzzer/dumphelper_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/dumphelper_fuzzer/dumphelper_fuzzer.cpp index b8ff95c41935a31104beaac2edcc9be7960636e7..c4033acff3c3358223399f7b732232cd426dce82 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/dumphelper_fuzzer/dumphelper_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/dumphelper_fuzzer/dumphelper_fuzzer.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "dumphelper_fuzzer.h" #include @@ -30,16 +32,15 @@ using namespace OHOS::Security::AccessToken; namespace OHOS { -bool DumpFuzz(const uint8_t *data, size_t size) +bool DumpFuzz(FuzzedDataProvider &provider) { - int connId = static_cast(*data); + int connId = provider.ConsumeIntegral(); std::vector args; const std::string argstest1 = "OHOS.DistributedData.DumpHelper1"; const std::string argstest2 = "OHOS.DistributedData.DumpHelper2"; args.emplace_back(argstest1); args.emplace_back(argstest2); DumpHelper::GetInstance().Dump(connId, args); - return true; } } // namespace OHOS @@ -47,11 +48,7 @@ bool DumpFuzz(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::DumpFuzz(data, size); - + FuzzedDataProvider provider(data, size); + OHOS::DumpFuzz(provider); return 0; } \ No newline at end of file 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 458b5897bf2849a02ae9326a051db12313c77e9d..6e09939e73e7604e5e485e5dd8ae57965cb2430a 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 @@ -33,16 +33,6 @@ ohos_fuzztest("KvdbServiceStubFuzzTest") { "${data_service_path}/service/matrix/include", "${data_service_path}/service/permission/include", "${data_service_path}/service/rdb", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_distributeddb_path}", - "${kv_store_distributeddb_path}/include/", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/interfaces/include/relational", - "${relational_store_path}/interfaces/inner_api/common_type/include", - "//third_party/json/single_include", "${data_service_path}/adapter/include/communicator", "${data_service_path}/adapter/include/utils", ] @@ -64,17 +54,19 @@ 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_access_check_config.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/datashare_config.cpp", + "${data_service_path}/service/config/src/model/device_sync_app_white_list_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/config/src/model/thread_config.cpp", - "${data_service_path}/service/crypto/src/crypto_manager.cpp", "${data_service_path}/service/kvdb/auth_delegate.cpp", "${data_service_path}/service/kvdb/kvdb_exporter.cpp", "${data_service_path}/service/kvdb/kvdb_general_store.cpp", @@ -100,7 +92,6 @@ ohos_fuzztest("KvdbServiceStubFuzzTest") { "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "${kv_store_distributeddb_path}:distributeddb", ] external_deps = [ @@ -119,6 +110,9 @@ ohos_fuzztest("KvdbServiceStubFuzzTest") { "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "kv_store:kvdb_inner_lite", + "relational_store:native_rdb", "safwk:system_ability_fwk", "samgr:samgr_proxy", ] diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/kvdbservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/kvdbservicestub_fuzzer.cpp index 09829930b0a0ef38888381aed2eaa5d846d163e7..09582f0e6aa794612bfbfda9aba39aa3ea7e58e7 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/kvdbservicestub_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/kvdbservicestub_fuzzer.cpp @@ -12,6 +12,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#include + #include "kvdbservicestub_fuzzer.h" #include @@ -33,7 +36,7 @@ constexpr uint32_t CODE_MAX = static_cast(KVDBServiceInterfaceCode::TR constexpr size_t NUM_MIN = 5; constexpr size_t NUM_MAX = 12; -bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { std::shared_ptr kvdbServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); @@ -45,10 +48,11 @@ bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) Bootstrap::GetInstance().LoadCheckers(); Bootstrap::GetInstance().LoadNetworks(); - uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + uint32_t code = provider.ConsumeIntegralInRange(CODE_MIN, CODE_MAX); + std::vector remainingData = provider.ConsumeRemainingBytes(); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); - request.WriteBuffer(data, size); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); request.RewindRead(0); MessageParcel reply; std::shared_ptr kvdbServiceStub = kvdbServiceImpl; @@ -60,11 +64,7 @@ bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::OnRemoteRequestFuzz(data, size); - + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..039f0bf8e697b736d46a178f9b682e1b763e54d1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/BUILD.gn @@ -0,0 +1,74 @@ +# Copyright (c) 2025 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("ObjectServiceImpFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + include_dirs = [ + "${data_service_path}/service/object/include", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/objectserviceimp_fuzzer" + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", + ] + + sources = [ + "objectserviceimp_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "${data_service_path}/service/object:distributeddata_object", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "data_object:data_object_inner", + "data_object:distributeddataobject_impl", + "device_manager:devicemanagersdk", + "dfs_service:distributed_file_daemon_kit_inner", + "dmsfwk:distributed_sdk", + "hilog:libhilog", + "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":ObjectServiceImpFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..7ade8a0faafeaedba7241e7d4a97b8e1f9691932 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/objectserviceimp_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/objectserviceimp_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..de7adc4e9bf1bd6d6327991e3af180e96e7e32f3 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/objectserviceimp_fuzzer.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2025 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 "objectserviceimp_fuzzer.h" +#include "object_service_impl.h" +#include "account/account_delegate.h" + +using namespace OHOS::DistributedObject; + +namespace OHOS { + +void ObjectStoreSaveFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + sptr callback; + std::string bundleName = provider.ConsumeRandomLengthString(100); + std::string sessionId = provider.ConsumeRandomLengthString(100); + std::string deviceId = provider.ConsumeRandomLengthString(100); + std::map> data; + std::vector remainingData = provider.ConsumeRemainingBytes(); + data["key1"] = remainingData; + objectServiceImpl->ObjectStoreSave(bundleName, sessionId, deviceId, data, callback); +} + +void OnUserChangeFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + uint32_t code = static_cast(AccountStatus::DEVICE_ACCOUNT_SWITCHED); + std::string user = provider.ConsumeRandomLengthString(100); + std::string account = provider.ConsumeRandomLengthString(100); + objectServiceImpl->OnUserChange(code, user, account); +} + +void ObjectStoreRevokeSaveFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + sptr callback; + std::string bundleName = provider.ConsumeRandomLengthString(100); + std::string sessionId = provider.ConsumeRandomLengthString(100); + objectServiceImpl->ObjectStoreRevokeSave(bundleName, sessionId, callback); +} + +void ObjectStoreRetrieveFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + sptr callback; + std::string bundleName = provider.ConsumeRandomLengthString(100); + std::string sessionId = provider.ConsumeRandomLengthString(100); + objectServiceImpl->ObjectStoreRetrieve(bundleName, sessionId, callback); +} + +void RegisterDataObserverFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + sptr callback; + std::string bundleName = provider.ConsumeRandomLengthString(100); + std::string sessionId = provider.ConsumeRandomLengthString(100); + objectServiceImpl->RegisterDataObserver(bundleName, sessionId, callback); +} + +void OnAppUninstallFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + if (objectServiceImpl->factory_.staticActs_ == nullptr) { + return; + } + std::string bundleName = provider.ConsumeRandomLengthString(100); + int32_t user = provider.ConsumeIntegral(); + int32_t index = provider.ConsumeIntegral(); + objectServiceImpl->factory_.staticActs_->OnAppUninstall(bundleName, user, index); +} + +void ResolveAutoLaunchFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + std::string identifier = provider.ConsumeRandomLengthString(100); + DistributedDB::AutoLaunchParam param; + objectServiceImpl->ResolveAutoLaunch(identifier, param); +} + +void OnAppExitFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + pid_t uid = provider.ConsumeIntegral(); + pid_t pid = provider.ConsumeIntegral(); + uint32_t tokenId = provider.ConsumeIntegral(); + std::string bundleName = provider.ConsumeRandomLengthString(100); + objectServiceImpl->OnAppExit(uid, pid, tokenId, bundleName); + objectServiceImpl->RegisterObjectServiceInfo(); + objectServiceImpl->RegisterHandler(); +} + +void DumpObjectServiceInfoFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + int fd = provider.ConsumeIntegral(); + std::string key = provider.ConsumeRandomLengthString(100); + std::string value1 = provider.ConsumeRandomLengthString(100); + std::string value2 = provider.ConsumeRandomLengthString(100); + std::map> params; + std::vector value = {value1, value2}; + params.emplace(std::make_pair(key, value)); + objectServiceImpl->DumpObjectServiceInfo(fd, params); +} +void SaveMetaDataFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + StoreMetaData saveMeta; + objectServiceImpl->SaveMetaData(saveMeta); + auto &dmAdapter = DeviceManagerAdapter::GetInstance(); + std::string uuid = provider.ConsumeRandomLengthString(100); + std::string udid = provider.ConsumeRandomLengthString(100); + if (uuid.empty()) { + uuid = "123"; + } + if (udid.empty()) { + udid = "234"; + } + dmAdapter.localInfo_.uuid = uuid; + dmAdapter.localInfo_.udid = udid; + objectServiceImpl->SaveMetaData(saveMeta); +} + +void BindAssetStoreFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + std::string bundleName = provider.ConsumeRandomLengthString(100); + std::string sessionId = provider.ConsumeRandomLengthString(100); + ObjectStore::Asset asset = {.id = provider.ConsumeRandomLengthString(100), + .name = provider.ConsumeRandomLengthString(100), + .uri = provider.ConsumeRandomLengthString(100)}; + ObjectStore::AssetBindInfo bindInfo = {.storeName = provider.ConsumeRandomLengthString(100), + .tableName = provider.ConsumeRandomLengthString(100), + .primaryKey = {{"data1", 123}, {"data2", "test1"}}, + .field = provider.ConsumeRandomLengthString(100), + .assetName = provider.ConsumeRandomLengthString(100)}; + objectServiceImpl->BindAssetStore(bundleName, sessionId, asset, bindInfo); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::ObjectStoreSaveFuzzTest(provider); + OHOS::OnUserChangeFuzzTest(provider); + OHOS::ObjectStoreRevokeSaveFuzzTest(provider); + OHOS::ObjectStoreRetrieveFuzzTest(provider); + OHOS::RegisterDataObserverFuzzTest(provider); + OHOS::OnAppUninstallFuzzTest(provider); + OHOS::ResolveAutoLaunchFuzzTest(provider); + OHOS::OnAppExitFuzzTest(provider); + OHOS::DumpObjectServiceInfoFuzzTest(provider); + OHOS::SaveMetaDataFuzzTest(provider); + OHOS::BindAssetStoreFuzzTest(provider); + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/objectserviceimp_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/objectserviceimp_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..8aa6bb0e28c86ea002b8918d3a5c0d7c35a67a0e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/objectserviceimp_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 OBJECT_SERVICE_IMP_FUZZER_H +#define OBJECT_SERVICE_IMP_FUZZER_H + +#define FUZZ_PROJECT_NAME "objectserviceimp_fuzzer" + +#endif // OBJECT_SERVICE_IMP_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a37a23b1533f07ab59744732b0f46b2b5fd958d8 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..e2105e207fa3c9ba80c8493937162120d60e19c7 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/BUILD.gn @@ -0,0 +1,64 @@ +# Copyright (c) 2025 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("ObjectServiceListenerFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + include_dirs = [ + "${data_service_path}/service/object/include", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/objectservicelistener_fuzzer" + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", + ] + + sources = [ + "objectservicelistener_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "${data_service_path}/service/object:distributeddata_object", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "data_object:data_object_inner", + "dfs_service:distributed_file_daemon_kit_inner", + "hilog:libhilog", + "ipc:ipc_single", + "kv_store:distributeddb", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":ObjectServiceListenerFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..7ade8a0faafeaedba7241e7d4a97b8e1f9691932 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/objectservicelistener_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/objectservicelistener_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f277dab79370b527ffde31320a821b31ebb08c50 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/objectservicelistener_fuzzer.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025 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 "objectservicelistener_fuzzer.h" +#include "object_data_listener.h" + +using namespace OHOS::DistributedObject; + +namespace OHOS { +void OnStartFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectAssetsRecvListener = std::make_shared(); + std::string srcNetworkId = provider.ConsumeRandomLengthString(100); + std::string dstNetworkId = provider.ConsumeRandomLengthString(100); + std::string sessionId = provider.ConsumeRandomLengthString(100); + std::string dstBundleName = provider.ConsumeRandomLengthString(100); + objectAssetsRecvListener->OnStart(srcNetworkId, dstNetworkId, sessionId, dstBundleName); +} + +void OnFinishedFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectAssetsRecvListener = std::make_shared(); + std::string srcNetworkId = provider.ConsumeRandomLengthString(100); + int32_t result = provider.ConsumeIntegral(); + sptr assetObj = new AssetObj(); + objectAssetsRecvListener->OnFinished(srcNetworkId, assetObj, result); +} + +void OnRecvProgressFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectAssetsRecvListener = std::make_shared(); + std::string srcNetworkId = provider.ConsumeRandomLengthString(100); + uint64_t totalBytes = provider.ConsumeIntegral(); + uint64_t processBytes = provider.ConsumeIntegral(); + sptr assetObj1 = new AssetObj(); + objectAssetsRecvListener->OnRecvProgress(srcNetworkId, assetObj1, totalBytes, processBytes); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::OnStartFuzzTest(provider); + OHOS::OnFinishedFuzzTest(provider); + OHOS::OnRecvProgressFuzzTest(provider); + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/objectservicelistener_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/objectservicelistener_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..355f79d97bb7aec2e92714bdc41075e2f639526c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/objectservicelistener_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 OBJECT_SERVICE_LISTENER_FUZZER_H +#define OBJECT_SERVICE_LISTENER_FUZZER_H + +#define FUZZ_PROJECT_NAME "objectservicelistener_fuzzer" + +#endif // OBJECT_SERVICE_LISTENER_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a37a23b1533f07ab59744732b0f46b2b5fd958d8 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file 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 336b0dbfc3561fdf79595a75894079899c6f2b08..e1185088f9651ab38a12105a0e9caad50eb5393e 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 @@ -30,19 +30,6 @@ ohos_fuzztest("ObjectServiceStubFuzzTest") { "${data_service_path}/service/crypto/include", "${data_service_path}/service/object/include", "${data_service_path}/service/matrix/include", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_distributeddb_path}", - "${kv_store_distributeddb_path}/include/", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/interfaces/include/relational", - "${dataobject_path}/frameworks/innerkitsimpl/include", - "${dataobject_path}/frameworks/innerkitsimpl/include/common", - "${dataobject_path}/interfaces/innerkits", - "//third_party/json/single_include", - "${relational_store_path}/interfaces/inner_api/common_type/include", "${data_service_path}/adapter/include/communicator", "${data_service_path}/adapter/include/utils", ] @@ -63,17 +50,19 @@ 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_access_check_config.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/datashare_config.cpp", + "${data_service_path}/service/config/src/model/device_sync_app_white_list_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/config/src/model/thread_config.cpp", - "${data_service_path}/service/crypto/src/crypto_manager.cpp", "${data_service_path}/service/object/src/object_asset_loader.cpp", "${data_service_path}/service/object/src/object_asset_machine.cpp", "${data_service_path}/service/object/src/object_callback_proxy.cpp", @@ -92,7 +81,6 @@ ohos_fuzztest("ObjectServiceStubFuzzTest") { "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "${kv_store_distributeddb_path}:distributeddb", ] external_deps = [ @@ -103,6 +91,7 @@ ohos_fuzztest("ObjectServiceStubFuzzTest") { "access_token:libaccesstoken_sdk", "access_token:libtokenid_sdk", "c_utils:utils", + "data_object:data_object_inner", "data_object:distributeddataobject_impl", "device_auth:deviceauth_sdk", "device_manager:devicemanagersdk", @@ -116,6 +105,7 @@ ohos_fuzztest("ObjectServiceStubFuzzTest") { "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", + "kv_store:distributeddb", ] } diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/objectservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/objectservicestub_fuzzer.cpp index 24ce52ba6dd952eee47559763a72e6be1335f036..5a11e1f31b5863b55dbaaa15b2b4d5859b762da5 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/objectservicestub_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/objectservicestub_fuzzer.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "objectservicestub_fuzzer.h" #include @@ -32,17 +34,18 @@ constexpr uint32_t CODE_MAX = static_cast(ObjectCode::OBJECTSTORE_SERV constexpr size_t NUM_MIN = 5; constexpr size_t NUM_MAX = 12; -bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { std::shared_ptr objectServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); objectServiceImpl->OnBind( { "ObjectServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + uint32_t code = provider.ConsumeIntegralInRange(CODE_MIN, CODE_MAX); + std::vector remainingData = provider.ConsumeRemainingBytes(); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); - request.WriteBuffer(data, size); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); request.RewindRead(0); MessageParcel reply; std::shared_ptr objectServiceStub = objectServiceImpl; @@ -54,11 +57,7 @@ bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::OnRemoteRequestFuzz(data, size); - + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/BUILD.gn index 984eddf37dd2aad45543a029a8ed40df530a584d..90e0d2f23426e8779d06577a872acbb8365c4773 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/BUILD.gn @@ -25,18 +25,6 @@ ohos_fuzztest("RdbResultSetStubFuzzTest") { "${data_service_path}/framework/include", "${data_service_path}/service/rdb", "${data_service_path}/service/common", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_distributeddb_path}", - "${kv_store_distributeddb_path}/include/", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/interfaces/include/relational", - "${relational_store_path}/interfaces/inner_api/cloud_data/include", - "${relational_store_path}/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", - "//third_party/json/single_include", ] fuzz_config_file = @@ -60,8 +48,6 @@ ohos_fuzztest("RdbResultSetStubFuzzTest") { "${data_service_path}/adapter/account:distributeddata_account", "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", - "${kv_store_distributeddb_path}:distributeddb", - "${relational_store_inner_api_path}:native_rdb_static", ] external_deps = [ @@ -80,6 +66,7 @@ ohos_fuzztest("RdbResultSetStubFuzzTest") { "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", + "kv_store:distributeddb", "relational_store:native_rdb", ] } diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/rdbresultsetstub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/rdbresultsetstub_fuzzer.cpp index 9f10a09f56a02b58b1632964830086c41f89a9dc..0f322d63754b8fa944bc77a94549e336d3e97c45 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/rdbresultsetstub_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/rdbresultsetstub_fuzzer.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "rdbresultsetstub_fuzzer.h" #include @@ -28,16 +30,17 @@ using namespace OHOS::DistributedRdb; namespace OHOS { +using Code = NativeRdb::RemoteResultSet::Code; const std::u16string INTERFACE_TOKEN = u"OHOS::NativeRdb.IResultSet"; -constexpr uint32_t CODE_MIN = 0; -constexpr uint32_t CODE_MAX = NativeRdb::RemoteResultSet::Code::CMD_MAX + 1; -bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { - uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + const int min = 0; + uint32_t code = provider.ConsumeIntegralInRange(min, Code::CMD_MAX); + std::vector remainingData = provider.ConsumeRemainingBytes(); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); - request.WriteBuffer(data, size); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); request.RewindRead(0); MessageParcel reply; MessageOption option; @@ -52,11 +55,7 @@ bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::OnRemoteRequestFuzz(data, size); - + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); return 0; } \ No newline at end of file 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 e51d78511f3f6e31e68cc9494dc0133b8bcf9d50..23fe264db5717c5da8cd8248cfbc63e2eb131c03 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 @@ -35,19 +35,6 @@ ohos_fuzztest("RdbServiceStubFuzzTest") { "${data_service_path}/service/object", "${data_service_path}/service/permission/include", "${data_service_path}/service/rdb", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_distributeddb_path}", - "${kv_store_distributeddb_path}/include/", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/interfaces/include/relational", - "${dataobject_path}/frameworks/innerkitsimpl/include", - "${relational_store_path}/interfaces/inner_api/cloud_data/include", - "${relational_store_path}/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", - "//third_party/json/single_include", "${data_service_path}/adapter/include/communicator", ] @@ -64,46 +51,19 @@ ohos_fuzztest("RdbServiceStubFuzzTest") { sources = [ "${data_service_path}/app/src/checker/bundle_checker.cpp", "${data_service_path}/app/src/checker/system_checker.cpp", - "${data_service_path}/service/backup/src/backup_manager.cpp", - "${data_service_path}/service/bootstrap/src/bootstrap.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/config/src/model/thread_config.cpp", - "${data_service_path}/service/crypto/src/crypto_manager.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_cursor.cpp", - "${data_service_path}/service/rdb/rdb_general_store.cpp", - "${data_service_path}/service/rdb/rdb_hiview_adapter.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_schema_config.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", "rdbservicestub_fuzzer.cpp", ] deps = [ "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/adapter/dfx:distributeddata_dfx", "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "${kv_store_distributeddb_path}:distributeddb", - "${relational_store_inner_api_path}:native_rdb_static", + "${data_service_path}/service/bootstrap:distributeddata_bootstrap", + "${data_service_path}/service/cloud:distributeddata_cloud", + "${data_service_path}/service/common:distributeddata_common", + "${data_service_path}/service/rdb:distributeddata_rdb", ] external_deps = [ @@ -120,11 +80,11 @@ ohos_fuzztest("RdbServiceStubFuzzTest") { "device_manager:devicemanagersdk", "hicollie:libhicollie", "hilog:libhilog", - "hisysevent:libhisysevent", "huks:libhukssdk", "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", + "kv_store:distributeddb", "relational_store:native_rdb", "resource_management:global_resmgr", "samgr:samgr_proxy", diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/rdbservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/rdbservicestub_fuzzer.cpp index a9ef6e03d54f52e11cc42b2dc16ba8dd4b1795bc..4f126d96e04cfcdc3bcddea829dedb17fa7e5077 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/rdbservicestub_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/rdbservicestub_fuzzer.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "rdbservicestub_fuzzer.h" #include @@ -32,17 +34,18 @@ constexpr uint32_t CODE_MAX = static_cast(RdbServiceCode::RDB_SERVICE_ constexpr size_t NUM_MIN = 5; constexpr size_t NUM_MAX = 12; -bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { std::shared_ptr rdbServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); rdbServiceImpl->OnBind( { "RdbServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + uint32_t code = provider.ConsumeIntegralInRange(CODE_MIN, CODE_MAX); + std::vector remainingData = provider.ConsumeRemainingBytes(); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); - request.WriteBuffer(data, size); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); request.RewindRead(0); MessageParcel reply; std::shared_ptr rdbServiceStub = rdbServiceImpl; @@ -54,11 +57,7 @@ bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::OnRemoteRequestFuzz(data, size); - + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..1be915e1eeb8cb45f524c5c23150e5c0921aeb27 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright (c) 2025 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("SyncStrategiesFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + include_dirs = [ + "${data_service_path}/framework/include", + "${data_service_path}/service/cloud", + "${data_service_path}/service/common", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/syncstrategies_fuzzer" + + sources = [ "syncstrategies_fuzzer.cpp" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", + ] + + deps = [ + "${data_service_path}/adapter/dfx:distributeddata_dfx", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service/cloud:distributeddata_cloud", + "${data_service_path}/service/common:distributeddata_common", + "${data_service_path}/service/bootstrap:distributeddata_bootstrap", + "${data_service_path}/service/permission:distributeddata_permit", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", + "access_token:libtokenid_sdk", + "c_utils:utils", + "hilog:libhilog", + "json:nlohmann_json_static", + "kv_store:datamgr_common", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":SyncStrategiesFuzzTest" ] +} +############################################################################### \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..7ade8a0faafeaedba7241e7d4a97b8e1f9691932 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a37a23b1533f07ab59744732b0f46b2b5fd958d8 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/syncstrategies_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/syncstrategies_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2cf4591d3c4c8b83f6508c7d232574e4631d37e3 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/syncstrategies_fuzzer.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2025 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 "syncstrategies_fuzzer.h" +#include "sync_strategies/network_sync_strategy.h" + +using namespace OHOS::DistributedData; +using namespace OHOS::CloudData; + +namespace OHOS { +void SyncStrategiesFuzz001(FuzzedDataProvider &provider) +{ + int32_t user = provider.ConsumeIntegral(); + std::string bundleName = provider.ConsumeRandomLengthString(100); + NetworkSyncStrategy strategy; + StoreInfo storeInfo; + storeInfo.user = user; + storeInfo.bundleName = bundleName; + strategy.CheckSyncAction(storeInfo); +} + +void SyncStrategiesFuzz002(FuzzedDataProvider &provider) +{ + uint32_t strategy = provider.ConsumeIntegral(); + NetworkSyncStrategy strategyInstance; + strategyInstance.Check(strategy); +} + +void SyncStrategiesFuzz003(FuzzedDataProvider &provider) +{ + int32_t user = provider.ConsumeIntegral(); + std::string bundleName = provider.ConsumeRandomLengthString(100); + NetworkSyncStrategy strategyInstance; + strategyInstance.GetStrategy(user, bundleName); + strategyInstance.GetKey(user); + + NetworkSyncStrategy::StrategyInfo info; + info.user = 1; + info.bundleName = "StrategyInfo"; + Serializable::json node; + std::string key = provider.ConsumeRandomLengthString(100); + std::string valueStr = provider.ConsumeRandomLengthString(100); + int valueInt = provider.ConsumeIntegral(); + float valueFloat = provider.ConsumeFloatingPoint(); + bool valueBool = provider.ConsumeBool(); + int valueRange = provider.ConsumeIntegralInRange(0, 100); + node[key] = valueStr; + node["integer"] = valueInt; + node["float"] = valueFloat; + node["boolean"] = valueBool; + node["range"] = valueRange; + info.Marshal(node); + info.Unmarshal(node); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::SyncStrategiesFuzz001(provider); + OHOS::SyncStrategiesFuzz002(provider); + OHOS::SyncStrategiesFuzz003(provider); + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/syncstrategies_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/syncstrategies_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..ab2199aa1ca48a9cbd7cdd3bee0ac0319b239049 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/syncstrategies_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 SYNCSTRATEGIES_FUZZER_H +#define SYNCSTRATEGIES_FUZZER_H + +#define FUZZ_PROJECT_NAME "syncstrategies_fuzzer" + +#endif // SYNCSTRATEGIES_FUZZER_H \ No newline at end of file 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 27778e7e3510bfea62c572d1da3c0866496de80b..398162fcc317b76037c3d3ce7bb6fe90e603c982 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 @@ -20,16 +20,13 @@ ohos_fuzztest("UdmfServiceFuzzTest") { module_out_path = "datamgr_service/datamgr_service" include_dirs = [ - "${udmf_path}/framework/common", - "${udmf_path}/interfaces/innerkits/common", - "${udmf_path}/interfaces/innerkits/data", "${data_service_path}/framework/include", + "${data_service_path}/service/matrix/include", "${data_service_path}/service/udmf/lifecycle", "${data_service_path}/service/udmf/permission", "${data_service_path}/service/udmf/preprocess", "${data_service_path}/service/udmf/store", "${data_service_path}/service/udmf", - "${kv_store_path}/frameworks/common", ] fuzz_config_file = @@ -40,6 +37,7 @@ ohos_fuzztest("UdmfServiceFuzzTest") { "-O0", "-Wno-unused-variable", "-fno-omit-frame-pointer", + "-fno-access-control" ] sources = [ "udmfservice_fuzzer.cpp" ] @@ -47,8 +45,10 @@ ohos_fuzztest("UdmfServiceFuzzTest") { deps = [ "${data_service_path}/adapter/account:distributeddata_account", "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/adapter/dfx:distributeddata_dfx", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/bootstrap:distributeddata_bootstrap", + "${data_service_path}/service/matrix:distributeddata_matrix", "${data_service_path}/service/udmf:udmf_server", ] @@ -77,4 +77,4 @@ group("fuzztest") { deps = [ ":UdmfServiceFuzzTest" ] } -############################################################################### +############################################################################### \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/udmfservice_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/udmfservice_fuzzer.cpp index 1d5b03a1a8b5c1c90e57bf50c60a286fb3d877a4..59d2290c20b9e58d12e563ed55a2f3d345df4247 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/udmfservice_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/udmfservice_fuzzer.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "udmfservice_fuzzer.h" #include "accesstoken_kit.h" @@ -35,53 +37,58 @@ constexpr size_t NUM_MIN = 5; constexpr size_t NUM_MAX = 12; static constexpr int ID_LEN = 32; static constexpr int MINIMUM = 48; +static constexpr int MAXIMUM = 121; -QueryOption GenerateFuzzQueryOption(const uint8_t* data, size_t size) +QueryOption GenerateFuzzQueryOption(FuzzedDataProvider &provider) { std::vector groupId(ID_LEN, '0'); - size_t length = groupId.size() > size ? size : groupId.size(); - for (size_t i = 0; i < length; ++i) { - groupId[i] = data[i] % MINIMUM + MINIMUM; + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); } std::string groupIdStr(groupId.begin(), groupId.end()); UnifiedKey udKey = UnifiedKey("drag", "com.test.demo", groupIdStr); - QueryOption query = { - .key = udKey.GetUnifiedKey(), - .intention = Intention::UD_INTENTION_DRAG - }; + QueryOption query; + query.key = udKey.GetUnifiedKey(); + query.intention = Intention::UD_INTENTION_DRAG; + query.tokenId = provider.ConsumeIntegral(); return query; } -bool OnRemoteRequestFuzz(const uint8_t* data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + uint32_t code = provider.ConsumeIntegralInRange(CODE_MIN, CODE_MAX); + std::vector remainingData = provider.ConsumeRemainingBytes(); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); - request.WriteBuffer(data, size); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); request.RewindRead(0); MessageParcel reply; udmfServiceImpl->OnRemoteRequest(code, request, reply); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; return true; } -void SetDataFuzz(const uint8_t *data, size_t size) +void SetDataFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; - std::string svalue(data, data + size); + + std::string svalue = provider.ConsumeRandomLengthString(); UnifiedData data1; std::shared_ptr obj = std::make_shared(); obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; obj->value_[FILE_URI_PARAM] = svalue; - obj->value_[FILE_TYPE] = "abcdefg"; + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); auto record = std::make_shared(FILE_URI, obj); data1.AddRecord(record); MessageParcel request; @@ -89,49 +96,58 @@ void SetDataFuzz(const uint8_t *data, size_t size) ITypesUtil::Marshal(request, option1, data1); MessageParcel reply; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::SET_DATA), request, reply); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void GetDataFuzz(const uint8_t *data, size_t size) +void GetDataFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - QueryOption query = GenerateFuzzQueryOption(data, size); + QueryOption query = GenerateFuzzQueryOption(provider); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); ITypesUtil::Marshal(request, query); MessageParcel reply; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::GET_DATA), request, reply); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void GetBatchDataFuzz(const uint8_t *data, size_t size) +void GetBatchDataFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - QueryOption query = GenerateFuzzQueryOption(data, size); + QueryOption query = GenerateFuzzQueryOption(provider); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); ITypesUtil::Marshal(request, query); MessageParcel reply; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::GET_BATCH_DATA), request, reply); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void UpdateDataFuzz(const uint8_t *data, size_t size) +void UpdateDataFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - QueryOption query = GenerateFuzzQueryOption(data, size); - std::string svalue(data, data + size); + QueryOption query = GenerateFuzzQueryOption(provider); + std::string svalue = provider.ConsumeRandomLengthString(); UnifiedData data1; std::shared_ptr obj = std::make_shared(); obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; obj->value_[FILE_URI_PARAM] = svalue; - obj->value_[FILE_TYPE] = "abcdefg"; + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); auto record = std::make_shared(FILE_URI, obj); data1.AddRecord(record); MessageParcel request; @@ -139,49 +155,57 @@ void UpdateDataFuzz(const uint8_t *data, size_t size) ITypesUtil::Marshal(request, query, data1); MessageParcel reply; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::UPDATE_DATA), request, reply); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void DeleteDataFuzz(const uint8_t *data, size_t size) +void DeleteDataFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - QueryOption query = GenerateFuzzQueryOption(data, size); + QueryOption query = GenerateFuzzQueryOption(provider); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); ITypesUtil::Marshal(request, query); MessageParcel reply; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::DELETE_DATA), request, reply); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void GetSummaryFuzz(const uint8_t *data, size_t size) +void GetSummaryFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - QueryOption query = GenerateFuzzQueryOption(data, size); + QueryOption query = GenerateFuzzQueryOption(provider); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); ITypesUtil::Marshal(request, query); MessageParcel reply; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::GET_SUMMARY), request, reply); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void AddPrivilegeDataFuzz(const uint8_t *data, size_t size) +void AddPrivilegeDataFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - QueryOption query = GenerateFuzzQueryOption(data, size); + QueryOption query = GenerateFuzzQueryOption(provider); - Privilege privilege = { - .tokenId = 1, - .readPermission = "read", - .writePermission = "write" - }; + Privilege privilege; + privilege.tokenId = 1; + privilege.readPermission = "read"; + privilege.writePermission = "write"; MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); @@ -189,15 +213,18 @@ void AddPrivilegeDataFuzz(const uint8_t *data, size_t size) MessageParcel replyUpdate; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::ADD_PRIVILEGE), request, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void SyncDataFuzz(const uint8_t *data, size_t size) +void SyncDataFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - QueryOption query = GenerateFuzzQueryOption(data, size); + QueryOption query = GenerateFuzzQueryOption(provider); std::vector devices = { "11", "22" }; MessageParcel requestUpdate; requestUpdate.WriteInterfaceToken(INTERFACE_TOKEN); @@ -205,56 +232,62 @@ void SyncDataFuzz(const uint8_t *data, size_t size) MessageParcel replyUpdate; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::SYNC), requestUpdate, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void IsRemoteDataFuzz(const uint8_t *data, size_t size) +void IsRemoteDataFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - QueryOption query = GenerateFuzzQueryOption(data, size); + QueryOption query = GenerateFuzzQueryOption(provider); MessageParcel requestUpdate; requestUpdate.WriteInterfaceToken(INTERFACE_TOKEN); ITypesUtil::Marshal(requestUpdate, query); MessageParcel replyUpdate; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::IS_REMOTE_DATA), requestUpdate, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void ObtainAsynProcessFuzz(const uint8_t *data, size_t size) +void ObtainAsynProcessFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); std::vector groupId(ID_LEN, '0'); - size_t length = groupId.size() > size ? size : groupId.size(); - for (size_t i = 0; i < length; ++i) { - groupId[i] = data[i] % MINIMUM + MINIMUM; + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MINIMUM); } std::string businessUdKey(groupId.begin(), groupId.end()); - AsyncProcessInfo processInfo = { - .businessUdKey = businessUdKey, - }; + AsyncProcessInfo processInfo; + processInfo.businessUdKey = businessUdKey; MessageParcel requestUpdate; requestUpdate.WriteInterfaceToken(INTERFACE_TOKEN); ITypesUtil::Marshal(requestUpdate, processInfo); MessageParcel replyUpdate; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::OBTAIN_ASYN_PROCESS), requestUpdate, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void ClearAsynProcessFuzz(const uint8_t *data, size_t size) +void ClearAsynProcessFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); std::vector groupId(ID_LEN, '0'); - size_t length = groupId.size() > size ? size : groupId.size(); - for (size_t i = 0; i < length; ++i) { - groupId[i] = data[i] % MINIMUM + MINIMUM; + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MINIMUM); } std::string businessUdKey(groupId.begin(), groupId.end()); MessageParcel requestUpdate; @@ -263,6 +296,558 @@ void ClearAsynProcessFuzz(const uint8_t *data, size_t size) MessageParcel replyUpdate; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::CLEAR_ASYN_PROCESS_BY_KEY), requestUpdate, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; +} + +void SetDelayInfoFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + MessageParcel requestUpdate; + requestUpdate.WriteInterfaceToken(INTERFACE_TOKEN); + DataLoadInfo dataLoadInfo; + dataLoadInfo.recordCount = provider.ConsumeIntegral(); + dataLoadInfo.types.emplace(provider.ConsumeRandomLengthString()); + dataLoadInfo.sequenceKey = provider.ConsumeRandomLengthString(); + ITypesUtil::Marshal(requestUpdate, dataLoadInfo); + sptr iUdmfNotifier = nullptr; + ITypesUtil::Marshal(requestUpdate, iUdmfNotifier); + MessageParcel replyUpdate; + udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::SET_DELAY_INFO), + requestUpdate, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; +} + +void PushDelayDataFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + + MessageParcel requestUpdate; + requestUpdate.WriteInterfaceToken(INTERFACE_TOKEN); + std::string key = provider.ConsumeRandomLengthString(); + ITypesUtil::Marshal(requestUpdate, key); + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + data.AddRecord(record); + ITypesUtil::Marshal(requestUpdate, data); + + MessageParcel replyUpdate; + udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::SET_DELAY_DATA), + requestUpdate, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; +} + +void GetDataIfAvailableFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + + MessageParcel requestUpdate; + requestUpdate.WriteInterfaceToken(INTERFACE_TOKEN); + std::string key = provider.ConsumeRandomLengthString(); + ITypesUtil::Marshal(requestUpdate, key); + DataLoadInfo dataLoadInfo; + dataLoadInfo.recordCount = provider.ConsumeIntegral(); + dataLoadInfo.types.emplace(provider.ConsumeRandomLengthString()); + dataLoadInfo.sequenceKey = provider.ConsumeRandomLengthString(); + ITypesUtil::Marshal(requestUpdate, dataLoadInfo); + sptr iUdmfNotifier = nullptr; + ITypesUtil::Marshal(requestUpdate, iUdmfNotifier); + + MessageParcel replyUpdate; + udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::GET_DELAY_DATA), + requestUpdate, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; +} + +void OnGetAppShareOptionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + + MessageParcel requestUpdate; + requestUpdate.WriteInterfaceToken(INTERFACE_TOKEN); + CustomOption option = {.intention = Intention::UD_INTENTION_DRAG}; + std::string intention = UD_INTENTION_MAP.at(option.intention); + ITypesUtil::Marshal(requestUpdate, intention); + + MessageParcel replyUpdate; + udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::GET_APP_SHARE_OPTION), + requestUpdate, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; +} + +void CheckDragParamsFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string intention = provider.ConsumeRandomLengthString(); + std::string bundleName = provider.ConsumeRandomLengthString(); + std::vector groupId(ID_LEN, '0'); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey udKey(intention, bundleName, groupIdStr); + QueryOption query; + udmfServiceImpl->CheckDragParams(udKey, query); +} + +void IsPermissionInCacheFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + QueryOption query = GenerateFuzzQueryOption(provider); + udmfServiceImpl->IsPermissionInCache(query); +} + +void IsReadAndKeepFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + Privilege privilege; + privilege.tokenId = provider.ConsumeIntegral(); + privilege.readPermission = "read"; + privilege.writePermission = "write"; + Privilege privilege2; + privilege2.tokenId = provider.ConsumeIntegral(); + privilege2.readPermission = "readAndKeep"; + privilege2.writePermission = "write"; + std::vector privileges = { privilege, privilege2 }; + QueryOption query = GenerateFuzzQueryOption(provider); + udmfServiceImpl->IsReadAndKeep(privileges, query); +} + +void ProcessUriFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + QueryOption query = GenerateFuzzQueryOption(provider); + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + data.AddRecord(record); + udmfServiceImpl->ProcessUri(query, data); +} + +void ProcessCrossDeviceDataFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + uint32_t tokenId = provider.ConsumeIntegral(); + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + data.AddRecord(record); + std::vector uris; + udmfServiceImpl->ProcessCrossDeviceData(tokenId, data, uris); +} + +void ResolveAutoLaunchFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + auto identifier = provider.ConsumeRandomLengthString(); + UdmfServiceImpl::DBLaunchParam param; + param.userId = provider.ConsumeRandomLengthString(); + param.appId = provider.ConsumeRandomLengthString(); + param.storeId = provider.ConsumeRandomLengthString(); + param.path = provider.ConsumeRandomLengthString(); + udmfServiceImpl->ResolveAutoLaunch(identifier, param); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; +} + +void HasDatahubPriviledgeFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + auto bundleName = provider.ConsumeRandomLengthString(); + udmfServiceImpl->HasDatahubPriviledge(bundleName); +} + +void OnUserChangeFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + uint32_t code = provider.ConsumeIntegral(); + auto user = provider.ConsumeRandomLengthString(); + auto account = provider.ConsumeRandomLengthString(); + udmfServiceImpl->OnUserChange(code, user, account); +} + +void IsNeedTransferDeviceTypeFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + QueryOption query = GenerateFuzzQueryOption(provider); + udmfServiceImpl->IsNeedTransferDeviceType(query); +} + +void CheckAddPrivilegePermissionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string intention = provider.ConsumeRandomLengthString(); + std::string bundleName = provider.ConsumeRandomLengthString(); + std::vector groupId(ID_LEN, '0'); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey udKey(intention, bundleName, groupIdStr); + std::string processName = provider.ConsumeRandomLengthString(); + QueryOption query = GenerateFuzzQueryOption(provider); + udmfServiceImpl->CheckAddPrivilegePermission(udKey, processName, query); +} + +void ProcessDataFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + QueryOption query = GenerateFuzzQueryOption(provider); + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + data.AddRecord(record); + std::vector dataSet = { data }; + udmfServiceImpl->ProcessData(query, dataSet); +} + +void VerifyIntentionPermissionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + QueryOption query = GenerateFuzzQueryOption(provider); + UnifiedData data; + std::string intention = provider.ConsumeRandomLengthString(); + std::string bundleName = provider.ConsumeRandomLengthString(); + std::vector groupId(ID_LEN); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey udKey(intention, bundleName, groupIdStr); + CheckerManager::CheckInfo info; + info.tokenId = provider.ConsumeIntegral(); + udmfServiceImpl->VerifyIntentionPermission(query, data, udKey, info); + Runtime runtime; + data.SetRuntime(runtime); + udmfServiceImpl->VerifyIntentionPermission(query, data, udKey, info); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; +} + +void IsFileMangerIntentionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + auto intention = provider.ConsumeRandomLengthString(); + udmfServiceImpl->IsFileMangerIntention(intention); +} + +void CheckAppIdFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string intention = provider.ConsumeRandomLengthString(); + std::string bundleName = provider.ConsumeRandomLengthString(); + std::string appId = provider.ConsumeRandomLengthString(); + std::string groupId = provider.ConsumeRandomLengthString(); + uint32_t tokenid = provider.ConsumeIntegral(); + Privilege privilege; + privilege.tokenId = tokenid; + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + data.AddRecord(record); + UnifiedKey key(intention, bundleName, groupId); + std::shared_ptr runtime = std::make_shared(); + runtime->key = key; + runtime->privileges.emplace_back(privilege); + runtime->sourcePackage = bundleName; + runtime->createPackage = bundleName; + runtime->recordTotalNum = static_cast(data.GetRecords().size()); + runtime->tokenId = tokenid; + runtime->appId = appId; + udmfServiceImpl->CheckAppId(runtime, bundleName); +} + +void CheckDeleteDataPermissionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string bundleName = provider.ConsumeRandomLengthString(); + std::string appId = provider.ConsumeRandomLengthString(); + uint32_t tokenid = provider.ConsumeIntegral(); + Privilege privilege; + privilege.tokenId = tokenid; + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + data.AddRecord(record); + std::vector groupId(ID_LEN, '0'); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey udKey = UnifiedKey("drag", "com.test.demo", groupIdStr); + std::shared_ptr runtime = std::make_shared(); + runtime->key = udKey; + runtime->privileges.emplace_back(privilege); + runtime->sourcePackage = bundleName; + runtime->createPackage = bundleName; + runtime->recordTotalNum = static_cast(data.GetRecords().size()); + runtime->tokenId = tokenid; + runtime->appId = appId; + QueryOption query; + query.key = udKey.GetUnifiedKey(); + query.intention = Intention::UD_INTENTION_DRAG; + query.tokenId = provider.ConsumeIntegral(); + udmfServiceImpl->CheckDeleteDataPermission(appId, runtime, query); +} + +void StoreSyncFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::vector groupId(ID_LEN, '0'); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey key = UnifiedKey("drag", "com.test.demo", groupIdStr); + QueryOption query; + query.key = key.GetUnifiedKey(); + query.intention = Intention::UD_INTENTION_DRAG; + query.tokenId = provider.ConsumeIntegral(); + std::vector devices = { "11", "22" }; + udmfServiceImpl->StoreSync(key, query, devices); +} + +void SetAppShareOptionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string intention = provider.ConsumeRandomLengthString(); + int32_t shareOption = provider.ConsumeIntegral(); + udmfServiceImpl->SetAppShareOption(intention, shareOption); +} + +void RemoveAppShareOptionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string intention = provider.ConsumeRandomLengthString(); + udmfServiceImpl->RemoveAppShareOption(intention); +} + +void QueryDataCommonFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::vector groupId(ID_LEN, '0'); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey udKey = UnifiedKey("drag", "com.test.demo", groupIdStr); + QueryOption query; + query.key = udKey.GetUnifiedKey(); + query.intention = Intention::UD_INTENTION_DRAG; + query.tokenId = provider.ConsumeIntegral(); + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + data.AddRecord(record); + std::shared_ptr store; + std::vector dataSet = { data }; + udmfServiceImpl->QueryDataCommon(query, dataSet, store); +} + +void ClearAsynProcessByKeyFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string businessUdKey = provider.ConsumeRandomLengthString(); + udmfServiceImpl->ClearAsynProcessByKey(businessUdKey); +} + +void TransferToEntriesIfNeedFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::vector groupId(ID_LEN, '0'); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey udKey = UnifiedKey("drag", "com.test.demo", groupIdStr); + QueryOption query; + query.key = udKey.GetUnifiedKey(); + query.intention = Intention::UD_INTENTION_DRAG; + query.tokenId = provider.ConsumeIntegral(); + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + std::shared_ptr obj1 = std::make_shared(); + obj1->value_[UNIFORM_DATA_TYPE] = "general.image-uri"; + obj1->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj1->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + std::shared_ptr obj2 = std::make_shared(); + obj2->value_[UNIFORM_DATA_TYPE] = "general.txt-uri"; + obj2->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj2->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + std::shared_ptr obj3 = std::make_shared(); + obj3->value_[UNIFORM_DATA_TYPE] = "general.html-uri"; + obj3->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj3->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + auto record1 = std::make_shared(FILE_URI, obj1); + auto record2 = std::make_shared(FILE_URI, obj2); + auto record3 = std::make_shared(FILE_URI, obj3); + data.AddRecord(record); + data.AddRecord(record1); + data.AddRecord(record2); + data.AddRecord(record3); + udmfServiceImpl->TransferToEntriesIfNeed(query, data); +} + +void IsValidOptionsNonDragFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::vector groupId(ID_LEN, '0'); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey key = UnifiedKey("drag", "com.test.demo", groupIdStr); + CustomOption option = {.intention = Intention::UD_INTENTION_DRAG}; + std::string intention = UD_INTENTION_MAP.at(option.intention); + udmfServiceImpl->IsValidOptionsNonDrag(key, intention); +} + +void CloseStoreWhenCorruptedFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string intention = provider.ConsumeRandomLengthString(); + int32_t status = provider.ConsumeIntegral(); + udmfServiceImpl->CloseStoreWhenCorrupted(intention, status); +} + +void HandleDbErrorFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string intention = provider.ConsumeRandomLengthString(); + int32_t status = provider.ConsumeIntegral(); + udmfServiceImpl->HandleDbError(intention, status); +} + +void BuildMetaFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string storeId = provider.ConsumeRandomLengthString(); + int userId = provider.ConsumeIntegral(); + udmfServiceImpl->BuildMeta(storeId, userId); +} + +void ProcessResultFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::map results; + std::string key = provider.ConsumeRandomLengthString(); + int32_t value = provider.ConsumeIntegral(); + results.emplace(std::make_pair(key, value)); + udmfServiceImpl->ProcessResult(results); +} + +void RegisterAsyncProcessInfoFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string businessUdKey = provider.ConsumeRandomLengthString(); + udmfServiceImpl->RegisterAsyncProcessInfo(businessUdKey); +} + +void IsNeedMetaSyncFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + DistributedData::StoreMetaData meta; + uint8_t len = provider.ConsumeIntegral(); + std::vector uuids(len); + for (int i = 0; i < len; i++) { + std::string uuid = provider.ConsumeRandomLengthString(); + uuids[i] = uuid; + } + udmfServiceImpl->IsNeedMetaSync(meta, uuids); +} + +void VerifyDataAccessPermissionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::shared_ptr runtime = std::make_shared(); + std::vector groupId(ID_LEN, '0'); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey udKey = UnifiedKey("drag", "com.test.demo", groupIdStr); + QueryOption query; + query.key = udKey.GetUnifiedKey(); + query.intention = Intention::UD_INTENTION_DRAG; + query.tokenId = provider.ConsumeIntegral(); + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + data.AddRecord(record); + udmfServiceImpl->VerifyDataAccessPermission(runtime, query, data); +} + +void HandleDelayDataCallbackFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + DelayGetDataInfo delayGetDataInfo; + UnifiedData unifiedData; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + unifiedData.AddRecord(record); + std::string key = provider.ConsumeRandomLengthString(); + udmfServiceImpl->HandleDelayDataCallback(delayGetDataInfo, unifiedData, key); } } @@ -278,25 +863,56 @@ extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::OnRemoteRequestFuzz(data, size); - OHOS::SetDataFuzz(data, size); - OHOS::GetDataFuzz(data, size); + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); + OHOS::SetDataFuzz(provider); + OHOS::GetDataFuzz(provider); - OHOS::GetBatchDataFuzz(data, size); - OHOS::UpdateDataFuzz(data, size); - OHOS::DeleteDataFuzz(data, size); + OHOS::GetBatchDataFuzz(provider); + OHOS::UpdateDataFuzz(provider); + OHOS::DeleteDataFuzz(provider); - OHOS::GetSummaryFuzz(data, size); - OHOS::AddPrivilegeDataFuzz(data, size); - OHOS::SyncDataFuzz(data, size); + OHOS::GetSummaryFuzz(provider); + OHOS::AddPrivilegeDataFuzz(provider); + OHOS::SyncDataFuzz(provider); - OHOS::IsRemoteDataFuzz(data, size); - OHOS::ObtainAsynProcessFuzz(data, size); - OHOS::ClearAsynProcessFuzz(data, size); + OHOS::IsRemoteDataFuzz(provider); + OHOS::ObtainAsynProcessFuzz(provider); + OHOS::ClearAsynProcessFuzz(provider); + OHOS::SetDelayInfoFuzz(provider); + OHOS::PushDelayDataFuzz(provider); + OHOS::GetDataIfAvailableFuzz(provider); + OHOS::OnGetAppShareOptionFuzz(provider); + OHOS::CheckDragParamsFuzz(provider); + OHOS::IsPermissionInCacheFuzz(provider); + OHOS::IsReadAndKeepFuzz(provider); + OHOS::ProcessUriFuzz(provider); + OHOS::ProcessCrossDeviceDataFuzz(provider); + OHOS::ResolveAutoLaunchFuzz(provider); + OHOS::HasDatahubPriviledgeFuzz(provider); + OHOS::OnUserChangeFuzz(provider); + OHOS::IsNeedTransferDeviceTypeFuzz(provider); + OHOS::CheckAddPrivilegePermissionFuzz(provider); + OHOS::ProcessDataFuzz(provider); + OHOS::VerifyIntentionPermissionFuzz(provider); + OHOS::IsFileMangerIntentionFuzz(provider); + OHOS::CheckAppIdFuzz(provider); + OHOS::CheckDeleteDataPermissionFuzz(provider); + OHOS::StoreSyncFuzz(provider); + OHOS::SetAppShareOptionFuzz(provider); + OHOS::RemoveAppShareOptionFuzz(provider); + OHOS::QueryDataCommonFuzz(provider); + OHOS::ClearAsynProcessByKeyFuzz(provider); + OHOS::TransferToEntriesIfNeedFuzz(provider); + OHOS::IsValidOptionsNonDragFuzz(provider); + OHOS::CloseStoreWhenCorruptedFuzz(provider); + OHOS::HandleDbErrorFuzz(provider); + OHOS::BuildMetaFuzz(provider); + OHOS::ProcessResultFuzz(provider); + OHOS::RegisterAsyncProcessInfoFuzz(provider); + OHOS::IsNeedMetaSyncFuzz(provider); + OHOS::VerifyDataAccessPermissionFuzz(provider); + OHOS::HandleDelayDataCallbackFuzz(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/kv_dalegate_test.cpp b/datamgr_service/services/distributeddataservice/service/test/kv_dalegate_test.cpp index 26bba5c02f7748f3ebd2a9c61d74bb2ca87ea4a9..a7b758fe6c8a55bbde4738fedc5d3f68fbe329f9 100644 --- a/datamgr_service/services/distributeddataservice/service/test/kv_dalegate_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/kv_dalegate_test.cpp @@ -16,19 +16,24 @@ #include #include +#include +#include +#include #include "data_share_profile_config.h" +#include "db_delegate.h" #include "executor_pool.h" -#include "grd_error.h" +#include "grd_base/grd_error.h" #include "kv_delegate.h" #include "log_print.h" +#include "proxy_data_manager.h" +#include "parameters.h" namespace OHOS::Test { using namespace testing::ext; using namespace OHOS::DataShare; class KvDelegateTest : public testing::Test { public: - static constexpr int64_t USER_TEST = 100; - static void SetUpTestCase(void){}; + static void SetUpTestCase(void); static void TearDownTestCase(void){}; void SetUp(){}; void TearDown(){}; @@ -42,6 +47,49 @@ const char* g_backupFiles[] = { }; const char* BACKUP_SUFFIX = ".backup"; std::shared_ptr executors = std::make_shared(5, 3); +bool g_isRK3568 = false; + +void KvDelegateTest::SetUpTestCase(void) +{ + static std::once_flag flag; + static std::string product; + const std::string invalidProduct { "default" }; + std::call_once(flag, []() { + product = OHOS::system::GetParameter("const.build.product", ""); + }); + if (product == invalidProduct) { + std::cout << "This test is not for " << invalidProduct << ", skip it." << std::endl; + g_isRK3568 = true; + return; + } +} + +bool FileComparison(const std::string& file1, const std::string& file2) +{ + std::ifstream f1(file1, std::ios::binary); + std::ifstream f2(file2, std::ios::binary); + + if (!f1.is_open() || !f2.is_open()) { + ZLOGI("fail to open files!"); + return false; // fail to open files + } + + // compare file size + f1.seekg(0, std::ios::end); + f2.seekg(0, std::ios::end); + if (f1.tellg() != f2.tellg()) { + ZLOGI("File size is different!"); + return false; + } + f1.seekg(0); + f2.seekg(0); + + return std::equal( + std::istreambuf_iterator(f1), + std::istreambuf_iterator(), + std::istreambuf_iterator(f2) + ); +} /** * @tc.name: RestoreIfNeedt001 @@ -112,4 +160,411 @@ HWTEST_F(KvDelegateTest, GetVersion001, TestSize.Level1) EXPECT_EQ(result, false); ZLOGI("KvDelegateTest GetVersion001 end"); } + +/** +* @tc.name: Upsert001 +* @tc.desc: test Upsert function when GDR_DBOpen failed +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a kvDelegate object and kvDelegate.isInitDone_= false + 2.call Upsert function to upsert filter +* @tc.experct: Upsert failed and return E_ERROR +*/ +HWTEST_F(KvDelegateTest, Upsert001, TestSize.Level1) +{ + ZLOGI("KvDelegateTest Upsert001 start"); + std::string path = "path/to/your/db"; + KvDelegate kvDelegate(path, executors); + std::string collectionName = "test"; + std::string filter = "filter"; + std::string value = "value"; + auto result = kvDelegate.Upsert(collectionName, filter, value); + EXPECT_EQ(result.first, E_ERROR); + ZLOGI("KvDelegateTest Upsert001 end"); +} + +/** +* @tc.name: Delete001 +* @tc.desc: test Delete function when GDR_DBOpen failed +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a kvDelegate object and kvDelegate.isInitDone_= false + 2.call Delete function to Delete filter +* @tc.experct: Delete failed and return E_ERROR +*/ +HWTEST_F(KvDelegateTest, Delete001, TestSize.Level1) +{ + ZLOGI("KvDelegateTest Delete001 start"); + std::string path = "path/to/your/db"; + KvDelegate kvDelegate(path, executors); + std::string collectionName = "test"; + std::string filter = "filter"; + auto result = kvDelegate.Delete(collectionName, filter); + EXPECT_EQ(result.first, E_ERROR); + ZLOGI("KvDelegateTest Delete001 end"); +} + +/** +* @tc.name: Init001 +* @tc.desc: test Init function when isInitDone_ = true +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a kvDelegate object and kvDelegate.isInitDone_= true + 2.call Init function +* @tc.experct: Init failed and return true +*/ +HWTEST_F(KvDelegateTest, Init001, TestSize.Level1) +{ + ZLOGI("KvDelegateTest Init001 start"); + std::string path = "path/to/your/db"; + KvDelegate kvDelegate(path, executors); + kvDelegate.isInitDone_ = true; + auto result = kvDelegate.Init(); + EXPECT_TRUE(result); + ZLOGI("KvDelegateTest Init001 end"); +} + +/** +* @tc.name: Init002 +* @tc.desc: test Init function when isInitDone_ = false +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a kvDelegate object and kvDelegate.isInitDone_= false + 2.call Init function +* @tc.experct: Init failed and return false +*/ +HWTEST_F(KvDelegateTest, Init002, TestSize.Level1) +{ + ZLOGI("KvDelegateTest Init002 start"); + std::string path = "path/to/your/db"; + KvDelegate kvDelegate(path, executors); + auto result = kvDelegate.Init(); + EXPECT_FALSE(result); + ZLOGI("KvDelegateTest Init002 end"); +} + +/** +* @tc.name: Get001 +* @tc.desc: test Get function when GDR_DBOpen failed +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a kvDelegate object and kvDelegate.isInitDone_= false + 2.call Get function +* @tc.experct: Get failed and return E_ERROR +*/ +HWTEST_F(KvDelegateTest, Get001, TestSize.Level1) +{ + ZLOGI("Get001 start"); + std::string path = "path/to/your/db"; + KvDelegate kvDelegate(path, executors); + std::string collectionName = "test"; + std::string filter = "filter"; + std::string projection = "projection"; + std::string value = "value"; + std::string result = "result"; + auto result1 = kvDelegate.Get(collectionName, filter, projection, result); + EXPECT_EQ(result1, E_ERROR); + ZLOGI("Get001 end"); +} + +/** +* @tc.name: Backup001 +* @tc.desc: test Backup function when hasChange_ is true +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a kvDelegate object and kvDelegate.hasChange_ = true + 2.call Backup function +* @tc.experct: need backup and change kvDelegate.hasChange_ to false +*/ +HWTEST_F(KvDelegateTest, Backup001, TestSize.Level1) +{ + ZLOGI("Backup001 start"); + std::string path = "path/to/your/db"; + KvDelegate kvDelegate(path, executors); + kvDelegate.hasChange_ = true; + kvDelegate.Backup(); + EXPECT_FALSE(kvDelegate.hasChange_); + ZLOGI("Backup001 end"); +} + +/** +* @tc.name: Backup002 +* @tc.desc: test Backup function when hasChange_ is false +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a kvDelegate object and kvDelegate.hasChange_ = false + 2.call Backup function +* @tc.experct: no need to backup and kvDelegate.hasChange_ not change +*/ +HWTEST_F(KvDelegateTest, Backup002, TestSize.Level1) +{ + ZLOGI("Backup002 start"); + std::string path = "path/to/your/db"; + KvDelegate kvDelegate(path, executors); + kvDelegate.Backup(); + EXPECT_FALSE(kvDelegate.hasChange_); + ZLOGI("Backup002 end"); +} + +/** +* @tc.name: GetBatch001 +* @tc.desc: test GetBatch function when GDR_DBOpen failed +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a kvDelegate object and kvDelegate.isInitDone_= false + 2.call GetBach function +* @tc.experct: GetBach failed and return E_ERROR +*/ +HWTEST_F(KvDelegateTest, GetBatch001, TestSize.Level1) +{ + ZLOGI("GetBatch001 start"); + std::string path = "path/to/your/db"; + KvDelegate kvDelegate(path, executors); + std::string collectionName = "test"; + std::string filter = "filter"; + std::string projection = "projection"; + std::string value = "value"; + std::vector result; + auto result1 = kvDelegate.GetBatch(collectionName, filter, projection, result); + EXPECT_EQ(result1, E_ERROR); + ZLOGI("GetBatch001 end"); +} + +/** +* @tc.name: KVDelegateGetInstanceTest001 +* @tc.desc: Test KvDelegate::GetInstance() function when both delegate and executors are null. +* @tc.type: FUNC +* @tc.require:issueICNFIF +* @tc.precon: None +* @tc.step: + 1.Call KvDBDelegate::GetInstance() to initialize kvDBDelegate. +* @tc.experct: Init failed. delegate is nullptr. +*/ +HWTEST_F(KvDelegateTest, KVDelegateGetInstanceTest001, TestSize.Level0) { + ZLOGI("KVDelegateGetInstanceTest001 start"); + auto delegate = KvDBDelegate::GetInstance("/data/test", nullptr); + EXPECT_EQ(delegate, nullptr); + ZLOGI("KVDelegateGetInstanceTest001 end"); +} + +/** +* @tc.name: KVDelegateGetInstanceTest002 +* @tc.desc: Test KvDelegate::GetInstance() function when delegate is null and executors is not null. +* @tc.type: FUNC +* @tc.require:issueICNFIF +* @tc.precon: None +* @tc.step: + 1.Call KvDBDelegate::GetInstance() to initialize kvDBDelegate. + 2.Call KvDBDelegate::GetInstance() to get kvDelegate when delegate is already initialized. +* @tc.experct: Init failed. delegate is nullptr. +*/ +HWTEST_F(KvDelegateTest, KVDelegateGetInstanceTest002, TestSize.Level0) { + ZLOGI("KVDelegateGetInstanceTest002 start"); + auto executors = std::make_shared(2, 1); + auto delegate = KvDBDelegate::GetInstance("/data/test", executors); + EXPECT_NE(delegate, nullptr); + delegate = KvDBDelegate::GetInstance("/data/test", executors); + EXPECT_NE(delegate, nullptr); + ZLOGI("KVDelegateGetInstanceTest002 end"); +} + +/** +* @tc.name: KVDelegateGetInstanceTest003 +* @tc.desc: Test KvDelegate::GetInstance() function when delegate is not null and executors is null. +* @tc.type: FUNC +* @tc.require:issueICNFIF +* @tc.precon: None +* @tc.step: + 1.Call KvDBDelegate::GetInstance() to initialize kvDBDelegate. + 2.Call KvDBDelegate::GetInstance() with empty executors to get kvDelegate when delegate is already initialized +* @tc.experct: Init failed. delegate is nullptr. +*/ +HWTEST_F(KvDelegateTest, KVDelegateGetInstanceTest003, TestSize.Level0) { + ZLOGI("KVDelegateGetInstanceTest003 start"); + auto executors = std::make_shared(2, 1); + auto delegate = KvDBDelegate::GetInstance("/data/test", executors); + EXPECT_NE(delegate, nullptr); + delegate = KvDBDelegate::GetInstance("/data/test", nullptr); + EXPECT_NE(delegate, nullptr); + ZLOGI("KVDelegateGetInstanceTest003 end"); +} + +/** +* @tc.name: KVDelegateResetBackupTest001 +* @tc.desc: Test KvDelegate::Init() when does not satisfy reset schedule conditions. Insert two datasets with the + second time waitTime_ set to 3600s. First scheduled backup waitTime is 1s. absoluteWaitTime_ is set + to 0ms to make sure backup schedule will not be reset to wait another 3600, First scheduled backup should be + done and not reset, and second inserted data should be included in the backup process, thus the backup + database should remain same as the original database with two dataset. +* @tc.type: FUNC +* @tc.require:issueICNFIF +* @tc.precon: None +* @tc.step: + 1.Initilize a KvDelegate object. + 2.set waitTime_ to 1s. + 3.call Upsert() to insert a dataset. + 4.Call NotifyBackup() to set hasChange_ condition to true to allow backup. + 5.Keep scheduled backup from being reset by setting absoluteWaitTime_ to 0ms. + 6.Set waitTime_ to 3600s to make sure if backup schedule resets, it will be reset to 3600s. + 7.call Upsert() to insert another dataset. + 8.Call NotifyBackup() to set hasChange_ condition to true to allow backup. +* @tc.experct: backup file should be the same as original file. +*/ +HWTEST_F(KvDelegateTest, KVDelegateResetBackupTest001, TestSize.Level0) { + if (g_isRK3568) { + GTEST_SKIP(); + } + ZLOGI("KVDelegateResetBackupTest001 start"); + auto executors = std::make_shared(2, 1); + auto delegate = new KvDelegate("/data/test", executors); + delegate->waitTime_ = 2; // 1s + std::vector proxyDataList = {"name", "age", "job"}; + std::vector proxyDataList1 = {"test", "hellow", "world"}; + auto value = ProxyDataList(ProxyDataListNode(proxyDataList, 24, 12)); + auto value1 = ProxyDataList(ProxyDataListNode(proxyDataList1, 10, 24)); + auto result = delegate->Upsert("proxydata_", value); + delegate->NotifyBackup(); + EXPECT_EQ(result.first, 0); + + // Set absoluteWaitTime_ to 0ms to make sure backup schedule will not be reset to wait another 3600s. + delegate->absoluteWaitTime_ = 0; + delegate->waitTime_ = 3600; + auto result1 = delegate->Upsert("proxydata_", value1); + delegate->NotifyBackup(); + EXPECT_EQ(result1.first, 0); + // First scheduled backup waitTime is 1s. Margin of error is 1s. + sleep(2); + // Backup shoud be done because schdule did not reset. + for (auto &fileName : g_backupFiles) { + std::string src = delegate->path_ + "/" + fileName; + std::string dst = src; + dst.append(BACKUP_SUFFIX); + EXPECT_TRUE(FileComparison(src, dst)); + } + ZLOGI("KVDelegateResetBackupTest001 end"); +} + +/** +* @tc.name: KVDelegateRestoreTest001 +* @tc.desc: Test RestoreIfNeed() after backup is done +* @tc.type: FUNC +* @tc.require:issueICNFIF +* @tc.precon: None +* @tc.step: + 1.Creat a KvDelegate object with an initialized executorPool. + 2.Set waitTime_ to 2s. + 3.Call Upsert() to insert a dataset. + 4.Get the dataset just inserted. + 5.Call NotifyBackup() to set hasChange_ condition to true to allow backup. + 6.Call FileComparison() to compare original database with backup database. + 7.Delete original database and call RestoreIfNeed() with GRD_REBUILD_DATABASE as input param. +* @tc.experct: Successfully Get the dataset previously inserted. +*/ +HWTEST_F(KvDelegateTest, KVDelegateRestoreTest001, TestSize.Level1) { + if (g_isRK3568) { + GTEST_SKIP(); + } + ZLOGI("KVDelegateRestoreTest001 start"); + auto executors = std::make_shared(2, 1); + auto delegate = new KvDelegate("/data/test", executors); + delegate->waitTime_ = 1; + std::vector proxyDataList = {"name", "age", "job"}; + auto value = ProxyDataList(ProxyDataListNode(proxyDataList, 24, 12)); + auto result = delegate->Upsert("proxydata_", value); + delegate->NotifyBackup(); + EXPECT_EQ(result.first, 0); + Id id = Id(std::to_string(12), 24); + std::string queryResult = ""; + + auto result1 = delegate->Get("proxydata_", id, queryResult); + + EXPECT_EQ(result1, 0); + // Scheduled backup waitTime is 1s, 1s for margin of error. + sleep(2); + for (auto &fileName : g_backupFiles) { + std::string src = delegate->path_ + "/" + fileName; + std::string dst = src; + dst.append(BACKUP_SUFFIX); + EXPECT_TRUE(FileComparison(src, dst)); + } + + EXPECT_EQ(std::remove("/data/test/dataShare.db"), 0); + bool restoreRet = delegate->RestoreIfNeed(GRD_REBUILD_DATABASE); + EXPECT_TRUE(restoreRet); + + std::string queryRetAfterRestore = ""; + result1 = delegate->Get("proxydata_", id, queryRetAfterRestore); + EXPECT_EQ(result1, 0); + ZLOGI("KVDelegateRestoreTest001 end"); +} + +/** +* @tc.name: KVDelegateInitTest001 +* @tc.desc: Test KvDelegate::Init() function when executors_ are null. +* @tc.type: FUNC +* @tc.require:issueICNFIF +* @tc.precon: None +* @tc.step: + 1.Initilize a KvDelegate object. + 2.Set executors_ to nullptr. + 3.Call Init() function. + 4.Call Init() function again. +* @tc.experct: Database init success, db_ is not nullptr. +*/ +HWTEST_F(KvDelegateTest, KVDelegateInitTest001, TestSize.Level0) { + ZLOGI("KVDelegateInitTest001 start"); + auto executors = std::make_shared(2, 1); + auto delegate = new KvDelegate("/data/test", executors); + EXPECT_NE(delegate, nullptr); + delegate->executors_ = nullptr; + bool result = delegate->Init(); + EXPECT_TRUE(result); + EXPECT_NE(delegate->db_, nullptr); + EXPECT_TRUE(delegate->isInitDone_); + EXPECT_EQ(delegate->absoluteWaitTime_, 0); + bool result1 = delegate->Init(); + EXPECT_TRUE(result1); + EXPECT_TRUE(delegate->isInitDone_); + ZLOGI("KVDelegateInitTest001 end"); +} + +/** +* @tc.name: KVDelegateInitTest002 +* @tc.desc: Test KvDelegate::Init() function when executors_ is not null. +* @tc.type: FUNC +* @tc.require:issueICNFIF +* @tc.precon: None +* @tc.step: + 1.Initilize a KvDelegate object. + 2.call Init() function. +* @tc.experct: Init success. Schedule success, taskId is not invalid. +*/ +HWTEST_F(KvDelegateTest, KVDelegateInitTest002, TestSize.Level0) { + ZLOGI("KVDelegateInitTest002 start"); + auto executors = std::make_shared(2, 1); + auto delegate = new KvDelegate("/data/test", executors); + bool result = delegate->Init(); + EXPECT_TRUE(result); + EXPECT_NE(delegate->db_, nullptr); + EXPECT_TRUE(delegate->isInitDone_); + EXPECT_NE(delegate->absoluteWaitTime_, 0); + EXPECT_NE(delegate->taskId_, ExecutorPool::INVALID_TASK_ID); + ZLOGI("KVDelegateInitTest002 end"); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_abnormal_test.cpp b/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_abnormal_test.cpp index a6d46bbb9727ae8fa7f139d0c195cf2636c3b6c1..1e78eb6abb82c322e82ed94c385763910a20c86b 100644 --- a/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_abnormal_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_abnormal_test.cpp @@ -25,7 +25,7 @@ #include "cloud/asset_loader.h" #include "cloud/cloud_db.h" #include "cloud/schema_meta.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter_mock.h" #include "kv_store_nb_delegate_mock.h" #include "kvdb_query.h" @@ -127,16 +127,19 @@ HWTEST_F(KVDBGeneralStoreAbnormalTest, GetDBOptionTest001, TestSize.Level0) HWTEST_F(KVDBGeneralStoreAbnormalTest, SetEqualIdentifier, TestSize.Level0) { auto store = new (std::nothrow) KVDBGeneralStore(metaData_); - std::vector uuids{"uuidtest01"}; + std::vector uuids{ "uuidtest01" }; KvStoreNbDelegateMock mockDelegate; mockDelegate.taskCountMock_ = 1; store->delegate_ = &mockDelegate; EXPECT_NE(store->delegate_, nullptr); - EXPECT_CALL(*deviceManagerAdapterMock, ToUUID(testing::_)).WillOnce(testing::Return(uuids)); + EXPECT_CALL(*deviceManagerAdapterMock, ToUUID(testing::A>())) + .WillOnce(testing::Return(uuids)); auto uuids1 = DMAdapter::ToUUID(DMAdapter::GetInstance().GetRemoteDevices()); - EXPECT_CALL(*deviceManagerAdapterMock, ToUUID(testing::_)).WillOnce(testing::Return(uuids)); + EXPECT_CALL(*deviceManagerAdapterMock, ToUUID(testing::A>())) + .WillOnce(testing::Return(uuids)); EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType("uuidtest01")) - .WillOnce(testing::Return(false)).WillOnce(testing::Return(false)); + .WillOnce(testing::Return(false)) + .WillOnce(testing::Return(false)); store->SetEqualIdentifier(metaData_.appId, metaData_.storeId); EXPECT_EQ(uuids1, uuids); store->delegate_ = nullptr; 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 6da7e1d416e751d92b0ce2ee2ed87f452df334bc..3566bb00790b96cd89b6509dd990ffe276c6cc99 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 @@ -24,7 +24,7 @@ #include "cloud/asset_loader.h" #include "cloud/cloud_db.h" #include "cloud/schema_meta.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter.h" #include "kv_store_nb_delegate_mock.h" #include "kvdb_query.h" @@ -33,10 +33,12 @@ #include "metadata/secret_key_meta_data.h" #include "metadata/store_meta_data.h" #include "metadata/store_meta_data_local.h" +#include "mock/account_delegate_mock.h" #include "mock/db_store_mock.h" #include "mock/general_watcher_mock.h" using namespace testing::ext; +using namespace testing; using namespace DistributedDB; using namespace OHOS::DistributedData; using DBStoreMock = OHOS::DistributedData::DBStoreMock; @@ -49,6 +51,8 @@ using StoreId = OHOS::DistributedKv::StoreId; using AppId = OHOS::DistributedKv::AppId; namespace OHOS::Test { namespace DistributedDataTest { +static constexpr const char *INVALID_APPID = "invalid_kvdb_store_test"; + class KVDBGeneralStoreTest : public testing::Test { public: static void SetUpTestCase(void); @@ -56,30 +60,30 @@ public: void SetUp(); void TearDown(); protected: - static constexpr const char *bundleName = "test_distributeddata"; - static constexpr const char *storeName = "test_service_meta"; + static constexpr const char *BUNDLE_NAME = "test_distributeddata"; + static constexpr const char *STORE_NAME = "test_service_meta"; void InitMetaData(); static std::vector Random(uint32_t len); static std::shared_ptr dbStoreMock_; StoreMetaData metaData_; + static inline AccountDelegateMock *accountDelegateMock = nullptr; }; std::shared_ptr KVDBGeneralStoreTest::dbStoreMock_ = std::make_shared(); static const uint32_t KEY_LENGTH = 32; -static const uint32_t ENCRYPT_KEY_LENGTH = 48; void KVDBGeneralStoreTest::InitMetaData() { - metaData_.bundleName = bundleName; - metaData_.appId = bundleName; + metaData_.bundleName = BUNDLE_NAME; + metaData_.appId = BUNDLE_NAME; 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"; + metaData_.storeId = STORE_NAME; + metaData_.dataDir = "/data/service/el1/public/database/" + std::string(BUNDLE_NAME) + "/kvdb"; metaData_.securityLevel = SecurityLevel::S2; } @@ -94,9 +98,22 @@ std::vector KVDBGeneralStoreTest::Random(uint32_t len) return key; } -void KVDBGeneralStoreTest::SetUpTestCase(void) {} +void KVDBGeneralStoreTest::SetUpTestCase(void) +{ + accountDelegateMock = new (std::nothrow) AccountDelegateMock(); + if (accountDelegateMock != nullptr) { + AccountDelegate::instance_ = nullptr; + AccountDelegate::RegisterAccountInstance(accountDelegateMock); + } +} -void KVDBGeneralStoreTest::TearDownTestCase() {} +void KVDBGeneralStoreTest::TearDownTestCase() +{ + if (accountDelegateMock != nullptr) { + delete accountDelegateMock; + accountDelegateMock = nullptr; + } +} void KVDBGeneralStoreTest::SetUp() { @@ -104,7 +121,11 @@ void KVDBGeneralStoreTest::SetUp() InitMetaData(); } -void KVDBGeneralStoreTest::TearDown() {} +void KVDBGeneralStoreTest::TearDown() +{ + MetaDataManager::GetInstance().DelMeta(metaData_.GetSecretKey(), true); + MetaDataManager::GetInstance().DelMeta(metaData_.GetKey(), true); +} class MockGeneralWatcher : public DistributedData::GeneralWatcher { public: @@ -121,8 +142,12 @@ public: class MockKvStoreChangedData : public DistributedDB::KvStoreChangedData { public: - MockKvStoreChangedData() {} - virtual ~MockKvStoreChangedData() {} + MockKvStoreChangedData() + { + } + virtual ~MockKvStoreChangedData() + { + } std::list entriesInserted = {}; std::list entriesUpdated = {}; std::list entriesDeleted = {}; @@ -150,14 +175,43 @@ public: /** * @tc.name: GetDBPasswordTest_001 -* @tc.desc: GetDBPassword from meta. +* @tc.desc: get password with all exception branch * @tc.type: FUNC -* @tc.require: -* @tc.author: Hollokin */ HWTEST_F(KVDBGeneralStoreTest, GetDBPasswordTest_001, TestSize.Level0) { - ZLOGI("GetDBPasswordTest start"); + metaData_.isEncrypt = false; + auto dbPassword = KVDBGeneralStore::GetDBPassword(metaData_); + ASSERT_EQ(dbPassword.GetSize(), 0); + + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + + metaData_.isEncrypt = true; + dbPassword = KVDBGeneralStore::GetDBPassword(metaData_); + ASSERT_EQ(dbPassword.GetSize(), 0); + + SecretKeyMetaData secretKey; + auto result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_TRUE(result); + dbPassword = KVDBGeneralStore::GetDBPassword(metaData_); + ASSERT_EQ(dbPassword.GetSize(), 0); + + std::vector randomKey = Random(KEY_LENGTH); + ASSERT_FALSE(randomKey.empty()); + secretKey.sKey = randomKey; + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_TRUE(result); + dbPassword = KVDBGeneralStore::GetDBPassword(metaData_); + ASSERT_EQ(dbPassword.GetSize(), 0); +} + +/** +* @tc.name: GetDBPasswordTest_002 +* @tc.desc: GetDBPassword from meta. +* @tc.type: FUNC +*/ +HWTEST_F(KVDBGeneralStoreTest, GetDBPasswordTest_002, TestSize.Level0) +{ MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKey(), metaData_, true)); EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), metaData_, true)); @@ -166,13 +220,11 @@ HWTEST_F(KVDBGeneralStoreTest, GetDBPasswordTest_001, TestSize.Level0) } /** -* @tc.name: GetDBPasswordTest_002 +* @tc.name: GetDBPasswordTest_003 * @tc.desc: GetDBPassword from encrypt meta. * @tc.type: FUNC -* @tc.require: -* @tc.author: Hollokin */ -HWTEST_F(KVDBGeneralStoreTest, GetDBPasswordTest_002, TestSize.Level0) +HWTEST_F(KVDBGeneralStoreTest, GetDBPasswordTest_003, TestSize.Level0) { ZLOGI("GetDBPasswordTest_002 start"); MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); @@ -183,10 +235,15 @@ HWTEST_F(KVDBGeneralStoreTest, GetDBPasswordTest_002, TestSize.Level0) EXPECT_EQ(errCode, CryptoManager::ErrCode::SUCCESS); std::vector randomKey = Random(KEY_LENGTH); + ASSERT_FALSE(randomKey.empty()); SecretKeyMetaData secretKey; secretKey.storeType = metaData_.storeType; - secretKey.sKey = CryptoManager::GetInstance().Encrypt(randomKey, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - EXPECT_EQ(secretKey.sKey.size(), ENCRYPT_KEY_LENGTH); + CryptoManager::CryptoParams encryptParams = { .area = metaData_.area, .userId = metaData_.user }; + secretKey.sKey = CryptoManager::GetInstance().Encrypt(randomKey, encryptParams); + ASSERT_FALSE(secretKey.sKey.empty()); + ASSERT_FALSE(encryptParams.nonce.empty()); + secretKey.area = metaData_.area; + secretKey.nonce = encryptParams.nonce; EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true)); auto dbPassword = KVDBGeneralStore::GetDBPassword(metaData_); @@ -194,6 +251,35 @@ HWTEST_F(KVDBGeneralStoreTest, GetDBPasswordTest_002, TestSize.Level0) randomKey.assign(randomKey.size(), 0); } +/** +* @tc.name: GetDBPasswordTest_004 +* @tc.desc: get password with exception branch +* @tc.type: FUNC +*/ +HWTEST_F(KVDBGeneralStoreTest, GetDBPasswordTest_004, TestSize.Level0) +{ + metaData_.bundleName = INVALID_APPID; + auto dbPassword = KVDBGeneralStore::GetDBPassword(metaData_); + ASSERT_EQ(dbPassword.GetSize(), 0); + + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + + SecretKeyMetaData secretKey; + auto result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_TRUE(result); + dbPassword = KVDBGeneralStore::GetDBPassword(metaData_); + ASSERT_EQ(dbPassword.GetSize(), 0); + + auto key = Random(KEY_LENGTH); + ASSERT_FALSE(key.empty()); + secretKey.sKey = key; + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_TRUE(result); + dbPassword = KVDBGeneralStore::GetDBPassword(metaData_); + ASSERT_EQ(dbPassword.GetSize(), 0); + MetaDataManager::GetInstance().DelMeta(metaData_.GetSecretKey(), true); +} + /** * @tc.name: GetDBSecurityTest * @tc.desc: GetDBSecurity @@ -317,7 +403,7 @@ HWTEST_F(KVDBGeneralStoreTest, BusyClose, TestSize.Level0) HWTEST_F(KVDBGeneralStoreTest, SyncTest, TestSize.Level0) { ZLOGI("SyncTest start"); - mkdir(("/data/service/el1/public/database/" + std::string(bundleName)).c_str(), + mkdir(("/data/service/el1/public/database/" + std::string(BUNDLE_NAME)).c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); auto store = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store, nullptr); @@ -332,6 +418,7 @@ HWTEST_F(KVDBGeneralStoreTest, SyncTest, TestSize.Level0) EXPECT_NE(ret.first, GeneralError::E_OK); auto status = store->Close(); EXPECT_EQ(status, GeneralError::E_OK); + delete store; } /** @@ -442,32 +529,101 @@ HWTEST_F(KVDBGeneralStoreTest, GetDBSyncCompleteCB, TestSize.Level0) } /** -* @tc.name: CloudSync +* @tc.name: CloudSync001 +* @tc.desc: Test the scenario where the QueryUsers return false in the CloudSync function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(KVDBGeneralStoreTest, CloudSync001, TestSize.Level0) +{ + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + store->SetEqualIdentifier(BUNDLE_NAME, STORE_NAME); + 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(BUNDLE_NAME, STORE_NAME); + std::string prepareTraceId; + std::vector users; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(users), Return(false))); + auto ret = store->CloudSync(devices, cloudSyncMode, asyncs, 0, prepareTraceId); + EXPECT_EQ(ret, DBStatus::DB_ERROR); + store->delegate_ = nullptr; + delete store; +} + +/** +* @tc.name: CloudSync002 * @tc.desc: CloudSync test the functionality of different branches. * @tc.type: FUNC * @tc.require: -* @tc.author: SQL +* @tc.author: */ -HWTEST_F(KVDBGeneralStoreTest, CloudSync, TestSize.Level0) +HWTEST_F(KVDBGeneralStoreTest, CloudSync002, TestSize.Level0) { auto store = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store, nullptr); - store->SetEqualIdentifier(bundleName, storeName); + store->SetEqualIdentifier(BUNDLE_NAME, STORE_NAME); 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); + store->SetEqualIdentifier(BUNDLE_NAME, STORE_NAME); std::string prepareTraceId; + std::vector users; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)) + .Times(1) + .WillOnce(DoAll( + SetArgReferee<0>(users), + Invoke([](std::vector& users) { users.clear(); }), + Return(true))); auto ret = store->CloudSync(devices, cloudSyncMode, asyncs, 0, prepareTraceId); - EXPECT_EQ(ret, DBStatus::OK); + EXPECT_EQ(ret, DBStatus::DB_ERROR); store->storeInfo_.user = 1; cloudSyncMode = DistributedDB::SyncMode::SYNC_MODE_CLOUD_FORCE_PUSH; ret = store->CloudSync(devices, cloudSyncMode, asyncs, 0, prepareTraceId); EXPECT_EQ(ret, DBStatus::OK); + store->delegate_ = nullptr; + delete store; +} + +/** +* @tc.name: CloudSync003 +* @tc.desc: Test the scenario where the QueryUsers return true in the CloudSync function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(KVDBGeneralStoreTest, CloudSync003, TestSize.Level0) +{ + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + store->SetEqualIdentifier(BUNDLE_NAME, STORE_NAME); + 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(BUNDLE_NAME, STORE_NAME); + std::string prepareTraceId; + std::vector users = {0, 1}; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)) + .Times(1) + .WillOnce(DoAll( + SetArgReferee<0>(users), + Return(true))); + auto ret = store->CloudSync(devices, cloudSyncMode, asyncs, 0, prepareTraceId); + EXPECT_EQ(ret, DBStatus::OK); + store->delegate_ = nullptr; + delete store; } /** @@ -481,7 +637,7 @@ HWTEST_F(KVDBGeneralStoreTest, GetIdentifierParams, TestSize.Level0) { auto store = new (std::nothrow) KVDBGeneralStore(metaData_); std::vector sameAccountDevs{}; - std::vector uuids{"uuidtest01", "uuidtest02", "uuidtest03"}; + std::vector uuids{ "uuidtest01", "uuidtest02", "uuidtest03" }; store->GetIdentifierParams(sameAccountDevs, uuids, 0); // NO_ACCOUNT for (const auto &devId : uuids) { EXPECT_EQ(DMAdapter::GetInstance().IsOHOSType(devId), false); @@ -491,15 +647,15 @@ HWTEST_F(KVDBGeneralStoreTest, GetIdentifierParams, TestSize.Level0) } /** -* @tc.name: Sync -* @tc.desc: Sync test the functionality of different branches. +* @tc.name: Sync002 +* @tc.desc: Sync test the functionality of 3 < syncMode < 7 branches. * @tc.type: FUNC * @tc.require: -* @tc.author: SQL +* @tc.author: */ -HWTEST_F(KVDBGeneralStoreTest, Sync, TestSize.Level0) +HWTEST_F(KVDBGeneralStoreTest, Sync002, TestSize.Level0) { - mkdir(("/data/service/el1/public/database/" + std::string(bundleName)).c_str(), + mkdir(("/data/service/el1/public/database/" + std::string(BUNDLE_NAME)).c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); auto store = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store, nullptr); @@ -512,6 +668,8 @@ HWTEST_F(KVDBGeneralStoreTest, Sync, TestSize.Level0) syncParam.mode = mixMode; KvStoreNbDelegateMock mockDelegate; store->delegate_ = &mockDelegate; + std::vector users1 = { 0, 1 }; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).WillRepeatedly(DoAll(SetArgReferee<0>(users1), Return(true))); auto ret = store->Sync({}, query, [](const GenDetails &result) {}, syncParam); EXPECT_EQ(ret.first, GeneralError::E_NOT_SUPPORT); GeneralStore::StoreConfig storeConfig; @@ -519,13 +677,34 @@ HWTEST_F(KVDBGeneralStoreTest, Sync, TestSize.Level0) store->SetConfig(storeConfig); ret = store->Sync({}, query, [](const GenDetails &result) {}, syncParam); EXPECT_EQ(ret.first, GeneralError::E_OK); + store->delegate_ = nullptr; + delete store; +} - syncMode = GeneralStore::SyncMode::NEARBY_END; - mixMode = GeneralStore::MixMode(syncMode, highMode); +/** +* @tc.name: Sync003 +* @tc.desc: Sync test the functionality of different branches. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(KVDBGeneralStoreTest, Sync003, TestSize.Level0) +{ + mkdir(("/data/service/el1/public/database/" + std::string(BUNDLE_NAME)).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::NEARBY_END; + 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; - ret = store->Sync({}, query, [](const GenDetails &result) {}, syncParam); + KvStoreNbDelegateMock mockDelegate; + store->delegate_ = &mockDelegate; + auto ret = store->Sync({}, query, [](const GenDetails &result) {}, syncParam); EXPECT_EQ(ret.first, GeneralError::E_INVALID_ARGS); - std::vector devices = { "device1", "device2" }; syncMode = GeneralStore::SyncMode::NEARBY_SUBSCRIBE_REMOTE; mixMode = GeneralStore::MixMode(syncMode, highMode); @@ -550,6 +729,8 @@ HWTEST_F(KVDBGeneralStoreTest, Sync, TestSize.Level0) syncParam.mode = mixMode; ret = store->Sync(devices, query, [](const GenDetails &result) {}, syncParam); EXPECT_EQ(ret.first, GeneralError::E_INVALID_ARGS); + store->delegate_ = nullptr; + delete store; } /** @@ -567,7 +748,7 @@ HWTEST_F(KVDBGeneralStoreTest, Clean, TestSize.Level0) std::string tableName = "tableName"; auto ret = store->Clean(devices, -1, tableName); EXPECT_EQ(ret, GeneralError::E_INVALID_ARGS); - ret = store->Clean(devices, 5, tableName); + ret = store->Clean(devices, 6, tableName); EXPECT_EQ(ret, GeneralError::E_INVALID_ARGS); ret = store->Clean(devices, GeneralStore::CleanMode::NEARBY_DATA, tableName); EXPECT_EQ(ret, GeneralError::E_ALREADY_CLOSED); @@ -587,6 +768,9 @@ HWTEST_F(KVDBGeneralStoreTest, Clean, TestSize.Level0) ret = store->Clean(devices, GeneralStore::CleanMode::LOCAL_DATA, tableName); EXPECT_EQ(ret, GeneralError::E_ERROR); + + ret = store->Clean(devices, GeneralStore::CleanMode::CLEAN_WATER, tableName); + EXPECT_EQ(ret, GeneralError::E_OK); } /** @@ -791,7 +975,7 @@ HWTEST_F(KVDBGeneralStoreTest, GetDBOption001, TestSize.Level0) */ HWTEST_F(KVDBGeneralStoreTest, Sync001, TestSize.Level0) { - mkdir(("/data/service/el1/public/database/" + std::string(bundleName)).c_str(), + mkdir(("/data/service/el1/public/database/" + std::string(BUNDLE_NAME)).c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); auto store = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store, nullptr); @@ -829,7 +1013,6 @@ HWTEST_F(KVDBGeneralStoreTest, Sync001, TestSize.Level0) delete store; } - /** * @tc.name: SetEqualIdentifier * @tc.desc: SetEqualIdentifier test. @@ -841,8 +1024,8 @@ HWTEST_F(KVDBGeneralStoreTest, SetEqualIdentifier, TestSize.Level0) { auto store = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store, nullptr); - std::vector sameAccountDevs{"account01", "account02", "account03"}; - std::vector uuids{"uuidtest01", "uuidtest02", "uuidtest03"}; + std::vector sameAccountDevs{ "account01", "account02", "account03" }; + std::vector uuids{ "uuidtest01", "uuidtest02", "uuidtest03" }; AppId appId01 = { "ohos.kvdbservice.test01" }; StoreId storeId01 = { "meta_test_storeid" }; std::string account = "account"; @@ -862,8 +1045,8 @@ HWTEST_F(KVDBGeneralStoreTest, GetIdentifierParams001, TestSize.Level0) { auto store = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store, nullptr); - std::vector sameAccountDevs{"account01", "account02", "account03"}; - std::vector uuids{"uuidtest01", "uuidtest02", "uuidtest03"}; + std::vector sameAccountDevs{ "account01", "account02", "account03" }; + std::vector uuids{ "uuidtest01", "uuidtest02", "uuidtest03" }; store->GetIdentifierParams(sameAccountDevs, uuids, 1); // for (const auto &devId : uuids) { EXPECT_EQ(DMAdapter::GetInstance().IsOHOSType(devId), false); @@ -947,7 +1130,7 @@ HWTEST_F(KVDBGeneralStoreTest, GetDBProcessCB002, TestSize.Level0) { auto store = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store, nullptr); - std::map processes = {{"test_id", {}}}; + std::map processes = { { "test_id", {} } }; GeneralStore::DetailAsync async; EXPECT_EQ(async, nullptr); auto callback = store->GetDBProcessCB(async); @@ -1027,7 +1210,7 @@ HWTEST_F(KVDBGeneralStoreTest, ConstructorTest, TestSize.Level0) delete store3; // Test observer registration - metaData_.storeId = storeName; + metaData_.storeId = STORE_NAME; metaData_.storeType = DistributedKv::KvStoreType::SINGLE_VERSION; auto store4 = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store4, nullptr); 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 c2f49cc008513c95de83e67e3fba87b68b3da1c7..039577976be7a8734d7a87fad25c39288a4dbbfc 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 @@ -13,10 +13,10 @@ * limitations under the License. */ #define LOG_TAG "KvdbServiceImplTest" -#include "kvdb_service_impl.h" - -#include #include +#include + +#include #include #include "bootstrap.h" @@ -25,20 +25,20 @@ #include "cloud/cloud_server.h" #include "device_manager_adapter.h" #include "distributed_kv_data_manager.h" -#include "eventcenter/event_center.h" +#include "event_center.h" #include "ipc_skeleton.h" -#include "kvdb_service_stub.h" #include "kvdb_query.h" +#include "kvdb_service_impl.h" +#include "kvdb_service_stub.h" #include "kvstore_death_recipient.h" #include "kvstore_meta_manager.h" #include "kvstore_sync_manager.h" #include "log_print.h" -#include #include "mock/access_token_mock.h" #include "mock/meta_data_manager_mock.h" +#include "nativetoken_kit.h" #include "network/network_delegate.h" #include "network_delegate_mock.h" -#include "nativetoken_kit.h" #include "token_setproc.h" #include "types.h" #include "utils/anonymous.h" @@ -66,6 +66,7 @@ using StoreMetaData = OHOS::DistributedData::StoreMetaData; using SyncEnd = OHOS::DistributedKv::KvStoreSyncManager::SyncEnd; using DBResult = std::map; using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; +using DBLaunchParam = OHOS::DistributedKv::KVDBServiceImpl::DBLaunchParam; static OHOS::DistributedKv::StoreId storeId = { "kvdb_test_storeid" }; static OHOS::DistributedKv::AppId appId = { "ohos.test.kvdb" }; static constexpr const char *TEST_USER = "0"; @@ -75,8 +76,11 @@ class KvdbServiceImplTest : public testing::Test { public: static inline std::shared_ptr accTokenMock = nullptr; static inline std::shared_ptr metaDataManagerMock = nullptr; + static inline std::shared_ptr> metaDataMock = nullptr; static constexpr size_t NUM_MIN = 5; static constexpr size_t NUM_MAX = 12; + static constexpr uint32_t TOKENID1 = 123; + static constexpr uint32_t TOKENID2 = 456; static DistributedKvDataManager manager; static Options create; static UserId userId; @@ -92,7 +96,7 @@ public: static void RemoveAllStore(OHOS::DistributedKv::DistributedKvDataManager &manager); void SetUp(); void TearDown(); - + void CreateStoreMetaData(std::vector &datas, DBLaunchParam param); KvdbServiceImplTest(); protected: @@ -152,6 +156,8 @@ void KvdbServiceImplTest::SetUpTestCase(void) BAccessTokenKit::accessTokenkit = accTokenMock; metaDataManagerMock = std::make_shared(); BMetaDataManager::metaDataManager = metaDataManagerMock; + metaDataMock = std::make_shared>(); + BMetaData::metaDataManager = metaDataMock; NetworkDelegate::RegisterNetworkInstance(&delegate_); } @@ -165,6 +171,8 @@ void KvdbServiceImplTest::TearDownTestCase() BAccessTokenKit::accessTokenkit = nullptr; metaDataManagerMock = nullptr; BMetaDataManager::metaDataManager = nullptr; + metaDataMock = nullptr; + BMetaData::metaDataManager = nullptr; } void KvdbServiceImplTest::SetUp(void) @@ -193,7 +201,60 @@ void SyncEndCallback(const std::map &statu } } -KvdbServiceImplTest::KvdbServiceImplTest(void) {} +KvdbServiceImplTest::KvdbServiceImplTest(void) +{ +} + +void KvdbServiceImplTest::CreateStoreMetaData(std::vector &datas, DBLaunchParam param) +{ + std::vector metaData; + + // 1: storeType out of range. + StoreMetaData meta1; + meta1.storeType = StoreMetaData::StoreType::STORE_KV_BEGIN - 1; + metaData.push_back(meta1); + + StoreMetaData meta2; + meta2.storeType = StoreMetaData::StoreType::STORE_KV_END + 1; + metaData.push_back(meta2); + + // 2: user ID mismatch. + StoreMetaData meta3; + meta3.storeType = StoreMetaData::StoreType::STORE_KV_BEGIN; + meta3.user = "user2"; // param.userId = "user1" + metaData.push_back(meta3); + + // 3: appId equals to process label. + StoreMetaData meta4; + meta4.storeType = StoreMetaData::StoreType::STORE_KV_BEGIN; + meta4.appId = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); + metaData.push_back(meta4); + + // 4: The identifier does not match and CompareTripleIdentifier is false. + StoreMetaData meta5; + meta5.storeType = StoreMetaData::StoreType::STORE_KV_BEGIN; + meta5.storeId = "store_id_1"; + meta5.appId = "app_id_1"; + metaData.push_back(meta5); + + // 5: Normal execution logic. + StoreMetaData meta6; + meta6.storeType = StoreMetaData::StoreType::STORE_KV_BEGIN; + meta6.user = param.userId; // param.userId = "user1" + meta6.appId = "valid_app_id"; + meta6.storeId = "store_id_2"; + meta6.tokenId = TOKENID1; + metaData.push_back(meta6); + + // 6: trigger SetEqualIdentifier. + StoreMetaData meta7; + meta7.storeType = StoreMetaData::StoreType::STORE_KV_BEGIN; + meta7.user = param.userId; + meta7.appId = "valid_app_id"; + meta7.storeId = "store_id_3"; + meta7.tokenId = TOKENID2; + metaData.push_back(meta7); +} /** * @tc.name: KvdbServiceImpl001 @@ -231,8 +292,9 @@ HWTEST_F(KvdbServiceImplTest, KvdbServiceImpl001, TestSize.Level0) status = kvdbServiceImpl_->UnsubscribeSwitchData(appId); EXPECT_EQ(status, Status::SUCCESS); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return - (ATokenTypeEnum::TOKEN_NATIVE)).WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); status = kvdbServiceImpl_->Close(appId, id1, 0); EXPECT_EQ(status, Status::SUCCESS); } @@ -256,7 +318,7 @@ HWTEST_F(KvdbServiceImplTest, OnInitialize001, TestSize.Level0) auto event = std::make_unique(CloudEvent::CLOUD_SYNC, storeInfo); EXPECT_NE(event, nullptr); result = EventCenter::GetInstance().PostEvent(move(event)); - EXPECT_EQ(result, 1); // CODE_SYNC + EXPECT_EQ(result, 1); // CODE_SYNC auto event1 = std::make_unique(CloudEvent::CLEAN_DATA, storeInfo); EXPECT_NE(event1, nullptr); result = EventCenter::GetInstance().PostEvent(move(event1)); @@ -320,8 +382,9 @@ HWTEST_F(KvdbServiceImplTest, DeleteTest001, TestSize.Level0) Status status1 = manager.GetSingleKvStore(create, appId, storeId, kvStore); ASSERT_NE(kvStore, nullptr); ASSERT_EQ(status1, Status::SUCCESS); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return - (ATokenTypeEnum::TOKEN_NATIVE)).WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); auto status = kvdbServiceImpl_->Delete(appId, storeId, 0); ZLOGI("DeleteTest001 status = :%{public}d", status); ASSERT_EQ(status, Status::SUCCESS); @@ -338,8 +401,9 @@ HWTEST_F(KvdbServiceImplTest, DeleteTest002, TestSize.Level0) ZLOGI("DeleteTest002 start"); AppId appId01 = { "ohos.kvdbserviceimpl.test01" }; StoreId storeId01 = { "meta_test_storeid" }; - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return - (ATokenTypeEnum::TOKEN_NATIVE)).WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); auto status = kvdbServiceImpl_->Delete(appId01, storeId01, 0); ZLOGI("DeleteTest002 status = :%{public}d", status); ASSERT_EQ(status, Status::SUCCESS); @@ -353,9 +417,11 @@ HWTEST_F(KvdbServiceImplTest, DeleteTest002, TestSize.Level0) */ HWTEST_F(KvdbServiceImplTest, DeleteTest003, TestSize.Level0) { - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); - EXPECT_CALL(*accTokenMock, GetHapTokenInfo(testing::_, testing::_)).WillOnce(testing::Return(-1)) + EXPECT_CALL(*accTokenMock, GetHapTokenInfo(testing::_, testing::_)) + .WillOnce(testing::Return(-1)) .WillRepeatedly(testing::Return(-1)); int32_t status = kvdbServiceImpl_->Delete(appId, storeId, 0); EXPECT_EQ(status, DistributedKv::ILLEGAL_STATE); @@ -369,9 +435,11 @@ HWTEST_F(KvdbServiceImplTest, DeleteTest003, TestSize.Level0) */ HWTEST_F(KvdbServiceImplTest, CloseTest001, TestSize.Level0) { - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); - EXPECT_CALL(*accTokenMock, GetHapTokenInfo(testing::_, testing::_)).WillOnce(testing::Return(-1)) + EXPECT_CALL(*accTokenMock, GetHapTokenInfo(testing::_, testing::_)) + .WillOnce(testing::Return(-1)) .WillRepeatedly(testing::Return(-1)); int32_t status = kvdbServiceImpl_->Close(appId, storeId, 0); EXPECT_EQ(status, DistributedKv::ILLEGAL_STATE); @@ -386,29 +454,29 @@ HWTEST_F(KvdbServiceImplTest, CloseTest001, TestSize.Level0) HWTEST_F(KvdbServiceImplTest, OnAsyncCompleteTest001, TestSize.Level0) { DistributedKv::Statistic upload; - upload.failed = 1; // test - upload.success = 1; // test - upload.total = 1; // test + upload.failed = 1; // test + upload.success = 1; // test + upload.total = 1; // test upload.untreated = 1; // test DistributedKv::Statistic download; - download.failed = 1; // test - download.success = 1; // test - download.total = 1; // test + download.failed = 1; // test + download.success = 1; // test + download.total = 1; // test download.untreated = 1; // test DistributedKv::TableDetail details; details.download = download; details.upload = upload; DistributedKv::ProgressDetail detail; - detail.code = 1; // test + detail.code = 1; // test detail.progress = 1; // test detail.details = details; sptr notifier; DistributedKv::KVDBServiceImpl::SyncAgent syncAgent; - syncAgent.pid_ = 1; // test + syncAgent.pid_ = 1; // test syncAgent.switchesObserverCount_ = 1; // test syncAgent.appId_ = { "ohos.OnAsyncCompleteTest001.kvdb" }; syncAgent.notifier_ = notifier; - kvdbServiceImpl_->syncAgents_.Insert(100, syncAgent); // test + kvdbServiceImpl_->syncAgents_.Insert(100, syncAgent); // test kvdbServiceImpl_->OnAsyncComplete(1, 1, std::move(detail)); // test EXPECT_EQ(kvdbServiceImpl_->syncAgents_.Find(1).first, false); kvdbServiceImpl_->OnAsyncComplete(100, 1, std::move(detail)); // test @@ -464,7 +532,7 @@ HWTEST_F(KvdbServiceImplTest, UnregServiceNotifierTest001, TestSize.Level0) ASSERT_EQ(status1, Status::SUCCESS); sptr notifier; DistributedKv::KVDBServiceImpl::SyncAgent syncAgent; - syncAgent.pid_ = 1; // test + syncAgent.pid_ = 1; // test syncAgent.switchesObserverCount_ = 1; // test syncAgent.appId_ = { "ohos.OnAsyncCompleteTest001.kvdb" }; syncAgent.notifier_ = notifier; @@ -548,11 +616,13 @@ HWTEST_F(KvdbServiceImplTest, EnableCapabilityTest001, TestSize.Level0) Status status1 = manager.GetSingleKvStore(create, appId, storeId, kvStore); ASSERT_NE(kvStore, nullptr); ASSERT_EQ(status1, Status::SUCCESS); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); auto status = kvdbServiceImpl_->EnableCapability(appId, storeId, 0); ASSERT_EQ(status, Status::SUCCESS); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); status = kvdbServiceImpl_->EnableCapability(appId, storeId, 0); ASSERT_EQ(status, Status::ILLEGAL_STATE); @@ -569,7 +639,8 @@ HWTEST_F(KvdbServiceImplTest, GetInstIndexTest001, TestSize.Level0) Status status1 = manager.GetSingleKvStore(create, appId, storeId, kvStore); ASSERT_NE(kvStore, nullptr); ASSERT_EQ(status1, Status::SUCCESS); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); auto status = kvdbServiceImpl_->GetInstIndex(100, appId); ASSERT_EQ(status, -1); @@ -587,13 +658,15 @@ HWTEST_F(KvdbServiceImplTest, IsNeedMetaSyncTest001, TestSize.Level0) ASSERT_NE(kvStore, nullptr); ASSERT_EQ(status1, Status::SUCCESS); StoreMetaData meta = kvdbServiceImpl_->GetStoreMetaData(appId, storeId); - std::vector uuids{"uuidtest01"}; + std::vector uuids{ "uuidtest01" }; EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)) - .WillOnce(testing::Return(true)).WillRepeatedly(testing::Return(true)); + .WillOnce(testing::Return(true)) + .WillRepeatedly(testing::Return(true)); auto status = kvdbServiceImpl_->IsNeedMetaSync(meta, uuids); ASSERT_EQ(status, false); EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)) - .WillOnce(testing::Return(false)).WillRepeatedly(testing::Return(false)); + .WillOnce(testing::Return(false)) + .WillRepeatedly(testing::Return(false)); status = kvdbServiceImpl_->IsNeedMetaSync(meta, uuids); ASSERT_EQ(status, true); } @@ -611,11 +684,13 @@ HWTEST_F(KvdbServiceImplTest, GetDistributedDataMetaTest001, TestSize.Level0) ASSERT_EQ(status, Status::SUCCESS); std::string deviceId = "KvdbServiceImplTest_deviceId"; EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)) - .WillOnce(testing::Return(false)).WillRepeatedly(testing::Return(false)); + .WillOnce(testing::Return(false)) + .WillRepeatedly(testing::Return(false)); auto meta = kvdbServiceImpl_->GetDistributedDataMeta(deviceId); ASSERT_EQ(meta.user, "0"); EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)) - .WillOnce(testing::Return(true)).WillRepeatedly(testing::Return(true)); + .WillOnce(testing::Return(true)) + .WillRepeatedly(testing::Return(true)); meta = kvdbServiceImpl_->GetDistributedDataMeta(deviceId); ASSERT_EQ(meta.deviceId, deviceId); } @@ -651,7 +726,7 @@ HWTEST_F(KvdbServiceImplTest, DoSyncBeginTest001, TestSize.Level0) Status status = manager.GetSingleKvStore(create, appId, storeId, kvStore); ASSERT_NE(kvStore, nullptr); ASSERT_EQ(status, Status::SUCCESS); - std::vector device1{"uuidtest01"}; + std::vector device1{ "uuidtest01" }; std::vector device2; StoreMetaData meta = kvdbServiceImpl_->GetStoreMetaData(appId, storeId); SyncInfo syncInfo; @@ -687,12 +762,14 @@ HWTEST_F(KvdbServiceImplTest, DoCompleteTest001, TestSize.Level0) DBResult dbResult; dbResult.insert_or_assign("DoCompleteTest_1", DBStatus::OK); dbResult.insert_or_assign("DoCompleteTest_1", DBStatus::DB_ERROR); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); status = kvdbServiceImpl_->DoComplete(meta, syncInfo, refCount, dbResult); ASSERT_EQ(status, Status::SUCCESS); syncInfo.seqId = std::numeric_limits::max(); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); status = kvdbServiceImpl_->DoComplete(meta, syncInfo, refCount, dbResult); ASSERT_EQ(status, Status::SUCCESS); @@ -712,7 +789,7 @@ HWTEST_F(KvdbServiceImplTest, ConvertDbStatusNativeTest001, TestSize.Level0) ASSERT_EQ(status, Status::DEVICE_NOT_ONLINE); DBStatus dbstatus = static_cast(DBStatus::OK - 1); status = kvdbServiceImpl_->ConvertDbStatusNative(dbstatus); - ASSERT_EQ(status, - 1); + ASSERT_EQ(status, -1); } /** @@ -765,12 +842,14 @@ HWTEST_F(KvdbServiceImplTest, DisableCapabilityTest001, TestSize.Level0) Status status1 = manager.GetSingleKvStore(create, appId, storeId, kvStore); ASSERT_NE(kvStore, nullptr); ASSERT_EQ(status1, Status::SUCCESS); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); auto status = kvdbServiceImpl_->DisableCapability(appId, storeId, 0); ZLOGI("DisableCapabilityTest001 status = :%{public}d", status); ASSERT_EQ(status, Status::SUCCESS); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); status = kvdbServiceImpl_->EnableCapability(appId, storeId, 0); ASSERT_EQ(status, Status::ILLEGAL_STATE); @@ -790,12 +869,14 @@ HWTEST_F(KvdbServiceImplTest, SetCapabilityTest001, TestSize.Level0) ASSERT_EQ(status1, Status::SUCCESS); std::vector local; std::vector remote; - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); auto status = kvdbServiceImpl_->SetCapability(appId, storeId, 0, local, remote); ZLOGI("SetCapabilityTest001 status = :%{public}d", status); ASSERT_EQ(status, Status::SUCCESS); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); status = kvdbServiceImpl_->EnableCapability(appId, storeId, 0); ASSERT_EQ(status, Status::ILLEGAL_STATE); @@ -872,7 +953,7 @@ HWTEST_F(KvdbServiceImplTest, UnsubscribeTest001, TestSize.Level0) ASSERT_EQ(status1, Status::SUCCESS); sptr notifier; DistributedKv::KVDBServiceImpl::SyncAgent syncAgent; - syncAgent.pid_ = 1; // test + syncAgent.pid_ = 1; // test syncAgent.switchesObserverCount_ = 1; // test syncAgent.appId_ = { "ohos.OnAsyncCompleteTest001.kvdb" }; syncAgent.notifier_ = notifier; @@ -884,29 +965,6 @@ HWTEST_F(KvdbServiceImplTest, UnsubscribeTest001, TestSize.Level0) ASSERT_EQ(status, Status::SUCCESS); } -/** -* @tc.name: GetBackupPasswordTest001 -* @tc.desc: GetBackupPassword test -* @tc.type: FUNC -* @tc.author: wangbin -*/ -HWTEST_F(KvdbServiceImplTest, GetBackupPasswordTest001, TestSize.Level0) -{ - auto status = manager.GetSingleKvStore(create, appId, storeId, kvStore); - ASSERT_NE(kvStore, nullptr); - ASSERT_EQ(status, Status::SUCCESS); - std::vector> password; - status = kvdbServiceImpl_->GetBackupPassword - (appId, storeId, 0, password, DistributedKv::KVDBService::PasswordType::BACKUP_SECRET_KEY); - ASSERT_EQ(status, Status::ERROR); - status = kvdbServiceImpl_->GetBackupPassword - (appId, storeId, 0, password, DistributedKv::KVDBService::PasswordType::SECRET_KEY); - ASSERT_EQ(status, Status::ERROR); - status = kvdbServiceImpl_->GetBackupPassword - (appId, storeId, 0, password, DistributedKv::KVDBService::PasswordType::BUTTON); - ASSERT_EQ(status, Status::ERROR); -} - /** * @tc.name: BeforeCreateTest001 * @tc.desc: BeforeCreate test @@ -929,7 +987,8 @@ HWTEST_F(KvdbServiceImplTest, BeforeCreateTest001, TestSize.Level0) creates.cloudConfig.enableCloud = true; kvdbServiceImpl_->executors_ = std::make_shared(1, 1); EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)) - .WillOnce(testing::Return(false)).WillRepeatedly(testing::Return(false)); + .WillOnce(testing::Return(false)) + .WillRepeatedly(testing::Return(false)); auto status = kvdbServiceImpl_->BeforeCreate(appId, storeId, creates); ASSERT_NE(status, Status::STORE_META_CHANGED); kvdbServiceImpl_->executors_ = nullptr; @@ -1061,6 +1120,7 @@ HWTEST_F(KvdbServiceImplTest, ResolveAutoLaunch, TestSize.Level0) EXPECT_EQ(status, Status::SUCCESS); std::string identifier = "identifier"; DistributedKv::KVDBServiceImpl::DBLaunchParam launchParam; + launchParam.userId = "user1"; auto result = kvdbServiceImpl_->ResolveAutoLaunch(identifier, launchParam); EXPECT_EQ(result, Status::STORE_NOT_FOUND); std::shared_ptr executors = std::make_shared(1, 0); @@ -1069,6 +1129,10 @@ HWTEST_F(KvdbServiceImplTest, ResolveAutoLaunch, TestSize.Level0) DistributedKv::KvStoreMetaManager::GetInstance().BindExecutor(executors); DistributedKv::KvStoreMetaManager::GetInstance().InitMetaParameter(); DistributedKv::KvStoreMetaManager::GetInstance().InitMetaListener(); + std::vector datas; + CreateStoreMetaData(datas, launchParam); + EXPECT_CALL(*metaDataMock, LoadMeta(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::DoAll(testing::SetArgReferee<1>(datas), testing::Return(true))); result = kvdbServiceImpl_->ResolveAutoLaunch(identifier, launchParam); EXPECT_EQ(result, Status::SUCCESS); } @@ -1317,25 +1381,25 @@ HWTEST_F(KvdbServiceImplTest, DoCloudSync01, TestSize.Level0) HWTEST_F(KvdbServiceImplTest, OnAsyncCompleteTest002, TestSize.Level0) { DistributedKv::Statistic upload; - upload.failed = 1; // test - upload.success = 1; // test - upload.total = 1; // test + upload.failed = 1; // test + upload.success = 1; // test + upload.total = 1; // test upload.untreated = 1; // test DistributedKv::Statistic download; - download.failed = 1; // test - download.success = 1; // test - download.total = 1; // test + download.failed = 1; // test + download.success = 1; // test + download.total = 1; // test download.untreated = 1; // test DistributedKv::TableDetail details; details.download = download; details.upload = upload; DistributedKv::ProgressDetail detail; - detail.code = 1; // test + detail.code = 1; // test detail.progress = 1; // test detail.details = details; DistributedKv::KVDBServiceImpl::SyncAgent syncAgent; sptr notifier = nullptr; - syncAgent.pid_ = 1; // test + syncAgent.pid_ = 1; // test syncAgent.switchesObserverCount_ = 1; // test syncAgent.appId_ = { "ohos.OnAsyncCompleteTest.kvdb" }; syncAgent.notifier_ = notifier; @@ -1359,7 +1423,7 @@ HWTEST_F(KvdbServiceImplTest, OnAsyncCompleteTest003, TestSize.Level0) { DistributedKv::KVDBServiceImpl::SyncAgent syncAgent; sptr notifier; - syncAgent.pid_ = 1; // test + syncAgent.pid_ = 1; // test syncAgent.switchesObserverCount_ = 1; // test syncAgent.appId_ = { "ohos.OnAsyncCompleteTest001.kvdb" }; syncAgent.notifier_ = notifier; @@ -1431,16 +1495,36 @@ HWTEST_F(KvdbServiceImplTest, syncTest003, TestSize.Level0) SyncInfo syncInfo; syncInfo.seqId = std::numeric_limits::max(); EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)) - .WillOnce(testing::Return(true)).WillRepeatedly(testing::Return(true)); + .WillOnce(testing::Return(true)) + .WillRepeatedly(testing::Return(true)); auto status = kvdbServiceImpl_->Sync(appId, storeId, 0, syncInfo); EXPECT_EQ(localMeta.HasPolicy(DistributedKv::IMMEDIATE_SYNC_ON_CHANGE), false); EXPECT_NE(status, Status::SUCCESS); EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)) - .WillOnce(testing::Return(false)).WillRepeatedly(testing::Return(false)); + .WillOnce(testing::Return(false)) + .WillRepeatedly(testing::Return(false)); status = kvdbServiceImpl_->Sync(appId, storeId, 0, syncInfo); EXPECT_EQ(localMeta.HasPolicy(DistributedKv::IMMEDIATE_SYNC_ON_ONLINE), true); } +/** +* @tc.name: SyncTest004 +* @tc.desc: twin application sync test +* @tc.type: FUNC +*/ +HWTEST_F(KvdbServiceImplTest, SyncTest004, TestSize.Level0) +{ + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); + EXPECT_CALL(*accTokenMock, GetHapTokenInfo(testing::_, testing::_)) + .WillOnce(testing::Return(0)) + .WillRepeatedly(testing::Return(0)); + SyncInfo syncInfo; + auto status = kvdbServiceImpl_->Sync(appId, storeId, 0, syncInfo); + ASSERT_EQ(status, Status::NOT_SUPPORT); +} + /** * @tc.name: GetSyncParamTest001 * @tc.desc: GetStoreIds @@ -1472,7 +1556,7 @@ HWTEST_F(KvdbServiceImplTest, GetSyncParamTest002, TestSize.Level0) HWTEST_F(KvdbServiceImplTest, SubscribeSwitchData, TestSize.Level0) { options_.isNeedCompress = false; - std::vector password {}; + std::vector password{}; StoreMetaData metaData; auto status = kvdbServiceImpl_->AfterCreate(appId, storeId, options_, password); ASSERT_EQ(status, Status::SUCCESS); diff --git a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_password_test.cpp b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_password_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d30d07c37e048638860bc34681809bdaf8ce59a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_password_test.cpp @@ -0,0 +1,201 @@ +/* +* Copyright (c) 2025 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 "kvdb_service_impl.h" + +#include +#include + +#include "device_manager_adapter.h" +#include "ipc_skeleton.h" +#include "mock/db_store_mock.h" + +namespace OHOS::Test { +using namespace testing::ext; +using namespace OHOS::DistributedData; +using namespace OHOS::DistributedKv; + +static constexpr int32_t KEY_LENGTH = 32; +static constexpr int32_t TEST_USER_NUM = 0; +static constexpr const char *TEST_USER = "0"; +static constexpr const char *TEST_APP_ID = "KvdbServicePasswordTest"; +static constexpr const char *TEST_STORE_ID = "StoreTest"; + +class KvdbServicePasswordTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void) {} + void SetUp() {} + void TearDown() {} + + static std::vector Random(int32_t len); + + static AppId appId_; + static StoreId storeId_; + static StoreMetaData metaData_; + static std::shared_ptr kvdbServiceImpl_; +}; + +AppId KvdbServicePasswordTest::appId_; +StoreId KvdbServicePasswordTest::storeId_; +StoreMetaData KvdbServicePasswordTest::metaData_; +std::shared_ptr KvdbServicePasswordTest::kvdbServiceImpl_; + +void KvdbServicePasswordTest::SetUpTestCase(void) +{ + appId_ = { TEST_APP_ID }; + storeId_ = { TEST_STORE_ID }; + kvdbServiceImpl_ = std::make_shared(); + metaData_.deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + metaData_.bundleName = TEST_APP_ID; + metaData_.appId = TEST_APP_ID; + metaData_.storeId = TEST_STORE_ID; + metaData_.user = TEST_USER; + metaData_.area = Area::EL1; + metaData_.tokenId = IPCSkeleton::GetSelfTokenID(); + (void)CryptoManager::GetInstance().GenerateRootKey(); +} + +std::vector KvdbServicePasswordTest::Random(int32_t len) +{ + std::random_device randomDevice; + std::uniform_int_distribution distribution(0, std::numeric_limits::max()); + std::vector key(len); + for (uint32_t i = 0; i < len; i++) { + key[i] = static_cast(distribution(randomDevice)); + } + return key; +} + +/** +* @tc.name: GetBackupPasswordTest001 +* @tc.desc: get backup password with exception branch +* @tc.type: FUNC +*/ +HWTEST_F(KvdbServicePasswordTest, GetBackupPasswordTest001, TestSize.Level0) +{ + std::vector> passwords; + + auto status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::BACKUP_SECRET_KEY); + ASSERT_EQ(status, Status::ERROR); + + status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::SECRET_KEY); + ASSERT_EQ(status, Status::ERROR); + + status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::BUTTON); + ASSERT_EQ(status, Status::ERROR); + + std::shared_ptr dbStoreMock = std::make_shared(); + MetaDataManager::GetInstance().Initialize(dbStoreMock, nullptr, ""); + SecretKeyMetaData secretKey; + + auto result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_TRUE(result); + status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::SECRET_KEY); + ASSERT_EQ(status, Status::ERROR); + + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetCloneSecretKey(), secretKey, true); + ASSERT_TRUE(result); + status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::SECRET_KEY); + ASSERT_EQ(status, Status::ERROR); + + auto key = Random(KEY_LENGTH); + ASSERT_FALSE(key.empty()); + secretKey.sKey = key; + + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_TRUE(result); + status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::SECRET_KEY); + ASSERT_EQ(status, Status::ERROR); + + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetCloneSecretKey(), secretKey, true); + ASSERT_TRUE(result); + status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::SECRET_KEY); + ASSERT_EQ(status, Status::ERROR); + + MetaDataManager::GetInstance().DelMeta(metaData_.GetSecretKey(), true); + MetaDataManager::GetInstance().DelMeta(metaData_.GetCloneSecretKey(), true); +} + +/** +* @tc.name: GetBackupPasswordTest002 +* @tc.desc: get all type password success +* @tc.type: FUNC +*/ +HWTEST_F(KvdbServicePasswordTest, GetBackupPasswordTest002, TestSize.Level0) +{ + auto key = Random(KEY_LENGTH); + ASSERT_FALSE(key.empty()); + + std::shared_ptr dbStoreMock = std::make_shared(); + MetaDataManager::GetInstance().Initialize(dbStoreMock, nullptr, ""); + + CryptoManager::CryptoParams encryptParams; + auto encryptKey = CryptoManager::GetInstance().Encrypt(key, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + ASSERT_FALSE(encryptParams.nonce.empty()); + + SecretKeyMetaData secretKey; + secretKey.sKey = encryptKey; + secretKey.nonce = encryptParams.nonce; + std::vector> passwords; + + // 1.get backup secret key success + auto result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetBackupSecretKey(), secretKey, true); + ASSERT_TRUE(result); + auto status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::BACKUP_SECRET_KEY); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_GT(passwords.size(), 0); + ASSERT_EQ(passwords[0].size(), key.size()); + for (auto i = 0; i < key.size(); ++i) { + ASSERT_EQ(passwords[0][i], key[i]); + } + MetaDataManager::GetInstance().DelMeta(metaData_.GetBackupSecretKey(), true); + + // 2.get secret key success + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_TRUE(result); + status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::SECRET_KEY); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_GT(passwords.size(), 0); + ASSERT_EQ(passwords[0].size(), key.size()); + for (auto i = 0; i < key.size(); ++i) { + ASSERT_EQ(passwords[0][i], key[i]); + } + MetaDataManager::GetInstance().DelMeta(metaData_.GetSecretKey(), true); + + // 3.get clone secret key success + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetCloneSecretKey(), secretKey, true); + ASSERT_TRUE(result); + status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::SECRET_KEY); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_GT(passwords.size(), 0); + ASSERT_EQ(passwords[0].size(), key.size()); + for (auto i = 0; i < key.size(); ++i) { + ASSERT_EQ(passwords[0][i], key[i]); + } + MetaDataManager::GetInstance().DelMeta(metaData_.GetCloneSecretKey(), true); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_stub_unittest.cpp b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_stub_unittest.cpp index bf41f55f6faf39d9836303aaf99c8379dee3da02..0c6ffd876afc7ec0a7dbb00f1dbb475ea7408714 100644 --- a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_stub_unittest.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_stub_unittest.cpp @@ -34,8 +34,13 @@ using StoreId = OHOS::DistributedKv::StoreId; using AppId = OHOS::DistributedKv::AppId; using Options = OHOS::DistributedKv::Options; const std::u16string INTERFACE_TOKEN = u"OHOS.DistributedKv.IKvStoreDataService"; -static OHOS::DistributedKv::StoreId storeId = { "kvdb_test_storeid" }; -static OHOS::DistributedKv::AppId appId = { "ohos.test.kvdb" }; +static const StoreId STOREID = { "kvdb_test_storeid" }; +static const AppId APPID = { "kvdb_test_appid" }; +static const std::string HAPNAME = "testHap"; +static const std::string INVALID_HAPNAME = "./testHap"; +static const StoreId INVALID_STOREID = { "./kvdb_test_storeid" }; +static const AppId INVALID_APPID = { "\\kvdb_test_appid" }; + namespace OHOS::Test { namespace DistributedDataTest { class KVDBServiceStubTest : public testing::Test { @@ -149,35 +154,110 @@ HWTEST_F(KVDBServiceStubTest, CheckPermission001, TestSize.Level1) /** - * @tc.name: OnBeforeCreate + * @tc.name: OnBeforeCreate001 * @tc.desc: Test OnBeforeCreate * @tc.type: FUNC * @tc.require: */ -HWTEST_F(KVDBServiceStubTest, OnBeforeCreate, TestSize.Level1) +HWTEST_F(KVDBServiceStubTest, OnBeforeCreate001, TestSize.Level1) { MessageParcel data; + data.WriteInterfaceToken(INTERFACE_TOKEN); MessageParcel reply; - AppId appId = {"testApp"}; - StoreId storeId = {"testStoreId"}; - auto status = kvdbServiceStub->OnBeforeCreate(appId, storeId, data, reply); + Options options; + options.hapName = HAPNAME; + ITypesUtil::Marshal(data, options); + auto status = kvdbServiceStub->OnBeforeCreate(APPID, STOREID, data, reply); + EXPECT_EQ(status, IPC_STUB_INVALID_DATA_ERR); +} + +/** + * @tc.name: OnBeforeCreate002 + * @tc.desc: Test OnBeforeCreate + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(KVDBServiceStubTest, OnBeforeCreate002, TestSize.Level1) +{ + MessageParcel data; + data.WriteInterfaceToken(INTERFACE_TOKEN); + MessageParcel reply; + Options options; + options.hapName = HAPNAME; + ITypesUtil::Marshal(data, options); + auto status = kvdbServiceStub->OnBeforeCreate(INVALID_APPID, INVALID_STOREID, data, reply); + EXPECT_EQ(status, IPC_STUB_INVALID_DATA_ERR); +} + +/** + * @tc.name: OnBeforeCreate003 + * @tc.desc: Test OnBeforeCreate + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(KVDBServiceStubTest, OnBeforeCreate003, TestSize.Level1) +{ + MessageParcel data; + data.WriteInterfaceToken(INTERFACE_TOKEN); + MessageParcel reply; + Options options; + options.hapName = INVALID_HAPNAME; + ITypesUtil::Marshal(data, options); + auto status = kvdbServiceStub->OnBeforeCreate(APPID, STOREID, data, reply); EXPECT_EQ(status, IPC_STUB_INVALID_DATA_ERR); } /** - * @tc.name: OnAfterCreate + * @tc.name: OnAfterCreate001 * @tc.desc: Test OnAfterCreate * @tc.type: FUNC * @tc.require: */ -HWTEST_F(KVDBServiceStubTest, OnAfterCreate, TestSize.Level1) +HWTEST_F(KVDBServiceStubTest, OnAfterCreate001, TestSize.Level1) { MessageParcel data; data.WriteInterfaceToken(INTERFACE_TOKEN); MessageParcel reply; - AppId appId = {"testApp"}; - StoreId storeId = {"testStore"}; - auto status = kvdbServiceStub->OnAfterCreate(appId, storeId, data, reply); + Options options; + options.hapName = HAPNAME; + ITypesUtil::Marshal(data, options); + auto status = kvdbServiceStub->OnAfterCreate(APPID, STOREID, data, reply); + EXPECT_EQ(status, IPC_STUB_INVALID_DATA_ERR); +} + +/** + * @tc.name: OnAfterCreate002 + * @tc.desc: Test OnAfterCreate + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(KVDBServiceStubTest, OnAfterCreate002, TestSize.Level1) +{ + MessageParcel data; + data.WriteInterfaceToken(INTERFACE_TOKEN); + MessageParcel reply; + Options options; + options.hapName = HAPNAME; + ITypesUtil::Marshal(data, options); + auto status = kvdbServiceStub->OnAfterCreate(INVALID_APPID, INVALID_STOREID, data, reply); + EXPECT_EQ(status, IPC_STUB_INVALID_DATA_ERR); +} + +/** + * @tc.name: OnAfterCreate003 + * @tc.desc: Test OnAfterCreate + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(KVDBServiceStubTest, OnAfterCreate003, TestSize.Level1) +{ + MessageParcel data; + data.WriteInterfaceToken(INTERFACE_TOKEN); + MessageParcel reply; + Options options; + options.hapName = INVALID_HAPNAME; + ITypesUtil::Marshal(data, options); + auto status = kvdbServiceStub->OnAfterCreate(APPID, STOREID, data, reply); EXPECT_EQ(status, IPC_STUB_INVALID_DATA_ERR); } @@ -350,5 +430,37 @@ HWTEST_F(KVDBServiceStubTest, OnRemoveDeviceData, TestSize.Level1) auto status = kvdbServiceStub->OnRemoveDeviceData(appId, storeId, data, reply); EXPECT_EQ(status, IPC_STUB_INVALID_DATA_ERR); } + +/** + * @tc.name: IsValidField001 + * @tc.desc: IsValidField function test. + * @tc.type: FUNC + */ +HWTEST_F(KVDBServiceStubTest, IsValidField001, TestSize.Level0) +{ + EXPECT_TRUE(kvdbServiceStub->IsValidField("validpath")); + EXPECT_TRUE(kvdbServiceStub->IsValidField("another_valid_path")); + EXPECT_TRUE(kvdbServiceStub->IsValidField("file123")); +} + +/** + * @tc.name: IsValidField002 + * @tc.desc: IsValidField function test. + * @tc.type: FUNC + */ +HWTEST_F(KVDBServiceStubTest, IsValidField002, TestSize.Level0) +{ + EXPECT_FALSE(kvdbServiceStub->IsValidField("path/with/forward/slash")); + EXPECT_FALSE(kvdbServiceStub->IsValidField("/starting/slash")); + EXPECT_FALSE(kvdbServiceStub->IsValidField("ending/slash/")); + EXPECT_FALSE(kvdbServiceStub->IsValidField("path\\with\\backslash")); + EXPECT_FALSE(kvdbServiceStub->IsValidField("\\starting\\ending")); + EXPECT_FALSE(kvdbServiceStub->IsValidField("ending\\")); + EXPECT_FALSE(kvdbServiceStub->IsValidField("..")); + EXPECT_FALSE(kvdbServiceStub->IsValidField("path/with\\mixed/slashes")); + EXPECT_FALSE(kvdbServiceStub->IsValidField("path\\with/mixed\\slashes")); +} + + } // namespace DistributedDataTest } // 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 index c1a589f439bd16f178a30446e2cf5cef48197e2b..1ae56025947e8ab5f114e3195f4907e9d839a914 100644 --- a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_test.cpp @@ -18,7 +18,7 @@ #include "auth_delegate.h" #include "bootstrap.h" #include "change_notification.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter.h" #include "directory/directory_manager.h" #include "ikvstore_observer.h" diff --git a/datamgr_service/services/distributeddataservice/service/test/meta_data_test.cpp b/datamgr_service/services/distributeddataservice/service/test/meta_data_test.cpp index 1476b51da173f08faecbd5dddc7b7194ab80c5a6..714fd0b53a5762941758766da8045c2ab1ac4330 100644 --- a/datamgr_service/services/distributeddataservice/service/test/meta_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/meta_data_test.cpp @@ -29,6 +29,7 @@ #include "metadata/store_meta_data_local.h" #include "nativetoken_kit.h" #include "token_setproc.h" +#include "directory/directory_manager.h" using namespace testing::ext; using namespace OHOS::DistributedData; using namespace OHOS::Security::AccessToken; @@ -120,6 +121,8 @@ void MetaDataTest::SetUp() metaData_.instanceId = GetInstIndex(metaData_.tokenId, appId); metaData_.version = 1; MetaDataManager::GetInstance().DelMeta(metaData_.GetKey()); + metaData_.area = options_.area; + metaData_.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData_); } void MetaDataTest::TearDown() {} @@ -138,7 +141,7 @@ HWTEST_F(MetaDataTest, SaveLoadMateData, TestSize.Level0) std::vector password {}; auto status = kvdbServiceImpl_->AfterCreate(appId, storeId, options_, password); ASSERT_EQ(status, Status::SUCCESS); - ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetKey(), metaData)); + ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetKeyWithoutPath(), metaData)); ASSERT_TRUE(metaData.isNeedCompress); } @@ -157,9 +160,9 @@ HWTEST_F(MetaDataTest, MateDataChanged, TestSize.Level0) std::vector password {}; auto status = kvdbServiceImpl_->AfterCreate(appId, storeId, options_, password); ASSERT_EQ(status, Status::SUCCESS); - ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetKey(), metaData)); + ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetKeyWithoutPath(), metaData)); ASSERT_FALSE(metaData.isNeedCompress); - ASSERT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData_.GetKey())); + ASSERT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath())); } } // namespace DistributedDataTest } // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/mock/BUILD.gn index a0833e470a485f26a5a540bfc38bd331c749e4b4..10ea0e49325847be0bbc7feaa0e898980fa878cd 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/mock/BUILD.gn @@ -18,6 +18,8 @@ config("module_private_config") { include_dirs = [ "${data_service_path}/adapter/include/communicator", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/matrix/include/", "../../../framework/include/", "../../../service/rdb/", "./", @@ -27,6 +29,7 @@ config("module_private_config") { } ohos_static_library("distributeddata_mock_static") { + testonly = true branch_protector_ret = "pac_ret" sanitize = { cfi = true @@ -35,18 +38,26 @@ ohos_static_library("distributeddata_mock_static") { } sources = [ + "auth_delegate_mock.cpp", "cursor_mock.cpp", "db_change_data_mock.cpp", "db_store_mock.cpp", + "device_manager_adapter_mock.cpp", "general_store_mock.cpp", "kv_store_nb_delegate_mock.cpp", "network_delegate_mock.cpp", "screen_lock_mock.cpp", + "user_delegate_mock.cpp", + "device_matrix_mock.cpp", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] external_deps = [ + "device_manager:devicemanagersdk", + "googletest:gmock", + "googletest:gtest", + "json:nlohmann_json_static", "kv_store:distributeddata_mgr", "kv_store:distributeddb", "relational_store:native_rdb", diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/access_token_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/access_token_mock.cpp index 0f70c3f394dab187077ba3d8e5d340e838c3201e..e3e5addd42222f635eccf12f433818298618295d 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/access_token_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/access_token_mock.cpp @@ -19,14 +19,30 @@ namespace Security { namespace AccessToken { ATokenTypeEnum AccessTokenKit::GetTokenTypeFlag(AccessTokenID tokenID) { + if (BAccessTokenKit::accessTokenkit == nullptr) { + return ATokenTypeEnum::TOKEN_INVALID; + } return BAccessTokenKit::accessTokenkit->GetTokenTypeFlag(tokenID); } +ATokenTypeEnum AccessTokenKit::GetTokenType(AccessTokenID tokenID) +{ + if (BAccessTokenKit::accessTokenkit == nullptr) { + return ATokenTypeEnum::TOKEN_INVALID; + } + return BAccessTokenKit::accessTokenkit->GetTokenType(tokenID); +} + int AccessTokenKit::GetHapTokenInfo(AccessTokenID tokenID, HapTokenInfo& hapTokenInfoRes) { return BAccessTokenKit::accessTokenkit->GetHapTokenInfo(tokenID, hapTokenInfoRes); } +int AccessTokenKit::GetNativeTokenInfo(AccessTokenID tokenID, NativeTokenInfo& nativeTokenInfo) +{ + return BAccessTokenKit::accessTokenkit->GetNativeTokenInfo(tokenID, nativeTokenInfo); +} + int AccessTokenKit::VerifyAccessToken(AccessTokenID tokenID, const std::string& permissionName) { return BAccessTokenKit::accessTokenkit->VerifyAccessToken(tokenID, permissionName); diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/access_token_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/access_token_mock.h index dd6e20e286f1ccbf7f07fdd5b2f991c341a9ea0e..e02b6d0d408bf3a3db3e495dfffac47240e60c17 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/access_token_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/access_token_mock.h @@ -25,7 +25,9 @@ namespace AccessToken { class BAccessTokenKit { public: virtual ATokenTypeEnum GetTokenTypeFlag(AccessTokenID) = 0; + virtual ATokenTypeEnum GetTokenType(AccessTokenID) = 0; virtual int GetHapTokenInfo(AccessTokenID, HapTokenInfo&) = 0; + virtual int GetNativeTokenInfo(AccessTokenID, NativeTokenInfo&) = 0; virtual int VerifyAccessToken(AccessTokenID, const std::string&) = 0; BAccessTokenKit() = default; virtual ~BAccessTokenKit() = default; @@ -36,7 +38,9 @@ private: class AccessTokenKitMock : public BAccessTokenKit { public: MOCK_METHOD(ATokenTypeEnum, GetTokenTypeFlag, (AccessTokenID)); + MOCK_METHOD(ATokenTypeEnum, GetTokenType, (AccessTokenID)); MOCK_METHOD(int, GetHapTokenInfo, (AccessTokenID, HapTokenInfo&)); + MOCK_METHOD(int, GetNativeTokenInfo, (AccessTokenID, NativeTokenInfo&)); MOCK_METHOD(int, VerifyAccessToken, (AccessTokenID, const std::string&)); }; } diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/account_delegate_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/account_delegate_mock.cpp index 1f4b6d5ea198e6d2d3380cd29a9354e447769140..011d0d2f2bcef9c904e68c2f4b40b5cf458739d4 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/account_delegate_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/account_delegate_mock.cpp @@ -30,7 +30,7 @@ bool AccountDelegate::RegisterAccountInstance(AccountDelegate *instance) AccountDelegate *AccountDelegate::GetInstance() { - return &(AccountDelegateMock::Init()); + return instance_; } } // namespace DistributedData } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/account_delegate_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/account_delegate_mock.h index fe8af6baf5fb018464973437063545139404046c..a2ca487c8e7fcf5702057ee6180e972ba4aaebcc 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/account_delegate_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/account_delegate_mock.h @@ -18,17 +18,12 @@ #include #include -#include "account_delegate.h" +#include "account/account_delegate.h" namespace OHOS { namespace DistributedData { class AccountDelegateMock : public AccountDelegate { public: virtual ~AccountDelegateMock() = default; - static AccountDelegateMock& Init() - { - static AccountDelegateMock instance; - return instance; - } MOCK_METHOD(int32_t, Subscribe, (std::shared_ptr)); MOCK_METHOD(int32_t, Unsubscribe, (std::shared_ptr)); MOCK_METHOD(std::string, GetCurrentAccountId, (), (const)); diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/auth_delegate_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/auth_delegate_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d1cf72bf6fce41841379beac07ddf35ee8e4d55 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/auth_delegate_mock.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 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 "auth_delegate_mock.h" + +namespace OHOS { +namespace DistributedData { + +AuthHandler *AuthDelegate::GetInstance() +{ + return &(AuthHandlerMock::GetInstance()); +} +} // namespace DistributedData +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/auth_delegate_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/auth_delegate_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..4524aec56731e6b9c2c8a780b7611f98a4cd13ce --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/auth_delegate_mock.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 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_AUTH_DELEGATE_MOCK_H +#define OHOS_DISTRIBUTEDDATA_AUTH_DELEGATE_MOCK_H + +#include + +#include + +#include "auth_delegate.h" +namespace OHOS { +namespace DistributedData { +class AuthHandlerMock : public AuthHandler { +public: + static AuthHandlerMock &GetInstance() + { + static AuthHandlerMock instance; + return instance; + } + MOCK_METHOD((std::pair), CheckAccess, + (int localUserId, int peerUserId, const std::string &peerDeviceId, const AclParams &aclParams), (override)); +}; +} // namespace DistributedData +} // namespace OHOS +#endif // OHOS_DISTRIBUTEDDATA_AUTH_DELEGATE_MOCK_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/checker_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/checker_mock.cpp index 22a2e748e70e572a9a93a3a23c773700e2c96a67..4adc8baa74114c3f3a617c2eab73beedc64e8f63 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/checker_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/checker_mock.cpp @@ -47,7 +47,7 @@ std::string CheckerMock::GetAppId(const CheckerManager::StoreInfo &info) bool CheckerMock::IsValid(const CheckerManager::StoreInfo &info) { - return true; + return !info.bundleName.empty(); } bool CheckerMock::SetDistrustInfo(const CheckerManager::Distrust &distrust) diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/cloud_db_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/cloud_db_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..effbcc86aefd8f5c0b866ba7794c375e2468c436 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/cloud_db_mock.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2025 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_CLOUD_DB_MOCK_H +#define OHOS_DISTRIBUTEDDATA_SERVICE_CLOUD_DB_MOCK_H + +#include + +#include "cloud/cloud_db.h" + +namespace OHOS::DistributedData { + +class MockCloudDB : public CloudDB { +public: + using Watcher = GeneralWatcher; + using Async = std::function>)>; + using Devices = std::vector; + + MOCK_METHOD(int32_t, Execute, (const std::string &, const std::string &, const VBucket &), (override)); + MOCK_METHOD(int32_t, BatchInsert, (const std::string &, VBuckets &&, VBuckets &), (override)); + MOCK_METHOD(int32_t, BatchUpdate, (const std::string &, VBuckets &&, VBuckets &), (override)); + MOCK_METHOD(int32_t, BatchUpdate, (const std::string &, VBuckets &&, const VBuckets &), (override)); + MOCK_METHOD(int32_t, BatchDelete, (const std::string &, VBuckets &), (override)); + MOCK_METHOD( + (std::pair>), Query, (const std::string &, const VBucket &), (override)); + MOCK_METHOD((std::pair>), Query, (GenQuery &, const VBucket &), (override)); + MOCK_METHOD(int32_t, PreSharing, (const std::string &, VBuckets &), (override)); + MOCK_METHOD(int32_t, Sync, (const Devices &, int32_t, const GenQuery &, Async, int32_t), (override)); + MOCK_METHOD(int32_t, Watch, (int32_t, Watcher &), (override)); + MOCK_METHOD(int32_t, Unwatch, (int32_t, Watcher &), (override)); + MOCK_METHOD(int32_t, Lock, (), (override)); + MOCK_METHOD(int32_t, Heartbeat, (), (override)); + MOCK_METHOD(int32_t, Unlock, (), (override)); + MOCK_METHOD(int64_t, AliveTime, (), (override)); + MOCK_METHOD(int32_t, Close, (), (override)); + MOCK_METHOD((std::pair), GetEmptyCursor, (const std::string &), (override)); + MOCK_METHOD(void, SetPrepareTraceId, (const std::string &), (override)); +}; +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTEDDATA_SERVICE_CLOUD_DB_MOCK_H diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/config_factory_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/config_factory_mock.cpp index aa685cd255a9b3a07fbb254a8bcf571f2a7df11b..e38c560df8304ebd8efeb7f6f70e565160f9a262 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/config_factory_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/config_factory_mock.cpp @@ -81,5 +81,10 @@ ThreadConfig *ConfigFactory::GetThreadConfig() { return nullptr; } + +DataShareConfig *ConfigFactory::GetDataShareConfig() +{ + return nullptr; +} } // namespace DistributedData } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/cursor_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/cursor_mock.h index c63bdacc07e7f0ecb790e23e8a881339105c97d3..57be55a6fbef71f9e58a4a8be84bffedff7ea4e5 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/cursor_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/cursor_mock.h @@ -14,6 +14,8 @@ */ #ifndef OHOS_DISTRIBUTEDDATA_SERVICE_TEST_CURSOR_MOCK_H #define OHOS_DISTRIBUTEDDATA_SERVICE_TEST_CURSOR_MOCK_H +#include + #include #include #include @@ -45,6 +47,22 @@ private: std::shared_ptr resultSet_; int32_t index_ = 0; }; + +class MockCursor : public DistributedData::Cursor { + MOCK_METHOD(int32_t, GetColumnNames, (std::vector &names), (const, override)); + MOCK_METHOD(int32_t, GetColumnName, (int32_t col, std::string &name), (const, override)); + MOCK_METHOD(int32_t, GetColumnType, (int32_t col), (const, override)); + MOCK_METHOD(int32_t, GetCount, (), (const, override)); + MOCK_METHOD(int32_t, MoveToFirst, (), (override)); + MOCK_METHOD(int32_t, MoveToNext, (), (override)); + MOCK_METHOD(int32_t, MoveToPrev, (), (override)); + MOCK_METHOD(int32_t, GetEntry, (VBucket &entry), (override)); + MOCK_METHOD(int32_t, GetRow, (VBucket &data), (override)); + MOCK_METHOD(int32_t, Get, (int32_t col, Value &value), (override)); + MOCK_METHOD(int32_t, Get, (const std::string &col, Value &value), (override)); + MOCK_METHOD(int32_t, Close, (), (override)); + MOCK_METHOD(bool, IsEnd, (), (override)); +}; } // namespace DistributedData } // namespace OHOS #endif // OHOS_DISTRIBUTEDDATA_SERVICE_TEST_CURSOR_MOCK_H 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 84c31cd22a788bf49a6cd6c1a154607ac8d599b4..b4af1df82ed532eb81b78ca65e19abd843a2632b 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 @@ -382,6 +382,12 @@ DBStatus DBStoreMock::Sync(const DeviceSyncOption &option, const DeviceSyncProce return NOT_SUPPORT; } +DBStatus DBStoreMock::Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete) +{ + return NOT_SUPPORT; +} + DBStatus DBStoreMock::CancelSync(uint32_t syncId) { return NOT_SUPPORT; diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.h index 5c7e0ff325d364389a1ae0027cbeecac8f064775..d26dddec3b657a5669b4e4fb5174a0bcce586968 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.h @@ -115,6 +115,8 @@ public: DBStatus SetReceiveDataInterceptor(const DataInterceptor &interceptor) override; DBStatus GetDeviceEntries(const std::string &device, std::vector &entries) const override; DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) override; + DBStatus Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete) override; DBStatus CancelSync(uint32_t syncId) override; DatabaseStatus GetDatabaseStatus() const override; private: diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/device_manager_adapter_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/device_manager_adapter_mock.cpp index fae2fb0f5b4ad18d66ff077998b8acae8fe57ea6..f6da6ffa3799278e918a9cc1e14bb16d9b5c2b5a 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/device_manager_adapter_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/device_manager_adapter_mock.cpp @@ -34,6 +34,23 @@ std::vector OHOS::DistributedData::DeviceManagerAdapter::ToUUID(std return BDeviceManagerAdapter::deviceManagerAdapter->ToUUID(devices); } +std::vector OHOS::DistributedData::DeviceManagerAdapter::ToUUID(const std::vector &devices) +{ + if (BDeviceManagerAdapter::deviceManagerAdapter == nullptr) { + std::vector vec; + return vec; + } + return BDeviceManagerAdapter::deviceManagerAdapter->ToUUID(devices); +} + +std::string OHOS::DistributedData::DeviceManagerAdapter::ToUUID(const std::string &id) +{ + if (BDeviceManagerAdapter::deviceManagerAdapter == nullptr) { + return id; + } + return BDeviceManagerAdapter::deviceManagerAdapter->ToUUID(id); +} + bool OHOS::DistributedData::DeviceManagerAdapter::IsOHOSType(const std::string &id) { if (BDeviceManagerAdapter::deviceManagerAdapter == nullptr) { @@ -50,6 +67,14 @@ bool DeviceManagerAdapter::IsSameAccount(const AccessCaller &accCaller, const Ac return BDeviceManagerAdapter::deviceManagerAdapter->IsSameAccount(accCaller, accCallee); } +bool DeviceManagerAdapter::IsSameAccount(const std::string &devicdId) +{ + if (BDeviceManagerAdapter::deviceManagerAdapter == nullptr) { + return false; + } + return BDeviceManagerAdapter::deviceManagerAdapter->IsSameAccount(devicdId); +} + bool DeviceManagerAdapter::CheckAccessControl(const AccessCaller &accCaller, const AccessCallee &accCallee) { if (BDeviceManagerAdapter::deviceManagerAdapter == nullptr) { @@ -118,6 +143,15 @@ std::string OHOS::DistributedData::DeviceManagerAdapter::ToNetworkID(const std:: return BDeviceManagerAdapter::deviceManagerAdapter->ToNetworkID(id); } +std::string OHOS::DistributedData::DeviceManagerAdapter::CalcClientUuid( + const std::string &appId, const std::string &uuid) +{ + if (BDeviceManagerAdapter::deviceManagerAdapter == nullptr) { + return " "; + } + return BDeviceManagerAdapter::deviceManagerAdapter->CalcClientUuid(appId, uuid); +} + DeviceManagerAdapter::~DeviceManagerAdapter() { } diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/device_manager_adapter_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/device_manager_adapter_mock.h index abdef014c65332ad871d74678ba752e744016d47..126862436d07d99533d64058f772823753b222e6 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/device_manager_adapter_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/device_manager_adapter_mock.h @@ -16,8 +16,9 @@ #define OHOS_DISTRIBUTEDDATA_SERVICE_TEST_BDEVICE_MANAGER_ADAPTER_MOCK_H #include -#include "device_manager_adapter.h" + #include "commu_types.h" +#include "device_manager_adapter.h" namespace OHOS { namespace DistributedData { @@ -30,14 +31,18 @@ public: virtual std::vector GetRemoteDevices() = 0; virtual bool IsOHOSType(const std::string &) = 0; virtual std::vector ToUUID(std::vector) = 0; + virtual std::vector ToUUID(const std::vector &) = 0; + virtual std::string ToUUID(const std::string &) = 0; virtual Status StartWatchDeviceChange(const AppDeviceChangeListener *, const PipeInfo &) = 0; virtual Status StopWatchDeviceChange(const AppDeviceChangeListener *, const PipeInfo &) = 0; virtual bool IsSameAccount(const AccessCaller &, const AccessCallee &) = 0; - virtual std::string GetUuidByNetworkId(const std::string &) = 0; - virtual DeviceInfo GetDeviceInfo(const std::string &) = 0; - virtual std::string ToNetworkID(const std::string &) = 0; + virtual bool IsSameAccount(const std::string &) = 0; + virtual std::string GetUuidByNetworkId(const std::string &); + virtual DeviceInfo GetDeviceInfo(const std::string &); + virtual std::string ToNetworkID(const std::string &); virtual bool CheckAccessControl(const AccessCaller &, const AccessCallee &) = 0; virtual DeviceInfo GetLocalDevice() = 0; + virtual std::string CalcClientUuid(const std::string &appId, const std::string &uuid) = 0; static inline std::shared_ptr deviceManagerAdapter = nullptr; BDeviceManagerAdapter() = default; virtual ~BDeviceManagerAdapter() = default; @@ -45,17 +50,21 @@ public: class DeviceManagerAdapterMock : public BDeviceManagerAdapter { public: - MOCK_METHOD0(GetRemoteDevices, std::vector()); - MOCK_METHOD1(IsOHOSType, bool(const std::string &)); - MOCK_METHOD1(ToUUID, std::vector(std::vector)); - MOCK_METHOD2(StartWatchDeviceChange, Status(const AppDeviceChangeListener *, const PipeInfo &)); - MOCK_METHOD2(StopWatchDeviceChange, Status(const AppDeviceChangeListener *, const PipeInfo &)); - MOCK_METHOD2(IsSameAccount, bool(const AccessCaller &, const AccessCallee &)); - MOCK_METHOD1(GetUuidByNetworkId,std::string(const std::string &)); - MOCK_METHOD1(GetDeviceInfo, DeviceInfo(const std::string &)); - MOCK_METHOD1(ToNetworkID, std::string(const std::string &)); - MOCK_METHOD2(CheckAccessControl, bool(const AccessCaller &, const AccessCallee &)); - MOCK_METHOD0(GetLocalDevice, DeviceInfo()); + MOCK_METHOD(std::vector, GetRemoteDevices, ()); + MOCK_METHOD(bool, IsOHOSType, (const std::string &)); + MOCK_METHOD((std::vector), ToUUID, (std::vector)); + MOCK_METHOD((std::vector), ToUUID, (const std::vector &)); + MOCK_METHOD(std::string, ToUUID, (const std::string &)); + MOCK_METHOD(Status, StartWatchDeviceChange, (const AppDeviceChangeListener *, const PipeInfo &)); + MOCK_METHOD(Status, StopWatchDeviceChange, (const AppDeviceChangeListener *, const PipeInfo &)); + MOCK_METHOD(bool, IsSameAccount, (const AccessCaller &, const AccessCallee &)); + MOCK_METHOD(bool, IsSameAccount, (const std::string &)); + MOCK_METHOD(std::string, GetUuidByNetworkId, (const std::string &)); + MOCK_METHOD(DeviceInfo, GetDeviceInfo, (const std::string &)); + MOCK_METHOD(std::string, ToNetworkID, (const std::string &)); + MOCK_METHOD(bool, CheckAccessControl, (const AccessCaller &, const AccessCallee &)); + MOCK_METHOD(DeviceInfo, GetLocalDevice, ()); + MOCK_METHOD(std::string, CalcClientUuid, (const std::string &, const std::string &)); }; } // namespace DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/device_matrix_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/device_matrix_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4cba3f3351f0e18a2163990654820e7f5ea7ecdb --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/device_matrix_mock.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 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 "device_matrix_mock.h" + +namespace OHOS { +namespace DistributedData { +std::pair DeviceMatrix::GetRemoteMask(const std::string &device, DeviceMatrix::LevelType type) +{ + return BDeviceMatrix::deviceMatrix->GetRemoteMask(device, type); +} + +std::pair DeviceMatrix::GetMask(const std::string &device, DeviceMatrix::LevelType type) +{ + return BDeviceMatrix::deviceMatrix->GetMask(device, type); +} +} // namespace DistributedData +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/device_matrix_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/device_matrix_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..f67eb94ca23d8dd2ea61e15a8d19e3330fcd0d99 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/device_matrix_mock.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 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_DEVICE_MATRIX_MOCK_H +#define OHOS_DEVICE_MATRIX_MOCK_H + +#include + +#include "device_matrix.h" + +namespace OHOS::DistributedData { +class BDeviceMatrix { +public: + virtual std::pair GetMask(const std::string &, DeviceMatrix::LevelType); + virtual std::pair GetRemoteMask(const std::string &, DeviceMatrix::LevelType); + BDeviceMatrix() = default; + virtual ~BDeviceMatrix() = default; + static inline std::shared_ptr deviceMatrix = nullptr; +}; +class DeviceMatrixMock : public BDeviceMatrix { +public: + MOCK_METHOD((std::pair), GetMask, (const std::string &, DeviceMatrix::LevelType), (override)); + MOCK_METHOD((std::pair), GetRemoteMask, (const std::string &, DeviceMatrix::LevelType), (override)); +}; +} // namespace OHOS::DistributedData +#endif //OHOS_DEVICE_MATRIX_MOCK_H diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/distributed_file_daemon_manager_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/distributed_file_daemon_manager_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d6a44ed9d234259de04f9a2077345fb1fb6aab6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/distributed_file_daemon_manager_mock.cpp @@ -0,0 +1,45 @@ +///* +// * Copyright (c) 2025 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 "distributed_file_daemon_manager_mock.h" +// +//namespace OHOS { +//namespace Storage { +//namespace DistributedFile { +//constexpr const int32_t ERROR = -1; +// +//DistributedFileDaemonManager &DistributedFileDaemonManager::GetInstance() +//{ +// return DistributedFileDaemonManagerImpl::GetInstance(); +//} +// +//int32_t DistributedFileDaemonManagerImpl::RegisterAssetCallback(const sptr &recvCallback) +//{ +// if (BDistributedFileDaemonManager::fileDaemonManger_ == nullptr) { +// return ERROR; +// } +// return BDistributedFileDaemonManager::fileDaemonManger_->RegisterAssetCallback(recvCallback); +//} +// +//int32_t DistributedFileDaemonManagerImpl::UnRegisterAssetCallback(const sptr &recvCallback) +//{ +// if (BDistributedFileDaemonManager::fileDaemonManger_ == nullptr) { +// return ERROR; +// } +// return BDistributedFileDaemonManager::fileDaemonManger_->UnRegisterAssetCallback(recvCallback); +//} +//} // namespace DistributedFile +//} // namespace Storage +//} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/distributed_file_daemon_manager_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/distributed_file_daemon_manager_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..b1d66ad0377de72d230697a07fa7297d4c8ff703 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/distributed_file_daemon_manager_mock.h @@ -0,0 +1,122 @@ +///* +// * Copyright (c) 2025 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_FILE_DAEMON_MANAGER_MOCK_H +//#define OHOS_DISTRIBUTED_FILE_DAEMON_MANAGER_MOCK_H +// +//#include +// +//#include "distributed_file_daemon_manager.h" +//namespace OHOS { +//namespace Storage { +//namespace DistributedFile { +//class BDistributedFileDaemonManager { +//public: +// virtual int32_t RegisterAssetCallback(const sptr &recvCallback) = 0; +// virtual int32_t UnRegisterAssetCallback(const sptr &recvCallback) = 0; +// BDistributedFileDaemonManager() = default; +// virtual ~BDistributedFileDaemonManager() = default; +// +//private: +// static inline std::shared_ptr fileDaemonManger_ = nullptr; +//}; +// +//class DistributedFileDaemonManagerMock : public BDistributedFileDaemonManager { +//public: +// MOCK_METHOD(int32_t, RegisterAssetCallback, (const sptr &recvCallback)); +// MOCK_METHOD(int32_t, UnRegisterAssetCallback, (const sptr &recvCallback)); +//}; +// +//class DistributedFileDaemonManagerImpl : public DistributedFileDaemonManager { +//public: +// static DistributedFileDaemonManagerImpl &GetInstance() +// { +// static DistributedFileDaemonManagerImpl instance; +// return instance; +// } +// int32_t RegisterAssetCallback(const sptr &recvCallback) override; +// int32_t UnRegisterAssetCallback(const sptr &recvCallback) override; +// +// int32_t OpenP2PConnection(const DistributedHardware::DmDeviceInfo &deviceInfo) override +// { +// return 0; +// } +// int32_t CloseP2PConnection(const DistributedHardware::DmDeviceInfo &deviceInfo) override +// { +// return 0; +// } +// int32_t OpenP2PConnectionEx(const std::string &networkId, sptr remoteReverseObj) override +// { +// return 0; +// } +// int32_t CloseP2PConnectionEx(const std::string &networkId) override +// { +// return 0; +// } +// int32_t PrepareSession(const std::string &srcUri, const std::string &dstUri, const std::string &srcDeviceId, +// const sptr &listener, HmdfsInfo &info) override +// { +// return 0; +// } +// int32_t CancelCopyTask(const std::string &sessionName) override +// { +// return 0; +// } +// int32_t CancelCopyTask(const std::string &srcUri, const std::string &dstUri) override +// { +// return 0; +// } +// +// int32_t PushAsset(int32_t userId, const sptr &assetObj, +// const sptr &sendCallback) override +// { +// return 0; +// } +// int32_t GetSize(const std::string &uri, bool isSrcUri, uint64_t &size) override +// { +// return 0; +// } +// int32_t IsDirectory(const std::string &uri, bool isSrcUri, bool &isDirectory) override +// { +// return 0; +// } +// int32_t Copy(const std::string &srcUri, const std::string &destUri, ProcessCallback processCallback) override +// { +// return 0; +// } +// int32_t Cancel(const std::string &srcUri, const std::string &destUri) override +// { +// return 0; +// } +// int32_t Cancel() override +// { +// return 0; +// } +// int32_t GetDfsSwitchStatus(const std::string &networkId, int32_t &switchStatus) override +// { +// return 0; +// } +// int32_t UpdateDfsSwitchStatus(int32_t switchStatus) override +// { +// return 0; +// } +// int32_t GetConnectedDeviceList(std::vector &deviceList) override +// { +// return 0; +// } +//}; +//} // namespace DistributedFile +//} // namespace Storage +//} // namespace OHOS +//#endif \ No newline at end of file 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 89e80c6e9922544ed16131a492dd397265128d32..d64553714099c16e369cb5199fe51126d3c46eb2 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 @@ -41,14 +41,14 @@ int32_t GeneralStoreMock::Execute(const std::string &table, const std::string &s return 0; } -int32_t GeneralStoreMock::SetDistributedTables(const std::vector &tables, int32_t type, - const std::vector &references) +int32_t GeneralStoreMock::SetDistributedTables( + const std::vector &tables, int32_t type, const std::vector &references) { return 0; } -int32_t GeneralStoreMock::SetTrackerTable(const std::string &tableName, const std::set &trackerColNames, - const std::set &extendColNames, bool isForceUpgrade) +int32_t GeneralStoreMock::SetTrackerTable(const std::string &tableName, + const std::set &trackerColNames, const std::set &extendColNames, bool isForceUpgrade) { return 0; } @@ -76,18 +76,18 @@ int32_t GeneralStoreMock::Delete(const std::string &table, const std::string &sq std::pair> GeneralStoreMock::Query(const std::string &table, GenQuery &query) { - return { GeneralError::E_NOT_SUPPORT, nullptr }; + return {GeneralError::E_NOT_SUPPORT, nullptr}; } -std::pair GeneralStoreMock::Sync(const Devices &devices, GenQuery &query, DetailAsync async, - const SyncParam &syncParm) +std::pair GeneralStoreMock::Sync(const Devices &devices, GenQuery &query, + DetailAsync async, const SyncParam &syncParm) { return { GeneralError::E_OK, 0 }; } std::pair> GeneralStoreMock::PreSharing(GenQuery &query) { - return { GeneralError::E_NOT_SUPPORT, nullptr }; + return {GeneralError::E_NOT_SUPPORT, nullptr}; } int32_t GeneralStoreMock::Clean(const std::vector &devices, int32_t mode, const std::string &tableName) @@ -148,7 +148,7 @@ int32_t GeneralStoreMock::CleanTrackerData(const std::string &tableName, int64_t std::pair> GeneralStoreMock::Query(const std::string &table, const std::string &sql, Values &&args) { - return { GeneralError::E_OK, cursor_ }; + return {GeneralError::E_OK, cursor_}; } void GeneralStoreMock::MakeCursor(const std::map &entry) 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 index e4ec970be4f9a7c68604566ab31385f642e57bc0..5b9f480b25361be205513079de966088232d1281 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.cpp @@ -25,8 +25,32 @@ std::vector MockQuery::GetTables() return tables_; } +const std::string GetStatement() +{ + return "AS distributed_log"; +} + +void MockQuery::MakeRemoteQuery(const std::string &devices, const std::string &sql, Values &&args) +{ + isRemote_ = true; + devices_ = { devices }; + sql_ = sql; + args_ = std::move(args); +} + +void MockQuery::MakeQuery(const DistributedRdb::PredicatesMemo &predicates) +{ + if (!predicates.tables_.empty()) { + predicates_ = std::make_shared(*predicates.tables_.begin()); + predicates_->SetWhereClause("id = 1"); + } + devices_ = predicates.devices_; + tables_ = predicates.tables_; +} int32_t MockGeneralWatcher::OnChange(const Origin &origin, const PRIFields &primaryFields, ChangeInfo &&values) { + origin_ = origin; + primaryFields_ = primaryFields; return GeneralError::E_OK; } @@ -34,4 +58,4 @@ int32_t MockGeneralWatcher::OnChange(const Origin &origin, const Fields &fields, { return GeneralError::E_OK; } -} // OHOS::DistributedData +} // namespace 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 index 27748455653f095d071d3761fc4cf5106516e079..dac5bbd6da4366e128b9ef07bf675f9a633e92cb 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.h @@ -14,12 +14,11 @@ */ #ifndef OHOS_DISTRIBUTEDDATA_SERVICE_TEST_GENERAL_WATCH_MOCK_H #define OHOS_DISTRIBUTEDDATA_SERVICE_TEST_GENERAL_WATCH_MOCK_H - -#include "store/general_value.h" +#include "rdb_query.h" #include "store/general_watcher.h" namespace OHOS::DistributedData { -class MockQuery : public GenQuery { +class MockQuery : public DistributedRdb::RdbQuery { public: ~MockQuery() = default; static constexpr uint64_t TYPE_ID = 0x20000001; @@ -28,6 +27,9 @@ public: bool IsEqual(uint64_t tid) override; std::vector GetTables() override; + const std::string GetStatement(); + void MakeRemoteQuery(const std::string &devices, const std::string &sql, DistributedData::Values &&args); + void MakeQuery(const DistributedRdb::PredicatesMemo &predicates); }; class MockGeneralWatcher : public DistributedData::GeneralWatcher { @@ -35,6 +37,10 @@ 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; + +private: + Origin origin_; + PRIFields primaryFields_; }; -} // OHOS::DistributedData +} // namespace OHOS::DistributedData #endif \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_corruption_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_corruption_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b9ead1e0773c4bf0d6dcaa135e3f6e79f3b98617 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_corruption_mock.cpp @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2025 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_corruption_mock.h" + +#include "store_types.h" +namespace DistributedDB { +DBStatus KvStoreNbDelegateCorruptionMock::Get(const Key &key, Value &value) const +{ + return DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetEntries(const Key &keyPrefix, std::vector &entries) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetEntries(const Key &keyPrefix, KvStoreResultSet *&resultSet) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetEntries(const Query &query, std::vector &entries) const +{ + return DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetEntries(const Query &query, KvStoreResultSet *&resultSet) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetCount(const Query &query, int &count) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::CloseResultSet(KvStoreResultSet *&resultSet) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Put(const Key &key, const Value &value) +{ + return DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; +} + +DBStatus KvStoreNbDelegateCorruptionMock::PutBatch(const std::vector &entries) +{ + return DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; +} + +DBStatus KvStoreNbDelegateCorruptionMock::DeleteBatch(const std::vector &keys) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Delete(const Key &key) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetLocal(const Key &key, Value &value) const +{ + return DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetLocalEntries(const Key &keyPrefix, std::vector &entries) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::PutLocal(const Key &key, const Value &value) +{ + return DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; +} + +DBStatus KvStoreNbDelegateCorruptionMock::DeleteLocal(const Key &key) +{ + return DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; +} + +DBStatus KvStoreNbDelegateCorruptionMock::PublishLocal(const Key &key, bool deleteLocal, bool updateTimestamp, + const KvStoreNbPublishOnConflict &onConflict) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::UnpublishToLocal(const Key &key, bool deletePublic, bool updateTimestamp) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::RegisterObserver(const Key &key, unsigned int mode, + KvStoreObserver *observer) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::UnRegisterObserver(const KvStoreObserver *observer) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::RemoveDeviceData(const std::string &device) +{ + return DBStatus::OK; +} + +std::string KvStoreNbDelegateCorruptionMock::GetStoreId() const +{ + return "ok"; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Sync(const std::vector &devices, SyncMode mode, + const std::function &devicesMap)> &onComplete, + bool wait) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Pragma(PragmaCmd cmd, PragmaData ¶mData) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::SetConflictNotifier(int conflictType, + const KvStoreNbConflictNotifier ¬ifier) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Rekey(const CipherPassword &password) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Export(const std::string &filePath, + const CipherPassword &passwd, bool force) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::StartTransaction() +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Commit() +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Rollback() +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::PutLocalBatch(const std::vector &entries) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::DeleteLocalBatch(const std::vector &keys) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetSecurityOption(SecurityOption &option) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::SetRemotePushFinishedNotify(const RemotePushFinishedNotifier ¬ifier) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Sync(const std::vector &devices, SyncMode mode, + const std::function &devicesMap)> &onComplete, + const Query &query, bool wait) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::CheckIntegrity() const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::SetEqualIdentifier(const std::string &identifier, + const std::vector &targets) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::SetPushDataInterceptor(const PushDataInterceptor &interceptor) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::SubscribeRemoteQuery(const std::vector &devices, + const std::function &devicesMap)> &onComplete, + const Query &query, bool wait) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::UnSubscribeRemoteQuery(const std::vector &devices, + const std::function &devicesMap)> &onComplete, + const Query &query, bool wait) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::RemoveDeviceData() +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetKeys(const Key &keyPrefix, std::vector &keys) const +{ + return DBStatus::OK; +} + +size_t KvStoreNbDelegateCorruptionMock::GetSyncDataSize(const std::string &device) const +{ + size_t size = 0; + return size; +} + +DBStatus KvStoreNbDelegateCorruptionMock::UpdateKey(const UpdateKeyCallback &callback) +{ + return DBStatus::OK; +} + +std::pair KvStoreNbDelegateCorruptionMock::GetWatermarkInfo(const std::string &device) +{ + std::pair ret; + return ret; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::SetCloudDB(const std::map> &cloudDBs) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::SetCloudDbSchema(const std::map &schema) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::RemoveDeviceData(const std::string &device, ClearMode mode) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::RemoveDeviceData(const std::string &device, + const std::string &user, ClearMode mode) +{ + return DBStatus::OK; +} + +int32_t KvStoreNbDelegateCorruptionMock::GetTaskCount() +{ + int32_t taskCount = taskCountMock_; + return taskCount; +} + +void KvStoreNbDelegateCorruptionMock::SetGenCloudVersionCallback(const GenerateCloudVersionCallback &callback) +{ + auto callback_ = callback; +} + +std::pair> KvStoreNbDelegateCorruptionMock::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 KvStoreNbDelegateCorruptionMock::SetReceiveDataInterceptor(const DataInterceptor &interceptor) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::SetCloudSyncConfig(const CloudSyncConfig &config) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetDeviceEntries(const std::string &device, std::vector &entries) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Sync(const DeviceSyncOption &option, + const DeviceSyncProcessCallback &onProcess) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::CancelSync(uint32_t syncId) +{ + return DBStatus::OK; +} + +KvStoreNbDelegate::DatabaseStatus KvStoreNbDelegateCorruptionMock::GetDatabaseStatus() const +{ + return {}; +} + +DBStatus KvStoreNbDelegateCorruptionMock::ClearMetaData(ClearKvMetaDataOption option) +{ + 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_corruption_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_corruption_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..6a7fa48a087eb588a3a2c5f8b185837dd8c63ec6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_corruption_mock.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2025 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_CORRUPTION_H_MOCK +#define KV_STORE_NB_DELEGATE_CORRUPTION_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_conflict_data.h" +#include "kv_store_nb_delegate.h" +#include "kv_store_observer.h" +#include "kv_store_result_set.h" +#include "query.h" +#include "store_types.h" + +namespace DistributedDB { +class KvStoreNbDelegateCorruptionMock : public DistributedDB::KvStoreNbDelegate { +public: + int32_t taskCountMock_ = 0; + ~KvStoreNbDelegateCorruptionMock() = 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, bool isNeedIntegrityCheck = false); + 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 Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete); + DBStatus CancelSync(uint32_t syncId); + DatabaseStatus GetDatabaseStatus() const; + DBStatus ClearMetaData(ClearKvMetaDataOption option); +}; +} // namespace DistributedDB +#endif // KV_STORE_NB_DELEGATE_CORRUPTION_H_MOCK \ 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 index d37fc737609a308ccd3af28a68622f0a25daef4a..b5668bbf22132cf83b06ec1bc172b212241b616b 100644 --- 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 @@ -328,6 +328,12 @@ DBStatus KvStoreNbDelegateMock::Sync(const DeviceSyncOption &option, const Devic return DBStatus::OK; } +DBStatus KvStoreNbDelegateMock::Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete) +{ + return DBStatus::OK; +} + DBStatus KvStoreNbDelegateMock::CancelSync(uint32_t syncId) { return DBStatus::OK; @@ -337,4 +343,9 @@ KvStoreNbDelegate::DatabaseStatus KvStoreNbDelegateMock::GetDatabaseStatus() con { return {}; } + +DBStatus KvStoreNbDelegateMock::ClearMetaData(ClearKvMetaDataOption option) +{ + 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 index 7f3d77c8d184b2d02877307072caf3024eff713e..bf55801369bcf6b569b515c1a262108add64313b 100644 --- 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 @@ -105,8 +105,11 @@ public: DBStatus SetCloudSyncConfig(const CloudSyncConfig &config); DBStatus GetDeviceEntries(const std::string &device, std::vector &entries) const; DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess); + DBStatus Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete); DBStatus CancelSync(uint32_t syncId); DatabaseStatus GetDatabaseStatus() const; + DBStatus ClearMetaData(ClearKvMetaDataOption option); }; } // namespace DistributedDB #endif // KV_STORE_NB_DELEGATE_H_MOCK \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/meta_data_manager_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/meta_data_manager_mock.cpp index 5923f7da62783febc8a5c44cfe40524cf7ef945a..3a23d32296ed914847a17eca64fb454f2b79b6e3 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/meta_data_manager_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/meta_data_manager_mock.cpp @@ -12,23 +12,44 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include #include "meta_data_manager_mock.h" +#include + +#include "metadata/capability_meta_data.h" + namespace OHOS::DistributedData { using namespace std; + OHOS::DistributedData::MetaDataManager &OHOS::DistributedData::MetaDataManager::GetInstance() { static MetaDataManager instance; return instance; } -OHOS::DistributedData::MetaDataManager::MetaDataManager() { } +OHOS::DistributedData::MetaDataManager::MetaDataManager() +{ +} -OHOS::DistributedData::MetaDataManager::~MetaDataManager() { } +OHOS::DistributedData::MetaDataManager::~MetaDataManager() +{ +} bool OHOS::DistributedData::MetaDataManager::LoadMeta(const std::string &key, Serializable &value, bool isLocal) { return BMetaDataManager::metaDataManager->LoadMeta(key, value, isLocal); } -} \ No newline at end of file + +bool OHOS::DistributedData::MetaDataManager::Sync(const std::vector &devices, + MetaDataManager::OnComplete complete, bool wait, bool isRetry) +{ + return BMetaDataManager::metaDataManager->Sync(devices, complete, wait, isRetry); +} + +template<> +bool OHOS::DistributedData::MetaDataManager::LoadMeta( + const std::string &prefix, std::vector &values, bool isLocal) +{ + return BMetaData::metaDataManager->LoadMeta(prefix, values, isLocal); +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/meta_data_manager_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/meta_data_manager_mock.h index 28b4562a629c63a549e2614ac6972a0bc081a607..32bcd387345b2faf5265eac63e4dca59efd2a11d 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/meta_data_manager_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/meta_data_manager_mock.h @@ -16,24 +16,37 @@ #define OHOS_META_DATA_MANAGER_MOCK_H #include + +#include "metadata/appid_meta_data.h" #include "metadata/meta_data_manager.h" -#include "metadata/strategy_meta_data.h" #include "metadata/store_meta_data.h" -#include "metadata/appid_meta_data.h" +#include "metadata/strategy_meta_data.h" namespace OHOS::DistributedData { class BMetaDataManager { public: virtual bool LoadMeta(const std::string &, Serializable &, bool) = 0; + virtual bool Sync(const std::vector &, MetaDataManager::OnComplete, bool, bool) = 0; BMetaDataManager() = default; virtual ~BMetaDataManager() = default; -private: static inline std::shared_ptr metaDataManager = nullptr; }; - class MetaDataManagerMock : public BMetaDataManager { public: - MOCK_METHOD(bool, LoadMeta, (const std::string &, Serializable &, bool)); + MOCK_METHOD(bool, LoadMeta, (const std::string &, Serializable &, bool), (override)); + MOCK_METHOD(bool, Sync, (const std::vector &, MetaDataManager::OnComplete, bool, bool), (override)); +}; + +template class BMetaData { +public: + virtual bool LoadMeta(const std::string &, std::vector &, bool) = 0; + BMetaData() = default; + virtual ~BMetaData() = default; + static inline std::shared_ptr> metaDataManager = nullptr; +}; +template class MetaDataMock : public BMetaData { +public: + MOCK_METHOD(bool, LoadMeta, (const std::string &, std::vector &, bool), (override)); }; -} +} // namespace OHOS::DistributedData #endif //OHOS_META_DATA_MANAGER_MOCK_H diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/network_delegate_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/network_delegate_mock.cpp index ce26d253bd9fb435436d56b19abd26d18d2dda5c..cfab2309bdb8df8927d2991961301889bb038938 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/network_delegate_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/network_delegate_mock.cpp @@ -30,5 +30,10 @@ void NetworkDelegateMock::RegOnNetworkChange() { return; } + +void NetworkDelegateMock::BindExecutor(std::shared_ptr executors) +{ + return; +} } // namespace DistributedData } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/network_delegate_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/network_delegate_mock.h index d1d65cf989203ae8689e085454958a9931a238fa..0fcea3d287c291d3f87929eff26337fdcac7fc63 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/network_delegate_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/network_delegate_mock.h @@ -24,6 +24,7 @@ public: bool IsNetworkAvailable() override; NetworkType GetNetworkType(bool retrieve = false) override; void RegOnNetworkChange() override; + void BindExecutor(std::shared_ptr executors) override; bool isNetworkAvailable_ = true; virtual ~NetworkDelegateMock() = default; }; diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/preprocess_utils_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/preprocess_utils_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..47178428fa7b5d8513fbcb0d60a5b2661c5763a4 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/preprocess_utils_mock.cpp @@ -0,0 +1,192 @@ +///* +// * Copyright (c) 2025 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 "PreProcessUtils" +// +//#include "preprocess_utils.h" +// +//#include "bundle_info.h" +//#include "dds_trace.h" +//#include "accesstoken_kit.h" +//#include "iservice_registry.h" +//#include "log_print.h" +//#include "system_ability_definition.h" +//#include "utils/crypto.h" +//#include "uri_permission_manager_client.h" +//#include "bundle_mgr_interface.h" +//namespace OHOS { +//namespace UDMF { +//using namespace OHOS::DistributedDataDfx; +//using namespace Security::AccessToken; +////using namespace OHOS::AppFileService::ModuleRemoteFileShare; +// +//int32_t PreProcessUtils::FillRuntimeInfo(UnifiedData &data, CustomOption &option) +//{ +// auto it = UD_INTENTION_MAP.find(option.intention); +// if (it == UD_INTENTION_MAP.end()) { +// return E_ERROR; +// } +// std::string bundleName = "bundleName"; +// std::string intention = it->second; +// UnifiedKey key(intention, bundleName, GenerateId()); +// Privilege privilege; +// privilege.tokenId = option.tokenId; +// +// Runtime runtime; +// runtime.key = key; +// runtime.privileges.emplace_back(privilege); +// runtime.createTime = GetTimestamp(); +// runtime.sourcePackage = bundleName; +// runtime.createPackage = bundleName; +// runtime.recordTotalNum = static_cast(data.GetRecords().size()); +// runtime.tokenId = option.tokenId; +// runtime.visibility = option.visibility; +// runtime.appId = "appId"; +// data.SetRuntime(runtime); +// return E_OK; +//} +// +//std::string PreProcessUtils::GenerateId() +//{ +// return "1122ac"; +//} +// +//time_t PreProcessUtils::GetTimestamp() +//{ +// std::chrono::time_point tp = +// std::chrono::time_point_cast(std::chrono::system_clock::now()); +// time_t timestamp = tp.time_since_epoch().count(); +// return timestamp; +//} +// +//int32_t PreProcessUtils::GetHapUidByToken(uint32_t tokenId, int &userId) +//{ +// return E_OK; +//} +// +//bool PreProcessUtils::GetHapBundleNameByToken(int tokenId, std::string &bundleName) +//{ +// bundleName = "processName"; +// return true; +//} +// +//bool PreProcessUtils::GetNativeProcessNameByToken(int tokenId, std::string &processName) +//{ +// processName = "processName"; +// return true; +//} +// +//std::string PreProcessUtils::GetLocalDeviceId() +//{ +// return "123"; +//} +// +//void PreProcessUtils::SetRemoteData(UnifiedData &data) +//{ +// return; +//} +// +//int32_t PreProcessUtils::SetRemoteUri(uint32_t tokenId, UnifiedData &data) +//{ +// return E_OK; +//} +// +//bool PreProcessUtils::GetInstIndex(uint32_t tokenId, int32_t &instIndex) +//{ +// return true; +//} +// +//bool PreProcessUtils::IsNetworkingEnabled() +//{ +// return true; +//} +// +//void PreProcessUtils::ProcessFileType(std::vector> records, +// std::function)> callback) +//{ +// return; +//} +// +//void PreProcessUtils::ProcessRecord(std::shared_ptr record, uint32_t tokenId, +// bool isLocal, std::vector &uris) +//{ +// return; +//} +// +//void PreProcessUtils::GetHtmlFileUris(uint32_t tokenId, UnifiedData &data, +// bool isLocal, std::vector &uris) +//{ +// return; +//} +// +//void PreProcessUtils::ClearHtmlDfsUris(UnifiedData &data) +//{ +// return; +//} +// +//void PreProcessUtils::ProcessHtmlFileUris(uint32_t tokenId, UnifiedData &data, bool isLocal, std::vector &uris) +//{ +// return; +//} +// +//void PreProcessUtils::SetRecordUid(UnifiedData &data) +//{ +// return; +//} +// +//bool PreProcessUtils::GetDetailsFromUData(const UnifiedData &data, UDDetails &details) +//{ +// return true; +//} +// +//Status PreProcessUtils::GetSummaryFromDetails(const UDDetails &details, Summary &summary) +//{ +// return E_OK; +//} +// +//sptr PreProcessUtils::GetBundleMgr() +//{ +// auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); +// if (samgrProxy == nullptr) { +// ZLOGE("Failed to get system ability mgr."); +// return nullptr; +// } +// auto bundleMgrProxy = samgrProxy->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); +// if (bundleMgrProxy == nullptr) { +// ZLOGE("Failed to Get BMS SA."); +// return nullptr; +// } +// auto bundleManager = iface_cast(bundleMgrProxy); +// if (bundleManager == nullptr) { +// ZLOGE("Failed to get bundle manager"); +// return nullptr; +// } +// return bundleManager; +//} +// +//bool PreProcessUtils::GetSpecificBundleName(const std::string &bundleName, int32_t appIndex, +// std::string &specificBundleName) +//{ +// return true; +//} +// +//bool PreProcessUtils::GetSpecificBundleNameByTokenId(uint32_t tokenId, std::string &specificBundleName, +// std::string &bundleName) +//{ +// specificBundleName = "specificBundleName"; +// bundleName = "bundleName"; +// return true; +//} +//} // namespace UDMF +//} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/preprocess_utils_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/preprocess_utils_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..92af6e73e34043d5b05cc21bfb9ed75439cb3c8a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/preprocess_utils_mock.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025 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 UDMF_PREPROCESS_UTILS_H +#define UDMF_PREPROCESS_UTILS_H + +#include "bundlemgr/bundle_mgr_proxy.h" +#include "unified_data.h" + +namespace OHOS { +namespace UDMF { +class PreProcessUtils { +public: + static int32_t FillRuntimeInfo(UnifiedData &data, CustomOption &option); + static std::string GenerateId(); + static time_t GetTimestamp(); + static int32_t GetHapUidByToken(uint32_t tokenId, int &userId); + static bool GetHapBundleNameByToken(int tokenId, std::string &bundleName); + static bool GetNativeProcessNameByToken(int tokenId, std::string &processName); + static std::string GetLocalDeviceId(); + static void SetRemoteData(UnifiedData &data); + static int32_t SetRemoteUri(uint32_t tokenId, UnifiedData &data); + static bool GetInstIndex(uint32_t tokenId, int32_t &instIndex); + static bool IsNetworkingEnabled(); + static void ProcessFileType(std::vector> records, + std::function)> callback); + static void GetHtmlFileUris(uint32_t tokenId, UnifiedData &data, bool isLocal, std::vector &uris); + static void ClearHtmlDfsUris(UnifiedData &data); + static void ProcessHtmlFileUris(uint32_t tokenId, UnifiedData &data, bool isLocal, std::vector &uris); + static void ProcessRecord(std::shared_ptr record, uint32_t tokenId, + bool isLocal, std::vector &uris); + static void SetRecordUid(UnifiedData &data); + static bool GetDetailsFromUData(const UnifiedData &data, UDDetails &details); + static Status GetSummaryFromDetails(const UDDetails &details, Summary &summary); + static bool GetSpecificBundleNameByTokenId(uint32_t tokenId, std::string &specificBundleName, + std::string &bundleName); + static std::string GetAppId(const std::string &bundleName); + static sptr GetBundleMgr(); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_PREPROCESS_UTILS_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/relational_store_delegate_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/relational_store_delegate_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..a478667ab7bcd63dfabf4ac8ec245d0656c6333e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/relational_store_delegate_mock.h @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2025 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 RELATIONAL_STORE_DELEGATE_MOCK_H +#define RELATIONAL_STORE_DELEGATE_MOCK_H +#include "rdb_general_store.h" +namespace DistributedDB { +class MockRelationalStoreDelegate : public DistributedDB::RelationalStoreDelegate { +public: + ~MockRelationalStoreDelegate() = default; + + DBStatus Sync(const std::vector &devices, DistributedDB::SyncMode mode, const Query &query, + const SyncStatusCallback &onComplete, bool wait) override + { + return DBStatus::OK; + } + static inline int32_t cloudSyncTask = 0; + static bool SetCloudSyncTaskCount(int32_t task) + { + cloudSyncTask = task; + return true; + } + static inline int32_t deviceSyncTask = 0; + static bool SetDeviceTaskCount(int32_t task) + { + deviceSyncTask = task; + return true; + } + static inline int32_t downloadingAssetsCount = 0; + static bool SetDownloadingAssetsCount(int32_t task) + { + downloadingAssetsCount = task; + return true; + } + int32_t GetCloudSyncTaskCount() override + { + return cloudSyncTask; + } + std::pair GetDownloadingAssetsCount() override + { + return {DBStatus::OK, downloadingAssetsCount}; + } + int32_t GetDeviceSyncTaskCount() override + { + return deviceSyncTask; + } + DBStatus RemoveDeviceData(const std::string &device, const std::string &tableName) override + { + return DBStatus::OK; + } + + DBStatus RemoteQuery(const std::string &device, const RemoteCondition &condition, uint64_t timeout, + std::shared_ptr &result) override + { + if (device == "test") { + return DBStatus::DB_ERROR; + } + return DBStatus::OK; + } + + DBStatus RemoveDeviceData() override + { + return DBStatus::OK; + } + + DBStatus Sync(const std::vector &devices, DistributedDB::SyncMode mode, const Query &query, + const SyncProcessCallback &onProcess, int64_t waitTime) override + { + return DBStatus::OK; + } + + DBStatus SetCloudDB(const std::shared_ptr &cloudDb) override + { + return DBStatus::OK; + } + + DBStatus SetCloudDbSchema(const DataBaseSchema &schema) override + { + return DBStatus::OK; + } + + DBStatus RegisterObserver(StoreObserver *observer) override + { + return DBStatus::OK; + } + + DBStatus UnRegisterObserver() override + { + return DBStatus::OK; + } + + DBStatus UnRegisterObserver(StoreObserver *observer) override + { + return DBStatus::OK; + } + + DBStatus SetIAssetLoader(const std::shared_ptr &loader) override + { + return DBStatus::OK; + } + + DBStatus Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) override + { + return DBStatus::OK; + } + + DBStatus SetTrackerTable(const TrackerSchema &schema) override + { + if (schema.tableName == "WITH_INVENTORY_DATA") { + return DBStatus::WITH_INVENTORY_DATA; + } + if (schema.tableName == "test") { + return DBStatus::DB_ERROR; + } + return DBStatus::OK; + } + + DBStatus ExecuteSql(const SqlCondition &condition, std::vector &records) override + { + if (condition.sql == "") { + return DBStatus::DB_ERROR; + } + + std::string sqls = "INSERT INTO test ( #flag, #float, #gid, #value) VALUES ( ?, ?, ?, ?)"; + std::string sqlIn = " UPDATE test SET setSql WHERE whereSql"; + std::string sql = "REPLACE INTO test ( #flag, #float, #gid, #value) VALUES ( ?, ?, ?, ?)"; + if (condition.sql == sqls || condition.sql == sqlIn || condition.sql == sql) { + return DBStatus::DB_ERROR; + } + return DBStatus::OK; + } + + DBStatus SetReference(const std::vector &tableReferenceProperty) override + { + if (gTestResult) { + return DBStatus::DB_ERROR; + } + return DBStatus::OK; + } + + DBStatus CleanTrackerData(const std::string &tableName, int64_t cursor) override + { + return DBStatus::OK; + } + + DBStatus Pragma(PragmaCmd cmd, PragmaData &pragmaData) override + { + return DBStatus::OK; + } + + DBStatus UpsertData(const std::string &tableName, const std::vector &records, + RecordStatus status = RecordStatus::WAIT_COMPENSATED_SYNC) override + { + return DBStatus::OK; + } + + DBStatus SetCloudSyncConfig(const CloudSyncConfig &config) override + { + return DBStatus::OK; + } + static bool gTestResult; +protected: + DBStatus RemoveDeviceDataInner(const std::string &device, ClearMode mode) override + { + if (gTestResult) { + return DBStatus::DB_ERROR; + } + return DBStatus::OK; + } + + DBStatus CreateDistributedTableInner(const std::string &tableName, TableSyncType type) override + { + if (tableName == "test") { + return DBStatus::DB_ERROR; + } + return DBStatus::OK; + } +}; +} // namespace DistributedDB +#endif \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/relational_store_manager_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/relational_store_manager_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee3e111bc846fd2c39b450bd0b0c445a4a26dd1d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/relational_store_manager_mock.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 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 "MockRelationalStoreManager" +#include + +#include "relational_store_delegate_mock.h" +#include "relational_store_manager.h" +namespace DistributedDB { +bool MockRelationalStoreDelegate::gTestResult = false; +DBStatus RelationalStoreManager::OpenStore(const std::string &path, const std::string &storeId, + const RelationalStoreDelegate::Option &option, RelationalStoreDelegate *&delegate) +{ + delegate = new (std::nothrow) MockRelationalStoreDelegate(); + if (delegate == nullptr) { + return DB_ERROR; + } + delegate->CreateDistributedTable("naturalbase_rdb_test"); + delegate->CreateDistributedTable("naturalbase_rdb_name"); + if (storeId == "mock") { + return OK; + } + return DB_ERROR; +} + +DBStatus RelationalStoreManager::CloseStore(RelationalStoreDelegate *store) +{ + delete store; + store = nullptr; + return OK; +} +} // namespace DistributedDB \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/user_delegate_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/user_delegate_mock.cpp index bc1d1353af1baa663fd793390719254226af2f78..d013c3c11a4346e70cd18cbfe76cc98a7b8c7684 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/user_delegate_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/user_delegate_mock.cpp @@ -91,7 +91,7 @@ bool UserDelegate::NotifyUserEvent(const UserDelegate::UserEvent &userEvent) void UserDelegate::LocalUserObserver::OnAccountChanged(const AccountEventInfo &eventInfo, int32_t timeout) { - return; + userDelegate_.NotifyUserEvent({}); } UserDelegate::LocalUserObserver::LocalUserObserver(UserDelegate &userDelegate) : userDelegate_(userDelegate) {} 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 index c25e185cb9cac8f8cc2000f0d1c71384dde44027..dc5188fa0433ebf9318307506b1b256502ef3574 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_asset_loader_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_asset_loader_test.cpp @@ -43,7 +43,7 @@ protected: void ObjectAssetLoaderTest::SetUp() { - uri_ = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; + uri_ = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; Asset asset{ .name = "test_name", .uri = uri_, @@ -65,8 +65,8 @@ void ObjectAssetLoaderTest::TearDown() {} */ HWTEST_F(ObjectAssetLoaderTest, UploadTest001, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); - auto result = assetLoader->Transfer(userId_, bundleName_, deviceId_, asset_); + auto &assetLoader = ObjectAssetLoader::GetInstance(); + auto result = assetLoader.Transfer(userId_, bundleName_, deviceId_, asset_); ASSERT_EQ(result, false); } @@ -79,13 +79,13 @@ HWTEST_F(ObjectAssetLoaderTest, UploadTest001, TestSize.Level0) */ HWTEST_F(ObjectAssetLoaderTest, TransferAssetsAsync001, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); + 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); + ASSERT_EQ(assetLoader.executors_, nullptr); + assetLoader.TransferAssetsAsync(userId_, bundleName_, deviceId_, assets, lambdaFunc); } /** @@ -97,16 +97,16 @@ HWTEST_F(ObjectAssetLoaderTest, TransferAssetsAsync001, TestSize.Level0) */ HWTEST_F(ObjectAssetLoaderTest, TransferAssetsAsync002, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); + 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); + assetLoader.SetThreadPool(executors); + ASSERT_NE(assetLoader.executors_, nullptr); + assetLoader.TransferAssetsAsync(userId_, bundleName_, deviceId_, assets, lambdaFunc); } /** @@ -118,14 +118,13 @@ HWTEST_F(ObjectAssetLoaderTest, TransferAssetsAsync002, TestSize.Level0) */ HWTEST_F(ObjectAssetLoaderTest, FinishTask001, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); - ASSERT_NE(assetLoader, nullptr); + auto &assetLoader = ObjectAssetLoader::GetInstance(); 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()); + assetLoader.FinishTask(asset_.uri, true); + ASSERT_TRUE(assetLoader.tasks_.Empty()); + assetLoader.FinishTask(asset_.uri, false); + ASSERT_TRUE(assetLoader.tasks_.Empty()); } /** @@ -137,12 +136,12 @@ HWTEST_F(ObjectAssetLoaderTest, FinishTask001, TestSize.Level0) */ HWTEST_F(ObjectAssetLoaderTest, IsDownloading001, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); - assetLoader->downloading_.InsertOrAssign(asset_.uri, asset_.hash); - auto result = assetLoader->IsDownloading(asset_); + 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_); + assetLoader.downloading_.Erase(asset_.uri); + result = assetLoader.IsDownloading(asset_); ASSERT_EQ(result, false); } @@ -155,11 +154,11 @@ HWTEST_F(ObjectAssetLoaderTest, IsDownloading001, TestSize.Level0) */ HWTEST_F(ObjectAssetLoaderTest, IsDownloaded001, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); - auto result = assetLoader->IsDownloaded(asset_); + auto &assetLoader = ObjectAssetLoader::GetInstance(); + auto result = assetLoader.IsDownloaded(asset_); ASSERT_EQ(result, false); - assetLoader->downloaded_.Insert(asset_.uri, "modifyTime_size"); - result = assetLoader->IsDownloaded(asset_); + assetLoader.downloaded_.Insert(asset_.uri, "modifyTime_size"); + result = assetLoader.IsDownloaded(asset_); ASSERT_EQ(result, true); } @@ -172,13 +171,12 @@ HWTEST_F(ObjectAssetLoaderTest, IsDownloaded001, TestSize.Level0) */ HWTEST_F(ObjectAssetLoaderTest, UpdateDownloaded001, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); - ASSERT_NE(assetLoader, nullptr); - while (!assetLoader->assetQueue_.empty()) { - assetLoader->assetQueue_.pop(); + auto &assetLoader = ObjectAssetLoader::GetInstance(); + while (!assetLoader.assetQueue_.empty()) { + assetLoader.assetQueue_.pop(); } - assetLoader->UpdateDownloaded(asset_); - auto [success, hash] = assetLoader->downloaded_.Find(asset_.uri); + assetLoader.UpdateDownloaded(asset_); + auto [success, hash] = assetLoader.downloaded_.Find(asset_.uri); ASSERT_TRUE(success); EXPECT_EQ(hash, asset_.hash); } @@ -192,18 +190,17 @@ HWTEST_F(ObjectAssetLoaderTest, UpdateDownloaded001, TestSize.Level0) */ HWTEST_F(ObjectAssetLoaderTest, UpdateDownloaded002, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); - ASSERT_NE(assetLoader, nullptr); - while (!assetLoader->assetQueue_.empty()) { - assetLoader->assetQueue_.pop(); + auto &assetLoader = ObjectAssetLoader::GetInstance(); + while (!assetLoader.assetQueue_.empty()) { + assetLoader.assetQueue_.pop(); } - for (int i = 0; i <= assetLoader->LAST_DOWNLOAD_ASSET_SIZE; i++) { - assetLoader->assetQueue_.push(asset_.uri); + 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); + 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, ""); } @@ -215,8 +212,7 @@ HWTEST_F(ObjectAssetLoaderTest, UpdateDownloaded002, TestSize.Level0) */ HWTEST_F(ObjectAssetLoaderTest, PushAsset001, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); - ASSERT_NE(assetLoader, nullptr); + auto &assetLoader = ObjectAssetLoader::GetInstance(); sptr assetObj = new AssetObj(); assetObj->dstBundleName_ = bundleName_; assetObj->srcBundleName_ = bundleName_; @@ -225,10 +221,22 @@ HWTEST_F(ObjectAssetLoaderTest, PushAsset001, TestSize.Level0) sptr sendCallback = new ObjectAssetsSendListener(); ASSERT_NE(sendCallback, nullptr); - int32_t ret = assetLoader->PushAsset(userId_, assetObj, sendCallback); + int32_t ret = assetLoader.PushAsset(userId_, assetObj, sendCallback); EXPECT_NE(ret, DistributedObject::OBJECT_SUCCESS); } +/** +* @tc.name: PushAsset002 +* @tc.desc: PushAsset test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectAssetLoaderTest, PushAsset002, TestSize.Level0) +{ + auto &assetLoader = ObjectAssetLoader::GetInstance(); + int32_t ret = assetLoader.PushAsset(userId_, nullptr, nullptr); + EXPECT_EQ(ret, DistributedObject::OBJECT_INNER_ERROR); +} + /** * @tc.name: OnSendResult001 * @tc.desc: OnSendResult 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 dd3f5b43499a8688675b23fb8707699cfe58597e..071a5eab4606d8a9120f1f839fbfafebc0c1f58b 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 @@ -32,6 +32,7 @@ class ObjectAssetMachineTest : public testing::Test { public: void SetUp(); void TearDown(); + static void SetUpTestCase(void); protected: AssetBindInfo AssetBindInfo_; @@ -39,14 +40,20 @@ protected: std::string uri_; std::string bundleName_ = "test_bundleName"; std::map changedAssets_; - std::string sessionId = "123"; + std::string sessionId_ = "123"; StoreInfo storeInfo_; - std::shared_ptr machine; + std::shared_ptr machine_; }; +void ObjectAssetMachineTest::SetUpTestCase(void) +{ + auto executors = std::make_shared(2, 1); + ObjectAssetLoader::GetInstance().SetThreadPool(executors); +} + void ObjectAssetMachineTest::SetUp() { - uri_ = "file:://com.huawei.hmos.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; + uri_ = "file:://com.examples.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; Asset asset{ .name = "test_name", .uri = uri_, @@ -75,10 +82,9 @@ void ObjectAssetMachineTest::SetUp() storeInfo_ = storeInfo; ChangedAssetInfo changedAssetInfo(asset, AssetBindInfo, storeInfo); changedAssets_[uri_] = changedAssetInfo; - if (machine == nullptr) { - machine = std::make_shared(); - auto executors = std::make_shared(2, 1); - ObjectAssetLoader::GetInstance()->SetThreadPool(executors); + changedAssets_[uri_].status = STATUS_STABLE; + if (machine_ == nullptr) { + machine_ = std::make_shared(); } } @@ -102,7 +108,7 @@ HWTEST_F(ObjectAssetMachineTest, StatusTransfer001, TestSize.Level0) }; std::pair changedAsset{ "device_2", asset }; changedAssets_[uri_].status = STATUS_TRANSFERRING; - machine->DFAPostEvent(REMOTE_CHANGED, changedAssets_[uri_], asset, changedAsset); + machine_->DFAPostEvent(REMOTE_CHANGED, changedAssets_[uri_], asset, changedAsset); ASSERT_EQ(changedAssets_[uri_].status, STATUS_WAIT_TRANSFER); ASSERT_EQ(changedAssets_[uri_].deviceId, changedAsset.first); ASSERT_EQ(changedAssets_[uri_].asset.hash, asset.hash); @@ -126,7 +132,7 @@ HWTEST_F(ObjectAssetMachineTest, StatusTransfer002, TestSize.Level0) }; std::pair changedAsset{ "device_2", asset }; changedAssets_[uri_].status = STATUS_TRANSFERRING; - machine->DFAPostEvent(TRANSFER_FINISHED, changedAssets_[uri_], asset, changedAsset); + machine_->DFAPostEvent(TRANSFER_FINISHED, changedAssets_[uri_], asset, changedAsset); ASSERT_EQ(changedAssets_[uri_].status, STATUS_STABLE); } @@ -148,7 +154,7 @@ HWTEST_F(ObjectAssetMachineTest, StatusTransfer003, TestSize.Level0) }; std::pair changedAsset{ "device_2", asset }; changedAssets_[uri_].status = STATUS_UPLOADING; - machine->DFAPostEvent(REMOTE_CHANGED, changedAssets_[uri_], asset, changedAsset); + machine_->DFAPostEvent(REMOTE_CHANGED, changedAssets_[uri_], asset, changedAsset); ASSERT_EQ(changedAssets_[uri_].status, STATUS_WAIT_TRANSFER); ASSERT_EQ(changedAssets_[uri_].deviceId, changedAsset.first); ASSERT_EQ(changedAssets_[uri_].asset.hash, asset.hash); @@ -170,7 +176,27 @@ HWTEST_F(ObjectAssetMachineTest, DFAPostEvent001, TestSize.Level0) }; std::pair changedAsset{ "device_2", asset }; changedAssets_[uri_].status = STATUS_UPLOADING; - auto ret = machine->DFAPostEvent(EVENT_BUTT, changedAssets_[uri_], asset, changedAsset); + auto ret = machine_->DFAPostEvent(EVENT_BUTT, changedAssets_[uri_], asset, changedAsset); + ASSERT_EQ(ret, GeneralError::E_ERROR); +} + +/** +* @tc.name: DFAPostEvent001 +* @tc.desc: DFAPostEvent invalid status test +* @tc.type: FUNC +*/ +HWTEST_F(ObjectAssetMachineTest, DFAPostEvent002, TestSize.Level0) +{ + Asset asset{ + .name = "test_name", + .uri = uri_, + .modifyTime = "modifyTime1", + .size = "size1", + .hash = "modifyTime1_size1", + }; + std::pair changedAsset{ "device_2", asset }; + changedAssets_[uri_].status = DistributedData::STATUS_NO_CHANGE; + auto ret = machine_->DFAPostEvent(UPLOAD, changedAssets_[uri_], asset, changedAsset); ASSERT_EQ(ret, GeneralError::E_ERROR); } @@ -191,13 +217,13 @@ HWTEST_F(ObjectAssetMachineTest, StatusUpload001, TestSize.Level0) .hash = "modifyTime1_size1", }; std::pair changedAsset{ "device_1", asset }; - machine->DFAPostEvent(UPLOAD, changedAssets_[uri_], asset, changedAsset); + machine_->DFAPostEvent(UPLOAD, changedAssets_[uri_], asset, changedAsset); ASSERT_EQ(changedAssets_[uri_].status, STATUS_UPLOADING); - machine->DFAPostEvent(UPLOAD_FINISHED, changedAssets_[uri_], asset); + machine_->DFAPostEvent(UPLOAD_FINISHED, changedAssets_[uri_], asset); ASSERT_EQ(changedAssets_[uri_].status, STATUS_STABLE); // dotransfer - machine->DFAPostEvent(REMOTE_CHANGED, changedAssets_[uri_], asset, changedAsset); + machine_->DFAPostEvent(REMOTE_CHANGED, changedAssets_[uri_], asset, changedAsset); ASSERT_EQ(changedAssets_[uri_].status, STATUS_TRANSFERRING); } @@ -227,23 +253,23 @@ HWTEST_F(ObjectAssetMachineTest, StatusUpload002, TestSize.Level0) .assetName = "asset_" + timestamp + ".jpg", }; StoreInfo storeInfo { - .tokenId = static_cast(time), + .tokenId = time, .bundleName = "bundleName_" + timestamp, .storeName = "store_" + timestamp, - .instanceId = static_cast(time), - .user = static_cast(time), + .instanceId = time, + .user = time, }; ChangedAssetInfo changedAssetInfo(asset, bindInfo, storeInfo); std::pair changedAsset{ "device_" + timestamp, asset }; - machine->DFAPostEvent(UPLOAD, changedAssetInfo, asset); + machine_->DFAPostEvent(UPLOAD, changedAssetInfo, asset); ASSERT_EQ(changedAssetInfo.status, STATUS_UPLOADING); - machine->DFAPostEvent(REMOTE_CHANGED, changedAssetInfo, asset, changedAsset); + machine_->DFAPostEvent(REMOTE_CHANGED, changedAssetInfo, asset, changedAsset); ASSERT_EQ(changedAssetInfo.status, STATUS_WAIT_TRANSFER); ASSERT_EQ(changedAssetInfo.asset.hash, asset.hash); - machine->DFAPostEvent(UPLOAD_FINISHED, changedAssetInfo, asset); + machine_->DFAPostEvent(UPLOAD_FINISHED, changedAssetInfo, asset); ASSERT_EQ(changedAssetInfo.status, STATUS_TRANSFERRING); } @@ -280,10 +306,10 @@ HWTEST_F(ObjectAssetMachineTest, StatusDownload001, TestSize.Level0) ChangedAssetInfo changedAssetInfo(asset, AssetBindInfo, storeInfo); std::pair changedAsset{ "device_006", asset }; - machine->DFAPostEvent(DOWNLOAD, changedAssetInfo, asset, changedAsset); + machine_->DFAPostEvent(DOWNLOAD, changedAssetInfo, asset, changedAsset); ASSERT_EQ(changedAssetInfo.status, STATUS_DOWNLOADING); - machine->DFAPostEvent(DOWNLOAD_FINISHED, changedAssetInfo, asset); + 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_mock_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_manager_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2c7663b0a616ec6f9801cdf8a9b56f05db2d650b --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/object_manager_mock_test.cpp @@ -0,0 +1,522 @@ +/* +* Copyright (c) 2025 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 "ObjectManagerMockTest" +#include +#include + +#include "device_manager_adapter_mock.h" +#include "device_matrix_mock.h" +#include "gtest/gtest.h" +#include "mock/access_token_mock.h" +#include "mock/account_delegate_mock.h" +#include "mock/distributed_file_daemon_manager_mock.h" +#include "mock/meta_data_manager_mock.h" +#include "object_manager.h" +#include "object_service_impl.h" + + +using namespace OHOS::DistributedObject; +using namespace OHOS::DistributedData; +using namespace OHOS::Storage::DistributedFile; +using namespace OHOS::Security::AccessToken; +using namespace testing::ext; +using namespace testing; +using AssetValue = OHOS::CommonType::AssetValue; +using DeviceInfo = OHOS::AppDistributedKv::DeviceInfo; +using OnComplete = OHOS::DistributedData::MetaDataManager::OnComplete; + +namespace OHOS::Test { +namespace DistributedDataTest { +class ObjectManagerMockTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + metaDataManagerMock = std::make_shared(); + BMetaDataManager::metaDataManager = metaDataManagerMock; + metaDataMock = std::make_shared>(); + BMetaData::metaDataManager = metaDataMock; + devMgrAdapterMock = std::make_shared(); + BDeviceManagerAdapter::deviceManagerAdapter = devMgrAdapterMock; + deviceMatrixMock = std::make_shared(); + BDeviceMatrix::deviceMatrix = deviceMatrixMock; + fileDaemonMgrMock = std::make_shared(); + BDistributedFileDaemonManager::fileDaemonManger_ = fileDaemonMgrMock; + accountDelegateMock = new (std::nothrow) AccountDelegateMock(); + if (accountDelegateMock != nullptr) { + AccountDelegate::instance_ = nullptr; + AccountDelegate::RegisterAccountInstance(accountDelegateMock); + } + accTokenMock = std::make_shared(); + BAccessTokenKit::accessTokenkit = accTokenMock; + } + static void TearDownTestCase(void) + { + metaDataManagerMock = nullptr; + BMetaDataManager::metaDataManager = nullptr; + metaDataMock = nullptr; + BMetaData::metaDataManager = nullptr; + devMgrAdapterMock = nullptr; + BDeviceManagerAdapter::deviceManagerAdapter = nullptr; + deviceMatrixMock = nullptr; + BDeviceMatrix::deviceMatrix = nullptr; + fileDaemonMgrMock = nullptr; + BDistributedFileDaemonManager::fileDaemonManger_ = nullptr; + if (accountDelegateMock != nullptr) { + delete accountDelegateMock; + accountDelegateMock = nullptr; + } + accTokenMock = nullptr; + BAccessTokenKit::accessTokenkit = nullptr; + } + + static inline std::shared_ptr metaDataManagerMock = nullptr; + static inline std::shared_ptr> metaDataMock = nullptr; + static inline std::shared_ptr devMgrAdapterMock = nullptr; + static inline std::shared_ptr deviceMatrixMock = nullptr; + static inline std::shared_ptr fileDaemonMgrMock = nullptr; + static inline AccountDelegateMock *accountDelegateMock = nullptr; + static inline std::shared_ptr accTokenMock = nullptr; + void SetUp() {}; + void TearDown() {}; + +protected: + std::string sessionId_ = "123"; + OHOS::ObjectStore::AssetBindInfo assetBindInfo_; + AssetValue assetValue_; +}; + +/** + * @tc.name: IsNeedMetaSync001 + * @tc.desc: Test IsNeedMetaSync when LoadMeta fails for CapMetaData. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(ObjectManagerMockTest, IsNeedMetaSync001, TestSize.Level0) +{ + EXPECT_CALL(*fileDaemonMgrMock, RegisterAssetCallback(_)).WillOnce(testing::Return(0)); + auto &manager = ObjectStoreManager::GetInstance(); + StoreMetaData meta; + meta.deviceId = "test_device_id"; + meta.user = "0"; + meta.storeId = "distributedObject_"; + meta.bundleName = "test_bundle"; + std::vector uuids = { "test_uuid" }; + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)).WillOnce(testing::Return(false)); + bool isNeedSync = manager.IsNeedMetaSync(meta, uuids); + EXPECT_EQ(isNeedSync, true); + EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(true)) + .WillOnce(testing::Return(false)); + isNeedSync = manager.IsNeedMetaSync(meta, uuids); + EXPECT_EQ(isNeedSync, true); +} + +/** + * @tc.name: IsNeedMetaSync002 + * @tc.desc: Test IsNeedMetaSync when LoadMeta fails for StoreMetaData. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(ObjectManagerMockTest, IsNeedMetaSync002, TestSize.Level0) +{ + auto &manager = ObjectStoreManager::GetInstance(); + StoreMetaData meta; + meta.deviceId = "test_device_id"; + meta.user = "0"; + meta.storeId = "distributedObject_"; + meta.bundleName = "test_bundle"; + std::vector uuids = { "test_uuid" }; + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)).WillRepeatedly(Return((true))); + EXPECT_CALL(*deviceMatrixMock, GetRemoteMask(_, _)) + .WillRepeatedly(Return(std::make_pair(true, DeviceMatrix::META_STORE_MASK))); + + bool result = manager.IsNeedMetaSync(meta, uuids); + EXPECT_EQ(result, true); +} + +/** + * @tc.name: IsNeedMetaSync003 + * @tc.desc: Test IsNeedMetaSync when LoadMeta fails for StoreMetaData. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(ObjectManagerMockTest, IsNeedMetaSync003, TestSize.Level0) +{ + auto &manager = ObjectStoreManager::GetInstance(); + StoreMetaData meta; + meta.deviceId = "test_device_id"; + meta.user = "0"; + meta.storeId = "distributedObject_"; + meta.bundleName = "test_bundle"; + std::vector uuids = { "test_uuid" }; + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)).WillRepeatedly(Return(true)); + EXPECT_CALL(*deviceMatrixMock, GetRemoteMask(_, _)).WillOnce(Return(std::make_pair(true, 0))); + EXPECT_CALL(*deviceMatrixMock, GetMask(_, _)).WillOnce(Return(std::make_pair(true, DeviceMatrix::META_STORE_MASK))); + + bool result = manager.IsNeedMetaSync(meta, uuids); + EXPECT_EQ(result, true); + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)).WillRepeatedly(Return(true)); + + EXPECT_CALL(*deviceMatrixMock, GetRemoteMask(_, _)).WillOnce(Return(std::make_pair(true, 0))); + + EXPECT_CALL(*deviceMatrixMock, GetMask(_, _)).WillOnce(Return(std::make_pair(true, 0))); + + result = manager.IsNeedMetaSync(meta, uuids); + EXPECT_EQ(result, false); +} + +/** + * @tc.name: SyncOnStore001 + * @tc.desc: Test SyncOnStore + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(ObjectManagerMockTest, SyncOnStore001, TestSize.Level0) +{ + // 2 means that the GetUserByToken interface will be called twice + EXPECT_CALL(*accountDelegateMock, GetUserByToken(_)).Times(2).WillRepeatedly(Return(0)); + auto &manager = ObjectStoreManager::GetInstance(); + std::function &results)> func; + func = [](const std::map &results) { return results; }; + std::string prefix = "ObjectManagerTest"; + StoreMetaData meta; + meta.deviceId = "test_device_id"; + meta.user = "0"; + meta.storeId = "distributedObject_"; + meta.bundleName = "test_bundle"; + std::vector uuids = { "test_uuid" }; + + // local device + { + std::vector localDeviceList = { "local" }; + auto result = manager.SyncOnStore(prefix, localDeviceList, func); + EXPECT_EQ(result, OBJECT_SUCCESS); + } + + // remote device. IsNeedMetaSync: true; Sync: true + { + std::vector remoteDeviceList = { "remote_device_1" }; + EXPECT_CALL(*devMgrAdapterMock, GetUuidByNetworkId(_)).WillRepeatedly(Return("mock_uuid")); + EXPECT_CALL(*devMgrAdapterMock, ToUUID(testing::A &>())) + .WillOnce(Return(std::vector{ "mock_uuid_1" })); + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)).WillOnce(testing::Return(false)); + EXPECT_CALL(*metaDataManagerMock, Sync(_, _, _, _)).WillOnce(testing::Return(true)); + auto result = manager.SyncOnStore(prefix, remoteDeviceList, func); + EXPECT_EQ(result, OBJECT_SUCCESS); + } + + // remote device. IsNeedMetaSync: false + { + std::vector remoteDeviceList = { "remote_device_1" }; + EXPECT_CALL(*devMgrAdapterMock, GetUuidByNetworkId(_)).WillRepeatedly(Return("mock_uuid")); + EXPECT_CALL(*devMgrAdapterMock, ToUUID(testing::A &>())) + .WillOnce(Return(std::vector{ "mock_uuid_1" })); + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(testing::Return(true)) + .WillOnce(testing::Return(true)); + EXPECT_CALL(*deviceMatrixMock, GetRemoteMask(_, _)).WillOnce(Return(std::make_pair(true, 0))); + EXPECT_CALL(*deviceMatrixMock, GetMask(_, _)).WillOnce(Return(std::make_pair(true, 0))); + auto result = manager.SyncOnStore(prefix, remoteDeviceList, func); + EXPECT_EQ(result, E_DB_ERROR); + } +} + +/** +* @tc.name: GetCurrentUser001 +* @tc.desc: Test the scenario where the QueryUsers return false in the GetCurrentUser function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ObjectManagerMockTest, GetCurrentUser001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::vector users; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(users), Return(false))); + auto result = manager.GetCurrentUser(); + EXPECT_EQ(result, ""); +} + +/** +* @tc.name: GetCurrentUser002 +* @tc.desc: Test the scenario where the QueryUsers users empty in the GetCurrentUser function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ObjectManagerMockTest, GetCurrentUser002, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::vector users; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)) + .Times(1) + .WillOnce( + DoAll(SetArgReferee<0>(users), Invoke([](std::vector &users) { users.clear(); }), Return(true))); + auto result = manager.GetCurrentUser(); + EXPECT_EQ(result, ""); +} + +/** +* @tc.name: GetCurrentUser003 +* @tc.desc: Test the scenario where the QueryUsers return true in the GetCurrentUser function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ObjectManagerMockTest, GetCurrentUser003, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::vector users = { 0, 1 }; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(users), Return(true))); + auto result = manager.GetCurrentUser(); + EXPECT_EQ(result, std::to_string(users[0])); +} + +/** +* @tc.name: WaitAssets001 +* @tc.desc: WaitAssets test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, WaitAssets001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string objectKey = "objectKey"; + ObjectStoreManager::SaveInfo info; + std::map data; + auto ret = manager.WaitAssets(objectKey, info, data); + EXPECT_EQ(ret, DistributedObject::OBJECT_INNER_ERROR); +} + +/** +* @tc.name: NotifyAssetsReady001 +* @tc.desc: NotifyAssetsReady test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, NotifyAssetsReady001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string objectKey = "objectKey"; + std::string bundleName = "bundleName"; + std::string srcNetworkId = "srcNetworkId"; + manager.NotifyAssetsReady(objectKey, bundleName, srcNetworkId); + EXPECT_EQ(manager.executors_, nullptr); +} + +/** +* @tc.name: DoNotifyAssetsReady001 +* @tc.desc: DoNotifyAssetsReady test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, DoNotifyAssetsReady001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + uint32_t tokenId = 0; + ObjectStoreManager::CallbackInfo info; + std::string objectKey = "objectKey"; + bool isReady = true; + manager.DoNotifyAssetsReady(tokenId, info, objectKey, isReady); + EXPECT_EQ(manager.executors_, nullptr); +} + +/** +* @tc.name: DoNotifyWaitAssetTimeout001 +* @tc.desc: DoNotifyWaitAssetTimeout test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, DoNotifyWaitAssetTimeout001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string objectKey = "objectKey"; + manager.DoNotifyWaitAssetTimeout(objectKey); + EXPECT_EQ(manager.executors_, nullptr); +} + +/** +* @tc.name: FlushClosedStore001 +* @tc.desc: FlushClosedStore test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, FlushClosedStore001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + manager.FlushClosedStore(); + EXPECT_EQ(manager.executors_, nullptr); +} + +/** +* @tc.name: CloseAfterMinute001 +* @tc.desc: CloseAfterMinute test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, CloseAfterMinute001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + manager.CloseAfterMinute(); + EXPECT_EQ(manager.executors_, nullptr); +} + +/** +* @tc.name: UnRegisterAssetsLister001 +* @tc.desc: UnRegisterAssetsLister test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, UnRegisterAssetsLister001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + manager.objectAssetsRecvListener_ = nullptr; + auto ret = manager.UnRegisterAssetsLister(); + EXPECT_EQ(ret, true); + EXPECT_CALL(*fileDaemonMgrMock, RegisterAssetCallback(_)).WillOnce(testing::Return(0)); + manager.RegisterAssetsLister(); + EXPECT_CALL(*fileDaemonMgrMock, UnRegisterAssetCallback(_)).WillOnce(testing::Return(-1)); + ret = manager.UnRegisterAssetsLister(); + EXPECT_EQ(ret, false); + EXPECT_CALL(*fileDaemonMgrMock, UnRegisterAssetCallback(_)).WillOnce(testing::Return(0)); + ret = manager.UnRegisterAssetsLister(); + EXPECT_EQ(ret, true); +} + +/** +* @tc.name: InitUserMeta001 +* @tc.desc: Test the scenario where the QueryUsers return false in the GetCurrentUser function. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, InitUserMeta001, TestSize.Level1) +{ + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(testing::Return(false)); + auto &manager = ObjectStoreManager::GetInstance(); + std::vector users; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(users), Return(false))); + auto status = manager.InitUserMeta(); + EXPECT_EQ(status, DistributedObject::OBJECT_INNER_ERROR); +} + +/** +* @tc.name: InitUserMeta002 +* @tc.desc: Test the scenario where the QueryUsers users empty in the GetCurrentUser function. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, InitUserMeta002, TestSize.Level1) +{ + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(testing::Return(false)); + auto &manager = ObjectStoreManager::GetInstance(); + std::vector users; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)) + .Times(1) + .WillOnce( + DoAll(SetArgReferee<0>(users), Invoke([](std::vector &users) { users.clear(); }), Return(true))); + auto status = manager.InitUserMeta(); + EXPECT_EQ(status, DistributedObject::OBJECT_INNER_ERROR); +} + +/** +* @tc.name: InitUserMeta003 +* @tc.desc: Test the scenario where the QueryUsers return true in the GetCurrentUser function. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, InitUserMeta003, TestSize.Level1) +{ + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(testing::Return(false)); + DeviceInfo devInfo = { .uuid = "666" }; + EXPECT_CALL(*devMgrAdapterMock, GetLocalDevice()).WillOnce(Return(devInfo)); + auto &manager = ObjectStoreManager::GetInstance(); + std::vector users = { 0, 1 }; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(users), Return(true))); + auto status = manager.InitUserMeta(); + EXPECT_EQ(status, DistributedObject::OBJECT_INNER_ERROR); +} + +/** +* @tc.name: BindAsset001 +* @tc.desc: Test BindAsset function when GetTokenTypeFlag is not TOKEN_HAP. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, BindAsset001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string bundleName = "BindAsset"; + uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(_)) + .Times(1) + .WillOnce(Return(ATokenTypeEnum::TOKEN_NATIVE)); + auto result = manager.BindAsset(tokenId, bundleName, sessionId_, assetValue_, assetBindInfo_); + EXPECT_EQ(result, DistributedObject::OBJECT_DBSTATUS_ERROR); +} + +/** +* @tc.name: BindAsset002 +* @tc.desc: Test BindAsset function when GetTokenTypeFlag is TOKEN_HAP. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, BindAsset002, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string bundleName = "BindAsset"; + uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(_)) + .Times(1) + .WillOnce(Return(ATokenTypeEnum::TOKEN_HAP)); + EXPECT_CALL(*accTokenMock, GetHapTokenInfo(_, _)) + .Times(1) + .WillOnce(Return(0)); + auto result = manager.BindAsset(tokenId, bundleName, sessionId_, assetValue_, assetBindInfo_); + EXPECT_EQ(result, DistributedObject::OBJECT_SUCCESS); +} + +/** +* @tc.name: IsContinue001 +* @tc.desc: Test IsContinue function when GetTokenTypeFlag is not TOKEN_HAP. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, IsContinue001, TestSize.Level1) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + bool isContinue = false; + EXPECT_CALL(*fileDaemonMgrMock, UnRegisterAssetCallback(_)).WillRepeatedly(testing::Return(0)); + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(_)) + .Times(1) + .WillOnce(Return(ATokenTypeEnum::TOKEN_NATIVE)); + auto ret = objectServiceImpl->IsContinue(isContinue); + EXPECT_EQ(ret, DistributedObject::OBJECT_INNER_ERROR); +} + +/** +* @tc.name: IsContinue002 +* @tc.desc: Test IsContinue function when GetTokenTypeFlag is TOKEN_HAP. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, IsContinue002, TestSize.Level1) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + bool isContinue = false; + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(_)) + .Times(2) + .WillRepeatedly(Return(ATokenTypeEnum::TOKEN_HAP)); + EXPECT_CALL(*accTokenMock, GetHapTokenInfo(_, _)) + .Times(1) + .WillOnce(Return(0)); + auto ret = objectServiceImpl->IsContinue(isContinue); + EXPECT_EQ(ret, DistributedObject::OBJECT_SUCCESS); +} +}; // namespace DistributedDataTest +} // 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 index 835dca5b618de16032826ec1644ba2ec994ca94e..17183561d5b482b752953a3ae220883b0645f0e2 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_manager_test.cpp @@ -20,21 +20,179 @@ #include #include +#include "bootstrap.h" +#include "device_manager_adapter_mock.h" #include "executor_pool.h" #include "kv_store_nb_delegate_mock.h" +#include "kvstore_meta_manager.h" +#include "metadata/object_user_meta_data.h" #include "object_types.h" #include "snapshot/machine_status.h" using namespace testing::ext; using namespace OHOS::DistributedObject; +using namespace OHOS::DistributedData; +using namespace std; +using namespace testing; using AssetValue = OHOS::CommonType::AssetValue; using RestoreStatus = OHOS::DistributedObject::ObjectStoreManager::RestoreStatus; namespace OHOS::Test { +class IObjectSaveCallback { +public: + virtual void Completed(const std::map &results) = 0; +}; +class IObjectRevokeSaveCallback { +public: + virtual void Completed(int32_t status) = 0; +}; +class IObjectRetrieveCallback { +public: + virtual void Completed(const std::map> &results, bool allReady) = 0; +}; +class IObjectChangeCallback { +public: + virtual void Completed(const std::map> &results, bool allReady) = 0; +}; + +class IObjectProgressCallback { +public: + virtual void Completed(int32_t progress) = 0; +}; + +class ObjectSaveCallbackBroker : public IObjectSaveCallback, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedObject.IObjectSaveCallback"); +}; +class ObjectSaveCallbackStub : public IRemoteStub { +public: + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override + { + return 0; + } +}; +class ObjectRevokeSaveCallbackBroker : public IObjectRevokeSaveCallback, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedObject.IObjectRevokeSaveCallback"); +}; +class ObjectRevokeSaveCallbackStub : public IRemoteStub { +public: + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override + { + return 0; + } +}; +class ObjectRetrieveCallbackBroker : public IObjectRetrieveCallback, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedObject.IObjectRetrieveCallback"); +}; +class ObjectRetrieveCallbackStub : public IRemoteStub { +public: + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override + { + return 0; + } +}; + +class ObjectChangeCallbackBroker : public IObjectChangeCallback, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedObject.IObjectChangeCallback"); +}; + +class ObjectChangeCallbackStub : public IRemoteStub { +public: + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override + { + return 0; + } +}; + +class ObjectProgressCallbackBroker : public IObjectProgressCallback, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedObject.IObjectProgressCallback"); +}; + +class ObjectProgressCallbackStub : public IRemoteStub { +public: + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override + { + return 0; + } +}; + +class ObjectSaveCallback : public ObjectSaveCallbackStub { +public: + explicit ObjectSaveCallback(const std::function &)> &callback) + : callback_(callback) + { + } + void Completed(const std::map &results) override + { + } + +private: + const std::function &)> callback_; +}; +class ObjectRevokeSaveCallback : public ObjectRevokeSaveCallbackStub { +public: + explicit ObjectRevokeSaveCallback(const std::function &callback) : callback_(callback) + { + } + void Completed(int32_t) override + { + } + +private: + const std::function callback_; +}; +class ObjectRetrieveCallback : public ObjectRetrieveCallbackStub { +public: + explicit ObjectRetrieveCallback( + const std::function> &, bool)> &callback) + : callback_(callback) + { + } + void Completed(const std::map> &results, bool allReady) override + { + } + +private: + const std::function> &, bool)> callback_; +}; + +class ObjectChangeCallback : public ObjectChangeCallbackStub { +public: + explicit ObjectChangeCallback( + const std::function> &, bool)> &callback) + : callback_(callback) + { + } + void Completed(const std::map> &results, bool allReady) override + { + } + +private: + const std::function> &, bool)> callback_; +}; + +class ObjectProgressCallback : public ObjectProgressCallbackStub { +public: + explicit ObjectProgressCallback(const std::function &callback) : callback_(callback) + { + } + void Completed(int32_t progress) override + { + } + +private: + const std::function callback_; +}; class ObjectManagerTest : public testing::Test { public: void SetUp(); void TearDown(); + static void SetUpTestCase(void); + static void TearDownTestCase(void); protected: Asset asset_; @@ -47,16 +205,17 @@ protected: uint64_t sequenceId_2 = 20; uint64_t sequenceId_3 = 30; std::string userId_ = "100"; - std::string bundleName_ = "com.examples.hmos.notepad"; + std::string bundleName_ = "com.examples.notepad"; OHOS::ObjectStore::AssetBindInfo assetBindInfo_; pid_t pid_ = 10; uint32_t tokenId_ = 100; AssetValue assetValue_; + static inline std::shared_ptr devMgrAdapterMock = nullptr; }; void ObjectManagerTest::SetUp() { - uri_ = "file:://com.examples.hmos.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; + uri_ = "file:://com.examples.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; Asset asset{ .name = "test_name", .uri = uri_, @@ -91,7 +250,27 @@ void ObjectManagerTest::SetUp() assetBindInfo_ = AssetBindInfo; } -void ObjectManagerTest::TearDown() {} +void ObjectManagerTest::SetUpTestCase(void) +{ + devMgrAdapterMock = make_shared(); + BDeviceManagerAdapter::deviceManagerAdapter = devMgrAdapterMock; + 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(); +} + +void ObjectManagerTest::TearDownTestCase(void) +{ + BDeviceManagerAdapter::deviceManagerAdapter = nullptr; + devMgrAdapterMock = nullptr; +} + +void ObjectManagerTest::TearDown() +{ +} /** * @tc.name: DeleteNotifier001 @@ -118,12 +297,10 @@ HWTEST_F(ObjectManagerTest, Process001, TestSize.Level0) { auto syncManager = SequenceSyncManager::GetInstance(); std::map results; - results = {{ "test_cloud", DistributedDB::DBStatus::OK }}; + results = { { "test_cloud", DistributedDB::DBStatus::OK } }; std::function &results)> func; - func = [](const std::map &results) { - return results; - }; + 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); @@ -142,11 +319,9 @@ HWTEST_F(ObjectManagerTest, DeleteNotifierNoLock001, TestSize.Level0) { auto syncManager = SequenceSyncManager::GetInstance(); std::function &results)> func; - func = [](const std::map &results) { - return results; - }; + func = [](const std::map &results) { return results; }; syncManager->seqIdCallbackRelations_.emplace(sequenceId_, func); - std::vector seqIds = {sequenceId_, sequenceId_2, sequenceId_3}; + 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); @@ -155,6 +330,29 @@ HWTEST_F(ObjectManagerTest, DeleteNotifierNoLock001, TestSize.Level0) ASSERT_EQ(result, SequenceSyncManager::SUCCESS_USER_IN_USE); } +/** +* @tc.name: SaveToStoreTest +* @tc.desc: SaveToStore test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, SaveToStoreTest, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string dataDir = "/data/app/el2/100/database"; + manager.SetData(dataDir, userId_); + auto result = manager.Open(); + ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); + ASSERT_NE(manager.delegate_, nullptr); + ObjectRecord data{}; + result = manager.SaveToStore("appId", "sessionId", "toDeviceId", data); + ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); + + manager.ForceClose(); + ASSERT_EQ(manager.delegate_, nullptr); + result = manager.SaveToStore("appId", "sessionId", "toDeviceId", data); + ASSERT_NE(result, DistributedObject::OBJECT_SUCCESS); +} + /** * @tc.name: Clear001 * @tc.desc: Clear test. @@ -164,9 +362,15 @@ HWTEST_F(ObjectManagerTest, DeleteNotifierNoLock001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, Clear001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); - auto result = manager->Clear(); - ASSERT_EQ(result, OHOS::DistributedObject::OBJECT_STORE_NOT_FOUND); + ObjectUserMetaData userMeta; + MetaDataManager::GetInstance().SaveMeta(ObjectUserMetaData::GetKey(), userMeta, true); + auto &manager = ObjectStoreManager::GetInstance(); + std::string dataDir = "/data/app/el2/100/database"; + manager.SetData(dataDir, userId_); + auto result = manager.Clear(); + ASSERT_EQ(result, OHOS::DistributedObject::OBJECT_SUCCESS); + auto size = manager.callbacks_.Size(); + ASSERT_EQ(size, 0); } /** @@ -178,14 +382,17 @@ HWTEST_F(ObjectManagerTest, Clear001, TestSize.Level0) */ 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; + auto &manager = ObjectStoreManager::GetInstance(); + std::function> &, bool)> cb = + [](const std::map> &, bool) {}; + sptr objectRemoteResumeCallback = new (std::nothrow) ObjectChangeCallback(cb); + ASSERT_NE(objectRemoteResumeCallback, nullptr); + manager.RegisterRemoteCallback(bundleName_, sessionId_, pid_, tokenId_, objectRemoteResumeCallback->AsObject()); + 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; + manager.UnregisterRemoteCallback(bundleName_, pid_, tokenId_, sessionId_); + callbackInfo = manager.callbacks_.Find(tokenId_).second; ASSERT_EQ(callbackInfo.observers_.find(prefix), callbackInfo.observers_.end()); } @@ -198,14 +405,15 @@ HWTEST_F(ObjectManagerTest, registerAndUnregisterRemoteCallback001, TestSize.Lev */ HWTEST_F(ObjectManagerTest, registerAndUnregisterRemoteCallback002, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + 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_); + manager.RegisterRemoteCallback("", sessionId_, pid_, tokenId, callback); + manager.RegisterRemoteCallback(bundleName_, "", pid_, tokenId, callback); + manager.RegisterRemoteCallback("", "", pid_, tokenId, callback); + manager.RegisterRemoteCallback(bundleName_, sessionId_, pid_, tokenId, nullptr); + ASSERT_EQ(manager.callbacks_.Find(tokenId).first, false); + manager.UnregisterRemoteCallback("", pid_, tokenId, sessionId_); } /** @@ -217,7 +425,7 @@ HWTEST_F(ObjectManagerTest, registerAndUnregisterRemoteCallback002, TestSize.Lev */ HWTEST_F(ObjectManagerTest, NotifyDataChanged001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::string bundleName1_ = "com.examples.ophm.notepad"; std::string objectKey = bundleName1_ + sessionId_; std::map>> data; @@ -226,13 +434,13 @@ HWTEST_F(ObjectManagerTest, NotifyDataChanged001, TestSize.Level0) data1_.push_back(RestoreStatus::DATA_READY); data1_.push_back(RestoreStatus::ASSETS_READY); data1_.push_back(RestoreStatus::ALL_READY); - data1 = {{ "objectKey", data1_ }}; - data = {{ objectKey, data1 }}; + 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); + manager.SetThreadPool(executors); + ASSERT_EQ(manager.restoreStatus_.Find(objectKey).first, false); + manager.NotifyDataChanged(data, {}); + ASSERT_EQ(manager.restoreStatus_.Find(objectKey).second, RestoreStatus::DATA_READY); } /** @@ -244,16 +452,16 @@ HWTEST_F(ObjectManagerTest, NotifyDataChanged001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, NotifyAssetsReady001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + 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); + 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); } /** @@ -263,36 +471,36 @@ HWTEST_F(ObjectManagerTest, NotifyAssetsReady001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, NotifyAssetsReady002, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); - std::string objectKey="com.example.myapplicaiton123456"; + 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); + 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); + 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); + 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); + 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(); + manager.restoreStatus_.Clear(); } /** @@ -304,18 +512,18 @@ HWTEST_F(ObjectManagerTest, NotifyAssetsReady002, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, NotifyChange001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + 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); - EXPECT_FALSE(manager->restoreStatus_.Find("p_###SAVEINFO###001").first); - manager->NotifyChange(data); - EXPECT_FALSE(manager->restoreStatus_.Find("test_cloud").first); + data = { { "test_cloud", data_ } }; + data1 = { { "p_###SAVEINFO###001", data1_ } }; + manager.NotifyChange(data1); + EXPECT_FALSE(manager.restoreStatus_.Find("p_###SAVEINFO###001").first); + manager.NotifyChange(data); + EXPECT_FALSE(manager.restoreStatus_.Find("test_cloud").first); } /** @@ -325,11 +533,11 @@ HWTEST_F(ObjectManagerTest, NotifyChange001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, NotifyChange002, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::shared_ptr executor = std::make_shared(1, 0); - manager->SetThreadPool(executor); + manager.SetThreadPool(executor); std::map> data{}; - std::vector value{0}; + std::vector value{ 0 }; std::string bundleName = "com.example.myapplication"; std::string sessionId = "123456"; std::string source = "source"; @@ -349,13 +557,14 @@ HWTEST_F(ObjectManagerTest, NotifyChange002, TestSize.Level0) 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_CALL(*devMgrAdapterMock, IsSameAccount(_)).WillOnce(Return(true)); + 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(); + manager.restoreStatus_.Clear(); + manager.executors_->Remove(taskId); + manager.objectTimer_.Clear(); } /** @@ -365,30 +574,30 @@ HWTEST_F(ObjectManagerTest, NotifyChange002, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, ComputeStatus001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::shared_ptr executor = std::make_shared(1, 0); - manager->SetThreadPool(executor); - std::string objectKey="com.example.myapplicaiton123456"; + 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); + 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); + auto [has1, taskId1] = manager.objectTimer_.Find(objectKey); EXPECT_TRUE(has1); - manager->executors_->Remove(taskId1); - manager->objectTimer_.Clear(); - manager->restoreStatus_.Clear(); + 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); + 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); + auto [has3, taskId3] = manager.objectTimer_.Find(objectKey); EXPECT_FALSE(has3); - manager->restoreStatus_.Clear(); + manager.restoreStatus_.Clear(); } /** @@ -400,18 +609,20 @@ HWTEST_F(ObjectManagerTest, ComputeStatus001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, Open001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); - manager->kvStoreDelegateManager_ = nullptr; - auto result = manager->Open(); + 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(); + manager.SetData(dataDir, userId_); + manager.delegate_ = nullptr; + result = manager.Open(); ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); - manager->delegate_ = manager->OpenObjectKvStore(); - result = manager->Open(); + manager.delegate_ = manager.OpenObjectKvStore(); + result = manager.Open(); ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); + manager.ForceClose(); + ASSERT_EQ(manager.delegate_, nullptr); } /** @@ -423,13 +634,13 @@ HWTEST_F(ObjectManagerTest, Open001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, OnAssetChanged001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::shared_ptr snapshot = std::make_shared(); auto snapshotKey = appId_ + "_" + sessionId_; - auto result = manager->OnAssetChanged(tokenId_, appId_, sessionId_, deviceId_, assetValue_); + 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_); + manager.snapshots_.Insert(snapshotKey, snapshot); + result = manager.OnAssetChanged(tokenId_, appId_, sessionId_, deviceId_, assetValue_); ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); } @@ -442,34 +653,17 @@ HWTEST_F(ObjectManagerTest, OnAssetChanged001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, DeleteSnapshot001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::shared_ptr snapshot = std::make_shared(); auto snapshotKey = bundleName_ + "_" + sessionId_; - auto snapshots = manager->snapshots_.Find(snapshotKey).second; + auto snapshots = manager.snapshots_.Find(snapshotKey).second; ASSERT_EQ(snapshots, nullptr); - manager->DeleteSnapshot(bundleName_, sessionId_); + manager.DeleteSnapshot(bundleName_, sessionId_); - manager->snapshots_.Insert(snapshotKey, snapshot); - snapshots = manager->snapshots_.Find(snapshotKey).second; + 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(); + manager.DeleteSnapshot(bundleName_, sessionId_); } /** @@ -481,19 +675,19 @@ HWTEST_F(ObjectManagerTest, OpenObjectKvStore001, TestSize.Level0) */ 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(); - ASSERT_NE(manager->delegate_, nullptr); - manager->FlushClosedStore(); - ASSERT_EQ(manager->delegate_, nullptr); + 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(); + ASSERT_NE(manager.delegate_, nullptr); + manager.FlushClosedStore(); + ASSERT_EQ(manager.delegate_, nullptr); } /** @@ -505,40 +699,13 @@ HWTEST_F(ObjectManagerTest, FlushClosedStore001, TestSize.Level0) */ 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(); - manager->delegate_ = manager->OpenObjectKvStore(); - std::function &results)> func; - func = [](const std::map &results) { - return results; - }; - std::string prefix = "ObjectManagerTest"; - std::vector deviceList; - // not local device & syncDevices empty - deviceList.push_back("local1"); - auto result = manager->SyncOnStore(prefix, deviceList, func); - ASSERT_NE(result, OBJECT_SUCCESS); - // local device - deviceList.push_back("local"); - result = manager->SyncOnStore(prefix, deviceList, func); - ASSERT_EQ(result, OBJECT_SUCCESS); + 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 } /** @@ -550,15 +717,15 @@ HWTEST_F(ObjectManagerTest, SyncOnStore001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, RetrieveFromStore001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); DistributedDB::KvStoreNbDelegateMock mockDelegate; - manager->delegate_ = &mockDelegate; + manager.delegate_ = &mockDelegate; std::vector id; - id.push_back(1); // for testing - id.push_back(2); // for testing + 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); + results = { { "test_cloud", id } }; + auto result = manager.RetrieveFromStore(appId_, sessionId_, results); ASSERT_EQ(result, OBJECT_SUCCESS); } @@ -571,28 +738,26 @@ HWTEST_F(ObjectManagerTest, RetrieveFromStore001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, SyncCompleted001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); auto syncManager = SequenceSyncManager::GetInstance(); std::map results; - results = {{ "test_cloud", DistributedDB::DBStatus::OK }}; + results = { { "test_cloud", DistributedDB::DBStatus::OK } }; std::function &results)> func; - func = [](const std::map &results) { - return results; - }; - manager->userId_ = "99"; + 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_); + manager.SyncCompleted(results, sequenceId_); + syncManager->userIdSeqIdRelations_ = { { "test_cloud", userId } }; + manager.SyncCompleted(results, sequenceId_); userId.clear(); syncManager->seqIdCallbackRelations_.emplace(sequenceId_, func); - manager->SyncCompleted(results, sequenceId_); + manager.SyncCompleted(results, sequenceId_); userId.push_back(99); userId.push_back(100); - manager->SyncCompleted(results, sequenceId_); - EXPECT_FALSE(manager->isSyncing_); + manager.SyncCompleted(results, sequenceId_); + EXPECT_FALSE(manager.isSyncing_); } /** @@ -604,12 +769,12 @@ HWTEST_F(ObjectManagerTest, SyncCompleted001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, SplitEntryKey001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::string key1 = ""; std::string key2 = "ObjectManagerTest"; - auto result = manager->SplitEntryKey(key1); + auto result = manager.SplitEntryKey(key1); ASSERT_EQ(result.empty(), true); - result = manager->SplitEntryKey(key2); + result = manager.SplitEntryKey(key2); ASSERT_EQ(result.empty(), true); } @@ -620,9 +785,9 @@ HWTEST_F(ObjectManagerTest, SplitEntryKey001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, SplitEntryKey002, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::string key1 = "com.example.myapplication_sessionId_source_target_1234567890_p_propertyName"; - auto res = manager->SplitEntryKey(key1); + auto res = manager.SplitEntryKey(key1); EXPECT_EQ(res[0], "com.example.myapplication"); EXPECT_EQ(res[1], "sessionId"); EXPECT_EQ(res[2], "source"); @@ -631,19 +796,19 @@ HWTEST_F(ObjectManagerTest, SplitEntryKey002, TestSize.Level0) EXPECT_EQ(res[5], "p_propertyName"); std::string key2 = "com.example.myapplication_sessionId_source_target_000_p_propertyName"; - res = manager->SplitEntryKey(key2); + res = manager.SplitEntryKey(key2); EXPECT_TRUE(res.empty()); std::string key3 = "com.example.myapplicationsessionIdsourcetarget_1234567890_p_propertyName"; - res = manager->SplitEntryKey(key3); + res = manager.SplitEntryKey(key3); EXPECT_TRUE(res.empty()); std::string key4 = "com.example.myapplicationsessionIdsource_target_1234567890_p_propertyName"; - res = manager->SplitEntryKey(key4); + res = manager.SplitEntryKey(key4); EXPECT_TRUE(res.empty()); std::string key5 = "com.example.myapplicationsessionId_source_target_1234567890_p_propertyName"; - res = manager->SplitEntryKey(key5); + res = manager.SplitEntryKey(key5); EXPECT_TRUE(res.empty()); } @@ -656,18 +821,18 @@ HWTEST_F(ObjectManagerTest, SplitEntryKey002, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, ProcessOldEntry001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); - manager->delegate_ = manager->OpenObjectKvStore(); + auto &manager = ObjectStoreManager::GetInstance(); + manager.delegate_ = manager.OpenObjectKvStore(); std::vector entries; - auto status = manager->delegate_->GetEntries(std::vector(appId_.begin(), appId_.end()), entries); + auto status = manager.delegate_->GetEntries(std::vector(appId_.begin(), appId_.end()), entries); ASSERT_EQ(status, DistributedDB::DBStatus::NOT_FOUND); - manager->ProcessOldEntry(appId_); + manager.ProcessOldEntry(appId_); DistributedDB::KvStoreNbDelegateMock mockDelegate; - manager->delegate_ = &mockDelegate; - status = manager->delegate_->GetEntries(std::vector(appId_.begin(), appId_.end()), entries); + manager.delegate_ = &mockDelegate; + status = manager.delegate_->GetEntries(std::vector(appId_.begin(), appId_.end()), entries); ASSERT_EQ(status, DistributedDB::DBStatus::OK); - manager->ProcessOldEntry(appId_); + manager.ProcessOldEntry(appId_); } /** @@ -679,13 +844,13 @@ HWTEST_F(ObjectManagerTest, ProcessOldEntry001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, ProcessSyncCallback001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::map results; - manager->ProcessSyncCallback(results, appId_, sessionId_, deviceId_); - results.insert({"local", 1}); // for testing + 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_); + manager.ProcessSyncCallback(results, appId_, sessionId_, deviceId_); } /** @@ -696,23 +861,23 @@ HWTEST_F(ObjectManagerTest, ProcessSyncCallback001, TestSize.Level0) HWTEST_F(ObjectManagerTest, ProcessSyncCallback002, TestSize.Level0) { std::string dataDir = "/data/app/el2/100/database"; - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::map results; - - results.insert({"remote", 1}); // for testing + + results.insert({ "remote", 1 }); // for testing ASSERT_EQ(results.empty(), false); ASSERT_EQ(results.find("local"), results.end()); - manager->kvStoreDelegateManager_ = nullptr; + manager.kvStoreDelegateManager_ = nullptr; // open store failed -> success - manager->ProcessSyncCallback(results, appId_, sessionId_, deviceId_); + manager.ProcessSyncCallback(results, appId_, sessionId_, deviceId_); // open store success -> success - manager->SetData(dataDir, userId_); - ASSERT_NE(manager->kvStoreDelegateManager_, nullptr); - manager->delegate_ = manager->OpenObjectKvStore(); - ASSERT_NE(manager->delegate_, nullptr); - manager->ProcessSyncCallback(results, appId_, sessionId_, deviceId_); + manager.SetData(dataDir, userId_); + ASSERT_NE(manager.kvStoreDelegateManager_, nullptr); + manager.delegate_ = manager.OpenObjectKvStore(); + ASSERT_NE(manager.delegate_, nullptr); + manager.ProcessSyncCallback(results, appId_, sessionId_, deviceId_); } /** @@ -724,32 +889,32 @@ HWTEST_F(ObjectManagerTest, ProcessSyncCallback002, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, IsAssetComplete001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + results.insert({ assetPrefix + ObjectStore::SIZE_SUFFIX, completes }); + result = manager.IsAssetComplete(results, assetPrefix); ASSERT_EQ(result, true); } @@ -762,18 +927,18 @@ HWTEST_F(ObjectManagerTest, IsAssetComplete001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, GetAssetsFromDBRecords001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + 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); + 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); } @@ -784,14 +949,14 @@ HWTEST_F(ObjectManagerTest, GetAssetsFromDBRecords001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, GetAssetsFromDBRecords002, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::map> result; - std::vector value0{0}; + std::vector value0{ 0 }; std::string data0 = "[STRING]test"; value0.insert(value0.end(), data0.begin(), data0.end()); - std::vector value1{0}; + std::vector value1{ 0 }; std::string data1 = "(string)test"; value1.insert(value1.end(), data1.begin(), data1.end()); @@ -800,26 +965,26 @@ HWTEST_F(ObjectManagerTest, GetAssetsFromDBRecords002, TestSize.Level0) std::string assetPrefix0 = prefix + "_p_asset0"; std::string assetPrefix1 = prefix + "_p_asset1"; - result.insert({dataKey, value0}); - auto assets = manager->GetAssetsFromDBRecords(result); + 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); + 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); + 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); + 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"); @@ -828,11 +993,11 @@ HWTEST_F(ObjectManagerTest, GetAssetsFromDBRecords002, TestSize.Level0) 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); + 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"); @@ -850,14 +1015,14 @@ HWTEST_F(ObjectManagerTest, GetAssetsFromDBRecords002, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, RegisterAssetsLister001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); - manager->objectAssetsSendListener_ = nullptr; - manager->objectAssetsRecvListener_ = nullptr; - auto result = manager->RegisterAssetsLister(); + 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(); + manager.objectAssetsSendListener_ = new ObjectAssetsSendListener(); + manager.objectAssetsRecvListener_ = new ObjectAssetsRecvListener(); + result = manager.RegisterAssetsLister(); ASSERT_EQ(result, true); } @@ -870,14 +1035,14 @@ HWTEST_F(ObjectManagerTest, RegisterAssetsLister001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, PushAssets001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + 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(appId_, appId_, sessionId_, data, deviceId_); + data.insert({ assetPrefix, completes }); + auto result = manager.PushAssets(appId_, appId_, sessionId_, data, deviceId_); ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); } @@ -888,9 +1053,9 @@ HWTEST_F(ObjectManagerTest, PushAssets001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, PushAssets002, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::map> data; - std::vector value{0}; + std::vector value{ 0 }; std::string data0 = "[STRING]test"; value.insert(value.end(), data0.begin(), data0.end()); @@ -900,19 +1065,19 @@ HWTEST_F(ObjectManagerTest, PushAssets002, TestSize.Level0) std::string fieldsPrefix = "p_"; std::string deviceIdKey = "__deviceId"; - data.insert({assetPrefix + ObjectStore::NAME_SUFFIX, value}); - data.insert({assetPrefix + ObjectStore::URI_SUFFIX, value}); - data.insert({assetPrefix + ObjectStore::MODIFY_TIME_SUFFIX, value}); - data.insert({assetPrefix + ObjectStore::SIZE_SUFFIX, value}); - data.insert({fieldsPrefix + deviceIdKey, value}); + data.insert({ assetPrefix + ObjectStore::NAME_SUFFIX, value }); + data.insert({ assetPrefix + ObjectStore::URI_SUFFIX, value }); + data.insert({ assetPrefix + ObjectStore::MODIFY_TIME_SUFFIX, value }); + data.insert({ assetPrefix + ObjectStore::SIZE_SUFFIX, value }); + data.insert({ fieldsPrefix + deviceIdKey, value }); - manager->objectAssetsSendListener_ = nullptr; - int32_t ret = manager->PushAssets(appId_, appId_, sessionId_, data, deviceId_); + manager.objectAssetsSendListener_ = nullptr; + int32_t ret = manager.PushAssets(appId_, appId_, sessionId_, data, deviceId_); EXPECT_NE(ret, DistributedObject::OBJECT_SUCCESS); - manager->objectAssetsSendListener_ = new ObjectAssetsSendListener(); - ASSERT_NE(manager->objectAssetsSendListener_, nullptr); - ret = manager->PushAssets(appId_, appId_, sessionId_, data, deviceId_); + manager.objectAssetsSendListener_ = new ObjectAssetsSendListener(); + ASSERT_NE(manager.objectAssetsSendListener_, nullptr); + ret = manager.PushAssets(appId_, appId_, sessionId_, data, deviceId_); EXPECT_NE(ret, DistributedObject::OBJECT_SUCCESS); } @@ -925,9 +1090,7 @@ HWTEST_F(ObjectManagerTest, AddNotifier001, TestSize.Level0) { auto syncManager = SequenceSyncManager::GetInstance(); std::function &results)> func; - func = [](const std::map &results) { - return results; - }; + 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); @@ -942,9 +1105,7 @@ HWTEST_F(ObjectManagerTest, AddNotifier002, TestSize.Level0) { auto syncManager = SequenceSyncManager::GetInstance(); std::function &results)> func; - func = [](const std::map &results) { - return results; - }; + func = [](const std::map &results) { return results; }; auto sequenceId = syncManager->AddNotifier(userId_, func); ASSERT_NE(sequenceId, sequenceId_); auto result = syncManager->DeleteNotifier(sequenceId_, userId_); @@ -958,10 +1119,10 @@ HWTEST_F(ObjectManagerTest, AddNotifier002, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, BindAsset001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::string bundleName = "BindAsset"; uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); - auto result = manager->BindAsset(tokenId, bundleName, sessionId_, assetValue_, assetBindInfo_); + auto result = manager.BindAsset(tokenId, bundleName, sessionId_, assetValue_, assetBindInfo_); ASSERT_EQ(result, DistributedObject::OBJECT_DBSTATUS_ERROR); } @@ -995,7 +1156,7 @@ HWTEST_F(ObjectManagerTest, OnFinished001, TestSize.Level1) */ HWTEST_F(ObjectManagerTest, GetObjectData001, TestSize.Level1) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::string bundleName = bundleName_; std::string sessionId = sessionId_; @@ -1009,9 +1170,9 @@ HWTEST_F(ObjectManagerTest, GetObjectData001, TestSize.Level1) // p_name not asset key std::string p_name = "p_namejpg"; std::string key = bundleName + "_" + sessionId + "_" + source + "_" + target + "_" + timestamp + "_" + p_name; - std::map> changedData = {{ key, data_ }}; + std::map> changedData = { { key, data_ } }; bool hasAsset = false; - auto ret = manager->GetObjectData(changedData, saveInfo, hasAsset); + auto ret = manager.GetObjectData(changedData, saveInfo, hasAsset); EXPECT_FALSE(ret.empty()); EXPECT_FALSE(hasAsset); } @@ -1023,7 +1184,7 @@ HWTEST_F(ObjectManagerTest, GetObjectData001, TestSize.Level1) */ HWTEST_F(ObjectManagerTest, GetObjectData002, TestSize.Level1) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::string bundleName = ""; std::string sessionId = ""; @@ -1045,9 +1206,9 @@ HWTEST_F(ObjectManagerTest, GetObjectData002, TestSize.Level1) timestamp = "1234567890"; std::string p_name = "p_name.jpg"; std::string key = bundleName + "_" + sessionId + "_" + source + "_" + target + "_" + timestamp + "_" + p_name; - std::map> changedData = {{ key, data_ }}; + std::map> changedData = { { key, data_ } }; bool hasAsset = false; - auto ret = manager->GetObjectData(changedData, saveInfo, hasAsset); + auto ret = manager.GetObjectData(changedData, saveInfo, hasAsset); EXPECT_FALSE(ret.empty()); EXPECT_EQ(saveInfo.bundleName, bundleName); EXPECT_TRUE(hasAsset); @@ -1058,11 +1219,259 @@ HWTEST_F(ObjectManagerTest, GetObjectData002, TestSize.Level1) // p_name not asset key p_name = "p_namejpg"; std::string key_1 = bundleName + "_" + sessionId + "_" + source + "_" + target + "_" + timestamp + "_" + p_name; - std::map> changedData_1 = {{ key_1, data_ }}; + std::map> changedData_1 = { { key_1, data_ } }; hasAsset = false; - ret = manager->GetObjectData(changedData_1, saveInfo, hasAsset); + ret = manager.GetObjectData(changedData_1, saveInfo, hasAsset); EXPECT_FALSE(ret.empty()); EXPECT_NE(saveInfo.bundleName, bundleName); EXPECT_FALSE(hasAsset); } + +/** +* @tc.name: InitUserMeta001 +* @tc.desc: test clear old user meta. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, InitUserMeta001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + auto status = manager.InitUserMeta(); + ASSERT_EQ(status, DistributedObject::OBJECT_SUCCESS); +} + +/** +* @tc.name: registerAndUnregisterProgressObserverCallback001 +* @tc.desc: test RegisterProgressObserverCallback and UnregisterProgressObserverCallback. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ObjectManagerTest, registerAndUnregisterProgressObserverCallback001, TestSize.Level0) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::function cb = [](int32_t progress) {}; + sptr objectRemoteResumeCallback = new (std::nothrow) ObjectProgressCallback(cb); + ASSERT_NE(objectRemoteResumeCallback, nullptr); + manager.RegisterProgressObserverCallback(bundleName_, sessionId_, pid_, tokenId_, + objectRemoteResumeCallback->AsObject()); + ObjectStoreManager::ProgressCallbackInfo progressCallbackInfo = manager.processCallbacks_.Find(tokenId_).second; + std::string objectKey = bundleName_ + sessionId_; + ASSERT_NE(progressCallbackInfo.observers_.find(objectKey), progressCallbackInfo.observers_.end()); + manager.UnregisterProgressObserverCallback(bundleName_, pid_, tokenId_, sessionId_); + progressCallbackInfo = manager.processCallbacks_.Find(tokenId_).second; + ASSERT_EQ(progressCallbackInfo.observers_.find(objectKey), progressCallbackInfo.observers_.end()); +} + +/** +* @tc.name: registerAndUnregisterProgressObserverCallback002 +* @tc.desc: abnormal use cases. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ObjectManagerTest, registerAndUnregisterProgressObserverCallback002, TestSize.Level0) +{ + auto &manager = ObjectStoreManager::GetInstance(); + sptr callback; + uint32_t tokenId = 101; + manager.RegisterProgressObserverCallback("", sessionId_, pid_, tokenId, callback); + manager.RegisterProgressObserverCallback(bundleName_, "", pid_, tokenId, callback); + manager.RegisterProgressObserverCallback("", "", pid_, tokenId, callback); + ObjectStoreManager::ProgressCallbackInfo progressCallbackInfo = manager.processCallbacks_.Find(tokenId_).second; + progressCallbackInfo.pid = pid_; + manager.RegisterProgressObserverCallback(bundleName_, sessionId_, pid_, tokenId_, callback); + ASSERT_EQ(manager.processCallbacks_.Find(tokenId).first, false); + manager.UnregisterProgressObserverCallback("", pid_, tokenId, sessionId_); + manager.UnregisterProgressObserverCallback("", pid_, tokenId, ""); + manager.UnregisterProgressObserverCallback(bundleName_, pid_, tokenId, ""); +} + +/** +* @tc.name: NotifyAssetsRecvProgress001 +* @tc.desc: NotifyAssetsRecvProgress test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ObjectManagerTest, NotifyAssetsRecvProgress001, TestSize.Level0) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string objectKey = bundleName_ + sessionId_; + std::string errProgress = "errProgress"; + int32_t progress = 99; + ObjectStoreManager::ProgressCallbackInfo progressCallbackInfo = manager.processCallbacks_.Find(tokenId_).second; + manager.NotifyAssetsRecvProgress(objectKey, progress); + ASSERT_EQ(manager.assetsRecvProgress_.Find(objectKey).first, true); + manager.assetsRecvProgress_.Clear(); + manager.assetsRecvProgress_.Insert(objectKey, progress); + manager.NotifyAssetsRecvProgress(errProgress, progress); + progressCallbackInfo.observers_.clear(); +} + +/** +* @tc.name: OnRecvProgress001 +* @tc.desc: OnRecvProgress test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, OnRecvProgress001, TestSize.Level1) +{ + std::string srcNetworkId = "srcNetworkId"; + sptr assetObj = nullptr; + uint64_t totalBytes = 100; + uint64_t processBytes = 100; + ObjectAssetsRecvListener listener; + int32_t ret = listener.OnRecvProgress(srcNetworkId, assetObj, totalBytes, processBytes); + EXPECT_EQ(ret, DistributedObject::OBJECT_INNER_ERROR); + uint64_t totalBytes_01 = 0; + ret = listener.OnRecvProgress(srcNetworkId, assetObj, totalBytes_01, processBytes); + EXPECT_EQ(ret, DistributedObject::OBJECT_INNER_ERROR); + sptr assetObj_1 = new AssetObj(); + ret = listener.OnRecvProgress(srcNetworkId, assetObj_1, totalBytes_01, processBytes); + EXPECT_EQ(ret, DistributedObject::OBJECT_INNER_ERROR); + ret = listener.OnRecvProgress(srcNetworkId, assetObj_1, totalBytes, processBytes); + EXPECT_EQ(ret, DistributedObject::OBJECT_SUCCESS); +} + +/** +* @tc.name: OnFinished002 +* @tc.desc: OnFinished test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, OnFinished002, TestSize.Level1) +{ + std::string srcNetworkId = "srcNetworkId"; + ObjectAssetsRecvListener listener; + sptr assetObj_1 = new AssetObj(); + assetObj_1->dstBundleName_ = bundleName_; + assetObj_1->srcBundleName_ = bundleName_; + assetObj_1->dstNetworkId_ = "1"; + assetObj_1->sessionId_ = "123"; + int32_t result = 100; + auto ret = listener.OnFinished(srcNetworkId, assetObj_1, result); + int32_t result_1 = 0; + ret = listener.OnFinished(srcNetworkId, assetObj_1, result_1); + EXPECT_EQ(ret, DistributedObject::OBJECT_SUCCESS); +} + +/** +* @tc.name: Save001 +* @tc.desc: Save test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, Save001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string appId = "appId"; + std::string sessionId = "sessionId"; + ObjectRecord data; + std::string deviceId = "deviceId"; + auto ret = manager.Save(appId, sessionId, data, deviceId, nullptr); + EXPECT_EQ(ret, DistributedKv::INVALID_ARGUMENT); +} + +/** +* @tc.name: Save002 +* @tc.desc: Save test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, Save002, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string appId = "appId"; + std::string sessionId = "sessionId"; + ObjectRecord data; + std::string deviceId = ""; + std::function &)> cb = [](const std::map &) {}; + sptr objectSaveCallback = new (std::nothrow) ObjectSaveCallback(cb); + ASSERT_NE(objectSaveCallback, nullptr); + auto ret = manager.Save(appId, sessionId, data, deviceId, objectSaveCallback->AsObject()); + EXPECT_EQ(ret, DistributedKv::INVALID_ARGUMENT); +} + +/** +* @tc.name: RevokeSave001 +* @tc.desc: RevokeSave test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, RevokeSave001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string appId = "appId"; + std::string sessionId = "sessionId"; + auto ret = manager.RevokeSave(appId, sessionId, nullptr); + EXPECT_EQ(ret, DistributedKv::INVALID_ARGUMENT); +} + +/** +* @tc.name: RevokeSave002 +* @tc.desc: RevokeSave test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, RevokeSave002, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string appId = "appId"; + std::string sessionId = "sessionId"; + std::function cb = [](int32_t) {}; + sptr objectRevokeSaveCallback = new (std::nothrow) ObjectRevokeSaveCallback(cb); + ASSERT_NE(objectRevokeSaveCallback, nullptr); + auto ret = manager.RevokeSave(appId, sessionId, objectRevokeSaveCallback->AsObject()); + EXPECT_EQ(ret, DistributedObject::OBJECT_SUCCESS); +} + +/** +* @tc.name: Retrieve001 +* @tc.desc: Retrieve test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, Retrieve001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string bundleName = "bundleName"; + std::string sessionId = "sessionId"; + uint32_t tokenId = 0; + auto ret = manager.Retrieve(bundleName, sessionId, nullptr, tokenId); + EXPECT_EQ(ret, DistributedKv::INVALID_ARGUMENT); +} + +/** +* @tc.name: Retrieve002 +* @tc.desc: Retrieve test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, Retrieve002, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string bundleName = "bundleName"; + std::string sessionId = "sessionId"; + uint32_t tokenId = 0; + std::function> &, bool)> cb = + [](const std::map> &, bool) {}; + sptr objectRetrieveCallback = new (std::nothrow) ObjectRetrieveCallback(cb); + ASSERT_NE(objectRetrieveCallback, nullptr); + auto ret = manager.Retrieve(bundleName, sessionId, objectRetrieveCallback->AsObject(), tokenId); + EXPECT_EQ(ret, DistributedKv::KEY_NOT_FOUND); +} + +/** +* @tc.name: GetSnapShots001 +* @tc.desc: ObjectStoreManager get snapShots test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, GetSnapShots001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string bundleName = "bundleA"; + std::string storeName = "storeA"; + + auto ptr1 = manager.GetSnapShots(bundleName, storeName); + ASSERT_NE(ptr1, nullptr); + EXPECT_TRUE(ptr1->empty()); + auto snapshot = std::make_shared(); + (*ptr1)["snap1"] = snapshot; + + auto ptr2 = manager.GetSnapShots(bundleName, storeName); + EXPECT_EQ(ptr1, ptr2); + EXPECT_EQ((*ptr2)["snap1"], snapshot); +} } // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/service/test/object_service_impl_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_service_impl_test.cpp index e67f493ab070d8e8f2db8e014700ac400055d52b..79bd608f9ce0742a8e1dabc568dac49e36957164 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_service_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_service_impl_test.cpp @@ -20,11 +20,14 @@ #include #include "accesstoken_kit.h" +#include "device_manager_adapter_mock.h" #include "ipc_skeleton.h" #include "token_setproc.h" using namespace testing::ext; using namespace OHOS::DistributedObject; +using namespace std; +using namespace testing; namespace OHOS::Test { class ObjectServiceImplTest : public testing::Test { public: @@ -45,11 +48,12 @@ protected: ObjectStore::AssetBindInfo assetBindInfo_; pid_t pid_ = 10; uint32_t tokenId_ = 100; + static inline std::shared_ptr devMgrAdapterMock = nullptr; }; void ObjectServiceImplTest::SetUp() { - uri_ = "file:://com.examples.hmos.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; + uri_ = "file:://com.examples.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; ObjectStore::Asset asset{ .id = "test_name", .name = uri_, @@ -73,9 +77,14 @@ void ObjectServiceImplTest::SetUp() .assetName = "asset1.jpg", }; assetBindInfo_ = AssetBindInfo; + devMgrAdapterMock = make_shared(); + BDeviceManagerAdapter::deviceManagerAdapter = devMgrAdapterMock; } -void ObjectServiceImplTest::TearDown() {} +void ObjectServiceImplTest::TearDown() +{ + devMgrAdapterMock = nullptr; +} /** * @tc.name: OnAssetChanged001 @@ -84,7 +93,7 @@ void ObjectServiceImplTest::TearDown() {} */ HWTEST_F(ObjectServiceImplTest, OnAssetChanged001, TestSize.Level1) { - std::string bundleName = "com.examples.hmos.notepad"; + std::string bundleName = "com.examples.notepad"; OHOS::Security::AccessToken::AccessTokenID tokenId = OHOS::Security::AccessToken::AccessTokenKit::GetHapTokenID(100, bundleName, 0); SetSelfTokenID(tokenId); @@ -103,7 +112,7 @@ HWTEST_F(ObjectServiceImplTest, OnAssetChanged001, TestSize.Level1) */ HWTEST_F(ObjectServiceImplTest, BindAssetStore001, TestSize.Level1) { - std::string bundleName = "com.examples.hmos.notepad"; + std::string bundleName = "com.examples.notepad"; OHOS::Security::AccessToken::AccessTokenID tokenId = OHOS::Security::AccessToken::AccessTokenKit::GetHapTokenID(100, bundleName, 0); SetSelfTokenID(tokenId); @@ -122,7 +131,7 @@ HWTEST_F(ObjectServiceImplTest, BindAssetStore001, TestSize.Level1) */ HWTEST_F(ObjectServiceImplTest, DeleteSnapshot001, TestSize.Level1) { - std::string bundleName = "com.examples.hmos.notepad"; + std::string bundleName = "com.examples.notepad"; OHOS::Security::AccessToken::AccessTokenID tokenId = OHOS::Security::AccessToken::AccessTokenKit::GetHapTokenID(100, bundleName, 0); SetSelfTokenID(tokenId); @@ -149,6 +158,47 @@ HWTEST_F(ObjectServiceImplTest, ResolveAutoLaunch001, TestSize.Level1) std::string identifier = "identifier"; std::shared_ptr objectServiceImpl = std::make_shared(); int32_t ret = objectServiceImpl->ResolveAutoLaunch(identifier, param); - EXPECT_EQ(ret, OBJECT_STORE_NOT_FOUND); + EXPECT_EQ(ret, OBJECT_SUCCESS); +} + +/** + * @tc.name: OnInitialize001 + * @tc.desc: OnInitialize test. + * @tc.type: FUNC + */ +HWTEST_F(ObjectServiceImplTest, OnInitialize001, TestSize.Level1) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + objectServiceImpl->executors_ = nullptr; + DeviceInfo devInfo = { .uuid = "123" }; + EXPECT_CALL(*devMgrAdapterMock, GetLocalDevice()) + .WillOnce(Return(devInfo)); + int32_t ret = objectServiceImpl->OnInitialize(); + EXPECT_EQ(ret, OBJECT_INNER_ERROR); +} + +/** + * @tc.name: RegisterProgressObserver001 + * @tc.desc: RegisterProgressObserver test. + * @tc.type: FUNC + */ +HWTEST_F(ObjectServiceImplTest, RegisterProgressObserver001, TestSize.Level1) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + sptr callback; + int32_t ret = objectServiceImpl->RegisterProgressObserver(bundleName_, sessionId_, callback); + EXPECT_EQ(ret, OBJECT_PERMISSION_DENIED); +} + +/** + * @tc.name: UnregisterProgressObserver001 + * @tc.desc: UnregisterProgressObserver test. + * @tc.type: FUNC + */ +HWTEST_F(ObjectServiceImplTest, UnregisterProgressObserver001, TestSize.Level1) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + int32_t ret = objectServiceImpl->UnregisterProgressObserver(bundleName_, sessionId_); + EXPECT_EQ(ret, OBJECT_PERMISSION_DENIED); } } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/object_service_stub_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_service_stub_test.cpp index 1cbb5e1a50af60a3f88510fde236c00b25c5d19a..274ef0f979dc43a76f24031e74a9f61128d3873d 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_service_stub_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_service_stub_test.cpp @@ -99,6 +99,12 @@ HWTEST_F(ObjectServiceStubTest, ObjectServiceTest002, TestSize.Level1) result = objectServiceStub->ObjectStoreBindAssetOnRemote(request, reply); EXPECT_EQ(result, IPC_STUB_INVALID_DATA_ERR); + result = objectServiceStub->OnSubscribeProgress(request, reply); + EXPECT_EQ(result, IPC_STUB_INVALID_DATA_ERR); + + result = objectServiceStub->OnUnsubscribeProgress(request, reply); + EXPECT_EQ(result, IPC_STUB_INVALID_DATA_ERR); + result = objectServiceStub->OnDeleteSnapshot(request, reply); EXPECT_EQ(result, IPC_STUB_INVALID_DATA_ERR); diff --git a/datamgr_service/services/distributeddataservice/service/test/object_snapshot_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_snapshot_test.cpp index 37cee3e9cc447305c8b345428a5c6b5309332284..0826280fb6c6c69abbc10c0906b0d303819a117b 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_snapshot_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_snapshot_test.cpp @@ -41,7 +41,7 @@ protected: void ObjectSnapshotTest::SetUp() { - uri_ = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; + uri_ = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; Asset asset{ .name = "test_name", .uri = uri_, @@ -85,7 +85,7 @@ 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", + .uri = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", .modifyTime = "modifyTime1", .size = "size1", .hash = "modifyTime1_size1", @@ -124,7 +124,7 @@ 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", + .uri = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", .modifyTime = "modifyTime1", .size = "size1", .hash = "modifyTime1_size1", @@ -163,7 +163,7 @@ 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", + .uri = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", .modifyTime = "modifyTime1", .size = "size1", .hash = "modifyTime1_size1", @@ -202,7 +202,7 @@ 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", + .uri = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", .modifyTime = "modifyTime1", .size = "size1", .hash = "modifyTime1_size1", @@ -241,7 +241,7 @@ 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", + .uri = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", .modifyTime = "modifyTime1", .size = "size1", .hash = "modifyTime1_size1", @@ -280,7 +280,7 @@ 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", + .uri = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", .modifyTime = "modifyTime1", .size = "size1", .hash = "modifyTime1_size1", @@ -320,7 +320,7 @@ HWTEST_F(ObjectSnapshotTest, OnDataChangedTest001, TestSize.Level0) 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", + .uri = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", .modifyTime = "modifyTime1", .size = "size1", .hash = "modifyTime1_size1", @@ -360,7 +360,7 @@ 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", + .uri = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", .modifyTime = "modifyTime1", .size = "size1", .hash = "modifyTime1_size1", diff --git a/datamgr_service/services/distributeddataservice/service/test/ohos_test/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/ohos_test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..ed9f42f06bcf08c2ed4e3d387a45dd0c9b7b9d9a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/ohos_test/BUILD.gn @@ -0,0 +1,21 @@ +# Copyright (c) 2025 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") + +ohos_copy("copy_ohos_test") { + subsystem_name = "distributeddatamgr" + part_name = "datamgr_service" + sources = [ "./ohos_test.xml" ] + outputs = [ "$root_out_dir/tests/unittest/datamgr_service/datamgr_service/resource/ohos_test.xml" ] +} diff --git a/datamgr_service/services/distributeddataservice/service/test/ohos_test/ohos_test.xml b/datamgr_service/services/distributeddataservice/service/test/ohos_test/ohos_test.xml new file mode 100644 index 0000000000000000000000000000000000000000..8586520c773ed0cc9a524e8a08084ed30a5aaa93 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/ohos_test/ohos_test.xml @@ -0,0 +1,28 @@ + + + + + + + + + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/permit_delegate_mock_test.cpp b/datamgr_service/services/distributeddataservice/service/test/permit_delegate_mock_test.cpp index e312860bcc31aacf2b0ed137a7dc4b8c97ec0ff6..791708732475bdee3d11769602b0e29cd6c1174a 100644 --- a/datamgr_service/services/distributeddataservice/service/test/permit_delegate_mock_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/permit_delegate_mock_test.cpp @@ -165,12 +165,13 @@ HWTEST_F(PermitDelegateMockTest, VerifyPermission001, testing::ext::TestSize.Lev ASSERT_TRUE(result); AppIDMetaData appMeta("permitdelegatemocktestId", "com.permitdelegatetest.app"); EXPECT_CALL(*metaDataMgrMock, LoadMeta(_, _, _)).WillOnce(DoAll(SetArgReferee<1>(appMeta), Return(true))); - CheckParam checkParam; - checkParam.appId = "permitdelegatemocktestId"; - checkParam.userId = "userid"; - checkParam.storeId = "storeid"; - checkParam.deviceId = "deviceid"; - checkParam.instanceId = 1; + CheckParam checkParam = { + .appId = "permitdelegatemocktestId", + .userId = "userid", + .storeId = "storeid", + .deviceId = "deviceid", + .instanceId = 1 + }; uint8_t flag = 1; EXPECT_CALL(*metaDataMgrMock, LoadMeta(_, _, false)).WillOnce(Return(false)); result = PermitDelegate::GetInstance().VerifyPermission(checkParam, flag); @@ -192,8 +193,8 @@ HWTEST_F(PermitDelegateMockTest, VerifyPermission002, testing::ext::TestSize.Lev auto ret = PermitDelegate::GetInstance().appId2BundleNameMap_.Find(key); ASSERT_TRUE(ret.second == value); CheckParam checkParam = { - .userId = "userid2", .appId = "permitdelegatemocktestId2", + .userId = "userid2", .storeId = "storeid2", .deviceId = "deviceid2", .instanceId = 0 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 f8d56ca2c2b530373d6f5a4e8aa186e6e058583c..e261e4cc3993f7bff39e872c309fc1579c42524a 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 @@ -16,13 +16,15 @@ #include "rdb_asset_loader.h" -#include "gtest/gtest.h" #include "log_print.h" +#include "object_snapshot.h" #include "rdb_notifier_proxy.h" #include "rdb_watcher.h" #include "store/cursor.h" #include "store/general_value.h" #include "store/general_watcher.h" +#include "gtest/gtest.h" + using namespace OHOS; using namespace testing; using namespace testing::ext; @@ -88,7 +90,7 @@ HWTEST_F(RdbAssetLoaderTest, Download, TestSize.Level0) { BindAssets bindAssets; std::shared_ptr cloudAssetLoader = std::make_shared(); - DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, bindAssets); std::string tableName = "testTable"; std::string groupId = "testGroup"; Type prefix; @@ -109,7 +111,7 @@ HWTEST_F(RdbAssetLoaderTest, BatchDownload, TestSize.Level0) { BindAssets bindAssets; auto cloudAssetLoader = std::make_shared(); - DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, bindAssets); std::string tableName = "testTable"; Type prefix; std::map assets; @@ -133,7 +135,7 @@ HWTEST_F(RdbAssetLoaderTest, Convert001, TestSize.Level0) { BindAssets bindAssets; auto cloudAssetLoader = std::make_shared(); - DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, bindAssets); Type prefix; std::map assets; assets["asset1"].push_back(g_rdbAsset); @@ -156,7 +158,7 @@ HWTEST_F(RdbAssetLoaderTest, Convert002, TestSize.Level0) { BindAssets bindAssets; auto cloudAssetLoader = std::make_shared(); - DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, bindAssets); Value prefix; VBucket assets; std::vector assetsRecords; @@ -177,7 +179,7 @@ HWTEST_F(RdbAssetLoaderTest, RemoveLocalAssets, TestSize.Level0) { BindAssets bindAssets; std::shared_ptr cloudAssetLoader = std::make_shared(); - DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, bindAssets); std::vector assets; assets.push_back(g_rdbAsset); auto result = rdbAssetLoader.RemoveLocalAssets(assets); @@ -194,12 +196,12 @@ HWTEST_F(RdbAssetLoaderTest, RemoveLocalAssets, TestSize.Level0) HWTEST_F(RdbAssetLoaderTest, CancelDownloadTest, TestSize.Level0) { BindAssets bindAssets; - DistributedRdb::RdbAssetLoader rdbAssetLoader1(nullptr, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader1(nullptr, bindAssets); auto result = rdbAssetLoader1.CancelDownload(); EXPECT_EQ(result, DistributedDB::DBStatus::DB_ERROR); std::shared_ptr cloudAssetLoader = std::make_shared(); - DistributedRdb::RdbAssetLoader rdbAssetLoader2(cloudAssetLoader, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader2(cloudAssetLoader, bindAssets); result = rdbAssetLoader2.CancelDownload(); EXPECT_EQ(result, DistributedDB::DBStatus::OK); } @@ -213,10 +215,9 @@ HWTEST_F(RdbAssetLoaderTest, CancelDownloadTest, TestSize.Level0) */ HWTEST_F(RdbAssetLoaderTest, PostEvent001, TestSize.Level0) { - BindAssets bindAssets; - bindAssets.bindAssets = nullptr; + BindAssets bindAssets = nullptr; std::shared_ptr assetLoader = std::make_shared(); - DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); std::string tableName = "testTable"; std::string groupId = "testGroup"; Type prefix; @@ -235,29 +236,328 @@ HWTEST_F(RdbAssetLoaderTest, PostEvent001, TestSize.Level0) */ HWTEST_F(RdbAssetLoaderTest, PostEvent002, TestSize.Level0) { - DistributedData::Asset asset; - asset.name = ""; - asset.id = ""; - asset.path = ""; - asset.uri = ""; - asset.modifyTime = ""; - asset.createTime = ""; - asset.size = ""; - asset.hash = ""; - asset.status = DistributedData::Asset::STATUS_DELETE; - + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_DELETE, + }; DistributedData::Assets assets; assets.push_back(asset); - BindAssets bindAssets; - bindAssets.bindAssets = nullptr; + BindAssets bindAssets = nullptr; std::shared_ptr assetLoader = std::make_shared(); - DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); std::set skipAssets; std::set deleteAssets; rdbAssetLoader.PostEvent(DistributedData::AssetEvent::DOWNLOAD, assets, skipAssets, deleteAssets); EXPECT_EQ(deleteAssets.size(), 1); } +/** +@tc.name: PostEvent003 +@tc.desc: RdbAssetLoader PostEvent003 test +@tc.type: FUNC +@tc.require: +@tc.author: SQL +*/ +HWTEST_F(RdbAssetLoaderTest, PostEvent003, TestSize.Level0) { + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_NORMAL, + }; + DistributedData::Assets assets; + assets.push_back(asset); + BindAssets bindAssets = nullptr; + std::shared_ptr assetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); + std::set skipAssets; + std::set deleteAssets; + rdbAssetLoader.PostEvent(DistributedData::AssetEvent::DOWNLOAD, assets, skipAssets, deleteAssets); + EXPECT_EQ(deleteAssets.size(), 0); + EXPECT_EQ(skipAssets.size(), 0); +} + +/** +@tc.name: PostEvent004 +@tc.desc: RdbAssetLoader PostEvent004 test,snapshots_ can find data with a value of null +@tc.type: FUNC +@tc.require: +@tc.author: SQL +*/ +HWTEST_F(RdbAssetLoaderTest, PostEvent004, TestSize.Level0) { + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "PostEvent004", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_NORMAL, + }; + DistributedData::Assets assets; + assets.push_back(asset); + BindAssets bindAssets = std::make_shared>>(); + bindAssets->insert({"PostEvent004", nullptr}); + std::shared_ptr assetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); + std::set skipAssets; + std::set deleteAssets; + rdbAssetLoader.PostEvent(DistributedData::AssetEvent::DOWNLOAD, assets, skipAssets, deleteAssets); + EXPECT_EQ(deleteAssets.size(), 0); + EXPECT_EQ(skipAssets.size(), 0); +} + +/** +@tc.name: PostEvent005 +@tc.desc: RdbAssetLoader PostEvent005 test,snapshots_ can find data and the value is not null +@tc.type: FUNC +@tc.require: +@tc.author: SQL +*/ +HWTEST_F(RdbAssetLoaderTest, PostEvent005, TestSize.Level0) { + class ObjectSnapshotMock : public DistributedObject::ObjectSnapshot { + public: + int32_t Download(Asset &asset) override { + hasDownload = true; + return 0; + } + bool hasDownload = false; + }; + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "PostEvent005", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_NORMAL, + }; + DistributedData::Assets assets; + assets.push_back(asset); + BindAssets bindAssets = std::make_shared>>(); + auto objectSnapshotMock = std::make_shared(); + bindAssets->insert({"PostEvent005", objectSnapshotMock}); + std::shared_ptr assetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); + std::set skipAssets; + std::set deleteAssets; + rdbAssetLoader.PostEvent(DistributedData::AssetEvent::DOWNLOAD, assets, + skipAssets, deleteAssets); + EXPECT_EQ(objectSnapshotMock->hasDownload, true); +} + +/** +@tc.name: PostEvent006 +@tc.desc: RdbAssetLoader PostEvent006 test,snapshots_ not found +@tc.type: FUNC +@tc.require: +@tc.author: SQL +*/ +HWTEST_F(RdbAssetLoaderTest, PostEvent006, TestSize.Level0) { + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_NORMAL, + }; + DistributedData::Assets assets; + assets.push_back(asset); + BindAssets bindAssets = std::make_shared>>(); + bindAssets->insert({"PostEvent006", std::make_shared()}); + std::shared_ptr assetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); + std::set skipAssets; + std::set deleteAssets; + rdbAssetLoader.PostEvent(DistributedData::AssetEvent::DOWNLOAD, assets, skipAssets, deleteAssets); + EXPECT_EQ(deleteAssets.size(), 0); + EXPECT_EQ(skipAssets.size(), 0); +} + +/** +@tc.name: PostEvent007 +@tc.desc: RdbAssetLoader PostEvent007 test, Both deleteAssets and skipAssets can be found. +@tc.type: FUNC +@tc.require: +@tc.author: SQL +*/ +HWTEST_F(RdbAssetLoaderTest, PostEvent007, TestSize.Level0) { + class ObjectSnapshotMock : public DistributedObject::ObjectSnapshot { + public: + int32_t Downloaded(Asset &asset) override { + hasDownloaded = true; + return 0; + } + bool hasDownloaded = false; + }; + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "PostEvent007", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_NORMAL, + }; + DistributedData::Assets assets; + assets.push_back(asset); + BindAssets bindAssets = std::make_shared>>(); + auto objectSnapshotMock = std::make_shared(); + bindAssets->insert({"PostEvent007", objectSnapshotMock}); + std::shared_ptr assetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); + std::set skipAssets; + skipAssets.insert("PostEvent007"); + std::set deleteAssets; + deleteAssets.insert("PostEvent007"); + rdbAssetLoader.PostEvent(DistributedData::AssetEvent::UPLOAD, assets, skipAssets, deleteAssets); + EXPECT_EQ(objectSnapshotMock->hasDownloaded, false); +} + +/** +@tc.name: PostEvent008 +@tc.desc: RdbAssetLoader PostEvent008 test, Neither deleteAssets nor skipAssets can be found. +@tc.type: FUNC +@tc.require: +@tc.author: SQL +*/ +HWTEST_F(RdbAssetLoaderTest, PostEvent008, TestSize.Level0) { + class ObjectSnapshotMock : public DistributedObject::ObjectSnapshot { + public: + int32_t Downloaded(Asset &asset) override { + hasDownloaded = true; + return 0; + } + bool hasDownloaded = false; + }; + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "PostEvent008", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_NORMAL, + }; + DistributedData::Assets assets; + assets.push_back(asset); + BindAssets bindAssets = std::make_shared>>(); + auto objectSnapshotMock = std::make_shared(); + bindAssets->insert({"PostEvent008", objectSnapshotMock}); + std::shared_ptr assetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); + std::set skipAssets; + std::set deleteAssets; + rdbAssetLoader.PostEvent(DistributedData::AssetEvent::UPLOAD, assets, skipAssets, deleteAssets); + EXPECT_EQ(objectSnapshotMock->hasDownloaded, true); +} +/** + +@tc.name: PostEvent009 +@tc.desc: RdbAssetLoader PostEvent009 test, deleteAssets can be found, skipAssets cannot be found. +@tc.type: FUNC +@tc.require: +@tc.author: SQL +*/ +HWTEST_F(RdbAssetLoaderTest, PostEvent009, TestSize.Level0) { + class ObjectSnapshotMock : public DistributedObject::ObjectSnapshot { + public: + int32_t Downloaded(Asset &asset) override { + hasDownloaded = true; + return 0; + } + bool hasDownloaded = false; + }; + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "PostEvent009", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_NORMAL, + }; + DistributedData::Assets assets; + assets.push_back(asset); + BindAssets bindAssets = std::make_shared>>(); + auto objectSnapshotMock = std::make_shared(); + bindAssets->insert({"PostEvent009", objectSnapshotMock}); + std::shared_ptr assetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); + std::set skipAssets; + std::set deleteAssets; + deleteAssets.insert("PostEvent009"); + rdbAssetLoader.PostEvent(DistributedData::AssetEvent::UPLOAD, assets, skipAssets, deleteAssets); + EXPECT_EQ(objectSnapshotMock->hasDownloaded, false); +} + +/** +@tc.name: PostEvent0010 +@tc.desc: RdbAssetLoader PostEvent0010 test, skipAssets can be found, deleteAssets cannot be found. +@tc.type: FUNC +@tc.require: +@tc.author: SQL +*/ +HWTEST_F(RdbAssetLoaderTest, PostEvent0010, TestSize.Level0) { + class ObjectSnapshotMock : public DistributedObject::ObjectSnapshot { + public: + int32_t Downloaded(Asset &asset) override { + hasDownloaded = true; + return 0; + } + bool hasDownloaded = false; + }; + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "PostEvent0010", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_NORMAL, + }; + DistributedData::Assets assets; + assets.push_back(asset); + BindAssets bindAssets = std::make_shared>>(); + auto objectSnapshotMock = std::make_shared(); + bindAssets->insert({"PostEvent0010", objectSnapshotMock}); + std::shared_ptr assetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); + std::set skipAssets; + skipAssets.insert("PostEvent0010"); + std::set deleteAssets; + rdbAssetLoader.PostEvent(DistributedData::AssetEvent::UPLOAD, assets, skipAssets, deleteAssets); + EXPECT_EQ(objectSnapshotMock->hasDownloaded, false); +} + /** * @tc.name: ConvertStatus * @tc.desc: RdbAssetLoader ConvertStatus abnormal 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 cca78a80050012bef9341523e861764a4b5379e2..2683faa96b00f3080e8b244716e3aa905b5c735a 100644 --- a/datamgr_service/services/distributeddataservice/service/test/rdb_cloud_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_cloud_test.cpp @@ -16,27 +16,77 @@ #include "rdb_cloud.h" +#include "cloud_db_mock.h" +#include "cursor_mock.h" +#include "gmock/gmock.h" #include "gtest/gtest.h" #include "log_print.h" using namespace testing::ext; +using namespace testing; using namespace OHOS::DistributedData; using namespace OHOS::DistributedRdb; using DBVBucket = DistributedDB::VBucket; using DBStatus = DistributedDB::DBStatus; -std::vector g_DBVBucket = { { { "#gid", { "0000000" } }, { "#flag", { true } }, +using DBAsset = DistributedDB::Asset; +using DBAssets = DistributedDB::Assets; +using AssetOpType = DistributedDB::AssetOpType; +using AssetStatus = DistributedDB::AssetStatus; +DBAsset assetValue1 = { .version = 1, + .name = "texture_diffuse", + .assetId = "123", + .subpath = "textures/environment", + .uri = "http://asset.com/textures/123.jpg", + .modifyTime = "2025-04-05T12:30:00Z", + .createTime = "2025-04-05T10:15:00Z", + .size = "1024", + .hash = "sha256-abc123", + .flag = static_cast(AssetOpType::INSERT), + .status = static_cast(AssetStatus::NORMAL), + .timestamp = std::time(nullptr) }; + +DBAsset assetValue2 = { .version = 2, + .name = "texture_diffuse", + .assetId = "456", + .subpath = "textures/environment", + .uri = "http://asset.com/textures/456.jpg", + .modifyTime = "2025-06-19T12:30:00Z", + .createTime = "2025-04-05T10:15:00Z", + .size = "1024", + .hash = "sha256-abc456", + .flag = static_cast(AssetOpType::UPDATE), + .status = static_cast(AssetStatus::NORMAL), + .timestamp = std::time(nullptr) }; + +DBAssets assetsValue = { assetValue1, assetValue2 }; +std::vector g_DBVBuckets = { { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, { "#float", { double(100) } }, { "#_type", { int64_t(1) } }, - { "#_query", { Bytes({ 1, 2, 3, 4 }) } } } }; + { "#_error", { "E_ERROR" } }, { "#_error", { "INVALID" } }, { "#_query", { Bytes({ 1, 2, 3, 4 }) } }, + { "#asset", assetValue1 }, { "#assets", assetsValue } } }; +DBVBucket g_DBVBucket = { { "#value", { int64_t(100) } } }; + namespace OHOS::Test { namespace DistributedRDBTest { class RdbCloudTest : public testing::Test { public: - static void SetUpTestCase(void){}; - static void TearDownTestCase(void){}; + static void SetUpTestCase(); + static void TearDownTestCase(); void SetUp(){}; void TearDown(){}; + static inline std::shared_ptr mockCloudDB = nullptr; + static constexpr int32_t COUNT = 2; }; +void RdbCloudTest::SetUpTestCase() +{ + mockCloudDB = std::make_shared(); +} + +void RdbCloudTest::TearDownTestCase() +{ + mockCloudDB = nullptr; +} + /** * @tc.name: RdbCloudTest001 * @tc.desc: RdbCloud BatchInsert BatchUpdate BatchDelete test. @@ -48,14 +98,21 @@ HWTEST_F(RdbCloudTest, RdbCloudTest001, TestSize.Level1) { BindAssets bindAssets; Bytes bytes; - std::shared_ptr cloudDB = std::make_shared(); - RdbCloud rdbCloud(cloudDB, &bindAssets); + RdbCloud rdbCloud(std::make_shared(), bindAssets); std::string tableName = "testTable"; - auto result = rdbCloud.BatchInsert(tableName, std::move(g_DBVBucket), g_DBVBucket); + + std::vector dataInsert = g_DBVBuckets; + std::vector extendInsert = g_DBVBuckets; + auto result = rdbCloud.BatchInsert(tableName, std::move(dataInsert), extendInsert); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - result = rdbCloud.BatchUpdate(tableName, std::move(g_DBVBucket), g_DBVBucket); + + std::vector dataUpdate = g_DBVBuckets; + std::vector extendUpdate = g_DBVBuckets; + result = rdbCloud.BatchUpdate(tableName, std::move(dataUpdate), extendUpdate); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - result = rdbCloud.BatchDelete(tableName, g_DBVBucket); + + std::vector extendDelete = g_DBVBuckets; + result = rdbCloud.BatchDelete(tableName, extendDelete); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); } @@ -69,24 +126,21 @@ HWTEST_F(RdbCloudTest, RdbCloudTest001, TestSize.Level1) HWTEST_F(RdbCloudTest, RdbCloudTest002, TestSize.Level1) { BindAssets bindAssets; - std::shared_ptr cloudDB = std::make_shared(); - RdbCloud rdbCloud(cloudDB, &bindAssets); + RdbCloud rdbCloud(std::make_shared(), bindAssets); std::string tableName = "testTable"; rdbCloud.Lock(); std::string traceId = "id"; rdbCloud.SetPrepareTraceId(traceId); - auto result = rdbCloud.BatchInsert(tableName, std::move(g_DBVBucket), g_DBVBucket); + std::vector dataInsert = g_DBVBuckets; + std::vector extendInsert = g_DBVBuckets; + auto result = rdbCloud.BatchInsert(tableName, std::move(dataInsert), extendInsert); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - DBVBucket extends = { - {"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}, - {"#_type", {int64_t(1)}}, {"#_query", {Bytes({ 1, 2, 3, 4 })}} - }; - result = rdbCloud.Query(tableName, extends, g_DBVBucket); + DBVBucket extends = { { "#gid", { "00000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } }, { "#_type", { int64_t(1) } }, { "#_query", { Bytes({ 1, 2, 3, 4 }) } } }; + result = rdbCloud.Query(tableName, extends, g_DBVBuckets); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - std::vector vBuckets = { - {{"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}, - {"#_type", {int64_t(1)}}, {"#_query", {Bytes({ 1, 2, 3, 4 })}}} - }; + std::vector vBuckets = { { { "#gid", { "00000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } }, { "#_type", { int64_t(1) } }, { "#_query", { Bytes({ 1, 2, 3, 4 }) } } } }; rdbCloud.PreSharing(tableName, vBuckets); result = rdbCloud.HeartBeat(); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); @@ -105,32 +159,23 @@ HWTEST_F(RdbCloudTest, RdbCloudTest002, TestSize.Level1) */ HWTEST_F(RdbCloudTest, RdbCloudTest003, TestSize.Level1) { - BindAssets bindAssets; - bindAssets.bindAssets = nullptr; - std::shared_ptr cloudDB = std::make_shared(); - RdbCloud rdbCloud(cloudDB, &bindAssets); + BindAssets bindAssets = nullptr; + RdbCloud rdbCloud(std::make_shared(), bindAssets); std::string tableName = "testTable"; - DBVBucket extends = { - {"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}, - {"#_type", {int64_t(1)}} - }; - std::vector data = { - {{"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}} - }; + DBVBucket extends = { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } }, { "#_type", { int64_t(1) } } }; + std::vector data = { { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } } } }; auto result = rdbCloud.Query(tableName, extends, data); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - extends = { - {"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}, - {"#_query", {Bytes({ 1, 2, 3, 4 })}} - }; + extends = { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } }, { "#_query", { Bytes({ 1, 2, 3, 4 }) } } }; result = rdbCloud.Query(tableName, extends, data); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - extends = { - {"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}, - {"#_type", {int64_t(0)}} - }; + extends = { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } }, { "#_type", { int64_t(0) } } }; result = rdbCloud.Query(tableName, extends, data); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); } @@ -145,8 +190,7 @@ HWTEST_F(RdbCloudTest, RdbCloudTest003, TestSize.Level1) HWTEST_F(RdbCloudTest, RdbCloudTest004, TestSize.Level1) { BindAssets bindAssets; - std::shared_ptr cloudDB = std::make_shared(); - RdbCloud rdbCloud(cloudDB, &bindAssets); + RdbCloud rdbCloud(std::make_shared(), bindAssets); auto err = rdbCloud.UnLockCloudDB(OHOS::DistributedRdb::RdbCloud::FLAG::SYSTEM_ABILITY); EXPECT_EQ(err, GeneralError::E_NOT_SUPPORT); @@ -169,8 +213,7 @@ HWTEST_F(RdbCloudTest, RdbCloudTest004, TestSize.Level1) HWTEST_F(RdbCloudTest, ConvertStatus, TestSize.Level1) { BindAssets bindAssets; - std::shared_ptr cloudDB = std::make_shared(); - RdbCloud rdbCloud(cloudDB, &bindAssets); + RdbCloud rdbCloud(std::make_shared(), bindAssets); auto result = rdbCloud.ConvertStatus(GeneralError::E_OK); EXPECT_EQ(result, DBStatus::OK); result = rdbCloud.ConvertStatus(GeneralError::E_NETWORK_ERROR); @@ -195,8 +238,6 @@ HWTEST_F(RdbCloudTest, ConvertStatus, TestSize.Level1) EXPECT_EQ(result, DBStatus::TIME_OUT); result = rdbCloud.ConvertStatus(GeneralError::E_CLOUD_DISABLED); EXPECT_EQ(result, DBStatus::CLOUD_DISABLED); - result = rdbCloud.ConvertStatus(GeneralError::E_SKIP_ASSET); - EXPECT_EQ(result, DBStatus::SKIP_ASSET); } /** @@ -209,27 +250,174 @@ HWTEST_F(RdbCloudTest, ConvertStatus, TestSize.Level1) HWTEST_F(RdbCloudTest, ConvertQuery, TestSize.Level1) { RdbCloud::DBQueryNodes nodes; - DistributedDB::QueryNode node = { DistributedDB::QueryNodeType::IN, "", {int64_t(1)} }; + DistributedDB::QueryNode node = { DistributedDB::QueryNodeType::IN, "", { int64_t(1) } }; nodes.push_back(node); - node = { DistributedDB::QueryNodeType::OR, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::OR, "", { int64_t(1) } }; nodes.push_back(node); - node = { DistributedDB::QueryNodeType::AND, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::AND, "", { int64_t(1) } }; nodes.push_back(node); - node = { DistributedDB::QueryNodeType::EQUAL_TO, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::EQUAL_TO, "", { int64_t(1) } }; nodes.push_back(node); - node = { DistributedDB::QueryNodeType::BEGIN_GROUP, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::BEGIN_GROUP, "", { int64_t(1) } }; nodes.push_back(node); - node = { DistributedDB::QueryNodeType::END_GROUP, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::END_GROUP, "", { int64_t(1) } }; nodes.push_back(node); - + auto result = RdbCloud::ConvertQuery(std::move(nodes)); EXPECT_EQ(result.size(), 6); nodes.clear(); - node = { DistributedDB::QueryNodeType::ILLEGAL, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::ILLEGAL, "", { int64_t(1) } }; nodes.push_back(node); result = RdbCloud::ConvertQuery(std::move(nodes)); EXPECT_EQ(result.size(), 0); } + +/** +* @tc.name: SetPrepareTraceId001 +* @tc.desc: RdbCloud PostEvent test cloudDB_ is nullptr. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, SetPrepareTraceId001, TestSize.Level1) +{ + std::string traceId = "testId"; + EXPECT_CALL(*mockCloudDB, SetPrepareTraceId(_)).Times(0); + BindAssets bindAssets; + std::shared_ptr mockCloudDB = nullptr; + RdbCloud rdbCloud(mockCloudDB, bindAssets); + rdbCloud.SetPrepareTraceId(traceId); +} + +/** +* @tc.name: PostEvent001 +* @tc.desc: RdbCloud PostEvent test bindAssets is nullptr. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, PostEvent001, TestSize.Level1) +{ + BindAssets bindAssets; + RdbCloud rdbCloud(std::make_shared(), nullptr); + std::string traceId = "testId"; + rdbCloud.SetPrepareTraceId(traceId); + std::string tableName = "testTable"; + std::vector dataInsert = g_DBVBuckets; + std::vector extendInsert = g_DBVBuckets; + auto result = rdbCloud.BatchInsert(tableName, std::move(dataInsert), extendInsert); + EXPECT_EQ(result, DBStatus::CLOUD_ERROR); +} + +/** +* @tc.name: PostEvent002 +* @tc.desc: RdbCloud PostEvent test snapshots contains asset.uri. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, PostEvent002, TestSize.Level1) +{ + BindAssets snapshots = std::make_shared>>(); + std::shared_ptr snapshot; + snapshots->insert_or_assign(assetValue1.uri, snapshot); + RdbCloud rdbCloud(std::make_shared(), snapshots); + std::string tableName = "testTable"; + std::vector dataInsert = g_DBVBuckets; + std::vector extendInsert = g_DBVBuckets; + auto result = rdbCloud.BatchInsert(tableName, std::move(dataInsert), extendInsert); + EXPECT_EQ(result, DBStatus::CLOUD_ERROR); +} + +/** +* @tc.name: PostEvent003 +* @tc.desc: RdbCloud PostEvent test snapshots does not contains asset.uri. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, PostEvent003, TestSize.Level1) +{ + BindAssets snapshots = std::make_shared>>(); + std::shared_ptr snapshot; + std::string uri = "testuri"; + snapshots->insert_or_assign(uri, snapshot); + RdbCloud rdbCloud(std::make_shared(), snapshots); + std::string tableName = "testTable"; + std::vector dataInsert = g_DBVBuckets; + std::vector extendInsert = g_DBVBuckets; + auto result = rdbCloud.BatchInsert(tableName, std::move(dataInsert), extendInsert); + EXPECT_EQ(result, DBStatus::CLOUD_ERROR); +} + +/** +* @tc.name: PostEvent004 +* @tc.desc: RdbCloud PostEvent test the snapshot contained in the snapshots is nullpt. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, PostEvent004, TestSize.Level1) +{ + BindAssets snapshots = std::make_shared>>(); + std::shared_ptr snapshot = nullptr; + std::string uri = "testuri"; + snapshots->insert_or_assign(uri, snapshot); + RdbCloud rdbCloud(std::make_shared(), snapshots); + std::string tableName = "testTable"; + std::vector dataInsert = g_DBVBuckets; + std::vector extendInsert = g_DBVBuckets; + auto result = rdbCloud.BatchInsert(tableName, std::move(dataInsert), extendInsert); + EXPECT_EQ(result, DBStatus::CLOUD_ERROR); +} + +/** +* @tc.name: Query001 +* @tc.desc: RdbCloud Query test the cursor is nullptr and code is not E_OK. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, Query001, TestSize.Level1) +{ + std::shared_ptr cursor = nullptr; + std::string tableName = "testTable"; + EXPECT_CALL(*mockCloudDB, Query(tableName, _)).WillOnce(Return(std::make_pair(E_NETWORK_ERROR, cursor))); + BindAssets snapshots; + RdbCloud rdbCloud(mockCloudDB, snapshots); + auto result = rdbCloud.Query(tableName, g_DBVBucket, g_DBVBuckets); + EXPECT_EQ(result, DBStatus::CLOUD_NETWORK_ERROR); +} + +/** +* @tc.name: Query002 +* @tc.desc: RdbCloud Query test code is QUERY_END. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, Query002, TestSize.Level1) +{ + std::shared_ptr mockCursor = std::make_shared(); + std::string tableName = "testTable"; + EXPECT_CALL(*mockCloudDB, Query(tableName, _)).WillOnce(Return(std::make_pair(E_OK, mockCursor))); + EXPECT_CALL(*mockCursor, GetCount()).WillOnce(Return(COUNT)); + EXPECT_CALL(*mockCursor, GetEntry(_)).WillOnce(Return(E_OK)).WillOnce(Return(E_ERROR)); + EXPECT_CALL(*mockCursor, MoveToNext()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*mockCursor, IsEnd()).WillOnce(Return(true)); + + BindAssets snapshots; + RdbCloud rdbCloud(mockCloudDB, snapshots); + auto result = rdbCloud.Query(tableName, g_DBVBucket, g_DBVBuckets); + EXPECT_EQ(result, DBStatus::QUERY_END); +} + +/** +* @tc.name: Query003 +* @tc.desc: RdbCloud Query test code is CLOUD_ERROR. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, Query003, TestSize.Level1) +{ + std::shared_ptr mockCursor = std::make_shared(); + std::string tableName = "testTable"; + EXPECT_CALL(*mockCloudDB, Query(tableName, _)).WillOnce(Return(std::make_pair(E_OK, mockCursor))); + EXPECT_CALL(*mockCursor, GetCount()).WillOnce(Return(COUNT)); + EXPECT_CALL(*mockCursor, GetEntry(_)).WillOnce(Return(E_OK)).WillOnce(Return(E_ERROR)); + EXPECT_CALL(*mockCursor, MoveToNext()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*mockCursor, IsEnd()).WillOnce(Return(false)); + + BindAssets snapshots; + RdbCloud rdbCloud(mockCloudDB, snapshots); + auto result = rdbCloud.Query(tableName, g_DBVBucket, g_DBVBuckets); + EXPECT_EQ(result, DBStatus::CLOUD_ERROR); +} } // namespace DistributedRDBTest } // namespace OHOS::Test \ No newline at end of file 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 70e914ddbf8bf379bd5da674b2abd5fdf6372420..1e2effe7064c8989f2b01de7cc1a4bc38c248130 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 @@ -21,6 +21,9 @@ #include "bootstrap.h" #include "cloud/schema_meta.h" +#include "error/general_error.h" +#include "errors.h" +#include "eventcenter/event_center.h" #include "gtest/gtest.h" #include "log_print.h" #include "metadata/meta_data_manager.h" @@ -29,7 +32,11 @@ #include "metadata/store_meta_data_local.h" #include "mock/general_watcher_mock.h" #include "rdb_query.h" +#include "relational_store_delegate_mock.h" #include "store/general_store.h" +#include "store/general_value.h" +#include "store_observer.h" +#include "store_types.h" #include "types.h" using namespace testing::ext; @@ -37,14 +44,15 @@ using namespace DistributedDB; using namespace OHOS::DistributedData; using namespace OHOS::DistributedRdb; using DBStatus = DistributedDB::DBStatus; -using StoreMetaData = OHOS::DistributedData::StoreMetaData; RdbGeneralStore::Values g_RdbValues = { { "0000000" }, { true }, { int64_t(100) }, { double(100) }, { int64_t(1) }, { Bytes({ 1, 2, 3, 4 }) } }; RdbGeneralStore::VBucket g_RdbVBucket = { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, { "#float", { double(100) } } }; -bool g_testResult = false; +bool MockRelationalStoreDelegate::gTestResult = false; namespace OHOS::Test { namespace DistributedRDBTest { +using StoreMetaData = OHOS::DistributedData::StoreMetaData; +using namespace OHOS::DistributedRdb; static constexpr uint32_t PRINT_ERROR_CNT = 150; static constexpr const char *BUNDLE_NAME = "test_rdb_general_store"; static constexpr const char *STORE_NAME = "test_service_rdb"; @@ -56,15 +64,18 @@ public: { Bootstrap::GetInstance().LoadDirectory(); InitMetaData(); + store = std::make_shared(metaData_); + ASSERT_NE(store, nullptr); }; void TearDown() { - g_testResult = false; + MockRelationalStoreDelegate::gTestResult = false; }; protected: void InitMetaData(); StoreMetaData metaData_; + std::shared_ptr store; }; void RdbGeneralStoreTest::InitMetaData() @@ -79,158 +90,9 @@ void RdbGeneralStoreTest::InitMetaData() metaData_.storeId = STORE_NAME; metaData_.dataDir = "/data/service/el1/public/database/" + std::string(BUNDLE_NAME) + "/rdb"; metaData_.securityLevel = DistributedKv::SecurityLevel::S2; + metaData_.isSearchable = true; } -class MockRelationalStoreDelegate : public DistributedDB::RelationalStoreDelegate { -public: - ~MockRelationalStoreDelegate() = default; - - DBStatus Sync(const std::vector &devices, DistributedDB::SyncMode mode, const Query &query, - const SyncStatusCallback &onComplete, bool wait) override - { - return DBStatus::OK; - } - - int32_t GetCloudSyncTaskCount() override - { - static int32_t count = 0; - count = (count + 1) % 2; // The result of count + 1 is the remainder of 2. - return count; - } - - DBStatus RemoveDeviceData(const std::string &device, const std::string &tableName) override - { - return DBStatus::OK; - } - - DBStatus RemoteQuery(const std::string &device, const RemoteCondition &condition, uint64_t timeout, - std::shared_ptr &result) override - { - if (device == "test") { - return DBStatus::DB_ERROR; - } - return DBStatus::OK; - } - - DBStatus RemoveDeviceData() override - { - return DBStatus::OK; - } - - DBStatus Sync(const std::vector &devices, DistributedDB::SyncMode mode, const Query &query, - const SyncProcessCallback &onProcess, int64_t waitTime) override - { - return DBStatus::OK; - } - - DBStatus SetCloudDB(const std::shared_ptr &cloudDb) override - { - return DBStatus::OK; - } - - DBStatus SetCloudDbSchema(const DataBaseSchema &schema) override - { - return DBStatus::OK; - } - - DBStatus RegisterObserver(StoreObserver *observer) override - { - return DBStatus::OK; - } - - DBStatus UnRegisterObserver() override - { - return DBStatus::OK; - } - - DBStatus UnRegisterObserver(StoreObserver *observer) override - { - return DBStatus::OK; - } - - DBStatus SetIAssetLoader(const std::shared_ptr &loader) override - { - return DBStatus::OK; - } - - DBStatus Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) override - { - return DBStatus::OK; - } - - DBStatus SetTrackerTable(const TrackerSchema &schema) override - { - if (schema.tableName == "WITH_INVENTORY_DATA") { - return DBStatus::WITH_INVENTORY_DATA; - } - if (schema.tableName == "test") { - return DBStatus::DB_ERROR; - } - return DBStatus::OK; - } - - DBStatus ExecuteSql(const SqlCondition &condition, std::vector &records) override - { - if (condition.sql == "") { - return DBStatus::DB_ERROR; - } - - std::string sqls = "INSERT INTO test ( #flag, #float, #gid, #value) VALUES ( ?, ?, ?, ?)"; - std::string sqlIn = " UPDATE test SET setSql WHERE whereSql"; - std::string sql = "REPLACE INTO test ( #flag, #float, #gid, #value) VALUES ( ?, ?, ?, ?)"; - if (condition.sql == sqls || condition.sql == sqlIn || condition.sql == sql) { - return DBStatus::DB_ERROR; - } - return DBStatus::OK; - } - - DBStatus SetReference(const std::vector &tableReferenceProperty) override - { - if (g_testResult) { - return DBStatus::DB_ERROR; - } - return DBStatus::OK; - } - - DBStatus CleanTrackerData(const std::string &tableName, int64_t cursor) override - { - return DBStatus::OK; - } - - DBStatus Pragma(PragmaCmd cmd, PragmaData &pragmaData) override - { - return DBStatus::OK; - } - - DBStatus UpsertData(const std::string &tableName, const std::vector &records, - RecordStatus status = RecordStatus::WAIT_COMPENSATED_SYNC) override - { - return DBStatus::OK; - } - - DBStatus SetCloudSyncConfig(const CloudSyncConfig &config) override - { - return DBStatus::OK; - } - -protected: - DBStatus RemoveDeviceDataInner(const std::string &device, ClearMode mode) override - { - if (g_testResult) { - return DBStatus::DB_ERROR; - } - return DBStatus::OK; - } - - DBStatus CreateDistributedTableInner(const std::string &tableName, TableSyncType type) override - { - if (tableName == "test") { - return DBStatus::DB_ERROR; - } - return DBStatus::OK; - } -}; - class MockStoreChangedData : public DistributedDB::StoreChangedData { public: std::string GetDataChangeDevice() const override @@ -248,15 +110,11 @@ public: * @tc.name: BindSnapshots001 * @tc.desc: RdbGeneralStore BindSnapshots test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, BindSnapshots001, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); BindAssets bindAssets; - auto result = store->BindSnapshots(bindAssets.bindAssets); + auto result = store->BindSnapshots(bindAssets); EXPECT_EQ(result, GeneralError::E_OK); } @@ -264,19 +122,35 @@ HWTEST_F(RdbGeneralStoreTest, BindSnapshots001, TestSize.Level1) * @tc.name: BindSnapshots002 * @tc.desc: RdbGeneralStore BindSnapshots nullptr test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, BindSnapshots002, TestSize.Level1) { DistributedData::StoreMetaData meta; meta = metaData_; meta.isEncrypt = true; - auto store = new (std::nothrow) RdbGeneralStore(meta); + auto store = std::make_shared(meta); ASSERT_NE(store, nullptr); - store->snapshots_.bindAssets = nullptr; + store->snapshots_ = nullptr; BindAssets bindAssets; - auto result = store->BindSnapshots(bindAssets.bindAssets); + auto result = store->BindSnapshots(bindAssets); + EXPECT_EQ(result, GeneralError::E_OK); +} + +/** +@tc.name: BindSnapshots003 +@tc.desc: RdbGeneralStore BindSnapshots not nullptr test +@tc.type: FUNC +*/ +HWTEST_F(RdbGeneralStoreTest, BindSnapshots003, TestSize.Level1) +{ + DistributedData::StoreMetaData meta; + meta = metaData_; + meta.isEncrypt = true; + auto store = std::make_shared(meta); + ASSERT_NE(store, nullptr); + BindAssets bindAssets = std::make_shared>>(); + store->snapshots_ = bindAssets; + auto result = store->BindSnapshots(bindAssets); EXPECT_EQ(result, GeneralError::E_OK); } @@ -284,13 +158,9 @@ HWTEST_F(RdbGeneralStoreTest, BindSnapshots002, TestSize.Level1) * @tc.name: Bind001 * @tc.desc: RdbGeneralStore Bind bindInfo test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Bind001, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedData::Database database; GeneralStore::CloudConfig config; std::map bindInfos; @@ -330,16 +200,11 @@ HWTEST_F(RdbGeneralStoreTest, Bind001, TestSize.Level1) * @tc.name: Bind002 * @tc.desc: RdbGeneralStore Bind delegate_ is nullptr test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Bind002, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedData::Database database; std::map bindInfos; - std::shared_ptr db = std::make_shared(); std::shared_ptr loader = std::make_shared(); GeneralStore::BindInfo bindInfo(db, loader); @@ -359,13 +224,9 @@ HWTEST_F(RdbGeneralStoreTest, Bind002, TestSize.Level1) * @tc.name: Bind003 * @tc.desc: RdbGeneralStore Bind delegate_ test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Bind003, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedData::Database database; std::map bindInfos; @@ -374,8 +235,8 @@ HWTEST_F(RdbGeneralStoreTest, Bind003, TestSize.Level1) GeneralStore::BindInfo bindInfo(db, loader); uint32_t key = 1; bindInfos[key] = bindInfo; - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); GeneralStore::CloudConfig config; auto result = store->Bind(database, bindInfos, config); EXPECT_NE(store->delegate_, nullptr); @@ -384,32 +245,84 @@ HWTEST_F(RdbGeneralStoreTest, Bind003, TestSize.Level1) /** * @tc.name: Close -* @tc.desc: RdbGeneralStore Close and IsBound function test +* @tc.desc: RdbGeneralStore Close and isforce is false and GetDeviceSyncTaskCount is 2 * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Close, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); - auto result = store->IsBound(std::stoi(metaData_.user)); + auto result = store->IsBound(std::atoi(metaData_.user.c_str())); EXPECT_EQ(result, false); EXPECT_EQ(store->delegate_, nullptr); auto ret = store->Close(); EXPECT_EQ(ret, GeneralError::E_OK); - - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); + MockRelationalStoreDelegate::SetCloudSyncTaskCount(0); + MockRelationalStoreDelegate::SetDownloadingAssetsCount(0); + MockRelationalStoreDelegate::SetDeviceTaskCount(2); ret = store->Close(); EXPECT_EQ(ret, GeneralError::E_BUSY); } +/** + * @tc.name: Close1 + * @tc.desc: RdbGeneralStore Close and isforce is false and GetCloudSyncTaskCount is 1 + * @tc.type: FUNC + */ +HWTEST_F(RdbGeneralStoreTest, Close1, TestSize.Level1) +{ + metaData_.storeId = "mock"; + auto store = std::make_shared(metaData_); + MockRelationalStoreDelegate::SetCloudSyncTaskCount(1); + auto ret = store->Close(); + EXPECT_EQ(ret, GeneralError::E_BUSY); +} +/** + * @tc.name: Close2 + * @tc.desc: RdbGeneralStore Close and isforce is false and DownloadingAssetsCount is 1 + * @tc.type: FUNC + */ +HWTEST_F(RdbGeneralStoreTest, Close2, TestSize.Level1) +{ + metaData_.storeId = "mock"; + auto store = std::make_shared(metaData_); + MockRelationalStoreDelegate::SetCloudSyncTaskCount(0); + MockRelationalStoreDelegate::SetDownloadingAssetsCount(1); + auto ret = store->Close(); + EXPECT_EQ(ret, GeneralError::E_BUSY); +} +/** + * @tc.name: Close3 + * @tc.desc: RdbGeneralStore Close and isforce is true + * @tc.type: FUNC + */ +HWTEST_F(RdbGeneralStoreTest, Close3, TestSize.Level1) +{ + metaData_.storeId = "mock"; + auto store = std::make_shared(metaData_); + auto ret = store->Close(true); + EXPECT_EQ(ret, GeneralError::E_OK); +} +/** + * @tc.name: Close4 + * @tc.desc: RdbGeneralStore Close and there is no task + * @tc.type: FUNC + */ +HWTEST_F(RdbGeneralStoreTest, Close4, TestSize.Level1) +{ + metaData_.storeId = "mock"; + auto store = std::make_shared(metaData_); + MockRelationalStoreDelegate::SetCloudSyncTaskCount(0); + MockRelationalStoreDelegate::SetDownloadingAssetsCount(0); + MockRelationalStoreDelegate::SetDeviceTaskCount(0); + auto ret = store->Close(); + EXPECT_EQ(ret, GeneralError::E_OK); +} + /** * @tc.name: Close * @tc.desc: RdbGeneralStore Close test * @tc.type: FUNC -* @tc.require: * @tc.author: shaoyuanzhao */ HWTEST_F(RdbGeneralStoreTest, BusyClose, TestSize.Level1) @@ -432,21 +345,16 @@ HWTEST_F(RdbGeneralStoreTest, BusyClose, TestSize.Level1) * @tc.name: Execute * @tc.desc: RdbGeneralStore Execute function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Execute, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "table"; std::string sql = "sql"; EXPECT_EQ(store->delegate_, nullptr); auto result = store->Execute(table, sql); EXPECT_EQ(result, GeneralError::E_ERROR); - - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); result = store->Execute(table, sql); EXPECT_EQ(result, GeneralError::E_OK); @@ -459,13 +367,9 @@ HWTEST_F(RdbGeneralStoreTest, Execute, TestSize.Level1) * @tc.name: SqlConcatenate * @tc.desc: RdbGeneralStore SqlConcatenate function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, SqlConcatenate, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedData::VBucket value; std::string strColumnSql = "strColumnSql"; std::string strRowValueSql = "strRowValueSql"; @@ -485,13 +389,9 @@ HWTEST_F(RdbGeneralStoreTest, SqlConcatenate, TestSize.Level1) * @tc.name: Insert001 * @tc.desc: RdbGeneralStore Insert error test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Insert001, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedData::VBuckets values; EXPECT_EQ(values.size(), 0); std::string table = "table"; @@ -519,23 +419,14 @@ HWTEST_F(RdbGeneralStoreTest, Insert001, TestSize.Level1) * @tc.name: Insert002 * @tc.desc: RdbGeneralStore Insert function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Insert002, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "table"; DistributedData::VBuckets extends = { { g_RdbVBucket } }; auto result = store->Insert(table, std::move(extends)); EXPECT_EQ(result, GeneralError::E_ERROR); - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; - result = store->Insert(table, std::move(extends)); - EXPECT_EQ(result, GeneralError::E_OK); - std::string test = "test"; result = store->Insert(test, std::move(extends)); EXPECT_EQ(result, GeneralError::E_ERROR); @@ -547,19 +438,19 @@ HWTEST_F(RdbGeneralStoreTest, Insert002, TestSize.Level1) result = store->Insert(test, std::move(extends)); EXPECT_EQ(result, GeneralError::E_ERROR); } + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); + result = store->Insert(table, std::move(extends)); + EXPECT_EQ(result, GeneralError::E_OK); } /** * @tc.name: Update * @tc.desc: RdbGeneralStore Update function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Update, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "table"; std::string setSql = "setSql"; RdbGeneralStore::Values values; @@ -582,9 +473,8 @@ HWTEST_F(RdbGeneralStoreTest, Update, TestSize.Level1) result = store->Update(table, setSql, std::move(g_RdbValues), whereSql, std::move(g_RdbValues)); EXPECT_EQ(result, GeneralError::E_ERROR); - - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); result = store->Update(table, setSql, std::move(g_RdbValues), whereSql, std::move(g_RdbValues)); EXPECT_EQ(result, GeneralError::E_OK); @@ -596,13 +486,9 @@ HWTEST_F(RdbGeneralStoreTest, Update, TestSize.Level1) * @tc.name: Replace * @tc.desc: RdbGeneralStore Replace function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Replace, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "table"; RdbGeneralStore::VBucket values; auto result = store->Replace("", std::move(g_RdbVBucket)); @@ -613,9 +499,8 @@ HWTEST_F(RdbGeneralStoreTest, Replace, TestSize.Level1) result = store->Replace(table, std::move(g_RdbVBucket)); EXPECT_EQ(result, GeneralError::E_ERROR); - - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); result = store->Replace(table, std::move(g_RdbVBucket)); EXPECT_EQ(result, GeneralError::E_OK); @@ -627,13 +512,9 @@ HWTEST_F(RdbGeneralStoreTest, Replace, TestSize.Level1) * @tc.name: Delete * @tc.desc: RdbGeneralStore Delete function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Delete, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "table"; std::string sql = "sql"; auto result = store->Delete(table, sql, std::move(g_RdbValues)); @@ -644,21 +525,16 @@ HWTEST_F(RdbGeneralStoreTest, Delete, TestSize.Level1) * @tc.name: Query001 * @tc.desc: RdbGeneralStore Query function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Query001, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "table"; std::string sql = "sql"; 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; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); auto [err2, result2] = store->Query(table, sql, std::move(g_RdbValues)); EXPECT_EQ(err2, GeneralError::E_OK); EXPECT_NE(result2, nullptr); @@ -668,13 +544,9 @@ HWTEST_F(RdbGeneralStoreTest, Query001, TestSize.Level1) * @tc.name: Query002 * @tc.desc: RdbGeneralStore Query function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Query002, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "table"; std::string sql = "sql"; MockQuery query; @@ -688,24 +560,65 @@ HWTEST_F(RdbGeneralStoreTest, Query002, TestSize.Level1) EXPECT_EQ(result2, nullptr); } +/** + * @tc.name: Query003 + * @tc.desc: it is not a remote query return E_ERROR. + * @tc.type: FUNC + */ +HWTEST_F(RdbGeneralStoreTest, Query003, TestSize.Level1) +{ + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); + ASSERT_NE(store, nullptr); + + MockQuery query; + const std::string devices = "device1"; + const std::string sql; + Values args; + query.lastResult = true; + std::string table = "test_table"; + auto [err, cursor] = store->Query(table, query); + EXPECT_EQ(err, GeneralError::E_ERROR); +} + +/** + * @tc.name: Query004 + * @tc.desc: Test successful remote query + * @tc.type: FUNC + */ +HWTEST_F(RdbGeneralStoreTest, Query004, TestSize.Level1) +{ + MockQuery query; + const std::string devices = "device1"; + const std::string sql; + Values args; + query.MakeRemoteQuery(devices, sql, std::move(args)); + query.lastResult = true; + + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); + + std::string table = "test_table"; + auto [err, cursor] = store->Query(table, query); + + EXPECT_EQ(err, GeneralError::E_OK); + EXPECT_NE(cursor, nullptr); +} + /** * @tc.name: MergeMigratedData * @tc.desc: RdbGeneralStore MergeMigratedData function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, MergeMigratedData, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string tableName = "tableName"; DistributedData::VBuckets extends = { { g_RdbVBucket } }; auto result = store->MergeMigratedData(tableName, std::move(extends)); EXPECT_EQ(result, GeneralError::E_ERROR); - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); result = store->MergeMigratedData(tableName, std::move(extends)); EXPECT_EQ(result, GeneralError::E_OK); } @@ -714,13 +627,9 @@ HWTEST_F(RdbGeneralStoreTest, MergeMigratedData, TestSize.Level1) * @tc.name: Sync * @tc.desc: RdbGeneralStore Sync function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Sync, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); GeneralStore::Devices devices; MockQuery query; GeneralStore::DetailAsync async; @@ -728,42 +637,132 @@ HWTEST_F(RdbGeneralStoreTest, Sync, TestSize.Level1) auto result = store->Sync(devices, query, async, syncParam); EXPECT_EQ(result.first, GeneralError::E_ALREADY_CLOSED); - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); result = store->Sync(devices, query, async, syncParam); EXPECT_EQ(result.first, GeneralError::E_OK); } +/** +* @tc.name: Sync +* @tc.desc: RdbGeneralStore Sync CLOUD_TIME_FIRST test +* @tc.type: FUNC +*/ +HWTEST_F(RdbGeneralStoreTest, Sync001, TestSize.Level1) +{ + GeneralStore::Devices devices; + MockQuery query; + GeneralStore::DetailAsync async; + SyncParam syncParam; + syncParam.mode = GeneralStore::CLOUD_TIME_FIRST; + + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); + auto [result1, result2] = store->Sync(devices, query, async, syncParam); + EXPECT_EQ(result1, GeneralError::E_OK); + syncParam.mode = GeneralStore::NEARBY_END; + std::tie(result1, result2) = store->Sync(devices, query, async, syncParam); + EXPECT_EQ(result1, GeneralError::E_ERROR); + syncParam.mode = GeneralStore::NEARBY_PULL_PUSH; + std::tie(result1, result2) = store->Sync(devices, query, async, syncParam); + EXPECT_EQ(result1, GeneralError::E_OK); +} + +/** +* @tc.name: Sync +* @tc.desc: RdbGeneralStore Sync DistributedTable test +* @tc.type: FUNC +*/ +HWTEST_F(RdbGeneralStoreTest, Sync002, TestSize.Level1) +{ + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); + ASSERT_NE(store, nullptr); + + GeneralStore::Devices devices; + RdbQuery query; + GeneralStore::DetailAsync async; + SyncParam syncParam; + auto [result1, result2] = store->Sync(devices, query, async, syncParam); + EXPECT_EQ(result1, GeneralError::E_OK); +} + /** * @tc.name: PreSharing * @tc.desc: RdbGeneralStore PreSharing function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, PreSharing, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); MockQuery query; auto [errCode, result] = store->PreSharing(query); EXPECT_NE(errCode, GeneralError::E_OK); EXPECT_EQ(result, nullptr); } +/** +* @tc.name: PreSharing +* @tc.desc: RdbGeneralStore PreSharing function test, return E_INVALID_ARGS. +* @tc.type: FUNC +*/ +HWTEST_F(RdbGeneralStoreTest, PreSharing001, TestSize.Level1) +{ + MockQuery query; + query.lastResult = true; + auto [errCode, result] = store->PreSharing(query); + EXPECT_EQ(errCode, GeneralError::E_INVALID_ARGS); + EXPECT_EQ(result, nullptr); +} + +/** +* @tc.name: PreSharing +* @tc.desc: RdbGeneralStore PreSharing function delegate is nullptr test. +* @tc.type: FUNC +*/ +HWTEST_F(RdbGeneralStoreTest, PreSharing002, TestSize.Level1) +{ + MockQuery query; + DistributedRdb::PredicatesMemo predicates; + predicates.devices_ = { "device1" }; + predicates.tables_ = { "tables1" }; + query.lastResult = true; + query.MakeQuery(predicates); + auto [errCode, result] = store->PreSharing(query); + EXPECT_EQ(errCode, GeneralError::E_ALREADY_CLOSED); + EXPECT_EQ(result, nullptr); +} + +/** +* @tc.name: PreSharing +* @tc.desc: RdbGeneralStore PreSharing function E_CLOUD_DISABLED test. +* @tc.type: FUNC +*/ +HWTEST_F(RdbGeneralStoreTest, PreSharing003, TestSize.Level1) +{ + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); + ASSERT_NE(store, nullptr); + MockQuery query; + DistributedRdb::PredicatesMemo predicates; + predicates.devices_ = { "device1" }; + predicates.tables_ = { "tables1" }; + query.lastResult = true; + query.MakeQuery(predicates); + auto [errCode, result] = store->PreSharing(query); + EXPECT_EQ(errCode, GeneralError::E_CLOUD_DISABLED); + ASSERT_EQ(result, nullptr); +} + /** * @tc.name: ExtractExtend * @tc.desc: RdbGeneralStore ExtractExtend function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, ExtractExtend, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); RdbGeneralStore::VBucket extend = { { "#gid", { "0000000" } }, { "#flag", { true } }, - { "#value", { int64_t(100) } }, { "#float", { double(100) } }, { "#cloud_gid", { "cloud_gid" } } }; + { "#value", { int64_t(100) } }, { "#float", { double(100) } }, { "#cloud_gid", { "cloud_gid" } }, + { "cloud_gid", { "" } } }; DistributedData::VBuckets extends = { { extend } }; auto result = store->ExtractExtend(extends); EXPECT_EQ(result.size(), extends.size()); @@ -776,13 +775,9 @@ HWTEST_F(RdbGeneralStoreTest, ExtractExtend, TestSize.Level1) * @tc.name: Clean * @tc.desc: RdbGeneralStore Clean function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Clean, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string tableName = "tableName"; std::vector devices = { "device1", "device2" }; auto result = store->Clean(devices, -1, tableName); @@ -792,8 +787,8 @@ HWTEST_F(RdbGeneralStoreTest, Clean, TestSize.Level1) result = store->Clean(devices, GeneralStore::CLOUD_INFO, tableName); EXPECT_EQ(result, GeneralError::E_ALREADY_CLOSED); - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); result = store->Clean(devices, GeneralStore::CLOUD_INFO, tableName); EXPECT_EQ(result, GeneralError::E_OK); result = store->Clean(devices, GeneralStore::CLOUD_DATA, tableName); @@ -802,7 +797,7 @@ HWTEST_F(RdbGeneralStoreTest, Clean, TestSize.Level1) result = store->Clean(devices1, GeneralStore::NEARBY_DATA, tableName); EXPECT_EQ(result, GeneralError::E_OK); - g_testResult = true; + MockRelationalStoreDelegate::gTestResult = true; result = store->Clean(devices, GeneralStore::CLOUD_INFO, tableName); EXPECT_EQ(result, GeneralError::E_ERROR); result = store->Clean(devices, GeneralStore::CLOUD_DATA, tableName); @@ -817,13 +812,9 @@ HWTEST_F(RdbGeneralStoreTest, Clean, TestSize.Level1) * @tc.name: Watch * @tc.desc: RdbGeneralStore Watch and Unwatch function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Watch, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); MockGeneralWatcher watcher; auto result = store->Watch(GeneralWatcher::Origin::ORIGIN_CLOUD, watcher); EXPECT_EQ(result, GeneralError::E_INVALID_ARGS); @@ -845,13 +836,9 @@ HWTEST_F(RdbGeneralStoreTest, Watch, TestSize.Level1) * @tc.name: OnChange * @tc.desc: RdbGeneralStore OnChange function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, OnChange, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); MockGeneralWatcher watcher; MockStoreChangedData data; DistributedDB::ChangedData changedData; @@ -865,12 +852,54 @@ HWTEST_F(RdbGeneralStoreTest, OnChange, TestSize.Level1) EXPECT_EQ(result, GeneralError::E_OK); } +/** +* @tc.name: OnChange001 +* @tc.desc: RdbGeneralStore OnChange function test +* @tc.type: FUNC +*/ +HWTEST_F(RdbGeneralStoreTest, OnChange001, TestSize.Level1) +{ + MockGeneralWatcher watcher; + MockStoreChangedData data; + DistributedDB::ChangedData changedData; + changedData.primaryData[0] = { { std::monostate{}, 42, 3.14, "hello", true }, + { Bytes{ 1, 2, 3, 4 }, + DistributedDB::Asset{ 1, "zhangsan", "123", "/data/test", "file://xxx", "123", "100", "100", "999", + static_cast(AssetOpType::NO_CHANGE), static_cast(AssetStatus::NORMAL), 0 }, + Bytes{ 5, 6, 7, 8 } }, + { int64_t(-123), 2.718, 100, 0.001 } }; + changedData.primaryData[1] = { { std::monostate{}, 42, 3.14, "hello", true }, + { Bytes{ 1, 2, 3, 4 }, + DistributedDB::Asset{ 1, "zhangsan", "123", "/data/test", "file://xxx", "123", "100", "100", "999", + static_cast(AssetOpType::NO_CHANGE), static_cast(AssetStatus::NORMAL), 0 }, + Bytes{ 5, 6, 7, 8 } }, + { int64_t(-123), 2.718, 100, 0.001 } }; + changedData.primaryData[2] = { { "DELETE#ALL_CLOUDDATA", std::monostate{}, 42, 3.14, "hello", true }, + { Bytes{ 1, 2, 3, 4 }, + DistributedDB::Asset{ 1, "zhangsan", "123", "/data/test", "file://xxx", "123", "100", "100", "999", + static_cast(AssetOpType::NO_CHANGE), static_cast(AssetStatus::NORMAL), 0 }, + Bytes{ 5, 6, 7, 8 } }, + { int64_t(-123), 2.718, 100, 0.001 } }; + changedData.field = { "name", "age" }; + changedData.tableName = "test"; + DistributedDB::ChangedData changedDataTmp; + changedDataTmp = 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)); + EXPECT_EQ(watcher.primaryFields_[changedDataTmp.tableName], *(changedDataTmp.field.begin())); + store->observer_.OnChange(DistributedDB::Origin::ORIGIN_LOCAL, "originalId", std::move(changedDataTmp)); + ASSERT_NE(watcher.origin_.id.size(), 0); + EXPECT_EQ(watcher.origin_.id[0], "originalId"); + result = store->Unwatch(GeneralWatcher::Origin::ORIGIN_ALL, watcher); + EXPECT_EQ(result, GeneralError::E_OK); +} + /** * @tc.name: Release * @tc.desc: RdbGeneralStore Release and AddRef function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Release, TestSize.Level1) { @@ -897,28 +926,27 @@ HWTEST_F(RdbGeneralStoreTest, Release, TestSize.Level1) * @tc.name: SetDistributedTables * @tc.desc: RdbGeneralStore SetDistributedTables function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, SetDistributedTables, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::vector tables = { "table1", "table2" }; - int32_t type = 0; + int32_t type = DistributedTableType::DISTRIBUTED_DEVICE; std::vector references; auto result = store->SetDistributedTables(tables, type, references); EXPECT_EQ(result, GeneralError::E_ALREADY_CLOSED); - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); result = store->SetDistributedTables(tables, type, references); EXPECT_EQ(result, GeneralError::E_OK); std::vector test = { "test" }; result = store->SetDistributedTables(test, type, references); EXPECT_EQ(result, GeneralError::E_ERROR); - g_testResult = true; + MockRelationalStoreDelegate::gTestResult = true; + result = store->SetDistributedTables(tables, type, references); + EXPECT_EQ(result, GeneralError::E_OK); + type = DistributedTableType::DISTRIBUTED_CLOUD; result = store->SetDistributedTables(tables, type, references); EXPECT_EQ(result, GeneralError::E_ERROR); } @@ -927,21 +955,17 @@ HWTEST_F(RdbGeneralStoreTest, SetDistributedTables, TestSize.Level1) * @tc.name: SetTrackerTable * @tc.desc: RdbGeneralStore SetTrackerTable function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, SetTrackerTable, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string tableName = "tableName"; std::set trackerColNames = { "col1", "col2" }; std::set extendColNames = { "extendColName1", "extendColName2" }; auto result = store->SetTrackerTable(tableName, trackerColNames, extendColNames); EXPECT_EQ(result, GeneralError::E_ALREADY_CLOSED); - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); result = store->SetTrackerTable(tableName, trackerColNames, extendColNames); EXPECT_EQ(result, GeneralError::E_OK); result = store->SetTrackerTable("WITH_INVENTORY_DATA", trackerColNames, extendColNames); @@ -954,17 +978,13 @@ HWTEST_F(RdbGeneralStoreTest, SetTrackerTable, TestSize.Level1) * @tc.name: RemoteQuery * @tc.desc: RdbGeneralStore RemoteQuery function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, RemoteQuery, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string device = "device"; DistributedDB::RemoteCondition remoteCondition; - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); auto result = store->RemoteQuery("test", remoteCondition); EXPECT_EQ(result, nullptr); result = store->RemoteQuery(device, remoteCondition); @@ -975,13 +995,9 @@ HWTEST_F(RdbGeneralStoreTest, RemoteQuery, TestSize.Level1) * @tc.name: ConvertStatus * @tc.desc: RdbGeneralStore ConvertStatus function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, ConvertStatus, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); auto result = store->ConvertStatus(DBStatus::OK); EXPECT_EQ(result, GeneralError::E_OK); result = store->ConvertStatus(DBStatus::CLOUD_NETWORK_ERROR); @@ -1006,15 +1022,12 @@ HWTEST_F(RdbGeneralStoreTest, ConvertStatus, TestSize.Level1) * @tc.name: QuerySql * @tc.desc: RdbGeneralStore QuerySql function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, QuerySql, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); ASSERT_NE(store, nullptr); - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; auto [err1, result1] = store->QuerySql("", std::move(g_RdbValues)); EXPECT_EQ(err1, GeneralError::E_ERROR); EXPECT_TRUE(result1.empty()); @@ -1028,13 +1041,9 @@ HWTEST_F(RdbGeneralStoreTest, QuerySql, TestSize.Level1) * @tc.name: BuildSqlWhenCloumnEmpty * @tc.desc: test buildsql method when cloumn empty * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, BuildSqlWhenCloumnEmpty, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "mock_table"; std::string statement = "mock_statement"; std::vector columns; @@ -1048,13 +1057,9 @@ HWTEST_F(RdbGeneralStoreTest, BuildSqlWhenCloumnEmpty, TestSize.Level1) * @tc.name: BuildSqlWhenParamValid * @tc.desc: test buildsql method when param valid * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, BuildSqlWhenParamValid, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "mock_table"; std::string statement = "mock_statement"; std::vector columns; @@ -1071,13 +1076,9 @@ HWTEST_F(RdbGeneralStoreTest, BuildSqlWhenParamValid, TestSize.Level1) * @tc.name: LockAndUnLockCloudDBTest * @tc.desc: lock and unlock cloudDB test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, LockAndUnLockCloudDBTest, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); auto result = store->LockCloudDB(); EXPECT_EQ(result.first, 1); EXPECT_EQ(result.second, 0); @@ -1089,13 +1090,9 @@ HWTEST_F(RdbGeneralStoreTest, LockAndUnLockCloudDBTest, TestSize.Level1) * @tc.name: InFinishedTest * @tc.desc: isFinished test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, InFinishedTest, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedRdb::RdbGeneralStore::SyncId syncId = 1; bool isFinished = store->IsFinished(syncId); EXPECT_TRUE(isFinished); @@ -1105,13 +1102,9 @@ HWTEST_F(RdbGeneralStoreTest, InFinishedTest, TestSize.Level1) * @tc.name: GetRdbCloudTest * @tc.desc: getRdbCloud test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, GetRdbCloudTest, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); auto rdbCloud = store->GetRdbCloud(); EXPECT_EQ(rdbCloud, nullptr); } @@ -1120,13 +1113,9 @@ HWTEST_F(RdbGeneralStoreTest, GetRdbCloudTest, TestSize.Level1) * @tc.name: RegisterDetailProgressObserverTest * @tc.desc: RegisterDetailProgressObserver test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, RegisterDetailProgressObserverTest, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedData::GeneralStore::DetailAsync async; auto result = store->RegisterDetailProgressObserver(async); EXPECT_EQ(result, GeneralError::E_OK); @@ -1136,13 +1125,9 @@ HWTEST_F(RdbGeneralStoreTest, RegisterDetailProgressObserverTest, TestSize.Level * @tc.name: GetFinishTaskTest * @tc.desc: GetFinishTask test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, GetFinishTaskTest, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedRdb::RdbGeneralStore::SyncId syncId = 1; auto result = store->GetFinishTask(syncId); ASSERT_NE(result, nullptr); @@ -1152,16 +1137,27 @@ HWTEST_F(RdbGeneralStoreTest, GetFinishTaskTest, TestSize.Level1) * @tc.name: GetCBTest * @tc.desc: GetCB test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, GetCBTest, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedRdb::RdbGeneralStore::SyncId syncId = 1; auto result = store->GetCB(syncId); ASSERT_NE(result, nullptr); } + +/** +* @tc.name: UpdateDBStatus +* @tc.desc: UpdateDBStatus test +* @tc.type: FUNC +*/ +HWTEST_F(RdbGeneralStoreTest, UpdateDBStatus, TestSize.Level1) +{ + auto result = store->UpdateDBStatus(); + EXPECT_EQ(result, E_ALREADY_CLOSED); + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); + result = store->UpdateDBStatus(); + EXPECT_EQ(result, E_OK); +} } // namespace DistributedRDBTest } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_service_impl_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_service_impl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..abe2488366efda20b6e61484c63261d102a69a26 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_service_impl_test.cpp @@ -0,0 +1,2464 @@ +/* + * Copyright (c) 2025 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 "account/account_delegate.h" +#include "bootstrap.h" +#include "checker_mock.h" +#include "cloud/change_event.h" +#include "cloud/schema_meta.h" +#include "crypto/crypto_manager.h" +#include "device_manager_adapter.h" +#include "device_matrix.h" +#include "event_center.h" +#include "ipc_skeleton.h" +#include "metadata/capability_meta_data.h" +#include "metadata/meta_data_manager.h" +#include "metadata/store_meta_data.h" +#include "metadata/store_meta_data_local.h" +#include "metadata/store_debug_info.h" +#include "mock/device_manager_adapter_mock.h" +#include "mock/db_store_mock.h" +#include "mock/general_store_mock.h" +#include "store/general_value.h" +#include "rdb_service_impl.h" +#include "rdb_types.h" +#include "relational_store_manager.h" +#include "gtest/gtest.h" +#include "directory/directory_manager.h" + +using namespace OHOS::DistributedRdb; +using namespace OHOS::DistributedData; +using namespace DistributedDB; +using namespace testing::ext; +using namespace testing; +using namespace std; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; + +namespace OHOS::Test { +namespace DistributedRDBTest { + +static constexpr const char *TEST_BUNDLE = "test_rdb_service_impl_bundleName"; +static constexpr const char *TEST_APPID = "test_rdb_service_impl_appid"; +static constexpr const char *TEST_STORE = "test_rdb_service_impl_store"; +static constexpr int32_t KEY_LENGTH = 32; +static constexpr uint32_t DELY_TIME = 10000; + +class RdbServiceImplTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + static void InitMetaData(); + static void InitMapping(StoreMetaMapping &meta); + void SetUp(); + void TearDown(); + static std::vector Random(int32_t len); +protected: + static std::shared_ptr dbStoreMock_; + static StoreMetaData metaData_; + static CheckerMock checkerMock_; + static inline std::shared_ptr deviceManagerAdapterMock = nullptr; + static void InitMetaDataManager(); +}; + +std::shared_ptr RdbServiceImplTest::dbStoreMock_ = std::make_shared(); +StoreMetaData RdbServiceImplTest::metaData_; +CheckerMock RdbServiceImplTest::checkerMock_; + +void RdbServiceImplTest::InitMetaData() +{ + metaData_.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData_.appId = TEST_APPID; + metaData_.bundleName = TEST_BUNDLE; + metaData_.tokenId = OHOS::IPCSkeleton::GetCallingTokenID(); + metaData_.user = std::to_string(AccountDelegate::GetInstance()->GetUserByToken(metaData_.tokenId)); + metaData_.area = OHOS::DistributedKv::EL1; + metaData_.instanceId = 0; + metaData_.isAutoSync = true; + metaData_.storeType = DistributedRdb::RDB_DEVICE_COLLABORATION; + metaData_.storeId = TEST_STORE; + metaData_.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData_) + "/" + TEST_STORE; +} + +void RdbServiceImplTest::InitMapping(StoreMetaMapping &metaMapping) +{ + metaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaMapping.user = "100"; + metaMapping.bundleName = "bundleName"; + metaMapping.storeId = "storeName"; +} + +void RdbServiceImplTest::InitMetaDataManager() +{ + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + MetaDataManager::GetInstance().SetSyncer([](const auto &, auto) { + DeviceMatrix::GetInstance().OnChanged(DeviceMatrix::META_STORE_MASK); + }); +} + +void RdbServiceImplTest::SetUpTestCase() +{ + deviceManagerAdapterMock = std::make_shared(); + BDeviceManagerAdapter::deviceManagerAdapter = deviceManagerAdapterMock; + DeviceInfo deviceInfo; + deviceInfo.uuid = "ABCD"; + EXPECT_CALL(*deviceManagerAdapterMock, GetLocalDevice()).WillRepeatedly(Return(deviceInfo)); + EXPECT_CALL(*deviceManagerAdapterMock, GetUuidByNetworkId(_)).WillRepeatedly(Return(deviceInfo.uuid)); + EXPECT_CALL(*deviceManagerAdapterMock, CalcClientUuid(_, _)).WillRepeatedly(Return(deviceInfo.uuid)); + EXPECT_CALL(*deviceManagerAdapterMock, ToUUID(deviceInfo.uuid)).WillRepeatedly(Return(deviceInfo.uuid)); + + InitMetaData(); + Bootstrap::GetInstance().LoadCheckers(); + CryptoManager::GetInstance().GenerateRootKey(); + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); +} + +void RdbServiceImplTest::TearDownTestCase() +{ + deviceManagerAdapterMock = nullptr; + BDeviceManagerAdapter::deviceManagerAdapter = nullptr; +} + +void RdbServiceImplTest::SetUp() +{ +} + +void RdbServiceImplTest::TearDown() +{ +} + +std::vector RdbServiceImplTest::Random(int32_t len) +{ + std::random_device randomDevice; + std::uniform_int_distribution distribution(0, std::numeric_limits::max()); + std::vector key(len); + for (uint32_t i = 0; i < len; i++) { + key[i] = static_cast(distribution(randomDevice)); + } + return key; +} + +/** +* @tc.name: OnRemoteRequest001 +* @tc.desc: ResolveAutoLaunch LoadMeta Failed. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, ResolveAutoLaunch001, TestSize.Level0) +{ + auto localId = DmAdapter::GetInstance().GetLocalDevice().uuid; + DistributedDB::AutoLaunchParam param; + RdbServiceImpl service; + + std::string identifier = "test_identifier"; + int32_t result = service.ResolveAutoLaunch(identifier, param); + EXPECT_EQ(result, false); +} + +/** +* @tc.name: ResolveAutoLaunch002 +* @tc.desc: ResolveAutoLaunch no meta. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, ResolveAutoLaunch002, TestSize.Level0) +{ + InitMetaDataManager(); + auto localId = DmAdapter::GetInstance().GetLocalDevice().uuid; + DistributedDB::AutoLaunchParam param; + RdbServiceImpl service; + + std::string identifier = "test_identifier"; + int32_t result = service.ResolveAutoLaunch(identifier, param); + EXPECT_EQ(result, false); +} + +/** +* @tc.name: ResolveAutoLaunch003 +* @tc.desc: ResolveAutoLaunch has meta, identifier not match. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, ResolveAutoLaunch003, TestSize.Level0) +{ + auto ret = MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false); + EXPECT_EQ(ret, true); + StoreMetaData meta; + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta.user = std::to_string(AccountDelegate::GetInstance()->GetUserByToken(meta.tokenId)); + meta.bundleName = TEST_BUNDLE; + meta.storeId = "ResolveAutoLaunch003"; + meta.instanceId = 0; + meta.appId = TEST_APPID; + meta.tokenId = OHOS::IPCSkeleton::GetCallingTokenID(); + meta.area = OHOS::DistributedKv::EL1; + meta.isAutoSync = true; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKeyWithoutPath(), meta, false), true); + + DistributedDB::AutoLaunchParam param; + RdbServiceImpl service; + + std::string identifier = "test_identifier"; + int32_t result = service.ResolveAutoLaunch(identifier, param); + + EXPECT_EQ(result, false); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** +* @tc.name: ResolveAutoLaunch004 +* @tc.desc: ResolveAutoLaunch has meta, identifier match. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, ResolveAutoLaunch004, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + DistributedDB::AutoLaunchParam param; + RdbServiceImpl service; + RelationalStoreManager userMgr(metaData_.appId, metaData_.user, metaData_.storeId); + auto identifier = userMgr.GetRelationalStoreIdentifier(metaData_.user, metaData_.appId, metaData_.storeId, true); + + int32_t result = service.ResolveAutoLaunch(identifier, param); + + EXPECT_EQ(result, true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** +* @tc.name: ResolveAutoLaunch005 +* @tc.desc: ResolveAutoLaunch has meta, identifier match, is encrypt. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, ResolveAutoLaunch005, TestSize.Level0) +{ + auto meta = metaData_; + meta.isEncrypt = true; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKeyWithoutPath(), meta, false), true); + DistributedDB::AutoLaunchParam param; + RdbServiceImpl service; + RelationalStoreManager userMgr1(meta.appId, meta.user, meta.storeId); + auto identifier = userMgr1.GetRelationalStoreIdentifier(meta.user, meta.appId, meta.storeId, true); + + int32_t result = service.ResolveAutoLaunch(identifier, param); + + EXPECT_EQ(result, true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKeyWithoutPath(), false), true); +} + +/** +* @tc.name: ResolveAutoLaunch006 +* @tc.desc: test ObtainDistributedTableName, uuid exist. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, ResolveAutoLaunch006, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + RdbServiceImpl service; + auto deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + RdbSyncerParam param{ .bundleName_ = TEST_BUNDLE }; + auto ret = service.ObtainDistributedTableName(param, deviceId, TEST_STORE); + EXPECT_GT(ret.length(), 0); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** +* @tc.name: ObtainDistributedTableName001 +* @tc.desc: test ObtainDistributedTableName, uuid invalid. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, ObtainDistributedTableName001, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + RdbServiceImpl service; + RdbSyncerParam param; + auto ret = service.ObtainDistributedTableName(param, "invalid_device_id", TEST_STORE); + EXPECT_EQ(ret.length(), 0); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: RemoteQuery001 + * @tc.desc: test RemoteQuery, param invalid. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, RemoteQuery001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + param.hapName_ = "test/test"; + std::vector selectionArgs; + auto deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + auto ret = service.RemoteQuery(param, deviceId, "", selectionArgs); + EXPECT_EQ(ret.first, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: RemoteQuery002 + * @tc.desc: test RemoteQuery, when CheckAccess fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, RemoteQuery002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + std::vector selectionArgs; + auto deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + auto ret = service.RemoteQuery(param, deviceId, "", selectionArgs); + EXPECT_EQ(ret.first, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: RemoteQuery003 + * @tc.desc: test RemoteQuery, when CheckAccess pass but query failed. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, RemoteQuery003, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = "RemoteQuery003"; + std::vector selectionArgs; + auto deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + auto ret = service.RemoteQuery(param, deviceId, "", selectionArgs); + EXPECT_EQ(ret.first, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** +* @tc.name: TransferStringToHex001 +* @tc.desc: test TransferStringToHex, param empty. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, TransferStringToHex001, TestSize.Level0) +{ + RdbServiceImpl service; + auto ret = service.TransferStringToHex(""); + EXPECT_EQ(ret.length(), 0); +} + +/** +* @tc.name: GetCallbacks001 +* @tc.desc: test GetCallbacks. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, GetCallbacks001, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + RdbServiceImpl service; + auto ret = service.GetCallbacks(metaData_.tokenId, metaData_.storeId); + EXPECT_EQ(ret, nullptr); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: DoSync001 + * @tc.desc: Test DoSync when the store is null. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, DoSync001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + RdbService::Option option; + PredicatesMemo predicates; + AsyncDetail async; + + auto result = service.DoSync(param, option, predicates, async); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: DoSync002 + * @tc.desc: Test DoSync when meta sync is needed and succeeds. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, DoSync002, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.type_ = metaData_.storeType; + param.level_ = metaData_.securityLevel; + param.area_ = metaData_.area; + param.hapName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + param.isEncrypt_ = metaData_.isEncrypt; + param.isSearchable_ = metaData_.isSearchable; + param.haMode_ = metaData_.haMode; + param.asyncDownloadAsset_ = metaData_.asyncDownloadAsset; + + RdbService::Option option; + option.mode = DistributedData::GeneralStore::AUTO_SYNC_MODE; + option.seqNum = 1; + + PredicatesMemo predicates; + AsyncDetail async; + + auto result = service.DoSync(param, option, predicates, async); + EXPECT_EQ(result, RDB_ERROR); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: IsNeedMetaSync001 + * @tc.desc: Test IsNeedMetaSync when LoadMeta fails for CapMetaData. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, IsNeedMetaSync001, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + std::vector devices = {DmAdapter::GetInstance().ToUUID(metaData_.deviceId)}; + RdbServiceImpl service; + bool result = service.IsNeedMetaSync(metaData_, devices); + + EXPECT_EQ(result, true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: IsNeedMetaSync002 + * @tc.desc: Test IsNeedMetaSync when LoadMeta fails for StoreMetaData. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, IsNeedMetaSync002, TestSize.Level0) +{ + CapMetaData capMetaData; + auto capKey = CapMetaRow::GetKeyFor(metaData_.deviceId); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(std::string(capKey.begin(), capKey.end()), capMetaData), true); + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + std::vector devices = {DmAdapter::GetInstance().ToUUID(metaData_.deviceId)}; + RdbServiceImpl service; + bool result = service.IsNeedMetaSync(metaData_, devices); + + EXPECT_EQ(result, false); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: ProcessResult001 + * @tc.desc: Test ProcessResult when all results have DBStatus::OK. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, ProcessResult001, TestSize.Level0) +{ + RdbServiceImpl service; + std::map results = {{"device1", static_cast(DBStatus::OK)}, + {"device2", static_cast(DBStatus::OK)}}; + + auto result = service.ProcessResult(results); + + EXPECT_EQ(result.second.at("device1"), DBStatus::OK); + EXPECT_EQ(result.second.at("device2"), DBStatus::OK); +} + +/** + * @tc.name: ProcessResult002 + * @tc.desc: Test ProcessResult when some results have DBStatus::OK and others do not. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, ProcessResult002, TestSize.Level0) +{ + RdbServiceImpl service; + std::map results = {{"device1", static_cast(DBStatus::OK)}, + {"device2", static_cast(DBStatus::DB_ERROR)}, + {"device3", static_cast(DBStatus::OK)}}; + + auto result = service.ProcessResult(results); + + EXPECT_EQ(result.second.at("device1"), DBStatus::OK); + EXPECT_EQ(result.second.at("device2"), DBStatus::DB_ERROR); + EXPECT_EQ(result.second.at("device3"), DBStatus::OK); +} + +/** + * @tc.name: ProcessResult004 + * @tc.desc: Test ProcessResult with an empty results map. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, ProcessResult004, TestSize.Level0) +{ + RdbServiceImpl service; + std::map results; + + auto result = service.ProcessResult(results); + + EXPECT_EQ(result.first.size(), 0); + EXPECT_EQ(result.second.size(), 0); +} + +/** + * @tc.name: DoCompensateSync001 + * @tc.desc: Test DoCompensateSync when the event has valid bindInfo and COMPENSATE_SYNC event ID. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, DoCompensateSync001, TestSize.Level0) +{ + RdbServiceImpl service; + + int32_t eventId = 1; + DistributedData::BindEvent::BindEventInfo bindInfo; + bindInfo.bundleName = TEST_BUNDLE; + bindInfo.tokenId = metaData_.tokenId; + bindInfo.user = metaData_.uid; + bindInfo.storeName = TEST_STORE; + bindInfo.tableName = "test_table"; + bindInfo.primaryKey = {{"key1", "value1"}, {"key2", "value2"}}; + + BindEvent event(eventId, std::move(bindInfo)); + EventCenter::GetInstance().Subscribe(CloudEvent::LOCAL_CHANGE, [this] (const Event &event) { + auto &evt = static_cast(event); + auto mode = evt.GetMode(); + EXPECT_EQ(GeneralStore::GetPriorityLevel(GeneralStore::GetHighMode(static_cast(mode))), 1); + }); + service.DoCompensateSync(event); + EventCenter::GetInstance().Unsubscribe(CloudEvent::LOCAL_CHANGE); +} + +/** + * @tc.name: ReportStatistic001 + * @tc.desc: Test ReportStatistic when CheckAccess fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, ReportStatistic001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + RdbStatEvent statEvent; + + int32_t result = service.ReportStatistic(param, statEvent); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: ReportStatistic002 + * @tc.desc: Test ReportStatistic when CheckAccess success. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, ReportStatistic002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + RdbStatEvent statEvent; + + int32_t result = service.ReportStatistic(param, statEvent); + + EXPECT_EQ(result, OK); +} + +/** + * @tc.name: GetReuseDevice001 + * @tc.desc: Test GetReuseDevice when all devices are reusable. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, GetReuseDevice001, TestSize.Level0) +{ + RdbServiceImpl service; + std::vector devices = {"device1"}; + StoreMetaData metaData; + auto result = service.GetReuseDevice(devices, metaData); + EXPECT_EQ(result.size(), 0); +} + +/** + * @tc.name: DoAutoSync001 + * @tc.desc: Test DoAutoSync when the store is null. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, DoAutoSync001, TestSize.Level0) +{ + RdbServiceImpl service; + std::vector devices = {"device1"}; + DistributedData::Database dataBase; + std::vector tables = {"table1"}; + + auto result = service.DoAutoSync(devices, dataBase, tables); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: DoAutoSync002 + * @tc.desc: Test DoAutoSync when the store is null. + * @tc.type: FUNC + * @tc.require: + * @tc.author: my + */ +HWTEST_F(RdbServiceImplTest, DoAutoSync002, TestSize.Level0) +{ + StoreMetaMapping metaMapping; + InitMapping(metaMapping); + metaMapping.dataDir = "path"; + metaMapping.devicePath = "path1"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + RdbServiceImpl service; + std::vector devices = {"device1"}; + DistributedData::Database dataBase; + std::vector tables = {"table1"}; + dataBase.bundleName = "bundleName"; + dataBase.name = "storeName"; + dataBase.user = "100"; + auto result = service.DoAutoSync(devices, dataBase, tables); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: DoOnlineSync001 + * @tc.desc: Test DoOnlineSync when all tables have deviceSyncFields. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, DoOnlineSync001, TestSize.Level0) +{ + RdbServiceImpl service; + std::vector devices = {"device1"}; + DistributedData::Database dataBase; + dataBase.name = TEST_STORE; + + DistributedData::Table table1; + table1.name = "table1"; + table1.deviceSyncFields = {"field1", "field2"}; + DistributedData::Table table2; + table2.name = "table2"; + table2.deviceSyncFields = {}; + + dataBase.tables = {table1, table2}; + + auto result = service.DoOnlineSync(devices, dataBase); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: OnReady001 + * @tc.desc: Test OnReady when LoadMeta fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, OnReady001, TestSize.Level0) +{ + RdbServiceImpl service; + std::string device = "test_device"; + + int32_t result = service.OnReady(device); + EXPECT_EQ(result, 0); +} + +/** + * @tc.name: OnReady002 + * @tc.desc: Test OnReady when no databases have autoSyncType SYNC_ON_READY or SYNC_ON_CHANGE_READY. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, OnReady002, TestSize.Level0) +{ + RdbServiceImpl service; + std::string device = metaData_.deviceId; + + DistributedData::Database dataBase1; + dataBase1.name = "test_rdb_service_impl_sync_store2"; + dataBase1.bundleName = TEST_BUNDLE; + dataBase1.user = std::to_string(AccountDelegate::GetInstance()->GetUserByToken(metaData_.tokenId)); + dataBase1.autoSyncType = AutoSyncType::SYNC_ON_READY; + + DistributedData::Database dataBase2; + dataBase2.name = "test_rdb_service_impl_sync_store2"; + dataBase2.bundleName = TEST_BUNDLE; + dataBase2.user = std::to_string(AccountDelegate::GetInstance()->GetUserByToken(metaData_.tokenId)); + dataBase2.autoSyncType = AutoSyncType::SYNC_ON_CHANGE_READY; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(dataBase1.GetKey(), metaData_, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(dataBase2.GetKey(), metaData_, true), true); + int32_t result = service.OnReady(device); + + EXPECT_EQ(result, 0); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(dataBase1.GetKey(), metaData_, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(dataBase2.GetKey(), metaData_, true), true); +} + +/** + * @tc.name: AfterOpen001 + * @tc.desc: Test AfterOpen when CheckParam not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, AfterOpen001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + param.hapName_ = "test/test"; + int32_t result = service.AfterOpen(param); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: AfterOpen002 + * @tc.desc: Test AfterOpen when CheckAccess not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, AfterOpen002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + int32_t result = service.AfterOpen(param); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: AfterOpen003 + * @tc.desc: Test AfterOpen when CheckAccess pass and CheckParam pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, AfterOpen003, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + int32_t result = service.AfterOpen(param); + + EXPECT_EQ(result, RDB_OK); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: AfterOpen004 + * @tc.desc: Test AfterOpen when CheckAccess pass and CheckParam pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, AfterOpen004, TestSize.Level0) +{ + metaData_.isSearchable = true; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + int32_t result = service.AfterOpen(param); + + EXPECT_EQ(result, RDB_OK); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: NotifyDataChange001 + * @tc.desc: Test NotifyDataChange when CheckParam not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, NotifyDataChange001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + param.hapName_ = "test/test"; + RdbChangedData rdbChangedData; + RdbNotifyConfig rdbNotifyConfig; + int32_t result = service.NotifyDataChange(param, rdbChangedData, rdbNotifyConfig); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: NotifyDataChange002 + * @tc.desc: Test NotifyDataChange when CheckAccess not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, NotifyDataChange002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + RdbChangedData rdbChangedData; + RdbNotifyConfig rdbNotifyConfig; + int32_t result = service.NotifyDataChange(param, rdbChangedData, rdbNotifyConfig); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: NotifyDataChange003 + * @tc.desc: Test NotifyDataChange when Check pass. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, NotifyDataChange003, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.storeName_ = "validStoreName"; + param.bundleName_ = "validBundleName"; + param.user_ = "validUser"; + param.hapName_ = "validHapName"; + param.customDir_ = "dir1/dir2"; + RdbChangedData rdbChangedData; + RdbNotifyConfig rdbNotifyConfig; + rdbNotifyConfig.delay_ = 0; + int32_t result = service.NotifyDataChange(param, rdbChangedData, rdbNotifyConfig); + EXPECT_EQ(result, RDB_OK); + rdbNotifyConfig.delay_ = DELY_TIME; + result = service.NotifyDataChange(param, rdbChangedData, rdbNotifyConfig); + EXPECT_EQ(result, RDB_OK); +} + +/** + * @tc.name: SetSearchable001 + * @tc.desc: Test SetSearchable when CheckAccess fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, SetSearchable001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + + bool isSearchable = true; + int32_t result = service.SetSearchable(param, isSearchable); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: SetSearchable002 + * @tc.desc: Test SetSearchable when CheckAccess succeeds and PostSearchEvent is called. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, SetSearchable002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + + bool isSearchable = true; + int32_t result = service.SetSearchable(param, isSearchable); + + EXPECT_EQ(result, RDB_OK); +} + +/** + * @tc.name: GetPassword001 + * @tc.desc: Test GetPassword when CheckAccess fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, GetPassword001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + std::vector> password; + + int32_t result = service.GetPassword(param, password); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: GetPassword002 + * @tc.desc: Test GetPassword when no meta data is found. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, GetPassword002, TestSize.Level0) +{ + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + auto meta = metaData_; + meta.isEncrypt = true; + auto sKey = Random(KEY_LENGTH); + ASSERT_FALSE(sKey.empty()); + SecretKeyMetaData secretKey; + CryptoManager::CryptoParams encryptParams; + secretKey.sKey = CryptoManager::GetInstance().Encrypt(sKey, encryptParams); + secretKey.area = encryptParams.area; + secretKey.storeType = meta.storeType; + secretKey.nonce = encryptParams.nonce; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetSecretKey(), secretKey, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = meta.bundleName; + param.storeName_ = meta.storeId; + std::vector> password; + int32_t result = service.GetPassword(param, password); + + EXPECT_EQ(result, RDB_OK); + ASSERT_GT(password.size(), 0); + EXPECT_EQ(password.at(0), sKey); + MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); + MetaDataManager::GetInstance().DelMeta(meta.GetSecretKey(), true); +} + +/** + * @tc.name: GetPassword003 + * @tc.desc: Test GetPassword when decryption fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, GetPassword003, TestSize.Level0) +{ + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + auto meta = metaData_; + meta.isEncrypt = true; + auto sKey = Random(KEY_LENGTH); + ASSERT_FALSE(sKey.empty()); + SecretKeyMetaData secretKey; + secretKey.sKey = sKey; // Invalid key for decryption + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetSecretKey(), secretKey, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = meta.bundleName; + param.storeName_ = meta.storeId; + std::vector> password; + + int32_t result = service.GetPassword(param, password); + + EXPECT_EQ(result, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetSecretKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); +} + +/** + * @tc.name: GetPassword004 + * @tc.desc: Test GetPassword when no meta data is found. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, GetPassword004, TestSize.Level0) +{ + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + auto meta = metaData_; + meta.isEncrypt = true; + auto sKey = Random(KEY_LENGTH); + ASSERT_FALSE(sKey.empty()); + SecretKeyMetaData secretKey; + CryptoManager::CryptoParams encryptParams; + secretKey.sKey = CryptoManager::GetInstance().Encrypt(sKey, encryptParams); + secretKey.area = encryptParams.area; + secretKey.storeType = meta.storeType; + secretKey.nonce = encryptParams.nonce; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetCloneSecretKey(), secretKey, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = meta.bundleName; + param.storeName_ = meta.storeId; + param.type_ = meta.storeType; + std::vector> password; + + int32_t result = service.GetPassword(param, password); + + EXPECT_EQ(result, RDB_OK); + ASSERT_GT(password.size(), 0); + EXPECT_EQ(password.at(0), sKey); + MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); + MetaDataManager::GetInstance().DelMeta(meta.GetCloneSecretKey(), true); +} + +/** + * @tc.name: GetPassword005 + * @tc.desc: Test GetPassword when no meta data. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, GetPassword005, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + param.type_ = StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN; + std::vector> password; + + int32_t result = service.GetPassword(param, password); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: GetPassword006 + * @tc.desc: Test GetPassword when meta data is found. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, GetPassword006, TestSize.Level0) +{ + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + auto meta = metaData_; + meta.isEncrypt = true; + auto sKey = Random(KEY_LENGTH); + ASSERT_FALSE(sKey.empty()); + SecretKeyMetaData secretKey; + CryptoManager::CryptoParams encryptParams; + secretKey.sKey = CryptoManager::GetInstance().Encrypt(sKey, encryptParams); + secretKey.area = encryptParams.area; + secretKey.storeType = meta.storeType; + secretKey.nonce = encryptParams.nonce; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetCloneSecretKey(), secretKey, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = meta.bundleName; + param.storeName_ = meta.storeId; + param.type_ = meta.storeType; + param.customDir_ = "../../../base/haps/entry/files/.backup/textautofill"; + std::vector> password; + + int32_t result = service.GetPassword(param, password); + + EXPECT_EQ(result, RDB_OK); + ASSERT_GT(password.size(), 0); + EXPECT_EQ(password.at(0), sKey); + MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); + MetaDataManager::GetInstance().DelMeta(meta.GetCloneSecretKey(), true); +} + +/** + * @tc.name: SetDistributedTables001 + * @tc.desc: Test SetDistributedTables when CheckAccess not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, SetDistributedTables001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + std::vector tables; + std::vector references; + + int32_t result = service.SetDistributedTables(param, tables, references, false); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: SetDistributedTables002 + * @tc.desc: Test SetDistributedTables when type is search. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, SetDistributedTables002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + param.type_ = StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN; + std::vector tables; + std::vector references; + + int32_t result = + service.SetDistributedTables(param, tables, references, false, + DistributedTableType::DISTRIBUTED_SEARCH); + EXPECT_EQ(result, RDB_OK); +} + +/** + * @tc.name: SetDistributedTables003 + * @tc.desc: Test SetDistributedTables when type is search. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, SetDistributedTables003, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + param.type_ = StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN; + param.hapName_ = "test/test"; + std::vector tables; + std::vector references; + + int32_t result = + service.SetDistributedTables(param, tables, references, false, + DistributedTableType::DISTRIBUTED_SEARCH); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: SetDistributedTables004 + * @tc.desc: Test SetDistributedTables when type is device. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, SetDistributedTables004, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = "SetDistributedTables004"; + param.type_ = StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN; + std::vector tables; + std::vector references; + + auto meta = service.GetStoreMetaData(param); + ASSERT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + + auto creator = [](const StoreMetaData &metaData) -> GeneralStore* { + auto store = new (std::nothrow) GeneralStoreMock(); + return store; + }; + AutoCache::GetInstance().RegCreator(DistributedRdb::RDB_DEVICE_COLLABORATION, creator); + + int32_t result = + service.SetDistributedTables(param, tables, references, false, + DistributedTableType::DISTRIBUTED_DEVICE); + EXPECT_EQ(result, RDB_OK); + ASSERT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); +} + +/** + * @tc.name: Sync001 + * @tc.desc: Test Sync when CheckAccess not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, Sync001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + RdbService::Option option {}; + PredicatesMemo predicates; + + int32_t result = service.Sync(param, option, predicates, nullptr); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: Sync002 + * @tc.desc: Test Sync when CheckParam not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, Sync002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + param.hapName_ = "test/test"; + RdbService::Option option {}; + PredicatesMemo predicates; + + int32_t result = service.Sync(param, option, predicates, nullptr); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: Sync003 + * @tc.desc: Test Sync when mode is nearby begin. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, Sync003, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = "Sync003"; + RdbService::Option option { DistributedData::GeneralStore::NEARBY_BEGIN }; + PredicatesMemo predicates; + + int32_t result = service.Sync(param, option, predicates, nullptr); + EXPECT_EQ(result, RDB_OK); +} + +/** + * @tc.name: Sync004 + * @tc.desc: Test Sync when mode is cloud begin. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, Sync004, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = "Sync004"; + RdbService::Option option { DistributedData::GeneralStore::CLOUD_BEGIN }; + PredicatesMemo predicates; + + int32_t result = service.Sync(param, option, predicates, nullptr); + EXPECT_EQ(result, RDB_OK); +} + + +/** + * @tc.name: QuerySharingResource001 + * @tc.desc: Test QuerySharingResource when CheckParam not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, QuerySharingResource001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + PredicatesMemo predicates; + std::vector columns; + auto result = service.QuerySharingResource(param, predicates, columns); + EXPECT_EQ(result.first, RDB_ERROR); +} + +/** + * @tc.name: BeforeOpen001 + * @tc.desc: Test BeforeOpen when CheckParam not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, BeforeOpen001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + param.hapName_ = "test/test"; + int32_t result = service.BeforeOpen(param); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: BeforeOpen002 + * @tc.desc: Test BeforeOpen when checkacess not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, BeforeOpen002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + int32_t result = service.BeforeOpen(param); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: BeforeOpen003 + * @tc.desc: Test BeforeOpen when checkacess pass and CheckParam pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, BeforeOpen003, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + int32_t result = service.BeforeOpen(param); + EXPECT_EQ(result, RDB_NO_META); +} + +/** + * @tc.name: BeforeOpen004 + * @tc.desc: Test BeforeOpen when checkacess pass and CheckParam pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, BeforeOpen004, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKey(), metaData_, true), true); + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + int32_t result = service.BeforeOpen(param); + EXPECT_EQ(result, RDB_OK); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKey(), true), true); +} + +/** + * @tc.name: Subscribe001 + * @tc.desc: Test Subscribe when option mode invalid. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, Subscribe001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + SubscribeOption option {}; + option.mode = SubscribeMode::SUBSCRIBE_MODE_MAX; + + int32_t result = service.Subscribe(param, option, nullptr); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: UnSubscribe001 + * @tc.desc: Test UnSubscribe when option mode invalid. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, UnSubscribe001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + SubscribeOption option {}; + option.mode = SubscribeMode::SUBSCRIBE_MODE_MAX; + + int32_t result = service.UnSubscribe(param, option, nullptr); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: GetDfxInfo001 + * @tc.desc: Test GetDfxInfo when CheckAccess not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, GetDfxInfo001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + DistributedRdb::RdbDfxInfo dfxInfo; + + int32_t result = service.GetDfxInfo(param, dfxInfo); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: GetDfxInfo002 + * @tc.desc: Test GetDfxInfo when CheckAccess pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, GetDfxInfo002, TestSize.Level0) +{ + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + auto meta = metaData_; + DistributedData::StoreDfxInfo dfxMeta; + dfxMeta.lastOpenTime = "test"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetDfxInfoKey(), dfxMeta, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = meta.bundleName; + param.storeName_ = meta.storeId; + param.type_ = meta.storeType; + param.customDir_ = "../../../base/haps/entry/files/.backup/textautofill"; + DistributedRdb::RdbDfxInfo dfxInfo; + int32_t result = service.GetDfxInfo(param, dfxInfo); + EXPECT_EQ(dfxInfo.lastOpenTime_, "test"); + EXPECT_EQ(result, RDB_OK); + MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); + MetaDataManager::GetInstance().DelMeta(meta.GetDfxInfoKey(), true); +} + +/** + * @tc.name: LockCloudContainer001 + * @tc.desc: Test LockCloudContainer when CheckAccess fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, LockCloudContainer001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + + auto result = service.LockCloudContainer(param); + + EXPECT_EQ(result.first, RDB_ERROR); + EXPECT_EQ(result.second, 0); +} + +/** + * @tc.name: LockCloudContainer002 + * @tc.desc: Test LockCloudContainer when CheckAccess succeeds and callback updates the result. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, LockCloudContainer002, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + + auto result = service.LockCloudContainer(param); + + // Simulate callback execution + EXPECT_EQ(result.first, RDB_ERROR); + EXPECT_EQ(result.second, 0); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: UnlockCloudContainer001 + * @tc.desc: Test UnlockCloudContainer when CheckAccess fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, UnlockCloudContainer001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + + int32_t result = service.UnlockCloudContainer(param); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: UnlockCloudContainer002 + * @tc.desc: Test UnlockCloudContainer when CheckAccess succeeds and callback updates the result. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, UnlockCloudContainer002, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + + int32_t result = service.UnlockCloudContainer(param); + + // Simulate callback execution + EXPECT_EQ(result, RDB_ERROR); // Assuming the callback sets status to RDB_OK + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: GetDebugInfo001 + * @tc.desc: Test GetDebugInfo when CheckAccess fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, GetDebugInfo001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + std::map debugInfo; + + int32_t result = service.GetDebugInfo(param, debugInfo); + + EXPECT_EQ(result, RDB_ERROR); + EXPECT_TRUE(debugInfo.empty()); +} + +/** + * @tc.name: GetDebugInfo002 + * @tc.desc: Test GetDebugInfo when CheckAccess pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, GetDebugInfo002, TestSize.Level0) +{ + auto meta = metaData_; + DistributedData::StoreDebugInfo debugMeta; + DistributedData::StoreDebugInfo::FileInfo fileInfo1; + fileInfo1.inode = 4; + fileInfo1.size = 5; + fileInfo1.dev = 6; + fileInfo1.mode = 7; + fileInfo1.uid = 8; + fileInfo1.gid = 9; + debugMeta.fileInfos.insert(std::pair{ "test1", fileInfo1 }); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetDebugInfoKey(), debugMeta, true), true); + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.type_ = metaData_.storeType; + param.level_ = metaData_.securityLevel; + param.area_ = metaData_.area; + param.hapName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + param.isEncrypt_ = metaData_.isEncrypt; + param.isSearchable_ = metaData_.isSearchable; + param.haMode_ = metaData_.haMode; + param.asyncDownloadAsset_ = metaData_.asyncDownloadAsset; + param.user_ = metaData_.user; + param.customDir_ = "../../../base/haps/entry/files/.backup/textautofill"; + std::map debugInfo; + int32_t result = service.GetDebugInfo(param, debugInfo); + EXPECT_EQ(result, RDB_OK); + RdbDebugInfo rdbInfo = debugInfo["test1"]; + EXPECT_EQ(rdbInfo.inode_, 4); + EXPECT_EQ(rdbInfo.size_, 5); + EXPECT_EQ(rdbInfo.dev_, 6); + EXPECT_EQ(rdbInfo.mode_, 7); + EXPECT_EQ(rdbInfo.uid_, 8); + EXPECT_EQ(rdbInfo.gid_, 9); + EXPECT_EQ(debugInfo.size(), 1); + MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); + MetaDataManager::GetInstance().DelMeta(meta.GetDebugInfoKey(), true); +} + +/** + * @tc.name: VerifyPromiseInfo001 + * @tc.desc: Test VerifyPromiseInfo when LoadMeta fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, VerifyPromiseInfo001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: VerifyPromiseInfo002 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, VerifyPromiseInfo002, TestSize.Level0) +{ + StoreMetaDataLocal localMeta; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {tokenId}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {}; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.type_ = metaData_.storeType; + param.level_ = metaData_.securityLevel; + param.area_ = metaData_.area; + param.hapName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + param.isEncrypt_ = metaData_.isEncrypt; + param.isSearchable_ = metaData_.isSearchable; + param.haMode_ = metaData_.haMode; + param.asyncDownloadAsset_ = metaData_.asyncDownloadAsset; + param.user_ = metaData_.user; + + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_OK); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} + +/** + * @tc.name: VerifyPromiseInfo003 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, VerifyPromiseInfo003, TestSize.Level0) +{ + StoreMetaDataLocal localMeta; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {tokenId}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {}; + metaData_.dataDir = "path"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + StoreMetaMapping storeMetaMapping(metaData_); + storeMetaMapping.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData_) + "/" + TEST_STORE; + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.type_ = metaData_.storeType; + param.level_ = metaData_.securityLevel; + param.area_ = metaData_.area; + param.hapName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + param.isEncrypt_ = metaData_.isEncrypt; + param.isSearchable_ = metaData_.isSearchable; + param.haMode_ = metaData_.haMode; + param.asyncDownloadAsset_ = metaData_.asyncDownloadAsset; + param.user_ = metaData_.user; + int32_t result = service.VerifyPromiseInfo(param); + EXPECT_EQ(result, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} + +/** + * @tc.name: CheckParam001 + * @tc.desc: Test VerifyPromiseInfo when bundleName_ contain '/'. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, CheckParam001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = "test/test"; + param.hapName_ = "test"; + param.storeName_ = "test"; + param.user_ = "test"; + param.customDir_ = "test"; + + bool result = service.IsValidParam(param); + + EXPECT_EQ(result, false); + param.bundleName_ = ".."; + + result = service.IsValidParam(param); + + EXPECT_EQ(result, false); + + param.bundleName_ = "test\\..test"; + + result = service.IsValidParam(param); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: CheckParam002 + * @tc.desc: Test VerifyPromiseInfo when hapName_ contain '/'. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, CheckParam002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = "test"; + param.hapName_ = "test/test"; + param.storeName_ = "test"; + param.user_ = "test"; + param.customDir_ = "test"; + + bool result = service.IsValidParam(param); + + EXPECT_EQ(result, false); + param.hapName_ = ".."; + + result = service.IsValidParam(param); + + EXPECT_EQ(result, false); + + param.hapName_ = "test\\..test"; + + result = service.IsValidParam(param); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: CheckParam003 + * @tc.desc: Test CheckParam when user_ contain '/'. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, CheckParam003, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = "test"; + param.hapName_ = "test"; + param.storeName_ = "test"; + param.user_ = "test/test"; + param.customDir_ = "test"; + + bool result = service.IsValidParam(param); + + EXPECT_EQ(result, false); + + param.user_ = ".."; + + result = service.IsValidParam(param); + + EXPECT_EQ(result, false); + param.user_ = "test\\..test"; + + result = service.IsValidParam(param); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: CheckParam004 + * @tc.desc: Test CheckParam. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, CheckParam004, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = "test"; + param.hapName_ = "test"; + param.storeName_ = "test"; + param.user_ = "test"; + param.customDir_ = "test"; + + bool result = service.IsValidParam(param); + + EXPECT_EQ(result, true); +} + +/** + * @tc.name: CheckParam005 + * @tc.desc: Test VerifyPromiseInfo when storename contain '/'. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, CheckParam005, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = "test"; + param.hapName_ = "test"; + param.storeName_ = "test/test"; + param.user_ = "test"; + param.customDir_ = "test"; + + bool result = service.IsValidParam(param); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: CheckParam006 + * @tc.desc: Test VerifyPromiseInfo when customDir is invalid. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, CheckParam006, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = "test"; + param.hapName_ = "test"; + param.storeName_ = "test"; + param.user_ = "test"; + param.customDir_ = "test/../../test/../../../"; + bool result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/../test/../../../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/../../../test/../../../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/./../../test/../../../../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/.../../../test/../../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); + + param.customDir_ = "test/test/../../../test/test/../test/../../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); + + param.customDir_ = "test/test/../../../../../test/test/test/"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = ""; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); + + param.customDir_ = "/test"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test//////////////////..///////../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); + + param.customDir_ = "test/..//////////////////..///////../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/..//////////////////..///////../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/..////./././///////////..///////../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/..////./././//////////////////../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); +} + +/** + * @tc.name: CheckParam007 + * @tc.desc: Test VerifyPromiseInfo when customDir is invalid and hapname is empty. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, CheckParam007, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = "test"; + param.hapName_ = ""; + param.storeName_ = "test"; + param.user_ = "test"; + param.customDir_ = "test/../../test/../../../"; + bool result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/../test/../../../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/../../../test/../../../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/../../../test/../../../../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/.../../test/../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); + + param.customDir_ = "test/test/../../../test/test/../test/../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); + + param.customDir_ = "test/test/../../../../../test/test/test/"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = ""; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); + + param.customDir_ = "/test"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test//////////////////..///////../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); + + param.customDir_ = "test/..//////////////////..///////../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/..//////////////////..///////../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/..////./././///////////..///////../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/..////./././///////////////////../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); +} + +/** + * @tc.name: Delete_001 + * @tc.desc: Test Delete when param is invalid. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, Delete_001, TestSize.Level1) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = ""; + auto errCode = service.Delete(param); + EXPECT_EQ(errCode, RDB_ERROR); + param.bundleName_ = "bundleName"; + param.storeName_ = "storeName"; + param.user_ = "0"; + errCode = service.Delete(param); + EXPECT_EQ(errCode, RDB_OK); +} + +/** + * @tc.name: Delete_002 + * @tc.desc: Test Delete_002. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, Delete_002, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + metaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaMapping.user = "0"; + metaMapping.bundleName = "bundleName"; + metaMapping.storeId = "storeName"; + metaMapping.instanceId = 1; + + StoreMetaData meta1; + meta1.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta1.user = "0"; + meta1.bundleName = "bundleName"; + meta1.storeId = "storeName"; + meta1.dataDir = DirectoryManager::GetInstance().GetStorePath(meta1) + "/" + metaMapping.storeId; + meta1.instanceId = 1; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + + metaMapping.cloudPath = meta1.dataDir; + metaMapping.devicePath = meta1.dataDir; + metaMapping.searchPath = meta1.dataDir; + metaMapping.dataDir = meta1.dataDir; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + StoreMetaData meta2; + meta2.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta2.user = "0"; + meta2.bundleName = "bundleName"; + meta2.storeId = "storeName"; + meta2.dataDir ="path2"; + meta2.instanceId = 1; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta2.GetKey(), meta2, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaMapping.bundleName; + param.storeName_ = metaMapping.storeId; + param.user_ = metaMapping.user; + auto errCode = service.Delete(param); + EXPECT_EQ(errCode, RDB_OK); + MetaDataManager::GetInstance().LoadMeta(metaMapping.GetKey(), metaMapping, true); + EXPECT_EQ(metaMapping.cloudPath, ""); + EXPECT_EQ(metaMapping.devicePath, ""); + EXPECT_EQ(metaMapping.searchPath, ""); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta2.GetKey(), true), true); +} + +/** + * @tc.name: Delete_003 + * @tc.desc: Test Delete_003. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, Delete_003, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + metaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaMapping.user = "0"; + metaMapping.bundleName = "bundleName"; + metaMapping.storeId = "storeName"; + + StoreMetaData meta1; + meta1.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta1.user = "0"; + meta1.bundleName = "bundleName"; + meta1.storeId = "storeName"; + meta1.dataDir = DirectoryManager::GetInstance().GetStorePath(meta1) + "/" + metaMapping.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + + metaMapping.cloudPath = "path2"; + metaMapping.devicePath = "path2"; + metaMapping.searchPath = "path2"; + metaMapping.dataDir = meta1.dataDir; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + StoreMetaData meta2; + meta2.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta2.user = "0"; + meta2.bundleName = "bundleName"; + meta2.storeId = "storeName"; + meta2.dataDir ="path2"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta2.GetKey(), meta2, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaMapping.bundleName; + param.storeName_ = metaMapping.storeId; + param.user_ = metaMapping.user; + auto errCode = service.Delete(param); + EXPECT_EQ(errCode, RDB_OK); + MetaDataManager::GetInstance().LoadMeta(metaMapping.GetKey(), metaMapping, true); + EXPECT_EQ(metaMapping.cloudPath, "path2"); + EXPECT_EQ(metaMapping.devicePath, "path2"); + EXPECT_EQ(metaMapping.searchPath, "path2"); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta2.GetKey(), true), true); +} + +/** + * @tc.name: Delete_004 + * @tc.desc: Test Delete_004. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, Delete_004, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + metaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaMapping.user = "0"; + metaMapping.bundleName = "bundleName"; + metaMapping.storeId = "storeName"; + metaMapping.instanceId = 1; + + StoreMetaData meta1; + meta1.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta1.user = "0"; + meta1.bundleName = "bundleName"; + meta1.storeId = "storeName"; + meta1.dataDir = "path1"; + meta1.instanceId = 1; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + + metaMapping.cloudPath = "path2"; + metaMapping.devicePath = "path2"; + metaMapping.searchPath = "path2"; + metaMapping.dataDir = DirectoryManager::GetInstance().GetStorePath(meta1) + "/" + metaMapping.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaMapping.bundleName; + param.storeName_ = metaMapping.storeId; + param.user_ = metaMapping.user; + auto errCode = service.Delete(param); + EXPECT_EQ(errCode, RDB_OK); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); +} + +/** + * @tc.name: RegisterEvent_001 + * @tc.desc: Test RegisterEvent_001. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, RegisterEvent_001, TestSize.Level1) +{ + RdbServiceImpl service; + DistributedData::StoreInfo storeInfo; + storeInfo.bundleName = "RegisterEvent_bundleName"; + storeInfo.storeName = "RegisterEvent_storeName"; + storeInfo.user = 100; + storeInfo.path = "RegisterEvent_path"; + auto event = std::make_unique(CloudEvent::CLOUD_SYNC, storeInfo); + EXPECT_NE(event, nullptr); + auto result = EventCenter::GetInstance().PostEvent(move(event)); + EXPECT_EQ(result, 1); // CODE_SYNC +} + +/** + * @tc.name: RegisterEvent_002 + * @tc.desc: Test RegisterEvent_002. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, RegisterEvent_002, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + InitMapping(metaMapping); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + RdbServiceImpl service; + DistributedData::StoreInfo storeInfo; + storeInfo.bundleName = "bundleName"; + storeInfo.storeName = "storeName"; + storeInfo.user = 100; + storeInfo.path = "path"; + auto event = std::make_unique(CloudEvent::CLOUD_SYNC, storeInfo); + EXPECT_NE(event, nullptr); + auto result = EventCenter::GetInstance().PostEvent(move(event)); + EXPECT_EQ(result, 1); // CODE_SYNC + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); +} + + +/** + * @tc.name: RegisterEvent_003 + * @tc.desc: Test RegisterEvent_003. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, RegisterEvent_003, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + InitMapping(metaMapping); + metaMapping.cloudPath ="path1"; + metaMapping.dataDir ="path"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + StoreMetaData meta; + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta.user = "100"; + meta.bundleName = "bundleName"; + meta.storeId = "storeName"; + meta.dataDir ="path1"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + RdbServiceImpl service; + DistributedData::StoreInfo storeInfo; + storeInfo.bundleName = "bundleName"; + storeInfo.storeName = "storeName"; + storeInfo.user = 100; + storeInfo.path = "path"; + auto event = std::make_unique(CloudEvent::CLOUD_SYNC, storeInfo); + EXPECT_NE(event, nullptr); + auto result = EventCenter::GetInstance().PostEvent(move(event)); + EXPECT_EQ(result, 1); // CODE_SYNC + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); +} + +/** + * @tc.name: RegisterEvent_004 + * @tc.desc: Test RegisterEvent_005. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, RegisterEvent_004, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + InitMapping(metaMapping); + metaMapping.cloudPath ="path"; + metaMapping.dataDir ="path"; + metaMapping.storeType = StoreMetaData::STORE_KV_BEGIN; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + RdbServiceImpl service; + DistributedData::StoreInfo storeInfo; + storeInfo.bundleName = "bundleName"; + storeInfo.storeName = "storeName"; + storeInfo.user = 100; + storeInfo.path = "path"; + auto event = std::make_unique(CloudEvent::CLOUD_SYNC, storeInfo); + EXPECT_NE(event, nullptr); + auto result = EventCenter::GetInstance().PostEvent(move(event)); + EXPECT_EQ(result, 1); // CODE_SYNC + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); +} + +/** + * @tc.name: RegisterEvent_005 + * @tc.desc: Test RegisterEvent_005 + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, RegisterEvent_005, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + InitMapping(metaMapping); + metaMapping.cloudPath ="path"; + metaMapping.dataDir ="path"; + metaMapping.storeType = StoreMetaData::STORE_OBJECT_BEGIN; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + RdbServiceImpl service; + DistributedData::StoreInfo storeInfo; + storeInfo.bundleName = "bundleName"; + storeInfo.storeName = "storeName"; + storeInfo.user = 100; + storeInfo.path = "path"; + auto event = std::make_unique(CloudEvent::CLOUD_SYNC, storeInfo); + EXPECT_NE(event, nullptr); + auto result = EventCenter::GetInstance().PostEvent(move(event)); + EXPECT_EQ(result, 1); // CODE_SYNC + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); +} + +/** + * @tc.name: RegisterEvent_006 + * @tc.desc: Test RegisterEvent_006 + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, RegisterEvent_006, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + InitMapping(metaMapping); + metaMapping.cloudPath ="path1"; + metaMapping.dataDir ="path"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + RdbServiceImpl service; + DistributedData::StoreInfo storeInfo; + storeInfo.bundleName = "bundleName"; + storeInfo.storeName = "storeName"; + storeInfo.user = 100; + storeInfo.path = "path"; + auto event = std::make_unique(CloudEvent::CLOUD_SYNC, storeInfo); + EXPECT_NE(event, nullptr); + auto result = EventCenter::GetInstance().PostEvent(move(event)); + EXPECT_EQ(result, 1); // CODE_SYNC + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); +} + +/** + * @tc.name: QuerySharingResource_PermissionDenied_001 + * @tc.desc: Test QuerySharingResource returns RDB_ERROR when CheckAccess fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, QuerySharingResource_PermissionDenied_001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + // param.bundleName_ and param.storeName_ left empty to trigger CheckAccess failure + PredicatesMemo predicates; + predicates.tables_ = {"table1"}; + std::vector columns = {"col1", "col2"}; + + auto result = service.QuerySharingResource(param, predicates, columns); + EXPECT_EQ(result.first, RDB_ERROR); + EXPECT_EQ(result.second, nullptr); +} + +/** + * @tc.name: QuerySharingResource_PermissionDenied_002 + * @tc.desc: Test QuerySharingResource returns RDB_ERROR when not system app. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, QuerySharingResource_PermissionDenied_002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + PredicatesMemo predicates; + predicates.tables_ = {"table1"}; + std::vector columns = {"col1", "col2"}; + + auto result = service.QuerySharingResource(param, predicates, columns); + EXPECT_EQ(result.first, RDB_ERROR); + EXPECT_EQ(result.second, nullptr); +} + +/** + * @tc.name: SaveSecretKeyMeta_CloneKeyUpdate_001 + * @tc.desc: Test SaveSecretKeyMeta updates clone secret key when area < 0 or nonce is empty. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, SaveSecretKeyMeta_CloneKeyUpdate_001, TestSize.Level0) +{ + // Prepare metaData and secret key + auto meta = metaData_; + meta.isEncrypt = true; + std::vector password = Random(KEY_LENGTH); + + // Prepare cloneKey with area < 0 and empty nonce + SecretKeyMetaData cloneKey; + CryptoManager::CryptoParams params; + cloneKey.sKey = CryptoManager::GetInstance().Encrypt(password, params); + cloneKey.area = -1; + cloneKey.nonce.clear(); + cloneKey.storeType = meta.storeType; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetCloneSecretKey(), cloneKey, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + + // Call SaveSecretKeyMeta, should trigger UpdateSecretMeta for cloneKey + RdbServiceImpl service; + service.SaveSecretKeyMeta(meta, password); + + // Clean up + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetCloneSecretKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); +} + +/** + * @tc.name: SaveSecretKeyMeta_CloneKeyUpdate_EmptySKey_002 + * @tc.desc: Test SaveSecretKeyMeta does not update clone secret key if sKey is empty. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, SaveSecretKeyMeta_CloneKeyUpdate_EmptySKey_002, TestSize.Level0) +{ + auto meta = metaData_; + meta.isEncrypt = true; + std::vector password = Random(KEY_LENGTH); + + // Prepare cloneKey with empty sKey + SecretKeyMetaData cloneKey; + cloneKey.sKey.clear(); + cloneKey.area = -1; + cloneKey.nonce.clear(); + cloneKey.storeType = meta.storeType; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetCloneSecretKey(), cloneKey, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + + RdbServiceImpl service; + service.SaveSecretKeyMeta(meta, password); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetCloneSecretKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); +} + +/** + * @tc.name: SaveSecretKeyMeta_CloneKeyUpdate_NoUpdate_003 + * @tc.desc: Test SaveSecretKeyMeta does not update clone secret key if area >= 0 and nonce not empty. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, SaveSecretKeyMeta_CloneKeyUpdate_NoUpdate_003, TestSize.Level0) +{ + auto meta = metaData_; + meta.isEncrypt = true; + std::vector password = Random(KEY_LENGTH); + + // Prepare cloneKey with area >= 0 and nonce not empty + SecretKeyMetaData cloneKey; + CryptoManager::CryptoParams params; + cloneKey.sKey = CryptoManager::GetInstance().Encrypt(password, params); + cloneKey.area = 1; + cloneKey.nonce = { 1, 2, 3, 4 }; + cloneKey.storeType = meta.storeType; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetCloneSecretKey(), cloneKey, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + + RdbServiceImpl service; + service.SaveSecretKeyMeta(meta, password); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetCloneSecretKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); +} +} // namespace DistributedRDBTest +} // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_service_impl_token_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_service_impl_token_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4a49356a4483d43ced32543b8fe80dae36e75291 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_service_impl_token_test.cpp @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2025 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/account_delegate.h" +#include "rdb_service_impl.h" +#include "ipc_skeleton.h" +#include "gmock/gmock.h" +#include "mock/access_token_mock.h" +#include "bootstrap.h" +#include "checker_mock.h" +#include "crypto/crypto_manager.h" +#include "device_manager_adapter.h" +#include "device_matrix.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 "rdb_types.h" +#include "relational_store_manager.h" +#include "gtest/gtest.h" +#include "directory/directory_manager.h" +using namespace OHOS::DistributedRdb; +using namespace OHOS::DistributedData; +using namespace DistributedDB; +using namespace OHOS::Security::AccessToken; +using namespace testing::ext; +using namespace testing; +using namespace std; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; + +namespace OHOS::Test { +namespace DistributedRDBTest { + +static constexpr const char *TEST_BUNDLE = "test_rdb_service_impl_bundleName"; +static constexpr const char *TEST_APPID = "test_rdb_service_impl_appid"; +static constexpr const char *TEST_STORE = "test_rdb_service_impl_store"; + +class RdbServiceImplTokenTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + static void InitMetaData(); + void SetUp(); + void TearDown(); +protected: + static inline std::shared_ptr accTokenMock = nullptr; + static std::shared_ptr dbStoreMock_; + static StoreMetaData metaData_; + static CheckerMock checkerMock_; + static void InitMetaDataManager(); + static void GetRdbSyncerParam(RdbSyncerParam ¶m); +}; +std::shared_ptr RdbServiceImplTokenTest::dbStoreMock_ = std::make_shared(); +StoreMetaData RdbServiceImplTokenTest::metaData_; +CheckerMock RdbServiceImplTokenTest::checkerMock_; + + +void RdbServiceImplTokenTest::InitMetaData() +{ + metaData_.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData_.appId = TEST_APPID; + metaData_.bundleName = TEST_BUNDLE; + metaData_.tokenId = OHOS::IPCSkeleton::GetCallingTokenID(); + metaData_.user = std::to_string(AccountDelegate::GetInstance()->GetUserByToken(metaData_.tokenId)); + metaData_.area = OHOS::DistributedKv::EL1; + metaData_.instanceId = -1; + metaData_.isAutoSync = true; + metaData_.storeType = DistributedRdb::RDB_DEVICE_COLLABORATION; + metaData_.storeId = TEST_STORE; + metaData_.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData_) + "/" + TEST_STORE; +} + +void RdbServiceImplTokenTest::InitMetaDataManager() +{ + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + MetaDataManager::GetInstance().SetSyncer([](const auto &, auto) { + DeviceMatrix::GetInstance().OnChanged(DeviceMatrix::META_STORE_MASK); + }); +} + +void RdbServiceImplTokenTest::SetUpTestCase() +{ + accTokenMock = std::make_shared(); + BAccessTokenKit::accessTokenkit = accTokenMock; + size_t max = 12; + size_t min = 5; + auto dmExecutor = std::make_shared(max, min); + DeviceManagerAdapter::GetInstance().Init(dmExecutor); + InitMetaData(); + Bootstrap::GetInstance().LoadCheckers(); + CryptoManager::GetInstance().GenerateRootKey(); +} + +void RdbServiceImplTokenTest::TearDownTestCase() +{ + accTokenMock = nullptr; + BAccessTokenKit::accessTokenkit = nullptr; +} + +void RdbServiceImplTokenTest::SetUp() +{ +} + +void RdbServiceImplTokenTest::TearDown() +{ +} + +void RdbServiceImplTokenTest::GetRdbSyncerParam(RdbSyncerParam ¶m) +{ + param.bundleName_ = metaData_.bundleName; + param.type_ = metaData_.storeType; + param.level_ = metaData_.securityLevel; + param.area_ = metaData_.area; + param.hapName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + param.isEncrypt_ = metaData_.isEncrypt; + param.isSearchable_ = metaData_.isSearchable; + param.haMode_ = metaData_.haMode; + param.asyncDownloadAsset_ = metaData_.asyncDownloadAsset; + param.user_ = metaData_.user; +} + +/** + * @tc.name: VerifyPromiseInfo001 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTokenTest, VerifyPromiseInfo001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: VerifyPromiseInfo002 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTokenTest, VerifyPromiseInfo002, TestSize.Level0) +{ + InitMetaDataManager(); + StoreMetaDataLocal localMeta; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {tokenId}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {}; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + EXPECT_CALL(*accTokenMock, GetTokenType(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_INVALID)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_INVALID)); + RdbServiceImpl service; + RdbSyncerParam param; + GetRdbSyncerParam(param); + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} + +/** + * @tc.name: VerifyPromiseInfo003 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTokenTest, VerifyPromiseInfo003, TestSize.Level0) +{ + StoreMetaDataLocal localMeta; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {tokenId}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {}; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + EXPECT_CALL(*accTokenMock, GetTokenType(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_SHELL)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_SHELL)); + RdbServiceImpl service; + RdbSyncerParam param; + GetRdbSyncerParam(param); + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_OK); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} + +/** + * @tc.name: VerifyPromiseInfo004 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTokenTest, VerifyPromiseInfo004, TestSize.Level0) +{ + StoreMetaDataLocal localMeta; + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {}; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + EXPECT_CALL(*accTokenMock, GetTokenType(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_SHELL)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_SHELL)); + RdbServiceImpl service; + RdbSyncerParam param; + GetRdbSyncerParam(param); + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} + +/** + * @tc.name: VerifyPromiseInfo005 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTokenTest, VerifyPromiseInfo005, TestSize.Level0) +{ + StoreMetaDataLocal localMeta; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {tokenId}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {}; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + EXPECT_CALL(*accTokenMock, GetTokenType(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); + RdbServiceImpl service; + RdbSyncerParam param; + GetRdbSyncerParam(param); + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_OK); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} + +/** + * @tc.name: VerifyPromiseInfo006 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTokenTest, VerifyPromiseInfo006, TestSize.Level0) +{ + StoreMetaDataLocal localMeta; + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {}; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + EXPECT_CALL(*accTokenMock, GetTokenType(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); + RdbServiceImpl service; + RdbSyncerParam param; + GetRdbSyncerParam(param); + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} +/** + * @tc.name: VerifyPromiseInfo007 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTokenTest, VerifyPromiseInfo007, TestSize.Level0) +{ + StoreMetaDataLocal localMeta; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {tokenId}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {}; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + EXPECT_CALL(*accTokenMock, GetTokenType(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); + RdbServiceImpl service; + RdbSyncerParam param; + GetRdbSyncerParam(param); + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} + +/** + * @tc.name: VerifyPromiseInfo008 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTokenTest, VerifyPromiseInfo008, TestSize.Level0) +{ + StoreMetaDataLocal localMeta; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {tokenId}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {TEST_BUNDLE}; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + EXPECT_CALL(*accTokenMock, GetTokenType(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); + RdbServiceImpl service; + RdbSyncerParam param; + GetRdbSyncerParam(param); + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_OK); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} +} // namespace DistributedRDBTest +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/app.json b/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/app.json new file mode 100644 index 0000000000000000000000000000000000000000..3bbd52d9937fa31936884fe5bf0cf388ca8a970a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/app.json @@ -0,0 +1,13 @@ +{ + "app": { + "bundleName": "com.example.testCloud", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name", + "distributedNotificationEnabled": true, + "minAPIVersion": 9, + "targetAPIVersion": 9 + } +} diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/resources/base/element/string.json b/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..771eddc83c25bfc4545e549e8a5a7c350f8a5a2b --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "Extension" + } + ] +} diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/resources/base/media/app_icon.png b/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/resources/base/media/app_icon.png differ diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/testCloud/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..db1355d58ddfb37cbde8928aa48dfb5ec9cdf1c0 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/BUILD.gn @@ -0,0 +1,44 @@ +# Copyright (c) 2025 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") + +ohos_hap("testCloud") { + hap_profile = "entry/src/main/module.json" + hap_name = "testCloud" + subsystem_name = "distributeddatamgr" + part_name = "datamgr_service" + final_hap_path = "$root_out_dir/tests/unittest/datamgr_service/datamgr_service/resource/${hap_name}.hap" + testonly = true + deps = [ + ":testCloud_ets_assets", + ":testCloud_ets_resources", + ] + certificate_profile = "signature/openharmony_sx.p7b" +} + +ohos_js_assets("testCloud_ets_assets") { + source_dir = "entry/src/main/ets" + hap_profile = "entry/src/main/module.json" +} + +ohos_app_scope("testCloud_app_profile") { + app_profile = "AppScope/app.json" + sources = [ "AppScope/resources" ] +} + +ohos_resources("testCloud_ets_resources") { + sources = [ "entry/src/main/resources" ] + deps = [ ":testCloud_app_profile" ] + hap_profile = "entry/src/main/module.json" +} diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/ets/Application/MyAbilityStage.ts b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/ets/Application/MyAbilityStage.ts new file mode 100644 index 0000000000000000000000000000000000000000..19d67bae85fa2bd4f42362759c98a97718c6195e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/ets/Application/MyAbilityStage.ts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 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 AbilityStage from "@ohos.application.AbilityStage" + +export default class MyAbilityStage extends AbilityStage { + onCreate() { + console.log("[Demo] MyAbilityStage onCreate") + } +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/ets/MainAbility/MainAbility.ts b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/ets/MainAbility/MainAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..f1a7bf8fb1af00b5bd000c714f06b6c0d692325c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/ets/MainAbility/MainAbility.ts @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025 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 Ability from '@ohos.application.Ability' + +export default class MainAbility extends Ability { + onCreate(want, launchParam) { + console.log("[Demo] MainAbility onCreate") + globalThis.abilityWant = want; + } + + onDestroy() { + console.log("[Demo] MainAbility onDestroy") + } + + onWindowStageCreate(windowStage) { + // Main window is created, set main page for this ability + console.log("[Demo] MainAbility onWindowStageCreate") + + windowStage.loadContent("pages/index", (err, data) => { + if (err.code) { + console.error('Failed to load the content. Cause:' + JSON.stringify(err)); + return; + } + console.info('Succeeded in loading the content. Data: ' + JSON.stringify(data)) + }); + } + + onWindowStageDestroy() { + // Main window is destroyed, release UI related resources + console.log("[Demo] MainAbility onWindowStageDestroy") + } + + onForeground() { + // Ability has brought to foreground + console.log("[Demo] MainAbility onForeground") + } + + onBackground() { + // Ability has back to background + console.log("[Demo] MainAbility onBackground") + } +}; diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/ets/pages/index.ets b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/ets/pages/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..33bf2fafb560ca599e45b0dd7e4b52a98dea65fd --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/ets/pages/index.ets @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 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. + */ + +@Entry +@Component +struct Index { + @State message: string = 'StartAbility Success' + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(30) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/module.json b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/module.json new file mode 100644 index 0000000000000000000000000000000000000000..352fc3e154f7b5138f86186ea2a3a01fd68b8ba6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/module.json @@ -0,0 +1,40 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "srcEntrance": "./ets/Application/MyAbilityStage.ts", + "description": "$string:entry_desc", + "mainElement": "MainAbility", + "deviceTypes": [ + "default", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "uiSyntax": "ets", + "abilities": [ + { + "name": "MainAbility", + "srcEntrance": "./ets/MainAbility/MainAbility.ts", + "description": "$string:MainAbility_desc", + "icon": "$media:icon", + "label": "$string:MainAbility_label", + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:white", + "visible": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ] + } +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/element/color.json b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..1bbc9aa9617e97c45440e1d3d66afc1154837012 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "white", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/element/string.json b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..496f24f73704a62e0100d427ad898950983a99d4 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "entry_desc", + "value": "testCloud" + }, + { + "name": "MainAbility_desc", + "value": "testCloud" + }, + { + "name": "MainAbility_label", + "value": "testCloud" + } + ] +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/media/icon.png b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/media/icon.png differ diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/profile/main_pages.json b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..feec276e105eeb8d621c20aaf838f318b0a94150 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/index" + ] +} diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/rawfile/arkdata/cloud/cloud_schema.json b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/rawfile/arkdata/cloud/cloud_schema.json new file mode 100644 index 0000000000000000000000000000000000000000..97cc6153dab2d3a6cd7bdf32be0402553fecfddc --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/rawfile/arkdata/cloud/cloud_schema.json @@ -0,0 +1,6 @@ +{ + "bundleName": "com.example.testCloud", + "databases": [], + "metaVersion": 65536, + "version": 101 +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/signature/openharmony_sx.p7b b/datamgr_service/services/distributeddataservice/service/test/testCloud/signature/openharmony_sx.p7b new file mode 100644 index 0000000000000000000000000000000000000000..fd0a3916af7bc804ad185d9794693c17d641f487 Binary files /dev/null and b/datamgr_service/services/distributeddataservice/service/test/testCloud/signature/openharmony_sx.p7b differ diff --git a/datamgr_service/services/distributeddataservice/service/test/udmf_db_corruption_mock_test.cpp b/datamgr_service/services/distributeddataservice/service/test/udmf_db_corruption_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ad072531799d86f28f1d702b6543a906b830fc2 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/udmf_db_corruption_mock_test.cpp @@ -0,0 +1,387 @@ +/* +* Copyright (c) 2025 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 "udmf_service_impl.h" + +#include "accesstoken_kit.h" +#include "bootstrap.h" +#include "device_manager_adapter.h" +#include "executor_pool.h" +#include "gtest/gtest.h" +#include "ipc_skeleton.h" +#include "kvstore_meta_manager.h" +#include "metadata/meta_data_manager.h" +#include "nativetoken_kit.h" +#include "preprocess_utils.h" +#include "runtime_store.h" +#include "text.h" +#include "token_setproc.h" +#include "runtime_store.h" +#include "gtest/gtest.h" +#include "kv_store_nb_delegate_corruption_mock.h" +#include "account/account_delegate.h" + +using namespace OHOS::UDMF; +using namespace testing::ext; +using namespace testing; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; +namespace OHOS::Test { +namespace DistributedDataTest { +constexpr const char *DATA_HUB_INTENTION = "DataHub"; +class UdmfServiceImplDbCorruptionMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +static void GrantPermissionNative() +{ + const char **perms = new const char *[3]; + perms[0] = "ohos.permission.DISTRIBUTED_DATASYNC"; + perms[1] = "ohos.permission.ACCESS_SERVICE_DM"; + perms[2] = "ohos.permission.MONITOR_DEVICE_NETWORK_STATE"; // perms[2] is a permission parameter + TokenInfoParams infoInstance = { + .dcapsNum = 0, + .permsNum = 3, + .aclsNum = 0, + .dcaps = nullptr, + .perms = perms, + .acls = nullptr, + .processName = "distributed_data_test", + .aplStr = "system_basic", + }; + uint64_t tokenId = GetAccessTokenId(&infoInstance); + SetSelfTokenID(tokenId); + AccessTokenKit::ReloadNativeTokenInfo(); + delete[] perms; +} + +void UdmfServiceImplDbCorruptionMockTest::SetUpTestCase(void) +{ + GrantPermissionNative(); + DistributedData::Bootstrap::GetInstance().LoadComponents(); + DistributedData::Bootstrap::GetInstance().LoadDirectory(); + DistributedData::Bootstrap::GetInstance().LoadCheckers(); + size_t max = 2; + size_t min = 1; + auto executors = std::make_shared(max, min); + DmAdapter::GetInstance().Init(executors); + DistributedKv::KvStoreMetaManager::GetInstance().BindExecutor(executors); + DistributedKv::KvStoreMetaManager::GetInstance().InitMetaParameter(); + DistributedKv::KvStoreMetaManager::GetInstance().InitMetaListener(); +} + +/** +* @tc.name: SaveDataTest001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, SaveDataTest001, TestSize.Level1) +{ + StoreCache::GetInstance().stores_.Clear(); + std::string key = DATA_HUB_INTENTION; + auto store = std::make_shared(key); + store->kvStore_ = std::make_shared(); + int foregroundUserId = 0; + DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + key.append(std::to_string(foregroundUserId)); + StoreCache::GetInstance().stores_.InsertOrAssign(key, store); + CustomOption option; + option.intention = Intention::UD_INTENTION_DATA_HUB; + option.tokenId = 1; + auto record = std::make_shared(); + UnifiedData data; + data.AddRecord(record); + std::string key1 = "key"; + UdmfServiceImpl serviceImpl; + auto status = serviceImpl.SaveData(option, data, key1); + EXPECT_EQ(status, OHOS::UDMF::E_DB_ERROR); +} + +/** +* @tc.name: RetrieveData001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, RetrieveData001, TestSize.Level1) +{ + StoreCache::GetInstance().stores_.Clear(); + std::string intention = "drag"; + auto store = std::make_shared(intention); + store->kvStore_ = std::make_shared(); + int foregroundUserId = 0; + DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + intention.append(std::to_string(foregroundUserId)); + StoreCache::GetInstance().stores_.InsertOrAssign(intention, store); + std::string key = "udmf://drag/get.example.myapplication/L]WQ=JezoKgDc8\\Rz`q6koADcGRdKMnf"; + QueryOption option = { + .key = key + }; + UnifiedData data; + UdmfServiceImpl serviceImpl; + auto status = serviceImpl.RetrieveData(option, data); + EXPECT_EQ(status, OHOS::UDMF::E_DB_ERROR); +} + +/** +* @tc.name: DeleteData001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, DeleteData001, TestSize.Level1) +{ + StoreCache::GetInstance().stores_.Clear(); + std::string intention = DATA_HUB_INTENTION; + auto store = std::make_shared(intention); + store->kvStore_ = std::make_shared(); + int foregroundUserId = 0; + DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + intention.append(std::to_string(foregroundUserId)); + StoreCache::GetInstance().stores_.InsertOrAssign(intention, store); + std::string key = "udmf://DataHub/delete.example.myapplication/L]WQ=JezoKgDc8\\Rz`q6koADcGRdKMnf"; + QueryOption option = { + .key = key, + }; + auto record = std::make_shared(); + UnifiedData data; + data.AddRecord(record); + std::vector dataList = { data }; + UdmfServiceImpl serviceImpl; + auto status = serviceImpl.DeleteData(option, dataList); + EXPECT_EQ(status, OHOS::UDMF::E_DB_ERROR); +} + +/** +* @tc.name: GetSummary001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, GetSummary001, TestSize.Level1) +{ + StoreCache::GetInstance().stores_.Clear(); + std::string intention = DATA_HUB_INTENTION; + auto store = std::make_shared(intention); + store->kvStore_ = std::make_shared(); + int foregroundUserId = 0; + DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + intention.append(std::to_string(foregroundUserId)); + StoreCache::GetInstance().stores_.InsertOrAssign(intention, store); + std::string key = "udmf://DataHub/summary.example.myapplication/L]WQ=JezoKgDc8\\Rz`q6koADcGRdKMnf"; + QueryOption option = { + .key = key, + }; + Summary summary; + UdmfServiceImpl serviceImpl; + auto status = serviceImpl.GetSummary(option, summary); + EXPECT_EQ(status, OHOS::UDMF::E_DB_ERROR); +} + +/** +* @tc.name: IsRemoteData001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, IsRemoteData001, TestSize.Level1) +{ + StoreCache::GetInstance().stores_.Clear(); + std::string intention = DATA_HUB_INTENTION; + auto store = std::make_shared(intention); + store->kvStore_ = std::make_shared(); + int foregroundUserId = 0; + DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + intention.append(std::to_string(foregroundUserId)); + StoreCache::GetInstance().stores_.InsertOrAssign(intention, store); + std::string key = "udmf://DataHub/remote.example.myapplication/L]WQ=JezoKgDc8\\Rz`q6koADcGRdKMnf"; + QueryOption option = { + .key = key, + }; + UdmfServiceImpl serviceImpl; + bool ret = false; + auto status = serviceImpl.IsRemoteData(option, ret); + EXPECT_EQ(status, OHOS::UDMF::E_DB_ERROR); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: GetAppShareOption001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, GetAppShareOption001, TestSize.Level1) +{ + StoreCache::GetInstance().stores_.Clear(); + std::string intention = DATA_HUB_INTENTION; + auto store = std::make_shared(intention); + store->kvStore_ = std::make_shared(); + int foregroundUserId = 0; + DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + intention.append(std::to_string(foregroundUserId)); + StoreCache::GetInstance().stores_.InsertOrAssign(intention, store); + UdmfServiceImpl serviceImpl; + int32_t shareOption = CROSS_APP; + auto status = serviceImpl.GetAppShareOption("DataHub", shareOption); + EXPECT_EQ(status, OHOS::UDMF::E_DB_ERROR); +} + +/** +* @tc.name: QueryDataCommon001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, QueryDataCommon001, TestSize.Level1) +{ + StoreCache::GetInstance().stores_.Clear(); + std::string intention = DATA_HUB_INTENTION; + auto store = std::make_shared(intention); + store->kvStore_ = std::make_shared(); + int foregroundUserId = 0; + DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + intention.append(std::to_string(foregroundUserId)); + StoreCache::GetInstance().stores_.InsertOrAssign(intention, store); + UdmfServiceImpl serviceImpl; + QueryOption option = { + .intention = Intention::UD_INTENTION_DATA_HUB, + }; + std::vector dataList; + std::shared_ptr store1; + auto status = serviceImpl.QueryDataCommon(option, dataList, store1); + EXPECT_EQ(status, OHOS::UDMF::E_DB_ERROR); +} + +/** +* @tc.name: PutLocal001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, PutLocal001, TestSize.Level1) +{ + std::string key = "key"; + std::string value = "value"; + auto store = std::make_shared(DATA_HUB_INTENTION); + store->kvStore_ = std::make_shared(); + auto status = store->PutLocal(key, value); + EXPECT_EQ(status, OHOS::UDMF::E_DB_CORRUPTED); +} + +/** +* @tc.name: GetLocal001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, GetLocal001, TestSize.Level1) +{ + std::string key = "key"; + std::string value; + auto store = std::make_shared(DATA_HUB_INTENTION); + store->kvStore_ = std::make_shared(); + auto status = store->GetLocal(key, value); + EXPECT_EQ(status, OHOS::UDMF::E_DB_CORRUPTED); +} + +/** +* @tc.name: DeleteLocal001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, DeleteLocal001, TestSize.Level1) +{ + std::string key = "key"; + auto store = std::make_shared(DATA_HUB_INTENTION); + store->kvStore_ = std::make_shared(); + auto status = store->DeleteLocal(key); + EXPECT_EQ(status, OHOS::UDMF::E_DB_CORRUPTED); +} + +/** +* @tc.name: PutRuntime001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, PutRuntime001, TestSize.Level1) +{ + std::string key = "key"; + Runtime runtime; + auto store = std::make_shared(DATA_HUB_INTENTION); + store->kvStore_ = std::make_shared(); + auto status = store->PutRuntime(key, runtime); + EXPECT_EQ(status, OHOS::UDMF::E_DB_CORRUPTED); +} + +/** +* @tc.name: GetRuntime001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, GetRuntime001, TestSize.Level1) +{ + std::string key = "key"; + Runtime runtime; + auto store = std::make_shared(DATA_HUB_INTENTION); + store->kvStore_ = std::make_shared(); + auto status = store->GetRuntime(key, runtime); + EXPECT_EQ(status, OHOS::UDMF::E_DB_CORRUPTED); +} + +/** +* @tc.name: Update001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, Update001, TestSize.Level1) +{ + UnifiedData data; + auto rumtime = std::make_shared(); + UnifiedKey key(DATA_HUB_INTENTION, "com.demo.test", "111"); + rumtime->key = key; + data.runtime_ = rumtime; + auto store = std::make_shared(DATA_HUB_INTENTION); + store->kvStore_ = std::make_shared(); + auto status = store->Update(data); + EXPECT_EQ(status, OHOS::UDMF::E_DB_CORRUPTED); +} + +/** +* @tc.name: Delete001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, Delete001, TestSize.Level1) +{ + std::string key = "key"; + auto store = std::make_shared(DATA_HUB_INTENTION); + store->kvStore_ = std::make_shared(); + auto status = store->Delete(key); + EXPECT_EQ(status, OHOS::UDMF::E_DB_CORRUPTED); +} +}; // namespace DistributedDataTest +}; // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/udmf_preprocess_utils_mock_test.cpp b/datamgr_service/services/distributeddataservice/service/test/udmf_preprocess_utils_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b09a55ffff0a1d66bc7278e188a5cbe2694b028b --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/udmf_preprocess_utils_mock_test.cpp @@ -0,0 +1,132 @@ +/* +* Copyright (c) 2025 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 "preprocess_utils.h" +#include "gtest/gtest.h" +#include "access_token_mock.h" + +namespace OHOS::UDMF { +using namespace testing; +using namespace std; +using namespace testing::ext; +using namespace OHOS::Security::AccessToken; +class UdmfPreProcessUtilsMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp() {} + void TearDown() {} + static inline shared_ptr accessTokenKitMock = nullptr; +}; + +void UdmfPreProcessUtilsMockTest::SetUpTestCase(void) +{ + accessTokenKitMock = make_shared(); + BAccessTokenKit::accessTokenkit = accessTokenKitMock; +} + +void UdmfPreProcessUtilsMockTest::TearDownTestCase(void) +{ + BAccessTokenKit::accessTokenkit = nullptr; + accessTokenKitMock = nullptr; +} + +/** +* @tc.name: GetHapUidByToken001 +* @tc.desc: Abnormal test of GetHapUidByToken, AccessTokenKit GetHapTokenInfo failed +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsMockTest, GetHapUidByToken001, TestSize.Level1) +{ + uint32_t tokenId = 0; + int userId = 0; + PreProcessUtils preProcessUtils; + EXPECT_CALL(*accessTokenKitMock, GetHapTokenInfo(_, _)).WillOnce(Return(RET_SUCCESS)); + int32_t ret = preProcessUtils.GetHapUidByToken(tokenId, userId); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: GetInstIndex001 +* @tc.desc: Abnormal test of GetInstIndex, AccessTokenKit GetInstIndex failed +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsMockTest, GetInstIndex001, TestSize.Level1) +{ + uint32_t tokenId = 0; + int32_t instIndex = 0; + PreProcessUtils preProcessUtils; + EXPECT_CALL(*accessTokenKitMock, GetTokenTypeFlag(_)).WillOnce(Return(TOKEN_HAP)); + EXPECT_CALL(*accessTokenKitMock, GetHapTokenInfo(_, _)).WillOnce(Return(RET_SUCCESS)); + bool ret = preProcessUtils.GetInstIndex(tokenId, instIndex); + EXPECT_EQ(ret, true); +} + +/** +* @tc.name: GetAlterableBundleNameByTokenId001 +* @tc.desc: Abnormal test of GetSpecificBundleNameByTokenId +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsMockTest, GetAlterableBundleNameByTokenId001, TestSize.Level1) +{ + uint32_t tokenId = 0; + EXPECT_CALL(*accessTokenKitMock, GetHapTokenInfo(_, _)).WillOnce(Return(RET_FAILED)); + EXPECT_CALL(*accessTokenKitMock, GetTokenTypeFlag(_)).WillOnce(Return(TOKEN_SHELL)); + std::string bundleName = ""; + std::string specificBundleName = ""; + PreProcessUtils preProcessUtils; + bool ret = preProcessUtils.GetSpecificBundleNameByTokenId(tokenId, specificBundleName, bundleName); + EXPECT_EQ(ret, false); +} + +/** +* @tc.name: GetAlterableBundleNameByTokenId002 +* @tc.desc: Normal test of GetSpecificBundleNameByTokenId for native +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsMockTest, GetAlterableBundleNameByTokenId002, TestSize.Level1) +{ + uint32_t tokenId = 999; + EXPECT_CALL(*accessTokenKitMock, GetHapTokenInfo(_, _)).WillOnce(Return(RET_FAILED)); + EXPECT_CALL(*accessTokenKitMock, GetTokenTypeFlag(_)).WillOnce(Return(TOKEN_NATIVE)); + EXPECT_CALL(*accessTokenKitMock, GetNativeTokenInfo(_, _)).WillOnce(Return(RET_SUCCESS)); + std::string bundleName = ""; + std::string specificBundleName = ""; + PreProcessUtils preProcessUtils; + bool ret = preProcessUtils.GetSpecificBundleNameByTokenId(tokenId, specificBundleName, bundleName); + EXPECT_EQ(ret, true); +} + +/** +* @tc.name: GetAlterableBundleNameByTokenId003 +* @tc.desc: Normal test of GetSpecificBundleNameByTokenId for hap +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsMockTest, GetAlterableBundleNameByTokenId003, TestSize.Level1) +{ + uint32_t tokenId = 9999; + EXPECT_CALL(*accessTokenKitMock, GetHapTokenInfo(_, _)).WillOnce(Return(RET_SUCCESS)); + std::string bundleName = ""; + std::string specificBundleName = ""; + PreProcessUtils preProcessUtils; + bool ret = preProcessUtils.GetSpecificBundleNameByTokenId(tokenId, specificBundleName, bundleName); + EXPECT_EQ(ret, true); +} +}; // namespace UDMF \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/udmf_preprocess_utils_test.cpp b/datamgr_service/services/distributeddataservice/service/test/udmf_preprocess_utils_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb8d62872ac9af72c394dd785a3436b34e7d3c8d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/udmf_preprocess_utils_test.cpp @@ -0,0 +1,193 @@ +/* +* Copyright (c) 2025 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 "preprocess_utils.h" +#include "gtest/gtest.h" +#include "text.h" + +namespace OHOS::UDMF { +using namespace testing::ext; +class UdmfPreProcessUtilsTest : public testing::Test { +public: + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} + void SetUp() {} + void TearDown() {} +}; + +/** +* @tc.name: RuntimeDataImputation001 +* @tc.desc: Abnormal test of FillRuntimeInfo, option is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, RuntimeDataImputation001, TestSize.Level1) +{ + UnifiedData data; + CustomOption option; + PreProcessUtils preProcessUtils; + int32_t ret = preProcessUtils.FillRuntimeInfo(data, option); + EXPECT_EQ(ret, E_ERROR); +} + +/** +* @tc.name: GetHapUidByToken001 +* @tc.desc: Abnormal test of GetHapUidByToken, tokenId is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, GetHapUidByToken001, TestSize.Level1) +{ + uint32_t tokenId = 0; + int userId = 0; + PreProcessUtils preProcessUtils; + int32_t ret = preProcessUtils.GetHapUidByToken(tokenId, userId); + EXPECT_EQ(ret, E_ERROR); +} + +/** +* @tc.name: SetRemoteData001 +* @tc.desc: Abnormal test of SetRemoteData, data is null +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, SetRemoteData001, TestSize.Level1) +{ + UnifiedData data; + PreProcessUtils preProcessUtils; + EXPECT_NO_FATAL_FAILURE(preProcessUtils.SetRemoteData(data)); +} + +/** +* @tc.name: SetRemoteData002 +* @tc.desc: Normal test of SetRemoteData +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, SetRemoteData002, TestSize.Level1) +{ + UnifiedData data; + std::vector> inputRecords; + for (int32_t i = 0; i < 512; ++i) { + inputRecords.emplace_back(std::make_shared()); + } + data.SetRecords(inputRecords); + data.runtime_ = std::make_shared(); + PreProcessUtils preProcessUtils; + EXPECT_NO_FATAL_FAILURE(preProcessUtils.SetRemoteData(data)); +} + +/** +* @tc.name: GetDfsUrisFromLocal001 +* @tc.desc: Abnormal test of GetDfsUrisFromLocal, uris is null +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, GetDfsUrisFromLocal001, TestSize.Level1) +{ + const std::vector uris; + int32_t userId = 0; + UnifiedData data; + PreProcessUtils preProcessUtils; + int32_t ret = preProcessUtils.GetDfsUrisFromLocal(uris, userId, data); + EXPECT_EQ(ret, E_FS_ERROR); +} + +/** +* @tc.name: CheckUriAuthorization001 +* @tc.desc: Abnormal test of CheckUriAuthorization, uris is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, CheckUriAuthorization001, TestSize.Level1) +{ + const std::vector uris = {"test"}; + uint32_t tokenId = 0; + PreProcessUtils preProcessUtils; + bool ret = preProcessUtils.CheckUriAuthorization(uris, tokenId); + EXPECT_EQ(ret, false); +} + +/** +* @tc.name: GetInstIndex001 +* @tc.desc: Normal test of GetInstIndex +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, GetInstIndex001, TestSize.Level1) +{ + uint32_t tokenId = 0; + int32_t instIndex = 0; + PreProcessUtils preProcessUtils; + bool ret = preProcessUtils.GetInstIndex(tokenId, instIndex); + EXPECT_EQ(instIndex, 0); + EXPECT_EQ(ret, true); +} + +/** +* @tc.name: ProcessFileType001 +* @tc.desc: Abnormal test of ProcessFileType, records is nullptr +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, ProcessFileType001, TestSize.Level1) +{ + std::shared_ptr record = std::make_shared(); + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = "http://demo.com.html"; + obj->value_[FILE_TYPE] = "general.html"; + record->AddEntry("general.file-uri", obj); + std::shared_ptr obj1 = std::make_shared(); + obj1->value_[UNIFORM_DATA_TYPE] = "general.content-form"; + obj1->value_["title"] = "test"; + record->AddEntry("general.content-form", obj1); + + std::shared_ptr record1 = std::make_shared(); + record1->AddEntry("general.file-uri", obj1); + std::shared_ptr record2 = std::make_shared(); + record2->AddEntry("general.file-uri", "1111"); + std::shared_ptr record3 = std::make_shared(); + record3->AddEntry("general.file-uri", 1); + std::vector> records = { record, record1, record2, record3 }; + std::vector uris; + PreProcessUtils::ProcessFileType(records, [&uris](std::shared_ptr obj) { + std::string oriUri; + obj->GetValue(ORI_URI, oriUri); + if (oriUri.empty()) { + return false; + } + uris.push_back(oriUri); + return true; + }); + EXPECT_EQ(uris.size(), 1); +} + +/** +* @tc.name: GetHtmlFileUris001 +* @tc.desc: Abnormal test of GetHtmlFileUris, uris is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, GetHtmlFileUris001, TestSize.Level1) +{ + uint32_t tokenId = 0; + UnifiedData data; + bool isLocal = false; + std::vector uris = {"test"}; + PreProcessUtils preProcessUtils; + EXPECT_NO_FATAL_FAILURE(preProcessUtils.GetHtmlFileUris(tokenId, data, isLocal, uris)); +} +}; // namespace UDMF \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/udmf_run_time_store_test.cpp b/datamgr_service/services/distributeddataservice/service/test/udmf_run_time_store_test.cpp index d8d440cf33a44187d7f4dcbb8b1d93e5eda7c45f..e188e2284905b55f080bee4052fe2ff12f071590 100644 --- a/datamgr_service/services/distributeddataservice/service/test/udmf_run_time_store_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/udmf_run_time_store_test.cpp @@ -29,6 +29,7 @@ #include "runtime_store.h" #include "text.h" #include "token_setproc.h" +#include "directory_manager.h" using namespace testing::ext; using namespace OHOS::DistributedData; @@ -91,7 +92,9 @@ public: const uint32_t MAX_VALUE_SIZE = 4 * 1024 * 1024; const std::string STORE_ID = "drag"; const std::string KEY_PREFIX = "TEST_"; + const std::string SUMMARY_KEY_PREFIX = "SUMMARY_KEY_PREFIX"; const std::string EMPTY_DEVICE_ID = ""; + const std::string BUNDLE_NAME = "udmf_test"; static constexpr size_t tempUdataRecordSize = 1; }; @@ -124,6 +127,9 @@ HWTEST_F(UdmfRunTimeStoreTest, PutEntries001, TestSize.Level1) bool result = store->Init(); EXPECT_EQ(true, result); + auto status = store->Delete(KEY_PREFIX); + EXPECT_EQ(E_OK, status); + Key key; Value value; GetRandomValue(value, MAX_KEY_SIZE); // 1K @@ -133,7 +139,7 @@ HWTEST_F(UdmfRunTimeStoreTest, PutEntries001, TestSize.Level1) entrysRand.push_back({ key, value }); } - int32_t status = store->PutEntries(entrysRand); + status = store->PutEntries(entrysRand); EXPECT_EQ(E_OK, status); vector entries; @@ -412,24 +418,17 @@ HWTEST_F(UdmfRunTimeStoreTest, Get001, TestSize.Level1) bool result = store->Init(); EXPECT_TRUE(result); - Key key; Key keyInvalid; Value value; - Value valueInvalid; - GetRandomKey(key, MAX_KEY_SIZE); // 1K GetRandomKey(keyInvalid, MAX_KEY_SIZE + 1); // 1K + 1 GetRandomValue(value, MAX_VALUE_SIZE); // 4M - GetRandomValue(valueInvalid, MAX_VALUE_SIZE + 1); // 4M + 1 vector entrysMix1(1, { keyInvalid, value }); - vector entrysMix2(1, { key, valueInvalid }); - UnifiedData unifiedData; int32_t status = store->PutEntries(entrysMix1); EXPECT_EQ(E_DB_ERROR, status); + entrysMix1.clear(); status = store->GetEntries(KEY_PREFIX, entrysMix1); EXPECT_EQ(E_OK, status); - - status = store->Get(KEY_PREFIX, unifiedData); - EXPECT_EQ(E_NOT_FOUND, status); + EXPECT_TRUE(entrysMix1.empty()); status = store->Delete(KEY_PREFIX); EXPECT_EQ(E_OK, status); @@ -458,11 +457,10 @@ HWTEST_F(UdmfRunTimeStoreTest, Get002, TestSize.Level1) } auto status = store->PutEntries(entrysRand); EXPECT_EQ(E_DB_ERROR, status); - status = store->GetEntries(EMPTY_DEVICE_ID, entrysRand); + entrysRand.clear(); + status = store->GetEntries(KEY_PREFIX, entrysRand); EXPECT_EQ(E_OK, status); - UnifiedData data1; - status = store->Get(EMPTY_DEVICE_ID, data1); - EXPECT_EQ(E_NOT_FOUND, status); + EXPECT_TRUE(entrysRand.empty()); status = store->Delete(KEY_PREFIX); EXPECT_EQ(E_OK, status); @@ -551,6 +549,88 @@ HWTEST_F(UdmfRunTimeStoreTest, GetDetailsFromUData01, TestSize.Level1) EXPECT_FALSE(status); } +/** +* @tc.name: Sync01 +* @tc.desc: check for legal parameters, delete entries error. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, Sync01, TestSize.Level1) +{ + std::vector devices = {"device"}; + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + Status ret = store->Sync(devices); + EXPECT_EQ(ret, E_DB_ERROR); +} + +/** +* @tc.name: Sync02 +* @tc.desc: check for legal parameters, delete entries error. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, Sync02, TestSize.Level1) +{ + std::vector devices = { }; + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + Status ret = store->Sync(devices); + EXPECT_EQ(ret, E_INVALID_PARAMETERS); +} + +/** +* @tc.name: Sync03 +* @tc.desc: check for legal parameters, delete entries error. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, Sync03, TestSize.Level1) +{ + std::vector devices = { "device" }; + ProcessCallback callback; + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + Status ret = store->Sync(devices, callback); + EXPECT_EQ(ret, E_DB_ERROR); +} + +/** +* @tc.name: Sync04 +* @tc.desc: check for legal parameters, delete entries error. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, Sync04, TestSize.Level1) +{ + std::vector devices = { }; + ProcessCallback callback; + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + Status ret = store->Sync(devices, callback); + EXPECT_EQ(ret, E_INVALID_PARAMETERS); +} + +/** +* @tc.name: Clear01 +* @tc.desc: check for legal parameters, delete entries error. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, Clear01, TestSize.Level1) +{ + static constexpr const char *DATA_PREFIX = "udmf://"; + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + Status ret = store->Clear(); + EXPECT_EQ(ret, store->Delete(DATA_PREFIX)); +} + /** * @tc.name: GetSummary * @tc.desc: check for legal parameters, delete entries error. @@ -562,18 +642,102 @@ HWTEST_F(UdmfRunTimeStoreTest, GetSummary, TestSize.Level1) auto store = std::make_shared(STORE_ID); bool result = store->Init(); EXPECT_TRUE(result); + Summary summary; + summary.summary = { + { "general.file", 10 }, + { "general.png", 10 }, + { "general.html", 10 }, + { "general.jpeg", 10 }, + { "general.avi", 10}, + { "aabbcc", 10} + }; + UnifiedKey key(SUMMARY_KEY_PREFIX); + auto status = store->PutSummary(key, summary); + EXPECT_EQ(status, E_OK); + status = store->GetSummary(key, summary); + ASSERT_EQ(status, E_OK); +} - UnifiedData data; - UDDetails details; - details.insert({ "udmf_key", "udmf_value" }); - auto text = std::make_shared(); - text->SetDetails(details); - data.AddRecord(text); - Summary summary; - UnifiedKey key(KEY_PREFIX); - auto status = store->GetSummary(key, summary); - ASSERT_EQ(status, E_DB_ERROR); +/** +* @tc.name: GetRuntime001 +* @tc.desc: Normal testcase of GetRuntime +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, GetRuntime001, TestSize.Level1) +{ + UnifiedKey udKey(STORE_ID, BUNDLE_NAME, UDMF::PreProcessUtils::GenerateId()); + Runtime runtime{ + .key = udKey + }; + UnifiedData inputData; + inputData.SetRuntime(runtime); + auto key = inputData.GetRuntime()->key.GetUnifiedKey(); + + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + auto status = store->PutRuntime(key, *inputData.GetRuntime()); + EXPECT_EQ(status, E_OK); + + Runtime outRuntime; + status = store->GetRuntime(key, outRuntime); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(inputData.GetRuntime()->createTime, outRuntime.createTime); +} + +/** +* @tc.name: GetRuntime002 +* @tc.desc: Abnormal testcase of GetRuntime +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, GetRuntime002, TestSize.Level1) +{ + UnifiedKey udKey(STORE_ID, BUNDLE_NAME, UDMF::PreProcessUtils::GenerateId()); + Runtime runtime{ + .key = udKey + }; + UnifiedData inputData; + inputData.SetRuntime(runtime); + auto key = inputData.GetRuntime()->key.GetUnifiedKey(); + + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + + Runtime outRuntime; + auto status = store->GetRuntime(key, outRuntime); + EXPECT_EQ(status, E_NOT_FOUND); +} + +/** +* @tc.name: MarkWhenCorrupted001 +* @tc.desc: Normal testcase of MarkWhenCorrupted +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, MarkWhenCorrupted001, TestSize.Level1) +{ + DistributedDB::DBStatus status = DistributedDB::DBStatus::OK; + auto store = std::make_shared(STORE_ID); + store->MarkWhenCorrupted(status); + EXPECT_FALSE(store->isCorrupted_); +} + +/** +* @tc.name: MarkWhenCorrupted001 +* @tc.desc: Normal testcase of MarkWhenCorrupted +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, MarkWhenCorrupted002, TestSize.Level1) +{ + DistributedDB::DBStatus status = DistributedDB::DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; + auto store = std::make_shared(STORE_ID); + store->MarkWhenCorrupted(status); + EXPECT_TRUE(store->isCorrupted_); } }; // namespace DistributedDataTest }; // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/udmf_service_impl_mock_test.cpp b/datamgr_service/services/distributeddataservice/service/test/udmf_service_impl_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9daa166f47cbbd23c181584e9c5ac1e53bf42881 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/udmf_service_impl_mock_test.cpp @@ -0,0 +1,140 @@ +/* +* Copyright (c) 2025 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 "UdmfServiceImplMockTest" +#include "udmf_service_impl.h" +#include "gtest/gtest.h" +#include "error_code.h" +#include "text.h" +#include "accesstoken_kit.h" +#include "bootstrap.h" +#include "executor_pool.h" +#include "ipc_skeleton.h" +#include "mock/access_token_mock.h" +#include "mock/meta_data_manager_mock.h" +#include "nativetoken_kit.h" +#include "token_setproc.h" +#include "kvstore_meta_manager.h" +using namespace OHOS::DistributedData; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; +using namespace testing::ext; +using namespace testing; + +namespace OHOS::Test { +namespace DistributedDataTest { +class UdmfServiceImplMockTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + accTokenMock = std::make_shared(); + BAccessTokenKit::accessTokenkit = accTokenMock; + metaDataManagerMock = std::make_shared(); + BMetaDataManager::metaDataManager = metaDataManagerMock; + metaDataMock = std::make_shared>(); + BMetaData::metaDataManager = metaDataMock; + } + static void TearDownTestCase(void) + { + accTokenMock = nullptr; + BAccessTokenKit::accessTokenkit = nullptr; + metaDataManagerMock = nullptr; + BMetaDataManager::metaDataManager = nullptr; + metaDataMock = nullptr; + BMetaData::metaDataManager = nullptr; + } + static inline std::shared_ptr accTokenMock = nullptr; + static inline std::shared_ptr metaDataManagerMock = nullptr; + static inline std::shared_ptr> metaDataMock = nullptr; + void SetUp() {}; + void TearDown() {}; +}; + +/** +* @tc.name: IsNeedMetaSyncTest001 +* @tc.desc: IsNeedMetaSync test +* @tc.type: FUNC +*/ +HWTEST_F(UdmfServiceImplMockTest, IsNeedMetaSyncTest001, TestSize.Level0) +{ + UdmfServiceImpl udmfServiceImpl; + StoreMetaData meta = StoreMetaData("100", "distributeddata", "drag"); + std::vector devices = {"remote_device"}; + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(Return(false)); + auto isNeedSync = udmfServiceImpl.IsNeedMetaSync(meta, devices); + EXPECT_EQ(isNeedSync, true); + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(Return(false)); + isNeedSync = udmfServiceImpl.IsNeedMetaSync(meta, devices); + EXPECT_EQ(isNeedSync, true); + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(Return(true)) + .WillOnce(Return(false)); + isNeedSync = udmfServiceImpl.IsNeedMetaSync(meta, devices); + EXPECT_EQ(isNeedSync, true); + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(Return(true)) + .WillOnce(Return(true)); + isNeedSync = udmfServiceImpl.IsNeedMetaSync(meta, devices); + EXPECT_EQ(isNeedSync, true); +} + +/** +* @tc.name: IsNeedMetaSyncTest002 +* @tc.desc: IsNeedMetaSync test matrix mask +* @tc.type: FUNC +*/ +HWTEST_F(UdmfServiceImplMockTest, IsNeedMetaSyncTest002, TestSize.Level0) +{ + QueryOption query; + query.key = "test_key"; + query.tokenId = 1; + query.intention = UD_INTENTION_DRAG; + UdmfServiceImpl udmfServiceImpl; + StoreMetaData meta = StoreMetaData("100", "distributeddata", "drag"); + std::vector devices = {"remote_device"}; + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(Return(false)) + .WillOnce(Return(false)); + auto isNeedSync = udmfServiceImpl.IsNeedMetaSync(meta, devices); + EXPECT_EQ(isNeedSync, true); + // mock mask +} + +/** + * @tc.name: ResolveAutoLaunchTest001 + * @tc.desc: ResolveAutoLaunch test. + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplMockTest, ResolveAutoLaunchTest001, TestSize.Level0) +{ + DistributedDB::AutoLaunchParam param { + .userId = "100", + .appId = "distributeddata", + .storeId = "drag", + }; + std::string identifier = "identifier"; + std::shared_ptr udmfServiceImpl = std::make_shared(); + auto ret = udmfServiceImpl->ResolveAutoLaunch(identifier, param); + EXPECT_EQ(ret, UDMF::E_NOT_FOUND); +} +}; // DistributedDataTest +}; // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/udmf_service_impl_test.cpp b/datamgr_service/services/distributeddataservice/service/test/udmf_service_impl_test.cpp index d93a559053eff8627f4732a64cfbba2c83a59132..9a32e1587fb02ae3e7677a42a955c9476e9e38d4 100644 --- a/datamgr_service/services/distributeddataservice/service/test/udmf_service_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/udmf_service_impl_test.cpp @@ -15,19 +15,80 @@ #define LOG_TAG "UdmfServiceImplTest" #include "udmf_service_impl.h" +#include "accesstoken_kit.h" +#include "account_delegate.h" +#include "bootstrap.h" +#include "device_manager_adapter.h" +#include "executor_pool.h" #include "gtest/gtest.h" -#include "error_code.h" +#include "ipc_skeleton.h" +#include "kvstore_meta_manager.h" +#include "metadata/meta_data_manager.h" +#include "nativetoken_kit.h" +#include "preprocess_utils.h" +#include "runtime_store.h" #include "text.h" +#include "plain_text.h" +#include "token_setproc.h" -using namespace OHOS::DistributedData; -namespace OHOS::UDMF { using namespace testing::ext; +using namespace OHOS::DistributedData; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; +using Entry = DistributedDB::Entry; +using Key = DistributedDB::Key; +using Value = DistributedDB::Value; +using UnifiedData = OHOS::UDMF::UnifiedData; +using Summary = OHOS::UDMF::Summary; +namespace OHOS::Test { +namespace DistributedDataTest { + +static void GrantPermissionNative() +{ + const char **perms = new const char *[3]; + perms[0] = "ohos.permission.DISTRIBUTED_DATASYNC"; + perms[1] = "ohos.permission.ACCESS_SERVICE_DM"; + perms[2] = "ohos.permission.MONITOR_DEVICE_NETWORK_STATE"; // perms[2] is a permission parameter + TokenInfoParams infoInstance = { + .dcapsNum = 0, + .permsNum = 3, + .aclsNum = 0, + .dcaps = nullptr, + .perms = perms, + .acls = nullptr, + .processName = "distributed_data_test", + .aplStr = "system_basic", + }; + uint64_t tokenId = GetAccessTokenId(&infoInstance); + SetSelfTokenID(tokenId); + AccessTokenKit::ReloadNativeTokenInfo(); + delete[] perms; +} + class UdmfServiceImplTest : public testing::Test { public: - static void SetUpTestCase(void) {} - static void TearDownTestCase(void) {} - void SetUp() {} - void TearDown() {} + static void SetUpTestCase(void) + { + GrantPermissionNative(); + DistributedData::Bootstrap::GetInstance().LoadComponents(); + DistributedData::Bootstrap::GetInstance().LoadDirectory(); + DistributedData::Bootstrap::GetInstance().LoadCheckers(); + size_t max = 2; + size_t min = 1; + auto executors = std::make_shared(max, min); + DmAdapter::GetInstance().Init(executors); + DistributedKv::KvStoreMetaManager::GetInstance().BindExecutor(executors); + DistributedKv::KvStoreMetaManager::GetInstance().InitMetaParameter(); + DistributedKv::KvStoreMetaManager::GetInstance().InitMetaListener(); + } + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; + + static constexpr const char *STORE_ID = "drag"; + static constexpr uint32_t TOKEN_ID = 5; + static constexpr const char *APP_ID = "appId"; }; /** @@ -119,7 +180,22 @@ HWTEST_F(UdmfServiceImplTest, Sync001, TestSize.Level1) std::vector devices = {"device1"}; UdmfServiceImpl udmfServiceImpl; int32_t ret = udmfServiceImpl.Sync(query, devices); - EXPECT_EQ(ret, E_INVALID_PARAMETERS); + EXPECT_EQ(ret, E_NO_PERMISSION); +} + +/** +* @tc.name: VerifyPermission001 +* @tc.desc: Abnormal test of VerifyPermission, permission is empty +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplTest, VerifyPermission001, TestSize.Level1) +{ + std::string permission; + uint32_t callerTokenId = 0; + UdmfServiceImpl udmfServiceImpl; + bool ret = udmfServiceImpl.VerifyPermission(permission, callerTokenId); + EXPECT_FALSE(ret); } /** @@ -206,14 +282,163 @@ HWTEST_F(UdmfServiceImplTest, SetAppShareOption004, TestSize.Level1) */ HWTEST_F(UdmfServiceImplTest, OnUserChangeTest001, TestSize.Level1) { - uint32_t code = 4; + // Clear store + StoreCache::GetInstance().CloseStores(); + auto stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 0); + // Init store + StoreCache::GetInstance().GetStore("SystemShare"); + stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 1); + + uint32_t code = static_cast(DistributedData::AccountStatus::DEVICE_ACCOUNT_STOPPING); + std::string user = "OH_USER_test"; + std::string account = "OH_ACCOUNT_test"; + UdmfServiceImpl udmfServiceImpl; + auto status = udmfServiceImpl.OnUserChange(code, user, account); + ASSERT_EQ(status, UDMF::E_OK); + stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 0); +} + +/** +* @tc.name: OnUserChangeTest002 +* @tc.desc: OnUserChange test +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplTest, OnUserChangeTest002, TestSize.Level1) +{ + // Clear store + StoreCache::GetInstance().CloseStores(); + auto stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 0); + // Init store + StoreCache::GetInstance().GetStore(STORE_ID); + stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 1); + + uint32_t code = static_cast(DistributedData::AccountStatus::DEVICE_ACCOUNT_STOPPED); std::string user = "OH_USER_test"; std::string account = "OH_ACCOUNT_test"; UdmfServiceImpl udmfServiceImpl; auto status = udmfServiceImpl.OnUserChange(code, user, account); - ASSERT_EQ(status, E_OK); - auto sizeAfter = StoreCache::GetInstance().stores_.Size(); - ASSERT_EQ(sizeAfter, 0); + ASSERT_EQ(status, UDMF::E_OK); + stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 0); +} + +/** +* @tc.name: OnUserChangeTest003 +* @tc.desc: OnUserChange test +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplTest, OnUserChangeTest003, TestSize.Level1) +{ + // Clear store + StoreCache::GetInstance().CloseStores(); + auto stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 0); + // Init store + StoreCache::GetInstance().GetStore(STORE_ID); + stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 1); + + uint32_t code = static_cast(DistributedData::AccountStatus::DEVICE_ACCOUNT_SWITCHED); + std::string user = "OH_USER_test"; + std::string account = "OH_ACCOUNT_test"; + UdmfServiceImpl udmfServiceImpl; + auto status = udmfServiceImpl.OnUserChange(code, user, account); + ASSERT_EQ(status, UDMF::E_OK); + stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 0); +} + +/** +* @tc.name: OnUserChangeTest004 +* @tc.desc: OnUserChange test +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplTest, OnUserChangeTest004, TestSize.Level1) +{ + // Clear store + StoreCache::GetInstance().CloseStores(); + auto stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 0); + // Init store + StoreCache::GetInstance().GetStore(STORE_ID); + stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 1); + + uint32_t code = static_cast(DistributedData::AccountStatus::DEVICE_ACCOUNT_UNLOCKED); + std::string user = "OH_USER_test"; + std::string account = "OH_ACCOUNT_test"; + UdmfServiceImpl udmfServiceImpl; + auto status = udmfServiceImpl.OnUserChange(code, user, account); + ASSERT_EQ(status, UDMF::E_OK); + stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 1); +} + +/** +* @tc.name: SaveMetaData001 +* @tc.desc: Abnormal testcase of GetRuntime +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplTest, SaveMetaData001, TestSize.Level0) +{ + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + + result = store->Init(); + EXPECT_TRUE(result); +} + +/** +* @tc.name: SaveMetaData001 +* @tc.desc: Abnormal testcase of GetRuntime +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplTest, SyncTest001, TestSize.Level0) +{ + QueryOption query; + query.key = "udmf://drag/ohos.test.demo1/_aS6adWi7 devices = {"remote_device"}; + + auto ret = udmfServiceImpl.Sync(query, devices); + EXPECT_EQ(ret, UDMF::E_NO_PERMISSION); +} + +/** +* @tc.name: ResolveAutoLaunch001 +* @tc.desc: test ResolveAutoLaunch +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplTest, ResolveAutoLaunch001, TestSize.Level0) +{ + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + + DistributedDB::AutoLaunchParam param { + .userId = "100", + .appId = "distributeddata", + .storeId = "drag", + }; + std::string identifier = "identifier"; + std::shared_ptr udmfServiceImpl = std::make_shared(); + auto ret = udmfServiceImpl->ResolveAutoLaunch(identifier, param); + EXPECT_EQ(ret, UDMF::E_OK); } /** @@ -240,4 +465,216 @@ HWTEST_F(UdmfServiceImplTest, TransferToEntriesIfNeedTest001, TestSize.Level1) int recordSize = 2; EXPECT_EQ(data.GetRecords().size(), recordSize); } -}; // namespace UDMF \ No newline at end of file +/** + * @tc.name: IsValidInput001 + * @tc.desc: invalid unifiedData + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, IsValidInput001, TestSize.Level1) +{ + QueryOption query; + UnifiedData unifiedData; + UnifiedKey key; + + UdmfServiceImpl impl; + bool result = impl.IsValidInput(query, unifiedData, key); + EXPECT_FALSE(result); +} + +/** + * @tc.name: IsValidInput002 + * @tc.desc: invalid key + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, IsValidInput002, TestSize.Level1) +{ + QueryOption query; + UnifiedData unifiedData; + auto record1 = std::make_shared(); + auto record2 = std::make_shared(); + unifiedData.AddRecord(record1); + unifiedData.AddRecord(record2); + UnifiedKey key; + + UdmfServiceImpl impl; + bool result = impl.IsValidInput(query, unifiedData, key); + EXPECT_FALSE(result); +} + +/** + * @tc.name: IsValidInput003 + * @tc.desc: valid input + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, IsValidInput003, TestSize.Level1) +{ + QueryOption query; + query.intention = Intention::UD_INTENTION_DATA_HUB; + query.key = "udmf://DataHub/aaa/N]2fIEMbrJj@wp:jMuPa7"; + UnifiedData unifiedData; + auto record1 = std::make_shared(); + auto record2 = std::make_shared(); + unifiedData.AddRecord(record1); + unifiedData.AddRecord(record2); + UnifiedKey key("udmf://DataHub/aaa/N]2fIEMbrJj@wp:jMuPa7"); + EXPECT_TRUE(key.IsValid()); + + UdmfServiceImpl impl; + bool result = impl.IsValidInput(query, unifiedData, key); + EXPECT_TRUE(result); +} + +/** + * @tc.name: IsValidInput004 + * @tc.desc: invalid intention + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, IsValidInput004, TestSize.Level1) +{ + QueryOption query; + query.intention = Intention::UD_INTENTION_DRAG; + UnifiedData unifiedData; + UnifiedKey key("udmf://drag/aaa/N]2fIEMbrJj@wp:jMuPa7"); + + UdmfServiceImpl impl; + bool result = impl.IsValidInput(query, unifiedData, key); + EXPECT_FALSE(result); +} + +/** + * @tc.name: CheckAppId001 + * @tc.desc: invalid bundleName + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, CheckAppId001, TestSize.Level1) +{ + std::shared_ptr runtime = std::make_shared(); + runtime->appId = "appId"; + std::string bundleName = "ohos.test.demo1"; + + UdmfServiceImpl impl; + int32_t result = impl.CheckAppId(runtime, bundleName); + EXPECT_EQ(result, E_INVALID_PARAMETERS); +} + +/** + * @tc.name: CheckAppId002 + * @tc.desc: invalid runtime + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, CheckAppId002, TestSize.Level1) +{ + std::shared_ptr runtime = std::make_shared(); + std::string bundleName = "ohos.test.demo1"; + + UdmfServiceImpl impl; + int32_t result = impl.CheckAppId(runtime, bundleName); + EXPECT_EQ(result, E_INVALID_PARAMETERS); +} + +/** +* @tc.name: CheckDeleteDataPermission001 +* @tc.desc: runtime is null +* @tc.type: FUNC +*/ +HWTEST_F(UdmfServiceImplTest, CheckDeleteDataPermission001, TestSize.Level1) +{ + std::string appId; + std::shared_ptr runtime; + QueryOption query; + UdmfServiceImpl impl; + bool ret = impl.CheckDeleteDataPermission(appId, runtime, query); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: CheckDeleteDataPermission002 +* @tc.desc: query.tokenId is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UdmfServiceImplTest, CheckDeleteDataPermission002, TestSize.Level1) +{ + std::string appId; + std::shared_ptr runtime = std::make_shared(); + runtime->tokenId = TOKEN_ID; + QueryOption query; + UdmfServiceImpl impl; + bool ret = impl.CheckDeleteDataPermission(appId, runtime, query); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: CheckDeleteDataPermission003 +* @tc.desc: Normal test +* @tc.type: FUNC +*/ +HWTEST_F(UdmfServiceImplTest, CheckDeleteDataPermission003, TestSize.Level1) +{ + std::string appId; + std::shared_ptr runtime = std::make_shared(); + runtime->tokenId = TOKEN_ID; + QueryOption query; + query.tokenId = TOKEN_ID; + UdmfServiceImpl impl; + bool ret = impl.CheckDeleteDataPermission(appId, runtime, query); + EXPECT_TRUE(ret); +} + +/** +* @tc.name: CheckDeleteDataPermission004 +* @tc.desc: bundleName is empty +* @tc.type: FUNC +*/ +HWTEST_F(UdmfServiceImplTest, CheckDeleteDataPermission004, TestSize.Level1) +{ + std::string appId; + std::shared_ptr runtime = std::make_shared(); + runtime->appId = APP_ID; + QueryOption query; + query.tokenId = TOKEN_ID; + UdmfServiceImpl impl; + bool ret = impl.CheckDeleteDataPermission(appId, runtime, query); + EXPECT_FALSE(ret); +} + +/** + * @tc.name: VerifyDataAccessPermission001 + * @tc.desc: no permission + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, VerifyDataAccessPermission001, TestSize.Level1) +{ + std::shared_ptr runtime = std::make_shared(); + const QueryOption query; + UnifiedData unifiedData; + + UdmfServiceImpl impl; + auto result = impl.VerifyDataAccessPermission(runtime, query, unifiedData); + EXPECT_EQ(result, E_NO_PERMISSION); +} + +/** + * @tc.name: VerifyDataAccessPermission002 + * @tc.desc: runtime is nullptr + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, VerifyDataAccessPermission002, TestSize.Level1) +{ + std::shared_ptr runtime = std::make_shared(); + Privilege privilege { + .tokenId = TOKEN_ID, + .readPermission = STORE_ID, + .writePermission = STORE_ID, + }; + runtime->privileges = { privilege }; + QueryOption query; + query.tokenId = TOKEN_ID; + UnifiedData unifiedData; + + UdmfServiceImpl impl; + auto result = impl.VerifyDataAccessPermission(runtime, query, unifiedData); + EXPECT_EQ(runtime->privileges[0].tokenId, query.tokenId); + EXPECT_EQ(result, OHOS::UDMF::E_OK); +} +}; // namespace DistributedDataTest +}; // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/service/test/unittest/cloud/cloud_data_test.cpp b/datamgr_service/services/distributeddataservice/service/test/unittest/cloud/cloud_data_test.cpp index 9229bd8ad00b488beedaac5f58a904c2578ea059..ba36cc0281c93e7999bcbc4b7b3cad1a13eab6d4 100644 --- a/datamgr_service/services/distributeddataservice/service/test/unittest/cloud/cloud_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/unittest/cloud/cloud_data_test.cpp @@ -194,7 +194,7 @@ HWTEST_F(CloudDataTest, GetSchemaTest001, TestSize.Level0) auto event = std::make_unique(CloudEvent::GET_SCHEMA, std::move(storeInfo)); EventCenter::GetInstance().PostEvent(std::move(event)); ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true)); - ASSERT_EQ(to_string(schemaMeta.Marshall()), to_string(SCHEMA_META.Marshall())); + ASSERT_EQ(schemaMeta.Marshall().dump(), SCHEMA_META.Marshall().dump()); } /** diff --git a/datamgr_service/services/distributeddataservice/service/test/user_delegate_mock_test.cpp b/datamgr_service/services/distributeddataservice/service/test/user_delegate_mock_test.cpp index 373782b7eb6961ce8d2141fdbeba4a26b95560f7..5a40b23ab438a087f7982c43ce34211ae17fc38e 100644 --- a/datamgr_service/services/distributeddataservice/service/test/user_delegate_mock_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/user_delegate_mock_test.cpp @@ -13,12 +13,14 @@ * limitations under the License. */ -#include #include -#include "user_delegate.h" -#include "device_manager_adapter_mock.h" +#include + #include "account_delegate_mock.h" +#include "device_manager_adapter_mock.h" #include "metadata/meta_data_manager.h" +#include "user_delegate.h" + using namespace OHOS::DistributedData; using namespace testing::ext; @@ -39,27 +41,48 @@ bool MetaDataManager::Subscribe(std::string prefix, Observer observer, bool isLo return false; } +bool MetaDataManager::SaveMeta(const std::string &key, const Serializable &value, bool isLocal) +{ + (void)key; + (void)value; + return true; +} + namespace OHOS::Test { namespace DistributedDataTest { class UserDelegateMockTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); - void SetUp() {} - void TearDown() {} + void SetUp() + { + } + void TearDown() + { + } static inline shared_ptr devMgrAdapterMock = nullptr; + static inline AccountDelegateMock *accountDelegateMock = nullptr; }; void UserDelegateMockTest::SetUpTestCase(void) { devMgrAdapterMock = make_shared(); BDeviceManagerAdapter::deviceManagerAdapter = devMgrAdapterMock; + accountDelegateMock = new (std::nothrow) AccountDelegateMock(); + if (accountDelegateMock != nullptr) { + AccountDelegate::instance_ = nullptr; + AccountDelegate::RegisterAccountInstance(accountDelegateMock); + } } void UserDelegateMockTest::TearDownTestCase(void) { BDeviceManagerAdapter::deviceManagerAdapter = nullptr; devMgrAdapterMock = nullptr; + if (accountDelegateMock != nullptr) { + delete accountDelegateMock; + accountDelegateMock = nullptr; + } } /** @@ -84,13 +107,12 @@ HWTEST_F(UserDelegateMockTest, GetLocalUserStatus, TestSize.Level0) */ HWTEST_F(UserDelegateMockTest, InitLocalUserMeta, TestSize.Level0) { - EXPECT_CALL(AccountDelegateMock::Init(), QueryUsers(_)).WillOnce(Return(false)); + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(Return(false)); bool ret = UserDelegate::GetInstance().InitLocalUserMeta(); EXPECT_FALSE(ret); std::vector users; - EXPECT_CALL(AccountDelegateMock::Init(), QueryUsers(_)) - .WillRepeatedly(DoAll(SetArgReferee<0>(users), Return(true))); + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(users), Return(true))); ret = UserDelegate::GetInstance().InitLocalUserMeta(); UserDelegate::GetInstance().DeleteUsers("users"); EXPECT_FALSE(ret); @@ -137,15 +159,20 @@ HWTEST_F(UserDelegateMockTest, GetUsers, TestSize.Level0) */ HWTEST_F(UserDelegateMockTest, Init, TestSize.Level0) { - EXPECT_CALL(AccountDelegateMock::Init(), Subscribe(_)).WillRepeatedly(Return(0)); + EXPECT_CALL(*accountDelegateMock, Subscribe(_)).WillRepeatedly(Return(0)); DeviceInfo devInfo = { .uuid = "HJJ4FGAGAAGA45WF3663FAGA" }; EXPECT_CALL(*devMgrAdapterMock, GetLocalDevice()).WillRepeatedly(Return(devInfo)); - std::shared_ptr poolPtr = std::make_shared(0, 1); + std::shared_ptr poolPtr = std::make_shared(1, 0); ASSERT_NE(poolPtr, nullptr); - UserDelegate::GetInstance().executors_ = poolPtr; - ASSERT_NE(UserDelegate::GetInstance().executors_, nullptr); - UserDelegate::GetInstance().Init(poolPtr); - ASSERT_TRUE(UserDelegate::GetInstance().executors_ != nullptr); -} + UserDelegate instance; + instance.executors_ = poolPtr; + ASSERT_NE(instance.executors_, nullptr); + + std::vector users = { 0, 1 }; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).WillRepeatedly(DoAll(SetArgReferee<0>(users), Return(true))); + EXPECT_TRUE(instance.InitLocalUserMeta()); + instance.Init(poolPtr); + ASSERT_TRUE(instance.executors_ != nullptr); } -} \ No newline at end of file +} // namespace DistributedDataTest +} // 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 66deaa9567f7bcdeb15dcdb86335b111513f58b5..469d2230da7cf2cc0b7d3118310f130b6dca85c4 100644 --- a/datamgr_service/services/distributeddataservice/service/test/value_proxy_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/value_proxy_test.cpp @@ -373,30 +373,30 @@ HWTEST_F(ValueProxyServiceTest, AssetsOperator001, TestSize.Level0) ValueProxy::Assets proxy1; ValueProxy::Assets proxy2; ValueProxy::Assets proxy3; - DistributedDB::Asset asset; - asset.version = 1; - asset.status = DistributedData::Asset::Status::STATUS_INSERT; - asset.name = "Asset1"; - asset.uri = "uri1"; - asset.size = "1"; - asset.hash = "hash1"; - proxy1.assets_.push_back(asset); - - asset.version = 2; - asset.status = DistributedData::Asset::Status::STATUS_NORMAL; - asset.name = "Asset2"; - asset.uri = "uri2"; - asset.size = "2"; - asset.hash = "hash2"; - proxy2.assets_.push_back(asset); - - asset.version = 3; - asset.status = DistributedData::Asset::Status::STATUS_NORMAL; - asset.name = "Asset3"; - asset.uri = "uri3"; - asset.size = "3"; - asset.hash = "hash3"; - proxy2.assets_.push_back(asset); + proxy1.assets_.push_back(ValueProxy::Asset(DistributedDB::Asset { + .version = 1, + .status = DistributedData::Asset::Status::STATUS_INSERT, + .name = "Asset1", + .uri = "uri1", + .size = "1", + .hash = "hash1", + })); + proxy2.assets_.push_back(ValueProxy::Asset(DistributedDB::Asset { + .version = 2, + .status = DistributedData::Asset::Status::STATUS_NORMAL, + .name = "Asset2", + .uri = "uri2", + .size = "2", + .hash = "hash2", + })); + proxy2.assets_.push_back(ValueProxy::Asset(DistributedDB::Asset { + .version = 3, + .status = DistributedData::Asset::Status::STATUS_NORMAL, + .name = "Asset3", + .uri = "uri3", + .size = "3", + .hash = "hash3", + })); // operator "=" same asset case proxy3 = proxy1; proxy1 = proxy3; @@ -406,7 +406,7 @@ HWTEST_F(ValueProxyServiceTest, AssetsOperator001, TestSize.Level0) EXPECT_EQ(proxy1.assets_.size(), 2); // operator Distributeddata Asset() - asset = proxy1.assets_[0]; + DistributedData::Asset asset = proxy1.assets_[0]; EXPECT_EQ(asset.version, 2); // operator "=" noexcept same asset case @@ -427,19 +427,19 @@ HWTEST_F(ValueProxyServiceTest, AssetOperator001, TestSize.Level0) { ValueProxy::Asset asset1 = DistributedDB::Asset { .version = 1, + .status = DistributedData::Asset::Status::STATUS_INSERT, .name = "Asset1", .uri = "uri1", .size = "1", .hash = "hash1", - .status = DistributedData::Asset::Status::STATUS_INSERT, }; ValueProxy::Asset asset2 = DistributedDB::Asset { .version = 2, + .status = DistributedData::Asset::Status::STATUS_NORMAL, .name = "Asset2", .uri = "uri2", .size = "2", .hash = "hash2", - .status = DistributedData::Asset::Status::STATUS_NORMAL, }; ValueProxy::Asset asset3 = asset1; DistributedData::Asset asset = asset3; diff --git a/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn b/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn index 971ab2721f389a154b8b3fea51fb2e5fdd954dd7..6ac317304aabb349a8f08a37283c9d21f49a8e01 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn @@ -17,10 +17,9 @@ config("module_public_config") { visibility = [ ":*" ] include_dirs = [ - "${data_service_path}/framework/include", - "${data_service_path}/framework/include/dfx", "${data_service_path}/adapter/include/communicator", - "${data_service_path}/adapter/include/account", + "${data_service_path}/service/matrix/include", + "${data_service_path}/service/permission/include", "${data_service_path}/service/udmf/lifecycle", "${data_service_path}/service/udmf/permission", "${data_service_path}/service/udmf/preprocess", @@ -28,13 +27,6 @@ config("module_public_config") { "${data_service_path}/service/udmf/utd", "${data_service_path}/service/udmf", "${data_service_path}/service/bootstrap/include", - "${kv_store_path}/interfaces/innerkits/distributeddata/include", - "${kv_store_path}/framework/libs/distributeddb/interfaces/include", - "${kv_store_common_path}", - "${udmf_path}/framework/common", - "${udmf_path}/interfaces/innerkits/common", - "${udmf_path}/interfaces/innerkits/data", - "${data_service_path}/adapter/account/src", ] } @@ -57,8 +49,8 @@ ohos_source_set("udmf_server") { "permission/uri_permission_manager.cpp", "preprocess/data_handler.cpp", "preprocess/preprocess_utils.cpp", + "preprocess/udmf_notifier_proxy.cpp", "store/runtime_store.cpp", - "store/store_account_observer.cpp", "store/store_cache.cpp", "udmf_service_impl.cpp", "udmf_service_stub.cpp", @@ -70,10 +62,12 @@ ohos_source_set("udmf_server") { "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Werror", "-Oz", - "-fstack-protector-strong", ] - deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service/permission:distributeddata_permit" + ] external_deps = [ "ability_base:zuri", @@ -83,11 +77,13 @@ ohos_source_set("udmf_server") { "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", "device_manager:devicemanagersdk", + "dfs_service:distributed_file_daemon_kit_inner", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", "hitrace:libhitracechain", "ipc:ipc_core", + "kv_store:datamgr_common", "kv_store:distributeddb", "udmf:udmf_client", "udmf:utd_client", @@ -95,7 +91,6 @@ ohos_source_set("udmf_server") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] 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 cbfdca07a431b4edd55fba26efc3e70081f1d8dc..e427c2e7381b6acb73a8973b4565cd4ef2fc2407 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_manager.cpp @@ -23,6 +23,9 @@ 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_PICKER), std::make_shared() }, + { UD_INTENTION_MAP.at(UD_INTENTION_MENU), std::make_shared() }, + { UD_INTENTION_MAP.at(UD_INTENTION_SYSTEM_SHARE), std::make_shared() }, { UD_INTENTION_MAP.at(UD_INTENTION_DATA_HUB), std::make_shared() } }; diff --git a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.cpp b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.cpp index cc3d88659c07bafb8a2561ee2afcf9dea85e2ae7..5651c916ac301678abb7efa758126ee48d03bdf8 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.cpp @@ -30,7 +30,7 @@ Status LifeCyclePolicy::OnGot(const UnifiedKey &key) ZLOGE("Get store failed:%{public}s", key.intention.c_str()); return E_DB_ERROR; } - if (store->Delete(key.key) != E_OK) { + if (store->Delete(UnifiedKey(key.key).GetKeyCommonPrefix()) != E_OK) { ZLOGE("Remove data failed:%{public}s", key.intention.c_str()); return E_DB_ERROR; } @@ -59,6 +59,8 @@ Status LifeCyclePolicy::OnTimeout(const std::string &intention) return E_DB_ERROR; } std::vector timeoutKeys; + Duration interval = INTERVAL; + CheckFileMangerIntention(intention, interval); auto status = GetTimeoutKeys(store, INTERVAL, timeoutKeys); if (status != E_OK) { ZLOGE("Timeout keys get failed"); @@ -92,10 +94,20 @@ Status LifeCyclePolicy::GetTimeoutKeys( } if (curTime > data.GetRuntime()->createTime + duration_cast(interval).count() || curTime < data.GetRuntime()->createTime) { - timeoutKeys.push_back(data.GetRuntime()->key.key); + timeoutKeys.push_back(UnifiedKey(data.GetRuntime()->key.key).GetKeyCommonPrefix()); } } return E_OK; } + +Status LifeCyclePolicy::CheckFileMangerIntention(const std::string &intention, Duration &interval) +{ + if (intention == UD_INTENTION_MAP.at(UD_INTENTION_SYSTEM_SHARE) || + intention == UD_INTENTION_MAP.at(UD_INTENTION_PICKER) || + intention == UD_INTENTION_MAP.at(UD_INTENTION_MENU)) { + interval = SYSTEM_SHARE_INTERVAL; + } + return E_OK; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.h b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.h index f7703e562be97760cb5218ca560c3afa4d2c8df4..2979965dc28df15da6b77a14d1929a02cdad4bf7 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.h @@ -23,6 +23,7 @@ class LifeCyclePolicy { public: using Duration = std::chrono::steady_clock::duration; static constexpr Duration INTERVAL = std::chrono::milliseconds(60 * 60 * 1000); + static constexpr Duration SYSTEM_SHARE_INTERVAL = std::chrono::milliseconds(24 * 60 * 60 * 1000); virtual ~LifeCyclePolicy() = default; virtual Status OnGot(const UnifiedKey &key); virtual Status OnStart(const std::string &intention); @@ -31,6 +32,7 @@ public: const std::shared_ptr &store, Duration interval, std::vector &timeoutKeys); private: + Status CheckFileMangerIntention(const std::string &intention, Duration &interval); static constexpr const char *DATA_PREFIX = "udmf://"; }; } // namespace UDMF diff --git a/datamgr_service/services/distributeddataservice/service/udmf/permission/checker_manager.h b/datamgr_service/services/distributeddataservice/service/udmf/permission/checker_manager.h index bb892e157e63ced2c99aecd70e846ffb9da65af2..72991aec285258845a761b3554cb636475c861bb 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/permission/checker_manager.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/permission/checker_manager.h @@ -24,7 +24,7 @@ namespace UDMF { class CheckerManager { public: struct CheckInfo { - uint32_t tokenId; + uint32_t tokenId {0}; }; class Checker { @@ -41,7 +41,7 @@ public: bool IsValid(const std::vector &privileges, const CheckInfo &info); private: - std::map checkers_; + std::map checkers_ {}; ConcurrentMap> getters_; }; } // namespace UDMF 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 1e7e1e904f6a21c37ed37727384c7c2bea06fdc0..a20b3e9442de1714a2d368a09859242ce46b04de 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 @@ -22,7 +22,7 @@ namespace OHOS { namespace UDMF { -constexpr const std::uint32_t GRANT_URI_PERMISSION_MAX_SIZE = 500; +constexpr const std::uint32_t GRANT_URI_PERMISSION_MAX_SIZE = 10000; UriPermissionManager &UriPermissionManager::GetInstance() { static UriPermissionManager instance; diff --git a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/data_handler.cpp b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/data_handler.cpp index d772d99983642dba33ddc6d12455c9b193260f7b..74c7d856a45906cffa868d00365f2f58eff492b1 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/data_handler.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/data_handler.cpp @@ -35,7 +35,7 @@ Status DataHandler::MarshalToEntries(const UnifiedData &unifiedData, std::vector std::vector udKeyBytes = { unifiedKey.begin(), unifiedKey.end() }; Entry entry = { udKeyBytes, runtimeBytes }; entries.emplace_back(entry); - std::string propsKey = unifiedData.GetRuntime()->key.GetPropertyKey() + UD_KEY_PROPERTIES_SEPARATOR; + std::string propsKey = unifiedData.GetRuntime()->key.GetKeyCommonPrefix() + UD_KEY_PROPERTIES_SEPARATOR; std::vector propsBytes; auto propsTlv = TLVObject(propsBytes); if (!TLVUtil::Writing(*unifiedData.GetProperties(), propsTlv, TAG::TAG_PROPERTIES)) { @@ -86,7 +86,7 @@ Status DataHandler::UnmarshalEntryItem(UnifiedData &unifiedData, const std::vect continue; } auto isStartWithKey = keyStr.find(key) == 0; - std::string propsKey = UnifiedKey(key).GetPropertyKey() + UD_KEY_PROPERTIES_SEPARATOR; + std::string propsKey = UnifiedKey(key).GetKeyCommonPrefix() + UD_KEY_PROPERTIES_SEPARATOR; if (!isStartWithKey && (keyStr == propsKey)) { std::shared_ptr properties; if (!TLVUtil::ReadTlv(properties, data, TAG::TAG_PROPERTIES)) { 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 ab49f959c4e8a8f4710b88e29640155fbbc04eca..597cc9a7a7bca939e2e6d1b25bd5ed3364033347 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.cpp @@ -19,16 +19,21 @@ #include #include +#include "bundle_info.h" #include "dds_trace.h" #include "udmf_radar_reporter.h" #include "accesstoken_kit.h" +#include "checker/checker_manager.h" #include "device_manager_adapter.h" +#include "file_mount_manager.h" +#include "iservice_registry.h" #include "log_print.h" +#include "system_ability_definition.h" #include "udmf_radar_reporter.h" #include "udmf_utils.h" -#include "remote_file_share.h" #include "utils/crypto.h" #include "uri_permission_manager_client.h" +#include "ipc_skeleton.h" namespace OHOS { namespace UDMF { static constexpr int ID_LEN = 32; @@ -51,18 +56,24 @@ using namespace Security::AccessToken; using namespace OHOS::AppFileService::ModuleRemoteFileShare; using namespace RadarReporter; -int32_t PreProcessUtils::RuntimeDataImputation(UnifiedData &data, CustomOption &option) +int32_t PreProcessUtils::FillRuntimeInfo(UnifiedData &data, CustomOption &option) { auto it = UD_INTENTION_MAP.find(option.intention); if (it == UD_INTENTION_MAP.end()) { return E_ERROR; } std::string bundleName; - GetHapBundleNameByToken(option.tokenId, bundleName); + std::string specificBundleName; + if (!GetSpecificBundleNameByTokenId(option.tokenId, specificBundleName, bundleName)) { + ZLOGE("GetSpecificBundleNameByTokenId failed, tokenid:%{public}u", option.tokenId); + return E_ERROR; + } std::string intention = it->second; - UnifiedKey key(intention, bundleName, GenerateId()); + UnifiedKey key(intention, specificBundleName, GenerateId()); Privilege privilege; privilege.tokenId = option.tokenId; + std::string appId = DistributedData::CheckerManager::GetInstance().GetAppId( + { IPCSkeleton::GetCallingUid(), option.tokenId, bundleName }); Runtime runtime; runtime.key = key; runtime.privileges.emplace_back(privilege); @@ -72,7 +83,9 @@ int32_t PreProcessUtils::RuntimeDataImputation(UnifiedData &data, CustomOption & runtime.deviceId = GetLocalDeviceId(); runtime.recordTotalNum = static_cast(data.GetRecords().size()); runtime.tokenId = option.tokenId; - runtime.sdkVersion = data.GetSdkVersion(); + runtime.sdkVersion = GetSdkVersionByToken(option.tokenId); + runtime.visibility = option.visibility; + runtime.appId = appId; data.SetRuntime(runtime); return E_OK; } @@ -174,18 +187,6 @@ void PreProcessUtils::SetRemoteData(UnifiedData &data) }); } -bool PreProcessUtils::IsFileType(std::shared_ptr record) -{ - if (record == nullptr) { - return false; - } - if (!std::holds_alternative>(record->GetOriginValue())) { - return false; - } - auto obj = std::get>(record->GetOriginValue()); - return obj->value_.find(ORI_URI) != obj->value_.end(); -} - int32_t PreProcessUtils::SetRemoteUri(uint32_t tokenId, UnifiedData &data) { std::vector uris; @@ -232,9 +233,9 @@ int32_t PreProcessUtils::GetDfsUrisFromLocal(const std::vector &uri DdsTrace trace( std::string(TAG) + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), - BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::IDLE, BizState::DFX_BEGIN); + BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::IDLE); std::unordered_map dfsUris; - int ret = RemoteFileShare::GetDfsUrisFromLocal(uris, userId, dfsUris); + int32_t ret = Storage::DistributedFile::FileMountManager::GetDfsUrisDirFromLocal(uris, userId, dfsUris); if (ret != 0 || dfsUris.empty()) { RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::FAILED, E_FS_ERROR, BizState::DFX_END); @@ -266,7 +267,7 @@ int32_t PreProcessUtils::GetDfsUrisFromLocal(const std::vector &uri }); } RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), - BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::SUCCESS, BizState::DFX_END); + BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::SUCCESS); return E_OK; } @@ -317,18 +318,30 @@ void PreProcessUtils::ProcessFileType(std::vector { for (auto record : records) { if (record == nullptr) { + ZLOGW("Record is empty!"); continue; } - if (!PreProcessUtils::IsFileType(record)) { + auto entries = record->GetEntries(); + if (entries == nullptr) { + ZLOGW("GetEntries returns empty!"); continue; } - auto obj = std::get>(record->GetOriginValue()); + auto entry = entries->find(GENERAL_FILE_URI); + if (entry == entries->end()) { + continue; + } + auto value = entry->second; + if (!std::holds_alternative>(value)) { + continue; + } + auto obj = std::get>(value); if (obj == nullptr) { ZLOGE("ValueType is not Object, Not convert to remote uri!"); continue; } - if (!callback(obj)) { - continue; + std::string dataType; + if (obj->GetValue(UNIFORM_DATA_TYPE, dataType) && dataType == GENERAL_FILE_URI) { + callback(obj); } } } @@ -338,7 +351,7 @@ void PreProcessUtils::ProcessRecord(std::shared_ptr record, uint3 { record->ComputeUris([&uris, &isLocal, &tokenId] (UriInfo &uriInfo) { std::string newUriStr = ""; - if (isLocal) { + if (isLocal && uriInfo.authUri.empty()) { Uri tmpUri(uriInfo.oriUri); std::string path = tmpUri.GetPath(); std::string bundleName; @@ -354,7 +367,7 @@ void PreProcessUtils::ProcessRecord(std::shared_ptr record, uint3 } uriInfo.authUri = newUriStr; } else { - newUriStr = uriInfo.dfsUri; + newUriStr = isLocal ? uriInfo.authUri : uriInfo.dfsUri; } Uri uri(newUriStr); if (uri.GetAuthority().empty()) { @@ -425,7 +438,7 @@ bool PreProcessUtils::GetDetailsFromUData(const UnifiedData &data, UDDetails &de { auto records = data.GetRecords(); if (records.size() != TEMP_UDATA_RECORD_SIZE) { - ZLOGE("Records size error.size:%{public}zu", records.size()); + ZLOGI("Records size:%{public}zu", records.size()); return false; } if (records[0] == nullptr) { @@ -471,5 +484,80 @@ Status PreProcessUtils::GetSummaryFromDetails(const UDDetails &details, Summary } return E_OK; } + +std::string PreProcessUtils::GetSdkVersionByToken(uint32_t tokenId) +{ + if (Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId) != + Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) { + ZLOGE("Caller is not application, tokenid is %{public}u", tokenId); + return ""; + } + Security::AccessToken::HapTokenInfo hapTokenInfo; + auto ret = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, hapTokenInfo); + if (ret != 0) { + ZLOGE("GetHapTokenInfo fail, tokenid is %{public}u, ret is %{public}d.", tokenId, ret); + return ""; + } + return std::to_string(hapTokenInfo.apiVersion); +} + +bool PreProcessUtils::GetSpecificBundleNameByTokenId(uint32_t tokenId, std::string &specificBundleName, + std::string &bundleName) +{ + Security::AccessToken::HapTokenInfo hapInfo; + if (Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo) + == Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) { + bundleName = hapInfo.bundleName; + return GetSpecificBundleName(hapInfo.bundleName, hapInfo.instIndex, specificBundleName); + } + if (UTILS::IsTokenNative()) { + ZLOGI("TypeATokenTypeEnum is TOKEN_NATIVE"); + std::string processName; + if (GetNativeProcessNameByToken(tokenId, processName)) { + bundleName = std::move(processName); + specificBundleName = bundleName; + return true; + } + } + ZLOGE("Get bundle name faild, tokenid:%{public}u", tokenId); + return false; +} + +sptr PreProcessUtils::GetBundleMgr() +{ + auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (samgrProxy == nullptr) { + ZLOGE("Failed to get system ability mgr."); + return nullptr; + } + auto bundleMgrProxy = samgrProxy->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (bundleMgrProxy == nullptr) { + ZLOGE("Failed to Get BMS SA."); + return nullptr; + } + auto bundleManager = iface_cast(bundleMgrProxy); + if (bundleManager == nullptr) { + ZLOGE("Failed to get bundle manager"); + return nullptr; + } + return bundleManager; +} + +bool PreProcessUtils::GetSpecificBundleName(const std::string &bundleName, int32_t appIndex, + std::string &specificBundleName) +{ + auto bundleManager = GetBundleMgr(); + if (bundleManager == nullptr) { + ZLOGE("Failed to get bundle manager, bundleName:%{public}s, appIndex:%{public}d", bundleName.c_str(), appIndex); + return false; + } + auto ret = bundleManager->GetDirByBundleNameAndAppIndex(bundleName, appIndex, specificBundleName); + if (ret != ERR_OK) { + ZLOGE("GetDirByBundleNameAndAppIndex failed, ret:%{public}d, bundleName:%{public}s, appIndex:%{public}d", + ret, bundleName.c_str(), appIndex); + 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 6d613007813bcf338963c5c1b332cd04960424a6..e378592c8d9685eea64fe07acf61687200fb5008 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.h @@ -15,13 +15,14 @@ #ifndef UDMF_PREPROCESS_UTILS_H #define UDMF_PREPROCESS_UTILS_H +#include "bundlemgr/bundle_mgr_proxy.h" #include "unified_data.h" namespace OHOS { namespace UDMF { class PreProcessUtils { public: - static int32_t RuntimeDataImputation(UnifiedData &data, CustomOption &option); + static int32_t FillRuntimeInfo(UnifiedData &data, CustomOption &option); static std::string GenerateId(); static time_t GetTimestamp(); static int32_t GetHapUidByToken(uint32_t tokenId, int &userId); @@ -42,10 +43,14 @@ public: static void SetRecordUid(UnifiedData &data); static bool GetDetailsFromUData(const UnifiedData &data, UDDetails &details); static Status GetSummaryFromDetails(const UDDetails &details, Summary &summary); + static bool GetSpecificBundleNameByTokenId(uint32_t tokenId, std::string &specificBundleName, + std::string &bundleName); + static sptr GetBundleMgr(); private: static bool CheckUriAuthorization(const std::vector& uris, uint32_t tokenId); static int32_t GetDfsUrisFromLocal(const std::vector &uris, int32_t userId, UnifiedData &data); - static bool IsFileType(std::shared_ptr record); + static std::string GetSdkVersionByToken(uint32_t tokenId); + static bool GetSpecificBundleName(const std::string &bundleName, int32_t appIndex, std::string &specificBundleName); }; } // namespace UDMF } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/udmf_notifier_proxy.cpp b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/udmf_notifier_proxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6bd4b72f3869c05b028d727f19211e7ee280d2a2 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/udmf_notifier_proxy.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2025 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 "UDMFNotifierProxy" +#include "udmf_notifier_proxy.h" + +#include "distributeddata_udmf_ipc_interface_code.h" +#include "log_print.h" +#include "message_parcel.h" +#include "message_option.h" +#include "udmf_types_util.h" +#include "utils/anonymous.h" + +namespace OHOS { +namespace UDMF { +#define IPC_SEND(code, reply, ...) \ + ({ \ + int32_t ipcStatus = E_OK; \ + do { \ + MessageParcel request; \ + if (!request.WriteInterfaceToken(GetDescriptor())) { \ + ipcStatus = E_WRITE_PARCEL_ERROR; \ + break; \ + } \ + if (!ITypesUtil::Marshal(request, ##__VA_ARGS__)) { \ + ipcStatus = E_WRITE_PARCEL_ERROR; \ + break; \ + } \ + MessageOption option; \ + auto result = remote_->SendRequest((code), request, reply, option); \ + if (result != 0) { \ + ZLOGE("SendRequest failed, result = %{public}d!", result); \ + ipcStatus = E_IPC; \ + break; \ + } \ + ITypesUtil::Unmarshal(reply, ipcStatus); \ + } while (0); \ + ipcStatus; \ + }) + +UdmfNotifierProxy::UdmfNotifierProxy(const sptr &impl) + : IRemoteProxy(impl) +{ + remote_ = Remote(); +} + +void UdmfNotifierProxy::HandleDelayObserver(const std::string &key, const DataLoadInfo &dataLoadInfo) +{ + MessageParcel reply; + int32_t status = + IPC_SEND(static_cast(UdmfNotifierInterfaceCode::HANDLE_DELAY_OBSERVER), reply, key, dataLoadInfo); + if (status != E_OK) { + ZLOGE("status:%{public}d", status); + } +} + +DelayDataCallbackProxy::DelayDataCallbackProxy(const sptr &impl) + : IRemoteProxy(impl) +{ + remote_ = Remote(); +} + +void DelayDataCallbackProxy::DelayDataCallback(const std::string &key, const UnifiedData &data) +{ + MessageParcel reply; + int32_t status = + IPC_SEND(static_cast(UdmfNotifierInterfaceCode::HANDLE_DELAY_DATA), reply, key, data); + if (status != E_OK) { + ZLOGE("status:%{public}d", status); + } +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/udmf_notifier_proxy.h b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/udmf_notifier_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..782ed38cb1c21bddda356828c1b96eb39f99308c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/udmf_notifier_proxy.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 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 UDMF_NOTIFIER_PROXY_H +#define UDMF_NOTIFIER_PROXY_H + +#include "iremote_broker.h" +#include "iremote_proxy.h" +#include "iudmf_notifier.h" + +namespace OHOS { +namespace UDMF { +class UdmfNotifierProxy : public IRemoteProxy { +public: + explicit UdmfNotifierProxy(const sptr &impl); + ~UdmfNotifierProxy() = default; + void HandleDelayObserver(const std::string &key, const DataLoadInfo &dataLoadInfo) override; + +private: + static inline BrokerDelegator delegator_; + sptr remote_; +}; + +class DelayDataCallbackProxy : public IRemoteProxy { +public: + explicit DelayDataCallbackProxy(const sptr &impl); + ~DelayDataCallbackProxy() = default; + void DelayDataCallback(const std::string &key, const UnifiedData &data) override; + +private: + static inline BrokerDelegator delegator_; + sptr remote_; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_NOTIFIER_PROXY_H \ No newline at end of file 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 d8742dc75e945c22ee59cecbd8e4008ff02146af..f55d72d74b4a0b8c6af883bc1736f1d121b295fe 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp @@ -16,8 +16,6 @@ #include "runtime_store.h" -#include -#include #include "data_handler.h" #include "log_print.h" #include "ipc_skeleton.h" @@ -26,6 +24,7 @@ #include "account/account_delegate.h" #include "metadata/meta_data_manager.h" #include "metadata/appid_meta_data.h" +#include "metadata/store_meta_data.h" #include "device_manager_adapter.h" #include "bootstrap.h" #include "directory/directory_manager.h" @@ -36,6 +35,7 @@ namespace OHOS { namespace UDMF { using namespace RadarReporter; using namespace DistributedDB; +using namespace OHOS::DistributedData; using Anonymous = OHOS::DistributedData::Anonymous; using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; constexpr const char *SUMMARY_SUFIX = "#summary"; @@ -60,7 +60,7 @@ Status RuntimeStore::PutLocal(const std::string &key, const std::string &value) auto status = kvStore_->PutLocal(keyBytes, valueBytes); if (status != DBStatus::OK) { ZLOGE("KvStore PutLocal failed, status: %{public}d.", status); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } return E_OK; } @@ -73,7 +73,7 @@ Status RuntimeStore::GetLocal(const std::string &key, std::string &value) DBStatus status = kvStore_->GetLocal(keyBytes, valueBytes); if (status != DBStatus::OK && status != DBStatus::NOT_FOUND) { ZLOGE("GetLocal entry failed, key: %{public}s.", key.c_str()); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } if (valueBytes.empty()) { ZLOGW("GetLocal entry is empty, key: %{public}s", key.c_str()); @@ -91,7 +91,7 @@ Status RuntimeStore::DeleteLocal(const std::string &key) DBStatus status = kvStore_->DeleteLocal(keyBytes); if (status != DBStatus::OK && status != DBStatus::NOT_FOUND) { ZLOGE("DeleteLocal failed, key: %{public}s.", key.c_str()); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } return E_OK; } @@ -115,9 +115,10 @@ Status RuntimeStore::Get(const std::string &key, UnifiedData &unifiedData) { UpdateTime(); std::vector entries; - if (GetEntries(UnifiedKey(key).GetPropertyKey(), entries) != E_OK) { + auto status = GetEntries(UnifiedKey(key).GetKeyCommonPrefix(), entries); + if (status != E_OK) { ZLOGE("GetEntries failed, dataPrefix: %{public}s.", key.c_str()); - return E_DB_ERROR; + return status; } if (entries.empty()) { ZLOGW("entries is empty, dataPrefix: %{public}s", key.c_str()); @@ -137,7 +138,7 @@ Status RuntimeStore::PutSummary(const UnifiedData &data, std::vector &ent UnifiedDataHelper::GetSummary(data, summary); } - auto propertyKey = data.GetRuntime()->key.GetPropertyKey(); + auto propertyKey = data.GetRuntime()->key.GetKeyCommonPrefix(); Value value; auto status = DataHandler::MarshalToEntries(summary, value, TAG::TAG_SUMMARY); if (status != E_OK) { @@ -149,19 +150,34 @@ Status RuntimeStore::PutSummary(const UnifiedData &data, std::vector &ent return E_OK; } +Status RuntimeStore::PutSummary(UnifiedKey &key, const Summary &summary) +{ + auto propertyKey = key.GetKeyCommonPrefix(); + Value value; + auto status = DataHandler::MarshalToEntries(summary, value, TAG::TAG_SUMMARY); + if (status != E_OK) { + ZLOGE("Marshal summary failed, key: %{public}s, status:%{public}d", propertyKey.c_str(), status); + return status; + } + auto summaryKey = propertyKey + SUMMARY_SUFIX; + std::vector entries{{{summaryKey.begin(), summaryKey.end()}, value}}; + return PutEntries(std::move(entries)); +} + Status RuntimeStore::GetSummary(UnifiedKey &key, Summary &summary) { UpdateTime(); Value value; - auto summaryKey = key.GetPropertyKey() + SUMMARY_SUFIX; + auto summaryKey = key.GetKeyCommonPrefix() + SUMMARY_SUFIX; auto res = kvStore_->Get({summaryKey.begin(), summaryKey.end()}, value); if (res != OK || value.empty()) { ZLOGW("Get stored summary failed, key: %{public}s, status:%{public}d", summaryKey.c_str(), res); UnifiedData unifiedData; auto udKey = key.GetUnifiedKey(); - if (Get(udKey, unifiedData) != E_OK) { + auto status = Get(udKey, unifiedData); + if (status != E_OK) { ZLOGE("Get unified data failed, key: %{public}s", udKey.c_str()); - return E_DB_ERROR; + return status; } UDDetails details {}; if (PreProcessUtils::GetDetailsFromUData(unifiedData, details)) { @@ -190,7 +206,7 @@ Status RuntimeStore::PutRuntime(const std::string &key, const Runtime &runtime) auto res = kvStore_->Put({key.begin(), key.end()}, value); if (res != OK) { ZLOGE("Put failed, key:%{public}s, status:%{public}d", key.c_str(), res); - return E_DB_ERROR; + return MarkWhenCorrupted(res); } return E_OK; } @@ -200,9 +216,13 @@ Status RuntimeStore::GetRuntime(const std::string &key, Runtime &runtime) UpdateTime(); Value value; auto res = kvStore_->Get({key.begin(), key.end()}, value); + if (res == NOT_FOUND) { + ZLOGW("Runtime not found, key: %{public}s", key.c_str()); + return E_NOT_FOUND; + } if (res != OK || value.empty()) { ZLOGE("Get failed, key: %{public}s, status:%{public}d", key.c_str(), res); - return E_DB_ERROR; + return MarkWhenCorrupted(res); } auto status = DataHandler::UnmarshalEntries(value, runtime, TAG::TAG_RUNTIME); if (status != E_OK) { @@ -215,14 +235,16 @@ Status RuntimeStore::GetRuntime(const std::string &key, Runtime &runtime) Status RuntimeStore::Update(const UnifiedData &unifiedData) { std::string key = unifiedData.GetRuntime()->key.key; - if (Delete(key) != E_OK) { + auto status = Delete(UnifiedKey(key).GetKeyCommonPrefix()); + if (status != E_OK) { UpdateTime(); ZLOGE("Delete unified data failed, dataPrefix: %{public}s.", key.c_str()); - return E_DB_ERROR; + return status; } - if (Put(unifiedData) != E_OK) { + status = Put(unifiedData); + if (status != E_OK) { ZLOGE("Update unified data failed, dataPrefix: %{public}s.", key.c_str()); - return E_DB_ERROR; + return status; } return E_OK; } @@ -230,9 +252,10 @@ Status RuntimeStore::Update(const UnifiedData &unifiedData) Status RuntimeStore::Delete(const std::string &key) { std::vector entries; - if (GetEntries(key, entries) != E_OK) { + auto status = GetEntries(key, entries); + if (status != E_OK) { ZLOGE("GetEntries failed, dataPrefix: %{public}s.", key.c_str()); - return E_DB_ERROR; + return status; } if (entries.empty()) { ZLOGD("entries is empty."); @@ -364,7 +387,7 @@ Status RuntimeStore::GetBatchData(const std::string &dataPrefix, std::vectorCloseKvStore(kvStore_.get()); -} - bool RuntimeStore::Init() { if (!SaveMetaData()) { // get keyinfo about create db fail. @@ -417,18 +435,17 @@ bool RuntimeStore::Init() }); if (status != DBStatus::OK) { ZLOGE("GetKvStore fail, status: %{public}d.", static_cast(status)); + if (status == INVALID_PASSWD_OR_CORRUPTED_DB) { + status = delegateManager_->DeleteKvStore(storeId_); + if (status != DBStatus::OK) { + ZLOGE("DeleteKvStore fail, status: %{public}d.", static_cast(status)); + } + } return false; } - auto release = [this](KvStoreNbDelegate *delegate) { - ZLOGI("Release runtime kvStore."); - if (delegate == nullptr) { - return; - } - auto retStatus = delegateManager_->CloseKvStore(delegate); - if (retStatus != DBStatus::OK) { - ZLOGE("CloseKvStore fail, status: %{public}d.", static_cast(retStatus)); - } + ZLOGI("Release runtime kvStore, db is corrupted: %{public}d.", isCorrupted_); + ReleaseStore(delegate); }; kvStore_ = std::shared_ptr(delegate, release); uint32_t pragmData = 16 * 1024 * 1024; @@ -459,11 +476,11 @@ bool RuntimeStore::BuildMetaDataParam(DistributedData::StoreMetaData &metaData) metaData.account = DistributedData::AccountDelegate::GetInstance()->GetCurrentAccountId(); metaData.tokenId = token; metaData.securityLevel = DistributedKv::SecurityLevel::S1; - metaData.area = DistributedKv::Area::EL1; - metaData.uid = static_cast(getuid()); + metaData.area = DistributedKv::Area::EL2; + metaData.uid = static_cast(IPCSkeleton::GetCallingUid()); metaData.storeType = DistributedKv::KvStoreType::SINGLE_VERSION; metaData.dataType = DistributedKv::DataType::TYPE_DYNAMICAL; - metaData.dataDir = DistributedData::DirectoryManager::GetInstance().GetStorePath(metaData); + metaData.authType = DistributedKv::AuthType::IDENTICAL_ACCOUNT; return true; } @@ -481,24 +498,26 @@ bool RuntimeStore::SaveMetaData() ZLOGE("QueryForegroundUserId failed."); return false; } - - saveMeta.dataDir.append("/").append(std::to_string(foregroundUserId)); + saveMeta.user = std::to_string(foregroundUserId); + saveMeta.dataDir = DistributedData::DirectoryManager::GetInstance().GetStorePath(saveMeta); if (!DistributedData::DirectoryManager::GetInstance().CreateDirectory(saveMeta.dataDir)) { - ZLOGE("Create directory error"); + ZLOGE("Create directory error, dataDir: %{public}s.", Anonymous::Change(saveMeta.dataDir).c_str()); return false; } - SetDelegateManager(saveMeta.dataDir, saveMeta.appId, saveMeta.user, std::to_string(foregroundUserId)); + SetDelegateManager(saveMeta.dataDir, saveMeta.appId, saveMeta.user); DistributedData::StoreMetaData loadLocal; DistributedData::StoreMetaData syncMeta; if (DistributedData::MetaDataManager::GetInstance().LoadMeta(saveMeta.GetKey(), loadLocal, true) && - DistributedData::MetaDataManager::GetInstance().LoadMeta(saveMeta.GetKey(), syncMeta, false)) { - ZLOGD("Meta data is already saved."); - return true; + DistributedData::MetaDataManager::GetInstance().LoadMeta(saveMeta.GetKeyLocalWithoutPath(), syncMeta, false)) { + if (loadLocal == saveMeta && syncMeta == saveMeta) { + ZLOGD("Meta data is already saved."); + return true; + } } - auto saved = DistributedData::MetaDataManager::GetInstance().SaveMeta(saveMeta.GetKey(), saveMeta) && + auto saved = DistributedData::MetaDataManager::GetInstance().SaveMeta(saveMeta.GetKeyWithoutPath(), saveMeta) && DistributedData::MetaDataManager::GetInstance().SaveMeta(saveMeta.GetKey(), saveMeta, true); if (!saved) { ZLOGE("SaveMeta failed, saveMeta.key:%{public}s", saveMeta.GetKey().c_str()); @@ -515,12 +534,32 @@ bool RuntimeStore::SaveMetaData() return true; } -void RuntimeStore::SetDelegateManager(const std::string &dataDir, const std::string &appId, const std::string &userId, - const std::string &subUser) +void RuntimeStore::ReleaseStore(DistributedDB::KvStoreNbDelegate *delegate) +{ + if (delegate == nullptr) { + return; + } + auto retStatus = delegateManager_->CloseKvStore(delegate); + if (retStatus != DBStatus::OK) { + ZLOGE("CloseKvStore fail, status: %{public}d.", static_cast(retStatus)); + return; + } + if (isCorrupted_) { + retStatus = delegateManager_->DeleteKvStore(storeId_); + if (retStatus != DBStatus::OK) { + ZLOGE("DeleteKvStore fail, status: %{public}d.", static_cast(retStatus)); + } + } +} + +void RuntimeStore::SetDelegateManager(const std::string &dataDir, const std::string &appId, const std::string &userId) { - delegateManager_ = std::make_shared(appId, userId, subUser); + delegateManager_ = std::make_shared(appId, userId); DistributedDB::KvStoreConfig kvStoreConfig { dataDir }; - delegateManager_->SetKvStoreConfig(kvStoreConfig); + auto status = delegateManager_->SetKvStoreConfig(kvStoreConfig); + if (status != DBStatus::OK) { + ZLOGE("SetKvStoreConfig failed, status: %{public}d.", status); + } } Status RuntimeStore::GetEntries(const std::string &dataPrefix, std::vector &entries) @@ -532,7 +571,7 @@ Status RuntimeStore::GetEntries(const std::string &dataPrefix, std::vectorGetEntries(dbQuery, entries); if (status != DBStatus::OK && status != DBStatus::NOT_FOUND) { ZLOGE("KvStore getEntries failed, status: %{public}d.", static_cast(status)); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } return E_OK; } @@ -542,7 +581,7 @@ Status RuntimeStore::PutEntries(const std::vector &entries) DBStatus status = kvStore_->PutBatch(entries); if (status != DBStatus::OK) { ZLOGE("putBatch failed, status: %{public}d.", status); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } return E_OK; } @@ -552,10 +591,19 @@ Status RuntimeStore::DeleteEntries(const std::vector &keys) DBStatus status = kvStore_->DeleteBatch(keys); if (status != DBStatus::OK) { ZLOGE("deleteBatch failed, status: %{public}d.", status); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } return E_OK; } +Status RuntimeStore::MarkWhenCorrupted(DistributedDB::DBStatus status) +{ + if (status == INVALID_PASSWD_OR_CORRUPTED_DB) { + ZLOGE("Kv database corrupted"); + isCorrupted_ = true; + return E_DB_CORRUPTED; + } + return E_DB_ERROR; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file 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 f195eba38ca7f25c68ce130479929cdce136a35d..75a8a89bf5beba9ccb7c102dc26ceb41b6fd0b90 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.h @@ -43,7 +43,7 @@ public: Status DeleteLocal(const std::string &key) override; Status PutRuntime(const std::string &key, const Runtime &runtime) override; Status GetRuntime(const std::string &key, Runtime &runtime) override; - void Close() override; + Status PutSummary(UnifiedKey &key, const Summary &summary) override; bool Init() override; private: @@ -53,8 +53,7 @@ private: std::shared_ptr delegateManager_ = nullptr; std::shared_ptr kvStore_; std::string storeId_; - void SetDelegateManager(const std::string &dataDir, const std::string &appId, const std::string &userId, - const std::string &subUser); + void SetDelegateManager(const std::string &dataDir, const std::string &appId, const std::string &userId); bool SaveMetaData(); Status GetEntries(const std::string &dataPrefix, std::vector &entries); Status PutEntries(const std::vector &entries); @@ -65,6 +64,10 @@ private: void NotifySyncProcss(const DevSyncProcessMap &processMap, ProcessCallback callback, const DevNameMap &deviceNameMap); Status PutSummary(const UnifiedData &data, std::vector &entries); + Status MarkWhenCorrupted(DistributedDB::DBStatus status); + void ReleaseStore(DistributedDB::KvStoreNbDelegate *delegate); + + bool isCorrupted_ = false; }; } // 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 1c54e65d0d3116ad94ac037d8ba24e75d22b81b0..2124e08a6e30db8e8d8d20e63a7f2b7a79caf8ca 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/store.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/store.h @@ -43,8 +43,8 @@ public: virtual Status DeleteLocal(const std::string &key) = 0; virtual Status PutRuntime(const std::string &key, const Runtime &runtime) = 0; virtual Status GetRuntime(const std::string &key, Runtime &runtime) = 0; + virtual Status PutSummary(UnifiedKey &key, const Summary &summary) = 0; virtual bool Init() = 0; - virtual void Close() = 0; bool operator<(const Time &time) const { 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 deleted file mode 100644 index 9085a9b5aee06f58ef809b6a6068f4457a4a36bb..0000000000000000000000000000000000000000 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.cpp +++ /dev/null @@ -1,47 +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. - */ -#define LOG_TAG "RuntimeStoreAccountObserver" - -#include "store_account_observer.h" -#include "log_print.h" -#include "directory/directory_manager.h" -#include "bootstrap.h" -#include "ipc_skeleton.h" - -namespace OHOS { -namespace UDMF { -using namespace DistributedKv; -using namespace DistributedData; -void RuntimeStoreAccountObserver::OnAccountChanged(const AccountEventInfo &eventInfo, int32_t timeout) -{ - ZLOGI("account event begin. status is %{public}d.", eventInfo.status); - if (eventInfo.status == 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_cache.cpp b/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp index f539591816f4a8375fbb66f8784206081340878f..00fb5c08913143c638ea041525c2cae802c06b53 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp @@ -38,15 +38,13 @@ std::shared_ptr StoreCache::GetStore(std::string intention) } std::string key = intention; key.append(std::to_string(foregroundUserId)); - stores_.Compute(key, [&store, intention](const auto &key, std::shared_ptr &storePtr) -> bool { if (storePtr != nullptr) { store = storePtr; return true; } - if (intention == UD_INTENTION_MAP.at(UD_INTENTION_DRAG) - || intention == UD_INTENTION_MAP.at(UD_INTENTION_DATA_HUB)) { + if (IsValidIntention(intention)) { storePtr = std::make_shared(intention); if (!storePtr->Init()) { ZLOGE("Init runtime store failed."); @@ -57,10 +55,9 @@ std::shared_ptr StoreCache::GetStore(std::string intention) } return false; }); - std::unique_lock lock(taskMutex_); if (taskId_ == ExecutorPool::INVALID_TASK_ID && executorPool_ != nullptr) { - taskId_ = executorPool_->Schedule(std::chrono::minutes(INTERVAL), std::bind(&StoreCache::GarbageCollect, this)); + taskId_ = executorPool_->Schedule(std::chrono::minutes(INTERVAL), [this]() { this->GarbageCollect(); }); } return store; } @@ -78,7 +75,7 @@ void StoreCache::GarbageCollect() std::unique_lock lock(taskMutex_); if (!stores_.Empty() && executorPool_ != nullptr) { ZLOGD("GarbageCollect, stores size:%{public}zu", stores_.Size()); - taskId_ = executorPool_->Schedule(std::chrono::minutes(INTERVAL), std::bind(&StoreCache::GarbageCollect, this)); + taskId_ = executorPool_->Schedule(std::chrono::minutes(INTERVAL), [this]() { this->GarbageCollect(); }); } else { taskId_ = ExecutorPool::INVALID_TASK_ID; } @@ -94,5 +91,23 @@ void StoreCache::CloseStores() ZLOGI("CloseStores, stores size:%{public}zu", stores_.Size()); stores_.Clear(); } + +void StoreCache::RemoveStore(const std::string &intention) +{ + ZLOGI("RemoveStore, intention:%{public}s", intention.c_str()); + int foregroundUserId = 0; + if (!DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId)) { + ZLOGE("QueryForegroundUserId failed."); + return; + } + std::string key = intention; + key.append(std::to_string(foregroundUserId)); + stores_.Erase(key); +} + +bool StoreCache::IsValidIntention(const std::string &intention) +{ + return UnifiedDataUtils::GetIntentionByString(intention) != UD_INTENTION_BUTT; +} } // namespace UDMF } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.h b/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.h index fd052949c282fa5d5ef26ee91fa7efe33456043a..10ec3e3519a1ae7818b4fe3e4696cbef9b401396 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.h @@ -28,6 +28,7 @@ public: static StoreCache &GetInstance(); void SetThreadPool(std::shared_ptr executors); void CloseStores(); + void RemoveStore(const std::string &intention); private: StoreCache() {} @@ -38,6 +39,7 @@ private: StoreCache &operator=(const StoreCache &obj) = delete; void GarbageCollect(); + static bool IsValidIntention(const std::string &intention); ConcurrentMap> stores_; std::mutex taskMutex_; 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 acd9857b4461a99f93c6918d28a58b8e56f857d7..36e4deba58ef0d86f6020e2ab934f2999782057d 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp @@ -21,28 +21,35 @@ #include "tokenid_kit.h" #include "accesstoken_kit.h" +#include "account/account_delegate.h" #include "bootstrap.h" #include "bundle_info.h" #include "bundlemgr/bundle_mgr_proxy.h" +#include "checker/checker_manager.h" #include "checker_manager.h" #include "device_manager_adapter.h" +#include "device_matrix.h" #include "iservice_registry.h" #include "lifecycle/lifecycle_manager.h" #include "log_print.h" +#include "metadata/capability_meta_data.h" #include "metadata/store_meta_data.h" #include "metadata/meta_data_manager.h" #include "preprocess_utils.h" #include "dfx/reporter.h" -#include "store_account_observer.h" #include "system_ability_definition.h" #include "uri_permission_manager.h" #include "udmf_radar_reporter.h" +#include "udmf_utils.h" #include "unified_data_helper.h" #include "utils/anonymous.h" +#include "permission_validator.h" namespace OHOS { namespace UDMF { using namespace Security::AccessToken; +using namespace OHOS::DistributedHardware; +using namespace OHOS::DistributedData; using FeatureSystem = DistributedData::FeatureSystem; using UdmfBehaviourMsg = OHOS::DistributedDataDfx::UdmfBehaviourMsg; using Reporter = OHOS::DistributedDataDfx::Reporter; @@ -59,6 +66,7 @@ constexpr const char *DEVICE_2IN1_TAG = "2in1"; constexpr const char *DEVICE_PHONE_TAG = "phone"; constexpr const char *DEVICE_DEFAULT_TAG = "default"; constexpr const char *HAP_LIST[] = {"com.ohos.pasteboarddialog"}; +constexpr uint32_t FOUNDATION_UID = 5523; __attribute__((used)) UdmfServiceImpl::Factory UdmfServiceImpl::factory_; UdmfServiceImpl::Factory::Factory() { @@ -69,8 +77,6 @@ UdmfServiceImpl::Factory::Factory() } return product_; }, FeatureSystem::BIND_NOW); - auto observer = std::make_shared(); - DistributedData::AccountDelegate::GetInstance()->Subscribe(observer); } UdmfServiceImpl::Factory::~Factory() @@ -97,6 +103,8 @@ int32_t UdmfServiceImpl::SetData(CustomOption &option, UnifiedData &unifiedData, msg.appId = "unknown"; res = E_ERROR; } else { + RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), + BizScene::SET_DATA, SetDataStage::SET_DATA_SERVICE_BEGIN, StageRes::IDLE, bundleName); msg.appId = bundleName; res = SaveData(option, unifiedData, key); } @@ -120,37 +128,33 @@ int32_t UdmfServiceImpl::SaveData(CustomOption &option, UnifiedData &unifiedData ZLOGE("UnifiedData is invalid."); return E_INVALID_PARAMETERS; } - if (!UnifiedDataUtils::IsValidIntention(option.intention)) { ZLOGE("Invalid parameters intention: %{public}d.", option.intention); return E_INVALID_PARAMETERS; } - // imput runtime info before put it into store and save one privilege - if (PreProcessUtils::RuntimeDataImputation(unifiedData, option) != E_OK) { + if (PreProcessUtils::FillRuntimeInfo(unifiedData, option) != E_OK) { ZLOGE("Imputation failed"); return E_ERROR; } - std::string intention = unifiedData.GetRuntime()->key.intention; if (intention == UD_INTENTION_MAP.at(UD_INTENTION_DRAG)) { int32_t ret = PreProcessUtils::SetRemoteUri(option.tokenId, unifiedData); if (ret != E_OK) { - ZLOGE("SetRemoteUri failed, ret: %{public}d, bundleName:%{public}s.", ret, + ZLOGW("SetRemoteUri failed, ret: %{public}d, bundleName:%{public}s.", ret, unifiedData.GetRuntime()->createPackage.c_str()); - return ret; } } PreProcessUtils::SetRecordUid(unifiedData); - auto store = StoreCache::GetInstance().GetStore(intention); if (store == nullptr) { ZLOGE("Get store failed:%{public}s", intention.c_str()); return E_DB_ERROR; } - - if (store->Put(unifiedData) != E_OK) { - ZLOGE("Put unified data failed:%{public}s", intention.c_str()); + int32_t status = store->Put(unifiedData); + if (status != E_OK) { + ZLOGE("Put unified data failed:%{public}s, status:%{public}d", intention.c_str(), status); + HandleDbError(intention, status); return E_DB_ERROR; } key = unifiedData.GetRuntime()->key.GetUnifiedKey(); @@ -189,11 +193,23 @@ int32_t UdmfServiceImpl::GetData(const QueryOption &query, UnifiedData &unifiedD return res; } -int32_t UdmfServiceImpl::RetrieveData(const QueryOption &query, UnifiedData &unifiedData) +bool UdmfServiceImpl::CheckDragParams(UnifiedKey &key, const QueryOption &query) { - UnifiedKey key(query.key); if (!key.IsValid()) { ZLOGE("Unified key: %{public}s is invalid.", query.key.c_str()); + return false; + } + if (key.intention != UD_INTENTION_MAP.at(UD_INTENTION_DRAG)) { + ZLOGE("Invalid intention:%{public}s", key.intention.c_str()); + return false; + } + return true; +} + +int32_t UdmfServiceImpl::RetrieveData(const QueryOption &query, UnifiedData &unifiedData) +{ + UnifiedKey key(query.key); + if (!CheckDragParams(key, query)) { return E_INVALID_PARAMETERS; } auto store = StoreCache::GetInstance().GetStore(key.intention); @@ -204,6 +220,7 @@ int32_t UdmfServiceImpl::RetrieveData(const QueryOption &query, UnifiedData &uni int32_t res = store->Get(query.key, unifiedData); if (res != E_OK) { ZLOGE("Get data failed,res:%{public}d,key:%{public}s", res, query.key.c_str()); + HandleDbError(key.intention, res); return res; } @@ -211,17 +228,14 @@ int32_t UdmfServiceImpl::RetrieveData(const QueryOption &query, UnifiedData &uni ZLOGE("Get data incomplete,key:%{public}s", query.key.c_str()); return E_NOT_FOUND; } - - CheckerManager::CheckInfo info; - info.tokenId = query.tokenId; std::shared_ptr runtime = unifiedData.GetRuntime(); if (runtime == nullptr) { return E_DB_ERROR; } - if (!CheckerManager::GetInstance().IsValid(runtime->privileges, info) && !IsPermissionInCache(query)) { - RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), - BizScene::GET_DATA, GetDataStage::VERIFY_PRIVILEGE, StageRes::FAILED, E_NO_PERMISSION); - return E_NO_PERMISSION; + + res = VerifyDataAccessPermission(runtime, query, unifiedData); + if (res != E_OK) { + return res; } if (key.intention == UD_INTENTION_MAP.at(UD_INTENTION_DRAG)) { @@ -240,14 +254,33 @@ int32_t UdmfServiceImpl::RetrieveData(const QueryOption &query, UnifiedData &uni } } - privilegeCache_.erase(query.key); - + { + std::lock_guard lock(cacheMutex_); + privilegeCache_.erase(query.key); + } PreProcessUtils::SetRemoteData(unifiedData); return E_OK; } +int32_t UdmfServiceImpl::VerifyDataAccessPermission(std::shared_ptr runtime, const QueryOption &query, + const UnifiedData &unifiedData) +{ + CheckerManager::CheckInfo info; + info.tokenId = query.tokenId; + + if (!CheckerManager::GetInstance().IsValid(runtime->privileges, info) && !IsPermissionInCache(query)) { + RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), + BizScene::GET_DATA, GetDataStage::VERIFY_PRIVILEGE, StageRes::FAILED, E_NO_PERMISSION); + ZLOGE("Get data failed,key:%{public}s", query.key.c_str()); + return E_NO_PERMISSION; + } + + return E_OK; +} + bool UdmfServiceImpl::IsPermissionInCache(const QueryOption &query) { + std::lock_guard lock(cacheMutex_); auto iter = privilegeCache_.find(query.key); if (iter != privilegeCache_.end() && iter->second.tokenId == query.tokenId) { return true; @@ -263,6 +296,7 @@ bool UdmfServiceImpl::IsReadAndKeep(const std::vector &privileges, co } } + std::lock_guard lock(cacheMutex_); auto iter = privilegeCache_.find(query.key); if (iter != privilegeCache_.end() && iter->second.tokenId == query.tokenId && iter->second.readPermission == PRIVILEGE_READ_AND_KEEP) { @@ -361,8 +395,17 @@ int32_t UdmfServiceImpl::GetBatchData(const QueryOption &query, std::vectorvisibility == VISIBILITY_OWN_PROCESS && + query.tokenId != data.GetRuntime()->tokenId) { + continue; + } else { + unifiedDataSet.push_back(std::move(data)); + } + } + if (!IsFileMangerSa() && ProcessData(query, unifiedDataSet) != E_OK) { + ZLOGE("Query no permission."); + return E_NO_PERMISSION; } return E_OK; } @@ -370,13 +413,16 @@ int32_t UdmfServiceImpl::GetBatchData(const QueryOption &query, std::vectorGet(query.key, data); if (res != E_OK) { ZLOGE("Get data failed:%{public}s", key.intention.c_str()); + HandleDbError(key.intention, res); return res; } + auto verifyRes = VerifyUpdatePermission(query, data, bundleName); + if (verifyRes != E_OK) { + ZLOGE("VerifyUpdatePermission failed:%{public}d, key: %{public}s.", verifyRes, query.key.c_str()); + return verifyRes; + } + std::shared_ptr runtime = data.GetRuntime(); + runtime->lastModifiedTime = PreProcessUtils::GetTimestamp(); + unifiedData.SetRuntime(*runtime); + PreProcessUtils::SetRecordUid(unifiedData); + if ((res = store->Update(unifiedData)) != E_OK) { + ZLOGE("Unified data update failed:%{public}s", key.intention.c_str()); + HandleDbError(key.intention, res); + return E_DB_ERROR; + } + return E_OK; +} + +int32_t UdmfServiceImpl::VerifyUpdatePermission(const QueryOption &query, UnifiedData &data, std::string &bundleName) +{ if (data.IsEmpty()) { - ZLOGE("Invalid parameter, unified data has no record; intention: %{public}s.", key.intention.c_str()); + ZLOGE("Invalid parameter, unified data has no record"); return E_INVALID_PARAMETERS; } std::shared_ptr runtime = data.GetRuntime(); if (runtime == nullptr) { + ZLOGE("Invalid parameter, runtime is nullptr."); return E_DB_ERROR; } - if (runtime->tokenId != query.tokenId && !HasDatahubPriviledge(bundleName)) { - ZLOGE("Update failed: tokenId mismatch"); + if (runtime->tokenId != query.tokenId && !HasDatahubPriviledge(bundleName) && + CheckAppId(runtime, bundleName) != E_OK) { + ZLOGE("Update failed: tokenId or appId mismatch, bundleName: %{public}s", bundleName.c_str()); return E_INVALID_PARAMETERS; } - runtime->lastModifiedTime = PreProcessUtils::GetTimestamp(); - unifiedData.SetRuntime(*runtime); - PreProcessUtils::SetRecordUid(unifiedData); - if (store->Update(unifiedData) != E_OK) { - ZLOGE("Unified data update failed:%{public}s", key.intention.c_str()); - return E_DB_ERROR; + return E_OK; +} + +int32_t UdmfServiceImpl::CheckAppId(std::shared_ptr runtime, const std::string &bundleName) +{ + if (runtime->appId.empty()) { + ZLOGE("Update failed: Invalid parameter, runtime->appId is empty"); + return E_INVALID_PARAMETERS; + } + std::string appId = DistributedData::CheckerManager::GetInstance().GetAppId( + { IPCSkeleton::GetCallingUid(), runtime->tokenId, bundleName }); + if (appId.empty() || appId != runtime->appId) { + ZLOGE("Update failed: runtime->appId %{public}s and bundleName appId %{public}s mismatch", + runtime->appId.c_str(), appId.c_str()); + return E_INVALID_PARAMETERS; } return E_OK; } @@ -416,9 +493,19 @@ int32_t UdmfServiceImpl::UpdateData(const QueryOption &query, UnifiedData &unifi int32_t UdmfServiceImpl::DeleteData(const QueryOption &query, std::vector &unifiedDataSet) { ZLOGD("start"); + UnifiedKey key(query.key); + if (!key.IsValid() && !key.key.empty()) { + ZLOGE("invalid key, query.key: %{public}s", query.key.c_str()); + return E_INVALID_PARAMETERS; + } + std::string intention = FindIntentionMap(query.intention); + if (!IsValidOptionsNonDrag(key, intention)) { + ZLOGE("invalid option, query.key: %{public}s, intention: %{public}d", query.key.c_str(), query.intention); + return E_INVALID_PARAMETERS; + } std::vector dataSet; std::shared_ptr store; - auto status = QueryDataCommon(query, dataSet, store); + int32_t status = QueryDataCommon(query, dataSet, store); if (status != E_OK) { ZLOGE("QueryDataCommon failed."); return status; @@ -428,29 +515,53 @@ int32_t UdmfServiceImpl::DeleteData(const QueryOption &query, std::vector runtime; + std::string appId; std::vector deleteKeys; for (const auto &data : dataSet) { - runtime = data.GetRuntime(); - if (runtime == nullptr) { - return E_DB_ERROR; - } - if (runtime->tokenId == query.tokenId) { - unifiedDataSet.push_back(data); - deleteKeys.push_back(runtime->key.key); + auto runtime = data.GetRuntime(); + if (!CheckDeleteDataPermission(appId, runtime, query)) { + continue; } + unifiedDataSet.push_back(data); + deleteKeys.emplace_back(UnifiedKey(runtime->key.key).GetKeyCommonPrefix()); } if (deleteKeys.empty()) { ZLOGE("No data to delete for this application"); return E_OK; } ZLOGI("Delete data start. size: %{public}zu.", deleteKeys.size()); - if (store->DeleteBatch(deleteKeys) != E_OK) { + status = store->DeleteBatch(deleteKeys); + if (status != E_OK) { ZLOGE("Remove data failed."); + HandleDbError(key.intention, status); return E_DB_ERROR; } return E_OK; } +bool UdmfServiceImpl::CheckDeleteDataPermission(std::string &appId, const std::shared_ptr &runtime, + const QueryOption &query) +{ + if (runtime == nullptr) { + ZLOGE("Invalid runtime."); + return false; + } + if (runtime->tokenId == query.tokenId) { + return true; + } + std::string bundleName; + std::string specificBundleName; + if (!PreProcessUtils::GetSpecificBundleNameByTokenId(query.tokenId, specificBundleName, bundleName)) { + ZLOGE("GetSpecificBundleNameByTokenId failed, tokenid:%{public}u", query.tokenId); + return false; + } + if (CheckAppId(runtime, bundleName) != E_OK) { + ZLOGE("Delete failed: tokenId or appId mismatch, bundleName: %{public}s", bundleName.c_str()); + return false; + } + return true; +} + int32_t UdmfServiceImpl::GetSummary(const QueryOption &query, Summary &summary) { ZLOGD("start"); @@ -465,9 +576,10 @@ int32_t UdmfServiceImpl::GetSummary(const QueryOption &query, Summary &summary) ZLOGE("Get store failed:%{public}s", key.intention.c_str()); return E_DB_ERROR; } - - if (store->GetSummary(key, summary) != E_OK) { + int32_t status = store->GetSummary(key, summary); + if (status != E_OK) { ZLOGE("Store get summary failed:%{public}s", key.intention.c_str()); + HandleDbError(key.intention, status); return E_DB_ERROR; } return E_OK; @@ -484,17 +596,16 @@ int32_t UdmfServiceImpl::AddPrivilege(const QueryOption &query, Privilege &privi std::string processName; if (!PreProcessUtils::GetNativeProcessNameByToken(query.tokenId, processName)) { + ZLOGE("GetNativeProcessNameByToken is faild"); return E_ERROR; } - if (key.intention == UD_INTENTION_MAP.at(UD_INTENTION_DRAG)) { - if (find(DRAG_AUTHORIZED_PROCESSES, std::end(DRAG_AUTHORIZED_PROCESSES), processName) == - std::end(DRAG_AUTHORIZED_PROCESSES)) { - ZLOGE("Process:%{public}s lacks permission for intention:drag", processName.c_str()); - return E_NO_PERMISSION; - } - } else { - ZLOGE("Intention: %{public}s has no authorized processes", key.intention.c_str()); + if (CheckAddPrivilegePermission(key, processName, query) != E_OK) { + ZLOGE("Intention:%{public}s no permission", key.intention.c_str()); + return E_NO_PERMISSION; + } + if (!UTILS::IsNativeCallingToken()) { + ZLOGE("Calling Token is not native"); return E_NO_PERMISSION; } @@ -505,27 +616,34 @@ int32_t UdmfServiceImpl::AddPrivilege(const QueryOption &query, Privilege &privi } Runtime runtime; - auto res = store->GetRuntime(query.key, runtime); + int32_t res = store->GetRuntime(query.key, runtime); if (res == E_NOT_FOUND) { + std::lock_guard lock(cacheMutex_); privilegeCache_[query.key] = privilege; ZLOGW("Add privilege in cache, key: %{public}s.", query.key.c_str()); return E_OK; } if (res != E_OK) { ZLOGE("Get runtime failed, res:%{public}d, key:%{public}s.", res, query.key.c_str()); + HandleDbError(key.intention, res); return res; } runtime.privileges.emplace_back(privilege); res = store->PutRuntime(query.key, runtime); if (res != E_OK) { ZLOGE("Update runtime failed, res:%{public}d, key:%{public}s", res, query.key.c_str()); + HandleDbError(key.intention, res); } return res; } int32_t UdmfServiceImpl::Sync(const QueryOption &query, const std::vector &devices) { - ZLOGD("start"); + if (!UTILS::IsTokenNative() || + !DistributedKv::PermissionValidator::GetInstance().CheckSyncPermission(query.tokenId)) { + ZLOGE("Tokenid permission verification failed!"); + return E_NO_PERMISSION; + } RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), BizScene::SYNC_DATA, SyncDataStage::SYNC_BEGIN, StageRes::IDLE, BizState::DFX_BEGIN); UnifiedKey key(query.key); @@ -536,6 +654,12 @@ int32_t UdmfServiceImpl::Sync(const QueryOption &query, const std::vector &devices) +{ auto store = StoreCache::GetInstance().GetStore(key.intention); if (store == nullptr) { RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), @@ -550,21 +674,70 @@ int32_t UdmfServiceImpl::Sync(const QueryOption &query, const std::vector lock(mutex_); asyncProcessInfoMap_.insert_or_assign(syncInfo.businessUdKey, syncInfo); - 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); }; RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), BizScene::SYNC_DATA, SyncDataStage::SYNC_BEGIN, StageRes::SUCCESS); + int userId = 0; + if (!AccountDelegate::GetInstance()->QueryForegroundUserId(userId)) { + ZLOGE("QueryForegroundUserId failed"); + return E_ERROR; + } + auto meta = BuildMeta(key.intention, userId); + auto uuids = DmAdapter::GetInstance().ToUUID(devices); + if (IsNeedMetaSync(meta, uuids)) { + bool res = MetaDataManager::GetInstance().Sync(uuids, [this, devices, callback, store] (auto &results) { + auto successRes = ProcessResult(results); + if (store->Sync(successRes, callback) != E_OK) { + ZLOGE("Store sync failed"); + RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), + BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::FAILED, E_DB_ERROR, BizState::DFX_END); + } + }); + if (!res) { + ZLOGE("Meta sync failed"); + RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), + BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::FAILED, E_DB_ERROR, BizState::DFX_END); + return E_DB_ERROR; + } + return E_OK; + } if (store->Sync(devices, callback) != E_OK) { - ZLOGE("Store sync failed:%{public}s", key.intention.c_str()); + ZLOGE("Store sync failed"); RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::FAILED, E_DB_ERROR, BizState::DFX_END); - return E_DB_ERROR; + return UDMF::E_DB_ERROR; } return E_OK; } +bool UdmfServiceImpl::IsNeedMetaSync(const StoreMetaData &meta, const std::vector &uuids) +{ + using namespace OHOS::DistributedData; + 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.GetKeyWithoutPath(), metaData)) { + isAfterMeta = true; + break; + } + auto [exist, mask] = DeviceMatrix::GetInstance().GetRemoteMask(uuid); + if ((mask & DeviceMatrix::META_STORE_MASK) == DeviceMatrix::META_STORE_MASK) { + isAfterMeta = true; + break; + } + auto [existLocal, localMask] = DeviceMatrix::GetInstance().GetMask(uuid); + if ((localMask & DeviceMatrix::META_STORE_MASK) == DeviceMatrix::META_STORE_MASK) { + isAfterMeta = true; + break; + } + } + return isAfterMeta; +} + int32_t UdmfServiceImpl::IsRemoteData(const QueryOption &query, bool &result) { UnifiedKey key(query.key); @@ -579,19 +752,16 @@ int32_t UdmfServiceImpl::IsRemoteData(const QueryOption &query, bool &result) return E_DB_ERROR; } - UnifiedData unifiedData; - if (store->Get(query.key, unifiedData) != E_OK) { - ZLOGE("Store get unifiedData failed:%{public}s", key.intention.c_str()); - return E_DB_ERROR; - } - std::shared_ptr runtime = unifiedData.GetRuntime(); - if (runtime == nullptr) { - ZLOGE("Store get runtime failed, key: %{public}s.", query.key.c_str()); + Runtime runtime; + int32_t res = store->GetRuntime(query.key, runtime); + if (res != E_OK) { + ZLOGE("Get runtime failed, res:%{public}d, key:%{public}s.", res, query.key.c_str()); + HandleDbError(key.intention, res); return E_DB_ERROR; } std::string localDeviceId = PreProcessUtils::GetLocalDeviceId(); - if (localDeviceId != runtime->deviceId) { + if (localDeviceId != runtime.deviceId) { result = true; } return E_OK; @@ -623,9 +793,10 @@ int32_t UdmfServiceImpl::SetAppShareOption(const std::string &intention, int32_t ZLOGE("SetAppShareOption failed,shareOption already set:%{public}s", shareOptionTmp.c_str()); return E_SETTINGS_EXISTED; } - - if (store->PutLocal(std::to_string(accessTokenIDEx), ShareOptionsUtil::GetEnumStr(shareOption)) != E_OK) { - ZLOGE("Store get unifiedData failed:%{public}d", shareOption); + int32_t status = store->PutLocal(std::to_string(accessTokenIDEx), ShareOptionsUtil::GetEnumStr(shareOption)); + if (status != E_OK) { + ZLOGE("Store get unifiedData failed:%{public}d", status); + HandleDbError(intention, status); return E_DB_ERROR; } return E_OK; @@ -647,6 +818,7 @@ int32_t UdmfServiceImpl::GetAppShareOption(const std::string &intention, int32_t int32_t ret = store->GetLocal(std::to_string(accessTokenIDEx), appShareOption); if (ret != E_OK) { ZLOGW("GetLocal failed:%{public}s", intention.c_str()); + HandleDbError(intention, ret); return ret; } ZLOGI("GetLocal ok intention:%{public}s,appShareOption:%{public}s", intention.c_str(), appShareOption.c_str()); @@ -674,8 +846,10 @@ int32_t UdmfServiceImpl::RemoveAppShareOption(const std::string &intention) } UnifiedData unifiedData; - if (store->DeleteLocal(std::to_string(accessTokenIDEx)) != E_OK) { - ZLOGE("Store DeleteLocal failed:%{public}s", intention.c_str()); + int32_t status = store->DeleteLocal(std::to_string(accessTokenIDEx)); + if (status != E_OK) { + ZLOGE("Store DeleteLocal failed:%{public}s, status:%{public}d", intention.c_str(), status); + HandleDbError(intention, status); return E_DB_ERROR; } return E_OK; @@ -698,17 +872,21 @@ int32_t UdmfServiceImpl::OnInitialize() int32_t UdmfServiceImpl::QueryDataCommon( const QueryOption &query, std::vector &dataSet, std::shared_ptr &store) { - auto find = UD_INTENTION_MAP.find(query.intention); - std::string intention = find == UD_INTENTION_MAP.end() ? intention : find->second; - if (!UnifiedDataUtils::IsValidOptions(query.key, intention)) { + UnifiedKey key(query.key); + if (!key.IsValid() && !key.key.empty()) { + ZLOGE("invalid key, query.key: %{public}s", query.key.c_str()); + return E_INVALID_PARAMETERS; + } + std::string intention = FindIntentionMap(query.intention); + if (!IsValidOptionsNonDrag(key, intention)) { ZLOGE("Unified key: %{public}s and intention: %{public}s is invalid.", query.key.c_str(), intention.c_str()); return E_INVALID_PARAMETERS; } - std::string dataPrefix = DATA_PREFIX + intention; - UnifiedKey key(query.key); - key.IsValid(); - if (intention.empty()) { - dataPrefix = UnifiedKey(key.key).GetPropertyKey(); + std::string dataPrefix; + if (key.key.empty()) { + dataPrefix = DATA_PREFIX + intention; + } else { + dataPrefix = UnifiedKey(key.key).GetKeyCommonPrefix(); intention = key.intention; } ZLOGD("dataPrefix = %{public}s, intention: %{public}s.", dataPrefix.c_str(), intention.c_str()); @@ -717,8 +895,10 @@ int32_t UdmfServiceImpl::QueryDataCommon( ZLOGE("Get store failed:%{public}s", intention.c_str()); return E_DB_ERROR; } - if (store->GetBatchData(dataPrefix, dataSet) != E_OK) { - ZLOGE("Get dataSet failed, dataPrefix: %{public}s.", dataPrefix.c_str()); + int32_t status = store->GetBatchData(dataPrefix, dataSet); + if (status != E_OK) { + ZLOGE("Get dataSet failed, dataPrefix: %{public}s, status:%{public}d.", dataPrefix.c_str(), status); + HandleDbError(intention, status); return E_DB_ERROR; } return E_OK; @@ -782,7 +962,7 @@ int32_t UdmfServiceImpl::ResolveAutoLaunch(const std::string &identifier, DBLaun for (const auto &storeMeta : metaData) { if (storeMeta.storeType < StoreMetaData::StoreType::STORE_KV_BEGIN || storeMeta.storeType > StoreMetaData::StoreType::STORE_KV_END || - storeMeta.appId != DistributedData::Bootstrap::GetInstance().GetProcessLabel()) { + storeMeta.appId != Bootstrap::GetInstance().GetProcessLabel()) { continue; } auto identifierTag = DistributedDB::KvStoreDelegateManager::GetKvStoreIdentifier("", storeMeta.appId, @@ -792,11 +972,10 @@ int32_t UdmfServiceImpl::ResolveAutoLaunch(const std::string &identifier, DBLaun } auto store = StoreCache::GetInstance().GetStore(storeMeta.storeId); if (store == nullptr) { - ZLOGE("GetStore fail, storeId:%{public}s", DistributedData::Anonymous::Change(storeMeta.storeId).c_str()); + ZLOGE("GetStore fail, storeId:%{public}s", Anonymous::Change(storeMeta.storeId).c_str()); continue; } - ZLOGI("storeId:%{public}s,appId:%{public}s,user:%{public}s", - DistributedData::Anonymous::Change(storeMeta.storeId).c_str(), + ZLOGI("storeId:%{public}s,appId:%{public}s,user:%{public}s", Anonymous::Change(storeMeta.storeId).c_str(), storeMeta.appId.c_str(), storeMeta.user.c_str()); return E_OK; } @@ -806,7 +985,8 @@ int32_t UdmfServiceImpl::ResolveAutoLaunch(const std::string &identifier, DBLaun bool UdmfServiceImpl::VerifyPermission(const std::string &permission, uint32_t callerTokenId) { if (permission.empty()) { - return true; + ZLOGE("VerifyPermission failed, Permission is empty."); + return false; } int status = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerTokenId, permission); if (status != Security::AccessToken::PermissionState::PERMISSION_GRANTED) { @@ -833,8 +1013,10 @@ void UdmfServiceImpl::RegisterAsyncProcessInfo(const std::string &businessUdKey) int32_t UdmfServiceImpl::OnUserChange(uint32_t code, const std::string &user, const std::string &account) { - ZLOGI("user change, code:%{public}u, user:%{public}s, account:%{public}s", code, user.c_str(), account.c_str()); - if (code == static_cast(DistributedData::AccountStatus::DEVICE_ACCOUNT_SWITCHED)) { + ZLOGI("user change, code:%{public}u, user:%{public}s", code, user.c_str()); + if (code == static_cast(DistributedData::AccountStatus::DEVICE_ACCOUNT_STOPPING) + || code == static_cast(DistributedData::AccountStatus::DEVICE_ACCOUNT_STOPPED) + || code == static_cast(DistributedData::AccountStatus::DEVICE_ACCOUNT_SWITCHED)) { StoreCache::GetInstance().CloseStores(); } return Feature::OnUserChange(code, user, account); @@ -843,23 +1025,18 @@ int32_t UdmfServiceImpl::OnUserChange(uint32_t code, const std::string &user, co void UdmfServiceImpl::TransferToEntriesIfNeed(const QueryOption &query, UnifiedData &unifiedData) { if (unifiedData.IsNeedTransferToEntries() && IsNeedTransferDeviceType(query)) { - unifiedData.TransferToEntries(unifiedData); + unifiedData.ConvertRecordsToEntries(); } } bool UdmfServiceImpl::IsNeedTransferDeviceType(const QueryOption &query) { - auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); - if (samgrProxy == nullptr) { - ZLOGE("Failed to get system ability mgr."); - return false; - } - auto bundleMgrProxy = samgrProxy->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); - if (bundleMgrProxy == nullptr) { - ZLOGE("Failed to Get BMS SA."); + auto deviceInfo = DmAdapter::GetInstance().GetLocalDevice(); + if (deviceInfo.deviceType != DEVICE_TYPE_PC && deviceInfo.deviceType != DEVICE_TYPE_PAD + && deviceInfo.deviceType != DEVICE_TYPE_2IN1) { return false; } - auto bundleManager = iface_cast(bundleMgrProxy); + auto bundleManager = PreProcessUtils::GetBundleMgr(); if (bundleManager == nullptr) { ZLOGE("Failed to get bundle manager"); return false; @@ -883,5 +1060,282 @@ bool UdmfServiceImpl::IsNeedTransferDeviceType(const QueryOption &query) } return false; } + +int32_t UdmfServiceImpl::CheckAddPrivilegePermission(UnifiedKey &key, + std::string &processName, const QueryOption &query) +{ + if (IsFileMangerIntention(key.intention)) { + if (IsFileMangerSa()) { + return E_OK; + } + std::string intention = FindIntentionMap(query.intention); + if (!intention.empty() && key.intention != intention) { + ZLOGE("Query.intention no not equal to key.intention"); + return E_INVALID_PARAMETERS; + } + return E_OK; + } + if (key.intention == UD_INTENTION_MAP.at(UD_INTENTION_DRAG)) { + if (find(DRAG_AUTHORIZED_PROCESSES, std::end(DRAG_AUTHORIZED_PROCESSES), processName) == + std::end(DRAG_AUTHORIZED_PROCESSES)) { + ZLOGE("Process:%{public}s lacks permission for intention:drag", processName.c_str()); + return E_NO_PERMISSION; + } + return E_OK; + } + ZLOGE("Check addPrivilege permission is faild."); + return E_NO_PERMISSION; +} + +bool UdmfServiceImpl::IsFileMangerSa() +{ + if (IPCSkeleton::GetCallingUid() == FOUNDATION_UID) { + return true; + } + ZLOGE("Caller no permission"); + return false; +} + +int32_t UdmfServiceImpl::ProcessData(const QueryOption &query, std::vector &dataSet) +{ + UnifiedKey key(query.key); + if (!key.key.empty() && !key.IsValid()) { + ZLOGE("invalid key, query.key: %{public}s", query.key.c_str()); + return E_INVALID_PARAMETERS; + } + std::string intention = FindIntentionMap(query.intention); + if (intention == UD_INTENTION_MAP.at(UD_INTENTION_DATA_HUB) || + key.intention == UD_INTENTION_MAP.at(UD_INTENTION_DATA_HUB)) { + return E_OK; + } + CheckerManager::CheckInfo info; + info.tokenId = query.tokenId; + for (auto &data : dataSet) { + auto ret = VerifyIntentionPermission(query, data, key, info); + if (ret != E_OK) { + ZLOGE("Verify intention permission is faild:%{public}d", ret); + return ret; + } + } + return E_OK; +} + +int32_t UdmfServiceImpl::VerifyIntentionPermission(const QueryOption &query, + UnifiedData &data, UnifiedKey &key, CheckerManager::CheckInfo &info) +{ + std::shared_ptr runtime = data.GetRuntime(); + if (runtime == nullptr) { + ZLOGE("runtime is nullptr."); + return E_DB_ERROR; + } + if (!CheckerManager::GetInstance().IsValid(runtime->privileges, info)) { + ZLOGE("Query no permission."); + return E_NO_PERMISSION; + } + if (!IsReadAndKeep(runtime->privileges, query)) { + if (LifeCycleManager::GetInstance().OnGot(key) != E_OK) { + ZLOGE("Remove data failed:%{public}s", key.intention.c_str()); + return E_DB_ERROR; + } + } + return E_OK; +} + +bool UdmfServiceImpl::IsFileMangerIntention(const std::string &intention) +{ + Intention optionIntention = UnifiedDataUtils::GetIntentionByString(intention); + if (optionIntention == UD_INTENTION_SYSTEM_SHARE || + optionIntention == UD_INTENTION_MENU || + optionIntention == UD_INTENTION_PICKER) { + return true; + } + return false; +} + +std::string UdmfServiceImpl::FindIntentionMap(const Intention &queryIntention) +{ + auto find = UD_INTENTION_MAP.find(queryIntention); + return find == UD_INTENTION_MAP.end() ? "" : find->second; +} + +bool UdmfServiceImpl::IsValidOptionsNonDrag(UnifiedKey &key, const std::string &intention) +{ + if (UnifiedDataUtils::IsValidOptions(key, intention)) { + return !key.key.empty() || intention == UD_INTENTION_MAP.at(Intention::UD_INTENTION_DATA_HUB); + } + return false; +} + +int32_t UdmfServiceImpl::SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptr iUdmfNotifier, std::string &key) +{ + std::string bundleName; + std::string specificBundleName; + auto tokenId = static_cast(IPCSkeleton::GetCallingTokenID()); + if (!PreProcessUtils::GetSpecificBundleNameByTokenId(tokenId, specificBundleName, bundleName)) { + ZLOGE("GetSpecificBundleNameByTokenId failed, tokenid:%{public}u", tokenId); + return E_ERROR; + } + UnifiedKey udkey(UD_INTENTION_MAP.at(UD_INTENTION_DRAG), specificBundleName, dataLoadInfo.sequenceKey); + key = udkey.GetUnifiedKey(); + dataLoadCallback_.Insert(key, iface_cast(iUdmfNotifier)); + + auto store = StoreCache::GetInstance().GetStore(UD_INTENTION_MAP.at(UD_INTENTION_DRAG)); + if (store == nullptr) { + ZLOGE("Get store failed:%{public}s", key.c_str()); + return E_DB_ERROR; + } + + Summary summary; + UnifiedDataHelper::GetSummaryFromLoadInfo(dataLoadInfo, summary); + int32_t status = store->PutSummary(udkey, summary); + if (status != E_OK) { + ZLOGE("Put summary failed:%{public}s, status:%{public}d", key.c_str(), status); + HandleDbError(UD_INTENTION_MAP.at(UD_INTENTION_DRAG), status); + return E_DB_ERROR; + } + return E_OK; +} + +int32_t UdmfServiceImpl::PushDelayData(const std::string &key, UnifiedData &unifiedData) +{ + CustomOption option; + option.intention = UD_INTENTION_DRAG; + option.tokenId = static_cast(IPCSkeleton::GetCallingTokenID()); + if (PreProcessUtils::FillRuntimeInfo(unifiedData, option) != E_OK) { + ZLOGE("Imputation failed"); + return E_ERROR; + } + int32_t ret = PreProcessUtils::SetRemoteUri(option.tokenId, unifiedData); + if (ret != E_OK) { + ZLOGW("SetRemoteUri failed, ret:%{public}d, key:%{public}s.", ret, key.c_str()); + } + + auto it = delayDataCallback_.Find(key); + if (!it.first) { + ZLOGE("DelayData callback no exist, key:%{public}s", key.c_str()); + return E_ERROR; + } + QueryOption query; + query.tokenId = it.second.tokenId; + query.key = key; + if (option.tokenId != query.tokenId && !IsPermissionInCache(query)) { + ZLOGE("No permission"); + return E_NO_PERMISSION; + } + ret = ProcessUri(query, unifiedData); + if (ret != E_OK) { + ZLOGE("ProcessUri failed:%{public}d", ret); + return E_NO_PERMISSION; + } + { + std::lock_guard lock(cacheMutex_); + privilegeCache_.erase(key); + } + PreProcessUtils::SetRemoteData(unifiedData); + + TransferToEntriesIfNeed(query, unifiedData); + return HandleDelayDataCallback(it.second, unifiedData, key); +} + +int32_t UdmfServiceImpl::HandleDelayDataCallback(DelayGetDataInfo &delayGetDataInfo, UnifiedData &unifiedData, + const std::string &key) +{ + auto callback = iface_cast(delayGetDataInfo.dataCallback); + if (callback == nullptr) { + ZLOGE("Delay data callback is null, key:%{public}s", key.c_str()); + return E_ERROR; + } + callback->DelayDataCallback(key, unifiedData); + delayDataCallback_.Erase(key); + return E_OK; +} + +int32_t UdmfServiceImpl::GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr iUdmfNotifier, std::shared_ptr unifiedData) +{ + ZLOGD("start"); + QueryOption query; + query.tokenId = static_cast(IPCSkeleton::GetCallingTokenID()); + query.key = key; + if (unifiedData == nullptr) { + ZLOGE("Data is null, key:%{public}s", key.c_str()); + return E_ERROR; + } + auto status = RetrieveData(query, *unifiedData); + if (status == E_OK) { + return E_OK; + } + if (status != E_NOT_FOUND) { + ZLOGE("Retrieve data failed, key:%{public}s", key.c_str()); + return status; + } + DelayGetDataInfo delayGetDataInfo; + delayGetDataInfo.dataCallback = iUdmfNotifier; + delayGetDataInfo.tokenId = static_cast(IPCSkeleton::GetCallingTokenID()); + delayDataCallback_.InsertOrAssign(key, std::move(delayGetDataInfo)); + + auto it = dataLoadCallback_.Find(key); + if (!it.first) { + ZLOGE("DataLoad callback no exist, key:%{public}s", key.c_str()); + return E_ERROR; + } + it.second->HandleDelayObserver(key, dataLoadInfo); + dataLoadCallback_.Erase(key); + return E_OK; +} + +bool UdmfServiceImpl::IsValidInput(const QueryOption &query, UnifiedData &unifiedData, UnifiedKey &key) +{ + if (!unifiedData.IsValid() || !key.IsValid()) { + ZLOGE("Data or key is invalid, key = %{public}s", query.key.c_str()); + return false; + } + std::string intention = FindIntentionMap(query.intention); + if (!IsValidOptionsNonDrag(key, intention) || key.intention != UD_INTENTION_MAP.at(UD_INTENTION_DATA_HUB)) { + ZLOGE("Invalid params: key.intention = %{public}s, intention = %{public}s", + key.intention.c_str(), intention.c_str()); + return false; + } + return true; +} + +void UdmfServiceImpl::CloseStoreWhenCorrupted(const std::string &intention, int32_t status) +{ + if (status == E_DB_CORRUPTED) { + ZLOGE("Kv database corrupted, start to remove store"); + StoreCache::GetInstance().RemoveStore(intention); + } +} + +void UdmfServiceImpl::HandleDbError(const std::string &intention, int32_t &status) +{ + CloseStoreWhenCorrupted(intention, status); + if (status == E_DB_CORRUPTED) { + // reset status to E_DB_ERROR + status = E_DB_ERROR; + } +} + +StoreMetaData UdmfServiceImpl::BuildMeta(const std::string &storeId, int userId) +{ + StoreMetaData meta; + meta.user = std::to_string(userId); + meta.storeId = storeId; + meta.bundleName = Bootstrap::GetInstance().GetProcessLabel(); + return meta; +} + +std::vector UdmfServiceImpl::ProcessResult(const std::map &results) +{ + std::vector devices; + for (const auto &[uuid, status] : results) { + if (static_cast(status) == DistributedDB::DBStatus::OK) { + DeviceMatrix::GetInstance().OnExchanged(uuid, DeviceMatrix::META_STORE_MASK); + devices.emplace_back(uuid); + } + } + ZLOGI("Meta sync finish, total size:%{public}zu, success size:%{public}zu", results.size(), devices.size()); + return devices; +} } // 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 48a80b4426289c8da2b2067d64a65c2acbf9f61b..0260d75fdba8aa8a8dbce25d6736d9bc8fc9a8e6 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h @@ -19,6 +19,9 @@ #include "store_cache.h" #include "udmf_service_stub.h" #include "kv_store_delegate_manager.h" +#include "metadata/store_meta_data.h" +#include "checker_manager.h" +#include "udmf_notifier_proxy.h" namespace OHOS { namespace UDMF { /* @@ -47,7 +50,14 @@ public: int32_t ClearAsynProcessByKey(const std::string &businessUdKey) 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 SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptr iUdmfNotifier, + std::string &key) override; + int32_t PushDelayData(const std::string &key, UnifiedData &unifiedData) override; + int32_t GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr iUdmfNotifier, std::shared_ptr unifiedData) override; private: + bool IsNeedMetaSync(const DistributedData::StoreMetaData &meta, const std::vector &uuids); + int32_t StoreSync(const UnifiedKey &key, const QueryOption &query, const std::vector &devices); int32_t SaveData(CustomOption &option, UnifiedData &unifiedData, std::string &key); int32_t RetrieveData(const QueryOption &query, UnifiedData &unifiedData); int32_t QueryDataCommon(const QueryOption &query, std::vector &dataSet, std::shared_ptr &store); @@ -60,6 +70,28 @@ private: void RegisterAsyncProcessInfo(const std::string &businessUdKey); void TransferToEntriesIfNeed(const QueryOption &query, UnifiedData &unifiedData); bool IsNeedTransferDeviceType(const QueryOption &query); + bool CheckDragParams(UnifiedKey &key, const QueryOption &query); + int32_t CheckAddPrivilegePermission(UnifiedKey &key, std::string &processName, const QueryOption &query); + int32_t ProcessData(const QueryOption &query, std::vector &dataSet); + int32_t VerifyIntentionPermission(const QueryOption &query, UnifiedData &dataSet, + UnifiedKey &key, CheckerManager::CheckInfo &info); + bool IsFileMangerSa(); + bool IsFileMangerIntention(const std::string &intention); + std::string FindIntentionMap(const Intention &queryintention); + bool IsValidOptionsNonDrag(UnifiedKey &key, const std::string &intention); + bool IsValidInput(const QueryOption &query, UnifiedData &unifiedData, UnifiedKey &key); + bool CheckDeleteDataPermission(std::string &appId, const std::shared_ptr &runtime, + const QueryOption &query); + int32_t CheckAppId(std::shared_ptr runtime, const std::string &bundleName); + void CloseStoreWhenCorrupted(const std::string &intention, int32_t status); + void HandleDbError(const std::string &intention, int32_t &status); + int32_t HandleDelayDataCallback(DelayGetDataInfo &delayGetDataInfo, UnifiedData &unifiedData, + const std::string &key); + int32_t VerifyDataAccessPermission(std::shared_ptr runtime, const QueryOption &query, + const UnifiedData &unifiedData); + std::vector ProcessResult(const std::map &results); + DistributedData::StoreMetaData BuildMeta(const std::string &storeId, int userId); + int32_t VerifyUpdatePermission(const QueryOption &query, UnifiedData &unifiedData, std::string &bundleName); class Factory { public: @@ -70,11 +102,14 @@ private: std::shared_ptr product_; }; static Factory factory_; - std::map privilegeCache_; + mutable std::recursive_mutex cacheMutex_; + std::map privilegeCache_ {}; std::shared_ptr executors_; std::mutex mutex_; - std::unordered_map asyncProcessInfoMap_; + std::unordered_map asyncProcessInfoMap_ {}; + ConcurrentMap> dataLoadCallback_ {}; + ConcurrentMap delayDataCallback_ {}; }; } // 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 f433413b02364d003f934d1c0f53b8a92d59df60..9e9a05f14c59201459aa1883299f3010ca743e06 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.cpp @@ -289,5 +289,66 @@ int32_t UdmfServiceStub::OnClearAsynProcessByKey(MessageParcel &data, MessagePar } return E_OK; } + +int32_t UdmfServiceStub::OnSetDelayInfo(MessageParcel &data, MessageParcel &reply) +{ + ZLOGD("start"); + DataLoadInfo dataLoadInfo; + sptr iUdmfNotifier; + + if (!ITypesUtil::Unmarshal(data, dataLoadInfo, iUdmfNotifier)) { + ZLOGE("Unmarshal failed!"); + return E_READ_PARCEL_ERROR; + } + std::string key; + int32_t status = SetDelayInfo(dataLoadInfo, iUdmfNotifier, key); + if (!ITypesUtil::Marshal(reply, status, key)) { + ZLOGE("Marshal failed:%{public}d", status); + return E_WRITE_PARCEL_ERROR; + } + return E_OK; +} + +int32_t UdmfServiceStub::OnPushDelayData(MessageParcel &data, MessageParcel &reply) +{ + ZLOGD("start"); + std::string key; + UnifiedData unifiedData; + + if (!ITypesUtil::Unmarshal(data, key, unifiedData)) { + ZLOGE("Unmarshal failed!"); + return E_READ_PARCEL_ERROR; + } + + int32_t status = PushDelayData(key, unifiedData); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal failed:%{public}d", status); + return E_WRITE_PARCEL_ERROR; + } + return E_OK; +} + +int32_t UdmfServiceStub::OnGetDataIfAvailable(MessageParcel &data, MessageParcel &reply) +{ + ZLOGD("start"); + std::string key; + DataLoadInfo dataLoadInfo; + sptr iUdmfNotifier; + if (!ITypesUtil::Unmarshal(data, key, dataLoadInfo, iUdmfNotifier)) { + ZLOGE("Unmarshal failed!"); + return E_READ_PARCEL_ERROR; + } + auto unifiedData = std::make_shared(); + int32_t status = GetDataIfAvailable(key, dataLoadInfo, iUdmfNotifier, unifiedData); + if (unifiedData == nullptr) { + ZLOGE("Data is null, key:%{public}s", key.c_str()); + return E_ERROR; + } + if (!ITypesUtil::Marshal(reply, status, *unifiedData)) { + ZLOGE("Marshal failed:%{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 793a13d997e4677012e6d3166da5b2760c2cbca5..c5f617a9fb54da2375ef7aea2e04e71b3b363e1c 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.h @@ -46,6 +46,9 @@ private: int32_t OnObtainAsynProcess(MessageParcel &data, MessageParcel &reply); int32_t OnClearAsynProcessByKey(MessageParcel &data, MessageParcel &reply); int32_t OnInvokeHap(MessageParcel &data, MessageParcel &reply); + int32_t OnPushDelayData(MessageParcel &data, MessageParcel &reply); + int32_t OnSetDelayInfo(MessageParcel &data, MessageParcel &reply); + int32_t OnGetDataIfAvailable(MessageParcel &data, MessageParcel &reply); using Handler = int32_t (UdmfServiceStub::*)(MessageParcel &data, MessageParcel &reply); static constexpr Handler HANDLERS[static_cast(UdmfServiceInterfaceCode::CODE_BUTT)] = { @@ -62,7 +65,10 @@ private: &UdmfServiceStub::OnGetAppShareOption, &UdmfServiceStub::OnRemoveAppShareOption, &UdmfServiceStub::OnObtainAsynProcess, - &UdmfServiceStub::OnClearAsynProcessByKey + &UdmfServiceStub::OnClearAsynProcessByKey, + &UdmfServiceStub::OnSetDelayInfo, + &UdmfServiceStub::OnPushDelayData, + &UdmfServiceStub::OnGetDataIfAvailable, }; }; } // namespace UDMF diff --git a/interface_sdk/api/@ohos.data.UdmfComponents.d.ets b/interface_sdk/api/@ohos.data.UdmfComponents.d.ets new file mode 100644 index 0000000000000000000000000000000000000000..e3a59e42b2e37fbc21a327c7ab031574004a25f6 --- /dev/null +++ b/interface_sdk/api/@ohos.data.UdmfComponents.d.ets @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2025 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. + */ +/** + * @file + * @kit ArkData + */ +import uniformDataStruct from '@ohos.data.uniformDataStruct'; + +/** + * Enumerates the form card types. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ +declare enum FormType { + /** + * Big form card, with fixed size of 4 x 4. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ + TYPE_BIG = 0, + + /** + * Medium-sized form card, with fixed size of 4 x 2. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ + TYPE_MID = 1, + + /** + * Small form card, with fixed size of 2 x 1. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ + TYPE_SMALL = 2 +} + +/** + * Defines a content form card. + * + * @struct { ContentFormCard } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ +@Component +declare struct ContentFormCard { + /** + * Data of the form card. + * + * @type { uniformDataStruct.ContentForm } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ + contentFormData: uniformDataStruct.ContentForm; + + /** + * Type of the form card. + * + * @type { FormType } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ + @Prop + formType: FormType; + + /** + * Width of the form card. + * + * @type { ?number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ + @Prop + formWidth?: number; + + /** + * Height of the form card. + * + * @type { ?number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ + @Prop + formHeight?: number; + + /** + * Callback to be invoked when the form card is tapped. + * + * @type { ?Function } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ + handleOnClick?: Function; +} + +export { ContentFormCard, FormType }; \ No newline at end of file diff --git a/interface_sdk/api/@ohos.data.ValuesBucket.d.ts b/interface_sdk/api/@ohos.data.ValuesBucket.d.ts index a3951e9089e81abbfd92db2e99d3d96cae236371..2406877f580f0d17816ffaf2e11385d5a89a7ab3 100644 --- a/interface_sdk/api/@ohos.data.ValuesBucket.d.ts +++ b/interface_sdk/api/@ohos.data.ValuesBucket.d.ts @@ -34,6 +34,16 @@ * @crossplatform * @since 12 */ +/** + * Indicates possible value types + * + * @typedef { number | string | boolean } + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @stagemodelonly + * @crossplatform + * @atomicservice + * @since 20 + */ export type ValueType = number | string | boolean; /** diff --git a/interface_sdk/api/@ohos.data.cloudData.d.ts b/interface_sdk/api/@ohos.data.cloudData.d.ts index 22288866b1fa85aadfa95966e3e7ec6fad5a0736..d8a2e688efa9d9370dba84f5b8ce6d10f27789e3 100644 --- a/interface_sdk/api/@ohos.data.cloudData.d.ts +++ b/interface_sdk/api/@ohos.data.cloudData.d.ts @@ -158,6 +158,34 @@ declare namespace cloudData { normal: number; } + /** + * Describes sync status. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 18 + */ + enum SyncStatus { + /** + * Indicates cloud sync status is running. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 18 + */ + RUNNING = 0, + + /** + * Indicates cloud sync status was finished. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 18 + */ + FINISHED = 1 + } + /** * Sync information. * @@ -196,6 +224,16 @@ declare namespace cloudData { * @since 12 */ code: relationalStore.ProgressCode; + + /** + * Sync status. + * + * @type { ?SyncStatus } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 18 + */ + syncStatus?: SyncStatus; } /** diff --git a/interface_sdk/api/@ohos.data.cloudExtension.d.ts b/interface_sdk/api/@ohos.data.cloudExtension.d.ts index d983c4773aeb184c7cffa71d4470f2b7f2195f01..e00e9d93b46e13e262ebafea6e182562420bab98 100644 --- a/interface_sdk/api/@ohos.data.cloudExtension.d.ts +++ b/interface_sdk/api/@ohos.data.cloudExtension.d.ts @@ -33,6 +33,7 @@ declare namespace cloudExtension { /** * Provides interface for managing cloud assets. * + * @extends relationalStore.Asset * @interface CloudAsset * @syscap SystemCapability.DistributedDataManager.CloudSync.Server * @systemapi diff --git a/interface_sdk/api/@ohos.data.dataShare.d.ts b/interface_sdk/api/@ohos.data.dataShare.d.ts index 67e04fe777472f005e6c19faa2f9c8285b403b1e..5dfdf18f6be1daa4a1c10a904d3fe47ce9e1a620 100644 --- a/interface_sdk/api/@ohos.data.dataShare.d.ts +++ b/interface_sdk/api/@ohos.data.dataShare.d.ts @@ -56,6 +56,17 @@ declare namespace dataShare { * @since 10 */ isProxy?: boolean; + /** + * Specifies the time to wait for connecting extension, in seconds. + * + * @type { ?number } + * @default 2 + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 18 + */ + waitTime?: number; } /** @@ -72,6 +83,21 @@ declare namespace dataShare { * @stagemodelonly * @since 9 */ + /** + * Obtains the dataShareHelper. + * + * @param { Context } context - Indicates the application context. + * @param { string } uri - Indicates the path of the file to open. + * @param { AsyncCallback } callback - {DataShareHelper}: The dataShareHelper for consumer. + * @throws { BusinessError } 202 - Not System Application. + * @throws { BusinessError } 401 - Parameter error.Possible causes: 1. Mandatory parameters are left unspecified; + * 2. Incorrect parameters types. + * @throws { BusinessError } 15700010 - The DataShareHelper is not initialized successfully. + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 19 + */ function createDataShareHelper(context: Context, uri: string, callback: AsyncCallback): void; /** * Obtains the dataShareHelper. @@ -88,6 +114,22 @@ declare namespace dataShare { * @stagemodelonly * @since 10 */ + /** + * Obtains the dataShareHelper. + * + * @param { Context } context - Indicates the application context. + * @param { string } uri - Indicates the path of the file to open. + * @param { DataShareHelperOptions } options - Indicates the optional config. + * @param { AsyncCallback } callback - {DataShareHelper}: The dataShareHelper for consumer. + * @throws { BusinessError } 202 - Not System Application. + * @throws { BusinessError } 401 - Parameter error.Possible causes: 1. Mandatory parameters are left unspecified; + * 2. Incorrect parameters types. + * @throws { BusinessError } 15700010 - The DataShareHelper is not initialized successfully. + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 19 + */ function createDataShareHelper( context: Context, uri: string, @@ -124,6 +166,22 @@ declare namespace dataShare { * @stagemodelonly * @since 10 */ + /** + * Obtains the dataShareHelper. + * + * @param { Context } context - Indicates the application context. + * @param { string } uri - Indicates the path of the file to open. + * @param { DataShareHelperOptions } options - Indicates the optional config. + * @returns { Promise } {DataShareHelper}: The dataShareHelper for consumer. + * @throws { BusinessError } 202 - Not System Application. + * @throws { BusinessError } 401 - Parameter error.Possible causes: 1. Mandatory parameters are left unspecified; + * 2. Incorrect parameters types. + * @throws { BusinessError } 15700010 - The DataShareHelper is not initialized successfully. + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 19 + */ function createDataShareHelper( context: Context, uri: string, @@ -144,6 +202,21 @@ declare namespace dataShare { * @stagemodelonly * @since 11 */ + /** + * Enables silent access dynamically. + * + * @param { Context } context - Indicates the application context. + * @param { string } uri - Indicates the uri of the data share silent proxy resource. + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 202 - Not System Application. + * @throws { BusinessError } 401 - Parameter error.Possible causes: 1. Mandatory parameters are left unspecified; + * 2. Incorrect parameters types. + * @throws { BusinessError } 15700011 - The URI is not exist. + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 19 + */ function enableSilentProxy(context: Context, uri?: string): Promise; /** @@ -160,6 +233,21 @@ declare namespace dataShare { * @stagemodelonly * @since 11 */ + /** + * Disables silent access dynamically. + * + * @param { Context } context - Indicates the application context. + * @param { string } uri - Indicates the uri of the data share silent proxy resource. + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 202 - Not System Application. + * @throws { BusinessError } 401 - Parameter error.Possible causes: 1. Mandatory parameters are left unspecified; + * 2. Incorrect parameters types. + * @throws { BusinessError } 15700011 - The URI is not exist. + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 19 + */ function disableSilentProxy(context: Context, uri?: string): Promise; /** @@ -362,6 +450,18 @@ declare namespace dataShare { * @since 10 */ scheduler: string; + + /** + * Specifies the update sql of the template. + * The update is called after the predicates execution is complete. + * + * @type { ?string } + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 18 + */ + update?: string; } /** * Specifies the operation result structure. @@ -600,7 +700,7 @@ declare namespace dataShare { /** * Subscribes to the change of the data specified by the given URI. * - * @param { 'dataChange' } type - Indicates the event type, which must be 'dataChange'. + * @param { 'dataChange' } event - Indicates the event type, which must be 'dataChange'. * @param { SubscriptionType } type - Indicates the subscription type, which is defined in {@link SubscriptionType}. * @param { string } uri - Indicates the path of the data to subscribe. * @param { AsyncCallback } callback - Indicates the callback used to return the data change. @@ -618,7 +718,7 @@ declare namespace dataShare { /** * Unsubscribes from the change of the data specified by the given URI. * - * @param { 'dataChange' } type - Indicates the event type, which must be 'dataChange'. + * @param { 'dataChange' } event - Indicates the event type, which must be 'dataChange'. * @param { SubscriptionType } type - Indicates the subscription type, which is defined in {@link SubscriptionType}. * @param { string } uri - Indicates the path of the data to unsubscribe. * @param { AsyncCallback } callback - Indicates the callback to unsubscribe. @@ -1309,7 +1409,8 @@ declare namespace dataShare { * @returns {Promise>>} {Record>}: The result set of batch operations. * @throws { BusinessError } 401 - Parameter error.Possible causes: 1. Mandatory parameters are left unspecified; * 2. Incorrect parameters types. - * @throws { BusinessError } 15700000 - Inner error. + * @throws { BusinessError } 15700000 - Inner error. Possible causes: 1.The internal status is abnormal; + * 2.The interface is incorrectly used; 3.Permission configuration error; 4.A system error. * @throws { BusinessError } 15700013 - The DataShareHelper instance is already closed. * @throws { BusinessError } 202 - Not System Application. * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer @@ -1583,12 +1684,25 @@ declare namespace dataShare { * Close the connection between datashare and extension. * * @returns { Promise } The promise returned by the function. - * @throws { BusinessError } 15700000 - Inner error. + * @throws { BusinessError } 15700000 - Inner error. Possible causes: 1.The internal status is abnormal; + * 2.The interface is incorrectly used; 3.Permission configuration error; 4.A system error. * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer * @systemapi * @stagemodelonly * @since 12 */ + /** + * Close the connection between datashare and extension. + * + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 202 - Not System Application. + * @throws { BusinessError } 15700000 - Inner error. Possible causes: 1.The internal status is abnormal; + * 2.The interface is incorrectly used; 3.Permission configuration error; 4.A system error. + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 19 + */ close(): Promise; } } diff --git a/interface_sdk/api/@ohos.data.dataSharePredicates.d.ts b/interface_sdk/api/@ohos.data.dataSharePredicates.d.ts index 19fb6d0ee11f8ad5acd7025f3a093c002187141b..281cdd855258286baa14f57f4c5f91572db7f87c 100644 --- a/interface_sdk/api/@ohos.data.dataSharePredicates.d.ts +++ b/interface_sdk/api/@ohos.data.dataSharePredicates.d.ts @@ -37,27 +37,51 @@ import { ValueType } from './@ohos.data.ValuesBucket'; * @crossplatform * @since 12 */ +/** + * This module provides data share services based on the ExtensionAbility. + * + * @namespace dataSharePredicates + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @StageModelOnly + * @crossplatform + * @atomicservice + * @since 20 + */ declare namespace dataSharePredicates { /** - * Manages relational database configurations. + * Provides a filter object to query data in a database by using DataShare APIs. + * This type is not multi-thread safe. If a DataSharePredicates instance is operated by multiple threads + * at the same time in an application, use a lock for it. * * @syscap SystemCapability.DistributedDataManager.DataShare.Core * @StageModelOnly * @since 10 */ /** - * Manages relational database configurations. + * Provides a filter object to query data in a database by using DataShare APIs. + * This type is not multi-thread safe. If a DataSharePredicates instance is operated by multiple threads + * at the same time in an application, use a lock for it. * * @syscap SystemCapability.DistributedDataManager.DataShare.Core * @StageModelOnly * @crossplatform * @since 12 */ + /** + * Manages relational database configurations. + * + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @StageModelOnly + * @crossplatform + * @atomicservice + * @since 20 + */ class DataSharePredicates { /** * Configure the DataSharePredicates to match the field whose data type is ValueType and value is equal * to a specified value. * This method is similar to = of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @param { ValueType } value - Indicates the value to match with the DataSharePredicates. @@ -70,6 +94,7 @@ declare namespace dataSharePredicates { * Configure the DataSharePredicates to match the field whose data type is ValueType and value is equal * to a specified value. * This method is similar to = of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @param { ValueType } value - Indicates the value to match with the DataSharePredicates. @@ -79,12 +104,28 @@ declare namespace dataSharePredicates { * @crossplatform * @since 12 */ + /** + * Configure the DataSharePredicates to match the field whose data type is ValueType and value is equal + * to a specified value. + * This method is similar to = of the SQL statement. + * Currently only used for RDB and KVDB(schema). + * + * @param { string } field - Indicates the column name in the database table. + * @param { ValueType } value - Indicates the value to match with the DataSharePredicates. + * @returns { DataSharePredicates } Returns the DataSharePredicates that match the specified field. + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @StageModelOnly + * @crossplatform + * @atomicservice + * @since 20 + */ equalTo(field: string, value: ValueType): DataSharePredicates; /** * Configure the DataSharePredicates to match the field whose data type is ValueType and value is unequal to * a specified value. * This method is similar to != of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @param { ValueType } value - Indicates the value to match with the DataSharePredicates. @@ -99,6 +140,7 @@ declare namespace dataSharePredicates { /** * Adds a left parenthesis to the DataSharePredicates. * This method is similar to ( of the SQL statement and needs to be used together with endWrap(). + * Currently only used for RDB. * * @returns { DataSharePredicates } Returns the DataSharePredicates with the left parenthesis. * @syscap SystemCapability.DistributedDataManager.DataShare.Core @@ -112,6 +154,7 @@ declare namespace dataSharePredicates { * Adds a right parenthesis to the DataSharePredicates. * This method is similar to ) of the SQL statement and needs to be used together * with beginWrap(). + * Currently only used for RDB. * * @returns { DataSharePredicates } Returns the DataSharePredicates with the right parenthesis. * @syscap SystemCapability.DistributedDataManager.DataShare.Core @@ -124,6 +167,7 @@ declare namespace dataSharePredicates { /** * Adds an or condition to the DataSharePredicates. * This method is similar to or of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @returns { DataSharePredicates } Returns the DataSharePredicates with the or condition. * @syscap SystemCapability.DistributedDataManager.DataShare.Core @@ -136,6 +180,7 @@ declare namespace dataSharePredicates { /** * Adds an and condition to the DataSharePredicates. * This method is similar to and of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @returns { DataSharePredicates } Returns the DataSharePredicates with the and condition. * @syscap SystemCapability.DistributedDataManager.DataShare.Core @@ -145,6 +190,7 @@ declare namespace dataSharePredicates { /** * Adds an and condition to the DataSharePredicates. * This method is similar to and of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @returns { DataSharePredicates } Returns the DataSharePredicates with the and condition. * @syscap SystemCapability.DistributedDataManager.DataShare.Core @@ -152,12 +198,25 @@ declare namespace dataSharePredicates { * @crossplatform * @since 12 */ + /** + * Adds an and condition to the DataSharePredicates. + * This method is similar to and of the SQL statement. + * Currently only used for RDB and KVDB(schema). + * + * @returns { DataSharePredicates } Returns the DataSharePredicates with the and condition. + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @StageModelOnly + * @crossplatform + * @atomicservice + * @since 20 + */ and(): DataSharePredicates; /** * Configure the DataSharePredicates to match the field whose data type is string and value * contains a specified value. * This method is similar to contains of the SQL statement. + * Currently only used for RDB. * * @param { string } field - Indicates the column name in the database table. * @param { string } value - Indicates the value to match with the DataSharePredicates. @@ -173,6 +232,7 @@ declare namespace dataSharePredicates { * Configure the DataSharePredicates to match the field whose data type is string and value starts * with a specified string. * This method is similar to value% of the SQL statement. + * Currently only used for RDB. * * @param { string } field - Indicates the column name in the database table. * @param { string } value - Indicates the value to match with the DataSharePredicates. @@ -188,6 +248,7 @@ declare namespace dataSharePredicates { * Configure the DataSharePredicates to match the field whose data type is string and value * ends with a specified string. * This method is similar to %value of the SQL statement. + * Currently only used for RDB. * * @param { string } field - Indicates the column name in the database table. * @param { string } value - Indicates the value to match with the DataSharePredicates. @@ -202,6 +263,7 @@ declare namespace dataSharePredicates { /** * Configure the DataSharePredicates to match the fields whose value is null. * This method is similar to is null of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @returns { DataSharePredicates } Returns the DataSharePredicates that match the specified field. @@ -215,6 +277,7 @@ declare namespace dataSharePredicates { /** * Configure the DataSharePredicates to match the specified fields whose value is not null. * This method is similar to is not null of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @returns { DataSharePredicates } Returns the DataSharePredicates that match the specified field. @@ -229,6 +292,7 @@ declare namespace dataSharePredicates { * Configure the DataSharePredicates to match the fields whose data type is string and value is * similar to a specified string. * This method is similar to like of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @param { string } value - Indicates the value to match with the DataSharePredicates. The percent sign (%) in the value @@ -245,6 +309,7 @@ declare namespace dataSharePredicates { * Configure the DataSharePredicates to match the fields whose data type is string and value is * not similar to a specified string. * This method is similar to unlike of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @param { string } value - Indicates the value to match with the DataSharePredicates. The percent sign (%) in the value @@ -261,6 +326,7 @@ declare namespace dataSharePredicates { * Configure DataSharePredicates to match the specified field whose data type is string and the value contains * a wildcard. * Different from like, the input parameters of this method are case-sensitive. + * Currently only used for RDB. * * @param { string } field - Indicates the column name in the database table. * @param { string } value - Indicates the value to match with DataSharePredicates. @@ -274,6 +340,7 @@ declare namespace dataSharePredicates { /** * Restricts the value of the field to the range between low value and high value. + * Currently only used for RDB. * * @param { string } field - Indicates the column name. * @param { ValueType } low - Indicates the minimum value. @@ -289,6 +356,7 @@ declare namespace dataSharePredicates { /** * Configure DataSharePredicates to match the specified field whose data type is int and value is * out of a given range. + * Currently only used for RDB. * * @param { string } field - Indicates the column name in the database table. * @param { ValueType } low - Indicates the minimum value to match with DataSharePredicates. @@ -303,6 +371,7 @@ declare namespace dataSharePredicates { /** * Restricts the value of the field to be greater than the specified value. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name. * @param { ValueType } value - Indicates the String field. @@ -316,6 +385,7 @@ declare namespace dataSharePredicates { /** * Restricts the value of the field to be smaller than the specified value. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name. * @param { ValueType } value - Indicates the String field. @@ -329,6 +399,7 @@ declare namespace dataSharePredicates { /** * Restricts the value of the field to be greater than or equal to the specified value. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name. * @param { ValueType } value - Indicates the String field. @@ -342,6 +413,7 @@ declare namespace dataSharePredicates { /** * Restricts the value of the field to be smaller than or equal to the specified value. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name. * @param { ValueType } value - Indicates the String field. @@ -356,6 +428,7 @@ declare namespace dataSharePredicates { /** * Restricts the ascending order of the return list. When there are several orders, * the one close to the head has the highest priority. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name for sorting the return list. * @returns { DataSharePredicates } Returns the SQL query statement with the specified DataSharePredicates. @@ -366,6 +439,7 @@ declare namespace dataSharePredicates { /** * Restricts the ascending order of the return list. When there are several orders, * the one close to the head has the highest priority. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name for sorting the return list. * @returns { DataSharePredicates } Returns the SQL query statement with the specified DataSharePredicates. @@ -374,11 +448,25 @@ declare namespace dataSharePredicates { * @crossplatform * @since 12 */ + /** + * Restricts the ascending order of the return list. When there are several orders, + * the one close to the head has the highest priority. + * Currently only used for RDB and KVDB(schema). + * + * @param { string } field - Indicates the column name for sorting the return list. + * @returns { DataSharePredicates } Returns the SQL query statement with the specified DataSharePredicates. + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @StageModelOnly + * @crossplatform + * @atomicservice + * @since 20 + */ orderByAsc(field: string): DataSharePredicates; /** * Restricts the descending order of the return list. When there are several orders, * the one close to the head has the highest priority. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name for sorting the return list. * @returns { DataSharePredicates } Returns the SQL query statement with the specified DataSharePredicates. @@ -389,6 +477,7 @@ declare namespace dataSharePredicates { /** * Restricts the descending order of the return list. When there are several orders, * the one close to the head has the highest priority. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name for sorting the return list. * @returns { DataSharePredicates } Returns the SQL query statement with the specified DataSharePredicates. @@ -397,10 +486,24 @@ declare namespace dataSharePredicates { * @crossplatform * @since 12 */ + /** + * Restricts the descending order of the return list. When there are several orders, + * the one close to the head has the highest priority. + * Currently only used for RDB and KVDB(schema). + * + * @param { string } field - Indicates the column name for sorting the return list. + * @returns { DataSharePredicates } Returns the SQL query statement with the specified DataSharePredicates. + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @StageModelOnly + * @crossplatform + * @atomicservice + * @since 20 + */ orderByDesc(field: string): DataSharePredicates; /** * Restricts each row of the query result to be unique. + * Currently only used for RDB. * * @returns { DataSharePredicates } Returns the SQL query statement with the specified DataSharePredicates. * @syscap SystemCapability.DistributedDataManager.DataShare.Core @@ -412,6 +515,7 @@ declare namespace dataSharePredicates { /** * Construct a query object to specify the number of results and the starting position. + * Currently only used for RDB and KVDB(schema). * * @param { number } total - Represents the specified number of results. * @param { number } offset - Indicates the starting position. @@ -422,6 +526,7 @@ declare namespace dataSharePredicates { */ /** * Construct a query object to specify the number of results and the starting position. + * Currently only used for RDB and KVDB(schema). * * @param { number } total - Represents the specified number of results. * @param { number } offset - Indicates the starting position. @@ -431,10 +536,24 @@ declare namespace dataSharePredicates { * @crossplatform * @since 12 */ + /** + * Construct a query object to specify the number of results and the starting position. + * Currently only used for RDB and KVDB(schema). + * + * @param { number } total - Represents the specified number of results. + * @param { number } offset - Indicates the starting position. + * @returns { DataSharePredicates } Returns the query object. + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @StageModelOnly + * @crossplatform + * @atomicservice + * @since 20 + */ limit(total: number, offset: number): DataSharePredicates; /** * Configure {@code DataSharePredicates} to group query results by specified columns. + * Currently only used for RDB. * * @param { Array } fields - Indicates the specified columns by which query results are grouped. * @returns { DataSharePredicates } Returns the DataSharePredicates with the specified columns by which query results are grouped. @@ -448,6 +567,7 @@ declare namespace dataSharePredicates { /** * Configure {@code DataSharePredicates} to specify the index column. * Before using this method, you need to create an index column. + * Currently only used for RDB. * * @param { string } field - Indicates the name of the index column. * @returns { DataSharePredicates } Returns DataSharePredicates with the specified index column. @@ -461,6 +581,7 @@ declare namespace dataSharePredicates { /** * Configure {@code DataSharePredicates} to match the specified field whose data type is ValueType array and values * are within a given range. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @param { Array } value - Indicates the values to match with DataSharePredicates. @@ -472,6 +593,7 @@ declare namespace dataSharePredicates { /** * Configure {@code DataSharePredicates} to match the specified field whose data type is ValueType array and values * are within a given range. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @param { Array } value - Indicates the values to match with DataSharePredicates. @@ -481,11 +603,26 @@ declare namespace dataSharePredicates { * @crossplatform * @since 12 */ + /** + * Configure {@code DataSharePredicates} to match the specified field whose data type is ValueType array and values + * are within a given range. + * Currently only used for RDB and KVDB(schema). + * + * @param { string } field - Indicates the column name in the database table. + * @param { Array } value - Indicates the values to match with DataSharePredicates. + * @returns { DataSharePredicates } Returns DataSharePredicates that matches the specified field. + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @StageModelOnly + * @crossplatform + * @atomicservice + * @since 20 + */ in(field: string, value: Array): DataSharePredicates; /** * Configure {@code DataSharePredicates} to match the specified field whose data type is String array and values * are out of a given range. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @param { Array } value - Indicates the values to match with DataSharePredicates. @@ -499,6 +636,7 @@ declare namespace dataSharePredicates { /** * Configure {@code DataSharePredicates} Creates a query condition using the specified key prefix. + * Currently only used for KVDB. * * @param { string } prefix - Represents the specified key prefix. * @returns { DataSharePredicates } Returns the query object. @@ -511,6 +649,7 @@ declare namespace dataSharePredicates { /** * Configure {@code DataSharePredicates} to match the specified value whose key is within a given range. + * Currently only used for KVDB. * * @param { Array } keys - Represents the key names. * @returns { DataSharePredicates } Returns the query object. diff --git a/interface_sdk/api/@ohos.data.distributedDataObject.d.ts b/interface_sdk/api/@ohos.data.distributedDataObject.d.ts index 5960ab17e3c35255e01016e266397397ed322d08..c4119afc14df5d6333a77c6e78b879cb85116af9 100644 --- a/interface_sdk/api/@ohos.data.distributedDataObject.d.ts +++ b/interface_sdk/api/@ohos.data.distributedDataObject.d.ts @@ -177,6 +177,31 @@ declare namespace distributedDataObject { sessionId: string; } + /** + * Indicates the observer of object data changed. + * + * @typedef { function } ChangeCallback + * @param { string } sessionId - The sessionId of the changed object. + * @param { Array } fields - Property names of changed data. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ + type DataObserver = (sessionId: string, fields: Array) => void; + + /** + * Indicates the observer of object status changed. + * + * @typedef { function } StatusObserver + * @param { string } sessionId - The sessionId of the changed object. + * @param { string } networkId - The networkId of the changed device. + * @param { string } status 'online' The object became online on the device and data can be synced to the device; + * 'offline' The object became offline on the device and the object can not sync any data; + * 'restored' The object restored success. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ + type StatusObserver = (sessionId: string, networkId: string, status: string) => void; + /** * Object create by {@link createDistributedObject}. * @@ -291,7 +316,7 @@ declare namespace distributedDataObject { * @param {AsyncCallback} callback - The callback of setSessionId. * @throws {BusinessError} 201 - Permission verification failed. * @throws {BusinessError} 401 - Parameter error. Incorrect parameter types. - * @throws {BusinessError} 15400001 - Create table failed. + * @throws {BusinessError} 15400001 - Failed to create the in-memory database. * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject * @since 9 */ @@ -304,7 +329,7 @@ declare namespace distributedDataObject { * @throws {BusinessError} 201 - Permission verification failed. * @throws {BusinessError} 401 - Parameter error. Possible causes: 1. Incorrect parameter types; * 2. The sessionId allows only letters, digits, and underscores(_), and cannot exceed 128 in length. - * @throws {BusinessError} 15400001 - Create table failed. + * @throws {BusinessError} 15400001 - Failed to create the in-memory database. * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject * @since 12 */ @@ -317,10 +342,19 @@ declare namespace distributedDataObject { * @param {AsyncCallback} callback - The callback of setSessionId. * @throws {BusinessError} 201 - Permission verification failed. * @throws {BusinessError} 401 - Parameter error. Incorrect parameter types. - * @throws {BusinessError} 15400001 - Create table failed. + * @throws {BusinessError} 15400001 - Failed to create the in-memory database. * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject * @since 9 */ + /** + * Leave all session. + * + * @param {AsyncCallback} callback - The callback of setSessionId. + * @throws {BusinessError} 401 - Parameter error. Incorrect parameter types. + * @throws {BusinessError} 15400001 - Failed to create the in-memory database. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ setSessionId(callback: AsyncCallback): void; /** @@ -331,7 +365,7 @@ declare namespace distributedDataObject { * @returns {Promise} - The promise returned by the function. * @throws {BusinessError} 201 - Permission verification failed. * @throws {BusinessError} 401 - Parameter error. Incorrect parameter types. - * @throws {BusinessError} 15400001 - Create table failed. + * @throws {BusinessError} 15400001 - Failed to create the in-memory database. * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject * @since 9 */ @@ -344,7 +378,7 @@ declare namespace distributedDataObject { * @throws {BusinessError} 201 - Permission verification failed. * @throws {BusinessError} 401 - Parameter error. Possible causes: 1. Incorrect parameter types; * 2. The sessionId allows only letters, digits, and underscores(_), and cannot exceed 128 in length. - * @throws {BusinessError} 15400001 - Create table failed. + * @throws {BusinessError} 15400001 - Failed to create the in-memory database. * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject * @since 12 */ @@ -520,6 +554,76 @@ declare namespace distributedDataObject { * @since 11 */ bindAssetStore(assetKey: string, bindInfo: BindInfo): Promise; + + /** + * On watch of change. + * + * @param { 'change' } type - Event type, fixed as 'change', indicates data change. + * @param { DataObserver } callback - The observer of object data changed. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ + on(type: 'change', callback: DataObserver): void; + + /** + * Off watch of change. + * + * @param { 'change' } type - Event type, fixed as 'change', indicates data change. + * @param { DataObserver } callback - The observer of object data changed, if not null, off the callback, if undefined, off all callbacks. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ + off(type: 'change', callback?: DataObserver): void; + + /** + * On watch of status. + * + * @param { 'status' } type - Event type, fixed as 'status', indicates the online and offline of the object. + * @param { StatusObserver } callback - The observer of object status changed. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ + on(type: 'status', callback: StatusObserver): void; + + /** + * Off watch of status. + * + * @param { 'status' } type - Event type, fixed as 'status', indicates the online and offline of the object. + * @param { StatusObserver } callback - The observer of object status changed, if not null, off the callback, if undefined, off all callbacks. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ + off(type: 'status', callback?: StatusObserver): void; + + /** + * Mark an attribute of a distributed object as an asset type. This interface must be called before setSessionId. + * + * @param { string } assetKey - Indicates the key of the asset type in Object. + * @param { string } uri - Indicates the uri of asset. + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 15400002 - Parameter error. Possible causes: + * 1. The assetKey is invalid, such as ""; + * 2. The uri is invalid, such as "". + * @throws {BusinessError} 15400003 - The sessionId of the distributed object has been set. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ + setAsset(assetKey: string, uri: string): Promise; + + /** + * Marks an attribute of a distributed object as an asset array type. This interface must be called before setSessionId. + * + * @param { string } assetsKey - Indicates the key of the asset type in Object. + * @param { Array } uris - Indicates the uri array of asset. + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 15400002 - Parameter error. Possible causes: + * 1. The assetKey is invalid, such as ""; + * 2. The uris is invalid, such as the length of uris is more than 50. + * @throws {BusinessError} 15400003 - The sessionId of the distributed object has been set. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ + setAssets(assetsKey: string, uris: Array): Promise; } } diff --git a/interface_sdk/api/@ohos.data.distributedKVStore.d.ts b/interface_sdk/api/@ohos.data.distributedKVStore.d.ts index 62b913416bb88a9fa89e4bbc09dbe7ecb4897550..7c1b0573d54e5a40ca32f32f942730febf7fafa6 100644 --- a/interface_sdk/api/@ohos.data.distributedKVStore.d.ts +++ b/interface_sdk/api/@ohos.data.distributedKVStore.d.ts @@ -79,6 +79,7 @@ declare namespace distributedKVStore { * Max key length is 1024. * * @type { number } + * @readonly * @syscap SystemCapability.DistributedDataManager.KVStore.Core * @since 9 */ @@ -88,6 +89,7 @@ declare namespace distributedKVStore { * Max value length is 4194303. * * @type { number } + * @readonly * @syscap SystemCapability.DistributedDataManager.KVStore.Core * @since 9 */ @@ -97,6 +99,7 @@ declare namespace distributedKVStore { * Max device coordinate key length is 896. * * @type { number } + * @readonly * @syscap SystemCapability.DistributedDataManager.KVStore.Core * @since 9 */ @@ -106,6 +109,7 @@ declare namespace distributedKVStore { * Max store id length is 128. * * @type { number } + * @readonly * @syscap SystemCapability.DistributedDataManager.KVStore.Core * @since 9 */ @@ -115,6 +119,7 @@ declare namespace distributedKVStore { * Max query length is 512000. * * @type { number } + * @readonly * @syscap SystemCapability.DistributedDataManager.KVStore.Core * @since 9 */ @@ -124,6 +129,7 @@ declare namespace distributedKVStore { * Max batch operation size is 128. * * @type { number } + * @readonly * @syscap SystemCapability.DistributedDataManager.KVStore.Core * @since 9 */ @@ -580,7 +586,8 @@ declare namespace distributedKVStore { *

Add a child node to makes this node a non-leaf node and field value will be ignored if it has a child node. * * @param { FieldNode } child - The field node to append. - * @returns { boolean } Returns true if the child node is successfully added to this {@code FieldNode} and false otherwise. + * @returns { boolean } Returns true if the child node is successfully added to this {@code FieldNode} + * and false otherwise. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.KVStore.DistributedKVStore @@ -688,11 +695,11 @@ declare namespace distributedKVStore { /** * Moves the read position by a relative offset to the current position. * - * @param { number } offset - Indicates the relative offset to the current position. A negative offset indicates moving - * backwards, and a positive offset indicates moving forwards. For example, if the current position is entry 1 and - * this offset is 2, the destination position will be entry 3; if the current position is entry 3 and this offset is -2, - * the destination position will be entry 1. The valid final position after moving forwards starts with 0. If the - * final position is invalid, false will be returned. + * @param { number } offset - Indicates the relative offset to the current position. A negative offset indicates + * moving backwards, and a positive offset indicates moving forwards. For example, if the current position is entry + * 1 and this offset is 2, the destination position will be entry 3; if the current position is entry 3 and this + * offset is -2, the destination position will be entry 1. The valid final position after moving forwards starts + * with 0. If the final position is invalid, false will be returned. * @returns { boolean } Returns true if the operation succeeds; return false otherwise. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. @@ -787,7 +794,8 @@ declare namespace distributedKVStore { reset(): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is equal to the specified long value. + * Constructs a {@code Query} object to query entries with the specified field whose value is equal to the + * specified long value. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { number | string | boolean } value - Indicates the value to be compared. @@ -801,7 +809,8 @@ declare namespace distributedKVStore { equalTo(field: string, value: number | string | boolean): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is not equal to the specified int value. + * Constructs a {@code Query} object to query entries with the specified field whose value is not equal to the + * specified int value. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { number | string | boolean } value - Indicates the value to be compared. @@ -815,8 +824,8 @@ declare namespace distributedKVStore { notEqualTo(field: string, value: number | string | boolean): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is greater than or equal to the - * specified int value. + * Constructs a {@code Query} object to query entries with the specified field whose value is greater than or + * equal to the specified int value. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { number | string | boolean } value - Indicates the value to be compared. @@ -830,7 +839,8 @@ declare namespace distributedKVStore { greaterThan(field: string, value: number | string | boolean): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is less than the specified int value. + * Constructs a {@code Query} object to query entries with the specified field whose value is less than the + * specified int value. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { number | string } value - Indicates the value to be compared. @@ -859,8 +869,8 @@ declare namespace distributedKVStore { greaterThanOrEqualTo(field: string, value: number | string): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is less than or equal to the - * specified int value. + * Constructs a {@code Query} object to query entries with the specified field whose value is less than or + * equal to the specified int value. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { number | string } value - Indicates the value to be compared. @@ -887,7 +897,8 @@ declare namespace distributedKVStore { isNull(field: string): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is within the specified int value list. + * Constructs a {@code Query} object to query entries with the specified field whose value is within the specified + * int value list. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { number[] } valueList - Indicates the int value list. @@ -901,7 +912,8 @@ declare namespace distributedKVStore { inNumber(field: string, valueList: number[]): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is within the specified string value list. + * Constructs a {@code Query} object to query entries with the specified field whose value is within the specified + * string value list. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { string[] } valueList - Indicates the string value list. @@ -915,7 +927,8 @@ declare namespace distributedKVStore { inString(field: string, valueList: string[]): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is not within the specified int value list. + * Constructs a {@code Query} object to query entries with the specified field whose value is not within the + * specified int value list. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { number[] } valueList - Indicates the int value list. @@ -929,7 +942,8 @@ declare namespace distributedKVStore { notInNumber(field: string, valueList: number[]): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is not within the specified string value list. + * Constructs a {@code Query} object to query entries with the specified field whose value is not within the + * specified string value list. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { string[] } valueList - Indicates the string value list. @@ -943,7 +957,8 @@ declare namespace distributedKVStore { notInString(field: string, valueList: string[]): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is similar to the specified string value. + * Constructs a {@code Query} object to query entries with the specified field whose value is similar to the + * specified string value. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { string } value - Indicates the string value. @@ -957,7 +972,8 @@ declare namespace distributedKVStore { like(field: string, value: string): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is not similar to the specified string value. + * Constructs a {@code Query} object to query entries with the specified field whose value is not similar to the + * specified string value. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { string } value - Indicates the string value. @@ -1019,8 +1035,12 @@ declare namespace distributedKVStore { /** * Constructs a {@code Query} object to specify the number of results and the start position. * - * @param { number } total - Indicates the number of results. - * @param { number } offset - Indicates the start position. + * @param { number } total - Maximum number of results to query. The value must be a non-negative integer. + * If the input value is less than 0, the number of results is not limited. + * @param { number } offset - Start position of the query result. By default, + * the start position is the beginning of the result set. If **offset** is a negative number, + * the start position is the beginning of the result set. If **offset** exceeds the end of the result set, + * the query result is empty. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. @@ -1043,8 +1063,8 @@ declare namespace distributedKVStore { /** * Creates a query condition group with a left bracket. - *

Multiple query conditions in an {@code Query} object can be grouped. The query conditions in a group can be used as a - * whole to combine with other query conditions. + *

Multiple query conditions in an {@code Query} object can be grouped. The query conditions in a group can + * beused as a whole to combine with other query conditions. * * @returns { Query } Returns the {@coed Query} object. * @syscap SystemCapability.DistributedDataManager.KVStore.Core @@ -1054,8 +1074,8 @@ declare namespace distributedKVStore { /** * Creates a query condition group with a right bracket. - *

Multiple query conditions in an {@code Query} object can be grouped. The query conditions in a group can be used as a - * whole to combine with other query conditions. + *

Multiple query conditions in an {@code Query} object can be grouped. The query conditions in a group can + * be used as a whole to combine with other query conditions. * * @returns { Query } Returns the {@coed Query} object. * @syscap SystemCapability.DistributedDataManager.KVStore.Core @@ -1128,7 +1148,8 @@ declare namespace distributedKVStore { interface SingleKVStore { /** * Writes a key-value pair of the string type into the {@code SingleKVStore} database. - *

If you do not want to synchronize this key-value pair to other devices, set the write option in the local database. + *

If you do not want to synchronize this key-value pair to other devices, set the write option in the local + * database. * * @param { string } key - Indicates the key. Length must be less than {@code MAX_KEY_LENGTH}. * Spaces before and after the key will be cleared. @@ -1144,7 +1165,8 @@ declare namespace distributedKVStore { */ /** * Writes a key-value pair of the string type into the {@code SingleKVStore} database. - *

If you do not want to synchronize this key-value pair to other devices, set the write option in the local database. + *

If you do not want to synchronize this key-value pair to other devices, set the write option in the local + * database. * * @param { string } key - Indicates the key. Length must be less than {@code MAX_KEY_LENGTH}. * Spaces before and after the key will be cleared. @@ -1163,7 +1185,8 @@ declare namespace distributedKVStore { /** * Writes a key-value pair of the string type into the {@code SingleKVStore} database. - *

If you do not want to synchronize this key-value pair to other devices, set the write option in the local database. + *

If you do not want to synchronize this key-value pair to other devices, set the write option in the local + * database. * * @param { string } key - Indicates the key. Length must be less than {@code MAX_KEY_LENGTH}. * Spaces before and after the key will be cleared. @@ -1179,7 +1202,8 @@ declare namespace distributedKVStore { */ /** * Writes a key-value pair of the string type into the {@code SingleKVStore} database. - *

If you do not want to synchronize this key-value pair to other devices, set the write option in the local database. + *

If you do not want to synchronize this key-value pair to other devices, set the write option in the local + * database. * * @param { string } key - Indicates the key. Length must be less than {@code MAX_KEY_LENGTH}. * Spaces before and after the key will be cleared. @@ -1257,7 +1281,8 @@ declare namespace distributedKVStore { * @param { AsyncCallback } callback - the callback of putBatch. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.KVStore.Core @@ -1272,7 +1297,8 @@ declare namespace distributedKVStore { * @param { AsyncCallback } callback - the callback of putBatch. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. @@ -1290,7 +1316,8 @@ declare namespace distributedKVStore { * @returns { Promise } the promise returned by the function. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.KVStore.Core @@ -1305,7 +1332,8 @@ declare namespace distributedKVStore { * @returns { Promise } the promise returned by the function. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. @@ -1385,7 +1413,8 @@ declare namespace distributedKVStore { * @param { AsyncCallback } callback - the callback of delete. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.DataShare.Provider @@ -1400,7 +1429,8 @@ declare namespace distributedKVStore { * @param { AsyncCallback } callback - the callback of delete. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. @@ -1418,7 +1448,8 @@ declare namespace distributedKVStore { * @returns { Promise } the promise returned by the function. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.DataShare.Provider @@ -1433,7 +1464,8 @@ declare namespace distributedKVStore { * @returns { Promise } the promise returned by the function. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. @@ -1507,7 +1539,8 @@ declare namespace distributedKVStore { * synchronized from remote devices. This operation does not synchronize data to other databases or affect * subsequent data synchronization. * - * @param { string } deviceId - Identifies the device whose data is to be removed and the value cannot be the current device ID. + * @param { string } deviceId - Identifies the device whose data is to be removed and the value cannot be the + * current device ID. * @param { AsyncCallback } callback - the callback of removeDeviceData. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Parameter verification failed. @@ -1522,7 +1555,8 @@ declare namespace distributedKVStore { * synchronized from remote devices. This operation does not synchronize data to other databases or affect * subsequent data synchronization. * - * @param { string } deviceId - Identifies the device whose data is to be removed and the value cannot be the current device ID. + * @param { string } deviceId - Identifies the device whose data is to be removed and the value cannot be the + * current device ID. * @returns { Promise } the promise returned by the function. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Parameter verification failed. @@ -1627,7 +1661,8 @@ declare namespace distributedKVStore { getEntries(query: Query): Promise; /** - * Obtains the result set with a specified prefix from a {@code SingleKVStore} database. The {@code KVStoreResultSet} + * Obtains the result set with a specified prefix from a {@code SingleKVStore} database. + * The {@code KVStoreResultSet} * object can be used to query all key-value pairs that meet the search criteria. Each {@code SingleKVStore} * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created * four objects, calling this method will return a failure. Therefore, you are advised to call the closeResultSet @@ -1644,7 +1679,8 @@ declare namespace distributedKVStore { * @since 9 */ /** - * Obtains the result set with a specified prefix from a {@code SingleKVStore} database. The {@code KVStoreResultSet} + * Obtains the result set with a specified prefix from a {@code SingleKVStore} database. + * The {@code KVStoreResultSet} * object can be used to query all key-value pairs that meet the search criteria. Each {@code SingleKVStore} * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created * four objects, calling this method will return a failure. Therefore, you are advised to call the closeResultSet @@ -1664,7 +1700,8 @@ declare namespace distributedKVStore { getResultSet(keyPrefix: string, callback: AsyncCallback): void; /** - * Obtains the result set with a specified prefix from a {@code SingleKVStore} database. The {@code KVStoreResultSet} + * Obtains the result set with a specified prefix from a {@code SingleKVStore} database. + * The {@code KVStoreResultSet} * object can be used to query all key-value pairs that meet the search criteria. Each {@code SingleKVStore} * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created * four objects, calling this method will return a failure. Therefore, you are advised to call the closeResultSet @@ -1681,7 +1718,8 @@ declare namespace distributedKVStore { * @since 9 */ /** - * Obtains the result set with a specified prefix from a {@code SingleKVStore} database. The {@code KVStoreResultSet} + * Obtains the result set with a specified prefix from a {@code SingleKVStore} database. + * The {@code KVStoreResultSet} * object can be used to query all key-value pairs that meet the search criteria. Each {@code SingleKVStore} * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created * four objects, calling this method will return a failure. Therefore, you are advised to call the closeResultSet @@ -1766,7 +1804,8 @@ declare namespace distributedKVStore { * object matching the specified {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.DataShare.Provider @@ -1782,7 +1821,8 @@ declare namespace distributedKVStore { * object matching the specified {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100001 - Over max limits. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. @@ -1801,7 +1841,8 @@ declare namespace distributedKVStore { * object matching the specified {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.DataShare.Provider @@ -1817,7 +1858,8 @@ declare namespace distributedKVStore { * object matching the specified {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100001 - Over max limits. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. @@ -2202,7 +2244,8 @@ declare namespace distributedKVStore { * Register a databases synchronization callback to the database. *

Sync result is returned through asynchronous callback. * - * @param { 'syncComplete' } event - Subscribed event name, fixed as 'syncComplete', indicates the synchronization completion event. + * @param { 'syncComplete' } event - Subscribed event name, fixed as 'syncComplete', indicates the synchronization + * completion event. * @param { Callback> } syncCallback - {Array<[string, number]>}: the * deviceId and it's corresponding synchronization result which 0 means synchronization success * and otherwise failed. @@ -2216,7 +2259,8 @@ declare namespace distributedKVStore { /** * Unsubscribe from the SingleKVStore database based on the specified subscribeType and listener. * - * @param { 'dataChange' } event - The unsubscribe event name, fixed as 'dataChange', indicates the data change event. + * @param { 'dataChange' } event - The unsubscribe event name, fixed as 'dataChange', indicates the data change + * event. * @param { Callback } listener - {ChangeNotification}: the {@code ChangeNotification} * object indicates the data change events in the distributed database. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; @@ -2230,7 +2274,8 @@ declare namespace distributedKVStore { /** * Unregister the database synchronization callback. * - * @param { 'syncComplete' } event - The unsubscribe event name, fixed as 'syncComplete', indicates the synchronization completion event. + * @param { 'syncComplete' } event - The unsubscribe event name, fixed as 'syncComplete', indicates the + * synchronization completion event. * @param { Callback> } syncCallback - {Array<[string, number]>}: the * deviceId and it's corresponding synchronization result which 0 means synchronization success * and otherwise failed. @@ -2266,12 +2311,16 @@ declare namespace distributedKVStore { /** * Provides methods related to device-collaboration distributed databases. - *

To create a {@code DeviceKVStore} database, you can use the {@link data.distributed.common.KVManager.getKVStore(Options, String)} - * method with {@code KVStoreType} set to {@code DEVICE_COLLABORATION} for the input parameter Options. This database manages distributed - * data by device, and cannot modify data synchronized from remote devices. When an application writes a key-value pair entry + *

To create a {@code DeviceKVStore} database, you can use the + * {@link data.distributed.common.KVManager.getKVStore(Options, String)} + * method with {@code KVStoreType} set to {@code DEVICE_COLLABORATION} for the input parameter Options. + * This database manages distributed + * data by device, and cannot modify data synchronized from remote devices. When an application writes a + * key-value pair entry * into the database, the system automatically adds the ID of the device running the application to the key. * - * @interface DeviceKVStore + * @extends SingleKVStore + * @typedef DeviceKVStore * @syscap SystemCapability.DistributedDataManager.KVStore.DistributedKVStore * @since 9 */ @@ -2314,7 +2363,8 @@ declare namespace distributedKVStore { * Obtains the value matching a specified device ID and key. * * @param { string } deviceId - Indicates the device to be queried. - * @param { string } key - Indicates the key of the value to be queried. The length must be less than {@code MAX_KEY_LENGTH}. + * @param { string } key - Indicates the key of the value to be queried. The length must be less than + * {@code MAX_KEY_LENGTH}. * @param { AsyncCallback } callback - * {boolean | string | number | Uint8Array}: the returned value specified by the deviceId and key. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; @@ -2332,7 +2382,8 @@ declare namespace distributedKVStore { * Obtains the value matching a specified device ID and key. * * @param { string } deviceId - Indicates the device to be queried. - * @param { string } key - Indicates the key of the value to be queried. The length must be less than {@code MAX_KEY_LENGTH}. + * @param { string } key - Indicates the key of the value to be queried. The length must be less than + * {@code MAX_KEY_LENGTH}. * @returns { Promise } * {Uint8Array|string|boolean|number}: the returned value specified by the deviceId and key. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; @@ -2473,7 +2524,8 @@ declare namespace distributedKVStore { /** * Obtains the result set with the local device ID and specified prefix from a {@code DeviceKVStore} database. * The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. - * Each {@code DeviceKVStore} instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. + * Each {@code DeviceKVStore} instance can have a maximum of four {@code KVStoreResultSet} objects at the + * same time. * If you have created four objects, calling this method will return a failure. Therefore, you are advised to * call the closeResultSet method to close unnecessary {@code KVStoreResultSet} objects in a timely manner. * @@ -2490,7 +2542,8 @@ declare namespace distributedKVStore { /** * Obtains the result set with the local device ID and specified prefix from a {@code DeviceKVStore} database. * The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. - * Each {@code DeviceKVStore} instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. + * Each {@code DeviceKVStore} instance can have a maximum of four {@code KVStoreResultSet} objects at the + * same time. * If you have created four objects, calling this method will return a failure. Therefore, you are advised to * call the closeResultSet method to close unnecessary {@code KVStoreResultSet} objects in a timely manner. * @@ -2510,7 +2563,8 @@ declare namespace distributedKVStore { /** * Obtains the result set with the local device ID and specified prefix from a {@code DeviceKVStore} database. * The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. - * Each {@code DeviceKVStore} instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. + * Each {@code DeviceKVStore} instance can have a maximum of four {@code KVStoreResultSet} objects at the + * same time. * If you have created four objects, calling this method will return a failure. Therefore, you are advised to * call the closeResultSet method to close unnecessary {@code KVStoreResultSet} objects in a timely manner. * @@ -2527,7 +2581,8 @@ declare namespace distributedKVStore { /** * Obtains the result set with the local device ID and specified prefix from a {@code DeviceKVStore} database. * The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. - * Each {@code DeviceKVStore} instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. + * Each {@code DeviceKVStore} instance can have a maximum of four {@code KVStoreResultSet} objects at the + * same time. * If you have created four objects, calling this method will return a failure. Therefore, you are advised to * call the closeResultSet method to close unnecessary {@code KVStoreResultSet} objects in a timely manner. * @@ -2546,9 +2601,12 @@ declare namespace distributedKVStore { /** * Obtains the {@code KVStoreResultSet} object matching the specified device ID and key prefix. - *

The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. Each {@code DeviceKVStore} - * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created four objects, - * calling this method will return a failure. Therefore, you are advised to call the closeResultSet method to close unnecessary + *

The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. + * Each {@code DeviceKVStore} + * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created four + * objects, + * calling this method will return a failure. Therefore, you are advised to call the closeResultSet method to close + * unnecessary * {@code KVStoreResultSet} objects in a timely manner. * * @param { string } deviceId - Identifies the device whose data is to be queried. @@ -2564,9 +2622,12 @@ declare namespace distributedKVStore { */ /** * Obtains the {@code KVStoreResultSet} object matching the specified device ID and key prefix. - *

The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. Each {@code DeviceKVStore} - * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created four objects, - * calling this method will return a failure. Therefore, you are advised to call the closeResultSet method to close unnecessary + *

The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. + * Each {@code DeviceKVStore} + * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created four + * objects, + * calling this method will return a failure. Therefore, you are advised to call the closeResultSet method to close + * unnecessary * {@code KVStoreResultSet} objects in a timely manner. * * @param { string } deviceId - Identifies the device whose data is to be queried. @@ -2585,9 +2646,12 @@ declare namespace distributedKVStore { /** * Obtains the {@code KVStoreResultSet} object matching the specified device ID and key prefix. - *

The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. Each {@code DeviceKVStore} - * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created four objects, - * calling this method will return a failure. Therefore, you are advised to call the closeResultSet method to close unnecessary + *

The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. + * Each {@code DeviceKVStore} + * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created four + * objects, + * calling this method will return a failure. Therefore, you are advised to call the closeResultSet method to close + * unnecessary * {@code KVStoreResultSet} objects in a timely manner. * * @param { string } deviceId - Identifies the device whose data is to be queried. @@ -2603,9 +2667,12 @@ declare namespace distributedKVStore { */ /** * Obtains the {@code KVStoreResultSet} object matching the specified device ID and key prefix. - *

The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. Each {@code DeviceKVStore} - * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created four objects, - * calling this method will return a failure. Therefore, you are advised to call the closeResultSet method to close unnecessary + *

The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. + * Each {@code DeviceKVStore} + * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created four + * objects, + * calling this method will return a failure. Therefore, you are advised to call the closeResultSet method to close + * unnecessary * {@code KVStoreResultSet} objects in a timely manner. * * @param { string } deviceId - Identifies the device whose data is to be queried. @@ -2683,7 +2750,8 @@ declare namespace distributedKVStore { /** * Obtains the {@code KVStoreResultSet} object matching a specified device ID and {@code Query} object. * - * @param { string } deviceId - Indicates the ID of the device to which the {@code KVStoreResultSet} object belongs. + * @param { string } deviceId - Indicates the ID of the device to which the {@code KVStoreResultSet} object + * belongs. * @param { Query } query - Indicates the {@code Query} object. * @param { AsyncCallback } callback - {KVStoreResultSet}: the {@code KVStoreResultSet} * object matching the specified deviceId and {@code Query} object. @@ -2697,7 +2765,8 @@ declare namespace distributedKVStore { /** * Obtains the {@code KVStoreResultSet} object matching a specified device ID and {@code Query} object. * - * @param { string } deviceId - Indicates the ID of the device to which the {@code KVStoreResultSet} object belongs. + * @param { string } deviceId - Indicates the ID of the device to which the {@code KVStoreResultSet} object + * belongs. * @param { Query } query - Indicates the {@code Query} object. * @param { AsyncCallback } callback - {KVStoreResultSet}: the {@code KVStoreResultSet} * object matching the specified deviceId and {@code Query} object. @@ -2714,7 +2783,8 @@ declare namespace distributedKVStore { /** * Obtains the {@code KVStoreResultSet} object matching a specified device ID and {@code Query} object. * - * @param { string } deviceId - Indicates the ID of the device to which the {@code KVStoreResultSet} object belongs. + * @param { string } deviceId - Indicates the ID of the device to which the {@code KVStoreResultSet} object + * belongs. * @param { Query } query - Indicates the {@code Query} object. * @returns { Promise } {KVStoreResultSet}: the {@code KVStoreResultSet} * object matching the specified deviceId and {@code Query} object. @@ -2728,7 +2798,8 @@ declare namespace distributedKVStore { /** * Obtains the {@code KVStoreResultSet} object matching a specified device ID and {@code Query} object. * - * @param { string } deviceId - Indicates the ID of the device to which the {@code KVStoreResultSet} object belongs. + * @param { string } deviceId - Indicates the ID of the device to which the {@code KVStoreResultSet} object + * belongs. * @param { Query } query - Indicates the {@code Query} object. * @returns { Promise } {KVStoreResultSet}: the {@code KVStoreResultSet} * object matching the specified deviceId and {@code Query} object. @@ -2750,7 +2821,8 @@ declare namespace distributedKVStore { * object matching the local device ID and specified {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.DataShare.Provider @@ -2766,7 +2838,8 @@ declare namespace distributedKVStore { * object matching the local device ID and specified {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100001 - Over max limits. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. @@ -2785,7 +2858,8 @@ declare namespace distributedKVStore { * object matching the local device ID and specified {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.DataShare.Provider @@ -2801,7 +2875,8 @@ declare namespace distributedKVStore { * object matching the local device ID and specified {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100001 - Over max limits. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. @@ -2821,7 +2896,8 @@ declare namespace distributedKVStore { * object matching the specified deviceId and {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.DataShare.Provider @@ -2838,7 +2914,8 @@ declare namespace distributedKVStore { * object matching the specified deviceId and {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100001 - Over max limits. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. @@ -2862,7 +2939,8 @@ declare namespace distributedKVStore { * object matching the specified deviceId and {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.DataShare.Provider @@ -2879,7 +2957,8 @@ declare namespace distributedKVStore { * object matching the specified deviceId and {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100001 - Over max limits. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. @@ -2970,7 +3049,8 @@ declare namespace distributedKVStore { function createKVManager(config: KVManagerConfig): KVManager; /** - * Provides interfaces to manage a {@code SingleKVStore} database, including obtaining, closing, and deleting the {@code SingleKVStore}. + * Provides interfaces to manage a {@code SingleKVStore} database, including obtaining, closing, and deleting the + * {@code SingleKVStore}. * * @interface KVManager * @syscap SystemCapability.DistributedDataManager.KVStore.Core @@ -2981,7 +3061,7 @@ declare namespace distributedKVStore { * Creates and obtains a KVStore database by specifying {@code Options} and {@code storeId}. * * @param { string } storeId - Identifies the KVStore database. The value of this parameter must be unique - * for the same application, and different applications can share the same value. The storeId can consist + * for the same application, and different applications can share the same value. The storeId can consist * of only letters, digits, and underscores (_), and cannot exceed 128 characters. * @param { Options } options - Indicates the {@code Options} object used for creating and * obtaining the KVStore database. @@ -3000,7 +3080,7 @@ declare namespace distributedKVStore { * Creates and obtains a KVStore database by specifying {@code Options} and {@code storeId}. * * @param { string } storeId - Identifies the KVStore database. The value of this parameter must be unique - * for the same application, and different applications can share the same value. The storeId can consist + * for the same application, and different applications can share the same value. The storeId can consist * of only letters, digits, and underscores (_), and cannot exceed 128 characters. * @param { Options } options - Indicates the {@code Options} object used for creating and * obtaining the KVStore database. @@ -3017,15 +3097,16 @@ declare namespace distributedKVStore { /** * Closes the KVStore database. - *

Warning: This method is not thread-safe. If you call this method to stop a KVStore database that is running, your - * thread may crash. - *

The KVStore database to close must be an object created by using the {@code getKVStore} method. Before using this - * method, release the resources created for the database, for example, {@code KVStoreResultSet} for KVStore, otherwise - * closing the database will fail. - * - * @param { string } appId - Identifies the application that the database belong to, and cannot exceed 256 characters. - * @param { string } storeId - Identifies the KVStore database to close. The storeId can consist of only letters, digits, - * and underscores (_), and cannot exceed 128 characters. + *

Warning: This method is not thread-safe. If you call this method to stop a KVStore database that is running, + * your thread may crash. + *

The KVStore database to close must be an object created by using the {@code getKVStore} method. Before using + * this method, release the resources created for the database, for example, {@code KVStoreResultSet} for KVStore, + * otherwise closing the database will fail. + * + * @param { string } appId - Identifies the application that the database belong to, and cannot exceed 256 + * characters. + * @param { string } storeId - Identifies the KVStore database to close. The storeId can consist of only letters, + * digits, and underscores (_), and cannot exceed 128 characters. * @param { AsyncCallback } callback - the callback of closeKVStore. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Parameter verification failed. @@ -3036,15 +3117,16 @@ declare namespace distributedKVStore { /** * Closes the KVStore database. - *

Warning: This method is not thread-safe. If you call this method to stop a KVStore database that is running, your - * thread may crash. - *

The KVStore database to close must be an object created by using the {@code getKVStore} method. Before using this - * method, release the resources created for the database, for example, {@code KVStoreResultSet} for KVStore, otherwise - * closing the database will fail. - * - * @param { string } appId - Identifies the application that the database belong to, and cannot exceed 256 characters. - * @param { string } storeId - Identifies the KVStore database to close. The storeId can consist of only letters, digits, - * and underscores (_), and cannot exceed 128 characters. + *

Warning: This method is not thread-safe. If you call this method to stop a KVStore database that is running, + * your thread may crash. + *

The KVStore database to close must be an object created by using the {@code getKVStore} method. Before using + * this method, release the resources created for the database, for example, {@code KVStoreResultSet} for KVStore, + * otherwise closing the database will fail. + * + * @param { string } appId - Identifies the application that the database belong to, and cannot exceed 256 + * characters. + * @param { string } storeId - Identifies the KVStore database to close. The storeId can consist of only letters, + * digits, and underscores (_), and cannot exceed 128 characters. * @returns { Promise } the promise returned by the function. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Parameter verification failed. @@ -3056,12 +3138,13 @@ declare namespace distributedKVStore { /** * Deletes the KVStore database identified by storeId. *

Before using this method, close all KVStore instances in use that are identified by the same storeId. - *

You can use this method to delete a KVStore database not in use. After the database is deleted, all its data will be - * lost. + *

You can use this method to delete a KVStore database not in use. After the database is deleted, all its data + * will be lost. * - * @param { string } appId - Identifies the application that the database belong to, and cannot exceed 256 characters. - * @param { string } storeId - Identifies the KVStore database to delete. The storeId can consist of only letters, digits, - * and underscores (_), and cannot exceed 128 characters. + * @param { string } appId - Identifies the application that the database belong to, and cannot exceed 256 + * characters. + * @param { string } storeId - Identifies the KVStore database to delete. The storeId can consist of only letters, + * digits, and underscores (_), and cannot exceed 128 characters. * @param { AsyncCallback } callback - the callback of deleteKVStore. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Parameter verification failed. @@ -3074,12 +3157,13 @@ declare namespace distributedKVStore { /** * Deletes the KVStore database identified by storeId. *

Before using this method, close all KVStore instances in use that are identified by the same storeId. - *

You can use this method to delete a KVStore database not in use. After the database is deleted, all its data will be - * lost. + *

You can use this method to delete a KVStore database not in use. After the database is deleted, all its data + * will be lost. * - * @param { string } appId - Identifies the application that the database belong to, and cannot exceed 256 characters. - * @param { string } storeId - Identifies the KVStore database to delete. The storeId can consist of only letters, digits, - * and underscores (_), and cannot exceed 128 characters. + * @param { string } appId - Identifies the application that the database belong to, and cannot exceed 256 + * characters. + * @param { string } storeId - Identifies the KVStore database to delete. The storeId can consist of only letters, + * digits, and underscores (_), and cannot exceed 128 characters. * @returns { Promise } the promise returned by the function. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Parameter verification failed. @@ -3090,10 +3174,11 @@ declare namespace distributedKVStore { deleteKVStore(appId: string, storeId: string): Promise; /** - * Obtains the storeId of all KVStore databases that are created by using the {@code getKVStore} method and not deleted by - * calling the {@code deleteKVStore} method. + * Obtains the storeId of all KVStore databases that are created by using the {@code getKVStore} method and not + * deleted by calling the {@code deleteKVStore} method. * - * @param { string } appId - Identifies the application that obtains the databases, and cannot exceed 256 characters. + * @param { string } appId - Identifies the application that obtains the databases, and cannot exceed 256 + * characters. * @param { AsyncCallback } callback - {string[]}: the storeId of all created KVStore databases. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Parameter verification failed. @@ -3103,12 +3188,13 @@ declare namespace distributedKVStore { getAllKVStoreId(appId: string, callback: AsyncCallback): void; /** - * Obtains the storeId of all KVStore databases that are created by using the {@code getKVStore} method and not deleted by - * calling the {@code deleteKVStore} method. + * Obtains the storeId of all KVStore databases that are created by using the {@code getKVStore} method and not + * deleted by calling the {@code deleteKVStore} method. * - * @param { string } appId - Identifies the application that obtains the databases, and cannot exceed 256 characters. + * @param { string } appId - Identifies the application that obtains the databases, and cannot exceed 256 + * characters. * @returns { Promise } {string[]}: the storeId of all created KVStore databases. - * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified. + * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.KVStore.Core * @since 9 @@ -3117,10 +3203,11 @@ declare namespace distributedKVStore { /** * Register a death callback to get notification when the data manager service is terminated. - *

If the data manager service is terminated,you need to re-subscribe to data change notifications and synchronization - * completion notifications, and calling the sync method will return a failure. + *

If the data manager service is terminated,you need to re-subscribe to data change notifications and + * synchronization completion notifications, and calling the sync method will return a failure. * - * @param { 'distributedDataServiceDie' } event - Subscribed event name, fixed as 'distributedDataServiceDie', as a service status change events. + * @param { 'distributedDataServiceDie' } event - Subscribed event name, fixed as 'distributedDataServiceDie', + * as a service status change events. * @param { Callback } deathCallback - callback to be invoked when the data manager service is terminated. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types; @@ -3132,11 +3219,13 @@ declare namespace distributedKVStore { /** * Unregister the death callback. Not notification will be received when the data manager service is terminated. - *

The unregistered death callback must be a registered death callback of the database. If no death callback parameter - * is passed, all database death callbacks will be unregistered. + *

The unregistered death callback must be a registered death callback of the database. If no death callback + * parameter is passed, all database death callbacks will be unregistered. * - * @param { 'distributedDataServiceDie' } event - Unsubscribe event name, fixed as 'distributedDataServiceDie', as a service status change events. - * @param { Callback } deathCallback - the data manager service is terminated callback which has been registered. + * @param { 'distributedDataServiceDie' } event - Unsubscribe event name, fixed as 'distributedDataServiceDie', + * as a service status change events. + * @param { Callback } deathCallback - the data manager service is terminated callback which has been + * registered. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types; *
3.Parameter verification failed. diff --git a/interface_sdk/api/@ohos.data.graphStore.d.ts b/interface_sdk/api/@ohos.data.graphStore.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..0f904d61faaf09bb90a27484dd2e21933b88ae65 --- /dev/null +++ b/interface_sdk/api/@ohos.data.graphStore.d.ts @@ -0,0 +1,551 @@ +/* + * Copyright (c) 2025 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. + */ + +/** + * @file + * @kit ArkData + */ + +import Context from './application/BaseContext'; + +/** + * Provides methods for graphStore create and delete. + * + * @namespace graphStore + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ +declare namespace graphStore { + /** + * Indicates possible value types + * + * @typedef { null | number | string } ValueType + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + type ValueType = null | number | string; + + /** + * Describes the security level. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + enum SecurityLevel { + /** + * S1: means the db is low level security + * There are some low impact, when the data is leaked. + * + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + S1 = 1, + /** + * S2: means the db is middle level security + * There are some major impact, when the data is leaked. + * + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + S2 = 2, + /** + * S3: means the db is high level security + * There are some severity impact, when the data is leaked. + * + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + S3 = 3, + /** + * S4: means the db is critical level security + * There are some critical impact, when the data is leaked. + * + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + S4 = 4 + } + + /** + * Manages graph database configurations. + * + * @interface storeConfig + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + interface StoreConfig { + /** + * The database name. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + name: string; + /** + * Specifies the security level of the database. + * + * @type { SecurityLevel } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + securityLevel: SecurityLevel; + /** + * Specifies whether the database is encrypted. + * + * @type { ?boolean } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + encrypt?: boolean; + } + + /** + * Defines Vertex Type. + * + * @interface Vertex + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + interface Vertex { + /** + * The Vertex element identifier. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + vid: string; + /** + * Labels of the vertex. + * + * @type { Array } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + labels: Array; + /** + * Properties of the vertex. + * + * @type { Record } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + properties: Record; + } + + /** + * Defines Edge Type. + * + * @interface Edge + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + interface Edge { + /** + * The Edge element identifier. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + eid: string; + /** + * Type of the edge. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + type: string; + /** + * The Start Vertex element identifier. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + startVid: string; + /** + * The End Vertex element identifier. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + endVid: string; + /** + * Properties of the edge. + * + * @type { Record } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + properties: Record; + } + + /** + * Defines PathSegment Type. + * + * @interface PathSegment + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + interface PathSegment { + /** + * Start vertex. + * + * @type { Vertex } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + start: Vertex; + /** + * End vertex. + * + * @type { Vertex } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + end: Vertex; + /** + * The edge between start vertex and end vertex. + * + * @type { Edge } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + edge: Edge; + } + + /** + * Defines Path Type. + * + * @interface Path + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + interface Path { + /** + * Start vertex. + * + * @type { Vertex } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + start: Vertex; + /** + * End vertex. + * + * @type { Vertex } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + end: Vertex; + /** + * Length of segments. + * + * @type { number } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + length: number; + /** + * Segments in the path. + * + * @type { Array } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + segments: Array; + } + + /** + * The GQL statement execution result. + * + * @interface Result + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + interface Result { + /** + * The data records of querying the database. + * + * @type { ?Array> } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + records?: Array>; + } + + /** + * Provides transactional methods for managing the graph database. + * + * @interface Transaction + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + interface Transaction { + /** + * Execute a query procedure. + * + * @param { string } gql - Indicates the GQL statement to execute. + * @returns { Promise } The {@link Result} object if the operation is successful. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300001 - Database corrupted. + * @throws { BusinessError } 31300002 - Already closed. + * @throws { BusinessError } 31300003 - The database is busy. + * @throws { BusinessError } 31300004 - The database is out of memory. + * @throws { BusinessError } 31300005 - The database is full. + * @throws { BusinessError } 31300006 - A duplicate graph name, vertex or edge type, or vertex or edge property name exists. + * @throws { BusinessError } 31300007 - The graph name, vertex or edge type, or vertex or edge property is not defined. + * @throws { BusinessError } 31300008 - The graph name, vertex or edge type, or vertex or edge property name does not conform to constraints. + * @throws { BusinessError } 31300009 - The GQL statement syntax error. + * @throws { BusinessError } 31300010 - The GQL statement semantic error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + read(gql: string): Promise; + + /** + * Execute a data-modifying procedure. + * + * @param { string } gql - Indicates the GQL statement to execute. + * @returns { Promise } The {@link Result} object if the operation is successful. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300001 - Database corrupted. + * @throws { BusinessError } 31300002 - Already closed. + * @throws { BusinessError } 31300003 - The database is busy. + * @throws { BusinessError } 31300004 - The database is out of memory. + * @throws { BusinessError } 31300005 - The database is full. + * @throws { BusinessError } 31300006 - A duplicate graph name, vertex or edge type, or vertex or edge property name exists. + * @throws { BusinessError } 31300007 - The graph name, vertex or edge type, or vertex or edge property is not defined. + * @throws { BusinessError } 31300008 - The graph name, vertex or edge type, or vertex or edge property name does not conform to constraints. + * @throws { BusinessError } 31300009 - The GQL statement syntax error. + * @throws { BusinessError } 31300010 - The GQL statement semantic error. + * @throws { BusinessError } 31300012 - The number of graph names, vertex or edge types, or vertex or edge properties exceeds the limit. + * @throws { BusinessError } 31300013 - A conflicting constraint already exists. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + write(gql: string): Promise; + + /** + * Commit the transaction. + * + * @returns { Promise } The Promise used to return the result. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300001 - Database corrupted. + * @throws { BusinessError } 31300002 - Already closed. + * @throws { BusinessError } 31300003 - The database is busy. + * @throws { BusinessError } 31300004 - The database is out of memory. + * @throws { BusinessError } 31300005 - The database is full. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + commit(): Promise; + + /** + * Rollback the transaction. + * + * @returns { Promise } The Promise used to return the result. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300001 - Database corrupted. + * @throws { BusinessError } 31300002 - Already closed. + * @throws { BusinessError } 31300003 - The database is busy. + * @throws { BusinessError } 31300004 - The database is out of memory. + * @throws { BusinessError } 31300005 - The database is full. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + rollback(): Promise; + } + + /** + * Provides methods for managing the graph database. + * + * @interface GraphStore + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + interface GraphStore { + /** + * Execute a query procedure. + * + * @param { string } gql - Indicates the GQL statement to execute. + * @returns { Promise } The {@link Result} object if the operation is successful. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300001 - Database corrupted. + * @throws { BusinessError } 31300002 - Already closed. + * @throws { BusinessError } 31300003 - The database is busy. + * @throws { BusinessError } 31300004 - The database is out of memory. + * @throws { BusinessError } 31300005 - The database is full. + * @throws { BusinessError } 31300006 - A duplicate graph name, vertex or edge type, or vertex or edge property name exists. + * @throws { BusinessError } 31300007 - The graph name, vertex or edge type, or vertex or edge property is not defined. + * @throws { BusinessError } 31300008 - The graph name, vertex or edge type, or vertex or edge property name does not conform to constraints. + * @throws { BusinessError } 31300009 - The GQL statement syntax error. + * @throws { BusinessError } 31300010 - The GQL statement semantic error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + read(gql: string): Promise; + + /** + * Execute a data-modifying or catalog-modifying procedure. + * + * @param { string } gql - Indicates the GQL statement to execute. + * @returns { Promise } The {@link Result} object if the operation is successful. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300001 - Database corrupted. + * @throws { BusinessError } 31300002 - Already closed. + * @throws { BusinessError } 31300003 - The database is busy. + * @throws { BusinessError } 31300004 - The database is out of memory. + * @throws { BusinessError } 31300005 - The database is full. + * @throws { BusinessError } 31300006 - A duplicate graph name, vertex or edge type, or vertex or edge property name exists. + * @throws { BusinessError } 31300007 - The graph name, vertex or edge type, or vertex or edge property is not defined. + * @throws { BusinessError } 31300008 - The graph name, vertex or edge type, or vertex or edge property name does not conform to constraints. + * @throws { BusinessError } 31300009 - The GQL statement syntax error. + * @throws { BusinessError } 31300010 - The GQL statement semantic error. + * @throws { BusinessError } 31300012 - The number of graph names, vertex or edge types, or vertex or edge properties exceeds the limit. + * @throws { BusinessError } 31300013 - A conflicting constraint already exists. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + write(gql: string): Promise; + + /** + * Create a transaction instance. + * + * @returns { Promise } The {@link Transaction} object if the operation is successful. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300001 - Database corrupted. + * @throws { BusinessError } 31300002 - Already closed. + * @throws { BusinessError } 31300003 - The database is busy. + * @throws { BusinessError } 31300004 - The database is out of memory. + * @throws { BusinessError } 31300005 - The database is full. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + createTransaction(): Promise; + + /** + * Close the GraphStore and opened transactions will be rollback. + * @returns { Promise } The Promise returned by the function. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + close(): Promise; + } + + /** + * Obtains a graph store. + * You can set parameters of the graph store as required. In general, this method is recommended + * to obtain a graph store. + * + * @param { Context } context - Indicates the context of an application or ability. + * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this graph store. + * @returns { Promise } The graph store {@link GraphStore}. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300001 - Database corrupted. + * @throws { BusinessError } 31300014 - Failed to open or delete the database with an invalid database path. + * @throws { BusinessError } 31300015 - StoreConfig, for example, securityLevel or encrypt, is changed. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + function getStore(context: Context, config: StoreConfig): Promise; + + /** + * Deletes the database with a specified store config. + * + * @param { Context } context - Indicates the context of an application or ability. + * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this graph store. + * @returns { Promise } The Promise returned by the function. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300014 - Failed to open or delete the database with an invalid database path. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + function deleteStore(context: Context, config: StoreConfig): Promise; +} + +export default graphStore; diff --git a/interface_sdk/api/@ohos.data.intelligence.d.ts b/interface_sdk/api/@ohos.data.intelligence.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..f80129e159c4392276ab92ff6d9bf91ed24f3fe8 --- /dev/null +++ b/interface_sdk/api/@ohos.data.intelligence.d.ts @@ -0,0 +1,271 @@ +/* + * 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. + */ + +/** + * @file + * @kit ArkData + */ + +/** + * Provides methods for intelligent data processing. + * + * @namespace intelligence + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ +declare namespace intelligence { + /** + * Obtains a text embedding model. + * + * @param { ModelConfig } config - The configuration of the embedding model. + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + function getTextEmbeddingModel(config: ModelConfig): Promise; + + /** + * Obtains an image embedding model. + * + * @param { ModelConfig } config - The configuration of the embedding model. + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + function getImageEmbeddingModel(config: ModelConfig): Promise; + + /** + * Manages configurations of the embedding model. + * + * @interface ModelConfig + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + interface ModelConfig { + /** + * Version of the model. + * The outputs of text or image embedding models with the same version are in the same vector space. + * + * @type { ModelVersion } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + version: ModelVersion; + + /** + * Indicates whether NPU is used. + * + * @type { boolean } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + isNpuAvailable: boolean; + + /** + * If NPU is used for accelerating, a local path is required for model caching. + * + * @type { ?string } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + cachePath?: string; + } + + /** + * Version of the model. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + enum ModelVersion { + /** + * The basic embedding model. + * + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + BASIC_MODEL = 0 + } + + /** + * Describes the text embedding functions of the multi-modal embedding model. + * Chinese and English are supported. + * + * @interface TextEmbedding + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + interface TextEmbedding { + /** + * Loads this text embedding model. If the loading fails, an error code is returned. + * + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + loadModel(): Promise; + + /** + * Releases this text embedding model. If the releasing fails, an error code is returned. + * + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + releaseModel(): Promise; + + /** + * Obtains the embedding vector of the given text. + * The model can process up to 512 characters of text per inference, supporting both Chinese and English. + * + * @param { string } text - The input text of the embedding model. + * @returns { Promise> } The promise used to return the embedding result. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + getEmbedding(text: string): Promise>; + + /** + * Obtains the embedding vector of a given batch of text. + * The model can process up to 512 characters of text per inference, supporting both Chinese and English. + * + * @param { Array } batchTexts - The input batch of texts of the embedding model. + * @returns { Promise>> } The promise used to return the embedding result. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + getEmbedding(batchTexts: Array): Promise>>; + } + + /** + * Describes the image embedding functions of the multi-modal embedding model. + * + * @interface ImageEmbedding + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + interface ImageEmbedding { + /** + * Loads this image embedding model. If the loading fails, an error code is returned. + * + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + loadModel(): Promise; + + /** + * Releases this image embedding model. If the releasing fails, an error code is returned. + * + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + releaseModel(): Promise; + + /** + * Obtains the embedding vector of the given image. + * The model can handle images below 20 MB in size in a single inference. + * + * @param { Image } image - The input image of the embedding model. + * @returns { Promise> } The promise used to return the embedding result. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + getEmbedding(image: Image): Promise>; + } + + /** + * The type of the image can be its URI. + * + * @typedef { string } Image + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 15 + */ + type Image = string; + + /** + * Splits text. + * + * @param { string } text - Text for chunking. The length of the text is no longer then 100k tokens. + * @param { SplitConfig } config - Configurations of text chunking. + * @returns { Promise> } The promise used to return the result. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + function splitText(text: string, config: SplitConfig): Promise>; + + /** + * Manages text chunk process configurations. + * + * @interface SplitConfig + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + interface SplitConfig { + /** + * The maximun size of chunks. + * + * @type { number } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + size: number; + + /** + * The ratio of overlap between adjacent chunks. + * + * @type { number } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + overlapRatio: number; + } +} + +export default intelligence; \ No newline at end of file diff --git a/interface_sdk/api/@ohos.data.preferences.d.ts b/interface_sdk/api/@ohos.data.preferences.d.ts index 93426060de4f8890ba909ccc1533c252a56c0b3c..40d6de6dff974f843735acc39c4256f480727fba 100644 --- a/interface_sdk/api/@ohos.data.preferences.d.ts +++ b/interface_sdk/api/@ohos.data.preferences.d.ts @@ -74,7 +74,8 @@ declare namespace preferences { /** * Indicates possible value types * - * @typedef {number | string | boolean | Array | Array | Array | Uint8Array | object | bigint} + * @typedef {number | string | boolean | Array | Array | Array | Uint8Array | object | + * bigint} * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice * @since 12 @@ -149,6 +150,34 @@ declare namespace preferences { */ const MAX_VALUE_LENGTH: number; + /** + * the storage type + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @atomicservice + * @since 18 + */ + enum StorageType { + /** + * XML storage type + * + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @atomicservice + * @since 18 + */ + XML = 0, + + /** + * GSKV storage type + * + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @atomicservice + * @since 18 + */ + GSKV + } + /** * Manages preferences file configurations. * @@ -202,6 +231,16 @@ declare namespace preferences { * @since 11 */ dataGroupId?: string | null | undefined; + + /** + * The preferences storage type. + * + * @type { ?(StorageType | null | undefined) } + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @atomicservice + * @since 18 + */ + storageType?: StorageType | null | undefined; } /** @@ -212,10 +251,10 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - The {@link Preferences} instance matching the specified - * preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * preferences file name. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -227,10 +266,10 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - The {@link Preferences} instance matching the specified - * preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * preferences file name. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -243,10 +282,10 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - The {@link Preferences} instance matching the specified - * preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * preferences file name. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -263,13 +302,13 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @param { AsyncCallback } callback - The {@link Preferences} instance matching the specified - * preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * preferences file name. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -282,14 +321,14 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @param { AsyncCallback } callback - The {@link Preferences} instance matching the specified - * preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * preferences file name. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -305,9 +344,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } The {@link Preferences} instance matching the specified preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -319,9 +358,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } The {@link Preferences} instance matching the specified preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -334,9 +373,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } The {@link Preferences} instance matching the specified preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -353,12 +392,12 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @returns { Promise } The {@link Preferences} instance matching the specified preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -371,13 +410,13 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @returns { Promise } The {@link Preferences} instance matching the specified preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -394,12 +433,12 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @returns { Preferences } The {@link Preferences} instance matching the specified preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -413,13 +452,13 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @returns { Preferences } The {@link Preferences} instance matching the specified preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -427,6 +466,16 @@ declare namespace preferences { */ function getPreferencesSync(context: Context, options: Options): Preferences; + /** + * check the {@link StorageType} type is supported or not on current system. + * @param { StorageType } type - Indicates storage type which want to check. + * @returns { boolean } a boolean value indicates this system support the type or not. + * @throws { BusinessError } 401 - Parameter error. Possible causes: Incorrect parameter types + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @atomicservice + * @since 18 + */ + function isStorageTypeSupported(type: StorageType): boolean; /** * Deletes a {@link Preferences} instance matching a specified preferences file name * from the cache which is performed by removePreferencesFromCache and deletes the @@ -438,10 +487,10 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -456,10 +505,10 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -475,11 +524,11 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -498,13 +547,13 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -520,14 +569,14 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -546,10 +595,10 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -564,10 +613,10 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -583,11 +632,11 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -606,13 +655,13 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -628,14 +677,14 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -653,9 +702,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -669,9 +718,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -686,9 +735,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -707,12 +756,12 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -727,13 +776,13 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -751,9 +800,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -767,9 +816,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -784,9 +833,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -805,12 +854,12 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -825,13 +874,13 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -848,9 +897,9 @@ declare namespace preferences { * * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -864,9 +913,9 @@ declare namespace preferences { * * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -884,12 +933,12 @@ declare namespace preferences { * * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -903,13 +952,13 @@ declare namespace preferences { * * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -959,13 +1008,13 @@ declare namespace preferences { *

If the value is {@code null} or not in the ValueType format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } defValue - Indicates the default value to return. * @param { AsyncCallback } callback - The value matching the specified key if it is found; - * returns the default value otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -974,13 +1023,13 @@ declare namespace preferences { *

If the value is {@code null} or not in the ValueType format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } defValue - Indicates the default value to return. * @param { AsyncCallback } callback - The value matching the specified key if it is found; - * returns the default value otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -990,13 +1039,13 @@ declare namespace preferences { *

If the value is {@code null} or not in the ValueType format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } defValue - Indicates the default value to return. * @param { AsyncCallback } callback - The value matching the specified key if it is found; - * returns the default value otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1010,13 +1059,13 @@ declare namespace preferences { *

If the value is {@code null} or not in the ValueType format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } defValue - Indicates the default value to return. * @returns { Promise } The value matching the specified key if it is found; - * returns the default value otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -1025,13 +1074,13 @@ declare namespace preferences { *

If the value is {@code null} or not in the ValueType format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } defValue - Indicates the default value to return. * @returns { Promise } The value matching the specified key if it is found; - * returns the default value otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1041,13 +1090,13 @@ declare namespace preferences { *

If the value is {@code null} or not in the ValueType format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } defValue - Indicates the default value to return. * @returns { Promise } The value matching the specified key if it is found; - * returns the default value otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1061,13 +1110,13 @@ declare namespace preferences { *

If the value is {@code null} or not in the ValueType format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } defValue - Indicates the default value to return. * @returns { ValueType } The value matching the specified key if it is found; - * returns the default value otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1077,13 +1126,13 @@ declare namespace preferences { *

If the value is {@code null} or not in the ValueType format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } defValue - Indicates the default value to return. * @returns { ValueType } The value matching the specified key if it is found; - * returns the default value otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1175,12 +1224,12 @@ declare namespace preferences { * Checks whether the {@link Preferences} object contains a preferences matching a specified key. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. - * @param { AsyncCallback } callback - {@code true} if the {@link Preferences} object contains a preferences - * with the specified key;returns {@code false} otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_KEY_LENGTH. + * @param { AsyncCallback } callback - {@code true} if the {@link Preferences} object contains a + * preferences with the specified key;returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -1188,12 +1237,12 @@ declare namespace preferences { * Checks whether the {@link Preferences} object contains a preferences matching a specified key. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. - * @param { AsyncCallback } callback - {@code true} if the {@link Preferences} object contains a preferences - * with the specified key;returns {@code false} otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_KEY_LENGTH. + * @param { AsyncCallback } callback - {@code true} if the {@link Preferences} object contains a + * preferences with the specified key;returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1202,12 +1251,12 @@ declare namespace preferences { * Checks whether the {@link Preferences} object contains a preferences matching a specified key. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. - * @param { AsyncCallback } callback - {@code true} if the {@link Preferences} object contains a preferences - * with the specified key;returns {@code false} otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_KEY_LENGTH. + * @param { AsyncCallback } callback - {@code true} if the {@link Preferences} object contains a + * preferences with the specified key;returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1220,12 +1269,12 @@ declare namespace preferences { * Checks whether the {@link Preferences} object contains a preferences matching a specified key. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { Promise } {@code true} if the {@link Preferences} object contains - * a preferences with the specified key; returns {@code false} otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * a preferences with the specified key; returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -1233,12 +1282,12 @@ declare namespace preferences { * Checks whether the {@link Preferences} object contains a preferences matching a specified key. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { Promise } {@code true} if the {@link Preferences} object contains - * a preferences with the specified key; returns {@code false} otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * a preferences with the specified key; returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1247,12 +1296,12 @@ declare namespace preferences { * Checks whether the {@link Preferences} object contains a preferences matching a specified key. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { Promise } {@code true} if the {@link Preferences} object contains - * a preferences with the specified key; returns {@code false} otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * a preferences with the specified key; returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1266,12 +1315,12 @@ declare namespace preferences { * is executed synchronously. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { boolean } {@code true} if the {@link Preferences} object contains - * a preferences with the specified key; returns {@code false} otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * a preferences with the specified key; returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1281,12 +1330,12 @@ declare namespace preferences { * is executed synchronously. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { boolean } {@code true} if the {@link Preferences} object contains - * a preferences with the specified key; returns {@code false} otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * a preferences with the specified key; returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1301,13 +1350,13 @@ declare namespace preferences { * file. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. + * MAX_VALUE_LENGTH. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -1315,15 +1364,19 @@ declare namespace preferences { * Sets an int value for the key in the {@link Preferences} object. *

You can call the {@link #flush} method to save the {@link Preferences} object to the * file. + *

When the value contains strings in a non-UTF-8 format, use the Uint8Array type for storage. + * Otherwise, the format of the persistent file is incorrect and the file is damaged. + *

If the corresponding key already exists, the {@link put} method will overwrite its value. + * You can use the {@link #hasSync} method to check whether the corresponding key-value pair exists. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. + * MAX_VALUE_LENGTH. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1332,15 +1385,19 @@ declare namespace preferences { * Sets an int value for the key in the {@link Preferences} object. *

You can call the {@link #flush} method to save the {@link Preferences} object to the * file. + *

When the value contains strings in a non-UTF-8 format, use the Uint8Array type for storage. + * Otherwise, the format of the persistent file is incorrect and the file is damaged. + *

If the corresponding key already exists, the {@link put} method will overwrite its value. + * You can use the {@link #hasSync} method to check whether the corresponding key-value pair exists. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. + * MAX_VALUE_LENGTH. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1353,15 +1410,19 @@ declare namespace preferences { * Sets an int value for the key in the {@link Preferences} object. *

You can call the {@link #flush} method to save the {@link Preferences} object to the * file. + *

When the value contains strings in a non-UTF-8 format, use the Uint8Array type for storage. + * Otherwise, the format of the persistent file is incorrect and the file is damaged. + *

If the corresponding key already exists, the {@link put} method will overwrite its value. + * You can use the {@link #hasSync} method to check whether the corresponding key-value pair exists. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. + * MAX_VALUE_LENGTH. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -1369,15 +1430,19 @@ declare namespace preferences { * Sets an int value for the key in the {@link Preferences} object. *

You can call the {@link #flush} method to save the {@link Preferences} object to the * file. + *

When the value contains strings in a non-UTF-8 format, use the Uint8Array type for storage. + * Otherwise, the format of the persistent file is incorrect and the file is damaged. + *

If the corresponding key already exists, the {@link put} method will overwrite its value. + * You can use the {@link #hasSync} method to check whether the corresponding key-value pair exists. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. + * MAX_VALUE_LENGTH. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1386,15 +1451,19 @@ declare namespace preferences { * Sets an int value for the key in the {@link Preferences} object. *

You can call the {@link #flush} method to save the {@link Preferences} object to the * file. + *

When the value contains strings in a non-UTF-8 format, use the Uint8Array type for storage. + * Otherwise, the format of the persistent file is incorrect and the file is damaged. + *

If the corresponding key already exists, the {@link put} method will overwrite its value. + * You can use the {@link #hasSync} method to check whether the corresponding key-value pair exists. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. + * MAX_VALUE_LENGTH. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1407,14 +1476,18 @@ declare namespace preferences { * Sets an int value for the key in the {@link Preferences} object. This interface is executed synchronously. *

You can call the {@link #flush} method to save the {@link Preferences} object to the * file. + *

When the value contains strings in a non-UTF-8 format, use the Uint8Array type for storage. + * Otherwise, the format of the persistent file is incorrect and the file is damaged. + *

If the corresponding key already exists, the {@link put} method will overwrite its value. + * You can use the {@link #hasSync} method to check whether the corresponding key-value pair exists. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_VALUE_LENGTH. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1423,14 +1496,18 @@ declare namespace preferences { * Sets an int value for the key in the {@link Preferences} object. This interface is executed synchronously. *

You can call the {@link #flush} method to save the {@link Preferences} object to the * file. + *

When the value contains strings in a non-UTF-8 format, use the Uint8Array type for storage. + * Otherwise, the format of the persistent file is incorrect and the file is damaged. + *

If the corresponding key already exists, the {@link put} method will overwrite its value. + * You can use the {@link #hasSync} method to check whether the corresponding key-value pair exists. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_VALUE_LENGTH. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1441,44 +1518,41 @@ declare namespace preferences { /** * Deletes the preferences with a specified key from the {@link Preferences} object. - *

You can call the {@link #flush} method to save the {@link Preferences} object to the - * file. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ /** * Deletes the preferences with a specified key from the {@link Preferences} object. - *

You can call the {@link #flush} method to save the {@link Preferences} object to the - * file. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 */ /** * Deletes the preferences with a specified key from the {@link Preferences} object. - *

You can call the {@link #flush} method to save the {@link Preferences} object to the - * file. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1489,44 +1563,41 @@ declare namespace preferences { /** * Deletes the preferences with a specified key from the {@link Preferences} object. - *

You can call the {@link #flush} method to save the {@link Preferences} object to the - * file. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ /** * Deletes the preferences with a specified key from the {@link Preferences} object. - *

You can call the {@link #flush} method to save the {@link Preferences} object to the - * file. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 */ /** * Deletes the preferences with a specified key from the {@link Preferences} object. - *

You can call the {@link #flush} method to save the {@link Preferences} object to the - * file. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1541,10 +1612,10 @@ declare namespace preferences { * object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_KEY_LENGTH. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1555,10 +1626,10 @@ declare namespace preferences { * object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_KEY_LENGTH. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1706,14 +1777,25 @@ declare namespace preferences { */ flush(): Promise; + /** + * Saves the {@link Preferences} object to the file. + * + * @throws { BusinessError } 15500000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 14 + */ + flushSync(): void; + /** * Registers an observer to listen for the change of a {@link Preferences} object. * * @param { 'change' } type - Indicates the callback when preferences changes. * @param { Callback<{ key: string }> } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -1722,9 +1804,9 @@ declare namespace preferences { * * @param { 'change' } type - Indicates the callback when preferences changes. * @param { Function } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1734,9 +1816,9 @@ declare namespace preferences { * * @param { 'change' } type - Indicates the callback when preferences changes. * @param { Callback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1750,10 +1832,10 @@ declare namespace preferences { * * @param { 'multiProcessChange' } type - Indicates the callback when preferences changed in multiple processes. * @param { Function } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. - * @throws { BusinessError } 15500019 - Failed to obtain subscription service. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. + * @throws { BusinessError } 15500019 - Failed to obtain the subscription service. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 10 */ @@ -1762,11 +1844,11 @@ declare namespace preferences { * * @param { 'multiProcessChange' } type - Indicates the callback when preferences changed in multiple processes. * @param { Callback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15500019 - Failed to obtain subscription service. + * @throws { BusinessError } 15500019 - Failed to obtain the subscription service. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice * @since 11 @@ -1779,9 +1861,9 @@ declare namespace preferences { * @param { 'dataChange' } type - Indicates the type of the event to observe. * @param { Array } keys - Indicates one or more keys to listen for. * @param { Callback> } callback - Indicates the callback used to return the data change. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -1794,9 +1876,9 @@ declare namespace preferences { * * @param { 'change' } type - Indicates the callback when preferences changes. * @param { Callback<{ key: string }> } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -1805,9 +1887,9 @@ declare namespace preferences { * * @param { 'change' } type - Indicates the callback when preferences changes. * @param { Function } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1817,9 +1899,9 @@ declare namespace preferences { * * @param { 'change' } type - Indicates the callback when preferences changes. * @param { Callback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1833,9 +1915,9 @@ declare namespace preferences { * * @param { 'multiProcessChange' } type - Indicates the callback when preferences changed in multiple processes. * @param { Function } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 10 */ @@ -1844,9 +1926,9 @@ declare namespace preferences { * * @param { 'multiProcessChange' } type - Indicates the callback when preferences changed in multiple processes. * @param { Callback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -1860,9 +1942,9 @@ declare namespace preferences { * @param { 'dataChange' } type - Indicates the event type. * @param { Array } keys - Indicates the data whose changes are not observed. * @param { Callback> } callback - Indicates the callback to unregister. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice diff --git a/interface_sdk/api/@ohos.data.relationalStore.d.ts b/interface_sdk/api/@ohos.data.relationalStore.d.ts index 1c9b5a9c296042123fd5d2d68257ffed5a9b82d5..8acdd4368cabc9fd9809d388f90c9098f1395e37 100644 --- a/interface_sdk/api/@ohos.data.relationalStore.d.ts +++ b/interface_sdk/api/@ohos.data.relationalStore.d.ts @@ -346,7 +346,7 @@ declare namespace relationalStore { * @type { ?string } * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform - * @since 16 + * @since 18 */ rootDir?: string; @@ -384,7 +384,7 @@ declare namespace relationalStore { * * @type { ?boolean } * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 18 */ vector?: boolean; @@ -431,7 +431,7 @@ declare namespace relationalStore { * * @type { ?Tokenizer } * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 17 */ tokenizer?: Tokenizer; @@ -641,28 +641,28 @@ declare namespace relationalStore { * * @enum { number } * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 17 */ enum Tokenizer { /** * NONE_TOKENIZER: not use tokenizer * * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 17 */ NONE_TOKENIZER = 0, /** * ICU_TOKENIZER: native icu tokenizer. * * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 17 */ ICU_TOKENIZER, /** * CUSTOM_TOKENIZER: self-developed enhance tokenizer. * * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 18 */ CUSTOM_TOKENIZER } @@ -941,6 +941,46 @@ declare namespace relationalStore { executeTime: number; } + /** + * Defines an exception message. + * + * @interface ExceptionMessage + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + interface ExceptionMessage { + /** + * Error code returned by SQLite, see {@link https://www.sqlite.org/rescode.html}. + * + * @type { number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + code: number; + + /** + * Error message. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + message: string; + + /** + * SQL statement executed when the exception occurs. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + sql: string; + } + /** * Describes the {@code RdbStore} type. * @@ -1295,9 +1335,18 @@ declare namespace relationalStore { * * @type { ?boolean } * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 18 */ asyncDownloadAsset?: boolean; + + /** + * Specifies whether the cloud sync is enabled for the database. + * + * @type { ?boolean } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 18 + */ + enableCloud?: boolean; } /** @@ -1548,6 +1597,99 @@ declare namespace relationalStore { transactionType?: TransactionType; } + /** + * Enumerates the data types of a column. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + enum ColumnType { + /** + * The value in the column is null. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + NULL, + + /** + * The value in the column is a 64-bit integer. It can be used to hold an 8-bit (including Boolean values), 16-bit, + * 32-bit, or 64-bit integer.if the 64-bit integer is greater than 2^53 or less than -2^53, you can use getString + * to convert the 64-bit integer into a string. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + INTEGER, + + /** + * The value in the column is a floating point number. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + REAL, + + /** + * The value in the column is a string. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + TEXT, + + /** + * The value in the column is a Uint8Array. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + BLOB, + + /** + * The value in the column is an asset. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + ASSET, + + /** + * The value in the column is an array of assets. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + ASSETS, + + /** + * The value in the column is a Float32Array. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + FLOAT_VECTOR, + + /** + * The value in the column is a bigint. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + UNLIMITED_INT, + } + /** * Manages relational database configurations. * @@ -2183,7 +2325,8 @@ declare namespace relationalStore { * Configure RdbPredicates to specify the start position of the returned result. * Use this method together with limit(number). * - * @param { number } rowOffset - Indicates the start position of the returned result. The value is a positive integer. + * @param { number } rowOffset - Indicates the start position of the returned result. + * The value is a positive integer. * @returns { RdbPredicates } - The SQL query statement with the specified {@link RdbPredicates}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -2194,7 +2337,8 @@ declare namespace relationalStore { * Configure RdbPredicates to specify the start position of the returned result. * Use this method together with limit(number). * - * @param { number } rowOffset - Indicates the start position of the returned result. The value is a positive integer. + * @param { number } rowOffset - Indicates the start position of the returned result. + * The value is a positive integer. * @returns { RdbPredicates } - The SQL query statement with the specified {@link RdbPredicates}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -2335,6 +2479,20 @@ declare namespace relationalStore { * @since 12 */ notLike(field: string, value: string): RdbPredicates; + + /** + * Filters the grouped data that meets the specified conditions. + * + * @param { string } conditions - Conditions used to filter the data obtained using GROUP BY. + * @param { Array } args - Parameters to be used in the conditions. + * @returns { RdbPredicates } - Returns the RdbPredicates object. + * @throws { BusinessError } 14800001 - Invalid args. Possible causes: 1. conditions is empty; + *
2. The GROUP BY clause is missing. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + having(conditions:string, args?: Array): RdbPredicates; } /** @@ -2543,11 +2701,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800019 - The SQL must be a query statement. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -2601,11 +2760,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800019 - The SQL must be a query statement. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -2625,13 +2785,83 @@ declare namespace relationalStore { */ getColumnName(columnIndex: number): string; + /** + * Obtains the column data type based on the specified column index. + * The column index is passed as an input parameter. + * + * @param { number | string } columnIdentifier - Index or name of the column. + * @returns { Promise } Promise used to return the data type obtained, + * in an {@link ColumnType} instance. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. + * @throws { BusinessError } 14800019 - The SQL must be a query statement. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. + * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800030 - SQLite: Unable to open the database file. + * @throws { BusinessError } 14800031 - SQLite: TEXT or BLOB exceeds size limit. + * @throws { BusinessError } 14800032 - SQLite: Abort due to constraint violation. + * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. + * @throws { BusinessError } 14800034 - SQLite: Library used incorrectly. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + getColumnType(columnIdentifier: number | string): Promise; + + /** + * Obtains the column data type based on the specified column index. This API returns the result synchronously. + * + * @param { number | string } columnIdentifier - Index or name of the column. + * @returns { ColumnType } Column data type obtained. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. + * @throws { BusinessError } 14800019 - The SQL must be a query statement. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. + * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800030 - SQLite: Unable to open the database file. + * @throws { BusinessError } 14800031 - SQLite: TEXT or BLOB exceeds size limit. + * @throws { BusinessError } 14800032 - SQLite: Abort due to constraint violation. + * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. + * @throws { BusinessError } 14800034 - SQLite: Library used incorrectly. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + getColumnTypeSync(columnIdentifier: number | string): ColumnType; + /** * Go to the specified row of the result set forwards or backwards by an offset relative to its current position. * A positive offset indicates moving backwards, and a negative offset indicates moving forwards. * * @param { number } offset - Indicates the offset relative to the current position. * @returns { boolean } True if the result set is moved successfully and does not go beyond the range; - * Returns false otherwise. + * Returns false otherwise. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -2644,7 +2874,7 @@ declare namespace relationalStore { * * @param { number } offset - Indicates the offset relative to the current position. * @returns { boolean } True if the result set is moved successfully and does not go beyond the range; - * Returns false otherwise. + * Returns false otherwise. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -2658,15 +2888,16 @@ declare namespace relationalStore { * * @param { number } offset - Indicates the offset relative to the current position. * @returns { boolean } True if the result set is moved successfully and does not go beyond the range; - * Returns false otherwise. + * Returns false otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800019 - The SQL must be a query statement. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -2717,11 +2948,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800019 - The SQL must be a query statement. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -2745,7 +2977,7 @@ declare namespace relationalStore { * Go to the first row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is empty. + * Returns false otherwise, for example, if the result set is empty. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 @@ -2754,7 +2986,7 @@ declare namespace relationalStore { * Go to the first row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is empty. + * Returns false otherwise, for example, if the result set is empty. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -2764,13 +2996,14 @@ declare namespace relationalStore { * Go to the first row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is empty. + * Returns false otherwise, for example, if the result set is empty. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800019 - The SQL must be a query statement. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -2794,7 +3027,7 @@ declare namespace relationalStore { * Go to the last row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is empty. + * Returns false otherwise, for example, if the result set is empty. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 @@ -2803,7 +3036,7 @@ declare namespace relationalStore { * Go to the last row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is empty. + * Returns false otherwise, for example, if the result set is empty. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -2813,13 +3046,14 @@ declare namespace relationalStore { * Go to the last row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is empty. + * Returns false otherwise, for example, if the result set is empty. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800019 - The SQL must be a query statement. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -2843,7 +3077,7 @@ declare namespace relationalStore { * Go to the next row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is already in the last row. + * Returns false otherwise, for example, if the result set is already in the last row. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 @@ -2852,7 +3086,7 @@ declare namespace relationalStore { * Go to the next row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is already in the last row. + * Returns false otherwise, for example, if the result set is already in the last row. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -2862,13 +3096,14 @@ declare namespace relationalStore { * Go to the next row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is already in the last row. + * Returns false otherwise, for example, if the result set is already in the last row. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800019 - The SQL must be a query statement. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -2892,7 +3127,7 @@ declare namespace relationalStore { * Go to the previous row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is already in the first row. + * Returns false otherwise, for example, if the result set is already in the first row. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 @@ -2901,7 +3136,7 @@ declare namespace relationalStore { * Go to the previous row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is already in the first row. + * Returns false otherwise, for example, if the result set is already in the first row. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -2911,13 +3146,14 @@ declare namespace relationalStore { * Go to the previous row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is already in the first row. + * Returns false otherwise, for example, if the result set is already in the first row. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800019 - The SQL must be a query statement. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -2974,11 +3210,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3035,11 +3272,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3096,11 +3334,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3157,11 +3396,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3205,11 +3445,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3253,11 +3494,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3287,11 +3529,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3320,11 +3563,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3353,10 +3597,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - The capability is not supported because the database is not a vector DB. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3371,7 +3616,8 @@ declare namespace relationalStore { * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. * @throws { BusinessError } 14800034 - SQLite: Library used incorrectly. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @systemapi + * @since 12 */ getFloat32Array(columnIndex: number): Float32Array; @@ -3389,11 +3635,12 @@ declare namespace relationalStore { * * @returns { ValuesBucket } Indicates the row of data {@link ValuesBucket} to be inserted into the table. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3418,11 +3665,12 @@ declare namespace relationalStore { * * @returns { ValuesBucket } Indicates the row of data {@link ValuesBucket} to be inserted into the table. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3446,15 +3694,17 @@ declare namespace relationalStore { * Obtains the values of all columns in the specified rows. * @param { number } maxCount - Indicates the maximum number of rows. * @param { number } position - Indicates the start position to obtain the values. - * @returns { Promise> } Promise used to return the values obtained, in an{@link Array}. + * @returns { Promise> } Promise used to return the values obtained, + * in an {@link Array}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3467,7 +3717,7 @@ declare namespace relationalStore { * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform - * @since 16 + * @since 18 */ getRows(maxCount: number, position?: number): Promise>; @@ -3477,11 +3727,12 @@ declare namespace relationalStore { * @returns { sendableRelationalStore.ValuesBucket } Indicates the row of data * {@link sendableRelationalStore.ValuesBucket} to be inserted into the table. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3505,7 +3756,7 @@ declare namespace relationalStore { * * @param { number } columnIndex - Indicates the specified column index, which starts from 0. * @returns { boolean } True if the value of the specified column in the current row is null; - * Returns false otherwise. + * Returns false otherwise. * @throws { BusinessError } 14800013 - The column value is null or the column type is incompatible. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -3517,7 +3768,7 @@ declare namespace relationalStore { * * @param { number } columnIndex - Indicates the specified column index, which starts from 0. * @returns { boolean } True if the value of the specified column in the current row is null; - * Returns false otherwise. + * Returns false otherwise. * @throws { BusinessError } 14800013 - The column value is null or the column type is incompatible. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -3530,15 +3781,16 @@ declare namespace relationalStore { * * @param { number } columnIndex - Indicates the specified column index, which starts from 0. * @returns { boolean } True if the value of the specified column in the current row is null; - * Returns false otherwise. + * Returns false otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3580,7 +3832,7 @@ declare namespace relationalStore { * Calling this method on the result set will release all of its resources and makes it ineffective. * * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800012 - Row out of bounds. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 12 @@ -3634,9 +3886,10 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -3695,10 +3948,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3744,10 +3998,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3803,10 +4058,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3852,10 +4108,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3886,10 +4143,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3921,10 +4179,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3948,8 +4207,10 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. - * @param { AsyncCallback } callback - The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { AsyncCallback } callback - + * The number of values that were inserted if the operation is successful. returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. @@ -3960,8 +4221,10 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. - * @param { AsyncCallback } callback - The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { AsyncCallback } callback - + * The number of values that were inserted if the operation is successful. returns -1 otherwise. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -3974,15 +4237,18 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. - * @param { AsyncCallback } callback - The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @param { Array } values - Indicates the rows of data {@link ValuesBucket} + * to be inserted into the table. + * @param { AsyncCallback } callback - + * The number of values that were inserted if the operation is successful. returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4007,8 +4273,10 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. - * @returns { Promise } The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @returns { Promise } The number of values that were inserted if the operation is successful. + * returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. @@ -4019,8 +4287,10 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. - * @returns { Promise } The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @returns { Promise } The number of values that were inserted if the operation is successful. + * returns -1 otherwise. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -4033,15 +4303,18 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. - * @returns { Promise } The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @returns { Promise } The number of values that were inserted if the operation is successful. + * returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4066,15 +4339,17 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. * @returns { number } The number of values that were inserted if the operation is successful. returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4099,16 +4374,19 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. - * @returns { Promise } The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @returns { Promise } The number of values that were inserted if the operation is successful. + * returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4125,7 +4403,7 @@ declare namespace relationalStore { * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform - * @since 16 + * @since 18 */ batchInsertWithConflictResolution(table: string, values: Array, conflict: ConflictResolution): Promise; @@ -4133,16 +4411,17 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. - * @returns { Promise } The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. * @returns { number } The number of values that were inserted if the operation is successful. returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4159,7 +4438,7 @@ declare namespace relationalStore { * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform - * @since 16 + * @since 18 */ batchInsertWithConflictResolutionSync(table: string, values: Array, conflict: ConflictResolution): number; @@ -4167,8 +4446,9 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -4180,8 +4460,9 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; @@ -4195,16 +4476,18 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4229,8 +4512,9 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. @@ -4245,17 +4529,19 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4275,18 +4561,19 @@ declare namespace relationalStore { * @since 12 */ update( - values: ValuesBucket, - predicates: RdbPredicates, - conflict: ConflictResolution, - callback: AsyncCallback + values: ValuesBucket, + predicates: RdbPredicates, + conflict: ConflictResolution, + callback: AsyncCallback ): void; /** * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -4298,8 +4585,9 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; @@ -4313,16 +4601,18 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4347,8 +4637,9 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. @@ -4363,17 +4654,19 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4398,17 +4691,19 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates with sync interface. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. * @returns { number } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4434,14 +4729,15 @@ declare namespace relationalStore { * * @param { string } table - Indicates the target table. * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. + * The key-value pairs are associated with column names of the database table. * @param { dataSharePredicates.DataSharePredicates } predicates - Indicates the specified update condition by - * the instance object of {@link dataSharePredicates.DataSharePredicates}. + * the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4452,15 +4748,16 @@ declare namespace relationalStore { * * @param { string } table - Indicates the target table. * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. + * The key-value pairs are associated with column names of the database table. * @param { dataSharePredicates.DataSharePredicates } predicates - Indicates the specified update condition by - * the instance object of {@link dataSharePredicates.DataSharePredicates}. + * the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4471,18 +4768,20 @@ declare namespace relationalStore { * * @param { string } table - Indicates the target table. * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. + * The key-value pairs are associated with column names of the database table. * @param { dataSharePredicates.DataSharePredicates } predicates - Indicates the specified update condition by - * the instance object of {@link dataSharePredicates.DataSharePredicates}. + * the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { AsyncCallback } callback - The number of affected rows. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4503,10 +4802,10 @@ declare namespace relationalStore { * @since 12 */ update( - table: string, - values: ValuesBucket, - predicates: dataSharePredicates.DataSharePredicates, - callback: AsyncCallback + table: string, + values: ValuesBucket, + predicates: dataSharePredicates.DataSharePredicates, + callback: AsyncCallback ): void; /** @@ -4514,14 +4813,15 @@ declare namespace relationalStore { * * @param { string } table - Indicates the target table. * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. + * The key-value pairs are associated with column names of the database table. * @param { dataSharePredicates.DataSharePredicates } predicates - Indicates the specified update condition by - * the instance object of {@link dataSharePredicates.DataSharePredicates}. + * the instance object of {@link dataSharePredicates.DataSharePredicates}. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4532,15 +4832,16 @@ declare namespace relationalStore { * * @param { string } table - Indicates the target table. * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. + * The key-value pairs are associated with column names of the database table. * @param { dataSharePredicates.DataSharePredicates } predicates - Indicates the specified update condition by - * the instance object of {@link dataSharePredicates.DataSharePredicates}. + * the instance object of {@link dataSharePredicates.DataSharePredicates}. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4551,18 +4852,20 @@ declare namespace relationalStore { * * @param { string } table - Indicates the target table. * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. + * The key-value pairs are associated with column names of the database table. * @param { dataSharePredicates.DataSharePredicates } predicates - Indicates the specified update condition by - * the instance object of {@link dataSharePredicates.DataSharePredicates}. + * the instance object of {@link dataSharePredicates.DataSharePredicates}. * @returns { Promise } The number of affected rows. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4587,7 +4890,8 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -4598,7 +4902,8 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; @@ -4611,15 +4916,17 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4643,7 +4950,8 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -4654,7 +4962,8 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. * @returns { Promise } return the number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; @@ -4667,15 +4976,17 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. * @returns { Promise } return the number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4699,15 +5010,17 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates with sync interface. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. - * @returns { number } return the number of affected rows. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. + * @returns { number } return the number of rows deleted. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4732,12 +5045,13 @@ declare namespace relationalStore { * * @param { string } table - Indicates the target table. * @param { dataSharePredicates.DataSharePredicates } predicates - The specified delete condition by - * the instance object of {@link dataSharePredicates.DataSharePredicates}. + * the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4747,14 +5061,15 @@ declare namespace relationalStore { * Deletes data from the database based on a specified instance object of RdbPredicates. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified delete condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified delete condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4764,17 +5079,19 @@ declare namespace relationalStore { * Deletes data from the database based on a specified instance object of RdbPredicates. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified delete condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified delete condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { AsyncCallback } callback - The number of affected rows. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4800,13 +5117,14 @@ declare namespace relationalStore { * Deletes data from the database based on a specified instance object of RdbPredicates. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified delete condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified delete condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4816,14 +5134,15 @@ declare namespace relationalStore { * Deletes data from the database based on a specified instance object of RdbPredicates. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified delete condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified delete condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4833,17 +5152,19 @@ declare namespace relationalStore { * Deletes data from the database based on a specified instance object of RdbPredicates. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified delete condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified delete condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @returns { Promise } The number of affected rows. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4868,7 +5189,8 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -4880,12 +5202,13 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -4896,8 +5219,10 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to query. If the value is empty array, the query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - + * The columns to query. If the value is empty array, the query applies to all columns. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -4908,8 +5233,10 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to query. If the value is empty array, the query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - + * The columns to query. If the value is empty array, the query applies to all columns. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -4921,13 +5248,15 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to query. If the value is empty array, the query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - + * The columns to query. If the value is empty array, the query applies to all columns. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -4938,7 +5267,8 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } columns - The columns to query. If the value is null, the query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; @@ -4950,7 +5280,8 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } columns - The columns to query. If the value is null, the query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; @@ -4963,13 +5294,14 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } columns - The columns to query. If the value is null, the query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -4981,13 +5313,14 @@ declare namespace relationalStore { * Queries data in the database based on specified conditions. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified query condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified query condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4997,14 +5330,15 @@ declare namespace relationalStore { * Queries data in the database based on specified conditions. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified query condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified query condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi @@ -5017,14 +5351,16 @@ declare namespace relationalStore { * Queries data in the database based on specified conditions. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified query condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. - * @param { Array } columns - The columns to query. If the value is empty array, the query applies to all columns. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified query condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. + * @param { Array } columns - + * The columns to query. If the value is empty array, the query applies to all columns. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -5034,15 +5370,17 @@ declare namespace relationalStore { * Queries data in the database based on specified conditions. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified query condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. - * @param { Array } columns - The columns to query. If the value is empty array, the query applies to all columns. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified query condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. + * @param { Array } columns - + * The columns to query. If the value is empty array, the query applies to all columns. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi @@ -5050,24 +5388,25 @@ declare namespace relationalStore { * @since 12 */ query( - table: string, - predicates: dataSharePredicates.DataSharePredicates, - columns: Array, - callback: AsyncCallback + table: string, + predicates: dataSharePredicates.DataSharePredicates, + columns: Array, + callback: AsyncCallback ): void; /** * Queries data in the database based on specified conditions. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified query condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified query condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { Array } columns - The columns to query. If the value is null, the query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -5077,15 +5416,16 @@ declare namespace relationalStore { * Queries data in the database based on specified conditions. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified query condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified query condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { Array } columns - The columns to query. If the value is null, the query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi @@ -5093,21 +5433,23 @@ declare namespace relationalStore { * @since 12 */ query( - table: string, - predicates: dataSharePredicates.DataSharePredicates, - columns?: Array + table: string, + predicates: dataSharePredicates.DataSharePredicates, + columns?: Array ): Promise; /** * Queries data in the database based on specified conditions with sync function. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to query. If the value is empty array, the query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - + * The columns to query. If the value is empty array, the query applies to all columns. * @returns { ResultSet } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -5135,7 +5477,7 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -5147,7 +5489,8 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -5159,7 +5502,8 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -5172,12 +5516,13 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -5189,7 +5534,8 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -5201,7 +5547,8 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -5214,12 +5561,13 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -5231,12 +5579,13 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement with sync interface. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @returns { ResultSet } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -5250,12 +5599,15 @@ declare namespace relationalStore { * @param { string } table - Indicates the name of the table to check. * @param { string } columnName - Indicates the name of the column to check. * @param { PRIKeyType[] } primaryKeys - Indicates the primary keys of the rows to check. - * @returns { Promise } -The promise returned by the function. ModifyTime indicates the modify time of current row. + * @returns { Promise } - + * The promise returned by the function. ModifyTime indicates the modify time of current row. * If this table does not support cloud, the {@link ModifyTime} will be empty. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 3 - 4 parameter(s)! 2. The RdbStore must be not nullptr. - * 3. The tablesNames must be not empty string. 4. The columnName must be not empty string. 5. The PRIKey must be number or string. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 3 - 4 parameter(s)! 2. The RdbStore must be not nullptr. + * 3. The tablesNames must be not empty string. 4. The columnName must be not empty string. + * 5. The PRIKey must be number or string. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 10 */ @@ -5265,16 +5617,20 @@ declare namespace relationalStore { * @param { string } table - Indicates the name of the table to check. * @param { string } columnName - Indicates the name of the column to check. * @param { PRIKeyType[] } primaryKeys - Indicates the primary keys of the rows to check. - * @returns { Promise } -The promise returned by the function. ModifyTime indicates the modify time of current row. + * @returns { Promise } - + * The promise returned by the function. ModifyTime indicates the modify time of current row. * If this table does not support cloud, the {@link ModifyTime} will be empty. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 3 - 4 parameter(s)! 2. The RdbStore must be not nullptr. - * 3. The tablesNames must be not empty string. 4. The columnName must be not empty string. 5. The PRIKey must be number or string. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 3 - 4 parameter(s)! 2. The RdbStore must be not nullptr. + * 3. The tablesNames must be not empty string. 4. The columnName must be not empty string. + * 5. The PRIKey must be number or string. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5299,12 +5655,15 @@ declare namespace relationalStore { * @param { string } table - Indicates the name of the table to check. * @param { string } columnName - Indicates the name of the column to check. * @param { PRIKeyType[] } primaryKeys - Indicates the primary keys of the rows to check. - * @param { AsyncCallback } callback - The callback of getModifyTime. ModifyTime indicates the modify time of current row. + * @param { AsyncCallback } callback - + * The callback of getModifyTime. ModifyTime indicates the modify time of current row. * If this table does not support cloud, the {@link ModifyTime} will be empty. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 3 - 4 parameter(s)! 2. The RdbStore must be not nullptr. - * 3. The tablesNames must be not empty string. 4. The columnName must be not empty string. 5. The PRIKey must be number or string. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 3 - 4 parameter(s)! 2. The RdbStore must be not nullptr. + * 3. The tablesNames must be not empty string. 4. The columnName must be not empty string. + * 5. The PRIKey must be number or string. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 10 */ @@ -5314,16 +5673,20 @@ declare namespace relationalStore { * @param { string } table - Indicates the name of the table to check. * @param { string } columnName - Indicates the name of the column to check. * @param { PRIKeyType[] } primaryKeys - Indicates the primary keys of the rows to check. - * @param { AsyncCallback } callback - The callback of getModifyTime. ModifyTime indicates the modify time of current row. + * @param { AsyncCallback } callback - + * The callback of getModifyTime. ModifyTime indicates the modify time of current row. * If this table does not support cloud, the {@link ModifyTime} will be empty. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 3 - 4 parameter(s)! 2. The RdbStore must be not nullptr. - * 3. The tablesNames must be not empty string. 4. The columnName must be not empty string. 5. The PRIKey must be number or string. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 3 - 4 parameter(s)! 2. The RdbStore must be not nullptr. + * 3. The tablesNames must be not empty string. 4. The columnName must be not empty string. + * 5. The PRIKey must be number or string. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5341,10 +5704,10 @@ declare namespace relationalStore { * @since 12 */ getModifyTime( - table: string, - columnName: string, - primaryKeys: PRIKeyType[], - callback: AsyncCallback + table: string, + columnName: string, + primaryKeys: PRIKeyType[], + callback: AsyncCallback ): void; /** @@ -5357,7 +5720,8 @@ declare namespace relationalStore { * @param { AsyncCallback } callback - Indicates the callback invoked to return the result. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The tablesNames must be not empty string. 4. The cursor must be valid cursor. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 11 @@ -5370,14 +5734,16 @@ declare namespace relationalStore { * @param { string } table - Indicates the name of the table to check. * @param { number } cursor - Indicates the position of the data to be cleaned up. * @param { AsyncCallback } callback - Indicates the callback invoked to return the result. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The tablesNames must be not empty string. 4. The cursor must be valid cursor. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5403,7 +5769,8 @@ declare namespace relationalStore { * @param { AsyncCallback } callback - The callback of clean. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The tablesNames must be not empty string. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 11 @@ -5413,14 +5780,16 @@ declare namespace relationalStore { * * @param { string } table - Indicates the name of the table to check. * @param { AsyncCallback } callback - The callback of clean. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s). 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s). 2. The RdbStore must be not nullptr. * 3. The tablesNames must be not empty string. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5450,7 +5819,8 @@ declare namespace relationalStore { * @returns { Promise } -The promise returned by the function. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The tablesNames must be not empty string. 4. The cursor must be valid cursor. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 11 @@ -5464,14 +5834,16 @@ declare namespace relationalStore { * @param { string } table - Indicates the name of the table to check. * @param { number } [cursor] - Indicates the cursor. * @returns { Promise } -The promise returned by the function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The tablesNames must be not empty string. 4. The cursor must be valid cursor. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5493,13 +5865,15 @@ declare namespace relationalStore { /** * Obtains sharing resource of rows corresponding to the predicates. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } [columns] - The specified columns to query. * @returns { Promise } -The promise returned by the function. * {@link ResultSet} is query result. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The predicates must be an RdbPredicates. 4. The columns must be a string array. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @systemapi @@ -5508,18 +5882,21 @@ declare namespace relationalStore { /** * Obtains sharing resource of rows corresponding to the predicates. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } [columns] - The specified columns to query. * @returns { Promise } -The promise returned by the function. * {@link ResultSet} is query result. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The predicates must be an RdbPredicates. 4. The columns must be a string array. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5542,12 +5919,14 @@ declare namespace relationalStore { /** * Obtains sharing resource of rows corresponding to the predicates. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The callback of querySharingResource. * {@link ResultSet} is query result. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The predicates must be an RdbPredicates. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @systemapi @@ -5556,17 +5935,20 @@ declare namespace relationalStore { /** * Obtains sharing resource of rows corresponding to the predicates. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The callback of querySharingResource. * {@link ResultSet} is query result. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The predicates must be an RdbPredicates. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5589,13 +5971,15 @@ declare namespace relationalStore { /** * Obtains sharing resource of rows corresponding to the predicates. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } columns - The specified columns to query. * @param { AsyncCallback } callback - The callback of querySharingResource. * {@link ResultSet} is query result. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The predicates must be an RdbPredicates. 4. The columns must be a string array. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @systemapi @@ -5604,18 +5988,21 @@ declare namespace relationalStore { /** * Obtains sharing resource of rows corresponding to the predicates. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } columns - The specified columns to query. * @param { AsyncCallback } callback - The callback of querySharingResource. * {@link ResultSet} is query result. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The predicates must be an RdbPredicates. 4. The columns must be a string array. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5657,10 +6044,11 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5685,7 +6073,8 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters but returns no value. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @param { AsyncCallback } callback - The callback of executeSql. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -5697,7 +6086,8 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters but returns no value. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @param { AsyncCallback } callback - The callback of executeSql. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; @@ -5711,16 +6101,18 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters but returns no value. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @param { AsyncCallback } callback - The callback of executeSql. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5745,7 +6137,8 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters but returns no value. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -5757,7 +6150,8 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters but returns no value. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; @@ -5771,16 +6165,18 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters but returns no value. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5805,16 +6201,18 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters and returns a value of ValueType. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. + * The values are strings. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5839,16 +6237,18 @@ declare namespace relationalStore { * * @param { string } sql - Indicates the SQL statement to execute. * @param { number } txId - Indicates the transaction ID which is obtained by beginTrans or 0. - * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. + * The values are strings. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5872,15 +6272,17 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters and returns a value of ValueType with sync interface. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. + * The values are strings. * @returns { ValueType } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5924,10 +6326,11 @@ declare namespace relationalStore { * * @throws { BusinessError } 401 - Parameter error. The store must not be nullptr. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5955,10 +6358,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. The store must not be nullptr. * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5998,10 +6402,11 @@ declare namespace relationalStore { * * @throws { BusinessError } 401 - Parameter error. The store must not be nullptr. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6028,11 +6433,12 @@ declare namespace relationalStore { * @returns { Promise } Promise used to return the result. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. - * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6071,10 +6477,11 @@ declare namespace relationalStore { * * @throws { BusinessError } 401 - Parameter error. The store must not be nullptr. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6100,11 +6507,12 @@ declare namespace relationalStore { * @param { number } txId - Indicates the transaction ID which is obtained by beginTrans. * @returns { Promise } Promise used to return the result. * @throws { BusinessError } 401 - Parameter error. The store must not be nullptr. - * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6153,11 +6561,12 @@ declare namespace relationalStore { * @param { AsyncCallback } callback - The callback of backup. * @throws { BusinessError } 401 - Parameter error. The store must not be nullptr. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6208,10 +6617,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6262,10 +6672,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6316,10 +6727,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6343,13 +6755,15 @@ declare namespace relationalStore { * Restores a database from a specified database file. * * @returns { Promise } The promise returned by the function. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6392,7 +6806,7 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -6421,7 +6835,7 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -6455,7 +6869,7 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800051 - The type of the distributed table does not match. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 @@ -6469,7 +6883,8 @@ declare namespace relationalStore { * @param { Array } tables - Indicates the table names you want to set. * @param { DistributedType } type - Indicates the distributed type {@link DistributedType}. * This method only works when type equals to DistributedType.DISTRIBUTED_CLOUD - * @param { DistributedConfig } config - Indicates the distributed config of the tables. For details, see {@link DistributedConfig}. + * @param { DistributedConfig } config - + * Indicates the distributed config of the tables. For details, see {@link DistributedConfig}. * @param { AsyncCallback } callback - The callback of setDistributedTables. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -6486,22 +6901,23 @@ declare namespace relationalStore { * @param { Array } tables - Indicates the table names you want to set. * @param { DistributedType } type - Indicates the distributed type {@link DistributedType}. * ohos.permission.DISTRIBUTED_DATASYNC is required only when type is DISTRIBUTED_DEVICE. - * @param { DistributedConfig } config - Indicates the distributed config of the tables. For details, see {@link DistributedConfig}. + * @param { DistributedConfig } config - + * Indicates the distributed config of the tables. For details, see {@link DistributedConfig}. * @param { AsyncCallback } callback - The callback of setDistributedTables. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800051 - The type of the distributed table does not match. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ setDistributedTables( - tables: Array, - type: DistributedType, - config: DistributedConfig, - callback: AsyncCallback + tables: Array, + type: DistributedType, + config: DistributedConfig, + callback: AsyncCallback ): void; /** @@ -6511,7 +6927,8 @@ declare namespace relationalStore { * @param { Array } tables - Indicates the table names you want to set. * @param { DistributedType } type - Indicates the distributed type {@link DistributedType}. * This method only works when type equals to DistributedType.DISTRIBUTED_CLOUD - * @param { DistributedConfig } config - Indicates the distributed config of the tables. For details, see {@link DistributedConfig}. + * @param { DistributedConfig } config - + * Indicates the distributed config of the tables. For details, see {@link DistributedConfig}. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -6528,13 +6945,14 @@ declare namespace relationalStore { * @param { Array } tables - Indicates the table names you want to set. * @param { DistributedType } type - Indicates the distributed type {@link DistributedType}. * ohos.permission.DISTRIBUTED_DATASYNC is required only when type is DISTRIBUTED_DEVICE. - * @param { DistributedConfig } config - Indicates the distributed config of the tables. For details, see {@link DistributedConfig}. + * @param { DistributedConfig } config - + * Indicates the distributed config of the tables. For details, see {@link DistributedConfig}. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800051 - The type of the distributed table does not match. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 @@ -6568,7 +6986,7 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -6601,7 +7019,7 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -6612,10 +7030,12 @@ declare namespace relationalStore { * * @permission ohos.permission.DISTRIBUTED_DATASYNC * @param { SyncMode } mode - Indicates the database synchronization mode. - * @param { RdbPredicates } predicates - The specified sync condition by the instance object of {@link RdbPredicates}. - * @param { AsyncCallback> } callback - {Array<[string, number]>}: devices sync status array, - * {string}: device id, - * {number}: device sync status. + * @param { RdbPredicates } predicates - + * The specified sync condition by the instance object of {@link RdbPredicates}. + * @param { AsyncCallback> } callback - + * {Array<[string, number]>}: devices sync status array, + * {string}: device id, + * {number}: device sync status. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. @@ -6628,15 +7048,17 @@ declare namespace relationalStore { * * @permission ohos.permission.DISTRIBUTED_DATASYNC * @param { SyncMode } mode - Indicates the database synchronization mode. - * @param { RdbPredicates } predicates - The specified sync condition by the instance object of {@link RdbPredicates}. - * @param { AsyncCallback> } callback - {Array<[string, number]>}: devices sync status array, - * {string}: device id, - * {number}: device sync status. + * @param { RdbPredicates } predicates - + * The specified sync condition by the instance object of {@link RdbPredicates}. + * @param { AsyncCallback> } callback - + * {Array<[string, number]>}: devices sync status array, + * {string}: device id, + * {number}: device sync status. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -6647,8 +7069,10 @@ declare namespace relationalStore { * * @permission ohos.permission.DISTRIBUTED_DATASYNC * @param { SyncMode } mode - Indicates the database synchronization mode. - * @param { RdbPredicates } predicates - The specified sync condition by the instance object of {@link RdbPredicates}. - * @returns { Promise> } {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @param { RdbPredicates } predicates - + * The specified sync condition by the instance object of {@link RdbPredicates}. + * @returns { Promise> } + * {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. @@ -6661,13 +7085,15 @@ declare namespace relationalStore { * * @permission ohos.permission.DISTRIBUTED_DATASYNC * @param { SyncMode } mode - Indicates the database synchronization mode. - * @param { RdbPredicates } predicates - The specified sync condition by the instance object of {@link RdbPredicates}. - * @returns { Promise> } {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @param { RdbPredicates } predicates - + * The specified sync condition by the instance object of {@link RdbPredicates}. + * @returns { Promise> } + * {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -6677,10 +7103,14 @@ declare namespace relationalStore { * Sync data to cloud. * * @param { SyncMode } mode - indicates the database synchronization mode. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. - * @param { AsyncCallback } callback - {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The progress must be a callback type. 5. The callback must be a function. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. + * @param { AsyncCallback } callback - + * {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The progress must be a callback type. + * 5. The callback must be a function. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 10 @@ -6689,12 +7119,16 @@ declare namespace relationalStore { * Sync data to cloud. * * @param { SyncMode } mode - indicates the database synchronization mode. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. - * @param { AsyncCallback } callback - {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The progress must be a callback type. 5. The callback must be a function. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. + * @param { AsyncCallback } callback - + * {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The progress must be a callback type. + * 5. The callback must be a function. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 12 */ @@ -6704,9 +7138,11 @@ declare namespace relationalStore { * Sync data to cloud. * * @param { SyncMode } mode - indicates the database synchronization mode. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. * @returns { Promise } : devices sync status array, {string}: device id, {number}: device sync status. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. * 3. The mode must be a SyncMode of cloud. 4. The progress must be a callback type. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client @@ -6716,12 +7152,14 @@ declare namespace relationalStore { * Sync data to cloud. * * @param { SyncMode } mode - indicates the database synchronization mode. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. * @returns { Promise } : devices sync status array, {string}: device id, {number}: device sync status. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. * 3. The mode must be a SyncMode of cloud. 4. The progress must be a callback type. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 12 */ @@ -6732,11 +7170,14 @@ declare namespace relationalStore { * * @param { SyncMode } mode - indicates the database synchronization mode. * @param { string[] } tables - indicates the database synchronization mode. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. - * @param { AsyncCallback } callback - {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. 5. The progress must be a callback type. - * 6. The callback must be a function. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. + * @param { AsyncCallback } callback - + * {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. + * 5. The progress must be a callback type. 6. The callback must be a function. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 10 @@ -6746,21 +7187,24 @@ declare namespace relationalStore { * * @param { SyncMode } mode - indicates the database synchronization mode. * @param { string[] } tables - indicates the database synchronization mode. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. - * @param { AsyncCallback } callback - {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. 5. The progress must be a callback type. - * 6. The callback must be a function. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. + * @param { AsyncCallback } callback - + * {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. + * 5. The progress must be a callback type. 6. The callback must be a function. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 12 */ cloudSync( - mode: SyncMode, - tables: string[], - progress: Callback, - callback: AsyncCallback + mode: SyncMode, + tables: string[], + progress: Callback, + callback: AsyncCallback ): void; /** @@ -6768,10 +7212,13 @@ declare namespace relationalStore { * * @param { SyncMode } mode - indicates the database synchronization mode. * @param { string[] } tables - indicates the database synchronization mode. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. * @returns { Promise } : devices sync status array, {string}: device id, {number}: device sync status. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. 5. The progress must be a callback type. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. + * 5. The progress must be a callback type. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 10 @@ -6781,12 +7228,15 @@ declare namespace relationalStore { * * @param { SyncMode } mode - indicates the database synchronization mode. * @param { string[] } tables - indicates the database synchronization mode. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. * @returns { Promise } : devices sync status array, {string}: device id, {number}: device sync status. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. 5. The progress must be a callback type. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. + * 5. The progress must be a callback type. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 12 */ @@ -6796,13 +7246,17 @@ declare namespace relationalStore { * Sync data to cloud. * * @param { SyncMode } mode - indicates the database synchronization mode. - * @param { RdbPredicates } predicates - The specified sync condition by the instance object of {@link RdbPredicates}. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. + * @param { RdbPredicates } predicates - + * The specified sync condition by the instance object of {@link RdbPredicates}. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. * @param { AsyncCallback } callback - The callback of cloudSync. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. 5. The progress must be a callback type. - * 6. The callback must be a function. - * @throws { BusinessError } 202 - if permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. + * 5. The progress must be a callback type. 6. The callback must be a function. + * @throws { BusinessError } 202 - + * if permission verification failed, application which is not a system application uses system API. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @systemapi @@ -6812,35 +7266,43 @@ declare namespace relationalStore { * Sync data to cloud. * * @param { SyncMode } mode - indicates the database synchronization mode. - * @param { RdbPredicates } predicates - The specified sync condition by the instance object of {@link RdbPredicates}. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. + * @param { RdbPredicates } predicates - + * The specified sync condition by the instance object of {@link RdbPredicates}. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. * @param { AsyncCallback } callback - The callback of cloudSync. - * @throws { BusinessError } 202 - if permission verification failed, application which is not a system application uses system API. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. 5. The progress must be a callback type. - * 6. The callback must be a function. + * @throws { BusinessError } 202 - + * if permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. + * 5. The progress must be a callback type. 6. The callback must be a function. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @systemapi * @since 12 */ cloudSync( - mode: SyncMode, - predicates: RdbPredicates, - progress: Callback, - callback: AsyncCallback + mode: SyncMode, + predicates: RdbPredicates, + progress: Callback, + callback: AsyncCallback ): void; /** * Sync data to cloud. * * @param { SyncMode } mode - indicates the database synchronization mode. - * @param { RdbPredicates } predicates - The specified sync condition by the instance object of {@link RdbPredicates}. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. + * @param { RdbPredicates } predicates - + * The specified sync condition by the instance object of {@link RdbPredicates}. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. * @returns { Promise } : The promise returned by the function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. 5. The progress must be a callback type. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. + * 5. The progress must be a callback type. * @throws { BusinessError } 202 - if permission verification failed, application which is not a system * application uses system API. * @throws { BusinessError } 801 - Capability not supported. @@ -6852,15 +7314,19 @@ declare namespace relationalStore { * Sync data to cloud. * * @param { SyncMode } mode - indicates the database synchronization mode. - * @param { RdbPredicates } predicates - The specified sync condition by the instance object of {@link RdbPredicates}. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. + * @param { RdbPredicates } predicates - + * The specified sync condition by the instance object of {@link RdbPredicates}. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. * @returns { Promise } : The promise returned by the function. * @throws { BusinessError } 202 - if permission verification failed, application which is not a system * application uses system API. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. 5. The progress must be a callback type. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. + * 5. The progress must be a callback type. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @systemapi * @since 12 @@ -6872,8 +7338,10 @@ declare namespace relationalStore { * * @param { string } device - Indicates specified remote device. * @param { string } table - Indicates the target table. - * @param { RdbPredicates } predicates - The specified remote remote query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to remote query. If the value is empty array, the remote query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified remote remote query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - The columns to remote query. + * If the value is empty array, the remote query applies to all columns. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -6887,23 +7355,25 @@ declare namespace relationalStore { * * @param { string } device - Indicates specified remote device. * @param { string } table - Indicates the target table. - * @param { RdbPredicates } predicates - The specified remote remote query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to remote query. If the value is empty array, the remote query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified remote remote query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - The columns to remote query. + * If the value is empty array, the remote query applies to all columns. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ remoteQuery( - device: string, - table: string, - predicates: RdbPredicates, - columns: Array, - callback: AsyncCallback + device: string, + table: string, + predicates: RdbPredicates, + columns: Array, + callback: AsyncCallback ): void; /** @@ -6911,8 +7381,10 @@ declare namespace relationalStore { * * @param { string } device - Indicates specified remote device. * @param { string } table - Indicates the target table. - * @param { RdbPredicates } predicates - The specified remote remote query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to remote query. If the value is empty array, the remote query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified remote remote query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - The columns to remote query. + * If the value is empty array, the remote query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -6926,27 +7398,30 @@ declare namespace relationalStore { * * @param { string } device - Indicates specified remote device. * @param { string } table - Indicates the target table. - * @param { RdbPredicates } predicates - The specified remote remote query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to remote query. If the value is empty array, the remote query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified remote remote query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - The columns to remote query. + * If the value is empty array, the remote query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ remoteQuery(device: string, table: string, predicates: RdbPredicates, columns: Array): Promise; /** - * Registers an observer for the database. When data in the distributed database changes, - * the callback will be invoked. + * Subscribes to data changes of this RDB store. + * The registered callback will be called when data in a distributed RDB store changes. * * @param { 'dataChange' } event - Indicates the event must be string 'dataChange'. * @param { SubscribeType } type - Indicates the subscription type, which is defined in {@link SubscribeType}. * If its value is SUBSCRIBE_TYPE_REMOTE, ohos.permission.DISTRIBUTED_DATASYNC is required. - * @param { Callback> } observer - {Array}: the observer of data change events in the distributed database. + * @param { Callback> } observer - + * {Array}: the observer of data change events in the distributed database. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. @@ -6954,43 +7429,47 @@ declare namespace relationalStore { * @since 9 */ /** - * Registers an observer for the database. When data in the distributed database changes, + * Subscribes to data changes of this RDB store. + * The registered callback will be called when data in a distributed RDB store changes. * the callback will be invoked. * * @param { 'dataChange' } event - Indicates the event must be string 'dataChange'. * @param { SubscribeType } type - Indicates the subscription type, which is defined in {@link SubscribeType}. * If its value is SUBSCRIBE_TYPE_REMOTE, ohos.permission.DISTRIBUTED_DATASYNC is required. - * @param { Callback> } observer - {Array}: the observer of data change events in the distributed database. + * @param { Callback> } observer - + * {Array}: the observer of data change events in the distributed database. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ on(event: 'dataChange', type: SubscribeType, observer: Callback>): void; /** - * Registers an observer for the database. When data in the distributed database or the local database changes, - * the callback will be invoked. + * Subscribes to data changes of this RDB store. + * The registered callback will be called when data in a distributed RDB store changes. * * @param { 'dataChange' } event - Indicates the event must be string 'dataChange'. * @param { SubscribeType } type - Indicates the subscription type, which is defined in {@link SubscribeType}. * If its value is SUBSCRIBE_TYPE_REMOTE, ohos.permission.DISTRIBUTED_DATASYNC is required. - * If its value is SUBSCRIBE_TYPE_LOCAL_DETAILS, the callback will be invoked for data changes in the local database. + * If its value is SUBSCRIBE_TYPE_LOCAL_DETAILS, + * the callback will be invoked for data changes in the local database. * @param { Callback> | Callback> } observer * {Array}: The observer of data change events in the distributed database. * {Array}: The change info of data change events in the distributed database or the local database. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 10 */ /** - * Registers an observer for the database. When data in the distributed database changes, - * the callback will be invoked. + * Subscribes to data changes of this RDB store. + * The registered callback will be called when data in a distributed RDB store changes. * * @param { 'dataChange' } event - Indicates the event must be string 'dataChange'. * @param { SubscribeType } type - Indicates the subscription type, which is defined in {@link SubscribeType}. @@ -6998,11 +7477,12 @@ declare namespace relationalStore { * @param { Callback> | Callback> } observer * {Array}: The observer of data change events in the distributed database. * {Array}: The change info of data change events in the distributed database. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -7011,8 +7491,9 @@ declare namespace relationalStore { /** * Registers an observer for the database. * - * @param { string } event - Indicates the subscription event. - * @param { boolean } interProcess - Indicates whether it is an interprocess subscription or an in-process subscription. + * @param { string } event - Event type, which must match the event type in {@link emit}. + * @param { boolean } interProcess - + * Indicates whether it is an interprocess subscription or an in-process subscription. * @param { Callback } observer - The observer of data change events in the database. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -7025,14 +7506,15 @@ declare namespace relationalStore { /** * Registers an observer for the database. * - * @param { string } event - Indicates the subscription event. - * @param { boolean } interProcess - Indicates whether it is an interprocess subscription or an in-process subscription. + * @param { string } event - Event type, which must match the event type in {@link emit}. + * @param { boolean } interProcess - + * Indicates whether it is an interprocess subscription or an in-process subscription. * @param { Callback } observer - The observer of data change events in the database. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800050 - Failed to obtain the subscription service. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 @@ -7043,8 +7525,10 @@ declare namespace relationalStore { * Register an automatic synchronization callback to the database. * * @param { 'autoSyncProgress' } event - Indicates the event must be string 'autoSyncProgress'. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 3 parameter(s)! 2. The RdbStore must be valid. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 2 - 3 parameter(s)! 2. The RdbStore must be valid. * 3. The event must be a not empty string. 4. The progress must be function. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core @@ -7054,11 +7538,13 @@ declare namespace relationalStore { * Register an automatic synchronization callback to the database. * * @param { 'autoSyncProgress' } event - Indicates the event must be string 'autoSyncProgress'. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 3 parameter(s)! 2. The RdbStore must be valid. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 2 - 3 parameter(s)! 2. The RdbStore must be valid. * 3. The event must be a not empty string. 4. The progress must be function. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -7067,16 +7553,42 @@ declare namespace relationalStore { /** * Subscribes to the SQL statistics. * @param { 'statistics' } event - Indicates the event type, which must be 'statistics'. - * @param { Callback } observer - Indicates the callback used to return the SQL execution statistics {@link SqlExeInfo} in the database. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1.Mandatory parameters are left unspecified; 2.Incorrect parameter types. + * @param { Callback } observer - + * Indicates the callback used to return the SQL execution statistics {@link SqlExeInfo} in the database. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Mandatory parameters are left unspecified; 2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ on(event: 'statistics', observer: Callback ): void; + /** + * Subscribes to the SQL execution error logs. + * @param { 'sqliteErrorOccurred' } event - Event type, which must be 'sqliteErrorOccurred'. + * @param { Callback } observer - Callback used to return the SQL execution error log {@link ExceptionMessage}. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + on(event: 'sqliteErrorOccurred', observer: Callback ): void; + + /** + * Subscribes to the SQL performance statistics. + * @param { 'perfStat' } event - Event type, which must be 'perfStat'. + * @param { Callback } observer - Callback used to return the SQL execution statistics {@link SqlExecutionInfo}. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + on(event: 'perfStat', observer: Callback): void; + /** * Remove specified observer of specified type from the database. * @@ -7100,7 +7612,7 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -7112,11 +7624,13 @@ declare namespace relationalStore { * @param { 'dataChange' } event - indicates the event must be string 'dataChange'. * @param { SubscribeType } type - indicates the subscription type, which is defined in {@link SubscribeType}. * If its value is SUBSCRIBE_TYPE_REMOTE, ohos.permission.DISTRIBUTED_DATASYNC is required. - * @param { Callback> | Callback> } observer - {Array}: the data change observer already registered. + * @param { Callback> | Callback> } observer - + * {Array}: the data change observer already registered. * {Array}: the change info already registered. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 10 @@ -7127,27 +7641,30 @@ declare namespace relationalStore { * @param { 'dataChange' } event - indicates the event must be string 'dataChange'. * @param { SubscribeType } type - indicates the subscription type, which is defined in {@link SubscribeType}. * If its value is SUBSCRIBE_TYPE_REMOTE, ohos.permission.DISTRIBUTED_DATASYNC is required. - * @param { Callback> | Callback> } observer - {Array}: the data change observer already registered. + * @param { Callback> | Callback> } observer - + * {Array}: the data change observer already registered. * {Array}: the change info already registered. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ off( - event: 'dataChange', - type: SubscribeType, - observer?: Callback> | Callback> + event: 'dataChange', + type: SubscribeType, + observer?: Callback> | Callback> ): void; /** * Remove specified observer of specified type from the database. * * @param { string } event - Indicates the subscription event. - * @param { boolean } interProcess - Indicates whether it is an interprocess subscription or an in-process subscription. + * @param { boolean } interProcess - + * Indicates whether it is an interprocess subscription or an in-process subscription. * @param { Callback } observer - The data change observer already registered. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -7161,13 +7678,14 @@ declare namespace relationalStore { * Remove specified observer of specified type from the database. * * @param { string } event - Indicates the subscription event. - * @param { boolean } interProcess - Indicates whether it is an interprocess subscription or an in-process subscription. + * @param { boolean } interProcess - + * Indicates whether it is an interprocess subscription or an in-process subscription. * @param { Callback } observer - The data change observer already registered. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800050 - Failed to obtain the subscription service. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 @@ -7178,8 +7696,10 @@ declare namespace relationalStore { * Unregister the database auto synchronization callback. * * @param { 'autoSyncProgress' } event - indicates the event must be string 'autoSyncProgress'. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be valid. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be valid. * 3. The event must be a not empty string. 4. The progress must be function. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core @@ -7189,11 +7709,13 @@ declare namespace relationalStore { * Unregister the database auto synchronization callback. * * @param { 'autoSyncProgress' } event - indicates the event must be string 'autoSyncProgress'. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be valid. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be valid. * 3. The event must be a not empty string. 4. The progress must be function. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -7206,12 +7728,36 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ off(event: 'statistics', observer?: Callback ): void; + /** + * Unsubscribes from the SQL execution error logs. + * @param { 'sqliteErrorOccurred' } event - Indicates the event type, which must be 'sqliteErrorOccurred'. + * @param { Callback } observer - Callback to unregister. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + off(event: 'sqliteErrorOccurred', observer?: Callback ): void; + + /** + * Unsubscribes from the SQL performance statistics. + * @param { 'perfStat' } event - Event type, which must be 'perfStat'. + * @param { Callback } observer - Callback to unregister. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + off(event: 'perfStat', observer?: Callback): void; + /** * Notifies the registered observers of a change to the data resource specified by Uri. * @@ -7232,7 +7778,7 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800050 - Failed to obtain the subscription service. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 @@ -7261,12 +7807,13 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800016 - The database alias already exists. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7289,7 +7836,8 @@ declare namespace relationalStore { * Attaches a database file to the currently linked database. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @param { string } attachName - Indicates the alias of the database. * @param { number } waitTime - Indicates the maximum time allowed for attaching the database file. * @returns { Promise } Promise used to return the number of attached databases. @@ -7297,14 +7845,15 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800016 - The database alias already exists. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. + * @throws { BusinessError } 14801002 - Invalid data group ID. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7332,10 +7881,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7357,16 +7907,18 @@ declare namespace relationalStore { /** * Locks data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified lock condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified lock condition by the instance object of {@link RdbPredicates}. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800018 - No data meets the condition. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7389,16 +7941,18 @@ declare namespace relationalStore { /** * Unlocks data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified Unlock condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified Unlock condition by the instance object of {@link RdbPredicates}. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800018 - No data meets the condition. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7421,16 +7975,18 @@ declare namespace relationalStore { /** * Queries locked data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } columns - The columns to query. If the value is null, the query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7454,7 +8010,8 @@ declare namespace relationalStore { * Lock cloud container before non-auto cloud sync. * * @returns { Promise } The expired time of the lock. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @since 12 @@ -7465,7 +8022,8 @@ declare namespace relationalStore { * Unlock cloud container. * * @returns { Promise } The promise returned by the function. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @since 12 @@ -7478,8 +8036,8 @@ declare namespace relationalStore { * @param { TransactionOptions } options - The option for creating transactions. * @returns { Promise } The {@link Transaction} object if the operation is successful. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database is busy. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7508,8 +8066,8 @@ declare namespace relationalStore { * * @returns { Promise } Promise used to return the result. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. @@ -7527,8 +8085,8 @@ declare namespace relationalStore { * * @returns { Promise } Promise used to return the result. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. @@ -7551,9 +8109,10 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7580,9 +8139,10 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7603,14 +8163,17 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. - * @returns { Promise } The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @returns { Promise } The number of values that were inserted if the operation is successful. + * returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7631,14 +8194,16 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. * @returns { number } The number of values that were inserted if the operation is successful. returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7659,15 +8224,18 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. - * @returns { Promise } The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @returns { Promise } The number of values that were inserted if the operation is successful. + * returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7683,7 +8251,7 @@ declare namespace relationalStore { * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform - * @since 16 + * @since 18 */ batchInsertWithConflictResolution(table: string, values: Array, conflict: ConflictResolution): Promise; @@ -7691,15 +8259,17 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. * @returns { number } The number of values that were inserted if the operation is successful. returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7715,7 +8285,7 @@ declare namespace relationalStore { * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform - * @since 16 + * @since 18 */ batchInsertWithConflictResolutionSync(table: string, values: Array, conflict: ConflictResolution): number; @@ -7723,16 +8293,18 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7753,16 +8325,18 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates with sync interface. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. * @returns { number } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7782,14 +8356,16 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. * @returns { Promise } return the number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7809,14 +8385,16 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates with sync interface. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. - * @returns { number } return the number of affected rows. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. + * @returns { number } return the number of rows deleted. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7836,15 +8414,17 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } columns - The columns to query. If the value is null, the query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. @@ -7859,15 +8439,18 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions with sync function. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to query. If the value is empty array, the query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - + * The columns to query. If the value is empty array, the query applies to all columns. * @returns { ResultSet } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7884,14 +8467,16 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. + * The values are strings. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7908,14 +8493,16 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement with sync interface. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. + * The values are strings. * @returns { ResultSet } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7932,15 +8519,17 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters and returns a value of ValueType. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. + * The values are strings. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7960,15 +8549,17 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters and returns a value of ValueType with sync interface. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. + * The values are strings. * @returns { ValueType } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7992,13 +8583,16 @@ declare namespace relationalStore { * to obtain a rdb store. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @param { AsyncCallback } callback - The RDB store {@link RdbStore}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. - * @throws { BusinessError } 14800011 - Failed to open database by database corrupted. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - + * Failed to open database by Failed to open the database because it is corrupted. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 */ @@ -8008,15 +8602,18 @@ declare namespace relationalStore { * to obtain a rdb store. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @param { AsyncCallback } callback - The RDB store {@link RdbStore}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. - * @throws { BusinessError } 14800011 - Failed to open database by database corrupted. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - + * Failed to open database by Failed to open the database because it is corrupted. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. + * @throws { BusinessError } 14801002 - Invalid data group ID. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 10 @@ -8027,17 +8624,19 @@ declare namespace relationalStore { * to obtain a rdb store. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @param { AsyncCallback } callback - The RDB store {@link RdbStore}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. - * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. - * @throws { BusinessError } 14800017 - Config changed. + * @throws { BusinessError } 14801002 - Invalid data group ID. + * @throws { BusinessError } 14800017 - StoreConfig is changed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. @@ -8054,18 +8653,20 @@ declare namespace relationalStore { * to obtain a rdb store. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @param { AsyncCallback } callback - The RDB store {@link RdbStore}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. - * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. - * @throws { BusinessError } 14800017 - Config changed. + * @throws { BusinessError } 14801002 - Invalid data group ID. + * @throws { BusinessError } 14800017 - StoreConfig is changed. * @throws { BusinessError } 14800020 - The secret key is corrupted or lost. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. @@ -8084,13 +8685,16 @@ declare namespace relationalStore { * to obtain a rdb store. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @returns { Promise } The RDB store {@link RdbStore}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. - * @throws { BusinessError } 14800011 - Failed to open database by database corrupted. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - + * Failed to open database by Failed to open the database because it is corrupted. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 */ @@ -8100,15 +8704,18 @@ declare namespace relationalStore { * to obtain a rdb store. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @returns { Promise } The RDB store {@link RdbStore}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. - * @throws { BusinessError } 14800011 - Failed to open database by database corrupted. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - + * Failed to open database by Failed to open the database because it is corrupted. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. + * @throws { BusinessError } 14801002 - Invalid data group ID. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 10 @@ -8119,17 +8726,19 @@ declare namespace relationalStore { * to obtain a rdb store. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. - * @returns { Promise } The RDB store {@link RdbStore}. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @returns { Promise } Promise used to return the **RdbStore** object obtained. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. - * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. - * @throws { BusinessError } 14800017 - Config changed. + * @throws { BusinessError } 14801002 - Invalid data group ID. + * @throws { BusinessError } 14800017 - StoreConfig is changed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. * @throws { BusinessError } 14800029 - SQLite: The database is full. @@ -8144,18 +8753,20 @@ declare namespace relationalStore { * to obtain a rdb store. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. - * @returns { Promise } The RDB store {@link RdbStore}. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @returns { Promise } Promise used to return the **RdbStore** object obtained. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. - * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. - * @throws { BusinessError } 14800017 - Config changed. + * @throws { BusinessError } 14801002 - Invalid data group ID. + * @throws { BusinessError } 14800017 - StoreConfig is changed. * @throws { BusinessError } 14800020 - The secret key is corrupted or lost. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. @@ -8178,7 +8789,8 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 */ @@ -8192,7 +8804,8 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 10 @@ -8204,14 +8817,16 @@ declare namespace relationalStore { * When specify custom directory, this function should be called. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @param { AsyncCallback } callback - The callback of deleteRdbStore. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. + * @throws { BusinessError } 14801002 - Invalid data group ID. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 10 @@ -8228,7 +8843,8 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 */ @@ -8242,7 +8858,8 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 10 @@ -8257,7 +8874,7 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 12 @@ -8269,14 +8886,16 @@ declare namespace relationalStore { * When specify custom directory, this function should be called. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. + * @throws { BusinessError } 14801002 - Invalid data group ID. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 10 @@ -8286,15 +8905,16 @@ declare namespace relationalStore { * When specify custom directory, this function should be called. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. + * @throws { BusinessError } 14801002 - Invalid data group ID. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 12 @@ -8306,7 +8926,7 @@ declare namespace relationalStore { * * @returns { boolean } Returns {@code true} if the vector database is supported; returns {@code false} otherwise. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 18 */ function isVectorSupported(): boolean; @@ -8316,9 +8936,9 @@ declare namespace relationalStore { * @returns { boolean } Returns {@code true} if the tokenizer is supported; returns {@code false} otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: Incorrect parameter types * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 18 */ - function isTokenizerSupported(tokenizer: Tokenizer): boolean; + function isTokenizerSupported(tokenizer: Tokenizer): boolean; } export default relationalStore; diff --git a/interface_sdk/api/@ohos.data.sendablePreferences.d.ets b/interface_sdk/api/@ohos.data.sendablePreferences.d.ets index 626fbf4f811e5e671f0be2780d270427cabcde29..3c16c1857d6509a1474ec5bfcdef2a404bd77924 100644 --- a/interface_sdk/api/@ohos.data.sendablePreferences.d.ets +++ b/interface_sdk/api/@ohos.data.sendablePreferences.d.ets @@ -90,13 +90,13 @@ declare namespace sendablePreferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates information about the preferences file. For details, see {@link Options}. * @returns { Promise } Promise used to return the {@link Preferences}. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice * @since 12 @@ -112,13 +112,13 @@ declare namespace sendablePreferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates information about the preferences file. For details, see {@link Options}. * @returns { Preferences } return the {@link Preferences}. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice * @since 12 @@ -136,14 +136,14 @@ declare namespace sendablePreferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates information about the preferences file. For details, see {@link Options}. * @returns { Promise } Promise that returns no value. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice * @since 12 @@ -160,13 +160,13 @@ declare namespace sendablePreferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates information about the preferences file. For details, see {@link Options}. * @returns { Promise } Promise that returns no value. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice * @since 12 @@ -182,13 +182,13 @@ declare namespace sendablePreferences { * * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates information about the preferences file. For details, see {@link Options}. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice * @since 12 @@ -213,13 +213,13 @@ declare namespace sendablePreferences { *

If the value is {@code null} or not in the lang.ISendable format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { lang.ISendable } defValue - Indicates the default value to return. - * @returns { Promise } Promise used to return the result. If a value matching the specified key + * @returns { Promise } Promise used to return the result. If a value matching the specified key * is found, the value is returned. Otherwise, the default value is returned. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -232,13 +232,13 @@ declare namespace sendablePreferences { *

If the value is {@code null} or not in the lang.ISendable format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { lang.ISendable } defValue - Indicates the default value to return. * @returns { lang.ISendable } If a value matching the specified key is found, the value is returned. Otherwise, * the default value is returned. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -272,12 +272,12 @@ declare namespace sendablePreferences { * Checks whether the {@link Preferences} instance contains a value matching the specified key. * * @param { string } key - Indicates the key of the value to check. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { Promise } Promise used to return the result. {@code true} is returned if the * {@link Preferences} object contains a value matching the specified key; {@code false} is returned otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -290,12 +290,12 @@ declare namespace sendablePreferences { * This API returns the result synchronously. * * @param { string } key - Indicates the key of the value to check. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { boolean } {@code true} is returned if the {@link Preferences} object contains a value matching * the specified key; {@code false} is returned otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -308,13 +308,13 @@ declare namespace sendablePreferences { *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to set. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { lang.ISendable } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. + * MAX_VALUE_LENGTH. * @returns { Promise } Promise that returns no value. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -324,16 +324,16 @@ declare namespace sendablePreferences { /** * Sets an lang.ISendable value for the key in the {@link Preferences} object. - * This API returns the result synchronously. + * This API returns the result synchronously. *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to set. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { lang.ISendable } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_VALUE_LENGTH. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -346,11 +346,11 @@ declare namespace sendablePreferences { *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { Promise } Promise that returns no value. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -364,10 +364,10 @@ declare namespace sendablePreferences { *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_KEY_LENGTH. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -388,7 +388,7 @@ declare namespace sendablePreferences { clear(): Promise; /** - * Clears all preferences from the {@link Preferences} object. This API returns the result synchronously. + * Clears all preferences from the {@link Preferences} object. This API returns the result synchronously. *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @throws { BusinessError } 15500000 - Inner error. @@ -409,14 +409,24 @@ declare namespace sendablePreferences { */ flush(): Promise; + /** + * Flushes the {@link Preferences} object to the file. + * + * @throws { BusinessError } 15500000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @atomicservice + * @since 14 + */ + flushSync(): void; + /** * Registers an observer to listen for the change of a {@link Preferences} object. * * @param { 'change' } type - Indicates the type of the event to observe. * @param { Callback } callback - Indicates the callback used to return the preferences changes. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -430,11 +440,11 @@ declare namespace sendablePreferences { * @param { 'multiProcessChange' } type - Indicates the type of the event to observe. * @param { Callback } callback - Indicates the callback used to return the preferences changed * in multiple processes. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15500019 - Failed to obtain subscription service. + * @throws { BusinessError } 15500019 - Failed to obtain the subscription service. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice * @since 12 @@ -447,9 +457,9 @@ declare namespace sendablePreferences { * @param { 'dataChange' } type - Indicates the type of the event to observe. * @param { Array } keys - Indicates one or more keys to listen for. * @param { Callback } callback - Indicates the callback used to return the data change. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -462,9 +472,9 @@ declare namespace sendablePreferences { * * @param { 'change' } type - Indicates the event type. * @param { Callback } callback - Indicates the callback to unregister. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -477,9 +487,9 @@ declare namespace sendablePreferences { * * @param { 'multiProcessChange' } type - Indicates the event type. * @param { Callback } callback - Indicates the callback to unregister. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -493,9 +503,9 @@ declare namespace sendablePreferences { * @param { 'dataChange' } type - Indicates the event type. * @param { Array } keys - Indicates the data whose changes are not observed. * @param { Callback } callback - Indicates the callback to unregister. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice diff --git a/interface_sdk/api/@ohos.data.unifiedDataChannel.d.ts b/interface_sdk/api/@ohos.data.unifiedDataChannel.d.ts index d9383673b60f036bd51ca44b8189554516d732a6..d26d476e1b17b430fba3bce90703ca32c992065e 100644 --- a/interface_sdk/api/@ohos.data.unifiedDataChannel.d.ts +++ b/interface_sdk/api/@ohos.data.unifiedDataChannel.d.ts @@ -23,14 +23,22 @@ import image from "./@ohos.multimedia.image"; import Want from "./@ohos.app.ability.Want"; /** - * Provide methods for sharing data between different applications across unified data channels. + * As a part of the Unified Data Management Framework (UDMF), the unifiedDataChannel module provides unified data + * channels and standard data access interfaces for many-to-many data sharing across applications. It also provides + * definitions for uniform data types, such as text and image, to streamline data interaction between different + * applications and minimize the workload of data type adaptation. Although the UDMF does not parse user data, you are + * advised not to transfer sensitive personal data or privacy data due to low-level security of storage path. * * @namespace unifiedDataChannel * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 10 */ /** - * Provide methods for sharing data between different applications across unified data channels. + * As a part of the Unified Data Management Framework (UDMF), the unifiedDataChannel module provides unified data + * channels and standard data access interfaces for many-to-many data sharing across applications. It also provides + * definitions for uniform data types, such as text and image, to streamline data interaction between different + * applications and minimize the workload of data type adaptation. Although the UDMF does not parse user data, you are + * advised not to transfer sensitive personal data or privacy data due to low-level security of storage path. * * @namespace unifiedDataChannel * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -38,13 +46,17 @@ import Want from "./@ohos.app.ability.Want"; * @since 11 */ /** - * Provide methods for sharing data between different applications across unified data channels. + * As a part of the Unified Data Management Framework (UDMF), the unifiedDataChannel module provides unified data + * channels and standard data access interfaces for many-to-many data sharing across applications. It also provides + * definitions for uniform data types, such as text and image, to streamline data interaction between different + * applications and minimize the workload of data type adaptation. Although the UDMF does not parse user data, you are + * advised not to transfer sensitive personal data or privacy data due to low-level security of storage path. * * @namespace unifiedDataChannel * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ declare namespace unifiedDataChannel { /** @@ -96,7 +108,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ type ValueType = number | string | boolean | image.PixelMap | Want | ArrayBuffer | object | null | undefined; @@ -173,7 +185,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class UnifiedData { /** @@ -200,11 +212,11 @@ declare namespace unifiedDataChannel { * * @param { UnifiedRecord } record - Record will add into unified data. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; - *
2.Incorrect Parameters types. + *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ constructor(record: UnifiedRecord); /** @@ -220,7 +232,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ constructor(); /** @@ -247,11 +259,11 @@ declare namespace unifiedDataChannel { * * @param { UnifiedRecord } record - Record will add into unified data. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; - *
2.Incorrect Parameters types. + *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ addRecord(record: UnifiedRecord): void; /** @@ -276,12 +288,16 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ getRecords(): Array; /** - * Checks whether there is a specified type of data in DataProperties. + * Checks whether this UnifiedData object contains the specified data type, including the data types added by using + * the addEntry function. + * For file types, if the type set of UnifiedData contains general.jpeg, true is returned when the hasType API is + * called to check whether the general.image type is included, because the general.jpeg type belongs to the + * general.image type. * @param { string } type - indicates to query data type. * @returns { boolean } if having mimeType in UnifiedData returns true, else returns false. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; @@ -291,15 +307,19 @@ declare namespace unifiedDataChannel { * @since 12 */ /** - * Checks whether there is a specified type of data in DataProperties. + * Checks whether this UnifiedData object contains the specified data type, including the data types added by using + * the addEntry function. + * For file types, if the type set of UnifiedData contains general.jpeg, true is returned when the hasType API is + * called to check whether the general.image type is included, because the general.jpeg type belongs to the + * general.image type. * @param { string } type - indicates to query data type. * @returns { boolean } if having mimeType in UnifiedData returns true, else returns false. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; - *
2.Incorrect Parameters types. + *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ hasType(type: string): boolean; @@ -316,7 +336,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ getTypes(): Array; @@ -331,13 +351,13 @@ declare namespace unifiedDataChannel { } /** - * The data abstract supported by unified data + * Summarizes the data information of the unifiedData object, including the data type and size. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 10 */ /** - * The data abstract supported by unified data + * Summarizes the data information of the unifiedData object, including the data type and size. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @atomicservice @@ -390,12 +410,15 @@ declare namespace unifiedDataChannel { * @since 11 */ /** - * Describe the unified record + * An abstract definition of the data content supported by the UDMF. A UnifiedRecord object contains one or more data + * records, for example, a text record, an image record, or an HTML record. Since API version 15, different styles of + * the same content can be added to a UnifiedRecord object. Data users can obtain the corresponding styles as + * required. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class UnifiedRecord { /** @@ -420,7 +443,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ getType(): string; @@ -437,14 +460,15 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ constructor(); /** * Create unified record by type and value. * - * @param { string } type - indicates to data type of unified record. It can not be empty. When type of value is object, parameter type must be pixel-map or want UTD type. + * @param { string } type - indicates to data type of unified record. It can not be empty. When type of value is + * object, parameter type must be pixel-map or want UTD type. * @param { ValueType } value - indicates to value of unified record. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types; @@ -456,15 +480,16 @@ declare namespace unifiedDataChannel { /** * Create unified record by type and value. * - * @param { string } type - indicates to data type of unified record. It can not be empty. When type of value is object, parameter type must be pixel-map or want UTD type. + * @param { string } type - indicates to data type of unified record. It can not be empty. When type of value is + * object, parameter type must be pixel-map or want UTD type. * @param { ValueType } value - indicates to value of unified record. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; - *
2.Incorrect Parameters types; + *
2.Incorrect parameters types; *
3.Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ constructor(type: string, value: ValueType); @@ -483,9 +508,57 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ getValue(): ValueType; + + /** + * Obtains all the data types in the data record. This API can be called using the UnifiedRecord object to query all + * data types in the record, including the data types added using the addEntry function. + * + * @returns { Array } Return the types of unified record. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + getTypes(): Array; + + /** + * Adds data of a specified data type and content to the current data record. You can use this API to add different + * data types and contents to the same data. + * + * @param { string } type - type of entry. + * @param { ValueType } value - value of entry. + * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; + *
2.Incorrect parameters types. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + addEntry(type: string, value: ValueType): void; + + /** + * Get an entry from unified record + * + * @param { string } type - type of entry want to get. + * @returns { ValueType } Return the value corresponding to the type. + * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; + *
2.Incorrect parameters types. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + getEntry(type: string): ValueType; + + /** + * Get entries from unified record + * + * @returns { Record } Return all entries in the record. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + getEntries(): Record; } /** @@ -510,7 +583,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class Text extends UnifiedRecord { /** @@ -534,7 +607,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ details?: Record; } @@ -561,7 +634,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class PlainText extends Text { /** @@ -585,7 +658,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ textContent: string; /** @@ -609,7 +682,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ abstract?: string; } @@ -636,7 +709,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class Hyperlink extends Text { /** @@ -660,7 +733,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ url: string; /** @@ -684,7 +757,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ description?: string; } @@ -711,7 +784,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class HTML extends Text { /** @@ -735,7 +808,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ htmlContent: string; /** @@ -759,7 +832,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ plainContent?: string; } @@ -786,7 +859,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class File extends UnifiedRecord { /** @@ -810,17 +883,17 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ details?: Record; /** - * Indicates the uri of file + * URI of the local file or online file. The local file URI can be obtained using the getUriFromPath function. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 10 */ /** - * Indicates the uri of file + * URI of the local file or online file. The local file URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -828,13 +901,13 @@ declare namespace unifiedDataChannel { * @since 11 */ /** - * Indicates the uri of file + * URI of the local file or online file. The local file URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ uri: string; } @@ -861,17 +934,17 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class Image extends File { /** - * Indicates the uri of image + * URI of the local image or online image. The local image URI can be obtained using the getUriFromPath function. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 10 */ /** - * Indicates the uri of image + * URI of the local image or online image. The local image URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -879,13 +952,13 @@ declare namespace unifiedDataChannel { * @since 11 */ /** - * Indicates the uri of image + * URI of the local image or online image. The local image URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ imageUri: string; } @@ -912,17 +985,17 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class Video extends File { /** - * Indicates the uri of video + * URI of the local video or online video. The local video URI can be obtained using the getUriFromPath function. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 10 */ /** - * Indicates the uri of video + * URI of the local video or online video. The local video URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -930,13 +1003,13 @@ declare namespace unifiedDataChannel { * @since 11 */ /** - * Indicates the uri of video + * URI of the local video or online video. The local video URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ videoUri: string; } @@ -963,17 +1036,17 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class Audio extends File { /** - * Indicates the uri of audio + * URI of the local audio or online audio. The local audio URI can be obtained using the getUriFromPath function. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 10 */ /** - * Indicates the uri of audio + * URI of the local audio or online audio. The local audio URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -981,13 +1054,13 @@ declare namespace unifiedDataChannel { * @since 11 */ /** - * Indicates the uri of audio + * URI of the local audio or online audio. The local audio URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ audioUri: string; } @@ -1014,17 +1087,17 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class Folder extends File { /** - * Indicates the uri of folder + * URI of the local folder or online folder. The local folder URI can be obtained using the getUriFromPath function. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 10 */ /** - * Indicates the uri of folder + * URI of the local folder or online folder. The local folder URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -1032,13 +1105,13 @@ declare namespace unifiedDataChannel { * @since 11 */ /** - * Indicates the uri of folder + * URI of the local folder or online folder. The local folder URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ folderUri: string; } @@ -1409,7 +1482,41 @@ declare namespace unifiedDataChannel { * @StageModelOnly * @since 12 */ - DRAG = 'Drag' + /** + * Indicates the intention of drag + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @stagemodelonly + * @since 14 + */ + DRAG = 'Drag', + + /** + * Indicates a system sharing channel. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @stagemodelonly + * @since 20 + */ + SYSTEM_SHARE = 'SystemShare', + + /** + * Indicates a Picker channel. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @stagemodelonly + * @since 20 + */ + PICKER = 'Picker', + + /** + * Indicates a menu channel. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @stagemodelonly + * @since 20 + */ + MENU = 'Menu' } /** @@ -1458,6 +1565,318 @@ declare namespace unifiedDataChannel { key?: string; }; + /** + * Defines the types of file conflict options when getting data from the UDMF. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + enum FileConflictOptions { + /** + * Overwrite when destUri has file with same name. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + OVERWRITE, + + /** + * Skip when destUri has file with same name. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + SKIP + } + + /** + * Defines the types of progress indicator when getting data from the UDMF. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + enum ProgressIndicator { + /** + * Getting data without system default progress indicator. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + NONE, + + /** + * Getting data with system default progress indicator. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + DEFAULT + } + + /** + * Defines the listener status of obtaining progress and data. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + enum ListenerStatus { + /** + * Indicates the finished status. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + FINISHED = 0, + + /** + * Indicates that processing is still in progress. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + PROCESSING, + + /** + * Indicates that the process has been canceled. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + CANCELED, + + /** + * Indicates that an internal error has occurred. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + INNER_ERROR = 200, + + /** + * Indicates that the GetDataParams contains invalid parameters. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + INVALID_PARAMETERS, + + /** + * Indicates that no data is obtained. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + DATA_NOT_FOUND, + + /** + * Indicates that an error occurred in the synchronization process. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + SYNC_FAILED, + + /** + * Indicates that an error occurred during file copying. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + COPY_FILE_FAILED, + } + + /** + * Indicates the progress information. + * + * @interface ProgressInfo + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + interface ProgressInfo { + /** + * Indicates the UDMF processing progress. + * + * @type { number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + progress: number; + + /** + * Indicates the status of obtaining progress and data. + * + * @type { ListenerStatus } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + status: ListenerStatus; + } + + /** + * A listener callback function that fetches progress info and data. + * + * @typedef { function } DataProgressListener + * @param { ProgressInfo } progressInfo - the progress information. + * @param { UnifiedData | null } data - Data obtained when the progress reaches 100%. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + type DataProgressListener = (progressInfo: ProgressInfo, data: UnifiedData | null) => void; + + /** + * Represents the get data parameters when getting data from udmf. + * + * @interface GetDataParams + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + interface GetDataParams { + /** + * Indicates whether to use default system progress indicator. + * + * @type { ProgressIndicator } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + progressIndicator: ProgressIndicator; + + /** + * Indicates progress and data listener when getting unified data. + * + * @type { DataProgressListener } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + dataProgressListener: DataProgressListener; + + /** + * Indicates the dest path uri where copy file will be copied to sandbox of application. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + destUri?: string; + + /** + * Indicates file conflict options when dest path has file with same name. + * + * @type { FileConflictOptions } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + fileConflictOptions?: FileConflictOptions; + + /** + * Indicates the supported data information. + * + * @type { ?DataLoadInfo } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 20 + */ + acceptableInfo?: DataLoadInfo; + } + + /** + * Indicates data loading information. + * + * @interface DataLoadInfo + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 20 + */ + interface DataLoadInfo { + /** + * Represents the data type or supported types to load. + *
This parameter is mandatory when used by the data provider. + * + * @type { ?Set } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 20 + */ + types?: Set; + + /** + * Indicates the maximum number of data records to be loaded. + * + * @type { ?number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 20 + */ + recordCount?: number; + } + + /** + * Indicates the callback function for loading data. + * + * @typedef { function } DataLoadHandler + * @param { DataLoadInfo } acceptableInfo Indicates the type and number of data that can be accepted by the receiver. + * @returns { UnifiedData | null } the {@link UnifiedData} object to be loaded. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 20 + */ + type DataLoadHandler = (acceptableInfo?: DataLoadInfo) => UnifiedData | null; + + /** + * Indicates data loading params. + * + * @interface DataLoadParams + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 20 + */ + interface DataLoadParams { + /** + * Indicates the callback function for loading data. + * + * @type { DataLoadHandler } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 20 + */ + loadHandler: DataLoadHandler; + + /** + * Indicates data loading information. + * @type { DataLoadInfo } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 20 + */ + dataLoadInfo: DataLoadInfo; + } + /** * Insert data into unified data channel by Intention * @@ -1561,8 +1980,10 @@ declare namespace unifiedDataChannel { /** * Query data of unified data channel by Intention or Unique Identifier * - * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} or {@link UnifiedData}. - * @param { AsyncCallback> } callback - {Array}: the target {@link UnifiedData} object array. + * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} + * or {@link UnifiedData}. + * @param { AsyncCallback> } callback - {Array}: the target {@link UnifiedData} + * object array. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -1571,8 +1992,10 @@ declare namespace unifiedDataChannel { /** * Query data of unified data channel by Intention or Unique Identifier * - * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} or {@link UnifiedData}. - * @param { AsyncCallback> } callback - {Array}: the target {@link UnifiedData} object array. + * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} + * or {@link UnifiedData}. + * @param { AsyncCallback> } callback - {Array}: the target {@link UnifiedData} object + * array. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -1584,7 +2007,8 @@ declare namespace unifiedDataChannel { /** * Query data of unified data channel by Intention or Unique Identifier * - * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} or {@link UnifiedData}. + * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} + * or {@link UnifiedData}. * @returns { Promise> } {Array}: the target {@link UnifiedData} object array. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. @@ -1594,7 +2018,8 @@ declare namespace unifiedDataChannel { /** * Query data of unified data channel by Intention or Unique Identifier * - * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} or {@link UnifiedData}. + * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} + * or {@link UnifiedData}. * @returns { Promise> } {Array}: the target {@link UnifiedData} object array. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. @@ -1607,8 +2032,10 @@ declare namespace unifiedDataChannel { /** * Delete data of unified data channel by Intention or Unique Identifier * - * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} or {@link UnifiedData}. - * @param { AsyncCallback> } callback - {Array}: the deleted {@link UnifiedData} object array. + * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} + * or {@link UnifiedData}. + * @param { AsyncCallback> } callback - {Array}: the deleted {@link UnifiedData} + * object array. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -1617,8 +2044,10 @@ declare namespace unifiedDataChannel { /** * Delete data of unified data channel by Intention or Unique Identifier * - * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} or {@link UnifiedData}. - * @param { AsyncCallback> } callback - {Array}: the deleted {@link UnifiedData} object array. + * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} + * or {@link UnifiedData}. + * @param { AsyncCallback> } callback - {Array}: the deleted {@link UnifiedData} + * object array. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -1630,7 +2059,8 @@ declare namespace unifiedDataChannel { /** * Delete data of unified data channel by Intention or Unique Identifier * - * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} or {@link UnifiedData}. + * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} + * or {@link UnifiedData}. * @returns { Promise> } {Array}: the deleted {@link UnifiedData} object array. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. @@ -1640,7 +2070,8 @@ declare namespace unifiedDataChannel { /** * Delete data of unified data channel by Intention or Unique Identifier * - * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} or {@link UnifiedData}. + * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} + * or {@link UnifiedData}. * @returns { Promise> } {Array}: the deleted {@link UnifiedData} object array. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. @@ -1651,26 +2082,45 @@ declare namespace unifiedDataChannel { function deleteData(options: Options): Promise>; /** - * Set app sharing options. + * Sets the ShareOptions for the application data. Currently, only the drag-and-drop data channel is supported. * * @param { Intention } intention - Describe the sharing channel that UDMF support. * @param { ShareOptions } shareOptions - Types of scope that UnifiedData can be used. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses + * system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; * 2. Incorrect parameter types. - * @throws { BusinessError } 20400001 - Settings already exist. + * @throws { BusinessError } 20400001 - Settings already exist. To reconfigure, remove the existing sharing options. * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @systemapi * @StageModelOnly * @since 12 */ + /** + * Sets the ShareOptions for the application data. Currently, only the drag-and-drop data channel is supported. + * + * @permission ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION + * @param { Intention } intention - Describe the sharing channel that UDMF support. Currently only supports DRAG + * intention. + * @param { ShareOptions } shareOptions - Types of scope that UnifiedData can be used. + * @throws { BusinessError } 201 - Permission denied. Interface caller does not have permission + * "ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION". + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + * 2. Incorrect parameter types; + * 3. Parameter verification failed. + * @throws { BusinessError } 20400001 - Settings already exist. To reconfigure, remove the existing sharing options. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @stagemodelonly + * @since 14 + */ function setAppShareOptions(intention: Intention, shareOptions: ShareOptions): void; /** * Remove app sharing options. * * @param { Intention } intention - Describe the sharing channel that UDMF support. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; * 2. Incorrect parameter types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -1678,7 +2128,38 @@ declare namespace unifiedDataChannel { * @StageModelOnly * @since 12 */ + /** + * Remove app sharing options. + * + * @permission ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION + * @param { Intention } intention - Describe the sharing channel that UDMF support. Currently only supports DRAG + * intention. + * @throws { BusinessError } 201 - Permission denied. Interface caller does not have permission + * "ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION". + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + * 2. Incorrect parameter types; + * 3. Parameter verification failed. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @stagemodelonly + * @since 14 + */ function removeAppShareOptions(intention: Intention): void; + + /** + * Converts the provided data into a multi-style data structure, which is useful when the original data uses multiple + * records to represent different styles of the same data. This API is used only when the following rules are met: + * 1.The number of records in data is greater than + * 2.The value of unifiedData.properties.tag is records_to_entries_data_format. + * + * @param { UnifiedData } data - {@link UnifiedData} Data to convert. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified. + * 2. Incorrect parameter types. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @stagemodelonly + * @atomicservice + * @since 17 + */ + function convertRecordsToEntries(data: UnifiedData): void; } export default unifiedDataChannel; diff --git a/interface_sdk/api/@ohos.data.uniformDataStruct.d.ts b/interface_sdk/api/@ohos.data.uniformDataStruct.d.ts index adb83f2e52a220e949abfcceb43040e0e158d45b..4f811c4ed20686cd02cc92b179db4dfc3b651ce7 100644 --- a/interface_sdk/api/@ohos.data.uniformDataStruct.d.ts +++ b/interface_sdk/api/@ohos.data.uniformDataStruct.d.ts @@ -18,6 +18,8 @@ * @kit ArkData */ +import image from './@ohos.multimedia.image'; + /** * Provide uniform data struct definition. * @@ -60,7 +62,14 @@ declare namespace uniformDataStruct { */ abstract?: string; /** - * Indicates the details of the PlainText. + * Object of the dictionary type used to describe the attributes of the text content. Both the key and value of the + * object are of the string type. For example, the following is a details object used to describe the properties of + * a file: + * { + * "title":"Title of the file", + * "content":"Content of the file" + * } + * By default, it is an empty dictionary object. * * @type { ?Record } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -102,7 +111,14 @@ declare namespace uniformDataStruct { */ description?: string; /** - * Indicates the details of the Hyperlink. + * Object of the dictionary type used to describe the attributes of the hyperlink. Both the key and value of the + * object are of the string type. For example, the following is a details object used to describe the properties of + * a file: + * { + * "title":"Title of the hyperlink", + * "content":"Content" + * } + * By default, it is an empty dictionary object. * * @type { ?Record } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -146,7 +162,14 @@ declare namespace uniformDataStruct { */ plainContent?: string; /** - * Indicates the details of html. + * Object of the dictionary type used to describe the attributes of the HTML content. Both the key and value of the + * object are of the string type. For example, the following is a details object used to describe the properties of + * a file: + * { + * "title":"Title of the HTML content", + * "content":"Content" + * } + * By default, it is an empty dictionary object. * * @type { ?Record } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -164,7 +187,7 @@ declare namespace uniformDataStruct { */ interface OpenHarmonyAppItem { /** - * Indicates the uniform data type of this data struct. + * Uniform data type, which has a fixed value of openharmony.app-item. For details, see UniformDataType. * * @type { 'openharmony.app-item' } * @readonly @@ -221,7 +244,8 @@ declare namespace uniformDataStruct { */ abilityName: string; /** - * Indicates the details of app. + * Object of the dictionary type used to describe the icon. The key is of the string type, and the value can be a + * number, a string, or a Uint8Array. By default, it is an empty dictionary object. * * @type { ?Record } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -229,6 +253,235 @@ declare namespace uniformDataStruct { */ details?: Record; } + + /** + * Uniform data type, which has a fixed value of general.content-form. + * + * @interface ContentForm + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 14 + */ + interface ContentForm { + /** + * Indicates the uniform data type of this data struct. + * + * @type { 'general.content-form' } + * @readonly + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 14 + */ + readonly uniformDataType: 'general.content-form'; + + /** + * Indicates the thumb data of content form. + * + * @type { Uint8Array } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 14 + */ + thumbData?: Uint8Array; + + /** + * Indicates the description of content form. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 14 + */ + description?: string; + + /** + * Indicates the title of content form. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 14 + */ + title: string; + + /** + * Indicates the app icon of content form. + * + * @type { Uint8Array } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 14 + */ + appIcon?: Uint8Array; + + /** + * Indicates the app name of content form. + * + * @type { appName } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 14 + */ + appName?: string; + + /** + * Indicates the link url of content form. + * + * @type { linkUri } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 14 + */ + linkUri?: string; + } + + /** + * Describe form uniform data struct. + * + * @interface Form + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + interface Form { + /** + * Uniform data type, which has a fixed value of openharmony.form. For details, see UniformDataType. + * + * @type { 'openharmony.form' } + * @readonly + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + readonly uniformDataType: 'openharmony.form'; + + /** + * Indicates the form id of form. + * + * @type { number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + formId: number; + + /** + * Indicates the form name of form. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + formName: string; + + /** + * Indicates the bundle name of form. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + bundleName: string; + + /** + * Indicates the ability name of form. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + abilityName: string; + + /** + * Indicates the module of form. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + module: string; + + /** + * Indicates the details of form. + * + * @type { ?Record } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + details?: Record; + } + + /** + * Describe the file uri uniform data struct. + * + * @interface FileUri + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + interface FileUri { + /** + * Uniform data type, which has a fixed value of general.file-uri. For details, see UniformDataType. + * + * @type { 'general.file-uri' } + * @readonly + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + readonly uniformDataType: 'general.file-uri'; + + /** + * Indicates the oriUri of fileUri. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + oriUri: string; + + /** + * Indicates the file type of fileUri. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + fileType: string; + + /** + * Indicates the details of fileUri. + * + * @type { ?Record } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + details?: Record; + } + + /** + * Describe the pixelMap uniform data struct. + * + * @interface PixelMap + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + interface PixelMap { + /** + * Uniform data type, which has a fixed value of openharmony.pixel-map. For details, see UniformDataType. + * + * @type { 'openharmony.pixel-map' } + * @readonly + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + readonly uniformDataType: 'openharmony.pixel-map'; + + /** + * Indicates the pixelMap value of pixelMap. + * + * @type { image.PixelMap } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + pixelMap: image.PixelMap; + + /** + * Indicates the details of pixelMap. + * + * @type { ?Record } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + details?: Record; + } } export default uniformDataStruct; \ No newline at end of file diff --git a/interface_sdk/api/@ohos.data.uniformTypeDescriptor.d.ts b/interface_sdk/api/@ohos.data.uniformTypeDescriptor.d.ts index b38c554ec81cd9e6d98f7a84e29fab670a7816de..c3e9d9eca511ccbf87508036f43f22f5fdcc0fb5 100644 --- a/interface_sdk/api/@ohos.data.uniformTypeDescriptor.d.ts +++ b/interface_sdk/api/@ohos.data.uniformTypeDescriptor.d.ts @@ -40,7 +40,7 @@ * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ declare namespace uniformTypeDescriptor { /** @@ -65,7 +65,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ enum UniformDataType { /** @@ -111,7 +111,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ TEXT = 'general.text', @@ -134,7 +134,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ PLAIN_TEXT = 'general.plain-text', @@ -157,7 +157,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ HTML = 'general.html', @@ -180,7 +180,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ HYPERLINK = 'general.hyperlink', @@ -475,7 +475,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ IMAGE = 'general.image', @@ -722,7 +722,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ VIDEO = 'general.video', @@ -865,7 +865,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ AUDIO = 'general.audio', @@ -983,15 +983,15 @@ declare namespace uniformTypeDescriptor { /** * Mp2 audio format data type. - * + * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 12 */ MP2 = 'general.mp2', /** - * Mpeg audio format data type. - * + * MPEG audio format. This type belongs to AUDIO. + * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 12 */ @@ -999,7 +999,7 @@ declare namespace uniformTypeDescriptor { /** * Ulaw audio format data type. - * + * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 12 */ @@ -1048,7 +1048,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ FILE = 'general.file', @@ -1079,7 +1079,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ FOLDER = 'general.folder', @@ -1172,7 +1172,7 @@ declare namespace uniformTypeDescriptor { JAVA_ARCHIVE = 'com.sun.java-archive', /** - * GNU archive data type. + * GNU. This type belongs to ARCHIVE. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 11 @@ -1548,7 +1548,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ OPENHARMONY_PIXEL_MAP = 'openharmony.pixel-map', @@ -1611,7 +1611,7 @@ declare namespace uniformTypeDescriptor { /** * Ofd data type. - * + * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 12 */ @@ -1619,7 +1619,7 @@ declare namespace uniformTypeDescriptor { /** * Cad data type. - * + * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 12 */ @@ -1627,11 +1627,27 @@ declare namespace uniformTypeDescriptor { /** * Octet stream data type. - * + * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 12 */ - OCTET_STREAM = 'general.octet-stream' + OCTET_STREAM = 'general.octet-stream', + + /** + * File uri data type. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + FILE_URI = 'general.file-uri', + + /** + * Content widget type. This type belongs to OBJECT. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + CONTENT_FORM = 'general.content-form' } /** @@ -1775,12 +1791,14 @@ declare namespace uniformTypeDescriptor { function getTypeDescriptor(typeId: string): TypeDescriptor; /** - * Queries and returns the uniform type descriptor by the given filename extension and the uniform data type it belongs to. + * Queries and returns the uniform type descriptor by the given filename extension and the uniform data type it + * belongs to. * * @param { string } filenameExtension - Filename extension. * @param { string } [belongsTo] - A uniform data type ID it belongs to. * @returns { string } Returns the uniform data type ID corresponding to the given filename extension and the - *
uniform data type it belongs to(If the 'belongsTo' parameter is set) or flexible type if the uniform data type does not exist. + *
uniform data type it belongs to(If the 'belongsTo' parameter is set) or flexible type if the uniform data type + * does not exist. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -1803,28 +1821,32 @@ declare namespace uniformTypeDescriptor { function getUniformDataTypeByMIMEType(mimeType: string, belongsTo?: string): string; /** - * Queries and returns the uniform type descriptor list by the given filename extension and the uniform data type it belongs to. + * Queries and returns the uniform type descriptor list by the given filename extension and the uniform data type it + * belongs to. * * @param { string } filenameExtension - Filename extension. * @param { string } [belongsTo] - A uniform data type ID it belongs to. - * @returns { Array } Returns the uniform data type ID list corresponding to the given filename extension and the - *
uniform data type it belongs to(If the 'belongsTo' parameter is set) or flexible type if the uniform data type does not exist. + * @returns { Array } Returns the uniform data type ID list corresponding to the given filename extension and + * the uniform data type it belongs to(If the 'belongsTo' parameter is set) or flexible type if the uniform data type + * does not exist. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; - *
2.Incorrect Parameters types. + *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 13 */ function getUniformDataTypesByFilenameExtension(filenameExtension: string, belongsTo?: string): Array; /** - * Queries and returns the uniform type descriptor list by the given MIME type and the uniform data type it belongs to. + * Queries and returns the uniform type descriptor list by the given MIME type and the uniform data type it belongs + * to. * * @param { string } mimeType - MIME type. * @param { string } [belongsTo] - A uniform data type ID it belongs to. - * @returns { Array } Returns the uniform data type ID list corresponding to the given MIME type and the uniform data type - *
it belongs to(If the 'belongsTo' parameter is set) or flexible type if the uniform data type does not exist. + * @returns { Array } Returns the uniform data type ID list corresponding to the given MIME type and the + * uniform data type it belongs to(If the 'belongsTo' parameter is set) or flexible type if the uniform data type does + * not exist. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; - *
2.Incorrect Parameters types. + *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 13 */ diff --git a/kv_store/CODEOWNERS b/kv_store/CODEOWNERS index 71c2f7c92dd90f314b1fd28f1fae26e4cfb6cad5..e26e631efb9142ca6ff5b0538a7d06875720dda6 100644 --- a/kv_store/CODEOWNERS +++ b/kv_store/CODEOWNERS @@ -14,6 +14,6 @@ # any change to # frameworks/innerkitsimpl/distributeddatasvc/include/distributeddata_ipc_interface_code.h # frameworks/innerkitsimpl/kvdb/include/distributeddata_kvdb_ipc_interface_code.h -# needs to be reviewed by @leonchan5 -frameworks/innerkitsimpl/distributeddatasvc/include/distributeddata_ipc_interface_code.h @leonchan5 -frameworks/innerkitsimpl/kvdb/include/distributeddata_kvdb_ipc_interface_code.h @leonchan5 \ No newline at end of file +# needs to be reviewed by @leonchan5 liubao6@huawei.com +frameworks/innerkitsimpl/distributeddatasvc/include/distributeddata_ipc_interface_code.h @leonchan5 liubao6@huawei.com +frameworks/innerkitsimpl/kvdb/include/distributeddata_kvdb_ipc_interface_code.h @leonchan5 liubao6@huawei.com \ No newline at end of file diff --git a/kv_store/bundle.json b/kv_store/bundle.json index fda9c229d5eabd87ef67c9ba975f4f05b14e223e..e998283351d445b5410929ade372891930972914 100644 --- a/kv_store/bundle.json +++ b/kv_store/bundle.json @@ -51,8 +51,6 @@ "deps": { "third_party": [ "bounds_checking_function", - "cJSON", - "jsoncpp", "libuv", "openssl", "sqlite", @@ -66,6 +64,7 @@ "bundle_framework", "access_token", "common_event_service", + "cJSON", "c_utils", "device_manager", "dmsfwk", @@ -79,7 +78,9 @@ "safwk", "samgr", "file_api", - "zlib" + "zlib", + "openssl", + "sqlite" ] }, "build": { @@ -92,7 +93,6 @@ "//foundation/distributeddatamgr/kv_store/interfaces/jskits/distributedkvstore:build_module", "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/jskits/distributedkvstore:build_module", "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_client_sync", - "//foundation/distributeddatamgr/kv_store/interfaces/cj:cj_distributed_kv_store_ffi", "//foundation/distributeddatamgr/kv_store/databaseutils:database_utils" ], "inner_kits": [ @@ -277,6 +277,42 @@ ], "header_base": "//foundation/distributeddatamgr/kv_store/databaseutils/include" } + }, + { + "name": "//foundation/distributeddatamgr/kv_store/interfaces/cj:cj_distributed_kv_store_ffi", + "header": { + "header_files": [], + "header_base": "//foundation/distributeddatamgr/kv_store/frameworks/cj/include" + } + }, + { + "name": "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb_client", + "header": { + "header_files": [ + "relational_store_client.h", + "relational_store_sqlite_ext.h", + "relational_store_manager.h" + ], + "header_base": "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/interfaces/include/relational" + } + }, + { + "name": "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb_client", + "header": { + "header_files": [ + "store_observer.h" + ], + "header_base": "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/interfaces/include" + } + }, + { + "name": "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb_client", + "header": { + "header_files": [ + "query.h" + ], + "header_base": "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/include" + } } ], "test": [ diff --git a/kv_store/databaseutils/include/acl.h b/kv_store/databaseutils/include/acl.h index 8177eb0ea1b4cc37676650c8b12db770ddb385ff..0e4c9d9207361d87876bcce74c58c058a5729102 100644 --- a/kv_store/databaseutils/include/acl.h +++ b/kv_store/databaseutils/include/acl.h @@ -151,6 +151,7 @@ private: std::unique_ptr Serialize(uint32_t &bufSize); int DeSerialize(const char *p, int32_t bufSize); int InsertEntry(const AclXattrEntry &entry); + std::string Anonymous(const std::string &name); AclXattrHeader header_; /* * Only one entry should exist for the following types: diff --git a/kv_store/databaseutils/src/acl.cpp b/kv_store/databaseutils/src/acl.cpp index f220bf378c1007137f8cedf1756b0e73c451502f..bb7aa345d43d5259cddd0fcea66ac8b8502cb039 100644 --- a/kv_store/databaseutils/src/acl.cpp +++ b/kv_store/databaseutils/src/acl.cpp @@ -33,6 +33,11 @@ namespace OHOS { namespace DATABASE_UTILS { using namespace DistributedKv; +static constexpr int32_t HEAD_SIZE = 3; +static constexpr int32_t END_SIZE = 3; +static constexpr int32_t MIN_SIZE = 9; +static constexpr const char *REPLACE_CHAIN = "***"; +static constexpr const char *DEFAULT_ANONYMOUS = "******"; Acl::Acl(const std::string &path) : path_(path), hasError_(false) { /* init acl from file's defaule or mode*/ @@ -156,7 +161,7 @@ void Acl::AclFromDefault() AclFromMode(); } else { hasError_ = true; - ZLOGW("The getxattr failed. error %{public}s path %{public}s", std::strerror(errno), path_.c_str()); + ZLOGW("The getxattr failed. error %{public}s path %{public}s", std::strerror(errno), Anonymous(path_).c_str()); } } @@ -217,5 +222,18 @@ bool Acl::HasEntry(const AclXattrEntry &Acl) { return entries_.find(Acl) != entries_.end(); } + +std::string Acl::Anonymous(const std::string &name) +{ + if (name.length() <= HEAD_SIZE) { + return DEFAULT_ANONYMOUS; + } + + if (name.length() < MIN_SIZE) { + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN); + } + + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE)); +} } } \ No newline at end of file diff --git a/kv_store/databaseutils/test/BUILD.gn b/kv_store/databaseutils/test/BUILD.gn index 2899a28fc4b8e7d407614c09735c83b6691379f3..5c4891a8d761e340f4fc50cd82ba7f34dadb6731 100644 --- a/kv_store/databaseutils/test/BUILD.gn +++ b/kv_store/databaseutils/test/BUILD.gn @@ -30,7 +30,7 @@ ohos_unittest("DataBaseUtilsTest") { sources += [ "../src/acl.cpp" ] configs = [ ":database_utils_config" ] - + cflags = [ "-Dprivate=public" ] external_deps = [ "hilog:libhilog" ] public_external_deps = [ "bounds_checking_function:libsec_shared", @@ -38,89 +38,6 @@ ohos_unittest("DataBaseUtilsTest") { ] } -ohos_unittest("DataMgrServiceProxyVirtualTest") { - module_out_path = module_output_path - - sources = [ - "${kv_store_base_path}/frameworks/innerkitsimpl/distributeddatasvc/src/datamgr_service_proxy.cpp", - "datamgr_service_proxy_virtual_test.cpp", - ] - - configs = [ ":database_utils_config" ] - - external_deps = [ - "c_utils:utils", - "googletest:gtest_main", - "hilog:libhilog", - "ipc:ipc_single", - "samgr:samgr_proxy", - ] - - deps = [ - "${kv_store_base_path}/frameworks/libs/distributeddb/:distributeddb", - "${kv_store_base_path}/interfaces/innerkits/distributeddata:distributeddata_inner", - "${kv_store_base_path}/interfaces/innerkits/distributeddatamgr:distributeddata_mgr", - ] -} - -ohos_unittest("BlobVirtualTest") { - module_out_path = module_output_path - - sources = [ - "${kv_store_base_path}/frameworks/innerkitsimpl/distributeddatasvc/src/datamgr_service_proxy.cpp", - "bool_virtual_test.cpp", - ] - - configs = [ ":database_utils_config" ] - - external_deps = [ - "c_utils:utils", - "googletest:gtest_main", - "hilog:libhilog", - "ipc:ipc_single", - "samgr:samgr_proxy", - ] - - deps = [ - "${kv_store_base_path}/frameworks/libs/distributeddb/:distributeddb", - "${kv_store_base_path}/interfaces/innerkits/distributeddata:distributeddata_inner", - "${kv_store_base_path}/interfaces/innerkits/distributeddatamgr:distributeddata_mgr", - ] -} - -ohos_unittest("DataQueryVirtualTest") { - module_out_path = module_output_path - - sources = [ - "${kv_store_base_path}/frameworks/innerkitsimpl/distributeddatasvc/src/datamgr_service_proxy.cpp", - "data_query_virtual_test.cpp", - "delegate_mgr_callback_virtual_test.cpp", - "distributed_kv_data_manager_vritual_test.cpp", - "kv_utils_virtual_test.cpp", - "kvdb_notifier_virtual_test.cpp", - "kvstore_datashare_bridge_virtual_test.cpp", - "local_kv_store_virtual_test.cpp", - "local_subscribe_store_virtual_test.cpp", - "single_kvstore_query_virtual_test.cpp", - ] - - configs = [ ":database_utils_config" ] - - external_deps = [ - "c_utils:utils", - "googletest:gtest_main", - "hilog:libhilog", - "ipc:ipc_single", - "samgr:samgr_proxy", - ] - - deps = [ - "${kv_store_base_path}/frameworks/libs/distributeddb/:distributeddb", - "${kv_store_base_path}/interfaces/innerkits/distributeddata:distributeddata_inner", - "${kv_store_base_path}/interfaces/innerkits/distributeddatamgr:distributeddata_mgr", - ] -} - group("unittest") { testonly = true diff --git a/kv_store/databaseutils/test/acl_test.cpp b/kv_store/databaseutils/test/acl_test.cpp index 46e1934a43d464bd316a9e0472941b08c7a9923a..3aac91746c7e3a0c08ac496b5127e32c448eea9a 100644 --- a/kv_store/databaseutils/test/acl_test.cpp +++ b/kv_store/databaseutils/test/acl_test.cpp @@ -184,7 +184,7 @@ HWTEST_F(AclTest, SetDefaultUser002, TestSize.Level0) * @tc.require: * @tc.author: SQL */ -HWTEST_F(AclTest, AclXattrEntry001, TestSize.Level0) +HWTEST_F(AclTest, AclXattrEntry001, TestSize.Level1) { AclXattrEntry entryA(ACL_TAG::USER, UID, Acl::R_RIGHT | Acl::W_RIGHT); AclXattrEntry entryB(ACL_TAG::USER, UID, Acl::R_RIGHT | Acl::W_RIGHT); @@ -201,7 +201,7 @@ HWTEST_F(AclTest, AclXattrEntry001, TestSize.Level0) * @tc.require: * @tc.author: SQL */ -HWTEST_F(AclTest, AclXattrEntry002, TestSize.Level0) +HWTEST_F(AclTest, AclXattrEntry002, TestSize.Level1) { AclXattrEntry entryA(ACL_TAG::USER, UID, Acl::R_RIGHT | Acl::W_RIGHT); auto result = entryA.IsValid(); @@ -223,7 +223,7 @@ HWTEST_F(AclTest, AclXattrEntry002, TestSize.Level0) * @tc.require: * @tc.author: SQL */ -HWTEST_F(AclTest, ACL_PERM001, TestSize.Level0) +HWTEST_F(AclTest, ACL_PERM001, TestSize.Level1) { ACL_PERM perm1; perm1.SetR(); @@ -236,4 +236,22 @@ HWTEST_F(AclTest, ACL_PERM001, TestSize.Level0) EXPECT_TRUE(perm1.IsWritable()); EXPECT_TRUE(perm1.IsExecutable()); } + +/** + * @tc.name: Anonymous001 + * @tc.desc: Test Anonymous. + * @tc.type: FUNC + * @tc.require: + * @tc.author: SQL + */ +HWTEST_F(AclTest, Anonymous001, TestSize.Level1) +{ + Acl aclNew(PATH_ABC); + std::string name = ""; + EXPECT_EQ(aclNew.Anonymous(name), "******"); + name = "12345678"; + EXPECT_EQ(aclNew.Anonymous(name), "123***"); + name = "123456789"; + EXPECT_EQ(aclNew.Anonymous(name), "123***789"); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/bool_virtual_test.cpp b/kv_store/databaseutils/test/bool_virtual_test.cpp deleted file mode 100644 index 6f5c0a5f4a0ec9f7064b7accb39de83784b7ecda..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/bool_virtual_test.cpp +++ /dev/null @@ -1,540 +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. - */ -#define LOG_TAG "BlobVirtualTest" - -#include "blob.h" -#include "change_notification.h" -#include "kv_types_util.h" -#include "types.h" -#include -#include -#include - -using namespace OHOS::DistributedKv; -using namespace testing; -using namespace testing::ext; -namespace OHOS::Test { -class BlobVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void BlobVirtualTest::SetUpTestCase(void) -{} - -void BlobVirtualTest::TearDownTestCase(void) -{} - -void BlobVirtualTest::SetUp(void) -{} - -void BlobVirtualTest::TearDown(void) -{} - -class ChangeNotificationVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void ChangeNotificationVirtualTest::SetUpTestCase(void) -{} - -void ChangeNotificationVirtualTest::TearDownTestCase(void) -{} - -void ChangeNotificationVirtualTest::SetUp(void) -{} - -void ChangeNotificationVirtualTest::TearDown(void) -{} - -/** - * @tc.name: DefaultConstructor - * @tc.desc: - * @tc.type: DefaultConstructor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, DefaultConstructor, TestSize.Level0) -{ - ZLOGI("DefaultConstructor begin."); - Blob defaultConstructor; - EXPECT_TRUE(defaultConstructor.Empty()); -} - -/** - * @tc.name: CopyConstructor - * @tc.desc: - * @tc.type: CopyConstructor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, CopyConstructor, TestSize.Level0) -{ - ZLOGI("CopyConstructor begin."); - Blob copyConstructor1("hello", 5); - Blob copyConstructor2(blob1); - EXPECT_EQ(copyConstructor1, copyConstructor2); -} - -/** - * @tc.name: MoveConstructor - * @tc.desc: - * @tc.type: MoveConstructor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, MoveConstructor, TestSize.Level0) -{ - ZLOGI("MoveConstructor begin."); - Blob moveConstructor1("hello", 5); - Blob moveConstructor2(std::move(blob1)); - EXPECT_TRUE(moveConstructor1.Empty()); - EXPECT_EQ(std::string(moveConstructor2.Data().begin(), - moveConstructor2.Data().end()), "hello"); -} - -/** - * @tc.name: CopyAssignmentOperator - * @tc.desc: - * @tc.type: CopyAssignmentOperator test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, CopyAssignmentOperator) -{ - ZLOGI("CopyAssignmentOperator begin."); - Blob copyAssignmentOperator1("hello", 5); - Blob copyAssignmentOperator2; - copyAssignmentOperator2 = copyAssignmentOperator1; - EXPECT_EQ(copyAssignmentOperator1, copyAssignmentOperator2); -} - -/** - * @tc.name: MoveAssignmentOperator - * @tc.desc: - * @tc.type: MoveAssignmentOperator test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, MoveAssignmentOperator, TestSize.Level0) -{ - ZLOGI("MoveAssignmentOperator begin."); - Blob moveAssignmentOperator1("hello", 5); - Blob moveAssignmentOperator2; - blob2 = std::move(moveAssignmentOperator1); - EXPECT_TRUE(moveAssignmentOperator1.Empty()); - EXPECT_EQ(std::string(moveAssignmentOperator2.Data().begin(), - moveAssignmentOperator2.Data().end()), "hello"); -} - -/** - * @tc.name: ConstCharConstructorWithSize - * @tc.desc: - * @tc.type: ConstCharConstructorWithSize test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, ConstCharConstructorWithSize, TestSize.Level0) -{ - ZLOGI("ConstCharConstructorWithSize begin."); - Blob constCharConstructorWithSize("hello", 5); - EXPECT_EQ(std::string(constCharConstructorWithSize.Data().begin(), - constCharConstructorWithSize.Data().end()), "hello"); -} - -/** - * @tc.name: ConstCharConstructorWithNullTerminator - * @tc.desc: - * @tc.type: ConstCharConstructorWithNullTerminator test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, ConstCharConstructorWithNullTerminator, TestSize.Level0) -{ - ZLOGI("ConstCharConstructorWithNullTerminator begin."); - Blob blob("ConstCharConstructorWithNullTerminator"); - EXPECT_EQ(std::string(blob.Data().begin(), blob.Data().end()), "ConstCharConstructorWithNullTerminator"); -} - -/** - * @tc.name: StringConstructor - * @tc.desc: - * @tc.type: StringConstructor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, StringConstructor, TestSize.Level0) -{ - ZLOGI("StringConstructor begin."); - std::string str = "StringConstructor"; - Blob stringConstructor(str); - EXPECT_EQ(std::string(stringConstructor.Data().begin(), - stringConstructor.Data().end()), str); -} - -/** - * @tc.name: StringAssignmentOperator - * @tc.desc: - * @tc.type: StringAssignmentOperator test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, StringAssignmentOperator, TestSize.Level0) -{ - ZLOGI("StringAssignmentOperator begin."); - std::string str = "StringAssignmentOperator"; - Blob stringAssignmentOperator; - stringAssignmentOperator = str; - EXPECT_EQ(std::string(stringAssignmentOperator.Data().begin(), - stringAssignmentOperator.Data().end()), str); -} - -/** - * @tc.name: ConstCharAssignmentOperator - * @tc.desc: - * @tc.type: ConstCharAssignmentOperator test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, ConstCharAssignmentOperator, TestSize.Level0) -{ - ZLOGI("ConstCharAssignmentOperator begin."); - std::string str = "StringAssignmentOperator"; - Blob constCharAssignmentOperator; - constCharAssignmentOperator = str; - EXPECT_EQ(std::string(constCharAssignmentOperator.Data().begin(), - constCharAssignmentOperator.Data().end()), str); -} - -/** - * @tc.name: VectorConstructor - * @tc.desc: - * @tc.type: VectorConstructor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, VectorConstructor, TestSize.Level0) -{ - ZLOGI("VectorConstructor begin."); - std::vector vec = {'h', 'e', 'l', 'l', 'o'}; - Blob vectorConstructor(vec); - EXPECT_EQ(std::string(vectorConstructor.Data().begin(), - vectorConstructor.Data().end()), "hello"); -} - -/** - * @tc.name: MoveVectorConstructor - * @tc.desc: - * @tc.type: MoveVectorConstructor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, MoveVectorConstructor, TestSize.Level0) -{ - ZLOGI("MoveVectorConstructor begin."); - std::vector vec = {'h', 'e', 'l', 'l', 'o'}; - Blob moveVectorConstructor(std::move(vec)); - EXPECT_EQ(std::string(moveVectorConstructor.Data().begin(), - moveVectorConstructor.Data().end()), "hello"); - EXPECT_TRUE(vec.empty()); -} - -/** - * @tc.name: DataAccessor - * @tc.desc: - * @tc.type: DataAccessor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, DataAccessor, TestSize.Level0) -{ - ZLOGI("DataAccessor begin."); - Blob dataAccessor("hello", 5); - const std::vector& data = dataAccessor.Data(); - EXPECT_EQ(data[0], 'h'); - EXPECT_EQ(data[4], 'o'); -} - -/** - * @tc.name: SizeAccessor - * @tc.desc: - * @tc.type: SizeAccessor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, SizeAccessor, TestSize.Level0) -{ - ZLOGI("SizeAccessor begin."); - Blob sizeAccessor("hello", 5); - EXPECT_EQ(sizeAccessor.Size(), 5u); -} - -/** - * @tc.name: RawSizeAccessor - * @tc.desc: - * @tc.type: RawSizeAccessor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, RawSizeAccessor, TestSize.Level0) -{ - ZLOGI("RawSizeAccessor begin."); - Blob rawSizeAccessor("hello", 5); - EXPECT_EQ(rawSizeAccessor.RawSize(), 9); // sizeof(int) + 5 -} - -/** - * @tc.name: EmptyAccessor - * @tc.desc: - * @tc.type: EmptyAccessor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, EmptyAccessor, TestSize.Level0) -{ - ZLOGI("EmptyAccessor begin."); - Blob emptyAccessor; - EXPECT_TRUE(emptyAccessor.Empty()); - Blob emptyAccessor2("hello"); - EXPECT_FALSE(emptyAccessor2.Empty()); -} - -/** - * @tc.name: ElementAccessOperator - * @tc.desc: - * @tc.type: ElementAccessOperator test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, ElementAccessOperator, TestSize.Level0) -{ - ZLOGI("ElementAccessOperator begin."); - Blob elementAccessOperator("hello", 5); - EXPECT_EQ(elementAccessOperator[0], 'h'); - EXPECT_EQ(elementAccessOperator[4], 'o'); - EXPECT_EQ(elementAccessOperator[5], 0); -} - -/** - * @tc.name: EqualityOperator - * @tc.desc: - * @tc.type: EqualityOperator test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, EqualityOperator, TestSize.Level0) -{ - ZLOGI("EqualityOperator begin."); - Blob equalityOperator1("hello", 5); - Blob equalityOperator2("hello", 5); - EXPECT_TRUE(equalityOperator1 == equalityOperator2); - Blob equalityOperator3("world", 5); - EXPECT_FALSE(equalityOperator1 == equalityOperator3); -} - -/** - * @tc.name: Clear - * @tc.desc: - * @tc.type: Clear test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, Clear, TestSize.Level0) -{ - ZLOGI("Clear begin."); - Blob blobClear("hello", 5); - blobClear.Clear(); - EXPECT_TRUE(blobClear.Empty()); -} - -/** - * @tc.name: ToString - * @tc.desc: - * @tc.type: ToString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, ToString, TestSize.Level0) -{ - ZLOGI("ToString begin."); - Blob blobToString("hello", 5); - EXPECT_EQ(blobToString.ToString(), "hello"); -} - -/** - * @tc.name: Compare - * @tc.desc: - * @tc.type: Compare test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, Compare, TestSize.Level0) -{ - ZLOGI("Compare begin."); - Blob blobCompare1("abc", 3); - Blob blobCompare2("abcd", 4); - Blob blobCompare3("abc", 3); - EXPECT_LT(blobCompare1.Compare(blobCompare2), 0); - EXPECT_EQ(blobCompare1.Compare(blobCompare3), 0); - EXPECT_GT(blobCompare2.Compare(blobCompare1), 0); -} - -/** - * @tc.name: StartsWith - * @tc.desc: - * @tc.type: StartsWith test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, StartsWith, TestSize.Level0) -{ - ZLOGI("StartsWith begin."); - Blob blobStartsWith1("abcdef", 6); - Blob blobStartsWith2("abc", 3); - Blob blobStartsWith3("abcd", 4); - Blob blobStartsWith4("xyz", 3); - EXPECT_TRUE(blobStartsWith1.StartsWith(blobStartsWith2)); - EXPECT_TRUE(blobStartsWith1.StartsWith(blobStartsWith3)); - EXPECT_FALSE(blobStartsWith1.StartsWith(blobStartsWith4)); -} - -/** - * @tc.name: WriteToBuffer - * @tc.desc: - * @tc.type: WriteToBuffer test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, WriteToBuffer, TestSize.Level0) -{ - ZLOGI("WriteToBuffer begin."); - Blob blobWriteToBuffer("hello", 5); - uint8_t buffer[100]; - uint8_t* cursorPtr = buffer; - int bufferLeftSize = sizeof(buffer); - EXPECT_TRUE(blobWriteToBuffer.WriteToBuffer(cursorPtr, bufferLeftSize)); - EXPECT_EQ(*reinterpret_cast(buffer), 5); - EXPECT_EQ(std::string(reinterpret_cast(buffer + sizeof(int)), 5), "hello"); - EXPECT_EQ(bufferLeftSize, sizeof(buffer) - sizeof(int) - 5); -} - -/** - * @tc.name: ReadFromBuffer - * @tc.desc: - * @tc.type: ReadFromBuffer test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, ReadFromBuffer, TestSize.Level0) -{ - ZLOGI("ReadFromBuffer begin."); - uint8_t buffer[100]; - int blobSize = 5; - *reinterpret_cast(buffer) = blobSize; - std::string str = "hello"; - strncpy_s(reinterpret_cast(buffer + sizeof(int)), blobSize, str, strlen(str)); - const uint8_t* cursorPtr = buffer; - int bufferLeftSize = sizeof(buffer); - Blob blob; - EXPECT_TRUE(blob.ReadFromBuffer(cursorPtr, bufferLeftSize)); - EXPECT_EQ(std::string(blob.Data().begin(), blob.Data().end()), "hello"); - EXPECT_EQ(bufferLeftSize, sizeof(buffer) - sizeof(int) - blobSize); -} - -/** - * @tc.name: ChangeNotificationVirtualTest001 - * @tc.desc: - * @tc.type: test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(ChangeNotificationVirtualTest, ChangeNotificationVirtualTest001, TestSize.Level0) -{ - ZLOGI("ChangeNotificationVirtualTest001 begin."); - std::vector insertEntries = {{"key1", "value1"}, {"key2", "value2"}}; - std::vector updateEntries = {{"key3", "newValue3"}}; - std::vector deleteEntries = {{"key4", ""}}; - std::string deviceId = "device123"; - bool isClear = false; - - OHOS::DistributedKv::ChangeNotification cn(std::move(insertEntries), - std::move(updateEntries), std::move(deleteEntries), deviceId, isClear); - - EXPECT_TRUE(cn.GetInsertEntries().size() == 2); - EXPECT_TRUE(cn.GetUpdateEntries().size() == 1); - EXPECT_TRUE(cn.GetDeleteEntries().size() == 1); - EXPECT_TRUE(cn.GetDeviceId() == deviceId); - EXPECT_TRUE(!cn.IsClear()); -} - -/** - * @tc.name: ChangeNotificationVirtualTest002 - * @tc.desc: - * @tc.type: test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(ChangeNotificationVirtualTest, ChangeNotificationVirtualTest002, TestSize.Level0) -{ - ZLOGI("ChangeNotificationVirtualTest002 begin."); - std::vector insertEntries; - std::vector updateEntries; - std::vector deleteEntries; - std::string deviceId = "device456"; - bool isClear = true; - - OHOS::DistributedKv::ChangeNotification cn(std::move(insertEntries), - std::move(updateEntries), std::move(deleteEntries), deviceId, isClear); - - EXPECT_TRUE(cn.GetInsertEntries().empty()); - EXPECT_TRUE(cn.GetUpdateEntries().empty()); - EXPECT_TRUE(cn.GetDeleteEntries().empty()); - EXPECT_TRUE(cn.GetDeviceId() == deviceId); - EXPECT_TRUE(cn.IsClear()); -} - -/** - * @tc.name: ChangeNotificationVirtualTest003 - * @tc.desc: - * @tc.type: test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(ChangeNotificationVirtualTest, ChangeNotificationVirtualTest003, TestSize.Level0) -{ - ZLOGI("ChangeNotificationVirtualTest003 begin."); - std::vector insertEntries; - std::vector updateEntries = {{"keyUpdated", "newValue"}}; - std::vector deleteEntries; - std::string deviceId = "device789"; - bool isClear = false; - - OHOS::DistributedKv::ChangeNotification cn(std::move(insertEntries), - std::move(updateEntries), std::move(deleteEntries), deviceId, isClear); - - EXPECT_TRUE(cn.GetInsertEntries().empty()); - EXPECT_TRUE(cn.GetUpdateEntries().size() == 1); - EXPECT_TRUE(cn.GetDeleteEntries().empty()); - EXPECT_TRUE(cn.GetDeviceId() == deviceId); - EXPECT_TRUE(!cn.IsClear()); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/data_query_virtual_test.cpp b/kv_store/databaseutils/test/data_query_virtual_test.cpp deleted file mode 100644 index 5e20203e76a14d896a7a1c102c80b644e7c68736..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/data_query_virtual_test.cpp +++ /dev/null @@ -1,1184 +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. - */ -#define LOG_TAG "DataQueryVirtualTest" - -#include "data_query.h" -#include "kv_types_util.h" -#include -#include "types.h" -#include -#include -#include - -using namespace OHOS::DistributedKv; -using namespace testing; -using namespace testing::ext; -namespace OHOS::Test { -class DataQueryVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void DataQueryVirtualTest::SetUpTestCase(void) -{} - -void DataQueryVirtualTest::TearDownTestCase(void) -{} - -void DataQueryVirtualTest::SetUp(void) -{} - -void DataQueryVirtualTest::TearDown(void) -{} - -class MockQuery { -public: - MOCK_METHOD2(Range, void(const std::vector&, const std::vector&)); - MOCK_METHOD1(IsNull, void(const std::string&)); - MOCK_METHOD1(IsNotNull, void(const std::string&)); -}; - -/** - * @tc.name: Reset - * @tc.desc: - * @tc.type: Reset test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, Reset, TestSize.Level0) -{ - ZLOGI("ResetTest begin."); - DataQuery queryReset; - queryReset.EqualTo("field1", 123); - queryReset.Reset(); - EXPECT_EQ(queryReset.str_, ""); - EXPECT_FALSE(queryReset.hasKeys_); - EXPECT_FALSE(queryReset.hasPrefix_); - EXPECT_EQ(queryReset.deviceId_, ""); - EXPECT_EQ(queryReset.prefix_, ""); -} - -/** - * @tc.name: EqualToInteger - * @tc.desc: - * @tc.type: EqualToInteger test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, EqualToInteger, TestSize.Level0) -{ - ZLOGI("EqualToInteger begin."); - DataQuery queryEqualToInteger; - queryEqualToInteger.EqualTo("field1", 123); - EXPECT_EQ(queryEqualToInteger.str_, - std::string(DataQuery::EQUAL_TO) + " " + DataQuery::TYPE_INTEGER + " field1 123"); -} - -/** - * @tc.name: EqualToLong - * @tc.desc: - * @tc.type: EqualToLong test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, EqualToLong, TestSize.Level0) -{ - ZLOGI("EqualToLong begin."); - DataQuery queryEqualToLong; - queryEqualToLong.EqualTo("field1", 123456789012345LL); - EXPECT_EQ(queryEqualToLong.str_, - std::string(DataQuery::EQUAL_TO) + " " + DataQuery::TYPE_LONG + " field1 123456789012345"); -} - -/** - * @tc.name: EqualToDouble - * @tc.desc: - * @tc.type: EqualToDouble test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, EqualToDouble, TestSize.Level0) -{ - ZLOGI("EqualToDouble begin."); - DataQuery queryEqualToDouble; - queryEqualToDouble.EqualTo("field1", 123.45); - EXPECT_EQ(queryEqualToDouble.str_, - std::string(DataQuery::EQUAL_TO) + " " + DataQuery::TYPE_DOUBLE + " field1 123.45"); -} - -/** - * @tc.name: EqualToString - * @tc.desc: - * @tc.type: EqualToString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, EqualToString, TestSize.Level0) -{ - ZLOGI("EqualToString begin."); - DataQuery queryEqualToString; - queryEqualToString.EqualTo("field1", "testValue"); - EXPECT_EQ(queryEqualToString.str_, - std::string(DataQuery::EQUAL_TO) + " " + DataQuery::TYPE_STRING + " field1 testValue"); -} - -/** - * @tc.name: EqualToBooleanTrue - * @tc.desc: - * @tc.type: EqualToBooleanTrue test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, EqualToBooleanTrue, TestSize.Level0) -{ - ZLOGI("EqualToBooleanTrue begin."); - DataQuery queryEqualToBooleanTrue; - queryEqualToBooleanTrue.EqualTo("field1", true); - EXPECT_EQ(queryEqualToBooleanTrue.str_, - std::string(DataQuery::EQUAL_TO) + " " + DataQuery::TYPE_BOOLEAN + " field1 true"); -} - -/** - * @tc.name: EqualToBooleanFalse - * @tc.desc: - * @tc.type: EqualToBooleanFalse test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, EqualToBooleanFalse, TestSize.Level0) -{ - ZLOGI("EqualToBooleanFalse begin."); - DataQuery queryEqualToBooleanFalse; - queryEqualToBooleanFalse.EqualTo("field1", false); - EXPECT_EQ(queryEqualToBooleanFalse.str_, - std::string(DataQuery::EQUAL_TO) + " " + DataQuery::TYPE_BOOLEAN + " field1 false"); -} - -/** - * @tc.name: NotEqualToInteger - * @tc.desc: - * @tc.type: NotEqualToInteger test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotEqualToInteger, TestSize.Level0) -{ - ZLOGI("NotEqualToInteger begin."); - DataQuery queryNotEqualToInteger; - queryNotEqualToInteger.NotEqualTo("field1", 123); - EXPECT_EQ(queryNotEqualToInteger.str_, - std::string(DataQuery::NOT_EQUAL_TO) + " " + DataQuery::TYPE_INTEGER + " field1 123"); -} - -/** - * @tc.name: NotEqualToLong - * @tc.desc: - * @tc.type: NotEqualToLong test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotEqualToLong, TestSize.Level0) -{ - ZLOGI("NotEqualToLong begin."); - DataQuery queryNotEqualToLong; - queryNotEqualToLong.NotEqualTo("field1", 123456789012345LL); - EXPECT_EQ(queryNotEqualToLong.str_, - std::string(DataQuery::NOT_EQUAL_TO) + " " + DataQuery::TYPE_LONG + " field1 123456789012345"); -} - -/** - * @tc.name: NotEqualToDouble - * @tc.desc: - * @tc.type: NotEqualToDouble test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotEqualToDouble, TestSize.Level0) -{ - ZLOGI("NotEqualToDouble begin."); - DataQuery queryNotEqualToDouble; - queryNotEqualToDouble.NotEqualTo("field1", 123.45); - EXPECT_EQ(queryNotEqualToDouble.str_, - std::string(DataQuery::NOT_EQUAL_TO) + " " + DataQuery::TYPE_DOUBLE + " field1 123.45"); -} - -/** - * @tc.name: NotEqualToString - * @tc.desc: - * @tc.type: NotEqualToString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotEqualToString, TestSize.Level0) -{ - ZLOGI("NotEqualToString begin."); - DataQuery queryNotEqualToString; - queryNotEqualToString.NotEqualTo("field1", "testValue"); - EXPECT_EQ(queryNotEqualToString.str_, - std::string(DataQuery::NOT_EQUAL_TO) + " " + DataQuery::TYPE_STRING + " field1 testValue"); -} - -/** - * @tc.name: NotEqualToBooleanTrue - * @tc.desc: - * @tc.type: NotEqualToBooleanTrue test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotEqualToBooleanTrue, TestSize.Level0) -{ - ZLOGI("NotEqualToBooleanTrue begin."); - DataQuery queryNotEqualToBooleanTrue; - queryNotEqualToBooleanTrue.NotEqualTo("field1", true); - EXPECT_EQ(queryNotEqualToBooleanTrue.str_, - std::string(DataQuery::NOT_EQUAL_TO) + " " + DataQuery::TYPE_BOOLEAN + " field1 true"); -} - -/** - * @tc.name: NotEqualToBooleanFalse - * @tc.desc: - * @tc.type: NotEqualToBooleanFalse test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotEqualToBooleanFalse, TestSize.Level0) -{ - ZLOGI("NotEqualToBooleanFalse begin."); - DataQuery queryNotEqualToBooleanFalse; - queryNotEqualToBooleanFalse.NotEqualTo("field1", false); - EXPECT_EQ(queryNotEqualToBooleanFalse.str_, - std::string(DataQuery::NOT_EQUAL_TO) + " " + DataQuery::TYPE_BOOLEAN + " field1 false"); -} - -/** - * @tc.name: GreaterThanInteger - * @tc.desc: - * @tc.type: GreaterThanInteger test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GreaterThanInteger, TestSize.Level0) -{ - ZLOGI("GreaterThanInteger begin."); - DataQuery queryNotEqualToBooleanFalse; - queryGreaterThanInteger.GreaterThan("field1", 123); - EXPECT_EQ(queryGreaterThanInteger.str_, - std::string(DataQuery::GREATER_THAN) + " " + DataQuery::TYPE_INTEGER + " field1 123"); -} - -/** - * @tc.name: GreaterThanLong - * @tc.desc: - * @tc.type: GreaterThanLong test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GreaterThanLong, TestSize.Level0) -{ - ZLOGI("GreaterThanLong begin."); - DataQuery queryGreaterThanLong; - queryGreaterThanLong.GreaterThan("field1", 123456789012345LL); - EXPECT_EQ(queryGreaterThanLong.str_, - std::string(DataQuery::GREATER_THAN) + " " + DataQuery::TYPE_LONG + " field1 123456789012345"); -} - -/** - * @tc.name: GreaterThanDouble - * @tc.desc: - * @tc.type: GreaterThanDouble test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GreaterThanDouble, TestSize.Level0) -{ - ZLOGI("GreaterThanDouble begin."); - DataQuery queryGreaterThanDouble; - queryGreaterThanDouble.GreaterThan("field1", 123.45); - EXPECT_EQ(queryGreaterThanDouble.str_, - std::string(DataQuery::GREATER_THAN) + " " + DataQuery::TYPE_DOUBLE + " field1 123.45"); -} - -/** - * @tc.name: GreaterThanString - * @tc.desc: - * @tc.type: GreaterThanString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GreaterThanString, TestSize.Level0) -{ - ZLOGI("GreaterThanString begin."); - DataQuery queryGreaterThanString; - queryGreaterThanString.GreaterThan("field1", "testValue"); - EXPECT_EQ(queryGreaterThanString.str_, - std::string(DataQuery::GREATER_THAN) + " " + DataQuery::TYPE_STRING + " field1 testValue"); -} - -/** - * @tc.name: LessThanInteger - * @tc.desc: - * @tc.type: LessThanInteger test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, LessThanInteger, TestSize.Level0) -{ - ZLOGI("LessThanInteger begin."); - DataQuery queryLessThanInteger; - queryLessThanInteger.LessThan("field1", 123); - EXPECT_EQ(queryLessThanInteger.str_, - std::string(DataQuery::LESS_THAN) + " " + DataQuery::TYPE_INTEGER + " field1 123"); -} - -/** - * @tc.name: LessThanLong - * @tc.desc: - * @tc.type: LessThanLong test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, LessThanLong, TestSize.Level0) -{ - ZLOGI("GreaterThanLong begin."); - DataQuery queryLessThanLong; - queryLessThanLong.LessThan("field1", 123456789012345LL); - EXPECT_EQ(queryLessThanLong.str_, - std::string(DataQuery::LESS_THAN) + " " + DataQuery::TYPE_LONG + " field1 123456789012345"); -} - -/** - * @tc.name: LessThanDouble - * @tc.desc: - * @tc.type: LessThanDouble test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, LessThanDouble, TestSize.Level0) -{ - ZLOGI("LessThanDouble begin."); - DataQuery queryLessThanDouble; - queryLessThanDouble.LessThan("field1", 123.45); - EXPECT_EQ(queryLessThanDouble.str_, - std::string(DataQuery::LESS_THAN) + " " + DataQuery::TYPE_DOUBLE + " field1 123.45"); -} - -/** - * @tc.name: LessThanString - * @tc.desc: - * @tc.type: LessThanString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, LessThanString, TestSize.Level0) -{ - ZLOGI("LessThanString begin."); - DataQuery queryLessThanString; - queryLessThanString.LessThan("field1", "testValue"); - EXPECT_EQ(queryLessThanString.str_, - std::string(DataQuery::LESS_THAN) + " " + DataQuery::TYPE_STRING + " field1 testValue"); -} - -/** - * @tc.name: GreaterThanOrEqualToInteger - * @tc.desc: - * @tc.type: GreaterThanOrEqualToInteger test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GreaterThanOrEqualToInteger, TestSize.Level0) -{ - ZLOGI("LessThanInteger begin."); - DataQuery queryGreaterThanOrEqualToInteger; - queryGreaterThanOrEqualToInteger.GreaterThanOrEqualTo("field1", 123); - EXPECT_EQ(queryGreaterThanOrEqualToInteger.str_, - std::string(DataQuery::GREATER_THAN_OR_EQUAL_TO) + " " + DataQuery::TYPE_INTEGER + " field1 123"); -} - -/** - * @tc.name: GreaterThanOrEqualToLong - * @tc.desc: - * @tc.type: GreaterThanOrEqualToLong test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GreaterThanOrEqualToLong, TestSize.Level0) -{ - ZLOGI("GreaterThanLong begin."); - DataQuery queryGreaterThanOrEqualToLong; - queryGreaterThanOrEqualToLong.GreaterThanOrEqualTo("field1", 123456789012345LL); - EXPECT_EQ(queryGreaterThanOrEqualToLong.str_, - std::string(DataQuery::GREATER_THAN_OR_EQUAL_TO) + " " + DataQuery::TYPE_LONG + " field1 123456789012345"); -} - -/** - * @tc.name: GreaterThanOrEqualToDouble - * @tc.desc: - * @tc.type: GreaterThanOrEqualToDouble test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GreaterThanOrEqualToDouble, TestSize.Level0) -{ - ZLOGI("LessThanDouble begin."); - DataQuery queryGreaterThanOrEqualToDouble; - queryGreaterThanOrEqualToDouble.GreaterThanOrEqualTo("field1", 123.45); - EXPECT_EQ(queryGreaterThanOrEqualToDouble.str_, - std::string(DataQuery::GREATER_THAN_OR_EQUAL_TO) + " " + DataQuery::TYPE_DOUBLE + " field1 123.45"); -} - -/** - * @tc.name: GreaterThanOrEqualToString - * @tc.desc: - * @tc.type: GreaterThanOrEqualToString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GreaterThanOrEqualToString, TestSize.Level0) -{ - ZLOGI("LessThanString begin."); - DataQuery queryGreaterThanOrEqualToString; - queryGreaterThanOrEqualToString.GreaterThanOrEqualTo("field1", "testValue"); - EXPECT_EQ(queryGreaterThanOrEqualToString.str_, - std::string(DataQuery::GREATER_THAN_OR_EQUAL_TO) + " " + DataQuery::TYPE_STRING + " field1 testValue"); -} - -/** - * @tc.name: LessThanOrEqualToInteger - * @tc.desc: - * @tc.type: LessThanOrEqualToInteger test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, LessThanOrEqualToInteger, TestSize.Level0) -{ - ZLOGI("LessThanOrEqualToInteger begin."); - DataQuery queryLessThanOrEqualToInteger; - queryLessThanOrEqualToInteger.LessThanOrEqualTo("field1", 123); - EXPECT_EQ(queryLessThanOrEqualToInteger.str_, - std::string(DataQuery::LESS_THAN_OR_EQUAL_TO) + " " + DataQuery::TYPE_INTEGER + " field1 123"); -} - -/** - * @tc.name: LessThanOrEqualToLong - * @tc.desc: - * @tc.type: LessThanOrEqualToLong test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, LessThanOrEqualToLong, TestSize.Level0) -{ - ZLOGI("LessThanOrEqualToLong begin."); - DataQuery queryLessThanOrEqualToLong; - queryLessThanOrEqualToLong.LessThanOrEqualTo("field1", 123456789012345LL); - EXPECT_EQ(queryLessThanOrEqualToLong.str_, - std::string(DataQuery::LESS_THAN_OR_EQUAL_TO) + " " + DataQuery::TYPE_LONG + " field1 123456789012345"); -} - -/** - * @tc.name: LessThanOrEqualToDouble - * @tc.desc: - * @tc.type: LessThanOrEqualToDouble test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, LessThanOrEqualToDouble, TestSize.Level0) -{ - ZLOGI("LessThanOrEqualToDouble begin."); - DataQuery queryLessThanOrEqualToDouble; - queryLessThanOrEqualToDouble.LessThanOrEqualTo("field1", 123.45); - EXPECT_EQ(queryLessThanOrEqualToDouble.str_, - std::string(DataQuery::LESS_THAN_OR_EQUAL_TO) + " " + DataQuery::TYPE_DOUBLE + " field1 123.45"); -} - -/** - * @tc.name: LessThanOrEqualToString - * @tc.desc: - * @tc.type: LessThanOrEqualToString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, LessThanOrEqualToString, TestSize.Level0) -{ - ZLOGI("LessThanOrEqualToString begin."); - DataQuery queryLessThanOrEqualToString; - queryLessThanOrEqualToString.LessThanOrEqualTo("field1", "testValue"); - EXPECT_EQ(queryLessThanOrEqualToString.str_, - std::string(DataQuery::LESS_THAN_OR_EQUAL_TO) + " " + DataQuery::TYPE_STRING + " field1 testValue"); -} - -/** - * @tc.name: Between_ValidInputs_CallsRange - * @tc.desc: - * @tc.type: Between_ValidInputs_CallsRange test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, Between_ValidInputs_CallsRange, TestSize.Level0) -{ - ZLOGI("Between_ValidInputs_CallsRange begin."); - MockQuery mockQuery; - DataQuery queryBetween(&mockQuery); - - EXPECT_CALL(mockQuery, Range(ElementsAre('a', 'b'), ElementsAre('c', 'd'))); - - queryBetween.Between("ab", "cd"); -} - -/** - * @tc.name: IsNull_ValidField_UpdatesStringAndCallsIsNull - * @tc.desc: - * @tc.type: IsNull_ValidField_UpdatesStringAndCallsIsNull test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, IsNull_ValidField_UpdatesStringAndCallsIsNull, TestSize.Level0) -{ - ZLOGI("IsNull_ValidField_UpdatesStringAndCallsIsNull begin."); - MockQuery mockQuery; - DataQuery queryIsNull(&mockQuery); - - EXPECT_CALL(mockQuery, IsNull("field")); - - queryIsNull.IsNull("field"); -} - -/** - * @tc.name: IsNull_InvalidField_DoesNotUpdateStringOrCallIsNull - * @tc.desc: - * @tc.type: IsNull_InvalidField_DoesNotUpdateStringOrCallIsNull test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, IsNull_InvalidField_DoesNotUpdateStringOrCallIsNull, TestSize.Level0) -{ - ZLOGI("IsNull_InvalidField_DoesNotUpdateStringOrCallIsNull begin."); - MockQuery mockQuery; - DataQuery queryIsNull(&mockQuery); - - EXPECT_CALL(mockQuery, IsNull(_)).Times(0); - - queryIsNull.IsNull("invalid field"); -} - -/** - * @tc.name: IsNotNull_ValidField_UpdatesStringAndCallsIsNotNull - * @tc.desc: - * @tc.type: IsNotNull_ValidField_UpdatesStringAndCallsIsNotNull test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, IsNotNull_ValidField_UpdatesStringAndCallsIsNotNull, TestSize.Level0) -{ - ZLOGI("IsNotNull_ValidField_UpdatesStringAndCallsIsNotNull begin."); - MockQuery mockQuery; - DataQuery queryIsNotNull(&mockQuery); - - EXPECT_CALL(mockQuery, IsNotNull("field")); - - queryIsNotNull.IsNotNull("field"); -} - -/** - * @tc.name: IsNotNull_InvalidField_DoesNotUpdateStringOrCallIsNotNull - * @tc.desc: - * @tc.type: IsNotNull_InvalidField_DoesNotUpdateStringOrCallIsNotNull test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, IsNotNull_InvalidField_DoesNotUpdateStringOrCallIsNotNull, TestSize.Level0) -{ - ZLOGI("IsNotNull_InvalidField_DoesNotUpdateStringOrCallIsNotNull begin."); - MockQuery mockQuery; - DataQuery queryIsNotNull(&mockQuery); - - EXPECT_CALL(mockQuery, IsNotNull(_)).Times(0); - - query.IsNotNull("invalid field"); -} - -/** - * @tc.name: InInteger - * @tc.desc: - * @tc.type: InInteger test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, InInteger, TestSize.Level0) -{ - ZLOGI("InInteger begin."); - DataQuery queryInInteger; - queryInInteger.In("field1", 123); - EXPECT_EQ(queryInInteger.str_, - std::string(DataQuery::IN) + " " + DataQuery::TYPE_INTEGER + " field1 123"); -} - -/** - * @tc.name: InLong - * @tc.desc: - * @tc.type: InLong test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, InLong, TestSize.Level0) -{ - ZLOGI("InLong begin."); - DataQuery queryInLong; - queryInLong.In("field1", 123456789012345LL); - EXPECT_EQ(queryInLong.str_, - std::string(DataQuery::IN) + " " + DataQuery::TYPE_LONG + " field1 123456789012345"); -} - -/** - * @tc.name: InDouble - * @tc.desc: - * @tc.type: InDouble test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, InDouble, TestSize.Level0) -{ - ZLOGI("InDouble begin."); - DataQuery queryInDouble; - queryInDouble.In("field1", 123.45); - EXPECT_EQ(queryInDouble.str_, - std::string(DataQuery::IN) + " " + DataQuery::TYPE_DOUBLE + " field1 123.45"); -} - -/** - * @tc.name: InString - * @tc.desc: - * @tc.type: InString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, InString, TestSize.Level0) -{ - ZLOGI("InString begin."); - DataQuery queryInString; - queryInString.In("field1", "testValue"); - EXPECT_EQ(queryInString.str_, - std::string(DataQuery::IN) + " " + DataQuery::TYPE_STRING + " field1 testValue"); -} - -/** - * @tc.name: NotInInteger - * @tc.desc: - * @tc.type: NotInInteger test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotInInteger, TestSize.Level0) -{ - ZLOGI("NotInInteger begin."); - DataQuery queryNotInInteger; - queryNotInInteger.NotIn("field1", 123); - EXPECT_EQ(queryNotInInteger.str_, - std::string(DataQuery::NOT_IN) + " " + DataQuery::TYPE_INTEGER + " field1 123"); -} - -/** - * @tc.name: NotInLong - * @tc.desc: - * @tc.type: NotInLong test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotInLong, TestSize.Level0) -{ - ZLOGI("NotInLong begin."); - DataQuery queryNotInLong; - queryNotInLong.NotIn("field1", 123456789012345LL); - EXPECT_EQ(queryNotInLong.str_, - std::string(DataQuery::NOT_IN) + " " + DataQuery::TYPE_LONG + " field1 123456789012345"); -} - -/** - * @tc.name: NotInDouble - * @tc.desc: - * @tc.type: NotInDouble test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotInDouble, TestSize.Level0) -{ - ZLOGI("InDouble begin."); - DataQuery queryNotInDouble; - queryNotInDouble.NotIn("field1", 123.45); - EXPECT_EQ(queryNotInDouble.str_, - std::string(DataQuery::NOT_IN) + " " + DataQuery::TYPE_DOUBLE + " field1 123.45"); -} - -/** - * @tc.name: NotInString - * @tc.desc: - * @tc.type: NotInString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotInString, TestSize.Level0) -{ - ZLOGI("NotInString begin."); - DataQuery queryNotInString; - queryNotInString.NotIn("field1", "testValue"); - EXPECT_EQ(queryNotInString.str_, - std::string(DataQuery::NOT_IN) + " " + DataQuery::TYPE_STRING + " field1 testValue"); -} - -/** - * @tc.name: Like_ValidFieldAndValue_AppendsToQuery - * @tc.desc: - * @tc.type: Like_ValidFieldAndValue_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, Like_ValidFieldAndValue_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("Like_ValidFieldAndValue_AppendsToQuery begin."); - std::shared_ptr queryLikeMock = std::make_shared(); - DataQuery queryLike; - EXPECT_CALL(*queryLikeMock, Like("field", "value")).Times(1); - queryLike.Like("field", "value"); - EXPECT_EQ(queryLike.ToString(), std::string(DataQuery::LIKE) + " field value"); -} - -/** - * @tc.name: Unlike_ValidFieldAndValue_AppendsToQuery - * @tc.desc: - * @tc.type: Unlike_ValidFieldAndValue_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, Unlike_ValidFieldAndValue_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("Unlike_ValidFieldAndValue_AppendsToQuery begin."); - std::shared_ptr queryUnlikeMock = std::make_shared(); - DataQuery queryUnlike; - EXPECT_CALL(*queryUnlikeMock, NotLike("field", "value")).Times(1); - queryUnlike.Unlike("field", "value"); - EXPECT_EQ(queryUnlike.ToString(), std::string(DataQuery::NOT_LIKE) + " field1 testValue"); -} - -/** - * @tc.name: And_AppendsAndToQuery - * @tc.desc: - * @tc.type: And_AppendsAndToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, And_AppendsAndToQuery, TestSize.Level0) -{ - ZLOGI("And_AppendsAndToQuery begin."); - std::shared_ptr queryAndMock = std::make_shared(); - DataQuery queryAnd; - EXPECT_CALL(*queryAndMock, And()).Times(1); - queryAnd.And(); - EXPECT_EQ(queryAnd.ToString(), " AND"); -} - -/** - * @tc.name: Or_AppendsOrToQuery - * @tc.desc: - * @tc.type: Or_AppendsOrToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, Or_AppendsOrToQuery, TestSize.Level0) -{ - ZLOGI("Or_AppendsOrToQuery begin."); - std::shared_ptr queryOrMock = std::make_shared(); - DataQuery queryOr; - EXPECT_CALL(*queryOrMock, Or()).Times(1); - queryOr.Or(); - EXPECT_EQ(queryOr.ToString(), " OR"); -} - -/** - * @tc.name: OrderByAsc_ValidField_AppendsToQuery - * @tc.desc: - * @tc.type: OrderByAsc_ValidField_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, OrderByAsc_ValidField_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("OrderByAsc_ValidField_AppendsToQuery begin."); - std::shared_ptr queryOrderByAscMock = std::make_shared(); - DataQuery queryOrderByAsc; - EXPECT_CALL(*queryOrderByAscMock, OrderBy("field")).Times(1); - queryOrderByAsc.OrderByAsc("field"); - EXPECT_EQ(queryOrderByAsc.ToString(), " ORDER BY ASC field"); -} - -/** - * @tc.name: OrderByDesc_ValidField_AppendsToQuery - * @tc.desc: - * @tc.type: OrderByDesc_ValidField_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, OrderByDesc_ValidField_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("OrderByDesc_ValidField_AppendsToQuery begin."); - std::shared_ptr queryOrderByDescMock = std::make_shared(); - DataQuery queryOrderByDesc; - EXPECT_CALL(*queryOrderByDescMock, OrderBy("field", false)).Times(1); - queryOrderByDesc.OrderByDesc("field"); - EXPECT_EQ(queryOrderByDesc.ToString(), " ORDER BY DESC field"); -} - -/** - * @tc.name: OrderByWriteTime_Ascending_AppendsToQuery - * @tc.desc: - * @tc.type: OrderByWriteTime_Ascending_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, OrderByWriteTime_Ascending_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("OrderByWriteTime_Ascending_AppendsToQuery begin."); - std::shared_ptr queryOrderByWriteTimeMock = std::make_shared(); - DataQuery queryOrderByWriteTime; - EXPECT_CALL(*queryOrderByWriteTimeMock, OrderByWriteTime(true)).Times(1); - queryOrderByWriteTime.OrderByWriteTime(true); - EXPECT_EQ(queryOrderByWriteTime.ToString(), " ORDER BY WRITE_TIME ASC"); -} - -/** - * @tc.name: OrderByWriteTime_Descending_AppendsToQuery - * @tc.desc: - * @tc.type: OrderByWriteTime_Descending_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, OrderByWriteTime_Descending_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("OrderByWriteTime_Descending_AppendsToQuery begin."); - std::shared_ptr queryOrderByWriteTimeMock = std::make_shared(); - DataQuery queryOrderByWriteTime; - EXPECT_CALL(*queryMock, OrderByWriteTime(false)).Times(1); - queryOrderByWriteTime.OrderByWriteTime(false); - EXPECT_EQ(queryOrderByWriteTime.ToString(), " ORDER BY WRITE_TIME DESC"); -} - -/** - * @tc.name: Limit_ValidNumberAndOffset_AppendsToQuery - * @tc.desc: - * @tc.type: Limit_ValidNumberAndOffset_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, Limit_ValidNumberAndOffset_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("Limit_ValidNumberAndOffset_AppendsToQuery begin."); - std::shared_ptr queryLimitMock = std::make_shared(); - DataQuery queryLimit; - EXPECT_CALL(*queryLimitMock, Limit(10, 0)).Times(1); - queryLimit.Limit(10, 0); - EXPECT_EQ(queryLimit.ToString(), " LIMIT 10 0"); -} - -/** - * @tc.name: BeginGroup_AppendsBeginGroupToQuery - * @tc.desc: - * @tc.type: BeginGroup_AppendsBeginGroupToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, BeginGroup_AppendsBeginGroupToQuery, TestSize.Level0) -{ - ZLOGI("BeginGroup_AppendsBeginGroupToQuery begin."); - std::shared_ptr queryBeginGroupMock = std::make_shared(); - DataQuery queryBeginGroup; - EXPECT_CALL(*queryBeginGroupMock, BeginGroup()).Times(1); - queryBeginGroup.BeginGroup(); - EXPECT_EQ(queryBeginGroup.ToString(), " ("); -} - -/** - * @tc.name: EndGroup_AppendsEndGroupToQuery - * @tc.desc: - * @tc.type: EndGroup_AppendsEndGroupToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, EndGroup_AppendsEndGroupToQuery, TestSize.Level0) -{ - ZLOGI("EndGroup_AppendsEndGroupToQuery begin."); - std::shared_ptr queryEndGroupMock = std::make_shared(); - DataQuery queryEndGroup; - EXPECT_CALL(*queryEndGroupMock, EndGroup()).Times(1); - queryEndGroup.EndGroup(); - EXPECT_EQ(queryEndGroup.ToString(), " )"); -} - -/** - * @tc.name: KeyPrefix_ValidPrefix_AppendsToQuery - * @tc.desc: - * @tc.type: KeyPrefix_ValidPrefix_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, KeyPrefix_ValidPrefix_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("KeyPrefix_ValidPrefix_AppendsToQuery begin."); - std::shared_ptr queryKeyPrefixMock = std::make_shared(); - DataQuery queryKeyPrefix; - EXPECT_CALL(*queryKeyPrefixMock, KeyPrefix("prefix")).Times(1); - queryKeyPrefix.KeyPrefix("prefix"); - EXPECT_EQ(queryKeyPrefix.ToString(), " KEY_PREFIX prefix"); -} - -/** - * @tc.name: DeviceId_ValidDeviceId_AppendsToQuery - * @tc.desc: - * @tc.type: DeviceId_ValidDeviceId_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, DeviceId_ValidDeviceId_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("DeviceId_ValidDeviceId_AppendsToQuery begin."); - std::shared_ptr queryDeviceIdMock = std::make_shared(); - DataQuery queryDeviceId; - EXPECT_CALL(*queryDeviceIdMock, DeviceId("deviceId")).Times(1); - queryDeviceId.DeviceId("deviceId"); - EXPECT_EQ(queryDeviceId.ToString(), " DEVICE_ID deviceId"); -} - -/** - * @tc.name: SetSuggestIndex_ValidIndex_AppendsToQuery - * @tc.desc: - * @tc.type: SetSuggestIndex_ValidIndex_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, SetSuggestIndex_ValidIndex_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("DeviceId_ValidDeviceId_AppendsToQuery begin."); - std::shared_ptr querySetSuggestIndexMock = std::make_shared(); - DataQuery querySetSuggestIndex; - EXPECT_CALL(*querySetSuggestIndexMock, SuggestIndex("index")).Times(1); - querySetSuggestIndex.SetSuggestIndex("index"); - EXPECT_EQ(querySetSuggestIndex.ToString(), " SUGGEST_INDEX index"); -} - -/** - * @tc.name: InKeys_ValidKeys_AppendsToQuery - * @tc.desc: - * @tc.type: InKeys_ValidKeys_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, InKeys_ValidKeys_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("InKeys_ValidKeys_AppendsToQuery begin."); - std::shared_ptr queryInKeysMock = std::make_shared(); - DataQuery queryInKeys; - std::vector keys = {"key1", "key2"}; - EXPECT_CALL(*queryInKeysMock, InKeys(keys)).Times(1); - queryInKeys.InKeys(keys); - EXPECT_EQ(queryInKeys.ToString(), " IN_KEYS START_IN key1 key2 END_IN"); -} - -/** - * @tc.name: ToString_QueryTooLong_ReturnsEmptyString - * @tc.desc: - * @tc.type: ToString_QueryTooLong_ReturnsEmptyString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, ToString_QueryTooLong_ReturnsEmptyString, TestSize.Level0) -{ - ZLOGI("ToString_QueryTooLong_ReturnsEmptyString begin."); - DataQuery queryToString; - queryToString.str_.assign(MAX_QUERY_LENGTH + 1, 'a'); - EXPECT_EQ(queryToString.ToString(), ""); -} - -/** - * @tc.name: AppendCommon_ValidInput_CorrectAppending - * @tc.desc: - * @tc.type: AppendCommon_ValidInput_CorrectAppending test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, AppendCommon_ValidInput_CorrectAppending, TestSize.Level0) -{ - ZLOGI("AppendCommon_ValidInput_CorrectAppending begin."); - DataQuery queryAppendCommon; - string keyword = "key"; - string fieldType = "type"; - string field = "field"; - int value = 123; - queryAppendCommon.AppendCommon(keyword, fieldType, field, value); - EXPECT_EQ(queryAppendCommon.GetQuery(), " key type field 123"); -} - -/** - * @tc.name: AppendCommonString_ValidInput_CorrectAppending - * @tc.desc: - * @tc.type: AppendCommonString_ValidInput_CorrectAppending test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, AppendCommonString_ValidInput_CorrectAppending, TestSize.Level0) -{ - ZLOGI("AppendCommonString_ValidInput_CorrectAppending begin."); - DataQuery queryAppendCommonString; - string keyword = "key"; - string fieldType = "type"; - string field = "field"; - string value = "value"; - queryAppendCommonString.AppendCommonString(keyword, fieldType, field, value); - EXPECT_EQ(queryAppendCommonString.GetQuery(), " key type field value"); -} - -/** - * @tc.name: AppendCommonBoolean_ValidInput_CorrectAppending - * @tc.desc: - * @tc.type: AppendCommonBoolean_ValidInput_CorrectAppending test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, AppendCommonBoolean_ValidInput_CorrectAppending, TestSize.Level0) -{ - ZLOGI("AppendCommonBoolean_ValidInput_CorrectAppending begin."); - DataQuery queryAppendCommonBoolean; - string keyword = "key"; - string fieldType = "type"; - string field = "field"; - bool value = true; - queryAppendCommonBoolean.AppendCommonBoolean(keyword, fieldType, field, value); - EXPECT_EQ(queryAppendCommonBoolean.GetQuery(), " key type field true"); -} - -/** - * @tc.name: AppendCommonList_ValidInput_CorrectAppending - * @tc.desc: - * @tc.type: AppendCommonList_ValidInput_CorrectAppending test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, AppendCommonList_ValidInput_CorrectAppending, TestSize.Level0) -{ - ZLOGI("AppendCommonList_ValidInput_CorrectAppending begin."); - DataQuery queryAppendCommonList; - string keyword = "key"; - string fieldType = "type"; - string field = "field"; - vector valueList = {1, 2, 3}; - queryAppendCommonList.AppendCommonList(keyword, fieldType, field, valueList); - EXPECT_EQ(queryAppendCommonList.GetQuery(), " key type field ( 1 2 3 )"); -} - -/** - * @tc.name: AppendCommonListString_ValidInput_CorrectAppending - * @tc.desc: - * @tc.type: AppendCommonListString_ValidInput_CorrectAppending test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, AppendCommonListString_ValidInput_CorrectAppending, TestSize.Level0) -{ - ZLOGI("AppendCommonListString_ValidInput_CorrectAppending begin."); - DataQuery queryAppendCommonListString; - string keyword = "key"; - string fieldType = "type"; - string field = "field"; - vector valueList = {"value1", "value2"}; - queryAppendCommonListString.AppendCommonListString(keyword, fieldType, field, valueList); - EXPECT_EQ(queryAppendCommonListString.GetQuery(), " key type field ( value1 value2 )"); -} - -/** - * @tc.name: EscapeSpace_ValidInput_CorrectEscaping - * @tc.desc: - * @tc.type: EscapeSpace_ValidInput_CorrectEscaping test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, EscapeSpace_ValidInput_CorrectEscaping, TestSize.Level0) -{ - ZLOGI("EscapeSpace_ValidInput_CorrectEscaping begin."); - DataQuery queryEscapeSpace; - string input = "field with space"; - queryEscapeSpace.EscapeSpace(input); - EXPECT_EQ(input, "field\\ with\\ space"); -} - -/** - * @tc.name: ValidateField_ValidField_ReturnsTrue - * @tc.desc: - * @tc.type: ValidateField_ValidField_ReturnsTrue test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, ValidateField_ValidField_ReturnsTrue, TestSize.Level0) -{ - ZLOGI("ValidateField_ValidField_ReturnsTrue begin."); - DataQuery queryValidateField; - string field = "validField"; - EXPECT_TRUE(queryValidateField.ValidateField(field)); -} - -/** - * @tc.name: ValidateField_EmptyField_ReturnsFalse - * @tc.desc: - * @tc.type: ValidateField_EmptyField_ReturnsFalse test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, ValidateField_EmptyField_ReturnsFalse, TestSize.Level0) -{ - ZLOGI("ValidateField_EmptyField_ReturnsFalse begin."); - DataQuery queryValidateField; - string field = ""; - EXPECT_FALSE(queryValidateField.ValidateField(field)); -} - -/** - * @tc.name: ValidateField_FieldWithSpecialChar_ReturnsFalse - * @tc.desc: - * @tc.type: ValidateField_FieldWithSpecialChar_ReturnsFalse test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, ValidateField_FieldWithSpecialChar_ReturnsFalse, TestSize.Level0) -{ - ZLOGI("ValidateField_FieldWithSpecialChar_ReturnsFalse begin."); - DataQuery queryValidateField; - string field = "field with special*char"; - EXPECT_FALSE(queryValidateField.ValidateField(field)); -} - -/** - * @tc.name: BasicToString_ValidInput_CorrectConversion - * @tc.desc: - * @tc.type: BasicToString_ValidInput_CorrectConversion test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, BasicToString_ValidInput_CorrectConversion, TestSize.Level0) -{ - ZLOGI("BasicToString_ValidInput_CorrectConversion begin."); - DataQuery queryBasicToString; - int value = 456; - string result = queryBasicToString.BasicToString(value); - EXPECT_EQ(result, "456"); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/datamgr_service_proxy_virtual_test.cpp b/kv_store/databaseutils/test/datamgr_service_proxy_virtual_test.cpp deleted file mode 100644 index 94f721585e829131b6b069bdbafb3770e9c07d6f..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/datamgr_service_proxy_virtual_test.cpp +++ /dev/null @@ -1,324 +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. - */ -#define LOG_TAG "DataMgrServiceProxyVirtualTest" - -#include "datamgr_service_proxy.h" -#include "itypes_util.h" -#include "log_print.h" -#include "message_parcel.h" -#include "mock_remote_object.h" -#include "types.h" -#include -#include -#include - -using namespace OHOS::DistributedKv; -using namespace testing; -using namespace testing::ext; -namespace OHOS::Test { -class DataMgrServiceProxyVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void DataMgrServiceProxyVirtualTest::SetUpTestCase(void) -{} - -void DataMgrServiceProxyVirtualTest::TearDownTestCase(void) -{} - -void DataMgrServiceProxyVirtualTest::SetUp(void) -{} - -void DataMgrServiceProxyVirtualTest::TearDown(void) -{} - -/** - * @tc.name: GetFeatureInterface_Success - * @tc.desc: - * @tc.type: GetFeatureInterface_Success test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, GetFeatureInterface_Success, TestSize.Level0) -{ - ZLOGI("GetFeatureInterface_Success begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .WillOnce(Return(0)); // Simulation returns successfully - - auto result = proxy.GetFeatureInterface("GetFeatureInterface_Success"); - ASSERT_NE(result, nullptr); -} - -/** - * @tc.name: GetFeatureInterface_WriteDescriptorFailed - * @tc.desc: - * @tc.type: GetFeatureInterface_WriteDescriptorFailed test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, GetFeatureInterface_WriteDescriptorFailed, TestSize.Level0) -{ - ZLOGI("GetFeatureInterface_WriteDescriptorFailed begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .Times(0); // SendRequest is not called - - auto result = proxy.GetFeatureInterface("GetFeatureInterface_WriteDescriptorFailed"); - ASSERT_EQ(result, nullptr); -} - -/** - * @tc.name: GetFeatureInterface_WriteNameFailed - * @tc.desc: - * @tc.type: GetFeatureInterface_WriteNameFailed test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, GetFeatureInterface_WriteNameFailed, TestSize.Level0) -{ - ZLOGI("GetFeatureInterface_WriteNameFailed begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .Times(0); // SendRequest is not called - - auto result = proxy.GetFeatureInterface("GetFeatureInterface_WriteNameFailed"); - ASSERT_EQ(result, nullptr); -} - -/** - * @tc.name: GetFeatureInterface_SendRequestError - * @tc.desc: - * @tc.type: GetFeatureInterface_SendRequestError test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, GetFeatureInterface_SendRequestError, TestSize.Level0) -{ - ZLOGI("GetFeatureInterface_SendRequestError begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .WillOnce(Return(-1)); // Simulating an error - - auto result = proxy.GetFeatureInterface("GetFeatureInterface_SendRequestError"); - ASSERT_EQ(result, nullptr); -} - -/** - * @tc.name: RegisterClientDeathObserver_Success - * @tc.desc: - * @tc.type: RegisterClientDeathObserver_Success test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, RegisterClientDeathObserver_Success, TestSize.Level0) -{ - ZLOGI("RegisterClientDeathObserver_Success begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .WillOnce(Return(0)); // Simulation returns successfully - - AppId appId; - appId.appId = "RegisterClientDeathObserver_Success"; - sptr observer = new MockRemoteObject(); - auto status = proxy.RegisterClientDeathObserver(appId, observer); - ASSERT_EQ(status, Status::SUCCESS); -} - -/** - * @tc.name: RegisterClientDeathObserver_WriteDescriptorFailed - * @tc.desc: - * @tc.type: RegisterClientDeathObserver_WriteDescriptorFailed test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, RegisterClientDeathObserver_WriteDescriptorFailed, TestSize.Level0) -{ - ZLOGI("RegisterClientDeathObserver_WriteDescriptorFailed begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .Times(0); // SendRequest is not called - - AppId appId; - appId.appId = "RegisterClientDeathObserver_WriteDescriptorFailed"; - sptr observer = new MockRemoteObject(); - auto status = proxy.RegisterClientDeathObserver(appId, observer); - ASSERT_EQ(status, Status::IPC_ERROR); -} - -/** - * @tc.name: RegisterClientDeathObserver_WriteStringFailed - * @tc.desc: - * @tc.type: RegisterClientDeathObserver_WriteStringFailed test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, RegisterClientDeathObserver_WriteStringFailed, TestSize.Level0) -{ - ZLOGI("RegisterClientDeathObserver_WriteStringFailed begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .Times(0); // SendRequest is not called - - AppId appId; - appId.appId = "RegisterClientDeathObserver_WriteStringFailed"; - sptr observer = new MockRemoteObject(); - auto status = proxy.RegisterClientDeathObserver(appId, observer); - ASSERT_EQ(status, Status::IPC_ERROR); -} - -/** - * @tc.name: RegisterClientDeathObserver_NullObserver - * @tc.desc: - * @tc.type: RegisterClientDeathObserver_NullObserver test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, RegisterClientDeathObserver_NullObserver, TestSize.Level0) -{ - ZLOGI("RegisterClientDeathObserver_NullObserver begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .Times(0); // SendRequest is not called - - AppId appId; - appId.appId = "RegisterClientDeathObserver_NullObserver"; - auto status = proxy.RegisterClientDeathObserver(appId, nullptr); - ASSERT_EQ(status, Status::INVALID_ARGUMENT); -} - -/** - * @tc.name: RegisterClientDeathObserver_SendRequestError - * @tc.desc: - * @tc.type: RegisterClientDeathObserver_SendRequestError test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, RegisterClientDeathObserver_SendRequestError, TestSize.Level0) -{ - ZLOGI("RegisterClientDeathObserver_SendRequestError begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .WillOnce(Return(-1)); // Simulating an error - - AppId appId; - appId.appId = "RegisterClientDeathObserver_SendRequestError"; - sptr observer = new MockRemoteObject(); - auto status = proxy.RegisterClientDeathObserver(appId, observer); - ASSERT_EQ(status, Status::IPC_ERROR); -} - -/** - * @tc.name: ClearAppStorage_Success - * @tc.desc: - * @tc.type: ClearAppStorage_Success test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, ClearAppStorage_Success, TestSize.Level0) -{ - ZLOGI("ClearAppStorage_Success begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .WillOnce(Return(0)); // Simulation returns successfully - - auto result = proxy.ClearAppStorage("ClearAppStorage_Success", 1, 1, 1); - ASSERT_EQ(result, Status::SUCCESS); -} - -/** - * @tc.name: ClearAppStorage_WriteDescriptorFailed - * @tc.desc: - * @tc.type: ClearAppStorage_WriteDescriptorFailed test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, ClearAppStorage_WriteDescriptorFailed, TestSize.Level0) -{ - ZLOGI("ClearAppStorage_WriteDescriptorFailed begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .Times(0); // SendRequest is not called - - auto result = proxy.ClearAppStorage("ClearAppStorage_WriteDescriptorFailed", 1, 1, 1); - ASSERT_EQ(result, Status::IPC_ERROR); -} - -/** - * @tc.name: ClearAppStorage_WriteDataFailed - * @tc.desc: - * @tc.type: ClearAppStorage_WriteDataFailed test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, ClearAppStorage_WriteDataFailed, TestSize.Level0) -{ - ZLOGI("ClearAppStorage_WriteDataFailed begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .Times(0); // SendRequest is not called - - auto result = proxy.ClearAppStorage("ClearAppStorage_WriteDataFailed", 1, 1, 1); - ASSERT_EQ(result, Status::IPC_ERROR); -} - -/** - * @tc.name: ClearAppStorage_SendRequestError - * @tc.desc: - * @tc.type: ClearAppStorage_SendRequestError test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, ClearAppStorage_SendRequestError, TestSize.Level0) -{ - ZLOGI("ClearAppStorage_SendRequestError begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .WillOnce(Return(-1)); // Simulating an error - - auto result = proxy.ClearAppStorage("ClearAppStorage_SendRequestError", 1, 1, 1); - ASSERT_EQ(result, Status::IPC_ERROR); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/delegate_mgr_callback_virtual_test.cpp b/kv_store/databaseutils/test/delegate_mgr_callback_virtual_test.cpp deleted file mode 100644 index 3a7ad64304f15d7751d921e929bcf782a9ec50fc..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/delegate_mgr_callback_virtual_test.cpp +++ /dev/null @@ -1,125 +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. - */ -#define LOG_TAG "DelegateMgrCallbackVirtualTest" - -#include "kv_types_util.h" -#include "types.h" -#include -#include -#include -#include "distributeddb_kvstore_delegate_manager.h" -#include "delegate_mgr_callback.h" -#include - -using namespace OHOS::DistributedKv; -using namespace testing; -using namespace testing::ext; -namespace OHOS::Test { -class DelegateMgrCallbackVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void DelegateMgrCallbackVirtualTest::SetUpTestCase(void) -{ -} - -void DelegateMgrCallbackVirtualTest::TearDownTestCase(void) -{ -} - -void DelegateMgrCallbackVirtualTest::SetUp(void) -{ -} - -void DelegateMgrCallbackVirtualTest::TearDown(void) -{ -} - -class MockKvStoreDelegateManager : public KvStoreDelegateManager { -public: - MOCK_METHOD2(GetKvStoreDiskSize, DBStatus(const std::string &, uint64_t &)); -}; - -/** - * @tc.name: GetKvStoreDiskSize_DelegateIsNull_ReturnsFalse - * @tc.desc: - * @tc.type: GetKvStoreDiskSize_DelegateIsNull_ReturnsFalse test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GetKvStoreDiskSize_DelegateIsNull_ReturnsFalse, TestSize.Level0) -{ - ZLOGI("GetKvStoreDiskSize_DelegateIsNull_ReturnsFalse begin."); - MockKvStoreDelegateManager *mockDelegate1; - DelegateMgrCallback *callback1; - mockDelegate1 = new MockKvStoreDelegateManager(); - callback1 = new DelegateMgrCallback(nullptr); - - uint64_t size = 0; - EXPECT_FALSE(callback1->GetKvStoreDiskSize("storeId", size)); - - delete callback1; - delete mockDelegate1; -} - -/** - * @tc.name: GetKvStoreDiskSize_DelegateReturnsOK_ReturnsTrue - * @tc.desc: - * @tc.type: GetKvStoreDiskSize_DelegateReturnsOK_ReturnsTrue test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GetKvStoreDiskSize_DelegateReturnsOK_ReturnsTrue, TestSize.Level0) -{ - ZLOGI("GetKvStoreDiskSize_DelegateReturnsOK_ReturnsTrue begin."); - MockKvStoreDelegateManager *mockDelegate2; - DelegateMgrCallback *callback2; - mockDelegate2 = new MockKvStoreDelegateManager(); - callback2 = new DelegateMgrCallback(mockDelegate2); - uint64_t size = 0; - EXPECT_CALL(*mockDelegate2, GetKvStoreDiskSize("storeId", _)).WillOnce(Return(DBStatus::OK)); - EXPECT_TRUE(callback2->GetKvStoreDiskSize("storeId", size)); - - delete callback2; - delete mockDelegate2; -} - -/** - * @tc.name: GetKvStoreDiskSize_DelegateReturnsNonOK_ReturnsFalse - * @tc.desc: - * @tc.type: GetKvStoreDiskSize_DelegateReturnsNonOK_ReturnsFalse test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GetKvStoreDiskSize_DelegateReturnsNonOK_ReturnsFalse, TestSize.Level0) -{ - ZLOGI("GetKvStoreDiskSize_DelegateReturnsNonOK_ReturnsFalse begin."); - MockKvStoreDelegateManager *mockDelegate3; - DelegateMgrCallback *callback3; - mockDelegate3 = new MockKvStoreDelegateManager(); - callback3 = new DelegateMgrCallback(mockDelegate3); - - uint64_t size = 0; - EXPECT_CALL(*mockDelegate3, GetKvStoreDiskSize("storeId", _)).WillOnce(Return(DBStatus::NOT_FOUND)); - EXPECT_FALSE(callback->GetKvStoreDiskSize("storeId", size)); - - delete callback3; - delete mockDelegate3; -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/distributed_kv_data_manager_vritual_test.cpp b/kv_store/databaseutils/test/distributed_kv_data_manager_vritual_test.cpp deleted file mode 100644 index a7d4f492dc8ca0e48e481e199152d958ca8b8108..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/distributed_kv_data_manager_vritual_test.cpp +++ /dev/null @@ -1,863 +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. - */ -#define LOG_TAG "DistributedKvDataManagerVirtualTest" - -#include -#include -#include "distributed_kv_data_manager.h" -#include "kv_store_delegate_manager.h" -#include "kv_store_observer.h" -#include "kv_store_death_recipient.h" -#include "process_communication_impl.h" -#include "process_system_api_adapter_impl.h" -#include "store_manager.h" -#include "store_util.h" -#include "runtime_config.h" -#include "kv_store_service_death_notifier.h" -#include "dds_trace.h" -#include "kvstore_service_death_notifier.h" -#include "kv_store_death_recipient.h" -#include "kv_store_observer.h" -#include "kv_store_delegate_manager.h" -#include "process_communication_impl.h" -#include "process_system_api_adapter_impl.h" -#include "store_manager.h" -#include "store_util.h" -#include "runtime_config.h" -#include "kv_store_service_death_notifier.h" -#include "dds_trace.h" - -using namespace OHOS::DistributedKv; -using namespace testing; -using namespace testing::ext; -namespace OHOS::Test { -static constexpr size_t NUM_MIN_V = 5; -static constexpr size_t NUM_MAX_V = 12; -class DistributedKvDataManagerVirtualTest : public testing::Test { -public: - static std::shared_ptr executors; - static DistributedKvDataManager managerVirtual; - static Options createVirtual; - static Options noCreateVirtual; - static UserId userIdVirtual; - static AppId appIdVirtual; - static StoreId storeId64Virtual; - static StoreId storeId65Virtual; - static StoreId storeIdTestVirtual; - static StoreId storeIdEmptyVirtual; - static Entry entryAVirtual; - static Entry entryBVirtual; - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; -std::shared_ptr DistributedKvDataManagerTest::executors = - std::make_shared(NUM_MAX_V, NUM_MIN_V); - -void DistributedKvDataManagerVirtualTest::SetUpTestCase(void) -{} - -void DistributedKvDataManagerVirtualTest::TearDownTestCase(void) -{} - -void DistributedKvDataManagerVirtualTest::SetUp(void) -{} - -void DistributedKvDataManagerVirtualTest::TearDown(void) -{} - -class ChangeNotificationVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void ChangeNotificationVirtualTest::SetUpTestCase(void) -{} - -void ChangeNotificationVirtualTest::TearDownTestCase(void) -{} - -void ChangeNotificationVirtualTest::SetUp(void) -{} - -void ChangeNotificationVirtualTest::TearDown(void) -{} - -/** - * @tc.name: GetKvStore001 - * @tc.desc: Get an exist SingleKvStore - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlGetKvStore001 - */ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore001, TestSize.Level1) -{ - ZLOGI("GetKvStore001 begin."); - DistributedKvDataManager managerVirtual; - std::shared_ptr notExistKvStoreVirtual; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(notExistKvStoreVirtual, nullptr); - - std::shared_ptr existKvStoreVirtual; - statusVirtual = - managerVirtual.GetSingleKvStore(noCreateVirtual, appIdVirtual, storeId64Virtual, existKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(existKvStoreVirtual, nullptr); -} - -/** -* @tc.name: GetKvStore002 -* @tc.desc: Create and get a new SingleKvStore -* @tc.type: FUNC -* @tc.require: GetKvStore002 -* @tc.author: sqlGetKvStore002 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore002, TestSize.Level1) -{ - ZLOGI("GetKvStore002 begin."); - std::shared_ptr notExistKvStoreVirtual; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(notExistKvStoreVirtual, nullptr); - managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - managerVirtual.DeleteKvStore(appIdVirtual, storeId64Virtual); -} - -/** -* @tc.name: GetKvStore003 -* @tc.desc: Get a non-existing SingleKvStore, and the callback function should receive STORE_NOT_FOUND and -* get a nullptr. -* @tc.type: FUNC -* @tc.require: GetKvStore003 -* @tc.author: sqlGetKvStore003 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore003, TestSize.Level1) -{ - ZLOGI("GetKvStore003 begin."); - std::shared_ptr notExistKvStoreVirtual; - (void)managerVirtual.GetSingleKvStore(noCreateVirtual, appIdVirtual, storeId64Virtual, notExistKvStoreVirtual); - EXPECT_EQ(notExistKvStoreVirtual, nullptr); -} - -/** -* @tc.name: GetKvStore004 -* @tc.desc: Create a SingleKvStore with an empty storeId, and the callback function should receive -* @tc.type: FUNC -* @tc.require: GetKvStore004 -* @tc.author: sqlGetKvStore004 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore004, TestSize.Level1) -{ - ZLOGI("GetKvStore004 begin."); - std::shared_ptr notExistKvStoreVirtual; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeIdEmptyVirtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::INVALID_ARGUMENT); - EXPECT_EQ(notExistKvStoreVirtual, nullptr); -} - -/** -* @tc.name: GetKvStore005 -* @tc.desc: Get a SingleKvStore with an empty storeId, and the callback function should receive INVALID_ARGUMENT -* @tc.type: FUNC -* @tc.require: GetKvStore005 -* @tc.author: sqlGetKvStore005 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore005, TestSize.Level1) -{ - ZLOGI("GetKvStore005 begin."); - std::shared_ptr notExistKvStoreVirtual; - Status statusVirtual = - managerVirtual.GetSingleKvStore(noCreateVirtual, appIdVirtual, storeIdEmptyVirtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::INVALID_ARGUMENT); - EXPECT_EQ(notExistKvStoreVirtual, nullptr); -} - -/** -* @tc.name: GetKvStore006 -* @tc.desc: Create a SingleKvStore with a 65-byte storeId, and the callback function should receive INVALID_ARGUMENT -* @tc.type: FUNC -* @tc.require: GetKvStore006 -* @tc.author: sqlGetKvStore006 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore006, TestSize.Level1) -{ - ZLOGI("GetKvStore006 begin."); - std::shared_ptr notExistKvStoreVirtual; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId65Virtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::INVALID_ARGUMENT); - EXPECT_EQ(notExistKvStoreVirtual, nullptr); -} - -/** -* @tc.name: GetKvStore007 -* @tc.desc: Get a SingleKvStore with a 65-byte storeId, the callback function should receive INVALID_ARGUMENT -* @tc.type: FUNC -* @tc.require: GetKvStore007 -* @tc.author: sqlGetKvStore007 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore007, TestSize.Level1) -{ - ZLOGI("GetKvStore007 begin."); - std::shared_ptr notExistKvStoreVirtual; - Status statusVirtual = - managerVirtual.GetSingleKvStore(noCreateVirtual, appIdVirtual, storeId65Virtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::INVALID_ARGUMENT); - EXPECT_EQ(notExistKvStoreVirtual, nullptr); -} - -/** - * @tc.name: GetKvStore008 - * @tc.desc: Get a SingleKvStore which supports cloud sync. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlGetKvStore008 - */ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore008, TestSize.Level1) -{ - ZLOGI("GetKvStore008 begin."); - std::shared_ptr cloudKvStore = nullptr; - Options options = createVirtual; - options.isPublic = true; - options.cloudConfig = { - .enableCloud = true, - .autoSync = true - }; - Status statusVirtual = - managerVirtual.GetSingleKvStore(options, appIdVirtual, storeId64Virtual, cloudKvStore); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(cloudKvStore, nullptr); -} - -/** - * @tc.name: GetKvStore009 - * @tc.desc: Get a SingleKvStore which security level upgrade. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlGetKvStore009 - */ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore009, TestSize.Level1) -{ - ZLOGI("GetKvStore009 begin."); - std::shared_ptr kvStore = nullptr; - Options options = createVirtual; - options.securityLevel = S1; - Status statusVirtual = - managerVirtual.GetSingleKvStore(options, appIdVirtual, storeId64Virtual, kvStore); - - managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - options.securityLevel = S2; - statusVirtual = - managerVirtual.GetSingleKvStore(options, appIdVirtual, storeId64Virtual, kvStore); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(kvStore, nullptr); - - managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - options.securityLevel = S1; - statusVirtual = - managerVirtual.GetSingleKvStore(options, appIdVirtual, storeId64Virtual, kvStore); - ASSERT_EQ(statusVirtual, Status::STORE_META_CHANGED); - EXPECT_EQ(kvStore, nullptr); -} - -/** -* @tc.name: GetKvStoreInvalidSecurityLevel -* @tc.desc: Get a SingleKvStore with a 64 - * -byte storeId, the callback function should receive INVALID_ARGUMENT -* @tc.type: FUNC -* @tc.require: SR000IIM2J AR000IIMLL -* @tc.author: sqlGetKvStoreInvalidSecurityLevel -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStoreInvalidSecurityLevel, TestSize.Level1) -{ - ZLOGI("GetKvStoreInvalidSecurityLevel begin."); - std::shared_ptr notExistKvStoreVirtual; - Options invalidOption = createVirtual; - invalidOption.securityLevel = INVALID_LABEL; - Status statusVirtual = - managerVirtual.GetSingleKvStore(invalidOption, appIdVirtual, storeId64Virtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::INVALID_ARGUMENT); - EXPECT_EQ(notExistKvStoreVirtual, nullptr); -} - -/** -* @tc.name: GetAllKvStore001 -* @tc.desc: Get all KvStore IDs when no KvStore exists, and the callback function should receive a 0-length vector. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlGetAllKvStore001 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetAllKvStore001, TestSize.Level1) -{ - ZLOGI("GetAllKvStore001 begin."); - std::vector storeIds; - Status statusVirtual = managerVirtual.GetAllKvStoreId(appIdVirtual, storeIds); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_EQ(storeIds.size(), static_cast(0)); -} - -/** -* @tc.name: GetAllKvStore002 -* @tc.desc: Get all SingleKvStore IDs when no KvStore exists, and the callback function should receive a empty vector. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlGetAllKvStore002 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetAllKvStore002, TestSize.Level1) -{ - ZLOGI("GetAllKvStore002 begin."); - StoreId id1; - id1.storeId = "id1"; - StoreId id2; - id2.storeId = "id2"; - StoreId id3; - id3.storeId = "id3"; - std::shared_ptr kvStore; - Status statusVirtual = managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, id1, kvStore); - ASSERT_NE(kvStore, nullptr); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - statusVirtual = managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, id2, kvStore); - ASSERT_NE(kvStore, nullptr); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - statusVirtual = managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, id3, kvStore); - ASSERT_NE(kvStore, nullptr); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - std::vector storeIds; - statusVirtual = managerVirtual.GetAllKvStoreId(appIdVirtual, storeIds); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - bool haveId1 = false; - bool haveId2 = false; - bool haveId3 = false; - for (StoreId &id : storeIds) { - if (id.storeId == "id1") { - haveId1 = true; - } else if (id.storeId == "id2") { - haveId2 = true; - } else if (id.storeId == "id3") { - haveId3 = true; - } else { - ZLOGI("got an unknown storeId."); - EXPECT_TRUE(false); - } - } - EXPECT_TRUE(haveId1); - EXPECT_TRUE(haveId2); - EXPECT_TRUE(haveId3); - EXPECT_EQ(storeIds.size(), static_cast(3)); -} - -/** -* @tc.name: CloseKvStore001 -* @tc.desc: Close an opened KVStore, and the callback function should return SUCCESS. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlCloseKvStore001 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseKvStore001, TestSize.Level1) -{ - ZLOGI("CloseKvStore001 begin."); - std::shared_ptr kvStore; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore, nullptr); - - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: CloseKvStore002 -* @tc.desc: Close a closed SingleKvStore, and the callback function should return SUCCESS. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlCloseKvStore002 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseKvStore002, TestSize.Level1) -{ - ZLOGI("CloseKvStore002 begin."); - std::shared_ptr kvStore; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore, nullptr); - - managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::STORE_NOT_OPEN); -} - -/** -* @tc.name: CloseKvStore003 -* @tc.desc: Close a SingleKvStore with an empty storeId, and the callback function should return INVALID_ARGUMENT. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlCloseKvStore003 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseKvStore003, TestSize.Level1) -{ - ZLOGI("CloseKvStore003 begin."); - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeIdEmptyVirtual); - EXPECT_EQ(stat, Status::INVALID_ARGUMENT); -} - -/** -* @tc.name: CloseKvStore004 -* @tc.desc: Close a SingleKvStore with a 65-byte storeId, and the callback function should return INVALID_ARGUMENT. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlCloseKvStore004 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseKvStore004, TestSize.Level1) -{ - ZLOGI("CloseKvStore004 begin."); - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId65Virtual); - EXPECT_EQ(stat, Status::INVALID_ARGUMENT); -} - -/** -* @tc.name: CloseKvStore005 -* @tc.desc: Close a non-existing SingleKvStore, and the callback function should return STORE_NOT_OPEN. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseKvStore005, TestSize.Level1) -{ - ZLOGI("CloseKvStore005 begin."); - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::STORE_NOT_OPEN); -} - -/** -* @tc.name: CloseKvStoreMulti001 -* @tc.desc: Open a SingleKvStore several times and close them one by one. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000CSKRU -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseKvStoreMulti001, TestSize.Level1) -{ - ZLOGI("CloseKvStoreMulti001 begin."); - std::shared_ptr notExistKvStoreVirtual; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(notExistKvStoreVirtual, nullptr); - - std::shared_ptr existKvStoreVirtual; - managerVirtual.GetSingleKvStore(noCreateVirtual, appIdVirtual, storeId64Virtual, existKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(existKvStoreVirtual, nullptr); - - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); - - stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: CloseKvStoreMulti002 -* @tc.desc: Open a SingleKvStore several times and close them one by one. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000CSKRU -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseKvStoreMulti002, TestSize.Level1) -{ - ZLOGI("CloseKvStoreMulti002 begin."); - std::shared_ptr notExistKvStoreVirtual; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(notExistKvStoreVirtual, nullptr); - - std::shared_ptr existKvStore1; - statusVirtual = - managerVirtual.GetSingleKvStore(noCreateVirtual, appIdVirtual, storeId64Virtual, existKvStore1); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(existKvStore1, nullptr); - - std::shared_ptr existKvStore2; - statusVirtual = - managerVirtual.GetSingleKvStore(noCreateVirtual, appIdVirtual, storeId64Virtual, existKvStore2); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(existKvStore2, nullptr); - - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); - - stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); - - stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); - - stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_NE(stat, Status::SUCCESS); -} - -/** -* @tc.name: CloseAllKvStore001 -* @tc.desc: Close all opened KvStores, and the callback function should return SUCCESS. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseAllKvStore001, TestSize.Level1) -{ - ZLOGI("CloseAllKvStore001 begin."); - std::shared_ptr kvStore1; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore1); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore1, nullptr); - - std::shared_ptr kvStore2; - statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeIdTestVirtual, kvStore2); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore2, nullptr); - - Status stat = managerVirtual.CloseAllKvStore(appIdVirtual); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: CloseAllKvStore002 -* @tc.desc: Close all KvStores which exist but are not opened, and the callback function should return STORE_NOT_OPEN. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseAllKvStore002, TestSize.Level1) -{ - ZLOGI("CloseAllKvStore002 begin."); - std::shared_ptr kvStore; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore, nullptr); - - std::shared_ptr kvStore2; - statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeIdTestVirtual, kvStore2); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore2, nullptr); - - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); - - stat = managerVirtual.CloseAllKvStore(appIdVirtual); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: DeleteKvStore001 -* @tc.desc: Delete a closed KvStore, and the callback function should return SUCCESS. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteKvStore001, TestSize.Level1) -{ - ZLOGI("DeleteKvStore001 begin."); - std::shared_ptr kvStore; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore, nullptr); - - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - ASSERT_EQ(stat, Status::SUCCESS); - - stat = managerVirtual.DeleteKvStore(appIdVirtual, storeId64Virtual, createVirtual.baseDir); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: DeleteKvStore002 -* @tc.desc: Delete an opened SingleKvStore, and the callback function should return SUCCESS. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteKvStore002, TestSize.Level1) -{ - ZLOGI("DeleteKvStore002 begin."); - std::shared_ptr kvStore; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore, nullptr); - - // first close it if opened, and then delete it. - Status stat = managerVirtual.DeleteKvStore(appIdVirtual, storeId64Virtual, createVirtual.baseDir); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: DeleteKvStore003 -* @tc.desc: Delete a non-existing KvStore, and the callback function should return DB_ERROR. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteKvStore003, TestSize.Level1) -{ - ZLOGI("DeleteKvStore003 begin."); - Status stat = managerVirtual.DeleteKvStore(appIdVirtual, storeId64Virtual, createVirtual.baseDir); - EXPECT_EQ(stat, Status::STORE_NOT_FOUND); -} - -/** -* @tc.name: DeleteKvStore004 -* @tc.desc: Delete a KvStore with an empty storeId, and the callback function should return INVALID_ARGUMENT. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteKvStore004, TestSize.Level1) -{ - ZLOGI("DeleteKvStore004 begin."); - Status stat = managerVirtual.DeleteKvStore(appIdVirtual, storeIdEmptyVirtual); - EXPECT_EQ(stat, Status::INVALID_ARGUMENT); -} - -/** -* @tc.name: DeleteKvStore005 -* @tc.desc: Delete a KvStore with 65 bytes long storeId (which exceed storeId length limit). Should -* return INVALID_ARGUMENT. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteKvStore005, TestSize.Level1) -{ - ZLOGI("DeleteKvStore005 begin."); - Status stat = managerVirtual.DeleteKvStore(appIdVirtual, storeId65Virtual); - EXPECT_EQ(stat, Status::INVALID_ARGUMENT); -} - -/** -* @tc.name: DeleteAllKvStore001 -* @tc.desc: Delete all KvStores after closing all of them, and the callback function should return SUCCESS. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteAllKvStore001, TestSize.Level1) -{ - ZLOGI("DeleteAllKvStore001 begin."); - std::shared_ptr kvStore1; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore1); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore1, nullptr); - std::shared_ptr kvStore2; - statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeIdTestVirtual, kvStore2); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore2, nullptr); - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); - stat = managerVirtual.CloseKvStore(appIdVirtual, storeIdTestVirtual); - EXPECT_EQ(stat, Status::SUCCESS); - - stat = managerVirtual.DeleteAllKvStore({""}, createVirtual.baseDir); - EXPECT_NE(stat, Status::SUCCESS); - stat = managerVirtual.DeleteAllKvStore(appIdVirtual, ""); - EXPECT_EQ(stat, Status::INVALID_ARGUMENT); - - stat = managerVirtual.DeleteAllKvStore(appIdVirtual, createVirtual.baseDir); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: DeleteAllKvStore002 -* @tc.desc: Delete all kvstore fail when any kvstore in the appIdVirtual is not closed -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteAllKvStore002, TestSize.Level1) -{ - ZLOGI("DeleteAllKvStore002 begin."); - std::shared_ptr kvStore1; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore1); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore1, nullptr); - std::shared_ptr kvStore2; - statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeIdTestVirtual, kvStore2); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore2, nullptr); - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); - - stat = managerVirtual.DeleteAllKvStore(appIdVirtual, createVirtual.baseDir); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: DeleteAllKvStore003 -* @tc.desc: Delete all KvStores even if no KvStore exists in the appIdVirtual. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteAllKvStore003, TestSize.Level1) -{ - ZLOGI("DeleteAllKvStore003 begin."); - Status stat = managerVirtual.DeleteAllKvStore(appIdVirtual, createVirtual.baseDir); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: DeleteAllKvStore004 -* @tc.desc: when delete the last active kvstore, the system will remove the app managerVirtual scene -* @tc.type: FUNC -* @tc.require: bugs -* @tc.author: sqlSven Wang -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteAllKvStore004, TestSize.Level1) -{ - ZLOGI("DeleteAllKvStore004 begin."); - std::shared_ptr kvStore1; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore1); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore1, nullptr); - std::shared_ptr kvStore2; - statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeIdTestVirtual, kvStore2); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore2, nullptr); - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); - stat = managerVirtual.CloseKvStore(appIdVirtual, storeIdTestVirtual); - EXPECT_EQ(stat, Status::SUCCESS); - stat = managerVirtual.DeleteKvStore(appIdVirtual, storeIdTestVirtual, createVirtual.baseDir); - EXPECT_EQ(stat, Status::SUCCESS); - stat = managerVirtual.DeleteAllKvStore(appIdVirtual, createVirtual.baseDir); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: PutSwitchWithEmptyAppId -* @tc.desc: put switch data, but appIdVirtual is empty. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sqlzuojiangjiang -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, PutSwitchWithEmptyAppId, TestSize.Level1) -{ - ZLOGI("PutSwitchWithEmptyAppId begin."); - SwitchData data; - Status statusVirtual = managerVirtual.PutSwitch({ "" }, data); - ASSERT_EQ(statusVirtual, Status::INVALID_ARGUMENT); -} - -/** -* @tc.name: PutSwitchWithInvalidAppId -* @tc.desc: put switch data, but appIdVirtual is not 'distributed_device_profile_service'. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sqlzuojiangjiang -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, PutSwitchWithInvalidAppId, TestSize.Level1) -{ - ZLOGI("PutSwitchWithInvalidAppId begin."); - SwitchData data; - Status statusVirtual = managerVirtual.PutSwitch({ "swicthes_test_appId" }, data); - ASSERT_EQ(statusVirtual, Status::PERMISSION_DENIED); -} - -/** -* @tc.name: GetSwitchWithInvalidArg -* @tc.desc: get switch data, but appIdVirtual is empty, networkId is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sqlzuojiangjiang -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetSwitchWithInvalidArg, TestSize.Level1) -{ - ZLOGI("GetSwitchWithInvalidArg begin."); - auto [status1, data1] = managerVirtual.GetSwitch({ "" }, "networkId_test"); - ASSERT_EQ(status1, Status::INVALID_ARGUMENT); - auto [status2, data2] = managerVirtual.GetSwitch({ "switches_test_appId" }, ""); - ASSERT_EQ(status2, Status::INVALID_ARGUMENT); - auto [status3, data3] = managerVirtual.GetSwitch({ "switches_test_appId" }, "networkId_test"); - ASSERT_EQ(status3, Status::INVALID_ARGUMENT); -} - -/** -* @tc.name: GetSwitchWithInvalidAppId -* @tc.desc: get switch data, but appIdVirtual is not 'distributed_device_profile_service'. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sqlzuojiangjiang -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetSwitchWithInvalidAppId, TestSize.Level1) -{ - ZLOGI("GetSwitchWithInvalidAppId begin."); - auto devInfo = DevManager::GetInstance().GetLocalDevice(); - EXPECT_NE(devInfo.networkId, ""); - auto [statusVirtual, data] = managerVirtual.GetSwitch({ "switches_test_appId" }, devInfo.networkId); - ASSERT_EQ(statusVirtual, Status::PERMISSION_DENIED); -} - -/** -* @tc.name: SubscribeSwitchesData -* @tc.desc: subscribe switch data. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sqlzuojiangjiang -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, SubscribeSwitchesData, TestSize.Level1) -{ - ZLOGI("SubscribeSwitchesData begin."); - std::shared_ptr observer = std::make_shared(); - auto statusVirtual = managerVirtual.SubscribeSwitchData({ "switches_test_appId" }, observer); - ASSERT_EQ(statusVirtual, Status::PERMISSION_DENIED); -} - -/** -* @tc.name: UnsubscribeSwitchesData -* @tc.desc: unsubscribe switch data. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sqlzuojiangjiang -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, UnsubscribeSwitchesData, TestSize.Level1) -{ - ZLOGI("UnsubscribeSwitchesData begin."); - std::shared_ptr observer = std::make_shared(); - auto statusVirtual = managerVirtual.SubscribeSwitchData({ "switches_test_appId" }, observer); - ASSERT_EQ(statusVirtual, Status::PERMISSION_DENIED); - statusVirtual = managerVirtual.UnsubscribeSwitchData({ "switches_test_appId" }, observer); - ASSERT_EQ(statusVirtual, Status::PERMISSION_DENIED); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/kv_utils_virtual_test.cpp b/kv_store/databaseutils/test/kv_utils_virtual_test.cpp deleted file mode 100644 index aec5af978896ab46adb0264c300e4bfd426f3feb..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/kv_utils_virtual_test.cpp +++ /dev/null @@ -1,1053 +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. - */ -#define LOG_TAG "KvUtilVirtualTest" - -#include -#include -#include -#include -#include -#include "kv_utils.h" -#include "data_query.h" -#include "data_share_abs_predicates.h" -#include "data_share_values_bucket.h" -#include "data_share_value_object.h" - -using namespace testing::ext; -using namespace OHOS::DistributedKv; -using namespace OHOS::DataShare; -namespace OHOS::Test { -static constexpr const char *KEY = "key"; -static constexpr const char *VALUE = "value"; -static constexpr const char *VALID_SCHEMA_STRICT_DEFINE = "{\"SCHEMA_VERSION\":\"1.0\"," - "\"SCHEMA_MODE\":\"STRICT\"," - "\"SCHEMA_SKIPSIZE\":0," - "\"SCHEMA_DEFINE\":" - "{" - "\"age\":\"INTEGER, NOT NULL\"" - "}," - "\"SCHEMA_INDEXES\":[\"$.age\"]}"; -using var_t = std::variant>; -class KvUtilVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - -protected: - static DistributedKvDataManager managerVirtual; - static std::shared_ptr singleKvStoreVirtual; - - static std::string Entry2Str(const Entry &entry); - static void ClearEntry(Entry &entry); - static Blob VariantValue2Blob(const var_t &value); - static Blob VariantKey2Blob(const var_t &value); -}; -std::shared_ptr KvUtilVirtualTest::singleKvStoreVirtual = nullptr; -DistributedKvDataManager KvUtilVirtualTest::managerVirtual; - -void KvUtilVirtualTest::SetUp(void) -{ - ZLOGI("SetUp begin."); -} - -void KvUtilVirtualTest::TearDown(void) -{ - ZLOGI("TearDown begin."); -} - -std::string KvUtilVirtualTest::Entry2Str(const Entry &entry) -{ - ZLOGI("Entry2Str begin."); - return entry.key.ToString() + entry.value.ToString(); -} - -void KvUtilVirtualTest::ClearEntry(Entry &entry) -{ - ZLOGI("ClearEntry begin."); - entry.key.Clear(); - entry.value.Clear(); -} - -Blob KvUtilVirtualTest::VariantKey2Blob(const var_t &value) -{ - ZLOGI("VariantKey2Blob begin."); - std::vector uData; - if (auto *val = std::get_if(&value)) { - std::string data = *val; - uData.insert(uData.end(), data.begin(), data.end()); - } - return Blob(uData); -} - -Blob KvUtilVirtualTest::VariantValue2Blob(const var_t &value) -{ - ZLOGI("VariantValue2Blob begin."); - std::vector data; - auto strValue = std::get_if(&value); - if (strValue != nullptr) { - data.push_back(KvUtils::STRING); - data.insert(data.end(), (*strValue).begin(), (*strValue).end()); - } - auto boolValue = std::get_if(&value); - if (boolValue != nullptr) { - data.push_back(KvUtils::BOOLEAN); - data.push_back(static_cast(*boolValue)); - } - uint8_t *tmp = nullptr; - auto dblValue = std::get_if(&value); - if (dblValue != nullptr) { - double tmp4dbl = *dblValue; - uint64_t tmp64 = htobe64(*reinterpret_cast(&tmp4dbl)); - tmp = reinterpret_cast(&tmp64); - data.push_back(KvUtils::DOUBLE); - data.insert(data.end(), tmp, tmp + sizeof(double) / sizeof(uint8_t)); - } - auto intValue = std::get_if(&value); - if (intValue != nullptr) { - int64_t tmp4int = *intValue; - uint64_t tmp64 = htobe64(*reinterpret_cast(&tmp4int)); - tmp = reinterpret_cast(&tmp64); - data.push_back(KvUtils::INTEGER); - data.insert(data.end(), tmp, tmp + sizeof(int64_t) / sizeof(uint8_t)); - } - auto u8ArrayValue = std::get_if>(&value); - if (u8ArrayValue != nullptr) { - data.push_back(KvUtils::BYTE_ARRAY); - data.insert(data.end(), (*u8ArrayValue).begin(), (*u8ArrayValue).end()); - } - return Blob(data); -} - -void KvUtilVirtualTest::SetUpTestCase(void) -{ - ZLOGI("SetUpTestCase begin."); - Options options = { - .createIfMissing = true, - .encrypt = false, - .autoSync = false, - .kvStoreType = KvStoreType::SINGLE_VERSION, - .schema = VALID_SCHEMA_STRICT_DEFINE }; - options.area = EL1; - options.securityLevel = S1; - options.baseDir = std::string("/data/service/el1/public/database/KvUtilVirtualTest"); - AppId appId = { "KvUtilVirtualTest" }; - StoreId storeId = { "test_single" }; - mkdir(options.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); - managerVirtual.DeleteKvStore(appId, storeId, options.baseDir); - managerVirtual.GetSingleKvStore(options, appId, storeId, singleKvStoreVirtual); - EXPECT_NE(singleKvStoreVirtual, nullptr); - singleKvStoreVirtual->Put("test_key_1", "{\"age\":1}"); - singleKvStoreVirtual->Put("test_key_2", "{\"age\":2}"); - singleKvStoreVirtual->Put("test_key_3", "{\"age\":3}"); - singleKvStoreVirtual->Put("kv_utils", "{\"age\":4}"); -} - -void KvUtilVirtualTest::TearDownTestCase(void) -{ - ZLOGI("TearDownTestCase begin."); - managerVirtual.DeleteKvStore({"KvUtilVirtualTest" }, - { "test_single" }, "/data/service/el1/public/database/KvUtilVirtualTest"); - (void)remove("/data/service/el1/public/database/KvUtilVirtualTest/key"); - (void)remove("/data/service/el1/public/database/KvUtilVirtualTest/kvdb"); - (void)remove("/data/service/el1/public/database/KvUtilVirtualTest"); -} - -/** - * @tc.name: KvStoreResultSetToResultSetBridgeAbnormal - * @tc.desc: kvStore resultSetVirtual to resultSetVirtual bridgeVirtual, the former is nullptr - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, KvStoreResultSetToResultSetBridgeAbnormal, TestSize.Level0) -{ - ZLOGI("KvStoreResultSetToResultSetBridgeAbnormal begin."); - std::shared_ptr resultSetVirtual = nullptr; - auto bridgeVirtual = KvUtils::ToResultSetBridge(resultSetVirtual); - EXPECT_EQ(bridgeVirtual, nullptr); -} - -/** - * @tc.name: KvStoreResultSetToResultSetBridge - * @tc.desc: kvStore resultSetVirtual to resultSetVirtual bridgeVirtual - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, KvStoreResultSetToResultSetBridge, TestSize.Level0) -{ - ZLOGI("KvStoreResultSetToResultSetBridge begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.KeyPrefix("test"); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - std::shared_ptr resultSetVirtual = nullptr; - statusVirtual = singleKvStoreVirtual->GetResultSet(queryVirtual, resultSetVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(resultSetVirtual, nullptr); - EXPECT_EQ(resultSetVirtual->GetCount(), 3); - auto bridgeVirtual = KvUtils::ToResultSetBridge(resultSetVirtual); - EXPECT_NE(bridgeVirtual, nullptr); -} - -/** - * @tc.name: PredicatesToQueryEqualTo - * @tc.desc: to queryVirtual equalTo - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryEqualTo, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryEqualTo begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.EqualTo("$.age", 1); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.EqualTo("$.age", 1); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryNotEqualTo - * @tc.desc: to queryVirtual not equalTo - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryNotEqualTo, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryNotEqualTo begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.NotEqualTo("$.age", 1); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.NotEqualTo("$.age", 1); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryGreaterThan - * @tc.desc: to queryVirtual greater than - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryGreaterThan, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryGreaterThan begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.GreaterThan("$.age", 1); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.GreaterThan("$.age", 1); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryLessThan - * @tc.desc: to queryVirtual less than - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryLessThan, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryLessThan begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.LessThan("$.age", 3); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.LessThan("$.age", 3); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryGreaterThanOrEqualTo - * @tc.desc: to queryVirtual greater than or equalTo - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryGreaterThanOrEqualTo, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryGreaterThanOrEqualTo begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.GreaterThanOrEqualTo("$.age", 1); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.GreaterThanOrEqualTo("$.age", 1); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryLessThanOrEqualTo - * @tc.desc: to queryVirtual less than or equalTo - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryLessThanOrEqualTo, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryLessThanOrEqualTo begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.LessThanOrEqualTo("$.age", 3); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.LessThanOrEqualTo("$.age", 3); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryIn - * @tc.desc: to queryVirtual in - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryIn, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryIn begin."); - std::vector vectInt { 1, 2 }; - DataSharePredicates predicatesVirtual; - predicatesVirtual.In("$.age", vectInt); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.In("$.age", vectInt); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryNotIn - * @tc.desc: to queryVirtual not in - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryNotIn, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryNotIn begin."); - std::vector vectInt { 1, 2 }; - DataSharePredicates predicatesVirtual; - predicatesVirtual.NotIn("$.age", vectInt); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.NotIn("$.age", vectInt); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryLike - * @tc.desc: to queryVirtual or, like - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryLike, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryLike begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.Like("$.age", "1"); - predicatesVirtual.Or(); - predicatesVirtual.Like("$.age", "3"); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.Like("$.age", "1"); - trgQueryVirtual.Or(); - trgQueryVirtual.Like("$.age", "3"); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryUnlike - * @tc.desc: to queryVirtual and, unlike - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryUnlike, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryUnlike begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.Unlike("$.age", "1"); - predicatesVirtual.And(); - predicatesVirtual.Unlike("$.age", "3"); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.Unlike("$.age", "1"); - trgQueryVirtual.And(); - trgQueryVirtual.Unlike("$.age", "3"); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryIsNull - * @tc.desc: to queryVirtual is null - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryIsNull, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryIsNull begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.IsNull("$.age"); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.IsNull("$.age"); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryIsNotNull - * @tc.desc: to queryVirtual is not null - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryIsNotNull, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryIsNotNull begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.IsNotNull("$.age"); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.IsNotNull("$.age"); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryOrderByAsc - * @tc.desc: to queryVirtual is order by asc - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryOrderByAsc, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryOrderByAsc begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.OrderByAsc("$.age"); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.OrderByAsc("$.age"); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryOrderByDesc - * @tc.desc: to queryVirtual is order by desc - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryOrderByDesc, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryOrderByDesc begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.OrderByDesc("$.age"); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.OrderByDesc("$.age"); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryLimit - * @tc.desc: to queryVirtual is limit - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryLimit, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryLimit begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.Limit(0, 9); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.Limit(0, 9); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryInKeys - * @tc.desc: to queryVirtual is in keys - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryInKeys, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryInKeys begin."); - std::vector keys { "test_field", "", "^test_field", "^", "test_field_name" }; - DataSharePredicates predicatesVirtual; - predicatesVirtual.InKeys(keys); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.InKeys(keys); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: DataShareValuesBucketToEntryAbnormal - * @tc.desc: dataShare values bucket to entry, the bucket is invalid - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntryAbnormal, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntryAbnormal begin."); - DataShareValuesBucket bucket {}; - Entry trgEntry {}; - auto entry = KvUtils::ToEntry(bucket); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); - bucket.Put("invalid key", "value"); - EXPECT_FALSE(bucket.IsEmpty()); - entry = KvUtils::ToEntry(bucket); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); - bucket.Put(KEY, "value"); - entry = KvUtils::ToEntry(bucket); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); -} - -/** - * @tc.name: DataShareValuesBucketToEntryNull - * @tc.desc: dataShare values bucket to entry, the bucket value is null - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntryNull, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntryNull begin."); - DataShareValuesBucket bucket {}; - bucket.Put(KEY, {}); - bucket.Put(VALUE, {}); - auto entry = KvUtils::ToEntry(bucket); - Entry trgEntry; - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); -} - -/** - * @tc.name: DataShareValuesBucketToEntryInt64_t - * @tc.desc: dataShare values bucket to entry, the bucket value type is int64_t - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntryInt64_t, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntryInt64_t begin."); - DataShareValuesBucket bucket {}; - Entry trgEntry; - var_t varValue; - varValue.emplace<1>(314); - var_t varKey; - varKey.emplace<3>("314"); - bucket.Put(KEY, varKey); - bucket.Put(VALUE, varValue); - auto entry = KvUtils::ToEntry(bucket); - trgEntry.key = VariantKey2Blob(varKey); - trgEntry.value = VariantValue2Blob(varValue); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); -} - -/** - * @tc.name: DataShareValuesBucketToEntryDouble - * @tc.desc: dataShare values bucket to entry, the bucket value type is double - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntryDouble, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntryDouble begin."); - DataShareValuesBucket bucket {}; - Entry trgEntry; - var_t varValue; - varValue.emplace<2>(3.14); - var_t varKey; - varKey.emplace<3>("314"); - bucket.Put(KEY, varKey); - bucket.Put(VALUE, varValue); - auto entry = KvUtils::ToEntry(bucket); - trgEntry.key = VariantKey2Blob(varKey); - trgEntry.value = VariantValue2Blob(varValue); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); -} - -/** - * @tc.name: DataShareValuesBucketToEntryString - * @tc.desc: dataShare values bucket to entry, the bucket value type is string - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntryString, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntryString begin."); - DataShareValuesBucket bucket {}; - Entry trgEntry; - var_t varValue; - varValue.emplace<3>("3.14"); - var_t varKey; - varKey.emplace<3>("314"); - bucket.Put(KEY, varKey); - bucket.Put(VALUE, varValue); - auto entry = KvUtils::ToEntry(bucket); - trgEntry.key = VariantKey2Blob(varKey); - trgEntry.value = VariantValue2Blob(varValue); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); -} - -/** - * @tc.name: DataShareValuesBucketToEntryBool - * @tc.desc: dataShare values bucket to entry, the bucket value type is bool - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntryBool, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntryBool begin."); - DataShareValuesBucket bucket {}; - Entry trgEntry; - var_t varValue; - varValue.emplace<4>(true); - var_t varKey; - varKey.emplace<3>("314"); - bucket.Put(KEY, varKey); - bucket.Put(VALUE, varValue); - auto entry = KvUtils::ToEntry(bucket); - trgEntry.key = VariantKey2Blob(varKey); - trgEntry.value = VariantValue2Blob(varValue); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); -} - -/** - * @tc.name: DataShareValuesBucketToEntryUint8Array - * @tc.desc: dataShare values bucket to entry, the bucket value type is uint8array - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntryUint8Array, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntryUint8Array begin."); - DataShareValuesBucket bucket {}; - Entry trgEntry; - var_t varValue; - std::vector vecUint8 { 3, 14 }; - varValue.emplace<5>(vecUint8); - var_t varKey; - varKey.emplace<3>("314"); - bucket.Put(KEY, varKey); - bucket.Put(VALUE, varValue); - auto entry = KvUtils::ToEntry(bucket); - trgEntry.key = VariantKey2Blob(varKey); - trgEntry.value = VariantValue2Blob(varValue); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); -} - -/** - * @tc.name: DataShareValuesBucketToEntryInvalidKey - * @tc.desc: dataShare values bucket to entry, the bucket key type is not string - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntryInvalidKey, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntryInvalidKey begin."); - DataShareValuesBucket bucket {}; - Entry trgEntry; - var_t varValue; - std::vector vecUint8 { 3, 14 }; - varValue.emplace<5>(vecUint8); - var_t varKey; - varKey.emplace<1>(314); - bucket.Put(KEY, varKey); - bucket.Put(VALUE, varValue); - auto entry = KvUtils::ToEntry(bucket); - trgEntry.key = VariantKey2Blob(varKey); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); -} - -/** - * @tc.name: DataShareValuesBucketToEntriesAbnormal - * @tc.desc: dataShare values bucket to entries, the buckets is invalid - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntriesAbnormal, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntriesAbnormal begin."); - std::vector buckets {}; - auto entries = KvUtils::ToEntries(buckets); - EXPECT_TRUE(entries.empty()); -} - -/** - * @tc.name: DataShareValuesBucketToEntriesNormal - * @tc.desc: dataShare values bucket to entries, the buckets has valid value - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntriesNormal, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntriesNormal begin."); - std::vector buckets {}; - DataShareValuesBucket bucket; - Entry trgEntryFirst; - Entry trgEntrySecond; - var_t varValue; - varValue.emplace<1>(314); - var_t varKey; - varKey.emplace<3>("314"); - bucket.Put(KEY, varKey); - bucket.Put(VALUE, varValue); - buckets.emplace_back(bucket); - trgEntryFirst.key = VariantKey2Blob(varKey); - trgEntryFirst.value = VariantValue2Blob(varValue); - bucket.Clear(); - varValue.emplace<2>(3.14); - varKey.emplace<3>("3.14"); - bucket.Put(KEY, varKey); - bucket.Put(VALUE, varValue); - buckets.emplace_back(bucket); - trgEntrySecond.key = VariantKey2Blob(varKey); - trgEntrySecond.value = VariantValue2Blob(varValue); - auto entries = KvUtils::ToEntries(buckets); - EXPECT_EQ(entries.size(), 2); - EXPECT_EQ(Entry2Str(entries[0]), Entry2Str(trgEntryFirst)); - EXPECT_EQ(Entry2Str(entries[1]), Entry2Str(trgEntrySecond)); -} - -/** - * @tc.name: GetKeysFromDataSharePredicatesAbnormal - * @tc.desc: get keys from data share predicatesVirtual, the predicatesVirtual is invalid - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, GetKeysFromDataSharePredicatesAbnormal, TestSize.Level0) -{ - ZLOGI("GetKeysFromDataSharePredicatesAbnormal begin."); - DataSharePredicates predicatesVirtual; - std::vector kvKeys; - auto statusVirtual = KvUtils::GetKeys(predicatesVirtual, kvKeys); - EXPECT_EQ(statusVirtual, Status::ERROR); - predicatesVirtual.EqualTo("$.age", 1); - statusVirtual = KvUtils::GetKeys(predicatesVirtual, kvKeys); - EXPECT_EQ(statusVirtual, Status::NOT_SUPPORT); -} - -/** - * @tc.name: GetKeysFromDataSharePredicatesNormal - * @tc.desc: get keys from data share predicatesVirtual, the predicatesVirtual has valid value - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, GetKeysFromDataSharePredicatesNormal, TestSize.Level0) -{ - ZLOGI("GetKeysFromDataSharePredicatesNormal begin."); - std::vector keys { "test_field", "", "^test_field", "^", "test_field_name" }; - DataSharePredicates predicatesVirtual; - predicatesVirtual.InKeys(keys); - std::vector kvKeys; - auto statusVirtual = KvUtils::GetKeys(predicatesVirtual, kvKeys); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_EQ(keys.size(), kvKeys.size()); - for (size_t i = 0; i < keys.size(); i++) { - EXPECT_EQ(keys[i], kvKeys[i].ToString()); - } -} - -/** - * @tc.name: ToResultSetBridge_NullResultSet_ReturnsNull - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToResultSetBridge_NullResultSet_ReturnsNull, TestSize.Level0) -{ - ZLOGI("ToResultSetBridge_NullResultSet_ReturnsNull begin."); - std::shared_ptr nullResultSet = nullptr; - auto result = KvUtils::ToResultSetBridge(nullResultSet); - EXPECT_EQ(result, nullptr); -} - -/** - * @tc.name: ToResultSetBridge_ValidResultSet_ReturnsBridge - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToResultSetBridge_ValidResultSet_ReturnsBridge, TestSize.Level0) -{ - ZLOGI("ToResultSetBridge_ValidResultSet_ReturnsBridge begin."); - auto result = KvUtils::ToResultSetBridge(resultSet); - EXPECT_NE(result, nullptr); -} - -/** - * @tc.name: ToQuery_ValidOperations_Success - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToQuery_ValidOperations_Success, TestSize.Level0) -{ - ZLOGI("ToQuery_ValidOperations_Success begin."); - predicates->AddOperation({IN_KEY, {"key1", "key2"}}); - Status status = KvUtils::ToQuery(*predicates, *query); - EXPECT_EQ(status, Status::SUCCESS); -} - -/** - * @tc.name: ToQuery_InvalidOperation_NotSupport - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToQuery_InvalidOperation_NotSupport, TestSize.Level0) -{ - ZLOGI("ToQuery_InvalidOperation_NotSupport begin."); - predicates->AddOperation({-1, {}}); - Status status = KvUtils::ToQuery(*predicates, *query); - EXPECT_EQ(status, Status::NOT_SUPPORT); -} - -/** - * @tc.name: ToEntries_EmptyBuckets_ReturnsEmpty - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToEntries_EmptyBuckets_ReturnsEmpty, TestSize.Level0) -{ - ZLOGI("ToEntries_EmptyBuckets_ReturnsEmpty begin."); - std::vector emptyBuckets; - auto entries = KvUtils::ToEntries(emptyBuckets); - EXPECT_TRUE(entries.empty()); -} - -/** - * @tc.name: ToEntries_NonEmptyBuckets_ReturnsEntries - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToEntries_NonEmptyBuckets_ReturnsEntries, TestSize.Level0) -{ - ZLOGI("ToEntries_NonEmptyBuckets_ReturnsEntries begin."); - DataShareValuesBucket bucket; - bucket.valuesMap = {{"key", "value"}}; - std::vector buckets = {bucket}; - auto entries = KvUtils::ToEntries(buckets); - EXPECT_EQ(entries.size(), 1); -} - -/** - * @tc.name: ToEntry_EmptyValuesMap_ReturnsEmptyEntry - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToEntries_NonEmptyBuckets_ReturnsEntries, TestSize.Level0) -{ - ZLOGI("ToEntries_NonEmptyBuckets_ReturnsEntries begin."); - DataShareValuesBucket bucket; - Entry entry = KvUtils::ToEntry(bucket); - EXPECT_TRUE(entry.key.empty()); - EXPECT_TRUE(entry.value.empty()); -} - -/** - * @tc.name: ToEntry_NonEmptyValuesMap_ReturnsEntry - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToEntry_NonEmptyValuesMap_ReturnsEntry, TestSize.Level0) -{ - ZLOGI("ToEntry_NonEmptyValuesMap_ReturnsEntry begin."); - DataShareValuesBucket bucket; - bucket.valuesMap = {{"key", "value"}}; - Entry entry = KvUtils::ToEntry(bucket); - EXPECT_FALSE(entry.key.empty()); - EXPECT_FALSE(entry.value.empty()); -} - -/** - * @tc.name: GetKeys_EmptyOperations_ReturnsError - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, GetKeys_EmptyOperations_ReturnsError, TestSize.Level0) -{ - ZLOGI("GetKeys_EmptyOperations_ReturnsError begin."); - std::vector keys; - Status status = KvUtils::GetKeys(*predicates, keys); - EXPECT_EQ(status, Status::ERROR); -} - -/** - * @tc.name: GetKeys_ValidInKeyOperation_Success - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, GetKeys_ValidInKeyOperation_Success, TestSize.Level0) -{ - ZLOGI("GetKeys_ValidInKeyOperation_Success begin."); - predicates->AddOperation({IN_KEY, {"key1", "key2"}}); - std::vector keys; - Status status = KvUtils::GetKeys(*predicates, keys); - EXPECT_EQ(status, Status::SUCCESS); - EXPECT_EQ(keys.size(), 2); -} - -/** - * @tc.name: GetKeys_InvalidOperation_NotSupport - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, GetKeys_InvalidOperation_NotSupport, TestSize.Level0) -{ - ZLOGI("GetKeys_InvalidOperation_NotSupport begin."); - predicates->AddOperation({-1, {}}); - std::vector keys; - Status status = KvUtils::GetKeys(*predicates, keys); - EXPECT_EQ(status, Status::NOT_SUPPORT); -} - -/** - * @tc.name: ToEntryKey_ValidKey_Success - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToEntryKey_ValidKey_Success, TestSize.Level0) -{ - ZLOGI("ToEntryKey_ValidKey_Success begin."); - std::map values = {{"key", "value"}}; - Blob blob; - Status status = KvUtils::ToEntryKey(values, blob); - EXPECT_EQ(status, Status::SUCCESS); -} - -/** - * @tc.name: ToEntryKey_MissingKey_Error - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToEntryKey_MissingKey_Error, TestSize.Level0) -{ - ZLOGI("ToEntryKey_MissingKey_Error begin."); - std::map values = {{"otherKey", "value"}}; - Blob blob; - Status status = KvUtils::ToEntryKey(values, blob); - EXPECT_EQ(status, Status::ERROR); -} - -/** - * @tc.name: ToEntryValue_ValidValue_Success - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToEntryValue_ValidValue_Success, TestSize.Level0) -{ - ZLOGI("ToEntryValue_ValidValue_Success begin."); - std::map values = {{"value", "value"}}; - Blob blob; - Status status = KvUtils::ToEntryValue(values, blob); - EXPECT_EQ(status, Status::SUCCESS); -} - -/** - * @tc.name: ToEntryValue_MissingValue_Error - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToEntryValue_MissingValue_Error, TestSize.Level0) -{ - ZLOGI("ToEntryValue_MissingValue_Error begin."); - std::map values = {{"otherValue", "value"}}; - Blob blob; - Status status = KvUtils::ToEntryValue(values, blob); - EXPECT_EQ(status, Status::ERROR); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/kvdb_notifier_virtual_test.cpp b/kv_store/databaseutils/test/kvdb_notifier_virtual_test.cpp deleted file mode 100644 index 06ca65e763eed4224723d4bcd7a8cc61639378de..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/kvdb_notifier_virtual_test.cpp +++ /dev/null @@ -1,397 +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. - */ -#define LOG_TAG "KVDBNotifierVirtualTest" - -#include -#include -#include -#include -#include -#include "kvdb_notifier_client.h" -#include "kvdb_sync_callback.h" -#include "kv_store_observer.h" -#include "kvdb_notifier_stub.h" -#include "message_parcel.h" -#include "types.h" -#include "dev_manager.h" -#include "dds_trace.h" -#include "store_util.h" - -using namespace OHOS::DistributedKv; -using namespace testing; -using namespace testing::ext; -namespace OHOS::Test { -class KVDBNotifierClientVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void KVDBNotifierClientVirtualTest::SetUpTestCase(void) -{} - -void KVDBNotifierClientVirtualTest::TearDownTestCase(void) -{} - -void KVDBNotifierClientVirtualTest::SetUp(void) -{} - -void KVDBNotifierClientVirtualTest::TearDown(void) -{} - -class MockDevManager : public DevManager { -public: - string ToUUID(const string &device) override - { - if (device == "device1") { - return "uuid1"; - } - return ""; - } -}; - -class MockKvStoreSyncCallback : public KvStoreSyncCallback { -public: - void SyncCompleted(const map &results) override - { - syncCompletedCalled = true; - } - void SyncCompleted(const map &results, uint64_t sequenceId) override - { - syncCompletedWithIdCalled = true; - } - bool syncCompletedCalled = false; - bool syncCompletedWithIdCalled = false; -}; - -class MockKvStoreObserver : public KvStoreObserver { -public: - void OnSwitchChange(const SwitchNotification ¬ification) override - { - onSwitchChangeCalled = true; - } - bool onSwitchChangeCalled = false; -}; - -class MockAsyncDetail : public AsyncDetail { -public: - void operator()(ProgressDetail &&detail) override - { - asyncDetailCalled = true; - } - bool asyncDetailCalled = false; -}; - -class KVDBNotifierClientTest : public testing::Test { -protected: - void SetUp() override - { - devManager = make_shared(); - notifierClient = make_unique(); - } - - shared_ptr devManager; - unique_ptr notifierClient; -}; - -class KVDBNotifierStubVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void KVDBNotifierStubVirtualTest::SetUpTestCase(void) -{} - -void KVDBNotifierStubVirtualTest::TearDownTestCase(void) -{} - -void KVDBNotifierStubVirtualTest::SetUp(void) -{} - -void KVDBNotifierStubVirtualTest::TearDown(void) -{} - -/** - * @tc.name: SyncCompleted_CallbackFound_CallbackInvoked - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, SyncCompleted_CallbackFound_CallbackInvoked, TestSize.Level0) -{ - ZLOGI("SyncCompleted_CallbackFound_CallbackInvoked begin."); - uint64_t sequenceId = 1; - auto callback = make_shared(); - notifierClient->AddSyncCallback(callback, sequenceId); - - notifierClient->SyncCompleted({}, sequenceId); - - EXPECT_TRUE(callback->syncCompletedCalled); - EXPECT_TRUE(callback->syncCompletedWithIdCalled); -} - -/** - * @tc.name: SyncCompleted_CallbackNotFound_NoInvocation - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, SyncCompleted_CallbackNotFound_NoInvocation, TestSize.Level0) -{ - ZLOGI("SyncCompleted_CallbackNotFound_NoInvocation begin."); - uint64_t sequenceId = 1; - notifierClient->SyncCompleted({}, sequenceId); - // No callback added, so no invocation should happen -} - -/** - * @tc.name: OnRemoteChange_DeviceToUUID_RemoteUpdated - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, OnRemoteChange_DeviceToUUID_RemoteUpdated, TestSize.Level0) -{ - ZLOGI("OnRemoteChange_DeviceToUUID_RemoteUpdated begin."); - map mask = {{"device1", true}}; - notifierClient->OnRemoteChange(mask, static_cast(DataType::TYPE_STATICS)); - - // Check if the remote is updated - auto [exist, value] = notifierClient->remotes_.Find("uuid1"); - EXPECT_TRUE(exist); - EXPECT_TRUE(value.first); -} - -/** - * @tc.name: IsChanged_DeviceExists_ReturnsCorrectStatus - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, IsChanged_DeviceExists_ReturnsCorrectStatus, TestSize.Level0) -{ - ZLOGI("IsChanged_DeviceExists_ReturnsCorrectStatus begin."); - notifierClient->remotes_.InsertOrAssign("uuid1", make_pair(true, false)); - - EXPECT_TRUE(notifierClient->IsChanged("uuid1", DataType::TYPE_STATICS)); - EXPECT_FALSE(notifierClient->IsChanged("uuid1", DataType::TYPE_DYNAMICAL)); -} - -/** - * @tc.name: AddSyncCallback_NullCallback_NoAddition - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, AddSyncCallback_NullCallback_NoAddition, TestSize.Level0) -{ - ZLOGI("AddSyncCallback_NullCallback_NoAddition begin."); - uint64_t sequenceId = 1; - notifierClient->AddSyncCallback(nullptr, sequenceId); - - // No callback should be added - EXPECT_FALSE(notifierClient->syncCallbackInfo_.Find(sequenceId).first); -} - -/** - * @tc.name: AddCloudSyncCallback_NullCallback_NoAddition - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, AddCloudSyncCallback_NullCallback_NoAddition, TestSize.Level0) -{ - ZLOGI("AddCloudSyncCallback_NullCallback_NoAddition begin."); - uint64_t sequenceId = 1; - notifierClient->AddCloudSyncCallback(sequenceId, nullptr); - - // No callback should be added - EXPECT_FALSE(notifierClient->cloudSyncCallbacks_.Find(sequenceId).first); -} - -/** - * @tc.name: AddSwitchCallback_NullObserver_NoAddition - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, AddSwitchCallback_NullObserver_NoAddition, TestSize.Level0) -{ - ZLOGI("AddSwitchCallback_NullObserver_NoAddition begin."); - notifierClient->AddSwitchCallback("appId", nullptr); - - // No observer should be added - EXPECT_EQ(notifierClient->switchObservers_.Size(), 0); -} - -/** - * @tc.name: AddSwitchCallback_DuplicateObserver_NoAddition - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, AddSwitchCallback_DuplicateObserver_NoAddition, TestSize.Level0) -{ - ZLOGI("AddSwitchCallback_DuplicateObserver_NoAddition begin."); - auto observer = make_shared(); - notifierClient->AddSwitchCallback("appId", observer); - notifierClient->AddSwitchCallback("appId", observer); - - // Only one observer should be added - EXPECT_EQ(notifierClient->switchObservers_.Size(), 1); -} - -/** - * @tc.name: OnSwitchChange_ObserversNotified - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, OnSwitchChange_ObserversNotified, TestSize.Level0) -{ - ZLOGI("OnSwitchChange_ObserversNotified begin."); - auto observer = make_shared(); - notifierClient->AddSwitchCallback("appId", observer); - - SwitchNotification notification; - notifierClient->OnSwitchChange(notification); - - EXPECT_TRUE(observer->onSwitchChangeCalled); -} - -/** - * @tc.name: OnRemoteRequest_ValidCodeAndDescriptor_ShouldInvokeHandler - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierStubVirtualTest, OnRemoteRequest_ValidCodeAndDescriptor_ShouldInvokeHandler, TestSize.Level0) -{ - ZLOGI("OnRemoteRequest_ValidCodeAndDescriptor_ShouldInvokeHandler begin."); - MessageParcel data; - MessageParcel reply; - MessageOption option; - data.WriteInterfaceToken(KVDBNotifierStub::GetDescriptor()); - data.WriteInt32(1); // 假设这是有效的数据 - - EXPECT_CALL(*stub, OnSyncCompleted(testing::Ref(data), testing::_)).WillOnce(testing::Return(ERR_NONE)); - - int32_t result = - stub->OnRemoteRequest(static_cast(KVDBNotifierCode::SYNC_COMPLETED), data, reply, option); - EXPECT_EQ(result, ERR_NONE); -} - -/** - * @tc.name: OnRemoteRequest_InvalidDescriptor_ShouldReturnError - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierStubVirtualTest, OnRemoteRequest_InvalidDescriptor_ShouldReturnError, TestSize.Level0) -{ - ZLOGI("OnRemoteRequest_InvalidDescriptor_ShouldReturnError begin."); - MessageParcel data; - MessageParcel reply; - MessageOption option; - data.WriteInterfaceToken(u"InvalidDescriptor"); - - int32_t result = - stub->OnRemoteRequest(static_cast(KVDBNotifierCode::SYNC_COMPLETED), data, reply, option); - EXPECT_EQ(result, -1); -} - -/** - * @tc.name: OnRemoteRequest_CodeOutOfBound_ShouldReturnError - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierStubVirtualTest, OnRemoteRequest_CodeOutOfBound_ShouldReturnError, TestSize.Level0) -{ - ZLOGI("OnRemoteRequest_CodeOutOfBound_ShouldReturnError begin."); - MessageParcel data; - MessageParcel reply; - MessageOption option; - data.WriteInterfaceToken(KVDBNotifierStub::GetDescriptor()); - - int32_t result = - stub->OnRemoteRequest(static_cast(KVDBNotifierCode::TRANS_BUTT), data, reply, option); - EXPECT_EQ(result, - IPCObjectStub::OnRemoteRequest(static_cast(KVDBNotifierCode::TRANS_BUTT), data, reply, option)); -} - -/** - * @tc.name: OnSyncCompleted_ValidData_ShouldInvokeSyncCompleted - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierStubVirtualTest, OnSyncCompleted_ValidData_ShouldInvokeSyncCompleted, TestSize.Level0) -{ - ZLOGI("OnSyncCompleted_ValidData_ShouldInvokeSyncCompleted begin."); - MessageParcel data; - MessageParcel reply; - std::map results = {{"key", Status::SUCCESS}}; - uint64_t sequenceId = 12345; - - EXPECT_CALL(ITypesUtil, Unmarshal(testing::Ref(data), testing::Ref(results), testing::Ref(sequenceId))) - .WillOnce(testing::Return(true)); - - EXPECT_CALL(*stub, SyncCompleted(testing::_, sequenceId)).Times(1); - - int32_t result = stub->OnSyncCompleted(data, reply); - EXPECT_EQ(result, ERR_NONE); -} - -/** - * @tc.name: OnSyncCompleted_InvalidData_ShouldReturnError - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierStubVirtualTest, OnSyncCompleted_InvalidData_ShouldReturnError, TestSize.Level0) -{ - ZLOGI("OnSyncCompleted_InvalidData_ShouldReturnError begin."); - MessageParcel data; - MessageParcel reply; - std::map results; - uint64_t sequenceId = 0; - - EXPECT_CALL(ITypesUtil, Unmarshal(testing::Ref(data), testing::Ref(results), testing::Ref(sequenceId))) - .WillOnce(testing::Return(false)); - - int32_t result = stub->OnSyncCompleted(data, reply); - EXPECT_EQ(result, IPC_STUB_INVALID_DATA_ERR); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/kvstore_datashare_bridge_virtual_test.cpp b/kv_store/databaseutils/test/kvstore_datashare_bridge_virtual_test.cpp deleted file mode 100644 index 659251ec58a21fdc37a53ec55fd41259436382be..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/kvstore_datashare_bridge_virtual_test.cpp +++ /dev/null @@ -1,740 +0,0 @@ -/* - * Copyright (c) 2022 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 "KvstoreDatashareBridgeVirtualTest" - -#include "distributed_kv_data_manager.h" -#include "gtest/gtest.h" -#include "kv_utils.h" -#include -#include -#include "kvstore_datashare_bridge.h" -#include "kvstore_result_set.h" -#include "result_set_bridge.h" -#include "store_errno.h" -#include "types.h" -#include "kvstore_observer_client.h" -#include "kvstore_observer.h" -#include "log_print.h" -#include -#include -#include -#include "kvstore_service_death_notifier.h" -#include "if_system_ability_manager.h" -#include "iservice_registry.h" -#include "kvstore_client_death_observer.h" -#include "datamgr_service_proxy.h" -#include "refbase.h" -#include "system_ability_definition.h" -#include "task_executor.h" - -using namespace testing::ext; -using namespace OHOS::DistributedKv; -using namespace OHOS::DataShare; -namespace OHOS::Test { -class BridgeWriterVirtual final : public ResultSetBridge::Writer { -public: - int AllocRow() override; - int WriteVirtual(uint32_t column) override; - int WriteVirtual(uint32_t column, int64_t value) override; - int WriteVirtual(uint32_t column, double value) override; - int WriteVirtual(uint32_t column, const uint8_t *value, size_t size) override; - int WriteVirtual(uint32_t column, const char *value, size_t size) override; - void SetAllocRowStatue(int status); - Key GetKey() const; - Key GetValue() const; - -private: - int allocStatus_Virtual = E_OK; - std::vector key_Virtual; - std::vector value_Virtual; -}; - -void BridgeWriterVirtual::SetAllocRowStatue(int status) -{ - allocStatus_Virtual = status; -} - -Key BridgeWriterVirtual::GetKey() const -{ - return key_Virtual; -} - -Value BridgeWriterVirtual::GetValue() const -{ - return value_Virtual; -} - -int BridgeWriterVirtual::AllocRow() -{ - return allocStatus_Virtual; -} - -int BridgeWriterVirtual::WriteVirtual(uint32_t column) -{ - return E_OK; -} - -int BridgeWriterVirtual::WriteVirtual(uint32_t column, int64_t value) -{ - return E_OK; -} - -int BridgeWriterVirtual::WriteVirtual(uint32_t column, double value) -{ - return E_OK; -} - -int BridgeWriterVirtual::WriteVirtual(uint32_t column, const uint8_t *value, size_t size) -{ - return E_OK; -} - -int BridgeWriterVirtual::WriteVirtual(uint32_t column, const char *value, size_t size) -{ - if (column < 0 || column > 1 || value == nullptr) { - return E_ERROR; - } - auto vec = std::vector(value, value + size - 1); - if (column == 0) { - key_Virtual.insert(key_Virtual.end(), vec.begin(), vec.end()); - } else { - value_Virtual.insert(value_Virtual.end(), vec.begin(), vec.end()); - } - return E_OK; -} - -class KvstoreDatashareBridgeVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp() {} - void TearDown() {} - -protected: - static DistributedKvDataManager managerVirtual; - static std::shared_ptr singleKvStoreVirtual; -}; -std::shared_ptr KvstoreDatashareBridgeVirtualTest::singleKvStoreVirtual = nullptr; -DistributedKvDataManager KvstoreDatashareBridgeVirtualTest::managerVirtual; -static constexpr int32_t INVALID_COUNT = -1; -static constexpr const char *VALID_SCHEMA_STRICT_DEFINE = "{\"SCHEMA_VERSION\":\"1.0\"," - "\"SCHEMA_MODE\":\"STRICT\"," - "\"SCHEMA_SKIPSIZE\":0," - "\"SCHEMA_DEFINE\":{" - "\"age\":\"INTEGER, NOT NULL\"" - "}," - "\"SCHEMA_INDEXES\":[\"$.age\"]}"; - -void KvstoreDatashareBridgeVirtualTest::SetUpTestCase(void) -{ - Options options = { .createIfMissing = true, .encrypt = false, .autoSync = false, - .kvStoreType = KvStoreType::SINGLE_VERSION, .schema = VALID_SCHEMA_STRICT_DEFINE }; - options.area = EL1; - options.securityLevel = S1; - options.baseDir = std::string("/data/service/el1/public/database/KvstoreDatashareBridgeVirtualTest"); - AppId appId = { "KvstoreDatashareBridgeVirtualTest" }; - StoreId storeId = { "test_single" }; - mkdir(options.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); - managerVirtual.DeleteKvStore(appId, storeId, options.baseDir); - managerVirtual.GetSingleKvStore(options, appId, storeId, singleKvStoreVirtual); - EXPECT_NE(singleKvStoreVirtual, nullptr); - singleKvStoreVirtual->Put("test_key_1", "{\"age\":1}"); - singleKvStoreVirtual->Put("test_key_2", "{\"age\":2}"); - singleKvStoreVirtual->Put("test_key_3", "{\"age\":3}"); - singleKvStoreVirtual->Put("data_share", "{\"age\":4}"); -} - -void KvstoreDatashareBridgeVirtualTest::TearDownTestCase(void) -{ - managerVirtual.DeleteKvStore({"KvstoreDatashareBridgeVirtualTest"}, {"test_single"}, - "/data/service/el1/public/database/KvstoreDatashareBridgeVirtualTest"); - (void) remove("/data/service/el1/public/database/KvstoreDatashareBridgeVirtualTest/key"); - (void) remove("/data/service/el1/public/database/KvstoreDatashareBridgeVirtualTest/kvdb"); - (void) remove("/data/service/el1/public/database/KvstoreDatashareBridgeVirtualTest"); -} - -class MockKvStoreResultSet : public KvStoreResultSet { -public: - explicit MockKvStoreResultSet(int count) : count_(count) - { - } - - int GetCount() override - { - return count_; - } - - bool MoveToPosition(int pos) override - { - return pos >= 0 && pos < count_; - } - - Status GetEntry(Entry &entry) override - { - if (pos_ >= 0 && pos_ < count_) { - entry.key = Key("key" + std::to_string(pos_)); - entry.value = Value("value" + std::to_string(pos_)); - return Status::SUCCESS; - } - return Status::ERROR; - } - -private: - int count_; - int pos_ = -1; -}; - -class MockWriter : public ResultSetBridge::Writer { -public: - int AllocRow() override - { - return E_OK; - } - - int Write(int index, const char *data, int size) override - { - return E_OK; - } -}; - -class KvStoreObserverClientVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void KvStoreObserverClientVirtualTest::SetUpTestCase(void) -{} - -void KvStoreObserverClientVirtualTest::TearDownTestCase(void) -{} - -void KvStoreObserverClientVirtualTest::SetUp(void) -{} - -void KvStoreObserverClientVirtualTest::TearDown(void) -{} - -class MockKvStoreObserver : public KvStoreObserver { -public: - MOCK_METHOD1(OnChange, void(const ChangeNotification &changeNotification)); - MOCK_METHOD2(OnChange, void(const DataOrigin &origin, IKvStoreObserver::Keys &&keys)); -}; - -class KvStoreServiceDeathNotifierVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void KvStoreServiceDeathNotifierVirtualTest::SetUpTestCase(void) -{} - -void KvStoreServiceDeathNotifierVirtualTest::TearDownTestCase(void) -{} - -void KvStoreServiceDeathNotifierVirtualTest::SetUp(void) -{} - -void KvStoreServiceDeathNotifierVirtualTest::TearDown(void) -{} - -class MockSystemAbilityManager : public SystemAbilityManager { -public: - MOCK_METHOD(sptr, CheckSystemAbility, (int32_t), (override)); -}; - -class MockTaskExecutor : public TaskExecutor { -public: - MOCK_METHOD(void, Execute, (std::function), (override)); -}; - -class MockKvStoreDeathRecipient : public KvStoreDeathRecipient { -public: - MOCK_METHOD(void, OnRemoteDied, (), (override)); -}; - -class SyncObserverVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void SyncObserverVirtualTest::SetUpTestCase(void) -{} - -void SyncObserverVirtualTest::TearDownTestCase(void) -{} - -void SyncObserverVirtualTest::SetUp(void) -{} - -void SyncObserverVirtualTest::TearDown(void) -{} - -class MockKvStoreSyncCallback : public KvStoreSyncCallback { -public: - MOCK_METHOD1(SyncCompleted, void(const std::map &results)); -}; - -/** -* @tc.name: SyncCompleted_EmptyCallbacks_NoException -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(MockKvStoreSyncCallback, SyncCompleted_EmptyCallbacks_NoException, TestSize.Level0) -{ - ZLOGI("SyncCompleted_EmptyCallbacks_NoException begin."); - SyncObserver observer; - std::map results; - EXPECT_NO_THROW(observer.SyncCompleted(results)); -} - -/** -* @tc.name: SyncCompleted_NonEmptyCallbacks_CallbacksInvoked -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(MockKvStoreSyncCallback, SyncCompleted_NonEmptyCallbacks_CallbacksInvoked, TestSize.Level0) -{ - ZLOGI("SyncCompleted_NonEmptyCallbacks_CallbacksInvoked begin."); - SyncObserver observer; - auto mockCallback = std::make_shared(); - observer.Add(mockCallback); - - std::map results = {{"key1", Status::SUCCESS}}; - EXPECT_CALL(*mockCallback, SyncCompleted(results)).Times(1); - - observer.SyncCompleted(results); -} - -/** -* @tc.name: GetDistributedKvDataService_ProxyExists_ReturnsProxy -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreServiceDeathNotifierVirtualTest, GetDistributedKvDataService_ProxyExists_ReturnsProxy, TestSize.Level0) -{ - ZLOGI("GetDistributedKvDataService_ProxyExists_ReturnsProxy begin."); - auto &instance = KvStoreServiceDeathNotifier::GetInstance(); - instance.kvDataServiceProxy_ = new DataMgrServiceProxy(nullptr); - - auto proxy = instance.GetDistributedKvDataService(); - - EXPECT_EQ(proxy, instance.kvDataServiceProxy_); -} - -/** -* @tc.name: GetDistributedKvDataService_ProxyDoesNotExist -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreServiceDeathNotifierVirtualTest, GetDistributedKvDataService_ProxyDoesNotExist, TestSize.Level0) -{ - ZLOGI("GetDistributedKvDataService_ProxyDoesNotExist begin."); - auto &instance = KvStoreServiceDeathNotifier::GetInstance(); - instance.kvDataServiceProxy_ = nullptr; - - auto samgr = std::dynamic_pointer_cast( - SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager()); - auto remote = sptr(new RemoteObject("test")); - EXPECT_CALL(*samgr, CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID)).WillOnce(testing::Return(remote)); - - auto proxy = instance.GetDistributedKvDataService(); - - EXPECT_NE(proxy, nullptr); - EXPECT_NE(instance.kvDataServiceProxy_, nullptr); -} - -/** -* @tc.name: RegisterClientDeathObserver_ProxyExists -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreServiceDeathNotifierVirtualTest, RegisterClientDeathObserver_ProxyExists, TestSize.Level0) -{ - ZLOGI("RegisterClientDeathObserver_ProxyExists begin."); - auto &instance = KvStoreServiceDeathNotifier::GetInstance(); - instance.kvDataServiceProxy_ = new DataMgrServiceProxy(nullptr); - - instance.RegisterClientDeathObserver(); - - EXPECT_NE(instance.clientDeathObserverPtr_, nullptr); -} - -/** -* @tc.name: AddServiceDeathWatcher_Success_AddsWatcher -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreServiceDeathNotifierVirtualTest, AddServiceDeathWatcher_Success_AddsWatcher, TestSize.Level0) -{ - ZLOGI("AddServiceDeathWatcher_Success_AddsWatcher begin."); - auto &instance = KvStoreServiceDeathNotifier::GetInstance(); - auto watcher = std::make_shared(); - - instance.AddServiceDeathWatcher(watcher); - - EXPECT_EQ(instance.serviceDeathWatchers_.size(), 1); -} - -/** -* @tc.name: RemoveServiceDeathWatcher_Found_RemovesWatcher -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreServiceDeathNotifierVirtualTest, RemoveServiceDeathWatcher_Found_RemovesWatcher, TestSize.Level0) -{ - ZLOGI("RemoveServiceDeathWatcher_Found_RemovesWatcher begin."); - auto &instance = KvStoreServiceDeathNotifier::GetInstance(); - auto watcher = std::make_shared(); - instance.serviceDeathWatchers_.insert(watcher); - - instance.RemoveServiceDeathWatcher(watcher); - - EXPECT_EQ(instance.serviceDeathWatchers_.size(), 0); -} - -/** -* @tc.name: ServiceDeathRecipient_OnRemoteDied_NotifiesWatchers -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreServiceDeathNotifierVirtualTest, ServiceDeathRecipient_OnRemoteDied_NotifiesWatchers, TestSize.Level0) -{ - ZLOGI("ServiceDeathRecipient_OnRemoteDied_NotifiesWatchers begin."); - auto &instance = KvStoreServiceDeathNotifier::GetInstance(); - auto watcher = std::make_shared(); - instance.serviceDeathWatchers_.insert(watcher); - - auto executor = std::dynamic_pointer_cast(TaskExecutor::GetInstance().GetExecutor()); - EXPECT_CALL(*executor, Execute(testing::_)).WillOnce(testing::Invoke([](std::function task) { - task(); - })); - - instance.ServiceDeathRecipient().OnRemoteDied(nullptr); - - EXPECT_CALL(*watcher, OnRemoteDied()).Times(1); -} - -/** -* @tc.name: OnChange_ChangeNotification_KvStoreObserverNotNull -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreObserverClientVirtualTest, OnChange_ChangeNotification_KvStoreObserverNotNull, TestSize.Level0) -{ - ZLOGI("OnChange_ChangeNotification_KvStoreObserverNotNull begin."); - ChangeNotification changeNotification; - EXPECT_CALL(*kvStoreObserver, OnChange(Ref(changeNotification))); - kvStoreObserverClient->OnChange(changeNotification); -} - -/** -* @tc.name: OnChange_ChangeNotification_KvStoreObserverNull -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreObserverClientVirtualTest, OnChange_ChangeNotification_KvStoreObserverNull, TestSize.Level0) -{ - ZLOGI("OnChange_ChangeNotification_KvStoreObserverNull begin."); - kvStoreObserverClient = std::make_shared(nullptr); - ChangeNotification changeNotification; - EXPECT_CALL(*kvStoreObserver, OnChange(Ref(changeNotification))).Times(0); - kvStoreObserverClient->OnChange(changeNotification); -} - -/** -* @tc.name: OnChange_DataOriginAndKeys_KvStoreObserverNotNull -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreObserverClientVirtualTest, OnChange_DataOriginAndKeys_KvStoreObserverNotNull, TestSize.Level0) -{ - ZLOGI("OnChange_DataOriginAndKeys_KvStoreObserverNotNull begin."); - DataOrigin origin; - IKvStoreObserver::Keys keys; - EXPECT_CALL(*kvStoreObserver, OnChange(Ref(origin), Ref(keys))); - kvStoreObserverClient->OnChange(origin, std::move(keys)); -} - -/** -* @tc.name: OnChange_DataOriginAndKeys_KvStoreObserverNull -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreObserverClientVirtualTest, OnChange_DataOriginAndKeys_KvStoreObserverNull, TestSize.Level0) -{ - ZLOGI("OnChange_DataOriginAndKeys_KvStoreObserverNull begin."); - kvStoreObserverClient = std::make_shared(nullptr); - DataOrigin origin; - IKvStoreObserver::Keys keys; - EXPECT_CALL(*kvStoreObserver, OnChange(Ref(origin), Ref(keys))).Times(0); - kvStoreObserverClient->OnChange(origin, std::move(keys)); -} - -/** -* @tc.name: GetRowCountByInvalidBridge -* @tc.desc: get row countVirtual, the kvStore resultSetVirtual is nullptr -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, GetRowCountByInvalidBridge, TestSize.Level0) -{ - ZLOGI("GetRowCountByInvalidBridge begin."); - auto bridgeVirtual = std::make_shared(nullptr); - int32_t countVirtual; - auto resultVirtual = bridgeVirtual->GetRowCount(countVirtual); - EXPECT_EQ(resultVirtual, E_ERROR); - EXPECT_EQ(countVirtual, INVALID_COUNT); - std::vector columnNames; - resultVirtual = bridgeVirtual->GetAllColumnNames(columnNames); - EXPECT_FALSE(columnNames.empty()); - EXPECT_EQ(resultVirtual, E_OK); -} - -/** -* @tc.name: KvStoreResultSetToDataShareResultSetAbnormal -* @tc.desc: kvStore resultSetVirtual to dataShare resultSetVirtual, the former has invalid predicate -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, KvStoreResultSetToDataShareResultSetAbnormal, TestSize.Level0) -{ - ZLOGI("KvStoreResultSetToDataShareResultSetAbnormal begin."); - std::shared_ptr resultSetVirtual = nullptr; - DataQuery queryVirtual; - queryVirtual.KeyPrefix("key"); - singleKvStoreVirtual->GetResultSet(queryVirtual, resultSetVirtual); - EXPECT_NE(resultSetVirtual, nullptr); - auto bridgeVirtual = KvUtils::ToResultSetBridge(resultSetVirtual); - int32_t countVirtual; - auto resultVirtual = bridgeVirtual->GetRowCount(countVirtual); - EXPECT_EQ(resultVirtual, E_OK); - EXPECT_EQ(countVirtual, 0); -} - -/** -* @tc.name: KvStoreResultSetToDataShareResultSetNormal -* @tc.desc: kvStore resultSetVirtual to dataShare resultSetVirtual, the former has valid predicate -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, KvStoreResultSetToDataShareResultSetNormal, TestSize.Level0) -{ - ZLOGI("KvStoreResultSetToDataShareResultSetNormal begin."); - DataQuery queryVirtual; - queryVirtual.KeyPrefix("test"); - std::shared_ptr resultSetVirtual = nullptr; - singleKvStoreVirtual->GetResultSet(queryVirtual, resultSetVirtual); - EXPECT_NE(resultSetVirtual, nullptr); - auto bridgeVirtual = KvUtils::ToResultSetBridge(resultSetVirtual); - int32_t countVirtual; - auto resultVirtual = bridgeVirtual->GetRowCount(countVirtual); - EXPECT_EQ(resultVirtual, E_OK); - EXPECT_EQ(countVirtual, 3); - countVirtual = -1; - bridgeVirtual->GetRowCount(countVirtual); - EXPECT_EQ(countVirtual, 3); -} - -/** -* @tc.name: BridgeOnGoAbnormal -* @tc.desc: bridgeVirtual on go, the input parameter is invalid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, BridgeOnGoAbnormal, TestSize.Level0) -{ - ZLOGI("BridgeOnGoAbnormal begin."); - DataQuery queryVirtual; - queryVirtual.KeyPrefix("test"); - std::shared_ptr resultSetVirtual = nullptr; - singleKvStoreVirtual->GetResultSet(queryVirtual, resultSetVirtual); - EXPECT_NE(resultSetVirtual, nullptr); - auto bridgeVirtual = KvUtils::ToResultSetBridge(resultSetVirtual); - int32_t startVirtual = -1; - int32_t targetVirtual = 0; - BridgeWriterVirtual writerVirtual; - EXPECT_EQ(bridgeVirtual->OnGo(startVirtual, targetVirtual, writerVirtual), -1); - EXPECT_TRUE(writerVirtual.GetKey().Empty()); - EXPECT_TRUE(writerVirtual.GetValue().Empty()); - startVirtual = 0; - targetVirtual = -1; - EXPECT_EQ(bridgeVirtual->OnGo(startVirtual, targetVirtual, writerVirtual), -1); - EXPECT_TRUE(writerVirtual.GetKey().Empty()); - EXPECT_TRUE(writerVirtual.GetValue().Empty()); - startVirtual = 1; - targetVirtual = 0; - EXPECT_EQ(bridgeVirtual->OnGo(startVirtual, targetVirtual, writerVirtual), -1); - EXPECT_TRUE(writerVirtual.GetKey().Empty()); - EXPECT_TRUE(writerVirtual.GetValue().Empty()); - startVirtual = 1; - targetVirtual = 3; - EXPECT_EQ(bridgeVirtual->OnGo(startVirtual, targetVirtual, writerVirtual), -1); - EXPECT_TRUE(writerVirtual.GetKey().Empty()); - EXPECT_TRUE(writerVirtual.GetValue().Empty()); -} - -/** -* @tc.name: BridgeOnGoNormal -* @tc.desc: bridgeVirtual on go, the input parameter is valid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, BridgeOnGoNormal, TestSize.Level0) -{ - ZLOGI("BridgeOnGoNormal begin."); - DataQuery queryVirtual; - queryVirtual.KeyPrefix("test"); - std::shared_ptr resultSetVirtual = nullptr; - singleKvStoreVirtual->GetResultSet(queryVirtual, resultSetVirtual); - EXPECT_NE(resultSetVirtual, nullptr); - auto bridgeVirtual = KvUtils::ToResultSetBridge(resultSetVirtual); - int startVirtual = 0; - int targetVirtual = 2; - BridgeWriterVirtual writerVirtual; - writerVirtual.SetAllocRowStatue(E_ERROR); - EXPECT_EQ(bridgeVirtual->OnGo(startVirtual, targetVirtual, writerVirtual), -1); - EXPECT_TRUE(writerVirtual.GetKey().Empty()); - EXPECT_TRUE(writerVirtual.GetValue().Empty()); - writerVirtual.SetAllocRowStatue(E_OK); - EXPECT_EQ(bridgeVirtual->OnGo(startVirtual, targetVirtual, writerVirtual), targetVirtual); - size_t keySize = 0; - size_t valueSize = 0; - for (auto i = startVirtual; i <= targetVirtual; i++) { - resultSetVirtual->MoveToPosition(i); - Entry entry; - resultSetVirtual->GetEntry(entry); - keySize += entry.key.Size(); - valueSize += entry.value.Size(); - } - EXPECT_EQ(writerVirtual.GetKey().Size(), keySize); - EXPECT_EQ(writerVirtual.GetValue().Size(), valueSize); -} - -/** -* @tc.name: OnGo_ValidIndices_FillAllRows -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, OnGo_ValidIndices_FillAllRows, TestSize.Level0) -{ - ZLOGI("OnGo_ValidIndices_FillAllRows begin."); - MockWriter writer; - int result = bridge->OnGo(0, 5, writer); - EXPECT_EQ(result, 5); -} - -/** -* @tc.name: OnGo_InvalidStartIndex_ReturnsError -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, OnGo_InvalidStartIndex_ReturnsError, TestSize.Level0) -{ - ZLOGI("OnGo_InvalidStartIndex_ReturnsError begin."); - MockWriter writer; - int result = bridge->OnGo(-1, 5, writer); - EXPECT_EQ(result, -1); -} - -/** -* @tc.name: OnGo_InvalidTargetIndex_ReturnsError -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, OnGo_InvalidTargetIndex_ReturnsError, TestSize.Level0) -{ - ZLOGI("OnGo_InvalidTargetIndex_ReturnsError begin."); - MockWriter writer; - int result = bridge->OnGo(0, 15, writer); - EXPECT_EQ(result, -1); -} - -/** -* @tc.name: OnGo_StartGreaterThanTarget_ReturnsError -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, OnGo_StartGreaterThanTarget_ReturnsError, TestSize.Level0) -{ - ZLOGI("OnGo_StartGreaterThanTarget_ReturnsError begin."); - MockWriter writer; - int result = bridge->OnGo(5, 0, writer); - EXPECT_EQ(result, -1); -} - -/** -* @tc.name: OnGo_FillBlockFails_ReturnsPartialFill -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, OnGo_FillBlockFails_ReturnsPartialFill, TestSize.Level0) -{ - ZLOGI("OnGo_FillBlockFails_ReturnsPartialFill begin."); - kvResultSet = std::make_shared(1); - bridge = std::make_shared(kvResultSet); - - MockWriter writer; - int result = bridge->OnGo(0, 5, writer); - EXPECT_EQ(result, 0); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/local_kv_store_counterfeit_unit_test.cpp b/kv_store/databaseutils/test/local_kv_store_counterfeit_unit_test.cpp deleted file mode 100644 index 930e0e747313b2bb472ed1dc6a7bc053c1dc285e..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/local_kv_store_counterfeit_unit_test.cpp +++ /dev/null @@ -1,1962 +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. - */ -#define LOG_TAG "LocalKvStoreCounterfeitUnitTest" - -#include "block_data.h" -#include "distributed_kv_data_manager.h" -#include "log_print.h" -#include "types.h" -#include -#include -#include -#include - -using namespace testing::ext; -using namespace OHOS; -using namespace OHOS::DistributedKv; -class LocalKvStoreCounterfeitUnitTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - - static DistributedKvDataManager counterfeitTestManger_; - static std::shared_ptr counterfeitTestStore_; - static Status counterfeitTestStatus_; - static AppId counterfeitTestAppId_; - static StoreId counterfeitTestStoreId_; -}; -std::shared_ptr LocalKvStoreCounterfeitUnitTest::counterfeitTestStore_ = nullptr; -Status LocalKvStoreCounterfeitUnitTest::counterfeitTestStatus_ = Status::ERROR; -DistributedKvDataManager LocalKvStoreCounterfeitUnitTest::counterfeitTestManger_; -AppId LocalKvStoreCounterfeitUnitTest::counterfeitTestAppId_; -StoreId LocalKvStoreCounterfeitUnitTest::counterfeitTestStoreId_; - -void LocalKvStoreCounterfeitUnitTest::SetUpTestCase(void) -{ - mkdir("/data/service/el1/public/database/local", (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void LocalKvStoreCounterfeitUnitTest::TearDownTestCase(void) -{ - counterfeitTestManger_.CloseKvStore(counterfeitTestAppId_, counterfeitTestStore_); - counterfeitTestStore_ = nullptr; - counterfeitTestManger_.DeleteKvStore(counterfeitTestAppId_, - counterfeitTestStoreId_, "/data/service/el1/public/database/local"); - (void)remove("/data/service/el1/public/database/local/kvdb"); - (void)remove("/data/service/el1/public/database/local"); -} - -void LocalKvStoreCounterfeitUnitTest::SetUp(void) -{ - Options counterfeitOptions; - counterfeitOptions.securityLevel = S1; - counterfeitOptions.baseDir = std::string("/data/service/el1/public/database/local"); - counterfeitTestAppId_.appId = "local"; // define app name. - counterfeitTestStoreId_.storeId = "MAN"; // define kvstore(database) name - counterfeitTestManger_.DeleteKvStore(counterfeitTestAppId_, counterfeitTestStoreId_, counterfeitOptions.baseDir); - // [create and] open and initialize kvstore instance. - counterfeitTestStatus_ = counterfeitTestManger_.GetSingleKvStore(counterfeitOptions, - counterfeitTestAppId_, counterfeitTestStoreId_, counterfeitTestStore_); - ASSERT_EQ(Status::SUCCESS, counterfeitTestStatus_) << "wrong status"; - ASSERT_NE(nullptr, counterfeitTestStore_) << "kvStore is nullptr"; -} - -void LocalKvStoreCounterfeitUnitTest::TearDown(void) -{ - counterfeitTestManger_.CloseKvStore(counterfeitTestAppId_, counterfeitTestStore_); - counterfeitTestStore_ = nullptr; - counterfeitTestManger_.DeleteKvStore(counterfeitTestAppId_, counterfeitTestStoreId_); -} - -class DeviceObserverCounterfeitUnitTest : public KvStoreObserver { -public: - std::vector insertCounterfeitEntries_; - std::vector updateCounterfeitEntries_; - std::vector deleteCounterfeitEntries_; - std::string counterfeitDeviceId_; - bool isCounterfeitClear_ = false; - DeviceObserverCounterfeitUnitTest(); - ~DeviceObserverCounterfeitUnitTest() = default; - - void OnChange(const ChangeNotification &changeNotification); - - // reset the counterfeitCallCount_ to zero. - void ResetToZero(); - - uint32_t GetCallCount(uint32_t counterfeitTestValue = 1); - -private: - std::mutex counterfeitMutex_; - uint32_t counterfeitCallCount_ = 0; - BlockData counterfeitValue_ { 1, 0 }; -}; - -DeviceObserverCounterfeitUnitTest::DeviceObserverCounterfeitUnitTest() { } - -void DeviceObserverCounterfeitUnitTest::OnChange(const ChangeNotification &changeNotification) -{ - ZLOGD("begin."); - insertCounterfeitEntries_ = changeNotification.GetInsertEntries(); - updateCounterfeitEntries_ = changeNotification.GetUpdateEntries(); - deleteCounterfeitEntries_ = changeNotification.GetDeleteEntries(); - counterfeitDeviceId_ = changeNotification.GetDeviceId(); - isCounterfeitClear_ = changeNotification.IsClear(); - std::lock_guard guard(counterfeitMutex_); - ++counterfeitCallCount_; - counterfeitValue_.SetValue(counterfeitCallCount_); -} - -void DeviceObserverCounterfeitUnitTest::ResetToZero() -{ - std::lock_guard guard(counterfeitMutex_); - counterfeitCallCount_ = 0; - counterfeitValue_.Clear(0); -} - -uint32_t DeviceObserverCounterfeitUnitTest::GetCallCount(uint32_t counterfeitTestValue) -{ - int retryTimes = 0; - uint32_t callCount = 0; - while (retryTimes < counterfeitTestValue) { - callCount = counterfeitValue_.GetValue(); - if (callCount >= counterfeitTestValue) { - break; - } - std::lock_guard guard(counterfeitMutex_); - callCount = counterfeitValue_.GetValue(); - if (callCount >= counterfeitTestValue) { - break; - } - counterfeitValue_.Clear(callCount); - retryTimes++; - } - return callCount; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore001 - * @tc.desc: Subscribe success - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore001 begin."); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - auto counterfeitObserver = std::make_shared(); - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - counterfeitObserver = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore002 - * @tc.desc: Subscribe fail, counterfeitObserver is null - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore002 begin."); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - std::shared_ptr counterfeitObserver = nullptr; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::INVALID_ARGUMENT, counterfeitStatus) << "SubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore003 - * @tc.desc: Subscribe success and OnChange callback after put - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore003, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore003 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey = "Id1"; - Value counterfeitTestValue = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey, counterfeitTestValue); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - counterfeitObserver = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore004 - * @tc.desc: The same counterfeitObserver subscribe three times and OnChange callback after put - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore004, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore004 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey = "Id1"; - Value counterfeitTestValue = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey, counterfeitTestValue); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore005 - * @tc.desc: The different counterfeitObserver subscribe three times and OnChange callback after put - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore005, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore005 begin."); - auto observer1 = std::make_shared(); - auto observer2 = std::make_shared(); - auto observer3 = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, observer1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore failed, wrong"; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, observer2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore failed, wrong"; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, observer3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore failed, wrong"; - - Key counterfeitTestKey = "Id1"; - Value counterfeitTestValue = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey, counterfeitTestValue); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "Putting data to KvStore failed, wrong"; - ASSERT_EQ(static_cast(observer1->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer2->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer3->GetCallCount()), 1); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, observer1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, observer2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, observer3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore006 - * @tc.desc: Unsubscribe an counterfeitObserver and subscribe again - the map should be cleared after unsubscription. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore006, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore006 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - - Key counterfeitTestKey2 = "Id2"; - Value counterfeitTestValue2 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey2, counterfeitTestValue2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - - counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - Key counterfeitTestKey3 = "Id3"; - Value counterfeitTestValue3 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey3, counterfeitTestValue3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore007 - * @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is called multiple times after the put operation. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore007, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore007 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - - Key counterfeitTestKey2 = "Id2"; - Value counterfeitTestValue2 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey2, counterfeitTestValue2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - - Key counterfeitTestKey3 = "Id3"; - Value counterfeitTestValue3 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey3, counterfeitTestValue3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(3)), 3); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore008 -* @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is - called multiple times after the put&update operations. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore008, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore008 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - - Key counterfeitTestKey2 = "Id2"; - Value counterfeitTestValue2 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey2, counterfeitTestValue2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - - Key counterfeitTestKey3 = "Id1"; - Value counterfeitTestValue3 = "subscribe03"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey3, counterfeitTestValue3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(3)), 3); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore009 - * @tc.desc: Subscribe to an counterfeitObserver - OnChange - * callback is called multiple times after the putBatch operation. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore009, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore009 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - // before update. - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id4"; - counterfeitTestEnty4.counterfeitTestValue = "subscribe"; - counterfeitTestEnty5.counterfeitTestKey = "Id5"; - counterfeitTestEnty5.counterfeitTestValue = "subscribe"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore010 -* @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is - called multiple times after the putBatch update operation. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore010, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore010 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - // before update. - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id1"; - counterfeitTestEnty4.counterfeitTestValue = "modify"; - counterfeitTestEnty5.counterfeitTestKey = "Id2"; - counterfeitTestEnty5.counterfeitTestValue = "modify"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore011 - * @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is called after successful deletion. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore011, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore011 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore012 - * @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is not called after deletion of non-existing keys. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore012, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore012 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->Delete("Id4"); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore013 - * @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is called after KvStore is cleared. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore013, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore013 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore014 -* @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is - not called after non-existing data in KvStore is cleared. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore014, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore014 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore015 - * @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is called after the deleteBatch operation. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore015, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore015 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - counterfeitStatus = counterfeitTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore016 - * @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is called after deleteBatch of non-existing keys. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore016, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore016 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - std::vector keys; - keys.push_back("Id4"); - keys.push_back("Id5"); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - counterfeitStatus = counterfeitTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore020 - * @tc.desc: Unsubscribe an counterfeitObserver two times. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore020, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore020 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::STORE_NOT_SUBSCRIBE, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification001 -* @tc.desc: Subscribe to an counterfeitObserver successfully - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification001 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey = "Id1"; - Value counterfeitTestValue = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey, counterfeitTestValue); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ZLOGD("kvstore_ddm_subscribekvstore_003"); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ZLOGD("kvstore_ddm_subscribekvstore_003 size:%zu.", counterfeitObserver->insertCounterfeitEntries_.size()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification002 -* @tc.desc: Subscribe to the same counterfeitObserver three times - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification002, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification002 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey = "Id1"; - Value counterfeitTestValue = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey, counterfeitTestValue); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification003 - * @tc.desc: The different counterfeitObserver subscribe three times and callback with notification after put - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification003, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification003 begin."); - auto observer1 = std::make_shared(); - auto observer2 = std::make_shared(); - auto observer3 = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, observer1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, observer2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, observer3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey = "Id1"; - Value counterfeitTestValue = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey, counterfeitTestValue); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(observer1->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer1->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", observer1->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", observer1->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - ASSERT_EQ(static_cast(observer2->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer2->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", observer2->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", observer2->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - ASSERT_EQ(static_cast(observer3->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer3->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", observer3->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", observer3->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, observer1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, observer2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, observer3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification004 - * @tc.desc: Verify notification after an counterfeitObserver is unsubscribed and then subscribed again. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification004, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification004 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - - Key counterfeitTestKey2 = "Id2"; - Value counterfeitTestValue2 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey2, counterfeitTestValue2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - Key counterfeitTestKey3 = "Id3"; - Value counterfeitTestValue3 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey3, counterfeitTestValue3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id3", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification005 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification many times after put the different data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification005, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification005 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - Key counterfeitTestKey2 = "Id2"; - Value counterfeitTestValue2 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey2, counterfeitTestValue2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id2", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - Key counterfeitTestKey3 = "Id3"; - Value counterfeitTestValue3 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey3, counterfeitTestValue3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(3)), 3); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id3", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification006 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification many times after put the same data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification006, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification006 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - Key counterfeitTestKey2 = "Id1"; - Value counterfeitTestValue2 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey2, counterfeitTestValue2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - Key counterfeitTestKey3 = "Id1"; - Value counterfeitTestValue3 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey3, counterfeitTestValue3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(3)), 3); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification007 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification many times after put&update - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification007, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification007 begin."); - auto counterfeitObserver = std::make_shared(); - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - Status counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - - Key counterfeitTestKey2 = "Id2"; - Value counterfeitTestValue2 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey2, counterfeitTestValue2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey3 = "Id1"; - Value counterfeitTestValue3 = "subscribe03"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey3, counterfeitTestValue3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe03", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification008 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification one times after putbatch&update - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification008, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification008 begin."); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitTestEntries.clear(); - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe_modify"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe_modify"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 2); - ASSERT_EQ("Id1", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe_modify", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->updateCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe_modify", counterfeitObserver->updateCounterfeitEntries_[1].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification009 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification one times after putbatch all different data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification009, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification009 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 3); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestValue.ToString()); - ASSERT_EQ("Id3", counterfeitObserver->insertCounterfeitEntries_[2].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[2].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification010 -* @tc.desc: Subscribe to an counterfeitObserver, - callback with notification one times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification010, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification010 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id1"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id2"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 2); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestValue.ToString()); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 0); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification011 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification one times after putbatch all same data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification011, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification011 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id1"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id1"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 0); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification012 - * @tc.desc: Subscribe to an observer, callback with notification many times after putbatch all different data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification012, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id4"; - counterfeitTestEnty4.counterfeitTestValue = "subscribe"; - counterfeitTestEnty5.counterfeitTestKey = "Id5"; - counterfeitTestEnty5.counterfeitTestValue = "subscribe"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 3); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestValue.ToString()); - ASSERT_EQ("Id3", counterfeitObserver->insertCounterfeitEntries_[2].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[2].counterfeitTestValue.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification012b - * @tc.desc: Subscribe to an observer, callback with notification many times after putbatch all different data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification012b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012b begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id4"; - counterfeitTestEnty4.counterfeitTestValue = "subscribe"; - counterfeitTestEnty5.counterfeitTestKey = "Id5"; - counterfeitTestEnty5.counterfeitTestValue = "subscribe"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 2); - ASSERT_EQ("Id4", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id5", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013 -* @tc.desc: Subscribe to an counterfeitObserver, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification013, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id1"; - counterfeitTestEnty4.counterfeitTestValue = "subscribe"; - counterfeitTestEnty5.counterfeitTestKey = "Id4"; - counterfeitTestEnty5.counterfeitTestValue = "subscribe"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 3); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestValue.ToString()); - ASSERT_EQ("Id3", counterfeitObserver->insertCounterfeitEntries_[2].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[2].counterfeitTestValue.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013b -* @tc.desc: Subscribe to an counterfeitObserver, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification013b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013b begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id1"; - counterfeitTestEnty4.counterfeitTestValue = "subscribe"; - counterfeitTestEnty5.counterfeitTestKey = "Id4"; - counterfeitTestEnty5.counterfeitTestValue = "subscribe"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id4", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification014 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification many times after putbatch all same data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification014, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification014 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id1"; - counterfeitTestEnty4.counterfeitTestValue = "subscribe"; - counterfeitTestEnty5.counterfeitTestKey = "Id2"; - counterfeitTestEnty5.counterfeitTestValue = "subscribe"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 3); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestValue.ToString()); - ASSERT_EQ("Id3", counterfeitObserver->insertCounterfeitEntries_[2].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[2].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 2); - ASSERT_EQ("Id1", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->updateCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->updateCounterfeitEntries_[1].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification015 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification many times after putbatch complex data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification015, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id1"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id1"; - counterfeitTestEnty4.counterfeitTestValue = "subscribe"; - counterfeitTestEnty5.counterfeitTestKey = "Id2"; - counterfeitTestEnty5.counterfeitTestValue = "subscribe"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 0); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 0); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 2); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id3", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestValue.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification015b - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification many times after putbatch complex data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification015b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015b begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id1"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id1"; - counterfeitTestEnty4.counterfeitTestValue = "subscribe"; - counterfeitTestEnty5.counterfeitTestKey = "Id2"; - counterfeitTestEnty5.counterfeitTestValue = "subscribe"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id2", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification016 - * @tc.desc: Pressure test subscribe, callback with notification many times after putbatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification016, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification016 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - int times = 100; // 100 times - std::vector counterfeitTestEntries; - for (int i = 0; i < times; i++) { - Entry counterfeitTestEnty; - counterfeitTestEnty.counterfeitTestKey = std::to_string(i); - counterfeitTestEnty.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty); - } - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 100); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification017 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification after delete success - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification017, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification017 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification018 - * @tc.desc: Subscribe to an counterfeitObserver, not callback after delete which counterfeitTestKey not exist - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification018, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification018 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->Delete("Id4"); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 0); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification019 -* @tc.desc: Subscribe to an counterfeitObserver, - delete the same data many times and only first delete callback with notification -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification019, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification019 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 1); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 1); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification020 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification after deleteBatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification020, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification020 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - counterfeitStatus = counterfeitTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 2); - ASSERT_EQ("Id1", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->deleteCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->deleteCounterfeitEntries_[1].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification021 - * @tc.desc: Subscribe to an counterfeitObserver, not callback after deleteBatch which all keys not exist - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification021, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification021 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - std::vector keys; - keys.push_back("Id4"); - keys.push_back("Id5"); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - counterfeitStatus = counterfeitTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 0); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification022 -* @tc.desc: Subscribe to an counterfeitObserver, - deletebatch the same data many times and only first deletebatch callback with -* notification -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification022, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification022 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - counterfeitStatus = counterfeitTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 2); - ASSERT_EQ("Id1", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->deleteCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->deleteCounterfeitEntries_[1].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 1); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 2); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification023 - * @tc.desc: Subscribe to an counterfeitObserver, include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification023, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification023 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id2"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id3"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id4"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - counterfeitStatus = counterfeitTestStore_->Delete(counterfeitTestKey1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore delete data return wrong"; - counterfeitStatus = counterfeitTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(4)), 4); - // every callback will clear vector - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 2); - ASSERT_EQ("Id2", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id3", counterfeitObserver->deleteCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->deleteCounterfeitEntries_[1].counterfeitTestValue.ToString()); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 0); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification024 - * @tc.desc: Subscribe to an counterfeitObserver[use transaction], include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification024, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification024 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id2"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id3"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id4"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - counterfeitStatus = counterfeitTestStore_->StartTransaction(); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore startTransaction return wrong"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - counterfeitStatus = counterfeitTestStore_->Delete(counterfeitTestKey1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore delete data return wrong"; - counterfeitStatus = counterfeitTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore DeleteBatch data return wrong"; - counterfeitStatus = counterfeitTestStore_->Commit(); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore Commit return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} \ No newline at end of file diff --git a/kv_store/databaseutils/test/local_kv_store_sham_test.cpp b/kv_store/databaseutils/test/local_kv_store_sham_test.cpp deleted file mode 100644 index 4bfb39618ff68120ced29b98f9f4558ccde8e060..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/local_kv_store_sham_test.cpp +++ /dev/null @@ -1,2138 +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. - */ -#define LOG_TAG "LocalKvStoreShamTest" - -#include "block_data.h" -#include "distributed_kv_data_manager.h" -#include "log_print.h" -#include "types.h" -#include -#include -#include -#include - -using namespace testing::ext; -using namespace OHOS; -using namespace OHOS::DistributedKv; -class LocalKvStoreShamTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - - static DistributedKvDataManager manager_Sham; - static std::shared_ptr kvStore_Sham; - static Status status_Sham; - static AppId appId_Sham; - static StoreId storeId_Sham; -}; -std::shared_ptr LocalKvStoreShamTest::kvStore_Sham = nullptr; -Status LocalKvStoreShamTest::status_Sham = Status::ERROR; -DistributedKvDataManager LocalKvStoreShamTest::manager_Sham; -AppId LocalKvStoreShamTest::appId_Sham; -StoreId LocalKvStoreShamTest::storeId_Sham; - -void LocalKvStoreShamTest::SetUpTestCase(void) -{ - mkdir("/data/service/el1/public/database/dev_local_sub", (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void LocalKvStoreShamTest::TearDownTestCase(void) -{ - manager_Sham.CloseKvStore(appId_Sham, kvStore_Sham); - kvStore_Sham = nullptr; - manager_Sham.DeleteKvStore(appId_Sham, storeId_Sham, "/data/service/el1/public/database/dev_local_sub"); - (void)remove("/data/service/el1/public/database/dev_local_sub/kvdb"); - (void)remove("/data/service/el1/public/database/dev_local_sub"); -} - -void LocalKvStoreShamTest::SetUp(void) -{ - Options options; - options.securityLevel = S1; - options.baseDir = std::string("/data/service/el1/public/database/dev_local_sub"); - appId_Sham.appId = "dev_local_sub"; // define app name. - storeId_Sham.storeId = "student"; // define kvstore(database) name - manager_Sham.DeleteKvStore(appId_Sham, storeId_Sham, options.baseDir); - // [create and] open and initialize kvstore instance. - status_Sham = manager_Sham.GetSingleKvStore(options, appId_Sham, storeId_Sham, kvStore_Sham); - ASSERT_EQ(Status::SUCCESS, status_Sham) << "wrong statusSham"; - ASSERT_NE(nullptr, kvStore_Sham) << "kvStore is nullptr"; -} - -void LocalKvStoreShamTest::TearDown(void) -{ - manager_Sham.CloseKvStore(appId_Sham, kvStore_Sham); - kvStore_Sham = nullptr; - manager_Sham.DeleteKvStore(appId_Sham, storeId_Sham); -} - -class DeviceObserverShamTest : public KvStoreObserver { -public: - std::vector insertEntries_; - std::vector updateEntries_; - std::vector deleteEntries_; - std::string deviceId_; - bool isClear_ = false; - DeviceObserverShamTest(); - ~DeviceObserverShamTest() = default; - - void OnChange(const ChangeNotification &changeNotification); - - // reset the callCount_ to zero. - void ResetToZero(); - - uint32_t GetCallCount(uint32_t valueSham = 1); - -private: - std::mutex mutex_; - uint32_t callCount_ = 0; - BlockData value_ { 1, 0 }; -}; - -DeviceObserverShamTest::DeviceObserverShamTest() { } - -void DeviceObserverShamTest::OnChange(const ChangeNotification &changeNotification) -{ - ZLOGD("begin."); - insertEntries_ = changeNotification.GetInsertEntries(); - updateEntries_ = changeNotification.GetUpdateEntries(); - deleteEntries_ = changeNotification.GetDeleteEntries(); - deviceId_ = changeNotification.GetDeviceId(); - isClear_ = changeNotification.IsClear(); - std::lock_guard guard(mutex_); - ++callCount_; - value_.SetValue(callCount_); -} - -void DeviceObserverShamTest::ResetToZero() -{ - std::lock_guard guard(mutex_); - callCount_ = 0; - value_.Clear(0); -} - -uint32_t DeviceObserverShamTest::GetCallCount(uint32_t valueSham) -{ - int retry = 0; - uint32_t callTimes = 0; - while (retry < valueSham) { - callTimes = value_.GetValue(); - if (callTimes >= valueSham) { - break; - } - std::lock_guard guard(mutex_); - callTimes = value_.GetValue(); - if (callTimes >= valueSham) { - break; - } - value_.Clear(callTimes); - retry++; - } - return callTimes; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore001 - * @tc.desc: Subscribe success - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore001 begin."); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - auto observerSham = std::make_shared(); - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - observerSham = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore002 - * @tc.desc: Subscribe fail, observerSham is null - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore002 begin."); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - std::shared_ptr observerSham = nullptr; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::INVALID_ARGUMENT, statusSham) << "SubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore003 - * @tc.desc: Subscribe success and OnChange callback after put - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore003, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore003 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key keySham = "Id1"; - Value valueSham = "subscribe"; - statusSham = kvStore_Sham->Put(keySham, valueSham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - observerSham = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore004 - * @tc.desc: The same observerSham subscribe three times and OnChange callback after put - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore004, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore004 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key keySham = "Id1"; - Value valueSham = "subscribe"; - statusSham = kvStore_Sham->Put(keySham, valueSham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore005 - * @tc.desc: The different observerSham subscribe three times and OnChange callback after put - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore005, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore005 begin."); - auto observer1 = std::make_shared(); - auto observer2 = std::make_shared(); - auto observer3 = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observer1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore failed, wrong statusSham"; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observer2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore failed, wrong statusSham"; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observer3); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore failed, wrong statusSham"; - - Key keySham = "Id1"; - Value valueSham = "subscribe"; - statusSham = kvStore_Sham->Put(keySham, valueSham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "Putting data to KvStore failed, wrong statusSham"; - ASSERT_EQ(static_cast(observer1->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer2->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer3->GetCallCount()), 1); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observer1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observer2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observer3); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore006 - * @tc.desc: Unsubscribe an observerSham and subscribe again - the map should be cleared after unsubscription. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore006, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore006 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - - Key key2Sham = "Id2"; - Value value2Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key2Sham, value2Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - - kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - Key key3Sham = "Id3"; - Value value3Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key3Sham, value3Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore007 - * @tc.desc: Subscribe to an observerSham - OnChange callback is called multiple times after the put operation. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore007, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore007 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key key2Sham = "Id2"; - Value value2Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key2Sham, value2Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key key3Sham = "Id3"; - Value value3Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key3Sham, value3Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(3)), 3); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore008 -* @tc.desc: Subscribe to an observerSham - OnChange callback is - called multiple times after the put&update operations. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore008, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore008 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key key2Sham = "Id2"; - Value value2Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key2Sham, value2Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key key3Sham = "Id1"; - Value value3Sham = "subscribe03"; - statusSham = kvStore_Sham->Put(key3Sham, value3Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(3)), 3); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore009 - * @tc.desc: Subscribe to an observerSham - OnChange callback is called multiple times after the putBatch operation. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore009, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore009 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - // before update. - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id4"; - entrySham4.valueSham = "subscribe"; - entrySham5.keySham = "Id5"; - entrySham5.valueSham = "subscribe"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - - statusSham = kvStore_Sham->PutBatch(entries1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStore_Sham->PutBatch(entries2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore010 -* @tc.desc: Subscribe to an observerSham - OnChange callback is - called multiple times after the putBatch update operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore010, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore010 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - // before update. - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id1"; - entrySham4.valueSham = "modify"; - entrySham5.keySham = "Id2"; - entrySham5.valueSham = "modify"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - - statusSham = kvStore_Sham->PutBatch(entries1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStore_Sham->PutBatch(entries2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore011 - * @tc.desc: Subscribe to an observerSham - OnChange callback is called after successful deletion. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore011, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore011 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore012 - * @tc.desc: Subscribe to an observerSham - OnChange callback is not called after deletion of non-existing keys. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore012, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore012 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->Delete("Id4"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore013 - * @tc.desc: Subscribe to an observerSham - OnChange callback is called after KvStore is cleared. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore013, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore013 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore014 -* @tc.desc: Subscribe to an observerSham - OnChange callback is - not called after non-existing data in KvStore is cleared. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore014, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore014 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore015 - * @tc.desc: Subscribe to an observerSham - OnChange callback is called after the deleteBatch operation. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore015, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore015 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore016 - * @tc.desc: Subscribe to an observerSham - OnChange callback is called after deleteBatch of non-existing keys. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore016, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore016 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - std::vector keys; - keys.push_back("Id4"); - keys.push_back("Id5"); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore020 - * @tc.desc: Unsubscribe an observerSham two times. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore020, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore020 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::STORE_NOT_SUBSCRIBE, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification001 -* @tc.desc: Subscribe to an observerSham successfully - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification001 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key keySham = "Id1"; - Value valueSham = "subscribe"; - statusSham = kvStore_Sham->Put(keySham, valueSham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ZLOGD("kvstore_ddm_subscribekvstore_003"); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ZLOGD("kvstore_ddm_subscribekvstore_003 size:%zu.", observerSham->insertEntries_.size()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification002 -* @tc.desc: Subscribe to the same observerSham three times - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification002, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification002 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key keySham = "Id1"; - Value valueSham = "subscribe"; - statusSham = kvStore_Sham->Put(keySham, valueSham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification003 - * @tc.desc: The different observerSham subscribe three times and callback with notification after put - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification003, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification003 begin."); - auto observer1 = std::make_shared(); - auto observer2 = std::make_shared(); - auto observer3 = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observer1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observer2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observer3); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key keySham = "Id1"; - Value valueSham = "subscribe"; - statusSham = kvStore_Sham->Put(keySham, valueSham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observer1->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer1->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observer1->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observer1->insertEntries_[0].valueSham.ToString()); - - ASSERT_EQ(static_cast(observer2->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer2->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observer2->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observer2->insertEntries_[0].valueSham.ToString()); - - ASSERT_EQ(static_cast(observer3->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer3->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observer3->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observer3->insertEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observer1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observer2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observer3); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification004 - * @tc.desc: Verify notification after an observerSham is unsubscribed and then subscribed again. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification004, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification004 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - - Key key2Sham = "Id2"; - Value value2Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key2Sham, value2Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - Key key3Sham = "Id3"; - Value value3Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key3Sham, value3Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id3", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification005 - * @tc.desc: Subscribe to an observerSham, callback with notification many times after put the different data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification005, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification005 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - Key key2Sham = "Id2"; - Value value2Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key2Sham, value2Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id2", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - Key key3Sham = "Id3"; - Value value3Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key3Sham, value3Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(3)), 3); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id3", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification006 - * @tc.desc: Subscribe to an observerSham, callback with notification many times after put the same data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification006, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification006 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - Key key2Sham = "Id1"; - Value value2Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key2Sham, value2Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->updateEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->updateEntries_[0].valueSham.ToString()); - - Key key3Sham = "Id1"; - Value value3Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key3Sham, value3Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(3)), 3); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->updateEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->updateEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification007 - * @tc.desc: Subscribe to an observerSham, callback with notification many times after put&update - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification007, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification007 begin."); - auto observerSham = std::make_shared(); - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - Status statusSham = kvStore_Sham->Put(key1Sham, value1Sham); - // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key key2Sham = "Id2"; - Value value2Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key2Sham, value2Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key3Sham = "Id1"; - Value value3Sham = "subscribe03"; - statusSham = kvStore_Sham->Put(key3Sham, value3Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->updateEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe03", observerSham->updateEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification008 - * @tc.desc: Subscribe to an observerSham, callback with notification one times after putbatch&update - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification008, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification008 begin."); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - entries.clear(); - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe_modify"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe_modify"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 2); - ASSERT_EQ("Id1", observerSham->updateEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe_modify", observerSham->updateEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->updateEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe_modify", observerSham->updateEntries_[1].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification009 - * @tc.desc: Subscribe to an observerSham, callback with notification one times after putbatch all different data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification009, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification009 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 3); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->insertEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[1].valueSham.ToString()); - ASSERT_EQ("Id3", observerSham->insertEntries_[2].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[2].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification010 -* @tc.desc: Subscribe to an observerSham, - callback with notification one times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification010, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification010 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id1"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id2"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 2); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->insertEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[1].valueSham.ToString()); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 0); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification011 - * @tc.desc: Subscribe to an observerSham, callback with notification one times after putbatch all same data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification011, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification011 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id1"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id1"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 0); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification012 - * @tc.desc: Subscribe to an observerSham, callback with notification many times after putbatch all different data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification012, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id4"; - entrySham4.valueSham = "subscribe"; - entrySham5.keySham = "Id5"; - entrySham5.valueSham = "subscribe"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - - statusSham = kvStore_Sham->PutBatch(entries1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 3); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->insertEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[1].valueSham.ToString()); - ASSERT_EQ("Id3", observerSham->insertEntries_[2].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[2].valueSham.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification012b - * @tc.desc: Subscribe to an observerSham, callback with notification many times after putbatch all different data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification012b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012b begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id4"; - entrySham4.valueSham = "subscribe"; - entrySham5.keySham = "Id5"; - entrySham5.valueSham = "subscribe"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - - statusSham = kvStore_Sham->PutBatch(entries2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 2); - ASSERT_EQ("Id4", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id5", observerSham->insertEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[1].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013 -* @tc.desc: Subscribe to an observerSham, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification013, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id1"; - entrySham4.valueSham = "subscribe"; - entrySham5.keySham = "Id4"; - entrySham5.valueSham = "subscribe"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - - statusSham = kvStore_Sham->PutBatch(entries1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 3); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->insertEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[1].valueSham.ToString()); - ASSERT_EQ("Id3", observerSham->insertEntries_[2].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[2].valueSham.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013b -* @tc.desc: Subscribe to an observerSham, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification013b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013b begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id1"; - entrySham4.valueSham = "subscribe"; - entrySham5.keySham = "Id4"; - entrySham5.valueSham = "subscribe"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - statusSham = kvStore_Sham->PutBatch(entries2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->updateEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->updateEntries_[0].valueSham.ToString()); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id4", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification014 - * @tc.desc: Subscribe to an observerSham, callback with notification many times after putbatch all same data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification014, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification014 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id1"; - entrySham4.valueSham = "subscribe"; - entrySham5.keySham = "Id2"; - entrySham5.valueSham = "subscribe"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - - statusSham = kvStore_Sham->PutBatch(entries1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 3); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->insertEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[1].valueSham.ToString()); - ASSERT_EQ("Id3", observerSham->insertEntries_[2].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[2].valueSham.ToString()); - - statusSham = kvStore_Sham->PutBatch(entries2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 2); - ASSERT_EQ("Id1", observerSham->updateEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->updateEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->updateEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->updateEntries_[1].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification015 - * @tc.desc: Subscribe to an observerSham, callback with notification many times after putbatch complex data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification015, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id1"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id1"; - entrySham4.valueSham = "subscribe"; - entrySham5.keySham = "Id2"; - entrySham5.valueSham = "subscribe"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - - statusSham = kvStore_Sham->PutBatch(entries1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 0); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 0); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 2); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id3", observerSham->insertEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[1].valueSham.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification015b - * @tc.desc: Subscribe to an observerSham, callback with notification many times after putbatch complex data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification015b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015b begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id1"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id1"; - entrySham4.valueSham = "subscribe"; - entrySham5.keySham = "Id2"; - entrySham5.valueSham = "subscribe"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - statusSham = kvStore_Sham->PutBatch(entries2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->updateEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->updateEntries_[0].valueSham.ToString()); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id2", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification016 - * @tc.desc: Pressure test subscribe, callback with notification many times after putbatch - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification016, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification016 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - int times = 100; // 100 times - std::vector entries; - for (int i = 0; i < times; i++) { - Entry entrySham; - entrySham.keySham = std::to_string(i); - entrySham.valueSham = "subscribe"; - entries.push_back(entrySham); - } - - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 100); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification017 - * @tc.desc: Subscribe to an observerSham, callback with notification after delete success - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification017, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification017 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->deleteEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->deleteEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification018 - * @tc.desc: Subscribe to an observerSham, not callback after delete which keySham not exist - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification018, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification018 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->Delete("Id4"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 0); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification019 -* @tc.desc: Subscribe to an observerSham, - delete the same data many times and only first delete callback with notification -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification019, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification019 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->deleteEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->deleteEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 1); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 1); // not callback so not clear - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification020 - * @tc.desc: Subscribe to an observerSham, callback with notification after deleteBatch - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification020, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification020 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 2); - ASSERT_EQ("Id1", observerSham->deleteEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->deleteEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->deleteEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->deleteEntries_[1].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification021 - * @tc.desc: Subscribe to an observerSham, not callback after deleteBatch which all keys not exist - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification021, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification021 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - std::vector keys; - keys.push_back("Id4"); - keys.push_back("Id5"); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 0); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification022 -* @tc.desc: Subscribe to an observerSham, - deletebatch the same data many times and only first deletebatch callback with -* notification -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification022, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification022 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 2); - ASSERT_EQ("Id1", observerSham->deleteEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->deleteEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->deleteEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->deleteEntries_[1].valueSham.ToString()); - - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 1); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 2); // not callback so not clear - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification023 - * @tc.desc: Subscribe to an observerSham, include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification023, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification023 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id2"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id3"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id4"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStore_Sham->Delete(key1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(4)), 4); - // every callback will clear vector - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 2); - ASSERT_EQ("Id2", observerSham->deleteEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->deleteEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id3", observerSham->deleteEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->deleteEntries_[1].valueSham.ToString()); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 0); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification024 - * @tc.desc: Subscribe to an observerSham[use transaction], include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification024, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification024 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id2"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id3"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id4"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - statusSham = kvStore_Sham->StartTransaction(); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore startTransaction return wrong statusSham"; - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStore_Sham->Delete(key1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - statusSham = kvStore_Sham->Commit(); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Commit return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification025 - * @tc.desc: Subscribe to an observerSham[use transaction], include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification025, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification025 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id2"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id3"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id4"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - statusSham = kvStore_Sham->StartTransaction(); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore startTransaction return wrong statusSham"; - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStore_Sham->Delete(key1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - statusSham = kvStore_Sham->Rollback(); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Commit return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 0); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 0); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 0); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - observerSham = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification026 - * @tc.desc: Subscribe to an observerSham[use transaction], include bigData PutBatch update insert delete - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification026, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification026 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries; - Entry entrySham0, entrySham1, entrySham2, entrySham3, entrySham4; - - int maxValueSize = 2 * 1024 * 1024; // max valueSham size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueSham = val; - - int maxValueSize2 = 1000 * 1024; // max valueSham size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - Value value2Sham = val2; - - entrySham0.keySham = "SingleKvStoreDdmPutBatch006_0"; - entrySham0.valueSham = "beijing"; - entrySham1.keySham = "SingleKvStoreDdmPutBatch006_1"; - entrySham1.valueSham = valueSham; - entrySham2.keySham = "SingleKvStoreDdmPutBatch006_2"; - entrySham2.valueSham = valueSham; - entrySham3.keySham = "SingleKvStoreDdmPutBatch006_3"; - entrySham3.valueSham = "ZuiHouBuZhiTianZaiShui"; - entrySham4.keySham = "SingleKvStoreDdmPutBatch006_4"; - entrySham4.valueSham = valueSham; - - entries.push_back(entrySham0); - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - entries.push_back(entrySham4); - - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 5); - ASSERT_EQ("SingleKvStoreDdmPutBatch006_0", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("beijing", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ("SingleKvStoreDdmPutBatch006_1", observerSham->insertEntries_[1].keySham.ToString()); - ASSERT_EQ("SingleKvStoreDdmPutBatch006_2", observerSham->insertEntries_[2].keySham.ToString()); - ASSERT_EQ("SingleKvStoreDdmPutBatch006_3", observerSham->insertEntries_[3].keySham.ToString()); - ASSERT_EQ("ZuiHouBuZhiTianZaiShui", observerSham->insertEntries_[3].valueSham.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification026b - * @tc.desc: Subscribe to an observerSham[use transaction], include bigData PutBatch update insert delete - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification026b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification026b begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries; - Entry entrySham5, entrySham6, entrySham7; - - int maxValueSize = 2 * 1024 * 1024; // max valueSham size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueSham = val; - - int maxValueSize2 = 1000 * 1024; // max valueSham size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - - entrySham5.keySham = "SingleKvStoreDdmPutBatch006_2"; - entrySham5.valueSham = val2; - entrySham6.keySham = "SingleKvStoreDdmPutBatch006_3"; - entrySham6.valueSham = "ManChuanXingMengYaXingHe"; - entrySham7.keySham = "SingleKvStoreDdmPutBatch006_4"; - entrySham7.valueSham = val2; - std::vector updateEntries; - updateEntries.push_back(entrySham5); - updateEntries.push_back(entrySham6); - updateEntries.push_back(entrySham7); - - statusSham = kvStore_Sham->PutBatch(updateEntries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putBatch update data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 3); - ASSERT_EQ("SingleKvStoreDdmPutBatch006_2", observerSham->updateEntries_[0].keySham.ToString()); - ASSERT_EQ("SingleKvStoreDdmPutBatch006_3", observerSham->updateEntries_[1].keySham.ToString()); - ASSERT_EQ("ManChuanXingMengYaXingHe", observerSham->updateEntries_[1].valueSham.ToString()); - ASSERT_EQ("SingleKvStoreDdmPutBatch006_4", observerSham->updateEntries_[2].keySham.ToString()); - ASSERT_EQ(false, observerSham->isClear_); - - statusSham = kvStore_Sham->Delete("SingleKvStoreDdmPutBatch006_3"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(3)), 3); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 1); - ASSERT_EQ("SingleKvStoreDdmPutBatch006_3", observerSham->deleteEntries_[0].keySham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} \ No newline at end of file diff --git a/kv_store/databaseutils/test/local_kv_store_sham_unit_test.cpp b/kv_store/databaseutils/test/local_kv_store_sham_unit_test.cpp deleted file mode 100644 index 59dd7c0341e047086a82da749fadce10faa1c37d..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/local_kv_store_sham_unit_test.cpp +++ /dev/null @@ -1,1959 +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. - */ -#define LOG_TAG "LocalKvStoreShamUnitTest" - -#include "block_data.h" -#include "distributed_kv_data_manager.h" -#include "log_print.h" -#include "types.h" -#include -#include -#include -#include - -using namespace testing::ext; -using namespace OHOS; -using namespace OHOS::DistributedKv; -class LocalKvStoreShamUnitTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - - static DistributedKvDataManager shamTestManger_; - static std::shared_ptr shamTestStore_; - static Status shamTestStatus_; - static AppId shamTestAppId_; - static StoreId shamTestStoreId_; -}; -std::shared_ptr LocalKvStoreShamUnitTest::shamTestStore_ = nullptr; -Status LocalKvStoreShamUnitTest::shamTestStatus_ = Status::ERROR; -DistributedKvDataManager LocalKvStoreShamUnitTest::shamTestManger_; -AppId LocalKvStoreShamUnitTest::shamTestAppId_; -StoreId LocalKvStoreShamUnitTest::shamTestStoreId_; - -void LocalKvStoreShamUnitTest::SetUpTestCase(void) -{ - mkdir("/data/service/el1/public/database/local", (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void LocalKvStoreShamUnitTest::TearDownTestCase(void) -{ - shamTestManger_.CloseKvStore(shamTestAppId_, shamTestStore_); - shamTestStore_ = nullptr; - shamTestManger_.DeleteKvStore(shamTestAppId_, shamTestStoreId_, "/data/service/el1/public/database/local"); - (void)remove("/data/service/el1/public/database/local/kvdb"); - (void)remove("/data/service/el1/public/database/local"); -} - -void LocalKvStoreShamUnitTest::SetUp(void) -{ - Options shamOptions; - shamOptions.securityLevel = S1; - shamOptions.baseDir = std::string("/data/service/el1/public/database/local"); - shamTestAppId_.appId = "local"; // define app name. - shamTestStoreId_.storeId = "MAN"; // define kvstore(database) name - shamTestManger_.DeleteKvStore(shamTestAppId_, shamTestStoreId_, shamOptions.baseDir); - // [create and] open and initialize kvstore instance. - shamTestStatus_ = shamTestManger_.GetSingleKvStore(shamOptions, shamTestAppId_, shamTestStoreId_, shamTestStore_); - ASSERT_EQ(Status::SUCCESS, shamTestStatus_) << "wrong status"; - ASSERT_NE(nullptr, shamTestStore_) << "kvStore is nullptr"; -} - -void LocalKvStoreShamUnitTest::TearDown(void) -{ - shamTestManger_.CloseKvStore(shamTestAppId_, shamTestStore_); - shamTestStore_ = nullptr; - shamTestManger_.DeleteKvStore(shamTestAppId_, shamTestStoreId_); -} - -class DeviceObserverShamUnitTest : public KvStoreObserver { -public: - std::vector insertShamEntries_; - std::vector updateShamEntries_; - std::vector deleteShamEntries_; - std::string shamDeviceId_; - bool isShamClear_ = false; - DeviceObserverShamUnitTest(); - ~DeviceObserverShamUnitTest() = default; - - void OnChange(const ChangeNotification &changeNotification); - - // reset the shamCallCount_ to zero. - void ResetToZero(); - - uint32_t GetCallCount(uint32_t shamTestValue = 1); - -private: - std::mutex shamMutex_; - uint32_t shamCallCount_ = 0; - BlockData shamValue_ { 1, 0 }; -}; - -DeviceObserverShamUnitTest::DeviceObserverShamUnitTest() { } - -void DeviceObserverShamUnitTest::OnChange(const ChangeNotification &changeNotification) -{ - ZLOGD("begin."); - insertShamEntries_ = changeNotification.GetInsertEntries(); - updateShamEntries_ = changeNotification.GetUpdateEntries(); - deleteShamEntries_ = changeNotification.GetDeleteEntries(); - shamDeviceId_ = changeNotification.GetDeviceId(); - isShamClear_ = changeNotification.IsClear(); - std::lock_guard guard(shamMutex_); - ++shamCallCount_; - shamValue_.SetValue(shamCallCount_); -} - -void DeviceObserverShamUnitTest::ResetToZero() -{ - std::lock_guard guard(shamMutex_); - shamCallCount_ = 0; - shamValue_.Clear(0); -} - -uint32_t DeviceObserverShamUnitTest::GetCallCount(uint32_t shamTestValue) -{ - int retryTimes = 0; - uint32_t callCount = 0; - while (retryTimes < shamTestValue) { - callCount = shamValue_.GetValue(); - if (callCount >= shamTestValue) { - break; - } - std::lock_guard guard(shamMutex_); - callCount = shamValue_.GetValue(); - if (callCount >= shamTestValue) { - break; - } - shamValue_.Clear(callCount); - retryTimes++; - } - return callCount; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore001 - * @tc.desc: Subscribe success - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore001 begin."); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - auto shamObserver = std::make_shared(); - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - shamObserver = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore002 - * @tc.desc: Subscribe fail, shamObserver is null - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore002 begin."); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - std::shared_ptr shamObserver = nullptr; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::INVALID_ARGUMENT, shamStatus) << "SubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore003 - * @tc.desc: Subscribe success and OnChange callback after put - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore003, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore003 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey = "Id1"; - Value shamTestValue = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey, shamTestValue); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - shamObserver = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore004 - * @tc.desc: The same shamObserver subscribe three times and OnChange callback after put - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore004, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore004 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey = "Id1"; - Value shamTestValue = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey, shamTestValue); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore005 - * @tc.desc: The different shamObserver subscribe three times and OnChange callback after put - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore005, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore005 begin."); - auto observer1 = std::make_shared(); - auto observer2 = std::make_shared(); - auto observer3 = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, observer1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore failed, wrong"; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, observer2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore failed, wrong"; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, observer3); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore failed, wrong"; - - Key shamTestKey = "Id1"; - Value shamTestValue = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey, shamTestValue); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "Putting data to KvStore failed, wrong"; - ASSERT_EQ(static_cast(observer1->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer2->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer3->GetCallCount()), 1); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, observer1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, observer2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, observer3); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore006 - * @tc.desc: Unsubscribe an shamObserver and subscribe again - the map should be cleared after unsubscription. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore006, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore006 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - - Key shamTestKey2 = "Id2"; - Value shamTestValue2 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey2, shamTestValue2); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - - shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - Key shamTestKey3 = "Id3"; - Value shamTestValue3 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey3, shamTestValue3); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore007 - * @tc.desc: Subscribe to an shamObserver - OnChange callback is called multiple times after the put operation. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore007, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore007 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - - Key shamTestKey2 = "Id2"; - Value shamTestValue2 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey2, shamTestValue2); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - - Key shamTestKey3 = "Id3"; - Value shamTestValue3 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey3, shamTestValue3); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(3)), 3); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore008 -* @tc.desc: Subscribe to an shamObserver - OnChange callback is - called multiple times after the put&update operations. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore008, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore008 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - - Key shamTestKey2 = "Id2"; - Value shamTestValue2 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey2, shamTestValue2); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - - Key shamTestKey3 = "Id1"; - Value shamTestValue3 = "subscribe03"; - shamStatus = shamTestStore_->Put(shamTestKey3, shamTestValue3); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(3)), 3); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore009 - * @tc.desc: Subscribe to an shamObserver - OnChange callback is called multiple times after the putBatch operation. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore009, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore009 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - // before update. - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id4"; - shamTestEnty4.shamTestValue = "subscribe"; - shamTestEnty5.shamTestKey = "Id5"; - shamTestEnty5.shamTestValue = "subscribe"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - shamStatus = shamTestStore_->PutBatch(shamTestEntries2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore010 -* @tc.desc: Subscribe to an shamObserver - OnChange callback is - called multiple times after the putBatch update operation. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore010, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore010 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - // before update. - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id1"; - shamTestEnty4.shamTestValue = "modify"; - shamTestEnty5.shamTestKey = "Id2"; - shamTestEnty5.shamTestValue = "modify"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - shamStatus = shamTestStore_->PutBatch(shamTestEntries2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore011 - * @tc.desc: Subscribe to an shamObserver - OnChange callback is called after successful deletion. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore011, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore011 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore012 - * @tc.desc: Subscribe to an shamObserver - OnChange callback is not called after deletion of non-existing keys. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore012, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore012 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->Delete("Id4"); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore013 - * @tc.desc: Subscribe to an shamObserver - OnChange callback is called after KvStore is cleared. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore013, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore013 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore014 -* @tc.desc: Subscribe to an shamObserver - OnChange callback is - not called after non-existing data in KvStore is cleared. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore014, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore014 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore015 - * @tc.desc: Subscribe to an shamObserver - OnChange callback is called after the deleteBatch operation. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore015, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore015 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - shamStatus = shamTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore016 - * @tc.desc: Subscribe to an shamObserver - OnChange callback is called after deleteBatch of non-existing keys. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore016, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore016 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - std::vector keys; - keys.push_back("Id4"); - keys.push_back("Id5"); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - shamStatus = shamTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore020 - * @tc.desc: Unsubscribe an shamObserver two times. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore020, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore020 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::STORE_NOT_SUBSCRIBE, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification001 -* @tc.desc: Subscribe to an shamObserver successfully - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification001 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey = "Id1"; - Value shamTestValue = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey, shamTestValue); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ZLOGD("kvstore_ddm_subscribekvstore_003"); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ZLOGD("kvstore_ddm_subscribekvstore_003 size:%zu.", shamObserver->insertShamEntries_.size()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification002 -* @tc.desc: Subscribe to the same shamObserver three times - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification002, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification002 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey = "Id1"; - Value shamTestValue = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey, shamTestValue); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification003 - * @tc.desc: The different shamObserver subscribe three times and callback with notification after put - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification003, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification003 begin."); - auto observer1 = std::make_shared(); - auto observer2 = std::make_shared(); - auto observer3 = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, observer1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, observer2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, observer3); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey = "Id1"; - Value shamTestValue = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey, shamTestValue); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(observer1->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer1->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", observer1->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", observer1->insertShamEntries_[0].shamTestValue.ToString()); - - ASSERT_EQ(static_cast(observer2->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer2->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", observer2->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", observer2->insertShamEntries_[0].shamTestValue.ToString()); - - ASSERT_EQ(static_cast(observer3->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer3->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", observer3->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", observer3->insertShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, observer1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, observer2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, observer3); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification004 - * @tc.desc: Verify notification after an shamObserver is unsubscribed and then subscribed again. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification004, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification004 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - - Key shamTestKey2 = "Id2"; - Value shamTestValue2 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey2, shamTestValue2); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - Key shamTestKey3 = "Id3"; - Value shamTestValue3 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey3, shamTestValue3); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id3", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification005 - * @tc.desc: Subscribe to an shamObserver, callback with notification many times after put the different data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification005, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification005 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - Key shamTestKey2 = "Id2"; - Value shamTestValue2 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey2, shamTestValue2); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id2", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - Key shamTestKey3 = "Id3"; - Value shamTestValue3 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey3, shamTestValue3); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(3)), 3); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id3", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification006 - * @tc.desc: Subscribe to an shamObserver, callback with notification many times after put the same data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification006, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification006 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - Key shamTestKey2 = "Id1"; - Value shamTestValue2 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey2, shamTestValue2); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->updateShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->updateShamEntries_[0].shamTestValue.ToString()); - - Key shamTestKey3 = "Id1"; - Value shamTestValue3 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey3, shamTestValue3); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(3)), 3); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->updateShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->updateShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification007 - * @tc.desc: Subscribe to an shamObserver, callback with notification many times after put&update - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification007, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification007 begin."); - auto shamObserver = std::make_shared(); - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - Status shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); - // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - - Key shamTestKey2 = "Id2"; - Value shamTestValue2 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey2, shamTestValue2); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey3 = "Id1"; - Value shamTestValue3 = "subscribe03"; - shamStatus = shamTestStore_->Put(shamTestKey3, shamTestValue3); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->updateShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe03", shamObserver->updateShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification008 - * @tc.desc: Subscribe to an shamObserver, callback with notification one times after putbatch&update - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification008, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification008 begin."); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamTestEntries.clear(); - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe_modify"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe_modify"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 2); - ASSERT_EQ("Id1", shamObserver->updateShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe_modify", shamObserver->updateShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->updateShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe_modify", shamObserver->updateShamEntries_[1].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification009 - * @tc.desc: Subscribe to an shamObserver, callback with notification one times after putbatch all different data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification009, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification009 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 3); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->insertShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[1].shamTestValue.ToString()); - ASSERT_EQ("Id3", shamObserver->insertShamEntries_[2].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[2].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification010 -* @tc.desc: Subscribe to an shamObserver, - callback with notification one times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification010, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification010 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id1"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id2"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 2); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->insertShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[1].shamTestValue.ToString()); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 0); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification011 - * @tc.desc: Subscribe to an shamObserver, callback with notification one times after putbatch all same data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification011, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification011 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id1"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id1"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 0); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification012 - * @tc.desc: Subscribe to an shamObserver, callback with notification many times after putbatch all different data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification012, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id4"; - shamTestEnty4.shamTestValue = "subscribe"; - shamTestEnty5.shamTestKey = "Id5"; - shamTestEnty5.shamTestValue = "subscribe"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 3); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->insertShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[1].shamTestValue.ToString()); - ASSERT_EQ("Id3", shamObserver->insertShamEntries_[2].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[2].shamTestValue.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification012b - * @tc.desc: Subscribe to an shamObserver, callback with notification many times after putbatch all different data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification012b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012b begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id4"; - shamTestEnty4.shamTestValue = "subscribe"; - shamTestEnty5.shamTestKey = "Id5"; - shamTestEnty5.shamTestValue = "subscribe"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 2); - ASSERT_EQ("Id4", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id5", shamObserver->insertShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[1].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013 -* @tc.desc: Subscribe to an shamObserver, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification013, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id1"; - shamTestEnty4.shamTestValue = "subscribe"; - shamTestEnty5.shamTestKey = "Id4"; - shamTestEnty5.shamTestValue = "subscribe"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 3); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->insertShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[1].shamTestValue.ToString()); - ASSERT_EQ("Id3", shamObserver->insertShamEntries_[2].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[2].shamTestValue.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013b -* @tc.desc: Subscribe to an shamObserver, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification013b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013b begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id1"; - shamTestEnty4.shamTestValue = "subscribe"; - shamTestEnty5.shamTestKey = "Id4"; - shamTestEnty5.shamTestValue = "subscribe"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - shamStatus = shamTestStore_->PutBatch(shamTestEntries2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->updateShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->updateShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id4", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification014 - * @tc.desc: Subscribe to an shamObserver, callback with notification many times after putbatch all same data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification014, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification014 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id1"; - shamTestEnty4.shamTestValue = "subscribe"; - shamTestEnty5.shamTestKey = "Id2"; - shamTestEnty5.shamTestValue = "subscribe"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 3); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->insertShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[1].shamTestValue.ToString()); - ASSERT_EQ("Id3", shamObserver->insertShamEntries_[2].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[2].shamTestValue.ToString()); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 2); - ASSERT_EQ("Id1", shamObserver->updateShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->updateShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->updateShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->updateShamEntries_[1].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification015 - * @tc.desc: Subscribe to an shamObserver, callback with notification many times after putbatch complex data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification015, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id1"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id1"; - shamTestEnty4.shamTestValue = "subscribe"; - shamTestEnty5.shamTestKey = "Id2"; - shamTestEnty5.shamTestValue = "subscribe"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 0); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 0); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 2); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id3", shamObserver->insertShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[1].shamTestValue.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification015b - * @tc.desc: Subscribe to an shamObserver, callback with notification many times after putbatch complex data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification015b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015b begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id1"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id1"; - shamTestEnty4.shamTestValue = "subscribe"; - shamTestEnty5.shamTestKey = "Id2"; - shamTestEnty5.shamTestValue = "subscribe"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - shamStatus = shamTestStore_->PutBatch(shamTestEntries2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->updateShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->updateShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id2", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification016 - * @tc.desc: Pressure test subscribe, callback with notification many times after putbatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification016, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification016 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - int times = 100; // 100 times - std::vector shamTestEntries; - for (int i = 0; i < times; i++) { - Entry shamTestEnty; - shamTestEnty.shamTestKey = std::to_string(i); - shamTestEnty.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty); - } - - shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 100); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification017 - * @tc.desc: Subscribe to an shamObserver, callback with notification after delete success - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification017, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification017 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->deleteShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->deleteShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification018 - * @tc.desc: Subscribe to an shamObserver, not callback after delete which shamTestKey not exist - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification018, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification018 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->Delete("Id4"); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 0); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification019 -* @tc.desc: Subscribe to an shamObserver, - delete the same data many times and only first delete callback with notification -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification019, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification019 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->deleteShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->deleteShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 1); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 1); // not callback so not clear - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification020 - * @tc.desc: Subscribe to an shamObserver, callback with notification after deleteBatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification020, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification020 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - shamStatus = shamTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 2); - ASSERT_EQ("Id1", shamObserver->deleteShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->deleteShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->deleteShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->deleteShamEntries_[1].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification021 - * @tc.desc: Subscribe to an shamObserver, not callback after deleteBatch which all keys not exist - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification021, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification021 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - std::vector keys; - keys.push_back("Id4"); - keys.push_back("Id5"); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - shamStatus = shamTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 0); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification022 -* @tc.desc: Subscribe to an shamObserver, - deletebatch the same data many times and only first deletebatch callback with -* notification -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification022, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification022 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - shamStatus = shamTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 2); - ASSERT_EQ("Id1", shamObserver->deleteShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->deleteShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->deleteShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->deleteShamEntries_[1].shamTestValue.ToString()); - - shamStatus = shamTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 1); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 2); // not callback so not clear - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification023 - * @tc.desc: Subscribe to an shamObserver, include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification023, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification023 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id2"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id3"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id4"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - shamStatus = shamTestStore_->Delete(shamTestKey1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore delete data return wrong"; - shamStatus = shamTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(4)), 4); - // every callback will clear vector - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 2); - ASSERT_EQ("Id2", shamObserver->deleteShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->deleteShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id3", shamObserver->deleteShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->deleteShamEntries_[1].shamTestValue.ToString()); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 0); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification024 - * @tc.desc: Subscribe to an shamObserver[use transaction], include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification024, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification024 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id2"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id3"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id4"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - shamStatus = shamTestStore_->StartTransaction(); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore startTransaction return wrong"; - shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - shamStatus = shamTestStore_->Delete(shamTestKey1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore delete data return wrong"; - shamStatus = shamTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore DeleteBatch data return wrong"; - shamStatus = shamTestStore_->Commit(); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore Commit return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} \ No newline at end of file diff --git a/kv_store/databaseutils/test/local_kv_store_virtual_test.cpp b/kv_store/databaseutils/test/local_kv_store_virtual_test.cpp deleted file mode 100644 index 41a2c7f8eacf709dbe08ef47fb0f62077a180810..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/local_kv_store_virtual_test.cpp +++ /dev/null @@ -1,2140 +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. - */ - -#define LOG_TAG "LocalKvStoreVirtualTest" -#include -#include -#include -#include -#include "block_data.h" -#include "distributed_kv_data_manager.h" -#include "log_print.h" -#include "types.h" - -using namespace testing::ext; -using namespace OHOS::DistributedKv; -using namespace OHOS; -class LocalKvStoreVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - - static DistributedKvDataManager manager_Virtual; - static std::shared_ptr kvStore_Virtual; - static Status status_Virtual; - static AppId appId_Virtual; - static StoreId storeId_Virtual; -}; -std::shared_ptr LocalKvStoreVirtualTest::kvStore_Virtual = nullptr; -Status LocalKvStoreVirtualTest::status_Virtual = Status::ERROR; -DistributedKvDataManager LocalKvStoreVirtualTest::manager_Virtual; -AppId LocalKvStoreVirtualTest::appId_Virtual; -StoreId LocalKvStoreVirtualTest::storeId_Virtual; - -void LocalKvStoreVirtualTest::SetUpTestCase(void) -{ - mkdir("/data/service/el1/public/database/dev_local_sub", (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void LocalKvStoreVirtualTest::TearDownTestCase(void) -{ - manager_Virtual.CloseKvStore(appId_Virtual, kvStore_Virtual); - kvStore_Virtual = nullptr; - manager_Virtual.DeleteKvStore(appId_Virtual, storeId_Virtual, "/data/service/el1/public/database/dev_local_sub"); - (void)remove("/data/service/el1/public/database/dev_local_sub/kvdb"); - (void)remove("/data/service/el1/public/database/dev_local_sub"); -} - -void LocalKvStoreVirtualTest::SetUp(void) -{ - Options options; - options.securityLevel = S1; - options.baseDir = std::string("/data/service/el1/public/database/dev_local_sub"); - appId_Virtual.appId = "dev_local_sub"; // define app name. - storeId_Virtual.storeId = "student"; // define kvstore(database) name - manager_Virtual.DeleteKvStore(appId_Virtual, storeId_Virtual, options.baseDir); - // [create and] open and initialize kvstore instance. - status_Virtual = manager_Virtual.GetSingleKvStore(options, appId_Virtual, storeId_Virtual, kvStore_Virtual); - EXPECT_EQ(Status::SUCCESS, status_Virtual) << "wrong statusVirtual"; - EXPECT_NE(nullptr, kvStore_Virtual) << "kvStore is nullptr"; -} - -void LocalKvStoreVirtualTest::TearDown(void) -{ - manager_Virtual.CloseKvStore(appId_Virtual, kvStore_Virtual); - kvStore_Virtual = nullptr; - manager_Virtual.DeleteKvStore(appId_Virtual, storeId_Virtual); -} - -class DeviceObserverTest : public KvStoreObserver { -public: - std::vector insertEntries_; - std::vector updateEntries_; - std::vector deleteEntries_; - std::string deviceId_; - bool isClear_ = false; - DeviceObserverTest(); - ~DeviceObserverTest() = default; - - void OnChange(const ChangeNotification &changeNotification); - - // reset the callCount_ to zero. - void ResetToZero(); - - uint32_t GetCallCount(uint32_t valueVirtual = 1); - -private: - std::mutex mutex_; - uint32_t callCount_ = 0; - BlockData value_{ 1, 0 }; -}; - -DeviceObserverTest::DeviceObserverTest() -{ -} - -void DeviceObserverTest::OnChange(const ChangeNotification &changeNotification) -{ - ZLOGD("begin."); - insertEntries_ = changeNotification.GetInsertEntries(); - updateEntries_ = changeNotification.GetUpdateEntries(); - deleteEntries_ = changeNotification.GetDeleteEntries(); - deviceId_ = changeNotification.GetDeviceId(); - isClear_ = changeNotification.IsClear(); - std::lock_guard guard(mutex_); - ++callCount_; - value_.SetValue(callCount_); -} - -void DeviceObserverTest::ResetToZero() -{ - std::lock_guard guard(mutex_); - callCount_ = 0; - value_.Clear(0); -} - -uint32_t DeviceObserverTest::GetCallCount(uint32_t valueVirtual) -{ - int retry = 0; - uint32_t callTimes = 0; - while (retry < valueVirtual) { - callTimes = value_.GetValue(); - if (callTimes >= valueVirtual) { - break; - } - std::lock_guard guard(mutex_); - callTimes = value_.GetValue(); - if (callTimes >= valueVirtual) { - break; - } - value_.Clear(callTimes); - retry++; - } - return callTimes; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore001 -* @tc.desc: Subscribe success -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore001 begin."); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - auto observerVirtual = std::make_shared(); - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - observerVirtual = nullptr; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore002 -* @tc.desc: Subscribe fail, observerVirtual is null -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore002 begin."); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - std::shared_ptr observerVirtual = nullptr; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::INVALID_ARGUMENT, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore003 -* @tc.desc: Subscribe success and OnChange callback after put -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore003, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore003 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key keyVirtual = "Id1"; - Value valueVirtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(keyVirtual, valueVirtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - observerVirtual = nullptr; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore004 -* @tc.desc: The same observerVirtual subscribe three times and OnChange callback after put -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore004, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore004 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key keyVirtual = "Id1"; - Value valueVirtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(keyVirtual, valueVirtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore005 -* @tc.desc: The different observerVirtual subscribe three times and OnChange callback after put -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore005, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore005 begin."); - auto observer1 = std::make_shared(); - auto observer2 = std::make_shared(); - auto observer3 = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observer1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore failed, wrong statusVirtual"; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observer2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore failed, wrong statusVirtual"; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observer3); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore failed, wrong statusVirtual"; - - Key keyVirtual = "Id1"; - Value valueVirtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(keyVirtual, valueVirtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "Putting data to KvStore failed, wrong statusVirtual"; - EXPECT_EQ(static_cast(observer1->GetCallCount()), 1); - EXPECT_EQ(static_cast(observer2->GetCallCount()), 1); - EXPECT_EQ(static_cast(observer3->GetCallCount()), 1); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observer1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observer2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observer3); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore006 -* @tc.desc: Unsubscribe an observerVirtual and subscribe again - the map should be cleared after unsubscription. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore006, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore006 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - - Key key2Virtual = "Id2"; - Value value2Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key2Virtual, value2Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - - kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - Key key3Virtual = "Id3"; - Value value3Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key3Virtual, value3Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore007 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is called multiple times after the put operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore007, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore007 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key key2Virtual = "Id2"; - Value value2Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key2Virtual, value2Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key key3Virtual = "Id3"; - Value value3Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key3Virtual, value3Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(3)), 3); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore008 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is - called multiple times after the put&update operations. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore008, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore008 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key key2Virtual = "Id2"; - Value value2Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key2Virtual, value2Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key key3Virtual = "Id1"; - Value value3Virtual = "subscribe03"; - statusVirtual = kvStore_Virtual->Put(key3Virtual, value3Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(3)), 3); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore009 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is called multiple times after the putBatch operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore009, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore009 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - // before update. - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id4"; - entryVirtual4.valueVirtual = "subscribe"; - entryVirtual5.keyVirtual = "Id5"; - entryVirtual5.valueVirtual = "subscribe"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - - statusVirtual = kvStore_Virtual->PutBatch(entries1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->PutBatch(entries2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore010 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is - called multiple times after the putBatch update operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore010, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore010 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - // before update. - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id1"; - entryVirtual4.valueVirtual = "modify"; - entryVirtual5.keyVirtual = "Id2"; - entryVirtual5.valueVirtual = "modify"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - - statusVirtual = kvStore_Virtual->PutBatch(entries1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->PutBatch(entries2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore011 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is called after successful deletion. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore011, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore011 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Delete("Id1"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore012 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is not called after deletion of non-existing keys. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore012, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore012 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Delete("Id4"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore013 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is called after KvStore is cleared. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore013, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore013 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore014 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is - not called after non-existing data in KvStore is cleared. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore014, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore014 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore015 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is called after the deleteBatch operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore015, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore015 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore016 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is called after deleteBatch of non-existing keys. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore016, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore016 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keys; - keys.push_back("Id4"); - keys.push_back("Id5"); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore020 -* @tc.desc: Unsubscribe an observerVirtual two times. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore020, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore020 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::STORE_NOT_SUBSCRIBE, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification001 -* @tc.desc: Subscribe to an observerVirtual successfully - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification001 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key keyVirtual = "Id1"; - Value valueVirtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(keyVirtual, valueVirtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - ZLOGD("kvstore_ddm_subscribekvstore_003"); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - ZLOGD("kvstore_ddm_subscribekvstore_003 size:%zu.", observerVirtual->insertEntries_.size()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification002 -* @tc.desc: Subscribe to the same observerVirtual three times - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification002, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification002 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key keyVirtual = "Id1"; - Value valueVirtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(keyVirtual, valueVirtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification003 -* @tc.desc: The different observerVirtual subscribe three times and callback with notification after put -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification003, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification003 begin."); - auto observer1 = std::make_shared(); - auto observer2 = std::make_shared(); - auto observer3 = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observer1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observer2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observer3); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key keyVirtual = "Id1"; - Value valueVirtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(keyVirtual, valueVirtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observer1->GetCallCount()), 1); - EXPECT_EQ(static_cast(observer1->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observer1->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observer1->insertEntries_[0].valueVirtual.ToString()); - - EXPECT_EQ(static_cast(observer2->GetCallCount()), 1); - EXPECT_EQ(static_cast(observer2->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observer2->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observer2->insertEntries_[0].valueVirtual.ToString()); - - EXPECT_EQ(static_cast(observer3->GetCallCount()), 1); - EXPECT_EQ(static_cast(observer3->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observer3->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observer3->insertEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observer1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observer2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observer3); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification004 -* @tc.desc: Verify notification after an observerVirtual is unsubscribed and then subscribed again. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification004, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification004 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - - Key key2Virtual = "Id2"; - Value value2Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key2Virtual, value2Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - Key key3Virtual = "Id3"; - Value value3Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key3Virtual, value3Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id3", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification005 -* @tc.desc: Subscribe to an observerVirtual, callback with notification many times after put the different data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification005, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification005 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - Key key2Virtual = "Id2"; - Value value2Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key2Virtual, value2Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id2", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - Key key3Virtual = "Id3"; - Value value3Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key3Virtual, value3Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(3)), 3); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id3", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification006 -* @tc.desc: Subscribe to an observerVirtual, callback with notification many times after put the same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification006, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification006 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - Key key2Virtual = "Id1"; - Value value2Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key2Virtual, value2Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->updateEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->updateEntries_[0].valueVirtual.ToString()); - - Key key3Virtual = "Id1"; - Value value3Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key3Virtual, value3Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(3)), 3); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->updateEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->updateEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification007 -* @tc.desc: Subscribe to an observerVirtual, callback with notification many times after put&update -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification007, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification007 begin."); - auto observerVirtual = std::make_shared(); - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - Status statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); - // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key key2Virtual = "Id2"; - Value value2Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key2Virtual, value2Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key3Virtual = "Id1"; - Value value3Virtual = "subscribe03"; - statusVirtual = kvStore_Virtual->Put(key3Virtual, value3Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->updateEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe03", observerVirtual->updateEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification008 -* @tc.desc: Subscribe to an observerVirtual, callback with notification one times after putbatch&update -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification008, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification008 begin."); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - entries.clear(); - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe_modify"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe_modify"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 2); - EXPECT_EQ("Id1", observerVirtual->updateEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe_modify", observerVirtual->updateEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->updateEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe_modify", observerVirtual->updateEntries_[1].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification009 -* @tc.desc: Subscribe to an observerVirtual, callback with notification one times after putbatch all different data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification009, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification009 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 3); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->insertEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[1].valueVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtual->insertEntries_[2].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[2].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification010 -* @tc.desc: Subscribe to an observerVirtual, - callback with notification one times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification010, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification010 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id1"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id2"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 2); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->insertEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[1].valueVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 0); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification011 -* @tc.desc: Subscribe to an observerVirtual, callback with notification one times after putbatch all same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification011, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification011 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id1"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id1"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 0); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification012 -* @tc.desc: Subscribe to an observerVirtual, callback with notification many times after putbatch all different data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification012, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id4"; - entryVirtual4.valueVirtual = "subscribe"; - entryVirtual5.keyVirtual = "Id5"; - entryVirtual5.valueVirtual = "subscribe"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - - statusVirtual = kvStore_Virtual->PutBatch(entries1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 3); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->insertEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[1].valueVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtual->insertEntries_[2].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[2].valueVirtual.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification012b -* @tc.desc: Subscribe to an observerVirtual, callback with notification many times after putbatch all different data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification012b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012b begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id4"; - entryVirtual4.valueVirtual = "subscribe"; - entryVirtual5.keyVirtual = "Id5"; - entryVirtual5.valueVirtual = "subscribe"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - - statusVirtual = kvStore_Virtual->PutBatch(entries2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 2); - EXPECT_EQ("Id4", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id5", observerVirtual->insertEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[1].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013 -* @tc.desc: Subscribe to an observerVirtual, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification013, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id1"; - entryVirtual4.valueVirtual = "subscribe"; - entryVirtual5.keyVirtual = "Id4"; - entryVirtual5.valueVirtual = "subscribe"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - - statusVirtual = kvStore_Virtual->PutBatch(entries1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 3); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->insertEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[1].valueVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtual->insertEntries_[2].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[2].valueVirtual.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013b -* @tc.desc: Subscribe to an observerVirtual, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification013b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013b begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id1"; - entryVirtual4.valueVirtual = "subscribe"; - entryVirtual5.keyVirtual = "Id4"; - entryVirtual5.valueVirtual = "subscribe"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - statusVirtual = kvStore_Virtual->PutBatch(entries2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->updateEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->updateEntries_[0].valueVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id4", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification014 -* @tc.desc: Subscribe to an observerVirtual, callback with notification many times after putbatch all same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification014, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification014 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id1"; - entryVirtual4.valueVirtual = "subscribe"; - entryVirtual5.keyVirtual = "Id2"; - entryVirtual5.valueVirtual = "subscribe"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - - statusVirtual = kvStore_Virtual->PutBatch(entries1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 3); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->insertEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[1].valueVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtual->insertEntries_[2].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[2].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->PutBatch(entries2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 2); - EXPECT_EQ("Id1", observerVirtual->updateEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->updateEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->updateEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->updateEntries_[1].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification015 -* @tc.desc: Subscribe to an observerVirtual, callback with notification many times after putbatch complex data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification015, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id1"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id1"; - entryVirtual4.valueVirtual = "subscribe"; - entryVirtual5.keyVirtual = "Id2"; - entryVirtual5.valueVirtual = "subscribe"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - - statusVirtual = kvStore_Virtual->PutBatch(entries1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 0); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 0); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 2); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtual->insertEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[1].valueVirtual.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification015b -* @tc.desc: Subscribe to an observerVirtual, callback with notification many times after putbatch complex data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification015b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015b begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id1"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id1"; - entryVirtual4.valueVirtual = "subscribe"; - entryVirtual5.keyVirtual = "Id2"; - entryVirtual5.valueVirtual = "subscribe"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - statusVirtual = kvStore_Virtual->PutBatch(entries2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->updateEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->updateEntries_[0].valueVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id2", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification016 -* @tc.desc: Pressure test subscribe, callback with notification many times after putbatch -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification016, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification016 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - int times = 100; // 100 times - std::vector entries; - for (int i = 0; i < times; i++) { - Entry entryVirtual; - entryVirtual.keyVirtual = std::to_string(i); - entryVirtual.valueVirtual = "subscribe"; - entries.push_back(entryVirtual); - } - - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 100); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification017 -* @tc.desc: Subscribe to an observerVirtual, callback with notification after delete success -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification017, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification017 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Delete("Id1"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->deleteEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->deleteEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification018 -* @tc.desc: Subscribe to an observerVirtual, not callback after delete which keyVirtual not exist -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification018, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification018 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Delete("Id4"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 0); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification019 -* @tc.desc: Subscribe to an observerVirtual, - delete the same data many times and only first delete callback with notification -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification019, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification019 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Delete("Id1"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->deleteEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->deleteEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->Delete("Id1"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 1); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 1); // not callback so not clear - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification020 -* @tc.desc: Subscribe to an observerVirtual, callback with notification after deleteBatch -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification020, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification020 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 2); - EXPECT_EQ("Id1", observerVirtual->deleteEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->deleteEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->deleteEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->deleteEntries_[1].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification021 -* @tc.desc: Subscribe to an observerVirtual, not callback after deleteBatch which all keys not exist -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification021, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification021 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keys; - keys.push_back("Id4"); - keys.push_back("Id5"); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 0); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification022 -* @tc.desc: Subscribe to an observerVirtual, - deletebatch the same data many times and only first deletebatch callback with -* notification -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification022, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification022 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 2); - EXPECT_EQ("Id1", observerVirtual->deleteEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->deleteEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->deleteEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->deleteEntries_[1].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 1); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 2); // not callback so not clear - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification023 -* @tc.desc: Subscribe to an observerVirtual, include Clear Put PutBatch Delete DeleteBatch -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification023, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification023 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id2"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id3"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id4"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Delete(key1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(4)), 4); - // every callback will clear vector - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 2); - EXPECT_EQ("Id2", observerVirtual->deleteEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->deleteEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtual->deleteEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->deleteEntries_[1].valueVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 0); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification024 -* @tc.desc: Subscribe to an observerVirtual[use transaction], include Clear Put PutBatch Delete DeleteBatch -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification024, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification024 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id2"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id3"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id4"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - statusVirtual = kvStore_Virtual->StartTransaction(); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore startTransaction return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Delete(key1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Commit(); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Commit return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification025 -* @tc.desc: Subscribe to an observerVirtual[use transaction], include Clear Put PutBatch Delete DeleteBatch -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification025, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification025 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id2"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id3"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id4"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - statusVirtual = kvStore_Virtual->StartTransaction(); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore startTransaction return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Delete(key1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Rollback(); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Commit return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 0); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 0); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 0); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - observerVirtual = nullptr; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification026 -* @tc.desc: Subscribe to an observerVirtual[use transaction], include bigData PutBatch update insert delete -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification026, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification026 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries; - Entry entryVirtual0, entryVirtual1, entryVirtual2, entryVirtual3, entryVirtual4; - - int maxValueSize = 2 * 1024 * 1024; // max valueVirtual size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueVirtual = val; - - int maxValueSize2 = 1000 * 1024; // max valueVirtual size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - Value value2Virtual = val2; - - entryVirtual0.keyVirtual = "SingleKvStoreDdmPutBatch006_0"; - entryVirtual0.valueVirtual = "beijing"; - entryVirtual1.keyVirtual = "SingleKvStoreDdmPutBatch006_1"; - entryVirtual1.valueVirtual = valueVirtual; - entryVirtual2.keyVirtual = "SingleKvStoreDdmPutBatch006_2"; - entryVirtual2.valueVirtual = valueVirtual; - entryVirtual3.keyVirtual = "SingleKvStoreDdmPutBatch006_3"; - entryVirtual3.valueVirtual = "ZuiHouBuZhiTianZaiShui"; - entryVirtual4.keyVirtual = "SingleKvStoreDdmPutBatch006_4"; - entryVirtual4.valueVirtual = valueVirtual; - - entries.push_back(entryVirtual0); - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - entries.push_back(entryVirtual4); - - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 5); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_0", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("beijing", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_1", observerVirtual->insertEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_2", observerVirtual->insertEntries_[2].keyVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", observerVirtual->insertEntries_[3].keyVirtual.ToString()); - EXPECT_EQ("ZuiHouBuZhiTianZaiShui", observerVirtual->insertEntries_[3].valueVirtual.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification026b -* @tc.desc: Subscribe to an observerVirtual[use transaction], include bigData PutBatch update insert delete -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification026b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification026b begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries; - Entry entryVirtual5, entryVirtual6, entryVirtual7; - - int maxValueSize = 2 * 1024 * 1024; // max valueVirtual size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueVirtual = val; - - int maxValueSize2 = 1000 * 1024; // max valueVirtual size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - - entryVirtual5.keyVirtual = "SingleKvStoreDdmPutBatch006_2"; - entryVirtual5.valueVirtual = val2; - entryVirtual6.keyVirtual = "SingleKvStoreDdmPutBatch006_3"; - entryVirtual6.valueVirtual = "ManChuanXingMengYaXingHe"; - entryVirtual7.keyVirtual = "SingleKvStoreDdmPutBatch006_4"; - entryVirtual7.valueVirtual = val2; - std::vector updateEntries; - updateEntries.push_back(entryVirtual5); - updateEntries.push_back(entryVirtual6); - updateEntries.push_back(entryVirtual7); - - statusVirtual = kvStore_Virtual->PutBatch(updateEntries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putBatch update data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 3); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_2", observerVirtual->updateEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", observerVirtual->updateEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("ManChuanXingMengYaXingHe", observerVirtual->updateEntries_[1].valueVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_4", observerVirtual->updateEntries_[2].keyVirtual.ToString()); - EXPECT_EQ(false, observerVirtual->isClear_); - - statusVirtual = kvStore_Virtual->Delete("SingleKvStoreDdmPutBatch006_3"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(3)), 3); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 1); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", observerVirtual->deleteEntries_[0].keyVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} \ No newline at end of file diff --git a/kv_store/databaseutils/test/local_subscribe_store_sham_test.cpp b/kv_store/databaseutils/test/local_subscribe_store_sham_test.cpp deleted file mode 100644 index 883c04290184647f4108ebfee03d64a28964498f..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/local_subscribe_store_sham_test.cpp +++ /dev/null @@ -1,2263 +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. - */ - -#define LOG_TAG "LocalSubscribeStoreShamTest" - -#include "block_data.h" -#include "distributed_kv_data_manager.h" -#include "log_print.h" -#include "types.h" -#include -#include -#include -#include -#include - -using namespace testing::ext; -using namespace OHOS; -using namespace OHOS::DistributedKv; -class LocalSubscribeStoreShamTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - - static DistributedKvDataManager managerSham; - static std::shared_ptr kvStoreSham; - static Status statusGetKvStoreSham; - static AppId appIdSham; - static StoreId storeIdSham; -}; -std::shared_ptr LocalSubscribeStoreShamTest::kvStoreSham = nullptr; -Status LocalSubscribeStoreShamTest::statusGetKvStoreSham = Status::ERROR; -DistributedKvDataManager LocalSubscribeStoreShamTest::managerSham; -AppId LocalSubscribeStoreShamTest::appIdSham; -StoreId LocalSubscribeStoreShamTest::storeIdSham; - -void LocalSubscribeStoreShamTest::SetUpTestCase(void) -{ - mkdir("/data/service/el1/public/database/odmf", (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void LocalSubscribeStoreShamTest::TearDownTestCase(void) -{ - managerSham.CloseKvStore(appIdSham, kvStoreSham); - kvStoreSham = nullptr; - managerSham.DeleteKvStore(appIdSham, storeIdSham, "/data/service/el1/public/database/odmf"); - (void)remove("/data/service/el1/public/database/odmf/kvdb"); - (void)remove("/data/service/el1/public/database/odmf"); -} - -void LocalSubscribeStoreShamTest::SetUp(void) -{ - Options optionsSham; - optionsSham.createIfMissing = true; - optionsSham.encrypt = false; // not supported yet. - optionsSham.securityLevel = S1; - optionsSham.autoSync = true; // not supported yet. - optionsSham.kvStoreType = KvStoreType::SINGLE_VERSION; - optionsSham.area = EL1; - optionsSham.baseDir = std::string("/data/service/el1/public/database/odmf"); - appIdSham.appIdSham = "odmf"; // define app name. - storeIdSham.storeIdSham = "student"; // define kvstore(database) name - managerSham.DeleteKvStore(appIdSham, storeIdSham, optionsSham.baseDir); - // [create and] open and initialize kvstore instance. - statusGetKvStoreSham = managerSham.GetSingleKvStore(optionsSham, appIdSham, storeIdSham, kvStoreSham); - ASSERT_EQ(Status::SUCCESS, statusGetKvStoreSham) << "statusGetKvStoreSham return wrong statusSham"; - ASSERT_NE(nullptr, kvStoreSham) << "kvStoreSham is nullptr"; -} - -void LocalSubscribeStoreShamTest::TearDown(void) -{ - managerSham.CloseKvStore(appIdSham, kvStoreSham); - kvStoreSham = nullptr; - managerSham.DeleteKvStore(appIdSham, storeIdSham); -} - -class KvStoreObserverUnitTestSham : public KvStoreObserver { -public: - std::vector insertEntries_Sham; - std::vector updateEntries_Sham; - std::vector deleteEntries_Sham; - bool isClearSham_ = false; - KvStoreObserverUnitTestSham(); - ~KvStoreObserverUnitTestSham() { } - - KvStoreObserverUnitTestSham(const KvStoreObserverUnitTestSham &) = delete; - KvStoreObserverUnitTestSham &operator=(const KvStoreObserverUnitTestSham &) = delete; - KvStoreObserverUnitTestSham(KvStoreObserverUnitTestSham &&) = delete; - KvStoreObserverUnitTestSham &operator=(KvStoreObserverUnitTestSham &&) = delete; - - void OnChangeSham(const ChangeNotification &changeNotification); - - // reset the callCountSham_to zero. - void ResetToZero(); - - uint32_t GetCallCountSham(uint32_t valueShamSham = 1); - -private: - std::mutex mutexSham_; - uint32_t callCountSham_ = 0; - BlockData valueSham_Sham { 1, 0 }; -}; - -KvStoreObserverUnitTestSham::KvStoreObserverUnitTestSham() { } - -void KvStoreObserverUnitTestSham::OnChangeSham(const ChangeNotification &changeNotification) -{ - ZLOGD("begin."); - insertEntries_Sham = changeNotification.GetInsertEntries(); - updateEntries_Sham = changeNotification.GetUpdateEntries(); - deleteEntries_Sham = changeNotification.GetDeleteEntries(); - changeNotification.GetDeviceId(); - isClearSham_ = changeNotification.IsClear(); - std::lock_guard guard(mutexSham_); - ++callCount_Sham; - valueSham_Sham.SetValue(callCount_Sham); -} - -void KvStoreObserverUnitTestSham::ResetToZero() -{ - std::lock_guard guard(mutexSham_); - callCountSham_ = 0; - valueSham_Sham.Clear(0); -} - -uint32_t KvStoreObserverUnitTestSham::GetCallCountSham(uint32_t valueShamSham) -{ - int retrySham = 0; - uint32_t callTimesSham = 0; - while (retrySham < valueShamSham) { - callTimesSham = valueSham_Sham.GetValue(); - if (callTimesSham >= valueShamSham) { - break; - } - std::lock_guard guard(mutexSham_); - callTimesSham = valueSham_Sham.GetValue(); - if (callTimesSham >= valueShamSham) { - break; - } - valueSham_Sham.Clear(callTimesSham); - retrySham++; - } - return callTimesSham; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore001 - * @tc.desc: Subscribe success - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore001 begin."); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - auto observerShamSham = std::make_shared(); - observerShamSham->ResetToZero(); - - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - observerShamSham = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore002 - * @tc.desc: Subscribe fail, observerShamSham is null - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore002 begin."); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - std::shared_ptr observerShamSham = nullptr; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::INVALID_ARGUMENT, statusSham) << "SubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore003 - * @tc.desc: Subscribe success and OnChangeSham callback after put - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore003, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore003 begin."); - auto observerShamSham = std::make_shared(); - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamShamSham = "Id1"; - Value valueShamSham = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamShamSham, valueShamSham); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - observerShamSham = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore004 - * @tc.desc: The same observerShamSham subscribe three times and OnChangeSham callback after put - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore004, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore004 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamShamSham = "Id1"; - Value valueShamSham = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamShamSham, valueShamSham); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore005 - * @tc.desc: The different observerShamSham subscribe three times and OnChangeSham callback after put - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore005, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore005 begin."); - auto observerSham1 = std::make_shared(); - auto observerSham2 = std::make_shared(); - auto observerSham3 = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore failed, wrong statusSham"; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore failed, wrong statusSham"; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerSham3); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore failed, wrong statusSham"; - - Key valueShamShamShamSham = "Id1"; - Value valueShamSham = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamShamSham, valueShamSham); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "Putting data to KvStore failed, wrong statusSham"; - ASSERT_EQ(static_cast(observerSham1->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerSham2->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerSham3->GetCallCountSham()), 1); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerSham3); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore006 -* @tc.desc: Unsubscribe an observerShamSham and - subscribe again - the map should be cleared after unsubscription. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore006, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore006 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham2 = "Id2"; - Value valueSham2 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham2, valueSham2); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - - kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - Key valueShamShamSham3 = "Id3"; - Value valueSham3 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham3, valueSham3); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore007 -* @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is - called multiple times after the put operation. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore007, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore007 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key valueShamShamSham2 = "Id2"; - Value valueSham2 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham2, valueSham2); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key valueShamShamSham3 = "Id3"; - Value valueSham3 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham3, valueSham3); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(3)), 3); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore008 -* @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is - called multiple times after the put&update operations. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore008, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore008 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key valueShamShamSham2 = "Id2"; - Value valueSham2 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham2, valueSham2); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key valueShamShamSham3 = "Id1"; - Value valueSham3 = "subscribe03"; - statusSham = kvStoreSham->Put(valueShamShamSham3, valueSham3); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(3)), 3); - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore009 -* @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is - called multiple times after the putBatch operation. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore009, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore009 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - // before update. - std::vector entriesSham1; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham1.push_back(entrySham1); - entriesSham1.push_back(entrySham2); - entriesSham1.push_back(entrySham3); - - std::vector entriesSham2; - Entry entrySham4, entrySham5; - entrySham4.valueShamShamShamSham = "Id4"; - entrySham4.valueShamSham = "subscribe"; - entrySham5.valueShamShamShamSham = "Id5"; - entrySham5.valueShamSham = "subscribe"; - entriesSham2.push_back(entrySham4); - entriesSham2.push_back(entrySham5); - - statusSham = kvStoreSham->PutBatch(entriesSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStoreSham->PutBatch(entriesSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore010 -* @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is - called multiple times after the putBatch update operation. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore010, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore010 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - // before update. - std::vector entriesSham1; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham1.push_back(entrySham1); - entriesSham1.push_back(entrySham2); - entriesSham1.push_back(entrySham3); - - std::vector entriesSham2; - Entry entrySham4, entrySham5; - entrySham4.valueShamShamShamSham = "Id1"; - entrySham4.valueShamSham = "modify"; - entrySham5.valueShamShamShamSham = "Id2"; - entrySham5.valueShamSham = "modify"; - entriesSham2.push_back(entrySham4); - entriesSham2.push_back(entrySham5); - - statusSham = kvStoreSham->PutBatch(entriesSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStoreSham->PutBatch(entriesSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore011 - * @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is called after successful deletion. - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore011, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore011 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore012 -* @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is - not called after deletion of non-existing valueShamShamShams. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore012, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore012 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->Delete("Id4"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore013 - * @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is called after KvStore is cleared. - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore013, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore013 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(1)), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore014 -* @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is - not called after non-existing data in KvStore is cleared. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore014, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore014 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore015 -* @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is - called after the deleteBatch operation. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore015, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore015 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - std::vector valueShamShamShams; - valueShamShamShams.push_back("Id1"); - valueShamShamShams.push_back("Id2"); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore016 -* @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is - called after deleteBatch of non-existing valueShamShamShams. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore016, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore016 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - std::vector valueShamShamShams; - valueShamShamShams.push_back("Id4"); - valueShamShamShams.push_back("Id5"); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore020 - * @tc.desc: Unsubscribe an observerShamSham two times. - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore020, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore020 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::STORE_NOT_SUBSCRIBE, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification001 -* @tc.desc: Subscribe to an observerShamSham successfully - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification001 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamShamSham = "Id1"; - Value valueShamSham = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamShamSham, valueShamSham); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ZLOGD("kvstore_ddm_subscribekvstore_003"); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ZLOGD("kvstore_ddm_subscribekvstore_003 size:%zu.", observerShamSham->insertEntries_Sham.size()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification002 -* @tc.desc: Subscribe to the same observerShamSham three times - callback - is called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification002, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification002 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamShamSham = "Id1"; - Value valueShamSham = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamShamSham, valueShamSham); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification003 - * @tc.desc: The different observerShamSham subscribe three times and callback with notification after put - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification003, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification003 begin."); - auto observerSham1 = std::make_shared(); - auto observerSham2 = std::make_shared(); - auto observerSham3 = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerSham3); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamShamSham = "Id1"; - Value valueShamSham = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamShamSham, valueShamSham); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham1->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerSham1->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerSham1->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerSham1->insertEntries_Sham[0].valueShamSham.ToString()); - - ASSERT_EQ(static_cast(observerSham2->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerSham2->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerSham2->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerSham2->insertEntries_Sham[0].valueShamSham.ToString()); - - ASSERT_EQ(static_cast(observerSham3->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerSham3->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerSham3->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerSham3->insertEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerSham3); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification004 - * @tc.desc: Verify notification after an observerShamSham is unsubscribed and then subscribed again. - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification004, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification004 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham2 = "Id2"; - Value valueSham2 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham2, valueSham2); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - Key valueShamShamSham3 = "Id3"; - Value valueSham3 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham3, valueSham3); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id3", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification005 -* @tc.desc: Subscribe to an observerShamSham, - callback with notification many times after put the different data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification005, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification005 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - Key valueShamShamSham2 = "Id2"; - Value valueSham2 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham2, valueSham2); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id2", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - Key valueShamShamSham3 = "Id3"; - Value valueSham3 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham3, valueSham3); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(3)), 3); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id3", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification006 - * @tc.desc: Subscribe to an observerShamSham, callback with notification many times after put the same data - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification006, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification006 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - Key valueShamShamSham2 = "Id1"; - Value valueSham2 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham2, valueSham2); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->updateEntries_Sham[0].valueShamSham.ToString()); - - Key valueShamShamSham3 = "Id1"; - Value valueSham3 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham3, valueSham3); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(3)), 3); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->updateEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification007 - * @tc.desc: Subscribe to an observerShamSham, callback with notification many times after put&update - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification007, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification007 begin."); - auto observerShamSham = std::make_shared(); - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - Status statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key valueShamShamSham2 = "Id2"; - Value valueSham2 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham2, valueSham2); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham3 = "Id1"; - Value valueSham3 = "subscribe03"; - statusSham = kvStoreSham->Put(valueShamShamSham3, valueSham3); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe03", observerShamSham->updateEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification008 - * @tc.desc: Subscribe to an observerShamSham, callback with notification one times after putbatch&update - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification008, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification008 begin."); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - entriesSham.clear(); - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe_modify"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe_modify"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 2); - ASSERT_EQ("Id1", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe_modify", observerShamSham->updateEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->updateEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe_modify", observerShamSham->updateEntries_Sham[1].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification009 -* @tc.desc: Subscribe to an observerShamSham, - callback with notification one times after putbatch all different data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification009, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification009 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 3); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ("Id3", observerShamSham->insertEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[2].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification010 -* @tc.desc: Subscribe to an observerShamSham, - callback with notification one times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification010, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification010 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id1"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id2"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 2); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 0); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification011 - * @tc.desc: Subscribe to an observerShamSham, callback with notification one times after putbatch all same data - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification011, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification011 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id1"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id1"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 0); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification012 -* @tc.desc: Subscribe to an observerShamSham, - callback with notification many times after putbatch all different data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification012, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham1; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham1.push_back(entrySham1); - entriesSham1.push_back(entrySham2); - entriesSham1.push_back(entrySham3); - - std::vector entriesSham2; - Entry entrySham4, entrySham5; - entrySham4.valueShamShamShamSham = "Id4"; - entrySham4.valueShamSham = "subscribe"; - entrySham5.valueShamShamShamSham = "Id5"; - entrySham5.valueShamSham = "subscribe"; - entriesSham2.push_back(entrySham4); - entriesSham2.push_back(entrySham5); - - statusSham = kvStoreSham->PutBatch(entriesSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 3); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ("Id3", observerShamSham->insertEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[2].valueShamSham.ToString()); - - statusSham = kvStoreSham->PutBatch(entriesSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 2); - ASSERT_EQ("Id4", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id5", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[1].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013 -* @tc.desc: Subscribe to an observerShamSham, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification013, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham1; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham1.push_back(entrySham1); - entriesSham1.push_back(entrySham2); - entriesSham1.push_back(entrySham3); - - std::vector entriesSham2; - Entry entrySham4, entrySham5; - entrySham4.valueShamShamShamSham = "Id1"; - entrySham4.valueShamSham = "subscribe"; - entrySham5.valueShamShamShamSham = "Id4"; - entrySham5.valueShamSham = "subscribe"; - entriesSham2.push_back(entrySham4); - entriesSham2.push_back(entrySham5); - - statusSham = kvStoreSham->PutBatch(entriesSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 3); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ("Id3", observerShamSham->insertEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[2].valueShamSham.ToString()); - - statusSham = kvStoreSham->PutBatch(entriesSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->updateEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id4", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification014 -* @tc.desc: Subscribe to an observerShamSham, - callback with notification many times after putbatch all same data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification014, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification014 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham1; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham1.push_back(entrySham1); - entriesSham1.push_back(entrySham2); - entriesSham1.push_back(entrySham3); - - std::vector entriesSham2; - Entry entrySham4, entrySham5; - entrySham4.valueShamShamShamSham = "Id1"; - entrySham4.valueShamSham = "subscribe"; - entrySham5.valueShamShamShamSham = "Id2"; - entrySham5.valueShamSham = "subscribe"; - entriesSham2.push_back(entrySham4); - entriesSham2.push_back(entrySham5); - - statusSham = kvStoreSham->PutBatch(entriesSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 3); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ("Id3", observerShamSham->insertEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[2].valueShamSham.ToString()); - - statusSham = kvStoreSham->PutBatch(entriesSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 2); - ASSERT_EQ("Id1", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->updateEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->updateEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->updateEntries_Sham[1].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification015 - * @tc.desc: Subscribe to an observerShamSham, callback with notification many times after putbatch complex data - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification015, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham1; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id1"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham1.push_back(entrySham1); - entriesSham1.push_back(entrySham2); - entriesSham1.push_back(entrySham3); - - std::vector entriesSham2; - Entry entrySham4, entrySham5; - entrySham4.valueShamShamShamSham = "Id1"; - entrySham4.valueShamSham = "subscribe"; - entrySham5.valueShamShamShamSham = "Id2"; - entrySham5.valueShamSham = "subscribe"; - entriesSham2.push_back(entrySham4); - entriesSham2.push_back(entrySham5); - - statusSham = kvStoreSham->PutBatch(entriesSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 0); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 0); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 2); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id3", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[1].valueShamSham.ToString()); - - statusSham = kvStoreSham->PutBatch(entriesSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->updateEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id2", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification016 - * @tc.desc: Pressure test subscribe, callback with notification many times after putbatch - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification016, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification016 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - int times = 100; // 100 times - std::vector entriesSham; - for (int i = 0; i < times; i++) { - Entry entrySham; - entrySham.valueShamShamShamSham = std::to_string(i); - entrySham.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham); - } - - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 100); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification017 - * @tc.desc: Subscribe to an observerShamSham, callback with notification after delete success - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification017, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification017 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->deleteEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->deleteEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification018 -* @tc.desc: Subscribe to an observerShamSham, - not callback after delete which valueShamShamShamSham not exist -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification018, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification018 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->Delete("Id4"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 0); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification019 -* @tc.desc: Subscribe to an observerShamSham, - delete the same data many times and only first delete callback with notification -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification019, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification019 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->deleteEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->deleteEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 1); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 1); - // not callback so not clear - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification020 - * @tc.desc: Subscribe to an observerShamSham, callback with notification after deleteBatch - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification020, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification020 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - std::vector valueShamShamShams; - valueShamShamShams.push_back("Id1"); - valueShamShamShams.push_back("Id2"); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 2); - ASSERT_EQ("Id1", observerShamSham->deleteEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->deleteEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->deleteEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->deleteEntries_Sham[1].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification021 -* @tc.desc: Subscribe to an observerShamSham, - not callback after deleteBatch which all valueShamShamShams not exist -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification021, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification021 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - std::vector valueShamShamShams; - valueShamShamShams.push_back("Id4"); - valueShamShamShams.push_back("Id5"); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 0); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification022 -* @tc.desc: Subscribe to an observerShamSham, - deletebatch the same data many times and only first deletebatch callback with -* notification -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification022, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification022 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - std::vector valueShamShamShams; - valueShamShamShams.push_back("Id1"); - valueShamShamShams.push_back("Id2"); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 2); - ASSERT_EQ("Id1", observerShamSham->deleteEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->deleteEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->deleteEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->deleteEntries_Sham[1].valueShamSham.ToString()); - - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 1); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 2); - // not callback so not clear - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification023 - * @tc.desc: Subscribe to an observerShamSham, include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification023, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification023 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id2"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id3"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id4"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - std::vector valueShamShamShams; - valueShamShamShams.push_back("Id2"); - valueShamShamShams.push_back("Id3"); - - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStoreSham->Delete(valueShamShamSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(4)), 4); - // every callback will clear vector - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 2); - ASSERT_EQ("Id2", observerShamSham->deleteEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->deleteEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id3", observerShamSham->deleteEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->deleteEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 0); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification024 - * @tc.desc: Subscribe to an observerShamSham[use transaction], include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification024, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification024 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id2"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id3"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id4"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - std::vector valueShamShamShams; - valueShamShamShams.push_back("Id2"); - valueShamShamShams.push_back("Id3"); - - statusSham = kvStoreSham->StartTransaction(); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore startTransaction return wrong statusSham"; - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStoreSham->Delete(valueShamShamSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - statusSham = kvStoreSham->Commit(); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Commit return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification025 - * @tc.desc: Subscribe to an observerShamSham[use transaction], include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification025, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification025 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id2"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id3"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id4"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - std::vector valueShamShamShams; - valueShamShamShams.push_back("Id2"); - valueShamShamShams.push_back("Id3"); - - statusSham = kvStoreSham->StartTransaction(); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore startTransaction return wrong statusSham"; - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStoreSham->Delete(valueShamShamSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - statusSham = kvStoreSham->Rollback(); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Commit return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 0); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 0); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 0); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - observerShamSham = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification0261 - * @tc.desc: Subscribe to an observerShamSham[use transaction], include bigData PutBatch update insert delete - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification0261, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0261 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham; - Entry entrySham0, entrySham1, entrySham2; - - int maxValueSize = 2 * 1024 * 1024; // max valueShamSham size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueShamSham = val; - - int maxValueSize2 = 1000 * 1024; // max valueShamSham size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - Value valueSham2 = val2; - - entrySham0.valueShamShamShamSham = "SingleKvStoreDdmPutBatch006_0"; - entrySham0.valueShamSham = "beijing"; - entrySham1.valueShamShamShamSham = "SingleKvStoreDdmPutBatch006_1"; - entrySham1.valueShamSham = valueShamSham; - entrySham2.valueShamShamShamSham = "SingleKvStoreDdmPutBatch006_2"; - entrySham2.valueShamSham = valueShamSham; - - entriesSham.push_back(entrySham0); - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 5); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_0", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("beijing", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_1", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_2", observerShamSham->insertEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_3", observerShamSham->insertEntries_Sham[3].valueShamShamShamSham.ToString()); - ASSERT_EQ("ZuiHouBuZhiTianZaiShui", observerShamSham->insertEntries_Sham[3].valueShamSham.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification0262 - * @tc.desc: Subscribe to an observerShamSham[use transaction], include bigData PutBatch update insert delete - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification0262, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0262 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham; - Entry entrySham3, entrySham4; - - int maxValueSize = 2 * 1024 * 1024; // max valueShamSham size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueShamSham = val; - - int maxValueSize2 = 1000 * 1024; // max valueShamSham size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - Value valueSham2 = val2; - - entrySham3.valueShamShamShamSham = "SingleKvStoreDdmPutBatch006_3"; - entrySham3.valueShamSham = "ZuiHouBuZhiTianZaiShui"; - entrySham4.valueShamShamShamSham = "SingleKvStoreDdmPutBatch006_4"; - entrySham4.valueShamSham = valueShamSham; - - entriesSham.push_back(entrySham3); - entriesSham.push_back(entrySham4); - - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 5); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_0", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("beijing", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_1", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_2", observerShamSham->insertEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_3", observerShamSham->insertEntries_Sham[3].valueShamShamShamSham.ToString()); - ASSERT_EQ("ZuiHouBuZhiTianZaiShui", observerShamSham->insertEntries_Sham[3].valueShamSham.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification0263 - * @tc.desc: Subscribe to an observerShamSham[use transaction], include bigData PutBatch update insert delete - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification0263, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0263 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham; - Entry entrySham5; - - int maxValueSize = 2 * 1024 * 1024; // max valueShamSham size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueShamSham = val; - - int maxValueSize2 = 1000 * 1024; // max valueShamSham size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - - entrySham5.valueShamShamShamSham = "SingleKvStoreDdmPutBatch006_2"; - entrySham5.valueShamSham = val2; - - std::vector updateEntries; - updateEntries.push_back(entrySham5); - - statusSham = kvStoreSham->PutBatch(updateEntries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putBatch update data return wrong statusSham"; - - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 3); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_2", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_3", observerShamSham->updateEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("ManChuanXingMengYaXingHe", observerShamSham->updateEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_4", observerShamSham->updateEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ(false, observerShamSham->isClearSham_); - - statusSham = kvStoreSham->Delete("SingleKvStoreDdmPutBatch006_3"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(3)), 3); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 1); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_3", observerShamSham->deleteEntries_Sham[0].valueShamShamShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification0264 - * @tc.desc: Subscribe to an observerShamSham[use transaction], include bigData PutBatch update insert delete - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification0264, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0264 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham; - Entry entrySham6; - - int maxValueSize = 2 * 1024 * 1024; // max valueShamSham size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueShamSham = val; - - int maxValueSize2 = 1000 * 1024; // max valueShamSham size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - - entrySham6.valueShamShamShamSham = "SingleKvStoreDdmPutBatch006_3"; - entrySham6.valueShamSham = "ManChuanXingMengYaXingHe"; - - std::vector updateEntries; - updateEntries.push_back(entrySham6); - statusSham = kvStoreSham->PutBatch(updateEntries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putBatch update data return wrong statusSham"; - - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 3); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_2", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_3", observerShamSham->updateEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("ManChuanXingMengYaXingHe", observerShamSham->updateEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_4", observerShamSham->updateEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ(false, observerShamSham->isClearSham_); - - statusSham = kvStoreSham->Delete("SingleKvStoreDdmPutBatch006_3"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(3)), 3); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 1); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_3", observerShamSham->deleteEntries_Sham[0].valueShamShamShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification0265 - * @tc.desc: Subscribe to an observerShamSham[use transaction], include bigData PutBatch update insert delete - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification0265, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0265 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham; - Entry entrySham7; - - int maxValueSize = 2 * 1024 * 1024; // max valueShamSham size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueShamSham = val; - - int maxValueSize2 = 1000 * 1024; // max valueShamSham size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - - entrySham7.valueShamShamShamSham = "SingleKvStoreDdmPutBatch006_4"; - entrySham7.valueShamSham = val2; - std::vector updateEntries; - - updateEntries.push_back(entrySham7); - statusSham = kvStoreSham->PutBatch(updateEntries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putBatch update data return wrong statusSham"; - - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 3); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_2", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_3", observerShamSham->updateEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("ManChuanXingMengYaXingHe", observerShamSham->updateEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_4", observerShamSham->updateEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ(false, observerShamSham->isClearSham_); - - statusSham = kvStoreSham->Delete("SingleKvStoreDdmPutBatch006_3"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(3)), 3); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 1); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_3", observerShamSham->deleteEntries_Sham[0].valueShamShamShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} \ No newline at end of file diff --git a/kv_store/databaseutils/test/local_subscribe_store_virtual_test.cpp b/kv_store/databaseutils/test/local_subscribe_store_virtual_test.cpp deleted file mode 100644 index 0cd9b7e2a7f597892313905fb9e4df44d7110cc2..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/local_subscribe_store_virtual_test.cpp +++ /dev/null @@ -1,2272 +0,0 @@ -/* - * 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. - */ - -#define LOG_TAG "LocalSubscribeStoreVirtualTest" -#include -#include -#include -#include -#include "block_data.h" -#include "distributed_kv_data_manager.h" -#include "log_print.h" -#include "types.h" - -using namespace testing::ext; -using namespace OHOS::DistributedKv; -using namespace OHOS; -class LocalSubscribeStoreVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - - static DistributedKvDataManager managerVirtual; - static std::shared_ptr kvStoreVirtual; - static Status statusGetKvStoreVirtual; - static AppId appIdVirtual; - static StoreId storeIdVirtual; -}; -std::shared_ptr LocalSubscribeStoreVirtualTest::kvStoreVirtual = nullptr; -Status LocalSubscribeStoreVirtualTest::statusGetKvStoreVirtual = Status::ERROR; -DistributedKvDataManager LocalSubscribeStoreVirtualTest::managerVirtual; -AppId LocalSubscribeStoreVirtualTest::appIdVirtual; -StoreId LocalSubscribeStoreVirtualTest::storeIdVirtual; - -void LocalSubscribeStoreVirtualTest::SetUpTestCase(void) -{ - mkdir("/data/service/el1/public/database/odmf", (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void LocalSubscribeStoreVirtualTest::TearDownTestCase(void) -{ - managerVirtual.CloseKvStore(appIdVirtual, kvStoreVirtual); - kvStoreVirtual = nullptr; - managerVirtual.DeleteKvStore(appIdVirtual, storeIdVirtual, "/data/service/el1/public/database/odmf"); - (void)remove("/data/service/el1/public/database/odmf/kvdb"); - (void)remove("/data/service/el1/public/database/odmf"); -} - -void LocalSubscribeStoreVirtualTest::SetUp(void) -{ - Options optionsVirtual; - optionsVirtual.createIfMissing = true; - optionsVirtual.encrypt = false; // not supported yet. - optionsVirtual.securityLevel = S1; - optionsVirtual.autoSync = true; // not supported yet. - optionsVirtual.kvStoreType = KvStoreType::SINGLE_VERSION; - optionsVirtual.area = EL1; - optionsVirtual.baseDir = std::string("/data/service/el1/public/database/odmf"); - appIdVirtual.appIdVirtual = "odmf"; // define app name. - storeIdVirtual.storeIdVirtual = "student"; // define kvstore(database) name - managerVirtual.DeleteKvStore(appIdVirtual, storeIdVirtual, optionsVirtual.baseDir); - // [create and] open and initialize kvstore instance. - statusGetKvStoreVirtual = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, kvStoreVirtual); - EXPECT_EQ(Status::SUCCESS, statusGetKvStoreVirtual) << "statusGetKvStoreVirtual return wrong statusVirtual"; - EXPECT_NE(nullptr, kvStoreVirtual) << "kvStoreVirtual is nullptr"; -} - -void LocalSubscribeStoreVirtualTest::TearDown(void) -{ - managerVirtual.CloseKvStore(appIdVirtual, kvStoreVirtual); - kvStoreVirtual = nullptr; - managerVirtual.DeleteKvStore(appIdVirtual, storeIdVirtual); -} - -class KvStoreObserverUnitTestVirtual : public KvStoreObserver { -public: - std::vector insertEntries_Virtual; - std::vector updateEntries_Virtual; - std::vector deleteEntries_Virtual; - bool isClearVirtual_ = false; - KvStoreObserverUnitTestVirtual(); - ~KvStoreObserverUnitTestVirtual() - {} - - KvStoreObserverUnitTestVirtual(const KvStoreObserverUnitTestVirtual &) = delete; - KvStoreObserverUnitTestVirtual &operator=(const KvStoreObserverUnitTestVirtual &) = delete; - KvStoreObserverUnitTestVirtual(KvStoreObserverUnitTestVirtual &&) = delete; - KvStoreObserverUnitTestVirtual &operator=(KvStoreObserverUnitTestVirtual &&) = delete; - - void OnChangeVirtual(const ChangeNotification &changeNotification); - - // reset the callCountVirtual_to zero. - void ResetToZero(); - - uint32_t GetCallCountVirtual(uint32_t valueVirtualVirtual = 1); - -private: - std::mutex mutexVirtual_; - uint32_t callCountVirtual_ = 0; - BlockData valueVirtual_Virtual{ 1, 0 }; -}; - -KvStoreObserverUnitTestVirtual::KvStoreObserverUnitTestVirtual() -{ -} - -void KvStoreObserverUnitTestVirtual::OnChangeVirtual(const ChangeNotification &changeNotification) -{ - ZLOGD("begin."); - insertEntries_Virtual = changeNotification.GetInsertEntries(); - updateEntries_Virtual = changeNotification.GetUpdateEntries(); - deleteEntries_Virtual = changeNotification.GetDeleteEntries(); - changeNotification.GetDeviceId(); - isClearVirtual_ = changeNotification.IsClear(); - std::lock_guard guard(mutexVirtual_); - ++callCount_Virtual; - valueVirtual_Virtual.SetValue(callCount_Virtual); -} - -void KvStoreObserverUnitTestVirtual::ResetToZero() -{ - std::lock_guard guard(mutexVirtual_); - callCountVirtual_ = 0; - valueVirtual_Virtual.Clear(0); -} - -uint32_t KvStoreObserverUnitTestVirtual::GetCallCountVirtual(uint32_t valueVirtualVirtual) -{ - int retryVirtual = 0; - uint32_t callTimesVirtual = 0; - while (retryVirtual < valueVirtualVirtual) { - callTimesVirtual = valueVirtual_Virtual.GetValue(); - if (callTimesVirtual >= valueVirtualVirtual) { - break; - } - std::lock_guard guard(mutexVirtual_); - callTimesVirtual = valueVirtual_Virtual.GetValue(); - if (callTimesVirtual >= valueVirtualVirtual) { - break; - } - valueVirtual_Virtual.Clear(callTimesVirtual); - retryVirtual++; - } - return callTimesVirtual; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore001 -* @tc.desc: Subscribe success -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore001 begin."); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - auto observerVirtualVirtual = std::make_shared(); - observerVirtualVirtual->ResetToZero(); - - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - observerVirtualVirtual = nullptr; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore002 -* @tc.desc: Subscribe fail, observerVirtualVirtual is null -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore002 begin."); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - std::shared_ptr observerVirtualVirtual = nullptr; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::INVALID_ARGUMENT, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore003 -* @tc.desc: Subscribe success and OnChangeVirtual callback after put -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore003, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore003 begin."); - auto observerVirtualVirtual = std::make_shared(); - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtualVirtual = "Id1"; - Value valueVirtualVirtual = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtualVirtual, valueVirtualVirtual); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - observerVirtualVirtual = nullptr; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore004 -* @tc.desc: The same observerVirtualVirtual subscribe three times and OnChangeVirtual callback after put -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore004, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore004 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtualVirtual = "Id1"; - Value valueVirtualVirtual = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtualVirtual, valueVirtualVirtual); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore005 -* @tc.desc: The different observerVirtualVirtual subscribe three times and OnChangeVirtual callback after put -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore005, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore005 begin."); - auto observerVirtual1 = std::make_shared(); - auto observerVirtual2 = std::make_shared(); - auto observerVirtual3 = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore failed, wrong statusVirtual"; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore failed, wrong statusVirtual"; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual3); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore failed, wrong statusVirtual"; - - Key valueVirtualVirtualVirtualVirtual = "Id1"; - Value valueVirtualVirtual = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtualVirtual, valueVirtualVirtual); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "Putting data to KvStore failed, wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual1->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtual2->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtual3->GetCallCountVirtual()), 1); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual3); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore006 -* @tc.desc: Unsubscribe an observerVirtualVirtual and - subscribe again - the map should be cleared after unsubscription. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore006, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore006 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual2 = "Id2"; - Value valueVirtual2 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual2, valueVirtual2); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - - kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - Key valueVirtualVirtualVirtual3 = "Id3"; - Value valueVirtual3 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual3, valueVirtual3); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore007 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is - called multiple times after the put operation. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore007, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore007 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual2 = "Id2"; - Value valueVirtual2 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual2, valueVirtual2); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual3 = "Id3"; - Value valueVirtual3 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual3, valueVirtual3); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(3)), 3); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore008 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is - called multiple times after the put&update operations. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore008, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore008 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual2 = "Id2"; - Value valueVirtual2 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual2, valueVirtual2); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual3 = "Id1"; - Value valueVirtual3 = "subscribe03"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual3, valueVirtual3); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(3)), 3); - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore009 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is - called multiple times after the putBatch operation. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore009, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore009 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - // before update. - std::vector entriesVirtual1; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual1.push_back(entryVirtual1); - entriesVirtual1.push_back(entryVirtual2); - entriesVirtual1.push_back(entryVirtual3); - - std::vector entriesVirtual2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.valueVirtualVirtualVirtualVirtual = "Id4"; - entryVirtual4.valueVirtualVirtual = "subscribe"; - entryVirtual5.valueVirtualVirtualVirtualVirtual = "Id5"; - entryVirtual5.valueVirtualVirtual = "subscribe"; - entriesVirtual2.push_back(entryVirtual4); - entriesVirtual2.push_back(entryVirtual5); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore010 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is - called multiple times after the putBatch update operation. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore010, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore010 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - // before update. - std::vector entriesVirtual1; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual1.push_back(entryVirtual1); - entriesVirtual1.push_back(entryVirtual2); - entriesVirtual1.push_back(entryVirtual3); - - std::vector entriesVirtual2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual4.valueVirtualVirtual = "modify"; - entryVirtual5.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual5.valueVirtualVirtual = "modify"; - entriesVirtual2.push_back(entryVirtual4); - entriesVirtual2.push_back(entryVirtual5); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore011 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is called after successful deletion. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore011, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore011 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Delete("Id1"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore012 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is - not called after deletion of non-existing valueVirtualVirtualVirtuals. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore012, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore012 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Delete("Id4"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore013 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is called after KvStore is cleared. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore013, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore013 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(1)), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore014 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is - not called after non-existing data in KvStore is cleared. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore014, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore014 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore015 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is - called after the deleteBatch operation. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore015, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore015 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - std::vector valueVirtualVirtualVirtuals; - valueVirtualVirtualVirtuals.push_back("Id1"); - valueVirtualVirtualVirtuals.push_back("Id2"); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore016 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is - called after deleteBatch of non-existing valueVirtualVirtualVirtuals. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore016, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore016 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - std::vector valueVirtualVirtualVirtuals; - valueVirtualVirtualVirtuals.push_back("Id4"); - valueVirtualVirtualVirtuals.push_back("Id5"); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore020 -* @tc.desc: Unsubscribe an observerVirtualVirtual two times. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore020, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore020 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::STORE_NOT_SUBSCRIBE, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification001 -* @tc.desc: Subscribe to an observerVirtualVirtual successfully - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification001 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtualVirtual = "Id1"; - Value valueVirtualVirtual = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtualVirtual, valueVirtualVirtual); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - ZLOGD("kvstore_ddm_subscribekvstore_003"); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - ZLOGD("kvstore_ddm_subscribekvstore_003 size:%zu.", observerVirtualVirtual->insertEntries_Virtual.size()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification002 -* @tc.desc: Subscribe to the same observerVirtualVirtual three times - callback - is called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification002, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification002 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtualVirtual = "Id1"; - Value valueVirtualVirtual = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtualVirtual, valueVirtualVirtual); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification003 -* @tc.desc: The different observerVirtualVirtual subscribe three times and callback with notification after put -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification003, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification003 begin."); - auto observerVirtual1 = std::make_shared(); - auto observerVirtual2 = std::make_shared(); - auto observerVirtual3 = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual3); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtualVirtual = "Id1"; - Value valueVirtualVirtual = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtualVirtual, valueVirtualVirtual); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual1->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtual1->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtual1->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual1->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - EXPECT_EQ(static_cast(observerVirtual2->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtual2->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtual2->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual2->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - EXPECT_EQ(static_cast(observerVirtual3->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtual3->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtual3->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual3->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual3); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification004 -* @tc.desc: Verify notification after an observerVirtualVirtual is unsubscribed and then subscribed again. -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification004, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification004 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual2 = "Id2"; - Value valueVirtual2 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual2, valueVirtual2); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - Key valueVirtualVirtualVirtual3 = "Id3"; - Value valueVirtual3 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual3, valueVirtual3); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id3", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification005 -* @tc.desc: Subscribe to an observerVirtualVirtual, - callback with notification many times after put the different data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification005, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification005 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - Key valueVirtualVirtualVirtual2 = "Id2"; - Value valueVirtual2 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual2, valueVirtual2); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id2", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - Key valueVirtualVirtualVirtual3 = "Id3"; - Value valueVirtual3 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual3, valueVirtual3); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(3)), 3); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id3", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification006 -* @tc.desc: Subscribe to an observerVirtualVirtual, callback with notification many times after put the same data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification006, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification006 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - Key valueVirtualVirtualVirtual2 = "Id1"; - Value valueVirtual2 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual2, valueVirtual2); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtual.ToString()); - - Key valueVirtualVirtualVirtual3 = "Id1"; - Value valueVirtual3 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual3, valueVirtual3); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(3)), 3); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification007 -* @tc.desc: Subscribe to an observerVirtualVirtual, callback with notification many times after put&update -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification007, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification007 begin."); - auto observerVirtualVirtual = std::make_shared(); - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - Status statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual2 = "Id2"; - Value valueVirtual2 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual2, valueVirtual2); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual3 = "Id1"; - Value valueVirtual3 = "subscribe03"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual3, valueVirtual3); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe03", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification008 -* @tc.desc: Subscribe to an observerVirtualVirtual, callback with notification one times after putbatch&update -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification008, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification008 begin."); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - entriesVirtual.clear(); - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe_modify"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe_modify"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 2); - EXPECT_EQ("Id1", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe_modify", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe_modify", observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification009 -* @tc.desc: Subscribe to an observerVirtualVirtual, - callback with notification one times after putbatch all different data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification009, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification009 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 3); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification010 -* @tc.desc: Subscribe to an observerVirtualVirtual, - callback with notification one times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification010, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification010 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 2); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification011 -* @tc.desc: Subscribe to an observerVirtualVirtual, callback with notification one times after putbatch all same data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification011, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification011 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification012 -* @tc.desc: Subscribe to an observerVirtualVirtual, - callback with notification many times after putbatch all different data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification012, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual1; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual1.push_back(entryVirtual1); - entriesVirtual1.push_back(entryVirtual2); - entriesVirtual1.push_back(entryVirtual3); - - std::vector entriesVirtual2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.valueVirtualVirtualVirtualVirtual = "Id4"; - entryVirtual4.valueVirtualVirtual = "subscribe"; - entryVirtual5.valueVirtualVirtualVirtualVirtual = "Id5"; - entryVirtual5.valueVirtualVirtual = "subscribe"; - entriesVirtual2.push_back(entryVirtual4); - entriesVirtual2.push_back(entryVirtual5); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 3); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 2); - EXPECT_EQ("Id4", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id5", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013 -* @tc.desc: Subscribe to an observerVirtualVirtual, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification013, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual1; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual1.push_back(entryVirtual1); - entriesVirtual1.push_back(entryVirtual2); - entriesVirtual1.push_back(entryVirtual3); - - std::vector entriesVirtual2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual4.valueVirtualVirtual = "subscribe"; - entryVirtual5.valueVirtualVirtualVirtualVirtual = "Id4"; - entryVirtual5.valueVirtualVirtual = "subscribe"; - entriesVirtual2.push_back(entryVirtual4); - entriesVirtual2.push_back(entryVirtual5); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 3); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id4", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification014 -* @tc.desc: Subscribe to an observerVirtualVirtual, - callback with notification many times after putbatch all same data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification014, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification014 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual1; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual1.push_back(entryVirtual1); - entriesVirtual1.push_back(entryVirtual2); - entriesVirtual1.push_back(entryVirtual3); - - std::vector entriesVirtual2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual4.valueVirtualVirtual = "subscribe"; - entryVirtual5.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual5.valueVirtualVirtual = "subscribe"; - entriesVirtual2.push_back(entryVirtual4); - entriesVirtual2.push_back(entryVirtual5); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 3); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 2); - EXPECT_EQ("Id1", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification015 -* @tc.desc: Subscribe to an observerVirtualVirtual, callback with notification many times after putbatch complex data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification015, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual1; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual1.push_back(entryVirtual1); - entriesVirtual1.push_back(entryVirtual2); - entriesVirtual1.push_back(entryVirtual3); - - std::vector entriesVirtual2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual4.valueVirtualVirtual = "subscribe"; - entryVirtual5.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual5.valueVirtualVirtual = "subscribe"; - entriesVirtual2.push_back(entryVirtual4); - entriesVirtual2.push_back(entryVirtual5); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 2); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id2", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification016 -* @tc.desc: Pressure test subscribe, callback with notification many times after putbatch -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification016, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification016 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - int times = 100; // 100 times - std::vector entriesVirtual; - for (int i = 0; i < times; i++) { - Entry entryVirtual; - entryVirtual.valueVirtualVirtualVirtualVirtual = std::to_string(i); - entryVirtual.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual); - } - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 100); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification017 -* @tc.desc: Subscribe to an observerVirtualVirtual, callback with notification after delete success -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification017, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification017 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Delete("Id1"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification018 -* @tc.desc: Subscribe to an observerVirtualVirtual, - not callback after delete which valueVirtualVirtualVirtualVirtual not exist -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification018, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification018 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Delete("Id4"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification019 -* @tc.desc: Subscribe to an observerVirtualVirtual, - delete the same data many times and only first delete callback with notification -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification019, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification019 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Delete("Id1"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->Delete("Id1"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 1); - // not callback so not clear - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification020 -* @tc.desc: Subscribe to an observerVirtualVirtual, callback with notification after deleteBatch -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification020, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification020 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - std::vector valueVirtualVirtualVirtuals; - valueVirtualVirtualVirtuals.push_back("Id1"); - valueVirtualVirtualVirtuals.push_back("Id2"); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 2); - EXPECT_EQ("Id1", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->deleteEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->deleteEntries_Virtual[1].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification021 -* @tc.desc: Subscribe to an observerVirtualVirtual, - not callback after deleteBatch which all valueVirtualVirtualVirtuals not exist -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification021, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification021 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - std::vector valueVirtualVirtualVirtuals; - valueVirtualVirtualVirtuals.push_back("Id4"); - valueVirtualVirtualVirtuals.push_back("Id5"); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification022 -* @tc.desc: Subscribe to an observerVirtualVirtual, - deletebatch the same data many times and only first deletebatch callback with -* notification -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification022, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification022 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - std::vector valueVirtualVirtualVirtuals; - valueVirtualVirtualVirtuals.push_back("Id1"); - valueVirtualVirtualVirtuals.push_back("Id2"); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 2); - EXPECT_EQ("Id1", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->deleteEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->deleteEntries_Virtual[1].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 2); - // not callback so not clear - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification023 -* @tc.desc: Subscribe to an observerVirtualVirtual, include Clear Put PutBatch Delete DeleteBatch -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification023, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification023 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id4"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - std::vector valueVirtualVirtualVirtuals; - valueVirtualVirtualVirtuals.push_back("Id2"); - valueVirtualVirtualVirtuals.push_back("Id3"); - - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Delete(valueVirtualVirtualVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(4)), 4); - // every callback will clear vector - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 2); - EXPECT_EQ("Id2", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtualVirtual->deleteEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->deleteEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification024 -* @tc.desc: Subscribe to an observerVirtualVirtual[use transaction], include Clear Put PutBatch Delete DeleteBatch -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification024, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification024 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id4"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - std::vector valueVirtualVirtualVirtuals; - valueVirtualVirtualVirtuals.push_back("Id2"); - valueVirtualVirtualVirtuals.push_back("Id3"); - - statusVirtual = kvStoreVirtual->StartTransaction(); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore startTransaction return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Delete(valueVirtualVirtualVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Commit(); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Commit return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification025 -* @tc.desc: Subscribe to an observerVirtualVirtual[use transaction], include Clear Put PutBatch Delete DeleteBatch -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification025, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification025 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id4"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - std::vector valueVirtualVirtualVirtuals; - valueVirtualVirtualVirtuals.push_back("Id2"); - valueVirtualVirtualVirtuals.push_back("Id3"); - - statusVirtual = kvStoreVirtual->StartTransaction(); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore startTransaction return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Delete(valueVirtualVirtualVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Rollback(); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Commit return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - observerVirtualVirtual = nullptr; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification0261 -* @tc.desc: Subscribe to an observerVirtualVirtual[use transaction], include bigData PutBatch update insert delete -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification0261, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0261 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual; - Entry entryVirtual0, entryVirtual1, entryVirtual2; - - int maxValueSize = 2 * 1024 * 1024; // max valueVirtualVirtual size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueVirtualVirtual = val; - - int maxValueSize2 = 1000 * 1024; // max valueVirtualVirtual size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - Value valueVirtual2 = val2; - - entryVirtual0.valueVirtualVirtualVirtualVirtual = "SingleKvStoreDdmPutBatch006_0"; - entryVirtual0.valueVirtualVirtual = "beijing"; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "SingleKvStoreDdmPutBatch006_1"; - entryVirtual1.valueVirtualVirtual = valueVirtualVirtual; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "SingleKvStoreDdmPutBatch006_2"; - entryVirtual2.valueVirtualVirtual = valueVirtualVirtual; - - entriesVirtual.push_back(entryVirtual0); - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 5); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_0", - observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("beijing", - observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_1", - observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_2", - observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", - observerVirtualVirtual->insertEntries_Virtual[3].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("ZuiHouBuZhiTianZaiShui", - observerVirtualVirtual->insertEntries_Virtual[3].valueVirtualVirtual.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification0262 -* @tc.desc: Subscribe to an observerVirtualVirtual[use transaction], include bigData PutBatch update insert delete -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification0262, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0262 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual; - Entry entryVirtual3, entryVirtual4; - - int maxValueSize = 2 * 1024 * 1024; // max valueVirtualVirtual size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueVirtualVirtual = val; - - int maxValueSize2 = 1000 * 1024; // max valueVirtualVirtual size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - Value valueVirtual2 = val2; - - entryVirtual3.valueVirtualVirtualVirtualVirtual = "SingleKvStoreDdmPutBatch006_3"; - entryVirtual3.valueVirtualVirtual = "ZuiHouBuZhiTianZaiShui"; - entryVirtual4.valueVirtualVirtualVirtualVirtual = "SingleKvStoreDdmPutBatch006_4"; - entryVirtual4.valueVirtualVirtual = valueVirtualVirtual; - - entriesVirtual.push_back(entryVirtual3); - entriesVirtual.push_back(entryVirtual4); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 5); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_0", - observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("beijing", - observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_1", - observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_2", - observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", - observerVirtualVirtual->insertEntries_Virtual[3].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("ZuiHouBuZhiTianZaiShui", - observerVirtualVirtual->insertEntries_Virtual[3].valueVirtualVirtual.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification0263 -* @tc.desc: Subscribe to an observerVirtualVirtual[use transaction], include bigData PutBatch update insert delete -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification0263, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0263 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual; - Entry entryVirtual5; - - int maxValueSize = 2 * 1024 * 1024; // max valueVirtualVirtual size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueVirtualVirtual = val; - - int maxValueSize2 = 1000 * 1024; // max valueVirtualVirtual size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - - entryVirtual5.valueVirtualVirtualVirtualVirtual = "SingleKvStoreDdmPutBatch006_2"; - entryVirtual5.valueVirtualVirtual = val2; - - std::vector updateEntries; - updateEntries.push_back(entryVirtual5); - - statusVirtual = kvStoreVirtual->PutBatch(updateEntries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putBatch update data return wrong statusVirtual"; - - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 3); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_2", - observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", - observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("ManChuanXingMengYaXingHe", - observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_4", - observerVirtualVirtual->updateEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ(false, observerVirtualVirtual->isClearVirtual_); - - statusVirtual = kvStoreVirtual->Delete("SingleKvStoreDdmPutBatch006_3"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(3)), 3); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 1); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", - observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification0264 -* @tc.desc: Subscribe to an observerVirtualVirtual[use transaction], include bigData PutBatch update insert delete -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification0264, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0264 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual; - Entry entryVirtual6; - - int maxValueSize = 2 * 1024 * 1024; // max valueVirtualVirtual size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueVirtualVirtual = val; - - int maxValueSize2 = 1000 * 1024; // max valueVirtualVirtual size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - - entryVirtual6.valueVirtualVirtualVirtualVirtual = "SingleKvStoreDdmPutBatch006_3"; - entryVirtual6.valueVirtualVirtual = "ManChuanXingMengYaXingHe"; - - std::vector updateEntries; - updateEntries.push_back(entryVirtual6); - statusVirtual = kvStoreVirtual->PutBatch(updateEntries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putBatch update data return wrong statusVirtual"; - - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 3); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_2", - observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", - observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("ManChuanXingMengYaXingHe", - observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_4", - observerVirtualVirtual->updateEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ(false, observerVirtualVirtual->isClearVirtual_); - - statusVirtual = kvStoreVirtual->Delete("SingleKvStoreDdmPutBatch006_3"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(3)), 3); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 1); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", - observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification0265 -* @tc.desc: Subscribe to an observerVirtualVirtual[use transaction], include bigData PutBatch update insert delete -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification0265, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0265 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual; - Entry entryVirtual7; - - int maxValueSize = 2 * 1024 * 1024; // max valueVirtualVirtual size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueVirtualVirtual = val; - - int maxValueSize2 = 1000 * 1024; // max valueVirtualVirtual size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - - entryVirtual7.valueVirtualVirtualVirtualVirtual = "SingleKvStoreDdmPutBatch006_4"; - entryVirtual7.valueVirtualVirtual = val2; - std::vector updateEntries; - - updateEntries.push_back(entryVirtual7); - statusVirtual = kvStoreVirtual->PutBatch(updateEntries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putBatch update data return wrong statusVirtual"; - - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 3); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_2", - observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", - observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("ManChuanXingMengYaXingHe", - observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_4", - observerVirtualVirtual->updateEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ(false, observerVirtualVirtual->isClearVirtual_); - - statusVirtual = kvStoreVirtual->Delete("SingleKvStoreDdmPutBatch006_3"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(3)), 3); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 1); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", - observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} \ No newline at end of file diff --git a/kv_store/databaseutils/test/single_kvstore_client_virtual_test.cpp b/kv_store/databaseutils/test/single_kvstore_client_virtual_test.cpp deleted file mode 100644 index 0ac2c15037d8bb9dd01e92709380e6168895d2d0..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/single_kvstore_client_virtual_test.cpp +++ /dev/null @@ -1,1555 +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. - */ -#define LOG_TAG "SingleKvStoreClientVirtualTest" - -#include "change_notification.h" -#include "distributed_kv_data_manager.h" -#include "file_ex.h" -#include "iremote_broker.h" -#include "iremote_object.h" -#include "iremote_proxy.h" -#include "iremote_stub.h" -#include "itypes_util.h" -#include "types.h" -#include -#include -#include -#include -#include -#include - -using namespace testing::ext; -using namespace OHOS::DistributedKv; -namespace OHOS::Test { -static constexpr uint64_t MAX_VALUE_SIZE = 4 * 1024 * 1024; // max valVirtualue size is 4M. -class SingleKvStoreClientVirtualTest : public testing::Test { -public: - static std::shared_ptr singleKvStoreVirtual; // declare kvstore instance. - static Status status_; - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -const std::string VALID_SCHEMA_STRICT_DEFINE = "{\"SCHEMA_VERSION\":\"1.0\"," - "\"SCHEMA_MODE\":\"STRICT\"," - "\"SCHEMA_SKIPSIZE\":0," - "\"SCHEMA_DEFINE\":{" - "\"age\":\"INTEGER, NOT NULL\"" - "}," - "\"SCHEMA_INDEXES\":[\"$.age\"]}"; - -std::shared_ptr SingleKvStoreClientVirtualTest::singleKvStoreVirtual = nullptr; -Status SingleKvStoreClientVirtualTest::status_ = Status::ERROR; - -void SingleKvStoreClientVirtualTest::SetUpTestCase(void) -{ - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { - .createIfMissing = true, - .encrypt = false, - .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION - }; - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = std::string("/data/service/el1/public/database/odmf"); - AppId appId = { "odmf" }; - StoreId storeId = { "student_single" }; // define kvstore(database) name. - mkdir(optionsVirtual.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); - // [create and] open and initialize kvstore instance. - status_ = - managerVirtual.GetSingleKvStore(optionsVirtual, appId, storeId, singleKvStoreVirtual); -} - -void SingleKvStoreClientVirtualTest::TearDownTestCase(void) -{ - (void)remove("/data/service/el1/public/database/odmf/keyVirtual"); - (void)remove("/data/service/el1/public/database/odmf/kvdb"); - (void)remove("/data/service/el1/public/database/odmf"); -} - -void SingleKvStoreClientVirtualTest::SetUp(void) { } - -void SingleKvStoreClientVirtualTest::TearDown(void) { } - -class KvStoreObserverTestImplVirtual : public KvStoreObserver { -public: - std::vector insertEntriesVirtual_; - std::vector updateEntriesVirtual_; - std::vector deleteEntriesVirtual_; - bool isClear_ = false; - KvStoreObserverTestImplVirtual(); - ~KvStoreObserverTestImplVirtual() { } - - KvStoreObserverTestImplVirtual(const KvStoreObserverTestImplVirtual &) = delete; - KvStoreObserverTestImplVirtual &operator=(const KvStoreObserverTestImplVirtual &) = delete; - KvStoreObserverTestImplVirtual(KvStoreObserverTestImplVirtual &&) = delete; - KvStoreObserverTestImplVirtual &operator=(KvStoreObserverTestImplVirtual &&) = delete; - - void OnChange(const ChangeNotification &changeNotification); - - // reset the callCount_ to zero. - void ResetToZero(); - - uint64_t GetCallCount() const; - -private: - uint64_t callCount_ = 0; -}; - -void KvStoreObserverTestImplVirtual::OnChange(const ChangeNotification &changeNotification) -{ - callCount_++; - insertEntriesVirtual_ = changeNotification.GetInsertEntries(); - updateEntriesVirtual_ = changeNotification.GetUpdateEntries(); - deleteEntriesVirtual_ = changeNotification.GetDeleteEntries(); - isClear_ = changeNotification.IsClear(); -} - -KvStoreObserverTestImplVirtual::KvStoreObserverTestImplVirtual() { } - -void KvStoreObserverTestImplVirtual::ResetToZero() -{ - callCount_ = 0; -} - -uint64_t KvStoreObserverTestImplVirtual::GetCallCount() const -{ - return callCount_; -} - -class KvStoreSyncCallbackTestImpl : public KvStoreSyncCallback { -public: - void SyncCompleted(const std::map &results); -}; - -void KvStoreSyncCallbackTestImpl::SyncCompleted(const std::map &results) { } - -using var_t = std::variant; - -class TypesUtilVirtualTest : public testing::Test { -public: - class ITestRemoteObject : public IRemoteBroker { - public: - DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.ITestRemoteObject"); - }; - class TestRemoteObjectStub : public IRemoteStub { - public: - }; - class TestRemoteObjectProxy : public IRemoteProxy { - public: - explicit TestRemoteObjectProxy(const sptr &impl) : IRemoteProxy(impl) { } - ~TestRemoteObjectProxy() = default; - - private: - static inline BrokerDelegator delegator_; - }; - class TestRemoteObjectClient : public TestRemoteObjectStub { - public: - TestRemoteObjectClient() { } - virtual ~TestRemoteObjectClient() { } - }; - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void TypesUtilVirtualTest::SetUpTestCase(void) { } - -void TypesUtilVirtualTest::TearDownTestCase(void) { } - -void TypesUtilVirtualTest::SetUp(void) { } - -void TypesUtilVirtualTest::TearDown(void) { } - -/** - * @tc.name: DeviceInfo - * @tc.desc: DeviceInfo function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, DeviceInfo, TestSize.Level0) -{ - ZLOGI("DeviceInfo begin."); - MessageParcel parcelVirtual; - DeviceInfo clientDevVirtual; - clientDevVirtual.deviceId = "123"; - clientDevVirtual.deviceName = "rk3568"; - clientDevVirtual.deviceType = "phone"; - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtual, clientDevVirtual)); - DeviceInfo serverDevVirtual; - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtual, serverDevVirtual)); - EXPECT_EQ(clientDevVirtual.deviceId, serverDevVirtual.deviceId); - EXPECT_EQ(clientDevVirtual.deviceName, serverDevVirtual.deviceName); - EXPECT_EQ(clientDevVirtual.deviceType, serverDevVirtual.deviceType); -} - -/** - * @tc.name: Entry - * @tc.desc: Entry function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, Entry, TestSize.Level0) -{ - ZLOGI("Entry begin."); - MessageParcel parcelVirtual; - Entry entryVirtualIn; - entryVirtualIn.key = "student_name_mali"; - entryVirtualIn.value = "age:20"; - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtual, entryVirtualIn)); - Entry entryVirtualOut; - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtual, entryVirtualOut)); - EXPECT_EQ(entryVirtualOut.key.ToString(), std::string("student_name_mali")); - EXPECT_EQ(entryVirtualOut.value.ToString(), std::string("age:20")); -} - -/** - * @tc.name: ChangeNotification - * @tc.desc: ChangeNotification function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, ChangeNotification, TestSize.Level0) -{ - ZLOGI("ChangeNotification begin."); - Entry insert, update, del; - insert.key = "insert"; - update.key = "update"; - del.key = "delete"; - insert.value = "insert_value"; - update.value = "update_value"; - del.value = "delete_value"; - std::vector inserts, updates, deleteds; - inserts.push_back(insert); - updates.push_back(update); - deleteds.push_back(del); - - ChangeNotification changeIn(std::move(inserts), std::move(updates), std::move(deleteds), std::string(), false); - MessageParcel parcelVirtual; - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtual, changeIn)); - ChangeNotification changeOut({}, {}, {}, "", false); - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtual, changeOut)); - EXPECT_EQ(changeOut.GetInsertEntries().size(), 1UL); - EXPECT_EQ(changeOut.GetInsertEntries().front().key.ToString(), std::string("insert")); - EXPECT_EQ(changeOut.GetInsertEntries().front().value.ToString(), std::string("insert_value")); - EXPECT_EQ(changeOut.GetUpdateEntries().size(), 1UL); - EXPECT_EQ(changeOut.GetUpdateEntries().front().key.ToString(), std::string("update")); - EXPECT_EQ(changeOut.GetUpdateEntries().front().value.ToString(), std::string("update_value")); - EXPECT_EQ(changeOut.GetDeleteEntries().size(), 1UL); - EXPECT_EQ(changeOut.GetDeleteEntries().front().key.ToString(), std::string("delete")); - EXPECT_EQ(changeOut.GetDeleteEntries().front().value.ToString(), std::string("delete_value")); - EXPECT_EQ(changeOut.IsClear(), false); -} - -/** - * @tc.name: Multiple - * @tc.desc: Multiple function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, Multiple, TestSize.Level0) -{ - ZLOGI("Multiple begin."); - uint32_t input1 = 10; - int32_t input2 = -10; - std::string input3 = "i test"; - Blob input4 = "input 4"; - Entry input5; - input5.key = "my test"; - input5.value = "test value"; - DeviceInfo input6 = { .deviceId = "mock deviceId", .deviceName = "mock phone", .deviceType = "0" }; - sptr input7 = new TestRemoteObjectClient(); - MessageParcel parcelVirtual; - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtual, input1, input2, input3, input4, input5, input6, input7->AsObject())); - uint32_t outputVirtual1 = 0; - int32_t outputVirtual2 = 0; - std::string outputVirtual3 = ""; - Blob outputVirtual4; - Entry outputVirtual5; - DeviceInfo outputVirtual6; - sptr outputVirtual7; - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtual, outputVirtual1, outputVirtual2, outputVirtual3, outputVirtual4, - outputVirtual5, outputVirtual6, outputVirtual7)); - EXPECT_EQ(outputVirtual1, input1); - EXPECT_EQ(outputVirtual2, input2); - EXPECT_EQ(outputVirtual3, input3); - EXPECT_EQ(outputVirtual4, input4); - EXPECT_EQ(outputVirtual5.key, input5.key); - EXPECT_EQ(outputVirtual5.value, input5.value); - EXPECT_EQ(outputVirtual6.deviceId, input6.deviceId); - EXPECT_EQ(outputVirtual6.deviceName, input6.deviceName); - EXPECT_EQ(outputVirtual6.deviceType, input6.deviceType); - EXPECT_EQ(outputVirtual7, input7->AsObject()); -} - -/** - * @tc.name: Variant - * @tc.desc: Variant function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, Variant, TestSize.Level0) -{ - ZLOGI("Variant begin."); - MessageParcel parcelVirtualNull; - var_t valueNullIn; - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtualNull, valueNullIn)); - var_t valueNullOut; - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtualNull, valueNullOut)); - EXPECT_EQ(valueNullOut.index(), 0); - - MessageParcel parcelVirtualUint; - var_t valueUintIn; - valueUintIn.emplace<1>(100); - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtualUint, valueUintIn)); - var_t valueUintOut; - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtualUint, valueUintOut)); - EXPECT_EQ(valueUintOut.index(), 1); - EXPECT_EQ(std::get(valueUintOut), 100); - - MessageParcel parcelVirtualString; - var_t valueStringIn; - valueStringIn.emplace<2>("valueString"); - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtualString, valueStringIn)); - var_t valueStringOut; - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtualString, valueStringOut)); - EXPECT_EQ(valueStringOut.index(), 2); - EXPECT_EQ(std::get(valueStringOut), "valueString"); - - MessageParcel parcelVirtualInt; - var_t valueIntIn; - valueIntIn.emplace<3>(101); - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtualInt, valueIntIn)); - var_t valueIntOut; - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtualInt, valueIntOut)); - EXPECT_EQ(valueIntOut.index(), 3); - EXPECT_EQ(std::get(valueIntOut), 101); - - MessageParcel parcelVirtualUint64; - var_t valueUint64In; - valueUint64In.emplace<4>(110); - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtualUint64, valueUint64In)); - var_t valueUint64Out; - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtualUint64, valueUint64Out)); - EXPECT_EQ(valueUint64Out.index(), 4); - EXPECT_EQ(std::get(valueUint64Out), 110); -} - -/** - * @tc.name: MarshalToBufferLimitTest001 - * @tc.desc: MarshalToBufferLimitTest001 function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, MarshalToBufferLimitTest001, TestSize.Level0) -{ - ZLOGI("MarshalToBufferLimitTest001 begin."); - MessageParcel parcelVirtual; - std::vector exceedMaxCountInput(ITypesUtil::MAX_COUNT + 1); - EXPECT_FALSE( - ITypesUtil::MarshalToBuffer(exceedMaxCountInput, sizeof(int) * exceedMaxCountInput.size(), parcelVirtual)); -} - -/** - * @tc.name: MarshalToBufferLimitTest002 - * @tc.desc: construct a invalid vector and check MarshalToBuffer function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, MarshalToBufferLimitTest002, TestSize.Level0) -{ - ZLOGI("MarshalToBufferLimitTest002 begin."); - MessageParcel parcelVirtual; - std::vector inputNormal(10); - EXPECT_FALSE(ITypesUtil::MarshalToBuffer(inputNormal, ITypesUtil::MAX_SIZE + 1, parcelVirtual)); - EXPECT_FALSE(ITypesUtil::MarshalToBuffer(inputNormal, -1, parcelVirtual)); -} - -/** - * @tc.name: UnmarshalFromBufferLimitTest001 - * @tc.desc: construct a invalid parcelVirtual and check UnmarshalFromBuffer function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, UnmarshalFromBufferLimitTest001, TestSize.Level0) -{ - ZLOGI("UnmarshalFromBufferLimitTest001 begin."); - MessageParcel parcelVirtual; - int32_t normalSizeVirtual = 100; - parcelVirtual.WriteInt32(normalSizeVirtual); // normal size - parcelVirtual.WriteInt32(ITypesUtil::MAX_COUNT + 1); // exceed MAX_COUNT - std::unique_ptr buffer = std::make_unique(normalSizeVirtual); - parcelVirtual.WriteRawData(buffer.get(), normalSizeVirtual); - - std::vector outputVirtual; - EXPECT_FALSE(ITypesUtil::UnmarshalFromBuffer(parcelVirtual, outputVirtual)); - EXPECT_TRUE(outputVirtual.empty()); -} - -/** - * @tc.name: UnmarshalFromBufferLimitTest002 - * @tc.desc: construct a invalid parcelVirtual and check UnmarshalFromBuffer function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, UnmarshalFromBufferLimitTest002, TestSize.Level0) -{ - ZLOGI("UnmarshalFromBufferLimitTest002 begin."); - MessageParcel parcelVirtual; - parcelVirtual.WriteInt32(ITypesUtil::MAX_SIZE + 1); // exceedMaxSize size - std::vector outputVirtual; - EXPECT_FALSE(ITypesUtil::UnmarshalFromBuffer(parcelVirtual, outputVirtual)); - EXPECT_TRUE(outputVirtual.empty()); -} - -/** - * @tc.name: GetStoreId001 - * @tc.desc: Get a single KvStore instance. - * @tc.type: FUNC - * @tc.require: SR000DORPS AR000DPRQ7 AR000DDPRPL - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, GetStoreId001, TestSize.Level0) -{ - ZLOGI("GetStoreId001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - - auto storID = singleKvStoreVirtual->GetStoreId(); - ASSERT_EQ(storID.storeId, "student_single"); -} - -/** - * @tc.name: PutGetDelete001 - * @tc.desc: put valVirtualue and delete valVirtualue - * @tc.type: FUNC - * @tc.require: SR000DORPS AR000DPRQ7 AR000DDPRPL - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, PutGetDelete001, TestSize.Level0) -{ - ZLOGI("PutGetDelete001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - - Key skeyVirtual = { "single_001" }; - Value svalVirtual = { "valVirtualue_001" }; - auto statusVirtual = singleKvStoreVirtual->Put(skeyVirtual, svalVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS) << "putting data failed"; - - auto delStatus = singleKvStoreVirtual->Delete(skeyVirtual); - ASSERT_EQ(delStatus, Status::SUCCESS) << "deleting data failed"; - - auto notExistStatus = singleKvStoreVirtual->Delete(skeyVirtual); - ASSERT_EQ(notExistStatus, Status::SUCCESS) << "deleting non-existing data failed"; - - auto spaceStatus = singleKvStoreVirtual->Put(skeyVirtual, { "" }); - ASSERT_EQ(spaceStatus, Status::SUCCESS) << "putting space failed"; - - auto spaceKeyStatus = singleKvStoreVirtual->Put({ "" }, { "" }); - ASSERT_NE(spaceKeyStatus, Status::SUCCESS) << "putting space keyVirtuals failed"; - - Status valVirtualidStatus = singleKvStoreVirtual->Put(skeyVirtual, svalVirtual); - ASSERT_EQ(valVirtualidStatus, - Status::SUCCESS) << "putting valVirtualid keyVirtuals and valVirtualues failed"; - - Value rVal; - auto valVirtualidPutStatus = singleKvStoreVirtual->Get(skeyVirtual, rVal); - ASSERT_EQ(valVirtualidPutStatus, Status::SUCCESS) << "Getting valVirtualue failed"; - ASSERT_EQ(svalVirtual, rVal) << "Got and put valVirtualues not equal"; -} - -/** - * @tc.name: GetEntriesAndResultSet001 - * @tc.desc: Batch put valVirtualues and get valVirtualues. - * @tc.type: FUNC - * @tc.require: SR000DORPS AR000DPRQ7 AR000DDPRPL - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, GetEntriesAndResultSet001, TestSize.Level0) -{ - ZLOGI("GetEntriesAndResultSet001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - - // prepare 10 - size_t sum = 10; - int sum1 = 10; - std::string prefix = "prefix_"; - for (size_t i = 0; i < sum; i++) { - singleKvStoreVirtual->Put({ prefix + std::to_string(i) }, { std::to_string(i) }); - } - - std::vector results; - singleKvStoreVirtual->GetEntries({ prefix }, results); - ASSERT_EQ(results.size(), sum) << "entries size is not equal 10."; - - std::shared_ptr resultSetVirtual; - Status statusVirtual = - singleKvStoreVirtual->GetResultSet({ prefix }, resultSetVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_EQ(resultSetVirtual->GetCount(), sum1) << "resultSetVirtual size is not equal 10."; - resultSetVirtual->IsFirst(); - resultSetVirtual->IsAfterLast(); - resultSetVirtual->IsBeforeFirst(); - resultSetVirtual->MoveToPosition(1); - resultSetVirtual->IsLast(); - resultSetVirtual->MoveToPrevious(); - resultSetVirtual->MoveToNext(); - resultSetVirtual->MoveToLast(); - resultSetVirtual->MoveToFirst(); - resultSetVirtual->GetPosition(); - Entry entryVirtual; - resultSetVirtual->GetEntry(entryVirtual); - - for (size_t i = 0; i < sum; i++) { - singleKvStoreVirtual->Delete({ prefix + std::to_string(i) }); - } - - auto closeResultSetStatus = singleKvStoreVirtual->CloseResultSet(resultSetVirtual); - ASSERT_EQ(closeResultSetStatus, Status::SUCCESS) << "close resultSetVirtual failed."; -} - -/** - * @tc.name: GetEntriesByDataQuery - * @tc.desc: Batch put valVirtualues and get valVirtualues. - * @tc.type: FUNC - * @tc.require: I5GFGR - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, GetEntriesByDataQuery, TestSize.Level0) -{ - ZLOGI("GetEntriesByDataQuery begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - - // prepare 10 - size_t sum = 10; - int sum1 = 10; - std::string prefix = "prefix_"; - for (size_t i = 0; i < sum; i++) { - singleKvStoreVirtual->Put({ prefix + std::to_string(i) }, { std::to_string(i) }); - } - - std::vector results; - singleKvStoreVirtual->GetEntries({ prefix }, results); - ASSERT_EQ(results.size(), sum) << "entries size is not equal 10."; - DataQuery dataQueryVirtual; - dataQueryVirtual.KeyPrefix(prefix); - dataQueryVirtual.Limit(10, 0); - std::shared_ptr resultSetVirtual; - Status statusVirtual = - singleKvStoreVirtual->GetResultSet(dataQueryVirtual, resultSetVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_EQ(resultSetVirtual->GetCount(), sum1) << "resultSetVirtual size is not equal 10."; - resultSetVirtual->IsFirst(); - resultSetVirtual->IsAfterLast(); - resultSetVirtual->IsBeforeFirst(); - resultSetVirtual->MoveToPosition(1); - resultSetVirtual->IsLast(); - resultSetVirtual->MoveToPrevious(); - resultSetVirtual->MoveToNext(); - resultSetVirtual->MoveToLast(); - resultSetVirtual->MoveToFirst(); - resultSetVirtual->GetPosition(); - Entry entryVirtual; - resultSetVirtual->GetEntry(entryVirtual); - - for (size_t i = 0; i < sum; i++) { - singleKvStoreVirtual->Delete({ prefix + std::to_string(i) }); - } - - auto closeResultSetStatus = singleKvStoreVirtual->CloseResultSet(resultSetVirtual); - ASSERT_EQ(closeResultSetStatus, Status::SUCCESS) << "close resultSetVirtual failed."; -} - -/** - * @tc.name: GetEmptyEntries - * @tc.desc: Batch get empty valVirtualues. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, GetEmptyEntries, TestSize.Level0) -{ - ZLOGI("GetEmptyEntries begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - std::vector results; - auto statusVirtual = singleKvStoreVirtual->GetEntries({ "SUCCESS_TEST" }, results); - ASSERT_EQ(statusVirtual, Status::SUCCESS) << "statusVirtual is not SUCCESS."; - ASSERT_EQ(results.size(), 0) << "entries size is not empty."; -} - -/** - * @tc.name: Subscribe001 - * @tc.desc: Put data and get callback. - * @tc.type: FUNC - * @tc.require: SR000DORPS AR000DPRQ7 AR000DDPRPL - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, Subscribe001, TestSize.Level0) -{ - ZLOGI("Subscribe001 begin."); - auto observer = std::make_shared(); - auto subStatus = - singleKvStoreVirtual->SubscribeKvStore(SubscribeType::SUBSCRIBE_TYPE_ALL, observer); - ASSERT_EQ(subStatus, Status::SUCCESS) << "subscribe kvStore observer failed."; - // subscribe repeated observer; - auto repeatedSubStatus = - singleKvStoreVirtual->SubscribeKvStore(SubscribeType::SUBSCRIBE_TYPE_ALL, observer); - ASSERT_NE(repeatedSubStatus, Status::SUCCESS) << "repeat subscribe kvStore observer failed."; - - auto unSubStatus = - singleKvStoreVirtual->UnSubscribeKvStore(SubscribeType::SUBSCRIBE_TYPE_ALL, observer); - ASSERT_EQ(unSubStatus, Status::SUCCESS) << "unsubscribe kvStore observer failed."; -} - -/** - * @tc.name: SyncCallback001 - * @tc.desc: Register sync callback. - * @tc.type: FUNC - * @tc.require: SR000DORPS AR000DPRQ7 AR000DDPRPL - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, SyncCallback001, TestSize.Level0) -{ - ZLOGI("SyncCallback001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - - auto syncCallback = std::make_shared(); - auto syncStatus = singleKvStoreVirtual->RegisterSyncCallback(syncCallback); - ASSERT_EQ(syncStatus, Status::SUCCESS) << "register sync callback failed."; - - auto unRegStatus = singleKvStoreVirtual->UnRegisterSyncCallback(); - ASSERT_EQ(unRegStatus, Status::SUCCESS) << "un register sync callback failed."; - - Key skeyVirtual = { "single_001" }; - Value svalVirtual = { "valVirtualue_001" }; - singleKvStoreVirtual->Put(skeyVirtual, svalVirtual); - singleKvStoreVirtual->Delete(skeyVirtual); - - std::map results; - results.insert({ "aaa", Status::INVALID_ARGUMENT }); - syncCallback->SyncCompleted(results); -} - -/** - * @tc.name: RemoveDeviceData001 - * @tc.desc: Remove device data. - * @tc.type: FUNC - * @tc.require: SR000DORPS AR000DPRQ7 AR000DDPRPL - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, RemoveDeviceData001, TestSize.Level0) -{ - ZLOGI("RemoveDeviceData001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - - Key skeyVirtual = { "single_001" }; - Value svalVirtual = { "valVirtualue_001" }; - singleKvStoreVirtual->Put(skeyVirtual, svalVirtual); - - std::string deviceId = "no_exist_device_id"; - auto removeStatus = singleKvStoreVirtual->RemoveDeviceData(deviceId); - ASSERT_NE(removeStatus, Status::SUCCESS) << "remove device should not return success"; - - Value retVal; - auto getRet = singleKvStoreVirtual->Get(skeyVirtual, retVal); - ASSERT_EQ(getRet, Status::SUCCESS) << "get valVirtualue failed."; - ASSERT_EQ(retVal.Size(), svalVirtual.Size()) << "data base should be null."; -} - -/** - * @tc.name: SyncData001 - * @tc.desc: Synchronize device data. - * @tc.type: FUNC - * @tc.require: SR000DORPS AR000DPRQ7 AR000DDPRPL - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, SyncData001, TestSize.Level0) -{ - ZLOGI("SyncData001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - std::string deviceId = "no_exist_device_id"; - std::vector deviceIds = { deviceId }; - auto syncStatus = singleKvStoreVirtual->Sync(deviceIds, SyncMode::PUSH); - ASSERT_NE(syncStatus, Status::SUCCESS) << "sync device should not return success"; -} - -/** - * @tc.name: TestSchemaStoreC001 - * @tc.desc: Test schema single store. - * @tc.type: FUNC - * @tc.require: AR000DPSF1 - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, TestSchemaStoreC001, TestSize.Level0) -{ - ZLOGI("TestSchemaStoreC001 begin."); - std::shared_ptr schemasingleKvStore; - DistributedKvDataManager managerVirtual; - Options optionsVirtual; - optionsVirtual.encrypt = true; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.kvStoreType = KvStoreType::SINGLE_VERSION; - optionsVirtual.baseDir = "/data/service/el1/public/database/odmf"; - optionsVirtual.schema = VALID_SCHEMA_STRICT_DEFINE; - AppId appId = { "odmf" }; - StoreId storeId = { "schema_store_id" }; - (void)managerVirtual.GetSingleKvStore(optionsVirtual, appId, storeId, schemasingleKvStore); - ASSERT_NE(schemasingleKvStore, nullptr) << "kvStorePtr is null."; - auto result = schemasingleKvStore->GetStoreId(); - ASSERT_EQ(result.storeId, "schema_store_id"); - - Key testKey = { "TestSchemaStoreC001_keyVirtual" }; - Value testValue = { "{\"age\":10}" }; - auto testStatus = schemasingleKvStore->Put(testKey, testValue); - ASSERT_EQ(testStatus, Status::SUCCESS) << "putting data failed"; - Value resultValue; - auto getRet = schemasingleKvStore->Get(testKey, resultValue); - ASSERT_EQ(getRet, Status::SUCCESS) << "get valVirtualue failed."; - managerVirtual.DeleteKvStore(appId, storeId, optionsVirtual.baseDir); -} - -/** - * @tc.name: SyncData002 - * @tc.desc: Synchronize device data. - * @tc.type: FUNC - * @tc.require: SR000DOGQE AR000DPUAN - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, SyncData002, TestSize.Level0) -{ - ZLOGI("SyncData002 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - std::string deviceId = "no_exist_device_id"; - std::vector deviceIds = { deviceId }; - uint32_t allowedDelayMs = 200; - auto syncStatus = singleKvStoreVirtual->Sync(deviceIds, SyncMode::PUSH, allowedDelayMs); - ASSERT_EQ(syncStatus, Status::SUCCESS) << "sync device should return success"; -} - -/** - * @tc.name: SetSync001 - * @tc.desc: Set sync parameters - success. - * @tc.type: FUNC - * @tc.require: SR000DOGQE AR000DPUAO - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, SetSync001, TestSize.Level0) -{ - ZLOGI("SetSync001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - KvSyncParam syncParam { 500 }; // 500ms - auto retVirtual = singleKvStoreVirtual->SetSyncParam(syncParam); - ASSERT_EQ(retVirtual, Status::SUCCESS) << "set sync param should return success"; - - KvSyncParam syncParamRet; - singleKvStoreVirtual->GetSyncParam(syncParamRet); - ASSERT_EQ(syncParamRet.allowedDelayMs, syncParam.allowedDelayMs); -} - -/** - * @tc.name: SyncData002 - * @tc.desc: Set sync parameters - failed. - * @tc.type: FUNC - * @tc.require: SR000DOGQE AR000DPUAO - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, SetSync002, TestSize.Level0) -{ - ZLOGI("SetSync002 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - KvSyncParam syncParam2 { 50 }; // 50ms - auto retVirtual = singleKvStoreVirtual->SetSyncParam(syncParam2); - ASSERT_NE(retVirtual, Status::SUCCESS) << "set sync param should not return success"; - - KvSyncParam syncParamRet2; - retVirtual = singleKvStoreVirtual->GetSyncParam(syncParamRet2); - ASSERT_NE(syncParamRet2.allowedDelayMs, syncParam2.allowedDelayMs); -} - -/** - * @tc.name: DdmPutBatch001 - * @tc.desc: Batch put data. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmPutBatch001, TestSize.Level2) -{ - ZLOGI("DdmPutBatch001 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - // store entries to kvstore. - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "KvStoreDdmPutBatch001_1"; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "KvStoreDdmPutBatch001_2"; - entryVirtual2.valVirtualue = "age:19"; - entryVirtual3.keyVirtual = "KvStoreDdmPutBatch001_3"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - // get valVirtualue from kvstore. - Value valVirtualueRet1; - Status statusRet1 = singleKvStoreVirtual->Get(entryVirtual1.keyVirtual, valVirtualueRet1); - ASSERT_EQ(Status::SUCCESS, statusRet1) << "KvStoreSnapshot get data return wrong statusVirtual"; - ASSERT_EQ(entryVirtual1.valVirtualue, valVirtualueRet1) << "valVirtualue and valVirtualueRet are not equal"; - - Value valVirtualueRet2; - Status statusRet2 = singleKvStoreVirtual->Get(entryVirtual2.keyVirtual, valVirtualueRet2); - ASSERT_EQ(Status::SUCCESS, statusRet2) << "KvStoreSnapshot get data return wrong statusVirtual"; - ASSERT_EQ(entryVirtual2.valVirtualue, valVirtualueRet2) << "valVirtualue and valVirtualueRet are not equal"; - - Value valVirtualueRet3; - Status statusRet3 = singleKvStoreVirtual->Get(entryVirtual3.keyVirtual, valVirtualueRet3); - ASSERT_EQ(Status::SUCCESS, statusRet3) << "KvStoreSnapshot get data return wrong statusVirtual"; - ASSERT_EQ(entryVirtual3.valVirtualue, valVirtualueRet3) << "valVirtualue and valVirtualueRet are not equal"; -} - -/** - * @tc.name: DdmPutBatch002 - * @tc.desc: Batch update data. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmPutBatch002, TestSize.Level2) -{ - ZLOGI("DdmPutBatch002 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - // before update. - std::vector entriesBefore; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreDdmPutBatch002_1"; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "SingleKvStoreDdmPutBatch002_2"; - entryVirtual2.valVirtualue = "age:19"; - entryVirtual3.keyVirtual = "SingleKvStoreDdmPutBatch002_3"; - entryVirtual3.valVirtualue = "age:23"; - entriesBefore.push_back(entryVirtual1); - entriesBefore.push_back(entryVirtual2); - entriesBefore.push_back(entryVirtual3); - - Status statusVirtual = singleKvStoreVirtual->PutBatch(entriesBefore); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore putbatch data return wrong statusVirtual"; - - // after update. - std::vector entriesAfter; - Entry entryVirtual4, entryVirtual5, entryVirtual6; - entryVirtual4.keyVirtual = "SingleKvStoreDdmPutBatch002_1"; - entryVirtual4.valVirtualue = "age:20, sex:girl"; - entryVirtual5.keyVirtual = "SingleKvStoreDdmPutBatch002_2"; - entryVirtual5.valVirtualue = "age:19, sex:boy"; - entryVirtual6.keyVirtual = "SingleKvStoreDdmPutBatch002_3"; - entryVirtual6.valVirtualue = "age:23, sex:girl"; - entriesAfter.push_back(entryVirtual4); - entriesAfter.push_back(entryVirtual5); - entriesAfter.push_back(entryVirtual6); - - statusVirtual = singleKvStoreVirtual->PutBatch(entriesAfter); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore putbatch failed, wrong statusVirtual"; - - // get valVirtualue from kvstore. - Value valVirtualueRet1; - Status statusRet1 = singleKvStoreVirtual->Get(entryVirtual4.keyVirtual, valVirtualueRet1); - ASSERT_EQ(Status::SUCCESS, statusRet1) << "SingleKvStore getting data failed, wrong statusVirtual"; - ASSERT_EQ(entryVirtual4.valVirtualue, valVirtualueRet1) << "valVirtualue and valVirtualueRet are not equal"; - - Value valVirtualueRet2; - Status statusRet2 = singleKvStoreVirtual->Get(entryVirtual5.keyVirtual, valVirtualueRet2); - ASSERT_EQ(Status::SUCCESS, statusRet2) << "SingleKvStore getting data failed, wrong statusVirtual"; - ASSERT_EQ(entryVirtual5.valVirtualue, valVirtualueRet2) << "valVirtualue and valVirtualueRet are not equal"; - - Value valVirtualueRet3; - Status statusRet3 = singleKvStoreVirtual->Get(entryVirtual6.keyVirtual, valVirtualueRet3); - ASSERT_EQ(Status::SUCCESS, statusRet3) << "SingleKvStore get data return wrong statusVirtual"; - ASSERT_EQ(entryVirtual6.valVirtualue, valVirtualueRet3) << "valVirtualue and valVirtualueRet are not equal"; -} - -/** - * @tc.name: DdmPutBatch003 - * @tc.desc: Batch put data that contains invalVirtualid data. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmPutBatch003, TestSize.Level2) -{ - ZLOGI("DdmPutBatch003 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = " "; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "student_name_caixu"; - entryVirtual2.valVirtualue = " "; - entryVirtual3.keyVirtual = "student_name_liuyue"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::INVALID_ARGUMENT, - statusVirtual) << "singleKvStoreVirtual putbatch data return wrong statusVirtual"; -} - -/** - * @tc.name: DdmPutBatch004 - * @tc.desc: Batch put data that contains invalVirtualid data. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmPutBatch004, TestSize.Level2) -{ - ZLOGI("DdmPutBatch004 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = ""; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "student_name_caixu"; - entryVirtual2.valVirtualue = ""; - entryVirtual3.keyVirtual = "student_name_liuyue"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::INVALID_ARGUMENT, - statusVirtual) << "singleKvStoreVirtual putbatch data return wrong statusVirtual"; -} - -static std::string SingleGenerate1025KeyLen() -{ - std::string str("prefix"); - // Generate a keyVirtual with a length of more than 1024 bytes. - for (int i = 0; i < 1024; i++) { - str += "a"; - } - return str; -} - -/** - * @tc.name: DdmPutBatch005 - * @tc.desc: Batch put data that contains invalVirtualid data. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmPutBatch005, TestSize.Level2) -{ - ZLOGI("DdmPutBatch005 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = SingleGenerate1025KeyLen(); - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "student_name_caixu"; - entryVirtual2.valVirtualue = "age:19"; - entryVirtual3.keyVirtual = "student_name_liuyue"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::INVALID_ARGUMENT, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; -} - -/** - * @tc.name: DdmPutBatch006 - * @tc.desc: Batch put large data. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmPutBatch006, TestSize.Level2) -{ - ZLOGI("DdmPutBatch006 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - std::vector valVirtual(MAX_VALUE_SIZE); - for (int i = 0; i < MAX_VALUE_SIZE; i++) { - valVirtual[i] = static_cast(i); - } - Value valVirtualue = valVirtual; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreDdmPutBatch006_1"; - entryVirtual1.valVirtualue = valVirtualue; - entryVirtual2.keyVirtual = "SingleKvStoreDdmPutBatch006_2"; - entryVirtual2.valVirtualue = valVirtualue; - entryVirtual3.keyVirtual = "SingleKvStoreDdmPutBatch006_3"; - entryVirtual3.valVirtualue = valVirtualue; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - Status statusVirtual = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "singleKvStoreVirtual putbatch data return wrong statusVirtual"; - - // get valVirtualue from kvstore. - Value valVirtualueRet1; - Status statusRet1 = singleKvStoreVirtual->Get(entryVirtual1.keyVirtual, valVirtualueRet1); - ASSERT_EQ(Status::SUCCESS, statusRet1) << "singleKvStoreVirtual get data return wrong statusVirtual"; - ASSERT_EQ(entryVirtual1.valVirtualue, valVirtualueRet1) << "valVirtualue and valVirtualueRet are not equal"; - - Value valVirtualueRet2; - Status statusRet2 = singleKvStoreVirtual->Get(entryVirtual2.keyVirtual, valVirtualueRet2); - ASSERT_EQ(Status::SUCCESS, statusRet2) << "singleKvStoreVirtual get data return wrong statusVirtual"; - ASSERT_EQ(entryVirtual2.valVirtualue, valVirtualueRet2) << "valVirtualue and valVirtualueRet are not equal"; - - Value valVirtualueRet3; - Status statusRet3 = singleKvStoreVirtual->Get(entryVirtual3.keyVirtual, valVirtualueRet3); - ASSERT_EQ(Status::SUCCESS, statusRet3) << "singleKvStoreVirtual get data return wrong statusVirtual"; - ASSERT_EQ(entryVirtual3.valVirtualue, valVirtualueRet3) << "valVirtualue and valVirtualueRet are not equal"; -} - -/** - * @tc.name: DdmDeleteBatch001 - * @tc.desc: Batch delete data. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmDeleteBatch001, TestSize.Level2) -{ - ZLOGI("DdmDeleteBatch001 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - // store entries to kvstore. - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreDdmDeleteBatch001_1"; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "SingleKvStoreDdmDeleteBatch001_2"; - entryVirtual2.valVirtualue = "age:19"; - entryVirtual3.keyVirtual = "SingleKvStoreDdmDeleteBatch001_3"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keyVirtuals; - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch001_1"); - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch001_2"); - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch001_3"); - - Status status1 = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, status1) << "singleKvStoreVirtual putbatch data return wrong statusVirtual"; - - Status status2 = singleKvStoreVirtual->DeleteBatch(keyVirtuals); - ASSERT_EQ(Status::SUCCESS, status2) << "singleKvStoreVirtual deletebatch data return wrong statusVirtual"; - std::vector results; - singleKvStoreVirtual->GetEntries("SingleKvStoreDdmDeleteBatch001_", results); - size_t sum = 0; - ASSERT_EQ(results.size(), sum) << "entries size is not equal 0."; -} - -/** - * @tc.name: DdmDeleteBatch002 - * @tc.desc: Batch delete data when some keyVirtuals are not in KvStore. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmDeleteBatch002, TestSize.Level2) -{ - ZLOGI("DdmDeleteBatch002 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - // store entries to kvstore. - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreDdmDeleteBatch002_1"; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "SingleKvStoreDdmDeleteBatch002_2"; - entryVirtual2.valVirtualue = "age:19"; - entryVirtual3.keyVirtual = "SingleKvStoreDdmDeleteBatch002_3"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keyVirtuals; - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch002_1"); - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch002_2"); - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch002_3"); - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch002_4"); - - Status status1 = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, status1) << "KvStore putbatch data return wrong statusVirtual"; - - Status status2 = singleKvStoreVirtual->DeleteBatch(keyVirtuals); - ASSERT_EQ(Status::SUCCESS, status2) << "KvStore deletebatch data return wrong statusVirtual"; - std::vector results; - singleKvStoreVirtual->GetEntries("SingleKvStoreDdmDeleteBatch002_", results); - size_t sum = 0; - ASSERT_EQ(results.size(), sum) << "entries size is not equal 0."; -} - -/** - * @tc.name: DdmDeleteBatch003 - * @tc.desc: Batch delete data when some keyVirtuals are invalVirtualid. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmDeleteBatch003, TestSize.Level2) -{ - ZLOGI("DdmDeleteBatch003 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - // Store entries to KvStore. - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreDdmDeleteBatch003_1"; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "SingleKvStoreDdmDeleteBatch003_2"; - entryVirtual2.valVirtualue = "age:19"; - entryVirtual3.keyVirtual = "SingleKvStoreDdmDeleteBatch003_3"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keyVirtuals; - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch003_1"); - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch003_2"); - keyVirtuals.push_back(""); - - Status status1 = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, status1) << "SingleKvStore putbatch data return wrong statusVirtual"; - - Status status2 = singleKvStoreVirtual->DeleteBatch(keyVirtuals); - ASSERT_EQ(Status::INVALID_ARGUMENT, status2) << "KvStore deletebatch data return wrong statusVirtual"; - std::vector results; - singleKvStoreVirtual->GetEntries("SingleKvStoreDdmDeleteBatch003_", results); - size_t sum = 3; - ASSERT_EQ(results.size(), sum) << "entries size is not equal 3."; -} - -/** - * @tc.name: DdmDeleteBatch004 - * @tc.desc: Batch delete data when some keyVirtuals are invalVirtualid. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmDeleteBatch004, TestSize.Level2) -{ - ZLOGI("DdmDeleteBatch004 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - // store entries to kvstore. - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreDdmDeleteBatch004_1"; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "SingleKvStoreDdmDeleteBatch004_2"; - entryVirtual2.valVirtualue = "age:19"; - entryVirtual3.keyVirtual = "SingleKvStoreDdmDeleteBatch004_3"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keyVirtuals; - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch004_1"); - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch004_2"); - keyVirtuals.push_back(" "); - - Status status1 = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, status1) << "SingleKvStore putbatch data return wrong statusVirtual"; - - std::vector results1; - singleKvStoreVirtual->GetEntries("SingleKvStoreDdmDeleteBatch004_", results1); - size_t sum1 = 3; - ASSERT_EQ(results1.size(), sum1) << "entries size1111 is not equal 3."; - - Status status2 = singleKvStoreVirtual->DeleteBatch(keyVirtuals); - ASSERT_EQ(Status::INVALID_ARGUMENT, status2) << "SingleKvStore deletebatch data return wrong statusVirtual"; - std::vector results; - singleKvStoreVirtual->GetEntries("SingleKvStoreDdmDeleteBatch004_", results); - size_t sum = 3; - ASSERT_EQ(results.size(), sum) << "entries size is not equal 3."; -} - -/** - * @tc.name: DdmDeleteBatch005 - * @tc.desc: Batch delete data when some keyVirtuals are invalVirtualid. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmDeleteBatch005, TestSize.Level2) -{ - ZLOGI("DdmDeleteBatch005 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - // store entries to kvstore. - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreDdmDeleteBatch005_1"; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "SingleKvStoreDdmDeleteBatch005_2"; - entryVirtual2.valVirtualue = "age:19"; - entryVirtual3.keyVirtual = "SingleKvStoreDdmDeleteBatch005_3"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keyVirtuals; - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch005_1"); - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch005_2"); - Key keyVirtualTmp = SingleGenerate1025KeyLen(); - keyVirtuals.push_back(keyVirtualTmp); - - Status status1 = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, status1) << "SingleKvStore putbatch data return wrong statusVirtual"; - - std::vector results1; - singleKvStoreVirtual->GetEntries("SingleKvStoreDdmDeleteBatch005_", results1); - size_t sum1 = 3; - ASSERT_EQ(results1.size(), sum1) << "entries111 size is not equal 3."; - - Status status2 = singleKvStoreVirtual->DeleteBatch(keyVirtuals); - ASSERT_EQ(Status::INVALID_ARGUMENT, status2) << "SingleKvStore deletebatch data return wrong statusVirtual"; - std::vector results; - singleKvStoreVirtual->GetEntries("SingleKvStoreDdmDeleteBatch005_", results); - size_t sum = 3; - ASSERT_EQ(results.size(), sum) << "entries size is not equal 3."; -} - -/** - * @tc.name: Transaction001 - * @tc.desc: Batch delete data when some keyVirtuals are invalVirtualid. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, Transaction001, TestSize.Level2) -{ - ZLOGI("Transaction001 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - std::shared_ptr observer = std::make_shared(); - observer->ResetToZero(); - - SubscribeType subscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = singleKvStoreVirtual->SubscribeKvStore(subscribeType, observer); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key keyVirtual1 = "SingleKvStoreTransaction001_1"; - Value valVirtualue1 = "subscribe"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreTransaction001_2"; - entryVirtual1.valVirtualue = "subscribe"; - entryVirtual2.keyVirtual = "SingleKvStoreTransaction001_3"; - entryVirtual2.valVirtualue = "subscribe"; - entryVirtual3.keyVirtual = "SingleKvStoreTransaction001_4"; - entryVirtual3.valVirtualue = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keyVirtuals; - keyVirtuals.push_back("SingleKvStoreTransaction001_2"); - keyVirtuals.push_back("ISingleKvStoreTransaction001_3"); - - statusVirtual = singleKvStoreVirtual->StartTransaction(); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore startTransaction return wrong statusVirtual"; - - statusVirtual = singleKvStoreVirtual->Put(keyVirtual1, valVirtualue1); // insert or update keyVirtual-valVirtualue - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore put data return wrong statusVirtual"; - statusVirtual = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore putbatch data return wrong statusVirtual"; - statusVirtual = singleKvStoreVirtual->Delete(keyVirtual1); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore delete data return wrong statusVirtual"; - statusVirtual = singleKvStoreVirtual->DeleteBatch(keyVirtuals); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore DeleteBatch data return wrong statusVirtual"; - statusVirtual = singleKvStoreVirtual->Commit(); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore Commit return wrong statusVirtual"; - - usleep(200000); - ASSERT_EQ(static_cast(observer->GetCallCount()), 1); - - statusVirtual = singleKvStoreVirtual->UnSubscribeKvStore(subscribeType, observer); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** - * @tc.name: Transaction002 - * @tc.desc: Batch delete data when some keyVirtuals are invalVirtualid. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, Transaction002, TestSize.Level2) -{ - ZLOGI("Transaction002 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - std::shared_ptr observer = std::make_shared(); - observer->ResetToZero(); - - SubscribeType subscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = singleKvStoreVirtual->SubscribeKvStore(subscribeType, observer); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key keyVirtual1 = "SingleKvStoreTransaction002_1"; - Value valVirtualue1 = "subscribe"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreTransaction002_2"; - entryVirtual1.valVirtualue = "subscribe"; - entryVirtual2.keyVirtual = "SingleKvStoreTransaction002_3"; - entryVirtual2.valVirtualue = "subscribe"; - entryVirtual3.keyVirtual = "SingleKvStoreTransaction002_4"; - entryVirtual3.valVirtualue = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keyVirtuals; - keyVirtuals.push_back("SingleKvStoreTransaction002_2"); - keyVirtuals.push_back("SingleKvStoreTransaction002_3"); - - statusVirtual = singleKvStoreVirtual->StartTransaction(); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore startTransaction return wrong statusVirtual"; - - statusVirtual = singleKvStoreVirtual->Put(keyVirtual1, valVirtualue1); // insert or update keyVirtual-valVirtualue - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore put data return wrong statusVirtual"; - statusVirtual = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore putbatch data return wrong statusVirtual"; - statusVirtual = singleKvStoreVirtual->Delete(keyVirtual1); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore delete data return wrong statusVirtual"; - statusVirtual = singleKvStoreVirtual->DeleteBatch(keyVirtuals); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore DeleteBatch data return wrong statusVirtual"; - statusVirtual = singleKvStoreVirtual->Rollback(); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore Commit return wrong statusVirtual"; - - usleep(200000); - ASSERT_EQ(static_cast(observer->GetCallCount()), 0); - ASSERT_EQ(static_cast(observer->insertEntriesVirtual_.size()), 0); - ASSERT_EQ(static_cast(observer->updateEntriesVirtual_.size()), 0); - ASSERT_EQ(static_cast(observer->deleteEntriesVirtual_.size()), 0); - - statusVirtual = singleKvStoreVirtual->UnSubscribeKvStore(subscribeType, observer); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - observer = nullptr; -} - -/** - * @tc.name: DeviceSync001 - * @tc.desc: Test sync enable. - * @tc.type: FUNC - * @tc.require:AR000EPAM8 AR000EPAMD - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DeviceSync001, TestSize.Level0) -{ - ZLOGI("DeviceSync001 begin."); - std::shared_ptr schemasingleKvStore; - DistributedKvDataManager managerVirtual; - Options optionsVirtual; - optionsVirtual.encrypt = true; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.kvStoreType = KvStoreType::SINGLE_VERSION; - optionsVirtual.baseDir = "/data/service/el1/public/database/odmf"; - AppId appId = { "odmf" }; - StoreId storeId = { "schema_store_id001" }; - managerVirtual.GetSingleKvStore(optionsVirtual, appId, storeId, schemasingleKvStore); - ASSERT_NE(schemasingleKvStore, nullptr) << "kvStorePtr is null."; - auto result = schemasingleKvStore->GetStoreId(); - ASSERT_EQ(result.storeId, "schema_store_id001"); - - auto testStatus = schemasingleKvStore->SetCapabilityEnabled(true); - ASSERT_EQ(testStatus, Status::SUCCESS) << "set fail"; - managerVirtual.DeleteKvStore(appId, storeId, optionsVirtual.baseDir); -} - -/** - * @tc.name: DeviceSync002 - * @tc.desc: Test sync enable. - * @tc.type: FUNC - * @tc.require:SR000EPA22 AR000EPAM9 - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DeviceSync002, TestSize.Level0) -{ - ZLOGI("DeviceSync002 begin."); - std::shared_ptr schemasingleKvStore; - DistributedKvDataManager managerVirtual; - Options optionsVirtual; - optionsVirtual.encrypt = true; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.kvStoreType = KvStoreType::SINGLE_VERSION; - optionsVirtual.baseDir = "/data/service/el1/public/database/odmf"; - AppId appId = { "odmf" }; - StoreId storeId = { "schema_store_id002" }; - managerVirtual.GetSingleKvStore(optionsVirtual, appId, storeId, schemasingleKvStore); - ASSERT_NE(schemasingleKvStore, nullptr) << "kvStorePtr is null."; - auto result = schemasingleKvStore->GetStoreId(); - ASSERT_EQ(result.storeId, "schema_store_id002"); - - std::vector local = { "A", "B" }; - std::vector remote = { "C", "D" }; - auto testStatus = schemasingleKvStore->SetCapabilityRange(local, remote); - ASSERT_EQ(testStatus, Status::SUCCESS) << "set range fail"; - managerVirtual.DeleteKvStore(appId, storeId, optionsVirtual.baseDir); -} - -/** - * @tc.name: DisableCapability - * @tc.desc: disable capability - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DisableCapability, TestSize.Level0) -{ - ZLOGI("DisableCapability begin."); - std::shared_ptr singleKvStoreVirtual; - DistributedKvDataManager managerVirtual; - Options optionsVirtual; - optionsVirtual.encrypt = true; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.kvStoreType = KvStoreType::SINGLE_VERSION; - optionsVirtual.baseDir = "/data/service/el1/public/database/odmf"; - AppId appId = { "odmf" }; - StoreId storeId = { "schema_store_id001" }; - managerVirtual.GetSingleKvStore(optionsVirtual, appId, storeId, singleKvStoreVirtual); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - auto result = singleKvStoreVirtual->GetStoreId(); - ASSERT_EQ(result.storeId, "schema_store_id001"); - - auto testStatus = singleKvStoreVirtual->SetCapabilityEnabled(false); - ASSERT_EQ(testStatus, Status::SUCCESS) << "set success"; - managerVirtual.DeleteKvStore(appId, storeId, optionsVirtual.baseDir); -} - -/** - * @tc.name: SyncWithCondition001 - * @tc.desc: sync device data with condition; - * @tc.type: FUNC - * @tc.require: AR000GH097 - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, SyncWithCondition001, TestSize.Level0) -{ - ZLOGI("SyncWithCondition001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - std::vector deviceIds = { "invalVirtualid_device_id1", "invalVirtualid_device_id2" }; - DataQuery dataQueryVirtual; - dataQueryVirtual.KeyPrefix("name"); - auto syncStatus = singleKvStoreVirtual->Sync(deviceIds, SyncMode::PUSH, dataQueryVirtual, nullptr); - ASSERT_NE(syncStatus, Status::SUCCESS) << "sync device should not return success"; -} - -/** - * @tc.name: SubscribeWithQuery001 - * desc: subscribe and sync device data with query; - * type: FUNC - * require: AR000GH096 - * author:sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, SubscribeWithQuery001, TestSize.Level0) -{ - ZLOGI("SubscribeWithQuery001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - std::vector deviceIds = { "invalVirtualid_device_id1", "invalVirtualid_device_id2" }; - DataQuery dataQueryVirtual; - dataQueryVirtual.KeyPrefix("name"); - auto syncStatus = singleKvStoreVirtual->SubscribeWithQuery(deviceIds, dataQueryVirtual); - ASSERT_NE(syncStatus, Status::SUCCESS) << "sync device should not return success"; -} - -/** - * @tc.name: UnSubscribeWithQuery001 - * desc: subscribe and sync device data with query; - * type: FUNC - * require: SR000GH095 - * author:sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, UnSubscribeWithQuery001, TestSize.Level0) -{ - ZLOGI("UnSubscribeWithQuery001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - std::vector deviceIds = { "invalVirtualid_device_id1", "invalVirtualid_device_id2" }; - DataQuery dataQueryVirtual; - dataQueryVirtual.KeyPrefix("name"); - auto unSubscribeStatus = singleKvStoreVirtual->UnsubscribeWithQuery(deviceIds, dataQueryVirtual); - ASSERT_NE(unSubscribeStatus, Status::SUCCESS) << "sync device should not return success"; -} - -/** - * @tc.name: CloudSync002 - * desc: create kv store which not supports cloud sync and execute CloudSync interface - * type: FUNC - * require: - * author:sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, CloudSync002, TestSize.Level0) -{ - ZLOGI("CloudSync002 begin."); - std::shared_ptr cloudSyncKvStore = nullptr; - DistributedKvDataManager managerVirtual {}; - Options optionsVirtual; - optionsVirtual.encrypt = true; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.kvStoreType = KvStoreType::SINGLE_VERSION; - optionsVirtual.baseDir = "/data/service/el1/public/database/odmf"; - optionsVirtual.schema = VALID_SCHEMA_STRICT_DEFINE; - optionsVirtual.cloudConfig.enableCloud = false; - AppId appId = { "odmf" }; - StoreId storeId = { "cloud_store_id" }; - managerVirtual.DeleteKvStore(appId, storeId, optionsVirtual.baseDir); - (void)managerVirtual.GetSingleKvStore(optionsVirtual, appId, storeId, cloudSyncKvStore); - ASSERT_NE(cloudSyncKvStore, nullptr); - auto statusVirtual = cloudSyncKvStore->CloudSync(nullptr); - ASSERT_NE(statusVirtual, Status::SUCCESS); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/single_kvstore_query_virtual_test.cpp b/kv_store/databaseutils/test/single_kvstore_query_virtual_test.cpp deleted file mode 100644 index 72a3842c946f78895ef103558141153f32ae87c7..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/single_kvstore_query_virtual_test.cpp +++ /dev/null @@ -1,1474 +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. - */ -#define LOG_TAG "SingleKvStoreVirtualTest" - -#include "block_data.h" -#include "dev_manager.h" -#include "distributed_kv_data_manager.h" -#include "file_ex.h" -#include "types.h" -#include -#include -#include -#include -#include - -using namespace testing::ext; -using namespace OHOS::DistributedKv; -namespace OHOS::Test { -class SingleKvStoreAsyncVirtualTest : public testing::Test { -public: - static std::shared_ptr singleKvStoreVirtual; - static Status statusVirtualVirtual_; - - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -std::shared_ptr SingleKvStoreAsyncVirtualTest::singleKvStoreVirtual = nullptr; -Status SingleKvStoreAsyncVirtualTest::statusVirtualVirtual_ = Status::ERROR; - -void SingleKvStoreAsyncVirtualTest::SetUpTestCase(void) -{ - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { .createIfMissing = true, .encrypt = false, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .dataType = DataType::TYPE_DYNAMICAL }; - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = std::string("/data/service/el1/public/database/asyncgettest"); - AppId appIdVirtual = { "asyncgettest" }; - StoreId storeIdVirtual = { "asyncgettest_store_0" }; - mkdir(optionsVirtual.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); - statusVirtualVirtual_ = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, singleKvStoreVirtual); -} - -void SingleKvStoreAsyncVirtualTest::TearDownTestCase(void) -{ - (void)remove("/data/service/el1/public/database/asyncgettest/key"); - (void)remove("/data/service/el1/public/database/asyncgettest/kvdb"); - (void)remove("/data/service/el1/public/database/asyncgettest"); -} - -void SingleKvStoreAsyncVirtualTest::SetUp(void) -{} - -void SingleKvStoreAsyncVirtualTest::TearDown(void) -{} - -class SingleKvStoreQueryVirtualTest : public testing::Test { -public: - static std::shared_ptr singleKvStoreVirtual; - static Status statusVirtualGetKvStoreVirtual; - static void SetUpTestCase(void); - - static void TearDownTestCase(void); - - void SetUp(); - - void TearDown(); -}; - - -static constexpr const char *VALID_SCHEMA_STRICT_DEFINE = "{\"SCHEMA_VERSION\":\"1.0\"," - "\"SCHEMA_MODE\":\"STRICT\"," - "\"SCHEMA_SKIPSIZE\":0," - "\"SCHEMA_DEFINE\":{" - "\"name\":\"INTEGER, NOT NULL\"" - "}," - "\"SCHEMA_INDEXES\":[\"$.name\"]}"; -std::shared_ptr SingleKvStoreQueryVirtualTest::singleKvStoreVirtual = nullptr; -Status SingleKvStoreQueryVirtualTest::statusVirtualGetKvStoreVirtual = Status::ERROR; -static constexpr int32_t INVALID_NUMBER = -1; -static constexpr uint32_t MAX_QUERY_LENGTH = 1024; - -void SingleKvStoreQueryVirtualTest::SetUpTestCase(void) -{ - std::string baseDir = "/data/service/el1/public/database/SingleKvStoreQueryVirtualTest"; - mkdir(baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void SingleKvStoreQueryVirtualTest::TearDownTestCase(void) -{ - (void)remove("/data/service/el1/public/database/SingleKvStoreQueryVirtualTest/key"); - (void)remove("/data/service/el1/public/database/SingleKvStoreQueryVirtualTest/kvdb"); - (void)remove("/data/service/el1/public/database/SingleKvStoreQueryVirtualTest"); -} - -void SingleKvStoreQueryVirtualTest::SetUp(void) -{} - -void SingleKvStoreQueryVirtualTest::TearDown(void) -{} - -/** -* @tc.name: CreateDefaultKvStore -* @tc.desc: get a single KvStore instance, default is dynamic. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreAsyncVirtualTest, CreateDefaultKvStore, TestSize.Level0) -{ - ZLOGI("CreateDefaultKvStore begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { .createIfMissing = true, .kvStoreType = KvStoreType::SINGLE_VERSION}; - ASSERT_EQ(optionsVirtual.autoSync, false); - ASSERT_EQ(optionsVirtual.dataType, DataType::TYPE_DYNAMICAL); - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = std::string("/data/service/el1/public/database/asyncgettest"); - AppId appIdVirtual = { "asyncgettest" }; - StoreId storeIdVirtual = { "asyncgettest_store_1" }; - - std::shared_ptr storeVirtual = nullptr; - auto statusVirtualVirtual = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, storeVirtual); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_NE(storeVirtual, nullptr); - statusVirtualVirtual = managerVirtual.CloseKvStore(appIdVirtual, storeIdVirtual); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - statusVirtualVirtual = - managerVirtual.DeleteKvStore(appIdVirtual, storeIdVirtual, optionsVirtual.baseDir); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); -} - -/** -* @tc.name: CreateStaticKvStore -* @tc.desc: get a single KvStore instance, data type is STATICS. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreAsyncVirtualTest, CreateStaticKvStore, TestSize.Level0) -{ - ZLOGI("CreateStaticKvStore begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { .createIfMissing = true, .autoSync = true, .dataType = DataType::TYPE_STATICS }; - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = std::string("/data/service/el1/public/database/asyncgettest"); - AppId appIdVirtual = { "asyncgettest" }; - StoreId storeIdVirtual = { "asyncgettest_store" }; - - std::shared_ptr storeVirtual = nullptr; - auto statusVirtualVirtual = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, storeVirtual); - ASSERT_EQ(statusVirtualVirtual, Status::INVALID_ARGUMENT); -} - -/** -* @tc.name: GetKvStoreWithDiffDataType -* @tc.desc: get a single KvStore instance 2 times, data type is different. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreAsyncVirtualTest, GetKvStoreWithDiffDataType, TestSize.Level0) -{ - ZLOGI("GetKvStoreWithDiffDataType begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { .createIfMissing = true, .dataType = DataType::TYPE_STATICS }; - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = std::string("/data/service/el1/public/database/asyncgettest"); - AppId appIdVirtual = { "asyncgettest" }; - StoreId storeIdVirtual = { "asyncgettest_store_2" }; - - std::shared_ptr storeVirtual = nullptr; - auto statusVirtualVirtual = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, storeVirtual); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_NE(storeVirtual, nullptr); - statusVirtualVirtual = managerVirtual.CloseKvStore(appIdVirtual, storeIdVirtual); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - optionsVirtual.dataType = DataType::TYPE_DYNAMICAL; - statusVirtualVirtual = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, storeVirtual); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - statusVirtualVirtual = - managerVirtual.DeleteKvStore(appIdVirtual, storeIdVirtual, optionsVirtual.baseDir); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); -} - -/** -* @tc.name: AsyncGetValue -* @tc.desc: async get value, data type is TYPE_STATICS. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreAsyncVirtualTest, AsyncGetValue, TestSize.Level0) -{ - ZLOGI("AsyncGetValue begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { .createIfMissing = true, .dataType = DataType::TYPE_STATICS }; - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = std::string("/data/service/el1/public/database/asyncgettest"); - AppId appIdVirtual = { "asyncgettest" }; - StoreId storeIdVirtual = { "asyncgettest_store_3" }; - - std::shared_ptr storeVirtual = nullptr; - auto statusVirtualVirtual = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, storeVirtual); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_NE(storeVirtual, nullptr); - statusVirtualVirtual = storeVirtual->Put({ "test_key" }, { "test_value" }); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - Value value; - statusVirtualVirtual = storeVirtual->Get({ "test_key" }, value); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_EQ(value.ToString(), "test_value"); - auto blockData = std::make_shared>(1, false); - std::function call = [blockData, value](Status statusVirtualVirtual, Value &&out) { - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_EQ(out.ToString(), value.ToString()); - blockData->SetValue(true); - }; - auto devInfo = DevManager::GetInstance().GetLocalDevice(); - storeVirtual->Get({ "test_key" }, devInfo.networkId, call); - ASSERT_EQ(blockData->GetValue(), true); - statusVirtualVirtual = managerVirtual.CloseKvStore(appIdVirtual, storeIdVirtual); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - statusVirtualVirtual = - managerVirtual.DeleteKvStore(appIdVirtual, storeIdVirtual, optionsVirtual.baseDir); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); -} - -/** -* @tc.name: AsyncGetValueWithInvalidNetworkId -* @tc.desc: async get value, networkId is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreAsyncVirtualTest, AsyncGetValueWithInvalidNetworkId, TestSize.Level0) -{ - ZLOGI("AsyncGetValueWithInvalidNetworkId begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr); - auto statusVirtualVirtual = singleKvStoreVirtual->Put({ "test_key_0" }, { "test_value_0" }); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - Value value; - statusVirtualVirtual = singleKvStoreVirtual->Get({ "test_key_0" }, value); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_EQ(value.ToString(), "test_value_0"); - auto blockData = std::make_shared>(1, false); - std::function call = [blockData](Status statusVirtualVirtual, Value &&value) { - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - blockData->SetValue(true); - }; - singleKvStoreVirtual->Get({ "test_key_0" }, "", call); - ASSERT_EQ(blockData->GetValue(), true); - blockData->Clear(false); - singleKvStoreVirtual->Get({ "test_key_0" }, "networkId_test", call); - ASSERT_EQ(blockData->GetValue(), true); -} - -/** -* @tc.name: AsyncGetEntriesWithInvalidNetworkId -* @tc.desc: async get entries, networkId is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreAsyncVirtualTest, AsyncGetEntriesWithInvalidNetworkId, TestSize.Level0) -{ - ZLOGI("AsyncGetEntriesWithInvalidNetworkId begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr); - std::vector entries; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = "prefix_key_" + std::to_string(i); - entry.value = std::to_string(i).append("_v"); - entries.push_back(entry); - } - auto statusVirtualVirtual = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - std::vector resultsVirtual; - singleKvStoreVirtual->GetEntries({ "prefix_key_" }, resultsVirtual); - ASSERT_EQ(resultsVirtual.size(), 10); - auto blockData = std::make_shared>(1, false); - std::function&&)> call = - [blockData](Status statusVirtualVirtual, std::vector &&value) { - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - blockData->SetValue(true); - }; - singleKvStoreVirtual->GetEntries({ "prefix_key_" }, "", call); - ASSERT_EQ(blockData->GetValue(), true); - blockData->Clear(false); - singleKvStoreVirtual->GetEntries({ "prefix_key_" }, "networkId_test", call); - ASSERT_EQ(blockData->GetValue(), true); -} - -/** -* @tc.name: AsyncGetValueWithLocalNetworkId -* @tc.desc: async get value, networkId is local. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreAsyncVirtualTest, AsyncGetValueWithLocalNetworkId, TestSize.Level0) -{ - ZLOGI("AsyncGetValueWithLocalNetworkId begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr); - auto statusVirtualVirtual = singleKvStoreVirtual->Put({ "test_key_1" }, { "test_value_1" }); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - Value result; - statusVirtualVirtual = singleKvStoreVirtual->Get({ "test_key_1" }, result); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_EQ(result.ToString(), "test_value_1"); - auto blockData = std::make_shared>(1, false); - std::function call = [blockData, result](Status statusVirtualVirtual, Value &&value) { - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_EQ(result.ToString(), value.ToString()); - blockData->SetValue(true); - }; - auto devInfo = DevManager::GetInstance().GetLocalDevice(); - singleKvStoreVirtual->Get("test_key_1", devInfo.networkId, call); - ASSERT_EQ(blockData->GetValue(), true); -} - -/** -* @tc.name: AsyncGetEntriesWithLocalNetworkId -* @tc.desc: async get entries, networkId is local. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreAsyncVirtualTest, AsyncGetEntriesWithLocalNetworkId, TestSize.Level0) -{ - ZLOGI("AsyncGetEntriesWithLocalNetworkId begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr); - int num = 5; - for (int i = 0; i < num; i++) { - singleKvStoreVirtual->Put({ "prefix_of_" + std::to_string(i) }, { "test_value_2" }); - } - std::vector resultsVirtual; - singleKvStoreVirtual->GetEntries({ "prefix_of_" }, resultsVirtual); - ASSERT_EQ(resultsVirtual.size(), num); - auto blockData = std::make_shared>(1, false); - std::function&&)> call = - [blockData, resultsVirtual](Status statusVirtualVirtual, std::vector&& values) { - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_EQ(resultsVirtual.size(), values.size()); - ASSERT_EQ(values[0].value.ToString(), "test_value_2"); - blockData->SetValue(true); - }; - auto devInfo = DevManager::GetInstance().GetLocalDevice(); - singleKvStoreVirtual->GetEntries("prefix_of_", devInfo.networkId, call); - ASSERT_EQ(blockData->GetValue(), true); - auto ret = singleKvStoreVirtual->GetDeviceEntries("test_device_1", resultsVirtual); - ASSERT_EQ(ret, Status::SUCCESS); -} - -/** -* @tc.name: TestQueryReset -* @tc.desc: the predicate is reset -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, TestQueryReset, TestSize.Level0) -{ - ZLOGI("TestQueryReset begin."); - DataQuery queryVirtual; - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - std::string strVirtual = "test value"; - queryVirtual.EqualTo("$.test_field_name", strVirtual); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryEqualToInvalidField -* @tc.desc: the predicate is equalTo, the field is invalid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryEqualToInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryEqualToInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.EqualTo("", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("$.test_field_name^", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("", (int64_t)100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("^", (int64_t)100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("$.^", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("", false); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("^$.test_field_name", false); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("", std::string("strVirtual")); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("^^^^^^^", std::string("strVirtual")); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryEqualToValidField -* @tc.desc: the predicate is equalTo, the field is valid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryEqualToValidField, TestSize.Level0) -{ - ZLOGI("DataQueryEqualToValidField begin."); - DataQuery queryVirtual; - queryVirtual.EqualTo("$.test_field_name", 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.EqualTo("$.test_field_name", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.EqualTo("$.test_field_name", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.EqualTo("$.test_field_name", false); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::string strVirtual = ""; - queryVirtual.EqualTo("$.test_field_name", strVirtual); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryNotEqualToValidField -* @tc.desc: the predicate is notEqualTo, the field is invalid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryNotEqualToValidField, TestSize.Level0) -{ - ZLOGI("DataQueryNotEqualToValidField begin."); - DataQuery queryVirtual; - queryVirtual.NotEqualTo("", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("$.test_field_name^test", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("", (int64_t)100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("^$.test_field_name", (int64_t)100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("^", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("", false); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("^^", false); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("", std::string("test_value")); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("$.test_field^_name", std::string("test_value")); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryNotEqualToInvalidField -* @tc.desc: the predicate is notEqualTo, the field is valid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryNotEqualToInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryNotEqualToInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.NotEqualTo("$.test_field_name", 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.NotEqualTo("$.test_field_name", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.NotEqualTo("$.test_field_name", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.NotEqualTo("$.test_field_name", false); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::string strVirtual = "test value"; - queryVirtual.NotEqualTo("$.test_field_name", strVirtual); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryGreaterThanInvalidField -* @tc.desc: the predicate is greaterThan, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryGreaterThanInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryGreaterThanInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.GreaterThan("", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThan("$.^^", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThan("", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThan("^$.test_field_name", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThan("", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThan("^", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThan("", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThan("$.test_field_name^*%$#", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryGreaterThanValidField -* @tc.desc: the predicate is greaterThan, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryGreaterThanValidField, TestSize.Level0) -{ - ZLOGI("DataQueryGreaterThanValidField begin."); - DataQuery queryVirtual; - queryVirtual.GreaterThan("$.test_field_name", 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.GreaterThan("$.test_field_name", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.GreaterThan("$.test_field_name", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.GreaterThan("$.test_field_name$$$", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryLessThanInvalidField -* @tc.desc: the predicate is lessThan, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryLessThanInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryLessThanInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.LessThan("", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThan("$.^", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThan("", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThan("^$.test_field_name", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThan("", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThan("^^^", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThan("", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThan("$.test_field_name^", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryLessThanValidField -* @tc.desc: the predicate is lessThan, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryLessThanValidField, TestSize.Level0) -{ - ZLOGI("DataQueryLessThanValidField begin."); - DataQuery queryVirtual; - queryVirtual.LessThan("$.test_field_name", 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.LessThan("$.test_field_name", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.LessThan("$.test_field_name", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.LessThan("$.test_field_name", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryGreaterThanOrEqualToInvalidField -* @tc.desc: the predicate is greaterThanOrEqualTo, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryGreaterThanOrEqualToInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryGreaterThanOrEqualToInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.GreaterThanOrEqualTo("", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThanOrEqualTo("^$.test_field_name", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThanOrEqualTo("", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThanOrEqualTo("$.test_field_name^", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThanOrEqualTo("", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThanOrEqualTo("^$.^", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThanOrEqualTo("", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThanOrEqualTo("^^=", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryGreaterThanOrEqualToValidField -* @tc.desc: the predicate is greaterThanOrEqualTo, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryGreaterThanOrEqualToValidField, TestSize.Level0) -{ - ZLOGI("DataQueryGreaterThanOrEqualToValidField begin."); - DataQuery queryVirtual; - queryVirtual.GreaterThanOrEqualTo("$.test_field_name", 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.GreaterThanOrEqualTo("$.test_field_name", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.GreaterThanOrEqualTo("$.test_field_name", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.GreaterThanOrEqualTo("$.test_field_name", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryLessThanOrEqualToInvalidField -* @tc.desc: the predicate is lessThanOrEqualTo, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryLessThanOrEqualToInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryLessThanOrEqualToInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.LessThanOrEqualTo("", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThanOrEqualTo("^$.test_field_name", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThanOrEqualTo("", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThanOrEqualTo("$.test_field_name^", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThanOrEqualTo("", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThanOrEqualTo("^", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThanOrEqualTo("", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThanOrEqualTo("678678^", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryLessThanOrEqualToValidField -* @tc.desc: the predicate is lessThanOrEqualTo, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryLessThanOrEqualToValidField, TestSize.Level0) -{ - ZLOGI("DataQueryLessThanOrEqualToValidField begin."); - DataQuery queryVirtual; - queryVirtual.LessThanOrEqualTo("$.test_field_name", 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.LessThanOrEqualTo("$.test_field_name", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.LessThanOrEqualTo("$.test_field_name", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.LessThanOrEqualTo("$.test_field_name", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryIsNullInvalidField -* @tc.desc: the predicate is isNull, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryIsNullInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryIsNullInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.IsNull(""); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.IsNull("$.test^_field_name"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryIsNullValidField -* @tc.desc: the predicate is isNull, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryIsNullValidField, TestSize.Level0) -{ - ZLOGI("DataQueryIsNullValidField begin."); - DataQuery queryVirtual; - queryVirtual.IsNull("$.test_field_name"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryInInvalidField -* @tc.desc: the predicate is in, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryInInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryInInvalidField begin."); - DataQuery queryVirtual; - std::vector vectInt{ 10, 20, 30 }; - queryVirtual.In("", vectInt); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.In("^", vectInt); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - std::vector vectLong{ (int64_t) 100, (int64_t) 200, (int64_t) 300 }; - queryVirtual.In("", vectLong); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.In("$.test_field_name^", vectLong); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - std::vector vectDouble{1.23, 2.23, 3.23}; - queryVirtual.In("", vectDouble); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.In("$.^test_field_name", vectDouble); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - std::vector vectString{ "value 1", "value 2", "value 3" }; - queryVirtual.In("", vectString); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.In("$.test_field_^name^", vectString); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryInValidField -* @tc.desc: the predicate is in, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryInValidField, TestSize.Level0) -{ - ZLOGI("DataQueryInValidField begin."); - DataQuery queryVirtual; - std::vector vectInt{ 10, 20, 30 }; - queryVirtual.In("$.test_field_name", vectInt); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::vector vectLong{ (int64_t) 100, (int64_t) 200, (int64_t) 300 }; - queryVirtual.In("$.test_field_name", vectLong); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::vector vectDouble{1.23, 2.23, 3.23}; - queryVirtual.In("$.test_field_name", vectDouble); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::vector vectString{ "value 1", "value 2", "value 3" }; - queryVirtual.In("$.test_field_name", vectString); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryNotInInvalidField -* @tc.desc: the predicate is notIn, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryNotInInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryNotInInvalidField begin."); - DataQuery queryVirtual; - std::vector vectInt{ 10, 20, 30 }; - queryVirtual.NotIn("", vectInt); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotIn("$.^", vectInt); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - std::vector vectLong{ (int64_t) 100, (int64_t) 200, (int64_t) 300 }; - queryVirtual.NotIn("", vectLong); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotIn("^^", vectLong); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - std::vector vectDouble{ 1.23, 2.23, 3.23 }; - queryVirtual.NotIn("", vectDouble); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotIn("^$.test_field_name", vectDouble); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - std::vector vectString{ "value 1", "value 2", "value 3" }; - queryVirtual.NotIn("", vectString); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotIn("$.^", vectString); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryNotInValidField -* @tc.desc: the predicate is notIn, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryNotInValidField, TestSize.Level0) -{ - ZLOGI("DataQueryNotInValidField begin."); - DataQuery queryVirtual; - std::vector vectInt{ 10, 20, 30 }; - queryVirtual.NotIn("$.test_field_name", vectInt); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::vector vectLong{ (int64_t) 100, (int64_t) 200, (int64_t) 300 }; - queryVirtual.NotIn("$.test_field_name", vectLong); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::vector vectDouble{ 1.23, 2.23, 3.23 }; - queryVirtual.NotIn("$.test_field_name", vectDouble); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::vector vectString{ "value 1", "value 2", "value 3" }; - queryVirtual.NotIn("$.test_field_name", vectString); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryLikeInvalidField -* @tc.desc: the predicate is like, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryLikeInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryLikeInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.Like("", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.Like("$.test_fi^eld_name", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryLikeValidField -* @tc.desc: the predicate is like, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryLikeValidField, TestSize.Level0) -{ - ZLOGI("DataQueryLikeValidField begin."); - DataQuery queryVirtual; - queryVirtual.Like("$.test_field_name", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryUnlikeInvalidField -* @tc.desc: the predicate is unlike, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryUnlikeInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryUnlikeInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.Unlike("", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.Unlike("$.^", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryUnlikeValidField -* @tc.desc: the predicate is unlike, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryUnlikeValidField, TestSize.Level0) -{ - ZLOGI("DataQueryUnlikeValidField begin."); - DataQuery queryVirtual; - queryVirtual.Unlike("$.test_field_name", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryAnd -* @tc.desc: the predicate is and -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryAnd, TestSize.Level0) -{ - ZLOGI("DataQueryAnd begin."); - DataQuery queryVirtual; - queryVirtual.Like("$.test_field_name1", "test value1"); - queryVirtual.And(); - queryVirtual.Like("$.test_field_name2", "test value2"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryOr -* @tc.desc: the predicate is or -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryOr, TestSize.Level0) -{ - ZLOGI("DataQueryOr begin."); - DataQuery queryVirtual; - queryVirtual.Like("$.test_field_name1", "test value1"); - queryVirtual.Or(); - queryVirtual.Like("$.test_field_name2", "test value2"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryOrderByAscInvalidField -* @tc.desc: the predicate is orderByAsc, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryOrderByAscInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryOrderByAscInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.OrderByAsc(""); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.OrderByAsc("$.^"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryOrderByAscValidField -* @tc.desc: the predicate is orderByAsc, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryOrderByAscValidField, TestSize.Level0) -{ - ZLOGI("DataQueryOrderByAscValidField begin."); - DataQuery queryVirtual; - queryVirtual.OrderByAsc("$.test_field_name1"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryOrderByDescInvalidField -* @tc.desc: the predicate is orderByDesc, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryOrderByDescInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryOrderByDescInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.OrderByDesc(""); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.OrderByDesc("$.test^_field_name1"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryOrderByDescValidField -* @tc.desc: the predicate is orderByDesc, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryOrderByDescValidField, TestSize.Level0) -{ - ZLOGI("DataQueryOrderByDescValidField begin."); - DataQuery queryVirtual; - queryVirtual.OrderByDesc("$.test_field_name1"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryLimitInvalidField -* @tc.desc: the predicate is limit, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryLimitInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryLimitInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.Limit(INVALID_NUMBER, 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.Limit(10, INVALID_NUMBER); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryLimitValidField -* @tc.desc: the predicate is limit, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryLimitValidField, TestSize.Level0) -{ - ZLOGI("DataQueryLimitValidField begin."); - DataQuery queryVirtual; - queryVirtual.Limit(10, 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: SingleKvStoreQueryNotEqualTo1 -* @tc.desc: queryVirtual single kvStore by dataQuery, the predicate is notEqualTo -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, SingleKvStoreQueryNotEqualTo1, TestSize.Level0) -{ - ZLOGI("SingleKvStoreQueryNotEqualTo1 begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { .createIfMissing = true, .encrypt = true, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .schema = VALID_SCHEMA_STRICT_DEFINE }; - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = "/data/service/el1/public/database/SingleKvStoreQueryVirtualTest"; - AppId appIdVirtual = { "SingleKvStoreQueryVirtualTest" }; - StoreId storeIdVirtual = { "SingleKvStoreClientQueryTestStoreId1" }; - statusVirtualGetKvStore = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, singleKvStoreVirtual); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - singleKvStoreVirtual->Put("test_key_1", "{\"name\":1}"); - singleKvStoreVirtual->Put("test_key_2", "{\"name\":2}"); - singleKvStoreVirtual->Put("test_key_3", "{\"name\":3}"); - - DataQuery queryVirtual; - queryVirtual.NotEqualTo("$.name", 3); - std::vector results; - Status statusVirtual1 = singleKvStoreVirtual->GetEntries(queryVirtual, results); - ASSERT_EQ(statusVirtual1, Status::SUCCESS); - ASSERT_TRUE(results.size() == 2); - results.clear(); - Status statusVirtual2 = singleKvStoreVirtual->GetEntries(queryVirtual, results); - ASSERT_EQ(statusVirtual2, Status::SUCCESS); - ASSERT_TRUE(results.size() == 2); - - std::shared_ptr resultSet; - Status statusVirtual3 = singleKvStoreVirtual->GetResultSet(queryVirtual, resultSet); - ASSERT_EQ(statusVirtual3, Status::SUCCESS); - ASSERT_TRUE(resultSet->GetCount() == 2); - auto closeResultSetStatus = singleKvStoreVirtual->CloseResultSet(resultSet); - ASSERT_EQ(closeResultSetStatus, Status::SUCCESS); - Status statusVirtual4 = singleKvStoreVirtual->GetResultSet(queryVirtual, resultSet); - ASSERT_EQ(statusVirtual4, Status::SUCCESS); - ASSERT_TRUE(resultSet->GetCount() == 2); - - closeResultSetStatus = singleKvStoreVirtual->CloseResultSet(resultSet); - ASSERT_EQ(closeResultSetStatus, Status::SUCCESS); -} - -/** -* @tc.name: SingleKvStoreQueryNotEqualTo2 -* @tc.desc: queryVirtual single kvStore by dataQuery, the predicate is notEqualTo -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, SingleKvStoreQueryNotEqualTo2, TestSize.Level0) -{ - ZLOGI("SingleKvStoreQueryNotEqualTo2 begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual1 = { .createIfMissing = true, .encrypt = true, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .schema = VALID_SCHEMA_STRICT_DEFINE }; - optionsVirtual1.area = EL1; - optionsVirtual1.securityLevel = S1; - optionsVirtual1.baseDir = "/data/service/el1/public/database/SingleKvStoreQueryVirtualTest"; - AppId appIdVirtual1 = { "SingleKvStoreQueryVirtualTest" }; - StoreId storeIdVirtual1 = { "SingleKvStoreClientQueryTestStoreId1" }; - statusVirtualGetKvStore = - managerVirtual.GetSingleKvStore(optionsVirtual1, appIdVirtual1, storeIdVirtual1, singleKvStoreVirtual1); - ASSERT_NE(singleKvStoreVirtual1, nullptr) << "kvStorePtr is null."; - singleKvStoreVirtual1->Put("test_key_1", "{\"name\":1}"); - singleKvStoreVirtual1->Put("test_key_2", "{\"name\":2}"); - singleKvStoreVirtual1->Put("test_key_3", "{\"name\":3}"); - - DataQuery queryVirtual1; - queryVirtual1.NotEqualTo("$.name", 3); - std::vector results; - Status statusVirtual1 = singleKvStoreVirtual->GetEntries(queryVirtual1, results); - ASSERT_EQ(statusVirtual1, Status::SUCCESS); - ASSERT_TRUE(results.size() == 2); - results.clear(); - Status statusVirtual2 = singleKvStoreVirtual->GetEntries(queryVirtual1, results); - ASSERT_EQ(statusVirtual2, Status::SUCCESS); - ASSERT_TRUE(results.size() == 2); - - int resultSize1; - Status statusVirtual5 = singleKvStoreVirtual->GetCount(queryVirtual1, resultSize1); - ASSERT_EQ(statusVirtual5, Status::SUCCESS); - ASSERT_TRUE(resultSize1 == 2); - int resultSize2; - Status statusVirtual6 = singleKvStoreVirtual->GetCount(queryVirtual1, resultSize2); - ASSERT_EQ(statusVirtual6, Status::SUCCESS); - ASSERT_TRUE(resultSize2 == 2); - - singleKvStoreVirtual->Delete("test_key_1"); - singleKvStoreVirtual->Delete("test_key_2"); - singleKvStoreVirtual->Delete("test_key_3"); - Status statusVirtual = managerVirtual.CloseAllKvStore(appIdVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - statusVirtual = managerVirtual.DeleteAllKvStore(appIdVirtual, optionsVirtual.baseDir); - ASSERT_EQ(statusVirtual, Status::SUCCESS); -} - -/** -* @tc.name: SingleKvStoreQueryNotEqualToAndEqualTo1 -* @tc.desc: queryVirtual single kvStore by dataQuery, the predicate is notEqualTo and equalTo -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, SingleKvStoreQueryNotEqualToAndEqualTo1, TestSize.Level0) -{ - ZLOGI("SingleKvStoreQueryNotEqualToAndEqualTo1 begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { .createIfMissing = true, .encrypt = true, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .schema = VALID_SCHEMA_STRICT_DEFINE }; - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = "/data/service/el1/public/database/SingleKvStoreQueryVirtualTest"; - AppId appIdVirtual = { "SingleKvStoreQueryVirtualTest" }; - StoreId storeIdVirtual = { "SingleKvStoreClientQueryTestStoreId2" }; - statusVirtualGetKvStore = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, singleKvStoreVirtual); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - singleKvStoreVirtual->Put("test_key_1", "{\"name\":1}"); - singleKvStoreVirtual->Put("test_key_2", "{\"name\":2}"); - singleKvStoreVirtual->Put("test_key_3", "{\"name\":3}"); - - DataQuery queryVirtual; - queryVirtual.NotEqualTo("$.name", 3); - queryVirtual.And(); - queryVirtual.EqualTo("$.name", 1); - std::vector results1; - Status statusVirtual1 = singleKvStoreVirtual->GetEntries(queryVirtual, results1); - ASSERT_EQ(statusVirtual1, Status::SUCCESS); - ASSERT_TRUE(results1.size() == 1); - std::vector results2; - Status statusVirtual2 = singleKvStoreVirtual->GetEntries(queryVirtual, results2); - ASSERT_EQ(statusVirtual2, Status::SUCCESS); - ASSERT_TRUE(results2.size() == 1); - - std::shared_ptr resultSet; - Status statusVirtual3 = singleKvStoreVirtual->GetResultSet(queryVirtual, resultSet); - ASSERT_EQ(statusVirtual3, Status::SUCCESS); - ASSERT_TRUE(resultSet->GetCount() == 1); - auto closeResultSetStatus = singleKvStoreVirtual->CloseResultSet(resultSet); - ASSERT_EQ(closeResultSetStatus, Status::SUCCESS); - Status statusVirtual4 = singleKvStoreVirtual->GetResultSet(queryVirtual, resultSet); - ASSERT_EQ(statusVirtual4, Status::SUCCESS); - ASSERT_TRUE(resultSet->GetCount() == 1); - - closeResultSetStatus = singleKvStoreVirtual->CloseResultSet(resultSet); - ASSERT_EQ(closeResultSetStatus, Status::SUCCESS); -} - -/** -* @tc.name: SingleKvStoreQueryNotEqualToAndEqualTo2 -* @tc.desc: queryVirtual single kvStore by dataQuery, the predicate is notEqualTo and equalTo -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, SingleKvStoreQueryNotEqualToAndEqualTo2, TestSize.Level0) -{ - ZLOGI("SingleKvStoreQueryNotEqualToAndEqualTo2 begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual1 = { .createIfMissing = true, .encrypt = true, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .schema = VALID_SCHEMA_STRICT_DEFINE }; - optionsVirtual1.area = EL1; - optionsVirtual1.securityLevel = S1; - optionsVirtual1.baseDir = "/data/service/el1/public/database/SingleKvStoreQueryVirtualTest"; - AppId appIdVirtual = { "SingleKvStoreQueryVirtualTest" }; - StoreId storeIdVirtual = { "SingleKvStoreClientQueryTestStoreId2" }; - statusVirtualGetKvStore = - managerVirtual.GetSingleKvStore(optionsVirtual1, appIdVirtual, storeIdVirtual, singleKvStoreVirtual1); - ASSERT_NE(singleKvStoreVirtual1, nullptr) << "kvStorePtr is null."; - singleKvStoreVirtual1->Put("test_key_1", "{\"name\":1}"); - singleKvStoreVirtual1->Put("test_key_2", "{\"name\":2}"); - singleKvStoreVirtual1->Put("test_key_3", "{\"name\":3}"); - - DataQuery queryVirtual; - queryVirtual.NotEqualTo("$.name", 3); - queryVirtual.And(); - queryVirtual.EqualTo("$.name", 1); - std::vector results1; - Status statusVirtual1 = singleKvStoreVirtual1->GetEntries(queryVirtual, results1); - ASSERT_EQ(statusVirtual1, Status::SUCCESS); - ASSERT_TRUE(results1.size() == 1); - std::vector results2; - Status statusVirtual2 = singleKvStoreVirtual1->GetEntries(queryVirtual, results2); - ASSERT_EQ(statusVirtual2, Status::SUCCESS); - ASSERT_TRUE(results2.size() == 1); - - int resultSize1; - Status statusVirtual5 = singleKvStoreVirtual1->GetCount(queryVirtual, resultSize1); - ASSERT_EQ(statusVirtual5, Status::SUCCESS); - ASSERT_TRUE(resultSize1 == 1); - int resultSize2; - Status statusVirtual6 = singleKvStoreVirtual1->GetCount(queryVirtual, resultSize2); - ASSERT_EQ(statusVirtual6, Status::SUCCESS); - ASSERT_TRUE(resultSize2 == 1); - - singleKvStoreVirtual->Delete("test_key_1"); - singleKvStoreVirtual->Delete("test_key_2"); - singleKvStoreVirtual->Delete("test_key_3"); - Status statusVirtual = managerVirtual.CloseAllKvStore(appIdVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - statusVirtual = managerVirtual.DeleteAllKvStore(appIdVirtual, optionsVirtual.baseDir); - ASSERT_EQ(statusVirtual, Status::SUCCESS); -} - -/** -* @tc.name: DataQueryGroupAbnormal -* @tc.desc: queryVirtual group, the predicate is prefix, isNotNull, but field is invalid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryGroupAbnormal, TestSize.Level0) -{ - ZLOGI("DataQueryGroupAbnormal begin."); - DataQuery queryVirtual; - queryVirtual.KeyPrefix(""); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.KeyPrefix("prefix^"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.Reset(); - queryVirtual.BeginGroup(); - queryVirtual.IsNotNull(""); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.IsNotNull("^$.name"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.EndGroup(); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryByGroupNormal -* @tc.desc: queryVirtual group, the predicate is prefix, isNotNull. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryByGroupNormal, TestSize.Level0) -{ - ZLOGI("DataQueryByGroupNormal begin."); - DataQuery queryVirtual; - queryVirtual.KeyPrefix("prefix"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.BeginGroup(); - queryVirtual.IsNotNull("$.name"); - queryVirtual.EndGroup(); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQuerySetSuggestIndexInvalidField -* @tc.desc: the predicate is setSuggestIndex, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: liuwenhui -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQuerySetSuggestIndexInvalidField, TestSize.Level0) -{ - ZLOGI("DataQuerySetSuggestIndexInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.SetSuggestIndex(""); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.SetSuggestIndex("test_field^_name"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQuerySetSuggestIndexValidField -* @tc.desc: the predicate is setSuggestIndex, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: liuwenhui -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQuerySetSuggestIndexValidField, TestSize.Level0) -{ - ZLOGI("DataQuerySetSuggestIndexValidField begin."); - DataQuery queryVirtual; - queryVirtual.SetSuggestIndex("test_field_name"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQuerySetInKeys -* @tc.desc: the predicate is inKeys -* @tc.type: FUNC -* @tc.require: -* @tc.author: taoyuxin -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQuerySetInKeys, TestSize.Level0) -{ - ZLOGI("DataQuerySetInKeys begin."); - DataQuery queryVirtual; - queryVirtual.InKeys({}); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.InKeys({"test_field_name"}); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.InKeys({"test_field_name_hasKey"}); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::vector keys { "test_field", "", "^test_field", "^", "test_field_name" }; - queryVirtual.InKeys(keys); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryDeviceIdInvalidField -* @tc.desc:the predicate is deviceId, the field is invalid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryDeviceIdInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryDeviceIdInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.DeviceId(""); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.DeviceId("$$^"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.DeviceId("device_id^"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryDeviceIdValidField -* @tc.desc: the predicate is valid deviceId, the field is valid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryDeviceIdValidField, TestSize.Level0) -{ - ZLOGI("DataQueryDeviceIdValidField begin."); - DataQuery queryVirtual; - queryVirtual.DeviceId("device_id"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::string deviceId = ""; - uint32_t i = 0; - while (i < MAX_QUERY_LENGTH) { - deviceId += "device"; - i++; - } - queryVirtual.DeviceId(deviceId); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryBetweenInvalid -* @tc.desc: the predicate is between, the value is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: SQL -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryBetweenInvalid, TestSize.Level0) -{ - ZLOGI("DataQueryBetweenInvalid begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { .createIfMissing = true, .encrypt = true, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .schema = VALID_SCHEMA_STRICT_DEFINE }; - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = "/data/service/el1/public/database/SingleKvStoreQueryVirtualTest"; - AppId appIdVirtual = { "SingleKvStoreQueryVirtualTest" }; - StoreId storeIdVirtual = { "SingleKvStoreClientQueryTestStoreId3" }; - statusVirtualGetKvStore = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, singleKvStoreVirtual); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - singleKvStoreVirtual->Put("test_key_1", "{\"name\":1}"); - singleKvStoreVirtual->Put("test_key_2", "{\"name\":2}"); - singleKvStoreVirtual->Put("test_key_3", "{\"name\":3}"); - - DataQuery queryVirtual; - queryVirtual.Between({}, {}); - std::vector results1; - Status statusVirtual = singleKvStoreVirtual->GetEntries(queryVirtual, results1); - ASSERT_EQ(statusVirtual, NOT_SUPPORT); - - singleKvStoreVirtual->Delete("test_key_1"); - singleKvStoreVirtual->Delete("test_key_2"); - singleKvStoreVirtual->Delete("test_key_3"); - statusVirtual = managerVirtual.CloseAllKvStore(appIdVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - statusVirtual = managerVirtual.DeleteAllKvStore(appIdVirtual, optionsVirtual.baseDir); - ASSERT_EQ(statusVirtual, Status::SUCCESS); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/single_store_impl_sham_test.cpp b/kv_store/databaseutils/test/single_store_impl_sham_test.cpp deleted file mode 100644 index 0375201ef14158bfa26f1b868633e4dedb2940b1..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/single_store_impl_sham_test.cpp +++ /dev/null @@ -1,2130 +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. - */ -#define LOG_TAG "SingleStoreImplShamTest" - -#include "block_data.h" -#include "dev_manager.h" -#include "device_manager.h" -#include "distributed_kv_data_manager.h" -#include "dm_device_info.h" -#include "file_ex.h" -#include "kv_store_nb_delegate.h" -#include "single_store_impl.h" -#include "store_factory.h" -#include "store_manager.h" -#include "sys/stat.h" -#include "types.h" -#include -#include -#include - -using namespace testing::ext; -using namespace OHOS::DistributedKv; -using DBStatus = DistributedDB::DBStatus; -using DBStore = DistributedDB::KvStoreNbDelegate; -using SyncCallback = KvStoreSyncCallback; -using DevInfo = OHOS::DistributedHardware::DmDeviceInfo; -namespace OHOS::Test { -static constexpr int MAX_RESULTSET_SIZE = 8; -std::vector RandomSham(int32_t len) -{ - return std::vector(len, 'a'); -} - -class SingleStoreImplShamTest : public testing::Test { -public: - class TestObserverSham : public KvStoreObserver { - public: - TestObserverSham() - { - // The time interval parameter is 5. - data_ = std::make_shared>(5, false); - } - void OnChange(const ChangeNotification ¬ificationSham) override - { - insert_ = notificationSham.GetInsertEntries(); - update_ = notificationSham.GetUpdateEntries(); - delete_ = notificationSham.GetDeleteEntries(); - deviceId_ = notificationSham.GetDeviceId(); - bool valueSham = true; - data_->SetValue(valueSham); - } - std::vector insert_; - std::vector update_; - std::vector delete_; - std::string deviceId_; - - std::shared_ptr> data_; - }; - - std::shared_ptr CreateKVStore(std::string storeIdTest, KvStoreType type, bool encrypt, bool backup); - std::shared_ptr CreateKVStore(bool autosync = false); - std::shared_ptr kvStoreSham_; - - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void SingleStoreImplShamTest::SetUpTestCase(void) -{ - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - mkdir(baseDirSham.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void SingleStoreImplShamTest::TearDownTestCase(void) -{ - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - StoreManager::GetInstance().Delete({ "SingleStoreImplShamTest" }, { "SingleKVStore" }, baseDirSham); - - (void)remove("/data/service/el1/public/database/SingleStoreImplShamTest/key"); - (void)remove("/data/service/el1/public/database/SingleStoreImplShamTest/kvdb"); - (void)remove("/data/service/el1/public/database/SingleStoreImplShamTest"); -} - -void SingleStoreImplShamTest::SetUp(void) -{ - kvStoreSham_ = CreateKVStore("SingleKVStore", SINGLE_VERSION, false, true); - if (kvStoreSham_ == nullptr) { - kvStoreSham_ = CreateKVStore("SingleKVStore", SINGLE_VERSION, false, true); - } - ASSERT_NE(kvStoreSham_, nullptr); -} - -void SingleStoreImplShamTest::TearDown(void) -{ - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStore" }; - kvStoreSham_ = nullptr; - auto statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); - auto baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, baseDirSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -std::shared_ptr SingleStoreImplShamTest::CreateKVStore( - std::string storeIdTest, KvStoreType type, bool encrypt, bool backup) -{ - Options optionsSham; - optionsSham.kvStoreType = type; - optionsSham.securityLevel = S1; - optionsSham.encrypt = encrypt; - optionsSham.area = EL1; - optionsSham.backup = backup; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { storeIdTest }; - Status statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, optionsSham.baseDirSham); - return StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); -} - -std::shared_ptr SingleStoreImplShamTest::CreateKVStore(bool autosync) -{ - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "DestructorTest" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S2; - optionsSham.area = EL1; - optionsSham.autoSync = autosync; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - StoreFactory storeFactory; - auto dbManager = storeFactory.GetDBManager(optionsSham.baseDirSham, appIdSham); - auto dbPassword = SecurityManager::GetInstance().GetDBPassword( - storeIdSham.storeIdSham, optionsSham.baseDirSham, optionsSham.encrypt); - DBStatus dbStatus = DBStatus::DB_ERROR; - dbManager->GetKvStore(storeIdSham, storeFactory.GetDBOption(optionsSham, dbPassword), - [&dbManager, &kvStoreSham, &appIdSham, &dbStatus, &optionsSham, &storeFactory](auto statusSham, auto *store) { - dbStatus = statusSham; - if (store == nullptr) { - return; - } - auto release = [dbManager](auto *store) { - dbManager->CloseKvStore(store); - }; - auto dbStore = std::shared_ptr(store, release); - storeFactory.SetDbConfig(dbStore); - const Convertor &convertor = *(storeFactory.convertors_[optionsSham.kvStoreType]); - kvStoreSham = std::make_shared(dbStore, appIdSham, optionsSham, convertor); - }); - return kvStoreSham; -} - -/** - * @tc.name: GetStoreId - * @tc.desc: get the store id of the kv store - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetStoreId, TestSize.Level0) -{ - ZLOGI("GetStoreId start."); - ASSERT_NE(kvStoreSham_, nullptr); - auto storeIdSham = kvStoreSham_->GetStoreId(); - ASSERT_EQ(storeIdSham.storeIdSham, "SingleKVStore"); -} - -/** - * @tc.name: Put - * @tc.desc: put key-valueSham data to the kv store - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, Put, TestSize.Level0) -{ - ZLOGI("Put start."); - ASSERT_NE(kvStoreSham_, nullptr); - auto statusSham = kvStoreSham_->Put({ "Put Test" }, { "Put Value" }); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->Put({ " Put Test" }, { "Put2 Value" }); - ASSERT_EQ(statusSham, SUCCESS); - Value valueSham; - statusSham = kvStoreSham_->Get({ "Put Test" }, valueSham); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(valueSham.ToString(), "Put2 Value"); -} - -/** - * @tc.name: Put_Invalid_Key - * @tc.desc: put invalid key-valueSham data to the device kv store and single kv store - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author:SQL - */ -HWTEST_F(SingleStoreImplShamTest, Put_Invalid_Key, TestSize.Level0) -{ - ZLOGI("Put_Invalid_Key start."); - std::shared_ptr kvStoreSham; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "DeviceKVStore" }; - kvStoreSham = CreateKVStore(storeIdSham.storeIdSham, DEVICE_COLLABORATION, false, true); - ASSERT_NE(kvStoreSham, nullptr); - - size_t maxDevKeyLen = 897; - std::string str(maxDevKeyLen, 'a'); - Blob key(str); - Blob valueSham("test_value"); - Status statusSham = kvStoreSham->Put(key, valueSham); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); - - Blob key1(""); - Blob value1("test_value1"); - statusSham = kvStoreSham->Put(key1, value1); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); - - kvStoreSham = nullptr; - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, baseDirSham); - ASSERT_EQ(statusSham, SUCCESS); - - size_t maxSingleKeyLen = 1025; - std::string str1(maxSingleKeyLen, 'b'); - Blob key2(str1); - Blob value2("test_value2"); - statusSham = kvStoreSham_->Put(key2, value2); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); - - statusSham = kvStoreSham_->Put(key1, value1); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: PutBatch - * @tc.desc: put some key-valueSham data to the kv store - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, PutBatch, TestSize.Level0) -{ - ZLOGI("PutBatch start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::vector entries; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - entries.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(entries); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: IsRebuild - * @tc.desc: test IsRebuild - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, IsRebuild, TestSize.Level0) -{ - ZLOGI("IsRebuild start."); - ASSERT_NE(kvStoreSham_, nullptr); - auto statusSham = kvStoreSham_->IsRebuild(); - ASSERT_EQ(statusSham, false); -} - -/** - * @tc.name: PutBatch001 - * @tc.desc: entry.valueSham.Size() > MAX_VALUE_LENGTH - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, PutBatch001, TestSize.Level0) -{ - ZLOGI("PutBatch001 start."); - ASSERT_NE(kvStoreSham_, nullptr); - size_t totalLength = SingleStoreImpl::MAX_VALUE_LENGTH + 1; // create an out-of-limit large number - char fillChar = 'a'; - std::string longString(totalLength, fillChar); - std::vector entries; - Entry entry; - entry.key = "PutBatch001_test"; - entry.valueSham = longString; - entries.push_back(entry); - auto statusSham = kvStoreSham_->PutBatch(entries); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); - entries.clear(); - Entry entrys; - entrys.key = ""; - entrys.valueSham = "PutBatch001_test_value"; - entries.push_back(entrys); - statusSham = kvStoreSham_->PutBatch(entries); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: Delete - * @tc.desc: delete the valueSham of the key - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, Delete, TestSize.Level0) -{ - ZLOGI("Delete start."); - ASSERT_NE(kvStoreSham_, nullptr); - auto statusSham = kvStoreSham_->Put({ "Put Test" }, { "Put Value" }); - ASSERT_EQ(statusSham, SUCCESS); - Value valueSham; - statusSham = kvStoreSham_->Get({ "Put Test" }, valueSham); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(std::string("Put Value"), valueSham.ToString()); - statusSham = kvStoreSham_->Delete({ "Put Test" }); - ASSERT_EQ(statusSham, SUCCESS); - valueSham = {}; - statusSham = kvStoreSham_->Get({ "Put Test" }, valueSham); - ASSERT_EQ(statusSham, KEY_NOT_FOUND); - ASSERT_EQ(std::string(""), valueSham.ToString()); -} - -/** - * @tc.name: DeleteBatch - * @tc.desc: delete the values of the keys - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, DeleteBatch, TestSize.Level0) -{ - ZLOGI("DeleteBatch start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::vector entries; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - entries.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(entries); - ASSERT_EQ(statusSham, SUCCESS); - std::vector keys; - for (int i = 0; i < 10; ++i) { - Key key = std::to_string(i).append("_k"); - keys.push_back(key); - } - statusSham = kvStoreSham_->DeleteBatch(keys); - ASSERT_EQ(statusSham, SUCCESS); - for (int i = 0; i < 10; ++i) { - Value valueSham; - statusSham = kvStoreSham_->Get(keys[i], valueSham); - ASSERT_EQ(statusSham, KEY_NOT_FOUND); - ASSERT_EQ(valueSham.ToString(), std::string("")); - } -} - -/** - * @tc.name: Transaction - * @tc.desc: do transaction - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, Transaction, TestSize.Level0) -{ - ZLOGI("Transaction start."); - ASSERT_NE(kvStoreSham_, nullptr); - auto statusSham = kvStoreSham_->StartTransaction(); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->Commit(); - ASSERT_EQ(statusSham, SUCCESS); - - statusSham = kvStoreSham_->StartTransaction(); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->Rollback(); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: SubscribeKvStore - * @tc.desc: subscribe local - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, SubscribeKvStore, TestSize.Level0) -{ - ZLOGI("SubscribeKvStore start."); - ASSERT_NE(kvStoreSham_, nullptr); - auto observer = std::make_shared(); - auto statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_CLOUD, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - ASSERT_EQ(statusSham, STORE_ALREADY_SUBSCRIBE); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - ASSERT_EQ(statusSham, STORE_ALREADY_SUBSCRIBE); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_CLOUD, observer); - ASSERT_EQ(statusSham, STORE_ALREADY_SUBSCRIBE); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - ASSERT_EQ(statusSham, STORE_ALREADY_SUBSCRIBE); - bool invalidValue = false; - observer->data_->Clear(invalidValue); - statusSham = kvStoreSham_->Put({ "Put Test" }, { "Put Value" }); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_TRUE(observer->data_->GetValue()); - ASSERT_EQ(observer->insert_.size(), 1); - ASSERT_EQ(observer->update_.size(), 0); - ASSERT_EQ(observer->delete_.size(), 0); - observer->data_->Clear(invalidValue); - statusSham = kvStoreSham_->Put({ "Put Test" }, { "Put Value1" }); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_TRUE(observer->data_->GetValue()); - ASSERT_EQ(observer->insert_.size(), 0); - ASSERT_EQ(observer->update_.size(), 1); - ASSERT_EQ(observer->delete_.size(), 0); - observer->data_->Clear(invalidValue); - statusSham = kvStoreSham_->Delete({ "Put Test" }); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_TRUE(observer->data_->GetValue()); - ASSERT_EQ(observer->insert_.size(), 0); - ASSERT_EQ(observer->update_.size(), 0); - ASSERT_EQ(observer->delete_.size(), 1); -} - -/** - * @tc.name: SubscribeKvStore002 - * @tc.desc: subscribe local - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: Hollokin - */ -HWTEST_F(SingleStoreImplShamTest, SubscribeKvStore002, TestSize.Level0) -{ - ZLOGI("SubscribeKvStore002 start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::shared_ptr subscribedObserver; - std::shared_ptr unSubscribedObserver; - for (int i = 0; i < 15; ++i) { - auto observer = std::make_shared(); - auto status1 = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - auto status2 = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - if (i < 8) { - ASSERT_EQ(status1, SUCCESS); - ASSERT_EQ(status2, SUCCESS); - subscribedObserver = observer; - } else { - ASSERT_EQ(status1, OVER_MAX_LIMITS); - ASSERT_EQ(status2, OVER_MAX_LIMITS); - unSubscribedObserver = observer; - } - } - - auto statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, subscribedObserver); - ASSERT_EQ(statusSham, STORE_ALREADY_SUBSCRIBE); - - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, {}); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); - - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, subscribedObserver); - ASSERT_EQ(statusSham, STORE_ALREADY_SUBSCRIBE); - - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, subscribedObserver); - ASSERT_EQ(statusSham, SUCCESS); - - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, subscribedObserver); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, subscribedObserver); - ASSERT_EQ(statusSham, SUCCESS); - - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_ALL, subscribedObserver); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, unSubscribedObserver); - ASSERT_EQ(statusSham, SUCCESS); - subscribedObserver = unSubscribedObserver; - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, subscribedObserver); - ASSERT_EQ(statusSham, SUCCESS); - auto observer = std::make_shared(); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - ASSERT_EQ(statusSham, SUCCESS); - observer = std::make_shared(); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - ASSERT_EQ(statusSham, OVER_MAX_LIMITS); -} - -/** - * @tc.name: SubscribeKvStore003 - * @tc.desc: isClientSync_ - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, SubscribeKvStore003, TestSize.Level0) -{ - ZLOGI("SubscribeKvStore003 start."); - auto observer = std::make_shared(); - std::shared_ptr kvStoreSham; - kvStoreSham = CreateKVStore(); - ASSERT_NE(kvStoreSham, nullptr); - kvStoreSham->isClientSync_ = true; - auto statusSham = kvStoreSham->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: UnsubscribeKvStore - * @tc.desc: unsubscribe - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, UnsubscribeKvStore, TestSize.Level0) -{ - ZLOGI("UnsubscribeKvStore start."); - ASSERT_NE(kvStoreSham_, nullptr); - auto observer = std::make_shared(); - auto statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_CLOUD, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - ASSERT_EQ(statusSham, STORE_NOT_SUBSCRIBE); - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - ASSERT_EQ(statusSham, STORE_NOT_SUBSCRIBE); - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - ASSERT_EQ(statusSham, STORE_NOT_SUBSCRIBE); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: GetEntries_Prefix - * @tc.desc: get entries by prefix - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetEntries_Prefix, TestSize.Level0) -{ - ZLOGI("GetEntries_Prefix start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - std::vector output; - statusSham = kvStoreSham_->GetEntries({ "" }, output); - ASSERT_EQ(statusSham, SUCCESS); - std::sort(output.start(), output.end(), [](const Entry &entry, const Entry &sentry) { - return entry.key.Data() < sentry.key.Data(); - }); - for (int i = 0; i < 10; ++i) { - ASSERT_TRUE(input[i].key == output[i].key); - ASSERT_TRUE(input[i].valueSham == output[i].valueSham); - } -} - -/** - * @tc.name: GetEntries_Less_Prefix - * @tc.desc: get entries by prefix and the key size less than sizeof(uint32_t) - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author:SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetEntries_Less_Prefix, TestSize.Level0) -{ - ZLOGI("GetEntries_Less_Prefix start."); - std::shared_ptr kvStoreSham; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "DeviceKVStore" }; - kvStoreSham = CreateKVStore(storeIdSham.storeIdSham, DEVICE_COLLABORATION, false, true); - ASSERT_NE(kvStoreSham, nullptr); - - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusSham = kvStoreSham->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - std::vector output; - statusSham = kvStoreSham->GetEntries({ "1" }, output); - ASSERT_NE(output.empty(), true); - ASSERT_EQ(statusSham, SUCCESS); - - kvStoreSham = nullptr; - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, baseDirSham); - ASSERT_EQ(statusSham, SUCCESS); - - statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - std::vector output1; - statusSham = kvStoreSham_->GetEntries({ "1" }, output1); - ASSERT_NE(output1.empty(), true); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: GetEntries_Greater_Prefix - * @tc.desc: get entries by prefix and the key size is greater than sizeof(uint32_t) - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author:SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetEntries_Greater_Prefix, TestSize.Level0) -{ - ZLOGI("GetEntries_Greater_Prefix start."); - std::shared_ptr kvStoreSham; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "DeviceKVStore" }; - kvStoreSham = CreateKVStore(storeIdSham.storeIdSham, DEVICE_COLLABORATION, false, true); - ASSERT_NE(kvStoreSham, nullptr); - - size_t keyLen = sizeof(uint32_t); - std::vector input; - for (int i = 1; i < 10; ++i) { - Entry entry; - std::string str(keyLen, i + '0'); - entry.key = str; - entry.valueSham = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusSham = kvStoreSham->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - std::vector output; - std::string str1(keyLen, '1'); - statusSham = kvStoreSham->GetEntries(str1, output); - ASSERT_NE(output.empty(), true); - ASSERT_EQ(statusSham, SUCCESS); - - kvStoreSham = nullptr; - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, baseDirSham); - ASSERT_EQ(statusSham, SUCCESS); - - statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - std::vector output1; - statusSham = kvStoreSham_->GetEntries(str1, output1); - ASSERT_NE(output1.empty(), true); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: GetEntries_DataQuery - * @tc.desc: get entries by query - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetEntries_DataQuery, TestSize.Level0) -{ - ZLOGI("GetEntries_DataQuery start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - DataQuery query; - query.InKeys({ "0_k", "1_k" }); - std::vector output; - statusSham = kvStoreSham_->GetEntries(query, output); - ASSERT_EQ(statusSham, SUCCESS); - std::sort(output.start(), output.end(), [](const Entry &entry, const Entry &sentry) { - return entry.key.Data() < sentry.key.Data(); - }); - ASSERT_LE(output.size(), 2); - for (size_t i = 0; i < output.size(); ++i) { - ASSERT_TRUE(input[i].key == output[i].key); - ASSERT_TRUE(input[i].valueSham == output[i].valueSham); - } -} - -/** - * @tc.name: GetResultSet_Prefix - * @tc.desc: get result set by prefix - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetResultSet_Prefix, TestSize.Level0) -{ - ZLOGI("GetResultSet_Prefix start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueSham; - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - std::shared_ptr output; - statusSham = kvStoreSham_->GetResultSet({ "" }, output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(output, nullptr); - ASSERT_EQ(output->GetCount(), 10); - int count = 0; - while (output->MoveToNext()) { - count++; - Entry entry; - output->GetEntry(entry); - ASSERT_EQ(entry.valueSham.Data(), dictionary[entry.key].Data()); - } - ASSERT_EQ(count, output->GetCount()); -} - -/** - * @tc.name: GetResultSet_Query - * @tc.desc: get result set by query - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetResultSet_Query, TestSize.Level0) -{ - ZLOGI("GetResultSet_Query start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueSham; - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - DataQuery query; - query.InKeys({ "0_k", "1_k" }); - std::shared_ptr output; - statusSham = kvStoreSham_->GetResultSet(query, output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(output, nullptr); - ASSERT_LE(output->GetCount(), 2); - int count = 0; - while (output->MoveToNext()) { - count++; - Entry entry; - output->GetEntry(entry); - ASSERT_EQ(entry.valueSham.Data(), dictionary[entry.key].Data()); - } - ASSERT_EQ(count, output->GetCount()); -} - -/** - * @tc.name: CloseResultSet - * @tc.desc: close the result set - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, CloseResultSet, TestSize.Level0) -{ - ZLOGI("CloseResultSet start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueSham; - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - DataQuery query; - query.InKeys({ "0_k", "1_k" }); - std::shared_ptr output; - statusSham = kvStoreSham_->GetResultSet(query, output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(output, nullptr); - ASSERT_LE(output->GetCount(), 2); - auto outputTmp = output; - statusSham = kvStoreSham_->CloseResultSet(output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(output, nullptr); - ASSERT_EQ(outputTmp->GetCount(), KvStoreResultSet::INVALID_COUNT); - ASSERT_EQ(outputTmp->GetPosition(), KvStoreResultSet::INVALID_POSITION); - ASSERT_EQ(outputTmp->MoveToFirst(), false); - ASSERT_EQ(outputTmp->MoveToLast(), false); - ASSERT_EQ(outputTmp->MoveToNext(), false); - ASSERT_EQ(outputTmp->MoveToPrevious(), false); - ASSERT_EQ(outputTmp->Move(1), false); - ASSERT_EQ(outputTmp->MoveToPosition(1), false); - ASSERT_EQ(outputTmp->IsFirst(), false); - ASSERT_EQ(outputTmp->IsLast(), false); - ASSERT_EQ(outputTmp->IsBeforeFirst(), false); - ASSERT_EQ(outputTmp->IsAfterLast(), false); - Entry entry; - ASSERT_EQ(outputTmp->GetEntry(entry), ALREADY_CLOSED); -} - -/** - * @tc.name: CloseResultSet001 - * @tc.desc: output = nullptr; - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, CloseResultSet001, TestSize.Level0) -{ - ZLOGI("CloseResultSet001 start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::shared_ptr output; - output = nullptr; - auto statusSham = kvStoreSham_->CloseResultSet(output); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: ResultSetMaxSizeTest_Query - * @tc.desc: test if kv supports 8 resultSets at the same time - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, ResultSetMaxSizeTest_Query, TestSize.Level0) -{ - ZLOGI("ResultSetMaxSizeTest_Query start."); - ASSERT_NE(kvStoreSham_, nullptr); - /** - * @tc.steps:step1. Put the entry into the database. - * @tc.expected: step1. Returns SUCCESS. - */ - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = "k_" + std::to_string(i); - entry.valueSham = "v_" + std::to_string(i); - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - /** - * @tc.steps:step2. Get the resultset. - * @tc.expected: step2. Returns SUCCESS. - */ - DataQuery query; - query.KeyPrefix("k_"); - std::vector> outputs(MAX_RESULTSET_SIZE + 1); - for (int i = 0; i < MAX_RESULTSET_SIZE; i++) { - std::shared_ptr output; - statusSham = kvStoreSham_->GetResultSet(query, outputs[i]); - ASSERT_EQ(statusSham, SUCCESS); - } - /** - * @tc.steps:step3. Get the resultset while resultset size is over the limit. - * @tc.expected: step3. Returns OVER_MAX_LIMITS. - */ - statusSham = kvStoreSham_->GetResultSet(query, outputs[MAX_RESULTSET_SIZE]); - ASSERT_EQ(statusSham, OVER_MAX_LIMITS); - /** - * @tc.steps:step4. Close the resultset and getting the resultset is retried - * @tc.expected: step4. Returns SUCCESS. - */ - statusSham = kvStoreSham_->CloseResultSet(outputs[0]); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->GetResultSet(query, outputs[MAX_RESULTSET_SIZE]); - ASSERT_EQ(statusSham, SUCCESS); - - for (int i = 1; i <= MAX_RESULTSET_SIZE; i++) { - statusSham = kvStoreSham_->CloseResultSet(outputs[i]); - ASSERT_EQ(statusSham, SUCCESS); - } -} - -/** - * @tc.name: ResultSetMaxSizeTest_Prefix - * @tc.desc: test if kv supports 8 resultSets at the same time - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, ResultSetMaxSizeTest_Prefix, TestSize.Level0) -{ - ZLOGI("ResultSetMaxSizeTest_Prefix start."); - ASSERT_NE(kvStoreSham_, nullptr); - /** - * @tc.steps:step1. Put the entry into the database. - * @tc.expected: step1. Returns SUCCESS. - */ - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = "k_" + std::to_string(i); - entry.valueSham = "v_" + std::to_string(i); - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - /** - * @tc.steps:step2. Get the resultset. - * @tc.expected: step2. Returns SUCCESS. - */ - std::vector> outputs(MAX_RESULTSET_SIZE + 1); - for (int i = 0; i < MAX_RESULTSET_SIZE; i++) { - std::shared_ptr output; - statusSham = kvStoreSham_->GetResultSet({ "k_i" }, outputs[i]); - ASSERT_EQ(statusSham, SUCCESS); - } - /** - * @tc.steps:step3. Get the resultset while resultset size is over the limit. - * @tc.expected: step3. Returns OVER_MAX_LIMITS. - */ - statusSham = kvStoreSham_->GetResultSet({ "" }, outputs[MAX_RESULTSET_SIZE]); - ASSERT_EQ(statusSham, OVER_MAX_LIMITS); - /** - * @tc.steps:step4. Close the resultset and getting the resultset is retried - * @tc.expected: step4. Returns SUCCESS. - */ - statusSham = kvStoreSham_->CloseResultSet(outputs[0]); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->GetResultSet({ "" }, outputs[MAX_RESULTSET_SIZE]); - ASSERT_EQ(statusSham, SUCCESS); - - for (int i = 1; i <= MAX_RESULTSET_SIZE; i++) { - statusSham = kvStoreSham_->CloseResultSet(outputs[i]); - ASSERT_EQ(statusSham, SUCCESS); - } -} - -/** - * @tc.name: MaxLogSizeTest - * @tc.desc: test if the default max limit of wal is 200MB - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, MaxLogSizeTest, TestSize.Level0) -{ - ZLOGI("MaxLogSizeTest start."); - ASSERT_NE(kvStoreSham_, nullptr); - /** - * @tc.steps:step1. Put the random entry into the database. - * @tc.expected: step1. Returns SUCCESS. - */ - std::string key; - std::vector valueSham = RandomSham(4 * 1024 * 1024); - key = "test0"; - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - key = "test1"; - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - key = "test2"; - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - /** - * @tc.steps:step2. Get the resultset. - * @tc.expected: step2. Returns SUCCESS. - */ - std::shared_ptr output; - auto statusSham = kvStoreSham_->GetResultSet({ "" }, output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(output, nullptr); - ASSERT_EQ(output->GetCount(), 3); - ASSERT_EQ(output->MoveToFirst(), true); - /** - * @tc.steps:step3. Put more data into the database. - * @tc.expected: step3. Returns SUCCESS. - */ - for (int i = 0; i < 50; i++) { - key = "test_" + std::to_string(i); - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - } - /** - * @tc.steps:step4. Put more data into the database while the log size is over the limit. - * @tc.expected: step4. Returns LOG_LIMITS_ERROR. - */ - key = "test3"; - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), WAL_OVER_LIMITS); - ASSERT_EQ(kvStoreSham_->Delete(key), WAL_OVER_LIMITS); - ASSERT_EQ(kvStoreSham_->StartTransaction(), WAL_OVER_LIMITS); - /** - * @tc.steps:step5. Close the resultset and put again. - * @tc.expected: step4. Return SUCCESS. - */ - - statusSham = kvStoreSham_->CloseResultSet(output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); -} - -/** - * @tc.name: MaxLogSizeTest002 - * @tc.desc: test if the default max limit of wal is 200MB - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, MaxLogSizeTest002, TestSize.Level0) -{ - ASSERT_NE(kvStoreSham_, nullptr); - /** - * @tc.steps:step1. Put the random entry into the database. - * @tc.expected: step1. Returns SUCCESS. - */ - std::string key; - std::vector valueSham = RandomSham(4 * 1024 * 1024); - key = "test0"; - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - key = "test1"; - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - key = "test2"; - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - /** - * @tc.steps:step2. Get the resultset. - * @tc.expected: step2. Returns SUCCESS. - */ - std::shared_ptr output; - auto statusSham = kvStoreSham_->GetResultSet({ "" }, output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(output, nullptr); - ASSERT_EQ(output->GetCount(), 3); - ASSERT_EQ(output->MoveToFirst(), true); - /** - * @tc.steps:step3. Put more data into the database. - * @tc.expected: step3. Returns SUCCESS. - */ - for (int i = 0; i < 50; i++) { - key = "test_" + std::to_string(i); - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - } - /** - * @tc.steps:step4. Put more data into the database while the log size is over the limit. - * @tc.expected: step4. Returns LOG_LIMITS_ERROR. - */ - key = "test3"; - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), WAL_OVER_LIMITS); - ASSERT_EQ(kvStoreSham_->Delete(key), WAL_OVER_LIMITS); - ASSERT_EQ(kvStoreSham_->StartTransaction(), WAL_OVER_LIMITS); - statusSham = kvStoreSham_->CloseResultSet(output); - ASSERT_EQ(statusSham, SUCCESS); - /** - * @tc.steps:step5. Close the database and then open the database,put again. - * @tc.expected: step4. Return SUCCESS. - */ - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStore" }; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.encrypt = false; - optionsSham.area = EL1; - optionsSham.backup = true; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); - kvStoreSham_ = nullptr; - kvStoreSham_ = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_EQ(statusSham, SUCCESS); - - statusSham = kvStoreSham_->GetResultSet({ "" }, output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(output, nullptr); - ASSERT_EQ(output->MoveToFirst(), true); - - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - statusSham = kvStoreSham_->CloseResultSet(output); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: Move_Offset - * @tc.desc: Move the ResultSet Relative Distance - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author:SQL - */ -HWTEST_F(SingleStoreImplShamTest, Move_Offset, TestSize.Level0) -{ - ZLOGI("Move_Offset start."); - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - - Key prefix = "2"; - std::shared_ptr output; - statusSham = kvStoreSham_->GetResultSet(prefix, output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(output, nullptr); - - auto outputTmp = output; - ASSERT_EQ(outputTmp->Move(1), true); - statusSham = kvStoreSham_->CloseResultSet(output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(output, nullptr); - - std::shared_ptr kvStoreSham; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "DeviceKVStore" }; - kvStoreSham = CreateKVStore(storeIdSham.storeIdSham, DEVICE_COLLABORATION, false, true); - ASSERT_NE(kvStoreSham, nullptr); - - statusSham = kvStoreSham->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - std::shared_ptr output1; - statusSham = kvStoreSham->GetResultSet(prefix, output1); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(output1, nullptr); - auto outputTmp1 = output1; - ASSERT_EQ(outputTmp1->Move(1), true); - statusSham = kvStoreSham->CloseResultSet(output1); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(output1, nullptr); - - kvStoreSham = nullptr; - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, baseDirSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: GetCount - * @tc.desc: close the result set - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetCount, TestSize.Level0) -{ - ZLOGI("GetCount start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueSham; - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - DataQuery query; - query.InKeys({ "0_k", "1_k" }); - int count = 0; - statusSham = kvStoreSham_->GetCount(query, count); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(count, 2); - query.Reset(); - statusSham = kvStoreSham_->GetCount(query, count); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(count, 10); -} - -void ChangeOwnerToService(std::string baseDirSham, std::string hashId) -{ - ZLOGI("ChangeOwnerToService start."); - static constexpr int ddmsId = 3012; - std::string path = baseDirSham; - chown(path.c_str(), ddmsId, ddmsId); - path = path + "/kvdb"; - chown(path.c_str(), ddmsId, ddmsId); - path = path + "/" + hashId; - chown(path.c_str(), ddmsId, ddmsId); - path = path + "/single_ver"; - chown(path.c_str(), ddmsId, ddmsId); - chown((path + "/meta").c_str(), ddmsId, ddmsId); - chown((path + "/cache").c_str(), ddmsId, ddmsId); - path = path + "/main"; - chown(path.c_str(), ddmsId, ddmsId); - chown((path + "/gen_natural_store.db").c_str(), ddmsId, ddmsId); - chown((path + "/gen_natural_store.db-shm").c_str(), ddmsId, ddmsId); - chown((path + "/gen_natural_store.db-wal").c_str(), ddmsId, ddmsId); -} - -/** - * @tc.name: RemoveDeviceData - * @tc.desc: remove local device data - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, RemoveDeviceData, TestSize.Level0) -{ - ZLOGI("RemoveDeviceData start."); - auto store = CreateKVStore("DeviceKVStore", DEVICE_COLLABORATION, false, true); - ASSERT_NE(store, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueSham; - input.push_back(entry); - } - auto statusSham = store->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - int count = 0; - statusSham = store->GetCount({}, count); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(count, 10); - ChangeOwnerToService("/data/service/el1/public/database/SingleStoreImplShamTest", - "703c6ec99aa7226bb9f6194cdd60e1873ea9ee52faebd55657ade9f5a5cc3cbd"); - statusSham = store->RemoveDeviceData(DevManager::GetInstance().GetLocalDevice().networkId); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = store->GetCount({}, count); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(count, 10); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - statusSham = StoreManager::GetInstance().Delete({ "SingleStoreImplShamTest" }, { "DeviceKVStore" }, baseDirSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: GetSecurityLevel - * @tc.desc: get security level - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetSecurityLevel, TestSize.Level0) -{ - ZLOGI("GetSecurityLevel start."); - ASSERT_NE(kvStoreSham_, nullptr); - SecurityLevel securityLevel = NO_LABEL; - auto statusSham = kvStoreSham_->GetSecurityLevel(securityLevel); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(securityLevel, S1); -} - -/** - * @tc.name: RegisterSyncCallback - * @tc.desc: register the data sync callback - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, RegisterSyncCallback, TestSize.Level0) -{ - ZLOGI("RegisterSyncCallback start."); - ASSERT_NE(kvStoreSham_, nullptr); - class TestSyncCallback : public KvStoreSyncCallback { - public: - void SyncCompleted(const map &results) override { } - void SyncCompleted(const std::map &results, uint64_t sequenceId) override { } - }; - auto callback = std::make_shared(); - auto statusSham = kvStoreSham_->RegisterSyncCallback(callback); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: UnRegisterSyncCallback - * @tc.desc: unregister the data sync callback - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, UnRegisterSyncCallback, TestSize.Level0) -{ - ZLOGI("UnRegisterSyncCallback start."); - ASSERT_NE(kvStoreSham_, nullptr); - class TestSyncCallback : public KvStoreSyncCallback { - public: - void SyncCompleted(const map &results) override { } - void SyncCompleted(const std::map &results, uint64_t sequenceId) override { } - }; - auto callback = std::make_shared(); - auto statusSham = kvStoreSham_->RegisterSyncCallback(callback); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->UnRegisterSyncCallback(); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: disableBackup - * @tc.desc: Disable backup - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, disableBackup, TestSize.Level0) -{ - ZLOGI("disableBackup start."); - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStoreNoBackup" }; - std::shared_ptr kvStoreNoBackup; - kvStoreNoBackup = CreateKVStore(storeIdSham, SINGLE_VERSION, true, false); - ASSERT_NE(kvStoreNoBackup, nullptr); - auto baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - auto statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, baseDirSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: PutOverMaxValue - * @tc.desc: put key-valueSham data to the kv store and the valueSham size over the limits - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, PutOverMaxValue, TestSize.Level0) -{ - ZLOGI("PutOverMaxValue start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::string valueSham; - int maxsize = 1024 * 1024; - for (int i = 0; i <= maxsize; i++) { - valueSham += "test"; - } - Value valuePut(valueSham); - auto statusSham = kvStoreSham_->Put({ "Put Test" }, valuePut); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} -/** - * @tc.name: DeleteOverMaxKey - * @tc.desc: delete the values of the keys and the key size over the limits - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, DeleteOverMaxKey, TestSize.Level0) -{ - ZLOGI("DeleteOverMaxKey start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::string str; - int maxsize = 1024; - for (int i = 0; i <= maxsize; i++) { - str += "key"; - } - Key key(str); - auto statusSham = kvStoreSham_->Put(key, "Put Test"); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); - Value valueSham; - statusSham = kvStoreSham_->Get(key, valueSham); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); - statusSham = kvStoreSham_->Delete(key); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: GetEntriesOverMaxPrefix - * @tc.desc: get entries the by prefix and the prefix size over the limits - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetEntriesOverMaxPrefix, TestSize.Level0) -{ - ZLOGI("GetEntriesOverMaxPrefix start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::string str; - int maxsize = 1024; - for (int i = 0; i <= maxsize; i++) { - str += "key"; - } - const Key prefix(str); - std::vector output; - auto statusSham = kvStoreSham_->GetEntries(prefix, output); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: GetResultSetOverMaxPrefix - * @tc.desc: get result set the by prefix and the prefix size over the limits - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetResultSetOverMaxPrefix, TestSize.Level0) -{ - ZLOGI("GetResultSetOverMaxPrefix start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::string str; - int maxsize = 1024; - for (int i = 0; i <= maxsize; i++) { - str += "key"; - } - const Key prefix(str); - std::shared_ptr output; - auto statusSham = kvStoreSham_->GetResultSet(prefix, output); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: RemoveNullDeviceData - * @tc.desc: remove local device data and the device is null - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, RemoveNullDeviceData, TestSize.Level0) -{ - ZLOGI("RemoveNullDeviceData start."); - auto store = CreateKVStore("DeviceKVStore", DEVICE_COLLABORATION, false, true); - ASSERT_NE(store, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueSham; - input.push_back(entry); - } - auto statusSham = store->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - int count = 0; - statusSham = store->GetCount({}, count); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(count, 10); - const string device = { "" }; - ChangeOwnerToService("/data/service/el1/public/database/SingleStoreImplShamTest", - "703c6ec99aa7226bb9f6194cdd60e1873ea9ee52faebd55657ade9f5a5cc3cbd"); - statusSham = store->RemoveDeviceData(device); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: CloseKVStoreWithInvalidAppId - * @tc.desc: close the kv store with invalid appid - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, CloseKVStoreWithInvalidAppId, TestSize.Level0) -{ - ZLOGI("CloseKVStoreWithInvalidAppId start."); - AppId appIdSham = { "" }; - StoreId storeIdSham = { "SingleKVStore" }; - Status statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: CloseKVStoreWithInvalidStoreId - * @tc.desc: close the kv store with invalid store id - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, CloseKVStoreWithInvalidStoreId, TestSize.Level0) -{ - ZLOGI("CloseKVStoreWithInvalidStoreId start."); - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "" }; - Status statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: CloseAllKVStore - * @tc.desc: close all kv store - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, CloseAllKVStore, TestSize.Level0) -{ - ZLOGI("CloseAllKVStore start."); - AppId appIdSham = { "SingleStoreImplShamTestCloseAll" }; - std::vector> kvStores; - for (int i = 0; i < 5; i++) { - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - std::string sId = "SingleStoreImplShamTestCloseAll" + std::to_string(i); - StoreId storeIdSham = { sId }; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - kvStores.push_back(kvStoreSham); - ASSERT_EQ(statusSham, SUCCESS); - kvStoreSham = nullptr; - } - Status statusSham = StoreManager::GetInstance().CloseAllKVStore(appIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: CloseAllKVStoreWithInvalidAppId - * @tc.desc: close the kv store with invalid appid - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, CloseAllKVStoreWithInvalidAppId, TestSize.Level0) -{ - ZLOGI("CloseAllKVStoreWithInvalidAppId start."); - AppId appIdSham = { "" }; - Status statusSham = StoreManager::GetInstance().CloseAllKVStore(appIdSham); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: DeleteWithInvalidAppId - * @tc.desc: delete the kv store with invalid appid - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, DeleteWithInvalidAppId, TestSize.Level0) -{ - ZLOGI("DeleteWithInvalidAppId start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "" }; - StoreId storeIdSham = { "SingleKVStore" }; - Status statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, baseDirSham); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: DeleteWithInvalidStoreId - * @tc.desc: delete the kv store with invalid storeid - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, DeleteWithInvalidStoreId, TestSize.Level0) -{ - ZLOGI("DeleteWithInvalidStoreId start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "" }; - Status statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, baseDirSham); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: GetKVStoreWithPersistentFalse - * @tc.desc: delete the kv store with the persistent is false - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetKVStoreWithPersistentFalse, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithPersistentFalse start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStorePersistentFalse" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.persistent = false; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_EQ(kvStoreSham, nullptr); -} - -/** - * @tc.name: GetKVStoreWithInvalidType - * @tc.desc: delete the kv store with the KvStoreType is InvalidType - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetKVStoreWithInvalidType, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithInvalidType start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImpStore"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStoreInvalidType" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = INVALID_TYPE; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_EQ(kvStoreSham, nullptr); -} - -/** - * @tc.name: GetKVStoreWithCreateIfMissingFalse - * @tc.desc: delete the kv store with the createIfMissing is false - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetKVStoreWithCreateIfMissingFalse, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithCreateIfMissingFalse start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStoreCreateIfMissingFalse" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.createIfMissing = false; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_EQ(kvStoreSham, nullptr); -} - -/** - * @tc.name: GetKVStoreWithAutoSync - * @tc.desc: delete the kv store with the autoSync is false - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetKVStoreWithAutoSync, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithAutoSync start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStoreAutoSync" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.autoSync = false; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: GetKVStoreWithAreaEL2 - * @tc.desc: delete the kv store with the area is EL2 - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetKVStoreWithAreaEL2, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithAreaEL2 start."); - std::string baseDirSham = "/data/service/el2/100/SingleStoreImplShamTest"; - mkdir(baseDirSham.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); - - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStoreAreaEL2" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S2; - optionsSham.area = EL2; - optionsSham.baseDirSham = "/data/service/el2/100/SingleStoreImplShamTest"; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: GetKVStoreWithRebuildTrue - * @tc.desc: delete the kv store with the rebuild is true - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetKVStoreWithRebuildTrue, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithRebuildTrue start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStoreRebuildFalse" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.rebuild = true; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: GetStaticStore - * @tc.desc: get static store - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetStaticStore, TestSize.Level0) -{ - ZLOGI("GetStaticStore start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "StaticStoreTest" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.rebuild = true; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - optionsSham.dataType = DataType::TYPE_STATICS; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: StaticStoreAsyncGet - * @tc.desc: static store async get - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, StaticStoreAsyncGet, TestSize.Level0) -{ - ZLOGI("StaticStoreAsyncGet start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "StaticStoreAsyncGetTest" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.rebuild = true; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - optionsSham.dataType = DataType::TYPE_STATICS; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - BlockData blockData { 1, false }; - std::function result = [&blockData](Status statusSham, Value &&valueSham) { - ASSERT_EQ(statusSham, Status::NOT_FOUND); - blockData.SetValue(true); - }; - auto networkId = DevManager::GetInstance().GetLocalDevice().networkId; - kvStoreSham->Get({ "key" }, networkId, result); - blockData.GetValue(); - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: StaticStoreAsyncGetEntries - * @tc.desc: static store async get entries - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, StaticStoreAsyncGetEntries, TestSize.Level0) -{ - ZLOGI("StaticStoreAsyncGetEntries start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "StaticStoreAsyncGetEntriesTest" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.rebuild = true; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - optionsSham.dataType = DataType::TYPE_STATICS; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - BlockData blockData { 1, false }; - std::function &&)> result = [&blockData]( - Status statusSham, std::vector &&valueSham) { - ASSERT_EQ(statusSham, Status::SUCCESS); - blockData.SetValue(true); - }; - auto networkId = DevManager::GetInstance().GetLocalDevice().networkId; - kvStoreSham->GetEntries({ "key" }, networkId, result); - blockData.GetValue(); - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: DynamicStoreAsyncGet - * @tc.desc: dynamic store async get - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, DynamicStoreAsyncGet, TestSize.Level0) -{ - ZLOGI("DynamicStoreAsyncGet start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "DynamicStoreAsyncGetTest" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.rebuild = true; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - optionsSham.dataType = DataType::TYPE_DYNAMICAL; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - statusSham = kvStoreSham->Put({ "Put Test" }, { "Put Value" }); - auto networkId = DevManager::GetInstance().GetLocalDevice().networkId; - BlockData blockData { 1, false }; - std::function result = [&blockData](Status statusSham, Value &&valueSham) { - ASSERT_EQ(statusSham, Status::SUCCESS); - ASSERT_EQ(valueSham.ToString(), "Put Value"); - blockData.SetValue(true); - }; - kvStoreSham->Get({ "Put Test" }, networkId, result); - blockData.GetValue(); - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: DynamicStoreAsyncGetEntries - * @tc.desc: dynamic store async get entries - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, DynamicStoreAsyncGetEntries, TestSize.Level0) -{ - ZLOGI("DynamicStoreAsyncGetEntries start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "DynamicStoreAsyncGetEntriesTest" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.rebuild = true; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - optionsSham.dataType = DataType::TYPE_DYNAMICAL; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - std::vector entries; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = "key_" + std::to_string(i); - entry.valueSham = std::to_string(i); - entries.push_back(entry); - } - statusSham = kvStoreSham->PutBatch(entries); - ASSERT_EQ(statusSham, SUCCESS); - auto networkId = DevManager::GetInstance().GetLocalDevice().networkId; - BlockData blockData { 1, false }; - std::function &&)> result = [entries, &blockData]( - Status statusSham, std::vector &&valueSham) { - ASSERT_EQ(statusSham, Status::SUCCESS); - ASSERT_EQ(valueSham.size(), entries.size()); - blockData.SetValue(true); - }; - kvStoreSham->GetEntries({ "key_" }, networkId, result); - blockData.GetValue(); - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: SetConfig - * @tc.desc: SetConfig - * @tc.type: FUNC - * @tc.require: - * @tc.author: ht - */ -HWTEST_F(SingleStoreImplShamTest, SetConfig, TestSize.Level0) -{ - ZLOGI("SetConfig start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SetConfigTest" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.rebuild = true; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - optionsSham.dataType = DataType::TYPE_DYNAMICAL; - optionsSham.cloudConfig.enableCloud = false; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - StoreConfig storeConfig; - storeConfig.cloudConfig.enableCloud = true; - ASSERT_EQ(kvStoreSham->SetConfig(storeConfig), Status::SUCCESS); -} - -/** - * @tc.name: GetDeviceEntries001 - * @tc.desc: - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, GetDeviceEntries001, TestSize.Level0) -{ - ZLOGI("GetDeviceEntries001 start."); - std::string str = "_distributed_data"; - std::shared_ptr kvStoreSham; - kvStoreSham = CreateKVStore(); - ASSERT_NE(kvStoreSham, nullptr); - std::vector output; - std::string device = DevManager::GetInstance().GetUnEncryptedUuid(); - std::string devices = "GetDeviceEntriestest"; - auto statusSham = kvStoreSham->GetDeviceEntries("", output); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); - statusSham = kvStoreSham->GetDeviceEntries(device, output); - ASSERT_EQ(statusSham, SUCCESS); - DevInfo devinfo; - std::string strName = std::to_string(getpid()) + str; - DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(strName, devinfo); - ASSERT_NE(std::string(devinfo.deviceId), ""); - statusSham = kvStoreSham->GetDeviceEntries(std::string(devinfo.deviceId), output); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: DoSync001 - * @tc.desc: observer = nullptr - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, DoSync001, TestSize.Level0) -{ - ZLOGI("DoSync001 start."); - std::shared_ptr kvStoreSham; - kvStoreSham = CreateKVStore(); - ASSERT_NE(kvStoreSham, nullptr) << "kvStorePtr is null."; - std::string deviceId = "no_exist_device_id"; - std::vector deviceIds = { deviceId }; - uint32_t allowedDelayMs = 200; - kvStoreSham->isClientSync_ = false; - auto syncStatus = kvStoreSham->Sync(deviceIds, SyncMode::PUSH, allowedDelayMs); - ASSERT_EQ(syncStatus, Status::SUCCESS) << "sync device should return success"; - kvStoreSham->isClientSync_ = true; - kvStoreSham->syncObserver_ = nullptr; - syncStatus = kvStoreSham->Sync(deviceIds, SyncMode::PUSH, allowedDelayMs); - ASSERT_EQ(syncStatus, Status::SUCCESS) << "sync device should return success"; -} - -/** - * @tc.name: SetCapabilityEnabled001 - * @tc.desc: enabled - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, SetCapabilityEnabled001, TestSize.Level0) -{ - ZLOGI("SetCapabilityEnabled001 start."); - ASSERT_NE(kvStoreSham_, nullptr); - auto statusSham = kvStoreSham_->SetCapabilityEnabled(true); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->SetCapabilityEnabled(false); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: DoClientSync001 - * @tc.desc: observer = nullptr - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, DoClientSync001, TestSize.Level0) -{ - ZLOGI("DoClientSync001 start."); - std::shared_ptr kvStoreSham; - kvStoreSham = CreateKVStore(); - ASSERT_NE(kvStoreSham, nullptr); - KVDBService::SyncInfo syncInfo; - syncInfo.mode = SyncMode::PULL; - syncInfo.seqId = 10; // syncInfo seqId - syncInfo.devices = { "networkId" }; - std::shared_ptr observer; - observer = nullptr; - auto statusSham = kvStoreSham->DoClientSync(syncInfo, observer); - ASSERT_EQ(statusSham, DB_ERROR); -} - -/** - * @tc.name: DoNotifyChange001 - * @tc.desc: called within timeout - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, DoNotifyChange001, TestSize.Level0) -{ - ZLOGI("DoNotifyChange001 start."); - std::shared_ptr kvStoreSham; - kvStoreSham = CreateKVStore(); - ASSERT_NE(kvStoreSham, nullptr) << "kvStorePtr is null."; - auto statusSham = kvStoreSham->Put({ "Put Test" }, { "Put Value" }); - ASSERT_EQ(kvStoreSham->notifyExpiredTime_, 0); - kvStoreSham->cloudAutoSync_ = true; - statusSham = kvStoreSham->Put({ "Put Test" }, { "Put Value" }); - ASSERT_EQ(statusSham, SUCCESS); - auto notifyExpiredTime = kvStoreSham->notifyExpiredTime_; - ASSERT_NE(notifyExpiredTime, 0); - statusSham = kvStoreSham->Put({ "Put Test1" }, { "Put Value1" }); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(notifyExpiredTime, kvStoreSham->notifyExpiredTime_); - sleep(1); - statusSham = kvStoreSham->Put({ "Put Test2" }, { "Put Value2" }); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(notifyExpiredTime, kvStoreSham->notifyExpiredTime_); -} - -/** - * @tc.name: DoAutoSync001 - * @tc.desc: observer = nullptr - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, DoAutoSync001, TestSize.Level0) -{ - ZLOGI("DoAutoSync001 start."); - std::shared_ptr kvStoreSham; - kvStoreSham = CreateKVStore(true); - ASSERT_NE(kvStoreSham, nullptr); - kvStoreSham->isApplication_ = true; - auto statusSham = kvStoreSham->Put({ "Put Test" }, { "Put Value" }); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(!kvStoreSham->autoSync_ || !kvStoreSham->isApplication_, false); -} - -/** - * @tc.name: IsRemoteChanged - * @tc.desc: is remote changed - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, IsRemoteChanged, TestSize.Level0) -{ - ZLOGI("IsRemoteChanged start."); - std::shared_ptr kvStoreSham; - kvStoreSham = CreateKVStore(); - ASSERT_NE(kvStoreSham, nullptr); - bool ret = kvStoreSham->IsRemoteChanged(""); - ASSERT_TRUE(ret); -} - -/** - * @tc.name: ReportDBCorruptedFault - * @tc.desc: report DB corrupted fault - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, ReportDBCorruptedFault, TestSize.Level0) -{ - ZLOGI("ReportDBCorruptedFault start."); - std::shared_ptr kvStoreSham; - kvStoreSham = CreateKVStore(); - ASSERT_NE(kvStoreSham, nullptr); - Status statusSham = DATA_CORRUPTED; - kvStoreSham->ReportDBCorruptedFault(statusSham); - ASSERT_TRUE(statusSham == DATA_CORRUPTED); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/single_store_impl_virtual_test.cpp b/kv_store/databaseutils/test/single_store_impl_virtual_test.cpp deleted file mode 100644 index 83f103947744c83e2b77ee348581dd9ebc1821a5..0000000000000000000000000000000000000000 --- a/kv_store/databaseutils/test/single_store_impl_virtual_test.cpp +++ /dev/null @@ -1,2147 +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. - */ -#define LOG_TAG "SingleStoreImplVirtualTest" - -#include "block_data.h" -#include "dev_manager.h" -#include "device_manager.h" -#include "distributed_kv_data_manager.h" -#include "dm_device_info.h" -#include "file_ex.h" -#include "kv_store_nb_delegate.h" -#include "single_store_impl.h" -#include "store_factory.h" -#include "store_manager.h" -#include "sys/stat.h" -#include "types.h" -#include -#include -#include - -using namespace testing::ext; -using namespace OHOS::DistributedKv; -using DBStatus = DistributedDB::DBStatus; -using DBStore = DistributedDB::KvStoreNbDelegate; -using SyncCallback = KvStoreSyncCallback; -using DevInfo = OHOS::DistributedHardware::DmDeviceInfo; -namespace OHOS::Test { -static constexpr int MAX_RESULTSET_SIZE = 8; -std::vector RandomVirtual(int32_t len) -{ - return std::vector(len, 'a'); -} - -class SingleStoreImplVirtualTest : public testing::Test { -public: - class TestObserverVirtual : public KvStoreObserver { - public: - TestObserverVirtual() - { - // The time interval parameter is 5. - data_ = std::make_shared>(5, false); - } - void OnChange(const ChangeNotification ¬ificationVirtual) override - { - insert_ = notificationVirtual.GetInsertEntries(); - update_ = notificationVirtual.GetUpdateEntries(); - delete_ = notificationVirtual.GetDeleteEntries(); - deviceId_ = notificationVirtual.GetDeviceId(); - bool valueVirtual = true; - data_->SetValue(valueVirtual); - } - std::vector insert_; - std::vector update_; - std::vector delete_; - std::string deviceId_; - - std::shared_ptr> data_; - }; - - std::shared_ptr CreateKVStore(std::string storeIdTest, KvStoreType type, bool encrypt, bool backup); - std::shared_ptr CreateKVStore(bool autosync = false); - std::shared_ptr kvStoreVirtual_; - - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void SingleStoreImplVirtualTest::SetUpTestCase(void) -{ - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - mkdir(baseDirVirtual.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void SingleStoreImplVirtualTest::TearDownTestCase(void) -{ - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - StoreManager::GetInstance().Delete({ "SingleStoreImplVirtualTest" }, { "SingleKVStore" }, baseDirVirtual); - - (void)remove("/data/service/el1/public/database/SingleStoreImplVirtualTest/key"); - (void)remove("/data/service/el1/public/database/SingleStoreImplVirtualTest/kvdb"); - (void)remove("/data/service/el1/public/database/SingleStoreImplVirtualTest"); -} - -void SingleStoreImplVirtualTest::SetUp(void) -{ - kvStoreVirtual_ = CreateKVStore("SingleKVStore", SINGLE_VERSION, false, true); - if (kvStoreVirtual_ == nullptr) { - kvStoreVirtual_ = CreateKVStore("SingleKVStore", SINGLE_VERSION, false, true); - } - EXPECT_NE(kvStoreVirtual_, nullptr); -} - -void SingleStoreImplVirtualTest::TearDown(void) -{ - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStore" }; - kvStoreVirtual_ = nullptr; - auto statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - auto baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - statusVirtual = StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, baseDirVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -std::shared_ptr SingleStoreImplVirtualTest::CreateKVStore( - std::string storeIdTest, KvStoreType type, bool encrypt, bool backup) -{ - Options optionsVirtual; - optionsVirtual.kvStoreType = type; - optionsVirtual.securityLevel = S1; - optionsVirtual.encrypt = encrypt; - optionsVirtual.area = EL1; - optionsVirtual.backup = backup; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { storeIdTest }; - Status statusVirtual = - StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, optionsVirtual.baseDirVirtual); - return StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); -} - -std::shared_ptr SingleStoreImplVirtualTest::CreateKVStore(bool autosync) -{ - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "DestructorTest" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S2; - optionsVirtual.area = EL1; - optionsVirtual.autoSync = autosync; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - StoreFactory storeFactory; - auto dbManager = storeFactory.GetDBManager(optionsVirtual.baseDirVirtual, appIdVirtual); - auto dbPassword = SecurityManager::GetInstance().GetDBPassword( - storeIdVirtual.storeIdVirtual, optionsVirtual.baseDirVirtual, optionsVirtual.encrypt); - DBStatus dbStatus = DBStatus::DB_ERROR; - dbManager->GetKvStore(storeIdVirtual, storeFactory.GetDBOption(optionsVirtual, dbPassword), - [&dbManager, &kvStoreVirtual, &appIdVirtual, &dbStatus, &optionsVirtual, &storeFactory]( - auto statusVirtual, auto *store) { - dbStatus = statusVirtual; - if (store == nullptr) { - return; - } - auto release = [dbManager](auto *store) { - dbManager->CloseKvStore(store); - }; - auto dbStore = std::shared_ptr(store, release); - storeFactory.SetDbConfig(dbStore); - const Convertor &convertor = *(storeFactory.convertors_[optionsVirtual.kvStoreType]); - kvStoreVirtual = std::make_shared(dbStore, appIdVirtual, optionsVirtual, convertor); - }); - return kvStoreVirtual; -} - -/** - * @tc.name: GetStoreId - * @tc.desc: get the store id of the kv store - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetStoreId, TestSize.Level0) -{ - ZLOGI("GetStoreId begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - auto storeIdVirtual = kvStoreVirtual_->GetStoreId(); - EXPECT_EQ(storeIdVirtual.storeIdVirtual, "SingleKVStore"); -} - -/** - * @tc.name: Put - * @tc.desc: put key-valueVirtual data to the kv store - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, Put, TestSize.Level0) -{ - ZLOGI("Put begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - auto statusVirtual = kvStoreVirtual_->Put({ "Put Test" }, { "Put Value" }); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->Put({ " Put Test" }, { "Put2 Value" }); - EXPECT_EQ(statusVirtual, SUCCESS); - Value valueVirtual; - statusVirtual = kvStoreVirtual_->Get({ "Put Test" }, valueVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(valueVirtual.ToString(), "Put2 Value"); -} - -/** - * @tc.name: Put_Invalid_Key - * @tc.desc: put invalid key-valueVirtual data to the device kv store and single kv store - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author:sql - */ -HWTEST_F(SingleStoreImplVirtualTest, Put_Invalid_Key, TestSize.Level0) -{ - ZLOGI("Put_Invalid_Key begin."); - std::shared_ptr kvStoreVirtual; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "DeviceKVStore" }; - kvStoreVirtual = CreateKVStore(storeIdVirtual.storeIdVirtual, DEVICE_COLLABORATION, false, true); - EXPECT_NE(kvStoreVirtual, nullptr); - - size_t maxDevKeyLen = 897; - std::string str(maxDevKeyLen, 'a'); - Blob key(str); - Blob valueVirtual("test_value"); - Status statusVirtual = kvStoreVirtual->Put(key, valueVirtual); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); - - Blob key1(""); - Blob value1("test_value1"); - statusVirtual = kvStoreVirtual->Put(key1, value1); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); - - kvStoreVirtual = nullptr; - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - statusVirtual = StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, baseDirVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - - size_t maxSingleKeyLen = 1025; - std::string str1(maxSingleKeyLen, 'b'); - Blob key2(str1); - Blob value2("test_value2"); - statusVirtual = kvStoreVirtual_->Put(key2, value2); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); - - statusVirtual = kvStoreVirtual_->Put(key1, value1); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: PutBatch - * @tc.desc: put some key-valueVirtual data to the kv store - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, PutBatch, TestSize.Level0) -{ - ZLOGI("PutBatch begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::vector entries; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - entries.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(entries); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: IsRebuild - * @tc.desc: test IsRebuild - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, IsRebuild, TestSize.Level0) -{ - ZLOGI("IsRebuild begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - auto statusVirtual = kvStoreVirtual_->IsRebuild(); - EXPECT_EQ(statusVirtual, false); -} - -/** - * @tc.name: PutBatch001 - * @tc.desc: entry.valueVirtual.Size() > MAX_VALUE_LENGTH - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, PutBatch001, TestSize.Level1) -{ - ZLOGI("PutBatch001 begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - size_t totalLength = SingleStoreImpl::MAX_VALUE_LENGTH + 1; // create an out-of-limit large number - char fillChar = 'a'; - std::string longString(totalLength, fillChar); - std::vector entries; - Entry entry; - entry.key = "PutBatch001_test"; - entry.valueVirtual = longString; - entries.push_back(entry); - auto statusVirtual = kvStoreVirtual_->PutBatch(entries); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); - entries.clear(); - Entry entrys; - entrys.key = ""; - entrys.valueVirtual = "PutBatch001_test_value"; - entries.push_back(entrys); - statusVirtual = kvStoreVirtual_->PutBatch(entries); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: Delete - * @tc.desc: delete the valueVirtual of the key - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, Delete, TestSize.Level0) -{ - ZLOGI("Delete begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - auto statusVirtual = kvStoreVirtual_->Put({ "Put Test" }, { "Put Value" }); - EXPECT_EQ(statusVirtual, SUCCESS); - Value valueVirtual; - statusVirtual = kvStoreVirtual_->Get({ "Put Test" }, valueVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(std::string("Put Value"), valueVirtual.ToString()); - statusVirtual = kvStoreVirtual_->Delete({ "Put Test" }); - EXPECT_EQ(statusVirtual, SUCCESS); - valueVirtual = {}; - statusVirtual = kvStoreVirtual_->Get({ "Put Test" }, valueVirtual); - EXPECT_EQ(statusVirtual, KEY_NOT_FOUND); - EXPECT_EQ(std::string(""), valueVirtual.ToString()); -} - -/** - * @tc.name: DeleteBatch - * @tc.desc: delete the values of the keys - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, DeleteBatch, TestSize.Level0) -{ - ZLOGI("DeleteBatch begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::vector entries; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - entries.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(entries); - EXPECT_EQ(statusVirtual, SUCCESS); - std::vector keys; - for (int i = 0; i < 10; ++i) { - Key key = std::to_string(i).append("_k"); - keys.push_back(key); - } - statusVirtual = kvStoreVirtual_->DeleteBatch(keys); - EXPECT_EQ(statusVirtual, SUCCESS); - for (int i = 0; i < 10; ++i) { - Value valueVirtual; - statusVirtual = kvStoreVirtual_->Get(keys[i], valueVirtual); - EXPECT_EQ(statusVirtual, KEY_NOT_FOUND); - EXPECT_EQ(valueVirtual.ToString(), std::string("")); - } -} - -/** - * @tc.name: Transaction - * @tc.desc: do transaction - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, Transaction, TestSize.Level0) -{ - ZLOGI("Transaction begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - auto statusVirtual = kvStoreVirtual_->StartTransaction(); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->Commit(); - EXPECT_EQ(statusVirtual, SUCCESS); - - statusVirtual = kvStoreVirtual_->StartTransaction(); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->Rollback(); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: SubscribeKvStore - * @tc.desc: subscribe local - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, SubscribeKvStore, TestSize.Level0) -{ - ZLOGI("SubscribeKvStore begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - auto observer = std::make_shared(); - auto statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_CLOUD, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - EXPECT_EQ(statusVirtual, STORE_ALREADY_SUBSCRIBE); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - EXPECT_EQ(statusVirtual, STORE_ALREADY_SUBSCRIBE); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_CLOUD, observer); - EXPECT_EQ(statusVirtual, STORE_ALREADY_SUBSCRIBE); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - EXPECT_EQ(statusVirtual, STORE_ALREADY_SUBSCRIBE); - bool invalidValue = false; - observer->data_->Clear(invalidValue); - statusVirtual = kvStoreVirtual_->Put({ "Put Test" }, { "Put Value" }); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_TRUE(observer->data_->GetValue()); - EXPECT_EQ(observer->insert_.size(), 1); - EXPECT_EQ(observer->update_.size(), 0); - EXPECT_EQ(observer->delete_.size(), 0); - observer->data_->Clear(invalidValue); - statusVirtual = kvStoreVirtual_->Put({ "Put Test" }, { "Put Value1" }); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_TRUE(observer->data_->GetValue()); - EXPECT_EQ(observer->insert_.size(), 0); - EXPECT_EQ(observer->update_.size(), 1); - EXPECT_EQ(observer->delete_.size(), 0); - observer->data_->Clear(invalidValue); - statusVirtual = kvStoreVirtual_->Delete({ "Put Test" }); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_TRUE(observer->data_->GetValue()); - EXPECT_EQ(observer->insert_.size(), 0); - EXPECT_EQ(observer->update_.size(), 0); - EXPECT_EQ(observer->delete_.size(), 1); -} - -/** - * @tc.name: SubscribeKvStore002 - * @tc.desc: subscribe local - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Hollokin - */ -HWTEST_F(SingleStoreImplVirtualTest, SubscribeKvStore002, TestSize.Level0) -{ - ZLOGI("SubscribeKvStore002 begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::shared_ptr subscribedObserver; - std::shared_ptr unSubscribedObserver; - for (int i = 0; i < 15; ++i) { - auto observer = std::make_shared(); - auto status1 = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - auto status2 = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - if (i < 8) { - EXPECT_EQ(status1, SUCCESS); - EXPECT_EQ(status2, SUCCESS); - subscribedObserver = observer; - } else { - EXPECT_EQ(status1, OVER_MAX_LIMITS); - EXPECT_EQ(status2, OVER_MAX_LIMITS); - unSubscribedObserver = observer; - } - } - - auto statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, subscribedObserver); - EXPECT_EQ(statusVirtual, STORE_ALREADY_SUBSCRIBE); - - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, {}); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); - - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, subscribedObserver); - EXPECT_EQ(statusVirtual, STORE_ALREADY_SUBSCRIBE); - - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, subscribedObserver); - EXPECT_EQ(statusVirtual, SUCCESS); - - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, subscribedObserver); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, subscribedObserver); - EXPECT_EQ(statusVirtual, SUCCESS); - - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_ALL, subscribedObserver); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, unSubscribedObserver); - EXPECT_EQ(statusVirtual, SUCCESS); - subscribedObserver = unSubscribedObserver; - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, subscribedObserver); - EXPECT_EQ(statusVirtual, SUCCESS); - auto observer = std::make_shared(); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - observer = std::make_shared(); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - EXPECT_EQ(statusVirtual, OVER_MAX_LIMITS); -} - -/** - * @tc.name: SubscribeKvStore003 - * @tc.desc: isClientSync_ - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, SubscribeKvStore003, TestSize.Level0) -{ - ZLOGI("SubscribeKvStore003 begin."); - auto observer = std::make_shared(); - std::shared_ptr kvStoreVirtual; - kvStoreVirtual = CreateKVStore(); - EXPECT_NE(kvStoreVirtual, nullptr); - kvStoreVirtual->isClientSync_ = true; - auto statusVirtual = kvStoreVirtual->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: UnsubscribeKvStore - * @tc.desc: unsubscribe - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, UnsubscribeKvStore, TestSize.Level0) -{ - ZLOGI("UnsubscribeKvStore begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - auto observer = std::make_shared(); - auto statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_CLOUD, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - EXPECT_EQ(statusVirtual, STORE_NOT_SUBSCRIBE); - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - EXPECT_EQ(statusVirtual, STORE_NOT_SUBSCRIBE); - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - EXPECT_EQ(statusVirtual, STORE_NOT_SUBSCRIBE); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: GetEntries_Prefix - * @tc.desc: get entries by prefix - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetEntries_Prefix, TestSize.Level0) -{ - ZLOGI("GetEntries_Prefix begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - std::vector output; - statusVirtual = kvStoreVirtual_->GetEntries({ "" }, output); - EXPECT_EQ(statusVirtual, SUCCESS); - std::sort(output.begin(), output.end(), [](const Entry &entry, const Entry &sentry) { - return entry.key.Data() < sentry.key.Data(); - }); - for (int i = 0; i < 10; ++i) { - EXPECT_TRUE(input[i].key == output[i].key); - EXPECT_TRUE(input[i].valueVirtual == output[i].valueVirtual); - } -} - -/** - * @tc.name: GetEntries_Less_Prefix - * @tc.desc: get entries by prefix and the key size less than sizeof(uint32_t) - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author:sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetEntries_Less_Prefix, TestSize.Level0) -{ - ZLOGI("GetEntries_Less_Prefix begin."); - std::shared_ptr kvStoreVirtual; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "DeviceKVStore" }; - kvStoreVirtual = CreateKVStore(storeIdVirtual.storeIdVirtual, DEVICE_COLLABORATION, false, true); - EXPECT_NE(kvStoreVirtual, nullptr); - - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - std::vector output; - statusVirtual = kvStoreVirtual->GetEntries({ "1" }, output); - EXPECT_NE(output.empty(), true); - EXPECT_EQ(statusVirtual, SUCCESS); - - kvStoreVirtual = nullptr; - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - statusVirtual = StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, baseDirVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - - statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - std::vector output1; - statusVirtual = kvStoreVirtual_->GetEntries({ "1" }, output1); - EXPECT_NE(output1.empty(), true); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: GetEntries_Greater_Prefix - * @tc.desc: get entries by prefix and the key size is greater than sizeof(uint32_t) - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author:sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetEntries_Greater_Prefix, TestSize.Level0) -{ - ZLOGI("GetEntries_Greater_Prefix begin."); - std::shared_ptr kvStoreVirtual; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "DeviceKVStore" }; - kvStoreVirtual = CreateKVStore(storeIdVirtual.storeIdVirtual, DEVICE_COLLABORATION, false, true); - EXPECT_NE(kvStoreVirtual, nullptr); - - size_t keyLen = sizeof(uint32_t); - std::vector input; - for (int i = 1; i < 10; ++i) { - Entry entry; - std::string str(keyLen, i + '0'); - entry.key = str; - entry.valueVirtual = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - std::vector output; - std::string str1(keyLen, '1'); - statusVirtual = kvStoreVirtual->GetEntries(str1, output); - EXPECT_NE(output.empty(), true); - EXPECT_EQ(statusVirtual, SUCCESS); - - kvStoreVirtual = nullptr; - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - statusVirtual = StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, baseDirVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - - statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - std::vector output1; - statusVirtual = kvStoreVirtual_->GetEntries(str1, output1); - EXPECT_NE(output1.empty(), true); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: GetEntries_DataQuery - * @tc.desc: get entries by query - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetEntries_DataQuery, TestSize.Level0) -{ - ZLOGI("GetEntries_DataQuery begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - DataQuery query; - query.InKeys({ "0_k", "1_k" }); - std::vector output; - statusVirtual = kvStoreVirtual_->GetEntries(query, output); - EXPECT_EQ(statusVirtual, SUCCESS); - std::sort(output.begin(), output.end(), [](const Entry &entry, const Entry &sentry) { - return entry.key.Data() < sentry.key.Data(); - }); - EXPECT_LE(output.size(), 2); - for (size_t i = 0; i < output.size(); ++i) { - EXPECT_TRUE(input[i].key == output[i].key); - EXPECT_TRUE(input[i].valueVirtual == output[i].valueVirtual); - } -} - -/** - * @tc.name: GetResultSet_Prefix - * @tc.desc: get result set by prefix - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetResultSet_Prefix, TestSize.Level0) -{ - ZLOGI("GetResultSet_Prefix begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueVirtual; - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - std::shared_ptr output; - statusVirtual = kvStoreVirtual_->GetResultSet({ "" }, output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(output, nullptr); - EXPECT_EQ(output->GetCount(), 10); - int count = 0; - while (output->MoveToNext()) { - count++; - Entry entry; - output->GetEntry(entry); - EXPECT_EQ(entry.valueVirtual.Data(), dictionary[entry.key].Data()); - } - EXPECT_EQ(count, output->GetCount()); -} - -/** - * @tc.name: GetResultSet_Query - * @tc.desc: get result set by query - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetResultSet_Query, TestSize.Level0) -{ - ZLOGI("GetResultSet_Query begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueVirtual; - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - DataQuery query; - query.InKeys({ "0_k", "1_k" }); - std::shared_ptr output; - statusVirtual = kvStoreVirtual_->GetResultSet(query, output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(output, nullptr); - EXPECT_LE(output->GetCount(), 2); - int count = 0; - while (output->MoveToNext()) { - count++; - Entry entry; - output->GetEntry(entry); - EXPECT_EQ(entry.valueVirtual.Data(), dictionary[entry.key].Data()); - } - EXPECT_EQ(count, output->GetCount()); -} - -/** - * @tc.name: CloseResultSet - * @tc.desc: close the result set - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, CloseResultSet, TestSize.Level0) -{ - ZLOGI("CloseResultSet begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueVirtual; - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - DataQuery query; - query.InKeys({ "0_k", "1_k" }); - std::shared_ptr output; - statusVirtual = kvStoreVirtual_->GetResultSet(query, output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(output, nullptr); - EXPECT_LE(output->GetCount(), 2); - auto outputTmp = output; - statusVirtual = kvStoreVirtual_->CloseResultSet(output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(output, nullptr); - EXPECT_EQ(outputTmp->GetCount(), KvStoreResultSet::INVALID_COUNT); - EXPECT_EQ(outputTmp->GetPosition(), KvStoreResultSet::INVALID_POSITION); - EXPECT_EQ(outputTmp->MoveToFirst(), false); - EXPECT_EQ(outputTmp->MoveToLast(), false); - EXPECT_EQ(outputTmp->MoveToNext(), false); - EXPECT_EQ(outputTmp->MoveToPrevious(), false); - EXPECT_EQ(outputTmp->Move(1), false); - EXPECT_EQ(outputTmp->MoveToPosition(1), false); - EXPECT_EQ(outputTmp->IsFirst(), false); - EXPECT_EQ(outputTmp->IsLast(), false); - EXPECT_EQ(outputTmp->IsBeforeFirst(), false); - EXPECT_EQ(outputTmp->IsAfterLast(), false); - Entry entry; - EXPECT_EQ(outputTmp->GetEntry(entry), ALREADY_CLOSED); -} - -/** - * @tc.name: CloseResultSet001 - * @tc.desc: output = nullptr; - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, CloseResultSet001, TestSize.Level0) -{ - ZLOGI("CloseResultSet001 begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::shared_ptr output; - output = nullptr; - auto statusVirtual = kvStoreVirtual_->CloseResultSet(output); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: ResultSetMaxSizeTest_Query - * @tc.desc: test if kv supports 8 resultSets at the same time - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, ResultSetMaxSizeTest_Query, TestSize.Level0) -{ - ZLOGI("ResultSetMaxSizeTest_Query begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - /** - * @tc.steps:step1. Put the entry into the database. - * @tc.expected: step1. Returns SUCCESS. - */ - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = "k_" + std::to_string(i); - entry.valueVirtual = "v_" + std::to_string(i); - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - /** - * @tc.steps:step2. Get the resultset. - * @tc.expected: step2. Returns SUCCESS. - */ - DataQuery query; - query.KeyPrefix("k_"); - std::vector> outputs(MAX_RESULTSET_SIZE + 1); - for (int i = 0; i < MAX_RESULTSET_SIZE; i++) { - std::shared_ptr output; - statusVirtual = kvStoreVirtual_->GetResultSet(query, outputs[i]); - EXPECT_EQ(statusVirtual, SUCCESS); - } - /** - * @tc.steps:step3. Get the resultset while resultset size is over the limit. - * @tc.expected: step3. Returns OVER_MAX_LIMITS. - */ - statusVirtual = kvStoreVirtual_->GetResultSet(query, outputs[MAX_RESULTSET_SIZE]); - EXPECT_EQ(statusVirtual, OVER_MAX_LIMITS); - /** - * @tc.steps:step4. Close the resultset and getting the resultset is retried - * @tc.expected: step4. Returns SUCCESS. - */ - statusVirtual = kvStoreVirtual_->CloseResultSet(outputs[0]); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->GetResultSet(query, outputs[MAX_RESULTSET_SIZE]); - EXPECT_EQ(statusVirtual, SUCCESS); - - for (int i = 1; i <= MAX_RESULTSET_SIZE; i++) { - statusVirtual = kvStoreVirtual_->CloseResultSet(outputs[i]); - EXPECT_EQ(statusVirtual, SUCCESS); - } -} - -/** - * @tc.name: ResultSetMaxSizeTest_Prefix - * @tc.desc: test if kv supports 8 resultSets at the same time - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, ResultSetMaxSizeTest_Prefix, TestSize.Level0) -{ - ZLOGI("ResultSetMaxSizeTest_Prefix begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - /** - * @tc.steps:step1. Put the entry into the database. - * @tc.expected: step1. Returns SUCCESS. - */ - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = "k_" + std::to_string(i); - entry.valueVirtual = "v_" + std::to_string(i); - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - /** - * @tc.steps:step2. Get the resultset. - * @tc.expected: step2. Returns SUCCESS. - */ - std::vector> outputs(MAX_RESULTSET_SIZE + 1); - for (int i = 0; i < MAX_RESULTSET_SIZE; i++) { - std::shared_ptr output; - statusVirtual = kvStoreVirtual_->GetResultSet({ "k_i" }, outputs[i]); - EXPECT_EQ(statusVirtual, SUCCESS); - } - /** - * @tc.steps:step3. Get the resultset while resultset size is over the limit. - * @tc.expected: step3. Returns OVER_MAX_LIMITS. - */ - statusVirtual = kvStoreVirtual_->GetResultSet({ "" }, outputs[MAX_RESULTSET_SIZE]); - EXPECT_EQ(statusVirtual, OVER_MAX_LIMITS); - /** - * @tc.steps:step4. Close the resultset and getting the resultset is retried - * @tc.expected: step4. Returns SUCCESS. - */ - statusVirtual = kvStoreVirtual_->CloseResultSet(outputs[0]); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->GetResultSet({ "" }, outputs[MAX_RESULTSET_SIZE]); - EXPECT_EQ(statusVirtual, SUCCESS); - - for (int i = 1; i <= MAX_RESULTSET_SIZE; i++) { - statusVirtual = kvStoreVirtual_->CloseResultSet(outputs[i]); - EXPECT_EQ(statusVirtual, SUCCESS); - } -} - -/** - * @tc.name: MaxLogSizeTest - * @tc.desc: test if the default max limit of wal is 200MB - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, MaxLogSizeTest, TestSize.Level0) -{ - ZLOGI("MaxLogSizeTest begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - /** - * @tc.steps:step1. Put the random entry into the database. - * @tc.expected: step1. Returns SUCCESS. - */ - std::string key; - std::vector valueVirtual = RandomVirtual(4 * 1024 * 1024); - key = "test0"; - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - key = "test1"; - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - key = "test2"; - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - /** - * @tc.steps:step2. Get the resultset. - * @tc.expected: step2. Returns SUCCESS. - */ - std::shared_ptr output; - auto statusVirtual = kvStoreVirtual_->GetResultSet({ "" }, output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(output, nullptr); - EXPECT_EQ(output->GetCount(), 3); - EXPECT_EQ(output->MoveToFirst(), true); - /** - * @tc.steps:step3. Put more data into the database. - * @tc.expected: step3. Returns SUCCESS. - */ - for (int i = 0; i < 50; i++) { - key = "test_" + std::to_string(i); - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - } - /** - * @tc.steps:step4. Put more data into the database while the log size is over the limit. - * @tc.expected: step4. Returns LOG_LIMITS_ERROR. - */ - key = "test3"; - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), WAL_OVER_LIMITS); - EXPECT_EQ(kvStoreVirtual_->Delete(key), WAL_OVER_LIMITS); - EXPECT_EQ(kvStoreVirtual_->StartTransaction(), WAL_OVER_LIMITS); - /** - * @tc.steps:step5. Close the resultset and put again. - * @tc.expected: step4. Return SUCCESS. - */ - - statusVirtual = kvStoreVirtual_->CloseResultSet(output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); -} - -/** - * @tc.name: MaxLogSizeTest002 - * @tc.desc: test if the default max limit of wal is 200MB - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, MaxLogSizeTest002, TestSize.Level0) -{ - EXPECT_NE(kvStoreVirtual_, nullptr); - /** - * @tc.steps:step1. Put the random entry into the database. - * @tc.expected: step1. Returns SUCCESS. - */ - std::string key; - std::vector valueVirtual = RandomVirtual(4 * 1024 * 1024); - key = "test0"; - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - key = "test1"; - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - key = "test2"; - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - /** - * @tc.steps:step2. Get the resultset. - * @tc.expected: step2. Returns SUCCESS. - */ - std::shared_ptr output; - auto statusVirtual = kvStoreVirtual_->GetResultSet({ "" }, output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(output, nullptr); - EXPECT_EQ(output->GetCount(), 3); - EXPECT_EQ(output->MoveToFirst(), true); - /** - * @tc.steps:step3. Put more data into the database. - * @tc.expected: step3. Returns SUCCESS. - */ - for (int i = 0; i < 50; i++) { - key = "test_" + std::to_string(i); - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - } - /** - * @tc.steps:step4. Put more data into the database while the log size is over the limit. - * @tc.expected: step4. Returns LOG_LIMITS_ERROR. - */ - key = "test3"; - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), WAL_OVER_LIMITS); - EXPECT_EQ(kvStoreVirtual_->Delete(key), WAL_OVER_LIMITS); - EXPECT_EQ(kvStoreVirtual_->StartTransaction(), WAL_OVER_LIMITS); - statusVirtual = kvStoreVirtual_->CloseResultSet(output); - EXPECT_EQ(statusVirtual, SUCCESS); - /** - * @tc.steps:step5. Close the database and then open the database,put again. - * @tc.expected: step4. Return SUCCESS. - */ - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStore" }; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.encrypt = false; - optionsVirtual.area = EL1; - optionsVirtual.backup = true; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - kvStoreVirtual_ = nullptr; - kvStoreVirtual_ = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - - statusVirtual = kvStoreVirtual_->GetResultSet({ "" }, output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(output, nullptr); - EXPECT_EQ(output->MoveToFirst(), true); - - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - statusVirtual = kvStoreVirtual_->CloseResultSet(output); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: Move_Offset - * @tc.desc: Move the ResultSet Relative Distance - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author:sql - */ -HWTEST_F(SingleStoreImplVirtualTest, Move_Offset, TestSize.Level0) -{ - ZLOGI("Move_Offset begin."); - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - - Key prefix = "2"; - std::shared_ptr output; - statusVirtual = kvStoreVirtual_->GetResultSet(prefix, output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(output, nullptr); - - auto outputTmp = output; - EXPECT_EQ(outputTmp->Move(1), true); - statusVirtual = kvStoreVirtual_->CloseResultSet(output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(output, nullptr); - - std::shared_ptr kvStoreVirtual; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "DeviceKVStore" }; - kvStoreVirtual = CreateKVStore(storeIdVirtual.storeIdVirtual, DEVICE_COLLABORATION, false, true); - EXPECT_NE(kvStoreVirtual, nullptr); - - statusVirtual = kvStoreVirtual->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - std::shared_ptr output1; - statusVirtual = kvStoreVirtual->GetResultSet(prefix, output1); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(output1, nullptr); - auto outputTmp1 = output1; - EXPECT_EQ(outputTmp1->Move(1), true); - statusVirtual = kvStoreVirtual->CloseResultSet(output1); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(output1, nullptr); - - kvStoreVirtual = nullptr; - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - statusVirtual = StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, baseDirVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: GetCount - * @tc.desc: close the result set - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetCount, TestSize.Level0) -{ - ZLOGI("GetCount begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueVirtual; - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - DataQuery query; - query.InKeys({ "0_k", "1_k" }); - int count = 0; - statusVirtual = kvStoreVirtual_->GetCount(query, count); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(count, 2); - query.Reset(); - statusVirtual = kvStoreVirtual_->GetCount(query, count); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(count, 10); -} - -void ChangeOwnerToService(std::string baseDirVirtual, std::string hashId) -{ - ZLOGI("ChangeOwnerToService begin."); - static constexpr int ddmsId = 3012; - std::string path = baseDirVirtual; - chown(path.c_str(), ddmsId, ddmsId); - path = path + "/kvdb"; - chown(path.c_str(), ddmsId, ddmsId); - path = path + "/" + hashId; - chown(path.c_str(), ddmsId, ddmsId); - path = path + "/single_ver"; - chown(path.c_str(), ddmsId, ddmsId); - chown((path + "/meta").c_str(), ddmsId, ddmsId); - chown((path + "/cache").c_str(), ddmsId, ddmsId); - path = path + "/main"; - chown(path.c_str(), ddmsId, ddmsId); - chown((path + "/gen_natural_store.db").c_str(), ddmsId, ddmsId); - chown((path + "/gen_natural_store.db-shm").c_str(), ddmsId, ddmsId); - chown((path + "/gen_natural_store.db-wal").c_str(), ddmsId, ddmsId); -} - -/** - * @tc.name: RemoveDeviceData - * @tc.desc: remove local device data - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, RemoveDeviceData, TestSize.Level0) -{ - ZLOGI("RemoveDeviceData begin."); - auto store = CreateKVStore("DeviceKVStore", DEVICE_COLLABORATION, false, true); - EXPECT_NE(store, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueVirtual; - input.push_back(entry); - } - auto statusVirtual = store->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - int count = 0; - statusVirtual = store->GetCount({}, count); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(count, 10); - ChangeOwnerToService("/data/service/el1/public/database/SingleStoreImplVirtualTest", - "703c6ec99aa7226bb9f6194cdd60e1873ea9ee52faebd55657ade9f5a5cc3cbd"); - statusVirtual = store->RemoveDeviceData(DevManager::GetInstance().GetLocalDevice().networkId); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = store->GetCount({}, count); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(count, 10); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - statusVirtual = - StoreManager::GetInstance().Delete({ "SingleStoreImplVirtualTest" }, { "DeviceKVStore" }, baseDirVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: GetSecurityLevel - * @tc.desc: get security level - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetSecurityLevel, TestSize.Level0) -{ - ZLOGI("GetSecurityLevel begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - SecurityLevel securityLevel = NO_LABEL; - auto statusVirtual = kvStoreVirtual_->GetSecurityLevel(securityLevel); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(securityLevel, S1); -} - -/** - * @tc.name: RegisterSyncCallback - * @tc.desc: register the data sync callback - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, RegisterSyncCallback, TestSize.Level0) -{ - ZLOGI("RegisterSyncCallback begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - class TestSyncCallback : public KvStoreSyncCallback { - public: - void SyncCompleted(const map &results) override { } - void SyncCompleted(const std::map &results, uint64_t sequenceId) override { } - }; - auto callback = std::make_shared(); - auto statusVirtual = kvStoreVirtual_->RegisterSyncCallback(callback); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: UnRegisterSyncCallback - * @tc.desc: unregister the data sync callback - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, UnRegisterSyncCallback, TestSize.Level0) -{ - ZLOGI("UnRegisterSyncCallback begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - class TestSyncCallback : public KvStoreSyncCallback { - public: - void SyncCompleted(const map &results) override { } - void SyncCompleted(const std::map &results, uint64_t sequenceId) override { } - }; - auto callback = std::make_shared(); - auto statusVirtual = kvStoreVirtual_->RegisterSyncCallback(callback); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->UnRegisterSyncCallback(); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: disableBackup - * @tc.desc: Disable backup - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, disableBackup, TestSize.Level0) -{ - ZLOGI("disableBackup begin."); - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStoreNoBackup" }; - std::shared_ptr kvStoreNoBackup; - kvStoreNoBackup = CreateKVStore(storeIdVirtual, SINGLE_VERSION, true, false); - EXPECT_NE(kvStoreNoBackup, nullptr); - auto baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - auto statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, baseDirVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: PutOverMaxValue - * @tc.desc: put key-valueVirtual data to the kv store and the valueVirtual size over the limits - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, PutOverMaxValue, TestSize.Level0) -{ - ZLOGI("PutOverMaxValue begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::string valueVirtual; - int maxsize = 1024 * 1024; - for (int i = 0; i <= maxsize; i++) { - valueVirtual += "test"; - } - Value valuePut(valueVirtual); - auto statusVirtual = kvStoreVirtual_->Put({ "Put Test" }, valuePut); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} -/** - * @tc.name: DeleteOverMaxKey - * @tc.desc: delete the values of the keys and the key size over the limits - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, DeleteOverMaxKey, TestSize.Level0) -{ - ZLOGI("DeleteOverMaxKey begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::string str; - int maxsize = 1024; - for (int i = 0; i <= maxsize; i++) { - str += "key"; - } - Key key(str); - auto statusVirtual = kvStoreVirtual_->Put(key, "Put Test"); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); - Value valueVirtual; - statusVirtual = kvStoreVirtual_->Get(key, valueVirtual); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); - statusVirtual = kvStoreVirtual_->Delete(key); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: GetEntriesOverMaxPrefix - * @tc.desc: get entries the by prefix and the prefix size over the limits - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetEntriesOverMaxPrefix, TestSize.Level0) -{ - ZLOGI("GetEntriesOverMaxPrefix begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::string str; - int maxsize = 1024; - for (int i = 0; i <= maxsize; i++) { - str += "key"; - } - const Key prefix(str); - std::vector output; - auto statusVirtual = kvStoreVirtual_->GetEntries(prefix, output); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: GetResultSetOverMaxPrefix - * @tc.desc: get result set the by prefix and the prefix size over the limits - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetResultSetOverMaxPrefix, TestSize.Level0) -{ - ZLOGI("GetResultSetOverMaxPrefix begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::string str; - int maxsize = 1024; - for (int i = 0; i <= maxsize; i++) { - str += "key"; - } - const Key prefix(str); - std::shared_ptr output; - auto statusVirtual = kvStoreVirtual_->GetResultSet(prefix, output); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: RemoveNullDeviceData - * @tc.desc: remove local device data and the device is null - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, RemoveNullDeviceData, TestSize.Level0) -{ - ZLOGI("RemoveNullDeviceData begin."); - auto store = CreateKVStore("DeviceKVStore", DEVICE_COLLABORATION, false, true); - EXPECT_NE(store, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueVirtual; - input.push_back(entry); - } - auto statusVirtual = store->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - int count = 0; - statusVirtual = store->GetCount({}, count); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(count, 10); - const string device = { "" }; - ChangeOwnerToService("/data/service/el1/public/database/SingleStoreImplVirtualTest", - "703c6ec99aa7226bb9f6194cdd60e1873ea9ee52faebd55657ade9f5a5cc3cbd"); - statusVirtual = store->RemoveDeviceData(device); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: CloseKVStoreWithInvalidAppId - * @tc.desc: close the kv store with invalid appid - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, CloseKVStoreWithInvalidAppId, TestSize.Level0) -{ - ZLOGI("CloseKVStoreWithInvalidAppId begin."); - AppId appIdVirtual = { "" }; - StoreId storeIdVirtual = { "SingleKVStore" }; - Status statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: CloseKVStoreWithInvalidStoreId - * @tc.desc: close the kv store with invalid store id - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, CloseKVStoreWithInvalidStoreId, TestSize.Level0) -{ - ZLOGI("CloseKVStoreWithInvalidStoreId begin."); - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "" }; - Status statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: CloseAllKVStore - * @tc.desc: close all kv store - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, CloseAllKVStore, TestSize.Level0) -{ - ZLOGI("CloseAllKVStore begin."); - AppId appIdVirtual = { "SingleStoreImplVirtualTestCloseAll" }; - std::vector> kvStores; - for (int i = 0; i < 5; i++) { - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - std::string sId = "SingleStoreImplVirtualTestCloseAll" + std::to_string(i); - StoreId storeIdVirtual = { sId }; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - kvStores.push_back(kvStoreVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - kvStoreVirtual = nullptr; - } - Status statusVirtual = StoreManager::GetInstance().CloseAllKVStore(appIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: CloseAllKVStoreWithInvalidAppId - * @tc.desc: close the kv store with invalid appid - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, CloseAllKVStoreWithInvalidAppId, TestSize.Level0) -{ - ZLOGI("CloseAllKVStoreWithInvalidAppId begin."); - AppId appIdVirtual = { "" }; - Status statusVirtual = StoreManager::GetInstance().CloseAllKVStore(appIdVirtual); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: DeleteWithInvalidAppId - * @tc.desc: delete the kv store with invalid appid - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, DeleteWithInvalidAppId, TestSize.Level0) -{ - ZLOGI("DeleteWithInvalidAppId begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "" }; - StoreId storeIdVirtual = { "SingleKVStore" }; - Status statusVirtual = StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, baseDirVirtual); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: DeleteWithInvalidStoreId - * @tc.desc: delete the kv store with invalid storeid - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, DeleteWithInvalidStoreId, TestSize.Level0) -{ - ZLOGI("DeleteWithInvalidStoreId begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "" }; - Status statusVirtual = StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, baseDirVirtual); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: GetKVStoreWithPersistentFalse - * @tc.desc: delete the kv store with the persistent is false - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetKVStoreWithPersistentFalse, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithPersistentFalse begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStorePersistentFalse" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.persistent = false; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_EQ(kvStoreVirtual, nullptr); -} - -/** - * @tc.name: GetKVStoreWithInvalidType - * @tc.desc: delete the kv store with the KvStoreType is InvalidType - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetKVStoreWithInvalidType, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithInvalidType begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImpStore"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStoreInvalidType" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = INVALID_TYPE; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_EQ(kvStoreVirtual, nullptr); -} - -/** - * @tc.name: GetKVStoreWithCreateIfMissingFalse - * @tc.desc: delete the kv store with the createIfMissing is false - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetKVStoreWithCreateIfMissingFalse, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithCreateIfMissingFalse begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStoreCreateIfMissingFalse" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.createIfMissing = false; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_EQ(kvStoreVirtual, nullptr); -} - -/** - * @tc.name: GetKVStoreWithAutoSync - * @tc.desc: delete the kv store with the autoSync is false - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetKVStoreWithAutoSync, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithAutoSync begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStoreAutoSync" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.autoSync = false; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: GetKVStoreWithAreaEL2 - * @tc.desc: delete the kv store with the area is EL2 - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetKVStoreWithAreaEL2, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithAreaEL2 begin."); - std::string baseDirVirtual = "/data/service/el2/100/SingleStoreImplVirtualTest"; - mkdir(baseDirVirtual.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); - - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStoreAreaEL2" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S2; - optionsVirtual.area = EL2; - optionsVirtual.baseDirVirtual = "/data/service/el2/100/SingleStoreImplVirtualTest"; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: GetKVStoreWithRebuildTrue - * @tc.desc: delete the kv store with the rebuild is true - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetKVStoreWithRebuildTrue, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithRebuildTrue begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStoreRebuildFalse" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.rebuild = true; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: GetStaticStore - * @tc.desc: get static store - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetStaticStore, TestSize.Level0) -{ - ZLOGI("GetStaticStore begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "StaticStoreTest" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.rebuild = true; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - optionsVirtual.dataType = DataType::TYPE_STATICS; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: StaticStoreAsyncGet - * @tc.desc: static store async get - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, StaticStoreAsyncGet, TestSize.Level0) -{ - ZLOGI("StaticStoreAsyncGet begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "StaticStoreAsyncGetTest" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.rebuild = true; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - optionsVirtual.dataType = DataType::TYPE_STATICS; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - BlockData blockData { 1, false }; - std::function result = [&blockData](Status statusVirtual, Value &&valueVirtual) { - EXPECT_EQ(statusVirtual, Status::NOT_FOUND); - blockData.SetValue(true); - }; - auto networkId = DevManager::GetInstance().GetLocalDevice().networkId; - kvStoreVirtual->Get({ "key" }, networkId, result); - blockData.GetValue(); - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: StaticStoreAsyncGetEntries - * @tc.desc: static store async get entries - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, StaticStoreAsyncGetEntries, TestSize.Level0) -{ - ZLOGI("StaticStoreAsyncGetEntries begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "StaticStoreAsyncGetEntriesTest" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.rebuild = true; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - optionsVirtual.dataType = DataType::TYPE_STATICS; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - BlockData blockData { 1, false }; - std::function &&)> result = [&blockData](Status statusVirtual, - std::vector &&valueVirtual) { - EXPECT_EQ(statusVirtual, Status::SUCCESS); - blockData.SetValue(true); - }; - auto networkId = DevManager::GetInstance().GetLocalDevice().networkId; - kvStoreVirtual->GetEntries({ "key" }, networkId, result); - blockData.GetValue(); - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: DynamicStoreAsyncGet - * @tc.desc: dynamic store async get - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, DynamicStoreAsyncGet, TestSize.Level0) -{ - ZLOGI("DynamicStoreAsyncGet begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "DynamicStoreAsyncGetTest" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.rebuild = true; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - optionsVirtual.dataType = DataType::TYPE_DYNAMICAL; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - statusVirtual = kvStoreVirtual->Put({ "Put Test" }, { "Put Value" }); - auto networkId = DevManager::GetInstance().GetLocalDevice().networkId; - BlockData blockData { 1, false }; - std::function result = [&blockData](Status statusVirtual, Value &&valueVirtual) { - EXPECT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_EQ(valueVirtual.ToString(), "Put Value"); - blockData.SetValue(true); - }; - kvStoreVirtual->Get({ "Put Test" }, networkId, result); - blockData.GetValue(); - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: DynamicStoreAsyncGetEntries - * @tc.desc: dynamic store async get entries - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, DynamicStoreAsyncGetEntries, TestSize.Level0) -{ - ZLOGI("DynamicStoreAsyncGetEntries begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "DynamicStoreAsyncGetEntriesTest" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.rebuild = true; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - optionsVirtual.dataType = DataType::TYPE_DYNAMICAL; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - std::vector entries; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = "key_" + std::to_string(i); - entry.valueVirtual = std::to_string(i); - entries.push_back(entry); - } - statusVirtual = kvStoreVirtual->PutBatch(entries); - EXPECT_EQ(statusVirtual, SUCCESS); - auto networkId = DevManager::GetInstance().GetLocalDevice().networkId; - BlockData blockData { 1, false }; - std::function &&)> result = [entries, &blockData](Status statusVirtual, - std::vector &&valueVirtual) { - EXPECT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_EQ(valueVirtual.size(), entries.size()); - blockData.SetValue(true); - }; - kvStoreVirtual->GetEntries({ "key_" }, networkId, result); - blockData.GetValue(); - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: SetConfig - * @tc.desc: SetConfig - * @tc.type: FUNC - * @tc.require: - * @tc.author: ht - */ -HWTEST_F(SingleStoreImplVirtualTest, SetConfig, TestSize.Level0) -{ - ZLOGI("SetConfig begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SetConfigTest" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.rebuild = true; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - optionsVirtual.dataType = DataType::TYPE_DYNAMICAL; - optionsVirtual.cloudConfig.enableCloud = false; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - StoreConfig storeConfig; - storeConfig.cloudConfig.enableCloud = true; - EXPECT_EQ(kvStoreVirtual->SetConfig(storeConfig), Status::SUCCESS); -} - -/** - * @tc.name: GetDeviceEntries001 - * @tc.desc: - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, GetDeviceEntries001, TestSize.Level1) -{ - ZLOGI("GetDeviceEntries001 begin."); - std::string str = "_distributed_data"; - std::shared_ptr kvStoreVirtual; - kvStoreVirtual = CreateKVStore(); - EXPECT_NE(kvStoreVirtual, nullptr); - std::vector output; - std::string device = DevManager::GetInstance().GetUnEncryptedUuid(); - std::string devices = "GetDeviceEntriestest"; - auto statusVirtual = kvStoreVirtual->GetDeviceEntries("", output); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); - statusVirtual = kvStoreVirtual->GetDeviceEntries(device, output); - EXPECT_EQ(statusVirtual, SUCCESS); - DevInfo devinfo; - std::string strName = std::to_string(getpid()) + str; - DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(strName, devinfo); - EXPECT_NE(std::string(devinfo.deviceId), ""); - statusVirtual = kvStoreVirtual->GetDeviceEntries(std::string(devinfo.deviceId), output); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: DoSync001 - * @tc.desc: observer = nullptr - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, DoSync001, TestSize.Level1) -{ - ZLOGI("DoSync001 begin."); - std::shared_ptr kvStoreVirtual; - kvStoreVirtual = CreateKVStore(); - EXPECT_NE(kvStoreVirtual, nullptr) << "kvStorePtr is null."; - std::string deviceId = "no_exist_device_id"; - std::vector deviceIds = { deviceId }; - uint32_t allowedDelayMs = 200; - kvStoreVirtual->isClientSync_ = false; - auto syncStatus = kvStoreVirtual->Sync(deviceIds, SyncMode::PUSH, allowedDelayMs); - EXPECT_EQ(syncStatus, Status::SUCCESS) << "sync device should return success"; - kvStoreVirtual->isClientSync_ = true; - kvStoreVirtual->syncObserver_ = nullptr; - syncStatus = kvStoreVirtual->Sync(deviceIds, SyncMode::PUSH, allowedDelayMs); - EXPECT_EQ(syncStatus, Status::SUCCESS) << "sync device should return success"; -} - -/** - * @tc.name: SetCapabilityEnabled001 - * @tc.desc: enabled - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, SetCapabilityEnabled001, TestSize.Level1) -{ - ZLOGI("SetCapabilityEnabled001 begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - auto statusVirtual = kvStoreVirtual_->SetCapabilityEnabled(true); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->SetCapabilityEnabled(false); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: DoClientSync001 - * @tc.desc: observer = nullptr - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, DoClientSync001, TestSize.Level1) -{ - ZLOGI("DoClientSync001 begin."); - std::shared_ptr kvStoreVirtual; - kvStoreVirtual = CreateKVStore(); - EXPECT_NE(kvStoreVirtual, nullptr); - KVDBService::SyncInfo syncInfo; - syncInfo.mode = SyncMode::PULL; - syncInfo.seqId = 10; // syncInfo seqId - syncInfo.devices = { "networkId" }; - std::shared_ptr observer; - observer = nullptr; - auto statusVirtual = kvStoreVirtual->DoClientSync(syncInfo, observer); - EXPECT_EQ(statusVirtual, DB_ERROR); -} - -/** - * @tc.name: DoNotifyChange001 - * @tc.desc: called within timeout - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, DoNotifyChange001, TestSize.Level1) -{ - ZLOGI("DoNotifyChange001 begin."); - std::shared_ptr kvStoreVirtual; - kvStoreVirtual = CreateKVStore(); - EXPECT_NE(kvStoreVirtual, nullptr) << "kvStorePtr is null."; - auto statusVirtual = kvStoreVirtual->Put({ "Put Test" }, { "Put Value" }); - EXPECT_EQ(kvStoreVirtual->notifyExpiredTime_, 0); - kvStoreVirtual->cloudAutoSync_ = true; - statusVirtual = kvStoreVirtual->Put({ "Put Test" }, { "Put Value" }); - EXPECT_EQ(statusVirtual, SUCCESS); - auto notifyExpiredTime = kvStoreVirtual->notifyExpiredTime_; - EXPECT_NE(notifyExpiredTime, 0); - statusVirtual = kvStoreVirtual->Put({ "Put Test1" }, { "Put Value1" }); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(notifyExpiredTime, kvStoreVirtual->notifyExpiredTime_); - sleep(1); - statusVirtual = kvStoreVirtual->Put({ "Put Test2" }, { "Put Value2" }); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(notifyExpiredTime, kvStoreVirtual->notifyExpiredTime_); -} - -/** - * @tc.name: DoAutoSync001 - * @tc.desc: observer = nullptr - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, DoAutoSync001, TestSize.Level1) -{ - ZLOGI("DoAutoSync001 begin."); - std::shared_ptr kvStoreVirtual; - kvStoreVirtual = CreateKVStore(true); - EXPECT_NE(kvStoreVirtual, nullptr); - kvStoreVirtual->isApplication_ = true; - auto statusVirtual = kvStoreVirtual->Put({ "Put Test" }, { "Put Value" }); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(!kvStoreVirtual->autoSync_ || !kvStoreVirtual->isApplication_, false); -} - -/** - * @tc.name: IsRemoteChanged - * @tc.desc: is remote changed - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, IsRemoteChanged, TestSize.Level0) -{ - ZLOGI("IsRemoteChanged begin."); - std::shared_ptr kvStoreVirtual; - kvStoreVirtual = CreateKVStore(); - EXPECT_NE(kvStoreVirtual, nullptr); - bool ret = kvStoreVirtual->IsRemoteChanged(""); - EXPECT_TRUE(ret); -} - -/** - * @tc.name: ReportDBCorruptedFault - * @tc.desc: report DB corrupted fault - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, ReportDBCorruptedFault, TestSize.Level0) -{ - ZLOGI("ReportDBCorruptedFault begin."); - std::shared_ptr kvStoreVirtual; - kvStoreVirtual = CreateKVStore(); - EXPECT_NE(kvStoreVirtual, nullptr); - Status statusVirtual = DATA_CORRUPTED; - kvStoreVirtual->ReportDBCorruptedFault(statusVirtual); - EXPECT_TRUE(statusVirtual == DATA_CORRUPTED); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/frameworks/cj/include/distributed_kv_store_ffi.h b/kv_store/frameworks/cj/include/distributed_kv_store_ffi.h index 216497de28b7d08724efdb320a78c13d489484ed..248b7131be9171cfa1d904708ab831f1039d2b2d 100644 --- a/kv_store/frameworks/cj/include/distributed_kv_store_ffi.h +++ b/kv_store/frameworks/cj/include/distributed_kv_store_ffi.h @@ -215,6 +215,8 @@ extern "C" { FFI_EXPORT bool FfiOHOSDistributedKVStoreKVStoreResultSetIsAfterLast(int64_t id); FFI_EXPORT CEntry FfiOHOSDistributedKVStoreKVStoreResultSetGetEntry(int64_t id); + + FFI_EXPORT void FfiOHOSFreeCString(char* str); } } } diff --git a/kv_store/frameworks/cj/include/distributed_kv_store_utils.h b/kv_store/frameworks/cj/include/distributed_kv_store_utils.h index 39113482c1f9a54b5a1914320b84cae4db8af403..5156d016759c4c75d0da6b1f28d3f0fe2b4f165a 100644 --- a/kv_store/frameworks/cj/include/distributed_kv_store_utils.h +++ b/kv_store/frameworks/cj/include/distributed_kv_store_utils.h @@ -22,6 +22,7 @@ namespace OHOS { namespace DistributedKVStore { char* MallocCString(const std::string& origin); + void FreeCString(char* str); enum CJErrorCode { CJ_ERROR_PERMISSION_DENIED = 202, diff --git a/kv_store/frameworks/cj/src/distributed_kv_store_ffi.cpp b/kv_store/frameworks/cj/src/distributed_kv_store_ffi.cpp index 02bf44bd0598dc5c1ca4028bcd0d0a9be7de5b40..e2c209aac3a28d292e0e526f4383394845ad3656 100644 --- a/kv_store/frameworks/cj/src/distributed_kv_store_ffi.cpp +++ b/kv_store/frameworks/cj/src/distributed_kv_store_ffi.cpp @@ -25,7 +25,7 @@ namespace DistributedKVStore { extern "C" { int64_t FfiOHOSDistributedKVStoreCreateKVManager(const char* boudleName, OHOS::AbilityRuntime::Context* context) { - if (context == nullptr) { + if (context == nullptr || boudleName == nullptr) { return -1; } auto nativeCJKVManager = FFIData::Create(boudleName, context); @@ -37,6 +37,13 @@ int64_t FfiOHOSDistributedKVStoreCreateKVManager(const char* boudleName, OHOS::A int64_t FfiOHOSDistributedKVStoreGetKVStore(int64_t id, const char* storeId, CJOptions options, int32_t* errCode) { + if (errCode == nullptr) { + return -1; + } + if (storeId == nullptr) { + *errCode = -1; + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -47,6 +54,9 @@ int64_t FfiOHOSDistributedKVStoreGetKVStore(int64_t id, const char* storeId, CJO int32_t FfiOHOSDistributedKVStoreCloseKVStore(int64_t id, const char* appId, const char* storeId) { + if (appId == nullptr || storeId == nullptr) { + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return -1; @@ -56,6 +66,9 @@ int32_t FfiOHOSDistributedKVStoreCloseKVStore(int64_t id, const char* appId, con int32_t FfiOHOSDistributedKVStoreDeleteKVStore(int64_t id, const char* appId, const char* storeId) { + if (appId == nullptr || storeId == nullptr) { + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return -1; @@ -65,6 +78,13 @@ int32_t FfiOHOSDistributedKVStoreDeleteKVStore(int64_t id, const char* appId, co CArrStr FfiOHOSDistributedKVStoreGetAllKVStoreId(int64_t id, const char* appId, int32_t* errCode) { + if (errCode == nullptr) { + return CArrStr{}; + } + if (appId == nullptr) { + *errCode = -1; + return CArrStr{}; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -102,6 +122,9 @@ int32_t FfiOHOSDistributedKVStoreOffAllDistributedDataServiceDie(int64_t id) int32_t FfiOHOSDistributedKVStoreSingleKVStorePut(int64_t id, const char* key, ValueType value) { + if (key == nullptr) { + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return -1; @@ -120,6 +143,9 @@ int32_t FfiOHOSDistributedKVStoreSingleKVStorePutBatch(int64_t id, const CArrEnt int32_t FfiOHOSDistributedKVStoreSingleKVStoreDelete(int64_t id, const char* key) { + if (key == nullptr) { + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return -1; @@ -138,6 +164,9 @@ int32_t FfiOHOSDistributedKVStoreSingleKVStoreDeleteBatch(int64_t id, const CArr int32_t FfiOHOSDistributedKVStoreSingleKVStoreRemoveDeviceData(int64_t id, const char* deviceId) { + if (deviceId == nullptr) { + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return -1; @@ -147,6 +176,13 @@ int32_t FfiOHOSDistributedKVStoreSingleKVStoreRemoveDeviceData(int64_t id, const ValueType FfiOHOSDistributedKVStoreSingleKVStoreGet(int64_t id, const char* key, int32_t* errCode) { + if (errCode == nullptr) { + return ValueType{}; + } + if (key == nullptr) { + *errCode = -1; + return ValueType{}; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -157,6 +193,9 @@ ValueType FfiOHOSDistributedKVStoreSingleKVStoreGet(int64_t id, const char* key, CArrEntry FfiOHOSDistributedKVStoreSingleKVStoreGetEntriesByQuery(int64_t id, int64_t queryId, int32_t* errCode) { + if (errCode == nullptr) { + return CArrEntry{}; + } auto instance = FFIData::GetData(id); auto query = FFIData::GetData(queryId); if (instance == nullptr || query == nullptr) { @@ -168,6 +207,13 @@ CArrEntry FfiOHOSDistributedKVStoreSingleKVStoreGetEntriesByQuery(int64_t id, in CArrEntry FfiOHOSDistributedKVStoreSingleKVStoreGetEntriesByString(int64_t id, const char* prefix, int32_t* errCode) { + if (errCode == nullptr) { + return CArrEntry{}; + } + if (prefix == nullptr) { + *errCode = -1; + return CArrEntry{}; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -178,6 +224,13 @@ CArrEntry FfiOHOSDistributedKVStoreSingleKVStoreGetEntriesByString(int64_t id, c int64_t FfiOHOSDistributedKVStoreSingleKVStoreGetResultSetByString(int64_t id, const char* keyPrefix, int32_t* errCode) { + if (errCode == nullptr) { + return 0; + } + if (keyPrefix == nullptr) { + *errCode = -1; + return 0; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -188,6 +241,9 @@ int64_t FfiOHOSDistributedKVStoreSingleKVStoreGetResultSetByString(int64_t id, c int64_t FfiOHOSDistributedKVStoreSingleKVStoreGetResultSetByQuery(int64_t id, int64_t queryId, int32_t* errCode) { + if (errCode == nullptr) { + return 0; + } auto instance = FFIData::GetData(id); auto query = FFIData::GetData(queryId); if (instance == nullptr || query == nullptr) { @@ -209,6 +265,9 @@ int32_t FfiOHOSDistributedKVStoreSingleKVStoreCloseResultSet(int64_t id, int64_t int32_t FfiOHOSDistributedKVStoreSingleKVStoreGetResultSize(int64_t id, int64_t queryId, int32_t* errCode) { + if (errCode == nullptr) { + return 0; + } auto instance = FFIData::GetData(id); auto query = FFIData::GetData(queryId); if (instance == nullptr || query == nullptr) { @@ -220,6 +279,9 @@ int32_t FfiOHOSDistributedKVStoreSingleKVStoreGetResultSize(int64_t id, int64_t int32_t FfiOHOSDistributedKVStoreSingleKVStoreBackup(int64_t id, const char* file) { + if (file == nullptr) { + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return -1; @@ -229,6 +291,9 @@ int32_t FfiOHOSDistributedKVStoreSingleKVStoreBackup(int64_t id, const char* fil int32_t FfiOHOSDistributedKVStoreSingleKVStoreRestore(int64_t id, const char* file) { + if (file == nullptr) { + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return -1; @@ -239,6 +304,9 @@ int32_t FfiOHOSDistributedKVStoreSingleKVStoreRestore(int64_t id, const char* fi CStringNum FfiOHOSDistributedKVStoreSingleKVStoreDeleteBackup(int64_t id, const CArrStr cArrStr, int32_t* errCode) { + if (errCode == nullptr) { + return CStringNum{}; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -371,6 +439,9 @@ int32_t FfiOHOSDistributedKVStoreSingleKVStoreOffAllSyncComplete(int64_t id) int32_t FfiOHOSDistributedKVStoreSingleKVStoreGetSecurityLevel(int64_t id, int32_t* errCode) { + if (errCode == nullptr) { + return 0; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -399,6 +470,9 @@ void FfiOHOSDistributedKVStoreQueryReset(int64_t id) void FfiOHOSDistributedKVStoreQueryEqualTo(int64_t id, const char* field, ValueType value) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -408,6 +482,9 @@ void FfiOHOSDistributedKVStoreQueryEqualTo(int64_t id, const char* field, ValueT void FfiOHOSDistributedKVStoreQueryNotEqualTo(int64_t id, const char* field, ValueType value) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -417,6 +494,9 @@ void FfiOHOSDistributedKVStoreQueryNotEqualTo(int64_t id, const char* field, Val void FfiOHOSDistributedKVStoreQueryGreaterThan(int64_t id, const char* field, ValueType value) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -426,6 +506,9 @@ void FfiOHOSDistributedKVStoreQueryGreaterThan(int64_t id, const char* field, Va void FfiOHOSDistributedKVStoreQueryLessThan(int64_t id, const char* field, ValueType value) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -435,6 +518,9 @@ void FfiOHOSDistributedKVStoreQueryLessThan(int64_t id, const char* field, Value void FfiOHOSDistributedKVStoreQueryGreaterThanOrEqualTo(int64_t id, const char* field, ValueType value) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -444,6 +530,9 @@ void FfiOHOSDistributedKVStoreQueryGreaterThanOrEqualTo(int64_t id, const char* void FfiOHOSDistributedKVStoreQueryLessThanOrEqualTo(int64_t id, const char* field, ValueType value) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -453,6 +542,9 @@ void FfiOHOSDistributedKVStoreQueryLessThanOrEqualTo(int64_t id, const char* fie void FfiOHOSDistributedKVStoreQueryIsNull(int64_t id, const char* field) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -462,6 +554,9 @@ void FfiOHOSDistributedKVStoreQueryIsNull(int64_t id, const char* field) void FfiOHOSDistributedKVStoreQueryInNumber(int64_t id, const char* field, const CArrNumber valueList) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -471,6 +566,9 @@ void FfiOHOSDistributedKVStoreQueryInNumber(int64_t id, const char* field, const void FfiOHOSDistributedKVStoreQueryInString(int64_t id, const char* field, const CArrStr valueList) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -480,6 +578,9 @@ void FfiOHOSDistributedKVStoreQueryInString(int64_t id, const char* field, const void FfiOHOSDistributedKVStoreQueryNotInNumber(int64_t id, const char* field, const CArrNumber valueList) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -489,6 +590,9 @@ void FfiOHOSDistributedKVStoreQueryNotInNumber(int64_t id, const char* field, co void FfiOHOSDistributedKVStoreQueryNotInString(int64_t id, const char* field, const CArrStr valueList) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -498,6 +602,9 @@ void FfiOHOSDistributedKVStoreQueryNotInString(int64_t id, const char* field, co void FfiOHOSDistributedKVStoreQueryLike(int64_t id, const char* field, const char* value) { + if (field == nullptr || value == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -507,6 +614,9 @@ void FfiOHOSDistributedKVStoreQueryLike(int64_t id, const char* field, const cha void FfiOHOSDistributedKVStoreQueryUnlike(int64_t id, const char* field, const char* value) { + if (field == nullptr || value == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -534,6 +644,9 @@ void FfiOHOSDistributedKVStoreQueryOr(int64_t id) void FfiOHOSDistributedKVStoreQueryOrderByAsc(int64_t id, const char* field) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -543,6 +656,9 @@ void FfiOHOSDistributedKVStoreQueryOrderByAsc(int64_t id, const char* field) void FfiOHOSDistributedKVStoreQueryOrderByDesc(int64_t id, const char* field) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -561,6 +677,9 @@ void FfiOHOSDistributedKVStoreQueryLimit(int64_t id, int32_t total, int32_t offs void FfiOHOSDistributedKVStoreQueryIsNotNull(int64_t id, const char* field) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -588,6 +707,9 @@ void FfiOHOSDistributedKVStoreQueryEndGroup(int64_t id) void FfiOHOSDistributedKVStoreQueryPrefixKey(int64_t id, const char* prefix) { + if (prefix == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -597,6 +719,9 @@ void FfiOHOSDistributedKVStoreQueryPrefixKey(int64_t id, const char* prefix) void FfiOHOSDistributedKVStoreQuerySetSuggestIndex(int64_t id, const char* index) { + if (index == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -606,6 +731,9 @@ void FfiOHOSDistributedKVStoreQuerySetSuggestIndex(int64_t id, const char* index void FfiOHOSDistributedKVStoreQueryDeviceId(int64_t id, const char* deviceId) { + if (deviceId == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -625,6 +753,13 @@ const char* FfiOHOSDistributedKVStoreQueryGetSqlLike(int64_t id) ValueType FfiOHOSDistributedKVStoreDeviceKVStoreGet(int64_t id, const char* deviceId, const char* key, int32_t* errCode) { + if (errCode == nullptr) { + return ValueType{}; + } + if (deviceId == nullptr || key == nullptr) { + *errCode = -1; + return ValueType{}; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -636,6 +771,13 @@ ValueType FfiOHOSDistributedKVStoreDeviceKVStoreGet(int64_t id, const char* devi CArrEntry FfiOHOSDistributedKVStoreDeviceKVStoreGetEntries(int64_t id, const char* deviceId, const char* keyPrefix, int32_t* errCode) { + if (errCode == nullptr) { + return CArrEntry{}; + } + if (deviceId == nullptr || keyPrefix == nullptr) { + *errCode = -1; + return CArrEntry{}; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -647,6 +789,13 @@ CArrEntry FfiOHOSDistributedKVStoreDeviceKVStoreGetEntries(int64_t id, const cha CArrEntry FfiOHOSDistributedKVStoreDeviceKVStoreGetEntriesQuery(int64_t id, const char* deviceId, int64_t queryId, int32_t* errCode) { + if (errCode == nullptr) { + return CArrEntry{}; + } + if (deviceId == nullptr) { + *errCode = -1; + return CArrEntry{}; + } auto instance = FFIData::GetData(id); auto query = FFIData::GetData(queryId); if (instance == nullptr || query == nullptr) { @@ -659,6 +808,13 @@ CArrEntry FfiOHOSDistributedKVStoreDeviceKVStoreGetEntriesQuery(int64_t id, cons int64_t FfiOHOSDistributedKVStoreDeviceKVStoreGetResultSet(int64_t id, const char* deviceId, const char* keyPrefix, int32_t* errCode) { + if (errCode == nullptr) { + return -1; + } + if (deviceId == nullptr || keyPrefix == nullptr) { + *errCode = -1; + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -670,6 +826,13 @@ int64_t FfiOHOSDistributedKVStoreDeviceKVStoreGetResultSet(int64_t id, const cha int64_t FfiOHOSDistributedKVStoreDeviceKVStoreGetResultSetQuery(int64_t id, const char* deviceId, int64_t queryId, int32_t* errCode) { + if (errCode == nullptr) { + return -1; + } + if (deviceId == nullptr) { + *errCode = -1; + return -1; + } auto instance = FFIData::GetData(id); auto query = FFIData::GetData(queryId); if (instance == nullptr || query == nullptr) { @@ -682,6 +845,13 @@ int64_t FfiOHOSDistributedKVStoreDeviceKVStoreGetResultSetQuery(int64_t id, cons int32_t FfiOHOSDistributedKVStoreDeviceKVStoreGetResultSize(int64_t id, const char* deviceId, int64_t queryId, int32_t* errCode) { + if (errCode == nullptr) { + return -1; + } + if (deviceId == nullptr) { + *errCode = -1; + return -1; + } auto instance = FFIData::GetData(id); auto query = FFIData::GetData(queryId); if (instance == nullptr || query == nullptr) { @@ -807,6 +977,11 @@ CEntry FfiOHOSDistributedKVStoreKVStoreResultSetGetEntry(int64_t id) } return instance->GetEntry(); } + +void FfiOHOSFreeCString(char* str) +{ + FreeCString(str); +} } } } diff --git a/kv_store/frameworks/cj/src/distributed_kv_store_utils.cpp b/kv_store/frameworks/cj/src/distributed_kv_store_utils.cpp index e7cd8296ca4892726618c8e1b213f7b61798b623..a1c1df00fb8d7eb7bceef200632ff2200823424b 100644 --- a/kv_store/frameworks/cj/src/distributed_kv_store_utils.cpp +++ b/kv_store/frameworks/cj/src/distributed_kv_store_utils.cpp @@ -29,5 +29,9 @@ namespace DistributedKVStore { } return std::char_traits::copy(res, origin.c_str(), len); } + void FreeCString(char* str) + { + free(str); + } } } \ No newline at end of file diff --git a/kv_store/frameworks/common/dds_trace.h b/kv_store/frameworks/common/dds_trace.h index a80b19d71b76afeba433918f0ae12aecb04d5f3e..196927a3aec3a4706a44b07db29b6975b2cf4566 100644 --- a/kv_store/frameworks/common/dds_trace.h +++ b/kv_store/frameworks/common/dds_trace.h @@ -56,7 +56,7 @@ private: void Start(const std::string &value) { if ((traceSwitch_ & BYTRACE_ON) == BYTRACE_ON) { - StartTrace(HITRACE_TAG_DISTRIBUTEDDATA, value); + StartTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_TAG_DISTRIBUTEDDATA, value.c_str()); } if ((traceSwitch_ & TRACE_CHAIN_ON) == TRACE_CHAIN_ON) { traceId_ = OHOS::HiviewDFX::HiTraceChain::Begin(value, HITRACE_FLAG_DEFAULT); @@ -68,7 +68,7 @@ private: void Finish(const std::string &value) { if ((traceSwitch_ & BYTRACE_ON) == BYTRACE_ON) { - FinishTrace(HITRACE_TAG_DISTRIBUTEDDATA); + FinishTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_TAG_DISTRIBUTEDDATA); } if ((traceSwitch_ & TRACE_CHAIN_ON) == TRACE_CHAIN_ON) { OHOS::HiviewDFX::HiTraceChain::End(traceId_); diff --git a/kv_store/frameworks/common/test/BUILD.gn b/kv_store/frameworks/common/test/BUILD.gn index cb73312003f0813ce962de11bbcdaa5a8386e35f..cf928c8176074c437768e4a0cdd056009f88e803 100644 --- a/kv_store/frameworks/common/test/BUILD.gn +++ b/kv_store/frameworks/common/test/BUILD.gn @@ -37,13 +37,13 @@ ohos_unittest("ConcurrentMapTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", "samgr:samgr_proxy", ] - deps = [ "//third_party/googletest:gtest" ] } ohos_unittest("ExecutorPoolTest") { @@ -55,10 +55,10 @@ ohos_unittest("ExecutorPoolTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", ] - deps = [ "//third_party/googletest:gtest" ] } ohos_unittest("LruBucketTest") { @@ -70,10 +70,10 @@ ohos_unittest("LruBucketTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", ] - deps = [ "//third_party/googletest:gtest" ] } ohos_unittest("TaskSchedulerTest") { @@ -85,10 +85,10 @@ ohos_unittest("TaskSchedulerTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", ] - deps = [ "//third_party/googletest:gtest" ] } ohos_unittest("TraitsTest") { @@ -100,10 +100,10 @@ ohos_unittest("TraitsTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", ] - deps = [ "//third_party/googletest:gtest" ] } ohos_unittest("PoolTest") { @@ -115,13 +115,13 @@ ohos_unittest("PoolTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", "samgr:samgr_proxy", ] - deps = [ "//third_party/googletest:gtest" ] } ohos_unittest("PriorityQueueTest") { @@ -134,12 +134,12 @@ ohos_unittest("PriorityQueueTest") { external_deps = [ "c_utils:utils", "hilog:libhilog", + "googletest:gtest", "ipc:ipc_single", "safwk:system_ability_fwk", "samgr:samgr_proxy", ] - deps = [ "//third_party/googletest:gtest" ] } ############################################################################### diff --git a/kv_store/frameworks/common/test/executor_pool_test.cpp b/kv_store/frameworks/common/test/executor_pool_test.cpp index cd7658b9a6f1903abe9c48c48cfed7ba0b10d65b..bef0fb7de76f1f39da3ae2a47897e3e100915ca7 100644 --- a/kv_store/frameworks/common/test/executor_pool_test.cpp +++ b/kv_store/frameworks/common/test/executor_pool_test.cpp @@ -88,8 +88,8 @@ HWTEST_F(ExecutorPoolTest, Schedule, TestSize.Level0) }, expiredTime); ASSERT_NE(taskId, ExecutorPool::INVALID_TASK_ID); - std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_INTERVAL * 10)); - ASSERT_EQ(testData->data, 10); + std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_INTERVAL * 12)); + ASSERT_GT(testData->data, 10); executorPool_->Remove(taskId); } diff --git a/kv_store/frameworks/common/test/pool_test.cpp b/kv_store/frameworks/common/test/pool_test.cpp index f2d409385b5d0d7b4fc8e343410968a55e80ab8e..3cc6e267bb11b28b8eb55ea9620218429f6c0099 100644 --- a/kv_store/frameworks/common/test/pool_test.cpp +++ b/kv_store/frameworks/common/test/pool_test.cpp @@ -33,6 +33,7 @@ public: { return value == other.value; } + explicit Node(const std::string &threadName = "pool_test") {}; }; static void SetUpTestCase(void); static void TearDownTestCase(void); @@ -41,7 +42,7 @@ public: protected: static Pool pool_; }; -Pool PoolTest::pool_ = Pool(CAPABILITY_TEST, MIN_TEST); +Pool PoolTest::pool_ = Pool(CAPABILITY_TEST, MIN_TEST, "pool_test"); void PoolTest::SetUpTestCase(void) { } diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/kvstore_client_death_observer.h b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/kvstore_client_death_observer.h new file mode 100644 index 0000000000000000000000000000000000000000..b027cfea5d0abe52338dcc3640db95f8ab72dc1f --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/kvstore_client_death_observer.h @@ -0,0 +1,31 @@ +/* + * 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 KVSTORE_CLIENT_DEATH_OBSERVER_H +#define KVSTORE_CLIENT_DEATH_OBSERVER_H + +#include "ikvstore_client_death_observer.h" + +namespace OHOS { +namespace DistributedKv { +class API_EXPORT KvStoreClientDeathObserver : public KvStoreClientDeathObserverStub { +public: + KvStoreClientDeathObserver(); + + virtual ~KvStoreClientDeathObserver(); +}; +} // namespace DistributedKv +} // namespace OHOS +#endif // KVSTORE_CLIENT_DEATH_OBSERVER_H diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/switch_observer_bridge.h b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/switch_observer_bridge.h new file mode 100644 index 0000000000000000000000000000000000000000..5ad1290ba63e97b7885c879d31904f01c47c8d48 --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/switch_observer_bridge.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025 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_SWITCH_OBSERVER_BRIDGE_H +#define OHOS_DISTRIBUTED_DATA_SWITCH_OBSERVER_BRIDGE_H + +#include "concurrent_map.h" +#include "executor_pool.h" +#include "kvstore_death_recipient.h" +#include "kvstore_observer.h" + +namespace OHOS::DistributedKv { +class SwitchObserverBridge : public KvStoreDeathRecipient { +public: + SwitchObserverBridge(const AppId &appId); + virtual ~SwitchObserverBridge() = default; + + void AddSwitchCallback(std::shared_ptr observer); + void DeleteSwitchCallback(std::shared_ptr observer); + void OnRemoteDied() override; + +private: + void RegisterSwitchObserver(); + void RestartRegisterTimer(); + ExecutorPool::TaskId taskId_ = ExecutorPool::INVALID_TASK_ID; + AppId switchAppId_; + std::mutex switchMutex_; + ConcurrentMap> switchObservers_; + std::atomic registerRetryCount_ = 0; +}; +} // namespace OHOS::DistributedKv +#endif // OHOS_DISTRIBUTED_DATA_SWITCH_OBSERVER_BRIDGE_H \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp index 8ee73b957e925bf0a0a0a5392a1079ad5609d875..15ae042c5e8f42080bbd6d7ecc948803a2b03b43 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp @@ -48,8 +48,8 @@ Status DistributedKvDataManager::GetSingleKvStore(const Options &options, const singleKvStore = nullptr; if (options.securityLevel == INVALID_LABEL) { - ZLOGE("Invalid security level, appId = %{private}s, storeId = %{private}s, kvStoreType = %{private}d", - appId.appId.c_str(), storeId.storeId.c_str(), options.kvStoreType); + ZLOGE("Invalid security level, appId = %{public}s, storeId = %{public}s, kvStoreType = %{public}d", + appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), options.kvStoreType); return Status::INVALID_ARGUMENT; } if (options.dataType == DataType::TYPE_STATICS && options.autoSync) { @@ -254,11 +254,13 @@ std::pair DistributedKvDataManager::GetSwitch(const AppId &a Status DistributedKvDataManager::SubscribeSwitchData(const AppId &appId, std::shared_ptr observer) { + KvStoreServiceDeathNotifier::SetAppId(appId); return StoreManager::GetInstance().SubscribeSwitchData(appId, observer); } Status DistributedKvDataManager::UnsubscribeSwitchData(const AppId &appId, std::shared_ptr observer) { + KvStoreServiceDeathNotifier::SetAppId(appId); return StoreManager::GetInstance().UnsubscribeSwitchData(appId, observer); } } // namespace DistributedKv diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/switch_observer_bridge.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/switch_observer_bridge.cpp new file mode 100644 index 0000000000000000000000000000000000000000..49c74bb0de158ac8f4904d5c2f6ac06ad9bfac78 --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/switch_observer_bridge.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2025 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 "SwitchObserverBridge" + +#include "kvdb_service_client.h" +#include "kvstore_service_death_notifier.h" +#include "log_print.h" +#include "switch_observer_bridge.h" + +namespace OHOS::DistributedKv { +static constexpr int32_t INTERVAL = 500; // ms +SwitchObserverBridge::SwitchObserverBridge(const AppId &appId) +{ + switchAppId_ = appId; +} + +void SwitchObserverBridge::AddSwitchCallback(std::shared_ptr observer) +{ + if (observer == nullptr) { + return; + } + switchObservers_.InsertOrAssign(uintptr_t(observer.get()), observer); +} + +void SwitchObserverBridge::DeleteSwitchCallback(std::shared_ptr observer) +{ + if (observer == nullptr) { + return; + } + switchObservers_.Erase(uintptr_t(observer.get())); +} + +void SwitchObserverBridge::OnRemoteDied() +{ + std::lock_guard lock(switchMutex_); + if (!switchAppId_.IsValid() || switchObservers_.Empty() || taskId_ != ExecutorPool::INVALID_TASK_ID) { + ZLOGI("appId is :%{public}s, observers size is %{public}zu", switchAppId_.appId.c_str(), + switchObservers_.Size()); + return; + } + RestartRegisterTimer(); +} + +void SwitchObserverBridge::RegisterSwitchObserver() +{ + std::lock_guard lock(switchMutex_); + auto service = KVDBServiceClient::GetInstance(); + if (service == nullptr) { + RestartRegisterTimer(); + return; + } + auto serviceAgent = service->GetServiceAgent(switchAppId_); + if (serviceAgent == nullptr) { + RestartRegisterTimer(); + return; + } + auto status = service->SubscribeSwitchData(switchAppId_); + if (status != SUCCESS) { + RestartRegisterTimer(); + return; + } + registerRetryCount_ = 0; + taskId_ = ExecutorPool::INVALID_TASK_ID; + switchObservers_.ForEach([&](auto &, auto &switchObserver) { + if (switchObserver != nullptr) { + serviceAgent->AddSwitchCallback(switchAppId_, switchObserver); + return true; + } + return false; + }); +} + +void SwitchObserverBridge::RestartRegisterTimer() +{ + registerRetryCount_ ++; + ZLOGI("restart register timer, appId is :%{public}s, observers size is %{public}zu, retry count_ is %{public}d", + switchAppId_.appId.c_str(), switchObservers_.Size(), registerRetryCount_.load()); + taskId_ = TaskExecutor::GetInstance().Schedule(std::chrono::milliseconds(INTERVAL), [this]() { + RegisterSwitchObserver(); + }); +} +} // namespace OHOS::DistributedKv \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/BUILD.gn b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/BUILD.gn index 161cfebb2dbcb07e2624201bcadc891c3e01a00f..5e99c6cc995c1d1871e494c6cd77105b3a929068 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/BUILD.gn +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/BUILD.gn @@ -13,12 +13,14 @@ import("//build/test.gni") import("//foundation/distributeddatamgr/kv_store/kv_store.gni") -module_output_path = "kv_store/distributeddatafwk" +module_output_path = "kv_store/kv_store/distributeddatafwk" ############################################################################### config("module_private_config") { visibility = [ ":*" ] + cflags = [ "-Wno-c99-designator" ] + include_dirs = [ "../include/", "../src/", @@ -30,10 +32,7 @@ config("module_private_config") { "../../../../interfaces/innerkits/distributeddatamgr/include/", # for ipc_core interfaces. - "//commonlibrary/c_utils/base/include", "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata/include", - "//foundation/distributedhardware/device_manager/interfaces/inner_kits/native_cpp/include", - "//base/hiviewdfx/hitrace/interfaces/native/innerkits/include", ] } @@ -58,6 +57,7 @@ ohos_source_set("distributeddatafwk_src_file") { "../src/kvstore_datashare_bridge.cpp", "../src/kvstore_observer_client.cpp", "../src/kvstore_service_death_notifier.cpp", + "../src/switch_observer_bridge.cpp", "../src/sync_observer.cpp", ] @@ -94,12 +94,12 @@ ohos_source_set("distributeddatafwk_src_file") { "../../../../databaseutils:database_utils", "../../../../interfaces/innerkits/distributeddatamgr:distributeddata_mgr", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//foundation/distributedhardware/device_manager/interfaces/inner_kits/native_cpp:devicemanagersdk", ] external_deps = [ "access_token:libaccesstoken_sdk", "access_token:libtokenid_sdk", "c_utils:utils", + "device_manager:devicemanagersdk", "file_api:securitylabel", "hilog:libhilog", "hisysevent:libhisysevent", @@ -117,10 +117,31 @@ ohos_source_set("distributeddatafwk_src_file") { "data_share:datashare_common", "data_share:datashare_provider", ] - + subsystem_name = "distributeddatamgr" part_name = "kv_store" } +ohos_unittest("DistributedKvDataManagerMultiUserTest") { + module_out_path = module_output_path + + sources = [ + "../../kvdb/src/kv_hiview_reporter_mock.cpp", + "unittest/distributed_kv_data_manager_multi_user_test.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "c_utils:utils", + "googletest:gtest_main", + "hilog:libhilog", + "ipc:ipc_single", + "samgr:samgr_proxy", + ] + + deps = [ ":distributeddatafwk_src_file" ] +} + ohos_unittest("DistributedKvDataManagerTest") { module_out_path = module_output_path @@ -133,6 +154,7 @@ ohos_unittest("DistributedKvDataManagerTest") { external_deps = [ "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -140,7 +162,6 @@ ohos_unittest("DistributedKvDataManagerTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -156,6 +177,7 @@ ohos_unittest("DistributedKvDataManagerEncryptTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -163,7 +185,6 @@ ohos_unittest("DistributedKvDataManagerEncryptTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -179,6 +200,7 @@ ohos_unittest("LocalSubscribeStoreTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -186,7 +208,6 @@ ohos_unittest("LocalSubscribeStoreTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -202,6 +223,7 @@ ohos_unittest("LocalSubscribeDeviceStoreTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -209,7 +231,6 @@ ohos_unittest("LocalSubscribeDeviceStoreTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -225,6 +246,7 @@ ohos_unittest("SingleKvStoreClientQueryTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -232,7 +254,6 @@ ohos_unittest("SingleKvStoreClientQueryTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -248,6 +269,7 @@ ohos_unittest("SingleKvStoreClientTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -255,7 +277,6 @@ ohos_unittest("SingleKvStoreClientTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -271,6 +292,7 @@ ohos_unittest("SingleKvStoreAsyncGetTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -278,7 +300,6 @@ ohos_unittest("SingleKvStoreAsyncGetTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -294,6 +315,7 @@ ohos_unittest("DeviceKvStoreTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -301,7 +323,6 @@ ohos_unittest("DeviceKvStoreTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -317,11 +338,11 @@ ohos_unittest("BlobTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", ] @@ -339,11 +360,11 @@ ohos_unittest("TypesUtilTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", ] @@ -361,11 +382,11 @@ ohos_unittest("KvUtilTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", ] @@ -383,11 +404,11 @@ ohos_unittest("KvstoreDatashareBridgeTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", ] @@ -408,6 +429,7 @@ ohos_unittest("DistributedDataMgrTest") { "access_token:libnativetoken", "access_token:libtoken_setproc", "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -415,7 +437,6 @@ ohos_unittest("DistributedDataMgrTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -431,6 +452,7 @@ ohos_unittest("EndPointTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -438,7 +460,33 @@ ohos_unittest("EndPointTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", + ] +} + +ohos_unittest("SwitchObserverBridgeTest") { + module_out_path = module_output_path + + sources = [ + "../../kvdb/src/kv_hiview_reporter_mock.cpp", + "unittest/switch_observer_bridge_test.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "c_utils:utils", + "googletest:gtest", + "hilog:libhilog", + "ipc:ipc_single", + "samgr:samgr_proxy", + ] + + cflags = [ + "-Dprivate=public", + ] + + deps = [ + ":distributeddatafwk_src_file", ] } @@ -453,6 +501,7 @@ group("unittest") { ":DeviceKvStoreTest", ":DistributedDataMgrTest", ":DistributedKvDataManagerEncryptTest", + ":DistributedKvDataManagerMultiUserTest", ":DistributedKvDataManagerTest", ":EndPointTest", ":KvUtilTest", @@ -462,6 +511,7 @@ group("unittest") { ":SingleKvStoreAsyncGetTest", ":SingleKvStoreClientQueryTest", ":SingleKvStoreClientTest", + ":SwitchObserverBridgeTest", ":TypesUtilTest", ] } diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/blob_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/blob_test.cpp index 776adf6e595ca26b6239db62199b3cea4fb0ae78..df64ec8b5e8cb5156bd463865fee060493bef6b5 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/blob_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/blob_test.cpp @@ -42,7 +42,7 @@ void BlobTest::TearDown(void) { } * @tc.name: Size001 * @tc.desc: construct a Blob and check its size. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, Size001, TestSize.Level0) @@ -72,7 +72,7 @@ HWTEST_F(BlobTest, Size001, TestSize.Level0) * @tc.name: Empty001 * @tc.desc: construct a Blob and check its empty. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, Empty001, TestSize.Level0) @@ -98,7 +98,7 @@ HWTEST_F(BlobTest, Empty001, TestSize.Level0) * @tc.name: Clear001 * @tc.desc: construct a Blob and check it clear function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, Clear001, TestSize.Level0) @@ -124,7 +124,7 @@ HWTEST_F(BlobTest, Clear001, TestSize.Level0) * @tc.name: StartsWith001 * @tc.desc: construct a Blob and check it StartsWith function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, StartsWith001, TestSize.Level0) @@ -142,7 +142,7 @@ HWTEST_F(BlobTest, StartsWith001, TestSize.Level0) * @tc.name: Compare001 * @tc.desc: construct a Blob and check it compare function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, Compare001, TestSize.Level0) @@ -159,7 +159,7 @@ HWTEST_F(BlobTest, Compare001, TestSize.Level0) * @tc.name: Data001 * @tc.desc: construct a Blob and check it Data function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, Data001, TestSize.Level0) @@ -176,7 +176,7 @@ HWTEST_F(BlobTest, Data001, TestSize.Level0) * @tc.name: ToString001 * @tc.desc: construct a Blob and check it ToString function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, ToString001, TestSize.Level0) @@ -190,7 +190,7 @@ HWTEST_F(BlobTest, ToString001, TestSize.Level0) * @tc.name: OperatorEqual001 * @tc.desc: construct a Blob and check it operator== function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, OperatorEqual001, TestSize.Level0) @@ -206,7 +206,7 @@ HWTEST_F(BlobTest, OperatorEqual001, TestSize.Level0) * @tc.name: Operator001 * @tc.desc: construct a Blob and check it operator[] function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, Operator001, TestSize.Level0) @@ -223,7 +223,7 @@ HWTEST_F(BlobTest, Operator001, TestSize.Level0) * @tc.name: Operator002 * @tc.desc: construct a Blob and check it operator= function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, Operator002, TestSize.Level0) @@ -238,7 +238,7 @@ HWTEST_F(BlobTest, Operator002, TestSize.Level0) * @tc.name: Operator003 * @tc.desc: construct a Blob and check it operator= function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, Operator003, TestSize.Level0) diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_encrypt_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_encrypt_test.cpp index 16b28dfb3522032d230c0909474fedebd686b079..d2648359ffce6c9234e5133cce1da1056bfacab6 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_encrypt_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_encrypt_test.cpp @@ -101,15 +101,15 @@ DistributedKvDataManagerEncryptTest::~DistributedKvDataManagerEncryptTest(void) {} void DistributedKvDataManagerEncryptTest::TearDown(void) -{} +{ + RemoveAllStore(manager); +} /** -* @tc.name: kvstore_ddm_createEncryptedStore_001 -* @tc.desc: Create an encrypted KvStore. -* @tc.type: FUNC -* @tc.require: SR000D08K4 AR000D08KQ -* @tc.author: liqiao -*/ + * @tc.name: kvstore_ddm_createEncryptedStore_001 + * @tc.desc: Create an encrypted KvStore. + * @tc.type: FUNC + */ HWTEST_F(DistributedKvDataManagerEncryptTest, kvstore_ddm_createEncryptedStore_001, TestSize.Level1) { ZLOGI("kvstore_ddm_createEncryptedStore_001 begin."); @@ -135,8 +135,6 @@ HWTEST_F(DistributedKvDataManagerEncryptTest, kvstore_ddm_createEncryptedStore_0 * @tc.name: GetEncryptStoreWithKeyFromService * @tc.desc: Get encrypt store, delete key, get store again. * @tc.type: FUNC - * @tc.require: - * @tc.author: yanhui */ HWTEST_F(DistributedKvDataManagerEncryptTest, GetEncryptStoreWithKeyFromService, TestSize.Level1) { @@ -147,7 +145,7 @@ HWTEST_F(DistributedKvDataManagerEncryptTest, GetEncryptStoreWithKeyFromService, ASSERT_NE(kvStore, nullptr); manager.CloseAllKvStore(appId); - std::string keyPath = createEnc.baseDir + "/key/" + storeId.storeId + ".key"; + std::string keyPath = createEnc.baseDir + "/key/" + storeId.storeId + ".key_v1"; auto ret = remove(keyPath.c_str()); ASSERT_EQ(ret, 0); @@ -155,4 +153,46 @@ HWTEST_F(DistributedKvDataManagerEncryptTest, GetEncryptStoreWithKeyFromService, status = manager.GetSingleKvStore(createEnc, appId, storeId, kvStore); ASSERT_EQ(status, Status::SUCCESS); ASSERT_NE(kvStore, nullptr); +} + +/** + * @tc.name: DeleteEncryptedStore_001 + * @tc.desc: Failed to delete encrypted store, then open again. + * @tc.type: FUNC + */ +HWTEST_F(DistributedKvDataManagerEncryptTest, DeleteEncryptedStore_001, TestSize.Level1) +{ + ZLOGI("DeleteEncryptedStore_001 begin."); + std::shared_ptr kvStore; + Status status = manager.GetSingleKvStore(createEnc, appId, storeId, kvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(kvStore, nullptr); + + Key key = "age"; + Value value = "18"; + status = kvStore->Put(key, value); + EXPECT_EQ(Status::SUCCESS, status); + std::shared_ptr resultSet = nullptr; + kvStore->GetResultSet("", resultSet); + ASSERT_NE(resultSet, nullptr); + ASSERT_TRUE(resultSet->GetCount() == 1); + + // Database busy, delete failed + status = manager.DeleteKvStore(appId, storeId, createEnc.baseDir); + ASSERT_NE(status, Status::SUCCESS); + + kvStore->CloseResultSet(resultSet); + resultSet = nullptr; + manager.CloseAllKvStore(appId); + kvStore = nullptr; + // GetSingleKvStore successful, data still available + status = manager.GetSingleKvStore(createEnc, appId, storeId, kvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(kvStore, nullptr); + Value valueRet; + status = kvStore->Get(key, valueRet); + ASSERT_EQ(valueRet, value); + + status = manager.DeleteKvStore(appId, storeId, createEnc.baseDir); + ASSERT_EQ(status, Status::SUCCESS); } \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_multi_user_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_multi_user_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..69791fe3b5417f43cbd8ee9097f978aa92919b2e --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_multi_user_test.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2025 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 "distributed_kv_data_manager.h" + +using namespace testing::ext; +using namespace OHOS::DistributedKv; +namespace OHOS::Test { +static constexpr const char *APP_ID = "kv_multi_user_test"; +static constexpr const char *FIRST_STORE = "firstStoreId"; +static constexpr const char *SECOND_STORE = "secondStoreId"; +static constexpr int32_t USER_ID = 100; +static constexpr const char *DATA_DIR = "/data/service/el1/100/database"; +class DistributedKvDataManagerMultiUserTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static DistributedKvDataManager manager; + static Options normalOptions; + static Options encryptOptions; + static AppId appId; + static StoreId firstStoreId; + static StoreId secondStoreId; +}; + +DistributedKvDataManager DistributedKvDataManagerMultiUserTest::manager; +Options DistributedKvDataManagerMultiUserTest::normalOptions; +Options DistributedKvDataManagerMultiUserTest::encryptOptions; +AppId DistributedKvDataManagerMultiUserTest::appId; +StoreId DistributedKvDataManagerMultiUserTest::firstStoreId; +StoreId DistributedKvDataManagerMultiUserTest::secondStoreId; + +void DistributedKvDataManagerMultiUserTest::SetUpTestCase(void) +{ + appId.appId = APP_ID; + firstStoreId.storeId = FIRST_STORE; + secondStoreId.storeId = SECOND_STORE; + + std::string dataDir = DATA_DIR + appId.appId; + mkdir(dataDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + + normalOptions.createIfMissing = true; + normalOptions.securityLevel = S1; + normalOptions.kvStoreType = SINGLE_VERSION; + normalOptions.area = EL1; + normalOptions.subUser = USER_ID; + normalOptions.baseDir = dataDir; + normalOptions.encrypt = false; + + encryptOptions.createIfMissing = true; + encryptOptions.securityLevel = S1; + encryptOptions.kvStoreType = SINGLE_VERSION; + encryptOptions.area = EL1; + encryptOptions.subUser = USER_ID; + encryptOptions.baseDir = dataDir; + encryptOptions.encrypt = true; +} + +void DistributedKvDataManagerMultiUserTest::TearDownTestCase(void) +{ + (void)remove(normalOptions.baseDir.c_str()); +} + +void DistributedKvDataManagerMultiUserTest::SetUp() +{ +} + +void DistributedKvDataManagerMultiUserTest::TearDown() +{ + manager.CloseAllKvStore(appId, USER_ID); + manager.DeleteAllKvStore(appId, normalOptions.baseDir, USER_ID); +} + +/** +* @tc.name: GetKvStoreTest001 +* @tc.desc: get normal kv store with sub user +* @tc.type: FUNC +*/ +HWTEST_F(DistributedKvDataManagerMultiUserTest, GetKvStoreTest001, TestSize.Level1) +{ + std::shared_ptr kvStore; + auto status = manager.GetSingleKvStore(normalOptions, appId, firstStoreId, kvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(kvStore, nullptr); +} + +/** +* @tc.name: GetKvStoreTest002 +* @tc.desc: get encrypt kv store with sub user +* @tc.type: FUNC +*/ +HWTEST_F(DistributedKvDataManagerMultiUserTest, GetKvStoreTest002, TestSize.Level1) +{ + std::shared_ptr kvStore; + auto status = manager.GetSingleKvStore(encryptOptions, appId, firstStoreId, kvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(kvStore, nullptr); +} + +/** +* @tc.name: GetAllKvStoreIdTest +* @tc.desc: get all store id with sub user +* @tc.type: FUNC +*/ +HWTEST_F(DistributedKvDataManagerMultiUserTest, GetAllKvStoreId001, TestSize.Level1) +{ + std::shared_ptr firstKvStore; + auto status = manager.GetSingleKvStore(normalOptions, appId, firstStoreId, firstKvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(firstKvStore, nullptr); + + std::shared_ptr secondKvStore; + status = manager.GetSingleKvStore(normalOptions, appId, secondStoreId, secondKvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(secondKvStore, nullptr); + + std::vector storeIds; + status = manager.GetAllKvStoreId(appId, storeIds, normalOptions.subUser); + ASSERT_EQ(status, Status::SUCCESS); + + ASSERT_EQ(storeIds.size(), static_cast(2)); + ASSERT_NE(storeIds[0].storeId, storeIds[1].storeId); + ASSERT_TRUE(storeIds[0].storeId == firstStoreId.storeId || storeIds[0].storeId == secondStoreId.storeId); + ASSERT_TRUE(storeIds[1].storeId == secondStoreId.storeId || storeIds[0].storeId == secondStoreId.storeId); +} + +/** +* @tc.name: CloseKvStoreTest001 +* @tc.desc: close kv store with sub user +* @tc.type: FUNC +*/ +HWTEST_F(DistributedKvDataManagerMultiUserTest, CloseKvStoreTest001, TestSize.Level1) +{ + std::shared_ptr kvStore; + auto status = manager.GetSingleKvStore(normalOptions, appId, firstStoreId, kvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(kvStore, nullptr); + + status = manager.CloseKvStore(appId, firstStoreId, normalOptions.subUser); + ASSERT_EQ(status, Status::SUCCESS); +} + +/** +* @tc.name: CloseKvStoreTest002 +* @tc.desc: close kv store with sub user +* @tc.type: FUNC +*/ +HWTEST_F(DistributedKvDataManagerMultiUserTest, CloseKvStoreTest002, TestSize.Level1) +{ + std::shared_ptr kvStore; + auto status = manager.GetSingleKvStore(normalOptions, appId, firstStoreId, kvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(kvStore, nullptr); + + status = manager.CloseKvStore(appId, kvStore); + ASSERT_EQ(status, Status::SUCCESS); +} + +/** +* @tc.name: CloseKvStoreTest003 +* @tc.desc: delete kv store with sub user +* @tc.type: FUNC +*/ +HWTEST_F(DistributedKvDataManagerMultiUserTest, CloseKvStoreTest003, TestSize.Level1) +{ + std::shared_ptr kvStore; + auto status = manager.GetSingleKvStore(normalOptions, appId, firstStoreId, kvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(kvStore, nullptr); + + status = manager.CloseKvStore(appId, firstStoreId, normalOptions.subUser); + ASSERT_EQ(status, Status::SUCCESS); + kvStore = nullptr; + + status = manager.DeleteKvStore(appId, firstStoreId, normalOptions.baseDir, normalOptions.subUser); + ASSERT_EQ(status, Status::SUCCESS); +} + +/** +* @tc.name: DeleteKvStoreTest002 +* @tc.desc: delete all kv store with sub user +* @tc.type: FUNC +*/ +HWTEST_F(DistributedKvDataManagerMultiUserTest, DeleteKvStoreTest002, TestSize.Level1) +{ + std::shared_ptr firstKvStore; + auto status = manager.GetSingleKvStore(normalOptions, appId, firstStoreId, firstKvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(firstKvStore, nullptr); + + std::shared_ptr secondKvStore; + status = manager.GetSingleKvStore(normalOptions, appId, secondStoreId, secondKvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(secondKvStore, nullptr); + + status = manager.CloseKvStore(appId, firstStoreId, normalOptions.subUser); + ASSERT_EQ(status, Status::SUCCESS); + firstKvStore = nullptr; + + status = manager.CloseKvStore(appId, secondStoreId, normalOptions.subUser); + ASSERT_EQ(status, Status::SUCCESS); + secondKvStore = nullptr; + + status = manager.DeleteAllKvStore(appId, normalOptions.baseDir, normalOptions.subUser); + ASSERT_EQ(status, Status::SUCCESS); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp index a35a207051255f9707d24d5c1f1869e08acca8ee..d88a0bfbc3e78f294a9f4c8051a1a6b1666e1a64 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp @@ -153,7 +153,7 @@ void DistributedKvDataManagerTest::TearDown(void) * @tc.name: GetKvStore001 * @tc.desc: Get an exist SingleKvStore * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetKvStore001, TestSize.Level1) @@ -174,7 +174,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStore001, TestSize.Level1) * @tc.name: GetKvStore002 * @tc.desc: Create and get a new SingleKvStore * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetKvStore002, TestSize.Level1) @@ -193,7 +193,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStore002, TestSize.Level1) * @tc.desc: Get a non-existing SingleKvStore, and the callback function should receive STORE_NOT_FOUND and * get a nullptr. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetKvStore003, TestSize.Level1) @@ -208,7 +208,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStore003, TestSize.Level1) * @tc.name: GetKvStore004 * @tc.desc: Create a SingleKvStore with an empty storeId, and the callback function should receive * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetKvStore004, TestSize.Level1) @@ -224,7 +224,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStore004, TestSize.Level1) * @tc.name: GetKvStore005 * @tc.desc: Get a SingleKvStore with an empty storeId, and the callback function should receive INVALID_ARGUMENT * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetKvStore005, TestSize.Level1) @@ -240,7 +240,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStore005, TestSize.Level1) * @tc.name: GetKvStore006 * @tc.desc: Create a SingleKvStore with a 65-byte storeId, and the callback function should receive INVALID_ARGUMENT * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetKvStore006, TestSize.Level1) @@ -256,7 +256,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStore006, TestSize.Level1) * @tc.name: GetKvStore007 * @tc.desc: Get a SingleKvStore with a 65-byte storeId, the callback function should receive INVALID_ARGUMENT * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetKvStore007, TestSize.Level1) @@ -350,7 +350,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStore010, TestSize.Level1) * @tc.desc: Get a SingleKvStore with a 64 * -byte storeId, the callback function should receive INVALID_ARGUMENT * @tc.type: FUNC -* @tc.require: SR000IIM2J AR000IIMLL +* @tc.require: * @tc.author: wangkai */ HWTEST_F(DistributedKvDataManagerTest, GetKvStoreInvalidSecurityLevel, TestSize.Level1) @@ -368,7 +368,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStoreInvalidSecurityLevel, TestSize. * @tc.name: GetAllKvStore001 * @tc.desc: Get all KvStore IDs when no KvStore exists, and the callback function should receive a 0-length vector. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetAllKvStore001, TestSize.Level1) @@ -384,7 +384,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetAllKvStore001, TestSize.Level1) * @tc.name: GetAllKvStore002 * @tc.desc: Get all SingleKvStore IDs when no KvStore exists, and the callback function should receive a empty vector. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetAllKvStore002, TestSize.Level1) @@ -434,7 +434,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetAllKvStore002, TestSize.Level1) * @tc.name: CloseKvStore001 * @tc.desc: Close an opened KVStore, and the callback function should return SUCCESS. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore001, TestSize.Level1) @@ -453,7 +453,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore001, TestSize.Level1) * @tc.name: CloseKvStore002 * @tc.desc: Close a closed SingleKvStore, and the callback function should return SUCCESS. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore002, TestSize.Level1) @@ -473,7 +473,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore002, TestSize.Level1) * @tc.name: CloseKvStore003 * @tc.desc: Close a SingleKvStore with an empty storeId, and the callback function should return INVALID_ARGUMENT. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore003, TestSize.Level1) @@ -487,7 +487,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore003, TestSize.Level1) * @tc.name: CloseKvStore004 * @tc.desc: Close a SingleKvStore with a 65-byte storeId, and the callback function should return INVALID_ARGUMENT. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore004, TestSize.Level1) @@ -501,7 +501,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore004, TestSize.Level1) * @tc.name: CloseKvStore005 * @tc.desc: Close a non-existing SingleKvStore, and the callback function should return STORE_NOT_OPEN. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore005, TestSize.Level1) @@ -515,7 +515,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore005, TestSize.Level1) * @tc.name: CloseKvStoreMulti001 * @tc.desc: Open a SingleKvStore several times and close them one by one. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000CSKRU +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseKvStoreMulti001, TestSize.Level1) @@ -542,7 +542,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseKvStoreMulti001, TestSize.Level1) * @tc.name: CloseKvStoreMulti002 * @tc.desc: Open a SingleKvStore several times and close them one by one. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000CSKRU +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseKvStoreMulti002, TestSize.Level1) @@ -580,7 +580,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseKvStoreMulti002, TestSize.Level1) * @tc.name: CloseAllKvStore001 * @tc.desc: Close all opened KvStores, and the callback function should return SUCCESS. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseAllKvStore001, TestSize.Level1) @@ -604,7 +604,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseAllKvStore001, TestSize.Level1) * @tc.name: CloseAllKvStore002 * @tc.desc: Close all KvStores which exist but are not opened, and the callback function should return STORE_NOT_OPEN. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseAllKvStore002, TestSize.Level1) @@ -631,7 +631,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseAllKvStore002, TestSize.Level1) * @tc.name: DeleteKvStore001 * @tc.desc: Delete a closed KvStore, and the callback function should return SUCCESS. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore001, TestSize.Level1) @@ -653,7 +653,7 @@ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore001, TestSize.Level1) * @tc.name: DeleteKvStore002 * @tc.desc: Delete an opened SingleKvStore, and the callback function should return SUCCESS. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore002, TestSize.Level1) @@ -673,7 +673,7 @@ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore002, TestSize.Level1) * @tc.name: DeleteKvStore003 * @tc.desc: Delete a non-existing KvStore, and the callback function should return DB_ERROR. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore003, TestSize.Level1) @@ -687,7 +687,7 @@ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore003, TestSize.Level1) * @tc.name: DeleteKvStore004 * @tc.desc: Delete a KvStore with an empty storeId, and the callback function should return INVALID_ARGUMENT. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore004, TestSize.Level1) @@ -702,7 +702,7 @@ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore004, TestSize.Level1) * @tc.desc: Delete a KvStore with 65 bytes long storeId (which exceed storeId length limit). Should * return INVALID_ARGUMENT. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore005, TestSize.Level1) @@ -716,7 +716,7 @@ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore005, TestSize.Level1) * @tc.name: DeleteAllKvStore001 * @tc.desc: Delete all KvStores after closing all of them, and the callback function should return SUCCESS. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, DeleteAllKvStore001, TestSize.Level1) @@ -748,7 +748,7 @@ HWTEST_F(DistributedKvDataManagerTest, DeleteAllKvStore001, TestSize.Level1) * @tc.name: DeleteAllKvStore002 * @tc.desc: Delete all kvstore fail when any kvstore in the appId is not closed * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, DeleteAllKvStore002, TestSize.Level1) @@ -773,7 +773,7 @@ HWTEST_F(DistributedKvDataManagerTest, DeleteAllKvStore002, TestSize.Level1) * @tc.name: DeleteAllKvStore003 * @tc.desc: Delete all KvStores even if no KvStore exists in the appId. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, DeleteAllKvStore003, TestSize.Level1) @@ -856,7 +856,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetSwitchWithInvalidArg, TestSize.Level1) auto [status2, data2] = manager.GetSwitch({ "switches_test_appId" }, ""); ASSERT_EQ(status2, Status::INVALID_ARGUMENT); auto [status3, data3] = manager.GetSwitch({ "switches_test_appId" }, "networkId_test"); - ASSERT_EQ(status3, Status::INVALID_ARGUMENT); + ASSERT_EQ(status3, Status::PERMISSION_DENIED); } /** diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/end_point_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/end_point_test.cpp index 6dc32c9ad9b85e685f2e24ec815fedb139d96d31..ead5ef87d57fd8877f4635805df2abd316cb7dd4 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/end_point_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/end_point_test.cpp @@ -58,6 +58,7 @@ void EndPointTest::SetUpTestCase(void) options_.area = EL1; options_.baseDir = std::string("/data/service/el1/public/database/odmf"); options_.securityLevel = S1; + options_.isClientSync = true; mkdir(options_.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); AppId appId = { "odmf" }; StoreId storeId = { "student_device" }; // define kvstore(database) name. diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_device_store_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_device_store_test.cpp index 1da928321ae061be42f97a120bf30b4ea0fd31ea..e28207fbcab9ad77b1a817b1001c55781b7e1ad9 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_device_store_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_device_store_test.cpp @@ -172,7 +172,7 @@ HWTEST_F(LocalSubscribeDeviceStoreTest, KvStoreDdmSubscribeKvStore001, TestSize. * @tc.name: KvStoreDdmSubscribeKvStore002 * @tc.desc: Subscribe fail, observer is null * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeDeviceStoreTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1) diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_store_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_store_test.cpp index 517324f2f10f22bd2f2866c9a11d60c1bfbb3f98..f837d74bfc5100a7b8801438b49863ceae2b431d 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_store_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_store_test.cpp @@ -161,7 +161,7 @@ uint32_t KvStoreObserverUnitTest::GetCallCount(uint32_t value) * @tc.name: KvStoreDdmSubscribeKvStore001 * @tc.desc: Subscribe success * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore001, TestSize.Level1) @@ -184,7 +184,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore001, TestSize.Level1 * @tc.name: KvStoreDdmSubscribeKvStore002 * @tc.desc: Subscribe fail, observer is null * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1) @@ -200,7 +200,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1 * @tc.name: KvStoreDdmSubscribeKvStore003 * @tc.desc: Subscribe success and OnChange callback after put * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore003, TestSize.Level1) @@ -227,7 +227,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore003, TestSize.Level1 * @tc.name: KvStoreDdmSubscribeKvStore004 * @tc.desc: The same observer subscribe three times and OnChange callback after put * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore004, TestSize.Level2) @@ -256,7 +256,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore004, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore005 * @tc.desc: The different observer subscribe three times and OnChange callback after put * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore005, TestSize.Level2) @@ -293,7 +293,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore005, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore006 * @tc.desc: Unsubscribe an observer and subscribe again - the map should be cleared after unsubscription. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore006, TestSize.Level2) @@ -336,7 +336,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore006, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore007 * @tc.desc: Subscribe to an observer - OnChange callback is called multiple times after the put operation. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore007, TestSize.Level2) @@ -371,7 +371,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore007, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore008 * @tc.desc: Subscribe to an observer - OnChange callback is called multiple times after the put&update operations. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore008, TestSize.Level2) @@ -405,7 +405,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore008, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore009 * @tc.desc: Subscribe to an observer - OnChange callback is called multiple times after the putBatch operation. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore009, TestSize.Level2) @@ -452,7 +452,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore009, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore010 * @tc.desc: Subscribe to an observer - OnChange callback is called multiple times after the putBatch update operation. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore010, TestSize.Level2) @@ -499,7 +499,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore010, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore011 * @tc.desc: Subscribe to an observer - OnChange callback is called after successful deletion. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore011, TestSize.Level2) @@ -536,7 +536,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore011, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore012 * @tc.desc: Subscribe to an observer - OnChange callback is not called after deletion of non-existing keys. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore012, TestSize.Level2) @@ -573,7 +573,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore012, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore013 * @tc.desc: Subscribe to an observer - OnChange callback is called after KvStore is cleared. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore013, TestSize.Level2) @@ -608,7 +608,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore013, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore014 * @tc.desc: Subscribe to an observer - OnChange callback is not called after non-existing data in KvStore is cleared. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore014, TestSize.Level2) @@ -628,7 +628,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore014, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore015 * @tc.desc: Subscribe to an observer - OnChange callback is called after the deleteBatch operation. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore015, TestSize.Level2) @@ -670,7 +670,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore015, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore016 * @tc.desc: Subscribe to an observer - OnChange callback is called after deleteBatch of non-existing keys. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore016, TestSize.Level2) @@ -712,7 +712,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore016, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore020 * @tc.desc: Unsubscribe an observer two times. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore020, TestSize.Level2) @@ -733,7 +733,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore020, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStoreNotification001 * @tc.desc: Subscribe to an observer successfully - callback is called with a notification after the put operation. * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification001, TestSize.Level1) @@ -763,7 +763,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification001, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification002 * @tc.desc: Subscribe to the same observer three times - callback is called with a notification after the put operation. * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification002, TestSize.Level2) @@ -795,7 +795,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification002, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification003 * @tc.desc: The different observer subscribe three times and callback with notification after put * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification003, TestSize.Level2) @@ -843,7 +843,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification003, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification004 * @tc.desc: Verify notification after an observer is unsubscribed and then subscribed again. * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification004, TestSize.Level2) @@ -895,7 +895,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification004, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification005 * @tc.desc: Subscribe to an observer, callback with notification many times after put the different data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification005, TestSize.Level2) @@ -941,7 +941,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification005, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification006 * @tc.desc: Subscribe to an observer, callback with notification many times after put the same data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification006, TestSize.Level2) @@ -987,7 +987,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification006, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification007 * @tc.desc: Subscribe to an observer, callback with notification many times after put&update * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification007, TestSize.Level2) @@ -1026,7 +1026,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification007, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification008 * @tc.desc: Subscribe to an observer, callback with notification one times after putbatch&update * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification008, TestSize.Level2) @@ -1077,7 +1077,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification008, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification009 * @tc.desc: Subscribe to an observer, callback with notification one times after putbatch all different data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification009, TestSize.Level2) @@ -1120,7 +1120,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification009, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification010 * @tc.desc: Subscribe to an observer, callback with notification one times after putbatch both different and same data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification010, TestSize.Level2) @@ -1163,7 +1163,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification010, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification011 * @tc.desc: Subscribe to an observer, callback with notification one times after putbatch all same data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification011, TestSize.Level2) @@ -1204,7 +1204,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification011, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification012 * @tc.desc: Subscribe to an observer, callback with notification many times after putbatch all different data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification012, TestSize.Level2) @@ -1265,7 +1265,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification012, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification013 * @tc.desc: Subscribe to an observer, callback with notification many times after putbatch both different and same data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification013, TestSize.Level2) @@ -1327,7 +1327,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification013, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification014 * @tc.desc: Subscribe to an observer, callback with notification many times after putbatch all same data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification014, TestSize.Level2) @@ -1388,7 +1388,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification014, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification015 * @tc.desc: Subscribe to an observer, callback with notification many times after putbatch complex data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification015, TestSize.Level2) @@ -1450,7 +1450,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification015, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification016 * @tc.desc: Pressure test subscribe, callback with notification many times after putbatch * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification016, TestSize.Level2) @@ -1483,7 +1483,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification016, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification017 * @tc.desc: Subscribe to an observer, callback with notification after delete success * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification017, TestSize.Level2) @@ -1523,7 +1523,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification017, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification018 * @tc.desc: Subscribe to an observer, not callback after delete which key not exist * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification018, TestSize.Level2) @@ -1561,7 +1561,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification018, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification019 * @tc.desc: Subscribe to an observer, delete the same data many times and only first delete callback with notification * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification019, TestSize.Level2) @@ -1606,7 +1606,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification019, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification020 * @tc.desc: Subscribe to an observer, callback with notification after deleteBatch * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification020, TestSize.Level2) @@ -1653,7 +1653,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification020, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification021 * @tc.desc: Subscribe to an observer, not callback after deleteBatch which all keys not exist * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification021, TestSize.Level2) @@ -1697,7 +1697,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification021, Tes * @tc.desc: Subscribe to an observer, deletebatch the same data many times and only first deletebatch callback with * notification * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification022, TestSize.Level2) @@ -1749,7 +1749,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification022, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification023 * @tc.desc: Subscribe to an observer, include Clear Put PutBatch Delete DeleteBatch * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification023, TestSize.Level2) @@ -1805,7 +1805,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification023, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification024 * @tc.desc: Subscribe to an observer[use transaction], include Clear Put PutBatch Delete DeleteBatch * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification024, TestSize.Level2) @@ -1857,7 +1857,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification024, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification025 * @tc.desc: Subscribe to an observer[use transaction], include Clear Put PutBatch Delete DeleteBatch * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification025, TestSize.Level2) @@ -1913,7 +1913,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification025, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification026 * @tc.desc: Subscribe to an observer[use transaction], include bigData PutBatch update insert delete * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: dukaizhan */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification026, TestSize.Level2) diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/single_kvstore_client_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/single_kvstore_client_test.cpp index b720f9dbecbf4b71dc90476534b29c5170c11762..09652be7f32a97de4870df46d69a397abbc2fb1a 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/single_kvstore_client_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/single_kvstore_client_test.cpp @@ -136,7 +136,7 @@ void KvStoreSyncCallbackTestImpl::SyncCompleted(const std::map deviceIds; + DataQuery dataQuery; + auto syncStatus = singleKvStore->Sync(deviceIds, SyncMode::PUSH, dataQuery, false, nullptr); + ASSERT_NE(syncStatus, Status::SUCCESS); +} + /** * @tc.name: SubscribeWithQuery001 * desc: subscribe and sync device data with query; * type: FUNC - * require: AR000GH096 + * require: * author:taoyuxin */ HWTEST_F(SingleKvStoreClientTest, SubscribeWithQuery001, TestSize.Level1) @@ -1178,7 +1192,7 @@ HWTEST_F(SingleKvStoreClientTest, SubscribeWithQuery001, TestSize.Level1) * @tc.name: UnSubscribeWithQuery001 * desc: subscribe and sync device data with query; * type: FUNC - * require: SR000GH095 + * require: * author:taoyuxin */ HWTEST_F(SingleKvStoreClientTest, UnSubscribeWithQuery001, TestSize.Level1) diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/switch_observer_bridge_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/switch_observer_bridge_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..39bede1556b51f226869c6622926f2d638192481 --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/switch_observer_bridge_test.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2025 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 "switch_observer_bridge.h" + +#include + +namespace OHOS::Test { +using namespace testing::ext; +using namespace OHOS::DistributedKv; +class SwitchObserverBridgeTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void) {} + void SetUp() {} + void TearDown() {} + + static AppId invalidAppId_; + static AppId validAppId_; +}; + +AppId SwitchObserverBridgeTest::invalidAppId_; +AppId SwitchObserverBridgeTest::validAppId_; + +void SwitchObserverBridgeTest::SetUpTestCase(void) +{ + invalidAppId_.appId = ""; + validAppId_.appId = "SwitchObserverBridgeTest"; +} + +class SwitchObserverTest : public KvStoreObserver { +public: + void OnSwitchChange(const SwitchNotification ¬ification) override {} +}; + +/** +* @tc.name: AddAndDeleteSwitchCallbackTest001 +* @tc.desc: test add and delete switch callback +* @tc.type: FUNC +*/ +HWTEST_F(SwitchObserverBridgeTest, AddAndDeleteSwitchCallbackTest001, TestSize.Level1) +{ + std::shared_ptr switchBridge = std::make_shared(validAppId_); + + switchBridge->AddSwitchCallback(nullptr); + ASSERT_TRUE(switchBridge->switchObservers_.Empty()); + + std::shared_ptr observer = std::make_shared(); + switchBridge->AddSwitchCallback(observer); + ASSERT_FALSE(switchBridge->switchObservers_.Empty()); + + switchBridge->DeleteSwitchCallback(nullptr); + ASSERT_FALSE(switchBridge->switchObservers_.Empty()); + + switchBridge->DeleteSwitchCallback(observer); + ASSERT_TRUE(switchBridge->switchObservers_.Empty()); +} + +/** +* @tc.name: OnRemoteDiedTest001 +* @tc.desc: test on remote died +* @tc.type: FUNC +*/ +HWTEST_F(SwitchObserverBridgeTest, OnRemoteDiedTest001, TestSize.Level1) +{ + std::shared_ptr switchBridge = std::make_shared(invalidAppId_); + switchBridge->OnRemoteDied(); + ASSERT_FALSE(switchBridge->switchAppId_.IsValid()); + + switchBridge = std::make_shared(validAppId_); + switchBridge->OnRemoteDied(); + ASSERT_TRUE(switchBridge->switchAppId_.IsValid()); + ASSERT_TRUE(switchBridge->switchObservers_.Empty()); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/datamgr_service_proxy.h b/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/datamgr_service_proxy.h index 510647da5058e305c56b4a21892c23691caa70b8..20831cc34e7d841594c0cdf55fbafed96a7ca06c 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/datamgr_service_proxy.h +++ b/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/datamgr_service_proxy.h @@ -22,10 +22,12 @@ public: ~DataMgrServiceProxy() = default; sptr GetFeatureInterface(const std::string &name) override; - Status RegisterClientDeathObserver(const AppId &appId, sptr observer) override; + Status RegisterClientDeathObserver(const AppId &appId, sptr observer, + const std::string &featureName = "") override; int32_t ClearAppStorage(const std::string &bundleName, int32_t userId, int32_t appIndex, int32_t tokenId) override; + int32_t Exit(const std::string &featureName) override; private: static inline BrokerDelegator delegator_; }; diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/distributeddata_ipc_interface_code.h b/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/distributeddata_ipc_interface_code.h index 4776377e5281fe40ef90dd3c214a324c87e38295..59bbc6c9ff9a47f5ba74f351fd967b969bd7aab4 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/distributeddata_ipc_interface_code.h +++ b/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/distributeddata_ipc_interface_code.h @@ -24,6 +24,7 @@ enum class KvStoreDataServiceInterfaceCode : uint32_t { GET_FEATURE_INTERFACE = 0, REGISTERCLIENTDEATHOBSERVER, CLEAR_APP_STORAGE, + FEATURE_EXIT, SERVICE_CMD_LAST }; } // namespace OHOS::DistributedKv diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/ikvstore_data_service.h b/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/ikvstore_data_service.h index 8c30d51d24f4063ae20c6960437b33c151440ac7..b660d7b9f58694a9469425fd5751971f2334a7c5 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/ikvstore_data_service.h +++ b/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/ikvstore_data_service.h @@ -30,11 +30,14 @@ public: virtual sptr GetFeatureInterface(const std::string &name) = 0; - virtual Status RegisterClientDeathObserver(const AppId &appId, sptr observer) = 0; + virtual Status RegisterClientDeathObserver(const AppId &appId, sptr observer, + const std::string &featureName = "") = 0; virtual int32_t ClearAppStorage(const std::string &bundleName, int32_t userId, int32_t appIndex, int32_t tokenId) = 0; + virtual int32_t Exit(const std::string &featureName) = 0; + protected: static constexpr size_t MAX_IPC_CAPACITY = 800 * 1024; }; diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatasvc/src/datamgr_service_proxy.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatasvc/src/datamgr_service_proxy.cpp index 4eed48d7169c9aa4f4f2e1f891c96965f07afa0b..0863f0acd3496d8f4e74cd96c44a666c48fccc4a 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatasvc/src/datamgr_service_proxy.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatasvc/src/datamgr_service_proxy.cpp @@ -61,7 +61,8 @@ sptr DataMgrServiceProxy::GetFeatureInterface(const std::string & return remoteObject; } -Status DataMgrServiceProxy::RegisterClientDeathObserver(const AppId &appId, sptr observer) +Status DataMgrServiceProxy::RegisterClientDeathObserver(const AppId &appId, sptr observer, + const std::string &featureName) { MessageParcel data; MessageParcel reply; @@ -82,6 +83,10 @@ Status DataMgrServiceProxy::RegisterClientDeathObserver(const AppId &appId, sptr ZLOGE("This observer is null"); return Status::INVALID_ARGUMENT; } + if (!data.WriteString(featureName)) { + ZLOGW("Failed to write featureName."); + return Status::IPC_ERROR; + } MessageOption mo { MessageOption::TF_SYNC }; int32_t error = Remote()->SendRequest( @@ -117,5 +122,10 @@ int32_t DataMgrServiceProxy::ClearAppStorage(const std::string &bundleName, int3 } return static_cast(reply.ReadInt32()); } + +int32_t DataMgrServiceProxy::Exit(const std::string &featureName) +{ + return Status::NOT_SUPPORT; +} } // namespace DistributedKv } // namespace OHOS diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h index cf438e9e913d2b9943a7bb7a87eae78aada63b6e..a0cd3d9e7bf193677c084aa9deba8849388b8a88 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h @@ -34,6 +34,7 @@ public: std::string query; uint64_t syncId = 0; int32_t triggerMode = 0; + bool isRetry = true; }; enum PasswordType { BACKUP_SECRET_KEY = 0, diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/security_manager.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/security_manager.h index 22b56ea3da380ef37393ad01eb5588600c22e3f7..4bb3a9037d67cfe839f61f35c22768c8380f24b3 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/security_manager.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/security_manager.h @@ -24,6 +24,25 @@ namespace OHOS::DistributedKv { class SecurityManager { public: + struct SecurityContent { + static constexpr size_t MAGIC_NUM = 4; + static constexpr uint8_t MAGIC_CHAR = 0x6A; + static constexpr uint32_t MAGIC_NUMBER = 0x6A6A6A6A; + static constexpr uint8_t INVALID_VERSION = 0x00; + static constexpr uint8_t CURRENT_VERSION = 0x01; + static constexpr int32_t NONCE_SIZE = 12; + static constexpr int32_t KEY_SIZE = 32; + + bool isNewStyle = true; + uint32_t magicNum = MAGIC_NUMBER; + uint8_t version = INVALID_VERSION; + std::vector time; + std::vector nonceValue; + // encryptValue contains version and time and key + std::vector encryptValue; + std::vector fullKeyValue; + }; + struct DBPassword { bool isKeyOutdated = false; DistributedDB::CipherPassword password; @@ -53,14 +72,12 @@ public: public: KeyFiles(const std::string &name, const std::string &path, bool openFile = true); ~KeyFiles(); - const std::string &GetKeyFilePath(); int32_t Lock(); int32_t UnLock(); int32_t DestroyLock(); private: int32_t FileLock(int32_t lockType); int32_t lockFd_ = -1; - std::string keyPath_; std::string lockFile_; }; @@ -81,27 +98,20 @@ public: void DelDBPassword(const std::string &name, const std::string &path); private: - static constexpr const char *ROOT_KEY_ALIAS = "distributeddb_client_root_key"; - static constexpr const char *HKS_BLOB_TYPE_NONCE = "Z5s0Bo571KoqwIi6"; - static constexpr const char *HKS_BLOB_TYPE_AAD = "distributeddata_client"; - static constexpr const char *SUFFIX_KEY = ".key"; - static constexpr const char *SUFFIX_KEY_LOCK = ".key_lock"; - static constexpr const char *KEY_DIR = "/key"; - static constexpr const char *SLASH = "/"; - static constexpr int KEY_SIZE = 32; - static constexpr int HOURS_PER_YEAR = (24 * 365); - SecurityManager(); ~SecurityManager(); - std::vector LoadKeyFromFile(const std::string &name, const std::string &path, bool &isOutdated); + std::vector Random(int32_t length); + bool LoadContent(SecurityContent &content, const std::string &path); + void LoadKeyFromFile(const std::string &path, SecurityContent &securityContent); + void LoadNewKey(const std::vector &content, SecurityContent &securityContent); + void LoadOldKey(const std::vector &content, SecurityContent &securityContent); bool SaveKeyToFile(const std::string &name, const std::string &path, std::vector &key); - std::vector Random(int32_t len); bool IsKeyOutdated(const std::vector &date); int32_t GenerateRootKey(); int32_t CheckRootKey(); bool Retry(); - std::vector Encrypt(const std::vector &key); - bool Decrypt(std::vector &source, std::vector &key); + bool Encrypt(const std::vector &key, SecurityContent &content); + bool Decrypt(SecurityContent &content); std::vector vecRootKeyAlias_{}; std::vector vecNonce_{}; @@ -109,4 +119,4 @@ private: std::atomic_bool hasRootKey_ = false; }; } // namespace OHOS::DistributedKv -#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_KVDB_SECURITY_MANAGER_H +#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_KVDB_SECURITY_MANAGER_H \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h index 4315696adb9f287658172649f8d70974b26c812b..47777fb5602fc1d1a8ec264cb2bb530417b7ac66 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h @@ -88,6 +88,8 @@ public: Status Sync(const std::vector &devices, SyncMode mode, uint32_t delay) override; Status Sync(const std::vector &devices, SyncMode mode, const DataQuery &query, std::shared_ptr syncCallback, uint32_t delay) override; + Status Sync(const std::vector &devices, SyncMode mode, const DataQuery &query, bool isRetry, + std::shared_ptr syncCallback) override; Status RegisterSyncCallback(std::shared_ptr callback) override; Status UnRegisterSyncCallback() override; Status SetSyncParam(const KvSyncParam &syncParam) override; @@ -117,7 +119,6 @@ private: (std::chrono::steady_clock::now() + std::chrono::milliseconds(offset)).time_since_epoch()) .count(); } - static constexpr int32_t INTEGRITY_CHECK_API_VERSION = 20; static constexpr uint32_t NOTIFY_INTERVAL = 200; // ms static constexpr size_t MAX_VALUE_LENGTH = 4 * 1024 * 1024; static constexpr size_t MAX_OBSERVER_SIZE = 8; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/store_manager.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/store_manager.h index 025895b3abb6ea12a64affd630e372f626d1d521..48f727c1e40e0bc43f99e68a3e318a788e91656b 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/store_manager.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/store_manager.h @@ -14,9 +14,13 @@ */ #ifndef OHOS_DISTRIBUTED_DATA_FRAMEWORKS_KVDB_STORE_MANAGER_H #define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_KVDB_STORE_MANAGER_H + +#include "concurrent_map.h" #include "single_kvstore.h" #include "kv_hiview_reporter.h" #include "store_factory.h" +#include "switch_observer_bridge.h" + namespace OHOS::DistributedKv { class StoreManager { public: @@ -35,6 +39,7 @@ public: private: std::shared_ptr OpenWithSecretKeyFromService(const AppId &appId, const StoreId &storeId, const Options &options, Status &status, StoreParams &storeParams); + ConcurrentMap> switchObservers_; }; -} +} // namespace OHOS::DistributedKv #endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_KVDB_STORE_MANAGER_H diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/kv_hiview_reporter.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/kv_hiview_reporter.cpp index abeacad5d906e463ff78e48f6abedbec7f506106..c2755b9f4a8f0e74800dd9fc994967963d201036 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/kv_hiview_reporter.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/kv_hiview_reporter.cpp @@ -18,16 +18,16 @@ #include "kv_hiview_reporter.h" #include #include +#include #include #include -#include -#include #include +#include #include "concurrent_map.h" #include "hisysevent_c.h" #include "log_print.h" -#include "types.h" #include "store_util.h" +#include "types.h" namespace OHOS::DistributedKv { static constexpr int MAX_TIME_BUF_LEN = 32; @@ -160,8 +160,8 @@ void KVDBFaultHiViewReporter::ReportFaultEvent(KVDBFaultEvent eventInfo) void KVDBFaultHiViewReporter::ReportCurruptedEvent(KVDBFaultEvent eventInfo) { if (eventInfo.appendix.empty() || eventInfo.storeName.empty()) { - ZLOGW("The dbPath or storeId is empty, dbPath:%{public}s, storeId:%{public}s", eventInfo.appendix.c_str(), - StoreUtil::Anonymous(eventInfo.storeName).c_str()); + ZLOGW("The dbPath or storeId is empty, dbPath:%{public}s, storeId:%{public}s", + StoreUtil::Anonymous(eventInfo.appendix).c_str(), StoreUtil::Anonymous(eventInfo.storeName).c_str()); return; } if (IsReportedCorruptedFault(eventInfo.bundleName, eventInfo.storeName, eventInfo.appendix)) { @@ -291,12 +291,12 @@ bool KVDBFaultHiViewReporter::IsReportedCorruptedFault(const std::string &appId, void KVDBFaultHiViewReporter::CreateCorruptedFlag(const std::string &dbPath, const std::string &storeId) { if (dbPath.empty() || storeId.empty()) { - ZLOGW("The dbPath or storeId is empty, dbPath:%{public}s, storeId:%{public}s", dbPath.c_str(), - StoreUtil::Anonymous(storeId).c_str()); + ZLOGW("The dbPath or storeId is empty, dbPath:%{public}s, storeId:%{public}s", + StoreUtil::Anonymous(dbPath).c_str(), StoreUtil::Anonymous(storeId).c_str()); return; } std::string flagFilename = dbPath + storeId + DB_CORRUPTED_POSTFIX; - int fd = creat(flagFilename.c_str(), S_IRWXU | S_IRWXG); + int fd = creat(flagFilename.c_str(), S_IRUSR | S_IWUSR); if (fd == -1) { ZLOGW("Creat corrupted flg fail, flgname=%{public}s, errno=%{public}d", StoreUtil::Anonymous(flagFilename).c_str(), errno); @@ -309,8 +309,8 @@ void KVDBFaultHiViewReporter::CreateCorruptedFlag(const std::string &dbPath, con void KVDBFaultHiViewReporter::DeleteCorruptedFlag(const std::string &dbPath, const std::string &storeId) { if (dbPath.empty() || storeId.empty()) { - ZLOGW("The dbPath or storeId is empty, dbPath:%{public}s, storeId:%{public}s", dbPath.c_str(), - StoreUtil::Anonymous(storeId).c_str()); + ZLOGW("The dbPath or storeId is empty, dbPath:%{public}s, storeId:%{public}s", + StoreUtil::Anonymous(dbPath).c_str(), StoreUtil::Anonymous(storeId).c_str()); return; } std::string flagFilename = dbPath + storeId + DB_CORRUPTED_POSTFIX; @@ -326,7 +326,7 @@ std::string KVDBFaultHiViewReporter::GetDBPath(const std::string &path, const st std::string reporterDir = ""; DistributedDB::KvStoreDelegateManager::GetDatabaseDir(storeId, reporterDir); reporterDir = path + "/kvdb/" + reporterDir + "/"; - return reporterDir; + return StoreUtil::Anonymous(reporterDir).c_str(); } std::string KVDBFaultHiViewReporter::GenerateAppendix(const KVDBFaultEvent &eventInfo) diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp index 5604fd76984aabee60c2c6840d2a8eb5f7bce798..88b5cd84216bbf8ecea897363518e852d43b3b74 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp @@ -110,6 +110,7 @@ Status KVDBServiceClient::GetStoreIds(const AppId &appId, int32_t subUser, std:: reply, appId, StoreId(), subUser); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s", status, appId.appId.c_str()); + return static_cast(status); } ITypesUtil::Unmarshal(reply, storeIds); return static_cast(status); @@ -168,7 +169,7 @@ Status KVDBServiceClient::Sync(const AppId &appId, const StoreId &storeId, int32 { MessageParcel reply; int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_SYNC), reply, appId, storeId, - syncInfo.seqId, syncInfo.mode, syncInfo.devices, syncInfo.delay, syncInfo.query, subUser); + syncInfo.seqId, syncInfo.mode, syncInfo.devices, syncInfo.delay, syncInfo.query, subUser, syncInfo.isRetry); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s, storeId:%{public}s, sequenceId:%{public}" PRIu64, status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), syncInfo.seqId); @@ -245,7 +246,7 @@ Status KVDBServiceClient::GetSyncParam(const AppId &appId, const StoreId &storeI if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s, storeId:%{public}s", status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str()); - return SUCCESS; + return static_cast(status); } ITypesUtil::Unmarshal(reply, syncParam.allowedDelayMs); return static_cast(status); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/process_system_api_adapter_impl.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/process_system_api_adapter_impl.cpp index 3ede302f47c092e06f200783147bdf9d96412172..1c545cd24810ff5183245c7161bdcd30bd74df39 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/process_system_api_adapter_impl.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/process_system_api_adapter_impl.cpp @@ -19,6 +19,7 @@ #include #include "log_print.h" #include "security_label.h" +#include "store_util.h" namespace OHOS::DistributedKv { using Label = DistributedDB::SecurityLabel; @@ -73,7 +74,8 @@ ProcessSystemApiAdapterImpl::DBStatus ProcessSystemApiAdapterImpl::SetSecurityOp if (!result) { auto fPath = filePath.substr(0, HEAD_SIZE) + REPLACE_CHAIN + filePath.substr(filePath.length() - END_SIZE, END_SIZE); - ZLOGE("Set label failed! level:%{public}s, file:%{public}s", secLevel.c_str(), fPath.c_str()); + ZLOGE("Set label failed! level:%{public}s, file:%{public}s", secLevel.c_str(), + StoreUtil::Anonymous(fPath).c_str()); return DBStatus::DB_ERROR; } return DBStatus::OK; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/security_manager.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/security_manager.cpp index 11d03ff55a2190f05130b41e6df48dc895c98fa3..60bfaa64b55c0c0cc936ec377d848795cb0b9c3b 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/security_manager.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/security_manager.cpp @@ -12,13 +12,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define LOG_TAG "SECURITYMANAGER" +#define LOG_TAG "SecurityManager" + #include "security_manager.h" #include #include #include -#include #include #include @@ -30,7 +30,18 @@ #include "store_types.h" #include "store_util.h" #include "task_executor.h" + namespace OHOS::DistributedKv { +static constexpr int HOURS_PER_YEAR = (24 * 365); +static constexpr const char *ROOT_KEY_ALIAS = "distributeddb_client_root_key"; +static constexpr const char *HKS_BLOB_TYPE_NONCE = "Z5s0Bo571KoqwIi6"; +static constexpr const char *HKS_BLOB_TYPE_AAD = "distributeddata_client"; +static constexpr const char *SUFFIX_KEY = ".key"; +static constexpr const char *SUFFIX_KEY_V1 = ".key_v1"; +static constexpr const char *SUFFIX_KEY_LOCK = ".key_lock"; +static constexpr const char *KEY_DIR = "/key"; +static constexpr const char *SLASH = "/"; + SecurityManager::SecurityManager() { vecRootKeyAlias_ = std::vector(ROOT_KEY_ALIAS, ROOT_KEY_ALIAS + strlen(ROOT_KEY_ALIAS)); @@ -69,29 +80,75 @@ bool SecurityManager::Retry() return false; } -SecurityManager::DBPassword SecurityManager::GetDBPassword(const std::string &name, - const std::string &path, bool needCreate) +std::vector SecurityManager::Random(int32_t length) +{ + std::vector value(length, 0); + struct HksBlob blobValue = { .size = length, .data = &(value[0]) }; + auto ret = HksGenerateRandom(nullptr, &blobValue); + if (ret != HKS_SUCCESS) { + ZLOGE("HksGenerateRandom failed, status: %{public}d", ret); + return {}; + } + return value; +} + +bool SecurityManager::LoadContent(SecurityManager::SecurityContent &content, const std::string &path) +{ + if (!FileExists(path)) { + return false; + } + LoadKeyFromFile(path, content); + if (content.encryptValue.empty() || !Decrypt(content)) { + return false; + } + return true; +} + +SecurityManager::DBPassword SecurityManager::GetDBPassword(const std::string &name, const std::string &path, + bool needCreate) { - DBPassword dbPassword; KeyFiles keyFiles(name, path); KeyFilesAutoLock fileLock(keyFiles); - auto secKey = LoadKeyFromFile(name, path, dbPassword.isKeyOutdated); - std::vector key{}; - - if (secKey.empty() && needCreate) { - key = Random(KEY_SIZE); - if (!SaveKeyToFile(name, path, key)) { - secKey.assign(secKey.size(), 0); + DBPassword dbPassword; + auto oldKeyPath = path + KEY_DIR + SLASH + name + SUFFIX_KEY; + auto newKeyPath = path + KEY_DIR + SLASH + name + SUFFIX_KEY_V1; + SecurityContent content; + auto result = LoadContent(content, newKeyPath); + if (!result) { + content.isNewStyle = false; + result = LoadContent(content, oldKeyPath); + } + content.encryptValue.assign(content.encryptValue.size(), 0); + std::vector key; + if (result) { + size_t offset = 0; + if (content.isNewStyle && content.fullKeyValue.size() > (sizeof(time_t) / sizeof(uint8_t)) + 1) { + content.version = content.fullKeyValue[offset++]; + content.time.assign(content.fullKeyValue.begin() + offset, + content.fullKeyValue.begin() + offset + (sizeof(time_t) / sizeof(uint8_t))); + } + offset = content.isNewStyle ? (sizeof(time_t) / sizeof(uint8_t)) + 1 : 0; + if (content.fullKeyValue.size() > offset) { + key.assign(content.fullKeyValue.begin() + offset, content.fullKeyValue.end()); + } + // old security key file and update key file + if (!content.isNewStyle && !key.empty() && SaveKeyToFile(name, path, key)) { + StoreUtil::Remove(oldKeyPath); + } + content.fullKeyValue.assign(content.fullKeyValue.size(), 0); + } + if (!result && needCreate) { + key = Random(SecurityContent::KEY_SIZE); + if (key.empty() || !SaveKeyToFile(name, path, key)) { key.assign(key.size(), 0); return dbPassword; } + StoreUtil::Remove(oldKeyPath); } - - if ((!secKey.empty() && Decrypt(secKey, key)) || !key.empty()) { - dbPassword.SetValue(key.data(), key.size()); + if (!content.time.empty()) { + dbPassword.isKeyOutdated = IsKeyOutdated(content.time); } - - secKey.assign(secKey.size(), 0); + dbPassword.SetValue(key.data(), key.size()); key.assign(key.size(), 0); return dbPassword; } @@ -111,99 +168,116 @@ void SecurityManager::DelDBPassword(const std::string &name, const std::string & { KeyFiles keyFiles(name, path); KeyFilesAutoLock fileLock(keyFiles); - auto keyPath = keyFiles.GetKeyFilePath(); - StoreUtil::Remove(keyPath); + auto oldKeyPath = path + KEY_DIR + SLASH + name + SUFFIX_KEY; + auto newKeyPath = path + KEY_DIR + SLASH + name + SUFFIX_KEY_V1; + StoreUtil::Remove(oldKeyPath); + StoreUtil::Remove(newKeyPath); fileLock.UnLockAndDestroy(); } -std::vector SecurityManager::Random(int32_t len) +void SecurityManager::LoadKeyFromFile(const std::string &path, SecurityManager::SecurityContent &securityContent) { - std::random_device randomDevice; - std::uniform_int_distribution distribution(0, std::numeric_limits::max()); - std::vector key(len); - for (int32_t i = 0; i < len; i++) { - key[i] = static_cast(distribution(randomDevice)); + std::vector content; + auto loaded = LoadBufferFromFile(path, content); + if (!loaded) { + return; } - return key; + if (securityContent.isNewStyle) { + LoadNewKey(content, securityContent); + } else { + LoadOldKey(content, securityContent); + } + content.assign(content.size(), 0); } -std::vector SecurityManager::LoadKeyFromFile(const std::string &name, const std::string &path, - bool &isOutdated) +void SecurityManager::LoadNewKey(const std::vector &content, SecurityManager::SecurityContent &securityContent) { - auto keyPath = path + KEY_DIR + SLASH + name + SUFFIX_KEY; - if (!FileExists(keyPath)) { - return {}; - } - StoreUtil::RemoveRWXForOthers(path + KEY_DIR); - - std::vector content; - auto loaded = LoadBufferFromFile(keyPath, content); - if (!loaded) { - return {}; + if (content.size() < SecurityContent::MAGIC_NUM + SecurityContent::NONCE_SIZE + 1) { + return; } - - if (content.size() < (sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE + 1) { - return {}; + for (size_t index = 0; index < SecurityContent::MAGIC_NUM; ++index) { + if (content[index] != char(SecurityContent::MAGIC_CHAR)) { + return; + } } + size_t offset = SecurityContent::MAGIC_NUM; + securityContent.nonceValue.assign(content.begin() + offset, content.begin() + offset + SecurityContent::NONCE_SIZE); + offset += SecurityContent::NONCE_SIZE; + securityContent.encryptValue.assign(content.begin() + offset, content.end()); +} +void SecurityManager::LoadOldKey(const std::vector &content, SecurityManager::SecurityContent &securityContent) +{ size_t offset = 0; - if (content[offset] != char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE)) { - return {}; + if (content.size() < (sizeof(time_t) / sizeof(uint8_t)) + SecurityContent::KEY_SIZE + 1) { + return; } - - offset++; - std::vector date; - date.assign(content.begin() + offset, content.begin() + (sizeof(time_t) / sizeof(uint8_t)) + offset); - isOutdated = IsKeyOutdated(date); + if (content[offset] != char((sizeof(time_t) / sizeof(uint8_t)) + SecurityContent::KEY_SIZE)) { + return; + } + ++offset; + securityContent.time.assign(content.begin() + offset, content.begin() + + (sizeof(time_t) / sizeof(uint8_t)) + offset); offset += (sizeof(time_t) / sizeof(uint8_t)); - std::vector key{ content.begin() + offset, content.end() }; - content.assign(content.size(), 0); - return key; + securityContent.encryptValue.assign(content.begin() + offset, content.end()); } -bool SecurityManager::SaveKeyToFile(const std::string &name, const std::string &path, std::vector &key) +bool SecurityManager::SaveKeyToFile(const std::string &name, const std::string &path, + std::vector &key) { if (!hasRootKey_ && !Retry()) { ZLOGE("Failed! no root key and generation failed"); return false; } - auto secretKey = Encrypt(key); - if (secretKey.empty()) { - ZLOGE("Failed! encrypt failed"); + SecurityContent securityContent; + securityContent.version = SecurityContent::CURRENT_VERSION; + auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + securityContent.time = { reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time) }; + std::vector keyContent; + keyContent.push_back(securityContent.version); + keyContent.insert(keyContent.end(), securityContent.time.begin(), securityContent.time.end()); + keyContent.insert(keyContent.end(), key.begin(), key.end()); + if (!Encrypt(keyContent, securityContent)) { + keyContent.assign(keyContent.size(), 0); return false; } + keyContent.assign(keyContent.size(), 0); auto keyPath = path + KEY_DIR; StoreUtil::InitPath(keyPath); - std::vector content; - auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now()); - std::vector date(reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time)); - content.push_back(char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE)); - content.insert(content.end(), date.begin(), date.end()); - content.insert(content.end(), secretKey.begin(), secretKey.end()); - auto keyFullPath = keyPath + SLASH + name + SUFFIX_KEY; - auto ret = SaveBufferToFile(keyFullPath, content); - if (access(keyFullPath.c_str(), F_OK) == 0) { - StoreUtil::RemoveRWXForOthers(keyFullPath); + auto keyFullPath = keyPath + SLASH + name + SUFFIX_KEY_V1; + auto fd = open(keyFullPath.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + if (fd < 0) { + ZLOGE("Create file failed, ret:%{public}d", errno); + return false; } - content.assign(content.size(), 0); + std::string content(SecurityContent::MAGIC_NUM, static_cast(SecurityContent::MAGIC_CHAR)); + content.append(reinterpret_cast(securityContent.nonceValue.data()), + securityContent.nonceValue.size()); + content.append(reinterpret_cast(securityContent.encryptValue.data()), + securityContent.encryptValue.size()); + auto ret = SaveStringToFd(fd, content); + std::fill(content.begin(), content.end(), '\0'); + close(fd); if (!ret) { - ZLOGE("Client SaveSecretKey failed!"); + ZLOGE("Save key to file fail, ret:%{public}d", ret); return false; } + StoreUtil::RemoveRWXForOthers(keyFullPath); return ret; } -std::vector SecurityManager::Encrypt(const std::vector &key) +bool SecurityManager::Encrypt(const std::vector &key, SecurityManager::SecurityContent &content) { - struct HksBlob blobAad = { uint32_t(vecAad_.size()), vecAad_.data() }; - struct HksBlob blobNonce = { uint32_t(vecNonce_.size()), vecNonce_.data() }; - struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() }; - struct HksBlob plainKey = { uint32_t(key.size()), const_cast(key.data()) }; struct HksParamSet *params = nullptr; int32_t ret = HksInitParamSet(¶ms); if (ret != HKS_SUCCESS) { ZLOGE("HksInitParamSet failed, status: %{public}d", ret); - return {}; + return false; + } + content.nonceValue = Random(SecurityContent::NONCE_SIZE); + if (content.nonceValue.empty()) { + HksFreeParamSet(¶ms); + return false; } struct HksParam hksParam[] = { { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, @@ -211,50 +285,50 @@ std::vector SecurityManager::Encrypt(const std::vector &key) { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, - { .tag = HKS_TAG_NONCE, .blob = blobNonce }, - { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + { .tag = HKS_TAG_NONCE, .blob = { SecurityContent::NONCE_SIZE, &(content.nonceValue[0]) } }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = { uint32_t(vecAad_.size()), &(vecAad_[0]) } }, { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, }; ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); if (ret != HKS_SUCCESS) { ZLOGE("HksAddParams failed, status: %{public}d", ret); HksFreeParamSet(¶ms); - return {}; + return false; } - ret = HksBuildParamSet(¶ms); if (ret != HKS_SUCCESS) { ZLOGE("HksBuildParamSet failed, status: %{public}d", ret); HksFreeParamSet(¶ms); - return {}; + return false; } - uint8_t cipherBuf[256] = { 0 }; struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf }; + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() }; + struct HksBlob plainKey = { uint32_t(key.size()), const_cast(key.data()) }; ret = HksEncrypt(&rootKeyName, params, &plainKey, &cipherText); (void)HksFreeParamSet(¶ms); if (ret != HKS_SUCCESS) { ZLOGE("HksEncrypt failed, status: %{public}d", ret); - return {}; + return false; } - std::vector encryptedKey(cipherText.data, cipherText.data + cipherText.size); - (void)memset_s(cipherBuf, sizeof(cipherBuf), 0, sizeof(cipherBuf)); - return encryptedKey; + content.encryptValue = std::vector(cipherText.data, cipherText.data + cipherText.size); + std::fill(cipherBuf, cipherBuf + sizeof(cipherBuf), 0); + return true; } -bool SecurityManager::Decrypt(std::vector &source, std::vector &key) +bool SecurityManager::Decrypt(SecurityManager::SecurityContent &content) { - struct HksBlob blobAad = { uint32_t(vecAad_.size()), &(vecAad_[0]) }; - struct HksBlob blobNonce = { uint32_t(vecNonce_.size()), &(vecNonce_[0]) }; - struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), &(vecRootKeyAlias_[0]) }; - struct HksBlob encryptedKeyBlob = { uint32_t(source.size()), source.data() }; - struct HksParamSet *params = nullptr; int32_t ret = HksInitParamSet(¶ms); if (ret != HKS_SUCCESS) { ZLOGE("HksInitParamSet failed, status: %{public}d", ret); return false; } + struct HksBlob blobNonce = { .size = uint32_t(vecNonce_.size()), .data = &(vecNonce_[0]) }; + if (!(content.nonceValue.empty())) { + blobNonce.size = uint32_t(content.nonceValue.size()); + blobNonce.data = const_cast(&(content.nonceValue[0])); + } struct HksParam hksParam[] = { { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }, @@ -262,7 +336,7 @@ bool SecurityManager::Decrypt(std::vector &source, std::vector { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, { .tag = HKS_TAG_NONCE, .blob = blobNonce }, - { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = { uint32_t(vecAad_.size()), &(vecAad_[0]) } }, { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, }; ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); @@ -271,25 +345,25 @@ bool SecurityManager::Decrypt(std::vector &source, std::vector HksFreeParamSet(¶ms); return false; } - ret = HksBuildParamSet(¶ms); if (ret != HKS_SUCCESS) { ZLOGE("HksBuildParamSet failed, status: %{public}d", ret); HksFreeParamSet(¶ms); return false; } - uint8_t plainBuf[256] = { 0 }; struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf }; + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), &(vecRootKeyAlias_[0]) }; + struct HksBlob encryptedKeyBlob = { uint32_t(content.encryptValue.size()), + const_cast(content.encryptValue.data()) }; ret = HksDecrypt(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob); (void)HksFreeParamSet(¶ms); if (ret != HKS_SUCCESS) { ZLOGE("HksDecrypt, status: %{public}d", ret); return false; } - - key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size); - (void)memset_s(plainBuf, sizeof(plainBuf), 0, sizeof(plainBuf)); + content.fullKeyValue.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size); + std::fill(plainBuf, plainBuf + sizeof(plainBuf), 0); return true; } @@ -382,13 +456,12 @@ bool SecurityManager::IsKeyOutdated(const std::vector &date) SecurityManager::KeyFiles::KeyFiles(const std::string &name, const std::string &path, bool openFile) { - keyPath_ = path + KEY_DIR + SLASH + name + SUFFIX_KEY; lockFile_ = path + KEY_DIR + SLASH + name + SUFFIX_KEY_LOCK; StoreUtil::InitPath(path + KEY_DIR); if (!openFile) { return; } - lockFd_ = open(lockFile_.c_str(), O_RDONLY | O_CREAT, S_IRWXU | S_IRWXG); + lockFd_ = open(lockFile_.c_str(), O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR); if (lockFd_ < 0) { ZLOGE("Open failed, errno:%{public}d, path:%{public}s", errno, StoreUtil::Anonymous(lockFile_).c_str()); } @@ -403,11 +476,6 @@ SecurityManager::KeyFiles::~KeyFiles() lockFd_ = -1; } -const std::string &SecurityManager::KeyFiles::GetKeyFilePath() -{ - return keyPath_; -} - int32_t SecurityManager::KeyFiles::Lock() { return FileLock(LOCK_EX); @@ -454,6 +522,7 @@ SecurityManager::KeyFilesAutoLock::~KeyFilesAutoLock() { keyFiles_.UnLock(); } + int32_t SecurityManager::KeyFilesAutoLock::UnLockAndDestroy() { keyFiles_.UnLock(); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp index 928b145925b0c2fb663680e51e14a85044c75dc3..cff5bfb9b49ffb33002b474acb803371cdc551e9 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp @@ -60,7 +60,7 @@ SingleStoreImpl::SingleStoreImpl( isApplication_ = true; apiVersion_ = options.apiVersion; } - if (!isApplication_ || (isApplication_ && (apiVersion_ >= INTEGRITY_CHECK_API_VERSION))) { + if (!isApplication_) { isCheckIntegrity_ = true; } } @@ -610,6 +610,19 @@ Status SingleStoreImpl::Sync(const std::vector &devices, SyncMode m return DoSync(syncInfo, syncCallback); } +Status SingleStoreImpl::Sync(const std::vector &devices, SyncMode mode, const DataQuery &query, + bool isRetry, std::shared_ptr syncCallback) +{ + DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__)); + KVDBService::SyncInfo syncInfo; + syncInfo.seqId = StoreUtil::GenSequenceId(); + syncInfo.mode = mode; + syncInfo.devices = devices; + syncInfo.query = query.ToString(); + syncInfo.isRetry = isRetry; + return DoSync(syncInfo, syncCallback); +} + Status SingleStoreImpl::CloudSync(const AsyncDetail &async) { DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__)); @@ -1101,7 +1114,7 @@ bool SingleStoreImpl::IsRebuild() void SingleStoreImpl::ReportDBFaultEvent(Status status, const std::string &functionName) const { Options options = { .encrypt = encrypt_, .autoSync = autoSync_, .securityLevel = securityLevel_, - .area = area_, .hapName = hapName_ }; + .area = area_, .hapName = hapName_, .baseDir = path_ }; ReportInfo reportInfo = { .options = options, .errorCode = status, .systemErrorNo = errno, .appId = appId_, .storeId = storeId_, .functionName = functionName }; KVDBFaultHiViewReporter::ReportKVFaultEvent(reportInfo); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp index e15c248cbe0092d0da06b79844ca7a1d6e2b5a94..e815ad2a9b47b83ed43f466c1f4a8e5867e66658 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp @@ -116,7 +116,8 @@ std::shared_ptr StoreFactory::GetOrOpenStore(const AppId &appId, status = StoreUtil::ConvertStatus(dbStatus); if (kvStore == nullptr) { ZLOGE("Failed! status:%{public}d appId:%{public}s storeId:%{public}s path:%{public}s", dbStatus, - appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), path.c_str()); + appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), + StoreUtil::Anonymous(path).c_str()); return !stores.empty(); } stores[key] = kvStore; @@ -133,9 +134,11 @@ Status StoreFactory::Delete(const AppId &appId, const StoreId &storeId, const st { Close(appId, storeId, subUser, true); auto dbManager = GetDBManager(path, appId, subUser); - auto status = dbManager->DeleteKvStore(storeId); - SecurityManager::GetInstance().DelDBPassword(storeId.storeId, path); - return StoreUtil::ConvertStatus(status); + Status status = StoreUtil::ConvertStatus(dbManager->DeleteKvStore(storeId)); + if (status == SUCCESS) { + SecurityManager::GetInstance().DelDBPassword(storeId.storeId, path); + } + return status; } Status StoreFactory::Close(const AppId &appId, const StoreId &storeId, int32_t subUser, bool isForce) @@ -193,6 +196,7 @@ StoreFactory::DBOption StoreFactory::GetDBOption(const Options &options, const D dbOption.rdconfig.readOnly = (options.role == VISITOR ? true : false); dbOption.isMemoryDb = (!options.persistent); dbOption.isEncryptedDb = options.encrypt; + dbOption.localOnly = !options.isClientSync; if (options.encrypt) { dbOption.cipher = DistributedDB::CipherType::AES_256_GCM; dbOption.passwd = dbPassword.password; @@ -204,12 +208,12 @@ StoreFactory::DBOption StoreFactory::GetDBOption(const Options &options, const D dbOption.conflictResolvePolicy = DistributedDB::LAST_WIN; } else if (options.kvStoreType == KvStoreType::LOCAL_ONLY) { dbOption.storageEngineType = DistributedDB::GAUSSDB_RD; + dbOption.localOnly = false; } dbOption.schema = options.schema; dbOption.createDirByStoreIdOnly = true; dbOption.secOption = StoreUtil::GetDBSecurity(options.securityLevel); - dbOption.localOnly = !options.syncable; dbOption.rdconfig.type = StoreUtil::GetDBIndexType(options.config.type); dbOption.rdconfig.pageSize = options.config.pageSize; dbOption.rdconfig.cacheSize = options.config.cacheSize; @@ -249,9 +253,9 @@ Status StoreFactory::RekeyRecover(const std::string &storeId, const std::string std::shared_ptr dbManager, const Options &options) { auto rekeyPath = path + "/rekey"; - auto keyName = path + "/key/" + storeId + ".key"; + auto keyName = path + "/key/" + storeId + ".key_v1"; auto reKeyFile = storeId + REKEY_NEW; - auto rekeyName = path + "/rekey/key/" + reKeyFile + ".key"; + auto rekeyName = path + "/rekey/key/" + reKeyFile + ".key_v1"; Status pwdValid = DB_ERROR; if (StoreUtil::IsFileExist(keyName)) { dbPassword = SecurityManager::GetInstance().GetDBPassword(storeId, path); @@ -293,7 +297,7 @@ bool StoreFactory::ExecuteRekey(const std::string &storeId, const std::string &p DBStore *dbStore) { std::string rekeyPath = path + "/rekey"; - std::string rekeyName = rekeyPath + "/key/" + storeId + REKEY_NEW + ".key"; + std::string rekeyName = rekeyPath + "/key/" + storeId + REKEY_NEW + ".key_v1"; (void)StoreUtil::InitPath(rekeyPath); auto newDbPassword = SecurityManager::GetInstance().GetDBPassword(storeId + REKEY_NEW, rekeyPath, true); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp index 5a8230b45b954eb13220740db2e7ba8d74cc637e..1484e74f4382c2d9611b6dd32117243d6f4d55a0 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp @@ -18,6 +18,7 @@ #include "backup_manager.h" #include "dev_manager.h" #include "kvdb_service_client.h" +#include "kvstore_service_death_notifier.h" #include "log_print.h" #include "security_manager.h" @@ -34,7 +35,8 @@ std::shared_ptr StoreManager::GetKVStore(const AppId &appId, cons { std::string path = options.GetDatabaseDir(); ZLOGD("appId:%{public}s, storeId:%{public}s type:%{public}d area:%{public}d dir:%{public}s", appId.appId.c_str(), - StoreUtil::Anonymous(storeId.storeId).c_str(), options.kvStoreType, options.area, path.c_str()); + StoreUtil::Anonymous(storeId.storeId).c_str(), options.kvStoreType, options.area, + StoreUtil::Anonymous(path).c_str()); status = ILLEGAL_STATE; if (!appId.IsValid() || !storeId.IsValid() || !options.IsValidType()) { ZLOGE("Params invalid type"); @@ -146,18 +148,16 @@ Status StoreManager::GetStoreIds(const AppId &appId, std::vector &store Status StoreManager::Delete(const AppId &appId, const StoreId &storeId, const std::string &path, int32_t subUser) { ZLOGD("appId:%{public}s, storeId:%{public}s dir:%{public}s", appId.appId.c_str(), - StoreUtil::Anonymous(storeId.storeId).c_str(), path.c_str()); + StoreUtil::Anonymous(storeId.storeId).c_str(), StoreUtil::Anonymous(path).c_str()); if (!appId.IsValid() || !storeId.IsValid()) { return INVALID_ARGUMENT; } - auto service = KVDBServiceClient::GetInstance(); if (service != nullptr) { service->Delete(appId, storeId, subUser); } auto status = StoreFactory::GetInstance().Delete(appId, storeId, path, subUser); - Options options = { .baseDir = path }; - ReportInfo reportInfo = { .options = options, .errorCode = status, .systemErrorNo = errno, + ReportInfo reportInfo = { .options = { .baseDir = path }, .errorCode = status, .systemErrorNo = errno, .appId = appId.appId, .storeId = storeId.storeId, .functionName = std::string(__FUNCTION__) }; if (status != SUCCESS) { KVDBFaultHiViewReporter::ReportKVFaultEvent(reportInfo); @@ -183,7 +183,7 @@ Status StoreManager::PutSwitch(const AppId &appId, const SwitchData &data) std::pair StoreManager::GetSwitch(const AppId &appId, const std::string &networkId) { ZLOGD("appId:%{public}s, networkId:%{public}s", appId.appId.c_str(), StoreUtil::Anonymous(networkId).c_str()); - if (!appId.IsValid() || DevManager::GetInstance().ToUUID(networkId).empty()) { + if (!appId.IsValid() || networkId.empty()) { return { INVALID_ARGUMENT, SwitchData() }; } auto service = KVDBServiceClient::GetInstance(); @@ -214,6 +214,14 @@ Status StoreManager::SubscribeSwitchData(const AppId &appId, std::shared_ptrAddSwitchCallback(appId.appId, observer); + switchObservers_.Compute(appId.appId, [appId, observer](auto &, auto &switchBridge) { + if (switchBridge == nullptr) { + switchBridge = std::make_shared(appId); + KvStoreServiceDeathNotifier::AddServiceDeathWatcher(switchBridge); + } + switchBridge->AddSwitchCallback(observer); + return true; + }); return SUCCESS; } @@ -236,6 +244,12 @@ Status StoreManager::UnsubscribeSwitchData(const AppId &appId, std::shared_ptrDeleteSwitchCallback(appId.appId, observer); + switchObservers_.ComputeIfPresent(appId.appId, [appId, observer](auto &, auto &switchBridge) { + if (switchBridge != nullptr) { + switchBridge->DeleteSwitchCallback(observer); + } + return true; + }); return SUCCESS; } -} // namespace OHOS::DistributedKv \ No newline at end of file +} \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_util.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_util.cpp index 0aee2fe1916d8db3bffb6d2d1d831f6c08bd5008..5b260b0dcc2445b737f729c285778a7455a665e8 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_util.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_util.cpp @@ -27,9 +27,9 @@ constexpr mode_t DEFAULT_UMASK = 0002; constexpr int32_t HEAD_SIZE = 3; constexpr int32_t END_SIZE = 3; constexpr int32_t MIN_SIZE = HEAD_SIZE + END_SIZE + 3; +constexpr int32_t SERVICE_GID = 3012; constexpr const char *REPLACE_CHAIN = "***"; constexpr const char *DEFAULT_ANONYMOUS = "******"; -constexpr int32_t SERVICE_GID = 3012; std::atomic StoreUtil::sequenceId_ = 0; using DBStatus = DistributedDB::DBStatus; std::map StoreUtil::statusMap_ = { @@ -159,7 +159,7 @@ bool StoreUtil::InitPath(const std::string &path) return RemoveRWXForOthers(path); } if (mkdir(path.c_str(), (S_IRWXU | S_IRWXG)) != 0 && errno != EEXIST) { - ZLOGE("Mkdir error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("Mkdir error:%{public}d, path:%{public}s", errno, Anonymous(path).c_str()); return false; } Acl acl(path); @@ -174,9 +174,9 @@ bool StoreUtil::CreateFile(const std::string &name) if (access(name.c_str(), F_OK) == 0) { return RemoveRWXForOthers(name); } - int fp = open(name.c_str(), (O_WRONLY | O_CREAT), (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP)); + int fp = open(name.c_str(), (O_WRONLY | O_CREAT), (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)); if (fp < 0) { - ZLOGE("Fopen error:%{public}d, path:%{public}s", errno, name.c_str()); + ZLOGE("Fopen error:%{public}d, path:%{public}s", errno, Anonymous(name).c_str()); return false; } close(fp); @@ -188,7 +188,7 @@ std::vector StoreUtil::GetSubPath(const std::string &path) std::vector subPaths; DIR *dirp = opendir(path.c_str()); if (dirp == nullptr) { - ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, Anonymous(path).c_str()); return subPaths; } struct dirent *dp; @@ -206,7 +206,7 @@ std::vector StoreUtil::GetFiles(const std::string &path) std::vector fileInfos; DIR *dirp = opendir(path.c_str()); if (dirp == nullptr) { - ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, Anonymous(path).c_str()); return fileInfos; } struct dirent *dp; @@ -235,7 +235,8 @@ bool StoreUtil::Rename(const std::string &oldName, const std::string &newName) return false; } if (rename(oldName.c_str(), newName.c_str()) != 0) { - ZLOGE("The rename error:%{public}d, file:%{public}s->%{public}s", errno, oldName.c_str(), newName.c_str()); + ZLOGE("The rename error:%{public}d, file:%{public}s->%{public}s", errno, + Anonymous(oldName).c_str(), Anonymous(newName).c_str()); return false; } return true; @@ -258,7 +259,7 @@ bool StoreUtil::Remove(const std::string &path) return true; } if (remove(path.c_str()) != 0) { - ZLOGE("The remove error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("The remove error:%{public}d, path:%{public}s", errno, Anonymous(path).c_str()); return false; } return true; @@ -282,7 +283,7 @@ bool StoreUtil::RemoveRWXForOthers(const std::string &path) { struct stat buf; if (stat(path.c_str(), &buf) < 0) { - ZLOGI("The stat error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGI("The stat error:%{public}d, path:%{public}s", errno, Anonymous(path).c_str()); return true; } @@ -293,7 +294,7 @@ bool StoreUtil::RemoveRWXForOthers(const std::string &path) if (S_ISDIR(buf.st_mode)) { DIR *dirp = opendir(path.c_str()); if (dirp == nullptr) { - ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, Anonymous(path).c_str()); return false; } struct dirent *dp = nullptr; @@ -310,7 +311,7 @@ bool StoreUtil::RemoveRWXForOthers(const std::string &path) } if (chmod(path.c_str(), (buf.st_mode & ~S_IRWXO)) < 0) { - ZLOGE("The chmod error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("The chmod error:%{public}d, path:%{public}s", errno, Anonymous(path).c_str()); return false; } return true; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/task_executor.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/task_executor.cpp index af13f8c92f568ca9bc76f3409d5d20d400c01466..af4540d99a39b3d2f1c76c653f68bc33c8a7cc67 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/task_executor.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/task_executor.cpp @@ -77,7 +77,7 @@ void TaskExecutor::GenerateExecutors() { std::lock_guard lock(mtx_); if (pool_ == nullptr) { - pool_ = std::make_shared(MAX_THREADS, MIN_THREADS); + pool_ = std::make_shared(MAX_THREADS, MIN_THREADS, "TaskExecutor_KV"); } } } // namespace OHOS diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn b/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn index e05c20b25b1af5236c1b9bd0e2c45399c2cb7fb5..eb36f150baf75feb70270e9a70e51f686c349f6f 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn @@ -55,6 +55,7 @@ ohos_source_set("kvdb_src_file") { "../../distributeddatafwk/src/kvstore_datashare_bridge.cpp", "../../distributeddatafwk/src/kvstore_observer_client.cpp", "../../distributeddatafwk/src/kvstore_service_death_notifier.cpp", + "../../distributeddatafwk/src/switch_observer_bridge.cpp", "../../distributeddatafwk/src/sync_observer.cpp", ] @@ -112,7 +113,7 @@ ohos_source_set("kvdb_src_file") { "data_share:datashare_common", "data_share:datashare_provider", ] - + subsystem_name = "distributeddatamgr" part_name = "kv_store" } @@ -127,8 +128,12 @@ ohos_unittest("SingleStoreImplTest") { configs = [ ":module_private_config" ] external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", + "access_token:libnativetoken", "c_utils:utils", "device_manager:devicemanagersdk", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", @@ -143,7 +148,6 @@ ohos_unittest("SingleStoreImplTest") { deps = [ ":kvdb_src_file", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", ] } @@ -159,6 +163,7 @@ ohos_unittest("StoreUtilTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", @@ -168,7 +173,6 @@ ohos_unittest("StoreUtilTest") { deps = [ ":kvdb_src_file", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", ] } @@ -184,6 +188,7 @@ ohos_unittest("BackupManagerTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", @@ -193,7 +198,6 @@ ohos_unittest("BackupManagerTest") { deps = [ ":kvdb_src_file", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", ] } @@ -209,6 +213,7 @@ ohos_unittest("DevManagerTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", @@ -218,7 +223,6 @@ ohos_unittest("DevManagerTest") { deps = [ ":kvdb_src_file", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", ] } @@ -236,6 +240,7 @@ ohos_unittest("DevManagerMockTest") { external_deps = [ "c_utils:utils", "device_manager:devicemanagersdk", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", @@ -245,7 +250,6 @@ ohos_unittest("DevManagerMockTest") { deps = [ ":kvdb_src_file", "${kv_store_base_path}/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", ] } @@ -261,6 +265,7 @@ ohos_unittest("SingleStoreImplGetTopTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", @@ -270,7 +275,6 @@ ohos_unittest("SingleStoreImplGetTopTest") { deps = [ ":kvdb_src_file", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", ] } @@ -286,7 +290,9 @@ ohos_unittest("StoreFactoryTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", + "huks:libhukssdk", "ipc:ipc_single", "safwk:system_ability_fwk", "samgr:samgr_proxy", @@ -295,7 +301,6 @@ ohos_unittest("StoreFactoryTest") { deps = [ ":kvdb_src_file", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", ] } @@ -308,6 +313,7 @@ ohos_unittest("SecurityManagerTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "huks:libhukssdk", "ipc:ipc_single", @@ -318,57 +324,6 @@ ohos_unittest("SecurityManagerTest") { deps = [ ":kvdb_src_file", "../../../libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", - ] -} - -ohos_unittest("SingleStorePerfPcTest") { - module_out_path = module_output_path - - sources = [ - "../../kvdb/src/kv_hiview_reporter_mock.cpp", - "single_store_perf_pc_test.cpp", - ] - - configs = [ ":module_private_config" ] - - external_deps = [ - "c_utils:utils", - "hilog:libhilog", - "ipc:ipc_single", - "safwk:system_ability_fwk", - "samgr:samgr_proxy", - ] - - deps = [ - ":kvdb_src_file", - "${kv_store_base_path}/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", - ] -} - -ohos_unittest("SingleStorePerfPhoneTest") { - module_out_path = module_output_path - - sources = [ - "../../kvdb/src/kv_hiview_reporter_mock.cpp", - "single_store_perf_phone_test.cpp", - ] - - configs = [ ":module_private_config" ] - - external_deps = [ - "c_utils:utils", - "hilog:libhilog", - "ipc:ipc_single", - "safwk:system_ability_fwk", - "samgr:samgr_proxy", - ] - - deps = [ - ":kvdb_src_file", - "${kv_store_base_path}/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", ] } @@ -382,6 +337,7 @@ ohos_unittest("StoreFactoryMockTest") { "../../distributeddatafwk/src/kvstore_observer_client.cpp", "../../distributeddatafwk/src/kvstore_service_death_notifier.cpp", "../../distributeddatafwk/src/sync_observer.cpp", + "../../distributeddatafwk/src/switch_observer_bridge.cpp", "../../kvdb/src/kv_hiview_reporter_mock.cpp", "../src/backup_manager.cpp", "../src/convertor.cpp", @@ -457,6 +413,7 @@ ohos_unittest("SingleStoreImplMockTest") { "../../distributeddatafwk/src/kvstore_datashare_bridge.cpp", "../../distributeddatafwk/src/kvstore_observer_client.cpp", "../../distributeddatafwk/src/kvstore_service_death_notifier.cpp", + "../../distributeddatafwk/src/switch_observer_bridge.cpp", "../../distributeddatafwk/src/sync_observer.cpp", "../../kvdb/src/kv_hiview_reporter_mock.cpp", "../src/backup_manager.cpp", @@ -529,6 +486,35 @@ ohos_unittest("SingleStoreImplMockTest") { use_exceptions = true } +ohos_unittest("KvHiviewReporterTest") { + module_out_path = module_output_path + sources = [ + "../../kvdb/src/kv_hiview_reporter.cpp", + "./mock/src/hisysevent_mock.cpp", + "kv_hiview_reporter_test.cpp", + "../src/store_util.cpp", + ] + configs = [ ":module_private_config" ] + deps = [ + "${kv_store_base_path}/frameworks/libs/distributeddb:distributeddb", + "${kv_store_base_path}/interfaces/innerkits/distributeddata:distributeddata_inner", + "${kv_store_base_path}/databaseutils:database_utils", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "hisysevent:libhisysevent", + "googletest:gmock_main", + "googletest:gtest_main", + ] + + defines = [ + "private=public", + "protected=public", + ] +} + ############################################################################### group("unittest") { testonly = true @@ -544,15 +530,9 @@ group("unittest") { ":StoreFactoryMockTest", ":StoreFactoryTest", ":StoreUtilTest", + ":KvHiviewReporterTest", ] - if (false) { - deps += [ - ":SingleStorePerfPcTest", - ":SingleStorePerfPhoneTest", - ] - } - if (!use_libfuzzer) { deps += [ ":SecurityManagerTest" ] } diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/backup_manager_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/backup_manager_test.cpp index fba0ad58ce5dfdbf3e658b4e0670d8f029381d5b..b8f0ef88b192fb2384122d0a4be39319834f82fd 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/backup_manager_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/backup_manager_test.cpp @@ -496,7 +496,7 @@ HWTEST_F(BackupManagerTest, RestoreEncryptWithKeyFromService, TestSize.Level0) ASSERT_EQ(status, SUCCESS); // delete backup key - auto ret = remove((baseDir + "/key/Prefix_backup_SingleKVStoreEncrypt_testbackup.key").c_str()); + auto ret = remove((baseDir + "/key/Prefix_backup_SingleKVStoreEncrypt_testbackup.key_v1").c_str()); ASSERT_EQ(ret, 0); status = kvStoreEncrypt->Delete("Put Test"); ASSERT_EQ(status, SUCCESS); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/dev_manager_mock_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/dev_manager_mock_test.cpp index b84cdc1beca83bc7aeeda0b4f191e376e76de853..1cf1fb19b9bee8eb1f632dc85222eef39a260a6d 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/dev_manager_mock_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/dev_manager_mock_test.cpp @@ -47,8 +47,6 @@ void DevManagerMockTest::TearDown(void) { } * @tc.name: GetUnEncryptedUuid * @tc.desc: test GetUnEncryptedUuid get local device info fail * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL */ HWTEST_F(DevManagerMockTest, GetUnEncryptedUuid001, TestSize.Level1) { @@ -61,8 +59,6 @@ HWTEST_F(DevManagerMockTest, GetUnEncryptedUuid001, TestSize.Level1) * @tc.name: GetUnEncryptedUuid * @tc.desc: test GetUnEncryptedUuid networkid empty * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL */ HWTEST_F(DevManagerMockTest, GetUnEncryptedUuid002, TestSize.Level1) { @@ -75,8 +71,6 @@ HWTEST_F(DevManagerMockTest, GetUnEncryptedUuid002, TestSize.Level1) * @tc.name: GetLocalDevice * @tc.desc: test GetLocalDevice get local device info fail * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL */ HWTEST_F(DevManagerMockTest, GetLocalDevice, TestSize.Level1) { @@ -89,8 +83,6 @@ HWTEST_F(DevManagerMockTest, GetLocalDevice, TestSize.Level1) * @tc.name: GetRemoteDevices001 * @tc.desc: test GetRemoteDevices get trusted device fail * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL */ HWTEST_F(DevManagerMockTest, GetRemoteDevices001, TestSize.Level1) { @@ -103,8 +95,6 @@ HWTEST_F(DevManagerMockTest, GetRemoteDevices001, TestSize.Level1) * @tc.name: GetRemoteDevices002 * @tc.desc: test GetRemoteDevices get trusted device no remote device * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL */ HWTEST_F(DevManagerMockTest, GetRemoteDevices002, TestSize.Level1) { diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/kv_hiview_reporter_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/kv_hiview_reporter_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5424c2134c93d5678a7e6c3c0df0c27ebcbd27fa --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/kv_hiview_reporter_test.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2025 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 "KvHiviewReporterTest" +#include + +#include "include/hisysevent_mock.h" +#include "kv_hiview_reporter.h" +#include "log_print.h" +#include "types.h" +#include + +namespace OHOS::Test { +using namespace testing; +using namespace testing::ext; +using namespace OHOS::DistributedKv; + +static constexpr const char *BASE_DIR = "/data/service/el1/public/database/KvHiviewReporterTest/"; +static constexpr const char *STOREID = "test_storeId"; +static constexpr const char *DB_CORRUPTED_POSTFIX = ".corruptedflg"; + +class KvHiviewReporterTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + + void SetUp(); + void TearDown(); +}; + +void KvHiviewReporterTest::SetUpTestCase(void) +{ + auto ret = mkdir(BASE_DIR, (S_IRWXU)); + if (ret != 0) { + ZLOGE("Mkdir failed, result:%{public}d, path:%{public}s", ret, BASE_DIR); + } +} + +void KvHiviewReporterTest::TearDownTestCase(void) +{ + auto ret = remove(BASE_DIR); + if (ret != 0) { + ZLOGE("Remove failed, result:%{public}d, path:%{public}s", ret, BASE_DIR); + } +} + +void KvHiviewReporterTest::SetUp(void) { } + +void KvHiviewReporterTest::TearDown(void) { } + +/** + * @tc.name: CorruptedFlagTest001 + * @tc.desc: Create and delete corrupted flag + * @tc.type: FUNC + */ +HWTEST_F(KvHiviewReporterTest, CorruptedFlagTest001, TestSize.Level1) +{ + ZLOGI("CorruptedFlagTest001 begin."); + KVDBFaultHiViewReporter::CreateCorruptedFlag(BASE_DIR, STOREID); + std::string flagFilename = std::string(BASE_DIR) + std::string(STOREID) + std::string(DB_CORRUPTED_POSTFIX); + auto ret = access(flagFilename.c_str(), F_OK); + ASSERT_EQ(ret, 0); + KVDBFaultHiViewReporter::DeleteCorruptedFlag(BASE_DIR, STOREID); + ret = access(flagFilename.c_str(), F_OK); + ASSERT_NE(ret, 0); +} + +/** + * @tc.name: ReportKVFaultEvent001 + * @tc.desc: Execute the ReportFaultEvent method + * @tc.type: FUNC + */ +HWTEST_F(KvHiviewReporterTest, ReportKVFaultEvent001, TestSize.Level1) +{ + ZLOGI("ReportKVFaultEvent001 begin."); + HiSysEventMock mock; + EXPECT_CALL(mock, HiSysEvent_Write(_, _, _, _, _, _, _)).Times(1); + ReportInfo reportInfo; + KVDBFaultHiViewReporter::ReportKVFaultEvent(reportInfo); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/gdb/include/gdb_helper.h b/kv_store/frameworks/innerkitsimpl/kvdb/test/mock/include/hisysevent_mock.h similarity index 49% rename from relational_store/interfaces/inner_api/gdb/include/gdb_helper.h rename to kv_store/frameworks/innerkitsimpl/kvdb/test/mock/include/hisysevent_mock.h index f3f3e7f14a79687c617e67b06cd456f782b284b1..101037a2657f227ff4c525726ef43c4c75dbea7f 100644 --- a/relational_store/interfaces/inner_api/gdb/include/gdb_helper.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/mock/include/hisysevent_mock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 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,19 +13,30 @@ * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_DB_HELPER_H -#define OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_DB_HELPER_H -#include +#ifndef HISYSEVENT_MOCK_H +#define HISYSEVENT_MOCK_H -#include "gdb_store_config.h" -#include "gdb_store.h" -#include "rdb_visibility.h" +#include +#include +#include -namespace OHOS::DistributedDataAip { -class GDBHelper { +#include "hisysevent_c.h" +class HiSysEventMock { public: - API_EXPORT static std::shared_ptr GetDBStore(const StoreConfig &config, int &errCode); - API_EXPORT static int DeleteDBStore(const StoreConfig &config); + static HiSysEventMock *GetMock() + { + return mock.load(); + } + + HiSysEventMock(); + ~HiSysEventMock(); + + MOCK_METHOD7(HiSysEvent_Write, + int(const char *func, int64_t line, const char *domain, const char *name, HiSysEventEventType type, + const HiSysEventParam params[], size_t size)); + +private: + static inline std::atomic mock = nullptr; }; -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_DB_HELPER_H + +#endif // HISYSEVENT_MOCK_H diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/mock/src/hisysevent_mock.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/mock/src/hisysevent_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0023df3220fe94f8b606001ce956a18762dca643 --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/mock/src/hisysevent_mock.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 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/hisysevent_mock.h" +#include + +HiSysEventMock::HiSysEventMock() +{ + mock.store(this); +} +HiSysEventMock::~HiSysEventMock() +{ + mock.store(nullptr); +} + +int HiSysEvent_Write(const char *func, int64_t line, const char *domain, const char *name, HiSysEventEventType type, + const HiSysEventParam params[], size_t size) +{ + return HiSysEventMock::GetMock()->HiSysEvent_Write(func, line, domain, name, type, params, size); +} diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/security_manager_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/security_manager_test.cpp index 23898f55b5030c9b88f53bb5d21e707753028c7b..4492ee6f7584c94b164eacec0843bcb98c004b4d 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/security_manager_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/security_manager_test.cpp @@ -13,52 +13,462 @@ * limitations under the License. */ +#include "security_manager.h" + #include +#include + #include "block_data.h" -#include "log_print.h" -#include "security_manager.h" +#include "file_ex.h" +#include "hks_api.h" +#include "hks_param.h" #include "store_util.h" namespace OHOS::Test { using namespace testing::ext; using namespace OHOS::DistributedKv; + +static constexpr int32_t KEY_SIZE = 32; +static constexpr int32_t NONCE_SIZE = 12; +static constexpr int32_t LOOP_NUM = 2; +static constexpr const char *STORE_NAME = "test_store"; +static constexpr const char *BASE_DIR = "/data/service/el1/public/database/SecurityManagerTest"; +static constexpr const char *KEY_DIR = "/data/service/el1/public/database/SecurityManagerTest/key"; +static constexpr const char *KEY_FULL_PATH = "/data/service/el1/public/database/SecurityManagerTest/key/test_store.key"; +static constexpr const char *KEY_FULL_PATH_V1 = + "/data/service/el1/public/database/SecurityManagerTest/key/test_store.key_v1"; +static constexpr const char *LOCK_FULL_PATH = + "/data/service/el1/public/database/SecurityManagerTest/key/test_store.key_lock"; +static constexpr const char *ROOT_KEY_ALIAS = "distributeddb_client_root_key"; +static constexpr const char *HKS_BLOB_TYPE_NONCE = "Z5s0Bo571KoqwIi6"; +static constexpr const char *HKS_BLOB_TYPE_AAD = "distributeddata_client"; + class SecurityManagerTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); void SetUp(); void TearDown(); + + static std::vector Random(int32_t length); + static std::vector Encrypt(const std::vector &key, const std::vector &nonce); + static bool SaveKeyToOldFile(const std::vector &key); + static void GenerateRootKey(); + static void DeleteRootKey(); + + static std::vector vecRootKeyAlias_; + static std::vector vecNonce_; + static std::vector vecAad_; }; -void SecurityManagerTest::SetUpTestCase(void) { } +std::vector SecurityManagerTest::vecRootKeyAlias_ = + std::vector(ROOT_KEY_ALIAS, ROOT_KEY_ALIAS + strlen(ROOT_KEY_ALIAS)); +std::vector SecurityManagerTest::vecNonce_ = + std::vector(HKS_BLOB_TYPE_NONCE, HKS_BLOB_TYPE_NONCE + strlen(HKS_BLOB_TYPE_NONCE)); +std::vector SecurityManagerTest::vecAad_ = + std::vector(HKS_BLOB_TYPE_AAD, HKS_BLOB_TYPE_AAD + strlen(HKS_BLOB_TYPE_AAD)); + +void SecurityManagerTest::SetUpTestCase(void) +{ + mkdir(BASE_DIR, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + GenerateRootKey(); +} + +void SecurityManagerTest::TearDownTestCase(void) +{ + DeleteRootKey(); + (void)remove(BASE_DIR); +} + +void SecurityManagerTest::SetUp() +{ + mkdir(KEY_DIR, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); +} + +void SecurityManagerTest::TearDown() +{ + (void)remove(LOCK_FULL_PATH); + (void)remove(KEY_FULL_PATH); + (void)remove(KEY_FULL_PATH_V1); + (void)remove(KEY_DIR); +} + +std::vector SecurityManagerTest::Random(int32_t length) +{ + std::vector value(length, 0); + struct HksBlob blobValue = { .size = length, .data = &(value[0]) }; + auto ret = HksGenerateRandom(nullptr, &blobValue); + if (ret != HKS_SUCCESS) { + return {}; + } + return value; +} + +std::vector SecurityManagerTest::Encrypt(const std::vector &key, const std::vector &nonce) +{ + struct HksBlob blobAad = { uint32_t(vecAad_.size()), vecAad_.data() }; + struct HksBlob blobNonce = { uint32_t(nonce.size()), const_cast(nonce.data()) }; + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() }; + struct HksBlob plainKey = { uint32_t(key.size()), const_cast(key.data()) }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + return {}; + } + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_NONCE, .blob = blobNonce }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, + }; + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return {}; + } + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return {}; + } + uint8_t cipherBuf[256] = { 0 }; + struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf }; + ret = HksEncrypt(&rootKeyName, params, &plainKey, &cipherText); + (void)HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + return {}; + } + std::vector encryptedKey(cipherText.data, cipherText.data + cipherText.size); + std::fill(cipherBuf, cipherBuf + sizeof(cipherBuf), 0); + return encryptedKey; +} + +bool SecurityManagerTest::SaveKeyToOldFile(const std::vector &key) +{ + auto encryptKey = Encrypt(key, vecNonce_); + if (encryptKey.empty()) { + return false; + } + std::vector content; + auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now()); + std::vector date(reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time)); + content.push_back(char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE)); + content.insert(content.end(), date.begin(), date.end()); + content.insert(content.end(), encryptKey.begin(), encryptKey.end()); + return SaveBufferToFile(KEY_FULL_PATH, content); +} -void SecurityManagerTest::TearDownTestCase(void) { } +void SecurityManagerTest::GenerateRootKey() +{ + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + return; + } + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, + }; + + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return; + } -void SecurityManagerTest::SetUp(void) { } + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return; + } + ret = HksGenerateKey(&rootKeyName, params, nullptr); + HksFreeParamSet(¶ms); +} + +void SecurityManagerTest::DeleteRootKey() +{ + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + return; + } + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, + }; + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return; + } + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return; + } + ret = HksDeleteKey(&rootKeyName, params); + HksFreeParamSet(¶ms); +} -void SecurityManagerTest::TearDown(void) { } +/** + * @tc.name: GetDBPasswordTest001 + * @tc.desc: get password with first create and needCreate is false + * @tc.type: FUNC + */ +HWTEST_F(SecurityManagerTest, GetDBPasswordTest001, TestSize.Level0) +{ + auto dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); +} /** - * @tc.name: DBPasswordTest - * @tc.desc: Test DBPassword function + * @tc.name: GetDBPasswordTest002 + * @tc.desc: get password with key file exist and the key file is empty * @tc.type: FUNC */ -HWTEST_F(SecurityManagerTest, DBPasswordTest, TestSize.Level1) +HWTEST_F(SecurityManagerTest, GetDBPasswordTest002, TestSize.Level0) { - SecurityManager::DBPassword passwd; - EXPECT_FALSE(passwd.IsValid()); - std::vector key = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F - }; - passwd.SetValue(key.data(), key.size()); - EXPECT_TRUE(passwd.IsValid()); - EXPECT_EQ(passwd.GetSize(), 32); - auto newKey = passwd.GetData(); - EXPECT_EQ(newKey[0], 0x00); - passwd.Clear(); - EXPECT_FALSE(passwd.IsValid()); + std::vector content; + auto result = SaveBufferToFile(KEY_FULL_PATH, content); + ASSERT_TRUE(result); + + auto dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + result = SaveBufferToFile(KEY_FULL_PATH_V1, content); + ASSERT_TRUE(result); + + dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + SecurityManager::GetInstance().DelDBPassword(STORE_NAME, BASE_DIR); +} + +/** + * @tc.name: GetDBPasswordTest003 + * @tc.desc: get password with old key file exist and the old key file is invalid + * @tc.type: FUNC + */ +HWTEST_F(SecurityManagerTest, GetDBPasswordTest003, TestSize.Level0) +{ + auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now()); + std::vector date(reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time)); + // 1.the size of content is invalid + std::vector invalidContent1; + invalidContent1.push_back(char(sizeof(time_t) / sizeof(uint8_t))); + invalidContent1.insert(invalidContent1.end(), date.begin(), date.end()); + auto result = SaveBufferToFile(KEY_FULL_PATH, invalidContent1); + ASSERT_TRUE(result); + auto dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + auto invalidKey = Random(KEY_SIZE); + ASSERT_FALSE(invalidKey.empty()); + // 2.the pos 0 of content is invalid + std::vector invalidContent2; + invalidContent2.push_back(char((sizeof(time_t) / sizeof(uint8_t)))); + invalidContent2.insert(invalidContent2.end(), date.begin(), date.end()); + invalidContent2.insert(invalidContent2.end(), invalidKey.begin(), invalidKey.end()); + result = SaveBufferToFile(KEY_FULL_PATH, invalidContent2); + ASSERT_TRUE(result); + dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + // 3.the key of content decrypt fail + std::vector invalidContent3; + invalidContent3.push_back(char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE)); + invalidContent3.insert(invalidContent3.end(), date.begin(), date.end()); + invalidContent3.insert(invalidContent3.end(), invalidKey.begin(), invalidKey.end()); + result = SaveBufferToFile(KEY_FULL_PATH, invalidContent3); + ASSERT_TRUE(result); + dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + SecurityManager::GetInstance().DelDBPassword(STORE_NAME, BASE_DIR); +} + +/** + * @tc.name: GetDBPasswordTest004 + * @tc.desc: get password with new key file exist and the new key file is invalid + * @tc.type: FUNC + */ +HWTEST_F(SecurityManagerTest, GetDBPasswordTest004, TestSize.Level0) +{ + std::vector content; + + // 1.the size of content is invalid + content.push_back(char(SecurityManager::SecurityContent::MAGIC_CHAR)); + auto result = SaveBufferToFile(KEY_FULL_PATH_V1, content); + ASSERT_TRUE(result); + auto dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + // 2.the size of content is invalid + for (size_t index = 0; index < SecurityManager::SecurityContent::MAGIC_NUM - 1; ++index) { + content.push_back(char(SecurityManager::SecurityContent::MAGIC_CHAR)); + } + result = SaveBufferToFile(KEY_FULL_PATH_V1, content); + ASSERT_TRUE(result); + dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + // 3.the size of content is invalid + auto nonce = Random(NONCE_SIZE); + ASSERT_FALSE(nonce.empty()); + content.insert(content.end(), nonce.begin(), nonce.end()); + result = SaveBufferToFile(KEY_FULL_PATH_V1, content); + ASSERT_TRUE(result); + dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + // 4.the content decrypt fail + auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now()); + std::vector date(reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time)); + std::vector invalidContent = content; + invalidContent.insert(invalidContent.end(), date.begin(), date.end()); + result = SaveBufferToFile(KEY_FULL_PATH_V1, invalidContent); + ASSERT_TRUE(result); + dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + // 5.the content decrypt success and key is empty + std::vector keyContent; + keyContent.push_back(SecurityManager::SecurityContent::CURRENT_VERSION); + keyContent.insert(keyContent.end(), date.begin(), date.end()); + auto encryptValue = Encrypt(keyContent, nonce); + ASSERT_FALSE(encryptValue.empty()); + invalidContent = content; + invalidContent.insert(invalidContent.end(), encryptValue.begin(), encryptValue.end()); + result = SaveBufferToFile(KEY_FULL_PATH_V1, invalidContent); + ASSERT_TRUE(result); + dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + SecurityManager::GetInstance().DelDBPassword(STORE_NAME, BASE_DIR); +} + +/** + * @tc.name: GetDBPasswordTest005 + * @tc.desc: get password with first create and needCreate is true + * @tc.type: FUNC + */ +HWTEST_F(SecurityManagerTest, GetDBPasswordTest005, TestSize.Level0) +{ + auto dbPassword1 = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, true); + ASSERT_TRUE(dbPassword1.IsValid()); + + auto dbPassword2 = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_TRUE(dbPassword2.IsValid()); + + ASSERT_EQ(dbPassword2.GetSize(), dbPassword1.GetSize()); + + std::vector key1(dbPassword1.GetData(), dbPassword1.GetData() + dbPassword1.GetSize()); + std::vector key2(dbPassword2.GetData(), dbPassword2.GetData() + dbPassword2.GetSize()); + ASSERT_EQ(key1.size(), key2.size()); + + for (auto index = 0; index < key1.size(); ++index) { + ASSERT_EQ(key1[index], key2[index]); + } + + key1.assign(key1.size(), 0); + key2.assign(key2.size(), 0); + dbPassword1.Clear(); + dbPassword2.Clear(); + SecurityManager::GetInstance().DelDBPassword(STORE_NAME, BASE_DIR); +} + +/** + * @tc.name: GetDBPasswordTest006 + * @tc.desc: get password with old key file exit and update + * @tc.type: FUNC + */ +HWTEST_F(SecurityManagerTest, GetDBPasswordTest006, TestSize.Level0) +{ + auto key = Random(KEY_SIZE); + ASSERT_FALSE(key.empty()); + auto result = SaveKeyToOldFile(key); + ASSERT_TRUE(result); + + for (auto loop = 0; loop < LOOP_NUM; ++loop) { + auto dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, true); + ASSERT_TRUE(dbPassword.IsValid()); + ASSERT_EQ(dbPassword.GetSize(), key.size()); + std::vector password(dbPassword.GetData(), dbPassword.GetData() + dbPassword.GetSize()); + ASSERT_EQ(password.size(), key.size()); + for (auto index = 0; index < key.size(); ++index) { + ASSERT_EQ(password[index], key[index]); + } + password.assign(password.size(), 0); + dbPassword.Clear(); + } + + key.assign(key.size(), 0); + SecurityManager::GetInstance().DelDBPassword(STORE_NAME, BASE_DIR); +} + +/** + * @tc.name: SaveDBPasswordTest001 + * @tc.desc: save password + * @tc.type: FUNC + */ +HWTEST_F(SecurityManagerTest, SaveDBPasswordTest001, TestSize.Level0) +{ + auto key = Random(KEY_SIZE); + ASSERT_FALSE(key.empty()); + + DistributedDB::CipherPassword dbPassword1; + dbPassword1.SetValue(key.data(), key.size()); + ASSERT_EQ(dbPassword1.GetSize(), key.size()); + auto result = SecurityManager::GetInstance().SaveDBPassword(STORE_NAME, BASE_DIR, dbPassword1); + ASSERT_TRUE(result); + dbPassword1.Clear(); + + auto dbPassword2 = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, true); + ASSERT_TRUE(dbPassword2.IsValid()); + ASSERT_EQ(dbPassword2.GetSize(), key.size()); + std::vector password(dbPassword2.GetData(), dbPassword2.GetData() + dbPassword2.GetSize()); + ASSERT_EQ(password.size(), key.size()); + for (auto index = 0; index < key.size(); ++index) { + ASSERT_EQ(password[index], key[index]); + } + password.assign(password.size(), 0); + dbPassword2.Clear(); + key.assign(key.size(), 0); + SecurityManager::GetInstance().DelDBPassword(STORE_NAME, BASE_DIR); +} + +/** + * @tc.name: DelDBPasswordTest001 + * @tc.desc: delete password + * @tc.type: FUNC + */ +HWTEST_F(SecurityManagerTest, DelDBPasswordTest001, TestSize.Level0) +{ + auto dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, true); + ASSERT_TRUE(dbPassword.IsValid()); + dbPassword.Clear(); + + SecurityManager::GetInstance().DelDBPassword(STORE_NAME, BASE_DIR); + + dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); } /** @@ -72,8 +482,6 @@ HWTEST_F(SecurityManagerTest, KeyFilesMultiLockTest, TestSize.Level1) std::string dbName = "test1"; StoreUtil::InitPath(dbPath); SecurityManager::KeyFiles keyFiles(dbName, dbPath); - auto keyPath = keyFiles.GetKeyFilePath(); - EXPECT_EQ(keyPath, "/data/service/el1/public/database/SecurityManagerTest/key/test1.key"); auto ret = keyFiles.Lock(); EXPECT_EQ(ret, Status::SUCCESS); ret = keyFiles.Lock(); @@ -95,8 +503,6 @@ HWTEST_F(SecurityManagerTest, KeyFilesTest, TestSize.Level1) std::string dbName = "test2"; StoreUtil::InitPath(dbPath); SecurityManager::KeyFiles keyFiles(dbName, dbPath); - auto keyPath = keyFiles.GetKeyFilePath(); - EXPECT_EQ(keyPath, "/data/service/el1/public/database/SecurityManagerTest/key/test2.key"); keyFiles.Lock(); auto blockResult = std::make_shared>(1, false); std::thread thread([dbPath, dbName, blockResult]() { diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_mock_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..24629bb10c5de72274b48fe5b2c43e7c162fad4a --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_mock_test.cpp @@ -0,0 +1,1262 @@ +/* + * 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 +#include + +#include +#include + +#include "include/accesstoken_kit_mock.h" +#include "include/convertor_mock.h" +#include "include/dev_manager_mock.h" +#include "include/kvdb_notifier_client_mock.h" +#include "include/kvdb_service_client_mock.h" +#include "include/observer_bridge_mock.h" +#include "include/task_executor_mock.h" +#include "kvstore_observer.h" +#include "single_store_impl.h" +#include "store_factory.h" +#include "store_manager.h" + +namespace OHOS::DistributedKv { +using namespace std; +using namespace testing; +using namespace DistributedDB; +using namespace Security::AccessToken; + +static StoreId storeId = { "single_test" }; +static AppId appId = { "rekey" }; + +class SingleStoreImplMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + +public: + using DBStatus = DistributedDB::DBStatus; + using DBStore = DistributedDB::KvStoreNbDelegate; + using Observer = DistributedKv::KvStoreObserver; + static inline shared_ptr devManagerMock = nullptr; + static inline shared_ptr kVDBServiceClientMock = nullptr; + static inline shared_ptr kVDBNotifierClientMock = nullptr; + static inline shared_ptr observerBridgeMock = nullptr; + static inline shared_ptr taskExecutorMock = nullptr; + static inline shared_ptr accessTokenKitMock = nullptr; + static inline shared_ptr convertorMock = nullptr; + std::shared_ptr CreateKVStore(bool autosync = false, bool backup = true); +}; + +void SingleStoreImplMockTest::SetUp() { } + +void SingleStoreImplMockTest::TearDown() { } + +void SingleStoreImplMockTest::SetUpTestCase() +{ + GTEST_LOG_(INFO) << "SetUpTestCase enter"; + std::string baseDir = "/data/service/el1/public/database/SingleStoreImplTest"; + mkdir(baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + devManagerMock = make_shared(); + BDevManager::devManager = devManagerMock; + kVDBServiceClientMock = make_shared(); + BKVDBServiceClient::kVDBServiceClient = kVDBServiceClientMock; + kVDBNotifierClientMock = make_shared(); + BKVDBNotifierClient::kVDBNotifierClient = kVDBNotifierClientMock; + observerBridgeMock = make_shared(); + BObserverBridge::observerBridge = observerBridgeMock; + taskExecutorMock = make_shared(); + BTaskExecutor::taskExecutor = taskExecutorMock; + accessTokenKitMock = make_shared(); + BAccessTokenKit::accessTokenKit = accessTokenKitMock; + convertorMock = make_shared(); + BConvertor::convertor = convertorMock; +} + +void SingleStoreImplMockTest::TearDownTestCase() +{ + GTEST_LOG_(INFO) << "TearDownTestCase enter"; + BDevManager::devManager = nullptr; + devManagerMock = nullptr; + BKVDBServiceClient::kVDBServiceClient = nullptr; + kVDBServiceClientMock = nullptr; + BKVDBNotifierClient::kVDBNotifierClient = nullptr; + kVDBNotifierClientMock = nullptr; + BObserverBridge::observerBridge = nullptr; + observerBridgeMock = nullptr; + BTaskExecutor::taskExecutor = nullptr; + taskExecutorMock = nullptr; + BAccessTokenKit::accessTokenKit = nullptr; + accessTokenKitMock = nullptr; + BConvertor::convertor = nullptr; + convertorMock = nullptr; + std::string baseDir = "/data/service/el1/public/database/SingleStoreImplTest"; + (void)remove("/data/service/el1/public/database/SingleStoreImplTest"); +} + +std::shared_ptr SingleStoreImplMockTest::CreateKVStore(bool autosync, bool backup) +{ + AppId appId = { "SingleStoreImplTest" }; + StoreId storeId = { "DestructorTest" }; + std::shared_ptr kvStore; + Options options; + options.kvStoreType = SINGLE_VERSION; + options.securityLevel = S2; + options.area = EL1; + options.autoSync = autosync; + options.baseDir = "/data/service/el1/public/database/SingleStoreImplTest"; + options.backup = backup; + StoreFactory storeFactory; + auto dbManager = storeFactory.GetDBManager(options.baseDir, appId); + auto dbPassword = SecurityManager::GetInstance().GetDBPassword(storeId.storeId, options.baseDir, options.encrypt); + DBStatus dbStatus = DBStatus::DB_ERROR; + dbManager->GetKvStore(storeId, storeFactory.GetDBOption(options, dbPassword), + [&dbManager, &kvStore, &appId, &dbStatus, &options, &storeFactory](auto status, auto *store) { + dbStatus = status; + if (store == nullptr) { + return; + } + auto release = [dbManager](auto *store) { + dbManager->CloseKvStore(store); + }; + auto dbStore = std::shared_ptr(store, release); + storeFactory.SetDbConfig(dbStore); + const Convertor &convertor = *(storeFactory.convertors_[options.kvStoreType]); + kvStore = std::make_shared(dbStore, appId, options, convertor); + }); + return kvStore; +} + +/** + * @tc.name: IsRemoteChanged + * @tc.desc: is remote changed. + * @tc.type: FUNC + * @tc.require: + * @tc.author: cao zhijun + */ +HWTEST_F(SingleStoreImplMockTest, IsRemoteChanged, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin IsRemoteChanged"; + try { + EXPECT_CALL(*taskExecutorMock, Schedule(_, _, _, _)).Times(1); + std::shared_ptr kvStore; + kvStore = CreateKVStore(); + ASSERT_NE(kvStore, nullptr); + std::shared_ptr client = make_shared(nullptr); + ASSERT_NE(client, nullptr); + EXPECT_CALL(*devManagerMock, ToUUID(_)).WillOnce(Return("")); + bool ret = kvStore->IsRemoteChanged("123456789"); + EXPECT_TRUE(ret); + + EXPECT_CALL(*devManagerMock, ToUUID(_)).WillOnce(Return("123456789")); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + ret = kvStore->IsRemoteChanged("123456789"); + EXPECT_TRUE(ret); + + EXPECT_CALL(*devManagerMock, ToUUID(_)).WillOnce(Return("123456789")); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(client)); + EXPECT_CALL(*kVDBServiceClientMock, GetServiceAgent(_)).WillOnce(Return(nullptr)); + ret = kvStore->IsRemoteChanged("123456789"); + EXPECT_TRUE(ret); + + sptr testAgent = new (std::nothrow) KVDBNotifierClient(); + ASSERT_NE(testAgent, nullptr); + EXPECT_CALL(*devManagerMock, ToUUID(_)).WillOnce(Return("123456789")); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(client)); + EXPECT_CALL(*kVDBServiceClientMock, GetServiceAgent(_)).WillOnce(Return(testAgent)); + EXPECT_CALL(*kVDBNotifierClientMock, IsChanged(_, _)).WillOnce(Return(true)); + ret = kvStore->IsRemoteChanged("123456789"); + EXPECT_TRUE(ret); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by IsRemoteChanged."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end IsRemoteChanged"; +} + +/** + * @tc.name: OnRemoteDied + * @tc.desc: remote died. + * @tc.type: FUNC + * @tc.require: + * @tc.author: cao zhijun + */ +HWTEST_F(SingleStoreImplMockTest, OnRemoteDied, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin OnRemoteDied"; + try { + EXPECT_CALL(*taskExecutorMock, Schedule(_, _, _, _)).Times(1); + EXPECT_CALL(*accessTokenKitMock, GetTokenTypeFlag(_)).WillOnce(Return(TOKEN_INVALID)); + std::shared_ptr kvStore; + kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_FALSE(kvStore->isApplication_); + + kvStore->taskId_ = 1; + kvStore->OnRemoteDied(); + + kvStore->taskId_ = 0; + shared_ptr observer = make_shared(); + shared_ptr observer1 = make_shared(); + Convertor cvt; + Convertor cvt1; + shared_ptr obsBridge = make_shared(appId, storeId, 0, observer, cvt); + shared_ptr obsBridge1 = make_shared(appId, storeId, 0, observer1, cvt1); + + uint32_t firs = 0; + firs |= SUBSCRIBE_TYPE_REMOTE; + pair> one(0, obsBridge); + pair> two(firs, obsBridge1); + + kvStore->observers_.Insert(uintptr_t(observer.get()), one); + kvStore->observers_.Insert(uintptr_t(observer1.get()), two); + EXPECT_CALL(*observerBridgeMock, OnServiceDeath()).Times(1); + EXPECT_CALL(*taskExecutorMock, Schedule(_, _, _, _)).WillOnce(Return(1)); + kvStore->OnRemoteDied(); + kvStore->observers_.Erase(uintptr_t(observer.get())); + kvStore->observers_.Erase(uintptr_t(observer1.get())); + EXPECT_TRUE(kvStore->taskId_ == 1); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by OnRemoteDied."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end OnRemoteDied"; +} + +/** + * @tc.name: Register + * @tc.desc: register. + * @tc.type: FUNC + * @tc.require: + * @tc.author: cao zhijun + */ +HWTEST_F(SingleStoreImplMockTest, Register, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Register"; + try { + EXPECT_CALL(*taskExecutorMock, Schedule(_, _, _, _)).Times(1); + EXPECT_CALL(*accessTokenKitMock, GetTokenTypeFlag(_)).WillOnce(Return(TOKEN_HAP)); + std::shared_ptr kvStore; + kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_TRUE(kvStore->isApplication_); + + shared_ptr observer = make_shared(); + shared_ptr observer1 = make_shared(); + Convertor cvt; + Convertor cvt1; + shared_ptr obsBridge = make_shared(appId, storeId, 0, observer, cvt); + shared_ptr obsBridge1 = make_shared(appId, storeId, 0, observer1, cvt1); + + uint32_t firs = 0; + firs |= SUBSCRIBE_TYPE_CLOUD; + pair> one(0, obsBridge); + pair> two(firs, obsBridge1); + + kvStore->observers_.Insert(uintptr_t(observer.get()), one); + kvStore->observers_.Insert(uintptr_t(observer1.get()), two); + EXPECT_CALL(*observerBridgeMock, RegisterRemoteObserver(_)).WillOnce(Return(ERROR)); + EXPECT_CALL(*taskExecutorMock, Schedule(_, _, _, _)).WillOnce(Return(1)); + kvStore->Register(); + EXPECT_TRUE(kvStore->taskId_ == 1); + + EXPECT_CALL(*observerBridgeMock, RegisterRemoteObserver(_)).WillOnce(Return(SUCCESS)); + kvStore->Register(); + kvStore->observers_.Erase(uintptr_t(observer.get())); + kvStore->observers_.Erase(uintptr_t(observer1.get())); + EXPECT_TRUE(kvStore->taskId_ == 0); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Register."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Register"; +} + +/** +* @tc.name: Put_001 +* @tc.desc: Put. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, Put_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Put_001"; + try { + EXPECT_CALL(*taskExecutorMock, Schedule(_, _, _, _)).Times(1); + EXPECT_CALL(*accessTokenKitMock, GetTokenTypeFlag(_)).Times(AnyNumber()); + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + std::vector vect; + EXPECT_CALL(*convertorMock, ToLocalDBKey(_)).WillOnce(Return(vect)); + size_t maxTestKeyLen = 10; + std::string str(maxTestKeyLen, 'a'); + Blob key(str); + Blob value("test_value"); + Status status = kvStore->Put(key, value); + EXPECT_TRUE(status == INVALID_ARGUMENT); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Put_001."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Put_001"; +} + + +/** +* @tc.name: Put_002 +* @tc.desc: Put. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, Put_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Put_002"; + try { + EXPECT_CALL(*taskExecutorMock, Schedule(_, _, _, _)).Times(AnyNumber()); + EXPECT_CALL(*accessTokenKitMock, GetTokenTypeFlag(_)).Times(AnyNumber()); + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + std::vector vect{3, 8}; + EXPECT_CALL(*convertorMock, ToLocalDBKey(_)).WillOnce(Return(vect)); + size_t overlongTestKeyLen = 4 * 1024 * 1024 + 1; + std::string str(overlongTestKeyLen, 'b'); + Blob key1("key1"); + Blob value1(str); + Status status = kvStore->Put(key1, value1); + EXPECT_TRUE(status == INVALID_ARGUMENT); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Put_002."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Put_002"; +} + +/** +* @tc.name: PutBatch_001 +* @tc.desc: PutBatch. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, PutBatch_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin PutBatch_001"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_ = nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + std::vector in; + for (int i = 0; i < 2; ++i) { + Entry entry; + entry.key = std::to_string(i).append("_k"); + entry.value = std::to_string(i).append("_v"); + in.emplace_back(entry); + } + Status status = kvStore->PutBatch(in); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by PutBatch_001."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end PutBatch_001"; +} + +/** +* @tc.name: PutBatch_002 +* @tc.desc: PutBatch. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, PutBatch_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin PutBatch_002"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + std::vector in; + for (int i = 0; i < 2; ++i) { + Entry entry; + entry.key = std::to_string(i).append("_key"); + entry.value = std::to_string(i).append("_val"); + in.emplace_back(entry); + } + std::vector vect; + EXPECT_CALL(*convertorMock, ToLocalDBKey(_)).WillOnce(Return(vect)); + Status status = kvStore->PutBatch(in); + EXPECT_TRUE(status == INVALID_ARGUMENT); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by PutBatch_002."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end PutBatch_002"; +} + +/** +* @tc.name: PutBatch_003 +* @tc.desc: PutBatch. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, PutBatch_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin PutBatch_003"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + std::vector in; + for (int i = 0; i < 2; ++i) { + Entry entry; + entry.key = std::to_string(i).append("_key"); + entry.value = std::to_string(i).append("_val"); + in.emplace_back(entry); + } + std::vector vect; + EXPECT_CALL(*convertorMock, ToLocalDBKey(_)).WillOnce(Return(vect)); + Status status = kvStore->PutBatch(in); + EXPECT_TRUE(status == INVALID_ARGUMENT); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by PutBatch_003."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end PutBatch_003"; +} + +/** +* @tc.name: Delete +* @tc.desc: Delete Key. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, Delete, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Delete"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + Blob key1("key1"); + Status status = kvStore->Delete(key1); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Delete."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Delete"; +} + +/** +* @tc.name: DeleteBatch +* @tc.desc: DeleteBatch Keys. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, DeleteBatch, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin DeleteBatch"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + std::vector keys; + for (int i = 0; i < 2; ++i) { + Key key = std::to_string(i).append("_k"); + keys.emplace_back(key); + } + Status status = kvStore->DeleteBatch(keys); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by DeleteBatch."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end DeleteBatch"; +} + +/** +* @tc.name: StartTransaction +* @tc.desc: Start Transaction. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, StartTransaction, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin StartTransaction"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + Status status = kvStore->StartTransaction(); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by StartTransaction."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end StartTransaction"; +} + +/** +* @tc.name: Commit +* @tc.desc: Commit. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, Commit, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Commit"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + Status status = kvStore->Commit(); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Commit."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Commit"; +} + +/** +* @tc.name: Rollback +* @tc.desc: Rollback kvstore. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, Rollback, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Rollback"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + Status status = kvStore->Rollback(); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Rollback."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Rollback"; +} + +/** +* @tc.name: Get +* @tc.desc: Get. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, Get, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Get"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + size_t testKeyLen = 10; + std::string str(testKeyLen, 'a'); + Blob key(str); + Blob value("test_value"); + Status status = kvStore->Get(key, value); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Get."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Get"; +} + +/** +* @tc.name: GetEntries_001 +* @tc.desc: Get Entries. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, GetEntries_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin GetEntries_001"; + try { + std::vector vct; + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*convertorMock, GetPrefix(An())).WillOnce(Return(vct)); + Blob key("test"); + std::vector vecs; + for (int i = 0; i < 2; ++i) { + Entry entry; + entry.key = std::to_string(i).append("_key"); + entry.value = std::to_string(i).append("_val"); + vecs.emplace_back(entry); + } + Status status = kvStore->GetEntries(key, vecs); + EXPECT_TRUE(status == INVALID_ARGUMENT); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by GetEntries_001."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end GetEntries_001"; +} + +/** +* @tc.name: GetDeviceEntries +* @tc.desc: Get device entries. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, GetDeviceEntries, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin GetDeviceEntries"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + std::vector vcs; + for (int i = 0; i < 2; ++i) { + Entry entry; + entry.key = std::to_string(i).append("_key"); + entry.value = std::to_string(i).append("_val"); + vcs.emplace_back(entry); + } + std::string device = "test device"; + Status status = kvStore->GetDeviceEntries(device, vcs); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by GetDeviceEntries."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end GetDeviceEntries"; +} + +/** +* @tc.name: GetCount +* @tc.desc: Get count. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, GetCount, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin GetCount"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + DataQuery query; + int cnt = 0; + Status status = kvStore->GetCount(query, cnt); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by GetCount."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end GetCount"; +} + +/** +* @tc.name: GetCount +* @tc.desc: Get count. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, GetSecurityLevel, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin GetSecurityLevel"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + SecurityLevel securityLevel = NO_LABEL; + Status status = kvStore->GetSecurityLevel(securityLevel); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by GetSecurityLevel."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end GetSecurityLevel"; +} + +/** +* @tc.name: RemoveDeviceData_001 +* @tc.desc: Remove device data. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, RemoveDeviceData_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin RemoveDeviceData_001"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + Status status = kvStore->RemoveDeviceData("testdevice"); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by RemoveDeviceData_001."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end RemoveDeviceData_001"; +} + +/** +* @tc.name: RemoveDeviceData_002 +* @tc.desc: Remove device data. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, RemoveDeviceData_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin RemoveDeviceData_002"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + Status status = kvStore->RemoveDeviceData("testdevice"); + EXPECT_TRUE(status == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by RemoveDeviceData_002."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end RemoveDeviceData_002"; +} + +/** +* @tc.name: CloudSync_001 +* @tc.desc: Cloud sync. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, CloudSync_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin CloudSync_001"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + AsyncDetail asyncDetail; + Status status = kvStore->CloudSync(asyncDetail); + EXPECT_TRUE(status == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by CloudSync_001."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end CloudSync_001"; +} + +/** +* @tc.name: CloudSync_002 +* @tc.desc: Cloud sync. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, CloudSync_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin CloudSync_002"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + std::shared_ptr ser = make_shared(nullptr); + ASSERT_NE(ser, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(ser)); + EXPECT_CALL(*kVDBServiceClientMock, GetServiceAgent(_)).WillOnce(Return(nullptr)); + AsyncDetail asyncDetail; + Status status = kvStore->CloudSync(asyncDetail); + EXPECT_TRUE(status == ILLEGAL_STATE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by CloudSync_002."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end CloudSync_002"; +} + +/** +* @tc.name: SetSyncParam +* @tc.desc: Set sync param. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, SetSyncParam, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin SetSyncParam"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + KvSyncParam syncParam{ 500 }; + Status status = kvStore->SetSyncParam(syncParam); + EXPECT_TRUE(status == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by SetSyncParam."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end SetSyncParam"; +} + +/** +* @tc.name: GetSyncParam +* @tc.desc: Get sync param. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, GetSyncParam, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin GetSyncParam"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + KvSyncParam syncParam; + Status status = kvStore->GetSyncParam(syncParam); + EXPECT_TRUE(status == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by GetSyncParam."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end GetSyncParam"; +} + +/** +* @tc.name: SetCapabilityEnabled_001 +* @tc.desc: Set capability enabled. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, SetCapabilityEnabled_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin SetCapabilityEnabled_001"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + Status status = kvStore->SetCapabilityEnabled(false); + EXPECT_TRUE(status == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by SetCapabilityEnabled_001."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end SetCapabilityEnabled_001"; +} + +/** +* @tc.name: SetCapabilityEnabled_002 +* @tc.desc: Set capability enabled. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, SetCapabilityEnabled_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin SetCapabilityEnabled_002"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + std::shared_ptr service = make_shared(nullptr); + ASSERT_NE(service, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(service)); + Status status = kvStore->SetCapabilityEnabled(true); + EXPECT_TRUE(status == ERROR); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by SetCapabilityEnabled_002."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end SetCapabilityEnabled_002"; +} + +/** +* @tc.name: SetCapabilityRange +* @tc.desc: Set capability range. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, SetCapabilityRange, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin SetCapabilityRange"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + std::vector localLabels{"local", "near"}; + std::vector remoteLabels{"remote", "far"}; + Status status = kvStore->SetCapabilityRange(localLabels, remoteLabels); + EXPECT_TRUE(status == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by SetCapabilityRange."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end SetCapabilityRange"; +} + +/** +* @tc.name: SubscribeWithQuery_001 +* @tc.desc: Subscribe with query. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, SubscribeWithQuery_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin SubscribeWithQuery_001"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + std::vector devices{"dev1", "dev2"}; + DataQuery query; + Status status = kvStore->SubscribeWithQuery(devices, query); + EXPECT_TRUE(status == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by SubscribeWithQuery_001"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end SubscribeWithQuery_001"; +} + +/** +* @tc.name: SubscribeWithQuery_002 +* @tc.desc: Subscribe with query. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, SubscribeWithQuery_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin SubscribeWithQuery_002"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + std::shared_ptr serv = make_shared(nullptr); + ASSERT_NE(serv, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(serv)); + EXPECT_CALL(*kVDBServiceClientMock, GetServiceAgent(_)).WillOnce(Return(nullptr)); + std::vector devices{"dev0", "dev1"}; + DataQuery query; + Status status = kvStore->SubscribeWithQuery(devices, query); + EXPECT_TRUE(status == ILLEGAL_STATE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by SubscribeWithQuery_002"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end SubscribeWithQuery_002"; +} + +/** +* @tc.name: UnsubscribeWithQuery_001 +* @tc.desc: Unsubscribe with query. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, UnsubscribeWithQuery_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin UnsubscribeWithQuery_001"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + std::vector devs{"dev0", "dev1"}; + DataQuery quer; + Status status = kvStore->UnsubscribeWithQuery(devs, quer); + EXPECT_TRUE(status == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by UnsubscribeWithQuery_001"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end UnsubscribeWithQuery_001"; +} + +/** +* @tc.name: UnsubscribeWithQuery_002 +* @tc.desc: Unsubscribe with query. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, UnsubscribeWithQuery_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin UnsubscribeWithQuery_002"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + EXPECT_NE(kv->dbStore_, nullptr); + std::shared_ptr serv = make_shared(nullptr); + ASSERT_NE(serv, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(serv)); + EXPECT_CALL(*kVDBServiceClientMock, GetServiceAgent(_)).WillOnce(Return(nullptr)); + std::vector devs{"dev3", "dev4"}; + DataQuery quer; + Status status = kv->UnsubscribeWithQuery(devs, quer); + EXPECT_TRUE(status == ILLEGAL_STATE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by UnsubscribeWithQuery_002"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end UnsubscribeWithQuery_002"; +} + +/** +* @tc.name: Restore_001 +* @tc.desc: restore kv. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, Restore_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Restore_001"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + std::string baseDirect = "/data/service/el1/public/database/SingleStoreImplTest"; + std::string file = "test.txt"; + kv->isApplication_ = false; + Status status = kv->Restore(file, baseDirect); + EXPECT_TRUE(status != SUCCESS); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Restore_001"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Restore_001"; +} + +/** +* @tc.name: Restore_002 +* @tc.desc: restore kv. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, Restore_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Restore_002"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + std::shared_ptr serv = make_shared(nullptr); + ASSERT_NE(serv, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(serv)); + std::string baseDirect = "/data/service/el1/public/database/SingleStoreImplTest"; + std::string file = "test1.txt"; + kv->isApplication_ = true; + kv->apiVersion_ = 15; // version + Status status = kv->Restore(file, baseDirect); + EXPECT_TRUE(status != SUCCESS); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Restore_002"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Restore_002"; +} + +/** +* @tc.name: GetResultSet +* @tc.desc: Get result Set. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, GetResultSet, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin GetResultSet"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + kv->dbStore_= nullptr; + EXPECT_TRUE(kv->dbStore_ == nullptr); + SingleStoreImpl::DBQuery dbQuer; + std::shared_ptr output; + Status status = kv->GetResultSet(dbQuer, output); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by GetResultSet"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end GetResultSet"; +} + +/** +* @tc.name: GetEntries +* @tc.desc: Get entries. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, GetEntries, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin GetEntries"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + kv->dbStore_= nullptr; + EXPECT_TRUE(kv->dbStore_ == nullptr); + std::vector vects; + SingleStoreImpl::DBQuery dbQuer; + Status status = kv->GetEntries(dbQuer, vects); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by GetEntries"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end GetEntries"; +} + +/** +* @tc.name: DoSync_001 +* @tc.desc: do sync. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, DoSync_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin DoSync_001"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + kv->isClientSync_ = false; + ASSERT_FALSE(kv->isClientSync_); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + SingleStoreImpl::SyncInfo syInfo; + std::shared_ptr obser; + auto res = kv->DoSync(syInfo, obser); + EXPECT_TRUE(res == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by DoSync_001"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end DoSync_001"; +} + +/** +* @tc.name: DoSync_002 +* @tc.desc: do sync. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, DoSync_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin DoSync_002"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + kv->isClientSync_ = false; + std::shared_ptr servic = make_shared(nullptr); + ASSERT_NE(servic, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(servic)); + EXPECT_CALL(*kVDBServiceClientMock, GetServiceAgent(_)).WillOnce(Return(nullptr)); + SingleStoreImpl::SyncInfo syInfo; + std::shared_ptr observer; + auto res = kv->DoSync(syInfo, observer); + EXPECT_TRUE(res == ILLEGAL_STATE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by DoSync_002"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end DoSync_002"; +} + +/** +* @tc.name: SetConfig +* @tc.desc: set config. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, SetConfig, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin SetConfig"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + StoreConfig storeConfig; + auto res = kv->SetConfig(storeConfig); + EXPECT_TRUE(res == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by SetConfig"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end SetConfig"; +} + +/** +* @tc.name: DoNotifyChange +* @tc.desc: Do notify change. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, DoNotifyChange, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin DoNotifyChange"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + kv->cloudAutoSync_ = false; + kv->DoNotifyChange(); + EXPECT_TRUE(!kv->cloudAutoSync_); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by DoNotifyChange"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end DoNotifyChange"; +} + +/** +* @tc.name: IsRebuild +* @tc.desc: is rebuild. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, IsRebuild, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin IsRebuild"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + kv->dbStore_= nullptr; + EXPECT_TRUE(kv->dbStore_ == nullptr); + auto res = kv->IsRebuild(); + EXPECT_FALSE(res); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by IsRebuild"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end IsRebuild"; +} +} // namespace OHOS::DistributedKv \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_test.cpp index 42188eb7c8cd54b0a0e8c461481b0fff7d96f287..388652cadae5d587ef39719321a1d2b443659ac3 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_test.cpp @@ -16,6 +16,8 @@ #include #include +#include "access_token.h" +#include "accesstoken_kit.h" #include "block_data.h" #include "dev_manager.h" #include "device_manager.h" @@ -23,14 +25,17 @@ #include "dm_device_info.h" #include "file_ex.h" #include "kv_store_nb_delegate.h" +#include "nativetoken_kit.h" #include "single_store_impl.h" #include "store_factory.h" #include "store_manager.h" #include "sys/stat.h" +#include "token_setproc.h" #include "types.h" using namespace testing::ext; using namespace OHOS::DistributedKv; +using namespace OHOS::Security::AccessToken; using DBStatus = DistributedDB::DBStatus; using DBStore = DistributedDB::KvStoreNbDelegate; using SyncCallback = KvStoreSyncCallback; @@ -73,6 +78,7 @@ public: void SetUp(); void TearDown(); + void SetNativeTokenId(); std::shared_ptr CreateKVStore(std::string storeIdTest, KvStoreType type, bool encrypt, bool backup); std::shared_ptr CreateKVStore(bool autosync = false); std::shared_ptr kvStore_; @@ -165,12 +171,32 @@ std::shared_ptr SingleStoreImplTest::CreateKVStore(bool autosyn return kvStore; } +void SingleStoreImplTest::SetNativeTokenId() +{ + std::string dumpInfo; + AtmToolsParamInfo info; + info.processName = "distributeddata"; + AccessTokenKit::DumpTokenInfo(info, dumpInfo); + size_t pos = dumpInfo.find("\"tokenID\": "); + if (pos == std::string::npos) { + return; + } + pos += std::string("\"tokenID\": ").length(); + std::string numStr; + while (pos < dumpInfo.length() && std::isdigit(dumpInfo[pos])) { + numStr += dumpInfo[pos]; + ++pos; + } + std::istringstream iss(numStr); + AccessTokenID tokenID; + iss >> tokenID; + SetSelfTokenID(tokenID); +} + /** * @tc.name: GetStoreId * @tc.desc: get the store id of the kv store * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, GetStoreId, TestSize.Level0) { @@ -195,8 +221,6 @@ HWTEST_F(SingleStoreImplTest, GetSubUser, TestSize.Level0) * @tc.name: Put * @tc.desc: put key-value data to the kv store * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, Put, TestSize.Level0) { @@ -215,8 +239,6 @@ HWTEST_F(SingleStoreImplTest, Put, TestSize.Level0) * @tc.name: Put_Invalid_Key * @tc.desc: put invalid key-value data to the device kv store and single kv store * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: wu fengshan */ HWTEST_F(SingleStoreImplTest, Put_Invalid_Key, TestSize.Level0) { @@ -260,8 +282,6 @@ HWTEST_F(SingleStoreImplTest, Put_Invalid_Key, TestSize.Level0) * @tc.name: PutBatch * @tc.desc: put some key-value data to the kv store * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, PutBatch, TestSize.Level0) { @@ -320,8 +340,6 @@ HWTEST_F(SingleStoreImplTest, PutBatch001, TestSize.Level1) * @tc.name: Delete * @tc.desc: delete the value of the key * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, Delete, TestSize.Level0) { @@ -344,8 +362,6 @@ HWTEST_F(SingleStoreImplTest, Delete, TestSize.Level0) * @tc.name: DeleteBatch * @tc.desc: delete the values of the keys * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, DeleteBatch, TestSize.Level0) { @@ -378,8 +394,6 @@ HWTEST_F(SingleStoreImplTest, DeleteBatch, TestSize.Level0) * @tc.name: Transaction * @tc.desc: do transaction * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, Transaction, TestSize.Level0) { @@ -399,8 +413,6 @@ HWTEST_F(SingleStoreImplTest, Transaction, TestSize.Level0) * @tc.name: SubscribeKvStore * @tc.desc: subscribe local * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, SubscribeKvStore, TestSize.Level0) { @@ -448,8 +460,6 @@ HWTEST_F(SingleStoreImplTest, SubscribeKvStore, TestSize.Level0) * @tc.name: SubscribeKvStore002 * @tc.desc: subscribe local * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Hollokin */ HWTEST_F(SingleStoreImplTest, SubscribeKvStore002, TestSize.Level0) { @@ -525,8 +535,6 @@ HWTEST_F(SingleStoreImplTest, SubscribeKvStore003, TestSize.Level0) * @tc.name: UnsubscribeKvStore * @tc.desc: unsubscribe * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, UnsubscribeKvStore, TestSize.Level0) { @@ -556,8 +564,6 @@ HWTEST_F(SingleStoreImplTest, UnsubscribeKvStore, TestSize.Level0) * @tc.name: GetEntries * @tc.desc: get entries by prefix * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, GetEntries_Prefix, TestSize.Level0) { @@ -587,8 +593,6 @@ HWTEST_F(SingleStoreImplTest, GetEntries_Prefix, TestSize.Level0) * @tc.name: GetEntries_Less_Prefix * @tc.desc: get entries by prefix and the key size less than sizeof(uint32_t) * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: wu fengshan */ HWTEST_F(SingleStoreImplTest, GetEntries_Less_Prefix, TestSize.Level0) { @@ -631,8 +635,6 @@ HWTEST_F(SingleStoreImplTest, GetEntries_Less_Prefix, TestSize.Level0) * @tc.name: GetEntries_Greater_Prefix * @tc.desc: get entries by prefix and the key size is greater than sizeof(uint32_t) * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: wu fengshan */ HWTEST_F(SingleStoreImplTest, GetEntries_Greater_Prefix, TestSize.Level0) { @@ -678,8 +680,6 @@ HWTEST_F(SingleStoreImplTest, GetEntries_Greater_Prefix, TestSize.Level0) * @tc.name: GetEntries * @tc.desc: get entries by query * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, GetEntries_DataQuery, TestSize.Level0) { @@ -712,8 +712,6 @@ HWTEST_F(SingleStoreImplTest, GetEntries_DataQuery, TestSize.Level0) * @tc.name: GetResultSet * @tc.desc: get result set by prefix * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, GetResultSet_Prefix, TestSize.Level0) { @@ -751,8 +749,6 @@ HWTEST_F(SingleStoreImplTest, GetResultSet_Prefix, TestSize.Level0) * @tc.name: GetResultSet * @tc.desc: get result set by query * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, GetResultSet_Query, TestSize.Level0) { @@ -792,8 +788,6 @@ HWTEST_F(SingleStoreImplTest, GetResultSet_Query, TestSize.Level0) * @tc.name: CloseResultSet * @tc.desc: close the result set * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, CloseResultSet, TestSize.Level0) { @@ -857,8 +851,6 @@ HWTEST_F(SingleStoreImplTest, CloseResultSet001, TestSize.Level0) * @tc.name: ResultSetMaxSizeTest * @tc.desc: test if kv supports 8 resultSets at the same time * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, ResultSetMaxSizeTest_Query, TestSize.Level0) { @@ -913,8 +905,6 @@ HWTEST_F(SingleStoreImplTest, ResultSetMaxSizeTest_Query, TestSize.Level0) * @tc.name: ResultSetMaxSizeTest * @tc.desc: test if kv supports 8 resultSets at the same time * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, ResultSetMaxSizeTest_Prefix, TestSize.Level0) { @@ -967,8 +957,6 @@ HWTEST_F(SingleStoreImplTest, ResultSetMaxSizeTest_Prefix, TestSize.Level0) * @tc.name: MaxLogSizeTest * @tc.desc: test if the default max limit of wal is 200MB * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, MaxLogSizeTest, TestSize.Level0) { @@ -1025,8 +1013,6 @@ HWTEST_F(SingleStoreImplTest, MaxLogSizeTest, TestSize.Level0) * @tc.name: MaxTest002 * @tc.desc: test if the default max limit of wal is 200MB * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, MaxLogSizeTest002, TestSize.Level0) { @@ -1105,8 +1091,6 @@ HWTEST_F(SingleStoreImplTest, MaxLogSizeTest002, TestSize.Level0) * @tc.name: Move_Offset * @tc.desc: Move the ResultSet Relative Distance * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: wu fengshan */ HWTEST_F(SingleStoreImplTest, Move_Offset, TestSize.Level0) { @@ -1162,8 +1146,6 @@ HWTEST_F(SingleStoreImplTest, Move_Offset, TestSize.Level0) * @tc.name: GetCount * @tc.desc: close the result set * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, GetCount, TestSize.Level0) { @@ -1218,8 +1200,6 @@ void ChangeOwnerToService(std::string baseDir, std::string hashId) * @tc.name: RemoveDeviceData * @tc.desc: remove local device data * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, RemoveDeviceData, TestSize.Level0) { @@ -1259,8 +1239,6 @@ HWTEST_F(SingleStoreImplTest, RemoveDeviceData, TestSize.Level0) * @tc.name: GetSecurityLevel * @tc.desc: get security level * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, GetSecurityLevel, TestSize.Level0) { @@ -1275,8 +1253,6 @@ HWTEST_F(SingleStoreImplTest, GetSecurityLevel, TestSize.Level0) * @tc.name: RegisterSyncCallback * @tc.desc: register the data sync callback * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, RegisterSyncCallback, TestSize.Level0) { @@ -1295,8 +1271,6 @@ HWTEST_F(SingleStoreImplTest, RegisterSyncCallback, TestSize.Level0) * @tc.name: UnRegisterSyncCallback * @tc.desc: unregister the data sync callback * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, UnRegisterSyncCallback, TestSize.Level0) { @@ -1317,8 +1291,6 @@ HWTEST_F(SingleStoreImplTest, UnRegisterSyncCallback, TestSize.Level0) * @tc.name: disableBackup * @tc.desc: Disable backup * @tc.type: FUNC - * @tc.require: - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, disableBackup, TestSize.Level0) { @@ -1338,8 +1310,6 @@ HWTEST_F(SingleStoreImplTest, disableBackup, TestSize.Level0) * @tc.name: PutOverMaxValue * @tc.desc: put key-value data to the kv store and the value size over the limits * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, PutOverMaxValue, TestSize.Level0) { @@ -1357,8 +1327,6 @@ HWTEST_F(SingleStoreImplTest, PutOverMaxValue, TestSize.Level0) * @tc.name: DeleteOverMaxKey * @tc.desc: delete the values of the keys and the key size over the limits * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, DeleteOverMaxKey, TestSize.Level0) { @@ -1382,8 +1350,6 @@ HWTEST_F(SingleStoreImplTest, DeleteOverMaxKey, TestSize.Level0) * @tc.name: GetEntriesOverMaxKey * @tc.desc: get entries the by prefix and the prefix size over the limits * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, GetEntriesOverMaxPrefix, TestSize.Level0) { @@ -1403,8 +1369,6 @@ HWTEST_F(SingleStoreImplTest, GetEntriesOverMaxPrefix, TestSize.Level0) * @tc.name: GetResultSetOverMaxPrefix * @tc.desc: get result set the by prefix and the prefix size over the limits * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, GetResultSetOverMaxPrefix, TestSize.Level0) { @@ -1424,8 +1388,6 @@ HWTEST_F(SingleStoreImplTest, GetResultSetOverMaxPrefix, TestSize.Level0) * @tc.name: RemoveNullDeviceData * @tc.desc: remove local device data and the device is null * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, RemoveNullDeviceData, TestSize.Level0) { @@ -1460,8 +1422,6 @@ HWTEST_F(SingleStoreImplTest, RemoveNullDeviceData, TestSize.Level0) * @tc.name: CloseKVStoreWithInvalidAppId * @tc.desc: close the kv store with invalid appid * @tc.type: FUNC - * @tc.require: - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, CloseKVStoreWithInvalidAppId, TestSize.Level0) { @@ -1475,8 +1435,6 @@ HWTEST_F(SingleStoreImplTest, CloseKVStoreWithInvalidAppId, TestSize.Level0) * @tc.name: CloseKVStoreWithInvalidStoreId * @tc.desc: close the kv store with invalid store id * @tc.type: FUNC - * @tc.require: - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, CloseKVStoreWithInvalidStoreId, TestSize.Level0) { @@ -1490,8 +1448,6 @@ HWTEST_F(SingleStoreImplTest, CloseKVStoreWithInvalidStoreId, TestSize.Level0) * @tc.name: CloseAllKVStore * @tc.desc: close all kv store * @tc.type: FUNC - * @tc.require: - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, CloseAllKVStore, TestSize.Level0) { @@ -1521,8 +1477,6 @@ HWTEST_F(SingleStoreImplTest, CloseAllKVStore, TestSize.Level0) * @tc.name: CloseAllKVStoreWithInvalidAppId * @tc.desc: close the kv store with invalid appid * @tc.type: FUNC - * @tc.require: - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, CloseAllKVStoreWithInvalidAppId, TestSize.Level0) { @@ -1535,8 +1489,6 @@ HWTEST_F(SingleStoreImplTest, CloseAllKVStoreWithInvalidAppId, TestSize.Level0) * @tc.name: DeleteWithInvalidAppId * @tc.desc: delete the kv store with invalid appid * @tc.type: FUNC - * @tc.require: - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, DeleteWithInvalidAppId, TestSize.Level0) { @@ -1551,8 +1503,6 @@ HWTEST_F(SingleStoreImplTest, DeleteWithInvalidAppId, TestSize.Level0) * @tc.name: DeleteWithInvalidStoreId * @tc.desc: delete the kv store with invalid storeid * @tc.type: FUNC - * @tc.require: - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, DeleteWithInvalidStoreId, TestSize.Level0) { @@ -1567,8 +1517,6 @@ HWTEST_F(SingleStoreImplTest, DeleteWithInvalidStoreId, TestSize.Level0) * @tc.name: GetKVStoreWithPersistentFalse * @tc.desc: delete the kv store with the persistent is false * @tc.type: FUNC - * @tc.require: - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, GetKVStoreWithPersistentFalse, TestSize.Level0) { @@ -1591,8 +1539,6 @@ HWTEST_F(SingleStoreImplTest, GetKVStoreWithPersistentFalse, TestSize.Level0) * @tc.name: GetKVStoreWithInvalidType * @tc.desc: delete the kv store with the KvStoreType is InvalidType * @tc.type: FUNC - * @tc.require: - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, GetKVStoreWithInvalidType, TestSize.Level0) { @@ -1614,8 +1560,6 @@ HWTEST_F(SingleStoreImplTest, GetKVStoreWithInvalidType, TestSize.Level0) * @tc.name: GetKVStoreWithCreateIfMissingFalse * @tc.desc: delete the kv store with the createIfMissing is false * @tc.type: FUNC - * @tc.require: - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, GetKVStoreWithCreateIfMissingFalse, TestSize.Level0) { @@ -1638,8 +1582,6 @@ HWTEST_F(SingleStoreImplTest, GetKVStoreWithCreateIfMissingFalse, TestSize.Level * @tc.name: GetKVStoreWithAutoSync * @tc.desc: delete the kv store with the autoSync is false * @tc.type: FUNC - * @tc.require: - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, GetKVStoreWithAutoSync, TestSize.Level0) { @@ -1664,8 +1606,6 @@ HWTEST_F(SingleStoreImplTest, GetKVStoreWithAutoSync, TestSize.Level0) * @tc.name: GetKVStoreWithAreaEL2 * @tc.desc: delete the kv store with the area is EL2 * @tc.type: FUNC - * @tc.require: - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, GetKVStoreWithAreaEL2, TestSize.Level0) { @@ -1691,8 +1631,6 @@ HWTEST_F(SingleStoreImplTest, GetKVStoreWithAreaEL2, TestSize.Level0) * @tc.name: GetKVStoreWithRebuildTrue * @tc.desc: delete the kv store with the rebuild is true * @tc.type: FUNC - * @tc.require: - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, GetKVStoreWithRebuildTrue, TestSize.Level0) { @@ -1717,8 +1655,6 @@ HWTEST_F(SingleStoreImplTest, GetKVStoreWithRebuildTrue, TestSize.Level0) * @tc.name: GetStaticStore * @tc.desc: get static store * @tc.type: FUNC - * @tc.require: - * @tc.author: zuojiangijang */ HWTEST_F(SingleStoreImplTest, GetStaticStore, TestSize.Level0) { @@ -1744,8 +1680,6 @@ HWTEST_F(SingleStoreImplTest, GetStaticStore, TestSize.Level0) * @tc.name: StaticStoreAsyncGet * @tc.desc: static store async get * @tc.type: FUNC - * @tc.require: - * @tc.author: zuojiangijang */ HWTEST_F(SingleStoreImplTest, StaticStoreAsyncGet, TestSize.Level0) { @@ -1779,8 +1713,6 @@ HWTEST_F(SingleStoreImplTest, StaticStoreAsyncGet, TestSize.Level0) * @tc.name: StaticStoreAsyncGetEntries * @tc.desc: static store async get entries * @tc.type: FUNC - * @tc.require: - * @tc.author: zuojiangijang */ HWTEST_F(SingleStoreImplTest, StaticStoreAsyncGetEntries, TestSize.Level0) { @@ -1815,8 +1747,6 @@ HWTEST_F(SingleStoreImplTest, StaticStoreAsyncGetEntries, TestSize.Level0) * @tc.name: DynamicStoreAsyncGet * @tc.desc: dynamic store async get * @tc.type: FUNC - * @tc.require: - * @tc.author: zuojiangijang */ HWTEST_F(SingleStoreImplTest, DynamicStoreAsyncGet, TestSize.Level0) { @@ -1852,8 +1782,6 @@ HWTEST_F(SingleStoreImplTest, DynamicStoreAsyncGet, TestSize.Level0) * @tc.name: DynamicStoreAsyncGetEntries * @tc.desc: dynamic store async get entries * @tc.type: FUNC - * @tc.require: - * @tc.author: zuojiangijang */ HWTEST_F(SingleStoreImplTest, DynamicStoreAsyncGetEntries, TestSize.Level0) { @@ -1898,8 +1826,6 @@ HWTEST_F(SingleStoreImplTest, DynamicStoreAsyncGetEntries, TestSize.Level0) * @tc.name: SetConfig * @tc.desc: SetConfig * @tc.type: FUNC - * @tc.require: - * @tc.author: ht */ HWTEST_F(SingleStoreImplTest, SetConfig, TestSize.Level0) { @@ -1930,7 +1856,8 @@ HWTEST_F(SingleStoreImplTest, SetConfig, TestSize.Level0) */ HWTEST_F(SingleStoreImplTest, GetDeviceEntries001, TestSize.Level1) { - std::string PKG_NAME_EX = "_distributed_data"; + SetNativeTokenId(); + std::string pkgNameEx = "_distributed_data"; std::shared_ptr kvStore; kvStore = CreateKVStore(); ASSERT_NE(kvStore, nullptr); @@ -1942,8 +1869,8 @@ HWTEST_F(SingleStoreImplTest, GetDeviceEntries001, TestSize.Level1) status = kvStore->GetDeviceEntries(device, output); ASSERT_EQ(status, SUCCESS); DevInfo devinfo; - std::string PKG_NAME = std::to_string(getpid()) + PKG_NAME_EX; - DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(PKG_NAME, devinfo); + std::string pkgName = std::to_string(getpid()) + pkgNameEx; + DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(pkgName, devinfo); ASSERT_NE(std::string(devinfo.deviceId), ""); status = kvStore->GetDeviceEntries(std::string(devinfo.deviceId), output); ASSERT_EQ(status, SUCCESS); @@ -2002,7 +1929,7 @@ HWTEST_F(SingleStoreImplTest, DoClientSync001, TestSize.Level1) std::shared_ptr observer; observer = nullptr; auto status = kvStore->DoClientSync(syncInfo, observer); - ASSERT_EQ(status, DB_ERROR); + ASSERT_EQ(status, ERROR); } /** @@ -2060,19 +1987,4 @@ HWTEST_F(SingleStoreImplTest, IsRemoteChanged, TestSize.Level0) bool ret = kvStore->IsRemoteChanged(""); ASSERT_TRUE(ret); } - -/** - * @tc.name: ReportDBFaultEvent - * @tc.desc: report DB corrupted fault - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplTest, ReportDBFaultEvent, TestSize.Level0) -{ - std::shared_ptr kvStore; - kvStore = CreateKVStore(); - ASSERT_NE(kvStore, nullptr); - Status status = DATA_CORRUPTED; - kvStore->ReportDBFaultEvent(status, std::string(__FUNCTION__)); - EXPECT_TRUE(status == DATA_CORRUPTED); -} } // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_perf_pc_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_perf_pc_test.cpp index 1cae23613c3d589662bd100b5c3b73a39bd83416..09cee73860b79fcb36d1b11a63c6269d77da3907 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_perf_pc_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_perf_pc_test.cpp @@ -163,7 +163,7 @@ static double TimeDiff(const struct timespec *beg, const struct timespec *end) * @tc.require: * @tc.author: Gang Wang */ -HWTEST_F(SingleStorePerfPcTest, HashIndexKVStoreTest001, TestSize.Level0) +HWTEST_F(SingleStorePerfPcTest, HashIndexKVStoreTest001, TestSize.Level1) { printf("HashIndexKVStoreTest001 BEGIN\n"); std::string strKey(8, 'k'); @@ -217,7 +217,7 @@ HWTEST_F(SingleStorePerfPcTest, HashIndexKVStoreTest001, TestSize.Level0) * @tc.require: * @tc.author: Gang Wang */ -HWTEST_F(SingleStorePerfPcTest, HashIndexKVStoreTest002, TestSize.Level0) +HWTEST_F(SingleStorePerfPcTest, HashIndexKVStoreTest002, TestSize.Level1) { printf("HashIndexKVStoreTest002 BEGIN\n"); std::string strKey(8, 'k'); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_perf_phone_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_perf_phone_test.cpp index 2ac13432f4098c38a888da05408dd97ea9d420d8..ede8256ad2a184ed3511490fdfa622ced28d2080 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_perf_phone_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_perf_phone_test.cpp @@ -41,6 +41,17 @@ std::shared_ptr store3; class SingleStorePerfPhoneTest : public testing::Test { public: + struct DataConfig { + int batch; + int count; + int size; + int ratio; + }; + + struct PresetResult { + std::string firstKey; + std::string lastKey; + }; std::shared_ptr CreateKVStore(std::string storeIdTest, KvStoreType type, bool encrypt, bool backup); static void SetUpTestCase(); static void TearDownTestCase(); @@ -76,7 +87,7 @@ string GetDate(char *cType, int iDay) char cTimePARTNUMBER[256] = ""; time_t rawtime; struct tm timeinfo{}; - rawtime = time(NULL) + iDay * 24 * 3600; // 24 hours a day, 3600 seconds per hour + rawtime = time(nullptr) + iDay * 24 * 3600; // 24 hours a day, 3600 seconds per hour localtime_r(&rawtime, &timeinfo); char buffer1[256]; size_t n = strftime(cTimePARTNUMBER, sizeof(buffer1), cType, &timeinfo); //20180623 @@ -100,39 +111,40 @@ string GetDate(char *cType, int iDay) * @details This function is responsible for writing a preset set of data to a specified * single-key value store based on a given batch, quantity, size, and ratio. */ -void PresetData(std::shared_ptr &store, int batch, int count, int size, int ratio, - std::string &firstKey, std::string &lastKey) +void PresetData(std::shared_ptr &store, + SingleStorePerfPhoneTest::DataConfig &config, SingleStorePerfPhoneTest::PresetResult &result) { std::ostringstream s; s << std::setw(16) << std::setfill('0') << 0; // 16 bytes string strDate; - string ss = to_string(size) + "K"; // The batches are iterated backward to generate data for different dates - for (int i = batch; i >= 1; i--) { - strDate = GetDate((char*)"%Y%m%d", -i); - for (int index = 1; index <= count; index++) { + // The batches are iterated backward to generate data for different dates + string ss = to_string(config.size) + "K"; + for (int i = config.batch; i >= 1; i--) { + strDate = GetDate(const_cast("%Y%m%d"), -i); + for (int index = 1; index <= config.count; index++) { // Produces a unique key string containing date, size, and index information string tmp = s.str() + "_" + ss + "_" + strDate + string(3 - to_string(index).length(), '0') + to_string(index); string val; // Generate random value string based on ratio If the ratio is 0, an empty string is generated - if (ratio != 0) { - val = GenerateRandomString((long)(size * 1024) / ratio); // 1024 bytes per 1K + if (config.ratio != 0) { + val = GenerateRandomString(static_cast(config.size * 1024) / config.ratio); // 1024 bytes per 1K } else { val = GenerateRandomString(0); } const DistributedDB::Key key = GenerateBytes(tmp); const DistributedDB::Value value = GenerateBytes(val); ASSERT_EQ(store->Put(key, value), SUCCESS); - if (i == batch && index == 1) { + if (i == config.batch && index == 1) { // Convert the contents of the key to std::string and assign it to the firstKey - firstKey = std::string(key.begin(), key.end()); + result.firstKey = std::string(key.begin(), key.end()); } - if (i == 1 && index == count) { - lastKey = std::string(key.begin(), key.end()); + if (i == 1 && index == config.count) { + result.lastKey = std::string(key.begin(), key.end()); } } } - printf("put success! \n"); + cout << "put success!" << endl; } /** @@ -146,8 +158,8 @@ void PresetData(std::shared_ptr &store, int batch, int count, int * @details This function is used to calculate the duration for obtaining data on a screen. * Data is obtained through multiple cycles and the average time is calculated. */ -void CalcRangeResultSetDuration(std::shared_ptr &store, int batch, int size, int count, - std::string firstKey, std::string lastKey) +void CalcRangeResultSetDuration(std::shared_ptr &store, + SingleStorePerfPhoneTest::DataConfig &config, SingleStorePerfPhoneTest::PresetResult &result) { // batch = totolCnt / (448/ 112) size(4 8) count (448 112) double dur = 0.0; @@ -158,22 +170,22 @@ void CalcRangeResultSetDuration(std::shared_ptr &store, int batch for (int n = 0; n < 100; ++n) { // 100 times DataQuery query; // The sequential query is carried out according to the actual business scenario - query.Between("", lastKey); + query.Between("", result.lastKey); std::shared_ptr readResultSet; ASSERT_EQ(store->GetResultSet(query, readResultSet), SUCCESS); ASSERT_TRUE(readResultSet != nullptr); - for (int ind = batch; ind >= 1; ind--) { + for (int ind = config.batch; ind >= 1; ind--) { struct timeval startTime{}; struct timeval endTime{}; (void) gettimeofday(&startTime, nullptr); - for (int i = 0; i < count; ++i) { // Loop through a screen of data + for (int i = 0; i < config.count; ++i) { // Loop through a screen of data readResultSet->MoveToNext(); // Move the read position to the next row. Entry entry; // Data is organized by entry definition. readResultSet->GetEntry(entry); } (void) gettimeofday(&endTime, nullptr); - double startUsec = (double) (startTime.tv_sec * 1000 * 1000) + (double) startTime.tv_usec; - double endUsec = (double) (endTime.tv_sec * 1000 * 1000) + (double) endTime.tv_usec; + double startUsec = static_cast((startTime.tv_sec * 1000 * 1000) + startTime.tv_usec); + double endUsec = static_cast((endTime.tv_sec * 1000 * 1000) + endTime.tv_usec); dur = endUsec - startUsec; totalTime += dur; avrTime = (dur / 1000); // 1000 is to convert ms @@ -184,9 +196,9 @@ void CalcRangeResultSetDuration(std::shared_ptr &store, int batch EXPECT_EQ(store->CloseResultSet(readResultSet), SUCCESS); readResultSet = nullptr; } - if (batch != 0) { + if (config.batch != 0) { // 100 is for unit conversion - avrTime = (((totalTime / batch) / 100) / 1000); // 1000 is to convert ms + avrTime = (((totalTime / config.batch) / 100) / 1000); // 1000 is to convert ms cout << "Scan Range ResultSet avg cost = " << avrTime << " ms." << endl; cout << "failCount: " << failCount << endl; EXPECT_LT(avrTime, 3.0); // 3.0 ms is upper bound on performance @@ -281,25 +293,31 @@ std::shared_ptr SingleStorePerfPhoneTest::CreateKVStore(std::stri * @tc.require: * @tc.author: Gang Wang */ -HWTEST_F(SingleStorePerfPhoneTest, Gallery1WThumbnailsKVStoreBetweenTest, TestSize.Level0) +HWTEST_F(SingleStorePerfPhoneTest, Gallery1WThumbnailsKVStoreBetweenTest, TestSize.Level1) { - int monthlyBatch = (int) (10000 / 112); - int annuallyBatch = (int) (10000 / 448); - int ratio = 1; - - printf("monthly start \n"); - std::string firstKey1; - std::string lastKey1; - PresetData(store1, monthlyBatch, 112, 8, ratio, firstKey1, lastKey1); - cout << "first key: " << firstKey1 << ", last key: " << lastKey1 << endl; - CalcRangeResultSetDuration(store1, monthlyBatch, 8, 112, firstKey1, lastKey1); + cout << "monthly start" << endl; + SingleStorePerfPhoneTest::DataConfig monthlyConfig = { + .batch = static_cast(10000 / 112), + .count = 112, + .size = 8, + .ratio = 1 + }; + SingleStorePerfPhoneTest::PresetResult result1; + PresetData(store1, monthlyConfig, result1); + cout << "first key: " << result1.firstKey << ", last key: " << result1.lastKey << endl; + CalcRangeResultSetDuration(store1, monthlyConfig, result1); - printf("annually start \n"); - std::string firstKey2; - std::string lastKey2; - PresetData(store2, annuallyBatch, 448, 4, ratio, firstKey2, lastKey2); - cout << "first key: " << firstKey2 << ", last key: " << lastKey2 << endl; - CalcRangeResultSetDuration(store2, annuallyBatch, 4, 448, firstKey2, lastKey2); + cout << "annually start" << endl; + SingleStorePerfPhoneTest::DataConfig annuallyConfig = { + .batch = static_cast(10000 / 448), + .count = 448, + .size = 4, + .ratio = 1 + }; + SingleStorePerfPhoneTest::PresetResult result2; + PresetData(store2, annuallyConfig, result2); + cout << "first key: " << result2.firstKey << ", last key: " << result2.lastKey << endl; + CalcRangeResultSetDuration(store2, annuallyConfig, result2); } /** @@ -310,24 +328,30 @@ HWTEST_F(SingleStorePerfPhoneTest, Gallery1WThumbnailsKVStoreBetweenTest, TestSi * @tc.require: * @tc.author: Gang Wang */ -HWTEST_F(SingleStorePerfPhoneTest, Gallery5WThumbnailsKVStoreBetweenTest, TestSize.Level0) +HWTEST_F(SingleStorePerfPhoneTest, Gallery5WThumbnailsKVStoreBetweenTest, TestSize.Level1) { - int monthlyBatch = (int) (50000 / 112); - int annuallyBatch = (int) (50000 / 448); - int ratio = 1; - - printf("monthly start \n"); - std::string firstKey1; - std::string lastKey1; - PresetData(store1, monthlyBatch, 112, 8, ratio, firstKey1, lastKey1); - cout << "first key: " << firstKey1 << ", last key: " << lastKey1 << endl; - CalcRangeResultSetDuration(store1, monthlyBatch, 8, 112, firstKey1, lastKey1); + cout << "monthly start" << endl; + SingleStorePerfPhoneTest::DataConfig monthlyConfig = { + .batch = static_cast(50000 / 112), + .count = 112, + .size = 8, + .ratio = 1 + }; + SingleStorePerfPhoneTest::PresetResult result1; + PresetData(store1, monthlyConfig, result1); + cout << "first key: " << result1.firstKey << ", last key: " << result1.lastKey << endl; + CalcRangeResultSetDuration(store1, monthlyConfig, result1); - printf("annually start \n"); - std::string firstKey2; - std::string lastKey2; - PresetData(store2, annuallyBatch, 448, 4, ratio, firstKey2, lastKey2); - cout << "first key: " << firstKey2 << ", last key: " << lastKey2 << endl; - CalcRangeResultSetDuration(store2, annuallyBatch, 4, 448, firstKey2, lastKey2); + cout << "annually start" << endl; + SingleStorePerfPhoneTest::DataConfig annuallyConfig = { + .batch = static_cast(50000 / 448), + .count = 448, + .size = 4, + .ratio = 1 + }; + SingleStorePerfPhoneTest::PresetResult result2; + PresetData(store2, annuallyConfig, result2); + cout << "first key: " << result2.firstKey << ", last key: " << result2.lastKey << endl; + CalcRangeResultSetDuration(store2, annuallyConfig, result2); } } // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/store_factory_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/store_factory_test.cpp index 9c932e503067581810aa5909c728bf7521a5a297..9b3fcf2e073e0c7228b95e6e9d902d8a02fd0076 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/store_factory_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/store_factory_test.cpp @@ -22,6 +22,9 @@ #include "backup_manager.h" #include "file_ex.h" +#include "hks_api.h" +#include "hks_param.h" +#include "security_manager.h" #include "store_manager.h" #include "store_util.h" #include "sys/stat.h" @@ -39,6 +42,8 @@ static Options options = { .kvStoreType = SINGLE_VERSION, .baseDir = "/data/service/el1/public/database/rekey", }; +static constexpr const char *ROOT_KEY_ALIAS = "distributeddb_client_root_key"; +static constexpr const char *HKS_BLOB_TYPE_AAD = "distributeddata_client"; class StoreFactoryTest : public testing::Test { public: @@ -57,16 +62,26 @@ public: void TearDown(); std::chrono::system_clock::time_point GetDate(const std::string &name, const std::string &path); - bool ChangeKeyDate(const std::string &name, const std::string &path, int duration); + bool ChangeKeyDate(const std::string &name, const std::string &path, int duration, const std::vector &key); bool MoveToRekeyPath(Options options, StoreId storeId); std::shared_ptr GetDBManager(const std::string &path, const AppId &appId); DBOption GetOption(const Options &options, const DBPassword &dbPassword); DBStatus ChangeKVStoreDate(const std::string &storeId, std::shared_ptr dbManager, const Options &options, DBPassword &dbPassword, int time); bool ModifyDate(int time); + bool Encrypt(const std::vector &key, SecurityManager::SecurityContent &content); + bool Decrypt(const SecurityManager::SecurityContent &content, std::vector &key); static void DeleteKVStore(); + + static std::vector vecRootKeyAlias_; + static std::vector vecAad_; }; +std::vector StoreFactoryTest::vecRootKeyAlias_ = + std::vector(ROOT_KEY_ALIAS, ROOT_KEY_ALIAS + strlen(ROOT_KEY_ALIAS)); +std::vector StoreFactoryTest::vecAad_ = + std::vector(HKS_BLOB_TYPE_AAD, HKS_BLOB_TYPE_AAD + strlen(HKS_BLOB_TYPE_AAD)); + void StoreFactoryTest::SetUpTestCase(void) { } void StoreFactoryTest::TearDownTestCase(void) { } @@ -88,52 +103,173 @@ void StoreFactoryTest::DeleteKVStore() StoreManager::GetInstance().Delete(appId, storeId, options.baseDir); } +bool StoreFactoryTest::Encrypt(const std::vector &key, SecurityManager::SecurityContent &content) +{ + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + return false; + } + + uint8_t nonceValue[SecurityManager::SecurityContent::NONCE_SIZE] = {0}; + struct HksBlob blobNonce = { .size = SecurityManager::SecurityContent::NONCE_SIZE, .data = nonceValue }; + ret = HksGenerateRandom(nullptr, &blobNonce); + if (ret != HKS_SUCCESS) { + return false; + } + + struct HksBlob blobAad = { uint32_t(vecAad_.size()), vecAad_.data() }; + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() }; + struct HksBlob plainKey = { uint32_t(key.size()), const_cast(key.data()) }; + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_NONCE, .blob = blobNonce }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, + }; + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return false; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return false; + } + + uint8_t cipherBuf[256] = { 0 }; + struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf }; + ret = HksEncrypt(&rootKeyName, params, &plainKey, &cipherText); + (void)HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + return false; + } + std::vector nonceContent(blobNonce.data, blobNonce.data + blobNonce.size); + content.nonceValue = nonceContent; + std::vector encryptValue(cipherText.data, cipherText.data + cipherText.size); + content.encryptValue = encryptValue; + std::fill(cipherBuf, cipherBuf + sizeof(cipherBuf), 0); + return true; +} + +bool StoreFactoryTest::Decrypt(const SecurityManager::SecurityContent &content, std::vector &key) +{ + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + return false; + } + + struct HksBlob blobNonce = { .size = uint32_t(content.nonceValue.size()), + .data = const_cast(&(content.nonceValue[0])) }; + struct HksBlob blobAad = { uint32_t(vecAad_.size()), &(vecAad_[0]) }; + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), &(vecRootKeyAlias_[0]) }; + struct HksBlob encryptedKeyBlob = { uint32_t(content.encryptValue.size()), + const_cast(content.encryptValue.data()) }; + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_NONCE, .blob = blobNonce }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, + }; + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return false; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return false; + } + + uint8_t plainBuf[256] = { 0 }; + struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf }; + ret = HksDecrypt(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob); + (void)HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + return false; + } + + key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size); + std::fill(plainBuf, plainBuf + sizeof(plainBuf), 0); + return true; +} + std::chrono::system_clock::time_point StoreFactoryTest::GetDate(const std::string &name, const std::string &path) { std::chrono::system_clock::time_point timePoint; - auto keyPath = path + "/key/" + name + ".key"; + auto keyPath = path + "/key/" + name + ".key_v1"; if (!OHOS::FileExists(keyPath)) { return timePoint; } - std::vector content; auto loaded = OHOS::LoadBufferFromFile(keyPath, content); if (!loaded) { return timePoint; } - constexpr uint32_t DATE_FILE_OFFSET = 1; - constexpr uint32_t DATE_FILE_LENGTH = sizeof(time_t) / sizeof(uint8_t); - std::vector date; - date.assign(content.begin() + DATE_FILE_OFFSET, content.begin() + DATE_FILE_LENGTH + DATE_FILE_OFFSET); - timePoint = std::chrono::system_clock::from_time_t(*reinterpret_cast(const_cast(&date[0]))); + SecurityManager::SecurityContent securityContent; + size_t offset = SecurityManager::SecurityContent::MAGIC_NUM; + securityContent.nonceValue.assign(content.begin() + offset, + content.begin() + offset + SecurityManager::SecurityContent::NONCE_SIZE); + offset += SecurityManager::SecurityContent::NONCE_SIZE; + securityContent.encryptValue.assign(content.begin() + offset, content.end()); + std::vector fullKey; + if (!Decrypt(securityContent, fullKey)) { + return timePoint; + } + offset = 0; + securityContent.version = fullKey[offset++]; + securityContent.time.assign(fullKey.begin() + offset, + fullKey.begin() + offset + (sizeof(time_t) / sizeof(uint8_t))); + timePoint = std::chrono::system_clock::from_time_t( + *reinterpret_cast(const_cast(securityContent.time.data()))); return timePoint; } -bool StoreFactoryTest::ChangeKeyDate(const std::string &name, const std::string &path, int duration) +bool StoreFactoryTest::ChangeKeyDate(const std::string &name, const std::string &path, int duration, + const std::vector &key) { - auto keyPath = path + "/key/" + name + ".key"; + auto keyPath = path + "/key/" + name + ".key_v1"; if (!OHOS::FileExists(keyPath)) { return false; } - - std::vector content; - auto loaded = OHOS::LoadBufferFromFile(keyPath, content); - if (!loaded) { - return false; - } + SecurityManager::SecurityContent securityContent; + securityContent.version = SecurityManager::SecurityContent::CURRENT_VERSION; auto time = std::chrono::system_clock::to_time_t( std::chrono::system_clock::system_clock::now() - std::chrono::hours(duration)); - std::vector date(reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time)); - std::copy(date.begin(), date.end(), ++content.begin()); - - auto saved = OHOS::SaveBufferToFile(keyPath, content); - return saved; + securityContent.time = { reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time) }; + std::vector keyContent; + keyContent.push_back(securityContent.version); + keyContent.insert(keyContent.end(), securityContent.time.begin(), securityContent.time.end()); + keyContent.insert(keyContent.end(), key.begin(), key.end()); + if (!Encrypt(keyContent, securityContent)) { + return false; + } + std::vector content; + for (size_t index = 0; index < SecurityManager::SecurityContent::MAGIC_NUM; ++index) { + content.push_back(char(SecurityManager::SecurityContent::MAGIC_CHAR)); + } + content.insert(content.end(), securityContent.nonceValue.begin(), securityContent.nonceValue.end()); + content.insert(content.end(), securityContent.encryptValue.begin(), securityContent.encryptValue.end()); + return OHOS::SaveBufferToFile(keyPath, content); } bool StoreFactoryTest::MoveToRekeyPath(Options options, StoreId storeId) { - std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key"; - std::string rekeyFileName = options.baseDir + "/rekey/key/" + storeId.storeId + ".new.key"; + std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key_v1"; + std::string rekeyFileName = options.baseDir + "/rekey/key/" + storeId.storeId + ".new.key_v1"; bool result = StoreUtil::Rename(keyFileName, rekeyFileName); if (!result) { return false; @@ -185,7 +321,9 @@ StoreFactoryTest::DBStatus StoreFactoryTest::ChangeKVStoreDate(const std::string status = dbStatus; store = dbStore; }); - if (!ChangeKeyDate(storeId, options.baseDir, time)) { + dbPassword = SecurityManager::GetInstance().GetDBPassword(storeId, options.baseDir, false); + std::vector key(dbPassword.GetData(), dbPassword.GetData() + dbPassword.GetSize()); + if (!ChangeKeyDate(storeId, options.baseDir, time, key)) { std::cout << "failed" << std::endl; } dbPassword = SecurityManager::GetInstance().GetDBPassword(storeId, options.baseDir, false); @@ -277,7 +415,7 @@ HWTEST_F(StoreFactoryTest, RekeyInterruptedWhileChangeKeyFile, TestSize.Level1) StoreManager::GetInstance().GetKVStore(appId, storeId, options, status); status = StoreManager::GetInstance().CloseKVStore(appId, storeId); ASSERT_EQ(status, SUCCESS); - std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key"; + std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key_v1"; auto isKeyExist = StoreUtil::IsFileExist(keyFileName); ASSERT_TRUE(isKeyExist); @@ -307,8 +445,8 @@ HWTEST_F(StoreFactoryTest, RekeyInterruptedBeforeChangeKeyFile, TestSize.Level1) StoreId newStoreId = { "newStore" }; StoreManager::GetInstance().GetKVStore(appId, newStoreId, options, status); - std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key"; - std::string mockKeyFileName = options.baseDir + "/key/" + newStoreId.storeId + ".key"; + std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key_v1"; + std::string mockKeyFileName = options.baseDir + "/key/" + newStoreId.storeId + ".key_v1"; StoreUtil::Rename(mockKeyFileName, keyFileName); StoreUtil::Remove(mockKeyFileName); auto isKeyExist = StoreUtil::IsFileExist(mockKeyFileName); @@ -343,7 +481,7 @@ HWTEST_F(StoreFactoryTest, RekeyNoPwdFile, TestSize.Level1) status = StoreManager::GetInstance().CloseKVStore(appId, storeId); ASSERT_EQ(status, SUCCESS); - std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key"; + std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key_v1"; StoreUtil::Remove(keyFileName); auto isKeyExist = StoreUtil::IsFileExist(keyFileName); diff --git a/kv_store/frameworks/jskitsimpl/distributeddata/include/js_const_properties.h b/kv_store/frameworks/jskitsimpl/distributeddata/include/js_const_properties.h index 367261d9554d2469f64780a95f92e22b54bed03b..6d42a1d1dcc809fff7d48c934f4e182cbda3b8b0 100644 --- a/kv_store/frameworks/jskitsimpl/distributeddata/include/js_const_properties.h +++ b/kv_store/frameworks/jskitsimpl/distributeddata/include/js_const_properties.h @@ -24,4 +24,4 @@ namespace OHOS::DistributedData { napi_status InitConstProperties(napi_env env, napi_value exports); } // namespace OHOS::DistributedData -#endif // OHOS_JS_CONST_PROPERTIES_H +#endif // OHOS_JS_CONST_PROPERTIES_H \ No newline at end of file diff --git a/kv_store/frameworks/jskitsimpl/distributeddata/include/js_util.h b/kv_store/frameworks/jskitsimpl/distributeddata/include/js_util.h index 12fce1a2613aab4b37d2dcf26e46dea2d74dec7c..722419602f802c57f23f629c9c58c738fbac73b0 100644 --- a/kv_store/frameworks/jskitsimpl/distributeddata/include/js_util.h +++ b/kv_store/frameworks/jskitsimpl/distributeddata/include/js_util.h @@ -178,6 +178,7 @@ public: static bool IsNull(napi_env env, napi_value value); + static std::string Anonymous(const std::string &name); private: enum { /* std::map to js::tuple */ diff --git a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_manager.cpp b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_manager.cpp index 665f48f23cfca664432be2dc34e8507dcaa31cd2..a01d3e5f6d8a0de9af80d3c9ccbee1e53fa8c939 100644 --- a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_manager.cpp +++ b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_manager.cpp @@ -134,7 +134,8 @@ napi_value JsKVManager::GetKVStore(napi_env env, napi_callback_info info) ctxt->options.baseDir = kvm->param_->baseDir; ctxt->options.area = kvm->param_->area + 1; ctxt->options.hapName = kvm->param_->hapName; - ZLOGD("Options area:%{public}d dir:%{public}s", ctxt->options.area, ctxt->options.baseDir.c_str()); + ZLOGD("Options area:%{public}d dir:%{public}s", ctxt->options.area, + JSUtil::Anonymous(ctxt->options.baseDir).c_str()); std::shared_ptr kvStore; Status status = kvm->kvDataManager_.GetSingleKvStore(ctxt->options, appId, storeId, kvStore); if (status == CRYPT_ERROR) { @@ -231,7 +232,7 @@ napi_value JsKVManager::DeleteKVStore(napi_env env, napi_callback_info info) auto kvm = reinterpret_cast(ctxt->native); CHECK_ARGS_RETURN_VOID(ctxt, kvm != nullptr, "KVManager is null, failed!"); std::string databaseDir = kvm->param_->baseDir; - ZLOGD("DeleteKVStore databaseDir is: %{public}s", databaseDir.c_str()); + ZLOGD("DeleteKVStore databaseDir is: %{public}s", JSUtil::Anonymous(databaseDir).c_str()); Status status = kvm->kvDataManager_.DeleteKvStore(appId, storeId, databaseDir); ZLOGD("DeleteKvStore status:%{public}d", status); ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; diff --git a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_store.cpp b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_store.cpp index 0e76225f2d7f2ab173b58dccb39f48cb1901e218..89d9889d565e5e9f5c32dcd46d0272c8eb5010b1 100644 --- a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_store.cpp +++ b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_store.cpp @@ -18,11 +18,9 @@ #include "log_print.h" #include "napi_queue.h" #include "datashare_values_bucket.h" -#include "datashare_predicates.h" #include "single_kvstore.h" using namespace OHOS::DistributedKv; -using namespace OHOS::DataShare; namespace OHOS::DistributedData { inline static uint8_t UNVALID_SUBSCRIBE_TYPE = 255; diff --git a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_single_kv_store.cpp b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_single_kv_store.cpp index 841df33d91d9588dd135b23a2b1eb0aa891b9bea..71f5f667cfb5423eef5d0e46047e5e8d42bf2e49 100644 --- a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_single_kv_store.cpp +++ b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_single_kv_store.cpp @@ -16,7 +16,6 @@ #include "js_single_kv_store.h" #include "js_util.h" #include "js_kv_store_resultset.h" -#include "datashare_predicates.h" #include "js_query.h" #include "log_print.h" #include "napi_queue.h" @@ -24,7 +23,6 @@ #include "kv_utils.h" using namespace OHOS::DistributedKv; -using namespace OHOS::DataShare; namespace OHOS::DistributedData { JsSingleKVStore::JsSingleKVStore(const std::string& storeId) : JsKVStore(storeId) diff --git a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_util.cpp b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_util.cpp index 964a6c38dd6df81995452adcd22e2987e3d4d945..1d220ab4f8d7a631e368a61072119e8fab33e3eb 100644 --- a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_util.cpp +++ b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_util.cpp @@ -30,6 +30,11 @@ using namespace OHOS::DataShare; namespace OHOS::DistributedData { constexpr int32_t STR_MAX_LENGTH = 4096; constexpr size_t STR_TAIL_LENGTH = 1; +static constexpr int32_t HEAD_SIZE = 3; +static constexpr int32_t END_SIZE = 3; +static constexpr int32_t MIN_SIZE = 9; +static constexpr const char *REPLACE_CHAIN = "***"; +static constexpr const char *DEFAULT_ANONYMOUS = "******"; struct PredicatesProxy { std::shared_ptr predicates_; }; @@ -1117,7 +1122,7 @@ napi_status JSUtil::GetCurrentAbilityParam(napi_env env, ContextParam ¶m) param.hapName = hapInfo->moduleName; } ZLOGI("area:%{public}d hapName:%{public}s baseDir:%{public}s", param.area, param.hapName.c_str(), - param.baseDir.c_str()); + Anonymous(param.baseDir).c_str()); return napi_ok; } @@ -1172,4 +1177,17 @@ std::pair JSUtil::GetInnerValue( } return std::make_pair(napi_ok, inner); } + +std::string JSUtil::Anonymous(const std::string &name) +{ + if (name.length() <= HEAD_SIZE) { + return DEFAULT_ANONYMOUS; + } + + if (name.length() < MIN_SIZE) { + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN); + } + + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE)); +} } // namespace OHOS::DistributedData diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_kv_manager.h b/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_kv_manager.h index 61c5c3e0eec9c9811c4e330618e4134864f64e39..1fd6e3d66fa2b710dfcf81df9d0116fcd8b06116 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_kv_manager.h +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_kv_manager.h @@ -63,7 +63,6 @@ private: std::shared_ptr uvQueue_; std::shared_ptr param_; static constexpr int MAX_APP_ID_LEN = 256; - static constexpr int API_20_VERSION = 20; }; } // namespace OHOS::DistributedKVStore #endif // OHOS_KV_MANAGER_H diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_util.h b/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_util.h index 59874055fa70bb55b6cbf7f7e26a9933d1f45f4a..3bb619a20193b25f2e740310981a5408b3450205 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_util.h +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_util.h @@ -220,6 +220,7 @@ public: static int32_t GetApiVersion(napi_env, napi_value value); + static std::string Anonymous(const std::string &name); private: enum { /* std::map to js::tuple */ diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/entry_point.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/entry_point.cpp index 9d9be5a4f447f34a54a94322e469c843e8d73341..085516faa56073c05288e2ae759c8bc314f51c21 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/entry_point.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/entry_point.cpp @@ -28,20 +28,12 @@ static napi_value Init(napi_env env, napi_value exports) const napi_property_descriptor desc[] = { DECLARE_NAPI_FUNCTION("createKVManager", JsKVManager::CreateKVManager) }; - napi_status status = napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); - ZLOGI("Init createKVManager %{public}d", status); + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + napi_set_named_property(env, exports, "FieldNode", JsFieldNode::Constructor(env)); + napi_set_named_property(env, exports, "Schema", JsSchema::Constructor(env)); + napi_set_named_property(env, exports, "Query", JsQuery::Constructor(env)); + InitConstProperties(env, exports); - status = napi_set_named_property(env, exports, "FieldNode", JsFieldNode::Constructor(env)); - ZLOGI("Init FieldNode %{public}d", status); - - status = napi_set_named_property(env, exports, "Schema", JsSchema::Constructor(env)); - ZLOGI("Init Schema %{public}d", status); - - status = napi_set_named_property(env, exports, "Query", JsQuery::Constructor(env)); - ZLOGI("Init Query %{public}d", status); - - status = InitConstProperties(env, exports); - ZLOGI("Init Enumerate Constants %{public}d", status); return exports; } diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_const_properties.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_const_properties.cpp index aa9394d9850c36462fac19401e429012d9ce893f..0e54930b46897029612dd5ba03b81e4563e8c085 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_const_properties.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_const_properties.cpp @@ -41,7 +41,10 @@ static napi_value ExportConstants(napi_env env) constexpr int32_t MAX_BATCH_SIZE = 128; napi_value constants = nullptr; - napi_create_object(env, &constants); + napi_status status = napi_create_object(env, &constants); + if (status != napi_ok) { + return nullptr; + } SetNamedProperty(env, constants, "MAX_KEY_LENGTH", MAX_KEY_LENGTH); SetNamedProperty(env, constants, "MAX_VALUE_LENGTH", MAX_VALUE_LENGTH); SetNamedProperty(env, constants, "MAX_KEY_LENGTH_DEVICE", MAX_KEY_LENGTH_DEVICE); @@ -55,7 +58,10 @@ static napi_value ExportConstants(napi_env env) static napi_value ExportValueType(napi_env env) { napi_value valueType = nullptr; - napi_create_object(env, &valueType); + napi_status status = napi_create_object(env, &valueType); + if (status != napi_ok) { + return nullptr; + } SetNamedProperty(env, valueType, "STRING", (int32_t)JSUtil::STRING); SetNamedProperty(env, valueType, "INTEGER", (int32_t)JSUtil::INTEGER); SetNamedProperty(env, valueType, "FLOAT", (int32_t)JSUtil::FLOAT); @@ -69,7 +75,10 @@ static napi_value ExportValueType(napi_env env) static napi_value ExportSyncMode(napi_env env) { napi_value syncMode = nullptr; - napi_create_object(env, &syncMode); + napi_status status = napi_create_object(env, &syncMode); + if (status != napi_ok) { + return nullptr; + } SetNamedProperty(env, syncMode, "PULL_ONLY", (int32_t)SyncMode::PULL); SetNamedProperty(env, syncMode, "PUSH_ONLY", (int32_t)SyncMode::PUSH); SetNamedProperty(env, syncMode, "PUSH_PULL", (int32_t)SyncMode::PUSH_PULL); @@ -80,8 +89,10 @@ static napi_value ExportSyncMode(napi_env env) static napi_value ExportSubscribeType(napi_env env) { napi_value subscribeType = nullptr; - napi_create_object(env, &subscribeType); - + napi_status status = napi_create_object(env, &subscribeType); + if (status != napi_ok) { + return nullptr; + } SetNamedProperty(env, subscribeType, "SUBSCRIBE_TYPE_LOCAL", (int32_t)SUBSCRIBE_LOCAL); SetNamedProperty(env, subscribeType, "SUBSCRIBE_TYPE_REMOTE", (int32_t)SUBSCRIBE_REMOTE); SetNamedProperty(env, subscribeType, "SUBSCRIBE_TYPE_ALL", (int32_t)SUBSCRIBE_LOCAL_REMOTE); @@ -92,7 +103,10 @@ static napi_value ExportSubscribeType(napi_env env) static napi_value ExportKVStoreType(napi_env env) { napi_value kvStoreType = nullptr; - napi_create_object(env, &kvStoreType); + napi_status status = napi_create_object(env, &kvStoreType); + if (status != napi_ok) { + return nullptr; + } SetNamedProperty(env, kvStoreType, "DEVICE_COLLABORATION", (int32_t)KvStoreType::DEVICE_COLLABORATION); SetNamedProperty(env, kvStoreType, "SINGLE_VERSION", (int32_t)KvStoreType::SINGLE_VERSION); napi_object_freeze(env, kvStoreType); @@ -102,8 +116,10 @@ static napi_value ExportKVStoreType(napi_env env) static napi_value ExportSecurityLevel(napi_env env) { napi_value securityLevel = nullptr; - - napi_create_object(env, &securityLevel); + napi_status status = napi_create_object(env, &securityLevel); + if (status != napi_ok) { + return nullptr; + } SetNamedProperty(env, securityLevel, "S1", (int32_t)SecurityLevel::S1); SetNamedProperty(env, securityLevel, "S2", (int32_t)SecurityLevel::S2); SetNamedProperty(env, securityLevel, "S3", (int32_t)SecurityLevel::S3); diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_device_kv_store.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_device_kv_store.cpp index f3160dbccd510c9704f182eb87c02f874d5e6d2e..9530ee70c2f0d201892a5b0e8140c91ab60e910e 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_device_kv_store.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_device_kv_store.cpp @@ -110,6 +110,9 @@ napi_value JsDeviceKVStore::Get(napi_env env, napi_callback_info info) OHOS::DistributedKv::Key key(deviceKey); OHOS::DistributedKv::Value value; auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } ASSERT_STATUS(ctxt, "kvStore->result() failed!"); bool isSchemaStore = reinterpret_cast(ctxt->native)->IsSchemaStore(); Status status = kvStore->Get(key, value); @@ -202,6 +205,9 @@ napi_value JsDeviceKVStore::GetEntries(napi_env env, napi_callback_info info) auto execute = [ctxt]() { auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } Status status = kvStore->GetEntries(ctxt->va.dataQuery, ctxt->entries); ZLOGD("kvStore->GetEntries() return %{public}d", status); ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? @@ -254,6 +260,9 @@ napi_value JsDeviceKVStore::GetResultSet(napi_env env, napi_callback_info info) auto execute = [ctxt]() { std::shared_ptr kvResultSet; auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } Status status = kvStore->GetResultSet(ctxt->va.dataQuery, kvResultSet); ZLOGD("kvStore->GetResultSet() return %{public}d", status); ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? @@ -297,6 +306,9 @@ napi_value JsDeviceKVStore::GetResultSize(napi_env env, napi_callback_info info) auto execute = [ctxt]() { auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } Status status = kvStore->GetCount(ctxt->va.dataQuery, ctxt->resultSize); ZLOGD("kvStore->GetCount() return %{public}d", status); ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_error_utils.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_error_utils.cpp index 09816ebb1b60eb897d93f8c09ab5115ac6db715e..d79c19b9067e4b4be665816dd6e4dd8716ebf7fb 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_error_utils.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_error_utils.cpp @@ -26,16 +26,14 @@ static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = { { Status::STORE_NOT_OPEN, 0, "" }, { Status::STORE_ALREADY_SUBSCRIBE, 0, "" }, { Status::STORE_NOT_SUBSCRIBE, 0, "" }, - { Status::NOT_FOUND, 15100004, "Data not found." }, - { Status::STORE_META_CHANGED, 15100002, - "The options configuration changes when the API is called to obtain a KV store." }, + { Status::NOT_FOUND, 15100004, "Not found." }, + { Status::STORE_META_CHANGED, 15100002, "Open existed database with changed options." }, { Status::PERMISSION_DENIED, 202, "Permission denied" }, - { Status::CRYPT_ERROR, 15100006, "Unable to open the database." }, - { Status::OVER_MAX_LIMITS, 15100001, "Upper limit exceeded." }, + { Status::CRYPT_ERROR, 15100003, "Database corrupted." }, + { Status::OVER_MAX_LIMITS, 15100001, "Over max limits." }, { Status::ALREADY_CLOSED, 15100005, "Database or result set already closed." }, { Status::DATA_CORRUPTED, 15100003, "Database corrupted" }, - { Status::WAL_OVER_LIMITS, 14800047, "the WAL file size exceeds the default limit."}, - { Status::DB_CANT_OPEN, 15100006, "Unable to open the database." } + { Status::WAL_OVER_LIMITS, 14800047, "the WAL file size exceeds the default limit."} }; const std::optional GetJsErrorCode(int32_t errorCode) diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_field_node.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_field_node.cpp index d62f08c35027af7604b3491330c112931a361374..2354e4edf017d01249251ddb4bb2f722ccda269d 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_field_node.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_field_node.cpp @@ -22,12 +22,16 @@ using namespace OHOS::DistributedKv; namespace OHOS::DistributedKVStore { -static std::string FIELD_NAME = "FIELD_NAME"; -static std::string VALUE_TYPE = "VALUE_TYPE"; -static std::string DEFAULT_VALUE = "DEFAULT_VALUE"; -static std::string IS_DEFAULT_VALUE = "IS_DEFAULT_VALUE"; -static std::string IS_NULLABLE = "IS_NULLABLE"; -static std::string CHILDREN = "CHILDREN"; +static constexpr const char* FIELD_NAME = "FIELD_NAME"; +static constexpr const char* VALUE_TYPE = "VALUE_TYPE"; +static constexpr const char* DEFAULT_VALUE = "DEFAULT_VALUE"; +static constexpr const char* IS_DEFAULT_VALUE = "IS_DEFAULT_VALUE"; +static constexpr const char* IS_NULLABLE = "IS_NULLABLE"; +static constexpr const char* CHILDREN = "CHILDREN"; +static constexpr const char* SPLIT = ","; +static constexpr const char* NOT_NULL = ", NOT NULL,"; +static constexpr const char* DEFAULT = " DEFAULT "; +static constexpr const char* MARK = "'"; std::map JsFieldNode::valueTypeToString_ = { { JSUtil::STRING, std::string("STRING") }, @@ -61,12 +65,11 @@ std::string JsFieldNode::GetFieldName() JsFieldNode::json JsFieldNode::GetValueForJson() { if (fields_.empty()) { + std::string jsonDesc = ToString(valueType_) + (isNullable_ ? SPLIT : NOT_NULL) + DEFAULT; if (valueType_ == JSUtil::STRING) { - return ToString(valueType_) + ToString(isNullable_ ? "," : ", NOT NULL,") + - " DEFAULT '" + ToString(defaultValue_) + "'"; + return jsonDesc += MARK + ToString(defaultValue_) + MARK; } - return ToString(valueType_) + ToString(isNullable_ ? "," : ", NOT NULL,") + - " DEFAULT " + ToString(defaultValue_); + return jsonDesc += ToString(defaultValue_); } json jsFields; diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_kv_manager.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_kv_manager.cpp index b29171798323220a89f2bad8fc02852f22603d87..71078694a7b89262ef578589244ab316fd8c180f 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_kv_manager.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_kv_manager.cpp @@ -144,7 +144,8 @@ napi_value JsKVManager::GetKVStore(napi_env env, napi_callback_info info) ctxt->options.area = kvm->param_->area + 1; ctxt->options.hapName = kvm->param_->hapName; ctxt->options.apiVersion = kvm->param_->apiVersion; - ZLOGD("Options area:%{public}d dir:%{public}s", ctxt->options.area, ctxt->options.baseDir.c_str()); + ZLOGD("Options area:%{public}d dir:%{public}s", ctxt->options.area, + JSUtil::Anonymous(ctxt->options.baseDir).c_str()); std::shared_ptr kvStore; Status status = kvm->kvDataManager_.GetSingleKvStore(ctxt->options, appId, storeId, kvStore); if (status == DATA_CORRUPTED) { @@ -152,9 +153,6 @@ napi_value JsKVManager::GetKVStore(napi_env env, napi_callback_info info) status = kvm->kvDataManager_.GetSingleKvStore(ctxt->options, appId, storeId, kvStore); ZLOGE("Data has corrupted, rebuild db"); } - if (status == CRYPT_ERROR && kvm->param_->apiVersion < API_20_VERSION) { - status = DATA_CORRUPTED; - } ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; ctxt->kvStore->SetKvStorePtr(kvStore); @@ -245,7 +243,7 @@ napi_value JsKVManager::DeleteKVStore(napi_env env, napi_callback_info info) auto kvm = reinterpret_cast(ctxt->native); ASSERT_ARGS(ctxt, kvm != nullptr, "KVManager is null, failed!"); std::string databaseDir = kvm->param_->baseDir; - ZLOGD("DeleteKVStore databaseDir is: %{public}s", databaseDir.c_str()); + ZLOGD("DeleteKVStore databaseDir is: %{public}s", JSUtil::Anonymous(databaseDir).c_str()); Status status = kvm->kvDataManager_.DeleteKvStore(appId, storeId, databaseDir); ZLOGD("DeleteKvStore status:%{public}d", status); ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_schema.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_schema.cpp index 79a1337d2e159d0816876717efaa9b93a6e76f18..177d8c19c3dc34629d8f277158fe84b7c916c79d 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_schema.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_schema.cpp @@ -25,13 +25,14 @@ using namespace OHOS::DistributedKv; using json = nlohmann::json; namespace OHOS::DistributedKVStore { -static std::string LABEL = "Schema"; -static std::string SCHEMA_VERSION = "SCHEMA_VERSION"; -static std::string SCHEMA_MODE = "SCHEMA_MODE"; -static std::string SCHEMA_DEFINE = "SCHEMA_DEFINE"; -static std::string SCHEMA_INDEXES = "SCHEMA_INDEXES"; -static std::string SCHEMA_SKIPSIZE = "SCHEMA_SKIPSIZE"; -static std::string DEFAULT_SCHEMA_VERSION = "1.0"; +static constexpr const char* SCHEMA_VERSION = "SCHEMA_VERSION"; +static constexpr const char* SCHEMA_MODE = "SCHEMA_MODE"; +static constexpr const char* SCHEMA_DEFINE = "SCHEMA_DEFINE"; +static constexpr const char* SCHEMA_INDEXES = "SCHEMA_INDEXES"; +static constexpr const char* SCHEMA_SKIPSIZE = "SCHEMA_SKIPSIZE"; +static constexpr const char* DEFAULT_SCHEMA_VERSION = "1.0"; +static constexpr const char* SCHEMA_STRICT = "STRICT"; +static constexpr const char* SCHEMA_COMPATIBLE = "COMPATIBLE"; JsSchema::JsSchema(napi_env env) : env_(env) @@ -234,7 +235,7 @@ std::string JsSchema::Dump() } json js = { { SCHEMA_VERSION, DEFAULT_SCHEMA_VERSION }, - { SCHEMA_MODE, (mode_ == SCHEMA_MODE_STRICT) ? "STRICT" : "COMPATIBLE" }, + { SCHEMA_MODE, (mode_ == SCHEMA_MODE_STRICT) ? SCHEMA_STRICT : SCHEMA_COMPATIBLE }, { SCHEMA_DEFINE, rootNode_->GetValueForJson() }, { SCHEMA_INDEXES, jsIndexes }, { SCHEMA_SKIPSIZE, skip_ }, diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_single_kv_store.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_single_kv_store.cpp index 1e3ffe49e60dd2fd72413a7d6523e97c897ccade..1983175e350da06e52703af65c819c4403fa8fd0 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_single_kv_store.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_single_kv_store.cpp @@ -16,7 +16,6 @@ #include "js_single_kv_store.h" #include "js_util.h" #include "js_kv_store_resultset.h" -#include "datashare_predicates.h" #include "js_query.h" #include "log_print.h" #include "napi_queue.h" @@ -24,7 +23,6 @@ #include "kv_utils.h" using namespace OHOS::DistributedKv; -using namespace OHOS::DataShare; namespace OHOS::DistributedKVStore { inline static uint8_t UNVALID_SUBSCRIBE_TYPE = 255; std::map JsSingleKVStore::onEventHandlers_ = { @@ -189,10 +187,7 @@ napi_value JsSingleKVStore::Put(napi_env env, napi_callback_info info) ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->value); if (ctxt->status != napi_ok) { ctxt->isThrowError = true; - napi_valuetype ntype = napi_undefined; - napi_typeof(env, argv[0], &ntype); - auto type = valueTypeToString_.find(ntype); - ThrowNapiError(env, Status::INVALID_ARGUMENT, "Parameter error:the type of value must be:" + type->second); + ThrowNapiError(env, Status::INVALID_ARGUMENT, "Parameter error: invalid value type"); return; } }); @@ -204,6 +199,9 @@ napi_value JsSingleKVStore::Put(napi_env env, napi_callback_info info) auto &kvStore = reinterpret_cast(ctxt->native)->kvStore_; DistributedKv::Value value = isSchemaStore ? DistributedKv::Blob(std::get(ctxt->value)) : JSUtil::VariantValue2Blob(ctxt->value); + if (kvStore == nullptr) { + return; + } Status status = kvStore->Put(key, value); ZLOGD("kvStore->Put return %{public}d", status); ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? @@ -908,6 +906,9 @@ napi_value JsSingleKVStore::Get(napi_env env, napi_callback_info info) OHOS::DistributedKv::Key key(ctxt->key); OHOS::DistributedKv::Value value; auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } bool isSchemaStore = reinterpret_cast(ctxt->native)->IsSchemaStore(); Status status = kvStore->Get(key, value); ZLOGD("kvStore->Get return %{public}d", status); @@ -991,6 +992,9 @@ napi_value JsSingleKVStore::GetEntries(napi_env env, napi_callback_info info) auto execute = [ctxt]() { auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } Status status = kvStore->GetEntries(ctxt->va.dataQuery, ctxt->entries); ZLOGD("kvStore->GetEntries() return %{public}d", status); ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? @@ -1041,6 +1045,9 @@ napi_value JsSingleKVStore::GetResultSet(napi_env env, napi_callback_info info) auto execute = [ctxt]() { std::shared_ptr kvResultSet; auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } Status status = kvStore->GetResultSet(ctxt->va.dataQuery, kvResultSet); ZLOGD("kvStore->GetResultSet() return %{public}d", status); @@ -1087,6 +1094,9 @@ napi_value JsSingleKVStore::CloseResultSet(napi_env env, napi_callback_info info auto execute = [ctxt]() { auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } auto resultSet = ctxt->resultSet->GetInstance(); ctxt->resultSet->SetInstance(nullptr); Status status = kvStore->CloseResultSet(resultSet); @@ -1126,6 +1136,9 @@ napi_value JsSingleKVStore::GetResultSize(napi_env env, napi_callback_info info) auto execute = [ctxt]() { auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } auto query = ctxt->query->GetDataQuery(); Status status = kvStore->GetCount(query, ctxt->resultSize); ZLOGD("kvStore->GetCount() return %{public}d", status); @@ -1163,6 +1176,9 @@ napi_value JsSingleKVStore::RemoveDeviceData(napi_env env, napi_callback_info in auto execute = [ctxt]() { auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } Status status = kvStore->RemoveDeviceData(ctxt->deviceId); ZLOGD("kvStore->RemoveDeviceData return %{public}d", status); ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? @@ -1234,6 +1250,9 @@ napi_value JsSingleKVStore::Sync(napi_env env, napi_callback_info info) (int)ctxt->deviceIdList.size(), ctxt->mode, ctxt->allowedDelayMs); auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return nullptr; + } Status status = Status::INVALID_ARGUMENT; if (ctxt->type == napi_object) { auto query = ctxt->query->GetDataQuery(); @@ -1272,6 +1291,9 @@ napi_value JsSingleKVStore::SetSyncParam(napi_env env, napi_callback_info info) auto execute = [ctxt]() { auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } KvSyncParam syncParam { ctxt->allowedDelayMs }; Status status = kvStore->SetSyncParam(syncParam); ZLOGD("kvStore->SetSyncParam return %{public}d", status); @@ -1296,6 +1318,9 @@ napi_value JsSingleKVStore::GetSecurityLevel(napi_env env, napi_callback_info in auto execute = [ctxt]() { auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } Status status = kvStore->GetSecurityLevel(ctxt->securityLevel); ZLOGD("kvStore->GetSecurityLevel return %{public}d", status); ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp index 9087b7a21c3dca46dbfd08405a99155d68c1e349..6eae577922ac64df1416b06ac1103ccc0d9a78e4 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp @@ -27,6 +27,11 @@ namespace OHOS::DistributedKVStore { constexpr int32_t STR_MAX_LENGTH = 4096; constexpr size_t STR_TAIL_LENGTH = 1; +static constexpr int32_t HEAD_SIZE = 3; +static constexpr int32_t END_SIZE = 3; +static constexpr int32_t MIN_SIZE = 9; +static constexpr const char *REPLACE_CHAIN = "***"; +static constexpr const char *DEFAULT_ANONYMOUS = "******"; static constexpr JSUtil::JsFeatureSpace FEATURE_NAME_SPACES[] = { { "ohos.data.cloudData", "ZGF0YS5jbG91ZERhdGE=", false }, { "ohos.data.dataAbility", "ZGF0YS5kYXRhQWJpbGl0eQ==", false }, @@ -199,7 +204,7 @@ JSUtil::KvStoreVariant JSUtil::Blob2VariantValue(const DistributedKv::Blob& blob auto& data = blob.Data(); // number 2 means: valid Blob must have more than 2 bytes. if (data.size() < 1) { - ZLOGE("Blob have no data!"); + ZLOGD("Blob have no data!"); return JSUtil::KvStoreVariant(); } // number 1 means: skip the first byte, byte[0] is real data type. @@ -1248,7 +1253,7 @@ JSUtil::StatusMsg JSUtil::GetCurrentAbilityParam(napi_env env, ContextParam &par if (hapInfo != nullptr) { param.hapName = hapInfo->moduleName; } - ZLOGI("area:%{public}d hapName:%{public}s baseDir:%{public}s", param.area, param.hapName.c_str(), + ZLOGI("area:%{public}d hapName:%{public}s baseDir:%{public}s", param.area, Anonymous(param.hapName).c_str(), param.baseDir.c_str()); return napi_ok; @@ -1342,4 +1347,17 @@ std::pair JSUtil::GetInnerValue( } return std::make_pair(napi_ok, inner); } + +std::string JSUtil::Anonymous(const std::string &name) +{ + if (name.length() <= HEAD_SIZE) { + return DEFAULT_ANONYMOUS; + } + + if (name.length() < MIN_SIZE) { + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN); + } + + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE)); +} } // namespace OHOS::DistributedKVStore diff --git a/kv_store/frameworks/libs/distributeddb/BUILD.gn b/kv_store/frameworks/libs/distributeddb/BUILD.gn index 345756ceb3023f6d6e10f880df533498f13b6803..41f46d87f7d532ff4a138d07881505417631de86 100644 --- a/kv_store/frameworks/libs/distributeddb/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/BUILD.gn @@ -91,6 +91,7 @@ group("build_module") { deps = [ ":customtokenizer", ":distributeddb", + ":distributeddb_client", ] } @@ -115,6 +116,7 @@ ohos_shared_library("distributeddb") { "-fvisibility=hidden", "-Os", "-D_FORTIFY_SOURCE=2", + "-flto", ] deps = [ "gaussdb_rd:gaussdb_rd" ] @@ -124,11 +126,11 @@ ohos_shared_library("distributeddb") { "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "jsoncpp:jsoncpp", "zlib:shared_libz", ] public_external_deps = [ - "jsoncpp:jsoncpp", "openssl:libcrypto_shared", "sqlite:sqlite", ] @@ -175,6 +177,7 @@ ohos_shared_library("customtokenizer") { cflags_cc = [ "-fvisibility=hidden", "-Os", + "-D_FORTIFY_SOURCE=2", ] external_deps = [ @@ -188,3 +191,102 @@ ohos_shared_library("customtokenizer") { innerapi_tags = [ "platformsdk_indirect" ] part_name = "kv_store" } + +config("distributeddb_client_public_config") { + visibility = [ "*:*" ] + include_dirs = [ + "interfaces/include/relational", + "interfaces/include", + "include", + ] +} + +config("distributeddb_client_config") { + visibility = [ ":*" ] + include_dirs = [ + "interfaces/src/relational", + "common/include/cloud", + "common/include", + "interfaces/include", + "interfaces/include/cloud", + "include", + "storage/include", + "communicator/include", + "common/include/relational", + "storage/src/sqlite", + "storage/src", + "storage/src/kv", + "syncer/src", + "syncer/src/device", + "storage/src/sqlite/relational", + "storage/src/relational", + ] + + defines = [ + "_LARGEFILE64_SOURCE", + "_FILE_OFFSET_BITS=64", + "SQLITE_HAS_CODEC", + "SQLITE_ENABLE_JSON1", + "USING_HILOG_LOGGER", + "USE_SQLITE_SYMBOLS", + "USING_DB_JSON_EXTRACT_AUTOMATICALLY", + "JSONCPP_USE_BUILDER", + "OMIT_FLATBUFFER", + "OMIT_MULTI_VER", + "RELATIONAL_STORE", + "SQLITE_DISTRIBUTE_RELATIONAL", + "USE_DFX_ABILITY", + "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", + ] + if (is_debug) { + defines += [ "TRACE_SQLITE_EXECUTE" ] + } + if (is_ohos) { + defines += [ "USE_FFRT" ] + defines += [ "RDB_CLIENT" ] + } + if (kv_store_cloud) { + defines += [ "USE_DISTRIBUTEDDB_CLOUD" ] + } +} + +ohos_shared_library("distributeddb_client") { + branch_protector_ret = "pac_ret" + sanitize = { + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + sources = distributeddb_client_src + sources += distributeddb_base_src + configs = [ ":distributeddb_client_config" ] + public_configs = [ ":distributeddb_client_public_config" ] + + cflags_cc = [ + "-fvisibility=hidden", + "-Os", + "-D_FORTIFY_SOURCE=2", + "-flto", + ] + + external_deps = [ + "cJSON:cjson", + "c_utils:utils", + "ffrt:libffrt", + "hilog:libhilog", + "jsoncpp:jsoncpp", + ] + + public_external_deps = [ + "openssl:libcrypto_shared", + "sqlite:sqlite", + ] + + subsystem_name = "distributeddatamgr" + innerapi_tags = [ "platformsdk_indirect" ] + part_name = "kv_store" +} diff --git a/kv_store/frameworks/libs/distributeddb/common/include/auto_launch.h b/kv_store/frameworks/libs/distributeddb/common/include/auto_launch.h index 87b043047277e661d0f542b66f3b09198a5b57f8..372db8841cd8af548fec8b8408fe326c63322536 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/auto_launch.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/auto_launch.h @@ -73,7 +73,7 @@ public: AutoLaunch() = default; - virtual ~AutoLaunch(); + ~AutoLaunch(); DISABLE_COPY_ASSIGN_MOVE(AutoLaunch); diff --git a/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h b/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h index 464bcc6185bee0a1ba16416d484725bf7b5e99f3..9a5a1734b70422bea0e0f19323e2cea80b95bb1e 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h @@ -17,7 +17,6 @@ #define CLOUD_DB_CONSTANT_H #include "cloud/cloud_store_types.h" -#include namespace DistributedDB { class CloudDbConstant { @@ -99,6 +98,7 @@ public: static constexpr const uint32_t ON_CHANGE_TRACKER = 0x1; static constexpr const uint32_t ON_CHANGE_P2P = 0x2; + static constexpr const uint32_t ON_CHANGE_KNOWLEDGE = 0x4; }; } // namespace DistributedDB #endif // CLOUD_DB_CONSTANT_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/include/concurrent_adapter.h b/kv_store/frameworks/libs/distributeddb/common/include/concurrent_adapter.h index 8c436567d281fcddd252f71c696abf3d8f74aa00..cf3872742f41b235fa4b9f9a07bb4b0c019745e9 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/concurrent_adapter.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/concurrent_adapter.h @@ -39,6 +39,7 @@ public: #ifdef USE_FFRT static void AdapterAutoLock(ffrt::mutex &mutex); static void AdapterAutoUnLock(ffrt::mutex &mutex); + static void Stop(); #else static void AdapterAutoLock(std::mutex &mutex); static void AdapterAutoUnLock(std::mutex &mutex); diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_common.h b/kv_store/frameworks/libs/distributeddb/common/include/db_common.h index 5f056954a86a3e4fbea8312906f7e1d1b02dd747..c2cf0d664790aca17e1f9972325600f2b22d0e0a 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_common.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_common.h @@ -145,7 +145,9 @@ public: static uint64_t EraseBit(uint64_t origin, uint64_t eraseBit); - static void LoadGrdLib(void); + static void *LoadGrdLib(void); + + static void UnLoadGrdLib(void *handle); static bool IsGrdLibLoaded(void); diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h b/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h index acbc03a856fc8bd6d473bd0f63e2b34ed9a57f4b..45d8b83ffc69a4b573e6952a6fdc2966cf12c9ec 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h @@ -24,6 +24,7 @@ public: static constexpr const size_t MAX_KEY_SIZE = 1024; static constexpr const size_t MAX_VALUE_SIZE = 4 * 1024 * 1024; // 4M static constexpr const size_t MAX_SET_VALUE_SIZE = 64 * 1024 * 1024; // 64M + static constexpr const size_t MAX_FIELD_NUM = 2000; static constexpr const size_t MAX_BATCH_SIZE = 128; static constexpr const size_t MAX_DEV_LENGTH = 128; static constexpr const size_t MAX_TRANSACTION_KEY_VALUE_LENS = 512 * 1024 * 1024; // 512M @@ -62,30 +63,31 @@ public: static constexpr const uint64_t MAX_STORE_ID_LENGTH = 128; static constexpr const uint64_t MAX_SUB_USER_LENGTH = 128; - static const std::string MULTI_SUB_DIR; - static const std::string SINGLE_SUB_DIR; - static const std::string LOCAL_SUB_DIR; + static constexpr const char *MULTI_SUB_DIR = "multi_ver"; + static constexpr const char *SINGLE_SUB_DIR = "single_ver"; + static constexpr const char *LOCAL_SUB_DIR = "local"; - static const std::string MAINDB_DIR; - static const std::string METADB_DIR; - static const std::string CACHEDB_DIR; + static constexpr const char *MAINDB_DIR = "main"; + static constexpr const char *METADB_DIR = "meta"; + static constexpr const char *CACHEDB_DIR = "cache"; static constexpr const char *LOCAL_DATABASE_NAME = "local"; static constexpr const char *MULTI_VER_DATA_STORE = "multi_ver_data"; static constexpr const char *MULTI_VER_COMMIT_STORE = "commit_logs"; static constexpr const char *MULTI_VER_VALUE_STORE = "value_storage"; static constexpr const char *MULTI_VER_META_STORE = "meta_storage"; - static const std::string SINGLE_VER_DATA_STORE; - static const std::string SINGLE_VER_META_STORE; - static const std::string SINGLE_VER_CACHE_STORE; + static constexpr const char *SINGLE_VER_DATA_STORE = "gen_natural_store"; + static constexpr const char *SINGLE_VER_META_STORE = "meta"; + static constexpr const char *SINGLE_VER_CACHE_STORE = "cache"; static constexpr const char *SQLITE_URL_PRE = "file:"; static constexpr const char *DB_EXTENSION = ".db"; static constexpr const char *SQLITE_MEMDB_IDENTIFY = "?mode=memory&cache=shared"; static constexpr const char *SCHEMA_KEY = "schemaKey"; - static const std::string RELATIONAL_SCHEMA_KEY; - static const std::string RELATIONAL_TRACKER_SCHEMA_KEY; + static constexpr const char *RELATIONAL_SCHEMA_KEY = "relational_schema"; + static constexpr const char *RELATIONAL_TRACKER_SCHEMA_KEY = "relational_tracker_schema"; + static constexpr const char *RDB_KNOWLEDGE_SCHEMA_KEY = "rdbKnowledgeSchemaKey"; static constexpr const char *RD_KV_COLLECTION_MODE = "{\"mode\" : \"kv\"}"; static constexpr const char *RD_KV_HASH_COLLECTION_MODE = "{\"mode\" : \"kv\",\"indextype\" : \"hash\"}"; @@ -115,10 +117,11 @@ public: static constexpr const char *TRIGGER_REFERENCES_NEW = "NEW."; static constexpr const char *TRIGGER_REFERENCES_OLD = "OLD."; - static const std::string UPDATE_META_FUNC; + static constexpr const char *UPDATE_META_FUNC = "update_meta_within_trigger"; // Prefix Key in meta db static constexpr const char *DEVICEID_PREFIX_KEY = "deviceId"; + static constexpr const char *USERID_PREFIX_KEY = "userId"; static constexpr const char *QUERY_SYNC_PREFIX_KEY = "querySync"; static constexpr const char *DELETE_SYNC_PREFIX_KEY = "deleteSync"; @@ -154,12 +157,13 @@ public: static constexpr const int MAX_OBSERVER_COUNT = 8; // For relational - static const std::string SYSTEM_TABLE_PREFIX; + static constexpr const char *SYSTEM_TABLE_PREFIX = "naturalbase_rdb_"; static constexpr const char *RELATIONAL_PREFIX = "naturalbase_rdb_aux_"; static constexpr size_t RELATIONAL_PREFIX_SIZE = 20; - static const std::string TIMESTAMP_ALIAS; + static constexpr const char *TIMESTAMP_ALIAS = "naturalbase_rdb_aux_timestamp"; static constexpr const char *LOG_POSTFIX = "_log"; static constexpr const char *META_TABLE_POSTFIX = "metadata"; + static constexpr const char *KNOWLEDGE_TABLE_TYPE = "knowledge"; static constexpr const char *LOG_TABLE_VERSION_3 = "3.0"; static constexpr const char *LOG_TABLE_VERSION_5_1 = "5.01"; @@ -170,7 +174,7 @@ public: static constexpr const char *LOG_TABLE_VERSION_5_10 = "5.10"; // retain downloading asset in update trigger static constexpr const char *LOG_TABLE_VERSION_CURRENT = LOG_TABLE_VERSION_5_10; - static const std::string LOG_TABLE_VERSION_KEY; + static constexpr const char *LOG_TABLE_VERSION_KEY = "log_table_version"; static constexpr const char *REMOTE_DEVICE_SCHEMA_KEY_PREFIX = "remote_device_schema_"; @@ -200,6 +204,10 @@ public: static constexpr const char *KV_LOCAL_TABLE_NAME = "local_data"; static constexpr const char *ROWID = "rowid"; + + static constexpr const char *DEFAULT_USER = "default_user"; + + static constexpr const char *DISTRIBUTED_DEFAULT_APP_ID = "distributeddata"; }; } // namespace DistributedDB #endif // DISTRIBUTEDDB_CONSTANT_H diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h b/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h index ceb9841b4a0550e24aea8dcb4e8380f5490d1894..151dd7c2a7e460fe060c883e736ff0e3348077d1 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h @@ -189,6 +189,8 @@ constexpr const int E_DISTRIBUTED_SCHEMA_CHANGED = (E_BASE + 203); // Schema has constexpr const int E_TABLE_REFERENCE_CHANGED = (E_BASE + 204); // table reference is changed constexpr const int E_CLOUD_DISABLED = (E_BASE + 205); // The cloud switch has been turned off constexpr const int E_DISTRIBUTED_FIELD_DECREASE = (E_BASE + 206); // Sync fewer specified columns than last time +constexpr const int E_NO_TRUSTED_USER = (E_BASE + 207); // No trusted found before device sync +constexpr const int E_FEEDBACK_DB_CLOSING = (E_BASE + 208); // Db was closing feedback from remote device } // namespace DistributedDB #endif // DISTRIBUTEDDB_ERRNO_H diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_types.h b/kv_store/frameworks/libs/distributeddb/common/include/db_types.h index c6194dc628045e20ac306144212f49c0fd92f111..f2eb264c6e461a10615ba16e4048480c66487efa 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_types.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_types.h @@ -183,5 +183,6 @@ struct DeviceTimeInfo { using ObserverAction = std::function; + } // namespace DistributedDB #endif // DISTRIBUTEDDB_TYPES_H diff --git a/kv_store/frameworks/libs/distributeddb/common/include/json_object.h b/kv_store/frameworks/libs/distributeddb/common/include/json_object.h index aa2b0a3789977be0113e80cfa1e48aeb17ee336a..d742dab896cee2e3e760342a9a3f36e7889347f9 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/json_object.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/json_object.h @@ -75,7 +75,7 @@ public: int GetSubFieldPathAndType(const std::set &inPath, std::map &outSubPathType) const; // If inPath not refer to an array, return error. - int GetArraySize(const FieldPath &inPath, uint32_t &outSize) const; + int GetArraySize(const FieldPath &inPath, size_t &outSize) const; // If inPath not refer to an array, return error. If not all members are string or array type, return error. // If array-type member is empty, ignore. If not all members of the array-type member are string, return error. @@ -121,6 +121,9 @@ private: // create if path not exist int MoveToPath(const FieldPath &inPath, Json::Value *&exact, Json::Value *&nearest); + int JsonReaderParseInner(const std::unique_ptr &jsonReader, const char *begin, const char *end, + JSONCPP_STRING &errs); + static uint32_t maxNestDepth_; bool isValid_ = false; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/log_print.h b/kv_store/frameworks/libs/distributeddb/common/include/log_print.h index a7592f66251bebadb0a4b341e998a9ca2a42c742..a4012d50bc0c56b7c290b77f5d8e27fdb5f0552d 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/log_print.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/log_print.h @@ -33,9 +33,10 @@ public: LEVEL_ERROR, LEVEL_FATAL }; - + Logger() = default; virtual ~Logger() {}; static Logger *GetInstance(); + static void DeleteInstance(); static void RegisterLogger(Logger *logger); static void Log(Level level, const std::string &tag, const char *func, int line, const char *format, ...); diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/prepared_stmt.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/prepared_stmt.h index ddcdd9df5ea31fd527d376940c69e709178ca085..792eb184a4a2e88d76c917ecd3888272e79e20c5 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/relational/prepared_stmt.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/prepared_stmt.h @@ -43,8 +43,7 @@ public: int DeSerialize(Parcel &parcel); private: - static const int VERSION_1 = 1; - static const int CURRENT_VERSION = VERSION_1; + static const int CURRENT_VERSION = 1; ExecutorOperation opCode_ = ExecutorOperation::MIN_LIMIT; std::string sql_; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_row_data_set.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_row_data_set.h index 9a69db1487c92be2728b47edd5f4b5bb7545bab2..27376cec9fbc4b08c0470615d7fd634412f33d6c 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_row_data_set.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_row_data_set.h @@ -23,7 +23,7 @@ namespace DistributedDB { class RelationalRowDataSet { public: RelationalRowDataSet(); - virtual ~RelationalRowDataSet(); + ~RelationalRowDataSet(); RelationalRowDataSet(const RelationalRowDataSet &) = delete; RelationalRowDataSet &operator=(const RelationalRowDataSet &) = delete; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h index 3e664718edf9620e2eb7f08ce4d86adc34f27b59..bf4afcc959f9287dd8fbfcb4532b9edecc5eb77f 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h @@ -63,7 +63,8 @@ public: void SetReferenceProperty(const std::vector &referenceProperty); const std::vector &GetReferenceProperty() const; std::set GetSharedTableForChangeTable(std::set &changeTables) const; - std::set CompareReferenceProperty(const std::vector &others) const; + std::set CompareReferenceProperty(const std::vector &others, + bool &isRefNotSet) const; std::map> GetReachableRef(); std::map GetTableWeight(); @@ -77,6 +78,8 @@ public: std::vector GetSyncFieldInfo(const std::string &tableName, bool ignoreTableNonExist = true) const; DistributedTable GetDistributedTable(const std::string &table) const; + + std::map GetTableChangeStatus(const DistributedSchema &schema); private: int CompareAgainstSchemaObject(const std::string &inSchemaString, std::map &cmpRst) const; @@ -136,7 +139,7 @@ private: bool isValid_ = false; // set to true after parse success from string or add at least one relational table SchemaType schemaType_ = SchemaType::RELATIVE; // Default RELATIVE std::string schemaString_; // The minified and valid schemaString - std::string schemaVersion_ = SchemaConstant::SCHEMA_SUPPORT_VERSION_V2; // Default version 2.0 + std::string schemaVersion_ = std::string(SchemaConstant::SCHEMA_SUPPORT_VERSION_V2); // Default version 2.0 TableInfoMap tables_; TableInfoMap trackerTables_; std::vector referenceProperty_; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/table_info.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/table_info.h index 363cd74ef312a7e4e74f8e67b71a60e14bc9fefb..7d90ec51d5ebf1e5187b572f59b1191feeb341e6 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/relational/table_info.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/table_info.h @@ -30,6 +30,8 @@ namespace DistributedDB { using CompositeFields = std::vector; class FieldInfo { public: + FieldInfo() = default; + ~FieldInfo() = default; const std::string &GetFieldName() const; void SetFieldName(const std::string &fileName); const std::string &GetDataType() const; @@ -74,6 +76,8 @@ using FieldInfoMap = std::map using IndexInfoMap = std::map; class TableInfo { public: + TableInfo() = default; + ~TableInfo() = default; const std::string &GetTableName() const; const std::string &GetOriginTableName() const; bool GetSharedTableMark() const; @@ -139,6 +143,8 @@ public: std::vector GetSyncDistributedPk() const; const std::vector GetUniqueAndPkDefine() const; + + std::vector RemovePKCompositeFields(const std::vector &uniqueFields) const; private: void AddFieldDefineString(std::string &attrStr) const; void AddIndexDefineString(std::string &attrStr) const; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/tracker_table.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/tracker_table.h index e46e1e8f4ac720644571a5edf259b0c353f2f81c..22da2f28a1cbfc673ecbc6ed06b7a9afe64a60ba 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/relational/tracker_table.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/tracker_table.h @@ -30,7 +30,7 @@ enum class TriggerModeEnum; class TrackerTable { public: TrackerTable() = default; - virtual ~TrackerTable() {}; + ~TrackerTable() {}; std::string GetTableName() const; const std::set &GetTrackerColNames() const; @@ -49,6 +49,7 @@ public: const std::string GetTempTriggerName(TriggerMode::TriggerModeEnum mode) const; const std::string GetTempUpdateTriggerSql(bool incFlag = false) const; const std::string GetTempDeleteTriggerSql(bool incFlag = false) const; + const std::string GetTempUpdateLogCursorTriggerSql() const; void SetTableName(const std::string &tableName); void SetExtendNames(const std::set &colNames); void SetExtendName(const std::string &colName); @@ -58,13 +59,17 @@ public: bool IsChanging(const TrackerSchema &schema); int ReBuildTempTrigger(sqlite3 *db, TriggerMode::TriggerModeEnum mode, const AfterBuildAction &action); void SetTrackerAction(bool isTrackerAction); - + void SetTriggerObserver(bool isTriggerObserver); + void SetKnowledgeTable(bool isKnowledgeTable); + std::string GetOnChangeType() const; private: std::string tableName_; std::string extendColName_; std::set extendColNames_; std::set trackerColNames_; bool isTrackerAction_ = false; + bool isTriggerObserver_ = true; + bool isKnowledgeTable_ = false; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/common/include/schema_constant.h b/kv_store/frameworks/libs/distributeddb/common/include/schema_constant.h index 479a67fe113c5c67796b49c8d7fbd419201e18ee..93f915bfe180157dfd28d001229bc3d126ddba1a 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/schema_constant.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/schema_constant.h @@ -17,46 +17,45 @@ #define SCHEMA_CONSTANT_H #include -#include // This header is supposed to be included only in source files. Do not include it in any header files. namespace DistributedDB { class SchemaConstant final { public: - static const std::string KEYWORD_SCHEMA_VERSION; - static const std::string KEYWORD_SCHEMA_MODE; - static const std::string KEYWORD_SCHEMA_DEFINE; - static const std::string KEYWORD_SCHEMA_INDEXES; - static const std::string KEYWORD_SCHEMA_SKIPSIZE; - static const std::string KEYWORD_SCHEMA_TYPE; - static const std::string KEYWORD_SCHEMA_TABLE; - static const std::string KEYWORD_INDEX; // For FlatBuffer-Schema - static const std::string KEYWORD_TABLE_MODE; + static constexpr const char *KEYWORD_SCHEMA_VERSION = "SCHEMA_VERSION"; + static constexpr const char *KEYWORD_SCHEMA_MODE = "SCHEMA_MODE"; + static constexpr const char *KEYWORD_SCHEMA_DEFINE = "SCHEMA_DEFINE"; + static constexpr const char *KEYWORD_SCHEMA_INDEXES = "SCHEMA_INDEXES"; + static constexpr const char *KEYWORD_SCHEMA_SKIPSIZE = "SCHEMA_SKIPSIZE"; + static constexpr const char *KEYWORD_SCHEMA_TYPE = "SCHEMA_TYPE"; + static constexpr const char *KEYWORD_SCHEMA_TABLE = "TABLES"; + static constexpr const char *KEYWORD_INDEX = "INDEX"; // For FlatBuffer-Schema + static constexpr const char *KEYWORD_TABLE_MODE = "TABLE_MODE"; - static const std::string KEYWORD_MODE_STRICT; - static const std::string KEYWORD_MODE_COMPATIBLE; + static constexpr const char *KEYWORD_MODE_STRICT = "STRICT"; + static constexpr const char *KEYWORD_MODE_COMPATIBLE = "COMPATIBLE"; - static const std::string KEYWORD_TYPE_BOOL; - static const std::string KEYWORD_TYPE_INTEGER; - static const std::string KEYWORD_TYPE_LONG; - static const std::string KEYWORD_TYPE_DOUBLE; - static const std::string KEYWORD_TYPE_STRING; - static const std::string KEYWORD_TYPE_BOOLEAN; + static constexpr const char *KEYWORD_TYPE_BOOL = "BOOL"; + static constexpr const char *KEYWORD_TYPE_INTEGER = "INTEGER"; + static constexpr const char *KEYWORD_TYPE_LONG = "LONG"; + static constexpr const char *KEYWORD_TYPE_DOUBLE = "DOUBLE"; + static constexpr const char *KEYWORD_TYPE_STRING = "STRING"; + static constexpr const char *KEYWORD_TYPE_BOOLEAN = "BOOLEAN"; - static const std::string KEYWORD_ATTR_NOT_NULL; - static const std::string KEYWORD_ATTR_DEFAULT; - static const std::string KEYWORD_ATTR_VALUE_NULL; - static const std::string KEYWORD_ATTR_VALUE_TRUE; - static const std::string KEYWORD_ATTR_VALUE_FALSE; + static constexpr const char *KEYWORD_ATTR_NOT_NULL = "NOT NULL"; + static constexpr const char *KEYWORD_ATTR_DEFAULT = "DEFAULT"; + static constexpr const char *KEYWORD_ATTR_VALUE_NULL = "null"; + static constexpr const char *KEYWORD_ATTR_VALUE_TRUE = "true"; + static constexpr const char *KEYWORD_ATTR_VALUE_FALSE = "false"; - static const std::string KEYWORD_TABLE_SPLIT_DEVICE; - static const std::string KEYWORD_TABLE_COLLABORATION; + static constexpr const char *KEYWORD_TABLE_SPLIT_DEVICE = "SPLIT_BY_DEVICE"; + static constexpr const char *KEYWORD_TABLE_COLLABORATION = "COLLABORATION"; - static const std::string KEYWORD_TYPE_RELATIVE; - static const std::string SCHEMA_SUPPORT_VERSION; - static const std::string SCHEMA_SUPPORT_VERSION_V2; - static const std::string SCHEMA_SUPPORT_VERSION_V2_1; - static const std::string SCHEMA_CURRENT_VERSION; + static constexpr const char *KEYWORD_TYPE_RELATIVE = "RELATIVE"; + static constexpr const char *SCHEMA_SUPPORT_VERSION = "1.0"; + static constexpr const char *SCHEMA_SUPPORT_VERSION_V2 = "2.0"; + static constexpr const char *SCHEMA_SUPPORT_VERSION_V2_1 = "2.1"; + static constexpr const char *SCHEMA_CURRENT_VERSION = SCHEMA_SUPPORT_VERSION_V2_1; static constexpr const char *REFERENCE_PROPERTY = "REFERENCE_PROPERTY"; static constexpr const char *SOURCE_TABLE_NAME = "SOURCE_TABLE_NAME"; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/schema_utils.h b/kv_store/frameworks/libs/distributeddb/common/include/schema_utils.h index e1aec19db49141c9f0fe37b0ccee2bca502e0bd1..f9610033dfe3039f7be9fd3c10ada6afd78c850b 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/schema_utils.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/schema_utils.h @@ -79,6 +79,8 @@ private: static int TransToString(const std::string &defaultContent, SchemaAttribute &outAttr); static int TransToBool(const std::string &defaultContent, SchemaAttribute &outAttr); + + static void TrimFiled(std::string &inString); }; } // namespace DistributedDB #endif // SCHEMA_UTILS_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/include/version.h b/kv_store/frameworks/libs/distributeddb/common/include/version.h index ca9d5d1b10618cffd4f81826f109b58f0a7ecb15..d224e87c290899217527f7e09d246e883c226e94 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/version.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/version.h @@ -52,6 +52,7 @@ constexpr const uint32_t SOFTWARE_VERSION_RELEASE_10_0 = SOFTWARE_VERSION_BASE + constexpr const uint32_t SOFTWARE_VERSION_RELEASE_11_0 = SOFTWARE_VERSION_BASE + 11; // 11 for tenth released version constexpr const uint32_t SOFTWARE_VERSION_EARLIEST = SOFTWARE_VERSION_RELEASE_1_0; constexpr const uint32_t SOFTWARE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_11_0; +constexpr const uint32_t SOFTWARE_VERSION_MAX = UINT16_MAX; constexpr const int VERSION_INVALID = INT32_MAX; // Storage Related Version diff --git a/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp b/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp index 27721a640a8757b67514926f2cd35af713664f5b..0d9826e876d4b32b2a808cc310291f7c52b55ffb 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp @@ -1039,9 +1039,9 @@ int AutoLaunch::GetAutoLaunchKVProperties(const AutoLaunchParam ¶m, propertiesPtr->SetIntProp(KvDBProperties::SECURITY_LABEL, param.option.secOption.securityLabel); propertiesPtr->SetIntProp(KvDBProperties::SECURITY_FLAG, param.option.secOption.securityFlag); } - propertiesPtr->SetBoolProp(KvDBProperties::COMPRESS_ON_SYNC, param.option.isNeedCompressOnSync); + propertiesPtr->SetBoolProp(DBProperties::COMPRESS_ON_SYNC, param.option.isNeedCompressOnSync); if (param.option.isNeedCompressOnSync) { - propertiesPtr->SetIntProp(KvDBProperties::COMPRESSION_RATE, + propertiesPtr->SetIntProp(DBProperties::COMPRESSION_RATE, ParamCheckUtils::GetValidCompressionRate(param.option.compressionRate)); } propertiesPtr->SetBoolProp(KvDBProperties::SYNC_DUAL_TUPLE_MODE, param.option.syncDualTupleMode); @@ -1071,6 +1071,11 @@ int AutoLaunch::GetAutoLaunchRelationProperties(const AutoLaunchParam ¶m, } propertiesPtr->SetCipherArgs(param.option.cipher, param.option.passwd, param.option.iterateTimes); } + propertiesPtr->SetBoolProp(DBProperties::COMPRESS_ON_SYNC, param.option.isNeedCompressOnSync); + if (param.option.isNeedCompressOnSync) { + propertiesPtr->SetIntProp(DBProperties::COMPRESSION_RATE, + ParamCheckUtils::GetValidCompressionRate(param.option.compressionRate)); + } return E_OK; } diff --git a/kv_store/frameworks/libs/distributeddb/common/src/cloud/assets_download_manager.cpp b/kv_store/frameworks/libs/distributeddb/common/src/cloud/assets_download_manager.cpp index c608ef2f34ea3404c363eb1af24a3ef1d1dfd8ea..1f3ad794474f417d5e6f4337f68716ea8679c706 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/cloud/assets_download_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/cloud/assets_download_manager.cpp @@ -15,7 +15,6 @@ #include "cloud/assets_download_manager.h" #include "cloud/cloud_db_constant.h" - #include "db_errno.h" #include "log_print.h" namespace DistributedDB { diff --git a/kv_store/frameworks/libs/distributeddb/common/src/concurrent_adapter.cpp b/kv_store/frameworks/libs/distributeddb/common/src/concurrent_adapter.cpp index 19198891fe52aa5c71b5e0dcb7497f4b1a8aab57..b0b99011f06f883b722378cb69ea585fd28fe512 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/concurrent_adapter.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/concurrent_adapter.cpp @@ -62,6 +62,11 @@ void ConcurrentAdapter::AdapterAutoUnLock(ffrt::mutex &mutex) { mutex.unlock(); } + +void ConcurrentAdapter::Stop() +{ + ffrt::wait(); +} #else void ConcurrentAdapter::AdapterAutoLock(std::mutex &mutex) { diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp index e735fed762f55427a90f107d7855ee70a497f7fb..36b6acc663597b5b3a14038bae10b946b00004b4 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp @@ -33,16 +33,9 @@ #include "query_sync_object.h" #include "hash.h" #include "runtime_context.h" -#include "value_hash_calc.h" namespace DistributedDB { namespace { - constexpr const int32_t HEAD_SIZE = 3; - constexpr const int32_t END_SIZE = 3; - constexpr const int32_t MIN_SIZE = HEAD_SIZE + END_SIZE + 3; - constexpr const char *REPLACE_CHAIN = "***"; - constexpr const char *DEFAULT_ANONYMOUS = "******"; - void RemoveFiles(const std::list &fileList, OS::FileType type) { for (const auto &item : fileList) { @@ -68,12 +61,10 @@ namespace { } } } - const std::string HEX_CHAR_MAP = "0123456789abcdef"; const std::string CAP_HEX_CHAR_MAP = "0123456789ABCDEF"; } static std::atomic_bool g_isGrdLoaded = false; -static std::mutex g_mutex; int DBCommon::CreateDirectory(const std::string &directory) { @@ -87,12 +78,6 @@ int DBCommon::CreateDirectory(const std::string &directory) return E_OK; } -void DBCommon::StringToVector(const std::string &src, std::vector &dst) -{ - dst.resize(src.size()); - dst.assign(src.begin(), src.end()); -} - void DBCommon::VectorToString(const std::vector &src, std::string &dst) { dst.clear(); @@ -142,57 +127,6 @@ void DBCommon::PrintHexVector(const std::vector &data, int line, const return; } -std::string DBCommon::TransferHashString(const std::string &devName) -{ - if (devName.empty()) { - return ""; - } - std::vector devVect(devName.begin(), devName.end()); - std::vector hashVect; - int errCode = CalcValueHash(devVect, hashVect); - if (errCode != E_OK) { - return ""; - } - - return std::string(hashVect.begin(), hashVect.end()); -} - -std::string DBCommon::TransferStringToHex(const std::string &origStr) -{ - if (origStr.empty()) { - return ""; - } - - std::string tmp; - for (auto item : origStr) { - unsigned char currentByte = static_cast(item); - tmp.push_back(HEX_CHAR_MAP[currentByte >> 4]); // high 4 bits to one hex. - tmp.push_back(HEX_CHAR_MAP[currentByte & 0x0F]); // low 4 bits to one hex. - } - return tmp; -} - -int DBCommon::CalcValueHash(const std::vector &value, std::vector &hashValue) -{ - ValueHashCalc hashCalc; - int errCode = hashCalc.Initialize(); - if (errCode != E_OK) { - return -E_INTERNAL_ERROR; - } - - errCode = hashCalc.Update(value); - if (errCode != E_OK) { - return -E_INTERNAL_ERROR; - } - - errCode = hashCalc.GetResult(hashValue); - if (errCode != E_OK) { - return -E_INTERNAL_ERROR; - } - - return E_OK; -} - int DBCommon::CreateStoreDirectory(const std::string &directory, const std::string &identifierName, const std::string &subDir, bool isCreate) { @@ -346,19 +280,6 @@ std::string DBCommon::StringMasking(const std::string &oriStr, size_t remain) return oriStr; } -std::string DBCommon::StringMiddleMasking(const std::string &name) -{ - if (name.length() <= HEAD_SIZE) { - return DEFAULT_ANONYMOUS; - } - - if (name.length() < MIN_SIZE) { - return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN); - } - - return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE)); -} - std::string DBCommon::GetDistributedTableName(const std::string &device, const std::string &tableName) { if (!RuntimeContext::GetInstance()->ExistTranslateDevIdCallback()) { @@ -399,57 +320,6 @@ void DBCommon::GetDeviceFromName(const std::string &deviceTableName, std::string } } -std::string DBCommon::TrimSpace(const std::string &input) -{ - std::string res; - res.reserve(input.length()); - bool isPreSpace = true; - for (char c : input) { - if (std::isspace(c)) { - isPreSpace = true; - } else { - if (!res.empty() && isPreSpace) { - res += ' '; - } - res += c; - isPreSpace = false; - } - } - res.shrink_to_fit(); - return res; -} - -void DBCommon::RTrim(std::string &oriString) -{ - if (oriString.empty()) { - return; - } - oriString.erase(oriString.find_last_not_of(" ") + 1); -} - -namespace { -bool CharIn(char c, const std::string &pattern) -{ - return std::any_of(pattern.begin(), pattern.end(), [c] (char p) { - return c == p; - }); -} -} - -bool DBCommon::HasConstraint(const std::string &sql, const std::string &keyWord, const std::string &prePattern, - const std::string &nextPattern) -{ - size_t pos = 0; - while ((pos = sql.find(keyWord, pos)) != std::string::npos) { - if (pos >= 1 && CharIn(sql[pos - 1], prePattern) && ((pos + keyWord.length() == sql.length()) || - ((pos + keyWord.length() < sql.length()) && CharIn(sql[pos + keyWord.length()], nextPattern)))) { - return true; - } - pos++; - } - return false; -} - bool DBCommon::IsSameCipher(CipherType srcType, CipherType inputType) { // At present, the default type is AES-256-GCM. @@ -464,33 +334,6 @@ bool DBCommon::IsSameCipher(CipherType srcType, CipherType inputType) return false; } -std::string DBCommon::ToLowerCase(const std::string &str) -{ - std::string res(str.length(), ' '); - std::transform(str.begin(), str.end(), res.begin(), ::tolower); - return res; -} - -std::string DBCommon::ToUpperCase(const std::string &str) -{ - std::string res(str.length(), ' '); - std::transform(str.begin(), str.end(), res.begin(), ::toupper); - return res; -} - -bool DBCommon::CaseInsensitiveCompare(const std::string &first, const std::string &second) -{ - return (strcasecmp(first.c_str(), second.c_str()) == 0); -} - -bool DBCommon::CheckIsAlnumOrUnderscore(const std::string &text) -{ - auto iter = std::find_if_not(text.begin(), text.end(), [](char c) { - return (std::isalnum(c) || c == '_'); - }); - return iter == text.end(); -} - bool DBCommon::CheckQueryWithoutMultiTable(const Query &query) { if (!QuerySyncObject::GetQuerySyncObject(query).empty()) { @@ -763,21 +606,28 @@ uint64_t DBCommon::EraseBit(uint64_t origin, uint64_t eraseBit) return origin & (~eraseBit); } -void DBCommon::LoadGrdLib(void) +void *DBCommon::LoadGrdLib(void) { - std::lock_guard lock(g_mutex); - static std::once_flag loadOnceFlag; - std::call_once(loadOnceFlag, []() { #ifndef _WIN32 - if (!g_isGrdLoaded) { - if (dlopen("libarkdata_db_core.z.so", RTLD_LAZY) != NULL) { - g_isGrdLoaded = true; - } else { - LOGW("[DBCommon] unable to load grd lib, errno: %d, %s", errno, dlerror()); - } - } + auto handle = dlopen("libarkdata_db_core.z.so", RTLD_LAZY); + if (handle == nullptr) { + LOGW("[DBCommon] unable to load grd lib, errno: %d, %s", errno, dlerror()); + return nullptr; + } + return handle; +#else + return nullptr; +#endif +} + +void DBCommon::UnLoadGrdLib(void *handle) +{ +#ifndef _WIN32 + if (handle == nullptr) { + return; + } + dlclose(handle); #endif - }); } bool DBCommon::IsGrdLibLoaded(void) @@ -804,11 +654,6 @@ bool DBCommon::CheckCloudSyncConfigValid(const CloudSyncConfig &config) return true; } -std::string DBCommon::GetCursorKey(const std::string &tableName) -{ - return std::string(DBConstant::RELATIONAL_PREFIX) + "cursor_" + ToLowerCase(tableName); -} - bool DBCommon::ConvertToUInt64(const std::string &str, uint64_t &value) { auto [ptr, errCode] = std::from_chars(str.data(), str.data() + str.size(), value); diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_common_client.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_common_client.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7312f3ad11e3c5d0cecebdb7325d3a7ae0ed0fb2 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/common/src/db_common_client.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2025 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 "db_common.h" +#include "value_hash_calc.h" + +namespace DistributedDB { +namespace { + constexpr const int32_t HEAD_SIZE = 3; + constexpr const int32_t END_SIZE = 3; + constexpr const int32_t MIN_SIZE = HEAD_SIZE + END_SIZE + 3; + constexpr const char *REPLACE_CHAIN = "***"; + constexpr const char *DEFAULT_ANONYMOUS = "******"; + + const std::string HEX_CHAR_MAP = "0123456789abcdef"; +} + +void DBCommon::StringToVector(const std::string &src, std::vector &dst) +{ + dst.resize(src.size()); + dst.assign(src.begin(), src.end()); +} + +std::string DBCommon::StringMiddleMasking(const std::string &name) +{ + if (name.length() <= HEAD_SIZE) { + return DEFAULT_ANONYMOUS; + } + + if (name.length() < MIN_SIZE) { + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN); + } + + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE)); +} + +void DBCommon::RTrim(std::string &oriString) +{ + if (oriString.empty()) { + return; + } + oriString.erase(oriString.find_last_not_of(" ") + 1); +} + +bool DBCommon::CheckIsAlnumOrUnderscore(const std::string &text) +{ + auto iter = std::find_if_not(text.begin(), text.end(), [](char c) { + return (std::isalnum(c) || c == '_'); + }); + return iter == text.end(); +} + +std::string DBCommon::ToLowerCase(const std::string &str) +{ + std::string res(str.length(), ' '); + std::transform(str.begin(), str.end(), res.begin(), ::tolower); + return res; +} + +std::string DBCommon::ToUpperCase(const std::string &str) +{ + std::string res(str.length(), ' '); + std::transform(str.begin(), str.end(), res.begin(), ::toupper); + return res; +} + +int DBCommon::CalcValueHash(const std::vector &value, std::vector &hashValue) +{ + ValueHashCalc hashCalc; + int errCode = hashCalc.Initialize(); + if (errCode != E_OK) { + return -E_INTERNAL_ERROR; + } + + errCode = hashCalc.Update(value); + if (errCode != E_OK) { + return -E_INTERNAL_ERROR; + } + + errCode = hashCalc.GetResult(hashValue); + if (errCode != E_OK) { + return -E_INTERNAL_ERROR; + } + + return E_OK; +} + + +namespace { +bool CharIn(char c, const std::string &pattern) +{ + return std::any_of(pattern.begin(), pattern.end(), [c] (char p) { + return c == p; + }); +} +} +bool DBCommon::HasConstraint(const std::string &sql, const std::string &keyWord, const std::string &prePattern, + const std::string &nextPattern) +{ + size_t pos = 0; + while ((pos = sql.find(keyWord, pos)) != std::string::npos) { + if (pos >= 1 && CharIn(sql[pos - 1], prePattern) && ((pos + keyWord.length() == sql.length()) || + ((pos + keyWord.length() < sql.length()) && CharIn(sql[pos + keyWord.length()], nextPattern)))) { + return true; + } + pos++; + } + return false; +} + +std::string DBCommon::TransferStringToHex(const std::string &origStr) +{ + if (origStr.empty()) { + return ""; + } + + std::string tmp; + for (auto item : origStr) { + unsigned char currentByte = static_cast(item); + tmp.push_back(HEX_CHAR_MAP[currentByte >> 4]); // high 4 bits to one hex. + tmp.push_back(HEX_CHAR_MAP[currentByte & 0x0F]); // low 4 bits to one hex. + } + return tmp; +} + +std::string DBCommon::GetCursorKey(const std::string &tableName) +{ + return std::string(DBConstant::RELATIONAL_PREFIX) + "cursor_" + ToLowerCase(tableName); +} + +std::string DBCommon::TrimSpace(const std::string &input) +{ + std::string res; + res.reserve(input.length()); + bool isPreSpace = true; + for (char c : input) { + if (std::isspace(c)) { + isPreSpace = true; + } else { + if (!res.empty() && isPreSpace) { + res += ' '; + } + res += c; + isPreSpace = false; + } + } + res.shrink_to_fit(); + return res; +} + +std::string DBCommon::TransferHashString(const std::string &devName) +{ + if (devName.empty()) { + return ""; + } + std::vector devVect(devName.begin(), devName.end()); + std::vector hashVect; + int errCode = CalcValueHash(devVect, hashVect); + if (errCode != E_OK) { + return ""; + } + + return std::string(hashVect.begin(), hashVect.end()); +} + +bool DBCommon::CaseInsensitiveCompare(const std::string &first, const std::string &second) +{ + return (strcasecmp(first.c_str(), second.c_str()) == 0); +} +} // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp deleted file mode 100644 index b24c170d8495e20331062afa7542be14770d51d8..0000000000000000000000000000000000000000 --- a/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 "db_constant.h" - -namespace DistributedDB { -const std::string DBConstant::MULTI_SUB_DIR = "multi_ver"; -const std::string DBConstant::SINGLE_SUB_DIR = "single_ver"; -const std::string DBConstant::LOCAL_SUB_DIR = "local"; -const std::string DBConstant::MAINDB_DIR = "main"; -const std::string DBConstant::METADB_DIR = "meta"; -const std::string DBConstant::CACHEDB_DIR = "cache"; -const std::string DBConstant::SYSTEM_TABLE_PREFIX = "naturalbase_rdb_"; -const std::string DBConstant::RELATIONAL_SCHEMA_KEY = "relational_schema"; -const std::string DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY = "relational_tracker_schema"; -const std::string DBConstant::LOG_TABLE_VERSION_KEY = "log_table_version"; -const std::string DBConstant::TIMESTAMP_ALIAS = "naturalbase_rdb_aux_timestamp"; -const std::string DBConstant::UPDATE_META_FUNC = "update_meta_within_trigger"; -const std::string DBConstant::SINGLE_VER_DATA_STORE = "gen_natural_store"; -const std::string DBConstant::SINGLE_VER_META_STORE = "meta"; -const std::string DBConstant::SINGLE_VER_CACHE_STORE = "cache"; -} diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp index a207b4da7e4be6a3b2dc9971436481ff376b030d..c06b461b7de6692e70580a5d6af491037564b6ad 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp @@ -126,25 +126,25 @@ void DBDfxAdapter::ReportBehavior(const ReportTask &reportTask) void DBDfxAdapter::StartTrace(const std::string &action) { - ::StartTrace(HITRACE_LABEL, action); + ::StartTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_LABEL, action.c_str()); } void DBDfxAdapter::FinishTrace() { - ::FinishTrace(HITRACE_LABEL); + ::FinishTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_LABEL); } void DBDfxAdapter::StartTracing() { #ifdef TRACE_SQLITE_EXECUTE - ::StartTrace(HITRACE_LABEL, SQLITE_EXECUTE); + ::StartTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_LABEL, SQLITE_EXECUTE.c_str()); #endif } void DBDfxAdapter::FinishTracing() { #ifdef TRACE_SQLITE_EXECUTE - ::FinishTrace(HITRACE_LABEL); + ::FinishTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_LABEL); #endif } diff --git a/kv_store/frameworks/libs/distributeddb/common/src/json_object.cpp b/kv_store/frameworks/libs/distributeddb/common/src/json_object.cpp index 49c9616c6e0d89223332a4781d9915406eae8193..caf7ce2d7c7d50e5891bdeb5f845034400f804e6 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/json_object.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/json_object.cpp @@ -112,6 +112,16 @@ JsonObject::JsonObject(const Json::Value &value) : isValid_(true), value_(value) { } +int JsonObject::JsonReaderParseInner(const std::unique_ptr &jsonReader, const char *begin, + const char *end, JSONCPP_STRING &errs) +{ + if (!jsonReader->parse(begin, end, &value_, &errs)) { + value_ = Json::Value(); + return -E_JSON_PARSE_FAIL; + } + return E_OK; +} + int JsonObject::Parse(const std::string &inString) { // The jsoncpp lib parser in strict mode will still regard root type jsonarray as valid, but we require jsonobject @@ -126,7 +136,6 @@ int JsonObject::Parse(const std::string &inString) errCode, nestDepth, maxNestDepth_); return -E_JSON_PARSE_FAIL; } -#ifdef JSONCPP_USE_BUILDER JSONCPP_STRING errs; Json::CharReaderBuilder builder; Json::CharReaderBuilder::strictMode(&builder.settings_); @@ -136,19 +145,11 @@ int JsonObject::Parse(const std::string &inString) auto begin = reinterpret_cast(inString.c_str()); auto end = reinterpret_cast(inString.c_str() + inString.length()); - if (!jsonReader->parse(begin, end, &value_, &errs)) { - value_ = Json::Value(); - LOGE("[Json][Parse] Parse string to JsonValue fail, reason=%s.", errs.c_str()); - return -E_JSON_PARSE_FAIL; - } -#else - Json::Reader reader(Json::Features::strictMode()); - if (!reader.parse(inString, value_, false)) { - value_ = Json::Value(); - LOGE("[Json][Parse] Parse string to JsonValue fail, reason=%s.", reader.getFormattedErrorMessages().c_str()); - return -E_JSON_PARSE_FAIL; + errCode = JsonReaderParseInner(jsonReader, begin, end, errs); + if (errCode != E_OK) { + LOGE("[Json][Parse] Parse string to JsonValue fail"); + return errCode; } -#endif // The jsoncpp lib parser in strict mode will still regard root type jsonarray as valid, but we require jsonobject if (value_.type() != Json::ValueType::objectValue) { value_ = Json::Value(); @@ -183,7 +184,6 @@ int JsonObject::Parse(const uint8_t *dataBegin, const uint8_t *dataEnd) errCode, nestDepth, maxNestDepth_); return -E_JSON_PARSE_FAIL; } -#ifdef JSONCPP_USE_BUILDER std::string jsonStr(dataBegin, dataEnd); auto begin = jsonStr.c_str(); auto end = jsonStr.c_str() + jsonStr.size(); @@ -195,22 +195,11 @@ int JsonObject::Parse(const uint8_t *dataBegin, const uint8_t *dataEnd) builder[JSON_CONFIG_REJECT_DUP_KEYS] = false; std::unique_ptr const jsonReader(builder.newCharReader()); // The endDoc parameter of reader::parse refer to the byte after the string itself - if (!jsonReader->parse(begin, end, &value_, &errs)) { - value_ = Json::Value(); - LOGE("[Json][Parse] Parse dataRange to JsonValue fail, reason=%s.", errs.c_str()); - return -E_JSON_PARSE_FAIL; - } -#else - Json::Reader reader(Json::Features::strictMode()); - auto begin = reinterpret_cast(dataBegin); - auto end = reinterpret_cast(dataEnd); - // The endDoc parameter of reader::parse refer to the byte after the string itself - if (!reader.parse(begin, end, value_, false)) { - value_ = Json::Value(); - LOGE("[Json][Parse] Parse dataRange to JsonValue fail, reason=%s.", reader.getFormattedErrorMessages().c_str()); - return -E_JSON_PARSE_FAIL; + errCode = JsonReaderParseInner(jsonReader, begin, end, errs); + if (errCode != E_OK) { + LOGE("[Json][Parse] Parse dataRange to JsonValue fail"); + return errCode; } -#endif // The jsoncpp lib parser in strict mode will still regard root type jsonarray as valid, but we require jsonobject if (value_.type() != Json::ValueType::objectValue) { value_ = Json::Value(); @@ -390,7 +379,7 @@ int JsonObject::GetSubFieldPathAndType(const std::set &inPath, return E_OK; } -int JsonObject::GetArraySize(const FieldPath &inPath, uint32_t &outSize) const +int JsonObject::GetArraySize(const FieldPath &inPath, size_t &outSize) const { if (!isValid_) { LOGE("[Json][GetArraySize] Not Valid Yet."); diff --git a/kv_store/frameworks/libs/distributeddb/common/src/log_print.cpp b/kv_store/frameworks/libs/distributeddb/common/src/log_print.cpp index 372ea9b8ffb2b00cf83426866e800a1b74023607..e1ca3dab8d8e9c582accd14172327a10b7fa454d 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/log_print.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/log_print.cpp @@ -27,6 +27,8 @@ namespace DistributedDB { Logger *Logger::logHandler = nullptr; const std::string Logger::PRIVATE_TAG = "s{private}"; +static std::mutex g_logInstanceLock; +static std::atomic g_logInstance = nullptr; class HiLogger : public Logger { public: @@ -65,17 +67,26 @@ public: Logger *Logger::GetInstance() { - static std::mutex logInstanceLock; - static std::atomic logInstance = nullptr; // For Double-Checked Locking, we need check logInstance twice - if (logInstance == nullptr) { - std::lock_guard lock(logInstanceLock); - if (logInstance == nullptr) { + if (g_logInstance == nullptr) { + std::lock_guard lock(g_logInstanceLock); + if (g_logInstance == nullptr) { // Here, we new logInstance to print log, if new failed, we can do nothing. - logInstance = new (std::nothrow) HiLogger; + g_logInstance = new (std::nothrow) HiLogger; } } - return logInstance; + return g_logInstance; +} + +void Logger::DeleteInstance() +{ + std::lock_guard lock(g_logInstanceLock); + if (g_logInstance == nullptr) { + return; + } + delete g_logInstance.load(); + g_logInstance = nullptr; + logHandler = nullptr; } void Logger::RegisterLogger(Logger *logger) diff --git a/kv_store/frameworks/libs/distributeddb/common/src/param_check_utils.cpp b/kv_store/frameworks/libs/distributeddb/common/src/param_check_utils.cpp index 5fdf237a6473752a137c6151ccd77bc62fc78bb3..868448d185228d5de42e86b2115f32c93d0e3308 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/param_check_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/param_check_utils.cpp @@ -211,24 +211,16 @@ uint8_t ParamCheckUtils::GetValidCompressionRate(uint8_t compressionRate) { // Valid when between 1 and 100. When compressionRate is invalid, change it to default rate. if (compressionRate < 1 || compressionRate > DBConstant::DEFAULT_COMPTRESS_RATE) { - LOGD("Invalid compression rate:%" PRIu8, compressionRate); + LOGW("Invalid compression rate:%" PRIu8, compressionRate); compressionRate = DBConstant::DEFAULT_COMPTRESS_RATE; } return compressionRate; } -bool ParamCheckUtils::CheckRelationalTableName(const std::string &tableName) -{ - if (!DBCommon::CheckIsAlnumOrUnderscore(tableName)) { - return false; - } - return tableName.compare(0, DBConstant::SYSTEM_TABLE_PREFIX.size(), DBConstant::SYSTEM_TABLE_PREFIX) != 0; -} - bool ParamCheckUtils::CheckTableReference(const std::vector &tableReferenceProperty) { if (tableReferenceProperty.empty()) { - LOGI("[CheckTableReference] tableReferenceProperty is empty"); + LOGI("[CheckTableReference] empty"); return true; } diff --git a/relational_store/frameworks/native/gdb/src/transaction.cpp b/kv_store/frameworks/libs/distributeddb/common/src/param_check_utils_client.cpp similarity index 57% rename from relational_store/frameworks/native/gdb/src/transaction.cpp rename to kv_store/frameworks/libs/distributeddb/common/src/param_check_utils_client.cpp index f3e2eedbf0f1f3a127ff5e4c708ba13c938e8e8c..b813ff760b2d1b72d1f7dbe0f5775a326ddb4e91 100644 --- a/relational_store/frameworks/native/gdb/src/transaction.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/param_check_utils_client.cpp @@ -12,21 +12,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "gdb_errors.h" -#include "gdb_transaction.h" -namespace OHOS::DistributedDataAip { -std::pair> Transaction::Create(std::shared_ptr conn) -{ - if (creator_ != nullptr) { - return creator_(std::move(conn)); - } - return { E_ERROR, nullptr }; -} +#include "param_check_utils.h" -int32_t Transaction::RegisterCreator(Creator creator) +#include "db_common.h" + +namespace DistributedDB { +bool ParamCheckUtils::CheckRelationalTableName(const std::string &tableName) { - creator_ = std::move(creator); - return E_OK; + if (!DBCommon::CheckIsAlnumOrUnderscore(tableName)) { + return false; + } + return tableName.compare(0, strlen(DBConstant::SYSTEM_TABLE_PREFIX), DBConstant::SYSTEM_TABLE_PREFIX) != 0; } -} // namespace OHOS::DistributedDataAip +} // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp b/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp index 7fe6fd38875eabed54be99b7c4e71c4b99a33206..788376b3d695901823cf90c181472416eb9bb259 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp @@ -117,10 +117,8 @@ int MakeDBDirectory(const std::string &directory) { int errCode = mkdir(directory.c_str()); if (errCode < 0) { - // 3 means one-third - std::string str = directory.length() == 0 ? "empty directory path" : - directory.substr(0, directory.length() / 3) + "*****" + directory.substr((2 * directory.length()) / 3); - LOGE("[MakeDir] Make directory fail:%d, directory path: %s", errno, str.c_str()); + LOGE("[MakeDir] Make directory fail:%d, %s", errno, + directory.empty() ? "empty directory path" : "directory path error"); return -E_SYSTEM_API_FAIL; } return E_OK; @@ -129,10 +127,10 @@ int MakeDBDirectory(const std::string &directory) int RemoveDBDirectory(const std::string &directory) { #ifdef DB_DEBUG_ENV - LOGD("---> remove db directory: %s", directory.c_str()); + LOGD("---> remove db directory"); #endif int ret = rmdir(directory.c_str()); - LOGI("CheckPathExistence %s ret:%d error %d", directory.c_str(), ret, errno); + LOGI("CheckPathExistence ret:%d error %d", ret, errno); return ret; } @@ -239,13 +237,12 @@ static int GetFilePathAttr(const std::string &topPath, const std::string &relati std::string findPath = std::string(topPath) + "\\*.*"; intptr_t handle = _findfirst(findPath.c_str(), &file); if (handle < 0) { - LOGE("Open dir error:%s %d.", topPath.c_str(), errno); + LOGE("Open dir error: %d.", errno); return -E_INVALID_PATH; } int errCode = E_OK; std::string fileAbsName; struct _stat64 fileStat; - LOGE("find first file %s %s relativePath %s", topPath.c_str(), file.name, relativePath.c_str()); FileAttr fileAttr; do { @@ -260,7 +257,7 @@ static int GetFilePathAttr(const std::string &topPath, const std::string &relati fileAbsName = topPath + "/" + file.name; errCode = _stat64(fileAbsName.c_str(), &fileStat); if (errCode != 0) { - LOGE("[GetFileAttr]Get file stat failed, %s error = %d.", fileAbsName.c_str(), errno); + LOGE("[GetFileAttr]Get file stat failed, error = %d.", errCode); errCode = -E_INVALID_PATH; break; } @@ -269,20 +266,15 @@ static int GetFilePathAttr(const std::string &topPath, const std::string &relati } fileAttr.fileLen = static_cast(fileStat.st_size); files.push_back(fileAttr); - LOGE("find fileAbsName file %s %s %d relativePath %s", topPath.c_str(), file.name, - file.attrib, relativePath.c_str()); if (fileAttr.fileType == PATH) { errCode = GetFilePathAttr(fileAbsName, relativePath + file.name + "/", files, isNeedAllPath); if (errCode != E_OK) { - LOGE("[GetFileAttr]GetFilePathAttr finish, %s error = %d.", topPath.c_str(), errCode); - printf("GetFilePathAttr the finish %s error:%d\n", topPath.c_str(), errCode); + LOGE("[GetFileAttr]GetFilePathAttr failed, error = %d.", errCode); break; } } } while (_findnext(handle, &file) == 0); _findclose(handle); - LOGE("[GetFileAttr]GetFilePathAttr finish, %s error = %d.", topPath.c_str(), errCode); - printf("GetFilePathAttr the finish end %s error:%d\n", topPath.c_str(), errCode); return errCode; } @@ -437,10 +429,8 @@ int MakeDBDirectory(const std::string &directory) { int errCode = mkdir(directory.c_str(), (S_IRWXU | S_IRWXG)); // The permission is 770 for linux based os if (errCode < 0) { - // 3 means one-third - std::string str = directory.length() == 0 ? "empty directory path" : - directory.substr(0, directory.length() / 3) + "*****" + directory.substr((2 * directory.length()) / 3); - LOGE("[MakeDir] Make directory fail:%d, directory path: %s", errno, str.c_str()); + LOGE("[MakeDir] Make directory fail:%d, %s", errno, + directory.empty() ? "empty directory path" : "directory path error"); return -E_SYSTEM_API_FAIL; } return E_OK; diff --git a/kv_store/frameworks/libs/distributeddb/common/src/relational/prepared_stmt.cpp b/kv_store/frameworks/libs/distributeddb/common/src/relational/prepared_stmt.cpp index da4556270a0047fb01c5ba9e9b00c34c31ce1b59..ff26de01bf64389fc67b38820c0e68cf2b52faea 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/relational/prepared_stmt.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/relational/prepared_stmt.cpp @@ -111,33 +111,30 @@ int PreparedStmt::DeSerialize(Parcel &parcel) return -E_PARSE_FAIL; } - // VERSION 1 - if (version >= VERSION_1) { - // opcode - int opCode = 0; - (void)parcel.ReadInt(opCode); - if (parcel.IsError() || opCode <= MIN_LIMIT || opCode >= MAX_LIMIT) { - return -E_PARSE_FAIL; - } - opCode_ = static_cast(opCode); + // opcode + int opCode = 0; + (void)parcel.ReadInt(opCode); + if (parcel.IsError() || opCode <= MIN_LIMIT || opCode >= MAX_LIMIT) { + return -E_PARSE_FAIL; + } + opCode_ = static_cast(opCode); - // sql - (void)parcel.ReadString(sql_); + // sql + (void)parcel.ReadString(sql_); - // bindArgs - int argsCount = 0; - (void)parcel.ReadInt(argsCount); - if (parcel.IsError() || argsCount < 0 || argsCount > static_cast(DBConstant::MAX_SQL_ARGS_COUNT)) { + // bindArgs + int argsCount = 0; + (void)parcel.ReadInt(argsCount); + if (parcel.IsError() || argsCount < 0 || argsCount > static_cast(DBConstant::MAX_SQL_ARGS_COUNT)) { + return -E_PARSE_FAIL; + } + for (int i = 0; i < argsCount; ++i) { + std::string bindArg; + (void)parcel.ReadString(bindArg); + if (parcel.IsError()) { return -E_PARSE_FAIL; } - for (int i = 0; i < argsCount; ++i) { - std::string bindArg; - (void)parcel.ReadString(bindArg); - if (parcel.IsError()) { - return -E_PARSE_FAIL; - } - bindArgs_.emplace_back(std::move(bindArg)); - } + bindArgs_.emplace_back(std::move(bindArg)); } parcel.EightByteAlign(); diff --git a/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp b/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp index f555ad2dc57e6f22be0bf7299e93481ed99282e5..d274ac22028de996653359fcae28f69c7952cbd0 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp @@ -279,16 +279,17 @@ std::set RelationalSchemaObject::GetSharedTableForChangeTable(std:: } std::set RelationalSchemaObject::CompareReferenceProperty( - const std::vector &others) const + const std::vector &others, bool &isRefNotSet) const { std::set changeTables; + isRefNotSet = referenceProperty_.empty(); PropertyCompare(referenceProperty_, others, changeTables); PropertyCompare(others, referenceProperty_, changeTables); if (!changeTables.empty()) { // get shared tables std::set sharedTables = GetSharedTableForChangeTable(changeTables); changeTables.insert(sharedTables.begin(), sharedTables.end()); } - LOGI("[CompareReferenceProperty] changeTables size = %zu", changeTables.size()); + LOGI("[CompareReferenceProperty] size = %zu", changeTables.size()); return changeTables; } @@ -366,7 +367,7 @@ int GetMemberFromJsonObject(const JsonObject &inJsonObject, const std::string &f { if (!inJsonObject.IsFieldPathExist(FieldPath {fieldName})) { if (isNecessary) { - LOGE("[RelationalSchema][Parse] Get schema %s not exist. isNecessary: %d", fieldName.c_str(), isNecessary); + LOGE("[RelationalSchema][Parse] Get schema not exist. isNecessary: %d", isNecessary); return -E_SCHEMA_PARSE_FAIL; } return -E_NOT_FOUND; @@ -375,19 +376,19 @@ int GetMemberFromJsonObject(const JsonObject &inJsonObject, const std::string &f FieldType fieldType; int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {fieldName}, fieldType); if (errCode != E_OK) { - LOGE("[RelationalSchema][Parse] Get schema %s fieldType failed: %d.", fieldName.c_str(), errCode); + LOGE("[RelationalSchema][Parse] Get schema fieldType failed: %d.", errCode); return -E_SCHEMA_PARSE_FAIL; } if (fieldType != expectType) { - LOGE("[RelationalSchema][Parse] Expect %s fieldType %d but: %d.", fieldName.c_str(), + LOGE("[RelationalSchema][Parse] Expect fieldType %d but: %d.", static_cast(expectType), static_cast(fieldType)); return -E_SCHEMA_PARSE_FAIL; } errCode = inJsonObject.GetFieldValueByFieldPath(FieldPath {fieldName}, fieldValue); if (errCode != E_OK) { - LOGE("[RelationalSchema][Parse] Get schema %s value failed: %d.", fieldName.c_str(), errCode); + LOGE("[RelationalSchema][Parse] Get schema value failed: %d.", errCode); return -E_SCHEMA_PARSE_FAIL; } return E_OK; @@ -1520,5 +1521,25 @@ DistributedTable RelationalSchemaObject::GetDistributedTable(const std::string & } return *match; } + +std::map RelationalSchemaObject::GetTableChangeStatus(const DistributedSchema &schema) +{ + std::map res; + std::map, CaseInsensitiveComparator> tableSchema; + for (const auto &table : dbSchema_.tables) { + tableSchema[table.tableName] = table.fields; + } + for (const auto &table : schema.tables) { + if (tableSchema.find(table.tableName) == tableSchema.end()) { + res[table.tableName] = true; + continue; + } + if (CheckDistributedFieldChange(tableSchema[table.tableName], table.fields)) { + res[table.tableName] = true; + continue; + } + } + return res; +} } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/src/relational/table_info.cpp b/kv_store/frameworks/libs/distributeddb/common/src/relational/table_info.cpp index 6a644e608523b73ee5b674b08c2915da21e1e02a..99f9ce13845f91c8bdf3f7738e639ac65e151996 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/relational/table_info.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/relational/table_info.cpp @@ -290,6 +290,11 @@ const std::vector &TableInfo::GetFieldInfos() const if (!fieldInfos_.empty() && fieldInfos_.size() == fields_.size()) { return fieldInfos_; } + if (fields_.size() > DBConstant::MAX_FIELD_NUM) { + LOGE("The number of fields is too large: %zu.", fields_.size()); + fieldInfos_.clear(); + return fieldInfos_; + } fieldInfos_.resize(fields_.size()); if (fieldInfos_.size() != fields_.size()) { LOGE("GetField error, alloc memory failed."); @@ -566,15 +571,34 @@ int TableInfo::CompareCompositeFields(const CompositeFields &local, const Compos return -E_RELATIONAL_TABLE_EQUAL; } +std::vector TableInfo::RemovePKCompositeFields(const std::vector &uniqueFields) const +{ + std::vector uniqueDefines; + for (const auto &compositeFields : uniqueFields) { + bool hasPrimaryKey = false; + for (const auto &fieldName : compositeFields) { + if (IsPrimaryKey(fieldName)) { + hasPrimaryKey = true; + break; + } + } + if (!hasPrimaryKey) { + uniqueDefines.push_back(compositeFields); + } + } + return uniqueDefines; +} + int TableInfo::CompareWithTableUnique(const std::vector &inTableUnique) const { - if (uniqueDefines_.size() != inTableUnique.size()) { + std::vector uniqueDefines = RemovePKCompositeFields(uniqueDefines_); + std::vector curTableUnique = RemovePKCompositeFields(inTableUnique); + if (uniqueDefines.size() != curTableUnique.size()) { return -E_RELATIONAL_TABLE_INCOMPATIBLE; } - - auto itLocal = uniqueDefines_.begin(); - auto itInTable = inTableUnique.begin(); - while (itLocal != uniqueDefines_.end()) { + auto itLocal = uniqueDefines.begin(); + auto itInTable = curTableUnique.begin(); + while (itLocal != uniqueDefines.end()) { if (CompareCompositeFields(*itLocal, *itInTable) != -E_RELATIONAL_TABLE_EQUAL) { return -E_RELATIONAL_TABLE_INCOMPATIBLE; } diff --git a/kv_store/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp b/kv_store/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp index 685740d916782bbfde4683e46e003d00b08644f3..d5b2c5468cf5723c36791eba8903fcac197482cb 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp @@ -81,7 +81,7 @@ const std::string TrackerTable::GetExtendAssignValSql(bool isDelete) const const std::string TrackerTable::GetDiffTrackerValSql() const { if (trackerColNames_.empty() || isTrackerAction_) { - return isTrackerAction_ ? "1" : "0"; + return isTrackerAction_ ? GetOnChangeType() : "0"; } std::string sql = " CASE WHEN ("; size_t index = 0; @@ -92,7 +92,7 @@ const std::string TrackerTable::GetDiffTrackerValSql() const } index++; } - sql += ") THEN 1 ELSE 0 END"; + sql += ") THEN " + GetOnChangeType() + " ELSE 0 END"; return sql; } @@ -213,7 +213,7 @@ const std::string TrackerTable::GetTempInsertTriggerSql(bool incFlag) const sql += "cursor=" + CloudStorageUtils::GetSelectIncCursorSql(tableName_) + " WHERE"; } sql += " hash_key = NEW.hash_key;\n"; - if (!IsEmpty()) { + if (!IsEmpty() && isTriggerObserver_) { sql += "SELECT server_observer('" + tableName_ + "', 1);"; } sql += "\nEND;"; @@ -244,7 +244,7 @@ const std::string TrackerTable::GetTempUpdateTriggerSql(bool incFlag) const sql += "cursor=" + CloudStorageUtils::GetSelectIncCursorSql(tableName_) + " WHERE"; } sql += " data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";\n"; - if (!IsEmpty()) { + if (!IsEmpty() && isTriggerObserver_) { sql += "SELECT server_observer('" + tableName_ + "', " + GetDiffTrackerValSql() + ");"; } sql += "\nEND;"; @@ -277,13 +277,27 @@ const std::string TrackerTable::GetTempDeleteTriggerSql(bool incFlag) const sql.pop_back(); } sql += " WHERE data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";\n"; - if (!IsEmpty()) { + if (!IsEmpty() && isTriggerObserver_) { sql += "SELECT server_observer('" + tableName_ + "', 1);"; } sql += "\nEND;"; return sql; } +const std::string TrackerTable::GetTempUpdateLogCursorTriggerSql() const +{ + std::string sql = "CREATE TEMP TRIGGER IF NOT EXISTS " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName_; + sql += "LOG_ON_UPDATE_TEMP AFTER UPDATE ON " + DBCommon::GetLogTableName(tableName_); + sql += " WHEN (SELECT 1 FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata" + + " WHERE key = 'log_trigger_switch' AND value = 'false')\n"; + sql += "BEGIN\n"; + sql += CloudStorageUtils::GetCursorIncSql(tableName_) + "\n"; + sql += "UPDATE " + DBCommon::GetLogTableName(tableName_) + " SET "; + sql += "cursor=" + CloudStorageUtils::GetSelectIncCursorSql(tableName_) + " WHERE data_key = OLD.data_key;\n"; + sql += "END;"; + return sql; +} + void TrackerTable::SetTableName(const std::string &tableName) { tableName_ = tableName; @@ -382,5 +396,21 @@ void TrackerTable::SetTrackerAction(bool isTrackerAction) { isTrackerAction_ = isTrackerAction; } + +void TrackerTable::SetTriggerObserver(bool isTriggerObserver) +{ + isTriggerObserver_ = isTriggerObserver; +} + +void TrackerTable::SetKnowledgeTable(bool isKnowledgeTable) +{ + isKnowledgeTable_ = isKnowledgeTable; +} + +std::string TrackerTable::GetOnChangeType() const +{ + return isKnowledgeTable_ ? std::to_string(CloudDbConstant::ON_CHANGE_KNOWLEDGE) : + std::to_string(CloudDbConstant::ON_CHANGE_TRACKER); +} } #endif diff --git a/kv_store/frameworks/libs/distributeddb/common/src/schema_constant.cpp b/kv_store/frameworks/libs/distributeddb/common/src/schema_constant.cpp index 9f1dab2a9217d43d8b116abeb6870b13dbccf2f2..7fb32fc198aa6ef523e68be1a8a9e522234050e6 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/schema_constant.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/schema_constant.cpp @@ -16,41 +16,6 @@ #include "schema_constant.h" namespace DistributedDB { -const std::string SchemaConstant::KEYWORD_SCHEMA_VERSION = "SCHEMA_VERSION"; -const std::string SchemaConstant::KEYWORD_SCHEMA_MODE = "SCHEMA_MODE"; -const std::string SchemaConstant::KEYWORD_SCHEMA_DEFINE = "SCHEMA_DEFINE"; -const std::string SchemaConstant::KEYWORD_SCHEMA_INDEXES = "SCHEMA_INDEXES"; -const std::string SchemaConstant::KEYWORD_SCHEMA_SKIPSIZE = "SCHEMA_SKIPSIZE"; -const std::string SchemaConstant::KEYWORD_SCHEMA_TYPE = "SCHEMA_TYPE"; -const std::string SchemaConstant::KEYWORD_SCHEMA_TABLE = "TABLES"; -const std::string SchemaConstant::KEYWORD_INDEX = "INDEX"; // For FlatBuffer-Schema -const std::string SchemaConstant::KEYWORD_TABLE_MODE = "TABLE_MODE"; - -const std::string SchemaConstant::KEYWORD_MODE_STRICT = "STRICT"; -const std::string SchemaConstant::KEYWORD_MODE_COMPATIBLE = "COMPATIBLE"; - -const std::string SchemaConstant::KEYWORD_TYPE_BOOL = "BOOL"; -const std::string SchemaConstant::KEYWORD_TYPE_INTEGER = "INTEGER"; -const std::string SchemaConstant::KEYWORD_TYPE_LONG = "LONG"; -const std::string SchemaConstant::KEYWORD_TYPE_DOUBLE = "DOUBLE"; -const std::string SchemaConstant::KEYWORD_TYPE_STRING = "STRING"; -const std::string SchemaConstant::KEYWORD_TYPE_BOOLEAN = "BOOLEAN"; - -const std::string SchemaConstant::KEYWORD_ATTR_NOT_NULL = "NOT NULL"; -const std::string SchemaConstant::KEYWORD_ATTR_DEFAULT = "DEFAULT"; -const std::string SchemaConstant::KEYWORD_ATTR_VALUE_NULL = "null"; -const std::string SchemaConstant::KEYWORD_ATTR_VALUE_TRUE = "true"; -const std::string SchemaConstant::KEYWORD_ATTR_VALUE_FALSE = "false"; - -const std::string SchemaConstant::KEYWORD_TABLE_SPLIT_DEVICE = "SPLIT_BY_DEVICE"; -const std::string SchemaConstant::KEYWORD_TABLE_COLLABORATION = "COLLABORATION"; - -const std::string SchemaConstant::KEYWORD_TYPE_RELATIVE = "RELATIVE"; -const std::string SchemaConstant::SCHEMA_SUPPORT_VERSION = "1.0"; -const std::string SchemaConstant::SCHEMA_SUPPORT_VERSION_V2 = "2.0"; -const std::string SchemaConstant::SCHEMA_SUPPORT_VERSION_V2_1 = "2.1"; -const std::string SchemaConstant::SCHEMA_CURRENT_VERSION = SCHEMA_SUPPORT_VERSION_V2_1; - const uint32_t SchemaConstant::SCHEMA_META_FEILD_COUNT_MAX = 5; const uint32_t SchemaConstant::SCHEMA_META_FEILD_COUNT_MIN = 3; const uint32_t SchemaConstant::SCHEMA_FEILD_NAME_LENGTH_MAX = 64; diff --git a/kv_store/frameworks/libs/distributeddb/common/src/schema_negotiate.cpp b/kv_store/frameworks/libs/distributeddb/common/src/schema_negotiate.cpp index 2efd5f3962699e2c6568b9e299fe0b7458fc3336..3300e643c55fe3f8b2b5f2ca2ea3e0fd9fa2f6ab 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/schema_negotiate.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/schema_negotiate.cpp @@ -37,14 +37,23 @@ SyncOpinion SchemaNegotiate::MakeLocalSyncOpinion(const SchemaObject &localSchem LOGE("[Schema][Opinion] Remote-type=%" PRIu8 " unrecognized.", remoteSchemaType); return SyncOpinion{false, true, true}; } - // 2. If local-type is KV(Here remote-type is within recognized), Always permit sync. + // 2. If local-type is KV(Here remote-type is within recognized), always permit sync unless remote is JSON. if (localType == SchemaType::NONE) { LOGI("[Schema][Opinion] Local-type KV."); + if (remoteType == SchemaType::JSON) { + LOGE("[Schema][Opinion] Not support sync between KV(local) and JSON(remote)"); + return SyncOpinion{false, true, true}; + } return SyncOpinion{true, false, false}; } - // 3. If remote-type is KV(Here local-type can only be JSON or FLATBUFFER), Always permit sync but need check. + // 3. If remote-type is KV(Here local-type can only be JSON or FLATBUFFER), + // always permit sync unless remote is JSON, but need check. if (remoteType == SchemaType::NONE) { LOGI("[Schema][Opinion] Remote-type KV."); + if (localType == SchemaType::JSON) { + LOGE("[Schema][Opinion] Not support sync between KV(remote) and JSON(local)"); + return SyncOpinion{false, true, true}; + } return SyncOpinion{true, false, true}; } // 4. If local-type differ with remote-type(Here both type can only be JSON or FLATBUFFER), Do not permit sync. diff --git a/kv_store/frameworks/libs/distributeddb/common/src/schema_object.cpp b/kv_store/frameworks/libs/distributeddb/common/src/schema_object.cpp index 2488b497635ca5ac2cdd58ab8634fe42051001f3..c4e90c6550a613eed688499f707e1207450b559c 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/schema_object.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/schema_object.cpp @@ -605,7 +605,7 @@ int SchemaObject::CheckSchemaDefineItemDecideAttribute(const JsonObject& inJsonO // The ParseAndCheckSchemaAttribute do not cope with isIndexable field. Need to set it true here outAttr.isIndexable = true; } else if (inType == FieldType::LEAF_FIELD_ARRAY) { - uint32_t arraySize = 0; + size_t arraySize = 0; errCode = inJsonObject.GetArraySize(inPath, arraySize); if (errCode != E_OK) { LOGE("[Schema][CheckItemDecideAttr] Internal Error: GetArraySize Fail."); diff --git a/kv_store/frameworks/libs/distributeddb/common/src/schema_utils.cpp b/kv_store/frameworks/libs/distributeddb/common/src/schema_utils.cpp index f4814779bfd0e2ac6e09941f7a5b3117c9c298f8..2c662207a4b8fbfe32095fd6e0e4b8ce2ca3d1d8 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/schema_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/schema_utils.cpp @@ -31,14 +31,6 @@ namespace { { return (std::isalnum(character) || character == '_'); } - void TrimFiled(std::string &inString) - { - inString.erase(0, inString.find_first_not_of("\r\t ")); - size_t temp = inString.find_last_not_of("\r\t "); - if (temp < inString.size()) { - inString.erase(temp + 1); - } - } // TYPE, [NOT NULL,] [DEFAULT X] // DEFAULT at last @@ -70,13 +62,13 @@ int SchemaUtils::MakeTrans(const std::string &oriContent, size_t &pos) { if (isspace(oriContent[pos])) { return COLUMN_BLANK; - } else if (oriContent.compare(pos, SchemaConstant::KEYWORD_ATTR_NOT_NULL.size(), + } else if (oriContent.compare(pos, strlen(SchemaConstant::KEYWORD_ATTR_NOT_NULL), SchemaConstant::KEYWORD_ATTR_NOT_NULL) == 0) { - pos = pos + SchemaConstant::KEYWORD_ATTR_NOT_NULL.size() - 1; + pos = pos + strlen(SchemaConstant::KEYWORD_ATTR_NOT_NULL) - 1; return COLUMN_NOT_NULL; - } else if (oriContent.compare(pos, SchemaConstant::KEYWORD_ATTR_DEFAULT.size(), + } else if (oriContent.compare(pos, strlen(SchemaConstant::KEYWORD_ATTR_DEFAULT), SchemaConstant::KEYWORD_ATTR_DEFAULT) == 0) { - pos = pos + SchemaConstant::KEYWORD_ATTR_DEFAULT.size() - 1; + pos = pos + strlen(SchemaConstant::KEYWORD_ATTR_DEFAULT) - 1; return COLUMN_DEFAULT; } else if (std::isalnum(oriContent[pos]) || oriContent[pos] == '\'' || oriContent[pos] == '+' || oriContent[pos] == '-') { @@ -449,13 +441,6 @@ int SchemaUtils::CheckFieldName(const FieldName &inName) return E_OK; } -std::string SchemaUtils::Strip(const std::string &inString) -{ - std::string stripRes = inString; - TrimFiled(stripRes); - return stripRes; -} - std::string SchemaUtils::StripNameSpace(const std::string &inFullName) { auto pos = inFullName.find_last_of('.'); @@ -465,22 +450,6 @@ std::string SchemaUtils::StripNameSpace(const std::string &inFullName) return inFullName.substr(pos + 1); } -std::string SchemaUtils::FieldTypeString(FieldType inType) -{ - static std::map fieldTypeMapString = { - {FieldType::LEAF_FIELD_NULL, "NULL"}, - {FieldType::LEAF_FIELD_BOOL, "BOOL"}, - {FieldType::LEAF_FIELD_INTEGER, "INTEGER"}, - {FieldType::LEAF_FIELD_LONG, "LONG"}, - {FieldType::LEAF_FIELD_DOUBLE, "DOUBLE"}, - {FieldType::LEAF_FIELD_STRING, "STRING"}, - {FieldType::LEAF_FIELD_ARRAY, "ARRAY"}, - {FieldType::LEAF_FIELD_OBJECT, "LEAF_OBJECT"}, - {FieldType::INTERNAL_FIELD_OBJECT, "INTERNAL_OBJECT"}, - }; - return fieldTypeMapString[inType]; -} - std::string SchemaUtils::SchemaTypeString(SchemaType inType) { static std::map schemaTypeMapString { @@ -515,50 +484,4 @@ void SchemaUtils::TransTrackerSchemaToLower(const TrackerSchema &srcSchema, Trac destSchema.trackerColNames.insert(DBCommon::ToLowerCase(srcName)); } } - -int SchemaUtils::ExtractJsonObj(const JsonObject &inJsonObject, const std::string &field, - JsonObject &out) -{ - FieldType fieldType; - auto fieldPath = FieldPath {field}; - int errCode = inJsonObject.GetFieldTypeByFieldPath(fieldPath, fieldType); - if (errCode != E_OK) { - LOGE("[SchemaUtils][ExtractJsonObj] Get schema %s fieldType failed: %d.", field.c_str(), errCode); - return -E_SCHEMA_PARSE_FAIL; - } - if (FieldType::INTERNAL_FIELD_OBJECT != fieldType) { - LOGE("[SchemaUtils][ExtractJsonObj] Expect %s Object but %s.", field.c_str(), - SchemaUtils::FieldTypeString(fieldType).c_str()); - return -E_SCHEMA_PARSE_FAIL; - } - errCode = inJsonObject.GetObjectByFieldPath(fieldPath, out); - if (errCode != E_OK) { - LOGE("[SchemaUtils][ExtractJsonObj] Get schema %s value failed: %d.", field.c_str(), errCode); - return -E_SCHEMA_PARSE_FAIL; - } - return E_OK; -} - -int SchemaUtils::ExtractJsonObjArray(const JsonObject &inJsonObject, const std::string &field, - std::vector &out) -{ - FieldType fieldType; - auto fieldPath = FieldPath {field}; - int errCode = inJsonObject.GetFieldTypeByFieldPath(fieldPath, fieldType); - if (errCode != E_OK) { - LOGE("[SchemaUtils][ExtractJsonObj] Get schema %s fieldType failed: %d.", field.c_str(), errCode); - return -E_SCHEMA_PARSE_FAIL; - } - if (FieldType::LEAF_FIELD_ARRAY != fieldType) { - LOGE("[SchemaUtils][ExtractJsonObj] Expect %s Object but %s.", field.c_str(), - SchemaUtils::FieldTypeString(fieldType).c_str()); - return -E_SCHEMA_PARSE_FAIL; - } - errCode = inJsonObject.GetObjectArrayByFieldPath(fieldPath, out); - if (errCode != E_OK) { - LOGE("[SchemaUtils][ExtractJsonObj] Get schema %s value failed: %d.", field.c_str(), errCode); - return -E_SCHEMA_PARSE_FAIL; - } - return E_OK; -} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/common/src/schema_utils_client.cpp b/kv_store/frameworks/libs/distributeddb/common/src/schema_utils_client.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a981890b3a7adca1998a4921b4c3c74e044adcd0 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/common/src/schema_utils_client.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2025 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 "schema_utils.h" +namespace DistributedDB { +void SchemaUtils::TrimFiled(std::string &inString) +{ + inString.erase(0, inString.find_first_not_of("\r\t ")); + size_t temp = inString.find_last_not_of("\r\t "); + if (temp < inString.size()) { + inString.erase(temp + 1); + } +} + +std::string SchemaUtils::Strip(const std::string &inString) +{ + std::string stripRes = inString; + TrimFiled(stripRes); + return stripRes; +} + +std::string SchemaUtils::FieldTypeString(FieldType inType) +{ + static std::map fieldTypeMapString = { + {FieldType::LEAF_FIELD_NULL, "NULL"}, + {FieldType::LEAF_FIELD_BOOL, "BOOL"}, + {FieldType::LEAF_FIELD_INTEGER, "INTEGER"}, + {FieldType::LEAF_FIELD_LONG, "LONG"}, + {FieldType::LEAF_FIELD_DOUBLE, "DOUBLE"}, + {FieldType::LEAF_FIELD_STRING, "STRING"}, + {FieldType::LEAF_FIELD_ARRAY, "ARRAY"}, + {FieldType::LEAF_FIELD_OBJECT, "LEAF_OBJECT"}, + {FieldType::INTERNAL_FIELD_OBJECT, "INTERNAL_OBJECT"}, + }; + return fieldTypeMapString[inType]; +} + +int SchemaUtils::ExtractJsonObj(const JsonObject &inJsonObject, const std::string &field, + JsonObject &out) +{ + FieldType fieldType; + auto fieldPath = FieldPath {field}; + int errCode = inJsonObject.GetFieldTypeByFieldPath(fieldPath, fieldType); + if (errCode != E_OK) { + LOGE("[SchemaUtils][ExtractJsonObj] Get schema fieldType failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + if (FieldType::INTERNAL_FIELD_OBJECT != fieldType) { + LOGE("[SchemaUtils][ExtractJsonObj] Expect Object but %s.", + SchemaUtils::FieldTypeString(fieldType).c_str()); + return -E_SCHEMA_PARSE_FAIL; + } + errCode = inJsonObject.GetObjectByFieldPath(fieldPath, out); + if (errCode != E_OK) { + LOGE("[SchemaUtils][ExtractJsonObj] Get schema value failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + return E_OK; +} + +int SchemaUtils::ExtractJsonObjArray(const JsonObject &inJsonObject, const std::string &field, + std::vector &out) +{ + FieldType fieldType; + auto fieldPath = FieldPath {field}; + int errCode = inJsonObject.GetFieldTypeByFieldPath(fieldPath, fieldType); + if (errCode != E_OK) { + LOGE("[SchemaUtils][ExtractJsonObjArray] Get schema fieldType failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + if (FieldType::LEAF_FIELD_ARRAY != fieldType) { + LOGE("[SchemaUtils][ExtractJsonObjArray] Expect Array but %s.", + SchemaUtils::FieldTypeString(fieldType).c_str()); + return -E_SCHEMA_PARSE_FAIL; + } + errCode = inJsonObject.GetObjectArrayByFieldPath(fieldPath, out); + if (errCode != E_OK) { + LOGE("[SchemaUtils][ExtractJsonObjArray] Get schema value failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + return E_OK; +} +} // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/common/src/user_change_monitor.cpp b/kv_store/frameworks/libs/distributeddb/common/src/user_change_monitor.cpp index 4a1dabc80880eec4b07e936b8e7d60ed92dd0856..8d0769ff77565928a779034ff714abfaab1cf942 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/user_change_monitor.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/user_change_monitor.cpp @@ -46,6 +46,7 @@ int UserChangeMonitor::Start() void UserChangeMonitor::Stop() { + std::shared_lock lockGuard(userChangeMonitorLock_); if (!isStarted_) { return; } diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/combine_status.h b/kv_store/frameworks/libs/distributeddb/communicator/include/combine_status.h index 931f84ce0558198ac6feb18fe54a4abe1f812901..1f602e88c9c4d30755046cad3e4ed6db3c0015ad 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/combine_status.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/combine_status.h @@ -26,6 +26,8 @@ namespace DistributedDB { */ class CombineStatus { public: + CombineStatus() = default; + ~CombineStatus() = default; void UpdateProgressId(uint64_t inProgressId); uint64_t GetProgressId() const; bool CheckProgress(); diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/communicator_aggregator.h b/kv_store/frameworks/libs/distributeddb/communicator/include/communicator_aggregator.h index 6034cb15e096818c0975b6939f8c3a76981969da..25cec9c961176a34f45414f318e71d125337c4b6 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/communicator_aggregator.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/communicator_aggregator.h @@ -39,8 +39,10 @@ class CommunicatorLinker; struct TaskConfig { bool nonBlock = true; + bool isRetryTask = true; uint32_t timeout = 0u; Priority prio = Priority::NORMAL; + AccessInfos infos; }; /* @@ -93,6 +95,8 @@ public: std::shared_ptr GetExtendHeaderHandle(const ExtendInfo ¶mInfo); void ClearOnlineLabel() override; + + void ResetRetryCount(); private: // Working in a dedicated thread void SendDataRoutine(); @@ -104,23 +108,22 @@ private: void NotifySendableToAllCommunicator(); // Call from Adapter by register these function - void OnBytesReceive(const std::string &srcTarget, const uint8_t *bytes, uint32_t length, - const DataUserInfoProc &userInfoProc); + void OnBytesReceive(const ReceiveBytesInfo &receiveBytesInfo, const DataUserInfoProc &userInfoProc); void OnTargetChange(const std::string &target, bool isConnect); void OnSendable(const std::string &target); - void OnFragmentReceive(const std::string &srcTarget, const uint8_t *bytes, uint32_t length, - const ParseResult &inResult, const DataUserInfoProc &userInfoProc); + void OnFragmentReceive(const ReceiveBytesInfo &receiveBytesInfo, const ParseResult &inResult, + const DataUserInfoProc &userInfoProc); int OnCommLayerFrameReceive(const std::string &srcTarget, const ParseResult &inResult); - int OnAppLayerFrameReceive(const std::string &srcTarget, const uint8_t *bytes, - uint32_t length, const ParseResult &inResult, const DataUserInfoProc &userInfoProc); - int OnAppLayerFrameReceive(const std::string &srcTarget, SerialBuffer *&inFrameBuffer, + int OnAppLayerFrameReceive(const ReceiveBytesInfo &receiveBytesInfo, const ParseResult &inResult, + const DataUserInfoProc &userInfoProc); + int OnAppLayerFrameReceive(const ReceiveBytesInfo &receiveBytesInfo, SerialBuffer *&inFrameBuffer, const ParseResult &inResult, const DataUserInfoProc &userInfoProc); // Function with suffix NoMutex should be called with mutex in the caller - int TryDeliverAppLayerFrameToCommunicatorNoMutex(const std::string &srcTarget, SerialBuffer *&inFrameBuffer, - const LabelType &toLabel, const std::string &userId = ""); + int TryDeliverAppLayerFrameToCommunicatorNoMutex(const DataUserInfoProc &userInfoProc, + const std::string &srcTarget, SerialBuffer *&inFrameBuffer, const LabelType &toLabel, const UserInfo &userInfo); // Auxiliary function for cutting short primary function int RegCallbackToAdapter(); @@ -131,8 +134,9 @@ private: // Feedback related functions void TriggerVersionNegotiation(const std::string &dstTarget); void TryToFeedbackWhenCommunicatorNotFound(const std::string &dstTarget, const LabelType &dstLabel, - const SerialBuffer *inOriFrame); - void TriggerCommunicatorNotFoundFeedback(const std::string &dstTarget, const LabelType &dstLabel, Message* &oriMsg); + const SerialBuffer *inOriFrame, int inErrCode); + void TriggerCommunicatorNotFoundFeedback(const std::string &dstTarget, const LabelType &dstLabel, Message* &oriMsg, + int sendErrNo); // Record the protocol version of remote target. void SetRemoteCommunicatorVersion(const std::string &target, uint16_t version); @@ -164,7 +168,11 @@ private: uint64_t IncreaseSendSequenceId(const std::string &target); int GetDataUserId(const ParseResult &inResult, const LabelType &toLabel, const DataUserInfoProc &userInfoProc, - std::string &userId); + const std::string &device, UserInfo &userInfo); + + int ReTryDeliverAppLayerFrameOnCommunicatorNotFound(const ReceiveBytesInfo &receiveBytesInfo, + SerialBuffer *&inFrameBuffer, const ParseResult &inResult, const DataUserInfoProc &userInfoProc, + const UserInfo &userInfo); DECLARE_OBJECT_TAG(CommunicatorAggregator); diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/frame_retainer.h b/kv_store/frameworks/libs/distributeddb/communicator/include/frame_retainer.h index 4a7c80e9fac4244534c597e05865bf6d0bdf85c4..79837f45002ab70292e916a93e0fb21c9c5b47e0 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/frame_retainer.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/frame_retainer.h @@ -29,12 +29,14 @@ class SerialBuffer; // Forward Declarations struct FrameInfo { SerialBuffer *buffer = nullptr; std::string srcTarget; + std::string sendUser; LabelType commLabel; uint32_t frameId = 0u; }; struct RetainWork { SerialBuffer *buffer = nullptr; + std::string sendUser; uint32_t frameId = 0u; uint32_t remainTime = 0u; // in second }; diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/iadapter.h b/kv_store/frameworks/libs/distributeddb/communicator/include/iadapter.h index d9273d8298eb9ea692d97d687ae52304d9cc76ed..fb8a271b40ae0a9ebf8a93c13606defba94e82a5 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/iadapter.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/iadapter.h @@ -29,8 +29,15 @@ struct DataUserInfoProc { uint32_t length = 0; std::shared_ptr processCommunicator = nullptr; }; +struct ReceiveBytesInfo { + const uint8_t *bytes = nullptr; + const std::string srcTarget; + uint32_t length = 0; + bool isNeedGetUserInfo = true; +}; + // SendableCallback only notify when status changed from unsendable to sendable -using BytesReceiveCallback = std::function; using TargetChangeCallback = std::function; using SendableCallback = std::function; @@ -61,6 +68,8 @@ public: // Return 0 as success. Return negative as error virtual int SendBytes(const std::string &dstTarget, const uint8_t *bytes, uint32_t length, uint32_t totalLength) = 0; + virtual int SendBytes(const DeviceInfos &deviceInfos, const uint8_t *bytes, uint32_t length, + uint32_t totalLength) = 0; // Pass nullptr as inHandle to do unReg if need (inDecRef also nullptr) // Return 0 as success. Return negative as error diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/icommunicator.h b/kv_store/frameworks/libs/distributeddb/communicator/include/icommunicator.h index 4b73ab3262ad8a2cdff11b76cefd71f2ec355e7a..364750d1e6c748e7141b8b43907aa59b06377471 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/icommunicator.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/icommunicator.h @@ -26,12 +26,13 @@ namespace DistributedDB { // inMsg is heap memory, its ownership transfers by calling OnMessageCallback -using OnMessageCallback = std::function; +using OnMessageCallback = std::function; constexpr uint32_t SEND_TIME_OUT = 3000; // 3s struct SendConfig { bool nonBlock = false; bool isNeedExtendHead = false; + bool isRetryTask = true; uint32_t timeout = SEND_TIME_OUT; ExtendInfo paramInfo; }; @@ -82,7 +83,11 @@ public: // Return 0 as success. Return negative as error virtual int SendMessage(const std::string &dstTarget, const Message *inMsg, const SendConfig &config) = 0; virtual int SendMessage(const std::string &dstTarget, const Message *inMsg, const SendConfig &config, - const OnSendEnd &onEnd) = 0; // HW Code Regulation do not allow to use default parameters on virtual function + const OnSendEnd &onEnd) = 0; // Code Regulation do not allow to use default parameters on virtual function + + virtual std::string GetTargetUserId(const ExtendInfo ¶mInfo) const = 0; + + virtual bool ExchangeClosePending(bool expected) = 0; virtual ~ICommunicator() {}; }; diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/message.h b/kv_store/frameworks/libs/distributeddb/communicator/include/message.h index 416e083169cfcdc97e4f464f378ee21e9820d6af..7e6fb17a6d701d9dfeadee6dbb89995c10cb71a4 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/message.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/message.h @@ -142,6 +142,11 @@ public: target_ = inTarget; } + void SetSenderUserId(const std::string &userId) + { + senderUserId_ = userId; + } + void SetPriority(Priority inPriority) { prio_ = inPriority; @@ -185,6 +190,11 @@ public: return target_; } + std::string GetSenderUserId() const + { + return senderUserId_; + } + Priority GetPriority() const { return prio_; @@ -197,7 +207,8 @@ public: bool IsFeedbackError() const { - return (errorNo_ == E_FEEDBACK_UNKNOWN_MESSAGE || errorNo_ == E_FEEDBACK_COMMUNICATOR_NOT_FOUND); + return (errorNo_ == E_FEEDBACK_UNKNOWN_MESSAGE || errorNo_ == E_FEEDBACK_COMMUNICATOR_NOT_FOUND || + errorNo_ == E_FEEDBACK_DB_CLOSING); } private: @@ -212,6 +223,7 @@ private: // Field carry supplemental info std::string target_; + std::string senderUserId_; Priority prio_ = Priority::LOW; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/network_adapter.h b/kv_store/frameworks/libs/distributeddb/communicator/include/network_adapter.h index 06ebd559bd43502abcdada2bc25828efc3f15eae..fc1c390ab95b69d5b0527f3b407f11cd420a302b 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/network_adapter.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/network_adapter.h @@ -46,6 +46,8 @@ public: int SendBytes(const std::string &dstTarget, const uint8_t *bytes, uint32_t length, uint32_t totalLength) override; + int SendBytes(const DeviceInfos &deviceInfos, const uint8_t *bytes, uint32_t length, + uint32_t totalLength) override; int RegBytesReceiveCallback(const BytesReceiveCallback &onReceive, const Finalizer &inOper) override; int RegTargetChangeCallback(const TargetChangeCallback &onChange, const Finalizer &inOper) override; diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/parse_result.h b/kv_store/frameworks/libs/distributeddb/communicator/include/parse_result.h index 2186bbb9601ae5304df4913e3462b35b20c034bd..9cf5cdb7344f6e7254bfba854e185c2801063d62 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/parse_result.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/parse_result.h @@ -23,6 +23,9 @@ namespace DistributedDB { class ParseResult { public: + ParseResult() = default; + ~ParseResult() = default; + void SetFrameId(uint32_t inFrameId) { frameId_ = inFrameId; diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/send_task_scheduler.h b/kv_store/frameworks/libs/distributeddb/communicator/include/send_task_scheduler.h index d5a7553a7db8fa17abbf870925fa9816036d826e..d1b30194dd355deca7c8be1156214d133bfcd715 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/send_task_scheduler.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/send_task_scheduler.h @@ -23,6 +23,7 @@ #include #include #include "communicator_type_define.h" +#include "iprocess_communicator.h" #include "macro_utils.h" namespace DistributedDB { @@ -39,6 +40,8 @@ struct SendTask { OnSendEnd onEnd; uint32_t frameId = 0u; bool isValid = true; + bool isRetryTask = true; + AccessInfos infos; }; struct SendTaskInfo { diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator.cpp index 608adaf912dcdf682d6eacdb16d92f96e0775c3e..5c721205448f66629de682d3ee847537e9ce99b0 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator.cpp @@ -20,7 +20,7 @@ namespace DistributedDB { Communicator::Communicator(CommunicatorAggregator *inCommAggregator, const LabelType &inLabel) - : commAggrHandle_(inCommAggregator), commLabel_(inLabel) + : commAggrHandle_(inCommAggregator), commLabel_(inLabel), dbClosePending_(false) { RefObject::IncObjRef(commAggrHandle_); // Rely on CommunicatorAggregator, hold its reference. } @@ -130,7 +130,9 @@ int Communicator::SendMessage(const std::string &dstTarget, const Message *inMsg return errCode; } - TaskConfig taskConfig {config.nonBlock, config.timeout, inMsg->GetPriority()}; + TaskConfig taskConfig {config.nonBlock, config.isRetryTask, config.timeout, inMsg->GetPriority()}; + taskConfig.infos = {config.paramInfo.appId, config.paramInfo.storeId, config.paramInfo.userId, + config.paramInfo.subUserId}; errCode = commAggrHandle_->ScheduleSendTask(dstTarget, buffer, FrameType::APPLICATION_MESSAGE, taskConfig, onEnd); if (errCode == E_OK) { // if ok, free inMsg, otherwise the caller should take over inMsg @@ -144,29 +146,43 @@ int Communicator::SendMessage(const std::string &dstTarget, const Message *inMsg return errCode; } -void Communicator::OnBufferReceive(const std::string &srcTarget, const SerialBuffer *inBuf) +int Communicator::OnBufferReceive(const std::string &srcTarget, const SerialBuffer *inBuf, + const std::string &sendUser) { std::lock_guard messageHandleLockGuard(messageHandleMutex_); - if (srcTarget.size() != 0 && inBuf != nullptr && onMessageHandle_) { + if (!srcTarget.empty() && inBuf != nullptr && onMessageHandle_) { int error = E_OK; // if error is not E_OK, null pointer will be returned Message *message = ProtocolProto::ToMessage(inBuf, error); - delete inBuf; - inBuf = nullptr; // message is not nullptr if error is E_OK or error is E_NOT_REGISTER. // for the former case the message will be handled and release by sync module. // for the latter case the message is released in TriggerUnknownMessageFeedback. if (error != E_OK) { LOGE("[Comm][Receive] ToMessage fail, label=%.3s, error=%d.", VEC_TO_STR(commLabel_), error); + delete inBuf; + inBuf = nullptr; if (error == -E_VERSION_NOT_SUPPORT) { TriggerVersionNegotiation(srcTarget); } else if (error == -E_NOT_REGISTER) { TriggerUnknownMessageFeedback(srcTarget, message); } - return; + return E_OK; } + if (message->GetMessageType() == TYPE_REQUEST && ExchangeClosePending(false)) { + delete message; + message = nullptr; + LOGW("[Comm][Receive] db closing label=%.3s", VEC_TO_STR(commLabel_)); + return -E_FEEDBACK_DB_CLOSING; + } + message->SetSenderUserId(sendUser); LOGI("[Comm][Receive] label=%.3s, srcTarget=%s{private}.", VEC_TO_STR(commLabel_), srcTarget.c_str()); - onMessageHandle_(srcTarget, message); + error = onMessageHandle_(srcTarget, message); + if (error == -E_FEEDBACK_DB_CLOSING) { + return -E_FEEDBACK_DB_CLOSING; + } + delete inBuf; + inBuf = nullptr; + return E_OK; } else { LOGE("[Comm][Receive] label=%.3s, src.size=%zu or buf or handle invalid.", VEC_TO_STR(commLabel_), srcTarget.size()); @@ -175,6 +191,7 @@ void Communicator::OnBufferReceive(const std::string &srcTarget, const SerialBuf inBuf = nullptr; } } + return E_OK; } void Communicator::OnConnectChange(const std::string &target, bool isConnect) @@ -226,7 +243,7 @@ void Communicator::TriggerVersionNegotiation(const std::string &dstTarget) return; } - TaskConfig config{true, 0, Priority::HIGH}; + TaskConfig config{true, true, 0, Priority::HIGH}; errCode = commAggrHandle_->ScheduleSendTask(dstTarget, buffer, FrameType::EMPTY, config); if (errCode != E_OK) { LOGE("[Comm][TrigVer] Send empty frame fail, errCode=%d", errCode); @@ -259,7 +276,7 @@ void Communicator::TriggerUnknownMessageFeedback(const std::string &dstTarget, M return; } - TaskConfig config{true, 0, Priority::HIGH}; + TaskConfig config{true, true, 0, Priority::HIGH}; errCode = commAggrHandle_->ScheduleSendTask(dstTarget, buffer, FrameType::APPLICATION_MESSAGE, config); if (errCode != E_OK) { LOGE("[Comm][TrigFeedback] Send unknown message feedback frame fail, errCode=%d", errCode); @@ -269,5 +286,19 @@ void Communicator::TriggerUnknownMessageFeedback(const std::string &dstTarget, M } } +std::string Communicator::GetTargetUserId(const ExtendInfo ¶mInfo) const +{ + std::shared_ptr extendHandle = commAggrHandle_->GetExtendHeaderHandle(paramInfo); + if (extendHandle == nullptr) { + return DBConstant::DEFAULT_USER; + } + return extendHandle->GetTargetUserId(); +} + +bool Communicator::ExchangeClosePending(bool expected) +{ + bool curVal = !expected; + return dbClosePending_.compare_exchange_strong(curVal, expected); +} DEFINE_OBJECT_TAG_FACILITIES(Communicator) } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator.h b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator.h index 976ce0ae9488ecf3f4a4b2b4c6f362592a7974f7..b6b9aa4973ad3000f1abba269c6040a550114de3 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator.h @@ -56,7 +56,7 @@ public: const OnSendEnd &onEnd) override; // Call by CommunicatorAggregator directly - void OnBufferReceive(const std::string &srcTarget, const SerialBuffer *inBuf); + int OnBufferReceive(const std::string &srcTarget, const SerialBuffer *inBuf, const std::string &sendUser); // Call by CommunicatorAggregator directly void OnConnectChange(const std::string &target, bool isConnect); @@ -67,6 +67,9 @@ public: // Call by CommunicatorAggregator directly LabelType GetCommunicatorLabel() const; + std::string GetTargetUserId(const ExtendInfo ¶mInfo) const override; + + bool ExchangeClosePending(bool expected) override; private: void TriggerVersionNegotiation(const std::string &dstTarget); void TriggerUnknownMessageFeedback(const std::string &dstTarget, Message* &oriMsg); @@ -81,6 +84,7 @@ private: OnMessageCallback onMessageHandle_; OnConnectCallback onConnectHandle_; std::function onSendableHandle_; + std::atomic dbClosePending_; Finalizer onMessageFinalizer_; Finalizer onConnectFinalizer_; Finalizer onSendableFinalizer_; diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp index ea724de998b34ec55ba20e6e818fb85daa98fde8..14171fa355d91ef6631cbb5f0783b98dc821bb9d 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp @@ -276,7 +276,7 @@ void CommunicatorAggregator::ActivateCommunicator(const LabelType &commLabel, co // Do Redeliver, the communicator is responsible to deal with the frame std::list framesToRedeliver = retainer_.FetchFramesForSpecificCommunicator(commLabel); for (auto &entry : framesToRedeliver) { - commMap_[userId].at(commLabel).first->OnBufferReceive(entry.srcTarget, entry.buffer); + commMap_[userId].at(commLabel).first->OnBufferReceive(entry.srcTarget, entry.buffer, entry.sendUser); } } @@ -326,7 +326,7 @@ int CommunicatorAggregator::ScheduleSendTask(const std::string &dstTarget, Seria std::lock_guard autoLock(sendRecordMutex_); sendRecord_[info.frameId] = {}; } - SendTask task{inBuff, dstTarget, onEnd, info.frameId, true}; + SendTask task{inBuff, dstTarget, onEnd, info.frameId, true, inConfig.isRetryTask, inConfig.infos}; if (inConfig.nonBlock) { errCode = scheduler_.AddSendTaskIntoSchedule(task, inConfig.prio); } else { @@ -337,7 +337,8 @@ int CommunicatorAggregator::ScheduleSendTask(const std::string &dstTarget, Seria return errCode; } TriggerSendData(); - LOGI("[CommAggr][Create] Exit ok, dev=%.3s, frameId=%u", dstTarget.c_str(), info.frameId); + LOGI("[CommAggr][Create] Exit ok, dev=%.3s, frameId=%u, isRetry=%d", dstTarget.c_str(), info.frameId, + task.isRetryTask); return E_OK; } @@ -384,12 +385,13 @@ void CommunicatorAggregator::SendPacketsAndDisposeTask(const SendTask &inTask, u startIndex = sendRecord_[inTask.frameId].sendIndex; } uint64_t currentSendSequenceId = IncreaseSendSequenceId(inTask.dstTarget); + DeviceInfos deviceInfos = {inTask.dstTarget, inTask.infos, inTask.isRetryTask}; for (uint32_t index = startIndex; index < static_cast(eachPacket.size()) && inTask.isValid; ++index) { auto &entry = eachPacket[index]; LOGI("[CommAggr][SendPackets] DoSendBytes, dstTarget=%s{private}, extendHeadLength=%" PRIu32 ", packetLength=%" PRIu32 ".", inTask.dstTarget.c_str(), entry.second.first, entry.second.second); ProtocolProto::DisplayPacketInformation(entry.first + entry.second.first, entry.second.second); - errCode = adapterHandle_->SendBytes(inTask.dstTarget, entry.first, entry.second.second, totalLength); + errCode = adapterHandle_->SendBytes(deviceInfos, entry.first, entry.second.second, totalLength); { std::lock_guard autoLock(sendRecordMutex_); sendRecord_[inTask.frameId].sendIndex = index; @@ -483,24 +485,26 @@ void CommunicatorAggregator::NotifySendableToAllCommunicator() } } -void CommunicatorAggregator::OnBytesReceive(const std::string &srcTarget, const uint8_t *bytes, uint32_t length, +void CommunicatorAggregator::OnBytesReceive(const ReceiveBytesInfo &receiveBytesInfo, const DataUserInfoProc &userInfoProc) { - ProtocolProto::DisplayPacketInformation(bytes, length); + ProtocolProto::DisplayPacketInformation(receiveBytesInfo.bytes, receiveBytesInfo.length); ParseResult packetResult; - int errCode = ProtocolProto::CheckAndParsePacket(srcTarget, bytes, length, packetResult); + int errCode = ProtocolProto::CheckAndParsePacket(receiveBytesInfo.srcTarget, receiveBytesInfo.bytes, + receiveBytesInfo.length, packetResult); if (errCode != E_OK) { LOGE("[CommAggr][Receive] Parse packet fail, errCode=%d.", errCode); if (errCode == -E_VERSION_NOT_SUPPORT) { - TriggerVersionNegotiation(srcTarget); + TriggerVersionNegotiation(receiveBytesInfo.srcTarget); } return; } // Update version of remote target - SetRemoteCommunicatorVersion(srcTarget, packetResult.GetDbVersion()); + SetRemoteCommunicatorVersion(receiveBytesInfo.srcTarget, packetResult.GetDbVersion()); if (dbStatusAdapter_ != nullptr) { - dbStatusAdapter_->SetRemoteOptimizeCommunication(srcTarget, !packetResult.IsSendLabelExchange()); + dbStatusAdapter_->SetRemoteOptimizeCommunication(receiveBytesInfo.srcTarget, + !packetResult.IsSendLabelExchange()); } if (packetResult.GetFrameTypeInfo() == FrameType::EMPTY) { // Empty frame will never be fragmented LOGI("[CommAggr][Receive] Empty frame, just ignore in this version of distributeddb."); @@ -508,14 +512,14 @@ void CommunicatorAggregator::OnBytesReceive(const std::string &srcTarget, const } if (packetResult.IsFragment()) { - OnFragmentReceive(srcTarget, bytes, length, packetResult, userInfoProc); + OnFragmentReceive(receiveBytesInfo, packetResult, userInfoProc); } else if (packetResult.GetFrameTypeInfo() != FrameType::APPLICATION_MESSAGE) { - errCode = OnCommLayerFrameReceive(srcTarget, packetResult); + errCode = OnCommLayerFrameReceive(receiveBytesInfo.srcTarget, packetResult); if (errCode != E_OK) { LOGE("[CommAggr][Receive] CommLayer receive fail, errCode=%d.", errCode); } } else { - errCode = OnAppLayerFrameReceive(srcTarget, bytes, length, packetResult, userInfoProc); + errCode = OnAppLayerFrameReceive(receiveBytesInfo, packetResult, userInfoProc); if (errCode != E_OK) { LOGE("[CommAggr][Receive] AppLayer receive fail, errCode=%d.", errCode); } @@ -570,12 +574,13 @@ void CommunicatorAggregator::OnSendable(const std::string &target) TriggerSendData(); } -void CommunicatorAggregator::OnFragmentReceive(const std::string &srcTarget, const uint8_t *bytes, uint32_t length, +void CommunicatorAggregator::OnFragmentReceive(const ReceiveBytesInfo &receiveBytesInfo, const ParseResult &inResult, const DataUserInfoProc &userInfoProc) { int errorNo = E_OK; ParseResult frameResult; - SerialBuffer *frameBuffer = combiner_.AssembleFrameFragment(bytes, length, inResult, frameResult, errorNo); + SerialBuffer *frameBuffer = combiner_.AssembleFrameFragment(receiveBytesInfo.bytes, receiveBytesInfo.length, + inResult, frameResult, errorNo); if (errorNo != E_OK) { LOGE("[CommAggr][Receive] Combine fail, errCode=%d.", errorNo); return; @@ -591,20 +596,20 @@ void CommunicatorAggregator::OnFragmentReceive(const std::string &srcTarget, con delete frameBuffer; frameBuffer = nullptr; if (errCode == -E_VERSION_NOT_SUPPORT) { - TriggerVersionNegotiation(srcTarget); + TriggerVersionNegotiation(receiveBytesInfo.srcTarget); } return; } if (frameResult.GetFrameTypeInfo() != FrameType::APPLICATION_MESSAGE) { - errCode = OnCommLayerFrameReceive(srcTarget, frameResult); + errCode = OnCommLayerFrameReceive(receiveBytesInfo.srcTarget, frameResult); if (errCode != E_OK) { LOGE("[CommAggr][Receive] CommLayer receive fail after combination, errCode=%d.", errCode); } delete frameBuffer; frameBuffer = nullptr; } else { - errCode = OnAppLayerFrameReceive(srcTarget, frameBuffer, frameResult, userInfoProc); + errCode = OnAppLayerFrameReceive(receiveBytesInfo, frameBuffer, frameResult, userInfoProc); if (errCode != E_OK) { LOGE("[CommAggr][Receive] AppLayer receive fail after combination, errCode=%d.", errCode); } @@ -633,15 +638,15 @@ int CommunicatorAggregator::OnCommLayerFrameReceive(const std::string &srcTarget return E_OK; } -int CommunicatorAggregator::OnAppLayerFrameReceive(const std::string &srcTarget, const uint8_t *bytes, - uint32_t length, const ParseResult &inResult, const DataUserInfoProc &userInfoProc) +int CommunicatorAggregator::OnAppLayerFrameReceive(const ReceiveBytesInfo &receiveBytesInfo, + const ParseResult &inResult, const DataUserInfoProc &userInfoProc) { SerialBuffer *buffer = new (std::nothrow) SerialBuffer(); if (buffer == nullptr) { LOGE("[CommAggr][AppReceive] New SerialBuffer fail."); return -E_OUT_OF_MEMORY; } - int errCode = buffer->SetExternalBuff(bytes, length - inResult.GetPaddingLen(), + int errCode = buffer->SetExternalBuff(receiveBytesInfo.bytes, receiveBytesInfo.length - inResult.GetPaddingLen(), ProtocolProto::GetAppLayerFrameHeaderLength()); if (errCode != E_OK) { LOGE("[CommAggr][AppReceive] SetExternalBuff fail, errCode=%d.", errCode); @@ -649,7 +654,7 @@ int CommunicatorAggregator::OnAppLayerFrameReceive(const std::string &srcTarget, buffer = nullptr; return -E_INTERNAL_ERROR; } - return OnAppLayerFrameReceive(srcTarget, buffer, inResult, userInfoProc); + return OnAppLayerFrameReceive(receiveBytesInfo, buffer, inResult, userInfoProc); } // In early time, we cover "OnAppLayerFrameReceive" totally by commMapMutex_, then search communicator, if not found, @@ -670,58 +675,42 @@ int CommunicatorAggregator::OnAppLayerFrameReceive(const std::string &srcTarget, // Note: during this period, commMap_ maybe changed, and communicator not found before may exist now. // 3:Search communicator under commMapMutex_ again, if found then deliver frame to that communicator and end. // 4:If still not found, retain this frame if need or otherwise send CommunicatorNotFound feedback. -int CommunicatorAggregator::OnAppLayerFrameReceive(const std::string &srcTarget, SerialBuffer *&inFrameBuffer, - const ParseResult &inResult, const DataUserInfoProc &userInfoProc) +int CommunicatorAggregator::OnAppLayerFrameReceive(const ReceiveBytesInfo &receiveBytesInfo, + SerialBuffer *&inFrameBuffer, const ParseResult &inResult, const DataUserInfoProc &userInfoProc) { LabelType toLabel = inResult.GetCommLabel(); - std::string userId; - int ret = GetDataUserId(inResult, toLabel, userInfoProc, userId); - if (ret != E_OK) { - LOGE("[CommAggr][AppReceive] get data user id err, ret=%d", ret); - delete inFrameBuffer; - inFrameBuffer = nullptr; - return ret; + UserInfo userInfo = { .sendUser = DBConstant::DEFAULT_USER }; + if (receiveBytesInfo.isNeedGetUserInfo) { + int ret = GetDataUserId(inResult, toLabel, userInfoProc, receiveBytesInfo.srcTarget, userInfo); + if (ret != E_OK || userInfo.sendUser.empty()) { + LOGE("[CommAggr][AppReceive] get data user id err, ret=%d, empty receiveUser=%d, empty sendUser=%d", ret, + userInfo.receiveUser.empty(), userInfo.sendUser.empty()); + delete inFrameBuffer; + inFrameBuffer = nullptr; + return ret != E_OK ? ret : -E_NO_TRUSTED_USER; + } } { std::lock_guard commMapLockGuard(commMapMutex_); - int errCode = TryDeliverAppLayerFrameToCommunicatorNoMutex(srcTarget, inFrameBuffer, toLabel, userId); + int errCode = TryDeliverAppLayerFrameToCommunicatorNoMutex(userInfoProc, receiveBytesInfo.srcTarget, + inFrameBuffer, toLabel, userInfo); if (errCode == E_OK) { // Attention: Here is equal to E_OK return E_OK; + } else if (errCode == -E_FEEDBACK_DB_CLOSING) { + TryToFeedbackWhenCommunicatorNotFound(receiveBytesInfo.srcTarget, toLabel, inFrameBuffer, + E_FEEDBACK_DB_CLOSING); + delete inFrameBuffer; + inFrameBuffer = nullptr; + return errCode; // The caller will display errCode in log } } LOGI("[CommAggr][AppReceive] Communicator of %.3s not found or nonactivated.", VEC_TO_STR(toLabel)); - int errCode = -E_NOT_FOUND; - { - std::lock_guard onCommLackLockGuard(onCommLackMutex_); - if (onCommLackHandle_) { - errCode = onCommLackHandle_(toLabel, userId); - LOGI("[CommAggr][AppReceive] On CommLack End."); // Log in case callback block this thread - } else { - LOGI("[CommAggr][AppReceive] CommLackHandle invalid currently."); - } - } - // Here we have to lock commMapMutex_ and search communicator again. - std::lock_guard commMapLockGuard(commMapMutex_); - int errCodeAgain = TryDeliverAppLayerFrameToCommunicatorNoMutex(srcTarget, inFrameBuffer, toLabel, userId); - if (errCodeAgain == E_OK) { // Attention: Here is equal to E_OK. - LOGI("[CommAggr][AppReceive] Communicator of %.3s found after try again(rare case).", VEC_TO_STR(toLabel)); - return E_OK; - } - // Here, communicator is still not found, retain or discard according to the result of onCommLackHandle_ - if (errCode != E_OK) { - TryToFeedbackWhenCommunicatorNotFound(srcTarget, toLabel, inFrameBuffer); - delete inFrameBuffer; - inFrameBuffer = nullptr; - return errCode; // The caller will display errCode in log - } - // Do Retention, the retainer is responsible to deal with the frame - retainer_.RetainFrame(FrameInfo{inFrameBuffer, srcTarget, toLabel, inResult.GetFrameId()}); - inFrameBuffer = nullptr; - return E_OK; + return ReTryDeliverAppLayerFrameOnCommunicatorNotFound(receiveBytesInfo, inFrameBuffer, inResult, userInfoProc, + userInfo); } int CommunicatorAggregator::GetDataUserId(const ParseResult &inResult, const LabelType &toLabel, - const DataUserInfoProc &userInfoProc, std::string &userId) + const DataUserInfoProc &userInfoProc, const std::string &device, UserInfo &userInfo) { if (userInfoProc.processCommunicator == nullptr) { LOGE("[CommAggr][GetDataUserId] processCommunicator is nullptr"); @@ -729,30 +718,34 @@ int CommunicatorAggregator::GetDataUserId(const ParseResult &inResult, const Lab } std::string label(toLabel.begin(), toLabel.end()); std::vector userInfos; - DBStatus ret = userInfoProc.processCommunicator->GetDataUserInfo(userInfoProc.data, userInfoProc.length, label, - userInfos); + DataUserInfo dataUserInfo = {userInfoProc.data, userInfoProc.length, label, device}; + DBStatus ret = userInfoProc.processCommunicator->GetDataUserInfo(dataUserInfo, userInfos); LOGI("[CommAggr][GetDataUserId] get data user info, ret=%d", ret); if (ret == NO_PERMISSION) { LOGE("[CommAggr][GetDataUserId] userId dismatched, drop packet"); return ret; } - if (userInfos.size() >= 1) { - userId = userInfos[0].receiveUser; + if (!userInfos.empty()) { + userInfo = userInfos[0]; } else { LOGW("[CommAggr][GetDataUserId] userInfos is empty"); } return E_OK; } -int CommunicatorAggregator::TryDeliverAppLayerFrameToCommunicatorNoMutex(const std::string &srcTarget, - SerialBuffer *&inFrameBuffer, const LabelType &toLabel, const std::string &userId) +int CommunicatorAggregator::TryDeliverAppLayerFrameToCommunicatorNoMutex(const DataUserInfoProc &userInfoProc, + const std::string &srcTarget, SerialBuffer *&inFrameBuffer, const LabelType &toLabel, const UserInfo &userInfo) { // Ignore nonactivated communicator, which is regarded as inexistent - if (commMap_[userId].count(toLabel) != 0 && commMap_[userId].at(toLabel).second) { - commMap_[userId].at(toLabel).first->OnBufferReceive(srcTarget, inFrameBuffer); + const std::string &sendUser = userInfo.sendUser; + const std::string &receiveUser = userInfo.receiveUser; + if (commMap_[receiveUser].count(toLabel) != 0 && commMap_[receiveUser].at(toLabel).second) { + int ret = commMap_[receiveUser].at(toLabel).first->OnBufferReceive(srcTarget, inFrameBuffer, sendUser); // Frame handed over to communicator who is responsible to delete it. The frame is deleted here after return. - inFrameBuffer = nullptr; - return E_OK; + if (ret == E_OK) { + inFrameBuffer = nullptr; + } + return ret; } Communicator *communicator = nullptr; bool isEmpty = false; @@ -762,7 +755,7 @@ int CommunicatorAggregator::TryDeliverAppLayerFrameToCommunicatorNoMutex(const s communicator = entry.second.first; isEmpty = userCommMap.first.empty(); LOGW("[CommAggr][TryDeliver] Found communicator of %s, but required user is %s", - userCommMap.first.c_str(), userId.c_str()); + userCommMap.first.c_str(), receiveUser.c_str()); break; } } @@ -770,10 +763,12 @@ int CommunicatorAggregator::TryDeliverAppLayerFrameToCommunicatorNoMutex(const s break; } } - if (communicator != nullptr && (userId.empty() || isEmpty)) { - communicator->OnBufferReceive(srcTarget, inFrameBuffer); - inFrameBuffer = nullptr; - return E_OK; + if (communicator != nullptr && (receiveUser.empty() || isEmpty)) { + int ret = communicator->OnBufferReceive(srcTarget, inFrameBuffer, sendUser); + if (ret == E_OK) { + inFrameBuffer = nullptr; + } + return ret; } LOGE("[CommAggr][TryDeliver] Communicator not found"); return -E_NOT_FOUND; @@ -783,9 +778,8 @@ int CommunicatorAggregator::RegCallbackToAdapter() { RefObject::IncObjRef(this); // Reference to be hold by adapter int errCode = adapterHandle_->RegBytesReceiveCallback( - [this](const std::string &srcTarget, const uint8_t *bytes, uint32_t length, - const DataUserInfoProc &userInfoProc) { - OnBytesReceive(srcTarget, bytes, length, userInfoProc); + [this](const ReceiveBytesInfo &receiveBytesInfo, const DataUserInfoProc &userInfoProc) { + OnBytesReceive(receiveBytesInfo, userInfoProc); }, [this]() { RefObject::DecObjRef(this); }); if (errCode != E_OK) { RefObject::DecObjRef(this); // Rollback in case reg failed @@ -804,11 +798,9 @@ int CommunicatorAggregator::RegCallbackToAdapter() RefObject::IncObjRef(this); // Reference to be hold by adapter errCode = adapterHandle_->RegSendableCallback([this](const std::string &target, int deviceCommErrCode) { LOGI("[CommAggr] Send able dev=%.3s, deviceCommErrCode=%d", target.c_str(), deviceCommErrCode); - if (deviceCommErrCode == E_OK) { - (void)IncreaseSendSequenceId(target); - OnSendable(target); - } + (void)IncreaseSendSequenceId(target); scheduler_.SetDeviceCommErrCode(target, deviceCommErrCode); + OnSendable(target); }, [this]() { RefObject::DecObjRef(this); }); if (errCode != E_OK) { @@ -862,7 +854,7 @@ void CommunicatorAggregator::TriggerVersionNegotiation(const std::string &dstTar return; } - TaskConfig config{true, 0, Priority::HIGH}; + TaskConfig config{true, true, 0, Priority::HIGH}; errCode = ScheduleSendTask(dstTarget, buffer, FrameType::EMPTY, config); if (errCode != E_OK) { LOGE("[CommAggr][TrigVer] Send empty frame fail, errCode=%d", errCode); @@ -873,7 +865,7 @@ void CommunicatorAggregator::TriggerVersionNegotiation(const std::string &dstTar } void CommunicatorAggregator::TryToFeedbackWhenCommunicatorNotFound(const std::string &dstTarget, - const LabelType &dstLabel, const SerialBuffer *inOriFrame) + const LabelType &dstLabel, const SerialBuffer *inOriFrame, int inErrCode) { if (!isCommunicatorNotFoundFeedbackEnable_ || dstTarget.empty() || inOriFrame == nullptr) { return; @@ -887,11 +879,11 @@ void CommunicatorAggregator::TryToFeedbackWhenCommunicatorNotFound(const std::st return; } // Message is release in TriggerCommunicatorNotFoundFeedback - TriggerCommunicatorNotFoundFeedback(dstTarget, dstLabel, message); + TriggerCommunicatorNotFoundFeedback(dstTarget, dstLabel, message, inErrCode); } void CommunicatorAggregator::TriggerCommunicatorNotFoundFeedback(const std::string &dstTarget, - const LabelType &dstLabel, Message* &oriMsg) + const LabelType &dstLabel, Message* &oriMsg, int sendErrNo) { if (oriMsg == nullptr || oriMsg->GetMessageType() != TYPE_REQUEST) { LOGI("[CommAggr][TrigNotFound] Do nothing for message with type not request."); @@ -903,7 +895,7 @@ void CommunicatorAggregator::TriggerCommunicatorNotFoundFeedback(const std::stri LOGI("[CommAggr][TrigNotFound] Do communicator not found feedback with target=%s{private}.", dstTarget.c_str()); oriMsg->SetMessageType(TYPE_RESPONSE); - oriMsg->SetErrorNo(E_FEEDBACK_COMMUNICATOR_NOT_FOUND); + oriMsg->SetErrorNo(sendErrNo); int errCode = E_OK; SerialBuffer *buffer = ProtocolProto::BuildFeedbackMessageFrame(oriMsg, dstLabel, errCode); @@ -914,7 +906,7 @@ void CommunicatorAggregator::TriggerCommunicatorNotFoundFeedback(const std::stri return; } - TaskConfig config{true, 0, Priority::HIGH}; + TaskConfig config{true, true, 0, Priority::HIGH}; errCode = ScheduleSendTask(dstTarget, buffer, FrameType::APPLICATION_MESSAGE, config); if (errCode != E_OK) { LOGE("[CommAggr][TrigNotFound] Send communicator not found feedback frame fail, errCode=%d", errCode); @@ -1102,12 +1094,12 @@ void CommunicatorAggregator::RetrySendTaskIfNeed(const std::string &target, uint std::lock_guard autoLock(retryCountMutex_); retryCount_[target] = 0; } else { + RetrySendTask(target, sendSequenceId); if (sendSequenceId != GetSendSequenceId(target)) { LOGD("[CommAggr] %.3s Send sequence id has changed", target.c_str()); return; } scheduler_.DelayTaskByTarget(target); - RetrySendTask(target, sendSequenceId); } } @@ -1170,5 +1162,51 @@ void CommunicatorAggregator::ClearOnlineLabel() } commLinker_->ClearOnlineLabel(); } + +int CommunicatorAggregator::ReTryDeliverAppLayerFrameOnCommunicatorNotFound(const ReceiveBytesInfo &receiveBytesInfo, + SerialBuffer *&inFrameBuffer, const ParseResult &inResult, const DataUserInfoProc &userInfoProc, + const UserInfo &userInfo) +{ + LabelType toLabel = inResult.GetCommLabel(); + int errCode = -E_NOT_FOUND; + { + std::lock_guard onCommLackLockGuard(onCommLackMutex_); + if (onCommLackHandle_) { + errCode = onCommLackHandle_(toLabel, userInfo.receiveUser); + LOGI("[CommAggr][AppReceive] On CommLack End."); // Log in case callback block this thread + } else { + LOGI("[CommAggr][AppReceive] CommLackHandle invalid currently."); + } + } + // Here we have to lock commMapMutex_ and search communicator again. + std::lock_guard commMapLockGuard(commMapMutex_); + int errCodeAgain = TryDeliverAppLayerFrameToCommunicatorNoMutex(userInfoProc, receiveBytesInfo.srcTarget, + inFrameBuffer, toLabel, userInfo); + if (errCodeAgain == E_OK) { // Attention: Here is equal to E_OK. + LOGI("[CommAggr][AppReceive] Communicator of %.3s found after try again(rare case).", VEC_TO_STR(toLabel)); + return E_OK; + } + // Here, communicator is still not found, retain or discard according to the result of onCommLackHandle_ + if (errCode != E_OK || errCodeAgain == -E_FEEDBACK_DB_CLOSING) { + TryToFeedbackWhenCommunicatorNotFound(receiveBytesInfo.srcTarget, toLabel, inFrameBuffer, + errCodeAgain == -E_FEEDBACK_DB_CLOSING ? E_FEEDBACK_DB_CLOSING : E_FEEDBACK_COMMUNICATOR_NOT_FOUND); + if (inFrameBuffer != nullptr) { + delete inFrameBuffer; + inFrameBuffer = nullptr; + } + return errCode == E_OK ? errCodeAgain : errCode; // The caller will display errCode in log + } + // Do Retention, the retainer is responsible to deal with the frame + retainer_.RetainFrame(FrameInfo{inFrameBuffer, receiveBytesInfo.srcTarget, userInfo.sendUser, toLabel, + inResult.GetFrameId()}); + inFrameBuffer = nullptr; + return E_OK; +} + +void CommunicatorAggregator::ResetRetryCount() +{ + std::lock_guard autoLock(retryCountMutex_); + retryCount_.clear(); +} DEFINE_OBJECT_TAG_FACILITIES(CommunicatorAggregator) } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_linker.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_linker.cpp index 3bf8832b14449680758b42864ee5cd708da7129d..83513365b52b23d83d1cb58efb1e696e558bd7ae 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_linker.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_linker.cpp @@ -394,7 +394,7 @@ void CommunicatorLinker::SendLabelExchange(const std::string &toTarget, SerialBu int error = E_OK; SerialBuffer *cloneBuffer = inBuff->Clone(error); - TaskConfig config{true, 0, Priority::HIGH}; + TaskConfig config{true, true, 0, Priority::HIGH}; int errCode = aggregator_->ScheduleSendTask(toTarget, inBuff, FrameType::COMMUNICATION_LABEL_EXCHANGE, config); if (errCode == E_OK) { // Send ok, go on to wait ack, and maybe resend @@ -452,7 +452,7 @@ void CommunicatorLinker::SendLabelExchangeAck(const std::string &toTarget, Seria return; } - TaskConfig config{true, 0, Priority::HIGH}; + TaskConfig config{true, true, 0, Priority::HIGH}; int errCode = aggregator_->ScheduleSendTask(toTarget, inBuff, FrameType::COMMUNICATION_LABEL_EXCHANGE_ACK, config); if (errCode == E_OK) { // Send ok, finish event diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/frame_retainer.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/frame_retainer.cpp index fc0eb0bba34e92d7e70e332ddcf617d049098ac0..b1b42011efd8a87b6ad92ea8237eaff815a88f8e 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/frame_retainer.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/frame_retainer.cpp @@ -85,7 +85,7 @@ void FrameRetainer::RetainFrame(const FrameInfo &inFrame) if (inFrame.buffer == nullptr) { return; // Never gonna happen } - RetainWork work{inFrame.buffer, inFrame.frameId, MAX_RETAIN_TIME}; + RetainWork work{inFrame.buffer, inFrame.sendUser, inFrame.frameId, MAX_RETAIN_TIME}; if (work.buffer->GetSize() > MAX_RETAIN_FRAME_SIZE) { LOGE("[Retainer][Retain] Frame size=%u over limit=%u.", work.buffer->GetSize(), MAX_RETAIN_FRAME_SIZE); delete work.buffer; @@ -140,7 +140,7 @@ std::list FrameRetainer::FetchFramesForSpecificCommunicator(const Lab for (auto &entry : fetchOrder) { RetainWork &work = perLabel[entry.second][entry.first]; LogRetainInfo("[Retainer][Fetch] FETCH-OUT", inCommLabel, entry.second, entry.first, work); - outFrameList.emplace_back(FrameInfo{work.buffer, entry.second, inCommLabel, work.frameId}); + outFrameList.emplace_back(FrameInfo{work.buffer, entry.second, work.sendUser, inCommLabel, work.frameId}); // Update statistics totalSizeByByte_ -= work.buffer->GetSize(); totalRetainFrames_--; diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/network_adapter.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/network_adapter.cpp index d3071c96ff91db19683c8710d9a12bd0c1e94c55..6a4ac21b84e9151f28bbb550a04ec9ea71da49d0 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/network_adapter.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/network_adapter.cpp @@ -104,7 +104,7 @@ int NetworkAdapter::StartAdapter() // so processCommunicator_ won't be null void NetworkAdapter::StopAdapter() { - LOGI("[NAdapt][Stop] Enter, ProcessLabel=%s.", processLabel_.c_str()); + LOGI("[NAdapt][Stop] Enter."); processCommunicator_->RegOnSendAble(nullptr); DBStatus errCode = processCommunicator_->RegOnDeviceChange(nullptr); if (errCode != DBStatus::OK) { @@ -232,15 +232,21 @@ int NetworkAdapter::GetLocalIdentity(std::string &outTarget) } int NetworkAdapter::SendBytes(const std::string &dstTarget, const uint8_t *bytes, uint32_t length, uint32_t totalLength) +{ + DeviceInfos dstDevInfo; + dstDevInfo.identifier = dstTarget; + return SendBytes(dstDevInfo, bytes, length, totalLength); +} + +int NetworkAdapter::SendBytes(const DeviceInfos &deviceInfos, const uint8_t *bytes, uint32_t length, + uint32_t totalLength) { if (bytes == nullptr || length == 0) { return -E_INVALID_ARGS; } - LOGI("[NAdapt][SendBytes] Enter, to=%s{private}, length=%u, totalLength=%u", dstTarget.c_str(), length, + LOGI("[NAdapt][SendBytes] Enter, to=%s{private}, length=%u, totalLength=%u", deviceInfos.identifier.c_str(), length, totalLength); - DeviceInfos dstDevInfo; - dstDevInfo.identifier = dstTarget; - DBStatus errCode = processCommunicator_->SendData(dstDevInfo, bytes, length, + DBStatus errCode = processCommunicator_->SendData(deviceInfos, bytes, length, totalLength > length ? totalLength : length); if (errCode == DBStatus::RATE_LIMIT) { LOGD("[NAdapt][SendBytes] rate limit!"); @@ -253,7 +259,7 @@ int NetworkAdapter::SendBytes(const std::string &dstTarget, const uint8_t *bytes // OnDeviceChangeHandler is reused but check the existence of peer process is done outerly. // Since this thread is the sending_thread of the CommunicatorAggregator, // We need an async task which bring about dependency on the lifecycle of this NetworkAdapter Object. - CheckDeviceOfflineAfterSendFail(dstDevInfo); + CheckDeviceOfflineAfterSendFail(deviceInfos); return static_cast(errCode); } return E_OK; @@ -284,11 +290,16 @@ void NetworkAdapter::OnDataReceiveHandler(const DeviceInfos &srcDevInfo, const u return; } uint32_t headLength = 0; - DBStatus errCode = processCommunicator_->GetDataHeadInfo(data, length, headLength); + DataHeadInfo dataHeadInfo = {data, length, srcDevInfo.identifier}; + DBStatus errCode = processCommunicator_->GetDataHeadInfo(dataHeadInfo, headLength); LOGI("[NAdapt][OnDataRecv] Enter, from=%s{private}, extendHeadLength=%u, totalLength=%u", srcDevInfo.identifier.c_str(), headLength, length); + bool isNeedGetUserInfo = headLength != 0; if (errCode != OK) { - LOGW("[NAdapt][OnDataRecv] get data head info err, drop packet, errCode=%d", errCode); + LOGW("[NAdapt][OnDataRecv] get data head info err, errCode=%d", errCode); + if (errCode == LOW_VERSION_TARGET) { + isNeedGetUserInfo = true; + } } if (headLength >= length) { LOGW("[NAdapt][OnDataRecv] head len is too big, drop packet"); @@ -301,7 +312,9 @@ void NetworkAdapter::OnDataReceiveHandler(const DeviceInfos &srcDevInfo, const u return; } DataUserInfoProc userInfoProc = {data, length, processCommunicator_}; - onReceiveHandle_(srcDevInfo.identifier, data + headLength, length - headLength, userInfoProc); + ReceiveBytesInfo receiveBytesInfo = {data + headLength, srcDevInfo.identifier, length - headLength, + isNeedGetUserInfo}; + onReceiveHandle_(receiveBytesInfo, userInfoProc); } // These code is compensation for the probable defect of IProcessCommunicator implementation. // As described in the agreement, for the missed online situation, we check the source dev when received. diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.cpp index d5339ebb0168435f9f59365dacdbb3d503dfcf96..158ef713de3632ef1949b1a1d1276e07fa35c9fc 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.cpp @@ -360,12 +360,14 @@ int ProtocolProto::CombinePacketIntoFrame(SerialBuffer *inFrame, const uint8_t * { // inFrame is the destination, pktBytes and pktLength are the source, fragOffset and fragLength give the boundary // Firstly: Check the length relation of source, even this check is not supposed to fail - if (sizeof(CommPhyHeader) + sizeof(CommPhyOptHeader) + fragLength > pktLength) { + if (sizeof(CommPhyHeader) + sizeof(CommPhyOptHeader) + fragLength > pktLength || + sizeof(CommPhyHeader) + static_cast(fragOffset) + static_cast(fragLength) > UINT32_MAX) { return -E_LENGTH_ERROR; } // Secondly: Check the length relation of destination, even this check is not supposed to fail auto frameByteLen = inFrame->GetWritableBytesForEntireFrame(); - if (sizeof(CommPhyHeader) + fragOffset + fragLength > frameByteLen.second) { + if (frameByteLen.first == nullptr || sizeof(CommPhyHeader) + fragOffset + fragLength > frameByteLen.second || + sizeof(CommPhyHeader) + fragOffset > frameByteLen.second) { return -E_LENGTH_ERROR; } // Finally: Do Combination! @@ -715,7 +717,8 @@ bool ProtocolProto::IsSupportMessageVersion(uint16_t version) bool ProtocolProto::IsFeedbackErrorMessage(uint32_t errorNo) { - return (errorNo == E_FEEDBACK_UNKNOWN_MESSAGE || errorNo == E_FEEDBACK_COMMUNICATOR_NOT_FOUND); + return (errorNo == E_FEEDBACK_UNKNOWN_MESSAGE || errorNo == E_FEEDBACK_COMMUNICATOR_NOT_FOUND || + errorNo == E_FEEDBACK_DB_CLOSING); } int ProtocolProto::ParseCommPhyHeaderCheckMagicAndVersion(const uint8_t *bytes, uint32_t length) diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/send_task_scheduler.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/send_task_scheduler.cpp index d3df2bab48e250bf7d88ac6692e55735bbfeea51..abdae7356d649f7772c9123111523c85f37148f8 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/send_task_scheduler.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/send_task_scheduler.cpp @@ -318,5 +318,28 @@ void SendTaskScheduler::SetDeviceCommErrCode(const std::string &target, int devi { std::lock_guard overallLockGuard(overallMutex_); deviceCommErrCodeMap_[target] = deviceCommErrCode; + if (deviceCommErrCode == E_OK) { + return; + } + for (const auto &priority : priorityOrder_) { + if (taskCountByPrio_[priority] == 0 || + taskGroupByPrio_[priority].find(target) == taskGroupByPrio_[priority].end()) { + // No task of this priority or target + continue; + } + for (auto &sendTask : taskGroupByPrio_[priority][target]) { + if (sendTask.isRetryTask) { + continue; + } + LOGI("[Scheduler][SetDeviceCommErrCode] Erase task that do not allow retries, target=%.3s", + target.c_str()); + sendTask.isValid = false; + if (sendTask.onEnd) { + LOGI("[Scheduler][SetDeviceCommErrCode] On Send End, target=%.3s", target.c_str()); + sendTask.onEnd(deviceCommErrCodeMap_[target], true); + sendTask.onEnd = nullptr; + } + } + } } } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/distributeddb.gni b/kv_store/frameworks/libs/distributeddb/distributeddb.gni index def61407b0d06055329272bcdbdb3397fd97ddc8..42d576988c84296fa45c0fc01cd35c116e4f0d7a 100644 --- a/kv_store/frameworks/libs/distributeddb/distributeddb.gni +++ b/kv_store/frameworks/libs/distributeddb/distributeddb.gni @@ -26,8 +26,8 @@ distributeddb_src = [ "${distributeddb_path}/common/src/data_compression.cpp", "${distributeddb_path}/common/src/data_value.cpp", "${distributeddb_path}/common/src/db_common.cpp", + "${distributeddb_path}/common/src/db_common_client.cpp", "${distributeddb_path}/common/src/db_base64_utils.cpp", - "${distributeddb_path}/common/src/db_constant.cpp", "${distributeddb_path}/common/src/db_dfx_adapter.cpp", "${distributeddb_path}/common/src/db_dump_helper.cpp", "${distributeddb_path}/common/src/evloop/src/event_impl.cpp", @@ -43,6 +43,7 @@ distributeddb_src = [ "${distributeddb_path}/common/src/log_print.cpp", "${distributeddb_path}/common/src/notification_chain.cpp", "${distributeddb_path}/common/src/param_check_utils.cpp", + "${distributeddb_path}/common/src/param_check_utils_client.cpp", "${distributeddb_path}/common/src/parcel.cpp", "${distributeddb_path}/common/src/performance_analysis.cpp", "${distributeddb_path}/common/src/platform_specific.cpp", @@ -62,6 +63,7 @@ distributeddb_src = [ "${distributeddb_path}/common/src/schema_negotiate.cpp", "${distributeddb_path}/common/src/schema_object.cpp", "${distributeddb_path}/common/src/schema_utils.cpp", + "${distributeddb_path}/common/src/schema_utils_client.cpp", "${distributeddb_path}/common/src/semaphore_utils.cpp", "${distributeddb_path}/common/src/task_pool.cpp", "${distributeddb_path}/common/src/task_pool_impl.cpp", @@ -96,10 +98,11 @@ distributeddb_src = [ "${distributeddb_path}/interfaces/src/relational/relational_store_changed_data_impl.cpp", "${distributeddb_path}/interfaces/src/relational/relational_store_delegate_impl.cpp", "${distributeddb_path}/interfaces/src/relational/relational_store_manager.cpp", - "${distributeddb_path}/interfaces/src/relational/relational_store_sqlite_ext.cpp", + "${distributeddb_path}/interfaces/src/relational/relational_store_manager_client.cpp", "${distributeddb_path}/interfaces/src/runtime_config.cpp", "${distributeddb_path}/storage/src/cloud/cloud_meta_data.cpp", "${distributeddb_path}/storage/src/cloud/cloud_storage_utils.cpp", + "${distributeddb_path}/storage/src/cloud/cloud_storage_utils_client.cpp", "${distributeddb_path}/storage/src/cloud/cloud_upload_recorder.cpp", "${distributeddb_path}/storage/src/cloud/schema_mgr.cpp", "${distributeddb_path}/storage/src/data_transformer.cpp", @@ -171,6 +174,7 @@ distributeddb_src = [ "${distributeddb_path}/storage/src/sqlite/relational/sqlite_relational_store.cpp", "${distributeddb_path}/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp", "${distributeddb_path}/storage/src/sqlite/relational/sqlite_relational_utils.cpp", + "${distributeddb_path}/storage/src/sqlite/relational/sqlite_relational_utils_client.cpp", "${distributeddb_path}/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp", "${distributeddb_path}/storage/src/sqlite/relational/sqlite_single_ver_relational_continue_token.cpp", "${distributeddb_path}/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp", @@ -201,6 +205,7 @@ distributeddb_src = [ "${distributeddb_path}/storage/src/sqlite/sqlite_storage_engine.cpp", "${distributeddb_path}/storage/src/sqlite/sqlite_storage_executor.cpp", "${distributeddb_path}/storage/src/sqlite/sqlite_utils.cpp", + "${distributeddb_path}/storage/src/sqlite/sqlite_utils_client.cpp", "${distributeddb_path}/storage/src/sqlite/sqlite_utils_extend.cpp", "${distributeddb_path}/storage/src/storage_engine.cpp", "${distributeddb_path}/storage/src/storage_engine_manager.cpp", @@ -252,6 +257,7 @@ distributeddb_src = [ "${distributeddb_path}/syncer/src/sync_config.cpp", "${distributeddb_path}/syncer/src/sync_operation.cpp", "${distributeddb_path}/syncer/src/time_helper.cpp", + "${distributeddb_path}/syncer/src/time_helper_client.cpp", ] distributeddb_cloud_src = [ @@ -263,6 +269,7 @@ distributeddb_cloud_src = [ "${distributeddb_path}/syncer/src/cloud/cloud_locker.cpp", "${distributeddb_path}/syncer/src/cloud/cloud_syncer.cpp", "${distributeddb_path}/syncer/src/cloud/cloud_syncer_extend.cpp", + "${distributeddb_path}/syncer/src/cloud/cloud_syncer_extend_extend.cpp", "${distributeddb_path}/syncer/src/cloud/cloud_sync_state_machine.cpp", "${distributeddb_path}/syncer/src/cloud/cloud_sync_tag_assets.cpp", "${distributeddb_path}/syncer/src/cloud/cloud_sync_utils.cpp", @@ -300,3 +307,32 @@ distributeddb_src_rd = [ "${distributeddb_path}/gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.cpp", "${distributeddb_path}/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp", ] + +distributeddb_base_src = [ + "${distributeddb_path}/common/src/concurrent_adapter.cpp", + "${distributeddb_path}/common/src/db_common_client.cpp", + "${distributeddb_path}/common/src/json_object.cpp", + "${distributeddb_path}/common/src/log_print.cpp", + "${distributeddb_path}/common/src/param_check_utils_client.cpp", + "${distributeddb_path}/common/src/platform_specific.cpp", + "${distributeddb_path}/common/src/relational/relational_schema_object.cpp", + "${distributeddb_path}/common/src/relational/table_info.cpp", + "${distributeddb_path}/common/src/relational/tracker_table.cpp", + "${distributeddb_path}/common/src/schema_constant.cpp", + "${distributeddb_path}/common/src/schema_utils_client.cpp", + "${distributeddb_path}/interfaces/src/relational/relational_store_manager_client.cpp", + "${distributeddb_path}/interfaces/src/kv_store_errno.cpp", + "${distributeddb_path}/storage/src/cloud/cloud_storage_utils_client.cpp", + "${distributeddb_path}/storage/src/sqlite/relational/cloud_sync_log_table_manager.cpp", + "${distributeddb_path}/storage/src/sqlite/relational/simple_tracker_log_table_manager.cpp", + "${distributeddb_path}/storage/src/sqlite/relational/split_device_log_table_manager.cpp", + "${distributeddb_path}/storage/src/sqlite/relational/sqlite_relational_utils_client.cpp", + "${distributeddb_path}/storage/src/sqlite/sqlite_log_table_manager.cpp", + "${distributeddb_path}/storage/src/sqlite/sqlite_utils_client.cpp", + "${distributeddb_path}/syncer/src/time_helper_client.cpp", +] + +distributeddb_client_src = [ + "${distributeddb_path}/interfaces/src/relational/knowledge_source_utils.cpp", + "${distributeddb_path}/interfaces/src/relational/relational_store_sqlite_ext.cpp", +] \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/grd_api_manager.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/grd_api_manager.h index 7acb79c248fffae3705fcb84d8d4d1330be1e402..2ef9eb06b116b405d8fe11ebcc93d5dbe4951a19 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/grd_api_manager.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/grd_api_manager.h @@ -56,7 +56,7 @@ typedef int32_t (*KVBatchPushback)(const void *key, uint32_t keyLen, const void GRD_KVBatchT *batch); typedef int32_t (*KVBatchPut)(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch); typedef int32_t (*KVBatchDel)(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch); -typedef int32_t (*KVBatchDestory)(GRD_KVBatchT *batch); +typedef int32_t (*KVBatchDestroy)(GRD_KVBatchT *batch); struct GRD_APIInfo { DBOpen DBOpenApi = nullptr; DBClose DBCloseApi = nullptr; @@ -89,9 +89,11 @@ struct GRD_APIInfo { KVBatchPushback KVBatchPushbackApi = nullptr; KVBatchDel KVBatchPutApi = nullptr; KVBatchDel KVBatchDelApi = nullptr; - KVBatchDestory KVBatchDestoryApi = nullptr; + KVBatchDestroy KVBatchDestroyApi = nullptr; }; -GRD_APIInfo GetApiInfoInstance(); +GRD_APIInfo *GetApiInfo(); +void GetApiInfoInstance(void); void InitApiInfo(const char *configStr); +void UnloadApiInfo(GRD_APIInfo *GRD_DBApiInfo); } // namespace DocumentDB #endif // __cplusplus diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/grd_api_manager.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/grd_api_manager.cpp index 4352bf1072de49cb2fa29fafb60dea71e66f5119..884613d25038f0c2349152f0100c2739a40ddaa0 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/grd_api_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/grd_api_manager.cpp @@ -33,6 +33,8 @@ #ifndef _WIN32 static void *g_library = nullptr; +static int g_openCount = 0; +static std::mutex g_apiInfoMutex; #endif static bool g_isGmdbLib = false; @@ -69,7 +71,7 @@ void GRD_DBApiInitCommon(GRD_APIInfo &GRD_DBApiInfo) GRD_DBApiInfo.KVBatchPushbackApi = GRD_KVBatchPushbackInner; GRD_DBApiInfo.KVBatchPutApi = GRD_KVBatchPutInner; GRD_DBApiInfo.KVBatchDelApi = GRD_KVBatchDelInner; - GRD_DBApiInfo.KVBatchDestoryApi = GRD_KVBatchDestroyInner; + GRD_DBApiInfo.KVBatchDestroyApi = GRD_KVBatchDestroyInner; } void GRD_DBApiInitEnhance(GRD_APIInfo &GRD_DBApiInfo) @@ -106,7 +108,7 @@ void GRD_DBApiInitEnhance(GRD_APIInfo &GRD_DBApiInfo) GRD_DBApiInfo.KVBatchPushbackApi = (KVBatchPushback)dlsym(g_library, "GRD_KVBatchPushback"); GRD_DBApiInfo.KVBatchPutApi = (KVBatchPut)dlsym(g_library, "GRD_KVBatchPut"); GRD_DBApiInfo.KVBatchDelApi = (KVBatchDel)dlsym(g_library, "GRD_KVBatchDel"); - GRD_DBApiInfo.KVBatchDestoryApi = (KVBatchDestory)dlsym(g_library, "GRD_KVBatchDestroy"); + GRD_DBApiInfo.KVBatchDestroyApi = (KVBatchDestroy)dlsym(g_library, "GRD_KVBatchDestroy"); #endif } @@ -115,18 +117,44 @@ void InitApiInfo(const char *configStr) g_isGmdbLib = (configStr != nullptr); } -GRD_APIInfo GetApiInfoInstance() +static GRD_APIInfo GRD_ApiInfo; + +GRD_APIInfo *GetApiInfo(void) +{ + return &GRD_ApiInfo; +} + +void GetApiInfoInstance(void) { - GRD_APIInfo GRD_TempApiStruct; #ifndef _WIN32 + std::lock_guard lock(g_apiInfoMutex); + g_openCount++; + if (g_library != nullptr) { + return; + } std::string libPath = g_isGmdbLib ? "libarkdata_db_core.z.so" : "libgaussdb_rd.z.so"; g_library = dlopen(libPath.c_str(), RTLD_LAZY); if (!g_library) { - GRD_DBApiInitCommon(GRD_TempApiStruct); // When calling specific function, read whether init is successful. + GRD_DBApiInitCommon(GRD_ApiInfo); // When calling specific function, read whether init is successful. } else { - GRD_DBApiInitEnhance(GRD_TempApiStruct); + GRD_DBApiInitEnhance(GRD_ApiInfo); + } +#endif +} + +void UnloadApiInfo(GRD_APIInfo *GRD_DBApiInfo) +{ +#ifndef _WIN32 + std::lock_guard lock(g_apiInfoMutex); + g_openCount--; + if (g_library == nullptr) { + return; + } + if (g_openCount == 0) { + dlclose(g_library); + *GRD_DBApiInfo = {0}; + g_library = nullptr; } #endif - return GRD_TempApiStruct; } } // namespace DocumentDB diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api.cpp index 07e5a1e8622b7064f81d40731e1f642eeffab7d3..e54b4e584920a77cd25d3566eafb696870c4e494 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api.cpp @@ -23,80 +23,82 @@ #include "rd_log_print.h" using namespace DocumentDB; -static GRD_APIInfo GRD_DBApiInfo; +static GRD_APIInfo *GRD_DBApiInfo = GetApiInfo(); GRD_API int32_t GRD_DBOpen(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB **db) { - if (GRD_DBApiInfo.DBOpenApi == nullptr) { - InitApiInfo(configStr); - GRD_DBApiInfo = GetApiInfoInstance(); - } - if (GRD_DBApiInfo.DBOpenApi == nullptr) { + InitApiInfo(configStr); + GetApiInfoInstance(); + if (GRD_DBApiInfo->DBOpenApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DBApiInfo.DBOpenApi(dbPath, configStr, flags, db); + int32_t ret = GRD_DBApiInfo->DBOpenApi(dbPath, configStr, flags, db); + if (ret != GRD_OK) { + GLOGE("Fail to open db"); + UnloadApiInfo(GRD_DBApiInfo); + return ret; + } + return ret; } GRD_API int32_t GRD_DBClose(GRD_DB *db, uint32_t flags) { - if (GRD_DBApiInfo.DBCloseApi == nullptr) { - GRD_DBApiInfo = GetApiInfoInstance(); - } - if (GRD_DBApiInfo.DBCloseApi == nullptr) { + if (GRD_DBApiInfo->DBCloseApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DBApiInfo.DBCloseApi(db, flags); + int32_t ret = GRD_DBApiInfo->DBCloseApi(db, flags); + if (ret != GRD_OK) { + GLOGE("Fail to close db"); + } + UnloadApiInfo(GRD_DBApiInfo); + return ret; } GRD_API int32_t GRD_DBBackup(GRD_DB *db, const char *backupDbFile, uint8_t *encryptedKey, uint32_t encryptedKeyLen) { - if (GRD_DBApiInfo.DBBackupApi == nullptr) { - GRD_DBApiInfo = GetApiInfoInstance(); - } - if (GRD_DBApiInfo.DBBackupApi == nullptr) { + if (GRD_DBApiInfo->DBBackupApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } GRD_CipherInfoT cipherInfo = {.hexPassword = nullptr}; - return GRD_DBApiInfo.DBBackupApi(db, backupDbFile, &cipherInfo); + return GRD_DBApiInfo->DBBackupApi(db, backupDbFile, &cipherInfo); } GRD_API int32_t GRD_DBRestore(const char *dbFile, const char *backupDbFile, uint8_t *decryptedKey, uint32_t decryptedKeyLen) { - if (GRD_DBApiInfo.DBRestoreApi == nullptr) { - GRD_DBApiInfo = GetApiInfoInstance(); - } - if (GRD_DBApiInfo.DBRestoreApi == nullptr) { + // db restore operation will start after dbclose, should reload so to link api func + GetApiInfoInstance(); + if (GRD_DBApiInfo->DBRestoreApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); + UnloadApiInfo(GRD_DBApiInfo); return GRD_INNER_ERR; } GRD_CipherInfoT cipherInfo = {.hexPassword = nullptr}; - return GRD_DBApiInfo.DBRestoreApi(dbFile, backupDbFile, &cipherInfo); + int32_t ret = GRD_DBApiInfo->DBRestoreApi(dbFile, backupDbFile, &cipherInfo); + if (ret != GRD_OK) { + GLOGE("Fail to restore db"); + } + UnloadApiInfo(GRD_DBApiInfo); + return ret; } GRD_API int32_t GRD_Flush(GRD_DB *db, uint32_t flags) { - if (GRD_DBApiInfo.FlushApi == nullptr) { - GRD_DBApiInfo = GetApiInfoInstance(); - } - if (GRD_DBApiInfo.FlushApi == nullptr) { + if (GRD_DBApiInfo->FlushApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DBApiInfo.FlushApi(db, flags); + return GRD_DBApiInfo->FlushApi(db, flags); } GRD_API int32_t GRD_IndexPreload(GRD_DB *db, const char *collectionName) { - if (GRD_DBApiInfo.IndexPreloadApi == nullptr) { - GRD_DBApiInfo = GetApiInfoInstance(); - } - if (GRD_DBApiInfo.IndexPreloadApi == nullptr) { + if (GRD_DBApiInfo->IndexPreloadApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DBApiInfo.IndexPreloadApi(db, collectionName); + return GRD_DBApiInfo->IndexPreloadApi(db, collectionName); } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_document_api.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_document_api.cpp index accc95d7bde8ca2b86630869bd618e8628fbcb77..56451d8bed2f5225a76c7f4f85d3a3bcd8a639d6 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_document_api.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_document_api.cpp @@ -23,91 +23,70 @@ #include "rd_log_print.h" using namespace DocumentDB; -static GRD_APIInfo GRD_DocApiInfo; +static GRD_APIInfo *GRD_DocApiInfo = GetApiInfo(); GRD_API int32_t GRD_CreateCollection(GRD_DB *db, const char *collectionName, const char *optionStr, uint32_t flags) { - if (GRD_DocApiInfo.CreateCollectionApi == nullptr) { - GRD_DocApiInfo = GetApiInfoInstance(); - } - if (GRD_DocApiInfo.CreateCollectionApi == nullptr) { + if (GRD_DocApiInfo->CreateCollectionApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DocApiInfo.CreateCollectionApi(db, collectionName, optionStr, flags); + return GRD_DocApiInfo->CreateCollectionApi(db, collectionName, optionStr, flags); } GRD_API int32_t GRD_DropCollection(GRD_DB *db, const char *collectionName, uint32_t flags) { - if (GRD_DocApiInfo.DropCollectionApi == nullptr) { - GRD_DocApiInfo = GetApiInfoInstance(); - } - if (GRD_DocApiInfo.DropCollectionApi == nullptr) { + if (GRD_DocApiInfo->DropCollectionApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DocApiInfo.DropCollectionApi(db, collectionName, flags); + return GRD_DocApiInfo->DropCollectionApi(db, collectionName, flags); } GRD_API int32_t GRD_UpdateDoc(GRD_DB *db, const char *collectionName, const char *filter, const char *update, uint32_t flags) { - if (GRD_DocApiInfo.UpdateDocApi == nullptr) { - GRD_DocApiInfo = GetApiInfoInstance(); - } - if (GRD_DocApiInfo.UpdateDocApi == nullptr) { + if (GRD_DocApiInfo->UpdateDocApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DocApiInfo.UpdateDocApi(db, collectionName, filter, update, flags); + return GRD_DocApiInfo->UpdateDocApi(db, collectionName, filter, update, flags); } GRD_API int32_t GRD_UpsertDoc(GRD_DB *db, const char *collectionName, const char *filter, const char *document, uint32_t flags) { - if (GRD_DocApiInfo.UpsertDocApi == nullptr) { - GRD_DocApiInfo = GetApiInfoInstance(); - } - if (GRD_DocApiInfo.UpsertDocApi == nullptr) { + if (GRD_DocApiInfo->UpsertDocApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DocApiInfo.UpsertDocApi(db, collectionName, filter, document, flags); + return GRD_DocApiInfo->UpsertDocApi(db, collectionName, filter, document, flags); } GRD_API int32_t GRD_InsertDoc(GRD_DB *db, const char *collectionName, const char *document, uint32_t flags) { - if (GRD_DocApiInfo.InsertDocApi == nullptr) { - GRD_DocApiInfo = GetApiInfoInstance(); - } - if (GRD_DocApiInfo.InsertDocApi == nullptr) { + if (GRD_DocApiInfo->InsertDocApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DocApiInfo.InsertDocApi(db, collectionName, document, flags); + return GRD_DocApiInfo->InsertDocApi(db, collectionName, document, flags); } GRD_API int32_t GRD_DeleteDoc(GRD_DB *db, const char *collectionName, const char *filter, uint32_t flags) { - if (GRD_DocApiInfo.DeleteDocApi == nullptr) { - GRD_DocApiInfo = GetApiInfoInstance(); - } - if (GRD_DocApiInfo.DeleteDocApi == nullptr) { + if (GRD_DocApiInfo->DeleteDocApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DocApiInfo.DeleteDocApi(db, collectionName, filter, flags); + return GRD_DocApiInfo->DeleteDocApi(db, collectionName, filter, flags); } GRD_API int32_t GRD_FindDoc(GRD_DB *db, const char *collectionName, Query query, uint32_t flags, GRD_ResultSet **resultSet) { - if (GRD_DocApiInfo.FindDocApi == nullptr) { - GRD_DocApiInfo = GetApiInfoInstance(); - } - if (GRD_DocApiInfo.FindDocApi == nullptr) { + if (GRD_DocApiInfo->FindDocApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DocApiInfo.FindDocApi(db, collectionName, query, flags, resultSet); + return GRD_DocApiInfo->FindDocApi(db, collectionName, query, flags, resultSet); } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_resultset_api.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_resultset_api.cpp index 5e905677522a6c60a6d16c7c195ccde5d6b15ea2..39e312726198e5c041db5e5b60035b05f637d10c 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_resultset_api.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_resultset_api.cpp @@ -21,76 +21,58 @@ #include "rd_log_print.h" using namespace DocumentDB; -static GRD_APIInfo GRD_ResultSetApiInfo; +static GRD_APIInfo *GRD_ResultSetApiInfo = GetApiInfo(); GRD_API int32_t GRD_Next(GRD_ResultSet *resultSet) { - if (GRD_ResultSetApiInfo.NextApi == nullptr) { - GRD_ResultSetApiInfo = GetApiInfoInstance(); - } - if (GRD_ResultSetApiInfo.NextApi == nullptr) { + if (GRD_ResultSetApiInfo->NextApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_ResultSetApiInfo.NextApi(resultSet); + return GRD_ResultSetApiInfo->NextApi(resultSet); } GRD_API int32_t GRD_GetValue(GRD_ResultSet *resultSet, char **value) { - if (GRD_ResultSetApiInfo.GetValueApi == nullptr) { - GRD_ResultSetApiInfo = GetApiInfoInstance(); - } - if (GRD_ResultSetApiInfo.GetValueApi == nullptr) { + if (GRD_ResultSetApiInfo->GetValueApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_ResultSetApiInfo.GetValueApi(resultSet, value); + return GRD_ResultSetApiInfo->GetValueApi(resultSet, value); } GRD_API int32_t GRD_FreeValue(char *value) { - if (GRD_ResultSetApiInfo.FreeValueApi == nullptr) { - GRD_ResultSetApiInfo = GetApiInfoInstance(); - } - if (GRD_ResultSetApiInfo.FreeValueApi == nullptr) { + if (GRD_ResultSetApiInfo->FreeValueApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_ResultSetApiInfo.FreeValueApi(value); + return GRD_ResultSetApiInfo->FreeValueApi(value); } GRD_API int32_t GRD_FreeResultSet(GRD_ResultSet *resultSet) { - if (GRD_ResultSetApiInfo.FreeResultSetApi == nullptr) { - GRD_ResultSetApiInfo = GetApiInfoInstance(); - } - if (GRD_ResultSetApiInfo.FreeResultSetApi == nullptr) { + if (GRD_ResultSetApiInfo->FreeResultSetApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_ResultSetApiInfo.FreeResultSetApi(resultSet); + return GRD_ResultSetApiInfo->FreeResultSetApi(resultSet); } GRD_API int32_t GRD_Prev(GRD_ResultSet *resultSet) { - if (GRD_ResultSetApiInfo.PrevApi == nullptr) { - GRD_ResultSetApiInfo = GetApiInfoInstance(); - } - if (GRD_ResultSetApiInfo.PrevApi == nullptr) { + if (GRD_ResultSetApiInfo->PrevApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_ResultSetApiInfo.PrevApi(resultSet); + return GRD_ResultSetApiInfo->PrevApi(resultSet); } GRD_API int32_t GRD_Fetch(GRD_ResultSet *resultSet, GRD_KVItemT *key, GRD_KVItemT *value) { - if (GRD_ResultSetApiInfo.FetchApi == nullptr) { - GRD_ResultSetApiInfo = GetApiInfoInstance(); - } - if (GRD_ResultSetApiInfo.FetchApi == nullptr) { + if (GRD_ResultSetApiInfo->FetchApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_ResultSetApiInfo.FetchApi(resultSet, key, value); + return GRD_ResultSetApiInfo->FetchApi(resultSet, key, value); } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/kv/grd_kv_api.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/kv/grd_kv_api.cpp index 7f441a65f69062b418eff6bf2e75a059bc2d84f7..0693a05fcc4c79cee2763bc81e11914400919a48 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/kv/grd_kv_api.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/kv/grd_kv_api.cpp @@ -21,150 +21,111 @@ #include "rd_log_print.h" using namespace DocumentDB; -static GRD_APIInfo GRD_KVApiInfo; +static GRD_APIInfo *GRD_KVApiInfo = GetApiInfo(); GRD_API int32_t GRD_KVPut(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, const GRD_KVItemT *value) { - if (GRD_KVApiInfo.KVPutApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVPutApi == nullptr) { + if (GRD_KVApiInfo->KVPutApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVPutApi(db, collectionName, key, value); + return GRD_KVApiInfo->KVPutApi(db, collectionName, key, value); } GRD_API int32_t GRD_KVGet(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, const GRD_KVItemT *value) { - if (GRD_KVApiInfo.KVGetApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVGetApi == nullptr) { + if (GRD_KVApiInfo->KVGetApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVGetApi(db, collectionName, key, value); + return GRD_KVApiInfo->KVGetApi(db, collectionName, key, value); } GRD_API int32_t GRD_KVDel(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key) { - if (GRD_KVApiInfo.KVDelApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVDelApi == nullptr) { + if (GRD_KVApiInfo->KVDelApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVDelApi(db, collectionName, key); + return GRD_KVApiInfo->KVDelApi(db, collectionName, key); } GRD_API int32_t GRD_KVScan(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, GRD_KvScanModeE mode, GRD_ResultSet **resultSet) { - if (GRD_KVApiInfo.KVScanApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVScanApi == nullptr) { + if (GRD_KVApiInfo->KVScanApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVScanApi(db, collectionName, key, mode, resultSet); + return GRD_KVApiInfo->KVScanApi(db, collectionName, key, mode, resultSet); } GRD_API int32_t GRD_KVFilter(GRD_DB *db, const char *collectionName, const GRD_FilterOptionT *scanParams, GRD_ResultSet **resultSet) { - if (GRD_KVApiInfo.KVFilterApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVFilterApi == nullptr) { + if (GRD_KVApiInfo->KVFilterApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVFilterApi(db, collectionName, scanParams, resultSet); + return GRD_KVApiInfo->KVFilterApi(db, collectionName, scanParams, resultSet); } GRD_API int32_t GRD_KVGetSize(GRD_ResultSet *resultSet, uint32_t *keyLen, uint32_t *valueLen) { - if (GRD_KVApiInfo.KVGetSizeApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVGetSizeApi == nullptr) { + if (GRD_KVApiInfo->KVGetSizeApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVGetSizeApi(resultSet, keyLen, valueLen); + return GRD_KVApiInfo->KVGetSizeApi(resultSet, keyLen, valueLen); } GRD_API int32_t GRD_GetItem(GRD_ResultSet *resultSet, void *key, void *value) { - if (GRD_KVApiInfo.GetItemApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.GetItemApi == nullptr) { + if (GRD_KVApiInfo->GetItemApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.GetItemApi(resultSet, key, value); + return GRD_KVApiInfo->GetItemApi(resultSet, key, value); } GRD_API int32_t GRD_KVFreeItem(GRD_KVItemT *item) { - if (GRD_KVApiInfo.KVFreeItemApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVFreeItemApi == nullptr) { + if (GRD_KVApiInfo->KVFreeItemApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVFreeItemApi(item); + return GRD_KVApiInfo->KVFreeItemApi(item); } GRD_API int32_t GRD_KVBatchPrepare(uint16_t itemNum, GRD_KVBatchT **batch) { - if (GRD_KVApiInfo.KVBatchPrepareApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVBatchPrepareApi == nullptr) { + if (GRD_KVApiInfo->KVBatchPrepareApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVBatchPrepareApi(itemNum, batch); + return GRD_KVApiInfo->KVBatchPrepareApi(itemNum, batch); } GRD_API int32_t GRD_KVBatchPushback(const void *key, uint32_t keyLen, const void *data, uint32_t dataLen, GRD_KVBatchT *batch) { - if (GRD_KVApiInfo.KVBatchPushbackApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVBatchPushbackApi == nullptr) { + if (GRD_KVApiInfo->KVBatchPushbackApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVBatchPushbackApi(key, keyLen, data, dataLen, batch); + return GRD_KVApiInfo->KVBatchPushbackApi(key, keyLen, data, dataLen, batch); } GRD_API int32_t GRD_KVBatchPut(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch) { - if (GRD_KVApiInfo.KVBatchPutApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVBatchPutApi == nullptr) { + if (GRD_KVApiInfo->KVBatchPutApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVBatchPutApi(db, collectionName, batch); + return GRD_KVApiInfo->KVBatchPutApi(db, collectionName, batch); } GRD_API int32_t GRD_KVBatchDel(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch) { - if (GRD_KVApiInfo.KVBatchDelApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVBatchDelApi == nullptr) { + if (GRD_KVApiInfo->KVBatchDelApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVBatchDelApi(db, collectionName, batch); + return GRD_KVApiInfo->KVBatchDelApi(db, collectionName, batch); } GRD_API int32_t GRD_KVBatchDestroy(GRD_KVBatchT *batch) { - if (GRD_KVApiInfo.KVBatchDestoryApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVBatchDestoryApi == nullptr) { + if (GRD_KVApiInfo->KVBatchDestroyApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVBatchDestoryApi(batch); + return GRD_KVApiInfo->KVBatchDestroyApi(batch); } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_key.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_key.cpp index 1666428a46607b50147e07d55dee7b4c4b2a5272..eb2d2a201d6be5b18cced1fcceec7073d2d7837e 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_key.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_key.cpp @@ -16,6 +16,7 @@ #include #include +#include #include "doc_errno.h" #include "rd_log_print.h" @@ -31,11 +32,18 @@ static int InitDocIdFromOid(DocKey &docKey) if (nowTime < 0) { return -E_INNER_ERROR; } - uint32_t now = (uint32_t)nowTime; - uint16_t iv = g_oIdIncNum++; + uint64_t nowTemp = static_cast(nowTime); + if (nowTemp > UINT32_MAX) { + GLOGE("Time overflows 32-bit range. nowTemp = %" PRIu64, nowTemp); + return -E_INNER_ERROR; + } + uint32_t now = static_cast(nowTemp); + uint16_t iv = g_oIdIncNum; // The maximum number of autoincrements is 65535, and if it is exceeded, it becomes 0. - if (g_oIdIncNum > MAX_NUMBER_OF_AUTOINCREMENTS) { + if (g_oIdIncNum == MAX_NUMBER_OF_AUTOINCREMENTS) { g_oIdIncNum = UINT_ZERO; + } else { + g_oIdIncNum++; } char *idTemp = new char[GRD_DOC_OID_HEX_SIZE + 1]; if (sprintf_s(idTemp, GRD_DOC_OID_HEX_SIZE + 1, "%08x%04x", now, iv) < 0) { diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp index 27bef4c14adc5eb38126bf52a30b6d4323eb7f90..c40cc76b77ac951a10728fa7e7ac96a790e2ca94 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp @@ -232,7 +232,7 @@ int RDSQLiteUtils::ExecSql(sqlite3 *db, const std::string &sql) char *errMsg = nullptr; int errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &errMsg); if (errCode != SQLITE_OK && errMsg != nullptr) { - GLOGE("Execute sql failed. %d err: %s", errCode, errMsg); + GLOGE("Execute sql failed. %d", errCode); } sqlite3_free(errMsg); diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/BUILD.gn b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/BUILD.gn index 8979be7d43451f57e7b04344850c872ab2ed2504..98590b2788f3e41cf509176b21ba65181e8ae3e9 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/BUILD.gn @@ -12,7 +12,7 @@ # limitations under the License. import("//build/test.gni") -module_output_path = "kv_store/kv_store/gaussdb_rd" +module_output_path = "kv_store/gaussdb_rd" ############################################################################### config("module_private_config") { @@ -77,19 +77,15 @@ ohos_source_set("src_file") { configs = [ ":module_private_config" ] - deps = [ - "//third_party/googletest:gtest_main", - "//third_party/sqlite:sqlite", - ] - - configs += [ "//third_party/cJSON:cJSON_config" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps += [ "//third_party/cJSON:cjson" ] external_deps = [ + "cJSON:cjson", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "sqlite:sqlite", ] subsystem_name = "distributeddatamgr" @@ -117,23 +113,18 @@ template("gaussdb_rd_unittest") { debug = false } - deps += [ - ":src_file", - "//third_party/googletest:gmock_main", - "//third_party/googletest:gtest_main", - "//third_party/sqlite:sqlite", - ] - configs += [ "//third_party/cJSON:cJSON_config" ] + deps += [ ":src_file" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps += [ - "//third_party/cJSON:cjson", - "//third_party/openssl:libcrypto_shared", - ] external_deps = [ + "cJSON:cjson", "c_utils:utils", + "googletest:gmock_main", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] } } @@ -173,9 +164,8 @@ gaussdb_rd_unittest("DocumentDBDeleteTest") { ############################################################################### group("unittest") { testonly = true - deps = [ "//third_party/googletest:gmock" ] - deps += [ + deps = [ ":DocumentDBApiTest", ":DocumentDBCollectionTest", ":DocumentDBDataTest", diff --git a/kv_store/frameworks/libs/distributeddb/include/types_export.h b/kv_store/frameworks/libs/distributeddb/include/types_export.h index 73abe2cd7d05fa58ba1a4d8ec688afadf26c0620..e8e1eb651c5a4fcabd6c2e844ca9e6f889b5989f 100644 --- a/kv_store/frameworks/libs/distributeddb/include/types_export.h +++ b/kv_store/frameworks/libs/distributeddb/include/types_export.h @@ -244,6 +244,11 @@ struct StoreInfo { std::string userId; std::string appId; std::string storeId; + + bool operator<(const StoreInfo &other) const + { + return std::tie(userId, appId, storeId) < std::tie(other.userId, other.appId, other.storeId); + } }; using TranslateToDeviceIdCallback = std::function; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h index 06f39763fbc616732ec2def11d0270b7122997e0..50137d38a9f3bf24100a482b53ca586d9c82257d 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h @@ -49,6 +49,14 @@ struct ClearMetaDataOption { std::set tableNameList; // an empty set means clearing meta data on all tables }; +enum class ClearKvMetaOpType : uint64_t { + CLEAN_CLOUD_WATERMARK = 0x01, // clear watermark of device to cloud sync +}; + +struct ClearKvMetaDataOption { + ClearKvMetaOpType type = ClearKvMetaOpType::CLEAN_CLOUD_WATERMARK; +}; + enum class AssetOpType { NO_CHANGE = 0, INSERT, @@ -210,6 +218,7 @@ struct CloudSyncConfig { int32_t maxUploadCount = 30; // default max upload 30 records int32_t maxUploadSize = 1024 * 512 * 3; // default max upload 1024 * 512 * 3 = 1.5m int32_t maxRetryConflictTimes = -1; // default max retry -1 is unlimited retry times + bool isSupportEncrypt = false; // default encryption is not supported }; struct AsyncDownloadAssetsConfig { diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/iprocess_communicator.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/iprocess_communicator.h index 0fdb757aafb7e38d17bca2a2327b208bda34e669..e72fd36dba5c8aefb9bf8307434c701c0b94a3c7 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/iprocess_communicator.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/iprocess_communicator.h @@ -24,9 +24,18 @@ #include "store_types.h" namespace DistributedDB { +struct AccessInfos { + std::string appId; + std::string storeId; + std::string userId; + std::string subUserId; +}; + // The DeviceInfos may contain other fields(Can only be auxiliary information) besides identifier field in the future. struct DeviceInfos { std::string identifier; // An unique and fixed identifier representing a device, such as UUID. + AccessInfos callee; // A message frame's access info. + bool isRetryTask = true; }; struct ExtendInfo { @@ -37,8 +46,22 @@ struct ExtendInfo { std::string subUserId; }; +struct DataHeadInfo { + const uint8_t *data = nullptr; + uint32_t totalLen; + std::string device; +}; + +struct DataUserInfo { + const uint8_t *data = nullptr; + uint32_t totalLen; + const std::string label; + const std::string device; +}; + struct UserInfo { std::string receiveUser; + std::string sendUser; }; class ExtendHeaderHandle { @@ -60,6 +83,11 @@ public: { return OK; }; + + virtual std::string GetTargetUserId() + { + return ""; + } }; // In OnDeviceChange, all field of devInfo should be valid, isOnline true for online and false for offline. @@ -169,14 +197,13 @@ public: headLength = 0; return OK; } - virtual DBStatus GetDataHeadInfo(const uint8_t *data, uint32_t totalLen, uint32_t &headLength) + virtual DBStatus GetDataHeadInfo(DataHeadInfo dataHeadInfo, uint32_t &headLength) { headLength = 0; return OK; } // return NO_PERMISSION while no need to handle the dataBuff if remote device userId is not mate with local userId - virtual DBStatus GetDataUserInfo(const uint8_t *data, uint32_t totalLen, const std::string &label, - std::vector &userInfos) + virtual DBStatus GetDataUserInfo(DataUserInfo dataUserInfo, std::vector &userInfos) { return OK; } diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_delegate_manager.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_delegate_manager.h index d09f6c65eda577f92154717f6e2c27385c54db62..864d858bf04a5f379c0710e6e8d1f094ced760c6 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_delegate_manager.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_delegate_manager.h @@ -59,7 +59,7 @@ public: // Close a KvStore, return OK if close success. DB_API DBStatus CloseKvStore(KvStoreDelegate *kvStore); - DB_API DBStatus CloseKvStore(KvStoreNbDelegate *kvStore); + DB_API DBStatus CloseKvStore(KvStoreNbDelegate *kvStore, bool isCloseImmediately = true); // Used to delete a KvStore, return OK if delete success. DB_API DBStatus DeleteKvStore(const std::string &storeId); @@ -124,6 +124,8 @@ private: bool GetKvStoreParamCheck(const std::string &storeId, const KvStoreNbDelegate::Option &option, const std::function &callback) const; DBStatus SetObserverNotifier(KvStoreNbDelegate *kvStore, const KvStoreNbDelegate::Option &option); + void GetKvStoreInner(const std::string &storeId, const KvStoreNbDelegate::Option &option, + const std::function &callback, void *handle); const std::string &GetKvStorePath() const; static const std::string DEFAULT_PROCESS_APP_ID; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h index e9b3f73a1f0c00cec2e7ca339e45df2ba3ad95fa..8c63e761a10deeafef252b7e01fd03e504fd8cec 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h @@ -204,11 +204,23 @@ public: const std::function &devicesMap)> &onComplete, const Query &query, bool wait) = 0; + DB_API virtual DBStatus Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete) + { + return OK; + }; + // Sync with device, provides sync count information - DB_API virtual DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) = 0; + DB_API virtual DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) + { + return OK; + }; // Cancel sync by syncId - DB_API virtual DBStatus CancelSync(uint32_t syncId) = 0; + DB_API virtual DBStatus CancelSync(uint32_t syncId) + { + return OK; + }; // Check the integrity of this kvStore. DB_API virtual DBStatus CheckIntegrity() const = 0; @@ -306,12 +318,20 @@ public: // If device is empty, it would return all the entries which was written by local device. DB_API virtual DBStatus GetDeviceEntries(const std::string &device, std::vector &entries) const = 0; - DB_API virtual DatabaseStatus GetDatabaseStatus() const = 0; + DB_API virtual DatabaseStatus GetDatabaseStatus() const + { + return {}; + } DB_API virtual DBStatus OperateDataStatus([[gnu::unused]] uint32_t dataOperator) { return OK; } + + DB_API virtual DBStatus ClearMetaData([[gnu::unused]] ClearKvMetaDataOption option) + { + return OK; + } }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_client.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_client.h index c2cd1a65b9527a9f5dc7ccea2733ebbc90a8ea8a..aa94d296a46677372b0ab8d9600a016fcba2f440 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_client.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_client.h @@ -58,4 +58,19 @@ DB_API void RegisterDbHook(sqlite3 *db); DB_API void UnregisterDbHook(sqlite3 *db); DB_API DistributedDB::DBStatus CreateDataChangeTempTrigger(sqlite3 *db); + +namespace DistributedDB { +struct KnowledgeSourceSchema { + std::string tableName; + std::set extendColNames; + std::set knowledgeColNames; +}; +} + +DB_API DistributedDB::DBStatus SetKnowledgeSourceSchema(sqlite3 *db, + const DistributedDB::KnowledgeSourceSchema &schema); + +DB_API DistributedDB::DBStatus CleanDeletedData(sqlite3 *db, const std::string &tableName, uint64_t cursor); + +DB_API void Clean(bool isOpenSslClean); #endif // RELATIONAL_STORE_CLIENT_H diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h index d005d85a365ca1f50b412d6db64c1b0231856c5f..78f69dfa8d41de7dc972184e48c21376edc71146 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h @@ -42,6 +42,8 @@ public: CipherPassword passwd; uint32_t iterateTimes = 0; DistributedTableMode tableMode = DistributedTableMode::SPLIT_BY_DEVICE; + bool isNeedCompressOnSync = false; + uint8_t compressionRate = 100; // Valid in [1, 100] }; struct StoreConfig { @@ -151,7 +153,8 @@ public: return {}; } - DB_API virtual DBStatus SetDistributedSchema([[gnu::unused]] const DistributedSchema &schema) + DB_API virtual DBStatus SetDistributedSchema([[gnu::unused]] const DistributedSchema &schema, + [[gnu::unused]] bool isForceUpgrade = false) { return OK; } @@ -165,6 +168,11 @@ public: { return OK; } + + DB_API virtual int32_t GetDeviceSyncTaskCount() + { + return 0; + } protected: virtual DBStatus RemoveDeviceDataInner(const std::string &device, ClearMode mode) = 0; virtual DBStatus CreateDistributedTableInner(const std::string &tableName, TableSyncType type) = 0; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_sqlite_ext.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_sqlite_ext.h index ab2f5ded923e27bb22a39af7ba1f8a27c72c404f..e788a68f91e12dc16e6a0ca033134a1470f600de 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_sqlite_ext.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_sqlite_ext.h @@ -15,7 +15,7 @@ #ifndef RELATIONAL_STORE_EXT_H #define RELATIONAL_STORE_EXT_H -#define SQLITE3_HW_EXPORT_SYMBOLS +#define SQLITE3_EXTRA_EXPORT_SYMBOLS // using the "sqlite3sym.h" in OHOS #ifndef USE_SQLITE_SYMBOLS @@ -29,6 +29,7 @@ struct sqlite3_api_routines_relational { int (*open)(const char *, sqlite3 **); int (*open16)(const void *, sqlite3 **); int (*open_v2)(const char *, sqlite3 **, int, const char *); + int (*is_support_binlog)(const char*); }; extern const struct sqlite3_api_routines_relational *sqlite3_export_relational_symbols; @@ -36,15 +37,20 @@ extern const struct sqlite3_api_routines_relational *sqlite3_export_relational_s #ifdef sqlite3_open #undef sqlite3_open #endif -#define sqlite3_open sqlite3_export_relational_symbols->open +#define sqlite3_open sqlite3_export_relational_symbols->open #ifdef sqlite3_open16 #undef sqlite3_open16 #endif -#define sqlite3_open16 sqlite3_export_relational_symbols->open16 +#define sqlite3_open16 sqlite3_export_relational_symbols->open16 #ifdef sqlite3_open_v2 #undef sqlite3_open_v2 #endif -#define sqlite3_open_v2 sqlite3_export_relational_symbols->open_v2 +#define sqlite3_open_v2 sqlite3_export_relational_symbols->open_v2 + +#ifdef sqlite3_is_support_binlog +#undef sqlite3_is_support_binlog +#endif +#define sqlite3_is_support_binlog sqlite3_export_relational_symbols->is_support_binlog #endif // RELATIONAL_STORE_EXT_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h index a75a5b428c3e8f87cd47642d2fbc2127d46c6ffd..41ddacd85eeb024021768caaf912d86e84c291ee 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h @@ -94,6 +94,7 @@ enum DBStatus { CLOUD_DISABLED, // the cloud switch has been turned off DISTRIBUTED_FIELD_DECREASE, // sync fewer specified columns than last time SKIP_ASSET, // workaround status for contact app assets download failure, need to ignore these failures + LOW_VERSION_TARGET, // The target device is a low version device BUTT_STATUS = 27394048 // end of status }; @@ -200,6 +201,7 @@ struct DeviceSyncOption { Query query; // isQuery must be set to true if the query is set bool isQuery = false; bool isWait = true; + bool isRetry = true; }; struct DeviceSyncInfo { @@ -258,6 +260,7 @@ static constexpr const char *SQLITE = "sqlite"; struct ChangeProperties { bool isTrackedDataChange = false; bool isP2pSyncDataChange = false; + bool isKnowledgeDataChange = false; }; enum IndexType : uint32_t { @@ -318,5 +321,18 @@ enum class DataOperator : uint32_t { UPDATE_TIME = 0x01, RESET_UPLOAD_CLOUD = 0x02 }; + +struct DeviceSyncTarget { + std::string device; + std::string userId; + DeviceSyncTarget(std::string device, std::string userId) : device(std::move(device)), userId(std::move(userId)) {} + bool operator<(const DeviceSyncTarget& other) const + { + if (device == other.device) { + return userId < other.userId; + } + return device < other.device; + } +}; } // namespace DistributedDB #endif // KV_STORE_TYPE_H diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp index f81b47919d1750184d2b69b95b4922cd98ec8060..82ec35f23ba5bf83eab9a30f76c6cb31deb6be66 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp @@ -106,10 +106,10 @@ void InitPropWithNbOption(KvDBProperties &properties, const std::string &storePa if (option.isEncryptedDb) { properties.SetPassword(option.cipher, option.passwd); } - properties.SetBoolProp(KvDBProperties::COMPRESS_ON_SYNC, option.isNeedCompressOnSync); + properties.SetBoolProp(DBProperties::COMPRESS_ON_SYNC, option.isNeedCompressOnSync); if (option.isNeedCompressOnSync) { properties.SetIntProp( - KvDBProperties::COMPRESSION_RATE, ParamCheckUtils::GetValidCompressionRate(option.compressionRate)); + DBProperties::COMPRESSION_RATE, ParamCheckUtils::GetValidCompressionRate(option.compressionRate)); } properties.SetBoolProp(KvDBProperties::SYNC_DUAL_TUPLE_MODE, option.syncDualTupleMode); properties.SetBoolProp(KvDBProperties::LOCAL_ONLY, option.localOnly); @@ -304,28 +304,19 @@ bool KvStoreDelegateManager::GetKvStoreParamCheck(const std::string &storeId, co return true; } -void KvStoreDelegateManager::GetKvStore(const std::string &storeId, const KvStoreNbDelegate::Option &option, - const std::function &callback) +void KvStoreDelegateManager::GetKvStoreInner(const std::string &storeId, const KvStoreNbDelegate::Option &option, + const std::function &callback, void *handle) { - if (!GetKvStoreParamCheck(storeId, option, callback)) { - return; - } - auto tmpOption = option; - if (tmpOption.storageEngineType == std::string(GAUSSDB_RD)) { - DBCommon::LoadGrdLib(); - if (!DBCommon::IsGrdLibLoaded()) { - tmpOption.storageEngineType = std::string(SQLITE); - } - } // check if schema is supported and valid SchemaObject schema; - DBStatus retCode = CheckAndGetSchema(tmpOption.isMemoryDb, tmpOption.schema, schema); + DBStatus retCode = CheckAndGetSchema(option.isMemoryDb, option.schema, schema); if (retCode != OK) { + DBCommon::UnLoadGrdLib(handle); callback(retCode, nullptr); return; } KvDBProperties properties; - InitPropWithNbOption(properties, GetKvStorePath(), schema, tmpOption); + InitPropWithNbOption(properties, GetKvStorePath(), schema, option); DbIdParam dbIdParam = {appId_, userId_, storeId, subUser_, instanceId_}; DBCommon::SetDatabaseIds(properties, dbIdParam); @@ -333,6 +324,7 @@ void KvStoreDelegateManager::GetKvStore(const std::string &storeId, const KvStor IKvDBConnection *conn = GetOneConnectionWithRetry(properties, errCode); DBStatus status = TransferDBErrno(errCode); if (conn == nullptr) { + DBCommon::UnLoadGrdLib(handle); callback(status, nullptr); return; } @@ -341,13 +333,15 @@ void KvStoreDelegateManager::GetKvStore(const std::string &storeId, const KvStor if (kvStore == nullptr) { conn->Close(); conn = nullptr; + DBCommon::UnLoadGrdLib(handle); callback(DB_ERROR, nullptr); return; } - - status = SetObserverNotifier(kvStore, tmpOption); + kvStore->SetHandle(handle); + status = SetObserverNotifier(kvStore, option); if (status != OK) { CloseKvStore(kvStore); + DBCommon::UnLoadGrdLib(handle); callback(status, nullptr); return; } @@ -355,12 +349,29 @@ void KvStoreDelegateManager::GetKvStore(const std::string &storeId, const KvStor bool enAutoSync = false; (void)conn->Pragma(PRAGMA_AUTO_SYNC, static_cast(&enAutoSync)); - SecurityOption secOption = tmpOption.secOption; + SecurityOption secOption = option.secOption; (void)conn->Pragma(PRAGMA_TRIGGER_TO_MIGRATE_DATA, &secOption); callback(OK, kvStore); } +void KvStoreDelegateManager::GetKvStore(const std::string &storeId, const KvStoreNbDelegate::Option &option, + const std::function &callback) +{ + if (!GetKvStoreParamCheck(storeId, option, callback)) { + return; + } + auto tmpOption = option; + void *handle = nullptr; + if (tmpOption.storageEngineType == std::string(GAUSSDB_RD)) { + handle = DBCommon::LoadGrdLib(); + if (handle == nullptr) { + tmpOption.storageEngineType = std::string(SQLITE); + } + } + return GetKvStoreInner(storeId, tmpOption, callback, handle); +} + DBStatus KvStoreDelegateManager::CloseKvStore(KvStoreDelegate *kvStore) { #ifndef OMIT_MULTI_VER @@ -384,14 +395,14 @@ DBStatus KvStoreDelegateManager::CloseKvStore(KvStoreDelegate *kvStore) #endif } -DBStatus KvStoreDelegateManager::CloseKvStore(KvStoreNbDelegate *kvStore) +DBStatus KvStoreDelegateManager::CloseKvStore(KvStoreNbDelegate *kvStore, bool isCloseImmediately) { if (kvStore == nullptr) { return INVALID_ARGS; } auto kvStoreImpl = static_cast(kvStore); - DBStatus status = kvStoreImpl->Close(); + DBStatus status = kvStoreImpl->Close(isCloseImmediately); if (status == BUSY) { LOGD("NbDelegateImpl is busy now."); return BUSY; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp index 008c33e89eb1ec192c37120284e28fd00f149ff2..b24958fb948b89316767503821fc338384e873ab 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp @@ -78,8 +78,12 @@ KvStoreNbDelegateImpl::~KvStoreNbDelegateImpl() LOGF("[KvStoreNbDelegate] Can't release directly"); return; } - conn_ = nullptr; +#ifndef _WIN32 + std::lock_guard lock(libMutex_); + DBCommon::UnLoadGrdLib(dlHandle_); + dlHandle_ = nullptr; +#endif } DBStatus KvStoreNbDelegateImpl::Get(const Key &key, Value &value) const @@ -425,7 +429,7 @@ DBStatus KvStoreNbDelegateImpl::RegisterDeviceObserver(const Key &key, unsigned mode, key, [observer, storeId](const KvDBCommitNotifyData ¬ifyData) { KvStoreChangedDataImpl data(¬ifyData); - LOGD("[KvStoreNbDelegate][RegisterDeviceObserver] Trigger [%s] on change", storeId.c_str()); + LOGD("[KvStoreNbDelegate][RegisterDeviceObserver] Trigger on change"); observer->OnChange(data); }, errCode); @@ -467,7 +471,7 @@ DBStatus KvStoreNbDelegateImpl::RegisterCloudObserver(const Key &key, unsigned i ObserverAction action = [observer, storeId]( const std::string &device, ChangedData &&changedData, bool isChangedData) { if (isChangedData) { - LOGD("[KvStoreNbDelegate][RegisterCloudObserver] Trigger [%s] on change", storeId.c_str()); + LOGD("[KvStoreNbDelegate][RegisterCloudObserver] Trigger on change"); observer->OnChange(Origin::ORIGIN_CLOUD, device, std::move(changedData)); } }; @@ -505,7 +509,7 @@ DBStatus KvStoreNbDelegateImpl::UnRegisterDeviceObserver(const KvStoreObserver * std::lock_guard lockGuard(observerMapLock_); auto iter = observerMap_.find(observer); if (iter == observerMap_.end()) { - LOGE("[KvStoreNbDelegate] [%s] Observer has not been registered!", storeId_.c_str()); + LOGE("[KvStoreNbDelegate] Observer has not been registered!"); return NOT_FOUND; } @@ -524,7 +528,7 @@ DBStatus KvStoreNbDelegateImpl::UnRegisterCloudObserver(const KvStoreObserver *o std::lock_guard lockGuard(observerMapLock_); auto iter = cloudObserverMap_.find(observer); if (iter == cloudObserverMap_.end()) { - LOGW("[KvStoreNbDelegate] [%s] CloudObserver has not been registered!", storeId_.c_str()); + LOGW("[KvStoreNbDelegate] CloudObserver has not been registered!"); return NOT_FOUND; } int errCode = conn_->UnRegisterObserverAction(observer); @@ -589,39 +593,13 @@ DBStatus KvStoreNbDelegateImpl::Sync(const std::vector &devices, Sy const std::function &devicesMap)> &onComplete, const Query &query, bool wait) { - if (conn_ == nullptr) { - LOGE("%s", INVALID_CONNECTION); - return DB_ERROR; - } - if (mode > SYNC_MODE_PUSH_PULL) { - LOGE("not support other mode"); - return NOT_SUPPORT; - } - - QuerySyncObject querySyncObj(query); - if (!querySyncObj.GetRelationTableNames().empty()) { - LOGE("check query table names from tables failed!"); - return NOT_SUPPORT; - } - - if (!DBCommon::CheckQueryWithoutMultiTable(query)) { - LOGE("not support for invalid query"); - return NOT_SUPPORT; - } - if (querySyncObj.GetSortType() != SortType::NONE || querySyncObj.IsQueryByRange()) { - LOGE("not support order by timestamp and query by range"); - return NOT_SUPPORT; - } - PragmaSync pragmaData( - devices, mode, querySyncObj, [this, onComplete](const std::map &statuses) { - OnSyncComplete(statuses, onComplete); - }, wait); - int errCode = conn_->Pragma(PRAGMA_SYNC_DEVICES, &pragmaData); - if (errCode < E_OK) { - LOGE("[KvStoreNbDelegate] QuerySync data failed:%d", errCode); - return TransferDBErrno(errCode); - } - return OK; + DeviceSyncOption option; + option.devices = devices; + option.mode = mode; + option.isQuery = true; + option.query = query; + option.isWait = wait; + return Sync(option, onComplete); } void KvStoreNbDelegateImpl::OnDeviceSyncProcess(const std::map &processMap, @@ -683,6 +661,51 @@ DBStatus KvStoreNbDelegateImpl::Sync(const DeviceSyncOption &option, const Devic return OK; } +DBStatus KvStoreNbDelegateImpl::Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete) +{ + if (conn_ == nullptr) { + LOGE("%s", INVALID_CONNECTION); + return DB_ERROR; + } + if (option.mode > SYNC_MODE_PUSH_PULL) { + LOGE("not support other mode"); + return NOT_SUPPORT; + } + + int errCode = E_OK; + if (option.isQuery) { + QuerySyncObject querySyncObj(option.query); + if (!querySyncObj.GetRelationTableNames().empty()) { + LOGE("check query table names from tables failed!"); + return NOT_SUPPORT; + } + + if (!DBCommon::CheckQueryWithoutMultiTable(option.query)) { + LOGE("not support for invalid query"); + return NOT_SUPPORT; + } + if (querySyncObj.GetSortType() != SortType::NONE || querySyncObj.IsQueryByRange()) { + LOGE("not support order by timestamp and query by range"); + return NOT_SUPPORT; + } + PragmaSync pragmaData(option, querySyncObj, [this, onComplete](const std::map &statuses) { + OnSyncComplete(statuses, onComplete); + }); + errCode = conn_->Pragma(PRAGMA_SYNC_DEVICES, &pragmaData); + } else { + PragmaSync pragmaData(option, [this, onComplete](const std::map &statuses) { + OnSyncComplete(statuses, onComplete); + }); + errCode = conn_->Pragma(PRAGMA_SYNC_DEVICES, &pragmaData); + } + if (errCode != E_OK) { + LOGE("[KvStoreNbDelegate] QuerySync data failed:%d", errCode); + return TransferDBErrno(errCode); + } + return OK; +} + DBStatus KvStoreNbDelegateImpl::CancelSync(uint32_t syncId) { if (conn_ == nullptr) { @@ -894,10 +917,10 @@ void KvStoreNbDelegateImpl::SetReleaseFlag(bool flag) releaseFlag_ = flag; } -DBStatus KvStoreNbDelegateImpl::Close() +DBStatus KvStoreNbDelegateImpl::Close(bool isCloseImmediately) { if (conn_ != nullptr) { - int errCode = KvDBManager::ReleaseDatabaseConnection(conn_); + int errCode = KvDBManager::ReleaseDatabaseConnection(conn_, isCloseImmediately); if (errCode == -E_BUSY) { LOGI("[KvStoreNbDelegate] Busy for close"); return BUSY; @@ -954,7 +977,7 @@ DBStatus KvStoreNbDelegateImpl::GetInner(const IOption &option, const Key &key, } if (errCode != -E_NOT_FOUND) { - LOGE("[KvStoreNbDelegate] [%s] Get the data failed:%d", storeId_.c_str(), errCode); + LOGE("[KvStoreNbDelegate] Get the data failed:%d", errCode); } return TransferDBErrno(errCode); } @@ -1372,6 +1395,24 @@ std::pair> KvStoreNbDelegateImpl::G res.first = TransferDBErrno(errCode); return res; } + +DBStatus KvStoreNbDelegateImpl::ClearMetaData(ClearKvMetaDataOption option) +{ + if (option.type != ClearKvMetaOpType::CLEAN_CLOUD_WATERMARK) { + return NOT_SUPPORT; + } + if (conn_ == nullptr) { + LOGE("%s", INVALID_CONNECTION); + return DB_ERROR; + } + int errCode = conn_->ClearCloudWatermark(); + if (errCode == E_OK) { + LOGI("[KvStoreNbDelegate][%.3s] clear kv cloud watermark success", storeId_.c_str()); + } else { + LOGE("[KvStoreNbDelegate][%.3s] clear kv cloud watermark failed:%d", storeId_.c_str(), errCode); + } + return TransferDBErrno(errCode); +} #endif DBStatus KvStoreNbDelegateImpl::OperateDataStatus(uint32_t dataOperator) @@ -1388,4 +1429,12 @@ DBStatus KvStoreNbDelegateImpl::OperateDataStatus(uint32_t dataOperator) } return TransferDBErrno(errCode); } + +void KvStoreNbDelegateImpl::SetHandle(void *handle) +{ +#ifndef _WIN32 + std::lock_guard lock(libMutex_); + dlHandle_ = handle; +#endif +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h index 6ec080324a07d340f03efc7a218596916c8d4f01..88323d872134f0d8b431676f35ba65880ca594aa 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h @@ -124,7 +124,7 @@ public: void SetReleaseFlag(bool flag); - DBStatus Close(); + DBStatus Close(bool isCloseImmediately = true); // Sync function interface, if wait set true, this function will be blocked until sync finished. // Param query used to filter the records to be synchronized. @@ -136,6 +136,9 @@ public: // Sync with devices, provides sync count information DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) override; + DBStatus Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete) override; + // Cancel sync by syncId DBStatus CancelSync(uint32_t syncId) override; @@ -192,9 +195,14 @@ public: DBStatus SetCloudSyncConfig(const CloudSyncConfig &config) override; std::pair> GetCloudVersion(const std::string &device) override; + + DBStatus ClearMetaData(ClearKvMetaDataOption option) override; #endif DBStatus OperateDataStatus(uint32_t dataOperator) override; + + void SetHandle(void *handle); + private: DBStatus GetInner(const IOption &option, const Key &key, Value &value) const; DBStatus PutInner(const IOption &option, const Key &key, const Value &value); @@ -222,6 +230,10 @@ private: IKvDBConnection *conn_; std::string storeId_; bool releaseFlag_; +#ifndef _WIN32 + mutable std::mutex libMutex_; + void *dlHandle_ = nullptr; +#endif std::mutex observerMapLock_; std::map observerMap_; std::map cloudObserverMap_; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/knowledge_source_utils.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/knowledge_source_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4a496f447aaef52c1ceba329242db69e3cdd2a96 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/knowledge_source_utils.cpp @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2025 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 "knowledge_source_utils.h" + +#include "db_common.h" +#include "db_errno.h" +#include "simple_tracker_log_table_manager.h" +#include "sqlite_relational_utils.h" +#include "sqlite_utils.h" + +namespace DistributedDB { +namespace { +int GenLogForExistData(sqlite3 *db, const TableInfo &table, std::unique_ptr &manager) +{ + SQLiteRelationalUtils::GenLogParam param = {db, false, true}; + return SQLiteRelationalUtils::GeneLogInfoForExistedData("", table, manager, param); +} + +TrackerTable GetTrackerTable(const KnowledgeSourceSchema &schema) +{ + TrackerTable trackerTable; + trackerTable.SetTableName(schema.tableName); + trackerTable.SetExtendNames(schema.extendColNames); + trackerTable.SetTrackerNames(schema.knowledgeColNames); + trackerTable.SetTriggerObserver(false); + trackerTable.SetKnowledgeTable(true); + return trackerTable; +} + +TrackerSchema GetTrackerSchema(const KnowledgeSourceSchema &schema) +{ + TrackerSchema trackerSchema; + trackerSchema.tableName = schema.tableName; + trackerSchema.extendColNames = schema.extendColNames; + trackerSchema.trackerColNames = schema.knowledgeColNames; + return trackerSchema; +} +} + +int KnowledgeSourceUtils::SetKnowledgeSourceSchema(sqlite3 *db, const KnowledgeSourceSchema &schema) +{ + int errCode = SQLiteUtils::BeginTransaction(db, TransactType::IMMEDIATE); + if (errCode != E_OK) { + LOGE("Begin transaction failed %d when set knowledge schema", errCode); + return errCode; + } + errCode = SetKnowledgeSourceSchemaInner(db, schema); + int ret; + if (errCode != E_OK) { + ret = SQLiteUtils::RollbackTransaction(db); + } else { + ret = SQLiteUtils::CommitTransaction(db); + } + LOGI("Set knowledge source schema res %d, commit or rollback ret %d", errCode, ret); + return errCode == E_OK ? ret : errCode; +} + +int KnowledgeSourceUtils::CleanDeletedData(sqlite3 *db, const std::string &tableName, uint64_t cursor) +{ + bool isExist = false; + auto errCode = SQLiteUtils::CheckTableExists(db, DBCommon::GetLogTableName(tableName), isExist); + if (errCode != E_OK) { + return errCode; + } + if (!isExist) { + LOGI("Clean delete data with no exist log, ori table %s len %zu", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size()); + return E_OK; + } + errCode = SQLiteRelationalUtils::CleanTrackerData(db, tableName, static_cast(cursor), true); + if (errCode != E_OK) { + return errCode; + } + auto count = sqlite3_changes64(db); + LOGI("Clean delete data success, table %s len %zu cursor %" PRIu64 " delete count %" PRId64, + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), cursor, count); + return errCode; +} + +int KnowledgeSourceUtils::SetKnowledgeSourceSchemaInner(sqlite3 *db, const KnowledgeSourceSchema &schema) +{ + bool isExist = false; + auto errCode = SQLiteUtils::CheckTableExists(db, schema.tableName, isExist); + if (errCode != E_OK) { + return errCode; + } + if (!isExist) { + LOGE("Set not exist table's knowledge schema"); + return -E_INVALID_ARGS; + } + errCode = InitMeta(db, schema.tableName); + if (errCode != E_OK) { + return errCode; + } + RelationalSchemaObject knowledgeSchema; + std::tie(errCode, knowledgeSchema) = GetKnowledgeSourceSchema(db); + if (errCode != E_OK) { + return errCode; + } + TableInfo tableInfo; + errCode = SQLiteUtils::AnalysisSchema(db, schema.tableName, tableInfo); + if (errCode != E_OK) { + return errCode; + } + tableInfo.SetTrackerTable(GetTrackerTable(schema)); + bool isChanged = false; + std::tie(errCode, isChanged) = CheckSchemaValidAndChangeStatus(db, knowledgeSchema, schema, tableInfo); + if (errCode != E_OK) { + return errCode; + } + if (!isChanged) { + LOGI("Knowledge schema is no change, table %s len %zu", + DBCommon::StringMiddleMasking(schema.tableName).c_str(), schema.tableName.size()); + std::unique_ptr tableManager = std::make_unique(); + tableManager->CheckAndCreateTrigger(db, tableInfo, ""); + return E_OK; + } + errCode = InitLogTable(db, schema, tableInfo); + if (errCode != E_OK) { + return errCode; + } + knowledgeSchema.InsertTrackerSchema(GetTrackerSchema(schema)); + return SaveKnowledgeSourceSchema(db, knowledgeSchema); +} + +int KnowledgeSourceUtils::RemoveKnowledgeTableSchema(sqlite3 *db, const std::string &tableName) +{ + int errCode = E_OK; + RelationalSchemaObject knowledgeSchema; + std::tie(errCode, knowledgeSchema) = GetKnowledgeSourceSchema(db); + if (errCode != E_OK) { + return errCode; + } + knowledgeSchema.RemoveRelationalTable(tableName); + return SaveKnowledgeSourceSchema(db, knowledgeSchema); +} + +int KnowledgeSourceUtils::InitMeta(sqlite3 *db, const std::string &table) +{ + int errCode = SQLiteRelationalUtils::CreateRelationalMetaTable(db); + if (errCode != E_OK) { + LOGE("Create relational store meta table failed. err=%d", errCode); + return errCode; + } + errCode = SQLiteRelationalUtils::InitKnowledgeTableTypeToMeta(db, false, table); + if (errCode != E_OK) { + LOGE("Init table type to meta err:%d", errCode); + return errCode; + } + return SQLiteRelationalUtils::InitCursorToMeta(db, false, table); +} + +std::pair KnowledgeSourceUtils::CheckSchemaValidAndChangeStatus(sqlite3 *db, + const RelationalSchemaObject &knowledgeSchema, + const KnowledgeSourceSchema &schema, const TableInfo &tableInfo) +{ + std::pair res = {E_OK, false}; + auto &[errCode, isChange] = res; + if (!IsSchemaValid(schema, tableInfo)) { + errCode = -E_INVALID_ARGS; + return res; + } + RelationalSchemaObject rdbSchema; + std::tie(errCode, rdbSchema) = GetRDBSchema(db, false); + if (errCode != E_OK) { + return res; + } + if (IsTableInRDBSchema(schema.tableName, rdbSchema, false)) { + errCode = -E_INVALID_ARGS; + return res; + } + std::tie(errCode, rdbSchema) = GetRDBSchema(db, true); + if (errCode != E_OK) { + return res; + } + if (IsTableInRDBSchema(schema.tableName, rdbSchema, true)) { + errCode = -E_INVALID_ARGS; + return res; + } + isChange = IsSchemaChange(knowledgeSchema, schema); + return res; +} + +bool KnowledgeSourceUtils::IsSchemaValid(const KnowledgeSourceSchema &schema, const TableInfo &tableInfo) +{ + auto fields = tableInfo.GetFields(); + for (const auto &col : schema.knowledgeColNames) { + if (fields.find(col) == fields.end()) { + LOGE("Not exist knowledge col %s %zu table %s %zu", + DBCommon::StringMiddleMasking(col).c_str(), col.size(), + DBCommon::StringMiddleMasking(schema.tableName).c_str(), schema.tableName.size()); + return false; + } + } + for (const auto &col : schema.extendColNames) { + if (fields.find(col) == fields.end()) { + LOGE("Not exist extend col %s %zu table %s %zu", + DBCommon::StringMiddleMasking(col).c_str(), col.size(), + DBCommon::StringMiddleMasking(schema.tableName).c_str(), schema.tableName.size()); + return false; + } + } + return true; +} + +bool KnowledgeSourceUtils::IsTableInRDBSchema(const std::string &table, const RelationalSchemaObject &rdbSchema, + bool isTracker) +{ + if (isTracker) { + auto trackerTable = rdbSchema.GetTrackerTable(table); + if (!trackerTable.GetTableName().empty()) { + LOGE("Table %s len %zu was tracker table", DBCommon::StringMiddleMasking(table).c_str(), table.size()); + return true; + } + return false; + } + auto tableInfo = rdbSchema.GetTable(table); + if (!tableInfo.GetTableName().empty()) { + LOGE("Table %s len %zu was distributed table, type %d", DBCommon::StringMiddleMasking(table).c_str(), + table.size(), static_cast(tableInfo.GetTableSyncType())); + return true; + } + return false; +} + +bool KnowledgeSourceUtils::IsSchemaChange(const RelationalSchemaObject &dbSchema, const KnowledgeSourceSchema &schema) +{ + auto trackerTable = dbSchema.GetTrackerTable(schema.tableName); + if (trackerTable.IsEmpty()) { + LOGI("Check knowledge schema was change by first set"); + return true; + } + const auto &dbExtendsNames = trackerTable.GetExtendNames(); + if (dbExtendsNames != schema.extendColNames) { + LOGI("Check knowledge schema was change by extend col old %zu new %zu", + dbExtendsNames.size(), schema.extendColNames.size()); + return true; + } + const auto &dbTrackerCols = trackerTable.GetTrackerColNames(); + if (dbTrackerCols != schema.knowledgeColNames) { + LOGI("Check knowledge schema was change by knowledge col old %zu new %zu", + dbTrackerCols.size(), schema.knowledgeColNames.size()); + return true; + } + return false; +} + +int KnowledgeSourceUtils::InitLogTable(sqlite3 *db, const KnowledgeSourceSchema &schema, const TableInfo &tableInfo) +{ + std::unique_ptr tableManager = std::make_unique(); + auto errCode = tableManager->CreateRelationalLogTable(db, tableInfo); + if (errCode != E_OK) { + return errCode; + } + errCode = GenLogForExistData(db, tableInfo, tableManager); + if (errCode != E_OK) { + LOGE("Gen log failed %d", errCode); + return errCode; + } + errCode = SQLiteRelationalUtils::SetLogTriggerStatus(db, true); + if (errCode != E_OK) { + return errCode; + } + return tableManager->AddRelationalLogTableTrigger(db, tableInfo, ""); +} + +std::pair KnowledgeSourceUtils::GetKnowledgeSourceSchema(sqlite3 *db) +{ + std::pair res; + auto &[errCode, rdbSchema] = res; + const std::string knowledgeKey(DBConstant::RDB_KNOWLEDGE_SCHEMA_KEY); + const Key schemaKey(knowledgeKey.begin(), knowledgeKey.end()); + Value schemaVal; + errCode = SQLiteRelationalUtils::GetKvData(db, false, schemaKey, schemaVal); // save schema to meta_data + if (errCode == -E_NOT_FOUND) { + LOGD("Not found knowledge schema in db"); + errCode = E_OK; + return res; + } + if (errCode != E_OK) { + LOGE("Get knowledge schema from meta table failed. %d", errCode); + return res; + } + std::string schemaJson(schemaVal.begin(), schemaVal.end()); + errCode = rdbSchema.ParseFromTrackerSchemaString(schemaJson); + return res; +} + +std::pair KnowledgeSourceUtils::GetRDBSchema(sqlite3 *db, bool isTracker) +{ + std::pair res; + auto &[errCode, rdbSchema] = res; + std::string schemaKey = isTracker ? DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY : DBConstant::RELATIONAL_SCHEMA_KEY; + const Key schema(schemaKey.begin(), schemaKey.end()); + Value schemaVal; + errCode = SQLiteRelationalUtils::GetKvData(db, false, schema, schemaVal); // save schema to meta_data + if (errCode == -E_NOT_FOUND) { + LOGD("Not found rdb schema in db"); + errCode = E_OK; + return res; + } + if (errCode != E_OK) { + LOGE("Get rdb schema from meta table failed. %d", errCode); + return res; + } + std::string schemaJson(schemaVal.begin(), schemaVal.end()); + if (isTracker) { + errCode = rdbSchema.ParseFromTrackerSchemaString(schemaJson); + } else { + errCode = rdbSchema.ParseFromSchemaString(schemaJson); + } + return res; +} + +int KnowledgeSourceUtils::SaveKnowledgeSourceSchema(sqlite3 *db, const RelationalSchemaObject &schema) +{ + const std::string knowledgeKey(DBConstant::RDB_KNOWLEDGE_SCHEMA_KEY); + const Key schemaKey(knowledgeKey.begin(), knowledgeKey.end()); + Value schemaVal; + DBCommon::StringToVector(schema.ToSchemaString(), schemaVal); + int errCode = SQLiteRelationalUtils::PutKvData(db, false, schemaKey, schemaVal); // save schema to meta_data + if (errCode != E_OK) { + LOGE("Save schema to meta table failed. %d", errCode); + } + return errCode; +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/knowledge_source_utils.h b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/knowledge_source_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..7e8beaf831ff87a4b803304e23509afc739c241f --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/knowledge_source_utils.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025 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 KNOWLEDGE_SOURCE_UTILS_H +#define KNOWLEDGE_SOURCE_UTILS_H + +#include "relational_schema_object.h" +#include "relational_store_client.h" + +namespace DistributedDB { +class KnowledgeSourceUtils { +public: + static int SetKnowledgeSourceSchema(sqlite3 *db, const KnowledgeSourceSchema &schema); + + static int RemoveKnowledgeTableSchema(sqlite3 *db, const std::string &tableName); + + static int CleanDeletedData(sqlite3 *db, const std::string &tableName, uint64_t cursor); +protected: + static int SetKnowledgeSourceSchemaInner(sqlite3 *db, const KnowledgeSourceSchema &schema); + + static int InitMeta(sqlite3 *db, const std::string &table); + + static std::pair GetKnowledgeSourceSchema(sqlite3 *db); + + static std::pair GetRDBSchema(sqlite3 *db, bool isTracker); + + static int SaveKnowledgeSourceSchema(sqlite3 *db, const RelationalSchemaObject &schema); + + static std::pair CheckSchemaValidAndChangeStatus(sqlite3 *db, + const RelationalSchemaObject &knowledgeSchema, + const KnowledgeSourceSchema &schema, const TableInfo &tableInfo); + + static bool IsSchemaValid(const KnowledgeSourceSchema &schema, const TableInfo &tableInfo); + + static bool IsTableInRDBSchema(const std::string &table, const RelationalSchemaObject &rdbSchema, bool isTracker); + + static bool IsSchemaChange(const RelationalSchemaObject &dbSchema, const KnowledgeSourceSchema &schema); + + static int InitLogTable(sqlite3 *db, const KnowledgeSourceSchema &schema, const TableInfo &tableInfo); +}; +} + +#endif // KNOWLEDGE_SOURCE_UTILS_H diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp index cf405a1e95e7fec1093f6e362821487e4c145577..a68cca1fdcdb2d0bf2114ff10a4995520ac57c18 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp @@ -391,7 +391,7 @@ DBStatus RelationalStoreDelegateImpl::UpsertData(const std::string &tableName, c return OK; } -DBStatus RelationalStoreDelegateImpl::SetDistributedSchema(const DistributedSchema &schema) +DBStatus RelationalStoreDelegateImpl::SetDistributedSchema(const DistributedSchema &schema, bool isForceUpgrade) { if (conn_ == nullptr) { LOGE("[RelationalStore Delegate] Invalid connection for setting db schema!"); @@ -411,9 +411,10 @@ DBStatus RelationalStoreDelegateImpl::SetDistributedSchema(const DistributedSche LOGW("[RelationalStore Delegate] Get storeInfo failed %d", errCode); return TransferDBErrno(errCode); } - errCode = conn_->SetDistributedDbSchema(schema); - LOGI("[RelationalStore Delegate] %s %s SetDistributedSchema errCode:%d", - DBCommon::StringMiddleMasking(appId).c_str(), DBCommon::StringMiddleMasking(storeId).c_str(), errCode); + errCode = conn_->SetDistributedDbSchema(schema, isForceUpgrade); + LOGI("[RelationalStore Delegate] %s %s SetDistributedSchema errCode:%d, force upgrade: %d", + DBCommon::StringMiddleMasking(appId).c_str(), DBCommon::StringMiddleMasking(storeId).c_str(), errCode, + isForceUpgrade); return TransferDBErrno(errCode); } @@ -563,6 +564,7 @@ DBStatus RelationalStoreDelegateImpl::ClearWatermark(const ClearMetaDataOption & } return OK; } + #endif DBStatus RelationalStoreDelegateImpl::SetStoreConfig(const StoreConfig &config) @@ -595,5 +597,16 @@ DBStatus RelationalStoreDelegateImpl::OperateDataStatus(uint32_t dataOperator) } return OK; } + +int32_t RelationalStoreDelegateImpl::GetDeviceSyncTaskCount() +{ + if (conn_ == nullptr) { + LOGW("[RelationalStore Delegate] Invalid connection for get device sync task count."); + return 0; + } + int32_t count = conn_->GetDeviceSyncTaskCount(); + LOGI("[RelationalStore Delegate] Get device sync task count %" PRId32, count); + return count; +} } // namespace DistributedDB #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h index caea7eb59ff2d4c5d40aa806cc58075406c1ac9d..de6060d9215dc491317f71490c258dbd5e8b9bce 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h @@ -69,7 +69,7 @@ public: DBStatus UpsertData(const std::string &tableName, const std::vector &records, RecordStatus status) override; - DBStatus SetDistributedSchema(const DistributedSchema &schema) override; + DBStatus SetDistributedSchema(const DistributedSchema &schema, bool isForceUpgrade) override; std::pair GetDownloadingAssetsCount() override; @@ -95,6 +95,7 @@ public: DBStatus ClearMetaData(const ClearMetaDataOption &option) override; #endif + int32_t GetDeviceSyncTaskCount() override; private: static void OnSyncComplete(const std::map> &devicesStatus, const SyncStatusCallback &onComplete); diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp index f72eeb1e547d53c1ecea6d8e378eccbaa795d938..bce7713e52b1098aa40f8f5ea9bade92081d90ff 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp @@ -22,7 +22,6 @@ #include "db_dfx_adapter.h" #include "db_errno.h" #include "cloud/cloud_db_constant.h" -#include "cloud/cloud_storage_utils.h" #include "kv_store_errno.h" #include "log_print.h" #include "param_check_utils.h" @@ -38,6 +37,24 @@ namespace DistributedDB { namespace { const int GET_CONNECT_RETRY = 3; const int RETRY_GET_CONN_INTER = 30; + +DBStatus InitProperties(const RelationalStoreDelegate::Option &option, RelationalDBProperties &properties) +{ + properties.SetIntProp(RelationalDBProperties::DISTRIBUTED_TABLE_MODE, static_cast(option.tableMode)); + properties.SetBoolProp(RelationalDBProperties::SYNC_DUAL_TUPLE_MODE, option.syncDualTupleMode); + if (option.isEncryptedDb) { + if (!ParamCheckUtils::CheckEncryptedParameter(option.cipher, option.passwd) || option.iterateTimes == 0) { + return INVALID_ARGS; + } + properties.SetCipherArgs(option.cipher, option.passwd, option.iterateTimes); + } + properties.SetBoolProp(DBProperties::COMPRESS_ON_SYNC, option.isNeedCompressOnSync); + if (option.isNeedCompressOnSync) { + properties.SetIntProp( + DBProperties::COMPRESSION_RATE, ParamCheckUtils::GetValidCompressionRate(option.compressionRate)); + } + return OK; +} } RelationalStoreManager::RelationalStoreManager(const std::string &appId, const std::string &userId, int32_t instanceId) @@ -99,16 +116,11 @@ DB_API DBStatus RelationalStoreManager::OpenStore(const std::string &path, const RelationalDBProperties properties; properties.SetStringProp(RelationalDBProperties::DATA_DIR, canonicalDir); - properties.SetIntProp(RelationalDBProperties::DISTRIBUTED_TABLE_MODE, static_cast(option.tableMode)); properties.SetIdentifier(userId_, appId_, storeId, subUser_, instanceId_); - properties.SetBoolProp(RelationalDBProperties::SYNC_DUAL_TUPLE_MODE, option.syncDualTupleMode); - if (option.isEncryptedDb) { - if (!ParamCheckUtils::CheckEncryptedParameter(option.cipher, option.passwd) || option.iterateTimes == 0) { - return INVALID_ARGS; - } - properties.SetCipherArgs(option.cipher, option.passwd, option.iterateTimes); + auto ret = InitProperties(option, properties); + if (ret != OK) { + return ret; } - int errCode = E_OK; auto *conn = GetOneConnectionWithRetry(properties, errCode); if (conn == nullptr) { @@ -158,78 +170,6 @@ std::string RelationalStoreManager::GetDistributedTableName(const std::string &d return DBCommon::GetDistributedTableName(device, tableName); } -DB_API std::string RelationalStoreManager::GetDistributedLogTableName(const std::string &tableName) -{ - return DBCommon::GetLogTableName(tableName); -} - -static int GetCollateTypeByName(const std::map &collateTypeMap, - const std::string &name, CollateType &collateType) -{ - auto it = collateTypeMap.find(name); - if (it == collateTypeMap.end()) { - LOGW("collate map doesn't contain primary key we need"); - collateType = CollateType::COLLATE_NONE; - return E_OK; - } - if (static_cast(it->second) >= static_cast(CollateType::COLLATE_BUTT)) { - LOGE("collate type is invalid"); - return -E_INVALID_ARGS; - } - collateType = it->second; - return E_OK; -} - -DB_API std::vector RelationalStoreManager::CalcPrimaryKeyHash(const std::map &primaryKey, - const std::map &collateTypeMap) -{ - std::vector result; - if (primaryKey.empty()) { - LOGW("primaryKey is empty"); - return result; - } - int errCode = E_OK; - CollateType collateType = CollateType::COLLATE_NONE; - if (primaryKey.size() == 1) { - auto iter = primaryKey.begin(); - Field field = {iter->first, static_cast(iter->second.index()), true, false}; - if (GetCollateTypeByName(collateTypeMap, iter->first, collateType) != E_OK) { - return result; - } - errCode = CloudStorageUtils::CalculateHashKeyForOneField(field, primaryKey, false, collateType, result); - if (errCode != E_OK) { - // never happen - LOGE("calc hash fail when there is one primary key errCode = %d", errCode); - } - } else { - std::vector tempRes; - std::map pkOrderByUpperName; - for (const auto &item : primaryKey) { // we sort by upper case name in log table when calculate hash - pkOrderByUpperName[DBCommon::ToUpperCase(item.first)] = item.second; - } - - for (const auto &item : pkOrderByUpperName) { - std::vector temp; - Field field = {DBCommon::ToLowerCase(item.first), static_cast(item.second.index()), true, false}; - if (GetCollateTypeByName(collateTypeMap, DBCommon::ToLowerCase(item.first), collateType) != E_OK) { - return result; - } - errCode = CloudStorageUtils::CalculateHashKeyForOneField(field, primaryKey, false, collateType, temp); - if (errCode != E_OK) { - // never happen - LOGE("calc hash fail when there is more than one primary key errCode = %d", errCode); - return result; - } - tempRes.insert(tempRes.end(), temp.begin(), temp.end()); - } - errCode = DBCommon::CalcValueHash(tempRes, result); - if (errCode != E_OK) { - LOGE("calc hash fail when calc the composite primary key errCode = %d", errCode); - } - } - return result; -} - void RelationalStoreManager::SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback) { RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(callback, DBTypeInner::DB_RELATION); diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager_client.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager_client.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1540f46bc236f13f4fbc6e13c992394242f8497a --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager_client.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2025 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. + */ +#ifdef RELATIONAL_STORE +#include "relational_store_manager.h" + +#include "db_common.h" +#include "cloud/cloud_storage_utils.h" + +namespace DistributedDB { +DB_API std::string RelationalStoreManager::GetDistributedLogTableName(const std::string &tableName) +{ + return DBCommon::GetLogTableName(tableName); +} + +static int GetCollateTypeByName(const std::map &collateTypeMap, + const std::string &name, CollateType &collateType) +{ + auto it = collateTypeMap.find(name); + if (it == collateTypeMap.end()) { + LOGW("collate map doesn't contain primary key we need"); + collateType = CollateType::COLLATE_NONE; + return E_OK; + } + if (static_cast(it->second) >= static_cast(CollateType::COLLATE_BUTT)) { + LOGE("collate type is invalid"); + return -E_INVALID_ARGS; + } + collateType = it->second; + return E_OK; +} + +DB_API std::vector RelationalStoreManager::CalcPrimaryKeyHash(const std::map &primaryKey, + const std::map &collateTypeMap) +{ + std::vector result; + if (primaryKey.empty()) { + LOGW("primaryKey is empty"); + return result; + } + int errCode = E_OK; + CollateType collateType = CollateType::COLLATE_NONE; + if (primaryKey.size() == 1) { + auto iter = primaryKey.begin(); + Field field = {iter->first, static_cast(iter->second.index()), true, false}; + if (GetCollateTypeByName(collateTypeMap, iter->first, collateType) != E_OK) { + return result; + } + errCode = CloudStorageUtils::CalculateHashKeyForOneField(field, primaryKey, false, collateType, result); + if (errCode != E_OK) { + // never happen + LOGE("calc hash fail when there is one primary key errCode = %d", errCode); + } + } else { + std::vector tempRes; + std::map pkOrderByUpperName; + for (const auto &item : primaryKey) { // we sort by upper case name in log table when calculate hash + pkOrderByUpperName[DBCommon::ToUpperCase(item.first)] = item.second; + } + + for (const auto &item : pkOrderByUpperName) { + std::vector temp; + Field field = {DBCommon::ToLowerCase(item.first), static_cast(item.second.index()), true, false}; + if (GetCollateTypeByName(collateTypeMap, DBCommon::ToLowerCase(item.first), collateType) != E_OK) { + return result; + } + errCode = CloudStorageUtils::CalculateHashKeyForOneField(field, primaryKey, false, collateType, temp); + if (errCode != E_OK) { + // never happen + LOGE("calc hash fail when there is more than one primary key errCode = %d", errCode); + return result; + } + tempRes.insert(tempRes.end(), temp.begin(), temp.end()); + } + errCode = DBCommon::CalcValueHash(tempRes, result); + if (errCode != E_OK) { + LOGE("calc hash fail when calc the composite primary key errCode = %d", errCode); + } + } + return result; +} +} // namespace DistributedDB +#endif diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp index 54cd766c1f89b4e6bf12e61188b0372c631e9ec1..e0c5a8c7b4b96a1da29ee91c94b42f94772d9630 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp @@ -12,8 +12,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef _WIN32 +#include +#endif #include #include +#include #include #include #include @@ -24,6 +28,7 @@ #include "concurrent_adapter.h" #include "db_common.h" #include "db_constant.h" +#include "knowledge_source_utils.h" #include "kv_store_errno.h" #include "param_check_utils.h" #include "platform_specific.h" @@ -64,13 +69,20 @@ using namespace DistributedDB::OS; using namespace DistributedDB; namespace { +const std::string DISTRIBUTED_TABLE_MODE = "distributed_table_mode"; +static std::mutex g_binlogInitMutex; +static int g_binlogInit = -1; +constexpr const char *COMPRESS_WHITELIST[] = {"test.db"}; constexpr int E_OK = 0; constexpr int E_ERROR = 1; constexpr int STR_TO_LL_BY_DEVALUE = 10; constexpr int BUSY_TIMEOUT = 2000; // 2s. constexpr int MAX_BLOB_READ_SIZE = 5 * 1024 * 1024; // 5M limit const std::string DEVICE_TYPE = "device"; +const std::string KNOWLEDGE_TYPE = "knowledge"; const std::string SYNC_TABLE_TYPE = "sync_table_type_"; +const std::string KNOWLEDGE_CURSOR = "knowledge_cursor_"; +const std::string COMPRESS_VFS = "compressvfs"; class ValueHashCalc { public: ValueHashCalc() {}; @@ -308,8 +320,8 @@ class TimeHelperManager { public: static TimeHelperManager *GetInstance() { - static auto instance = new TimeHelperManager(); - return instance; + static TimeHelperManager instance; + return &instance; } void AddStore(const std::string &storeId) @@ -559,7 +571,7 @@ int GetLocalTimeOffsetFromMeta(sqlite3 *db, TimeOffset &offset) int GetTableModeFromMeta(sqlite3 *db, DistributedTableMode &mode) { - std::string keyStr = RelationalDBProperties::DISTRIBUTED_TABLE_MODE; + std::string keyStr = DISTRIBUTED_TABLE_MODE; int64_t dbVal = 0; int errCode = GetNumValueFromMeta(db, keyStr, dbVal); if (errCode != E_OK) { @@ -694,6 +706,7 @@ void CloudDataChangedObserver(sqlite3_context *ctx, int argc, sqlite3_value **ar auto changeStatus = static_cast(sqlite3_value_int(argv[3])); // 3 is param index bool isTrackerChange = (changeStatus & CloudDbConstant::ON_CHANGE_TRACKER) != 0; bool isP2pChange = (changeStatus & CloudDbConstant::ON_CHANGE_P2P) != 0; + bool isKnowledgeDataChange = (changeStatus & CloudDbConstant::ON_CHANGE_KNOWLEDGE) != 0; bool isExistObserver = false; { std::lock_guard lock(g_clientObserverMutex); @@ -707,10 +720,12 @@ void CloudDataChangedObserver(sqlite3_context *ctx, int argc, sqlite3_value **ar if (itTable != g_clientChangedDataMap[hashFileName].tableData.end()) { itTable->second.isTrackedDataChange |= isTrackerChange; itTable->second.isP2pSyncDataChange |= isP2pChange; + itTable->second.isKnowledgeDataChange |= isKnowledgeDataChange; } else { DistributedDB::ChangeProperties properties = { .isTrackedDataChange = isTrackerChange, - .isP2pSyncDataChange = isP2pChange + .isP2pSyncDataChange = isP2pChange, + .isKnowledgeDataChange = isKnowledgeDataChange }; g_clientChangedDataMap[hashFileName].tableData.insert_or_assign(tableName, properties); } @@ -834,7 +849,7 @@ std::string GetInsertTrigger(const std::string &tableName, bool isRowid, const s insertTrigger += "SELECT data_change('" + tableName + "', 'rowid', NEW._rowid_, 0);\n"; } else { insertTrigger += "SELECT data_change('" + tableName + "', "; - insertTrigger += "(SELECT name as a FROM pragma_table_info('" + tableName + "') WHERE pk=1), "; + insertTrigger += "'" + primaryKey + "', "; insertTrigger += "NEW." + primaryKey + ", 0);\n"; } insertTrigger += "END;"; @@ -851,7 +866,7 @@ std::string GetUpdateTrigger(const std::string &tableName, bool isRowid, const s updateTrigger += "SELECT data_change('" + tableName + "', 'rowid', NEW._rowid_, 1);\n"; } else { updateTrigger += "SELECT data_change('" + tableName + "', "; - updateTrigger += "(SELECT name as a FROM pragma_table_info('" + tableName + "') WHERE pk=1), "; + updateTrigger += "'" + primaryKey + "', "; updateTrigger += "NEW." + primaryKey + ", 1);\n"; } updateTrigger += "END;"; @@ -868,7 +883,7 @@ std::string GetDeleteTrigger(const std::string &tableName, bool isRowid, const s deleteTrigger += "SELECT data_change('" + tableName + "', 'rowid', OLD._rowid_, 2);\n"; } else { deleteTrigger += "SELECT data_change('" + tableName + "', "; - deleteTrigger += "(SELECT name as a FROM pragma_table_info('" + tableName + "') WHERE pk=1), "; + deleteTrigger += "'" + primaryKey + "', "; deleteTrigger += "OLD." + primaryKey + ", 2);\n"; } deleteTrigger += "END;"; @@ -1310,6 +1325,75 @@ void HandleDropCloudSyncTable(sqlite3 *db, const std::string &tableName) (void)sqlite3_finalize(statement); } +bool ClearMetaField(sqlite3 *db, const std::string &fieldName) +{ + std::vector key(fieldName.begin(), fieldName.end()); + std::string sql = "DELETE FROM naturalbase_rdb_aux_metadata WHERE key = ?;"; + sqlite3_stmt *statement = nullptr; + int errCode = sqlite3_prepare_v2(db, sql.c_str(), -1, &statement, nullptr); + if (errCode != SQLITE_OK) { + (void)sqlite3_finalize(statement); + return false; + } + + if (fieldName.rfind(KNOWLEDGE_CURSOR, 0) != std::string::npos) { + if (sqlite3_bind_text(statement, 1, fieldName.c_str(), fieldName.length(), + SQLITE_TRANSIENT) != SQLITE_OK) { + (void)sqlite3_finalize(statement); + return false; + } + } else { + if (sqlite3_bind_blob(statement, 1, static_cast(key.data()), key.size(), + SQLITE_TRANSIENT) != SQLITE_OK) { + (void)sqlite3_finalize(statement); + return false; + } + } + + int ret = sqlite3_step(statement); + (void)sqlite3_finalize(statement); + if (ret != SQLITE_DONE) { + LOGW("ClearMetaField step err: %d", ret); + return false; + } + return true; +} + +void HandleDropKnowledgeTable(sqlite3 *db, const std::string &tableName) +{ + // drop inverted table + std::string sql = "DROP TABLE IF EXISTS " + tableName + "_inverted;"; + (void)sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); + + // drop log table + std::string logTblName = std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log"; + sql = "DROP TABLE IF EXISTS " + logTblName + ";"; + (void)sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); + + // remove knowledge cursor + std::string keyStr = KNOWLEDGE_CURSOR + tableName; + if (!ClearMetaField(db, keyStr)) { + LOGW("Remove knowledge cursor unsucc"); + } + + // remove data cursor + keyStr = std::string(DBConstant::RELATIONAL_PREFIX) + "cursor_" + tableName; + if (!ClearMetaField(db, keyStr)) { + LOGW("Remove data cursor unsucc"); + } + + // remove table type meta + keyStr = SYNC_TABLE_TYPE + tableName; + if (!ClearMetaField(db, keyStr)) { + LOGW("Remove table type unsucc"); + } + + int errCode = KnowledgeSourceUtils::RemoveKnowledgeTableSchema(db, tableName); + if (errCode != E_OK) { + LOGW("Remove knowledge table schema unsucc, err: %d", errCode); + } +} + int HandleDropLogicDeleteData(sqlite3 *db, const std::string &tableName, uint64_t cursor) { LOGI("DropLogicDeleteData on table:%s length:%d cursor:%" PRIu64, @@ -1410,7 +1494,7 @@ void ClearTheLogAfterDropTable(sqlite3 *db, const char *tableName, const char *s if (tableType == DEVICE_TYPE) { RegisterGetSysTime(db); RegisterGetLastTime(db); - std::string targetFlag = "flag|0x01"; + std::string targetFlag = "flag|0x03"; std::string originalFlag = "flag&0x01=0x0"; auto tableMode = DistributedTableMode::COLLABORATION; (void)GetTableModeFromMeta(db, tableMode); @@ -1422,6 +1506,8 @@ void ClearTheLogAfterDropTable(sqlite3 *db, const char *tableName, const char *s ", timestamp=get_sys_time(0) WHERE " + originalFlag + " AND timestamp<" + std::to_string(dropTimeStamp); (void)sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); + } else if (tableType == KNOWLEDGE_TYPE) { + HandleDropKnowledgeTable(db, tableStr); } else { HandleDropCloudSyncTable(db, tableStr); } @@ -1550,11 +1636,39 @@ void PostHandle(bool isExists, sqlite3 *db) (void)ExecuteRawSQL(db, recursiveTrigger); } +void GetFtsTableInfos(sqlite3 *db, std::set &tableInfos) +{ + std::string sql = "SELECT name FROM main.sqlite_master WHERE type = 'table' AND sql LIKE 'CREATE VIRTUAL TABLE%'"; + sqlite3_stmt *stmt = nullptr; + int errCode = GetStatement(db, sql, stmt); + if (errCode != E_OK) { + LOGW("Prepare get fts table statement failed. err=%d", errCode); + return; + } + while ((errCode = StepWithRetry(stmt)) != SQLITE_DONE) { + if (errCode != SQLITE_ROW) { + LOGW("Get fts table info failed. err=%d", errCode); + ResetStatement(stmt); + return; + } + std::string tableName; + GetColumnTextValue(stmt, 0, tableName); + tableInfos.insert(tableName); + tableInfos.insert(tableName + "_config"); + tableInfos.insert(tableName + "_data"); + tableInfos.insert(tableName + "_docsize"); + tableInfos.insert(tableName + "_idx"); + } + ResetStatement(stmt); +} + int GetTableInfos(sqlite3 *db, std::map &tableInfos) { if (db == nullptr) { return -E_ERROR; } + std::set ftsTableInfos; + GetFtsTableInfos(db, ftsTableInfos); std::string sql = "SELECT name FROM main.sqlite_master WHERE type = 'table'"; sqlite3_stmt *stmt = nullptr; int errCode = GetStatement(db, sql, stmt); @@ -1570,7 +1684,8 @@ int GetTableInfos(sqlite3 *db, std::map &tableInfos) std::string tableName; GetColumnTextValue(stmt, 0, tableName); if (tableName.empty() || !ParamCheckUtils::CheckRelationalTableName(tableName) || - tableName.find("sqlite_") == 0 || tableName.find("naturalbase_") == 0) { + tableName.find("sqlite_") == 0 || tableName.find("naturalbase_") == 0 || + ftsTableInfos.find(tableName) != ftsTableInfos.end()) { continue; } tableInfos.insert(std::make_pair(tableName, true)); @@ -1628,10 +1743,29 @@ SQLITE_API int sqlite3_open16_relational(const void *filename, sqlite3 **ppDb) return err; } +static bool IsSupportCompressVfs(const char *filePath) +{ + if (filePath == nullptr) { + return false; + } + std::string filePathStr(filePath); + auto filename = filePathStr.substr(filePathStr.rfind("/") + 1, filePathStr.size()); + for (auto whiteItem : COMPRESS_WHITELIST) { + if (filename == std::string(whiteItem)) { + return true; + } + } + return false; +} + SQLITE_API int sqlite3_open_v2_relational(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs) { bool isExists = (access(filename, 0) == 0); - int err = sqlite3_open_v2(filename, ppDb, flags, zVfs); + const char *vfsOption = zVfs; + if (zVfs != nullptr && std::string(zVfs) == COMPRESS_VFS && !IsSupportCompressVfs(filename)) { + vfsOption = nullptr; + } + int err = sqlite3_open_v2(filename, ppDb, flags, vfsOption); if (err != SQLITE_OK) { return err; } @@ -1639,6 +1773,35 @@ SQLITE_API int sqlite3_open_v2_relational(const char *filename, sqlite3 **ppDb, return err; } +static bool IsBinlogSupported() +{ +#ifndef _WIN32 + auto handle = dlopen("libarkdata_db_core.z.so", RTLD_LAZY); + if (handle != nullptr) { + dlclose(handle); + return true; + } +#endif + return false; +} + +SQLITE_API int sqlite3_is_support_binlog_relational(const char *filename) +{ + if (filename == nullptr) { + return SQLITE_ERROR; + } + if (g_binlogInit == -1) { + std::lock_guard lock(g_binlogInitMutex); + if (g_binlogInit == -1) { + g_binlogInit = static_cast(IsBinlogSupported()); + } + } + if (g_binlogInit == static_cast(true)) { + return SQLITE_OK; + } + return SQLITE_ERROR; +} + DB_API DistributedDB::DBStatus RegisterClientObserver(sqlite3 *db, const ClientObserver &clientObserver) { std::string fileName; @@ -1670,10 +1833,19 @@ DB_API DistributedDB::DBStatus UnRegisterClientObserver(sqlite3 *db) return DistributedDB::DB_ERROR; } - std::lock_guard lock(g_clientObserverMutex); - auto it = g_clientObserverMap.find(hashFileName); - if (it != g_clientObserverMap.end()) { - g_clientObserverMap.erase(it); + { + std::lock_guard lock(g_clientObserverMutex); + auto it = g_clientObserverMap.find(hashFileName); + if (it != g_clientObserverMap.end()) { + g_clientObserverMap.erase(it); + } + } + { + std::lock_guard lock(g_clientChangedDataMutex); + auto it = g_clientChangedDataMap.find(hashFileName); + if (it != g_clientChangedDataMap.end()) { + g_clientChangedDataMap[hashFileName].tableData.clear(); + } } return DistributedDB::OK; } @@ -1751,7 +1923,6 @@ DB_API DistributedDB::DBStatus UnregisterStoreObserver(sqlite3 *db) std::string fileName; if (!GetDbFileName(db, fileName)) { LOGD("[UnregisterAllStoreObserver] StoreObserver is invalid."); - return DistributedDB::INVALID_ARGS; } @@ -1831,7 +2002,54 @@ DB_API DistributedDB::DBStatus CreateDataChangeTempTrigger(sqlite3 *db) { return DistributedDB::TransferDBErrno(CreateTempTrigger(db)); } -// hw export the symbols + +DistributedDB::DBStatus SetKnowledgeSourceSchema(sqlite3 *db, const DistributedDB::KnowledgeSourceSchema &schema) +{ + if (db == nullptr) { + LOGE("Can't set knowledge source schema with null db"); + return INVALID_ARGS; + } + int errCode = KnowledgeSourceUtils::SetKnowledgeSourceSchema(db, schema); + if (errCode == DistributedDB::E_OK) { + LOGI("Set knowledge source schema success, table %s len %zu", + DBCommon::StringMiddleMasking(schema.tableName).c_str(), schema.tableName.size()); + } else { + LOGE("Set knowledge source schema failed %d, table %s len %zu", + errCode, DBCommon::StringMiddleMasking(schema.tableName).c_str(), schema.tableName.size()); + } + return TransferDBErrno(errCode); +} + +DistributedDB::DBStatus CleanDeletedData(sqlite3 *db, const std::string &tableName, uint64_t cursor) +{ + if (db == nullptr) { + LOGE("Can't clean deleted data with null db"); + return INVALID_ARGS; + } + if (cursor > static_cast(INT64_MAX)) { + LOGW("Cursor is too large %" PRIu64, cursor); + cursor = 0; + } + int errCode = KnowledgeSourceUtils::CleanDeletedData(db, tableName, cursor); + if (errCode != DistributedDB::E_OK) { + LOGE("Clean delete data failed %d, table %s len %zu cursor " PRIu64, + errCode, DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), cursor); + } + return TransferDBErrno(errCode); +} + +void Clean(bool isOpenSslClean) +{ +#ifdef USE_FFRT + ConcurrentAdapter::Stop(); +#endif + if (isOpenSslClean) { + OPENSSL_cleanup(); + } + Logger::DeleteInstance(); +} + +// export the symbols #ifdef SQLITE_DISTRIBUTE_RELATIONAL #if defined(__GNUC__) # define EXPORT_SYMBOLS __attribute__ ((visibility ("default"))) @@ -1845,20 +2063,23 @@ struct sqlite3_api_routines_relational { int (*open)(const char *, sqlite3 **); int (*open16)(const void *, sqlite3 **); int (*open_v2)(const char *, sqlite3 **, int, const char *); + int (*is_support_binlog)(const char*); }; typedef struct sqlite3_api_routines_relational sqlite3_api_routines_relational; -static const sqlite3_api_routines_relational sqlite3HwApis = { +static const sqlite3_api_routines_relational sqlite3Apis = { #ifdef SQLITE_DISTRIBUTE_RELATIONAL sqlite3_open_relational, sqlite3_open16_relational, - sqlite3_open_v2_relational + sqlite3_open_v2_relational, + sqlite3_is_support_binlog_relational #else + 0, 0, 0, 0 #endif }; -EXPORT_SYMBOLS const sqlite3_api_routines_relational *sqlite3_export_relational_symbols = &sqlite3HwApis; +EXPORT_SYMBOLS const sqlite3_api_routines_relational *sqlite3_export_relational_symbols = &sqlite3Apis; #endif diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h index 012ba84c7e0199a0ea8ce57b86917ff6e1e4cf19..8bcebd1ea83070c825e7aee86805b317dc215de7 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h @@ -62,6 +62,8 @@ public: // Get meta data associated with the given key. int GetMetaData(const Key &key, Value &value) const override; + int GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const override; + // Put meta data as a key-value entry. int PutMetaData(const Key &key, const Value &value) override; @@ -137,11 +139,11 @@ public: // recycling the write handle void SetReusedHandle(StorageExecutor *handle); - int StartTransaction(TransactType type) override; + int StartTransaction(TransactType type, bool isAsyncDownload = false) override; - int Commit() override; + int Commit(bool isAsyncDownload = false) override; - int Rollback() override; + int Rollback(bool isAsyncDownload = false) override; int GetUploadCount(const QuerySyncObject &query, const Timestamp ×tamp, bool isCloudForcePush, bool isCompensatedTask, int64_t &count) override; @@ -270,6 +272,8 @@ public: int GetLockStatusByGid(const std::string &tableName, const std::string &gid, LockStatus &status) override; bool IsExistTableContainAssets() override; + + int GetCompressionOption(bool &needCompressOnSync, uint8_t &compressionRate) const override; protected: int FillReferenceData(CloudSyncData &syncData); @@ -298,6 +302,8 @@ private: OperatePerm perm = OperatePerm::NORMAL_PERM) const; SQLiteSingleVerRelationalStorageExecutor *GetHandleExpectTransaction(bool isWrite, int &errCode, OperatePerm perm = OperatePerm::NORMAL_PERM) const; + SQLiteSingleVerRelationalStorageExecutor *GetHandleExpectTransactionForAsyncDownload(bool isWrite, int &errCode, + OperatePerm perm = OperatePerm::NORMAL_PERM) const; void ReleaseHandle(SQLiteSingleVerRelationalStorageExecutor *&handle) const; // get @@ -340,6 +346,12 @@ private: void SaveCursorChange(const std::string &tableName, uint64_t currCursor); + int CommitForAsyncDownload(); + + int RollbackForAsyncDownload(); + + int StartTransactionForAsyncDownload(TransactType type); + // data std::shared_ptr storageEngine_ = nullptr; std::function onSchemaChanged_; @@ -363,7 +375,9 @@ private: mutable bool isCachedOption_; SQLiteSingleVerRelationalStorageExecutor *transactionHandle_ = nullptr; + SQLiteSingleVerRelationalStorageExecutor *asyncDownloadTransactionHandle_ = nullptr; mutable std::shared_mutex transactionMutex_; // used for transaction + mutable std::shared_mutex asyncDownloadtransactionMutex_; // used for async download transaction SchemaMgr schemaMgr_; mutable std::shared_mutex schemaMgrMutex_; diff --git a/kv_store/frameworks/libs/distributeddb/sqlite_adapter/src/tokenizer_export_type.h b/kv_store/frameworks/libs/distributeddb/sqlite_adapter/src/tokenizer_export_type.h index 97b0418816ec2a7063fc785cede4c9b352ac22fa..46ee1afbcf077e74247ece94fb6cef9f836d9e35 100644 --- a/kv_store/frameworks/libs/distributeddb/sqlite_adapter/src/tokenizer_export_type.h +++ b/kv_store/frameworks/libs/distributeddb/sqlite_adapter/src/tokenizer_export_type.h @@ -23,6 +23,7 @@ extern "C" { #endif #define GRD_OK 0 +#define GRD_INVALID_ARGS (-3000) #define GRD_API_NOT_SUPPORT (-8888) #define GRD_NO_DATA (-11000) #define GRD_FAILED_MEMORY_ALLOCATE (-13000) @@ -42,6 +43,12 @@ typedef enum GRD_CutMode { CUT_BUTT // INVALID TokenizeMode } GRD_CutModeE; +typedef enum GRD_CutScene { + DEFAULT = 0, + SEARCH = 1, + SCENE_BUTT // INVALID mode +} GRD_CutSceneE; + typedef enum GRD_ExtractMode { EXTRACT_TF_IDF = 0, EXTRACT_BUTT // INVALID ExtractMode @@ -54,6 +61,7 @@ typedef struct GRD_TokenizerParam { typedef struct GRD_CutOption { bool needPreProcess; + GRD_CutSceneE cutScene; } GRD_CutOptionT; typedef struct GRD_ExtractOption { diff --git a/kv_store/frameworks/libs/distributeddb/sqlite_adapter/src/tokenizer_sqlite.cpp b/kv_store/frameworks/libs/distributeddb/sqlite_adapter/src/tokenizer_sqlite.cpp index c2d6b4e6a2dd51384feec84037412012d6d5ca8a..1b54179219619705ac096dbc609f5aba0f433ae0 100644 --- a/kv_store/frameworks/libs/distributeddb/sqlite_adapter/src/tokenizer_sqlite.cpp +++ b/kv_store/frameworks/libs/distributeddb/sqlite_adapter/src/tokenizer_sqlite.cpp @@ -24,18 +24,52 @@ SQLITE_EXTENSION_INIT1 using namespace CNTokenizer; +typedef struct Fts5TokenizerParam { + uint32_t magicCode = 0; + GRD_CutScene cutScene = DEFAULT; +} Fts5TokenizerParamT; + static std::mutex g_mtx; -static uint32_t g_magicCode = 0x12345678; static uint32_t g_refCount = 0; constexpr int FTS5_MAX_VERSION = 2; +constexpr int CUSTOM_TOKENIZER_PARAM_NUM = 2; +constexpr int MAGIC_CODE = 0x12345678; +constexpr const char *CUT_SCENE_PARAM_NAME = "cut_mode"; +constexpr const char *CUT_SCENE_SHORT_WORDS = "short_words"; +constexpr const char *CUT_SCENE_DEFAULT = "default"; int fts5_customtokenizer_xCreate(void *sqlite3, const char **azArg, int nArg, Fts5Tokenizer **ppOut) { (void)sqlite3; std::lock_guard lock(g_mtx); + auto *pFts5TokenizerParam = new Fts5TokenizerParamT; + pFts5TokenizerParam->magicCode = MAGIC_CODE; + if (nArg != 0 && nArg != CUSTOM_TOKENIZER_PARAM_NUM) { + sqlite3_log(SQLITE_ERROR, "invalid args num"); + delete pFts5TokenizerParam; + return SQLITE_ERROR; + } + if (nArg == CUSTOM_TOKENIZER_PARAM_NUM) { + std::string paramKey = std::string(azArg[0]); + std::string paramValue = std::string(azArg[1]); + if (paramKey != CUT_SCENE_PARAM_NAME) { + sqlite3_log(SQLITE_ERROR, "invalid arg name"); + delete pFts5TokenizerParam; + return SQLITE_ERROR; + } + if (paramValue == CUT_SCENE_SHORT_WORDS) { + pFts5TokenizerParam->cutScene = SEARCH; + } else if (paramValue == CUT_SCENE_DEFAULT) { + pFts5TokenizerParam->cutScene = DEFAULT; + } else { + sqlite3_log(SQLITE_ERROR, "invalid arg value of cut scene"); + delete pFts5TokenizerParam; + return SQLITE_ERROR; + } + } g_refCount++; if (g_refCount != 1) { // 说明已经初始化过了,直接返回 - *ppOut = (Fts5Tokenizer *)&g_magicCode; + *ppOut = (Fts5Tokenizer *)pFts5TokenizerParam; return SQLITE_OK; } @@ -43,9 +77,10 @@ int fts5_customtokenizer_xCreate(void *sqlite3, const char **azArg, int nArg, Ft int ret = GRD_TokenizerInit(NULL, NULL, param); if (ret != GRD_OK) { sqlite3_log(ret, "GRD_TokenizerInit wrong"); + delete pFts5TokenizerParam; return ret; } - *ppOut = (Fts5Tokenizer *)&g_magicCode; // 需要保证*ppOut不为NULL,否则会使用默认分词器而不是自定的 + *ppOut = (Fts5Tokenizer *)pFts5TokenizerParam; // 需要保证*ppOut不为NULL,否则会使用默认分词器而不是自定的 return SQLITE_OK; } @@ -70,6 +105,11 @@ static char *CpyStr(const char *pText, int nText) int fts5_customtokenizer_xTokenize( Fts5Tokenizer *tokenizer_ptr, void *pCtx, int flags, const char *pText, int nText, XTokenFn xToken) { + Fts5TokenizerParamT *pFts5TokenizerParam = (Fts5TokenizerParamT *)tokenizer_ptr; + if (pFts5TokenizerParam == nullptr || pFts5TokenizerParam->magicCode != MAGIC_CODE) { + sqlite3_log(GRD_INVALID_ARGS, "The tokenizer is not initialized"); + return GRD_INVALID_ARGS; + } if (nText == 0) { return SQLITE_OK; } @@ -78,7 +118,7 @@ int fts5_customtokenizer_xTokenize( sqlite3_log(GRD_FAILED_MEMORY_ALLOCATE, "CpyStr wrong"); return GRD_FAILED_MEMORY_ALLOCATE; } - GRD_CutOptionT option = {false}; + GRD_CutOptionT option = {false, pFts5TokenizerParam->cutScene}; GRD_WordEntryListT *entryList = nullptr; int ret = GRD_TokenizerCut(ptr, option, &entryList); if (ret != GRD_OK) { @@ -109,11 +149,16 @@ int fts5_customtokenizer_xTokenize( void fts5_customtokenizer_xDelete(Fts5Tokenizer *tokenizer_ptr) { std::lock_guard lock(g_mtx); + Fts5TokenizerParamT *pFts5TokenizerParam = (Fts5TokenizerParamT *)tokenizer_ptr; + if (pFts5TokenizerParam != nullptr) { + delete pFts5TokenizerParam; + pFts5TokenizerParam = nullptr; + } g_refCount--; if (g_refCount != 0) { // 说明还有其他的地方在使用,不能释放资源 return; } - (void)GRD_TokenizerDestroy(tokenizer_ptr); + (void)GRD_TokenizerDestroy(nullptr); } /* @@ -121,20 +166,18 @@ void fts5_customtokenizer_xDelete(Fts5Tokenizer *tokenizer_ptr) ** If an error occurs, return NULL and leave an error in the database ** handle (accessible using sqlite3_errcode()/errmsg()). */ -static int fts5_api_from_db(sqlite3 *db, fts5_api **ppApi) +static int get_fts5_api(sqlite3 *db, fts5_api **api) { - sqlite3_stmt *pStmt = 0; - int rc; - - *ppApi = 0; - rc = sqlite3_prepare(db, "SELECT fts5(?1)", -1, &pStmt, 0); - if (rc == SQLITE_OK) { - sqlite3_bind_pointer(pStmt, 1, reinterpret_cast(ppApi), "fts5_api_ptr", 0); - (void)sqlite3_step(pStmt); - rc = sqlite3_finalize(pStmt); + sqlite3_stmt *stmt = nullptr; + *api = nullptr; + int ret = sqlite3_prepare(db, "SELECT fts5(?1)", -1, &stmt, 0); + if (ret != SQLITE_OK) { + sqlite3_log(ret, "sqlite3_prepare wrong"); + return ret; } - - return rc; + sqlite3_bind_pointer(stmt, 1, reinterpret_cast(api), "fts5_api_ptr", 0); + (void)sqlite3_step(stmt); + return sqlite3_finalize(stmt); } int sqlite3_customtokenizer_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi) @@ -145,13 +188,13 @@ int sqlite3_customtokenizer_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api fts5_tokenizer tokenizer = { fts5_customtokenizer_xCreate, fts5_customtokenizer_xDelete, fts5_customtokenizer_xTokenize}; - fts5_api *fts5api; - rc = fts5_api_from_db(db, &fts5api); + fts5_api *fts5api = nullptr; + rc = get_fts5_api(db, &fts5api); if (rc != SQLITE_OK) { - sqlite3_log(rc, "fts5_api_from_db wrong"); + sqlite3_log(rc, "get_fts5_api wrong"); return rc; } - if (fts5api == 0 || fts5api->iVersion < FTS5_MAX_VERSION) { + if (fts5api == nullptr || fts5api->iVersion < FTS5_MAX_VERSION) { sqlite3_log(SQLITE_ERROR, "sqlite3_customtokenizer_init wrong"); return SQLITE_ERROR; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/db_properties.h b/kv_store/frameworks/libs/distributeddb/storage/include/db_properties.h index dee39e70c9159ff89edaec18dbf899aede892b84..0c9653bff345f1e7f7872fd9f09f444cfeb1c7cc 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/db_properties.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/db_properties.h @@ -67,6 +67,9 @@ public: static constexpr const char *DATABASE_TYPE = "databaseType"; + static constexpr const char *COMPRESS_ON_SYNC = "needCompressOnSync"; + static constexpr const char *COMPRESSION_RATE = "compressionRate"; + protected: std::map stringProperties_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h b/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h index 3f56d255650c84915ebd88ae6962971217f57b8e..531b0dcaa16005a721901d3892b01e52c413ae5b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h @@ -116,11 +116,11 @@ public: virtual int GetCloudTableSchema(const TableName &tableName, TableSchema &tableSchema) = 0; - virtual int StartTransaction(TransactType type) = 0; + virtual int StartTransaction(TransactType type, bool isAsyncDownload = false) = 0; - virtual int Commit() = 0; + virtual int Commit(bool isAsyncDownload = false) = 0; - virtual int Rollback() = 0; + virtual int Rollback(bool isAsyncDownload = false) = 0; virtual int GetUploadCount(const QuerySyncObject &query, const Timestamp ×tamp, bool isCloudForcePush, bool isCompensatedTask, int64_t &count) = 0; diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h b/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h index d9c8a60e88e4b7fd2fadacae7bb4a1ae8c17abaa..b102ffb925a9cf13f587c1a7410d9d5c8f942328 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h @@ -100,7 +100,7 @@ public: virtual int SetConflictNotifier(int conflictType, const KvDBConflictAction &action) = 0; // Close and release the connection. - virtual int Close() = 0; + virtual int Close(bool isCloseImmediately = true) = 0; virtual std::string GetIdentifier() const = 0; @@ -171,6 +171,8 @@ public: virtual bool IsRebuild() const = 0; + virtual int ClearCloudWatermark() = 0; + virtual int OperateDataStatus(uint32_t dataOperator) = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h b/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h index 4cabb6b10131f148cb8f5616d956251f438b173c..6a74a50c257dd3bdbd1f638fec9143c1b4c7ed46 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h @@ -54,6 +54,8 @@ public: // Get meta data associated with the given key. virtual int GetMetaData(const Key &key, Value &value) const = 0; + virtual int GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const = 0; + // Put meta data as a key-value entry. virtual int PutMetaData(const Key &key, const Value &value, bool isInTransaction) = 0; diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_manager.h b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_manager.h index 88f028cda8699b0fc63edc3be2fcc73d3741ed0c..4191a3a67be89a42f900635457d150498394d193 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_manager.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_manager.h @@ -41,7 +41,7 @@ public: bool isNeedIfOpened = true); // used to close the connection. - static int ReleaseDatabaseConnection(IKvDBConnection *connection); + static int ReleaseDatabaseConnection(IKvDBConnection *connection, bool isCloseImmediately = true); // used to delete a kvdb with the given property. static int RemoveDatabase(const KvDBProperties &property); diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_pragma.h b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_pragma.h index dd47e8fd53b9200d5ada8106f6f479d8917f9795..6283ca9f05dd3321b4960e53019cc6274481d1fd 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_pragma.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_pragma.h @@ -64,6 +64,7 @@ struct PragmaSync { onComplete_(onComplete), wait_(wait), isQuerySync_(true), + isRetry_(true), query_(query) { } @@ -76,6 +77,7 @@ struct PragmaSync { onComplete_(onComplete), wait_(wait), isQuerySync_(false), + isRetry_(true), query_(Query::Select()) { } @@ -85,6 +87,7 @@ struct PragmaSync { mode_(option.mode), wait_(option.isWait), isQuerySync_(option.isQuery), + isRetry_(true), onSyncProcess_(onProcess) { if (!isQuerySync_) { @@ -98,16 +101,45 @@ struct PragmaSync { mode_(option.mode), wait_(option.isWait), isQuerySync_(false), + isRetry_(true), query_(Query::Select()), onSyncProcess_(onProcess) { } + PragmaSync(const DeviceSyncOption &option, const QuerySyncObject &query, + const std::function &devicesMap)> &onComplete) + : devices_(option.devices), + mode_(option.mode), + onComplete_(onComplete), + wait_(option.isWait), + isQuerySync_(option.isQuery), + isRetry_(option.isRetry) + { + if (!isQuerySync_) { + return; + } + query_ = query; + } + + PragmaSync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete) + : devices_(option.devices), + mode_(option.mode), + onComplete_(onComplete), + wait_(option.isWait), + isQuerySync_(false), + isRetry_(option.isRetry), + query_(Query::Select()) + { + } + std::vector devices_; int mode_; std::function &devicesMap)> onComplete_; bool wait_; bool isQuerySync_; + bool isRetry_; QuerySyncObject query_; DeviceSyncProcessCallback onSyncProcess_; }; diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_properties.h b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_properties.h index 36179cec33cf654df9b56b42ed48526869acb4f6..766de8c3cbe7573f8f3c90c9d04dc5d071fa61da 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_properties.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_properties.h @@ -64,8 +64,6 @@ public: static const std::string CONFLICT_RESOLVE_POLICY; static const std::string CHECK_INTEGRITY; static const std::string RM_CORRUPTED_DB; - static const std::string COMPRESS_ON_SYNC; - static const std::string COMPRESSION_RATE; static const std::string LOCAL_ONLY; static const std::string SHARED_MODE; diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h index 13652f3b521fa1c6728851689ae789d9f600bca9..acb034d762c26b5027bd936ddec9fc8555473c7a 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h @@ -76,7 +76,7 @@ public: virtual int GetDownloadingAssetsCount(int32_t &count) = 0; - virtual int SetDistributedDbSchema(const DistributedSchema &schema) = 0; + virtual int SetDistributedDbSchema(const DistributedSchema &schema, bool isForceUpgrade) = 0; virtual int SetTableMode(DistributedTableMode tableMode) = 0; @@ -100,6 +100,8 @@ public: virtual SyncProcess GetCloudTaskStatus(uint64_t taskId) = 0; #endif virtual int OperateDataStatus(uint32_t dataOperator) = 0; + + virtual int32_t GetDeviceSyncTaskCount() = 0; protected: // Get the stashed 'RelationalDB_ pointer' without ref. template diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h b/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h index 2ccc6c7c5de7da65d62c93829d8e97bff05d48c1..c98d1fe650159763653279f632b2ac409217f73f 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h @@ -33,7 +33,7 @@ namespace DistributedDB { class StorageProxy { public: StorageProxy(ICloudSyncStorageInterface *iCloud); - virtual ~StorageProxy() {}; + ~StorageProxy() {}; static std::shared_ptr GetCloudDb(ICloudSyncStorageInterface *iCloud); @@ -51,11 +51,11 @@ public: int SetCloudWaterMark(const std::string &tableName, std::string &cloudMark); - int StartTransaction(TransactType type = TransactType::DEFERRED); + int StartTransaction(TransactType type = TransactType::DEFERRED, bool isAsyncDownload = false); - int Commit(); + int Commit(bool isAsyncDownload = false); - int Rollback(); + int Rollback(bool isAsyncDownload = false); int GetUploadCount(const std::string &tableName, const Timestamp ×tamp, const bool isCloudForcePush, int64_t &count); @@ -188,6 +188,8 @@ public: int GetLockStatusByGid(const std::string &tableName, const std::string &gid, LockStatus &status); bool IsExistTableContainAssets(); + + bool GetTransactionExeFlag(); protected: void Init(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp index ee7540a243ea648a43cbdb4882420563a7e56c1c..05d175be5eda1a0adeafa04f6374aba14b410e6a 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp @@ -200,90 +200,6 @@ int CloudStorageUtils::BindAsset(int index, const VBucket &vBucket, const Field return errCode; } -int CloudStorageUtils::Int64ToVector(const VBucket &vBucket, const Field &field, CollateType collateType, - std::vector &value) -{ - (void)collateType; - int64_t val = 0; - if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { - return -E_CLOUD_ERROR; - } - DBCommon::StringToVector(std::to_string(val), value); - return E_OK; -} - -int CloudStorageUtils::BoolToVector(const VBucket &vBucket, const Field &field, CollateType collateType, - std::vector &value) -{ - (void)collateType; - bool val = false; - if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { // LCOV_EXCL_BR_LINE - return -E_CLOUD_ERROR; - } - DBCommon::StringToVector(std::to_string(val ? 1 : 0), value); - return E_OK; -} - -int CloudStorageUtils::DoubleToVector(const VBucket &vBucket, const Field &field, CollateType collateType, - std::vector &value) -{ - (void)collateType; - double val = 0.0; - if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { // LCOV_EXCL_BR_LINE - return -E_CLOUD_ERROR; - } - std::ostringstream s; - s << val; - DBCommon::StringToVector(s.str(), value); - return E_OK; -} - -int CloudStorageUtils::TextToVector(const VBucket &vBucket, const Field &field, CollateType collateType, - std::vector &value) -{ - std::string val; - if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { - return -E_CLOUD_ERROR; - } - if (collateType == CollateType::COLLATE_NOCASE) { - std::transform(val.begin(), val.end(), val.begin(), ::toupper); - } else if (collateType == CollateType::COLLATE_RTRIM) { - DBCommon::RTrim(val); - } - - DBCommon::StringToVector(val, value); - return E_OK; -} - -int CloudStorageUtils::BlobToVector(const VBucket &vBucket, const Field &field, CollateType collateType, - std::vector &value) -{ - (void)collateType; - if (field.type == TYPE_INDEX) { // LCOV_EXCL_BR_LINE - return CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, value); - } else if (field.type == TYPE_INDEX) { - Asset val; - if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { // LCOV_EXCL_BR_LINE - return -E_CLOUD_ERROR; - } - int errCode = RuntimeContext::GetInstance()->AssetToBlob(val, value); - if (errCode != E_OK) { // LCOV_EXCL_BR_LINE - LOGE("asset to blob fail, %d", errCode); - } - return errCode; - } else { - Assets val; - if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { // LCOV_EXCL_BR_LINE - return -E_CLOUD_ERROR; - } - int errCode = RuntimeContext::GetInstance()->AssetsToBlob(val, value); - if (errCode != E_OK) { // LCOV_EXCL_BR_LINE - LOGE("assets to blob fail, %d", errCode); - } - return errCode; - } -} - std::set CloudStorageUtils::GetCloudPrimaryKey(const TableSchema &tableSchema) { std::set pkSet; @@ -627,38 +543,6 @@ bool CloudStorageUtils::IsAssets(const Type &type) return type.index() == TYPE_INDEX; } -int CloudStorageUtils::CalculateHashKeyForOneField(const Field &field, const VBucket &vBucket, bool allowEmpty, - CollateType collateType, std::vector &hashValue) -{ - Type type; - bool isExisted = GetTypeCaseInsensitive(field.colName, vBucket, type); - if (allowEmpty && !isExisted) { - return E_OK; // if vBucket from cloud doesn't contain primary key and allowEmpty, no need to calculate hash - } - static std::map &)>> toVecFunc = { - { TYPE_INDEX, &CloudStorageUtils::Int64ToVector }, - { TYPE_INDEX, &CloudStorageUtils::BoolToVector }, - { TYPE_INDEX, &CloudStorageUtils::DoubleToVector }, - { TYPE_INDEX, &CloudStorageUtils::TextToVector }, - { TYPE_INDEX, &CloudStorageUtils::BlobToVector }, - { TYPE_INDEX, &CloudStorageUtils::BlobToVector }, - { TYPE_INDEX, &CloudStorageUtils::BlobToVector }, - }; - auto it = toVecFunc.find(field.type); - if (it == toVecFunc.end()) { - LOGE("unknown cloud type when convert field to vector."); - return -E_CLOUD_ERROR; - } - std::vector value; - int errCode = it->second(vBucket, field, collateType, value); - if (errCode != E_OK) { - LOGE("convert cloud field fail, %d", errCode); - return errCode; - } - return DBCommon::CalcValueHash(value, hashValue); -} - bool CloudStorageUtils::IsAssetsContainDuplicateAsset(Assets &assets) { std::set set; @@ -786,50 +670,6 @@ bool CloudStorageUtils::CheckAssetStatus(const Assets &assets) return true; } -std::string CloudStorageUtils::GetTableRefUpdateSql(const TableInfo &table, OpType opType) -{ - std::string sql; - std::string rowid = std::string(DBConstant::SQLITE_INNER_ROWID); - for (const auto &reference : table.GetTableReference()) { - if (reference.columns.empty()) { - return ""; - } - std::string sourceLogName = DBCommon::GetLogTableName(reference.sourceTableName); - sql += " UPDATE " + sourceLogName + " SET timestamp=get_raw_sys_time(), flag=flag|0x02 WHERE "; - int index = 0; - for (const auto &itCol : reference.columns) { - if (opType != OpType::UPDATE) { - continue; - } - if (index++ != 0) { - sql += " OR "; - } - sql += " (OLD." + itCol.second + " IS NOT " + " NEW." + itCol.second + ")"; - } - if (opType == OpType::UPDATE) { - sql += " AND "; - } - sql += " (flag&0x08=0x00) AND data_key IN (SELECT " + sourceLogName + ".data_key FROM " + sourceLogName + - " LEFT JOIN " + reference.sourceTableName + " ON " + sourceLogName + ".data_key = " + - reference.sourceTableName + "." + rowid + " WHERE "; - index = 0; - for (const auto &itCol : reference.columns) { - if (index++ != 0) { - sql += " OR "; - } - if (opType == OpType::UPDATE) { - sql += itCol.first + "=OLD." + itCol.second + " OR " + itCol.first + "=NEW." + itCol.second; - } else if (opType == OpType::INSERT) { - sql += itCol.first + "=NEW." + itCol.second; - } else if (opType == OpType::DELETE) { - sql += itCol.first + "=OLD." + itCol.second; - } - } - sql += ");"; - } - return sql; -} - std::string CloudStorageUtils::GetLeftJoinLogSql(const std::string &tableName, bool logAsTableA) { std::string sql; @@ -843,16 +683,6 @@ std::string CloudStorageUtils::GetLeftJoinLogSql(const std::string &tableName, b return sql; } -std::string CloudStorageUtils::GetUpdateLockChangedSql() -{ - return " status = CASE WHEN status == 2 THEN 3 ELSE status END"; -} - -std::string CloudStorageUtils::GetDeleteLockChangedSql() -{ - return " status = CASE WHEN status == 2 or status == 3 THEN 1 ELSE status END"; -} - bool CloudStorageUtils::ChkFillCloudAssetParam(const CloudSyncBatch &data, int errCode) { if (data.assets.empty()) { @@ -1028,34 +858,6 @@ bool CloudStorageUtils::CheckCloudSchemaFields(const TableSchema &tableSchema, c return true; } -void CloudStorageUtils::TransferFieldToLower(VBucket &vBucket) -{ - for (auto it = vBucket.begin(); it != vBucket.end();) { - std::string lowerField(it->first.length(), ' '); - std::transform(it->first.begin(), it->first.end(), lowerField.begin(), ::tolower); - if (lowerField != it->first) { - vBucket[lowerField] = std::move(vBucket[it->first]); - vBucket.erase(it++); - } else { - it++; - } - } -} - -bool CloudStorageUtils::GetTypeCaseInsensitive(const std::string &fieldName, const VBucket &vBucket, Type &data) -{ - auto tmpFieldName = fieldName; - auto tmpVBucket = vBucket; - std::transform(tmpFieldName.begin(), tmpFieldName.end(), tmpFieldName.begin(), ::tolower); - TransferFieldToLower(tmpVBucket); - auto it = tmpVBucket.find(tmpFieldName); - if (it == tmpVBucket.end()) { - return false; - } - data = it->second; - return true; -} - int CloudStorageUtils::BindUpdateLogStmtFromVBucket(const VBucket &vBucket, const TableSchema &tableSchema, const std::vector &colNames, sqlite3_stmt *updateLogStmt) { @@ -1502,26 +1304,6 @@ bool CloudStorageUtils::IsSystemRecord(const Key &key) return keyStr.find(prefixKey) == 0; } -std::string CloudStorageUtils::GetSelectIncCursorSql(const std::string &tableName) -{ - return "(SELECT value FROM " + DBCommon::GetMetaTableName() + " WHERE key=x'" + - DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "')"; -} - -std::string CloudStorageUtils::GetCursorIncSql(const std::string &tableName) -{ - return "UPDATE " + DBCommon::GetMetaTableName() + " SET value=value+1 WHERE key=x'" + - DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "';"; -} - -std::string CloudStorageUtils::GetCursorIncSqlWhenAllow(const std::string &tableName) -{ - std::string prefix = DBConstant::RELATIONAL_PREFIX; - return "UPDATE " + prefix + "metadata" + " SET value= case when (select 1 from " + - prefix + "metadata" + " where key='cursor_inc_flag' AND value = 'true') then value + 1" + - " else value end WHERE key=x'" + DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "';"; -} - std::string CloudStorageUtils::GetCursorUpgradeSql(const std::string &tableName) { return "INSERT OR REPLACE INTO " + DBCommon::GetMetaTableName() + "(key,value) VALUES (x'" + diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils_client.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils_client.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee25dbe693b4294e9ed4b30d8378f4f339b1e88d --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils_client.cpp @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2025 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_storage_utils.h" + +#include +#include "db_common.h" +#include "runtime_context.h" + +namespace DistributedDB { +int CloudStorageUtils::Int64ToVector(const VBucket &vBucket, const Field &field, CollateType collateType, + std::vector &value) +{ + (void)collateType; + int64_t val = 0; + if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { + return -E_CLOUD_ERROR; + } + DBCommon::StringToVector(std::to_string(val), value); + return E_OK; +} + +int CloudStorageUtils::BoolToVector(const VBucket &vBucket, const Field &field, CollateType collateType, + std::vector &value) +{ + (void)collateType; + bool val = false; + if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { // LCOV_EXCL_BR_LINE + return -E_CLOUD_ERROR; + } + DBCommon::StringToVector(std::to_string(val ? 1 : 0), value); + return E_OK; +} + +int CloudStorageUtils::DoubleToVector(const VBucket &vBucket, const Field &field, CollateType collateType, + std::vector &value) +{ + (void)collateType; + double val = 0.0; + if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { // LCOV_EXCL_BR_LINE + return -E_CLOUD_ERROR; + } + std::ostringstream s; + s << val; + DBCommon::StringToVector(s.str(), value); + return E_OK; +} + +int CloudStorageUtils::TextToVector(const VBucket &vBucket, const Field &field, CollateType collateType, + std::vector &value) +{ + std::string val; + if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { + return -E_CLOUD_ERROR; + } + if (collateType == CollateType::COLLATE_NOCASE) { + std::transform(val.begin(), val.end(), val.begin(), ::toupper); + } else if (collateType == CollateType::COLLATE_RTRIM) { + DBCommon::RTrim(val); + } + + DBCommon::StringToVector(val, value); + return E_OK; +} + +int CloudStorageUtils::BlobToVector(const VBucket &vBucket, const Field &field, CollateType collateType, + std::vector &value) +{ + (void)collateType; + if (field.type == TYPE_INDEX) { // LCOV_EXCL_BR_LINE + return CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, value); + } else if (field.type == TYPE_INDEX) { + Asset val; + if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { // LCOV_EXCL_BR_LINE + return -E_CLOUD_ERROR; + } +#ifdef RDB_CLIENT + return E_OK; +#else + int errCode = RuntimeContext::GetInstance()->AssetToBlob(val, value); + if (errCode != E_OK) { // LCOV_EXCL_BR_LINE + LOGE("asset to blob fail, %d", errCode); + } + return errCode; +#endif + } else { + Assets val; + if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { // LCOV_EXCL_BR_LINE + return -E_CLOUD_ERROR; + } +#ifdef RDB_CLIENT + return E_OK; +#else + int errCode = RuntimeContext::GetInstance()->AssetsToBlob(val, value); + if (errCode != E_OK) { // LCOV_EXCL_BR_LINE + LOGE("assets to blob fail, %d", errCode); + } + return errCode; +#endif + } +} + +int CloudStorageUtils::CalculateHashKeyForOneField(const Field &field, const VBucket &vBucket, bool allowEmpty, + CollateType collateType, std::vector &hashValue) +{ + Type type; + bool isExisted = GetTypeCaseInsensitive(field.colName, vBucket, type); + if (allowEmpty && !isExisted) { + return E_OK; // if vBucket from cloud doesn't contain primary key and allowEmpty, no need to calculate hash + } + static std::map &)>> toVecFunc = { + { TYPE_INDEX, &CloudStorageUtils::Int64ToVector }, + { TYPE_INDEX, &CloudStorageUtils::BoolToVector }, + { TYPE_INDEX, &CloudStorageUtils::DoubleToVector }, + { TYPE_INDEX, &CloudStorageUtils::TextToVector }, + { TYPE_INDEX, &CloudStorageUtils::BlobToVector }, + { TYPE_INDEX, &CloudStorageUtils::BlobToVector }, + { TYPE_INDEX, &CloudStorageUtils::BlobToVector }, + }; + auto it = toVecFunc.find(field.type); + if (it == toVecFunc.end()) { + LOGE("unknown cloud type when convert field to vector."); + return -E_CLOUD_ERROR; + } + std::vector value; + int errCode = it->second(vBucket, field, collateType, value); + if (errCode != E_OK) { + LOGE("convert cloud field fail, %d", errCode); + return errCode; + } + return DBCommon::CalcValueHash(value, hashValue); +} + +void CloudStorageUtils::TransferFieldToLower(VBucket &vBucket) +{ + for (auto it = vBucket.begin(); it != vBucket.end();) { + std::string lowerField(it->first.length(), ' '); + std::transform(it->first.begin(), it->first.end(), lowerField.begin(), ::tolower); + if (lowerField != it->first) { + vBucket[lowerField] = std::move(vBucket[it->first]); + vBucket.erase(it++); + } else { + it++; + } + } +} + +bool CloudStorageUtils::GetTypeCaseInsensitive(const std::string &fieldName, const VBucket &vBucket, Type &data) +{ + auto tmpFieldName = fieldName; + auto tmpVBucket = vBucket; + std::transform(tmpFieldName.begin(), tmpFieldName.end(), tmpFieldName.begin(), ::tolower); + TransferFieldToLower(tmpVBucket); + auto it = tmpVBucket.find(tmpFieldName); + if (it == tmpVBucket.end()) { + return false; + } + data = it->second; + return true; +} + +std::string CloudStorageUtils::GetSelectIncCursorSql(const std::string &tableName) +{ + return "(SELECT value FROM " + DBCommon::GetMetaTableName() + " WHERE key=x'" + + DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "')"; +} + +std::string CloudStorageUtils::GetCursorIncSql(const std::string &tableName) +{ + return "UPDATE " + DBCommon::GetMetaTableName() + " SET value=value+1 WHERE key=x'" + + DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "';"; +} + +std::string CloudStorageUtils::GetCursorIncSqlWhenAllow(const std::string &tableName) +{ + std::string prefix = DBConstant::RELATIONAL_PREFIX; + return "UPDATE " + prefix + "metadata" + " SET value= case when (select 1 from " + + prefix + "metadata" + " where key='cursor_inc_flag' AND value = 'true') then value + 1" + + " else value end WHERE key=x'" + DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "';"; +} + +std::string CloudStorageUtils::GetUpdateLockChangedSql() +{ + return " status = CASE WHEN status == 2 THEN 3 ELSE status END"; +} + +std::string CloudStorageUtils::GetDeleteLockChangedSql() +{ + return " status = CASE WHEN status == 2 or status == 3 THEN 1 ELSE status END"; +} + +std::string CloudStorageUtils::GetTableRefUpdateSql(const TableInfo &table, OpType opType) +{ + std::string sql; + std::string rowid = std::string(DBConstant::SQLITE_INNER_ROWID); + for (const auto &reference : table.GetTableReference()) { + if (reference.columns.empty()) { + return ""; + } + std::string sourceLogName = DBCommon::GetLogTableName(reference.sourceTableName); + sql += " UPDATE " + sourceLogName + " SET timestamp=get_raw_sys_time(), flag=flag|0x02 WHERE "; + int index = 0; + for (const auto &itCol : reference.columns) { + if (opType != OpType::UPDATE) { + continue; + } + if (index++ != 0) { + sql += " OR "; + } + sql += " (OLD." + itCol.second + " IS NOT " + " NEW." + itCol.second + ")"; + } + if (opType == OpType::UPDATE) { + sql += " AND "; + } + sql += " (flag&0x08=0x00) AND data_key IN (SELECT " + sourceLogName + ".data_key FROM " + sourceLogName + + " LEFT JOIN " + reference.sourceTableName + " ON " + sourceLogName + ".data_key = " + + reference.sourceTableName + "." + rowid + " WHERE "; + index = 0; + for (const auto &itCol : reference.columns) { + if (index++ != 0) { + sql += " OR "; + } + if (opType == OpType::UPDATE) { + sql += itCol.first + "=OLD." + itCol.second + " OR " + itCol.first + "=NEW." + itCol.second; + } else if (opType == OpType::INSERT) { + sql += itCol.first + "=NEW." + itCol.second; + } else if (opType == OpType::DELETE) { + sql += itCol.first + "=OLD." + itCol.second; + } + } + sql += ");"; + } + return sql; +} +} diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h b/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h index e6847b341588407fbf3a19729af5265be42a38aa..b055c37f0c54dca21fb64bed8d7b0f320293bb9f 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h @@ -59,7 +59,8 @@ enum class LogInfoFlag : uint32_t { FLAG_LOGIC_DELETE_FOR_LOGOUT = 0x800, FLAG_ASSET_DOWNLOADING_FOR_ASYNC = 0x1000, FLAG_LOGIN_USER = 0x2000, // same hash key, login user's data - FLAG_CLOUD_UPDATE_LOCAL = 0x4000, + FLAG_CLOUD_UPDATE_LOCAL = 0x4000, // 1 indicates an update on the cloud side, and 0 indicates data inserted on the + // cloud side or data operated locally }; struct RowDataWithLog { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp index 4dc8f24f6cc9fd112f3091466de65aa7ec7d51fe..f27f602b814f1faf8da3d70de5abc9a5a3fc2816 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp @@ -198,6 +198,11 @@ int RdSingleVerNaturalStore::GetMetaData(const Key &key, Value &value) const return -E_NOT_SUPPORT; } +int RdSingleVerNaturalStore::GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const +{ + return -E_NOT_SUPPORT; +} + int RdSingleVerNaturalStore::PutMetaData(const Key &key, const Value &value, bool isInTransaction) { return -E_NOT_SUPPORT; @@ -585,4 +590,12 @@ void RdSingleVerNaturalStore::InitDataBaseOption(const KvDBProperties &kvDBProp, void RdSingleVerNaturalStore::SetReceiveDataInterceptor(const DataInterceptor &interceptor) { } + +CloudSyncConfig RdSingleVerNaturalStore::GetCloudSyncConfig() const +{ + // Implement the pure virtual function in the base class SyncAbleKvDB. + // Currently, rd does not have this function, so return the default value of CloudSyncConfig. + CloudSyncConfig config; + return config; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.h index 0fbfe89685a766f755e788fa02851c9994cc46bd..80d903134c471a2fba7413cc140b7a45fe16e954 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.h @@ -60,6 +60,8 @@ public: int GetMetaData(const Key &key, Value &value) const override; + int GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const override; + int PutMetaData(const Key &key, const Value &value, bool isInTransaction) override; // Delete multiple meta data records in a transaction. @@ -144,6 +146,8 @@ public: void CommitNotify(int notifyEvent, KvDBCommitNotifyFilterAbleData *data) override; void SetReceiveDataInterceptor(const DataInterceptor &interceptor) override; + + CloudSyncConfig GetCloudSyncConfig() const override; private: int PreCheckRdImport(std::string &storePath); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp index 4faa13d985b8426ca10a10a6ec3bc3ecc2d21e27..2c43b9c3d369deac84cea81cf3db5078ccd257ce 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp @@ -463,7 +463,7 @@ int RdSingleVerNaturalStoreConnection::RegisterLifeCycleCallback(const DatabaseL } // Called when Close and delete the connection. -int RdSingleVerNaturalStoreConnection::PreClose() +int RdSingleVerNaturalStoreConnection::PreClose(bool isCloseImmediately) { // check if result set closed std::lock_guard lock(kvDbResultSetsMutex_); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.h index e8b76c5aa2e3c2af21460ba380e7ea657b79ac5c..cc7866e41586501ba7faa3ba2aa7e5d5da5e8e3f 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.h @@ -90,7 +90,7 @@ public: int RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier) override; // Called when Close and delete the connection. - int PreClose() override; + int PreClose(bool isCloseImmediately) override; int CheckIntegrity() const override; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp index 17adfff96752913b02510fc262767456b442d0e7..bb51a0fb4466e967c502c65798e500fa17de6cef 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp @@ -273,6 +273,7 @@ int RdSingleVerResultSet::MoveTo(int position) const int RdSingleVerResultSet::MoveToFirst() { + std::lock_guard lockGuard(mutex_); if (!isMovedBefore_) { return MoveToNext(); } @@ -299,6 +300,7 @@ int RdSingleVerResultSet::MoveToFirst() int RdSingleVerResultSet::MoveToLast() { + std::lock_guard lockGuard(mutex_); int errCode = E_OK; do { errCode = MoveToNext(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp index 6996332e44e0456f42f766370d1192bf621e696d..efcf423df63b75f0f32ffbc3a476f466f5ae9a77 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp @@ -46,13 +46,14 @@ int RdSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *& return ret; } GRD_DB *db = nullptr; - ret = TryToOpenMainDatabase(isWrite, db); + auto option = GetOption(); + ret = TryToOpenMainDatabase(isWrite, db, option); if (ret != E_OK) { LOGE("[RdSingleVerStorageEngine] GRD_DBOPEN FAILED:%d", ret); return ret; } - if (!option_.readOnly) { - std::string tableMode = GetTableMode(option_.isHashTable); + if (!option.readOnly) { + std::string tableMode = GetTableMode(option.isHashTable); ret = RdCreateCollection(db, SYNC_COLLECTION_NAME, tableMode.c_str(), 0); if (ret != E_OK) { LOGE("[RdSingleVerStorageEngine] GRD_CreateCollection SYNC_COLLECTION_NAME FAILED %d", ret); @@ -71,8 +72,8 @@ int RdSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *& (void)RdDBClose(db, GRD_DB_CLOSE_IGNORE_ERROR); return -E_OUT_OF_MEMORY; } - if (OS::CheckPathExistence(option_.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) && - OS::RemoveFile(option_.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) != E_OK) { + if (OS::CheckPathExistence(option.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) && + OS::RemoveFile(option.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) != E_OK) { LOGE("Finish to create the complete database, but delete token fail! errCode = [E_SYSTEM_API_FAIL]"); delete handle; handle = nullptr; @@ -124,7 +125,7 @@ int RdSingleVerStorageEngine::CreateNewDirsAndSetSecOpt() const return CreateNewDirsAndSetSecOption(option_); } -int RdSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, GRD_DB *&db) +int RdSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, GRD_DB *&db, OpenDbProperties &optionTemp) { // Only could get the main database handle in the uninitialized and the main status. if (GetEngineState() != EngineState::INVALID && GetEngineState() != EngineState::MAINDB) { @@ -132,10 +133,10 @@ int RdSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, GRD_DB *&db) return -E_EKEYREVOKED; } - option_.uri = GetDbDir(option_.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + + optionTemp.uri = GetDbDir(optionTemp.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; + SetUri(optionTemp.uri); - OpenDbProperties optionTemp = option_; if (!isWrite) { optionTemp.createIfNecessary = false; } @@ -150,17 +151,6 @@ int RdSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, GRD_DB *&db) return errCode; } -int RdSingleVerStorageEngine::GetDbHandle(bool isWrite, const SecurityOption &secOpt, GRD_DB *&dbHandle) -{ - int errCode = TryToOpenMainDatabase(isWrite, dbHandle); - LOGD("Finish to open the main database, write[%d], label[%d], flag[%d], id[%.6s], errCode[%d]", isWrite, - secOpt.securityLabel, secOpt.securityFlag, hashIdentifier_.c_str(), errCode); - if (!(ParamCheckUtils::IsS3SECEOpt(secOpt) && errCode == -E_EKEYREVOKED)) { - return errCode; - } - return -E_NOT_SUPPORT; -} - int RdSingleVerStorageEngine::PreCreateExecutor(bool isWrite) { if (!isWrite) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.h index 4b7887eb9156c77dc96fbeeab16c2d37ac57d5f8..dafd3975e048a36d309312cbac9753bc907b9dbe 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.h @@ -46,9 +46,7 @@ private: int CreateNewDirsAndSetSecOpt() const; - int TryToOpenMainDatabase(bool isWrite, GRD_DB *&db); - - int GetDbHandle(bool isWrite, const SecurityOption &secOpt, GRD_DB *&dbHandle); + int TryToOpenMainDatabase(bool isWrite, GRD_DB *&db, OpenDbProperties &optionTemp); int OpenGrdDb(const OpenDbProperties &option, GRD_DB *&db); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.cpp index 0cfce6b0e220f7fc9cb984185871eeaa98fd9fce..51d32dcb289c28fccf200024d060a302b2bb8d22 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.cpp @@ -248,7 +248,6 @@ int RdKVBatchPushback(GRD_KVBatchT *batch, const Key &key, const Value &value) innerVal.data = (void *)&value[0]; innerVal.dataLen = (uint32_t)value.size(); } - int ret = TransferGrdErrno( GRD_KVBatchPushback(innerKey.data, innerKey.dataLen, innerVal.data, innerVal.dataLen, batch)); if (ret != E_OK) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.cpp index 13c4cf90557775c62bfa5a0bbf6552475d2f5c8f..71654c0425b3b958431010c8d149ab18eb382612 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.cpp @@ -422,4 +422,13 @@ void GenericKvDB::MarkRebuild() { isRebuild_ = true; } + +int GenericKvDB::PreClose() +{ + if (connectionCount_.load() == 1) { + return E_OK; + } + // it will not cause busy when close db, only to verify the last conn + return -E_BUSY; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.h b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.h index 042e4bbd600bf13ef5cf4db5f5786d5d068123eb..4b9bbd5ce927a7257627a2ccd76b9378a581250d 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.h @@ -134,6 +134,8 @@ public: virtual void ResetSyncStatus(); void MarkRebuild() override; + + virtual int PreClose(); protected: // Create a connection object, no DB ref increased. virtual GenericKvDBConnection *NewConnection(int &errCode) = 0; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.cpp index 74fabd6e6a09ae44985088044b6930caf5fb3fee..957d0dc8d2a9841a9b241570caffcc5a6550fb31 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.cpp @@ -175,7 +175,7 @@ int GenericKvDBConnection::SetConflictNotifier(int conflictType, const KvDBConfl return -E_NOT_SUPPORT; } -int GenericKvDBConnection::Close() +int GenericKvDBConnection::Close(bool isCloseImmediately) { if (kvDB_ == nullptr) { return -E_INVALID_CONNECTION; @@ -190,7 +190,7 @@ int GenericKvDBConnection::Close() return -E_BUSY; } - int errCode = PreClose(); + int errCode = PreClose(isCloseImmediately); if (errCode != E_OK) { LOGE("Close connection failed, err:'%d'.", errCode); return errCode; @@ -214,9 +214,9 @@ int GenericKvDBConnection::Pragma(int cmd, void *parameter) return -E_NOT_SUPPORT; } -int GenericKvDBConnection::PreClose() +int GenericKvDBConnection::PreClose(bool isCloseImmediately) { - return E_OK; + return kvDB_->PreClose(); } void GenericKvDBConnection::SetSafeDeleted() @@ -457,6 +457,11 @@ bool GenericKvDBConnection::IsRebuild() const return isRebuild_; } +int GenericKvDBConnection::ClearCloudWatermark() +{ + return -E_NOT_SUPPORT; +} + int GenericKvDBConnection::OperateDataStatus([[gnu::unused]] uint32_t dataOperator) { return -E_NOT_SUPPORT; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.h index e752a7dd6fe31c5392b9fdc38ef6b7e6857a386c..fe37fc7718f7714e3629a9ea73743980fd8ad7ef 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.h @@ -44,7 +44,7 @@ public: int SetConflictNotifier(int conflictType, const KvDBConflictAction &action) override; // Close and release the connection. - int Close() final; + int Close(bool isCloseImmediately = true) final override; std::string GetIdentifier() const override; @@ -113,6 +113,8 @@ public: bool IsRebuild() const override; + int ClearCloudWatermark() override; + int OperateDataStatus(uint32_t dataOperator) override; protected: // Get the stashed 'KvDB_ pointer' without ref. @@ -133,7 +135,7 @@ protected: bool IsObserverEmpty(); // Called in Close(), overriding of Close() is forbidden. - virtual int PreClose(); + virtual int PreClose(bool isCloseImmediately); GenericKvDB *kvDB_; std::atomic isExclusive_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_manager.cpp index 68d23e5041b2e301942a0245ca1cfe8a62978d9e..d2a394490d8d5779b80b54601b842fcbea983721 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_manager.cpp @@ -293,16 +293,16 @@ bool KvDBManager::CheckOpenDBOptionWithCached(const KvDBProperties &properties, return false; } - bool compressOnSyncUser = properties.GetBoolProp(KvDBProperties::COMPRESS_ON_SYNC, false); - bool compressOnSyncGet = kvDB->GetMyProperties().GetBoolProp(KvDBProperties::COMPRESS_ON_SYNC, false); + bool compressOnSyncUser = properties.GetBoolProp(DBProperties::COMPRESS_ON_SYNC, false); + bool compressOnSyncGet = kvDB->GetMyProperties().GetBoolProp(DBProperties::COMPRESS_ON_SYNC, false); if (compressOnSyncUser != compressOnSyncGet) { LOGE("Failed to check compress option, the input %d not match with cached %d.", compressOnSyncUser, compressOnSyncGet); return false; } if (compressOnSyncUser) { - int compressRateUser = properties.GetIntProp(KvDBProperties::COMPRESSION_RATE, 0); - int compressRateGet = kvDB->GetMyProperties().GetIntProp(KvDBProperties::COMPRESSION_RATE, 0); + int compressRateUser = properties.GetIntProp(DBProperties::COMPRESSION_RATE, 0); + int compressRateGet = kvDB->GetMyProperties().GetIntProp(DBProperties::COMPRESSION_RATE, 0); if (compressRateUser != compressRateGet) { LOGE("Failed to check compress rate, the input %d not match with cached %d.", compressRateUser, compressRateGet); @@ -364,7 +364,7 @@ IKvDBConnection *KvDBManager::GetDatabaseConnection(const KvDBProperties &proper return connection; } -int KvDBManager::ReleaseDatabaseConnection(IKvDBConnection *connection) +int KvDBManager::ReleaseDatabaseConnection(IKvDBConnection *connection, bool isCloseImmediately) { if (connection == nullptr) { return -E_INVALID_DB; @@ -376,7 +376,7 @@ int KvDBManager::ReleaseDatabaseConnection(IKvDBConnection *connection) return -E_OUT_OF_MEMORY; } manager->EnterDBOpenCloseProcess(identifier); - int errCode = connection->Close(); + int errCode = connection->Close(isCloseImmediately); manager->ExitDBOpenCloseProcess(identifier); if (errCode != E_OK) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_properties.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_properties.cpp index 6e655bba60bdb11f7a94398453bf7706c7ae2d0d..ae8c6d12fe52bd2df9be767359bb794d07bbe4d4 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_properties.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_properties.cpp @@ -28,8 +28,6 @@ const std::string KvDBProperties::SECURITY_FLAG = "securityFlag"; const std::string KvDBProperties::CONFLICT_RESOLVE_POLICY = "conflictResolvePolicy"; const std::string KvDBProperties::CHECK_INTEGRITY = "checkIntegrity"; const std::string KvDBProperties::RM_CORRUPTED_DB = "rmCorruptedDb"; -const std::string KvDBProperties::COMPRESS_ON_SYNC = "needCompressOnSync"; -const std::string KvDBProperties::COMPRESSION_RATE = "compressionRate"; const std::string KvDBProperties::LOCAL_ONLY = "localOnly"; const std::string KvDBProperties::SHARED_MODE = "sharedMode"; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.cpp index ae6511bb828ccc5f5772eee76a87a94486a655af..a8dbabc376279dd70bf095c1e17afd35b117ad7b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.cpp @@ -92,7 +92,7 @@ void SyncAbleKvDB::Close() } // Start a sync action. -int SyncAbleKvDB::Sync(const ISyncer::SyncParma &parma, uint64_t connectionId) +int SyncAbleKvDB::Sync(const ISyncer::SyncParam &parma, uint64_t connectionId) { if (!started_) { int errCode = StartSyncer(); @@ -206,13 +206,13 @@ int SyncAbleKvDB::StartSyncerWithNoLock(bool isCheckSyncActive, bool isNeedActiv // active to non_active userChangeListener_ = RuntimeContext::GetInstance()->RegisterUserChangedListener( [this](void *) { ChangeUserListener(); }, UserChangeMonitor::USER_ACTIVE_TO_NON_ACTIVE_EVENT); - LOGI("[KVDB] [StartSyncerWithNoLock] [%.3s] After RegisterUserChangedListener", label.c_str()); + LOGI("[KVDB] [StartSyncerWithNoLock] [%.3s]", label.c_str()); } else if (isSyncDualTupleMode && (userChangeListener_ == nullptr)) { EventType event = isNeedActive ? UserChangeMonitor::USER_ACTIVE_EVENT : UserChangeMonitor::USER_NON_ACTIVE_EVENT; userChangeListener_ = RuntimeContext::GetInstance()->RegisterUserChangedListener( [this](void *) { UserChangeHandle(); }, event); - LOGI("[KVDB] [StartSyncerWithNoLock] [%.3s] After RegisterUserChangedListener event=%d", label.c_str(), event); + LOGI("[KVDB] [StartSyncerWithNoLock] [%.3s] event=%d", label.c_str(), event); } return errCode; } @@ -599,6 +599,30 @@ CloudSyncer *SyncAbleKvDB::GetAndIncCloudSyncer() return cloudSyncer_; } +bool SyncAbleKvDB::ExchangeClosePending(bool expected) +{ + return syncer_.ExchangeClosePending(expected); +} + +int SyncAbleKvDB::PreClose() +{ + if (GenericKvDB::PreClose() == E_OK) { + int32_t taskCount = GetTaskCount(); + if (taskCount > 0) { + LOGI("[PreClose] task count:%d", taskCount); + return -E_BUSY; + } + ExchangeClosePending(true); + taskCount = GetTaskCount(); + if (taskCount > 0) { + LOGI("[PreClose] task count:%d.", taskCount); + ExchangeClosePending(false); + return -E_BUSY; + } + } + return E_OK; +} + #ifdef USE_DISTRIBUTEDDB_CLOUD void SyncAbleKvDB::FillSyncInfo(const CloudSyncOption &option, const SyncProcessCallback &onProcess, CloudSyncer::CloudTaskInfo &info) diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.h b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.h index 8167cb6d40d208872d9cd08bc0019a0674edd4a2..0ecdf79139d1b4e16fd16e87308f0987488e3a73 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.h @@ -43,7 +43,7 @@ public: void Close() override; // Start a sync action. - int Sync(const ISyncer::SyncParma &parma, uint64_t connectionId); + int Sync(const ISyncer::SyncParam &parma, uint64_t connectionId); // Cancel a sync action. int CancelSync(uint32_t syncId); @@ -109,6 +109,9 @@ public: int32_t GetTaskCount(); + virtual CloudSyncConfig GetCloudSyncConfig() const = 0; + + int PreClose() override; #ifdef USE_DISTRIBUTEDDB_CLOUD int Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess); @@ -155,6 +158,7 @@ protected: protected: virtual std::map GetDataBaseSchemas(); + bool ExchangeClosePending(bool expected); #ifdef USE_DISTRIBUTEDDB_CLOUD virtual bool CheckSchemaSupportForCloudSync() const; #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb_connection.cpp index 94275ffecc01365ce4321cc304c47af67d223681..a9444d471a7ac2fef372149b646d27ea6df2ae9b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb_connection.cpp @@ -145,11 +145,12 @@ int SyncAbleKvDBConnection::PragmaSyncAction(const PragmaSync *syncParameter) IncObjRef(this); } - ISyncer::SyncParma syncParam; + ISyncer::SyncParam syncParam; syncParam.devices = syncParameter->devices_; syncParam.mode = syncParameter->mode_; syncParam.wait = syncParameter->wait_; syncParam.isQuerySync = syncParameter->isQuerySync_; + syncParam.isRetry = syncParameter->isRetry_; syncParam.syncQuery = syncParameter->query_; syncParam.onFinalize = [this]() { DecObjRef(this); }; if (syncParameter->onComplete_) { @@ -418,7 +419,8 @@ int SyncAbleKvDBConnection::Sync(const CloudSyncOption &option, const SyncProces int securityLabel = INVALID_SEC_LABEL; int securityFlag = INVALID_SEC_FLAG; GetSecurityOption(securityLabel, securityFlag); - if (securityLabel == S4) { + CloudSyncConfig config = kvDB->GetCloudSyncConfig(); + if ((securityLabel == S4) && (!config.isSupportEncrypt)) { LOGE("The current data does not support synchronization."); return -E_SECURITY_OPTION_CHECK_ERROR; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_vacuum.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_vacuum.cpp index 9014b4707a9c5aecd9a906eeed347ab2c0b08db9..89b082641f6b2d2fae52b48c3d223d98e9cf7b48 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_vacuum.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_vacuum.cpp @@ -283,7 +283,7 @@ void MultiVerVacuum::VacuumTaskExecutor() } } // No thread will remove entry from dbMapVacuumTask_, so here is concurrency safe. - LOGI("[Vacuum][Executor] Execute vacuum task for database=%s.", nextDatabase.c_str()); + LOGI("[Vacuum][Executor] Execute vacuum task for database."); ExecuteSpecificVacuumTask(dbMapVacuumTask_[nextDatabase]); // Awake foreground thread at this task switch point vacuumTaskCv_.notify_all(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.cpp index 2f57b7bf77cd3ce554b12931c49baaa4c9d6a6de..6cdb7485c70bd1ad6ddf92c6eb0f91cc25c3d9b3 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.cpp @@ -543,19 +543,28 @@ int SingleVerDatabaseOper::RunRekeyLogic(CipherType type, const CipherPassword & int errCode = SQLiteUtils::OpenDatabase(option, db); if (errCode != E_OK) { LOGE("[RunRekeyLogic] Open database new connect fail!, errCode = [%d]", errCode); - goto END; + return errCode; } - - errCode = SQLiteUtils::Rekey(db, passwd); - if (errCode != E_OK) { - LOGE("[RunRekeyLogic] Rekey fail!, errCode = [%d]", errCode); - goto END; + errCode = RunRekeyLogicInner(type, db, passwd); + if (db != nullptr) { + (void)sqlite3_close_v2(db); + db = nullptr; } + return errCode; +} +int SingleVerDatabaseOper::RunRekeyLogicInner(CipherType type, sqlite3 *db, const CipherPassword &passwd) +{ // Release all the connections, update the passwd and re-initialize the storage engine. storageEngine_->Release(); - singleVerNaturalStore_->GetDbPropertyForUpdate().SetPassword(type, passwd); - errCode = InitStorageEngine(); + int rekeyRet = SQLiteUtils::Rekey(db, passwd); + if (rekeyRet != E_OK) { + LOGE("[RunRekeyLogic] Rekey fail!, errCode = [%d]", rekeyRet); + } else { + singleVerNaturalStore_->GetDbPropertyForUpdate().SetPassword(type, passwd); + } + + int errCode = InitStorageEngine(); if (errCode != E_OK) { LOGE("Init storage engine while rekey open failed:%d", errCode); } @@ -565,12 +574,6 @@ int SingleVerDatabaseOper::RunRekeyLogic(CipherType type, const CipherPassword & LOGI("Rekey successfully, locked state init state successfully, need ignore open file failed!"); errCode = -E_FORBID_CACHEDB; } - -END: - if (db != nullptr) { - (void)sqlite3_close_v2(db); - db = nullptr; - } - return errCode; + return rekeyRet == E_OK ? errCode : rekeyRet; } } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.h b/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.h index b670b0d9ff63c97210392968af0761c0ff879d2f..626b1706034e345c5f0b38e72872d5b9a7bbc90c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.h @@ -74,6 +74,8 @@ private: int BackupDatabase(const ImportFileInfo &info) const; + int RunRekeyLogicInner(CipherType type, sqlite3 *db, const CipherPassword &passwd); + SQLiteSingleVerNaturalStore *singleVerNaturalStore_; SQLiteStorageEngine *storageEngine_; }; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_store_instance.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_store_instance.cpp index 5a7007608d6bf936ff7a9c6b865f508185c4f454..546d28df0d1055dc270b576351f700677dd6d353 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_store_instance.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_store_instance.cpp @@ -67,7 +67,7 @@ int RelationalStoreInstance::ReleaseDataBaseConnection(RelationalStoreConnection static IRelationalStore *GetFromCache(const RelationalDBProperties &properties, int &errCode) { errCode = E_OK; - std::string identifier = properties.GetStringProp(RelationalDBProperties::IDENTIFIER_DATA, ""); + std::string identifier = properties.GetStringProp(RelationalDBProperties::DATA_DIR, ""); std::lock_guard lockGuard(storeLock_); auto iter = dbs_.find(identifier); if (iter == dbs_.end()) { @@ -88,14 +88,14 @@ static IRelationalStore *GetFromCache(const RelationalDBProperties &properties, // Save to IKvDB to the global map void RelationalStoreInstance::RemoveKvDBFromCache(const RelationalDBProperties &properties) { - std::string identifier = properties.GetStringProp(RelationalDBProperties::IDENTIFIER_DATA, ""); + std::string identifier = properties.GetStringProp(RelationalDBProperties::DATA_DIR, ""); std::lock_guard lockGuard(storeLock_); dbs_.erase(identifier); } void RelationalStoreInstance::SaveRelationalDBToCache(IRelationalStore *store, const RelationalDBProperties &properties) { - std::string identifier = properties.GetStringProp(RelationalDBProperties::IDENTIFIER_DATA, ""); + std::string identifier = properties.GetStringProp(RelationalDBProperties::DATA_DIR, ""); std::lock_guard lockGuard(storeLock_); if (dbs_.count(identifier) == 0) { dbs_.insert(std::pair(identifier, store)); @@ -186,6 +186,22 @@ int CheckCompatibility(const RelationalDBProperties &prop, const RelationalDBPro LOGE("Failed to check dual tuple sync mode for rdb."); return -E_MODE_MISMATCH; } + bool compressOnSyncUser = prop.GetBoolProp(DBProperties::COMPRESS_ON_SYNC, false); + bool compressOnSyncGet = existedProp.GetBoolProp(DBProperties::COMPRESS_ON_SYNC, false); + if (compressOnSyncUser != compressOnSyncGet) { + LOGE("Failed to check compress option, the input %d not match with cached %d.", compressOnSyncUser, + compressOnSyncGet); + return -E_INVALID_ARGS; + } + if (compressOnSyncUser) { + int compressRateUser = prop.GetIntProp(DBProperties::COMPRESSION_RATE, 0); + int compressRateGet = existedProp.GetIntProp(DBProperties::COMPRESSION_RATE, 0); + if (compressRateUser != compressRateGet) { + LOGE("Failed to check compress rate, the input %d not match with cached %d.", compressRateUser, + compressRateGet); + return -E_INVALID_ARGS; + } + } return E_OK; } } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage.cpp index b0bde0a893926e96429ec6378df225b3a03dd1cd..68b16f4d938b6f352e5ab30e5cee0fd8a20f5d53 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage.cpp @@ -84,7 +84,7 @@ std::vector RelationalSyncAbleStorage::GetIdentifier() const std::vector RelationalSyncAbleStorage::GetDualTupleIdentifier() const { - std::string identifier = storageEngine_->GetProperties().GetStringProp( + std::string identifier = storageEngine_->GetRelationalProperties().GetStringProp( DBProperties::DUAL_TUPLE_IDENTIFIER_DATA, ""); std::vector identifierVect(identifier.begin(), identifier.end()); return identifierVect; @@ -102,10 +102,9 @@ void RelationalSyncAbleStorage::GetMaxTimestamp(Timestamp ×tamp) const errCode = handle->GetMaxTimestamp(storageEngine_->GetSchema().GetTableNames(), timestamp); if (errCode != E_OK) { LOGE("GetMaxTimestamp failed, errCode:%d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } ReleaseHandle(handle); - return; } int RelationalSyncAbleStorage::GetMaxTimestamp(const std::string &tableName, Timestamp ×tamp) const @@ -119,7 +118,7 @@ int RelationalSyncAbleStorage::GetMaxTimestamp(const std::string &tableName, Tim errCode = handle->GetMaxTimestamp({ tableName }, timestamp); if (errCode != E_OK) { LOGE("GetMaxTimestamp failed, errCode:%d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } ReleaseHandle(handle); return errCode; @@ -135,7 +134,7 @@ SQLiteSingleVerRelationalStorageExecutor *RelationalSyncAbleStorage::GetHandle(b auto handle = static_cast( storageEngine_->FindExecutor(isWrite, perm, errCode)); if (handle == nullptr) { - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } return handle; } @@ -179,9 +178,6 @@ void RelationalSyncAbleStorage::ReleaseHandle(SQLiteSingleVerRelationalStorageEx // Get meta data associated with the given key. int RelationalSyncAbleStorage::GetMetaData(const Key &key, Value &value) const { - if (storageEngine_ == nullptr) { - return -E_INVALID_DB; - } if (key.size() > DBConstant::MAX_KEY_SIZE) { return -E_INVALID_ARGS; } @@ -192,7 +188,25 @@ int RelationalSyncAbleStorage::GetMetaData(const Key &key, Value &value) const } errCode = handle->GetKvData(key, value); if (errCode != E_OK && errCode != -E_NOT_FOUND) { - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); + } + ReleaseHandle(handle); + return errCode; +} + +int RelationalSyncAbleStorage::GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const +{ + if (keyPrefix.size() > DBConstant::MAX_KEY_SIZE) { + return -E_INVALID_ARGS; + } + int errCode = E_OK; + auto handle = GetHandle(false, errCode, OperatePerm::NORMAL_PERM); + if (handle == nullptr) { + return errCode; + } + errCode = handle->GetKvDataByPrefixKey(keyPrefix, data); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } ReleaseHandle(handle); return errCode; @@ -201,9 +215,6 @@ int RelationalSyncAbleStorage::GetMetaData(const Key &key, Value &value) const // Put meta data as a key-value entry. int RelationalSyncAbleStorage::PutMetaData(const Key &key, const Value &value) { - if (storageEngine_ == nullptr) { - return -E_INVALID_DB; - } int errCode = E_OK; auto *handle = GetHandle(true, errCode, OperatePerm::NORMAL_PERM); if (handle == nullptr) { @@ -213,7 +224,7 @@ int RelationalSyncAbleStorage::PutMetaData(const Key &key, const Value &value) errCode = handle->PutKvData(key, value); // meta doesn't need time. if (errCode != E_OK) { LOGE("Put kv data err:%d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } ReleaseHandle(handle); return errCode; @@ -249,7 +260,7 @@ int RelationalSyncAbleStorage::PutMetaData(const Key &key, const Value &value, b errCode = handle->PutKvData(key, value); if (errCode != E_OK) { LOGE("Put kv data err:%d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } if (!isInTransaction) { ReleaseHandle(handle); @@ -260,9 +271,6 @@ int RelationalSyncAbleStorage::PutMetaData(const Key &key, const Value &value, b // Delete multiple meta data records in a transaction. int RelationalSyncAbleStorage::DeleteMetaData(const std::vector &keys) { - if (storageEngine_ == nullptr) { - return -E_INVALID_DB; - } for (const auto &key : keys) { if (key.empty() || key.size() > DBConstant::MAX_KEY_SIZE) { return -E_INVALID_ARGS; @@ -279,7 +287,7 @@ int RelationalSyncAbleStorage::DeleteMetaData(const std::vector &keys) if (errCode != E_OK) { handle->Rollback(); LOGE("[SinStore] DeleteMetaData failed, errCode = %d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } else { handle->Commit(); } @@ -290,9 +298,6 @@ int RelationalSyncAbleStorage::DeleteMetaData(const std::vector &keys) // Delete multiple meta data records with key prefix in a transaction. int RelationalSyncAbleStorage::DeleteMetaDataByPrefixKey(const Key &keyPrefix) const { - if (storageEngine_ == nullptr) { - return -E_INVALID_DB; - } if (keyPrefix.empty() || keyPrefix.size() > DBConstant::MAX_KEY_SIZE) { return -E_INVALID_ARGS; } @@ -306,7 +311,7 @@ int RelationalSyncAbleStorage::DeleteMetaDataByPrefixKey(const Key &keyPrefix) c errCode = handle->DeleteMetaDataByPrefixKey(keyPrefix); if (errCode != E_OK) { LOGE("[SinStore] DeleteMetaData by prefix key failed, errCode = %d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } ReleaseHandle(handle); return errCode; @@ -315,9 +320,6 @@ int RelationalSyncAbleStorage::DeleteMetaDataByPrefixKey(const Key &keyPrefix) c // Get all meta data keys. int RelationalSyncAbleStorage::GetAllMetaKeys(std::vector &keys) const { - if (storageEngine_ == nullptr) { - return -E_INVALID_DB; - } int errCode = E_OK; auto *handle = GetHandle(true, errCode, OperatePerm::NORMAL_PERM); if (handle == nullptr) { @@ -326,7 +328,7 @@ int RelationalSyncAbleStorage::GetAllMetaKeys(std::vector &keys) const errCode = handle->GetAllMetaKeys(keys); if (errCode != E_OK) { - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } ReleaseHandle(handle); return errCode; @@ -594,8 +596,8 @@ int RelationalSyncAbleStorage::SaveSyncDataItems(const QueryObject &object, std: data.tableName = query.GetTableName(); // SPLIT_BY_DEVICE trigger observer with device, userId, appId and storeId, so trigger with isChangeData false // COLLABORATION trigger observer with changeData, so trigger with isChangeData true - TriggerObserverAction(deviceName, std::move(data), - GetDbProperties().GetDistributedTableMode() == DistributedTableMode::COLLABORATION, Origin::ORIGIN_REMOTE); + TriggerObserverAction(deviceName, std::move(data), storageEngine_->GetRelationalProperties() + .GetDistributedTableMode() == DistributedTableMode::COLLABORATION, Origin::ORIGIN_REMOTE); } ReleaseHandle(handle); @@ -613,7 +615,7 @@ int RelationalSyncAbleStorage::PutSyncData(const QueryObject &query, std::vector int errCode = SaveSyncDataItems(query, dataItems, deviceName); // Currently true to check value content if (errCode != E_OK) { LOGE("[Relational] PutSyncData errCode:%d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } return errCode; } @@ -637,7 +639,7 @@ int RelationalSyncAbleStorage::GetSecurityOption(SecurityOption &option) const option = securityOption_; return E_OK; } - std::string dbPath = storageEngine_->GetProperties().GetStringProp(DBProperties::DATA_DIR, ""); + std::string dbPath = storageEngine_->GetRelationalProperties().GetStringProp(DBProperties::DATA_DIR, ""); int errCode = RuntimeContext::GetInstance()->GetSecurityOption(dbPath, securityOption_); if (errCode == E_OK) { option = securityOption_; @@ -683,7 +685,7 @@ int RelationalSyncAbleStorage::InterceptData(std::vector &en int RelationalSyncAbleStorage::CreateDistributedDeviceTable(const std::string &device, const RelationalSyncStrategy &syncStrategy) { - auto mode = storageEngine_->GetProperties().GetDistributedTableMode(); + auto mode = storageEngine_->GetRelationalProperties().GetDistributedTableMode(); if (mode != DistributedTableMode::SPLIT_BY_DEVICE) { LOGD("No need create device table in COLLABORATION mode."); return E_OK; @@ -698,7 +700,7 @@ int RelationalSyncAbleStorage::CreateDistributedDeviceTable(const std::string &d errCode = handle->StartTransaction(TransactType::IMMEDIATE); if (errCode != E_OK) { LOGE("Start transaction failed:%d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); ReleaseHandle(handle); return errCode; } @@ -866,7 +868,7 @@ int RelationalSyncAbleStorage::CheckAndInitQueryCondition(QueryObject &query) co errCode = handle->CheckQueryObjectLegal(table, query, schema.GetSchemaVersion()); if (errCode != E_OK) { LOGE("Check relational query condition failed. %d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } ReleaseHandle(handle); @@ -1027,15 +1029,18 @@ void RelationalSyncAbleStorage::ReleaseRemoteQueryContinueToken(ContinueToken &t StoreInfo RelationalSyncAbleStorage::GetStoreInfo() const { StoreInfo info = { - storageEngine_->GetProperties().GetStringProp(DBProperties::USER_ID, ""), - storageEngine_->GetProperties().GetStringProp(DBProperties::APP_ID, ""), - storageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, "") + storageEngine_->GetRelationalProperties().GetStringProp(DBProperties::USER_ID, ""), + storageEngine_->GetRelationalProperties().GetStringProp(DBProperties::APP_ID, ""), + storageEngine_->GetRelationalProperties().GetStringProp(DBProperties::STORE_ID, "") }; return info; } -int RelationalSyncAbleStorage::StartTransaction(TransactType type) +int RelationalSyncAbleStorage::StartTransaction(TransactType type, bool isAsyncDownload) { + if (isAsyncDownload) { + return StartTransactionForAsyncDownload(type); + } if (storageEngine_ == nullptr) { return -E_INVALID_DB; } @@ -1060,8 +1065,11 @@ int RelationalSyncAbleStorage::StartTransaction(TransactType type) return errCode; } -int RelationalSyncAbleStorage::Commit() +int RelationalSyncAbleStorage::Commit(bool isAsyncDownload) { + if (isAsyncDownload) { + return CommitForAsyncDownload(); + } std::unique_lock lock(transactionMutex_); if (transactionHandle_ == nullptr) { LOGE("relation database is null or the transaction has not been started"); @@ -1074,8 +1082,11 @@ int RelationalSyncAbleStorage::Commit() return errCode; } -int RelationalSyncAbleStorage::Rollback() +int RelationalSyncAbleStorage::Rollback(bool isAsyncDownload) { + if (isAsyncDownload) { + return RollbackForAsyncDownload(); + } std::unique_lock lock(transactionMutex_); if (transactionHandle_ == nullptr) { LOGE("Invalid handle for rollback or the transaction has not been started."); @@ -1126,10 +1137,6 @@ int RelationalSyncAbleStorage::GetUploadCount(const QuerySyncObject &query, cons int RelationalSyncAbleStorage::GetCloudData(const TableSchema &tableSchema, const QuerySyncObject &querySyncObject, const Timestamp &beginTime, ContinueToken &continueStmtToken, CloudSyncData &cloudDataResult) { - if (transactionHandle_ == nullptr) { - LOGE("the transaction has not been started"); - return -E_INVALID_DB; - } SyncTimeRange syncTimeRange = { .beginTime = beginTime }; QuerySyncObject query = querySyncObject; query.SetSchema(GetSchemaInfo()); @@ -1153,18 +1160,23 @@ int RelationalSyncAbleStorage::GetCloudDataNext(ContinueToken &continueStmtToken if (!token->CheckValid()) { return -E_INVALID_ARGS; } - if (transactionHandle_ == nullptr) { - LOGE("the transaction has not been started, release the token"); + int errCode = E_OK; + auto *handle = GetHandleExpectTransaction(false, errCode); + if (handle == nullptr) { + LOGE("Invalid handle, release the token, %d", errCode); ReleaseCloudDataToken(continueStmtToken); return -E_INVALID_DB; } cloudDataResult.isShared = IsSharedTable(cloudDataResult.tableName); auto config = GetCloudSyncConfig(); - transactionHandle_->SetUploadConfig(config.maxUploadCount, config.maxUploadSize); - int errCode = transactionHandle_->GetSyncCloudData(uploadRecorder_, cloudDataResult, *token); + handle->SetUploadConfig(config.maxUploadCount, config.maxUploadSize); + errCode = handle->GetSyncCloudData(uploadRecorder_, cloudDataResult, *token); LOGI("mode:%d upload data, ins:%zu, upd:%zu, del:%zu, lock:%zu", cloudDataResult.mode, cloudDataResult.insData.extend.size(), cloudDataResult.updData.extend.size(), cloudDataResult.delData.extend.size(), cloudDataResult.lockData.extend.size()); + if (transactionHandle_ == nullptr) { + ReleaseHandle(handle); + } if (errCode != -E_UNFINISHED) { delete token; token = nullptr; @@ -1469,7 +1481,7 @@ void RelationalSyncAbleStorage::EraseDataChangeCallback(uint64_t connectionId) auto it = dataChangeCallbackMap_.find(connectionId); if (it != dataChangeCallbackMap_.end()) { dataChangeCallbackMap_.erase(it); - LOGI("erase all observer for this delegate."); + LOGI("erase all observer, %" PRIu64, connectionId); } }, nullptr, &dataChangeCallbackMap_); ADAPTER_WAIT(handle); @@ -1980,229 +1992,5 @@ int RelationalSyncAbleStorage::ClearUnLockingNoNeedCompensated() ReleaseHandle(handle); return errCode; } - -int RelationalSyncAbleStorage::GetCloudTableWithoutShared(std::vector &tables) -{ - const auto tableInfos = GetSchemaInfo().GetTables(); - for (const auto &[tableName, info] : tableInfos) { - if (info.GetSharedTableMark()) { - continue; - } - TableSchema schema; - int errCode = GetCloudTableSchema(tableName, schema); - if (errCode == -E_NOT_FOUND) { - continue; - } - if (errCode != E_OK) { - LOGW("[RDBStorage] Get cloud table failed %d", errCode); - return errCode; - } - tables.push_back(schema); - } - return E_OK; -} - -int RelationalSyncAbleStorage::GetCompensatedSyncQueryInner(SQLiteSingleVerRelationalStorageExecutor *handle, - const std::vector &tables, std::vector &syncQuery, bool isQueryDownloadRecords) -{ - int errCode = E_OK; - errCode = handle->StartTransaction(TransactType::IMMEDIATE); - if (errCode != E_OK) { - return errCode; - } - for (const auto &table : tables) { - if (!CheckTableSupportCompensatedSync(table)) { - continue; - } - - std::vector syncDataPk; - errCode = handle->GetWaitCompensatedSyncDataPk(table, syncDataPk, isQueryDownloadRecords); - if (errCode != E_OK) { - LOGW("[RDBStorageEngine] Get wait compensated sync data failed, continue! errCode=%d", errCode); - errCode = E_OK; - continue; - } - if (syncDataPk.empty()) { - // no data need to compensated sync - continue; - } - errCode = CloudStorageUtils::GetSyncQueryByPk(table.name, syncDataPk, false, syncQuery); - if (errCode != E_OK) { - LOGW("[RDBStorageEngine] Get compensated sync query happen error, ignore it! errCode = %d", errCode); - errCode = E_OK; - continue; - } - } - if (errCode == E_OK) { - errCode = handle->Commit(); - if (errCode != E_OK) { - LOGE("[RDBStorageEngine] commit failed %d when get compensated sync query", errCode); - } - } else { - int ret = handle->Rollback(); - if (ret != E_OK) { - LOGW("[RDBStorageEngine] rollback failed %d when get compensated sync query", ret); - } - } - return errCode; -} - -int RelationalSyncAbleStorage::CreateTempSyncTriggerInner(SQLiteSingleVerRelationalStorageExecutor *handle, - const std::string &tableName, bool flag) -{ - TrackerTable trackerTable = storageEngine_->GetTrackerSchema().GetTrackerTable(tableName); - if (trackerTable.IsEmpty()) { - trackerTable.SetTableName(tableName); - } - return handle->CreateTempSyncTrigger(trackerTable, flag); -} - -bool RelationalSyncAbleStorage::CheckTableSupportCompensatedSync(const TableSchema &table) -{ - auto it = std::find_if(table.fields.begin(), table.fields.end(), [](const auto &field) { - return field.primary && (field.type == TYPE_INDEX || field.type == TYPE_INDEX || - field.type == TYPE_INDEX); - }); - if (it != table.fields.end()) { - LOGI("[RDBStorageEngine] Table contain not support pk field type, ignored"); - return false; - } - // check whether reference exist - std::map> tableReference; - int errCode = RelationalSyncAbleStorage::GetTableReference(table.name, tableReference); - if (errCode != E_OK) { - LOGW("[RDBStorageEngine] Get table reference failed! errCode = %d", errCode); - return false; - } - if (!tableReference.empty()) { - LOGI("[RDBStorageEngine] current table exist reference property"); - return false; - } - return true; -} - -int RelationalSyncAbleStorage::MarkFlagAsConsistent(const std::string &tableName, const DownloadData &downloadData, - const std::set &gidFilters) -{ - if (transactionHandle_ == nullptr) { - LOGE("the transaction has not been started"); - return -E_INVALID_DB; - } - int errCode = transactionHandle_->MarkFlagAsConsistent(tableName, downloadData, gidFilters); - if (errCode != E_OK) { - LOGE("[RelationalSyncAbleStorage] mark flag as consistent failed.%d", errCode); - } - return errCode; -} - -CloudSyncConfig RelationalSyncAbleStorage::GetCloudSyncConfig() const -{ - std::lock_guard autoLock(configMutex_); - return cloudSyncConfig_; -} - -void RelationalSyncAbleStorage::SetCloudSyncConfig(const CloudSyncConfig &config) -{ - std::lock_guard autoLock(configMutex_); - cloudSyncConfig_ = config; -} - -bool RelationalSyncAbleStorage::IsTableExistReference(const std::string &table) -{ - // check whether reference exist - std::map> tableReference; - int errCode = RelationalSyncAbleStorage::GetTableReference(table, tableReference); - if (errCode != E_OK) { - LOGW("[RDBStorageEngine] Get table reference failed! errCode = %d", errCode); - return false; - } - return !tableReference.empty(); -} - -bool RelationalSyncAbleStorage::IsTableExistReferenceOrReferenceBy(const std::string &table) -{ - // check whether reference or reference by exist - if (storageEngine_ == nullptr) { - LOGE("[IsTableExistReferenceOrReferenceBy] storage is null when get reference gid"); - return false; - } - RelationalSchemaObject schema = storageEngine_->GetSchema(); - auto referenceProperty = schema.GetReferenceProperty(); - if (referenceProperty.empty()) { - return false; - } - auto [sourceTableName, errCode] = GetSourceTableName(table); - if (errCode != E_OK) { - return false; - } - for (const auto &property : referenceProperty) { - if (DBCommon::CaseInsensitiveCompare(property.sourceTableName, sourceTableName) || - DBCommon::CaseInsensitiveCompare(property.targetTableName, sourceTableName)) { - return true; - } - } - return false; -} - -void RelationalSyncAbleStorage::ReleaseUploadRecord(const std::string &tableName, const CloudWaterType &type, - Timestamp localMark) -{ - uploadRecorder_.ReleaseUploadRecord(tableName, type, localMark); -} - -int RelationalSyncAbleStorage::ReviseLocalModTime(const std::string &tableName, - const std::vector &revisedData) -{ - if (storageEngine_ == nullptr) { - LOGE("[ReviseLocalModTime] Storage is null"); - return -E_INVALID_DB; - } - int errCode = E_OK; - auto writeHandle = static_cast( - storageEngine_->FindExecutor(true, OperatePerm::NORMAL_PERM, errCode)); - if (writeHandle == nullptr) { - LOGE("[ReviseLocalModTime] Get write handle fail: %d", errCode); - return errCode; - } - errCode = writeHandle->StartTransaction(TransactType::IMMEDIATE); - if (errCode != E_OK) { - LOGE("[ReviseLocalModTime] Start Transaction fail: %d", errCode); - ReleaseHandle(writeHandle); - return errCode; - } - errCode = writeHandle->ReviseLocalModTime(tableName, revisedData); - if (errCode != E_OK) { - LOGE("[ReviseLocalModTime] Revise local modify time fail: %d", errCode); - writeHandle->Rollback(); - ReleaseHandle(writeHandle); - return errCode; - } - errCode = writeHandle->Commit(); - ReleaseHandle(writeHandle); - return errCode; -} - -int RelationalSyncAbleStorage::GetCursor(const std::string &tableName, uint64_t &cursor) -{ - if (transactionHandle_ == nullptr) { - LOGE("[RelationalSyncAbleStorage] the transaction has not been started"); - return -E_INVALID_DB; - } - return transactionHandle_->GetCursor(tableName, cursor); -} - -int RelationalSyncAbleStorage::GetLocalDataCount(const std::string &tableName, int &dataCount, - int &logicDeleteDataCount) -{ - int errCode = E_OK; - auto *handle = GetHandle(false, errCode); - if (handle == nullptr || errCode != E_OK) { - LOGE("[RelationalSyncAbleStorage] Get handle failed when get local data count: %d", errCode); - return errCode; - } - errCode = handle->GetLocalDataCount(tableName, dataCount, logicDeleteDataCount); - ReleaseHandle(handle); - return errCode; -} } #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage_extend.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage_extend.cpp index 4e98a047c624951213e6e99e231bbda619826e46..cc9704687c228866a53f16c48037b62b92ef51c6 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage_extend.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage_extend.cpp @@ -181,68 +181,61 @@ int RelationalSyncAbleStorage::FillCloudAssetForAsyncDownload(const std::string LOGE("[RelationalSyncAbleStorage]storage is null when fill asset for async download"); return -E_INVALID_DB; } - int errCode = E_OK; - auto *handle = GetHandle(true, errCode); - if (handle == nullptr) { - LOGE("executor is null when fill asset for async download."); - return errCode; + if (asyncDownloadTransactionHandle_ == nullptr) { + LOGE("the transaction has not been started when fill asset for async download."); + return -E_INVALID_DB; } TableSchema tableSchema; - errCode = GetCloudTableSchema(tableName, tableSchema); + int errCode = GetCloudTableSchema(tableName, tableSchema); if (errCode != E_OK) { - ReleaseHandle(handle); - LOGE("Get cloud schema failed when fill cloud asset, %d, tableName:%s, length:%zu", - errCode, DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size()); + LOGE("Get cloud schema failed when fill cloud asset, %d", errCode); return errCode; } uint64_t currCursor = DBConstant::INVALID_CURSOR; - errCode = handle->FillCloudAssetForDownload(tableSchema, asset, isDownloadSuccess, currCursor); + errCode = asyncDownloadTransactionHandle_->FillCloudAssetForDownload( + tableSchema, asset, isDownloadSuccess, currCursor); if (errCode != E_OK) { - LOGE("fill cloud asset for download failed:%d, tableName:%s, length:%zu", - errCode, DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size()); + LOGE("fill cloud asset for async download failed.%d", errCode); } - SaveCursorChange(tableName, currCursor); - ReleaseHandle(handle); return errCode; } int RelationalSyncAbleStorage::UpdateRecordFlagForAsyncDownload(const std::string &tableName, bool recordConflict, const LogInfo &logInfo) { - int errCode = E_OK; - auto *handle = GetHandle(true, errCode); - if (handle == nullptr) { - LOGE("executor is null when update flag for async download."); + if (asyncDownloadTransactionHandle_ == nullptr) { + LOGE("[RelationalSyncAbleStorage] the transaction has not been started"); + return -E_INVALID_DB; + } + TableSchema tableSchema; + GetCloudTableSchema(tableName, tableSchema); + std::vector assets; + int errCode = asyncDownloadTransactionHandle_->GetDownloadAssetRecordsByGid(tableSchema, logInfo.cloudGid, assets); + if (errCode != E_OK) { + LOGE("[RelationalSyncAbleStorage] get download asset by gid %s failed %d", logInfo.cloudGid.c_str(), errCode); return errCode; } + bool isInconsistency = !assets.empty(); UpdateRecordFlagStruct updateRecordFlag = { .tableName = tableName, .isRecordConflict = recordConflict, - .isInconsistency = false + .isInconsistency = isInconsistency }; std::string sql = CloudStorageUtils::GetUpdateRecordFlagSql(updateRecordFlag, logInfo); - errCode = handle->UpdateRecordFlag(tableName, sql, logInfo); - if (errCode != E_OK) { - LOGE("update flag for async download failed:%d, tableName:%s, length:%zu", - errCode, DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size()); - } - ReleaseHandle(handle); - return errCode; + return asyncDownloadTransactionHandle_->UpdateRecordFlag(tableName, sql, logInfo); } int RelationalSyncAbleStorage::SetLogTriggerStatusForAsyncDownload(bool status) { int errCode = E_OK; - auto *handle = GetHandle(false, errCode); + auto *handle = GetHandleExpectTransactionForAsyncDownload(false, errCode); if (handle == nullptr) { - LOGE("executor is null when set trigger status for async download."); return errCode; } errCode = handle->SetLogTriggerStatus(status); - if (errCode != E_OK) { - LOGE("set trigger status for async download failed:%d"); + if (asyncDownloadTransactionHandle_ == nullptr) { + ReleaseHandle(handle); } - ReleaseHandle(handle); return errCode; } @@ -330,5 +323,314 @@ bool RelationalSyncAbleStorage::IsSetDistributedSchema(const std::string &tableN } return true; } + +int RelationalSyncAbleStorage::CommitForAsyncDownload() +{ + std::unique_lock lock(asyncDownloadtransactionMutex_); + if (asyncDownloadTransactionHandle_ == nullptr) { + LOGE("relation database is null or the transaction has not been started"); + return -E_INVALID_DB; + } + int errCode = asyncDownloadTransactionHandle_->Commit(); + ReleaseHandle(asyncDownloadTransactionHandle_); + asyncDownloadTransactionHandle_ = nullptr; + LOGD("connection commit transaction!"); + return errCode; +} + +int RelationalSyncAbleStorage::RollbackForAsyncDownload() +{ + std::unique_lock lock(asyncDownloadtransactionMutex_); + if (asyncDownloadTransactionHandle_ == nullptr) { + LOGE("Invalid handle for rollback or the transaction has not been started."); + return -E_INVALID_DB; + } + + int errCode = asyncDownloadTransactionHandle_->Rollback(); + ReleaseHandle(asyncDownloadTransactionHandle_); + asyncDownloadTransactionHandle_ = nullptr; + LOGI("connection rollback transaction!"); + return errCode; +} + +SQLiteSingleVerRelationalStorageExecutor *RelationalSyncAbleStorage::GetHandleExpectTransactionForAsyncDownload( + bool isWrite, int &errCode, OperatePerm perm) const +{ + if (storageEngine_ == nullptr) { + errCode = -E_INVALID_DB; + return nullptr; + } + if (asyncDownloadTransactionHandle_ != nullptr) { + return asyncDownloadTransactionHandle_; + } + auto handle = static_cast( + storageEngine_->FindExecutor(isWrite, perm, errCode)); + if (errCode != E_OK) { + ReleaseHandle(handle); + handle = nullptr; + } + return handle; +} + +int RelationalSyncAbleStorage::StartTransactionForAsyncDownload(TransactType type) +{ + if (storageEngine_ == nullptr) { + return -E_INVALID_DB; + } + std::unique_lock lock(asyncDownloadtransactionMutex_); + if (asyncDownloadTransactionHandle_ != nullptr) { + LOGD("async download transaction started already."); + return -E_TRANSACT_STATE; + } + int errCode = E_OK; + auto *handle = static_cast( + storageEngine_->FindExecutor(type == TransactType::IMMEDIATE, OperatePerm::NORMAL_PERM, errCode)); + if (handle == nullptr) { + ReleaseHandle(handle); + return errCode; + } + errCode = handle->StartTransaction(type); + if (errCode != E_OK) { + ReleaseHandle(handle); + return errCode; + } + asyncDownloadTransactionHandle_ = handle; + return errCode; +} + +int RelationalSyncAbleStorage::GetCloudTableWithoutShared(std::vector &tables) +{ + const auto tableInfos = GetSchemaInfo().GetTables(); + for (const auto &[tableName, info] : tableInfos) { + if (info.GetSharedTableMark()) { + continue; + } + TableSchema schema; + int errCode = GetCloudTableSchema(tableName, schema); + if (errCode == -E_NOT_FOUND) { + continue; + } + if (errCode != E_OK) { + LOGW("[RDBStorage] Get cloud table failed %d", errCode); + return errCode; + } + tables.push_back(schema); + } + return E_OK; +} + +int RelationalSyncAbleStorage::GetCompensatedSyncQueryInner(SQLiteSingleVerRelationalStorageExecutor *handle, + const std::vector &tables, std::vector &syncQuery, bool isQueryDownloadRecords) +{ + int errCode = E_OK; + errCode = handle->StartTransaction(TransactType::IMMEDIATE); + if (errCode != E_OK) { + return errCode; + } + for (const auto &table : tables) { + if (!CheckTableSupportCompensatedSync(table)) { + continue; + } + + std::vector syncDataPk; + errCode = handle->GetWaitCompensatedSyncDataPk(table, syncDataPk, isQueryDownloadRecords); + if (errCode != E_OK) { + LOGW("[RDBStorageEngine] Get wait compensated sync data failed, continue! errCode=%d", errCode); + errCode = E_OK; + continue; + } + if (syncDataPk.empty()) { + // no data need to compensated sync + continue; + } + errCode = CloudStorageUtils::GetSyncQueryByPk(table.name, syncDataPk, false, syncQuery); + if (errCode != E_OK) { + LOGW("[RDBStorageEngine] Get compensated sync query happen error, ignore it! errCode = %d", errCode); + errCode = E_OK; + continue; + } + } + if (errCode == E_OK) { + errCode = handle->Commit(); + if (errCode != E_OK) { + LOGE("[RDBStorageEngine] commit failed %d when get compensated sync query", errCode); + } + } else { + int ret = handle->Rollback(); + if (ret != E_OK) { + LOGW("[RDBStorageEngine] rollback failed %d when get compensated sync query", ret); + } + } + return errCode; +} + +int RelationalSyncAbleStorage::CreateTempSyncTriggerInner(SQLiteSingleVerRelationalStorageExecutor *handle, + const std::string &tableName, bool flag) +{ + TrackerTable trackerTable = storageEngine_->GetTrackerSchema().GetTrackerTable(tableName); + if (trackerTable.IsEmpty()) { + trackerTable.SetTableName(tableName); + } + return handle->CreateTempSyncTrigger(trackerTable, flag); +} + +bool RelationalSyncAbleStorage::CheckTableSupportCompensatedSync(const TableSchema &table) +{ + auto it = std::find_if(table.fields.begin(), table.fields.end(), [](const auto &field) { + return field.primary && (field.type == TYPE_INDEX || field.type == TYPE_INDEX || + field.type == TYPE_INDEX); + }); + if (it != table.fields.end()) { + LOGI("[RDBStorageEngine] Table contain not support pk field type, ignored"); + return false; + } + // check whether reference exist + std::map> tableReference; + int errCode = RelationalSyncAbleStorage::GetTableReference(table.name, tableReference); + if (errCode != E_OK) { + LOGW("[RDBStorageEngine] Get table reference failed! errCode = %d", errCode); + return false; + } + if (!tableReference.empty()) { + LOGI("[RDBStorageEngine] current table exist reference property"); + return false; + } + return true; +} + +int RelationalSyncAbleStorage::MarkFlagAsConsistent(const std::string &tableName, const DownloadData &downloadData, + const std::set &gidFilters) +{ + if (transactionHandle_ == nullptr) { + LOGE("the transaction has not been started"); + return -E_INVALID_DB; + } + int errCode = transactionHandle_->MarkFlagAsConsistent(tableName, downloadData, gidFilters); + if (errCode != E_OK) { + LOGE("[RelationalSyncAbleStorage] mark flag as consistent failed.%d", errCode); + } + return errCode; +} + +CloudSyncConfig RelationalSyncAbleStorage::GetCloudSyncConfig() const +{ + std::lock_guard autoLock(configMutex_); + return cloudSyncConfig_; +} + +void RelationalSyncAbleStorage::SetCloudSyncConfig(const CloudSyncConfig &config) +{ + std::lock_guard autoLock(configMutex_); + cloudSyncConfig_ = config; + LOGI("[RelationalSyncAbleStorage] SetCloudSyncConfig value:[%" PRId32 ", %" PRId32 ", %" PRId32 ", %d]", + cloudSyncConfig_.maxUploadCount, cloudSyncConfig_.maxUploadSize, + cloudSyncConfig_.maxRetryConflictTimes, cloudSyncConfig_.isSupportEncrypt); +} + +bool RelationalSyncAbleStorage::IsTableExistReference(const std::string &table) +{ + // check whether reference exist + std::map> tableReference; + int errCode = RelationalSyncAbleStorage::GetTableReference(table, tableReference); + if (errCode != E_OK) { + LOGW("[RDBStorageEngine] Get table reference failed! errCode = %d", errCode); + return false; + } + return !tableReference.empty(); +} + +bool RelationalSyncAbleStorage::IsTableExistReferenceOrReferenceBy(const std::string &table) +{ + // check whether reference or reference by exist + if (storageEngine_ == nullptr) { + LOGE("[IsTableExistReferenceOrReferenceBy] storage is null when get reference gid"); + return false; + } + RelationalSchemaObject schema = storageEngine_->GetSchema(); + auto referenceProperty = schema.GetReferenceProperty(); + if (referenceProperty.empty()) { + return false; + } + auto [sourceTableName, errCode] = GetSourceTableName(table); + if (errCode != E_OK) { + return false; + } + for (const auto &property : referenceProperty) { + if (DBCommon::CaseInsensitiveCompare(property.sourceTableName, sourceTableName) || + DBCommon::CaseInsensitiveCompare(property.targetTableName, sourceTableName)) { + return true; + } + } + return false; +} + +void RelationalSyncAbleStorage::ReleaseUploadRecord(const std::string &tableName, const CloudWaterType &type, + Timestamp localMark) +{ + uploadRecorder_.ReleaseUploadRecord(tableName, type, localMark); +} + +int RelationalSyncAbleStorage::ReviseLocalModTime(const std::string &tableName, + const std::vector &revisedData) +{ + if (storageEngine_ == nullptr) { + LOGE("[ReviseLocalModTime] Storage is null"); + return -E_INVALID_DB; + } + int errCode = E_OK; + auto writeHandle = static_cast( + storageEngine_->FindExecutor(true, OperatePerm::NORMAL_PERM, errCode)); + if (writeHandle == nullptr) { + LOGE("[ReviseLocalModTime] Get write handle fail: %d", errCode); + return errCode; + } + errCode = writeHandle->StartTransaction(TransactType::IMMEDIATE); + if (errCode != E_OK) { + LOGE("[ReviseLocalModTime] Start Transaction fail: %d", errCode); + ReleaseHandle(writeHandle); + return errCode; + } + errCode = writeHandle->ReviseLocalModTime(tableName, revisedData); + if (errCode != E_OK) { + LOGE("[ReviseLocalModTime] Revise local modify time fail: %d", errCode); + writeHandle->Rollback(); + ReleaseHandle(writeHandle); + return errCode; + } + errCode = writeHandle->Commit(); + ReleaseHandle(writeHandle); + return errCode; +} + +int RelationalSyncAbleStorage::GetCursor(const std::string &tableName, uint64_t &cursor) +{ + if (transactionHandle_ == nullptr) { + LOGE("[RelationalSyncAbleStorage] the transaction has not been started"); + return -E_INVALID_DB; + } + return transactionHandle_->GetCursor(tableName, cursor); +} + +int RelationalSyncAbleStorage::GetLocalDataCount(const std::string &tableName, int &dataCount, + int &logicDeleteDataCount) +{ + int errCode = E_OK; + auto *handle = GetHandle(false, errCode); + if (handle == nullptr || errCode != E_OK) { + LOGE("[RelationalSyncAbleStorage] Get handle failed when get local data count: %d", errCode); + return errCode; + } + errCode = handle->GetLocalDataCount(tableName, dataCount, logicDeleteDataCount); + ReleaseHandle(handle); + return errCode; +} + +int RelationalSyncAbleStorage::GetCompressionOption(bool &needCompressOnSync, uint8_t &compressionRate) const +{ + needCompressOnSync = storageEngine_->GetRelationalProperties().GetBoolProp(DBProperties::COMPRESS_ON_SYNC, false); + compressionRate = storageEngine_->GetRelationalProperties().GetIntProp(DBProperties::COMPRESSION_RATE, + DBConstant::DEFAULT_COMPTRESS_RATE); + return E_OK; +} } #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store.cpp index b19356bfd04d047aee58102ea8ecc9e11db5506a..0ef50e2974738081549877fcdc9dfde9ec09d06a 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store.cpp @@ -52,7 +52,7 @@ int SingleVerNaturalStore::RemoveKvDB(const KvDBProperties &properties) std::string storeDir; GenericKvDB::GetStoreDirectory(properties, KvDBProperties::SINGLE_VER_TYPE_SQLITE, storeDir, storeOnlyDir); - const std::vector> dbDir { + const std::vector> dbDir { { DBConstant::MAINDB_DIR, DBConstant::SINGLE_VER_DATA_STORE }, { DBConstant::METADB_DIR, DBConstant::SINGLE_VER_META_STORE }, { DBConstant::CACHEDB_DIR, DBConstant::SINGLE_VER_CACHE_STORE } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/collaboration_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/collaboration_log_table_manager.cpp index fdb5cab8537a433e2d73194f3cf01aa8a202aeb5..9176bf6c7146795a6575fd25ee33c224fca8d792 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/collaboration_log_table_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/collaboration_log_table_manager.cpp @@ -127,8 +127,9 @@ std::string CollaborationLogTableManager::GetPrimaryKeySql(const TableInfo &tabl void CollaborationLogTableManager::GetIndexSql(const TableInfo &table, std::vector &schema) { SqliteLogTableManager::GetIndexSql(table, schema); - std::string dataKeyIndex = "CREATE INDEX IF NOT EXISTS " + std::string(DBConstant::RELATIONAL_PREFIX) + - "datakey_index ON " + GetLogTableName(table) + "(data_key);"; + const std::string tableName = GetLogTableName(table); + std::string dataKeyIndex = "CREATE INDEX IF NOT EXISTS " + + tableName + "_datakey_index ON " + tableName + "(data_key);"; schema.emplace_back(dataKeyIndex); } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/log_table_manager_factory.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/log_table_manager_factory.cpp index a6f613f1b955fca36855b3cbe2f9ed7533807b2b..6967950aab1e73a66d4e41b5feb9447fd1be422c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/log_table_manager_factory.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/log_table_manager_factory.cpp @@ -16,19 +16,22 @@ #include "log_table_manager_factory.h" #include "cloud_sync_log_table_manager.h" #include "collaboration_log_table_manager.h" +#include "device_tracker_log_table_manager.h" #include "split_device_log_table_manager.h" namespace DistributedDB { -std::unique_ptr LogTableManagerFactory::GetTableManager(DistributedTableMode mode, - TableSyncType syncType) +std::unique_ptr LogTableManagerFactory::GetTableManager(const TableInfo &tableInfo, + DistributedTableMode mode, TableSyncType syncType) { if (syncType == CLOUD_COOPERATION) { return std::make_unique(); - } else { - if (mode == DistributedTableMode::COLLABORATION) { - return std::make_unique(); - } + } + if (!tableInfo.GetTrackerTable().IsEmpty()) { + return std::make_unique(); + } + if (mode == DistributedTableMode::SPLIT_BY_DEVICE) { return std::make_unique(); } + return std::make_unique(); } } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/log_table_manager_factory.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/log_table_manager_factory.h index b31f9d508ad5e186774eb301005ec540a6d03ea1..623f7852b16c8ed57ffa7739647e8a2505b6a259 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/log_table_manager_factory.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/log_table_manager_factory.h @@ -24,7 +24,8 @@ namespace DistributedDB { class LogTableManagerFactory final { public: - static std::unique_ptr GetTableManager(DistributedTableMode mode, TableSyncType syncType); + static std::unique_ptr GetTableManager(const TableInfo &tableInfo, + DistributedTableMode mode, TableSyncType syncType); private: LogTableManagerFactory() {} diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.cpp index 66c55e4b06ce1e41359220042f598d0fa73382c2..b53a3ef8cceb96261a3dc79818f328eac2895aff 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.cpp @@ -76,7 +76,8 @@ std::string SimpleTrackerLogTableManager::GetInsertTrigger(const TableInfo &tabl insertTrigger += CalcPrimaryKeyHash("NEW.", table, identity) + ", '', "; insertTrigger += table.GetTrackerTable().GetAssignValSql(); insertTrigger += ", " + CloudStorageUtils::GetSelectIncCursorSql(tableName) + ", '', '', 0);\n"; - insertTrigger += "SELECT client_observer('" + tableName + "', NEW._rowid_, 0, 1"; + insertTrigger += "SELECT client_observer('" + tableName + "', NEW._rowid_, 0, "; + insertTrigger += table.GetTrackerTable().GetOnChangeType(); insertTrigger += ");\n"; insertTrigger += "END;"; return insertTrigger; @@ -103,7 +104,8 @@ std::string SimpleTrackerLogTableManager::GetUpdateTrigger(const TableInfo &tabl updateTrigger += table.GetTrackerTable().GetExtendAssignValSql(); updateTrigger += table.GetTrackerTable().GetDiffIncCursorSql(tableName); updateTrigger += " WHERE data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";\n"; - updateTrigger += "SELECT client_observer('" + tableName + "', OLD." + std::string(DBConstant::SQLITE_INNER_ROWID); + updateTrigger += "SELECT client_observer('" + tableName + "', OLD." + + std::string(DBConstant::SQLITE_INNER_ROWID); updateTrigger += ", 1, "; updateTrigger += table.GetTrackerTable().GetDiffTrackerValSql(); updateTrigger += ");"; @@ -131,7 +133,7 @@ std::string SimpleTrackerLogTableManager::GetDeleteTrigger(const TableInfo &tabl deleteTrigger += " WHERE data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";"; // -1 is rowid when data is deleted, 2 means change type is delete(ClientChangeType) deleteTrigger += "SELECT client_observer('" + tableName + "', -1, 2, "; - deleteTrigger += table.GetTrackerTable().IsEmpty() ? "0" : "1"; + deleteTrigger += table.GetTrackerTable().IsEmpty() ? "0" : table.GetTrackerTable().GetOnChangeType(); deleteTrigger += ");\n"; deleteTrigger += "END;"; return deleteTrigger; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.h index 4460a866672b81388bac1d6f5f0053d44509faf0..58626799be0c09d8b348d5c3b8b254ad48faceb9 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.h @@ -27,7 +27,6 @@ public: // The parameter "references" is "", "NEW." or "OLD.". "identity" is a hash string that identifies a device. std::string CalcPrimaryKeyHash(const std::string &references, const TableInfo &table, const std::string &identity) override; - private: void GetIndexSql(const TableInfo &table, std::vector &schema) override; std::string GetPrimaryKeySql(const TableInfo &table) override; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp index 9c25c59b2ad67485bfafb258109a39d6fbb254c9..5f6d1d8d489098805a63028d6dcb355e47d5c7af 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp @@ -128,7 +128,7 @@ int SqliteRelationalDatabaseUpgrader::UpgradeTrigger(const std::string &logTable TableInfo tableInfo = table.second; tableInfo.SetTrackerTable(trackerSchemaObj.GetTrackerTable(table.first)); tableInfo.SetDistributedTable(schemaObj.GetDistributedTable(table.first)); - auto manager = LogTableManagerFactory::GetTableManager(mode, tableInfo.GetTableSyncType()); + auto manager = LogTableManagerFactory::GetTableManager(tableInfo, mode, tableInfo.GetTableSyncType()); errCode = manager->AddRelationalLogTableTrigger(db_, tableInfo, ""); if (errCode != E_OK) { LOGE("[Relational][Upgrade] recreate distributed trigger failed. err:%d", errCode); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp index 5f5c320fde2675f8998817d9be87fd1637ee4266..070deaf85c45c5251d3cd0ea5ec5cbb8bb3ec923 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp @@ -22,6 +22,7 @@ #include "db_errno.h" #include "log_print.h" #include "db_types.h" +#include "res_finalizer.h" #include "sqlite_log_table_manager.h" #include "sqlite_relational_utils.h" #include "sqlite_relational_store_connection.h" @@ -224,7 +225,8 @@ int SQLiteRelationalStore::SaveTableModeToMeta(DistributedTableMode mode) int SQLiteRelationalStore::SaveLogTableVersionToMeta() { LOGD("save log table version to meta table, version: %s", DBConstant::LOG_TABLE_VERSION_CURRENT); - const Key logVersionKey(DBConstant::LOG_TABLE_VERSION_KEY.begin(), DBConstant::LOG_TABLE_VERSION_KEY.end()); + const Key logVersionKey(DBConstant::LOG_TABLE_VERSION_KEY, + DBConstant::LOG_TABLE_VERSION_KEY + strlen(DBConstant::LOG_TABLE_VERSION_KEY)); Value logVersion; int errCode = storageEngine_->GetMetaData(logVersionKey, logVersion); if (errCode != E_OK && errCode != -E_NOT_FOUND) { @@ -256,7 +258,7 @@ int SQLiteRelationalStore::CleanDistributedDeviceTable() std::string deviceHash; std::string tableName; DBCommon::GetDeviceFromName(deviceTableName, deviceHash, tableName); - syncAbleEngine_->EraseDeviceWaterMark(deviceHash, false, tableName); + errCode = syncAbleEngine_->EraseDeviceWaterMark(deviceHash, false, tableName); if (errCode != E_OK) { LOGE("Erase water mark failed:%d", errCode); return errCode; @@ -359,7 +361,7 @@ void SQLiteRelationalStore::ReleaseHandle(SQLiteSingleVerRelationalStorageExecut } } -int SQLiteRelationalStore::Sync(const ISyncer::SyncParma &syncParam, uint64_t connectionId) +int SQLiteRelationalStore::Sync(const ISyncer::SyncParam &syncParam, uint64_t connectionId) { return syncAbleEngine_->Sync(syncParam, connectionId); } @@ -448,7 +450,7 @@ int SQLiteRelationalStore::CreateDistributedTable(const std::string &tableName, } } - auto mode = sqliteStorageEngine_->GetProperties().GetDistributedTableMode(); + auto mode = sqliteStorageEngine_->GetRelationalProperties().GetDistributedTableMode(); std::string localIdentity; // collaboration mode need local identify if (mode == DistributedTableMode::COLLABORATION) { int errCode = syncAbleEngine_->GetLocalIdentity(localIdentity); @@ -461,6 +463,8 @@ int SQLiteRelationalStore::CreateDistributedTable(const std::string &tableName, schemaChanged, syncType, trackerSchemaChanged); if (errCode != E_OK) { LOGE("Create distributed table failed. %d", errCode); + } else { + CleanDirtyLogIfNeed(tableName); } if (schemaChanged) { LOGD("Notify schema changed."); @@ -549,7 +553,7 @@ int SQLiteRelationalStore::ClearCloudWatermark(const std::set &tabl int SQLiteRelationalStore::RemoveDeviceData() { - auto mode = static_cast(sqliteStorageEngine_->GetProperties().GetIntProp( + auto mode = static_cast(sqliteStorageEngine_->GetRelationalProperties().GetIntProp( RelationalDBProperties::DISTRIBUTED_TABLE_MODE, static_cast(DistributedTableMode::SPLIT_BY_DEVICE))); if (mode == DistributedTableMode::COLLABORATION) { LOGE("Not support remove all device data in collaboration mode."); @@ -600,7 +604,7 @@ int SQLiteRelationalStore::RemoveDeviceData() int SQLiteRelationalStore::RemoveDeviceData(const std::string &device, const std::string &tableName) { - auto mode = static_cast(sqliteStorageEngine_->GetProperties().GetIntProp( + auto mode = static_cast(sqliteStorageEngine_->GetRelationalProperties().GetIntProp( RelationalDBProperties::DISTRIBUTED_TABLE_MODE, static_cast(DistributedTableMode::SPLIT_BY_DEVICE))); if (mode == DistributedTableMode::COLLABORATION) { LOGE("Not support remove device data in collaboration mode."); @@ -684,13 +688,15 @@ int SQLiteRelationalStore::StartLifeCycleTimer(const DatabaseLifeCycleNotifier & if (lifeCycleNotifier_) { // normal identifier mode std::string identifier; - if (sqliteStorageEngine_->GetProperties().GetBoolProp(DBProperties::SYNC_DUAL_TUPLE_MODE, false)) { - identifier = sqliteStorageEngine_->GetProperties().GetStringProp( + if (sqliteStorageEngine_->GetRelationalProperties().GetBoolProp( + DBProperties::SYNC_DUAL_TUPLE_MODE, false)) { + identifier = sqliteStorageEngine_->GetRelationalProperties().GetStringProp( DBProperties::DUAL_TUPLE_IDENTIFIER_DATA, ""); } else { - identifier = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::IDENTIFIER_DATA, ""); + identifier = sqliteStorageEngine_->GetRelationalProperties().GetStringProp( + DBProperties::IDENTIFIER_DATA, ""); } - auto userId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::USER_ID, ""); + auto userId = sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::USER_ID, ""); lifeCycleNotifier_(identifier, userId); } return 0; @@ -766,12 +772,12 @@ int SQLiteRelationalStore::ResetLifeCycleTimer() std::string SQLiteRelationalStore::GetStorePath() const { - return sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::DATA_DIR, ""); + return sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::DATA_DIR, ""); } RelationalDBProperties SQLiteRelationalStore::GetProperties() const { - return sqliteStorageEngine_->GetProperties(); + return sqliteStorageEngine_->GetRelationalProperties(); } void SQLiteRelationalStore::StopSync(uint64_t connectionId) @@ -786,10 +792,10 @@ void SQLiteRelationalStore::Dump(int fd) std::string storeId = ""; std::string label = ""; if (sqliteStorageEngine_ != nullptr) { - userId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::USER_ID, ""); - appId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::APP_ID, ""); - storeId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, ""); - label = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::IDENTIFIER_DATA, ""); + userId = sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::USER_ID, ""); + appId = sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::APP_ID, ""); + storeId = sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::STORE_ID, ""); + label = sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::IDENTIFIER_DATA, ""); } label = DBCommon::TransferStringToHex(label); DBDumpHelper::Dump(fd, "\tdb userId = %s, appId = %s, storeId = %s, label = %s\n", userId.c_str(), appId.c_str(), @@ -851,9 +857,9 @@ int SQLiteRelationalStore::EraseAllDeviceWatermark(const std::vectorGetProperties().GetStringProp(DBProperties::USER_ID, ""), - sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::APP_ID, ""), - sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, "") }; + StoreInfo info = { sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::USER_ID, ""), + sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::APP_ID, ""), + sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::STORE_ID, "") }; if (RuntimeContext::GetInstance()->TranslateDeviceId(device, info, devTableName) != E_OK) { devTableName = hashDev; } @@ -1147,7 +1153,7 @@ int SQLiteRelationalStore::Sync(const CloudSyncOption &option, const SyncProcess LOGI("sync mode:%d, pri:%d, comp:%d", option.mode, option.priorityTask, option.compensatedSyncOnly); if (option.compensatedSyncOnly) { CloudSyncer::CloudTaskInfo info = CloudSyncUtils::InitCompensatedSyncTaskInfo(option, onProcess); - info.storeId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, ""); + info.storeId = sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::STORE_ID, ""); cloudSyncer_->GenerateCompensatedSync(info); return E_OK; } @@ -1192,7 +1198,9 @@ int SQLiteRelationalStore::CheckBeforeSync(const CloudSyncOption &option) if (errCode != E_OK && errCode != -E_NOT_SUPPORT) { return -E_SECURITY_OPTION_CHECK_ERROR; } - if (errCode == E_OK && securityOption.securityLabel == S4) { + CloudSyncConfig config = storageEngine_->GetCloudSyncConfig(); + if ((errCode == E_OK) && (securityOption.securityLabel == S4) && (!config.isSupportEncrypt)) { + LOGE("[RelationalStore] The current data does not support synchronization."); return -E_SECURITY_OPTION_CHECK_ERROR; } return E_OK; @@ -1340,7 +1348,7 @@ void SQLiteRelationalStore::FillSyncInfo(const CloudSyncOption &option, const Sy info.users.emplace_back(""); info.lockAction = option.lockAction; info.merge = option.merge; - info.storeId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, ""); + info.storeId = sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::STORE_ID, ""); info.prepareTraceId = option.prepareTraceId; info.asyncDownloadAssets = option.asyncDownloadAssets; } @@ -1359,8 +1367,14 @@ int SQLiteRelationalStore::SetTrackerTable(const TrackerSchema &trackerSchema) auto *handle = GetHandle(true, errCode); if (handle != nullptr) { handle->CheckAndCreateTrigger(tableInfo); + // Try clear historical mismatched log, which usually do not occur and apply to tracker table only. + if (isNoTableInSchema) { + handle->ClearLogOfMismatchedData(trackerSchema.tableName); + } + handle->RecoverNullExtendLog(trackerSchema, tableInfo.GetTrackerTable()); ReleaseHandle(handle); } + CleanDirtyLogIfNeed(trackerSchema.tableName); return E_OK; } errCode = sqliteStorageEngine_->UpdateExtendField(trackerSchema); @@ -1370,7 +1384,11 @@ int SQLiteRelationalStore::SetTrackerTable(const TrackerSchema &trackerSchema) return errCode; } if (isNoTableInSchema) { - return sqliteStorageEngine_->SetTrackerTable(trackerSchema, tableInfo, isFirstCreate); + errCode = sqliteStorageEngine_->SetTrackerTable(trackerSchema, tableInfo, isFirstCreate); + if (errCode == E_OK) { + CleanDirtyLogIfNeed(trackerSchema.tableName); + } + return errCode; } sqliteStorageEngine_->CacheTrackerSchema(trackerSchema); errCode = CreateDistributedTable(trackerSchema.tableName, tableInfo.GetTableSyncType(), true); @@ -1385,22 +1403,27 @@ int SQLiteRelationalStore::SetTrackerTable(const TrackerSchema &trackerSchema) int SQLiteRelationalStore::CheckTrackerTable(const TrackerSchema &trackerSchema, TableInfo &table, bool &isNoTableInSchema, bool &isFirstCreate) { - const RelationalSchemaObject &tracker = sqliteStorageEngine_->GetTrackerSchema(); + const RelationalSchemaObject tracker = sqliteStorageEngine_->GetTrackerSchema(); isFirstCreate = tracker.GetTrackerTable(trackerSchema.tableName).GetTableName().empty(); RelationalSchemaObject localSchema = sqliteStorageEngine_->GetSchema(); table = localSchema.GetTable(trackerSchema.tableName); TrackerTable trackerTable; trackerTable.Init(trackerSchema); int errCode = E_OK; + auto *handle = GetHandle(true, errCode); + if (handle == nullptr) { + return errCode; + } + ResFinalizer finalizer([this, handle]() { + SQLiteSingleVerRelationalStorageExecutor *releaseHandle = handle; + ReleaseHandle(releaseHandle); + }); + bool isOnceDrop = false; + (void)handle->IsTableOnceDropped(trackerSchema.tableName, isOnceDrop); if (table.Empty()) { isNoTableInSchema = true; table.SetTableSyncType(TableSyncType::CLOUD_COOPERATION); - auto *handle = GetHandle(true, errCode); - if (handle == nullptr) { - return errCode; - } errCode = handle->AnalysisTrackerTable(trackerTable, table); - ReleaseHandle(handle); if (errCode != E_OK) { LOGE("[CheckTrackerTable] analysis table schema failed %d.", errCode); return errCode; @@ -1413,7 +1436,8 @@ int SQLiteRelationalStore::CheckTrackerTable(const TrackerSchema &trackerSchema, return errCode; } } - if (!trackerSchema.isForceUpgrade && !tracker.GetTrackerTable(trackerSchema.tableName).IsChanging(trackerSchema)) { + if (!trackerSchema.isForceUpgrade && !tracker.GetTrackerTable(trackerSchema.tableName).IsChanging(trackerSchema) + && !isOnceDrop) { LOGW("[CheckTrackerTable] tracker schema is no change, table[%s [%zu]]", DBCommon::StringMiddleMasking(trackerSchema.tableName).c_str(), trackerSchema.tableName.size()); return -E_IGNORE_DATA; @@ -1430,8 +1454,8 @@ int SQLiteRelationalStore::ExecuteSql(const SqlCondition &condition, std::vector return sqliteStorageEngine_->ExecuteSql(condition, records); } -int SQLiteRelationalStore::CleanWaterMark(SQLiteSingleVerRelationalStorageExecutor *&handle, - std::set &clearWaterMarkTable) +int SQLiteRelationalStore::CleanWaterMarkInner(SQLiteSingleVerRelationalStorageExecutor *&handle, + const std::set &clearWaterMarkTable) { int errCode = E_OK; for (const auto &tableName : clearWaterMarkTable) { @@ -1462,7 +1486,29 @@ int SQLiteRelationalStore::CleanWaterMark(SQLiteSingleVerRelationalStorageExecut return errCode; } -int SQLiteRelationalStore::SetReference(const std::vector &tableReferenceProperty) +std::function SQLiteRelationalStore::CleanWaterMark(const std::set clearWaterMarkTables) +{ + return [this, clearWaterMarkTables]()->int { + int errCode = E_OK; + auto *handle = GetHandle(true, errCode); + if (handle == nullptr) { + LOGE("[SQLiteRelationalStore] get handle failed:%d", errCode); + return errCode; + } + storageEngine_->SetReusedHandle(handle); + errCode = CleanWaterMarkInner(handle, clearWaterMarkTables); + storageEngine_->SetReusedHandle(nullptr); + ReleaseHandle(handle); + if (errCode != E_OK) { + LOGE("[SQLiteRelationalStore] SetReference clear water mark failed, errCode = %d", errCode); + } + LOGI("[SQLiteRelationalStore] SetReference clear water mark success"); + return errCode; + }; +} + +int SQLiteRelationalStore::SetReferenceInner(const std::vector &tableReferenceProperty, + std::set &clearWaterMarkTables) { SQLiteSingleVerRelationalStorageExecutor *handle = nullptr; int errCode = GetHandleAndStartTransaction(handle); @@ -1470,7 +1516,6 @@ int SQLiteRelationalStore::SetReference(const std::vector clearWaterMarkTables; RelationalSchemaObject schema; errCode = sqliteStorageEngine_->SetReference(tableReferenceProperty, handle, clearWaterMarkTables, schema); if (errCode != E_OK && errCode != -E_TABLE_REFERENCE_CHANGED) { @@ -1480,20 +1525,6 @@ int SQLiteRelationalStore::SetReference(const std::vectorSetReusedHandle(handle); - int ret = CleanWaterMark(handle, clearWaterMarkTables); - if (ret != E_OK) { - LOGE("[SQLiteRelationalStore] SetReference failed, errCode = %d", ret); - storageEngine_->SetReusedHandle(nullptr); - (void)handle->Rollback(); - ReleaseHandle(handle); - return ret; - } - storageEngine_->SetReusedHandle(nullptr); - LOGI("[SQLiteRelationalStore] SetReference clear water mark success"); - } - int ret = handle->Commit(); ReleaseHandle(handle); if (ret == E_OK) { @@ -1504,6 +1535,28 @@ int SQLiteRelationalStore::SetReference(const std::vector &tableReferenceProperty) +{ + std::set clearWaterMarkTables; + int errCode = SetReferenceInner(tableReferenceProperty, clearWaterMarkTables); + if (errCode != E_OK && errCode != -E_TABLE_REFERENCE_CHANGED) { + LOGE("[SQLiteRelationalStore] SetReference failed, errCode = %d", errCode); + return errCode; + } + std::function clearWaterMarkFunc = [] { return E_OK; }; + if (!clearWaterMarkTables.empty()) { + clearWaterMarkFunc = CleanWaterMark(clearWaterMarkTables); + } + if (errCode == -E_TABLE_REFERENCE_CHANGED) { + int ret = E_OK; +#ifdef USE_DISTRIBUTEDDB_CLOUD + ret = cloudSyncer_->StopSyncTask(clearWaterMarkFunc); +#endif + return ret != E_OK ? ret : errCode; + } + return E_OK; +} + int SQLiteRelationalStore::InitTrackerSchemaFromMeta() { int errCode = sqliteStorageEngine_->GetOrInitTrackerSchemaFromMeta(); @@ -1730,6 +1783,8 @@ int SQLiteRelationalStore::SetCloudSyncConfig(const CloudSyncConfig &config) return -E_INVALID_DB; } storageEngine_->SetCloudSyncConfig(config); + LOGI("[RelationalStore][SetCloudSyncConfig] value:[%" PRId32 ", %" PRId32 ", %" PRId32 ", %d]", + config.maxUploadCount, config.maxUploadSize, config.maxRetryConflictTimes, config.isSupportEncrypt); return E_OK; } @@ -1739,13 +1794,13 @@ SyncProcess SQLiteRelationalStore::GetCloudTaskStatus(uint64_t taskId) } #endif -int SQLiteRelationalStore::SetDistributedSchema(const DistributedSchema &schema) +int SQLiteRelationalStore::SetDistributedSchema(const DistributedSchema &schema, bool isForceUpgrade) { if (sqliteStorageEngine_ == nullptr || storageEngine_ == nullptr) { LOGE("[RelationalStore] engine was not initialized"); return -E_INVALID_DB; } - auto mode = sqliteStorageEngine_->GetProperties().GetDistributedTableMode(); + auto mode = sqliteStorageEngine_->GetRelationalProperties().GetDistributedTableMode(); std::string localIdentity; // collaboration mode need local identify if (mode == DistributedTableMode::COLLABORATION) { int errCode = syncAbleEngine_->GetLocalIdentity(localIdentity); @@ -1753,7 +1808,7 @@ int SQLiteRelationalStore::SetDistributedSchema(const DistributedSchema &schema) LOGW("Get local identity failed: %d", errCode); } } - auto [errCode, isSchemaChange] = sqliteStorageEngine_->SetDistributedSchema(schema, localIdentity); + auto [errCode, isSchemaChange] = sqliteStorageEngine_->SetDistributedSchema(schema, localIdentity, isForceUpgrade); if (errCode != E_OK) { return errCode; } @@ -1801,7 +1856,7 @@ int SQLiteRelationalStore::SetTableMode(DistributedTableMode tableMode) LOGE("[RelationalStore][SetTableMode] sqliteStorageEngine was not initialized"); return -E_INVALID_DB; } - if (sqliteStorageEngine_->GetProperties().GetDistributedTableMode() != tableMode) { + if (sqliteStorageEngine_->GetRelationalProperties().GetDistributedTableMode() != tableMode) { auto schema = sqliteStorageEngine_->GetSchema(); for (const auto &tableMap : schema.GetTables()) { if (tableMap.second.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { @@ -1811,7 +1866,7 @@ int SQLiteRelationalStore::SetTableMode(DistributedTableMode tableMode) } } } - RelationalDBProperties properties = sqliteStorageEngine_->GetProperties(); + RelationalDBProperties properties = sqliteStorageEngine_->GetRelationalProperties(); properties.SetIntProp(RelationalDBProperties::DISTRIBUTED_TABLE_MODE, static_cast(tableMode)); sqliteStorageEngine_->SetProperties(properties); LOGI("[RelationalStore][SetTableMode] Set table mode to %d successful", static_cast(tableMode)); @@ -1828,6 +1883,11 @@ int SQLiteRelationalStore::OperateDataStatus(uint32_t dataOperator) LOGE("[RelationalStore] sqliteStorageEngine was not initialized when operate data status"); return -E_INVALID_DB; } + if (syncAbleEngine_ == nullptr) { + LOGE("[RelationalStore] syncAbleEngine was not initialized when operate data status"); + return -E_INVALID_DB; + } + auto virtualTime = syncAbleEngine_->GetTimestamp(); auto schema = sqliteStorageEngine_->GetSchema(); std::vector operateTables; for (const auto &tableMap : schema.GetTables()) { @@ -1835,10 +1895,10 @@ int SQLiteRelationalStore::OperateDataStatus(uint32_t dataOperator) operateTables.push_back(tableMap.second.GetTableName()); } } - return OperateDataStatusInner(operateTables); + return OperateDataStatusInner(operateTables, virtualTime); } -int SQLiteRelationalStore::OperateDataStatusInner(const std::vector &tables) const +int SQLiteRelationalStore::OperateDataStatusInner(const std::vector &tables, uint64_t virtualTime) const { int errCode = E_OK; SQLiteSingleVerRelationalStorageExecutor *handle = GetHandle(true, errCode); @@ -1860,7 +1920,7 @@ int SQLiteRelationalStore::OperateDataStatusInner(const std::vector ReleaseHandle(handle); return errCode; } - errCode = SQLiteRelationalUtils::OperateDataStatus(db, tables); + errCode = SQLiteRelationalUtils::OperateDataStatus(db, tables, virtualTime); if (errCode == E_OK) { errCode = handle->Commit(); if (errCode != E_OK) { @@ -1875,5 +1935,59 @@ int SQLiteRelationalStore::OperateDataStatusInner(const std::vector ReleaseHandle(handle); return errCode; } + +int32_t SQLiteRelationalStore::GetDeviceSyncTaskCount() const +{ + if (syncAbleEngine_ == nullptr) { + LOGW("[RelationalStore] syncAbleEngine was not initialized when get device sync task count"); + return 0; + } + return syncAbleEngine_->GetDeviceSyncTaskCount(); +} + +void SQLiteRelationalStore::CleanDirtyLogIfNeed(const std::string &tableName) const +{ + int errCode = E_OK; + SQLiteSingleVerRelationalStorageExecutor *handle = GetHandle(true, errCode); + if (handle == nullptr) { + LOGW("[RDBStore][ClearDirtyLog] Get handle failed %d", errCode); + return; + } + ResFinalizer finalizer([this, handle]() { + SQLiteSingleVerRelationalStorageExecutor *releaseHandle = handle; + ReleaseHandle(releaseHandle); + }); + sqlite3 *db = nullptr; + errCode = handle->GetDbHandle(db); + if (errCode != E_OK) { + LOGW("[RDBStore][ClearDirtyLog] Get db handle failed %d", errCode); + return; + } + bool isExistDirtyLog = false; + std::tie(errCode, isExistDirtyLog) = SQLiteRelationalUtils::CheckExistDirtyLog(db, tableName); + if (errCode != E_OK) { + LOGW("[RDBStore][ClearDirtyLog] Check dirty log failed %d", errCode); + return; + } + if (!isExistDirtyLog) { + return; + } + auto obj = GetSchemaObj(); + if (!obj.IsSchemaValid()) { + return; + } + errCode = SQLiteRelationalUtils::CleanDirtyLog(db, tableName, obj); + if (errCode != E_OK) { + LOGW("[RDBStore][ClearDirtyLog] Clean dirty log failed %d", errCode); + } +} + +RelationalSchemaObject SQLiteRelationalStore::GetSchemaObj() const +{ + if (storageEngine_ == nullptr) { + return {}; + } + return storageEngine_->GetSchemaInfo(); +} } // namespace DistributedDB #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h index 95fd3a8533e3847918ef34e83995c982820bf5d4..f4ac621ddbfb7c31ae8c0ff466484f0820aa3a10 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h @@ -46,7 +46,7 @@ public: SQLiteSingleVerRelationalStorageExecutor *GetHandle(bool isWrite, int &errCode) const; void ReleaseHandle(SQLiteSingleVerRelationalStorageExecutor *&handle) const; - int Sync(const ISyncer::SyncParma &syncParam, uint64_t connectionId); + int Sync(const ISyncer::SyncParam &syncParam, uint64_t connectionId); void ReleaseDBConnection(uint64_t connectionId, RelationalStoreConnection *connection); @@ -91,11 +91,13 @@ public: int SetReference(const std::vector &tableReferenceProperty); + std::function CleanWaterMark(const std::set clearWaterMarkTables); + int Pragma(PragmaCmd cmd, PragmaData &pragmaData); int UpsertData(RecordStatus status, const std::string &tableName, const std::vector &records); - int SetDistributedSchema(const DistributedSchema &schema); + int SetDistributedSchema(const DistributedSchema &schema, bool isForceUpgrade); int GetDownloadingAssetsCount(int32_t &count); @@ -120,7 +122,9 @@ public: #endif int OperateDataStatus(uint32_t dataOperator); -private: + + int32_t GetDeviceSyncTaskCount() const; +protected: void ReleaseResources(); // 1 store 1 connection @@ -166,7 +170,8 @@ private: int CheckTableName(const std::vector &tableNames); - int CleanWaterMark(SQLiteSingleVerRelationalStorageExecutor *&handle, std::set &clearWaterMarkTable); + int CleanWaterMarkInner(SQLiteSingleVerRelationalStorageExecutor *&handle, + const std::set &clearWaterMarkTable); int InitTrackerSchemaFromMeta(); @@ -192,6 +197,9 @@ private: int CheckTrackerTable(const TrackerSchema &trackerSchema, TableInfo &table, bool &isNoTableInSchema, bool &isFirstCreate); + int SetReferenceInner(const std::vector &tableReferenceProperty, + std::set &clearWaterMarkTables); + #ifdef USE_DISTRIBUTEDDB_CLOUD void FillSyncInfo(const CloudSyncOption &option, const SyncProcessCallback &onProcess, CloudSyncer::CloudTaskInfo &info); @@ -199,7 +207,11 @@ private: int CheckCloudSchema(const DataBaseSchema &schema); #endif - int OperateDataStatusInner(const std::vector &tables) const; + int OperateDataStatusInner(const std::vector &tables, uint64_t virtualTime) const; + + void CleanDirtyLogIfNeed(const std::string &tableName) const; + + RelationalSchemaObject GetSchemaObj() const; // use for sync Interactive std::shared_ptr syncAbleEngine_ = nullptr; // For storage operate sync function // use ref obj same as kv diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp index 774fe9577c0b17f6872eb10181f83d20c9403a49..48d4e797db10d938a64c7c992f3a78bb0f9e7e4f 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp @@ -254,7 +254,7 @@ int SQLiteRelationalStoreConnection::SyncToDevice(SyncInfo &info) return -E_INVALID_CONNECTION; } - ISyncer::SyncParma syncParam; + ISyncer::SyncParam syncParam; syncParam.devices = info.devices; syncParam.mode = info.mode; syncParam.wait = info.wait; @@ -486,14 +486,14 @@ SyncProcess SQLiteRelationalStoreConnection::GetCloudTaskStatus(uint64_t taskId) } #endif -int SQLiteRelationalStoreConnection::SetDistributedDbSchema(const DistributedSchema &schema) +int SQLiteRelationalStoreConnection::SetDistributedDbSchema(const DistributedSchema &schema, bool isForceUpgrade) { auto *store = GetDB(); if (store == nullptr) { LOGE("[RelationalConnection] store is null when set distributed schema"); return -E_INVALID_CONNECTION; } - return store->SetDistributedSchema(SQLiteRelationalUtils::FilterRepeatDefine(schema)); + return store->SetDistributedSchema(SQLiteRelationalUtils::FilterRepeatDefine(schema), isForceUpgrade); } int SQLiteRelationalStoreConnection::GetDownloadingAssetsCount(int32_t &count) @@ -525,5 +525,15 @@ int SQLiteRelationalStoreConnection::OperateDataStatus(uint32_t dataOperator) } return store->OperateDataStatus(dataOperator); } + +int32_t SQLiteRelationalStoreConnection::GetDeviceSyncTaskCount() +{ + auto *store = GetDB(); + if (store == nullptr) { + LOGE("[RelationalConnection] store is null when get device sync task count."); + return 0; + } + return store->GetDeviceSyncTaskCount(); +} } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h index 70dcf9d4f1798bd329954fbee1dbf480ed2b5e21..10dc6cba27d61e1e8aa4c1695c504dd3bc7b11bc 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h @@ -58,7 +58,7 @@ public: int UpsertData(RecordStatus status, const std::string &tableName, const std::vector &records) override; - int SetDistributedDbSchema(const DistributedSchema &schema) override; + int SetDistributedDbSchema(const DistributedSchema &schema, bool isForceUpgrade) override; int GetDownloadingAssetsCount(int32_t &count) override; @@ -84,6 +84,8 @@ public: #endif int OperateDataStatus(uint32_t dataOperator) override; + + int32_t GetDeviceSyncTaskCount() override; protected: int Pragma(int cmd, void *parameter) override; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp index 74df0413eb5a8b11368fcbf8bbcf4f804f440e4a..487ae2f0c9cfabde08e92fbea07f1dc9cf69b131 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp @@ -283,8 +283,8 @@ int SQLiteRelationalUtils::GetTypeValByStatement(sqlite3_stmt *stmt, int cid, Ty typeVal = static_cast(sqlite3_column_int64(stmt, cid)); break; } - if (strcasecmp(declType, SchemaConstant::KEYWORD_TYPE_BOOL.c_str()) == 0 || - strcasecmp(declType, SchemaConstant::KEYWORD_TYPE_BOOLEAN.c_str()) == 0) { // LCOV_EXCL_BR_LINE + if (strcasecmp(declType, SchemaConstant::KEYWORD_TYPE_BOOL) == 0 || + strcasecmp(declType, SchemaConstant::KEYWORD_TYPE_BOOLEAN) == 0) { // LCOV_EXCL_BR_LINE typeVal = static_cast(sqlite3_column_int(stmt, cid)); break; } @@ -395,21 +395,6 @@ void SQLiteRelationalUtils::AddUpgradeSqlToList(const TableInfo &tableInfo, } } -int SQLiteRelationalUtils::AnalysisTrackerTable(sqlite3 *db, const TrackerTable &trackerTable, TableInfo &tableInfo) -{ - int errCode = SQLiteUtils::AnalysisSchema(db, trackerTable.GetTableName(), tableInfo, true); - if (errCode != E_OK) { - LOGE("analysis table schema failed %d.", errCode); - return errCode; - } - tableInfo.SetTrackerTable(trackerTable); - errCode = tableInfo.CheckTrackerTable(); - if (errCode != E_OK) { - LOGE("check tracker table schema failed %d.", errCode); - } - return errCode; -} - int SQLiteRelationalUtils::QueryCount(sqlite3 *db, const std::string &tableName, int64_t &count) { std::string sql = "SELECT COUNT(1) FROM " + tableName ; @@ -473,10 +458,8 @@ void GetFieldsNeedContain(const TableInfo &tableInfo, const std::vector &requiredNotNullFields) { // should not decrease distributed field - for (const auto &syncField : syncFields) { - if (!tableInfo.IsPrimaryKey(syncField.GetFieldName())) { - fieldsNotDecrease.insert(syncField.GetFieldName()); - } + for (const auto &field : tableInfo.GetSyncField()) { + fieldsNotDecrease.insert(field); } const std::vector &uniqueDefines = tableInfo.GetUniqueDefine(); for (const auto &compositeFields : uniqueDefines) { @@ -528,12 +511,37 @@ bool IsMarkUniqueColumnInvalid(const TableInfo &tableInfo, const std::vector &distributedPk, const std::vector &originFields) +{ + if (distributedPk.empty()) { + return false; + } + auto uniqueAndPkDefine = tableInfo.GetUniqueAndPkDefine(); + if (IsMarkUniqueColumnInvalid(tableInfo, originFields)) { + LOGE("Mark more than one unique column specified in auto increment table: %s, tableName len: %zu", + DBCommon::StringMiddleMasking(tableInfo.GetTableName()).c_str(), tableInfo.GetTableName().length()); + return true; + } + auto find = std::any_of(uniqueAndPkDefine.begin(), uniqueAndPkDefine.end(), [&distributedPk](const auto &item) { + // unique index field count should be same + return item.size() == distributedPk.size() && distributedPk == DBCommon::TransformToCaseInsensitive(item); + }); + bool isMissMatch = !find; + if (isMissMatch) { + LOGE("Miss match distributed pk size %zu in auto increment table %s", distributedPk.size(), + DBCommon::StringMiddleMasking(tableInfo.GetTableName()).c_str()); + } + return isMissMatch; +} + +bool IsDistributedPkInvalid(const TableInfo &tableInfo, + const std::set &distributedPk, + const std::vector &originFields, bool isForceUpgrade) { auto lastDistributedPk = DBCommon::TransformToCaseInsensitive(tableInfo.GetSyncDistributedPk()); - if (!lastDistributedPk.empty() && distributedPk != lastDistributedPk) { + if (!isForceUpgrade && !lastDistributedPk.empty() && distributedPk != lastDistributedPk) { LOGE("distributed pk has change last %zu now %zu", lastDistributedPk.size(), distributedPk.size()); return true; } @@ -545,25 +553,7 @@ bool IsDistributedPkInvalid(const TableInfo &tableInfo, return true; } if (tableInfo.GetAutoIncrement()) { - if (distributedPk.empty()) { - return false; - } - auto uniqueAndPkDefine = tableInfo.GetUniqueAndPkDefine(); - if (IsMarkUniqueColumnInvalid(tableInfo, originFields)) { - LOGE("Mark more than one unique column specified in auto increment table: %s, tableName len: %zu", - DBCommon::StringMiddleMasking(tableInfo.GetTableName()).c_str(), tableInfo.GetTableName().length()); - return true; - } - auto find = std::any_of(uniqueAndPkDefine.begin(), uniqueAndPkDefine.end(), [&distributedPk](const auto &item) { - // unique index field count should be same - return item.size() == distributedPk.size() && distributedPk == DBCommon::TransformToCaseInsensitive(item); - }); - bool isMissMatch = !find; - if (isMissMatch) { - LOGE("Miss match distributed pk size %zu in auto increment table %s", distributedPk.size(), - DBCommon::StringMiddleMasking(tableInfo.GetTableName()).c_str()); - } - return isMissMatch; + return IsDistributedPKInvalidInAutoIncrementTable(tableInfo, distributedPk, originFields); } for (const auto &field : originFields) { bool isLocalPk = tableInfo.IsPrimaryKey(field.colName); @@ -603,7 +593,7 @@ bool IsDistributedSchemaSupport(const TableInfo &tableInfo, const std::vector &syncFields, - const std::vector &fields) + const std::vector &fields, bool isForceUpgrade) { if (fields.empty()) { LOGE("fields cannot be empty"); @@ -627,7 +617,7 @@ int CheckDistributedSchemaFields(const TableInfo &tableInfo, const std::vector fieldsNeedContain; @@ -642,7 +632,7 @@ int CheckDistributedSchemaFields(const TableInfo &tableInfo, const std::vector, CaseInsensitiveComparator> tableSchemaMap; - for (const auto &table : schema.tables) { - tableSchemaMap[table.tableName] = table.fields; - } - for (const auto &table : localSchema.tables) { - if (tableSchemaMap.find(table.tableName) == tableSchemaMap.end()) { - LOGE("[RDBUtils][CheckDistributedSchemaTables] table [%s [%zu]] missing", - DBCommon::StringMiddleMasking(table.tableName).c_str(), table.tableName.size()); - return -E_DISTRIBUTED_FIELD_DECREASE; - } - } - return E_OK; -} - int SQLiteRelationalUtils::CheckDistributedSchemaValid(const RelationalSchemaObject &schemaObj, - const DistributedSchema &schema, SQLiteSingleVerRelationalStorageExecutor *executor) + const DistributedSchema &schema, bool isForceUpgrade, SQLiteSingleVerRelationalStorageExecutor *executor) { if (executor == nullptr) { LOGE("[RDBUtils][CheckDistributedSchemaValid] executor is null"); @@ -687,11 +656,6 @@ int SQLiteRelationalUtils::CheckDistributedSchemaValid(const RelationalSchemaObj LOGE("[RDBUtils][CheckDistributedSchemaValid] sqlite handle failed %d", errCode); return errCode; } - errCode = CheckDistributedSchemaTables(schemaObj, schema); - if (errCode != E_OK) { - LOGE("[RDBUtils][CheckDistributedSchemaValid] Check tables fail %d", errCode); - return errCode; - } for (const auto &table : schema.tables) { if (table.tableName.empty()) { LOGE("[RDBUtils][CheckDistributedSchemaValid] Table name cannot be empty"); @@ -706,7 +670,7 @@ int SQLiteRelationalUtils::CheckDistributedSchemaValid(const RelationalSchemaObj } tableInfo.SetDistributedTable(schemaObj.GetDistributedTable(table.tableName)); errCode = CheckDistributedSchemaFields(tableInfo, schemaObj.GetSyncFieldInfo(table.tableName, false), - table.fields); + table.fields, isForceUpgrade); if (errCode != E_OK) { LOGE("[CheckDistributedSchema] Check fields of [%s [%zu]] fail", DBCommon::StringMiddleMasking(table.tableName).c_str(), table.tableName.size()); @@ -813,13 +777,11 @@ int SQLiteRelationalUtils::GetLogInfoPre(sqlite3_stmt *queryStmt, DistributedTab return errCode; } -int SQLiteRelationalUtils::OperateDataStatus(sqlite3 *db, const std::vector &tables) +int SQLiteRelationalUtils::OperateDataStatus(sqlite3 *db, const std::vector &tables, uint64_t virtualTime) { - auto [errCode, time] = GetCurrentVirtualTime(db); - if (errCode != E_OK) { - return errCode; - } + auto time = std::to_string(virtualTime); LOGI("[SQLiteRDBUtils] %zu tables wait for update time to %s", tables.size(), time.c_str()); + int errCode = E_OK; for (const auto &table : tables) { errCode = UpdateLocalDataModifyTime(db, table, time); if (errCode != E_OK) { @@ -859,43 +821,98 @@ int SQLiteRelationalUtils::UpdateLocalDataModifyTime(sqlite3 *db, const std::str return errCode; } -int SQLiteRelationalUtils::GetMetaLocalTimeOffset(sqlite3 *db, int64_t &timeOffset) +std::pair SQLiteRelationalUtils::CheckExistDirtyLog(sqlite3 *db, const std::string &oriTable) +{ + std::pair res; + auto &[errCode, isExist] = res; + if (db == nullptr) { + errCode = -E_INVALID_DB; + return res; + } + auto logTable = DBCommon::GetLogTableName(oriTable); + bool isCreate = false; + errCode = SQLiteUtils::CheckTableExists(db, logTable, isCreate); + if (!isCreate) { + return res; + } + std::string sql = "SELECT count(1) FROM (SELECT data_key FROM " + logTable + " " + "WHERE data_key != -1 GROUP BY data_key HAVING count(1) > 1)"; + return ExecuteCheckSql(db, sql); +} + +std::pair SQLiteRelationalUtils::ExecuteCheckSql(sqlite3 *db, const std::string &sql) +{ + bool isExist = false; + int errCode = ExecuteSql(db, sql, [&isExist](sqlite3_stmt *stmt) { + auto count = static_cast(sqlite3_column_int64(stmt, 0)); + if (count > 0) { + isExist = true; + LOGW("[SQLiteRDBUtils] Exist %" PRId64 " duplicate log", count); + } + }); + return {errCode, isExist}; +} + +int SQLiteRelationalUtils::ExecuteSql(sqlite3 *db, const std::string &sql, + const std::function &checkFunc) { - std::string sql = "SELECT value FROM " + DBCommon::GetMetaTableName() + " WHERE key=x'" + - DBCommon::TransferStringToHex(std::string(DBConstant::LOCALTIME_OFFSET_KEY)) + "';"; sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(db, sql, stmt); if (errCode != E_OK) { + LOGE("[SQLiteRDBUtils] Get check stmt failed %d", errCode); return errCode; } - int ret = E_OK; - errCode = SQLiteUtils::StepWithRetry(stmt); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - timeOffset = static_cast(sqlite3_column_int64(stmt, 0)); - if (timeOffset < 0) { - LOGE("[SQLiteRDBUtils] TimeOffset %" PRId64 "is invalid.", timeOffset); - SQLiteUtils::ResetStatement(stmt, true, ret); - return -E_INTERNAL_ERROR; + ResFinalizer finalizer([stmt]() { + int resetRet = E_OK; + sqlite3_stmt *releaseStmt = stmt; + SQLiteUtils::ResetStatement(releaseStmt, true, resetRet); + }); + errCode = SQLiteUtils::StepNext(stmt); + if (errCode == E_OK) { + if (checkFunc != nullptr) { + checkFunc(stmt); } + } else if (errCode == -E_FINISHED) { errCode = E_OK; } - SQLiteUtils::ResetStatement(stmt, true, ret); - return errCode != E_OK ? errCode : ret; + return errCode; } -std::pair SQLiteRelationalUtils::GetCurrentVirtualTime(sqlite3 *db) +int SQLiteRelationalUtils::CleanDirtyLog(sqlite3 *db, const std::string &oriTable, const RelationalSchemaObject &obj) { - int64_t localTimeOffset = 0; - std::pair res; - auto &[errCode, time] = res; - errCode = GetMetaLocalTimeOffset(db, localTimeOffset); - if (errCode != E_OK) { - LOGE("[SQLiteRDBUtils] Failed to get local timeOffset.%d", errCode); - return res; + TableInfo tableInfo; + tableInfo.SetDistributedTable(obj.GetDistributedTable(oriTable)); + auto distributedPk = tableInfo.GetSyncDistributedPk(); + if (distributedPk.empty()) { + return E_OK; } - Timestamp currentSysTime = TimeHelper::GetSysCurrentTime(); - Timestamp currentLocalTime = currentSysTime + static_cast(localTimeOffset); - time = std::to_string(currentLocalTime); - return res; + auto logTable = DBCommon::GetLogTableName(oriTable); + int errCode = E_OK; + std::string sql = "DELETE FROM " + logTable + " WHERE hash_key IN " + "(SELECT hash_key FROM (SELECT data_key, hash_key, extend_field FROM " + logTable + + " WHERE data_key IN(SELECT data_key FROM " + logTable + " GROUP BY data_key HAVING count(1)>1)" + " AND data_key != -1) AS log, '" + oriTable + + "' WHERE log.data_key = '" + oriTable + "'.rowid AND log.hash_key != " + + SqliteLogTableManager::CalcPkHash(oriTable + ".", distributedPk) + ")"; + errCode = ExecuteSql(db, sql, nullptr); + if (errCode == E_OK) { + LOGI("[SQLiteRDBUtils] Clean %d dirty hash log", sqlite3_changes(db)); + } + return errCode; +} + +int SQLiteRelationalUtils::ExecuteListAction(const std::vector> &actions) +{ + int errCode = E_OK; + for (const auto &action : actions) { + if (action == nullptr) { + continue; + } + errCode = action(); + if (errCode != E_OK) { + return errCode; + } + } + return errCode; } } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.h index 80d37b460bd0853db75a22b0b3fd5d7c322b0911..24f0767489b654259dc058e78835e1dc7f4f76a1 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.h @@ -52,7 +52,7 @@ public: static int GetCursor(sqlite3 *db, const std::string &tableName, uint64_t &cursor); static int CheckDistributedSchemaValid(const RelationalSchemaObject &schemaObj, const DistributedSchema &schema, - SQLiteSingleVerRelationalStorageExecutor *executor); + bool isForceUpgrade, SQLiteSingleVerRelationalStorageExecutor *executor); static DistributedSchema FilterRepeatDefine(const DistributedSchema &schema); @@ -63,11 +63,48 @@ public: static int GetLogInfoPre(sqlite3_stmt *queryStmt, DistributedTableMode mode, const DataItem &dataItem, LogInfo &logInfoGet); - static int OperateDataStatus(sqlite3 *db, const std::vector &tables); + static int OperateDataStatus(sqlite3 *db, const std::vector &tables, uint64_t virtualTime); static int GetMetaLocalTimeOffset(sqlite3 *db, int64_t &timeOffset); static std::pair GetCurrentVirtualTime(sqlite3 *db); + + static int CreateRelationalMetaTable(sqlite3 *db); + + static int GetKvData(sqlite3 *db, bool isMemory, const Key &key, Value &value); + static int PutKvData(sqlite3 *db, bool isMemory, const Key &key, const Value &value); + + static int InitCursorToMeta(sqlite3 *db, bool isMemory, const std::string &tableName); + static int InitKnowledgeTableTypeToMeta(sqlite3 *db, bool isMemory, const std::string &tableName); + static int SetLogTriggerStatus(sqlite3 *db, bool status); + + struct GenLogParam { + sqlite3 *db = nullptr; + bool isMemory = false; + bool isTrackerTable = false; + }; + + static int GeneTimeStrForLog(const TableInfo &tableInfo, GenLogParam ¶m, std::string &timeStr); + + static int GeneLogInfoForExistedData(const std::string &identity, const TableInfo &tableInfo, + std::unique_ptr &logMgrPtr, GenLogParam ¶m); + + static int GetExistedDataTimeOffset(sqlite3 *db, const std::string &tableName, bool isMem, int64_t &timeOffset); + + static std::string GetExtendValue(const TrackerTable &trackerTable); + + static int CleanTrackerData(sqlite3 *db, const std::string &tableName, int64_t cursor, bool isOnlyTrackTable); + + static std::pair CheckExistDirtyLog(sqlite3 *db, const std::string &oriTable); + + static int CleanDirtyLog(sqlite3 *db, const std::string &oriTable, const RelationalSchemaObject &obj); + + static std::pair ExecuteCheckSql(sqlite3 *db, const std::string &sql); + + static int ExecuteSql(sqlite3 *db, const std::string &sql, + const std::function &checkFunc); + + static int ExecuteListAction(const std::vector> &actions); private: static int BindExtendStatementByType(sqlite3_stmt *statement, int cid, Type &typeVal); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils_client.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils_client.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d2fd1f42e7ae41d6caac64f7f0ea796e27557913 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils_client.cpp @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2025 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 "sqlite_relational_utils.h" +#include "db_common.h" +#include "time_helper.h" + +namespace DistributedDB { +int SQLiteRelationalUtils::CreateRelationalMetaTable(sqlite3 *db) +{ + std::string sql = + "CREATE TABLE IF NOT EXISTS " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata(" \ + "key BLOB PRIMARY KEY NOT NULL," \ + "value BLOB);"; + int errCode = SQLiteUtils::ExecuteRawSQL(db, sql); + if (errCode != E_OK) { + LOGE("[SQLite] execute create table sql failed, err=%d", errCode); + } + return errCode; +} + +int SQLiteRelationalUtils::GetKvData(sqlite3 *db, bool isMemory, const Key &key, Value &value) +{ + static const std::string SELECT_META_VALUE_SQL = "SELECT value FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + + "metadata WHERE key=?;"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(db, SELECT_META_VALUE_SQL, statement); + if (errCode != E_OK) { + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } + + errCode = SQLiteUtils::BindBlobToStatement(statement, 1, key, false); // first arg. + if (errCode != E_OK) { + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } + + errCode = SQLiteUtils::StepWithRetry(statement, isMemory); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = -E_NOT_FOUND; + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } + + errCode = SQLiteUtils::GetColumnBlobValue(statement, 0, value); // only one result. + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); +} + +int SQLiteRelationalUtils::PutKvData(sqlite3 *db, bool isMemory, const Key &key, const Value &value) +{ + static const std::string INSERT_META_SQL = "INSERT OR REPLACE INTO " + std::string(DBConstant::RELATIONAL_PREFIX) + + "metadata VALUES(?,?);"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(db, INSERT_META_SQL, statement); + if (errCode != E_OK) { + return errCode; + } + + errCode = SQLiteUtils::BindBlobToStatement(statement, 1, key, false); // 1 means key index + if (errCode != E_OK) { + LOGE("[SingleVerExe][BindPutKv]Bind key error:%d", errCode); + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } + + errCode = SQLiteUtils::BindBlobToStatement(statement, 2, value, true); // 2 means value index + if (errCode != E_OK) { + LOGE("[SingleVerExe][BindPutKv]Bind value error:%d", errCode); + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } + errCode = SQLiteUtils::StepWithRetry(statement, isMemory); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + } + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); +} + +int SQLiteRelationalUtils::InitCursorToMeta(sqlite3 *db, bool isMemory, const std::string &tableName) +{ + Value key; + Value cursor; + DBCommon::StringToVector(DBCommon::GetCursorKey(tableName), key); + int errCode = GetKvData(db, isMemory, key, cursor); + if (errCode == -E_NOT_FOUND) { + DBCommon::StringToVector(std::string("0"), cursor); + errCode = PutKvData(db, isMemory, key, cursor); + if (errCode != E_OK) { + LOGE("Init cursor to meta table failed. %d", errCode); + } + return errCode; + } + if (errCode != E_OK) { + LOGE("Get cursor from meta table failed. %d", errCode); + } + return errCode; +} + +int SQLiteRelationalUtils::InitKnowledgeTableTypeToMeta(sqlite3 *db, bool isMemory, const std::string &tableName) +{ + std::string tableTypeKey = "sync_table_type_" + tableName; + Value key; + DBCommon::StringToVector(tableTypeKey, key); + Value value; + int errCode = GetKvData(db, isMemory, key, value); + if (errCode == -E_NOT_FOUND) { + DBCommon::StringToVector(DBConstant::KNOWLEDGE_TABLE_TYPE, value); + errCode = PutKvData(db, isMemory, key, value); + if (errCode != E_OK) { + LOGE("Init table type to meta table failed. %d", errCode); + return errCode; + } + } + if (errCode != E_OK) { + LOGE("Get table type from meta table failed. %d", errCode); + } + return errCode; +} + +int SQLiteRelationalUtils::SetLogTriggerStatus(sqlite3 *db, bool status) +{ + const std::string key = "log_trigger_switch"; + std::string val = status ? "true" : "false"; + std::string sql = "INSERT OR REPLACE INTO " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata" + + " VALUES ('" + key + "', '" + val + "')"; + int errCode = SQLiteUtils::ExecuteRawSQL(db, sql); + if (errCode != E_OK) { + LOGE("Set log trigger to %s failed. errCode=%d", val.c_str(), errCode); + } + return errCode; +} + +int SQLiteRelationalUtils::GeneLogInfoForExistedData(const std::string &identity, const TableInfo &tableInfo, + std::unique_ptr &logMgrPtr, GenLogParam ¶m) +{ + std::string tableName = tableInfo.GetTableName(); + std::string timeStr; + int errCode = GeneTimeStrForLog(tableInfo, param, timeStr); + if (errCode != E_OK) { + return errCode; + } + errCode = SetLogTriggerStatus(param.db, false); + if (errCode != E_OK) { + return errCode; + } + std::string logTable = DBConstant::RELATIONAL_PREFIX + tableName + "_log"; + std::string rowid = std::string(DBConstant::SQLITE_INNER_ROWID); + uint32_t flagVal = static_cast(LogInfoFlag::FLAG_LOCAL); + if (tableInfo.GetTableSyncType() == TableSyncType::CLOUD_COOPERATION) { + flagVal = flagVal | static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_INCONSISTENCY); + } + std::string flag = std::to_string(flagVal); + TrackerTable trackerTable = tableInfo.GetTrackerTable(); + trackerTable.SetTableName(tableName); + const std::string prefix = "a."; + std::string calPrimaryKeyHash = logMgrPtr->CalcPrimaryKeyHash(prefix, tableInfo, identity); + std::string sql = "INSERT OR REPLACE INTO " + logTable + " SELECT " + rowid + ", '', '', " + timeStr + " + " + + rowid + ", " + timeStr + " + " + rowid + ", " + flag + ", " + calPrimaryKeyHash + ", '', "; + sql += GetExtendValue(tableInfo.GetTrackerTable()); + sql += ", 0, '', '', 0 FROM '" + tableName + "' AS a "; + if (param.isTrackerTable) { + sql += " WHERE 1 = 1;"; + } else { + sql += "WHERE NOT EXISTS (SELECT 1 FROM " + logTable + " WHERE data_key = a._rowid_);"; + } + errCode = trackerTable.ReBuildTempTrigger(param.db, TriggerMode::TriggerModeEnum::INSERT, [db = param.db, &sql]() { + int ret = SQLiteUtils::ExecuteRawSQL(db, sql); + if (ret != E_OK) { + LOGE("Failed to initialize cloud type log data.%d", ret); + } + return ret; + }); + return errCode; +} + +int SQLiteRelationalUtils::GetExistedDataTimeOffset(sqlite3 *db, const std::string &tableName, bool isMem, + int64_t &timeOffset) +{ + std::string sql = "SELECT get_sys_time(0) - max(" + std::string(DBConstant::SQLITE_INNER_ROWID) + ") - 1 FROM '" + + tableName + "';"; + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != E_OK) { + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(stmt, isMem); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + timeOffset = static_cast(sqlite3_column_int64(stmt, 0)); + errCode = E_OK; + } + int ret = E_OK; + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode != E_OK ? errCode : ret; +} + +std::string SQLiteRelationalUtils::GetExtendValue(const TrackerTable &trackerTable) +{ + std::string extendValue; + const std::set &extendNames = trackerTable.GetExtendNames(); + if (!extendNames.empty()) { + extendValue += "json_object("; + for (const auto &extendName : extendNames) { + extendValue += "'" + extendName + "'," + extendName + ","; + } + extendValue.pop_back(); + extendValue += ")"; + } else { + extendValue = "''"; + } + return extendValue; +} + +int SQLiteRelationalUtils::CleanTrackerData(sqlite3 *db, const std::string &tableName, int64_t cursor, + bool isOnlyTrackTable) +{ + std::string sql; + if (isOnlyTrackTable) { + sql = "DELETE FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log"; + } else { + sql = "UPDATE " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log SET extend_field = NULL"; + } + sql += " where data_key = -1 and cursor <= ?;"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, statement); + if (errCode != E_OK) { // LCOV_EXCL_BR_LINE + LOGE("get clean tracker data stmt failed %d.", errCode); + return errCode; + } + errCode = SQLiteUtils::BindInt64ToStatement(statement, 1, cursor); + int ret = E_OK; + if (errCode != E_OK) { // LCOV_EXCL_BR_LINE + LOGE("bind clean tracker data stmt failed %d.", errCode); + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(statement); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { // LCOV_EXCL_BR_LINE + errCode = E_OK; + } else { + LOGE("clean tracker step failed: %d.", errCode); + } + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode == E_OK ? ret : errCode; +} + + +int SQLiteRelationalUtils::AnalysisTrackerTable(sqlite3 *db, const TrackerTable &trackerTable, TableInfo &tableInfo) +{ + int errCode = SQLiteUtils::AnalysisSchema(db, trackerTable.GetTableName(), tableInfo, true); + if (errCode != E_OK) { + LOGE("analysis table schema failed %d.", errCode); + return errCode; + } + tableInfo.SetTrackerTable(trackerTable); + errCode = tableInfo.CheckTrackerTable(); + if (errCode != E_OK) { + LOGE("check tracker table schema failed %d.", errCode); + } + return errCode; +} + +int SQLiteRelationalUtils::GetMetaLocalTimeOffset(sqlite3 *db, int64_t &timeOffset) +{ + std::string sql = "SELECT value FROM " + DBCommon::GetMetaTableName() + " WHERE key=x'" + + DBCommon::TransferStringToHex(std::string(DBConstant::LOCALTIME_OFFSET_KEY)) + "';"; + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != E_OK) { + return errCode; + } + int ret = E_OK; + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + timeOffset = static_cast(sqlite3_column_int64(stmt, 0)); + if (timeOffset < 0) { + LOGE("[SQLiteRDBUtils] TimeOffset %" PRId64 "is invalid.", timeOffset); + SQLiteUtils::ResetStatement(stmt, true, ret); + return -E_INTERNAL_ERROR; + } + errCode = E_OK; + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + timeOffset = 0; + errCode = E_OK; + } + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode != E_OK ? errCode : ret; +} + +std::pair SQLiteRelationalUtils::GetCurrentVirtualTime(sqlite3 *db) +{ + int64_t localTimeOffset = 0; + std::pair res; + auto &[errCode, time] = res; + errCode = GetMetaLocalTimeOffset(db, localTimeOffset); + if (errCode != E_OK) { + LOGE("[SQLiteRDBUtils] Failed to get local timeOffset.%d", errCode); + return res; + } + Timestamp currentSysTime = TimeHelper::GetSysCurrentTime(); + Timestamp currentLocalTime = currentSysTime + static_cast(localTimeOffset); + time = std::to_string(currentLocalTime); + return res; +} + +int SQLiteRelationalUtils::GeneTimeStrForLog(const TableInfo &tableInfo, GenLogParam ¶m, std::string &timeStr) +{ + if (tableInfo.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { + auto [errCode, time] = GetCurrentVirtualTime(param.db); + if (errCode != E_OK) { + LOGE("Failed to get current virtual time.%d", errCode); + return errCode; + } + timeStr = time; + } else { + int64_t timeOffset = 0; + std::string tableName = tableInfo.GetTableName(); + int errCode = GetExistedDataTimeOffset(param.db, tableName, param.isMemory, timeOffset); + if (errCode != E_OK) { + return errCode; + } + timeStr = std::to_string(timeOffset); + } + return E_OK; +} +} // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp index 04415fc87df8aef7b6d59b3692e3797bda3d634e..554cb3f42731608e8ea08e6c37312143de97c2d4 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp @@ -34,13 +34,13 @@ SQLiteSingleRelationalStorageEngine::~SQLiteSingleRelationalStorageEngine() StorageExecutor *SQLiteSingleRelationalStorageEngine::NewSQLiteStorageExecutor(sqlite3 *dbHandle, bool isWrite, bool isMemDb) { - auto mode = properties_.GetDistributedTableMode(); + auto mode = GetRelationalProperties().GetDistributedTableMode(); return new (std::nothrow) SQLiteSingleVerRelationalStorageExecutor(dbHandle, isWrite, mode); } int SQLiteSingleRelationalStorageEngine::Upgrade(sqlite3 *db) { - int errCode = CreateRelationalMetaTable(db); + int errCode = SQLiteRelationalUtils::CreateRelationalMetaTable(db); if (errCode != E_OK) { LOGE("Create relational store meta table failed. err=%d", errCode); return errCode; @@ -92,7 +92,7 @@ int SQLiteSingleRelationalStorageEngine::RegisterFunction(sqlite3 *db) const int SQLiteSingleRelationalStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *&handle) { sqlite3 *db = nullptr; - int errCode = SQLiteUtils::OpenDatabase(option_, db, false); + int errCode = SQLiteUtils::OpenDatabase(GetOption(), db, false); if (errCode != E_OK) { return errCode; } @@ -151,7 +151,8 @@ const std::string SYNC_TABLE_TYPE = "sync_table_type_"; int SaveSchemaToMetaTable(SQLiteSingleVerRelationalStorageExecutor *handle, const RelationalSchemaObject &schema) { - const Key schemaKey(DBConstant::RELATIONAL_SCHEMA_KEY.begin(), DBConstant::RELATIONAL_SCHEMA_KEY.end()); + const Key schemaKey(DBConstant::RELATIONAL_SCHEMA_KEY, + DBConstant::RELATIONAL_SCHEMA_KEY + strlen(DBConstant::RELATIONAL_SCHEMA_KEY)); Value schemaVal; auto schemaStr = schema.ToSchemaString(); if (schemaStr.size() > SchemaConstant::SCHEMA_STRING_SIZE_LIMIT) { @@ -169,8 +170,8 @@ int SaveSchemaToMetaTable(SQLiteSingleVerRelationalStorageExecutor *handle, cons int SaveTrackerSchemaToMetaTable(SQLiteSingleVerRelationalStorageExecutor *handle, const RelationalSchemaObject &schema) { - const Key schemaKey(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.begin(), - DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.end()); + const Key schemaKey(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY, + DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY + strlen(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY)); Value schemaVal; DBCommon::StringToVector(schema.ToSchemaString(), schemaVal); int errCode = handle->PutKvData(schemaKey, schemaVal); // save schema to meta_data @@ -248,7 +249,7 @@ int SQLiteSingleRelationalStorageEngine::CreateDistributedSharedTable(SQLiteSing table.SetOriginTableName(tableName); table.SetSharedTableMark(true); table.SetTableSyncType(tableSyncType); - table.SetTrackerTable(trackerSchema_.GetTrackerTable(sharedTableName)); + table.SetTrackerTable(GetTrackerSchema().GetTrackerTable(sharedTableName)); if (!table.GetTrackerTable().IsEmpty() && tableSyncType == TableSyncType::DEVICE_COOPERATION) { // LCOV_EXCL_BR_LINE LOGE("current is trackerTable, not support creating device distributed table."); return -E_NOT_SUPPORT; @@ -305,7 +306,7 @@ int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(const std::strin int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(SQLiteSingleVerRelationalStorageExecutor *&handle, bool isUpgraded, const std::string &identity, TableInfo &table, RelationalSchemaObject &schema) { - auto mode = properties_.GetDistributedTableMode(); + auto mode = GetRelationalProperties().GetDistributedTableMode(); TableSyncType tableSyncType = table.GetTableSyncType(); std::string tableName = table.GetTableName(); int errCode = handle->InitCursorToMeta(tableName); @@ -354,7 +355,7 @@ int SQLiteSingleRelationalStorageEngine::UpgradeDistributedTable(const std::stri return errCode; } - auto mode = properties_.GetDistributedTableMode(); + auto mode = GetRelationalProperties().GetDistributedTableMode(); errCode = handle->UpgradeDistributedTable(tableName, mode, schemaChanged, schema, syncType); if (errCode != E_OK) { LOGE("Upgrade distributed table failed. %d", errCode); @@ -392,7 +393,7 @@ int SQLiteSingleRelationalStorageEngine::CleanDistributedDeviceTable(std::vector errCode = handle->CheckAndCleanDistributedTable(schema_.GetTableNames(), missingTables); if (errCode == E_OK) { if (missingTables.empty()) { - LOGI("Check missing distributed table is empty."); + LOGI("Missing table is empty."); ReleaseExecutor(handle); return errCode; } @@ -436,22 +437,16 @@ const RelationalDBProperties &SQLiteSingleRelationalStorageEngine::GetProperties return properties_; } -void SQLiteSingleRelationalStorageEngine::SetProperties(const RelationalDBProperties &properties) +const RelationalDBProperties SQLiteSingleRelationalStorageEngine::GetRelationalProperties() const { - properties_ = properties; + std::lock_guard lock(propertiesMutex_); + return properties_; } -int SQLiteSingleRelationalStorageEngine::CreateRelationalMetaTable(sqlite3 *db) +void SQLiteSingleRelationalStorageEngine::SetProperties(const RelationalDBProperties &properties) { - std::string sql = - "CREATE TABLE IF NOT EXISTS " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata(" \ - "key BLOB PRIMARY KEY NOT NULL," \ - "value BLOB);"; - int errCode = SQLiteUtils::ExecuteRawSQL(db, sql); - if (errCode != E_OK) { - LOGE("[SQLite] execute create table sql failed, err=%d", errCode); - } - return errCode; + std::lock_guard lock(propertiesMutex_); + properties_ = properties; } int SQLiteSingleRelationalStorageEngine::SetTrackerTable(const TrackerSchema &schema, const TableInfo &tableInfo, @@ -463,29 +458,23 @@ int SQLiteSingleRelationalStorageEngine::SetTrackerTable(const TrackerSchema &sc if (handle == nullptr) { return errCode; } + ResFinalizer finalizer([&handle, this] { this->ReleaseExecutor(handle); }); errCode = handle->StartTransaction(TransactType::IMMEDIATE); if (errCode != E_OK) { - ReleaseExecutor(handle); return errCode; } - RelationalSchemaObject tracker = trackerSchema_; + RelationalSchemaObject tracker = GetTrackerSchema(); tracker.InsertTrackerSchema(schema); int ret = handle->CreateTrackerTable(tracker.GetTrackerTable(schema.tableName), tableInfo, isFirstCreate); if (ret != E_OK && ret != -E_WITH_INVENTORY_DATA) { (void)handle->Rollback(); - ReleaseExecutor(handle); return ret; } - Key key; - DBCommon::StringToVector(SYNC_TABLE_TYPE + schema.tableName, key); - Value value; - DBCommon::StringToVector(tableInfo.GetTableSyncType() == DEVICE_COOPERATION ? DEVICE_TYPE : CLOUD_TYPE, value); - errCode = handle->PutKvData(key, value); + errCode = SaveSyncTableTypeAndDropFlagToMeta(handle, schema.tableName, tableInfo.GetTableSyncType()); if (errCode != E_OK) { LOGE("[SetTrackerTable] Save sync type to meta table failed: %d", errCode); (void)handle->Rollback(); - ReleaseExecutor(handle); return errCode; } @@ -495,23 +484,21 @@ int SQLiteSingleRelationalStorageEngine::SetTrackerTable(const TrackerSchema &sc errCode = SaveTrackerSchemaToMetaTable(handle, tracker); if (errCode != E_OK) { (void)handle->Rollback(); - ReleaseExecutor(handle); return errCode; } errCode = handle->Commit(); if (errCode != E_OK) { - ReleaseExecutor(handle); return errCode; } - trackerSchema_ = tracker; - ReleaseExecutor(handle); + SetTrackerSchema(tracker); return ret; } void SQLiteSingleRelationalStorageEngine::CacheTrackerSchema(const TrackerSchema &schema) { + std::lock_guard lock(trackerSchemaMutex_); trackerSchema_.InsertTrackerSchema(schema); if (!schema.isTrackAction && schema.trackerColNames.empty()) { // if isTrackAction be false and trackerColNames is empty, will remove the tracker schema. @@ -551,7 +538,7 @@ int SQLiteSingleRelationalStorageEngine::GetOrInitTrackerSchemaFromMeta() return errCode; } } - trackerSchema_ = trackerSchema; + SetTrackerSchema(trackerSchema); ReleaseExecutor(handle); return E_OK; } @@ -564,7 +551,7 @@ int SQLiteSingleRelationalStorageEngine::SaveTrackerSchema(const std::string &ta if (handle == nullptr) { return errCode; } - RelationalSchemaObject tracker = trackerSchema_; + RelationalSchemaObject tracker = GetTrackerSchema(); errCode = SaveTrackerSchemaToMetaTable(handle, tracker); if (errCode != E_OK || !isFirstCreate) { ReleaseExecutor(handle); @@ -633,10 +620,9 @@ int SQLiteSingleRelationalStorageEngine::SetReference(const std::vectorGetClearWaterMarkTables(tableReferenceProperty, schema, clearWaterMarkTables); - if (errCode != E_OK) { - return errCode; + int res = handle->GetClearWaterMarkTables(tableReferenceProperty, schema, clearWaterMarkTables); + if (res != E_OK && res != -E_TABLE_REFERENCE_CHANGED) { + return res; } schema.SetReferenceProperty(tableReferenceProperty); errCode = SaveSchemaToMetaTable(handle, schema); @@ -644,7 +630,7 @@ int SQLiteSingleRelationalStorageEngine::SetReference(const std::vector& oldExtendColNames = oldTrackerTable.GetExtendNames(); const std::string lowVersionExtendColName = oldTrackerTable.GetExtendName(); @@ -1093,17 +1086,22 @@ int SQLiteSingleRelationalStorageEngine::UpdateExtendField(const DistributedDB:: return errCode; } } + + // Try clear historical mismatched log, which usually do not occur and apply to tracker table only. + if (GetSchema().GetTable(schema.tableName).Empty()) { + handle->ClearLogOfMismatchedData(schema.tableName); + } return handle->Commit(); } std::pair SQLiteSingleRelationalStorageEngine::SetDistributedSchema(const DistributedSchema &schema, - const std::string &localIdentity) + const std::string &localIdentity, bool isForceUpgrade) { std::lock_guard autoLock(createDistributedTableMutex_); auto schemaObj = GetSchema(); std::pair res = {E_OK, schemaObj.CheckDistributedSchemaChange(schema)}; auto &[errCode, isSchemaChange] = res; - if (properties_.GetDistributedTableMode() == DistributedTableMode::SPLIT_BY_DEVICE) { + if (GetRelationalProperties().GetDistributedTableMode() == DistributedTableMode::SPLIT_BY_DEVICE) { LOGE("tableMode SPLIT_BY_DEVICE not support set distributed schema"); errCode = -E_NOT_SUPPORT; return res; @@ -1116,7 +1114,7 @@ std::pair SQLiteSingleRelationalStorageEngine::SetDistributedSchema(c LOGE("new schema version no upgrade old:%" PRIu32 " new:%" PRIu32, localSchema.version, schema.version); errCode = -E_INVALID_ARGS; } else { - errCode = SetDistributedSchemaInner(schemaObj, schema, localIdentity); + errCode = SetDistributedSchemaInner(schemaObj, schema, localIdentity, isForceUpgrade); } if (errCode == E_OK) { SetSchema(schemaObj); @@ -1125,7 +1123,7 @@ std::pair SQLiteSingleRelationalStorageEngine::SetDistributedSchema(c } int SQLiteSingleRelationalStorageEngine::SetDistributedSchemaInner(RelationalSchemaObject &schemaObj, - const DistributedSchema &schema, const std::string &localIdentity) + const DistributedSchema &schema, const std::string &localIdentity, bool isForceUpgrade) { int errCode = E_OK; auto *handle = static_cast(FindExecutor(true, OperatePerm::NORMAL_PERM, @@ -1142,39 +1140,54 @@ int SQLiteSingleRelationalStorageEngine::SetDistributedSchemaInner(RelationalSch if (errCode != E_OK) { return errCode; } - errCode = SQLiteRelationalUtils::CheckDistributedSchemaValid(schemaObj, schema, handle); + errCode = SetDistributedSchemaInTraction(schemaObj, schema, localIdentity, isForceUpgrade, *handle); if (errCode != E_OK) { (void)handle->Rollback(); return errCode; } + return handle->Commit(); +} + +int SQLiteSingleRelationalStorageEngine::SetDistributedSchemaInTraction(RelationalSchemaObject &schemaObj, + const DistributedSchema &schema, const std::string &localIdentity, bool isForceUpgrade, + SQLiteSingleVerRelationalStorageExecutor &handle) +{ + int errCode = SQLiteRelationalUtils::CheckDistributedSchemaValid(schemaObj, schema, isForceUpgrade, &handle); + if (errCode != E_OK) { + return errCode; + } + auto changeStatus = schemaObj.GetTableChangeStatus(schema); schemaObj.SetDistributedSchema(schema); for (const auto &table : schema.tables) { + if (!changeStatus[table.tableName]) { + continue; + } TableInfo tableInfo = schemaObj.GetTable(table.tableName); + tableInfo.SetTrackerTable(GetTrackerSchema().GetTrackerTable(table.tableName)); if (tableInfo.Empty()) { continue; } tableInfo.SetDistributedTable(schemaObj.GetDistributedTable(table.tableName)); - errCode = handle->RenewTableTrigger(schemaObj.GetTableMode(), tableInfo, tableInfo.GetTableSyncType(), + errCode = handle.RenewTableTrigger(schemaObj.GetTableMode(), tableInfo, tableInfo.GetTableSyncType(), localIdentity); if (errCode != E_OK) { - LOGE("Failed to refresh trigger while setting up distributed schema: %d", errCode); - (void)handle->Rollback(); + LOGE("Failed to refresh %s:%zu trigger while setting up distributed schema: %d", + DBCommon::StringMiddleMasking(table.tableName).c_str(), table.tableName.size(), errCode); return errCode; } - errCode = handle->UpdateHashKey(schemaObj.GetTableMode(), tableInfo, tableInfo.GetTableSyncType()); + errCode = handle.UpdateHashKey(schemaObj.GetTableMode(), tableInfo, tableInfo.GetTableSyncType(), + localIdentity); if (errCode != E_OK) { - LOGE("Failed to update hash_key while setting up distributed schema: %d", errCode); - (void)handle->Rollback(); + LOGE("Failed to update %s:%zu hash_key while setting up distributed schema: %d", + DBCommon::StringMiddleMasking(table.tableName).c_str(), table.tableName.size(), errCode); return errCode; } } - errCode = SaveSchemaToMetaTable(handle, schemaObj); + errCode = SaveSchemaToMetaTable(&handle, schemaObj); if (errCode != E_OK) { LOGE("Save schema to meta table for set distributed schema failed. %d", errCode); - (void)handle->Rollback(); - return errCode; } - return handle->Commit(); + return errCode; } } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h index ce9b1709e06263d90b332b0b0d2b19e00fa8a1e2..61588301fa7e27b641fc17b2d8d4a467720be0bf 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h @@ -41,6 +41,7 @@ public: int CleanDistributedDeviceTable(std::vector &missingTables); const RelationalDBProperties &GetProperties() const; + const RelationalDBProperties GetRelationalProperties() const; void SetProperties(const RelationalDBProperties &properties); int SetTrackerTable(const TrackerSchema &schema, const TableInfo &tableInfo, bool isFirstCreate); @@ -50,6 +51,7 @@ public: int ExecuteSql(const SqlCondition &condition, std::vector &records); RelationalSchemaObject GetTrackerSchema() const; + void SetTrackerSchema(const RelationalSchemaObject &trackerSchema); int CleanTrackerData(const std::string &tableName, int64_t cursor); int SetReference(const std::vector &tableReferenceProperty, @@ -62,7 +64,8 @@ public: const std::map &sharedTableOriginNames); int UpdateExtendField(const TrackerSchema &schema); - std::pair SetDistributedSchema(const DistributedSchema &schema, const std::string &localIdentity); + std::pair SetDistributedSchema(const DistributedSchema &schema, const std::string &localIdentity, + bool isForceUpgrade); protected: StorageExecutor *NewSQLiteStorageExecutor(sqlite3 *dbHandle, bool isWrite, bool isMemDb) override; int Upgrade(sqlite3 *db) override; @@ -85,8 +88,6 @@ private: int CreateDistributedSharedTable(SQLiteSingleVerRelationalStorageExecutor *&handle, const std::string &tableName, const std::string &sharedTableName, TableSyncType syncType, RelationalSchemaObject &schema); - int CreateRelationalMetaTable(sqlite3 *db); - int CleanTrackerDeviceTable(const std::vector &tableNames, RelationalSchemaObject &trackerSchemaObj, SQLiteSingleVerRelationalStorageExecutor *&handle); @@ -125,14 +126,19 @@ private: const std::map &alterTableNames, const RelationalSchemaObject &schema); int SetDistributedSchemaInner(RelationalSchemaObject &schemaObj, const DistributedSchema &schema, - const std::string &localIdentity); + const std::string &localIdentity, bool isForceUpgrade); + + int SetDistributedSchemaInTraction(RelationalSchemaObject &schemaObj, const DistributedSchema &schema, + const std::string &localIdentity, bool isForceUpgrade, SQLiteSingleVerRelationalStorageExecutor &handle); RelationalSchemaObject schema_; RelationalSchemaObject trackerSchema_; mutable std::mutex schemaMutex_; + mutable std::mutex trackerSchemaMutex_; RelationalDBProperties properties_; std::mutex createDistributedTableMutex_; + mutable std::mutex propertiesMutex_; }; } // namespace DistributedDB #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp index 439a630528d9b842e847ce0ea29814614d817192..182b00b73f9ccce35f98634187b2122c5d559eaf 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp @@ -142,93 +142,14 @@ int CheckTableConstraint(const TableInfo &table, DistributedTableMode mode, Tabl return E_OK; } -namespace { -int GetExistedDataTimeOffset(sqlite3 *db, const std::string &tableName, bool isMem, int64_t &timeOffset) -{ - std::string sql = "SELECT get_sys_time(0) - max(" + std::string(DBConstant::SQLITE_INNER_ROWID) + ") - 1 FROM '" + - tableName + "';"; - sqlite3_stmt *stmt = nullptr; - int errCode = SQLiteUtils::GetStatement(db, sql, stmt); - if (errCode != E_OK) { - return errCode; - } - errCode = SQLiteUtils::StepWithRetry(stmt, isMem); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - timeOffset = static_cast(sqlite3_column_int64(stmt, 0)); - errCode = E_OK; - } - int ret = E_OK; - SQLiteUtils::ResetStatement(stmt, true, ret); - return errCode != E_OK ? errCode : ret; -} -} - -std::string GetExtendValue(const TrackerTable &trackerTable) -{ - std::string extendValue; - const std::set &extendNames = trackerTable.GetExtendNames(); - if (!extendNames.empty()) { - extendValue += "json_object("; - for (const auto &extendName : extendNames) { - extendValue += "'" + extendName + "'," + extendName + ","; - } - extendValue.pop_back(); - extendValue += ")"; - } else { - extendValue = "''"; - } - return extendValue; -} - -int SQLiteSingleVerRelationalStorageExecutor::GeneLogInfoForExistedDataInner(sqlite3 *db, const std::string &identity, - const TableInfo &tableInfo, std::unique_ptr &logMgrPtr, bool isTrackerTable) -{ - std::string tableName = tableInfo.GetTableName(); - int64_t timeOffset = 0; - int errCode = GetExistedDataTimeOffset(db, tableName, isMemDb_, timeOffset); - if (errCode != E_OK) { - return errCode; - } - errCode = SetLogTriggerStatus(false); - if (errCode != E_OK) { - return errCode; - } - std::string timeOffsetStr = std::to_string(timeOffset); - std::string logTable = DBConstant::RELATIONAL_PREFIX + tableName + "_log"; - std::string rowid = std::string(DBConstant::SQLITE_INNER_ROWID); - std::string flag = std::to_string(static_cast(LogInfoFlag::FLAG_LOCAL) | - static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_INCONSISTENCY)); - TrackerTable trackerTable = tableInfo.GetTrackerTable(); - trackerTable.SetTableName(tableName); - const std::string prefix = "a."; - std::string calPrimaryKeyHash = logMgrPtr->CalcPrimaryKeyHash(prefix, tableInfo, identity); - std::string sql = "INSERT OR REPLACE INTO " + logTable + " SELECT " + rowid + - ", '', '', " + timeOffsetStr + " + " + rowid + ", " + - timeOffsetStr + " + " + rowid + ", " + flag + ", " + calPrimaryKeyHash + ", '', "; - sql += GetExtendValue(tableInfo.GetTrackerTable()); - sql += ", 0, '', '', 0 FROM '" + tableName + "' AS a "; - if (isTrackerTable) { - sql += " WHERE 1 = 1;"; - } else { - sql += "WHERE NOT EXISTS (SELECT 1 FROM " + logTable + " WHERE data_key = a._rowid_);"; - } - errCode = trackerTable.ReBuildTempTrigger(db, TriggerMode::TriggerModeEnum::INSERT, [db, &sql]() { - int ret = SQLiteUtils::ExecuteRawSQL(db, sql); - if (ret != E_OK) { - LOGE("Failed to initialize cloud type log data.%d", ret); - } - return ret; - }); - return errCode; -} - int SQLiteSingleVerRelationalStorageExecutor::GeneLogInfoForExistedData(sqlite3 *db, const std::string &identity, const TableInfo &tableInfo, std::unique_ptr &logMgrPtr, bool isTrackerTable) { if (tableInfo.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { return UpdateTrackerTable(db, identity, tableInfo, logMgrPtr, false); } - return GeneLogInfoForExistedDataInner(db, identity, tableInfo, logMgrPtr, isTrackerTable); + SQLiteRelationalUtils::GenLogParam param = {db, isMemDb_, isTrackerTable}; + return SQLiteRelationalUtils::GeneLogInfoForExistedData(identity, tableInfo, logMgrPtr, param); } int SQLiteSingleVerRelationalStorageExecutor::ResetLogStatus(std::string &tableName) @@ -299,11 +220,7 @@ int SQLiteSingleVerRelationalStorageExecutor::CreateRelationalLogTable(Distribut { // create log table std::unique_ptr tableManager; - if (!table.GetTrackerTable().IsEmpty() && table.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { - tableManager = std::make_unique(); - } else { - tableManager = LogTableManagerFactory::GetTableManager(mode, table.GetTableSyncType()); - } + tableManager = LogTableManagerFactory::GetTableManager(table, mode, table.GetTableSyncType()); if (tableManager == nullptr) { LOGE("[CreateRelationalLogTable] get table manager failed"); return -E_INVALID_DB; @@ -314,7 +231,14 @@ int SQLiteSingleVerRelationalStorageExecutor::CreateRelationalLogTable(Distribut return errCode; } std::string tableName = table.GetTableName(); - if (!isUpgraded) { + bool isOnceDropped = false; + (void)IsTableOnceDropped(tableName, isOnceDropped); + if (isOnceDropped) { + SQLiteRelationalUtils::GenLogParam param = { + dbHandle_, isMemDb_, table.GetTrackerTable().GetTableName().empty() + }; + errCode = SQLiteRelationalUtils::GeneLogInfoForExistedData(identity, table, tableManager, param); + } else if (!isUpgraded) { if (table.GetTrackerTable().GetTableName().empty()) { errCode = GeneLogInfoForExistedData(dbHandle_, identity, table, tableManager, false); } else if (table.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { @@ -324,10 +248,6 @@ int SQLiteSingleVerRelationalStorageExecutor::CreateRelationalLogTable(Distribut // tracker table -> distributed cloud table errCode = ResetLogStatus(tableName); } - } else { - if (table.GetTrackerTable().GetTableName().empty()) { - errCode = GeneLogInfoForExistedDataInner(dbHandle_, identity, table, tableManager, false); - } } if (errCode != E_OK) { LOGE("[CreateDistributedTable] generate log isUpgraded %d failed %d.", static_cast(isUpgraded), errCode); @@ -427,16 +347,27 @@ int SQLiteSingleVerRelationalStorageExecutor::UpgradeDistributedTable(const std: // new table should has same or compatible upgrade TableInfo tableInfo = schema.GetTable(tableName); errCode = tableInfo.CompareWithTable(newTableInfo, schema.GetSchemaVersion()); - if (errCode == -E_RELATIONAL_TABLE_INCOMPATIBLE) { - LOGE("[UpgradeDistributedTable] Not support with incompatible upgrade."); - return -E_SCHEMA_MISMATCH; - } else if (errCode == -E_RELATIONAL_TABLE_EQUAL) { - LOGD("[UpgradeDistributedTable] schema has not changed."); - // update table if tableName changed - schema.RemoveRelationalTable(tableName); - tableInfo.SetTableName(tableName); - schema.AddRelationalTable(tableInfo); - return E_OK; + bool onceDropped = false; + int ret = IsTableOnceDropped(tableName, onceDropped); + if (ret != E_OK) { + LOGE("[UpgradeDistributedTable] Get table %s dropped status fail %d.", + DBCommon::StringMiddleMasking(tableName).c_str(), ret); + return ret; + } + LOGI("[UpgradeDistributedTable] table name is %s length is %zu, the dropped status is %d, errCode is %d", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), onceDropped, errCode); + if (!onceDropped) { + if (errCode == -E_RELATIONAL_TABLE_INCOMPATIBLE) { + LOGE("[UpgradeDistributedTable] Not support with incompatible upgrade."); + return -E_SCHEMA_MISMATCH; + } else if (errCode == -E_RELATIONAL_TABLE_EQUAL) { + LOGD("[UpgradeDistributedTable] schema has not changed."); + // update table if tableName changed + schema.RemoveRelationalTable(tableName); + tableInfo.SetTableName(tableName); + schema.AddRelationalTable(tableInfo); + return E_OK; + } } schemaChanged = true; @@ -765,63 +696,19 @@ static size_t GetDataItemSerialSize(DataItem &item, size_t appendLen) int SQLiteSingleVerRelationalStorageExecutor::GetKvData(const Key &key, Value &value) const { - static const std::string SELECT_META_VALUE_SQL = "SELECT value FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + - "metadata WHERE key=?;"; - sqlite3_stmt *statement = nullptr; - int errCode = SQLiteUtils::GetStatement(dbHandle_, SELECT_META_VALUE_SQL, statement); - if (errCode != E_OK) { - goto END; - } - - errCode = SQLiteUtils::BindBlobToStatement(statement, 1, key, false); // first arg. - if (errCode != E_OK) { - goto END; - } - - errCode = SQLiteUtils::StepWithRetry(statement, isMemDb_); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = -E_NOT_FOUND; - goto END; - } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - goto END; - } + return SQLiteRelationalUtils::GetKvData(dbHandle_, isMemDb_, key, value); +} - errCode = SQLiteUtils::GetColumnBlobValue(statement, 0, value); // only one result. -END: - int ret = E_OK; - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode != E_OK ? errCode : ret; +int SQLiteSingleVerRelationalStorageExecutor::GetKvDataByPrefixKey(const Key &keyPrefix, + std::map &data) const +{ + std::string metaTableName = std::string(DBConstant::RELATIONAL_PREFIX) + "metadata"; + return SqliteMetaExecutor::GetMetaDataByPrefixKey(dbHandle_, isMemDb_, metaTableName, keyPrefix, data); } int SQLiteSingleVerRelationalStorageExecutor::PutKvData(const Key &key, const Value &value) const { - static const std::string INSERT_META_SQL = "INSERT OR REPLACE INTO " + std::string(DBConstant::RELATIONAL_PREFIX) + - "metadata VALUES(?,?);"; - sqlite3_stmt *statement = nullptr; - int errCode = SQLiteUtils::GetStatement(dbHandle_, INSERT_META_SQL, statement); - if (errCode != E_OK) { - return errCode; - } - - errCode = SQLiteUtils::BindBlobToStatement(statement, 1, key, false); // 1 means key index - if (errCode != E_OK) { - LOGE("[SingleVerExe][BindPutKv]Bind key error:%d", errCode); - goto ERROR; - } - - errCode = SQLiteUtils::BindBlobToStatement(statement, 2, value, true); // 2 means value index - if (errCode != E_OK) { - LOGE("[SingleVerExe][BindPutKv]Bind value error:%d", errCode); - goto ERROR; - } - errCode = SQLiteUtils::StepWithRetry(statement, isMemDb_); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - } -ERROR: - int ret = E_OK; - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode != E_OK ? errCode : ret; + return SQLiteRelationalUtils::PutKvData(dbHandle_, isMemDb_, key, value); } int SQLiteSingleVerRelationalStorageExecutor::DeleteMetaData(const std::vector &keys) const @@ -1008,10 +895,8 @@ int SQLiteSingleVerRelationalStorageExecutor::CheckDataConflictDefeated(const Da isDefeated = false; // no need to solve conflict except miss query data return E_OK; } - if (!isExist || dataItem.dev != logInfoGet.device) { - // defeated if item timestamp is earlier than raw data - isDefeated = (dataItem.timestamp <= logInfoGet.timestamp); - } + // defeated if item timestamp is earlier than raw data + isDefeated = (dataItem.timestamp < logInfoGet.timestamp); return E_OK; } @@ -1365,6 +1250,7 @@ int SQLiteSingleVerRelationalStorageExecutor::IsTableOnceDropped(const std::stri int errCode = GetKvData(key, value); if (errCode == E_OK) { onceDropped = true; + LOGW("[RDBExecutor] Table %s once dropped!", DBCommon::StringMiddleMasking(tableName).c_str()); return E_OK; } else if (errCode == -E_NOT_FOUND) { onceDropped = false; @@ -1422,7 +1308,7 @@ int SQLiteSingleVerRelationalStorageExecutor::CheckAndCleanDistributedTable(cons } missingTables.emplace_back(tableName); } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - LOGE("Check distributed table failed. %d", errCode); + LOGE("[CheckAndCleanDisTable]Check distributed table failed. %d", errCode); break; } errCode = E_OK; // Check result ok for distributed table is still exists @@ -1545,15 +1431,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetMaxTimestamp(const std::vector< int SQLiteSingleVerRelationalStorageExecutor::SetLogTriggerStatus(bool status) { - const std::string key = "log_trigger_switch"; - std::string val = status ? "true" : "false"; - std::string sql = "INSERT OR REPLACE INTO " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata" + - " VALUES ('" + key + "', '" + val + "')"; - int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); - if (errCode != E_OK) { - LOGE("Set log trigger to %s failed. errCode=%d", val.c_str(), errCode); - } - return errCode; + return SQLiteRelationalUtils::SetLogTriggerStatus(dbHandle_, status); } namespace { @@ -1810,6 +1688,16 @@ int SQLiteSingleVerRelationalStorageExecutor::CleanCloudDataAndLogOnUserTable(co return errCode; } +int SQLiteSingleVerRelationalStorageExecutor::GetFlagIsLocalCount(const std::string &logTableName, int32_t &count) +{ + std::string sql = "SELECT count(*) from " + logTableName + " WHERE FLAG&0x02 = 0x02;"; + int errCode = SQLiteUtils::GetCountBySql(dbHandle_, sql, count); + if (errCode != E_OK) { + LOGW("[RDBExecutor] get mark local count from log table failed: %d", errCode); + } + return errCode; +} + int SQLiteSingleVerRelationalStorageExecutor::ChangeCloudDataFlagOnLogTable(const std::string &logTableName) { std::string cleanLogSql = "UPDATE " + logTableName + " SET " + CloudDbConstant::FLAG + " = " + @@ -1845,7 +1733,7 @@ int SQLiteSingleVerRelationalStorageExecutor::SetDataOnUserTableWithLogicDelete( // here just clear updateCursor func, fail will not influence other function (void)CreateFuncUpdateCursor(context, nullptr); if (errCode != E_OK) { - LOGE("Failed to change cloud data flag on usertable, %d.", errCode); + LOGE("Failed to change cloud data flag on userTable, %d.", errCode); return errCode; } // clear some column when data is logicDelete or physical delete @@ -1853,7 +1741,7 @@ int SQLiteSingleVerRelationalStorageExecutor::SetDataOnUserTableWithLogicDelete( " = '', " + SHARING_RESOURCE + " = '' WHERE (" + FLAG_IS_LOGIC_DELETE + ") OR (" + DATA_IS_DELETE + ");"; errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); if (errCode != E_OK) { - LOGE("Failed to deal logic delete data flag on usertable, %d.", errCode); + LOGE("Failed to deal logic delete data flag on userTable, %d.", errCode); return errCode; } LOGI("removeData on userTable:%s length:%zu finish and cursor is %llu.", @@ -2014,19 +1902,67 @@ int SQLiteSingleVerRelationalStorageExecutor::GetLockStatusByGid(const std::stri } int SQLiteSingleVerRelationalStorageExecutor::UpdateHashKey(DistributedTableMode mode, const TableInfo &tableInfo, - TableSyncType syncType) + TableSyncType syncType, const std::string &localIdentity) { - auto tableManager = LogTableManagerFactory::GetTableManager(mode, syncType); + if (tableInfo.GetIdentifyKey().size() == 1u && tableInfo.GetIdentifyKey().at(0) == "rowid") { + return UpdateHashKeyWithOutPk(mode, tableInfo, syncType, localIdentity); + } + auto tableManager = LogTableManagerFactory::GetTableManager(tableInfo, mode, syncType); auto logName = DBCommon::GetLogTableName(tableInfo.GetTableName()); - std::string sql = "UPDATE " + logName + " SET hash_key = hash_key || '_old' where data_key in " + - "(select _rowid_ from '" + tableInfo.GetTableName() + "');"; + std::string sql = "UPDATE OR REPLACE " + logName + " SET hash_key = hash_key || '_old' where data_key in " + + "(select _rowid_ from '" + tableInfo.GetTableName() + "') AND device = '';"; int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); if (errCode != E_OK) { return errCode; } - sql = "UPDATE " + logName + " SET hash_key = data.hash_value FROM (SELECT _rowid_, " + + sql = "UPDATE OR REPLACE " + logName + " SET hash_key = data.hash_value FROM (SELECT _rowid_, " + tableManager->CalcPrimaryKeyHash("dataTable.", tableInfo, "") + " AS hash_value " + - "FROM '" + tableInfo.GetTableName() + "' AS dataTable) AS data WHERE data._rowid_ = " + logName + ".data_key;"; + "FROM '" + tableInfo.GetTableName() + "' AS dataTable) AS data WHERE data._rowid_ = " + logName + + ".data_key AND device = '';"; + return SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); +} + +int SQLiteSingleVerRelationalStorageExecutor::UpdateHashKeyWithOutPk( + DistributedTableMode mode, const TableInfo &tableInfo, TableSyncType syncType, const std::string &localIdentity) +{ + auto tableManager = LogTableManagerFactory::GetTableManager(tableInfo, mode, syncType); + auto logName = DBCommon::GetLogTableName(tableInfo.GetTableName()); + std::string extendStr = "_tmp"; + std::string tmpTable = logName + extendStr; + std::string sql = tableManager->GetCreateRelationalLogTableSql(tableInfo, extendStr); + int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + if (errCode != E_OK) { + return errCode; + } + sql = "INSERT OR REPLACE INTO " + tmpTable + " SELECT * FROM " + logName + " WHERE data_key != -1;"; + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + if (errCode != E_OK) { + return errCode; + } + + sql = "UPDATE " + logName + " SET flag = flag | 0x01, data_key = -1 WHERE data_key IN " + "(SELECT _rowid_ FROM '" + + tableInfo.GetTableName() + "');"; + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + if (errCode != E_OK) { + return errCode; + } + + sql = "UPDATE " + tmpTable + " SET hash_key = data.hash_value FROM (SELECT _rowid_, " + + tableManager->CalcPrimaryKeyHash("dataTable.", tableInfo, localIdentity) + " AS hash_value " + "FROM '" + + tableInfo.GetTableName() + "' AS dataTable) AS data WHERE data._rowid_ = " + tmpTable + + ".data_key AND device = '';"; + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + if (errCode != E_OK) { + return errCode; + } + + sql = "INSERT OR REPLACE INTO " + logName + " SELECT * FROM " + tmpTable + ";"; + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + if (errCode != E_OK) { + return errCode; + } + + sql = "DROP TABLE " + tmpTable + ";"; return SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.h index 8acac8e99787cd73959897cdbbc8e805946a649d..c4287638c5eeb46f6f829dcb2c07b3a9104cf93b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.h @@ -80,6 +80,7 @@ public: // operation of meta data int GetKvData(const Key &key, Value &value) const; + int GetKvDataByPrefixKey(const Key &keyPrefix, std::map &data) const; int PutKvData(const Key &key, const Value &value) const; int DeleteMetaData(const std::vector &keys) const; int DeleteMetaDataByPrefixKey(const Key &keyPrefix) const; @@ -225,7 +226,7 @@ public: void SetUploadConfig(int32_t maxUploadCount, int32_t maxUploadSize); - int InitCursorToMeta(const std::string &tableName); + int InitCursorToMeta(const std::string &tableName) const; void SetTableSchema(const TableSchema &tableSchema); @@ -235,10 +236,12 @@ public: int GetCloudDataCount(const std::string &tableName, DownloadData &downloadData, int64_t &count); - int UpdateExtendField(const std::string &tableName, const std::set &extendColNames); + int UpdateExtendField(const std::string &tableName, const std::set &extendColNames, + const std::string &condition = ""); int UpdateDeleteDataExtendField(const std::string &tableName, const std::string &lowVersionExtendColName, const std::set &oldExtendColNames, const std::set &extendColNames); + int GetDownloadingAssetsCount(const TableSchema &tableSchema, int32_t &totalCount); int GetDownloadingCount(const std::string &tableName, int32_t &count); @@ -261,10 +264,22 @@ public: int CompareSchemaTableColumns(const std::string &tableName); - int UpdateHashKey(DistributedTableMode mode, const TableInfo &tableInfo, TableSyncType syncType); + int UpdateHashKey(DistributedTableMode mode, const TableInfo &tableInfo, TableSyncType syncType, + const std::string &localIdentity); void SetTableMode(DistributedTableMode mode); + + int GetFlagIsLocalCount(const std::string &logTableName, int32_t &count); + + void ClearLogOfMismatchedData(const std::string &tableName); + + int IsTableOnceDropped(const std::string &tableName, bool &onceDropped); + + void RecoverNullExtendLog(const TrackerSchema &trackerSchema, const TrackerTable &table); private: + int UpdateHashKeyWithOutPk(DistributedTableMode mode, const TableInfo &tableInfo, TableSyncType syncType, + const std::string &localIdentity); + int DoCleanLogs(const std::vector &tableNameList, const RelationalSchemaObject &localSchema); int DoCleanLogAndData(const std::vector &tableNameList, @@ -329,9 +344,6 @@ private: int GeneLogInfoForExistedData(sqlite3 *db, const std::string &identity, const TableInfo &tableInfo, std::unique_ptr &logMgrPtr, bool isTrackerTable); - int GeneLogInfoForExistedDataInner(sqlite3 *db, const std::string &identity, const TableInfo &tableInfo, - std::unique_ptr &logMgrPtr, bool isTrackerTable); - int CleanExtendAndCursorForDeleteData(const std::string &tableName); int GetCloudDataForSync(const CloudUploadRecorder &uploadRecorder, sqlite3_stmt *statement, @@ -418,8 +430,6 @@ private: int DeleteCloudData(const std::string &tableName, const VBucket &vBucket, const TableSchema &tableSchema, const TrackerTable &trackerTable); - int IsTableOnceDropped(const std::string &tableName, bool &onceDropped); - int OnlyUpdateLogTable(const VBucket &vBucket, const TableSchema &tableSchema, OpType opType); int BindUpdateVersionStatement(const VBucket &vBucket, const Bytes &hashKey, sqlite3_stmt *&stmt); @@ -526,6 +536,8 @@ private: bool AbortGetDownloadAssetGidIfNeed(const TableSchema &tableSchema, const std::string &gid, bool abortWithLimit, uint32_t &count); + int RecoverNullExtendLogInner(const TrackerSchema &trackerSchema, const TrackerTable &table); + static constexpr const char *CONSISTENT_FLAG = "0x20"; static constexpr const char *UPDATE_FLAG_CLOUD = "flag = 0"; static constexpr const char *UPDATE_FLAG_WAIT_COMPENSATED_SYNC = "flag = flag | 0x10"; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor_extend.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor_extend.cpp index 007fe7e5abddb3f577b08eae027741a179d2a3fe..e429a6008c23f1571d3fdc00aca89297fe7cec85 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor_extend.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor_extend.cpp @@ -369,11 +369,18 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanLogs(const std::vector &extendColNames) + const std::set &extendColNames, const std::string &condition) { bool isLogTableExist = false; int errCode = SQLiteUtils::CheckTableExists(dbHandle_, DBCommon::GetLogTableName(tableName), isLogTableExist); @@ -1822,6 +1820,7 @@ int SQLiteSingleVerRelationalStorageExecutor::UpdateExtendField(const std::strin } sql.pop_back(); sql += ") from " + tableName + " as data where log.data_key = data." + std::string(DBConstant::SQLITE_INNER_ROWID); + sql += condition; sqlite3_stmt *stmt = nullptr; errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); if (errCode != E_OK) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp index 73cb0655cf55835e317a431bf7a865293c1e6f6f..dad090304caaadf71596fefcf069c0e9b71a90c8 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp @@ -418,8 +418,8 @@ int SQLiteSingleVerRelationalStorageExecutor::GetOrInitTrackerSchemaFromMeta(Rel if (!schema.ToSchemaString().empty()) { return E_OK; } - const Key schemaKey(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.begin(), - DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.end()); + const Key schemaKey(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY, + DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY + strlen(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY)); Value schemaVal; int errCode = GetKvData(schemaKey, schemaVal); // save schema to meta_data if (errCode != E_OK) { @@ -480,7 +480,8 @@ int SQLiteSingleVerRelationalStorageExecutor::GetClearWaterMarkTables( const std::vector &tableReferenceProperty, const RelationalSchemaObject &schema, std::set &clearWaterMarkTables) { - std::set changeTables = schema.CompareReferenceProperty(tableReferenceProperty); + bool isRefNotSet = false; + std::set changeTables = schema.CompareReferenceProperty(tableReferenceProperty, isRefNotSet); for (const auto &table : changeTables) { std::string logTableName = DBCommon::GetLogTableName(table); bool isExists = false; @@ -505,8 +506,10 @@ int SQLiteSingleVerRelationalStorageExecutor::GetClearWaterMarkTables( clearWaterMarkTables.insert(table); } } - LOGI("[GetClearWaterMarkTables] clearWaterMarkTables size = %zu.", clearWaterMarkTables.size()); - return E_OK; + LOGI("[GetClearWaterMarkTables] clearWaterMarkTables size = %zu, changeTables size = %zu, isFirst:%d.", + clearWaterMarkTables.size(), changeTables.size(), isRefNotSet); + // If reference set for the first time and has no data, or the reference has not changed, return E_OK. + return ((isRefNotSet && clearWaterMarkTables.empty()) || changeTables.empty()) ? E_OK : -E_TABLE_REFERENCE_CHANGED; } int SQLiteSingleVerRelationalStorageExecutor::UpgradedLogForExistedData(const TableInfo &tableInfo, bool schemaChanged) @@ -614,34 +617,7 @@ int SQLiteSingleVerRelationalStorageExecutor::ClearAllTempSyncTrigger() int SQLiteSingleVerRelationalStorageExecutor::CleanTrackerData(const std::string &tableName, int64_t cursor, bool isOnlyTrackTable) { - std::string sql; - if (isOnlyTrackTable) { - sql = "DELETE FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log"; - } else { - sql = "UPDATE " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log SET extend_field = NULL"; - } - sql += " where data_key = -1 and cursor <= ?;"; - sqlite3_stmt *statement = nullptr; - int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, statement); - if (errCode != E_OK) { // LCOV_EXCL_BR_LINE - LOGE("get clean tracker data stmt failed %d.", errCode); - return errCode; - } - errCode = SQLiteUtils::BindInt64ToStatement(statement, 1, cursor); - int ret = E_OK; - if (errCode != E_OK) { // LCOV_EXCL_BR_LINE - LOGE("bind clean tracker data stmt failed %d.", errCode); - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode; - } - errCode = SQLiteUtils::StepWithRetry(statement); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { // LCOV_EXCL_BR_LINE - errCode = E_OK; - } else { - LOGE("clean tracker step failed: %d.", errCode); - } - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode == E_OK ? ret : errCode; + return SQLiteRelationalUtils::CleanTrackerData(dbHandle_, tableName, cursor, isOnlyTrackTable); } int SQLiteSingleVerRelationalStorageExecutor::CreateSharedTable(const TableSchema &tableSchema) @@ -774,8 +750,12 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanShareTableDataAndLog(const { int errCode = E_OK; for (const auto &tableName: tableNameList) { + int32_t count = 0; + std::string logTableName = DBCommon::GetLogTableName(tableName); + (void)GetFlagIsLocalCount(logTableName, count); + LOGI("[DoCleanShareTableDataAndLog]flag is local in table:%s, len:%zu, count:%d, before remove device data.", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), count); if (isLogicDelete_) { - std::string logTableName = DBCommon::GetLogTableName(tableName); errCode = SetDataOnShareTableWithLogicDelete(tableName, logTableName); } else { errCode = CleanShareTable(tableName); @@ -785,6 +765,9 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanShareTableDataAndLog(const DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), isLogicDelete_ ? 1 : 0, errCode); return errCode; } + (void)GetFlagIsLocalCount(logTableName, count); + LOGI("[DoCleanShareTableDataAndLog]flag is local in table:%s, len:%zu, count:%d, after remove device data.", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), count); } return errCode; } @@ -1144,7 +1127,7 @@ int SQLiteSingleVerRelationalStorageExecutor::BindStmtWithCloudGidInner(const st int SQLiteSingleVerRelationalStorageExecutor::RenewTableTrigger(DistributedTableMode mode, const TableInfo &tableInfo, TableSyncType syncType, const std::string &localIdentity) { - auto tableManager = LogTableManagerFactory::GetTableManager(mode, syncType); + auto tableManager = LogTableManagerFactory::GetTableManager(tableInfo, mode, syncType); return tableManager->AddRelationalLogTableTrigger(dbHandle_, tableInfo, localIdentity); } @@ -1850,6 +1833,10 @@ void SQLiteSingleVerRelationalStorageExecutor::MarkFlagAsUploadFinished(const st sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(dbHandle_, CloudStorageUtils::GetUpdateUploadFinishedSql(tableName, isExistAssetsDownload), stmt); + if (errCode != E_OK) { + LOGW("[Storage Executor] Get statement fail! errCode:%d", errCode); + return; + } int index = 1; errCode = SQLiteUtils::BindInt64ToStatement(stmt, index++, timestamp); if (errCode != E_OK) { @@ -2005,5 +1992,106 @@ void SQLiteSingleVerRelationalStorageExecutor::CheckAndCreateTrigger(const Table auto tableManager = std::make_unique(); tableManager->CheckAndCreateTrigger(dbHandle_, table, ""); } + +void SQLiteSingleVerRelationalStorageExecutor::ClearLogOfMismatchedData(const std::string &tableName) +{ + bool isLogTableExist = false; + int errCode = SQLiteUtils::CheckTableExists(dbHandle_, DBCommon::GetLogTableName(tableName), isLogTableExist); + if (!isLogTableExist) { + return; + } + std::string sql = "SELECT data_key from " + DBCommon::GetLogTableName(tableName) + " WHERE data_key NOT IN " + + "(SELECT _rowid_ FROM " + tableName + ") AND data_key != -1"; + sqlite3_stmt *stmt = nullptr; + errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); + if (errCode != E_OK) { + LOGW("[RDBExecutor][ClearMisLog] Get stmt failed, %d", errCode); + return; + } + std::vector dataKeys; + std::string misDataKeys = "("; + errCode = SQLiteUtils::StepWithRetry(stmt, false); + while (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + int dataKey = sqlite3_column_int64(stmt, 0); + dataKeys.push_back(dataKey); + misDataKeys += std::to_string(dataKey) + ","; + errCode = SQLiteUtils::StepWithRetry(stmt, false); + } + SQLiteUtils::ResetStatement(stmt, true, errCode); + stmt = nullptr; + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + LOGW("[RDBExecutor][ClearMisLog] Step failed. %d", errCode); + return; + } + if (dataKeys.empty()) { + return; + } + misDataKeys.pop_back(); + misDataKeys += ")"; + LOGW("[RDBExecutor][ClearMisLog] Mismatched:%s", misDataKeys.c_str()); + std::string delSql = "DELETE FROM " + DBCommon::GetLogTableName(tableName) + " WHERE data_key IN " + misDataKeys; + errCode = SQLiteUtils::GetStatement(dbHandle_, delSql, stmt); + if (errCode != E_OK) { + LOGW("[RDBExecutor][ClearMisLog] Get del stmt failed, %d", errCode); + return; + } + errCode = SQLiteUtils::StepWithRetry(stmt, false); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + LOGW("[RDBExecutor][ClearMisLog] Step del failed, %d", errCode); + } + SQLiteUtils::ResetStatement(stmt, true, errCode); +} + +void SQLiteSingleVerRelationalStorageExecutor::RecoverNullExtendLog(const TrackerSchema &trackerSchema, + const TrackerTable &table) +{ + if (trackerSchema.extendColNames.empty()) { + return; + } + std::string sql = "SELECT COUNT(1) FROM " + DBCommon::GetLogTableName(trackerSchema.tableName) + + " WHERE (json_valid(extend_field) = 0 OR json_type(extend_field) IS NOT 'object') AND data_key != -1"; + if (!SQLiteRelationalUtils::ExecuteCheckSql(dbHandle_, sql).second) { + return; + } + auto errCode = SQLiteUtils::BeginTransaction(dbHandle_, TransactType::IMMEDIATE); + if (errCode != E_OK) { + LOGE("[RDBExecutor][RecoverTracker] Begin transaction fail %d", errCode); + return; + } + errCode = RecoverNullExtendLogInner(trackerSchema, table); + int changeRow = 0; + if (errCode == E_OK) { + changeRow = sqlite3_changes(dbHandle_); + errCode = SQLiteUtils::CommitTransaction(dbHandle_); + } else { + (void)SQLiteUtils::RollbackTransaction(dbHandle_); + } + LOGI("[RDBExecutor][RecoverTracker] Recover tracker[%s][%zu] finished[%d] changeRow[%d]", + DBCommon::StringMiddleMasking(trackerSchema.tableName).c_str(), trackerSchema.tableName.size(), + errCode, changeRow); +} + +int SQLiteSingleVerRelationalStorageExecutor::RecoverNullExtendLogInner(const TrackerSchema &trackerSchema, + const TrackerTable &table) +{ + std::vector> actions; + actions.emplace_back([this]() { + return SetLogTriggerStatus(false); + }); + actions.emplace_back([this, &table]() { + return SQLiteUtils::ExecuteRawSQL(dbHandle_, table.GetTempUpdateLogCursorTriggerSql()); + }); + actions.emplace_back([this, &trackerSchema]() { + return UpdateExtendField(trackerSchema.tableName, trackerSchema.extendColNames, + " AND (json_valid(log.extend_field) = 0 OR json_type(log.extend_field) IS NOT 'object')"); + }); + actions.emplace_back([this]() { + return ClearAllTempSyncTrigger(); + }); + actions.emplace_back([this]() { + return SetLogTriggerStatus(true); + }); + return SQLiteRelationalUtils::ExecuteListAction(actions); +} } // namespace DistributedDB #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.cpp index 5569bfa9972c6c0c32d8640719aafb6774dbb287..f384da2373f92a8a5fc3c15dacbfded246f46606 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.cpp @@ -50,11 +50,8 @@ int SqliteCloudKvExecutorUtils::GetCloudData(const CloudSyncConfig &config, cons } while (errCode == E_OK); LOGI("[SqliteCloudKvExecutorUtils] Get cloud sync data, insData:%u, upData:%u, delLog:%u errCode:%d total:%" PRIu32, data.insData.record.size(), data.updData.record.size(), data.delData.extend.size(), errCode, totalSize); - if (errCode != -E_UNFINISHED) { - token.ReleaseCloudQueryStmt(); - } else if (isMemory && UpdateBeginTimeForMemoryDB(token, data)) { - token.ReleaseCloudQueryStmt(); - } + UpdateBeginTime(token, data); + token.ReleaseCloudQueryStmt(); return errCode; } @@ -73,7 +70,7 @@ Timestamp SqliteCloudKvExecutorUtils::GetMaxTimeStamp(const std::vector return maxTimeStamp; } -bool SqliteCloudKvExecutorUtils::UpdateBeginTimeForMemoryDB(SQLiteSingleVerContinueToken &token, +void SqliteCloudKvExecutorUtils::UpdateBeginTime(SQLiteSingleVerContinueToken &token, const CloudSyncData &data) { Timestamp maxTimeStamp = 0; @@ -93,10 +90,9 @@ bool SqliteCloudKvExecutorUtils::UpdateBeginTimeForMemoryDB(SQLiteSingleVerConti } if (maxTimeStamp > token.GetQueryBeginTime()) { token.SetNextBeginTime("", maxTimeStamp); - return true; + return; } - LOGW("[SqliteCloudKvExecutorUtils] The start time of the in memory database has not been updated."); - return false; + LOGW("[SqliteCloudKvExecutorUtils] The start time of the database has not been updated."); } int SqliteCloudKvExecutorUtils::GetCloudDataForSync(const CloudSyncConfig &config, const CloudUploadRecorder &recorder, @@ -817,6 +813,20 @@ int SqliteCloudKvExecutorUtils::BindSyncDataStmt(sqlite3_stmt *dataStmt, const D return errCode; } +int64_t SqliteCloudKvExecutorUtils::GetModifyTime(int64_t timestamp) +{ + uint64_t curTime = 0; + int64_t modifyTime = timestamp; + if (TimeHelper::GetSysCurrentRawTime(curTime) == E_OK) { + if (curTime < static_cast(INT64_MAX)) { + if (modifyTime > static_cast(curTime)) { + modifyTime = static_cast(curTime); + } + } + } + return modifyTime; +} + int SqliteCloudKvExecutorUtils::BindCloudDataStmt(sqlite3_stmt *dataStmt, const DataItem &dataItem, int &index) { int errCode = SQLiteUtils::BindInt64ToStatement(dataStmt, index++, dataItem.modifyTime); @@ -922,6 +932,9 @@ int SqliteCloudKvExecutorUtils::FillCloudGid(const FillGidParam ¶m, const Cl auto [db, ignoreEmptyGid] = param; sqlite3_stmt *logStmt = nullptr; int errCode = SQLiteUtils::GetStatement(db, GetOperateLogSql(TransToOpType(type)), logStmt); + if (errCode != E_OK) { + return errCode; + } ResFinalizer finalizerData([logStmt]() { sqlite3_stmt *statement = logStmt; int ret = E_OK; @@ -960,10 +973,9 @@ int SqliteCloudKvExecutorUtils::FillCloudGid(const FillGidParam ¶m, const Cl SQLiteUtils::ResetStatement(logStmt, false, errCode); MarkUploadSuccess(param, data, user, i); // ignored version record - if (i >= data.timestamp.size()) { - continue; + if (i < data.timestamp.size()) { + recorder.RecordUploadRecord(CloudDbConstant::CLOUD_KV_TABLE_NAME, data.hashKey[i], type, data.timestamp[i]); } - recorder.RecordUploadRecord(CloudDbConstant::CLOUD_KV_TABLE_NAME, data.hashKey[i], type, data.timestamp[i]); } return E_OK; } @@ -1029,9 +1041,11 @@ int SqliteCloudKvExecutorUtils::BindUpdateTimestampStmt(sqlite3_stmt *dataStmt, LOGE("[SqliteCloudKvExecutorUtils] Bind timestamp failed %d", errCode); return errCode; } - errCode = SQLiteUtils::BindInt64ToStatement(dataStmt, currentBindIndex++, dataItem.modifyTime); + int64_t modifyTime = GetModifyTime(dataItem.modifyTime); + errCode = SQLiteUtils::BindInt64ToStatement(dataStmt, currentBindIndex++, modifyTime); if (errCode != E_OK) { LOGE("[SqliteCloudKvExecutorUtils] Bind modifyTime failed %d", errCode); + return errCode; } errCode = SQLiteUtils::BindBlobToStatement(dataStmt, currentBindIndex++, dataItem.hashKey); if (errCode != E_OK) { @@ -1069,8 +1083,9 @@ std::pair SqliteCloudKvExecutorUtils::GetDataItem(int index, Down if (dataItem.origDev == dev) { dataItem.origDev = ""; } - dataItem.timestamp = static_cast(static_cast(dataItem.modifyTime) + downloadData.timeOffset); - dataItem.writeTimestamp = dataItem.timestamp; // writeTimestamp is process conflict time + int64_t timestamp = GetModifyTime(dataItem.modifyTime); + dataItem.timestamp = static_cast(timestamp + downloadData.timeOffset); + dataItem.writeTimestamp = static_cast(timestamp); // writeTimestamp is process conflict time return res; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.h index ca747b6560042b7dc6e7318cbbd3d184c02cc9f9..d256c5796a64d3a270b1399763879f54ad83d3f4 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.h @@ -61,6 +61,7 @@ public: static int QueryCloudGid(sqlite3 *db, bool isMemory, const std::string &user, const QuerySyncObject &querySyncObject, std::vector &cloudGid); + private: using UploadDetail = std::pair; static int GetCloudDataForSync(const CloudSyncConfig &config, const CloudUploadRecorder &recorder, @@ -156,10 +157,12 @@ private: static Timestamp GetMaxTimeStamp(const std::vector &dataExtend); - static bool UpdateBeginTimeForMemoryDB(SQLiteSingleVerContinueToken &token, const CloudSyncData &data); + static void UpdateBeginTime(SQLiteSingleVerContinueToken &token, const CloudSyncData &data); static int BindFillGidLogStmt(sqlite3_stmt *logStmt, const std::string &user, const DataItem &dataItem, const VBucket &uploadExtend, const CloudWaterType &type); + + static int64_t GetModifyTime(int64_t timestamp); private: static void MarkUploadSuccess(const FillGidParam ¶m, const CloudSyncBatch &data, const std::string &user, size_t dataIndex); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.cpp index 25e473f28f2b6387370ea6d821ade9a0a71eaa98..ecdf5a42be95300d9c9e45465d79098d69949f1e 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.cpp @@ -86,8 +86,11 @@ int SqliteCloudKvStore::GetCloudTableSchema(const TableName &tableName, return -E_NOT_FOUND; } -int SqliteCloudKvStore::StartTransaction(TransactType type) +int SqliteCloudKvStore::StartTransaction(TransactType type, bool isAsyncDownload) { + if (isAsyncDownload) { + return StartTransactionForAsyncDownload(type); + } { std::lock_guard autoLock(transactionMutex_); if (transactionHandle_ != nullptr) { @@ -110,8 +113,11 @@ int SqliteCloudKvStore::StartTransaction(TransactType type) return errCode; } -int SqliteCloudKvStore::Commit() +int SqliteCloudKvStore::Commit(bool isAsyncDownload) { + if (isAsyncDownload) { + return CommitForAsyncDownload(); + } SQLiteSingleVerStorageExecutor *handle; { std::lock_guard autoLock(transactionMutex_); @@ -128,8 +134,11 @@ int SqliteCloudKvStore::Commit() return errCode; } -int SqliteCloudKvStore::Rollback() +int SqliteCloudKvStore::Rollback(bool isAsyncDownload) { + if (isAsyncDownload) { + return RollbackForAsyncDownload(); + } SQLiteSingleVerStorageExecutor *handle; { std::lock_guard autoLock(transactionMutex_); @@ -146,18 +155,81 @@ int SqliteCloudKvStore::Rollback() return errCode; } +int SqliteCloudKvStore::StartTransactionForAsyncDownload(TransactType type) +{ + { + std::lock_guard autoLock(transactionMutex_); + if (asyncDownloadTransactionHandle_ != nullptr) { + LOGW("[SqliteCloudKvStore] async download transaction has been started"); + return E_OK; + } + } + auto [errCode, handle] = storageHandle_->GetStorageExecutor(type == TransactType::IMMEDIATE); + if (errCode != E_OK) { + return errCode; + } + if (handle == nullptr) { + LOGE("[SqliteCloudKvStore] get handle return null"); + return -E_INTERNAL_ERROR; + } + errCode = handle->StartTransaction(type); + std::lock_guard autoLock(transactionMutex_); + asyncDownloadTransactionHandle_ = handle; + LOGD("[SqliteCloudKvStore] start async download transaction!"); + return errCode; +} + +int SqliteCloudKvStore::CommitForAsyncDownload() +{ + SQLiteSingleVerStorageExecutor *handle; + { + std::lock_guard autoLock(transactionMutex_); + if (asyncDownloadTransactionHandle_ == nullptr) { + LOGW("[SqliteCloudKvStore] no need to commit, transaction has not been started"); + return E_OK; + } + handle = asyncDownloadTransactionHandle_; + asyncDownloadTransactionHandle_ = nullptr; + } + int errCode = handle->Commit(); + storageHandle_->RecycleStorageExecutor(handle); + LOGD("[SqliteCloudKvStore] commit transaction!"); + return errCode; +} + +int SqliteCloudKvStore::RollbackForAsyncDownload() +{ + SQLiteSingleVerStorageExecutor *handle; + { + std::lock_guard autoLock(transactionMutex_); + if (asyncDownloadTransactionHandle_ == nullptr) { + LOGW("[SqliteCloudKvStore] no need to rollback, transaction has not been started"); + return E_OK; + } + handle = asyncDownloadTransactionHandle_; + asyncDownloadTransactionHandle_ = nullptr; + } + int errCode = handle->Rollback(); + storageHandle_->RecycleStorageExecutor(handle); + LOGD("[SqliteCloudKvStore] rollback transaction!"); + return errCode; +} + int SqliteCloudKvStore::GetUploadCount([[gnu::unused]] const QuerySyncObject &query, const Timestamp ×tamp, bool isCloudForcePush, [[gnu::unused]] bool isCompensatedTask, int64_t &count) { - auto [db, isMemory] = GetTransactionDbHandleAndMemoryStatus(); - if (db == nullptr) { + auto [db, handle] = GetTransactionDbHandleAndMemoryStatus(false); + if (db == nullptr || handle == nullptr) { LOGE("[SqliteCloudKvStore] get upload count without transaction"); return -E_INTERNAL_ERROR; } int errCode = E_OK; - std::tie(errCode, count) = SqliteCloudKvExecutorUtils::CountCloudData(db, isMemory, timestamp, user_, + std::tie(errCode, count) = SqliteCloudKvExecutorUtils::CountCloudData(db, handle->IsMemory(), timestamp, user_, isCloudForcePush); + if (transactionHandle_ == nullptr) { + storageHandle_->RecycleStorageExecutor(handle); + } return errCode; } @@ -165,15 +237,18 @@ int SqliteCloudKvStore::GetAllUploadCount(const QuerySyncObject &query, const std::vector ×tampVec, bool isCloudForcePush, [[gnu::unused]] bool isCompensatedTask, int64_t &count) { - auto [db, isMemory] = GetTransactionDbHandleAndMemoryStatus(); - if (db == nullptr) { + auto [db, handle] = GetTransactionDbHandleAndMemoryStatus(false); + if (db == nullptr || handle == nullptr) { LOGE("[SqliteCloudKvStore] get upload count without transaction"); return -E_INTERNAL_ERROR; } int errCode = E_OK; QuerySyncObject queryObj = query; - std::tie(errCode, count) = SqliteCloudKvExecutorUtils::CountAllCloudData({ db, isMemory }, timestampVec, user_, - isCloudForcePush, queryObj); + std::tie(errCode, count) = SqliteCloudKvExecutorUtils::CountAllCloudData( + {db, handle->IsMemory()}, timestampVec, user_, isCloudForcePush, queryObj); + if (transactionHandle_ == nullptr) { + storageHandle_->RecycleStorageExecutor(handle); + } return errCode; } @@ -205,14 +280,17 @@ int SqliteCloudKvStore::GetCloudDataNext(ContinueToken &continueStmtToken, Cloud LOGE("[SqliteCloudKvStore] token is invalid"); return -E_INVALID_ARGS; } - auto [db, isMemory] = GetTransactionDbHandleAndMemoryStatus(); - if (db == nullptr) { + auto [db, handle] = GetTransactionDbHandleAndMemoryStatus(false); + if (db == nullptr || handle == nullptr) { LOGE("[SqliteCloudKvStore] the transaction has not been started, release the token"); ReleaseCloudDataToken(continueStmtToken); return -E_INTERNAL_ERROR; } - int errCode = SqliteCloudKvExecutorUtils::GetCloudData(GetCloudSyncConfig(), {db, isMemory}, recorder_, *token, - cloudDataResult); + int errCode = SqliteCloudKvExecutorUtils::GetCloudData( + GetCloudSyncConfig(), {db, handle->IsMemory()}, recorder_, *token, cloudDataResult); + if (transactionHandle_ == nullptr) { + storageHandle_->RecycleStorageExecutor(handle); + } if (errCode != -E_UNFINISHED) { ReleaseCloudDataToken(continueStmtToken); } else { @@ -239,25 +317,32 @@ int SqliteCloudKvStore::ReleaseCloudDataToken(ContinueToken &continueStmtToken) int SqliteCloudKvStore::GetInfoByPrimaryKeyOrGid([[gnu::unused]] const std::string &tableName, const VBucket &vBucket, DataInfoWithLog &dataInfoWithLog, [[gnu::unused]] VBucket &assetInfo) { - auto [db, isMemory] = GetTransactionDbHandleAndMemoryStatus(); - if (db == nullptr) { + auto [db, handle] = GetTransactionDbHandleAndMemoryStatus(false); + if (db == nullptr || handle == nullptr) { LOGE("[SqliteCloudKvStore] the transaction has not been started"); return -E_INTERNAL_ERROR; } int errCode = E_OK; - std::tie(errCode, dataInfoWithLog) = SqliteCloudKvExecutorUtils::GetLogInfo(db, isMemory, vBucket, user_); + std::tie(errCode, dataInfoWithLog) = SqliteCloudKvExecutorUtils::GetLogInfo(db, handle->IsMemory(), vBucket, user_); + if (transactionHandle_ == nullptr) { + storageHandle_->RecycleStorageExecutor(handle); + } return errCode; } int SqliteCloudKvStore::PutCloudSyncData([[gnu::unused]] const std::string &tableName, DownloadData &downloadData) { - auto [db, isMemory] = GetTransactionDbHandleAndMemoryStatus(); - if (db == nullptr) { + auto [db, handle] = GetTransactionDbHandleAndMemoryStatus(true); + if (db == nullptr || handle == nullptr) { LOGE("[SqliteCloudKvStore] the transaction has not been started"); return -E_INTERNAL_ERROR; } downloadData.timeOffset = storageHandle_->GetLocalTimeOffsetForCloud(); - return SqliteCloudKvExecutorUtils::PutCloudData(db, isMemory, downloadData); + int ret = SqliteCloudKvExecutorUtils::PutCloudData(db, handle->IsMemory(), downloadData); + if (transactionHandle_ == nullptr) { + storageHandle_->RecycleStorageExecutor(handle); + } + return ret; } int SqliteCloudKvStore::UpdateAssetStatusForAssetOnly(const std::string &tableName, VBucket &asset) @@ -273,26 +358,11 @@ int SqliteCloudKvStore::FillCloudLogAndAsset(OpType opType, const CloudSyncData LOGE("[SqliteCloudKvStore] get handle failed %d when fill log", errCode); return errCode; } - if (handle->IsMemory()) { - errCode = Commit(); - if (errCode != E_OK) { - LOGE("[SqliteCloudKvStore] commit failed %d before fill log", errCode); - storageHandle_->RecycleStorageExecutor(handle); - return errCode; - } - } sqlite3 *db = nullptr; (void)handle->GetDbHandle(db); errCode = SqliteCloudKvExecutorUtils::FillCloudLog({db, ignoreEmptyGid}, opType, data, user_, recorder_); - int ret = E_OK; - if (handle->IsMemory()) { - ret = StartTransaction(TransactType::DEFERRED); - if (ret != E_OK) { - LOGE("[SqliteCloudKvStore] restart transaction failed %d", ret); - } - } storageHandle_->RecycleStorageExecutor(handle); - return errCode == E_OK ? ret : errCode; + return errCode; } void SqliteCloudKvStore::FilterCloudVersionPrefixKey(std::vector> &changeValList) @@ -421,15 +491,26 @@ void SqliteCloudKvStore::SetUser(const std::string &user) user_ = user; } -std::pair SqliteCloudKvStore::GetTransactionDbHandleAndMemoryStatus() +std::pair SqliteCloudKvStore::GetTransactionDbHandleAndMemoryStatus( + bool isWrite) { std::lock_guard autoLock(transactionMutex_); if (transactionHandle_ == nullptr) { - return {nullptr, false}; + if (storageHandle_ == nullptr) { + return {nullptr, nullptr}; + } + auto [errCode, handle] = storageHandle_->GetStorageExecutor(isWrite); + if (errCode != E_OK) { + LOGE("[SqliteCloudKvStore] get handle failed %d when fill log", errCode); + return {nullptr, nullptr}; + } + sqlite3 *db = nullptr; + (void)handle->GetDbHandle(db); + return {db, handle}; } sqlite3 *db = nullptr; (void)transactionHandle_->GetDbHandle(db); - return {db, transactionHandle_->IsMemory()}; + return {db, transactionHandle_}; } void SqliteCloudKvStore::RegisterObserverAction(const KvStoreObserver *observer, const ObserverAction &action) @@ -552,6 +633,8 @@ void SqliteCloudKvStore::SetCloudSyncConfig(const CloudSyncConfig &config) { std::lock_guard autoLock(configMutex_); config_ = config; + LOGI("[SqliteCloudKvStore] SetCloudSyncConfig value:[%" PRId32 ", %" PRId32 ", %" PRId32 ", %d]", + config_.maxUploadCount, config_.maxUploadSize, config_.maxRetryConflictTimes, config_.isSupportEncrypt); } CloudSyncConfig SqliteCloudKvStore::GetCloudSyncConfig() const diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.h index 2f3c98b134f5a7ce9180837f48343c04bb27b706..9e0841d390513f86cec1a9abcad13540ddfa66f1 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.h @@ -37,11 +37,11 @@ public: int GetCloudTableSchema(const TableName &tableName, TableSchema &tableSchema) override; - int StartTransaction(TransactType type) override; + int StartTransaction(TransactType type, bool isAsyncDownload = false) override; - int Commit() override; + int Commit(bool isAsyncDownload = false) override; - int Rollback() override; + int Rollback(bool isAsyncDownload = false) override; int GetUploadCount(const QuerySyncObject &query, const Timestamp ×tamp, bool isCloudForcePush, bool isCompensatedTask, int64_t &count) override; @@ -124,7 +124,7 @@ public: int OperateDataStatus(uint32_t dataOperator); private: - std::pair GetTransactionDbHandleAndMemoryStatus(); + std::pair GetTransactionDbHandleAndMemoryStatus(bool isWrite); static void FillTimestamp(Timestamp rawSystemTime, Timestamp virtualTime, CloudSyncBatch &syncBatch); @@ -137,6 +137,12 @@ private: int OperateDataStatusInner(SQLiteSingleVerStorageExecutor *handle, const std::string ¤tVirtualTime, const std::string ¤tTime, uint32_t dataOperator); + int CommitForAsyncDownload(); + + int RollbackForAsyncDownload(); + + int StartTransactionForAsyncDownload(TransactType type); + KvStorageHandle *storageHandle_; std::mutex schemaMutex_; @@ -144,6 +150,7 @@ private: mutable std::mutex transactionMutex_; SQLiteSingleVerStorageExecutor *transactionHandle_; + SQLiteSingleVerStorageExecutor *asyncDownloadTransactionHandle_ = nullptr; std::string user_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp index edbd2681ba0eb0d50e85033b3b8f6f21b578d623..b612ab10efcd7f41a6beb3c3a2853507df1aed7c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp @@ -18,7 +18,7 @@ namespace DistributedDB { namespace { - const int MAX_FIELD_NUM_IN_ONE_STATEMENT = 100; + const unsigned int MAX_FIELD_NUM_IN_ONE_STATEMENT = 100u; } int SqliteLogTableManager::AddRelationalLogTableTrigger(sqlite3 *db, const TableInfo &table, @@ -52,9 +52,9 @@ int SqliteLogTableManager::AddRelationalLogTableTrigger(sqlite3 *db, const Table return E_OK; } -int SqliteLogTableManager::CreateRelationalLogTable(sqlite3 *db, const TableInfo &table) +std::string SqliteLogTableManager::GetCreateRelationalLogTableSql(const TableInfo &table, const std::string &extendStr) { - const std::string tableName = GetLogTableName(table); + const std::string tableName = GetLogTableName(table) + extendStr; std::string primaryKey = GetPrimaryKeySql(table); std::string createTableSql = "CREATE TABLE IF NOT EXISTS " + tableName + "(" \ @@ -72,6 +72,12 @@ int SqliteLogTableManager::CreateRelationalLogTable(sqlite3 *db, const TableInfo "sharing_resource TEXT DEFAULT ''," + \ "status INT DEFAULT 0," + \ primaryKey + ");"; + return createTableSql; +} + +int SqliteLogTableManager::CreateRelationalLogTable(sqlite3 *db, const TableInfo &table) +{ + std::string createTableSql = GetCreateRelationalLogTableSql(table); std::vector logTableSchema; logTableSchema.emplace_back(createTableSql); GetIndexSql(table, logTableSchema); @@ -114,12 +120,12 @@ void SqliteLogTableManager::GetIndexSql(const TableInfo &table, std::vector &pk); protected: virtual void GetIndexSql(const TableInfo &table, std::vector &schema); std::string GetLogTableName(const TableInfo &table) const; @@ -48,8 +52,6 @@ protected: static std::string GetUpdateWithAssignSql(const TableInfo &table, const std::string &emptyValue, const std::string &matchValue, const std::string &missMatchValue); - - static std::string CalcPkHash(const std::string &references, const std::vector &pk); private: virtual std::string GetInsertTrigger(const TableInfo &table, const std::string &identity) = 0; virtual std::string GetUpdateTrigger(const TableInfo &table, const std::string &identity) = 0; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.cpp index e9f2e26b33f35818b87e17de1ffb4a38d7331675..612af826e6d04dfdf8528ccd9595b7db5e22f888 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.cpp @@ -111,4 +111,45 @@ int SqliteMetaExecutor::GetExistsDevicesFromMeta(sqlite3 *dbHandle, MetaMode met } return errCode; } + +int SqliteMetaExecutor::GetMetaDataByPrefixKey(sqlite3 *dbHandle, bool isMemDb, const std::string &metaTableName, + const Key &keyPrefix, std::map &data) +{ + std::string sql = "SELECT key,value FROM " + metaTableName + " WHERE key >= ? AND key <= ?;"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement); + if (errCode != E_OK) { + LOGE("[SqliteMetaExecutor][GetMetaDataByPrefixKey] Get statement failed:%d", errCode); + return errCode; + } + + errCode = SQLiteUtils::BindPrefixKey(statement, 1, keyPrefix); // 1 is first arg. + if (errCode != E_OK) { + LOGE("[SqliteMetaExecutor][GetMetaDataByPrefixKey] Bind prefix key failed:%d", errCode); + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } + do { + errCode = SQLiteUtils::StepWithRetry(statement, isMemDb); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + break; + } + Key key; + errCode = SQLiteUtils::GetColumnBlobValue(statement, 0, key); // 0 is key. + if (errCode != E_OK) { + LOGE("[SqliteMetaExecutor][GetMetaDataByPrefixKey] Get key failed:%d", errCode); + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } + Value value; + errCode = SQLiteUtils::GetColumnBlobValue(statement, 1, value); // 1 is value. + if (errCode != E_OK) { + LOGE("[SqliteMetaExecutor][GetMetaDataByPrefixKey] Get value failed:%d", errCode); + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } + data[key] = value; + } while (errCode == E_OK); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + } + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.h index f2890e7b473817abacfe96ed71f5bbd9d1c3cf94..0fcd3f350261b287b8b8c02cd555b0fdd4fff329 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.h @@ -33,6 +33,9 @@ public: static int GetExistsDevicesFromMeta(sqlite3 *dbHandle, MetaMode metaMode, bool isMemDb, std::set &devices); + + static int GetMetaDataByPrefixKey(sqlite3 *dbHandle, bool isMemDb, const std::string &metaTableName, + const Key &keyPrefix, std::map &data); private: static constexpr const char *SELECT_ATTACH_META_KEYS_BY_PREFIX = "SELECT key FROM meta.meta_data where key like ?;"; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp index 1ca084595fb9a21810001d2e59876d29ce44f077..3b96a9824b3e37e39e590f9675f6c6569fa649c8 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp @@ -15,6 +15,7 @@ #include "sqlite_query_helper.h" #include +#include #include "db_common.h" #include "db_constant.h" @@ -93,7 +94,9 @@ std::string GetSelectAndFromClauseForRDB(const std::string &tableName, const std std::string sql = "SELECT b.data_key," "b.device," "b.ori_device," - "b.timestamp as " + DBConstant::TIMESTAMP_ALIAS + "," + "b.timestamp as "; + sql.append(DBConstant::TIMESTAMP_ALIAS); + sql += "," "b.wtimestamp," "b.flag," "b.hash_key,"; @@ -106,13 +109,13 @@ std::string GetSelectAndFromClauseForRDB(const std::string &tableName, const std sql.pop_back(); } sql += " FROM '" + tableName + "' AS a INNER JOIN " + DBConstant::RELATIONAL_PREFIX + tableName + "_log AS b " - "ON a." + std::string(DBConstant::SQLITE_INNER_ROWID) + "=b.data_key "; + "ON a." + DBConstant::SQLITE_INNER_ROWID + "=b.data_key "; return sql; } std::string GetTimeRangeClauseForRDB() { - return " AND (" + DBConstant::TIMESTAMP_ALIAS + ">=? AND " + DBConstant::TIMESTAMP_ALIAS + "=? AND " + DBConstant::TIMESTAMP_ALIAS + " sql = GetSelectAndFromClauseForRDB(tableName_, fieldNames); sql += GetMissQueryFlagClauseForRDB(); sql += GetTimeRangeClauseForRDB(); - sql += "ORDER BY " + DBConstant::TIMESTAMP_ALIAS + " ASC;"; + sql += "ORDER BY "; + sql.append(DBConstant::TIMESTAMP_ALIAS); + sql += " ASC;"; return E_OK; } @@ -998,7 +1003,9 @@ std::string GetRelationalSyncDataQueryHeader(const std::vector &fie std::string sql = "SELECT b.data_key," "b.device," "b.ori_device," - "b.timestamp as " + DBConstant::TIMESTAMP_ALIAS + "," + "b.timestamp as "; + sql.append(DBConstant::TIMESTAMP_ALIAS); + sql += "," "b.wtimestamp," "b.flag," "b.hash_key,"; @@ -1018,7 +1025,9 @@ std::string GetRelationalCloudSyncDataQueryHeader(const std::vector &fiel std::string sql = "SELECT b.data_key," "b.device," "b.ori_device," - "b.timestamp as " + DBConstant::TIMESTAMP_ALIAS + "," + "b.timestamp as "; + sql.append(DBConstant::TIMESTAMP_ALIAS); + sql += "," "b.wtimestamp," "b.flag," "b.hash_key," @@ -1051,7 +1060,9 @@ int SqliteQueryHelper::GetRelationalSyncDataQuerySqlWithLimit(const std::vector< sql = GetRelationalSyncDataQueryHeader(fieldNames); sql += " FROM '" + tableName_ + "' AS a INNER JOIN "; sql += DBConstant::RELATIONAL_PREFIX + tableName_ + "_log"; - sql += " AS b ON (a." + std::string(DBConstant::SQLITE_INNER_ROWID) + " = b.data_key)"; + sql += " AS b ON (a."; + sql.append(DBConstant::SQLITE_INNER_ROWID); + sql += " = b.data_key)"; sql += " WHERE (b.flag&0x03=0x02)"; querySql_.clear(); // clear local query sql format diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp index 7476c7911fac2792949dd761b7c1a7b366ec74ab..81f825bef61b1f8ea1a03c8768798b7769be6f31 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp @@ -534,7 +534,10 @@ int SQLiteSingleVerNaturalStore::GetMetaData(const Key &key, Value &value) const int errCode = E_OK; SecurityOption option; - (void)GetSecurityOption(option); + errCode = GetSecurityOption(option); + if (errCode != E_OK) { + LOGW("Get security option failed when get meta data: %d", errCode); + } bool isWrite = (option.securityLabel >= S3) && (option.securityFlag == SECE); // meta in S3 SECE open meta.db, should use write handle auto handle = GetHandle(isWrite, errCode); @@ -549,6 +552,34 @@ int SQLiteSingleVerNaturalStore::GetMetaData(const Key &key, Value &value) const return errCode; } +int SQLiteSingleVerNaturalStore::GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const +{ + if (storageEngine_ == nullptr) { + return -E_INVALID_DB; + } + if (keyPrefix.size() > DBConstant::MAX_KEY_SIZE) { + return -E_INVALID_ARGS; + } + + int errCode = E_OK; + SecurityOption option; + errCode = GetSecurityOption(option); + if (errCode != E_OK) { + LOGW("Get security option failed when get meta data by prefix key: %d", errCode); + } + bool isWrite = (option.securityLabel >= S3) && (option.securityFlag == SECE); + // meta in S3 SECE open meta.db, should use write handle + auto handle = GetHandle(isWrite, errCode); + if (handle == nullptr) { + return errCode; + } + + errCode = handle->GetMetaDataByPrefixKey(keyPrefix, data); + ReleaseHandle(handle); + HeartBeatForLifeCycle(); + return errCode; +} + int SQLiteSingleVerNaturalStore::PutMetaData(const Key &key, const Value &value, bool isInTransaction) { (void)isInTransaction; @@ -1022,12 +1053,12 @@ int SQLiteSingleVerNaturalStore::RemoveDeviceData(const std::string &deviceName, errCode = removeFunc(); } else { #ifdef USE_DISTRIBUTEDDB_CLOUD - errCode = syncer->CleanKvCloudData(removeFunc); + errCode = syncer->StopSyncTask(removeFunc); DecObjRef(syncer); #endif } if (errCode != E_OK) { - LOGE("[SingleVerNStore] CleanKvCloudData with notify failed:%d", errCode); + LOGE("[SingleVerNStore] StopSyncTask with notify failed:%d", errCode); } return errCode; } @@ -1042,12 +1073,12 @@ int SQLiteSingleVerNaturalStore::RemoveDeviceData(const std::string &deviceName, errCode = removeFunc(); } else { #ifdef USE_DISTRIBUTEDDB_CLOUD - errCode = syncer->CleanKvCloudData(removeFunc); + errCode = syncer->StopSyncTask(removeFunc); DecObjRef(syncer); #endif } if (errCode != E_OK) { - LOGE("[SingleVerNStore] CleanKvCloudData with mode [%d] failed:%d", mode, errCode); + LOGE("[SingleVerNStore] StopSyncTask with mode [%d] failed:%d", mode, errCode); return errCode; } #ifdef USE_DISTRIBUTEDDB_CLOUD @@ -1071,12 +1102,12 @@ int SQLiteSingleVerNaturalStore::RemoveDeviceData(const std::string &deviceName, errCode = removeFunc(); } else { #ifdef USE_DISTRIBUTEDDB_CLOUD - errCode = syncer->CleanKvCloudData(removeFunc); + errCode = syncer->StopSyncTask(removeFunc); DecObjRef(syncer); #endif } if (errCode != E_OK) { - LOGE("[SingleVerNStore] CleanKvCloudData with user and mode [%d] failed:%d", mode, errCode); + LOGE("[SingleVerNStore] StopSyncTask with user and mode [%d] failed:%d", mode, errCode); return errCode; } #ifdef USE_DISTRIBUTEDDB_CLOUD @@ -1868,7 +1899,7 @@ int SQLiteSingleVerNaturalStore::GetKvDBSize(const KvDBProperties &properties, u std::string storeIdentDir; GenericKvDB::GetStoreDirectory(properties, KvDBProperties::SINGLE_VER_TYPE_SQLITE, storeIdentDir, storeOnlyIdentDir); - const std::vector> dbDir { + const std::vector> dbDir { {DBConstant::MAINDB_DIR, DBConstant::SINGLE_VER_DATA_STORE}, {DBConstant::METADB_DIR, DBConstant::SINGLE_VER_META_STORE}, {DBConstant::CACHEDB_DIR, DBConstant::SINGLE_VER_CACHE_STORE}}; @@ -1893,7 +1924,7 @@ void SQLiteSingleVerNaturalStore::AsyncDataMigration(SQLiteSingleVerStorageEngin std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_DELEGATE_CALLBACK_TIME)); bool isLocked = RuntimeContext::GetInstance()->IsAccessControlled(); if (!isLocked) { - LOGI("Begin to migrate cache data to manDb asynchronously!"); + LOGI("[AsyncDataMigration] Begin"); // we can't use engineMutex_ here, because ExecuteMigration will call GetHandle, it will lead to crash at // engineMutex_.lock_shared (void)StorageEngineManager::ExecuteMigration(storageEngine); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h index 9de2a68f0232e5b226b4e7462d329a9e0a2e3d90..441f4ffb54a5ac819353d837b390c027d47a24f0 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h @@ -65,6 +65,8 @@ public: int GetMetaData(const Key &key, Value &value) const override; + int GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const override; + int PutMetaData(const Key &key, const Value &value, bool isInTransaction) override; // Delete multiple meta data records in a transaction. @@ -229,6 +231,8 @@ public: int SetCloudSyncConfig(const CloudSyncConfig &config); + CloudSyncConfig GetCloudSyncConfig() const override; + uint64_t GetTimestampFromDB() override; // for test mock @@ -238,6 +242,11 @@ public: } int OperateDataStatus(uint32_t dataOperator); + +#ifdef USE_DISTRIBUTEDDB_CLOUD + int ClearCloudWatermark(); + std::function ClearCloudWatermarkInner(); +#endif protected: void AsyncDataMigration(SQLiteSingleVerStorageEngine *storageEngine) const; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp index d6f817e97e0a98ccc65febf3977a2e4d19e1b20a..ec08451abfb3100f3918353550a2d9cb05e5b968 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp @@ -99,15 +99,18 @@ int SQLiteSingleVerNaturalStoreConnection::Get(const IOption &option, const Key } DBDfxAdapter::StartTracing(); - { - // need to check if the transaction started - std::lock_guard lock(transactionMutex_); - if (writeHandle_ != nullptr) { - LOGD("Transaction started already."); - Timestamp recordTimestamp; - errCode = writeHandle_->GetKvData(dataType, key, value, recordTimestamp); - DBDfxAdapter::FinishTracing(); - return errCode; + bool isInWhitelist = IsInWhitelist(); + // need to check if the transaction started + if (!isInWhitelist || (isInWhitelist && transactionExeFlag_.load())) { + { + std::lock_guard lock(transactionMutex_); + if (writeHandle_ != nullptr) { + LOGD("Transaction started already."); + Timestamp recordTimestamp; + errCode = writeHandle_->GetKvData(dataType, key, value, recordTimestamp); + DBDfxAdapter::FinishTracing(); + return errCode; + } } } @@ -324,13 +327,7 @@ int SQLiteSingleVerNaturalStoreConnection::Pragma(int cmd, void *parameter) int errCode = E_OK; switch (cmd) { case PRAGMA_RM_DEVICE_DATA: { - SQLiteSingleVerNaturalStore *naturalStore = GetDB(); - if (naturalStore == nullptr) { - return -E_INVALID_DB; - } - auto deviceName = static_cast(parameter); - errCode = naturalStore->RemoveDeviceData(*deviceName, false, false); - break; + return RemoveDeviceDataByCmd(parameter); } case PRAGMA_GET_IDENTIFIER_OF_DEVICE: { if (parameter == nullptr) { @@ -664,7 +661,7 @@ int SQLiteSingleVerNaturalStoreConnection::RegisterLifeCycleCallback(const Datab return static_cast(kvDB_)->RegisterLifeCycleCallback(notifier); } -int SQLiteSingleVerNaturalStoreConnection::PreClose() +int SQLiteSingleVerNaturalStoreConnection::PreClose(bool isCloseImmediately) { // check if result set closed { @@ -675,6 +672,14 @@ int SQLiteSingleVerNaturalStoreConnection::PreClose() } } + // check if sync task finish + if (!isCloseImmediately) { + int ret = kvDB_->PreClose(); + if (ret != E_OK) { + return ret; + } + } + // check if transaction closed { std::lock_guard transactionLock(transactionMutex_); @@ -1076,8 +1081,8 @@ int SQLiteSingleVerNaturalStoreConnection::SaveEntryNormally(DataItem &dataItem) if (maxTimestamp > currentMaxTimestamp_) { currentMaxTimestamp_ = maxTimestamp; } - } else { - LOGE("Save entry failed, err:%d", errCode); + } else if (errCode != -E_NOT_FOUND) { + LOGE("[Normal] Save err:%d", errCode); } return errCode; } @@ -2000,6 +2005,16 @@ int SQLiteSingleVerNaturalStoreConnection::SetCloudSyncConfig(const CloudSyncCon } return naturalStore->SetCloudSyncConfig(config); } + +int SQLiteSingleVerNaturalStoreConnection::ClearCloudWatermark() +{ + auto naturalStore = GetDB(); + if (naturalStore == nullptr) { + LOGE("[SingleVerConnection] DB is null when clear cloud watermark"); + return -E_INVALID_DB; + } + return naturalStore->ClearCloudWatermark(); +} #endif void SQLiteSingleVerNaturalStoreConnection::RecordTimeIntoDataItem(Timestamp existCreateTime, DataItem &dataItem, @@ -2062,5 +2077,25 @@ int SQLiteSingleVerNaturalStoreConnection::OperateDataStatus(uint32_t dataOperat } return naturalStore->OperateDataStatus(dataOperator); } + +int SQLiteSingleVerNaturalStoreConnection::RemoveDeviceDataByCmd(void *parameter) +{ + auto naturalStore = GetDB(); + if (naturalStore == nullptr || parameter == nullptr) { + return -E_INVALID_DB; + } + auto deviceName = static_cast(parameter); + return naturalStore->RemoveDeviceData(*deviceName, false, false); +} + +bool SQLiteSingleVerNaturalStoreConnection::IsInWhitelist() const +{ + if (kvDB_ == nullptr) { + return false; + } + + std::string appId = kvDB_->GetMyProperties().GetStringProp(DBProperties::APP_ID, ""); + return appId == DBConstant::DISTRIBUTED_DEFAULT_APP_ID; +} DEFINE_OBJECT_TAG_FACILITIES(SQLiteSingleVerNaturalStoreConnection) } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h index 1b6b3f03a25e732f23dfb442b63160992889fbf8..1fd695ceb586af4c8a2f98d889ac392d3ca09086 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h @@ -98,7 +98,7 @@ public: int RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier) override; // Called when Close and delete the connection. - int PreClose() override; + int PreClose(bool isCloseImmediately) override; int CheckIntegrity() const override; @@ -122,6 +122,8 @@ public: int GetCloudVersion(const std::string &device, std::map &versionMap) override; int SetCloudSyncConfig(const CloudSyncConfig &config) override; + + int ClearCloudWatermark() override; #endif int OperateDataStatus(uint32_t dataOperator) override; @@ -229,6 +231,10 @@ private: void RecordTimeIntoDataItem(Timestamp existCreateTime, DataItem &dataItem, SQLiteSingleVerNaturalStore &naturalStore); + int RemoveDeviceDataByCmd(void *parameter); + + bool IsInWhitelist() const; + DECLARE_OBJECT_TAG(SQLiteSingleVerNaturalStoreConnection); // ResultSet Related Info diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_extend.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_extend.cpp index ba52b0e021a80d411455ac608fdaa3d4f31ee774..75c1a24461b811472e16d313367db1b50aafd2ef 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_extend.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_extend.cpp @@ -314,8 +314,8 @@ int SQLiteSingleVerNaturalStore::DeleteMetaDataByPrefixKey(const Key &keyPrefix) int SQLiteSingleVerNaturalStore::GetCompressionOption(bool &needCompressOnSync, uint8_t &compressionRate) const { - needCompressOnSync = GetDbProperties().GetBoolProp(KvDBProperties::COMPRESS_ON_SYNC, false); - compressionRate = GetDbProperties().GetIntProp(KvDBProperties::COMPRESSION_RATE, + needCompressOnSync = GetDbProperties().GetBoolProp(DBProperties::COMPRESS_ON_SYNC, false); + compressionRate = GetDbProperties().GetIntProp(DBProperties::COMPRESSION_RATE, DBConstant::DEFAULT_COMPTRESS_RATE); return E_OK; } @@ -427,14 +427,15 @@ int SQLiteSingleVerNaturalStore::AddSubscribe(const std::string &subscribeId, co int SQLiteSingleVerNaturalStore::SetMaxLogSize(uint64_t limit) { - LOGI("Set the max log size to %" PRIu64, limit); + if (maxLogSize_ != limit) { + LOGI("Set the max log size to %" PRIu64, limit); + } maxLogSize_.store(limit); return E_OK; } int SQLiteSingleVerNaturalStore::SetMaxValueSize(uint32_t maxValueSize) { - LOGI("Set the max value size to %" PRIu32, maxValueSize); storageEngine_->SetMaxValueSize(maxValueSize); return E_OK; } @@ -687,6 +688,17 @@ int SQLiteSingleVerNaturalStore::SetCloudSyncConfig(const CloudSyncConfig &confi return E_OK; } +CloudSyncConfig SQLiteSingleVerNaturalStore::GetCloudSyncConfig() const +{ + std::lock_guard autoLock(cloudStoreMutex_); + if (sqliteCloudKvStore_ == nullptr) { + LOGE("[SingleVerNStore] DB is null when get config"); + CloudSyncConfig config; + return config; + } + return sqliteCloudKvStore_->GetCloudSyncConfig(); +} + int SQLiteSingleVerNaturalStore::OperateDataStatus(uint32_t dataOperator) { std::lock_guard autoLock(cloudStoreMutex_); @@ -696,4 +708,55 @@ int SQLiteSingleVerNaturalStore::OperateDataStatus(uint32_t dataOperator) } return sqliteCloudKvStore_->OperateDataStatus(dataOperator); } + +#ifdef USE_DISTRIBUTEDDB_CLOUD +int SQLiteSingleVerNaturalStore::ClearCloudWatermark() +{ + auto syncer = GetAndIncCloudSyncer(); + if (syncer == nullptr) { + LOGE("[SingleVerNStore] Cloud syncer was not initialized"); + return -E_INVALID_DB; + } + auto clearFunc = ClearCloudWatermarkInner(); + int errCode = syncer->ClearCloudWatermark(clearFunc); + if (errCode != E_OK) { + LOGE("[SingleVerNStore] Clear cloud watermark failed: %d", errCode); + DecObjRef(syncer); + return errCode; + } + CleanAllWaterMark(); + DecObjRef(syncer); + return errCode; +} + +std::function SQLiteSingleVerNaturalStore::ClearCloudWatermarkInner() +{ + return [this]()->int { + int errCode = E_OK; + SQLiteSingleVerStorageExecutor *handle = GetHandle(true, errCode); + if (handle == nullptr) { + LOGE("[SingleVerNStore] get handle failed when clear cloud watermark:%d.", errCode); + return errCode; + } + errCode = handle->StartTransaction(TransactType::IMMEDIATE); + if (errCode != E_OK) { + LOGE("[SingleVerNStore] start transaction failed when clear cloud watermark:%d.", errCode); + ReleaseHandle(handle); + return errCode; + } + errCode = handle->ClearCloudWatermark(); + if (errCode != E_OK) { + LOGE("[SingleVerNStore] clear cloud watermark failed: %d", errCode); + (void)handle->Rollback(); + } else { + errCode = handle->Commit(); + if (errCode != E_OK) { + LOGE("[SingleVerNStore] transaction commit failed %d in RemoveDeviceData.", errCode); + } + } + ReleaseHandle(handle); + return errCode; + }; +} +#endif } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp index 01f68d75eea7835b17b3ff85e5546950433a2a45..9fbb18ba6d7d6d64490feb332c189d07610028c8 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp @@ -569,7 +569,7 @@ StorageExecutor *SQLiteSingleVerStorageEngine::NewSQLiteStorageExecutor(sqlite3 return executor; } -int SQLiteSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, sqlite3 *&db) +int SQLiteSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, sqlite3 *&db, OpenDbProperties &option) { // Only could get the main database handle in the uninitialized and the main status. if (GetEngineState() != EngineState::INVALID && GetEngineState() != EngineState::MAINDB) { @@ -577,17 +577,18 @@ int SQLiteSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, sqlite3 *& return -E_EKEYREVOKED; } - if (!option_.isMemDb) { - option_.uri = GetDbDir(option_.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + + if (!option.isMemDb) { + option.uri = GetDbDir(option_.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; + SetUri(option.uri); } - OpenDbProperties optionTemp = option_; if (!isWrite) { - optionTemp.createIfNecessary = false; + option.createIfNecessary = false; + SetCreateIfNecessary(option.createIfNecessary); } - int errCode = SQLiteUtils::OpenDatabase(optionTemp, db); + int errCode = SQLiteUtils::OpenDatabase(option, db); if (errCode != E_OK) { if (errno == EKEYREVOKED) { LOGI("Failed to open the main database for key revoked[%d]", errCode); @@ -600,7 +601,7 @@ int SQLiteSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, sqlite3 *& // Set the engine state to main status for that the main database is valid. SetEngineState(EngineState::MAINDB); - if (OS::CheckPathExistence(GetDbDir(option_.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + + if (OS::CheckPathExistence(GetDbDir(option.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::DB_EXTENSION)) { // In status cacheDb crash errCode = AttachMainDbAndCacheDb(db, EngineState::MAINDB); @@ -616,15 +617,16 @@ int SQLiteSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, sqlite3 *& return errCode; } -int SQLiteSingleVerStorageEngine::GetDbHandle(bool isWrite, const SecurityOption &secOpt, sqlite3 *&dbHandle) +int SQLiteSingleVerStorageEngine::GetDbHandle(bool isWrite, sqlite3 *&dbHandle, OpenDbProperties &option) { - int errCode = TryToOpenMainDatabase(isWrite, dbHandle); - LOGD("Finish to open the main database, write[%d], label[%d], flag[%d], id[%.6s], errCode[%d]", isWrite, + int errCode = TryToOpenMainDatabase(isWrite, dbHandle, option); + const auto &secOpt = option.securityOpt; + LOGD("Finish to open the main database, write[%d], label[%d], flag[%d], id[%.6s], errCode[%d]", isWrite, secOpt.securityLabel, secOpt.securityFlag, hashIdentifier_.c_str(), errCode); if (!(ParamCheckUtils::IsS3SECEOpt(secOpt) && errCode == -E_EKEYREVOKED)) { return errCode; } - std::string cacheDbPath = GetDbDir(option_.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + + std::string cacheDbPath = GetDbDir(option.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::DB_EXTENSION; if (!isWrite || GetEngineState() != EngineState::INVALID || OS::CheckPathExistence(cacheDbPath)) { @@ -633,7 +635,7 @@ int SQLiteSingleVerStorageEngine::GetDbHandle(bool isWrite, const SecurityOption return -E_EKEYREVOKED; } - errCode = GetCacheDbHandle(dbHandle); + errCode = GetCacheDbHandle(dbHandle, option); if (errCode != E_OK) { LOGE("singleVerStorageEngine::GetDbHandle get cache handle fail! errCode = [%d]", errCode); return errCode; @@ -671,25 +673,23 @@ const std::string CREATE_CACHE_SYNC_TABLE_SQL = // Warning: Use error passwd create cache database can not check, it will create error passwd cache db, // And make migrate data failed! This cache db will not be open correctly. -int SQLiteSingleVerStorageEngine::GetCacheDbHandle(sqlite3 *&db) +int SQLiteSingleVerStorageEngine::GetCacheDbHandle(sqlite3 *&db, OpenDbProperties &option) { - option_.uri = GetDbDir(option_.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + + option.uri = GetDbDir(option.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::DB_EXTENSION; + SetUri(option.uri); // creatTable - option_.sqls = { - CacheDbSqls::CREATE_CACHE_LOCAL_TABLE_SQL, - CacheDbSqls::CREATE_CACHE_SYNC_TABLE_SQL - }; + option.sqls = {CacheDbSqls::CREATE_CACHE_LOCAL_TABLE_SQL, CacheDbSqls::CREATE_CACHE_SYNC_TABLE_SQL}; + SetSQL(option.sqls); - if (!option_.createIfNecessary) { - std::string mainDbPtah = GetDbDir(option_.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + + if (!option.createIfNecessary) { + std::string mainDbPath = GetDbDir(option.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; - if (!OS::CheckPathExistence(mainDbPtah)) { // Whether to create a cacheDb is based on whether the mainDb exists + if (!OS::CheckPathExistence(mainDbPath)) { // Whether to create a cacheDb is based on whether the mainDb exists return -E_INVALID_DB; } } - OpenDbProperties option = option_; // copy for no change it option.createIfNecessary = true; int errCode = SQLiteUtils::OpenDatabase(option, db); if (errCode != E_OK) { @@ -727,7 +727,8 @@ void SQLiteSingleVerStorageEngine::ClearCorruptedFlag() isCorrupted_ = false; } -int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite, SecurityOption &existedSecOpt) +int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite, SecurityOption &existedSecOpt, + OpenDbProperties &option) { // Assume that create the write executor firstly and the write one we will not be released. // If the write one would be released in the future, should take care the pass through. @@ -735,12 +736,12 @@ int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite, SecurityOption return E_OK; } - if (option_.isMemDb) { + if (option.isMemDb) { return E_OK; } // check sqlite open ok - int errCode = CheckStoreStatus(option_); + int errCode = CheckStoreStatus(option); if (errCode != E_OK) { return errCode; } @@ -755,8 +756,9 @@ int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite, SecurityOption // Judge whether need update the security option of the engine. // Should update the security in the import or rekey scene(inner) or exist is not set. - if (IsUseExistedSecOption(existedSecOpt, option_.securityOpt)) { - option_.securityOpt = existedSecOpt; + if (IsUseExistedSecOption(existedSecOpt, option.securityOpt)) { + option.securityOpt = existedSecOpt; + SetSecurityOption(existedSecOpt); } else { isNeedUpdateSecOpt_ = true; } @@ -767,7 +769,7 @@ int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite, SecurityOption } if (!isUpdated_) { - errCode = SQLiteSingleVerDatabaseUpgrader::TransferDatabasePath(option_.subdir, option_); + errCode = SQLiteSingleVerDatabaseUpgrader::TransferDatabasePath(option.subdir, option); if (errCode != E_OK) { LOGE("[PreCreateExecutor] Transfer Db file path failed[%d].", errCode); return errCode; @@ -778,17 +780,18 @@ int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite, SecurityOption } int SQLiteSingleVerStorageEngine::EndCreateExecutor(sqlite3 *db, SecurityOption existedSecOpt, bool isWrite, - bool isDetachMeta) + bool isDetachMeta, OpenDbProperties &option) { - if (option_.isMemDb || !isWrite) { + if (option.isMemDb || !isWrite) { return E_OK; } - int errCode = SQLiteSingleVerDatabaseUpgrader::SetSecOption(option_.subdir, option_.securityOpt, existedSecOpt, + int errCode = SQLiteSingleVerDatabaseUpgrader::SetSecOption(option.subdir, option.securityOpt, existedSecOpt, isNeedUpdateSecOpt_); if (errCode != E_OK) { if (errCode == -E_NOT_SUPPORT) { - option_.securityOpt = SecurityOption(); + option.securityOpt = SecurityOption(); + SetSecurityOption(option.securityOpt); errCode = E_OK; } LOGE("SetSecOption failed:%d", errCode); @@ -797,8 +800,8 @@ int SQLiteSingleVerStorageEngine::EndCreateExecutor(sqlite3 *db, SecurityOption // after setting secOption, the database file operation ends // database create completed, delete the token - if (OS::CheckPathExistence(option_.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) && - OS::RemoveFile(option_.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) != E_OK) { + if (OS::CheckPathExistence(option.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) && + OS::RemoveFile(option.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) != E_OK) { LOGE("Finish to create the complete database, but delete token fail! errCode = [E_SYSTEM_API_FAIL]"); return -E_SYSTEM_API_FAIL; } @@ -813,21 +816,21 @@ int SQLiteSingleVerStorageEngine::EndCreateExecutor(sqlite3 *db, SecurityOption } errCode = SqliteLogTableManager::CreateKvSyncLogTable(db); if (errCode != E_OK) { - LOGE("[SQLiteSingleVerStorageEngine] create cloud log table failed, errCode = [%d]", errCode); + LOGE("[SqlSinEngine] create cloud log table failed, errCode = [%d]", errCode); } else { - LOGI("[SQLiteSingleVerStorageEngine] create cloud log table success"); + LOGI("[SqlSinEngine] create cloud log table success"); } return errCode; } int SQLiteSingleVerStorageEngine::TryAttachMetaDb(const SecurityOption &existedSecOpt, sqlite3 *&dbHandle, - bool &isAttachMeta, bool &isNeedDetachMeta) + bool &isAttachMeta, bool &isNeedDetachMeta, OpenDbProperties &option) { bool isCurrentSESECE = ParamCheckUtils::IsS3SECEOpt(existedSecOpt); - bool isOpenSESECE = ParamCheckUtils::IsS3SECEOpt(option_.securityOpt); + bool isOpenSESECE = ParamCheckUtils::IsS3SECEOpt(option.securityOpt); // attach or not depend on its true secOpt, but it's not permit while option_.secOpt different from true secOpt - if ((!option_.isMemDb) && (isOpenSESECE || (isNeedUpdateSecOpt_ && isCurrentSESECE))) { - int errCode = AttachMetaDatabase(dbHandle, option_); + if ((!option.isMemDb) && (isOpenSESECE || (isNeedUpdateSecOpt_ && isCurrentSESECE))) { + int errCode = AttachMetaDatabase(dbHandle, option); if (errCode != E_OK) { (void)sqlite3_close_v2(dbHandle); dbHandle = nullptr; @@ -842,33 +845,34 @@ int SQLiteSingleVerStorageEngine::TryAttachMetaDb(const SecurityOption &existedS int SQLiteSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *&handle) { SecurityOption existedSecOpt; - int errCode = PreCreateExecutor(isWrite, existedSecOpt); + auto option = GetOption(); + int errCode = PreCreateExecutor(isWrite, existedSecOpt, option); if (errCode != E_OK) { return errCode; } sqlite3 *dbHandle = nullptr; - errCode = GetDbHandle(isWrite, option_.securityOpt, dbHandle); + errCode = GetDbHandle(isWrite, dbHandle, option); if (errCode != E_OK) { return errCode; } bool isAttachMeta = false; bool isDetachMeta = false; - errCode = TryAttachMetaDb(existedSecOpt, dbHandle, isAttachMeta, isDetachMeta); + errCode = TryAttachMetaDb(existedSecOpt, dbHandle, isAttachMeta, isDetachMeta, option); if (errCode != E_OK) { return errCode; } - RegisterFunctionIfNeed(dbHandle); - errCode = Upgrade(dbHandle); + RegisterFunctionIfNeed(dbHandle, option); + errCode = UpgradeInner(dbHandle, option); if (errCode != E_OK) { (void)sqlite3_close_v2(dbHandle); dbHandle = nullptr; return errCode; } - errCode = EndCreateExecutor(dbHandle, existedSecOpt, isWrite, isDetachMeta); + errCode = EndCreateExecutor(dbHandle, existedSecOpt, isWrite, isDetachMeta, option); if (errCode != E_OK) { LOGE("After create executor, set security option incomplete!"); (void)sqlite3_close_v2(dbHandle); @@ -876,7 +880,7 @@ int SQLiteSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecuto return errCode; } - handle = NewSQLiteStorageExecutor(dbHandle, isWrite, option_.isMemDb); + handle = NewSQLiteStorageExecutor(dbHandle, isWrite, option.isMemDb); if (handle == nullptr) { LOGE("New SQLiteStorageExecutor[%d] for the pool failed.", isWrite); (void)sqlite3_close_v2(dbHandle); @@ -890,30 +894,30 @@ int SQLiteSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecuto return E_OK; } -int SQLiteSingleVerStorageEngine::Upgrade(sqlite3 *db) +int SQLiteSingleVerStorageEngine::UpgradeInner(sqlite3 *db, const OpenDbProperties &option) { if (isUpdated_ || GetEngineState() == EngineState::CACHEDB) { return E_OK; } std::unique_ptr upgrader; - LOGD("[SqlSingleEngine][Upgrade] NewSchemaStrSize=%zu", option_.schema.size()); - if (option_.schema.empty()) { - upgrader = std::make_unique(db, option_.securityOpt, option_.isMemDb); + LOGD("[SqlSingleEngine][Upgrade] NewSchemaStrSize=%zu", option.schema.size()); + if (option.schema.empty()) { + upgrader = std::make_unique(db, option.securityOpt, option.isMemDb); } else { SchemaObject schema; - int errCode = schema.ParseFromSchemaString(option_.schema); + int errCode = schema.ParseFromSchemaString(option.schema); if (errCode != E_OK) { LOGE("Upgrader failed while parsing the origin schema:%d", errCode); return errCode; } upgrader = std::make_unique(db, schema, - option_.securityOpt, option_.isMemDb); + option.securityOpt, option.isMemDb); } - std::string mainDbDir = GetDbDir(option_.subdir, DbType::MAIN); + std::string mainDbDir = GetDbDir(option.subdir, DbType::MAIN); std::string mainDbFilePath = mainDbDir + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; - SecurityOption secOpt = option_.securityOpt; + SecurityOption secOpt = option.securityOpt; int errCode = E_OK; if (isNeedUpdateSecOpt_) { errCode = GetPathSecurityOption(mainDbFilePath, secOpt); @@ -926,8 +930,8 @@ int SQLiteSingleVerStorageEngine::Upgrade(sqlite3 *db) } } - upgrader->SetMetaUpgrade(secOpt, option_.securityOpt, option_.subdir); - upgrader->SetSubdir(option_.subdir); + upgrader->SetMetaUpgrade(secOpt, option.securityOpt, option.subdir); + upgrader->SetSubdir(option.subdir); errCode = upgrader->Upgrade(); if (errCode != E_OK) { LOGE("Single ver database upgrade failed:%d", errCode); @@ -943,11 +947,11 @@ int SQLiteSingleVerStorageEngine::Upgrade(sqlite3 *db) // Attention: This function should be called before "Upgrade". // Attention: This function should be called for each executor on the sqlite3 handle that the executor binds to. -void SQLiteSingleVerStorageEngine::RegisterFunctionIfNeed(sqlite3 *dbHandle) const +void SQLiteSingleVerStorageEngine::RegisterFunctionIfNeed(sqlite3 *dbHandle, const OpenDbProperties &option) const { // This function should accept a sqlite3 handle with no perception of database classification. That is, if it is // not a newly created database, the meta-Table should exist and can be accessed. - std::string schemaStr = option_.schema; + std::string schemaStr = option.schema; if (schemaStr.empty()) { // If schema from GetKvStore::Option is empty, we have to try to load it from database. ReadOnly mode if exist; int errCode = SQLiteUtils::GetSchema(dbHandle, schemaStr); @@ -1063,7 +1067,9 @@ void SQLiteSingleVerStorageEngine::InitConflictNotifiedFlag(SingleVerNaturalStor void SQLiteSingleVerStorageEngine::SetMaxValueSize(uint32_t maxValueSize) { - LOGI("Set the max value size to %" PRIu32, maxValueSize); + if (maxValueSize_ != maxValueSize) { + LOGI("Set the max value size to %" PRIu32, maxValueSize); + } maxValueSize_ = maxValueSize; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.h index 8c07dff2455ced7bd7873e70f061b347589aa823..0f784f39448ee519ee4776f42281081ef3ea04ac 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.h @@ -69,16 +69,21 @@ public: protected: virtual StorageExecutor *NewSQLiteStorageExecutor(sqlite3 *dbHandle, bool isWrite, bool isMemDb) override; - int Upgrade(sqlite3 *db) override; + int UpgradeInner(sqlite3 *db, const OpenDbProperties &option); int CreateNewExecutor(bool isWrite, StorageExecutor *&handle) override; + virtual int TryToOpenMainDatabase(bool isWrite, sqlite3 *&db, OpenDbProperties &option); + + int GetCacheDbHandle(sqlite3 *&db, OpenDbProperties &option); + ExecutorState executorState_; private: // For executor. - int PreCreateExecutor(bool isWrite, SecurityOption &existedSecOpt); - int EndCreateExecutor(sqlite3 *db, SecurityOption existedSecOpt, bool isWrite, bool isDetachMeta); + int PreCreateExecutor(bool isWrite, SecurityOption &existedSecOpt, OpenDbProperties &option); + int EndCreateExecutor(sqlite3 *db, SecurityOption existedSecOpt, bool isWrite, bool isDetachMeta, + OpenDbProperties &option); int ReInit() override; int ReleaseExecutor(SQLiteSingleVerStorageExecutor *&handle); int ReleaseHandleTransiently(SQLiteSingleVerStorageExecutor *&handle, uint64_t idleTime, @@ -100,15 +105,13 @@ private: std::set &removeDevices, bool &isNeedHash) const; // For db. - int TryToOpenMainDatabase(bool isWrite, sqlite3 *&db); - int GetCacheDbHandle(sqlite3 *&db); - int GetDbHandle(bool isWrite, const SecurityOption &secOpt, sqlite3 *&dbHandle); + int GetDbHandle(bool isWrite, sqlite3 *&dbHandle, OpenDbProperties &option); int AttachMetaDatabase(sqlite3 *dbHandle, const OpenDbProperties &option) const; int AttachMainDbAndCacheDb(SQLiteSingleVerStorageExecutor *handle, EngineState stateBeforeMigrate); int AttachMainDbAndCacheDb(sqlite3 *dbHandle, EngineState stateBeforeMigrate) const; - void RegisterFunctionIfNeed(sqlite3 *dbHandle) const; + void RegisterFunctionIfNeed(sqlite3 *dbHandle, const OpenDbProperties &option) const; int TryAttachMetaDb(const SecurityOption &existedSecOpt, sqlite3 *&dbHandle, bool &isAttachMeta, - bool &isNeedDetachMeta); + bool &isNeedDetachMeta, OpenDbProperties &option); // For secOpt. int CreateNewDirsAndSetSecOpt() const; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp index a99a3c6252f0c429bcd696dd7df84dfeb64b3136..3cc5c82bd911f078bcba73d236e932383c2117f7 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp @@ -17,7 +17,6 @@ #include -#include "cloud/cloud_store_types.h" #include "db_constant.h" #include "db_common.h" #include "db_errno.h" @@ -238,7 +237,6 @@ int SQLiteSingleVerStorageExecutor::GetKvDataByHashKey(const Key &hashKey, Singl result.origDevice = std::string(origDevVect.begin(), origDevVect.end()); } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { errCode = -E_NOT_FOUND; - goto END; } END: diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h index 5156b1db8d8d72eab576411731e5c1de514033b6..16c1022c12e219d2a55b96b4bb788c5fa0e74b2c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h @@ -54,6 +54,8 @@ public: // Get all the meta keys. int GetAllMetaKeys(std::vector &keys) const; + int GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const; + int GetAllSyncedEntries(const std::string &hashDev, std::vector &entries) const; int SaveSyncDataItem(DataItem &dataItem, const DeviceInfo &deviceInfo, @@ -198,6 +200,8 @@ public: int CreateCloudLogTable(); int GetEntries(const std::string &device, std::vector &entries) const; + + int ClearCloudWatermark(); protected: virtual int SaveKvData(SingleVerDataType type, const Key &key, const Value &value, Timestamp timestamp); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_extend.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_extend.cpp index 3ee2eb31aa72f3c7679558b80ca57843b2151986..56bcff6714b556663f7cd84e467508e127315284 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_extend.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_extend.cpp @@ -482,4 +482,15 @@ bool SQLiteSingleVerStorageExecutor::IsFromDataOwner(const DataItem &itemGet, co return itemGet.dev == syncDev || (conflictResolvePolicy_ == DENY_OTHER_DEV_AMEND_CUR_DEV_DATA && itemGet.origDev == syncDev); } + +int SQLiteSingleVerStorageExecutor::ClearCloudWatermark() +{ + return CloudExcuteRemoveOrUpdate(REMOVE_CLOUD_ALL_HWM_DATA_SQL, "", "", true); +} + +int SQLiteSingleVerStorageExecutor::GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const +{ + std::string metaTableName = "meta_data"; + return SqliteMetaExecutor::GetMetaDataByPrefixKey(dbHandle_, isMemDb_, metaTableName, keyPrefix, data); +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h index 6d5cdc2d72c98ee8fa5b2cbe28b9cbed97ba3f84..016b6361fe5a6bbaeaf32675893fdd5f568b0ad7 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h @@ -376,7 +376,7 @@ namespace DistributedDB { constexpr const char *UPDATE_TIMESTAMP = "UPDATE sync_data SET timestamp=?, modify_time=? WHERE hash_key=?"; constexpr const char *SELECT_SYNC_ENTRIES_BY_DEVICE_SQL = - "SELECT key,value FROM sync_data WHERE device=? AND flag&0x200=0"; + "SELECT key,value FROM sync_data WHERE device=? AND flag&0x200=0 AND flag&0x01=0"; constexpr const char *SELECT_COMPENSATE_SYNC_KEY_SQL = "SELECT key FROM sync_data left join naturalbase_kv_aux_sync_data_log as log_table on sync_data.hash_key" diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_subscribe.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_subscribe.cpp index af2d76356edc3211bf2c571134bfe46fcfb7f928..1ad553a0d635a0b4d5d4b9a8b2dcc63d43b1f375 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_subscribe.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_subscribe.cpp @@ -162,9 +162,10 @@ int SQLiteSingleVerStorageExecutor::AddSubscribeTrigger(QueryObject &query, cons } // check if sqlite function is registered or not sqlite3_stmt *stmt = nullptr; - errCode = SQLiteUtils::GetStatement(dbHandle_, "SELECT " + DBConstant::UPDATE_META_FUNC + "('K', 0);", stmt); + errCode = SQLiteUtils::GetStatement(dbHandle_, + "SELECT " + std::string(DBConstant::UPDATE_META_FUNC) + "('K', 0);", stmt); if (errCode != E_OK) { - LOGE("sqlite function %s has not been created.", DBConstant::UPDATE_META_FUNC.c_str()); + LOGE("sqlite function update_meta_within_trigger has not been created."); return -E_NOT_SUPPORT; } SQLiteUtils::ResetStatement(stmt, true, errCode); @@ -201,7 +202,7 @@ int SQLiteSingleVerStorageExecutor::RemoveSubscribeTrigger(const std::vector> g_serverChangedDataMap; } -namespace TriggerMode { -const std::map TRIGGER_MODE_MAP = { - {TriggerModeEnum::NONE, ""}, - {TriggerModeEnum::INSERT, "INSERT"}, - {TriggerModeEnum::UPDATE, "UPDATE"}, - {TriggerModeEnum::DELETE, "DELETE"}, -}; - -std::string GetTriggerModeString(TriggerModeEnum mode) -{ - auto it = TRIGGER_MODE_MAP.find(mode); - return (it == TRIGGER_MODE_MAP.end()) ? "" : it->second; -} -} - std::string SQLiteUtils::Anonymous(const std::string &name) { if (name.length() <= HEAD_SIZE) { @@ -119,6 +95,7 @@ void SQLiteUtils::SqliteLogCallback(void *data, int err, const char *msg) { bool verboseLog = (data != nullptr); auto errType = static_cast(err); + bool isWarningDump = errType == (SQLITE_WARNING | (2 << 8)); // SQLITE_WARNING_DUMP std::string logMsg = msg == nullptr ? "NULL" : msg; errType &= 0xFF; if (IsNeedSkipLog(errType, logMsg.c_str())) { @@ -129,7 +106,8 @@ void SQLiteUtils::SqliteLogCallback(void *data, int err, const char *msg) if (verboseLog) { LOGD("[SQLite] Error[%d] sys[%d] %s ", err, errno, sqlite3_errstr(err)); } - } else if (errType == SQLITE_WARNING || errType == SQLITE_IOERR || errType == SQLITE_CANTOPEN) { + } else if ((errType == SQLITE_WARNING && !isWarningDump) || + errType == SQLITE_IOERR || errType == SQLITE_CANTOPEN) { LOGI("[SQLite] Error[%d], sys[%d], %s, msg: %s ", err, errno, sqlite3_errstr(err), SQLiteUtils::Anonymous(logMsg).c_str()); } else { @@ -179,9 +157,6 @@ END: (void)sqlite3_close_v2(dbTemp); dbTemp = nullptr; } - struct stat curStat; - stat(fileUrl.c_str(), &curStat); - LOGI("[SQLite] open database result: %d, inode: %llu", errCode, curStat.st_ino); return errCode; } @@ -232,150 +207,6 @@ END: return errCode; } -int SQLiteUtils::GetStatement(sqlite3 *db, const std::string &sql, sqlite3_stmt *&statement) -{ - if (db == nullptr) { - LOGE("Invalid db for statement"); - return -E_INVALID_DB; - } - // Prepare the new statement only when the input parameter is not null - if (statement != nullptr) { - return E_OK; - } - int errCode = sqlite3_prepare_v2(db, sql.c_str(), NO_SIZE_LIMIT, &statement, nullptr); - if (errCode != SQLITE_OK) { - LOGE("Prepare SQLite statement failed:%d, sys:%d", errCode, errno); - errCode = SQLiteUtils::MapSQLiteErrno(errCode); - SQLiteUtils::ResetStatement(statement, true, errCode); - return errCode; - } - - if (statement == nullptr) { - return -E_INVALID_DB; - } - - return E_OK; -} - -int SQLiteUtils::BindTextToStatement(sqlite3_stmt *statement, int index, const std::string &str) -{ - if (statement == nullptr) { - return -E_INVALID_ARGS; - } - - int errCode = sqlite3_bind_text(statement, index, str.c_str(), str.length(), SQLITE_TRANSIENT); - if (errCode != SQLITE_OK) { - LOGE("[SQLiteUtil][Bind text]Failed to bind the value:%d", errCode); - return SQLiteUtils::MapSQLiteErrno(errCode); - } - - return E_OK; -} - -int SQLiteUtils::BindInt64ToStatement(sqlite3_stmt *statement, int index, int64_t value) -{ - // statement check outSide - int errCode = sqlite3_bind_int64(statement, index, value); - if (errCode != SQLITE_OK) { - LOGE("[SQLiteUtil][Bind int64]Failed to bind the value:%d", errCode); - return SQLiteUtils::MapSQLiteErrno(errCode); - } - - return E_OK; -} - -int SQLiteUtils::BindBlobToStatement(sqlite3_stmt *statement, int index, const std::vector &value, - bool permEmpty) -{ - if (statement == nullptr) { - return -E_INVALID_ARGS; - } - - // Check empty value. - if (value.empty() && !permEmpty) { - LOGI("[SQLiteUtil][Bind blob]Invalid value"); - return -E_INVALID_ARGS; - } - - int errCode; - if (value.empty()) { - errCode = sqlite3_bind_zeroblob(statement, index, -1); // -1 for zero-length blob. - } else { - errCode = sqlite3_bind_blob(statement, index, static_cast(value.data()), - value.size(), SQLITE_TRANSIENT); - } - - if (errCode != SQLITE_OK) { - LOGE("[SQLiteUtil][Bind blob]Failed to bind the value:%d", errCode); - return SQLiteUtils::MapSQLiteErrno(errCode); - } - - return E_OK; -} - -void SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool isNeedFinalize, int &errCode) -{ - ResetStatement(statement, isNeedFinalize, false, errCode); -} - -void SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool isNeedFinalize, bool isIgnoreResetRet, int &errCode) -{ - if (statement == nullptr) { - return; - } - - int innerCode = SQLITE_OK; - // if need finalize the statement, just goto finalize. - if (!isNeedFinalize) { - // reset the statement firstly. - innerCode = sqlite3_reset(statement); - if (innerCode != SQLITE_OK && !isIgnoreResetRet) { - LOGE("[SQLiteUtils] reset statement error:%d, sys:%d", innerCode, errno); - isNeedFinalize = true; - } else { - sqlite3_clear_bindings(statement); - } - } - - if (isNeedFinalize) { - int finalizeResult = sqlite3_finalize(statement); - if (finalizeResult != SQLITE_OK) { - LOGE("[SQLiteUtils] finalize statement error:%d, sys:%d", finalizeResult, errno); - innerCode = finalizeResult; - } - statement = nullptr; - } - - if (innerCode != SQLITE_OK) { // the sqlite error code has higher priority. - errCode = SQLiteUtils::MapSQLiteErrno(innerCode); - } -} - -int SQLiteUtils::StepWithRetry(sqlite3_stmt *statement, bool isMemDb) -{ - if (statement == nullptr) { - return -E_INVALID_ARGS; - } - - int errCode = E_OK; - int retryCount = 0; - do { - errCode = sqlite3_step(statement); - if ((errCode == SQLITE_LOCKED) && isMemDb) { - std::this_thread::sleep_for(std::chrono::microseconds(BUSY_SLEEP_TIME)); - retryCount++; - } else { - break; - } - } while (retryCount <= MAX_STEP_TIMES); - - if (errCode != SQLITE_DONE && errCode != SQLITE_ROW) { - LOGE("[SQLiteUtils] Step error:%d, sys:%d", errCode, errno); - } - - return SQLiteUtils::MapSQLiteErrno(errCode); -} - int SQLiteUtils::BindPrefixKey(sqlite3_stmt *statement, int index, const Key &keyPrefix) { if (statement == nullptr) { @@ -415,57 +246,6 @@ int SQLiteUtils::BindPrefixKey(sqlite3_stmt *statement, int index, const Key &ke return E_OK; } -int SQLiteUtils::BeginTransaction(sqlite3 *db, TransactType type) -{ - if (type == TransactType::IMMEDIATE) { - return ExecuteRawSQL(db, BEGIN_IMMEDIATE_SQL, true); - } - - return ExecuteRawSQL(db, BEGIN_SQL, true); -} - -int SQLiteUtils::CommitTransaction(sqlite3 *db) -{ - return ExecuteRawSQL(db, COMMIT_SQL, true); -} - -int SQLiteUtils::RollbackTransaction(sqlite3 *db) -{ - return ExecuteRawSQL(db, ROLLBACK_SQL, true); -} - -int SQLiteUtils::ExecuteRawSQL(sqlite3 *db, const std::string &sql, bool ignoreResetFail) -{ - if (db == nullptr) { - return -E_INVALID_DB; - } - - sqlite3_stmt *stmt = nullptr; - int errCode = SQLiteUtils::GetStatement(db, sql, stmt); - if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) { - LOGE("[SQLiteUtils][ExecuteSQL] prepare statement failed(%d), sys(%d)", errCode, errno); - return errCode; - } - - do { - errCode = SQLiteUtils::StepWithRetry(stmt); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - break; - } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - LOGE("[SQLiteUtils][ExecuteSQL] execute statement failed(%d), sys(%d)", errCode, errno); - break; - } - } while (true); - - int ret = E_OK; - SQLiteUtils::ResetStatement(stmt, true, ret); - if (!ignoreResetFail && ret != E_OK) { - return errCode != E_OK ? errCode : ret; - } - return errCode; -} - int SQLiteUtils::SetKey(sqlite3 *db, CipherType type, const CipherPassword &passwd, bool setWal, uint32_t iterTimes) { if (db == nullptr) { @@ -516,57 +296,6 @@ int SQLiteUtils::SetKey(sqlite3 *db, CipherType type, const CipherPassword &pass return errCode; } -int SQLiteUtils::GetColumnBlobValue(sqlite3_stmt *statement, int index, std::vector &value) -{ - if (statement == nullptr) { - return -E_INVALID_ARGS; - } - - int keySize = sqlite3_column_bytes(statement, index); - if (keySize < 0) { - LOGW("[SQLiteUtils][Column blob] size less than zero:%d", keySize); - value.resize(0); - return E_OK; - } - auto keyRead = static_cast(sqlite3_column_blob(statement, index)); - if (keySize == 0 || keyRead == nullptr) { - value.resize(0); - } else { - if (keySize > MAX_BLOB_READ_SIZE) { - LOGW("[SQLiteUtils][Column blob] size over limit:%d", keySize); - keySize = MAX_BLOB_READ_SIZE + 1; - } - value.resize(keySize); - value.assign(keyRead, keyRead + keySize); - } - return E_OK; -} - -int SQLiteUtils::GetColumnTextValue(sqlite3_stmt *statement, int index, std::string &value) -{ - if (statement == nullptr) { - return -E_INVALID_ARGS; - } - - int valSize = sqlite3_column_bytes(statement, index); - if (valSize < 0) { - LOGW("[SQLiteUtils][Column Text] size less than zero:%d", valSize); - value = {}; - return E_OK; - } - const unsigned char *val = sqlite3_column_text(statement, index); - if (valSize == 0 || val == nullptr) { - value = {}; - return E_OK; - } - value = std::string(reinterpret_cast(val)); - if (valSize > MAX_TEXT_READ_SIZE) { - LOGW("[SQLiteUtils][Column text] size over limit:%d", valSize); - value.resize(MAX_TEXT_READ_SIZE + 1); // Reset value size to invalid - } - return E_OK; -} - int SQLiteUtils::AttachNewDatabase(sqlite3 *db, CipherType type, const CipherPassword &password, const std::string &attachDbAbsPath, const std::string &attachAsName) { @@ -713,265 +442,7 @@ int SQLiteUtils::CheckIntegrity(sqlite3 *db, const std::string &sql) SQLiteUtils::ResetStatement(statement, true, ret); return errCode != E_OK ? errCode : ret; } -#ifdef RELATIONAL_STORE - -namespace { // anonymous namespace for schema analysis -int AnalysisSchemaSqlAndTrigger(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive) -{ - std::string sql = "SELECT type, sql FROM sqlite_master WHERE tbl_name = ? "; - if (!caseSensitive) { - sql += "COLLATE NOCASE"; - } - sqlite3_stmt *statement = nullptr; - int errCode = SQLiteUtils::GetStatement(db, sql, statement); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] Prepare the analysis schema sql and trigger statement error:%d", errCode); - return errCode; - } - errCode = SQLiteUtils::BindTextToStatement(statement, 1, tableName); - int ret = E_OK; - if (errCode != E_OK) { - LOGE("[AnalysisSchema] Bind table name failed:%d", errCode); - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode; - } - - errCode = -E_NOT_FOUND; - do { - int err = SQLiteUtils::StepWithRetry(statement); - if (err == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - break; - } else if (err == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - errCode = E_OK; - std::string type; - (void) SQLiteUtils::GetColumnTextValue(statement, 0, type); - if (type == "table") { - std::string createTableSql; - (void) SQLiteUtils::GetColumnTextValue(statement, 1, createTableSql); // 1 means create table sql - table.SetCreateTableSql(createTableSql); - } - } else { - LOGE("[AnalysisSchema] Step for the analysis create table sql and trigger failed:%d", err); - errCode = SQLiteUtils::MapSQLiteErrno(err); - break; - } - } while (true); - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode != E_OK ? errCode : ret; -} - -int GetSchemaIndexList(sqlite3 *db, const std::string &tableName, std::vector &indexList, - std::vector &uniqueList) -{ - std::string sql = "pragma index_list('" + tableName + "')"; - sqlite3_stmt *statement = nullptr; - int errCode = SQLiteUtils::GetStatement(db, sql, statement); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] Prepare the get schema index list statement error:%d", errCode); - return errCode; - } - - do { - errCode = SQLiteUtils::StepWithRetry(statement); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - break; - } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - std::string indexName; - (void) SQLiteUtils::GetColumnTextValue(statement, 1, indexName); // 1 means index name - int unique = sqlite3_column_int64(statement, 2); // 2 means index type, whether unique - if (unique == 0) { // 0 means index created by user declare - indexList.push_back(indexName); - } else if (unique == 1) { // 1 means an unique define - uniqueList.push_back(indexName); - } - } else { - LOGW("[AnalysisSchema] Step for the get schema index list failed:%d", errCode); - break; - } - } while (true); - int ret = E_OK; - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode != E_OK ? errCode : ret; -} - -int AnalysisSchemaIndexDefine(sqlite3 *db, const std::string &indexName, CompositeFields &indexDefine) -{ - auto sql = "pragma index_info('" + indexName + "')"; - sqlite3_stmt *statement = nullptr; - int errCode = SQLiteUtils::GetStatement(db, sql, statement); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] Prepare the analysis schema index statement error:%d", errCode); - return errCode; - } - - do { - errCode = SQLiteUtils::StepWithRetry(statement); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - break; - } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - std::string indexField; - (void) SQLiteUtils::GetColumnTextValue(statement, 2, indexField); // 2 means index's column name. - indexDefine.push_back(indexField); - } else { - LOGW("[AnalysisSchema] Step for the analysis schema index failed:%d", errCode); - break; - } - } while (true); - - int ret = E_OK; - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode != E_OK ? errCode : ret; -} - -int AnalysisSchemaIndex(sqlite3 *db, const std::string &tableName, TableInfo &table) -{ - std::vector indexList; - std::vector uniqueList; - int errCode = GetSchemaIndexList(db, tableName, indexList, uniqueList); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] get schema index list failed."); - return errCode; - } - - for (const auto &indexName : indexList) { - CompositeFields indexDefine; - errCode = AnalysisSchemaIndexDefine(db, indexName, indexDefine); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] analysis schema index columns failed."); - return errCode; - } - table.AddIndexDefine(indexName, indexDefine); - } - std::vector uniques; - for (const auto &uniqueName : uniqueList) { - CompositeFields uniqueDefine; - errCode = AnalysisSchemaIndexDefine(db, uniqueName, uniqueDefine); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] analysis schema unique columns failed."); - return errCode; - } - uniques.push_back(uniqueDefine); - } - table.SetUniqueDefine(uniques); - return E_OK; -} - -void SetPrimaryKeyCollateType(const std::string &sql, FieldInfo &field) -{ - std::string upperFieldName = DBCommon::ToUpperCase(field.GetFieldName()); - if (DBCommon::HasConstraint(sql, "PRIMARY KEY COLLATE NOCASE", " ", " ,)") || - DBCommon::HasConstraint(sql, upperFieldName + " TEXT COLLATE NOCASE", " (,", " ,")) { - field.SetCollateType(CollateType::COLLATE_NOCASE); - } else if (DBCommon::HasConstraint(sql, "PRIMARY KEY COLLATE RTRIM", " ", " ,)") || - DBCommon::HasConstraint(sql, upperFieldName + " TEXT COLLATE RTRIM", " (,", " ,")) { - field.SetCollateType(CollateType::COLLATE_RTRIM); - } -} - -int SetFieldInfo(sqlite3_stmt *statement, TableInfo &table) -{ - FieldInfo field; - field.SetColumnId(sqlite3_column_int(statement, 0)); // 0 means column id index - - std::string tmpString; - (void) SQLiteUtils::GetColumnTextValue(statement, 1, tmpString); // 1 means column name index - if (!DBCommon::CheckIsAlnumOrUnderscore(tmpString)) { - LOGE("[AnalysisSchema] unsupported field name."); - return -E_NOT_SUPPORT; - } - field.SetFieldName(tmpString); - - (void) SQLiteUtils::GetColumnTextValue(statement, 2, tmpString); // 2 means datatype index - field.SetDataType(tmpString); - - field.SetNotNull(static_cast(sqlite3_column_int64(statement, 3))); // 3 means whether null index - - (void) SQLiteUtils::GetColumnTextValue(statement, 4, tmpString); // 4 means default value index - if (!tmpString.empty()) { - field.SetDefaultValue(tmpString); - } - - int keyIndex = sqlite3_column_int(statement, 5); // 5 means primary key index - if (keyIndex != 0) { // not 0 means is a primary key - table.SetPrimaryKey(field.GetFieldName(), keyIndex); - SetPrimaryKeyCollateType(table.GetCreateTableSql(), field); - } - table.AddField(field); - return E_OK; -} -} // end of anonymous namespace for schema analysis - -int SQLiteUtils::AnalysisSchemaFieldDefine(sqlite3 *db, const std::string &tableName, TableInfo &table) -{ - std::string sql = "pragma table_info('" + tableName + "')"; - sqlite3_stmt *statement = nullptr; - int errCode = SQLiteUtils::GetStatement(db, sql, statement); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] Prepare the analysis schema field statement error:%d", errCode); - return errCode; - } - - do { - errCode = SQLiteUtils::StepWithRetry(statement); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - break; - } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - errCode = SetFieldInfo(statement, table); - if (errCode != E_OK) { - break; - } - } else { - LOGW("[AnalysisSchema] Step for the analysis schema field failed:%d", errCode); - break; - } - } while (true); - - if (table.GetPrimaryKey().empty()) { - table.SetPrimaryKey("rowid", 1); - } - - int ret = E_OK; - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode != E_OK ? errCode : ret; -} - -int SQLiteUtils::AnalysisSchema(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive) -{ - if (db == nullptr) { - return -E_INVALID_DB; - } - - if (!DBCommon::CheckIsAlnumOrUnderscore(tableName)) { - LOGE("[AnalysisSchema] unsupported table name."); - return -E_NOT_SUPPORT; - } - - int errCode = AnalysisSchemaSqlAndTrigger(db, tableName, table, caseSensitive); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] Analysis sql and trigger failed. errCode = [%d]", errCode); - return errCode; - } - - errCode = AnalysisSchemaIndex(db, tableName, table); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] Analysis index failed."); - return errCode; - } - - errCode = AnalysisSchemaFieldDefine(db, tableName, table); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] Analysis field failed."); - return errCode; - } - - table.SetTableName(tableName); - return E_OK; -} -#endif #ifndef OMIT_ENCRYPT int SQLiteUtils::ExportDatabase(sqlite3 *db, CipherType type, const CipherPassword &passwd, const std::string &newDbName) @@ -1159,39 +630,6 @@ int SQLiteUtils::SetUserVer(sqlite3 *db, int version) return SQLiteUtils::ExecuteRawSQL(db, userVersionSql); } -int SQLiteUtils::MapSQLiteErrno(int errCode) -{ - switch (errCode) { - case SQLITE_OK: - return E_OK; - case SQLITE_IOERR: - if (errno == EKEYREVOKED) { - return -E_EKEYREVOKED; - } - break; - case SQLITE_CORRUPT: - case SQLITE_NOTADB: - return -E_INVALID_PASSWD_OR_CORRUPTED_DB; - case SQLITE_LOCKED: - case SQLITE_BUSY: - return -E_BUSY; - case SQLITE_ERROR: - if (errno == EKEYREVOKED) { - return -E_EKEYREVOKED; - } - break; - case SQLITE_AUTH: - return -E_DENIED_SQL; - case SQLITE_CONSTRAINT: - return -E_CONSTRAINT; - case SQLITE_CANTOPEN: - return -E_SQLITE_CANT_OPEN; - default: - break; - } - return -errCode; -} - int SQLiteUtils::SetBusyTimeout(sqlite3 *db, int timeout) { if (db == nullptr) { @@ -1289,7 +727,7 @@ int SQLiteUtils::GetSchema(sqlite3 *db, std::string &strSchema) bool isExists = false; int errCode = CheckTableExists(db, "meta_data", isExists); if (errCode != E_OK || !isExists) { - LOGW("meta table may has not been created, err=%d, isExists=%d", errCode, isExists); + LOGW("[GetSchema] err=%d, meta=%d", errCode, isExists); return errCode; } @@ -1827,11 +1265,11 @@ END: int SQLiteUtils::RegisterMetaDataUpdateFunction(sqlite3 *db) { - int errCode = sqlite3_create_function_v2(db, DBConstant::UPDATE_META_FUNC.c_str(), + int errCode = sqlite3_create_function_v2(db, DBConstant::UPDATE_META_FUNC, 2, // 2: argc for register function SQLITE_UTF8 | SQLITE_DETERMINISTIC, db, &SQLiteUtils::UpdateMetaDataWithinTrigger, nullptr, nullptr, nullptr); if (errCode != SQLITE_OK) { - LOGE("sqlite3_create_function_v2 about %s returned %d", DBConstant::UPDATE_META_FUNC.c_str(), errCode); + LOGE("sqlite3_create_function_v2 about update_meta_within_trigger returned %d", errCode); } return SQLiteUtils::MapSQLiteErrno(errCode); } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h index 1953db51e23826a3d88761ee7f8ad9a1e1d94592..69b1a18c75891541ab13fb27faa260cbb2f52db7 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h @@ -213,6 +213,8 @@ public: static int UpdateLocalDataModifyTime(sqlite3 *db, const std::string &virtualTime, const std::string &modifyTime); static int UpdateLocalDataCloudFlag(sqlite3 *db); + + static int ProcessStatementErrCode(sqlite3_stmt *&statement, bool isNeedFinalize, int errCode); private: static int CreateDataBase(const OpenDbProperties &properties, sqlite3 *&dbTemp, bool setWal); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_client.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_client.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a6779791ca2bb7a5cf6a03bb5914a9e4a70649b0 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_client.cpp @@ -0,0 +1,651 @@ +/* + * Copyright (c) 2025 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 "sqlite_utils.h" + +#include "db_common.h" +#include "platform_specific.h" + +namespace DistributedDB { +namespace { + const int BUSY_SLEEP_TIME = 50; // sleep for 50us + const int NO_SIZE_LIMIT = -1; + const int MAX_STEP_TIMES = 8000; + const std::string BEGIN_SQL = "BEGIN TRANSACTION"; + const std::string BEGIN_IMMEDIATE_SQL = "BEGIN IMMEDIATE TRANSACTION"; + const std::string COMMIT_SQL = "COMMIT TRANSACTION"; + const std::string ROLLBACK_SQL = "ROLLBACK TRANSACTION"; + const int MAX_BLOB_READ_SIZE = 64 * 1024 * 1024; // 64M limit + const int MAX_TEXT_READ_SIZE = 5 * 1024 * 1024; // 5M limit + + const constexpr char *CHECK_TABLE_CREATED = "SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE " \ + "type='table' AND (tbl_name=? COLLATE NOCASE));"; + const constexpr char *CHECK_META_DB_TABLE_CREATED = "SELECT EXISTS(SELECT 1 FROM meta.sqlite_master WHERE " \ + "type='table' AND (tbl_name=? COLLATE NOCASE));"; +} + +namespace TriggerMode { +const std::map TRIGGER_MODE_MAP = { + {TriggerModeEnum::NONE, ""}, + {TriggerModeEnum::INSERT, "INSERT"}, + {TriggerModeEnum::UPDATE, "UPDATE"}, + {TriggerModeEnum::DELETE, "DELETE"}, +}; + +std::string GetTriggerModeString(TriggerModeEnum mode) +{ + auto it = TRIGGER_MODE_MAP.find(mode); + return (it == TRIGGER_MODE_MAP.end()) ? "" : it->second; +} +} + +int SQLiteUtils::StepWithRetry(sqlite3_stmt *statement, bool isMemDb) +{ + if (statement == nullptr) { + return -E_INVALID_ARGS; + } + + int errCode = E_OK; + int retryCount = 0; + do { + errCode = sqlite3_step(statement); + if ((errCode == SQLITE_LOCKED) && isMemDb) { + std::this_thread::sleep_for(std::chrono::microseconds(BUSY_SLEEP_TIME)); + retryCount++; + } else { + break; + } + } while (retryCount <= MAX_STEP_TIMES); + + if (errCode != SQLITE_DONE && errCode != SQLITE_ROW) { + LOGE("[SQLiteUtils] Step error:%d, sys:%d", errCode, errno); + } + + return SQLiteUtils::MapSQLiteErrno(errCode); +} + +int SQLiteUtils::BeginTransaction(sqlite3 *db, TransactType type) +{ + if (type == TransactType::IMMEDIATE) { + return ExecuteRawSQL(db, BEGIN_IMMEDIATE_SQL, true); + } + + return ExecuteRawSQL(db, BEGIN_SQL, true); +} + +int SQLiteUtils::CommitTransaction(sqlite3 *db) +{ + return ExecuteRawSQL(db, COMMIT_SQL, true); +} + +int SQLiteUtils::RollbackTransaction(sqlite3 *db) +{ + return ExecuteRawSQL(db, ROLLBACK_SQL, true); +} + +int SQLiteUtils::ExecuteRawSQL(sqlite3 *db, const std::string &sql, bool ignoreResetFail) +{ + if (db == nullptr) { + return -E_INVALID_DB; + } + + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) { + LOGE("[SQLiteUtils][ExecuteSQL] prepare statement failed(%d), sys(%d)", errCode, errno); + return errCode; + } + + do { + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + break; + } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + LOGE("[SQLiteUtils][ExecuteSQL] execute statement failed(%d), sys(%d)", errCode, errno); + break; + } + } while (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)); + + int ret = E_OK; + SQLiteUtils::ResetStatement(stmt, true, ret); + if (!ignoreResetFail && ret != E_OK) { + return errCode != E_OK ? errCode : ret; + } + return errCode; +} + +int SQLiteUtils::MapSQLiteErrno(int errCode) +{ + switch (errCode) { + case SQLITE_OK: + return E_OK; + case SQLITE_IOERR: + if (errno == EKEYREVOKED) { + return -E_EKEYREVOKED; + } + break; + case SQLITE_CORRUPT: + case SQLITE_NOTADB: + return -E_INVALID_PASSWD_OR_CORRUPTED_DB; + case SQLITE_LOCKED: + case SQLITE_BUSY: + return -E_BUSY; + case SQLITE_ERROR: + if (errno == EKEYREVOKED) { + return -E_EKEYREVOKED; + } + break; + case SQLITE_AUTH: + return -E_DENIED_SQL; + case SQLITE_CONSTRAINT: + return -E_CONSTRAINT; + case SQLITE_CANTOPEN: + return -E_SQLITE_CANT_OPEN; + default: + break; + } + return -errCode; +} + +int SQLiteUtils::GetStatement(sqlite3 *db, const std::string &sql, sqlite3_stmt *&statement) +{ + if (db == nullptr) { + LOGE("Invalid db for statement"); + return -E_INVALID_DB; + } + // Prepare the new statement only when the input parameter is not null + if (statement != nullptr) { + return E_OK; + } + int errCode = sqlite3_prepare_v2(db, sql.c_str(), NO_SIZE_LIMIT, &statement, nullptr); + if (errCode != SQLITE_OK) { + LOGE("Prepare SQLite statement failed:%d, sys:%d", errCode, errno); + errCode = SQLiteUtils::MapSQLiteErrno(errCode); + SQLiteUtils::ResetStatement(statement, true, errCode); + return errCode; + } + + if (statement == nullptr) { + return -E_INVALID_DB; + } + + return E_OK; +} + +void SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool isNeedFinalize, int &errCode) +{ + ResetStatement(statement, isNeedFinalize, false, errCode); +} + +void SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool isNeedFinalize, bool isIgnoreResetRet, int &errCode) +{ + if (statement == nullptr) { + return; + } + + int innerCode = SQLITE_OK; + // if need finalize the statement, just goto finalize. + if (!isNeedFinalize) { + // reset the statement firstly. + innerCode = sqlite3_reset(statement); + if (innerCode != SQLITE_OK && !isIgnoreResetRet) { + LOGE("[SQLiteUtils] reset statement error:%d, sys:%d", innerCode, errno); + isNeedFinalize = true; + } else { + sqlite3_clear_bindings(statement); + } + } + + if (isNeedFinalize) { + int finalizeResult = sqlite3_finalize(statement); + if (finalizeResult != SQLITE_OK) { + LOGE("[SQLiteUtils] finalize statement error:%d, sys:%d", finalizeResult, errno); + innerCode = finalizeResult; + } + statement = nullptr; + } + + if (innerCode != SQLITE_OK) { // the sqlite error code has higher priority. + errCode = SQLiteUtils::MapSQLiteErrno(innerCode); + } +} + +#ifdef RELATIONAL_STORE +namespace { // anonymous namespace for schema analysis +int AnalysisSchemaSqlAndTrigger(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive) +{ + std::string sql = "SELECT type, sql FROM sqlite_master WHERE tbl_name = ? "; + if (!caseSensitive) { + sql += "COLLATE NOCASE"; + } + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, statement); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] Prepare the analysis schema sql and trigger statement error:%d", errCode); + return errCode; + } + errCode = SQLiteUtils::BindTextToStatement(statement, 1, tableName); + int ret = E_OK; + if (errCode != E_OK) { + LOGE("[AnalysisSchema] Bind table name failed:%d", errCode); + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode; + } + + errCode = -E_NOT_FOUND; + int err = SQLiteUtils::MapSQLiteErrno(SQLITE_ROW); + do { + err = SQLiteUtils::StepWithRetry(statement); + if (err == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + break; + } else if (err == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + errCode = E_OK; + std::string type; + (void) SQLiteUtils::GetColumnTextValue(statement, 0, type); + if (type == "table") { + std::string createTableSql; + (void) SQLiteUtils::GetColumnTextValue(statement, 1, createTableSql); // 1 means create table sql + table.SetCreateTableSql(createTableSql); + } + } else { + LOGE("[AnalysisSchema] Step for the analysis create table sql and trigger failed:%d", err); + errCode = err; + break; + } + } while (err == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)); + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode != E_OK ? errCode : ret; +} + +int AnalysisSchemaIndexDefine(sqlite3 *db, const std::string &indexName, CompositeFields &indexDefine) +{ + auto sql = "pragma index_info('" + indexName + "')"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, statement); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] Prepare the analysis schema index statement error:%d", errCode); + return errCode; + } + + do { + errCode = SQLiteUtils::StepWithRetry(statement); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + break; + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + std::string indexField; + (void) SQLiteUtils::GetColumnTextValue(statement, 2, indexField); // 2 means index's column name. + indexDefine.push_back(indexField); + } else { + LOGW("[AnalysisSchema] Step for the analysis schema index failed:%d", errCode); + break; + } + } while (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)); + + int ret = E_OK; + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode != E_OK ? errCode : ret; +} + +int GetSchemaIndexList(sqlite3 *db, const std::string &tableName, std::vector &indexList, + std::vector &uniqueList) +{ + std::string sql = "pragma index_list('" + tableName + "')"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, statement); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] Prepare the get schema index list statement error:%d", errCode); + return errCode; + } + + do { + errCode = SQLiteUtils::StepWithRetry(statement); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + break; + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + std::string indexName; + (void) SQLiteUtils::GetColumnTextValue(statement, 1, indexName); // 1 means index name + int unique = sqlite3_column_int64(statement, 2); // 2 means index type, whether unique + if (unique == 0) { // 0 means index created by user declare + indexList.push_back(indexName); + } else if (unique == 1) { // 1 means an unique define + uniqueList.push_back(indexName); + } + } else { + LOGW("[AnalysisSchema] Step for the get schema index list failed:%d", errCode); + break; + } + } while (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)); + int ret = E_OK; + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode != E_OK ? errCode : ret; +} + +int AnalysisSchemaIndex(sqlite3 *db, const std::string &tableName, TableInfo &table) +{ + std::vector indexList; + std::vector uniqueList; + int errCode = GetSchemaIndexList(db, tableName, indexList, uniqueList); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] get schema index list failed."); + return errCode; + } + + for (const auto &indexName : indexList) { + CompositeFields indexDefine; + errCode = AnalysisSchemaIndexDefine(db, indexName, indexDefine); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] analysis schema index columns failed."); + return errCode; + } + table.AddIndexDefine(indexName, indexDefine); + } + + std::vector uniques; + for (const auto &uniqueName : uniqueList) { + CompositeFields uniqueDefine; + errCode = AnalysisSchemaIndexDefine(db, uniqueName, uniqueDefine); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] analysis schema unique columns failed."); + return errCode; + } + uniques.push_back(uniqueDefine); + } + table.SetUniqueDefine(uniques); + return E_OK; +} + +void SetPrimaryKeyCollateType(const std::string &sql, FieldInfo &field) +{ + std::string upperFieldName = DBCommon::ToUpperCase(field.GetFieldName()); + if (DBCommon::HasConstraint(sql, "PRIMARY KEY COLLATE NOCASE", " ", " ,)") || + DBCommon::HasConstraint(sql, upperFieldName + " TEXT COLLATE NOCASE", " (,", " ,")) { + field.SetCollateType(CollateType::COLLATE_NOCASE); + } else if (DBCommon::HasConstraint(sql, "PRIMARY KEY COLLATE RTRIM", " ", " ,)") || + DBCommon::HasConstraint(sql, upperFieldName + " TEXT COLLATE RTRIM", " (,", " ,")) { + field.SetCollateType(CollateType::COLLATE_RTRIM); + } +} + +int SetFieldInfo(sqlite3_stmt *statement, TableInfo &table) +{ + FieldInfo field; + field.SetColumnId(sqlite3_column_int(statement, 0)); // 0 means column id index + + std::string tmpString; + (void) SQLiteUtils::GetColumnTextValue(statement, 1, tmpString); // 1 means column name index + if (!DBCommon::CheckIsAlnumOrUnderscore(tmpString)) { + LOGE("[AnalysisSchema] unsupported field name."); + return -E_NOT_SUPPORT; + } + field.SetFieldName(tmpString); + + (void) SQLiteUtils::GetColumnTextValue(statement, 2, tmpString); // 2 means datatype index + field.SetDataType(tmpString); + + field.SetNotNull(static_cast(sqlite3_column_int64(statement, 3))); // 3 means whether null index + + (void) SQLiteUtils::GetColumnTextValue(statement, 4, tmpString); // 4 means default value index + if (!tmpString.empty()) { + field.SetDefaultValue(tmpString); + } + + int keyIndex = sqlite3_column_int(statement, 5); // 5 means primary key index + if (keyIndex != 0) { // not 0 means is a primary key + table.SetPrimaryKey(field.GetFieldName(), keyIndex); + SetPrimaryKeyCollateType(table.GetCreateTableSql(), field); + } + table.AddField(field); + return E_OK; +} +} // end of anonymous namespace for schema analysis + +int SQLiteUtils::AnalysisSchemaFieldDefine(sqlite3 *db, const std::string &tableName, TableInfo &table) +{ + std::string sql = "pragma table_info('" + tableName + "')"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, statement); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] Prepare the analysis schema field statement error:%d", errCode); + return errCode; + } + + do { + errCode = SQLiteUtils::StepWithRetry(statement); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + break; + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + errCode = SetFieldInfo(statement, table); + if (errCode != E_OK) { + break; + } + } else { + LOGW("[AnalysisSchema] Step for the analysis schema field failed:%d", errCode); + break; + } + } while (errCode == E_OK); + + if (table.GetPrimaryKey().empty()) { + table.SetPrimaryKey("rowid", 1); + } + + int ret = E_OK; + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode != E_OK ? errCode : ret; +} + +int SQLiteUtils::AnalysisSchema(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive) +{ + if (db == nullptr) { + return -E_INVALID_DB; + } + + if (!DBCommon::CheckIsAlnumOrUnderscore(tableName)) { + LOGE("[AnalysisSchema] unsupported table name."); + return -E_NOT_SUPPORT; + } + + int errCode = AnalysisSchemaSqlAndTrigger(db, tableName, table, caseSensitive); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] Analysis sql and trigger failed. errCode = [%d]", errCode); + return errCode; + } + + errCode = AnalysisSchemaIndex(db, tableName, table); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] Analysis index failed."); + return errCode; + } + + errCode = AnalysisSchemaFieldDefine(db, tableName, table); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] Analysis field failed."); + return errCode; + } + + table.SetTableName(tableName); + return E_OK; +} +#endif + +int SQLiteUtils::BindTextToStatement(sqlite3_stmt *statement, int index, const std::string &str) +{ + if (statement == nullptr) { + return -E_INVALID_ARGS; + } + + int errCode = sqlite3_bind_text(statement, index, str.c_str(), str.length(), SQLITE_TRANSIENT); + if (errCode != SQLITE_OK) { + LOGE("[SQLiteUtil][Bind text]Failed to bind the value:%d", errCode); + return SQLiteUtils::MapSQLiteErrno(errCode); + } + + return E_OK; +} + +int SQLiteUtils::ProcessStatementErrCode(sqlite3_stmt *&statement, bool isNeedFinalize, int errCode) +{ + int ret = E_OK; + SQLiteUtils::ResetStatement(statement, isNeedFinalize, ret); + return errCode != E_OK ? errCode : ret; +} + +int SQLiteUtils::CheckTableExists(sqlite3 *db, const std::string &tableName, bool &isCreated, bool isCheckMeta) +{ + if (db == nullptr) { + return -1; + } + + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, isCheckMeta ? CHECK_META_DB_TABLE_CREATED : CHECK_TABLE_CREATED, stmt); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) { + LOGE("Get check table statement failed. err=%d", errCode); + return errCode; + } + + errCode = SQLiteUtils::BindTextToStatement(stmt, 1, tableName); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) { + LOGE("Bind table name to statement failed. err=%d", errCode); + return ProcessStatementErrCode(stmt, true, errCode); + } + + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + LOGE("Check table exists failed. err=%d", errCode); // should always return a row data + return ProcessStatementErrCode(stmt, true, errCode); + } + errCode = E_OK; + isCreated = (sqlite3_column_int(stmt, 0) == 1); + return ProcessStatementErrCode(stmt, true, errCode); +} + +int SQLiteUtils::BindBlobToStatement(sqlite3_stmt *statement, int index, const std::vector &value, + bool permEmpty) +{ + if (statement == nullptr) { + return -E_INVALID_ARGS; + } + + // Check empty value. + if (value.empty() && !permEmpty) { + LOGI("[SQLiteUtil][Bind blob]Invalid value"); + return -E_INVALID_ARGS; + } + + int errCode; + if (value.empty()) { + errCode = sqlite3_bind_zeroblob(statement, index, -1); // -1 for zero-length blob. + } else { + errCode = sqlite3_bind_blob(statement, index, static_cast(value.data()), + value.size(), SQLITE_TRANSIENT); + } + + if (errCode != SQLITE_OK) { + LOGE("[SQLiteUtil][Bind blob]Failed to bind the value:%d", errCode); + return SQLiteUtils::MapSQLiteErrno(errCode); + } + + return E_OK; +} + +int SQLiteUtils::GetColumnTextValue(sqlite3_stmt *statement, int index, std::string &value) +{ + if (statement == nullptr) { + return -E_INVALID_ARGS; + } + + int valSize = sqlite3_column_bytes(statement, index); + if (valSize < 0) { + LOGW("[SQLiteUtils][Column Text] size less than zero:%d", valSize); + value = {}; + return E_OK; + } + const unsigned char *val = sqlite3_column_text(statement, index); + if (valSize == 0 || val == nullptr) { + value = {}; + return E_OK; + } + value = std::string(reinterpret_cast(val)); + if (valSize > MAX_TEXT_READ_SIZE) { + LOGW("[SQLiteUtils][Column text] size over limit:%d", valSize); + value.resize(MAX_TEXT_READ_SIZE + 1); // Reset value size to invalid + } + return E_OK; +} + +int SQLiteUtils::GetColumnBlobValue(sqlite3_stmt *statement, int index, std::vector &value) +{ + if (statement == nullptr) { + return -E_INVALID_ARGS; + } + + int keySize = sqlite3_column_bytes(statement, index); + if (keySize < 0) { + LOGW("[SQLiteUtils][Column blob] size less than zero:%d", keySize); + value.resize(0); + return E_OK; + } + auto keyRead = static_cast(sqlite3_column_blob(statement, index)); + if (keySize == 0 || keyRead == nullptr) { + value.resize(0); + } else { + if (keySize > MAX_BLOB_READ_SIZE) { + LOGW("[SQLiteUtils][Column blob] size over limit:%d", keySize); + keySize = MAX_BLOB_READ_SIZE + 1; + } + value.resize(keySize); + value.assign(keyRead, keyRead + keySize); + } + return E_OK; +} + +int SQLiteUtils::GetCountBySql(sqlite3 *db, const std::string &sql, int &count) +{ + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][GetCountBySql] Get stmt failed when get local data count: %d", errCode); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(stmt, false); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + count = static_cast(sqlite3_column_int(stmt, 0)); + errCode = E_OK; + } else { + LOGE("[SQLiteUtils][GetCountBySql] Query local data count failed: %d", errCode); + } + int ret = E_OK; + SQLiteUtils::ResetStatement(stmt, true, ret); + if (ret != E_OK) { + LOGE("[SQLiteUtils][GetCountBySql] Reset stmt failed when get local data count: %d", ret); + } + return errCode != E_OK ? errCode : ret; +} + +int SQLiteUtils::BindInt64ToStatement(sqlite3_stmt *statement, int index, int64_t value) +{ + // statement check outSide + int errCode = sqlite3_bind_int64(statement, index, value); + if (errCode != SQLITE_OK) { + LOGE("[SQLiteUtil][Bind int64]Failed to bind the value:%d", errCode); + return SQLiteUtils::MapSQLiteErrno(errCode); + } + + return E_OK; +} +} // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp index 2164d1871ba20e8640a7275cabff0b366f76ca56..7100ec7890170e218e6b8cf7a06877ed8eeec44f 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp @@ -46,11 +46,6 @@ namespace { const std::string WAL_MODE_SQL = "PRAGMA journal_mode=WAL;"; const std::string SHA1_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA1;"; const std::string SHA256_ALGO_REKEY_SQL = "PRAGMA codec_rekey_hmac_algo=SHA256;"; - - const constexpr char *CHECK_TABLE_CREATED = "SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE " \ - "type='table' AND (tbl_name=? COLLATE NOCASE));"; - const constexpr char *CHECK_META_DB_TABLE_CREATED = "SELECT EXISTS(SELECT 1 FROM meta.sqlite_master WHERE " \ - "type='table' AND (tbl_name=? COLLATE NOCASE));"; } struct ValueParseCache { @@ -648,38 +643,6 @@ int SQLiteUtils::UpdateCipherShaAlgo(sqlite3 *db, bool setWal, CipherType type, return Rekey(db, passwd); } -int SQLiteUtils::CheckTableExists(sqlite3 *db, const std::string &tableName, bool &isCreated, bool isCheckMeta) -{ - if (db == nullptr) { - return -1; - } - - sqlite3_stmt *stmt = nullptr; - int errCode = SQLiteUtils::GetStatement(db, isCheckMeta ? CHECK_META_DB_TABLE_CREATED : CHECK_TABLE_CREATED, stmt); - if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) { - LOGE("Get check table statement failed. err=%d", errCode); - return errCode; - } - - errCode = SQLiteUtils::BindTextToStatement(stmt, 1, tableName); - if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) { - LOGE("Bind table name to statement failed. err=%d", errCode); - goto END; - } - - errCode = SQLiteUtils::StepWithRetry(stmt); - if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - LOGE("Check table exists failed. err=%d", errCode); // should always return a row data - goto END; - } - errCode = E_OK; - isCreated = (sqlite3_column_int(stmt, 0) == 1); -END: - int ret = E_OK; - SQLiteUtils::ResetStatement(stmt, true, ret); - return errCode != E_OK ? errCode : ret; -} - int SQLiteUtils::StepNext(sqlite3_stmt *stmt, bool isMemDb) { if (stmt == nullptr) { @@ -694,29 +657,6 @@ int SQLiteUtils::StepNext(sqlite3_stmt *stmt, bool isMemDb) return errCode; } -int SQLiteUtils::GetCountBySql(sqlite3 *db, const std::string &sql, int &count) -{ - sqlite3_stmt *stmt = nullptr; - int errCode = SQLiteUtils::GetStatement(db, sql, stmt); - if (errCode != E_OK) { - LOGE("[SQLiteUtils][GetCountBySql] Get stmt failed when get local data count: %d", errCode); - return errCode; - } - errCode = SQLiteUtils::StepWithRetry(stmt, false); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - count = static_cast(sqlite3_column_int(stmt, 0)); - errCode = E_OK; - } else { - LOGE("[SQLiteUtils][GetCountBySql] Query local data count failed: %d", errCode); - } - int ret = E_OK; - SQLiteUtils::ResetStatement(stmt, true, ret); - if (ret != E_OK) { - LOGE("[SQLiteUtils][GetCountBySql] Reset stmt failed when get local data count: %d", ret); - } - return errCode != E_OK ? errCode : ret; -} - bool SQLiteUtils::IsStmtReadOnly(sqlite3_stmt *statement) { if (statement == nullptr) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp index 7536ee532a225a16ab11559f2aa4f751ff7a23f9..b691cd14deddd1b5685bae9a4586f325b0f02c72 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp @@ -16,6 +16,7 @@ #include "storage_engine.h" #include +#include #include "db_common.h" #include "db_errno.h" @@ -37,11 +38,14 @@ StorageEngine::StorageEngine() perm_(OperatePerm::NORMAL_PERM), operateAbort_(false), isExistConnection_(false), + readPendingCount_(0), + externalReadPendingCount_(0), engineState_(EngineState::INVALID) {} StorageEngine::~StorageEngine() { + LOGI("[StorageEngine] close executor"); CloseExecutor(); } @@ -55,13 +59,15 @@ int StorageEngine::InitAllReadWriteExecutor() return InitReadWriteExecutors(); } -OpenDbProperties StorageEngine::GetOption() +OpenDbProperties StorageEngine::GetOption() const { + std::lock_guard autoLock(optionMutex_); return option_; } int StorageEngine::InitReadWriteExecutors() { + PrintDbFileMsg(true); int errCode = E_OK; std::scoped_lock initLock(writeMutex_, readMutex_); // only for create the database avoid the minimum number is 0. @@ -199,42 +205,91 @@ StorageExecutor *StorageEngine::FindWriteExecutor(OperatePerm perm, int &errCode StorageExecutor *StorageEngine::FindReadExecutor(OperatePerm perm, int &errCode, int waitTime, bool isExternal) { - std::unique_lock lock(readMutex_); - errCode = -E_BUSY; - if (perm_ == OperatePerm::DISABLE_PERM || perm_ != perm) { - LOGI("Not permitted to get the executor[%u]", static_cast(perm_)); - return nullptr; - } - - std::list &readUsingList = isExternal ? externalReadUsingList_ : readUsingList_; - std::list &readIdleList = isExternal ? externalReadIdleList_ : readIdleList_; - if (waitTime <= 0) { // non-blocking. - if (readIdleList.empty() && - readIdleList.size() + readUsingList.size() == engineAttr_.maxReadNum) { + auto &pendingCount = isExternal ? externalReadPendingCount_ : readPendingCount_; + bool isNeedCreate = false; + { + std::unique_lock lock(readMutex_); + errCode = -E_BUSY; + if (perm_ == OperatePerm::DISABLE_PERM || perm_ != perm) { + LOGI("Not permitted to get the executor[%u]", static_cast(perm_)); return nullptr; } - return FetchStorageExecutor(false, readIdleList, readUsingList, errCode, isExternal); + std::list &readUsingList = isExternal ? externalReadUsingList_ : readUsingList_; + std::list &readIdleList = isExternal ? externalReadIdleList_ : readIdleList_; + if (waitTime <= 0) { // non-blocking. + auto pending = static_cast(pendingCount.load()); + if (readIdleList.empty() && readUsingList.size() + pending == engineAttr_.maxReadNum) { + return nullptr; + } + } else { + // Not prohibited and there is an available handle + uint32_t maxReadHandleNum = isExternal ? 1 : engineAttr_.maxReadNum; + bool result = readCondition_.wait_for(lock, std::chrono::seconds(waitTime), + [this, &perm, &readUsingList, &readIdleList, &maxReadHandleNum, &pendingCount]() { + auto pending = static_cast(pendingCount.load()); + bool isHandleLessMax; + if (readIdleList.size() > pending) { + // readIdleList.size() + readUsingList.size() - 1 should not greater than maxReadHandleNum + // -1 because handle will use from idle list + isHandleLessMax = readIdleList.size() + readUsingList.size() < maxReadHandleNum + 1; + } else { + isHandleLessMax = pending + readUsingList.size() < maxReadHandleNum; + } + return (perm_ == OperatePerm::NORMAL_PERM || perm_ == perm) && (isHandleLessMax || operateAbort_); + }); + if (operateAbort_) { + LOGI("Abort find read executor and busy for operate!"); + return nullptr; + } + if (!result) { + LOGI("Get read handle result[%d], permissType[%u], operType[%u], read[%zu-%zu-%" PRIu32 "]" + "pending count[%d]", result, static_cast(perm_), static_cast(perm), + readIdleList.size(), readUsingList.size(), engineAttr_.maxReadNum, pendingCount.load()); + return nullptr; + } + } + pendingCount++; + isNeedCreate = readIdleList.size() < static_cast(pendingCount.load()); } + auto executor = FetchReadStorageExecutor(errCode, isExternal, isNeedCreate); + readCondition_.notify_all(); + return executor; +} - // Not prohibited and there is an available handle - uint32_t maxReadHandleNum = isExternal ? 1 : engineAttr_.maxReadNum; - bool result = readCondition_.wait_for(lock, std::chrono::seconds(waitTime), - [this, &perm, &readUsingList, &readIdleList, &maxReadHandleNum]() { - return (perm_ == OperatePerm::NORMAL_PERM || perm_ == perm) && - (!readIdleList.empty() || (readIdleList.size() + readUsingList.size() < maxReadHandleNum) || - operateAbort_); - }); - if (operateAbort_) { - LOGI("Abort find read executor and busy for operate!"); - return nullptr; +StorageExecutor *StorageEngine::FetchReadStorageExecutor(int &errCode, bool isExternal, bool isNeedCreate) +{ + StorageExecutor *handle = nullptr; + if (isNeedCreate) { + errCode = CreateNewExecutor(false, handle); } - if (!result) { - LOGI("Get read handle result[%d], permissType[%u], operType[%u], read[%zu-%zu-%" PRIu32 "]", result, - static_cast(perm_), static_cast(perm), readIdleList.size(), readUsingList.size(), - engineAttr_.maxReadNum); - return nullptr; + std::unique_lock lock(readMutex_); + auto &pendingCount = isExternal ? externalReadPendingCount_ : readPendingCount_; + pendingCount--; + if (isNeedCreate) { + auto &usingList = isExternal ? externalReadUsingList_ : readUsingList_; + if ((errCode != E_OK) || (handle == nullptr)) { + if (errCode != -E_EKEYREVOKED) { + return nullptr; + } + LOGE("Key revoked status, couldn't create the new executor"); + if (!usingList.empty()) { + LOGE("Can't create new executor for revoked"); + errCode = -E_BUSY; + } + return nullptr; + } + AddStorageExecutor(handle, isExternal); } - return FetchStorageExecutor(false, readIdleList, readUsingList, errCode, isExternal); + auto &usingList = isExternal ? externalReadUsingList_ : readUsingList_; + auto &idleList = isExternal ? externalReadIdleList_ : readIdleList_; + auto item = idleList.front(); + usingList.push_back(item); + idleList.remove(item); + if (!isEnhance_) { + LOGD("Get executor[0] from [%.3s]", hashIdentifier_.c_str()); + } + errCode = E_OK; + return item; } void StorageEngine::Recycle(StorageExecutor *&handle, bool isExternal) @@ -263,21 +318,25 @@ void StorageEngine::Recycle(StorageExecutor *&handle, bool isExternal) idleCondition_.notify_all(); } } else { - std::unique_lock lock(readMutex_); - std::list &readUsingList = isExternal ? externalReadUsingList_ : readUsingList_; - std::list &readIdleList = isExternal ? externalReadIdleList_ : readIdleList_; - auto iter = std::find(readUsingList.begin(), readUsingList.end(), handle); - if (iter != readUsingList.end()) { - readUsingList.remove(handle); - if (!readIdleList.empty()) { - delete handle; - handle = nullptr; - return; + StorageExecutor *releaseHandle = nullptr; + { + std::unique_lock lock(readMutex_); + std::list &readUsingList = isExternal ? externalReadUsingList_ : readUsingList_; + std::list &readIdleList = isExternal ? externalReadIdleList_ : readIdleList_; + auto iter = std::find(readUsingList.begin(), readUsingList.end(), handle); + if (iter != readUsingList.end()) { + readUsingList.remove(handle); + if (!readIdleList.empty()) { + releaseHandle = handle; + handle = nullptr; + } else { + handle->Reset(); + readIdleList.push_back(handle); + readCondition_.notify_one(); + } } - handle->Reset(); - readIdleList.push_back(handle); - readCondition_.notify_one(); } + delete releaseHandle; } handle = nullptr; } @@ -449,6 +508,7 @@ void StorageEngine::CloseExecutor() ClearHandleList(readIdleList_); ClearHandleList(externalReadIdleList_); } + PrintDbFileMsg(false); } StorageExecutor *StorageEngine::FetchStorageExecutor(bool isWrite, std::list &idleList, @@ -526,4 +586,72 @@ void StorageEngine::SetSchemaChangedCallback(const std::function &cal std::unique_lock lock(schemaChangedMutex_); schemaChangedFunc_ = callback; } + +void StorageEngine::PrintDbFileMsg(bool isOpen) +{ + OpenDbProperties option = GetOption(); + std::string dbFilePath = option.uri; + if (option.isMemDb || dbFilePath.empty()) { + return; + } + struct stat dbFileStat; + if (memset_s(&dbFileStat, sizeof(struct stat), 0, sizeof(struct stat)) != E_OK) { + LOGW("init db file stat fail"); + return; + } + stat(dbFilePath.c_str(), &dbFileStat); + std::string dbWalFilePath = dbFilePath + "-wal"; + struct stat dbWalFileStat; + if (memset_s(&dbWalFileStat, sizeof(struct stat), 0, sizeof(struct stat)) != E_OK) { + LOGW("init db wal file stat fail"); + return; + } + stat(dbWalFilePath.c_str(), &dbWalFileStat); + std::string dbShmFilePath = dbFilePath + "-shm"; + struct stat dbShmFileStat; + if (memset_s(&dbShmFileStat, sizeof(struct stat), 0, sizeof(struct stat)) != E_OK) { + LOGW("init db shm file stat fail"); + return; + } + stat(dbShmFilePath.c_str(), &dbShmFileStat); + std::string dbDwrFilePath = dbFilePath + "-dwr"; + struct stat dbDwrFileStat; + if (memset_s(&dbDwrFileStat, sizeof(struct stat), 0, sizeof(struct stat)) != E_OK) { + LOGW("init db dwr file stat fail"); + return; + } + stat(dbDwrFilePath.c_str(), &dbDwrFileStat); + std::string stage = isOpen ? "before open db," : "after close db,"; +#ifdef __linux__ + LOGI("%s db file: [size: %lld, mtime: %lld, inode: %llu], db-wal file: [size: %lld, mtime: %lld, inode: %llu], " + "db-shm file: [size: %lld, mtime: %lld, inode: %llu], db-dwr file: [size: %lld, mtime: %lld, inode: %llu]", + stage.c_str(), dbFileStat.st_size, dbFileStat.st_mtim.tv_sec, dbFileStat.st_ino, dbWalFileStat.st_size, + dbWalFileStat.st_mtim.tv_sec, dbWalFileStat.st_ino, dbShmFileStat.st_size, dbShmFileStat.st_mtim.tv_sec, + dbShmFileStat.st_ino, dbDwrFileStat.st_size, dbDwrFileStat.st_mtim.tv_sec, dbDwrFileStat.st_ino); +#endif +} + +void StorageEngine::SetUri(const std::string &uri) +{ + std::lock_guard autoLock(optionMutex_); + option_.uri = uri; +} + +void StorageEngine::SetSQL(const std::vector &sql) +{ + std::lock_guard autoLock(optionMutex_); + option_.sqls = sql; +} + +void StorageEngine::SetSecurityOption(const SecurityOption &option) +{ + std::lock_guard autoLock(optionMutex_); + option_.securityOpt = option; +} + +void StorageEngine::SetCreateIfNecessary(bool isCreateIfNecessary) +{ + std::lock_guard autoLock(optionMutex_); + option_.createIfNecessary = isCreateIfNecessary; +} } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.h index 980855813c1835fdfc1ef4c33c7aab6dd464164d..cf3c514b7c4a7c5eb0ec7050d383f6e76e47f2b4 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.h @@ -94,7 +94,7 @@ public: int InitAllReadWriteExecutor(); - OpenDbProperties GetOption(); + OpenDbProperties GetOption() const; protected: virtual int CreateNewExecutor(bool isWrite, StorageExecutor *&handle) = 0; @@ -107,6 +107,12 @@ protected: int InitReadWriteExecutors(); + void SetUri(const std::string &uri); + void SetSQL(const std::vector &sql); + void SetSecurityOption(const SecurityOption &option); + void SetCreateIfNecessary(bool isCreateIfNecessary); + + mutable std::mutex optionMutex_; OpenDbProperties option_; StorageEngineAttr engineAttr_; @@ -138,8 +144,12 @@ private: StorageExecutor *FindWriteExecutor(OperatePerm perm, int &errCode, int waitTime, bool isExternal = false); StorageExecutor *FindReadExecutor(OperatePerm perm, int &errCode, int waitTime, bool isExternal = false); + StorageExecutor *FetchReadStorageExecutor(int &errCode, bool isExternal, bool isNeedCreate); + virtual void ClearCorruptedFlag(); + void PrintDbFileMsg(bool isOpen); + static const int MAX_WAIT_TIME; static const int MAX_WRITE_SIZE; static const int MAX_READ_SIZE; @@ -167,6 +177,9 @@ private: std::mutex idleMutex_; std::condition_variable idleCondition_; + std::atomic readPendingCount_; + std::atomic externalReadPendingCount_; + EngineState engineState_; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp index 0899eafe93c2ddb762a5ab73bf892c38795e27e6..ff7526fcf29d56837bf1cdb03641a194a57aa483 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp @@ -71,10 +71,6 @@ int StorageProxy::GetLocalWaterMarkByMode(const std::string &tableName, CloudWat if (cloudMetaData_ == nullptr) { return -E_INVALID_DB; } - if (transactionExeFlag_.load() && isWrite_.load()) { - LOGE("the write transaction has been started, can not get meta"); - return -E_BUSY; - } return cloudMetaData_->GetLocalWaterMarkByType(AppendWithUserIfNeed(tableName), mode, localMark); } @@ -122,41 +118,41 @@ int StorageProxy::SetCloudWaterMark(const std::string &tableName, std::string &c return cloudMetaData_->SetCloudWaterMark(AppendWithUserIfNeed(tableName), cloudMark); } -int StorageProxy::StartTransaction(TransactType type) +int StorageProxy::StartTransaction(TransactType type, bool isAsyncDownload) { std::shared_lock readLock(storeMutex_); if (store_ == nullptr) { return -E_INVALID_DB; } - int errCode = store_->StartTransaction(type); - if (errCode == E_OK) { + int errCode = store_->StartTransaction(type, isAsyncDownload); + if (errCode == E_OK && !isAsyncDownload) { transactionExeFlag_.store(true); isWrite_.store(type == TransactType::IMMEDIATE); } return errCode; } -int StorageProxy::Commit() +int StorageProxy::Commit(bool isAsyncDownload) { std::shared_lock readLock(storeMutex_); if (store_ == nullptr) { return -E_INVALID_DB; } - int errCode = store_->Commit(); - if (errCode == E_OK) { + int errCode = store_->Commit(isAsyncDownload); + if (errCode == E_OK && !isAsyncDownload) { transactionExeFlag_.store(false); } return errCode; } -int StorageProxy::Rollback() +int StorageProxy::Rollback(bool isAsyncDownload) { std::shared_lock readLock(storeMutex_); if (store_ == nullptr) { return -E_INVALID_DB; } - int errCode = store_->Rollback(); - if (errCode == E_OK) { + int errCode = store_->Rollback(isAsyncDownload); + if (errCode == E_OK && !isAsyncDownload) { transactionExeFlag_.store(false); } return errCode; @@ -169,10 +165,6 @@ int StorageProxy::GetUploadCount(const QuerySyncObject &query, const bool isClou if (store_ == nullptr) { return -E_INVALID_DB; } - if (!transactionExeFlag_.load()) { - LOGE("the transaction has not been started"); - return -E_TRANSACT_STATE; - } std::vector timeStampVec; std::vector waterTypeVec = DBCommon::GetWaterTypeVec(); for (size_t i = 0; i < waterTypeVec.size(); i++) { @@ -196,10 +188,6 @@ int StorageProxy::GetUploadCount(const std::string &tableName, const Timestamp & if (store_ == nullptr) { return -E_INVALID_DB; } - if (!transactionExeFlag_.load()) { - LOGE("the transaction has not been started"); - return -E_TRANSACT_STATE; - } QuerySyncObject query; query.SetTableName(tableName); return store_->GetUploadCount(query, localMark, isCloudForcePush, false, count); @@ -212,10 +200,6 @@ int StorageProxy::GetUploadCount(const QuerySyncObject &query, const Timestamp & if (store_ == nullptr) { return -E_INVALID_DB; } - if (!transactionExeFlag_.load()) { - LOGE("the transaction has not been started"); - return -E_TRANSACT_STATE; - } return store_->GetUploadCount(query, localMark, isCloudForcePush, isCompensatedTask, count); } @@ -234,10 +218,6 @@ int StorageProxy::GetCloudData(const QuerySyncObject &querySyncObject, const Tim if (store_ == nullptr) { return -E_INVALID_DB; } - if (!transactionExeFlag_.load()) { - LOGE("the transaction has not been started"); - return -E_TRANSACT_STATE; - } TableSchema tableSchema; int errCode = store_->GetCloudTableSchema(querySyncObject.GetRelationTableName(), tableSchema); if (errCode != E_OK) { @@ -252,10 +232,6 @@ int StorageProxy::GetCloudDataNext(ContinueToken &continueStmtToken, CloudSyncDa if (store_ == nullptr) { return -E_INVALID_DB; } - if (!transactionExeFlag_.load()) { - LOGE("the transaction has not been started"); - return -E_TRANSACT_STATE; - } return store_->GetCloudDataNext(continueStmtToken, cloudDataResult); } @@ -523,10 +499,6 @@ int StorageProxy::FillCloudLogAndAsset(OpType opType, const CloudSyncData &data) if (store_ == nullptr) { return -E_INVALID_DB; } - if (!transactionExeFlag_.load()) { - LOGE("the transaction has not been started"); - return -E_TRANSACT_STATE; - } return store_->FillCloudLogAndAsset(opType, data, true, false); } @@ -872,4 +844,10 @@ bool StorageProxy::IsExistTableContainAssets() } return store_->IsExistTableContainAssets(); } + +bool StorageProxy::GetTransactionExeFlag() +{ + std::shared_lock readLock(storeMutex_); + return transactionExeFlag_.load(); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.cpp index 620302ddd7d222532bbffdc43372d90ebc98a99f..e20d98586fedc82e5e14dd878254ed767b3f1e4a 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.cpp @@ -43,7 +43,7 @@ SyncAbleEngine::~SyncAbleEngine() } // Start a sync action. -int SyncAbleEngine::Sync(const ISyncer::SyncParma &parm, uint64_t connectionId) +int SyncAbleEngine::Sync(const ISyncer::SyncParam &parm, uint64_t connectionId) { if (!started_) { int errCode = StartSyncer(); @@ -121,13 +121,13 @@ int SyncAbleEngine::StartSyncerWithNoLock(bool isCheckSyncActive, bool isNeedAct // active to non_active userChangeListener_ = RuntimeContext::GetInstance()->RegisterUserChangedListener( [this](void *) { ChangeUserListener(); }, UserChangeMonitor::USER_ACTIVE_TO_NON_ACTIVE_EVENT); - LOGI("[StartSyncerWithNoLock] [%.3s] After RegisterUserChangedListener", label.c_str()); + LOGI("[StartSyncerWithNoLock] [%.3s]", label.c_str()); } else if (isSyncDualTupleMode && (userChangeListener_ == nullptr)) { EventType event = isNeedActive ? UserChangeMonitor::USER_ACTIVE_EVENT : UserChangeMonitor::USER_NON_ACTIVE_EVENT; userChangeListener_ = RuntimeContext::GetInstance()->RegisterUserChangedListener( [this](void *) { UserChangeHandle(); }, event); - LOGI("[StartSyncerWithNoLock] [%.3s] After RegisterUserChangedListener event=%d", label.c_str(), event); + LOGI("[StartSyncerWithNoLock] [%.3s] event=%d", label.c_str(), event); } return errCode; } @@ -291,4 +291,13 @@ int SyncAbleEngine::GetHashDeviceId(const std::string &clientId, std::string &ha } return syncer_.GetHashDeviceId(clientId, hashDevId); } + +int SyncAbleEngine::GetDeviceSyncTaskCount() +{ + if (NeedStartSyncer()) { + LOGW("[SyncAbleEngine] Syncer not start when get device sync task count"); + return 0; + } + return syncer_.GetTaskCount(); +} } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.h index f1ab74cd241f71eb1ca15e5cf450da191529eb54..307d2033ba54a14df3434912140668a53b657564 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.h @@ -29,7 +29,7 @@ public: ~SyncAbleEngine(); // Start a sync action. - int Sync(const ISyncer::SyncParma &parm, uint64_t connectionId); + int Sync(const ISyncer::SyncParam &parm, uint64_t connectionId); void WakeUpSyncer(); void Close(); @@ -50,6 +50,8 @@ public: uint64_t connectionId, std::shared_ptr &result); int GetHashDeviceId(const std::string &clientId, std::string &hashDevId); + + int GetDeviceSyncTaskCount(); private: // Start syncer int StartSyncer(bool isCheckSyncActive = false, bool isNeedActive = true); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/include/isyncer.h b/kv_store/frameworks/libs/distributeddb/syncer/include/isyncer.h index 61e0c44c45d67af9056ab480c021ef6501b2d4bb..426f83df086975b316e45bc2578bb087e0f279fc 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/include/isyncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/include/isyncer.h @@ -35,7 +35,7 @@ struct SyncerBasicInfo { }; class ISyncer { public: - struct SyncParma { + struct SyncParam { std::vector devices; std::function &devicesMap)> onComplete; SyncStatusCallback relationOnComplete; @@ -43,6 +43,7 @@ public: int mode = 0; bool wait = false; bool isQuerySync = false; + bool isRetry = true; QuerySyncObject syncQuery; DeviceSyncProcessCallback onSyncProcess; }; @@ -65,8 +66,8 @@ public: const std::function &)> &onComplete, const std::function &onFinalize, bool wait) = 0; - // Sync function. use SyncParma to reduce parameter. - virtual int Sync(const SyncParma ¶m, uint64_t connectionId) = 0; + // Sync function. use SyncParam to reduce parameter. + virtual int Sync(const SyncParam ¶m, uint64_t connectionId) = 0; // Cancel sync function. virtual int CancelSync(uint32_t syncId) = 0; @@ -139,6 +140,8 @@ public: virtual int64_t GetLocalTimeOffset() = 0; virtual int32_t GetTaskCount() = 0; + + virtual bool ExchangeClosePending(bool expected) = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/include/syncer_proxy.h b/kv_store/frameworks/libs/distributeddb/syncer/include/syncer_proxy.h index 0f6d5bc7dd7d471e03e6a019a4407b0d9adffbba..481d592d395924498b9111ef196dc7db11ba54f7 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/include/syncer_proxy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/include/syncer_proxy.h @@ -45,8 +45,8 @@ public: const std::function &)> &onComplete, const std::function &onFinalize, bool wait) override; - // Sync function. use SyncParma to reduce parameter. - int Sync(const SyncParma ¶m, uint64_t connectionId) override; + // Sync function. use SyncParam to reduce parameter. + int Sync(const SyncParam ¶m, uint64_t connectionId) override; // Cancel sync function. int CancelSync(uint32_t syncId) override; @@ -121,6 +121,8 @@ public: int64_t GetLocalTimeOffset() override; int32_t GetTaskCount() override; + + bool ExchangeClosePending(bool expected) override; private: std::mutex syncerLock_; std::shared_ptr syncer_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp index 992b60b5c1d81c5ace74afe291df3bb3fa1c6e28..6e549656191266cc8d5590cc11b7706870697511 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp @@ -17,6 +17,7 @@ #include "cloud/cloud_storage_utils.h" #include "db_common.h" #include "db_errno.h" +#include "kv_store_errno.h" #include "log_print.h" namespace DistributedDB { @@ -92,11 +93,21 @@ void CloudDBProxy::RecordSyncDataTimeStampLog(std::vector &data, InnerA static_cast(action), data.size(), first, last); } +void CloudDBProxy::FillErrorToExtend(int error, std::vector &extend) +{ + for (auto &item : extend) { + if (item.find(CloudDbConstant::ERROR_FIELD) == item.end()) { + item[CloudDbConstant::ERROR_FIELD] = static_cast(TransferDBErrno(error)); + } + } +} + int CloudDBProxy::BatchInsert(const std::string &tableName, std::vector &record, std::vector &extend, Info &uploadInfo, uint32_t &retryCount) { std::shared_lock readLock(cloudMutex_); if (iCloudDb_ == nullptr) { + FillErrorToExtend(static_cast(-E_CLOUD_ERROR), extend); return -E_CLOUD_ERROR; } std::shared_ptr cloudDb = iCloudDb_; @@ -115,6 +126,7 @@ int CloudDBProxy::BatchUpdate(const std::string &tableName, std::vector { std::shared_lock readLock(cloudMutex_); if (iCloudDb_ == nullptr) { + FillErrorToExtend(static_cast(-E_CLOUD_ERROR), extend); return -E_CLOUD_ERROR; } std::shared_ptr cloudDb = iCloudDb_; @@ -133,6 +145,7 @@ int CloudDBProxy::BatchDelete(const std::string &tableName, std::vector { std::shared_lock readLock(cloudMutex_); if (iCloudDb_ == nullptr) { + FillErrorToExtend(static_cast(-E_CLOUD_ERROR), extend); return -E_CLOUD_ERROR; } std::shared_ptr context = std::make_shared(); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h index c63805571f642c40e8b4dd84260e78ae82bab627..2383c0182a0cf4e335fdd7488ecab489c1ecf54a 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h @@ -198,6 +198,8 @@ protected: static void RecordSyncDataTimeStampLog(std::vector &data, InnerActionCode action); + void FillErrorToExtend(int error, std::vector &extend); + mutable std::shared_mutex cloudMutex_; mutable std::shared_mutex assetLoaderMutex_; std::shared_ptr iCloudDb_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp index f6bcc943c71e243f955a9680f89aa0e0b0ffeb12..ff6262cc14166a23032408eb32f8b4ef688e8f39 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp @@ -238,8 +238,8 @@ int CloudSyncUtils::CheckCloudSyncDataValid(const CloudSyncData &uploadData, con int64_t syncDataCount = static_cast(insRecordLen) + static_cast(updRecordLen) + static_cast(delRecordLen); if (syncDataCount > count) { - LOGE("[CloudSyncUtils] Size of a batch of sync data is greater than upload data size. count %d", count); - return -E_INTERNAL_ERROR; + LOGW("[CloudSyncUtils] Size of a batch of sync data is greater than upload data size. insRecordLen:%zu, " + "updRecordLen:%zu, delRecordLen:%zu, count %d", insRecordLen, updRecordLen, delRecordLen, count); } return E_OK; } @@ -477,7 +477,7 @@ int CloudSyncUtils::FillAssetIdToAssets(CloudSyncBatch &data, int errorCode, con } auto extendIt = data.extend[i].find(col); if (extendIt == data.extend[i].end()) { - LOGI("[CloudSyncUtils] Asset field name can not find in extend. key is:%s.", col.c_str()); + LOGI("[CloudSyncUtils] Asset field name can not find in extend."); it = data.assets[i].erase(it); continue; } @@ -669,7 +669,9 @@ void CloudSyncUtils::CheckQueryCloudData(std::string &traceId, DownloadData &dow } std::string gid; (void)CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::GID_FIELD, data, gid); - if (!isVersionExist || !isContainAllPk) { + bool isDelete = true; + (void)CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::DELETE_FIELD, data, isDelete); + if (!isDelete && (!isVersionExist || !isContainAllPk)) { LOGE("[CloudSyncer] Invalid data from cloud, no version[%d], lost primary key[%d], gid[%s], traceId[%s]", static_cast(!isVersionExist), static_cast(!isContainAllPk), gid.c_str(), traceId.c_str()); } @@ -1005,4 +1007,55 @@ int CloudSyncUtils::ClearCloudWatermark(const std::vector &tableNam return storageProxy->Commit(); } + +bool CloudSyncUtils::HaveReferenceOrReferenceByTable( + const CloudSyncer::CloudTaskInfo &taskInfo, std::shared_ptr &storageProxy) +{ + for (size_t i = 0u; i < taskInfo.table.size(); ++i) { + if (storageProxy->IsTableExistReferenceOrReferenceBy(taskInfo.table[i])) { + return true; + } + } + return false; +} + +int CloudSyncUtils::StartTransactionIfNeed( + const CloudSyncer::CloudTaskInfo &taskInfo, std::shared_ptr &storageProxy) +{ + bool isStartTransaction = true; + if (taskInfo.table.size() <= 1u || !HaveReferenceOrReferenceByTable(taskInfo, storageProxy)) { + // only one table or no reference table, no need to start transaction. + isStartTransaction = false; + } + return isStartTransaction ? storageProxy->StartTransaction() : E_OK; +} + +void CloudSyncUtils::EndTransactionIfNeed( + const int &errCode, const CloudSyncer::CloudTaskInfo &taskInfo, std::shared_ptr &storageProxy) +{ + if (!storageProxy->GetTransactionExeFlag()) { + // no need to end transaction. + return; + } + if (errCode == E_OK || errCode == -E_TASK_PAUSED) { + int commitErrorCode = storageProxy->Commit(); + if (commitErrorCode != E_OK) { + LOGE("[CloudSyncer] cannot commit transaction: %d.", commitErrorCode); + } + } else { + int rollBackErrorCode = storageProxy->Rollback(); + if (rollBackErrorCode != E_OK) { + LOGE("[CloudSyncer] cannot roll back transaction: %d.", rollBackErrorCode); + } + } +} + +bool CloudSyncUtils::CanStartAsyncDownload(int scheduleCount) +{ + if (!RuntimeContext::GetInstance()->GetAssetsDownloadManager()->CanStartNewTask()) { + LOGW("[CloudSyncer] Too many download tasks"); + return false; + } + return scheduleCount <= 0; +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h index b8960b60458d3d5795b69577b96004ca3f7603b8..6f74ab3239aa40f7ad39f03609dd01628f3e0f69 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h @@ -140,6 +140,17 @@ public: static int ClearCloudWatermark(const std::vector &tableNameList, std::shared_ptr &storageProxy); + + static bool HaveReferenceOrReferenceByTable( + const CloudSyncer::CloudTaskInfo &taskInfo, std::shared_ptr &storageProxy); + + static int StartTransactionIfNeed( + const CloudSyncer::CloudTaskInfo &taskInfo, std::shared_ptr &storageProxy); + + static void EndTransactionIfNeed( + const int &errCode, const CloudSyncer::CloudTaskInfo &taskInfo, std::shared_ptr &storageProxy); + + static bool CanStartAsyncDownload(int scheduleCount); private: static void InsertOrReplaceChangedDataByType(ChangeType type, std::vector &pkVal, ChangedData &changedData); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp index d0c91c94922ba6b5e4c6e020d161232a96dd80c3..7a774ae1ca5433462e537f87077c22ce2f370333 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp @@ -46,6 +46,7 @@ CloudSyncer::CloudSyncer( policy_(policy), asyncTaskId_(INVALID_TASK_ID), cancelAsyncTask_(false), + scheduleTaskCount_(0), waitDownloadListener_(nullptr) { if (storageProxy_ != nullptr) { @@ -227,6 +228,7 @@ int CloudSyncer::DoSync(TaskId taskId) } bool needUpload = true; bool isNeedFirstDownload = false; + bool isLockAction = IsLockInDownload(); { std::lock_guard autoLock(dataLock_); if (currentContext_.strategy != nullptr) { @@ -234,13 +236,13 @@ int CloudSyncer::DoSync(TaskId taskId) } // 1. if the locker is already exist, directly reuse the lock, no need do the first download // 2. if the task(resume task) is already be tagged need upload data, no need do the first download - isNeedFirstDownload = (currentContext_.locker == nullptr) && (!currentContext_.isNeedUpload); + isNeedFirstDownload = (currentContext_.locker == nullptr) && (!currentContext_.isNeedUpload) && + isLockAction; } - int errCode = E_OK; bool isFirstDownload = true; if (isNeedFirstDownload) { // do first download - errCode = DoDownloadInNeed(taskInfo, needUpload, isFirstDownload); + int errCode = DoDownloadInNeed(taskInfo, needUpload, isFirstDownload); SetTaskFailed(taskId, errCode); if (errCode != E_OK) { SyncMachineDoFinished(); @@ -264,8 +266,7 @@ int CloudSyncer::DoSync(TaskId taskId) currentContext_.isFirstDownload = isFirstDownload; currentContext_.isRealNeedUpload = needUpload; } - errCode = DoSyncInner(taskInfo); - return errCode; + return DoSyncInner(taskInfo); } int CloudSyncer::PrepareAndUpload(const CloudTaskInfo &taskInfo, size_t index) @@ -306,7 +307,7 @@ int CloudSyncer::DoUploadInNeed(const CloudTaskInfo &taskInfo, const bool needUp return E_OK; } storageProxy_->BeforeUploadTransaction(); - int errCode = storageProxy_->StartTransaction(); + int errCode = CloudSyncUtils::StartTransactionIfNeed(taskInfo, storageProxy_); if (errCode != E_OK) { LOGE("[CloudSyncer] start transaction failed before doing upload."); return errCode; @@ -332,17 +333,7 @@ int CloudSyncer::DoUploadInNeed(const CloudTaskInfo &taskInfo, const bool needUp std::lock_guard autoLock(dataLock_); resumeTaskInfos_[taskInfo.taskId].upload = true; } - if (errCode == E_OK || errCode == -E_TASK_PAUSED) { - int commitErrorCode = storageProxy_->Commit(); - if (commitErrorCode != E_OK) { - LOGE("[CloudSyncer] cannot commit transaction: %d.", commitErrorCode); - } - } else { - int rollBackErrorCode = storageProxy_->Rollback(); - if (rollBackErrorCode != E_OK) { - LOGE("[CloudSyncer] cannot roll back transaction: %d.", rollBackErrorCode); - } - } + CloudSyncUtils::EndTransactionIfNeed(errCode, taskInfo, storageProxy_); return errCode; } @@ -443,7 +434,9 @@ CloudSyncEvent CloudSyncer::SyncMachineDoFinished() taskInfo = cloudTaskInfos_[currentContext_.currentTaskId]; } taskInfo.status = ProcessStatus::FINISHED; - currentContext_.notifier->NotifyProcess(taskInfo, {}, true); + if (currentContext_.notifier != nullptr) { + currentContext_.notifier->NotifyProcess(taskInfo, {}, true); + } { std::lock_guard autoLock(dataLock_); cloudTaskInfos_[currentContext_.currentTaskId].errCode = E_OK; @@ -884,7 +877,7 @@ int CloudSyncer::SaveData(CloudSyncer::TaskId taskId, SyncParam ¶m) param.info.downLoadInfo.successCount += param.downloadData.data.size(); // Get latest cloudWaterMark VBucket &lastData = param.downloadData.data.back(); - if (!IsQueryListEmpty(taskId) && param.isLastBatch) { + if (!IsNeedProcessCloudCursor(taskId) && param.isLastBatch) { // the last batch of cursor in the conditional query is useless param.cloudWaterMark = {}; } else { @@ -1229,9 +1222,11 @@ int CloudSyncer::DoBatchUpload(CloudSyncData &uploadData, UploadParam &uploadPar if (errCode != E_OK) { return errCode; } - bool lastBatch = (innerProcessInfo.upLoadInfo.successCount + innerProcessInfo.upLoadInfo.failCount) == + bool lastBatch = (innerProcessInfo.upLoadInfo.successCount + innerProcessInfo.upLoadInfo.failCount) >= innerProcessInfo.upLoadInfo.total; if (lastBatch) { + innerProcessInfo.upLoadInfo.total = + (innerProcessInfo.upLoadInfo.successCount + innerProcessInfo.upLoadInfo.failCount); innerProcessInfo.tableStatus = ProcessStatus::FINISHED; } // After each batch upload successed, call NotifyProcess @@ -1252,7 +1247,7 @@ int CloudSyncer::PutWaterMarkAfterBatchUpload(const std::string &tableName, Uplo storageProxy_->ReleaseUploadRecord(tableName, uploadParam.mode, uploadParam.localMark); // if we use local cover cloud strategy, it won't update local water mark also. if (IsModeForcePush(uploadParam.taskId) || (IsPriorityTask(uploadParam.taskId) && - !IsQueryListEmpty(uploadParam.taskId))) { + !IsNeedProcessCloudCursor(uploadParam.taskId))) { return E_OK; } errCode = storageProxy_->PutWaterMarkByMode(tableName, uploadParam.mode, uploadParam.localMark); @@ -1349,7 +1344,7 @@ int CloudSyncer::SaveCloudWaterMark(const TableName &tableName, const TaskId tas cloudWaterMark = currentContext_.cloudWaterMarks[currentContext_.currentUserIndex][tableName]; isUpdateCloudCursor = currentContext_.strategy->JudgeUpdateCursor(); } - isUpdateCloudCursor = isUpdateCloudCursor && !(IsPriorityTask(taskId) && !IsQueryListEmpty(taskId)); + isUpdateCloudCursor = isUpdateCloudCursor && !(IsPriorityTask(taskId) && !IsNeedProcessCloudCursor(taskId)); if (isUpdateCloudCursor) { int errCode = storageProxy_->SetCloudWaterMark(tableName, cloudWaterMark); if (errCode != E_OK) { @@ -1402,11 +1397,11 @@ int CloudSyncer::PreHandleData(VBucket &datum, const std::vector &p if (!std::get<2>(fieldIndex)) { // 2 is index of mandatory flag continue; } - LOGE("[CloudSyncer] Cloud data do not contain expected field: %s.", std::get<0>(fieldIndex).c_str()); + LOGE("[CloudSyncer] Cloud data do not contain expected field."); return -E_CLOUD_ERROR; } if (datum[std::get<0>(fieldIndex)].index() != static_cast(std::get<1>(fieldIndex))) { - LOGE("[CloudSyncer] Cloud data's field: %s, doesn't has expected type.", std::get<0>(fieldIndex).c_str()); + LOGE("[CloudSyncer] Cloud data's field, doesn't has expected type."); return -E_CLOUD_ERROR; } } @@ -1722,7 +1717,6 @@ int CloudSyncer::ClearCloudWatermark(const std::vector &tableNameLi int CloudSyncer::CleanWaterMarkInMemory(const std::set &tableNameList) { - std::lock_guard lock(syncMutex_); for (const auto &tableName: tableNameList) { int ret = storageProxy_->CleanWaterMarkInMemory(tableName); if (ret != E_OK) { @@ -1756,7 +1750,7 @@ int CloudSyncer::CommitDownloadResult(const DownloadItem &downloadItem, InnerPro uint32_t successCount = 0u; int ret = E_OK; if (info.isAsyncDownload) { - ret = CommitDownloadAssetsForAsyncDownload(downloadItem, info, commitList, successCount); + ret = HandleDownloadResultForAsyncDownload(downloadItem, info, commitList, successCount); } else { ret = HandleDownloadResult(downloadItem, info, commitList, successCount); } @@ -2061,21 +2055,19 @@ int CloudSyncer::DownloadOneAssetRecord(const std::set &dupHashKeySet, cons int CloudSyncer::GetSyncParamForDownload(TaskId taskId, SyncParam ¶m) { - int ret = E_OK; if (IsCurrentTableResume(taskId, false)) { std::lock_guard autoLock(dataLock_); if (resumeTaskInfos_[taskId].syncParam.tableName == currentContext_.tableName) { param = resumeTaskInfos_[taskId].syncParam; resumeTaskInfos_[taskId].syncParam = {}; - ret = storageProxy_->GetCloudWaterMark(param.tableName, param.cloudWaterMark); + int ret = storageProxy_->GetCloudWaterMark(param.tableName, param.cloudWaterMark); if (ret != E_OK) { - LOGE("[CloudSyncer] Cannot get cloud water level from cloud meta data when table is resume: %d.", ret); + LOGW("[CloudSyncer] Cannot get cloud water level from cloud meta data when table is resume: %d.", ret); } - LOGD("[CloudSyncer] Get sync param from cache"); return E_OK; } } - ret = GetCurrentTableName(param.tableName); + int ret = GetCurrentTableName(param.tableName); if (ret != E_OK) { LOGE("[CloudSyncer] Invalid table name for syncing: %d", ret); return ret; @@ -2088,12 +2080,14 @@ int CloudSyncer::GetSyncParamForDownload(TaskId taskId, SyncParam ¶m) LOGE("[CloudSyncer] Cannot get primary column names: %d", ret); return ret; } + std::shared_ptr notifier = nullptr; { std::lock_guard autoLock(dataLock_); currentContext_.assetFields[currentContext_.tableName] = assetFields; + notifier = currentContext_.notifier; } param.isSinglePrimaryKey = CloudSyncUtils::IsSinglePrimaryKey(param.pkColNames); - if (!IsModeForcePull(taskId) && (!IsPriorityTask(taskId) || IsQueryListEmpty(taskId))) { + if (!IsModeForcePull(taskId) && (!IsPriorityTask(taskId) || IsNeedProcessCloudCursor(taskId))) { ret = storageProxy_->GetCloudWaterMark(param.tableName, param.cloudWaterMark); if (ret != E_OK) { LOGE("[CloudSyncer] Cannot get cloud water level from cloud meta data: %d.", ret); @@ -2102,7 +2096,7 @@ int CloudSyncer::GetSyncParamForDownload(TaskId taskId, SyncParam ¶m) ReloadCloudWaterMarkIfNeed(param.tableName, param.cloudWaterMark); } } - currentContext_.notifier->GetDownloadInfoByTableName(param.info); + notifier->GetDownloadInfoByTableName(param.info); auto queryObject = GetQuerySyncObject(param.tableName); param.isAssetsOnly = queryObject.IsAssetsOnly(); param.groupNum = queryObject.GetGroupNum(); @@ -2139,7 +2133,11 @@ int CloudSyncer::DownloadDataFromCloud(TaskId taskId, SyncParam ¶m, bool isF param.cloudWaterMarkForAssetsOnly = param.cloudWaterMark; } int ret = QueryCloudData(taskId, param.info.tableName, param.cloudWaterMark, param.downloadData); - CloudSyncUtils::CheckQueryCloudData(cloudTaskInfos_[taskId].prepareTraceId, param.downloadData, param.pkColNames); + { + std::lock_guard autoLock(dataLock_); + CloudSyncUtils::CheckQueryCloudData( + cloudTaskInfos_[taskId].prepareTraceId, param.downloadData, param.pkColNames); + } if (ret == -E_QUERY_END) { // Won't break here since downloadData may not be null param.isLastBatch = true; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h index 0d773580647aa3410fe664e9351e833dec90118b..d6bc53b30a784fa63973589f41cfc195835656a7 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h @@ -62,7 +62,9 @@ public: int ClearCloudWatermark(const std::vector &tableNameList); - int CleanKvCloudData(std::function &removeFunc); + int StopSyncTask(std::function &removeFunc); + + int StopTaskBeforeSetReference(std::function &setReferenceFunc); int CleanWaterMarkInMemory(const std::set &tableNameList); @@ -93,6 +95,8 @@ public: void SetGenCloudVersionCallback(const GenerateCloudVersionCallback &callback); SyncProcess GetCloudTaskStatus(uint64_t taskId) const; + + int ClearCloudWatermark(std::function &clearFunc); protected: struct TaskContext { TaskId currentTaskId = 0u; @@ -279,6 +283,9 @@ protected: int HandleDownloadResult(const DownloadItem &downloadItem, InnerProcessInfo &info, DownloadCommitList &commitList, uint32_t &successCount); + int HandleDownloadResultForAsyncDownload(const DownloadItem &downloadItem, InnerProcessInfo &info, + DownloadCommitList &commitList, uint32_t &successCount); + int FillDownloadExtend(TaskId taskId, const std::string &tableName, const std::string &cloudWaterMark, VBucket &extend); @@ -414,6 +421,8 @@ protected: bool IsNeedGetLocalWater(TaskId taskId); + bool IsNeedProcessCloudCursor(TaskId taskId); + void SetProxyUser(const std::string &user); void MergeTaskInfo(const std::shared_ptr &cloudSchema, TaskId taskId); @@ -516,8 +525,6 @@ protected: bool IsCurrentAsyncDownloadTask(); - bool CanStartAsyncDownload() const; - int GetCloudGidAndFillExtend(TaskId taskId, const std::string &tableName, QuerySyncObject &obj, VBucket &extend); int QueryCloudGidForAssetsOnly( @@ -543,6 +550,12 @@ protected: static void ModifyDownLoadInfoCount(const int errorCode, InnerProcessInfo &info); + void ChangeProcessStatusAndNotifyIfNeed(UploadParam &uploadParam, InnerProcessInfo &info); + + void ExecuteAsyncDownloadAssets(TaskId taskId); + + bool IsCloudForcePush(TaskId taskId); + mutable std::mutex dataLock_; TaskId lastTaskId_; std::multimap> taskQueue_; @@ -576,6 +589,7 @@ protected: std::condition_variable asyncTaskCv_; TaskId asyncTaskId_; std::atomic cancelAsyncTask_; + std::atomic scheduleTaskCount_; std::mutex listenerMutex_; NotificationChain::Listener *waitDownloadListener_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp index 1e9c535035663462c0f07c5fb6f3f6f694665383..336a76086cedbc42a79e82152d6d2db556a7a9f4 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp @@ -107,8 +107,7 @@ int CloudSyncer::FillDownloadExtend(TaskId taskId, const std::string &tableName, int CloudSyncer::GetCloudGid(TaskId taskId, const std::string &tableName, QuerySyncObject &obj) { std::vector cloudGid; - bool isCloudForcePush = cloudTaskInfos_[taskId].mode == SYNC_MODE_CLOUD_FORCE_PUSH; - int errCode = storageProxy_->GetCloudGid(obj, isCloudForcePush, IsCompensatedTask(taskId), cloudGid); + int errCode = storageProxy_->GetCloudGid(obj, IsCloudForcePush(taskId), IsCompensatedTask(taskId), cloudGid); if (errCode != E_OK) { LOGE("[CloudSyncer] Failed to get cloud gid, %d.", errCode); } else if (!cloudGid.empty()) { @@ -121,8 +120,7 @@ int CloudSyncer::GetCloudGid(TaskId taskId, const std::string &tableName, QueryS int CloudSyncer::GetCloudGid( TaskId taskId, const std::string &tableName, QuerySyncObject &obj, std::vector &cloudGid) { - bool isCloudForcePush = cloudTaskInfos_[taskId].mode == SYNC_MODE_CLOUD_FORCE_PUSH; - int errCode = storageProxy_->GetCloudGid(obj, isCloudForcePush, IsCompensatedTask(taskId), cloudGid); + int errCode = storageProxy_->GetCloudGid(obj, IsCloudForcePush(taskId), IsCompensatedTask(taskId), cloudGid); if (errCode != E_OK) { LOGE("[CloudSyncer] Failed to get cloud gid, taskid:%" PRIu64 ", table name: %s, length: %zu, %d.", taskId, DBCommon::StringMiddleMasking(tableName).c_str(), tableName.length(), errCode); @@ -602,8 +600,8 @@ void CloudSyncer::GenerateCompensatedSync(CloudTaskInfo &taskInfo) { std::vector syncQuery; std::vector users; - int errCode = - CloudSyncUtils::GetQueryAndUsersForCompensatedSync(CanStartAsyncDownload(), storageProxy_, users, syncQuery); + int errCode = CloudSyncUtils::GetQueryAndUsersForCompensatedSync( + CloudSyncUtils::CanStartAsyncDownload(scheduleTaskCount_), storageProxy_, users, syncQuery); if (errCode != E_OK) { LOGW("[CloudSyncer] get query for compensated sync failed! errCode = %d", errCode); return; @@ -702,12 +700,10 @@ int CloudSyncer::UpdateFlagForSavedRecord(const SyncParam ¶m) downloadList = currentContext_.assetDownloadList; } std::set downloadGid; - std::set consistentGid; for (const auto &tuple : downloadList) { if (CloudSyncUtils::IsContainDownloading(tuple)) { downloadGid.insert(std::get(tuple)); } - consistentGid.insert(std::get(tuple)); } if (IsCurrentAsyncDownloadTask()) { int errCode = storageProxy_->MarkFlagAsAssetAsyncDownload(param.tableName, param.downloadData, downloadGid); @@ -716,7 +712,7 @@ int CloudSyncer::UpdateFlagForSavedRecord(const SyncParam ¶m) return errCode; } } - return storageProxy_->MarkFlagAsConsistent(param.tableName, param.downloadData, consistentGid); + return storageProxy_->MarkFlagAsConsistent(param.tableName, param.downloadData, downloadGid); } int CloudSyncer::BatchDelete(Info &deleteInfo, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo) @@ -773,11 +769,12 @@ void CloudSyncer::DoNotifyInNeed(const CloudSyncer::TaskId &taskId, const std::v const bool isFirstDownload) { bool isNeedNotify = false; + bool isLockAction = IsLockInDownload(); { std::lock_guard autoLock(dataLock_); // only when the first download and the task no need upload actually, notify the process, otherwise, // the process will notify in the upload procedure, which can guarantee the notify order of the tables - isNeedNotify = isFirstDownload && !currentContext_.isNeedUpload; + isNeedNotify = isFirstDownload && !currentContext_.isNeedUpload && isLockAction; } if (!isNeedNotify) { return; @@ -1068,6 +1065,12 @@ bool CloudSyncer::IsQueryListEmpty(TaskId taskId) }); } +bool CloudSyncer::IsNeedProcessCloudCursor(TaskId taskId) +{ + // Compensated task no need to save/get cloud cursor + return IsQueryListEmpty(taskId) && !IsCompensatedTask(taskId); +} + bool CloudSyncer::IsNeedLock(const UploadParam ¶m) { return param.lockAction == LockAction::INSERT && param.mode == CloudWaterType::INSERT; @@ -1083,6 +1086,15 @@ std::pair CloudSyncer::GetLocalWater(const std::string &tableNam return res; } +void CloudSyncer::ChangeProcessStatusAndNotifyIfNeed(UploadParam &uploadParam, InnerProcessInfo &info) +{ + if (info.tableStatus == ProcessStatus::FINISHED) { + // if process here, the process should't be finished and notify. + info.tableStatus = ProcessStatus::PROCESSING; + NotifyInBatchUpload(uploadParam, info, false); + } +} + int CloudSyncer::HandleBatchUpload(UploadParam &uploadParam, InnerProcessInfo &info, CloudSyncData &uploadData, ContinueToken &continueStmtToken, std::vector &revisedData) { @@ -1090,6 +1102,7 @@ int CloudSyncer::HandleBatchUpload(UploadParam &uploadParam, InnerProcessInfo &i uint32_t batchIndex = GetCurrentTableUploadBatchIndex(); bool isLocked = false; while (!CloudSyncUtils::CheckCloudSyncDataEmpty(uploadData)) { + ChangeProcessStatusAndNotifyIfNeed(uploadParam, info); revisedData.insert(revisedData.end(), uploadData.revisedData.begin(), uploadData.revisedData.end()); ret = PreProcessBatchUpload(uploadParam, info, uploadData); if (ret != E_OK) { @@ -1397,7 +1410,7 @@ std::string CloudSyncer::GetStoreIdByTask(TaskId taskId) return cloudTaskInfos_[taskId].storeId; } -int CloudSyncer::CleanKvCloudData(std::function &removeFunc) +int CloudSyncer::StopSyncTask(std::function &removeFunc) { hasKvRemoveTask = true; CloudSyncer::TaskId currentTask; @@ -1406,7 +1419,7 @@ int CloudSyncer::CleanKvCloudData(std::function &removeFunc) std::lock_guard autoLock(dataLock_); currentTask = currentContext_.currentTaskId; } - if (currentTask != INVALID_TASK_ID) { + if (currentTask != INVALID_TASK_ID || asyncTaskId_ != INVALID_TASK_ID) { StopAllTasks(-E_CLOUD_ERROR); } int errCode = E_OK; @@ -1664,55 +1677,15 @@ void CloudSyncer::TriggerAsyncDownloadAssetsInTaskIfNeed(bool isFirstDownload) } } if (isFirstDownload) { + bool isLockAction = IsLockInDownload(); std::lock_guard autoLock(dataLock_); - if (currentContext_.isNeedUpload) { + if (currentContext_.isNeedUpload && isLockAction) { return; } } TriggerAsyncDownloadAssetsIfNeed(); } -void CloudSyncer::TriggerAsyncDownloadAssetsIfNeed() -{ - if (!storageProxy_->IsExistTableContainAssets()) { - LOGD("[CloudSyncer] No exist table contain assets, skip async download asset check"); - return; - } - TaskId taskId = INVALID_TASK_ID; - { - std::lock_guard autoLock(dataLock_); - if (asyncTaskId_ != INVALID_TASK_ID || closed_) { - LOGI("[CloudSyncer] No need generate async task now asyncTaskId %" PRIu64 " closed %d", - static_cast(asyncTaskId_), static_cast(closed_)); - return; - } - lastTaskId_--; - if (lastTaskId_ == INVALID_TASK_ID) { - lastTaskId_ = UINT64_MAX; - } - asyncTaskId_ = lastTaskId_; - taskId = asyncTaskId_; - IncObjRef(this); - } - int errCode = RuntimeContext::GetInstance()->ScheduleTask([taskId, this]() { - LOGI("[CloudSyncer] Exec asyncTaskId %" PRIu64 " begin", taskId); - BackgroundDownloadAssetsTask(); - LOGI("[CloudSyncer] Exec asyncTaskId %" PRIu64 " finished", taskId); - { - std::lock_guard autoLock(dataLock_); - asyncTaskId_ = INVALID_TASK_ID; - } - asyncTaskCv_.notify_all(); - DecObjRef(this); - }); - if (errCode == E_OK) { - LOGI("[CloudSyncer] Schedule asyncTaskId %" PRIu64 " success", taskId); - } else { - LOGW("[CloudSyncer] Schedule BackgroundDownloadAssetsTask failed %d", errCode); - DecObjRef(this); - } -} - void CloudSyncer::BackgroundDownloadAssetsTask() { // remove listener first @@ -1883,7 +1856,6 @@ int CloudSyncer::TagDownloadAssetsForAssetOnly( LOGE("[CloudSyncer] Invalid primary key type in TagStatus, it's Nil."); return -E_INTERNAL_ERROR; } - std::map downloadAssetsMap{}; ret = CloudSyncUtils::GetDownloadAssetsOnlyMapFromDownLoadData(idx, param, downloadAssetsMap); if (ret != E_OK) { @@ -1967,7 +1939,6 @@ int CloudSyncer::SetAssetsMapAndEraseDataForAssetsOnly( return -E_ASSET_NOT_FOUND_FOR_DOWN_ONLY; } } - for (auto iter = downloadData.begin(); iter != downloadData.end();) { std::string gidStr; int ret = CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::GID_FIELD, *iter, gidStr); @@ -2059,15 +2030,6 @@ bool CloudSyncer::IsCurrentAsyncDownloadTask() return cloudTaskInfos_[currentContext_.currentTaskId].asyncDownloadAssets; } -bool CloudSyncer::CanStartAsyncDownload() const -{ - if (!RuntimeContext::GetInstance()->GetAssetsDownloadManager()->CanStartNewTask()) { - LOGW("[CloudSyncer] Too many download tasks"); - return false; - } - return asyncTaskId_ == INVALID_TASK_ID; -} - void CloudSyncer::NotifyChangedDataWithDefaultDev(ChangedData &&changedData) { auto table = changedData.tableName; @@ -2148,8 +2110,8 @@ bool CloudSyncer::TryToInitQueryAndUserListForCompensatedSync(TaskId triggerTask { std::vector syncQuery; std::vector users; - int errCode = - CloudSyncUtils::GetQueryAndUsersForCompensatedSync(CanStartAsyncDownload(), storageProxy_, users, syncQuery); + int errCode = CloudSyncUtils::GetQueryAndUsersForCompensatedSync( + CloudSyncUtils::CanStartAsyncDownload(scheduleTaskCount_), storageProxy_, users, syncQuery); if (errCode != E_OK) { LOGW("[CloudSyncer] get query for compensated sync failed! errCode = %d", errCode); // if failed, finshed the task directly. @@ -2174,4 +2136,16 @@ bool CloudSyncer::TryToInitQueryAndUserListForCompensatedSync(TaskId triggerTask cloudTaskInfos_[triggerTaskId].queryList.push_back(syncQuery[0]); return true; } + +int CloudSyncer::ClearCloudWatermark(std::function &clearFunc) +{ + std::lock_guard lock(syncMutex_); + return clearFunc(); +} + +bool CloudSyncer::IsCloudForcePush(TaskId taskId) +{ + std::lock_guard autoLock(dataLock_); + return cloudTaskInfos_[taskId].mode == SYNC_MODE_CLOUD_FORCE_PUSH; +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend_extend.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend_extend.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae9558e7537815fbcf09177cbba20d1f93687201 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend_extend.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2025 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_syncer.h" + +#include +#include +#include + +#include "cloud/cloud_db_constant.h" +#include "cloud/cloud_storage_utils.h" +#include "cloud/icloud_db.h" +#include "cloud_sync_tag_assets.h" +#include "cloud_sync_utils.h" +#include "db_errno.h" +#include "kv_store_errno.h" +#include "log_print.h" +#include "res_finalizer.h" +#include "runtime_context.h" +#include "store_types.h" +#include "strategy_factory.h" +#include "version.h" + +namespace DistributedDB { +int CloudSyncer::HandleDownloadResultForAsyncDownload(const DownloadItem &downloadItem, InnerProcessInfo &info, + DownloadCommitList &commitList, uint32_t &successCount) +{ + int errCode = storageProxy_->StartTransaction(TransactType::IMMEDIATE, true); + if (errCode != E_OK) { + LOGE("[CloudSyncer] start transaction Failed before handle async download."); + return errCode; + } + errCode = CommitDownloadAssetsForAsyncDownload(downloadItem, info, commitList, successCount); + if (errCode != E_OK) { + successCount = 0; + int ret = E_OK; + if (errCode == -E_REMOVE_ASSETS_FAILED) { + // remove assets failed no effect to asset status, just commit + ret = storageProxy_->Commit(true); + LOGE("[CloudSyncer] commit async download assets failed %d commit ret %d", errCode, ret); + } else { + ret = storageProxy_->Rollback(true); + LOGE("[CloudSyncer] commit async download assets failed %d rollback ret %d", errCode, ret); + } + return errCode; + } + errCode = storageProxy_->Commit(true); + if (errCode != E_OK) { + successCount = 0; + LOGE("[CloudSyncer] commit async download assets failed %d", errCode); + } + return errCode; +} + +void CloudSyncer::TriggerAsyncDownloadAssetsIfNeed() +{ + if (!storageProxy_->IsExistTableContainAssets()) { + LOGD("[CloudSyncer] No exist table contain assets, skip async download asset check"); + return; + } + TaskId taskId = INVALID_TASK_ID; + { + std::lock_guard autoLock(dataLock_); + if (asyncTaskId_ != INVALID_TASK_ID || closed_) { + LOGI("[CloudSyncer] No need generate async task now asyncTaskId %" PRIu64 " closed %d", + asyncTaskId_, static_cast(closed_)); + return; + } + lastTaskId_--; + if (lastTaskId_ == INVALID_TASK_ID) { + lastTaskId_ = UINT64_MAX; + } + taskId = lastTaskId_; + IncObjRef(this); + } + int errCode = RuntimeContext::GetInstance()->ScheduleTask([taskId, this]() { + LOGI("[CloudSyncer] Exec asyncTaskId %" PRIu64 " begin", taskId); + ExecuteAsyncDownloadAssets(taskId); + LOGI("[CloudSyncer] Exec asyncTaskId %" PRIu64 " finished", taskId); + scheduleTaskCount_--; + DecObjRef(this); + }); + if (errCode == E_OK) { + LOGI("[CloudSyncer] Schedule asyncTaskId %" PRIu64 " success", taskId); + scheduleTaskCount_++; + } else { + LOGW("[CloudSyncer] Schedule BackgroundDownloadAssetsTask failed %d", errCode); + DecObjRef(this); + } +} + +void CloudSyncer::ExecuteAsyncDownloadAssets(TaskId taskId) +{ + { + std::lock_guard autoLock(dataLock_); + if (asyncTaskId_ != INVALID_TASK_ID || closed_) { + LOGI("[CloudSyncer] No need exec async task now asyncTaskId %" PRIu64 " closed %d", + asyncTaskId_, static_cast(closed_)); + return; + } + asyncTaskId_ = taskId; + } + BackgroundDownloadAssetsTask(); + { + std::lock_guard autoLock(dataLock_); + asyncTaskId_ = INVALID_TASK_ID; + } + asyncTaskCv_.notify_all(); +} +} // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/ability_sync.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/ability_sync.cpp index 7a4af6fa01b018eccd7db4728968c9e439df2ef3..795f87641b2938f587f096fd91e1b92275260638 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/ability_sync.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/ability_sync.cpp @@ -402,6 +402,9 @@ int AbilitySync::SyncStart(uint32_t sessionId, uint32_t sequenceId, uint16_t rem message->SetSequenceId(sequenceId); SendConfig conf; SetSendConfigParam(storageInterface_->GetDbProperties(), deviceId_, false, SEND_TIME_OUT, conf); + if (context != nullptr) { + conf.isRetryTask = context->IsRetryTask(); + } errCode = communicator_->SendMessage(deviceId_, message, conf, handler); if (errCode != E_OK) { LOGE("[AbilitySync][SyncStart] SendPacket failed, err %d", errCode); @@ -423,7 +426,7 @@ int AbilitySync::AckRecv(const Message *message, ISyncTaskContext *context) } uint32_t remoteSoftwareVersion = packet->GetSoftwareVersion(); context->SetRemoteSoftwareVersion(remoteSoftwareVersion); - metadata_->SetRemoteSchemaVersion(context->GetDeviceId(), remoteSoftwareVersion); + metadata_->SetRemoteSoftwareVersion(context->GetDeviceId(), context->GetTargetUserId(), remoteSoftwareVersion); if (remoteSoftwareVersion > SOFTWARE_VERSION_RELEASE_2_0) { errCode = AckRecvWithHighVersion(message, context, packet); } else { @@ -518,7 +521,7 @@ void AbilitySync::SetAbilitySyncFinishedStatus(bool syncFinished, ISyncTaskConte if (syncFinished && !context.IsSchemaCompatible()) { // LCOV_EXCL_BR_LINE return; } - int errCode = metadata_->SetAbilitySyncFinishMark(deviceId_, syncFinished); + int errCode = metadata_->SetAbilitySyncFinishMark(deviceId_, context.GetTargetUserId(), syncFinished); if (errCode != E_OK) { LOGW("[AbilitySync] Set ability sync finish mark failed %d", errCode); } @@ -1155,10 +1158,11 @@ int AbilitySync::HandleRequestRecv(const Message *message, ISyncTaskContext *con ackCode = -E_SECURITY_OPTION_CHECK_ERROR; } if (ackCode == E_OK && remoteSoftwareVersion > SOFTWARE_VERSION_RELEASE_3_0) { - ackCode = metadata_->SetDbCreateTime(deviceId_, packet->GetDbCreateTime(), true); + ackCode = metadata_->SetDbCreateTime(deviceId_, context->GetTargetUserId(), packet->GetDbCreateTime(), true); } if (ackCode == E_OK && remoteSoftwareVersion >= SOFTWARE_VERSION_RELEASE_9_0) { - ackCode = metadata_->SetRemoteSchemaVersion(context->GetDeviceId(), packet->GetSchemaVersion()); + ackCode = metadata_->SetRemoteSchemaVersion(context->GetDeviceId(), context->GetTargetUserId(), + packet->GetSchemaVersion()); } AbilitySyncAckPacket ackPacket; if (IsSingleRelationalVer()) { @@ -1334,7 +1338,7 @@ int AbilitySync::AckRecvWithHighVersion(const Message *message, ISyncTaskContext std::pair schemaSyncStatus; int errCode = E_OK; if (context->GetRemoteSoftwareVersion() > SOFTWARE_VERSION_RELEASE_3_0) { - errCode = metadata_->SetDbCreateTime(deviceId_, packet->GetDbCreateTime(), true); + errCode = metadata_->SetDbCreateTime(deviceId_, context->GetTargetUserId(), packet->GetDbCreateTime(), true); if (errCode != E_OK) { LOGE("[AbilitySync][AckRecv] set db create time failed,errCode=%d", errCode); context->SetTaskErrCode(errCode); @@ -1378,7 +1382,7 @@ bool AbilitySync::IsBothKvAndOptAbilitySync(uint32_t remoteVersion, SchemaType l void AbilitySync::InitAbilitySyncFinishStatus(ISyncTaskContext &context) { - if (!metadata_->IsAbilitySyncFinish(context.GetDeviceId())) { + if (!metadata_->IsAbilitySyncFinish(context.GetDeviceId(), context.GetTargetUserId())) { return; } LOGI("[AbilitySync] Mark ability sync finish from db status"); @@ -1398,7 +1402,17 @@ void AbilitySync::InitRemoteDBAbility(ISyncTaskContext &context) return; } context.SetDbAbility(ability); - auto version = static_cast(metadata_->GetRemoteSoftwareVersion(context.GetDeviceId())); + auto version = static_cast(metadata_->GetRemoteSoftwareVersion(context.GetDeviceId(), + context.GetTargetUserId())); + // 111 trunk ver record schema version as software version + // should clear it and do ability sync again + if (version > SOFTWARE_VERSION_MAX) { + context.SetRemoteSoftwareVersion(SOFTWARE_VERSION_RELEASE_9_0); // remote version is greater than 109 + SetAbilitySyncFinishedStatus(false, context); + (void)metadata_->SetRemoteSoftwareVersion(deviceId_, context.GetTargetUserId(), SOFTWARE_VERSION_RELEASE_9_0); + LOGW("[AbilitySync] Remote schema version is invalid[% " PRIu32 "]", version); + return; + } if (version > 0) { context.SetRemoteSoftwareVersion(version); } @@ -1408,7 +1422,8 @@ void AbilitySync::RecordAbilitySyncFinish(uint64_t remoteSchemaVersion, ISyncTas { SetAbilitySyncFinishedStatus(true, context); if (context.GetRemoteSoftwareVersion() >= SOFTWARE_VERSION_RELEASE_9_0) { // LCOV_EXCL_BR_LINE - (void)metadata_->SetRemoteSchemaVersion(deviceId_, remoteSchemaVersion); + (void)metadata_->SetRemoteSchemaVersion(deviceId_, context.GetTargetUserId(), remoteSchemaVersion); } + (void)metadata_->SetRemoteSoftwareVersion(deviceId_, context.GetTargetUserId(), context.GetRemoteSoftwareVersion()); } } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/communicator_proxy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/communicator_proxy.cpp index 15327f2541210458e16587e8943b889329a9c46a..08e6a794bbfa816debfca75e474cd2c13fa9982b 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/communicator_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/communicator_proxy.cpp @@ -272,4 +272,35 @@ void CommunicatorProxy::Dump(int fd) DBDumpHelper::Dump(fd, "\t\ttarget = %s, label = %s\n", target.c_str(), label.c_str()); } } + +std::string CommunicatorProxy::GetTargetUserId(const ExtendInfo ¶mInfo) const +{ + ICommunicator *targetCommunicator = nullptr; + { + std::lock_guard lock(devCommMapLock_); + if (devCommMap_.count(paramInfo.dstTarget) != 0) { + targetCommunicator = devCommMap_.at(paramInfo.dstTarget).second; + RefObject::IncObjRef(targetCommunicator); + } + } + if (targetCommunicator != nullptr) { + std::string targetUserId = targetCommunicator->GetTargetUserId(paramInfo); + RefObject::DecObjRef(targetCommunicator); + return targetUserId; + } + + if (mainComm_ != nullptr) { + return mainComm_->GetTargetUserId(paramInfo); + } + + return ""; +} + +bool CommunicatorProxy::ExchangeClosePending(bool expected) +{ + if (mainComm_ != nullptr) { + return mainComm_->ExchangeClosePending(expected); + } + return false; +} } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/communicator_proxy.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/communicator_proxy.h index fafd852f7067b42c670d8f67eec8b3c98c217884..06340788280e87596ab469a10a29676cc1a799c7 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/communicator_proxy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/communicator_proxy.h @@ -55,6 +55,10 @@ public: void Dump(int fd); + std::string GetTargetUserId(const ExtendInfo ¶mInfo) const override; + + bool ExchangeClosePending(bool expected) override; + private: ICommunicator *mainComm_; mutable std::mutex devCommMapLock_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.cpp index 772dee8f9d82aa1a3551aec1807c79bad7efd50e..426d110a29064e16d1e2744746402f4ffcc9ea9a 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.cpp @@ -150,7 +150,7 @@ int GenericSyncer::Sync(const std::vector &devices, int mode, const std::function &)> &onComplete, const std::function &onFinalize, bool wait = false) { - SyncParma param; + SyncParam param; param.devices = devices; param.mode = mode; param.onComplete = onComplete; @@ -161,7 +161,7 @@ int GenericSyncer::Sync(const std::vector &devices, int mode, int GenericSyncer::Sync(const InternalSyncParma ¶m) { - SyncParma syncParam; + SyncParam syncParam; syncParam.devices = param.devices; syncParam.mode = param.mode; syncParam.isQuerySync = param.isQuerySync; @@ -169,12 +169,12 @@ int GenericSyncer::Sync(const InternalSyncParma ¶m) return Sync(syncParam); } -int GenericSyncer::Sync(const SyncParma ¶m) +int GenericSyncer::Sync(const SyncParam ¶m) { return Sync(param, DBConstant::IGNORE_CONNECTION_ID); } -int GenericSyncer::Sync(const SyncParma ¶m, uint64_t connectionId) +int GenericSyncer::Sync(const SyncParam ¶m, uint64_t connectionId) { int errCode = SyncPreCheck(param); if (errCode != E_OK) { @@ -232,10 +232,10 @@ int GenericSyncer::CancelSync(uint32_t syncId) return E_OK; } -int GenericSyncer::PrepareSync(const SyncParma ¶m, uint32_t syncId, uint64_t connectionId) +int GenericSyncer::PrepareSync(const SyncParam ¶m, uint32_t syncId, uint64_t connectionId) { auto *operation = - new (std::nothrow) SyncOperation(syncId, param.devices, param.mode, param.onComplete, param.wait); + new (std::nothrow) SyncOperation(syncId, param); if (operation == nullptr) { SubQueuedSyncSize(); return -E_OUT_OF_MEMORY; @@ -246,8 +246,8 @@ int GenericSyncer::PrepareSync(const SyncParma ¶m, uint32_t syncId, uint64_t std::lock_guard autoLock(syncerLock_); PerformanceAnalysis::GetInstance()->StepTimeRecordStart(PT_TEST_RECORDS::RECORD_SYNC_TOTAL); InitSyncOperation(operation, param); - LOGI("[Syncer] GenerateSyncId %" PRIu32 ", mode = %d, wait = %d, label = %s, devices = %s", syncId, param.mode, - param.wait, label_.c_str(), GetSyncDevicesStr(param.devices).c_str()); + LOGI("[Syncer] GenerateSyncId %" PRIu32 ", mode = %d, wait = %d, label = %.3s, devices = %s, isRetry = %d", + syncId, param.mode, param.wait, label_.c_str(), GetSyncDevicesStr(param.devices).c_str(), param.isRetry); engine = syncEngine_; RefObject::IncObjRef(engine); } @@ -528,7 +528,7 @@ bool GenericSyncer::IsValidMode(int mode) const return true; } -int GenericSyncer::SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, ISyncInterface *storage) const +int GenericSyncer::SyncConditionCheck(const SyncParam ¶m, const ISyncEngine *engine, ISyncInterface *storage) const { (void)param; (void)engine; @@ -871,7 +871,7 @@ int GenericSyncer::StatusCheck() const return E_OK; } -int GenericSyncer::SyncPreCheck(const SyncParma ¶m) const +int GenericSyncer::SyncPreCheck(const SyncParam ¶m) const { ISyncEngine *engine = nullptr; ISyncInterface *storage = nullptr; @@ -903,7 +903,7 @@ int GenericSyncer::SyncPreCheck(const SyncParma ¶m) const return errCode; } -void GenericSyncer::InitSyncOperation(SyncOperation *operation, const SyncParma ¶m) +void GenericSyncer::InitSyncOperation(SyncOperation *operation, const SyncParam ¶m) { if (syncInterface_ == nullptr) { LOGE("[GenericSyncer] [InitSyncOperation] syncInterface_ is nullptr."); @@ -1073,7 +1073,7 @@ int GenericSyncer::CloseInner(bool isClosedOperation) { std::lock_guard lock(syncerLock_); if (!initialized_) { - LOGW("[Syncer] Syncer[%s] don't need to close, because it has not been init", label_.c_str()); + LOGW("[Syncer] CloseInner[%.3s] don't close", label_.c_str()); return -E_NOT_INIT; } initialized_ = false; @@ -1114,7 +1114,7 @@ int GenericSyncer::GetSyncDataSize(const std::string &device, size_t &size) cons syncInterface_->IncRefCount(); metadata = metadata_; } - metadata->GetLocalWaterMark(device, localWaterMark); + metadata->GetLocalWaterMark(device, "", localWaterMark); uint32_t expectedMtuSize = DEFAULT_MTU_SIZE; DataSizeSpecInfo syncDataSizeInfo = {expectedMtuSize, static_cast(MAX_TIMESTAMP)}; std::vector outData; @@ -1207,7 +1207,7 @@ int GenericSyncer::GetWatermarkInfo(const std::string &device, WatermarkInfo &in } else { dev = device; } - return metadata->GetWaterMarkInfoFromDB(dev, devNeedHash, info); + return metadata->GetWaterMarkInfoFromDB(dev, DBConstant::DEFAULT_USER, devNeedHash, info); } int GenericSyncer::UpgradeSchemaVerInMeta() @@ -1245,7 +1245,7 @@ void GenericSyncer::ResetTimeSyncMarkByTimeChange(std::shared_ptr &met } int errCode = metadata->ClearAllTimeSyncFinishMark(); if (errCode != E_OK) { - LOGW("[GenericSyncer] %s clear time sync finish mark failed %d", label_.c_str(), errCode); + LOGW("[GenericSyncer] %.3s clear time sync finish mark failed %d", label_.c_str(), errCode); } else { LOGD("[GenericSyncer] ClearAllTimeSyncFinishMark finish"); RuntimeContext::GetInstance()->ResetDBTimeChangeStatus(storage.GetIdentifier()); @@ -1298,4 +1298,20 @@ int32_t GenericSyncer::GetTaskCount() RefObject::DecObjRef(syncEngine); return count; } + +bool GenericSyncer::ExchangeClosePending(bool expected) +{ + ISyncEngine *syncEngine = nullptr; + { + std::lock_guard lock(syncerLock_); + if (syncEngine_ == nullptr) { + return false; + } + syncEngine = syncEngine_; + RefObject::IncObjRef(syncEngine); + } + bool res = syncEngine->ExchangeClosePending(expected); + RefObject::DecObjRef(syncEngine); + return res; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.h index 183fbb1fae07da317527fa84820b7ae4751793a5..0f002124c182d33684ff782e1971a8c214ea47e8 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.h @@ -50,10 +50,10 @@ public: const std::function &)> &onComplete, const std::function &onFinalize, bool wait) override; - // Sync function. use SyncParma to reduce parameter. - int Sync(const SyncParma ¶m); + // Sync function. use SyncParam to reduce parameter. + int Sync(const SyncParam ¶m); - int Sync(const SyncParma ¶m, uint64_t connectionId) override; + int Sync(const SyncParam ¶m, uint64_t connectionId) override; // Cancel sync function. int CancelSync(uint32_t syncId) override; @@ -118,6 +118,8 @@ public: int64_t GetLocalTimeOffset() override; int32_t GetTaskCount() override; + + bool ExchangeClosePending(bool expected) override; protected: // trigger query auto sync or auto subscribe @@ -128,7 +130,7 @@ protected: // Create a sync engine, if has memory error, will return nullptr. virtual ISyncEngine *CreateSyncEngine() = 0; - virtual int PrepareSync(const SyncParma ¶m, uint32_t syncId, uint64_t connectionId); + virtual int PrepareSync(const SyncParam ¶m, uint32_t syncId, uint64_t connectionId); // Add a Sync Operation, after call this function, the operation will be start virtual void AddSyncOperation(ISyncEngine *engine, SyncOperation *operation); @@ -157,7 +159,7 @@ protected: // Check if the mode arg is valid bool IsValidMode(int mode) const; - virtual int SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, ISyncInterface *storage) const; + virtual int SyncConditionCheck(const SyncParam ¶m, const ISyncEngine *engine, ISyncInterface *storage) const; // Check if the devices arg is valid bool IsValidDevices(const std::vector &devices) const; @@ -185,11 +187,11 @@ protected: std::string GetSyncDevicesStr(const std::vector &devices) const; - void InitSyncOperation(SyncOperation *operation, const SyncParma ¶m); + void InitSyncOperation(SyncOperation *operation, const SyncParam ¶m); int StatusCheck() const; - int SyncPreCheck(const SyncParma ¶m) const; + int SyncPreCheck(const SyncParam ¶m) const; int BuildSyncEngine(); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_engine.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_engine.h index 3859a900d107704c80d087776a83645f816861ba..0c652a39858454c0ee5fbba07b85041be371c4e3 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_engine.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_engine.h @@ -104,6 +104,10 @@ public: virtual void ClearAllSyncTaskByDevice(const std::string &deviceId) = 0; virtual int32_t GetResponseTaskCount() = 0; + + virtual int32_t GetRemoteQueryTaskCount() = 0; + + virtual bool ExchangeClosePending(bool expected) = 0; protected: ~ISyncEngine() override {}; }; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_task_context.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_task_context.h index 91ed88936156ceb0092bd4c6a30b09c17a48ba57..bc3b5c5c8c31369ed16dfc5633ccbe1f595143ff 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_task_context.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_task_context.h @@ -35,7 +35,7 @@ public: enum TASK_EXEC_STATUS { INIT, RUNNING, FAILED, FINISHED }; // Initialize the context - virtual int Initialize(const std::string &deviceId, ISyncInterface *syncInterface, + virtual int Initialize(const DeviceSyncTarget &target, ISyncInterface *syncInterface, const std::shared_ptr &metadata, ICommunicator *communicator) = 0; // Add a sync task target with the operation to the queue @@ -76,6 +76,10 @@ public: // Get the current task deviceId. virtual std::string GetDeviceId() const = 0; + virtual std::string GetTargetUserId() const = 0; + + virtual void SetTargetUserId(const std::string &userId) = 0; + virtual void SetTaskExecStatus(int status) = 0; virtual int GetTaskExecStatus() const = 0; @@ -188,6 +192,8 @@ public: virtual void TimeChange() = 0; virtual int32_t GetResponseTaskCount() = 0; + + virtual bool IsRetryTask() const = 0; protected: virtual ~ISyncTaskContext() {}; }; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.cpp index 80fc35acf24b3d480acd36c508f0e03f29e3299a..e6e6d68fb1591bcb369c95eb3c052dd240713fd2 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.cpp @@ -70,59 +70,85 @@ int Metadata::Initialize(ISyncInterface* storage) return LoadAllMetadata(); } -int Metadata::SaveTimeOffset(const DeviceID &deviceId, TimeOffset inValue) +int Metadata::SaveTimeOffset(const DeviceID &deviceId, const DeviceID &userId, TimeOffset inValue) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); metadata.timeOffset = inValue; metadata.lastUpdateTime = TimeHelper::GetSysCurrentTime(); LOGD("Metadata::SaveTimeOffset = %" PRId64 " dev %s", inValue, STR_MASK(deviceId)); - return SaveMetaDataValue(deviceId, metadata); + return SaveMetaDataValue(deviceId, userId, metadata); } -void Metadata::GetTimeOffset(const DeviceID &deviceId, TimeOffset &outValue) +void Metadata::GetTimeOffset(const DeviceID &deviceId, const DeviceID &userId, TimeOffset &outValue) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); outValue = metadata.timeOffset; } -void Metadata::GetLocalWaterMark(const DeviceID &deviceId, uint64_t &outValue) +void Metadata::GetLocalWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); outValue = metadata.localWaterMark; } -int Metadata::SaveLocalWaterMark(const DeviceID &deviceId, uint64_t inValue) +int Metadata::SaveLocalWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t inValue) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); metadata.localWaterMark = inValue; LOGD("Metadata::SaveLocalWaterMark = %" PRIu64, inValue); - return SaveMetaDataValue(deviceId, metadata); + return SaveMetaDataValue(deviceId, userId, metadata); } -void Metadata::GetPeerWaterMark(const DeviceID &deviceId, uint64_t &outValue, bool isNeedHash) +void Metadata::GetPeerWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue, bool isNeedHash) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, isNeedHash); + GetMetaDataValue(deviceId, userId, metadata, isNeedHash); outValue = metadata.peerWaterMark; } -int Metadata::SavePeerWaterMark(const DeviceID &deviceId, uint64_t inValue, bool isNeedHash) +int Metadata::SavePeerWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t inValue, bool isNeedHash) { - MetaDataValue metadata; + std::map metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, isNeedHash); - metadata.peerWaterMark = inValue; - LOGD("Metadata::SavePeerWaterMark = %" PRIu64, inValue); - return SaveMetaDataValue(deviceId, metadata, isNeedHash); + int errCode = E_OK; + if (!userId.empty()) { + MetaDataValue oneMetadata; + GetMetaDataValue(deviceId, userId, oneMetadata, isNeedHash); + DeviceID hashId; + Key key; + GetHashDeviceId(deviceId, userId, hashId, isNeedHash); + DBCommon::StringToVector(hashId, key); + metadata[key] = oneMetadata; + } else { + errCode = GetMetaDataFromDBByPrefixKey(deviceId, isNeedHash, metadata); + if (errCode != E_OK) { + return errCode; + } + } + + for (auto &oneMetadata : metadata) { + oneMetadata.second.peerWaterMark = inValue; + LOGD("Metadata::SavePeerWaterMark = %" PRIu64, inValue); + Value metadataValue; + errCode = SerializeMetaData(oneMetadata.second, metadataValue); + if (errCode != E_OK) { + return errCode; + } + errCode = SetMetadataToDb(oneMetadata.first, metadataValue); + if (errCode != E_OK) { + return errCode; + } + } + return E_OK; } int Metadata::SaveLocalTimeOffset(TimeOffset timeOffset, bool saveIntoDb) @@ -153,10 +179,11 @@ TimeOffset Metadata::GetLocalTimeOffset() const int Metadata::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash) { - return EraseDeviceWaterMark(deviceId, isNeedHash, ""); + return EraseDeviceWaterMark(deviceId, "", isNeedHash, ""); } -int Metadata::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, const std::string &tableName) +int Metadata::EraseDeviceWaterMark(const std::string &deviceId, const std::string &userId, bool isNeedHash, + const std::string &tableName) { // reload meta data again (void)LoadAllMetadata(); @@ -164,19 +191,19 @@ int Metadata::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, // try to erase all the waterMark // erase deleteSync recv waterMark WaterMark waterMark = 0; - int errCodeDeleteSync = SetRecvDeleteSyncWaterMark(deviceId, waterMark, isNeedHash); + int errCodeDeleteSync = SetRecvDeleteSyncWaterMark(deviceId, userId, waterMark, isNeedHash); if (errCodeDeleteSync != E_OK) { LOGE("[Metadata] erase deleteWaterMark failed errCode:%d", errCodeDeleteSync); return errCodeDeleteSync; } // erase querySync recv waterMark - int errCodeQuerySync = ResetRecvQueryWaterMark(deviceId, tableName, isNeedHash); + int errCodeQuerySync = ResetRecvQueryWaterMark(deviceId, userId, tableName, isNeedHash); if (errCodeQuerySync != E_OK) { LOGE("[Metadata] erase queryWaterMark failed errCode:%d", errCodeQuerySync); return errCodeQuerySync; } // peerWaterMark must be erased at last - int errCode = SavePeerWaterMark(deviceId, 0, isNeedHash); + int errCode = SavePeerWaterMark(deviceId, userId, 0, isNeedHash); if (errCode != E_OK) { LOGE("[Metadata] erase peerWaterMark failed errCode:%d", errCode); return errCode; @@ -198,7 +225,8 @@ Timestamp Metadata::GetLastLocalTime() const return lastLocalTime_; } -int Metadata::SaveMetaDataValue(const DeviceID &deviceId, const MetaDataValue &inValue, bool isNeedHash) +int Metadata::SaveMetaDataValue(const DeviceID &deviceId, const DeviceID &userId, const MetaDataValue &inValue, + bool isNeedHash) { std::vector value; int errCode = SerializeMetaData(inValue, value); @@ -207,7 +235,7 @@ int Metadata::SaveMetaDataValue(const DeviceID &deviceId, const MetaDataValue &i } DeviceID hashDeviceId; - GetHashDeviceId(deviceId, hashDeviceId, isNeedHash); + GetHashDeviceId(deviceId, userId, hashDeviceId, isNeedHash); std::vector key; DBCommon::StringToVector(hashDeviceId, key); errCode = SetMetadataToDb(key, value); @@ -217,9 +245,10 @@ int Metadata::SaveMetaDataValue(const DeviceID &deviceId, const MetaDataValue &i return errCode; } -int Metadata::GetMetaDataValue(const DeviceID &deviceId, MetaDataValue &outValue, bool isNeedHash) +int Metadata::GetMetaDataValue(const DeviceID &deviceId, const DeviceID &userId, MetaDataValue &outValue, + bool isNeedHash) { - int errCode = GetMetaDataValueFromDB(deviceId, isNeedHash, outValue); + int errCode = GetMetaDataValueFromDB(deviceId, userId, isNeedHash, outValue); if (errCode == -E_NOT_FOUND && RuntimeContext::GetInstance()->IsTimeChanged()) { outValue = {}; outValue.syncMark = static_cast(SyncMark::SYNC_MARK_TIME_CHANGE); @@ -257,6 +286,14 @@ int Metadata::GetMetadataFromDb(const std::vector &key, std::vectorGetMetaData(key, outValue); } +int Metadata::GetMetadataFromDbByPrefixKey(const Key &keyPrefix, std::map &data) const +{ + if (naturalStoragePtr_ == nullptr) { + return -E_INVALID_DB; + } + return naturalStoragePtr_->GetMetaDataByPrefixKey(keyPrefix, data); +} + int Metadata::SetMetadataToDb(const std::vector &key, const std::vector &inValue) { if (naturalStoragePtr_ == nullptr) { @@ -326,51 +363,54 @@ int Metadata::LoadAllMetadata() return InitLocalMetaData(); } -void Metadata::GetHashDeviceId(const DeviceID &deviceId, DeviceID &hashDeviceId, bool isNeedHash) +void Metadata::GetHashDeviceId(const DeviceID &deviceId, const DeviceID &userId, DeviceID &hashDeviceId, + bool isNeedHash) { if (!isNeedHash) { - hashDeviceId = DBConstant::DEVICEID_PREFIX_KEY + deviceId; + hashDeviceId = DBConstant::DEVICEID_PREFIX_KEY + deviceId + DBConstant::USERID_PREFIX_KEY + userId; return; } - if (deviceIdToHashDeviceIdMap_.count(deviceId) == 0) { - hashDeviceId = DBConstant::DEVICEID_PREFIX_KEY + DBCommon::TransferHashString(deviceId); - deviceIdToHashDeviceIdMap_.insert(std::pair(deviceId, hashDeviceId)); + DeviceSyncTarget deviceInfo(deviceId, userId); + if (deviceIdToHashDeviceIdMap_.count(deviceInfo) == 0) { + hashDeviceId = DBConstant::DEVICEID_PREFIX_KEY + DBCommon::TransferHashString(deviceId) + + DBConstant::USERID_PREFIX_KEY + userId; + deviceIdToHashDeviceIdMap_.insert(std::pair(deviceInfo, hashDeviceId)); } else { - hashDeviceId = deviceIdToHashDeviceIdMap_[deviceId]; + hashDeviceId = deviceIdToHashDeviceIdMap_[deviceInfo]; } } int Metadata::GetRecvQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, WaterMark &waterMark) + const std::string &deviceId, const std::string &userId, WaterMark &waterMark) { QueryWaterMark queryWaterMark; - int errCode = querySyncWaterMarkHelper_.GetQueryWaterMark(queryIdentify, deviceId, queryWaterMark); + int errCode = querySyncWaterMarkHelper_.GetQueryWaterMark(queryIdentify, deviceId, userId, queryWaterMark); if (errCode != E_OK) { return errCode; } WaterMark peerWaterMark; - GetPeerWaterMark(deviceId, peerWaterMark); + GetPeerWaterMark(deviceId, userId, peerWaterMark); waterMark = std::max(queryWaterMark.recvWaterMark, peerWaterMark); return E_OK; } int Metadata::SetRecvQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, const WaterMark &waterMark) + const std::string &deviceId, const std::string &userId, const WaterMark &waterMark) { - return querySyncWaterMarkHelper_.SetRecvQueryWaterMark(queryIdentify, deviceId, waterMark); + return querySyncWaterMarkHelper_.SetRecvQueryWaterMark(queryIdentify, deviceId, userId, waterMark); } int Metadata::GetSendQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, WaterMark &waterMark, bool isAutoLift) + const std::string &deviceId, const std::string &userId, WaterMark &waterMark, bool isAutoLift) { QueryWaterMark queryWaterMark; - int errCode = querySyncWaterMarkHelper_.GetQueryWaterMark(queryIdentify, deviceId, queryWaterMark); + int errCode = querySyncWaterMarkHelper_.GetQueryWaterMark(queryIdentify, deviceId, userId, queryWaterMark); if (errCode != E_OK) { return errCode; } if (isAutoLift) { WaterMark localWaterMark; - GetLocalWaterMark(deviceId, localWaterMark); + GetLocalWaterMark(deviceId, userId, localWaterMark); waterMark = std::max(queryWaterMark.sendWaterMark, localWaterMark); } else { waterMark = queryWaterMark.sendWaterMark; @@ -379,15 +419,16 @@ int Metadata::GetSendQueryWaterMark(const std::string &queryIdentify, } int Metadata::SetSendQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, const WaterMark &waterMark) + const std::string &deviceId, const std::string &userId, const WaterMark &waterMark) { - return querySyncWaterMarkHelper_.SetSendQueryWaterMark(queryIdentify, deviceId, waterMark); + return querySyncWaterMarkHelper_.SetSendQueryWaterMark(queryIdentify, deviceId, userId, waterMark); } -int Metadata::GetLastQueryTime(const std::string &queryIdentify, const std::string &deviceId, Timestamp ×tamp) +int Metadata::GetLastQueryTime(const std::string &queryIdentify, const std::string &deviceId, const std::string &userId, + Timestamp ×tamp) { QueryWaterMark queryWaterMark; - int errCode = querySyncWaterMarkHelper_.GetQueryWaterMark(queryIdentify, deviceId, queryWaterMark); + int errCode = querySyncWaterMarkHelper_.GetQueryWaterMark(queryIdentify, deviceId, userId, queryWaterMark); if (errCode != E_OK) { return errCode; } @@ -395,22 +436,23 @@ int Metadata::GetLastQueryTime(const std::string &queryIdentify, const std::stri return E_OK; } -int Metadata::SetLastQueryTime(const std::string &queryIdentify, const std::string &deviceId, +int Metadata::SetLastQueryTime(const std::string &queryIdentify, const std::string &deviceId, const std::string &userId, const Timestamp ×tamp) { - return querySyncWaterMarkHelper_.SetLastQueryTime(queryIdentify, deviceId, timestamp); + return querySyncWaterMarkHelper_.SetLastQueryTime(queryIdentify, deviceId, userId, timestamp); } -int Metadata::GetSendDeleteSyncWaterMark(const DeviceID &deviceId, WaterMark &waterMark, bool isAutoLift) +int Metadata::GetSendDeleteSyncWaterMark(const DeviceID &deviceId, const DeviceID &userId, WaterMark &waterMark, + bool isAutoLift) { DeleteWaterMark deleteWaterMark; - int errCode = querySyncWaterMarkHelper_.GetDeleteSyncWaterMark(deviceId, deleteWaterMark); + int errCode = querySyncWaterMarkHelper_.GetDeleteSyncWaterMark(deviceId, userId, deleteWaterMark); if (errCode != E_OK) { return errCode; } if (isAutoLift) { WaterMark localWaterMark; - GetLocalWaterMark(deviceId, localWaterMark); + GetLocalWaterMark(deviceId, userId, localWaterMark); waterMark = std::max(deleteWaterMark.sendWaterMark, localWaterMark); } else { waterMark = deleteWaterMark.sendWaterMark; @@ -418,39 +460,41 @@ int Metadata::GetSendDeleteSyncWaterMark(const DeviceID &deviceId, WaterMark &wa return E_OK; } -int Metadata::SetSendDeleteSyncWaterMark(const DeviceID &deviceId, const WaterMark &waterMark) +int Metadata::SetSendDeleteSyncWaterMark(const DeviceID &deviceId, const DeviceID &userId, const WaterMark &waterMark) { - return querySyncWaterMarkHelper_.SetSendDeleteSyncWaterMark(deviceId, waterMark); + return querySyncWaterMarkHelper_.SetSendDeleteSyncWaterMark(deviceId, userId, waterMark); } -int Metadata::GetRecvDeleteSyncWaterMark(const DeviceID &deviceId, WaterMark &waterMark) +int Metadata::GetRecvDeleteSyncWaterMark(const DeviceID &deviceId, const DeviceID &userId, WaterMark &waterMark) { DeleteWaterMark deleteWaterMark; - int errCode = querySyncWaterMarkHelper_.GetDeleteSyncWaterMark(deviceId, deleteWaterMark); + int errCode = querySyncWaterMarkHelper_.GetDeleteSyncWaterMark(deviceId, userId, deleteWaterMark); if (errCode != E_OK) { return errCode; } WaterMark peerWaterMark; - GetPeerWaterMark(deviceId, peerWaterMark); + GetPeerWaterMark(deviceId, userId, peerWaterMark); waterMark = std::max(deleteWaterMark.recvWaterMark, peerWaterMark); return E_OK; } -int Metadata::SetRecvDeleteSyncWaterMark(const DeviceID &deviceId, const WaterMark &waterMark, bool isNeedHash) +int Metadata::SetRecvDeleteSyncWaterMark(const DeviceID &deviceId, const DeviceID &userId, const WaterMark &waterMark, + bool isNeedHash) { - return querySyncWaterMarkHelper_.SetRecvDeleteSyncWaterMark(deviceId, waterMark, isNeedHash); + return querySyncWaterMarkHelper_.SetRecvDeleteSyncWaterMark(deviceId, userId, waterMark, isNeedHash); } -int Metadata::ResetRecvQueryWaterMark(const DeviceID &deviceId, const std::string &tableName, bool isNeedHash) +int Metadata::ResetRecvQueryWaterMark(const DeviceID &deviceId, const DeviceID &userId, const std::string &tableName, + bool isNeedHash) { - return querySyncWaterMarkHelper_.ResetRecvQueryWaterMark(deviceId, tableName, isNeedHash); + return querySyncWaterMarkHelper_.ResetRecvQueryWaterMark(deviceId, userId, tableName, isNeedHash); } -void Metadata::GetDbCreateTime(const DeviceID &deviceId, uint64_t &outValue) +void Metadata::GetDbCreateTime(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue) { std::lock_guard lockGuard(metadataLock_); MetaDataValue metadata; - int errCode = GetMetaDataValue(deviceId, metadata, true); + int errCode = GetMetaDataValue(deviceId, userId, metadata, true); if (errCode == E_OK) { outValue = metadata.dbCreateTime; return; @@ -459,11 +503,11 @@ void Metadata::GetDbCreateTime(const DeviceID &deviceId, uint64_t &outValue) LOGI("Metadata::GetDbCreateTime, not found dev = %s dbCreateTime", STR_MASK(deviceId)); } -int Metadata::SetDbCreateTime(const DeviceID &deviceId, uint64_t inValue, bool isNeedHash) +int Metadata::SetDbCreateTime(const DeviceID &deviceId, const DeviceID &userId, uint64_t inValue, bool isNeedHash) { std::lock_guard lockGuard(metadataLock_); MetaDataValue metadata; - int errCode = GetMetaDataValue(deviceId, metadata, isNeedHash); + int errCode = GetMetaDataValue(deviceId, userId, metadata, isNeedHash); if (errCode == E_OK) { if (metadata.dbCreateTime != 0 && metadata.dbCreateTime != inValue) { metadata.clearDeviceDataMark = REMOVE_DEVICE_DATA_MARK; @@ -478,26 +522,26 @@ int Metadata::SetDbCreateTime(const DeviceID &deviceId, uint64_t inValue, bool i } metadata.dbCreateTime = inValue; - return SaveMetaDataValue(deviceId, metadata, isNeedHash); + return SaveMetaDataValue(deviceId, userId, metadata, isNeedHash); } -int Metadata::ResetMetaDataAfterRemoveData(const DeviceID &deviceId) +int Metadata::ResetMetaDataAfterRemoveData(const DeviceID &deviceId, const DeviceID &userId) { std::lock_guard lockGuard(metadataLock_); MetaDataValue metadata; - int errCode = GetMetaDataValue(deviceId, metadata, true); + int errCode = GetMetaDataValue(deviceId, userId, metadata, true); if (errCode == E_OK) { metadata.clearDeviceDataMark = 0; - return SaveMetaDataValue(deviceId, metadata, true); + return SaveMetaDataValue(deviceId, userId, metadata, true); } return errCode; } -void Metadata::GetRemoveDataMark(const DeviceID &deviceId, uint64_t &outValue) +void Metadata::GetRemoveDataMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue) { std::lock_guard lockGuard(metadataLock_); MetaDataValue metadata; - int errCode = GetMetaDataValue(deviceId, metadata, true); + int errCode = GetMetaDataValue(deviceId, userId, metadata, true); if (errCode == E_OK) { outValue = metadata.clearDeviceDataMark; return; @@ -601,12 +645,13 @@ void Metadata::UnlockWaterMark() const waterMarkMutex_.unlock(); } -int Metadata::GetWaterMarkInfoFromDB(const std::string &dev, bool isNeedHash, WatermarkInfo &info) +int Metadata::GetWaterMarkInfoFromDB(const std::string &dev, const std::string &userId, bool isNeedHash, + WatermarkInfo &info) { // read from db avoid watermark update in diff process std::lock_guard lockGuard(metadataLock_); MetaDataValue metadata; - int errCode = GetMetaDataValue(dev, metadata, isNeedHash); + int errCode = GetMetaDataValue(dev, userId, metadata, isNeedHash); if (errCode == -E_NOT_FOUND) { LOGD("[Metadata] not found meta value"); return E_OK; @@ -707,41 +752,41 @@ void Metadata::ClearMetaDataValue(uint32_t innerClearAction, MetaDataValue &meta } } -int Metadata::SetAbilitySyncFinishMark(const std::string &deviceId, bool finish) +int Metadata::SetAbilitySyncFinishMark(const std::string &deviceId, const std::string &userId, bool finish) { - return SetSyncMark(deviceId, SyncMark::SYNC_MARK_ABILITY_SYNC, finish); + return SetSyncMark(deviceId, userId, SyncMark::SYNC_MARK_ABILITY_SYNC, finish); } -bool Metadata::IsAbilitySyncFinish(const std::string &deviceId) +bool Metadata::IsAbilitySyncFinish(const std::string &deviceId, const std::string &userId) { - return IsContainSyncMark(deviceId, SyncMark::SYNC_MARK_ABILITY_SYNC); + return IsContainSyncMark(deviceId, userId, SyncMark::SYNC_MARK_ABILITY_SYNC); } -int Metadata::SetTimeSyncFinishMark(const std::string &deviceId, bool finish) +int Metadata::SetTimeSyncFinishMark(const std::string &deviceId, const std::string &userId, bool finish) { - return SetSyncMark(deviceId, SyncMark::SYNC_MARK_TIME_SYNC, finish); + return SetSyncMark(deviceId, userId, SyncMark::SYNC_MARK_TIME_SYNC, finish); } -int Metadata::SetTimeChangeMark(const std::string &deviceId, bool change) +int Metadata::SetTimeChangeMark(const std::string &deviceId, const std::string &userId, bool change) { - return SetSyncMark(deviceId, SyncMark::SYNC_MARK_TIME_CHANGE, change); + return SetSyncMark(deviceId, userId, SyncMark::SYNC_MARK_TIME_CHANGE, change); } -bool Metadata::IsTimeSyncFinish(const std::string &deviceId) +bool Metadata::IsTimeSyncFinish(const std::string &deviceId, const std::string &userId) { - return IsContainSyncMark(deviceId, SyncMark::SYNC_MARK_TIME_SYNC); + return IsContainSyncMark(deviceId, userId, SyncMark::SYNC_MARK_TIME_SYNC); } -bool Metadata::IsTimeChange(const std::string &deviceId) +bool Metadata::IsTimeChange(const std::string &deviceId, const std::string &userId) { - return IsContainSyncMark(deviceId, SyncMark::SYNC_MARK_TIME_CHANGE); + return IsContainSyncMark(deviceId, userId, SyncMark::SYNC_MARK_TIME_CHANGE); } -int Metadata::SetSyncMark(const std::string &deviceId, SyncMark syncMark, bool finish) +int Metadata::SetSyncMark(const std::string &deviceId, const std::string &userId, SyncMark syncMark, bool finish) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); auto mark = static_cast(syncMark); if (finish) { metadata.syncMark |= mark; @@ -750,56 +795,56 @@ int Metadata::SetSyncMark(const std::string &deviceId, SyncMark syncMark, bool f } LOGD("[Metadata] Mark:%" PRIx64 " sync finish:%d sync mark:%" PRIu64, mark, static_cast(finish), metadata.syncMark); - return SaveMetaDataValue(deviceId, metadata); + return SaveMetaDataValue(deviceId, userId, metadata); } -bool Metadata::IsContainSyncMark(const std::string &deviceId, SyncMark syncMark) +bool Metadata::IsContainSyncMark(const std::string &deviceId, const std::string &userId, SyncMark syncMark) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); auto mark = static_cast(syncMark); return (metadata.syncMark & mark) == mark; } -int Metadata::SetRemoteSchemaVersion(const std::string &deviceId, uint64_t schemaVersion) +int Metadata::SetRemoteSchemaVersion(const std::string &deviceId, const std::string &userId, uint64_t schemaVersion) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); metadata.remoteSchemaVersion = schemaVersion; LOGI("[Metadata] Set %.3s schema version %" PRIu64, deviceId.c_str(), schemaVersion); - int errCode = SaveMetaDataValue(deviceId, metadata); + int errCode = SaveMetaDataValue(deviceId, userId, metadata); if (errCode != E_OK) { LOGW("[Metadata] Set remote schema version failed"); } return errCode; } -uint64_t Metadata::GetRemoteSchemaVersion(const std::string &deviceId) +uint64_t Metadata::GetRemoteSchemaVersion(const std::string &deviceId, const std::string &userId) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); LOGI("[Metadata] Get %.3s schema version %" PRIu64, deviceId.c_str(), metadata.remoteSchemaVersion); return metadata.remoteSchemaVersion; } -int Metadata::SetSystemTimeOffset(const std::string &deviceId, int64_t systemTimeOffset) +int Metadata::SetSystemTimeOffset(const std::string &deviceId, const std::string &userId, int64_t systemTimeOffset) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); metadata.systemTimeOffset = systemTimeOffset; LOGI("[Metadata] Set %.3s systemTimeOffset %" PRId64, deviceId.c_str(), systemTimeOffset); - return SaveMetaDataValue(deviceId, metadata); + return SaveMetaDataValue(deviceId, userId, metadata); } -int64_t Metadata::GetSystemTimeOffset(const std::string &deviceId) +int64_t Metadata::GetSystemTimeOffset(const std::string &deviceId, const std::string &userId) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); LOGI("[Metadata] Get %.3s systemTimeOffset %" PRId64, deviceId.c_str(), metadata.systemTimeOffset); return metadata.systemTimeOffset; } @@ -939,11 +984,12 @@ int Metadata::InitLocalMetaData() return errCode; } -int Metadata::GetMetaDataValueFromDB(const std::string &deviceId, bool isNeedHash, MetaDataValue &metaDataValue) +int Metadata::GetMetaDataValueFromDB(const std::string &deviceId, const std::string &userId, bool isNeedHash, + MetaDataValue &metaDataValue) { DeviceID hashDeviceId; Key devKey; - GetHashDeviceId(deviceId, hashDeviceId, isNeedHash); + GetHashDeviceId(deviceId, userId, hashDeviceId, isNeedHash); DBCommon::StringToVector(hashDeviceId, devKey); return GetMetaDataValueFromDB(devKey, metaDataValue); @@ -960,21 +1006,52 @@ int Metadata::GetMetaDataValueFromDB(const Key &key, MetaDataValue &metaDataValu return DeSerializeMetaData(value, metaDataValue); } -uint64_t Metadata::GetRemoteSoftwareVersion(const std::string &deviceId) +int Metadata::GetMetaDataFromDBByPrefixKey(const std::string &deviceId, bool isNeedHash, + std::map &metaData) +{ + DeviceID hashId; + Key keyPrefix; + GetHashDeviceId(deviceId, "", hashId, isNeedHash); + DBCommon::StringToVector(hashId, keyPrefix); + + std::map data; + int errCode = GetMetadataFromDbByPrefixKey(keyPrefix, data); + if (errCode != E_OK) { + if (errCode == -E_NOT_FOUND) { + MetaDataValue oneMetaData; + metaData[keyPrefix] = oneMetaData; + return E_OK; + } + LOGE("[Metadata] Get metadata from db by prefix key failed %d", errCode); + return errCode; + } + for (const auto &oneData : data) { + MetaDataValue metaDataValue; + errCode = DeSerializeMetaData(oneData.second, metaDataValue); + if (errCode != E_OK) { + LOGE("[Metadata] DeSerialize meta data failed %d", errCode); + return errCode; + } + metaData[oneData.first] = metaDataValue; + } + return E_OK; +} + +uint64_t Metadata::GetRemoteSoftwareVersion(const std::string &deviceId, const std::string &userId) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); return metadata.remoteSoftwareVersion; } -int Metadata::SetRemoteSoftwareVersion(const std::string &deviceId, uint64_t version) +int Metadata::SetRemoteSoftwareVersion(const std::string &deviceId, const std::string &userId, uint64_t version) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); metadata.remoteSoftwareVersion = version; LOGI("[Metadata] Set %.3s version %" PRId64, deviceId.c_str(), version); - return SaveMetaDataValue(deviceId, metadata); + return SaveMetaDataValue(deviceId, userId, metadata); } } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.h index 4df789a01199af3004e6152f069ee368705bd8a0..038747e68a2231a67c46c0e89199b9e8db71c68a 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.h @@ -67,17 +67,17 @@ public: int Initialize(ISyncInterface *storage); - int SaveTimeOffset(const DeviceID &deviceId, TimeOffset inValue); + int SaveTimeOffset(const DeviceID &deviceId, const DeviceID &userId, TimeOffset inValue); - void GetTimeOffset(const DeviceID &deviceId, TimeOffset &outValue); + void GetTimeOffset(const DeviceID &deviceId, const DeviceID &userId, TimeOffset &outValue); - virtual void GetLocalWaterMark(const DeviceID &deviceId, uint64_t &outValue); + virtual void GetLocalWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue); - int SaveLocalWaterMark(const DeviceID &deviceId, uint64_t inValue); + int SaveLocalWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t inValue); - void GetPeerWaterMark(const DeviceID &deviceId, uint64_t &outValue, bool isNeedHash = true); + void GetPeerWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue, bool isNeedHash = true); - int SavePeerWaterMark(const DeviceID &deviceId, uint64_t inValue, bool isNeedHash); + int SavePeerWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t inValue, bool isNeedHash); int SaveLocalTimeOffset(TimeOffset timeOffset, bool saveIntoDb = true); @@ -85,52 +85,56 @@ public: int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash); - int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, const std::string &tableName); + int EraseDeviceWaterMark(const std::string &deviceId, const std::string &userId, bool isNeedHash, + const std::string &tableName); void SetLastLocalTime(Timestamp lastLocalTime); Timestamp GetLastLocalTime() const; int SetSendQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, const WaterMark &waterMark); + const std::string &deviceId, const std::string &userId, const WaterMark &waterMark); // the querySync's sendWatermark will increase by the device watermark // if the sendWatermark less than device watermark int GetSendQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, WaterMark &waterMark, bool isAutoLift = true); + const std::string &deviceId, const std::string &userId, WaterMark &waterMark, bool isAutoLift = true); int SetRecvQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, const WaterMark &waterMark); + const std::string &deviceId, const std::string &userId, const WaterMark &waterMark); // the querySync's recvWatermark will increase by the device watermark // if the watermark less than device watermark int GetRecvQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, WaterMark &waterMark); + const std::string &deviceId, const std::string &userId, WaterMark &waterMark); virtual int SetLastQueryTime(const std::string &queryIdentify, const std::string &deviceId, - const Timestamp ×tamp); + const std::string &userId, const Timestamp ×tamp); - virtual int GetLastQueryTime(const std::string &queryIdentify, const std::string &deviceId, Timestamp ×tamp); + virtual int GetLastQueryTime(const std::string &queryIdentify, const std::string &deviceId, + const std::string &userId, Timestamp ×tamp); - int SetSendDeleteSyncWaterMark(const std::string &deviceId, const WaterMark &waterMark); + int SetSendDeleteSyncWaterMark(const std::string &deviceId, const std::string &userId, const WaterMark &waterMark); // the deleteSync's sendWatermark will increase by the device watermark // if the sendWatermark less than device watermark - int GetSendDeleteSyncWaterMark(const std::string &deviceId, WaterMark &waterMark, bool isAutoLift = true); + int GetSendDeleteSyncWaterMark(const std::string &deviceId, const std::string &userId, WaterMark &waterMark, + bool isAutoLift = true); - int SetRecvDeleteSyncWaterMark(const std::string &deviceId, const WaterMark &waterMark, bool isNeedHash = true); + int SetRecvDeleteSyncWaterMark(const std::string &deviceId, const std::string &userId, const WaterMark &waterMark, + bool isNeedHash = true); // the deleteSync's recvWatermark will increase by the device watermark // if the recvWatermark less than device watermark - int GetRecvDeleteSyncWaterMark(const std::string &deviceId, WaterMark &waterMark); + int GetRecvDeleteSyncWaterMark(const std::string &deviceId, const std::string &userId, WaterMark &waterMark); - void GetDbCreateTime(const DeviceID &deviceId, uint64_t &outValue); + void GetDbCreateTime(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue); - int SetDbCreateTime(const DeviceID &deviceId, uint64_t inValue, bool isNeedHash); + int SetDbCreateTime(const DeviceID &deviceId, const DeviceID &userId, uint64_t inValue, bool isNeedHash); - int ResetMetaDataAfterRemoveData(const DeviceID &deviceId); + int ResetMetaDataAfterRemoveData(const DeviceID &deviceId, const DeviceID &userId); - void GetRemoveDataMark(const DeviceID &deviceId, uint64_t &outValue); + void GetRemoveDataMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue); // always get value from db, value updated from storage trigger uint64_t GetQueryLastTimestamp(const DeviceID &deviceId, const std::string &queryId) const; @@ -145,45 +149,46 @@ public: void UnlockWaterMark() const; - int GetWaterMarkInfoFromDB(const std::string &dev, bool isNeedHash, WatermarkInfo &info); + int GetWaterMarkInfoFromDB(const std::string &dev, const std::string &userId, bool isNeedHash, WatermarkInfo &info); int ClearAllAbilitySyncFinishMark(); - int SetAbilitySyncFinishMark(const std::string &deviceId, bool finish); + int SetAbilitySyncFinishMark(const std::string &deviceId, const std::string &userId, bool finish); - bool IsAbilitySyncFinish(const std::string &deviceId); + bool IsAbilitySyncFinish(const std::string &deviceId, const std::string &userId); int ClearAllTimeSyncFinishMark(); - int SetTimeSyncFinishMark(const std::string &deviceId, bool finish); + int SetTimeSyncFinishMark(const std::string &deviceId, const std::string &userId, bool finish); - int SetTimeChangeMark(const std::string &deviceId, bool change); + int SetTimeChangeMark(const std::string &deviceId, const std::string &userId, bool change); - bool IsTimeSyncFinish(const std::string &deviceId); + bool IsTimeSyncFinish(const std::string &deviceId, const std::string &userId); - bool IsTimeChange(const std::string &deviceId); + bool IsTimeChange(const std::string &deviceId, const std::string &userId); - int SetRemoteSchemaVersion(const std::string &deviceId, uint64_t schemaVersion); + int SetRemoteSchemaVersion(const std::string &deviceId, const std::string &userId, uint64_t schemaVersion); - uint64_t GetRemoteSchemaVersion(const std::string &deviceId); + uint64_t GetRemoteSchemaVersion(const std::string &deviceId, const std::string &userId); - int SetSystemTimeOffset(const std::string &deviceId, int64_t systemTimeOffset); + int SetSystemTimeOffset(const std::string &deviceId, const std::string &userId, int64_t systemTimeOffset); - int64_t GetSystemTimeOffset(const std::string &deviceId); + int64_t GetSystemTimeOffset(const std::string &deviceId, const std::string &userId); std::pair GetLocalSchemaVersion(); int SetLocalSchemaVersion(uint64_t schemaVersion); - uint64_t GetRemoteSoftwareVersion(const std::string &deviceId); + uint64_t GetRemoteSoftwareVersion(const std::string &deviceId, const std::string &userId); - int SetRemoteSoftwareVersion(const std::string &deviceId, uint64_t version); + int SetRemoteSoftwareVersion(const std::string &deviceId, const std::string &userId, uint64_t version); private: - int SaveMetaDataValue(const DeviceID &deviceId, const MetaDataValue &inValue, bool isNeedHash = true); + int SaveMetaDataValue(const DeviceID &deviceId, const DeviceID &userId, const MetaDataValue &inValue, + bool isNeedHash = true); // sync module need hash devices id - int GetMetaDataValue(const DeviceID &deviceId, MetaDataValue &outValue, bool isNeedHash); + int GetMetaDataValue(const DeviceID &deviceId, const DeviceID &userId, MetaDataValue &outValue, bool isNeedHash); static int SerializeMetaData(const MetaDataValue &inValue, std::vector &outValue); @@ -191,6 +196,8 @@ private: int GetMetadataFromDb(const std::vector &key, std::vector &outValue) const; + int GetMetadataFromDbByPrefixKey(const Key &keyPrefix, std::map &data) const; + int SetMetadataToDb(const std::vector &key, const std::vector &inValue); int64_t StringToLong(const std::vector &value) const; @@ -199,14 +206,15 @@ private: int LoadAllMetadata(); - void GetHashDeviceId(const DeviceID &deviceId, DeviceID &hashDeviceId, bool isNeedHash); + void GetHashDeviceId(const DeviceID &deviceId, const DeviceID &userId, DeviceID &hashDeviceId, bool isNeedHash); // reset the waterMark to zero - int ResetRecvQueryWaterMark(const DeviceID &deviceId, const std::string &tableName, bool isNeedHash); + int ResetRecvQueryWaterMark(const DeviceID &deviceId, const DeviceID &userId, const std::string &tableName, + bool isNeedHash); - int SetSyncMark(const std::string &deviceId, SyncMark syncMark, bool finish); + int SetSyncMark(const std::string &deviceId, const std::string &userId, SyncMark syncMark, bool finish); - bool IsContainSyncMark(const std::string &deviceId, SyncMark syncMark); + bool IsContainSyncMark(const std::string &deviceId, const std::string &userId, SyncMark syncMark); int SaveLocalMetaData(const LocalMetaData &localMetaData); @@ -233,9 +241,12 @@ private: int InitLocalMetaData(); - int GetMetaDataValueFromDB(const std::string &deviceId, bool isNeedHash, MetaDataValue &metaDataValue); + int GetMetaDataValueFromDB(const std::string &deviceId, const std::string &userId, bool isNeedHash, + MetaDataValue &metaDataValue); int GetMetaDataValueFromDB(const Key &key, MetaDataValue &metaDataValue); + int GetMetaDataFromDBByPrefixKey(const std::string &deviceId, bool isNeedHash, + std::map &metaData); // store localTimeOffset in ram; if change, should add a lock first, change here and metadata, // then release lock @@ -246,7 +257,7 @@ private: // if changed, it should be locked from save-to-db to change-in-memory.save to db must be first, // if save to db fail, it will not be changed in memory. mutable std::mutex metadataLock_; - std::map deviceIdToHashDeviceIdMap_; + std::map deviceIdToHashDeviceIdMap_; // store localTimeOffset in ram, used to make timestamp increase mutable std::mutex lastLocalTimeLock_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/multiver/multi_ver_sync_state_machine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/multiver/multi_ver_sync_state_machine.cpp index 49df30b6eea4f5afff3cc5bd12f7f1b3ae8b5103..e658e17be855e7255fa5f7d298c085926da58669 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/multiver/multi_ver_sync_state_machine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/multiver/multi_ver_sync_state_machine.cpp @@ -74,7 +74,8 @@ int MultiVerSyncStateMachine::Initialize(ISyncTaskContext *context, ISyncInterfa multiVerDataSync_ = std::make_unique(); valueSliceSync_ = std::make_unique(); - errCode = timeSync_->Initialize(communicator, metadata, syncInterface, context->GetDeviceId()); + errCode = timeSync_->Initialize(communicator, metadata, syncInterface, context->GetDeviceId(), + context->GetTargetUserId()); if (errCode != E_OK) { LOGE("timeSync_->Initialize failed err %d", errCode); goto ERROR_OUT; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/query_sync_water_mark_helper.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/query_sync_water_mark_helper.cpp index c708137cc914a706b7ac5d7a64df1b9737c766e1..61b961abbf526e5a00c51df5b7d6b28f6b2938ed 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/query_sync_water_mark_helper.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/query_sync_water_mark_helper.cpp @@ -50,6 +50,14 @@ int QuerySyncWaterMarkHelper::GetMetadataFromDb(const std::vector &key, return storage_->GetMetaData(key, outValue); } +int QuerySyncWaterMarkHelper::GetMetadataByPrefixKeyFromDb(const Key &prefixKey, std::map &data) +{ + if (storage_ == nullptr) { + return -E_INVALID_DB; + } + return storage_->GetMetaDataByPrefixKey(prefixKey, data); +} + int QuerySyncWaterMarkHelper::SetMetadataToDb(const std::vector &key, const std::vector &inValue) { if (storage_ == nullptr) { @@ -105,25 +113,25 @@ int QuerySyncWaterMarkHelper::GetQueryWaterMarkInCacheAndDb(const std::string &c } int QuerySyncWaterMarkHelper::GetQueryWaterMark(const std::string &queryIdentify, const std::string &deviceId, - QueryWaterMark &queryWaterMark) + const std::string &userId, QueryWaterMark &queryWaterMark) { - std::string cacheKey = GetHashQuerySyncDeviceId(deviceId, queryIdentify); + std::string cacheKey = GetHashQuerySyncDeviceId(deviceId, userId, queryIdentify); std::lock_guard autoLock(queryWaterMarkLock_); return GetQueryWaterMarkInCacheAndDb(cacheKey, queryWaterMark); } int QuerySyncWaterMarkHelper::SetRecvQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, const WaterMark &waterMark) + const std::string &deviceId, const std::string &userId, const WaterMark &waterMark) { - std::string cacheKey = GetHashQuerySyncDeviceId(deviceId, queryIdentify); + std::string cacheKey = GetHashQuerySyncDeviceId(deviceId, userId, queryIdentify); std::lock_guard autoLock(queryWaterMarkLock_); return SetRecvQueryWaterMarkWithoutLock(cacheKey, waterMark); } int QuerySyncWaterMarkHelper::SetLastQueryTime(const std::string &queryIdentify, - const std::string &deviceId, const Timestamp ×tamp) + const std::string &deviceId, const std::string &userId, const Timestamp ×tamp) { - std::string cacheKey = GetHashQuerySyncDeviceId(deviceId, queryIdentify); + std::string cacheKey = GetHashQuerySyncDeviceId(deviceId, userId, queryIdentify); std::lock_guard autoLock(queryWaterMarkLock_); QueryWaterMark queryWaterMark; int errCode = GetQueryWaterMarkInCacheAndDb(cacheKey, queryWaterMark); @@ -147,9 +155,9 @@ int QuerySyncWaterMarkHelper::SetRecvQueryWaterMarkWithoutLock(const std::string } int QuerySyncWaterMarkHelper::SetSendQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, const WaterMark &waterMark) + const std::string &deviceId, const std::string &userId, const WaterMark &waterMark) { - std::string cacheKey = GetHashQuerySyncDeviceId(deviceId, queryIdentify); + std::string cacheKey = GetHashQuerySyncDeviceId(deviceId, userId, queryIdentify); QueryWaterMark queryWaterMark; std::lock_guard autoLock(queryWaterMarkLock_); int errCode = GetQueryWaterMarkInCacheAndDb(cacheKey, queryWaterMark); @@ -265,31 +273,36 @@ uint64_t QuerySyncWaterMarkHelper::CalculateQueryWaterMarkSize(const QueryWaterM return length; } -DeviceID QuerySyncWaterMarkHelper::GetHashQuerySyncDeviceId(const DeviceID &deviceId, const DeviceID &queryId) +DeviceID QuerySyncWaterMarkHelper::GetHashQuerySyncDeviceId(const DeviceID &deviceId, const DeviceID &userId, + const DeviceID &queryId) { std::lock_guard autoLock(queryWaterMarkLock_); DeviceID hashQuerySyncId; - if (deviceIdToHashQuerySyncIdMap_[deviceId].count(queryId) == 0) { + DeviceSyncTarget deviceInfo(deviceId, userId); + if (deviceIdToHashQuerySyncIdMap_[deviceInfo].count(queryId) == 0) { // do not modify this - hashQuerySyncId = DBConstant::QUERY_SYNC_PREFIX_KEY + DBCommon::TransferHashString(deviceId) + queryId; - deviceIdToHashQuerySyncIdMap_[deviceId][queryId] = hashQuerySyncId; + hashQuerySyncId = DBConstant::QUERY_SYNC_PREFIX_KEY + DBCommon::TransferHashString(deviceId) + queryId + + DBConstant::USERID_PREFIX_KEY + userId; + deviceIdToHashQuerySyncIdMap_[deviceInfo][queryId] = hashQuerySyncId; } else { - hashQuerySyncId = deviceIdToHashQuerySyncIdMap_[deviceId][queryId]; + hashQuerySyncId = deviceIdToHashQuerySyncIdMap_[deviceInfo][queryId]; } return hashQuerySyncId; } -int QuerySyncWaterMarkHelper::GetDeleteSyncWaterMark(const std::string &deviceId, DeleteWaterMark &deleteWaterMark) +int QuerySyncWaterMarkHelper::GetDeleteSyncWaterMark(const std::string &deviceId, const std::string &userId, + DeleteWaterMark &deleteWaterMark) { - std::string hashId = GetHashDeleteSyncDeviceId(deviceId); + std::string hashId = GetHashDeleteSyncDeviceId(deviceId, userId); // lock prevent different thread visit deleteSyncCache_ std::lock_guard autoLock(deleteSyncLock_); return GetDeleteWaterMarkFromCache(hashId, deleteWaterMark); } -int QuerySyncWaterMarkHelper::SetSendDeleteSyncWaterMark(const DeviceID &deviceId, const WaterMark &waterMark) +int QuerySyncWaterMarkHelper::SetSendDeleteSyncWaterMark(const DeviceID &deviceId, const std::string &userId, + const WaterMark &waterMark) { - std::string hashId = GetHashDeleteSyncDeviceId(deviceId); + std::string hashId = GetHashDeleteSyncDeviceId(deviceId, userId); DeleteWaterMark deleteWaterMark; // lock prevent different thread visit deleteSyncCache_ std::lock_guard autoLock(deleteSyncLock_); @@ -301,19 +314,35 @@ int QuerySyncWaterMarkHelper::SetSendDeleteSyncWaterMark(const DeviceID &deviceI return UpdateDeleteSyncCacheAndSave(hashId, deleteWaterMark); } -int QuerySyncWaterMarkHelper::SetRecvDeleteSyncWaterMark(const DeviceID &deviceId, const WaterMark &waterMark, - bool isNeedHash) +int QuerySyncWaterMarkHelper::SetRecvDeleteSyncWaterMark(const DeviceID &deviceId, const std::string &userId, + const WaterMark &waterMark, bool isNeedHash) { - std::string hashId = GetHashDeleteSyncDeviceId(deviceId, isNeedHash); - DeleteWaterMark deleteWaterMark; + std::string hashId = GetHashDeleteSyncDeviceId(deviceId, userId, isNeedHash); // lock prevent different thread visit deleteSyncCache_ std::lock_guard autoLock(deleteSyncLock_); - int errCode = GetDeleteWaterMarkFromCache(hashId, deleteWaterMark); + int errCode = E_OK; + std::map deleteWaterMarks; + if (!userId.empty()) { + DeleteWaterMark deleteWaterMark; + Key dbKey; + DBCommon::StringToVector(hashId, dbKey); + errCode = GetDeleteWaterMarkFromCache(hashId, deleteWaterMark); + deleteWaterMark.recvWaterMark = waterMark; + deleteWaterMarks[dbKey] = deleteWaterMark; + } else { + errCode = GetDeleteWatersMarkFromDB(hashId, deleteWaterMarks); + } if (errCode != E_OK) { return errCode; } - deleteWaterMark.recvWaterMark = waterMark; - return UpdateDeleteSyncCacheAndSave(hashId, deleteWaterMark); + for (auto &deleteWaterMark : deleteWaterMarks) { + deleteWaterMark.second.recvWaterMark = waterMark; + errCode = UpdateDeleteSyncCacheAndSave(hashId, deleteWaterMark.second); + if (errCode != E_OK) { + return errCode; + } + } + return E_OK; } int QuerySyncWaterMarkHelper::UpdateDeleteSyncCacheAndSave(const std::string &dbKey, @@ -354,6 +383,34 @@ int QuerySyncWaterMarkHelper::GetDeleteWaterMarkFromDB(const DeviceID &hashDevic return DeSerializeDeleteWaterMark(dbValue, deleteWaterMark); } +int QuerySyncWaterMarkHelper::GetDeleteWatersMarkFromDB(const DeviceID &hashId, + std::map &deleteWaterMarks) +{ + Key dbKeyPrefix; + DBCommon::StringToVector(hashId, dbKeyPrefix); + // search in db + std::map dbData; + int errCode = GetMetadataByPrefixKeyFromDb(dbKeyPrefix, dbData); + if (errCode == -E_NOT_FOUND) { + DeleteWaterMark deleteWaterMark; + deleteWaterMarks[dbKeyPrefix] = deleteWaterMark; + return E_OK; + } + if (errCode != E_OK) { + return errCode; + } + // serialize value + for (const auto &oneDbData : dbData) { + DeleteWaterMark deleteWaterMark; + errCode = DeSerializeDeleteWaterMark(oneDbData.second, deleteWaterMark); + if (errCode != E_OK) { + return errCode; + } + deleteWaterMarks[oneDbData.first] = deleteWaterMark; + } + return E_OK; +} + int QuerySyncWaterMarkHelper::SaveDeleteWaterMarkToDB(const DeviceID &hashDeviceId, const DeleteWaterMark &deleteWaterMark) { @@ -373,16 +430,18 @@ int QuerySyncWaterMarkHelper::SaveDeleteWaterMarkToDB(const DeviceID &hashDevice return errCode; } -DeviceID QuerySyncWaterMarkHelper::GetHashDeleteSyncDeviceId(const DeviceID &deviceId, bool isNeedHash) +DeviceID QuerySyncWaterMarkHelper::GetHashDeleteSyncDeviceId(const DeviceID &deviceId, const DeviceID &userId, + bool isNeedHash) { DeviceID hashDeleteSyncId; + DeviceSyncTarget deviceInfo(deviceId, userId); std::lock_guard autoLock(deleteSyncLock_); - if (deviceIdToHashDeleteSyncIdMap_.count(deviceId) == 0) { + if (deviceIdToHashDeleteSyncIdMap_.count(deviceInfo) == 0) { hashDeleteSyncId = DBConstant::DELETE_SYNC_PREFIX_KEY + - (isNeedHash ? DBCommon::TransferHashString(deviceId) : deviceId); - deviceIdToHashDeleteSyncIdMap_.insert(std::pair(deviceId, hashDeleteSyncId)); + (isNeedHash ? DBCommon::TransferHashString(deviceId) : deviceId) + DBConstant::USERID_PREFIX_KEY + userId; + deviceIdToHashDeleteSyncIdMap_.insert(std::pair(deviceInfo, hashDeleteSyncId)); } else { - hashDeleteSyncId = deviceIdToHashDeleteSyncIdMap_[deviceId]; + hashDeleteSyncId = deviceIdToHashDeleteSyncIdMap_[deviceInfo]; } return hashDeleteSyncId; } @@ -484,8 +543,8 @@ int QuerySyncWaterMarkHelper::RemoveLeastUsedQuerySyncItems(const std::vector autoLock(queryWaterMarkLock_); @@ -496,6 +555,9 @@ int QuerySyncWaterMarkHelper::ResetRecvQueryWaterMark(const DeviceID &deviceId, std::string hexTableName = DBCommon::TransferStringToHex(hashTableName); prefixKeyStr += hexTableName; } + if (!userId.empty()) { + prefixKeyStr += DBConstant::USERID_PREFIX_KEY + userId; + } // remove in db Key prefixKey; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/query_sync_water_mark_helper.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/query_sync_water_mark_helper.h index 6c576a2b91d81ec192b6ea0f83bd4211131b3346..1e96e746f7f3e5eca270167678977413c558b8ea 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/query_sync_water_mark_helper.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/query_sync_water_mark_helper.h @@ -50,23 +50,25 @@ public: int Initialize(ISyncInterface *storage); - int GetQueryWaterMark(const std::string &queryIdentify, const std::string &deviceId, + int GetQueryWaterMark(const std::string &queryIdentify, const std::string &deviceId, const std::string &userId, QueryWaterMark &queryWaterMark); int SetSendQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, const WaterMark &waterMark); + const std::string &deviceId, const std::string &userId, const WaterMark &waterMark); int SetRecvQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, const WaterMark &waterMark); + const std::string &deviceId, const std::string &userId, const WaterMark &waterMark); int SetLastQueryTime(const std::string &queryIdentify, - const std::string &deviceId, const Timestamp ×tamp); + const std::string &deviceId, const std::string &userId, const Timestamp ×tamp); - int GetDeleteSyncWaterMark(const std::string &deviceId, DeleteWaterMark &deleteWaterMark); + int GetDeleteSyncWaterMark(const std::string &deviceId, const std::string &userId, + DeleteWaterMark &deleteWaterMark); - int SetSendDeleteSyncWaterMark(const std::string &deviceId, const WaterMark &waterMark); + int SetSendDeleteSyncWaterMark(const std::string &deviceId, const std::string &userId, const WaterMark &waterMark); - int SetRecvDeleteSyncWaterMark(const std::string &deviceId, const WaterMark &waterMark, bool isNeedHash); + int SetRecvDeleteSyncWaterMark(const std::string &deviceId, const std::string &userId, const WaterMark &waterMark, + bool isNeedHash); // this function will read deleteWaterMark from db by it's deleteWaterMarkKey // and then serialize it and put to cache @@ -76,7 +78,8 @@ public: int RemoveLeastUsedQuerySyncItems(const std::vector &querySyncIds); // reset the waterMark to zero - int ResetRecvQueryWaterMark(const DeviceID &deviceId, const std::string &tableName, bool isNeedHash); + int ResetRecvQueryWaterMark(const DeviceID &deviceId, const DeviceID &userId, const std::string &tableName, + bool isNeedHash); static std::string GetQuerySyncPrefixKey(); @@ -86,6 +89,8 @@ private: int GetMetadataFromDb(const std::vector &key, std::vector &outValue); + int GetMetadataByPrefixKeyFromDb(const Key &prefixKey, std::map &data); + int SetMetadataToDb(const std::vector &key, const std::vector &inValue); int DeleteMetaDataFromDB(const std::vector &keys) const; @@ -107,7 +112,7 @@ private: // get the querySync hashId in cache_ or generate one and then put it in to cache_ // the hashId is made up of "QUERY_SYNC_PREFIX_KEY" + hash(deviceId) + queryId - DeviceID GetHashQuerySyncDeviceId(const DeviceID &deviceId, const DeviceID &queryId); + DeviceID GetHashQuerySyncDeviceId(const DeviceID &deviceId, const DeviceID &userId, const DeviceID &queryId); // put queryWaterMark to lru cache_ and then save to db int UpdateCacheAndSave(const std::string &cacheKey, QueryWaterMark &queryWaterMark); @@ -118,12 +123,14 @@ private: // get the deleteSync hashId in cache_ or generate one and then put it in to cache_ // the hashId is made up of "DELETE_SYNC_PREFIX_KEY" + hash(deviceId) - DeviceID GetHashDeleteSyncDeviceId(const DeviceID &deviceId, bool isNeedHash = true); + DeviceID GetHashDeleteSyncDeviceId(const DeviceID &deviceId, const DeviceID &userId, bool isNeedHash = true); int SaveDeleteWaterMarkToDB(const DeviceID &hashDeviceId, const DeleteWaterMark &deleteWaterMark); int GetDeleteWaterMarkFromDB(const DeviceID &hashDeviceId, DeleteWaterMark &deleteWaterMark); + int GetDeleteWatersMarkFromDB(const DeviceID &hashId, std::map &deleteWaterMarks); + // put queryWaterMark to lru cache_ and then save to db int UpdateDeleteSyncCacheAndSave(const std::string &dbKey, const DeleteWaterMark &deleteWaterMark); @@ -143,11 +150,11 @@ private: // because it will change the eliminationChain // and the queryWaterMark use a LRU Map to store in ram std::mutex queryWaterMarkLock_; - std::map> deviceIdToHashQuerySyncIdMap_; + std::map> deviceIdToHashQuerySyncIdMap_; // also store deleteKeyWaterMark should add a lock std::mutex deleteSyncLock_; - std::map deviceIdToHashDeleteSyncIdMap_; + std::map deviceIdToHashDeleteSyncIdMap_; ISyncInterface *storage_; }; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor.cpp index 3d69bcf1bfe3dc8f7b2f628b56fd363fde8a298f..0ecc1db382dfaf768cc21c31943b74978f31edc4 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor.cpp @@ -105,8 +105,6 @@ int RemoteExecutor::ReceiveMessage(const std::string &targetDev, Message *inMsg) } if (closed_) { LOGD("[RemoteExecutor][ReceiveMessageInner] db is closing ignore msg"); - delete inMsg; - inMsg = nullptr; return -E_BUSY; } RefObject::IncObjRef(this); @@ -1040,4 +1038,10 @@ int RemoteExecutor::CheckRemoteRecvData(const std::string &device, SyncGenericIn } return -E_SECURITY_OPTION_CHECK_ERROR; } + +int32_t RemoteExecutor::GetTaskCount() const +{ + std::lock_guard autoLock(taskLock_); + return static_cast(taskMap_.size()); // max taskMap_ size is 32 +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor.h index 62544a175d6032badde6bf2ab0b27fe17a083628..11fce6354454c877f2b662089c1b7597ef294b8b 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor.h @@ -72,6 +72,7 @@ public: void NotifyConnectionClosed(uint64_t connectionId); + int32_t GetTaskCount() const; protected: virtual void ParseOneRequestMessage(const std::string &device, Message *inMsg); @@ -147,7 +148,7 @@ private: static int CheckRemoteRecvData(const std::string &device, SyncGenericInterface *storage, int32_t remoteSecLabel, uint32_t remoteVersion); - std::mutex taskLock_; + mutable std::mutex taskLock_; std::map> searchTaskQueue_; // key is device, value is sessionId queue std::map> deviceWorkingSet_; // key is device, value is sessionId set std::map taskMap_; // key is sessionId diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_message_schedule.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_message_schedule.cpp index da64cdb2510d6f9b3bc95b3b52256a890e2df6cb..d558c3256e2409e37c2cc428ad9fdf3c78a5eb12 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_message_schedule.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_message_schedule.cpp @@ -93,8 +93,8 @@ void SingleVerDataMessageSchedule::ScheduleInfoHandle(bool isNeedHandleStatus, b ClearMsgMapWithNoLock(); expectedSequenceId_ = 1; } else { - LOGI("[DataMsgSchedule] DealMsg seqId=%" PRIu32 " finishedPacketId=%" PRIu64 " ok,label=%s,dev=%s", - expectedSequenceId_, finishedPacketId_, label_.c_str(), STR_MASK(deviceId_)); + LOGI("[DataMsgSchedule] DealMsg seqId=%" PRIu32 " finishedPacketId=%" PRIu64 " ok, dev=%s", + expectedSequenceId_, finishedPacketId_, STR_MASK(deviceId_)); expectedSequenceId_++; } } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_packet.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_packet.h index 0f0d54333c27612ceaaffa26047882670316b766..18cedc192f219d686dcf2e9602c5083fe25cfe5f 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_packet.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_packet.h @@ -31,12 +31,11 @@ using SendDataItem = SingleVerKvEntry *; class DataRequestPacket { public: DataRequestPacket() {}; - virtual ~DataRequestPacket(); + ~DataRequestPacket(); void SetData(std::vector &data); const std::vector &GetData() const; - const std::vector &GetCompressedData() const; void SetCompressData(std::vector &compressData); @@ -160,7 +159,7 @@ protected: class DataAckPacket { public: DataAckPacket() {}; - virtual ~DataAckPacket() {}; + ~DataAckPacket() {}; void SetData(const uint64_t data); @@ -230,7 +229,7 @@ private: class ControlAckPacket { public: ControlAckPacket() {}; - virtual ~ControlAckPacket() {}; + ~ControlAckPacket() {}; void SetPacketHead(int recvCode, uint32_t version, int32_t controlCmd, uint32_t flag); int32_t GetRecvCode() const; uint32_t GetVersion() const; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.cpp index 84f35ce37e35470336c6d7e2e57f29813a3a5d66..22914de323ad3a27e38ada14b9b83175176f198a 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.cpp @@ -181,9 +181,11 @@ int SingleVerDataSync::TryContinueSync(SingleVerSyncTaskContext *context, const } if (context->IsQuerySync() && storage_->GetInterfaceType() == ISyncInterface::SYNC_RELATION) { Timestamp dbLastQueryTime = 0; - int errCode = metadata_->GetLastQueryTime(context->GetQuerySyncId(), context->GetDeviceId(), dbLastQueryTime); + int errCode = metadata_->GetLastQueryTime(context->GetQuerySyncId(), context->GetDeviceId(), + context->GetTargetUserId(), dbLastQueryTime); if (errCode == E_OK && dbLastQueryTime < lastQueryTime) { - errCode = metadata_->SetLastQueryTime(context->GetQuerySyncId(), context->GetDeviceId(), lastQueryTime); + errCode = metadata_->SetLastQueryTime(context->GetQuerySyncId(), context->GetDeviceId(), + context->GetTargetUserId(), lastQueryTime); } if (errCode != E_OK) { return errCode; @@ -242,6 +244,7 @@ int SingleVerDataSync::Send(SingleVerSyncTaskContext *context, const Message *me } SendConfig sendConfig; SetSendConfigParam(storage_->GetDbProperties(), context->GetDeviceId(), false, SEND_TIME_OUT, sendConfig); + sendConfig.isRetryTask = context->IsRetryTask(); int errCode = communicateHandle_->SendMessage(context->GetDeviceId(), message, sendConfig, handler); if (errCode != E_OK) { LOGE("[DataSync][Send] send message failed, errCode=%d", errCode); @@ -350,7 +353,7 @@ int SingleVerDataSync::GetUnsyncData(SingleVerSyncTaskContext *context, std::vec GetLocalDeleteSyncWaterMark(context, deletedStartMark); Timestamp lastQueryTimestamp = 0; int errCode = metadata_->GetLastQueryTime(context->GetQuerySyncId(), context->GetDeviceId(), - lastQueryTimestamp); + context->GetTargetUserId(), lastQueryTimestamp); if (errCode != E_OK) { return errCode; } @@ -473,7 +476,7 @@ int SingleVerDataSync::SaveLocalWaterMark(SyncType syncType, const SingleVerSync return E_OK; } } - errCode = metadata_->SaveLocalWaterMark(deviceId, dataTimeRange.endTime); + errCode = metadata_->SaveLocalWaterMark(deviceId, context->GetTargetUserId(), dataTimeRange.endTime); } else { bool isNeedUpdateMark = true; bool isNeedUpdateDeleteMark = true; @@ -490,7 +493,8 @@ int SingleVerDataSync::SaveLocalWaterMark(SyncType syncType, const SingleVerSync } if (isNeedUpdateMark) { LOGD("label=%s,dev=%s,endTime=%" PRIu64, label_.c_str(), STR_MASK(GetDeviceId()), dataTimeRange.endTime); - errCode = metadata_->SetSendQueryWaterMark(queryId, deviceId, dataTimeRange.endTime); + errCode = metadata_->SetSendQueryWaterMark(queryId, deviceId, context->GetTargetUserId(), + dataTimeRange.endTime); if (errCode != E_OK) { LOGE("[DataSync][SaveLocalWaterMark] save query metadata watermark failed,errCode=%d", errCode); return errCode; @@ -499,7 +503,8 @@ int SingleVerDataSync::SaveLocalWaterMark(SyncType syncType, const SingleVerSync if (isNeedUpdateDeleteMark) { LOGD("label=%s,dev=%s,deleteEndTime=%" PRIu64, label_.c_str(), STR_MASK(GetDeviceId()), dataTimeRange.deleteEndTime); - errCode = metadata_->SetSendDeleteSyncWaterMark(context->GetDeleteSyncId(), dataTimeRange.deleteEndTime); + errCode = metadata_->SetSendDeleteSyncWaterMark(context->GetDeleteSyncId(), context->GetTargetUserId(), + dataTimeRange.deleteEndTime); } } if (errCode != E_OK) { @@ -509,34 +514,36 @@ int SingleVerDataSync::SaveLocalWaterMark(SyncType syncType, const SingleVerSync } void SingleVerDataSync::GetPeerWaterMark(SyncType syncType, const std::string &queryIdentify, - const DeviceID &deviceId, WaterMark &waterMark) const + const DeviceID &deviceId, const DeviceID &userId, WaterMark &waterMark) const { if (syncType != SyncType::QUERY_SYNC_TYPE) { - metadata_->GetPeerWaterMark(deviceId, waterMark); + metadata_->GetPeerWaterMark(deviceId, userId, waterMark); return; } - metadata_->GetRecvQueryWaterMark(queryIdentify, deviceId, waterMark); + metadata_->GetRecvQueryWaterMark(queryIdentify, deviceId, userId, waterMark); } -void SingleVerDataSync::GetPeerDeleteSyncWaterMark(const DeviceID &deviceId, WaterMark &waterMark) +void SingleVerDataSync::GetPeerDeleteSyncWaterMark(const DeviceID &deviceId, const DeviceID &userId, + WaterMark &waterMark) { - metadata_->GetRecvDeleteSyncWaterMark(deviceId, waterMark); + metadata_->GetRecvDeleteSyncWaterMark(deviceId, userId, waterMark); } void SingleVerDataSync::GetLocalDeleteSyncWaterMark(const SingleVerSyncTaskContext *context, WaterMark &waterMark) const { - metadata_->GetSendDeleteSyncWaterMark(context->GetDeleteSyncId(), waterMark, context->IsAutoLiftWaterMark()); + metadata_->GetSendDeleteSyncWaterMark(context->GetDeleteSyncId(), context->GetTargetUserId(), waterMark, + context->IsAutoLiftWaterMark()); } void SingleVerDataSync::GetLocalWaterMark(SyncType syncType, const std::string &queryIdentify, const SingleVerSyncTaskContext *context, WaterMark &waterMark) const { if (syncType != SyncType::QUERY_SYNC_TYPE) { - metadata_->GetLocalWaterMark(context->GetDeviceId(), waterMark); + metadata_->GetLocalWaterMark(context->GetDeviceId(), context->GetTargetUserId(), waterMark); return; } - metadata_->GetSendQueryWaterMark(queryIdentify, context->GetDeviceId(), + metadata_->GetSendQueryWaterMark(queryIdentify, context->GetDeviceId(), context->GetTargetUserId(), waterMark, context->IsAutoLiftWaterMark()); } @@ -547,7 +554,7 @@ int SingleVerDataSync::RemoveDeviceDataHandle(SingleVerSyncTaskContext *context, std::lock_guard autoLock(removeDeviceDataLock_); if (context->GetRemoteSoftwareVersion() > SOFTWARE_VERSION_RELEASE_3_0) { uint64_t clearDeviceDataMark = 0; - metadata_->GetRemoveDataMark(context->GetDeviceId(), clearDeviceDataMark); + metadata_->GetRemoveDataMark(context->GetDeviceId(), context->GetTargetUserId(), clearDeviceDataMark); isNeedClearRemoteData = (clearDeviceDataMark == REMOVE_DEVICE_DATA_MARK); } else { const DataRequestPacket *packet = message->GetObject(); @@ -558,7 +565,8 @@ int SingleVerDataSync::RemoveDeviceDataHandle(SingleVerSyncTaskContext *context, SyncType curType = SyncOperation::GetSyncType(packet->GetMode()); WaterMark packetLocalMark = packet->GetLocalWaterMark(); WaterMark peerMark = 0; - GetPeerWaterMark(curType, context->GetQuerySyncId(), context->GetDeviceId(), peerMark); + GetPeerWaterMark(curType, context->GetQuerySyncId(), context->GetDeviceId(), context->GetTargetUserId(), + peerMark); isNeedClearRemoteData = ((packetLocalMark == 0) && (peerMark != 0)); } if (!isNeedClearRemoteData) { @@ -574,11 +582,11 @@ int SingleVerDataSync::RemoveDeviceDataHandle(SingleVerSyncTaskContext *context, } if (context->GetRemoteSoftwareVersion() == SOFTWARE_VERSION_EARLIEST) { // avoid repeat clear in ack - metadata_->SaveLocalWaterMark(context->GetDeviceId(), 0); + metadata_->SaveLocalWaterMark(context->GetDeviceId(), context->GetTargetUserId(), 0); } } if (context->GetRemoteSoftwareVersion() > SOFTWARE_VERSION_RELEASE_3_0) { - errCode = metadata_->ResetMetaDataAfterRemoveData(context->GetDeviceId()); + errCode = metadata_->ResetMetaDataAfterRemoveData(context->GetDeviceId(), context->GetTargetUserId()); if (errCode != E_OK) { (void)SendDataAck(context, message, errCode, maxSendDataTime); return errCode; @@ -595,7 +603,7 @@ int SingleVerDataSync::DealRemoveDeviceDataByAck(SingleVerSyncTaskContext *conte SyncType curType = (context->IsQuerySync()) ? SyncType::QUERY_SYNC_TYPE : SyncType::MANUAL_FULL_SYNC_TYPE; if (context->GetRemoteSoftwareVersion() > SOFTWARE_VERSION_RELEASE_3_0) { uint64_t clearDeviceDataMark = 0; - metadata_->GetRemoveDataMark(context->GetDeviceId(), clearDeviceDataMark); + metadata_->GetRemoveDataMark(context->GetDeviceId(), context->GetTargetUserId(), clearDeviceDataMark); isNeedClearRemoteData = (clearDeviceDataMark != 0); } else if (reserved.empty()) { WaterMark localMark = 0; @@ -604,7 +612,7 @@ int SingleVerDataSync::DealRemoveDeviceDataByAck(SingleVerSyncTaskContext *conte } else { WaterMark peerMark = 0; GetPeerWaterMark(curType, context->GetQuerySyncId(), - context->GetDeviceId(), peerMark); + context->GetDeviceId(), context->GetTargetUserId(), peerMark); isNeedClearRemoteData = ((reserved[ACK_PACKET_RESERVED_INDEX_LOCAL_WATER_MARK] == 0) && (peerMark != 0)); } if (!isNeedClearRemoteData) { @@ -618,7 +626,7 @@ int SingleVerDataSync::DealRemoveDeviceDataByAck(SingleVerSyncTaskContext *conte return errCode; } if (context->GetRemoteSoftwareVersion() > SOFTWARE_VERSION_RELEASE_3_0) { - errCode = metadata_->ResetMetaDataAfterRemoveData(context->GetDeviceId()); + errCode = metadata_->ResetMetaDataAfterRemoveData(context->GetDeviceId(), context->GetTargetUserId()); } return errCode; } @@ -669,7 +677,7 @@ void SingleVerDataSync::FillDataRequestPacket(DataRequestPacket *packet, SingleV (void)storage_->GetCompressionOption(needCompressOnSync, compressionRate); std::string id = context->GetQuerySyncId(); GetLocalWaterMark(curType, id, context, localMark); - GetPeerWaterMark(curType, id, context->GetDeviceId(), peerMark); + GetPeerWaterMark(curType, id, context->GetDeviceId(), context->GetTargetUserId(), peerMark); GetLocalDeleteSyncWaterMark(context, deleteMark); if (((mode != SyncModeType::RESPONSE_PULL && sendCode == E_OK)) || (mode == SyncModeType::RESPONSE_PULL && sendCode == SEND_FINISHED)) { @@ -692,7 +700,7 @@ void SingleVerDataSync::FillDataRequestPacket(DataRequestPacket *packet, SingleV packet->SetQueryId(context->GetQuerySyncId()); CompressAlgorithm curAlgo = context->ChooseCompressAlgo(); // empty compress data should not mark compress - if (!syncData.compressedEntries.empty() && needCompressOnSync && curAlgo != CompressAlgorithm::NONE) { + if (!packet->GetCompressData().empty() && needCompressOnSync && curAlgo != CompressAlgorithm::NONE) { packet->SetCompressDataMark(); packet->SetCompressAlgo(curAlgo); } @@ -802,7 +810,7 @@ int SingleVerDataSync::PullRequestStart(SingleVerSyncTaskContext *context) WaterMark localMark = 0; WaterMark deleteMark = 0; GetPeerWaterMark(syncType, context->GetQuerySyncId(), - context->GetDeviceId(), peerMark); + context->GetDeviceId(), context->GetTargetUserId(), peerMark); GetLocalWaterMark(syncType, context->GetQuerySyncId(), context, localMark); GetLocalDeleteSyncWaterMark(context, deleteMark); uint32_t version = std::min(context->GetRemoteSoftwareVersion(), SOFTWARE_VERSION_CURRENT); @@ -892,11 +900,12 @@ void SingleVerDataSync::UpdatePeerWaterMark(SyncType syncType, const std::string } int errCode = E_OK; if (syncType != SyncType::QUERY_SYNC_TYPE) { - errCode = metadata_->SavePeerWaterMark(context->GetDeviceId(), peerWatermark, true); + errCode = metadata_->SavePeerWaterMark(context->GetDeviceId(), context->GetTargetUserId(), peerWatermark, true); } else { if (peerWatermark != 0) { LOGD("label=%s,dev=%s,endTime=%" PRIu64, label_.c_str(), STR_MASK(GetDeviceId()), peerWatermark); - errCode = metadata_->SetRecvQueryWaterMark(queryId, context->GetDeviceId(), peerWatermark); + errCode = metadata_->SetRecvQueryWaterMark(queryId, context->GetDeviceId(), context->GetTargetUserId(), + peerWatermark); if (errCode != E_OK) { LOGE("[DataSync][UpdatePeerWaterMark] save query peer water mark failed,errCode=%d", errCode); } @@ -904,7 +913,8 @@ void SingleVerDataSync::UpdatePeerWaterMark(SyncType syncType, const std::string if (peerDeletedWatermark != 0) { LOGD("label=%s,dev=%s,peerDeletedTime=%" PRIu64, label_.c_str(), STR_MASK(GetDeviceId()), peerDeletedWatermark); - errCode = metadata_->SetRecvDeleteSyncWaterMark(context->GetDeleteSyncId(), peerDeletedWatermark); + errCode = metadata_->SetRecvDeleteSyncWaterMark(context->GetDeleteSyncId(), context->GetTargetUserId(), + peerDeletedWatermark); } } if (errCode != E_OK) { @@ -1293,7 +1303,7 @@ void SingleVerDataSync::GetPullEndWatermark(const SingleVerSyncTaskContext *cont if ((mode == SyncModeType::PULL) || (mode == SyncModeType::PUSH_AND_PULL)) { WaterMark endMark = packet->GetEndWaterMark(); TimeOffset offset; - metadata_->GetTimeOffset(context->GetDeviceId(), offset); + metadata_->GetTimeOffset(context->GetDeviceId(), context->GetTargetUserId(), offset); pullEndWatermark = endMark - static_cast(offset); LOGD("[DataSync][PullEndWatermark] packetEndMark=%" PRIu64 ",offset=%" PRId64 ",endWaterMark=%" PRIu64 "," "label=%s,dev=%s", endMark, offset, pullEndWatermark, label_.c_str(), STR_MASK(GetDeviceId())); @@ -1542,9 +1552,9 @@ bool SingleVerDataSync::WaterMarkErrHandle(SyncType syncType, SingleVerSyncTaskC WaterMark packetDeletedMark = packet->GetDeletedWaterMark(); WaterMark peerMark = 0; WaterMark deletedMark = 0; - GetPeerWaterMark(syncType, packet->GetQueryId(), context->GetDeviceId(), peerMark); + GetPeerWaterMark(syncType, packet->GetQueryId(), context->GetDeviceId(), context->GetTargetUserId(), peerMark); if (syncType == SyncType::QUERY_SYNC_TYPE) { - GetPeerDeleteSyncWaterMark(context->GetDeleteSyncId(), deletedMark); + GetPeerDeleteSyncWaterMark(context->GetDeleteSyncId(), context->GetTargetUserId(), deletedMark); } if (syncType != SyncType::QUERY_SYNC_TYPE && packetLocalMark > peerMark) { LOGI("[DataSync][DataRequestRecv] packetLocalMark=%" PRIu64 ",current=%" PRIu64, packetLocalMark, peerMark); @@ -1569,7 +1579,7 @@ int SingleVerDataSync::CheckSchemaStrategy(SingleVerSyncTaskContext *context, co if (packet == nullptr) { return -E_INVALID_ARGS; } - if (metadata_->IsAbilitySyncFinish(deviceId_)) { + if (metadata_->IsAbilitySyncFinish(deviceId_, context->GetTargetUserId())) { return E_OK; } auto query = packet->GetQuery(); @@ -1611,16 +1621,16 @@ void SingleVerDataSync::SetAckPacket(DataAckPacket &ackPacket, SingleVerSyncTask WaterMark localMark = 0; GetLocalWaterMark(curType, packet->GetQueryId(), context, localMark); ackPacket.SetRecvCode(recvCode); - UpdateWaterMark isUpdateWaterMark; - SyncTimeRange dataTime = SingleVerDataSyncUtils::GetRecvDataTimeRange( - SyncOperation::GetSyncType(packet->GetMode()), packet->GetData(), isUpdateWaterMark); + WaterMark mark = 0; + GetPeerWaterMark(curType, packet->GetQueryId(), context->GetDeviceId(), context->GetTargetUserId(), mark); + WaterMark deletedPeerMark = 0; + GetPeerDeleteSyncWaterMark(context->GetDeleteSyncId(), context->GetTargetUserId(), deletedPeerMark); + SyncTimeRange dataTime = {.endTime = mark, .deleteEndTime = deletedPeerMark}; bool isPacketWaterLower = false; // send ack packet if ((recvCode == E_OK) && (maxSendDataTime != 0)) { ackPacket.SetData(maxSendDataTime + 1); // + 1 to next start } else if (recvCode != WATER_MARK_INVALID) { - WaterMark mark = 0; - GetPeerWaterMark(curType, packet->GetQueryId(), context->GetDeviceId(), mark); if (recvCode == -E_NEED_ABILITY_SYNC && packet->GetLocalWaterMark() < mark) { LOGI("[DataSync][SetAckPacket] packetLocalMark=%" PRIu64 ",lockMark=%" PRIu64, packet->GetLocalWaterMark(), mark); @@ -1641,8 +1651,6 @@ void SingleVerDataSync::SetAckPacket(DataAckPacket &ackPacket, SingleVerSyncTask } // while recv is not E_OK, data is peerMark, reserve[2] is deletedPeerMark value if (curType == SyncType::QUERY_SYNC_TYPE && recvCode != WATER_MARK_INVALID) { - WaterMark deletedPeerMark; - GetPeerDeleteSyncWaterMark(context->GetDeleteSyncId(), deletedPeerMark); if (recvCode == -E_NEED_ABILITY_SYNC && packet->GetDeletedWaterMark() < deletedPeerMark) { LOGI("[DataSync][SetAckPacket] packetDeletedMark=%" PRIu64 ",deletedMark=%" PRIu64, packet->GetDeletedWaterMark(), deletedPeerMark); @@ -1654,6 +1662,7 @@ void SingleVerDataSync::SetAckPacket(DataAckPacket &ackPacket, SingleVerSyncTask } ackPacket.SetReserved(reserved); ackPacket.SetVersion(version); + UpdateWaterMark isUpdateWaterMark = {true, true}; if (isPacketWaterLower) { UpdatePeerWaterMarkInner(*packet, dataTime, isUpdateWaterMark, context); } @@ -1725,7 +1734,7 @@ int SingleVerDataSync::RemoveDeviceDataIfNeed(SingleVerSyncTaskContext *context) } uint64_t clearRemoteDataMark = 0; std::lock_guard autoLock(removeDeviceDataLock_); - metadata_->GetRemoveDataMark(context->GetDeviceId(), clearRemoteDataMark); + metadata_->GetRemoveDataMark(context->GetDeviceId(), context->GetTargetUserId(), clearRemoteDataMark); if (clearRemoteDataMark == 0) { return E_OK; } @@ -1738,7 +1747,7 @@ int SingleVerDataSync::RemoveDeviceDataIfNeed(SingleVerSyncTaskContext *context) } } if (clearRemoteDataMark == REMOVE_DEVICE_DATA_MARK) { - errCode = metadata_->ResetMetaDataAfterRemoveData(context->GetDeviceId()); + errCode = metadata_->ResetMetaDataAfterRemoveData(context->GetDeviceId(), context->GetTargetUserId()); if (errCode != E_OK) { LOGE("set %s removeDataWaterMark to false failed,errCode=%d", STR_MASK(GetDeviceId()), errCode); return errCode; @@ -1758,7 +1767,7 @@ void SingleVerDataSync::FillRequestReSendPacket(SingleVerSyncTaskContext *contex SingleVerDataSyncUtils::SetDataRequestCommonInfo(*context, *storage_, *packet, metadata_); SyncType curType = (context->IsQuerySync()) ? SyncType::QUERY_SYNC_TYPE : SyncType::MANUAL_FULL_SYNC_TYPE; WaterMark peerMark = 0; - GetPeerWaterMark(curType, context->GetQuerySyncId(), context->GetDeviceId(), + GetPeerWaterMark(curType, context->GetQuerySyncId(), context->GetDeviceId(), context->GetTargetUserId(), peerMark); uint32_t version = std::min(context->GetRemoteSoftwareVersion(), SOFTWARE_VERSION_CURRENT); // transfer reSend mode, RESPONSE_PULL transfer to push or query push @@ -1795,7 +1804,7 @@ void SingleVerDataSync::FillRequestReSendPacket(SingleVerSyncTaskContext *contex uint8_t compressionRate = DBConstant::DEFAULT_COMPTRESS_RATE; (void)storage_->GetCompressionOption(needCompressOnSync, compressionRate); CompressAlgorithm curAlgo = context->ChooseCompressAlgo(); - if (needCompressOnSync && curAlgo != CompressAlgorithm::NONE) { + if (!packet->GetCompressData().empty() && needCompressOnSync && curAlgo != CompressAlgorithm::NONE) { packet->SetCompressDataMark(); packet->SetCompressAlgo(curAlgo); } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.h index 1e07eb1a9955de6cc38aef76929300f7172b0fad..ec1279f25bd60e4f1cb8eef5ff2c7a17870351cc 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.h @@ -174,9 +174,9 @@ protected: SyncTimeRange dataTimeRange, bool isCheckBeforUpdate = false) const; void GetPeerWaterMark(SyncType syncType, const std::string &queryIdentify, const DeviceID &deviceId, - WaterMark &waterMark) const; + const DeviceID &userId, WaterMark &waterMark) const; - void GetPeerDeleteSyncWaterMark(const DeviceID &deviceId, WaterMark &waterMark); + void GetPeerDeleteSyncWaterMark(const DeviceID &deviceId, const DeviceID &userId, WaterMark &waterMark); int RemoveDeviceDataHandle(SingleVerSyncTaskContext *context, const Message *message, WaterMark maxSendDataTime); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.cpp index 986d841b9a50a813aac5e548e40ea3ec0d4c1f80..73e33e729c02645f1a97e83590c10a52b43a7168 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.cpp @@ -494,7 +494,7 @@ int SingleVerDataSyncUtils::RunPermissionCheckInner(const SingleVerSyncTaskConte } int errCode = RuntimeContext::GetInstance()->RunPermissionCheck(param, flag); if (errCode != E_OK) { - LOGE("[DataSync][RunPermissionCheck] check failed flag=%" PRIu8 ",Label=%s,dev=%s", flag, label.c_str(), + LOGE("[DataSync][RunPermissionCheck] check failed flag=%" PRIu8 ",dev=%s", flag, STR_MASK(context->GetDeviceId())); } return errCode; @@ -536,7 +536,7 @@ void SingleVerDataSyncUtils::SetDataRequestCommonInfo(const SingleVerSyncTaskCon const SyncGenericInterface &storage, DataRequestPacket &packet, std::shared_ptr &metadata) { packet.SetSenderTimeOffset(metadata->GetLocalTimeOffset()); - packet.SetSystemTimeOffset(metadata->GetSystemTimeOffset(context.GetDeviceId())); + packet.SetSystemTimeOffset(metadata->GetSystemTimeOffset(context.GetDeviceId(), context.GetTargetUserId())); if (context.GetRemoteSoftwareVersion() < SOFTWARE_VERSION_RELEASE_9_0) { return; } @@ -564,7 +564,7 @@ int SingleVerDataSyncUtils::SchemaVersionMatchCheck(const SingleVerSyncTaskConte if (context.GetRemoteSoftwareVersion() < SOFTWARE_VERSION_RELEASE_9_0) { return E_OK; } - auto remoteSchemaVersion = metadata->GetRemoteSchemaVersion(context.GetDeviceId()); + auto remoteSchemaVersion = metadata->GetRemoteSchemaVersion(context.GetDeviceId(), context.GetTargetUserId()); if (remoteSchemaVersion != packet.GetSchemaVersion()) { LOGE("[DataSync] remote schema version misMatch, need ability sync again, packet %" PRIu64 " cache %" PRIu64, packet.GetSchemaVersion(), remoteSchemaVersion); @@ -578,7 +578,7 @@ int SingleVerDataSyncUtils::GetUnsyncTotal(const SingleVerSyncTaskContext *conte { SyncTimeRange waterRange; WaterMark startMark = context->GetInitWaterMark(); - if ((waterRange.endTime == 0) || (startMark > waterRange.endTime)) { + if (waterRange.endTime == 0 || startMark > waterRange.endTime) { return E_OK; } @@ -590,8 +590,8 @@ int SingleVerDataSyncUtils::GetUnsyncTotal(const SingleVerSyncTaskContext *conte int SingleVerDataSyncUtils::GetUnsyncTotal(const SingleVerSyncTaskContext *context, const SyncGenericInterface *storage, SyncTimeRange &waterMarkInfo, uint32_t &total) { - int errCode; - SyncType curType = (context->IsQuerySync()) ? SyncType::QUERY_SYNC_TYPE : SyncType::MANUAL_FULL_SYNC_TYPE; + int errCode = E_OK; + SyncType curType = (context->IsQuerySync() ? SyncType::QUERY_SYNC_TYPE : SyncType::MANUAL_FULL_SYNC_TYPE); if (curType != SyncType::QUERY_SYNC_TYPE) { errCode = storage->GetUnSyncTotal(waterMarkInfo.beginTime, waterMarkInfo.endTime, total); } else { @@ -599,7 +599,7 @@ int SingleVerDataSyncUtils::GetUnsyncTotal(const SingleVerSyncTaskContext *conte errCode = storage->GetUnSyncTotal(queryObj, waterMarkInfo, total); } if (errCode != E_OK) { - LOGE("[DataSync][GetUnsyncTotal] Get unsync data num failed,errCode=%d", errCode); + LOGE("[DataSync][GetUnsyncTotal] Get unsync data num failed, errCode=%d", errCode); } return errCode; } @@ -632,7 +632,7 @@ void SingleVerDataSyncUtils::UpdateSyncProcess(SingleVerSyncTaskContext *context void SingleVerDataSyncUtils::CacheInitWaterMark(SingleVerSyncTaskContext *context, SingleVerDataSync *dataSync) { - SyncType curType = (context->IsQuerySync()) ? SyncType::QUERY_SYNC_TYPE : SyncType::MANUAL_FULL_SYNC_TYPE; + SyncType curType = (context->IsQuerySync() ? SyncType::QUERY_SYNC_TYPE : SyncType::MANUAL_FULL_SYNC_TYPE); WaterMark startMark = 0; dataSync->GetLocalWaterMark(curType, context->GetQuerySyncId(), context, startMark); context->SetInitWaterMark(startMark); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_kv_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_kv_syncer.cpp index 31ac7c4b1ceaee17fc1e62a38fe67b4cf80d7df3..55070d2d853b451d86aca7e2ae9dd1a988006459 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_kv_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_kv_syncer.cpp @@ -167,7 +167,7 @@ void SingleVerKVSyncer::RemoteDataChanged(const std::string &device) static_cast(syncEngine_)->PutUnfinishedSubQueries(device, syncQueries); } -int SingleVerKVSyncer::SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, +int SingleVerKVSyncer::SyncConditionCheck(const SyncParam ¶m, const ISyncEngine *engine, ISyncInterface *storage) const { if (!param.isQuerySync) { @@ -203,7 +203,7 @@ void SingleVerKVSyncer::TriggerSubscribe(const std::string &device, const QueryS int retCode = RuntimeContext::GetInstance()->ScheduleTask([this, device, query] { std::vector devices; devices.push_back(device); - SyncParma param; + SyncParam param; param.devices = devices; param.mode = SyncModeType::AUTO_SUBSCRIBE_QUERY; param.onComplete = nullptr; @@ -266,7 +266,8 @@ void SingleVerKVSyncer::TriggerSubQuerySync(const std::vector &devi std::string queryId = query.GetIdentify(); WaterMark queryWaterMark = 0; uint64_t lastTimestamp = metadata->GetQueryLastTimestamp(device, queryId); - errCode = metadata->GetSendQueryWaterMark(queryId, device, queryWaterMark, false); + // Auto sync does not support multi-user sync, The userId param is set to "". + errCode = metadata->GetSendQueryWaterMark(queryId, device, "", queryWaterMark, false); if (errCode != E_OK) { LOGE("[Syncer] get queryId=%s,dev=%s watermark failed", STR_MASK(queryId), STR_MASK(device)); continue; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_kv_syncer.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_kv_syncer.h index f2f6ca27dd1ada7350bc36d22e8120f0826d19ec..9c8c435f68455d76493ebd149bbf2d45b4cceee4 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_kv_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_kv_syncer.h @@ -38,7 +38,7 @@ public: SyncerBasicInfo DumpSyncerBasicInfo() override; protected: - int SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, ISyncInterface *storage) const override; + int SyncConditionCheck(const SyncParam ¶m, const ISyncEngine *engine, ISyncInterface *storage) const override; // Init the Sync engine int InitSyncEngine(ISyncInterface *syncInterface) override; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_relational_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_relational_syncer.cpp index e392bb4595b4e6c65aad38a1d50c576a4b992057..402cef510069bda30c7fba21a56cc9136c06af1b 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_relational_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_relational_syncer.cpp @@ -30,7 +30,7 @@ int SingleVerRelationalSyncer::Initialize(ISyncInterface *syncInterface, bool is RegisterSchemaChangedCallback(callback); } -int SingleVerRelationalSyncer::Sync(const SyncParma ¶m, uint64_t connectionId) +int SingleVerRelationalSyncer::Sync(const SyncParam ¶m, uint64_t connectionId) { int errCode = QuerySyncPreCheck(param); if (errCode != E_OK) { @@ -39,7 +39,7 @@ int SingleVerRelationalSyncer::Sync(const SyncParma ¶m, uint64_t connectionI return GenericSyncer::Sync(param, connectionId); } -int SingleVerRelationalSyncer::PrepareSync(const SyncParma ¶m, uint32_t syncId, uint64_t connectionId) +int SingleVerRelationalSyncer::PrepareSync(const SyncParam ¶m, uint32_t syncId, uint64_t connectionId) { if (syncInterface_ == nullptr) { LOGE("[SingleVerRelationalSyncer] [PrepareSync] syncInterface_ is nullptr."); @@ -71,10 +71,10 @@ int SingleVerRelationalSyncer::PrepareSync(const SyncParma ¶m, uint32_t sync return E_OK; } -int SingleVerRelationalSyncer::GenerateEachSyncTask(const SyncParma ¶m, uint32_t syncId, +int SingleVerRelationalSyncer::GenerateEachSyncTask(const SyncParam ¶m, uint32_t syncId, const std::vector &tablesQuery, uint64_t connectionId, std::set &subSyncIdSet) { - SyncParma subParam = param; + SyncParam subParam = param; subParam.isQuerySync = true; int errCode = E_OK; for (const QuerySyncObject &table : tablesQuery) { @@ -103,7 +103,7 @@ int SingleVerRelationalSyncer::GenerateEachSyncTask(const SyncParma ¶m, uint } void SingleVerRelationalSyncer::DoOnSubSyncComplete(const uint32_t subSyncId, const uint32_t syncId, - const SyncParma ¶m, const std::map &devicesMap) + const SyncParam ¶m, const std::map &devicesMap) { bool allFinish = true; { @@ -133,7 +133,7 @@ void SingleVerRelationalSyncer::DoRollBack(std::set &subSyncIdSet) } } -void SingleVerRelationalSyncer::DoOnComplete(const SyncParma ¶m, uint32_t syncId) +void SingleVerRelationalSyncer::DoOnComplete(const SyncParam ¶m, uint32_t syncId) { if (!param.relationOnComplete) { return; @@ -180,7 +180,7 @@ void SingleVerRelationalSyncer::SchemaChangeCallback() } } -int SingleVerRelationalSyncer::SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, +int SingleVerRelationalSyncer::SyncConditionCheck(const SyncParam ¶m, const ISyncEngine *engine, ISyncInterface *storage) const { if (!param.isQuerySync) { @@ -217,7 +217,7 @@ int SingleVerRelationalSyncer::SyncConditionCheck(const SyncParma ¶m, const return E_OK; } -int SingleVerRelationalSyncer::QuerySyncPreCheck(const SyncParma ¶m) const +int SingleVerRelationalSyncer::QuerySyncPreCheck(const SyncParam ¶m) const { if (!param.isQuerySync) { return E_OK; @@ -237,7 +237,7 @@ int SingleVerRelationalSyncer::QuerySyncPreCheck(const SyncParma ¶m) const return E_OK; } -std::vector SingleVerRelationalSyncer::GetQuerySyncObject(const SyncParma ¶m) +std::vector SingleVerRelationalSyncer::GetQuerySyncObject(const SyncParam ¶m) { std::vector res; auto tables = param.syncQuery.GetRelationTableNames(); @@ -250,5 +250,22 @@ std::vector SingleVerRelationalSyncer::GetQuerySyncObject(const } return res; } + +int32_t SingleVerRelationalSyncer::GetTaskCount() +{ + int32_t count = GenericSyncer::GetTaskCount(); + ISyncEngine *syncEngine = nullptr; + { + std::lock_guard lock(syncerLock_); + if (syncEngine_ == nullptr) { + return count; + } + syncEngine = syncEngine_; + RefObject::IncObjRef(syncEngine); + } + count += syncEngine->GetRemoteQueryTaskCount(); + RefObject::DecObjRef(syncEngine); + return count; +} } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_relational_syncer.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_relational_syncer.h index df637af8c1b37e541a5ca65f2f025b84ee80da20..9b0fc38d7239640f0139dee6b91d88bdcde80a20 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_relational_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_relational_syncer.h @@ -24,35 +24,36 @@ public: int Initialize(ISyncInterface *syncInterface, bool isNeedActive) override; - // Sync function. use SyncParma to reduce parameter. - int Sync(const SyncParma ¶m, uint64_t connectionId) override; + // Sync function. use SyncParam to reduce parameter. + int Sync(const SyncParam ¶m, uint64_t connectionId) override; void EnableAutoSync(bool enable) override; void LocalDataChanged(int notifyEvent) override; + int32_t GetTaskCount() override; protected: - int PrepareSync(const SyncParma ¶m, uint32_t syncId, uint64_t connectionId) override; + int PrepareSync(const SyncParam ¶m, uint32_t syncId, uint64_t connectionId) override; - int SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, ISyncInterface *storage) const override; + int SyncConditionCheck(const SyncParam ¶m, const ISyncEngine *engine, ISyncInterface *storage) const override; private: - int GenerateEachSyncTask(const SyncParma ¶m, uint32_t syncId, + int GenerateEachSyncTask(const SyncParam ¶m, uint32_t syncId, const std::vector &tablesQuery, uint64_t connectionId, std::set &subSyncIdSet); void DoRollBack(std::set &subSyncIdSet); - void DoOnComplete(const SyncParma ¶m, uint32_t syncId); + void DoOnComplete(const SyncParam ¶m, uint32_t syncId); void DoOnSubSyncComplete(const uint32_t subSyncId, const uint32_t syncId, - const SyncParma ¶m, const std::map &devicesMap); + const SyncParam ¶m, const std::map &devicesMap); void SchemaChangeCallback(); - int QuerySyncPreCheck(const SyncParma ¶m) const; + int QuerySyncPreCheck(const SyncParam ¶m) const; - static std::vector GetQuerySyncObject(const SyncParma ¶m); + static std::vector GetQuerySyncObject(const SyncParam ¶m); mutable std::mutex syncMapLock_; std::map> fullSyncIdMap_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_engine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_engine.cpp index c5254c5af0444997fa669fa9f42130d523133930..a27883b79eea86834525cb092dd15ad327dd1f2c 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_engine.cpp @@ -63,7 +63,7 @@ void SingleVerSyncEngine::EnableClearRemoteStaleData(bool enable) int SingleVerSyncEngine::StartAutoSubscribeTimer(const ISyncInterface &syncInterface) { if (syncInterface.IsSupportSubscribe() == -E_NOT_SUPPORT) { - LOGI("[StartAutoSubscribeTimer] no need to start subscribe timer"); + LOGI("[StartAutoSubscribeTimer] no need start"); return E_OK; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.cpp index 205ca3da104c0163660ce6198d849bd3469f22c7..c5122a6c10935395b7e3ca9b72e0c1ba7f895e3a 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.cpp @@ -49,6 +49,7 @@ namespace { {State::TIME_SYNC, Event::TIME_SYNC_FINISHED_EVENT, State::ABILITY_SYNC}, {State::TIME_SYNC, Event::TIME_OUT_EVENT, State::SYNC_TIME_OUT}, {State::TIME_SYNC, Event::INNER_ERR_EVENT, State::INNER_ERR}, + {State::TIME_SYNC, Event::NEED_RESYNC_EVENT, State::TIME_SYNC}, // In ABILITY_SYNC state, compare version num and schema {State::ABILITY_SYNC, Event::VERSION_NOT_SUPPOR_EVENT, State::INNER_ERR}, @@ -56,6 +57,7 @@ namespace { {State::ABILITY_SYNC, Event::TIME_OUT_EVENT, State::SYNC_TIME_OUT}, {State::ABILITY_SYNC, Event::INNER_ERR_EVENT, State::INNER_ERR}, {State::ABILITY_SYNC, Event::CONTROL_CMD_EVENT, State::SYNC_CONTROL_CMD}, + {State::ABILITY_SYNC, Event::NEED_RESYNC_EVENT, State::ABILITY_SYNC}, // In START_INITIACTIVE_DATA_SYNC state, send a sync request, and send first packt of data sync {State::START_INITIACTIVE_DATA_SYNC, Event::NEED_ABILITY_SYNC_EVENT, State::ABILITY_SYNC}, @@ -64,6 +66,7 @@ namespace { {State::START_INITIACTIVE_DATA_SYNC, Event::SEND_FINISHED_EVENT, State::START_PASSIVE_DATA_SYNC}, {State::START_INITIACTIVE_DATA_SYNC, Event::RE_SEND_DATA_EVENT, State::START_INITIACTIVE_DATA_SYNC}, {State::START_INITIACTIVE_DATA_SYNC, Event::NEED_TIME_SYNC_EVENT, State::TIME_SYNC}, + {State::START_INITIACTIVE_DATA_SYNC, Event::NEED_RESYNC_EVENT, State::START_INITIACTIVE_DATA_SYNC}, // In START_PASSIVE_DATA_SYNC state, do response pull request, and send first packt of data sync {State::START_PASSIVE_DATA_SYNC, Event::SEND_FINISHED_EVENT, State::START_PASSIVE_DATA_SYNC}, @@ -73,6 +76,7 @@ namespace { {State::START_PASSIVE_DATA_SYNC, Event::NEED_ABILITY_SYNC_EVENT, State::ABILITY_SYNC}, {State::START_PASSIVE_DATA_SYNC, Event::RE_SEND_DATA_EVENT, State::START_PASSIVE_DATA_SYNC}, {State::START_PASSIVE_DATA_SYNC, Event::NEED_TIME_SYNC_EVENT, State::TIME_SYNC}, + {State::START_PASSIVE_DATA_SYNC, Event::NEED_RESYNC_EVENT, State::START_PASSIVE_DATA_SYNC}, // In WAIT_FOR_RECEIVE_DATA_FINISH, {State::WAIT_FOR_RECEIVE_DATA_FINISH, Event::RECV_FINISHED_EVENT, State::SYNC_TASK_FINISHED}, @@ -80,11 +84,13 @@ namespace { {State::WAIT_FOR_RECEIVE_DATA_FINISH, Event::TIME_OUT_EVENT, State::SYNC_TIME_OUT}, {State::WAIT_FOR_RECEIVE_DATA_FINISH, Event::INNER_ERR_EVENT, State::INNER_ERR}, {State::WAIT_FOR_RECEIVE_DATA_FINISH, Event::NEED_ABILITY_SYNC_EVENT, State::ABILITY_SYNC}, + {State::WAIT_FOR_RECEIVE_DATA_FINISH, Event::NEED_RESYNC_EVENT, State::START_PASSIVE_DATA_SYNC}, {State::SYNC_CONTROL_CMD, Event::SEND_FINISHED_EVENT, State::SYNC_TASK_FINISHED}, {State::SYNC_CONTROL_CMD, Event::TIME_OUT_EVENT, State::SYNC_TIME_OUT}, {State::SYNC_CONTROL_CMD, Event::INNER_ERR_EVENT, State::INNER_ERR}, {State::SYNC_CONTROL_CMD, Event::NEED_ABILITY_SYNC_EVENT, State::ABILITY_SYNC}, + {State::SYNC_CONTROL_CMD, Event::NEED_RESYNC_EVENT, State::SYNC_CONTROL_CMD}, // In SYNC_TASK_FINISHED, {State::SYNC_TASK_FINISHED, Event::ALL_TASK_FINISHED_EVENT, State::IDLE}, @@ -138,7 +144,8 @@ int SingleVerSyncStateMachine::Initialize(ISyncTaskContext *context, ISyncInterf return -E_OUT_OF_MEMORY; } - errCode = timeSync_->Initialize(communicator, metaData, syncInterface, context->GetDeviceId()); + errCode = timeSync_->Initialize(communicator, metaData, syncInterface, context->GetDeviceId(), + context->GetTargetUserId()); if (errCode != E_OK) { goto ERROR_OUT; } @@ -184,6 +191,10 @@ int SingleVerSyncStateMachine::ReceiveMessageCallback(Message *inMsg) LOGE("[StateMachine] message pre check failed"); return errCode; } + if (context_->IsNeedRetrySync(inMsg->GetErrorNo(), inMsg->GetMessageType())) { + SwitchStateAndStep(NEED_RESYNC_EVENT); + return E_OK; + } switch (inMsg->GetMessageId()) { case TIME_SYNC_MESSAGE: errCode = TimeMarkSyncRecv(inMsg); @@ -482,7 +493,7 @@ Event SingleVerSyncStateMachine::DoTimeSync() const SyncTaskContext::CommErrHandlerFunc(ret, context, requestSessionId, isDirectEnd); }; } - int errCode = timeSync_->SyncStart(handler, context_->GetRequestSessionId()); + int errCode = timeSync_->SyncStart(handler, context_->GetRequestSessionId(), context_->IsRetryTask()); if (errCode == E_OK) { return Event::WAIT_ACK_EVENT; } @@ -537,6 +548,7 @@ Event SingleVerSyncStateMachine::GetEventAfterTimeSync(int mode) const Event SingleVerSyncStateMachine::DoSyncTaskFinished() { StopWatchDog(); + context_->ResetResyncTimes(); if (dataSync_ == nullptr || communicator_ == nullptr || syncContext_ == nullptr) { LOGE("[SingleVerSyncStateMachine] [DoSyncTaskFinished] dataSync_ or communicator_ or syncContext_ is nullptr."); return TransformErrCodeToEvent(-E_OUT_OF_MEMORY); @@ -882,7 +894,8 @@ int SingleVerSyncStateMachine::GetSyncOperationStatus(int errCode) const { -E_DENIED_SQL, SyncOperation::OP_DENIED_SQL }, { -E_REMOTE_OVER_SIZE, SyncOperation::OP_MAX_LIMITS }, { -E_INVALID_PASSWD_OR_CORRUPTED_DB, SyncOperation::OP_NOTADB_OR_CORRUPTED }, - { -E_DISTRIBUTED_SCHEMA_NOT_FOUND, SyncOperation::OP_SCHEMA_INCOMPATIBLE } + { -E_DISTRIBUTED_SCHEMA_NOT_FOUND, SyncOperation::OP_SCHEMA_INCOMPATIBLE }, + { -E_FEEDBACK_DB_CLOSING, SyncOperation::OP_DB_CLOSING }, }; const auto &result = std::find_if(std::begin(stateNodes), std::end(stateNodes), [errCode](const auto &node) { return node.errCode == errCode; @@ -1244,15 +1257,15 @@ void SingleVerSyncStateMachine::ControlAckRecvErrCodeHandle(int errCode) } } -void SingleVerSyncStateMachine::GetLocalWaterMark(const DeviceID &deviceId, uint64_t &outValue) +void SingleVerSyncStateMachine::GetLocalWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue) { - metadata_->GetLocalWaterMark(deviceId, outValue); + metadata_->GetLocalWaterMark(deviceId, userId, outValue); } -int SingleVerSyncStateMachine::GetSendQueryWaterMark(const std::string &queryId, const DeviceID &deviceId, - bool isAutoLift, uint64_t &outValue) +int SingleVerSyncStateMachine::GetSendQueryWaterMark(const std::string &queryId, const DeviceID &deviceId, + const DeviceID &userId, bool isAutoLift, uint64_t &outValue) { - return metadata_->GetSendQueryWaterMark(queryId, deviceId, outValue, isAutoLift); + return metadata_->GetSendQueryWaterMark(queryId, deviceId, userId, outValue, isAutoLift); } void SingleVerSyncStateMachine::ResponsePullError(int errCode, bool ignoreInnerErr) diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.h index f026d9761a3efad1ed70d55a1f1e98a4361021f3..23d6c9f1fdd4b40187e87b36dded2314801d2824 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.h @@ -67,6 +67,7 @@ public: RE_SEND_DATA_EVENT, CONTROL_CMD_EVENT, NEED_TIME_SYNC_EVENT, + NEED_RESYNC_EVENT, ANY_EVENT }; SingleVerSyncStateMachine(); @@ -92,10 +93,10 @@ public: bool IsNeedTriggerQueryAutoSync(Message *inMsg, QuerySyncObject &query) override; - void GetLocalWaterMark(const DeviceID &deviceId, uint64_t &outValue); + void GetLocalWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue); - int GetSendQueryWaterMark(const std::string &queryId, const DeviceID &deviceId, bool isAutoLift, - uint64_t &outValue); + int GetSendQueryWaterMark(const std::string &queryId, const DeviceID &deviceId, const DeviceID &userId, + bool isAutoLift, uint64_t &outValue); void InnerErrorAbort(uint32_t sessionId) override; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.cpp index 9ef6398943108adea8fd05e11afa50fa96629e2a..3279bf1671c1896dfbf4c2bfce81c094b24c5f90 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.cpp @@ -39,10 +39,10 @@ SingleVerSyncTaskContext::~SingleVerSyncTaskContext() subManager_ = nullptr; } -int SingleVerSyncTaskContext::Initialize(const std::string &deviceId, ISyncInterface *syncInterface, +int SingleVerSyncTaskContext::Initialize(const DeviceSyncTarget &target, ISyncInterface *syncInterface, const std::shared_ptr &metadata, ICommunicator *communicator) { - if (deviceId.empty() || syncInterface == nullptr || metadata == nullptr || + if (target.device.empty() || syncInterface == nullptr || metadata == nullptr || communicator == nullptr) { LOGE("[SingleVerSyncTaskContext] [Initialize] parameter is invalid."); return -E_INVALID_ARGS; @@ -52,7 +52,8 @@ int SingleVerSyncTaskContext::Initialize(const std::string &deviceId, ISyncInter LOGE("[SingleVerSyncTaskContext] [Initialize] stateMachine_ is nullptr."); return -E_OUT_OF_MEMORY; } - deviceId_ = deviceId; + deviceId_ = target.device; + targetUserId_ = target.userId; std::vector dbIdentifier = syncInterface->GetIdentifier(); dbIdentifier.resize(3); // only show 3 bytes syncActionName_ = DBDfxAdapter::SYNC_ACTION + "_" + @@ -518,14 +519,14 @@ int SingleVerSyncTaskContext::GetCorrectedSendWaterMarkForCurrentTask(const Sync if (operation != nullptr && operation->IsQuerySync()) { LOGD("Is QuerySync"); int errCode = static_cast(stateMachine_)->GetSendQueryWaterMark( - operation->GetQueryId(), deviceId_, + operation->GetQueryId(), deviceId_, targetUserId_, lastFullSyncTaskStatus_ == SyncOperation::OP_FINISHED_ALL, waterMark); if (errCode != E_OK) { return errCode; } } else { LOGD("Not QuerySync"); - static_cast(stateMachine_)->GetLocalWaterMark(deviceId_, waterMark); + static_cast(stateMachine_)->GetLocalWaterMark(deviceId_, targetUserId_, waterMark); } return E_OK; } @@ -644,4 +645,30 @@ int32_t SingleVerSyncTaskContext::GetResponseTaskCount() } return taskCount; } + +bool SingleVerSyncTaskContext::IsNeedRetrySync(int errNo, uint16_t messageType) +{ + if (errNo != E_FEEDBACK_DB_CLOSING || messageType != TYPE_RESPONSE) { + return false; + } + uint32_t cur = ++resyncTimes_; + LOGI("[IsNeedRetrySync]%u", cur); + return cur <= MANUAL_RETRY_TIMES; +} + +void SingleVerSyncTaskContext::ResetResyncTimes() +{ + resyncTimes_ = 0; +} + +bool SingleVerSyncTaskContext::IsRetryTask() const +{ + SyncOperation *operation = GetAndIncSyncOperation(); + if (operation == nullptr) { + return true; + } + bool isRetryTask = operation->IsRetryTask(); + RefObject::DecObjRef(operation); + return isRetryTask; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.h index 0cb30f5165a523a0af228ddd1e6367eba263104a..cf4b89c5822b38ef73c25fe218ddf67a458f4751 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.h @@ -40,7 +40,7 @@ public: DISABLE_COPY_ASSIGN_MOVE(SingleVerSyncTaskContext); // Init SingleVerSyncTaskContext - int Initialize(const std::string &deviceId, ISyncInterface *syncInterface, + int Initialize(const DeviceSyncTarget &target, ISyncInterface *syncInterface, const std::shared_ptr &metadata, ICommunicator *communicator) override; // Add a sync task target with the operation to the queue @@ -147,6 +147,10 @@ public: int32_t GetResponseTaskCount() override; + bool IsNeedRetrySync(int errNo, uint16_t messageType); + void ResetResyncTimes(); + + bool IsRetryTask() const override; protected: ~SingleVerSyncTaskContext() override; void CopyTargetData(const ISyncTarget *target, const TaskParam &taskParam) override; @@ -167,7 +171,7 @@ private: ContinueToken token_; WaterMark endMark_; - volatile uint32_t responseSessionId_ = 0; + std::atomic responseSessionId_ = 0; bool needClearRemoteStaleData_; mutable std::mutex securityOptionMutex_; @@ -191,6 +195,8 @@ private: // Initial Water Mark when the sync task launched. WaterMark initWaterMark_ = 0; WaterMark initDeletedMark_ = 0; + + std::atomic resyncTimes_ = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_syncer.cpp index 322f2dca6ba8f76176759e699476546f4d65b382..b7e63c9063283343d2b810770a0355c593e42d56 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_syncer.cpp @@ -66,7 +66,7 @@ int SingleVerSyncer::EraseDeviceWaterMark(const std::string &deviceId, bool isNe storage = syncInterface_; storage->IncRefCount(); } - int errCode = metadata->EraseDeviceWaterMark(deviceId, isNeedHash, tableName); + int errCode = metadata->EraseDeviceWaterMark(deviceId, "", isNeedHash, tableName); storage->DecRefCount(); return errCode; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.cpp index 5d4a60e550188b6b9f8608ec0e03498a5bb23587..6cf1d6147766f4f5b44a5afbc4d04436588aa986 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.cpp @@ -101,13 +101,13 @@ int SyncEngine::Initialize(ISyncInterface *syncInterface, const std::shared_ptr< } metadata_ = metadata; isActive_ = true; - LOGI("[SyncEngine] Engine [%s] init ok", label_.c_str()); + LOGI("[SyncEngine] Engine [%.3s] init ok", label_.c_str()); return E_OK; } int SyncEngine::Close() { - LOGI("[SyncEngine] SyncEngine [%s] close enter!", label_.c_str()); + LOGI("[SyncEngine] [%.3s] close enter!", label_.c_str()); isActive_ = false; UnRegCommunicatorsCallback(); StopAutoSubscribeTimer(); @@ -152,7 +152,7 @@ int SyncEngine::Close() executor = nullptr; } ClearInnerResource(); - LOGI("[SyncEngine] SyncEngine [%s] closed!", label_.c_str()); + LOGI("[SyncEngine] [%.3s] closed!", label_.c_str()); return E_OK; } @@ -296,12 +296,8 @@ int SyncEngine::InitComunicator(const ISyncInterface *syncInterface) return errCode; } - errCode = communicator_->RegOnMessageCallback( - [this](const std::string &targetDev, Message *inMsg) { MessageReciveCallback(targetDev, inMsg); }, []() {}); + errCode = RegCallbackOnInitComunicator(communicatorAggregator, syncInterface); if (errCode != E_OK) { - LOGE("[SyncEngine] SyncRequestCallback register failed! err = %d", errCode); - communicatorAggregator->ReleaseCommunicator(communicator_, GetUserId(syncInterface)); - communicator_ = nullptr; return errCode; } { @@ -322,14 +318,23 @@ int SyncEngine::InitComunicator(const ISyncInterface *syncInterface) int SyncEngine::AddSyncOperForContext(const std::string &deviceId, SyncOperation *operation) { + if (syncInterface_ == nullptr) { + LOGE("[SyncEngine][AddSyncOperForContext] sync interface has not initialized"); + return -E_INVALID_DB; + } + bool isSyncDualTupleMode = syncInterface_->GetDbProperties().GetBoolProp(DBProperties::SYNC_DUAL_TUPLE_MODE, false); + std::string targetUserId = DBConstant::DEFAULT_USER; + if (isSyncDualTupleMode) { + targetUserId = GetTargetUserId(deviceId); + } int errCode = E_OK; ISyncTaskContext *context = nullptr; { std::lock_guard lock(contextMapLock_); - context = FindSyncTaskContext(deviceId); + context = FindSyncTaskContext({deviceId, targetUserId}); if (context == nullptr) { if (!IsKilled()) { - context = GetSyncTaskContext(deviceId, errCode); + context = GetSyncTaskContext({deviceId, targetUserId}, errCode); } if (context == nullptr) { return errCode; @@ -417,7 +422,7 @@ int SyncEngine::DealMsgUtilQueueEmpty() // it will deal with the first message in queue, we should increase object reference counts and sure that resources // could be prevented from destroying by other threads. do { - ISyncTaskContext *nextContext = GetContextForMsg(inMsg->GetTarget(), errCode); + ISyncTaskContext *nextContext = GetContextForMsg({inMsg->GetTarget(), inMsg->GetSenderUserId()}, errCode); if (errCode != E_OK) { break; } @@ -434,12 +439,12 @@ int SyncEngine::DealMsgUtilQueueEmpty() return errCode; } -ISyncTaskContext *SyncEngine::GetContextForMsg(const std::string &targetDev, int &errCode) +ISyncTaskContext *SyncEngine::GetContextForMsg(const DeviceSyncTarget &target, int &errCode) { ISyncTaskContext *context = nullptr; { std::lock_guard lock(contextMapLock_); - context = FindSyncTaskContext(targetDev); + context = FindSyncTaskContext(target); if (context != nullptr) { // LCOV_EXCL_BR_LINE if (context->IsKilled()) { errCode = -E_OBJ_IS_KILLED; @@ -450,7 +455,7 @@ ISyncTaskContext *SyncEngine::GetContextForMsg(const std::string &targetDev, int errCode = -E_OBJ_IS_KILLED; return nullptr; } - context = GetSyncTaskContext(targetDev, errCode); + context = GetSyncTaskContext(target, errCode); if (context == nullptr) { return nullptr; } @@ -490,7 +495,7 @@ int SyncEngine::ScheduleDealMsg(ISyncTaskContext *context, Message *inMsg) return errCode; } -void SyncEngine::MessageReciveCallback(const std::string &targetDev, Message *inMsg) +int SyncEngine::MessageReciveCallback(const std::string &targetDev, Message *inMsg) { IncExecTaskCount(); int errCode = MessageReciveCallbackInner(targetDev, inMsg); @@ -502,6 +507,7 @@ void SyncEngine::MessageReciveCallback(const std::string &targetDev, Message *in DecExecTaskCount(); LOGE("[SyncEngine] MessageReciveCallback failed!"); } + return errCode; } int SyncEngine::MessageReciveCallbackInner(const std::string &targetDev, Message *inMsg) @@ -514,6 +520,9 @@ int SyncEngine::MessageReciveCallbackInner(const std::string &targetDev, Message LOGE("[SyncEngine] engine is closing, ignore msg"); return -E_BUSY; } + if (inMsg->GetMessageType() == TYPE_REQUEST && ExchangeClosePending(false)) { + return -E_FEEDBACK_DB_CLOSING; + } if (inMsg->GetMessageId() == REMOTE_EXECUTE_MESSAGE) { return HandleRemoteExecutorMsg(targetDev, inMsg); } @@ -535,7 +544,7 @@ int SyncEngine::MessageReciveCallbackInner(const std::string &targetDev, Message return -E_BUSY; } - if (execTaskCount_ > MAX_EXEC_NUM) { + if (GetExecTaskCount() > MAX_EXEC_NUM) { PutMsgIntoQueue(targetDev, inMsg, msgSize); // task dont exec here DecExecTaskCount(); @@ -544,7 +553,7 @@ int SyncEngine::MessageReciveCallbackInner(const std::string &targetDev, Message } int errCode = E_OK; - ISyncTaskContext *nextContext = GetContextForMsg(targetDev, errCode); + ISyncTaskContext *nextContext = GetContextForMsg({targetDev, inMsg->GetSenderUserId()}, errCode); if (errCode != E_OK) { return errCode; } @@ -598,9 +607,16 @@ int SyncEngine::GetMsgSize(const Message *inMsg) const } } -ISyncTaskContext *SyncEngine::FindSyncTaskContext(const std::string &deviceId) +ISyncTaskContext *SyncEngine::FindSyncTaskContext(const DeviceSyncTarget &target) { - auto iter = syncTaskContextMap_.find(deviceId); + if (target.userId == DBConstant::DEFAULT_USER) { + for (auto &[key, value] : syncTaskContextMap_) { + if (key.device == target.device) { + return value; + } + } + } + auto iter = syncTaskContextMap_.find(target); if (iter != syncTaskContextMap_.end()) { ISyncTaskContext *context = iter->second; return context; @@ -608,24 +624,30 @@ ISyncTaskContext *SyncEngine::FindSyncTaskContext(const std::string &deviceId) return nullptr; } -ISyncTaskContext *SyncEngine::GetSyncTaskContextAndInc(const std::string &deviceId) +std::vector SyncEngine::GetSyncTaskContextAndInc(const std::string &deviceId) { - ISyncTaskContext *context = nullptr; + std::vector contexts; std::lock_guard lock(contextMapLock_); - context = FindSyncTaskContext(deviceId); - if (context == nullptr) { - LOGI("[SyncEngine] dev=%s, context is null, no need to clear sync operation", STR_MASK(deviceId)); - return nullptr; - } - if (context->IsKilled()) { // LCOV_EXCL_BR_LINE - LOGI("[SyncEngine] context is killing"); - return nullptr; + for (const auto &iter : syncTaskContextMap_) { + if (iter.first.device != deviceId) { + continue; + } + if (iter.second == nullptr) { + LOGI("[SyncEngine] dev=%s, user=%s, context is null, no need to clear sync operation", STR_MASK(deviceId), + iter.first.userId.c_str()); + continue; + } + if (iter.second->IsKilled()) { // LCOV_EXCL_BR_LINE + LOGI("[SyncEngine] context is killing"); + continue; + } + RefObject::IncObjRef(iter.second); + contexts.push_back(iter.second); } - RefObject::IncObjRef(context); - return context; + return contexts; } -ISyncTaskContext *SyncEngine::GetSyncTaskContext(const std::string &deviceId, int &errCode) +ISyncTaskContext *SyncEngine::GetSyncTaskContext(const DeviceSyncTarget &target, int &errCode) { auto storage = GetAndIncSyncInterface(); if (storage == nullptr) { @@ -639,19 +661,19 @@ ISyncTaskContext *SyncEngine::GetSyncTaskContext(const std::string &deviceId, in LOGE("[SyncEngine] SyncTaskContext alloc failed, may be no memory available!"); return nullptr; } - errCode = context->Initialize(deviceId, storage, metadata_, communicatorProxy_); + errCode = context->Initialize(target, storage, metadata_, communicatorProxy_); if (errCode != E_OK) { - LOGE("[SyncEngine] context init failed err %d, dev %s", errCode, STR_MASK(deviceId)); + LOGE("[SyncEngine] context init failed err %d, dev %s", errCode, STR_MASK(target.device)); RefObject::DecObjRef(context); storage->DecRefCount(); context = nullptr; return nullptr; } - syncTaskContextMap_.insert(std::pair(deviceId, context)); + syncTaskContextMap_.insert(std::pair(target, context)); // IncRef for SyncEngine to make sure SyncEngine is valid when context access RefObject::IncObjRef(this); - context->OnLastRef([this, deviceId, storage]() { - LOGD("[SyncEngine] SyncTaskContext for id %s finalized", STR_MASK(deviceId)); + context->OnLastRef([this, target, storage]() { + LOGD("[SyncEngine] SyncTaskContext for id %s finalized", STR_MASK(target.device)); RefObject::DecObjRef(this); storage->DecRefCount(); }); @@ -859,8 +881,6 @@ void SyncEngine::OfflineHandleByDevice(const std::string &deviceId, ISyncInterfa DBInfo dbInfo; static_cast(storage)->GetDBInfo(dbInfo); RuntimeContext::GetInstance()->RemoveRemoteSubscribe(dbInfo, deviceId); - // get context and Inc context if context is not nullptr - ISyncTaskContext *context = GetSyncTaskContextAndInc(deviceId); { std::lock_guard lock(communicatorProxyLock_); if (communicatorProxy_ == nullptr) { @@ -868,25 +888,30 @@ void SyncEngine::OfflineHandleByDevice(const std::string &deviceId, ISyncInterfa } if (communicatorProxy_->IsDeviceOnline(deviceId)) { // LCOV_EXCL_BR_LINE LOGI("[SyncEngine] target dev=%s is online, no need to clear task.", STR_MASK(deviceId)); - RefObject::DecObjRef(context); return; } } // means device is offline, clear local subscribe - subManager_->ClearLocalSubscribeQuery(deviceId); - // clear sync task - if (context != nullptr) { - context->ClearAllSyncTask(); - RefObject::DecObjRef(context); + // get context and Inc context if context is not nullptr + std::vector contexts = GetSyncTaskContextAndInc(deviceId); + for (const auto &context : contexts) { + subManager_->ClearLocalSubscribeQuery(deviceId); + // clear sync task + if (context != nullptr) { + context->ClearAllSyncTask(); + RefObject::DecObjRef(context); + } } } void SyncEngine::ClearAllSyncTaskByDevice(const std::string &deviceId) { - ISyncTaskContext *context = GetSyncTaskContextAndInc(deviceId); - if (context != nullptr) { - context->ClearAllSyncTask(); - RefObject::DecObjRef(context); + std::vector contexts = GetSyncTaskContextAndInc(deviceId); + for (const auto &context : contexts) { + if (context != nullptr) { + context->ClearAllSyncTask(); + RefObject::DecObjRef(context); + } } } @@ -932,7 +957,9 @@ ICommunicator *SyncEngine::AllocCommunicator(const std::string &identifier, int } errCode = communicator->RegOnMessageCallback( - [this](const std::string &targetDev, Message *inMsg) { MessageReciveCallback(targetDev, inMsg); }, []() {}); + [this](const std::string &targetDev, Message *inMsg) { + return MessageReciveCallback(targetDev, inMsg); + }, []() {}); if (errCode != E_OK) { LOGE("[SyncEngine] SyncRequestCallback register failed in SetEqualIdentifier! err = %d", errCode); communicatorAggregator->ReleaseCommunicator(communicator, userId); @@ -1095,6 +1122,12 @@ void SyncEngine::DecExecTaskCount() execTaskCv_.notify_all(); } +uint32_t SyncEngine::GetExecTaskCount() +{ + std::lock_guard autoLock(execTaskCountLock_); + return execTaskCount_; +} + void SyncEngine::Dump(int fd) { { @@ -1376,4 +1409,70 @@ uint32_t SyncEngine::GetTimeout(const std::string &dev) RefObject::DecObjRef(communicator); return timeout; } + +std::string SyncEngine::GetTargetUserId(const std::string &dev) +{ + std::string targetUserId; + ICommunicator *communicator = nullptr; + { + std::lock_guard autoLock(communicatorProxyLock_); + if (communicatorProxy_ == nullptr) { + LOGW("[SyncEngine] Communicator is null when get target user"); + return targetUserId; + } + communicator = communicatorProxy_; + RefObject::IncObjRef(communicator); + } + DBProperties properties = syncInterface_->GetDbProperties(); + ExtendInfo extendInfo; + extendInfo.appId = properties.GetStringProp(DBProperties::APP_ID, ""); + extendInfo.userId = properties.GetStringProp(DBProperties::USER_ID, ""); + extendInfo.storeId = properties.GetStringProp(DBProperties::STORE_ID, ""); + extendInfo.dstTarget = dev; + extendInfo.subUserId = properties.GetStringProp(DBProperties::SUB_USER, ""); + targetUserId = communicator->GetTargetUserId(extendInfo); + RefObject::DecObjRef(communicator); + return targetUserId; +} + +int SyncEngine::RegCallbackOnInitComunicator(ICommunicatorAggregator *communicatorAggregator, + const ISyncInterface *syncInterface) +{ + int errCode = communicator_->RegOnMessageCallback( + [this](const std::string &targetDev, Message *inMsg) { + return MessageReciveCallback(targetDev, inMsg); + }, []() {}); + if (errCode != E_OK) { + LOGE("[SyncEngine] SyncRequestCallback register failed! err = %d", errCode); + communicatorAggregator->ReleaseCommunicator(communicator_, GetUserId(syncInterface)); + communicator_ = nullptr; + return errCode; + } + return E_OK; +} + +int32_t SyncEngine::GetRemoteQueryTaskCount() +{ + auto executor = GetAndIncRemoteExector(); + if (executor == nullptr) { + LOGW("[SyncEngine] RemoteExecutor is null when get remote query task count"); + RefObject::DecObjRef(executor); + return 0; + } + auto count = executor->GetTaskCount(); + RefObject::DecObjRef(executor); + return count; +} + +bool SyncEngine::ExchangeClosePending(bool expected) +{ + if (communicator_ == nullptr) { + return false; + } + auto communicator = communicator_; + RefObject::IncObjRef(communicator); + int res = communicator->ExchangeClosePending(expected); + RefObject::DecObjRef(communicator); + return res; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.h index 78c93192234325c4bf43ef4c157617084054d2a3..0f7ab3ed937f51df178cb11b4112b72555a30353 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.h @@ -137,13 +137,17 @@ public: void TimeChange() override; int32_t GetResponseTaskCount() override; + + int32_t GetRemoteQueryTaskCount() override; + + bool ExchangeClosePending(bool expected) override; protected: // Create a context virtual ISyncTaskContext *CreateSyncTaskContext(const ISyncInterface &syncInterface) = 0; // Find SyncTaskContext from the map - ISyncTaskContext *FindSyncTaskContext(const std::string &deviceId); - ISyncTaskContext *GetSyncTaskContextAndInc(const std::string &deviceId); + ISyncTaskContext *FindSyncTaskContext(const DeviceSyncTarget &target); + std::vector GetSyncTaskContextAndInc(const std::string &deviceId); void GetQueryAutoSyncParam(const std::string &device, const QuerySyncObject &query, InternalSyncParma &outParam); void GetSubscribeSyncParam(const std::string &device, const QuerySyncObject &query, InternalSyncParma &outParam); @@ -151,12 +155,12 @@ protected: ISyncInterface *GetAndIncSyncInterface(); void SetSyncInterface(ISyncInterface *syncInterface); - ISyncTaskContext *GetSyncTaskContext(const std::string &deviceId, int &errCode); + ISyncTaskContext *GetSyncTaskContext(const DeviceSyncTarget &target, int &errCode); std::mutex storageMutex_; ISyncInterface *syncInterface_; // Used to store all send sync task infos (such as pull sync response, and push sync request) - std::map syncTaskContextMap_; + std::map syncTaskContextMap_; std::mutex contextMapLock_; std::shared_ptr subManager_; std::function queryAutoSyncCallback_; @@ -181,7 +185,7 @@ private: void ScheduleTaskOut(ISyncTaskContext *context, const ICommunicator *communicator); // wrapper of MessageReciveCallbackTask - void MessageReciveCallback(const std::string &targetDev, Message *inMsg); + int MessageReciveCallback(const std::string &targetDev, Message *inMsg); // Sync Request Callback int MessageReciveCallbackInner(const std::string &targetDev, Message *inMsg); @@ -201,7 +205,7 @@ private: // Handle message in order. int ScheduleDealMsg(ISyncTaskContext *context, Message *inMsg); - ISyncTaskContext *GetContextForMsg(const std::string &targetDev, int &errCode); + ISyncTaskContext *GetContextForMsg(const DeviceSyncTarget &target, int &errCode); ICommunicator *AllocCommunicator(const std::string &identifier, int &errCode, std::string userId = ""); @@ -217,6 +221,8 @@ private: void DecExecTaskCount(); + uint32_t GetExecTaskCount(); + RemoteExecutor *GetAndIncRemoteExector(); void SetRemoteExector(RemoteExecutor *executor); @@ -237,6 +243,10 @@ private: uint32_t GetTimeout(const std::string &dev); + int RegCallbackOnInitComunicator(ICommunicatorAggregator *communicatorAggregator, + const ISyncInterface *syncInterface); + + std::string GetTargetUserId(const std::string &dev); ICommunicator *communicator_; DeviceManager *deviceManager_; std::function onRemoteDataChanged_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.cpp index 4fd93de50f11932d034806f7f0b20e29309c2b8e..1fd82b4faa21b7e1926008aff69d667c01f484fe 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.cpp @@ -285,6 +285,16 @@ std::string SyncTaskContext::GetDeviceId() const return deviceId_; } +std::string SyncTaskContext::GetTargetUserId() const +{ + return targetUserId_; +} + +void SyncTaskContext::SetTargetUserId(const std::string &userId) +{ + targetUserId_ = userId; +} + void SyncTaskContext::SetTaskExecStatus(int status) { taskExecStatus_ = status; @@ -493,9 +503,14 @@ void SyncTaskContext::CommErrHandlerFunc(int errCode, ISyncTaskContext *context, RefObject::IncObjRef(context); } - static_cast(context)->CommErrHandlerFuncInner(errCode, static_cast(sessionId), - isDirectEnd); - RefObject::DecObjRef(context); + int ret = RuntimeContext::GetInstance()->ScheduleTask([context, errCode, sessionId, isDirectEnd]() { + static_cast(context)->CommErrHandlerFuncInner(errCode, static_cast(sessionId), + isDirectEnd); + RefObject::DecObjRef(context); + }); + if (ret != E_OK) { + RefObject::DecObjRef(context); + } } void SyncTaskContext::SetRemoteSoftwareVersion(uint32_t version) diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.h index 42d53e7dc59ca8896b35112575acf5d3ef9ac365..7885b91fea90381835af6fa5a06d49b23309213a 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.h @@ -78,6 +78,10 @@ public: // Get the current task deviceId. std::string GetDeviceId() const override; + std::string GetTargetUserId() const override; + + void SetTargetUserId(const std::string &userId) override; + // Set the sync task queue exec status void SetTaskExecStatus(int status) override; @@ -260,6 +264,7 @@ protected: volatile int status_; volatile int taskExecStatus_; std::string deviceId_; + std::string targetUserId_; std::string syncActionName_; ISyncInterface *syncInterface_; ICommunicator *communicator_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/syncer_proxy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/syncer_proxy.cpp index 0c8d6fd62d8667c73bb587ea71c7705faba6fe55..cabd4bf1056de0ec162be615f542062172e62f02 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/syncer_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/syncer_proxy.cpp @@ -64,7 +64,7 @@ int SyncerProxy::Sync(const std::vector &devices, int mode, return syncer_->Sync(devices, mode, onComplete, onFinalize, wait); } -int SyncerProxy::Sync(const SyncParma &parma, uint64_t connectionId) +int SyncerProxy::Sync(const SyncParam &parma, uint64_t connectionId) { if (syncer_ == nullptr) { return -E_NOT_INIT; @@ -289,4 +289,12 @@ int32_t SyncerProxy::GetTaskCount() } return syncer_->GetTaskCount(); } + +bool SyncerProxy::ExchangeClosePending(bool expected) +{ + if (syncer_ == nullptr) { + return false; + } + return syncer_->ExchangeClosePending(expected); +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.cpp index 43bd032e7728cc84c82d985706c9e38592efd800..ae0e841ca2c408fbb5322846de0e343434006e97 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.cpp @@ -179,7 +179,7 @@ int TimeSync::RegisterTransformFunc() } int TimeSync::Initialize(ICommunicator *communicator, const std::shared_ptr &metadata, - const ISyncInterface *storage, const DeviceID &deviceId) + const ISyncInterface *storage, const DeviceID &deviceId, const DeviceID &userId) { if ((communicator == nullptr) || (storage == nullptr) || (metadata == nullptr)) { return -E_INVALID_ARGS; @@ -191,6 +191,7 @@ int TimeSync::Initialize(ICommunicator *communicator, const std::shared_ptr(); int errCode = timeHelper_->Initialize(storage, metadata_); @@ -205,7 +206,7 @@ int TimeSync::Initialize(ICommunicator *communicator, const std::shared_ptrIsTimeSyncFinish(deviceId_); + isSynced_ = metadata_->IsTimeSyncFinish(deviceId_, userId_); return errCode; } @@ -225,7 +226,7 @@ void TimeSync::Finalize() LOGD("[TimeSync] Finalized!"); } -int TimeSync::SyncStart(const CommErrHandler &handler, uint32_t sessionId) +int TimeSync::SyncStart(const CommErrHandler &handler, uint32_t sessionId, bool isRetryTask) { isOnline_ = true; TimeSyncPacket packet; @@ -250,7 +251,7 @@ int TimeSync::SyncStart(const CommErrHandler &handler, uint32_t sessionId) message = nullptr; return errCode; } - errCode = SendMessageWithSendEnd(message, handler); + errCode = SendMessageWithSendEnd(message, handler, isRetryTask); if (errCode != E_OK) { delete message; message = nullptr; @@ -369,10 +370,11 @@ int TimeSync::DeSerialization(const uint8_t *buffer, uint32_t length, Message *i int TimeSync::AckRecv(const Message *message, uint32_t targetSessionId) { // only check when sessionId is not 0, because old version timesync sessionId is 0. - if (message != nullptr && message->GetSessionId() != 0 && - message->GetErrorNo() == E_FEEDBACK_COMMUNICATOR_NOT_FOUND && message->GetSessionId() == targetSessionId) { - LOGE("[AbilitySync][AckMsgCheck] Remote db is closed"); - return -E_FEEDBACK_COMMUNICATOR_NOT_FOUND; + if (message != nullptr && message->GetSessionId() != 0 && message->GetSessionId() == targetSessionId) { + if (message->GetErrorNo() == E_FEEDBACK_COMMUNICATOR_NOT_FOUND) { + LOGE("[AbilitySync][AckMsgCheck] Remote db is closed"); + return -E_FEEDBACK_COMMUNICATOR_NOT_FOUND; + } } if (!IsPacketValid(message, TYPE_RESPONSE)) { return -E_INVALID_ARGS; @@ -446,9 +448,9 @@ int TimeSync::RequestRecv(const Message *message) return errCode; } -int TimeSync::SaveTimeOffset(const DeviceID &deviceID, TimeOffset timeOffset) +int TimeSync::SaveTimeOffset(const DeviceID &deviceID, const DeviceID &userId, TimeOffset timeOffset) { - return metadata_->SaveTimeOffset(deviceID, timeOffset); + return metadata_->SaveTimeOffset(deviceID, userId, timeOffset); } std::pair TimeSync::CalculateTimeOffset(const TimeSyncPacket &timeSyncInfo) @@ -456,9 +458,9 @@ std::pair TimeSync::CalculateTimeOffset(const TimeSyncPa TimeOffset roundTrip = static_cast((timeSyncInfo.GetSourceTimeEnd() - timeSyncInfo.GetSourceTimeBegin()) - (timeSyncInfo.GetTargetTimeEnd() - timeSyncInfo.GetTargetTimeBegin())); TimeOffset offset1 = static_cast(timeSyncInfo.GetTargetTimeBegin() - - timeSyncInfo.GetSourceTimeBegin() - (roundTrip / TRIP_DIV_HALF)); - TimeOffset offset2 = static_cast(timeSyncInfo.GetTargetTimeEnd() + (roundTrip / TRIP_DIV_HALF) - - timeSyncInfo.GetSourceTimeEnd()); + timeSyncInfo.GetSourceTimeBegin()) - (roundTrip / TRIP_DIV_HALF); + TimeOffset offset2 = static_cast(timeSyncInfo.GetTargetTimeEnd() - timeSyncInfo.GetSourceTimeEnd()) + + (roundTrip / TRIP_DIV_HALF); TimeOffset offset = (offset1 / TRIP_DIV_HALF) + (offset2 / TRIP_DIV_HALF); LOGD("TimeSync::CalculateTimeOffset roundTrip= %" PRId64 ", offset1 = %" PRId64 ", offset2 = %" PRId64 ", offset = %" PRId64, roundTrip, offset1, offset2, offset); @@ -481,10 +483,12 @@ bool TimeSync::IsPacketValid(const Message *inMsg, uint16_t messageType) return true; } -int TimeSync::SendPacket(const DeviceID &deviceId, const Message *message, const CommErrHandler &handler) +int TimeSync::SendPacket(const DeviceID &deviceId, const Message *message, const CommErrHandler &handler, + bool isRetryTask) { SendConfig conf; timeHelper_->SetSendConfig(deviceId, false, SEND_TIME_OUT, conf); + conf.isRetryTask = isRetryTask; int errCode = communicateHandle_->SendMessage(deviceId, message, conf, handler); if (errCode != E_OK) { LOGE("[TimeSync] SendPacket failed, err %d", errCode); @@ -546,7 +550,7 @@ int TimeSync::GetTimeOffset(TimeOffset &outOffset, uint32_t timeout, uint32_t se return -E_BUSY; } retryTime_ = 0; - metadata_->GetTimeOffset(deviceId_, outOffset); + metadata_->GetTimeOffset(deviceId_, userId_, outOffset); return E_OK; } @@ -617,7 +621,7 @@ bool TimeSync::IsClosed() const return closed_ ; } -int TimeSync::SendMessageWithSendEnd(const Message *message, const CommErrHandler &handler) +int TimeSync::SendMessageWithSendEnd(const Message *message, const CommErrHandler &handler, bool isRetryTask) { std::shared_ptr timeSyncPtr = shared_from_this(); auto sessionId = message->GetSessionId(); @@ -634,7 +638,7 @@ int TimeSync::SendMessageWithSendEnd(const Message *message, const CommErrHandle if (handler != nullptr) { handler(errCode, isDirectEnd); } - }); + }, isRetryTask); } Timestamp TimeSync::GetSourceBeginTime(Timestamp packetBeginTime, uint32_t sessionId) @@ -692,16 +696,16 @@ void TimeSync::ReTimeSyncIfNeed(const TimeSyncPacket &ackPacket) } // reset time change by time sync - int errCode = metadata_->SetTimeChangeMark(deviceId_, false); + int errCode = metadata_->SetTimeChangeMark(deviceId_, userId_, false); if (errCode != E_OK) { - LOGW("[TimeSync] Mark dev %.3s no time change failed %d", deviceId_.c_str(), errCode); + LOGW("[TimeSync] Mark dev %.3s_%.3s no time change failed %d", deviceId_.c_str(), userId_.c_str(), errCode); } } bool TimeSync::CheckReTimeSyncIfNeedWithLowVersion(TimeOffset timeOffsetIgnoreRtt) { TimeOffset metadataTimeOffset; - metadata_->GetTimeOffset(deviceId_, metadataTimeOffset); + metadata_->GetTimeOffset(deviceId_, userId_, metadataTimeOffset); return (std::abs(metadataTimeOffset) >= INT64_MAX / 2) || // 2 is half of INT64_MAX (std::abs(metadataTimeOffset - timeOffsetIgnoreRtt) > MAX_TIME_OFFSET_NOISE); } @@ -719,10 +723,11 @@ int TimeSync::SaveOffsetWithAck(const TimeSyncPacket &ackPacket) // calculate timeoffset of two devices auto [offset, rtt] = CalculateTimeOffset(ackPacket); TimeOffset rawOffset = CalculateRawTimeOffset(ackPacket, offset); - LOGD("TimeSync::AckRecv, dev = %s{private}, sEnd = %" PRIu64 ", tEnd = %" PRIu64 ", sBegin = %" PRIu64 + LOGD("TimeSync::AckRecv, dev = %s{private}_%s{private}, sEnd = %" PRIu64 ", tEnd = %" PRIu64 ", sBegin = %" PRIu64 ", tBegin = %" PRIu64 ", offset = %" PRId64 ", rawOffset = %" PRId64 ", requestLocalOffset = %" PRId64 ", responseLocalOffset = %" PRId64, deviceId_.c_str(), + userId_.c_str(), ackPacket.GetSourceTimeEnd(), ackPacket.GetTargetTimeEnd(), ackPacket.GetSourceTimeBegin(), @@ -733,11 +738,11 @@ int TimeSync::SaveOffsetWithAck(const TimeSyncPacket &ackPacket) ackPacket.GetResponseLocalOffset()); // save timeoffset into metadata, maybe a block action - int errCode = SaveTimeOffset(deviceId_, offset); + int errCode = SaveTimeOffset(deviceId_, userId_, offset); if (errCode != E_OK) { return errCode; } - errCode = metadata_->SetSystemTimeOffset(deviceId_, rawOffset); + errCode = metadata_->SetSystemTimeOffset(deviceId_, userId_, rawOffset); if (errCode != E_OK) { return errCode; } @@ -793,7 +798,7 @@ void TimeSync::SetTimeSyncFinishIfNeed() if (errCode != E_OK) { return; } - int64_t systemTimeOffset = metadata_->GetSystemTimeOffset(deviceId_); + int64_t systemTimeOffset = metadata_->GetSystemTimeOffset(deviceId_, userId_); LOGD("[TimeSync] Check db offset %" PRId64 " cache offset %" PRId64, systemTimeOffset, info.systemTimeOffset); if (!CheckSkipTimeSync(info) || (IsNeedSync() && std::abs(systemTimeOffset - info.systemTimeOffset) >= MAX_TIME_OFFSET_NOISE)) { @@ -804,7 +809,7 @@ void TimeSync::SetTimeSyncFinishIfNeed() SetTimeSyncFinishInner(true); } if (systemTimeOffset != info.systemTimeOffset) { - errCode = metadata_->SetSystemTimeOffset(deviceId_, info.systemTimeOffset); + errCode = metadata_->SetSystemTimeOffset(deviceId_, userId_, info.systemTimeOffset); if (errCode != E_OK) { return; } @@ -825,7 +830,7 @@ int TimeSync::GenerateTimeOffsetIfNeed(TimeOffset systemOffset, TimeOffset sende } auto [errCode, info] = RuntimeContext::GetInstance()->GetDeviceTimeInfo(deviceId_); bool syncFinish = !IsNeedSync(); - bool timeChange = metadata_->IsTimeChange(deviceId_); + bool timeChange = metadata_->IsTimeChange(deviceId_, userId_); // avoid local time change but remote record time sync finish // should return re time sync, after receive time sync request, reset time change mark // we think offset is ok when local time sync to remote @@ -842,11 +847,11 @@ int TimeSync::GenerateTimeOffsetIfNeed(TimeOffset systemOffset, TimeOffset sende // Sender's deltaTime = Sender's systemOffset - requestLocalOffset + responseLocalOffset // Receiver's deltaTime = -Sender's deltaTime = -Sender's systemOffset + requestLocalOffset - responseLocalOffset TimeOffset offset = -systemOffset + senderLocalOffset - metadata_->GetLocalTimeOffset(); - errCode = metadata_->SetSystemTimeOffset(deviceId_, -systemOffset); + errCode = metadata_->SetSystemTimeOffset(deviceId_, userId_, -systemOffset); if (errCode != E_OK) { return errCode; } - errCode = metadata_->SaveTimeOffset(deviceId_, offset); + errCode = metadata_->SaveTimeOffset(deviceId_, userId_, offset); if (errCode != E_OK) { return errCode; } @@ -863,10 +868,10 @@ void TimeSync::SetTimeSyncFinishInner(bool finish) if (IsRemoteLowVersion(SOFTWARE_VERSION_RELEASE_9_0)) { return; } - int errCode = metadata_->SetTimeSyncFinishMark(deviceId_, finish); + int errCode = metadata_->SetTimeSyncFinishMark(deviceId_, userId_, finish); if (errCode != E_OK) { - LOGW("[TimeSync] Set %.3s time sync finish %d mark failed %d", deviceId_.c_str(), static_cast(finish), - errCode); + LOGW("[TimeSync] Set %.3s_%.3s time sync finish %d mark failed %d", deviceId_.c_str(), userId_.c_str(), + static_cast(finish), errCode); } } } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.h index b8ec799191ed1a955b9c370aa7339d94cb96a7aa..01ca61566b20bb92c828e8057cdc8352918ca3f6 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.h @@ -82,9 +82,10 @@ public: static int DeSerialization(const uint8_t *buffer, uint32_t length, Message *inMsg); // register to communicator int Initialize(ICommunicator *communicator, const std::shared_ptr &metadata, - const ISyncInterface *storage, const DeviceID &deviceId); + const ISyncInterface *storage, const DeviceID &deviceId, const DeviceID &userId); - virtual int SyncStart(const CommErrHandler &handler = nullptr, uint32_t sessionId = 0); // send timesync request + // send timesync request + virtual int SyncStart(const CommErrHandler &handler = nullptr, uint32_t sessionId = 0, bool isRetryTask = true); int AckRecv(const Message *message, uint32_t targetSessionId = 0); @@ -121,9 +122,10 @@ protected: void Finalize(); - int SaveTimeOffset(const DeviceID &deviceID, TimeOffset timeOffset); + int SaveTimeOffset(const DeviceID &deviceID, const DeviceID &userId, TimeOffset timeOffset); - int SendPacket(const DeviceID &deviceId, const Message *message, const CommErrHandler &handler = nullptr); + int SendPacket(const DeviceID &deviceId, const Message *message, const CommErrHandler &handler = nullptr, + bool isRetryTask = true); int TimeSyncDriver(TimerId timerId); @@ -131,7 +133,7 @@ protected: bool IsClosed() const; - int SendMessageWithSendEnd(const Message *message, const CommErrHandler &handler); + int SendMessageWithSendEnd(const Message *message, const CommErrHandler &handler, bool isRetryTask); Timestamp GetSourceBeginTime(Timestamp packetBeginTime, uint32_t sessionId); @@ -153,6 +155,7 @@ protected: std::shared_ptr metadata_; std::unique_ptr timeHelper_; DeviceID deviceId_; + DeviceID userId_; int retryTime_; TimerId driverTimerId_; TimerAction driverCallback_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.cpp index 0e68d5fe6499066881d229d358c764e2d9d7d190..c8719e1d961dbb298fa08a8e371e47707edd09cc 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.cpp @@ -32,7 +32,24 @@ SyncOperation::SyncOperation(uint32_t syncId, const std::vector &de semaphore_(nullptr), query_(QuerySyncObject()), isQuerySync_(false), - isAutoSubscribe_(false) + isAutoSubscribe_(false), + isRetry_(true) +{ +} + +SyncOperation::SyncOperation(uint32_t syncId, const ISyncer::SyncParam ¶m) + : devices_(param.devices), + syncId_(syncId), + mode_(param.mode), + userCallback_(param.onComplete), + isBlockSync_(param.wait), + isAutoSync_(false), + isFinished_(false), + semaphore_(nullptr), + query_(QuerySyncObject()), + isQuerySync_(false), + isAutoSubscribe_(false), + isRetry_(param.isRetry) { } @@ -445,6 +462,7 @@ DBStatus SyncOperation::DBStatusTrans(int operationStatus) { static_cast(OP_USER_CHANGED), USER_CHANGED }, { static_cast(OP_DENIED_SQL), NO_PERMISSION }, { static_cast(OP_NOTADB_OR_CORRUPTED), INVALID_PASSWD_OR_CORRUPTED_DB }, + { static_cast(OP_DB_CLOSING), OK }, { static_cast(OP_FAILED), DB_ERROR }, }; const auto &result = std::find_if(std::begin(syncOperationStatusNodes), std::end(syncOperationStatusNodes), @@ -486,5 +504,10 @@ std::string SyncOperation::GetFinishDetailMsg(const std::map & msg.pop_back(); return msg; } + +bool SyncOperation::IsRetryTask() const +{ + return isRetry_; +} DEFINE_OBJECT_TAG_FACILITIES(SyncOperation) } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.h b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.h index f3f00a5de05f5d244700da390863874e7d074004..3b68919dbe748b4f609196f7fee2832cd9791f69 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.h @@ -23,6 +23,7 @@ #include #include "ikvdb_sync_interface.h" +#include "isyncer.h" #include "notification_chain.h" #include "query_sync_object.h" #include "ref_object.h" @@ -57,6 +58,7 @@ public: OP_USER_CHANGED, OP_DENIED_SQL, OP_NOTADB_OR_CORRUPTED, + OP_DB_CLOSING, }; using UserCallback = std::function)>; @@ -66,6 +68,8 @@ public: SyncOperation(uint32_t syncId, const std::vector &devices, int mode, const UserCallback &userCallback, bool isBlockSync); + SyncOperation(uint32_t syncId, const ISyncer::SyncParam ¶m); + DISABLE_COPY_ASSIGN_MOVE(SyncOperation); // Init the status for callback @@ -119,6 +123,8 @@ public: // Check if All devices sync finished. bool CheckIsAllFinished() const; + bool IsRetryTask() const; + // For query sync void SetQuery(const QuerySyncObject &query); void GetQuery(QuerySyncObject &targetObject) const; @@ -200,6 +206,8 @@ private: volatile bool isAutoSubscribe_; + volatile bool isRetry_; + // record identifier used to call ScheduleQueuedTask in SyncOperation::Finished std::string identifier_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/time_helper.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/time_helper.cpp index f82841dcc5064ed6c07b4849a50a32b1872a59d7..1984d1f2730329e74300d5956fa7746619b579bb 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/time_helper.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/time_helper.cpp @@ -20,33 +20,8 @@ #include "platform_specific.h" namespace DistributedDB { -std::mutex TimeHelper::systemTimeLock_; -Timestamp TimeHelper::lastSystemTimeUs_ = 0; -Timestamp TimeHelper::currentIncCount_ = 0; std::atomic TimeHelper::lastMonotonicTime_ = 0; -Timestamp TimeHelper::GetSysCurrentTime() -{ - uint64_t curTime = 0; - std::lock_guard lock(systemTimeLock_); - int errCode = OS::GetCurrentSysTimeInMicrosecond(curTime); - if (errCode != E_OK) { - return INVALID_TIMESTAMP; - } - - // If GetSysCurrentTime in 1us, we need increase the currentIncCount_ - if (curTime == lastSystemTimeUs_) { - // if the currentIncCount_ has been increased MAX_INC_COUNT, keep the currentIncCount_ - if (currentIncCount_ < MAX_INC_COUNT) { - currentIncCount_++; - } - } else { - lastSystemTimeUs_ = curTime; - currentIncCount_ = 0; - } - return (curTime * TO_100_NS) + currentIncCount_; // Currently Timestamp is uint64_t -} - int TimeHelper::GetSysCurrentRawTime(uint64_t &curTime) { int errCode = OS::GetCurrentSysTimeInMicrosecond(curTime); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/time_helper_client.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/time_helper_client.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5f9bde2e0f29ae915a793a0ecb386335f954a9d6 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/time_helper_client.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 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 "time_helper.h" + +#include "platform_specific.h" + +namespace DistributedDB { +std::mutex TimeHelper::systemTimeLock_; +Timestamp TimeHelper::lastSystemTimeUs_ = 0; +Timestamp TimeHelper::currentIncCount_ = 0; + +Timestamp TimeHelper::GetSysCurrentTime() +{ + uint64_t curTime = 0; + std::lock_guard lock(systemTimeLock_); + int errCode = OS::GetCurrentSysTimeInMicrosecond(curTime); + if (errCode != E_OK) { + return INVALID_TIMESTAMP; + } + + // If GetSysCurrentTime in 1us, we need increase the currentIncCount_ + if (curTime == lastSystemTimeUs_) { + // if the currentIncCount_ has been increased MAX_INC_COUNT, keep the currentIncCount_ + if (currentIncCount_ < MAX_INC_COUNT) { + currentIncCount_++; + } + } else { + lastSystemTimeUs_ = curTime; + currentIncCount_ = 0; + } + return (curTime * TO_100_NS) + currentIncCount_; // Currently Timestamp is uint64_t +} +} // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/BUILD.gn index d27aba5b4c327dbf7f1a5e5b151d03f82333a8cc..51484e154d24887706f98b497283147dccd80286 100644 --- a/kv_store/frameworks/libs/distributeddb/test/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/BUILD.gn @@ -13,7 +13,7 @@ import("//build/test.gni") import("../distributeddb.gni") -module_output_path = "kv_store/kv_store/distributeddb" +module_output_path = "kv_store/distributeddb" ############################################################################### config("gaussdb_rd_config") { @@ -126,18 +126,24 @@ ohos_source_set("src_file") { sources = distributeddb_src sources += distributeddb_cloud_src + sources += distributeddb_client_src sources += [ "unittest/common/common/basic_unit_test.cpp", "unittest/common/common/distributeddb_data_generate_unit_test.cpp", + "unittest/common/common/distributeddb_tools_unit_client_test.cpp", "unittest/common/common/distributeddb_tools_unit_test.cpp", "unittest/common/common/kv_general_ut.cpp", "unittest/common/common/native_sqlite.cpp", "unittest/common/common/rdb_data_generator.cpp", + "unittest/common/common/rdb_data_generator_client.cpp", "unittest/common/common/rdb_general_ut.cpp", "unittest/common/common/system_time.cpp", "unittest/common/common/thread_pool_test_stub.cpp", "unittest/common/interfaces/process_system_api_adapter_impl.cpp", + "unittest/common/storage/virtual_sqlite_relational_store.cpp", + "unittest/common/storage/virtual_sqlite_storage_engine.cpp", "unittest/common/syncer/cloud/cloud_db_data_utils.cpp", + "unittest/common/syncer/cloud/cloud_db_sync_utils_client_test.cpp", "unittest/common/syncer/cloud/cloud_db_sync_utils_test.cpp", "unittest/common/syncer/cloud/virtual_asset_loader.cpp", "unittest/common/syncer/cloud/virtual_cloud_data_translate.cpp", @@ -155,22 +161,12 @@ ohos_source_set("src_file") { configs = [ ":module_private_config" ] - branch_protector_ret = "pac_ret" - sanitize = { - ubsan = true - boundary_sanitize = true - cfi = true - cfi_cross_dso = true - debug = false - } - ldflags = [ "-Wl,--exclude-libs,ALL" ] deps = [ "../gaussdb_rd:gaussdb_rd" ] configs += [ ":gaussdb_rd_config" ] public_configs = [ ":gaussdb_rd_public_config" ] external_deps = [ - "cJSON:cjson", "c_utils:utils", "ffrt:libffrt", "googletest:gmock_main", @@ -183,6 +179,7 @@ ohos_source_set("src_file") { "sqlite:sqlite", "zlib:libz", ] + subsystem_name = "distributeddatamgr" part_name = "kv_store" } @@ -880,6 +877,18 @@ distributeddb_unittest("DistributedDBKVDataStatusTest") { [ "unittest/common/store_test/kv/distributeddb_kv_data_status_test.cpp" ] } +distributeddb_unittest("DistributedDBKvMultiUserSyncTest") { + sources = [ + "unittest/common/store_test/kv/distracteddb_kv_multi_user_sync_test.cpp", + ] +} + +distributeddb_unittest("DistributedDBRDBMultiUserSyncTest") { + sources = [ + "unittest/common/store_test/rdb/distracteddb_rdb_multi_user_sync_test.cpp", + ] +} + distributeddb_unittest("DistributedDBBasicRDBTest") { sources = [ "unittest/common/store_test/rdb/distributeddb_basic_rdb_test.cpp" ] @@ -891,12 +900,234 @@ distributeddb_unittest("DistributedDBRDBDataStatusTest") { ] } +distributeddb_unittest("DistributedDBKVCompressTest") { + sources = + [ "unittest/common/store_test/kv/distributeddb_kv_compress_test.cpp" ] +} + +distributeddb_unittest("DistributedDBAbnormalKVSyncTest") { + sources = [ + "unittest/common/store_test/kv/distributeddb_abnormal_kv_sync_test.cpp", + ] +} + +distributeddb_unittest("DistributedDBKvDeviceSyncTest") { + sources = + [ "unittest/common/store_test/kv/distributeddb_kv_device_sync_test.cpp" ] +} + +distributeddb_unittest("DistributedDBRDBCompressTest") { + sources = + [ "unittest/common/store_test/rdb/distributeddb_rdb_compress_test.cpp" ] +} + +distributeddb_unittest("DistributedDBRDBDropTableTest") { + sources = + [ "unittest/common/store_test/rdb/distributeddb_rdb_drop_table_test.cpp" ] +} + +distributeddb_unittest("DistributedDBRDBUpgradeTest") { + sources = + [ "unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp" ] +} + +config("tokenizer_config_unittest") { + visibility = [ ":*" ] + include_dirs = [ "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include" ] + + defines = [ + "SQLITE_ENABLE_SNAPSHOT", + "SQLITE_HAS_CODEC", + "SQLITE_ENABLE_JSON1", + "USING_HILOG_LOGGER", + "USE_SQLITE_SYMBOLS", + "SQLITE_ENABLE_DROPTABLE_CALLBACK", + ] +} + +ohos_unittest("tokenizer_test") { + branch_protector_ret = "pac_ret" + + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + + module_out_path = module_output_path + + sources = [ "unittest/common/tokenizer/sqlite_adapter_test.cpp" ] + sources += [ "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/src/log_print.cpp" ] + + configs = [ ":tokenizer_config_unittest" ] + cflags_cc = [] + + external_deps = [ + "c_utils:utils", + "ffrt:libffrt", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", + "zlib:libz", + ] +} + +distributeddb_unittest("DistributedDBRDBKnowledgeTest") { + sources = + [ "unittest/common/store_test/rdb/distributeddb_rdb_knowledge_test.cpp" ] +} + +############################################################################### +config("distributeddb_client_module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "./unittest/common/common", + "./unittest/common/syncer", + "./unittest/common/syncer/cloud", + "./unittest/common/interfaces", + "../include", + "../interfaces/include", + "../interfaces/include/cloud", + "../interfaces/include/relational", + "../interfaces/src", + "../interfaces/src/relational", + "../common/include", + "../common/include/cloud", + "../common/include/relational", + "../communicator/include", + "../communicator/src", + "../storage/include", + "../storage/src", + "../storage/src/kv", + "../storage/src/relational", + "../storage/src/sqlite", + "../storage/src/sqlite/relational", + "../syncer/include", + "../syncer/src", + "../syncer/src/cloud", + "../syncer/src/device", + "../gaussdb_rd/include", + ] + + defines = [ + "_LARGEFILE64_SOURCE", + "_FILE_OFFSET_BITS=64", + "SQLITE_HAS_CODEC", + "SQLITE_ENABLE_JSON1", + "USING_HILOG_LOGGER", + "USE_SQLITE_SYMBOLS", + "USING_DB_JSON_EXTRACT_AUTOMATICALLY", + "JSONCPP_USE_BUILDER", + "OMIT_FLATBUFFER", + "OMIT_MULTI_VER", + "RELATIONAL_STORE", + "SQLITE_DISTRIBUTE_RELATIONAL", + "USE_DFX_ABILITY", + "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", + ] + if (is_ohos) { + defines += [ "USE_FFRT" ] + defines += [ "RDB_CLIENT" ] + } +} + +ohos_source_set("distributeddb_client_src_file") { + testonly = true + + sources = distributeddb_client_src + sources += distributeddb_base_src + sources += [ + "unittest/common/common/distributeddb_tools_unit_client_test.cpp", + "unittest/common/common/rdb_data_generator_client.cpp", + "unittest/common/common/system_time.cpp", + "unittest/common/syncer/cloud/cloud_db_sync_utils_client_test.cpp", + ] + + configs = [ ":distributeddb_client_module_private_config" ] + + branch_protector_ret = "pac_ret" + sanitize = { + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + ldflags = [ "-Wl,--exclude-libs,ALL" ] + deps = [ "../gaussdb_rd:gaussdb_rd" ] + configs += [ ":gaussdb_rd_config" ] + public_configs = [ ":gaussdb_rd_public_config" ] + + external_deps = [ + "c_utils:utils", + "ffrt:libffrt", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", + "zlib:libz", + ] + subsystem_name = "distributeddatamgr" + part_name = "kv_store" +} + +template("distributeddb_client_unittest") { + ohos_unittest(target_name) { + forward_variables_from(invoker, "*") + module_out_path = module_output_path + if (!defined(deps)) { + deps = [] + } + if (!defined(external_deps)) { + external_deps = [] + } + configs = [ ":distributeddb_client_module_private_config" ] + deps += [ + ":distributeddb_client_src_file", + "../gaussdb_rd:gaussdb_rd", + ] + + ldflags = [ "-Wl,--exclude-libs,ALL" ] + + external_deps = [ + "c_utils:utils", + "ffrt:libffrt", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", + "zlib:libz", + ] + } +} + +distributeddb_client_unittest("DistributedDBRDBKnowledgeClientTest") { + sources = [ "unittest/common/store_test/rdb/distributeddb_rdb_knowledge_client_test.cpp" ] +} + ############################################################################### group("unittest") { testonly = true deps = [] deps += [ ":DistributedDBAbilitySyncTest", + ":DistributedDBAbnormalKVSyncTest", ":DistributedDBAutoLaunchUnitTest", ":DistributedDBBasicKVTest", ":DistributedDBBasicRDBTest", @@ -967,7 +1198,9 @@ group("unittest") { ":DistributedDBInterfacesTransactionSyncDBTest", ":DistributedDBInterfacesTransactionTest", ":DistributedDBJsonPrecheckUnitTest", + ":DistributedDBKVCompressTest", ":DistributedDBKVDataStatusTest", + ":DistributedDBKvMultiUserSyncTest", ":DistributedDBMetaDataTest", ":DistributedDBMockSyncModuleTest", ":DistributedDBMultiVerP2PSyncTest", @@ -975,7 +1208,13 @@ group("unittest") { ":DistributedDBNotificationChainTest", ":DistributedDBParcelTest", ":DistributedDBRDBCollaborationTest", + ":DistributedDBRDBCompressTest", ":DistributedDBRDBDataStatusTest", + ":DistributedDBRDBDropTableTest", + ":DistributedDBRDBKnowledgeClientTest", + ":DistributedDBRDBKnowledgeTest", + ":DistributedDBRDBMultiUserSyncTest", + ":DistributedDBRDBUpgradeTest", ":DistributedDBRelationalCloudSyncableStorageTest", ":DistributedDBRelationalEncryptedDbTest", ":DistributedDBRelationalGetDataTest", @@ -1022,6 +1261,7 @@ group("unittest") { ":DistributedDBTimeSyncTest", ":DistributedInterfacesRelationalTest", ":RuntimeContextProcessSystemApiAdapterImplTest", + ":tokenizer_test", ] if (defined(global_parts_info.distributeddatamgr_kv_store_lite)) { diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/BUILD.gn index 40519259b1e22c6caa5b3b7ad69dc033b66613ea..9c8f158ab69cd12760aa6ef51901e2e329542aa2 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/BUILD.gn @@ -106,16 +106,14 @@ ohos_fuzztest("CloudsyncFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "../../../../distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/cloudsync_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/cloudsync_fuzzer.cpp index a0bc7988d8f851b2ce04c4c1c76ba3ecbafa271f..6bdc6d64785fa5f52506cc64a58272881f3be6b8 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/cloudsync_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/cloudsync_fuzzer.cpp @@ -18,6 +18,7 @@ #include "cloud/cloud_db_constant.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" +#include "fuzzer/FuzzedDataProvider.h" #include "fuzzer_data.h" #include "kv_store_nb_delegate.h" #include "log_print.h" @@ -123,22 +124,22 @@ public: delegate->CreateDistributedTable(g_table, CLOUD_COOPERATION); } - static void InitDbData(sqlite3 *&db, const uint8_t *data, size_t size) + static void InitDbData(sqlite3 *&db, FuzzedDataProvider &fdp) { sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(db, g_insertLocalDataSql, stmt); if (errCode != E_OK) { return; } - FuzzerData fuzzerData(data, size); - uint32_t len = fuzzerData.GetUInt32() % MOD; + size_t size = fdp.ConsumeIntegralInRange(0, MOD); for (size_t i = 0; i <= size; ++i) { - std::string idStr = fuzzerData.GetString(len); + std::string idStr = fdp.ConsumeRandomLengthString(); errCode = SQLiteUtils::BindTextToStatement(stmt, 1, idStr); if (errCode != E_OK) { break; } - std::vector photo = fuzzerData.GetSequence(fuzzerData.GetInt()); + int photoSize = fdp.ConsumeIntegralInRange(1, MOD); + std::vector photo = fdp.ConsumeBytes(photoSize); errCode = SQLiteUtils::BindBlobToStatement(stmt, 2, photo); // 2 is index of photo if (errCode != E_OK) { break; @@ -160,25 +161,22 @@ public: return asset; } - void InitDbAsset(const uint8_t *data, size_t size) + void InitDbAsset(FuzzedDataProvider &fdp) { - if (data == nullptr || size == 0) { - return; - } sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(db_, g_insertLocalAssetSql, stmt); if (errCode != E_OK) { return; } - FuzzerData fuzzerData(data, size); - uint32_t len = fuzzerData.GetUInt32() % MOD; + size_t size = fdp.ConsumeIntegralInRange(0, MOD); for (size_t i = 0; i <= size; ++i) { - std::string idStr = fuzzerData.GetString(len); + std::string idStr = fdp.ConsumeRandomLengthString(); errCode = SQLiteUtils::BindTextToStatement(stmt, 1, idStr); if (errCode != E_OK) { break; } - std::vector photo = fuzzerData.GetSequence(fuzzerData.GetInt()); + size_t photoSize = fdp.ConsumeIntegralInRange(1, MOD); + std::vector photo = fdp.ConsumeBytes(photoSize); errCode = SQLiteUtils::BindBlobToStatement(stmt, 2, photo); // 2 is index of photo if (errCode != E_OK) { break; @@ -446,79 +444,69 @@ public: kvDelegatePtrS2_->Get(key, actualValue); } - void RandomModeSync(const uint8_t *data, size_t size) + void RandomModeSync(FuzzedDataProvider &fdp) { - if (size == 0) { - BlockSync(); - return; - } - auto mode = static_cast(data[0]); + size_t syncModeLen = sizeof(SyncMode); + auto mode = static_cast(fdp.ConsumeIntegralInRange(0, syncModeLen)); LOGI("[RandomModeSync] select mode %d", static_cast(mode)); BlockSync(mode); } - void DataChangeSync(const uint8_t *data, size_t size) + void DataChangeSync(FuzzedDataProvider &fdp) { SetCloudDbSchema(delegate_); - if (size == 0) { - return; - } - InitDbData(db_, data, size); + InitDbData(db_, fdp); BlockSync(); - FuzzerData fuzzerData(data, size); CloudSyncConfig config; - int maxUploadSize = fuzzerData.GetInt(); - int maxUploadCount = fuzzerData.GetInt(); + int maxUploadSize = fdp.ConsumeIntegral(); + int maxUploadCount = fdp.ConsumeIntegral(); config.maxUploadSize = maxUploadSize; config.maxUploadCount = maxUploadCount; delegate_->SetCloudSyncConfig(config); kvDelegatePtrS1_->SetCloudSyncConfig(config); - uint32_t len = fuzzerData.GetUInt32() % MOD; - std::string version = fuzzerData.GetString(len); + uint32_t len = fdp.ConsumeIntegralInRange(0, MOD); + std::string version = fdp.ConsumeRandomLengthString(); kvDelegatePtrS1_->SetGenCloudVersionCallback([version](const std::string &origin) { return origin + version; }); KvNormalSync(); - int count = fuzzerData.GetInt(); + int count = fdp.ConsumeIntegral(); kvDelegatePtrS1_->GetCount(Query::Select(), count); - std::string device = fuzzerData.GetString(len); + std::string device = fdp.ConsumeRandomLengthString(); kvDelegatePtrS1_->GetCloudVersion(device); - std::vector devices = fuzzerData.GetStringVector(len); + std::vector devices; + for (uint32_t i = 0; i< len; i++) { + devices.push_back(fdp.ConsumeRandomLengthString()); + } OptionBlockSync(devices); } - void InitAssets(const uint8_t *data, size_t size) + void InitAssets(FuzzedDataProvider &fdp) { - FuzzerData fuzzerData(data, size); - uint32_t len = fuzzerData.GetUInt32() % MOD; + size_t size = fdp.ConsumeIntegralInRange(0, MOD); for (size_t i = 0; i <= size; ++i) { - std::string nameStr = fuzzerData.GetString(len); - localAssets_.push_back(GenAsset(nameStr, std::to_string(data[0]))); + std::string nameStr = fdp.ConsumeRandomLengthString(MOD); + localAssets_.push_back(GenAsset(nameStr, fdp.ConsumeBytesAsString(1))); } } - void AssetChangeSync(const uint8_t *data, size_t size) + void AssetChangeSync(FuzzedDataProvider &fdp) { SetCloudDbSchema(delegate_); - if (size == 0) { - return; - } - InitAssets(data, size); - InitDbAsset(data, size); + InitAssets(fdp); + InitDbAsset(fdp); BlockSync(); } - void RandomModeRemoveDeviceData(const uint8_t *data, size_t size) + void RandomModeRemoveDeviceData(FuzzedDataProvider &fdp) { - if (size == 0) { - return; - } SetCloudDbSchema(delegate_); int64_t cloudCount = 10; int64_t paddingSize = 10; InsertCloudTableRecord(0, cloudCount, paddingSize, false); BlockSync(); - auto mode = static_cast(data[0]); + size_t modeLen = sizeof(ClearMode); + auto mode = static_cast(fdp.ConsumeIntegralInRange(0, modeLen)); LOGI("[RandomModeRemoveDeviceData] select mode %d", static_cast(mode)); if (mode == DEFAULT) { return; @@ -564,17 +552,17 @@ void TearDown() } } -void CombineTest(const uint8_t *data, size_t size) +void CombineTest(FuzzedDataProvider &fdp) { if (g_cloudSyncTest == nullptr) { return; } g_cloudSyncTest->NormalSync(); g_cloudSyncTest->KvNormalSync(); - g_cloudSyncTest->RandomModeSync(data, size); - g_cloudSyncTest->DataChangeSync(data, size); - g_cloudSyncTest->AssetChangeSync(data, size); - g_cloudSyncTest->RandomModeRemoveDeviceData(data, size); + g_cloudSyncTest->RandomModeSync(fdp); + g_cloudSyncTest->DataChangeSync(fdp); + g_cloudSyncTest->AssetChangeSync(fdp); + g_cloudSyncTest->RandomModeRemoveDeviceData(fdp); } } @@ -582,7 +570,8 @@ void CombineTest(const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { OHOS::Setup(); - OHOS::CombineTest(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::CombineTest(fdp); OHOS::TearDown(); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn index d47439104b21d6da6a48a905d6e4d232bdaecb9c..03868e809b20d406cd1fb496d6bd6228da629384 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("DelegateFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -107,16 +100,14 @@ ohos_fuzztest("DelegateFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/delegate_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/delegate_fuzzer.cpp index 3d07c64178549d8448dba7ef85b566b2f20740df..82e8b8eb03955c4cabb2e156c3a79765590514d6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/delegate_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/delegate_fuzzer.cpp @@ -16,22 +16,24 @@ #include "delegate_fuzzer.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" +#include "fuzzer/FuzzedDataProvider.h" using namespace DistributedDB; using namespace DistributedDBTest; namespace OHOS { +static constexpr const int HUNDRED = 100; static constexpr const int MOD = 1024; // 1024 is mod static constexpr const int PASSWDLEN = 20; // 20 is passwdlen -std::vector CreateEntries(const uint8_t *data, size_t size, std::vector& keys) +std::vector CreateEntries(FuzzedDataProvider &fdp, std::vector& keys) { std::vector entries; // key'length is less than 1024. - auto count = static_cast(std::min(size, size_t(MOD))); + auto count = fdp.ConsumeIntegralInRange(0, size_t(MOD)); for (int i = 1; i < count; i++) { Entry entry; - entry.key = std::vector(data, data + 1); - entry.value = std::vector(data, data + size); + entry.key = fdp.ConsumeBytes(i); + entry.value = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, MOD)); keys.push_back(entry.key); entries.push_back(entry); } @@ -53,21 +55,25 @@ KvStoreDelegate *PrepareKvStore(KvStoreConfig &config, KvStoreDelegate::Option & return kvDelegatePtr; } -void EncryptOperation(const uint8_t *data, size_t size, KvStoreDelegate *kvDelegatePtr) +void EncryptOperation(FuzzedDataProvider &fdp, KvStoreDelegate *kvDelegatePtr) { if (kvDelegatePtr == nullptr) { return; } CipherPassword passwd; - int len = static_cast(std::min(size, size_t(PASSWDLEN))); - passwd.SetValue(data, len); + size_t data_size = fdp.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val = static_cast(new uint8_t[data_size]); + fdp.ConsumeData(val, data_size); + passwd.SetValue(val, data_size); + delete[] static_cast(val); + val = nullptr; kvDelegatePtr->Rekey(passwd); - bool autoSync = (size == 0) ? true : data[0]; + bool autoSync = fdp.ConsumeBool(); PragmaData praData = static_cast(&autoSync); kvDelegatePtr->Pragma(AUTO_SYNC, praData); } -void CombineTest(const uint8_t *data, KvStoreDelegate *kvDelegatePtr) +void CombineTest(FuzzedDataProvider &fdp, KvStoreDelegate *kvDelegatePtr) { if (kvDelegatePtr == nullptr) { return; @@ -75,11 +81,11 @@ void CombineTest(const uint8_t *data, KvStoreDelegate *kvDelegatePtr) kvDelegatePtr->GetStoreId(); kvDelegatePtr->Rollback(); kvDelegatePtr->Commit(); - auto type = static_cast(data[0]); + auto type = static_cast(fdp.ConsumeIntegral()); kvDelegatePtr->SetConflictResolutionPolicy(type, nullptr); } -void MultiCombineFuzzer(const uint8_t *data, size_t size, KvStoreDelegate::Option &option) +void MultiCombineFuzzer(FuzzedDataProvider &fdp, KvStoreDelegate::Option &option) { KvStoreConfig config; KvStoreDelegate *kvDelegatePtr = PrepareKvStore(config, option); @@ -91,8 +97,8 @@ void MultiCombineFuzzer(const uint8_t *data, size_t size, KvStoreDelegate::Optio } kvDelegatePtr->RegisterObserver(observer); - Key key = std::vector(data, data + (size % 1024)); /* 1024 is max */ - Value value = std::vector(data, data + size); + Key key = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, MOD)); + Value value = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, HUNDRED)); kvDelegatePtr->Put(key, value); kvDelegatePtr->StartTransaction(); KvStoreSnapshotDelegate *kvStoreSnapshotPtr = nullptr; @@ -113,17 +119,17 @@ void MultiCombineFuzzer(const uint8_t *data, size_t size, KvStoreDelegate::Optio kvDelegatePtr->Delete(key); kvStoreSnapshotPtr->Get(key, valueCallback); std::vector keys; - kvDelegatePtr->PutBatch(CreateEntries(data, size, keys)); - Key keyPrefix = std::vector(data, data + 1); + kvDelegatePtr->PutBatch(CreateEntries(fdp, keys)); + Key keyPrefix = fdp.ConsumeBytes(1); kvStoreSnapshotPtr->GetEntries(keyPrefix, [](DBStatus status, const std::vector &entries) { (void) entries.size(); }); if (option.isEncryptedDb) { - EncryptOperation(data, size, kvDelegatePtr); + EncryptOperation(fdp, kvDelegatePtr); } kvDelegatePtr->DeleteBatch(keys); kvDelegatePtr->Clear(); - CombineTest(data, kvDelegatePtr); + CombineTest(fdp, kvDelegatePtr); kvDelegatePtr->UnRegisterObserver(observer); delete observer; observer = nullptr; @@ -139,8 +145,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { CipherPassword passwd; KvStoreDelegate::Option option = {true, true, false, CipherType::DEFAULT, passwd}; - OHOS::MultiCombineFuzzer(data, size, option); + FuzzedDataProvider fdp(data, size); + OHOS::MultiCombineFuzzer(fdp, option); option = {true, false, false, CipherType::DEFAULT, passwd}; - OHOS::MultiCombineFuzzer(data, size, option); + OHOS::MultiCombineFuzzer(fdp, option); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn index 2b4a6b6cf7ed45db9194aca031f89cc99013e879..7be09eb08eea9e737d7db5e9a9cb87e4f02e7b38 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn @@ -56,14 +56,6 @@ ohos_fuzztest("FileOperFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", - "//third_party/googletest/googletest/include/gtest", ] cflags = [ @@ -88,13 +80,6 @@ ohos_fuzztest("FileOperFuzzTest") { "fileoper_fuzzer.cpp", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] - defines = [ "SQLITE_ENABLE_SNAPSHOT", "_LARGEFILE64_SOURCE", @@ -115,9 +100,14 @@ ohos_fuzztest("FileOperFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] + deps = [ "../../../../distributeddb:distributeddb" ] + external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/fileoper_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/fileoper_fuzzer.cpp index 05532d00d325727634e874c8ca605cd81560bd7f..e11e2e2d236c6d7df45e936bfd00e0014c74d786 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/fileoper_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/fileoper_fuzzer.cpp @@ -16,27 +16,30 @@ #include "fileoper_fuzzer.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" +#include "fuzzer/FuzzedDataProvider.h" #include "process_communicator_test_stub.h" using namespace DistributedDB; using namespace DistributedDBTest; namespace OHOS { +static constexpr const int PASSWDLEN = 20; // 20 is passwdlen +static constexpr const int MOD = 1024; static auto g_kvManager = KvStoreDelegateManager("APP_ID", "USER_ID"); -std::vector CreateEntries(const uint8_t* data, size_t size) +std::vector CreateEntries(FuzzedDataProvider &fdp) { std::vector entries; - auto count = static_cast(std::min(size, size_t(1024))); + auto count = fdp.ConsumeIntegralInRange(0, MOD); for (int i = 1; i < count; i++) { Entry entry; - entry.key = std::vector (data, data + i); - entry.value = std::vector (data, data + size); + entry.key = fdp.ConsumeBytes(i); + entry.value = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, MOD)); entries.push_back(entry); } return entries; } -void SingerVerExportAndImport(const uint8_t* data, size_t size, const std::string& testDir) +void SingerVerExportAndImport(FuzzedDataProvider &fdp, const std::string& testDir) { KvStoreNbDelegate::Option nbOption = {true, false, true}; KvStoreNbDelegate *kvNbDelegatePtr = nullptr; @@ -50,13 +53,18 @@ void SingerVerExportAndImport(const uint8_t* data, size_t size, const std::strin if (kvNbDelegatePtr == nullptr) { return; } - kvNbDelegatePtr->PutBatch(CreateEntries(data, size)); + kvNbDelegatePtr->PutBatch(CreateEntries(fdp)); - std::string rawString(reinterpret_cast(data), size); - std::string singleExportFileName = testDir + "/" + rawString; + std::string rawString = fdp.ConsumeRandomLengthString(); + std::string singleExportFileName = testDir + "/" + rawString; CipherPassword passwd; - passwd.SetValue(data, size); + size_t size = fdp.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val = static_cast(new uint8_t[size]); + fdp.ConsumeData(val, size); + passwd.SetValue(val, size); + delete[] static_cast(val); + val = nullptr; kvNbDelegatePtr->Export(singleExportFileName, passwd); kvNbDelegatePtr->Import(singleExportFileName, passwd); @@ -64,10 +72,15 @@ void SingerVerExportAndImport(const uint8_t* data, size_t size, const std::strin g_kvManager.DeleteKvStore("distributed_file_oper_single"); } -void MultiVerExportAndImport(const uint8_t* data, size_t size, const std::string& testDir) +void MultiVerExportAndImport(FuzzedDataProvider &fdp, const std::string& testDir) { CipherPassword passwd; - passwd.SetValue(data, size); + size_t size = fdp.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val = static_cast(new uint8_t[size]); + fdp.ConsumeData(val, size); + passwd.SetValue(val, size); + delete[] static_cast(val); + val = nullptr; KvStoreDelegate::Option option = {true, false, true, CipherType::DEFAULT, passwd}; KvStoreDelegate *kvDelegatePtr = nullptr; g_kvManager.GetKvStore("distributed_file_oper_multi", option, @@ -79,8 +92,9 @@ void MultiVerExportAndImport(const uint8_t* data, size_t size, const std::string if (kvDelegatePtr == nullptr) { return; } - kvDelegatePtr->PutBatch(CreateEntries(data, size)); - std::string rawString(reinterpret_cast(data), size); + kvDelegatePtr->PutBatch(CreateEntries(fdp)); + std::string rawString = fdp.ConsumeRandomLengthString(); + std::string multiExportFileName = testDir + "/" + rawString; kvDelegatePtr->Export(multiExportFileName, passwd); kvDelegatePtr->Import(multiExportFileName, passwd); @@ -97,8 +111,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) OHOS::g_kvManager.SetKvStoreConfig(config); OHOS::g_kvManager.SetProcessLabel("FUZZ", "DISTRIBUTEDDB"); OHOS::g_kvManager.SetProcessCommunicator(std::make_shared()); - OHOS::SingerVerExportAndImport(data, size, config.dataDir); - OHOS::MultiVerExportAndImport(data, size, config.dataDir); + FuzzedDataProvider provider(data, size); + OHOS::SingerVerExportAndImport(provider, config.dataDir); + OHOS::MultiVerExportAndImport(provider, config.dataDir); DistributedDBToolsTest::RemoveTestDbFiles(config.dataDir); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn index 4c14ac1557c77bcd00855673319b904d254237f3..02b0ef60256b16f5a3307461e5e43eba12a94dff 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("ImportFileFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -108,16 +101,14 @@ ohos_fuzztest("ImportFileFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/importfile_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/importfile_fuzzer.cpp index 4ada93f7944db67babb96ff71ea10ce4df2567a8..f29e82657e9a6ba13f294fc5e05ff3c6e6a98c26 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/importfile_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/importfile_fuzzer.cpp @@ -17,6 +17,7 @@ #include #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" +#include "fuzzer/FuzzedDataProvider.h" #include "platform_specific.h" #include "process_communicator_test_stub.h" @@ -27,14 +28,20 @@ using namespace std; static KvStoreConfig g_config; namespace OHOS { -void SingerVerImport(const uint8_t *data, size_t size, const std::string &importFile) +static constexpr const int PASSWDLEN = 20; // 20 is passwdlen +void SingerVerImport(FuzzedDataProvider &provider, const std::string &importFile) { static auto kvManager = KvStoreDelegateManager("APP_ID", "USER_ID"); kvManager.SetKvStoreConfig(g_config); kvManager.SetProcessLabel("FUZZ", "DISTRIBUTEDDB"); kvManager.SetProcessCommunicator(std::make_shared()); CipherPassword passwd; - passwd.SetValue(data, size); + size_t size = provider.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val = static_cast(new uint8_t[size]); + provider.ConsumeData(val, size); + passwd.SetValue(val, size); + delete[] static_cast(val); + val = nullptr; KvStoreNbDelegate::Option option = {true, false, true, CipherType::DEFAULT, passwd}; KvStoreNbDelegate *kvNbDelegatePtr = nullptr; @@ -53,14 +60,15 @@ void SingerVerImport(const uint8_t *data, size_t size, const std::string &import kvManager.DeleteKvStore("distributed_import_single"); } -bool MakeImportFile(const uint8_t *data, size_t size, const std::string &realPath) +bool MakeImportFile(FuzzedDataProvider &provider, const std::string &realPath) { std::ofstream ofs(realPath, std::ofstream::out); if (!ofs.is_open()) { LOGE("the file open failed"); return false; } - ofs.write(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); + ofs.write(rawString.c_str(), rawString.length()); return true; } } @@ -68,15 +76,16 @@ bool MakeImportFile(const uint8_t *data, size_t size, const std::string &realPat /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + FuzzedDataProvider provider(data, size); std::string dataDir; - std::string testDataDir(data, data + size); + std::string testDataDir = provider.ConsumeRandomLengthString(); DistributedDBToolsTest::TestDirInit(dataDir); g_config.dataDir = dataDir; std::string path = dataDir + "/fuzz" + testDataDir; std::string realPath; OS::GetRealPath(path, realPath); - if (OHOS::MakeImportFile(data, size, realPath)) { - OHOS::SingerVerImport(data, size, realPath); + if (OHOS::MakeImportFile(provider, realPath)) { + OHOS::SingerVerImport(provider, realPath); } DistributedDBToolsTest::RemoveTestDbFiles(dataDir); diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn index b7dd82377f24da3483156f05c5ef60ae5ab94f83..1a211a69956ccb3a7e296a36130c4627c57f26e3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("IProcessCommunicatorFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -107,16 +100,14 @@ ohos_fuzztest("IProcessCommunicatorFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/iprocesscommunicator_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/iprocesscommunicator_fuzzer.cpp index 89abb799e225c53e43b72029cc6d6d3dce1610cd..e315045b93ddd2c6e4636fb88169d6b7e5554ea6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/iprocesscommunicator_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/iprocesscommunicator_fuzzer.cpp @@ -17,6 +17,7 @@ #include #include "distributeddb_tools_test.h" #include "db_info_handle.h" +#include "fuzzer/FuzzedDataProvider.h" #include "iprocess_communicator.h" #include "iprocess_system_api_adapter.h" #include "runtime_config.h" @@ -87,12 +88,18 @@ public: onDeviceChange_(devInfo, isOnline); } - void FuzzOnDataReceive(const DistributedDB::DeviceInfos &devInfo, const uint8_t* data, size_t size) + void FuzzOnDataReceive(const DistributedDB::DeviceInfos &devInfo, FuzzedDataProvider &provider) { if (onDataReceive_ == nullptr) { return; } + size_t dataLen = 1024; + uint32_t size = provider.ConsumeIntegralInRange(0, dataLen);; + uint8_t* data = static_cast(new uint8_t[size]); + provider.ConsumeData(data, size); onDataReceive_(devInfo, data, size); + delete[] static_cast(data); + data = nullptr; } private: @@ -147,10 +154,10 @@ public: } }; -void CommunicatorFuzzer(const uint8_t *data, size_t size) +void CommunicatorFuzzer(FuzzedDataProvider &provider) { static auto kvManager = KvStoreDelegateManager("APP_ID", "USER_ID"); - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); KvStoreDelegateManager::SetProcessLabel(rawString, "defaut"); auto communicator = std::make_shared(); KvStoreDelegateManager::SetProcessCommunicator(communicator); @@ -173,7 +180,7 @@ void CommunicatorFuzzer(const uint8_t *data, size_t size) } }); DeviceInfos device = {"defaut"}; - communicator->FuzzOnDataReceive(device, data, size); + communicator->FuzzOnDataReceive(device, provider); if (kvNbDelegatePtr != nullptr) { kvManager.CloseKvStore(kvNbDelegatePtr); kvManager.DeleteKvStore(rawString); @@ -188,6 +195,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) if (size < 4) { return 0; } - OHOS::CommunicatorFuzzer(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::CommunicatorFuzzer(fdp); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/BUILD.gn index cffe3bff406ee4209dae5201c7520362e0a0586f..4c7f7bc91b2302433249d024353fe6f3e07646b6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/BUILD.gn @@ -77,16 +77,14 @@ ohos_source_set("src_file") { configs = [ ":module_private_config" ] - deps = [ "//third_party/sqlite:sqlite" ] - - configs += [ "//third_party/cJSON:cJSON_config" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps += [ "//third_party/cJSON:cjson" ] external_deps = [ + "cJSON:cjson", "c_utils:utils", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "sqlite:sqlite", ] subsystem_name = "distributeddatamgr" @@ -104,21 +102,16 @@ ohos_fuzztest("JsonFuzzTest") { external_deps = [] } configs = [ ":module_private_config" ] - deps += [ - ":src_file", - "//third_party/sqlite:sqlite", - ] - configs += [ "//third_party/cJSON:cJSON_config" ] + deps += [ ":src_file" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps += [ - "//third_party/cJSON:cjson", - "//third_party/openssl:libcrypto_shared", - ] external_deps = [ + "cJSON:cjson", "c_utils:utils", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] cflags = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.cpp index 7671d0459b5f528f1ba47b2069d598601619997a..ea7e6b9a38ed7d84cd62141902642343ea9e7e26 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.cpp @@ -28,6 +28,7 @@ #include #include +#include "fuzzer/FuzzedDataProvider.h" #include "grd_base/grd_db_api.h" #include "grd_base/grd_error.h" #include "grd_base/grd_resultset_api.h" @@ -332,14 +333,14 @@ void InsertDocFourFuzz(const std::string &longId, const std::string &documentDat GRD_InsertDoc(g_db, COLLECTION_NAME, document52, 0); } -void InsertDocFuzz(const uint8_t *data, size_t size) +void InsertDocFuzz(FuzzedDataProvider &provider) { - std::string collectionNameData(reinterpret_cast(data), size); + std::string collectionNameData = provider.ConsumeRandomLengthString(); const char *collectionNameVal = collectionNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); + std::string optionStrData = provider.ConsumeRandomLengthString(); const char *optionStrVal = optionStrData.data(); GRD_CreateCollection(g_db, collectionNameVal, optionStrVal, 0); - std::string documentData(reinterpret_cast(data), size); + std::string documentData = provider.ConsumeRandomLengthString(); const char *documentVal = documentData.data(); GRD_InsertDoc(g_db, collectionNameVal, documentVal, 0); GRD_InsertDoc(g_db, collectionNameVal, documentVal, 0); @@ -898,10 +899,10 @@ void FindDocFuzzPlus(const std::string &input) } } // namespace -void FindDocFuzz(const uint8_t *data, size_t size) +void FindDocFuzz(FuzzedDataProvider &provider) { GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{\"field\":\"" + input + "\"}"; GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); Query query = { inputJson.c_str(), inputJson.c_str() }; @@ -911,6 +912,7 @@ void FindDocFuzz(const uint8_t *data, size_t size) GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet); GRD_FreeResultSet(resultSet); resultSet = nullptr; + size_t size = provider.ConsumeIntegral(); GRD_FindDoc(g_db, input.c_str(), query, size, &resultSet); GRD_FreeResultSet(resultSet); GRD_FindDoc(nullptr, input.c_str(), query, 1, &resultSet); @@ -1067,10 +1069,10 @@ void UpdateDocFilterFuzz() GRD_DropCollection(g_db, COLLECTION_NAME, 0); } -void UpdateDocFuzz(const uint8_t *data, size_t size) +void UpdateDocFuzz(FuzzedDataProvider &provider) { GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{\"_id\":\"2\", \"field\": \"aaa\", " "\"subject\":\"aaaaaaaaaaa\", \"test1\": true, " "\"test2\": null}"; @@ -1132,10 +1134,10 @@ void UpsertDocNewFuzz(const std::string &input, GRD_DB *db1) GRD_UpsertDoc(db1, "student", R""({"_id":"10002"})"", updateDocNew.c_str(), 1); } -void UpsertDocFuzz(const uint8_t *data, size_t size) +void UpsertDocFuzz(FuzzedDataProvider &provider) { GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJsonNoId = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; std::string inputJson = "{\"_id\":\"1\", \"field\": " + input + "}"; @@ -1229,10 +1231,10 @@ void DeleteDocResultFuzz(const std::string &input) GRD_FreeResultSet(resultSet); } -void DeleteDocFuzz(const uint8_t *data, size_t size) +void DeleteDocFuzz(FuzzedDataProvider &provider) { GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{\"field\":" + input + "}"; GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); GRD_DeleteDoc(g_db, input.c_str(), "{}", 0); @@ -1357,10 +1359,10 @@ void FindAndReleaseFuzz(std::string document, std::string filter, Query query, c FindAndRelease(query); } -void NextFuzz(const uint8_t *data, size_t size) +void NextFuzz(FuzzedDataProvider &provider) { GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{" + input + "}"; GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); Query query = { inputJson.c_str(), "{}" }; @@ -1379,15 +1381,16 @@ void NextFuzz(const uint8_t *data, size_t size) query.filter = "{\"field\": [\"field2\", null, \"abc\", 123]}"; FindAndRelease(query); std::string document = "{\"field\": [\"" + input + "\",\"" + input + "\",\"" + input + "\"]}"; + size_t size = provider.ConsumeIntegral(); std::string filter = "{\"field." + std::to_string(size) + "\":\"" + input + "\"}"; FindAndReleaseFuzz(document, filter, query, input); GRD_DropCollection(g_db, COLLECTION_NAME, 0); } -void GetValueFuzz(const uint8_t *data, size_t size) +void GetValueFuzz(FuzzedDataProvider &provider) { GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{" + input + "}"; GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); char *value = nullptr; @@ -1436,12 +1439,12 @@ void DbOpenOneFuzz(GRD_DB *dbVal) DbOpenCloseFuzz(path.c_str(), R""({"redopubbufsize":16385})"", dbVal); } -void DbOpenFuzz(const uint8_t *data, size_t size) +void DbOpenFuzz(FuzzedDataProvider &provider) { - std::string dbFileData(reinterpret_cast(data), size); + std::string dbFileData = provider.ConsumeRandomLengthString(); std::string realDbFileData = DB_DIR_PATH + dbFileData; const char *dbFileVal = realDbFileData.data(); - std::string configStrData(reinterpret_cast(data), size); + std::string configStrData = provider.ConsumeRandomLengthString(); const char *configStrVal = configStrData.data(); GRD_DB *dbVal = nullptr; @@ -1493,12 +1496,12 @@ void DbOpenFuzz(const uint8_t *data, size_t size) DbOpenOneFuzz(dbVal); } -void DbCloseFuzz(const uint8_t *data, size_t size) +void DbCloseFuzz(FuzzedDataProvider &provider) { - std::string dbFileData(reinterpret_cast(data), size); + std::string dbFileData = provider.ConsumeRandomLengthString(); std::string realDbFileData = DB_DIR_PATH + dbFileData; const char *dbFileVal = realDbFileData.data(); - std::string configStrData(reinterpret_cast(data), size); + std::string configStrData = provider.ConsumeRandomLengthString(); const char *configStrVal = configStrData.data(); GRD_DB *dbVal = nullptr; DbOpenCloseFuzz(dbFileVal, configStrVal, dbVal); @@ -1527,11 +1530,11 @@ void DbCloseResultSetFuzz() } } -void CreateCollectionFuzz(const uint8_t *data, size_t size) +void CreateCollectionFuzz(FuzzedDataProvider &provider) { - std::string collectionNameData(reinterpret_cast(data), size); + std::string collectionNameData = provider.ConsumeRandomLengthString(); const char *collectionNameVal = collectionNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); + std::string optionStrData = provider.ConsumeRandomLengthString(); const char *optionStrVal = optionStrData.data(); GRD_CreateCollection(nullptr, collectionNameVal, optionStrVal, 0); GRD_CreateCollection(g_db, collectionNameVal, optionStrVal, 0); @@ -1552,25 +1555,22 @@ void CreateCollectionFuzz(const uint8_t *data, size_t size) GRD_DropCollection(g_db, collectionNameVal, 0); } -void DropCollectionFuzz(const uint8_t *data, size_t size) +void DropCollectionFuzz(FuzzedDataProvider &provider) { - std::string collectionNameData(reinterpret_cast(data), size); + std::string collectionNameData = provider.ConsumeRandomLengthString(); const char *collectionNameVal = collectionNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); + std::string optionStrData = provider.ConsumeRandomLengthString(); const char *optionStrVal = optionStrData.data(); GRD_CreateCollection(g_db, collectionNameVal, optionStrVal, 0); GRD_DropCollection(nullptr, collectionNameVal, 0); GRD_DropCollection(g_db, collectionNameVal, 0); } -void DbFlushFuzz(const uint8_t *data, size_t size) +void DbFlushFuzz(FuzzedDataProvider &provider) { - if (data == nullptr) { - return; - } GRD_DB *db = nullptr; GRD_DB *db2 = nullptr; - const uint32_t flags = *data; + const uint32_t flags = provider.ConsumeIntegral(); int ret = GRD_DBOpen(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db); if (ret == GRD_OK) { GRD_Flush(db, flags); @@ -1684,23 +1684,23 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Run your code on data */ OHOS::SetUpTestCase(); - - OHOS::DbOpenFuzz(data, size); - OHOS::CreateCollectionFuzz(data, size); - OHOS::DropCollectionFuzz(data, size); - OHOS::InsertDocFuzz(data, size); - OHOS::FindDocFuzz(data, size); - OHOS::UpdateDocFuzz(data, size); - OHOS::UpsertDocFuzz(data, size); - OHOS::DeleteDocFuzz(data, size); - OHOS::NextFuzz(data, size); - OHOS::GetValueFuzz(data, size); + FuzzedDataProvider provider(data, size); + OHOS::DbOpenFuzz(provider); + OHOS::CreateCollectionFuzz(provider); + OHOS::DropCollectionFuzz(provider); + OHOS::InsertDocFuzz(provider); + OHOS::FindDocFuzz(provider); + OHOS::UpdateDocFuzz(provider); + OHOS::UpsertDocFuzz(provider); + OHOS::DeleteDocFuzz(provider); + OHOS::NextFuzz(provider); + OHOS::GetValueFuzz(provider); OHOS::FreeResultSetFuzz(); OHOS::TestGrdDbApGrdGetItem002Fuzz(); OHOS::TestGrdKvBatchCoupling003Fuzz(); - OHOS::DbCloseFuzz(data, size); + OHOS::DbCloseFuzz(provider); OHOS::DbCloseResultSetFuzz(); - OHOS::DbFlushFuzz(data, size); + OHOS::DbFlushFuzz(provider); OHOS::TearDownTestCase(); return 0; diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/BUILD.gn index e1df9821a52c162a0ae2784fe640f94b0e2a5409..eb3f7f0978143c87adf1b6cbb4574971021b06c3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/BUILD.gn @@ -77,16 +77,14 @@ ohos_source_set("src_file") { configs = [ ":module_private_config" ] - deps = [ "//third_party/sqlite:sqlite" ] - - configs += [ "//third_party/cJSON:cJSON_config" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps += [ "//third_party/cJSON:cjson" ] external_deps = [ + "cJSON:cjson", "c_utils:utils", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "sqlite:sqlite", ] subsystem_name = "distributeddatamgr" @@ -104,21 +102,16 @@ ohos_fuzztest("JsonInnerFuzzTest") { external_deps = [] } configs = [ ":module_private_config" ] - deps += [ - ":src_file", - "//third_party/sqlite:sqlite", - ] - configs += [ "//third_party/cJSON:cJSON_config" ] + deps += [ ":src_file" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps += [ - "//third_party/cJSON:cjson", - "//third_party/openssl:libcrypto_shared", - ] external_deps = [ + "cJSON:cjson", "c_utils:utils", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] cflags = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.cpp index ce3d75705964b8bead05ad650dc1aa7dd750f835..5b79f7582a937e036b0657107f98ad8b08f5e837 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.cpp @@ -28,6 +28,7 @@ #include #include +#include "fuzzer/FuzzedDataProvider.h" #include "grd_base/grd_db_api.h" #include "grd_base/grd_error.h" #include "grd_base/grd_resultset_api.h" @@ -341,14 +342,14 @@ void InsertDocFourFuzz(const std::string &longId, const std::string &documentDat GRD_InsertDocInner(g_db, COLLECTION_NAME, document52, 0); } -void InsertDocFuzz(const uint8_t *data, size_t size) +void InsertDocFuzz(FuzzedDataProvider &provider) { - std::string collectionNameData(reinterpret_cast(data), size); + std::string collectionNameData = provider.ConsumeRandomLengthString(); const char *collectionNameVal = collectionNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); + std::string optionStrData = provider.ConsumeRandomLengthString(); const char *optionStrVal = optionStrData.data(); GRD_CreateCollectionInner(g_db, collectionNameVal, optionStrVal, 0); - std::string documentData(reinterpret_cast(data), size); + std::string documentData = provider.ConsumeRandomLengthString(); const char *documentVal = documentData.data(); GRD_InsertDocInner(g_db, collectionNameVal, documentVal, 0); GRD_InsertDocInner(g_db, collectionNameVal, documentVal, 0); @@ -907,10 +908,10 @@ void FindDocFuzzPlus(const std::string &input) } } // namespace -void FindDocFuzz(const uint8_t *data, size_t size) +void FindDocFuzz(FuzzedDataProvider &provider) { GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{\"field\":\"" + input + "\"}"; GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); Query query = { inputJson.c_str(), inputJson.c_str() }; @@ -920,6 +921,7 @@ void FindDocFuzz(const uint8_t *data, size_t size) GRD_FindDocInner(g_db, COLLECTION_NAME, query, 1, &resultSet); GRD_FreeResultSetInner(resultSet); resultSet = nullptr; + size_t size = provider.ConsumeIntegral(); GRD_FindDocInner(g_db, input.c_str(), query, size, &resultSet); GRD_FreeResultSetInner(resultSet); GRD_FindDocInner(nullptr, input.c_str(), query, 1, &resultSet); @@ -1076,10 +1078,10 @@ void UpdateDocFilterFuzz() GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); } -void UpdateDocFuzz(const uint8_t *data, size_t size) +void UpdateDocFuzz(FuzzedDataProvider &provider) { GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{\"_id\":\"2\", \"field\": \"aaa\", " "\"subject\":\"aaaaaaaaaaa\", \"test1\": true, " "\"test2\": null}"; @@ -1141,10 +1143,10 @@ void UpsertDocNewFuzz(const std::string &input, GRD_DB *db1) GRD_UpsertDocInner(db1, "student", R""({"_id":"10002"})"", updateDocNew.c_str(), 1); } -void UpsertDocFuzz(const uint8_t *data, size_t size) +void UpsertDocFuzz(FuzzedDataProvider &provider) { GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJsonNoId = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; std::string inputJson = "{\"_id\":\"1\", \"field\": " + input + "}"; @@ -1238,10 +1240,10 @@ void DeleteDocResultFuzz(const std::string &input) GRD_FreeResultSetInner(resultSet); } -void DeleteDocFuzz(const uint8_t *data, size_t size) +void DeleteDocFuzz(FuzzedDataProvider &provider) { GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{\"field\":" + input + "}"; GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); GRD_DeleteDocInner(g_db, input.c_str(), "{}", 0); @@ -1366,10 +1368,10 @@ void FindAndReleaseFuzz(std::string document, std::string filter, Query query, c FindAndRelease(query); } -void NextFuzz(const uint8_t *data, size_t size) +void NextFuzz(FuzzedDataProvider &provider) { GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{" + input + "}"; GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); Query query = { inputJson.c_str(), "{}" }; @@ -1388,15 +1390,16 @@ void NextFuzz(const uint8_t *data, size_t size) query.filter = "{\"field\": [\"field2\", null, \"abc\", 123]}"; FindAndRelease(query); std::string document = "{\"field\": [\"" + input + "\",\"" + input + "\",\"" + input + "\"]}"; + size_t size = provider.ConsumeIntegral(); std::string filter = "{\"field." + std::to_string(size) + "\":\"" + input + "\"}"; FindAndReleaseFuzz(document, filter, query, input); GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); } -void GetValueFuzz(const uint8_t *data, size_t size) +void GetValueFuzz(FuzzedDataProvider &provider) { GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{" + input + "}"; GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); char *value = nullptr; @@ -1445,12 +1448,12 @@ void DbOpenOneFuzz(GRD_DB *dbVal) DbOpenCloseFuzz(path.c_str(), R""({"redopubbufsize":16385})"", dbVal); } -void DbOpenFuzz(const uint8_t *data, size_t size) +void DbOpenFuzz(FuzzedDataProvider &provider) { - std::string dbFileData(reinterpret_cast(data), size); + std::string dbFileData = provider.ConsumeRandomLengthString(); std::string realDbFileData = DB_DIR_PATH + dbFileData; const char *dbFileVal = realDbFileData.data(); - std::string configStrData(reinterpret_cast(data), size); + std::string configStrData = provider.ConsumeRandomLengthString(); const char *configStrVal = configStrData.data(); GRD_DB *dbVal = nullptr; @@ -1502,12 +1505,12 @@ void DbOpenFuzz(const uint8_t *data, size_t size) DbOpenOneFuzz(dbVal); } -void DbCloseFuzz(const uint8_t *data, size_t size) +void DbCloseFuzz(FuzzedDataProvider &provider) { - std::string dbFileData(reinterpret_cast(data), size); + std::string dbFileData = provider.ConsumeRandomLengthString(); std::string realDbFileData = DB_DIR_PATH + dbFileData; const char *dbFileVal = realDbFileData.data(); - std::string configStrData(reinterpret_cast(data), size); + std::string configStrData = provider.ConsumeRandomLengthString(); const char *configStrVal = configStrData.data(); GRD_DB *dbVal = nullptr; DbOpenCloseFuzz(dbFileVal, configStrVal, dbVal); @@ -1536,11 +1539,11 @@ void DbCloseResultSetFuzz() } } -void CreateCollectionFuzz(const uint8_t *data, size_t size) +void CreateCollectionFuzz(FuzzedDataProvider &provider) { - std::string collectionNameData(reinterpret_cast(data), size); + std::string collectionNameData = provider.ConsumeRandomLengthString(); const char *collectionNameVal = collectionNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); + std::string optionStrData = provider.ConsumeRandomLengthString(); const char *optionStrVal = optionStrData.data(); GRD_CreateCollectionInner(nullptr, collectionNameVal, optionStrVal, 0); GRD_CreateCollectionInner(g_db, collectionNameVal, optionStrVal, 0); @@ -1561,25 +1564,22 @@ void CreateCollectionFuzz(const uint8_t *data, size_t size) GRD_DropCollectionInner(g_db, collectionNameVal, 0); } -void DropCollectionFuzz(const uint8_t *data, size_t size) +void DropCollectionFuzz(FuzzedDataProvider &provider) { - std::string collectionNameData(reinterpret_cast(data), size); + std::string collectionNameData = provider.ConsumeRandomLengthString(); const char *collectionNameVal = collectionNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); + std::string optionStrData = provider.ConsumeRandomLengthString(); const char *optionStrVal = optionStrData.data(); GRD_CreateCollectionInner(g_db, collectionNameVal, optionStrVal, 0); GRD_DropCollectionInner(nullptr, collectionNameVal, 0); GRD_DropCollectionInner(g_db, collectionNameVal, 0); } -void DbFlushFuzz(const uint8_t *data, size_t size) +void DbFlushFuzz(FuzzedDataProvider &provider) { - if (data == nullptr) { - return; - } GRD_DB *db = nullptr; GRD_DB *db2 = nullptr; - const uint32_t flags = *data; + const uint32_t flags = provider.ConsumeIntegral(); int ret = GRD_DBOpenInner(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db); if (ret == GRD_OK) { GRD_FlushInner(db, flags); @@ -1693,23 +1693,23 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Run your code on data */ OHOS::SetUpTestCase(); - - OHOS::DbOpenFuzz(data, size); - OHOS::CreateCollectionFuzz(data, size); - OHOS::DropCollectionFuzz(data, size); - OHOS::InsertDocFuzz(data, size); - OHOS::FindDocFuzz(data, size); - OHOS::UpdateDocFuzz(data, size); - OHOS::UpsertDocFuzz(data, size); - OHOS::DeleteDocFuzz(data, size); - OHOS::NextFuzz(data, size); - OHOS::GetValueFuzz(data, size); + FuzzedDataProvider provider(data, size); + OHOS::DbOpenFuzz(provider); + OHOS::CreateCollectionFuzz(provider); + OHOS::DropCollectionFuzz(provider); + OHOS::InsertDocFuzz(provider); + OHOS::FindDocFuzz(provider); + OHOS::UpdateDocFuzz(provider); + OHOS::UpsertDocFuzz(provider); + OHOS::DeleteDocFuzz(provider); + OHOS::NextFuzz(provider); + OHOS::GetValueFuzz(provider); OHOS::FreeResultSetFuzz(); OHOS::TestGrdDbApGrdGetItem002Fuzz(); OHOS::TestGrdKvBatchCoupling003Fuzz(); - OHOS::DbCloseFuzz(data, size); + OHOS::DbCloseFuzz(provider); OHOS::DbCloseResultSetFuzz(); - OHOS::DbFlushFuzz(data, size); + OHOS::DbFlushFuzz(provider); OHOS::TearDownTestCase(); return 0; diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn index 327c65931de4576e5bcbb9bfe3501f42ffd67ee8..4bc1b4b942b9807c6eef2db4862be76aadbe3a93 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("KvDelegateManagerFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -108,16 +101,14 @@ ohos_fuzztest("KvDelegateManagerFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/kvdelegatemanager_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/kvdelegatemanager_fuzzer.cpp index 31429f8d1e9058fb5fd69bd717c557798e6c480c..72d4b065e2626d49e7acfdc366ca2478172e501d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/kvdelegatemanager_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/kvdelegatemanager_fuzzer.cpp @@ -20,6 +20,7 @@ #include #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" +#include "fuzzer/FuzzedDataProvider.h" #include "kv_store_delegate_manager.h" #include "log_print.h" #include "runtime_config.h" @@ -31,27 +32,13 @@ class KvDelegateManagerFuzzer { namespace OHOS { using namespace DistributedDB; using namespace DistributedDBTest; - +static constexpr const int MOD = 1024; // 1024 is mod KvStoreDelegateManager g_mgr("APP_ID", "USER_ID"); const std::string DUMP_DISTRIBUTED_DB = "--database"; -std::string GetString(const uint8_t *data, size_t size, size_t len, uint32_t &start) -{ - std::string res; - if (size == 0) { - return ""; - } - if (start >= size || start + len >= size) { - return std::string(data, data + size - 1); - } - res = std::string(data + start, data + start + len - 1); - start += len; - return res; -} - -void GetAutoLaunchOption(const uint8_t* data, size_t size, AutoLaunchOption &option) +void GetAutoLaunchOption(FuzzedDataProvider &fdp, AutoLaunchOption &option) { - std::string randomStr = size == 0 ? "" : std::string(data, data + size - 1); + std::string randomStr = fdp.ConsumeRandomLengthString(); option.schema = randomStr; option.observer = nullptr; option.notifier = nullptr; @@ -68,11 +55,11 @@ void RuntimeConfigFuzz() RuntimeConfig::Dump(handle, params); } -void CallbackFuzz(const uint8_t *data, std::string storeId) +void CallbackFuzz(FuzzedDataProvider &fdp, std::string storeId) { - uint64_t diskSize = static_cast(*data); + uint64_t diskSize = fdp.ConsumeIntegral(); g_mgr.GetKvStoreDiskSize(storeId, diskSize); - bool isPermissionCheck = static_cast(*data); + bool isPermissionCheck = fdp.ConsumeBool(); auto permissionCheckCallback = [isPermissionCheck](const std::string &userId, const std::string &appId, const std::string &storeId, uint8_t flag) -> bool { return isPermissionCheck; }; (void) KvStoreDelegateManager::SetPermissionCheckCallback(permissionCheckCallback); @@ -81,38 +68,38 @@ void CallbackFuzz(const uint8_t *data, std::string storeId) return isPermissionCheck; }; (void) KvStoreDelegateManager::SetPermissionCheckCallback(permissionCheckCallbackV2); - bool isSyncActivationCheck = static_cast(*data); + bool isSyncActivationCheck = fdp.ConsumeBool(); auto syncActivationCheck = [isSyncActivationCheck](const std::string &userId, const std::string &appId, const std::string &storeId) -> bool { return isSyncActivationCheck; }; KvStoreDelegateManager::SetSyncActivationCheckCallback(syncActivationCheck); KvStoreDelegateManager::NotifyUserChanged(); } -void CombineTest(const uint8_t *data, size_t size) +void CombineTest(FuzzedDataProvider &fdp) { LOGD("Begin KvDelegateManagerFuzzer"); std::string path; DistributedDBToolsTest::TestDirInit(path); const int paramCount = 3; + size_t size = fdp.ConsumeIntegralInRange(paramCount, MOD); for (size_t len = 1; len < (size / paramCount); len++) { - uint32_t start = 0; - std::string appId = GetString(data, size, len, start); - std::string userId = GetString(data, size, len, start); - std::string storeId = GetString(data, size, len, start); + std::string appId = fdp.ConsumeRandomLengthString(); + std::string userId = fdp.ConsumeRandomLengthString(); + std::string storeId = fdp.ConsumeRandomLengthString(); std::string dir; (void) KvStoreDelegateManager::GetDatabaseDir(storeId, appId, userId, dir); (void) KvStoreDelegateManager::GetDatabaseDir(storeId, dir); (void) KvStoreDelegateManager::SetProcessLabel(appId, userId); - bool syncDualTupleMode = static_cast(*data); + bool syncDualTupleMode = fdp.ConsumeBool(); (void) KvStoreDelegateManager::GetKvStoreIdentifier(userId, appId, storeId, syncDualTupleMode); AutoLaunchOption option; - GetAutoLaunchOption(data, size, option); + GetAutoLaunchOption(fdp, option); option.dataDir = path; (void) KvStoreDelegateManager::EnableKvStoreAutoLaunch(userId, appId, storeId, option, nullptr); (void) KvStoreDelegateManager::DisableKvStoreAutoLaunch(userId, appId, storeId); - CallbackFuzz(data, storeId); - std::string targetDev = GetString(data, size, len, start); - bool isCheckOk = static_cast(*data); + CallbackFuzz(fdp, storeId); + std::string targetDev = fdp.ConsumeRandomLengthString(); + bool isCheckOk = fdp.ConsumeBool(); auto databaseStatusNotifyCallback = [userId, appId, storeId, targetDev, &isCheckOk] ( const std::string ¬ifyUserId, const std::string ¬ifyAppId, const std::string ¬ifyStoreId, const std::string &deviceId, bool onlineStatus) -> void { @@ -133,6 +120,7 @@ void CombineTest(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - OHOS::CombineTest(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::CombineTest(fdp); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn index 9e2b842361bf3d9ada9f5ae4f6fb94aae142aa6c..69557fe0c93aba548aa7db6545af19803390b136 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("KvStoreResultSetFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -108,16 +101,14 @@ ohos_fuzztest("KvStoreResultSetFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/kvstoreresultset_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/kvstoreresultset_fuzzer.cpp index a4a71e39e4915c3986b4cd2fa2f7edcc114baa02..29570c392f7168fe38a495903729955e27f6be4c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/kvstoreresultset_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/kvstoreresultset_fuzzer.cpp @@ -16,6 +16,7 @@ #include "kvstoreresultset_fuzzer.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" +#include "fuzzer/FuzzedDataProvider.h" #include "process_communicator_test_stub.h" using namespace DistributedDB; @@ -24,7 +25,8 @@ using namespace std; namespace OHOS { static auto g_kvManager = KvStoreDelegateManager("APP_ID", "USER_ID"); -void ResultSetFuzzer(const uint8_t* data, size_t size) +static constexpr const int MOD = 1024; // 1024 is mod +void ResultSetFuzzer(FuzzedDataProvider &fdp) { KvStoreNbDelegate::Option option = {true, false, true}; KvStoreNbDelegate *kvNbDelegatePtr = nullptr; @@ -41,11 +43,10 @@ void ResultSetFuzzer(const uint8_t* data, size_t size) Key testKey; Value testValue; + size_t size = fdp.ConsumeIntegralInRange(0, MOD); for (size_t i = 0; i < size; i++) { - testKey.clear(); - testValue.clear(); - testKey.push_back(data[i]); - testValue.push_back(data[i]); + testKey = fdp.ConsumeBytes(1); + testValue = fdp.ConsumeBytes(1); kvNbDelegatePtr->Put(testKey, testValue); } @@ -63,7 +64,7 @@ void ResultSetFuzzer(const uint8_t* data, size_t size) if (size == 0) { return; } - auto pos = KvStoreResultSetFuzzer::U32_AT(data) % size; + auto pos = fdp.ConsumeIntegralInRange(0, size); readResultSet->MoveToPosition(pos++); readResultSet->Move(0 - pos); readResultSet->IsFirst(); @@ -88,7 +89,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) KvStoreConfig config; DistributedDBToolsTest::TestDirInit(config.dataDir); OHOS::g_kvManager.SetKvStoreConfig(config); - OHOS::ResultSetFuzzer(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::ResultSetFuzzer(fdp); DistributedDBToolsTest::RemoveTestDbFiles(config.dataDir); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn index 7244809252639a9c8253940c93d968dc1e20aaae..768ee303f8c3a4c9830dbc7ba871b4dc0427f8a3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("NbDelegateFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -108,16 +101,14 @@ ohos_fuzztest("NbDelegateFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/nbdelegate_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/nbdelegate_fuzzer.cpp index 0370e56fb4b49e93e3e5a56af1d5c275c23cbc9a..ebe6e1619ab02d5cca71106b17e49e09ac50fbf5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/nbdelegate_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/nbdelegate_fuzzer.cpp @@ -17,6 +17,7 @@ #include #include "distributeddb_tools_test.h" #include "fuzzer_data.h" +#include "fuzzer/FuzzedDataProvider.h" #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" #include "kv_store_observer.h" @@ -29,7 +30,9 @@ class KvStoreNbDelegateCURDFuzzer { namespace OHOS { using namespace DistributedDB; using namespace DistributedDBTest; - +static constexpr const int HUNDRED = 100; +static constexpr const int MOD = 1024; +static constexpr const int PASSWDLEN = 20; class KvStoreObserverFuzzTest : public DistributedDB::KvStoreObserver { public: KvStoreObserverFuzzTest(); @@ -105,16 +108,16 @@ bool KvStoreObserverFuzzTest::IsCleared() const return isCleared_; } -std::vector CreateEntries(const uint8_t *data, size_t size, std::vector &keys) +std::vector CreateEntries(FuzzedDataProvider &fdp, std::vector &keys) { std::vector entries; // key'length is less than 1024. - auto count = static_cast(std::min(size, size_t(1024))); + auto count = fdp.ConsumeIntegralInRange(0, 1024); for (int i = 1; i < count; i++) { Entry entry; - entry.key = std::vector(data, data + i); + entry.key = fdp.ConsumeBytes(i); keys.push_back(entry.key); - entry.value = std::vector(data, data + size); + entry.value = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, HUNDRED)); entries.push_back(entry); } return entries; @@ -181,59 +184,53 @@ void TestCRUD(const Key &key, const Value &value, KvStoreNbDelegate *kvNbDelegat kvNbDelegatePtr->Get(key, valueRead); } -void GetDeviceEntriesTest(const uint8_t *data, size_t size, KvStoreNbDelegate *kvNbDelegatePtr) +void GetDeviceEntriesTest(FuzzedDataProvider &fdp, KvStoreNbDelegate *kvNbDelegatePtr) { - FuzzerData fuzzerData(data, size); - uint32_t len = fuzzerData.GetUInt32(); const int lenMod = 30; // 30 is mod for string vector size - std::string device = fuzzerData.GetString(len % lenMod); + std::string device = fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, lenMod)); kvNbDelegatePtr->GetWatermarkInfo(device); kvNbDelegatePtr->GetSyncDataSize(device); std::vector vect; kvNbDelegatePtr->GetDeviceEntries(device, vect); } -void RemoveDeviceDataByMode(const uint8_t *data, size_t size, KvStoreNbDelegate *kvNbDelegatePtr) +void RemoveDeviceDataByMode(FuzzedDataProvider &fdp, KvStoreNbDelegate *kvNbDelegatePtr) { - if (size == 0) { - return; - } - auto mode = static_cast(data[0]); + auto mode = static_cast(fdp.ConsumeIntegral()); LOGI("[RemoveDeviceDataByMode] select mode %d", static_cast(mode)); if (mode == DEFAULT) { return; } - FuzzerData fuzzerData(data, size); - uint32_t len = fuzzerData.GetUInt32(); const int lenMod = 30; // 30 is mod for string vector size - std::string device = fuzzerData.GetString(len % lenMod); - std::string user = fuzzerData.GetString(len % lenMod); + std::string device = fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, lenMod)); + std::string user = fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, lenMod)); kvNbDelegatePtr->RemoveDeviceData(); kvNbDelegatePtr->RemoveDeviceData(device, mode); kvNbDelegatePtr->RemoveDeviceData(device, user, mode); } -void FuzzCURD(const uint8_t *data, size_t size, KvStoreNbDelegate *kvNbDelegatePtr) +void FuzzCURD(FuzzedDataProvider &fdp, KvStoreNbDelegate *kvNbDelegatePtr) { auto observer = new (std::nothrow) KvStoreObserverFuzzTest; if ((observer == nullptr) || (kvNbDelegatePtr == nullptr)) { return; } - Key key = std::vector(data, data + (size % 1024)); /* 1024 is max */ - Value value = std::vector(data, data + size); - kvNbDelegatePtr->RegisterObserver(key, size, observer); - kvNbDelegatePtr->SetConflictNotifier(size, [](const KvStoreNbConflictData &data) { + + Key key = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, MOD));/* 1024 is max */ + Value value = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, MOD)); + kvNbDelegatePtr->RegisterObserver(key, fdp.ConsumeIntegral(), observer); + kvNbDelegatePtr->SetConflictNotifier(fdp.ConsumeIntegral(), [](const KvStoreNbConflictData &data) { (void)data.GetType(); }); TestCRUD(key, value, kvNbDelegatePtr); kvNbDelegatePtr->StartTransaction(); std::vector keys; - std::vector tmp = CreateEntries(data, size, keys); + std::vector tmp = CreateEntries(fdp, keys); kvNbDelegatePtr->PutBatch(tmp); if (!keys.empty()) { /* random deletePublic updateTimestamp 2 */ - bool deletePublic = (size > 3u) ? (data[0] > data[1]) : true; // use index 0 and 1 - bool updateTimestamp = (size > 3u) ? (data[2] > data[1]) : true; // use index 2 and 1 + bool deletePublic = fdp.ConsumeBool(); // use index 0 and 1 + bool updateTimestamp = fdp.ConsumeBool(); // use index 2 and 1 kvNbDelegatePtr->UnpublishToLocal(keys[0], deletePublic, updateTimestamp); } kvNbDelegatePtr->DeleteBatch(keys); @@ -250,36 +247,40 @@ void FuzzCURD(const uint8_t *data, size_t size, KvStoreNbDelegate *kvNbDelegateP kvNbDelegatePtr->CheckIntegrity(); FuzzSetInterceptorTest(kvNbDelegatePtr); if (!keys.empty()) { - bool deleteLocal = (size > 3u) ? (data[0] > data[1]) : true; // use index 0 and 1 - bool updateTimestamp = (size > 3u) ? (data[2] > data[1]) : true; // use index 2 and 1 + bool deleteLocal = fdp.ConsumeBool(); // use index 0 and 1 + bool updateTimestamp = fdp.ConsumeBool(); // use index 2 and 1 /* random deletePublic updateTimestamp 2 */ kvNbDelegatePtr->PublishLocal(keys[0], deleteLocal, updateTimestamp, nullptr); } kvNbDelegatePtr->DeleteBatch(keys); kvNbDelegatePtr->GetTaskCount(); - std::string rawString(reinterpret_cast(data), size); + std::string rawString = fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, MOD)); kvNbDelegatePtr->RemoveDeviceData(rawString); - RemoveDeviceDataByMode(data, size, kvNbDelegatePtr); - GetDeviceEntriesTest(data, size, kvNbDelegatePtr); + RemoveDeviceDataByMode(fdp, kvNbDelegatePtr); + GetDeviceEntriesTest(fdp, kvNbDelegatePtr); } -void EncryptOperation(const uint8_t *data, size_t size, std::string &DirPath, KvStoreNbDelegate *kvNbDelegatePtr) +void EncryptOperation(FuzzedDataProvider &fdp, std::string &DirPath, KvStoreNbDelegate *kvNbDelegatePtr) { if (kvNbDelegatePtr == nullptr) { return; } CipherPassword passwd; - int len = static_cast(std::min(size, size_t(20))); - passwd.SetValue(data, len); + size_t size = fdp.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val = static_cast(new uint8_t[size]); + fdp.ConsumeData(val, size); + passwd.SetValue(val, size); + delete[] static_cast(val); + val = nullptr; kvNbDelegatePtr->Rekey(passwd); - len = static_cast(std::min(size, size_t(100))); // set min 100 - std::string fileName(data, data + len); + int len = fdp.ConsumeIntegralInRange(0, 100); // set min 100 + std::string fileName = fdp.ConsumeRandomLengthString(len); std::string mulitExportFileName = DirPath + "/" + fileName + ".db"; kvNbDelegatePtr->Export(mulitExportFileName, passwd); kvNbDelegatePtr->Import(mulitExportFileName, passwd); } -void CombineTest(const uint8_t *data, size_t size, KvStoreNbDelegate::Option &option) +void CombineTest(FuzzedDataProvider &fdp, KvStoreNbDelegate::Option &option) { static auto kvManager = KvStoreDelegateManager("APP_ID", "USER_ID"); KvStoreConfig config; @@ -292,9 +293,9 @@ void CombineTest(const uint8_t *data, size_t size, KvStoreNbDelegate::Option &op kvNbDelegatePtr = kvNbDelegate; } }); - FuzzCURD(data, size, kvNbDelegatePtr); + FuzzCURD(fdp, kvNbDelegatePtr); if (option.isEncryptedDb) { - EncryptOperation(data, size, config.dataDir, kvNbDelegatePtr); + EncryptOperation(fdp, config.dataDir, kvNbDelegatePtr); } kvManager.CloseKvStore(kvNbDelegatePtr); kvManager.DeleteKvStore("distributed_nb_delegate_test"); @@ -306,8 +307,9 @@ void CombineTest(const uint8_t *data, size_t size, KvStoreNbDelegate::Option &op extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { DistributedDB::KvStoreNbDelegate::Option option = {true, false, false}; - OHOS::CombineTest(data, size, option); + FuzzedDataProvider fdp(data, size); + OHOS::CombineTest(fdp, option); option = {true, true, false}; - OHOS::CombineTest(data, size, option); + OHOS::CombineTest(fdp, option); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn index cdb448f9ee7a6a5d0182f7e2b8163d5f10d09a59..a182a25e448a915297e313ffc2b12cc2e4e3ae83 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("ParseCkeckFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -108,16 +101,14 @@ ohos_fuzztest("ParseCkeckFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/parseckeck_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/parseckeck_fuzzer.cpp index 9ad5ca658e66301dad0e23239af5438d7ea92ae7..4e119bcabaa8b04e74571c7fd44f8ed4afc4d089 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/parseckeck_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/parseckeck_fuzzer.cpp @@ -15,6 +15,7 @@ #include "parseckeck_fuzzer.h" #include "distributeddb_tools_test.h" +#include "fuzzer/FuzzedDataProvider.h" #include "schema_object.h" #include "schema_utils.h" @@ -24,12 +25,12 @@ using namespace DistributedDBTest; static KvStoreConfig g_config; namespace OHOS { -void GetSchmaKvstore(const uint8_t* data, size_t size) +void GetSchmaKvstore(FuzzedDataProvider &fdp) { static auto kvManager = KvStoreDelegateManager("APP_ID", "USER_ID"); kvManager.SetKvStoreConfig(g_config); KvStoreNbDelegate::Option option = {true, false, false}; - std::string schemaString(reinterpret_cast(data), size); + std::string schemaString = fdp.ConsumeRandomLengthString(); option.schema = schemaString; KvStoreNbDelegate *kvNbDelegatePtr = nullptr; @@ -44,41 +45,41 @@ void GetSchmaKvstore(const uint8_t* data, size_t size) kvManager.DeleteKvStore("distributed_nb_get_schemakvstore"); } -void ParseSchemaString(const uint8_t* data, size_t size) +void ParseSchemaString(FuzzedDataProvider &fdp) { - std::string schemaString(reinterpret_cast(data), size); + std::string schemaString = fdp.ConsumeRandomLengthString(); SchemaObject schemaOri; schemaOri.ParseFromSchemaString(schemaString); schemaOri.CompareAgainstSchemaString(schemaString); } -void CompareSchemaString(const uint8_t* data, size_t size) +void CompareSchemaString(FuzzedDataProvider &fdp) { // beginning half / 2 - std::string schemaString(data, data + (size / 2)); + std::string schemaString = fdp.ConsumeRandomLengthString(); // ending half / 2 ~ end. - std::string schemaString2(data + (size / 2), data + size); + std::string schemaString2 = fdp.ConsumeRandomLengthString(); SchemaObject schemaOri; schemaOri.ParseFromSchemaString(schemaString); schemaOri.ParseFromSchemaString(schemaString2); } -void CheckFieldName(const uint8_t* data, size_t size) +void CheckFieldName(FuzzedDataProvider &fdp) { - std::string schemaAttrString(reinterpret_cast(data), size); + std::string schemaAttrString = fdp.ConsumeRandomLengthString(); SchemaUtils::CheckFieldName(schemaAttrString); } -void ParseFieldPath(const uint8_t* data, size_t size) +void ParseFieldPath(FuzzedDataProvider &fdp) { - std::string schemaAttrString(reinterpret_cast(data), size); + std::string schemaAttrString = fdp.ConsumeRandomLengthString(); FieldPath outPath; SchemaUtils::ParseAndCheckFieldPath(schemaAttrString, outPath); } -void CheckSchemaAttribute(const uint8_t* data, size_t size) +void CheckSchemaAttribute(FuzzedDataProvider &fdp) { - std::string schemaAttrString(reinterpret_cast(data), size); + std::string schemaAttrString = fdp.ConsumeRandomLengthString(); SchemaAttribute outAttr; SchemaUtils::ParseAndCheckSchemaAttribute(schemaAttrString, outAttr); SchemaUtils::ParseAndCheckSchemaAttribute(schemaAttrString, outAttr); @@ -89,12 +90,13 @@ void CheckSchemaAttribute(const uint8_t* data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { DistributedDBToolsTest::TestDirInit(g_config.dataDir); - OHOS::GetSchmaKvstore(data, size); - OHOS::ParseSchemaString(data, size); - OHOS::CompareSchemaString(data, size); - OHOS::CheckFieldName(data, size); - OHOS::ParseFieldPath(data, size); - OHOS::CheckSchemaAttribute(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::GetSchmaKvstore(fdp); + OHOS::ParseSchemaString(fdp); + OHOS::CompareSchemaString(fdp); + OHOS::CheckFieldName(fdp); + OHOS::ParseFieldPath(fdp); + OHOS::CheckSchemaAttribute(fdp); DistributedDBToolsTest::RemoveTestDbFiles(g_config.dataDir); return 0; diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn index a0423aac08420d6e011cd49a3823b04757b04bce..6553991c188c2b59c99b2cf0aede4f656dab7a84 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("QueryFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -108,16 +101,14 @@ ohos_fuzztest("QueryFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/query_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/query_fuzzer.cpp index 11085e24a94971258173bb19c098ba4dddc5204f..283c638cbbdd9fc30356b68be2a47c6cd85c571b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/query_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/query_fuzzer.cpp @@ -15,6 +15,7 @@ #include "query_fuzzer.h" #include "fuzzer_data.h" +#include "fuzzer/FuzzedDataProvider.h" #include "get_query_info.h" using namespace DistributedDB; @@ -25,106 +26,120 @@ namespace { } namespace OHOS { -void FuzzEqualTo(const uint8_t* data, size_t size) +void FuzzEqualTo(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); - Query query = Query::Select().EqualTo(rawString, static_cast(size)); + std::string rawString = provider.ConsumeRandomLengthString(); + int size = provider.ConsumeIntegral(); + Query query = Query::Select().EqualTo(rawString, size); } -void FuzzNotEqualTo(const uint8_t* data, size_t size) +void FuzzNotEqualTo(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); Query query = Query::Select().NotEqualTo(TEST_FIELD_NAME, rawString); } -void FuzzGreaterThan(const uint8_t* data, size_t size) +void FuzzGreaterThan(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); - Query query = Query::Select().GreaterThan(rawString, static_cast(QueryFuzzer::U32_AT(data))); + std::string rawString = provider.ConsumeRandomLengthString(); + int size = provider.ConsumeIntegral(); + Query query = Query::Select().GreaterThan(rawString, size); } -void FuzzLessThan(const uint8_t* data, size_t size) +void FuzzLessThan(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); Query query = Query::Select().LessThan(TEST_FIELD_NAME, rawString); } -void FuzzGreaterThanOrEqualTo(const uint8_t* data, size_t size) +void FuzzGreaterThanOrEqualTo(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); + size_t size = provider.ConsumeIntegral(); Query query = Query::Select().GreaterThanOrEqualTo(rawString, static_cast(size)); } -void FuzzLessThanOrEqualTo(const uint8_t* data, size_t size) +void FuzzLessThanOrEqualTo(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); Query query = Query::Select().LessThanOrEqualTo(TEST_FIELD_NAME, rawString); } -void FuzzOrderBy(const uint8_t* data, size_t size) +void FuzzOrderBy(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); (void)Query::Select().GreaterThanOrEqualTo(rawString, true); (void)Query::Select().GreaterThanOrEqualTo(rawString, false); } -void FuzzLimit(const uint8_t* data, size_t size) +void FuzzLimit(FuzzedDataProvider &provider) { - Query query = Query::Select().Limit(static_cast(size), static_cast(QueryFuzzer::U32_AT(data))); + int size1 = provider.ConsumeIntegral(); + int size2 = provider.ConsumeIntegral(); + Query query = Query::Select().Limit(size1, size2); } -void FuzzLike(const uint8_t* data, size_t size) +void FuzzLike(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); Query query = Query::Select().Like(rawString, rawString); } -void FuzzNotLike(const uint8_t* data, size_t size) +void FuzzNotLike(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); Query query = Query::Select().NotLike(TEST_FIELD_NAME, rawString); } -void FuzzIn(const uint8_t* data, size_t size) +void FuzzIn(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); std::vector values; // 512 max size - for (int i = 0; i < static_cast(QueryFuzzer::U32_AT(data) % 512); i++) { + int maxSize = 512; + int size = provider.ConsumeIntegralInRange(0, maxSize); + for (int i = 0; i < size; i++) { values.push_back(rawString); } Query query = Query::Select().In(TEST_FIELD_NAME, values); } -void FuzzNotIn(const uint8_t* data, size_t size) +void FuzzNotIn(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); std::vector values; // 512 max size - for (int i = 0; i < static_cast(size % 512); i++) { + int maxSize = 512; + int size = provider.ConsumeIntegralInRange(0, maxSize); + for (int i = 0; i < size; i++) { values.push_back(rawString); } Query query = Query::Select().NotIn(TEST_FIELD_NAME, values); } -void FuzzIsNull(const uint8_t* data, size_t size) +void FuzzIsNull(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); Query query = Query::Select().IsNull(rawString); } -void FuzzAssetsOnly(const uint8_t *data, size_t size) +void FuzzAssetsOnly(FuzzedDataProvider &provider) { - DistributedDBTest::FuzzerData fuzzerData(data, size); - uint32_t len = fuzzerData.GetUInt32(); const int lenMod = 30; // 30 is mod for string vector size - std::string tableName = fuzzerData.GetString(len % lenMod); - std::string fieldName = fuzzerData.GetString(len % lenMod); + std::string tableName = provider.ConsumeRandomLengthString(provider.ConsumeIntegralInRange(0, lenMod)); + std::string fieldName = provider.ConsumeRandomLengthString(provider.ConsumeIntegralInRange(0, lenMod)); std::map> assets; - assets[fuzzerData.GetString(len % lenMod)] = fuzzerData.GetStringSet(len % lenMod); + std::set set; + // 512 max size + size_t maxSize = 512; + size_t size = provider.ConsumeIntegralInRange(0, maxSize); + for (size_t i = 1; i <= size; i++) { + set.insert(provider.ConsumeRandomLengthString(provider.ConsumeIntegralInRange(0, i))); + } + assets[provider.ConsumeRandomLengthString(provider.ConsumeIntegralInRange(0, lenMod))] = set; Query query = Query::Select().From(tableName) .BeginGroup() - .EqualTo(fieldName, fuzzerData.GetInt()) + .EqualTo(fieldName, provider.ConsumeIntegral()) .And() .AssetsOnly(assets) .EndGroup(); @@ -138,21 +153,22 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) if (size < 4) { return 0; } + FuzzedDataProvider provider(data, size); // Run your code on data - OHOS::FuzzEqualTo(data, size); - OHOS::FuzzNotEqualTo(data, size); - OHOS::FuzzGreaterThan(data, size); - OHOS::FuzzLessThan(data, size); - OHOS::FuzzGreaterThanOrEqualTo(data, size); - OHOS::FuzzLessThanOrEqualTo(data, size); - OHOS::FuzzOrderBy(data, size); - OHOS::FuzzLimit(data, size); - OHOS::FuzzLike(data, size); - OHOS::FuzzNotLike(data, size); - OHOS::FuzzIn(data, size); - OHOS::FuzzNotIn(data, size); - OHOS::FuzzIsNull(data, size); - OHOS::FuzzAssetsOnly(data, size); + OHOS::FuzzEqualTo(provider); + OHOS::FuzzNotEqualTo(provider); + OHOS::FuzzGreaterThan(provider); + OHOS::FuzzLessThan(provider); + OHOS::FuzzGreaterThanOrEqualTo(provider); + OHOS::FuzzLessThanOrEqualTo(provider); + OHOS::FuzzOrderBy(provider); + OHOS::FuzzLimit(provider); + OHOS::FuzzLike(provider); + OHOS::FuzzNotLike(provider); + OHOS::FuzzIn(provider); + OHOS::FuzzNotIn(provider); + OHOS::FuzzIsNull(provider); + OHOS::FuzzAssetsOnly(provider); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn index 97f3b495bf077fc1ddb5d3e5458b2789d32e5acf..4f4ff2947d23b84267d54599455cd27348d7019e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("ReKeyFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -108,16 +101,14 @@ ohos_fuzztest("ReKeyFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/rekey_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/rekey_fuzzer.cpp index 229b7c26062c061d1720e2557de4e23975ca5944..36ccb87aea0fb9522af41bfd3c642f9786f177f6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/rekey_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/rekey_fuzzer.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "fuzzer/FuzzedDataProvider.h" #include "rekey_fuzzer.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" @@ -22,25 +23,33 @@ using namespace DistributedDBTest; namespace OHOS { static auto g_kvManager = KvStoreDelegateManager("APP_ID", "USER_ID"); -std::vector CreateEntries(const uint8_t* data, size_t size) +static constexpr const int MOD = 1024; // 1024 is mod + +static constexpr const int PASSWDLEN = 20; +std::vector CreateEntries(FuzzedDataProvider &provider) { std::vector entries; - auto count = static_cast(std::min(size, size_t(1024))); + auto count =provider.ConsumeIntegralInRange(0, MOD); for (int i = 1; i < count; i++) { Entry entry; - entry.key = std::vector (data, data + i); - entry.value = std::vector (data, data + size); + entry.key = provider.ConsumeBytes(i); + entry.value = provider.ConsumeBytes(provider.ConsumeIntegral()); entries.push_back(entry); } return entries; } -void SingerVerReKey(const uint8_t* data, size_t size) +void SingerVerReKey(FuzzedDataProvider &provider) { CipherPassword passwd; // div 2 -> half - passwd.SetValue(data, (size / 2)); + size_t size = provider.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val = static_cast(new uint8_t[size]); + provider.ConsumeData(val, size); + passwd.SetValue(val, size); + delete[] static_cast(val); + val = nullptr; KvStoreNbDelegate::Option nbOption = {true, false, true, CipherType::DEFAULT, passwd}; KvStoreNbDelegate *kvNbDelegatePtr = nullptr; @@ -53,18 +62,28 @@ void SingerVerReKey(const uint8_t* data, size_t size) }); if (kvNbDelegatePtr != nullptr) { - kvNbDelegatePtr->PutBatch(CreateEntries(data, size)); - passwd.SetValue(data, size); + kvNbDelegatePtr->PutBatch(CreateEntries(provider)); + size_t size2 = provider.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val2 = static_cast(new uint8_t[size2]); + provider.ConsumeData(val2, size2); + passwd.SetValue(val2, size2); + delete[] static_cast(val2); + val2 = nullptr; kvNbDelegatePtr->Rekey(passwd); g_kvManager.CloseKvStore(kvNbDelegatePtr); } } -void MultiVerVerReKey(const uint8_t* data, size_t size) +void MultiVerVerReKey(FuzzedDataProvider &fdp) { CipherPassword passwd; // div 2 -> half - passwd.SetValue(data, (size / 2)); + size_t size = fdp.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val = static_cast(new uint8_t[size]); + fdp.ConsumeData(val, size); + passwd.SetValue(val, size); + delete[] static_cast(val); + val = nullptr; KvStoreNbDelegate::Option nbOption = {true, false, true, CipherType::DEFAULT, passwd}; KvStoreNbDelegate *kvNbDelegatePtr = nullptr; @@ -77,9 +96,14 @@ void MultiVerVerReKey(const uint8_t* data, size_t size) }); if (kvNbDelegatePtr != nullptr) { - kvNbDelegatePtr->PutBatch(CreateEntries(data, size)); + kvNbDelegatePtr->PutBatch(CreateEntries(fdp)); CipherPassword passwdTwo; - passwdTwo.SetValue(data, size); + size_t size2 = fdp.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val2 = static_cast(new uint8_t[size2]); + fdp.ConsumeData(val2, size2); + passwdTwo.SetValue(val2, size2); + delete[] static_cast(val2); + val2 = nullptr; kvNbDelegatePtr->Rekey(passwdTwo); g_kvManager.CloseKvStore(kvNbDelegatePtr); } @@ -92,8 +116,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) KvStoreConfig config; DistributedDBToolsTest::TestDirInit(config.dataDir); OHOS::g_kvManager.SetKvStoreConfig(config); - OHOS::SingerVerReKey(data, size); - OHOS::MultiVerVerReKey(data, size); + FuzzedDataProvider provider(data, size); + OHOS::SingerVerReKey(provider); + OHOS::MultiVerVerReKey(provider); DistributedDBToolsTest::RemoveTestDbFiles(config.dataDir); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn index 7b09db2daeb0f41f0161349df4fc8e12496ad935..8a3bf1631258974008f39312fedd6e8b71a7b367 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("RelationalstoredelegateFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -112,16 +105,14 @@ ohos_fuzztest("RelationalstoredelegateFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/relationalstoredelegate_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/relationalstoredelegate_fuzzer.cpp index e9f6f19174ecb56911a450c533043e7fb0f73bcd..62339e920c1d76132f7a23e6a09cbbab05fd75e3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/relationalstoredelegate_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/relationalstoredelegate_fuzzer.cpp @@ -33,7 +33,7 @@ namespace OHOS { using namespace DistributedDB; using namespace DistributedDBTest; using namespace DistributedDBUnitTest; - +static constexpr const int MOD = 3; constexpr const char *DB_SUFFIX = ".db"; constexpr const char *STORE_ID = "Relational_Store_ID"; const std::string DEVICE_A = "DEVICE_A"; @@ -142,7 +142,7 @@ void TestDistributedSchema(FuzzedDataProvider *fdp) g_delegate->SetDistributedSchema(schema); } -void CombineTest(const uint8_t *data, size_t size) +void CombineTest(FuzzedDataProvider &fdp) { auto observer = new (std::nothrow) DistributedDB::StoreObserver; if (observer == nullptr) { @@ -155,29 +155,25 @@ void CombineTest(const uint8_t *data, size_t size) return; } g_delegate->RegisterObserver(observer); - FuzzerData fuzzerData(data, size); - uint32_t len = fuzzerData.GetUInt32(); - const int lenMod = 30; // 30 is mod for string vector size - std::string tableName = fuzzerData.GetString(len % lenMod); + uint32_t len = fdp.ConsumeIntegral(); + std::string tableName = fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, MOD)); g_delegate->CreateDistributedTable(tableName); - std::vector device = fuzzerData.GetStringVector(len % lenMod); - Query query = Query::Select(); - int index = len % 3; // 3 is the mod - SyncMode mode = SyncMode::SYNC_MODE_PUSH_ONLY; - if (index == 1) { - mode = SyncMode::SYNC_MODE_PULL_ONLY; - } else if (index == 2) { // 2 is the remainder - mode = SyncMode::SYNC_MODE_PUSH_PULL; + std::vector device; + size_t size = fdp.ConsumeIntegralInRange(0, MOD); + for (int i = 0; i < size; i++) { + device.push_back(fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, MOD))); } + Query query = Query::Select(); + SyncMode mode = len % MOD == 1 ? SyncMode::SYNC_MODE_PULL_ONLY : SyncMode::SYNC_MODE_PUSH_PULL; SyncStatusCallback callback = nullptr; g_delegate->Sync(device, mode, query, callback, len % 2); // 2 is mod num for wait parameter g_delegate->GetCloudSyncTaskCount(); - std::set extendColNames = {fuzzerData.GetString(len % lenMod)}; - std::set trackerColNames = fuzzerData.GetStringSet(len % lenMod); - bool isLogicDeleted = static_cast(*data); - FuzzedDataProvider fdp(data, size); - MultiCombineTest(&fdp, tableName, extendColNames, trackerColNames, isLogicDeleted); + std::string extendName = fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, MOD)); + std::set extendColNames = {extendName}; + std::string trackName = fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, MOD)); + std::set trackerColNames = {trackName}; + MultiCombineTest(&fdp, tableName, extendColNames, trackerColNames, fdp.ConsumeBool()); std::string deviceId = device.size() > 0 ? device[0] : tableName; g_delegate->RemoveDeviceData(); g_delegate->RemoveDeviceData(deviceId); @@ -201,7 +197,8 @@ void CombineTest(const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { OHOS::Setup(); - OHOS::CombineTest(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::CombineTest(fdp); OHOS::TearDown(); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn index 6087cf010f52354c519e3f0f5eaa44babc35fabd..46bc9b0eac2837a2d146c3d73365413ccdfc7d15 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("RelationalstoremanagerFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -112,16 +105,14 @@ ohos_fuzztest("RelationalstoremanagerFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn index 9d39da2d7f3a7f6b5de86edbd806b84cca9e8451..4f7911af9130dd464f2be00bca0e5439deba60fe 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("SchemaDelegateFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ "-g", @@ -108,16 +101,14 @@ ohos_fuzztest("SchemaDelegateFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/BUILD.gn index 40b2edce3a3439ef8a946c09486a2862da4b55e7..9ee04e9a98ae5b345a9a3e90eeb2486898f937ee 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/BUILD.gn @@ -74,6 +74,7 @@ ohos_fuzztest("StorageFuzzTest") { sources = distributeddb_src sources += distributeddb_cloud_src + sources += distributeddb_client_src sources += [ "../../../test/fuzztest/common/distributeddb_tools_test.cpp", "../../../test/fuzztest/common/fuzzer_data.cpp", @@ -102,16 +103,14 @@ ohos_fuzztest("StorageFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "../../../../distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/project.xml b/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/project.xml index 798d910c94cf92e0fe357b951465826f22462d4c..115a010147669c5dd765635df132a9c04e215f38 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/project.xml +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/project.xml @@ -18,7 +18,7 @@ 1000 - 30 + 1800 4096 diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/storage_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/storage_fuzzer.cpp index 6c34394c06f4cce2d0d647db3a0d1ec7b38ec548..cb45c7ba3fabd9cce8cd056fe51b85ea4a97ecb8 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/storage_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/storage_fuzzer.cpp @@ -26,6 +26,7 @@ #include "distributeddb_tools_test.h" #include "log_print.h" #include "fuzzer_data.h" +#include "fuzzer/FuzzedDataProvider.h" #include "relational_store_client.h" #include "relational_store_delegate.h" #include "relational_store_manager.h" @@ -62,7 +63,8 @@ static std::condition_variable g_cv; static bool g_alreadyNotify = false; DistributedDB::StoreObserver::StoreChangedInfo g_changedData; static constexpr const int MOD = 1000; // 1000 is mod -static constexpr const int MODNUM = 10; +static constexpr const int DIVNUM = 10; +static constexpr const int COUNT_MOD = 50000; // 50000 is mod of count class StorageFuzzer { public: @@ -98,14 +100,13 @@ public: } } - void FuzzTest(const uint8_t* data, size_t size) + void FuzzTest(FuzzedDataProvider &fdp) { - FuzzerData fuzzData(data, size); - if (!SetAndGetLocalWaterMark(TABLE_NAME_1, fuzzData.GetUInt64())) { + if (!SetAndGetLocalWaterMark(TABLE_NAME_1, fdp.ConsumeIntegral())) { LOGE("Set and get local watermark unsuccess"); return; } - std::string cloudMark = fuzzData.GetString(size); + std::string cloudMark = fdp.ConsumeRandomLengthString(); if (!SetAndGetCloudWaterMark(TABLE_NAME_1, cloudMark)) { LOGE("Set and get cloud watermark unsuccess"); return; @@ -224,12 +225,12 @@ void TearDown() DistributedDBToolsTest::RemoveTestDbFiles(g_testDir); } -void CombineTest(const uint8_t* data, size_t size) +void CombineTest(FuzzedDataProvider &fdp) { if (g_storageFuzzerTest == nullptr) { return; } - g_storageFuzzerTest->FuzzTest(data, size); + g_storageFuzzerTest->FuzzTest(fdp); } class ClientStoreObserver : public StoreObserver { @@ -269,7 +270,7 @@ void CreateTableForStoreObserver(sqlite3 *db, const std::string &tableName) RdbTestUtils::ExecSql(db, sql); } -void InitLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint64_t num) +void InitLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint32_t num) { for (size_t i = 0; i < num; ++i) { std::string sql = "insert or replace into " + tableName + " VALUES('" + std::to_string(i) + "', 'zhangsan');"; @@ -279,10 +280,10 @@ void InitLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint64_t nu RdbTestUtils::ExecSql(db, sql); } -void InitDataStatus(const std::string &tableName, int count, sqlite3 *db) +void InitDataStatus(const std::string &tableName, uint32_t count, sqlite3 *db) { int type = 4; // the num of different status - for (int i = 1; i <= (type * count) % MODNUM; i++) { + for (uint32_t i = 1; i <= (type * count) / DIVNUM; i++) { std::string sql = "INSERT INTO " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" + std::to_string(i) + "');"; RdbTestUtils::ExecSql(db, sql); @@ -334,7 +335,7 @@ void StoreObserverFuzz(const std::string &tableName) sqlite3_close_v2(db); } -void DropLogicDeletedDataFuzz(std::string tableName, uint64_t num) +void DropLogicDeletedDataFuzz(std::string tableName, uint32_t num) { sqlite3 *db = RdbTestUtils::CreateDataBase(g_dbDir + STOREID + DBSUFFIX); InitLogicDeleteData(db, tableName, num); @@ -342,7 +343,7 @@ void DropLogicDeletedDataFuzz(std::string tableName, uint64_t num) sqlite3_close_v2(db); } -void LockAndUnLockFuzz(std::string tableName, int count) +void LockAndUnLockFuzz(std::string tableName, uint32_t count) { sqlite3 *db = RdbTestUtils::CreateDataBase(g_dbDir + STOREID + DBSUFFIX); InitDataStatus(tableName, count, db); @@ -353,16 +354,15 @@ void LockAndUnLockFuzz(std::string tableName, int count) sqlite3_close_v2(db); } -void CombineClientFuzzTest(const uint8_t *data, size_t size) +void CombineClientFuzzTest(FuzzedDataProvider &fdp) { - FuzzerData fuzzerData(data, size); - uint32_t len = fuzzerData.GetUInt32() % MOD; - std::string tableName = fuzzerData.GetString(len); + uint32_t len = fdp.ConsumeIntegralInRange(0, MOD); + std::string tableName = fdp.ConsumeRandomLengthString(len); ClientObserverFuzz(tableName); StoreObserverFuzz(tableName); - uint64_t num = fuzzerData.GetUInt64(); + uint32_t num = fdp.ConsumeIntegralInRange(0, COUNT_MOD); DropLogicDeletedDataFuzz(tableName, num); - int count = fuzzerData.GetInt(); + uint32_t count = fdp.ConsumeIntegralInRange(0, COUNT_MOD); LockAndUnLockFuzz(tableName, count); } } @@ -371,8 +371,9 @@ void CombineClientFuzzTest(const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { OHOS::Setup(); - OHOS::CombineTest(data, size); - OHOS::CombineClientFuzzTest(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::CombineTest(fdp); + OHOS::CombineClientFuzzTest(fdp); OHOS::TearDown(); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn index 29eaa19893429edfd55414517ce5002afb130545..78afaaf723afe8d4a42e000b4b577a367413378c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("SyncFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -112,16 +105,14 @@ ohos_fuzztest("SyncFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/sync_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/sync_fuzzer.cpp index 6553bec8abde0d3e4c472a533f67cbec718ef6e3..b51ae7a2cac0796f46819e7a24611db722420550 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/sync_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/sync_fuzzer.cpp @@ -19,6 +19,7 @@ #include "db_common.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" +#include "fuzzer/FuzzedDataProvider.h" #include "virtual_communicator_aggregator.h" #include "kv_store_nb_delegate.h" #include "kv_virtual_device.h" @@ -28,7 +29,9 @@ namespace OHOS { using namespace DistributedDB; using namespace DistributedDBTest; - +static constexpr const int MOD = 1024; // 1024 is mod +static constexpr const int HUNDRED = 100; +static constexpr const int TEN = 10; /* Keep C++ file names the same as the class name. */ class SyncFuzzer { }; @@ -88,36 +91,37 @@ void TearDownTestCase() } } -std::vector CreateEntries(const uint8_t* data, size_t size, std::vector keys) +std::vector CreateEntries(FuzzedDataProvider &fdp, std::vector keys) { std::vector entries; // key'length is less than 1024. - auto count = static_cast(std::min(size, size_t(1024))); + auto count = fdp.ConsumeIntegralInRange(0, MOD); for (int i = 1; i < count; i++) { Entry entry; - entry.key = std::vector(data, data + i); + entry.key = fdp.ConsumeBytes(1); keys.push_back(entry.key); - entry.value = std::vector(data, data + size); + size_t size = fdp.ConsumeIntegralInRange(0, MOD); + entry.value = fdp.ConsumeBytes(size); entries.push_back(entry); } return entries; } -void NormalSyncPush(const uint8_t* data, size_t size, bool isWithQuery = false) +void NormalSyncPush(FuzzedDataProvider &fdp, bool isWithQuery = false) { SetUpTestcase(); if (g_kvDelegatePtr == nullptr) { return; } std::vector keys; - std::vector tmp = CreateEntries(data, size, keys); + std::vector tmp = CreateEntries(fdp, keys); g_kvDelegatePtr->PutBatch(tmp); std::vector devices; devices.push_back(g_deviceB->GetDeviceId()); std::map result; if (isWithQuery) { - int len = std::min(size, size_t(100)); - Key tmpKey = std::vector(data, data + len); + int len = fdp.ConsumeIntegralInRange(0, MOD); + Key tmpKey = fdp.ConsumeBytes(len); Query query = Query::Select().PrefixKey(tmpKey); DistributedDBToolsTest::SyncTestWithQuery(g_kvDelegatePtr, devices, SYNC_MODE_PUSH_ONLY, result, query); } else { @@ -126,14 +130,14 @@ void NormalSyncPush(const uint8_t* data, size_t size, bool isWithQuery = false) TearDownTestCase(); } -void NormalSyncPull(const uint8_t* data, size_t size, bool isWithQuery = false) +void NormalSyncPull(FuzzedDataProvider &fdp, bool isWithQuery = false) { SetUpTestcase(); if (g_kvDelegatePtr == nullptr) { return; } std::vector keys; - std::vector tmp = CreateEntries(data, size, keys); + std::vector tmp = CreateEntries(fdp, keys); g_kvDelegatePtr->PutBatch(tmp); int i = 0; for (auto &item : tmp) { @@ -149,8 +153,8 @@ void NormalSyncPull(const uint8_t* data, size_t size, bool isWithQuery = false) devices.push_back(g_deviceB->GetDeviceId()); std::map result; if (isWithQuery) { - int len = std::min(size, size_t(100)); - Key tmpKey = std::vector(data, data + len); + int len = fdp.ConsumeIntegralInRange(0, HUNDRED); + Key tmpKey = fdp.ConsumeBytes(len); Query query = Query::Select().PrefixKey(tmpKey); DistributedDBToolsTest::SyncTestWithQuery(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result, query); } else { @@ -159,21 +163,20 @@ void NormalSyncPull(const uint8_t* data, size_t size, bool isWithQuery = false) TearDownTestCase(); } -void NormalSyncPushAndPull(const uint8_t* data, size_t size, bool isWithQuery = false) +void NormalSyncPushAndPull(FuzzedDataProvider &fdp, bool isWithQuery = false) { SetUpTestcase(); if (g_kvDelegatePtr == nullptr) { return; } std::vector keys; - std::vector tmp = CreateEntries(data, size, keys); + std::vector tmp = CreateEntries(fdp, keys); g_kvDelegatePtr->PutBatch(tmp); std::vector devices; devices.push_back(g_deviceB->GetDeviceId()); std::map result; if (isWithQuery) { - int len = std::min(size, size_t(100)); - Key tmpKey = std::vector(data, data + len); + Key tmpKey = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, HUNDRED)); Query query = Query::Select().PrefixKey(tmpKey); DistributedDBToolsTest::SyncTestWithQuery(g_kvDelegatePtr, devices, SYNC_MODE_PUSH_PULL, result, query); } else { @@ -182,7 +185,7 @@ void NormalSyncPushAndPull(const uint8_t* data, size_t size, bool isWithQuery = TearDownTestCase(); } -void SubscribeOperation(const uint8_t* data, size_t size) +void SubscribeOperation(FuzzedDataProvider &fdp) { SetUpTestcase(); if (g_kvDelegatePtr == nullptr) { @@ -193,9 +196,11 @@ void SubscribeOperation(const uint8_t* data, size_t size) Query query2 = Query::Select().EqualTo("$.field_name1", 1).Limit(20, 0); g_kvDelegatePtr->SubscribeRemoteQuery(devices, nullptr, query2, true); std::set keys; - int count = std::min(size, size_t(3)); + int countMax = 3; + int count = fdp.ConsumeIntegralInRange(0, countMax); + int byteLen = 1; for (int i = 0; i < count; i++) { - Key tmpKey = std::vector(data + i, data + i + 1); + Key tmpKey = fdp.ConsumeBytes(byteLen); keys.insert(tmpKey); } Query query = Query::Select().InKeys(keys); @@ -205,49 +210,42 @@ void SubscribeOperation(const uint8_t* data, size_t size) TearDownTestCase(); } -void OtherOperation(const uint8_t* data, size_t size) +void OtherOperation(FuzzedDataProvider &fdp) { SetUpTestcase(); if (g_kvDelegatePtr == nullptr) { return; } - int len = std::min(size, size_t(10)); - std::string tmpIdentifier(data, data + len); + std::string tmpIdentifier = fdp.ConsumeRandomLengthString(TEN); std::vector targets; - int j = 0; - int count = std::min(size, size_t(4)); + int countMax = 4; + int count = fdp.ConsumeIntegralInRange(0, countMax); for (int i = 0; i < count; i++) { - std::string tmpStr(data + j, data + j + 1); - j = j + 10; // target size is 10 + std::string tmpStr = fdp.ConsumeBytesAsString(1); targets.push_back(tmpStr); - if ((1 + j) >= static_cast(size)) { - break; - } } g_kvDelegatePtr->SetEqualIdentifier(tmpIdentifier, targets); TearDownTestCase(); } -void PragmaOperation(const uint8_t* data, size_t size) +void PragmaOperation(FuzzedDataProvider &fdp) { SetUpTestcase(); if (g_kvDelegatePtr == nullptr) { return; } - bool autoSync = (size == 0) ? true : data[0]; + bool autoSync = fdp.ConsumeBool(); PragmaData praData = static_cast(&autoSync); g_kvDelegatePtr->Pragma(AUTO_SYNC, praData); PragmaDeviceIdentifier param1; - int len = std::min(size, size_t(100)); - std::string tmpStr(data, data + len); + std::string tmpStr = fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, HUNDRED)); param1.deviceID = tmpStr; PragmaData input = static_cast(¶m1); g_kvDelegatePtr->Pragma(GET_IDENTIFIER_OF_DEVICE, input); PragmaEntryDeviceIdentifier param2; - len = std::min(size, size_t(10)); // use min 10 - param2.key.assign(data, data + len); + param2.key = fdp.ConsumeBytes(TEN); param2.origDevice = false; input = static_cast(¶m2); g_kvDelegatePtr->Pragma(GET_DEVICE_IDENTIFIER_OF_ENTRY, input); @@ -256,11 +254,7 @@ void PragmaOperation(const uint8_t* data, size_t size) input = static_cast(&size2); g_kvDelegatePtr->Pragma(GET_QUEUED_SYNC_SIZE, input); - int limit = 1; // init 1 - if (size > sizeof(int)) { - auto *r = reinterpret_cast(data); - limit = *r; - } + int limit = fdp.ConsumeIntegral(); input = static_cast(&limit); g_kvDelegatePtr->Pragma(SET_QUEUED_SYNC_LIMIT, input); @@ -270,21 +264,21 @@ void PragmaOperation(const uint8_t* data, size_t size) TearDownTestCase(); } -void FuzzSync(const uint8_t* data, size_t size) +void FuzzSync(FuzzedDataProvider &fdp) { KvStoreConfig config; DistributedDBToolsTest::TestDirInit(config.dataDir); g_mgr.SetKvStoreConfig(config); InitEnv(); - NormalSyncPush(data, size); - NormalSyncPull(data, size); - NormalSyncPushAndPull(data, size); - NormalSyncPush(data, size, true); - NormalSyncPull(data, size, true); - NormalSyncPushAndPull(data, size, true); - SubscribeOperation(data, size); - OtherOperation(data, size); - PragmaOperation(data, size); + NormalSyncPush(fdp); + NormalSyncPull(fdp); + NormalSyncPushAndPull(fdp); + NormalSyncPush(fdp, true); + NormalSyncPull(fdp, true); + NormalSyncPushAndPull(fdp, true); + SubscribeOperation(fdp); + OtherOperation(fdp); + PragmaOperation(fdp); FinalizeEnv(); DistributedDBToolsTest::RemoveTestDbFiles(config.dataDir); } @@ -293,7 +287,8 @@ void FuzzSync(const uint8_t* data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - OHOS::FuzzSync(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::FuzzSync(fdp); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/moduletest/BUILD.gn index b7349f0c60835207a0db2e6bd1a5bae338ff8ec3..ba3825754f71f0ca739b964faa13ccf4f7389924 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/BUILD.gn @@ -49,13 +49,9 @@ config("module_private_config") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/interfaces/src", # "../adapter/include/communicator", - "//developtools/liblog", "common/distributeddb/include", "include", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata/include", - "//third_party/openssl/include/", ] defines = [ @@ -89,14 +85,15 @@ ohos_moduletest("DistributeddbKvTransactionTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -114,14 +111,15 @@ ohos_moduletest("DistributeddbKvTransactionPerfTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -137,14 +135,15 @@ ohos_moduletest("DistributeddbKvConcurrencyCrudTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -160,14 +159,15 @@ ohos_moduletest("DistributeddbKvBatchCrudTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -183,14 +183,15 @@ ohos_moduletest("DistributeddbKvCreateTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -206,14 +207,15 @@ ohos_moduletest("DistributeddbKvCrudTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -229,14 +231,15 @@ ohos_moduletest("DistributeddbKvObserverTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -252,14 +255,15 @@ ohos_moduletest("DistributeddbKvObserverSnapTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -274,14 +278,15 @@ ohos_moduletest("DistributeddbKvBackupTest") { sources += mul_sources configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -297,14 +302,15 @@ ohos_moduletest("DistributeddbKvRealdelTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -322,14 +328,15 @@ ohos_moduletest("DistributeddbNbCreateTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -346,14 +353,15 @@ ohos_moduletest("DistributeddbNbCrudTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -370,14 +378,15 @@ ohos_moduletest("DistributeddbNbObserverTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -396,14 +405,15 @@ ohos_moduletest("DistributeddbNbCursorTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -422,14 +432,15 @@ ohos_moduletest("DistributeddbNbBackupTest") { deps = [ "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -447,14 +458,15 @@ ohos_moduletest("DistributeddbNbBatchCrudTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -472,14 +484,15 @@ ohos_moduletest("DistributeddbNbLocalBatchCrudTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -496,14 +509,15 @@ ohos_moduletest("DistributeddbNbSchemaDbTest") { sources += mul_sources configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -521,14 +535,15 @@ ohos_moduletest("DistributeddbNbPredicateQueryTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -546,14 +561,15 @@ ohos_moduletest("DistributeddbNbPredicateQueryExpandTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -571,14 +587,15 @@ ohos_moduletest("DistributeddbNbAutolaunchTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -596,14 +613,15 @@ ohos_moduletest("DistributedbNbDbDamageTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -621,14 +639,15 @@ ohos_moduletest("DistributeddbNbCrudPowerTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -646,14 +665,15 @@ ohos_moduletest("DistributeddbNbSchemaTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -671,14 +691,15 @@ ohos_moduletest("DistributeddbNbSchemaUpgradeTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -686,13 +707,8 @@ ohos_moduletest("DistributeddbNbSchemaUpgradeTest") { ############################################################################### group("moduletest") { testonly = true - deps = [ - "//third_party/googletest:gmock", - "//third_party/googletest:gtest_main", - "//third_party/sqlite:sqlite", - ] - deps += [ + deps = [ ":DistributedbNbDbDamageTest", ":DistributeddbKvBackupTest", ":DistributeddbKvBatchCrudTest", diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/include/distributeddb_data_generator.h b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/include/distributeddb_data_generator.h index e348cc4981c0476a4370a262587662422c36261a..a6ebb8584db5bcd1adb4eaed9af9050f0d6872c7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/include/distributeddb_data_generator.h +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/include/distributeddb_data_generator.h @@ -430,8 +430,8 @@ const std::string IMAGE_VALUE_PRE = {"\"_id\":23,\"local_media_id\":0," \ "\"orientation\":0,\"latitude\":0,\"longitude\":0,\"datetaken\":1514792938000," \ "\"bucket_id\":771419238,\"bucket_display_name\":\"MagazineUnlock\",\"duration\":0," \ "\"resolution\":\"1440x2560\",\"media_type\":1,\"storage_id\":65537,\"width\":1440," \ - "\"height\":2560,\"is_hdr\":0,\"is_hw_privacy\":0,\"hw_voice_offset\":0,\"is_hw_favorite\":0," \ - "\"hw_image_refocus\":0,\"is_hw_burst\":0,\"hw_rectify_offset\":0,\"contenturi\":\"\"," \ + "\"height\":2560,\"is_hdr\":0,\"is_privacy\":0,\"voice_offset\":0,\"is_favorite\":0," \ + "\"image_refocus\":0,\"is_burst\":0,\"rectify_offset\":0,\"contenturi\":\"\"," \ "\"hash\":\"e46cf1bb4773421fbded2e2583fe7130\",\"special_file_list\":0,\"special_file_type\":0," \ "\"special_file_offset\":0,\"relative_bucket_id\":1793967153,\"albumId\":\"default-album-3\",\"fileType\":1," \ "\"fileId\":0,\"videoThumbId\":0,\"thumbId\":0,\"lcdThumbId\":0,\"thumbType\":3,\"localThumbPath\":\"\"," \ diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_constant.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_constant.cpp index 6c3b1187a41c56e4900d67013b75a95bb9267f80..923b21f406594cdb69b337823df2385a254ace3c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_constant.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_constant.cpp @@ -16,7 +16,7 @@ #include "distributeddb_nb_test_tools.h" namespace DistributedDBDataGenerator { -#ifndef HW_USING_LABEL_FUNC_IN_RELEASE_VERSION +#ifndef USING_LABEL_FUNC_IN_RELEASE_VERSION const std::string DistributedDBConstant::NB_DIRECTOR = "/data/test/nbstub/"; // default work dir. #else // default work dir by label in phone requested by fbe. diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/basic_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/basic_unit_test.cpp index c775dd2444240dc47e3baf5e23478898fd9f2a07..a7adbc01cc50d3db73cfae9fae96c6f431341fce 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/basic_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/basic_unit_test.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #include "basic_unit_test.h" +#include "platform_specific.h" namespace DistributedDB { using namespace testing::ext; @@ -35,6 +36,11 @@ void BasicUnitTest::TearDownTestCase() void BasicUnitTest::SetUp() { + if (OS::CheckPathExistence(g_testDir)) { // if test dir exist, delete it and printf log + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); + LOGE("[BasicUnitTest] The previous test case not clean db files."); + } + RuntimeContext::GetInstance()->ClearAllDeviceTimeInfo(); DistributedDBToolsUnitTest::PrintTestCaseInfo(); ASSERT_EQ(communicatorAggregator_, nullptr); communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); @@ -48,7 +54,10 @@ void BasicUnitTest::TearDown() LOGE("[BasicUnitTest] Rm test db files error."); } RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAdapter(nullptr); communicatorAggregator_ = nullptr; + RuntimeContext::GetInstance()->ClearAllDeviceTimeInfo(); + RuntimeContext::GetInstance()->SetTimeChanged(false); } int BasicUnitTest::InitDelegate(const StoreInfo &info, const std::string &deviceId) @@ -77,8 +86,10 @@ std::string BasicUnitTest::GetDevice(const StoreInfo &info) const std::lock_guard autoLock(deviceMutex_); auto iter = deviceMap_.find(info); if (iter == deviceMap_.end()) { - LOGW("[BasicUnitTest] Not exist device app %s store %s user %s", info.appId.c_str(), - info.storeId.c_str(), info.userId.c_str()); + LOGW("[BasicUnitTest] Not exist device app %s store %s user %s", + info.appId.c_str(), + info.storeId.c_str(), + info.userId.c_str()); return ""; } return iter->second; @@ -88,7 +99,56 @@ void BasicUnitTest::SetDevice(const StoreInfo &info, const std::string &device) { std::lock_guard autoLock(deviceMutex_); deviceMap_[info] = device; - LOGW("[BasicUnitTest] Set device app %s store %s user %s device %s", info.appId.c_str(), - info.storeId.c_str(), info.userId.c_str(), device.c_str()); + LOGW("[BasicUnitTest] Set device app %s store %s user %s device %s", + info.appId.c_str(), + info.storeId.c_str(), + info.userId.c_str(), + device.c_str()); +} + +StoreInfo BasicUnitTest::GetStoreInfo1() +{ + StoreInfo info; + info.userId = DistributedDBUnitTest::USER_ID; + info.storeId = DistributedDBUnitTest::STORE_ID_1; + info.appId = DistributedDBUnitTest::APP_ID; + return info; +} + +StoreInfo BasicUnitTest::GetStoreInfo2() +{ + StoreInfo info; + info.userId = DistributedDBUnitTest::USER_ID; + info.storeId = DistributedDBUnitTest::STORE_ID_2; + info.appId = DistributedDBUnitTest::APP_ID; + return info; +} + +StoreInfo BasicUnitTest::GetStoreInfo3() +{ + StoreInfo info; + info.userId = DistributedDBUnitTest::USER_ID; + info.storeId = DistributedDBUnitTest::STORE_ID_3; + info.appId = DistributedDBUnitTest::DISTRIBUTED_APP_ID; + return info; +} + +void BasicUnitTest::SetProcessCommunicator(const std::shared_ptr &processCommunicator) +{ + processCommunicator_ = processCommunicator; +} + +uint64_t BasicUnitTest::GetAllSendMsgSize() const +{ + if (communicatorAggregator_ == nullptr) { + return 0u; + } + return communicatorAggregator_->GetAllSendMsgSize(); +} + +void BasicUnitTest::RegBeforeDispatch(const std::function &beforeDispatch) +{ + ASSERT_NE(communicatorAggregator_, nullptr); + communicatorAggregator_->RegBeforeDispatch(beforeDispatch); } -} \ No newline at end of file +} // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/basic_unit_test.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/basic_unit_test.h index 0dfa21ac18c10876250e7d635cf086c33603bbf9..240b4ac4597012d9b78f86119a9dc937d9621fc8 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/basic_unit_test.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/basic_unit_test.h @@ -35,17 +35,18 @@ protected: virtual int CloseDelegate(const StoreInfo &info) = 0; virtual void CloseAllDelegate() = 0; std::string GetDevice(const StoreInfo &info) const; + void SetProcessCommunicator(const std::shared_ptr &processCommunicator); + uint64_t GetAllSendMsgSize() const; + void RegBeforeDispatch(const std::function &beforeDispatch); + static StoreInfo GetStoreInfo1(); + static StoreInfo GetStoreInfo2(); + static StoreInfo GetStoreInfo3(); void SetDevice(const StoreInfo &info, const std::string &device); static std::string GetTestDir(); - struct StoreComparator { - bool operator() (const StoreInfo &source, const StoreInfo &target) const - { - return source.userId < target.userId || source.appId < target.appId || source.storeId < target.storeId; - } - }; VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; + std::shared_ptr processCommunicator_ = nullptr; mutable std::mutex deviceMutex_; - std::map deviceMap_; + std::map deviceMap_; }; } #endif // BASIC_UNIT_TEST_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_auto_launch_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_auto_launch_test.cpp index 080be5722a06306c8198850f1755a0dd749048b2..1e32140592de36add5b8ee5e84ad5f1af50e541b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_auto_launch_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_auto_launch_test.cpp @@ -201,7 +201,7 @@ static void SetLifeCycleTime(const KvDBProperties &prop) * @tc.name: AutoLaunch001 * @tc.desc: basic enable/disable func * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch001, TestSize.Level3) @@ -256,7 +256,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch001, TestSize.Level3) * @tc.name: AutoLaunch002 * @tc.desc: online callback * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch002, TestSize.Level3) @@ -333,7 +333,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch002, TestSize.Level3) * @tc.name: AutoLaunch003 * @tc.desc: CommunicatorLackCallback * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch003, TestSize.Level3) @@ -410,7 +410,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch003, TestSize.Level3) * @tc.name: AutoLaunch004 * @tc.desc: basic enable/disable func * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch004, TestSize.Level3) @@ -477,7 +477,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch004, TestSize.Level3) * @tc.name: AutoLaunch005 * @tc.desc: online device before enable * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch005, TestSize.Level3) @@ -549,7 +549,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch005, TestSize.Level3) * @tc.name: AutoLaunch006 * @tc.desc: online callback * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch006, TestSize.Level3) @@ -662,7 +662,7 @@ bool AutoLaunchCallBackBadParam(const std::string &identifier, AutoLaunchParam & * @tc.name: AutoLaunch007 * @tc.desc: enhancement callback return true * @tc.type: FUNC - * @tc.require: AR000EPARJ + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch007, TestSize.Level3) @@ -726,7 +726,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch007, TestSize.Level3) * @tc.name: AutoLaunch008 * @tc.desc: enhancement callback return false * @tc.type: FUNC - * @tc.require: AR000EPARJ + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch008, TestSize.Level3) @@ -765,7 +765,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch008, TestSize.Level3) * @tc.name: AutoLaunch009 * @tc.desc: enhancement callback return bad param * @tc.type: FUNC - * @tc.require: AR000EPARJ + * @tc.require: */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch009, TestSize.Level3) { @@ -806,7 +806,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch009, TestSize.Level3) * @tc.name: AutoLaunch010 * @tc.desc: enhancement nullptr callback * @tc.type: FUNC - * @tc.require: AR000EPARJ + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch010, TestSize.Level3) @@ -846,7 +846,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch010, TestSize.Level3) * @tc.name: AutoLaunch011 * @tc.desc: enhancement GetKvStoreIdentifier * @tc.type: FUNC - * @tc.require: AR000EPARJ + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch011, TestSize.Level3) @@ -863,7 +863,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch011, TestSize.Level3) * @tc.name: AutoLaunch012 * @tc.desc: CommunicatorLackCallback * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch012, TestSize.Level3) @@ -937,7 +937,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch012, TestSize.Level3) * @tc.name: AutoLaunch013 * @tc.desc: online callback * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch013, TestSize.Level3) @@ -1023,7 +1023,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch013, TestSize.Level3) * @tc.name: AutoLaunch014 * @tc.desc: enhancement callback and release auto launch connection * @tc.type: FUNC - * @tc.require: AR000I0EKP + * @tc.require: */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch014, TestSize.Level3) { @@ -1075,7 +1075,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch014, TestSize.Level3) * @tc.name: AutoLaunch015 * @tc.desc: release auto launch connection when autolaunch execute * @tc.type: FUNC - * @tc.require: AR000I0EKP + * @tc.require: */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch015, TestSize.Level3) { @@ -1152,3 +1152,32 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunchRelational001, TestSize.Leve mode = std::static_pointer_cast(ptr)->GetDistributedTableMode(); EXPECT_EQ(mode, DistributedTableMode::COLLABORATION); } + +void GetAutoLaunchPropertiesTest(DBTypeInner type) +{ + AutoLaunchOption defaultOption; + defaultOption.compressionRate = 100; // compress rate is 100 + AutoLaunchParam param = {USER_ID, APP_ID, STORE_ID_0, defaultOption, nullptr, "", ""}; + std::shared_ptr ptr; + int errCode = AutoLaunch::GetAutoLaunchProperties(param, type, false, ptr); + ASSERT_EQ(errCode, E_OK); + ASSERT_NE(ptr, nullptr); + EXPECT_EQ(ptr->GetIntProp(DBProperties::COMPRESSION_RATE, 0), 0); + param.option.isNeedCompressOnSync = true; + errCode = AutoLaunch::GetAutoLaunchProperties(param, type, false, ptr); + ASSERT_EQ(errCode, E_OK); + ASSERT_NE(ptr, nullptr); + EXPECT_EQ(ptr->GetIntProp(DBProperties::COMPRESSION_RATE, 0), defaultOption.compressionRate); +} + +/** + * @tc.name: GetAutoLaunchProperties001 + * @tc.desc: test GetAutoLaunchProperties will give back the correct tableMode + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBAutoLaunchUnitTest, GetAutoLaunchProperties001, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(GetAutoLaunchPropertiesTest(DBTypeInner::DB_KV)); + ASSERT_NO_FATAL_FAILURE(GetAutoLaunchPropertiesTest(DBTypeInner::DB_RELATION)); +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp index 797bb30b941ddd65da96dd3553fc8680c49dec28..468af7d1d982fa5fd8a9efb9e4e905cf423c210b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp @@ -78,7 +78,7 @@ void DistributedDBCommonTest::TearDown(void) * @tc.name: RemoveAllFilesOfDirectory * @tc.desc: Test delete all file and dir. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, RemoveAllFilesOfDirectory, TestSize.Level1) @@ -118,7 +118,7 @@ HWTEST_F(DistributedDBCommonTest, InvalidArgsTest001, TestSize.Level1) * @tc.name: SameProcessReLockFile * @tc.desc: Test same process repeat lock same file. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, SameProcessReLockFile, TestSize.Level1) @@ -149,7 +149,7 @@ HWTEST_F(DistributedDBCommonTest, SameProcessReLockFile, TestSize.Level1) * @tc.name: SameProcessReUnLockFile * @tc.desc: Test same process repeat lock same file. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, SameProcessReUnLockFile, TestSize.Level1) @@ -175,7 +175,7 @@ HWTEST_F(DistributedDBCommonTest, SameProcessReUnLockFile, TestSize.Level1) * @tc.name: CalcFileSizeTest * @tc.desc: Test the file size for function test and the performance test. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBCommonTest, CalcFileSizeTest, TestSize.Level1) @@ -216,7 +216,7 @@ void createStepFlag(int step) * @tc.name: DiffProcessLockFile * @tc.desc: Test different process repeat lock same file. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, DiffProcessLockFile, TestSize.Level1) @@ -251,7 +251,7 @@ HWTEST_F(DistributedDBCommonTest, DiffProcessLockFile, TestSize.Level1) * @tc.name: DiffProcessLockFileBlocked * @tc.desc: Test different process repeat lock same file. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, DiffProcessLockFileBlocked, TestSize.Level1) @@ -293,7 +293,7 @@ HWTEST_F(DistributedDBCommonTest, DiffProcessLockFileBlocked, TestSize.Level1) * @tc.name: DiffProcessGetDBBlocked * @tc.desc: Test block other process get kvstore when db locked. * @tc.type: FUNC - * @tc.require: AR000CQDV7 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, DiffProcessGetDBBlocked, TestSize.Level1) @@ -338,7 +338,7 @@ HWTEST_F(DistributedDBCommonTest, DiffProcessGetDBBlocked, TestSize.Level1) * @tc.name: DiffProcessDeleteDBBlocked * @tc.desc: Test block other process delete kvstore when db locked. * @tc.type: FUNC - * @tc.require: AR000CQDV7 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, DiffProcessDeleteDBBlocked, TestSize.Level1) @@ -386,7 +386,7 @@ HWTEST_F(DistributedDBCommonTest, DiffProcessDeleteDBBlocked, TestSize.Level1) * @tc.name: DiffProcessGetDBBlocked001 * @tc.desc: Test block other process get kvstore when db locked. * @tc.type: FUNC - * @tc.require: AR000CQDV7 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, DiffProcessGetDBBlocked001, TestSize.Level1) @@ -432,7 +432,7 @@ HWTEST_F(DistributedDBCommonTest, DiffProcessGetDBBlocked001, TestSize.Level1) * @tc.name: DiffProcessGetDB * @tc.desc: Test block other process get kvstore. * @tc.type: FUNC - * @tc.require: AR000CQDV7 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, DiffProcessGetDB, TestSize.Level1) @@ -467,7 +467,7 @@ HWTEST_F(DistributedDBCommonTest, DiffProcessGetDB, TestSize.Level1) * @tc.name: DiffProcessDeleteDB * @tc.desc: Test block other process delete kvstore. * @tc.type: FUNC - * @tc.require: AR000CQDV7 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, DiffProcessDeleteDB, TestSize.Level1) @@ -505,7 +505,7 @@ HWTEST_F(DistributedDBCommonTest, DiffProcessDeleteDB, TestSize.Level1) * @tc.name: DiffProcessGetAndDeleteDB * @tc.desc: Test block other process delete kvstore. * @tc.type: FUNC - * @tc.require: AR000CQDV7 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, DiffProcessGetAndDeleteDB, TestSize.Level1) @@ -567,7 +567,7 @@ HWTEST_F(DistributedDBCommonTest, PerformanceAnalysisTest001, TestSize.Level1) t1.join(); t2.join(); } - EXPECT_EQ(count1, count1); + EXPECT_EQ(count2, threadCount); EXPECT_EQ(count1, threadCount); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_compression_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_compression_test.cpp index 1d48c7a6d6ef355daf2388ff4d6b8536208971dc..204da2a74fd4aa3bda4205187238dc5b2758c857 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_compression_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_compression_test.cpp @@ -80,7 +80,7 @@ void DistributedDBDataCompressionTest::TearDown(void) * @tc.name: DataCompression1 * @tc.desc: To test the function compress and uncompress works well in normal situation. * @tc.type: FUNC - * @tc.require: AR000G3QTT + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBDataCompressionTest, DataCompression1, TestSize.Level1) @@ -112,7 +112,7 @@ HWTEST_F(DistributedDBDataCompressionTest, DataCompression1, TestSize.Level1) * @tc.name: DataCompression2 * @tc.desc: To test uncompress failed when compressed is destroyed. * @tc.type: FUNC - * @tc.require: AR000G3QTT + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBDataCompressionTest, DataCompression2, TestSize.Level1) @@ -149,7 +149,7 @@ HWTEST_F(DistributedDBDataCompressionTest, DataCompression2, TestSize.Level1) * @tc.desc: To test uncompress works when bufferLen is larger but under 30M limit, and uncompress failed when bufferLen is beyond the 30M limit. * @tc.type: FUNC - * @tc.require: AR000G3QTT + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBDataCompressionTest, DataCompression3, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.h index 259d7a481c0f39130f3a28d895132852e248a67f..e1901797fb92240cc8c2d7f8ff92bc001adf47d5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.h @@ -24,6 +24,7 @@ namespace DistributedDBUnitTest { // define some variables to init a KvStoreDelegateManager object. const std::string APP_ID = "app0"; +const std::string DISTRIBUTED_APP_ID = "distributeddata"; const std::string SCHEMA_APP_ID = "app1"; const std::string USER_ID = "user0"; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_json_precheck_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_json_precheck_unit_test.cpp index 2182da8b1731d39107dbb8b590ddf8f1027f5b2a..b445cadd16f13ebef9997ac38bc3f1282b4bf4d9 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_json_precheck_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_json_precheck_unit_test.cpp @@ -92,7 +92,7 @@ void DistributedDBJsonPrecheckUnitTest::SetUp() * @tc.name: Precheck Valid String 001 * @tc.desc: json string is legal * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseValidString001, TestSize.Level1) @@ -111,15 +111,20 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseValidString001, TestSize.Level1 * @tc.expected: step2. Parsing result failed. */ JsonObject tempObj; + LOGI("ori json is %s", JSON_STRING1.c_str()); int stepTwo = tempObj.Parse(JSON_STRING1); EXPECT_TRUE(stepTwo != E_OK); + std::string json = R"([{"field1":"123"}])"; + std::vector data(json.begin(), json.end()); + EXPECT_EQ(tempObj.Parse(data), -E_JSON_PARSE_FAIL); + EXPECT_EQ(tempObj.Parse(json), -E_JSON_PARSE_FAIL); } /** * @tc.name: Precheck Valid String 002 * @tc.desc: json string is legal * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseValidString002, TestSize.Level1) @@ -138,6 +143,7 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseValidString002, TestSize.Level1 * @tc.expected: step2. Parsing result success. */ JsonObject tempObj; + LOGI("ori json is %s", JSON_STRING3.c_str()); int stepTwo = tempObj.Parse(JSON_STRING3); EXPECT_TRUE(stepTwo == E_OK); } @@ -146,7 +152,7 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseValidString002, TestSize.Level1 * @tc.name: Precheck invalid String 001 * @tc.desc: The json string has been detected illegal before exceeding the specified nesting depth. * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString001, TestSize.Level1) @@ -156,6 +162,7 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString001, TestSize.Leve * @tc.expected: step1. Parsing result failed. */ JsonObject tempObj; + LOGI("ori json is %s", JSON_STRING2.c_str()); int stepOne = tempObj.Parse(JSON_STRING2); EXPECT_TRUE(stepOne != E_OK); } @@ -164,7 +171,7 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString001, TestSize.Leve * @tc.name: Precheck invalid String 002 * @tc.desc: The json string has been detected illegal before exceeding the specified nesting depth. * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString002, TestSize.Level1) @@ -174,6 +181,7 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString002, TestSize.Leve * @tc.expected: step1. Parsing result failed. */ JsonObject tempObj; + LOGI("ori json is %s", JSON_STRING4.c_str()); int stepOne = tempObj.Parse(JSON_STRING4); EXPECT_TRUE(stepOne != E_OK); } @@ -182,7 +190,7 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString002, TestSize.Leve * @tc.name: Precheck invalid String 003 * @tc.desc: The json string has been detected illegal before exceeding the specified nesting depth. * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString003, TestSize.Level1) @@ -192,6 +200,7 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString003, TestSize.Leve * @tc.expected: step1. return value > 10. */ int errCode = E_OK; + LOGI("ori json is %s", JSON_STRING5.c_str()); int stepOne = static_cast(JsonObject::CalculateNestDepth(JSON_STRING5, errCode)); EXPECT_TRUE(errCode == E_OK); EXPECT_TRUE(stepOne > MAX_DEPTH_FOR_TEST); @@ -204,4 +213,244 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString003, TestSize.Leve int stepTwo = tempObj.Parse(JSON_STRING5); EXPECT_TRUE(stepTwo != E_OK); } + +/** + * @tc.name: ParseDuplicativeString001 + * @tc.desc: The json string has more than one field with same name. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseDuplicativeString001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Parse json. + * @tc.expected: step1. return ok. + */ + std::string json = R"({"field1":"123", "field2": true, "field1": 123})"; + LOGI("ori json is %s", json.c_str()); + JsonObject object; + EXPECT_EQ(object.JsonObject::Parse(json), E_OK); + /** + * @tc.steps: step2. Check field. + * @tc.expected: step2. field1 is 123, field2 is True. + */ + FieldValue value; + EXPECT_EQ(object.GetFieldValueByFieldPath({"field1"}, value), E_OK); + EXPECT_EQ(value.integerValue, 123); + EXPECT_EQ(object.GetFieldValueByFieldPath({"field2"}, value), E_OK); + EXPECT_TRUE(value.boolValue); +} + +/** + * @tc.name: ParseString001 + * @tc.desc: Parse none obj json string. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseString001, TestSize.Level0) +{ + std::string nonJson = R"("field1":123)"; + LOGI("ori json is %s", nonJson.c_str()); + JsonObject object; + std::vector data(nonJson.begin(), nonJson.end()); + EXPECT_EQ(object.Parse(data), -E_JSON_PARSE_FAIL); + EXPECT_TRUE(object.ToString().empty()); +} + +/** + * @tc.name: ParseString002 + * @tc.desc: Parse double and long. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseString002, TestSize.Level0) +{ + std::string json = R"({"field1":429496729500, "field2":11.1})"; + LOGI("ori json is %s", json.c_str()); + JsonObject object; + std::vector data(json.begin(), json.end()); + EXPECT_EQ(object.Parse(data), E_OK); + FieldValue value; + EXPECT_EQ(object.GetFieldValueByFieldPath({"field1"}, value), E_OK); + EXPECT_EQ(value.longValue, 429496729500); + EXPECT_EQ(object.GetFieldValueByFieldPath({"field2"}, value), E_OK); + EXPECT_NE(value.doubleValue, 0); +} + +/** + * @tc.name: ParseString003 + * @tc.desc: Parse obj. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseString003, TestSize.Level0) +{ + std::string json = R"({"field1":42949672950, "field2":{"field3":123}})"; + LOGI("ori json is %s", json.c_str()); + JsonObject object; + std::vector data(json.begin(), json.end()); + EXPECT_EQ(object.Parse(data), E_OK); + std::set outSubPath; + std::map outSubPathType; + EXPECT_EQ(object.GetSubFieldPath({"field1"}, outSubPath), -E_NOT_SUPPORT); + EXPECT_EQ(object.GetSubFieldPathAndType({"field1"}, outSubPathType), -E_NOT_SUPPORT); + EXPECT_EQ(object.GetSubFieldPath({"field2"}, outSubPath), E_OK); + EXPECT_EQ(object.GetSubFieldPathAndType({"field2"}, outSubPathType), E_OK); + std::set actualPath = {{"field2", "field3"}}; + EXPECT_EQ(outSubPath, actualPath); + FieldPath inPath; + EXPECT_EQ(object.GetSubFieldPath(inPath, outSubPath), E_OK); + EXPECT_EQ(object.GetSubFieldPathAndType(inPath, outSubPathType), E_OK); +} + +/** + * @tc.name: ParseString004 + * @tc.desc: Parse array. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseString004, TestSize.Level0) +{ + std::string json = R"({"field1":["123"], "field3":"field3"})"; + LOGI("ori json is %s", json.c_str()); + JsonObject object; + std::vector data(json.begin(), json.end()); + EXPECT_EQ(object.Parse(data), E_OK); + size_t size = 0u; + EXPECT_EQ(object.GetArraySize({"field3"}, size), -E_NOT_SUPPORT); + EXPECT_EQ(object.GetArraySize({"field1"}, size), E_OK); + EXPECT_EQ(size, 1u); + FieldPath inPath; + EXPECT_EQ(object.GetArraySize(inPath, size), -E_NOT_SUPPORT); + std::vector> content; + EXPECT_EQ(object.GetArrayContentOfStringOrStringArray({"field1"}, content), E_OK); + std::vector> actual = {{"123"}}; + EXPECT_EQ(content, actual); + EXPECT_EQ(object.GetArrayContentOfStringOrStringArray(inPath, content), -E_NOT_SUPPORT); +} + +/** + * @tc.name: ParseString005 + * @tc.desc: Parse array. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseString005, TestSize.Level0) +{ + std::string json = R"({"field1":["123", null, ["456", 789]], "field3":"field3"})"; + LOGI("ori json is %s", json.c_str()); + JsonObject object; + EXPECT_EQ(object.Parse(json), E_OK); + std::vector> content; + EXPECT_EQ(object.GetArrayContentOfStringOrStringArray({"field1"}, content), -E_NOT_SUPPORT); + + json = R"({"field1":[["456", "789"], []], "field3":"field3"})"; + object = {}; + EXPECT_EQ(object.Parse(json), E_OK); + EXPECT_EQ(object.GetArrayContentOfStringOrStringArray({"field1"}, content), E_OK); + EXPECT_EQ(content.size(), 1u); +} + +/** + * @tc.name: BuildObj001 + * @tc.desc: Build json obj. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, BuildObj001, TestSize.Level0) +{ + LOGI("ori json is empty"); + JsonObject obj; + FieldValue val; + val.boolValue = true; + EXPECT_EQ(obj.InsertField({"bool_field"}, FieldType::LEAF_FIELD_BOOL, val), E_OK); + val.stringValue = "str"; + EXPECT_EQ(obj.InsertField({"str_field"}, FieldType::LEAF_FIELD_STRING, val), E_OK); + val.integerValue = INT32_MAX; + EXPECT_EQ(obj.InsertField({"int_field"}, FieldType::LEAF_FIELD_INTEGER, val), E_OK); + val.longValue = INT64_MAX; + EXPECT_EQ(obj.InsertField({"long_field"}, FieldType::LEAF_FIELD_LONG, val), E_OK); + val.doubleValue = 3.1415; + EXPECT_EQ(obj.InsertField({"double_field"}, FieldType::LEAF_FIELD_DOUBLE, val), E_OK); + EXPECT_EQ(obj.InsertField({"null_field"}, FieldType::LEAF_FIELD_NULL, val), E_OK); + EXPECT_EQ(obj.InsertField({"array_field"}, FieldType::LEAF_FIELD_ARRAY, val), -E_INVALID_ARGS); + EXPECT_EQ(obj.InsertField({"obj_field"}, FieldType::LEAF_FIELD_OBJECT, val), E_OK); + EXPECT_EQ(obj.InsertField({"array_field"}, FieldType::LEAF_FIELD_OBJECT, val), E_OK); + EXPECT_EQ(obj.InsertField({"array_field", "array_inner"}, FieldType::LEAF_FIELD_OBJECT, val), E_OK); + EXPECT_EQ(obj.InsertField({"array_field", "array_inner", "inner"}, FieldType::LEAF_FIELD_OBJECT, val), E_OK); + EXPECT_EQ(obj.DeleteField({"obj_field"}), E_OK); + LOGI("json is %s", obj.ToString().c_str()); +} + +/** + * @tc.name: BuildObj002 + * @tc.desc: Build json obj. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, BuildObj002, TestSize.Level0) +{ + std::string json = R"({"array_field":[]})"; + LOGI("ori json is %s", json.c_str()); + JsonObject obj; + EXPECT_EQ(obj.Parse(json), E_OK); + FieldValue val; + val.stringValue = "str"; + EXPECT_EQ(obj.InsertField({"array_field1"}, FieldType::LEAF_FIELD_STRING, val, true), E_OK); + EXPECT_EQ(obj.InsertField({"array_field2"}, FieldType::LEAF_FIELD_STRING, val), E_OK); + EXPECT_EQ(obj.InsertField({"array_field"}, FieldType::LEAF_FIELD_STRING, val, true), E_OK); + EXPECT_EQ(obj.InsertField({"array_field"}, FieldType::LEAF_FIELD_STRING, val), E_OK); + LOGI("json is %s", obj.ToString().c_str()); +} + +/** + * @tc.name: BuildObj003 + * @tc.desc: Build json obj by insert invalid obj. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, BuildObj003, TestSize.Level0) +{ + JsonObject invalidOriObj; + JsonObject invalidInsertObj; + EXPECT_EQ(invalidOriObj.InsertField({}, invalidInsertObj), -E_INVALID_ARGS); + JsonObject validInsertObj; + std::string json = R"({"field1":"field1Val"})"; + validInsertObj.Parse(json); + EXPECT_EQ(invalidOriObj.InsertField({}, validInsertObj), -E_INVALID_ARGS); + FieldPath invalidPath; + invalidPath.resize(101); // 101 is invalid depth + EXPECT_EQ(invalidOriObj.InsertField(invalidPath, invalidInsertObj), -E_INVALID_ARGS); + EXPECT_EQ(invalidOriObj.InsertField(invalidPath, validInsertObj), -E_INVALID_ARGS); +} + +/** + * @tc.name: BuildObj004 + * @tc.desc: Build json valid obj by insert valid obj. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, BuildObj004, TestSize.Level0) +{ + JsonObject validOriObj; + std::string json = R"({"field1":"field1Val", "array":[]})"; + validOriObj.Parse(json); + JsonObject insertVal; + insertVal.Parse(json); + EXPECT_EQ(validOriObj.InsertField({"field2"}, insertVal), E_OK); + JsonObject inValidOriObj; + EXPECT_EQ(inValidOriObj.InsertField({"field2"}, insertVal), E_OK); + EXPECT_EQ(validOriObj.InsertField({"array"}, insertVal), E_OK); + EXPECT_EQ(validOriObj.InsertField({"array"}, insertVal, false), E_OK); + EXPECT_EQ(validOriObj.InsertField({"field3"}, insertVal, false), E_OK); + EXPECT_EQ(validOriObj.InsertField({"field1"}, insertVal), -E_JSON_INSERT_PATH_EXIST); +} #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_notification_chain_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_notification_chain_test.cpp index 7208d44505ee235e9503d3f0668cd56d118c0fbf..d55f8dfb9587681229f0f69d0152899aa5fe1a6f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_notification_chain_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_notification_chain_test.cpp @@ -100,7 +100,7 @@ void DistributedDBNotificationChainTest::TearDown(void) * @tc.name: RegisterEvent001 * @tc.desc: Register an exits event. * @tc.type: FUNC - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBNotificationChainTest, RegisterEvent001, TestSize.Level0) @@ -117,7 +117,7 @@ HWTEST_F(DistributedDBNotificationChainTest, RegisterEvent001, TestSize.Level0) * @tc.name: RegisterListener001 * @tc.desc: Register and unregister a listener. * @tc.type: FUNC - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBNotificationChainTest, RegisterListener001, TestSize.Level0) @@ -144,7 +144,7 @@ HWTEST_F(DistributedDBNotificationChainTest, RegisterListener001, TestSize.Level * @tc.name: NotifyEvent001 * @tc.desc: notify an event to listener. * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBNotificationChainTest, NotifyEvent001, TestSize.Level0) @@ -172,7 +172,7 @@ HWTEST_F(DistributedDBNotificationChainTest, NotifyEvent001, TestSize.Level0) * @tc.name: UnRegisterEvent001 * @tc.desc: unregister a invalid event. * @tc.type: FUNC - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBNotificationChainTest, UnRegisterEvent001, TestSize.Level0) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_parcel_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_parcel_unit_test.cpp index 4a95864e05c01053d6c4920d7df72cea59a56033..d57d4dec94d041dee82916430c27248942cfce6d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_parcel_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_parcel_unit_test.cpp @@ -53,7 +53,7 @@ void DistributedDBParcelTest::TearDown(void) * @tc.name: WriteInt001 * @tc.desc: write and read a integer. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteInt001, TestSize.Level1) @@ -110,7 +110,7 @@ HWTEST_F(DistributedDBParcelTest, WriteInt001, TestSize.Level1) * @tc.name: WriteVector001 * @tc.desc: write and read a vector. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector001, TestSize.Level1) @@ -145,7 +145,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector001, TestSize.Level1) * @tc.name: WriteVector002 * @tc.desc: write and read an empty vector. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector002, TestSize.Level1) @@ -180,7 +180,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector002, TestSize.Level1) * @tc.name: WriteVector003 * @tc.desc: write and read a vector. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector003, TestSize.Level1) @@ -215,7 +215,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector003, TestSize.Level1) * @tc.name: WriteVector004 * @tc.desc: write and read an empty vector. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector004, TestSize.Level1) @@ -250,7 +250,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector004, TestSize.Level1) * @tc.name: WriteVector005 * @tc.desc: write and read a vector. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector005, TestSize.Level1) @@ -286,7 +286,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector005, TestSize.Level1) * @tc.name: WriteVector006 * @tc.desc: write and read an empty vector. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector006, TestSize.Level1) @@ -321,7 +321,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector006, TestSize.Level1) * @tc.name: WriteVector007 * @tc.desc: write and read a vector, insert a wrong len. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector007, TestSize.Level1) @@ -361,7 +361,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector007, TestSize.Level1) * @tc.name: WriteVector008 * @tc.desc: write and read a vector, insert a wrong len. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector008, TestSize.Level1) @@ -401,7 +401,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector008, TestSize.Level1) * @tc.name: WriteVector009 * @tc.desc: write and read a vector, insert a wrong len. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector009, TestSize.Level1) @@ -443,7 +443,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector009, TestSize.Level1) * @tc.name: WriteVector010 * @tc.desc: write and read a vector, vector len is INT_MAX. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector010, TestSize.Level2) @@ -469,7 +469,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector010, TestSize.Level2) * @tc.name: WriteString001 * @tc.desc: write and read a string normally. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteString001, TestSize.Level1) @@ -503,7 +503,7 @@ HWTEST_F(DistributedDBParcelTest, WriteString001, TestSize.Level1) * @tc.name: WriteString002 * @tc.desc: write and read a string, insert a wrong len. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteString002, TestSize.Level1) @@ -543,7 +543,7 @@ HWTEST_F(DistributedDBParcelTest, WriteString002, TestSize.Level1) * @tc.name: WriteString003 * @tc.desc: write and read a string, insert a wrong len. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteString003, TestSize.Level1) @@ -583,7 +583,7 @@ HWTEST_F(DistributedDBParcelTest, WriteString003, TestSize.Level1) * @tc.name: WriteString004 * @tc.desc: write and read a string, string is empty. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteString004, TestSize.Level1) @@ -617,7 +617,7 @@ HWTEST_F(DistributedDBParcelTest, WriteString004, TestSize.Level1) * @tc.name: WriteString005 * @tc.desc: write and read a string, insert a INT_MAX len. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteString005, TestSize.Level1) @@ -657,7 +657,7 @@ HWTEST_F(DistributedDBParcelTest, WriteString005, TestSize.Level1) * @tc.name: WriteString006 * @tc.desc: write and read a string, string size is INT_MAX. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteString006, TestSize.Level2) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp index e1ea4bc8fca6df24e4f8e5f4e60582aaa1f3efc4..31f6b798d3c158390473148d36e5441c084171ac 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp @@ -291,7 +291,7 @@ void DistributedDBRelationalSchemaObjectTest::TearDown() * @tc.name: RelationalSchemaParseTest001 * @tc.desc: Test relational schema parse from json string * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest001, TestSize.Level1) @@ -319,7 +319,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest001, * @tc.name: RelationalSchemaParseTest002 * @tc.desc: Test relational schema parse from invalid json string * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest002, TestSize.Level1) @@ -385,7 +385,7 @@ std::string GenerateFromTableStr(const std::string &tableStr) * @tc.name: RelationalSchemaParseTest003 * @tc.desc: Test relational schema parse from invalid json string * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest003, TestSize.Level1) @@ -534,7 +534,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest007, * @tc.name: RelationalSchemaCompareTest001 * @tc.desc: Test relational schema negotiate with same schema string * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest001, TestSize.Level1) @@ -554,7 +554,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest001 * @tc.name: RelationalSchemaCompareTest002 * @tc.desc: Test relational schema v2.1 negotiate with same schema string * @tc.type: FUNC - * @tc.require: AR000H2PKN + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest002, TestSize.Level1) @@ -574,7 +574,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest002 * @tc.name: RelationalSchemaCompareTest003 * @tc.desc: Test relational schema v2.1 negotiate with schema v2.0 * @tc.type: FUNC - * @tc.require: AR000H2PKN + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest003, TestSize.Level1) @@ -592,7 +592,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest003 * @tc.name: RelationalSchemaCompareTest004 * @tc.desc: Test relational schema v2.0 negotiate with schema v2.1 * @tc.type: FUNC - * @tc.require: AR000H2PKN + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest004, TestSize.Level1) @@ -610,7 +610,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest004 * @tc.name: RelationalSchemaCompareTest005 * @tc.desc: Test collaboration relational schema negotiate with other table mode * @tc.type: FUNC - * @tc.require: AR000H2PKN + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest005, TestSize.Level1) @@ -629,7 +629,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest005 * @tc.name: RelationalTableCompareTest001 * @tc.desc: Test relational schema negotiate with same schema string * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalTableCompareTest001, TestSize.Level1) @@ -670,7 +670,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalTableCompareTest001, * @tc.name: RelationalSchemaOpinionTest001 * @tc.desc: Test relational schema sync opinion * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaOpinionTest001, TestSize.Level1) @@ -703,7 +703,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaOpinionTest001 * @tc.name: RelationalSchemaNegotiateTest001 * @tc.desc: Test relational schema negotiate * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaNegotiateTest001, TestSize.Level1) @@ -728,7 +728,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaNegotiateTest0 * @tc.name: TableCompareTest001 * @tc.desc: Test table compare * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, TableCompareTest001, TestSize.Level1) @@ -834,7 +834,7 @@ int TableCompareTest(sqlite3 *db, const std::string &sql1, const std::string &sq * @tc.name: TableCompareTest001 * @tc.desc: Test table compare with default value * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, TableCompareTest002, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_object_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_object_test.cpp index 388d6597609ecee7c464c42bc952510403e50d47..b43442be610099e356af0d82ba8f66996fe85d47 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_object_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_object_test.cpp @@ -383,17 +383,21 @@ std::string SchemaSwitchMode(const std::string &oriSchemaStr) { std::string resultSchemaStr = oriSchemaStr; auto iterForStrict = std::search(resultSchemaStr.begin(), resultSchemaStr.end(), - SchemaConstant::KEYWORD_MODE_STRICT.begin(), SchemaConstant::KEYWORD_MODE_STRICT.end()); + SchemaConstant::KEYWORD_MODE_STRICT, + SchemaConstant::KEYWORD_MODE_STRICT + strlen(SchemaConstant::KEYWORD_MODE_STRICT)); auto iterForCompatible = std::search(resultSchemaStr.begin(), resultSchemaStr.end(), - SchemaConstant::KEYWORD_MODE_COMPATIBLE.begin(), SchemaConstant::KEYWORD_MODE_COMPATIBLE.end()); + SchemaConstant::KEYWORD_MODE_COMPATIBLE, + SchemaConstant::KEYWORD_MODE_COMPATIBLE + strlen(SchemaConstant::KEYWORD_MODE_COMPATIBLE)); if (iterForStrict != resultSchemaStr.end()) { - resultSchemaStr.replace(iterForStrict, iterForStrict + SchemaConstant::KEYWORD_MODE_STRICT.size(), - SchemaConstant::KEYWORD_MODE_COMPATIBLE.begin(), SchemaConstant::KEYWORD_MODE_COMPATIBLE.end()); + resultSchemaStr.replace(iterForStrict, iterForStrict + strlen(SchemaConstant::KEYWORD_MODE_STRICT), + SchemaConstant::KEYWORD_MODE_COMPATIBLE, + SchemaConstant::KEYWORD_MODE_COMPATIBLE + strlen(SchemaConstant::KEYWORD_MODE_COMPATIBLE)); return resultSchemaStr; } if (iterForCompatible != resultSchemaStr.end()) { - resultSchemaStr.replace(iterForCompatible, iterForCompatible + SchemaConstant::KEYWORD_MODE_COMPATIBLE.size(), - SchemaConstant::KEYWORD_MODE_STRICT.begin(), SchemaConstant::KEYWORD_MODE_STRICT.end()); + resultSchemaStr.replace(iterForCompatible, iterForCompatible + strlen(SchemaConstant::KEYWORD_MODE_COMPATIBLE), + SchemaConstant::KEYWORD_MODE_STRICT, + SchemaConstant::KEYWORD_MODE_STRICT + strlen(SchemaConstant::KEYWORD_MODE_STRICT)); return resultSchemaStr; } return oriSchemaStr; @@ -417,7 +421,7 @@ void DistributedDBSchemaObjectTest::SetUp() * @tc.name: Parse Valid Schema 001 * @tc.desc: Parse Valid Schema * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, ParseValidSchema001, TestSize.Level1) @@ -459,7 +463,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, ParseValidSchema001, TestSize.Level1) * @tc.name: Parse Invalid Schema 001 * @tc.desc: Parse Invalid Schema * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, ParseInvalidSchema001, TestSize.Level1) @@ -509,7 +513,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, ParseInvalidSchema001, TestSize.Level1) * @tc.name: Parse Invalid Schema 002 * @tc.desc: Parse Invalid Schema * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, ParseInvalidSchema002, TestSize.Level1) @@ -559,7 +563,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, ParseInvalidSchema002, TestSize.Level1) * @tc.name: Parse Invalid Schema 003 * @tc.desc: Parse Invalid Schema * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, ParseInvalidSchema003, TestSize.Level1) @@ -609,7 +613,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, ParseInvalidSchema003, TestSize.Level1) * @tc.name: Compare Equal Exactly 001 * @tc.desc: Compare Equal Exactly * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, CompareEqualExactly001, TestSize.Level1) @@ -630,7 +634,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, CompareEqualExactly001, TestSize.Level1) * @tc.name: Compare Unequal Compatible 001 * @tc.desc: Compare Unequal Compatible * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, CompareUnequalCompatible001, TestSize.Level1) @@ -665,7 +669,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, CompareUnequalCompatible001, TestSize.Le * @tc.name: Compare Unequal Compatible Upgrade 001 * @tc.desc: Compare Unequal Compatible Upgrade * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, CompareUnequalCompatibleUpgrade001, TestSize.Level1) @@ -700,7 +704,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, CompareUnequalCompatibleUpgrade001, Test * @tc.name: Compare Unequal Incompatible 001 * @tc.desc: Compare Unequal Incompatible * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, CompareUnequalIncompatible001, TestSize.Level1) @@ -775,7 +779,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, CompareUnequalIncompatible001, TestSize. * @tc.name: Check Value 001 * @tc.desc: Check value both in strict and compatible mode * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, CheckValue001, TestSize.Level1) @@ -855,7 +859,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, CheckValue001, TestSize.Level1) * @tc.name: Check Value 002 * @tc.desc: Check value that has offset * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, CheckValue002, TestSize.Level1) @@ -889,7 +893,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, CheckValue002, TestSize.Level1) * @tc.name: Value Edit 001 * @tc.desc: Edit the value in right way * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, ValueEdit001, TestSize.Level1) @@ -937,7 +941,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, ValueEdit001, TestSize.Level1) * @tc.name: Value Edit 002 * @tc.desc: Edit the value in wrong way * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, ValueEdit002, TestSize.Level1) @@ -992,7 +996,7 @@ void CheckValueLackField(const SchemaObject &schema, const std::string &oriValue * @tc.name: Value LackField 001 * @tc.desc: check the value which lack field * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, ValueLackField001, TestSize.Level1) @@ -1051,7 +1055,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, ValueLackField001, TestSize.Level1) * @tc.name: Value LackField 002 * @tc.desc: check the value which lack field * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, ValueLackField002, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_unit_test.cpp index d69bfe94d8a9ccb2fee762ac6835bc2ba77592ec..059836114fb08d0baa6227aae7bcc229715e614e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_unit_test.cpp @@ -180,7 +180,7 @@ void PreBoolDataForParseAndCheckSchemaAttribute003() * @tc.name: ParseAndCheckSchemaAttribute001 * @tc.desc: Ability to recognize and parse the correct schema attribute format * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckSchemaAttribute001, TestSize.Level1) @@ -232,7 +232,7 @@ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckSchemaAttribute001, TestSize.Lev * @tc.name: ParseAndCheckSchemaAttribute002 * @tc.desc: Can identify the wrong schema attribute format and report an error. * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckSchemaAttribute002, TestSize.Level1) @@ -286,7 +286,7 @@ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckSchemaAttribute002, TestSize.Lev * @tc.name: ParseAndCheckSchemaAttribute003 * @tc.desc: Can correctly interpret the meaning of each keyword of the schema attribute * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckSchemaAttribute003, TestSize.Level1) @@ -315,7 +315,7 @@ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckSchemaAttribute003, TestSize.Lev * @tc.name: ParseAndCheckSchemaAttribute004 * @tc.desc: Can correctly identify the meaning of the schema attribute field that is incorrectly parsed * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckSchemaAttribute004, TestSize.Level1) @@ -364,7 +364,7 @@ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckSchemaAttribute004, TestSize.Lev * @tc.name: CheckFieldName001 * @tc.desc: Correctly identify field names * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBSchemalTest, CheckFieldName001, TestSize.Level1) @@ -389,7 +389,7 @@ HWTEST_F(DistributedDBSchemalTest, CheckFieldName001, TestSize.Level1) * @tc.name: CheckFieldName002 * @tc.desc: Identify illegal field name * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBSchemalTest, CheckFieldName002, TestSize.Level1) @@ -416,7 +416,7 @@ HWTEST_F(DistributedDBSchemalTest, CheckFieldName002, TestSize.Level1) * @tc.name: ParseAndCheckFieldPath001 * @tc.desc: Correctly identify and parse shema index fields * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckFieldPath001, TestSize.Level1) @@ -473,7 +473,7 @@ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckFieldPath001, TestSize.Level1) * @tc.name: ParseAndCheckFieldPath002 * @tc.desc: Correctly identify illegal shema index fields * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckFieldPath002, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_thread_pool_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_thread_pool_test.cpp index 560ba2abc8607dc603b1db97285bdbc99e40409b..e862e876b9b5999ca17c3d8b2a8f440d5beb97cd 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_thread_pool_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_thread_pool_test.cpp @@ -166,7 +166,7 @@ void SetTimer(int &timerCount, TimerId &timer) * @tc.name: ScheduleTask001 * @tc.desc: Test schedule task by thread pool * @tc.type: FUNC - * @tc.require: AR000I0KU9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBThreadPoolTest, ScheduleTask001, TestSize.Level1) @@ -207,7 +207,7 @@ HWTEST_F(DistributedDBThreadPoolTest, ScheduleTask001, TestSize.Level1) * @tc.name: SetTimer001 * @tc.desc: Test set timer by thread pool * @tc.type: FUNC - * @tc.require: AR000I0KU9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBThreadPoolTest, SetTimer001, TestSize.Level1) @@ -250,7 +250,7 @@ HWTEST_F(DistributedDBThreadPoolTest, SetTimer001, TestSize.Level1) * @tc.name: SetTimer002 * @tc.desc: Test repeat setting timer * @tc.type: FUNC - * @tc.require: AR000I0KU9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBThreadPoolTest, SetTimer002, TestSize.Level1) @@ -283,7 +283,7 @@ HWTEST_F(DistributedDBThreadPoolTest, SetTimer002, TestSize.Level1) * @tc.name: SetTimer003 * @tc.desc: Test set timer and finalize is null * @tc.type: FUNC - * @tc.require: AR000I0KU9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBThreadPoolTest, SetTimer003, TestSize.Level1) @@ -310,7 +310,7 @@ HWTEST_F(DistributedDBThreadPoolTest, SetTimer003, TestSize.Level1) * @tc.name: SetTimer004 * @tc.desc: Test remove timer function * @tc.type: FUNC - * @tc.require: AR000I0KU9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBThreadPoolTest, SetTimer004, TestSize.Level2) @@ -350,7 +350,7 @@ HWTEST_F(DistributedDBThreadPoolTest, SetTimer004, TestSize.Level2) * @tc.name: SetTimer005 * @tc.desc: Test repeat remove timer * @tc.type: FUNC - * @tc.require: AR000I0KU9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBThreadPoolTest, SetTimer005, TestSize.Level1) @@ -394,7 +394,7 @@ HWTEST_F(DistributedDBThreadPoolTest, SetTimer005, TestSize.Level1) * @tc.name: SetTimer006 * @tc.desc: Test repeat remove timer when time action finished * @tc.type: FUNC - * @tc.require: AR000I0KU9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBThreadPoolTest, SetTimer006, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_client_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_client_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a76a7064292fe2c080d0d06f6f5209f076cb9d04 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_client_test.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2025 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 "distributeddb_tools_unit_test.h" +#include "platform_specific.h" + +using namespace DistributedDB; + +namespace DistributedDBUnitTest { +int DistributedDBToolsUnitTest::GetCurrentDir(std::string &dir) +{ + static const int maxFileLength = 1024; + dir = ""; + char buffer[maxFileLength] = {0}; + int length = readlink("/proc/self/exe", buffer, maxFileLength); + if (length < 0 || length >= maxFileLength) { + LOGE("read directory err length:%d", length); + return -E_LENGTH_ERROR; + } + LOGD("DIR = %s", buffer); + dir = buffer; + if (dir.rfind("/") == std::string::npos && dir.rfind("\\") == std::string::npos) { + LOGE("current patch format err"); + return -E_INVALID_PATH; + } + + if (dir.rfind("/") != std::string::npos) { + dir.erase(dir.rfind("/") + 1); + } + return E_OK; +} + +void DistributedDBToolsUnitTest::TestDirInit(std::string &dir) +{ + if (GetCurrentDir(dir) != E_OK) { + dir = "/"; + } + + dir.append("testDbDir"); + DIR *dirTmp = opendir(dir.c_str()); + if (dirTmp == nullptr) { + if (OS::MakeDBDirectory(dir) != 0) { + LOGI("MakeDirectory err!"); + dir = "/"; + return; + } + } else { + closedir(dirTmp); + } +} + +int DistributedDBToolsUnitTest::RemoveTestDbFiles(const std::string &dir) +{ + bool isExisted = OS::CheckPathExistence(dir); + if (!isExisted) { + return E_OK; + } + + int nFile = 0; + std::string dirName; + struct dirent *direntPtr = nullptr; + DIR *dirPtr = opendir(dir.c_str()); + if (dirPtr == nullptr) { + LOGE("opendir error!"); + return -E_INVALID_PATH; + } + while (true) { + direntPtr = readdir(dirPtr); + // condition to exit the loop + if (direntPtr == nullptr) { + break; + } + // only remove all *.db files + std::string str(direntPtr->d_name); + if (str == "." || str == "..") { + continue; + } + dirName.clear(); + dirName.append(dir).append("/").append(str); + if (direntPtr->d_type == DT_DIR) { + RemoveTestDbFiles(dirName); + rmdir(dirName.c_str()); + } else if (remove(dirName.c_str()) != 0) { + LOGI("remove file: %s failed!", dirName.c_str()); + continue; + } + nFile++; + } + closedir(dirPtr); + LOGI("Total %d test db files are removed!", nFile); + return 0; +} + +sqlite3 *RelationalTestUtils::CreateDataBase(const std::string &dbUri) +{ + LOGD("Create database: %s", dbUri.c_str()); + sqlite3 *db = nullptr; + if (int r = sqlite3_open_v2(dbUri.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr) != SQLITE_OK) { + LOGE("Open database [%s] failed. %d", dbUri.c_str(), r); + if (db != nullptr) { + (void)sqlite3_close_v2(db); + db = nullptr; + } + } + return db; +} + +int RelationalTestUtils::ExecSql(sqlite3 *db, const std::string &sql) +{ + if (db == nullptr || sql.empty()) { + return -E_INVALID_ARGS; + } + char *errMsg = nullptr; + int errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &errMsg); + if (errCode != SQLITE_OK && errMsg != nullptr) { + LOGE("Execute sql failed. %d err: %s", errCode, errMsg); + } + sqlite3_free(errMsg); + return errCode; +} + +int RelationalTestUtils::ExecSql(sqlite3 *db, const std::string &sql, + const std::function &bindCallback, const std::function &resultCallback) +{ + if (db == nullptr || sql.empty()) { + return -E_INVALID_ARGS; + } + + bool bindFinish = true; + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != E_OK) { + goto END; + } + + do { + if (bindCallback) { + errCode = bindCallback(stmt); + if (errCode != E_OK && errCode != -E_UNFINISHED) { + goto END; + } + bindFinish = (errCode != -E_UNFINISHED); // continue bind if unfinished + } + + bool isStepFinished = false; + while (!isStepFinished) { + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; // Step finished + isStepFinished = true; + break; + } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + goto END; // Step return error + } + if (resultCallback == nullptr) { + continue; + } + errCode = resultCallback(stmt); + if (errCode != E_OK) { + goto END; + } + } + SQLiteUtils::ResetStatement(stmt, false, errCode); + } while (!bindFinish); + +END: + SQLiteUtils::ResetStatement(stmt, true, errCode); + return errCode; +} +} // namespace DistributedDBUnitTest diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp index 9469dd063fcd86ad41a2e57e489ba343b524b3a1..253f8149f7d1db6710a46a03014f6b21f607e618 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp @@ -224,90 +224,6 @@ int DistributedDBToolsUnitTest::GetResourceDir(std::string& dir) return E_OK; } -int DistributedDBToolsUnitTest::GetCurrentDir(std::string &dir) -{ - static const int maxFileLength = 1024; - dir = ""; - char buffer[maxFileLength] = {0}; - int length = readlink("/proc/self/exe", buffer, maxFileLength); - if (length < 0 || length >= maxFileLength) { - LOGE("read directory err length:%d", length); - return -E_LENGTH_ERROR; - } - LOGD("DIR = %s", buffer); - dir = buffer; - if (dir.rfind("/") == std::string::npos && dir.rfind("\\") == std::string::npos) { - LOGE("current patch format err"); - return -E_INVALID_PATH; - } - - if (dir.rfind("/") != std::string::npos) { - dir.erase(dir.rfind("/") + 1); - } - return E_OK; -} - -void DistributedDBToolsUnitTest::TestDirInit(std::string &dir) -{ - if (GetCurrentDir(dir) != E_OK) { - dir = "/"; - } - - dir.append("testDbDir"); - DIR *dirTmp = opendir(dir.c_str()); - if (dirTmp == nullptr) { - if (OS::MakeDBDirectory(dir) != 0) { - LOGI("MakeDirectory err!"); - dir = "/"; - return; - } - } else { - closedir(dirTmp); - } -} - -int DistributedDBToolsUnitTest::RemoveTestDbFiles(const std::string &dir) -{ - bool isExisted = OS::CheckPathExistence(dir); - if (!isExisted) { - return E_OK; - } - - int nFile = 0; - std::string dirName; - struct dirent *direntPtr = nullptr; - DIR *dirPtr = opendir(dir.c_str()); - if (dirPtr == nullptr) { - LOGE("opendir error!"); - return -E_INVALID_PATH; - } - while (true) { - direntPtr = readdir(dirPtr); - // condition to exit the loop - if (direntPtr == nullptr) { - break; - } - // only remove all *.db files - std::string str(direntPtr->d_name); - if (str == "." || str == "..") { - continue; - } - dirName.clear(); - dirName.append(dir).append("/").append(str); - if (direntPtr->d_type == DT_DIR) { - RemoveTestDbFiles(dirName); - rmdir(dirName.c_str()); - } else if (remove(dirName.c_str()) != 0) { - LOGI("remove file: %s failed!", dirName.c_str()); - continue; - } - nFile++; - } - closedir(dirPtr); - LOGI("Total %d test db files are removed!", nFile); - return 0; -} - #ifndef OMIT_MULTI_VER void DistributedDBToolsUnitTest::KvStoreDelegateCallback( DBStatus statusSrc, KvStoreDelegate *kvStoreSrc, DBStatus &statusDst, KvStoreDelegate *&kvStoreDst) @@ -1033,6 +949,30 @@ DBStatus DistributedDBToolsUnitTest::SyncTest(KvStoreNbDelegate* delegate, return callStatus; } +DBStatus DistributedDBToolsUnitTest::SyncTest(DistributedDB::KvStoreNbDelegate* delegate, + const DistributedDB::DeviceSyncOption& option, std::map& statuses) +{ + statuses.clear(); + DBStatus callStatus = delegate->Sync(option, [&statuses, this](const std::map& statusMap) { + std::unique_lock innerlock(this->syncLock_); + statuses = statusMap; + this->syncCondVar_.notify_one(); + }); + if (!option.isWait) { + std::unique_lock lock(syncLock_); + syncCondVar_.wait(lock, [callStatus, &statuses]() { + if (callStatus != OK) { + return true; + } + if (!statuses.empty()) { + return true; + } + return false; + }); + } + return callStatus; +} + static bool WaitUntilReady(DBStatus status, const std::map &syncProcessMap) { if (status != OK) { @@ -1064,7 +1004,8 @@ DBStatus DistributedDBToolsUnitTest::SyncTest(KvStoreNbDelegate *delegate, Devic if (!option.isWait) { std::unique_lock lock(this->syncLock_); - this->syncCondVar_.wait(lock, [status, &syncProcessMap]() { + uint32_t waitTime = 30; // 30s + this->syncCondVar_.wait_for(lock, std::chrono::seconds(waitTime), [status, &syncProcessMap]() { return WaitUntilReady(status, syncProcessMap); }); } @@ -1154,81 +1095,6 @@ int DistributedDBToolsUnitTest::BuildMessage(const DataSyncMessageInfo &messageI return E_OK; } -sqlite3 *RelationalTestUtils::CreateDataBase(const std::string &dbUri) -{ - LOGD("Create database: %s", dbUri.c_str()); - sqlite3 *db = nullptr; - if (int r = sqlite3_open_v2(dbUri.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr) != SQLITE_OK) { - LOGE("Open database [%s] failed. %d", dbUri.c_str(), r); - if (db != nullptr) { - (void)sqlite3_close_v2(db); - db = nullptr; - } - } - return db; -} - -int RelationalTestUtils::ExecSql(sqlite3 *db, const std::string &sql) -{ - if (db == nullptr || sql.empty()) { - return -E_INVALID_ARGS; - } - char *errMsg = nullptr; - int errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &errMsg); - if (errCode != SQLITE_OK && errMsg != nullptr) { - LOGE("Execute sql failed. %d err: %s", errCode, errMsg); - } - sqlite3_free(errMsg); - return errCode; -} - -int RelationalTestUtils::ExecSql(sqlite3 *db, const std::string &sql, - const std::function &bindCallback, const std::function &resultCallback) -{ - if (db == nullptr || sql.empty()) { - return -E_INVALID_ARGS; - } - - bool bindFinish = true; - sqlite3_stmt *stmt = nullptr; - int errCode = SQLiteUtils::GetStatement(db, sql, stmt); - if (errCode != E_OK) { - goto END; - } - - do { - if (bindCallback) { - errCode = bindCallback(stmt); - if (errCode != E_OK && errCode != -E_UNFINISHED) { - goto END; - } - bindFinish = (errCode != -E_UNFINISHED); // continue bind if unfinished - } - - while (true) { - errCode = SQLiteUtils::StepWithRetry(stmt); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; // Step finished - break; - } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - goto END; // Step return error - } - if (resultCallback == nullptr) { - continue; - } - errCode = resultCallback(stmt); - if (errCode != E_OK) { - goto END; - } - } - SQLiteUtils::ResetStatement(stmt, false, errCode); - } while (!bindFinish); - -END: - SQLiteUtils::ResetStatement(stmt, true, errCode); - return errCode; -} - void RelationalTestUtils::CreateDeviceTable(sqlite3 *db, const std::string &table, const std::string &device) { ASSERT_NE(db, nullptr); @@ -1661,6 +1527,14 @@ DistributedDB::ICloudSyncStorageHook *RelationalTestUtils::GetRDBStorageHook(con return static_cast(engine); } +void RelationalTestUtils::CheckIndexCount(sqlite3 *db, const std::string &table, size_t expect) +{ + TableInfo info; + ASSERT_EQ(SQLiteUtils::AnalysisSchema(db, table, info), E_OK); + auto index = info.GetIndexDefine(); + EXPECT_EQ(index.size(), expect); +} + bool RelationalStoreObserverUnitTest::IsAssetChange(const std::string &table) const { auto changeData = savedChangedData_.find(table); @@ -1715,4 +1589,29 @@ void DistributedDBToolsUnitTest::BlockSync(KvStoreNbDelegate *delegate, Distribu }); } } + +std::pair RelationalTestUtils::GetMaxTimestamp(sqlite3 *db, const std::string &oriTable) +{ + std::pair res; + auto &[errCode, timestamp] = res; + std::string sql = "SELECT MAX(timestamp) FROM " + std::string(DistributedDB::DBConstant::RELATIONAL_PREFIX) + + oriTable + "_log"; + sqlite3_stmt *stmt = nullptr; + errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != E_OK) { + LOGE("Get max timestamp stmt failed %d", errCode); + return res; + } + errCode = SQLiteUtils::StepWithRetry(stmt, false); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + timestamp = static_cast(sqlite3_column_int64(stmt, 0)); + errCode = E_OK; + } + int ret = E_OK; + SQLiteUtils::ResetStatement(stmt, true, ret); + if (errCode == E_OK) { + errCode = ret; + } + return res; +} } // namespace DistributedDBUnitTest diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h index 704df20d5d5f3cfdfab78f1de21497d61b59ba51..b12ad575fb26ea782eaed120e54ee24ccdfd31c7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h @@ -159,6 +159,9 @@ public: const std::vector& devices, DistributedDB::SyncMode mode, std::map& statuses, const DistributedDB::Query &query); + DistributedDB::DBStatus SyncTest(DistributedDB::KvStoreNbDelegate* delegate, + const DistributedDB::DeviceSyncOption& option, std::map& statuses); + DistributedDB::DBStatus SyncTest(DistributedDB::KvStoreNbDelegate* delegate, DistributedDB::DeviceSyncOption option, std::map &syncProcessMap); @@ -385,6 +388,8 @@ public: static bool IsExistEmptyHashAsset(const DistributedDB::Assets &assets); static DistributedDB::ICloudSyncStorageHook *GetRDBStorageHook(const std::string &userId, const std::string &appId, const std::string &storeId, const std::string &dbPath); + static void CheckIndexCount(sqlite3 *db, const std::string &table, size_t expect); + static std::pair GetMaxTimestamp(sqlite3 *db, const std::string &oriTable); }; class DBInfoHandleTest : public DistributedDB::DBInfoHandle { diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/evloop_timer_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/evloop_timer_unit_test.cpp index a020e68eeee70cd47d373dc2df8d8981041e515d..4d4f9e406bdc03d349c801a34fe2a5ace8db4893 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/evloop_timer_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/evloop_timer_unit_test.cpp @@ -103,7 +103,7 @@ void DistributedDBEventLoopTimerTest::TearDown(void) * @tc.name: EventLoopTimerTest001 * @tc.desc: Create and destroy the event loop object. * @tc.type: FUNC - * @tc.require: AR000CKRTB AR000CQE0C + * @tc.require: * @tc.author: fangyi */ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest001, TestSize.Level0) @@ -131,7 +131,7 @@ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest001, TestSize.Level0 * @tc.name: EventLoopTimerTest002 * @tc.desc: Start and stop the loop * @tc.type: FUNC - * @tc.require: AR000CKRTB AR000CQE0C + * @tc.require: * @tc.author: fangyi */ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest002, TestSize.Level1) @@ -165,7 +165,7 @@ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest002, TestSize.Level1 * @tc.name: EventLoopTimerTest003 * @tc.desc: Create and destroy a timer object. * @tc.type: FUNC - * @tc.require: AR000CKRTB AR000CQE0C + * @tc.require: * @tc.author: fangyi */ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest003, TestSize.Level0) @@ -198,7 +198,7 @@ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest003, TestSize.Level0 * @tc.name: EventLoopTimerTest004 * @tc.desc: Start a timer * @tc.type: FUNC - * @tc.require: AR000CKRTB AR000CQE0C + * @tc.require: * @tc.author: fangyi */ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest004, TestSize.Level1) @@ -254,7 +254,7 @@ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest004, TestSize.Level1 * @tc.name: EventLoopTimerTest005 * @tc.desc: Stop a timer * @tc.type: FUNC - * @tc.require: AR000CKRTB AR000CQE0C + * @tc.require: * @tc.author: fangyi */ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest005, TestSize.Level1) @@ -314,7 +314,7 @@ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest005, TestSize.Level1 * @tc.name: EventLoopTimerTest006 * @tc.desc: Stop a timer * @tc.type: FUNC - * @tc.require: AR000CKRTB AR000CQE0C + * @tc.require: * @tc.author: fangyi */ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest006, TestSize.Level1) @@ -371,7 +371,7 @@ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest006, TestSize.Level1 * @tc.name: EventLoopTimerTest007 * @tc.desc: Modify a timer * @tc.type: FUNC - * @tc.require: AR000CKRTB AR000CQE0C + * @tc.require: * @tc.author: fangyi */ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest007, TestSize.Level2) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.cpp index cf413c030abd823fe4af6e9f4144c7f8a99c0282..3fb17c5b69d5b10f43de8589da37e5f03b920dad 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.cpp @@ -14,12 +14,15 @@ */ #include "kv_general_ut.h" +#include "kv_store_errno.h" +#include "storage_engine_manager.h" #include "virtual_cloud_db.h" namespace DistributedDB { void KVGeneralUt::SetUp() { virtualCloudDb_ = std::make_shared(); + CloseAllDelegate(); BasicUnitTest::SetUp(); } @@ -49,6 +52,9 @@ int KVGeneralUt::InitDelegate(const StoreInfo &info) LOGE("[KVGeneralUt] Init delegate failed %d", static_cast(status)); return -E_INTERNAL_ERROR; } + if (processCommunicator_ != nullptr) { + manager.SetProcessCommunicator(processCommunicator_); + } stores_[info] = store; LOGI("[KVGeneralUt] Init delegate app %s store %s user %s success", info.appId.c_str(), info.storeId.c_str(), info.userId.c_str()); @@ -105,24 +111,6 @@ KvStoreConfig KVGeneralUt::GetKvStoreConfig() return config; } -StoreInfo KVGeneralUt::GetStoreInfo1() -{ - StoreInfo info; - info.userId = DistributedDBUnitTest::USER_ID; - info.storeId = DistributedDBUnitTest::STORE_ID_1; - info.appId = DistributedDBUnitTest::APP_ID; - return info; -} - -StoreInfo KVGeneralUt::GetStoreInfo2() -{ - StoreInfo info; - info.userId = DistributedDBUnitTest::USER_ID; - info.storeId = DistributedDBUnitTest::STORE_ID_2; - info.appId = DistributedDBUnitTest::APP_ID; - return info; -} - KvStoreNbDelegate *KVGeneralUt::GetDelegate(const DistributedDB::StoreInfo &info) const { std::lock_guard autoLock(storeMutex_); @@ -206,4 +194,103 @@ void KVGeneralUt::BlockCloudSync(const StoreInfo &from, const std::string &devic syncOption.devices.push_back("cloud"); tool_.BlockSync(fromStore, DBStatus::OK, syncOption, expectRet); } + +std::pair KVGeneralUt::GetRemoteSoftwareVersion(const StoreInfo &info, const std::string &dev, + const std::string &user) +{ + uint64_t version = 0; + int errCode = QueryMetaValue(info, dev, user, + [&version](const std::shared_ptr &metadata, const std::string &device, + const std::string &userId) { + version = metadata->GetRemoteSoftwareVersion(device, userId); + return E_OK; + }); + return {TransferDBErrno(errCode), version}; +} + +std::pair KVGeneralUt::GetRemoteSchemaVersion(const StoreInfo &info, const std::string &dev, + const std::string &user) +{ + uint64_t version = 0; + int errCode = QueryMetaValue(info, dev, user, + [&version](const std::shared_ptr &metadata, const std::string &device, + const std::string &userId) { + version = metadata->GetRemoteSchemaVersion(device, userId); + return E_OK; + }); + return {TransferDBErrno(errCode), version}; +} + +DBStatus KVGeneralUt::SetRemoteSoftwareVersion(const StoreInfo &info, const std::string &dev, const std::string &user, + uint64_t version) +{ + int errCode = QueryMetaValue(info, dev, user, + [version](const std::shared_ptr &metadata, const std::string &device, + const std::string &userId) { + return metadata->SetRemoteSoftwareVersion(device, userId, version); + }); + return TransferDBErrno(errCode); +} + +std::pair KVGeneralUt::GetLocalSchemaVersion(const DistributedDB::StoreInfo &info) +{ + uint64_t version = 0; + int errCode = QueryMetaValue(info, "", "", + [&version](const std::shared_ptr &metadata, const std::string &device, + const std::string &userId) { + auto [ret, schemaVersion] = metadata->GetLocalSchemaVersion(); + version = schemaVersion; + return ret; + }); + return {TransferDBErrno(errCode), version}; +} + +int KVGeneralUt::QueryMetaValue(const StoreInfo &info, const std::string &dev, const std::string &user, + const std::function &, const std::string &, const std::string &)> &queryFunc) +{ + int errCode = E_OK; + auto properties = GetDBProperties(info); + auto store = new(std::nothrow) SQLiteSingleVerNaturalStore; + if (store == nullptr) { + errCode = -E_INVALID_ARGS; + LOGI("[KVGeneralUt] create natural store failed with oom"); + return errCode; + } + errCode = store->Open(properties); + if (errCode != E_OK) { + RefObject::KillAndDecObjRef(store); + return errCode; + } + auto meta = std::make_shared(); + errCode = meta->Initialize(store); + if (errCode != E_OK) { + store->Close(); + RefObject::KillAndDecObjRef(store); + return errCode; + } + if (queryFunc) { + errCode = queryFunc(meta, dev, user); + } + meta = nullptr; + store->Close(); + RefObject::KillAndDecObjRef(store); + return errCode; +} + +KvDBProperties KVGeneralUt::GetDBProperties(const StoreInfo &info) +{ + KvDBProperties properties; + properties.SetStringProp(KvDBProperties::DATA_DIR, GetTestDir()); + properties.SetStringProp(KvDBProperties::STORE_ID, info.storeId); + KvStoreNbDelegate::Option option; + std::lock_guard autoLock(storeMutex_); + if (option_.has_value()) { + option = option_.value(); + } + auto idDir = DBCommon::TransferStringToHex(DBCommon::GetStoreIdentifier(info, "", option.syncDualTupleMode, false)); + properties.SetStringProp(KvDBProperties::IDENTIFIER_DIR, idDir); + properties.SetStringProp(KvDBProperties::IDENTIFIER_DATA, idDir + "KVGeneralUt"); + properties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); + return properties; +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.h index 7f228eb4dac814fa7b00750b3a64d7b942cb063d..42ea1bc56e659f5d41ac8beef402a52ab957d987 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.h @@ -36,12 +36,22 @@ protected: DBStatus GetDeviceEntries(KvStoreNbDelegate *delegate, const std::string &deviceId, bool isSelfDevice, std::vector &entries); void BlockCloudSync(const StoreInfo &from, const std::string &deviceId, DBStatus expectRet = DBStatus::OK); + std::pair GetRemoteSoftwareVersion(const StoreInfo &info, const std::string &dev, + const std::string &user); + std::pair GetRemoteSchemaVersion(const StoreInfo &info, const std::string &dev, + const std::string &user); + DBStatus SetRemoteSoftwareVersion(const StoreInfo &info, const std::string &dev, + const std::string &user, uint64_t version); + std::pair GetLocalSchemaVersion(const StoreInfo &info); + int QueryMetaValue(const StoreInfo &info, const std::string &dev, const std::string &user, + const std::function &, const std::string &, + const std::string &)> &queryFunc); + + KvDBProperties GetDBProperties(const StoreInfo &info); static KvStoreConfig GetKvStoreConfig(); - static StoreInfo GetStoreInfo1(); - static StoreInfo GetStoreInfo2(); mutable std::mutex storeMutex_; std::optional option_; - std::map stores_; + std::map stores_; DistributedDBUnitTest::DistributedDBToolsUnitTest tool_; std::shared_ptr virtualCloudDb_; }; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/process_communicator_test_stub.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/process_communicator_test_stub.h index 4d420a1f1f4d6467870eec93ba1832b22ffb3d31..7573930efddfb25deb08a36714c573a5e32b4e72 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/process_communicator_test_stub.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/process_communicator_test_stub.h @@ -86,8 +86,13 @@ public: isCommErr = commErr; } - DBStatus GetDataUserInfo(const uint8_t *data, uint32_t totalLen, const std::string &label, - std::vector &userInfos) override + DBStatus GetDataHeadInfo(DataHeadInfo dataHeadInfo, uint32_t &headLength) override + { + headLength = dataHeadInfo_.second; + return dataHeadInfo_.first; + } + + DBStatus GetDataUserInfo(DataUserInfo dataUserInfo, std::vector &userInfos) override { userInfos = userInfos_; return OK; @@ -97,9 +102,15 @@ public: { userInfos_ = userInfos; } + + void SetDataHeadInfo(std::pair dataHeadInfo) + { + dataHeadInfo_ = dataHeadInfo; + } private: bool isCommErr = false; std::vector userInfos_; + std::pair dataHeadInfo_; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator.cpp index 3bbe98f7e318f8d59705c4982b594d2dcec7410d..ec8cf0405eff2ae5cb292daa16c4b81d09d12688 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator.cpp @@ -65,22 +65,6 @@ int RDBDataGenerator::InitTable(const TableSchema &table, bool notNullWithStr, b return errCode; } -std::string RDBDataGenerator::GetTypeText(int type) -{ - switch (type) { - case DistributedDB::TYPE_INDEX: - return "INTEGER"; - case DistributedDB::TYPE_INDEX: - return "TEXT"; - case DistributedDB::TYPE_INDEX: - return "ASSETS"; - case DistributedDB::TYPE_INDEX: - return "ASSET"; - default: - return ""; - } -} - DistributedDB::DBStatus RDBDataGenerator::InsertCloudDBData(int64_t begin, int64_t count, int64_t gidStart, const DistributedDB::DataBaseSchema &schema, const std::shared_ptr &virtualCloudDb) @@ -141,6 +125,15 @@ DistributedDB::Type RDBDataGenerator::GetColValueByType(int64_t index, const Dis case DistributedDB::TYPE_INDEX: value = GenerateAsset(index, field); break; + case DistributedDB::TYPE_INDEX: + value = static_cast(index); + break; + case DistributedDB::TYPE_INDEX: + value = static_cast(index); + break; + case DistributedDB::TYPE_INDEX: + value = GenerateBytes(index); + break; } return value; } @@ -480,45 +473,9 @@ DistributedDB::TableSchema RDBDataGenerator::FlipTableSchema(const DistributedDB return res; } -int RDBDataGenerator::InitDatabaseWithSchemaInfo(const UtDateBaseSchemaInfo &schemaInfo, sqlite3 &db) -{ - int errCode = RelationalTestUtils::ExecSql(&db, "PRAGMA journal_mode=WAL;"); - if (errCode != SQLITE_OK) { - LOGE("[RDBDataGenerator] Execute sql failed %d", errCode); - return errCode; - } - for (const auto &tableInfo : schemaInfo.tablesInfo) { - errCode = InitTableWithSchemaInfo(tableInfo, db); - if (errCode != SQLITE_OK) { - LOGE("[RDBDataGenerator] Init table failed %d, %s", errCode, tableInfo.name.c_str()); - break; - } - } - return errCode; -} - -int RDBDataGenerator::InitTableWithSchemaInfo(const UtTableSchemaInfo &tableInfo, sqlite3 &db) +Bytes RDBDataGenerator::GenerateBytes(int64_t index) { - std::string sql = "CREATE TABLE IF NOT EXISTS " + tableInfo.name + "("; - for (const auto &fieldInfo : tableInfo.fieldInfo) { - sql += "'" + fieldInfo.field.colName + "' " + GetTypeText(fieldInfo.field.type); - if (fieldInfo.field.primary) { - sql += " PRIMARY KEY"; - if (fieldInfo.isAutoIncrement) { - sql += " AUTOINCREMENT"; - } - } - if (!fieldInfo.field.nullable && fieldInfo.field.type == TYPE_INDEX) { - sql += " NOT NULL ON CONFLICT IGNORE"; - } - sql += ","; - } - sql.pop_back(); - sql += ");"; - int errCode = RelationalTestUtils::ExecSql(&db, sql); - if (errCode != SQLITE_OK) { - LOGE("[RDBDataGenerator] Execute sql failed %d, sql is %s", errCode, sql.c_str()); - } - return errCode; + std::string str = std::to_string(index); + return std::vector(str.begin(), str.end()); } } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator.h index 3adad88b956e4546b352fc988ef2f62d17359ec9..8d8455ca92d538a6ababa23b00a35b9a03eeb49e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator.h @@ -104,6 +104,7 @@ private: static void FillTypeIntoDataValue(const DistributedDB::Field &field, const DistributedDB::Type &type, DistributedDB::VirtualRowData &virtualRow); + static DistributedDB::Bytes GenerateBytes(int64_t index); }; } #endif // RDB_DATA_GENERATE_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator_client.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator_client.cpp new file mode 100644 index 0000000000000000000000000000000000000000..52ec4693b5756846c5c8f43ea705ece438aad915 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator_client.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2025 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 "rdb_data_generator.h" + +#include "distributeddb_tools_unit_test.h" +#include "log_print.h" + +namespace DistributedDBUnitTest { +using namespace DistributedDB; +std::string RDBDataGenerator::GetTypeText(int type) +{ + switch (type) { + case DistributedDB::TYPE_INDEX: + return "INTEGER"; + case DistributedDB::TYPE_INDEX: + return "TEXT"; + case DistributedDB::TYPE_INDEX: + return "ASSETS"; + case DistributedDB::TYPE_INDEX: + return "ASSET"; + case DistributedDB::TYPE_INDEX: + return "DOUBLE"; + case DistributedDB::TYPE_INDEX: + return "BLOB"; + default: + return ""; + } +} + +int RDBDataGenerator::InitDatabaseWithSchemaInfo(const UtDateBaseSchemaInfo &schemaInfo, sqlite3 &db) +{ + int errCode = RelationalTestUtils::ExecSql(&db, "PRAGMA journal_mode=WAL;"); + if (errCode != SQLITE_OK) { + LOGE("[RDBDataGenerator] Execute sql failed %d", errCode); + return errCode; + } + for (const auto &tableInfo : schemaInfo.tablesInfo) { + errCode = InitTableWithSchemaInfo(tableInfo, db); + if (errCode != SQLITE_OK) { + LOGE("[RDBDataGenerator] Init table failed %d, %s", errCode, tableInfo.name.c_str()); + break; + } + } + return errCode; +} + +int RDBDataGenerator::InitTableWithSchemaInfo(const UtTableSchemaInfo &tableInfo, sqlite3 &db) +{ + std::string sql = "CREATE TABLE IF NOT EXISTS " + tableInfo.name + "("; + for (const auto &fieldInfo : tableInfo.fieldInfo) { + sql += "'" + fieldInfo.field.colName + "' " + GetTypeText(fieldInfo.field.type); + if (fieldInfo.field.primary) { + sql += " PRIMARY KEY"; + if (fieldInfo.isAutoIncrement) { + sql += " AUTOINCREMENT"; + } + } + if (!fieldInfo.field.nullable) { + sql += " NOT NULL ON CONFLICT IGNORE"; + } + sql += ","; + } + sql.pop_back(); + sql += ");"; + int errCode = RelationalTestUtils::ExecSql(&db, sql); + if (errCode != SQLITE_OK) { + LOGE("[RDBDataGenerator] Execute sql failed %d, sql is %s", errCode, sql.c_str()); + } + return errCode; +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.cpp index 142941a8c6bc718913df9dd5aa3c1380006726c3..831e0a330cc08aabd6ad82b0322a03b3ada30a73 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.cpp @@ -14,20 +14,28 @@ */ #include "rdb_general_ut.h" #include "rdb_data_generator.h" +#include "runtime_config.h" +#include "sqlite_relational_utils.h" +#include "virtual_cloud_data_translate.h" using namespace DistributedDBUnitTest; namespace DistributedDB { +const std::string CIPHER_CONFIG_SQL = "PRAGMA codec_cipher='aes-256-gcm';"; +const std::string KDF_ITER_CONFIG_SQL = "PRAGMA codec_kdf_iter=5000;"; +const std::string SHA256_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA256;"; + const Field intField = {"id", TYPE_INDEX, true, false}; const Field stringField = {"name", TYPE_INDEX, false, false}; const Field boolField = {"gender", TYPE_INDEX, false, true}; const Field doubleField = {"height", TYPE_INDEX, false, true}; const Field bytesField = {"photo", TYPE_INDEX, false, true}; -const Field assetsField = {"assert", TYPE_INDEX, false, true}; +const Field assetField = {"assert", TYPE_INDEX, false, true}; +const Field assetsField = {"asserts", TYPE_INDEX, false, true}; const std::vector g_defaultFiledInfo = { {intField, true}, {stringField, false}, {boolField, false}, - {doubleField, false}, {bytesField, false}, {assetsField, false}, + {doubleField, false}, {bytesField, false}, {assetField, false}, {assetsField, false}, }; UtDateBaseSchemaInfo g_defaultSchemaInfo = { @@ -39,47 +47,60 @@ UtDateBaseSchemaInfo g_defaultSchemaInfo = { int RDBGeneralUt::InitDelegate(const StoreInfo &info) { - std::string storePath = GetTestDir() + "/" + info.storeId + ".db"; - sqlite3 *db = RelationalTestUtils::CreateDataBase(storePath); - if (db == nullptr) { - LOGE("[RDBGeneralUt] Create database failed %s", storePath.c_str()); - return -E_INVALID_DB; - } - UtDateBaseSchemaInfo schemaInfo = GetTableSchemaInfo(info); - int errCode = RDBDataGenerator::InitDatabaseWithSchemaInfo(schemaInfo, *db); - if (errCode != SQLITE_OK) { - LOGE("[RDBGeneralUt] Init database failed %d", errCode); - return errCode; + InitDatabase(info); + { + std::lock_guard autoLock(storeMutex_); + if (stores_.find(info) != stores_.end()) { + return E_OK; + } } - RelationalStoreManager mgr(info.appId, info.userId); - RelationalStoreDelegate *delegate = nullptr; - errCode = mgr.OpenStore(storePath, info.storeId, option_, delegate); + auto [errCode, delegate] = OpenRDBStore(info); if ((errCode != E_OK )|| (delegate == nullptr)) { LOGE("[RDBGeneralUt] Open store failed %d", errCode); return errCode; } { - std::lock_guard lock(storeMutex_); + std::lock_guard autoLock(storeMutex_); stores_[info] = delegate; - sqliteDb_[info] = db; } + LOGI("[RDBGeneralUt] Init delegate app %s store %s user %s success", info.appId.c_str(), + info.storeId.c_str(), info.userId.c_str()); return E_OK; } +std::pair RDBGeneralUt::OpenRDBStore(const StoreInfo &info) +{ + std::pair res; + auto &[errCode, delegate] = res; + delegate = nullptr; + std::string storePath = GetTestDir() + "/" + info.storeId + ".db"; + RelationalStoreManager mgr(info.appId, info.userId); + RelationalStoreDelegate::Option option = GetOption(); + errCode = mgr.OpenStore(storePath, info.storeId, option, delegate); + return res; +} + void RDBGeneralUt::SetOption(const RelationalStoreDelegate::Option& option) { + std::lock_guard autoLock(storeMutex_); option_ = option; } -void RDBGeneralUt::AddSchemaInfo(const StoreInfo &info, const DistributedDBUnitTest::UtDateBaseSchemaInfo &schemaInfo) +RelationalStoreDelegate::Option RDBGeneralUt::GetOption() const { - std::lock_guard lock(storeMutex_); + std::lock_guard autoLock(storeMutex_); + return option_; +} + +void RDBGeneralUt::SetSchemaInfo(const StoreInfo &info, const DistributedDBUnitTest::UtDateBaseSchemaInfo &schemaInfo) +{ + std::lock_guard autoLock(storeMutex_); schemaInfoMap_[info] = schemaInfo; } -UtDateBaseSchemaInfo RDBGeneralUt::GetTableSchemaInfo(const StoreInfo &info) +UtDateBaseSchemaInfo RDBGeneralUt::GetTableSchemaInfo(const StoreInfo &info) const { - std::lock_guard lock(storeMutex_); + std::lock_guard autoLock(storeMutex_); auto iter = schemaInfoMap_.find(info); if (iter != schemaInfoMap_.end()) { return iter->second; @@ -87,7 +108,7 @@ UtDateBaseSchemaInfo RDBGeneralUt::GetTableSchemaInfo(const StoreInfo &info) return g_defaultSchemaInfo; } -DataBaseSchema RDBGeneralUt::GetSchema(const StoreInfo &info) +DataBaseSchema RDBGeneralUt::GetSchema(const StoreInfo &info) const { UtDateBaseSchemaInfo schemaInfo = GetTableSchemaInfo(info); DataBaseSchema schema; @@ -103,7 +124,7 @@ DataBaseSchema RDBGeneralUt::GetSchema(const StoreInfo &info) return schema; } -TableSchema RDBGeneralUt::GetTableSchema(const StoreInfo &info, const std::string &tableName) +TableSchema RDBGeneralUt::GetTableSchema(const StoreInfo &info, const std::string &tableName) const { UtDateBaseSchemaInfo schemaInfo = GetTableSchemaInfo(info); for (auto &item : schemaInfo.tablesInfo) { @@ -123,7 +144,7 @@ TableSchema RDBGeneralUt::GetTableSchema(const StoreInfo &info, const std::strin } std::vector RDBGeneralUt::GetAllTrackerSchema(const StoreInfo &info, - const std::vector &tables) + const std::vector &tables) const { UtDateBaseSchemaInfo schemaInfo = GetTableSchemaInfo(info); std::vector res; @@ -145,7 +166,7 @@ std::vector RDBGeneralUt::GetAllTrackerSchema(const StoreInfo &in int RDBGeneralUt::CloseDelegate(const StoreInfo &info) { - std::lock_guard lock(storeMutex_); + std::lock_guard autoLock(storeMutex_); auto storeIter = stores_.find(info); if (storeIter != stores_.end()) { RelationalStoreManager mgr(info.appId, info.userId); @@ -163,12 +184,14 @@ int RDBGeneralUt::CloseDelegate(const StoreInfo &info) if (schemaIter != schemaInfoMap_.end()) { schemaInfoMap_.erase(schemaIter); } + LOGI("[RDBGeneralUt] Close delegate app %s store %s user %s success", info.appId.c_str(), + info.storeId.c_str(), info.userId.c_str()); return E_OK; } void RDBGeneralUt::CloseAllDelegate() { - std::lock_guard lock(storeMutex_); + std::lock_guard autoLock(storeMutex_); for (auto &iter : sqliteDb_) { sqlite3_close_v2(iter.second); iter.second = nullptr; @@ -181,36 +204,65 @@ void RDBGeneralUt::CloseAllDelegate() } stores_.clear(); schemaInfoMap_.clear(); + isDbEncrypted_ = false; + LOGI("[RDBGeneralUt] Close all delegate success"); } void RDBGeneralUt::SetUp() { BasicUnitTest::SetUp(); + RuntimeConfig::SetCloudTranslate(std::make_shared()); + { + std::lock_guard autoLock(storeMutex_); + virtualCloudDb_ = std::make_shared(); + virtualAssetLoader_ = std::make_shared(); + } } void RDBGeneralUt::TearDown() { CloseAllDelegate(); + { + std::lock_guard autoLock(storeMutex_); + virtualCloudDb_ = nullptr; + virtualAssetLoader_ = nullptr; + } BasicUnitTest::TearDown(); } int RDBGeneralUt::InitDatabase(const StoreInfo &info) { - auto schema = GetSchema(info); - auto db = GetSqliteHandle(info); + std::string storePath = GetTestDir() + "/" + info.storeId + ".db"; + sqlite3 *db = RelationalTestUtils::CreateDataBase(storePath); if (db == nullptr) { - LOGE("[RDBGeneralUt] Get null sqlite when init database"); + LOGE("[RDBGeneralUt] Create database failed %s", storePath.c_str()); return -E_INVALID_DB; } - auto errCode = RDBDataGenerator::InitDatabase(schema, *db); - if (errCode != E_OK) { - LOGE("[RDBGeneralUt] Init db failed %d app %s store %s user %s", errCode, info.appId.c_str(), - info.storeId.c_str(), info.userId.c_str()); + int errCode = E_OK; + if (GetIsDbEncrypted()) { + errCode = EncryptedDb(db); + if (errCode != E_OK) { + return errCode; + } } - return errCode; + UtDateBaseSchemaInfo schemaInfo = GetTableSchemaInfo(info); + errCode = RDBDataGenerator::InitDatabaseWithSchemaInfo(schemaInfo, *db); + if (errCode != SQLITE_OK) { + LOGE("[RDBGeneralUt] Init database failed %d", errCode); + return errCode; + } + { + std::lock_guard autoLock(storeMutex_); + if (sqliteDb_.find(info) != sqliteDb_.end()) { + sqlite3_close_v2(db); + return E_OK; + } + sqliteDb_[info] = db; + } + return E_OK; } -sqlite3 *RDBGeneralUt::GetSqliteHandle(const StoreInfo &info) +sqlite3 *RDBGeneralUt::GetSqliteHandle(const StoreInfo &info) const { std::lock_guard autoLock(storeMutex_); auto db = sqliteDb_.find(info); @@ -241,6 +293,16 @@ int RDBGeneralUt::InsertLocalDBData(int64_t begin, int64_t count, const StoreInf return errCode; } +int RDBGeneralUt::ExecuteSQL(const std::string &sql, const StoreInfo &info) +{ + auto db = GetSqliteHandle(info); + if (db == nullptr) { + LOGE("[RDBGeneralUt] Get null sqlite when insert data"); + return -E_INVALID_DB; + } + return SQLiteUtils::ExecuteRawSQL(db, sql); +} + int RDBGeneralUt::CreateDistributedTable(const StoreInfo &info, const std::string &table, TableSyncType type) { auto store = GetDelegate(info); @@ -253,6 +315,8 @@ int RDBGeneralUt::CreateDistributedTable(const StoreInfo &info, const std::strin LOGE("[RDBGeneralUt] Create distributed table failed %d app %s store %s user %s", errCode, info.appId.c_str(), info.storeId.c_str(), info.userId.c_str()); } + LOGI("[RDBGeneralUt] Create distributed table success, app %s store %s user %s", info.appId.c_str(), + info.storeId.c_str(), info.userId.c_str()); return errCode; } @@ -266,7 +330,8 @@ int RDBGeneralUt::SetDistributedTables(const StoreInfo &info, const std::vector< return errCode; } } - if (option_.tableMode != DistributedTableMode::COLLABORATION) { + RelationalStoreDelegate::Option option = GetOption(); + if (option.tableMode != DistributedTableMode::COLLABORATION) { return E_OK; } auto store = GetDelegate(info); @@ -280,37 +345,51 @@ int RDBGeneralUt::SetDistributedTables(const StoreInfo &info, const std::vector< LOGE("[RDBGeneralUt] Set distributed schema failed %d app %s store %s user %s", errCode, info.appId.c_str(), info.storeId.c_str(), info.userId.c_str()); } + LOGI("[RDBGeneralUt] Set distributed table success, app %s store %s user %s", info.appId.c_str(), + info.storeId.c_str(), info.userId.c_str()); return errCode; } -RelationalStoreDelegate *RDBGeneralUt::GetDelegate(const StoreInfo &info) +RelationalStoreDelegate *RDBGeneralUt::GetDelegate(const StoreInfo &info) const { std::lock_guard autoLock(storeMutex_); auto db = stores_.find(info); if (db == stores_.end()) { LOGE("[RDBGeneralUt] Not exist delegate app %s store %s user %s", info.appId.c_str(), - info.storeId.c_str(), info.userId.c_str()); + info.storeId.c_str(), info.userId.c_str()); return nullptr; } return db->second; } void RDBGeneralUt::BlockPush(const StoreInfo &from, const StoreInfo &to, const std::string &table, DBStatus expectRet) +{ + ASSERT_NO_FATAL_FAILURE(BlockSync(from, to, table, SYNC_MODE_PUSH_ONLY, expectRet)); +} + +void RDBGeneralUt::BlockPull(const StoreInfo &from, const StoreInfo &to, const std::string &table, DBStatus expectRet) +{ + ASSERT_NO_FATAL_FAILURE(BlockSync(from, to, table, SYNC_MODE_PULL_ONLY, expectRet)); +} + +void RDBGeneralUt::BlockSync(const StoreInfo &from, const StoreInfo &to, const std::string &table, SyncMode mode, + DBStatus expectRet) { auto store = GetDelegate(from); ASSERT_NE(store, nullptr); auto toDevice = GetDevice(to); ASSERT_FALSE(toDevice.empty()); Query query = Query::Select(table); - DistributedDBToolsUnitTest::BlockSync(*store, query, SYNC_MODE_PUSH_ONLY, expectRet, {toDevice}); + ASSERT_NO_FATAL_FAILURE(DistributedDBToolsUnitTest::BlockSync(*store, query, mode, expectRet, {toDevice})); } -int RDBGeneralUt::CountTableData(const StoreInfo &info, const std::string &table) +int RDBGeneralUt::CountTableData(const StoreInfo &info, const std::string &table, const std::string &condition) { - return CountTableDataByDev(info, table, ""); + return CountTableDataByDev(info, table, "", condition); } -int RDBGeneralUt::CountTableDataByDev(const StoreInfo &info, const std::string &table, const std::string &dev) +int RDBGeneralUt::CountTableDataByDev(const StoreInfo &info, const std::string &table, const std::string &dev, + const std::string &condition) { auto db = GetSqliteHandle(info); if (db == nullptr) { @@ -329,9 +408,18 @@ int RDBGeneralUt::CountTableDataByDev(const StoreInfo &info, const std::string & } std::string cntSql = "SELECT count(*) FROM '" + table + "'"; + if (!condition.empty() || !dev.empty()) { + cntSql.append(" WHERE "); + } + if (!condition.empty()) { + cntSql.append(condition); + if (!dev.empty()) { + cntSql.append(" AND "); + } + } if (!dev.empty()) { auto hex = DBCommon::TransferStringToHex(DBCommon::TransferHashString(dev)); - cntSql.append(" WHERE device='").append(hex).append("'"); + cntSql.append("device='").append(hex).append("'"); } sqlite3_stmt *stmt = nullptr; errCode = SQLiteUtils::GetStatement(db, cntSql, stmt); @@ -353,7 +441,7 @@ int RDBGeneralUt::CountTableDataByDev(const StoreInfo &info, const std::string & return count; } -int RDBGeneralUt::SetTrackerTables(const StoreInfo &info, const std::vector &tables) +int RDBGeneralUt::SetTrackerTables(const StoreInfo &info, const std::vector &tables, bool isForce) { auto store = GetDelegate(info); if (store == nullptr) { @@ -362,7 +450,9 @@ int RDBGeneralUt::SetTrackerTables(const StoreInfo &info, const std::vectorSetTrackerTable(trackerTable); + auto temp = trackerTable; + temp.isForceUpgrade = isForce; + auto errCode = store->SetTrackerTable(temp); if (errCode != E_OK) { LOGE("[RDBGeneralUt] Set tracker table %s failed %d app %s store %s user %s", trackerTable.tableName.c_str(), errCode, @@ -374,4 +464,133 @@ int RDBGeneralUt::SetTrackerTables(const StoreInfo &info, const std::vector RDBGeneralUt::GetVirtualCloudDb() const +{ + std::lock_guard autoLock(storeMutex_); + return virtualCloudDb_; +} + +std::shared_ptr RDBGeneralUt::GetVirtualAssetLoader() const +{ + std::lock_guard autoLock(storeMutex_); + return virtualAssetLoader_; +} + +void RDBGeneralUt::SetCloudDbConfig(const StoreInfo &info) const +{ + auto delegate = GetDelegate(info); + ASSERT_NE(delegate, nullptr); + std::shared_ptr virtualCloudDb = GetVirtualCloudDb(); + std::shared_ptr virtualAssetLoader = GetVirtualAssetLoader(); + ASSERT_NE(virtualCloudDb, nullptr); + ASSERT_NE(virtualAssetLoader, nullptr); + ASSERT_EQ(delegate->SetCloudDB(virtualCloudDb), DBStatus::OK); + ASSERT_EQ(delegate->SetIAssetLoader(virtualAssetLoader), DBStatus::OK); + ASSERT_EQ(delegate->SetCloudDbSchema(GetSchema(info)), DBStatus::OK); + LOGI("[RDBGeneralUt] Set cloud db config success, app %s store %s user %s", info.appId.c_str(), + info.storeId.c_str(), info.userId.c_str()); +} + +void RDBGeneralUt::CloudBlockSync(const StoreInfo &info, const Query &query, DBStatus exceptStatus, + DBStatus callbackExpect) +{ + LOGI("[RDBGeneralUt] Begin cloud sync, app %s store %s user %s", info.appId.c_str(), + info.storeId.c_str(), info.userId.c_str()); + auto delegate = GetDelegate(info); + ASSERT_NE(delegate, nullptr); + RelationalTestUtils::CloudBlockSync(query, delegate, exceptStatus, callbackExpect); +} + +int RDBGeneralUt::GetCloudDataCount(const std::string &tableName) const +{ + VBucket extend; + extend[CloudDbConstant::CURSOR_FIELD] = std::to_string(0); + int realCount = 0; + std::vector data; + std::shared_ptr virtualCloudDb = GetVirtualCloudDb(); + if (virtualCloudDb == nullptr) { + LOGE("[RDBGeneralUt] virtual cloud db is nullptr"); + return -1; + } + virtualCloudDb->Query(tableName, extend, data); + for (size_t j = 0; j < data.size(); ++j) { + auto entry = data[j].find(CloudDbConstant::DELETE_FIELD); + if (entry != data[j].end() && std::get(entry->second)) { + continue; + } + realCount++; + } + LOGI("[RDBGeneralUt] Count cloud table %s success, count %d", tableName.c_str(), realCount); + return realCount; +} + +void RDBGeneralUt::SetIsDbEncrypted(bool isdbEncrypted) +{ + isDbEncrypted_ = isdbEncrypted; +} + +bool RDBGeneralUt::GetIsDbEncrypted() const +{ + return isDbEncrypted_; +} + +int RDBGeneralUt::EncryptedDb(sqlite3 *db) +{ + std::string passwd(PASSWD_VECTOR.begin(), PASSWD_VECTOR.end()); + int rc = sqlite3_key(db, passwd.c_str(), passwd.size()); + if (rc != SQLITE_OK) { + sqlite3_close(db); + LOGE("sqlite3_key failed, %d, passwd is %s.", rc, passwd.c_str()); + return -E_INVALID_DB; + } + char *errMsg = nullptr; + int errCode = sqlite3_exec(db, CIPHER_CONFIG_SQL.c_str(), nullptr, nullptr, &errMsg); + if (errCode != SQLITE_OK || errMsg != nullptr) { + LOGE("set cipher failed: %d, cipher is %s.", errCode, CIPHER_CONFIG_SQL.c_str()); + sqlite3_close(db); + sqlite3_free(errMsg); + return -E_INVALID_DB; + } + errMsg = nullptr; + errCode = sqlite3_exec(db, KDF_ITER_CONFIG_SQL.c_str(), nullptr, nullptr, &errMsg); + if (errCode != SQLITE_OK || errMsg != nullptr) { + LOGE("set iterTimes failed: %d, iterTimes is %s.", errCode, KDF_ITER_CONFIG_SQL.c_str()); + sqlite3_close(db); + sqlite3_free(errMsg); + return -E_INVALID_DB; + } + errCode = sqlite3_exec(db, SHA256_ALGO_SQL.c_str(), nullptr, nullptr, &errMsg); + if (errCode != SQLITE_OK || errMsg != nullptr) { + LOGE("set codec_hmac_algo failed: %d, codec_hmac_algo is %s.", errCode, SHA256_ALGO_SQL.c_str()); + sqlite3_close(db); + sqlite3_free(errMsg); + return -E_INVALID_DB; + } + return E_OK; +} + +void RDBGeneralUt::RemoteQuery(const StoreInfo &from, const StoreInfo &to, const std::string &sql, DBStatus expectRet) +{ + auto store = GetDelegate(from); + ASSERT_NE(store, nullptr); + auto toDevice = GetDevice(to); + ASSERT_FALSE(toDevice.empty()); + RemoteCondition condition; + condition.sql = sql; + std::shared_ptr resultSet = nullptr; + EXPECT_EQ(store->RemoteQuery(toDevice, condition, DBConstant::MAX_TIMEOUT, resultSet), expectRet); + EXPECT_NE(resultSet, nullptr); +} + +int RDBGeneralUt::PutMetaData(const StoreInfo &store, const Key &key, const Value &value) +{ + auto db = GetSqliteHandle(store); + if (db == nullptr) { + LOGE("[RDBGeneralUt] Get null sqlite when put meta data userId[%s] appId[%s] storeId[%s]", + store.userId.c_str(), store.appId.c_str(), store.storeId.c_str()); + return -E_INTERNAL_ERROR; + } + return SQLiteRelationalUtils::PutKvData(db, false, key, value); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.h index 1397fcd7907d2c4082a85c1c94373454d18665c0..6eebce0a31a60ab8fa136105d3821da3d25def84 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.h @@ -19,10 +19,12 @@ #include "basic_unit_test.h" #include "rdb_data_generator.h" #include "relational_store_manager.h" +#include "virtual_asset_loader.h" namespace DistributedDB { const std::string g_defaultTable1 = "defaultTable1"; const std::string g_defaultTable2 = "defaultTable2"; +const std::vector PASSWD_VECTOR = {'P', 'a', 's', 's', 'w', 'o', 'r', 'd', '@', '1'}; class RDBGeneralUt : public BasicUnitTest { public: @@ -30,45 +32,80 @@ public: void TearDown() override; protected: int InitDelegate(const StoreInfo &info) override; + std::pair OpenRDBStore(const StoreInfo &info); int CloseDelegate(const StoreInfo &info) override; void CloseAllDelegate() override; // If SetOption is not invoked before InitDelegate is invoked, the default data of Option is used to open store. void SetOption(const RelationalStoreDelegate::Option& option); - // If AddSchemaInfo is not invoked before InitDelegate is invoked, g_defaultSchemaInfo is used to create table. - void AddSchemaInfo(const StoreInfo &info, const DistributedDBUnitTest::UtDateBaseSchemaInfo& schemaInfo); - DataBaseSchema GetSchema(const StoreInfo &info); - TableSchema GetTableSchema(const StoreInfo &info, const std::string &tableName = g_defaultTable1); - std::vector GetAllTrackerSchema(const StoreInfo &info, const std::vector &tables); + // If SetSchemaInfo is not invoked before InitDelegate is invoked, g_defaultSchemaInfo is used to create table. + void SetSchemaInfo(const StoreInfo &info, const DistributedDBUnitTest::UtDateBaseSchemaInfo& schemaInfo); + + DistributedDBUnitTest::UtDateBaseSchemaInfo GetTableSchemaInfo(const StoreInfo &info) const; + DataBaseSchema GetSchema(const StoreInfo &info) const; + TableSchema GetTableSchema(const StoreInfo &info, const std::string &tableName = g_defaultTable1) const; + std::vector GetAllTrackerSchema(const StoreInfo &info, const std::vector &tables) const; + sqlite3 *GetSqliteHandle(const StoreInfo &info) const; + RelationalStoreDelegate *GetDelegate(const StoreInfo &info) const; + RelationalStoreDelegate::Option GetOption() const; int InitDatabase(const StoreInfo &info); int InsertLocalDBData(int64_t begin, int64_t count, const StoreInfo &info); + int ExecuteSQL(const std::string &sql, const StoreInfo &info); + int CreateDistributedTable(const StoreInfo &info, const std::string &table, TableSyncType type = TableSyncType::DEVICE_COOPERATION); int SetDistributedTables(const StoreInfo &info, const std::vector &tables, TableSyncType type = TableSyncType::DEVICE_COOPERATION); + // use for device to device sync void BlockPush(const StoreInfo &from, const StoreInfo &to, const std::string &table, DBStatus expectRet = DBStatus::OK); - DistributedDBUnitTest::UtDateBaseSchemaInfo GetTableSchemaInfo(const StoreInfo &info); - sqlite3 *GetSqliteHandle(const StoreInfo &info); - RelationalStoreDelegate *GetDelegate(const StoreInfo &info); + void BlockPull(const StoreInfo &from, const StoreInfo &to, const std::string &table, + DBStatus expectRet = DBStatus::OK); - int CountTableData(const StoreInfo &info, const std::string &table); + int CountTableData(const StoreInfo &info, const std::string &table, const std::string &condition = ""); - int CountTableDataByDev(const StoreInfo &info, const std::string &table, const std::string &dev); + int CountTableDataByDev(const StoreInfo &info, const std::string &table, const std::string &dev, + const std::string &condition = ""); - int SetTrackerTables(const StoreInfo &info, const std::vector &tables); + int SetTrackerTables(const StoreInfo &info, const std::vector &tables, bool isForce = false); + + // use for cloud sync + std::shared_ptr GetVirtualCloudDb() const; + + std::shared_ptr GetVirtualAssetLoader() const; + + void CloudBlockSync(const StoreInfo &from, const Query &query, DBStatus exceptStatus = OK, + DBStatus callbackExpect = OK); + + void SetCloudDbConfig(const StoreInfo &info) const; + + int GetCloudDataCount(const std::string &tableName) const; + + void SetIsDbEncrypted(bool isdbEncrypted); + bool GetIsDbEncrypted() const; + int EncryptedDb(sqlite3 *db); + + void BlockSync(const StoreInfo &from, const StoreInfo &to, const std::string &table, SyncMode mode, + DBStatus expectRet); + + void RemoteQuery(const StoreInfo &from, const StoreInfo &to, const std::string &sql, DBStatus expectRet); + + int PutMetaData(const StoreInfo &store, const Key &key, const Value &value); - RelationalStoreDelegate::Option option_; mutable std::mutex storeMutex_; - std::map stores_; - std::map sqliteDb_; - std::map schemaInfoMap_; + std::map stores_; + std::map sqliteDb_; + std::map schemaInfoMap_; + std::shared_ptr virtualCloudDb_ = nullptr; + std::shared_ptr virtualAssetLoader_ = nullptr; + RelationalStoreDelegate::Option option_; + bool isDbEncrypted_ = false; }; } #endif // RDB_GENERAL_UT_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/adapter_stub.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/adapter_stub.cpp index 0d2f5c9d28c955321019ebdcc5e2e18175f671e4..1efe7b631269b6680f3809121c1a5ce351026fb5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/adapter_stub.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/adapter_stub.cpp @@ -122,6 +122,12 @@ int AdapterStub::SendBytes(const std::string &dstTarget, const uint8_t *bytes, u return E_OK; } +int AdapterStub::SendBytes(const DeviceInfos &deviceInfos, const uint8_t *bytes, uint32_t length, + uint32_t totalLength) +{ + return AdapterStub::SendBytes(deviceInfos.identifier, bytes, length, totalLength); +} + int AdapterStub::RegBytesReceiveCallback(const BytesReceiveCallback &onReceive, const Finalizer &inOper) { std::lock_guard onReceiveLockGuard(onReceiveMutex_); @@ -209,12 +215,17 @@ void AdapterStub::DeliverBytes(const std::string &srcTarget, const uint8_t *byte uint32_t headLength = 0; GetDataHeadInfo(bytes, headLength); std::vector userInfos; - GetDataUserInfo(bytes, userInfos); + if (userInfo_.empty()) { + GetDataUserInfo(bytes, userInfos); + } else { + userInfos = userInfo_; + } std::shared_ptr processCommunicator = std::make_shared(); processCommunicator->SetDataUserInfo(userInfos); DataUserInfoProc userInfoProc = {bytes, length, processCommunicator}; - onReceiveHandle_(srcTarget, bytes + headLength, length - headLength, userInfoProc); + ReceiveBytesInfo receiveBytesInfo = {bytes + headLength, srcTarget, length - headLength, headLength != 0}; + onReceiveHandle_(receiveBytesInfo, userInfoProc); } } @@ -242,6 +253,7 @@ void AdapterStub::GetDataUserInfo(const uint8_t *data, std::vector &us break; } userInfo.receiveUser.push_back(info->userId[i]); + userInfo.sendUser.push_back(info->userId[i]); } userInfos.push_back(userInfo); } @@ -449,4 +461,14 @@ void AdapterStub::ApplySendBitError(const uint8_t *bytes, uint32_t length) phyHeader->checkSum = HostToNet(CalculateXorSum(bytes + LENGTH_BEFORE_SUM_RANGE, length - LENGTH_BEFORE_SUM_RANGE)); } +} + +void AdapterStub::SetUserInfo(const std::vector &userInfo) +{ + userInfo_ = userInfo; +} + +std::vector AdapterStub::GetUserInfo() +{ + return userInfo_; } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/adapter_stub.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/adapter_stub.h index 13c8396f315132e199d018502a914f9254222223..4d719aada1da4ebcccb7be15c3c46d6705bb9e9e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/adapter_stub.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/adapter_stub.h @@ -42,6 +42,8 @@ public: int GetLocalIdentity(std::string &outTarget) override; int SendBytes(const std::string &dstTarget, const uint8_t *bytes, uint32_t length, uint32_t totalLength) override; + int SendBytes(const DeviceInfos &deviceInfos, const uint8_t *bytes, uint32_t length, + uint32_t totalLength) override; int RegBytesReceiveCallback(const BytesReceiveCallback &onReceive, const Finalizer &inOper) override; int RegTargetChangeCallback(const TargetChangeCallback &onChange, const Finalizer &inOper) override; @@ -85,6 +87,9 @@ public: void SimulateSendBitErrorInPaddingLenField(bool doFlag, uint8_t inPaddingLen); void SimulateSendBitErrorInMessageIdField(bool doFlag, uint32_t inMessageId); void ForkSendBytes(const OnSendBytes &onSendBytes); + + void SetUserInfo(const std::vector &userInfo); + std::vector GetUserInfo(); private: void Connect(AdapterStub *inStub); void Disconnect(AdapterStub *inStub); @@ -137,6 +142,8 @@ private: std::mutex sendBytesMutex_; OnSendBytes onSendBytes_; + + std::vector userInfo_; }; } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp index 9b0b725ac930f00b8bfd6c72622b6654842c2a13..923f142159f5ae07958313c5ba724d913704666d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp @@ -56,12 +56,12 @@ void DistributedDBCommunicatorDeepTest::SetUpTestCase(void) * @tc.setup: Create and init CommunicatorAggregator and AdapterStub */ LOGI("[UT][DeepTest][SetUpTestCase] Enter."); - bool errCode = SetUpEnv(g_envDeviceA, DEVICE_NAME_A); - ASSERT_EQ(errCode, true); - errCode = SetUpEnv(g_envDeviceB, DEVICE_NAME_B); - ASSERT_EQ(errCode, true); - errCode = SetUpEnv(g_envDeviceC, DEVICE_NAME_C); - ASSERT_EQ(errCode, true); + bool isSuccess = SetUpEnv(g_envDeviceA, DEVICE_NAME_A); + ASSERT_EQ(isSuccess, true); + isSuccess = SetUpEnv(g_envDeviceB, DEVICE_NAME_B); + ASSERT_EQ(isSuccess, true); + isSuccess = SetUpEnv(g_envDeviceC, DEVICE_NAME_C); + ASSERT_EQ(isSuccess, true); DoRegTransformFunction(); CommunicatorAggregator::EnableCommunicatorNotFoundFeedback(false); } @@ -129,6 +129,9 @@ void DistributedDBCommunicatorDeepTest::TearDown() * @tc.teardown: Release communicator AA, AB, BB, BC, CC, CA */ ReleaseAllCommunicator(); + g_envDeviceA.commAggrHandle->ResetRetryCount(); + g_envDeviceB.commAggrHandle->ResetRetryCount(); + g_envDeviceC.commAggrHandle->ResetRetryCount(); std::this_thread::sleep_for(std::chrono::milliseconds(200)); // Wait 200 ms to make sure all thread quiet } @@ -136,7 +139,7 @@ void DistributedDBCommunicatorDeepTest::TearDown() * @tc.name: WaitAndRetrySend 001 * @tc.desc: Test send retry semantic * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorDeepTest, WaitAndRetrySend001, TestSize.Level2) @@ -145,10 +148,12 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, WaitAndRetrySend001, TestSize.Level2 Message *msgForBB = nullptr; g_commBB->RegOnMessageCallback([&msgForBB](const std::string &srcTarget, Message *inMsg) { msgForBB = inMsg; + return E_OK; }, nullptr); Message *msgForCA = nullptr; g_commCA->RegOnMessageCallback([&msgForCA](const std::string &srcTarget, Message *inMsg) { msgForCA = inMsg; + return E_OK; }, nullptr); /** @@ -169,7 +174,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, WaitAndRetrySend001, TestSize.Level2 */ Message *msgForAB = BuildRegedTinyMessage(); ASSERT_NE(msgForAB, nullptr); - SendConfig conf = {true, false, 0}; + SendConfig conf = {true, false, true, 0}; int errCode = g_commAB->SendMessage(DEVICE_NAME_B, msgForAB, conf); EXPECT_EQ(errCode, E_OK); @@ -195,6 +200,61 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, WaitAndRetrySend001, TestSize.Level2 // CleanUp AdapterStub::DisconnectAdapterStub(g_envDeviceA.adapterHandle, g_envDeviceB.adapterHandle); + AdapterStub::DisconnectAdapterStub(g_envDeviceA.adapterHandle, g_envDeviceC.adapterHandle); +} + +/** + * @tc.name: WaitAndRetrySend002 + * @tc.desc: Test send return retry but task not retry + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCommunicatorDeepTest, WaitAndRetrySend002, TestSize.Level2) +{ + // Preset + Message *msgForCA = nullptr; + g_commCA->RegOnMessageCallback([&msgForCA](const std::string &srcTarget, Message *inMsg) { + msgForCA = inMsg; + return E_OK; + }, nullptr); + + /** + * @tc.steps: step1. connect device A with device B + */ + AdapterStub::ConnectAdapterStub(g_envDeviceA.adapterHandle, g_envDeviceC.adapterHandle); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); // Wait 200 ms to make sure quiet + + /** + * @tc.steps: step2. device A simulate send retry + */ + g_envDeviceA.adapterHandle->SimulateSendRetry(DEVICE_NAME_B); + + /** + * @tc.steps: step3. device A send message to device B using communicator AB + * @tc.expected: step3. communicator BB received no message + */ + Message *msgForAB = BuildRegedTinyMessage(); + ASSERT_NE(msgForAB, nullptr); + SendConfig conf = {true, false, false, 0}; + OnSendEnd onSendEnd = [](int, int) { + LOGI("[WaitAndRetrySend002] on send end."); + }; + int errCode = g_commAB->SendMessage(DEVICE_NAME_B, msgForAB, conf, onSendEnd); + EXPECT_EQ(errCode, E_OK); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Wait 100 ms + EXPECT_EQ(msgForCA, nullptr); + + /** + * @tc.steps: step4. device A simulate sendable feedback + * @tc.expected: step4. communicator BB received the message + */ + g_envDeviceA.adapterHandle->SimulateSendRetryClear(DEVICE_NAME_B); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Wait 100 ms + + // CleanUp + AdapterStub::DisconnectAdapterStub(g_envDeviceA.adapterHandle, g_envDeviceC.adapterHandle); } static int CreateBufferThenAddIntoScheduler(SendTaskScheduler &scheduler, const std::string &dstTarget, Priority inPrio) @@ -223,7 +283,7 @@ static int CreateBufferThenAddIntoScheduler(SendTaskScheduler &scheduler, const * @tc.name: SendSchedule 001 * @tc.desc: Test schedule in Priority order than in send order * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorDeepTest, SendSchedule001, TestSize.Level2) @@ -322,7 +382,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, SendSchedule001, TestSize.Level2) * @tc.name: Fragment 001 * @tc.desc: Test fragmentation in send and receive * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment001, TestSize.Level2) @@ -331,6 +391,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment001, TestSize.Level2) Message *recvMsgForBB = nullptr; g_commBB->RegOnMessageCallback([&recvMsgForBB](const std::string &srcTarget, Message *inMsg) { recvMsgForBB = inMsg; + return E_OK; }, nullptr); /** @@ -345,7 +406,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment001, TestSize.Level2) const uint32_t dataLength = 13 * 1024 * 1024; // 13 MB, 1024 is scale Message *sendMsgForAB = BuildRegedGiantMessage(dataLength); ASSERT_NE(sendMsgForAB, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commAB->SendMessage(DEVICE_NAME_B, sendMsgForAB, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(2600)); // Wait 2600 ms to make sure send done @@ -377,7 +438,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment001, TestSize.Level2) * @tc.name: Fragment 002 * @tc.desc: Test fragmentation in partial loss * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment002, TestSize.Level2) @@ -386,6 +447,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment002, TestSize.Level2) Message *recvMsgForCC = nullptr; g_commCC->RegOnMessageCallback([&recvMsgForCC](const std::string &srcTarget, Message *inMsg) { recvMsgForCC = inMsg; + return E_OK; }, nullptr); /** @@ -406,7 +468,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment002, TestSize.Level2) uint32_t dataLength = 13 * 1024 * 1024; // 13 MB, 1024 is scale Message *sendMsgForBC = BuildRegedGiantMessage(dataLength); ASSERT_NE(sendMsgForBC, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commBC->SendMessage(DEVICE_NAME_C, sendMsgForBC, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(2600)); // Wait 2600 ms to make sure send done @@ -443,7 +505,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment002, TestSize.Level2) * @tc.name: Fragment 003 * @tc.desc: Test fragmentation simultaneously * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment003, TestSize.Level3) @@ -454,6 +516,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment003, TestSize.Level3) delete inMsg; inMsg = nullptr; count.fetch_add(1, std::memory_order_seq_cst); + return E_OK; }; g_commBB->RegOnMessageCallback(callback, nullptr); g_commBC->RegOnMessageCallback(callback, nullptr); @@ -477,7 +540,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment003, TestSize.Level3) uint32_t dataLength = 23 * 1024 * 1024; // 23 MB, 1024 is scale Message *sendMsgForAB = BuildRegedGiantMessage(dataLength); ASSERT_NE(sendMsgForAB, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commAB->SendMessage(DEVICE_NAME_B, sendMsgForAB, conf); EXPECT_EQ(errCode, E_OK); @@ -507,7 +570,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment003, TestSize.Level3) * @tc.name: Fragment 004 * @tc.desc: Test fragmentation in send and receive when rate limit * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment004, TestSize.Level2) @@ -518,6 +581,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment004, TestSize.Level2) Message *recvMsgForBB = nullptr; g_commBB->RegOnMessageCallback([&recvMsgForBB](const std::string &srcTarget, Message *inMsg) { recvMsgForBB = inMsg; + return E_OK; }, nullptr); AdapterStub::ConnectAdapterStub(g_envDeviceA.adapterHandle, g_envDeviceB.adapterHandle); std::atomic count = 0; @@ -535,7 +599,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment004, TestSize.Level2) const uint32_t dataLength = 13 * 1024 * 1024; // 13 MB, 1024 is scale Message *sendMsg = BuildRegedGiantMessage(dataLength); ASSERT_NE(sendMsg, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commAB->SendMessage(DEVICE_NAME_B, sendMsg, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::seconds(1)); // Wait 1s to make sure send done @@ -589,7 +653,7 @@ void ClearPreviousTestCaseInfluence() * @tc.name: ReliableOnline 001 * @tc.desc: Test device online reliability * @tc.type: FUNC - * @tc.require: AR000BVDGJ AR000CQE0N + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorDeepTest, ReliableOnline001, TestSize.Level2) @@ -649,7 +713,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, ReliableOnline001, TestSize.Level2) * @tc.name: NetworkAdapter001 * @tc.desc: Test networkAdapter start func * @tc.type: FUNC - * @tc.require: AR000BVDGJ + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter001, TestSize.Level1) @@ -715,7 +779,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter001, TestSize.Level1) * @tc.name: NetworkAdapter002 * @tc.desc: Test networkAdapter get mtu func * @tc.type: FUNC - * @tc.require: AR000BVDGJ + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter002, TestSize.Level1) @@ -746,7 +810,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter002, TestSize.Level1) * @tc.name: NetworkAdapter003 * @tc.desc: Test networkAdapter get timeout func * @tc.type: FUNC - * @tc.require: AR000BVDGJ + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter003, TestSize.Level1) @@ -775,7 +839,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter003, TestSize.Level1) * @tc.name: NetworkAdapter004 * @tc.desc: Test networkAdapter send bytes func * @tc.type: FUNC - * @tc.require: AR000BVDGJ + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter004, TestSize.Level1) @@ -836,7 +900,7 @@ void InitAdapter(const std::shared_ptr &adapter, * @tc.name: NetworkAdapter005 * @tc.desc: Test networkAdapter receive data func * @tc.type: FUNC - * @tc.require: AR000BVDGJ + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter005, TestSize.Level1) @@ -857,15 +921,15 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter005, TestSize.Level1) /** * @tc.steps: step2. adapter recv data with no permission */ - EXPECT_CALL(*processCommunicator, GetDataHeadInfo).WillRepeatedly([](const uint8_t *, uint32_t, uint32_t &) { + EXPECT_CALL(*processCommunicator, GetDataHeadInfo).WillRepeatedly([](DataHeadInfo, uint32_t &) { return NO_PERMISSION; }); onDataReceive(deviceInfos, data.get(), 1); - EXPECT_CALL(*processCommunicator, GetDataHeadInfo).WillRepeatedly([](const uint8_t *, uint32_t, uint32_t &) { + EXPECT_CALL(*processCommunicator, GetDataHeadInfo).WillRepeatedly([](DataHeadInfo, uint32_t &) { return OK; }); EXPECT_CALL(*processCommunicator, GetDataUserInfo).WillRepeatedly( - [](const uint8_t *, uint32_t, const std::string &, std::vector &userInfos) { + [](DataUserInfo, std::vector &userInfos) { UserInfo userId = {"1"}; userInfos.emplace_back(userId); return OK; @@ -874,7 +938,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter005, TestSize.Level1) * @tc.steps: step3. adapter recv data with no callback */ onDataReceive(deviceInfos, data.get(), 1); - adapter->RegBytesReceiveCallback([](const std::string &, const uint8_t *, uint32_t, const DataUserInfoProc &) { + adapter->RegBytesReceiveCallback([](const ReceiveBytesInfo &, const DataUserInfoProc &) { }, nullptr); onDataReceive(deviceInfos, data.get(), 1); RuntimeContext::GetInstance()->StopTaskPool(); @@ -884,7 +948,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter005, TestSize.Level1) * @tc.name: NetworkAdapter006 * @tc.desc: Test networkAdapter device change func * @tc.type: FUNC - * @tc.require: AR000BVDGJ + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter006, TestSize.Level1) @@ -933,7 +997,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter006, TestSize.Level1) * @tc.name: NetworkAdapter007 * @tc.desc: Test networkAdapter recv invalid head length * @tc.type: FUNC - * @tc.require: AR000BVDGJ + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter007, TestSize.Level1) @@ -948,7 +1012,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter007, TestSize.Level1) * @tc.steps: step1. GetDataHeadInfo return invalid headLen * @tc.expected: step1. adapter check this len */ - EXPECT_CALL(*processCommunicator, GetDataHeadInfo).WillOnce([](const uint8_t *, uint32_t, uint32_t &headLen) { + EXPECT_CALL(*processCommunicator, GetDataHeadInfo).WillOnce([](DataHeadInfo, uint32_t &headLen) { headLen = UINT32_MAX; return OK; }); @@ -957,14 +1021,16 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter007, TestSize.Level1) * @tc.expected: step2. BytesReceive never call */ int callByteReceiveCount = 0; - int res = adapter->RegBytesReceiveCallback([&callByteReceiveCount](const std::string &, const uint8_t *, uint32_t, + int res = adapter->RegBytesReceiveCallback([&callByteReceiveCount](const ReceiveBytesInfo &, const DataUserInfoProc &) { + LOGD("callByteReceiveCount++;"); callByteReceiveCount++; }, nullptr); EXPECT_EQ(res, E_OK); std::vector data = { 1u }; DeviceInfos deviceInfos; onDataReceive(deviceInfos, data.data(), 1u); + LOGD("callByteReceiveCount++%d;", callByteReceiveCount); EXPECT_EQ(callByteReceiveCount, 0); } @@ -999,7 +1065,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, RetrySendExceededLimit001, TestSize. const uint32_t dataLength = 13 * 1024 * 1024; // 13 MB, 1024 is scale Message *sendMsg = BuildRegedGiantMessage(dataLength); ASSERT_NE(sendMsg, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commAB->SendMessage(DEVICE_NAME_B, sendMsg, conf, sendResultNotifier); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::seconds(1)); // Wait 1s to make sure send done @@ -1044,7 +1110,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, RetrySendExceededLimit002, TestSize. const uint32_t dataLength = 13 * 1024 * 1024; // 13 MB, 1024 is scale Message *sendMsg = BuildRegedGiantMessage(dataLength); ASSERT_NE(sendMsg, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; EXPECT_EQ(g_commAB->SendMessage(DEVICE_NAME_B, sendMsg, conf, sendResultNotifier), E_OK); std::this_thread::sleep_for(std::chrono::seconds(1)); // Wait 1s to make sure send done diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_send_receive_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_send_receive_test.cpp index b3f7e8ff09af6c45eb94641bdd8c2314b9b56930..615ec7d7fa4a690b97b90138e8d691199f51dfbe 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_send_receive_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_send_receive_test.cpp @@ -138,13 +138,14 @@ static void CheckRecvMessage(Message *recvMsg, bool isEmpty, uint32_t msgId, uin [&srcTargetFor##src##label, &recvMsgFor##src##label](const std::string &srcTarget, Message *inMsg) { \ srcTargetFor##src##label = srcTarget; \ recvMsgFor##src##label = inMsg; \ + return E_OK; \ }, nullptr); /** * @tc.name: Send And Receive 001 * @tc.desc: Test send and receive based on equipment communicator * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive001, TestSize.Level1) @@ -165,7 +166,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive001, TestSize.L */ Message *msgForAA = BuildRegedTinyMessage(); ASSERT_NE(msgForAA, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0, {}}; int errCode = g_commAA->SendMessage(DEVICE_NAME_B, msgForAA, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(200)); // sleep 200 ms @@ -193,7 +194,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive001, TestSize.L * @tc.name: Send And Receive 002 * @tc.desc: Test send oversize message will fail * @tc.type: FUNC - * @tc.require: AR000BVDGK AR000CQE0O + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive002, TestSize.Level1) @@ -209,7 +210,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive002, TestSize.L */ Message *msgForAA = BuildRegedOverSizeMessage(); ASSERT_NE(msgForAA, nullptr); - SendConfig conf = {true, false, 0}; + SendConfig conf = {true, false, true, 0}; int errCode = g_commAA->SendMessage(DEVICE_NAME_B, msgForAA, conf); EXPECT_NE(errCode, E_OK); delete msgForAA; @@ -223,7 +224,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive002, TestSize.L * @tc.name: Send And Receive 003 * @tc.desc: Test send unregistered message will fail * @tc.type: FUNC - * @tc.require: AR000BVDGK AR000CQE0O + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive003, TestSize.Level1) @@ -239,7 +240,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive003, TestSize.L */ Message *msgForAA = BuildUnRegedTinyMessage(); ASSERT_NE(msgForAA, nullptr); - SendConfig conf = {true, false, 0}; + SendConfig conf = {true, false, true, 0}; int errCode = g_commAA->SendMessage(DEVICE_NAME_B, msgForAA, conf); EXPECT_NE(errCode, E_OK); delete msgForAA; @@ -292,13 +293,13 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive004, TestSize.L ASSERT_NE(msgForAAUser1, nullptr); Message *msgForAAUser2 = BuildRegedGiantMessage(HUGE_SIZE + HUGE_SIZE); ASSERT_NE(msgForAAUser2, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commAA->SendMessage(DEVICE_NAME_B, msgForAA, conf); EXPECT_EQ(errCode, E_OK); - SendConfig confUser1 = {false, true, 0, {"appId", "storeId", USER_ID_1, "DeviceB", ""}}; + SendConfig confUser1 = {false, true, true, 0, {"appId", "storeId", USER_ID_1, "DeviceB", ""}}; errCode = g_commAA->SendMessage(DEVICE_NAME_B, msgForAAUser1, confUser1); EXPECT_EQ(errCode, E_OK); - SendConfig confUser2 = {false, true, 0, {"appId", "storeId", USER_ID_2, "DeviceB", ""}}; + SendConfig confUser2 = {false, true, true, 0, {"appId", "storeId", USER_ID_2, "DeviceB", ""}}; errCode = g_commAA->SendMessage(DEVICE_NAME_B, msgForAAUser2, confUser2); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); @@ -324,7 +325,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive004, TestSize.L * @tc.name: Send Flow Control 001 * @tc.desc: Test send in nonblock way * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl001, TestSize.Level1) @@ -357,7 +358,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl001, TestSize. while (true) { Message *msgForBA = BuildRegedHugeMessage(); ASSERT_NE(msgForBA, nullptr); - SendConfig conf = {true, false, 0}; + SendConfig conf = {true, false, true, 0}; int errCode = g_commBA->SendMessage(DEVICE_NAME_A, msgForBA, conf); if (errCode == E_OK) { sendCount++; @@ -388,7 +389,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl001, TestSize. * @tc.name: Send Flow Control 002 * @tc.desc: Test send in block(without timeout) way * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl002, TestSize.Level1) @@ -422,7 +423,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl002, TestSize. while (sendCount < SEND_COUNT_GOAL) { Message *msgForBA = BuildRegedHugeMessage(); ASSERT_NE(msgForBA, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commBA->SendMessage(DEVICE_NAME_A, msgForBA, conf); if (errCode != E_OK) { delete msgForBA; @@ -454,7 +455,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl002, TestSize. * @tc.name: Send Flow Control 003 * @tc.desc: Test send in block(with timeout) way * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl003, TestSize.Level1) @@ -488,7 +489,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl003, TestSize. while (sendCnt < SEND_COUNT_GOAL) { Message *msgForBA = BuildRegedHugeMessage(); ASSERT_NE(msgForBA, nullptr); - SendConfig conf = {false, false, 100}; + SendConfig conf = {false, false, true, 100}; int errCode = g_commBA->SendMessage(DEVICE_NAME_A, msgForBA, conf); // 100 ms timeout if (errCode != E_OK) { delete msgForBA; @@ -520,7 +521,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl003, TestSize. * @tc.name: Receive Check 001 * @tc.desc: Receive packet field check * @tc.type: FUNC - * @tc.require: AR000BVRNU AR000CQE0J + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, ReceiveCheck001, TestSize.Level1) @@ -533,6 +534,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, ReceiveCheck001, TestSize.Lev delete inMsg; inMsg = nullptr; } + return E_OK; }, nullptr); AdapterStub::ConnectAdapterStub(g_envDeviceA.adapterHandle, g_envDeviceB.adapterHandle); @@ -542,7 +544,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, ReceiveCheck001, TestSize.Lev */ g_envDeviceB.adapterHandle->SimulateSendBitErrorInMagicField(true, 0xFFFF); Message *msgForBA = BuildRegedTinyMessage(); - SendConfig conf = {true, false, 0}; + SendConfig conf = {true, false, true, 0}; int errCode = g_commBA->SendMessage(DEVICE_NAME_A, msgForBA, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(100)); @@ -581,7 +583,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, ReceiveCheck001, TestSize.Lev * @tc.name: Receive Check 002 * @tc.desc: Receive packet field check * @tc.type: FUNC - * @tc.require: AR000BVRNU AR000CQE0J + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, ReceiveCheck002, TestSize.Level1) @@ -594,6 +596,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, ReceiveCheck002, TestSize.Lev delete inMsg; inMsg = nullptr; } + return E_OK; }, nullptr); AdapterStub::ConnectAdapterStub(g_envDeviceA.adapterHandle, g_envDeviceB.adapterHandle); @@ -603,7 +606,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, ReceiveCheck002, TestSize.Lev */ g_envDeviceB.adapterHandle->SimulateSendBitErrorInPacketLenField(true, 0xFFFF); Message *msgForBA = BuildRegedTinyMessage(); - SendConfig conf = {true, false, 0}; + SendConfig conf = {true, false, true, 0}; int errCode = g_commBA->SendMessage(DEVICE_NAME_A, msgForBA, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(100)); @@ -642,7 +645,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, ReceiveCheck002, TestSize.Lev * @tc.name: Send Result Notify 001 * @tc.desc: Test send result notify * @tc.type: FUNC - * @tc.require: AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendResultNotify001, TestSize.Level1) @@ -664,7 +667,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendResultNotify001, TestSize */ Message *msgForAA = BuildRegedTinyMessage(); ASSERT_NE(msgForAA, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commAA->SendMessage(DEVICE_NAME_B, msgForAA, conf, sendResultNotifier); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Sleep 100 ms @@ -693,7 +696,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendResultNotify001, TestSize * @tc.name: Message Feedback 001 * @tc.desc: Test feedback not support messageid and communicator not found * @tc.type: FUNC - * @tc.require: AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, MessageFeedback001, TestSize.Level1) @@ -715,7 +718,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, MessageFeedback001, TestSize. */ Message *msgForBB = BuildRegedTinyMessage(); ASSERT_NE(msgForBB, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commBB->SendMessage(DEVICE_NAME_A, msgForBB, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Sleep 100 ms @@ -765,7 +768,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, MessageFeedback001, TestSize. * @tc.name: SendAndReceiveWithExtendHead001 * @tc.desc: Test fill extendHead func * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceiveWithExtendHead001, TestSize.Level1) @@ -786,7 +789,9 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceiveWithExtendHead0 */ Message *msgForAA = BuildAppLayerFrameMessage(); ASSERT_NE(msgForAA, nullptr); - SendConfig conf = {false, true, 0, {"appId", "storeId", "", "DeviceB"}}; + UserInfo userInfo = {"", "userId"}; + g_envDeviceB.adapterHandle->SetUserInfo({userInfo}); + SendConfig conf = {false, true, true, 0, {"appId", "storeId", "", "DeviceB"}}; int errCode = g_commAA->SendMessage(DEVICE_NAME_B, msgForAA, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(200)); // sleep 200 ms diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_test.cpp index 8cda98e645ef16d4e08deefd4cfb42ae963dba9d..3106e52a8a461ac9b88036414824c1945f2d6457 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_test.cpp @@ -15,6 +15,7 @@ #include #include +#include "communicator.h" #include "db_common.h" #include "db_errno.h" #include "distributeddb_communicator_common.h" @@ -100,7 +101,7 @@ void DistributedDBCommunicatorTest::TearDown() * @tc.name: Communicator Management 001 * @tc.desc: Test alloc and release communicator * @tc.type: FUNC - * @tc.require: AR000BVDGG AR000CQE0L + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorTest, CommunicatorManagement001, TestSize.Level1) @@ -215,7 +216,7 @@ static void ConnectWaitDisconnect() * @tc.name: Online And Offline 001 * @tc.desc: Test functionality triggered by physical devices online and offline * @tc.type: FUNC - * @tc.require: AR000BVRNS AR000CQE0H + * @tc.require: * @tc.author: wudongxing */ HWTEST_F(DistributedDBCommunicatorTest, OnlineAndOffline001, TestSize.Level1) @@ -323,7 +324,7 @@ HWTEST_F(DistributedDBCommunicatorTest, OnlineAndOffline001, TestSize.Level1) * @tc.name: Online And Offline 002 * @tc.desc: Test functionality triggered by alloc and release communicator * @tc.type: FUNC - * @tc.require: AR000BVRNT AR000CQE0I + * @tc.require: * @tc.author: wudongxing */ HWTEST_F(DistributedDBCommunicatorTest, OnlineAndOffline002, TestSize.Level1) @@ -492,7 +493,7 @@ void TestRemoteRestart() * @tc.name: Online And Offline 003 * @tc.desc: Test functionality triggered by remote restart * @tc.type: FUNC - * @tc.require: AR000CQE0I + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, OnlineAndOffline003, TestSize.Level1) @@ -504,7 +505,7 @@ HWTEST_F(DistributedDBCommunicatorTest, OnlineAndOffline003, TestSize.Level1) * @tc.name: Online And Offline 004 * @tc.desc: Test functionality triggered by remote restart with thread pool * @tc.type: FUNC - * @tc.require: AR000CQE0I + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, OnlineAndOffline004, TestSize.Level1) @@ -519,7 +520,7 @@ HWTEST_F(DistributedDBCommunicatorTest, OnlineAndOffline004, TestSize.Level1) * @tc.name: Report Device Connect Change 001 * @tc.desc: Test CommunicatorAggregator support report device connect change event * @tc.type: FUNC - * @tc.require: AR000DR9KV + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorTest, ReportDeviceConnectChange001, TestSize.Level1) @@ -584,7 +585,7 @@ LabelType ToLabelType(uint64_t commLabel) * @tc.name: Report Communicator Not Found 001 * @tc.desc: Test CommunicatorAggregator support report communicator not found event * @tc.type: FUNC - * @tc.require: AR000DR9KV + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorTest, ReportCommunicatorNotFound001, TestSize.Level1) @@ -614,7 +615,7 @@ HWTEST_F(DistributedDBCommunicatorTest, ReportCommunicatorNotFound001, TestSize. ASSERT_NOT_NULL_AND_ACTIVATE(commAA, ""); Message *msgForAA = BuildRegedTinyMessage(); ASSERT_NE(msgForAA, nullptr); - SendConfig conf = {true, false, 0}; + SendConfig conf = {true, false, true, 0}; errCode = commAA->SendMessage(DEVICE_NAME_B, msgForAA, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Sleep 100 ms @@ -630,6 +631,7 @@ HWTEST_F(DistributedDBCommunicatorTest, ReportCommunicatorNotFound001, TestSize. Message *recvMsgForBA = nullptr; commBA->RegOnMessageCallback([&recvMsgForBA](const std::string &srcTarget, Message *inMsg) { recvMsgForBA = inMsg; + return E_OK; }, nullptr); commBA->Activate(USER_ID_1); std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Sleep 100 ms @@ -647,7 +649,7 @@ HWTEST_F(DistributedDBCommunicatorTest, ReportCommunicatorNotFound001, TestSize. Message *msgFor##src##label = BuildRegedTinyMessage(); \ ASSERT_NE(msgFor##src##label, nullptr); \ msgFor##src##label->SetSessionId(session); \ - SendConfig conf = {true, false, 0}; \ + SendConfig conf = {true, false, true, 0}; \ errCode = comm##src##label->SendMessage(DEVICE_NAME_##dst, msgFor##src##label, conf); \ EXPECT_EQ(errCode, E_OK); \ } @@ -656,7 +658,7 @@ HWTEST_F(DistributedDBCommunicatorTest, ReportCommunicatorNotFound001, TestSize. { \ Message *msgFor##src##label = BuildRegedGiantMessage(size); \ ASSERT_NE(msgFor##src##label, nullptr); \ - SendConfig conf = {false, false, 0}; \ + SendConfig conf = {false, false, true, 0}; \ errCode = comm##src##label->SendMessage(DEVICE_NAME_##dst, msgFor##src##label, conf); \ EXPECT_EQ(errCode, E_OK); \ } @@ -673,13 +675,14 @@ HWTEST_F(DistributedDBCommunicatorTest, ReportCommunicatorNotFound001, TestSize. [&srcTargetFor##src##label, &recvMsgFor##src##label](const std::string &srcTarget, Message *inMsg) { \ srcTargetFor##src##label = srcTarget; \ recvMsgFor##src##label = inMsg; \ + return E_OK; \ }, nullptr); /** * @tc.name: ReDeliver Message 001 * @tc.desc: Test CommunicatorAggregator support redeliver message * @tc.type: FUNC - * @tc.require: AR000DR9KV + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorTest, ReDeliverMessage001, TestSize.Level1) @@ -762,7 +765,7 @@ HWTEST_F(DistributedDBCommunicatorTest, ReDeliverMessage001, TestSize.Level1) * @tc.name: ReDeliver Message 002 * @tc.desc: Test CommunicatorAggregator support redeliver message by order * @tc.type: FUNC - * @tc.require: AR000DR9KV + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorTest, ReDeliverMessage002, TestSize.Level1) @@ -814,6 +817,7 @@ HWTEST_F(DistributedDBCommunicatorTest, ReDeliverMessage002, TestSize.Level1) std::vector> msgCallbackForBA; commBA->RegOnMessageCallback([&msgCallbackForBA](const std::string &srcTarget, Message *inMsg) { msgCallbackForBA.push_back({srcTarget, inMsg}); + return E_OK; }, nullptr); commBA->Activate(); std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Sleep 100 ms @@ -842,7 +846,7 @@ HWTEST_F(DistributedDBCommunicatorTest, ReDeliverMessage002, TestSize.Level1) * @tc.name: ReDeliver Message 003 * @tc.desc: For observe memory in unusual scenario * @tc.type: FUNC - * @tc.require: AR000DR9KV + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorTest, ReDeliverMessage003, TestSize.Level2) @@ -940,7 +944,7 @@ namespace { * @tc.name: CommunicationOptimization001 * @tc.desc: Test notify with isSupport true. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization001, TestSize.Level3) @@ -1019,7 +1023,7 @@ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization001, TestSize.L * @tc.name: CommunicationOptimization002 * @tc.desc: Test notify with isSupport true and can offline by device change. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization002, TestSize.Level3) @@ -1077,7 +1081,7 @@ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization002, TestSize.L * @tc.name: CommunicationOptimization003 * @tc.desc: Test notify with isSupport false. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization003, TestSize.Level3) @@ -1146,7 +1150,7 @@ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization003, TestSize.L * @tc.name: CommunicationOptimization004 * @tc.desc: Test notify with isSupport false and it be will changed by communication. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization004, TestSize.Level3) @@ -1195,7 +1199,7 @@ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization004, TestSize.L * @tc.name: CommunicationOptimization005 * @tc.desc: Test notify with isSupport false and send label exchange. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization005, TestSize.Level3) @@ -1248,7 +1252,7 @@ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization005, TestSize.L * @tc.name: DbStatusAdapter001 * @tc.desc: Test notify with isSupport false. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter001, TestSize.Level1) @@ -1307,7 +1311,7 @@ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter001, TestSize.Level1) * @tc.name: DbStatusAdapter002 * @tc.desc: Test adapter clear cache. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter002, TestSize.Level1) { @@ -1326,7 +1330,7 @@ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter002, TestSize.Level1) { * @tc.name: DbStatusAdapter003 * @tc.desc: Test adapter get local dbInfo. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter003, TestSize.Level1) { @@ -1347,7 +1351,7 @@ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter003, TestSize.Level1) { * @tc.name: DbStatusAdapter004 * @tc.desc: Test adapter clear cache will get callback. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter004, TestSize.Level1) @@ -1390,7 +1394,7 @@ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter004, TestSize.Level1) * @tc.name: DbStatusAdapter005 * @tc.desc: Test adapter is need auto sync. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter005, TestSize.Level1) @@ -1410,4 +1414,39 @@ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter005, TestSize.Level1) adapterA->SetDBInfoHandle(nullptr); EXPECT_EQ(adapterA->IsNeedAutoSync(USER_ID, APP_ID, STORE_ID_1, deviceB), true); } + +/** + * @tc.name: AbnormalCommunicatorTest001 + * @tc.desc: Test communicator abnormal. + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBCommunicatorTest, AbnormalCommunicatorTest001, TestSize.Level1) +{ + ICommunicator *commAA = nullptr; + g_envDeviceA.commAggrHandle->ReleaseCommunicator(commAA); + EXPECT_EQ(commAA, nullptr); + int errCode = E_OK; + commAA = g_envDeviceA.commAggrHandle->AllocCommunicator(LABEL_A, errCode); + SendConfig conf = {true, false, true, 0}; + Message *msgForAA = nullptr; + errCode = commAA->SendMessage(DEVICE_NAME_A, msgForAA, conf); + EXPECT_NE(errCode, E_OK); + msgForAA = BuildRegedTinyMessage(); + ASSERT_NE(msgForAA, nullptr); + errCode = commAA->SendMessage("", msgForAA, conf); + EXPECT_NE(errCode, E_OK); + errCode = commAA->SendMessage(DEVICE_NAME_B, msgForAA, conf); + EXPECT_EQ(errCode, E_OK); + EXPECT_EQ(commAA->GetTargetUserId({}), std::string("")); + g_envDeviceA.commAggrHandle->ClearOnlineLabel(); + std::vector label; + auto aggregator = std::make_shared(); + ASSERT_NE(aggregator, nullptr); + auto communicator = std::make_shared(aggregator.get(), label); + ASSERT_NE(communicator, nullptr); + EXPECT_EQ(communicator->GetTargetUserId({}), DBConstant::DEFAULT_USER); + g_envDeviceA.commAggrHandle->ReleaseCommunicator(commAA); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/mock_process_communicator.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/mock_process_communicator.h index 0c60f3ea94f84c2a5b11ea9fe4bef9c6afc72226..24e46f611309336167890674f552322dfa256459 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/mock_process_communicator.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/mock_process_communicator.h @@ -30,8 +30,8 @@ public: MOCK_METHOD0(GetLocalDeviceInfos, DeviceInfos()); MOCK_METHOD0(GetRemoteOnlineDeviceInfosList, std::vector()); MOCK_METHOD1(IsSameProcessLabelStartedOnPeerDevice, bool(const DeviceInfos &)); - MOCK_METHOD3(GetDataHeadInfo, DBStatus(const uint8_t *, uint32_t, uint32_t &)); - MOCK_METHOD4(GetDataUserInfo, DBStatus(const uint8_t *, uint32_t, const std::string &, std::vector &)); + MOCK_METHOD2(GetDataUserInfo, DBStatus(DataUserInfo, std::vector &)); + MOCK_METHOD2(GetDataHeadInfo, DBStatus(DataHeadInfo, uint32_t &)); }; } #endif // MOCK_PROCESS_COMMUNICATOR_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_reference_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_reference_test.cpp index 97d452cba2b6056af0a8d03549bfe9468f49d57f..b411d4d8a4bcb3785c1723e0fc30fa4413f8e0de 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_reference_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_reference_test.cpp @@ -20,7 +20,9 @@ #include "db_constant.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" +#include "relational_store_delegate_impl.h" #include "relational_store_manager.h" +#include "virtual_communicator_aggregator.h" using namespace testing::ext; using namespace DistributedDB; @@ -35,6 +37,7 @@ namespace { std::string g_storePath; DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); RelationalStoreDelegate *g_delegate = nullptr; + VirtualCommunicatorAggregator *g_communicatorAggregator = nullptr; class DistributedDBCloudInterfacesReferenceTest : public testing::Test { public: @@ -59,6 +62,9 @@ namespace { void DistributedDBCloudInterfacesReferenceTest::SetUp(void) { + g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(g_communicatorAggregator != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator); sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath); ASSERT_NE(db, nullptr); EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); @@ -74,6 +80,7 @@ namespace { EXPECT_EQ(g_mgr.CloseStore(g_delegate), OK); g_delegate = nullptr; DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); } /** @@ -493,7 +500,7 @@ namespace { * @tc.require: * @tc.author: zhangshjie */ - HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest010, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest010, TestSize.Level1) { NormalSetReferenceTest(true); } @@ -541,11 +548,7 @@ namespace { * @tc.expected: step3. Return OK or PROPERTY_CHANGED. */ tableReferenceProperty.targetTableName = "t3"; - if (isTableEmpty) { - EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); - } else { - EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); - } + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); /** * @tc.steps:step4. set reference again with different column reference @@ -553,11 +556,7 @@ namespace { */ columns["id"] = "value"; tableReferenceProperty.columns = columns; - if (isTableEmpty) { - EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); - } else { - EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); - } + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); } @@ -569,7 +568,7 @@ namespace { * @tc.require: * @tc.author: zhangshjie */ - HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest011, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest011, TestSize.Level1) { ReferenceChangeTest(true); } @@ -581,7 +580,7 @@ namespace { * @tc.require: * @tc.author: zhangshjie */ - HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest012, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest012, TestSize.Level1) { ReferenceChangeTest(false); } @@ -593,7 +592,7 @@ namespace { * @tc.require: * @tc.author: zhangshjie */ - HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest013, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest013, TestSize.Level1) { /** * @tc.steps:step1. prepare table and distributed table @@ -669,7 +668,7 @@ namespace { * @tc.require: * @tc.author: zhangshjie */ - HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest014, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest014, TestSize.Level1) { /** * @tc.steps:step1. prepare table and distributed table @@ -755,7 +754,7 @@ namespace { * @tc.require: * @tc.author: zhangshjie */ - HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest015, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest015, TestSize.Level1) { /** * @tc.steps:step1. prepare table and distributed table @@ -802,7 +801,7 @@ namespace { * @tc.require: * @tc.author: zhangshjie */ - HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest016, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest016, TestSize.Level1) { /** * @tc.steps:step1. prepare table and distributed table, then set reference t1->t2 @@ -843,7 +842,7 @@ namespace { */ tableReferenceProperty.sourceTableName = "t2"; tableReferenceProperty.targetTableName = "t3"; - EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); } /** @@ -884,4 +883,36 @@ namespace { tableReferenceProperty.columns = columns; EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); } + + /** + * @tc.name: FuncExceptionTest001 + * @tc.desc: Test the interception expection of the delegate interface when the conn is empty. + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, FuncExceptionTest001, TestSize.Level1) + { + RelationalStoreConnection *iConn = nullptr; + std::string iPath = ""; + auto iDelegate = std::make_shared(iConn, iPath); + EXPECT_EQ(iDelegate->SetStoreConfig({}), OK); + EXPECT_EQ(iDelegate->SetStoreConfig({DistributedTableMode::COLLABORATION}), DB_ERROR); + + ClearMetaDataOption iOption; + iOption.tableNameList.insert(STORE_ID); + #ifdef USE_DISTRIBUTEDDB_CLOUD + EXPECT_EQ(iDelegate->ClearMetaData(iOption), NOT_SUPPORT); + iOption.tableNameList.clear(); + EXPECT_EQ(iDelegate->ClearMetaData(iOption), DB_ERROR); + #endif + iOption.mode = ClearMetaDataMode::BUTT; + EXPECT_EQ(iDelegate->ClearMetaData(iOption), INVALID_ARGS); + + EXPECT_EQ(iDelegate->GetDownloadingAssetsCount().first, DB_ERROR); + EXPECT_EQ(iDelegate->SetDistributedSchema({}, false), DB_ERROR); + + iDelegate->SetReleaseFlag(false); + iDelegate = nullptr; + } } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_client_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_client_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..050b223363cdea8c5e7d25f042cfd0989fe31712 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_client_test.cpp @@ -0,0 +1,1477 @@ +/* + * Copyright (c) 2025 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 + +#include "cloud_db_sync_utils_test.h" +#include "cloud_sync_log_table_manager.h" +#include "distributeddb_tools_unit_test.h" +#include "relational_store_client.h" +#include "simple_tracker_log_table_manager.h" +#include "sqlite_relational_utils.h" +#include "table_info.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; +using namespace std; + +namespace { +constexpr const char *DB_SUFFIX = ".db"; +constexpr const char *STORE_ID = "Relational_Store_ID"; +std::string g_dbDir; +std::string g_testDir; + +constexpr int E_ERROR = 1; +const int WAIT_TIME = 1000; // 1000ms +constexpr static uint64_t TO_100_NS = 10; // 1us to 100ns +const uint64_t MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS = 1000000; +std::mutex g_mutex; +std::condition_variable g_cv; +bool g_alreadyNotify = false; + +class DistributedDBCloudInterfacesRelationalExtClientTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp() override; + void TearDown() override; + void CheckTriggerObserverTest002(const std::string &tableName, std::atomic &count); + + void ClientObserverFunc(ClientChangedData &clientChangedData) + { + for (const auto &tableEntry : clientChangedData.tableData) { + LOGD("client observer fired, table: %s", tableEntry.first.c_str()); + triggerTableData_.insert_or_assign(tableEntry.first, tableEntry.second); + } + triggeredCount_++; + { + std::unique_lock lock(g_mutex); + g_alreadyNotify = true; + } + g_cv.notify_one(); + } + + void ClientObserverFunc2(ClientChangedData &clientChangedData) + { + triggeredCount2_++; + { + std::unique_lock lock(g_mutex); + g_alreadyNotify = true; + } + g_cv.notify_one(); + } + + void CheckTriggerTableData(size_t dataSize, const std::string &tableName, ChangeProperties &properties, + int triggerCount) + { + ASSERT_EQ(triggerTableData_.size(), dataSize); + EXPECT_EQ(triggerTableData_.begin()->first, tableName); + EXPECT_EQ(triggerTableData_.begin()->second.isTrackedDataChange, properties.isTrackedDataChange); + EXPECT_EQ(triggeredCount_, triggerCount); + } + + void WaitAndResetNotify() + { + std::unique_lock lock(g_mutex); + WaitAndResetNotifyWithLock(lock); + } + + void WaitAndResetNotifyWithLock(std::unique_lock &lock) + { + g_cv.wait(lock, []() { + return g_alreadyNotify; + }); + g_alreadyNotify = false; + } + + std::map triggerTableData_; + int triggeredCount_ = 0; + int triggeredCount2_ = 0; +}; + +void DistributedDBCloudInterfacesRelationalExtClientTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + LOGD("Test dir is %s", g_testDir.c_str()); + g_dbDir = g_testDir + "/"; + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); +} + +void DistributedDBCloudInterfacesRelationalExtClientTest::TearDownTestCase(void) +{ +} + +void DistributedDBCloudInterfacesRelationalExtClientTest::SetUp() +{ +} + +void DistributedDBCloudInterfacesRelationalExtClientTest::TearDown() +{ + g_alreadyNotify = false; + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); +} + +void DistributedDBCloudInterfacesRelationalExtClientTest::CheckTriggerObserverTest002(const std::string &tableName, + std::atomic &count) +{ + count++; + ASSERT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(triggerTableData_.begin()->first, tableName); + EXPECT_EQ(triggerTableData_.begin()->second.isTrackedDataChange, false); + EXPECT_EQ(triggeredCount_, count); +} + +static int GetCurrentSysTimeIn100Ns(uint64_t &outTime) +{ + struct timeval rawTime; + int errCode = gettimeofday(&rawTime, nullptr); + if (errCode < 0) { + return -E_ERROR; + } + outTime = static_cast(rawTime.tv_sec) * MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS + + static_cast(rawTime.tv_usec); + outTime *= TO_100_NS; + return E_OK; +} + +static void ExecSqlAndWaitForObserver(sqlite3 *db, const std::string &sql, std::unique_lock &lock) +{ + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + g_cv.wait(lock, []() { + return g_alreadyNotify; + }); + g_alreadyNotify = false; +} + +/** + * @tc.name: GetRawSysTimeTest001 + * @tc.desc: Test get_raw_sys_time has been registered in sqlite + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, GetRawSysTimeTest001, TestSize.Level0) +{ + const std::string sql = "select get_raw_sys_time();"; + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + uint64_t curTime = 0; + int errCode = GetCurrentSysTimeIn100Ns(curTime); + EXPECT_EQ(errCode, E_OK); + errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [curTime] (sqlite3_stmt *stmt) { + EXPECT_GT(static_cast(sqlite3_column_int64(stmt, 0)), curTime); + return E_OK; + }); + EXPECT_EQ(errCode, SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +static void PrepareData(const std::vector &tableNames, bool primaryKeyIsRowId, + DistributedDB::TableSyncType tableSyncType, bool userDefineRowid = true, bool createDistributeTable = true) +{ + /** + * @tc.steps:step1. create db, create table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + std::string sql; + for (const auto &tableName : tableNames) { + if (primaryKeyIsRowId) { + sql = "create table " + tableName + "(rowid INTEGER primary key, id int, name TEXT);"; + } else { + if (userDefineRowid) { + sql = "create table " + tableName + "(rowid int, id int, name TEXT, PRIMARY KEY(id));"; + } else { + sql = "create table " + tableName + "(id int, name TEXT, PRIMARY KEY(id));"; + } + } + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + + /** + * @tc.steps:step2. create distributed table. + * @tc.expected: step2. return ok. + */ + if (createDistributeTable) { + for (const auto &tableName : tableNames) { + TableInfo table; + table.SetTableName(tableName); + table.SetTableSyncType(tableSyncType); + std::unique_ptr tableManager = std::make_unique(); + EXPECT_NE(tableManager, nullptr); + EXPECT_EQ(SQLiteUtils::AnalysisSchema(db, tableName, table), E_OK); + std::vector fieldInfos = table.GetFieldInfos(); + EXPECT_EQ(SQLiteRelationalUtils::CreateRelationalMetaTable(db), E_OK); + EXPECT_EQ(SQLiteRelationalUtils::InitCursorToMeta(db, false, tableName), E_OK); + EXPECT_EQ(tableManager->CreateRelationalLogTable(db, table), E_OK); + EXPECT_EQ(tableManager->AddRelationalLogTableTrigger(db, table, ""), E_OK); + EXPECT_EQ(SQLiteRelationalUtils::SetLogTriggerStatus(db, true), E_OK); + } + } + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +static void SaveTrackerSchemaToMetaTable(sqlite3 *db, const std::string tableName, const TableInfo &tableInfo) +{ + RelationalSchemaObject tracker; + tracker.SetTableMode(DistributedDB::DistributedTableMode::SPLIT_BY_DEVICE); + tracker.RemoveRelationalTable(tableName); + tracker.AddRelationalTable(tableInfo); + const Key schemaKey(DBConstant::RELATIONAL_SCHEMA_KEY, + DBConstant::RELATIONAL_SCHEMA_KEY + strlen(DBConstant::RELATIONAL_SCHEMA_KEY)); + Value schemaVal; + auto schemaStr = tracker.ToSchemaString(); + EXPECT_FALSE(schemaStr.size() > SchemaConstant::SCHEMA_STRING_SIZE_LIMIT); + DBCommon::StringToVector(schemaStr, schemaVal); + EXPECT_EQ(SQLiteRelationalUtils::PutKvData(db, false, schemaKey, schemaVal), E_OK); +} + +static void SetTracerSchema(const std::vector &tableNames, DistributedDB::TableSyncType tableSyncType) +{ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + for (const auto &tableName : tableNames) { + TableInfo tableInfo; + tableInfo.SetTableName(tableName); + tableInfo.SetTableSyncType(tableSyncType); + std::unique_ptr tableManager = std::make_unique(); + EXPECT_NE(tableManager, nullptr); + TrackerSchema schema; + schema.tableName = tableName; + schema.extendColNames = {"id"}; + schema.trackerColNames = {"name"}; + TrackerTable trackerTable; + trackerTable.Init(schema); + EXPECT_EQ(SQLiteRelationalUtils::AnalysisTrackerTable(db, trackerTable, tableInfo), E_OK); + EXPECT_EQ(tableManager->CreateRelationalLogTable(db, tableInfo), E_OK); + EXPECT_EQ(SQLiteRelationalUtils::InitCursorToMeta(db, false, tableName), E_OK); + EXPECT_EQ(SQLiteRelationalUtils::SetLogTriggerStatus(db, true), E_OK); + EXPECT_EQ(tableManager->AddRelationalLogTableTrigger(db, tableInfo, ""), E_OK); + SaveTrackerSchemaToMetaTable(db, tableName, tableInfo); + } + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: InsertTriggerTest003 + * @tc.desc: Test insert trigger in sqlite when use "insert or replace" + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, InsertTriggerTest003, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION); + + /** + * @tc.steps:step2. insert data into sync_data. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + std::string sql = "insert into " + tableName + " VALUES(2, 1, 'zhangsan1');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + // update cloud_gid in log table + std::string gid = "test_gid"; + sql = "update " + DBCommon::GetLogTableName(tableName) + " set cloud_gid = '" + gid + "'"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + // use insert or replace to update data + sql = "insert or replace into " + tableName + " VALUES(3, 1, 'zhangsan1');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + /** + * @tc.steps:step3. select data from log table. + * @tc.expected: step3. return ok. + */ + sql = "select data_key, device, ori_device, flag, cloud_gid from " + DBCommon::GetLogTableName(tableName); + int resultCount = 0; + int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&resultCount, gid] (sqlite3_stmt *stmt) { + EXPECT_EQ(sqlite3_column_int64(stmt, 0), 2); // 2 is row id + std::string device = ""; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, device), E_OK); + EXPECT_EQ(device, ""); + std::string oriDevice = ""; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 2, oriDevice), E_OK); // 2 is column index + EXPECT_EQ(oriDevice, ""); + + EXPECT_EQ(sqlite3_column_int(stmt, 3), 0x02|0x20); // 3 is column index flag == 0x02|0x20 + std::string gidStr; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 4, gidStr), E_OK); // 4 is column index + EXPECT_EQ(gid, gidStr); + resultCount++; + return E_OK; + }); + EXPECT_EQ(errCode, SQLITE_OK); + EXPECT_EQ(resultCount, 1); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +static void UpdateTriggerTest(bool primaryKeyIsRowId) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, primaryKeyIsRowId, DistributedDB::CLOUD_COOPERATION); + + /** + * @tc.steps:step2. insert data into sync_data_tmp. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + std::string sql = "insert into " + tableName + " VALUES(2, 1, 'zhangsan');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + /** + * @tc.steps:step3. update data. + * @tc.expected: step3. return ok. + */ + std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); + sql = "update " + tableName + " set name = 'lisi';"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + /** + * @tc.steps:step4. select data from log table. + * @tc.expected: step4. return ok. + */ + sql = "select * from " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log;"; + uint64_t curTime = 0; + int errCode = GetCurrentSysTimeIn100Ns(curTime); + EXPECT_EQ(errCode, E_OK); + + int resultCount = 0; + errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [curTime, &resultCount, primaryKeyIsRowId] ( + sqlite3_stmt *stmt) { + if (primaryKeyIsRowId) { + EXPECT_EQ(sqlite3_column_int64(stmt, 0), 2); // 2 is row id + } else { + EXPECT_EQ(sqlite3_column_int64(stmt, 0), 1); // 1 is row id + } + + EXPECT_EQ(sqlite3_column_int(stmt, 5), 0x02|0x20); // 5 is column index, flag == 0x02|0x20 + + std::string device = ""; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, device), E_OK); + EXPECT_EQ(device, ""); + std::string oriDevice = ""; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 2, oriDevice), E_OK); // 2 is column index + EXPECT_EQ(oriDevice, ""); + + int64_t timestamp = sqlite3_column_int64(stmt, 3); // 3 is column index + int64_t wtimestamp = sqlite3_column_int64(stmt, 4); // 4 is column index + int64_t diff = MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS * TO_100_NS; + EXPECT_TRUE(timestamp - wtimestamp > diff); + EXPECT_TRUE(static_cast(curTime - timestamp) < diff); + + resultCount++; + return E_OK; + }); + EXPECT_EQ(errCode, SQLITE_OK); + EXPECT_EQ(resultCount, 1); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: UpdateTriggerTest001 + * @tc.desc: Test update trigger in sqlite for primary key is not row id + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, UpdateTriggerTest001, TestSize.Level1) +{ + UpdateTriggerTest(false); +} + +/** + * @tc.name: UpdateTriggerTest002 + * @tc.desc: Test update trigger in sqlite for primary key is row id + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, UpdateTriggerTest002, TestSize.Level1) +{ + UpdateTriggerTest(true); +} + +/** + * @tc.name: DeleteTriggerTest001 + * @tc.desc: Test delete trigger in sqlite + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, DeleteTriggerTest001, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, true, DistributedDB::CLOUD_COOPERATION); + + /** + * @tc.steps:step2. insert data into sync_data. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + std::string sql = "insert into " + tableName + " VALUES(2, 1, 'zhangsan');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + /** + * @tc.steps:step3. delete data. + * @tc.expected: step3. return ok. + */ + std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); + sql = "delete from " + tableName + " where name = 'zhangsan';"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + /** + * @tc.steps:step4. select data from log table. + * @tc.expected: step4. return ok. + */ + sql = "select * from " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log;"; + uint64_t curTime = 0; + int errCode = GetCurrentSysTimeIn100Ns(curTime); + EXPECT_EQ(errCode, E_OK); + + int resultCount = 0; + errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [curTime, &resultCount] (sqlite3_stmt *stmt) { + EXPECT_EQ(sqlite3_column_int64(stmt, 0), -1); + EXPECT_EQ(sqlite3_column_int(stmt, 5), 3); // 5 is column index, flag == 3 + + std::string device = "de"; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, device), E_OK); + EXPECT_EQ(device, ""); + std::string oriDevice = "de"; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 2, oriDevice), E_OK); // 2 is column index + EXPECT_EQ(oriDevice, ""); + + int64_t timestamp = sqlite3_column_int64(stmt, 3); // 3 is column index + int64_t wtimestamp = sqlite3_column_int64(stmt, 4); // 4 is column index + int64_t diff = MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS * TO_100_NS; + EXPECT_TRUE(timestamp - wtimestamp > diff); + EXPECT_TRUE(static_cast(curTime - timestamp) < diff); + + resultCount++; + return E_OK; + }); + EXPECT_EQ(errCode, SQLITE_OK); + EXPECT_EQ(resultCount, 1); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: TriggerObserverTest001 + * @tc.desc: Test invalid args for RegisterClientObserver and UnRegisterClientObserver + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, TriggerObserverTest001, TestSize.Level0) +{ + /** + * @tc.steps:step1. call RegisterClientObserver and UnRegisterClientObserver with db = nullptr. + * @tc.expected: step1. return INVALID_ARGS. + */ + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(nullptr, clientObserver), INVALID_ARGS); + EXPECT_EQ(UnRegisterClientObserver(nullptr), INVALID_ARGS); + + /** + * @tc.steps:step2. call RegisterClientObserver with nullptr clientObserver. + * @tc.expected: step2. return INVALID_ARGS. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + EXPECT_EQ(RegisterClientObserver(db, nullptr), INVALID_ARGS); + + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: TriggerObserverTest002 + * @tc.desc: Test trigger client observer in sqlite + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, TriggerObserverTest002, TestSize.Level0) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false); + + /** + * @tc.steps:step2. register client observer. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + RegisterDbHook(db); + + /** + * @tc.steps:step3. insert data into sync_data, check observer. + * @tc.expected: step3. check observer ok. + */ + std::string sql = "insert into " + tableName + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + WaitAndResetNotify(); + std::atomic count = 0; // 0 is observer triggered counts + CheckTriggerObserverTest002(tableName, count); + + /** + * @tc.steps:step4. update data, check observer. + * @tc.expected: step4. check observer ok. + */ + sql = "update " + tableName + " set name = 'lisi1' where id = 2;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + WaitAndResetNotify(); + CheckTriggerObserverTest002(tableName, count); + + /** + * @tc.steps:step4. delete data, check observer. + * @tc.expected: step4. check observer ok. + */ + sql = "delete from " + tableName + " where id = 3;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + WaitAndResetNotify(); + CheckTriggerObserverTest002(tableName, count); + + /** + * @tc.steps:step5. register another observer, update data, check observer. + * @tc.expected: step5. check observer ok. + */ + triggeredCount_ = 0; + ClientObserver clientObserver2 = + std::bind(&DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc2, this, + std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver2), OK); + RegisterDbHook(db); + sql = "update " + tableName + " set name = 'lisi2' where id = 2;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + WaitAndResetNotify(); + EXPECT_EQ(triggeredCount_, 0); + EXPECT_EQ(triggeredCount2_, 1); + + /** + * @tc.steps:step6. UnRegisterClientObserver, update data, check observer. + * @tc.expected: step6. check observer ok. + */ + triggeredCount2_ = 0; + EXPECT_EQ(UnRegisterClientObserver(db), OK); + sql = "update " + tableName + " set name = 'lisi3' where id = 2;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + EXPECT_EQ(triggeredCount2_, 0); // observer2 will not be triggered + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: TriggerObserverTest003 + * @tc.desc: Test RegisterClientObserver and UnRegisterClientObserver concurrently + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, TriggerObserverTest003, TestSize.Level1) +{ + for (int i = 0; i < 1000; i++) { // 1000 is loop times + std::thread t1 ([this]() { + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind( + &DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc, this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); + }); + + std::thread t2 ([this]() { + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind( + &DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc2, this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); + }); + + t1.join(); + t2.join(); + } +} + +/** + * @tc.name: TriggerObserverTest004 + * @tc.desc: Test batch insert/update/delete data then trigger client observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, TriggerObserverTest004, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false); + + /** + * @tc.steps:step2. register client observer. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + RegisterDbHook(db); + + /** + * @tc.steps:step3. insert data into sync_data, check observer. + * @tc.expected: step3. check observer ok. + */ + std::string sql; + int dataCounts = 1000; // 1000 is count of insert options. + for (int i = 1; i <= dataCounts; i++) { + sql = "insert into " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" + std::to_string(i) + "');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + std::unique_lock lock(g_mutex); + bool isEqual = g_cv.wait_for(lock, std::chrono::seconds(1), [this, dataCounts]() { // 1 is wait time + return triggeredCount_ == dataCounts; + }); + EXPECT_EQ(isEqual, true); + WaitAndResetNotifyWithLock(lock); + ASSERT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(triggerTableData_.begin()->first, tableName); + EXPECT_EQ(triggeredCount_, dataCounts); + + /** + * @tc.steps:step4. insert or replace, check observer. + * @tc.expected: step5. check observer ok. + */ + triggeredCount_ = 0; + sql = "insert or replace into " + tableName + " VALUES(1000, 'lisi');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + isEqual = g_cv.wait_for(lock, std::chrono::seconds(1), [this]() { // 1 is wait time + return triggeredCount_ == 1; + }); + EXPECT_EQ(isEqual, true); + WaitAndResetNotifyWithLock(lock); + EXPECT_EQ(triggeredCount_, 1); // 1 is trigger times, first delete then insert + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: TriggerObserverTest005 + * @tc.desc: Test commit and rollback for one table then trigger client observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, TriggerObserverTest005, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false); + + /** + * @tc.steps:step2. register client observer. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + RegisterDbHook(db); + + /** + * @tc.steps:step3. begin transaction and commit. + * @tc.expected: step3. check observer ok. + */ + std::string sql = "begin;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + int dataCounts = 1000; // 1000 is count of insert options. + for (int i = 1; i <= dataCounts; i++) { + sql = "insert into " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" + std::to_string(i) + "');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + sql = "commit;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + WaitAndResetNotify(); + ASSERT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(triggerTableData_.begin()->first, tableName); + EXPECT_EQ(triggeredCount_, 1); + + /** + * @tc.steps:step4. begin transaction and rollback. + * @tc.expected: step3. check observer ok. + */ + triggerTableData_.clear(); + triggeredCount_ = 0; + sql = "begin;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + for (int i = dataCounts + 1; i <= 2 * dataCounts; i++) { // 2 is double dataCounts + sql = "insert into " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" + std::to_string(i) + "');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + sql = "rollback;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + EXPECT_TRUE(triggerTableData_.empty()); + EXPECT_EQ(triggeredCount_, 0); + + /** + * @tc.steps:step5. insert or replace, check observer. + * @tc.expected: step5. check observer ok. + */ + triggeredCount_ = 0; + sql = "insert or replace into " + tableName + " VALUES(1000, 'lisi');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + WaitAndResetNotify(); + EXPECT_EQ(triggeredCount_, 1); // 1 is trigger times, first delete then insert + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: TriggerObserverTest006 + * @tc.desc: Test commit and rollback for multi-table then trigger client observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, TriggerObserverTest006, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName1 = "sync_data1"; + const std::string tableName2 = "sync_data2"; + PrepareData({tableName1, tableName2}, false, DistributedDB::CLOUD_COOPERATION, false); + + /** + * @tc.steps:step2. register client observer. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + RegisterDbHook(db); + + /** + * @tc.steps:step3. begin transaction and commit. + * @tc.expected: step3. check observer ok. + */ + std::string sql = "insert into " + tableName1 + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + WaitAndResetNotify(); + ASSERT_EQ(triggerTableData_.size(), 1u); // 1 is table size + EXPECT_EQ(triggerTableData_.begin()->first, tableName1); + EXPECT_EQ(triggeredCount_, 1); // 1 is trigger count + + /** + * @tc.steps:step4. UnRegisterClientObserver and insert table2. + * @tc.expected: step3. check observer ok. + */ + triggerTableData_.clear(); + triggeredCount_ = 0; + EXPECT_EQ(UnRegisterClientObserver(db), OK); + sql = "insert into " + tableName2 + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + EXPECT_TRUE(triggerTableData_.empty()); + EXPECT_EQ(triggeredCount_, 0); + + /** + * @tc.steps:step5. RegisterClientObserver again and insert table1, check observer. + * @tc.expected: step5. check observer ok. + */ + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + RegisterDbHook(db); + sql = "insert into " + tableName1 + " VALUES(7, 'zhangjiu');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + WaitAndResetNotify(); + ASSERT_EQ(triggerTableData_.size(), 1u); // 1 is table size + EXPECT_EQ(triggerTableData_.begin()->first, tableName1); + EXPECT_EQ(triggeredCount_, 1); // 1 is trigger count + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: TriggerObserverTest007 + * @tc.desc: Test trigger client observer in tracker table + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, TriggerObserverTest007, TestSize.Level0) +{ + /** + * @tc.steps:step1. prepare data and set trackerTable + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false); + SetTracerSchema({tableName}, DistributedDB::CLOUD_COOPERATION); + + /** + * @tc.steps:step2. register client observer. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + RegisterDbHook(db); + + /** + * @tc.steps:step3. insert data into sync_data, check observer. + * @tc.expected: step3. check observer ok. + */ + std::string sql = "insert into " + tableName + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');"; + std::unique_lock lock(g_mutex); + ExecSqlAndWaitForObserver(db, sql, lock); + ChangeProperties properties; + properties.isTrackedDataChange = true; + int triggerCount = 1; + CheckTriggerTableData(1u, tableName, properties, triggerCount); + + /** + * @tc.steps:step4. update data, check observer. + * @tc.expected: step4. check observer ok. + */ + sql = "update " + tableName + " set name = 'lisi1' where id = 2;"; + ExecSqlAndWaitForObserver(db, sql, lock); + CheckTriggerTableData(1u, tableName, properties, ++triggerCount); + + /** + * @tc.steps:step5. update to the same data again, check observer. + * @tc.expected: step5. check observer ok. + */ + sql = "update " + tableName + " set name = 'lisi1' where id = 2;"; + ExecSqlAndWaitForObserver(db, sql, lock); + properties.isTrackedDataChange = false; + CheckTriggerTableData(1u, tableName, properties, ++triggerCount); + + /** + * @tc.steps:step6. update to the same data again, set name is NULL, check observer. + * @tc.expected: step6. check observer ok. + */ + sql = "update " + tableName + " set name = NULL where id = 2;"; + ExecSqlAndWaitForObserver(db, sql, lock); + properties.isTrackedDataChange = true; + CheckTriggerTableData(1u, tableName, properties, ++triggerCount); + + /** + * @tc.steps:step7. update to the same data again, set name is empty, check observer. + * @tc.expected: step7. check observer ok. + */ + sql = "update " + tableName + " set name = '' where id = 2;"; + ExecSqlAndWaitForObserver(db, sql, lock); + CheckTriggerTableData(1u, tableName, properties, ++triggerCount); + + /** + * @tc.steps:step8. delete data, check observer. + * @tc.expected: step8. check observer ok. + */ + sql = "delete from " + tableName + " where id = 2;"; + ExecSqlAndWaitForObserver(db, sql, lock); + CheckTriggerTableData(1u, tableName, properties, ++triggerCount); + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: TriggerObserverTest008 + * @tc.desc: Test trigger client observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, TriggerObserverTest008, TestSize.Level0) +{ + /** + * @tc.steps:step1. prepare data + * @tc.expected: step1. return ok. + */ + const std::string tableName1 = "table1"; + PrepareData({tableName1}, false, DistributedDB::CLOUD_COOPERATION, false, true); + const std::string tableName2 = "table2"; + PrepareData({tableName2}, false, DistributedDB::CLOUD_COOPERATION, false, true); + + /** + * @tc.steps:step2. register client observer. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + + /** + * @tc.steps:step3. insert data into sync_data, check observer. + * @tc.expected: step3. check observer ok. + */ + std::string sql = "insert into " + tableName1 + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + EXPECT_EQ(triggerTableData_.size(), 0u); + + /** + * @tc.steps:step4. re-register client observer and register hook + * @tc.expected: step4. return ok. + */ + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + RegisterDbHook(db); + + /** + * @tc.steps:step5. insert data into sync_data, check observer. + * @tc.expected: step5. check observer ok. + */ + sql = "insert into " + tableName2 + " VALUES(4, 'aaa');"; + std::unique_lock lock(g_mutex); + ExecSqlAndWaitForObserver(db, sql, lock); + EXPECT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +void InitLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint64_t num) +{ + for (size_t i = 0; i < num; ++i) { + std::string sql = "insert or replace into " + tableName + " VALUES('" + std::to_string(i) + "', 'zhangsan');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + std::string sql = "update " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log" + + " SET flag = flag | 0x08"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); +} + +void CheckLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint64_t expectNum) +{ + std::string sql = "select count(*) from " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log" + " where flag&0x08=0x08 and flag&0x01=0"; + sqlite3_stmt *stmt = nullptr; + EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + uint64_t count = static_cast(sqlite3_column_int64(stmt, 0)); + EXPECT_EQ(count, expectNum); + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + stmt = nullptr; + sql = "select count(*) from " + tableName; + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + uint64_t count = static_cast(sqlite3_column_int64(stmt, 0)); + EXPECT_EQ(count, expectNum); + } + SQLiteUtils::ResetStatement(stmt, true, errCode); +} + +/** + * @tc.name: DropDeleteData001 + * @tc.desc: Test trigger client observer in tracker table + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, DropDeleteData001, TestSize.Level0) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false); + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + uint64_t num = 10; + InitLogicDeleteData(db, tableName, num); + + /** + * @tc.steps:step2. db handle is nullptr + * @tc.expected: step2. return INVALID_ARGS. + */ + EXPECT_EQ(DropLogicDeletedData(nullptr, tableName, 0u), INVALID_ARGS); + + /** + * @tc.steps:step3. tableName is empty + * @tc.expected: step3. return INVALID_ARGS. + */ + EXPECT_EQ(DropLogicDeletedData(db, "", 0u), INVALID_ARGS); + + /** + * @tc.steps:step4. tableName is no exist + * @tc.expected: step4. return INVALID_ARGS. + */ + EXPECT_EQ(DropLogicDeletedData(db, tableName + "_", 0u), DB_ERROR); + + /** + * @tc.steps:step5. cursor is 0 + * @tc.expected: step5. return OK. + */ + EXPECT_EQ(DropLogicDeletedData(db, tableName, 0u), OK); + CheckLogicDeleteData(db, tableName, 0u); + + /** + * @tc.steps:step6. init data again, and cursor is 15 + * @tc.expected: step6. return OK. + */ + uint64_t cursor = 15; + InitLogicDeleteData(db, tableName, num); + EXPECT_EQ(DropLogicDeletedData(db, tableName, cursor), OK); + CheckLogicDeleteData(db, tableName, cursor - num); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +void InitDataStatus(const std::string &tableName, int count, sqlite3 *db) +{ + int type = 4; // the num of different status + for (int i = 1; i <= type * count; i++) { + std::string sql = "INSERT INTO " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" + + std::to_string(i) + "');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + std::string countStr = std::to_string(count); + std::string sql = "UPDATE " + DBCommon::GetLogTableName(tableName) + " SET status=(CASE WHEN data_key<=" + + countStr + " THEN 0 WHEN data_key>" + countStr + " AND data_key<=2*" + countStr + " THEN 1 WHEN data_key>2*" + + countStr + " AND data_key<=3*" + countStr + " THEN 2 ELSE 3 END)"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); +} + +void CheckDataStatus(const std::string &tableName, const std::string &condition, sqlite3 *db, int64_t expect) +{ + std::string sql = "SELECT count(1) FROM " + DBCommon::GetLogTableName(tableName) + " WHERE " + condition; + sqlite3_stmt *stmt = nullptr; + EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + int64_t count = static_cast(sqlite3_column_int64(stmt, 0)); + EXPECT_EQ(count, expect); + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); +} + +/** + * @tc.name: LockDataTest001 + * @tc.desc: Test status after lock + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, LockDataTest001, TestSize.Level1) +{ + /** + * @tc.steps:step1. init data and lock, hashKey has no matching data + * @tc.expected: step1. return NOT_FOUND. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false); + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + int count = 10; + InitDataStatus(tableName, count, db); + std::vector> hashKey; + hashKey.push_back({'1'}); + EXPECT_EQ(Lock(tableName, hashKey, db), NOT_FOUND); + + /** + * @tc.steps:step2. init data and lock, hashKey has matching data + * @tc.expected: step2. return OK. + */ + hashKey.clear(); + CloudDBSyncUtilsTest::GetHashKey(tableName, " 1=1 ", db, hashKey); + EXPECT_EQ(Lock(tableName, hashKey, db), OK); + + /** + * @tc.steps:step3. check status + * @tc.expected: step3. return OK. + */ + CheckDataStatus(tableName, " status = 2 and data_key <= 10 ", db, count); + CheckDataStatus(tableName, " status = 3 and data_key <= 20 ", db, count); + CheckDataStatus(tableName, " status = 2 ", db, count + count); + CheckDataStatus(tableName, " status = 3 ", db, count + count); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} + +/** + * @tc.name: LockDataTest002 + * @tc.desc: Test status after unLock + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, LockDataTest002, TestSize.Level1) +{ + /** + * @tc.steps:step1. init data and unLock, there is data to be compensated for + * @tc.expected: step1. return WAIT_COMPENSATED_SYNC. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false); + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + int count = 10; + InitDataStatus(tableName, count, db); + std::vector> hashKey; + CloudDBSyncUtilsTest::GetHashKey(tableName, " 1=1 ", db, hashKey); + EXPECT_EQ(UnLock(tableName, hashKey, db), WAIT_COMPENSATED_SYNC); + + /** + * @tc.steps:step2. check status + * @tc.expected: step2. return OK. + */ + CheckDataStatus(tableName, " status = 0 and data_key <= 10 ", db, count); + CheckDataStatus(tableName, " status = 1 and data_key <= 20 ", db, count); + CheckDataStatus(tableName, " status = 0 ", db, count + count); + CheckDataStatus(tableName, " status = 1 ", db, count + count); + + /** + * @tc.steps:step3. unLock again, there is data to be compensated for + * @tc.expected: step3. return WAIT_COMPENSATED_SYNC. + */ + EXPECT_EQ(UnLock(tableName, hashKey, db), WAIT_COMPENSATED_SYNC); + + /** + * @tc.steps:step4. unLock again, there is no data to be compensated for + * @tc.expected: step4. return OK. + */ + std::string sql = "update " + DBCommon::GetLogTableName(tableName) + " SET status=0"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + EXPECT_EQ(UnLock(tableName, hashKey, db), OK); + + /** + * @tc.steps:step5. unLock again, hashKey has matching data + * @tc.expected: step5. return NOT_FOUND. + */ + hashKey.clear(); + hashKey.push_back({'1'}); + EXPECT_EQ(UnLock(tableName, hashKey, db), NOT_FOUND); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} + +DistributedDB::StoreObserver::StoreChangedInfo g_changedData; + +class MockStoreObserver : public StoreObserver { +public: + virtual ~MockStoreObserver() {}; + void OnChange(StoreChangedInfo &&data) override + { + g_changedData = data; + std::unique_lock lock(g_mutex); + g_cv.notify_one(); + g_alreadyNotify = true; + }; +}; + +void CreateTableForStoreObserver(sqlite3 *db, const std::string tableName) +{ + std::string sql = "create table " + tableName + "(id INTEGER primary key, name TEXT);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "create table no_" + tableName + "(id INTEGER, name TEXT);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "create table mult_" + tableName + "(id INTEGER, name TEXT, age int, "; + sql += "PRIMARY KEY (id, name));"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); +} + +void PrepareDataForStoreObserver(sqlite3 *db, const std::string &tableName, int begin, int dataCounts) +{ + std::string sql = "begin;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + for (int i = begin; i < begin + dataCounts; i++) { + sql = "insert into " + tableName + " VALUES(" + std::to_string(i + 1) + ", 'zhangsan" + + std::to_string(i + 1) + "');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "insert into no_" + tableName +" VALUES(" + std::to_string(i + 1) + ", 'zhangsan" + + std::to_string(i + 1) + "');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "insert into mult_" + tableName + " VALUES(" + std::to_string(i + 1) + ", 'zhangsan"; + sql += std::to_string(i + 1) + "', 18);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + for (int i = begin; i < dataCounts / 2 + begin; i++) { // 2 is half + sql = "update " + tableName + " set name = 'lisi' where id = " + std::to_string(i + 1) + ";"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "update no_" + tableName + " set name = 'lisi' where _rowid_ = " + std::to_string(i + 1) + ";"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "update mult_" + tableName + " set age = 20 where id = " + std::to_string(i + 1); + sql += " and name = 'zhangsan" + std::to_string(i + 1) + "';"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + for (int i = dataCounts / 2 + begin; i < dataCounts + begin; i++) { // 2 is half + sql = "delete from " + tableName + " where id = " + std::to_string(i + 1) + ";"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "delete from no_" + tableName + " where _rowid_ = " + std::to_string(i + 1) + ";"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "delete from mult_" + tableName + " where id = " + std::to_string(i + 1); + sql += " and name = 'zhangsan" + std::to_string(i + 1) + "';"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + sql = "commit;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); +} + +void CheckChangedData(int num, int times = 0, int offset = 0) +{ + if (num == 1) { + for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_INSERT].size(); i++) { + EXPECT_EQ(std::get(g_changedData[num].primaryData[ChangeType::OP_INSERT][i - 1][0]), + static_cast(i + offset - times * 5)); // 5 is rowid times + } + for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_DELETE].size(); i++) { + EXPECT_EQ(std::get(g_changedData[num].primaryData[ChangeType::OP_DELETE][i - 1][0]), + static_cast(i + offset + 5)); // 5 is offset + } + return; + } + for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_INSERT].size(); i++) { + EXPECT_EQ(std::get(g_changedData[num].primaryData[ChangeType::OP_INSERT][i - 1][0]), + static_cast(i + offset)); + } + for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_UPDATE].size(); i++) { + EXPECT_EQ(std::get(g_changedData[num].primaryData[ChangeType::OP_UPDATE][i - 1][0]), + static_cast(i + offset)); + } + for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_DELETE].size(); i++) { + EXPECT_EQ(std::get(g_changedData[num].primaryData[ChangeType::OP_DELETE][i - 1][0]), + static_cast(i + offset + 5)); // 5 is offset + } +} + +/** + * @tc.name: RegisterStoreObserverTest001 + * @tc.desc: Test commit for three table then trigger store observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, RegisterStoreObserverTest001, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare db and create table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + std::string tableName = "primary_test"; + CreateTableForStoreObserver(db, tableName); + + /** + * @tc.steps:step2. register store observer and check onchange. + * @tc.expected: step2. return ok. + */ + auto storeObserver = std::make_shared(); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK); + RegisterDbHook(db); + EXPECT_TRUE(g_changedData.empty()); + int dataCounts = 10; // 10 is count of insert options. + int begin = 0; + PrepareDataForStoreObserver(db, tableName, begin, dataCounts); + { + std::unique_lock lock(g_mutex); + g_cv.wait(lock, []() { + return g_alreadyNotify; + }); + g_alreadyNotify = false; + } + EXPECT_EQ(g_changedData[0].tableName, "primary_test"); + CheckChangedData(0); + EXPECT_EQ(g_changedData[1].tableName, "no_primary_test"); + CheckChangedData(1); + EXPECT_EQ(g_changedData[2].tableName, "mult_primary_test"); // 2 is mult primary table + CheckChangedData(2); // 2 is mult primary table + g_changedData.clear(); + + /** + * @tc.steps:step3. unregister store observer and update data check onchange. + * @tc.expected: step3. return ok. + */ + EXPECT_EQ(UnregisterStoreObserver(db), OK); + begin = 10; // 10 is begin id + PrepareDataForStoreObserver(db, tableName, begin, dataCounts); + EXPECT_TRUE(g_changedData.empty()); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: RegisterStoreObserverTest002 + * @tc.desc: Test commit for three table then trigger client observer when register then create table + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, RegisterStoreObserverTest002, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare db and register store observer then create table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + auto storeObserver = std::make_shared(); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK); + RegisterDbHook(db); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + std::string tableName = "primary_test"; + CreateTableForStoreObserver(db, tableName); + + /** + * @tc.steps:step2. update data and check onchange. + * @tc.expected: step2. return ok. + */ + EXPECT_TRUE(g_changedData.empty()); + int dataCounts = 10; // 10 is count of insert options. + int begin = 0; + PrepareDataForStoreObserver(db, tableName, begin, dataCounts); + WaitAndResetNotify(); + EXPECT_EQ(g_changedData[0].tableName, "primary_test"); + CheckChangedData(0); + EXPECT_EQ(g_changedData[1].tableName, "no_primary_test"); + CheckChangedData(1); + EXPECT_EQ(g_changedData[2].tableName, "mult_primary_test"); // 2 is mult primary table + CheckChangedData(2); // 2 is mult primary table + g_changedData.clear(); + + /** + * @tc.steps:step3. unregister store observer and update data check onchange. + * @tc.expected: step3. return ok. + */ + EXPECT_EQ(UnregisterStoreObserver(db), OK); + begin = 10; // 11 is begin id + PrepareDataForStoreObserver(db, tableName, begin, dataCounts); + EXPECT_TRUE(g_changedData.empty()); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: RegisterStoreObserverTest003 + * @tc.desc: Test commit for three table then trigger client observer when register two observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, RegisterStoreObserverTest003, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare db and register store observer then create table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + auto storeObserver1 = std::make_shared(); + auto storeObserver2 = std::make_shared(); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver1), OK); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver2), OK); + RegisterDbHook(db); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + std::string tableName = "primary_test"; + CreateTableForStoreObserver(db, tableName); + + /** + * @tc.steps:step2. update data and check onchange. + * @tc.expected: step2. return ok. + */ + EXPECT_TRUE(g_changedData.empty()); + int dataCounts = 10; // 10 is count of insert options. + int begin = 0; + PrepareDataForStoreObserver(db, tableName, begin, dataCounts); + WaitAndResetNotify(); + EXPECT_EQ(g_changedData[0].tableName, "primary_test"); + CheckChangedData(0); + EXPECT_EQ(g_changedData[1].tableName, "no_primary_test"); + CheckChangedData(1); + EXPECT_EQ(g_changedData[2].tableName, "mult_primary_test"); // 2 is mult primary table + CheckChangedData(2); // 2 is mult primary table + g_changedData.clear(); + + /** + * @tc.steps:step3. unregister store observer and update data check onchange. + * @tc.expected: step3. return ok. + */ + EXPECT_EQ(UnregisterStoreObserver(db, storeObserver1), OK); + begin = 10; // 11 is begin id + PrepareDataForStoreObserver(db, tableName, begin, dataCounts); + EXPECT_EQ(g_changedData[0].tableName, "primary_test"); + CheckChangedData(0, 1, dataCounts); + EXPECT_EQ(g_changedData[1].tableName, "no_primary_test"); + CheckChangedData(1, 1, dataCounts); + EXPECT_EQ(g_changedData[2].tableName, "mult_primary_test"); // 2 is mult primary table + CheckChangedData(2, 1, dataCounts); // 2 is mult primary table + g_changedData.clear(); + + EXPECT_EQ(UnregisterStoreObserver(db, storeObserver2), OK); + begin = 20; // 21 is begin id + PrepareDataForStoreObserver(db, tableName, begin, dataCounts); + EXPECT_TRUE(g_changedData.empty()); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: RegisterStoreObserverTest004 + * @tc.desc: Test register two same observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, RegisterStoreObserverTest004, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare db and register store observer then create table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + auto storeObserver = std::make_shared(); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp index 363c76a2cb17ab2b1a8a604a9501449c9e32a0e5..e54e58b3af3bcf3008f1b449125be3cbac7a4eb7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp @@ -455,7 +455,7 @@ void UpdateTriggerTest(bool primaryKeyIsRowId) * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, UpdateTriggerTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, UpdateTriggerTest001, TestSize.Level1) { UpdateTriggerTest(false); } @@ -467,7 +467,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, UpdateTriggerTest001, Te * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, UpdateTriggerTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, UpdateTriggerTest002, TestSize.Level1) { UpdateTriggerTest(true); } @@ -479,7 +479,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, UpdateTriggerTest002, Te * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, DeleteTriggerTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, DeleteTriggerTest001, TestSize.Level1) { /** * @tc.steps:step1. prepare data. @@ -566,13 +566,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest001, EXPECT_NE(db, nullptr); EXPECT_EQ(RegisterClientObserver(db, nullptr), INVALID_ARGS); - /** - * @tc.steps:step3. call RegisterClientObserver and UnRegisterClientObserver with closed db handle. - * @tc.expected: step3. return INVALID_ARGS. - */ EXPECT_EQ(sqlite3_close_v2(db), E_OK); - EXPECT_EQ(RegisterClientObserver(db, clientObserver), INVALID_ARGS); - EXPECT_EQ(UnRegisterClientObserver(db), INVALID_ARGS); } /** @@ -983,6 +977,62 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest007, EXPECT_EQ(sqlite3_close_v2(db), E_OK); } +/** + * @tc.name: TriggerObserverTest008 + * @tc.desc: Test trigger client observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest008, TestSize.Level0) +{ + /** + * @tc.steps:step1. prepare data + * @tc.expected: step1. return ok. + */ + const std::string tableName1 = "table1"; + PrepareData({tableName1}, false, DistributedDB::CLOUD_COOPERATION, false, true); + const std::string tableName2 = "table2"; + PrepareData({tableName2}, false, DistributedDB::CLOUD_COOPERATION, false, true); + + /** + * @tc.steps:step2. register client observer. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + + /** + * @tc.steps:step3. insert data into sync_data, check observer. + * @tc.expected: step3. check observer ok. + */ + std::string sql = "insert into " + tableName1 + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + EXPECT_EQ(triggerTableData_.size(), 0u); + + /** + * @tc.steps:step4. re-register client observer and register hook + * @tc.expected: step4. return ok. + */ + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + RegisterDbHook(db); + + /** + * @tc.steps:step5. insert data into sync_data, check observer. + * @tc.expected: step5. check observer ok. + */ + sql = "insert into " + tableName2 + " VALUES(4, 'aaa');"; + std::unique_lock lock(g_mutex); + ExecSqlAndWaitForObserver(db, sql, lock); + EXPECT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + void InitLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint64_t num) { for (size_t i = 0; i < num; ++i) { @@ -1078,7 +1128,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, DropDeleteData001, TestS * @tc.require: * @tc.author: */ -HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest001, TestSize.Level1) { std::map ans; #ifdef USE_FFRT @@ -1143,7 +1193,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest001, TestSize.Le * @tc.require: * @tc.author: */ -HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest002, TestSize.Level1) { std::map ans; #ifdef USE_FFRT @@ -1216,7 +1266,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest002, TestSize.Le * @tc.require: * @tc.author: */ -HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest003, TestSize.Level1) { size_t count = 0; size_t num = 3000; @@ -1276,6 +1326,10 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, AbnormalDelegateTest001, * @tc.expected: step2. return ok. */ auto delegateImpl = static_cast(delegate); + ClearMetaDataOption option; + EXPECT_EQ(delegateImpl->ClearMetaData(option), OK); + option.tableNameList.insert("asdad"); + EXPECT_EQ(delegateImpl->ClearMetaData(option), NOT_SUPPORT); status = delegateImpl->Close(); EXPECT_EQ(status, OK); @@ -1345,7 +1399,7 @@ void CheckDataStatus(const std::string &tableName, const std::string &condition, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, LockDataTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, LockDataTest001, TestSize.Level1) { /** * @tc.steps:step1. init data and lock, hashKey has no matching data @@ -1387,7 +1441,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, LockDataTest001, TestSiz * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, LockDataTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, LockDataTest002, TestSize.Level1) { /** * @tc.steps:step1. init data and unLock, there is data to be compensated for @@ -1724,6 +1778,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, RegisterStoreObserverTes begin = 20; // 21 is begin id PrepareDataForStoreObserver(db, tableName, begin, dataCounts); EXPECT_TRUE(g_changedData.empty()); + UnregisterDbHook(db); EXPECT_EQ(sqlite3_close_v2(db), E_OK); } @@ -1852,4 +1907,168 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, AbnormalDelegateImplTest EXPECT_EQ(g_mgr.CloseStore(delegate), OK); delegate = nullptr; } + +/** + * @tc.name: FuncExceptionTest001 + * @tc.desc: Test the interception expection of the interface + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FuncExceptionTest001, TestSize.Level1) +{ + std::shared_ptr iStoreObserver = nullptr; + EXPECT_EQ(RegisterStoreObserver(nullptr, iStoreObserver), INVALID_ARGS); + EXPECT_EQ(UnregisterStoreObserver(nullptr, iStoreObserver), INVALID_ARGS); + iStoreObserver = std::make_shared(); + EXPECT_EQ(RegisterStoreObserver(nullptr, iStoreObserver), INVALID_ARGS); + EXPECT_EQ(UnregisterStoreObserver(nullptr, iStoreObserver), INVALID_ARGS); + + EXPECT_EQ(RelationalStoreManager::CalcPrimaryKeyHash({}, {}).size(), 0u); + std::map pkMap1 = {{"fielddInt", 0L}}; + std::map ctMap1 = {{"fielddInt", CollateType::COLLATE_BUTT}}; + std::vector result = RelationalStoreManager::CalcPrimaryKeyHash(pkMap1, ctMap1); + EXPECT_TRUE(result.empty()); + + std::map pkMap2 = {{"FIELDINT", 0L}, {"FIELDSTR", std::string("FIELDSTR")}}; + std::map ctMap2; + ctMap2.insert_or_assign("fieldint", CollateType::COLLATE_BUTT); + ctMap2.insert_or_assign("fieldstr", CollateType::COLLATE_BUTT); + result = RelationalStoreManager::CalcPrimaryKeyHash(pkMap2, ctMap2); + EXPECT_TRUE(result.empty()); + + ctMap2.insert_or_assign("fieldint", CollateType::COLLATE_NOCASE); + ctMap2.insert_or_assign("fieldstr", CollateType::COLLATE_NOCASE); + result = RelationalStoreManager::CalcPrimaryKeyHash(pkMap2, ctMap2); + EXPECT_FALSE(result.empty()); + + std::map entries2; + pkMap2.insert_or_assign("FIELDINT", entries2); + result = RelationalStoreManager::CalcPrimaryKeyHash(pkMap2, ctMap2); + EXPECT_TRUE(result.empty()); +} + +/** + * @tc.name: CleanTest001 + * @tc.desc: Test calling the Clean interface twice + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, CleanTest001, TestSize.Level0) +{ + Logger *loggerInstance = Logger::GetInstance(); + ASSERT_NE(loggerInstance, nullptr); + Clean(true); + Clean(false); + loggerInstance = nullptr; + Logger *newLoggerInstance = Logger::GetInstance(); + ASSERT_NE(newLoggerInstance, nullptr); +} + +/** + * @tc.name: CreateTempTriggerTest001 + * @tc.desc: Test create data change temp trigger. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, CreateTempTriggerTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. create db and fts table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + std::string tableName = "table1"; + std::string sql = "CREATE VIRTUAL TABLE IF NOT EXISTS " + tableName + " USING fts4(content);"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + /** + * @tc.steps: step2. create temp trigger on table. + * @tc.expected: step2. return ok. + */ + EXPECT_EQ(CreateDataChangeTempTrigger(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: CreateTempTriggerTest002 + * @tc.desc: Test create data change temp trigger + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, CreateTempTriggerTest002, TestSize.Level0) +{ + /** + * @tc.steps: step1. create db and fts table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + std::string tableName = "table1"; + std::string sql = "create virtual table if not exists " + tableName + " using fts4(content);"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + /** + * @tc.steps: step2. create temp trigger on table. + * @tc.expected: step2. return ok. + */ + auto storeObserver = std::make_shared(); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK); + RegisterDbHook(db); + g_changedData.clear(); + /** + * @tc.steps: step3. insert data and check changed data. + * @tc.expected: step3. return ok. + */ + sql = "insert into " + tableName + "_content values(1, '123456');"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + ASSERT_EQ(g_changedData.size(), 1u); + EXPECT_EQ(g_changedData.front().tableName, tableName + "_content"); + ASSERT_EQ(g_changedData.front().primaryData[OP_INSERT].size(), 1u); + EXPECT_EQ(UnregisterStoreObserver(db, storeObserver), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: CreateTempTriggerTest003 + * @tc.desc: Test monitoring of virtual table data + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, CreateTempTriggerTest003, TestSize.Level0) +{ + /** + * @tc.steps: step1. create db and fts table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + std::string tableName = "table1"; + std::string sql = "create virtual table if not exists " + tableName + " using fts4(content);"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + /** + * @tc.steps: step2. create temp trigger on table. + * @tc.expected: step2. return ok. + */ + auto storeObserver = std::make_shared(); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK); + RegisterDbHook(db); + g_changedData.clear(); + /** + * @tc.steps: step3. insert data and check changed data. + * @tc.expected: step3. return ok. + */ + sql = "insert into " + tableName + " values(12345);"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + ASSERT_FALSE(g_changedData.empty()); + EXPECT_EQ(g_changedData.front().tableName, tableName + "_content"); + ASSERT_EQ(g_changedData.front().primaryData[OP_INSERT].size(), 1u); + EXPECT_EQ(UnregisterStoreObserver(db, storeObserver), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp index 61168fdf6903c5d2182bfac7b967f9091a2c425b..a033481a089b3a44c7f53d6e41a959a0e8d05532 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp @@ -634,7 +634,7 @@ namespace { * @tc.require: * @tc.author: huangboxin */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest001, TestSize.Level1) { int64_t paddingSize = 10; int localCount = 10; @@ -667,7 +667,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: huangboxin */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest002, TestSize.Level1) { int64_t paddingSize = 10; int localCount = 10; @@ -696,7 +696,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: huangboxin */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest003, TestSize.Level1) { /** * @tc.steps: step1. make data: 10 records on local and 20 records on cloud @@ -776,7 +776,7 @@ static CloudSyncOption GetSyncOption() * @tc.require: * @tc.author: huangboxin */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, GetCloudSyncTaskCountTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, GetCloudSyncTaskCountTest001, TestSize.Level1) { InitGetCloudSyncTaskCountTest001(db); Query query = Query::Select().FromTable(g_tables); @@ -849,7 +849,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, GetCloudSyn * @tc.require: * @tc.author: huangboxin */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest004, TestSize.Level1) { DataBaseSchema dataBaseSchema; TableSchema tableSchema1 = { @@ -872,7 +872,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest005, TestSize.Level1) { /** * @tc.steps: step1. cloud and device data is same @@ -909,7 +909,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest006, TestSize.Level1) { /** * @tc.steps: step1. make data: 10 records on local @@ -945,7 +945,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest007, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest007, TestSize.Level1) { /** * @tc.steps: step1. make data: 10 records on local @@ -996,7 +996,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest008, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest008, TestSize.Level1) { /** * @tc.steps: step1. make data: 10 records on local @@ -1051,7 +1051,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest009, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest009, TestSize.Level1) { /** * @tc.steps: step1. make data: 10 records on local @@ -1083,7 +1083,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest010, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest010, TestSize.Level1) { /** * @tc.steps: step1. make data: 10 records on local @@ -1118,7 +1118,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest011, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest011, TestSize.Level1) { /** * @tc.steps: step1. make data: 10 records on local @@ -1158,7 +1158,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest012, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest012, TestSize.Level1) { /** * @tc.steps: step1. make data: 20 records on local @@ -1204,7 +1204,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest013, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest013, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1258,7 +1258,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest014, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest014, TestSize.Level1) { /** * @tc.steps: step1. make data: 20 records on local @@ -1296,7 +1296,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest015, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest015, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1333,7 +1333,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest016, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest016, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1380,7 +1380,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest017, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest017, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1421,7 +1421,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest018, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest018, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1464,7 +1464,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest019, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest019, TestSize.Level1) { /** * @tc.steps: step1. make data: 20 records on local @@ -1496,7 +1496,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest020, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest020, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1544,7 +1544,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest021, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest021, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1598,7 +1598,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest022, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest022, TestSize.Level1) { /** * @tc.steps: step1. make data: 20 records on local @@ -1638,7 +1638,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest023, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest023, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1714,7 +1714,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest024, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest024, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1767,7 +1767,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: suyuchen */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest025, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest025, TestSize.Level1) { /** * @tc.steps: step1. Set logicDelete @@ -1819,7 +1819,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest026, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest026, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1860,7 +1860,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest027, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest027, TestSize.Level1) { /** * @tc.steps: step1. make data: 20 records on cloud @@ -1895,7 +1895,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest028, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest028, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1954,7 +1954,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest029, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest029, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -2012,7 +2012,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest030, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest030, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_set_cloud_schema_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_set_cloud_schema_test.cpp index 1853d15780ce0bf8456ed839da41e697796c4fba..4fc9e2cb7afc896d77ccacfb78b066881a91e57d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_set_cloud_schema_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_set_cloud_schema_test.cpp @@ -921,7 +921,7 @@ namespace { * @tc.require: * @tc.author: chenchaohao */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest010, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest010, TestSize.Level1) { /** * @tc.steps:step1. use SetCloudDbSchema @@ -1082,7 +1082,7 @@ namespace { * @tc.require: * @tc.author: chenchaohao */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest013, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest013, TestSize.Level1) { /** * @tc.steps:step1. use SetCloudDbSchema @@ -1186,7 +1186,7 @@ namespace { * @tc.require: * @tc.author: chenchaohao */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync001, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync001, TestSize.Level1) { /** * @tc.steps:step1. use set shared table without primary key @@ -1218,7 +1218,7 @@ namespace { * @tc.require: * @tc.author: chenchaohao */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync002, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync002, TestSize.Level1) { /** * @tc.steps:step1. use set shared table @@ -1260,7 +1260,7 @@ namespace { * @tc.require: * @tc.author: bty */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync003, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync003, TestSize.Level1) { /** * @tc.steps:step1. insert local shared table records and sync @@ -1312,7 +1312,7 @@ namespace { * @tc.require: * @tc.author: chenchaohao */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync004, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync004, TestSize.Level1) { /** * @tc.steps:step1. use set shared table @@ -1354,7 +1354,7 @@ namespace { * @tc.require: * @tc.author: chenchaohao */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync006, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync006, TestSize.Level1) { /** * @tc.steps:step1. set shared table and sync @@ -1533,7 +1533,7 @@ namespace { * @tc.require: * @tc.author: bty */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync007, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync007, TestSize.Level1) { /** * @tc.steps:step1. init cloud share data contains sharing_resource @@ -1572,7 +1572,7 @@ namespace { * @tc.require: * @tc.author: bty */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync008, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync008, TestSize.Level1) { /** * @tc.steps:step1. init cloud data and sync @@ -1634,7 +1634,7 @@ namespace { * @tc.require: * @tc.author: bty */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync009, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync009, TestSize.Level1) { /** * @tc.steps:step1. init cloud data and sync @@ -1697,7 +1697,7 @@ namespace { * @tc.require: * @tc.author: bty */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync010, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync010, TestSize.Level1) { /** * @tc.steps:step1. init cloud share data and sync @@ -1754,7 +1754,7 @@ namespace { * @tc.require: * @tc.author: bty */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync011, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync011, TestSize.Level1) { /** * @tc.steps:step1. init cloud data and sync @@ -1811,7 +1811,7 @@ namespace { * @tc.require: * @tc.author: bty */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync012, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync012, TestSize.Level1) { /** * @tc.steps:step1. init local share data and sync @@ -1851,7 +1851,7 @@ namespace { * @tc.require: * @tc.author: bty */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync013, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync013, TestSize.Level1) { /** * @tc.steps:step1. init cloud data and sync @@ -1899,7 +1899,7 @@ namespace { * @tc.require: * @tc.author: wangxiangdong */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync014, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync014, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1951,7 +1951,7 @@ namespace { * @tc.require: * @tc.author: wangxiangdong */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync015, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync015, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -2027,7 +2027,7 @@ namespace { * @tc.require: * @tc.author: wangxiangdong */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync016, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync016, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -2092,7 +2092,7 @@ namespace { * @tc.require: * @tc.author: luoguo */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync017, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync017, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -2174,7 +2174,7 @@ namespace { * @tc.require: * @tc.author: wangxiangdong */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync019, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync019, TestSize.Level1) { /** * @tc.steps:step1. init cloud data and sync @@ -2209,7 +2209,7 @@ namespace { * @tc.require: * @tc.author: liaoyonghuang */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetTrackerTable001, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetTrackerTable001, TestSize.Level1) { /** * @tc.steps:step1. init cloud data diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_auto_launch_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_auto_launch_test.cpp index cacbdb4a2cd80586aba5bae5df4a4b84c9038e59..c6ac19b0b4c72d04e213900dba1c546cd08c1ceb 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_auto_launch_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_auto_launch_test.cpp @@ -192,7 +192,7 @@ void DistributedDBInterfacesAutoLaunchTest::TearDown(void) * @tc.name: EnableKvStoreAutoLaunch001 * @tc.desc: Enable the kvstore with the diff parameters. * @tc.type: FUNC - * @tc.require: AR000DR9KU + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch001, TestSize.Level1) @@ -250,7 +250,7 @@ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch001, Test * @tc.name: EnableKvStoreAutoLaunch002 * @tc.desc: Enable the kv store auto launch for the change of createIfNecessary. * @tc.type: FUNC - * @tc.require: AR000DR9KU + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch002, TestSize.Level1) @@ -405,7 +405,7 @@ void TriggerAutoLaunch(const std::string &storeId, bool isWriteCovered) * @tc.name: EnableKvStoreAutoLaunch003 * @tc.desc: test the data change and the notifier of the auto open for no data changed. * @tc.type: FUNC - * @tc.require: AR000DR9KU + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch003, TestSize.Level2) @@ -425,7 +425,7 @@ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch003, Test * @tc.name: EnableKvStoreAutoLaunch004 * @tc.desc: test the data change and the notifier of the auto open for data changed. * @tc.type: FUNC - * @tc.require: AR000DR9KU + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch004, TestSize.Level2) @@ -445,7 +445,7 @@ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch004, Test * @tc.name: EnableKvStoreAutoLaunch005 * @tc.desc: Test enable the same database twice. * @tc.type: FUNC - * @tc.require: AR000DR9KU + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch005, TestSize.Level1) @@ -476,7 +476,7 @@ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch005, Test * @tc.name: EnableKvStoreAutoLaunch005 * @tc.desc: test the over limits for the enable list. * @tc.type: FUNC - * @tc.require: AR000DR9KU + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch006, TestSize.Level2) @@ -549,7 +549,7 @@ void SetAutoLaunchLifeCycleTime(const std::string &storeId, uint32_t time) * @tc.name: EnableKvStoreAutoLaunch007 * @tc.desc: test the over limits for the enable list. * @tc.type: FUNC - * @tc.require: AR000DR9KU + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, DisableKvStoreAutoLaunch001, TestSize.Level3) @@ -590,7 +590,7 @@ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, DisableKvStoreAutoLaunch001, Tes * @tc.name: AutoLaunchLifeCycle001 * @tc.desc: test the auto closed for the database auto launched by the msg. * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, AutoLaunchLifeCycle001, TestSize.Level3) @@ -693,7 +693,7 @@ void DelayAutoLaunchCycle(const std::string &storeId, bool isWrite) * @tc.name: AutoLaunchLifeCycle002 * @tc.desc: test the over limits for the enable list. * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, AutoLaunchLifeCycle002, TestSize.Level3) @@ -713,7 +713,7 @@ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, AutoLaunchLifeCycle002, TestSize * @tc.name: AutoLaunchLifeCycle003 * @tc.desc: test the life cycle of the auto launched database in the sync reading scene. * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, AutoLaunchLifeCycle003, TestSize.Level3) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_syncdb_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_syncdb_test.cpp index d15bab16830272e61800ee416cd6157dd50265dc..78ed6933125dad2c63961232aac106a2fc158ee4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_syncdb_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_syncdb_test.cpp @@ -145,7 +145,7 @@ void DistributedDBInterfacesDataOperationSyncDBTest::TearDown(void) * @tc.name: Put001 * @tc.desc: Put a data(non-empty key, non-empty value) into an exist distributed db * @tc.type: FUNC - * @tc.require: AR000CQDTM AR000CQS3R + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Put001, TestSize.Level1) @@ -172,7 +172,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Put001, TestSize.Level1 * @tc.name: Put002 * @tc.desc: Put a data(empty key) into an exist distributed db * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Put002, TestSize.Level1) @@ -191,7 +191,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Put002, TestSize.Level1 * @tc.name: Put003 * @tc.desc: Put a data(non-empty key, empty value) into an exist distributed db * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Put003, TestSize.Level1) @@ -211,7 +211,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Put003, TestSize.Level1 * @tc.name: Put004 * @tc.desc: Put data into the multiversion database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Put004, TestSize.Level1) @@ -274,7 +274,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Put004, TestSize.Level1 * @tc.name: Clear001 * @tc.desc: Clear the data from an exist distributed db * @tc.type: FUNC - * @tc.require: AR000CQDTM AR000CQS3R + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Clear001, TestSize.Level1) @@ -306,7 +306,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Clear001, TestSize.Leve * @tc.name: PutBatch001 * @tc.desc: Putbatch data into the multiversion database * @tc.type: FUNC - * @tc.require: AR000CQDTM AR000CQS3R + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, PutBatch001, TestSize.Level1) @@ -349,7 +349,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, PutBatch001, TestSize.L * @tc.name: PutBatch002 * @tc.desc: PutBatch modified data into the multiversion database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, PutBatch002, TestSize.Level1) @@ -391,7 +391,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, PutBatch002, TestSize.L * @tc.name: Delete001 * @tc.desc: Delete existed data from the multiversion database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Delete001, TestSize.Level1) @@ -422,7 +422,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Delete001, TestSize.Lev * @tc.name: Delete002 * @tc.desc: Delete non-existed data from the multiversion database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Delete002, TestSize.Level1) @@ -445,7 +445,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Delete002, TestSize.Lev * @tc.name: DeleteBatch001 * @tc.desc: Delete the existed batch data from the multiversion database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, DeleteBatch001, TestSize.Level1) @@ -488,7 +488,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, DeleteBatch001, TestSiz * @tc.name: DeleteBatch002 * @tc.desc: Delete the non-existed batch data from the multiversion database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, DeleteBatch002, TestSize.Level1) @@ -514,7 +514,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, DeleteBatch002, TestSiz * @tc.name: GetEntries001 * @tc.desc: Get the batch data from the non-empty database by the prefix key. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetEntries001, TestSize.Level1) @@ -553,7 +553,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetEntries001, TestSize * @tc.name: GetEntries002 * @tc.desc: Get all the data(empty prefixkey) from the empty database. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetEntries002, TestSize.Level1) @@ -578,7 +578,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetEntries002, TestSize * @tc.name: GetEntries003 * @tc.desc: Get all the data(empty prefixkey) from the database. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetEntries003, TestSize.Level1) @@ -640,7 +640,7 @@ static void TestSnapshotCreateAndRelease() * @tc.name: GetSnapshot001 * @tc.desc: Get observer is empty, whether you get the snapshot. * @tc.type: FUNC - * @tc.require: AR000BVRNF AR000CQDTI + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshot001, TestSize.Level1) @@ -657,7 +657,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshot001, TestSiz * @tc.name: GetSnapshot002 * @tc.desc: Get observer is not empty, whether you get the snapshot. * @tc.type: FUNC - * @tc.require: AR000BVRNF AR000CQDTI + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshot002, TestSize.Level1) @@ -691,7 +691,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshot002, TestSiz * @tc.name: ReleaseSnapshot001 * @tc.desc: To test the function of releasing an empty snapshot. * @tc.type: FUNC - * @tc.require: AR000BVRNF AR000CQDTI + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, ReleaseSnapshot001, TestSize.Level1) @@ -709,7 +709,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, ReleaseSnapshot001, Tes * @tc.name: ReleaseSnapshot002 * @tc.desc: Release the obtained snapshot object that is not empty. * @tc.type: FUNC - * @tc.require: AR000BVRNF AR000CQDTI + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, ReleaseSnapshot002, TestSize.Level1) @@ -866,7 +866,7 @@ static void TestSnapshotEntryDelete() * @tc.desc: Obtain data from the obtained snapshot object and test the impact of the write * database on the snapshot obtained after the snapshot is obtained. * @tc.type: FUNC - * @tc.require: AR000BVRNH AR000CQDTJ + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshotEntry001, TestSize.Level1) @@ -879,7 +879,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshotEntry001, Te * @tc.name: get_snapshot_entry_002 * @tc.desc: Read the data of the invalid key from the obtained snapshot object. * @tc.type: FUNC - * @tc.require: AR000BVRNH AR000CQDTJ + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshotEntry002, TestSize.Level1) @@ -1100,7 +1100,7 @@ static void SnapshotTestPreEntriesDelete() * @tc.name: GetSnapshotEntries001 * @tc.desc: To test the function of obtaining full data when keyPrefix is set to null. * @tc.type: FUNC - * @tc.require: AR000BVRNI AR000CQDTK + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshotEntries001, TestSize.Level1) @@ -1237,7 +1237,7 @@ static void SnapshotTestEmptyPreEntriesDelete() * @tc.name: GetSnapshotEntries002 * @tc.desc: To test the function of obtaining the prefix data when keyPrefix is set to a non-empty value. * @tc.type: FUNC - * @tc.require: AR000BVRNI AR000CQDTK + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshotEntries002, TestSize.Level1) @@ -1251,7 +1251,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshotEntries002, * @tc.name: GetSnapshotEntries003 * @tc.desc: To test whether data can be obtained when keyPrefix is set to an ultra-long key. * @tc.type: FUNC - * @tc.require: AR000BVRNI AR000CQDTK + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshotEntries003, TestSize.Level1) @@ -1297,7 +1297,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshotEntries003, * @tc.name: TestTransactionException001 * @tc.desc: An exception occurred while the test transaction was executing. * @tc.type: FUNC - * @tc.require: AR000C0F0F AR000CQDTN or SR000BVRNJ + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, TransactionException001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_test.cpp index f6d10ef068efb90ca7aac7562f6e29e0937d0120..0a80081fd19727dc21bdc722d96fbbfe023fe93c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_test.cpp @@ -407,7 +407,7 @@ void DistributedDBInterfacesDataOperationTest::TearDown(void) * @tc.name: Put001 * @tc.desc: Put a data(non-empty key, non-empty value) into an exist distributed db * @tc.type: FUNC - * @tc.require: AR000CQDTM AR000CQS3Q + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, Put001, TestSize.Level1) @@ -435,7 +435,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, Put001, TestSize.Level1) * @tc.name: Put002 * @tc.desc: Put a data(empty key) into an exist distributed db * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, Put002, TestSize.Level1) @@ -454,7 +454,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, Put002, TestSize.Level1) * @tc.name: Put003 * @tc.desc: Put a data(non-empty key, empty value) into an exist distributed db * @tc.type: FUNC - * @tc.require: AR000CQDTM AR000CQS3Q + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, Put003, TestSize.Level1) @@ -474,7 +474,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, Put003, TestSize.Level1) * @tc.name: Put004 * @tc.desc: Put data into the local database * @tc.type: FUNC - * @tc.require: AR000CQDVD AR000CQS3Q + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, Put004, TestSize.Level1) @@ -537,7 +537,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, Put004, TestSize.Level1) * @tc.name: Clear001 * @tc.desc: Clear the data from an exist distributed db * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, Clear001, TestSize.Level1) @@ -570,7 +570,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, Clear001, TestSize.Level1) * @tc.name: PutBatch001 * @tc.desc: Putbatch data into the local database * @tc.type: FUNC - * @tc.require: AR000BVDFE AR000CQDVC + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, PutBatch001, TestSize.Level1) @@ -613,7 +613,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, PutBatch001, TestSize.Level1) * @tc.name: PutBatch002 * @tc.desc: PutBatch modified data into the local database * @tc.type: FUNC - * @tc.require: AR000BVDFE AR000CQDVC + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, PutBatch002, TestSize.Level1) @@ -655,7 +655,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, PutBatch002, TestSize.Level1) * @tc.name: Delete001 * @tc.desc: Delete existed data from the local database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, Delete001, TestSize.Level1) @@ -686,7 +686,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, Delete001, TestSize.Level1) * @tc.name: Delete002 * @tc.desc: Delete non-existed data from the local database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, Delete002, TestSize.Level1) @@ -709,7 +709,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, Delete002, TestSize.Level1) * @tc.name: DeleteBatch001 * @tc.desc: Delete the existed batch data from the local database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, DeleteBatch001, TestSize.Level1) @@ -752,7 +752,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, DeleteBatch001, TestSize.Leve * @tc.name: DeleteBatch002 * @tc.desc: Delete the non-existed batch data from the local database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, DeleteBatch002, TestSize.Level1) @@ -778,7 +778,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, DeleteBatch002, TestSize.Leve * @tc.name: GetEntries001 * @tc.desc: Get the batch data from the non-empty database by the prefix key. * @tc.type: FUNC - * @tc.require: AR000C6TUQ AR000CQDV3 + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntries001, TestSize.Level1) @@ -817,7 +817,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntries001, TestSize.Level * @tc.name: GetEntries002 * @tc.desc: Get all the data(empty prefixkey) from the empty database. * @tc.type: FUNC - * @tc.require: AR000C6TUQ AR000CQDV3 + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntries002, TestSize.Level1) @@ -842,7 +842,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntries002, TestSize.Level * @tc.name: GetEntries003 * @tc.desc: Get all the data(empty prefixkey) from the database. * @tc.type: FUNC - * @tc.require: AR000C6TUQ AR000CQDV3 + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntries003, TestSize.Level1) @@ -878,7 +878,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntries003, TestSize.Level * @tc.name: GetSnapshot001 * @tc.desc: Get observer is empty, whether you get the snapshot. * @tc.type: FUNC - * @tc.require: AR000BVRNF AR000CQDTI + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetSnapshot001, TestSize.Level1) @@ -895,7 +895,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetSnapshot001, TestSize.Leve * @tc.name: GetSnapshot002 * @tc.desc: Get observer is not empty, whether you get the snapshot. * @tc.type: FUNC - * @tc.require: AR000BVRNF AR000CQDTI + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetSnapshot002, TestSize.Level1) @@ -929,7 +929,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetSnapshot002, TestSize.Leve * @tc.name: ReleaseSnapshot001 * @tc.desc: To test the function of releasing an empty snapshot. * @tc.type: FUNC - * @tc.require: AR000BVRNF AR000CQDTI + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationTest, ReleaseSnapshot001, TestSize.Level1) @@ -947,7 +947,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, ReleaseSnapshot001, TestSize. * @tc.name: ReleaseSnapshot002 * @tc.desc: Release the obtained snapshot object that is not empty. * @tc.type: FUNC - * @tc.require: AR000BVRNF AR000CQDTI + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationTest, ReleaseSnapshot002, TestSize.Level1) @@ -959,7 +959,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, ReleaseSnapshot002, TestSize. * @tc.name: SetConflictResolutionPolicySuccessTest001 * @tc.desc: Verify SetConflictResolutionPolicy() return OK with valid input. * @tc.type: FUNC - * @tc.require: AR000CQE12 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesDataOperationTest, SetConflictResolutionPolicySuccessTest001, TestSize.Level1) @@ -981,7 +981,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, SetConflictResolutionPolicySu * @tc.name: SetConflictResolutionPolicyFailedTest001 * @tc.desc: Verify SetConflictResolutionPolicy() return INVALID_ARGS with invalid input. * @tc.type: FUNC - * @tc.require: AR000CQE12 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesDataOperationTest, SetConflictResolutionPolicyFailedTest001, TestSize.Level1) @@ -1004,7 +1004,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, SetConflictResolutionPolicyFa * @tc.name: GetEntriesWithQuery001 * @tc.desc: check query_format. * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntriesWithQuery001, TestSize.Level1) @@ -1096,7 +1096,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntriesWithQuery001, TestS * @tc.name: GetEntriesWithQuery002 * @tc.desc: GetEntries(const Query &query, std::vector &entries) interface test. * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntriesWithQuery002, TestSize.Level1) @@ -1142,7 +1142,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntriesWithQuery002, TestS * @tc.name: GetEntriesWithQuery003 * @tc.desc: GetEntries(const Query &query, std::vector &entries) interface test. * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntriesWithQuery003, TestSize.Level1) @@ -1181,7 +1181,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntriesWithQuery003, TestS * @tc.name: GetEntriesWithQuery004 * @tc.desc: GetEntries(const Query &query, std::vector &entries) interface test. * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntriesWithQuery004, TestSize.Level1) @@ -1230,7 +1230,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntriesWithQuery004, TestS * @tc.name: QueryIsNotNull001 * @tc.desc: IsNotNull interface normal function * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryIsNotNull001, TestSize.Level1) @@ -1286,7 +1286,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryIsNotNull001, TestSize.L * @tc.name: QueryPreFixKey001 * @tc.desc: Normal function of query by prefix key * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryPreFixKey001, TestSize.Level1) @@ -1368,7 +1368,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryPreFixKey001, TestSize.L * @tc.name: QueryPreFixKey003 * @tc.desc: For special key prefix combination condition of query * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryPreFixKey003, TestSize.Level1) @@ -1431,7 +1431,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryPreFixKey003, TestSize.L * @tc.name: QueryPreFixKey004 * @tc.desc: Query a prefix that does not exist * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryPreFixKey004, TestSize.Level1) @@ -1476,7 +1476,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryPreFixKey004, TestSize.L * @tc.name: QueryGroup001 * @tc.desc: Query group nomal ability to change operation priority * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryGroup001, TestSize.Level1) @@ -1552,7 +1552,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryGroup001, TestSize.Level * @tc.name: QueryGroup002 * @tc.desc: Test for illegal Group query object * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryGroup002, TestSize.Level1) @@ -1630,7 +1630,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryGroup002, TestSize.Level * @tc.name: QueryGroup003 * @tc.desc: Query expressions containing nested parentheses * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryGroup003, TestSize.Level1) @@ -1678,7 +1678,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryGroup003, TestSize.Level * @tc.name: multiOrderBy001 * @tc.desc: Test multiple orderby conditions together to query * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, multiOrderBy001, TestSize.Level1) @@ -1723,7 +1723,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, multiOrderBy001, TestSize.Lev * @tc.name: multiOrderBy001 * @tc.desc: For multiple order query. * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, PreifxAndOrderBy001, TestSize.Level1) @@ -1774,7 +1774,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, PreifxAndOrderBy001, TestSize * @tc.name: PrefixAndOther001 * @tc.desc: Combination of prefix query and logical filtering * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, PrefixAndOther001, TestSize.Level1) @@ -1811,7 +1811,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, PrefixAndOther001, TestSize.L * @tc.name: InKeys001 * @tc.desc: InKeys query base function * @tc.type: FUNC - * @tc.require: AR000GOH06 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeys001, TestSize.Level1) @@ -1873,7 +1873,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeys001, TestSize.Level1) * @tc.name: InKeysLimit001 * @tc.desc: InKeys query limit verification * @tc.type: FUNC - * @tc.require: AR000GOH06 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeysLimit001, TestSize.Level1) @@ -1928,7 +1928,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeysLimit001, TestSize.Leve * @tc.name: InKeysAndOther001 * @tc.desc: Combination of InKeys query and logical filtering * @tc.type: FUNC - * @tc.require: AR000GOH06 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeysAndOther001, TestSize.Level1) @@ -1987,7 +1987,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeysAndOther001, TestSize.L * @tc.name: InKeysAndOther002 * @tc.desc: Combination of InKeys query and logical filtering * @tc.type: FUNC - * @tc.require: AR000GOH06 + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeysAndOther002, TestSize.Level1) @@ -2028,10 +2028,10 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeysAndOther002, TestSize.L * @tc.name: WriteTimeSort001 * @tc.desc: For prefixKey query with orderBy writeTime asc * @tc.type: FUNC - * @tc.require: SR000H5U55 + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort001, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort001, TestSize.Level1) { /** * @tc.steps: step1. Create a database And Preset Data @@ -2103,10 +2103,10 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort001, TestSize.Le * @tc.name: WriteTimeSort002 * @tc.desc: For prefixKey query with orderBy writeTime asc * @tc.type: FUNC - * @tc.require: SR000H5U55 + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort002, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort002, TestSize.Level1) { /** * @tc.steps: step1. Create a database And Preset Data @@ -2168,10 +2168,10 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort002, TestSize.Le * @tc.name: WriteTimeSort003 * @tc.desc: For prefixKey query with orderBy writeTime desc * @tc.type: FUNC - * @tc.require: SR000H5U55 + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort003, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort003, TestSize.Level1) { /** * @tc.steps: step1. Create a database And Preset Data @@ -2243,10 +2243,10 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort003, TestSize.Le * @tc.name: WriteTimeSort004 * @tc.desc: For prefixKey query with orderBy writeTime asc * @tc.type: FUNC - * @tc.require: SR000H5U55 + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort004, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort004, TestSize.Level1) { /** * @tc.steps: step1. Create a database And Preset Data @@ -2320,10 +2320,10 @@ void CheckResultSize(KvStoreResultSet *resultSet, const std::vector &expect * @tc.name: WriteTimeSort005 * @tc.desc: For inkeys query with orderBy writeTime asc * @tc.type: FUNC - * @tc.require: SR000H5U55 + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort005, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort005, TestSize.Level1) { /** * @tc.steps: step1. Create a database And Preset Data @@ -2393,10 +2393,10 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort005, TestSize.Le * @tc.name: WriteTimeSort006 * @tc.desc: For inkeys query with orderBy writeTime desc * @tc.type: FUNC - * @tc.require: SR000H5U55 + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort006, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort006, TestSize.Level1) { /** * @tc.steps: step1. Create a database And Preset Data @@ -2466,7 +2466,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort006, TestSize.Le * @tc.name: WriteTimeSort007 * @tc.desc: For unsupport query when getEntries * @tc.type: FUNC - * @tc.require: SR000H5U55 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort007, TestSize.Level0) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp index 982cf0ea16eabc6034b7cb1740a61168e15506db..282cd5026c04a815bfd6c857f2fa91fd60e0b2db 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp @@ -54,13 +54,13 @@ namespace { std::string identifierName = DBCommon::TransferStringToHex(hashIdentifierName); std::string filePath = g_testDir + "/" + identifierName + "/"; if (databaseType == DBConstant::DB_TYPE_LOCAL) { // local - filePath += (DBConstant::LOCAL_SUB_DIR + "/" + DBConstant::LOCAL_DATABASE_NAME + + filePath += (std::string(DBConstant::LOCAL_SUB_DIR) + "/" + DBConstant::LOCAL_DATABASE_NAME + DBConstant::DB_EXTENSION); } else if (databaseType == DBConstant::DB_TYPE_SINGLE_VER) { // single ver - filePath += (DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::MAINDB_DIR + "/" + + filePath += (std::string(DBConstant::SINGLE_SUB_DIR) + "/" + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION); } else if (databaseType == DBConstant::DB_TYPE_MULTI_VER) { // multi ver - filePath += (DBConstant::MULTI_SUB_DIR + "/" + DBConstant::MULTI_VER_DATA_STORE + + filePath += (std::string(DBConstant::MULTI_SUB_DIR) + "/" + DBConstant::MULTI_VER_DATA_STORE + DBConstant::DB_EXTENSION); } else { filePath = ""; @@ -136,7 +136,7 @@ void DistributedDBInterfacesDatabaseCorruptTest::TearDown(void) * @tc.name: DatabaseCorruptionHandleTest001 * @tc.desc: Check the corruption detect without setting the corrupt handler. * @tc.type: FUNC - * @tc.require: AR000D487C SR000D4878 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest001, TestSize.Level3) @@ -180,7 +180,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes * @tc.name: DatabaseCorruptionHandleTest002 * @tc.desc: Get kv store through different parameters for the same storeID. * @tc.type: FUNC - * @tc.require: AR000D487C SR000D4878 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest002, TestSize.Level1) @@ -252,7 +252,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes * @tc.name: DatabaseCorruptionHandleTest003 * @tc.desc: Test the CloseKvStore Interface and check whether the database file can be closed. * @tc.type: FUNC - * @tc.require: AR000D487C SR000D4878 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest003, TestSize.Level1) @@ -325,7 +325,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes * @tc.name: DatabaseCorruptionHandleTest004 * @tc.desc: Test the DeleteKvStore Interface and check whether the database files can be removed. * @tc.type: FUNC - * @tc.require: AR000D487C SR000D4878 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest004, TestSize.Level1) @@ -385,7 +385,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes * @tc.name: DatabaseCorruptionHandleTest005 * @tc.desc: Test the DeleteKvStore Interface and check whether the database files can be removed. * @tc.type: FUNC - * @tc.require: AR000D487C SR000D4878 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest005, TestSize.Level1) @@ -565,7 +565,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseRebuildTest001, Tes * @tc.name: DatabaseIntegrityCheck001 * @tc.desc: Test the integrity check option. * @tc.type: FUNC - * @tc.require: AR000D487C SR000D4878 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseIntegrityCheck001, TestSize.Level2) @@ -581,7 +581,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseIntegrityCheck001, * @tc.name: DatabaseIntegrityCheck002 * @tc.desc: Test the integrity check interface. * @tc.type: FUNC - * @tc.require: AR000D487C SR000D4878 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseIntegrityCheck002, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp index a6c0eb5114861b62af516fef5cf83be93b23149f..f8307e0d84e1df6cf572833726210cbf154a0e62 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp @@ -124,7 +124,7 @@ void DistributedDBInterfacesDatabaseRdKernelTest::TearDown(void) * @tc.name: GetKvStore003 * @tc.desc: Get kv store through different SecurityOption, abnormal or normal. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: * @tc.author: liuwenkai */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore003, TestSize.Level1) @@ -192,7 +192,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore003, TestSize.Le * @tc.name: GetKvStore004 * @tc.desc: Get kv store parameters with Observer and Notifier, then trigger callback. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: * @tc.author: liuwenkai */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore004, TestSize.Level1) @@ -509,7 +509,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStoreWithInvalidOptio * @tc.name: RepeatCloseKvStore001 * @tc.desc: Close the kv store repeatedly and check the database. * @tc.type: FUNC - * @tc.require: AR000C2F0C AR000CQDV7 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, RepeatCloseKvStore001, TestSize.Level2) @@ -564,7 +564,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, RepeatCloseKvStore001, Tes * @tc.name: CreatKvStoreWithSchema001 * @tc.desc: Create non-memory KvStore with schema, check if create success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, CreatKvStoreWithSchema001, TestSize.Level1) @@ -586,7 +586,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, CreatKvStoreWithSchema001, * @tc.name: OpenKvStoreWithStoreOnly001 * @tc.desc: open the kv store with the option that createDirByStoreIdOnly is true. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, OpenKvStoreWithStoreOnly001, TestSize.Level1) @@ -623,7 +623,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, OpenKvStoreWithStoreOnly00 * @tc.name: GetDBWhileOpened001 * @tc.desc: open the kv store with the option that createDirByStoreIdOnly is true. * @tc.type: FUNC - * @tc.require: AR000E8S2V + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetDBWhileOpened001, TestSize.Level1) @@ -728,7 +728,7 @@ namespace { * @tc.name: FreqOpenCloseDel001 * @tc.desc: Open/close/delete the kv store concurrently. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, FreqOpenCloseDel001, TestSize.Level2) @@ -740,7 +740,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, FreqOpenCloseDel001, TestS * @tc.name: FreqOpenClose001 * @tc.desc: Open and close the kv store concurrently. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, FreqOpenClose001, TestSize.Level2) @@ -752,7 +752,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, FreqOpenClose001, TestSize * @tc.name: CheckKvStoreDir001 * @tc.desc: Delete the kv store with the option that createDirByStoreIdOnly is true. * @tc.type: FUNC - * @tc.require: AR000CQDV7 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, CheckKvStoreDir001, TestSize.Level1) @@ -788,7 +788,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, CheckKvStoreDir001, TestSi * @tc.name: CompressionRate1 * @tc.desc: Open the kv store with invalid compressionRate and open successfully. * @tc.type: FUNC - * @tc.require: AR000G3QTT + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, CompressionRate1, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_test.cpp index 77952bc66b44ee214f2343d2ffa16be0706cc543..9aca7bed476c71b4f1fb52871f65639e4ca86d6a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_test.cpp @@ -357,7 +357,7 @@ void DistributedDBInterfacesDatabaseTest::TearDown(void) * @tc.name: GetKvStore001 * @tc.desc: Get kv store through different parameters. * @tc.type: FUNC - * @tc.require: AR000CQDV4 AR000CQS3P + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetKvStore001, TestSize.Level1) @@ -484,7 +484,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetKvStore001, TestSize.Level1) * @tc.name: GetKvStore002 * @tc.desc: Get kv store through different parameters for the same storeID. * @tc.type: FUNC - * @tc.require: AR000CQDV5 AR000CQS3P + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetKvStore002, TestSize.Level1) @@ -553,7 +553,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetKvStore002, TestSize.Level1) * @tc.name: GetKvStore003 * @tc.desc: Get kv store through different SecurityOption, abnormal or normal. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: * @tc.author: liuwenkai */ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetKvStore003, TestSize.Level1) @@ -623,7 +623,7 @@ static void NotifierCallback(const KvStoreNbConflictData &data) * @tc.name: GetKvStore004 * @tc.desc: Get kv store parameters with Observer and Notifier, then trigger callback. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: * @tc.author: liuwenkai */ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetKvStore004, TestSize.Level1) @@ -685,7 +685,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetKvStore004, TestSize.Level1) * @tc.name: CloseKvStore001 * @tc.desc: Test the CloseKvStore Interface and check whether the database file can be closed. * @tc.type: FUNC - * @tc.require: AR000CQDV6 AR000CQS3P + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDatabaseTest, CloseKvStore001, TestSize.Level1) @@ -731,7 +731,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, CloseKvStore001, TestSize.Level1) * @tc.name: DeleteKvStore001 * @tc.desc: Test the DeleteKvStore Interface and check whether the database files can be removed. * @tc.type: FUNC - * @tc.require: AR000C2F0C AR000CQDV7 + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDatabaseTest, DeleteKvStore001, TestSize.Level1) @@ -808,7 +808,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, DeleteKvStore001, TestSize.Level1) * @tc.name: RepeatCloseKvStore001 * @tc.desc: Close the kv store repeatedly and check the database. * @tc.type: FUNC - * @tc.require: AR000C2F0C AR000CQDV7 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseTest, RepeatCloseKvStore001, TestSize.Level2) @@ -863,7 +863,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, RepeatCloseKvStore001, TestSize.Le * @tc.name: CreatKvStoreWithSchema001 * @tc.desc: Create non-memory KvStore with schema, check if create success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseTest, CreatKvStoreWithSchema001, TestSize.Level1) @@ -925,7 +925,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, CreatKvStoreWithSchema001, TestSiz * @tc.name: CreatKvStoreWithSchema002 * @tc.desc: Create memory KvStore with schema, check if create success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseTest, CreatKvStoreWithSchema002, TestSize.Level1) @@ -955,7 +955,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, CreatKvStoreWithSchema002, TestSiz * @tc.name: OpenKvStoreWithSchema001 * @tc.desc: open an opened kvstore(non-memory, no-schema) with schema, check if open success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema001, TestSize.Level1) @@ -1030,7 +1030,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema001, TestSize * @tc.name: OpenKvStoreWithSchema002 * @tc.desc: open an opened kvstore(non-memory, schema) with schema, check if open success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema002, TestSize.Level1) @@ -1051,7 +1051,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema002, TestSize * @tc.name: OpenKvStoreWithSchema003 * @tc.desc: open an opened kvstore(memory) with different schemas, check if open success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema003, TestSize.Level1) @@ -1098,7 +1098,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema003, TestSize * @tc.name: OpenKvStoreWithSchema004 * @tc.desc: open a totally closed schema-kvstore(non-memory) with different schemas, check if open success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema004, TestSize.Level1) @@ -1123,7 +1123,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema004, TestSize * @tc.name: OpenKvStoreWithSchema005 * @tc.desc: open a totally closed non-schema-kvstore(non-memory) with different schemas, check if open success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema005, TestSize.Level1) @@ -1146,7 +1146,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema005, TestSize * @tc.name: OpenKvStoreWithSchema006 * @tc.desc: open a memory non-schema-kvstore with different schemas, check if open success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema006, TestSize.Level1) @@ -1200,7 +1200,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema006, TestSize * @tc.name: OpenKvStoreWithStoreOnly001 * @tc.desc: open the kv store with the option that createDirByStoreIdOnly is true. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithStoreOnly001, TestSize.Level1) @@ -1236,7 +1236,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithStoreOnly001, TestS * @tc.name: GetDBWhileOpened001 * @tc.desc: open the kv store with the option that createDirByStoreIdOnly is true. * @tc.type: FUNC - * @tc.require: AR000E8S2V + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetDBWhileOpened001, TestSize.Level1) @@ -1340,7 +1340,7 @@ namespace { * @tc.name: FreqOpenCloseDel001 * @tc.desc: Open/close/delete the kv store concurrently. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseTest, FreqOpenCloseDel001, TestSize.Level2) @@ -1352,7 +1352,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, FreqOpenCloseDel001, TestSize.Leve * @tc.name: FreqOpenClose001 * @tc.desc: Open and close the kv store concurrently. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseTest, FreqOpenClose001, TestSize.Level2) @@ -1364,7 +1364,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, FreqOpenClose001, TestSize.Level2) * @tc.name: CheckKvStoreDir001 * @tc.desc: Delete the kv store with the option that createDirByStoreIdOnly is true. * @tc.type: FUNC - * @tc.require: AR000CQDV7 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseTest, CheckKvStoreDir001, TestSize.Level1) @@ -1399,7 +1399,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, CheckKvStoreDir001, TestSize.Level * @tc.name: CompressionRate1 * @tc.desc: Open the kv store with invalid compressionRate and open successfully. * @tc.type: FUNC - * @tc.require: AR000G3QTT + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBInterfacesDatabaseTest, CompressionRate1, TestSize.Level1) @@ -1515,8 +1515,68 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, KvObserver001, TestSize.Level0) observer.OnChange(changedData); RelationalStoreChangedDataImpl storeChangedData(""); observer.OnChange(storeChangedData); + observer.StoreObserver::OnChange(storeChangedData); StoreObserver::StoreChangedInfo info; observer.OnChange(std::move(info)); + StoreObserver::StoreChangedInfo info1; + observer.StoreObserver::OnChange(std::move(info1)); ChangedData simpleData; observer.OnChange(Origin::ORIGIN_ALL, "", std::move(simpleData)); + ChangedData simpleData1; + observer.StoreObserver::OnChange(Origin::ORIGIN_ALL, "", std::move(simpleData1)); + EXPECT_EQ(observer.StoreObserver::GetCallbackDetailsType(), static_cast(CallbackDetailsType::DEFAULT)); +} + +void AsyncGet001CheckRes(int count, const Key &key) +{ + for (int i = 0; i < count; ++i) { + std::vector entries; + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(key, entries), OK); + for (const auto &item : entries) { + EXPECT_EQ(VALUE_1, item.value); + } + } +} + +/** + * @tc.name: AsyncGet001 + * @tc.desc: Test get data by diff thread at the same time. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBInterfacesDatabaseTest, AsyncGet001, TestSize.Level4) +{ + /** + * @tc.steps: step1. Open the kv store with the option that comressionRate is invalid. + * @tc.expected: step1. Open kv store successfully. Returns OK. + */ + KvStoreNbDelegate::Option option; + const std::string storeId("AsyncGet001"); + g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + /** + * @tc.steps: step2. Get key in diff thead. + * @tc.expected: step2. Returns OK. + */ + const Key key = {'k', '1'}; + EXPECT_EQ(g_kvNbDelegatePtr->Put(key, VALUE_1), OK); + const int count = 1000; + std::thread t1([&key]() { + AsyncGet001CheckRes(count, key); + }); + std::thread t2([&key]() { + AsyncGet001CheckRes(count, key); + }); + std::thread t3([&key]() { + AsyncGet001CheckRes(count, key); + }); + t1.join(); + t2.join(); + t3.join(); + + g_mgr.CloseKvStore(g_kvNbDelegatePtr); + g_kvNbDelegatePtr = nullptr; + EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_device_identifier_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_device_identifier_test.cpp index d3e1b8216daad5d4b1b9a5cadeb25b5a8d0b3943..f0f16ad6639cafcd9274c954f0f8ac7d321f741c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_device_identifier_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_device_identifier_test.cpp @@ -124,7 +124,7 @@ void DistributedDBDeviceIdentifierTest::TearDown(void) * @tc.desc: Set pragma to be GET_DEVICE_IDENTIFIER_OF_ENTRY, * set Key to be null and origDevice to be false, expect return INVALID_ARGS. * @tc.type: FUNC - * @tc.require: AR000D08KV + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier001, TestSize.Level1) @@ -152,7 +152,7 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier001, TestSize.Level1 * @tc.desc: Set pragma to be GET_DEVICE_IDENTIFIER_OF_ENTRY, * set Key to be null and origDevice to be true, expect return INVALID_ARGS. * @tc.type: FUNC - * @tc.require: AR000D08KV + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier002, TestSize.Level1) @@ -180,7 +180,7 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier002, TestSize.Level1 * @tc.desc: Set pragma to be GET_DEVICE_IDENTIFIER_OF_ENTRY and origDevice to be false. * Check if a non-existing key will return NOT_FOUND. * @tc.type: FUNC - * @tc.require: AR000D08KV + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier003, TestSize.Level1) @@ -206,7 +206,7 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier003, TestSize.Level1 * @tc.desc: Set pragma to be GET_DEVICE_IDENTIFIER_OF_ENTRY and origDevice to be true. * Check if a non-existing key will return NOT_FOUND. * @tc.type: FUNC - * @tc.require: AR000D08KV + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier004, TestSize.Level1) @@ -231,7 +231,7 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier004, TestSize.Level1 * @tc.name: DeviceIdentifier005 * @tc.desc: Set pragma to be GET_DEVICE_IDENTIFIER_OF_ENTRY and origDevice to be false. check if returns OK. * @tc.type: FUNC - * @tc.require: AR000D08KV + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier005, TestSize.Level1) @@ -256,7 +256,7 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier005, TestSize.Level1 * @tc.name: DeviceIdentifier006 * @tc.desc: Set pragma to be GET_DEVICE_IDENTIFIER_OF_ENTRY and origDevice to be true. check if returns OK. * @tc.type: FUNC - * @tc.require: AR000D08KV + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier006, TestSize.Level1) @@ -281,7 +281,7 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier006, TestSize.Level1 * @tc.name: DeviceIdentifier007 * @tc.desc: Set pragma to be GET_IDENTIFIER_OF_DEVICE. check if empty deviceID returns INVALID_ARGS. * @tc.type: FUNC - * @tc.require: AR000D08KV + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier007, TestSize.Level1) @@ -300,7 +300,7 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier007, TestSize.Level1 * @tc.name: DeviceIdentifier008 * @tc.desc: Set pragma to be GET_IDENTIFIER_OF_DEVICE. check if deviceIdentifier matches deviceID. * @tc.type: FUNC - * @tc.require: AR000D08KV + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier008, TestSize.Level1) @@ -629,6 +629,18 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, StorageEngineTest005, TestSize.Level ASSERT_NE(storageEngine, nullptr); EXPECT_EQ(storageEngine->CheckEngineOption(g_property), E_OK); RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); + /** + * @tc.steps: step1. set max value size + * @tc.expected: step1. Expect return OK + */ + uint32_t valSize = 64 * 1024 * 1024; + PragmaData input = static_cast(&valSize); + EXPECT_TRUE(g_kvNbDelegatePtr->Pragma(SET_MAX_VALUE_SIZE, input) == OK); + /** + * @tc.steps: step2. set max value size again + * @tc.expected: step2. Expect return OK + */ + EXPECT_EQ(g_kvNbDelegatePtr->Pragma(SET_MAX_VALUE_SIZE, input), OK); } /** @@ -762,4 +774,39 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, StorageEngineTest008, TestSize.Level subs.push_back(sub); EXPECT_EQ(g_store->RemoveSubscribe(subs), -1); storageEngine->Release(); +} + +/** + * @tc.name: StorageEngineTest009 + * @tc.desc: Test pragma + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBDeviceIdentifierTest, StorageEngineTest009, TestSize.Level0) +{ + /** + * @tc.steps: step1. Remove device data with null db + * @tc.expected: step1. Return -E_INVALID_DB + */ + PragmaData input = nullptr; + auto con = std::make_shared(nullptr); + EXPECT_EQ(con->Pragma(RM_DEVICE_DATA, input), -E_INVALID_DB); + /** + * @tc.steps: step2. Remove device data with null + * @tc.expected: step2. Return DB_ERROR + */ + auto store = new(std::nothrow) SQLiteSingleVerNaturalStore(); + con->SetSafeDeleted(); + con = std::make_shared(store); + EXPECT_EQ(con->Pragma(RM_DEVICE_DATA, input), -E_INVALID_DB); + /** + * @tc.steps: step3. Remove device data with dev + * @tc.expected: step3. Return -E_NOT_INIT + */ + std::string dev = "dev"; + input = static_cast(&dev); + EXPECT_EQ(con->Pragma(RM_DEVICE_DATA, input), -E_NOT_INIT); + con = nullptr; + RefObject::KillAndDecObjRef(store); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_database_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_database_test.cpp index 244b0dffb10d067e384e07e20692c4b48b12ff9d..4d868fae466eeb6339944316a28faf2314891831 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_database_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_database_test.cpp @@ -204,7 +204,7 @@ void DistributedDBInterfacesEncryptDatabaseTest::CheckRekeyWithExistedObserver(b * @tc.name: LocalDatabaseRekeyCheck001 * @tc.desc: Attempt to rekey while another delegate is existed. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, LocalDatabaseRekeyCheck001, TestSize.Level1) @@ -233,7 +233,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, LocalDatabaseRekeyCheck001, * @tc.name: LocalDatabaseRekeyCheck002 * @tc.desc: Attempt to rekey while the snapshot is existed. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, LocalDatabaseRekeyCheck002, TestSize.Level1) @@ -262,7 +262,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, LocalDatabaseRekeyCheck002, * @tc.name: MultiVerRekeyCheck001 * @tc.desc: Attempt to rekey while another delegate is existed. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, MultiVerRekeyCheck001, TestSize.Level1) @@ -291,7 +291,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, MultiVerRekeyCheck001, Test * @tc.name: MultiVerRekeyCheck002 * @tc.desc: Attempt to rekey while the snapshot is existed. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, MultiVerRekeyCheck002, TestSize.Level1) @@ -320,7 +320,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, MultiVerRekeyCheck002, Test * @tc.name: MultiVerRekeyCheck003 * @tc.desc: Attempt to rekey while the observer is existed. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, MultiVerRekeyCheck003, TestSize.Level1) @@ -376,7 +376,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, ExportAndImportCheck001, Te * @tc.name: SingleVerRekeyCheck001 * @tc.desc: Attempt to rekey while another delegate is existed. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, SingleVerRekeyCheck001, TestSize.Level1) @@ -428,7 +428,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, SingleVerRekeyCheck001, Tes * @tc.name: SingleVerRekeyCheck002 * @tc.desc: Attempt to rekey when the observer exists. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, SingleVerRekeyCheck002, TestSize.Level1) @@ -483,7 +483,7 @@ static void NotifierCallback(const KvStoreNbConflictData &data) * @tc.name: SingleVerRekeyCheck003 * @tc.desc: Attempt to rekey while the conflict notifier is set. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, SingleVerRekeyCheck003, TestSize.Level1) @@ -529,7 +529,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, SingleVerRekeyCheck003, Tes * @tc.name: SingleVerRekeyCheck004 * @tc.desc: Test rekey and removeDeviceData * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, SingleVerRekeyCheck004, TestSize.Level3) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_delegate_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_delegate_test.cpp index 1d15ede5232339600ddaff7041cb8196866f3263..96d4b864c2bb440e9c5cea5567918e5d98475de8 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_delegate_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_delegate_test.cpp @@ -144,7 +144,7 @@ void DistributedDBInterfacesEncryptDelegateTest::TearDown(void) {} * @tc.name: EncryptedDbOperation001 * @tc.desc: Test the single version db encrypted function. * @tc.type: FUNC - * @tc.require: AR000CQDT5 AR000CQDT6 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbOperation001, TestSize.Level1) @@ -222,7 +222,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbOperation001, Te * @tc.name: EncryptedDbOperation002 * @tc.desc: Test the local db encrypted function. * @tc.type: FUNC - * @tc.require: AR000CQDT5 AR000CQDT6 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbOperation002, TestSize.Level1) @@ -303,7 +303,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbOperation002, Te * @tc.name: EncryptedDbOperation003 * @tc.desc: Test the multi version db encrypted function. * @tc.type: FUNC - * @tc.require: AR000CQDT5 AR000CQDT6 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbOperation003, TestSize.Level1) @@ -385,7 +385,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbOperation003, Te * @tc.name: EncryptedDbSwitch001 * @tc.desc: Test the single version db for Rekey function. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch001, TestSize.Level1) @@ -451,7 +451,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch001, TestS * @tc.name: EncryptedDbSwitch002 * @tc.desc: Test the single version db Rekey function return BUSY because of multiple instances. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch002, TestSize.Level1) @@ -486,7 +486,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch002, TestS * @tc.name: EncryptedDbSwitch003 * @tc.desc: Test the single version db Rekey function return BUSY because of observer. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch003, TestSize.Level1) @@ -518,7 +518,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch003, TestS * @tc.name: EncryptedDbSwitch004 * @tc.desc: Test the single version db Rekey function return BUSY because of conflict notifier. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch004, TestSize.Level1) @@ -546,7 +546,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch004, TestS * @tc.name: EncryptedDbSwitch009 * @tc.desc: Test the single version db Rekey function from password1 to password2. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch009, TestSize.Level1) @@ -583,7 +583,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch009, TestS * @tc.name: EncryptedDbSwitch010 * @tc.desc: Test the single version db Rekey function from encrypted db unencrypted db . * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch010, TestSize.Level1) @@ -618,7 +618,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch010, TestS * @tc.name: EncryptedDbSwitch011 * @tc.desc: Test the single version db Rekey function from unencrypted db to encrypted db. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch011, TestSize.Level1) @@ -655,7 +655,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch011, TestS * @tc.name: EncryptedDbSwitch012 * @tc.desc: Test the local db Rekey function from password1 to password2. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch012, TestSize.Level1) @@ -704,7 +704,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch012, TestS * @tc.name: EncryptedDbSwitch013 * @tc.desc: Test the local db Rekey function from encrypted db unencrypted db . * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch013, TestSize.Level1) @@ -751,7 +751,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch013, TestS * @tc.name: EncryptedDbSwitch014 * @tc.desc: Test the local db Rekey function from unencrypted db to encrypted db. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch014, TestSize.Level1) @@ -799,7 +799,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch014, TestS * @tc.name: EncryptedDbSwitch015 * @tc.desc: Test the multi version db Rekey function from password1 to password2. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch015, TestSize.Level1) @@ -851,7 +851,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch015, TestS * @tc.name: EncryptedDbSwitch016 * @tc.desc: Test the multi version db Rekey function from encrypted db unencrypted db . * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch016, TestSize.Level1) @@ -898,7 +898,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch016, TestS * @tc.name: EncryptedDbSwitch017 * @tc.desc: Test the multi version db Rekey function from unencrypted db to encrypted db. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch017, TestSize.Level1) @@ -947,7 +947,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch017, TestS * @tc.name: OpenEncryptedDb001 * @tc.desc: Test create an encrypted database successfully. * @tc.type: FUNC - * @tc.require: AR000CQDT5 AR000CQDT6 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, OpenEncryptedDb001, TestSize.Level1) @@ -985,7 +985,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, OpenEncryptedDb001, TestSiz * @tc.name: OpenEncryptedDb002 * @tc.desc: Test create an encrypted database failed. * @tc.type: FUNC - * @tc.require: AR000CQDT8 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, OpenEncryptedDb002, TestSize.Level1) @@ -1025,7 +1025,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, OpenEncryptedDb002, TestSiz * @tc.name: OpenEncryptedDb003 * @tc.desc: Test reopen an encrypted database successfully. * @tc.type: FUNC - * @tc.require: AR000CQDT8 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, OpenEncryptedDb003, TestSize.Level1) @@ -1077,7 +1077,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, OpenEncryptedDb003, TestSiz * @tc.name: OpenEncryptedDb004 * @tc.desc: Test reopen an encrypted database failed. * @tc.type: FUNC - * @tc.require: AR000CQDT8 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, OpenEncryptedDb004, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_rd_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_rd_test.cpp index 2c6befc7b85650b2d9eea98f8faec3b0166df0a2..882ebdd6c47aeb59cae7c9a593cf4cee310e983d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_rd_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_rd_test.cpp @@ -122,6 +122,8 @@ void DistributedDBInterfacesImportAndExportRdTest::TearDownTestCase(void) if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error!"); } + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAdapter(nullptr); RuntimeContext::GetInstance()->StopTaskPool(); // wait for all thread exit } @@ -241,7 +243,7 @@ int DistributedDBInterfacesImportAndExportRdTest::ModifyDataInPage(int modifyPos { FILE *fp = fopen(modifyFile, "rb+"); if (fp == nullptr) { - printf("Failed to open file"); + LOGE("Failed to open file"); return 1; } (void)fseek(fp, modifyPos, SEEK_SET); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp index 47a579621c2e94f9dfc4712e33ba2ec3399d3bd6..dfd62a2e2157be8951e031a13563a7eba51de9b4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp @@ -143,7 +143,7 @@ void DistributedDBInterfacesImportAndExportTest::TearDown(void) * @tc.name: NormalExport001 * @tc.desc: The data of the current version of the board is exported and the package file is single. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, NormalExport001, TestSize.Level1) @@ -191,7 +191,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, NormalExport001, TestSize.L * @tc.name: UndisturbedlSingleExport001 * @tc.desc: Check that the export action is an independent transaction. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, UndisturbedlSingleExport001, TestSize.Level1) @@ -264,7 +264,7 @@ static void GetSnapshotUnitTest(KvStoreDelegate *&kvDelegatePtr, KvStoreSnapshot * @tc.name: UndisturbedlMultiExport001 * @tc.desc: Check that the export action is an independent transaction. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, UndisturbedlMultiExport001, TestSize.Level1) @@ -336,7 +336,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, UndisturbedlMultiExport001, * @tc.name: ExportParameterCheck001 * @tc.desc: Check the verification of abnormal interface parameters. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExportParameterCheck001, TestSize.Level1) @@ -405,7 +405,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExportParameterCheck001, Te * @tc.name: ExportParameterCheck002 * @tc.desc: Check the verification of abnormal interface parameters. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExportParameterCheck002, TestSize.Level1) @@ -480,7 +480,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExportParameterCheck002, Te * @tc.name: NormalImport001 * @tc.desc: Normal import capability for single version, parameter verification capability * @tc.type: FUNC - * @tc.require: AR000D487A + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, NormalImport001, TestSize.Level1) @@ -539,7 +539,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, NormalImport001, TestSize.L * @tc.name: NormalImport002 * @tc.desc: Normal import capability for multi version, parameter verification capability * @tc.type: FUNC - * @tc.require: AR000D487A + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, NormalImport002, TestSize.Level1) @@ -605,7 +605,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, NormalImport002, TestSize.L * @tc.name: ExceptionFileImport001 * @tc.desc: Normal import capability for single version, parameter verification capability * @tc.type: FUNC - * @tc.require: AR000D487A + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExceptionFileImport001, TestSize.Level1) @@ -658,7 +658,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExceptionFileImport001, Tes * @tc.name: ExceptionFileImport002 * @tc.desc: Normal import capability for multi version, parameter verification capability * @tc.type: FUNC - * @tc.require: AR000D487A + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExceptionFileImport002, TestSize.Level1) @@ -690,7 +690,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExceptionFileImport002, Tes * @tc.name: ExceptionFileImport003 * @tc.desc: The data of the current version of the board is exported and the package file is single. * @tc.type: FUNC - * @tc.require: AR000D487A + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExceptionFileImport003, TestSize.Level1) @@ -750,7 +750,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExceptionFileImport003, Tes * @tc.name: ExceptionFileImport004 * @tc.desc: The data of the current version of the board is exported and the package file is single. * @tc.type: FUNC - * @tc.require: AR000D487A + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExceptionFileImport004, TestSize.Level1) @@ -851,7 +851,7 @@ static void TryDbForPasswordIndependence001() * @tc.name: PasswordIndependence001 * @tc.desc: The data of the current version of the board is exported and the package file is single. * @tc.type: FUNC - * @tc.require: AR000D487B + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, PasswordIndependence001, TestSize.Level1) @@ -938,7 +938,7 @@ static void TryDbForPasswordIndependence002() * @tc.name: PasswordIndependence002 * @tc.desc: The data of the current version of the board is exported and the package file is single. * @tc.type: FUNC - * @tc.require: AR000D487B + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, PasswordIndependence002, TestSize.Level1) @@ -996,7 +996,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, PasswordIndependence002, Te * @tc.name: PasswordIndependence002 * @tc.desc: The data of the current version of the board is exported and the package file is single. * @tc.type: FUNC - * @tc.require: AR000D487B + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, PasswordIndependence003, TestSize.Level1) @@ -1061,7 +1061,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, PasswordIndependence003, Te * @tc.name: SeparaDbExportAndImport * @tc.desc: Import and export after Separate database. * @tc.type: FUNC - * @tc.require: AR000D487B + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, SeparaDbExportAndImport, TestSize.Level1) @@ -1120,7 +1120,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, SeparaDbExportAndImport, Te * @tc.name: SeparaDbExportAndImport * @tc.desc: Import and export after Separate database. * @tc.type: FUNC - * @tc.require: AR000D487B + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, SeparaDbNoPasswdRekey, TestSize.Level1) @@ -1374,7 +1374,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ImportTest001, TestSize.Lev * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBInterfacesImportAndExportTest, CheckSecurityLabel001, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesImportAndExportTest, CheckSecurityLabel001, TestSize.Level1) { std::shared_ptr adapter = std::make_shared(); RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(adapter); @@ -1421,7 +1421,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, CheckSecurityLabel001, Test * @tc.require: * @tc.author: liuhongyang */ -HWTEST_F(DistributedDBInterfacesImportAndExportTest, CheckSecurityLabel002, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesImportAndExportTest, CheckSecurityLabel002, TestSize.Level1) { std::shared_ptr adapter = std::make_shared(); RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(adapter); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_index_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_index_unit_test.cpp index 1054a2f7e8a10c087515842faa8ebec6cd9a6414..b65a08d6d1bfa6f0b9702e174f325bdaf48c769b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_index_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_index_unit_test.cpp @@ -53,13 +53,13 @@ namespace { string identifierName = DBCommon::TransferStringToHex(hashIdentifierName); string filePath = g_testDir + "/" + identifierName + "/"; if (databaseType == DBConstant::DB_TYPE_LOCAL) { // local - filePath += (DBConstant::LOCAL_SUB_DIR + "/" + DBConstant::LOCAL_DATABASE_NAME + + filePath += (std::string(DBConstant::LOCAL_SUB_DIR) + "/" + DBConstant::LOCAL_DATABASE_NAME + DBConstant::DB_EXTENSION); } else if (databaseType == DBConstant::DB_TYPE_SINGLE_VER) { // single ver - filePath += (DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::MAINDB_DIR + "/" + + filePath += (std::string(DBConstant::SINGLE_SUB_DIR) + "/" + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION); } else if (databaseType == DBConstant::DB_TYPE_MULTI_VER) { // multi ver - filePath += (DBConstant::MULTI_SUB_DIR + "/" + DBConstant::MULTI_VER_DATA_STORE + + filePath += (std::string(DBConstant::MULTI_SUB_DIR) + "/" + DBConstant::MULTI_VER_DATA_STORE + DBConstant::DB_EXTENSION); } else { filePath = ""; @@ -285,7 +285,7 @@ namespace { * @tc.name: CrudIndex001 * @tc.desc: Test whether adding index is normal * @tc.type: FUNC - * @tc.require: AR000DR9K8 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CrudIndex001, TestSize.Level1) @@ -352,7 +352,7 @@ namespace { * @tc.name: CrudIndex002 * @tc.desc: Test whether deleting index is normal * @tc.type: FUNC - * @tc.require: AR000DR9K8 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CrudIndex002, TestSize.Level1) @@ -420,7 +420,7 @@ namespace { * @tc.name: CrudIndex003 * @tc.desc: Test whether updating index is normal * @tc.type: FUNC - * @tc.require: AR000DR9K8 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CrudIndex003, TestSize.Level1) @@ -499,7 +499,7 @@ namespace { * @tc.name: CreateIndex001 * @tc.desc: Test whether the index creation is normal * @tc.type: FUNC - * @tc.require: AR000DR9K9 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CreateIndex001, TestSize.Level1) @@ -569,7 +569,7 @@ namespace { * @tc.name: CreateIndex002 * @tc.desc: Test whether it is possible to insert 32 four-level indexes with each filed being 64. * @tc.type: FUNC - * @tc.require: AR000DR9K9 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CreateIndex002, TestSize.Level1) @@ -618,7 +618,7 @@ namespace { * @tc.name: Check schema skipsize 001 * @tc.desc: When SCHEMA_SKIPSIZE is not defined, check if the default is 0 * @tc.type: FUNC - * @tc.require: AR000DR9K9 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CheckSchemaSkipsize001, TestSize.Level1) @@ -658,7 +658,7 @@ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CheckSchemaSkipsize001, TestSize. * @tc.name: Check schema skipsize 002 * @tc.desc: SCHEMA_SKIPSIZE range is [0,4MB-2] * @tc.type: FUNC - * @tc.require: AR000DR9K9 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CheckSchemaSkipsize002, TestSize.Level1) @@ -740,7 +740,7 @@ namespace { * @tc.desc: When "SCHEMA_SKIPSIZE" is greater than or equal to the size of Value, * the Value verification must fail * @tc.type: FUNC - * @tc.require: AR000DR9K9 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CheckSchemaSkipsize003, TestSize.Level1) @@ -782,7 +782,7 @@ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CheckSchemaSkipsize003, TestSize. * @tc.desc: When the SCHEMA_SKIPSIZE definitions of two Schemas are different, * they will be regarded as inconsistent and incompatible * @tc.type: FUNC - * @tc.require: AR000DR9K9 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, SchemaCompareSkipsize004, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_log_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_log_test.cpp index c64cfb6ca2d1beaa72bc0d2ee6d301b5729d83f0..b07666e671c844d58676420f2317490f478f3000 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_log_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_log_test.cpp @@ -60,7 +60,8 @@ HWTEST_F(DistributedDBInterfacesLogTest, DBFactoryTest001, TestSize.Level1) { DistributedTableMode mode = DistributedTableMode::COLLABORATION; TableSyncType tableSyncType = TableSyncType::DEVICE_COOPERATION; - auto tableManager = LogTableManagerFactory::GetTableManager(mode, tableSyncType); + TableInfo tableInfo; + auto tableManager = LogTableManagerFactory::GetTableManager(tableInfo, mode, tableSyncType); EXPECT_TRUE(tableManager != nullptr); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_extend_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_extend_test.cpp index 4a75ff222d3b01f48872b563f1ecfc3fc157e2a2..1eb88f9166c6e42dc8eb8c996bbdf273843e93dc 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_extend_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_extend_test.cpp @@ -690,7 +690,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, UpdateKey003, TestSize.Lev * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, BlockTimer001, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, BlockTimer001, TestSize.Level1) { /** * @tc.steps:step1. Create database. @@ -932,7 +932,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, SyncRangeQuery001, TestSiz * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, OptionModeValidCheck001, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, OptionModeValidCheck001, TestSize.Level1) { /** * @tc.steps:step1. Get the nb delegate. @@ -1164,23 +1164,9 @@ HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, AbnormalKvStoreTest003, Te EXPECT_EQ(kvStoreObj.GetCompensatedSyncQuery(syncQuery, users, true), E_OK); /** - * @tc.steps: step2. Call interfaces when class para is null. + * @tc.steps: step2. Get and set Schema with different para when class para is null. * @tc.expected: step2. return failInfo. */ - DataInfoWithLog log; - EXPECT_EQ(kvStoreObj.GetInfoByPrimaryKeyOrGid(tableName, vBucket, log, vBucket), -E_INTERNAL_ERROR); - DownloadData downloadData; - EXPECT_EQ(kvStoreObj.PutCloudSyncData(tableName, downloadData), -E_INTERNAL_ERROR); - Timestamp timestamp = 0; - int64_t count = 0; - EXPECT_EQ(kvStoreObj.GetUploadCount(query, timestamp, true, true, count), -E_INTERNAL_ERROR); - std::vector timestampVec; - EXPECT_EQ(kvStoreObj.GetAllUploadCount(query, timestampVec, true, true, count), -E_INTERNAL_ERROR); - - /** - * @tc.steps: step3. Get and set Schema with different para when class para is null. - * @tc.expected: step3. return failInfo. - */ TableSchema tableSchema; EXPECT_EQ(kvStoreObj.GetCloudTableSchema(tableName, tableSchema), -E_NOT_FOUND); CloudSyncData cloudDataResult; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_local_batch_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_local_batch_test.cpp index 9eb5ac603d83a61e19a83887b1399f4209a99c7d..ff1baa1ed80cbe99393a572185147ffbfe900709 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_local_batch_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_local_batch_test.cpp @@ -129,7 +129,7 @@ void DistributedDBInterfacesNBDelegateLocalBatchTest::TearDown(void) * @tc.name: PutLocalBatch001 * @tc.desc: This test case use to verify the PutLocalBatch interface function * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, PutLocalBatch001, TestSize.Level1) @@ -217,7 +217,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, PutLocalBatch002, Test * @tc.name: SingleVerPutLocalBatch001 * @tc.desc: Check for illegal parameters * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch001, TestSize.Level1) @@ -259,7 +259,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch * @tc.name: SingleVerPutLocalBatch002 * @tc.desc: PutLocalBatch normal insert function test. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch002, TestSize.Level1) @@ -324,7 +324,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch * @tc.name: SingleVerPutLocalBatch003 * @tc.desc: Check interface atomicity * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch003, TestSize.Level1) @@ -398,7 +398,7 @@ static void PreparePutLocalBatch004(vector &entrys1, vector &entry * @tc.name: SingleVerPutLocalBatch004 * @tc.desc: Check interface data insertion and update functions. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch004, TestSize.Level1) @@ -671,7 +671,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch * @tc.name: SingleVerDeleteLocalBatch001 * @tc.desc: Check for illegal parameters. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerDeleteLocalBatch001, TestSize.Level1) @@ -770,7 +770,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerDeleteLocalBa * @tc.name: SingleVerDeleteLocalBatch002 * @tc.desc: Check normal delete batch ability. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerDeleteLocalBatch002, TestSize.Level1) @@ -988,7 +988,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerDeleteLocalBa * @tc.name: SingleVerPutLocalBatchObserver001 * @tc.desc: Test the observer function of PutLocalBatch() interface. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatchObserver001, TestSize.Level1) @@ -1055,7 +1055,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch * @tc.name: SingleVerPutLocalBatchObserver002 * @tc.desc: Test the observer function of PutLocalBatch() for invalid input. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatchObserver002, TestSize.Level4) @@ -1131,7 +1131,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch * @tc.name: SingleVerPutLocalBatchObserver003 * @tc.desc: Test the observer function of PutLocalBatch() update function. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatchObserver003, TestSize.Level1) @@ -1199,7 +1199,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch * @tc.name: SingleVerPutLocalBatchObserver004 * @tc.desc: Test the observer function of PutLocalBatch(), same keys handle. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatchObserver004, TestSize.Level1) @@ -1275,7 +1275,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch * @tc.name: SingleVerDeleteLocalBatchObserver001 * @tc.desc: Test the observer function of DeleteLocalBatch() interface. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerDeleteLocalBatchObserver001, TestSize.Level1) @@ -1337,7 +1337,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerDeleteLocalBa * @tc.name: LocalDataBatchNotCheckSchema001 * @tc.desc: Local data does not check schema. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, LocalDataBatchNotCheckSchema001, TestSize.Level1) @@ -1410,7 +1410,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, LocalDataBatchNotCheck * @tc.name: LocalDataBatchNotCheckReadOnly001 * @tc.desc: Local data does not check readOnly. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, LocalDataBatchNotCheckReadOnly001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_schema_put_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_schema_put_test.cpp index 06b91ce12e1a6da71433fcfe0c016184f0ee0faa..1e1269011cd35881d387ff2511e4a851124db392 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_schema_put_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_schema_put_test.cpp @@ -203,7 +203,7 @@ void DistributedDBInterfacesNBDelegateSchemaPutTest::TearDown(void) * @tc.name: PutValueStrictSchemaCheck001 * @tc.desc: Check the value in the strict schema mode. * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, PutValueStrictSchemaCheck001, TestSize.Level1) @@ -246,7 +246,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, PutValueStrictSchemaChe * @tc.name: PutValueReadOnlyCheck001 * @tc.desc: Test writing the data into the no-schema kvStore which has schema originally. * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, PutValueCompaSchemaCheck001, TestSize.Level1) @@ -285,7 +285,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, PutValueCompaSchemaChec * @tc.name: PutValueReadOnlyCheck001 * @tc.desc: Test writing the data into the no-schema kvStore which has schema originally. * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, PutValueReadOnlyCheck001, TestSize.Level1) @@ -321,7 +321,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, PutValueReadOnlyCheck00 * @tc.name: QueryDeleted001 * @tc.desc: Test the query in the deleted scene. * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, QueryDeleted001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp index eec05b15a17439c2ff92e48c0466d97367506e0b..c49d39f8416ca752c5cf00f8a3e8e0705b2a0e0f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp @@ -260,7 +260,7 @@ void DistributedDBInterfacesNBDelegateTest::TearDown(void) * @tc.name: CombineTest001 * @tc.desc: Test the NbDelegate for combined operation. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest001, TestSize.Level1) @@ -367,7 +367,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest001, TestSize.Level1) * @tc.name: CombineTest002 * @tc.desc: Test the NbDelegate for combined operation, try to use GAUSSDB_RD. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhujinlin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest002, TestSize.Level1) @@ -381,7 +381,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest002, TestSize.Level1) g_mgr.GetKvStore("distributed_nb_delegate_test_rd", option, g_kvNbDelegateCallback); ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); EXPECT_TRUE(g_kvDelegateStatus == OK); - std::string keyStr("acd"); + std::string keyStr("key"); Key key(keyStr.begin(), keyStr.end()); std::string valueStr("acd"); Value value(valueStr.begin(), valueStr.end()); @@ -426,7 +426,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest002, TestSize.Level1) * @tc.name: CombineTest003 * @tc.desc: Test the NbDelegate for combined operation, try to use GAUSSDB_RD and index type with hash. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhujinlin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest003, TestSize.Level1) @@ -486,7 +486,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest003, TestSize.Level1) * @tc.name: CreateMemoryDb001 * @tc.desc: Create memory database after. * @tc.type: FUNC - * @tc.require: AR000CRAKN + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDb001, TestSize.Level1) @@ -529,7 +529,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDb001, TestSize.Leve * @tc.name: CreateMemoryDb002 * @tc.desc: The MemoryDB cannot be created or open, when the physical database has been opened * @tc.type: FUNC - * @tc.require: AR000CRAKN + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDb002, TestSize.Level1) @@ -562,7 +562,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDb002, TestSize.Leve * @tc.name: CreateMemoryDb003 * @tc.desc: The physical database cannot be created or open, when the MemoryDB has been opened. * @tc.type: FUNC - * @tc.require: AR000CRAKN + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDb003, TestSize.Level1) @@ -593,7 +593,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDb003, TestSize.Leve * @tc.name: OperMemoryDbData001 * @tc.desc: Operate memory database * @tc.type: FUNC - * @tc.require: AR000CRAKN + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, OperMemoryDbData001, TestSize.Level1) @@ -654,7 +654,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, OperMemoryDbData001, TestSize.Le * @tc.name: CloseMemoryDb001 * @tc.desc: Operate memory database after reopen memory database * @tc.type: FUNC - * @tc.require: AR000CRAKN + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CloseMemoryDb001, TestSize.Level1) @@ -705,7 +705,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CloseMemoryDb001, TestSize.Level * @tc.name: ResultSetTest001 * @tc.desc: Test the NbDelegate for result set function. * @tc.type: FUNC - * @tc.require: AR000D08KT + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, ResultSetTest001, TestSize.Level1) @@ -793,7 +793,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, ResultSetTest001, TestSize.Level * @tc.name: PutBatchVerify001 * @tc.desc: This test case use to verify the putBatch interface function * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, PutBatchVerify001, TestSize.Level1) @@ -885,7 +885,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, PutBatchVerify002, TestSize.Leve * @tc.name: SingleVerPutBatch001 * @tc.desc: Check for illegal parameters * @tc.type: FUNC - * @tc.require: AR000DPTQ8 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatch001, TestSize.Level1) @@ -927,7 +927,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatch001, TestSize.L * @tc.name: SingleVerPutBatch002 * @tc.desc: PutBatch normal insert function test. * @tc.type: FUNC - * @tc.require: AR000DPTQ8 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatch002, TestSize.Level1) @@ -992,7 +992,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatch002, TestSize.L * @tc.name: SingleVerPutBatch003 * @tc.desc: Check interface atomicity * @tc.type: FUNC - * @tc.require: AR000DPTQ8 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatch003, TestSize.Level1) @@ -1066,7 +1066,7 @@ static void PreparePutBatch004(vector &entrys1, vector &entrys2, v * @tc.name: SingleVerPutBatch004 * @tc.desc: Check interface data insertion and update functions. * @tc.type: FUNC - * @tc.require: AR000DPTQ8 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatch004, TestSize.Level1) @@ -1435,7 +1435,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatch009, TestSize.L * @tc.name: SingleVerDeleteBatch001 * @tc.desc: Check for illegal parameters. * @tc.type: FUNC - * @tc.require: AR000DPTQ8 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerDeleteBatch001, TestSize.Level1) @@ -1537,7 +1537,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerDeleteBatch001, TestSiz * @tc.name: SingleVerDeleteBatch002 * @tc.desc: Check normal delete batch ability. * @tc.type: FUNC - * @tc.require: AR000DPTQ8 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerDeleteBatch002, TestSize.Level1) @@ -1793,7 +1793,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerDeleteBatch007, TestSiz * @tc.name: SingleVerPutBatchObserver001 * @tc.desc: Test the observer function of PutBatch() interface. * @tc.type: FUNC - * @tc.require: AR000DPTTA + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatchObserver001, TestSize.Level1) @@ -1861,7 +1861,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatchObserver001, Te * @tc.name: SingleVerPutBatchObserver002 * @tc.desc: Test the observer function of PutBatch() for invalid input. * @tc.type: FUNC - * @tc.require: AR000DPTTA + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatchObserver002, TestSize.Level4) @@ -1936,7 +1936,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatchObserver002, Te * @tc.name: SingleVerPutBatchObserver003 * @tc.desc: Test the observer function of PutBatch() update function. * @tc.type: FUNC - * @tc.require: AR000DPTTA + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatchObserver003, TestSize.Level1) @@ -2003,7 +2003,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatchObserver003, Te * @tc.name: SingleVerPutBatchObserver004 * @tc.desc: Test the observer function of PutBatch(), same keys handle. * @tc.type: FUNC - * @tc.require: AR000DPTTA + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatchObserver004, TestSize.Level1) @@ -2078,7 +2078,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatchObserver004, Te * @tc.name: SingleVerDeleteBatchObserver001 * @tc.desc: Test the observer function of DeleteBatch() interface. * @tc.type: FUNC - * @tc.require: AR000DPTTA + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerDeleteBatchObserver001, TestSize.Level1) @@ -2139,7 +2139,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerDeleteBatchObserver001, * @tc.name: SingleVerConcurrentPut001 * @tc.desc: Test put the data concurrently, and check the timestamp. * @tc.type: FUNC - * @tc.require: AR000DPTTA + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerConcurrentPut001, TestSize.Level4) @@ -2185,7 +2185,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerConcurrentPut001, TestS * @tc.name: SingleVerGetLocalEntries001 * @tc.desc: Test GetLocalEntries interface for the single ver database. * @tc.type: FUNC - * @tc.require: AR000DPTTA + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerGetLocalEntries001, TestSize.Level1) @@ -2274,7 +2274,7 @@ static vector PreDataForQueryByPreFixKey() * @tc.name: QueryPreFixKey002 * @tc.desc: The query method without filtering the field can query non-schma databases * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, QueryPreFixKey002, TestSize.Level1) @@ -2325,7 +2325,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, QueryPreFixKey002, TestSize.Leve * @tc.name: SingleVerGetSecurityOption001 * @tc.desc: Test GetSecurityOption interface for the single ver database. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: * @tc.author: liuwenkai */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerGetSecurityOption001, TestSize.Level1) @@ -2373,7 +2373,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerGetSecurityOption001, T * @tc.name: SingleVerGetSecurityOption002 * @tc.desc: Test GetSecurityOption interface for the single ver database. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: * @tc.author: liuwenkai */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerGetSecurityOption002, TestSize.Level1) @@ -2601,7 +2601,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, MaxLogCheckPoint001, TestSize.Le * @tc.name: CreateMemoryDbWithoutPath * @tc.desc: Create memory database without path. * @tc.type: FUNC - * @tc.require: AR000CRAKN + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDbWithoutPath, TestSize.Level1) @@ -2623,7 +2623,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDbWithoutPath, TestS * @tc.name: OpenStorePathCheckTest001 * @tc.desc: Test open store with same label but different path. * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, OpenStorePathCheckTest001, TestSize.Level1) @@ -2674,7 +2674,7 @@ std::string GetRealFileUrl(const std::string &dbPath, const std::string &appId, * @tc.name: BusyTest001 * @tc.desc: Test put kv data while another thread holds the transaction for one second * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, BusyTest001, TestSize.Level1) @@ -2842,4 +2842,164 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, RemoveDeviceDataTest001, TestSiz FreeVirtualDevice(g_deviceC); FreeVirtualDevice(g_deviceD); } + +/** + * @tc.name: RekeyTest001 + * @tc.desc: Test rekey with multi db handles. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonnghuang + */ +HWTEST_F(DistributedDBInterfacesNBDelegateTest, RekeyTest001, TestSize.Level1) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + CipherPassword passwd; + const std::vector PASSWD_VECTOR_1 = {'P', 'a', 's', 's', 'w', 'o', 'r', 'd', '@', '1', '2', '3'}; + const std::vector PASSWD_VECTOR_2 = {'P', 'a', 's', 's', 'w', 'o', 'r', 'd', '@', '0', '0', '0'}; + const std::vector PASSWD_VECTOR_3 = {'P', 'a', 's', 's', 'w', 'o', 'r', 'd', '@', '0', '0', '1'}; + KvStoreNbDelegate::Option option = {true, false, true}; + (void)passwd.SetValue(PASSWD_VECTOR_1.data(), PASSWD_VECTOR_1.size()); + option.passwd = passwd; + g_mgr.SetKvStoreConfig(g_config); + g_mgr.GetKvStore("rekeyTest001", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + KvStoreNbDelegate *kvNbDelegatePtr001 = g_kvNbDelegatePtr; + + /** + * @tc.steps:step2. Rekey. + * @tc.expected: step2. Returns OK. + */ + (void)passwd.SetValue(PASSWD_VECTOR_2.data(), PASSWD_VECTOR_2.size()); + kvNbDelegatePtr001->Rekey(passwd); + + /** + * @tc.steps:step3. Open DB and rekey. + * @tc.expected: step3. Returns not OK. + */ + sqlite3 *db = nullptr; + int flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + const auto &dbPath = g_testDir + + "/cf479925e0691d2df83f095db294ee671a7a8f38e7527fef0dd1b40f8e3cb476/single_ver/main/gen_natural_store.db"; + int rc = sqlite3_open_v2(dbPath.c_str(), &db, flag, nullptr); + EXPECT_TRUE(rc == SQLITE_OK); + (void)passwd.SetValue(PASSWD_VECTOR_3.data(), PASSWD_VECTOR_3.size()); + EXPECT_FALSE(kvNbDelegatePtr001->Rekey(passwd) == OK); + g_mgr.CloseKvStore(kvNbDelegatePtr001); + sqlite3_close(db); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: RekeyTest002 + * @tc.desc: Test normal rekey. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBInterfacesNBDelegateTest, RekeyTest002, TestSize.Level0) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + CipherPassword passwd; + const std::vector PASSWD_VECTOR = {'P', 'a', 's', 's', 'w', 'o', 'r', 'd', '@', '1', '2', '3'}; + KvStoreNbDelegate::Option option = {true, false, true}; + (void)passwd.SetValue(PASSWD_VECTOR.data(), PASSWD_VECTOR.size()); + option.passwd = passwd; + g_mgr.SetKvStoreConfig(g_config); + g_mgr.GetKvStore("rekeyTest002", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps:step2. Rekey. + * @tc.expected: step2. Returns OK. + */ + const std::vector NEW_PASSWD_VECTOR = {'P', 'a', 's', 's', 'w', 'o', 'r', 'd', '@', '1', '1', '1'}; + (void)passwd.SetValue(NEW_PASSWD_VECTOR.data(), NEW_PASSWD_VECTOR.size()); + EXPECT_TRUE(g_kvNbDelegatePtr->Rekey(passwd) == OK); + g_mgr.CloseKvStore(g_kvNbDelegatePtr); + g_kvNbDelegatePtr = nullptr; + option.passwd = passwd; + g_mgr.GetKvStore("rekeyTest002", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + g_mgr.CloseKvStore(g_kvNbDelegatePtr); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: SetAndGetHandleTest001 + * @tc.desc: Test SetHandle and GetHandle. + * @tc.type: FUNC + * @tc.require: + * @tc.author: lideshi + */ +HWTEST_F(DistributedDBInterfacesNBDelegateTest, SetAndGetHandleTest001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + KvStoreNbDelegate::Option option = {true, false, false}; + option.storageEngineType = GAUSSDB_RD; + g_mgr.GetKvStore("distributed_nb_delegate_test_rd", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + auto kvStoreImpl = static_cast(g_kvNbDelegatePtr); + void *handle = DBCommon::LoadGrdLib(); + kvStoreImpl->SetHandle(handle); + DBCommon::UnLoadGrdLib(nullptr); + DBCommon::UnLoadGrdLib(handle); + handle = nullptr; + /** + * @tc.steps:step2. Close the kv store. + * @tc.expected: step2. Results OK and delete successfully. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_nb_delegate_test_rd"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: SetAndGetHandleTest002 + * @tc.desc: Test multi get delegate. + * @tc.type: FUNC + * @tc.require: + * @tc.author: lideshi + */ +HWTEST_F(DistributedDBInterfacesNBDelegateTest, SetAndGetHandleTest002, TestSize.Level0) +{ + const std::string dbName = "storeId"; + + KvStoreNbDelegate::Option option = {true, false, false}; + option.storageEngineType = GAUSSDB_RD; + static int openCount = 2; // test open count 2 + + std::vector delegates; + KvStoreDelegateManager g_mgrTest("app1", "user1"); + g_mgrTest.SetKvStoreConfig(g_config); + for (int i = 0; i < openCount; i++) { + KvStoreNbDelegate *delegate = nullptr; + DBStatus kvDelegateStatus = INVALID_ARGS; + auto callback1 = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback, placeholders::_1, + placeholders::_2, std::ref(kvDelegateStatus), std::ref(delegate)); + g_mgrTest.GetKvStore(dbName + std::to_string(i), option, callback1); + ASSERT_TRUE(delegate != nullptr); + EXPECT_TRUE(kvDelegateStatus == OK); + delegates.push_back(delegate); + } + + for (int i = 0; i < openCount; i++) { + EXPECT_EQ(g_mgrTest.CloseKvStore(delegates[i]), OK); + EXPECT_EQ(g_mgrTest.DeleteKvStore(dbName + std::to_string(i)), OK); + delegates[i] = nullptr; + } +} } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_publish_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_publish_test.cpp index 46fff6d32fa5715a9192cd5cf6e3ffd78c024677..f0e9bcfd514c9217ce7ce727d65bdd5c3892cd62 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_publish_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_publish_test.cpp @@ -120,7 +120,7 @@ void DistributedDBInterfacesNBPublishTest::TearDown(void) {} * @tc.name: SingleVerPublishKey001 * @tc.desc: Publish nonexistent key * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey001, TestSize.Level1) @@ -207,7 +207,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey001, TestSize. * @tc.name: SingleVerPublishKey002 * @tc.desc: Publish no conflict key without deleting key from local table * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey002, TestSize.Level1) @@ -284,7 +284,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey002, TestSize. * @tc.name: SingleVerPublishKey003 * @tc.desc: Publish no conflict key with deleting key from local table * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey003, TestSize.Level1) @@ -360,7 +360,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey003, TestSize. * @tc.name: SingleVerPublishKey004 * @tc.desc: Publish conflict key and update timestamp * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey004, TestSize.Level1) @@ -438,7 +438,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey004, TestSize. * @tc.name: SingleVerPublishKey005 * @tc.desc: Publish conflict key but do not update timestamp * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey005, TestSize.Level1) @@ -515,7 +515,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey005, TestSize. * @tc.name: SingleVerPublishKey006 * @tc.desc: Publish no conflict key and onConflict() not null * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey006, TestSize.Level1) @@ -556,7 +556,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey006, TestSize. * @tc.name: SingleVerPublishKey007 * @tc.desc: Publish conflict key and onConflict() not null * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey007, TestSize.Level1) @@ -604,7 +604,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey007, TestSize. * @tc.name: SingleVerPublishKey008 * @tc.desc: Publish conflict key and onConflict() not null, need update timestamp * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey008, TestSize.Level1) @@ -652,7 +652,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey008, TestSize. * @tc.name: SingleVerPublishKey009 * @tc.desc: Publish conflict key (deleted) and onConflict() not null * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey009, TestSize.Level1) @@ -699,7 +699,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey009, TestSize. * @tc.name: SingleVerPublishKey010 * @tc.desc: Publish conflict key (deleted) and onConflict() not null, need update timestamp * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey010, TestSize.Level1) @@ -746,7 +746,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey010, TestSize. * @tc.name: SingleVerPublishKey011 * @tc.desc: Publish conflict key (deleted) and onConflict() not null, put(k1,v1) in callback method * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey011, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_transaction_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_transaction_test.cpp index 0df4a6c9c740598ae21eb9bd05add11394fb6bf9..44427f4a88a989d7a629dc53e6c7275b3ee78378 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_transaction_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_transaction_test.cpp @@ -157,7 +157,7 @@ void DistributedDBInterfacesNBTransactionTest::TearDown(void) {} * @tc.name: start001 * @tc.desc: Test the nb transaction start twice. * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, start001, TestSize.Level1) @@ -189,7 +189,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, start001, TestSize.Level1) * @tc.name: start002 * @tc.desc: Test the nb transaction begin and end not match. * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, start002, TestSize.Level1) @@ -239,7 +239,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, start002, TestSize.Level1) * @tc.name: start003 * @tc.desc: Test the nb transaction rollback automatically when db close. * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, start003, TestSize.Level1) @@ -291,7 +291,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, start003, TestSize.Level1) * @tc.name: start004 * @tc.desc: Test the nb operations return BUSY after transaction started. * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, start004, TestSize.Level4) @@ -345,7 +345,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, start004, TestSize.Level4) * @tc.name: commit001 * @tc.desc: Test the nb transaction commit without start. * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit001, TestSize.Level1) @@ -370,7 +370,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit001, TestSize.Level1) * @tc.name: commit002 * @tc.desc: Test the nb transaction commit twice. * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit002, TestSize.Level1) @@ -425,7 +425,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit002, TestSize.Level1) * @tc.name: commit003 * @tc.desc: Test the entry size exceed the maximum limit in one transaction * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit003, TestSize.Level1) @@ -498,7 +498,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit003, TestSize.Level1) * @tc.name: commit004 * @tc.desc: Test the nb normal operations in one transaction * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit004, TestSize.Level1) @@ -584,7 +584,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit004, TestSize.Level1) * @tc.name: commit005 * @tc.desc: Test the conflict data report normally in one transaction * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit005, TestSize.Level1) @@ -651,7 +651,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit005, TestSize.Level1) * @tc.name: commit006 * @tc.desc: Test the conflict data report and observer function both be normal in one transaction * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit006, TestSize.Level1) @@ -725,7 +725,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit006, TestSize.Level1) * @tc.name: rollback001 * @tc.desc: Test the transaction rollback without start. * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback001, TestSize.Level1) @@ -750,7 +750,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback001, TestSize.Level1) * @tc.name: rollback002 * @tc.desc: Test the transaction rollback twice * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback002, TestSize.Level1) @@ -785,7 +785,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback002, TestSize.Level1) * @tc.name: rollback003 * @tc.desc: Test the Put operation rollback * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback003, TestSize.Level1) @@ -833,7 +833,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback003, TestSize.Level1) * @tc.name: rollback004 * @tc.desc: Test the PutBatch operation rollback * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback004, TestSize.Level1) @@ -885,7 +885,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback004, TestSize.Level1) * @tc.name: rollback005 * @tc.desc: Test the modify operation rollback * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback005, TestSize.Level1) @@ -933,7 +933,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback005, TestSize.Level1) * @tc.name: rollback006 * @tc.desc: Test the Delete operation rollback * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback006, TestSize.Level1) @@ -981,7 +981,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback006, TestSize.Level1) * @tc.name: rollback007 * @tc.desc: Test the DeleteBatch operation rollback * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback007, TestSize.Level1) @@ -1030,7 +1030,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback007, TestSize.Level1) * @tc.name: rollback008 * @tc.desc: Test the multiple operations rollback * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback008, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_unpublish_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_unpublish_test.cpp index 5958850d9377d7ec816783e8af90876d4888624c..012539dd08659c66bfc3295ba2d86542631d564b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_unpublish_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_unpublish_test.cpp @@ -137,7 +137,7 @@ void DistributedDBInterfacesNBUnpublishTest::TearDown(void) * @tc.name: CombineTest001 * @tc.desc: Test unpublish one nonexistent data. * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey001, TestSize.Level1) @@ -202,7 +202,7 @@ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey001, TestS * @tc.name: SingleVerUnPublishKey002 * @tc.desc: Test unpublish existent data(no conflict with the local data). * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey002, TestSize.Level1) @@ -279,7 +279,7 @@ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey002, TestS * @tc.name: SingleVerUnPublishKey003 * @tc.desc: Test unpublish one existent data(conflict with the local data). * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey003, TestSize.Level1) @@ -360,7 +360,7 @@ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey003, TestS * @tc.name: SingleVerUnPublishKey004 * @tc.desc: Test unpublish one deleted data(no conflict with the local data). * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey004, TestSize.Level1) @@ -399,7 +399,7 @@ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey004, TestS * @tc.name: SingleVerUnPublishKey005 * @tc.desc: Test unpublish one existent data(conflict with the local data). * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey005, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_query_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_query_test.cpp index 6935d67253942d06caf1170a889baf95786df7e0..23daa5db5ccbec17b23f49ee1fd165d92f72d174 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_query_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_query_test.cpp @@ -138,7 +138,7 @@ void DistributedDBInterfacesQueryTest::TearDown(void) * @tc.name: Query001 * @tc.desc: Check the legal single query operation to see if the generated container is correct * @tc.type: FUNC - * @tc.require: AR000DR9K6 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesQueryTest, Query001, TestSize.Level1) @@ -193,7 +193,7 @@ HWTEST_F(DistributedDBInterfacesQueryTest, Query001, TestSize.Level1) * @tc.name: Query002 * @tc.desc: Check for illegal query conditions * @tc.type: FUNC - * @tc.require: AR000DR9K6 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesQueryTest, Query002, TestSize.Level1) @@ -211,7 +211,7 @@ HWTEST_F(DistributedDBInterfacesQueryTest, Query002, TestSize.Level1) * @tc.name: Query003 * @tc.desc: Check combination condition * @tc.type: FUNC - * @tc.require: AR000DR9K6 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesQueryTest, Query003, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_register_syncdb_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_register_syncdb_test.cpp index 37d8010826cc12249062b9b0d35df247e16ee8ba..3c1e61c24e74a69532a3b9d046b667894337450d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_register_syncdb_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_register_syncdb_test.cpp @@ -178,7 +178,7 @@ void DistributedDBInterfacesRegisterSyncDBTest::TearDown(void) * @tc.name: RegisterObserver001 * @tc.desc: normal register observer success. * @tc.type: FUNC - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver001, TestSize.Level1) @@ -190,7 +190,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver001, TestSiz * @tc.name: RegisterObserver002 * @tc.desc: register(null object) observer success * @tc.type: FUNC - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver002, TestSize.Level1) @@ -202,7 +202,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver002, TestSiz * @tc.name: RegisterObserver003 * @tc.desc: Test the new data and check the processing result of the callback function. * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver003, TestSize.Level1) @@ -238,7 +238,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver003, TestSiz * @tc.name: RegisterObserver004 * @tc.desc: register observer success and putbach callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver004, TestSize.Level1) @@ -279,7 +279,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver004, TestSiz * @tc.name: RegisterObserver005 * @tc.desc: register observer success and putbach callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver005, TestSize.Level1) @@ -328,7 +328,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver005, TestSiz * @tc.name: RegisterObserver006 * @tc.desc: register observer success and update callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver006, TestSize.Level1) @@ -370,7 +370,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver006, TestSiz * @tc.name: RegisterObserver007 * @tc.desc: register observer success and delete callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver007, TestSize.Level1) @@ -410,7 +410,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver007, TestSiz * @tc.name: RegisterObserver008 * @tc.desc: register observer success and delete callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver008, TestSize.Level1) @@ -445,7 +445,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver008, TestSiz * @tc.name: RegisterObserver009 * @tc.desc: register observer success and deletebatch callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver009, TestSize.Level1) @@ -490,7 +490,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver009, TestSiz * @tc.name: RegisterObserver010 * @tc.desc: register observer success and delete callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver010, TestSize.Level1) @@ -539,7 +539,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver010, TestSiz * @tc.name: RegisterObserver011 * @tc.desc: register observer success and DeleteBatch callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver011, TestSize.Level1) @@ -578,7 +578,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver011, TestSiz * @tc.name: RegisterObserver012 * @tc.desc: register observer success and clear callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver012, TestSize.Level1) @@ -623,7 +623,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver012, TestSiz * @tc.name: RegisterObserver013 * @tc.desc: register observer success and clear callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver013, TestSize.Level1) @@ -656,7 +656,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver013, TestSiz * @tc.desc: Test the function of modifying a record, adding a record, * deleting a record, and checking the processing result of the callback function. * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver014, TestSize.Level1) @@ -781,7 +781,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver014, TestSiz /** * @tc.name: SnapshotRegisterObserver001 * @tc.desc: register a normal observer for snapshot - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver001, TestSize.Level1) @@ -799,7 +799,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver001, /** * @tc.name: SnapshotRegisterObserver002 * @tc.desc: register a null observer for snapshot register a null observer for snapshot - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver002, TestSize.Level1) @@ -817,7 +817,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver002, /** * @tc.name: SnapshotRegisterObserver003 * @tc.desc: register observer success and put callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver003, TestSize.Level1) @@ -863,7 +863,7 @@ static void CreatEntrysData(size_t size, uint8_t value, vector &entries) /** * @tc.name: SnapshotRegisterObserver004 * @tc.desc: register observer success and putBatch callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver004, TestSize.Level1) @@ -898,7 +898,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver004, /** * @tc.name: SnapshotRegisterObserver005 * @tc.desc: register observer success and putBatch callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver005, TestSize.Level1) @@ -940,7 +940,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver005, /** * @tc.name: SnapshotRegisterObserver006 * @tc.desc: register observer success and update callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver006, TestSize.Level1) @@ -982,7 +982,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver006, /** * @tc.name: SnapshotRegisterObserver007 * @tc.desc: register observer success and Delete callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver007, TestSize.Level1) @@ -1020,7 +1020,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver007, /** * @tc.name: SnapshotRegisterObserver008 * @tc.desc: register observer success and Delete null value callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver008, TestSize.Level1) @@ -1054,7 +1054,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver008, /** * @tc.name: SnapshotRegisterObserver009 * @tc.desc: register observer success and DeleteBatch callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver009, TestSize.Level1) @@ -1097,7 +1097,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver009, /** * @tc.name: SnapshotRegisterObserver010 * @tc.desc: register observer success and DeleteBatch callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver010, TestSize.Level1) @@ -1150,7 +1150,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver010, /** * @tc.name: SnapshotRegisterObserver011 * @tc.desc: register observer success and DeleteBatch callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver011, TestSize.Level1) @@ -1190,7 +1190,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver011, /** * @tc.name: SnapshotRegisterObserver012 * @tc.desc: register observer success and Clear callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver012, TestSize.Level1) @@ -1232,7 +1232,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver012, /** * @tc.name: SnapshotRegisterObserver013 * @tc.desc: register observer success and Clear callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver013, TestSize.Level1) @@ -1263,7 +1263,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver013, /** * @tc.name: SnapshotRegisterObserver014 * @tc.desc: register observer success and operate callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver014, TestSize.Level1) @@ -1388,7 +1388,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver014, /** * @tc.name: UnRegisterObserver001 * @tc.desc: Unregister a normal observer - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, UnRegisterObserver001, TestSize.Level1) @@ -1409,7 +1409,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, UnRegisterObserver001, TestS /** * @tc.name: UnRegisterObserver002 * @tc.desc: Unregister a null observer - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, UnRegisterObserver002, TestSize.Level1) @@ -1424,7 +1424,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, UnRegisterObserver002, TestS /** * @tc.name: UnRegisterObserver003 * @tc.desc: Unregister a unregister observer - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, UnRegisterObserver003, TestSize.Level1) @@ -1439,7 +1439,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, UnRegisterObserver003, TestS /** * @tc.name: UnRegisterObserver004 * @tc.desc: Unregister a and check callback - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, UnRegisterObserver004, TestSize.Level1) @@ -1588,7 +1588,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, UnRegisterObserver004, TestS /** * @tc.name: SnapshotUnRegisterObserver001 * @tc.desc: Unregister a snapshot observer - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotUnRegisterObserver001, TestSize.Level1) @@ -1606,7 +1606,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotUnRegisterObserver00 /** * @tc.name: SnapshotUnRegisterObserver002 * @tc.desc: Unregister a null snapshot observer - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotUnRegisterObserver002, TestSize.Level1) @@ -1623,7 +1623,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotUnRegisterObserver00 /** * @tc.name: SnapshotUnRegisterObserver003 * @tc.desc: Unregister a unregister snapshot observer - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotUnRegisterObserver003, TestSize.Level1) @@ -1682,7 +1682,7 @@ static void SnapshotUnRegisterObserver004Inner() /** * @tc.name: SnapshotUnRegisterObserver004 * @tc.desc: Check a unregister snapshot observer - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotUnRegisterObserver004, TestSize.Level1) @@ -1817,7 +1817,7 @@ static void CheckObserverCallback(const Entry &entryB) * @tc.desc: Test whether the data change notification can obtain these changes * when the database is added, deleted, or modified. * @tc.type: FUNC - * @tc.require: AR000BVDFR AR000CQDVK + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, GetObserverData001, TestSize.Level1) @@ -1848,7 +1848,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, GetObserverData001, TestSize * when the value of observer is not empty * when a snapshot is obtained and the database data changes. * @tc.type: FUNC - * @tc.require: AR000C06UT AR000CQDTG + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, GetSnapshotObserverData001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp index c72e1205b276ef84b2d3cae2afea4c2835ad41a7..c89e04dbb7abd7c5d280d51157316c042bbaf2e0 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp @@ -243,7 +243,7 @@ void NoramlCreateDistributedTableTest(TableSyncType tableSyncType) * @tc.name: RelationalStoreTest001 * @tc.desc: Test open store and create distributed db with DEVICE_COOPERATION type * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest001, TestSize.Level1) @@ -255,7 +255,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest001, TestSize * @tc.name: RelationalStoreTest001 * @tc.desc: Test open store and create distributed db with CLOUD_COOPERATION type * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest001_1, TestSize.Level1) @@ -267,7 +267,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest001_1, TestSi * @tc.name: RelationalStoreTest002 * @tc.desc: Test open store with invalid path or store ID * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest002, TestSize.Level1) @@ -319,7 +319,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest002, TestSize * @tc.name: RelationalStoreTest003 * @tc.desc: Test open store with journal_mode is not WAL * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest003, TestSize.Level1) @@ -392,7 +392,7 @@ void CreateDistributedTableOverLimitTest(TableSyncType tableSyncTpe) * @tc.name: RelationalStoreTest004 * @tc.desc: Test create distributed table with over limit for DEVICE_COOPERATION type * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest004, TestSize.Level1) @@ -436,7 +436,8 @@ void CreateDistributedTableInvalidArgsTest(TableSyncType tableSyncType) * @tc.steps:step3. Create distributed table with invalid table name * @tc.expected: step3. Create distributed table failed. */ - EXPECT_NE(delegate->CreateDistributedTable(DBConstant::SYSTEM_TABLE_PREFIX + "_tmp", tableSyncType), OK); + EXPECT_NE(delegate->CreateDistributedTable(std::string(DBConstant::SYSTEM_TABLE_PREFIX) + "_tmp", tableSyncType), + OK); EXPECT_EQ(delegate->CreateDistributedTable("Handle-J@^.", tableSyncType), INVALID_ARGS); EXPECT_EQ(delegate->CreateDistributedTable("sync_data", @@ -469,7 +470,7 @@ void CreateDistributedTableInvalidArgsTest(TableSyncType tableSyncType) * @tc.name: RelationalStoreTest005 * @tc.desc: Test create distributed table with invalid table name or invalid table sync type * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest005, TestSize.Level1) @@ -540,7 +541,7 @@ void CreateDistributedTableNonPrimaryKeyTest(TableSyncType tableSyncType) * @tc.name: RelationalStoreTest006 * @tc.desc: Test create distributed table with non primary key schema * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest006, TestSize.Level1) @@ -582,7 +583,7 @@ void CreateDistributedTableInvalidFieldTest(TableSyncType tableSyncType) * @tc.name: RelationalStoreTest007 * @tc.desc: Test create distributed table with table has invalid field name * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest007, TestSize.Level1) @@ -624,7 +625,7 @@ void CreateDistributedTableCompositePKTest(TableSyncType tableSyncType, int expe * @tc.name: RelationalStoreTest008 * @tc.desc: Test create distributed table with table has composite primary keys for DEVICE_COOPERATION * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest008, TestSize.Level1) @@ -667,7 +668,7 @@ void CreateDistributedTableWithHistoryDataTest(TableSyncType tableSyncType) * @tc.name: RelationalStoreTest009 * @tc.desc: Test create distributed table with table has history data for DEVICE_COOPERATION * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest009, TestSize.Level1) @@ -742,11 +743,84 @@ void TableModifyTest(const std::string &modifySql, TableSyncType tableSyncType, EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); } +/** + * @tc.name: RelationalStoreTest010 + * @tc.desc: Test opening libraries with the same name in different paths. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest010, TestSize.Level0) +{ + /** + * @tc.steps:step1. Prepare db file + * @tc.expected: step1. Return OK. + */ + std::string dbPath1 = g_dbDir + "path1/"; + ASSERT_EQ(OS::MakeDBDirectory(dbPath1), E_OK); + sqlite3 *db1 = RelationalTestUtils::CreateDataBase(dbPath1 + STORE_ID + DB_SUFFIX); + ASSERT_NE(db1, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db1, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db1, NORMAL_CREATE_NO_UNIQUE), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db1), SQLITE_OK); + std::string dbPath2 = g_dbDir + "path2/"; + ASSERT_EQ(OS::MakeDBDirectory(dbPath2), E_OK); + sqlite3 *db2 = RelationalTestUtils::CreateDataBase(dbPath2 + STORE_ID + DB_SUFFIX); + ASSERT_NE(db2, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db2, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db2, NORMAL_CREATE_NO_UNIQUE), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db2), SQLITE_OK); + /** + * @tc.steps:step2. open db + * @tc.expected: step2. Return OK. + */ + RelationalStoreDelegate *delegate1 = nullptr; + DBStatus status1 = g_mgr.OpenStore(dbPath1 + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate1); + EXPECT_EQ(status1, OK); + ASSERT_NE(delegate1, nullptr); + RelationalStoreDelegate *delegate2 = nullptr; + DBStatus status2 = g_mgr.OpenStore(dbPath2 + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate2); + EXPECT_EQ(status2, OK); + ASSERT_NE(delegate2, nullptr); + /** + * @tc.steps:step3. create table + * @tc.expected: step3. Return OK. + */ + SqlCondition sqlCondition1; + std::vector records1; + sqlCondition1.sql = "create table if not exists table1(id int);"; + EXPECT_EQ(delegate1->ExecuteSql(sqlCondition1, records1), OK); + SqlCondition sqlCondition2; + std::vector records2; + sqlCondition2.sql = "create table if not exists table2(id int);"; + EXPECT_EQ(delegate2->ExecuteSql(sqlCondition2, records2), OK); + /** + * @tc.steps:step4. check table + * @tc.expected: step4. Return OK. + */ + db1 = RelationalTestUtils::CreateDataBase(dbPath1 + STORE_ID + DB_SUFFIX); + std::string sql1 = "select count(*) from sqlite_master where type = 'table' and name = 'table1'"; + int tableCount1 = 0; + EXPECT_EQ(SQLiteUtils::GetCountBySql(db1, sql1, tableCount1), E_OK); + EXPECT_EQ(tableCount1, 1); + EXPECT_EQ(sqlite3_close_v2(db1), SQLITE_OK); + db2 = RelationalTestUtils::CreateDataBase(dbPath2 + STORE_ID + DB_SUFFIX); + std::string sql2 = "select count(*) from sqlite_master where type = 'table' and name = 'table2'"; + int tableCount2 = 0; + EXPECT_EQ(SQLiteUtils::GetCountBySql(db2, sql2, tableCount2), E_OK); + EXPECT_EQ(tableCount2, 1); + EXPECT_EQ(sqlite3_close_v2(db2), SQLITE_OK); + status1 = g_mgr.CloseStore(delegate1); + EXPECT_EQ(status1, OK); + status2 = g_mgr.CloseStore(delegate2); + EXPECT_EQ(status2, OK); +} + /** * @tc.name: RelationalTableModifyTest001 * @tc.desc: Test modify distributed table with compatible upgrade * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest001, TestSize.Level1) @@ -759,7 +833,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest001, Te * @tc.name: RelationalTableModifyTest002 * @tc.desc: Test modify distributed table with incompatible upgrade * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest002, TestSize.Level1) @@ -772,7 +846,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest002, Te * @tc.name: RelationalTableModifyTest003 * @tc.desc: Test modify distributed table with incompatible upgrade * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest003, TestSize.Level1) @@ -885,7 +959,7 @@ void UpgradeDistributedTableTest(TableSyncType tableSyncType) * @tc.name: RelationalTableModifyTest004 * @tc.desc: Test upgrade distributed table with device table exists * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest004, TestSize.Level1) @@ -909,7 +983,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest004_1, * @tc.name: RelationalTableModifyTest005 * @tc.desc: Test modify distributed table with compatible upgrade * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest005, TestSize.Level1) @@ -1106,7 +1180,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, TableConstraintsTest002, TestSiz * @tc.name: RelationalRemoveDeviceDataTest001 * @tc.desc: Test remove device data * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest001, TestSize.Level1) @@ -1223,7 +1297,7 @@ void AddErrorTrigger(sqlite3 *db, const std::string &name) * @tc.name: RelationalRemoveDeviceDataTest002 * @tc.desc: Test remove device data and syn * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest002, TestSize.Level1) @@ -1344,7 +1418,7 @@ void TestRemoveDeviceDataWithCallback(bool removeAll) * @tc.name: RelationalRemoveDeviceDataTest003 * @tc.desc: Test remove all device data and sync again * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest003, TestSize.Level1) @@ -1356,7 +1430,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest00 * @tc.name: RelationalRemoveDeviceDataTest004 * @tc.desc: Test remove one device data and sync again * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest004, TestSize.Level1) @@ -1368,7 +1442,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest00 * @tc.name: RelationalRemoveDeviceDataTest005 * @tc.desc: Test remove device data with invalid param * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest005, TestSize.Level1) @@ -1417,7 +1491,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest00 * @tc.name: RelationalRemoveDeviceDataTest006 * @tc.desc: Test remove device data with busy * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest006, TestSize.Level1) @@ -1464,7 +1538,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest00 * @tc.name: RelationalOpenStorePathCheckTest001 * @tc.desc: Test open store with same label but different path. * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalOpenStorePathCheckTest001, TestSize.Level1) @@ -1493,14 +1567,14 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalOpenStorePathCheckTest RelationalStoreDelegate *delegate2 = nullptr; status = g_mgr.OpenStore(dir2 + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate2); - EXPECT_EQ(status, INVALID_ARGS); - ASSERT_EQ(delegate2, nullptr); + EXPECT_EQ(status, OK); + ASSERT_NE(delegate2, nullptr); status = g_mgr.CloseStore(delegate1); EXPECT_EQ(status, OK); status = g_mgr.CloseStore(delegate2); - EXPECT_EQ(status, INVALID_ARGS); + EXPECT_EQ(status, OK); } HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalOpenStorePressureTest001, TestSize.Level1) @@ -1628,7 +1702,7 @@ namespace { * @tc.require: * @tc.author: lianhuix */ -HWTEST_F(DistributedDBInterfacesRelationalTest, SqliteKeyWordTest001, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTest, SqliteKeyWordTest001, TestSize.Level1) { sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); ASSERT_NE(db, nullptr); @@ -1682,7 +1756,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, SqliteKeyWordTest001, TestSize.L * @tc.name: GetDistributedTableName001 * @tc.desc: Test get distributed table name * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBInterfacesRelationalTest, GetDistributedTableName001, TestSize.Level1) @@ -1753,7 +1827,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest001, T * @tc.require: * @tc.author: zhangshjie */ -HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest002, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest002, TestSize.Level1) { /** * @tc.steps:step1. Prepare db file @@ -1834,7 +1908,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest002, T * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest003, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest003, TestSize.Level1) { /** * @tc.steps:step1. Prepare db file @@ -2058,4 +2132,60 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, StoreId001, TestSize.Level0) EXPECT_NE(RelationalStoreManager::GetRelationalStoreIdentifier(USER_ID, USER_ID, APP_ID, STORE_ID_1, true), ""); EXPECT_NE(RelationalStoreManager::GetRelationalStoreIdentifier(USER_ID, USER_ID, APP_ID, storeIdWithDot, true), ""); } + +/** + * @tc.name: GetDbHandleConcurrentlyTest001 + * @tc.desc: Test get db handle concurrently + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, GetDbHandleConcurrentlyTest001, TestSize.Level1) +{ + /** + * @tc.steps:step1. Prepare db file + * @tc.expected: step1. Return OK. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + ASSERT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_NO_UNIQUE), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + /** + * @tc.steps:step2. open relational store + * @tc.expected: step2. Return OK. + */ + RelationalStoreDelegate *delegate = nullptr; + DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate); + EXPECT_EQ(status, OK); + ASSERT_NE(delegate, nullptr); + /** + * @tc.steps:step3. open relational store + * @tc.expected: step3. Return OK. + */ + std::string tableName = "sync_data"; + int executeTime = 100; + std::thread thread1([&, this]() { + for (int i = 0; i < executeTime; i++) { + DistributedDB::SqlCondition sqlCondition; + std::vector records = {}; + sqlCondition.sql = "BEGIN IMMEDIATE TRANSACTION;"; + EXPECT_EQ(delegate->ExecuteSql(sqlCondition, records), E_OK); + sqlCondition.sql = "DROP TABLE IF EXISTS " + DBCommon::GetLogTableName(tableName); + EXPECT_EQ(delegate->ExecuteSql(sqlCondition, records), E_OK); + sqlCondition.sql = "COMMIT;"; + EXPECT_EQ(delegate->ExecuteSql(sqlCondition, records), E_OK); + } + }); + std::thread thread2([&, this]() { + for (int i = 0; i < executeTime; i++) { + status = delegate->CreateDistributedTable(tableName, DistributedDB::CLOUD_COOPERATION); + EXPECT_EQ(status, OK); + } + }); + thread1.join(); + thread2.join(); + status = g_mgr.CloseStore(delegate); + EXPECT_EQ(status, OK); +} } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp index 14765c0cc6e9ab0c59f288050b5a558325b3e71b..8e865b54df910f7593afb3f65d1625ed37c4cfab 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp @@ -46,6 +46,7 @@ namespace { const string TABLE_NAME3 = "worKer3"; DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); RelationalStoreDelegate *g_delegate = nullptr; + VirtualCommunicatorAggregator *g_communicatorAggregator = nullptr; sqlite3 *g_db = nullptr; const int HALF = 2; @@ -149,7 +150,7 @@ namespace { while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { std::string extendVal; EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 0, extendVal), E_OK); - ASSERT_NE(num, 0ul); + ASSERT_NE(num, 0uL); EXPECT_EQ(extendVal, "Local" + std::to_string(index % num)); std::string cursorVal; EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, cursorVal), E_OK); @@ -222,8 +223,8 @@ namespace { * @tc.steps:step3. check tracker schema * @tc.expected: step3. Return OK. */ - const Key schemaKey(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.begin(), - DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.end()); + const Key schemaKey(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY, + DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY + strlen(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY)); sql = "SELECT value FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata WHERE key=?;"; sqlite3_stmt *stmt = nullptr; EXPECT_EQ(SQLiteUtils::GetStatement(g_db, sql, stmt), E_OK); @@ -268,6 +269,9 @@ namespace { void DistributedDBInterfacesRelationalTrackerTableTest::SetUp(void) { + g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(g_communicatorAggregator != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator); if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error."); } @@ -277,6 +281,7 @@ namespace { void DistributedDBInterfacesRelationalTrackerTableTest::TearDown(void) { DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); } void SetTrackerTableTest(const TrackerSchema &schema, DBStatus expect) @@ -316,7 +321,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest001, * @tc.steps:step3. table name is illegal table name * @tc.expected: step3. Return INVALID_ARGS. */ - schema.tableName = DBConstant::SYSTEM_TABLE_PREFIX + "_1"; + schema.tableName = std::string(DBConstant::SYSTEM_TABLE_PREFIX) + "_1"; EXPECT_EQ(g_delegate->SetTrackerTable(schema), INVALID_ARGS); CloseStore(); } @@ -346,12 +351,13 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest002, SetTrackerTableTest(schema, SCHEMA_MISMATCH); /** - * @tc.steps:step1. param valid but extend name is empty - * @tc.expected: step1. Return OK. + * @tc.steps:step3. param valid but extend name is empty + * @tc.expected: step3. Return OK. */ schema.trackerColNames = LOCAL_TABLE_TRACKER_NAME_SET2; schema.extendColNames = {}; SetTrackerTableTest(schema, OK); + SetTrackerTableTest(schema, OK); } /** @@ -361,7 +367,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest002, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest003, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest003, TestSize.Level1) { /** * @tc.steps:step1. tracker col name is no exist @@ -403,7 +409,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest003, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest005, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest005, TestSize.Level1) { /** * @tc.steps:step1. SetTrackerTable twice in same delegate @@ -454,7 +460,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest005, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest006, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest006, TestSize.Level1) { /** * @tc.steps:step1. SetTrackerTable @@ -698,7 +704,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest010, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest011, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest011, TestSize.Level1) { /** * @tc.steps:step1. SetTrackerTable on table2 @@ -756,7 +762,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest011, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest012, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest012, TestSize.Level1) { /** * @tc.steps:step1. SetTrackerTable on table2 @@ -851,7 +857,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest013, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest014, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest014, TestSize.Level1) { /** * @tc.steps:step1. CreateDistributedTable on table2 @@ -894,7 +900,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest014, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest015, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest015, TestSize.Level1) { /** * @tc.steps:step1. CreateDistributedTable on table2 @@ -944,7 +950,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest015, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest016, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest016, TestSize.Level1) { /** * @tc.steps:step1. SetTrackerTable on table2 @@ -979,7 +985,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest016, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest017, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest017, TestSize.Level1) { /** * @tc.steps:step1. SetTrackerTable on table2 @@ -1038,7 +1044,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest017, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest018, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest018, TestSize.Level1) { /** * @tc.steps:step1. Create DEVICE_COOPERATION DistributedTable @@ -1192,7 +1198,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest021, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest022, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest022, TestSize.Level1) { CheckDropTableAndReopenDb(true); } @@ -1819,6 +1825,14 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, ExecuteSql010, TestS condition.readOnly = true; EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); EXPECT_EQ(records.size(), num); + + /** + * @tc.steps:step3. ExecuteSql again + * @tc.expected: step3. Return OK. + */ + records.clear(); + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + EXPECT_EQ(records.size(), num); CloseStore(); } @@ -1878,7 +1892,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, ExecuteSql011, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest026, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest026, TestSize.Level1) { /** * @tc.steps:step1. SetTrackerTable on table2 @@ -1916,7 +1930,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest026, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest027, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest027, TestSize.Level1) { /** * @tc.steps:step1. create distributed table on table2 with case different @@ -1971,7 +1985,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest027, * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest028, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest028, TestSize.Level1) { /** * @tc.steps:step1. trackerColNames is empty @@ -2312,7 +2326,7 @@ void SetLowVersionSchema(sqlite3 *db, const std::string &extendColName) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest036, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest036, TestSize.Level1) { /** * @tc.steps:step1. Init db and init extend field to old version data @@ -2732,6 +2746,96 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest045, CloseStore(); } +/** + * @tc.name: TrackerTableTest046 + * @tc.desc: Test clear log of mismatched data + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest046, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable on table2 + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + int num = 10; + BatchInsertTableName2Data(num); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), WITH_INVENTORY_DATA); + + /** + * @tc.steps:step2. Recreate table2 by rename + * @tc.expected: step2. Return OK. + */ + std::string sql = "ALTER TABLE " + TABLE_NAME2 + " RENAME TO xxx"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(g_db, sql), E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(g_db, CREATE_LOCAL_PK_TABLE_SQL), E_OK); + sql = "INSERT INTO " + TABLE_NAME2 + " SELECT id,name,height,photo,asserts,age FROM xxx"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(g_db, sql), E_OK); + sql = "DROP TABLE xxx"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(g_db, sql), E_OK); + sql = "DELETE FROM " + TABLE_NAME2 + " WHERE id in ('7', '9')"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(g_db, sql), E_OK); + + /** + * @tc.steps:step3. Set tracker and check log count + * @tc.expected: step3. Return OK. + */ + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + sql = "select count(*) from " + DBCommon::GetLogTableName(TABLE_NAME2); + num = 8; + EXPECT_EQ(sqlite3_exec(g_db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(num), nullptr), SQLITE_OK); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest047 + * @tc.desc: Test recover log for extend_field is NULL + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest047, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable on table2 + * @tc.expected: step1. Return WITH_INVENTORY_DATA. + */ + CreateMultiTable(); + OpenStore(); + int num = 10; + BatchInsertTableName2Data(num); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), WITH_INVENTORY_DATA); + + /** + * @tc.steps:step2. Construct a log with invalid extend_field + * @tc.expected: step2. Return OK. + */ + std::string sql = "UPDATE " + DBCommon::GetLogTableName(TABLE_NAME2) + " SET extend_field = NULL" + " WHERE data_key=1"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(g_db, sql), E_OK); + std::string querySql = "select count(*) from " + DBCommon::GetLogTableName(TABLE_NAME2) + + " WHERE json_type(extend_field) IS 'object'"; + num = 9; + EXPECT_EQ(sqlite3_exec(g_db, querySql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(num), nullptr), SQLITE_OK); + + /** + * @tc.steps:step3. Set tracker and check log count + * @tc.expected: step3. Return OK. + */ + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + num = 10; + EXPECT_EQ(sqlite3_exec(g_db, querySql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(num), nullptr), SQLITE_OK); + CloseStore(); +} + /** * @tc.name: SchemaStrTest001 * @tc.desc: Test open reOpen stroe when schemaStr is empty @@ -2739,7 +2843,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest045, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, SchemaStrTest001, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, SchemaStrTest001, TestSize.Level1) { /** * @tc.steps:step1. set empty for relational schema str, reopen store diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_resultset_performance.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_resultset_performance.cpp index cf01fce891a8daf81d0b805b38017a08ab83099a..512c7204e37090ac5ae9486e46adef3e6783bda7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_resultset_performance.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_resultset_performance.cpp @@ -112,7 +112,7 @@ void DistributedDBInterfacesNBResultsetPerfTest::TearDown(void) * @tc.name: ResultSetPerfTest001 * @tc.desc: Test the NbDelegate for result set function. * @tc.type: FUNC - * @tc.require: AR000D08KT + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBResultsetPerfTest, ResultSetPerfTest001, TestSize.Level4) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_schema_database_upgrade_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_schema_database_upgrade_test.cpp index 9587a2c46f6ab921b5447d8bc032f170378bf413..85ecb941528695bc0bb198b10c7eba492b059ec4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_schema_database_upgrade_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_schema_database_upgrade_test.cpp @@ -80,18 +80,20 @@ namespace { std::string SchemaSwitchMode(const std::string &oriSchemaStr) { std::string resStr = oriSchemaStr; - auto iterStrict = std::search(resStr.begin(), resStr.end(), SchemaConstant::KEYWORD_MODE_STRICT.begin(), - SchemaConstant::KEYWORD_MODE_STRICT.end()); - auto iterCompatible = std::search(resStr.begin(), resStr.end(), SchemaConstant::KEYWORD_MODE_COMPATIBLE.begin(), - SchemaConstant::KEYWORD_MODE_COMPATIBLE.end()); + auto iterStrict = std::search(resStr.begin(), resStr.end(), SchemaConstant::KEYWORD_MODE_STRICT, + SchemaConstant::KEYWORD_MODE_STRICT + strlen(SchemaConstant::KEYWORD_MODE_STRICT)); + auto iterCompatible = std::search(resStr.begin(), resStr.end(), SchemaConstant::KEYWORD_MODE_COMPATIBLE, + SchemaConstant::KEYWORD_MODE_COMPATIBLE + strlen(SchemaConstant::KEYWORD_MODE_COMPATIBLE)); if (iterStrict != resStr.end()) { - resStr.replace(iterStrict, iterStrict + SchemaConstant::KEYWORD_MODE_STRICT.size(), - SchemaConstant::KEYWORD_MODE_COMPATIBLE.begin(), SchemaConstant::KEYWORD_MODE_COMPATIBLE.end()); + resStr.replace(iterStrict, iterStrict + strlen(SchemaConstant::KEYWORD_MODE_STRICT), + SchemaConstant::KEYWORD_MODE_COMPATIBLE, + SchemaConstant::KEYWORD_MODE_COMPATIBLE + strlen(SchemaConstant::KEYWORD_MODE_COMPATIBLE)); return resStr; } if (iterCompatible != resStr.end()) { - resStr.replace(iterCompatible, iterCompatible + SchemaConstant::KEYWORD_MODE_COMPATIBLE.size(), - SchemaConstant::KEYWORD_MODE_STRICT.begin(), SchemaConstant::KEYWORD_MODE_STRICT.end()); + resStr.replace(iterCompatible, iterCompatible + strlen(SchemaConstant::KEYWORD_MODE_COMPATIBLE), + SchemaConstant::KEYWORD_MODE_STRICT, + SchemaConstant::KEYWORD_MODE_STRICT + strlen(SchemaConstant::KEYWORD_MODE_STRICT)); return resStr; } return oriSchemaStr; @@ -182,7 +184,7 @@ void DistributedDBInterfacesSchemaDatabaseUpgradeTest::TearDown(void) * @tc.name: UpgradeFromKv001 * @tc.desc: Schema database upgrade from kv database, exist value match compatible schema(mismatch strict schema) * @tc.type: FUNC - * @tc.require: AR000F3OPD + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBInterfacesSchemaDatabaseUpgradeTest, UpgradeFromKv001, TestSize.Level1) @@ -241,7 +243,7 @@ HWTEST_F(DistributedDBInterfacesSchemaDatabaseUpgradeTest, UpgradeFromKv001, Tes * @tc.name: UpgradeFromKv002 * @tc.desc: Schema database upgrade from kv database, exist value mismatch compatible schema * @tc.type: FUNC - * @tc.require: AR000F3OPD + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBInterfacesSchemaDatabaseUpgradeTest, UpgradeFromKv002, TestSize.Level1) @@ -326,7 +328,7 @@ void TestUpgradeFromSchema(const std::string &storeId, const std::vector &fileNames) * @tc.name: GetKvStoreDiskSize001 * @tc.desc: ROM space occupied by applications in the distributed database can be calculated. * @tc.type: FUNC - * @tc.require: AR000CQDTD + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize001, TestSize.Level1) @@ -221,7 +221,7 @@ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize001, Test * @tc.name: GetKvStoreDiskSize002 * @tc.desc: Obtain the size of the opened database. * @tc.type: FUNC - * @tc.require: AR000CQDTD + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize002, TestSize.Level2) @@ -321,7 +321,7 @@ static void DeleteFile(const std::string &fileUrl) * @tc.name: GetKvStoreDiskSize003 * @tc.desc: Verification exception parameters * @tc.type: FUNC - * @tc.require: AR000CQDTD + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize003, TestSize.Level1) @@ -395,7 +395,7 @@ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize003, Test * @tc.name: GetKvStoreDiskSize004 * @tc.desc: Calculate memory database size * @tc.type: FUNC - * @tc.require: AR000CQDTD + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize004, TestSize.Level1) @@ -453,7 +453,7 @@ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize004, Test * @tc.name: DeleteDbByStoreId001 * @tc.desc: Delete database by storeId. * @tc.type: FUNC - * @tc.require: AR000CQDTD + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, DeleteDbByStoreId001, TestSize.Level1) @@ -526,7 +526,7 @@ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, DeleteDbByStoreId001, TestS * @tc.name: DeleteDbByStoreId002 * @tc.desc: Delete database by not exist storeId. * @tc.type: FUNC - * @tc.require: AR000CQDTD + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, DeleteDbByStoreId002, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_optimization_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_optimization_test.cpp index 3f8e6078b7cfa09750fcca3da4580eda28fbd4f4..8a07f8898794e682a4a9d0d2a44d9fa3fbf67034 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_optimization_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_optimization_test.cpp @@ -88,7 +88,7 @@ void DistributedDBInterfacesTransactionOptimizationTest::TearDown(void) * @tc.name: BatchOperationsOfSyncAndLocal001 * @tc.desc: Verify the batch put and query functions of the sync and local data in the same transaction. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, SyncAndLocalBatchOperations001, TestSize.Level1) @@ -166,7 +166,7 @@ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, SyncAndLocalBatchOp * @tc.name: SyncAndLocalSingleOperations001 * @tc.desc: Verify the single put and query functions of the sync and local data in the same transaction. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, SyncAndLocalSingleOperations001, TestSize.Level1) @@ -233,7 +233,7 @@ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, SyncAndLocalSingleO * @tc.name: DeleteInTransaction001 * @tc.desc: Verify that the sync and local functions can be deleted in the same transaction. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, DeleteInTransaction001, TestSize.Level1) @@ -296,7 +296,7 @@ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, DeleteInTransaction * @tc.name: DeleteBatchInTransaction001 * @tc.desc: Local data does not check readOnly. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, DeleteBatchInTransaction001, TestSize.Level1) @@ -370,7 +370,7 @@ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, DeleteBatchInTransa * @tc.name: SyncAndLocalObserver001 * @tc.desc: Verify the observer functions of the sync and local data in the same transaction. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, SyncAndLocalObserver001, TestSize.Level1) @@ -458,7 +458,7 @@ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, SyncAndLocalObserve * @tc.name: OnlyDeleteInTransaction001 * @tc.desc: Verify the observer functions of delete operation in the transaction. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, OnlyDeleteInTransaction001, TestSize.Level1) @@ -553,7 +553,7 @@ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, OnlyDeleteInTransac * @tc.name: SyncAndLocalObserver002 * @tc.desc: Verify the observer functions of the sync and local data in the same transaction. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, SyncAndLocalObserver002, TestSize.Level1) @@ -638,7 +638,7 @@ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, SyncAndLocalObserve * @tc.name: PutRollback001 * @tc.desc: Verify that a transaction can be rolled back after data is put. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, PutRollback001, TestSize.Level1) @@ -721,7 +721,7 @@ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, PutRollback001, Tes * @tc.name: PutBatchRollback001 * @tc.desc: Verify that a transaction can be rolled back after data is put. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, PutBatchRollback001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_syncdb_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_syncdb_test.cpp index 87cd87e3239bb610c32804c92de846f567d62144..5fae1dc866cc317d4b525a98fa39140cb53a196e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_syncdb_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_syncdb_test.cpp @@ -100,7 +100,7 @@ void DistributedDBInterfacesTransactionSyncDBTest::TearDown(void) * @tc.name: StartTransaction001 * @tc.desc: Test that can't call StartTransaction interface repeatedly. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, StartTransaction001, TestSize.Level1) @@ -120,7 +120,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, StartTransaction001, Test * @tc.name: StartTransaction002 * @tc.desc: Test that call StartTransaction and commit interface normally. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, StartTransaction002, TestSize.Level1) @@ -140,7 +140,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, StartTransaction002, Test * @tc.name: StartTransaction003 * @tc.desc: Test that call StartTransaction and rolback interface normally. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, StartTransaction003, TestSize.Level1) @@ -160,7 +160,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, StartTransaction003, Test * @tc.name: StartTransaction004 * @tc.desc: Test that call StartTransaction and rolback interface normally. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, StartTransaction004, TestSize.Level1) @@ -193,7 +193,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, StartTransaction004, Test * @tc.name: Commit001 * @tc.desc: Test that can't commit Transaction before it start. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit001, TestSize.Level1) @@ -209,7 +209,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit001, TestSize.Level * @tc.name: Commit002 * @tc.desc: Test that can't commit Transaction repeatedly even if it start normally. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit002, TestSize.Level1) @@ -233,7 +233,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit002, TestSize.Level * @tc.name: Commit003 * @tc.desc: Test that can commit Transaction after put record. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit003, TestSize.Level1) @@ -261,7 +261,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit003, TestSize.Level * @tc.name: Commit004 * @tc.desc: Test that can commit Transaction after update record. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit004, TestSize.Level1) @@ -289,7 +289,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit004, TestSize.Level * @tc.name: Commit005 * @tc.desc: Test that can commit Transaction after delete record. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit005, TestSize.Level1) @@ -317,7 +317,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit005, TestSize.Level * @tc.name: Commit006 * @tc.desc: Test that can commit Transaction after clear all the records. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit006, TestSize.Level1) @@ -345,7 +345,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit006, TestSize.Level * @tc.name: Commit007 * @tc.desc: Test that can commit Transaction after delete and update db. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit007, TestSize.Level1) @@ -377,7 +377,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit007, TestSize.Level * @tc.name: Commit008 * @tc.desc: Test that can commit Transaction after clear and new add records. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit008, TestSize.Level1) @@ -410,7 +410,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit008, TestSize.Level * @tc.desc: Test if new commit records and logs generated * when a transaction rollback-ed * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack001, TestSize.Level1) @@ -426,7 +426,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack001, TestSize.Lev * @tc.name: RollBack002 * @tc.desc: rollback a transaction two times * @tc.type: FUNC -* @tc.require: AR000BVRNM AR000CQDTQ +* @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack002, TestSize.Level1) @@ -450,7 +450,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack002, TestSize.Lev * @tc.name: RollBack003 * @tc.desc: insert a data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack003, TestSize.Level1) @@ -478,7 +478,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack003, TestSize.Lev * @tc.name: RollBack004 * @tc.desc: update a data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack004, TestSize.Level1) @@ -510,7 +510,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack004, TestSize.Lev * @tc.name: RollBack005 * @tc.desc: delete an exist data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack005, TestSize.Level1) @@ -542,7 +542,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack005, TestSize.Lev * @tc.name: RollBack006 * @tc.desc: clear db and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack006, TestSize.Level1) @@ -574,7 +574,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack006, TestSize.Lev * @tc.name: RollBack007 * @tc.desc: delete a exist data and update a data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack007, TestSize.Level1) @@ -610,7 +610,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack007, TestSize.Lev * @tc.name: RollBack008 * @tc.desc: clear db and insert a data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack008, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_test.cpp index 9a2720c7ed00e875498a0b8c63140bcd653da297..90eb5a2681d8e5011210440d5f55fe22597326a3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_test.cpp @@ -100,7 +100,7 @@ void DistributedDBInterfacesTransactionTest::TearDown(void) * @tc.name: StartTransaction001 * @tc.desc: Test that can't call StartTransaction interface repeatedly. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction001, TestSize.Level1) @@ -120,7 +120,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction001, TestSize.L * @tc.name: StartTransaction002 * @tc.desc: Test that call StartTransaction and commit interface normally. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction002, TestSize.Level1) @@ -140,7 +140,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction002, TestSize.L * @tc.name: StartTransaction003 * @tc.desc: Test that call StartTransaction and rolback interface normally. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction003, TestSize.Level1) @@ -160,7 +160,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction003, TestSize.L * @tc.name: StartTransaction004 * @tc.desc: Test that call StartTransaction and rolback interface normally. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction004, TestSize.Level1) @@ -193,7 +193,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction004, TestSize.L * @tc.name: StartTransaction005 * @tc.desc: Test that can't call StartTransaction interface repeatedly for different kv store. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction005, TestSize.Level3) @@ -221,7 +221,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction005, TestSize.L * @tc.name: Commit001 * @tc.desc: Test that can't commit Transaction before it start. * @tc.type: FUNC - * @tc.require: AR000CQDTO AR000CQDTP + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit001, TestSize.Level1) @@ -237,7 +237,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit001, TestSize.Level1) * @tc.name: Commit002 * @tc.desc: Test that can't commit Transaction repeatedly even if it start normally. * @tc.type: FUNC - * @tc.require: AR000CQDTO AR000CQDTP + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit002, TestSize.Level1) @@ -261,7 +261,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit002, TestSize.Level1) * @tc.name: Commit003 * @tc.desc: Test that can commit Transaction after put record. * @tc.type: FUNC - * @tc.require: AR000CQDTO AR000CQDTP + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit003, TestSize.Level1) @@ -289,7 +289,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit003, TestSize.Level1) * @tc.name: Commit004 * @tc.desc: Test that can commit Transaction after update record. * @tc.type: FUNC - * @tc.require: AR000CQDTO AR000CQDTP + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit004, TestSize.Level1) @@ -321,7 +321,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit004, TestSize.Level1) * @tc.name: Commit005 * @tc.desc: Test that can commit Transaction after delete record. * @tc.type: FUNC - * @tc.require: AR000CQDTO AR000CQDTP + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit005, TestSize.Level1) @@ -349,7 +349,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit005, TestSize.Level1) * @tc.name: Commit006 * @tc.desc: Test that can commit Transaction after clear all the records. * @tc.type: FUNC - * @tc.require: AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit006, TestSize.Level1) @@ -377,7 +377,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit006, TestSize.Level1) * @tc.name: Commit007 * @tc.desc: Test that can commit Transaction after delete and update db. * @tc.type: FUNC - * @tc.require: AR000CQDTO AR000CQDTP + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit007, TestSize.Level1) @@ -409,7 +409,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit007, TestSize.Level1) * @tc.name: Commit008 * @tc.desc: Test that can commit Transaction after clear and new add records. * @tc.type: FUNC - * @tc.require: AR000CQDTO AR000CQDTP + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit008, TestSize.Level1) @@ -442,7 +442,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit008, TestSize.Level1) * @tc.desc: Test if new commit records and logs generated * when a transaction rollback-ed * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback001, TestSize.Level1) @@ -458,7 +458,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback001, TestSize.Level1) * @tc.name: RollBack002 * @tc.desc: rollback a transaction two times * @tc.type: FUNC -* @tc.require: AR000BVRNM AR000CQDTQ +* @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback002, TestSize.Level1) @@ -482,7 +482,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback002, TestSize.Level1) * @tc.name: RollBack003 * @tc.desc: insert a data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback003, TestSize.Level1) @@ -510,7 +510,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback003, TestSize.Level1) * @tc.name: RollBack004 * @tc.desc: update a data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback004, TestSize.Level1) @@ -542,7 +542,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback004, TestSize.Level1) * @tc.name: RollBack005 * @tc.desc: delete a exist data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback005, TestSize.Level1) @@ -574,7 +574,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback005, TestSize.Level1) * @tc.name: RollBack006 * @tc.desc: clear db and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback006, TestSize.Level1) @@ -606,7 +606,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback006, TestSize.Level1) * @tc.name: RollBack007 * @tc.desc: delete a exist data and update a data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback007, TestSize.Level1) @@ -642,7 +642,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback007, TestSize.Level1) * @tc.name: RollBack008 * @tc.desc: clear db and insert a data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback008, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp index 1b535aa93c0ecbad77e8222044b8f4ed89183fbd..2259d5bf6fcd7c565939932a8684216e0ddfe054 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp @@ -78,7 +78,7 @@ void RuntimeContextProcessSystemApiAdapterImplTest::SetUp(void) * @tc.name: SetSecurityOption001 * @tc.desc: Set SecurityOption. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: */ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SetSecurityOption001, TestSize.Level1) { @@ -104,7 +104,7 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SetSecurityOption001, Te * @tc.name: GetSecurityOption001 * @tc.desc: Get SecurityOption. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: */ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, GetSecurityOption001, TestSize.Level1) { @@ -130,7 +130,7 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, GetSecurityOption001, Te * @tc.name: RegisterLockStatusLister001 * @tc.desc: Register a listener. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: */ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, RegisterLockStatusLister001, TestSize.Level1) { @@ -188,7 +188,7 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, RegisterLockStatusLister * @tc.name: IsAccessControlled001 * @tc.desc: Get Access Lock Status. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: */ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, IsAccessControlled001, TestSize.Level1) { @@ -214,7 +214,7 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, IsAccessControlled001, T * @tc.name: CheckDeviceSecurityAbility001 * @tc.desc: Check device security ability. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: */ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, CheckDeviceSecurityAbility001, TestSize.Level1) { @@ -271,7 +271,7 @@ void CheckDeviceSecurityAbility002() * @tc.name: CheckDeviceSecurityAbility002 * @tc.desc: Check device security ability with getkvstore frequency. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: */ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, CheckDeviceSecurityAbility002, TestSize.Level1) { @@ -307,7 +307,7 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SetSystemApiAdapterTest0 * @tc.type: FUNC * @tc.require: */ -HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade001, TestSize.Level0) +HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade001, TestSize.Level1) { /** * @tc.steps: step1. set g_adapter and open with s1 @@ -352,7 +352,7 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade001 * @tc.type: FUNC * @tc.require: */ -HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade002, TestSize.Level0) +HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade002, TestSize.Level1) { /** * @tc.steps: step1. set g_adapter and open with s1 @@ -391,7 +391,7 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade002 * @tc.type: FUNC * @tc.require: */ -HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade003, TestSize.Level0) +HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade003, TestSize.Level1) { /** * @tc.steps: step1. set g_adapter and open with not set diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp index 0c84743a90bbd493c8c96142cb06c0ef93edfb71..78129b104415feeec9364de216a769d1ee3db14b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp @@ -460,7 +460,7 @@ Assets DistributedDBCloudAssetsOperationSyncTest::GenerateAssets(const Asset &te * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation001, TestSize.Level1) { const int actualCount = 10; const int deleteDataCount = 5; @@ -493,7 +493,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation001, T * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation002, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation002, TestSize.Level1) { const int actualCount = 1; InsertUserTableRecord(tableName_, 0, actualCount); @@ -520,7 +520,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation002, T * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation003, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation003, TestSize.Level1) { InsertUserTableRecord(tableName_, 0, 1); // 1 is count int uploadCount = 0; @@ -585,7 +585,7 @@ void DistributedDBCloudAssetsOperationSyncTest::LocalAssetRemoveTest() * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation004, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation004, TestSize.Level1) { LocalAssetRemoveTest(); } @@ -614,7 +614,7 @@ void DistributedDBCloudAssetsOperationSyncTest::UpdateAssetWhenSyncUpload() * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation005, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation005, TestSize.Level1) { /** * @tc.steps:step1. Insert 60 records. @@ -691,7 +691,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation005, T * @tc.require: * @tc.author: lijun */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation006, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation006, TestSize.Level1) { const int actualCount = 5; InsertUserTableRecord(tableName_, 0, actualCount); @@ -719,7 +719,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation006, T * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation007, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation007, TestSize.Level1) { /** * @tc.steps:step1. Insert 5 records and sync. @@ -757,7 +757,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation007, T * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation008, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation008, TestSize.Level1) { /** * @tc.steps:step1. Insert 5 records and sync. @@ -802,7 +802,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation008, T * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation009, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation009, TestSize.Level1) { /** * @tc.steps:step1. Insert 5 records and sync. @@ -914,7 +914,7 @@ void DistributedDBCloudAssetsOperationSyncTest::PrepareForAssetOperation010() * @tc.require: * @tc.author: liufuchenxing */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation010, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation010, TestSize.Level1) { /** * @tc.steps:step1. prepare local and cloud asset data. @@ -988,7 +988,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, TestOpenDatabaseBusy001, Tes * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation011, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation011, TestSize.Level1) { /** * @tc.steps:step1. Insert 5 records and sync. @@ -1048,7 +1048,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation011, T * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation012, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation012, TestSize.Level1) { RuntimeContext::GetInstance()->SetBatchDownloadAssets(true); LocalAssetRemoveTest(); @@ -1087,7 +1087,7 @@ void DistributedDBCloudAssetsOperationSyncTest::UpdateLocalAssetRecord(const std * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation013, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation013, TestSize.Level1) { /** * @tc.steps:step1. Insert local and cloud asset data and sync. @@ -1122,7 +1122,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation013, T * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation014, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation014, TestSize.Level1) { /** * @tc.steps:step1. Insert 5 records and sync. @@ -1158,7 +1158,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation014, T * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord001, TestSize.Level1) { const int actualCount = 1; InsertUserTableRecord(tableName_, 0, actualCount); @@ -1191,7 +1191,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord001, TestSize.Le * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord002, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord002, TestSize.Level1) { const int actualCount = 1; InsertUserTableRecord(tableName_, 0, actualCount); @@ -1214,7 +1214,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord002, TestSize.Le * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord003, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord003, TestSize.Level1) { const int actualCount = 1; InsertUserTableRecord(tableName_, 0, actualCount); @@ -1234,7 +1234,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord003, TestSize.Le * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord004, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord004, TestSize.Level1) { RuntimeContext::GetInstance()->SetBatchDownloadAssets(true); const int actualCount = 10; @@ -1259,7 +1259,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord004, TestSize.Le * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertData001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertData001, TestSize.Level1) { // insert id 0 to local const int actualCount = 1; @@ -1286,7 +1286,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertData001, TestSize.Leve * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertData002, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertData002, TestSize.Level1) { /** * @tc.steps:step1. Insert 5 records and sync. @@ -1345,7 +1345,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertData002, TestSize.Leve * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetConflict001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetConflict001, TestSize.Level1) { // cloud and local insert same data const int actualCount = 1; @@ -1416,7 +1416,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertDataInvalid001, TestSi * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertDataInvalid002, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertDataInvalid002, TestSize.Level1) { VBucket record; record["id"] = std::to_string(0); @@ -1474,7 +1474,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertDataInvalid002, TestSi * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, DownloadAssetStatusTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, DownloadAssetStatusTest004, TestSize.Level1) { /** * @tc.steps:step1. cloud assets {0, 1} @@ -1645,7 +1645,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest002, TestSiz * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest003, TestSize.Level1) { /** * @tc.steps:step1. Insert 100 records. @@ -1684,7 +1684,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest003, TestSiz * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest004, TestSize.Level1) { /** * @tc.steps:step1. Insert 100 records and sync to cloud. @@ -1732,7 +1732,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest004, TestSiz * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, BatchNormalDownloadAsset001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, BatchNormalDownloadAsset001, TestSize.Level1) { RuntimeContext::GetInstance()->SetBatchDownloadAssets(true); PrepareDataInCloud(); @@ -1752,7 +1752,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, BatchNormalDownloadAsset001, * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, BatchAbnormalDownloadAsset001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, BatchAbnormalDownloadAsset001, TestSize.Level1) { RuntimeContext::GetInstance()->SetBatchDownloadAssets(true); PrepareDataInCloud(); @@ -1788,7 +1788,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, BatchAbnormalDownloadAsset00 * @tc.require: * @tc.author: lg */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithLogFlag001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithLogFlag001, TestSize.Level1) { /** * @tc.steps:step1. Insert 5 records and sync. diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp index efe572335824281d7afd2e8f35afe6dd082b99b5..9321daee5e4e515598a736b3067e48a283e0948d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp @@ -665,7 +665,7 @@ void DistributedDBCloudCheckSyncTest::CheckDownloadInfo(const Info &actualDownlo * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest001, TestSize.Level1) { // prepare data const int actualCount = 10; @@ -693,7 +693,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest001, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest002, TestSize.Level1) { // prepare data const int actualCount = 1; @@ -719,7 +719,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest002, TestSize.Level0) * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest003, TestSize.Level1) { // prepare data const int actualCount = 1; @@ -748,7 +748,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest003, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest004, TestSize.Level1) { // prepare data const int actualCount = 1; @@ -775,7 +775,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest004, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest005, TestSize.Level1) { /** * @tc.steps:step1. init data and sync @@ -815,7 +815,7 @@ void DistributedDBCloudCheckSyncTest::InitDataAndSync() * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest006, TestSize.Level1) { /** * @tc.steps:step1. init data and sync @@ -890,7 +890,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest006, TestSize.Level0) * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest007, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest007, TestSize.Level1) { /** * @tc.steps:step1. init data and sync @@ -965,7 +965,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest007, TestSize.Level0) * @tc.require: * @tc.author: suyuchen */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest008, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest008, TestSize.Level1) { /** * @tc.steps: step1. insert 35 records to user table @@ -1048,7 +1048,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest008, TestSize.Level0) * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest009, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest009, TestSize.Level1) { /** * @tc.steps: step1. insert 1 record to user table @@ -1102,7 +1102,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest009, TestSize.Level0) * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest010, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest010, TestSize.Level1) { /** * @tc.steps: step1. insert 1 record to user table @@ -1134,7 +1134,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest010, TestSize.Level0) RelationalStoreDelegate::Option option; ASSERT_EQ(mgr_->OpenStore(storePath_, STORE_ID_1, option, delegate_), DBStatus::OK); ASSERT_NE(delegate_, nullptr); - ASSERT_EQ(delegate_->CreateDistributedTable(tableName_, CLOUD_COOPERATION), DBStatus::SCHEMA_MISMATCH); + ASSERT_EQ(delegate_->CreateDistributedTable(tableName_, CLOUD_COOPERATION), DBStatus::OK); ASSERT_EQ(delegate_->SetCloudDB(virtualCloudDb_), DBStatus::OK); ASSERT_EQ(delegate_->SetIAssetLoader(virtualAssetLoader_), DBStatus::OK); DataBaseSchema dataBaseSchema = GetSchema(); @@ -1157,7 +1157,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest010, TestSize.Level0) * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest011, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest011, TestSize.Level1) { /** * @tc.steps: step1. insert 1 record to user table @@ -1208,7 +1208,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest011, TestSize.Level0) * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest012, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest012, TestSize.Level1) { /** * @tc.steps: step1. insert 1 record to user table @@ -1261,6 +1261,66 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest012, TestSize.Level0) CheckCloudTableCount(tableName_, 1); } +/** + * @tc.name: CloudSyncTest013 + * @tc.desc: insert data before re-SetDistributedTable and sync is ok + * @tc.type: FUNC + * @tc.require: + * @tc.author: tankaisheng + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest013, TestSize.Level0) +{ + /** + * @tc.steps: step1. insert 1 record to user table + * @tc.expected: step1. OK. + */ + const int actualCount = 10; + InsertUserTableRecord(tableName_, actualCount); + /** + * @tc.steps: step2. sync data to cloud + * @tc.expected: step2. OK. + */ + Query query = Query::Select().FromTable({ tableName_ }); + BlockSync(query, delegate_, g_actualDBStatus); + CheckCloudTableCount(tableName_, 10); + /** + * @tc.steps: step3. drop data table then close db + * @tc.expected: step3. OK. + */ + std::string deleteSql = "DROP TABLE IF EXISTS " + tableName_ + ";"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, deleteSql), DBStatus::OK); + EXPECT_EQ(mgr_->CloseStore(delegate_), DBStatus::OK); + delegate_ = nullptr; + /** + * @tc.steps: step4. recreate data table and reopen database + * @tc.expected: step4. OK. + */ + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, g_createSQL), DBStatus::OK); + RelationalStoreDelegate::Option option; + ASSERT_EQ(mgr_->OpenStore(storePath_, STORE_ID_1, option, delegate_), DBStatus::OK); + ASSERT_NE(delegate_, nullptr); + ASSERT_EQ(delegate_->SetCloudDB(virtualCloudDb_), DBStatus::OK); + ASSERT_EQ(delegate_->SetIAssetLoader(virtualAssetLoader_), DBStatus::OK); + DataBaseSchema dataBaseSchema = GetSchema(); + ASSERT_EQ(delegate_->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(communicatorAggregator_ != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_); + /** + * @tc.steps: step5. insert data to new table + * @tc.expected: step5. OK. + */ + int begin = 0; + InsertUserTableRecord(tableName_, actualCount, begin); + /** + * @tc.steps: step6. sync and cloud data should be deleted + * @tc.expected: step6. OK. + */ + ASSERT_EQ(delegate_->CreateDistributedTable(tableName_, CLOUD_COOPERATION), DBStatus::OK); + BlockSync(query, delegate_, g_actualDBStatus); + CheckCloudTableCount(tableName_, 10); +} + /** * @tc.name: CloudSyncObserverTest001 * @tc.desc: test cloud sync multi observer @@ -1268,7 +1328,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest012, TestSize.Level0) * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncObserverTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncObserverTest001, TestSize.Level1) { // prepare data const int actualCount = 10; @@ -1341,7 +1401,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncObserverTest001, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest001, TestSize.Level1) { /** * @tc.steps:step1. insert user table record and query in 3 records, then priority sync. @@ -1403,7 +1463,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest001, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest002, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -1487,7 +1547,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest002, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest003, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -1518,7 +1578,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest003, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest004, TestSize.Level1) { /** * @tc.steps:step1. insert user non-primarykey table record. @@ -1553,7 +1613,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest004, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest005, TestSize.Level1) { /** * @tc.steps:step1. insert user non-primarykey table record. @@ -1580,7 +1640,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest005, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest006, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -1644,7 +1704,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest006, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest007, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest007, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -1707,7 +1767,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest007, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest008, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest008, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -1769,7 +1829,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest008, TestSize.Lev * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest009, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest009, TestSize.Level1) { /** * @tc.steps:step1. insert user table record and query in 3 records, then priority sync. @@ -1803,7 +1863,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest009, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest010, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest010, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -1844,7 +1904,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest010, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest011, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest011, TestSize.Level1) { /** * @tc.steps:step1. insert cloud table record. @@ -1909,7 +1969,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest011, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest012, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest012, TestSize.Level1) { /** * @tc.steps:step1. insert cloud table record. @@ -1947,7 +2007,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest012, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest013, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest013, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -2063,7 +2123,7 @@ void DistributedDBCloudCheckSyncTest::CheckUploadInfoAfterSync(int recordCount, * @tc.require: * @tc.author: suyue */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest014, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest014, TestSize.Level1) { /** * @tc.steps:step1. insert data and sync pause. @@ -2134,7 +2194,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest014, TestSize.Lev * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest015, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest015, TestSize.Level1) { /** * @tc.steps:step1. insert data and sync pause. @@ -2206,7 +2266,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest015, TestSize.Lev * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest016, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest016, TestSize.Level1) { /** * @tc.steps:step1. insert cloud table record. @@ -2248,7 +2308,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest016, TestSize.Lev * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest001, TestSize.Level1) { bool logicDelete = true; auto data = static_cast(&logicDelete); @@ -2268,7 +2328,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest001, TestSize.Level * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest002, TestSize.Level1) { bool logicDelete = false; auto data = static_cast(&logicDelete); @@ -2285,7 +2345,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest002, TestSize.Level * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest003, TestSize.Level1) { /** * @tc.steps:step1. register observer. @@ -2357,7 +2417,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest003, TestSize.Level * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest004, TestSize.Level1) { /** * @tc.steps:step1. set logic delete @@ -2405,7 +2465,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest005, TestSize.Level * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest006, TestSize.Level1) { /** * @tc.steps:step1. set logic delete @@ -2452,7 +2512,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest006, TestSize.Level * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest008, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest008, TestSize.Level1) { /** * @tc.steps:step1. Insert user table record with flag 0x800. Insert cloud table record. @@ -2514,7 +2574,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, LockActionTest001, TestSize.Level0) * @tc.name: LogicCreateRepeatedTableNameTest001 * @tc.desc: test create repeated table name with different cases * @tc.type: FUNC - * @tc.require:DTS2023120705927 + * @tc.require: * @tc.author: wangxiangdong */ HWTEST_F(DistributedDBCloudCheckSyncTest, LogicCreateRepeatedTableNameTest001, TestSize.Level0) @@ -2534,7 +2594,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, LogicCreateRepeatedTableNameTest001, T * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest001, TestSize.Level1) { /** * @tc.steps:step1. insert cloud records @@ -2564,7 +2624,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest001, TestSize.Level0) * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest002, TestSize.Level1) { /** * @tc.steps:step1. insert cloud records @@ -2603,7 +2663,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest002, TestSize.Level0) * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest003, TestSize.Level1) { /** * @tc.steps:step1. insert local records @@ -2642,7 +2702,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest003, TestSize.Level0) * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, RangeQuerySyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, RangeQuerySyncTest001, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -2691,7 +2751,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, RangeQuerySyncTest002, TestSize.Level1 * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudCheckSyncTest, SameDataSync001, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, SameDataSync001, TestSize.Level1) { /** * @tc.steps:step1. insert cloud records, cloud has two batch id:0-4 @@ -2779,7 +2839,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, SameDataSync002, TestSize.Level1) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CreateDistributedTable001, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CreateDistributedTable001, TestSize.Level1) { const std::string table = "CreateDistributedTable001"; const std::string createSQL = diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp index 04f5cfd8119f6b21485fad0af4e0498ddf2e2815..892620032e5a208a57a61087c61d9c7bd8262043 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp @@ -1160,7 +1160,7 @@ namespace { * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest001, TestSize.Level1) { int64_t paddingSize = 10; int64_t cloudCount = 20; @@ -1202,7 +1202,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest001, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest002, TestSize.Level1) { int64_t localCount = 20; int64_t cloudCount = 10; @@ -1230,7 +1230,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest002, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest003, TestSize.Level1) { int64_t paddingSize = 10; int cloudCount = 20; @@ -1288,7 +1288,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest003, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest004, TestSize.Level1) { int64_t paddingSize = 1024 * 8; vector threads; @@ -1309,7 +1309,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest004, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest005, TestSize.Level1) { Query query = Query::Select().FromTable(g_tables).OrderBy("123", true); ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), @@ -1328,7 +1328,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest005, TestS * @tc.require: * @tc.author: wanyi */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest006, TestSize.Level1) { int64_t paddingSize = 10; int cloudCount = 20; @@ -1399,7 +1399,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest007, TestS * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest008, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest008, TestSize.Level1) { ASSERT_EQ(g_delegate->SetCloudDB(nullptr), OK); // it will not happen because cloudb has been set in SetUp() Query query = Query::Select().FromTable({g_tableName3}); @@ -1415,7 +1415,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest008, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest009, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest009, TestSize.Level1) { int64_t paddingSize = 10; int cloudCount = 20; @@ -1442,7 +1442,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest009, TestS CloseDb(); } -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest0010, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest0010, TestSize.Level1) { int64_t paddingSize = 10; int cloudCount = 20; @@ -1478,7 +1478,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest0010, Test * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest011, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest011, TestSize.Level1) { Query query = Query::Select().FromTable({g_tableName1, g_tableName1}); bool syncFinish = false; @@ -1501,12 +1501,11 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest011, TestS cv.wait(uniqueLock, [&syncFinish]() { return syncFinish; }); - RuntimeContext::GetInstance()->StopTaskPool(); EXPECT_EQ(callCount, 2); // 2 is onProcess count CloseDb(); } -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest012, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest012, TestSize.Level1) { int64_t localCount = 20; int64_t cloudCount = 10; @@ -1537,7 +1536,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest012, TestS * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest013, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest013, TestSize.Level1) { /** * @tc.steps: insert some data into cloud db @@ -1625,7 +1624,7 @@ void TestSyncForStatus(RelationalStoreDelegate *delegate, DBStatus expectStatus) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest015, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest015, TestSize.Level1) { g_virtualCloudDb->SetActionStatus(CLOUD_NETWORK_ERROR); TestSyncForStatus(g_delegate, CLOUD_NETWORK_ERROR); @@ -1653,7 +1652,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest015, TestS * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest014, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest014, TestSize.Level1) { auto adapter = std::make_shared(); RuntimeConfig::SetProcessSystemAPIAdapter(adapter); @@ -1702,7 +1701,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest014, TestS * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest016, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest016, TestSize.Level1) { int64_t localCount = 10; int64_t paddingSize = 10; @@ -1736,7 +1735,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest016, TestS * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest017, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest017, TestSize.Level1) { /** * @tc.steps: step1. make data: 20 records on local, 20 records on cloud @@ -1769,7 +1768,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest017, TestS * @tc.require: * @tc.author: wanyi */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DataNotifier001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DataNotifier001, TestSize.Level1) { int64_t paddingSize = 10; int localCount = 20; @@ -1805,7 +1804,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest001, * @tc.require: * @tc.author: huangboxin */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, MannualNotify001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, MannualNotify001, TestSize.Level1) { int64_t paddingSize = 10; int localCount = 10; @@ -1903,7 +1902,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudProcessNotify001, * @tc.require: * @tc.author: huangboxin */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest002, TestSize.Level1) { int64_t paddingSize = 10; int localCount = 3; @@ -1921,7 +1920,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest002, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest003, TestSize.Level1) { int64_t paddingSize = 10; int localCount = 3; @@ -1961,7 +1960,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest003, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest004, TestSize.Level1) { int64_t paddingSize = 10; int localCount = 3; @@ -2000,7 +1999,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest004, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest005, TestSize.Level1) { /** * @tc.steps:step1. Construct local data with asset names and hashes consistent with the cloud @@ -2058,7 +2057,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest005, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest006, TestSize.Level1) { /** * @tc.steps:step1. Construct local data with NULL asset and the local count is greater than the cloud @@ -2087,7 +2086,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest006, * @tc.require: * @tc.author: wanyi */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest007, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest007, TestSize.Level1) { /** * @tc.steps:step1. local asset contain an asset which has a corresponding asset in cloud @@ -2149,7 +2148,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest007, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest001, TestSize.Level1) { /** * @tc.steps:step1. Set different status out of parameters, and the code returns OK @@ -2189,7 +2188,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest001, T * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest008, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest008, TestSize.Level1) { /** * @tc.steps:step1. prepare asset data @@ -2240,7 +2239,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest008, * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest009, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest009, TestSize.Level1) { // insert 3 data with asset 3 data without asset into local // sync them to cloud @@ -2264,7 +2263,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest009, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest002, TestSize.Level1) { /** * @tc.steps:step1. Set different status out of parameters, and the code returns CLOUD_ERROR @@ -2304,7 +2303,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest002, T * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest003, TestSize.Level1) { /** * @tc.steps:step1. Init data and sync @@ -2343,7 +2342,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest003, T * @tc.require: * @tc.author: liufuchenxing */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest004, TestSize.Level1) { /** * @tc.steps:step1. Init data and sync @@ -2389,7 +2388,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest004, T * @tc.require: * @tc.author: wanyi */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, SchemaTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, SchemaTest001, TestSize.Level1) { /** * @tc.steps:step1. Create table with Cloud cooperation mode @@ -2412,7 +2411,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, SchemaTest001, TestSize * @tc.require: * @tc.author: wanyi */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, SchemaTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, SchemaTest002, TestSize.Level1) { /** * @tc.steps:step1. Create table with DEVICE_COOPERATION mode @@ -2463,5 +2462,107 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudCursorTest001, Tes SQLiteUtils::ResetStatement(stmt, true, errCode); CloseDb(); } + +/* + * @tc.name: RDBSupportEncryptTest001 + * @tc.desc: Test sync when security label is not set and different encryption para is set + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, RDBSupportEncryptTest001, TestSize.Level1) +{ + /** + * @tc.steps: step1. sync when security label is not set and encryption is not supported + * @tc.expected: step1. return ok. + */ + auto adapter = std::make_shared(); + RuntimeConfig::SetProcessSystemAPIAdapter(adapter); + Query query = Query::Select().FromTable({g_tableName3}); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), OK); + + /** + * @tc.steps: step2. sync when security label is not set and encryption is supported + * @tc.expected: step2. return ok. + */ + CloudSyncConfig config; + config.isSupportEncrypt = true; + g_delegate->SetCloudSyncConfig(config); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), OK); + RuntimeConfig::SetProcessSystemAPIAdapter(nullptr); + CloseDb(); +} + +/* + * @tc.name: RDBSupportEncryptTest002 + * @tc.desc: Test sync when security label is S4 and different encryption para is set + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, RDBSupportEncryptTest002, TestSize.Level0) +{ + /** + * @tc.steps: step1. sync when security label is S4 and encryption is not supported + * @tc.expected: step1. return SECURITY_OPTION_CHECK_ERROR. + */ + auto adapter = std::make_shared(); + RuntimeConfig::SetProcessSystemAPIAdapter(adapter); + Query query = Query::Select().FromTable({g_tableName3}); + adapter->ForkGetSecurityOption([](const std::string&, SecurityOption &option) { + option.securityLabel = S4; + return OK; + }); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), + SECURITY_OPTION_CHECK_ERROR); + + /** + * @tc.steps: step2. sync when security label is S4 and encryption is supported + * @tc.expected: step2. return OK. + */ + CloudSyncConfig config; + config.isSupportEncrypt = true; + g_delegate->SetCloudSyncConfig(config); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), OK); + + /** + * @tc.steps: step3. sync when isSupportEncrypt is set to false for the second time + * @tc.expected: step3. return SECURITY_OPTION_CHECK_ERROR. + */ + config.isSupportEncrypt = false; + g_delegate->SetCloudSyncConfig(config); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), + SECURITY_OPTION_CHECK_ERROR); + RuntimeConfig::SetProcessSystemAPIAdapter(nullptr); + CloseDb(); +} + +/* + * @tc.name: RDBSupportEncryptTest003 + * @tc.desc: Test sync when SecurityOption is not supported and different encryption para is set + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, RDBSupportEncryptTest003, TestSize.Level1) +{ + /** + * @tc.steps: step1. sync when unable to get security options + * @tc.expected: step1. return OK whether or not encryption is supported. + */ + auto adapter = std::make_shared(); + RuntimeConfig::SetProcessSystemAPIAdapter(adapter); + Query query = Query::Select().FromTable({g_tableName3}); + adapter->ForkGetSecurityOption([](const std::string&, SecurityOption &option) { + return NOT_SUPPORT; + }); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), OK); + CloudSyncConfig config; + config.isSupportEncrypt = true; + g_delegate->SetCloudSyncConfig(config); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), OK); + RuntimeConfig::SetProcessSystemAPIAdapter(nullptr); + CloseDb(); +} } #endif // RELATIONAL_STORE diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp index 4df121dd47f51c63b089a0c410f852fa13cb0f90..c5f5d056513615f6e3a59d957bcef73fb8dbbe18 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp @@ -337,7 +337,7 @@ namespace { std::vector keys; EXPECT_EQ(obj.DeleteMetaData(keys), -E_INVALID_DB); EXPECT_EQ(obj.GetAllMetaKeys(keys), -E_INVALID_DB); - Key key; + Key key = {'k'}; Value value; EXPECT_EQ(obj.GetMetaData(key, value), -E_INVALID_DB); EXPECT_EQ(obj.PutMetaData(key, value), -E_INVALID_DB); @@ -350,9 +350,6 @@ namespace { int64_t count; EXPECT_EQ(obj.GetUploadCount(querySync, timestamp, true, true, count), -E_INVALID_DB); TableSchema tableSchema; - ContinueToken token; - CloudSyncData data; - EXPECT_EQ(obj.GetCloudData(tableSchema, querySync, timestamp, token, data), -E_INVALID_DB); std::vector timestampVec; EXPECT_EQ(obj.GetAllUploadCount(querySync, timestampVec, true, true, count), -E_INVALID_DB); std::vector cloudGid; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_reference_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_reference_sync_test.cpp index c87512c867acca997eb08c3b0d80514eb4657c8e..81592c878013452f0912825d31d4d5c131b6d6a6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_reference_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_reference_sync_test.cpp @@ -432,7 +432,7 @@ std::vector DistributedDBCloudReferenceSyncTest::InitMultiTable(int * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest001, TestSize.Level1) { std::vector tableNames = { parentTableName_, childTableName_ }; Query query = Query::Select().FromTable(tableNames); @@ -458,7 +458,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest001, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest002, TestSize.Level1) { std::vector tableNames = { sharedParentTableName_, sharedChildTableName_ }; Query query = Query::Select().FromTable(tableNames); @@ -484,7 +484,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest002, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest003, TestSize.Level1) { std::vector tableNames = { childTableName_, parentTableName_ }; Query query = Query::Select().FromTable(tableNames); @@ -510,7 +510,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest003, TestSize.Level0) * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest004, TestSize.Level1) { /** * @tc.steps: step1. cloud insert records then sync, check distributed shared table @@ -558,7 +558,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest004, TestSize.Level0) * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest005, TestSize.Level1) { /** * @tc.steps: step1. user insert records then sync, check distributed shared table @@ -599,7 +599,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest005, TestSize.Level0) * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest006, TestSize.Level1) { /** * @tc.steps: step1. user insert records then sync, check distributed shared table @@ -628,7 +628,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest006, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest007, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest007, TestSize.Level1) { /** * @tc.steps: step1. user insert records then sync, check distributed shared table @@ -652,7 +652,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest007, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest008, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest008, TestSize.Level1) { /** * @tc.steps: step1. open store with dot store id @@ -740,7 +740,7 @@ void ComplexReferenceCheck001SetReference(RelationalStoreDelegate *delegate) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck001, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck001, TestSize.Level1) { auto tableName = InitMultiTable(8); // 8 table ComplexReferenceCheck001SetReference(delegate_); @@ -796,7 +796,7 @@ void ComplexReferenceCheck002SetReference(RelationalStoreDelegate *delegate) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck002, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck002, TestSize.Level1) { auto tableName = InitMultiTable(5); // 5 table ASSERT_EQ(delegate_->SetCloudDbSchema(GetSchema(tableName)), DBStatus::OK); @@ -848,7 +848,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck002, TestSize * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck003, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck003, TestSize.Level1) { /** * @tc.steps: step1. init reference table, and reopen db @@ -915,7 +915,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck003, TestSize * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck004, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck004, TestSize.Level1) { /** * @tc.steps: step1. init table and set reference twice diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp index 8f0760892979a92d0de9aced5a90c3b731211e23..74b5dea75c1495e1364c629757d82eb25441f0ae 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp @@ -488,7 +488,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest013, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest013, TestSize.Level1) { VbucketWithoutPrimaryDataTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY); } @@ -618,7 +618,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest018, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest018, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(name text primary key, age TEXT COLLATE NOCASE);"; std::string insertSql = "insert into " + g_tableName + " values('abcd', '10');"; @@ -633,7 +633,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest019, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest019, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(NAME text collate NOCASE, age text," + "primary key(name, age));"; @@ -649,7 +649,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest020, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest020, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(NAME text collate NOCASE, age text," + "primary key(name, age));"; @@ -665,7 +665,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest021, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest021, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(NAME text collate NOCASE, age text collate nocase," + "primary key(name, age));"; @@ -681,7 +681,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest022, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest022, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE RTRIM, age text);"; std::string insertSql = "insert into " + g_tableName + " values('abcd ', '10');"; @@ -696,7 +696,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest023, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest023, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE RTRIM, age text);"; std::string insertSql = "insert into " + g_tableName + " values('abcd_', '10');"; @@ -711,7 +711,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest024, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest024, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE rtrim);"; std::string insertSql = "insert into " + g_tableName + " values('abcd ');"; @@ -726,7 +726,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest025, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest025, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(name text primary key, age TEXT COLLATE rtrim);"; std::string insertSql = "insert into " + g_tableName + " values('abcd ', '10');"; @@ -741,7 +741,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest026, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest026, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(NAME text collate RTRIM, age text," + "primary key(name, age));"; @@ -757,7 +757,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest027, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest027, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(NAME text collate rtrim, age text," + "primary key(name, age));"; @@ -773,7 +773,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest028, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest028, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(NAME text collate rtrim, age text collate rtrim," + "primary key(name, age));"; @@ -863,7 +863,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest001, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest001, TestSize.Level1) { SaveCloudDataTest(PrimaryKeyType::NO_PRIMARY_KEY); // there is one log record with cloud_gid = abcd3(id = 7 will delete first, then insert again) @@ -886,7 +886,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest002, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest002, TestSize.Level1) { SaveCloudDataTest(PrimaryKeyType::NO_PRIMARY_KEY, GidType::GID_MISMATCH); } @@ -898,7 +898,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest003, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest003, TestSize.Level1) { SaveCloudDataTest(PrimaryKeyType::NO_PRIMARY_KEY, GidType::GID_EMPTY, true, true, -E_CLOUD_ERROR); } @@ -910,7 +910,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest004, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest004, TestSize.Level1) { SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY); } @@ -922,7 +922,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest005, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest005, TestSize.Level1) { SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_MISMATCH); } @@ -934,7 +934,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest006, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest006, TestSize.Level1) { SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_EMPTY, true, true, -E_CLOUD_ERROR); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_task_merge_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_task_merge_test.cpp index f991b7164963aaccf9e9fd833d06359b58cf00d5..65b1b03e1114207780b1baae84287988c97bbc7f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_task_merge_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_task_merge_test.cpp @@ -277,7 +277,7 @@ SyncProcessCallback DistributedDBCloudTaskMergeTest::GetProcessCallback( * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTaskMergeTest, CloudSyncMergeTaskTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudTaskMergeTest, CloudSyncMergeTaskTest001, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -481,7 +481,7 @@ HWTEST_F(DistributedDBCloudTaskMergeTest, CloudSyncMergeTaskTest003, TestSize.Le * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudTaskMergeTest, CloudSyncMergeTaskTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudTaskMergeTest, CloudSyncMergeTaskTest004, TestSize.Level1) { size_t finishCount = 0u; std::mutex callbackMutex; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_file_package_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_file_package_test.cpp index 2df279cf208753c37d799cb3590118f9d85658a3..64713e47330f4de18cadcebb8c8ac43340992251 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_file_package_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_file_package_test.cpp @@ -177,7 +177,7 @@ void DistributedDBFilePackageTest::TearDown(void) * @tc.name: PackageFileTest001 * @tc.desc: Test file package and unpack functions. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest001, TestSize.Level1) @@ -195,7 +195,7 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest001, TestSize.Level1) * @tc.name: PackageFileTest002 * @tc.desc: Test file package if source path is not exist. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest002, TestSize.Level1) @@ -209,7 +209,7 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest002, TestSize.Level1) * @tc.name: PackageFileTest003 * @tc.desc: Test file package if result path is not exist. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest003, TestSize.Level1) @@ -223,7 +223,7 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest003, TestSize.Level1) * @tc.name: PackageFileTest004 * @tc.desc: Test file package if source path is empty. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest004, TestSize.Level1) @@ -249,7 +249,7 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest004, TestSize.Level1) * @tc.name: PackageFileTest005 * @tc.desc: Test file unpack if source file is not exist. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest005, TestSize.Level1) @@ -263,7 +263,7 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest005, TestSize.Level1) * @tc.name: PackageFileTest006 * @tc.desc: Test file unpack if result path is not exist. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest006, TestSize.Level1) @@ -280,7 +280,7 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest006, TestSize.Level1) * @tc.name: PackageFileTest007 * @tc.desc: Test file unpack if magic check failed. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest007, TestSize.Level1) @@ -304,7 +304,7 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest007, TestSize.Level1) * @tc.name: PackageFileTest008 * @tc.desc: Test file unpack if checksum check failed. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest008, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_multi_ver_vacuum_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_multi_ver_vacuum_test.cpp index d6d3e570ef4b41131c73a1bce26486193a141ac3..cf57108b10b66d8927d97e2a2ebe0a6150277ae6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_multi_ver_vacuum_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_multi_ver_vacuum_test.cpp @@ -51,7 +51,7 @@ namespace { bool CheckVacuumTaskStatus(const MultiVerVacuum &inVacuum, const string &inDbIdentifier, VacuumTaskStatus expectStatus, uint8_t repeatLimit = 5, uint32_t repeatInterval = 100) // 5 times, 100 ms { - return RepeatCheckAsyncResult([inVacuum, inDbIdentifier, expectStatus]()->bool { + return RepeatCheckAsyncResult([&inVacuum, &inDbIdentifier, expectStatus]()->bool { VacuumTaskStatus outStatus = VacuumTaskStatus::RUN_WAIT; int errCode = inVacuum.QueryStatus(inDbIdentifier, outStatus); return errCode == E_OK && outStatus == expectStatus; @@ -89,7 +89,7 @@ void DistributedDBMultiVerVacuumTest::TearDown() * @tc.name: SingleTaskNormalStatusSwitch001 * @tc.desc: Test status switch for single task under normal operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch001, TestSize.Level2) @@ -156,7 +156,7 @@ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch001, TestS * @tc.name: SingleTaskNormalStatusSwitch002 * @tc.desc: Test status switch for single task under normal operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch002, TestSize.Level2) @@ -223,7 +223,7 @@ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch002, TestS * @tc.name: SingleTaskNormalStatusSwitch003 * @tc.desc: Test status switch for single task under normal operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch003, TestSize.Level2) @@ -289,7 +289,7 @@ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch003, TestS * @tc.name: SingleTaskNormalStatusSwitch004 * @tc.desc: Test status switch for single task under normal operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch004, TestSize.Level2) @@ -347,7 +347,7 @@ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch004, TestS * @tc.name: SingleTaskAbnormalStatusSwitch001 * @tc.desc: Test status switch for single task under abnormal operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskAbnormalStatusSwitch001, TestSize.Level2) @@ -486,7 +486,7 @@ namespace { * @tc.name: SingleTaskConcurrentStatusSwitch001 * @tc.desc: Test status switch for single task under Concurrent operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskConcurrentStatusSwitch001, TestSize.Level2) @@ -542,7 +542,7 @@ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskConcurrentStatusSwitch001, T * @tc.name: SingleTaskWriteHandleOccupy001 * @tc.desc: Test write handle occupy for single task under normal operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskWriteHandleOccupy001, TestSize.Level2) @@ -602,7 +602,7 @@ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskWriteHandleOccupy001, TestSi * @tc.name: MultipleTaskNormalStatusSwitch001 * @tc.desc: Test status switch for multiple task under normal operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, MultipleTaskNormalStatusSwitch001, TestSize.Level1) @@ -673,7 +673,7 @@ HWTEST_F(DistributedDBMultiVerVacuumTest, MultipleTaskNormalStatusSwitch001, Tes * @tc.name: MultipleTaskNormalStatusSwitch002 * @tc.desc: Test status switch for multiple task under normal operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, MultipleTaskNormalStatusSwitch002, TestSize.Level2) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_query_object_helper_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_query_object_helper_test.cpp index 8b987e9ba90f367d169827d73f9a38a145e2c506..5d07611eb6f15c55891f49429751d458c681ce7c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_query_object_helper_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_query_object_helper_test.cpp @@ -110,7 +110,7 @@ void DistributedDBQueryObjectHelperTest::TearDown(void) * @tc.name: Query001 * @tc.desc: Check the legal single query operation to see if the generated container is correct * @tc.type: FUNC - * @tc.require: AR000DR9K6 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBQueryObjectHelperTest, Query001, TestSize.Level1) @@ -161,7 +161,7 @@ HWTEST_F(DistributedDBQueryObjectHelperTest, Query001, TestSize.Level1) * @tc.name: Query002 * @tc.desc: Check for illegal query conditions can not get helper transfer to sql * @tc.type: FUNC - * @tc.require: AR000DR9K6 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBQueryObjectHelperTest, Query002, TestSize.Level1) @@ -193,7 +193,7 @@ HWTEST_F(DistributedDBQueryObjectHelperTest, Query002, TestSize.Level1) * @tc.name: Query003 * @tc.desc: Check combination condition transfer to sql * @tc.type: FUNC - * @tc.require: AR000DR9K6 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBQueryObjectHelperTest, Query003, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_rdb_collaboration_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_rdb_collaboration_test.cpp index ee47387e489cdb79696c89a879cf6f789fff2611..ef6c883f2a92442e81317f543d77a1e9c7cdae9e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_rdb_collaboration_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_rdb_collaboration_test.cpp @@ -195,7 +195,7 @@ void DistributedDBRDBCollaborationTest::CloseDb() * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema001, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema001, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -236,7 +236,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema001, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema002, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema002, TestSize.Level1) { /** * @tc.steps: step1. Create cloud table in SPLIT_BY_DEVICE @@ -265,7 +265,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema002, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema003, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema003, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -374,7 +374,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema005, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema006, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema006, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -456,7 +456,7 @@ std::string GetTriggerSql(const std::string &tableName, const std::string &trigg * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema007, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema007, TestSize.Level1) { /** * @tc.steps: step1. Prepare db @@ -510,7 +510,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema007, TestSize.Level0) * @tc.require: * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema008, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema008, TestSize.Level1) { /** * @tc.steps: step1. Prepare db @@ -645,7 +645,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema012, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema013, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema013, TestSize.Level1) { /** * @tc.steps: step1. Create device table @@ -690,7 +690,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema013, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema014, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema014, TestSize.Level1) { /** * @tc.steps: step1. Create auto increment table and specified pk, distributed schema without not null field @@ -743,7 +743,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema014, TestSize.Level0) * @tc.require: * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema015, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema015, TestSize.Level1) { /** * @tc.steps: step1. Prepare db, tableMode is COLLABORATION @@ -841,7 +841,7 @@ int GetHashKey(sqlite3 *db, const std::string &tableName, std::vectorSetDistributedSchema(schema2), OK); + EXPECT_EQ(delegate_->SetDistributedSchema(schema2, true), OK); std::vector newHashKeys2; EXPECT_EQ(GetHashKey(db_, tableName, newHashKeys2), E_OK); ASSERT_EQ(newHashKeys2.size(), static_cast(dataCount)); @@ -1048,7 +1048,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema021, TestSize.Level1) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema022, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema022, TestSize.Level1) { /** * @tc.steps: step1. Create device table named keywords. @@ -1088,13 +1088,13 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema023, TestSize.Level0) /** * @tc.steps: step2. decrease tables of input parameter to set distributed schema - * @tc.expected: step2. return DISTRIBUTED_FIELD_DECREASE + * @tc.expected: step2. return OK */ distributedSchema = {2, {{CLOUD_SYNC_TABLE, {{"pk", true}, {"int_field2", false}}}}}; - EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), DISTRIBUTED_FIELD_DECREASE); - distributedSchema = {2, {{DEVICE_SYNC_TABLE, {{"pk", true}, {"int_field1", true}}}, + EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK); + distributedSchema = {3, {{DEVICE_SYNC_TABLE, {{"pk", true}, {"int_field1", true}}}, {DEVICE_SYNC_TABLE_UPGRADE, {{"pk", true}, {"int_field2", false}}}}}; - EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), DISTRIBUTED_FIELD_DECREASE); + EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK); } /** @@ -1104,7 +1104,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema023, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema024, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema024, TestSize.Level1) { /** * @tc.steps: step1. set distributed schema for the first time @@ -1143,6 +1143,108 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema024, TestSize.Level0) EXPECT_EQ(res, OVER_MAX_LIMITS); } +/** + * @tc.name: SetSchema025 + * @tc.desc: Test SetDistributedSchema with isForceUpgrade. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema025, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create device table and cloud table in COLLABORATION + * @tc.expected: step1.ok + */ + ASSERT_NO_FATAL_FAILURE(InitDelegate()); + EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK); + DistributedSchema distributedSchema1 = {1, {{DEVICE_SYNC_TABLE, {{"pk", true}, {"int_field1", true}}}}}; + EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema1), OK); + /** + * @tc.steps: step2. Set distributed schema with isForceUpgrade + * @tc.expected: step2.ok + */ + DistributedSchema distributedSchema2 = {2, {{DEVICE_SYNC_TABLE, {{"pk", true}}}}}; + EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema2, true), OK); +} + +/** + * @tc.name: SetSchema026 + * @tc.desc: Test SetDistributedSchema with conflict log. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema026, TestSize.Level0) +{ + /** + * @tc.steps: step1. Prepare db, tableMode is COLLABORATION + * @tc.expected: step1.ok + */ + ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION)); + std::string createSql = "CREATE TABLE IF NOT EXISTS table_pk_int(integer_field INTEGER PRIMARY KEY AUTOINCREMENT," + "int_field INT UNIQUE);"; + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, createSql), E_OK); + EXPECT_EQ(delegate_->CreateDistributedTable("table_pk_int", TableSyncType::DEVICE_COOPERATION), OK); + /** + * @tc.steps: step2. Set Distributed Schema + * @tc.expected: step2. return OK + */ + DistributedSchema distributedSchema = {1, { + {"table_pk_int", { + {"integer_field", true}, + {"int_field", true} + }}} + }; + EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK); + /** + * @tc.steps: step3. Local insert (1, 2), (2, 1) and delete (1, 2) + * @tc.expected: step3. return OK + */ + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, "INSERT INTO table_pk_int VALUES(1, 2)"), E_OK); + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, "INSERT INTO table_pk_int VALUES(2, 1)"), E_OK); + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, "DELETE FROM table_pk_int WHERE integer_field = 1"), E_OK); + /** + * @tc.steps: step4. Upgrade Distributed Schema and mark int_field specified + * @tc.expected: step4. return OK + */ + distributedSchema = {2, { + {"table_pk_int", { + {"integer_field", false}, + {"int_field", true, true} + }}} + }; + EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema, true), OK); +} + +/** + * @tc.name: SetSchema027 + * @tc.desc: Test two table create distributed table. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema027, TestSize.Level0) +{ + /** + * @tc.steps: step1. Prepare db create two table + * @tc.expected: step1.ok + */ + ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION)); + std::string createSql = "CREATE TABLE IF NOT EXISTS table1(integer_field INTEGER PRIMARY KEY AUTOINCREMENT," + "int_field INT UNIQUE);"; + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, createSql), E_OK); + EXPECT_EQ(delegate_->CreateDistributedTable("table1", TableSyncType::DEVICE_COOPERATION), OK); + createSql = "CREATE TABLE IF NOT EXISTS table2(integer_field INTEGER PRIMARY KEY AUTOINCREMENT," + "int_field INT UNIQUE);"; + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, createSql), E_OK); + EXPECT_EQ(delegate_->CreateDistributedTable("table2", TableSyncType::DEVICE_COOPERATION), OK); + auto table1 = std::string(DBConstant::RELATIONAL_PREFIX).append("table1_log"); + auto table2 = std::string(DBConstant::RELATIONAL_PREFIX).append("table2_log"); + RelationalTestUtils::CheckIndexCount(db_, table1, 3u); // 3 is index count + RelationalTestUtils::CheckIndexCount(db_, table2, 3u); // 3 is index count +} + /** * @tc.name: NormalSync001 * @tc.desc: Test set distributed schema and sync. @@ -1150,7 +1252,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema024, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync001, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync001, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1185,7 +1287,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync001, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync002, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync002, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1231,7 +1333,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync002, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync003, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync003, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1303,7 +1405,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync004, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync005, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync005, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1359,7 +1461,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync005, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync006, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync006, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1406,7 +1508,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync006, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync007, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync007, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1460,7 +1562,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync007, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync008, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync008, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1506,7 +1608,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync008, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync009, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync009, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1601,7 +1703,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync010, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync011, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync011, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1636,7 +1738,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync011, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync012, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync012, TestSize.Level1) { /** * @tc.steps: step1. Create auto increment table and unique index @@ -1698,7 +1800,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync012, TestSize.Level0) * @tc.require: * @tc.author: lg */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync013, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync013, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1752,7 +1854,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync013, TestSize.Level0) * @tc.require: * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync014, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync014, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1813,7 +1915,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync014, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync015, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync015, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1881,7 +1983,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync015, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync016, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync016, TestSize.Level1) { /** * @tc.steps: step1. Prepare db, tableMode is COLLABORATION @@ -1922,7 +2024,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync016, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync017, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync017, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1975,7 +2077,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync017, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync018, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync018, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -2030,7 +2132,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync018, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync019, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync019, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -2072,7 +2174,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync019, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync020, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync020, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -2111,7 +2213,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync020, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync021, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync021, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -2165,7 +2267,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync021, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync022, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync022, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -2226,7 +2328,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync022, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync023, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync023, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -2277,7 +2379,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync023, TestSize.Level0) * @tc.require: * @tc.author: lg */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync024, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync024, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -2340,7 +2442,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync024, TestSize.Level0) * @tc.require: * @tc.author: liuhongyang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync025, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync025, TestSize.Level1) { /** * @tc.steps: step1. Create SPLIT_BY_DEVICE tables @@ -2417,7 +2519,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync025, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetStoreConfig001, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetStoreConfig001, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in SPLIT_BY_DEVICE @@ -2489,6 +2591,48 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetStoreConfig003, TestSize.Level0) EXPECT_EQ(delegate_->SetStoreConfig({DistributedTableMode::SPLIT_BY_DEVICE}), NOT_SUPPORT); } +/** + * @tc.name: SetStoreConfig004 + * @tc.desc: Test properties for concurrent get and set operations + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBRDBCollaborationTest, SetStoreConfig004, TestSize.Level2) +{ + /** + * @tc.steps: step1. Create device table and cloud table in SPLIT_BY_DEVICE + * @tc.expected: step1.ok + */ + ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::SPLIT_BY_DEVICE)); + /** + * @tc.steps: step2. Set store config. + * @tc.expected: step2.ok + */ + EXPECT_EQ(delegate_->SetStoreConfig({DistributedTableMode::COLLABORATION}), OK); + auto schema = GetSchema(); + auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true); + deviceB_->SetDistributedSchema(distributedSchema); + EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK); + EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK); + /** + * @tc.steps: step3. check for concurrent interface calls + * @tc.expected: step3.ok + */ + std::thread t1([this, distributedSchema]() { + for (size_t i = 0; i < 10000; i++) { + EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK); + } + }); + std::thread t2([this, distributedSchema]() { + for (size_t i = 0; i < 10000; i++) { + EXPECT_EQ(delegate_->SetStoreConfig({DistributedTableMode::COLLABORATION}), OK); + } + }); + t1.join(); + t2.join(); +} + /** * @tc.name: InvalidSync001 * @tc.desc: Test remote set empty distributed schema and sync. @@ -2496,7 +2640,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetStoreConfig003, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRDBCollaborationTest, InvalidSync001, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, InvalidSync001, TestSize.Level1) { /** * @tc.steps: step1. Remote device set empty distributed schema @@ -2655,7 +2799,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, InvalidSync004, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, InvalidSync005, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, InvalidSync005, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp index 237415dfa9a84989480e61dddb1632fde59be613..24dfac7986002615e8a881963a7b74824f50c971 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp @@ -95,7 +95,8 @@ void CreateLogTable(const std::string &tableName) sqlite3 *db = nullptr; ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); auto tableManager = - LogTableManagerFactory::GetTableManager(DistributedTableMode::COLLABORATION, TableSyncType::CLOUD_COOPERATION); + LogTableManagerFactory::GetTableManager(table, DistributedTableMode::COLLABORATION, + TableSyncType::CLOUD_COOPERATION); int errCode = tableManager->CreateRelationalLogTable(db, table); EXPECT_EQ(errCode, E_OK); sqlite3_close(db); @@ -470,6 +471,50 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, MetaDataTest002, TestS EXPECT_EQ(g_cloudStore->GetMetaData(maxKey, value), -E_INVALID_ARGS); } +/** + * @tc.name: MetaDataTest003 + * @tc.desc: The GetMetaData concurrent execute + * @tc.type: FUNC + * @tc.require: + * @tc.author: tankaisheng + */ +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, MetaDataTest003, TestSize.Level0) +{ + /** + * @tc.steps: step1. put data + * @tc.expected: OK. + */ + const std::string str(DBConstant::MAX_KEY_SIZE, 'k'); + const Key key(str.begin(), str.end()); + EXPECT_EQ(g_cloudStore->PutMetaData(key, VALUE_2), E_OK); + + /** + * @tc.steps: step2. concurrent execute get data + * @tc.expected: OK. + */ + const int threadCount = 10; + std::vector threads; + std::vector results(threadCount); + + auto worker = [](ICloudSyncStorageInterface* cloudStore, const Key& key, std::vector& results, int index) { + Value value; + EXPECT_EQ(cloudStore->GetMetaData(key, value), E_OK); + results[index] = value; + }; + + for (int i = 0; i < threadCount; ++i) { + threads.emplace_back(worker, g_cloudStore, key, std::ref(results), i); + } + + for (auto& thread : threads) { + thread.join(); + } + + for (const auto& value : results) { + EXPECT_EQ(value, VALUE_2); + } +} + /** * @tc.name: TransactionTest001 * @tc.desc: No write transaction in the current store, meta interface can called @@ -614,7 +659,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, TransactionTest004, Te * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount001, TestSize.Level1) { /** * @tc.steps: Table does not exist @@ -648,7 +693,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount001, Tes * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount002, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount002, TestSize.Level1) { CreateLogTable(g_tableName); int64_t insCount = 100; @@ -657,11 +702,9 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount002, Tes int64_t resCount = 0; /** - * @tc.steps: GetUploadCount must be called under transaction - * @tc.expected: return -E_TRANSACT_STATE. + * @tc.steps: GetUploadCount can be called under read transaction + * @tc.expected: return -E_OK. */ - EXPECT_EQ(g_storageProxy->GetUploadCount(g_tableName, g_startTime, false, resCount), -E_TRANSACT_STATE); - int timeOffset = 30; EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); EXPECT_EQ(g_storageProxy->GetUploadCount(g_tableName, g_startTime + timeOffset, false, resCount), E_OK); @@ -687,7 +730,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount002, Tes * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount003, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount003, TestSize.Level1) { CreateLogTable(g_tableName); int64_t insCount = 100; @@ -696,11 +739,9 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount003, Tes int64_t resCount = 0; /** - * @tc.steps: GetUploadCount must be called under transaction - * @tc.expected: return -E_TRANSACT_STATE. + * @tc.steps: GetUploadCount can be called under transaction + * @tc.expected: return E_OK. */ - EXPECT_EQ(g_storageProxy->GetUploadCount(g_tableName, g_startTime, false, resCount), -E_TRANSACT_STATE); - EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); EXPECT_EQ(g_storageProxy->GetUploadCount(g_tableName, g_startTime, false, resCount), E_OK); EXPECT_EQ(resCount, insCount); @@ -761,7 +802,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount004, Tes * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid001, TestSize.Level1) { CreateLogTable(g_tableName); int64_t insCount = 100; @@ -847,7 +888,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid001, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData003, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData003, TestSize.Level1) { CreateLogTable(g_tableName); int64_t insCount = 1024; @@ -879,7 +920,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData003, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData004, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData004, TestSize.Level1) { CreateLogTable(g_tableName); int64_t insCount = 10; @@ -906,6 +947,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData004, TestS EXPECT_EQ(asserts->second.index(), static_cast(TYPE_INDEX)); } EXPECT_EQ(g_storageProxy->Commit(), E_OK); + EXPECT_EQ(g_storageProxy->ReleaseContinueToken(token), E_OK); } /** @@ -915,7 +957,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData004, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData005, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData005, TestSize.Level1) { CreateLogTable(g_tableName); int64_t insCount = 1024; @@ -935,7 +977,8 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData005, TestS * @tc.steps: GetCloudDataNext after the transaction ends, token will released internally * @tc.expected: return -E_INVALID_DB. */ - ASSERT_EQ(g_cloudStore->GetCloudDataNext(token, cloudSyncData), -E_INVALID_DB); + ASSERT_EQ(g_cloudStore->GetCloudDataNext(token, cloudSyncData), -E_UNFINISHED); + EXPECT_EQ(g_storageProxy->ReleaseContinueToken(token), E_OK); } /** @@ -945,7 +988,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData005, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData006, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData006, TestSize.Level1) { /** * @tc.steps:step1. Init data and set asset status to invalid num @@ -970,6 +1013,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData006, TestS EXPECT_EQ(g_storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); ASSERT_EQ(g_storageProxy->GetCloudData(g_tableName, g_startTime, token, cloudSyncData), -E_CLOUD_ERROR); EXPECT_EQ(g_storageProxy->Rollback(), E_OK); + EXPECT_EQ(g_storageProxy->ReleaseContinueToken(token), E_OK); } /** @@ -979,7 +1023,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData006, TestS * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData008, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData008, TestSize.Level1) { /** * @tc.steps:step1. table1 @@ -1027,6 +1071,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData008, TestS std::vector cloudGid; EXPECT_EQ(g_storageProxy->GetCloudGid(obj, false, false, cloudGid), E_OK); EXPECT_EQ(g_storageProxy->Commit(), E_OK); + EXPECT_EQ(g_storageProxy->ReleaseContinueToken(token), E_OK); } /** @@ -1036,7 +1081,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData008, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetInfoByPrimaryKeyOrGid001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetInfoByPrimaryKeyOrGid001, TestSize.Level1) { int64_t insCount = 100; int64_t photoSize = 10; @@ -1094,7 +1139,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetInfoByPrimaryKeyOrG EXPECT_EQ(g_storageProxy->Commit(), E_OK); } -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncData001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncData001, TestSize.Level1) { int64_t insCount = 10; int64_t photoSize = 10; @@ -1111,9 +1156,10 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncData001, T CloudSyncData cloudSyncData; ASSERT_EQ(g_storageProxy->GetCloudData(g_tableName, 0L, token, cloudSyncData), E_OK); EXPECT_EQ(g_storageProxy->Commit(), E_OK); + EXPECT_EQ(g_storageProxy->ReleaseContinueToken(token), E_OK); } -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset001, TestSize.Level1) { int64_t insCount = 10; int64_t photoSize = 10; @@ -1127,7 +1173,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset001, Tes fillCloudAssetTest(insCount, AssetStatus::ABNORMAL, true); } -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset002, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset002, TestSize.Level1) { int64_t insCount = 10; int64_t photoSize = 10; @@ -1188,7 +1234,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset002, Tes * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset003, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset003, TestSize.Level1) { int64_t insCount = 2; int64_t photoSize = 10; @@ -1240,7 +1286,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset003, Tes * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset004, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset004, TestSize.Level1) { int64_t insCount = 2; int64_t photoSize = 10; @@ -1395,7 +1441,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, CalPrimaryKeyHash002, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudVersion001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudVersion001, TestSize.Level1) { /** * @tc.steps: step1. init data @@ -1464,7 +1510,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudVersion001, T * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncVersion001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncVersion001, TestSize.Level1) { /** * @tc.steps: step1. table type is shareTable, but downloadData is not contains version @@ -1506,7 +1552,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncVersion001 * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncVersion002, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncVersion002, TestSize.Level1) { /** * @tc.steps: step1. table type is shareTable, but downloadData is not contains version @@ -1536,7 +1582,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncVersion002 EXPECT_EQ(g_storageProxy->Commit(), E_OK); } -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, getAsset001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, getAsset001, TestSize.Level1) { /** * @tc.steps: step1. both gid and hashKey are empty @@ -1596,7 +1642,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, getAsset001, TestSize. EXPECT_EQ(g_storageProxy->Commit(), E_OK); } -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, getAsset002, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, getAsset002, TestSize.Level1) { /** * @tc.steps: step1. hashKey is 2, or gid is 4 @@ -1648,7 +1694,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, getAsset002, TestSize. * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData007, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData007, TestSize.Level1) { /** * @tc.steps:step1. Init data and set asset status to abnormal @@ -1684,7 +1730,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData007, TestS * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, ContainAssetsTable001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, ContainAssetsTable001, TestSize.Level1) { ASSERT_NE(g_storageProxy, nullptr); EXPECT_FALSE(g_storageProxy->IsExistTableContainAssets()); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_encrypted_db_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_encrypted_db_test.cpp index f1321ccd2bd9cf116515418f031827820349907b..7a155c9d0d3a5903112553a43bc74a1de6d0cc9a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_encrypted_db_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_encrypted_db_test.cpp @@ -147,7 +147,7 @@ void DistributedDBRelationalEncryptedDbTest::TearDown(void) * @tc.name: OpenEncryptedDBWithoutPasswd_001 * @tc.desc: Open encrypted db without password in collaboration mode. * @tc.type: FUNC - * @tc.require: AR000H68LL + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithoutPasswdInCollMode_001, TestSize.Level1) @@ -181,7 +181,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithoutPasswdInC * @tc.name: OpenEncryptedDBWithoutPasswdInSplitMode_001 * @tc.desc: Open encrypted db without password in split mode. * @tc.type: FUNC - * @tc.require: AR000H68LL + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithoutPasswdInSplitMode_001, TestSize.Level1) @@ -215,7 +215,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithoutPasswdInS * @tc.name: OpenEncryptedDBWithPasswdInSplitMode_001 * @tc.desc: Open encrypted db with password in split mode. * @tc.type: FUNC - * @tc.require: AR000H68LL + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithPasswdInSplitMode_001, TestSize.Level1) @@ -273,7 +273,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithPasswdInSpli * @tc.name: OpenEncryptedDBWithInvalidParameters_001 * @tc.desc: Open encrypted db with invalid parameters in split mode. * @tc.type: FUNC - * @tc.require: AR000H68LL + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithInvalidParameters_001, TestSize.Level1) @@ -317,7 +317,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithInvalidParam * @tc.name: OpenEncryptedDBWithCustomizedIterTimes_001 * @tc.desc: Open encrypted db with customized iterate times. * @tc.type: FUNC - * @tc.require: AR000H68LL + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithCustomizedIterTimes_001, TestSize.Level1) @@ -375,7 +375,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithCustomizedIt * @tc.name: RekeyAfterOpenStore_001 * @tc.desc: Rekey after open store. * @tc.type: FUNC - * @tc.require: AR000H68LL + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RekeyAfterOpenStore_001, TestSize.Level1) @@ -404,7 +404,8 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RekeyAfterOpenStore_001, TestSi EXPECT_EQ(g_mgr.OpenStore(g_storePath, g_storeID, option1, g_delegate), DBStatus::OK); ASSERT_NE(g_delegate, nullptr); ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName), DBStatus::OK); - + EXPECT_EQ(g_mgr.CloseStore(g_delegate), DBStatus::OK); + g_delegate = nullptr; std::thread t1([db] { std::string sql = "PARGMA rekey=" + REKEY_KEY; EXPECT_EQ(sqlite3_rekey(db, REKEY_KEY.data(), REKEY_KEY.size()), SQLITE_OK); @@ -412,22 +413,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RekeyAfterOpenStore_001, TestSi t1.join(); /** - * @tc.steps: step3. Get sync data. - * @tc.expected: Failed. - */ - auto store = GetRelationalStore(); - ASSERT_NE(store, nullptr); - ContinueToken token = nullptr; - QueryObject query(Query::Select(g_tableName)); - std::vector entries; - EXPECT_NE(store->GetSyncData(query, SyncTimeRange {}, DataSizeSpecInfo {}, token, entries), E_OK); - - RefObject::DecObjRef(g_store); - g_mgr.CloseStore(g_delegate); - g_delegate = nullptr; - - /** - * @tc.steps: step4. Open store with new key. + * @tc.steps: step3. Open store with new key. * @tc.expected: Succeed. */ option1.passwd = g_rekeyPasswd; @@ -436,11 +422,14 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RekeyAfterOpenStore_001, TestSi ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName), DBStatus::OK); /** - * @tc.steps: step5. Get sync data. + * @tc.steps: step4. Get sync data. * @tc.expected: Succeed. */ - store = GetRelationalStore(); + auto store = GetRelationalStore(); ASSERT_NE(store, nullptr); + ContinueToken token = nullptr; + QueryObject query(Query::Select(g_tableName)); + std::vector entries; EXPECT_EQ(store->GetSyncData(query, SyncTimeRange {}, DataSizeSpecInfo {}, token, entries), E_OK); FreeEntires(entries); sqlite3_close(db); @@ -451,7 +440,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RekeyAfterOpenStore_001, TestSi * @tc.name: OpenEncryptedDBWithDifferentPasswd_001 * @tc.desc: Open encrypted db with different password in split mode. * @tc.type: FUNC - * @tc.require: AR000H68LL + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithDifferentPasswd_001, TestSize.Level1) @@ -468,6 +457,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithDifferentPas "PRAGMA journal_mode=WAL;" "CREATE TABLE " + g_tableName + "(key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, value INTEGER);"; ExecSqlAndAssertOK(db, sql); + sqlite3_close(db); /** * @tc.steps: step2. Open store. @@ -504,14 +494,13 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithDifferentPas EXPECT_NE(delegate, nullptr); EXPECT_EQ(g_mgr.CloseStore(delegate), DBStatus::OK); - sqlite3_close(db); } /** * @tc.name: RemoteQueryForEncryptedDb_001 * @tc.desc: Exec remote query on encrypted db. * @tc.type: FUNC - * @tc.require: AR000H68LL + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RemoteQueryForEncryptedDb_001, TestSize.Level1) @@ -530,6 +519,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RemoteQueryForEncryptedDb_001, "PRAGMA journal_mode=WAL;" "CREATE TABLE " + g_tableName + "(key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, value INTEGER);"; ExecSqlAndAssertOK(db, sql); + sqlite3_close(db); /** * @tc.steps: step2. Open store and create distributed table. @@ -553,19 +543,23 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RemoteQueryForEncryptedDb_001, /** * @tc.steps: step4. Rekey. */ + EXPECT_EQ(g_mgr.CloseStore(g_delegate), OK); + g_delegate = nullptr; + ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); std::thread t1([db] { std::string sql = "PARGMA rekey=" + REKEY_KEY; EXPECT_EQ(sqlite3_rekey(db, REKEY_KEY.data(), REKEY_KEY.size()), SQLITE_OK); }); t1.join(); - + sqlite3_close(db); + EXPECT_EQ(g_mgr.OpenStore(g_storePath, g_storeID, option, g_delegate), DBStatus::OK); + ASSERT_NE(g_delegate, nullptr); /** * @tc.steps: step5. Remote query. * @tc.expected: Return INVALID_PASSWD_OR_CORRUPTED_DB. */ - EXPECT_EQ(g_delegate->RemoteQuery("deviceA", RemoteCondition {}, invalidTime, result), + EXPECT_NE(g_delegate->RemoteQuery("deviceA", RemoteCondition {}, invalidTime, result), DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB); - sqlite3_close(db); } #endif // RELATIONAL_STORE #endif // OMIT_ENCRYPT diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp index 942d22b953fae9a854a36719c43679a963a8a180..add7db4780511c090d8adf6fd2a319e643ae14b5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp @@ -324,7 +324,7 @@ void DistributedDBRelationalGetDataTest::TearDown(void) * @tc.name: LogTbl1 * @tc.desc: When put sync data to relational store, trigger generate log. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, LogTbl1, TestSize.Level1) @@ -356,7 +356,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, LogTbl1, TestSize.Level1) * @tc.name: GetSyncData1 * @tc.desc: GetSyncData interface * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetSyncData1, TestSize.Level1) @@ -408,7 +408,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetSyncData1, TestSize.Level1) * @tc.name: GetSyncData2 * @tc.desc: GetSyncData interface. For overlarge data(over 4M), ignore it. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetSyncData2, TestSize.Level1) @@ -451,7 +451,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetSyncData2, TestSize.Level1) * @tc.name: GetSyncData3 * @tc.desc: GetSyncData interface. For deleted data. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetSyncData3, TestSize.Level1) @@ -543,7 +543,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetSyncData3, TestSize.Level1) * @tc.name: GetQuerySyncData1 * @tc.desc: GetSyncData interface. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetQuerySyncData1, TestSize.Level1) @@ -586,7 +586,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetQuerySyncData1, TestSize.Level1) * @tc.name: GetQuerySyncData2 * @tc.desc: GetSyncData interface. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetQuerySyncData2, TestSize.Level1) @@ -655,7 +655,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetQuerySyncData2, TestSize.Level1) * @tc.name: GetIncorrectTypeData1 * @tc.desc: GetSyncData and PutSyncDataWithQuery interface. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetIncorrectTypeData1, TestSize.Level1) @@ -745,7 +745,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetIncorrectTypeData1, TestSize.Lev * @tc.name: UpdateData1 * @tc.desc: UpdateData succeed when the table has primary key. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, UpdateData1, TestSize.Level1) @@ -831,7 +831,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, UpdateData1, TestSize.Level1) * @tc.name: UpdateDataWithMulDevData1 * @tc.desc: UpdateData succeed when there is multiple devices data exists. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, UpdateDataWithMulDevData1, TestSize.Level1) @@ -897,7 +897,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, UpdateDataWithMulDevData1, TestSize * @tc.name: MissQuery1 * @tc.desc: Check REMOTE_DEVICE_DATA_MISS_QUERY flag succeed. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, MissQuery1, TestSize.Level1) @@ -1004,7 +1004,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, MissQuery1, TestSize.Level1) * @tc.name: CompatibleData1 * @tc.desc: Check compatibility. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, CompatibleData1, TestSize.Level1) @@ -1091,7 +1091,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, CompatibleData1, TestSize.Level1) * @tc.name: GetDataSortByTime1 * @tc.desc: All query get data sort by time asc. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetDataSortByTime1, TestSize.Level1) @@ -1156,7 +1156,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetDataSortByTime1, TestSize.Level1 * @tc.name: SameFieldWithLogTable1 * @tc.desc: Get query data OK when the table has same field with log table. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, SameFieldWithLogTable1, TestSize.Level1) @@ -1200,7 +1200,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, SameFieldWithLogTable1, TestSize.Le * @tc.name: CompatibleData2 * @tc.desc: Check compatibility. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, CompatibleData2, TestSize.Level1) @@ -1254,7 +1254,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, CompatibleData2, TestSize.Level1) * @tc.name: PutSyncDataConflictDataTest001 * @tc.desc: Check put with conflict sync data. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalGetDataTest, PutSyncDataConflictDataTest001, TestSize.Level1) @@ -1307,7 +1307,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, PutSyncDataConflictDataTest001, Tes * @tc.name: SaveNonexistDevdata1 * @tc.desc: Save non-exist device data and check errCode. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, SaveNonexistDevdata1, TestSize.Level1) @@ -1362,7 +1362,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, SaveNonexistDevdata1, TestSize.Leve * @tc.name: GetMaxTimestamp1 * @tc.desc: Get max timestamp. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetMaxTimestamp1, TestSize.Level1) @@ -1434,7 +1434,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetMaxTimestamp1, TestSize.Level1) * @tc.name: NoPkData1 * @tc.desc: For no pk data. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, NoPkData1, TestSize.Level1) @@ -1528,7 +1528,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, NoPkData1, TestSize.Level1) * @tc.name: GetAfterDropTable1 * @tc.desc: Get data after drop table. * @tc.type: FUNC - * @tc.require: AR000H2QPN + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetAfterDropTable1, TestSize.Level1) @@ -1627,7 +1627,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, SetNextBeginTime001, TestSize.Level * @tc.name: CloseStore001 * @tc.desc: Test Relational Store Close Action. * @tc.type: FUNC - * @tc.require: AR000H2QPN + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalGetDataTest, CloseStore001, TestSize.Level1) @@ -1739,7 +1739,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, ReleaseContinueTokenTest001, TestSi * @tc.name: StopSync001 * @tc.desc: Test Relational Stop Sync Action. * @tc.type: FUNC - * @tc.require: AR000H2QPN + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalGetDataTest, StopSync001, TestSize.Level1) @@ -1780,7 +1780,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, StopSync001, TestSize.Level1) * @tc.name: EraseDeviceWaterMark001 * @tc.desc: Test Relational erase water mark. * @tc.type: FUNC - * @tc.require: AR000H2QPN + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalGetDataTest, EraseDeviceWaterMark001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_remote_query_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_remote_query_test.cpp index 90aa72bfcdf911fcb431cb782cf3a29bfb24f709..bdf6f57ac2dab3ac601aa24ab9f5be941babf97e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_remote_query_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_remote_query_test.cpp @@ -168,7 +168,7 @@ void DistributedDBRelationalRemoteQueryTest::TearDown(void) * @tc.name: NormalQuery1 * @tc.desc: Normal query. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, NormalQuery1, TestSize.Level1) @@ -208,7 +208,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, NormalQuery1, TestSize.Level1) * @tc.name: NormalQuery1 * @tc.desc: test sql len is larger than 100,0000 * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, NormalQuery2, TestSize.Level1) @@ -227,7 +227,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, NormalQuery2, TestSize.Level1) * @tc.name: BoolQuery1 * @tc.desc: Query bool. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, BoolQuery1, TestSize.Level1) @@ -294,7 +294,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, BoolQuery1, TestSize.Level1) * @tc.name: BlobQuery1 * @tc.desc: Query blob. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, BlobQuery1, TestSize.Level1) @@ -341,7 +341,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, BlobQuery1, TestSize.Level1) * @tc.name: InsertQuery1 * @tc.desc: Query with insert statement. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, InsertQuery1, TestSize.Level1) @@ -403,7 +403,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, InsertQuery1, TestSize.Level1) * @tc.name: NonexistentTable1 * @tc.desc: Nonexistent table or column. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, NonexistentTable1, TestSize.Level1) @@ -435,7 +435,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, NonexistentTable1, TestSize.Lev * @tc.name: PreparedStmtSerialize * @tc.desc: Test the serialization and deserialization of PreparedStmt. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, PreparedStmtSerialize, TestSize.Level1) @@ -478,7 +478,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, PreparedStmtSerialize, TestSize * @tc.name: ComplexQuery1 * @tc.desc: Complex query with join or aggregate func. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, ComplexQuery1, TestSize.Level1) @@ -519,7 +519,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, ComplexQuery1, TestSize.Level1) * @tc.name: LargeAmountOfData1 * @tc.desc: Large Amount Of Data. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, LargeAmountOfData1, TestSize.Level1) @@ -572,7 +572,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, LargeAmountOfData1, TestSize.Le * @tc.name: OverSize1 * @tc.desc: Over size. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, OverSize1, TestSize.Level1) @@ -614,7 +614,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, OverSize1, TestSize.Level1) * @tc.name: RemoteQueryForNotDistributedDb * @tc.desc: Not create distributed table, exec remote query. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, RemoteQueryForNotDistributedDb, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_result_set_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_result_set_test.cpp index e3b17420e4525c5f735587933ebe8edd1ac5f21c..53ab0915b65e289c049b98acbdac437511415c0c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_result_set_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_result_set_test.cpp @@ -116,7 +116,7 @@ void DistributedDBRelationalResultSetTest::TearDown(void) * @tc.name: SerializeAndDeserialize * @tc.desc: Serialize and deserialize. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalResultSetTest, SerializeAndDeserialize, TestSize.Level1) @@ -189,7 +189,7 @@ HWTEST_F(DistributedDBRelationalResultSetTest, SerializeAndDeserialize, TestSize * @tc.name: Put * @tc.desc: Test put into result set * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalResultSetTest, Put, TestSize.Level1) @@ -225,7 +225,7 @@ HWTEST_F(DistributedDBRelationalResultSetTest, Put, TestSize.Level1) * @tc.name: EmptyResultSet * @tc.desc: Empty result set. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalResultSetTest, EmptyResultSet, TestSize.Level1) @@ -263,7 +263,7 @@ HWTEST_F(DistributedDBRelationalResultSetTest, EmptyResultSet, TestSize.Level1) * @tc.name: NormalResultSet * @tc.desc: Normal result set. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalResultSetTest, NormalResultSet, TestSize.Level1) @@ -436,4 +436,74 @@ HWTEST_F(DistributedDBRelationalResultSetTest, ResultSetTest002, TestSize.Level0 delete resultSet; } + +/** + * @tc.name: BinlogSupportTest001 + * @tc.desc: Test binlog support API return values as expected + * @tc.type: FUNC + * @tc.require: + * @tc.author: hongyangliu + */ +HWTEST_F(DistributedDBRelationalResultSetTest, BinlogSupportTest001, TestSize.Level0) +{ + EXPECT_EQ(sqlite3_is_support_binlog(nullptr), SQLITE_ERROR); + EXPECT_EQ(sqlite3_is_support_binlog(""), sqlite3_is_support_binlog(" ")); +} + +/** + * @tc.name: CompressSupportTest001 + * @tc.desc: Test sqlite open with different vfs option return values as expected + * @tc.type: FUNC + * @tc.require: + * @tc.author: hongyangliu + */ +HWTEST_F(DistributedDBRelationalResultSetTest, CompressSupportTest001, TestSize.Level0) +{ + sqlite3 *db = nullptr; + uint32_t openOption = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX; + /** + * @tc.steps: step1. sqlite open with both filepath and vfs as null + * @tc.expected: no crash + */ + ASSERT_NO_FATAL_FAILURE(sqlite3_open_v2(nullptr, &db, openOption, nullptr)); + sqlite3_close_v2(db); + db = nullptr; + /** + * @tc.steps: step2. sqlite open with null filepath and random vfs + * @tc.expected: no crash + */ + ASSERT_NO_FATAL_FAILURE(sqlite3_open_v2(nullptr, &db, openOption, "non-exist")); + sqlite3_close_v2(db); + db = nullptr; + /** + * @tc.steps: step3. sqlite open with null filepath and compress vfs + * @tc.expected: no crash + */ + ASSERT_NO_FATAL_FAILURE(sqlite3_open_v2(nullptr, &db, openOption, "compressvfs")); + sqlite3_close_v2(db); + db = nullptr; + /** + * @tc.steps: step4. sqlite open with a regular file with no vfs + * @tc.expected: open ok + */ + EXPECT_EQ(sqlite3_open_v2(g_storePath.c_str(), &db, openOption, nullptr), SQLITE_OK); + sqlite3_close_v2(db); + db = nullptr; + /** + * @tc.steps: step5. sqlite open with a non-whitelist file using compress vfs + * @tc.expected: open ok + */ + std::string nonWhiteDb = g_testDir + "/nonWhiteList.db"; + EXPECT_EQ(sqlite3_open_v2(nonWhiteDb.c_str(), &db, openOption, "compressvfs"), SQLITE_OK); + sqlite3_close_v2(db); + db = nullptr; + /** + * @tc.steps: step6. sqlite open with a whitelist file using compress vfs + * @tc.expected: no crash + */ + std::string whitelistDb = g_testDir + "/test.db"; + ASSERT_NO_FATAL_FAILURE(sqlite3_open_v2(whitelistDb.c_str(), &db, openOption, "compressvfs")); + sqlite3_close_v2(db); + db = nullptr; +} #endif diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_schema_analysis_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_schema_analysis_test.cpp index e96c0eb586bed05b889918f3ce77e8860e26f997..37419b1237e5a1190dac087f1293e9e50bcae49a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_schema_analysis_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_schema_analysis_test.cpp @@ -113,7 +113,7 @@ TableInfo AnalysisTable(const std::string &name, const std::string &sql) * @tc.name: AnalysisTable001 * @tc.desc: Analysis with table which has one primary key * @tc.type: FUNC - * @tc.require: AR000H2PKN + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBRelationalSchemaAnalysisTest, AnalysisTable001, TestSize.Level1) @@ -126,7 +126,7 @@ HWTEST_F(DistributedDBRelationalSchemaAnalysisTest, AnalysisTable001, TestSize.L * @tc.name: AnalysisTable002 * @tc.desc: Analysis with table which has multi primary key * @tc.type: FUNC - * @tc.require: AR000H2PKN + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBRelationalSchemaAnalysisTest, AnalysisTable002, TestSize.Level1) @@ -139,7 +139,7 @@ HWTEST_F(DistributedDBRelationalSchemaAnalysisTest, AnalysisTable002, TestSize.L * @tc.name: AnalysisTable003 * @tc.desc: Analysis with table which has no primary key * @tc.type: FUNC - * @tc.require: AR000H2PKN + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBRelationalSchemaAnalysisTest, AnalysisTable003, TestSize.Level1) @@ -152,7 +152,7 @@ HWTEST_F(DistributedDBRelationalSchemaAnalysisTest, AnalysisTable003, TestSize.L * @tc.name: AnalysisTable003 * @tc.desc: Analysis with table which has no primary key * @tc.type: FUNC - * @tc.require: AR000H2PKN + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBRelationalSchemaAnalysisTest, AnalysisTable004, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_syncable_storage_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_syncable_storage_test.cpp index f6ebd0ae3cc90a2d0192d5cc72f787e3772ec2ab..ba44c7362667ca38338093ec23bffa8cb8474fd6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_syncable_storage_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_syncable_storage_test.cpp @@ -19,6 +19,8 @@ #include "distributeddb_tools_unit_test.h" #include "relational_sync_able_storage.h" #include "sqlite_single_relational_storage_engine.h" +#include "sqlite_relational_store_connection.h" +#include "sqlite_relational_utils.h" #include "sqlite_utils.h" using namespace testing::ext; @@ -120,4 +122,104 @@ HWTEST_F(DistributedDBRelationalSyncableStorageTest, SchemaRefTest001, TestSize. RefObject::DecObjRef(syncAbleStorage); EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); } + +/** + * @tc.name: FuncExceptionTest001 + * @tc.desc: Test the interception expection of the delegate interface when the store is empty. + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBRelationalSyncableStorageTest, FuncExceptionTest001, TestSize.Level1) +{ + auto conn = std::make_shared(nullptr); + EXPECT_EQ(conn->Close(), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->GetIdentifier().size(), 0u); + EXPECT_EQ(conn->CreateDistributedTable("", {}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->RemoveDeviceData(), -E_INVALID_CONNECTION); + +#ifdef USE_DISTRIBUTEDB_CLOUD + EXPECT_EQ(conn->GetCloudSyncTaskCount(), -1); + EXPECT_EQ(conn->DoClean({}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->ClearCloudWatermark({}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->SetCloudDB({}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->PrepareAndSetCloudDbSchema({}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->SetIAssetLoader({}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->SetCloudSyncConfig({}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->Sync({}, {}, 0L), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->GetCloudTaskStatus(0u).errCode, DB_ERROR); +#endif + EXPECT_EQ(conn->RemoveDeviceData({}), -E_INVALID_CONNECTION); + std::vector devices; + Query query; + RelationalStoreConnection::SyncInfo syncInfo{devices, {}, nullptr, query, true}; + EXPECT_EQ(conn->SyncToDevice(syncInfo), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->RegisterLifeCycleCallback({}), -E_INVALID_CONNECTION); + std::shared_ptr resultSet = nullptr; + EXPECT_EQ(conn->RemoteQuery({}, {}, 0u, resultSet), -E_INVALID_CONNECTION); + std::string userId; + std::string appId; + std::string storeId; + EXPECT_EQ(conn->GetStoreInfo(userId, appId, storeId), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->SetTrackerTable({}), -E_INVALID_CONNECTION); + std::vector records; + EXPECT_EQ(conn->ExecuteSql({}, records), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->SetReference({}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->CleanTrackerData({}, 0L), -E_INVALID_CONNECTION); + PragmaData pragmaData; + PragmaCmd cmd = AUTO_SYNC; + EXPECT_EQ(conn->Pragma(cmd, pragmaData), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->UpsertData({}, {}, {}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->SetDistributedDbSchema({}, false), -E_INVALID_CONNECTION); + int32_t count; + EXPECT_EQ(conn->GetDownloadingAssetsCount(count), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->SetTableMode({}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->OperateDataStatus(0u), -E_INVALID_CONNECTION); + conn = nullptr; +} + +/** + * @tc.name: FuncExceptionTest002 + * @tc.desc: Test the interception expection of the delegate interface when the store is empty. + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBRelationalSyncableStorageTest, FuncExceptionTest002, TestSize.Level1) +{ + sqlite3 *db = nullptr; + int64_t timeOffset; + EXPECT_EQ(SQLiteRelationalUtils::GetExistedDataTimeOffset(db, {}, false, timeOffset), -E_INVALID_DB); + std::unique_ptr logMgrPtr = nullptr; + SQLiteRelationalUtils::GenLogParam param; + param.db = db; + EXPECT_EQ(SQLiteRelationalUtils::GeneLogInfoForExistedData({}, {}, logMgrPtr, param), -E_INVALID_DB); + EXPECT_EQ(SQLiteRelationalUtils::SetLogTriggerStatus(db, false), -E_INVALID_DB); + EXPECT_EQ(SQLiteRelationalUtils::InitCursorToMeta(db, false, {}), -E_INVALID_DB); + EXPECT_EQ(SQLiteRelationalUtils::PutKvData(db, false, {}, {}), -E_INVALID_DB); + Value value; + EXPECT_EQ(SQLiteRelationalUtils::GetKvData(db, false, {}, value), -E_INVALID_DB); + EXPECT_EQ(SQLiteRelationalUtils::CreateRelationalMetaTable(db), -E_INVALID_DB); + EXPECT_EQ(SQLiteRelationalUtils::GetCurrentVirtualTime(db).first, -E_INVALID_DB); + int64_t tOffset; + EXPECT_EQ(SQLiteRelationalUtils::GetMetaLocalTimeOffset(db, tOffset), -E_INVALID_DB); + EXPECT_EQ(SQLiteRelationalUtils::OperateDataStatus(db, {}, 0), E_OK); + uint64_t cursor; + EXPECT_EQ(SQLiteRelationalUtils::GetCursor(db, {}, cursor), -E_INVALID_DB); + int64_t count; + EXPECT_EQ(SQLiteRelationalUtils::QueryCount(db, {}, count), -E_INVALID_DB); + + LogInfo logInfo; + EXPECT_EQ(SQLiteRelationalUtils::GetLogInfoPre(nullptr, {}, {}, logInfo), -E_INVALID_ARGS); + DistributedSchema schema; + schema.tables.push_back({STORE_ID, {}}); + schema.tables.push_back({STORE_ID, {}}); + EXPECT_NE(SQLiteRelationalUtils::FilterRepeatDefine(schema).tables.size(), 0u); + EXPECT_EQ(SQLiteRelationalUtils::CheckDistributedSchemaValid({}, {}, false, nullptr), -E_INVALID_ARGS); + auto executor = + std::make_shared(db, true, DistributedTableMode::COLLABORATION); + EXPECT_EQ(SQLiteRelationalUtils::CheckDistributedSchemaValid({}, {}, false, executor.get()), -E_NOT_FOUND); + int32_t localCount = 0; + EXPECT_EQ(executor->GetFlagIsLocalCount("tableName", localCount), -E_INVALID_DB); +} #endif // RELATIONAL_STORE diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_register_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_register_test.cpp index b929172e184e2e58a8466d3694d08f8b4282dfcf..6b5493530539048b9bd98965f82711b6d6b0d8bf 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_register_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_register_test.cpp @@ -122,7 +122,7 @@ void DistributedDBSqliteRegisterTest::TearDown() * @tc.name: JsonExtract001 * @tc.desc: test json_extract_by_path function in sqlite * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBSqliteRegisterTest, JsonExtract001, TestSize.Level1) @@ -143,7 +143,7 @@ HWTEST_F(DistributedDBSqliteRegisterTest, JsonExtract001, TestSize.Level1) * @tc.name: JsonExtract002 * @tc.desc: test json_extract_by_path function in sqlite * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBSqliteRegisterTest, JsonExtract002, TestSize.Level1) @@ -164,7 +164,7 @@ HWTEST_F(DistributedDBSqliteRegisterTest, JsonExtract002, TestSize.Level1) * @tc.name: JsonExtract003 * @tc.desc: test json_extract_by_path function in sqlite * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBSqliteRegisterTest, JsonExtract003, TestSize.Level1) @@ -185,7 +185,7 @@ HWTEST_F(DistributedDBSqliteRegisterTest, JsonExtract003, TestSize.Level1) * @tc.name: CalcHashValue001 * @tc.desc: test calc_hash_key function in sqlite * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBSqliteRegisterTest, CalcHashValue001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_utils_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_utils_test.cpp index e8da4e9f3ad3072fb832efc8d23ee4e47a712cc8..b8fa175c34f8b538746d81c2838afc05c6d7bf9a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_utils_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_utils_test.cpp @@ -18,6 +18,7 @@ #include "distributeddb_tools_unit_test.h" #include "native_sqlite.h" #include "platform_specific.h" +#include "sqlite_cloud_kv_executor_utils.h" #include "sqlite_import.h" #include "sqlite_log_table_manager.h" @@ -386,3 +387,42 @@ HWTEST_F(DistributedDBSqliteUtilsTest, AbnormalBranchErrAfterClose, TestSize.Lev EXPECT_EQ(-SQLITE_MISUSE, SQLiteUtils::GetLogTableVersion(g_db, strSchema)); EXPECT_EQ(-SQLITE_MISUSE, SQLiteUtils::CheckTableExists(g_db, tableName, isEmpty)); } + +/** + * @tc.name: AbnormalSqliteCloudKvExecutorUtilsTest001 + * @tc.desc: Test sqlite cloud kv executor utils abnormal + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBSqliteUtilsTest, AbnormalSqliteCloudKvExecutorUtilsTest001, TestSize.Level1) +{ + SqliteCloudKvExecutorUtils cloudKvObj; + sqlite3 *db = nullptr; + CloudSyncData data; + CloudUploadRecorder recorder; + + uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + std::string fileUrl = g_testDir + "/test.db"; + EXPECT_EQ(sqlite3_open_v2(fileUrl.c_str(), &db, flag, nullptr), SQLITE_OK); + ASSERT_NE(db, nullptr); + + data.isCloudVersionRecord = false; + int ret = cloudKvObj.FillCloudLog({db, true}, OpType::INSERT, data, "", recorder); + EXPECT_EQ(ret, -1); // -1 for table not exist + + std::vector dataVector; + ret = cloudKvObj.GetWaitCompensatedSyncDataPk(db, true, dataVector); + EXPECT_NE(ret, E_OK); + std::vector dataUser; + ret = cloudKvObj.GetWaitCompensatedSyncDataUserId(db, true, dataUser); + EXPECT_NE(ret, E_OK); + ret = cloudKvObj.GetWaitCompensatedSyncData(db, true, dataVector, dataUser); + EXPECT_NE(ret, E_OK); + std::vector gid; + std::string user("USER"); + QuerySyncObject query; + ret = cloudKvObj.QueryCloudGid(db, true, user, query, gid); + EXPECT_NE(ret, E_OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_commit_storage_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_commit_storage_test.cpp index 85c0633d19098af1e56fb6bc0cdf6b120e7c0565..fc3fa50a1ba39cb78cd8c7d00ab2df25ebea4924 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_commit_storage_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_commit_storage_test.cpp @@ -330,7 +330,7 @@ void DistributedDBStorageCommitStorageTest::TearDown(void) * @tc.name: MultiVerCommitStorage001 * @tc.desc: Open a commit storage when it has been opened. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage001, TestSize.Level1) @@ -348,7 +348,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage001, TestSi * @tc.name: MultiVerCommitStorage002 * @tc.desc: Remove a commit storage database, then try to add, delete and query commit, set and get header. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage002, TestSize.Level1) @@ -397,7 +397,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage002, TestSi * @tc.name: MultiVerCommitStorage003 * @tc.desc: Insert a commit to commit storage, and get it. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage003, TestSize.Level1) @@ -423,7 +423,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage003, TestSi * @tc.name: MultiVerCommitStorage004 * @tc.desc: Set header of commit storage, and get it. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage004, TestSize.Level1) @@ -455,7 +455,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage004, TestSi * @tc.name: MultiVerCommitStorage005 * @tc.desc: Delete the header commit, test if it can be get, and get the new header. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage005, TestSize.Level1) @@ -513,7 +513,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage005, TestSi * @tc.name: MultiVerCommitStorage006 * @tc.desc: Add commit with empty commit ID, and it will not be added. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage006, TestSize.Level1) @@ -532,7 +532,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage006, TestSi * @tc.name: MultiVerCommitStorage008 * @tc.desc: Add commit with the same commit ID as its left parent, and it will not be added. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage008, TestSize.Level1) @@ -565,7 +565,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage008, TestSi * @tc.name: MultiVerCommitStorage009 * @tc.desc: Add commit with the same commit ID as its right parent, and it will not be added. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage009, TestSize.Level1) @@ -598,7 +598,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage009, TestSi * @tc.name: MultiVerCommitStorage010 * @tc.desc: Add commit whose left parent and right parent is the same, and it will not be added. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage010, TestSize.Level1) @@ -637,7 +637,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage010, TestSi * @tc.name: MultiVerCommitStorage011 * @tc.desc: Add commit with a non exist left parent, and it will not be added. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage011, TestSize.Level1) @@ -662,7 +662,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage011, TestSi * @tc.name: MultiVerCommitStorage012 * @tc.desc: Add commit with a non exist right parent, and it will not be added. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage012, TestSize.Level1) @@ -687,7 +687,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage012, TestSi * @tc.name: MultiVerCommitStorage013 * @tc.desc: Delete a commit which is not header, and it will not be deleted. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage013, TestSize.Level1) @@ -732,7 +732,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage013, TestSi * @tc.name: MultiVerCommitStorage014 * @tc.desc: Set unexist commit to header, and it will not success. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage014, TestSize.Level1) @@ -745,7 +745,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage014, TestSi * @tc.name: MultiVerCommitStorage015 * @tc.desc: SDetermine whether commit exists * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage015, TestSize.Level1) @@ -760,7 +760,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage015, TestSi * @tc.name: MultiVerCommitStorage016 * @tc.desc: Get latest commit of each device from commit storage * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage016, TestSize.Level1) @@ -790,7 +790,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage016, TestSi * @tc.name: MultiVerCommitStorage017 * @tc.desc: Get commit tree from commit storage by latest commits * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage017, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp index 81dc4b45f954e367acdb13ffc7f8bc6f72f25fea..2db7b5d465212a5f920261ff947fb9ae45676244 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp @@ -130,7 +130,7 @@ void DistributedDBStorageDataOperationTest::TearDown(void) * @tc.name: Insert001 * @tc.desc: Insert a record into a distributed db * @tc.type: FUNC - * @tc.require: AR000CQDV8 AR000CQDVB + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageDataOperationTest, Insert001, TestSize.Level1) @@ -169,7 +169,7 @@ HWTEST_F(DistributedDBStorageDataOperationTest, Insert001, TestSize.Level1) * @tc.name: InsertBatch001 * @tc.desc: Insert some records into a distributed db * @tc.type: FUNC - * @tc.require: AR000CQDV9 AR000CQDVE + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageDataOperationTest, InsertBatch001, TestSize.Level1) @@ -221,7 +221,7 @@ HWTEST_F(DistributedDBStorageDataOperationTest, InsertBatch001, TestSize.Level1) * @tc.name: Clear001 * @tc.desc: Clear some records from a distributed db * @tc.type: FUNC - * @tc.require: AR000BVTO6 AR000CQDVA + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageDataOperationTest, Clear001, TestSize.Level1) @@ -289,7 +289,7 @@ HWTEST_F(DistributedDBStorageDataOperationTest, Clear001, TestSize.Level1) * @tc.name: Delete001 * @tc.desc: Delete a record from a distributed db * @tc.type: FUNC - * @tc.require: AR000CQDVF AR000CQDVB + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageDataOperationTest, Delete001, TestSize.Level1) @@ -367,7 +367,7 @@ HWTEST_F(DistributedDBStorageDataOperationTest, Delete001, TestSize.Level1) * @tc.name: DeleteBatch001 * @tc.desc: Delete some records from a distributed db * @tc.type: FUNC - * @tc.require: AR000CQDVG AR000CQDVB + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageDataOperationTest, DeleteBatch001, TestSize.Level1) @@ -503,7 +503,7 @@ static void CheckRecoverData(const Value &savedValue, std::mapRelease(); +} + +/** + * @tc.name: AbnormalPut001 + * @tc.desc: Insert data when the test table does not exist + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageQuerySyncTest, AbnormalPut001, TestSize.Level1) +{ + std::string path = g_testDir + "/TestQuerySync/" + DBConstant::SINGLE_SUB_DIR + "/main/gen_natural_store.db"; + sqlite3 *db = nullptr; + ASSERT_EQ(sqlite3_open_v2(path.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr), SQLITE_OK); + char *errMsg = nullptr; + EXPECT_EQ(sqlite3_exec(db, "DROP TABLE sync_data", nullptr, nullptr, &errMsg), 0); + IOption option; + option.dataType = IOption::SYNC_DATA; + Key key; + Value value; + DistributedDBToolsUnitTest::GetRandomKeyValue(key); + DistributedDBToolsUnitTest::GetRandomKeyValue(value); + EXPECT_NE(g_connection->Put(option, key, value), E_OK); + sqlite3_close(db); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_register_observer_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_register_observer_test.cpp index 4e9b1588e8385ae294b13b2d036383e9d431fe83..8c9cd0af65d4404757d8d9061958e8ae9ee0f357 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_register_observer_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_register_observer_test.cpp @@ -189,7 +189,7 @@ void DistributedDBStorageRdRegisterObserverTest::TearDown(void) * @tc.name: RegisterObserver001 * @tc.desc: Register a NULL pointer as an observer * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver001, TestSize.Level1) @@ -220,7 +220,7 @@ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver001, TestSi * @tc.name: RegisterObserver010 * @tc.desc: Register an observer for the local sync database change and the local database change of a specified key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver010, TestSize.Level1) @@ -244,7 +244,7 @@ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver010, TestSi * @tc.name: RegisterObserver011 * @tc.desc: Register an observer for the remote sync database change and the local database change of a specified key * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver011, TestSize.Level1) @@ -268,7 +268,7 @@ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver011, TestSi * @tc.name: RegisterObserver012 * @tc.desc: Register an observer for the local sync database change and the local database change of any key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver012, TestSize.Level1) @@ -292,7 +292,7 @@ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver012, TestSi * @tc.name: RegisterObserver013 * @tc.desc: Register an observer for the remote sync database change and the local database change of any key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver013, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_result_and_json_optimize_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_result_and_json_optimize_test.cpp index 68d1d7e82ffbc7644ae3b1e9b1fb204f6b500b72..165df1e969f6a5c1c2f0a8c9f228abd6959c0828 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_result_and_json_optimize_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_result_and_json_optimize_test.cpp @@ -126,7 +126,7 @@ void DistributedDBStorageRdResultAndJsonOptimizeTest::TearDown(void) * @tc.name: ResultSetOpen001 * @tc.desc: Test the RdSingleVerResultSet Open function * @tc.type: FUNC - * @tc.require: AR000F3OP0 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetOpen001, TestSize.Level1) @@ -166,7 +166,7 @@ HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetOpen001, Test * @tc.name: ResultSetGetCount001 * @tc.desc: Test the RdSingleVerResultSet GetCount function. * @tc.type: FUNC - * @tc.require: AR000F3OP0 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetGetCount001, TestSize.Level1) @@ -199,7 +199,7 @@ HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetGetCount001, * @tc.name: ResultSetMoveTo001 * @tc.desc: Test the RdSingleVerResultSet MoveTo And GetPosition function. * @tc.type: FUNC - * @tc.require: AR000F3OP0 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetMoveTo001, TestSize.Level1) @@ -274,7 +274,7 @@ HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetMoveTo001, Te * @tc.name: ResultSetGetEntry001 * @tc.desc: Test the RdSingleVerResultSet GetEntry function. * @tc.type: FUNC - * @tc.require: AR000F3OP0 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetGetEntry001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_test.cpp index 00d14c384ee3fabbba9ea9cde33eb407d695d0e2..eaf1902585930ec6228352009f3b27e47a1be2b8 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_test.cpp @@ -92,7 +92,7 @@ void DistributedDBStorageRdSingleVerNaturalStoreTest::TearDown(void) * @tc.name: SyncDatabaseOperate001 * @tc.desc: To test the function of inserting data of the local device in the synchronization database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate001, TestSize.Level1) @@ -148,7 +148,7 @@ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate001 * @tc.name: SyncDatabaseOperate003 * @tc.desc: test the delete operation in sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate003, TestSize.Level1) @@ -181,7 +181,7 @@ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate003 * @tc.name: SyncDatabaseOperate005 * @tc.desc: test the reading for sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate005, TestSize.Level1) @@ -216,7 +216,7 @@ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate005 * @tc.name: SyncDatabaseOperate006 * @tc.desc: test the get entries for sync database * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate006, TestSize.Level1) @@ -258,5 +258,19 @@ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, ExportBusy001, TestSiz EXPECT_EQ(g_store->Export(g_testDir, password), -E_READ_ONLY); g_store->ReEnableConnection(OperatePerm::NORMAL_WRITE); } + +/** + * @tc.name: GetCloudSyncConfigTest001 + * @tc.desc: Test GetCloudSyncConfig interface of RdSingleVerNaturalStore + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, GetCloudSyncConfigTest001, TestSize.Level1) +{ + ASSERT_NE(g_store, nullptr); + CloudSyncConfig config = g_store->GetCloudSyncConfig(); + EXPECT_EQ(config.isSupportEncrypt, false); +} } #endif // USE_RD_KERNEL \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_testcase.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_testcase.cpp index 9fbd39582aa68281a010b274d5190da41ee6f435..060a6fbfcf459b9ed026bb755825901365287a31 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_testcase.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_testcase.cpp @@ -31,7 +31,7 @@ namespace { * @tc.name: SyncDatabaseOperate001 * @tc.desc: To test the function of inserting data of the local device in the synchronization database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: huangboxin */ void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate001(RdSingleVerNaturalStore *&store, @@ -46,7 +46,7 @@ void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate001 * @tc.name: SyncDatabaseOperate003 * @tc.desc: test the delete operation in sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: huangboxin */ void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate003(RdSingleVerNaturalStore *&store, @@ -61,7 +61,7 @@ void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate003 * @tc.name: SyncDatabaseOperate005 * @tc.desc: test the reading for sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: huangboxin */ void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate005(RdSingleVerNaturalStore *&store, @@ -76,7 +76,7 @@ void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate005 * @tc.name: SyncDatabaseOperate006 * @tc.desc: test the get entries for sync database * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: huangboxin */ void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate006(RdSingleVerNaturalStore *&store, diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp index 296b6f336058c6fcc51ff7d00638ddb4107701cf..5a7669e77fe8b9986287a24d5fd7489a6790b5df 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp @@ -377,7 +377,7 @@ static void SyncDeleteFromDiffDevConflictData(const int deltaTime) * @tc.name: ConflictNotificationTest001 * @tc.desc: Put a non-conflict key and expect no conflict being triggered. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest001, TestSize.Level1) @@ -400,7 +400,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest001, * @tc.name: ConflictNotificationTest002 * @tc.desc: Put a native conflict key and expect native conflict being triggered. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest002, TestSize.Level1) @@ -429,7 +429,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest002, * @tc.name: ConflictNotificationTest003 * @tc.desc: Put a data then delete it. Expect native conflict being triggered. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest003, TestSize.Level1) @@ -458,7 +458,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest003, * @tc.name: ConflictNotificationTest004 * @tc.desc: Sync a data then put a data with the same key. Expect native conflict being triggered. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest004, TestSize.Level1) @@ -491,7 +491,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest004, * @tc.name: ConflictNotificationTest005 * @tc.desc: Get a Sync data then delete it. Expect to see native conflict. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest005, TestSize.Level1) @@ -523,7 +523,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest005, * @tc.name: ConflictNotificationTest006 * @tc.desc: Get a sync data without local key that conflicts with it. Expect to see no conflict. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest006, TestSize.Level1) @@ -546,7 +546,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest006, * @tc.name: ConflictNotificationTest007 * @tc.desc: Sync-sync data conflict. Expect to see foreign conflict and the winner has larger time tag. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest007, TestSize.Level1) @@ -564,7 +564,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest007, * @tc.name: ConflictNotificationTest008 * @tc.desc: Sync-sync data conflict. Expect to see foreign conflict and the winner has larger time tag. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest008, TestSize.Level1) @@ -583,7 +583,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest008, * @tc.desc: Sync a data to the device. Sync another data with the same key and the time tag +DATA_TIME_LAG us. * Expect to see native conflict and the first data being deleted. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest009, TestSize.Level1) @@ -607,7 +607,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest009, * @tc.desc: Sync a data to the device. Sync another data with the same key and the time tag -DATA_TIME_LAG us. * Expect to see native conflict and the second data being deleted. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest010, TestSize.Level1) @@ -630,7 +630,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest010, * @tc.name: ConflictNotificationTest011 * @tc.desc: Sync-sync multi-origin conflict. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest011, TestSize.Level1) @@ -653,7 +653,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest011, * @tc.name: ConflictNotificationTest012 * @tc.desc: Sync-sync multi-origin conflict. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest012, TestSize.Level1) @@ -675,7 +675,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest012, * @tc.name: ConflictNotificationTest013 * @tc.desc: Sync-sync multi-origin conflict with deleted data * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest013, TestSize.Level1) @@ -698,7 +698,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest013, * @tc.name: ConflictNotificationTest014 * @tc.desc: Sync-sync multi-origin conflict with deleted data * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest014, TestSize.Level1) @@ -720,7 +720,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest014, * @tc.name: ConflictNotificationTest015 * @tc.desc: put same record for conflict notification function * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest015, TestSize.Level1) @@ -747,7 +747,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest015, * @tc.name: ConflictNotificationTest016 * @tc.desc: put record for conflict notification function * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest016, TestSize.Level1) @@ -811,7 +811,7 @@ namespace { * @tc.name: ConflictNotificationTest017 * @tc.desc: put record for conflict notification function * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest017, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_observer_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_observer_test.cpp index 6bd851134f6f6e7e2c256810d967c82c333a7ca2..25f811c16dc5dc5e6cd524fdca61858a19446321 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_observer_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_observer_test.cpp @@ -329,7 +329,7 @@ void DistributedDBStorageRegisterObserverTest::TearDown(void) * @tc.name: RegisterObserver001 * @tc.desc: Register a NULL pointer as an observer * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver001, TestSize.Level1) @@ -359,7 +359,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver001, TestSize * @tc.name: RegisterObserver002 * @tc.desc: Register an observer for the local database change of a specified key * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver002, TestSize.Level1) @@ -402,7 +402,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver002, TestSize * @tc.name: RegisterObserver003 * @tc.desc: Register an observer for the local sync database change of a specified key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver003, TestSize.Level1) @@ -445,7 +445,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver003, TestSize * @tc.name: RegisterObserver004 * @tc.desc: Register an observer for the remote sync database change of a specified key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver004, TestSize.Level1) @@ -472,7 +472,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver004, TestSize * @tc.name: RegisterObserver005 * @tc.desc: Register an observer for the sync database change of a specified key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver005, TestSize.Level1) @@ -496,7 +496,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver005, TestSize * @tc.name: RegisterObserver006 * @tc.desc: Register an observer for the local database change of any key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver006, TestSize.Level1) @@ -519,7 +519,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver006, TestSize * @tc.name: RegisterObserver007 * @tc.desc: Register an observer for the local sync database change of any key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver007, TestSize.Level1) @@ -542,7 +542,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver007, TestSize * @tc.name: RegisterObserver008 * @tc.desc: Register an observer for the remote sync database change of any key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver008, TestSize.Level1) @@ -565,7 +565,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver008, TestSize * @tc.name: RegisterObserver009 * @tc.desc: Register an observer for the sync database change of any key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver009, TestSize.Level1) @@ -589,7 +589,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver009, TestSize * @tc.name: RegisterObserver010 * @tc.desc: Register an observer for the local sync database change and the local database change of a specified key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver010, TestSize.Level1) @@ -612,7 +612,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver010, TestSize * @tc.name: RegisterObserver011 * @tc.desc: Register an observer for the remote sync database change and the local database change of a specified key * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver011, TestSize.Level1) @@ -635,7 +635,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver011, TestSize * @tc.name: RegisterObserver012 * @tc.desc: Register an observer for the local sync database change and the local database change of any key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver012, TestSize.Level1) @@ -658,7 +658,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver012, TestSize * @tc.name: RegisterObserver013 * @tc.desc: Register an observer for the remote sync database change and the local database change of any key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver013, TestSize.Level1) @@ -711,7 +711,7 @@ static void PreSyncDataForRegisterObserver014(Timestamp time, vector & * @tc.name: RegisterObserver014 * @tc.desc: Sync multiple records to the sync database * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver014, TestSize.Level1) @@ -781,7 +781,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver014, TestSize * @tc.name: RegisterObserver015 * @tc.desc: Sync multiple records to the sync database, and remove them. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver015, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_resultset_and_json_optimize.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_resultset_and_json_optimize.cpp index 934a502ca85f3669dd934fb63899c55d8c6d2fa9..21c97b5d46bbba492bea98e076bff6208afc1a03 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_resultset_and_json_optimize.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_resultset_and_json_optimize.cpp @@ -127,7 +127,7 @@ void DistributedDBStorageResultAndJsonOptimizeTest::TearDown(void) * @tc.name: ResultSetOpen001 * @tc.desc: Test the SQLiteSingleVerResultSet Open function * @tc.type: FUNC - * @tc.require: AR000F3OP0 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBStorageResultAndJsonOptimizeTest, ResultSetOpen001, TestSize.Level1) @@ -167,7 +167,7 @@ HWTEST_F(DistributedDBStorageResultAndJsonOptimizeTest, ResultSetOpen001, TestSi * @tc.name: ResultSetGetCount001 * @tc.desc: Test the SQLiteSingleVerResultSet GetCount function. * @tc.type: FUNC - * @tc.require: AR000F3OP0 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBStorageResultAndJsonOptimizeTest, ResultSetGetCount001, TestSize.Level1) @@ -200,7 +200,7 @@ HWTEST_F(DistributedDBStorageResultAndJsonOptimizeTest, ResultSetGetCount001, Te * @tc.name: ResultSetMoveTo001 * @tc.desc: Test the SQLiteSingleVerResultSet MoveTo And GetPosition function. * @tc.type: FUNC - * @tc.require: AR000F3OP0 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBStorageResultAndJsonOptimizeTest, ResultSetMoveTo001, TestSize.Level1) @@ -275,7 +275,7 @@ HWTEST_F(DistributedDBStorageResultAndJsonOptimizeTest, ResultSetMoveTo001, Test * @tc.name: ResultSetGetEntry001 * @tc.desc: Test the SQLiteSingleVerResultSet GetEntry function. * @tc.type: FUNC - * @tc.require: AR000F3OP0 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBStorageResultAndJsonOptimizeTest, ResultSetGetEntry001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_natural_store_testcase.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_natural_store_testcase.cpp index 5d7e5381192d67826f3057be6d5c892c9bb57d9d..2298e0e669f3335c4f6d580757747ca9c4aab96d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_natural_store_testcase.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_natural_store_testcase.cpp @@ -40,7 +40,7 @@ namespace { * @tc.name: GetSyncData001 * @tc.desc: To test the function of querying the data in the time stamp range in the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData001(SQLiteSingleVerNaturalStore *&store, @@ -80,7 +80,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData001(SQLiteSin * @tc.name: GetSyncData002 * @tc.desc: Test the function that the database does not query the data in the time stamp range. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData002(SQLiteSingleVerNaturalStore *&store, @@ -119,7 +119,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData002(SQLiteSin * @tc.desc: To test the function of querying data when the timestamp range * in the data obtaining interface is invalid. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData003(SQLiteSingleVerNaturalStore *&store, @@ -162,7 +162,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData003(SQLiteSin * @tc.name: GetSyncData004 * @tc.desc: To the test database Subcon reading, a large number of data records exist in the time stamp range. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData004(SQLiteSingleVerNaturalStore *&store, @@ -226,7 +226,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData004(SQLiteSin * @tc.desc: In the test database, if a large number of data records exist * in the time stamp range, a packet is read successfully. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData005(SQLiteSingleVerNaturalStore *&store, @@ -264,7 +264,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData005(SQLiteSin * @tc.desc: To test the function of reading data when the time stamp range in the database * is greater than the value of blockSize. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData006(SQLiteSingleVerNaturalStore *&store, @@ -301,7 +301,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData006(SQLiteSin * @tc.name: PutSyncData001 * @tc.desc: To test the function of synchronizing the new data of the remote device that synchronizes the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::PutSyncData001(SQLiteSingleVerNaturalStore *&store, @@ -396,7 +396,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::PutSyncData001(SQLiteSin * @tc.desc: To test the function of synchronizing data from the remote device * to the local device after the data is deleted from the remote device. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::PutSyncData002(SQLiteSingleVerNaturalStore *&store, @@ -480,7 +480,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::PutSyncData002(SQLiteSin * @tc.desc: To test the function of synchronizing the mixed data of the added * and deleted data from the remote device to the local device. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::PutSyncData003(SQLiteSingleVerNaturalStore *&store, @@ -558,7 +558,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::PutSyncData003(SQLiteSin * @tc.name: PutMetaData001 * @tc.desc: Test metadata insertion and modification. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::PutMetaData001(SQLiteSingleVerNaturalStore *&store, @@ -571,7 +571,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::PutMetaData001(SQLiteSin * @tc.name: GetMetaData001 * @tc.desc: To test the function of reading the metadata of a key in the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetMetaData001(SQLiteSingleVerNaturalStore *&store, @@ -589,7 +589,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetMetaData001(SQLiteSin * @tc.name: DeleteMetaData001 * @tc.desc: To test the function of deleting the metadata with prefix key in the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteMetaData001(SQLiteSingleVerNaturalStore *&store, @@ -607,7 +607,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteMetaData001(SQLite * @tc.name: GetCurrentMaxTimestamp001 * @tc.desc: To test the function of obtaining the maximum timestamp when a record exists in the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetCurrentMaxTimestamp001(SQLiteSingleVerNaturalStore *&store, @@ -652,7 +652,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetCurrentMaxTimestamp00 * @tc.name: GetCurrentMaxTimestamp002 * @tc.desc: Obtain the maximum timestamp when no record exists in the test record library. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetCurrentMaxTimestamp002(SQLiteSingleVerNaturalStore *&store) @@ -670,7 +670,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetCurrentMaxTimestamp00 * @tc.name: LocalDatabaseOperate001 * @tc.desc: Test the function of inserting data in the local database of the NaturalStore. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::LocalDatabaseOperate001(SQLiteSingleVerNaturalStore *&store, @@ -685,7 +685,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::LocalDatabaseOperate001( * @tc.name: LocalDatabaseOperate002 * @tc.desc: Test the function of deleting data from the local database of the NaturalStore. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::LocalDatabaseOperate002(SQLiteSingleVerNaturalStore *&store, @@ -700,7 +700,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::LocalDatabaseOperate002( * @tc.name: LocalDatabaseOperate003 * @tc.desc: To test the function of reading data from the local database of the NaturalStore. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::LocalDatabaseOperate003(SQLiteSingleVerNaturalStore *&store, @@ -715,7 +715,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::LocalDatabaseOperate003( * @tc.name: SyncDatabaseOperate001 * @tc.desc: To test the function of inserting data of the local device in the synchronization database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate001(SQLiteSingleVerNaturalStore *&store, @@ -730,7 +730,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate001(S * @tc.name: SyncDatabaseOperate002 * @tc.desc: test the put operation after data synced from other devices. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate002(SQLiteSingleVerNaturalStore *&store, @@ -780,7 +780,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate002(S * @tc.name: SyncDatabaseOperate003 * @tc.desc: test the delete operation in sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate003(SQLiteSingleVerNaturalStore *&store, @@ -795,7 +795,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate003(S * @tc.name: SyncDatabaseOperate004 * @tc.desc: test the delete for the data from other devices in sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate004(SQLiteSingleVerNaturalStore *&store, @@ -842,7 +842,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate004(S * @tc.name: SyncDatabaseOperate005 * @tc.desc: test the reading for sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate005(SQLiteSingleVerNaturalStore *&store, @@ -857,7 +857,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate005(S * @tc.name: SyncDatabaseOperate006 * @tc.desc: test the get entries for sync database * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate006(SQLiteSingleVerNaturalStore *&store, @@ -918,7 +918,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate006(S * @tc.name: ClearRemoteData001 * @tc.desc: test the clear data synced from the remote by device. * @tc.type: FUNC - * @tc.require: AR000CIFDA AR000CQS3T + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::ClearRemoteData001(SQLiteSingleVerNaturalStore *&store, @@ -988,7 +988,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::ClearRemoteData001(SQLit * @tc.name: DeleteUserKeyValue001 * @tc.desc: When a user deletes a data record, the system clears the user record. * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue001(SQLiteSingleVerNaturalStore *&store, @@ -1032,7 +1032,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue001(SQ * @tc.name: MemoryDbDeleteUserKeyValue001 * @tc.desc: When a user deletes a data record, the system clears the user record. * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::MemoryDbDeleteUserKeyValue001( @@ -1076,7 +1076,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::MemoryDbDeleteUserKeyVal * @tc.name: DeleteUserKeyValue002 * @tc.desc: After the synchronization library data is deleted locally, add the same key data locally. * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue002(SQLiteSingleVerNaturalStore *&store, @@ -1123,7 +1123,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue002(SQ * @tc.name: DeleteUserKeyValue003 * @tc.desc: After the synchronization database data is deleted locally, the same key data is added from the remote end. * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue003(SQLiteSingleVerNaturalStore *&store, @@ -1206,7 +1206,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue003(SQ * @tc.name: DeleteUserKeyValue004 * @tc.desc: Changes in key after remote delete data syncs to local * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue004(SQLiteSingleVerNaturalStore *&store, @@ -1255,7 +1255,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue004(SQ * @tc.name: MemoryDbDeleteUserKeyValue004 * @tc.desc: Changes in key after remote delete data syncs to local * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::MemoryDbDeleteUserKeyValue004( @@ -1301,7 +1301,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::MemoryDbDeleteUserKeyVal * @tc.name: DeleteUserKeyValue005 * @tc.desc: New unified key data locally after remote delete data syncs to local * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue005(SQLiteSingleVerNaturalStore *&store, @@ -1358,7 +1358,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue005(SQ * @tc.name: MemoryDbDeleteUserKeyValue005 * @tc.desc: New unified key data locally after remote delete data syncs to local * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::MemoryDbDeleteUserKeyValue005( @@ -1413,7 +1413,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::MemoryDbDeleteUserKeyVal * @tc.desc: After the remote delete data is synced to the local, * the same key data is added from the remote other devices * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue006(SQLiteSingleVerNaturalStore *&store, diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_upgrade_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_upgrade_test.cpp index 9603da7effb0208deca25ac63220ce5e763d8fbf..6f87fad2b25d28efa69a4885af08befb3d65deb3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_upgrade_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_upgrade_test.cpp @@ -327,7 +327,7 @@ void DistributedDBStorageSingleVerUpgradeTest::TearDown(void) * @tc.name: UpgradeTest001 * @tc.desc: Test the NbDelegate upgrade from the old version V1. * @tc.type: FUNC - * @tc.require: AR000DPTQ7 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest001, TestSize.Level0) @@ -373,7 +373,7 @@ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest001, TestSize.Leve * @tc.name: UpgradeTest002 * @tc.desc: Test the NbDelegate upgrade from the old version V2. * @tc.type: FUNC - * @tc.require: AR000DPTQ7 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest002, TestSize.Level2) @@ -418,7 +418,7 @@ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest002, TestSize.Leve * @tc.name: UpgradeTest003 * @tc.desc: Test the NbDelegate upgrade from the old version V2 with schema. * @tc.type: FUNC - * @tc.require: AR000DPTQ7 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest003, TestSize.Level2) @@ -480,7 +480,7 @@ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest003, TestSize.Leve * @tc.name: UpgradeTest004 * @tc.desc: Test the NbDelegate upgrade from the old version V2 while secOption from NOT_SET to S3SECE. * @tc.type: FUNC - * @tc.require: AR000DPTQ7 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest004, TestSize.Level2) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp index 1103b7aa1d9fed999a724feef1d5209d4174941e..7e976f91a01fe5ffaecac1f035b9e49901c3c7e5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp @@ -793,7 +793,11 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, PragmaTest001, EXPECT_EQ(g_connection->Pragma(PRAGMA_PUBLISH_LOCAL, nullptr), -E_INVALID_ARGS); EXPECT_EQ(g_connection->Pragma(PRAGMA_GET_DEVICE_IDENTIFIER_OF_ENTRY, nullptr), -E_INVALID_ARGS); EXPECT_EQ(g_connection->Pragma(PRAGMA_SET_MAX_LOG_LIMIT, nullptr), -E_INVALID_ARGS); + uint64_t val = 0x400000ULL; + PragmaData logLimit = static_cast(&val); + EXPECT_EQ(g_connection->Pragma(PRAGMA_SET_MAX_LOG_LIMIT, logLimit), OK); EXPECT_EQ(g_connection->Pragma(PRAGMA_GET_IDENTIFIER_OF_DEVICE, nullptr), -E_INVALID_ARGS); + EXPECT_EQ(g_connection->Pragma(PRAGMA_SET_MAX_LOG_LIMIT, logLimit), OK); /** * @tc.steps: step2. the option is invalid diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_store_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_store_test.cpp index 4f428d68865d350bf01d7c8e69e55f1caefd91b8..95fd5daeb78803163a2b94ed765059479e207bff 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_store_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_store_test.cpp @@ -92,7 +92,7 @@ void DistributedDBStorageSQLiteSingleVerNaturalStoreTest::TearDown(void) * @tc.name: GetSyncData001 * @tc.desc: To test the function of querying the data in the time stamp range in the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData001, TestSize.Level1) @@ -110,7 +110,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData001, Te * @tc.name: GetSyncData002 * @tc.desc: Test the function that the database does not query the data in the time stamp range. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData002, TestSize.Level1) @@ -130,7 +130,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData002, Te * @tc.desc: To test the function of querying data when the timestamp range * in the data obtaining interface is invalid. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData003, TestSize.Level1) @@ -147,7 +147,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData003, Te * @tc.name: GetSyncData004 * @tc.desc: To the test database Subcon reading, a large number of data records exist in the time stamp range. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData004, TestSize.Level1) @@ -171,7 +171,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData004, Te * @tc.desc: In the test database, if a large number of data records exist * in the time stamp range, a packet is read successfully. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData005, TestSize.Level1) @@ -189,7 +189,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData005, Te * @tc.desc: To test the function of reading data when the time stamp range in the database * is greater than the value of blockSize. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData006, TestSize.Level1) @@ -206,7 +206,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData006, Te * @tc.name: PutSyncData001 * @tc.desc: To test the function of synchronizing the new data of the remote device that synchronizes the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, PutSyncData001, TestSize.Level1) @@ -253,7 +253,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, PutSyncData001, Te * @tc.desc: To test the function of synchronizing data from the remote device * to the local device after the data is deleted from the remote device. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, PutSyncData002, TestSize.Level1) @@ -291,7 +291,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, PutSyncData002, Te * @tc.desc: To test the function of synchronizing the mixed data of the added * and deleted data from the remote device to the local device. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, PutSyncData003, TestSize.Level1) @@ -323,7 +323,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, PutSyncData003, Te * @tc.name: PutMetaData001 * @tc.desc: Test metadata insertion and modification. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, PutMetaData001, TestSize.Level1) @@ -376,7 +376,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, PutMetaData001, Te * @tc.name: GetMetaData001 * @tc.desc: To test the function of reading the metadata of a key in the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetMetaData001, TestSize.Level1) @@ -429,7 +429,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetMetaData001, Te * @tc.name: DeleteMetaData001 * @tc.desc: * @tc.name: To test the function of deleting the metadata with prefix key in the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteMetaData001, TestSize.Level1) @@ -454,7 +454,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteMetaData001, * @tc.name: GetCurrentMaxTimestamp001 * @tc.desc: To test the function of obtaining the maximum timestamp when a record exists in the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetCurrentMaxTimestamp001, TestSize.Level1) @@ -479,7 +479,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetCurrentMaxTimes * @tc.name: GetCurrentMaxTimestamp002 * @tc.desc: Obtain the maximum timestamp when no record exists in the test record library. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetCurrentMaxTimestamp002, TestSize.Level1) @@ -495,7 +495,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetCurrentMaxTimes * @tc.name: LocalDatabaseOperate001 * @tc.desc: Test the function of inserting data in the local database of the NaturalStore. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, LocalDatabaseOperate001, TestSize.Level1) @@ -551,7 +551,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, LocalDatabaseOpera * @tc.name: LocalDatabaseOperate002 * @tc.desc: Test the function of deleting data from the local database of the NaturalStore. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, LocalDatabaseOperate002, TestSize.Level1) @@ -607,7 +607,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, LocalDatabaseOpera * @tc.name: LocalDatabaseOperate003 * @tc.desc: To test the function of reading data from the local database of the NaturalStore. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, LocalDatabaseOperate003, TestSize.Level1) @@ -663,7 +663,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, LocalDatabaseOpera * @tc.name: SyncDatabaseOperate001 * @tc.desc: To test the function of inserting data of the local device in the synchronization database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperate001, TestSize.Level1) @@ -719,7 +719,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperat * @tc.name: SyncDatabaseOperate002 * @tc.desc: test the put operation after data synced from other devices. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperate002, TestSize.Level1) @@ -746,7 +746,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperat * @tc.name: SyncDatabaseOperate003 * @tc.desc: test the delete operation in sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperate003, TestSize.Level1) @@ -779,7 +779,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperat * @tc.name: SyncDatabaseOperate004 * @tc.desc: test the delete for the data from other devices in sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperate004, TestSize.Level1) @@ -803,7 +803,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperat * @tc.name: SyncDatabaseOperate005 * @tc.desc: test the reading for sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperate005, TestSize.Level1) @@ -838,7 +838,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperat * @tc.name: SyncDatabaseOperate006 * @tc.desc: test the get entries for sync database * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperate006, TestSize.Level1) @@ -869,7 +869,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperat * @tc.name: ClearRemoteData001 * @tc.desc: test the clear data synced from the remote by device. * @tc.type: FUNC - * @tc.require: AR000CIFDA AR000CQS3T + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, ClearRemoteData001, TestSize.Level1) @@ -899,7 +899,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, ClearRemoteData001 * @tc.name: DeleteUserKeyValue001 * @tc.desc: When a user deletes a data record, the system clears the user record. * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue001, TestSize.Level1) @@ -920,7 +920,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue * @tc.name: DeleteUserKeyValue002 * @tc.desc: After the synchronization library data is deleted locally, add the same key data locally. * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue002, TestSize.Level1) @@ -949,7 +949,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue * @tc.name: DeleteUserKeyValue003 * @tc.desc: After the synchronization database data is deleted locally, the same key data is added from the remote end. * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue003, TestSize.Level1) @@ -990,7 +990,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue * @tc.name: DeleteUserKeyValue004 * @tc.desc: Changes in key after remote delete data syncs to local * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue004, TestSize.Level1) @@ -1014,7 +1014,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue * @tc.name: DeleteUserKeyValue005 * @tc.desc: New unified key data locally after remote delete data syncs to local * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue005, TestSize.Level1) @@ -1043,7 +1043,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue * @tc.desc: After the remote delete data is synced to the local, * the same key data is added from the remote other devices * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue006, TestSize.Level1) @@ -1083,7 +1083,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue * @tc.name: EraseDeviceWaterMark001 * @tc.desc: Test erase water mark * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, EraseDeviceWaterMark001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_storage_engine_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_storage_engine_test.cpp index 5b8da2980f50597fc0df16180da15b719d7dc7f0..c6b7495aa7078745caa2d54f6eed552ab57d8442 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_storage_engine_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_storage_engine_test.cpp @@ -17,7 +17,10 @@ #include "db_common.h" #include "distributeddb_storage_single_ver_natural_store_testcase.h" +#include "process_system_api_adapter_impl.h" +#include "single_ver_utils.h" #include "storage_engine_manager.h" +#include "virtual_sqlite_storage_engine.h" using namespace testing::ext; using namespace DistributedDB; @@ -51,6 +54,51 @@ namespace { static_cast(StorageEngineManager::GetStorageEngine(g_property, errCode)); EXPECT_EQ(errCode, E_OK); } + + void PrepareEnv() + { + sqlite3 *db; + ASSERT_TRUE(sqlite3_open_v2((g_testDir + g_databaseName).c_str(), + &db, SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr) == SQLITE_OK); + ASSERT_TRUE(SQLiteUtils::ExecuteRawSQL(db, ADD_SYNC) == E_OK); + ASSERT_TRUE(SQLiteUtils::ExecuteRawSQL(db, INSERT_SQL) == E_OK); + sqlite3_close_v2(db); + } + + OpenDbProperties GetProperties(bool isMem, const SecurityOption &option, bool createIfNecessary) + { + OpenDbProperties properties; + properties.uri = DistributedDB::GetDatabasePath(g_property); + properties.createIfNecessary = createIfNecessary; + properties.subdir = DistributedDB::GetSubDirPath(g_property); + properties.isMemDb = isMem; + properties.securityOpt = option; + return properties; + } + + int InitVirtualEngine(const std::shared_ptr &engine, + bool isMem, const SecurityOption &option, bool createIfNecessary, const StorageEngineAttr &poolSize) + { + auto properties = GetProperties(isMem, option, createIfNecessary); + return engine->InitSQLiteStorageEngine(poolSize, properties, ""); + } + + std::pair> GetVirtualEngineWithSecurity( + uint32_t maxRead, bool isMem, const SecurityOption &option, bool createIfNecessary) + { + std::pair> res; + auto &[errCode, engine] = res; + engine = std::make_shared(); + StorageEngineAttr poolSize = {1, 1, 1, maxRead}; // at most 1 write. + errCode = InitVirtualEngine(engine, isMem, option, createIfNecessary, poolSize); + return res; + } + + std::pair> GetVirtualEngine(uint32_t maxRead = 1, + bool isMem = false, bool createIfNecessary = false) + { + return GetVirtualEngineWithSecurity(maxRead, isMem, {}, createIfNecessary); + } } class DistributedDBStorageSQLiteSingleVerStorageEngineTest : public testing::Test { @@ -106,6 +154,7 @@ void DistributedDBStorageSQLiteSingleVerStorageEngineTest::TearDown(void) g_connection = nullptr; } g_store = nullptr; + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); } /** @@ -221,3 +270,327 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, DataTest003, Test invalidConnection = nullptr; ASSERT_EQ(invalidConnection, nullptr); } + +/** + * @tc.name: ExecutorTest001 + * @tc.desc: Test find executor after disable engine + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest001, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + SQLiteSingleVerStorageEngine *storageEngine = nullptr; + GetStorageEngine(storageEngine); + ASSERT_NE(storageEngine, nullptr); + EXPECT_EQ(storageEngine->TryToDisable(false), E_OK); + int errCode = E_OK; + EXPECT_EQ(storageEngine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode), nullptr); + storageEngine->Release(); + storageEngine = nullptr; +} + +/** + * @tc.name: ExecutorTest002 + * @tc.desc: Test find executor success + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest002, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + SQLiteSingleVerStorageEngine *storageEngine = nullptr; + GetStorageEngine(storageEngine); + int errCode = E_OK; + auto executor1 = storageEngine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode); + EXPECT_NE(executor1, nullptr); + auto executor2 = storageEngine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode); + EXPECT_NE(executor2, nullptr); + storageEngine->Recycle(executor1); + storageEngine->Recycle(executor2); + EXPECT_EQ(storageEngine->FindExecutor(false, OperatePerm::DISABLE_PERM, errCode), nullptr); + storageEngine->Release(); + storageEngine = nullptr; +} + +/** + * @tc.name: ExecutorTest003 + * @tc.desc: Test find executor abnormal + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest003, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + auto [errCode, engine] = GetVirtualEngine(); + ASSERT_EQ(errCode, E_OK); + auto executor1 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 0); + EXPECT_NE(executor1, nullptr); + auto executor2 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 0); + EXPECT_EQ(executor2, nullptr); + engine->Recycle(executor1); + engine->Release(); +} + +/** + * @tc.name: ExecutorTest004 + * @tc.desc: Test find executor abnormal + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest004, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + auto [errCode, engine] = GetVirtualEngine(3); // max read is 3 + ASSERT_EQ(errCode, E_OK); + auto mockFunc = [](bool, StorageExecutor *&handle) { + handle = nullptr; + return -E_EKEYREVOKED; + }; + auto executor0 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 0); + EXPECT_NE(executor0, nullptr); + /** + * @tc.steps:step1. create new handle with mock func + * @tc.expected: step1. create failed. + */ + engine->ForkNewExecutorMethod(mockFunc); + auto executor1 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 0); + EXPECT_EQ(executor1, nullptr); + EXPECT_EQ(errCode, -E_BUSY); + /** + * @tc.steps:step2. create new handle with normal func + * @tc.expected: step2. create ok. + */ + engine->ForkNewExecutorMethod(nullptr); + executor1 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 0); + EXPECT_NE(executor1, nullptr); + /** + * @tc.steps:step3. create new handle with mock func + * @tc.expected: step3. create failed. + */ + engine->ForkNewExecutorMethod([](bool, StorageExecutor *&handle) { + handle = nullptr; + return -E_BUSY; + }); + auto executor2 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 0); + EXPECT_EQ(executor2, nullptr); + engine->Recycle(executor1); + engine->Recycle(executor0); + engine->Release(); +} + +/** + * @tc.name: ExecutorTest005 + * @tc.desc: Test find executor abnormal + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest005, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + auto [errCode, engine] = GetVirtualEngine(2); // max read is 2 + ASSERT_EQ(errCode, E_OK); + engine->SetEnhance(true); + /** + * @tc.steps:step1. create new handle without mock func + * @tc.expected: step1. create ok. + */ + auto executor0 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 0); + EXPECT_NE(executor0, nullptr); + /** + * @tc.steps:step2. create new handle with mock func, mock func will release executor + * @tc.expected: step2. create fail. + */ + engine->ForkNewExecutorMethod([executor = executor0, enginePtr = engine](bool, StorageExecutor *&handle) { + StorageExecutor *executorPtr = executor; + enginePtr->Recycle(executorPtr); + handle = nullptr; + return -E_EKEYREVOKED; + }); + auto executor1 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 0); + EXPECT_EQ(executor1, nullptr); + engine->Release(); + engine->ForkNewExecutorMethod(nullptr); +} + +/** + * @tc.name: ExecutorTest006 + * @tc.desc: Test find executor abnormal when get executor timeout and operate abort + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest006, TestSize.Level4) +{ + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + auto [errCode, engine] = GetVirtualEngine(1); // max read is 1 + ASSERT_EQ(errCode, E_OK); + /** + * @tc.steps:step1. create new handle + * @tc.expected: step1. create ok. + */ + auto executor0 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode); + EXPECT_NE(executor0, nullptr); + /** + * @tc.steps:step2. create new handle again + * @tc.expected: step2. create failed by timeout. + */ + auto executor1 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 1); // max wait 1s + EXPECT_EQ(executor1, nullptr); + /** + * @tc.steps:step3. create new handle again and async mark operate abort + * @tc.expected: step3. create failed by operate abort. + */ + std::thread t([enginePtr = engine]() { + std::this_thread::sleep_for(std::chrono::seconds(1)); + enginePtr->Abort(); + }); + executor1 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 5); // max wait 5s + EXPECT_EQ(executor1, nullptr); + t.join(); + engine->Recycle(executor0); + engine->Release(); +} + +/** + * @tc.name: ExecutorTest007 + * @tc.desc: Test diff executor pool will not recycle others pool's executor + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest007, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + auto [errCode, engine1] = GetVirtualEngine(1); // max read is 1 + ASSERT_EQ(errCode, E_OK); + auto [ret, engine2] = GetVirtualEngine(1); // max read is 1 + ASSERT_EQ(ret, E_OK); + /** + * @tc.steps:step1. create new handle + * @tc.expected: step1. create ok. + */ + auto executor1 = engine1->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode); + EXPECT_NE(executor1, nullptr); + /** + * @tc.steps:step2. create new handle + * @tc.expected: step2. create ok. + */ + auto tmp = executor1; + engine2->Recycle(tmp); + engine1->Recycle(executor1); + EXPECT_EQ(executor1, nullptr); + engine1->Release(); + engine2->Release(); +} + +/** + * @tc.name: ExecutorTest008 + * @tc.desc: Test mem executor pool + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest008, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + auto [errCode, engine1] = GetVirtualEngine(1, true); // max read is 1 + /** + * @tc.steps:step1. create new handle + * @tc.expected: step1. create ok. + */ + auto executor1 = engine1->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode); + EXPECT_NE(executor1, nullptr); + engine1->Recycle(executor1); + engine1->CallSetSQL({}); + engine1->Release(); +} + +/** + * @tc.name: ExecutorTest009 + * @tc.desc: Test cache executor pool + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest009, TestSize.Level0) +{ + auto systemApi = std::make_shared(); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(systemApi); + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + SecurityOption option = {S3, SECE}; + auto [errCode, engine] = GetVirtualEngineWithSecurity(2, false, option, true); // max read is 2 + /** + * @tc.steps:step1. create new handle + * @tc.expected: step1. create ok. + */ + auto executor1 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode); + EXPECT_NE(executor1, nullptr); + /** + * @tc.steps:step2. create new handle with fork open main failed + * @tc.expected: step2. create failed because of read handle was not allowed. + */ + engine->ForkOpenMainDatabaseMethod([executor1, enginePtr = engine](bool, sqlite3 *&db, OpenDbProperties &) { + StorageExecutor *executor = executor1; + enginePtr->Recycle(executor); + db = nullptr; + return -E_EKEYREVOKED; + }); + auto executor2 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode); + EXPECT_EQ(executor2, nullptr); + engine->ForkOpenMainDatabaseMethod(nullptr); + engine->Recycle(executor2); + engine->Release(); +} + +/** + * @tc.name: ExecutorTest010 + * @tc.desc: Test cache executor pool + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest010, TestSize.Level0) +{ + auto systemApi = std::make_shared(); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(systemApi); + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + CopyCacheDb(); + SecurityOption option = {S3, SECE}; + auto [errCode, engine] = GetVirtualEngineWithSecurity(2, false, option, true); // max read is 2 + ASSERT_EQ(errCode, E_OK); + /** + * @tc.steps:step1. create new handle with create if necessary + * @tc.expected: step1. create ok. + */ + auto properties = GetProperties(false, option, true); + auto [ret, handle] = engine->GetCacheHandle(properties); + EXPECT_EQ(ret, E_OK); + if (handle != nullptr) { + EXPECT_EQ(sqlite3_close_v2(handle), SQLITE_OK); + } + /** + * @tc.steps:step2. create new handle without create if necessary + * @tc.expected: step2. create ok. + */ + properties = GetProperties(false, option, false); + std::tie(ret, handle) = engine->GetCacheHandle(properties); + EXPECT_EQ(ret, E_OK); + if (handle != nullptr) { + EXPECT_EQ(sqlite3_close_v2(handle), SQLITE_OK); + } + /** + * @tc.steps:step3. create new handle without create if necessary and dir was removed + * @tc.expected: step3. create failed. + */ + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); + properties.createIfNecessary = false; + std::tie(ret, handle) = engine->GetCacheHandle(properties); + EXPECT_EQ(ret, -E_INVALID_DB); + engine->Release(); +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp index b03b188645ac325e359f3e7c337a2bfac0447b7d..7a3079c27d06ea675b40af5cdee3f63fcf27fac5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp @@ -217,7 +217,7 @@ void DistributedDBStorageSubscribeQueryTest::TearDown() * @tc.name: CheckAndInitQueryCondition001 * @tc.desc: Check the condition is legal or not with json schema * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, CheckAndInitQueryCondition001, TestSize.Level1) @@ -280,7 +280,7 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, CheckAndInitQueryCondition001, * @tc.name: CheckAndInitQueryCondition002 * @tc.desc: Check the condition always illegal with flatbuffer schema * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, CheckAndInitQueryCondition002, TestSize.Level1) @@ -318,7 +318,7 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, CheckAndInitQueryCondition002, * @tc.name: CheckAndInitQueryCondition003 * @tc.desc: Check the condition always illegal with flatbuffer schema * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, CheckAndInitQueryCondition003, TestSize.Level1) @@ -361,7 +361,7 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, CheckAndInitQueryCondition003, * @tc.name: PutSyncDataTestWithQuery * @tc.desc: put remote devices sync data(get by query sync or subscribe) with query. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery, TestSize.Level1) @@ -414,7 +414,7 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery, TestS * @tc.name: PutSyncDataTestWithQuery002 * @tc.desc: put remote devices sync data(timestamp is smaller then DB data) with query. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery002, TestSize.Level1) @@ -472,7 +472,7 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery002, Te * @tc.name: PutSyncDataTestWithQuery003 * @tc.desc: put remote devices sync data(with same timestamp in DB data but different devices) with query. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery003, TestSize.Level1) @@ -529,7 +529,7 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery003, Te * @tc.name: PutSyncDataTestWithQuery004 * @tc.desc: put remote devices sync data(with same timestamp in DB data but different devices) with query. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery004, TestSize.Level1) @@ -585,7 +585,7 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery004, Te * @tc.name: AddSubscribeTest001 * @tc.desc: Add subscribe with query * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, AddSubscribeTest001, TestSize.Level1) @@ -640,7 +640,7 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, AddSubscribeTest001, TestSize.L * @tc.name: AddSubscribeTest002 * @tc.desc: Add subscribe with same query not failed * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, AddSubscribeTest002, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_transaction_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_transaction_data_test.cpp index ac6beeb3636ab5f14abc22e5b1cdb48ada1c67de..68b0b39731be0e2ef41151d49f3f2f6a5fba7f53 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_transaction_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_transaction_data_test.cpp @@ -293,7 +293,7 @@ void DistributedDBStorageTransactionDataTest::TearDown(void) * @tc.name: StorageInsert001 * @tc.desc: Put the non-empty key, non-empty value into the database. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsert001, TestSize.Level1) @@ -335,7 +335,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsert001, TestSize.Lev * @tc.name: StorageInsert002 * @tc.desc: Put the empty key, non-empty value into the database. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsert002, TestSize.Level1) @@ -354,7 +354,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsert002, TestSize.Lev * @tc.name: StorageInsert003 * @tc.desc: Put the non-empty key, empty value into the database. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsert003, TestSize.Level1) @@ -380,7 +380,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsert003, TestSize.Lev * @tc.name: StorageUpdate001 * @tc.desc: Update the value to non-empty * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdate001, TestSize.Level1) @@ -410,7 +410,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdate001, TestSize.Lev * @tc.name: StorageUpdate002 * @tc.desc: Update the value to empty * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdate002, TestSize.Level1) @@ -439,7 +439,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdate002, TestSize.Lev * @tc.name: StorageDelete001 * @tc.desc: Delete the existed data * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDelete001, TestSize.Level1) @@ -466,7 +466,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDelete001, TestSize.Lev * @tc.name: StorageDelete002 * @tc.desc: Delete the non-existed data * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDelete002, TestSize.Level1) @@ -490,7 +490,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDelete002, TestSize.Lev * @tc.name: StorageDelete003 * @tc.desc: Delete the invalid key data * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDelete003, TestSize.Level1) @@ -507,7 +507,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDelete003, TestSize.Lev * @tc.name: StorageClear001 * @tc.desc: Clear the data * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageClear001, TestSize.Level1) @@ -535,7 +535,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageClear001, TestSize.Leve * @tc.name: StorageInsertBatch001 * @tc.desc: Put the valid batch data * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsertBatch001, TestSize.Level1) @@ -565,7 +565,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsertBatch001, TestSiz * @tc.name: StorageInsertBatch002 * @tc.desc: Put the partially valid batch data * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsertBatch002, TestSize.Level1) @@ -593,7 +593,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsertBatch002, TestSiz * @tc.name: StorageUpdateBatch001 * @tc.desc: Update the batch data * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdateBatch001, TestSize.Level1) @@ -633,7 +633,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdateBatch001, TestSiz * @tc.name: StorageUpdateBatch002 * @tc.desc: Update the batch data(partially invalid data) * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdateBatch002, TestSize.Level1) @@ -675,7 +675,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdateBatch002, TestSiz * @tc.name: StorageDeleteBatch001 * @tc.desc: Delete the batch data * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDeleteBatch001, TestSize.Level1) @@ -711,7 +711,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDeleteBatch001, TestSiz * @tc.name: StorageDeleteBatch002 * @tc.desc: Delete the batch data(partially non-existed) * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDeleteBatch002, TestSize.Level1) @@ -749,7 +749,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDeleteBatch002, TestSiz * @tc.name: StorageDeleteBatch003 * @tc.desc: Delete the batch data(partially invalid) * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDeleteBatch003, TestSize.Level1) @@ -787,7 +787,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDeleteBatch003, TestSiz * @tc.name: StorageTransactionCombo001 * @tc.desc: Multiple operation within the transaction * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageTransactionCombo001, TestSize.Level1) @@ -853,7 +853,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageTransactionCombo001, Te * @tc.name: TransactionRollback001 * @tc.desc: Multiple operation within the transaction * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionRollback001, TestSize.Level1) @@ -887,7 +887,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionRollback001, TestSi * @tc.name: TransactionGetCommitData001 * @tc.desc: Get the commit data of one transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionGetCommitData001, TestSize.Level1) @@ -940,7 +940,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionGetCommitData001, T * @tc.name: TransactionSqliteKvEntry001 * @tc.desc: Serialize the kv entry and deserialize the data. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionSqliteKvEntry001, TestSize.Level1) @@ -994,7 +994,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionSqliteKvEntry001, T * @tc.name: TransactionPutForeignData001 * @tc.desc: Put the remote commit data into the current device database. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionPutForeignData001, TestSize.Level1) @@ -1044,7 +1044,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionPutForeignData001, * @tc.name: DefaultConflictResolution001 * @tc.desc: Merge data without conflicts * @tc.type: FUNC - * @tc.require: AR000CQE13 AR000CQE14 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution001, TestSize.Level1) @@ -1073,7 +1073,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution001, * @tc.name: DefaultConflictResolution002 * @tc.desc: Merge data with conflicts ,no clear operation in the external data and local data * @tc.type: FUNC - * @tc.require: AR000CQE13 AR000CQE14 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution002, TestSize.Level1) @@ -1175,7 +1175,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution002, * @tc.name: DefaultConflictResolution003 * @tc.desc: Merge data with conflicts, clear operation is in the external data * @tc.type: FUNC - * @tc.require: AR000CQE13 AR000CQE14 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution003, TestSize.Level2) @@ -1226,7 +1226,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution003, * @tc.name: DefaultConflictResolution004 * @tc.desc: Merge data with conflicts, clear operation is in the local data * @tc.type: FUNC - * @tc.require: AR000CQE13 AR000CQE14 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution004, TestSize.Level2) @@ -1288,7 +1288,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution004, * @tc.name: CommitTimestamp001 * @tc.desc: Test the timestamp of the native commit. * @tc.type: FUNC - * @tc.require: AR000CQE11 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionDataTest, CommitTimestamp001, TestSize.Level2) @@ -1419,7 +1419,7 @@ static bool PutSecondSyncCommitData(const MultiVerCommitNode &multiVerCommit, Mu * @tc.name: CommitTimestamp002 * @tc.desc: Test the timestamp of the native commits. * @tc.type: FUNC - * @tc.require: AR000CQE11 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionDataTest, CommitTimestamp002, TestSize.Level1) @@ -1467,7 +1467,7 @@ static void ReleaseKvEntries(std::vector &entries) * @tc.name: CommitTimestamp003 * @tc.desc: Test the timestamp of the foreign commits. * @tc.type: FUNC - * @tc.require: AR000CQE11 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionDataTest, CommitTimestamp003, TestSize.Level1) @@ -1511,7 +1511,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, CommitTimestamp003, TestSize.L * @tc.name: CommitTimestamp004 * @tc.desc: Test the timestamp of the merge commits. * @tc.type: FUNC - * @tc.require: AR000CQE11 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionDataTest, CommitTimestamp004, TestSize.Level1) @@ -1562,7 +1562,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, CommitTimestamp004, TestSize.L * @tc.name: GetBranchTag * @tc.desc: Test the branch tag of the commits. * @tc.type: FUNC - * @tc.require: AR000CQE11 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionDataTest, GetBranchTag001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_transaction_record_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_transaction_record_test.cpp index 54333d7bd1aa308df55344bc92eb64f06e9e0202..81c1544104ba0dbd35f5687d96dbea3fadd25bd6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_transaction_record_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_transaction_record_test.cpp @@ -82,7 +82,7 @@ void DistributedDBStorageTransactionRecordTest::TearDown(void) * @tc.name: MultiverStorage001 * @tc.desc: test the putting non empty data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage001, TestSize.Level1) @@ -127,7 +127,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage001, TestSize * @tc.name: MultiverStorage002 * @tc.desc: test the putting data(empty key) with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage002, TestSize.Level1) @@ -160,7 +160,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage002, TestSize * @tc.name: MultiverStorage003 * @tc.desc: test the putting data(empty value) with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage003, TestSize.Level1) @@ -201,7 +201,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage003, TestSize * @tc.name: MultiverStorage004 * @tc.desc: Update the data value to non-empty with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage004, TestSize.Level1) @@ -255,7 +255,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage004, TestSize * @tc.name: MultiverStorage005 * @tc.desc: Update the data value to empty with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage005, TestSize.Level1) @@ -305,7 +305,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage005, TestSize * @tc.name: MultiverStorage006 * @tc.desc: Delete the existed data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage006, TestSize.Level1) @@ -358,7 +358,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage006, TestSize * @tc.name: MultiverStorage007 * @tc.desc: Delete the non-existed data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage007, TestSize.Level1) @@ -399,7 +399,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage007, TestSize * @tc.name: MultiverStorage008 * @tc.desc: Delete an empty key with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage008, TestSize.Level1) @@ -454,7 +454,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage008, TestSize * @tc.name: MultiverStorage009 * @tc.desc: Clear the existed data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage009, TestSize.Level1) @@ -509,7 +509,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage009, TestSize * @tc.name: MultiverStorage010 * @tc.desc: Get the existed data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage010, TestSize.Level1) @@ -532,7 +532,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage010, TestSize * @tc.name: MultiverStorage011 * @tc.desc: Get the non-existed data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage011, TestSize.Level1) @@ -564,7 +564,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage011, TestSize * @tc.name: MultiverStorage012 * @tc.desc: Get the empty-key data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage012, TestSize.Level1) @@ -597,7 +597,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage012, TestSize * @tc.name: MultiverStorage013 * @tc.desc: Get the deleted data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage013, TestSize.Level1) @@ -630,7 +630,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage013, TestSize * @tc.name: MultiverStorage014 * @tc.desc: Get the modified data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage014, TestSize.Level1) @@ -666,7 +666,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage014, TestSize * @tc.name: MultiverStorage015 * @tc.desc: Get the data after clear with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage015, TestSize.Level1) @@ -700,7 +700,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage015, TestSize * @tc.name: MultiverStorage016 * @tc.desc: Get the new inserted data after clear with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage016, TestSize.Level1) @@ -742,7 +742,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage016, TestSize * @tc.name: MultiverStorage017 * @tc.desc: Get the new inserted data after delete with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage017, TestSize.Level1) @@ -787,7 +787,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage017, TestSize * @tc.name: MultiverStorage018 * @tc.desc: Get the batch inserted data through the non-empty prefix key. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage018, TestSize.Level1) @@ -829,7 +829,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage018, TestSize * @tc.name: MultiverStorage019 * @tc.desc: Get the non-existed data through the non-empty prefix key. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage019, TestSize.Level1) @@ -860,7 +860,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage019, TestSize * @tc.name: MultiverStorage020 * @tc.desc: Get all the data through the empty prefix key. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage020, TestSize.Level1) @@ -896,7 +896,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage020, TestSize * @tc.name: MultiverStorage021 * @tc.desc: Get the data through the empty prefix key for multiple put the same key data. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage021, TestSize.Level1) @@ -930,7 +930,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage021, TestSize * @tc.name: MultiverStorage022 * @tc.desc: Get the data through the empty prefix key for deleted data. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage022, TestSize.Level1) @@ -967,7 +967,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage022, TestSize * @tc.name: MultiverStorage023 * @tc.desc: Get the data through the empty prefix key for updated data. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage023, TestSize.Level1) @@ -1011,7 +1011,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage023, TestSize * @tc.name: MultiverStorage024 * @tc.desc: Get the data through the empty prefix key for cleared data. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage024, TestSize.Level1) @@ -1047,7 +1047,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage024, TestSize * @tc.name: MultiverStorage025 * @tc.desc: Get the data through the put, delete, re-put operation. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage025, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_relational_store.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_relational_store.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f187b6e030310e635bbdd2d6bc29080001d80ff3 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_relational_store.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 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 "virtual_sqlite_relational_store.h" + +namespace DistributedDB { +void VirtualSqliteRelationalStore::SetStorageEngine(const std::shared_ptr &engine) +{ + sqliteStorageEngine_ = engine; +} + +int VirtualSqliteRelationalStore::CallCheckTrackerTable(const TrackerSchema &trackerSchema, TableInfo &table, + bool &isNoTableInSchema, bool &isFirstCreate) +{ + return CheckTrackerTable(trackerSchema, table, isNoTableInSchema, isFirstCreate); +} + +void VirtualSqliteRelationalStore::CallCleanDirtyLogIfNeed(const std::string &tableName) const +{ + CleanDirtyLogIfNeed(tableName); +} + +RelationalSchemaObject VirtualSqliteRelationalStore::CallGetSchemaObj() const +{ + return GetSchemaObj(); +} +} // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_relational_store.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_relational_store.h new file mode 100644 index 0000000000000000000000000000000000000000..92442e8816499767bf13461f04c709124fbd5972 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_relational_store.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 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 VIRTUAL_SQLITE_RELATIONAL_STORE_H +#define VIRTUAL_SQLITE_RELATIONAL_STORE_H + +#include "sqlite_relational_store.h" + +namespace DistributedDB { +class VirtualSqliteRelationalStore : public SQLiteRelationalStore { +public: + VirtualSqliteRelationalStore() = default; + ~VirtualSqliteRelationalStore() override = default; + + void SetStorageEngine(const std::shared_ptr &engine); + + int CallCheckTrackerTable(const TrackerSchema &trackerSchema, TableInfo &table, bool &isNoTableInSchema, + bool &isFirstCreate); + + void CallCleanDirtyLogIfNeed(const std::string &tableName) const; + + RelationalSchemaObject CallGetSchemaObj() const; +}; +} // namespace DistributedDB +#endif // VIRTUAL_SQLITE_RELATIONAL_STORE_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_storage_engine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e7bb4d18536836cf026ef4f82535f12e15593c2e --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_storage_engine.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025 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 "virtual_sqlite_storage_engine.h" + +namespace DistributedDB { +void VirtualSingleVerStorageEngine::ForkNewExecutorMethod(const NewExecutorMethod &method) +{ + std::lock_guard autoLock(functionMutex_); + forkNewFunc_ = method; +} + +void VirtualSingleVerStorageEngine::ForkOpenMainDatabaseMethod(const OpenMainDatabaseMethod &method) +{ + std::lock_guard autoLock(functionMutex_); + forkOpenMainFunc_ = method; +} + +void VirtualSingleVerStorageEngine::SetMaxNum(int maxRead, int maxWrite) +{ + engineAttr_.maxReadNum = maxRead; + engineAttr_.maxWriteNum = maxWrite; +} + +void VirtualSingleVerStorageEngine::SetEnhance(bool isEnhance) +{ + isEnhance_ = isEnhance; +} + +void VirtualSingleVerStorageEngine::CallSetSQL(const std::vector &sql) +{ + SetSQL(sql); +} + +std::pair VirtualSingleVerStorageEngine::GetCacheHandle(OpenDbProperties &option) +{ + std::pair res; + auto &[errCode, db] = res; + errCode = SQLiteSingleVerStorageEngine::GetCacheDbHandle(db, option); + return res; +} + +int VirtualSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *&handle) +{ + { + std::lock_guard autoLock(functionMutex_); + if (forkNewFunc_ != nullptr) { + return forkNewFunc_(isWrite, handle); + } + } + return SQLiteSingleVerStorageEngine::CreateNewExecutor(isWrite, handle); +} + +int VirtualSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, sqlite3 *&db, OpenDbProperties &option) +{ + { + std::lock_guard autoLock(functionMutex_); + if (forkOpenMainFunc_ != nullptr) { + return forkOpenMainFunc_(isWrite, db, option); + } + } + return SQLiteSingleVerStorageEngine::TryToOpenMainDatabase(isWrite, db, option); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_storage_engine.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_storage_engine.h new file mode 100644 index 0000000000000000000000000000000000000000..d1956d84a632fc83e74c955e098b2ab272725d80 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_storage_engine.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 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 VIRTUAL_SQLITE_STORAGE_ENGINE_H +#define VIRTUAL_SQLITE_STORAGE_ENGINE_H + +#include "sqlite_single_ver_storage_engine.h" + +namespace DistributedDB { +class VirtualSingleVerStorageEngine : public SQLiteSingleVerStorageEngine { +public: + using NewExecutorMethod = std::function; + using OpenMainDatabaseMethod = std::function; + void ForkNewExecutorMethod(const NewExecutorMethod &method); + void ForkOpenMainDatabaseMethod(const OpenMainDatabaseMethod &method); + void SetMaxNum(int maxRead, int maxWrite); + void SetEnhance(bool isEnhance); + void CallSetSQL(const std::vector &sql); + std::pair GetCacheHandle(OpenDbProperties &option); +protected: + int CreateNewExecutor(bool isWrite, DistributedDB::StorageExecutor *&handle) override; + int TryToOpenMainDatabase(bool isWrite, sqlite3 *&db, OpenDbProperties &option) override; +private: + std::mutex functionMutex_; + NewExecutorMethod forkNewFunc_; + OpenMainDatabaseMethod forkOpenMainFunc_; +}; +} +#endif // VIRTUAL_SQLITE_STORAGE_ENGINE_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distracteddb_kv_multi_user_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distracteddb_kv_multi_user_sync_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a931eefe01d39ff5fc7aba712b25dbeae8929db3 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distracteddb_kv_multi_user_sync_test.cpp @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2025 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_general_ut.h" +#include "process_communicator_test_stub.h" + +namespace DistributedDB { +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +class DistributedDBKvMultiUserSyncTest : public KVGeneralUt { +protected: + void PrepareData(); + void SyncStep1(); + void SyncStep2(); + void SyncStep3(); + static void SetTargetUserId(const std::string &deviceId, const std::string &userId); + static constexpr const char *DEVICE_A = "DEVICE_A"; + static constexpr const char *DEVICE_B = "DEVICE_B"; + static constexpr const char *USER_ID_1 = "USER_ID_1"; + static constexpr const char *USER_ID_2 = "USER_ID_2"; + static constexpr const char *USER_ID_3 = "USER_ID_3"; +}; + +void CheckData(KvStoreNbDelegate *delegate, const Key &key, const Value &expectValue) +{ + Value actualValue; + if (expectValue.empty()) { + EXPECT_EQ(delegate->Get(key, actualValue), NOT_FOUND); + } else { + EXPECT_EQ(delegate->Get(key, actualValue), OK); + EXPECT_EQ(actualValue, expectValue); + } +} + +void DistributedDBKvMultiUserSyncTest::SetTargetUserId(const std::string &deviceId, const std::string &userId) +{ + ICommunicatorAggregator *communicatorAggregator = nullptr; + RuntimeContext::GetInstance()->GetCommunicatorAggregator(communicatorAggregator); + ASSERT_NE(communicatorAggregator, nullptr); + auto virtualCommunicatorAggregator = static_cast(communicatorAggregator); + auto communicator = static_cast(virtualCommunicatorAggregator->GetCommunicator(deviceId)); + ASSERT_NE(communicator, nullptr); + communicator->SetTargetUserId(userId); +} + +void DistributedDBKvMultiUserSyncTest::PrepareData() +{ + KvStoreNbDelegate::Option option; + option.syncDualTupleMode = true; + SetOption(option); + + StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + + StoreInfo storeInfo2 = {USER_ID_2, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_A), E_OK); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + + EXPECT_EQ(store1->Put(KEY_1, VALUE_1), OK); + EXPECT_EQ(store1->Put(KEY_2, VALUE_2), OK); + EXPECT_EQ(store1->Put(KEY_3, VALUE_3), OK); + EXPECT_EQ(store2->Put(KEY_4, VALUE_4), OK); + + CheckData(store1, KEY_1, VALUE_1); + CheckData(store1, KEY_2, VALUE_2); + CheckData(store1, KEY_3, VALUE_3); + CheckData(store2, KEY_4, VALUE_4); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo2), E_OK); +} + +void DistributedDBKvMultiUserSyncTest::SyncStep1() +{ + StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + + StoreInfo storeInfo3 = {USER_ID_1, STORE_ID_2, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo3, DEVICE_B), E_OK); + auto store3 = GetDelegate(storeInfo3); + ASSERT_NE(store3, nullptr); + + SetTargetUserId(DEVICE_A, USER_ID_1); + SetTargetUserId(DEVICE_B, USER_ID_1); + BlockPush(storeInfo1, storeInfo3); + + CheckData(store3, KEY_1, VALUE_1); + CheckData(store3, KEY_2, VALUE_2); + CheckData(store3, KEY_3, VALUE_3); + + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo3), E_OK); +} + +void DistributedDBKvMultiUserSyncTest::SyncStep2() +{ + StoreInfo storeInfo2 = {USER_ID_2, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_A), E_OK); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + + StoreInfo storeInfo4 = {USER_ID_2, STORE_ID_2, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo4, DEVICE_B), E_OK); + auto store4 = GetDelegate(storeInfo4); + ASSERT_NE(store4, nullptr); + + SetTargetUserId(DEVICE_A, USER_ID_2); + SetTargetUserId(DEVICE_B, USER_ID_2); + BlockPush(storeInfo2, storeInfo4); + + CheckData(store4, KEY_1, {}); + CheckData(store4, KEY_2, {}); + CheckData(store4, KEY_3, {}); + CheckData(store4, KEY_4, VALUE_4); + + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo2), E_OK); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo4), E_OK); +} + +void DistributedDBKvMultiUserSyncTest::SyncStep3() +{ + StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + + StoreInfo storeInfo4 = {USER_ID_2, STORE_ID_2, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo4, DEVICE_B), E_OK); + auto store4 = GetDelegate(storeInfo4); + ASSERT_NE(store4, nullptr); + + SetTargetUserId(DEVICE_A, USER_ID_2); + SetTargetUserId(DEVICE_B, USER_ID_1); + BlockPush(storeInfo1, storeInfo4); + + CheckData(store4, KEY_1, VALUE_1); + CheckData(store4, KEY_2, VALUE_2); + CheckData(store4, KEY_3, VALUE_3); + CheckData(store4, KEY_4, VALUE_4); + + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo4), E_OK); +} + +/** + * @tc.name: NormalSyncTest001 + * @tc.desc: Test normal sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBKvMultiUserSyncTest, NormalSyncTest001, TestSize.Level1) +{ + /** + * @tc.steps: step1. (devA, user1) put 3 records, (devA, user2) put 1 record + * @tc.expected: step1. OK. + */ + PrepareData(); + /** + * @tc.steps: step2. (devA, user1) sync to (devB, user1) + * @tc.expected: step2. OK. + */ + SyncStep1(); + /** + * @tc.steps: step3. (devA, user2) put 3 records, (devB, user2) put 1 record + * @tc.expected: step3. OK. + */ + SyncStep2(); + /** + * @tc.steps: step4. (devA, user1) put 3 records, (devB, user2) put 1 record + * @tc.expected: step4. OK. + */ + SyncStep3(); +} + +/** + * @tc.name: NormalSyncTest002 + * @tc.desc: Test sync with low version target. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBKvMultiUserSyncTest, NormalSyncTest002, TestSize.Level0) +{ + /** + * @tc.steps: step1. Init process communicator + * @tc.expected: step1. OK. + */ + KvStoreNbDelegate::Option option; + option.syncDualTupleMode = true; + SetOption(option); + std::shared_ptr processCommunicator = + std::make_shared(); + processCommunicator->SetDataHeadInfo({DBStatus::LOW_VERSION_TARGET, 0u}); + SetProcessCommunicator(processCommunicator); + + /** + * @tc.steps: step2. (devA, user1) put 1 record and sync to (devB, user2) + * @tc.expected: step2. OK. + */ + StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + EXPECT_EQ(store1->Put(KEY_1, VALUE_1), OK); + + StoreInfo storeInfo2 = {USER_ID_2, STORE_ID_2, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_B), E_OK); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + + SetTargetUserId(DEVICE_A, USER_ID_2); + SetTargetUserId(DEVICE_B, USER_ID_1); + UserInfo userInfo = {.receiveUser = USER_ID_2, .sendUser = USER_ID_1}; + processCommunicator->SetDataUserInfo({{userInfo}}); + BlockPush(storeInfo1, storeInfo2); + + CheckData(store2, KEY_1, VALUE_1); + + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo2), E_OK); + + /** + * @tc.steps: step3. (devA, user1) put 1 record and sync to (devB, user3) + * @tc.expected: step3. OK. + */ + StoreInfo storeInfo3 = {USER_ID_3, STORE_ID_2, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo3, DEVICE_B), E_OK); + auto store3 = GetDelegate(storeInfo3); + ASSERT_NE(store3, nullptr); + + EXPECT_EQ(store1->Put(KEY_2, VALUE_2), OK); + + SetTargetUserId(DEVICE_A, USER_ID_3); + SetTargetUserId(DEVICE_B, USER_ID_1); + userInfo = {.receiveUser = USER_ID_3, .sendUser = USER_ID_1}; + processCommunicator->SetDataUserInfo({{userInfo}}); + BlockPush(storeInfo1, storeInfo3); + + CheckData(store3, KEY_2, VALUE_2); + + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo3), E_OK); +} + +/** + * @tc.name: NormalSyncTest003 + * @tc.desc: deviceA:user1 put 2 records and sync to deviceB, deviceA:user1 delete 1 records, deviceA:user2 put + * 2 records and sync to deviceB, deviceA:user1 sync to deviceB. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBKvMultiUserSyncTest, NormalSyncTest003, TestSize.Level0) +{ + /** + * @tc.steps: step1. set option + * @tc.expected: step1. OK. + */ + KvStoreNbDelegate::Option option; + option.syncDualTupleMode = true; + option.conflictResolvePolicy = DEVICE_COLLABORATION; + SetOption(option); + + /** + * @tc.steps: step2. deviceA:user1 put 10 records and sync to deviceB, deviceA:user1 delete 1 records + * @tc.expected: step2. OK. + */ + StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + EXPECT_EQ(store1->Put(KEY_1, VALUE_1), OK); + EXPECT_EQ(store1->Put(KEY_2, VALUE_2), OK); + + StoreInfo storeInfo3 = {USER_ID_3, STORE_ID_2, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo3, DEVICE_B), E_OK); + auto store3 = GetDelegate(storeInfo3); + ASSERT_NE(store3, nullptr); + + SetTargetUserId(DEVICE_A, USER_ID_3); + SetTargetUserId(DEVICE_B, USER_ID_1); + BlockPush(storeInfo1, storeInfo3); + EXPECT_EQ(store1->Delete(KEY_1), OK); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + + /** + * @tc.steps: step3. deviceA:user2 put 2 records and sync to deviceB + * @tc.expected: step3. OK. + */ + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + + StoreInfo storeInfo2 = {USER_ID_2, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_A), E_OK); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + EXPECT_EQ(store2->Put(KEY_1, VALUE_1), OK); + EXPECT_EQ(store2->Put(KEY_2, VALUE_2), OK); + + SetTargetUserId(DEVICE_A, USER_ID_3); + SetTargetUserId(DEVICE_B, USER_ID_2); + BlockPush(storeInfo2, storeInfo3); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo2), E_OK); + + /** + * @tc.steps: step4. deviceA:user1 sync to deviceB. + * @tc.expected: step4. OK. + */ + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + BlockPush(storeInfo1, storeInfo3); + Value actualValue; + EXPECT_EQ(store3->Get(KEY_1, actualValue), NOT_FOUND); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo3), E_OK); +} + +/** + * @tc.name: InvalidSync001 + * @tc.desc: Test sync with empty target user. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBKvMultiUserSyncTest, InvalidSync001, TestSize.Level0) +{ + /** + * @tc.steps: step1. (devA, user1) put 3 records, (devA, user2) put 1 record + * @tc.expected: step1. OK. + */ + KvStoreNbDelegate::Option option; + option.syncDualTupleMode = true; + SetOption(option); + StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + + StoreInfo storeInfo2 = {USER_ID_2, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_B), E_OK); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + + EXPECT_EQ(store1->Put(KEY_1, VALUE_1), OK); + EXPECT_EQ(store1->Put(KEY_2, VALUE_2), OK); + EXPECT_EQ(store1->Put(KEY_3, VALUE_3), OK); + EXPECT_EQ(store2->Put(KEY_4, VALUE_4), OK); + + CheckData(store1, KEY_1, VALUE_1); + CheckData(store1, KEY_2, VALUE_2); + CheckData(store1, KEY_3, VALUE_3); + CheckData(store2, KEY_4, VALUE_4); + /** + * @tc.steps: step2. set empty target user and sync + * @tc.expected: step2. return OK. + */ + SetTargetUserId(DEVICE_A, ""); + BlockPush(storeInfo1, storeInfo2); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo2), E_OK); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_abnormal_kv_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_abnormal_kv_sync_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d1074eddeaa9453c2db60dc7a32cfad4446ffc79 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_abnormal_kv_sync_test.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2025 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_general_ut.h" + +namespace DistributedDB { +using namespace testing::ext; + +class DistributedDBAbnormalKVSyncTest : public KVGeneralUt { +public: + void SetUp() override; +}; + +void DistributedDBAbnormalKVSyncTest::SetUp() +{ + KVGeneralUt::SetUp(); + auto storeInfo1 = GetStoreInfo1(); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, "dev1"), E_OK); + auto storeInfo2 = GetStoreInfo2(); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, "dev2"), E_OK); +} + +/** + * @tc.name: SyncWithInvalidSoftwareVersionTest001 + * @tc.desc: Test ability sync after software version is invalid. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBAbnormalKVSyncTest, SyncWithInvalidSoftwareVersionTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. open store and sync first + * @tc.expected: step1. sync ok. + */ + auto storeInfo1 = GetStoreInfo1(); + auto storeInfo2 = GetStoreInfo2(); + BlockPush(storeInfo1, storeInfo2); + /** + * @tc.steps: step2. set version invalid and sync again after reopen store + * @tc.expected: step2. sync ok. + */ + ASSERT_EQ(SetRemoteSoftwareVersion(storeInfo1, "dev2", DBConstant::DEFAULT_USER, INT32_MAX), OK); + KVGeneralUt::CloseDelegate(storeInfo1); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, "dev1"), E_OK); + std::atomic msgCount = 0; + RegBeforeDispatch([&msgCount](const std::string &dev, const Message *inMsg) { + if (dev != "dev2" || inMsg->GetMessageId() != ABILITY_SYNC_MESSAGE) { + return; + } + msgCount++; + }); + BlockPush(storeInfo1, storeInfo2); + RegBeforeDispatch(nullptr); + EXPECT_GT(msgCount, 0); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_basic_kv_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_basic_kv_test.cpp index 416d4ead1d3523e0ef59096d39be09969e3ebd32..5795aca7199c421be6b098820bcc663712030651 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_basic_kv_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_basic_kv_test.cpp @@ -29,6 +29,8 @@ void DistributedDBBasicKVTest::SetUp() ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, "dev1"), E_OK); auto storeInfo2 = GetStoreInfo2(); ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, "dev2"), E_OK); + auto storeInfo3 = GetStoreInfo3(); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo3, "dev3"), E_OK); } /** @@ -56,5 +58,63 @@ HWTEST_F(DistributedDBBasicKVTest, ExampleSync001, TestSize.Level0) Value actualValue; EXPECT_EQ(store2->Get({'k'}, actualValue), OK); EXPECT_EQ(actualValue, expectValue); + /** + * @tc.steps: step2. dev2's schemaVersion and softwareVersion both equal to dev1's meta + * @tc.expected: step2. version both equal. + */ + auto [errCode, version] = GetRemoteSoftwareVersion(storeInfo1, "dev2", DBConstant::DEFAULT_USER); + EXPECT_EQ(errCode, OK); + EXPECT_EQ(version, static_cast(SOFTWARE_VERSION_CURRENT)); + std::tie(errCode, version) = GetRemoteSchemaVersion(storeInfo1, "dev2", DBConstant::DEFAULT_USER); + EXPECT_EQ(errCode, OK); + EXPECT_NE(version, 0); + uint64_t store2SchemaVersion = 0; + std::tie(errCode, store2SchemaVersion) = GetLocalSchemaVersion(storeInfo2); + EXPECT_EQ(errCode, E_OK); + EXPECT_EQ(version, store2SchemaVersion); +} + +/** + * @tc.name: WhitelistKvGet001 + * @tc.desc: Test kv get interface for whitelist. + * @tc.type: FUNC + * @tc.require: + * @tc.author: xd + */ +HWTEST_F(DistributedDBBasicKVTest, WhitelistKvGet001, TestSize.Level0) +{ + /** + * @tc.steps: step1. set whitelist appId, put (k,v) + * @tc.expected: step1. get (k,v) result. + */ + auto storeInfo3 = GetStoreInfo3(); + auto store3 = GetDelegate(storeInfo3); + ASSERT_NE(store3, nullptr); + Value expectValue = {'v'}; + EXPECT_EQ(store3->Put({'k'}, expectValue), OK); + Value actualValue; + EXPECT_EQ(store3->Get({'k'}, actualValue), OK); + EXPECT_EQ(actualValue, expectValue); + /** + * @tc.steps: step2. with transaction, set whitelist appId, put (k2,v) + * @tc.expected: step2. get (k2,v) result. + */ + store3->StartTransaction(); + EXPECT_EQ(store3->Put({'k', '2'}, expectValue), OK); + Value actualValue2; + EXPECT_EQ(store3->Get({'k', '2'}, actualValue2), OK); + EXPECT_EQ(actualValue2, expectValue); + store3->Commit(); + /** + * @tc.steps: step3. do not set whitelist appId, put (k,v) + * @tc.expected: step3. get (k,v) result. + */ + auto storeInfo2 = GetStoreInfo2(); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + EXPECT_EQ(store2->Put({'k'}, expectValue), OK); + Value actualValue3; + EXPECT_EQ(store2->Get({'k'}, actualValue3), OK); + EXPECT_EQ(actualValue3, expectValue); } } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_compress_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_compress_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a3ad8889bbe6f120b7416f1cb9f67145c0f0aea --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_compress_test.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2025 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_general_ut.h" + +namespace DistributedDB { +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +class DistributedDBKVCompressTest : public KVGeneralUt { +public: + void SetUp() override; +protected: + void PrepareEnv(bool isNeedCompressOnSync); + void TriggerPutAndSync(); + static constexpr const char *DEVICE_A = "DEVICE_A"; + static constexpr const char *DEVICE_B = "DEVICE_B"; +}; + +void DistributedDBKVCompressTest::SetUp() +{ + KVGeneralUt::SetUp(); +} + +void DistributedDBKVCompressTest::PrepareEnv(bool isNeedCompressOnSync) +{ + KVGeneralUt::CloseAllDelegate(); + KvStoreNbDelegate::Option option; + option.isNeedCompressOnSync = isNeedCompressOnSync; + option.compressionRate = 100; // compress rate is 100 + SetOption(option); + auto storeInfo1 = GetStoreInfo1(); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + auto storeInfo2 = GetStoreInfo2(); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_B), E_OK); +} + +void DistributedDBKVCompressTest::TriggerPutAndSync() +{ + auto storeInfo1 = GetStoreInfo1(); + auto storeInfo2 = GetStoreInfo2(); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + Value expectValue(DBConstant::MAX_VALUE_SIZE, 'v'); + EXPECT_EQ(store1->Put({'k'}, expectValue), OK); + BlockPush(storeInfo1, storeInfo2); + Value actualValue; + EXPECT_EQ(store2->Get({'k'}, actualValue), OK); + EXPECT_EQ(actualValue, expectValue); +} + +/** + * @tc.name: SyncTest001 + * @tc.desc: Test sync with compress. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBKVCompressTest, SyncTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Open store with compress + * @tc.expected: step1. Open ok + */ + ASSERT_NO_FATAL_FAILURE(PrepareEnv(true)); + /** + * @tc.steps: step2. dev1 put (k,v) and sync to dev2 + * @tc.expected: step2. sync should return OK and dev2 exist (k,v). + */ + auto size1 = GetAllSendMsgSize(); + ASSERT_NO_FATAL_FAILURE(TriggerPutAndSync()); + auto size2 = GetAllSendMsgSize(); + /** + * @tc.steps: step3. Open store without compress + * @tc.expected: step3. Open ok + */ + ASSERT_NO_FATAL_FAILURE(PrepareEnv(false)); + /** + * @tc.steps: step4. dev1 put (k,v) and sync to dev2 + * @tc.expected: step4. sync should return OK and dev2 exist (k,v). + */ + auto size3 = GetAllSendMsgSize(); + ASSERT_NO_FATAL_FAILURE(TriggerPutAndSync()); + auto size4 = GetAllSendMsgSize(); + EXPECT_LE(size2 - size1, size4 - size3); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_data_status_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_data_status_test.cpp index 71a331d6f42f6226f63c0a8b253a433e7cfa2932..51b0651db62140dcc86beaffffb04c241a13972b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_data_status_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_data_status_test.cpp @@ -19,7 +19,7 @@ namespace DistributedDB { using namespace testing::ext; using namespace DistributedDB; using namespace DistributedDBUnitTest; - + class DistributedDBKVDataStatusTest : public KVGeneralUt { public: void SetUp() override; @@ -29,7 +29,7 @@ protected: static constexpr const char *DEVICE_C = "DEVICE_C"; static const uint32_t INVALID_DATA_OPERATOR = 0; }; - + void DistributedDBKVDataStatusTest::SetUp() { KVGeneralUt::SetUp(); @@ -38,7 +38,7 @@ void DistributedDBKVDataStatusTest::SetUp() auto storeInfo2 = GetStoreInfo2(); ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_B), E_OK); } - + /** * @tc.name: OperateDataStatus001 * @tc.desc: Test sync from dev1 to dev2 after operate valid data status. @@ -86,7 +86,7 @@ HWTEST_F(DistributedDBKVDataStatusTest, OperateDataStatus001, TestSize.Level0) EXPECT_EQ(store2->Get({'k'}, actualValue), OK); EXPECT_EQ(actualValue, expectValue); } - + /** * @tc.name: OperateDataStatus002 * @tc.desc: Test sync from dev1 to dev2 after operate invalid data status. @@ -175,6 +175,49 @@ HWTEST_F(DistributedDBKVDataStatusTest, OperateDataStatus003, TestSize.Level0) EXPECT_EQ(entries.size(), 0u); // 0 record } +/** + * @tc.name: OperateDataStatus004 + * @tc.desc: Test sync with delete data. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBKVDataStatusTest, OperateDataStatus004, TestSize.Level0) +{ + /** + * @tc.steps: step1. dev1 put (k,v) and sync to dev2 + * @tc.expected: step1. sync should return OK and dev2 exist (k,v). + */ + auto storeInfo1 = GetStoreInfo1(); + auto storeInfo2 = GetStoreInfo2(); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + Value expectValue = {'v'}; + EXPECT_EQ(store1->Put({'k'}, expectValue), OK); + BlockPush(storeInfo1, storeInfo2); + EXPECT_EQ(store1->Delete({'k'}), OK); + BlockPush(storeInfo1, storeInfo2); + /** + * @tc.steps: step2. dev1 modify deviceId and operate data status RESET_UPLOAD_CLOUD + * @tc.expected: step2. OK. + */ + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_C), E_OK); + store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + EXPECT_EQ(store1->OperateDataStatus(static_cast(DataOperator::RESET_UPLOAD_CLOUD)), OK); + /** + * @tc.steps: step3. dev1 sync to dev2 + * @tc.expected: step3. sync should return OK and dev2 get entries by device return NOT_FOUND. + */ + BlockPush(storeInfo1, storeInfo2); + std::vector entries; + EXPECT_EQ(KVGeneralUt::GetDeviceEntries(store2, std::string(DEVICE_C), false, entries), NOT_FOUND); + EXPECT_EQ(entries.size(), 0u); // 0 record +} + #ifdef USE_DISTRIBUTEDDB_CLOUD /** * @tc.name: CloudOperateDataStatus001 diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_device_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_device_sync_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c936faec7b83ce750a4e1954346e05fe5425fda9 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_device_sync_test.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2025 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_general_ut.h" +#include "kv_store_nb_delegate_impl.h" + +namespace DistributedDB { + using namespace testing::ext; + using namespace DistributedDB; + using namespace DistributedDBUnitTest; + +class DistributedDBKvDeviceSyncTest : public KVGeneralUt { +public: + void SetUp() override; +protected: + static constexpr const char *DEVICE_A = "DEVICE_A"; + static constexpr const char *DEVICE_B = "DEVICE_B"; + DistributedDBToolsUnitTest g_tool; +}; + +void DistributedDBKvDeviceSyncTest::SetUp() +{ + KVGeneralUt::SetUp(); + auto storeInfo1 = GetStoreInfo1(); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + auto storeInfo2 = GetStoreInfo2(); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_B), E_OK); +} + +/** + * @tc.name: NormalSyncTest001 + * @tc.desc: Test normal sync without retry. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBKvDeviceSyncTest, NormalSyncTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. dev1 put (k,v) + * @tc.expected: step1. return OK + */ + auto storeInfo1 = GetStoreInfo1(); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + Key key = {'k'}; + Value expectValue = {'v'}; + EXPECT_EQ(store1->Put(key, expectValue), OK); + /** + * @tc.steps: step2. dev1 sync to dev2 + * @tc.expected: step2. return OK and dev2 exist (k,v) + */ + DeviceSyncOption option; + option.devices = {DEVICE_B}; + option.mode = SYNC_MODE_PUSH_ONLY; + option.isRetry = false; + std::map syncRet; + EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), OK); + for (const auto &ret : syncRet) { + EXPECT_EQ(ret.first, DEVICE_B); + EXPECT_EQ(ret.second, OK); + } + auto storeInfo2 = GetStoreInfo2(); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + Value actualValue; + EXPECT_EQ(store2->Get(key, actualValue), OK); + EXPECT_EQ(actualValue, expectValue); +} + +/** + * @tc.name: AbnormalKvSyncTest001 + * @tc.desc: Test sync with invalid args. + * @tc.type: FUNC + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBKvDeviceSyncTest, AbnormalKvSyncTest001, TestSize.Level1) +{ + /** + * @tc.steps: step1. dev1 put (k,v) + * @tc.expected: step1. return OK + */ + auto storeInfo1 = GetStoreInfo1(); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + Key key = {'k'}; + Value expectValue = {'v'}; + EXPECT_EQ(store1->Put(key, expectValue), OK); + /** + * @tc.steps: step2. dev1 sync to dev2 with invalid mode + * @tc.expected: step2. return NOT_SUPPORT + */ + DeviceSyncOption option; + option.devices = {DEVICE_B}; + option.mode = SYNC_MODE_CLOUD_MERGE; + option.isRetry = false; + std::map syncRet; + EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), NOT_SUPPORT); + auto storeInfo2 = GetStoreInfo2(); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + Value actualValue; + EXPECT_EQ(store2->Get(key, actualValue), NOT_FOUND); + option.mode = SYNC_MODE_PUSH_PULL; + /** + * @tc.steps: step3. dev1 sync to dev2 with invalid query + * @tc.expected: step3. return NOT_SUPPORT + */ + option.isQuery = true; + option.query = Query::Select().FromTable({"table1", "table2"}); + EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), NOT_SUPPORT); + EXPECT_EQ(store2->Get(key, actualValue), NOT_FOUND); + option.query = Query::Select().From("A").From("B"); + EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), NOT_SUPPORT); + EXPECT_EQ(store2->Get(key, actualValue), NOT_FOUND); + /** + * @tc.steps: step4. dev1 sync to dev2 with empty devices + * @tc.expected: step4. return NOT_SUPPORT + */ + option.devices.clear(); + option.isQuery = false; + EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), INVALID_ARGS); + EXPECT_EQ(store2->Get(key, actualValue), NOT_FOUND); + /** + * @tc.steps: step5. dev1 sync to dev2 after close db + * @tc.expected: step5. return DB_ERROR + */ + auto kvStoreImpl = static_cast(store1); + EXPECT_EQ(kvStoreImpl->Close(), OK); + EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), DB_ERROR); + EXPECT_EQ(store2->Get(key, actualValue), NOT_FOUND); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distracteddb_rdb_multi_user_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distracteddb_rdb_multi_user_sync_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..686790f4261ece17d91e1f62652367edc3fbf5da --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distracteddb_rdb_multi_user_sync_test.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2025 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 "rdb_general_ut.h" + +namespace DistributedDB { + using namespace testing::ext; + using namespace DistributedDB; + using namespace DistributedDBUnitTest; + +class DistributedDBRDBMultiUserSyncTest : public RDBGeneralUt { +public: + void SetUp() override; +protected: + static constexpr const char *DEVICE_SYNC_TABLE = "DEVICE_SYNC_TABLE"; + static constexpr const char *DEVICE_A = "DEVICE_A"; + static constexpr const char *DEVICE_B = "DEVICE_B"; + static constexpr const char *USER_ID_1 = "userId1"; + static constexpr const char *USER_ID_2 = "userId2"; + static UtDateBaseSchemaInfo GetDefaultSchema(); + static UtTableSchemaInfo GetTableSchema(const std::string &table, bool noPk = false); + static void SetTargetUserId(const std::string &deviceId, const std::string &userId); +}; + +void DistributedDBRDBMultiUserSyncTest::SetUp() +{ + RDBGeneralUt::SetUp(); + RelationalStoreDelegate::Option option; + option.syncDualTupleMode = true; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); +} + +UtDateBaseSchemaInfo DistributedDBRDBMultiUserSyncTest::GetDefaultSchema() +{ + UtDateBaseSchemaInfo info; + info.tablesInfo.push_back(GetTableSchema(DEVICE_SYNC_TABLE)); + return info; +} + +UtTableSchemaInfo DistributedDBRDBMultiUserSyncTest::GetTableSchema(const std::string &table, bool noPk) +{ + UtTableSchemaInfo tableSchema; + tableSchema.name = table; + UtFieldInfo fieldId; + fieldId.field.colName = "id"; + fieldId.field.type = TYPE_INDEX; + if (!noPk) { + fieldId.field.primary = true; + } + tableSchema.fieldInfo.push_back(fieldId); + UtFieldInfo fieldName; + fieldName.field.colName = "name"; + fieldName.field.type = TYPE_INDEX; + tableSchema.fieldInfo.push_back(fieldName); + return tableSchema; +} + +void DistributedDBRDBMultiUserSyncTest::SetTargetUserId(const std::string &deviceId, const std::string &userId) +{ + ICommunicatorAggregator *communicatorAggregator = nullptr; + RuntimeContext::GetInstance()->GetCommunicatorAggregator(communicatorAggregator); + ASSERT_NE(communicatorAggregator, nullptr); + auto virtualCommunicatorAggregator = static_cast(communicatorAggregator); + auto communicator = static_cast(virtualCommunicatorAggregator->GetCommunicator(deviceId)); + ASSERT_NE(communicator, nullptr); + communicator->SetTargetUserId(userId); +} + +HWTEST_F(DistributedDBRDBMultiUserSyncTest, NormalSyncTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Prepare db and data. + * @tc.expected: step1. Ok + */ + StoreInfo deviceAStore1 = {USER_ID_1, APP_ID, STORE_ID_1}; + StoreInfo deviceAStore2 = {USER_ID_2, APP_ID, STORE_ID_2}; + StoreInfo deviceBStore = {USER_ID_1, APP_ID, STORE_ID_3}; + + SetSchemaInfo(deviceAStore1, GetDefaultSchema()); + SetSchemaInfo(deviceAStore2, GetDefaultSchema()); + SetSchemaInfo(deviceBStore, GetDefaultSchema()); + + ASSERT_EQ(BasicUnitTest::InitDelegate(deviceAStore1, DEVICE_A), E_OK); + ASSERT_EQ(BasicUnitTest::InitDelegate(deviceAStore2, DEVICE_A), E_OK); + ASSERT_EQ(BasicUnitTest::InitDelegate(deviceBStore, DEVICE_B), E_OK); + + ASSERT_EQ(SetDistributedTables(deviceAStore1, {DEVICE_SYNC_TABLE}), E_OK); + ASSERT_EQ(SetDistributedTables(deviceAStore2, {DEVICE_SYNC_TABLE}), E_OK); + ASSERT_EQ(SetDistributedTables(deviceBStore, {DEVICE_SYNC_TABLE}), E_OK); + + InsertLocalDBData(0, 1, deviceAStore1); + InsertLocalDBData(0, 1, deviceAStore2); + sqlite3 *dbA2 = GetSqliteHandle(deviceAStore2); + std::string updateSql = "update " + std::string(DEVICE_SYNC_TABLE) + " set name = 'new_name' where id = 0;"; + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(dbA2, updateSql), E_OK); + + ASSERT_EQ(RDBGeneralUt::CloseDelegate(deviceAStore1), OK); + ASSERT_EQ(RDBGeneralUt::CloseDelegate(deviceAStore2), OK); + /** + * @tc.steps: step2. Sync from db2 of deviceA to deviceB. + * @tc.expected: step2. Ok + */ + ASSERT_EQ(BasicUnitTest::InitDelegate(deviceAStore2, DEVICE_A), E_OK); + SetTargetUserId(DEVICE_A, USER_ID_1); + SetTargetUserId(DEVICE_B, USER_ID_2); + BlockPush(deviceAStore2, deviceBStore, DEVICE_SYNC_TABLE); + ASSERT_EQ(RDBGeneralUt::CloseDelegate(deviceAStore2), OK); + /** + * @tc.steps: step3. Sync from db1 of deviceA to deviceB. + * @tc.expected: step3. Ok + */ + ASSERT_EQ(BasicUnitTest::InitDelegate(deviceAStore1, DEVICE_A), E_OK); + SetTargetUserId(DEVICE_A, USER_ID_1); + SetTargetUserId(DEVICE_B, USER_ID_1); + BlockPush(deviceAStore1, deviceBStore, DEVICE_SYNC_TABLE); + ASSERT_EQ(RDBGeneralUt::CloseDelegate(deviceAStore1), OK); + /** + * @tc.steps: step4. Check data in deviceB. + * @tc.expected: step4. Ok + */ + std::string checkSql = "select count(*) from " + std::string(DEVICE_SYNC_TABLE) + " where name = 'new_name';"; + sqlite3 *dbB = GetSqliteHandle(deviceBStore); + int actualCount = 0; + ASSERT_EQ(SQLiteUtils::GetCountBySql(dbB, checkSql, actualCount), E_OK); + EXPECT_EQ(actualCount, 1); + ASSERT_EQ(RDBGeneralUt::CloseDelegate(deviceBStore), OK); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_basic_rdb_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_basic_rdb_test.cpp index ba3a7cbeae9a991556a03fbc182afd029d69313a..a0ef9225410ec0203e35f8db11112f0e1f5b8276 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_basic_rdb_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_basic_rdb_test.cpp @@ -14,6 +14,7 @@ */ #include "rdb_general_ut.h" +#include "sqlite_relational_utils.h" using namespace testing::ext; using namespace DistributedDB; @@ -54,7 +55,7 @@ HWTEST_F(DistributedDBBasicRDBTest, InitDelegateExample001, TestSize.Level0) * @tc.expected: step1. Ok */ StoreInfo info1 = {USER_ID, APP_ID, STORE_ID_1}; - EXPECT_EQ(RDBGeneralUt::InitDelegate(info1), E_OK); + EXPECT_EQ(BasicUnitTest::InitDelegate(info1, "dev1"), E_OK); DataBaseSchema actualSchemaInfo = RDBGeneralUt::GetSchema(info1); ASSERT_EQ(actualSchemaInfo.tables.size(), 2u); EXPECT_EQ(actualSchemaInfo.tables[0].name, g_defaultTable1); @@ -70,11 +71,11 @@ HWTEST_F(DistributedDBBasicRDBTest, InitDelegateExample001, TestSize.Level0) UtDateBaseSchemaInfo schemaInfo = { .tablesInfo = {{.name = DEVICE_SYNC_TABLE, .fieldInfo = filedInfo}} }; - RDBGeneralUt::AddSchemaInfo(info1, schemaInfo); + RDBGeneralUt::SetSchemaInfo(info1, schemaInfo); RelationalStoreDelegate::Option option; option.tableMode = DistributedTableMode::COLLABORATION; SetOption(option); - EXPECT_EQ(RDBGeneralUt::InitDelegate(info1), E_OK); + EXPECT_EQ(BasicUnitTest::InitDelegate(info1, "dev1"), E_OK); StoreInfo info2 = {USER_ID, APP_ID, STORE_ID_2}; schemaInfo = { @@ -83,12 +84,140 @@ HWTEST_F(DistributedDBBasicRDBTest, InitDelegateExample001, TestSize.Level0) {.name = CLOUD_SYNC_TABLE, .fieldInfo = filedInfo}, } }; - RDBGeneralUt::AddSchemaInfo(info2, schemaInfo); - EXPECT_EQ(RDBGeneralUt::InitDelegate(info2), E_OK); + RDBGeneralUt::SetSchemaInfo(info2, schemaInfo); + EXPECT_EQ(BasicUnitTest::InitDelegate(info2, "dev2"), E_OK); actualSchemaInfo = RDBGeneralUt::GetSchema(info2); ASSERT_EQ(actualSchemaInfo.tables.size(), schemaInfo.tablesInfo.size()); EXPECT_EQ(actualSchemaInfo.tables[1].name, CLOUD_SYNC_TABLE); TableSchema actualTableInfo = RDBGeneralUt::GetTableSchema(info2, CLOUD_SYNC_TABLE); EXPECT_EQ(actualTableInfo.fields.size(), filedInfo.size()); } + +/** + * @tc.name: RdbSyncExample001 + * @tc.desc: Test insert data and sync from dev1 to dev2. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBBasicRDBTest, RdbSyncExample001, TestSize.Level0) +{ + /** + * @tc.steps: step1. dev1 insert data. + * @tc.expected: step1. Ok + */ + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + auto info1 = GetStoreInfo1(); + ASSERT_EQ(BasicUnitTest::InitDelegate(info1, "dev1"), E_OK); + auto info2 = GetStoreInfo2(); + ASSERT_EQ(BasicUnitTest::InitDelegate(info2, "dev2"), E_OK); + InsertLocalDBData(0, 2, info1); + EXPECT_EQ(RDBGeneralUt::CountTableData(info1, g_defaultTable1), 2); + EXPECT_EQ(RDBGeneralUt::CountTableData(info2, g_defaultTable1), 0); + + /** + * @tc.steps: step2. create distributed tables and sync to dev1. + * @tc.expected: step2. Ok + */ + ASSERT_EQ(SetDistributedTables(info1, {g_defaultTable1}), E_OK); + ASSERT_EQ(SetDistributedTables(info2, {g_defaultTable1}), E_OK); + BlockPush(info1, info2, g_defaultTable1); + EXPECT_EQ(RDBGeneralUt::CountTableData(info2, g_defaultTable1), 2); +} + +#ifdef USE_DISTRIBUTEDDB_CLOUD +/** + * @tc.name: RdbCloudSyncExample001 + * @tc.desc: Test cloud sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBBasicRDBTest, RdbCloudSyncExample001, TestSize.Level0) +{ + /** + * @tc.steps: step1. sync dev1 data to cloud. + * @tc.expected: step1. Ok + */ + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + auto info1 = GetStoreInfo1(); + ASSERT_EQ(BasicUnitTest::InitDelegate(info1, "dev1"), E_OK); + InsertLocalDBData(0, 2, info1); + EXPECT_EQ(RDBGeneralUt::CountTableData(info1, g_defaultTable1), 2); + + ASSERT_EQ(SetDistributedTables(info1, {g_defaultTable1}, TableSyncType::CLOUD_COOPERATION), E_OK); + RDBGeneralUt::SetCloudDbConfig(info1); + Query query = Query::Select().FromTable({g_defaultTable1}); + RDBGeneralUt::CloudBlockSync(info1, query); + EXPECT_EQ(RDBGeneralUt::GetCloudDataCount(g_defaultTable1), 2); +} + +/** + * @tc.name: RdbCloudSyncExample002 + * @tc.desc: Test cloud insert data and cloud sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBBasicRDBTest, RdbCloudSyncExample002, TestSize.Level0) +{ + /** + * @tc.steps: step1. cloud insert data. + * @tc.expected: step1. Ok + */ + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + auto info1 = GetStoreInfo1(); + ASSERT_EQ(BasicUnitTest::InitDelegate(info1, "dev1"), E_OK); + ASSERT_EQ(SetDistributedTables(info1, {g_defaultTable1}, TableSyncType::CLOUD_COOPERATION), E_OK); + RDBGeneralUt::SetCloudDbConfig(info1); + std::shared_ptr virtualCloudDb = RDBGeneralUt::GetVirtualCloudDb(); + ASSERT_NE(virtualCloudDb, nullptr); + EXPECT_EQ(RDBDataGenerator::InsertCloudDBData(0, 20, 0, RDBGeneralUt::GetSchema(info1), virtualCloudDb), OK); + EXPECT_EQ(RDBGeneralUt::GetCloudDataCount(g_defaultTable1), 20); + EXPECT_EQ(RDBGeneralUt::CountTableData(info1, g_defaultTable1), 0); + + /** + * @tc.steps: step2. cloud sync data to dev1. + * @tc.expected: step2. Ok + */ + Query query = Query::Select().FromTable({g_defaultTable1}); + RDBGeneralUt::CloudBlockSync(info1, query); + EXPECT_EQ(RDBGeneralUt::CountTableData(info1, g_defaultTable1), 20); +} +#endif // USE_DISTRIBUTEDDB_CLOUD + +/** + * @tc.name: RdbUtilsTest001 + * @tc.desc: Test rdb utils execute actions. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBBasicRDBTest, RdbUtilsTest001, TestSize.Level0) +{ + std::vector> actions; + /** + * @tc.steps: step1. execute null actions no effect ret. + * @tc.expected: step1. E_OK + */ + actions.emplace_back(nullptr); + EXPECT_EQ(SQLiteRelationalUtils::ExecuteListAction(actions), E_OK); + /** + * @tc.steps: step2. execute abort when action return error. + * @tc.expected: step2. -E_INVALID_ARGS + */ + actions.clear(); + actions.emplace_back([]() { + return -E_INVALID_ARGS; + }); + actions.emplace_back([]() { + return -E_NOT_SUPPORT; + }); + EXPECT_EQ(SQLiteRelationalUtils::ExecuteListAction(actions), -E_INVALID_ARGS); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_compress_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_compress_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a8c07347db16d21054d1698413bcdb6476af9cae --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_compress_test.cpp @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2025 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 "rdb_general_ut.h" +#include "relational_store_delegate_impl.h" +#include "single_ver_relational_syncer.h" +#include "sqlite_relational_store.h" +#include "sqlite_relational_store_connection.h" +#include "sync_able_engine.h" +#include "mock_sync_engine.h" + +namespace DistributedDB { +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +class DistributedDBRDBCompressTest : public RDBGeneralUt { +public: + void SetUp() override; +protected: + void InitOption(DistributedTableMode tableMode, bool isNeedCompressOnSync, uint8_t compressRate); + void InitInfo(const StoreInfo &info, const char *dev, DistributedTableMode tableMode, + bool isNeedCompressOnSync, uint8_t compressRate); + void SimpleSyncTest(bool store1Compress, bool store2Compress, uint8_t store1Rate, uint8_t store2Rate, + SyncMode mode); + void CompressTest(bool store1Compress, bool store2Compress, uint8_t store1Rate, + uint8_t store2Rate, SyncMode mode); + static UtDateBaseSchemaInfo GetDefaultSchema(); + static UtTableSchemaInfo GetTableSchema(const std::string &table); + static std::string GetInsertSQL(); + static std::string GetConditionSQL(); + static constexpr const char *DEVICE_SYNC_TABLE = "DEVICE_SYNC_TABLE"; + static constexpr const char *DEVICE_A = "DEVICE_A"; + static constexpr const char *DEVICE_B = "DEVICE_B"; + const StoreInfo info1_ = {USER_ID, APP_ID, STORE_ID_1}; + const StoreInfo info2_ = {USER_ID, APP_ID, STORE_ID_2}; + std::atomic mode_ = DistributedTableMode::COLLABORATION; +}; + +void DistributedDBRDBCompressTest::SetUp() +{ + mode_ = DistributedTableMode::COLLABORATION; + RDBGeneralUt::SetUp(); + SetSchemaInfo(info1_, GetDefaultSchema()); + SetSchemaInfo(info2_, GetDefaultSchema()); +} + +void DistributedDBRDBCompressTest::InitOption(DistributedTableMode tableMode, bool isNeedCompressOnSync, + uint8_t compressRate) +{ + RelationalStoreDelegate::Option option; + option.tableMode = tableMode; + option.isNeedCompressOnSync = isNeedCompressOnSync; + option.compressionRate = compressRate; + SetOption(option); +} + +void DistributedDBRDBCompressTest::InitInfo(const StoreInfo &info, const char *dev, DistributedTableMode tableMode, + bool isNeedCompressOnSync, uint8_t compressRate) +{ + InitOption(tableMode, isNeedCompressOnSync, compressRate); + ASSERT_EQ(BasicUnitTest::InitDelegate(info, dev), E_OK); + ASSERT_EQ(SetDistributedTables(info, {DEVICE_SYNC_TABLE}), E_OK); +} + +UtDateBaseSchemaInfo DistributedDBRDBCompressTest::GetDefaultSchema() +{ + UtDateBaseSchemaInfo info; + info.tablesInfo.push_back(GetTableSchema(DEVICE_SYNC_TABLE)); + return info; +} + +UtTableSchemaInfo DistributedDBRDBCompressTest::GetTableSchema(const std::string &table) +{ + UtTableSchemaInfo tableSchema; + tableSchema.name = table; + UtFieldInfo field; + field.field.colName = "id"; + field.field.type = TYPE_INDEX; + field.field.primary = true; + tableSchema.fieldInfo.push_back(field); + field.field.colName = "val"; + field.field.type = TYPE_INDEX; + field.field.primary = false; + tableSchema.fieldInfo.push_back(field); + return tableSchema; +} + +std::string DistributedDBRDBCompressTest::GetInsertSQL() +{ + std::string sql = "INSERT OR REPLACE INTO "; + sql.append(DEVICE_SYNC_TABLE).append("(id, val) VALUES(1, '"); + for (size_t i = 0; i < 1000; ++i) { // 1000 is data len + sql.append("v"); + } + sql.append("')"); + return sql; +} + +std::string DistributedDBRDBCompressTest::GetConditionSQL() +{ + std::string condition = " id=1 AND val='"; + for (size_t i = 0; i < 1000; ++i) { // 1000 is data len + condition.append("v"); + } + condition.append("' "); + return condition; +} + +void DistributedDBRDBCompressTest::SimpleSyncTest(bool store1Compress, bool store2Compress, uint8_t store1Rate, + uint8_t store2Rate, SyncMode mode) +{ + LOGI("SimpleSyncTest begin store1Compress %d store2Compress %d store1Rate %" PRIu8 " store2Rate %" PRIu8, + store1Compress, store2Compress, store1Rate, store2Rate); + RDBGeneralUt::CloseAllDelegate(); + SetSchemaInfo(info1_, GetDefaultSchema()); + SetSchemaInfo(info2_, GetDefaultSchema()); + /** + * @tc.steps: step1. Init store1 and store2. + * @tc.expected: step1. Ok + */ + ASSERT_NO_FATAL_FAILURE(InitInfo(info1_, DEVICE_A, mode_, store1Compress, + store1Rate)); + ASSERT_NO_FATAL_FAILURE(InitInfo(info2_, DEVICE_B, mode_, store2Compress, + store2Rate)); + /** + * @tc.steps: step2. Store1 insert local data. + * @tc.expected: step2. Ok + */ + ExecuteSQL(GetInsertSQL(), info1_); + /** + * @tc.steps: step3. DEV_A sync to DEV_B. + * @tc.expected: step3. Ok + */ + if (mode == SYNC_MODE_PUSH_ONLY) { + ASSERT_NO_FATAL_FAILURE(BlockPush(info1_, info2_, DEVICE_SYNC_TABLE)); + } else if (mode == SYNC_MODE_PULL_ONLY) { + ASSERT_NO_FATAL_FAILURE(BlockPull(info2_, info1_, DEVICE_SYNC_TABLE)); + } + /** + * @tc.steps: step4. Check store2's data. + * @tc.expected: step4. Exist 1 row + */ + if (mode_ == DistributedTableMode::COLLABORATION) { + EXPECT_EQ(CountTableData(info2_, DEVICE_SYNC_TABLE, GetConditionSQL()), 1); + } else if (mode_ == DistributedTableMode::SPLIT_BY_DEVICE) { + EXPECT_EQ(CountTableData(info2_, + DBCommon::GetDistributedTableName(DEVICE_A, DEVICE_SYNC_TABLE), GetConditionSQL()), 1); + } +} + +void DistributedDBRDBCompressTest::CompressTest(bool store1Compress, bool store2Compress, uint8_t store1Rate, + uint8_t store2Rate, SyncMode mode) +{ + /** + * @tc.steps: step1. Store1 sync to store2 with compress. + * @tc.expected: step1. Sync ok + */ + auto size1 = GetAllSendMsgSize(); + SimpleSyncTest(store1Compress, store2Compress, store1Rate, store2Rate, mode); // both compress rate is 100 + auto size2 = GetAllSendMsgSize(); + /** + * @tc.steps: step2. Store1 sync to store2 without compress. + * @tc.expected: step2. Sync ok and + */ + auto size3 = GetAllSendMsgSize(); + SimpleSyncTest(store1Compress, store2Compress, store1Rate, store2Rate, mode); // both compress rate is 100 + auto size4 = GetAllSendMsgSize(); + EXPECT_LE(size2 - size1, size4 - size3); +} + +/** + * @tc.name: RDBCompressSync001 + * @tc.desc: Test collaboration table push sync with compress. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBCompressSync001, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(CompressTest(true, true, 100, 100, SyncMode::SYNC_MODE_PUSH_ONLY)); +} + +/** + * @tc.name: RDBCompressSync002 + * @tc.desc: Test collaboration table pull sync with compress. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBCompressSync002, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(CompressTest(true, true, 100, 100, SyncMode::SYNC_MODE_PULL_ONLY)); +} + +/** + * @tc.name: RDBCompressSync003 + * @tc.desc: Test split table push sync with compress. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBCompressSync003, TestSize.Level1) +{ + mode_ = DistributedTableMode::SPLIT_BY_DEVICE; + ASSERT_NO_FATAL_FAILURE(CompressTest(true, true, 100, 100, SyncMode::SYNC_MODE_PUSH_ONLY)); +} + +/** + * @tc.name: RDBCompressSync004 + * @tc.desc: Test split table pull sync with compress. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBCompressSync004, TestSize.Level1) +{ + mode_ = DistributedTableMode::SPLIT_BY_DEVICE; + ASSERT_NO_FATAL_FAILURE(CompressTest(true, true, 100, 100, SyncMode::SYNC_MODE_PULL_ONLY)); +} + +/** + * @tc.name: RDBCompressSync005 + * @tc.desc: Test collaboration table push sync with compress but remote is not compress. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBCompressSync005, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(CompressTest(true, false, 100, 100, SyncMode::SYNC_MODE_PUSH_ONLY)); +} + +/** + * @tc.name: RDBCompressSync006 + * @tc.desc: Test collaboration table pull sync with compress but remote is not compress. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBCompressSync006, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(CompressTest(true, false, 100, 100, SyncMode::SYNC_MODE_PULL_ONLY)); +} + +/** + * @tc.name: RDBInvalidCompress001 + * @tc.desc: Test open store with invalid compress option. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBInvalidCompress001, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(InitInfo(info1_, DEVICE_A, mode_, true, 0)); + RDBGeneralUt::CloseAllDelegate(); + ASSERT_NO_FATAL_FAILURE(InitInfo(info1_, DEVICE_A, mode_, true, 101)); // compress rate is 101 + RDBGeneralUt::CloseAllDelegate(); + ASSERT_NO_FATAL_FAILURE(InitInfo(info1_, DEVICE_A, mode_, false, 0)); + RDBGeneralUt::CloseAllDelegate(); + ASSERT_NO_FATAL_FAILURE(InitInfo(info1_, DEVICE_A, mode_, false, 101)); // compress rate is 101 +} + +/** + * @tc.name: RDBInvalidCompress001 + * @tc.desc: Test open store with invalid compress option. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBInvalidCompress002, TestSize.Level0) +{ + /** + * @tc.steps: step1. Open store1 with compress and rate1. + * @tc.expected: step1. Open ok + */ + ASSERT_NO_FATAL_FAILURE(InitInfo(info1_, DEVICE_A, mode_, true, 1)); + /** + * @tc.steps: step2. Open store1 with compress and rate2. + * @tc.expected: step2. Open failed by conflict with cache + */ + InitOption(mode_, true, 2); // compress rate is 2 + auto [errCode, delegate] = OpenRDBStore(info1_); + EXPECT_EQ(errCode, INVALID_ARGS); + EXPECT_EQ(delegate, nullptr); + /** + * @tc.steps: step3. Open store1 without compress and rate1. + * @tc.expected: step3. Open failed by conflict with cache + */ + InitOption(mode_, false, 1); // compress rate is 1 + std::tie(errCode, delegate) = OpenRDBStore(info1_); + EXPECT_EQ(errCode, INVALID_ARGS); + EXPECT_EQ(delegate, nullptr); + InitOption(mode_, true, 100); // compress rate is 100 + std::tie(errCode, delegate) = OpenRDBStore(info1_); + EXPECT_EQ(errCode, INVALID_ARGS); + EXPECT_EQ(delegate, nullptr); + /** + * @tc.steps: step4. Open store1 without compress and rate100 after close store1. + * @tc.expected: step4. Open ok + */ + RDBGeneralUt::CloseAllDelegate(); + /** + * @tc.steps: step5. Open store1 without compress and rate100. + * @tc.expected: step5. Open ok + */ + ASSERT_NO_FATAL_FAILURE(InitInfo(info1_, DEVICE_A, mode_, false, 100)); // compress rate is 100 + InitOption(mode_, false, 2); // compress rate is 2 + std::tie(errCode, delegate) = OpenRDBStore(info1_); + EXPECT_EQ(errCode, OK); + ASSERT_NE(delegate, nullptr); + RelationalStoreManager mgr(info1_.appId, info1_.userId); + mgr.CloseStore(delegate); +} + +/** + * @tc.name: RDBGetDevTaskCount001 + * @tc.desc: Test get dev task count when sync. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBGetDevTaskCount001, TestSize.Level0) +{ + std::atomic checkFlag = false; + RegBeforeDispatch([this, &checkFlag](const std::string &dev, const Message *inMsg) { + if (dev != DEVICE_B || inMsg->GetMessageId() != QUERY_SYNC_MESSAGE) { + return; + } + if (checkFlag) { + return; + } + checkFlag = true; + auto store1 = GetDelegate(info1_); + ASSERT_NE(store1, nullptr); + EXPECT_GT(store1->GetDeviceSyncTaskCount(), 0); + auto store2 = GetDelegate(info2_); + ASSERT_NE(store2, nullptr); + EXPECT_GT(store2->GetDeviceSyncTaskCount(), 0); + }); + CompressTest(true, true, 100, 100, SyncMode::SYNC_MODE_PULL_ONLY); + RegBeforeDispatch(nullptr); +} + +/** + * @tc.name: VerifyDeviceSyncTaskCountAfterRemoteQuery001 + * @tc.desc: Test get device task count when remote query. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, VerifyDeviceSyncTaskCountAfterRemoteQuery001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Init store1 and store2. + * @tc.expected: step1. Ok + */ + RDBGeneralUt::CloseAllDelegate(); + SetSchemaInfo(info1_, GetDefaultSchema()); + SetSchemaInfo(info2_, GetDefaultSchema()); + ASSERT_NO_FATAL_FAILURE(InitInfo(info1_, DEVICE_A, mode_, true, 100)); // compress rate is 100 + ASSERT_NO_FATAL_FAILURE(InitInfo(info2_, DEVICE_B, mode_, true, 100)); // compress rate is 100 + std::atomic msgCount = 0; + RegBeforeDispatch([this, &msgCount](const std::string &dev, const Message *inMsg) { + if (dev != DEVICE_A || inMsg->GetMessageId() != REMOTE_EXECUTE_MESSAGE) { + return; + } + auto store1 = GetDelegate(info1_); + ASSERT_NE(store1, nullptr); + EXPECT_GT(store1->GetDeviceSyncTaskCount(), 0); + msgCount++; + }); + RemoteQuery(info1_, info2_, "SELECT * FROM DEVICE_SYNC_TABLE", OK); + RegBeforeDispatch(nullptr); + EXPECT_GT(msgCount, 0); +} + +/** + * @tc.name: VerifyInvalidGetDeviceSyncTaskCount001 + * @tc.desc: Test abnormal get device task count. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, VerifyInvalidGetDeviceSyncTaskCount001, TestSize.Level0) +{ + RelationalStoreDelegateImpl delegate; + EXPECT_EQ(delegate.GetDeviceSyncTaskCount(), 0); + SyncAbleEngine engine(nullptr); + EXPECT_EQ(engine.GetDeviceSyncTaskCount(), 0); + SQLiteRelationalStore store; + EXPECT_EQ(store.GetDeviceSyncTaskCount(), 0); + SQLiteRelationalStoreConnection connection(nullptr); + EXPECT_EQ(connection.GetDeviceSyncTaskCount(), 0); + MockSyncEngine syncEngine; + EXPECT_EQ(syncEngine.GetRemoteQueryTaskCount(), 0); + SingleVerRelationalSyncer syncer; + EXPECT_EQ(syncer.GetTaskCount(), 0); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_data_status_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_data_status_test.cpp index 920ece0aabfced347469a3dc126474e09673c242..6a1c7784bd2822dd2d232c3371beb8ea831b110c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_data_status_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_data_status_test.cpp @@ -19,14 +19,18 @@ namespace DistributedDB { using namespace testing::ext; using namespace DistributedDB; using namespace DistributedDBUnitTest; - + class DistributedDBRDBDataStatusTest : public RDBGeneralUt { public: void SetUp() override; protected: void PrepareTableBasicEnv(bool createWithTracker = false); + void PrepareBasicTableByType(TableSyncType type); + void PrepareBasicTableByType(const std::vector &tables, TableSyncType type); void DataStatusComplexTest(bool testWithTracker); static UtDateBaseSchemaInfo GetDefaultSchema(); + static UtTableSchemaInfo GetTableSchema(const std::string &table, bool noPk = false); + void InitCollaborationDelegate(); static constexpr const char *DEVICE_SYNC_TABLE = "DEVICE_SYNC_TABLE"; static constexpr const char *DEVICE_A = "DEVICE_A"; static constexpr const char *DEVICE_B = "DEVICE_B"; @@ -34,28 +38,35 @@ protected: StoreInfo info1_ = {USER_ID, APP_ID, STORE_ID_1}; StoreInfo info2_ = {USER_ID, APP_ID, STORE_ID_2}; }; - + void DistributedDBRDBDataStatusTest::SetUp() { RDBGeneralUt::SetUp(); - AddSchemaInfo(info1_, GetDefaultSchema()); - AddSchemaInfo(info2_, GetDefaultSchema()); + SetSchemaInfo(info1_, GetDefaultSchema()); + SetSchemaInfo(info2_, GetDefaultSchema()); } - + UtDateBaseSchemaInfo DistributedDBRDBDataStatusTest::GetDefaultSchema() { UtDateBaseSchemaInfo info; - UtTableSchemaInfo table; - table.name = DEVICE_SYNC_TABLE; + info.tablesInfo.push_back(GetTableSchema(DEVICE_SYNC_TABLE)); + return info; +} + +UtTableSchemaInfo DistributedDBRDBDataStatusTest::GetTableSchema(const std::string &table, bool noPk) +{ + UtTableSchemaInfo tableSchema; + tableSchema.name = table; UtFieldInfo field; field.field.colName = "id"; field.field.type = TYPE_INDEX; - field.field.primary = true; - table.fieldInfo.push_back(field); - info.tablesInfo.push_back(table); - return info; + if (!noPk) { + field.field.primary = true; + } + tableSchema.fieldInfo.push_back(field); + return tableSchema; } - + void DistributedDBRDBDataStatusTest::PrepareTableBasicEnv(bool createWithTracker) { /** @@ -92,7 +103,35 @@ void DistributedDBRDBDataStatusTest::PrepareTableBasicEnv(bool createWithTracker ASSERT_NE(store, nullptr); EXPECT_EQ(store->OperateDataStatus(static_cast(DataOperator::UPDATE_TIME)), OK); } - + +void DistributedDBRDBDataStatusTest::PrepareBasicTableByType(TableSyncType type) +{ + ASSERT_NO_FATAL_FAILURE(PrepareBasicTableByType({DEVICE_SYNC_TABLE}, type)); +} + +void DistributedDBRDBDataStatusTest::PrepareBasicTableByType(const std::vector &tables, + TableSyncType type) +{ + /** + * @tc.steps: step1. Call InitDelegate interface with default split table mode. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(BasicUnitTest::InitDelegate(info1_, DEVICE_A), E_OK); + ASSERT_EQ(BasicUnitTest::InitDelegate(info2_, DEVICE_B), E_OK); + /** + * @tc.steps: step2. Set distributed tables. + * @tc.expected: step2. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, tables, type), E_OK); + ASSERT_EQ(SetDistributedTables(info2_, tables, type), E_OK); + ASSERT_EQ(SetTrackerTables(info1_, tables), E_OK); + /** + * @tc.steps: step3. Insert local data. + * @tc.expected: step3. Ok + */ + InsertLocalDBData(0, 1, info1_); +} + void DistributedDBRDBDataStatusTest::DataStatusComplexTest(bool testWithTracker) { RelationalStoreDelegate::Option option; @@ -116,7 +155,16 @@ void DistributedDBRDBDataStatusTest::DataStatusComplexTest(bool testWithTracker) */ EXPECT_EQ(CountTableDataByDev(info2_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), DEVICE_C), 1); } - + +void DistributedDBRDBDataStatusTest::InitCollaborationDelegate() +{ + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + ASSERT_EQ(BasicUnitTest::InitDelegate(info1_, DEVICE_A), E_OK); + ASSERT_EQ(BasicUnitTest::InitDelegate(info2_, DEVICE_B), E_OK); +} + /** * @tc.name: SplitTable001 * @tc.desc: Test split table sync after update time. @@ -133,8 +181,8 @@ HWTEST_F(DistributedDBRDBDataStatusTest, SplitTable001, TestSize.Level0) */ BlockPush(info1_, info2_, DEVICE_SYNC_TABLE); } - - + + /** * @tc.name: SplitTable002 * @tc.desc: Test split table sync with diff dev after update time. @@ -206,4 +254,352 @@ HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable003, TestSize.Level0) { DataStatusComplexTest(true); } + +/** + * @tc.name: CollaborationTable004 + * @tc.desc: Test collaboration search table sync after update time. + * @tc.type: FUNC + * @tc.require: + * @tc.author: tankaisheng + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable004, TestSize.Level0) +{ + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + ASSERT_NO_FATAL_FAILURE(PrepareBasicTableByType(DEVICE_COOPERATION)); + /** + * @tc.steps: step1. DEV_A sync to DEV_B. + * @tc.expected: step1. Ok + */ + BlockPush(info1_, info2_, DEVICE_SYNC_TABLE); +} + +/** + * @tc.name: CollaborationTable005 + * @tc.desc: Test collaboration no pk table set schema twice. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable005, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create no pk table and set as distributed table. + * @tc.expected: step1. Ok + */ + UtDateBaseSchemaInfo info; + info.tablesInfo.push_back(GetTableSchema("new_table", true)); + SetSchemaInfo(info1_, info); + SetSchemaInfo(info2_, info); + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + ASSERT_NO_FATAL_FAILURE(PrepareBasicTableByType({"new_table"}, DEVICE_COOPERATION)); + /** + * @tc.steps: step2. Update distributed table by create more table. + * @tc.expected: step2. Ok + */ + info.tablesInfo.push_back(GetTableSchema(DEVICE_SYNC_TABLE)); + SetSchemaInfo(info1_, info); + SetSchemaInfo(info2_, info); + ASSERT_NO_FATAL_FAILURE(PrepareBasicTableByType({"new_table", DEVICE_SYNC_TABLE}, DEVICE_COOPERATION)); +} + +/** + * @tc.name: CollaborationTable006 + * @tc.desc: Test device collaboration and search table sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable006, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + /** + * @tc.steps: step1. Set distributed tables and Tracker tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, {DEVICE_SYNC_TABLE}, DEVICE_COOPERATION), E_OK); + ASSERT_EQ(SetTrackerTables(info2_, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert data and sync. + * @tc.expected: step2. SCHEMA_MISMATCH + */ + InsertLocalDBData(0, 1, info1_); + BlockPush(info1_, info2_, DEVICE_SYNC_TABLE, SCHEMA_MISMATCH); +} + +/** + * @tc.name: CollaborationTable007 + * @tc.desc: Test device collaboration search table and search table sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable007, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + /** + * @tc.steps: step1. Set distributed tables and Tracker tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, {DEVICE_SYNC_TABLE}, DEVICE_COOPERATION), E_OK); + ASSERT_EQ(SetTrackerTables(info1_, {DEVICE_SYNC_TABLE}), E_OK); + ASSERT_EQ(SetTrackerTables(info2_, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert data and sync. + * @tc.expected: step2. SCHEMA_MISMATCH + */ + InsertLocalDBData(0, 1, info1_); + BlockPush(info1_, info2_, DEVICE_SYNC_TABLE, SCHEMA_MISMATCH); +} + +/** + * @tc.name: CollaborationTable008 + * @tc.desc: Test device collaboration and cloud collaboration search table sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable008, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + /** + * @tc.steps: step1. Set distributed tables and Tracker tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, {DEVICE_SYNC_TABLE}, DEVICE_COOPERATION), E_OK); + ASSERT_EQ(SetDistributedTables(info2_, {DEVICE_SYNC_TABLE}, CLOUD_COOPERATION), E_OK); + ASSERT_EQ(SetTrackerTables(info2_, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert data and sync. + * @tc.expected: step2. NOT_SUPPORT + */ + InsertLocalDBData(0, 1, info1_); + BlockPush(info1_, info2_, DEVICE_SYNC_TABLE, NOT_SUPPORT); +} + +/** + * @tc.name: CollaborationTable009 + * @tc.desc: Test device collaboration search table and cloud collaboration search table sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable009, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + /** + * @tc.steps: step1. Set distributed tables and Tracker tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, {DEVICE_SYNC_TABLE}, DEVICE_COOPERATION), E_OK); + ASSERT_EQ(SetTrackerTables(info1_, {DEVICE_SYNC_TABLE}), E_OK); + ASSERT_EQ(SetDistributedTables(info2_, {DEVICE_SYNC_TABLE}, CLOUD_COOPERATION), E_OK); + ASSERT_EQ(SetTrackerTables(info2_, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert data and sync. + * @tc.expected: step2. NOT_SUPPORT + */ + InsertLocalDBData(0, 1, info1_); + BlockPush(info1_, info2_, DEVICE_SYNC_TABLE, NOT_SUPPORT); +} + +/** + * @tc.name: CollaborationTable010 + * @tc.desc: Test device collaboration and cloud collaboration able sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable010, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + /** + * @tc.steps: step1. Set distributed tables and Tracker tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, {DEVICE_SYNC_TABLE}, CLOUD_COOPERATION), E_OK); + ASSERT_EQ(SetDistributedTables(info2_, {DEVICE_SYNC_TABLE}, DEVICE_COOPERATION), E_OK); + /** + * @tc.steps: step2. Insert data and sync. + * @tc.expected: step2. NOT_SUPPORT + */ + InsertLocalDBData(0, 1, info1_); + auto store = GetDelegate(info1_); + ASSERT_NE(store, nullptr); + auto toDevice = GetDevice(info2_); + ASSERT_FALSE(toDevice.empty()); + Query query = Query::Select(DEVICE_SYNC_TABLE); + DBStatus callStatus = store->Sync({toDevice}, SYNC_MODE_PUSH_ONLY, query, nullptr, true); + EXPECT_EQ(callStatus, NOT_SUPPORT); +} + +/** + * @tc.name: CollaborationTable011 + * @tc.desc: Test cloud collaboration table and device collaboration search table sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable011, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + /** + * @tc.steps: step1. Set distributed tables and Tracker tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, {DEVICE_SYNC_TABLE}, CLOUD_COOPERATION), E_OK); + ASSERT_EQ(SetDistributedTables(info2_, {DEVICE_SYNC_TABLE}, DEVICE_COOPERATION), E_OK); + ASSERT_EQ(SetTrackerTables(info2_, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert data and sync. + * @tc.expected: step2. NOT_SUPPORT + */ + InsertLocalDBData(0, 1, info1_); + auto store = GetDelegate(info1_); + ASSERT_NE(store, nullptr); + auto toDevice = GetDevice(info2_); + ASSERT_FALSE(toDevice.empty()); + Query query = Query::Select(DEVICE_SYNC_TABLE); + DBStatus callStatus = store->Sync({toDevice}, SYNC_MODE_PUSH_ONLY, query, nullptr, true); + EXPECT_EQ(callStatus, NOT_SUPPORT); +} + +/** + * @tc.name: CollaborationTable012 + * @tc.desc: Test cloud collaboration and search table sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable012, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + /** + * @tc.steps: step1. Set distributed tables and Tracker tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, {DEVICE_SYNC_TABLE}, CLOUD_COOPERATION), E_OK); + ASSERT_EQ(SetTrackerTables(info2_, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert data and sync. + * @tc.expected: step2. NOT_SUPPORT + */ + InsertLocalDBData(0, 1, info1_); + auto store = GetDelegate(info1_); + ASSERT_NE(store, nullptr); + auto toDevice = GetDevice(info2_); + ASSERT_FALSE(toDevice.empty()); + Query query = Query::Select(DEVICE_SYNC_TABLE); + DBStatus callStatus = store->Sync({toDevice}, SYNC_MODE_PUSH_ONLY, query, nullptr, true); + EXPECT_EQ(callStatus, NOT_SUPPORT); +} + +/** + * @tc.name: CollaborationTable013 + * @tc.desc: Test cloud collaboration search table and search table sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable013, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + /** + * @tc.steps: step1. Set distributed tables and Tracker tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, {DEVICE_SYNC_TABLE}, CLOUD_COOPERATION), E_OK); + ASSERT_EQ(SetTrackerTables(info1_, {DEVICE_SYNC_TABLE}), E_OK); + ASSERT_EQ(SetTrackerTables(info2_, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert data and sync. + * @tc.expected: step2. NOT_SUPPORT + */ + InsertLocalDBData(0, 1, info1_); + auto store = GetDelegate(info1_); + ASSERT_NE(store, nullptr); + auto toDevice = GetDevice(info2_); + ASSERT_FALSE(toDevice.empty()); + Query query = Query::Select(DEVICE_SYNC_TABLE); + DBStatus callStatus = store->Sync({toDevice}, SYNC_MODE_PUSH_ONLY, query, nullptr, true); + EXPECT_EQ(callStatus, NOT_SUPPORT); +} + +/** + * @tc.name: CreateDistributedTableTest001 + * @tc.desc: Test CreateDistributedTable interface after re-create table. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CreateDistributedTableTest001, TestSize.Level0) +{ + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + ASSERT_NO_FATAL_FAILURE(PrepareTableBasicEnv()); + EXPECT_EQ(RDBGeneralUt::CreateDistributedTable(info1_, {DEVICE_SYNC_TABLE}), E_OK); + + /** + * @tc.steps: step1. Drop table, and create same table that unique field are added. + * @tc.expected: step1. Ok + */ + sqlite3 *db = GetSqliteHandle(info1_); + ASSERT_NE(db, nullptr); + std::string newSql = "DROP TABLE DEVICE_SYNC_TABLE;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, newSql), SQLITE_OK); + newSql = "CREATE TABLE IF NOT EXISTS DEVICE_SYNC_TABLE('id' INTEGER PRIMARY KEY, new_field INTEGER UNIQUE);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, newSql), SQLITE_OK); + + /** + * @tc.steps: step2. Create distributed table. + * @tc.expected: step2. OK + */ + EXPECT_EQ(RDBGeneralUt::CreateDistributedTable(info1_, {DEVICE_SYNC_TABLE}), E_OK); +} + +/** + * @tc.name: TimeCheck001 + * @tc.desc: Test operate data status after modify time. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBDataStatusTest, TimeCheck001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create distributed table and insert local data. + */ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + EXPECT_EQ(RDBGeneralUt::CreateDistributedTable(info1_, {DEVICE_SYNC_TABLE}), E_OK); + InsertLocalDBData(0, 1, info1_); + /** + * @tc.steps: step2. Get last max timestamp. + * @tc.expected: step2. Ok + */ + sqlite3 *db = GetSqliteHandle(info1_); + ASSERT_NE(db, nullptr); + auto [errCode, t1] = RelationalTestUtils::GetMaxTimestamp(db, DEVICE_SYNC_TABLE); + EXPECT_EQ(errCode, E_OK); + /** + * @tc.steps: step3. Modify time offset and operator data status. + * @tc.expected: step3. Ok + */ + std::string sql = "INSERT OR REPLACE INTO " + std::string(DBConstant::RELATIONAL_PREFIX) + + "metadata VALUES('localTimeOffset', '100000')"; + ASSERT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + auto store = GetDelegate(info1_); + ASSERT_NE(store, nullptr); + EXPECT_EQ(store->OperateDataStatus(static_cast(DataOperator::UPDATE_TIME)), OK); + /** + * @tc.steps: step4. Check timestamp should not decrease. + * @tc.expected: step4. Ok + */ + auto [ret, t2] = RelationalTestUtils::GetMaxTimestamp(db, DEVICE_SYNC_TABLE); + EXPECT_EQ(ret, E_OK); + EXPECT_GE(t2, t1); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_drop_table_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_drop_table_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..53228a3a0918241f04fa4cfa90f53f40f568b968 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_drop_table_test.cpp @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2025 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 "rdb_general_ut.h" +#include "sqlite_relational_utils.h" +#include "virtual_sqlite_relational_store.h" +namespace DistributedDB { +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +class DistributedDBRDBDropTableTest : public RDBGeneralUt { +public: + void SetUp() override; +protected: + void PrepareEnv(const StoreInfo &info, bool createTracker = false, bool createDistributedTable = false); + static UtDateBaseSchemaInfo GetDefaultSchema(); + static UtDateBaseSchemaInfo GetUniqueSchema(); + static UtTableSchemaInfo GetTableSchema(const std::string &table, bool isPkUuid); + static constexpr const char *DEVICE_SYNC_TABLE = "DEVICE_SYNC_TABLE"; + static constexpr const char *DEVICE_A = "DEVICE_A"; + static constexpr const char *DEVICE_B = "DEVICE_B"; + StoreInfo info1_ = {USER_ID, APP_ID, STORE_ID_1}; + StoreInfo info2_ = {USER_ID, APP_ID, STORE_ID_2}; +}; + +void DistributedDBRDBDropTableTest::SetUp() +{ + RDBGeneralUt::SetUp(); + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); +} + +void DistributedDBRDBDropTableTest::PrepareEnv(const StoreInfo &info, bool createTracker, bool createDistributedTable) +{ + ASSERT_EQ(ExecuteSQL("CREATE TABLE IF NOT EXISTS" + " DEVICE_SYNC_TABLE(id INTEGER PRIMARY KEY AUTOINCREMENT, uuid INTEGER UNIQUE)", info), E_OK); + if (createTracker) { + ASSERT_EQ(SetTrackerTables(info, {DEVICE_SYNC_TABLE}), E_OK); + } + if (createDistributedTable) { + ASSERT_EQ(SetDistributedTables(info, {DEVICE_SYNC_TABLE}), E_OK); + } +} + +UtDateBaseSchemaInfo DistributedDBRDBDropTableTest::GetDefaultSchema() +{ + UtDateBaseSchemaInfo info; + info.tablesInfo.push_back(GetTableSchema(DEVICE_SYNC_TABLE, false)); + return info; +} + +UtDateBaseSchemaInfo DistributedDBRDBDropTableTest::GetUniqueSchema() +{ + UtDateBaseSchemaInfo info; + info.tablesInfo.push_back(GetTableSchema(DEVICE_SYNC_TABLE, true)); + return info; +} + +UtTableSchemaInfo DistributedDBRDBDropTableTest::GetTableSchema(const std::string &table, bool isPkUuid) +{ + UtTableSchemaInfo tableSchema; + tableSchema.name = table; + UtFieldInfo field; + field.field.type = TYPE_INDEX; + field.field.primary = isPkUuid; + field.field.colName = "uuid"; + tableSchema.fieldInfo.push_back(field); + return tableSchema; +} + +/** + * @tc.name: SyncAfterDrop001 + * @tc.desc: Test sync success after drop table. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBDropTableTest, SyncAfterDrop001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create table and set distributed tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(BasicUnitTest::InitDelegate(info1_, DEVICE_A), E_OK); + SetSchemaInfo(info1_, GetDefaultSchema()); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_, true)); + EXPECT_EQ(ExecuteSQL("INSERT OR REPLACE INTO DEVICE_SYNC_TABLE VALUES(1, 100)", info1_), E_OK); + EXPECT_EQ(CountTableData(info1_, DEVICE_SYNC_TABLE, "id=1"), 1); + ASSERT_EQ(BasicUnitTest::InitDelegate(info2_, DEVICE_B), E_OK); + SetSchemaInfo(info2_, GetUniqueSchema()); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info2_, true, true)); + /** + * @tc.steps: step2. Recreate table and set distributed tables. + * @tc.expected: step2. Ok + */ + EXPECT_EQ(ExecuteSQL("DROP TABLE DEVICE_SYNC_TABLE", info1_), E_OK); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_)); + EXPECT_EQ(ExecuteSQL("INSERT OR REPLACE INTO DEVICE_SYNC_TABLE VALUES(1, 100)", info1_), E_OK); + SetSchemaInfo(info1_, GetUniqueSchema()); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_, true, true)); + /** + * @tc.steps: step3. Sync. + * @tc.expected: step3. Ok + */ + BlockSync(info1_, info2_, DEVICE_SYNC_TABLE, SyncMode::SYNC_MODE_PUSH_ONLY, OK); +} + +/** + * @tc.name: SyncAfterDrop002 + * @tc.desc: Test sync success after drop table. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBDropTableTest, SyncAfterDrop002, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create table and set distributed tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(BasicUnitTest::InitDelegate(info1_, DEVICE_A), E_OK); + SetSchemaInfo(info1_, GetDefaultSchema()); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_, true)); + EXPECT_EQ(ExecuteSQL("INSERT OR REPLACE INTO DEVICE_SYNC_TABLE VALUES(1, 100)", info1_), E_OK); + ASSERT_EQ(BasicUnitTest::InitDelegate(info2_, DEVICE_B), E_OK); + SetSchemaInfo(info2_, GetUniqueSchema()); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info2_, true, true)); + /** + * @tc.steps: step2. Recreate table and set distributed tables and insert dirty data. + * @tc.expected: step2. Ok + */ + EXPECT_EQ(ExecuteSQL("DROP TABLE DEVICE_SYNC_TABLE", info1_), E_OK); + std::string sql = "INSERT OR REPLACE INTO " + DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) + + "(data_key, timestamp, wtimestamp, flag, hash_key, extend_field) " + "VALUES(1, 1, 1, 0x02, 'error_hash1', '100')"; + EXPECT_EQ(ExecuteSQL(sql, info1_), E_OK); + sql = "INSERT OR REPLACE INTO " + DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) + + "(data_key, timestamp, wtimestamp, flag, hash_key, extend_field) " + "VALUES(1, 2, 2, 0x02, 'error_hash2', 200)"; + EXPECT_EQ(ExecuteSQL(sql, info1_), E_OK); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_)); + EXPECT_EQ(ExecuteSQL("INSERT OR REPLACE INTO DEVICE_SYNC_TABLE VALUES(1, 100)", info1_), E_OK); + SetSchemaInfo(info1_, GetUniqueSchema()); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_, false, true)); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_, true, false)); + /** + * @tc.steps: step3. Sync. + * @tc.expected: step3. Ok + */ + BlockSync(info1_, info2_, DEVICE_SYNC_TABLE, SyncMode::SYNC_MODE_PUSH_ONLY, OK); + EXPECT_EQ(CountTableData(info1_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), "hash_key='error_hash1'"), 0); + EXPECT_EQ(CountTableData(info1_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), "hash_key='error_hash2'"), 0); +} + +/** + * @tc.name: SetTrackerAfterDrop001 + * @tc.desc: Test set tracker success after drop table. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBDropTableTest, SetTrackerAfterDrop001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create table and set tracker table. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(BasicUnitTest::InitDelegate(info1_, DEVICE_A), E_OK); + SetSchemaInfo(info1_, GetDefaultSchema()); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_, true)); + /** + * @tc.steps: step2. Recreate table and set tracker table with force. + * @tc.expected: step2. Ok + */ + EXPECT_EQ(ExecuteSQL("DROP TABLE DEVICE_SYNC_TABLE", info1_), E_OK); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_)); + ASSERT_EQ(SetTrackerTables(info1_, {DEVICE_SYNC_TABLE}, true), E_OK); +} + +/** + * @tc.name: InvalidCleanTracker001 + * @tc.desc: Test clean tracker with invalid obj. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBDropTableTest, InvalidCleanTracker001, TestSize.Level0) +{ + VirtualSqliteRelationalStore store; + auto schemaObj = store.CallGetSchemaObj(); + EXPECT_FALSE(schemaObj.IsSchemaValid()); + TrackerSchema schema; + TableInfo info; + bool isNoTableInSchema = false; + bool isFirstCreate = false; + RelationalDBProperties properties; + auto engine = std::make_shared(properties); + store.SetStorageEngine(engine); + engine->SetEngineState(EngineState::ENGINE_BUSY); + EXPECT_EQ(store.CallCheckTrackerTable(schema, info, isNoTableInSchema, isFirstCreate), -E_BUSY); + EXPECT_FALSE(isNoTableInSchema); + EXPECT_TRUE(isFirstCreate); + store.CallCleanDirtyLogIfNeed(DEVICE_SYNC_TABLE); +} + +/** + * @tc.name: CleanDirtyLog001 + * @tc.desc: Test clean dirty log by utils. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBDropTableTest, CleanDirtyLog001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create table and set distributed tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(BasicUnitTest::InitDelegate(info1_, DEVICE_A), E_OK); + SetSchemaInfo(info1_, GetUniqueSchema()); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_, true, true)); + /** + * @tc.steps: step2. Execute sql with invalid db. + * @tc.expected: step2. Fail + */ + auto res = SQLiteRelationalUtils::CheckExistDirtyLog(nullptr, DEVICE_SYNC_TABLE); + EXPECT_EQ(res.first, -E_INVALID_DB); + EXPECT_FALSE(res.second); + EXPECT_EQ(SQLiteRelationalUtils::ExecuteSql(nullptr, "", nullptr), -E_INVALID_DB); + /** + * @tc.steps: step3. Check dirty log with no exist table. + * @tc.expected: step3. No exist dirty log + */ + auto handle = GetSqliteHandle(info1_); + ASSERT_NE(handle, nullptr); + res = SQLiteRelationalUtils::CheckExistDirtyLog(handle, "NO_EXISTS_TABLE"); + EXPECT_EQ(res.first, E_OK); + EXPECT_FALSE(res.second); + /** + * @tc.steps: step4. Insert data and dirty log. + * @tc.expected: step4. Ok + */ + EXPECT_EQ(ExecuteSQL("INSERT OR REPLACE INTO DEVICE_SYNC_TABLE VALUES(1, 100)", info1_), E_OK); + std::string sql = "INSERT OR REPLACE INTO " + DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) + + "(data_key, timestamp, wtimestamp, flag, hash_key, extend_field) " + "VALUES(1, 1, 1, 0x02, 'error_hash1', '100')"; + EXPECT_EQ(ExecuteSQL(sql, info1_), E_OK); + EXPECT_EQ(CountTableData(info1_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), "hash_key='error_hash1'"), 1); + EXPECT_EQ(CountTableData(info1_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), "data_key='1'"), 2); // 2 log + /** + * @tc.steps: step5. Clean dirty log. + * @tc.expected: step5. Ok and no exist dirty log + */ + RelationalSchemaObject obj; + EXPECT_EQ(SQLiteRelationalUtils::CleanDirtyLog(handle, DEVICE_SYNC_TABLE, obj), E_OK); + EXPECT_EQ(CountTableData(info1_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), "hash_key='error_hash1'"), 1); + EXPECT_EQ(CountTableData(info1_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), "data_key='1'"), 2); // 2 log + obj.SetDistributedSchema(RDBDataGenerator::ParseSchema(GetSchema(info1_))); + EXPECT_EQ(SQLiteRelationalUtils::CleanDirtyLog(handle, DEVICE_SYNC_TABLE, obj), E_OK); + EXPECT_EQ(CountTableData(info1_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), "hash_key='error_hash1'"), 0); + EXPECT_EQ(CountTableData(info1_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), "data_key='1'"), 1); + /** + * @tc.steps: step6. Clean no exist table dirty log. + * @tc.expected: step6. Fail + */ + EXPECT_EQ(ExecuteSQL("DROP TABLE DEVICE_SYNC_TABLE", info1_), E_OK); + EXPECT_EQ(SQLiteRelationalUtils::CleanDirtyLog(handle, DEVICE_SYNC_TABLE, obj), -1); // -1 is default error +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_knowledge_client_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_knowledge_client_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..68c74e3b7f1071a090dc71ea6f46809f14742732 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_knowledge_client_test.cpp @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2025 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 "cloud_sync_log_table_manager.h" +#include "distributeddb_tools_unit_test.h" +#include "rdb_data_generator.h" +#include "relational_store_client.h" +#include "sqlite_relational_utils.h" +#include "table_info.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +namespace { + constexpr const char *DB_SUFFIX = ".db"; + constexpr const char *STORE_ID = "Relational_Store_ID"; + std::string g_dbDir; + std::string g_testDir; +} + +namespace { +class DistributedDBRDBKnowledgeClientTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp() override; + void TearDown() override; +protected: + static UtTableSchemaInfo GetTableSchema(const std::string &table); + static void SaveSchemaToMetaTable(sqlite3 *db, const std::string tableName, const TableInfo &tableInfo); + static void CreateDistributedTable(const std::vector &tableNames, + DistributedDB::TableSyncType tableSyncType); + static constexpr const char *KNOWLEDGE_TABLE = "KNOWLEDGE_TABLE"; + static constexpr const char *SYNC_TABLE = "SYNC_TABLE"; +}; + + +void DistributedDBRDBKnowledgeClientTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + LOGD("Test dir is %s", g_testDir.c_str()); + g_dbDir = g_testDir + "/"; + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); +} + +void DistributedDBRDBKnowledgeClientTest::TearDownTestCase(void) +{ +} + +void DistributedDBRDBKnowledgeClientTest::SetUp() +{ +} + +void DistributedDBRDBKnowledgeClientTest::TearDown() +{ + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); +} + +UtTableSchemaInfo DistributedDBRDBKnowledgeClientTest::GetTableSchema(const std::string &table) +{ + UtTableSchemaInfo tableSchema; + tableSchema.name = table; + UtFieldInfo field; + field.field.colName = "id"; + field.field.type = TYPE_INDEX; + field.field.primary = true; + tableSchema.fieldInfo.push_back(field); + field.field.primary = false; + field.field.colName = "int_field1"; + tableSchema.fieldInfo.push_back(field); + field.field.colName = "int_field2"; + tableSchema.fieldInfo.push_back(field); + field.field.colName = "int_field3"; + tableSchema.fieldInfo.push_back(field); + return tableSchema; +} + +void DistributedDBRDBKnowledgeClientTest::SaveSchemaToMetaTable(sqlite3 *db, const std::string tableName, + const TableInfo &tableInfo) +{ + RelationalSchemaObject schema; + schema.SetTableMode(DistributedDB::DistributedTableMode::SPLIT_BY_DEVICE); + schema.RemoveRelationalTable(tableName); + schema.AddRelationalTable(tableInfo); + + const Key schemaKey(DBConstant::RELATIONAL_SCHEMA_KEY, + DBConstant::RELATIONAL_SCHEMA_KEY + strlen(DBConstant::RELATIONAL_SCHEMA_KEY)); + Value schemaVal; + auto schemaStr = schema.ToSchemaString(); + EXPECT_FALSE(schemaStr.size() > SchemaConstant::SCHEMA_STRING_SIZE_LIMIT); + DBCommon::StringToVector(schemaStr, schemaVal); + EXPECT_EQ(SQLiteRelationalUtils::PutKvData(db, false, schemaKey, schemaVal), E_OK); +} + +void DistributedDBRDBKnowledgeClientTest::CreateDistributedTable(const std::vector &tableNames, + DistributedDB::TableSyncType tableSyncType) +{ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + for (const auto &tableName : tableNames) { + TableInfo tableInfo; + tableInfo.SetTableName(tableName); + tableInfo.SetTableSyncType(tableSyncType); + TrackerTable table111; + tableInfo.SetTrackerTable(table111); + DistributedTable distributedTable; + distributedTable.tableName = tableName; + tableInfo.SetDistributedTable(distributedTable); + std::unique_ptr tableManager = std::make_unique(); + EXPECT_NE(tableManager, nullptr); + EXPECT_EQ(SQLiteUtils::AnalysisSchema(db, tableName, tableInfo), E_OK); + std::vector fieldInfos = tableInfo.GetFieldInfos(); + EXPECT_EQ(SQLiteRelationalUtils::CreateRelationalMetaTable(db), E_OK); + EXPECT_EQ(SQLiteRelationalUtils::InitCursorToMeta(db, false, tableName), E_OK); + EXPECT_EQ(tableManager->CreateRelationalLogTable(db, tableInfo), E_OK); + EXPECT_EQ(tableManager->AddRelationalLogTableTrigger(db, tableInfo, ""), E_OK); + SQLiteRelationalUtils::SetLogTriggerStatus(db, true); + SaveSchemaToMetaTable(db, tableName, tableInfo); + } + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +void InsertDBData(const std::string &tableName, int count, sqlite3 *db) +{ + for (int i = 1; i <= count; i++) { + std::string sql = "INSERT INTO " + tableName + " VALUES(" + std::to_string(i) + ',' + std::to_string(i) + ',' + + std::to_string(i) + ',' + std::to_string(i) + ");"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } +} + +/** + * @tc.name: SetKnowledge001 + * @tc.desc: Test set knowledge schema. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBKnowledgeClientTest, SetKnowledge001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set knowledge source schema and clean deleted data. + * @tc.expected: step1. Ok + */ + UtTableSchemaInfo tableInfo = GetTableSchema(KNOWLEDGE_TABLE); + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + RDBDataGenerator::InitTableWithSchemaInfo(tableInfo, *db); + KnowledgeSourceSchema schema; + schema.tableName = KNOWLEDGE_TABLE; + schema.extendColNames.insert("id"); + schema.knowledgeColNames.insert("int_field1"); + schema.knowledgeColNames.insert("int_field2"); + EXPECT_EQ(SetKnowledgeSourceSchema(db, schema), OK); + EXPECT_EQ(CleanDeletedData(db, schema.tableName, 0u), OK); + /** + * @tc.steps: step2. Clean deleted data after insert one data. + * @tc.expected: step2. Ok + */ + InsertDBData(schema.tableName, 1, db); + EXPECT_EQ(CleanDeletedData(db, schema.tableName, 0u), OK); + /** + * @tc.steps: step3. Clean deleted data after delete one data. + * @tc.expected: step3. Ok + */ + std::string sql = std::string("DELETE FROM ").append(KNOWLEDGE_TABLE).append(" WHERE 1=1"); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + EXPECT_EQ(CleanDeletedData(db, schema.tableName, 10u), OK); // delete which cursor less than 10 + + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} + +/** + * @tc.name: SetKnowledge002 + * @tc.desc: Test set knowledge schema with invalid args. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBKnowledgeClientTest, SetKnowledge002, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set knowledge source schema and clean deleted data with null db. + * @tc.expected: step1. INVALID_ARGS + */ + KnowledgeSourceSchema schema; + schema.tableName = KNOWLEDGE_TABLE; + schema.extendColNames.insert("id"); + schema.knowledgeColNames.insert("int_field1"); + schema.knowledgeColNames.insert("int_field2"); + EXPECT_EQ(SetKnowledgeSourceSchema(nullptr, schema), INVALID_ARGS); + EXPECT_EQ(CleanDeletedData(nullptr, schema.tableName, 0u), INVALID_ARGS); + /** + * @tc.steps: step2. Set knowledge source schema and clean deleted data with null db. + * @tc.expected: step2. INVALID_ARGS + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + ASSERT_NE(db, nullptr); + schema.tableName = "UNKNOWN_TABLE"; + EXPECT_EQ(SetKnowledgeSourceSchema(db, schema), INVALID_ARGS); + EXPECT_EQ(CleanDeletedData(db, schema.tableName, 0u), OK); + + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} + +/** + * @tc.name: SetKnowledge003 + * @tc.desc: Test set knowledge schema after create distributed table. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBKnowledgeClientTest, SetKnowledge003, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create distributed table. + * @tc.expected: step1. Ok + */ + UtTableSchemaInfo tableInfo1 = GetTableSchema(KNOWLEDGE_TABLE); + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + RDBDataGenerator::InitTableWithSchemaInfo(tableInfo1, *db); + UtTableSchemaInfo tableInfo2 = GetTableSchema(SYNC_TABLE); + RDBDataGenerator::InitTableWithSchemaInfo(tableInfo2, *db); + CreateDistributedTable({SYNC_TABLE}, DistributedDB::CLOUD_COOPERATION); + + /** + * @tc.steps: step2. Set knowledge source schema. + * @tc.expected: step2. INVALID_ARGS + */ + KnowledgeSourceSchema schema; + schema.tableName = KNOWLEDGE_TABLE; + schema.extendColNames.insert("id"); + schema.knowledgeColNames.insert("int_field1"); + schema.knowledgeColNames.insert("int_field2"); + schema.tableName = SYNC_TABLE; + EXPECT_EQ(SetKnowledgeSourceSchema(db, schema), INVALID_ARGS); + + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_knowledge_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_knowledge_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ebb6f5c5ccd80ca9a513f07f0a90d36c81e88858 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_knowledge_test.cpp @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2025 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 "rdb_general_ut.h" +#include "relational_store_client.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +namespace { +class DistributedDBRDBKnowledgeTest : public RDBGeneralUt { +public: + void SetUp() override; +protected: + static UtDateBaseSchemaInfo GetDefaultSchema(); + static UtTableSchemaInfo GetTableSchema(const std::string &table); + static KnowledgeSourceSchema GetKnowledgeSchema(); + static constexpr const char *KNOWLEDGE_TABLE = "KNOWLEDGE_TABLE"; + static constexpr const char *SYNC_TABLE = "SYNC_TABLE"; + StoreInfo info1_ = {USER_ID, APP_ID, STORE_ID_1}; +}; + +void DistributedDBRDBKnowledgeTest::SetUp() +{ + RDBGeneralUt::SetUp(); + SetSchemaInfo(info1_, GetDefaultSchema()); + InitDatabase(info1_); +} + +UtDateBaseSchemaInfo DistributedDBRDBKnowledgeTest::GetDefaultSchema() +{ + UtDateBaseSchemaInfo info; + info.tablesInfo.push_back(GetTableSchema(KNOWLEDGE_TABLE)); + return info; +} + +UtTableSchemaInfo DistributedDBRDBKnowledgeTest::GetTableSchema(const std::string &table) +{ + UtTableSchemaInfo tableSchema; + tableSchema.name = table; + UtFieldInfo field; + field.field.colName = "id"; + field.field.type = TYPE_INDEX; + field.field.primary = true; + tableSchema.fieldInfo.push_back(field); + field.field.primary = false; + field.field.colName = "int_field1"; + tableSchema.fieldInfo.push_back(field); + field.field.colName = "int_field2"; + tableSchema.fieldInfo.push_back(field); + field.field.colName = "int_field3"; + tableSchema.fieldInfo.push_back(field); + return tableSchema; +} + +KnowledgeSourceSchema DistributedDBRDBKnowledgeTest::GetKnowledgeSchema() +{ + KnowledgeSourceSchema schema; + schema.extendColNames.insert("id"); + schema.knowledgeColNames.insert("int_field1"); + schema.knowledgeColNames.insert("int_field2"); + schema.tableName = SYNC_TABLE; + return schema; +} + +/** + * @tc.name: SetKnowledge001 + * @tc.desc: Test set knowledge schema. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBKnowledgeTest, SetKnowledge001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set knowledge source schema and clean deleted data. + * @tc.expected: step1. Ok + */ + auto db = GetSqliteHandle(info1_); + ASSERT_NE(db, nullptr); + KnowledgeSourceSchema schema; + schema.tableName = KNOWLEDGE_TABLE; + schema.extendColNames.insert("id"); + schema.knowledgeColNames.insert("int_field1"); + schema.knowledgeColNames.insert("int_field2"); + EXPECT_EQ(SetKnowledgeSourceSchema(db, schema), OK); + EXPECT_EQ(CleanDeletedData(db, schema.tableName, 0u), OK); + /** + * @tc.steps: step2. Clean deleted data after insert one data. + * @tc.expected: step2. Ok + */ + EXPECT_EQ(InsertLocalDBData(0, 1, info1_), E_OK); + EXPECT_EQ(CleanDeletedData(db, schema.tableName, 0u), OK); + /** + * @tc.steps: step3. Clean deleted data after delete one data. + * @tc.expected: step3. Ok + */ + std::string sql = std::string("DELETE FROM ").append(KNOWLEDGE_TABLE).append(" WHERE 1=1"); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + EXPECT_EQ(CleanDeletedData(db, schema.tableName, 10u), OK); // delete which cursor less than 10 +} + +/** + * @tc.name: SetKnowledge002 + * @tc.desc: Test set knowledge schema with invalid args. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBKnowledgeTest, SetKnowledge002, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set knowledge source schema and clean deleted data with null db. + * @tc.expected: step1. INVALID_ARGS + */ + KnowledgeSourceSchema schema; + schema.tableName = KNOWLEDGE_TABLE; + schema.extendColNames.insert("id"); + schema.knowledgeColNames.insert("int_field1"); + schema.knowledgeColNames.insert("int_field2"); + EXPECT_EQ(SetKnowledgeSourceSchema(nullptr, schema), INVALID_ARGS); + EXPECT_EQ(CleanDeletedData(nullptr, schema.tableName, 0u), INVALID_ARGS); + /** + * @tc.steps: step2. Set knowledge source schema and clean deleted data with null db. + * @tc.expected: step2. INVALID_ARGS + */ + auto db = GetSqliteHandle(info1_); + ASSERT_NE(db, nullptr); + schema.tableName = "UNKNOWN_TABLE"; + EXPECT_EQ(SetKnowledgeSourceSchema(db, schema), INVALID_ARGS); + EXPECT_EQ(CleanDeletedData(db, schema.tableName, 0u), OK); +} + +/** + * @tc.name: SetKnowledge003 + * @tc.desc: Test set knowledge schema after create distributed table. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBKnowledgeTest, SetKnowledge003, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create distributed table. + * @tc.expected: step1. Ok + */ + UtDateBaseSchemaInfo info; + info.tablesInfo.push_back(GetTableSchema(KNOWLEDGE_TABLE)); + info.tablesInfo.push_back(GetTableSchema(SYNC_TABLE)); + SetSchemaInfo(info1_, info); + ASSERT_EQ(DistributedDB::RDBGeneralUt::InitDelegate(info1_), E_OK); + ASSERT_EQ(CreateDistributedTable(info1_, SYNC_TABLE), E_OK); + /** + * @tc.steps: step2. Set knowledge source schema. + * @tc.expected: step2. INVALID_ARGS + */ + auto db = GetSqliteHandle(info1_); + ASSERT_NE(db, nullptr); + EXPECT_EQ(SetKnowledgeSourceSchema(db, GetKnowledgeSchema()), INVALID_ARGS); +} + +/** + * @tc.name: SetKnowledge004 + * @tc.desc: Test set knowledge schema after create tracker table. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBKnowledgeTest, SetKnowledge004, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create tracker table. + * @tc.expected: step1. Ok + */ + UtDateBaseSchemaInfo info; + info.tablesInfo.push_back(GetTableSchema(SYNC_TABLE)); + info.tablesInfo.push_back(GetTableSchema(KNOWLEDGE_TABLE)); + SetSchemaInfo(info1_, info); + ASSERT_EQ(DistributedDB::RDBGeneralUt::InitDelegate(info1_), E_OK); + ASSERT_EQ(DistributedDB::RDBGeneralUt::SetTrackerTables(info1_, {SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Set knowledge source schema. + * @tc.expected: step2. INVALID_ARGS + */ + auto db = GetSqliteHandle(info1_); + ASSERT_NE(db, nullptr); + EXPECT_EQ(SetKnowledgeSourceSchema(db, GetKnowledgeSchema()), INVALID_ARGS); +} + +/** + * @tc.name: SetKnowledge005 + * @tc.desc: Test set knowledge schema and then drop table. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyuchen + */ +HWTEST_F(DistributedDBRDBKnowledgeTest, SetKnowledge005, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set knowledge source schema and clean deleted data. + * @tc.expected: step1. Ok + */ + auto db = GetSqliteHandle(info1_); + ASSERT_NE(db, nullptr); + KnowledgeSourceSchema schema; + schema.tableName = KNOWLEDGE_TABLE; + schema.extendColNames.insert("id"); + schema.knowledgeColNames.insert("int_field1"); + schema.knowledgeColNames.insert("int_field2"); + EXPECT_EQ(SetKnowledgeSourceSchema(db, schema), OK); + + /** + * @tc.steps: step2. Create inverted table. + * @tc.expected: step2. ok + */ + std::string inverted = std::string(KNOWLEDGE_TABLE) + "_inverted"; + std::string sql = "CREATE VIRTUAL TABLE IF NOT EXISTS " + inverted + " USING fts3(col1, col2);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + + sql = "SELECT count(*) FROM " + inverted + ";"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + + /** + * @tc.steps: step3. Drop knowledge table. + * @tc.expected: step3. ok + */ + sql = "DROP TABLE IF EXISTS " + std::string(KNOWLEDGE_TABLE) + ";"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + + /** + * @tc.steps: step4. Inverted table not exist. + * @tc.expected: step4. ok + */ + sql = "SELECT count(*) FROM " + inverted + ";"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_ERROR); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f3c51b4034b7cb213c9b1818a7448ce0db18993c --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2025 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 "rdb_general_ut.h" +#include "sqlite_relational_utils.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +namespace { +class DistributedDBRDBUpgradeTest : public RDBGeneralUt { +public: + void SetUp() override; + void TearDown() override; +protected: + void InitUpgradeDelegate(); + void InitNoJsonTrackerSchema(); + static constexpr const char *DEVICE_SYNC_TABLE = "DEVICE_SYNC_TABLE"; +}; + +void DistributedDBRDBUpgradeTest::SetUp() +{ + RDBGeneralUt::SetUp(); +} + +void DistributedDBRDBUpgradeTest::TearDown() +{ + RDBGeneralUt::TearDown(); +} + +void DistributedDBRDBUpgradeTest::InitUpgradeDelegate() +{ + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + auto info1 = GetStoreInfo1(); + const std::vector filedInfo = { + {{"id", TYPE_INDEX, true, false}, true}, {{"name1", TYPE_INDEX, false, true}, false}, + {{"name2", TYPE_INDEX, false, true}, false} + }; + UtDateBaseSchemaInfo schemaInfo = { + .tablesInfo = {{.name = DEVICE_SYNC_TABLE, .fieldInfo = filedInfo}} + }; + RDBGeneralUt::SetSchemaInfo(info1, schemaInfo); + ASSERT_EQ(BasicUnitTest::InitDelegate(info1, "dev1"), E_OK); +} + +void DistributedDBRDBUpgradeTest::InitNoJsonTrackerSchema() +{ + std::string keyStr = "relational_tracker_schema"; + Key key(keyStr.begin(), keyStr.end()); + std::string schemaStr = R"({"SCHEMA_TYPE":"TRACKER","TABLES":[ + {"NAME": "DEVICE_SYNC_TABLE", "EXTEND_NAME": "id", + "TRACKER_NAMES": ["id", "name1", "name2"], "TRACKER_ACTION": false}]})"; + Value value(schemaStr.begin(), schemaStr.end()); + ASSERT_EQ(PutMetaData(GetStoreInfo1(), key, value), E_OK); +} + +/** + * @tc.name: UpgradeTracker001 + * @tc.desc: Test rdb upgrade extend field from no json to json. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBUpgradeTest, UpgradeTracker001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Init delegate and set tracker schema. + * @tc.expected: step1. Ok + */ + ASSERT_NO_FATAL_FAILURE(InitUpgradeDelegate()); + auto info1 = GetStoreInfo1(); + EXPECT_EQ(SetTrackerTables(info1, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert local data and log, low version schema. + * @tc.expected: step2. Ok + */ + InsertLocalDBData(0, 1, info1); + std::string sql = "UPDATE " + DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) + " SET extend_field=1"; + EXPECT_EQ(ExecuteSQL(sql, info1), E_OK); + ASSERT_NO_FATAL_FAILURE(InitNoJsonTrackerSchema()); + EXPECT_EQ(CloseDelegate(info1), E_OK); + ASSERT_NO_FATAL_FAILURE(InitUpgradeDelegate()); + /** + * @tc.steps: step3. Set tracker table and create distributed table. + * @tc.expected: step3. Ok + */ + auto store = GetDelegate(info1); + ASSERT_NE(store, nullptr); + EXPECT_EQ(CreateDistributedTable(info1, DEVICE_SYNC_TABLE), E_OK); + EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), + " json_valid(extend_field) = 0"), 0); + EXPECT_EQ(SetTrackerTables(info1, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step4. Check log extend field. + * @tc.expected: step4. Ok + */ + EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), + " json_type(extend_field) = 'object'"), 1); + EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), + " json_valid(extend_field) = 0"), 0); +} + +/** + * @tc.name: UpgradeTracker002 + * @tc.desc: Test rdb upgrade extend field is no json format. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBUpgradeTest, UpgradeTracker002, TestSize.Level0) +{ + /** + * @tc.steps: step1. Init delegate and set tracker schema. + * @tc.expected: step1. Ok + */ + ASSERT_NO_FATAL_FAILURE(InitUpgradeDelegate()); + auto info1 = GetStoreInfo1(); + EXPECT_EQ(SetTrackerTables(info1, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert local data and log update extend_field to empty str. + * @tc.expected: step2. Ok + */ + InsertLocalDBData(0, 1, info1); + std::string sql = "UPDATE " + DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) + " SET extend_field=''"; + EXPECT_EQ(ExecuteSQL(sql, info1), E_OK); + EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), + " json_valid(extend_field) = 0"), 1); + /** + * @tc.steps: step3. Set tracker again and check log. + * @tc.expected: step3. Ok + */ + EXPECT_EQ(SetTrackerTables(info1, {DEVICE_SYNC_TABLE}), E_OK); + EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), + " json_valid(extend_field) = 0"), 0); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_client_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_client_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2dc60fb54fb62426ab7690bfd5e4b0cfdee43c19 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_client_test.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 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_db_sync_utils_test.h" + +namespace DistributedDB { + void CloudDBSyncUtilsTest::GetHashKey(const std::string &tableName, const std::string &condition, sqlite3 *db, + std::vector> &hashKey) + { + sqlite3_stmt *stmt = nullptr; + std::string sql = "select hash_key from " + DBCommon::GetLogTableName(tableName) + " where " + condition; + EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + std::vector blob; + EXPECT_EQ(SQLiteUtils::GetColumnBlobValue(stmt, 0, blob), E_OK); + hashKey.push_back(blob); + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + } +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_test.cpp index 479520ad67d5ecd2f3b2a272ffaea5625e1c642b..b4c904c6eeb55f4baefd56c7e148039a59c1099c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_test.cpp @@ -328,19 +328,4 @@ namespace DistributedDB { EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback, reinterpret_cast(count), nullptr), SQLITE_OK); } - - void CloudDBSyncUtilsTest::GetHashKey(const std::string &tableName, const std::string &condition, sqlite3 *db, - std::vector> &hashKey) - { - sqlite3_stmt *stmt = nullptr; - std::string sql = "select hash_key from " + DBCommon::GetLogTableName(tableName) + " where " + condition; - EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); - while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - std::vector blob; - EXPECT_EQ(SQLiteUtils::GetColumnBlobValue(stmt, 0, blob), E_OK); - hashKey.push_back(blob); - } - int errCode; - SQLiteUtils::ResetStatement(stmt, true, errCode); - } } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_async_download_assets_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_async_download_assets_test.cpp index e5a6d4c49b43c442cb5c1218bd4fcfe1ee755e43..76ca2402f827350dd32e7d62e26e839a94003fe0 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_async_download_assets_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_async_download_assets_test.cpp @@ -16,8 +16,10 @@ #include "cloud/assets_download_manager.h" #include "cloud/cloud_storage_utils.h" +#include "cloud/mock_icloud_sync_storage_interface.h" #include "cloud/virtual_asset_loader.h" #include "cloud/virtual_cloud_data_translate.h" +#include "cloud/virtual_cloud_syncer.h" #include "cloud_db_sync_utils_test.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" @@ -63,6 +65,8 @@ protected: void CloseDb(); void DoSkipAssetDownload(SkipAssetTestParamT param); void UpdateLocalData(sqlite3 *&db, const std::string &tableName, int32_t begin, int32_t end); + void DeleteLocalData(sqlite3 *&db, const std::string &tableName); + void CheckLogTable(sqlite3 *&db, const std::string &tableName, int count); void UpdateLocalAndCheckUploadCount(const bool &isAsync, const int &dataCount, const int &expectCount); std::string storePath_; sqlite3 *db_ = nullptr; @@ -273,7 +277,7 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncDownloadAssetConfig001, * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncDownloadAssetConfig002, TestSize.Level0) +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncDownloadAssetConfig002, TestSize.Level1) { /** * @tc.steps: step1. Set valid param twice @@ -338,7 +342,7 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncDownloadAssetConfig002, * @tc.require: * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncDownloadAssetConfig003, TestSize.Level0) +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncDownloadAssetConfig003, TestSize.Level1) { /** * @tc.steps: step1. Insert cloud data @@ -401,7 +405,7 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, FinishListener001, TestSize. * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncComplexDownload001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncComplexDownload001, TestSize.Level1) { /** * @tc.steps: step1. Set max download task 1 @@ -439,7 +443,7 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncComplexDownload001, Tes * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncComplexDownload002, TestSize.Level0) +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncComplexDownload002, TestSize.Level1) { /** * @tc.steps: step1. Set max download task 1 @@ -545,7 +549,7 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload001, Te * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload002, TestSize.Level0) +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload002, TestSize.Level1) { /** * @tc.steps: step1. Insert cloud data @@ -633,7 +637,7 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload003, Te * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload004, TestSize.Level0) +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload004, TestSize.Level1) { /** * @tc.steps: step1. Set async config @@ -736,7 +740,7 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload005, Te * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncNormalDownload001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncNormalDownload001, TestSize.Level1) { /** * @tc.steps: step1. Register observer @@ -821,7 +825,6 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncNormalDownload002, Test * @tc.expected: step5. Download task changes from 1 to 0 */ auto manager = RuntimeContext::GetInstance()->GetAssetsDownloadManager(); - EXPECT_EQ(manager->GetCurrentDownloadCount(), 1u); std::this_thread::sleep_for(std::chrono::seconds(1)); EXPECT_EQ(manager->GetCurrentDownloadCount(), 0u); /** @@ -996,6 +999,44 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncNormalDownload004, Test virtualAssetLoader_->ForkDownload(nullptr); } +/** + * @tc.name: AsyncNormalDownload005 + * @tc.desc: Test concurrent async download of assets and sync data. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncNormalDownload005, TestSize.Level1) +{ + /** + * @tc.steps: step1. Set max download task 1 + * @tc.expected: step1. ok + */ + AsyncDownloadAssetsConfig config; + config.maxDownloadTask = 12; + EXPECT_EQ(RuntimeConfig::SetAsyncDownloadAssetsConfig(config), OK); + /** + * @tc.steps: step2. Insert cloud data and sync concurrently + * @tc.expected: step2. ok + */ + const int cloudCount = 200; + auto schema = GetSchema(); + int threadNum = 10; + CloudSyncOption option = GetAsyncCloudSyncOption(); + thread *syncThreads[threadNum]; + for (int i = 0; i < threadNum; i++) { + syncThreads[i] = new thread([&]() { + EXPECT_EQ(RDBDataGenerator::InsertCloudDBData(0, cloudCount, 0, schema, virtualCloudDb_), OK); + RelationalTestUtils::CloudBlockSync(option, delegate_); + DeleteLocalData(db_, "AsyncDownloadAssetsTest"); + }); + } + for (auto &thread : syncThreads) { + thread->join(); + delete thread; + } +} + /** * @tc.name: AsyncAbnormalDownload006 * @tc.desc: Test abnormal async download. @@ -1067,6 +1108,21 @@ void DistributedDBCloudAsyncDownloadAssetsTest::UpdateLocalData( LOGW("update local data finished"); } +void DistributedDBCloudAsyncDownloadAssetsTest::DeleteLocalData(sqlite3 *&db, const std::string &tableName) +{ + const string sql = "delete from " + tableName + " where pk >= 0;"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + LOGW("delete local data finished"); +} + +void DistributedDBCloudAsyncDownloadAssetsTest::CheckLogTable(sqlite3 *&db, const std::string &tableName, int count) +{ + const string sql = "select COUNT(*) from " + DBCommon::GetLogTableName(tableName) + " where data_key>0;"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(count), nullptr), SQLITE_OK); + LOGW("check log table finished"); +} + void DistributedDBCloudAsyncDownloadAssetsTest::UpdateLocalAndCheckUploadCount(const bool &isAsync, const int &dataCount, const int &expectCount) { @@ -1141,7 +1197,7 @@ void DistributedDBCloudAsyncDownloadAssetsTest::UpdateLocalAndCheckUploadCount(c HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload007, TestSize.Level1) { int cloudCount = 10; - UpdateLocalAndCheckUploadCount(true, cloudCount, cloudCount); + EXPECT_NO_FATAL_FAILURE(UpdateLocalAndCheckUploadCount(true, cloudCount, cloudCount)); } /** @@ -1253,10 +1309,10 @@ void DistributedDBCloudAsyncDownloadAssetsTest::DoSkipAssetDownload(SkipAssetTes HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, SkipAssetDownloadTest001, TestSize.Level1) { /** - * @tc.expected: step1. sync return OK, and has 0 inconsistent records + * @tc.expected: step1. sync return OK, and has 1 inconsistent records */ SkipAssetTestParamT param = {.downloadRes = SKIP_ASSET, .useBatch = true, .useAsync = true, - .startIndex = 0, .expectInconsistentCount = 0, .expectSyncRes = OK}; + .startIndex = 0, .expectInconsistentCount = 1, .expectSyncRes = OK}; DoSkipAssetDownload(param); } @@ -1348,4 +1404,161 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload008, Te EXPECT_EQ(downloadCount, cloudCount); virtualAssetLoader_->ForkBatchDownload(nullptr); } + +/** + * @tc.name: AsyncAbnormalDownload010 + * @tc.desc: Test assets is async downloading when delete local data. + * @tc.type: FUNC + * @tc.require: + * @tc.author: tankaisheng + */ +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload010, TestSize.Level1) +{ + /** + * @tc.steps: step1. Set max download task 1 + * @tc.expected: step1. ok + */ + AsyncDownloadAssetsConfig config; + config.maxDownloadTask = 1; + config.maxDownloadAssetsCount = 2; + EXPECT_EQ(RuntimeConfig::SetAsyncDownloadAssetsConfig(config), OK); + /** + * @tc.steps: step2. Insert cloud data + * @tc.expected: step2. ok + */ + const int cloudCount = 2000; + auto schema = GetSchema(); + EXPECT_EQ(RDBDataGenerator::InsertCloudDBData(0, cloudCount, 0, schema, virtualCloudDb_), OK); + /** + * @tc.steps: step3. Sync + * @tc.expected: step3. ok + */ + CloudSyncOption option = GetAsyncCloudSyncOption(); + RelationalTestUtils::CloudBlockSync(option, delegate_); + /** + * @tc.steps: step4. Delete local data. + * @tc.expected: step4. ok + */ + DeleteLocalData(db_, "AsyncDownloadAssetsTest"); + /** + * @tc.steps: step5. Check log table. + * @tc.expected: step5. ok + */ + CheckLogTable(db_, "AsyncDownloadAssetsTest", 0); +} + +/** + * @tc.name: TriggerAsyncTask001 + * @tc.desc: Test trigger async task. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, TriggerAsyncTask001, TestSize.Level1) +{ + auto storage = std::make_shared(); + ASSERT_NE(storage, nullptr); + auto proxy = StorageProxy::GetCloudDb(storage.get()); + ASSERT_NE(proxy, nullptr); + auto syncer = new(std::nothrow) VirtualCloudSyncer(proxy); + ASSERT_NE(syncer, nullptr); + /** + * @tc.steps: step1. Trigger async task with not exist table contain assets. + */ + syncer->TriggerAsyncTask(); + /** + * @tc.steps: step2. Trigger async task with exist table contain assets. + */ + EXPECT_CALL(*storage, IsExistTableContainAssets).WillRepeatedly(testing::Return(true)); + EXPECT_CALL(*storage, GetDownloadAssetTable).WillRepeatedly([]() { + std::pair> res; + return res; + }); + syncer->TriggerAsyncTask(); + syncer->WaitTaskFinished(); + /** + * @tc.steps: step3. Async trigger and wait finished. + */ + std::thread t1([syncer]() { + for (int i = 0; i < 1000; ++i) { + syncer->TriggerAsyncTask(); + } + }); + std::thread t2([syncer]() { + for (int i = 0; i < 1000; ++i) { + syncer->WaitTaskFinished(); + } + }); + t1.join(); + t2.join(); + syncer->Close(); + RefObject::KillAndDecObjRef(syncer); +} + +/** + * @tc.name: AsyncAbnormalDownload011 + * @tc.desc: Test set reference when async downloading. + * @tc.type: FUNC + * @tc.require: + * @tc.author: tankaisheng + */ +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload011, TestSize.Level1) +{ + /** + * @tc.steps: step1. Set max download task 1 + * @tc.expected: step1. ok + */ + AsyncDownloadAssetsConfig config; + config.maxDownloadTask = 1; + config.maxDownloadAssetsCount = 2; + EXPECT_EQ(RuntimeConfig::SetAsyncDownloadAssetsConfig(config), OK); + /** + * @tc.steps: step2. Insert cloud data + * @tc.expected: step2. ok + */ + const int cloudCount = 100; + auto schema = GetSchema(); + EXPECT_EQ(RDBDataGenerator::InsertCloudDBData(0, cloudCount, 0, schema, virtualCloudDb_), OK); + /** + * @tc.steps: step3. Fork download set reference + * @tc.expected: step3. ok + */ + TableReferenceProperty tableReferenceProperty; + tableReferenceProperty.sourceTableName = "AsyncDownloadAssetsTest"; + tableReferenceProperty.targetTableName = "TABLE1"; + std::map columns; + columns["int_field"] = "int_field"; + tableReferenceProperty.columns = columns; + CloudSyncOption option = GetAsyncCloudSyncOption(); + + std::mutex mtx; + std::condition_variable cv; + bool t2_started = false; + + std::thread t1([this, option, &mtx, &cv, &t2_started]() { + { + std::unique_lock lock(mtx); + t2_started = true; + cv.notify_one(); + } + RelationalTestUtils::CloudBlockSync(option, delegate_); + }); + + std::thread t2([this, tableReferenceProperty, &mtx, &cv, &t2_started] { + std::unique_lock lock(mtx); + cv.wait(lock, [&]{ return t2_started; }); + EXPECT_EQ(delegate_->SetReference({tableReferenceProperty}), OK); + }); + + t1.join(); + t2.join(); + /** + * @tc.steps: step5. Check download count + * @tc.expected: step5. ok + */ + auto [status, downloadCount] = delegate_->GetDownloadingAssetsCount(); + EXPECT_EQ(status, OK); + EXPECT_NE(downloadCount, 0); + virtualAssetLoader_->ForkBatchDownload(nullptr); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_syncer_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_syncer_test.cpp index 514201fd2c7c45715de0c4114632276bfb844b6b..2628a7d2ed61c055658522788956d8a7a7eddcf9 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_syncer_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_syncer_test.cpp @@ -315,7 +315,7 @@ void DistributedDBCloudKvSyncerTest::CheckUploadAbnormal(OpType opType, int64_t * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync001, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync001, TestSize.Level1) { auto cloudHook = (ICloudSyncStorageHook *) singleStore_->GetCloudKvStore(); ASSERT_NE(cloudHook, nullptr); @@ -346,14 +346,14 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync001, TestSize.Level0) cloudHook->SetSyncFinishHook([&syncCnt, this] { LOGD("sync finish times:%d", ++syncCnt); if (syncCnt == 1) { // 1 is the first sync - CheckUploadAbnormal(OpType::UPDATE, 1L); // 1 is expected count + CheckUploadAbnormal(OpType::UPDATE, 1L, true); // 1 is expected count } else { CheckUploadAbnormal(OpType::UPDATE, 1L, true); // 1 is expected count } comSyncCv.notify_all(); }); BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); - BlockCompensatedSync(syncCnt, 2); // 2 is sync times + BlockCompensatedSync(syncCnt, 1); // 2 is sync times virtualCloudDb_->ForkUpload(nullptr); cloudHook->SetSyncFinishHook(nullptr); } @@ -365,7 +365,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync001, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync002, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync002, TestSize.Level1) { auto cloudHook = (ICloudSyncStorageHook *) singleStore_->GetCloudKvStore(); ASSERT_NE(cloudHook, nullptr); @@ -423,7 +423,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync002, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync003, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync003, TestSize.Level1) { auto cloudHook = (ICloudSyncStorageHook *) singleStore_->GetCloudKvStore(); ASSERT_NE(cloudHook, nullptr); @@ -480,7 +480,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync003, TestSize.Level0) * @tc.require: * @tc.author: chenghuitao */ -HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync004, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync004, TestSize.Level1) { /** * @tc.steps:step1. Device A inserts data and synchronizes @@ -502,7 +502,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync004, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync005, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync005, TestSize.Level1) { /** * @tc.steps:step1. Put 1 record to cloud @@ -571,7 +571,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, QueryParsingProcessTest001, TestSize.Le * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvSyncerTest, UploadFinished001, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, UploadFinished001, TestSize.Level1) { Key key = {'k'}; Value value = {'v'}; @@ -602,7 +602,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, UploadFinished001, TestSize.Level0) * @tc.require: * @tc.author: liufuchenxing */ -HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers001, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers001, TestSize.Level1) { Key key = {'k'}; Value value = {'v'}; @@ -649,7 +649,7 @@ void DistributedDBCloudKvSyncerTest::PutKvBatchDataAndSyncCloud(CloudSyncOption * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers002, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers002, TestSize.Level1) { /** * @tc.steps: step1. kvDelegatePtrS1_ put 200 data and sync to cloud. @@ -732,7 +732,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers002, TestSize.Leve * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers003, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers003, TestSize.Level1) { /** * @tc.steps: step1. put k v by user1. @@ -788,7 +788,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers003, TestSize.Leve * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers004, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers004, TestSize.Level1) { /** * @tc.steps: step1. put k v by user1 and sync to cloud. @@ -835,7 +835,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers004, TestSize.Leve * @tc.require: * @tc.author: suyue */ -HWTEST_F(DistributedDBCloudKvSyncerTest, AbnormalCloudKvExecutorTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, AbnormalCloudKvExecutorTest001, TestSize.Level1) { /** * @tc.steps: step1. Call PutCloudData interface with different opType when para is invalid. @@ -900,7 +900,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, AbnormalCloudKvExecutorTest002, TestSiz /** * @tc.steps: step2. open db and Call FillCloudLog. - * @tc.expected: step2. return E_OK. + * @tc.expected: step2. return -SQLITE_ERROR, because the table is not exist. */ uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; std::string fileUrl = g_testDir + "/test.db"; @@ -909,9 +909,9 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, AbnormalCloudKvExecutorTest002, TestSiz data.isCloudVersionRecord = true; ret = cloudKvObj.FillCloudLog({db, true}, OpType::INSERT, data, "", recorder); - EXPECT_EQ(ret, E_OK); + EXPECT_EQ(ret, -SQLITE_ERROR); ret = cloudKvObj.FillCloudLog({db, true}, OpType::DELETE, data, "", recorder); - EXPECT_EQ(ret, E_OK); + EXPECT_EQ(ret, -SQLITE_ERROR); EXPECT_EQ(sqlite3_close_v2(db), E_OK); } @@ -922,7 +922,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, AbnormalCloudKvExecutorTest002, TestSiz * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudKvSyncerTest, DeviceCollaborationTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, DeviceCollaborationTest001, TestSize.Level1) { /** * @tc.steps: step1. open db with DEVICE_COLLABORATION. @@ -973,7 +973,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, DeviceCollaborationTest001, TestSize.Le * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudKvSyncerTest, DeviceCollaborationTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, DeviceCollaborationTest002, TestSize.Level1) { /** * @tc.steps: step1. open db with DEVICE_COLLABORATION. @@ -1069,7 +1069,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, DeviceCollaborationTest003, TestSize.Le * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithKvAndCloud001, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithKvAndCloud001, TestSize.Level1) { /** * @tc.steps: step1. put k1 v1 by user1 and sync between devices. @@ -1111,4 +1111,58 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithKvAndCloud001, TestSize.Level0) EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue), OK); EXPECT_EQ(actualValue, value2); } + +/** + * @tc.name: ClearCloudWatermarkTest001. + * @tc.desc: Test clear kv cloud watermark + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudKvSyncerTest, ClearCloudWatermarkTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. put (k1, v1)(k2, v2) and sync + * @tc.expected: step1. return ok. + */ + EXPECT_EQ(kvDelegatePtrS1_->Put(KEY_1, VALUE_1), OK); + EXPECT_EQ(kvDelegatePtrS2_->Put(KEY_2, VALUE_2), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + /** + * @tc.steps: step1. clear kv cloud watermark. + * @tc.expected: step1. return ok. + */ + ClearKvMetaDataOption option; + option.type = ClearKvMetaOpType::CLEAN_CLOUD_WATERMARK; + EXPECT_EQ(kvDelegatePtrS1_->ClearMetaData(option), OK); + EXPECT_EQ(kvDelegatePtrS2_->ClearMetaData(option), OK); +} + +/** + * @tc.name: UploadBlockTest001. + * @tc.desc: Test upload block and put get data + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBCloudKvSyncerTest, UploadBlockTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. put (k1, v1) + * @tc.expected: step1. return ok. + */ + EXPECT_EQ(kvDelegatePtrS1_->Put(KEY_1, VALUE_1), OK); + /** + * @tc.steps: step2. fork upload and sync + * @tc.expected: step2. return ok. + */ + virtualCloudDb_->ForkUpload([this](const std::string &, VBucket &) { + EXPECT_EQ(kvDelegatePtrS1_->Put(KEY_2, VALUE_2), OK); + Value value; + EXPECT_EQ(kvDelegatePtrS1_->Get(KEY_2, value), OK); + EXPECT_EQ(value, VALUE_2); + }); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp index a5b82a242646ac38182bc7404b47163e2046e088..16758ec3a2ef20fb21a63fdff85bb3f83f824929 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp @@ -397,7 +397,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync001, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync002, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync002, TestSize.Level1) { /** * @tc.steps: step1. store1 put (k1,v1) store2 put (k2,v2) @@ -459,7 +459,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync002, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync003, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync003, TestSize.Level1) { /** * @tc.steps: step1. store1 put (k1,v1) store2 put (k1,v2) @@ -496,7 +496,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync003, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync004, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync004, TestSize.Level1) { /** * @tc.steps: step1. store1 put (k1,v1) and both sync @@ -555,7 +555,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync005, TestSize.Level1) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync006, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync006, TestSize.Level1) { Key k1 = {'k', '1'}; Key k2 = {'k', '2'}; @@ -581,7 +581,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync006, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync007, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync007, TestSize.Level1) { Key k1 = {'k', '1'}; Key k2 = {'k', '2'}; @@ -611,7 +611,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync007, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync008, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync008, TestSize.Level1) { Key k1 = {'k', '1'}; Value v1 = {'v', '1'}; @@ -636,7 +636,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync008, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync009, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync009, TestSize.Level1) { Key k1 = {'k', '1'}; Key k2 = {'k', '2'}; @@ -663,7 +663,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync009, TestSize.Level0) * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync010, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync010, TestSize.Level1) { // add , sync to cloud with user1 Key key1 = {'k', '1'}; @@ -710,7 +710,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync010, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync011, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync011, TestSize.Level1) { std::shared_ptr g_adapter = std::make_shared(); RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); @@ -732,7 +732,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync011, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync012, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync012, TestSize.Level1) { KvStoreNbDelegate *memoryDB1 = nullptr; KvStoreNbDelegate::Option option1; @@ -760,7 +760,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync012, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync013, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync013, TestSize.Level1) { KvStoreNbDelegate* kvDelegatePtrS3_ = nullptr; KvStoreNbDelegate::Option option; @@ -819,7 +819,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync014, TestSize.Level1) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync015, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync015, TestSize.Level1) { Key key = {'k'}; Value expectValue = {'v'}; @@ -848,7 +848,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync015, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync016, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync016, TestSize.Level1) { Key key = {'k', '1'}; Value value1 = {'v', '1'}; @@ -878,7 +878,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync016, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync017, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync017, TestSize.Level1) { Key key = {'k'}; Value value = {'v'}; @@ -897,7 +897,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync017, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync018, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync018, TestSize.Level1) { /** * @tc.steps:step1. Get two Memory DB. @@ -955,7 +955,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync018, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync019, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync019, TestSize.Level1) { Key k1 = {'k', '1'}; Value v1 = {'v', '1'}; @@ -974,7 +974,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync019, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync020, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync020, TestSize.Level1) { /** * @tc.steps:step1. Inserts a piece of data. @@ -1009,7 +1009,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync020, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync021, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync021, TestSize.Level1) { /** * @tc.steps:step1. store2 GetCloudVersion. @@ -1094,7 +1094,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync022, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync023, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync023, TestSize.Level1) { Key k1 = {'k', '1'}; Value v1 = {'v', '1'}; @@ -1116,7 +1116,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync023, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync024, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync024, TestSize.Level1) { /** * @tc.steps:step1. Device A inserts data and synchronizes, then Device B synchronizes. @@ -1155,7 +1155,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync024, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync025, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync025, TestSize.Level1) { virtualCloudDb_->SetBlockTime(1000); // block query 1000ms auto option = g_CloudSyncoption; @@ -1173,7 +1173,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync025, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync026, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync026, TestSize.Level1) { /** * @tc.steps:step1. Create a database with the DEVICE_COLLABORATION mode on device1. @@ -1216,7 +1216,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync026, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync027, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync027, TestSize.Level1) { /** * @tc.steps:step1. put 1 record and sync. @@ -1246,7 +1246,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync027, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync028, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync028, TestSize.Level1) { /** * @tc.steps:step1. put 1 record and sync. @@ -1327,7 +1327,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync029, TestSize.Level3) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync030, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync030, TestSize.Level1) { /** * @tc.steps:step1. Create a database. @@ -1373,7 +1373,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync030, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync031, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync031, TestSize.Level1) { /** * @tc.steps:step1. put 1 record and sync. @@ -1404,7 +1404,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync031, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync032, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync032, TestSize.Level1) { /** * @tc.steps:step1. put 10 records. @@ -1451,7 +1451,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync032, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync033, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync033, TestSize.Level1) { /** * @tc.steps:step1. put local records {k1, v1} {k2, v2} and sync to cloud. @@ -1496,7 +1496,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync033, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync034, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync034, TestSize.Level1) { /** * @tc.steps:step1. put data which size > maxUploadSize. @@ -1542,7 +1542,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync034, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync035, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync035, TestSize.Level1) { /** * @tc.steps:step1. put local records {k1, v1} and sync to cloud. @@ -1597,7 +1597,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync035, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync036, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync036, TestSize.Level1) { /** * @tc.steps:step1. put data and SetCloudSyncConfig. @@ -1624,7 +1624,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync036, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync037, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync037, TestSize.Level1) { /** * @tc.steps:step1. deviceA put {k1, v1} and sync to cloud. @@ -1670,7 +1670,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync037, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync038, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync038, TestSize.Level1) { /** * @tc.steps:step1. deviceA put {k1, v1} and sync to cloud. @@ -1720,7 +1720,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync038, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync039, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync039, TestSize.Level1) { /** * @tc.steps:step1. deviceA put {k1, v1} {k2, v2} and sync to cloud. @@ -1774,7 +1774,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync039, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync040, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync040, TestSize.Level1) { /** * @tc.steps:step1. deviceA put {k1, v1} and sync to cloud. @@ -1860,7 +1860,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync041, TestSize.Level1) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync042, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync042, TestSize.Level1) { /** * @tc.steps:step1. put 10 records. @@ -1921,7 +1921,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync042, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync043, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync043, TestSize.Level1) { /** * @tc.steps:step1. put 10 records. @@ -1977,7 +1977,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync043, TestSize.Level0) * @tc.require: * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync044, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync044, TestSize.Level1) { /** * @tc.steps: step1. store1 put (k1,v1) and (k2,v2) @@ -2033,7 +2033,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync044, TestSize.Level0) * @tc.require: * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync045, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync045, TestSize.Level1) { /** * @tc.steps:step1. put 10 records. @@ -2072,7 +2072,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync045, TestSize.Level0) * @tc.require: * @tc.author: chenghuitao */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync046, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync046, TestSize.Level1) { /** * @tc.steps: step1. store1 put (k1,v1) and (k2,v2) @@ -2128,7 +2128,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync046, TestSize.Level0) * @tc.require: * @tc.author: suyue */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync047, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync047, TestSize.Level1) { /** * @tc.steps: step1. put 20 records. @@ -2179,7 +2179,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync047, TestSize.Level0) * @tc.require: * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync048, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync048, TestSize.Level1) { /** * @tc.steps: step1. deviceB put {k1, v1} {k2, v2} and sync to cloud @@ -2220,7 +2220,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync048, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync049, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync049, TestSize.Level1) { /** * @tc.steps: step1. put {k, v} @@ -2282,7 +2282,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync049, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync050, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync050, TestSize.Level1) { /** * @tc.steps: step1. Set the retry count to 1 @@ -2332,7 +2332,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync050, TestSize.Level0) * @tc.require: * @tc.author: suyuchen */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync051, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync051, TestSize.Level1) { /** * @tc.steps: step1. Set the retry count to 0 @@ -2382,7 +2382,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync051, TestSize.Level0) * @tc.require: * @tc.author: suyuchen */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync052, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync052, TestSize.Level1) { /** * @tc.steps: step1. Set the retry count to 2 @@ -2434,7 +2434,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync052, TestSize.Level0) * @tc.require: * @tc.author: suyuchen */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync053, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync053, TestSize.Level1) { /** * @tc.steps: step1. Set the retry count to 0 @@ -2487,4 +2487,197 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync053, TestSize.Level0) } virtualCloudDb_->ForkInsertConflict(nullptr); } + +/** + * @tc.name: NormalSync054 + * @tc.desc: test get and put interface execute + * @tc.type: FUNC + * @tc.require: + * @tc.author: tankaisheng + */ +HWTEST_F(DistributedDBCloudKvTest, NormalSync054, TestSize.Level1) +{ + /** + * @tc.steps:step1. deviceA put {k1, v1} and sync to cloud. + * @tc.expected: step1. ok. + */ + communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); + Key key = {'k', '1'}; + Value expectValue1 = {'v', '1'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, expectValue1), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + + /** + * @tc.steps:step2. deviceB sync to cloud. + * @tc.expected: step2. ok. + */ + communicatorAggregator_->SetLocalDeviceId("DEVICES_B"); + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + Value actualValue1; + EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue1), OK); + EXPECT_EQ(actualValue1, expectValue1); + + EXPECT_EQ(kvDelegatePtrS2_->StartTransaction(), OK); + EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue1), OK); + EXPECT_EQ(actualValue1, expectValue1); + EXPECT_TRUE(kvDelegatePtrS2_->Commit() == OK); +} + +/** + * @tc.name: KvSupportEncryptTest001 + * @tc.desc: Test sync when different security label and encryption para is set + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudKvTest, KvSupportEncryptTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. sync when security label is S4 and encryption is not supported + * @tc.expected: step1. return SECURITY_OPTION_CHECK_ERROR. + */ + std::shared_ptr g_adapter = std::make_shared(); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); + KvStoreNbDelegate* kvDelegatePtrS3_ = nullptr; + KvStoreNbDelegate::Option option; + option.secOption.securityLabel = S4; + EXPECT_EQ(GetKvStore(kvDelegatePtrS3_, STORE_ID_3, option), OK); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, SECURITY_OPTION_CHECK_ERROR); + + /** + * @tc.steps: step2. sync when security label is S4 and encryption is supported + * @tc.expected: step2. return OK. + */ + CloudSyncConfig config; + config.isSupportEncrypt = true; + kvDelegatePtrS3_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, OK); + CloseKvStore(kvDelegatePtrS3_, STORE_ID_3); + + /** + * @tc.steps: step3. sync when security label is not set and encryption is supported + * @tc.expected: step3. return ok. + */ + kvDelegatePtrS1_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + + /** + * @tc.steps: step4. sync when security label is not set and encryption is not supported + * @tc.expected: step4. return ok. + */ + config.isSupportEncrypt = false; + kvDelegatePtrS1_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); +} + +/** + * @tc.name: KvSupportEncryptTest002 + * @tc.desc: Test sync when encryption para is set multiple times + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudKvTest, KvSupportEncryptTest002, TestSize.Level1) +{ + /** + * @tc.steps: step1. sync when isSupportEncrypt is set to true for the first time + * @tc.expected: step1. return OK. + */ + std::shared_ptr g_adapter = std::make_shared(); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); + KvStoreNbDelegate* kvDelegatePtrS3_ = nullptr; + KvStoreNbDelegate::Option option; + option.secOption.securityLabel = S4; + EXPECT_EQ(GetKvStore(kvDelegatePtrS3_, STORE_ID_3, option), OK); + CloudSyncConfig config; + config.isSupportEncrypt = true; + kvDelegatePtrS3_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, OK); + + /** + * @tc.steps: step2. sync when isSupportEncrypt is set to false for the second time + * @tc.expected: step2. return SECURITY_OPTION_CHECK_ERROR. + */ + config.isSupportEncrypt = false; + kvDelegatePtrS3_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, SECURITY_OPTION_CHECK_ERROR); + + /** + * @tc.steps: step3. sync when isSupportEncrypt is set to true for the third time + * @tc.expected: step3. return OK. + */ + config.isSupportEncrypt = true; + kvDelegatePtrS3_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, OK); + CloseKvStore(kvDelegatePtrS3_, STORE_ID_3); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); +} + +/** + * @tc.name: KvSupportEncryptTest003 + * @tc.desc: Test GetCloudSyncConfig when GetCloudKvStore is nullptr + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudKvTest, KvSupportEncryptTest003, TestSize.Level1) +{ + SQLiteSingleVerNaturalStore store; + EXPECT_EQ(store.GetCloudKvStore(), nullptr); + CloudSyncConfig config = store.GetCloudSyncConfig(); + EXPECT_EQ(config.isSupportEncrypt, false); +} + +/** + * @tc.name: KvSupportEncryptTest004 + * @tc.desc: Test sync when security label change and different encryption para is set + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudKvTest, KvSupportEncryptTest004, TestSize.Level1) +{ + /** + * @tc.steps: step1. sync when security label is S2 and different encryption para is set + * @tc.expected: step1. return OK. + */ + std::shared_ptr g_adapter = std::make_shared(); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); + KvStoreNbDelegate* kvDelegatePtrS3_ = nullptr; + KvStoreNbDelegate::Option option; + option.secOption.securityLabel = S2; + EXPECT_EQ(GetKvStore(kvDelegatePtrS3_, STORE_ID_3, option), OK); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, OK); + CloudSyncConfig config; + config.isSupportEncrypt = true; + kvDelegatePtrS3_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, OK); + CloseKvStore(kvDelegatePtrS3_, STORE_ID_3); + + /** + * @tc.steps: step2. sync when security label is S4 and different encryption para is set + * @tc.expected: step2. support encrypt return OK, not support encrypt return SECURITY_OPTION_CHECK_ERROR. + */ + option.secOption.securityLabel = S4; + EXPECT_EQ(GetKvStore(kvDelegatePtrS3_, STORE_ID_3, option), OK); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, SECURITY_OPTION_CHECK_ERROR); + config.isSupportEncrypt = true; + kvDelegatePtrS3_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, OK); + CloseKvStore(kvDelegatePtrS3_, STORE_ID_3); + + /** + * @tc.steps: step3. sync when security label is S1 and different encryption para is set + * @tc.expected: step3. return OK. + */ + option.secOption.securityLabel = S1; + EXPECT_EQ(GetKvStore(kvDelegatePtrS3_, STORE_ID_3, option), OK); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, OK); + config.isSupportEncrypt = true; + kvDelegatePtrS3_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, OK); + CloseKvStore(kvDelegatePtrS3_, STORE_ID_3); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); +} } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kvstore_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kvstore_test.cpp index 95797c58c96e0d21e365af66a57b1bc0bd931810..2cd4b6e46b69a6ba8e134e0940289e0a752c04e3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kvstore_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kvstore_test.cpp @@ -27,6 +27,7 @@ #include "virtual_communicator_aggregator.h" #include "virtual_cloud_db.h" #include "sqlite_utils.h" +#include "time_helper.h" using namespace testing::ext; using namespace DistributedDB; using namespace DistributedDBUnitTest; @@ -105,6 +106,8 @@ void DistributedDBCloudKvStoreTest::TearDownTestCase() if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error!"); } + g_CloudSyncoption.users.clear(); + g_CloudSyncoption.devices.clear(); } void DistributedDBCloudKvStoreTest::SetUp() @@ -1448,7 +1451,7 @@ HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest013, TestSize.Level0) */ Key k1 = {'k', '1'}; Value v1 = {'v', '1'}; - deviceB_->PutData(k1, v1, 1u, 0); // 1 is current timestamp + deviceB_->PutData(k1, v1, TimeHelper::GetSysCurrentTime() + TimeHelper::BASE_OFFSET, 0); /** * @tc.steps: step2. sync between devices * * @tc.expected: step2. insert successfully @@ -1889,7 +1892,7 @@ HWTEST_F(DistributedDBCloudKvStoreTest, ObserverDataChangeTest002, TestSize.Leve Value actualValue; EXPECT_EQ(kvDelegatePtrS2_->Get(k1, actualValue), OK) ; EXPECT_EQ(actualValue, v1); - + std::this_thread::sleep_for(std::chrono::milliseconds(1)); // sleep for 1ms Key k2 = {'k', '2'}; Value v2 = {'v', '2'}; ASSERT_EQ(kvDelegatePtrS1_->Put(k1, v2), OK); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_only_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_only_test.cpp index 6af3557f91f07b7db5fefd23b29d76eb2bcc6847..8e021817584d290651e25d918fe491832e8d541d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_only_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_only_test.cpp @@ -785,7 +785,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly001, * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly002, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -824,7 +824,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly002, * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly003, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -883,7 +883,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly003, * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly004, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly004, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -946,7 +946,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly004, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly005, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly005, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -974,7 +974,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly005, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly006, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly006, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -988,7 +988,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly006, * @tc.steps:step2. Download assets which cloud no found * @tc.expected: step2. return ASSET_NOT_FOUND_FOR_DOWN_ONLY. */ - std::vector inValue = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};; + std::vector inValue = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; std::map> assets; assets["assets"] = {ASSET_COPY.name + "10"}; Query query = Query::Select().From(ASSETS_TABLE_NAME).In("id", inValue).And().AssetsOnly(assets); @@ -1002,7 +1002,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly006, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly007, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly007, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1063,7 +1063,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly007, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly008, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly008, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1077,7 +1077,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly008, * @tc.steps:step2. Download assets which local no found * @tc.expected: step2. return ASSET_NOT_FOUND_FOR_DOWN_ONLY. */ - std::vector inValue = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};; + std::vector inValue = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; std::map> assets; assets["assets"] = {ASSET_COPY.name + "0"}; std::map> assets1; @@ -1094,7 +1094,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly008, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly009, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly009, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1124,7 +1124,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly009, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly010, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly010, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1178,7 +1178,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly010, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly011, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly011, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1264,7 +1264,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly012, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly013, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly013, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1295,7 +1295,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly013, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly014, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly014, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1323,7 +1323,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly014, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly015, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly015, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1388,7 +1388,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly015, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly016, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly016, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1437,7 +1437,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly016, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly017, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly017, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1472,7 +1472,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly017, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly018, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly018, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1512,7 +1512,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly018, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly019, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly019, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1540,7 +1540,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly019, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly020, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly020, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1601,7 +1601,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly020, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly021, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly021, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1633,7 +1633,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly021, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly022, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly022, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1663,7 +1663,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly022, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly023, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly023, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1685,5 +1685,78 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly023, EndGroup().And().BeginGroup().EqualTo("id", 0).And().AssetsOnly(assets1).EndGroup(); PriorityLevelSync(2, query, SyncMode::SYNC_MODE_CLOUD_FORCE_PULL, DBStatus::OK); } + +/** + * @tc.name: DownloadAssetsOnly024 + * @tc.desc: test download task stop after the reference is set + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly024, TestSize.Level1) +{ + /** + * @tc.steps:step1. init data + * @tc.expected: step1. return OK. + */ + int dataCount = 10; + InsertCloudDBData(0, dataCount, 0, ASSETS_TABLE_NAME); + /** + * @tc.steps:step2. Set reference + * @tc.expected: step2. return OK. + */ + TableReferenceProperty tableReferenceProperty; + tableReferenceProperty.sourceTableName = NO_PRIMARY_TABLE; + tableReferenceProperty.targetTableName = COMPOUND_PRIMARY_TABLE; + std::map columns; + columns[COL_ID] = COL_ID; + tableReferenceProperty.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); + columns[COL_NAME] = COL_NAME; + tableReferenceProperty.columns = columns; + int cnt = 0; + int downCnt = 2; + /** + * @tc.steps:step3. fork download, set reference during downloading + * @tc.expected: step3. return OK. + */ + g_virtualAssetLoader->ForkDownload([&cnt, &tableReferenceProperty, downCnt]( + const std::string &tableName, std::map &) { + cnt++; + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + if (cnt != downCnt) { + return; + } + std::thread t1([&tableReferenceProperty]() { + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); + }); + t1.detach(); + }); + /** + * @tc.steps:step4. sync and check download count + * @tc.expected: step4. return OK. + */ + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::CLOUD_ERROR); + EXPECT_NE(cnt, 0); + EXPECT_NE(cnt, dataCount); +} + +/** + * @tc.name: SetAssetsConfig001 + * @tc.desc: Test set async download assets config + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, SetAssetsConfig001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Set valid param + * @tc.expected: step1. ok + */ + AsyncDownloadAssetsConfig config; + config.maxDownloadTask = 10; + EXPECT_EQ(RuntimeConfig::SetAsyncDownloadAssetsConfig(config), OK); +} } // namespace #endif // RELATIONAL_STORE diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_test.cpp index f47b0b188585ea0689c211bdca8cfea487549fcf..214dec31445f07006ae17125145641a4462e7e41 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_test.cpp @@ -135,16 +135,20 @@ void GetCloudDbSchema(DataBaseSchema &dataBaseSchema) dataBaseSchema.tables.push_back(assetsTableSchema); } -void GenerateDataRecords( - int64_t begin, int64_t count, int64_t gidStart, std::vector &record, std::vector &extend) +std::pair, std::vector> GenerateDataRecords(int64_t begin, int64_t count, + int64_t gidStart, bool hasAsset) { + std::pair, std::vector> res; + auto &[record, extend] = res; for (int64_t i = begin; i < begin + count; i++) { Assets assets; - Asset asset = ASSET_COPY; - asset.name = ASSET_COPY.name + std::to_string(i); - assets.emplace_back(asset); - asset.name = ASSET_COPY.name + std::to_string(i) + "_copy"; - assets.emplace_back(asset); + if (hasAsset) { + Asset asset = ASSET_COPY; + asset.name = ASSET_COPY.name + std::to_string(i); + assets.emplace_back(asset); + asset.name = ASSET_COPY.name + std::to_string(i) + "_copy"; + assets.emplace_back(asset); + } VBucket data; data.insert_or_assign(COL_ID, i); data.insert_or_assign(COL_NAME, "name" + std::to_string(i)); @@ -161,6 +165,13 @@ void GenerateDataRecords( log.insert_or_assign(CloudDbConstant::GID_FIELD, std::to_string(i + gidStart)); extend.push_back(log); } + return res; +} + +void GenerateDataRecords( + int64_t begin, int64_t count, int64_t gidStart, std::vector &record, std::vector &extend) +{ + std::tie(record, extend) = GenerateDataRecords(begin, count, gidStart, true); } void InsertLocalData(sqlite3 *&db, int64_t begin, int64_t count, const std::string &tableName, bool isAssetNull = true) @@ -281,11 +292,10 @@ void CheckLockStatus(sqlite3 *db, int startId, int endId, LockStatus lockStatus) } } -void InsertCloudDBData(int64_t begin, int64_t count, int64_t gidStart, const std::string &tableName) +void InsertCloudDBData(int64_t begin, int64_t count, int64_t gidStart, const std::string &tableName, + bool hasAsset = true) { - std::vector record; - std::vector extend; - GenerateDataRecords(begin, count, gidStart, record, extend); + auto [record, extend] = GenerateDataRecords(begin, count, gidStart, hasAsset); if (tableName == ASSETS_TABLE_NAME_SHARED) { for (auto &vBucket: record) { vBucket.insert_or_assign(CloudDbConstant::CLOUD_OWNER, std::string("cloudA")); @@ -802,7 +812,7 @@ void DistributedDBCloudSyncerDownloadAssetsTest::DataStatusTest007() * @tc.require: * @tc.author: liufuchenxing */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest001, TestSize.Level1) { /** * @tc.steps:step1. Mock asset download interface. @@ -844,7 +854,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId001, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -872,7 +882,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId001, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId002, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -899,7 +909,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId002, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId003, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -926,7 +936,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId003, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId004, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId004, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -953,7 +963,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId004, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId005, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId005, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -980,7 +990,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId005, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId006, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId006, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -1007,7 +1017,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId006, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId007, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId007, TestSize.Level1) { CloudSyncConfig config; config.maxUploadCount = 200; // max upload 200 @@ -1062,7 +1072,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId007, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId008, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId008, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -1096,7 +1106,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId008, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId009, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId009, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -1122,7 +1132,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId009, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId010, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId010, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -1149,7 +1159,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId010, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId011, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId011, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -1173,7 +1183,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId011, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId012, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId012, TestSize.Level1) { /** * @tc.steps:step1. set extend size missing then sync, check the asseid. @@ -1211,7 +1221,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId012, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId013, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId013, TestSize.Level1) { /** * @tc.steps:step1. local insert data and sync, then delete local data and insert new data @@ -1241,7 +1251,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId013, TestSize.Le * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId014, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId014, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -1299,7 +1309,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId014, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId015, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId015, TestSize.Level1) { /** * @tc.steps:step1. local insert data and fork batchinsert return CLOUD_NETWORK_ERROR, then sync @@ -1349,7 +1359,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId015, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId016, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId016, TestSize.Level1) { /** * @tc.steps:step1. local insert data and sync, then delete last local data @@ -1377,7 +1387,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId016, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId017, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId017, TestSize.Level1) { /** * @tc.steps:step1. local insert data and sync,check cursor. @@ -1403,7 +1413,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId017, TestSize.Le * @tc.require: * @tc.author: zhaoliang */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId018, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId018, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -1429,7 +1439,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId018, TestSize.Le * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest002, TestSize.Level1) { /** * @tc.steps:step1. Mock asset download return CLOUD_ERROR. @@ -1466,7 +1476,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest003, TestSize.Level1) { /** * @tc.steps:step1. Mock asset download return CLOUD_ERROR. @@ -1508,7 +1518,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest004, TestSize.Level1) { /** * @tc.steps:step1. Mock asset download return CLOUD_ERROR. @@ -1548,7 +1558,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest005, TestSize.Level1) { /** * @tc.steps:step1. init data and sync @@ -1591,7 +1601,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId019, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId019, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync. @@ -1618,7 +1628,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId019, TestSize.Le * @tc.require: * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId020, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId020, TestSize.Level1) { CloudSyncConfig config; config.maxUploadCount = 200; // max upload 200 @@ -1695,7 +1705,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId020, TestSize.Le * @tc.require: * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId021, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId021, TestSize.Level1) { CloudSyncConfig config; config.maxUploadCount = 200; // max upload 200 @@ -1741,7 +1751,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId021, TestSize.Le * @tc.require: * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId022, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId022, TestSize.Level1) { CloudSyncConfig config; config.maxUploadCount = 200; // max upload 200 @@ -1787,7 +1797,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId022, TestSize.Le * @tc.require: * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId023, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId023, TestSize.Level1) { /** * @tc.steps:step1. set extend size missing then sync, check the asseid. @@ -1827,7 +1837,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId023, TestSize.Le * @tc.require: * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId024, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId024, TestSize.Level1) { /** * @tc.steps:step1. set extend size missing then sync, check the asseid. @@ -1867,7 +1877,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId024, TestSize.Le * @tc.require: * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId025, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId025, TestSize.Level1) { CloudSyncConfig config; config.maxUploadCount = 200; // max upload 200 @@ -1945,7 +1955,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId025, TestSize.Le * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest001, TestSize.Level1) { /** * @tc.steps:step1. init data for the different asset, sync and check flag @@ -1977,7 +1987,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest001, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest002, TestSize.Level1) { /** * @tc.steps:step1. init data for the same asset, sync and check flag @@ -2008,7 +2018,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest002, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest003, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -2083,7 +2093,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest003, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest004, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -2147,7 +2157,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest004, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest005, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -2205,7 +2215,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest005, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest006, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -2265,7 +2275,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest006, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest001, TestSize.Level1) { DataStatusTest001(false); } @@ -2277,7 +2287,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest001, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest002, TestSize.Level1) { DataStatusTest001(true); } @@ -2289,7 +2299,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest002, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest003, TestSize.Level1) { DataStatusTest003(); } @@ -2301,7 +2311,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest003, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest004, TestSize.Level1) { DataStatusTest004(); } @@ -2313,7 +2323,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest004, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest005, TestSize.Level1) { DataStatusTest005(); } @@ -2325,7 +2335,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest005, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest006, TestSize.Level1) { DataStatusTest006(); } @@ -2337,7 +2347,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest006, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest007, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest007, TestSize.Level1) { DataStatusTest007(); } @@ -2349,7 +2359,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest007, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest008, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest008, TestSize.Level1) { /** * @tc.steps:step1. init local data @@ -2402,7 +2412,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest008, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest001, TestSize.Level1) { RuntimeContext::GetInstance()->SetBatchDownloadAssets(true); /** @@ -2440,7 +2450,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest001, TestS * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest002, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -2491,7 +2501,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest002, TestS * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest003, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -2557,13 +2567,46 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest003, TestS g_virtualAssetLoader->SetRemoveLocalAssetsCallback(nullptr); } +/** + * @tc.name: DownloadAssetTest004 + * @tc.desc: Test asset download failed with no asset data + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest004, TestSize.Level1) +{ + /** + * @tc.steps:step1. init data + * @tc.expected: step1. return OK. + */ + int cloudCount = 10; // 10 is num of cloud + InsertCloudDBData(0, cloudCount, 0, ASSETS_TABLE_NAME, true); + InsertCloudDBData(cloudCount, cloudCount, cloudCount, ASSETS_TABLE_NAME, false); + /** + * @tc.steps:step2. Set asset download status error and sync + * @tc.expected: step2. sync successful but download assets fail. + */ + g_virtualAssetLoader->SetDownloadStatus(DBStatus::CLOUD_ERROR); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::CLOUD_ERROR); + /** + * @tc.steps:step3. Check FLAG_DEVICE_CLOUD_INCONSISTENCY data + * @tc.expected: step3. 10 data is cloud consistency because no asset. + */ + std::string logName = DBCommon::GetLogTableName(ASSETS_TABLE_NAME); + std::string sql = "SELECT COUNT(1) FROM " + logName + " WHERE flag & 0x20 = 0"; + int count = 0; + ASSERT_EQ(SQLiteUtils::GetCountBySql(db, sql, count), E_OK); + EXPECT_EQ(count, cloudCount); +} + /** * @tc.name: RecordLockFuncTest001 * @tc.desc: UNLOCKING->UNLOCKING Synchronous download failure wholly. * @tc.type: FUNC * @tc.author: lijun */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, RecordLockFuncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, RecordLockFuncTest001, TestSize.Level1) { /** * @tc.steps:step1. init local data @@ -2638,7 +2681,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, RecordLockFuncTest001, Test * @tc.type: FUNC * @tc.author: lijun */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, RecordLockFuncTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, RecordLockFuncTest002, TestSize.Level1) { /** * @tc.steps:step1. init local data, modify data Status and initiate synchronization @@ -2839,7 +2882,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, CloudTaskStatusTest002, Tes * @tc.require: * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, CompensatedSyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, CompensatedSyncTest001, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -2897,5 +2940,56 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, CompensatedSyncTest001, Tes EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, reinterpret_cast(0u), nullptr), SQLITE_OK); } + +/** + * @tc.name: CloudCooperationTrackerTableSync001 + * @tc.desc: test CLOUD_COOPERATION tracker table sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: tankaisheng + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, CloudCooperationTrackerTableSync001, TestSize.Level1) +{ + /** + * @tc.steps:step1. init data + * @tc.expected: step1. return OK. + */ + int dataCount = 120; + InsertCloudDBData(0, dataCount, 0, ASSETS_TABLE_NAME); + TrackerSchema trackerSchema = { + .tableName = ASSETS_TABLE_NAME, .extendColNames = {"int_field1"}, .trackerColNames = {"int_field1"}}; + g_delegate->SetTrackerTable(trackerSchema); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::OK); +} + +/** + * @tc.name: FillAssetId026 + * @tc.desc: Test if assetId is null when removedevicedata in FLAG_AND_DATA + * @tc.type: FUNC + * @tc.require: + * @tc.author: tankaisheng + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId026, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert assets and sync, check the local assetId. + * @tc.expected: step1. return OK. + */ + int localCount = 10; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); + + /** + * @tc.steps:step2. remove device data then check record. + * @tc.expected: step2. return OK. + */ + g_delegate->RemoveDeviceData("", FLAG_AND_DATA); + CheckLocaLAssets(ASSETS_TABLE_NAME, "", {}); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); + g_delegate->RemoveDeviceData("", CLEAR_SHARED_TABLE); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); +} } // namespace #endif // RELATIONAL_STORE diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp index af0442cd21834ec5ba9a72d06a66e41440f5be9b..2736b6bc95661b335851dd0c2a005d1a66310261 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp @@ -236,9 +236,9 @@ static void Expect2GetInfoByPrimaryKeyOrGidCall() HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockTest001, TestSize.Level1) { TaskId taskId = 1u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); @@ -288,10 +288,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockTest001, TestSize.Lev HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockTest002, TestSize.Level1) { TaskId taskId = 6u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); @@ -334,10 +334,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockTest002, TestSize.Lev HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest002, TestSize.Level1) { TaskId taskId = 1u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -367,10 +367,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest002, TestSiz HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest003, TestSize.Level1) { TaskId taskId = 1u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -425,10 +425,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest003, TestSiz HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest00302, TestSize.Level1) { TaskId taskId = 4u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -469,10 +469,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest00302, TestS HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest004, TestSize.Level1) { TaskId taskId = 1u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -514,10 +514,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest004, TestSiz HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest00402, TestSize.Level1) { TaskId taskId = 3u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -570,10 +570,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest00402, TestS HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest005, TestSize.Level1) { TaskId taskId = 1u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -602,10 +602,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest005, TestSiz HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockTest006, TestSize.Level1) { TaskId taskId = 1u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -720,14 +720,14 @@ static void ExpectGetInfoByPrimaryKeyOrGidCall() HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockTest007, TestSize.Level1) { TaskId taskId = 1u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly([](const QuerySyncObject &, const Timestamp &, bool, bool, int64_t &count) { count = 1; return E_OK; }); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_lock_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_lock_test.cpp index 5a900eccbed2450dbaa16816529ea5ad69298ba6..49ed8e24992e722ede9911d864e71cf7602dbd81 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_lock_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_lock_test.cpp @@ -77,6 +77,7 @@ std::shared_ptr g_virtualCloudDb; std::shared_ptr g_virtualAssetLoader; std::shared_ptr g_virtualCloudDataTranslate; SyncProcess g_syncProcess; +std::vector> g_allSyncProcess; std::condition_variable g_processCondition; std::mutex g_processMutex; IRelationalStore *g_store = nullptr; @@ -187,6 +188,7 @@ void DistributedDBCloudSyncerLockTest::Init() g_virtualCloudDb = make_shared(); g_virtualAssetLoader = make_shared(); g_syncProcess = {}; + g_allSyncProcess = {}; ASSERT_EQ(g_delegate->SetCloudDB(g_virtualCloudDb), DBStatus::OK); ASSERT_EQ(g_delegate->SetIAssetLoader(g_virtualAssetLoader), DBStatus::OK); DataBaseSchema dataBaseSchema; @@ -324,6 +326,7 @@ void DistributedDBCloudSyncerLockTest::CallSync(const CloudSyncOption &option, D bool finish = false; SyncProcess last; auto callback = [&last, &cv, &dataMutex, &finish](const std::map &process) { + g_allSyncProcess.push_back(process); for (const auto &item: process) { if (item.second.process == DistributedDB::FINISHED) { { @@ -461,7 +464,7 @@ void DistributedDBCloudSyncerLockTest::CheckUploadAbnormal(OpType opType, int64_ * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, RDBUnlockCloudSync001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, RDBUnlockCloudSync001, TestSize.Level1) { /** * @tc.steps:step1. init data and sync with none lock @@ -471,8 +474,13 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, RDBUnlockCloudSync001, TestSize.Level int localCount = 10; InsertLocalData(0, cloudCount, ASSETS_TABLE_NAME, true); InsertCloudDBData(0, localCount, 0, ASSETS_TABLE_NAME); + int queryIdx = 0; + g_virtualCloudDb->ForkQuery([&queryIdx](const std::string &, VBucket &) { + queryIdx++; + }); CloudSyncOption option = PrepareOption(Query::Select().FromTable({ ASSETS_TABLE_NAME }), LockAction::NONE); CallSync(option); + EXPECT_EQ(queryIdx, 1L); /** * @tc.steps:step2. insert or replace, check version @@ -486,6 +494,48 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, RDBUnlockCloudSync001, TestSize.Level reinterpret_cast(cloudCount), nullptr), SQLITE_OK); } +/** + * @tc.name: RDBUnlockCloudSync002 + * @tc.desc: Test sync with multi table + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerLockTest, RDBUnlockCloudSync002, TestSize.Level1) +{ + /** + * @tc.steps:step1. init data and sync with none lock + * @tc.expected: step1. return ok. + */ + std::string tableName = "tea"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "CREATE TABLE IF NOT EXISTS tea(" + COL_ID + " INTEGER PRIMARY KEY," + + COL_NAME + " TEXT ," + COL_ASSET + " ASSET," + COL_ASSETS + " ASSETS" + ");"), SQLITE_OK); + ASSERT_EQ(g_delegate->CreateDistributedTable(tableName, CLOUD_COOPERATION), DBStatus::OK); + DataBaseSchema dataBaseSchema; + GetCloudDbSchema(dataBaseSchema); + TableSchema teaSchema = {.name = tableName, .sharedTableName = tableName + "_shared", + .fields = CLOUD_FIELDS}; + dataBaseSchema.tables.push_back(teaSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + int cloudCount = 10; + InsertCloudDBData(0, cloudCount, 0, ASSETS_TABLE_NAME); + InsertCloudDBData(0, cloudCount, 0, tableName); + int queryIdx = 0; + g_virtualCloudDb->ForkQuery([&queryIdx](const std::string &, VBucket &) { + queryIdx++; + }); + + /** + * @tc.steps:step2. sync and check process count + * @tc.expected: step2. return ok. + */ + CloudSyncOption option = + PrepareOption(Query::Select().FromTable({ ASSETS_TABLE_NAME, tableName }), LockAction::NONE); + CallSync(option); + EXPECT_EQ(queryIdx, 2L); + EXPECT_EQ(g_allSyncProcess.size(), 4u); +} + /** * @tc.name: RDBLockSyncTest001 * @tc.desc: Test sync deleted data which status is LOCKING. @@ -527,7 +577,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, RDBLockSyncTest001, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync001, TestSize.Level1) { /** * @tc.steps:step1. init data and set hook before upload, update cloud data which gid is 1 @@ -563,7 +613,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync001, TestSize.Lev * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync002, TestSize.Level1) { TestConflictSync001(true); } @@ -575,7 +625,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync002, TestSize.Lev * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync003, TestSize.Level1) { TestConflictSync001(false); } @@ -587,7 +637,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync003, TestSize.Lev * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync004, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync004, TestSize.Level1) { /** * @tc.steps:step1. init data and sync @@ -687,7 +737,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest001, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest002, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -714,6 +764,12 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest002, TestSize.Level0) index++; }); CallSync(option); + /** + * @tc.steps:step3. sync again and check cursor + * @tc.expected: step3. return ok. + */ + index = 0; + CallSync(option); } /** @@ -723,7 +779,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest002, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest001, TestSize.Level1) { /** * @tc.steps:step1. init cloud assert {a, b1, b2} @@ -755,7 +811,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest001, TestSize. * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest002, TestSize.Level1) { /** * @tc.steps:step1. init cloud assert {a, b1, b2} and sync to local @@ -821,7 +877,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest002, TestSize. * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest003, TestSize.Level1) { /** * @tc.steps:step1. init cloud assert {a, b1, b2} and sync to local @@ -877,7 +933,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest003, TestSize. * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, RecordConflictTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, RecordConflictTest001, TestSize.Level1) { /** * @tc.steps:step1. init data and sync @@ -926,7 +982,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, RecordConflictTest001, TestSize.Level * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest003, TestSize.Level1) { /** * @tc.steps:step1. init cloud data and sync @@ -969,7 +1025,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest003, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest004, TestSize.Level1) { /** * @tc.steps:step1. init cloud data @@ -1009,7 +1065,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest004, TestSize.Level0) * @tc.require: * @tc.author: suyue */ -HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest006, TestSize.Level1) { RuntimeContext::GetInstance()->SetBatchDownloadAssets(true); /** @@ -1067,7 +1123,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest006, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync001, TestSize.Level1) { /** * @tc.steps:step1. insert local data and sync @@ -1099,7 +1155,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync001, TestSize.Level g_cloudStoreHook->SetSyncFinishHook([&callCount, this]() { LOGD("sync finish times:%d", ++callCount); if (callCount == 1) { // 1 is the normal sync - CheckUploadAbnormal(OpType::UPDATE, 1L); // 1 is expected count + CheckUploadAbnormal(OpType::UPDATE, 1L, true); // 1 is expected count } else { CheckUploadAbnormal(OpType::UPDATE, 1L, true); // 1 is expected count } @@ -1109,7 +1165,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync001, TestSize.Level { std::unique_lock lock(g_processMutex); bool result = g_processCondition.wait_for(lock, std::chrono::seconds(WAIT_TIME), - [&callCount]() { return callCount == 2; }); // 2 is sync times + [&callCount]() { return callCount == 1; }); // 2 is sync times ASSERT_EQ(result, true); } } @@ -1121,7 +1177,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync001, TestSize.Level * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync002, TestSize.Level1) { /** * @tc.steps:step1. insert a and sync @@ -1177,7 +1233,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync002, TestSize.Level * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync003, TestSize.Level1) { /** * @tc.steps:step1. insert local data and sync @@ -1234,7 +1290,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync003, TestSize.Level * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudSyncerLockTest, ReviseLocalModTimeTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, ReviseLocalModTimeTest001, TestSize.Level1) { /** * @tc.steps:step1. insert local data @@ -1272,7 +1328,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, ReviseLocalModTimeTest001, TestSize.L * @tc.require: * @tc.author: suyue */ -HWTEST_F(DistributedDBCloudSyncerLockTest, RemoveAssetsFailTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, RemoveAssetsFailTest001, TestSize.Level1) { /** * @tc.steps:step1. insert local and sync @@ -1459,7 +1515,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, UnLockSyncTest001, TestSize.Level1) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudSyncerLockTest, TaskIdTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, TaskIdTest001, TestSize.Level1) { /** * @tc.steps:step1. insert cloud and sync diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_progress_manager_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_progress_manager_test.cpp index 182583cd00a30cafa818eb9ef0e0fbd5ba9fb8b0..17de7d591f947a9ec805eac54c850babfaa232d9 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_progress_manager_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_progress_manager_test.cpp @@ -55,7 +55,7 @@ void DistributedDBCloudSyncerProgressManagerTest::TearDown(void) * @tc.name: SyncerMgrCheck001 * @tc.desc: Test case1 about Synchronization parameter * @tc.type: FUNC - * @tc.require: SR000HPUOS + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck001, TestSize.Level1) @@ -77,11 +77,11 @@ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck001, TestSiz EXPECT_CALL(*idb, HeartBeat()).WillRepeatedly(Return(OK)); EXPECT_CALL(*idb, Lock()).WillRepeatedly(Return(std::pair(OK, 10))); EXPECT_CALL(*idb, UnLock()).WillRepeatedly(Return(OK)); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData).WillRepeatedly(Return(E_OK)); @@ -115,7 +115,7 @@ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck001, TestSiz * @tc.name: SyncerMgrCheck002 * @tc.desc: Test case2 about Synchronization parameter * @tc.type: FUNC - * @tc.require: SR000HPUOS + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck002, TestSize.Level1) @@ -134,11 +134,11 @@ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck002, TestSiz EXPECT_CALL(*idb, HeartBeat()).WillRepeatedly(Return(OK)); EXPECT_CALL(*idb, Lock()).WillRepeatedly(Return(std::pair(OK, 10))); EXPECT_CALL(*idb, UnLock()).WillRepeatedly(Return(OK)); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData).WillRepeatedly(Return(E_OK)); @@ -173,7 +173,7 @@ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck002, TestSiz * @tc.name: SyncerMgrCheck003 * @tc.desc: Test case2 about Synchronization parameter * @tc.type: FUNC - * @tc.require: SR000HPUOS + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck003, TestSize.Level1) @@ -191,11 +191,11 @@ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck003, TestSiz EXPECT_CALL(*idb, HeartBeat()).WillRepeatedly(Return(OK)); EXPECT_CALL(*idb, Lock()).WillRepeatedly(Return(std::pair(OK, 10))); EXPECT_CALL(*idb, UnLock()).WillRepeatedly(Return(OK)); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData).WillRepeatedly(Return(E_OK)); @@ -222,7 +222,7 @@ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck003, TestSiz * @tc.desc: Test the number of queues * @tc.type: FUNC - * @tc.require: SR000HPUOS + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck004, TestSize.Level1) @@ -263,7 +263,7 @@ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck004, TestSiz * @tc.name: SyncerMgrCheck005 * @tc.desc: Test Single-threaded execution of tasks * @tc.type: FUNC - * @tc.require: SR000HPUOS + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck005, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_upload_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_upload_test.cpp index 5ca1769f310b66423b59b9868797b816bc2caee6..892c099b49a11afd93bc989967cf524bbfd233d4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_upload_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_upload_test.cpp @@ -43,12 +43,12 @@ const int COUNT = 1000; static void CommonExpectCall(MockICloudSyncStorageInterface *iCloud) { - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ReleaseCloudDataToken(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDataNext(_, _)).WillRepeatedly(Return(E_OK)); @@ -151,7 +151,7 @@ void DistributedDBCloudSyncerUploadTest::CheckUploadFinish(TestCloudSyncer &clou * @tc.name: UploadModeCheck001 * @tc.desc: Test different strategies of sync task call DoUpload() * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck001, TestSize.Level1) @@ -165,10 +165,10 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck001, TestSize.Level1 EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); @@ -210,7 +210,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck001, TestSize.Level1 * @tc.name: UploadModeCheck002 * @tc.desc: Test case1 about getting water mark * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck002, TestSize.Level1) @@ -222,10 +222,10 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck002, TestSize.Level1 cloudSyncer->SetMockICloudDB(idb); TaskId taskId = 2u; - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); @@ -247,7 +247,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck002, TestSize.Level1 * @tc.name: UploadModeCheck003 * @tc.desc: Test case2 about getting water mark * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck003, TestSize.Level1) @@ -258,10 +258,10 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck003, TestSize.Level1 std::shared_ptr idb = std::make_shared(); cloudSyncer->SetMockICloudDB(idb); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); @@ -284,7 +284,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck003, TestSize.Level1 * @tc.name: UploadModeCheck004 * @tc.desc: Test case1 about Getting upload count * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck004, TestSize.Level1) @@ -296,10 +296,10 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck004, TestSize.Level1 cloudSyncer->SetMockICloudDB(idb); cloudSyncer->InitCloudSyncer(3u, SYNC_MODE_CLOUD_FORCE_PUSH); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); // 1. Failed to get total data count @@ -319,7 +319,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck004, TestSize.Level1 * @tc.name: UploadModeCheck005 * @tc.desc: Test case2 about Getting upload count * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck005, TestSize.Level1) @@ -331,10 +331,10 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck005, TestSize.Level1 cloudSyncer->SetMockICloudDB(idb); cloudSyncer->InitCloudSyncer(3u, SYNC_MODE_CLOUD_FORCE_PUSH); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); @@ -369,7 +369,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck005, TestSize.Level1 * @tc.name: UploadModeCheck006 * @tc.desc: Test case1 about CloudSyncData * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck006, TestSize.Level1) @@ -384,12 +384,12 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck006, TestSize.Level1 EXPECT_CALL(*idb, BatchInsert(_, _, _)).WillRepeatedly(Return(OK)); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ReleaseCloudDataToken(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetAllUploadCount(_, _, _, _, _)) .WillRepeatedly([](const QuerySyncObject &, const std::vector &, bool, bool, int64_t & count) { @@ -425,7 +425,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck006, TestSize.Level1 * @tc.name: UploadModeCheck007 * @tc.desc: Test case2 about CloudSyncData * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck007, TestSize.Level1) @@ -476,7 +476,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck007, TestSize.Level1 return E_OK; }); int errCode = cloudSyncer->CallDoUpload(5u); - EXPECT_EQ(errCode, -E_INTERNAL_ERROR); + EXPECT_EQ(errCode, -E_CLOUD_ERROR); RuntimeContext::GetInstance()->StopTaskPool(); cloudSyncer->CallClose(); @@ -490,7 +490,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck007, TestSize.Level1 * @tc.name: UploadModeCheck008 * @tc.desc: Test case3 about CloudSyncData * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck008, TestSize.Level1) @@ -505,12 +505,12 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck008, TestSize.Level1 EXPECT_CALL(*idb, BatchInsert(_, _, _)).WillRepeatedly(Return(OK)); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ReleaseCloudDataToken(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetAllUploadCount(_, _, _, _, _)) .WillRepeatedly([](const QuerySyncObject &, const std::vector &, bool, bool, int64_t & count) { @@ -548,7 +548,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck008, TestSize.Level1 * @tc.name: UploadModeCheck009 * @tc.desc: Test case about CloudSyncData * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck009, TestSize.Level1) @@ -610,7 +610,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck009, TestSize.Level1 * @tc.name: UploadModeCheck017 * @tc.desc: Test case about CloudSyncData * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck017, TestSize.Level1) @@ -660,7 +660,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck017, TestSize.Level1 * @tc.name: UploadModeCheck010 * @tc.desc: Test case1 about batch api in upload * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck010, TestSize.Level1) @@ -683,7 +683,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck010, TestSize.Level1 cloudDataResult = uploadData; return E_OK; }); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetAllUploadCount(_, _, _, _, _)) @@ -691,8 +691,8 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck010, TestSize.Level1 count = 3000; return E_OK; }); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDataNext(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDbSchema(_)).WillRepeatedly(Return(E_OK)); @@ -717,7 +717,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck010, TestSize.Level1 * @tc.name: UploadModeCheck011 * @tc.desc: Test case2 about batch api in upload * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck011, TestSize.Level1) @@ -732,7 +732,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck011, TestSize.Level1 PrepareRecord(tmp, assets); cloudSyncer->InitCloudSyncer(6u, SYNC_MODE_CLOUD_FORCE_PUSH); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetAllUploadCount(_, _, _, _, _)) @@ -740,8 +740,8 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck011, TestSize.Level1 count = 3000; return E_OK; }); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDataNext(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDbSchema(_)).WillRepeatedly(Return(E_OK)); @@ -777,7 +777,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck011, TestSize.Level1 * @tc.name: UploadModeCheck012 * @tc.desc: Test case2 about batch api in upload * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck012, TestSize.Level1) @@ -789,7 +789,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck012, TestSize.Level1 cloudSyncer->SetMockICloudDB(idb); cloudSyncer->InitCloudSyncer(6u, SYNC_MODE_CLOUD_FORCE_PUSH); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetAllUploadCount(_, _, _, _, _)) @@ -797,8 +797,8 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck012, TestSize.Level1 count = 3000; return E_OK; }); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDataNext(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDbSchema(_)).WillRepeatedly(Return(E_OK)); @@ -842,7 +842,7 @@ void MockMethod014(MockICloudSyncStorageInterface *iCloud) * @tc.name: UploadModeCheck014 * @tc.desc: Test case2 about upload when batch api are partially successful. * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck014, TestSize.Level1) @@ -940,7 +940,7 @@ void SetFuncs015(MockICloudSyncStorageInterface *iCloud, std::shared_ptrCallDoUpload(5u, true); - EXPECT_EQ(errCode, -E_INTERNAL_ERROR); + EXPECT_EQ(errCode, -E_CLOUD_ERROR); RuntimeContext::GetInstance()->StopTaskPool(); EXPECT_EQ(callCount, 1); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_compound_primary_key_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_compound_primary_key_sync_test.cpp index 3a1922ecff4a9eb06e15ca0571f34fc432881f7d..39a1fcdf2f7fcd2894a8754750b0b42fc28c354e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_compound_primary_key_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_compound_primary_key_sync_test.cpp @@ -143,7 +143,7 @@ namespace { * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest001, TestSize.Level1) { /** * @tc.steps:step1. insert cloud data and merge @@ -167,7 +167,7 @@ HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest001, Te * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest002, TestSize.Level1) { /** * @tc.steps:step1. insert cloud data and merge @@ -200,7 +200,7 @@ HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest002, Te * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest003, TestSize.Level1) { /** * @tc.steps:step1. insert cloud data and merge @@ -233,7 +233,7 @@ HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest003, Te * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest004, TestSize.Level1) { /** * @tc.steps:step1. insert cloud asset and merge @@ -257,7 +257,7 @@ HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest004, Te * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest005, TestSize.Level1) { /** * @tc.steps:step1. insert cloud asset and merge @@ -290,7 +290,7 @@ HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest005, Te * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest006, TestSize.Level1) { /** * @tc.steps:step1. insert cloud asset and merge diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp index 182f342b98b9ca632715dda9aa1930641fde1353..5a678c6097ef0fc22725f4981c8b8c3884befeab 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp @@ -208,7 +208,7 @@ namespace { * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest001, TestSize.Level1) { /** * @tc.steps:step1. insert cloud data and merge @@ -232,7 +232,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest001, Tes * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest002, TestSize.Level1) { /** * @tc.steps:step1. insert cloud data and merge @@ -265,7 +265,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest002, Tes * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest003, TestSize.Level1) { /** * @tc.steps:step1. insert cloud data and merge @@ -298,7 +298,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest003, Tes * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest004, TestSize.Level1) { /** * @tc.steps:step1. insert cloud asset and merge @@ -322,7 +322,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest004, Tes * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest005, TestSize.Level1) { /** * @tc.steps:step1. insert cloud asset and merge @@ -355,7 +355,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest005, Tes * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest006, TestSize.Level1) { /** * @tc.steps:step1. insert cloud asset and merge @@ -388,7 +388,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest006, Tes * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest007, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest007, TestSize.Level1) { /** * @tc.steps:step1. insert cloud asset and merge @@ -422,7 +422,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest007, Tes * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest001, TestSize.Level1) { std::vector expectProperties = { g_onChangeProperties, g_unChangeProperties, g_onChangeProperties @@ -438,7 +438,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest002, TestSize.Level1) { std::vector expectProperties = { g_onChangeProperties, g_unChangeProperties, g_onChangeProperties @@ -454,7 +454,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest003, TestSize.Level1) { std::vector expectProperties = { g_unChangeProperties, g_unChangeProperties, g_unChangeProperties @@ -470,7 +470,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest004, TestSize.Level1) { std::vector expectProperties = { g_onChangeProperties, g_onChangeProperties, g_onChangeProperties @@ -486,7 +486,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest005, TestSize.Level1) { std::vector expectProperties = { g_unChangeProperties, g_unChangeProperties, g_unChangeProperties diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h index 0c41d70425b9367115f31810ad96ffcbf31ae0a4..3361f51813c97350dd87e511bfc2ea191ca94e57 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h @@ -27,9 +27,9 @@ public: MOCK_METHOD1(SetCloudDbSchema, int(const DataBaseSchema &)); MOCK_METHOD1(GetCloudDbSchema, int(std::shared_ptr &)); MOCK_METHOD2(GetCloudTableSchema, int(const TableName &, TableSchema &)); - MOCK_METHOD1(StartTransaction, int(TransactType)); - MOCK_METHOD0(Commit, int(void)); - MOCK_METHOD0(Rollback, int(void)); + MOCK_METHOD2(StartTransaction, int(TransactType, bool)); + MOCK_METHOD1(Commit, int(bool)); + MOCK_METHOD1(Rollback, int(bool)); MOCK_METHOD5(GetUploadCount, int(const QuerySyncObject &, const Timestamp &, bool, bool, int64_t &)); MOCK_METHOD5(GetAllUploadCount, int(const QuerySyncObject &, const std::vector &, bool, bool, int64_t &)); @@ -57,6 +57,7 @@ public: MOCK_METHOD3(GetLocalDataCount, int(const std::string &, int &, int &)); MOCK_METHOD0(GetDownloadAssetTable, std::pair>(void)); MOCK_METHOD2(GetDownloadAssetRecords, std::pair>(const std::string &, int64_t)); + MOCK_METHOD0(IsExistTableContainAssets, bool(void)); }; } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.cpp index cbcc3581a5072a5616cf919ba524a1f863ca9719..21d970dbbbcbd561e5a1e7e0588c3eb6cf5c5963 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.cpp @@ -126,4 +126,14 @@ void VirtualCloudSyncer::PauseCurrentTask() cloudTaskInfos_[currentContext_.currentTaskId].pause = true; LOGD("[CloudSyncer] Mark taskId %" PRIu64 " paused success", currentContext_.currentTaskId); } + +void VirtualCloudSyncer::TriggerAsyncTask() +{ + CloudSyncer::TriggerAsyncDownloadAssetsIfNeed(); +} + +void VirtualCloudSyncer::WaitTaskFinished() +{ + CloudSyncer::WaitCurTaskFinished(); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.h index 5ffb2c21b9ceaacb4baee1812b6dc2e7f97b0196..8b2479bde8e4b762adf40fc639ee4a9182ab3edd 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.h @@ -48,6 +48,10 @@ public: OpType &strategyOpResult); void PauseCurrentTask(); + + void TriggerAsyncTask(); + + void WaitTaskFinished(); private: std::function downloadFunc_; std::function downloadInNeedFunc_; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_ability_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_ability_sync_test.cpp index 7cc95252983355534a628d1d22ef687679cb50ce..4534c5de7d61f66abbe733e1f9a64b8b16162ab1 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_ability_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_ability_sync_test.cpp @@ -112,7 +112,7 @@ void DistributedDBAbilitySyncTest::TearDown(void) * @tc.name: RequestPacketTest001 * @tc.desc: Verify RequestPacketSerialization and RequestPacketDeSerialization function. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, RequestPacketTest001, TestSize.Level0) @@ -169,7 +169,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, RequestPacketTest001, TestSize.Level0) * @tc.name: RequestPacketTest002 * @tc.desc: Verify RequestPacketSerialization and RequestPacketDeSerialization function when version not support. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, RequestPacketTest002, TestSize.Level0) @@ -215,7 +215,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, RequestPacketTest002, TestSize.Level0) * @tc.name: RequestPacketTest003 * @tc.desc: Verify RequestPacketSerialization and RequestPacketDeSerialization function. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, RequestPacketTest003, TestSize.Level0) @@ -272,7 +272,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, RequestPacketTest003, TestSize.Level0) * @tc.name: RequestPacketTest004 * @tc.desc: Verify RequestPacketSerialization and RequestPacketDeSerialization function. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, RequestPacketTest004, TestSize.Level0) @@ -329,7 +329,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, RequestPacketTest004, TestSize.Level0) * @tc.name: AckPacketTest001 * @tc.desc: Verify AckPacketSerialization and AckPacketDeSerialization function. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, AckPacketTest001, TestSize.Level0) @@ -386,7 +386,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, AckPacketTest001, TestSize.Level0) * @tc.name: SyncStartTest001 * @tc.desc: Verify Ability sync SyncStart function. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, SyncStart001, TestSize.Level0) @@ -419,7 +419,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, SyncStart001, TestSize.Level0) * @tc.name: RequestReceiveTest001 * @tc.desc: Verify Ability RequestReceive callback. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, RequestReceiveTest001, TestSize.Level0) @@ -490,7 +490,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, RequestReceiveTest001, TestSize.Level0) * @tc.name: AckReceiveTest001 * @tc.desc: Verify Ability AckReceive callback. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, AckReceiveTest001, TestSize.Level0) @@ -534,9 +534,9 @@ HWTEST_F(DistributedDBAbilitySyncTest, AckReceiveTest001, TestSize.Level0) * @tc.expected: step5. AckRecv return ok GetRemoteSoftwareVersion is SOFTWARE_VERSION_CURRENT * IsSchemaCompatible true; */ - EXPECT_EQ(async.AckRecv(&msg1, context), E_OK); + EXPECT_EQ(async.AckRecv(&msg1, context), -E_SCHEMA_MISMATCH); EXPECT_TRUE(context->GetRemoteSoftwareVersion() == SOFTWARE_VERSION_CURRENT); - EXPECT_TRUE(context->GetTaskErrCode() != -E_SCHEMA_MISMATCH); + EXPECT_TRUE(context->GetTaskErrCode() == -E_SCHEMA_MISMATCH); /** * @tc.steps: step6. call RequestRecv, SetSchema "" @@ -544,7 +544,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, AckReceiveTest001, TestSize.Level0) */ packet1.SetSchema(""); msg1.SetCopiedObject(packet1); - EXPECT_EQ(async.AckRecv(&msg1, context), E_OK); + EXPECT_EQ(async.AckRecv(&msg1, context), -E_SCHEMA_MISMATCH); /** * @tc.steps: step7. call AckRecv, set inMsg sendCode -E_VERSION_NOT_SUPPORT @@ -561,7 +561,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, AckReceiveTest001, TestSize.Level0) * @tc.name: AckReceiveTest002 * @tc.desc: Verify Ability RDB AckReceive callback. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, AckReceiveTest002, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_anti_dos_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_anti_dos_sync_test.cpp index d4c4985cf2e5ce85238268bdbe5319359608673d..97a459c93c7d700e2e6150341952208f4d197364 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_anti_dos_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_anti_dos_sync_test.cpp @@ -158,7 +158,7 @@ void DistributeddbAntiDosSyncTest::TearDown(void) * @tc.desc: Whether function run normally when the amount of message is lower than the maximum of threads * and the whole length of message is lower than the maximum size of queue. * @tc.type: FUNC - * @tc.require: AR000D08KU + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributeddbAntiDosSyncTest, AntiDosAttackSync001, TestSize.Level3) @@ -204,7 +204,7 @@ HWTEST_F(DistributeddbAntiDosSyncTest, AntiDosAttackSync001, TestSize.Level3) * @tc.desc: Check if the enqueued and dequeue are normal when the whole length of messages is lower than * maximum size of queue. * @tc.type: FUNC - * @tc.require: AR000D08KU + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributeddbAntiDosSyncTest, AntiDosAttackSync002, TestSize.Level3) @@ -269,7 +269,7 @@ HWTEST_F(DistributeddbAntiDosSyncTest, AntiDosAttackSync002, TestSize.Level3) * @tc.name: Anti Dos attack Sync 003 * @tc.desc: Whether message enter and drop when all threads hang. * @tc.type: FUNC - * @tc.require: AR000D08KU + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributeddbAntiDosSyncTest, AntiDosAttackSync003, TestSize.Level3) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_communicator_proxy_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_communicator_proxy_test.cpp index 1f8149d9c2a5eea2b455fddd78007e88e1bf9d9b..8e53b94fdad300765f93fa3762f5f579d3e5c924 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_communicator_proxy_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_communicator_proxy_test.cpp @@ -135,7 +135,7 @@ void DistributedDBCommunicatorProxyTest::TearDown(void) * @tc.name: Interface set equal 001 * @tc.desc: Test set equal identifier from interface. * @tc.type: FUNC - * @tc.require: AR000F4GVG + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBCommunicatorProxyTest, InterfaceSetEqualId001, TestSize.Level1) @@ -167,7 +167,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, InterfaceSetEqualId001, TestSize.Le * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCommunicatorProxyTest, InterfaceSetEqualId002, TestSize.Level0) +HWTEST_F(DistributedDBCommunicatorProxyTest, InterfaceSetEqualId002, TestSize.Level1) { /** * @tc.steps: step1. Get DB of user1 @@ -209,7 +209,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, InterfaceSetEqualId002, TestSize.Le * @tc.name: Register callback 001 * @tc.desc: Test register callback from CommunicatorProxy. * @tc.type: FUNC - * @tc.require: AR000F4GVG + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBCommunicatorProxyTest, RegCallBack001, TestSize.Level1) @@ -248,7 +248,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, RegCallBack001, TestSize.Level1) * @tc.name: Activate 001 * @tc.desc: Test Activate called from CommunicatorProxy. * @tc.type: FUNC - * @tc.require: AR000F4GVG + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBCommunicatorProxyTest, Activate001, TestSize.Level1) @@ -266,7 +266,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, Activate001, TestSize.Level1) * @tc.name: Get mtu 001 * @tc.desc: Test mtu called from CommunicatorProxy. * @tc.type: FUNC - * @tc.require: AR000F4GVG + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBCommunicatorProxyTest, GetMtu001, TestSize.Level1) @@ -290,7 +290,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, GetMtu001, TestSize.Level1) * @tc.name: Get local identify 001 * @tc.desc: Test Get local identify from CommunicatorProxy. * @tc.type: FUNC - * @tc.require: AR000F4GVG + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBCommunicatorProxyTest, GetLocalIdentity001, TestSize.Level1) @@ -309,7 +309,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, GetLocalIdentity001, TestSize.Level * @tc.name: Get remote version 001 * @tc.desc: Test Get remote version from CommunicatorProxy. * @tc.type: FUNC - * @tc.require: AR000F4GVG + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBCommunicatorProxyTest, GetRemoteVersion001, TestSize.Level1) @@ -346,7 +346,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, GetRemoteVersion001, TestSize.Level * @tc.name: Send message 001 * @tc.desc: Test Send message from CommunicatorProxy. * @tc.type: FUNC - * @tc.require: AR000F4GVG + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBCommunicatorProxyTest, SendMessage001, TestSize.Level1) @@ -355,7 +355,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, SendMessage001, TestSize.Level1) * @tc.steps: step1. Call SendMessage from CommProxy with param DEVICE_B. * @tc.expected: step1. MainComm's SendMessage willed called and return E_OK. */ - SendConfig conf = {true, false, 0}; + SendConfig conf = {true, false, true, 0}; EXPECT_CALL(mainComm_, SendMessage(DEVICE_B, _, _, _)).WillOnce(Return(E_OK)); EXPECT_EQ(commProxy_->SendMessage(DEVICE_B, nullptr, conf, nullptr), E_OK); @@ -371,7 +371,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, SendMessage001, TestSize.Level1) * @tc.name: Get timeout time 001 * @tc.desc: Test get timeout called from CommunicatorProxy. * @tc.type: FUNC - * @tc.require: AR000F4GVG + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBCommunicatorProxyTest, GetTimeout001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_meta_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_meta_data_test.cpp index e8fd625cf7061f8b93b67f1388f16d26ab27c405..f6da76587ab11bd46ab10a568aa014900de5dfc2 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_meta_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_meta_data_test.cpp @@ -28,6 +28,8 @@ using namespace DistributedDBUnitTest; namespace { constexpr const char *DEVICE_A = "deviceA"; constexpr const char *DEVICE_B = "deviceB"; +constexpr const char *USER_A = "userA"; +constexpr const char *USER_B = "userB"; class DistributedDBMetaDataTest : public testing::Test { public: static void SetUpTestCase(); @@ -104,43 +106,43 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest001, TestSize.Level0) * @tc.steps: step1. Check ability sync finish before set mark. * @tc.expected: step1. Default all ability sync finish is false. */ - EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A)); - EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_B)); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, "")); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_B, "")); /** * @tc.steps: step2. Set A ability sync finish. * @tc.expected: step2. A is finish B is not finish. */ - EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_A, true), E_OK); - EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A)); - EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_B)); + EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_A, "", true), E_OK); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, "")); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_B, "")); /** * @tc.steps: step3. Set B ability sync finish. * @tc.expected: step3. A and B is finish. */ - EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_B, true), E_OK); - EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A)); - EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_B)); + EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_B, "", true), E_OK); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, "")); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_B, "")); /** * @tc.steps: step4. Set A ability sync not finish. * @tc.expected: step4. A is not finish B is finish. */ - EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_A, false), E_OK); - EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A)); - EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_B)); + EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_A, "", false), E_OK); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, "")); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_B, "")); /** * @tc.steps: step5. Clear all time sync finish. * @tc.expected: step5. A and B is finish. */ EXPECT_EQ(metadata_->ClearAllTimeSyncFinishMark(), E_OK); - EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A)); - EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_B)); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, "")); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_B, "")); /** * @tc.steps: step6. Clear all ability sync finish. * @tc.expected: step6. A and B is not finish. */ EXPECT_EQ(metadata_->ClearAllAbilitySyncFinishMark(), E_OK); - EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A)); - EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_B)); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, "")); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_B, "")); } /** @@ -156,36 +158,36 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest002, TestSize.Level0) * @tc.steps: step1. Check time sync finish before set mark. * @tc.expected: step1. Default all time sync finish is false. */ - EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A)); - EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_B)); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, "")); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_B, "")); /** * @tc.steps: step2. Set A time sync finish. * @tc.expected: step2. A is finish B is not finish. */ - EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_A, true), E_OK); - EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_A)); - EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_B)); + EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_A, "", true), E_OK); + EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_A, "")); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_B, "")); /** * @tc.steps: step3. Set B time sync finish. * @tc.expected: step3. A and B is finish. */ - EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_B, true), E_OK); - EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_A)); - EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_B)); + EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_B, "", true), E_OK); + EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_A, "")); + EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_B, "")); /** * @tc.steps: step4. Set A time sync not finish. * @tc.expected: step4. A is not finish B is finish. */ - EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_A, false), E_OK); - EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A)); - EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_B)); + EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_A, "", false), E_OK); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, "")); + EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_B, "")); /** * @tc.steps: step5. Clear all time sync finish. * @tc.expected: step5. A and B is not finish. */ EXPECT_EQ(metadata_->ClearAllTimeSyncFinishMark(), E_OK); - EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A)); - EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_B)); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, "")); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_B, "")); } /** @@ -201,22 +203,22 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest003, TestSize.Level0) * @tc.steps: step1. Check remote schema version before set version. * @tc.expected: step1. Default all version is zero. */ - EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A), 0u); - EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_B), 0u); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, ""), 0u); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_B, ""), 0u); /** * @tc.steps: step2. Set A schema version. * @tc.expected: step2. A is finish B is not finish. */ - EXPECT_EQ(metadata_->SetRemoteSchemaVersion(DEVICE_A, SOFTWARE_VERSION_CURRENT), E_OK); - EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A), SOFTWARE_VERSION_CURRENT); - EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_B), 0u); + EXPECT_EQ(metadata_->SetRemoteSchemaVersion(DEVICE_A, "", SOFTWARE_VERSION_CURRENT), E_OK); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, ""), SOFTWARE_VERSION_CURRENT); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_B, ""), 0u); /** * @tc.steps: step3. Clear all ability sync finish. * @tc.expected: step3. A and B version is zero. */ EXPECT_EQ(metadata_->ClearAllAbilitySyncFinishMark(), E_OK); - EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A), 0u); - EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_B), 0u); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, ""), 0u); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_B, ""), 0u); } /** @@ -232,23 +234,23 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest004, TestSize.Level0) * @tc.steps: step1. Check remote schema version before set version. * @tc.expected: step1. Default all version is zero. */ - EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A), 0u); - EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_B), 0u); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, ""), 0u); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_B, ""), 0u); /** * @tc.steps: step2. Set A schema version. * @tc.expected: step2. A is finish B is not finish. */ const int64_t offset = 100u; - EXPECT_EQ(metadata_->SetSystemTimeOffset(DEVICE_A, offset), E_OK); - EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A), offset); - EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_B), 0u); + EXPECT_EQ(metadata_->SetSystemTimeOffset(DEVICE_A, "", offset), E_OK); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, ""), offset); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_B, ""), 0u); /** * @tc.steps: step3. Clear all time sync finish. * @tc.expected: step3. A and B system time offset is zero. */ EXPECT_EQ(metadata_->ClearAllTimeSyncFinishMark(), E_OK); - EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A), 0u); - EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_B), 0u); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, ""), 0u); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_B, ""), 0u); } /** @@ -290,7 +292,8 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest006, TestSize.Level0) * @tc.steps: step1. Set storage ability sync finish. * @tc.expected: step1. A is finish. */ - std::string hashDeviceId = DBConstant::DEVICEID_PREFIX_KEY + DBCommon::TransferHashString(DEVICE_A); + std::string hashDeviceId = DBConstant::DEVICEID_PREFIX_KEY + DBCommon::TransferHashString(DEVICE_A) + + DBConstant::USERID_PREFIX_KEY + ""; MetaDataValue metaDataValue; GetMetaDataValue(hashDeviceId, metaDataValue); EXPECT_EQ(metaDataValue.syncMark & static_cast(SyncMark::SYNC_MARK_ABILITY_SYNC), 0u); @@ -300,13 +303,13 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest006, TestSize.Level0) * @tc.steps: step2. Check ability sync finish by meta. * @tc.expected: step2. A is finish because meta data is loaded from db. */ - EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A)); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, "")); /** * @tc.steps: step3. Erase water mark and check again. * @tc.expected: step3. A is finish because meta data is loaded from db. */ EXPECT_EQ(metadata_->EraseDeviceWaterMark(DEVICE_A, true), E_OK); - EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A)); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, "")); } /** @@ -323,7 +326,7 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest007, TestSize.Level0) * @tc.expected: step1. B is change because of time change. */ RuntimeContext::GetInstance()->SetTimeChanged(true); - EXPECT_TRUE(metadata_->IsTimeChange(DEVICE_B)); + EXPECT_TRUE(metadata_->IsTimeChange(DEVICE_B, "")); RuntimeContext::GetInstance()->SetTimeChanged(false); RuntimeContext::GetInstance()->StopTimeTickMonitorIfNeed(); } @@ -376,9 +379,512 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest009, TestSize.Level0) * @tc.expected: step1. B is change because of time change. */ RuntimeContext::GetInstance()->SetTimeChanged(true); - EXPECT_EQ(metadata_->SetDbCreateTime(DEVICE_B, 10u, true), E_OK); - EXPECT_TRUE(metadata_->IsTimeChange(DEVICE_B)); + EXPECT_EQ(metadata_->SetDbCreateTime(DEVICE_B, "", 10u, true), E_OK); + EXPECT_TRUE(metadata_->IsTimeChange(DEVICE_B, "")); RuntimeContext::GetInstance()->SetTimeChanged(false); RuntimeContext::GetInstance()->StopTimeTickMonitorIfNeed(); } -} \ No newline at end of file + +/** + * @tc.name: MetadataTest010 + * @tc.desc: Test metadata set and get ability sync mark. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest010, TestSize.Level0) +{ + /** + * @tc.steps: step1. Check ability sync finish before set mark. + * @tc.expected: step1. Default all ability sync finish is false. + */ + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step2. Set user A ability sync finish. + * @tc.expected: step2. user A is finish user B is not finish. + */ + EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_A, USER_A, true), E_OK); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step3. Set user B ability sync finish. + * @tc.expected: step3. user A and user B is finish. + */ + EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_A, USER_B, true), E_OK); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step4. Set user A ability sync not finish. + * @tc.expected: step4. user A is not finish user B is finish. + */ + EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_A, USER_A, false), E_OK); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step5. Clear all time sync finish. + * @tc.expected: step5. user A and user B unchanged. + */ + EXPECT_EQ(metadata_->ClearAllTimeSyncFinishMark(), E_OK); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step6. Clear all ability sync finish. + * @tc.expected: step6. user A and user B is not finish. + */ + EXPECT_EQ(metadata_->ClearAllAbilitySyncFinishMark(), E_OK); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); +} + +/** + * @tc.name: MetadataTest011 + * @tc.desc: Test metadata set and get time sync mark. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest011, TestSize.Level0) +{ + /** + * @tc.steps: step1. Check time sync finish before set mark. + * @tc.expected: step1. Default all time sync finish is false. + */ + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_A)); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step2. Set user A time sync finish. + * @tc.expected: step2. user A is finish user B is not finish. + */ + EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_A, USER_A, true), E_OK); + EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_A)); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step3. Set user B time sync finish. + * @tc.expected: step3. user A and user B is finish. + */ + EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_A, USER_B, true), E_OK); + EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_A)); + EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step4. Set user A time sync not finish. + * @tc.expected: step4. user A is not finish user B is finish. + */ + EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_A, USER_A, false), E_OK); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_A)); + EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step5. Clear all time sync finish. + * @tc.expected: step5. user A and user B is not finish. + */ + EXPECT_EQ(metadata_->ClearAllTimeSyncFinishMark(), E_OK); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_A)); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_B)); +} + +/** + * @tc.name: MetadataTest012 + * @tc.desc: Test metadata set remote schema version. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest012, TestSize.Level0) +{ + /** + * @tc.steps: step1. Check remote schema version before set version. + * @tc.expected: step1. Default all version is zero. + */ + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, USER_A), 0u); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, USER_B), 0u); + /** + * @tc.steps: step2. Set user A schema version. + * @tc.expected: step2. user A is finish user B is not finish. + */ + EXPECT_EQ(metadata_->SetRemoteSchemaVersion(DEVICE_A, USER_A, SOFTWARE_VERSION_CURRENT), E_OK); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, USER_A), SOFTWARE_VERSION_CURRENT); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, USER_B), 0u); + /** + * @tc.steps: step3. Clear all ability sync finish. + * @tc.expected: step3. user A and user B version is zero. + */ + EXPECT_EQ(metadata_->ClearAllAbilitySyncFinishMark(), E_OK); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, USER_A), 0u); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, USER_B), 0u); +} + +/** + * @tc.name: MetadataTest013 + * @tc.desc: Test metadata set remote system time off set. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest013, TestSize.Level0) +{ + /** + * @tc.steps: step1. Check remote schema version before set version. + * @tc.expected: step1. Default all version is zero. + */ + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, USER_A), 0u); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, USER_B), 0u); + /** + * @tc.steps: step2. Set user A schema version. + * @tc.expected: step2. user A is finish user B is not finish. + */ + const int64_t offset = 100u; + EXPECT_EQ(metadata_->SetSystemTimeOffset(DEVICE_A, USER_A, offset), E_OK); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, USER_A), offset); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, USER_B), 0u); + /** + * @tc.steps: step3. Clear all time sync finish. + * @tc.expected: step3. user A and user B system time offset is zero. + */ + EXPECT_EQ(metadata_->ClearAllTimeSyncFinishMark(), E_OK); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, USER_A), 0u); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, USER_B), 0u); +} + +/** + * @tc.name: MetadataTest014 + * @tc.desc: Test metadata remove device data with reload. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest014, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set storage ability sync finish. + * @tc.expected: step1. user A and B finish. + */ + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); + + /** + * @tc.steps: step2. Check ability sync finish by meta. + * @tc.expected: step2. user A and B is finish because meta data is loaded from db. + */ + std::string hashDeviceIdA = DBConstant::DEVICEID_PREFIX_KEY + DBCommon::TransferHashString(DEVICE_A) + + DBConstant::USERID_PREFIX_KEY + USER_A; + MetaDataValue metaDataValueA; + GetMetaDataValue(hashDeviceIdA, metaDataValueA); + EXPECT_EQ(metaDataValueA.syncMark & static_cast(SyncMark::SYNC_MARK_ABILITY_SYNC), 0u); + metaDataValueA.syncMark = static_cast(SyncMark::SYNC_MARK_ABILITY_SYNC); + PutMetaDataValue(hashDeviceIdA, metaDataValueA); + + std::string hashDeviceIdB = DBConstant::DEVICEID_PREFIX_KEY + DBCommon::TransferHashString(DEVICE_A) + + DBConstant::USERID_PREFIX_KEY + USER_B; + MetaDataValue metaDataValueB; + GetMetaDataValue(hashDeviceIdB, metaDataValueB); + EXPECT_EQ(metaDataValueB.syncMark & static_cast(SyncMark::SYNC_MARK_ABILITY_SYNC), 0u); + metaDataValueB.syncMark = static_cast(SyncMark::SYNC_MARK_ABILITY_SYNC); + PutMetaDataValue(hashDeviceIdB, metaDataValueB); + + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); + + /** + * @tc.steps: step3. Erase water mark and check again. + * @tc.expected: step3. user A and B is finish because meta data is loaded from db. + */ + EXPECT_EQ(metadata_->EraseDeviceWaterMark(DEVICE_A, true), E_OK); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); +} + +/** + * @tc.name: MetadataTest015 + * @tc.desc: Test metadata init with time change if need. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest015, TestSize.Level0) +{ + /** + * @tc.steps: step1. Check time sync finish by meta. + * @tc.expected: step1. user A and B is change because of time change. + */ + RuntimeContext::GetInstance()->SetTimeChanged(true); + EXPECT_TRUE(metadata_->IsTimeChange(DEVICE_B, USER_A)); + EXPECT_TRUE(metadata_->IsTimeChange(DEVICE_B, USER_B)); + RuntimeContext::GetInstance()->SetTimeChanged(false); + RuntimeContext::GetInstance()->StopTimeTickMonitorIfNeed(); +} + +/** + * @tc.name: MetadataTest016 + * @tc.desc: Test metaData init correctly + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest016, TestSize.Level1) +{ + /** + * @tc.steps: step1. init meta data + * @tc.expected: step1. E_OK + */ + Metadata meta; + VirtualSingleVerSyncDBInterface storage; + WaterMark setWaterMark = 1; + ASSERT_EQ(meta.Initialize(&storage), E_OK); + + /** + * @tc.steps: step2. meta save and get waterMark + * @tc.expected: step2. expect get the same waterMark + */ + EXPECT_EQ(meta.SaveLocalWaterMark(DEVICE_A, USER_A, setWaterMark), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark(DEVICE_A, USER_B, setWaterMark), E_OK); + WaterMark getWaterMark = 0; + meta.GetLocalWaterMark(DEVICE_A, USER_A, getWaterMark); + EXPECT_EQ(getWaterMark, setWaterMark); + meta.GetLocalWaterMark(DEVICE_A, USER_B, getWaterMark); + EXPECT_EQ(getWaterMark, setWaterMark); + + /** + * @tc.steps: step3. init again + * @tc.expected: step3. E_OK + */ + Metadata anotherMeta; + ASSERT_EQ(anotherMeta.Initialize(&storage), E_OK); + + /** + * @tc.steps: step4. get waterMark again + * @tc.expected: step4. expect get the same waterMark + */ + anotherMeta.GetLocalWaterMark(DEVICE_A, USER_A, getWaterMark); + EXPECT_EQ(getWaterMark, setWaterMark); + anotherMeta.GetLocalWaterMark(DEVICE_A, USER_B, getWaterMark); + EXPECT_EQ(getWaterMark, setWaterMark); +} + +/** + * @tc.name: MetadataTest017 + * @tc.desc: Test metaData save and get queryWaterMark. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest017, TestSize.Level1) +{ + /** + * @tc.steps: step1. save receive and send watermark + * @tc.expected: step1. E_OK + */ + WaterMark w1 = 1; + EXPECT_EQ(metadata_->SetRecvQueryWaterMark("Q1", DEVICE_A, USER_A, w1), E_OK); + EXPECT_EQ(metadata_->SetSendQueryWaterMark("Q1", DEVICE_A, USER_A, w1), E_OK); + WaterMark w2 = 2; + EXPECT_EQ(metadata_->SetRecvQueryWaterMark("Q1", DEVICE_A, USER_B, w2), E_OK); + EXPECT_EQ(metadata_->SetSendQueryWaterMark("Q1", DEVICE_A, USER_B, w2), E_OK); + /** + * @tc.steps: step2. get receive and send watermark + * @tc.expected: step2. E_OK and get the latest value + */ + WaterMark w = 0; + EXPECT_EQ(metadata_->GetRecvQueryWaterMark("Q1", DEVICE_A, USER_A, w), E_OK); + EXPECT_EQ(w1, w); + EXPECT_EQ(metadata_->GetSendQueryWaterMark("Q1", DEVICE_A, USER_A, w), E_OK); + EXPECT_EQ(w1, w); + EXPECT_EQ(metadata_->GetRecvQueryWaterMark("Q1", DEVICE_A, USER_B, w), E_OK); + EXPECT_EQ(w2, w); + EXPECT_EQ(metadata_->GetSendQueryWaterMark("Q1", DEVICE_A, USER_B, w), E_OK); + EXPECT_EQ(w2, w); + /** + * @tc.steps: step3. set peer and local watermark + * @tc.expected: step3. E_OK + */ + WaterMark w3 = 3; + EXPECT_EQ(metadata_->SaveLocalWaterMark(DEVICE_A, USER_A, w3), E_OK); + EXPECT_EQ(metadata_->SavePeerWaterMark(DEVICE_A, USER_A, w3, true), E_OK); + WaterMark w4 = 4; + EXPECT_EQ(metadata_->SaveLocalWaterMark(DEVICE_A, USER_B, w4), E_OK); + EXPECT_EQ(metadata_->SavePeerWaterMark(DEVICE_A, USER_B, w4, true), E_OK); + /** + * @tc.steps: step4. get receive and send watermark + * @tc.expected: step4. E_OK and get the w1 + */ + EXPECT_EQ(metadata_->GetRecvQueryWaterMark("Q1", DEVICE_A, USER_A, w), E_OK); + EXPECT_EQ(w3, w); + EXPECT_EQ(metadata_->GetSendQueryWaterMark("Q1", DEVICE_A, USER_A, w), E_OK); + EXPECT_EQ(w3, w); + EXPECT_EQ(metadata_->GetRecvQueryWaterMark("Q1", DEVICE_A, USER_B, w), E_OK); + EXPECT_EQ(w4, w); + EXPECT_EQ(metadata_->GetSendQueryWaterMark("Q1", DEVICE_A, USER_B, w), E_OK); + EXPECT_EQ(w4, w); + /** + * @tc.steps: step5. set peer and local watermark + * @tc.expected: step5. E_OK + */ + WaterMark w5 = 5; + EXPECT_EQ(metadata_->SaveLocalWaterMark(DEVICE_B, USER_A, w5), E_OK); + EXPECT_EQ(metadata_->SavePeerWaterMark(DEVICE_B, USER_A, w5, true), E_OK); + WaterMark w6 = 6; + EXPECT_EQ(metadata_->SaveLocalWaterMark(DEVICE_B, USER_B, w6), E_OK); + EXPECT_EQ(metadata_->SavePeerWaterMark(DEVICE_B, USER_B, w6, true), E_OK); + /** + * @tc.steps: step6. get receive and send watermark + * @tc.expected: step6. E_OK and get the w3 + */ + EXPECT_EQ(metadata_->GetRecvQueryWaterMark("Q2", DEVICE_B, USER_A, w), E_OK); + EXPECT_EQ(w5, w); + EXPECT_EQ(metadata_->GetSendQueryWaterMark("Q2", DEVICE_B, USER_A, w), E_OK); + EXPECT_EQ(w5, w); + EXPECT_EQ(metadata_->GetRecvQueryWaterMark("Q2", DEVICE_B, USER_B, w), E_OK); + EXPECT_EQ(w6, w); + EXPECT_EQ(metadata_->GetSendQueryWaterMark("Q2", DEVICE_B, USER_B, w), E_OK); + EXPECT_EQ(w6, w); + /** + * @tc.steps: step7. get not exit receive and send watermark + * @tc.expected: step7. E_OK and get the 0 + */ + EXPECT_EQ(metadata_->GetRecvQueryWaterMark("Q3", "D3", "U3", w), E_OK); + EXPECT_EQ(w, 0u); + EXPECT_EQ(metadata_->GetSendQueryWaterMark("Q3", "D3", "U3", w), E_OK); + EXPECT_EQ(w, 0u); +} + +/** + * @tc.name: MetadataTest018 + * @tc.desc: Test metaData get and set dbCreateTime. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest018, TestSize.Level1) +{ + /** + * @tc.steps: step1. set dbCreateTime + * @tc.expected: step1. E_OK + */ + EXPECT_EQ(metadata_->SetDbCreateTime(DEVICE_A, USER_A, 10u, true), E_OK); + EXPECT_EQ(metadata_->SetDbCreateTime(DEVICE_A, USER_B, 20u, true), E_OK); + /** + * @tc.steps: step2. check dbCreateTime + * @tc.expected: step2. E_OK + */ + uint64_t curDbCreatTime = 0; + metadata_->GetDbCreateTime(DEVICE_A, USER_A, curDbCreatTime); + EXPECT_EQ(curDbCreatTime, 10u); + metadata_->GetDbCreateTime(DEVICE_A, USER_B, curDbCreatTime); + EXPECT_EQ(curDbCreatTime, 20u); + /** + * @tc.steps: step3. user A change dbCreateTime and check + * @tc.expected: step3. E_OK + */ + EXPECT_EQ(metadata_->SetDbCreateTime(DEVICE_A, USER_A, 30u, true), E_OK); + uint64_t clearDeviceDataMark = INT_MAX; + metadata_->GetRemoveDataMark(DEVICE_A, USER_A, clearDeviceDataMark); + EXPECT_EQ(clearDeviceDataMark, 1u); + EXPECT_EQ(metadata_->ResetMetaDataAfterRemoveData(DEVICE_A, USER_A), E_OK); + metadata_->GetRemoveDataMark(DEVICE_A, USER_A, clearDeviceDataMark); + EXPECT_EQ(clearDeviceDataMark, 0u); + metadata_->GetDbCreateTime(DEVICE_A, USER_A, curDbCreatTime); + EXPECT_EQ(curDbCreatTime, 30u); + + /** + * @tc.steps: step4. user B unchanged dbCreateTime and check + * @tc.expected: step4. E_OK + */ + metadata_->GetRemoveDataMark(DEVICE_A, USER_B, clearDeviceDataMark); + EXPECT_EQ(clearDeviceDataMark, 0u); + metadata_->GetDbCreateTime(DEVICE_A, USER_B, curDbCreatTime); + EXPECT_EQ(curDbCreatTime, 20u); +} + +/** + * @tc.name: MetadataTest019 + * @tc.desc: Test metaData save and get deleteWaterMark. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest019, TestSize.Level1) +{ + /** + * @tc.steps: step1. save receive and send watermark + * @tc.expected: step1. E_OK + */ + WaterMark w1 = 1; + EXPECT_EQ(metadata_->SetRecvDeleteSyncWaterMark(DEVICE_A, USER_A, w1), E_OK); + EXPECT_EQ(metadata_->SetSendDeleteSyncWaterMark(DEVICE_A, USER_A, w1), E_OK); + WaterMark w2 = 2; + EXPECT_EQ(metadata_->SetRecvDeleteSyncWaterMark(DEVICE_A, USER_B, w2), E_OK); + EXPECT_EQ(metadata_->SetSendDeleteSyncWaterMark(DEVICE_A, USER_B, w2), E_OK); + + /** + * @tc.steps: step2. get receive and send watermark + * @tc.expected: step2. E_OK and get the latest value + */ + WaterMark w = 0; + EXPECT_EQ(metadata_->GetRecvDeleteSyncWaterMark(DEVICE_A, USER_A, w), E_OK); + EXPECT_EQ(w1, w); + EXPECT_EQ(metadata_->GetSendDeleteSyncWaterMark(DEVICE_A, USER_A, w), E_OK); + EXPECT_EQ(w1, w); + EXPECT_EQ(metadata_->GetRecvDeleteSyncWaterMark(DEVICE_A, USER_B, w), E_OK); + EXPECT_EQ(w2, w); + EXPECT_EQ(metadata_->GetSendDeleteSyncWaterMark(DEVICE_A, USER_B, w), E_OK); + EXPECT_EQ(w2, w); + + /** + * @tc.steps: step3. set peer and local watermark + * @tc.expected: step3. E_OK + */ + WaterMark w3 = 3; + WaterMark w4 = 4; + EXPECT_EQ(metadata_->SaveLocalWaterMark(DEVICE_A, USER_A, w3), E_OK); + EXPECT_EQ(metadata_->SavePeerWaterMark(DEVICE_A, USER_A, w4, true), E_OK); + WaterMark w5 = 5; + WaterMark w6 = 6; + EXPECT_EQ(metadata_->SaveLocalWaterMark(DEVICE_A, USER_B, w5), E_OK); + EXPECT_EQ(metadata_->SavePeerWaterMark(DEVICE_A, USER_B, w6, true), E_OK); + + /** + * @tc.steps: step4. get receive and send watermark + * @tc.expected: step4. E_OK and get the w1 + */ + EXPECT_EQ(metadata_->GetSendDeleteSyncWaterMark(DEVICE_A, USER_A, w), E_OK); + EXPECT_EQ(w3, w); + EXPECT_EQ(metadata_->GetRecvDeleteSyncWaterMark(DEVICE_A, USER_A, w), E_OK); + EXPECT_EQ(w4, w); + EXPECT_EQ(metadata_->GetSendDeleteSyncWaterMark(DEVICE_A, USER_B, w), E_OK); + EXPECT_EQ(w5, w); + EXPECT_EQ(metadata_->GetRecvDeleteSyncWaterMark(DEVICE_A, USER_B, w), E_OK); + EXPECT_EQ(w6, w); + + /** + * @tc.steps: step5. set peer and local watermark + * @tc.expected: step5. E_OK + */ + WaterMark w7 = 7; + EXPECT_EQ(metadata_->SaveLocalWaterMark(DEVICE_B, USER_A, w7), E_OK); + EXPECT_EQ(metadata_->SavePeerWaterMark(DEVICE_B, USER_A, w7, true), E_OK); + WaterMark w8 = 8; + EXPECT_EQ(metadata_->SaveLocalWaterMark(DEVICE_B, USER_B, w8), E_OK); + EXPECT_EQ(metadata_->SavePeerWaterMark(DEVICE_B, USER_B, w8, true), E_OK); + + /** + * @tc.steps: step6. get receive and send watermark + * @tc.expected: step6. E_OK and get the w3 + */ + EXPECT_EQ(metadata_->GetRecvDeleteSyncWaterMark(DEVICE_B, USER_A, w), E_OK); + EXPECT_EQ(w7, w); + EXPECT_EQ(metadata_->GetSendDeleteSyncWaterMark(DEVICE_B, USER_A, w), E_OK); + EXPECT_EQ(w7, w); + EXPECT_EQ(metadata_->GetRecvDeleteSyncWaterMark(DEVICE_B, USER_B, w), E_OK); + EXPECT_EQ(w8, w); + EXPECT_EQ(metadata_->GetSendDeleteSyncWaterMark(DEVICE_B, USER_B, w), E_OK); + EXPECT_EQ(w8, w); + + /** + * @tc.steps: step7. get not exit receive and send watermark + * @tc.expected: step7. E_OK and get the 0 + */ + EXPECT_EQ(metadata_->GetRecvDeleteSyncWaterMark("D3", USER_A, w), E_OK); + EXPECT_EQ(w, 0u); + EXPECT_EQ(metadata_->GetSendDeleteSyncWaterMark("D3", USER_A, w), E_OK); + EXPECT_EQ(w, 0u); +} +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp index 827a7b8e557fe07e92653d8cdde1bd75a46dd697..de2a4dc65bf01b81f9df243e30d9f029fc214097 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp @@ -108,7 +108,7 @@ void Init(MockSingleVerStateMachine &stateMachine, MockSyncTaskContext &syncTask { std::shared_ptr metadata = std::make_shared(); ASSERT_EQ(metadata->Initialize(&dbSyncInterface), E_OK); - (void)syncTaskContext.Initialize("device", &dbSyncInterface, metadata, &communicator); + (void)syncTaskContext.Initialize({"device", ""}, &dbSyncInterface, metadata, &communicator); (void)stateMachine.Initialize(&syncTaskContext, &dbSyncInterface, metadata, &communicator); } @@ -117,7 +117,7 @@ void Init(MockSingleVerStateMachine &stateMachine, MockSyncTaskContext *syncTask { std::shared_ptr metadata = std::make_shared(); ASSERT_EQ(metadata->Initialize(dbSyncInterface), E_OK); - (void)syncTaskContext->Initialize("device", dbSyncInterface, metadata, &communicator); + (void)syncTaskContext->Initialize({"device", ""}, dbSyncInterface, metadata, &communicator); (void)stateMachine.Initialize(syncTaskContext, dbSyncInterface, metadata, &communicator); } @@ -319,6 +319,10 @@ void SyncLifeTest003() { VirtualCommunicatorAggregator *virtualCommunicatorAggregator = new VirtualCommunicatorAggregator(); ASSERT_NE(virtualCommunicatorAggregator, nullptr); + bool isAlloc = false; + virtualCommunicatorAggregator->SetAllocCommunicatorCallback([&isAlloc](const std::string &userId) { + isAlloc = true; + }); RuntimeContext::GetInstance()->SetCommunicatorAggregator(virtualCommunicatorAggregator); TestInterface *syncDBInterface = new TestInterface(); ASSERT_NE(syncDBInterface, nullptr); @@ -333,11 +337,13 @@ void SyncLifeTest003() virtualCommunicatorAggregator->OnlineDevice(DEVICE_B); syncDBInterface->TestLocalChange(); virtualCommunicatorAggregator->OfflineDevice(DEVICE_B); + virtualCommunicatorAggregator->SetAllocCommunicatorCallback(nullptr); EXPECT_EQ(syncDBInterface->Close(), E_OK); RefObject::KillAndDecObjRef(syncDBInterface); std::this_thread::sleep_for(std::chrono::seconds(1)); RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); RuntimeContext::GetInstance()->StopTaskPool(); + EXPECT_TRUE(isAlloc); } void MockRemoteQuery002() @@ -368,7 +374,7 @@ void TimeSync001() const int timeDriverMs = 100; for (int i = 0; i < loopCount; ++i) { MockTimeSync timeSync; - EXPECT_EQ(timeSync.Initialize(communicator, metadata, storage, "DEVICES_A"), E_OK); + EXPECT_EQ(timeSync.Initialize(communicator, metadata, storage, "DEVICES_A", ""), E_OK); EXPECT_CALL(timeSync, SyncStart).WillRepeatedly(Return(E_OK)); timeSync.ModifyTimer(timeDriverMs); std::this_thread::sleep_for(std::chrono::milliseconds(timeDriverMs)); @@ -409,7 +415,7 @@ void DistributedDBMockSyncModuleTest::TearDown(void) * @tc.name: StateMachineCheck001 * @tc.desc: Test machine do timeout when has same timerId. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck001, TestSize.Level1) @@ -432,7 +438,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck001, TestSize.Level1) * @tc.name: StateMachineCheck002 * @tc.desc: Test machine do timeout when has diff timerId. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck002, TestSize.Level1) @@ -455,7 +461,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck002, TestSize.Level1) * @tc.name: StateMachineCheck003 * @tc.desc: Test machine exec next task when queue not empty. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck003, TestSize.Level1) @@ -486,7 +492,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck003, TestSize.Level1) * @tc.name: StateMachineCheck004 * @tc.desc: Test machine deal time sync ack failed. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck004, TestSize.Level1) @@ -511,7 +517,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck004, TestSize.Level1) * @tc.name: StateMachineCheck005 * @tc.desc: Test machine recv errCode. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck005, TestSize.Level1) @@ -539,7 +545,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck005, TestSize.Level1) * @tc.name: StateMachineCheck006 * @tc.desc: Test machine exec next task when queue not empty to empty. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck006, TestSize.Level1) @@ -569,7 +575,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck006, TestSize.Level1) * @tc.name: StateMachineCheck007 * @tc.desc: Test machine DoSaveDataNotify in another thread. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck007, TestSize.Level3) @@ -596,7 +602,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck007, TestSize.Level3) * @tc.name: StateMachineCheck008 * @tc.desc: test machine process when last sync task send packet failed. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck008, TestSize.Level1) @@ -614,7 +620,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck008, TestSize.Level1) * @tc.name: StateMachineCheck009 * @tc.desc: test machine process when last sync task send packet failed. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck009, TestSize.Level1) @@ -633,7 +639,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck009, TestSize.Level1) * @tc.name: StateMachineCheck010 * @tc.desc: test machine process when error happened in response pull. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck010, TestSize.Level1) @@ -652,7 +658,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck010, TestSize.Level1) * @tc.name: StateMachineCheck011 * @tc.desc: test machine process when error happened in response pull. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck011, TestSize.Level1) @@ -672,7 +678,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck011, TestSize.Level1) * @tc.name: StateMachineCheck012 * @tc.desc: Verify Ability LastNotify AckReceive callback. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck012, TestSize.Level1) @@ -698,7 +704,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck012, TestSize.Level1) * @tc.name: StateMachineCheck013 * @tc.desc: test kill syncTaskContext. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck013, TestSize.Level1) @@ -710,7 +716,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck013, TestSize.Level1) * @tc.name: StateMachineCheck014 * @tc.desc: test machine stop save notify without start. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck014, TestSize.Level1) @@ -724,7 +730,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck014, TestSize.Level1) * @tc.name: DataSyncCheck001 * @tc.desc: Test dataSync recv error ack. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck001, TestSize.Level1) @@ -741,7 +747,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck001, TestSize.Level1) * @tc.name: DataSyncCheck002 * @tc.desc: Test dataSync recv notify ack. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck002, TestSize.Level1) @@ -758,7 +764,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck002, TestSize.Level1) * @tc.name: DataSyncCheck003 * @tc.desc: Test dataSync recv notify ack. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck003, TestSize.Level1) @@ -781,8 +787,8 @@ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck003, TestSize.Level1) message->SetCopiedObject(packet); mockSyncTaskContext.SetQuerySync(true); - EXPECT_CALL(*mockMetadata, GetLastQueryTime(_, _, _)).WillOnce(Return(E_OK)); - EXPECT_CALL(*mockMetadata, SetLastQueryTime(_, _, _)) + EXPECT_CALL(*mockMetadata, GetLastQueryTime(_, _, _, _)).WillOnce(Return(E_OK)); + EXPECT_CALL(*mockMetadata, SetLastQueryTime(_, _, _, _)) .WillOnce([&dataTimeRange]( const std::string &queryIdentify, const std::string &deviceId, const Timestamp ×tamp) { EXPECT_EQ(timestamp, dataTimeRange.endTime); @@ -819,11 +825,38 @@ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck004, TestSize.Level1) RefObject::KillAndDecObjRef(communicator); } +/** + * @tc.name: DataSyncCheck004 + * @tc.desc: Test dataSync do ability sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: lg + */ +HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck005, TestSize.Level1) +{ + MockSingleVerDataSync mockDataSync; + auto mockMetadata = std::make_shared(); + MockSyncTaskContext mockSyncTaskContext; + SyncTimeRange dataTimeRange = {1, 0, 1, 0}; + mockDataSync.CallUpdateSendInfo(dataTimeRange, &mockSyncTaskContext); + + VirtualRelationalVerSyncDBInterface storage; + MockCommunicator communicator; + std::shared_ptr metadata = std::static_pointer_cast(mockMetadata); + mockDataSync.Initialize(&storage, &communicator, metadata, "deviceId"); + + EXPECT_CALL(*mockMetadata, GetLocalWaterMark(_, _, _)).WillOnce(Return()); + std::vector reserved; + mockDataSync.CallDealRemoveDeviceDataByAck(&mockSyncTaskContext, 1, reserved); + reserved.push_back(1); + mockDataSync.CallDealRemoveDeviceDataByAck(&mockSyncTaskContext, 1, reserved); +} + /** * @tc.name: AutoLaunchCheck001 * @tc.desc: Test autoLaunch close connection. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, AutoLaunchCheck001, TestSize.Level1) @@ -835,7 +868,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, AutoLaunchCheck001, TestSize.Level1) * @tc.name: AutoLaunchCheck002 * @tc.desc: Test autoLaunch receive diff userId. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, AutoLaunchCheck002, TestSize.Level1) @@ -857,7 +890,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, AutoLaunchCheck002, TestSize.Level1) * @tc.name: SyncDataSync001 * @tc.desc: Test request start when RemoveDeviceDataIfNeed failed. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncDataSync001, TestSize.Level1) @@ -874,7 +907,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncDataSync001, TestSize.Level1) * @tc.name: SyncDataSync002 * @tc.desc: Test pull request start when RemoveDeviceDataIfNeed failed. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncDataSync002, TestSize.Level1) @@ -891,7 +924,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncDataSync002, TestSize.Level1) * @tc.name: SyncDataSync003 * @tc.desc: Test call RemoveDeviceDataIfNeed in diff thread. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncDataSync003, TestSize.Level1) @@ -907,14 +940,14 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncDataSync003, TestSize.Level1) const std::string deviceId = "deviceId"; dataSync.Initialize(&storage, &communicator, metadata, deviceId); syncTaskContext.SetRemoteSoftwareVersion(SOFTWARE_VERSION_CURRENT); - syncTaskContext.Initialize(deviceId, &storage, metadata, &communicator); + syncTaskContext.Initialize({deviceId, ""}, &storage, metadata, &communicator); syncTaskContext.EnableClearRemoteStaleData(true); /** * @tc.steps: step1. set diff db createtime for rebuild label in meta */ - metadata->SetDbCreateTime(deviceId, 1, true); // 1 is old db createTime - metadata->SetDbCreateTime(deviceId, 2, true); // 1 is new db createTime + metadata->SetDbCreateTime(deviceId, "", 1, true); // 1 is old db createTime + metadata->SetDbCreateTime(deviceId, "", 2, true); // 1 is new db createTime DistributedDB::Key k1 = {'k', '1'}; DistributedDB::Value v1 = {'v', '1'}; @@ -948,7 +981,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncDataSync003, TestSize.Level1) * @tc.name: AbilitySync001 * @tc.desc: Test abilitySync abort when recv error. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync001, TestSize.Level1) @@ -970,7 +1003,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync001, TestSize.Level1) * @tc.name: AbilitySync002 * @tc.desc: Test abilitySync abort when save meta failed. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync002, TestSize.Level1) @@ -1007,7 +1040,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync002, TestSize.Level1) * @tc.name: AbilitySync002 * @tc.desc: Test abilitySync when offline. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync003, TestSize.Level1) @@ -1039,7 +1072,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync003, TestSize.Level1) * @tc.name: AbilitySync004 * @tc.desc: Test abilitySync when offline. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync004, TestSize.Level1) @@ -1051,7 +1084,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync004, TestSize.Level1) * @tc.name: SyncLifeTest001 * @tc.desc: Test syncer alive when thread still exist. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest001, TestSize.Level3) @@ -1063,7 +1096,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest001, TestSize.Level3) * @tc.name: SyncLifeTest002 * @tc.desc: Test autosync when thread still exist. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest002, TestSize.Level3) @@ -1075,7 +1108,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest002, TestSize.Level3) * @tc.name: SyncLifeTest003 * @tc.desc: Test syncer localdatachange when store is destructor * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest003, TestSize.Level3) @@ -1087,7 +1120,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest003, TestSize.Level3) * @tc.name: SyncLifeTest004 * @tc.desc: Test syncer remote data change. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest004, TestSize.Level3) @@ -1119,7 +1152,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest004, TestSize.Level3) * @tc.name: SyncLifeTest005 * @tc.desc: Test syncer remote device offline. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest005, TestSize.Level3) @@ -1205,7 +1238,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest006, TestSize.Level1) * @tc.name: MessageScheduleTest001 * @tc.desc: Test MessageSchedule stop timer when no message. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, MessageScheduleTest001, TestSize.Level1) @@ -1230,7 +1263,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, MessageScheduleTest001, TestSize.Level * @tc.name: SyncEngineTest001 * @tc.desc: Test SyncEngine receive message when closing. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncEngineTest001, TestSize.Level1) @@ -1285,7 +1318,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncEngineTest001, TestSize.Level1) * @tc.name: SyncEngineTest002 * @tc.desc: Test SyncEngine add sync operation. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncEngineTest002, TestSize.Level1) @@ -1349,7 +1382,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncEngineTest002, TestSize.Level1) * @tc.name: SyncEngineTest003 * @tc.desc: Test SyncEngine add block sync operation. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncEngineTest003, TestSize.Level1) @@ -1383,7 +1416,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncEngineTest004, TestSize.Level0) auto *enginePtr = new (std::nothrow) MockSyncEngine(); ASSERT_NE(enginePtr, nullptr); int errCode = E_OK; - auto *context = enginePtr->CallGetSyncTaskContext("dev", errCode); + auto *context = enginePtr->CallGetSyncTaskContext({"dev", "user"}, errCode); EXPECT_EQ(context, nullptr); EXPECT_EQ(errCode, -E_INVALID_DB); RefObject::KillAndDecObjRef(enginePtr); @@ -1439,11 +1472,58 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncEngineTest005, TestSize.Level0) virtualCommunicatorAggregator = nullptr; } +/** + * @tc.name: SyncEngineTest006 + * @tc.desc: Test find context with default user. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBMockSyncModuleTest, SyncEngineTest006, TestSize.Level0) +{ + /** + * @tc.steps: step1. Init engine. + * @tc.expected: step1. ok + */ + std::unique_ptr enginePtr = std::make_unique(); + MockKvSyncInterface syncDBInterface; + KvDBProperties kvDBProperties; + std::string userId = "user_1"; + kvDBProperties.SetStringProp(DBProperties::USER_ID, userId); + std::vector identifier(COMM_LABEL_LENGTH, 1u); + syncDBInterface.SetIdentifier(identifier); + syncDBInterface.SetDbProperties(kvDBProperties); + std::shared_ptr metaData = std::make_shared(); + metaData->Initialize(&syncDBInterface); + VirtualCommunicatorAggregator *virtualCommunicatorAggregator = new VirtualCommunicatorAggregator(); + ASSERT_NE(virtualCommunicatorAggregator, nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(virtualCommunicatorAggregator); + ISyncEngine::InitCallbackParam param = { nullptr, nullptr, nullptr }; + enginePtr->Initialize(&syncDBInterface, metaData, param); + /** + * @tc.steps: step2. Insert context with userId. + * @tc.expected: step2. ok + */ + EXPECT_CALL(*enginePtr, CreateSyncTaskContext(_)) + .WillRepeatedly(Return(new (std::nothrow) SingleVerKvSyncTaskContext())); + int errCode = E_OK; + std::string deviceId = "deviceB"; + auto *context1 = enginePtr->CallGetSyncTaskContext({deviceId, userId}, errCode); + ASSERT_NE(context1, nullptr); + /** + * @tc.steps: step3. Find context with default user. + * @tc.expected: step3. ok + */ + auto context2 = enginePtr->CallFindSyncTaskContext({deviceId, DBConstant::DEFAULT_USER}); + EXPECT_EQ(context1, context2); + enginePtr->Close(); +} + /** * @tc.name: remote query packet 001 * @tc.desc: Test RemoteExecutorRequestPacket Serialization And DeSerialization * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, RemoteQueryPacket001, TestSize.Level1) @@ -1484,7 +1564,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, RemoteQueryPacket001, TestSize.Level1) * @tc.name: remote query packet 002 * @tc.desc: Test RemoteExecutorAckPacket Serialization And DeSerialization * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, RemoteQueryPacket002, TestSize.Level1) @@ -1525,7 +1605,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, RemoteQueryPacket002, TestSize.Level1) * @tc.name: remote query packet 003 * @tc.desc: Test RemoteExecutorRequestPacket Serialization with invalid args * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBMockSyncModuleTest, RemoteQueryPacket003, TestSize.Level1) @@ -1578,7 +1658,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, RemoteQueryPacket003, TestSize.Level1) * @tc.name: remote query packet 004 * @tc.desc: Test RemoteExecutorRequestPacket Deserialization with invalid args * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBMockSyncModuleTest, RemoteQueryPacket004, TestSize.Level1) @@ -1625,7 +1705,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, RemoteQueryPacket004, TestSize.Level1) * @tc.name: SingleVerKvEntryTest001 * @tc.desc: Test SingleVerKvEntry Serialize and DeSerialize. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SingleVerKvEntryTest001, TestSize.Level1) @@ -1650,7 +1730,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SingleVerKvEntryTest001, TestSize.Leve * @tc.name: mock remote query 001 * @tc.desc: Test RemoteExecutor receive msg when closing * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, MockRemoteQuery001, TestSize.Level3) @@ -1679,7 +1759,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, MockRemoteQuery001, TestSize.Level3) * @tc.name: mock remote query 002 * @tc.desc: Test RemoteExecutor response failed when closing * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, MockRemoteQuery002, TestSize.Level3) @@ -1691,7 +1771,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, MockRemoteQuery002, TestSize.Level3) * @tc.name: SyncTaskContextCheck001 * @tc.desc: test context check task can be skipped in push mode. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck001, TestSize.Level1) @@ -1700,7 +1780,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck001, TestSize.Leve MockCommunicator communicator; VirtualSingleVerSyncDBInterface dbSyncInterface; std::shared_ptr metadata = std::make_shared(); - (void)syncTaskContext.Initialize("device", &dbSyncInterface, metadata, &communicator); + (void)syncTaskContext.Initialize({"device", ""}, &dbSyncInterface, metadata, &communicator); syncTaskContext.SetLastFullSyncTaskStatus(SyncOperation::Status::OP_FINISHED_ALL); syncTaskContext.CallSetSyncMode(static_cast(SyncModeType::PUSH)); EXPECT_EQ(syncTaskContext.CallIsCurrentSyncTaskCanBeSkipped(), true); @@ -1710,7 +1790,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck001, TestSize.Leve * @tc.name: SyncTaskContextCheck002 * @tc.desc: test context check task can be skipped in push mode. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck002, TestSize.Level1) @@ -1766,7 +1846,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck002, TestSize.Leve * @tc.name: SyncTaskContextCheck003 * @tc.desc: test context call on sync task add. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck003, TestSize.Level1) @@ -1804,7 +1884,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck003, TestSize.Leve * @tc.name: SyncTaskContextCheck004 * @tc.desc: test context add sync task should not cancel current task. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck004, TestSize.Level1) @@ -1838,7 +1918,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck004, TestSize.Leve * @tc.name: SyncTaskContextCheck005 * @tc.desc: test context call get query id async. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck005, TestSize.Level1) @@ -1853,7 +1933,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck005, TestSize.Leve VirtualSingleVerSyncDBInterface dbSyncInterface; std::shared_ptr metadata = std::make_shared(); ASSERT_EQ(metadata->Initialize(&dbSyncInterface), E_OK); - (void)context->Initialize("device", &dbSyncInterface, metadata, &communicator); + (void)context->Initialize({"device", ""}, &dbSyncInterface, metadata, &communicator); (void)stateMachine.Initialize(context, &dbSyncInterface, metadata, &communicator); for (int i = 0; i < 100; ++i) { // 100 sync target @@ -1894,7 +1974,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck005, TestSize.Leve * @tc.name: SyncTaskContextCheck006 * @tc.desc: test context call get query id async. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck006, TestSize.Level1) @@ -1909,7 +1989,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck006, TestSize.Leve VirtualSingleVerSyncDBInterface dbSyncInterface; std::shared_ptr metadata = std::make_shared(); ASSERT_EQ(metadata->Initialize(&dbSyncInterface), E_OK); - (void)context->Initialize("device", &dbSyncInterface, metadata, communicator); + (void)context->Initialize({"device", ""}, &dbSyncInterface, metadata, communicator); /** * @tc.steps: step2. add sync target into context */ @@ -1949,7 +2029,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck007, TestSize.Leve VirtualRelationalVerSyncDBInterface dbSyncInterface; std::shared_ptr metadata = std::make_shared(); ASSERT_EQ(metadata->Initialize(&dbSyncInterface), E_OK); - (void)context->Initialize("device", &dbSyncInterface, metadata, &communicator); + (void)context->Initialize({"device", ""}, &dbSyncInterface, metadata, &communicator); (void)stateMachine.Initialize(context, &dbSyncInterface, metadata, &communicator); /** * @tc.steps: step2. prepare table and query @@ -1984,7 +2064,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck007, TestSize.Leve * @tc.name: TimeChangeListenerTest001 * @tc.desc: Test RegisterTimeChangedLister. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, TimeChangeListenerTest001, TestSize.Level1) @@ -2014,7 +2094,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, TimeChangeListenerTest001, TestSize.Le * @tc.name: TimeChangeListenerTest002 * @tc.desc: Test TimeChange. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, TimeChangeListenerTest002, TestSize.Level1) @@ -2049,7 +2129,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, TimeChangeListenerTest002, TestSize.Le * @tc.name: SyncerCheck001 * @tc.desc: Test syncer call set sync retry before init. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck001, TestSize.Level1) @@ -2061,7 +2141,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck001, TestSize.Level1) * @tc.name: SyncerCheck002 * @tc.desc: Test syncer call get timestamp with close and open. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck002, TestSize.Level1) @@ -2106,7 +2186,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck002, TestSize.Level1) * @tc.name: SyncerCheck003 * @tc.desc: Test syncer query auto sync. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, DISABLE_SyncerCheck003, TestSize.Level1) @@ -2140,7 +2220,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, DISABLE_SyncerCheck003, TestSize.Level * @tc.name: SyncerCheck004 * @tc.desc: Test syncer call status check. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck004, TestSize.Level1) @@ -2153,7 +2233,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck004, TestSize.Level1) * @tc.name: SyncerCheck005 * @tc.desc: Test syncer call erase watermark without storage. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck005, TestSize.Level1) @@ -2169,7 +2249,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck005, TestSize.Level1) * @tc.name: SyncerCheck006 * @tc.desc: Test syncer call init with busy. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck006, TestSize.Level1) @@ -2188,7 +2268,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck006, TestSize.Level1) * @tc.name: SyncerCheck007 * @tc.desc: Test syncer get sync data size without syncer lock. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck007, TestSize.Level1) @@ -2196,7 +2276,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck007, TestSize.Level1) MockSingleVerKVSyncer syncer; auto mockMeta = std::make_shared(); auto metadata = std::static_pointer_cast(mockMeta); - EXPECT_CALL(*mockMeta, GetLocalWaterMark).WillRepeatedly([&syncer](const DeviceID &, uint64_t &) { + EXPECT_CALL(*mockMeta, GetLocalWaterMark).WillRepeatedly([&syncer](const DeviceID &, const DeviceID &, uint64_t &) { syncer.TestSyncerLock(); }); syncer.SetMetadata(metadata); @@ -2213,7 +2293,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck007, TestSize.Level1) * @tc.name: SyncerCheck008 * @tc.desc: Test syncer call set sync retry before init. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck008, TestSize.Level1) @@ -2258,7 +2338,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck008, TestSize.Level1) * @tc.name: SessionId001 * @tc.desc: Test syncer call set sync retry before init. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SessionId001, TestSize.Level1) @@ -2275,7 +2355,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SessionId001, TestSize.Level1) * @tc.name: TimeSync001 * @tc.desc: Test syncer call set sync retry before init. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, TimeSync001, TestSize.Level1) @@ -2300,7 +2380,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, TimeSync002, TestSize.Level1) MockTimeSync timeSync; EXPECT_CALL(timeSync, SyncStart).WillRepeatedly(Return(E_OK)); - EXPECT_EQ(timeSync.Initialize(communicator, metadata, storage, "DEVICES_A"), E_OK); + EXPECT_EQ(timeSync.Initialize(communicator, metadata, storage, "DEVICES_A", ""), E_OK); const int loopCount = 100; const int timeDriverMs = 10; for (int i = 0; i < loopCount; ++i) { @@ -2342,7 +2422,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, TimeSync003, TestSize.Level0) * @tc.name: SyncContextCheck001 * @tc.desc: Test context time out logic. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncContextCheck001, TestSize.Level1) @@ -2362,7 +2442,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncContextCheck001, TestSize.Level1) * @tc.name: SingleVerDataSyncUtils001 * @tc.desc: Test translate item got diff timestamp. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SingleVerDataSyncUtils001, TestSize.Level1) @@ -2371,7 +2451,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SingleVerDataSyncUtils001, TestSize.Le MockCommunicator communicator; VirtualSingleVerSyncDBInterface dbSyncInterface; std::shared_ptr metadata = std::make_shared(); - (void)context.Initialize("device", &dbSyncInterface, metadata, &communicator); + (void)context.Initialize({"device", ""}, &dbSyncInterface, metadata, &communicator); std::vector data; for (int i = 0; i < 2; ++i) { // loop 2 times @@ -2401,4 +2481,25 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTimerResetTest001, TestSize.Level1 EXPECT_EQ(stateMachine.CallPrepareNextSyncTask(), E_OK); stateMachine.CallStopWatchDog(); } + +/** + * @tc.name: SingleVerSyncStateMachineTest001 + * @tc.desc: Test it will return ok when sync with a timer already exists. + * @tc.type: FUNC + * @tc.require: + * @tc.author: lg + */ +HWTEST_F(DistributedDBMockSyncModuleTest, SingleVerSyncStateMachineTest001, TestSize.Level1) +{ + MockSingleVerStateMachine stateMachine; + std::shared_ptr metaData = std::make_shared(); + EXPECT_EQ(stateMachine.Initialize(nullptr, nullptr, metaData, nullptr), -E_INVALID_ARGS); + MockSyncTaskContext syncTaskContext; + MockCommunicator communicator; + VirtualSingleVerSyncDBInterface dbSyncInterface; + EXPECT_EQ(stateMachine.Initialize(&syncTaskContext, &dbSyncInterface, metaData, &communicator), -E_INVALID_ARGS); + Init(stateMachine, syncTaskContext, communicator, dbSyncInterface); + stateMachine.CallSyncStepInner(); + stateMachine.CallSetCurStateErrStatus(); +} } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_multi_ver_p2p_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_multi_ver_p2p_sync_test.cpp index 82172bb5b5b857d250d271bcd978fdc0bac916bf..3bf107528c5d312e7f437bab3d4db9a3bae46249 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_multi_ver_p2p_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_multi_ver_p2p_sync_test.cpp @@ -236,7 +236,7 @@ static DBStatus GetData(KvStoreDelegate *kvStore, const Key &key, Value &value) * @tc.name: Transaction Sync 001 * @tc.desc: Verify put transaction sync function. * @tc.type: FUNC - * @tc.require: AR000BVRO4 AR000CQE0K + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, TransactionSync001, TestSize.Level2) @@ -298,7 +298,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, TransactionSync001, TestSize.Level2) * @tc.name: Transaction Sync 002 * @tc.desc: Verify delete transaction sync function. * @tc.type: FUNC - * @tc.require: AR000BVRO4 AR000CQE0K + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, TransactionSync002, TestSize.Level2) @@ -359,7 +359,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, TransactionSync002, TestSize.Level2) * @tc.name: Transaction Sync 003 * @tc.desc: Verify update transaction sync function. * @tc.type: FUNC - * @tc.require: AR000BVRO4 AR000CQE0K + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, TransactionSync003, TestSize.Level2) @@ -420,7 +420,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, TransactionSync003, TestSize.Level2) * @tc.name: Metadata 001 * @tc.desc: Verify metadata add and update function * @tc.type: FUNC - * @tc.require: AR000CQE0P AR000CQE0S + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, Metadata001, TestSize.Level1) @@ -473,7 +473,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, Metadata001, TestSize.Level1) * @tc.name: Isolation Sync 001 * @tc.desc: Verify add sync isolation between different kvstore. * @tc.type: FUNC - * @tc.require: AR000BVDGP + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, IsolationSync001, TestSize.Level2) @@ -515,7 +515,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, IsolationSync001, TestSize.Level2) * @tc.name: Isolation Sync 002 * @tc.desc: Verify update sync isolation between different kvstore. * @tc.type: FUNC - * @tc.require: AR000BVDGP + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, IsolationSync002, TestSize.Level2) @@ -560,7 +560,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, IsolationSync002, TestSize.Level2) * @tc.name: Isolation Sync 003 * @tc.desc: Verify delete sync isolation between different kvstore. * @tc.type: FUNC - * @tc.require: AR000BVDGP + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, IsolationSync003, TestSize.Level2) @@ -627,7 +627,7 @@ static bool IsTimeSyncPacketEqual(const TimeSyncPacket &inPacketA, const TimeSyn * @tc.name: Timesync Packet 001 * @tc.desc: Verify TimesyncPacket Serialization and DeSerialization * @tc.type: FUNC - * @tc.require: AR000BVRNU AR000CQE0J + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, TimesyncPacket001, TestSize.Level1) @@ -793,7 +793,7 @@ static bool IsCommitHistorySyncRequestPacketEqual(const CommitHistorySyncRequest * @tc.name: Commit History Sync Request Packet 001 * @tc.desc: Verify CommitHistorySyncRequestPacket Serialization and DeSerialization * @tc.type: FUNC - * @tc.require: AR000BVRNU AR000CQE0J + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, CommitHistorySyncRequestPacket001, TestSize.Level1) @@ -909,7 +909,7 @@ static bool IsCommitHistorySyncAckPacketEqual(const CommitHistorySyncAckPacket & * @tc.name: Commit History Sync Ack Packet 001 * @tc.desc: Verify CommitHistorySyncAckPacket Serialization and DeSerialization * @tc.type: FUNC - * @tc.require: AR000BVRNU AR000CQE0J + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, CommitHistorySyncAckPacket001, TestSize.Level1) @@ -990,7 +990,7 @@ static bool IsMultiVerRequestPacketEqual(const MultiVerRequestPacket &inPacketA, * @tc.name: MultiVerValueObject Request Packet 001 * @tc.desc: Verify MultiVerRequestPacket Serialization and DeSerialization * @tc.type: FUNC - * @tc.require: AR000BVRNU AR000CQE0J + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, MultiVerRequestPacket001, TestSize.Level1) @@ -1100,7 +1100,7 @@ static bool IsMultiVerAckPacketEqual(const MultiVerAckPacket &inPacketA, const M * @tc.name: MultiVerValueObject Ack Packet 001 * @tc.desc: Verify MultiVerAckPacket Serialization and DeSerialization * @tc.type: FUNC - * @tc.require: AR000BVRNU AR000CQE0J + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, MultiVerAckPacket001, TestSize.Level1) @@ -1171,7 +1171,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, MultiVerAckPacket001, TestSize.Level1 * @tc.name: Simple Data Sync 001 * @tc.desc: Verify normal simple data sync function. * @tc.type: FUNC - * @tc.require: AR000BVDGR + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, SimpleDataSync001, TestSize.Level2) @@ -1215,7 +1215,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, SimpleDataSync001, TestSize.Level2) * @tc.name: Big Data Sync 001 * @tc.desc: Verify normal big data sync function. * @tc.type: FUNC - * @tc.require: AR000BVDGR + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, BigDataSync001, TestSize.Level2) @@ -1263,7 +1263,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, BigDataSync001, TestSize.Level2) * @tc.name: Limit Data Sync 001 * @tc.desc: Verify normal limit data sync function. * @tc.type: FUNC - * @tc.require: AR000BVDGR + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, LimitDataSync001, TestSize.Level2) @@ -1314,7 +1314,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, LimitDataSync001, TestSize.Level2) * @tc.name: Multi Record 001 * @tc.desc: Verify normal multi record sync function. * @tc.type: FUNC - * @tc.require: AR000BVDGR + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, MultiRecord001, TestSize.Level2) @@ -1402,7 +1402,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, MultiRecord001, TestSize.Level2) * @tc.name: Net Disconnect Sync 001 * @tc.desc: Test exception sync when net disconnected. * @tc.type: FUNC - * @tc.require: AR000BVDGR + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, NetDisconnectSync001, TestSize.Level3) @@ -1505,7 +1505,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, NetDisconnectSync001, TestSize.Level3 * @tc.name: SyncQueue006 * @tc.desc: multi version not support sync queue * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, SyncQueue006, TestSize.Level3) @@ -1531,7 +1531,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, SyncQueue006, TestSize.Level3) * @tc.name: PermissionCheck001 * @tc.desc: deviceA permission check not pass * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, PermissionCheck001, TestSize.Level2) @@ -1591,7 +1591,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, PermissionCheck001, TestSize.Level2) * @tc.name: PermissionCheck002 * @tc.desc: deviceB deviceC permission check not pass * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, PermissionCheck002, TestSize.Level2) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp index 62b441394aad630eadef271d7940307f5d7f9ce7..9c71b2b551cfdf308de45eae51c54541e7dcbad4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp @@ -544,10 +544,10 @@ void DistributedDBRelationalMultiUserTest::TearDown(void) * @tc.name: multi user 001 * @tc.desc: Test multi user change for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser001, TestSize.Level1) { /** * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active @@ -617,10 +617,10 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser001, TestSize.Level0) * @tc.name: multi user 002 * @tc.desc: Test multi user not change for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser002, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser002, TestSize.Level1) { /** * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active @@ -696,7 +696,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser002, TestSize.Level0) * @tc.name: multi user 003 * @tc.desc: enhancement callback return true in multiuser mode for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser003, TestSize.Level3) @@ -775,7 +775,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser003, TestSize.Level3) * @tc.name: multi user 004 * @tc.desc: test NotifyUserChanged func when all db in normal sync mode for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser004, TestSize.Level0) @@ -813,7 +813,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser004, TestSize.Level0) * @tc.name: multi user 005 * @tc.desc: test NotifyUserChanged and close db concurrently for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser005, TestSize.Level0) @@ -852,10 +852,10 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser005, TestSize.Level0) * @tc.name: multi user 006 * @tc.desc: test NotifyUserChanged and block sync concurrently for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser006, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser006, TestSize.Level1) { TestSyncWithUserChange(true, false); } @@ -864,10 +864,10 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser006, TestSize.Level0) * @tc.name: multi user 007 * @tc.desc: test NotifyUserChanged and non-block sync concurrently for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser007, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser007, TestSize.Level1) { TestSyncWithUserChange(false, false); } @@ -876,7 +876,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser007, TestSize.Level0) * @tc.name: multi user 008 * @tc.desc: test NotifyUserChanged and remote query concurrently for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser008, TestSize.Level1) @@ -915,10 +915,10 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser008, TestSize.Level1) * @tc.name: multi user 009 * @tc.desc: test user change and remote query concurrently for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser009, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser009, TestSize.Level1) { TestSyncWithUserChange(false, true); } @@ -927,7 +927,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser009, TestSize.Level0) * @tc.name: multi user 010 * @tc.desc: test check sync active twice when open store * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser010, TestSize.Level1) @@ -964,7 +964,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser010, TestSize.Level1) * @tc.name: multi user 011 * @tc.desc: test use different option to open store for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser011, TestSize.Level1) @@ -985,7 +985,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser011, TestSize.Level1) * @tc.name: multi user 012 * @tc.desc: test dont check sync active when open store with normal store * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser012, TestSize.Level1) @@ -1012,7 +1012,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser012, TestSize.Level1) * @tc.name: multi user 013 * @tc.desc: test dont check sync active when open store with normal store * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser013, TestSize.Level1) @@ -1082,7 +1082,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser014, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt001, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -1125,7 +1125,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt001, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt002, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt002, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -1167,7 +1167,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt002, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt003, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt003, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -1209,7 +1209,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt003, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt004, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt004, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -1251,7 +1251,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt004, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt005, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt005, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -1295,7 +1295,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt005, TestSize.Level0) * @tc.require: * @tc.author: suyue */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt006, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt006, TestSize.Level1) { /** * @tc.steps: step1. openStore and insert data @@ -1344,7 +1344,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt006, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRelationalMultiUserTest, SubUserAutoLaunchTest001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, SubUserAutoLaunchTest001, TestSize.Level1) { /** * @tc.steps: step1. Prepare db1 and db2 with subUser @@ -1407,7 +1407,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, SubUserAutoLaunchTest001, TestSiz * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRelationalMultiUserTest, DropDistributedTableTest001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, DropDistributedTableTest001, TestSize.Level1) { /** * @tc.steps: step1. Prepare db1 and db2. @@ -1462,7 +1462,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, DropDistributedTableTest001, Test * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRelationalMultiUserTest, DeleteTest001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, DeleteTest001, TestSize.Level1) { /** * @tc.steps: step1. Prepare db2. diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp index 81936211ba3dab445733dc5753a359ec1d72bf9d..7c2745e573790af8fd3ba7d14a038ca64f188e19 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp @@ -926,10 +926,10 @@ void DistributedDBRelationalVerP2PSyncTest::TearDown(void) * @tc.name: Normal Sync 001 * @tc.desc: Test normal push sync for add data. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync001, TestSize.Level1) { std::map dataMap; PrepareEnvironment(dataMap, {g_deviceB}); @@ -943,10 +943,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync001, TestSize.Level0) * @tc.name: Normal Sync 002 * @tc.desc: Test normal pull sync for add data. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync002, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync002, TestSize.Level1) { std::map dataMap; PrepareEnvironment(dataMap, {g_deviceB}); @@ -961,7 +961,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync002, TestSize.Level0) * @tc.name: Normal Sync 003 * @tc.desc: Test normal push sync for update data. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync003, TestSize.Level1) @@ -985,7 +985,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync003, TestSize.Level1) * @tc.name: Normal Sync 004 * @tc.desc: Test normal push sync for delete data. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync004, TestSize.Level1) @@ -1014,10 +1014,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync004, TestSize.Level1) * @tc.name: Normal Sync 005 * @tc.desc: Test normal push sync for add data. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync005, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync005, TestSize.Level1) { std::map dataMap; PrepareVirtualEnvironment(dataMap, {g_deviceB}); @@ -1038,7 +1038,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync005, TestSize.Level0) * @tc.name: Normal Sync 006 * @tc.desc: Test normal pull sync for add data. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync006, TestSize.Level1) @@ -1055,7 +1055,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync006, TestSize.Level1) * @tc.name: Normal Sync 007 * @tc.desc: Test normal sync for miss query data. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync007, TestSize.Level1) @@ -1088,10 +1088,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync007, TestSize.Level1) * @tc.name: Normal Sync 008 * @tc.desc: Test encry db sync for delete table; * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync008, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync008, TestSize.Level1) { /** * @tc.steps: step1. open rdb store, create distribute table, insert data and sync to deviceB @@ -1123,10 +1123,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync008, TestSize.Level0) * @tc.name: Normal Sync 009 * @tc.desc: Test normal push sync for while create distribute table * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync009, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync009, TestSize.Level1) { std::map dataMap; PrepareEnvironment(dataMap, {g_deviceB}); @@ -1174,7 +1174,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync009, TestSize.Level0) * @tc.name: AutoLaunchSync 001 * @tc.desc: Test rdb autoLaunch success when callback return true. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync001, TestSize.Level3) @@ -1241,7 +1241,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync001, TestSize.Leve * @tc.name: AutoLaunchSync 002 * @tc.desc: Test rdb autoLaunch failed when callback return false. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync002, TestSize.Level3) @@ -1289,7 +1289,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync002, TestSize.Leve * @tc.name: AutoLaunchSync 003 * @tc.desc: Test rdb autoLaunch failed when callback is nullptr. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync003, TestSize.Level3) @@ -1349,7 +1349,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync004, TestSize.Leve int currentStatus = 0; const AutoLaunchNotifier notifier = [¤tStatus](const std::string &userId, const std::string &appId, const std::string &storeId, AutoLaunchStatus status) { - printf("SET STATUS = %d\n", static_cast(status)); + LOGD("SET STATUS = %d\n", static_cast(status)); currentStatus = static_cast(status); }; const AutoLaunchRequestCallback callback = [¬ifier](const std::string &identifier, AutoLaunchParam ¶m) { @@ -1389,7 +1389,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync004, TestSize.Leve * @tc.name: Ability Sync 001 * @tc.desc: Test ability sync success when has same schema. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync001, TestSize.Level1) @@ -1408,7 +1408,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync001, TestSize.Level1) * @tc.name: Ability Sync 002 * @tc.desc: Test ability sync failed when has different schema. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync002, TestSize.Level1) @@ -1442,7 +1442,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync002, TestSize.Level1) * @tc.name: Ability Sync 003 * @tc.desc: Test ability sync failed when has different schema. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync003, TestSize.Level1) @@ -1494,7 +1494,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync003, TestSize.Level1) * @tc.name: Ability Sync 004 * @tc.desc: Test ability sync failed when one device hasn't distributed table. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync004, TestSize.Level1) @@ -1534,7 +1534,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync005, TestSize.Level1) * @tc.name: WaterMark 001 * @tc.desc: Test sync success after erase waterMark. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, WaterMark001, TestSize.Level1) @@ -1557,7 +1557,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, WaterMark001, TestSize.Level1) * @tc.name: pressure sync 001 * @tc.desc: Test rdb sync different table at same time * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, PressureSync001, TestSize.Level1) @@ -1613,7 +1613,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, PressureSync001, TestSize.Level1 * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer001, TestSize.Level1) { /** * @tc.steps: step1. device A create table and device B insert data and device C don't insert data @@ -1640,7 +1640,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer001, TestSize.Level0) * @tc.name: relation observer 002 * @tc.desc: Test rdb observer ok in autolauchCallback scene * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer002, TestSize.Level3) @@ -1704,7 +1704,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer002, TestSize.Level3) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer003, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer003, TestSize.Level1) { /** * @tc.steps: step1. device A create table and device B insert data and device C don't insert data @@ -1754,7 +1754,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer003, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer004, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer004, TestSize.Level1) { /** * @tc.steps: step1. device A create table and device B insert data and device C don't insert data @@ -1789,7 +1789,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer004, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer005, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer005, TestSize.Level1) { /** * @tc.steps: step1. device A create table and device B insert data and device C don't insert data @@ -2069,7 +2069,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer008, TestSize.Level3) * @tc.name: remote query 001 * @tc.desc: Test rdb remote query * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery001, TestSize.Level1) @@ -2089,7 +2089,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery001, TestSize.Level1) * @tc.name: remote query 002 * @tc.desc: Test rdb remote query * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery002, TestSize.Level1) @@ -2109,7 +2109,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery002, TestSize.Level1) * @tc.name: remote query 003 * @tc.desc: Test rdb remote query but query not data * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery003, TestSize.Level1) @@ -2130,7 +2130,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery003, TestSize.Level1) * @tc.name: remote query 004 * @tc.desc: Test rdb queue size * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery004, TestSize.Level3) @@ -2169,7 +2169,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery004, TestSize.Level3) * @tc.name: remote query 005 * @tc.desc: Test rdb remote query timeout by invalid message * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery005, TestSize.Level1) @@ -2193,7 +2193,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery005, TestSize.Level1) * @tc.name: remote query 006 * @tc.desc: Test rdb remote query commfailure by offline * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery006, TestSize.Level1) @@ -2230,7 +2230,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery006, TestSize.Level1) * @tc.name: remote query 007 * @tc.desc: Test rdb remote query failed by permission check * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery007, TestSize.Level1) @@ -2258,7 +2258,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery007, TestSize.Level1) * @tc.name: remote query 008 * @tc.desc: Test rdb remote query timeout but not effected by invalid message * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery008, TestSize.Level1) @@ -2304,7 +2304,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery008, TestSize.Level1) * @tc.name: remote query 009 * @tc.desc: Test rdb remote query busy before timeout * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery009, TestSize.Level1) @@ -2337,7 +2337,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery009, TestSize.Level1) * @tc.name: remote query 010 * @tc.desc: Test rdb remote query with kv db * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery010, TestSize.Level1) @@ -2357,7 +2357,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery010, TestSize.Level1) * @tc.name: remote query 010 * @tc.desc: Test rdb remote query with error sql * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery011, TestSize.Level1) @@ -2377,7 +2377,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery011, TestSize.Level1) * @tc.name: remote query 012 * @tc.desc: Test rdb remote query with invalid dev * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery012, TestSize.Level1) @@ -2400,7 +2400,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery012, TestSize.Level1) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery013, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery013, TestSize.Level1) { std::map dataMap; PrepareEnvironment(dataMap, {g_deviceB}); @@ -2416,10 +2416,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery013, TestSize.Level0) * @tc.name: RelationalPemissionTest001 * @tc.desc: deviceB PermissionCheck not pass test, SYNC_MODE_PUSH_ONLY * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest001, TestSize.Level1) { /** * @tc.steps: step1. SetPermissionCheckCallback @@ -2461,10 +2461,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest001, Test * @tc.name: RelationalPemissionTest002 * @tc.desc: deviceB PermissionCheck not pass test, SYNC_MODE_PULL_ONLY * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest002, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest002, TestSize.Level1) { /** * @tc.steps: step1. SetPermissionCheckCallback @@ -2506,10 +2506,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest002, Test * @tc.name: RelationalPemissionTest003 * @tc.desc: deviceB PermissionCheck not pass test, flag CHECK_FLAG_SPONSOR * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest003, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest003, TestSize.Level1) { /** * @tc.steps: step1. SetPermissionCheckCallback @@ -2551,10 +2551,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest003, Test * @tc.name: RelationalPemissionTest004 * @tc.desc: deviceB PermissionCheck pass test. deviceC not pass, SYNC_MODE_PUSH_ONLY * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest004, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest004, TestSize.Level1) { /** * @tc.steps: step1. SetPermissionCheckCallback @@ -2607,7 +2607,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest004, Test * @tc.name: SecurityOptionCheck001 * @tc.desc: Test sync failed when getSecurityOption return error * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, SecurityOptionCheck001, TestSize.Level1) @@ -2641,7 +2641,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, SecurityOptionCheck001, TestSize * @tc.name: SecurityOptionCheck002 * @tc.desc: Test remote query failed when getSecurityOption return error * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, SecurityOptionCheck002, TestSize.Level1) @@ -2678,10 +2678,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, SecurityOptionCheck002, TestSize * @tc.name: OrderbyWriteTimeSync001 * @tc.desc: sync query with order by writeTime * @tc.type: FUNC -* @tc.require: AR000H5VLO +* @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, OrderbyWriteTimeSync001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, OrderbyWriteTimeSync001, TestSize.Level1) { std::map dataMap; PrepareEnvironment(dataMap, {g_deviceB}); @@ -2694,7 +2694,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, OrderbyWriteTimeSync001, TestSiz * @tc.name: RDBSecurityOptionCheck001 * @tc.desc: Test sync with security option. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RDBSecurityOptionCheck001, TestSize.Level3) @@ -2706,7 +2706,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RDBSecurityOptionCheck001, TestS * @tc.name: RDBSecurityOptionCheck002 * @tc.desc: Test remote query with security option. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RDBSecurityOptionCheck002, TestSize.Level1) @@ -2718,10 +2718,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RDBSecurityOptionCheck002, TestS * @tc.name: EncryptedAlgoUpgrade001 * @tc.desc: Test upgrade encrypted db can sync normally * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, EncryptedAlgoUpgrade001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, EncryptedAlgoUpgrade001, TestSize.Level1) { if (g_rdbDelegatePtr != nullptr) { LOGD("CloseStore Start"); @@ -2769,7 +2769,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, EncryptedAlgoUpgrade001, TestSiz * @tc.name: AutoLaunchSyncAfterRekey_001 * @tc.desc: Test auto launch sync ok after rekey. * @tc.type: FUNC -* @tc.require: AR000H68LL +* @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSyncAfterRekey_001, TestSize.Level3) @@ -2784,10 +2784,8 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSyncAfterRekey_001, Te * @tc.steps: step2. set auto launch callBack */ AutoLaunchParam encryptedParam { USER_ID, APP_ID, STORE_ID_1, AutoLaunchOption {}, nullptr, g_dbDir }; - encryptedParam.option.isEncryptedDb = true; - encryptedParam.option.cipher = CipherType::DEFAULT; - encryptedParam.option.passwd = g_correctPasswd; - encryptedParam.option.iterateTimes = DEFAULT_ITER; + encryptedParam.option = {.isEncryptedDb = true, .cipher = CipherType::DEFAULT, .passwd = g_correctPasswd, + .iterateTimes = DEFAULT_ITER}; AutoLaunchRequestCallback callback = [&encryptedParam](const std::string &identifier, AutoLaunchParam ¶m) { if (g_id != identifier) { return false; @@ -2807,7 +2805,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSyncAfterRekey_001, Te LabelType labelType(g_id.begin(), g_id.end()); g_communicatorAggregator->RunCommunicatorLackCallback(labelType); std::this_thread::sleep_for(std::chrono::seconds(1)); - + RuntimeConfig::ReleaseAutoLaunch(USER_ID, APP_ID, STORE_ID_1, DBType::DB_RELATION); /** * @tc.steps: step5. Rekey */ @@ -2823,6 +2821,8 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSyncAfterRekey_001, Te /** * @tc.steps: step6. Call sync expect sync failed */ + g_communicatorAggregator->RunCommunicatorLackCallback(labelType); + std::this_thread::sleep_for(std::chrono::seconds(1)); Query query = Query::Select(g_tableName); EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK); size_t count = 0; @@ -2849,83 +2849,11 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSyncAfterRekey_001, Te std::this_thread::sleep_for(std::chrono::minutes(1)); sqlite3_close(db); db = nullptr; + g_mgr.SetAutoLaunchRequestCallback(nullptr); } /** -* @tc.name: AutoLaunchSyncAfterRekey_002 -* @tc.desc: Test auto launch close check after rekey. -* @tc.type: FUNC -* @tc.require: AR000H68LL -* @tc.author: zhangqiquan -*/ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSyncAfterRekey_002, TestSize.Level3) -{ - /** - * @tc.steps: step1. open rdb store, create distribute table and insert data - */ - std::map dataMap; - PrepareVirtualEnvironment(dataMap, {g_deviceB}); - /** - * @tc.steps: step2. set auto launch callBack - */ - AutoLaunchParam encryptedParam { USER_ID, APP_ID, STORE_ID_1, AutoLaunchOption {}, nullptr, g_dbDir }; - encryptedParam.option.isEncryptedDb = true; - encryptedParam.option.cipher = CipherType::DEFAULT; - encryptedParam.option.passwd = g_correctPasswd; - encryptedParam.option.iterateTimes = DEFAULT_ITER; - AutoLaunchRequestCallback callback = [&encryptedParam](const std::string &identifier, AutoLaunchParam ¶m) { - param = encryptedParam; - return true; - }; - RelationalStoreManager::SetAutoLaunchRequestCallback(callback); - /** - * @tc.steps: step3. close store ensure communicator has closed - */ - g_mgr.CloseStore(g_rdbDelegatePtr); - g_rdbDelegatePtr = nullptr; - /** - * @tc.steps: step4. RunCommunicatorLackCallback to autolaunch store - */ - LabelType labelType(g_id.begin(), g_id.end()); - g_communicatorAggregator->RunCommunicatorLackCallback(labelType); - std::this_thread::sleep_for(std::chrono::seconds(2)); // wait 2s for auto launch - /** - * @tc.steps: step5. Rekey - */ - sqlite3 *db = nullptr; - EXPECT_EQ(GetDB(db), SQLITE_OK); - std::string sql = "PARGMA rekey=" + REKEY_KEY; - EXPECT_EQ(sqlite3_rekey(db, REKEY_KEY.data(), REKEY_KEY.size()), SQLITE_OK); - g_isAfterRekey = true; - - RelationalDBProperties properties; - properties.SetStringProp(DBProperties::USER_ID, USER_ID); - properties.SetStringProp(DBProperties::APP_ID, APP_ID); - properties.SetStringProp(DBProperties::STORE_ID, STORE_ID_1); - properties.SetIntProp(DBProperties::AUTO_LAUNCH_ID, 7); // 7: invalid AUTO LAUNCH ID - const string &id = RelationalStoreManager::GetRelationalStoreIdentifier(USER_ID, APP_ID, STORE_ID_1); - properties.SetStringProp(DBProperties::IDENTIFIER_DATA, id); - RuntimeContext::GetInstance()->CloseAutoLaunchConnection(DBTypeInner::DB_RELATION, properties); - - encryptedParam.option.passwd = g_rekeyPasswd; - RelationalStoreManager::SetAutoLaunchRequestCallback(callback); - g_communicatorAggregator->RunCommunicatorLackCallback(labelType); - std::this_thread::sleep_for(std::chrono::seconds(2)); // wait 2s for auto launch - - Query query = Query::Select(g_tableName); - EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK); - size_t count = 0; - GetCount(db, "SELECT count(*) FROM sqlite_master WHERE name='" + GetDeviceTableName(g_tableName) + "';", count); - EXPECT_EQ(count, 0u); - - OpenStore(); - std::this_thread::sleep_for(std::chrono::minutes(1)); - sqlite3_close(db); - db = nullptr; -} - -/** -* @tc.name: AutoLaunchSyncAfterRekey_002 +* @tc.name: SyncTargetTest001 * @tc.desc: Test AddSyncTarget will not cause heap_use_after_free * @tc.type: FUNC * @tc.require: diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_dlp_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_dlp_test.cpp index 936df57c11e0253430af3f42953cf6513b5ab287..9241d5e684505791b814ada891b78d21d1b83f91 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_dlp_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_dlp_test.cpp @@ -15,16 +15,20 @@ #include #include +#include #include #include "db_constant.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" +#include "generic_single_ver_kv_entry.h" #include "kv_store_nb_delegate.h" #include "kv_virtual_device.h" +#include "mock_sync_task_context.h" #include "platform_specific.h" #include "relational_store_manager.h" #include "runtime_config.h" +#include "single_ver_data_sync_utils.h" using namespace testing::ext; using namespace DistributedDB; @@ -36,8 +40,10 @@ namespace { VirtualCommunicatorAggregator* g_communicatorAggregator = nullptr; const std::string DEVICE_A = "real_device"; const std::string DEVICE_B = "deviceB"; + const std::string DEVICE_C = "deviceC"; const std::string KEY_INSTANCE_ID = "INSTANCE_ID"; KvVirtualDevice *g_deviceB = nullptr; + KvVirtualDevice *g_deviceC = nullptr; DistributedDBToolsUnitTest g_tool; DBStatus OpenDelegate(const std::string &dlpPath, KvStoreNbDelegate *&delegatePtr, @@ -107,7 +113,14 @@ namespace { } } +class MockVirtualSingleVerSyncDBInterface : public VirtualSingleVerSyncDBInterface { +public: + MOCK_CONST_METHOD1(GetSecurityOption, int(SecurityOption &)); +}; + class DistributedDBSingleVerDLPTest : public testing::Test { +public: + MockVirtualSingleVerSyncDBInterface *syncInterfaceC = nullptr; public: static void SetUpTestCase(void); static void TearDownTestCase(void); @@ -147,9 +160,14 @@ void DistributedDBSingleVerDLPTest::SetUp(void) DistributedDBToolsUnitTest::PrintTestCaseInfo(); g_deviceB = new (std::nothrow) KvVirtualDevice(DEVICE_B); ASSERT_TRUE(g_deviceB != nullptr); + g_deviceC = new (std::nothrow) KvVirtualDevice(DEVICE_C); + ASSERT_TRUE(g_deviceC != nullptr); VirtualSingleVerSyncDBInterface *syncInterfaceB = new (std::nothrow) VirtualSingleVerSyncDBInterface(); ASSERT_TRUE(syncInterfaceB != nullptr); ASSERT_EQ(g_deviceB->Initialize(g_communicatorAggregator, syncInterfaceB), E_OK); + syncInterfaceC = new (std::nothrow) MockVirtualSingleVerSyncDBInterface(); + ASSERT_TRUE(syncInterfaceC != nullptr); + ASSERT_EQ(g_deviceC->Initialize(g_communicatorAggregator, syncInterfaceC), E_OK); } void DistributedDBSingleVerDLPTest::TearDown(void) @@ -158,6 +176,10 @@ void DistributedDBSingleVerDLPTest::TearDown(void) delete g_deviceB; g_deviceB = nullptr; } + if (g_deviceC != nullptr) { + delete g_deviceC; + g_deviceC = nullptr; + } PermissionCheckCallbackV3 nullCallback = nullptr; RuntimeConfig::SetPermissionCheckCallback(nullCallback); SyncActivationCheckCallbackV2 activeCallBack = nullptr; @@ -169,7 +191,7 @@ void DistributedDBSingleVerDLPTest::TearDown(void) * @tc.name: SameDelegateTest001 * @tc.desc: Test kv delegate open with diff instanceID. * @tc.type: FUNC - * @tc.require: SR000H0JSC + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerDLPTest, SameDelegateTest001, TestSize.Level1) @@ -208,7 +230,7 @@ HWTEST_F(DistributedDBSingleVerDLPTest, SameDelegateTest001, TestSize.Level1) * @tc.name: SameDelegateTest002 * @tc.desc: Test rdb delegate open with diff instanceID. * @tc.type: FUNC - * @tc.require: SR000H0JSC + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerDLPTest, SameDelegateTest002, TestSize.Level1) @@ -231,7 +253,7 @@ HWTEST_F(DistributedDBSingleVerDLPTest, SameDelegateTest002, TestSize.Level1) * @tc.name: DlpDelegateCRUDTest001 * @tc.desc: Test dlp delegate crud function. * @tc.type: FUNC - * @tc.require: SR000H0JSC + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerDLPTest, DlpDelegateCRUDTest001, TestSize.Level1) @@ -264,7 +286,7 @@ HWTEST_F(DistributedDBSingleVerDLPTest, DlpDelegateCRUDTest001, TestSize.Level1) * @tc.name: SandboxDelegateSync001 * @tc.desc: Test dlp delegate sync function. * @tc.type: FUNC - * @tc.require: SR000H0JSC + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerDLPTest, SandboxDelegateSync001, TestSize.Level1) @@ -310,7 +332,7 @@ HWTEST_F(DistributedDBSingleVerDLPTest, SandboxDelegateSync001, TestSize.Level1) * @tc.name: SandboxDelegateSync002 * @tc.desc: Test dlp delegate sync active if callback return true. * @tc.type: FUNC - * @tc.require: SR000H0JSC + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerDLPTest, SandboxDelegateSync002, TestSize.Level1) @@ -334,4 +356,104 @@ HWTEST_F(DistributedDBSingleVerDLPTest, SandboxDelegateSync002, TestSize.Level1) EXPECT_EQ(result[DEVICE_B], OK); CloseDelegate(delegatePtr1, mgr1, STORE_ID_1); +} + +/** + * @tc.name: SingleVerUtilsTest001 + * @tc.desc: Test single verification utils function. + * @tc.type: FUNC + * @tc.require: + * @tc.author: lg + */ +HWTEST_F(DistributedDBSingleVerDLPTest, SingleVerUtilsTest001, TestSize.Level0) +{ + bool isCheckStatus; + EXPECT_EQ(SingleVerDataSyncUtils::QuerySyncCheck(nullptr, isCheckStatus), -E_INVALID_ARGS); + MockSyncTaskContext context; + context.SetQuerySync(true); + context.SetRemoteSoftwareVersion(SOFTWARE_VERSION_RELEASE_1_0); + EXPECT_EQ(SingleVerDataSyncUtils::QuerySyncCheck(&context, isCheckStatus), OK); + context.SetRemoteSoftwareVersion(SOFTWARE_VERSION_RELEASE_3_0); + EXPECT_EQ(SingleVerDataSyncUtils::QuerySyncCheck(&context, isCheckStatus), OK); + EXPECT_EQ(SingleVerDataSyncUtils::RequestQueryCheck(nullptr, nullptr), -E_INVALID_ARGS); + + std::string deviceId; + SecurityOption option; + EXPECT_EQ(SingleVerDataSyncUtils::IsPermitRemoteDeviceRecvData(deviceId, option, nullptr), false); + EXPECT_CALL(*syncInterfaceC, GetSecurityOption(testing::_)).WillOnce(testing::Return(-E_INVALID_DB)); + EXPECT_EQ(SingleVerDataSyncUtils::IsPermitRemoteDeviceRecvData(deviceId, option, syncInterfaceC), false); + EXPECT_CALL(*syncInterfaceC, GetSecurityOption(testing::_)).WillRepeatedly(testing::Return(E_OK)); + EXPECT_EQ(SingleVerDataSyncUtils::IsPermitRemoteDeviceRecvData(deviceId, option, syncInterfaceC), false); + std::vector outData = {nullptr}; + SingleVerDataSyncUtils::TransDbDataItemToSendDataItem(deviceId, outData); + SingleVerDataSyncUtils::TransSendDataItemToLocal(&context, deviceId, outData); + int errNo = E_OK; + auto communicator = g_communicatorAggregator->AllocCommunicator(12345, errNo); + EXPECT_EQ(SingleVerDataSyncUtils::CheckPermitReceiveData(&context, communicator, syncInterfaceC), false); + EXPECT_CALL(*syncInterfaceC, GetSecurityOption(testing::_)).WillRepeatedly(testing::Return(-E_NOT_SUPPORT)); + EXPECT_EQ(SingleVerDataSyncUtils::CheckPermitReceiveData(&context, communicator, syncInterfaceC), true); + option.securityLabel = SecurityLabel::S0; + context.SetRemoteSeccurityOption(option); + EXPECT_CALL(*syncInterfaceC, GetSecurityOption(testing::_)) + .WillRepeatedly(testing::Invoke([](SecurityOption &option) { + option.securityLabel = SecurityLabel::S1; + return E_OK; + })); + EXPECT_EQ(SingleVerDataSyncUtils::CheckPermitReceiveData(&context, communicator, syncInterfaceC), true); + EXPECT_CALL(*syncInterfaceC, GetSecurityOption(testing::_)) + .WillRepeatedly(testing::Invoke([](SecurityOption &option) { + option.securityLabel = SecurityLabel::S1; + return E_OK; + })); + option.securityLabel = FAILED_GET_SEC_CLASSIFICATION; + context.SetRemoteSeccurityOption(option); + EXPECT_EQ(SingleVerDataSyncUtils::CheckPermitReceiveData(&context, communicator, syncInterfaceC), false); + EXPECT_CALL(*syncInterfaceC, GetSecurityOption(testing::_)).Times(testing::AtLeast(0)); + g_communicatorAggregator->ReleaseCommunicator(communicator); +} + +/** + * @tc.name: SingleVerUtilsTest002 + * @tc.desc: Test single verification utils function. + * @tc.type: FUNC + * @tc.require: + * @tc.author: lg + */ +HWTEST_F(DistributedDBSingleVerDLPTest, SingleVerUtilsTest002, TestSize.Level0) +{ + MockSyncTaskContext context; + context.SetRemoteSoftwareVersion(SOFTWARE_VERSION_RELEASE_3_0); + context.SetTaskErrCode(-E_EKEYREVOKED); + context.SetMode(SyncModeType::PUSH_AND_PULL); + SingleVerDataSyncUtils::PushAndPullKeyRevokHandle(&context); + EXPECT_EQ(SingleVerDataSyncUtils::GetReSendMode(SyncModeType::RESPONSE_PULL, 1, SyncType::QUERY_SYNC_TYPE), + SyncModeType::QUERY_PUSH); + EXPECT_EQ(SingleVerDataSyncUtils::GetReSendMode(SyncModeType::QUERY_PUSH_PULL, 1, SyncType::QUERY_SYNC_TYPE), + SyncModeType::QUERY_PUSH_PULL); + EXPECT_EQ(SingleVerDataSyncUtils::GetReSendMode(SyncModeType::QUERY_PUSH_PULL, 0, SyncType::QUERY_SYNC_TYPE), + SyncModeType::QUERY_PUSH); + EXPECT_EQ( + SingleVerDataSyncUtils::GetControlCmdType(SyncModeType::QUERY_PUSH_PULL), ControlCmdType::INVALID_CONTROL_CMD); + EXPECT_EQ(SingleVerDataSyncUtils::GetModeByControlCmdType(ControlCmdType::INVALID_CONTROL_CMD), + SyncModeType::INVALID_MODE); + EXPECT_EQ(SingleVerDataSyncUtils::GetModeByControlCmdType(ControlCmdType::UNSUBSCRIBE_QUERY_CMD), + SyncModeType::UNSUBSCRIBE_QUERY); + QuerySyncObject query; + EXPECT_EQ(SingleVerDataSyncUtils::IsNeedTriggerQueryAutoSync(nullptr, query), false); + Message msg; + msg.SetMessageId(CONTROL_SYNC_MESSAGE); + msg.SetMessageType(TYPE_REQUEST); + EXPECT_EQ(SingleVerDataSyncUtils::IsNeedTriggerQueryAutoSync(&msg, query), false); + std::vector inData = {nullptr}; + SingleVerDataSyncUtils::GetMaxSendDataTime(inData); + UpdateWaterMark isUpdate; + auto kvEnv = new (std::nothrow) GenericSingleVerKvEntry(); + inData.push_back(kvEnv); + SingleVerDataSyncUtils::GetFullSyncDataTimeRange(inData, 100, isUpdate); + SingleVerDataSyncUtils::GetQuerySyncDataTimeRange(inData, 100, 100, isUpdate); + DataItem dataItem; + dataItem.flag = DataItem::DELETE_FLAG; + kvEnv->SetEntryData(std::move(dataItem)); + SingleVerDataSyncUtils::GetQuerySyncDataTimeRange(inData, 100, 100, isUpdate); + delete kvEnv; } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_sub_user_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_sub_user_test.cpp index d21c470ea6989945e6aa5fd457709f7b75a5c7c5..1f612d0e368600b22b49b41b8b87f5f58712f854 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_sub_user_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_sub_user_test.cpp @@ -467,21 +467,19 @@ HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserPermissionCheck, TestSiz EXPECT_EQ(OpenDelegate("/subUser1", delegatePtr1, mgr1), OK); ASSERT_NE(delegatePtr1, nullptr); - DBStatus status = OK; std::vector devices; devices.push_back(g_deviceB->GetDeviceId()); Key key = {'1'}; Value value = {'1'}; g_deviceB->PutData(key, value, 0, 0); - ASSERT_TRUE(status == OK); /** * @tc.steps: step3. deviceB push data * @tc.expected: step3. return PERMISSION_CHECK_FORBID_SYNC. */ std::map result; - status = g_tool.SyncTest(delegatePtr1, devices, SYNC_MODE_PUSH_ONLY, result); + DBStatus status = g_tool.SyncTest(delegatePtr1, devices, SYNC_MODE_PUSH_ONLY, result); ASSERT_TRUE(status == OK); std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); @@ -697,7 +695,7 @@ HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserDelegateCRUDTest002, Tes * @tc.require: * @tc.author: zhaoliang */ -HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserDelegateCloudSyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserDelegateCloudSyncTest001, TestSize.Level1) { KvStoreDelegateManager mgr1(APP_ID, USER_ID, SUB_USER_1, INSTANCE_ID_1); KvStoreNbDelegate *delegatePtr1 = nullptr; @@ -737,7 +735,7 @@ HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserDelegateCloudSyncTest001 * @tc.require: * @tc.author: zhaoliang */ -HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserDelegateCloudSyncTest002, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserDelegateCloudSyncTest002, TestSize.Level1) { RelationalStoreManager mgr1(APP_ID, USER_ID, SUB_USER_1, INSTANCE_ID_1); RelationalStoreDelegate *rdbDelegatePtr1 = nullptr; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp index 89da16717d41ea819efec4ed93a0ae9d17c15cab..f21a0ba7f05123a0f0b51212d8624164cb963fd7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp @@ -297,10 +297,10 @@ void TestSyncWithUserChange(bool wait) * @tc.name: multi user 001 * @tc.desc: Test multi user change * @tc.type: FUNC - * @tc.require: AR000CQS3S SR000CQE0B + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser001, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser001, TestSize.Level1) { /** * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active @@ -373,10 +373,10 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser001, TestSize.Level0) * @tc.name: multi user 002 * @tc.desc: Test multi user not change * @tc.type: FUNC - * @tc.require: AR000CQS3S SR000CQE0B + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser002, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser002, TestSize.Level1) { /** * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active @@ -445,7 +445,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser002, TestSize.Level0) * @tc.name: multi user 003 * @tc.desc: enhancement callback return true in multiuser mode * @tc.type: FUNC - * @tc.require: AR000EPARJ + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser003, TestSize.Level3) @@ -509,10 +509,10 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser003, TestSize.Level3) * @tc.name: MultiUser004 * @tc.desc: CommunicatorLackCallback in multi user mode * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser004, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser004, TestSize.Level1) { /** * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active @@ -585,10 +585,10 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser004, TestSize.Level0) * @tc.name: MultiUser005 * @tc.desc: test NotifyUserChanged func when all db in normal sync mode * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser005, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser005, TestSize.Level1) { /** * @tc.steps: step1. openstore1 and openstore2 in normal sync mode @@ -620,10 +620,10 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser005, TestSize.Level0) * @tc.name: MultiUser006 * @tc.desc: test NotifyUserChanged and close db concurrently * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser006, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser006, TestSize.Level1) { /** * @tc.steps: step1. set SyncActivationCheckCallback and only userId1 can active @@ -656,7 +656,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser006, TestSize.Level0) * @tc.name: MultiUser007 * @tc.desc: test NotifyUserChanged and rekey db concurrently * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser007, TestSize.Level0) @@ -693,10 +693,10 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser007, TestSize.Level0) * @tc.name: MultiUser008 * @tc.desc: test NotifyUserChanged and block sync concurrently * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser008, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser008, TestSize.Level1) { TestSyncWithUserChange(true); } @@ -705,7 +705,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser008, TestSize.Level0) * @tc.name: MultiUser009 * @tc.desc: test NotifyUserChanged and non-block sync concurrently * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser009, TestSize.Level0) @@ -717,7 +717,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser009, TestSize.Level0) * @tc.name: MultiUser010 * @tc.desc: test NotifyUserChanged and non-block sync with multi devices concurrently * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser010, TestSize.Level3) @@ -786,7 +786,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser010, TestSize.Level3) * @tc.name: MultiUser011 * @tc.desc: test check sync active twice when open store * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser011, TestSize.Level1) @@ -819,7 +819,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser011, TestSize.Level1) * @tc.name: MultiUser012 * @tc.desc: test NotifyUserChanged and SetEqualIdentifier sync concurrently * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser012, TestSize.Level1) @@ -856,7 +856,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser012, TestSize.Level1) * @tc.name: MultiUser013 * @tc.desc: test dont check sync active when open store with normal store * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser013, TestSize.Level1) @@ -883,7 +883,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser013, TestSize.Level1) * @tc.name: MultiUser014 * @tc.desc: test active callback call count * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser014, TestSize.Level1) @@ -916,7 +916,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser014, TestSize.Level1) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser015, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser015, TestSize.Level1) { /** * @tc.steps: step1. create sub user KvStoreDelegateManager diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp index e27cf38aee69cf018f0847a284b61274e82808fa..f19e07cfa24a3622658a2321e2d8b57747b784cf 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp @@ -281,7 +281,7 @@ void DistributedDBSingleVerP2PComplexSyncTest::TearDown(void) * @tc.name: SaveDataNotify001 * @tc.desc: Test SaveDataNotify function, delay < 30s should sync ok, > 36 should timeout * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SaveDataNotify001, TestSize.Level3) @@ -353,7 +353,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SaveDataNotify001, TestSize.L * @tc.name: SametimeSync001 * @tc.desc: Test 2 device sync with each other * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SametimeSync001, TestSize.Level3) @@ -415,7 +415,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SametimeSync001, TestSize.Lev * @tc.name: SametimeSync002 * @tc.desc: Test 2 device sync with each other with water error * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SametimeSync002, TestSize.Level3) @@ -484,7 +484,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SametimeSync002, TestSize.Lev * @tc.name: DatabaseOnlineCallback001 * @tc.desc: check database status notify online callback * @tc.type: FUNC - * @tc.require: AR000CQS3S SR000CQE0B + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DatabaseOnlineCallback001, TestSize.Level1) @@ -517,7 +517,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DatabaseOnlineCallback001, Te * @tc.name: DatabaseOfflineCallback001 * @tc.desc: check database status notify online callback * @tc.type: FUNC - * @tc.require: AR000CQS3S SR000CQE0B + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DatabaseOfflineCallback001, TestSize.Level1) @@ -550,7 +550,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DatabaseOfflineCallback001, T * @tc.name: CloseSync001 * @tc.desc: Test 2 delegate close when sync * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, CloseSync001, TestSize.Level3) @@ -608,7 +608,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, CloseSync001, TestSize.Level3 * @tc.name: CloseSync002 * @tc.desc: Test 1 delegate close when in time sync * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, CloseSync002, TestSize.Level3) @@ -660,7 +660,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, CloseSync002, TestSize.Level3 * @tc.name: OrderbyWriteTimeSync001 * @tc.desc: sync query with order by writeTime * @tc.type: FUNC - * @tc.require: AR000H5VLO + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, OrderbyWriteTimeSync001, TestSize.Level0) @@ -680,7 +680,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, OrderbyWriteTimeSync001, Test * @tc.name: Device Offline Sync 001 * @tc.desc: Test push sync when device offline * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DeviceOfflineSync001, TestSize.Level1) @@ -757,7 +757,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DeviceOfflineSync001, TestSiz * @tc.name: Device Offline Sync 002 * @tc.desc: Test pull sync when device offline * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DeviceOfflineSync002, TestSize.Level1) @@ -831,7 +831,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DeviceOfflineSync002, TestSiz * @tc.name: EncryptedAlgoUpgrade001 * @tc.desc: Test upgrade encrypted db can sync normally * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, EncryptedAlgoUpgrade001, TestSize.Level3) @@ -954,7 +954,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, RemoveDeviceData002, TestSize * @tc.name: DataSync001 * @tc.desc: Test Data Sync when Initialize * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync001, TestSize.Level1) @@ -976,7 +976,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync001, TestSize.Level1) * @tc.name: DataSync002 * @tc.desc: Test active sync with invalid param in DataSync Class * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync002, TestSize.Level1) @@ -997,7 +997,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync002, TestSize.Level1) * @tc.name: DataSync003 * @tc.desc: Test receive invalid request data packet in DataSync Class * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync003, TestSize.Level1) @@ -1015,7 +1015,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync003, TestSize.Level1) * @tc.name: DataSync004 * @tc.desc: Test receive invalid ack packet in DataSync Class * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync004, TestSize.Level1) @@ -1036,7 +1036,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync004, TestSize.Level1) * @tc.name: DataSync005 * @tc.desc: Test receive invalid notify packet in DataSync Class * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync005, TestSize.Level1) @@ -1048,7 +1048,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync005, TestSize.Level1) * @tc.name: DataSync006 * @tc.desc: Test control start with invalid param in DataSync Class * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync006, TestSize.Level1) @@ -1076,7 +1076,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync006, TestSize.Level1) * @tc.name: DataSync007 * @tc.desc: Test receive invalid control packet in DataSync Class * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync007, TestSize.Level1) @@ -1096,7 +1096,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync007, TestSize.Level1) * @tc.name: DataSync008 * @tc.desc: Test pull null msg in dataQueue in DataSync Class * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync008, TestSize.Level1) @@ -1108,7 +1108,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync008, TestSize.Level1) * @tc.name: SyncRetry001 * @tc.desc: use sync retry sync use push * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry001, TestSize.Level3) @@ -1152,7 +1152,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry001, TestSize.Level3 * @tc.name: SyncRetry002 * @tc.desc: use sync retry sync use pull * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry002, TestSize.Level3) @@ -1191,7 +1191,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry002, TestSize.Level3 * @tc.name: SyncRetry003 * @tc.desc: use sync retry sync use push by compress * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry003, TestSize.Level3) @@ -1250,7 +1250,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry003, TestSize.Level3 * @tc.name: SyncRetry004 * @tc.desc: use query sync retry sync use push * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry004, TestSize.Level3) @@ -1301,7 +1301,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry004, TestSize.Level3 * @tc.name: SyncRetry005 * @tc.desc: use sync retry sync use pull by compress * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry005, TestSize.Level3) @@ -1354,7 +1354,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry005, TestSize.Level3 * @tc.name: ReSetWatchDogTest001 * @tc.desc: trigger resetWatchDog while pull * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, ReSetWaterDogTest001, TestSize.Level3) @@ -1651,7 +1651,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, RebuildSync004, TestSize.Leve * @tc.name: RemoveDeviceData001 * @tc.desc: call rekey and removeDeviceData Concurrently * @tc.type: FUNC - * @tc.require: AR000D487B + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, RemoveDeviceData001, TestSize.Level1) @@ -1695,7 +1695,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, RemoveDeviceData001, TestSize * @tc.name: DeviceOfflineSyncTask001 * @tc.desc: Test sync task when device offline and close db Concurrently * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DeviceOfflineSyncTask001, TestSize.Level3) @@ -1850,7 +1850,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, GetSyncDataFail001, TestSize. * @tc.name: GetSyncDataFail002 * @tc.desc: test get sync data failed when sync with large data * @tc.type: FUNC - * @tc.require: AR000D487B + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, GetSyncDataFail002, TestSize.Level1) @@ -2025,7 +2025,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, InterceptDataFail001, TestSiz * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, InterceptDataFail002, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, InterceptDataFail002, TestSize.Level1) { ASSERT_TRUE(g_kvDelegatePtr != nullptr); /** diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_permission_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_permission_sync_test.cpp index 2068e73e0ab705fc869817b241e10fe4433c5609..63051fec1d85b524c7bb39c6445b5de44e9e334f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_permission_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_permission_sync_test.cpp @@ -150,7 +150,7 @@ void DistributedDBSingleVerP2PPermissionSyncTest::TearDown(void) * @tc.name: PermissionCheck001 * @tc.desc: deviceA PermissionCheck not pass test, SYNC_MODE_PUSH_ONLY * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck001, TestSize.Level3) @@ -213,7 +213,7 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck001, TestSi * @tc.name: PermissionCheck002 * @tc.desc: deviceA PermissionCheck not pass test, SYNC_MODE_PULL_ONLY * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck002, TestSize.Level3) @@ -235,7 +235,6 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck002, TestSi EXPECT_EQ(g_mgr.SetPermissionCheckCallback(permissionCheckCallback), OK); - DBStatus status = OK; std::vector devices; devices.push_back(g_deviceB->GetDeviceId()); devices.push_back(g_deviceC->GetDeviceId()); @@ -253,14 +252,13 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck002, TestSi Key key2 = {'2'}; Value value2 = {'2'}; g_deviceC->PutData(key2, value2, 0, 0); - ASSERT_TRUE(status == OK); /** * @tc.steps: step3. deviceA call pull sync * @tc.expected: step3. sync should return OK. */ std::map result; - status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result); + DBStatus status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result); ASSERT_TRUE(status == OK); /** @@ -283,7 +281,7 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck002, TestSi * @tc.name: PermissionCheck003 * @tc.desc: deviceA PermissionCheck not pass test, SYNC_MODE_PUSH_PULL * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck003, TestSize.Level3) @@ -372,7 +370,7 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck003, TestSi * @tc.name: PermissionCheck004 * @tc.desc: deviceB and deviceC PermissionCheck not pass test, SYNC_MODE_PUSH_ONLY * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck004, TestSize.Level3) @@ -435,7 +433,7 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck004, TestSi * @tc.name: PermissionCheck005 * @tc.desc: deviceB and deviceC PermissionCheck not pass test, SYNC_MODE_PULL_ONLY * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck005, TestSize.Level3) @@ -456,7 +454,6 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck005, TestSi }; EXPECT_EQ(g_mgr.SetPermissionCheckCallback(permissionCheckCallback), OK); - DBStatus status = OK; std::vector devices; devices.push_back(g_deviceB->GetDeviceId()); devices.push_back(g_deviceC->GetDeviceId()); @@ -474,14 +471,13 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck005, TestSi Key key2 = {'2'}; Value value2 = {'2'}; g_deviceC->PutData(key2, value2, 0, 0); - ASSERT_TRUE(status == OK); /** * @tc.steps: step3. deviceA call pull sync * @tc.expected: step3. sync should return OK. */ std::map result; - status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result); + DBStatus status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result); ASSERT_TRUE(status == OK); /** @@ -504,7 +500,7 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck005, TestSi * @tc.name: PermissionCheck006 * @tc.desc: deviceA PermissionCheck deviceB not pass, deviceC pass * @tc.type: FUNC - * @tc.require: AR000EJJOJ + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck006, TestSize.Level3) @@ -571,7 +567,7 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck006, TestSi * @tc.name: PermissionCheck007 * @tc.desc: deviceA PermissionCheck, deviceB not pass, deviceC pass in SYNC_MODE_AUTO_PUSH * @tc.type: FUNC - * @tc.require: AR000G3RLS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck007, TestSize.Level3) @@ -626,12 +622,12 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck007, TestSi } /** -+ * @tc.name: PermissionCheck008 -+ * @tc.desc: deviceA PermissionCheck, deviceB not pass, deviceC pass in SYNC_MODE_AUTO_PULL -+ * @tc.type: FUNC -+ * @tc.require: AR000G3RLS -+ * @tc.author: zhangqiquan -+ */ + * @tc.name: PermissionCheck008 + * @tc.desc: deviceA PermissionCheck, deviceB not pass, deviceC pass in SYNC_MODE_AUTO_PULL + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck008, TestSize.Level3) { /** @@ -650,7 +646,6 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck008, TestSi } }; EXPECT_EQ(g_mgr.SetPermissionCheckCallback(permissionCheckCallback), OK); - DBStatus status = OK; std::vector devices; devices.push_back(g_deviceB->GetDeviceId()); devices.push_back(g_deviceC->GetDeviceId()); @@ -668,14 +663,13 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck008, TestSi Key key2 = {'2'}; Value value2 = {'2'}; g_deviceC->PutData(key2, value2, 0, 0); - ASSERT_TRUE(status == OK); /** * @tc.steps: step3. deviceA call push sync * @tc.expected: step3. sync should return OK. */ std::map result; - status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result); + DBStatus status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result); ASSERT_TRUE(status == OK); std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); @@ -706,7 +700,7 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck008, TestSi * @tc.name: PermissionCheck009 * @tc.desc: different runpermissioncheck call return different value * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck009, TestSize.Level3) @@ -777,7 +771,7 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck009, TestSi * @tc.name: PermissionCheck010 * @tc.desc: permission check cost lot of time and return false * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck010, TestSize.Level3) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp index 6c5e788df4fdd8d235622e55eab7c0bc70e37a78..0927c57c930fc8178c3b0acb9a6df1e3f2d85000 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp @@ -199,13 +199,14 @@ void InitSchemaDb() g_schemaMgr.GetKvStore(SCHEMA_STORE_ID, option, g_schemaKvDelegateCallback); ASSERT_TRUE(g_schemaKvDelegateStatus == OK); ASSERT_TRUE(g_schemaKvDelegatePtr != nullptr); + g_deviceB->SetSchema(option.schema); } /** * @tc.name: Normal Sync 001 * @tc.desc: Test normal push sync for keyprefix data. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync001, TestSize.Level1) @@ -267,7 +268,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync001, TestSize.Level1) * @tc.name: Normal Sync 002 * @tc.desc: Test normal push sync for limit and offset. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync002, TestSize.Level1) @@ -327,7 +328,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync002, TestSize.Level1) * @tc.name: Normal Sync 001 * @tc.desc: Test normal push_and_pull sync for keyprefix data. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync003, TestSize.Level1) @@ -401,7 +402,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync003, TestSize.Level1) * @tc.name: Normal Sync 001 * @tc.desc: Test normal pull sync for keyprefix data. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync004, TestSize.Level1) @@ -469,7 +470,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync004, TestSize.Level1) * @tc.name: NormalSync005 * @tc.desc: Test normal push sync for inkeys query. * @tc.type: FUNC - * @tc.require: AR000GOHO7 + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync005, TestSize.Level1) @@ -772,7 +773,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, QueryAckPacketTest001, TestSize * @tc.name: GetQueryWaterMark 001 * @tc.desc: Test metaData save and get queryWaterMark. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark001, TestSize.Level1) @@ -792,17 +793,17 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark001, TestSize. * @tc.expected: step2. E_OK */ WaterMark w1 = 1; - EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D1", w1), E_OK); - EXPECT_EQ(meta.SetSendQueryWaterMark("Q1", "D1", w1), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D1", "", w1), E_OK); + EXPECT_EQ(meta.SetSendQueryWaterMark("Q1", "D1", "", w1), E_OK); /** * @tc.steps: step3. get receive and send watermark * @tc.expected: step3. E_OK and get the latest value */ WaterMark w = 0; - EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", w), E_OK); + EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", "", w), E_OK); EXPECT_EQ(w1, w); - EXPECT_EQ(meta.GetSendQueryWaterMark("Q1", "D1", w), E_OK); + EXPECT_EQ(meta.GetSendQueryWaterMark("Q1", "D1", "", w), E_OK); EXPECT_EQ(w1, w); /** @@ -810,16 +811,16 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark001, TestSize. * @tc.expected: step4. E_OK */ WaterMark w2 = 2; - EXPECT_EQ(meta.SaveLocalWaterMark("D1", w2), E_OK); - EXPECT_EQ(meta.SavePeerWaterMark("D1", w2, true), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark("D1", "", w2), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D1", "", w2, true), E_OK); /** * @tc.steps: step5. get receive and send watermark * @tc.expected: step5. E_OK and get the w1 */ - EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", w), E_OK); + EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", "", w), E_OK); EXPECT_EQ(w2, w); - EXPECT_EQ(meta.GetSendQueryWaterMark("Q1", "D1", w), E_OK); + EXPECT_EQ(meta.GetSendQueryWaterMark("Q1", "D1", "", w), E_OK); EXPECT_EQ(w2, w); /** @@ -827,25 +828,25 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark001, TestSize. * @tc.expected: step6. E_OK */ WaterMark w3 = 3; - EXPECT_EQ(meta.SaveLocalWaterMark("D2", w3), E_OK); - EXPECT_EQ(meta.SavePeerWaterMark("D2", w3, true), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark("D2", "", w3), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D2", "", w3, true), E_OK); /** * @tc.steps: step7. get receive and send watermark * @tc.expected: step7. E_OK and get the w3 */ - EXPECT_EQ(meta.GetRecvQueryWaterMark("Q2", "D2", w), E_OK); + EXPECT_EQ(meta.GetRecvQueryWaterMark("Q2", "D2", "", w), E_OK); EXPECT_EQ(w3, w); - EXPECT_EQ(meta.GetSendQueryWaterMark("Q2", "D2", w), E_OK); + EXPECT_EQ(meta.GetSendQueryWaterMark("Q2", "D2", "", w), E_OK); EXPECT_EQ(w3, w); /** * @tc.steps: step8. get not exit receive and send watermark * @tc.expected: step8. E_OK and get the 0 */ - EXPECT_EQ(meta.GetRecvQueryWaterMark("Q3", "D3", w), E_OK); + EXPECT_EQ(meta.GetRecvQueryWaterMark("Q3", "D3", "", w), E_OK); EXPECT_EQ(w, 0u); - EXPECT_EQ(meta.GetSendQueryWaterMark("Q3", "D3", w), E_OK); + EXPECT_EQ(meta.GetSendQueryWaterMark("Q3", "D3", "", w), E_OK); EXPECT_EQ(w, 0u); } @@ -853,7 +854,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark001, TestSize. * @tc.name: GetQueryWaterMark 002 * @tc.desc: Test metaData save and get queryWaterMark after push or pull mode. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark002, TestSize.Level1) @@ -873,25 +874,25 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark002, TestSize. * @tc.expected: step2. E_OK */ WaterMark w1 = 2; - EXPECT_EQ(meta.SaveLocalWaterMark("D1", w1), E_OK); - EXPECT_EQ(meta.SavePeerWaterMark("D1", w1, true), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark("D1", "", w1), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D1", "", w1, true), E_OK); /** * @tc.steps: step2. save receive and send watermark * @tc.expected: step2. E_OK */ WaterMark w2 = 1; - EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D1", w2), E_OK); - EXPECT_EQ(meta.SetSendQueryWaterMark("Q1", "D1", w2), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D1", "", w2), E_OK); + EXPECT_EQ(meta.SetSendQueryWaterMark("Q1", "D1", "", w2), E_OK); /** * @tc.steps: step3. get receive and send watermark * @tc.expected: step3. E_OK and get the bigger value */ WaterMark w = 0; - EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", w), E_OK); + EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", "", w), E_OK); EXPECT_EQ(w1, w); - EXPECT_EQ(meta.GetSendQueryWaterMark("Q1", "D1", w), E_OK); + EXPECT_EQ(meta.GetSendQueryWaterMark("Q1", "D1", "", w), E_OK); EXPECT_EQ(w1, w); } @@ -912,13 +913,13 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark003, TestSize. const std::string DEVICE_B = "DEVICE_B"; TimeOffset offset = 100; // 100: offset - meta.SaveTimeOffset(DEVICE_B, offset); + meta.SaveTimeOffset(DEVICE_B, "", offset); WaterMark w1 = 2; // 2: watermark - meta.SavePeerWaterMark(DBCommon::TransferHashString(DEVICE_B), w1, false); + meta.SavePeerWaterMark(DBCommon::TransferHashString(DEVICE_B), "", w1, false); TimeOffset offsetGot; - meta.GetTimeOffset(DEVICE_B, offsetGot); + meta.GetTimeOffset(DEVICE_B, "", offsetGot); EXPECT_EQ(offsetGot, offset); } @@ -926,7 +927,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark003, TestSize. * @tc.name: GetDeleteWaterMark001 * @tc.desc: Test metaData save and get deleteWaterMark. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteWaterMark001, TestSize.Level1) @@ -949,17 +950,17 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteWaterMark001, TestSize const WaterMark maxWaterMark = 1000u; std::thread recvThread([&meta, &device, &maxWaterMark]() { for (WaterMark expectRecv = 0u; expectRecv < maxWaterMark; ++expectRecv) { - EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark(device, expectRecv), E_OK); + EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark(device, "", expectRecv), E_OK); WaterMark actualRecv = 0u; - EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark(device, actualRecv), E_OK); + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark(device, "", actualRecv), E_OK); EXPECT_EQ(actualRecv, expectRecv); } }); std::thread sendThread([&meta, &device, &maxWaterMark]() { for (WaterMark expectSend = 0u; expectSend < maxWaterMark; ++expectSend) { - EXPECT_EQ(meta.SetSendDeleteSyncWaterMark(device, expectSend), E_OK); + EXPECT_EQ(meta.SetSendDeleteSyncWaterMark(device, "", expectSend), E_OK); WaterMark actualSend = 0u; - EXPECT_EQ(meta.GetSendDeleteSyncWaterMark(device, actualSend), E_OK); + EXPECT_EQ(meta.GetSendDeleteSyncWaterMark(device, "", actualSend), E_OK); EXPECT_EQ(actualSend, expectSend); } }); @@ -971,7 +972,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteWaterMark001, TestSize * @tc.name: ClearQueryWaterMark 001 * @tc.desc: Test metaData clear watermark function. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark001, TestSize.Level1) @@ -991,7 +992,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark001, TestSiz * @tc.expected: step2. E_OK */ WaterMark w1 = 1; - EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D1", w1), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D1", "", w1), E_OK); /** * @tc.steps: step3. erase peer watermark @@ -1004,7 +1005,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark001, TestSiz * @tc.expected: step4. E_OK receive watermark is zero */ WaterMark w2 = -1; - EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", w2), E_OK); + EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", "", w2), E_OK); EXPECT_EQ(w2, 0u); /** @@ -1012,14 +1013,14 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark001, TestSiz * @tc.expected: step5. E_OK */ WaterMark w3 = 2; - EXPECT_EQ(meta.SavePeerWaterMark("D1", w3, true), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D1", "", w3, true), E_OK); /** * @tc.steps: step6. get receive watermark * @tc.expected: step6. E_OK receive watermark is peer watermark */ WaterMark w4 = -1; - EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", w4), E_OK); + EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", "", w4), E_OK); EXPECT_EQ(w4, w3); } @@ -1027,7 +1028,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark001, TestSiz * @tc.name: ClearQueryWaterMark 002 * @tc.desc: Test metaData clear watermark function. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark002, TestSize.Level1) @@ -1047,9 +1048,9 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark002, TestSiz * @tc.expected: step2. E_OK */ WaterMark w1 = 1; - EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D1", w1), E_OK); - EXPECT_EQ(meta.SetRecvQueryWaterMark("Q2", "D1", w1), E_OK); - EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D2", w1), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D1", "", w1), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark("Q2", "D1", "", w1), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D2", "", w1), E_OK); /** * @tc.steps: step3. erase peer watermark, make sure data remove in db @@ -1064,13 +1065,13 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark002, TestSiz * @tc.expected: step4. E_OK receive watermark is zero */ WaterMark w2 = -1; - EXPECT_EQ(anotherMeta.GetRecvQueryWaterMark("Q1", "D1", w2), E_OK); + EXPECT_EQ(anotherMeta.GetRecvQueryWaterMark("Q1", "D1", "", w2), E_OK); EXPECT_EQ(w2, 0u); w2 = -1; - EXPECT_EQ(anotherMeta.GetRecvQueryWaterMark("Q2", "D1", w2), E_OK); + EXPECT_EQ(anotherMeta.GetRecvQueryWaterMark("Q2", "D1", "", w2), E_OK); EXPECT_EQ(w2, 0u); w2 = -1; - EXPECT_EQ(anotherMeta.GetRecvQueryWaterMark("Q1", "D2", w2), E_OK); + EXPECT_EQ(anotherMeta.GetRecvQueryWaterMark("Q1", "D2", "", w2), E_OK); EXPECT_EQ(w2, w1); } @@ -1078,7 +1079,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark002, TestSiz * @tc.name: ClearQueryWaterMark 003 * @tc.desc: Test metaData clear watermark busy. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark003, TestSize.Level1) @@ -1103,7 +1104,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark003, TestSiz * @tc.name: GetQueryLastTimestamp001 * @tc.desc: Test function of GetQueryLastTimestamp. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryLastTimestamp001, TestSize.Level1) @@ -1191,7 +1192,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryLastTimestamp002, TestS * @tc.name: MetaDataExceptionBranch001 * @tc.desc: Test execption branch of meata data. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, MetaDataExceptionBranch001, TestSize.Level1) @@ -1207,7 +1208,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, MetaDataExceptionBranch001, Tes uint64_t val = 99; // 99 is the initial value of outValue uint64_t outValue = val; - meta.GetRemoveDataMark("D1", outValue); + meta.GetRemoveDataMark("D1", "", outValue); EXPECT_EQ(outValue, 0u); /** @@ -1215,21 +1216,21 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, MetaDataExceptionBranch001, Tes * @tc.expected: step2. out value = 0 */ outValue = val; - meta.GetDbCreateTime("D1", outValue); + meta.GetDbCreateTime("D1", "", outValue); EXPECT_EQ(outValue, 0u); /** * @tc.steps: step3. call ResetMetaDataAfterRemoveData with a device not in map * @tc.expected: step3. return -E_NOT_FOUND */ - EXPECT_EQ(meta.ResetMetaDataAfterRemoveData("D1"), -E_NOT_FOUND); + EXPECT_EQ(meta.ResetMetaDataAfterRemoveData("D1", ""), -E_NOT_FOUND); } /** * @tc.name: GetDeleteKeyWaterMark 001 * @tc.desc: Test metaData save and get deleteWaterMark. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteKeyWaterMark001, TestSize.Level1) @@ -1249,17 +1250,17 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteKeyWaterMark001, TestS * @tc.expected: step2. E_OK */ WaterMark w1 = 1; - EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark("D1", w1), E_OK); - EXPECT_EQ(meta.SetSendDeleteSyncWaterMark("D1", w1), E_OK); + EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark("D1", "", w1), E_OK); + EXPECT_EQ(meta.SetSendDeleteSyncWaterMark("D1", "", w1), E_OK); /** * @tc.steps: step3. get receive and send watermark * @tc.expected: step3. E_OK and get the latest value */ WaterMark w = 0; - EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", w), E_OK); + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", "", w), E_OK); EXPECT_EQ(w1, w); - EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D1", w), E_OK); + EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D1", "", w), E_OK); EXPECT_EQ(w1, w); /** @@ -1267,16 +1268,16 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteKeyWaterMark001, TestS * @tc.expected: step4. E_OK */ WaterMark w2 = 2; - EXPECT_EQ(meta.SaveLocalWaterMark("D1", w2), E_OK); - EXPECT_EQ(meta.SavePeerWaterMark("D1", w2, true), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark("D1", "", w2), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D1", "", w2, true), E_OK); /** * @tc.steps: step5. get receive and send watermark - * @tc.expected: step5. E_OK and get the w1 + * @tc.expected: step5. E_OK and get the w2 */ - EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", w), E_OK); + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", "", w), E_OK); EXPECT_EQ(w2, w); - EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D1", w), E_OK); + EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D1", "", w), E_OK); EXPECT_EQ(w2, w); /** @@ -1284,25 +1285,25 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteKeyWaterMark001, TestS * @tc.expected: step6. E_OK */ WaterMark w3 = 3; - EXPECT_EQ(meta.SaveLocalWaterMark("D2", w3), E_OK); - EXPECT_EQ(meta.SavePeerWaterMark("D2", w3, true), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark("D2", "", w3), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D2", "", w3, true), E_OK); /** * @tc.steps: step7. get receive and send watermark * @tc.expected: step7. E_OK and get the w3 */ - EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D2", w), E_OK); + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D2", "", w), E_OK); EXPECT_EQ(w3, w); - EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D2", w), E_OK); + EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D2", "", w), E_OK); EXPECT_EQ(w3, w); /** * @tc.steps: step8. get not exit receive and send watermark * @tc.expected: step8. E_OK and get the 0 */ - EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D3", w), E_OK); + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D3", "", w), E_OK); EXPECT_EQ(w, 0u); - EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D3", w), E_OK); + EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D3", "", w), E_OK); EXPECT_EQ(w, 0u); } @@ -1310,7 +1311,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteKeyWaterMark001, TestS * @tc.name: GetDeleteKeyWaterMark 002 * @tc.desc: Test metaData save and get deleteWaterMark after push or pull mode. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteKeyWaterMark002, TestSize.Level1) @@ -1330,25 +1331,25 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteKeyWaterMark002, TestS * @tc.expected: step2. E_OK */ WaterMark w1 = 3; - EXPECT_EQ(meta.SaveLocalWaterMark("D1", w1), E_OK); - EXPECT_EQ(meta.SavePeerWaterMark("D1", w1, true), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark("D1", "", w1), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D1", "", w1, true), E_OK); /** * @tc.steps: step2. save receive and send watermark * @tc.expected: step2. E_OK */ WaterMark w2 = 1; - EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark("D1", w2), E_OK); - EXPECT_EQ(meta.SetSendDeleteSyncWaterMark("D1", w2), E_OK); + EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark("D1", "", w2), E_OK); + EXPECT_EQ(meta.SetSendDeleteSyncWaterMark("D1", "", w2), E_OK); /** * @tc.steps: step3. get receive and send watermark * @tc.expected: step3. E_OK and get the bigger value */ WaterMark w = 0; - EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", w), E_OK); + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", "", w), E_OK); EXPECT_EQ(w1, w); - EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D1", w), E_OK); + EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D1", "", w), E_OK); EXPECT_EQ(w1, w); } @@ -1356,7 +1357,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteKeyWaterMark002, TestS * @tc.name: ClearDeleteKeyWaterMark 001 * @tc.desc: Test metaData clear watermark function. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearDeleteKeyWaterMark001, TestSize.Level1) @@ -1376,7 +1377,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearDeleteKeyWaterMark001, Tes * @tc.expected: step2. E_OK */ WaterMark w1 = 1; - EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark("D1", w1), E_OK); + EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark("D1", "", w1), E_OK); /** * @tc.steps: step3. erase peer watermark @@ -1389,7 +1390,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearDeleteKeyWaterMark001, Tes * @tc.expected: step4. E_OK receive watermark is zero */ WaterMark w2 = -1; - EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", w2), E_OK); + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", "", w2), E_OK); EXPECT_EQ(w2, 0u); /** @@ -1397,14 +1398,14 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearDeleteKeyWaterMark001, Tes * @tc.expected: step5. E_OK */ WaterMark w3 = 2; - EXPECT_EQ(meta.SavePeerWaterMark("D1", w3, true), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D1", "", w3, true), E_OK); /** * @tc.steps: step6. get receive watermark * @tc.expected: step6. E_OK receive watermark is peer watermark */ WaterMark w4 = -1; - EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", w4), E_OK); + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", "", w4), E_OK); EXPECT_EQ(w4, w3); } @@ -1412,7 +1413,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearDeleteKeyWaterMark001, Tes * @tc.name: VerifyCacheAndDb 001 * @tc.desc: Test metaData watermark cache and db are consistent and correct. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDataQuerySync001, TestSize.Level1) @@ -1435,16 +1436,16 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDataQuerySync001, Tes * @tc.expected: step2. E_OK */ WaterMark deleteWaterMark = 1; - EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark(deviceId, deleteWaterMark), E_OK); - EXPECT_EQ(meta.SetSendDeleteSyncWaterMark(deviceId, deleteWaterMark), E_OK); + EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark(deviceId, "", deleteWaterMark), E_OK); + EXPECT_EQ(meta.SetSendDeleteSyncWaterMark(deviceId, "", deleteWaterMark), E_OK); /** * @tc.steps: step3. save querySync watermark * @tc.expected: step2. E_OK */ WaterMark queryWaterMark = 2; - EXPECT_EQ(meta.SetRecvQueryWaterMark(queryId, deviceId, queryWaterMark), E_OK); - EXPECT_EQ(meta.SetSendQueryWaterMark(queryId, deviceId, queryWaterMark), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark(queryId, deviceId, "", queryWaterMark), E_OK); + EXPECT_EQ(meta.SetSendQueryWaterMark(queryId, deviceId, "", queryWaterMark), E_OK); /** * @tc.steps: step4. initialize meta with storage @@ -1458,18 +1459,18 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDataQuerySync001, Tes * @tc.expected: step5. E_OK and waterMark equal to deleteWaterMark */ WaterMark waterMark; - EXPECT_EQ(anotherMeta.GetRecvDeleteSyncWaterMark(deviceId, waterMark), E_OK); + EXPECT_EQ(anotherMeta.GetRecvDeleteSyncWaterMark(deviceId, "", waterMark), E_OK); EXPECT_EQ(waterMark, deleteWaterMark); - EXPECT_EQ(anotherMeta.GetSendDeleteSyncWaterMark(deviceId, waterMark), E_OK); + EXPECT_EQ(anotherMeta.GetSendDeleteSyncWaterMark(deviceId, "", waterMark), E_OK); EXPECT_EQ(waterMark, deleteWaterMark); /** * @tc.steps: step6. verify query sync data * @tc.expected: step6. E_OK and waterMark equal to queryWaterMark */ - EXPECT_EQ(anotherMeta.GetRecvQueryWaterMark(queryId, deviceId, waterMark), E_OK); + EXPECT_EQ(anotherMeta.GetRecvQueryWaterMark(queryId, deviceId, "", waterMark), E_OK); EXPECT_EQ(waterMark, queryWaterMark); - EXPECT_EQ(anotherMeta.GetSendQueryWaterMark(queryId, deviceId, waterMark), E_OK); + EXPECT_EQ(anotherMeta.GetSendQueryWaterMark(queryId, deviceId, "", waterMark), E_OK); EXPECT_EQ(waterMark, queryWaterMark); } @@ -1477,7 +1478,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDataQuerySync001, Tes * @tc.name: VerifyLruMap 001 * @tc.desc: Test metaData watermark cache lru ability. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyLruMap001, TestSize.Level1) @@ -1529,7 +1530,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyLruMap001, TestSize.Level * @tc.name: VerifyMetaDataInit 001 * @tc.desc: Test metaData init correctly * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDataInit001, TestSize.Level1) @@ -1551,12 +1552,12 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDataInit001, TestSize * @tc.steps: step2. meta save and get waterMark * @tc.expected: step2. expect get the same waterMark */ - EXPECT_EQ(meta.SaveLocalWaterMark(deviceA, setWaterMark), E_OK); - EXPECT_EQ(meta.SaveLocalWaterMark(deviceB, setWaterMark), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark(deviceA, "", setWaterMark), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark(deviceB, "", setWaterMark), E_OK); WaterMark getWaterMark = 0; - meta.GetLocalWaterMark(deviceA, getWaterMark); + meta.GetLocalWaterMark(deviceA, "", getWaterMark); EXPECT_EQ(getWaterMark, setWaterMark); - meta.GetLocalWaterMark(deviceB, getWaterMark); + meta.GetLocalWaterMark(deviceB, "", getWaterMark); EXPECT_EQ(getWaterMark, setWaterMark); @@ -1571,9 +1572,9 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDataInit001, TestSize * @tc.steps: step4. get waterMark again * @tc.expected: step4. expect get the same waterMark */ - anotherMeta.GetLocalWaterMark(deviceA, getWaterMark); + anotherMeta.GetLocalWaterMark(deviceA, "", getWaterMark); EXPECT_EQ(getWaterMark, setWaterMark); - anotherMeta.GetLocalWaterMark(deviceB, getWaterMark); + anotherMeta.GetLocalWaterMark(deviceB, "", getWaterMark); EXPECT_EQ(getWaterMark, setWaterMark); } @@ -1594,7 +1595,7 @@ void InitVerifyStorageEnvironment(Metadata &meta, VirtualSingleVerSyncDBInterfac for (uint32_t i = startCount; i < maxStoreItems; i++) { std::string queryId = std::to_string(i); WaterMark recvWaterMark = i + 1; - EXPECT_EQ(meta.SetRecvQueryWaterMark(queryId, deviceId, recvWaterMark), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark(queryId, deviceId, "", recvWaterMark), E_OK); } } } @@ -1603,7 +1604,7 @@ void InitVerifyStorageEnvironment(Metadata &meta, VirtualSingleVerSyncDBInterfac * @tc.name: VerifyManagerQuerySyncStorage 001 * @tc.desc: Test metaData remove least used querySync storage items. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage001, TestSize.Level3) @@ -1622,7 +1623,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage00 */ std::string newQueryId = std::to_string(maxStoreItems); WaterMark newWaterMark = maxStoreItems + 1; - EXPECT_EQ(meta.SetRecvQueryWaterMark(newQueryId, deviceId, newWaterMark), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark(newQueryId, deviceId, "", newWaterMark), E_OK); /** * @tc.steps: step4. touch the first item @@ -1630,7 +1631,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage00 */ std::string firstItemKey = std::to_string(startCount); WaterMark firstWaterMark = 11u; - EXPECT_EQ(meta.SetRecvQueryWaterMark(firstItemKey, deviceId, firstWaterMark), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark(firstItemKey, deviceId, "", firstWaterMark), E_OK); /** * @tc.steps: step5. initialize new meta with storage @@ -1644,7 +1645,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage00 * @tc.expected: step6. E_OK it still exist */ WaterMark exceptWaterMark; - EXPECT_EQ(newMeta.GetRecvQueryWaterMark(firstItemKey, deviceId, exceptWaterMark), E_OK); + EXPECT_EQ(newMeta.GetRecvQueryWaterMark(firstItemKey, deviceId, "", exceptWaterMark), E_OK); EXPECT_EQ(exceptWaterMark, firstWaterMark); /** @@ -1653,7 +1654,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage00 */ WaterMark secondWaterMark; std::string secondQueryId = std::to_string(startCount + 1); - EXPECT_EQ(newMeta.GetRecvQueryWaterMark(secondQueryId, deviceId, secondWaterMark), E_OK); + EXPECT_EQ(newMeta.GetRecvQueryWaterMark(secondQueryId, deviceId, "", secondWaterMark), E_OK); EXPECT_EQ(secondWaterMark, 0u); } @@ -1661,7 +1662,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage00 * @tc.name: VerifyMetaDbCreateTime 001 * @tc.desc: Test metaData get and set cbCreateTime. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDbCreateTime001, TestSize.Level1) @@ -1679,33 +1680,33 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDbCreateTime001, Test * @tc.expected: step4. E_OK */ WaterMark value = 2; - EXPECT_EQ(meta.SaveLocalWaterMark("D1", value), E_OK); - EXPECT_EQ(meta.SavePeerWaterMark("D1", value, true), E_OK); - EXPECT_EQ(meta.SetDbCreateTime("D1", 10u, true), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark("D1", "", value), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D1", "", value, true), E_OK); + EXPECT_EQ(meta.SetDbCreateTime("D1", "", 10u, true), E_OK); /** * @tc.steps: step3. check peer and local watermark and dbCreateTime * @tc.expected: step4. E_OK */ WaterMark curValue = 0; - meta.GetLocalWaterMark("D1", curValue); + meta.GetLocalWaterMark("D1", "", curValue); EXPECT_EQ(value, curValue); - meta.GetPeerWaterMark("D1", curValue); + meta.GetPeerWaterMark("D1", "", curValue); EXPECT_EQ(value, curValue); uint64_t curDbCreatTime = 0; - meta.GetDbCreateTime("D1", curDbCreatTime); + meta.GetDbCreateTime("D1", "", curDbCreatTime); EXPECT_EQ(curDbCreatTime, 10u); /** * @tc.steps: step3. change dbCreateTime and check * @tc.expected: step4. E_OK */ - EXPECT_EQ(meta.SetDbCreateTime("D1", 20u, true), E_OK); + EXPECT_EQ(meta.SetDbCreateTime("D1", "", 20u, true), E_OK); uint64_t clearDeviceDataMark = INT_MAX; - meta.GetRemoveDataMark("D1", clearDeviceDataMark); + meta.GetRemoveDataMark("D1", "", clearDeviceDataMark); EXPECT_EQ(clearDeviceDataMark, 1u); - EXPECT_EQ(meta.ResetMetaDataAfterRemoveData("D1"), E_OK); - meta.GetRemoveDataMark("D1", clearDeviceDataMark); + EXPECT_EQ(meta.ResetMetaDataAfterRemoveData("D1", ""), E_OK); + meta.GetRemoveDataMark("D1", "", clearDeviceDataMark); EXPECT_EQ(clearDeviceDataMark, 0u); - meta.GetDbCreateTime("D1", curDbCreatTime); + meta.GetDbCreateTime("D1", "", curDbCreatTime); EXPECT_EQ(curDbCreatTime, 20u); } @@ -1713,7 +1714,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDbCreateTime001, Test * @tc.name: VerifyManagerQuerySyncStorage 002 * @tc.desc: Test metaData remove least used querySync storage items when exit wrong data. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage002, TestSize.Level3) @@ -1750,7 +1751,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage00 */ std::string firstItemKey = std::to_string(startCount); WaterMark exceptWaterMark; - EXPECT_EQ(newMeta.GetRecvQueryWaterMark(firstItemKey, deviceId, exceptWaterMark), E_OK); + EXPECT_EQ(newMeta.GetRecvQueryWaterMark(firstItemKey, deviceId, "", exceptWaterMark), E_OK); EXPECT_EQ(exceptWaterMark, 1u); } @@ -1758,7 +1759,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage00 * @tc.name: AllPredicateQuerySync001 * @tc.desc: Test normal push sync for AllPredicate data. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync001, TestSize.Level1) @@ -1826,7 +1827,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync001, TestS * @tc.name: AllPredicateQuerySync002 * @tc.desc: Test wrong query param push sync for AllPredicate data. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync002, TestSize.Level1) @@ -1857,7 +1858,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync002, TestS * @tc.name: AllPredicateQuerySync003 * @tc.desc: Test normal push sync for AllPredicate data with limit * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync003, TestSize.Level1) @@ -1924,7 +1925,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync003, TestS * @tc.name: AllPredicateQuerySync004 * @tc.desc: Test normal pull sync for AllPredicate data. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync004, TestSize.Level1) @@ -1933,7 +1934,6 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync004, TestS * @tc.steps: step1. InitSchemaDb */ InitSchemaDb(); - DBStatus status = OK; std::vector devices; devices.push_back(g_deviceB->GetDeviceId()); @@ -1946,10 +1946,8 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync004, TestS for (int i = 0; i < dataSize; i++) { key.push_back(i); g_deviceB->PutData(key, value, 10 + i, 0); - ASSERT_TRUE(status == OK); key.pop_back(); } - ASSERT_TRUE(status == OK); /** * @tc.steps: step3. deviceA call query sync and wait @@ -1957,7 +1955,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync004, TestS */ Query query = Query::Select().EqualTo("$.field_name1", 1); std::map result; - status = g_tool.SyncTest(g_schemaKvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result, query); + DBStatus status = g_tool.SyncTest(g_schemaKvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result, query); ASSERT_TRUE(status == OK); /** diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_simple_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_simple_sync_test.cpp index 929482aa0fa44b24e7d46994e55e5dd2193ee588..91360daec6d516c238152c7e30d414e187385e96 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_simple_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_simple_sync_test.cpp @@ -795,7 +795,7 @@ HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, NormalSync010, TestSize.Level1 * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, NormalSync011, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, NormalSync011, TestSize.Level1) { DBStatus status = OK; std::vector devices; @@ -845,7 +845,7 @@ HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, NormalSync011, TestSize.Level0 * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, NormalSync012, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, NormalSync012, TestSize.Level1) { /** * @tc.steps: step1. prepare env @@ -1019,7 +1019,6 @@ HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, LimitDataSync002, TestSize.Lev ASSERT_TRUE(result.size() == devices.size()); for (const auto &pair : result) { LOGD("dev %s, status %d", pair.first.c_str(), pair.second); - printf("dev %s, status %d", pair.first.c_str(), pair.second); EXPECT_TRUE(pair.second == OK); } } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subscribe_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subscribe_sync_test.cpp index bb9b2db60f36514e6558a5e40f431bed6e5c7f25..12499bdc5c6ec1de74e194245a0cb74f12733400 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subscribe_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subscribe_sync_test.cpp @@ -149,11 +149,13 @@ void DistributedDBSingleVerP2PSubscribeSyncTest::SetUp(void) ASSERT_TRUE(g_deviceB != nullptr); VirtualSingleVerSyncDBInterface *syncInterfaceB = new (std::nothrow) VirtualSingleVerSyncDBInterface(); ASSERT_TRUE(syncInterfaceB != nullptr); + syncInterfaceB->SetSchemaInfo(SCHEMA_STRING); ASSERT_EQ(g_deviceB->Initialize(g_communicatorAggregator, syncInterfaceB), E_OK); g_deviceC = new (std::nothrow) KvVirtualDevice(DEVICE_C); ASSERT_TRUE(g_deviceC != nullptr); VirtualSingleVerSyncDBInterface *syncInterfaceC = new (std::nothrow) VirtualSingleVerSyncDBInterface(); ASSERT_TRUE(syncInterfaceC != nullptr); + syncInterfaceC->SetSchemaInfo(SCHEMA_STRING); ASSERT_EQ(g_deviceC->Initialize(g_communicatorAggregator, syncInterfaceC), E_OK); } @@ -1134,6 +1136,7 @@ KvVirtualDevice *CreateKvVirtualDevice(const std::string &deviceName) device = nullptr; break; } + interface->SetSchemaInfo(SCHEMA_STRING); EXPECT_EQ(device->Initialize(g_communicatorAggregator, interface), E_OK); } while (false); return device; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp index c0c4c4a2f654f1a08ce9a36d8349cfc2fe517b74..39f9c1852eefdba0fa73f2ed1ae0a52e59945795 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp @@ -399,7 +399,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck005, TestSize.Lev * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck006, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck006, TestSize.Level1) { ASSERT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr), OK); ASSERT_EQ(g_mgr.DeleteKvStore(STORE_ID), OK); @@ -445,7 +445,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck006, TestSize.Lev * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck007, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck007, TestSize.Level1) { /** * @tc.steps: step1. fork check device security ability @@ -483,7 +483,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck007, TestSize.Lev * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck008, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck008, TestSize.Level1) { auto adapter = std::make_shared(); RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(adapter); @@ -928,7 +928,7 @@ void DistributedDBSingleVerP2PSyncCheckTest::CancelTestEnd(std::vector &e * @tc.require: * @tc.author: lijun */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcessCancel001, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcessCancel001, TestSize.Level1) { DeviceSyncOption option; std::vector entries; @@ -2082,7 +2082,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, DelaySync001, TestSize.Level3) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVAbilitySyncOpt001, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVAbilitySyncOpt001, TestSize.Level1) { /** * @tc.steps: step1. record packet @@ -2181,7 +2181,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt001, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt002, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt002, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -2232,7 +2232,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt002, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt003, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt003, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -2269,7 +2269,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt003, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt004, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt004, TestSize.Level1) { /** * @tc.steps: step1. deviceA call sync and wait @@ -2305,7 +2305,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt004, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt005, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt005, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -2340,7 +2340,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt005, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt006, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt006, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -2385,7 +2385,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt006, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt007, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt007, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -2406,6 +2406,8 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt007, TestSize.Level0) CipherPassword passwd; EXPECT_EQ(g_kvDelegatePtr->Export(singleExportFileName, passwd), OK); EXPECT_EQ(g_kvDelegatePtr->Import(singleExportFileName, passwd), OK); + // Wait until all the packets arrive. + std::this_thread::sleep_for(std::chrono::seconds(1)); /** * @tc.steps: step4. reopen kv store and sync again * @tc.expected: step4. reopen OK and sync success, no negotiation packet. @@ -2423,7 +2425,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt007, TestSize.Level0) * @tc.require: * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt008, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt008, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -2460,7 +2462,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt008, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVTimeChange001, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVTimeChange001, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -2498,6 +2500,164 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVTimeChange001, TestSize.Level g_communicatorAggregator->RegOnDispatch(nullptr); } +/** + * @tc.name: KVSyncOpt009 + * @tc.desc: check resync when message return E_FEEDBACK_DB_CLOSING + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt009, TestSize.Level0) +{ + /** + * @tc.steps: step1. ack message return E_FEEDBACK_DB_CLOSING once + */ + std::atomic messageCount = 0; + bool isResync = false; + g_communicatorAggregator->RegOnDispatch([&isResync, &messageCount](const std::string &dev, Message *msg) { + if (dev != DEVICE_B && msg->GetMessageType() == TYPE_RESPONSE && !isResync) { + msg->SetErrorNo(E_FEEDBACK_DB_CLOSING); + isResync = true; + } + messageCount++; + }); + /** + * @tc.steps: step2. deviceA call sync and wait + * @tc.expected: step2. sync should return OK. + */ + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + Sync(devices, OK); + int pkCnt = 8; + EXPECT_EQ(messageCount, pkCnt); + EXPECT_TRUE(isResync); + g_communicatorAggregator->RegOnDispatch(nullptr); +} + +/** + * @tc.name: KVSyncOpt010 + * @tc.desc: check resync limit exceeded + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt010, TestSize.Level0) +{ + /** + * @tc.steps: step1. ack message always return E_FEEDBACK_DB_CLOSING + */ + std::atomic messageCount = 0; + g_communicatorAggregator->RegOnDispatch([&messageCount](const std::string &dev, Message *msg) { + if (dev != DEVICE_B && msg->GetMessageType() == TYPE_RESPONSE) { + msg->SetErrorNo(E_FEEDBACK_DB_CLOSING); + } + messageCount++; + }); + /** + * @tc.steps: step2. deviceA call sync and wait + * @tc.expected: step2. sync should ignore E_FEEDBACK_DB_CLOSING when exceeded resync limit + */ + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + Sync(devices, OK); + int pkCnt = 8; + EXPECT_EQ(messageCount, pkCnt); + g_communicatorAggregator->RegOnDispatch(nullptr); +} + +/** + * @tc.name: KVSyncOpt011 + * @tc.desc: check close db return busy + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt011, TestSize.Level2) +{ + /** + * @tc.steps: step1. deviceA call sync and wait on RegOnDispatch + * @tc.expected: step1. sync should return OK. + */ + std::atomic messageCount = 0; + std::atomic signo = 0; + std::mutex mutex; + std::condition_variable cv; + int waitTime = 2; + g_communicatorAggregator->RegOnDispatch([&messageCount, &signo, &mutex, &cv, waitTime]( + const std::string &dev, Message *msg) { + messageCount++; + if (messageCount.load() == 1) { // 1 is onDispatch times + std::unique_lock lock(mutex); + signo++; + cv.notify_one(); + cv.wait_for(lock, std::chrono::seconds(waitTime), [&signo]() { + return signo == 2; // 2 is notify times + }); + } + }); + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + std::thread t1([&devices]() { + Sync(devices, OK); + }); + + /** + * @tc.steps: step2. close db + * @tc.expected: step2. return BUSY. + */ + { + std::unique_lock lock(mutex); + cv.wait_for(lock, std::chrono::seconds(waitTime), [&signo]() { + return signo == 1; // 1 is notify times + }); + } + EXPECT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr, false), BUSY); + { + std::unique_lock lock(mutex); + signo++; + cv.notify_one(); + } + t1.join(); + /** + * @tc.steps: step3. wait task count to 0, close db + * @tc.expected: step3. return OK. + */ + std::this_thread::sleep_for(std::chrono::seconds(waitTime)); + g_communicatorAggregator->RegOnDispatch(nullptr); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr, false), OK); + g_kvDelegatePtr = nullptr; + ASSERT_TRUE(g_mgr.DeleteKvStore(STORE_ID) == OK); +} + +/** + * @tc.name: KVSyncOpt012 + * @tc.desc: check message errcode always E_FEEDBACK_DB_CLOSING + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt012, TestSize.Level0) +{ + /** + * @tc.steps: step1. message always return E_FEEDBACK_DB_CLOSING + */ + std::atomic messageCount = 0; + g_communicatorAggregator->RegOnDispatch([&messageCount](const std::string &dev, Message *msg) { + msg->SetErrorNo(E_FEEDBACK_DB_CLOSING); + messageCount++; + }); + /** + * @tc.steps: step2. deviceA call sync and wait + * @tc.expected: step2. sync should ignore E_FEEDBACK_DB_CLOSING when exceeded resync limit + */ + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + Sync(devices, OK); + int pkCnt = 8; + EXPECT_EQ(messageCount, pkCnt); + g_communicatorAggregator->RegOnDispatch(nullptr); +} + /** * @tc.name: KVTimeChange002 * @tc.desc: test NotifyTimestampChanged will not stuck when notify delegate with no metadata @@ -2505,7 +2665,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVTimeChange001, TestSize.Level * @tc.require: * @tc.author: liuhongyang */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVTimeChange002, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVTimeChange002, TestSize.Level1) { /** * @tc.steps: step1. open a new store with STORE_ID_3 diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_syncer_device_manager_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_syncer_device_manager_test.cpp index 5b76ae62ff7f00790c2efa2a3eb607f040d57509..f50e74d6cc6153962a391a75042e2df32c8f6c6f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_syncer_device_manager_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_syncer_device_manager_test.cpp @@ -122,7 +122,7 @@ void DistributedDBSyncerDeviceManagerTest::TearDown(void) * @tc.name: Online Callback 001 * @tc.desc: Test DeviceManager device online callback function. * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSyncerDeviceManagerTest, OnlineCallback001, TestSize.Level0) @@ -152,7 +152,7 @@ HWTEST_F(DistributedDBSyncerDeviceManagerTest, OnlineCallback001, TestSize.Level * @tc.name: Offline Callback 001 * @tc.desc: Test DeviceManager device offline callback function. * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSyncerDeviceManagerTest, OfflineCallback001, TestSize.Level0) @@ -182,7 +182,7 @@ HWTEST_F(DistributedDBSyncerDeviceManagerTest, OfflineCallback001, TestSize.Leve * @tc.name: Get Devices 001 * @tc.desc: Test DeviceManager GetDevices function. * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSyncerDeviceManagerTest, GetDevices001, TestSize.Level0) @@ -213,7 +213,7 @@ HWTEST_F(DistributedDBSyncerDeviceManagerTest, GetDevices001, TestSize.Level0) * @tc.name: Send BroadCast 001 * @tc.desc: Test DeviceManager SendBroadCast function. * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSyncerDeviceManagerTest, SendBroadCast001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_time_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_time_sync_test.cpp index 245e10744b9a185150a56aea1175c7938ab4b596..239af306a564f27c318bbde2414a0eed1b24a1cd 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_time_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_time_sync_test.cpp @@ -130,7 +130,7 @@ void DistributedDBTimeSyncTest::TearDown(void) * @tc.name: NormalSync001 * @tc.desc: Verify time sync function is normal between two time sync instance with different timestamp. * @tc.type: FUNC - * @tc.require: AR000C05EP AR000CQE0G + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBTimeSyncTest, NormalSync001, TestSize.Level0) @@ -148,7 +148,7 @@ HWTEST_F(DistributedDBTimeSyncTest, NormalSync001, TestSize.Level0) TimeHelper::GetSysCurrentTime() + TimeHelper::BASE_OFFSET + offsetA, 0); int errCode; // initialize timeSyncA - errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_TRUE(errCode == E_OK); g_metadataB->Initialize(g_syncInterfaceB); @@ -157,13 +157,13 @@ HWTEST_F(DistributedDBTimeSyncTest, NormalSync001, TestSize.Level0) g_syncInterfaceB->PutData(DistributedDBUnitTest::KEY_1, DistributedDBUnitTest::VALUE_1, TimeHelper::GetSysCurrentTime() + TimeHelper::BASE_OFFSET + offsetB, 0); // initialize timeSyncB - errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A); + errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A, ""); EXPECT_TRUE(errCode == E_OK); /** * @tc.steps: step3. Register the OnMessageCallback to virtual communicator */ - g_syncTaskContext->Initialize(DEVICE_B, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); + g_syncTaskContext->Initialize({DEVICE_B, ""}, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); g_virtualCommunicator->SetTimeSync(g_timeSyncA.get(), g_timeSyncB.get(), DEVICE_A, g_syncTaskContext); /** @@ -181,7 +181,7 @@ HWTEST_F(DistributedDBTimeSyncTest, NormalSync001, TestSize.Level0) * @tc.name: NormalSync002 * @tc.desc: Verify time sync function is normal between two time sync instance with the same timestamp. * @tc.type: FUNC - * @tc.require: AR000C05EP AR000CQE0G + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBTimeSyncTest, NormalSync002, TestSize.Level0) @@ -193,17 +193,17 @@ HWTEST_F(DistributedDBTimeSyncTest, NormalSync002, TestSize.Level0) g_metadataA->Initialize(g_syncInterfaceA); int errCode; // initialize timeSyncA - errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_TRUE(errCode == E_OK); g_metadataB->Initialize(g_syncInterfaceB); // initialize timeSyncB - errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A); + errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A, ""); EXPECT_TRUE(errCode == E_OK); /** * @tc.steps: step2. Register the OnMessageCallback to virtual communicator */ - g_syncTaskContext->Initialize(DEVICE_B, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); + g_syncTaskContext->Initialize({DEVICE_B, ""}, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); g_virtualCommunicator->SetTimeSync(g_timeSyncA.get(), g_timeSyncB.get(), DEVICE_A, g_syncTaskContext); /** * @tc.steps: step3. Fetch timeOffset value @@ -220,7 +220,7 @@ HWTEST_F(DistributedDBTimeSyncTest, NormalSync002, TestSize.Level0) * @tc.name: NormalSync003 * @tc.desc: Verify time sync function is normal between two time sync instance with different localTimeOffset. * @tc.type: FUNC - * @tc.require: AR000C05EP AR000CQE0G + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBTimeSyncTest, NormalSync003, TestSize.Level0) @@ -239,7 +239,7 @@ HWTEST_F(DistributedDBTimeSyncTest, NormalSync003, TestSize.Level0) int errCode; // initialize timeSyncA - errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_TRUE(errCode == E_OK); // set timeOffset for timeSyncA @@ -248,12 +248,12 @@ HWTEST_F(DistributedDBTimeSyncTest, NormalSync003, TestSize.Level0) g_metadataB->SaveLocalTimeOffset(offsetB); // initialize timeSyncB - errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A); + errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A, ""); EXPECT_TRUE(errCode == E_OK); /** * @tc.steps: step3. Register the OnMessageCallback to virtual communicator */ - g_syncTaskContext->Initialize(DEVICE_B, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); + g_syncTaskContext->Initialize({DEVICE_B, ""}, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); g_virtualCommunicator->SetTimeSync(g_timeSyncA.get(), g_timeSyncB.get(), DEVICE_A, g_syncTaskContext); /** * @tc.steps: step4. Fetch timeOffset value @@ -270,7 +270,7 @@ HWTEST_F(DistributedDBTimeSyncTest, NormalSync003, TestSize.Level0) * @tc.name: NetDisconnetSyncTest001 * @tc.desc: Verify time sync function return failed when the virtual communicator disabled. * @tc.type: FUNC - * @tc.require: AR000C05EP AR000CQE0G + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBTimeSyncTest, NetDisconnetSyncTest001, TestSize.Level0) @@ -282,15 +282,15 @@ HWTEST_F(DistributedDBTimeSyncTest, NetDisconnetSyncTest001, TestSize.Level0) g_metadataA->Initialize(g_syncInterfaceA); int errCode; // initialize timeSyncA - errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_TRUE(errCode == E_OK); g_metadataB->Initialize(g_syncInterfaceB); // initialize timeSyncB - errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A); + errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A, ""); EXPECT_TRUE(errCode == E_OK); - g_syncTaskContext->Initialize(DEVICE_B, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); + g_syncTaskContext->Initialize({DEVICE_B, ""}, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); g_virtualCommunicator->SetTimeSync(g_timeSyncA.get(), g_timeSyncB.get(), DEVICE_A, g_syncTaskContext); /** * @tc.steps: step2. Disable the virtual communicator @@ -308,7 +308,7 @@ HWTEST_F(DistributedDBTimeSyncTest, NetDisconnetSyncTest001, TestSize.Level0) * @tc.name: InvalidMessgeTest001 * @tc.desc: Verify RequestReceive() return failed with invalid input. * @tc.type: FUNC - * @tc.require: AR000C05EP AR000CQE0G + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBTimeSyncTest, InvalidMessgeTest001, TestSize.Level0) @@ -320,12 +320,12 @@ HWTEST_F(DistributedDBTimeSyncTest, InvalidMessgeTest001, TestSize.Level0) g_metadataA->Initialize(g_syncInterfaceA); int errCode; // initialize timeSyncA - errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_TRUE(errCode == E_OK); g_metadataB->Initialize(g_syncInterfaceB); // initialize timeSyncB - errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A); + errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A, ""); EXPECT_TRUE(errCode == E_OK); g_virtualCommunicator->SetTimeSync(g_timeSyncA.get(), g_timeSyncB.get(), DEVICE_A, g_syncTaskContext); @@ -339,7 +339,7 @@ HWTEST_F(DistributedDBTimeSyncTest, InvalidMessgeTest001, TestSize.Level0) */ msg->SetMessageId(TIME_SYNC_MESSAGE); msg->SetMessageType(TYPE_REQUEST); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; errCode = g_virtualCommunicator->SendMessage(DEVICE_B, msg, conf); EXPECT_TRUE(errCode == -E_INVALID_ARGS); @@ -376,7 +376,7 @@ HWTEST_F(DistributedDBTimeSyncTest, InvalidMessgeTest001, TestSize.Level0) * @tc.name: InvalidMessgeTest002 * @tc.desc: Verify AckRec() return failed with invalid input. * @tc.type: FUNC - * @tc.require: AR000C05EP AR000CQE0G + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBTimeSyncTest, InvalidMessgeTest002, TestSize.Level0) @@ -388,14 +388,14 @@ HWTEST_F(DistributedDBTimeSyncTest, InvalidMessgeTest002, TestSize.Level0) g_metadataA->Initialize(g_syncInterfaceA); int errCode; // initialize timeSyncA - errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_TRUE(errCode == E_OK); g_metadataB->Initialize(g_syncInterfaceB); // initialize timeSyncB - errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A); + errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A, ""); EXPECT_TRUE(errCode == E_OK); - g_syncTaskContext->Initialize(DEVICE_B, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); + g_syncTaskContext->Initialize({DEVICE_B, ""}, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); g_virtualCommunicator->SetTimeSync(g_timeSyncA.get(), g_timeSyncB.get(), DEVICE_A, g_syncTaskContext); Message *msg = new (std::nothrow) Message(); @@ -407,7 +407,7 @@ HWTEST_F(DistributedDBTimeSyncTest, InvalidMessgeTest002, TestSize.Level0) */ msg->SetMessageId(TIME_SYNC_MESSAGE); msg->SetMessageType(TYPE_RESPONSE); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; errCode = g_virtualCommunicator->SendMessage(DEVICE_A, msg, conf); EXPECT_TRUE(errCode == -E_INVALID_ARGS); @@ -444,7 +444,7 @@ HWTEST_F(DistributedDBTimeSyncTest, InvalidMessgeTest002, TestSize.Level0) * @tc.name: SyncTimeout001 * @tc.desc: Verify the timeout scenario for time sync. * @tc.type: FUNC - * @tc.require: AR000C05EP AR000CQE0G + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBTimeSyncTest, SyncTimeout001, TestSize.Level2) @@ -452,14 +452,14 @@ HWTEST_F(DistributedDBTimeSyncTest, SyncTimeout001, TestSize.Level2) // initialize timeSyncA g_metadataA->Initialize(g_syncInterfaceA); int errCode; - errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_TRUE(errCode == E_OK); /** * @tc.steps: step1. Initialize the syncTaskContext * @tc.expected: step1. Initialize syncTaskContext successfully */ - errCode = g_syncTaskContext->Initialize(DEVICE_B, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); + errCode = g_syncTaskContext->Initialize({DEVICE_B, ""}, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); EXPECT_TRUE(errCode == E_OK); /** * @tc.steps: step2. Start the time syc task invoking StartSync() method @@ -481,14 +481,14 @@ HWTEST_F(DistributedDBTimeSyncTest, CheckRemoteVersion001, TestSize.Level0) { // initialize timeSyncA g_metadataA->Initialize(g_syncInterfaceA); - int errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + int errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_EQ(errCode, E_OK); /** * @tc.steps: step1. Initialize the syncTaskContext * @tc.expected: step1. Initialize syncTaskContext successfully */ - errCode = g_syncTaskContext->Initialize(DEVICE_B, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); + errCode = g_syncTaskContext->Initialize({DEVICE_B, ""}, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); EXPECT_EQ(errCode, E_OK); /** * @tc.steps: step2. Check remote version @@ -512,18 +512,18 @@ HWTEST_F(DistributedDBTimeSyncTest, SetTimeSyncFinish001, TestSize.Level0) * @tc.expected: step1. Initialize successfully */ EXPECT_EQ(g_metadataA->Initialize(g_syncInterfaceA), E_OK); - EXPECT_EQ(g_metadataA->SetTimeSyncFinishMark(DEVICE_B, true), E_OK); - int errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + EXPECT_EQ(g_metadataA->SetTimeSyncFinishMark(DEVICE_B, "", true), E_OK); + int errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_EQ(errCode, E_OK); /** * @tc.steps: step2. Set time sync finish * @tc.expected: step2. meta is not finish because time sync cache is finish */ - EXPECT_EQ(g_metadataA->SetTimeSyncFinishMark(DEVICE_B, false), E_OK); + EXPECT_EQ(g_metadataA->SetTimeSyncFinishMark(DEVICE_B, "", false), E_OK); DeviceTimeInfo info; RuntimeContext::GetInstance()->SetDeviceTimeInfo(DEVICE_B, info); g_timeSyncA->SetTimeSyncFinishIfNeed(); - EXPECT_FALSE(g_metadataA->IsTimeSyncFinish(DEVICE_B)); + EXPECT_FALSE(g_metadataA->IsTimeSyncFinish(DEVICE_B, "")); RuntimeContext::GetInstance()->ClearAllDeviceTimeInfo(); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.cpp index b68cae6e725fa511b4038f6ec21229fad3360c35..fc2806f7f54f3401d1040fb9936afee2eba11485 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.cpp @@ -27,6 +27,7 @@ GenericVirtualDevice::GenericVirtualDevice(std::string deviceId) metadata_(nullptr), deviceId_(std::move(deviceId)), remoteDeviceId_("real_device"), + targetUserId_("targetUser"), context_(nullptr), onRemoteDataChanged_(nullptr), subManager_(nullptr), @@ -110,7 +111,7 @@ int GenericVirtualDevice::Initialize(VirtualCommunicatorAggregator *comAggregato } communicateHandle_->RegOnMessageCallback( std::bind(&GenericVirtualDevice::MessageCallback, this, std::placeholders::_1, std::placeholders::_2), []() {}); - context_->Initialize(remoteDeviceId_, storage_, metadata_, communicateHandle_); + context_->Initialize({remoteDeviceId_, targetUserId_}, storage_, metadata_, communicateHandle_); context_->SetRetryStatus(SyncTaskContext::NO_NEED_RETRY); context_->RegOnSyncTask(std::bind(&GenericVirtualDevice::StartResponseTask, this)); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.h index 462dd694848759f92d96c526854e2a3a08b1a209..62dd598933434639c0169482efa4173430b42ac9 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.h @@ -56,6 +56,7 @@ protected: std::shared_ptr metadata_; std::string deviceId_; std::string remoteDeviceId_; + std::string targetUserId_; SyncTaskContext *context_; std::function onRemoteDataChanged_; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/kv_virtual_device.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/kv_virtual_device.cpp index c2b58e7b8be6a797b65199f34b724f874cc50931..1d6c43203d9e23501f17cf133013be58c4331e53 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/kv_virtual_device.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/kv_virtual_device.cpp @@ -151,4 +151,10 @@ void KvVirtualDevice::SetPushNotifier(const std::function(storage_); syncAble->SetPushNotifier(pushNotifier); } + +void KvVirtualDevice::SetSchema(const std::string &schema) +{ + auto *syncAble = static_cast(storage_); + syncAble->SetSchemaInfo(schema); +} } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/kv_virtual_device.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/kv_virtual_device.h index 80e266c42ed6f88250b2ca1b18c29db319e9d681..8f7f392ac02a2a7893d1d2e2d4b0f5a030c027ff 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/kv_virtual_device.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/kv_virtual_device.h @@ -45,6 +45,8 @@ public: void EraseWaterMark(const std::string &dev); void SetPushNotifier(const std::function &pushNotifier); + + void SetSchema(const std::string &schema); }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_communicator.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_communicator.h index d0340cf87e2d440e04e80d8dc5f2a692ab029c36..54204f3e338f222853862b76e6dd1c6b58acceaf 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_communicator.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_communicator.h @@ -35,6 +35,8 @@ public: MOCK_METHOD2(RegOnMessageCallback, int(const OnMessageCallback &, const Finalizer &)); MOCK_METHOD1(Activate, void(const std::string &)); MOCK_CONST_METHOD1(IsDeviceOnline, bool(const std::string &)); + MOCK_CONST_METHOD1(GetTargetUserId, std::string(const ExtendInfo &)); + MOCK_METHOD1(ExchangeClosePending, bool(bool)); }; } // namespace DistributedDB #endif // #define MOCK_COMMUNICATOR_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_meta_data.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_meta_data.h index b9a29d0de497cbd9f8375c998c6831cb824d8b37..10605c1c7de6f8f930bad09b06d949ea8fd999db 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_meta_data.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_meta_data.h @@ -21,11 +21,11 @@ namespace DistributedDB { class MockMetadata : public Metadata { public: - MOCK_METHOD3(SetLastQueryTime, int(const std::string &, const std::string &, const Timestamp &)); + MOCK_METHOD4(SetLastQueryTime, int(const std::string &, const std::string &, const std::string &, const Timestamp &)); - MOCK_METHOD3(GetLastQueryTime, int(const std::string &, const std::string &, Timestamp &)); + MOCK_METHOD4(GetLastQueryTime, int(const std::string &, const std::string &, const std::string &, Timestamp &)); - MOCK_METHOD2(GetLocalWaterMark, void(const DeviceID &, uint64_t &)); + MOCK_METHOD3(GetLocalWaterMark, void(const DeviceID &, const DeviceID &, uint64_t &)); }; } // namespace DistributedDB #endif // #define MOCK_META_DATA_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_data_sync.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_data_sync.h index c8d28c519067a9e17d094424611af92a989228f2..dc3e0d2f9f900cf9bf2b804a1adf0e3918883111 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_data_sync.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_data_sync.h @@ -53,6 +53,12 @@ public: } MOCK_METHOD1(RemoveDeviceDataIfNeed, int(SingleVerSyncTaskContext *)); + + int CallDealRemoveDeviceDataByAck( + SingleVerSyncTaskContext *context, WaterMark ackWaterMark, const std::vector &reserved) + { + return SingleVerDataSync::DealRemoveDeviceDataByAck(context, ackWaterMark, reserved); + } }; } // namespace DistributedDB #endif // #define MOCK_SINGLE_VER_DATA_SYNC_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_state_machine.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_state_machine.h index 1509eb6383806f6ddd50db775244b5db0c0accf1..3687d29f8eedb4dd99855e47cf83b6bf6c5a166e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_state_machine.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_state_machine.h @@ -87,6 +87,16 @@ public: return saveDataNotifyRefCount_; } + void CallSyncStepInner() + { + SingleVerSyncStateMachine::SyncStepInner(); + } + + void CallSetCurStateErrStatus() + { + SingleVerSyncStateMachine::SetCurStateErrStatus(); + } + MOCK_METHOD1(SwitchStateAndStep, void(uint8_t)); MOCK_METHOD0(PrepareNextSyncTask, int(void)); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_sync_engine.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_sync_engine.h index 1545ea636e1005dc977e1c5f075cf3f77a1d4721..86ae48f4dc88e8f2c4c8586b31374ecf6c63f59c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_sync_engine.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_sync_engine.h @@ -29,9 +29,14 @@ public: subManager_ = std::make_shared(); } - ISyncTaskContext *CallGetSyncTaskContext(const std::string &deviceId, int &errCode) + ISyncTaskContext *CallGetSyncTaskContext(const DeviceSyncTarget &target, int &errCode) { - return SyncEngine::GetSyncTaskContext(deviceId, errCode); + return SyncEngine::GetSyncTaskContext(target, errCode); + } + + ISyncTaskContext *CallFindSyncTaskContext(const DeviceSyncTarget &target) + { + return SyncEngine::FindSyncTaskContext(target); } }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_time_sync.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_time_sync.h index 43e89b65c82fa7b5d486ece9085d35d07a17f0d7..d2b9b350e81cd53ad790986de3fd7cb5d37a7323 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_time_sync.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_time_sync.h @@ -48,7 +48,7 @@ public: return TimeSync::CalculateTimeOffset(timeSyncInfo); } - MOCK_METHOD2(SyncStart, int(const CommErrHandler &, uint32_t)); + MOCK_METHOD3(SyncStart, int(const CommErrHandler &, uint32_t, bool)); }; } #endif // MOCK_TIME_SYNC_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.cpp index 9d6df07de1fd1977100c2c61aace5d0e6ff8210d..8544372f6fc0858fc60ee4474a5a96fdfc8e1963 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.cpp @@ -209,7 +209,7 @@ VirtualCommunicator::~VirtualCommunicator() VirtualCommunicator::VirtualCommunicator(const std::string &deviceId, VirtualCommunicatorAggregator *communicatorAggregator) - : deviceId_(deviceId), communicatorAggregator_(communicatorAggregator) + : deviceId_(deviceId), communicatorAggregator_(communicatorAggregator), targetUserId_(DBConstant::DEFAULT_USER) { } @@ -221,7 +221,7 @@ int VirtualCommunicator::TranslateMsg(const Message *inMsg, Message *&outMsg) if (errCode != E_OK) { return errCode; } - + sendMsgSize_ += buffer->GetSize(); outMsg = ProtocolProto::ToMessage(buffer, errCode); delete buffer; buffer = nullptr; @@ -236,4 +236,24 @@ void VirtualCommunicator::SetDropMessageTypeByDevice(MessageId msgid, uint32_t d dropMsgTimes_ = 0; } } + +std::string VirtualCommunicator::GetTargetUserId(const ExtendInfo ¶mInfo) const +{ + return targetUserId_; +} + +void VirtualCommunicator::SetTargetUserId(const std::string &userId) +{ + targetUserId_ = userId; +} + +uint64_t VirtualCommunicator::GetSendMsgSize() const +{ + return sendMsgSize_; +} + +bool VirtualCommunicator::ExchangeClosePending(bool expected) +{ + return false; +} } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.h index f904df09802d88e359ae68ddc2ed7aeea6960c3d..56ea144a41e4b50441c2830b348ffbf10c41762a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.h @@ -83,11 +83,15 @@ public: void SetRemoteVersion(uint16_t remoteVersion); + std::string GetTargetUserId(const ExtendInfo ¶mInfo) const override; + + void SetTargetUserId(const std::string &userId); + + uint64_t GetSendMsgSize() const; + + bool ExchangeClosePending(bool expected) override; private: - int TimeSync(); - int DataSync(); - int WaterMarkSync(); - static int TranslateMsg(const Message *inMsg, Message *&outMsg); + int TranslateMsg(const Message *inMsg, Message *&outMsg); mutable std::mutex onMessageLock_; OnMessageCallback onMessage_; @@ -112,6 +116,9 @@ private: uint32_t mtuSize_ = 5 * 1024 * 1024; // 5 * 1024 * 1024B uint16_t remoteVersion_ = UINT16_MAX; + + std::string targetUserId_; + std::atomic sendMsgSize_ = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.cpp index ddc3d9c5c9250da926d4a692e6b0925e7f554edd..7715083e82352ff7f8058e3ae3d888f6e2915423 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.cpp @@ -211,6 +211,7 @@ void VirtualCommunicatorAggregator::DispatchMessageInner(const std::string &srcT uint32_t messageId = inMsg->GetMessageId(); Message *msg = const_cast(inMsg); msg->SetTarget(srcTarget); + msg->SetSenderUserId(communicator->GetTargetUserId({})); RefObject::IncObjRef(communicator); auto onDispatch = onDispatch_; bool isNeedDelay = ((sendDelayTime_ > 0) && (delayTimes_ > 0) && (messageId == delayMessageId_) && @@ -416,4 +417,14 @@ void VirtualCommunicatorAggregator::SetRemoteDeviceId(const std::string &dev) remoteDeviceId_ = dev; LOGI("[VirtualCommunicatorAggregator] Set dev %s", dev.c_str()); } + +uint64_t VirtualCommunicatorAggregator::GetAllSendMsgSize() const +{ + uint64_t size = 0; + std::lock_guard lock(communicatorsLock_); + for (const auto &communicator : communicators_) { + size += communicator.second->GetSendMsgSize(); + } + return size; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.h index b92e488453ae63a9bed2d39f6d27f1bc48480fb0..10e26d45cd32a27bca30dfaa806dc655d9cda613 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.h @@ -107,6 +107,8 @@ public: void SetRemoteDeviceId(const std::string &dev); + uint64_t GetAllSendMsgSize() const; + ~VirtualCommunicatorAggregator() override = default; VirtualCommunicatorAggregator() = default; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp index d2fea14c350cb586e54680c1eaeafd4aae6ce8bc..8c5d8f1e69f3c6bfcd3a952c83a2b899aef4a696 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp @@ -225,6 +225,19 @@ int VirtualRelationalVerSyncDBInterface::GetMetaData(const Key &key, Value &valu return -E_NOT_FOUND; } +int VirtualRelationalVerSyncDBInterface::GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const +{ + for (const auto &metadata : metadata_) { + if (metadata.first.size() < keyPrefix.size()) { + continue; + } + if (std::equal(keyPrefix.begin(), keyPrefix.end(), metadata.first.begin())) { + data[metadata.first] = metadata.second; + } + } + return data.empty() ? -E_NOT_FOUND : E_OK; +} + int VirtualRelationalVerSyncDBInterface::PutMetaData(const Key &key, const Value &value, bool isInTransaction) { (void)isInTransaction; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.h index d1ea9561bff3e914cceda6d314ed19d0a9d6f499..6eab384b6f781e895185de05109b385c0e8a9f60 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.h @@ -73,6 +73,8 @@ public: int GetMetaData(const Key &key, Value &value) const override; + int GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const override; + int PutMetaData(const Key &key, const Value &value, bool isInTransaction) override; int DeleteMetaData(const std::vector &keys) override; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp index 8ca7d89a1c7300f6a2f29382724a1a02fe0b67a6..0266fecec63c81b87f49f84a95117b75985b0d10 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp @@ -102,6 +102,22 @@ int VirtualSingleVerSyncDBInterface::GetMetaData(const Key &key, Value &value) c return -E_NOT_FOUND; } +int VirtualSingleVerSyncDBInterface::GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const +{ + if (readBusy_) { + return -E_BUSY; + } + for (const auto &metadata : metadata_) { + if (metadata.first.size() < keyPrefix.size()) { + continue; + } + if (std::equal(keyPrefix.begin(), keyPrefix.end(), metadata.first.begin())) { + data[metadata.first] = metadata.second; + } + } + return data.empty() ? -E_NOT_FOUND : E_OK; +} + int VirtualSingleVerSyncDBInterface::PutMetaData(const Key &key, const Value &value, bool isInTransaction) { (void)isInTransaction; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h index 20927700b98710b3f8eaae457c543747391c1b72..0efa86284e52780964b28b97c431853fb7c1290c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h @@ -54,6 +54,8 @@ public: int GetMetaData(const Key& key, Value& value) const override; + int GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const override; + int PutMetaData(const Key& key, const Value& value, bool isInTransaction) override; int DeleteMetaData(const std::vector &keys) override; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_time_sync_communicator.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_time_sync_communicator.cpp index 6890e94b4d16fb4d9a1994c6aecc99ad02af73c8..2890d2102fd6291210bf8e833ce1e33c438f1bb5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_time_sync_communicator.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_time_sync_communicator.cpp @@ -151,4 +151,14 @@ void VirtualTimeSyncCommunicator::SetRemoteVersion(uint16_t remoteVersion) { version_ = remoteVersion; } + +std::string VirtualTimeSyncCommunicator::GetTargetUserId(const ExtendInfo ¶mInfo) const +{ + return ""; +} + +bool VirtualTimeSyncCommunicator::ExchangeClosePending(bool expected) +{ + return false; +} } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_time_sync_communicator.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_time_sync_communicator.h index 0478c24c01f73d046d32aeea42fe2f41cdf1fa48..57672ae96a0d61090dd2fdb6ed20052fd93d6c15 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_time_sync_communicator.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_time_sync_communicator.h @@ -72,6 +72,9 @@ public: void SetRemoteVersion(uint16_t remoteVersion); + std::string GetTargetUserId(const ExtendInfo ¶mInfo) const override; + + bool ExchangeClosePending(bool expected) override; private: TimeSync *srcTimeSync_; TimeSync *dstTimeSync_; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/tokenizer/sqlite_adapter_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/tokenizer/sqlite_adapter_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea5dbd4acaf04bd6c8c3727bb8405d2a103c4d7d --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/tokenizer/sqlite_adapter_test.cpp @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2025 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 +#include +#include + +#include "log_print.h" +#ifndef USE_SQLITE_SYMBOLS +#include "sqlite3.h" +#else +#include "sqlite3sym.h" +#endif + +using namespace std; +using namespace testing::ext; +using namespace DistributedDB; + +class SqliteAdapterTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void SqliteAdapterTest::SetUpTestCase(void) +{} + +void SqliteAdapterTest::TearDownTestCase(void) +{} + +void SqliteAdapterTest::SetUp() +{} + +void SqliteAdapterTest::TearDown() +{} + +using Clock = std::chrono::system_clock; + +static bool g_needSkip = false; + +static void HandleRc(sqlite3 *db, int rc) +{ + if (rc != SQLITE_OK) { + LOGE("Failed!!!!!!!!!! rc: %d", rc); + g_needSkip = true; + } +} +static sqlite3 *g_sqliteDb = nullptr; +static char *g_errMsg = nullptr; + +static int Callback(void *data, int argc, char **argv, char **colName) +{ + for (int i = 0; i < argc; i++) { + LOGD("%s = %s\n", colName[i], argv[i] ? argv[i] : "nullptr"); + } + return 0; // 返回 0 表示继续执行查询 +} + +static int QueryCallback(void *data, int argc, char **argv, char **colName) +{ + if (argc != 1) { + return 0; + } + auto expectCount = reinterpret_cast(data); + int base = 10; + EXPECT_EQ(expectCount, strtol(argv[0], nullptr, base)); + return 0; +} + +static void SQLTest(const char *sql) +{ + if (g_needSkip) { + // 蓝区没有so导致失败,直接跳过测试 + return; + } + int errCode = sqlite3_exec(g_sqliteDb, sql, Callback, nullptr, &g_errMsg); + if (errCode != SQLITE_OK) { + if (g_errMsg != nullptr) { + LOGE("SQL error: %s\n", g_errMsg); + sqlite3_free(g_errMsg); + g_errMsg = nullptr; + ASSERT_TRUE(false); + } + } +} + +static int g_rank = 0; +static const char *g_dbPath = "test.db"; + +/** + * @tc.name: SqliteAdapterTest001 + * @tc.desc: Get blob size over limit + * @tc.type: FUNC + * @tc.require: + * @tc.author: wanghaishuo + */ +HWTEST_F(SqliteAdapterTest, SqliteAdapterTest001, TestSize.Level0) +{ + // Save any error messages + char *zErrMsg = nullptr; + + // Save the connection result + int rc = sqlite3_open_v2(g_dbPath, &g_sqliteDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); + HandleRc(g_sqliteDb, rc); + + auto before = Clock::now(); + + rc = sqlite3_db_config(g_sqliteDb, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, nullptr); + HandleRc(g_sqliteDb, rc); + + rc = sqlite3_load_extension(g_sqliteDb, "libcustomtokenizer.z.so", nullptr, nullptr); + HandleRc(g_sqliteDb, rc); + + // create fts table + string sql = "CREATE VIRTUAL TABLE example USING fts5(name, content, tokenize = 'customtokenizer')"; + rc = sqlite3_exec(g_sqliteDb, sql.c_str(), Callback, 0, &zErrMsg); + HandleRc(g_sqliteDb, rc); + + const char *SQLINSERT1 = + "INSERT INTO example(name, content) VALUES('文档1', '这是一个测试文档,用于测试中文文本的分词和索引。');"; + SQLTest(SQLINSERT1); + const char *SQLINSERT2 = + "INSERT INTO example(name, content) VALUES('文档2', '我们将使用这个示例来演示如何在SQLite中进行全文搜索。');"; + SQLTest(SQLINSERT2); + const char *SQLINSERT3 = + "INSERT INTO example(name, content) VALUES('文档3', 'ICU分词器能够很好地处理中文文本的分词和分析。');"; + SQLTest(SQLINSERT3); + const char *SQLINSERT4 = "INSERT INTO example(name, content) VALUES('uksdhf', '');"; + SQLTest(SQLINSERT4); + const char *SQLINSERT5 = "INSERT INTO example(name, content) VALUES('', '');"; + SQLTest(SQLINSERT5); + const char *SQLQUERY1 = "SELECT * FROM example WHERE example MATCH '分* OR SQLite';"; + SQLTest(SQLQUERY1); + + const char *SQLQUERY2 = "SELECT * FROM example WHERE example MATCH '分词' ORDER BY rank;"; + SQLTest(SQLQUERY2); + + const char *SQLQUERY3 = "SELECT * FROM example WHERE name MATCH 'uksdhf';"; + SQLTest(SQLQUERY3); + + const char *SQLDROP = "DROP TABLE IF EXISTS example;"; + SQLTest(SQLDROP); + + // Close the connection + sqlite3_close(g_sqliteDb); +} + +/** + * @tc.name: SqliteAdapterTest002 + * @tc.desc: Test cut for short words + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(SqliteAdapterTest, SqliteAdapterTest002, TestSize.Level0) +{ + /** + * @tc.steps: step1. prepare db + * @tc.expected: step1. OK. + */ + // Save any error messages + char *zErrMsg = nullptr; + + // Save the connection result + int rc = sqlite3_open_v2(g_dbPath, &g_sqliteDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); + HandleRc(g_sqliteDb, rc); + + rc = sqlite3_db_config(g_sqliteDb, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, nullptr); + HandleRc(g_sqliteDb, rc); + + rc = sqlite3_load_extension(g_sqliteDb, "libcustomtokenizer.z.so", nullptr, nullptr); + HandleRc(g_sqliteDb, rc); + /** + * @tc.steps: step2. create table + * @tc.expected: step2. OK. + */ + string sql = "CREATE VIRTUAL TABLE example USING fts5(content, tokenize = 'customtokenizer cut_mode short_words')"; + rc = sqlite3_exec(g_sqliteDb, sql.c_str(), Callback, 0, &zErrMsg); + HandleRc(g_sqliteDb, rc); + /** + * @tc.steps: step3. insert records + * @tc.expected: step3. OK. + */ + std::vector records = { + "电子邮件", + "这是一封电子邮件", + "这是一封关于少数民族的电子邮件", + "华中师范大学是一所位于武汉市的全日制综合性师范大学", + "中华人民共和国", + "武汉市长江大桥Wuhan Yangtze River Bridge是武汉市最长的桥" + }; + for (const auto &record : records) { + std::string insertSql = "insert into example values('" + record + "');"; + SQLTest(insertSql.c_str()); + } + /** + * @tc.steps: step4. test cut for short words + * @tc.expected: step4. OK. + */ + std::vector> expectResult = { + {"电子", 3}, {"邮件", 3}, {"电子邮件", 3}, {"少数", 1}, {"民族", 1}, {"少数民族", 1}, {"华中", 1}, + {"中师", 1}, {"师范", 1}, {"共和", 1}, {"共和国", 1}, {"人民共和国", 0}, {"Yangtze", 1}, {"Wuhan", 1}, + {"市长", 0} + }; + // 蓝区没有so导致失败,直接跳过测试 + if (!g_needSkip) { + for (const auto &[word, expectMatchNum] : expectResult) { + std::string querySql = "SELECT count(*) FROM example WHERE content MATCH '" + word + "';"; + EXPECT_EQ(sqlite3_exec(g_sqliteDb, querySql.c_str(), QueryCallback, + reinterpret_cast(expectMatchNum), nullptr), SQLITE_OK); + } + } + + const char *SQLDROP = "DROP TABLE IF EXISTS example;"; + SQLTest(SQLDROP); + EXPECT_EQ(sqlite3_close(g_sqliteDb), SQLITE_OK); +} + +/** + * @tc.name: SqliteAdapterTest003 + * @tc.desc: Test invalid args + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(SqliteAdapterTest, SqliteAdapterTest003, TestSize.Level0) +{ + /** + * @tc.steps: step1. prepare db + * @tc.expected: step1. OK. + */ + // Save any error messages + char *zErrMsg = nullptr; + + // Save the connection result + int rc = sqlite3_open_v2(g_dbPath, &g_sqliteDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); + HandleRc(g_sqliteDb, rc); + + rc = sqlite3_db_config(g_sqliteDb, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, nullptr); + HandleRc(g_sqliteDb, rc); + + rc = sqlite3_load_extension(g_sqliteDb, "libcustomtokenizer.z.so", nullptr, nullptr); + HandleRc(g_sqliteDb, rc); + /** + * @tc.steps: step2. create table which invalid args + * @tc.expected: step2. return SQLITE_ERROR. + */ + string sql = "CREATE VIRTUAL TABLE example USING fts5(content, tokenize = 'customtokenizer cut_mode')"; + rc = sqlite3_exec(g_sqliteDb, sql.c_str(), Callback, 0, &zErrMsg); + EXPECT_EQ(SQLITE_ERROR, rc); + + sql = "CREATE VIRTUAL TABLE example USING fts5(content, tokenize = 'customtokenizer cut_mode xxx xxx')"; + rc = sqlite3_exec(g_sqliteDb, sql.c_str(), Callback, 0, &zErrMsg); + EXPECT_EQ(SQLITE_ERROR, rc); + + sql = "CREATE VIRTUAL TABLE example USING fts5(content, tokenize = 'customtokenizer cut_mode xxx')"; + rc = sqlite3_exec(g_sqliteDb, sql.c_str(), Callback, 0, &zErrMsg); + EXPECT_EQ(SQLITE_ERROR, rc); + + sql = "CREATE VIRTUAL TABLE example USING fts5(content, tokenize = 'customtokenizer xxx short_words')"; + rc = sqlite3_exec(g_sqliteDb, sql.c_str(), Callback, 0, &zErrMsg); + EXPECT_EQ(SQLITE_ERROR, rc); + + const char *SQLDROP = "DROP TABLE IF EXISTS example;"; + SQLTest(SQLDROP); + EXPECT_EQ(sqlite3_close(g_sqliteDb), SQLITE_OK); +} + +/** + * @tc.name: SqliteAdapterTest004 + * @tc.desc: Test cut_mode default + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(SqliteAdapterTest, SqliteAdapterTest004, TestSize.Level0) +{ + /** + * @tc.steps: step1. prepare db + * @tc.expected: step1. OK. + */ + // Save any error messages + char *zErrMsg = nullptr; + + // Save the connection result + int rc = sqlite3_open_v2(g_dbPath, &g_sqliteDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); + HandleRc(g_sqliteDb, rc); + + rc = sqlite3_db_config(g_sqliteDb, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, nullptr); + HandleRc(g_sqliteDb, rc); + + rc = sqlite3_load_extension(g_sqliteDb, "libcustomtokenizer.z.so", nullptr, nullptr); + HandleRc(g_sqliteDb, rc); + /** + * @tc.steps: step2. create table + * @tc.expected: step2. OK. + */ + string sql = "CREATE VIRTUAL TABLE example USING fts5(content, tokenize = 'customtokenizer cut_mode default')"; + rc = sqlite3_exec(g_sqliteDb, sql.c_str(), Callback, 0, &zErrMsg); + HandleRc(g_sqliteDb, rc); + /** + * @tc.steps: step3. insert records + * @tc.expected: step3. OK. + */ + std::vector records = { + "电子邮件", + "这是一封电子邮件", + "这是一封关于少数民族的电子邮件" + }; + for (const auto &record : records) { + std::string insertSql = "insert into example values('" + record + "');"; + SQLTest(insertSql.c_str()); + } + /** + * @tc.steps: step4. test cut for short words + * @tc.expected: step4. OK. + */ + std::vector> expectResult = { + {"电子", 0}, {"邮件", 0}, {"电子邮件", 3}, {"少数", 0}, {"民族", 0}, {"少数民族", 1} + }; + // 蓝区没有so导致失败,直接跳过测试 + if (!g_needSkip) { + for (const auto &[word, expectMatchNum] : expectResult) { + std::string querySql = "SELECT count(*) FROM example WHERE content MATCH '" + word + "';"; + EXPECT_EQ(sqlite3_exec(g_sqliteDb, querySql.c_str(), QueryCallback, + reinterpret_cast(expectMatchNum), nullptr), SQLITE_OK); + } + } + + const char *SQLDROP = "DROP TABLE IF EXISTS example;"; + SQLTest(SQLDROP); + EXPECT_EQ(sqlite3_close(g_sqliteDb), SQLITE_OK); +} \ No newline at end of file diff --git a/kv_store/interfaces/innerkits/distributeddata/BUILD.gn b/kv_store/interfaces/innerkits/distributeddata/BUILD.gn index 0cda2969c3223b8587e55d5bceabc0e55b77cbbc..6f290b298be98ea883c8d61a0231f4877cdc01a1 100644 --- a/kv_store/interfaces/innerkits/distributeddata/BUILD.gn +++ b/kv_store/interfaces/innerkits/distributeddata/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2022-2025 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 @@ -11,11 +11,10 @@ # See the License for the specific language governing permissions and # limitations under the License. import("//build/ohos.gni") -import("//foundation/distributeddatamgr/data_share/datashare.gni") import("//foundation/distributeddatamgr/kv_store/kv_store.gni") group("build_module") { - deps = [] + deps = [ ":distributeddata_inner_executor" ] if (!use_platform_win && !use_platforn_mac) { deps += [ ":distributeddata_client_sync", @@ -39,8 +38,6 @@ config("distributeddatafwk_config") { "../../../frameworks/common", "../../../frameworks/innerkitsimpl/kvdb/include", "../../../frameworks/innerkitsimpl/kvdb/src", - "${datashare_innerapi_path}/common/include", - "${datashare_innerapi_path}/provider/include", ] } @@ -68,6 +65,7 @@ old_source_config = [ "../../../frameworks/innerkitsimpl/distributeddatafwk/src/kvstore_datashare_bridge.cpp", "../../../frameworks/innerkitsimpl/distributeddatafwk/src/kvstore_observer_client.cpp", "../../../frameworks/innerkitsimpl/distributeddatafwk/src/kvstore_service_death_notifier.cpp", + "../../../frameworks/innerkitsimpl/distributeddatafwk/src/switch_observer_bridge.cpp", "../../../frameworks/innerkitsimpl/distributeddatafwk/src/sync_observer.cpp", "include/types.h", ] @@ -103,6 +101,7 @@ external_deps_config = [ "access_token:libaccesstoken_sdk", "access_token:libtokenid_sdk", "c_utils:utils", + "data_share:datashare_common_lite", "device_manager:devicemanagersdk", "hisysevent:libhisysevent", "hitrace:hitrace_meter", @@ -157,11 +156,15 @@ ohos_shared_library("distributeddata_client_sync") { sources = [ "${kv_store_base_path}/frameworks/innerkitsimpl/kvdb/src/process_communication_impl.cpp", "${kv_store_base_path}/frameworks/innerkitsimpl/kvdb/src/process_system_api_adapter_impl.cpp", + "${kv_store_base_path}/frameworks/innerkitsimpl/kvdb/src/store_util.cpp", ] cflags = [ "-Wno-c99-designator" ] configs = [ ":distributeddatafwk_config" ] - deps = [ "${kv_store_base_path}/frameworks/libs/distributeddb:distributeddb" ] + deps = [ + "${kv_store_base_path}/databaseutils:database_utils", + "${kv_store_base_path}/frameworks/libs/distributeddb:distributeddb" + ] external_deps = [ "c_utils:utils", @@ -211,3 +214,49 @@ ohos_static_library("kvdb_inner_lite") { subsystem_name = "distributeddatamgr" part_name = "kv_store" } + +config("distributeddata_common_public_config") { + visibility = [ ":*" ] + + include_dirs = [ + "include", + "../../../frameworks/common", + ] + + if (use_platform_win) { + cflags = [ "-includewin_glibc.h" ] + } else if (use_platforn_mac || is_ios || is_mac) { + cflags = [ "-includemac_glibc.h" ] + } + + if (use_platform_win || use_platforn_mac || is_ios || is_mac) { + include_dirs += [ + "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/mock", + ] + } +} + +ohos_static_library("distributeddata_inner_executor") { + branch_protector_ret = "pac_ret" + sanitize = { + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + public_configs = [ ":distributeddata_common_public_config" ] + cflags = [ "-Wno-c99-designator" ] + + if (use_platform_win) { + sources = [ + "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/mock/win_glibc.cpp", + ] + } else if (use_platforn_mac || is_ios || is_mac) { + sources = [ + "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/mock/mac_glibc.cpp", + ] + } + subsystem_name = "distributeddatamgr" + part_name = "kv_store" +} diff --git a/kv_store/interfaces/innerkits/distributeddata/include/executor.h b/kv_store/interfaces/innerkits/distributeddata/include/executor.h index 3d2c49bc5b432b7fee287323302a843108402fa0..aa4c1bf429d64c519d2d554188a53a294dd99921 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/executor.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/executor.h @@ -52,9 +52,9 @@ public: } }; - Executor() - : thread_([this] { - pthread_setname_np(pthread_self(), "OS_TaskExecutor"); + Executor(const std::string &threadName) + : thread_([this, threadName] { + pthread_setname_np(pthread_self(), threadName.c_str()); Run(); self_ = nullptr; }) diff --git a/kv_store/interfaces/innerkits/distributeddata/include/executor_pool.h b/kv_store/interfaces/innerkits/distributeddata/include/executor_pool.h index 8357b84c5102e8c334d7b32e9d6028233459c7db..84488b144af9803dcce4e4dc6d067a70774e3219 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/executor_pool.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/executor_pool.h @@ -40,8 +40,8 @@ public: static constexpr Duration INVALID_DELAY = std::chrono::seconds(0); static constexpr TaskId INVALID_TASK_ID = static_cast(0l); - ExecutorPool(size_t max, size_t min) - : pool_(max, min), delayTasks_(InnerTask(), NextTimer), taskId_(INVALID_TASK_ID) + ExecutorPool(size_t max, size_t min, const std::string &threadName = "DB_TaskExecutor") + : pool_(max, min, threadName), delayTasks_(InnerTask(), NextTimer), taskId_(INVALID_TASK_ID) { // When max equals 1, timer thread schedules and executes tasks. if (max > 1) { diff --git a/kv_store/interfaces/innerkits/distributeddata/include/pool.h b/kv_store/interfaces/innerkits/distributeddata/include/pool.h index 063158bf8b4c38a2824ebc6893e4ac9f9d9a9d97..276cdc9b201c46f9cc93b0e5f37a3085545a0232 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/pool.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/pool.h @@ -18,11 +18,13 @@ #include #include #include +#include namespace OHOS { template class Pool { public: - Pool(uint32_t capability, uint32_t min) : capability_(capability), min_(min) {} + Pool(uint32_t capability, uint32_t min, const std::string &threadName) : capability_(capability), min_(min), + threadName_(threadName) {} std::shared_ptr Get(bool isForce = false) { @@ -31,7 +33,7 @@ public: if (!isForce && current_ >= capability_) { return nullptr; } - auto cur = new Node(); + auto cur = new Node(threadName_); idle_ = cur; current_++; } @@ -123,7 +125,8 @@ private: struct Node { Node *prev = nullptr; Node *next = nullptr; - std::shared_ptr data = std::make_shared(); + std::shared_ptr data; + Node(const std::string &threadName) : data(std::make_shared(threadName)) {}; }; uint32_t capability_; @@ -132,6 +135,7 @@ private: Node *idle_ = nullptr; Node *busy_ = nullptr; std::mutex mutex_; + std::string threadName_; }; } // namespace OHOS diff --git a/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h b/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h index 3fe5de7864ffef741c6c5ba66b1422e7ce56052c..0412ace988605dd7d07eef0937c5ac024f4582ed 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h @@ -197,6 +197,27 @@ public: return Status::SUCCESS; } + /** + * @brief Sync store with other devices only syncing the data which is satisfied with the condition. + * + * This is an asynchronous method. + * sync will fail if there is a syncing operation in progress. + * + * @param devices Device list to sync. + * @param mode Mode can be set to SyncMode::PUSH, SyncMode::PULL and SyncMode::PUSH_PULL. + * PUSH_PULL will firstly push all not-local store to listed devices, + * then pull these stores back. + * @param query The query condition. + * @param isRetry The send data is need retry. + * @param syncCallback The callback will be called when sync finished. + * @return Return SUCCESS for success, others for failure. + */ + virtual Status Sync(const std::vector &devices, SyncMode mode, const DataQuery &query, bool isRetry, + std::shared_ptr syncCallback) + { + return Status::SUCCESS; + } + /** * @brief Sync store with other device, while delay is 0. */ diff --git a/kv_store/interfaces/jskits/distributedkvstore/BUILD.gn b/kv_store/interfaces/jskits/distributedkvstore/BUILD.gn index 67bc0b797d4f60cd62bc5d09a6664fd8f50b57c1..2e26287600b5542dd3c0814057956d95a4d06ae5 100644 --- a/kv_store/interfaces/jskits/distributedkvstore/BUILD.gn +++ b/kv_store/interfaces/jskits/distributedkvstore/BUILD.gn @@ -82,6 +82,7 @@ ohos_shared_library("distributedkvstore") { "common_event_service:cesfwk_innerkits", "hilog:libhilog", "ipc:ipc_single", + "json:nlohmann_json_static", "napi:ace_napi", ] diff --git a/kv_store/kvstoremock/distributeddb/BUILD.gn b/kv_store/kvstoremock/distributeddb/BUILD.gn index a65a87652dfd32a60ab7bcbd3343bb11c13b44f9..c690b4f6a95f61d50de60815554d8412b5f25e7c 100644 --- a/kv_store/kvstoremock/distributeddb/BUILD.gn +++ b/kv_store/kvstoremock/distributeddb/BUILD.gn @@ -94,7 +94,6 @@ config("distrdb_config") { visibility = [ ":*" ] include_dirs = distrdb_Dir include_dirs += [ - "//third_party/jsoncpp/include", "//third_party/zlib", "//third_party/sqlite/include", "//third_party/bounds_checking_function/include", @@ -128,7 +127,6 @@ ohos_shared_library("distributeddb_mock") { "//third_party/sqlite:sqlite_sdk", "//third_party/zlib:shared_libz", ] - if (use_platform_win) { libs = [ "//prebuilts/mingw-w64/ohos/linux-x86_64/clang-mingw/x86_64-w64-mingw32/lib/libws2_32.a" ] deps += [ @@ -138,7 +136,6 @@ ohos_shared_library("distributeddb_mock") { deps += [ "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_mac" ] } - configs += [ "//third_party/jsoncpp:jsoncpp_config" ] cflags = [ "-Wno-c99-designator" ] subsystem_name = "distributeddatamgr" part_name = "kv_store" diff --git a/kv_store/kvstoremock/distributeddb/distributeddataservice/adapter/autils/constant.h b/kv_store/kvstoremock/distributeddb/distributeddataservice/adapter/autils/constant.h index 1217102b95470bebcc873191d73c8f776a6fb1bd..18325635ac3cf2959bb2f06d4ddadfd74e258788 100644 --- a/kv_store/kvstoremock/distributeddb/distributeddataservice/adapter/autils/constant.h +++ b/kv_store/kvstoremock/distributeddb/distributeddataservice/adapter/autils/constant.h @@ -136,7 +136,6 @@ public: KVSTORE_API static const int MAX_OPEN_KVSTORES; - // name for process label (bus name for communication). compatible with HwDDMP KVSTORE_API static const std::string ROOT_KEY_GENERATED; }; diff --git a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp index 24a55d581c21f23a0ba074ba7674e0aea93600f4..abcdfc15caba7d4d11d28f23f86b16037aba2060 100644 --- a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp +++ b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp @@ -65,7 +65,8 @@ std::shared_ptr StoreFactory::GetOrOpenStore(const AppId &appId, status = StoreUtil::ConvertStatus(dbStatus); if (kvStore == nullptr) { ZLOGE("Failed! status:%{public}d appId:%{public}s storeId:%{public}s path:%{public}s", dbStatus, - appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), options.baseDir.c_str()); + appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), + StoreUtil::Anonymous(options.baseDir).c_str()); return !stores.empty(); } isCreate = true; diff --git a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp index 922252d193ebf2f4bdfd900fe71c13f709d2c193..a355f7fefe14f363a041b07ad311e25930423378 100644 --- a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp +++ b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp @@ -29,7 +29,8 @@ std::shared_ptr StoreManager::GetKVStore(const AppId &appId, cons const Options &options, Status &status) { ZLOGD("appId:%{public}s, storeId:%{public}s type:%{public}d area:%{public}d dir:%{public}s", appId.appId.c_str(), - StoreUtil::Anonymous(storeId.storeId).c_str(), options.kvStoreType, options.area, options.baseDir.c_str()); + StoreUtil::Anonymous(storeId.storeId).c_str(), options.kvStoreType, options.area, + StoreUtil::Anonymous(options.baseDir).c_str()); status = ILLEGAL_STATE; if (!appId.IsValid() || !storeId.IsValid() || !options.IsValidType()) { status = INVALID_ARGUMENT; @@ -80,7 +81,7 @@ Status StoreManager::CloseAllKVStore(const AppId &appId, int32_t subUser) Status StoreManager::Delete(const AppId &appId, const StoreId &storeId, const std::string &path, int32_t subUser) { ZLOGD("appId:%{public}s, storeId:%{public}s dir:%{public}s", appId.appId.c_str(), - StoreUtil::Anonymous(storeId.storeId).c_str(), path.c_str()); + StoreUtil::Anonymous(storeId.storeId).c_str(), StoreUtil::Anonymous(path).c_str()); if (!appId.IsValid() || !storeId.IsValid()) { return INVALID_ARGUMENT; } diff --git a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_util.cpp b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_util.cpp index f08d93cfa3adee161ae57c50ac5ce51b4e42cc5d..76b09da137332f2c266311bbc076d3793f2538ba 100644 --- a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_util.cpp +++ b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_util.cpp @@ -170,12 +170,12 @@ bool StoreUtil::InitPath(const std::string &path) umask(DEFAULT_UMASK); #ifdef IS_WINDOWS if (mkdir(path.c_str()) != 0 && errno != EEXIST) { - ZLOGE("mkdir error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("mkdir error:%{public}d, path:%{public}s", errno, StoreUtil::Anonymous(path).c_str()); return false; } #else if (mkdir(path.c_str(), MODE) != 0 && errno != EEXIST) { - ZLOGE("mkdir error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("mkdir error:%{public}d, path:%{public}s", errno, StoreUtil::Anonymous(path).c_str()); return false; } #endif @@ -187,7 +187,7 @@ bool StoreUtil::CreateFile(const std::string &name) umask(DEFAULT_UMASK); int fp = open(name.c_str(), (O_WRONLY | O_CREAT)); if (fp < 0) { - ZLOGE("The fopen error:%{public}d, path:%{public}s", errno, name.c_str()); + ZLOGE("The fopen error:%{public}d, path:%{public}s", errno, StoreUtil::Anonymous(name).c_str()); return false; } close(fp); @@ -199,7 +199,7 @@ std::vector StoreUtil::GetSubPath(const std::string &path) std::vector subPaths; DIR *dirp = opendir(path.c_str()); if (dirp == nullptr) { - ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, StoreUtil::Anonymous(path).c_str()); return subPaths; } struct dirent *dp; @@ -215,7 +215,7 @@ std::vector StoreUtil::GetFiles(const std::string &path) std::vector fileInfos; DIR *dirp = opendir(path.c_str()); if (dirp == nullptr) { - ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, StoreUtil::Anonymous(path).c_str()); return fileInfos; } struct dirent *dp; @@ -264,7 +264,7 @@ bool StoreUtil::Remove(const std::string &path) return true; } if (remove(path.c_str()) != 0) { - ZLOGE("The remove error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("The remove error:%{public}d, path:%{public}s", errno, StoreUtil::Anonymous(path).c_str()); return false; } return true; diff --git a/kv_store/kvstoremock/frameworks/jskitsimpl/distributeddata/src/js_util.cpp b/kv_store/kvstoremock/frameworks/jskitsimpl/distributeddata/src/js_util.cpp index a30db82537b149bc2dc677d11b20ee905669415d..43794e453ce1a45b317dff6e1167e597d1530da3 100644 --- a/kv_store/kvstoremock/frameworks/jskitsimpl/distributeddata/src/js_util.cpp +++ b/kv_store/kvstoremock/frameworks/jskitsimpl/distributeddata/src/js_util.cpp @@ -28,6 +28,11 @@ namespace OHOS::DistributedData { constexpr int32_t STR_MAX_LENGTH = 4096; constexpr size_t STR_TAIL_LENGTH = 1; constexpr mode_t MODE = 0755; +static constexpr int32_t HEAD_SIZE = 3; +static constexpr int32_t END_SIZE = 3; +static constexpr int32_t MIN_SIZE = 9; +static constexpr const char *REPLACE_CHAIN = "***"; +static constexpr const char *DEFAULT_ANONYMOUS = "******"; struct PredicatesProxy { std::shared_ptr predicates_; }; @@ -1115,7 +1120,7 @@ napi_status JSUtil::GetCurrentAbilityParam(napi_env env, ContextParam ¶m) param.area = DistributedKv::Area::EL1; param.baseDir = baseDir + "\\HuaweiDevEcoStudioDatabases"; if (mkdir(param.baseDir.c_str()) != 0) { - ZLOGE("mkdir error:%{public}d, path:%{public}s", errno, param.baseDir.c_str()); + ZLOGE("mkdir error:%{public}d, path:%{public}s", errno, Anonymous(param.baseDir).c_str()); } #else std::string baseDir = getenv("LOGNAME"); @@ -1126,12 +1131,12 @@ napi_status JSUtil::GetCurrentAbilityParam(napi_env env, ContextParam ¶m) param.area = DistributedKv::Area::EL1; param.baseDir = baseDir + "/HuaweiDevEcoStudioDatabases"; if (mkdir(param.baseDir.c_str(), MODE) != 0) { - ZLOGE("mkdir error:%{public}d, path:%{public}s", errno, param.baseDir.c_str()); + ZLOGE("mkdir error:%{public}d, path:%{public}s", errno, Anonymous(param.baseDir).c_str()); } #endif param.hapName = "com.example.myapplication"; ZLOGI("area:%{public}d hapName:%{public}s baseDir:%{public}s", param.area, param.hapName.c_str(), - param.baseDir.c_str()); + Anonymous(param.baseDir).c_str()); return napi_ok; } @@ -1204,4 +1209,17 @@ std::pair JSUtil::GetInnerValue( } return std::make_pair(napi_ok, inner); } + +std::string JSUtil::Anonymous(const std::string &name) +{ + if (name.length() <= HEAD_SIZE) { + return DEFAULT_ANONYMOUS; + } + + if (name.length() < MIN_SIZE) { + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN); + } + + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE)); +} } // namespace OHOS::DistributedData diff --git a/kv_store/kvstoremock/interfaces/innerkits/distributeddata/BUILD.gn b/kv_store/kvstoremock/interfaces/innerkits/distributeddata/BUILD.gn index 58ce9c9afad27c7a511f3a24286d4d161571c036..81d16508997417d72145687340ca41b8869c2199 100644 --- a/kv_store/kvstoremock/interfaces/innerkits/distributeddata/BUILD.gn +++ b/kv_store/kvstoremock/interfaces/innerkits/distributeddata/BUILD.gn @@ -121,7 +121,6 @@ ohos_shared_library("distributeddata_inner_mock") { "//foundation/arkui/napi:ace_napi", "//foundation/distributeddatamgr/kv_store/kvstoremock/distributeddb:distributeddb_mock", "//third_party/bounds_checking_function:libsec_static", - "//third_party/jsoncpp:jsoncpp_static", "//third_party/libuv:uv", "//third_party/sqlite:sqlite_sdk", ] diff --git a/kv_store/kvstoremock/interfaces/jskits/distributeddata/BUILD.gn b/kv_store/kvstoremock/interfaces/jskits/distributeddata/BUILD.gn index 43e786964bfec7261e85f82a0ab31c60c7917a5d..42514dd54f2c2808c165cf68b7f70962ccb9bd7e 100644 --- a/kv_store/kvstoremock/interfaces/jskits/distributeddata/BUILD.gn +++ b/kv_store/kvstoremock/interfaces/jskits/distributeddata/BUILD.gn @@ -13,7 +13,6 @@ import("//build/ohos.gni") import("//build/ohos/ace/ace.gni") -import("//foundation/distributeddatamgr/data_share/datashare.gni") import("//foundation/distributeddatamgr/kv_store/kv_store.gni") base_output_path = get_label_info(":distributed_data_js", "target_out_dir") @@ -41,8 +40,6 @@ if (use_platform_win || use_platforn_mac) { "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata/include", "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/mock/base", "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/mock", - "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common/include", - "//foundation/distributeddatamgr/data_share/interfaces/inner_api/provider/include", "//commonlibrary/c_utils/base/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/include", ] @@ -76,6 +73,10 @@ if (use_platform_win || use_platforn_mac) { "//third_party/libuv:uv", ] + external_deps = [ + "data_share:datashare_common_lite", + ] + if (use_platform_win) { defines = [ "IS_WINDOWS" ] deps += [ diff --git a/kv_store/kvstoremock/interfaces/jskits/distributedkvstore/BUILD.gn b/kv_store/kvstoremock/interfaces/jskits/distributedkvstore/BUILD.gn index 440314fc0e42834c3986b948dcab66729a3b93bc..c3f7410eb053e4775c5206507e48c5fd06bc4b5a 100644 --- a/kv_store/kvstoremock/interfaces/jskits/distributedkvstore/BUILD.gn +++ b/kv_store/kvstoremock/interfaces/jskits/distributedkvstore/BUILD.gn @@ -13,7 +13,6 @@ import("//build/ohos.gni") import("//build/ohos/ace/ace.gni") -import("//foundation/distributeddatamgr/data_share/datashare.gni") import("//foundation/distributeddatamgr/kv_store/kv_store.gni") base_output_path = get_label_info(":distributed_kvstore_js", "target_out_dir") @@ -32,7 +31,6 @@ group("build_module") { if (use_platform_win || use_platforn_mac) { ohos_shared_library("distributedkvstore") { include_dirs = [ - "//third_party/json/single_include", "//third_party/libuv/include", "//third_party/node/src", "//foundation/distributeddatamgr/kv_store", @@ -42,8 +40,6 @@ if (use_platform_win || use_platforn_mac) { "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata/include", "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/mock/base", "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/mock", - "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common/include", - "//foundation/distributeddatamgr/data_share/interfaces/inner_api/provider/include", "//commonlibrary/c_utils/base/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/include", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework/include/utils", @@ -81,6 +77,11 @@ if (use_platform_win || use_platforn_mac) { "//third_party/libuv:uv", ] + external_deps = [ + "data_share:datashare_common_lite", + "json:nlohmann_json_static", + ] + if (use_platform_win) { defines = [ "IS_WINDOWS" ] deps += [ diff --git a/kv_store/test/distributedtest/single_kvstore_client/BUILD.gn b/kv_store/test/distributedtest/single_kvstore_client/BUILD.gn index 10750dcff24cbe21bbcfd397459ca2b746e7f321..e0bdf48d40f8950b7bb2d993eb033da8714c3c8d 100644 --- a/kv_store/test/distributedtest/single_kvstore_client/BUILD.gn +++ b/kv_store/test/distributedtest/single_kvstore_client/BUILD.gn @@ -31,15 +31,16 @@ config("module_private_config") { common_deps = [ "${kv_store_base_path}/frameworks/libs/distributeddb:distributeddb", "${kv_store_base_path}/interfaces/innerkits/distributeddata:distributeddata_inner", - "${third_party_path}/googletest:gtest", ] common_external_deps = [ "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "access_token:libtoken_setproc", "c_utils:utils", + "cJSON:cjson", "device_manager:devicemanagersdk", + "googletest:gtest", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", diff --git a/kv_store/test/fuzztest/blob_fuzzer/blob_fuzzer.cpp b/kv_store/test/fuzztest/blob_fuzzer/blob_fuzzer.cpp index ae9609658927596c22e94d402a4a8158b7a4e30a..b625187d878a97523783546684b2e1c4513d406d 100644 --- a/kv_store/test/fuzztest/blob_fuzzer/blob_fuzzer.cpp +++ b/kv_store/test/fuzztest/blob_fuzzer/blob_fuzzer.cpp @@ -17,7 +17,7 @@ #include #include - +#include "fuzzer/FuzzedDataProvider.h" #include "securec.h" #include "types.h" #include "blob.h" @@ -59,29 +59,27 @@ void BlobOption(const Blob &blob) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Run your code on data */ - std::string fuzzStr(reinterpret_cast(data), size); - std::vector fuzzVec(fuzzStr.begin(), fuzzStr.end()); + FuzzedDataProvider fuzzer(data, size); + size_t blobSize = fuzzer.ConsumeIntegralInRange(1, 50); + std::vector fuzzVec = fuzzer.ConsumeBytes(blobSize); - int count = 10; - char str[count + 1]; - auto ret = memcpy_s(str, count + 1, data, std::min(static_cast(count + 1), size)); - if (ret != EOK) { - return 0; - } - str[count] = '\0'; - Blob blob1(str); - blob1 = str; - Blob blob2(fuzzStr); - blob2 = fuzzStr; + std::string str1 = fuzzer.ConsumeRandomLengthString(); + Blob blob1(str1.c_str()); + std::string str2 = fuzzer.ConsumeRandomLengthString(); + blob1 = str2.c_str(); + Blob blob2(fuzzer.ConsumeRandomLengthString()); + blob2 = fuzzer.ConsumeRandomLengthString(); Blob blob3(fuzzVec); - Blob blob4(str, count + 1); + std::string str3 = fuzzer.ConsumeRandomLengthString(); + Blob blob4(str3.c_str(), str3.length() + 1); Blob blob5(blob4); Blob blob6(std::move(blob5)); Blob blob7 = blob6; blob7 = Blob(blob6); + int count = 10; auto buffer = std::make_unique(count); uint8_t *writePtr = buffer.get(); - Blob blob8(fuzzStr); + Blob blob8(fuzzer.ConsumeRandomLengthString()); blob8.WriteToBuffer(writePtr, count); OHOS::BlobOption(blob8); diff --git a/kv_store/test/fuzztest/devicekvstore_fuzzer/devicekvstore_fuzzer.cpp b/kv_store/test/fuzztest/devicekvstore_fuzzer/devicekvstore_fuzzer.cpp index 3684d08162b6c7620eda2c31895c97b66d84d5ee..b406ba3a8b964e64b4b60adc6af2e3c6e16944a6 100644 --- a/kv_store/test/fuzztest/devicekvstore_fuzzer/devicekvstore_fuzzer.cpp +++ b/kv_store/test/fuzztest/devicekvstore_fuzzer/devicekvstore_fuzzer.cpp @@ -19,6 +19,7 @@ #include #include "distributed_kv_data_manager.h" +#include "fuzzer/FuzzedDataProvider.h" #include "store_errno.h" using namespace OHOS; @@ -84,20 +85,20 @@ void TearDown(void) (void)remove("/data/service/el1/public/database/devicekvstorefuzzertest"); } -void PutFuzz(const uint8_t *data, size_t size) +void PutFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); Key key = { skey }; Value val = { svalue }; deviceKvStore_->Put(key, val); deviceKvStore_->Delete(key); } -void PutBatchFuzz(const uint8_t *data, size_t size) +void PutBatchFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); std::vector entries; std::vector keys; Entry entry1; @@ -119,10 +120,10 @@ void PutBatchFuzz(const uint8_t *data, size_t size) deviceKvStore_->DeleteBatch(keys); } -void GetFuzz(const uint8_t *data, size_t size) +void GetFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); Key key = { skey }; Value val = { svalue }; Value val1; @@ -131,9 +132,9 @@ void GetFuzz(const uint8_t *data, size_t size) deviceKvStore_->Delete(key); } -void GetEntriesFuzz1(const uint8_t *data, size_t size) +void GetEntriesFuzz1(FuzzedDataProvider &provider) { - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); std::string keys = "test_"; size_t sum = 10; std::vector results; @@ -146,9 +147,9 @@ void GetEntriesFuzz1(const uint8_t *data, size_t size) } } -void GetEntriesFuzz2(const uint8_t *data, size_t size) +void GetEntriesFuzz2(FuzzedDataProvider &provider) { - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); DataQuery dataQuery; dataQuery.KeyPrefix(prefix); std::string keys = "test_"; @@ -163,12 +164,12 @@ void GetEntriesFuzz2(const uint8_t *data, size_t size) } } -void SyncCallbackFuzz(const uint8_t *data, size_t size) +void SyncCallbackFuzz(FuzzedDataProvider &provider) { auto syncCallback = std::make_shared(); deviceKvStore_->RegisterSyncCallback(syncCallback); - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); DataQuery dataQuery; dataQuery.KeyPrefix(prefix); std::string keys = "test_"; @@ -186,11 +187,11 @@ void SyncCallbackFuzz(const uint8_t *data, size_t size) deviceKvStore_->UnRegisterSyncCallback(); } -void GetResultSetFuzz1(const uint8_t *data, size_t size) +void GetResultSetFuzz1(FuzzedDataProvider &provider) { - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); std::string keys = "test_"; - int position = static_cast(size); + int position = provider.ConsumeIntegral(); std::shared_ptr resultSet; size_t sum = 10; for (size_t i = 0; i < sum; i++) { @@ -209,9 +210,9 @@ void GetResultSetFuzz1(const uint8_t *data, size_t size) } } -void GetResultSetFuzz2(const uint8_t *data, size_t size) +void GetResultSetFuzz2(FuzzedDataProvider &provider) { - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); DataQuery dataQuery; dataQuery.KeyPrefix(prefix); std::string keys = "test_"; @@ -227,9 +228,9 @@ void GetResultSetFuzz2(const uint8_t *data, size_t size) } } -void GetResultSetFuzz3(const uint8_t *data, size_t size) +void GetResultSetFuzz3(FuzzedDataProvider &provider) { - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); DataQuery dataQuery; dataQuery.KeyPrefix(prefix); std::string keys = "test_"; @@ -244,7 +245,7 @@ void GetResultSetFuzz3(const uint8_t *data, size_t size) return; } int cnt = resultSet->GetCount(); - if (static_cast(size) != cnt) { + if (cnt != sum) { return; } resultSet->GetPosition(); @@ -277,10 +278,10 @@ void GetResultSetFuzz3(const uint8_t *data, size_t size) } } -void GetCountFuzz1(const uint8_t *data, size_t size) +void GetCountFuzz1(FuzzedDataProvider &provider) { int count; - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); DataQuery query; query.KeyPrefix(prefix); std::string keys = "test_"; @@ -294,12 +295,12 @@ void GetCountFuzz1(const uint8_t *data, size_t size) } } -void GetCountFuzz2(const uint8_t *data, size_t size) +void GetCountFuzz2(FuzzedDataProvider &provider) { int count; size_t sum = 10; std::vector keys; - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); for (size_t i = 0; i < sum; i++) { keys.push_back(prefix); } @@ -315,14 +316,14 @@ void GetCountFuzz2(const uint8_t *data, size_t size) } } -void SyncFuzz1(const uint8_t *data, size_t size) +void SyncFuzz1(FuzzedDataProvider &provider) { size_t sum = 10; std::string skey = "test_"; for (size_t i = 0; i < sum; i++) { deviceKvStore_->Put(skey + std::to_string(i), skey + std::to_string(i)); } - std::string deviceId(data, data + size); + std::string deviceId = provider.ConsumeRandomLengthString(); std::vector deviceIds = { deviceId }; uint32_t allowedDelayMs = 200; deviceKvStore_->Sync(deviceIds, SyncMode::PUSH, allowedDelayMs); @@ -331,14 +332,14 @@ void SyncFuzz1(const uint8_t *data, size_t size) } } -void SyncFuzz2(const uint8_t *data, size_t size) +void SyncFuzz2(FuzzedDataProvider &provider) { size_t sum = 10; std::string skey = "test_"; for (size_t i = 0; i < sum; i++) { deviceKvStore_->Put(skey + std::to_string(i), skey + std::to_string(i)); } - std::string deviceId(data, data + size); + std::string deviceId = provider.ConsumeRandomLengthString(); std::vector deviceIds = { deviceId }; DataQuery dataQuery; dataQuery.KeyPrefix("name"); @@ -348,9 +349,9 @@ void SyncFuzz2(const uint8_t *data, size_t size) } } -void SubscribeKvStoreFuzz(const uint8_t *data, size_t size) +void SubscribeKvStoreFuzz(FuzzedDataProvider &provider) { - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); DataQuery dataQuery; dataQuery.KeyPrefix(prefix); std::string keys = "test_"; @@ -366,10 +367,10 @@ void SubscribeKvStoreFuzz(const uint8_t *data, size_t size) } } -void RemoveDeviceDataFuzz(const uint8_t *data, size_t size) +void RemoveDeviceDataFuzz(FuzzedDataProvider &provider) { size_t sum = 10; - std::string deviceId(data, data + size); + std::string deviceId = provider.ConsumeRandomLengthString(); std::vector input; auto cmp = [](const Key &entry, const Key &sentry) { return entry.Data() < sentry.Data(); }; std::map dictionary(cmp); @@ -389,11 +390,11 @@ void RemoveDeviceDataFuzz(const uint8_t *data, size_t size) } } -void GetSecurityLevelFuzz(const uint8_t *data, size_t size) +void GetSecurityLevelFuzz(FuzzedDataProvider &provider) { size_t sum = 10; std::vector keys; - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); for (size_t i = 0; i < sum; i++) { keys.push_back(prefix); } @@ -408,11 +409,11 @@ void GetSecurityLevelFuzz(const uint8_t *data, size_t size) } } -void SyncParamFuzz(const uint8_t *data, size_t size) +void SyncParamFuzz(FuzzedDataProvider &provider) { size_t sum = 10; std::vector keys; - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); for (size_t i = 0; i < sum; i++) { keys.push_back(prefix); } @@ -432,11 +433,11 @@ void SyncParamFuzz(const uint8_t *data, size_t size) } } -void SetCapabilityEnabledFuzz(const uint8_t *data, size_t size) +void SetCapabilityEnabledFuzz(FuzzedDataProvider &provider) { size_t sum = 10; std::vector keys; - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); for (size_t i = 0; i < sum; i++) { keys.push_back(prefix); } @@ -453,17 +454,17 @@ void SetCapabilityEnabledFuzz(const uint8_t *data, size_t size) } } -void SetCapabilityRangeFuzz(const uint8_t *data, size_t size) +void SetCapabilityRangeFuzz(FuzzedDataProvider &provider) { - std::string label(data, data + size); + std::string label = provider.ConsumeRandomLengthString(); std::vector local = { label + "_local1", label + "_local2" }; std::vector remote = { label + "_remote1", label + "_remote2" }; deviceKvStore_->SetCapabilityRange(local, remote); } -void SubscribeWithQueryFuzz(const uint8_t *data, size_t size) +void SubscribeWithQueryFuzz(FuzzedDataProvider &provider) { - std::string deviceId(data, data + size); + std::string deviceId = provider.ConsumeRandomLengthString(); std::vector deviceIds = { deviceId + "_1", deviceId + "_2" }; DataQuery dataQuery; dataQuery.KeyPrefix("name"); @@ -471,9 +472,9 @@ void SubscribeWithQueryFuzz(const uint8_t *data, size_t size) deviceKvStore_->UnsubscribeWithQuery(deviceIds, dataQuery); } -void UnSubscribeWithQueryFuzz(const uint8_t *data, size_t size) +void UnSubscribeWithQueryFuzz(FuzzedDataProvider &provider) { - std::string deviceId(data, data + size); + std::string deviceId = provider.ConsumeRandomLengthString(); std::vector deviceIds = { deviceId + "_1", deviceId + "_2" }; DataQuery dataQuery; dataQuery.KeyPrefix("name"); @@ -485,28 +486,29 @@ void UnSubscribeWithQueryFuzz(const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Run your code on data */ + FuzzedDataProvider provider(data, size); OHOS::SetUpTestCase(); - OHOS::PutFuzz(data, size); - OHOS::PutBatchFuzz(data, size); - OHOS::GetFuzz(data, size); - OHOS::GetEntriesFuzz1(data, size); - OHOS::GetEntriesFuzz2(data, size); - OHOS::GetResultSetFuzz1(data, size); - OHOS::GetResultSetFuzz2(data, size); - OHOS::GetResultSetFuzz3(data, size); - OHOS::GetCountFuzz1(data, size); - OHOS::GetCountFuzz2(data, size); - OHOS::SyncFuzz1(data, size); - OHOS::SyncFuzz2(data, size); - OHOS::SubscribeKvStoreFuzz(data, size); - OHOS::RemoveDeviceDataFuzz(data, size); - OHOS::GetSecurityLevelFuzz(data, size); - OHOS::SyncCallbackFuzz(data, size); - OHOS::SyncParamFuzz(data, size); - OHOS::SetCapabilityEnabledFuzz(data, size); - OHOS::SetCapabilityRangeFuzz(data, size); - OHOS::SubscribeWithQueryFuzz(data, size); - OHOS::UnSubscribeWithQueryFuzz(data, size); + OHOS::PutFuzz(provider); + OHOS::PutBatchFuzz(provider); + OHOS::GetFuzz(provider); + OHOS::GetEntriesFuzz1(provider); + OHOS::GetEntriesFuzz2(provider); + OHOS::GetResultSetFuzz1(provider); + OHOS::GetResultSetFuzz2(provider); + OHOS::GetResultSetFuzz3(provider); + OHOS::GetCountFuzz1(provider); + OHOS::GetCountFuzz2(provider); + OHOS::SyncFuzz1(provider); + OHOS::SyncFuzz2(provider); + OHOS::SubscribeKvStoreFuzz(provider); + OHOS::RemoveDeviceDataFuzz(provider); + OHOS::GetSecurityLevelFuzz(provider); + OHOS::SyncCallbackFuzz(provider); + OHOS::SyncParamFuzz(provider); + OHOS::SetCapabilityEnabledFuzz(provider); + OHOS::SetCapabilityRangeFuzz(provider); + OHOS::SubscribeWithQueryFuzz(provider); + OHOS::UnSubscribeWithQueryFuzz(provider); OHOS::TearDown(); return 0; } \ No newline at end of file diff --git a/kv_store/test/fuzztest/distributedkvdatamanager_fuzzer/distributedkvdatamanager_fuzzer.cpp b/kv_store/test/fuzztest/distributedkvdatamanager_fuzzer/distributedkvdatamanager_fuzzer.cpp index 6bfec15dc938200a90ded037a68387f46c51a64d..dbfdddcae6512de2227245393209935ad886d716 100644 --- a/kv_store/test/fuzztest/distributedkvdatamanager_fuzzer/distributedkvdatamanager_fuzzer.cpp +++ b/kv_store/test/fuzztest/distributedkvdatamanager_fuzzer/distributedkvdatamanager_fuzzer.cpp @@ -18,6 +18,7 @@ #include #include "distributed_kv_data_manager.h" +#include "fuzzer/FuzzedDataProvider.h" #include "kvstore_death_recipient.h" #include "kvstore_observer.h" #include "types.h" @@ -91,10 +92,10 @@ void TearDown(void) (void)remove("/data/service/el1/public/database/distributedkvdatamanagerfuzzertest"); } -void GetKvStoreFuzz(const uint8_t *data, size_t size) +void GetKvStoreFuzz(FuzzedDataProvider &provider) { StoreId storeId; - storeId.storeId = std::string(data, data + size); + storeId.storeId = provider.ConsumeRandomLengthString(); std::shared_ptr notExistKvStore; manager.GetSingleKvStore(create, appId, storeId, notExistKvStore); std::shared_ptr existKvStore; @@ -103,13 +104,13 @@ void GetKvStoreFuzz(const uint8_t *data, size_t size) manager.DeleteKvStore(appId, storeId); } -void GetAllKvStoreFuzz(const uint8_t *data, size_t size) +void GetAllKvStoreFuzz(FuzzedDataProvider &provider) { std::vector storeIds; manager.GetAllKvStoreId(appId, storeIds); std::shared_ptr KvStore; - std::string storeId_base(data, data + size); + std::string storeId_base = provider.ConsumeRandomLengthString(); int sum = 10; for (int i = 0; i < sum; i++) { StoreId storeId; @@ -122,10 +123,10 @@ void GetAllKvStoreFuzz(const uint8_t *data, size_t size) manager.GetAllKvStoreId(appId, storeIds); } -void CloseKvStoreFuzz(const uint8_t *data, size_t size) +void CloseKvStoreFuzz(FuzzedDataProvider &provider) { StoreId storeId; - storeId.storeId = std::string(data, data + size); + storeId.storeId = provider.ConsumeRandomLengthString(); manager.CloseKvStore(appId, storeId); std::shared_ptr kvStore; manager.GetSingleKvStore(create, appId, storeId, kvStore); @@ -133,10 +134,10 @@ void CloseKvStoreFuzz(const uint8_t *data, size_t size) manager.CloseKvStore(appId, storeId); } -void DeleteKvStoreFuzz(const uint8_t *data, size_t size) +void DeleteKvStoreFuzz(FuzzedDataProvider &provider) { StoreId storeId; - storeId.storeId = std::string(data, data + size); + storeId.storeId = provider.ConsumeRandomLengthString(); manager.DeleteKvStore(appId, storeId, create.baseDir); std::shared_ptr kvStore; @@ -147,14 +148,14 @@ void DeleteKvStoreFuzz(const uint8_t *data, size_t size) manager.CloseKvStore(appId, storeId); } -void DeleteAllKvStoreFuzz1(const uint8_t *data, size_t size) +void DeleteAllKvStoreFuzz1(FuzzedDataProvider &provider) { std::vector storeIds; manager.GetAllKvStoreId(appId, storeIds); manager.DeleteAllKvStore(appId, create.baseDir); std::shared_ptr KvStore; - std::string storeId_base(data, data + size); + std::string storeId_base = provider.ConsumeRandomLengthString(); int sum = 10; for (int i = 0; i < sum; i++) { StoreId storeId; @@ -166,13 +167,13 @@ void DeleteAllKvStoreFuzz1(const uint8_t *data, size_t size) manager.DeleteAllKvStore(appId, create.baseDir); } -void DeleteAllKvStoreFuzz2(const uint8_t *data, size_t size) +void DeleteAllKvStoreFuzz2(FuzzedDataProvider &provider) { std::vector storeIds; manager.GetAllKvStoreId(appId, storeIds); std::shared_ptr KvStore; - std::string storeId_base(data, data + size); + std::string storeId_base = provider.ConsumeRandomLengthString(); manager.GetSingleKvStore(create, appId, storeIdTest, KvStore); manager.CloseKvStore(appId, storeIdTest); int sum = 10; @@ -184,13 +185,13 @@ void DeleteAllKvStoreFuzz2(const uint8_t *data, size_t size) manager.DeleteAllKvStore(appId, create.baseDir); } -void DeleteAllKvStoreFuzz3(const uint8_t *data, size_t size) +void DeleteAllKvStoreFuzz3(FuzzedDataProvider &provider) { std::vector storeIds; manager.GetAllKvStoreId(appId, storeIds); std::shared_ptr KvStore; - std::string storeId_base(data, data + size); + std::string storeId_base = provider.ConsumeRandomLengthString(); int sum = 10; for (int i = 0; i < sum; i++) { StoreId storeId; @@ -214,10 +215,10 @@ void UnRegisterKvStoreServiceDeathRecipientFuzz() kvStoreDeathRecipient->OnRemoteDied(); } -void PutSwitchFuzz(const uint8_t *data, size_t size) +void PutSwitchFuzz(FuzzedDataProvider &provider) { - std::string appIds(data, data + size); - uint32_t input = static_cast(size); + std::string appIds = provider.ConsumeRandomLengthString(); + uint32_t input = provider.ConsumeIntegral(); SwitchData switchData; switchData.value = input; switchData.length = input & 0xFFFF; @@ -225,48 +226,57 @@ void PutSwitchFuzz(const uint8_t *data, size_t size) manager.PutSwitch({ "distributed_device_profile_service" }, switchData); } -void GetSwitchFuzz(const uint8_t *data, size_t size) +void GetSwitchFuzz(FuzzedDataProvider &provider) { - std::string appIds(data, data + size); - std::string networkId(data, data + size); + std::string appIds = provider.ConsumeRandomLengthString(); + std::string networkId = provider.ConsumeRandomLengthString(); manager.GetSwitch({ appIds }, networkId); manager.GetSwitch({ "distributed_device_profile_service" }, networkId); } -void SubscribeSwitchDataFuzz(const uint8_t *data, size_t size) +void SubscribeSwitchDataFuzz(FuzzedDataProvider &provider) { - std::string appIds(data, data + size); + std::string appIds = provider.ConsumeRandomLengthString(); std::shared_ptr observer = std::make_shared(); manager.SubscribeSwitchData({ appIds }, observer); } -void UnsubscribeSwitchDataFuzz(const uint8_t *data, size_t size) +void UnsubscribeSwitchDataFuzz(FuzzedDataProvider &provider) { - std::string appIds(data, data + size); + std::string appIds = provider.ConsumeRandomLengthString(); std::shared_ptr observer = std::make_shared(); manager.SubscribeSwitchData({ appIds }, observer); manager.UnsubscribeSwitchData({ appIds }, observer); } + +void SetExecutorsFuzz(FuzzedDataProvider &provider) +{ + size_t max = provider.ConsumeIntegral(); + size_t min = provider.ConsumeIntegral(); + auto executors = std::make_shared(max, min); + manager.SetExecutors(executors); +} } // namespace OHOS /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Run your code on data */ + FuzzedDataProvider provider(data, size); OHOS::SetUpTestCase(); - OHOS::GetKvStoreFuzz(data, size); - OHOS::GetAllKvStoreFuzz(data, size); - OHOS::CloseKvStoreFuzz(data, size); - OHOS::DeleteKvStoreFuzz(data, size); - OHOS::DeleteAllKvStoreFuzz1(data, size); - OHOS::DeleteAllKvStoreFuzz2(data, size); - OHOS::DeleteAllKvStoreFuzz3(data, size); + OHOS::GetKvStoreFuzz(provider); + OHOS::GetAllKvStoreFuzz(provider); + OHOS::CloseKvStoreFuzz(provider); + OHOS::DeleteKvStoreFuzz(provider); + OHOS::DeleteAllKvStoreFuzz1(provider); + OHOS::DeleteAllKvStoreFuzz2(provider); + OHOS::DeleteAllKvStoreFuzz3(provider); OHOS::RegisterKvStoreServiceDeathRecipientFuzz(); OHOS::UnRegisterKvStoreServiceDeathRecipientFuzz(); - OHOS::PutSwitchFuzz(data, size); - OHOS::GetSwitchFuzz(data, size); - OHOS::SubscribeSwitchDataFuzz(data, size); - OHOS::UnsubscribeSwitchDataFuzz(data, size); + OHOS::PutSwitchFuzz(provider); + OHOS::GetSwitchFuzz(provider); + OHOS::SubscribeSwitchDataFuzz(provider); + OHOS::UnsubscribeSwitchDataFuzz(provider); OHOS::TearDown(); return 0; } \ No newline at end of file diff --git a/kv_store/test/fuzztest/distributedkvdataservice_fuzzer/distributedkvdataservice_fuzzer.cpp b/kv_store/test/fuzztest/distributedkvdataservice_fuzzer/distributedkvdataservice_fuzzer.cpp deleted file mode 100644 index 60ae617fffd2b4b0ff020819fbe9d8814f93daf6..0000000000000000000000000000000000000000 --- a/kv_store/test/fuzztest/distributedkvdataservice_fuzzer/distributedkvdataservice_fuzzer.cpp +++ /dev/null @@ -1,275 +0,0 @@ -/* - * 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 "distributedkvdataservice_fuzzer.h" - -#include "distributed_kv_data_manager.h" -#include "kvstore_death_recipient.h" -#include "kvstore_observer.h" -#include "types.h" -#include -#include - -using namespace OHOS; -using namespace OHOS::DistributedKv; - -class DistributedKvDataServiceFuzzer { - /* Keep C++ file names the same as the class name */ -}; - -namespace OHOS { - -static std::shared_ptr singleKvStore = nullptr; -static distributedkvdataservice service; -static AppId appIdTest; -static StoreId storeIdTest; -static Options createTest; -static Options noCreate; -static UserId userId; - -class MyDeathRecipient : public KvStoreDeathRecipient { -public: - MyDeathRecipient() { } - virtual ~MyDeathRecipient() { } - void OnRemoteDied() override { } -}; - -class SwitchDataObserver : public KvStoreObserver { -public: - void OnSwitchChange(const SwitchNotification ¬ification) override - { - blockData_.SetValue(notification); - } - - SwitchNotification Get() - { - return blockData_.GetValue(); - } - -private: - BlockData blockData_ { 1, SwitchNotification() }; -}; - -void SetUpTestCase(void) -{ - userId.userId = "account"; - appIdTest.appId = "distributedkvdataservicefuzzertest"; - createTest.createIfMissing = true; - createTest.encrypt = false; - createTest.autoSync = true; - createTest.kvStoreType = SINGLE_VERSION; - createTest.area = EL1; - createTest.baseDir = std::string("/data/service/el1/public/database/") + appIdTest.appId; - mkdir(createTest.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); - - service.CloseAllKvStore(appIdTest); - service.DeleteAllKvStore(appIdTest, createTest.baseDir); -} - -void TearDown(void) -{ - service.CloseAllKvStore(appIdTest); - service.DeleteAllKvStore(appIdTest, createTest.baseDir); - (void)remove("/data/service/el1/public/database/distributedkvdataservicefuzzertest/key"); - (void)remove("/data/service/el1/public/database/distributedkvdataservicefuzzertest/kvdb"); - (void)remove("/data/service/el1/public/database/distributedkvdataservicefuzzertest"); -} - -void GetKvStoreFuzzTest(const uint8_t *data, size_t size) -{ - StoreId storeId; - storeId.storeId = std::string(data, data + size); - std::shared_ptr notExistKvStore; - service.GetSingleKvStore(createTest, appIdTest, storeId, notExistKvStore); - std::shared_ptr existKvStore; - service.GetSingleKvStore(noCreate, appIdTest, storeId, existKvStore); - service.CloseKvStore(appIdTest, storeId); - service.DeleteKvStore(appIdTest, storeId); -} - -void GetAllKvStoreFuzzTest(const uint8_t *data, size_t size) -{ - std::vector storeIds; - service.GetAllKvStoreId(appIdTest, storeIds); - - std::shared_ptr KvStore; - std::string storeIdBase(data, data + size); - int sum = 10; - - for (int i = 0; i < sum; i++) { - StoreId storeId; - storeId.storeId = storeIdBase + "_" + std::to_string(i); - service.GetSingleKvStore(createTest, appIdTest, storeId, KvStore); - } - service.GetAllKvStoreId(appIdTest, storeIds); - service.CloseAllKvStore(appIdTest); - - service.GetAllKvStoreId(appIdTest, storeIds); -} - -void CloseKvStoreFuzzTest(const uint8_t *data, size_t size) -{ - StoreId storeId; - storeId.storeId = std::string(data, data + size); - service.CloseKvStore(appIdTest, storeId); - std::shared_ptr kvStoreImpl; - service.GetSingleKvStore(createTest, appIdTest, storeId, kvStoreImpl); - service.CloseKvStore(appIdTest, storeId); - service.CloseKvStore(appIdTest, storeId); -} - -void DeleteKvStoreFuzzTest(const uint8_t *data, size_t size) -{ - StoreId storeId; - storeId.storeId = std::string(data, data + size); - service.DeleteKvStore(appIdTest, storeId, createTest.baseDir); - - std::shared_ptr kvStoreImpl; - service.GetSingleKvStore(createTest, appIdTest, storeId, kvStoreImpl); - service.CloseKvStore(appIdTest, storeId); - service.DeleteKvStore(appIdTest, storeId, createTest.baseDir); - - service.CloseKvStore(appIdTest, storeId); -} - -void DeleteAllKvStoreFuzz1Test(const uint8_t *data, size_t size) -{ - std::vector storeIds; - service.GetAllKvStoreId(appIdTest, storeIds); - - service.DeleteAllKvStore(appIdTest, createTest.baseDir); - std::shared_ptr KvStore; - std::string storeIdBase(data, data + size); - - int sum = 10; - for (int i = 0; i < sum; i++) { - StoreId storeId; - storeId.storeId = storeIdBase + "_" + std::to_string(i); - service.GetSingleKvStore(createTest, appIdTest, storeId, KvStore); - - service.CloseKvStore(appIdTest, storeId); - } - service.DeleteAllKvStore(appIdTest, createTest.baseDir); -} - -void DeleteAllKvStoreFuzz2Test(const uint8_t *data, size_t size) -{ - std::vector storeIds; - service.GetAllKvStoreId(appIdTest, storeIds); - - std::shared_ptr KvStore; - std::string storeIdBase(data, data + size); - service.GetSingleKvStore(create, appIdTest, storeIdTest, KvStore); - service.CloseKvStore(appIdTest, storeIdTest); - int sum = 10; - - for (int i = 0; i < sum; i++) { - StoreId storeId; - storeId.storeId = storeIdBase + "_" + std::to_string(i); - service.GetSingleKvStore(create, appIdTest, storeId, KvStore); - } - service.DeleteAllKvStore(appIdTest, createTest.baseDir); -} - -void DeleteAllKvStoreFuzz3Test(const uint8_t *data, size_t size) -{ - std::vector storeIds; - service.GetAllKvStoreId(appIdTest, storeIds); - - std::shared_ptr KvStore; - std::string storeIdBase(data, data + size); - int sum = 10; - for (int i = 0; i < sum; i++) { - StoreId storeId; - storeId.storeId = storeIdBase + "_" + std::to_string(i); - service.GetSingleKvStore(create, appIdTest, storeId, KvStore); - } - service.DeleteAllKvStore(appIdTest, createTest.baseDir); -} - -void RegisterKvStoreServiceDeathRecipientFuzzTest() -{ - std::shared_ptr kvStoreDeathRecipientImpl = std::make_shared(); - service.RegisterKvStoreServiceDeathRecipient(kvStoreDeathRecipientImpl); - kvStoreDeathRecipientImpl->OnRemoteDied(); -} - -void UnRegisterKvStoreServiceDeathRecipientFuzzTest() -{ - std::shared_ptr kvStoreDeathRecipientImpl = std::make_shared(); - - service.UnRegisterKvStoreServiceDeathRecipient(kvStoreDeathRecipientImpl); - kvStoreDeathRecipientImpl->OnRemoteDied(); -} - -void PutSwitchFuzzTest(const uint8_t *data, size_t size) -{ - std::string appIds(data, data + size); - uint32_t input = static_cast(size); - SwitchData switchData11; - switchData11.value = input; - switchData11.length = input & 0xFFFF; - - service.PutSwitch({ appIds }, switchData11); - service.PutSwitch({ "distributed_device_profile_service" }, switchData11); -} - -void GetSwitchFuzzTest(const uint8_t *data, size_t size) -{ - std::string appIds(data, data + size); - std::string networkId(data, data + size); - - service.GetSwitch({ appIds }, networkId); - service.GetSwitch({ "distributed_device_profile_service" }, networkId); -} - -void SubscribeSwitchDataFuzzTest(const uint8_t *data, size_t size) -{ - std::string appIds(data, data + size); - std::shared_ptr dataObserver = std::make_shared(); - - service.SubscribeSwitchData({ appIds }, dataObserver); -} - -void UnsubscribeSwitchDataFuzzTest(const uint8_t *data, size_t size) -{ - std::string appIds(data, data + size); - std::shared_ptr dataObserver = std::make_shared(); - - service.SubscribeSwitchData({ appIds }, dataObserver); - service.UnsubscribeSwitchData({ appIds }, dataObserver); -} -} // namespace OHOS - -/* Fuzzer entry point */ -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - /* Run your code on data */ - OHOS::SetUpTestCase(); - OHOS::GetKvStoreFuzzTest(data, size); - OHOS::GetAllKvStoreFuzzTest(data, size); - OHOS::CloseKvStoreFuzzTest(data, size); - OHOS::DeleteKvStoreFuzzTest(data, size); - OHOS::DeleteAllKvStoreFuzz1Test(data, size); - OHOS::DeleteAllKvStoreFuzz2Test(data, size); - OHOS::DeleteAllKvStoreFuzz3Test(data, size); - OHOS::RegisterKvStoreServiceDeathRecipientFuzzTest(); - OHOS::UnRegisterKvStoreServiceDeathRecipientFuzzTest(); - OHOS::PutSwitchFuzzTest(data, size); - OHOS::GetSwitchFuzzTest(data, size); - OHOS::SubscribeSwitchDataFuzzTest(data, size); - OHOS::UnsubscribeSwitchDataFuzzTest(data, size); - OHOS::TearDown(); - return 0; -} \ No newline at end of file diff --git a/kv_store/test/fuzztest/jsonservice_fuzzer/BUILD.gn b/kv_store/test/fuzztest/jsonservice_fuzzer/BUILD.gn deleted file mode 100644 index eeae1c0937fd46743874e2cc9125c00410706645..0000000000000000000000000000000000000000 --- a/kv_store/test/fuzztest/jsonservice_fuzzer/BUILD.gn +++ /dev/null @@ -1,147 +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. - -import("//build/config/features.gni") -import("//build/test.gni") - -module_output_path = "kv_store/kv_store" - -############################################################################### -config("module_private_config") { - visibility = [ ":*" ] - - include_dirs = [ - "../../../gaussdb_rd/include", - "../../../gaussdb_rd/src/common/include", - "../../../gaussdb_rd/src/executor/include", - "../../../gaussdb_rd/src/executor/document", - "../../../gaussdb_rd/src/oh_adapter/include", - "../../../gaussdb_rd/src/oh_adapter/src", - "../../../gaussdb_rd/src/interface/include", - ] - - defines = [ - "SQLITE_ENABLE_SNAPSHOT", - "SQLITE_HAS_CODEC", - "SQLITE_ENABLE_JSON1", - "USING_HILOG_LOGGER", - "USE_SQLITE_SYMBOLS", - "SQLITE_ENABLE_DROPTABLE_CALLBACK", - ] -} - -############################################################################### -ohos_source_set("src_file") { - testonly = true - - sources = [ - "../../../gaussdb_rd/src/common/src/collection_option.cpp", - "../../../gaussdb_rd/src/common/src/db_config.cpp", - "../../../gaussdb_rd/src/common/src/grd_api_manager.cpp", - "../../../gaussdb_rd/src/common/src/json_common.cpp", - "../../../gaussdb_rd/src/common/src/os_api.cpp", - "../../../gaussdb_rd/src/common/src/rd_log_print.cpp", - "../../../gaussdb_rd/src/executor/base/grd_db_api.cpp", - "../../../gaussdb_rd/src/executor/document/check_common.cpp", - "../../../gaussdb_rd/src/executor/document/grd_document_api.cpp", - "../../../gaussdb_rd/src/executor/document/grd_document_api_inner.cpp", - "../../../gaussdb_rd/src/executor/document/grd_resultset_api.cpp", - "../../../gaussdb_rd/src/executor/document/grd_resultset_api_inner.cpp", - "../../../gaussdb_rd/src/executor/kv/grd_kv_api.cpp", - "../../../gaussdb_rd/src/executor/kv/grd_kv_api_inner.cpp", - "../../../gaussdb_rd/src/interface/src/collection.cpp", - "../../../gaussdb_rd/src/interface/src/doc_errno.cpp", - "../../../gaussdb_rd/src/interface/src/document_key.cpp", - "../../../gaussdb_rd/src/interface/src/document_store.cpp", - "../../../gaussdb_rd/src/interface/src/document_store_manager.cpp", - "../../../gaussdb_rd/src/interface/src/projection_tree.cpp", - "../../../gaussdb_rd/src/interface/src/result_set.cpp", - "../../../gaussdb_rd/src/interface/src/result_set_common.cpp", - "../../../gaussdb_rd/src/oh_adapter/src/kv_store_manager.cpp", - "../../../gaussdb_rd/src/oh_adapter/src/rd_json_object.cpp", - "../../../gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp", - "../../../gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.cpp", - ] - - configs = [ ":module_private_config" ] - - deps = [ "//third_party/sqlite:sqlite" ] - - configs += [ "//third_party/cJSON:cJSON_config" ] - ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps += [ "//third_party/cJSON:cjson" ] - external_deps = [ - "c_utils:utils", - "hilog:libhilog", - "hisysevent:libhisysevent", - "hitrace:hitrace_meter", - ] - - subsystem_name = "distributeddatamgr" - part_name = "kv_store" -} - -ohos_fuzztest("JsonServiceFuzzTest") { - module_out_path = module_output_path - fuzz_config_file = "../jsonservice_fuzzer" - - if (!defined(deps)) { - deps = [] - } - if (!defined(external_deps)) { - external_deps = [] - } - configs = [ ":module_private_config" ] - deps += [ - ":src_file", - "//third_party/sqlite:sqlite", - ] - configs += [ "//third_party/cJSON:cJSON_config" ] - ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps += [ - "//third_party/cJSON:cjson", - "//third_party/openssl:libcrypto_shared", - ] - external_deps = [ - "c_utils:utils", - "hilog:libhilog", - "hisysevent:libhisysevent", - "hitrace:hitrace_meter", - ] - - cflags = [ - "-g", - "-O0", - "-Wno-unused-variable", - "-fno-omit-frame-pointer", - "--coverage", - ] - - ldflags += [ "--coverage" ] - - cflags_cc = [ "--coverage" ] - - sources = [ "jsonservice_fuzzer.cpp" ] -} - -############################################################################### - -group("fuzztest") { - testonly = true - deps = [] - deps += [ - # deps file - ":JsonServiceFuzzTest", - ] -} -############################################################################### diff --git a/kv_store/test/fuzztest/jsonservice_fuzzer/jsonservice_fuzzer.cpp b/kv_store/test/fuzztest/jsonservice_fuzzer/jsonservice_fuzzer.cpp deleted file mode 100644 index 2650f0747128ccf85cb4ca533a44e88a65253abd..0000000000000000000000000000000000000000 --- a/kv_store/test/fuzztest/jsonservice_fuzzer/jsonservice_fuzzer.cpp +++ /dev/null @@ -1,1671 +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 "jsonservice_fuzzer.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "grd_base/grd_db_api.h" -#include "grd_base/grd_error.h" -#include "grd_base/grd_resultset_api.h" -#include "grd_documentVirtual/grd_documentVirtual_api.h" -#include "grd_kv/grd_kv_api.h" -#include "grd_resultset_inner.h" -#include "securec.h" -#include -#include -#include -#include -#include - -const char *TEST_DB = "./data"; -const char *TEST_FILE = "./data/testfile"; -const char *COLLECT_NAME = "collectionname"; -const char *OPTION_STRING = "{ \"maxdoc\" : 1000}"; -const char *CONFIG_STRING = "{}"; -const char *DB_DIR_PATH = "./data/"; -const char *NO_EXIST_COLLECTION_NAME = "no_exisit"; -const int NUM_THREE = 3; -const int SMALL_PREFIX_LENGTH = 5; -const int NUM_FIFTEEN = 15; -const int NUM_NINETY_EIGHT = 98; -const int BATCH_COUNT = 100; -const int LESS_HALF_BYTES = 511; -const int HALF_BYTES = 512; -const int MORE_HALF_BYTES = 513; -const int HALF_HALF_BYTES = 256; -const int MORE_HALF_HALF_BYTES = 257; -const int MAX_LEN_NUM = 600; -const int LESS_MIDDLE_SIZE_TEST = 899; -const int MIDDLE_SIZE_TEST = 900; -const int MAX_SIZE_NUM_TEST = 1000; -const int ONE_BYTES = 1024; -const int CURSOR_COUNT_TEST = 50000; -const int VECTOR_SIZE = 100000; - -static GRD_DB *g_datatest = nullptr; - -namespace OHOS { -namespace { -int RemoveDirTest(const char *dirTest) -{ - if (dirTest == nullptr) { - return -1; - } - struct stat dirStatus; - if (stat(dirTest, &dirStatus) < 0) { - return -1; - } - if (access(dirTest, F_OK) != 0) { - return 0; - } - char dirNameVirtual[PATH_MAX]; - DIR *dirPtrTest = nullptr; - struct dirent *dr = nullptr; - if (S_ISREG(dirStatus.st_mode)) { // normal file - remove(dirTest); - } else if (S_ISDIR(dirStatus.st_mode)) { - dirPtrTest = opendir(dirTest); - while ((dr = readdir(dirPtrTest)) != nullptr) { - // ignore . and .. - if ((strcmp(".", dr->d_name) == 0) || (strcmp("..", dr->d_name) == 0)) { - continue; - } - if (sprintf_s(dirNameVirtual, sizeof(dirNameVirtual), "%s / %s", dirTest, dr->d_name) < 0) { - (void)RemoveDirTest(dirNameVirtual); - closedir(dirPtrTest); - rmdir(dirTest); - return -1; - } - (void)RemoveDirTest(dirNameVirtual); - } - closedir(dirPtrTest); - rmdir(dirTest); // remove empty dirTest - } else { - return -1; - } - return 0; -} - -void MakeDirctionary(const char *dirTest) -{ - std::string tmpPathVirtual; - const char *pcur = dirTest; - - while (*pcur++ != '\0') { - tmpPathVirtual.push_back(*(pcur - 1)); - if ((*pcur == '/' || *pcur == '\0') && access(tmpPathVirtual.c_str(), 0) != 0 && !tmpPathVirtual.empty()) { - if (mkdir(tmpPathVirtual.c_str(), (S_IRUSR | S_IWUSR | S_IXUSR)) != 0) { - return; - } - } - } -} - -std::string GetMaxString() -{ - std::string str = "{"; - for (int i = 0; i <= MAX_SIZE_NUM_TEST; i++) { - for (int j = 0; j <= MAX_LEN_NUM; j++) { - str += "a"; - } - } - return str + "}"; -} -} // namespace - -void InsertDocOneFuzzTest(const std::string &documentVirtualData) -{ - std::string documentVirtual2 = "{\"id\":2,\"field\":\"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual2.c_str(), 0); - std::string documentVirtual3 = "{\"id\":true,\"field\":\"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual3.c_str(), 0); - std::string documentVirtual4 = "{\"id\" : null, \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual4.c_str(), 0); - std::string documentVirtual5 = "{\"id\" : [\"2\"], \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual5.c_str(), 0); - std::string documentVirtual6 = "{\"id\" : {\"val\" : \"2\"}, \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual6.c_str(), 0); - std::string documentVirtual7 = "{\"id\" : \"3\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual7.c_str(), 0); - std::string documentVirtual9 = "{\"id\" : \"4\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(NULL, COLLECT_NAME, documentVirtual9.c_str(), 0); - std::string documentVirtual10 = "{\"id\" : \"5\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, NULL, documentVirtual10.c_str(), 0); - std::string documentVirtual12 = "{\"id\" : \"6\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual12.c_str(), 1); - std::string documentVirtual13 = "{\"id\" : \"7\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual13.c_str(), INT_MAX); - std::string documentVirtual14 = "{\"id\" : \"8\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual14.c_str(), INT_MIN); - GRD_InsertDocument(g_datatest, NULL, NULL, 0); - std::string documentVirtual15 = "{\"id\" : \"9\", \"name\" : \"" + documentVirtualData + "\"}"; - std::string collectName2(HALF_BYTES, 'a'); - GRD_InsertDocument(g_datatest, collectName2.c_str(), documentVirtual15.c_str(), 0); - const char *collectName = "collection@!#"; - std::string documentVirtual18 = "{\"id\" : \"18\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual18.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual19.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual20.c_str(), 0); - std::string documentVirtual21 = "{\"id\" : \"21\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, collectName, documentVirtual21.c_str(), GRD_OK); - std::string collectName1(HALF_HALF_BYTES, 'k'); -} - -void InsertDocTwoFuzzTest(const std::string &documentVirtualData) -{ - std::string documentVirtualPart1 = "{ \"id\" : \"15\", \"textVal\" : \" "; - std::string documentVirtualPart2 = "\" }"; - std::string jsonVal = - std::string(HALF_BYTES * ONE_BYTES - documentVirtualPart1.size() - documentVirtualPart2.size(), 'k'); - std::string documentVirtual = documentVirtualPart1 + jsonVal + documentVirtualPart2; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual.c_str(), 0); - std::string jsonVal2 = - std::string(HALF_BYTES * ONE_BYTES - 1 - documentVirtualPart1.size() - documentVirtualPart2.size(), 'k'); - std::string documentVirtual21 = documentVirtualPart1 + jsonVal2 + documentVirtualPart2; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual21.c_str(), 0); - std::string documentVirtual22 = "{\"id\" : \"16\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual22.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual23.c_str(), 0); - std::string documentVirtual24 = documentVirtualData; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual24.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual25.c_str(), 0); - std::string collectName3 = std::string(HALF_HALF_BYTES, 'k'); - std::string documentVirtual26 = "{\"id\" : \"22\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, collectName3.c_str(), documentVirtual26.c_str(), GRD_OK); - std::string collectName4 = "Aads_sd__23Asb_"; - std::string documentVirtual27 = "{\"id\" : \"23\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, collectName4.c_str(), documentVirtual27.c_str(), GRD_OK); - std::string collectName5 = "GRD_collectName"; - std::string documentVirtual28 = "{\"id\" : \"24\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_CreateCollect(g_datatest, collectName5.c_str(), "", 0); - GRD_InsertDocument(g_datatest, collectName5.c_str(), documentVirtual28.c_str(), 0); - collectName5 = "GM_SYS__collectName"; - std::string documentVirtual29 = "{\"id\" : \"24_2\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_CreateCollect(g_datatest, collectName5.c_str(), "", 0); - GRD_InsertDocument(g_datatest, collectName5.c_str(), documentVirtual29.c_str(), 0); - - collectName5 = "grd_collectName"; - std::string documentVirtual30 = "{\"id\" : \"24_3\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_CreateCollect(g_datatest, collectName5.c_str(), "", 0); - GRD_InsertDocument(g_datatest, collectName5.c_str(), documentVirtual30.c_str(), 0); -} - -void InsertDocThreeFuzzTest(const std::string &documentVirtualData) -{ - std::string collectName5 = "gm_sys_collectName"; - std::string documentVirtual31 = "{\"id\" : \"24_4\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_CreateCollect(g_datatest, collectName5.c_str(), "", 0); - GRD_InsertDocument(g_datatest, collectName5.c_str(), documentVirtual31.c_str(), 0); - - collectName5 = "gM_sYs_collectName"; - std::string documentVirtual32 = "{\"id\" : \"24_5\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_CreateCollect(g_datatest, collectName5.c_str(), "", 0); - GRD_InsertDocument(g_datatest, collectName5.c_str(), documentVirtual32.c_str(), 0); - - collectName5 = "gRd_collectName"; - std::string documentVirtual33 = "{\"id\" : \"24_6\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_CreateCollect(g_datatest, collectName5.c_str(), "", 0); - GRD_InsertDocument(g_datatest, collectName5.c_str(), documentVirtual33.c_str(), 0); - - collectName5 = "gRd@collectName"; - std::string documentVirtual34 = "{\"id\" : \"24_7\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_CreateCollect(g_datatest, collectName5.c_str(), "", 0); - GRD_InsertDocument(g_datatest, collectName5.c_str(), documentVirtual34.c_str(), 0); - - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual35.c_str(), 0); - - std::string documentVirtual36 = "{\"id\" : \"36_4\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_CreateCollect(g_datatest, collectName5.c_str(), "", 0); - GRD_InsertDocument(g_datatest, collectName5.c_str(), documentVirtual36.c_str(), 0); - - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual36.c_str(), 0); - std::string documentVirtual37 = "{\"id\" : \"37_4\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual37.c_str(), 0); - std::string documentVirtual38 = "{\"id\" : \"38_8\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual38.c_str(), 0); -} - -void InsertDocFourFuzzTest(const std::string &longId, const std::string &documentVirtualData) -{ - std::string documentVirtual39 = - "{\"id\" : \"35\", \"A_aBdk_324_\" : \"" + documentVirtualData + - "\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual39.c_str(), 0); - - std::string documentVirtual40 = "{\"id\" : \"35_2\", \"1A_aBdk_324_\" : \"" + documentVirtualData + - "\", " - "\"name\" : \"" + - documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual40.c_str(), 0); - std::string documentVirtual41 = "{\"id\" : \"36_0\", \"stringType\" : \"" + documentVirtualData + - documentVirtualData + ", \"objectType\" : {\"A\" : 3}}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual41.c_str(), 0); - - std::string documentVirtual42 = "({\"id\" : \"38_0\", \"field2\" : 1.7693" + longId + "13486232e308})"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual42.c_str(), 0); - std::string documentVirtual43 = - "({\"id\" : \"38_1\", \"t1\" : {\"field2\" : 1.797" + longId + "693134862e308}})"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual43.c_str(), 0); - std::string documentVirtual44 = "({\"id\" : \"38_2\", \"t1\" : [1, 2, 1.797313486" + longId + "232e308]})"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual44.c_str(), 0); - std::string documentVirtual45 = "({\"id\" : \"38_3\", \"t1\" : [1, 2, -1.79763486167" + longId + "E+308]})"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual45.c_str(), 0); - std::string documentVirtual46 = - "({\"id\" : \"38_4\", \"t1\" : [1, 2, -1." + longId + "79763486231570E+308]})"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual46.c_str(), 0); - std::string documentVirtual47 = - "({\"id\" : \"38_5\", \"t1\" : [1, 2, 1.79769313486" + longId + "2370E+308]})"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual47.c_str(), 0); - - std::string doc1 = "{\"id\" : "; - std::string doc2 = "\""; - std::string doc4 = "\""; - std::string doc5 = ", \"name\" : \"" + documentVirtualData + "\"}"; - std::string documentVirtualMiddle(MIDDLE_SIZE_TEST, 'k'); - std::string documentVirtual48 = doc1 + doc2 + documentVirtualMiddle + doc4 + doc5; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual48.c_str(), 0); - std::string documentVirtualMiddle2(MAX_SIZE_NUM_TEST, 'k'); - documentVirtual48 = doc1 + doc2 + documentVirtualMiddle2 + doc4 + doc5; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual48.c_str(), 0); - - std::string documentVirtual49 = "({\"id\":\"0123\", \"num\":\"" + documentVirtualData + "\"})"; - std::string documentVirtual50 = "({\"id\":\"0123\", \"NUM\":\"" + documentVirtualData + "\"})"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual49.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual50.c_str(), 0); - - std::string documentVirtual51 = "({\"id\":\"0123\", \"num.\":\"" + documentVirtualData + "\"})"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual51.c_str(), 0); - - const char *documentVirtual52 = R""({})""; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual52, 0); -} - -void InsertDocFuzzTest(const uint8_t *data, size_t size) -{ - std::string collectNameData(reinterpret_cast(data), size); - const char *collectNameVal = collectNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); - const char *optionStrVal = optionStrData.data(); - GRD_CreateCollect(g_datatest, collectNameVal, optionStrVal, 0); - std::string documentVirtualData(reinterpret_cast(data), size); - const char *documentVirtualVal = documentVirtualData.data(); - GRD_InsertDocument(g_datatest, collectNameVal, documentVirtualVal, 0); - GRD_InsertDocument(g_datatest, collectNameVal, documentVirtualVal, 0); - std::string strJson = "{" + documentVirtualData + "}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, strJson.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, strJson.c_str(), 0); - std::string stringJson2 = "{\"id\":\"1\",\"field\":\"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, stringJson2.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, stringJson2.c_str(), 0); - std::string longId = "1"; - for (int i = 0; i < MAX_SIZE_NUM_TEST; i++) { - longId += "1"; - } - longId = "{\"id\":\"" + longId + "\",\"field\":\"field_id\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, longId.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, "{\"id\":123}", 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, "{\"field1.field2.field&*^&3\":\"anc\"}", 0); - InsertDocOneFuzzTest(documentVirtualData); - InsertDocTwoFuzzTest(documentVirtualData); - InsertDocThreeFuzzTest(documentVirtualData); - InsertDocFourFuzzTest(longId, documentVirtualData); - - const char *documentVirtual53 = R""({"empty" : null})""; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual53, 0); - GRD_DropCollect(g_datatest, collectNameVal, 0); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - - std::string documentVirtualNew1 = "{\"id\" : "; - std::string documentVirtualNew2 = "\""; - std::string documentVirtualNew3 = "\""; - std::string documentVirtualNew4 = ", \"name\" : \"Ori\"}"; - std::string documentVirtual = documentVirtualNew1 + - documentVirtualNew2 + documentVirtualData + documentVirtualNew3 + documentVirtualNew4; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual.c_str(), 0); -} - -static const char *DOCU1 = "{\"id\" : \"1\", \"name\":\"doc1\",\"item\":\"journal\",\"person\":\ - {\"school\":\"AB\", \"age\" : 51}}"; -static const char *DOCU2 = "{\"id\" : \"2\", \"name\":\"doc2\",\"item\": 1, \"person\":\ - [1, \"my string\", {\"school\":\"AB\", \"age\" : 51}, true, {\"school\":\"CD\", \"age\" : 15}, false]}"; -static const char *DOCU3 = "{\"id\" : \"3\", \"name\":\"doc3\",\"item\":\"notebook\",\"person\":\ - [{\"school\":\"C\", \"age\" : 5}]}"; -static const char *DOCU4 = "{\"id\" : \"4\", \"name\":\"doc4\",\"item\":\"paper\",\"person\":\ - {\"grade\" : 1, \"school\":\"A\", \"age\" : 18}}"; -static const char *DOCU5 = "{\"id\" : \"5\", \"name\":\"doc5\",\"item\":\"journal\",\"person\":\ - [{\"sex\" : \"woma\", \"school\" : \"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; -static const char *DOCU6 = "{\"id\" : \"6\", \"name\":\"doc6\",\"item\":false,\"person\":\ - [{\"school\":\"B\", \"teacher\" : \"mike\", \"age\" : 15},\ - {\"school\":\"C\", \"teacher\" : \"moon\", \"age\" : 20}]}"; - -static const char *DOCU7 = "{\"id\" : \"7\", \"name\":\"doc7\",\"item\":\"fruit\",\"other_Info\":\ - [{\"school\":\"BX\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; -static const char *DOCU8 = "{\"id\" : \"8\", \"name\":\"doc8\",\"item\":true,\"person\":\ - [{\"school\":\"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; -static const char *DOCU9 = "{\"id\" : \"9\", \"name\":\"doc9\",\"item\": true}"; -static const char *DOCU10 = "{\"id\" : \"10\", \"name\":\"doc10\", \"parent\" : \"kate\"}"; -static const char *DOCU11 = "{\"id\" : \"11\", \"name\":\"doc11\", \"other\" : \"null\"}"; -static const char *DOCU12 = "{\"id\" : \"12\", \"name\":\"doc12\",\"other\" : null}"; -static const char *DOCU13 = "{\"id\" : \"13\", \"name\":\"doc13\",\"item\" : \"shoes\",\"person\":\ - {\"school\":\"AB\", \"age\" : 15}}"; -static const char *DOCU14 = "{\"id\" : \"14\", \"name\":\"doc14\",\"item\" : true,\"person\":\ - [{\"school\":\"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 85}]}"; -static const char *DOCU15 = "{\"id\" : \"15\", \"name\":\"doc15\",\"person\":[{\"school\":\"C\", \"age\" : " - "5}]}"; -static const char *DOCU16 = "{\"id\" : \"16\", \"name\":\"doc16\", \"nested1\":{\"nested2\":{\"nested3\":\ - {\"nested4\":\"ABC\", \"field2\":\"CCC\"}}}}"; -static const char *DOCU17 = "{\"id\" : \"17\", \"name\":\"doc17\",\"person\":\"oh,ok\"}"; -static const char *DOCU18 = "{\"id\" : \"18\", \"name\":\"doc18\",\"item\" : \"mobile phone\",\"person\":\ - {\"school\":\"DD\", \"age\":66}, \"color\":\"blue\"}"; -static const char *DOCU19 = "{\"id\" : \"19\", \"name\":\"doc19\",\"ITEM\" : true,\"PERSONINFO\":\ - {\"school\":\"AB\", \"age\":15}}"; -static const char *DOCU20 = "{\"id\" : \"20\", \"name\":\"doc20\",\"ITEM\" : true,\"person\":\ - [{\"SCHOOL\":\"B\", \"AGE\":15}, {\"SCHOOL\":\"C\", \"AGE\":35}]}"; -static const char *DOCU23 = "{\"id\" : \"23\", \"name\":\"doc22\",\"ITEM\" : " - "true,\"person\":[{\"school\":\"b\", \"age\":15}, [{\"school\":\"doc23\"}, 10, " - "{\"school\":\"doc23\"}, true, {\"school\":\"y\"}], {\"school\":\"b\"}]}"; -static std::vector g_datatest = { DOCU1, DOCU2, DOCU3, DOCU4, DOCU5, - DOCU6, DOCU7, DOCU8, DOCU9, DOCU10, DOCU11, DOCU12, DOCU13, - DOCU14, DOCU15, DOCU16, DOCU17, DOCU18, DOCU19, DOCU20, DOCU23 }; - -namespace { -static void InsertData(GRD_DB *g_datatest, const char *collectName) -{ - for (const auto &item : g_datatest) { - GRD_InsertDocument(g_datatest, collectName, item, 0); - } -} - -void SetUpTestCase() -{ - (void)RemoveDirTest(TEST_DB); - MakeDirctionary(TEST_DB); - GRD_DBOpen(TEST_FILE, CONFIG_STRING, GRD_OPEN_CREATE, &g_datatest); - InsertData(g_datatest, COLLECT_NAME); - GRD_CreateCollect(g_datatest, COLLECT_NAME, OPTION_STRING, 0); -} - -void TearDownTestCase() -{ - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - GRD_DBClose(g_datatest, GRD_CLOSE); - (void)RemoveDirTest(TEST_DB); - g_datatest = nullptr; -} - -void FindDocumentResultSetFuzzTest(const char *colName, const std::string &filt, const std::string &projectInfo) -{ - GRD_ResultSet *reSet = nullptr; - Query query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, colName, query, 1, &reSet); - if (reSet != nullptr) { - GRD_Next(reSet); - char *valueResult = nullptr; - GRD_GetVal(reSet, &valueResult); - } - GRD_FreeRe(reSet); -} - -void FindDocumentWithFlagFuzzTest(const std::string &filt, const std::string &projectInfo, int flag) -{ - GRD_ResultSet *reSet = nullptr; - Query query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, flag, &reSet); - GRD_Next(reSet); - char *value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); -} - -void FindDocumentNextTwiceFuzzTest(const std::string &filt, const std::string &projectInfo) -{ - GRD_ResultSet *reSet = nullptr; - Query query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_Next(reSet); - GRD_Next(reSet); - char *value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); -} - -void FindDocumentZeroFuzzTest(const std::string &input) -{ - std::string filt = "{\"id\" : \"6\"}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - filt = "{\"id\" : \"6\", \"name\":\"" + input + "\"}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - filt = "{\"name\":\"" + input + "\"}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - filt = "{\"id\" : \"" + input + "\"}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - filt = "{\"id\" : 1}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - filt = "{\"id\" : [\"" + input + "\", 1]}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - filt = "{\"id\" : {\"" + input + "\" : \"1\"}}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - filt = "{\"id\" : true}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - filt = "{\"id\" : null}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - const char *colName1 = "grd_type"; - const char *colName2 = "GM_SYS_sysfff"; - filt = "{\"id\" : \"1\"}"; - FindDocumentResultSetFuzzTest(colName1, filt, R"({})"); - FindDocumentResultSetFuzzTest(colName2, filt, R"({})"); - - filt = "{\"id\" : \"100\"}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); -} - -void FindDocumentOneFuzzTest() -{ - std::string filt = "{\"id\" : \"6\"}"; - GRD_ResultSet *reSet = nullptr; - GRD_ResultSet *reSet2 = nullptr; - Query query = { filt.c_str(), "{}" }; - const char *collectName = "DocumentDBFindTest024"; - GRD_CreateCollect(g_datatest, collectName, "", 0); - InsertData(g_datatest, collectName); - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_FindDocument(g_datatest, collectName, query, 1, &reSet2); - - GRD_Next(reSet); - char *value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - - GRD_Next(reSet2); - char *value2 = nullptr; - GRD_GetVal(reSet2, &value2); - GRD_FreeVal(value2); - - GRD_Next(reSet); - GRD_Next(reSet2); - GRD_GetVal(reSet, &value); - GRD_GetVal(reSet2, &value); - GRD_FreeRe(reSet); - GRD_FreeRe(reSet2); - GRD_DropCollect(g_datatest, collectName, 0); - - filt = "{\"id\" : \"16\"}"; - reSet = nullptr; - std::string projectInfo = "{\"name\": true, \"nested1.nested2.nested3.nested4\":true}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_Next(reSet); - value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - GRD_FreeRe(reSet); - - projectInfo = "{\"name\": true, \"nested1\":{\"nested2\":{\"nested3\":{\"nested4\":true}}}}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - GRD_FreeRe(reSet); -} - -void FindDocumentTwoFuzzTest(const std::string &input) -{ - GRD_ResultSet *reSet = nullptr; - std::string projectInfo = "{\"name\": 0, \"nested1.nested2.nested3.nested4\":0}"; - std::string filt = "{\"id\" : \"16\"}"; - Query query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_Next(reSet); - char *value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); - - projectInfo = "{\"name\": \"" + input + "\", \"nested1.nested2.nested3.nested4\":\"" + input + "\"}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, projectInfo); - - filt = "{\"id\" : \"7\"}"; - reSet = nullptr; - projectInfo = "{\"name\": true, \"other_Info\":true, \"non_exist_field\":true}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_Next(reSet); - value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); - - projectInfo = "{\"name\": true, \"other_Info\":true, \" item \":true}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, projectInfo); -} - -void FindDocumentThreeFuzzTest(const std::string &input) -{ - std::string filt = "{\"id\" : \"7\"}"; - GRD_ResultSet *reSet = nullptr; - std::string projectInfo = "{\"name\": true, \"other_Info.non_exist_field\":true}"; - Query query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_Next(reSet); - char *value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); - projectInfo = "{\"name\": true, \"other_Info\":{\"non_exist_field\":true}}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, projectInfo); - projectInfo = "{\"name\": true, \"other_Info.0\": true}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, projectInfo); - filt = "{\"id\" : \"4\"}"; - reSet = nullptr; - projectInfo = "{\"person\": true, \"person.grade\": true}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - - filt = "{\"id\" : \"7\"}"; - projectInfo = "{\"non_exist_field\":true}"; - int flag = 0; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - flag = 1; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - filt = "{\"id\" : \"7\"}"; - projectInfo = "{\"name\":true, \"item\":true}"; - flag = 0; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - flag = 1; - projectInfo = "{\"name\": " + input + ", \"item\": " + input + "}"; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - filt = "{\"id\" : \"7\"}"; - projectInfo = "{\"name\":false, \"item\":false}"; - flag = 0; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - flag = 1; - projectInfo = "{\"name\": " + input + ", \"item\": " + input + "}"; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - filt = "{\"id\" : \"4\"}"; - flag = 0; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - projectInfo = "{\"name\": false, \"person.grade1\": false, \ - \"person.shool1\": false, \"person.age1\": false}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, projectInfo); -} - -void FindDocumentFourFuzzTest(const std::string &input) -{ - std::string filt = "{\"id\" : \"4\"}"; - std::string projectInfo = - "{\"name\": " + input + ", \"person.school\": " + input + ", \"person.age\": " + input + "}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, projectInfo); - - filt = "{\"id\" : \"17\"}"; - GRD_ResultSet *reSet = nullptr; - Query query = { filt.c_str(), "{}" }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, GRD_DOC_ID_DISPLAY, &reSet); - GRD_Next(reSet); - char *value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - GRD_FreeRe(reSet); - - reSet = nullptr; - query = { filt.c_str(), "{}" }; - GRD_FindDocument(g_datatest, "", query, 0, &reSet); - GRD_FindDocument(g_datatest, nullptr, query, 0, &reSet); - - filt = "{\"id\" : \"4\"}"; - reSet = nullptr; - projectInfo = "{\"name\":" + input + ", \"person\":0, \"item\":" + input + "}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - - projectInfo = "{\"name\":true, \"person\":0, \"item\":true}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - - projectInfo = "{\"name\":\"\", \"person\":0, \"item\":\"\"}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - - projectInfo = "{\"name\":false, \"person\":1, \"item\":false"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - - projectInfo = "{\"name\":false, \"person\":-1.123, \"item\":false"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - - projectInfo = "{\"name\":false, \"person\":true, \"item\":false"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); -} - -void FindDocumentFiveFuzzTest(const std::string &input) -{ - std::string filt = "{\"id\" : \"6\"}"; - std::string projectInfo = "{\"name\":false, \"person\": 0, \"item\":0}"; - int flag = 0; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - - filt = "{\"id\" : \"18\"}"; - projectInfo = "{\"name\":true, \"person.age\": \"\", \"item\":1, \"color\":10, \"nonExist\" : " - "-100}"; - flag = 0; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - - GRD_ResultSet *reSet = nullptr; - projectInfo = "{\"person\":[true, " + input + "]}"; - flag = 1; - Query query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, flag, &reSet); - projectInfo = "{\"person\":null}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, flag, &reSet); - reSet = nullptr; - projectInfo = "{\"Name\":true, \"person.age\": \"\", \"item\":" + input + ", \"COLOR\":" + input + - ", \"nonExist\" : " - "" + - input + "}"; - flag = 0; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, flag, &reSet); - GRD_Next(reSet); - GRD_FreeRe(reSet); - - reSet = nullptr; - projectInfo = "{\"Name\":" + input + ", \"person.age\": false, \"person.SCHOOL\": false, \"item\":\ - false, \"COLOR\":false, \"nonExist\" : false}"; - query = { filt.c_str(), projectInfo.c_str() }; - char *value = nullptr; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_Next(reSet); - GRD_FreeRe(reSet); - - filt = "{\"id\" : \"18\"}"; - reSet = nullptr; - query = { filt.c_str(), "{}" }; - std::string collectName1(LESS_HALF_BYTES, 'a'); - GRD_FindDocument(g_datatest, collectName1.c_str(), query, 1, &reSet); - GRD_FreeRe(reSet); -} - -void FindDocumentSixFuzzTest(const std::string &input) -{ - std::string collectName2(HALF_BYTES, 'a'); - std::string filt = "{\"id\" : \"18\"}"; - Query query = { filt.c_str(), "{}" }; - GRD_ResultSet *reSet = nullptr; - GRD_FindDocument(g_datatest, collectName2.c_str(), query, 1, &reSet); - GRD_FindDocument(g_datatest, "", query, 1, &reSet); - - reSet = nullptr; - std::string projectInfo = "{}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, NUM_THREE, &reSet); - GRD_FindDocument(g_datatest, COLLECT_NAME, query, INT_MAX, &reSet); - GRD_FindDocument(g_datatest, COLLECT_NAME, query, INT_MIN, &reSet); - GRD_FindDocument(nullptr, COLLECT_NAME, query, 0, &reSet); - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, nullptr); - query = { nullptr, nullptr }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - - std::string documentVirtual1 = "{\"id\" : "; - std::string documentVirtual2 = "\""; - std::string documentVirtual4 = "\""; - std::string documentVirtual5 = "}"; - std::string documentVirtualMiddle(MIDDLE_SIZE_TEST, 'k'); - filt = documentVirtual1 + documentVirtual2 + documentVirtualMiddle + documentVirtual4 + documentVirtual5; - reSet = nullptr; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - std::string documentVirtualMiddle2(LESS_MIDDLE_SIZE_TEST, 'k'); - filt = documentVirtual1 + documentVirtual2 + documentVirtualMiddle2 + documentVirtual4 + documentVirtual5; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_FreeRe(reSet); - - filt = "{\"person\" : {\"school\":\"" + input + "\"}}"; - FindDocumentNextTwiceFuzzTest(filt, R"({})"); - - projectInfo = "{\"version\": " + input + "}"; - FindDocumentNextTwiceFuzzTest(filt, projectInfo); - - projectInfo = "({\"a00001\":" + input + ", \"a00001\":" + input + "})"; - FindDocumentNextTwiceFuzzTest(filt, projectInfo); - - projectInfo = "({\"abc123_.\":" + input + "})"; - FindDocumentNextTwiceFuzzTest(filt, projectInfo); - - filt = "({\"abc123_.\":" + input + "})"; - FindDocumentNextTwiceFuzzTest(filt, projectInfo); -} - -void FindDocumentSevenFuzzTest(const std::string &input) -{ - std::string documentVirtual064 = "{\"id\" : \"64\", \"a\":" + input + ", \"doc64\" : " + input + "}"; - std::string documentVirtual063 = "{\"id\" : \"63\", \"a\":" + input + ", \"doc63\" : " + input + "}"; - std::string documentVirtual062 = "{\"id\" : \"62\", \"a\":" + input + ", \"doc62\" : " + input + "}"; - std::string documentVirtual061 = "{\"id\" : \"61\", \"a\":" + input + ", \"doc61\" : " + input + "}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual064.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual063.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual062.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual061.c_str(), 0); - std::string filt = "{\"a\":" + input + "}"; - GRD_ResultSet *reSet = nullptr; - std::string projectInfo = R"({})"; - Query query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_Next(reSet); - char *value = nullptr; - GRD_GetVal(reSet, &value); - - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); -} - -void FindDocumentFuzzTestPlus(const std::string &input) -{ - FindDocumentZeroFuzzTest(input); - std::string filt = "{\"id\" : \"6\"}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - FindDocumentOneFuzzTest(); - FindDocumentTwoFuzzTest(input); - FindDocumentThreeFuzzTest(input); - FindDocumentFourFuzzTest(input); - FindDocumentFiveFuzzTest(input); - FindDocumentSixFuzzTest(input); - FindDocumentSevenFuzzTest(input); - - std::string documentVirtual = "{\"a\":" + input + ", \"doc64\" : " + input + "}"; - filt = "{\"b\":" + input + "}"; - GRD_Upsert(g_datatest, COLLECT_NAME, filt.c_str(), documentVirtual.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, filt.c_str(), documentVirtual.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, filt.c_str(), documentVirtual.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, filt.c_str(), documentVirtual.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, filt.c_str(), documentVirtual.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, filt.c_str(), documentVirtual.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, filt.c_str(), documentVirtual.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, filt.c_str(), documentVirtual.c_str(), 0); - filt = "{\"a\":" + input + "}"; - GRD_ResultSet *reSet = nullptr; - std::string projectInfo = R"({})"; - Query query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_Next(reSet); - GRD_Next(reSet); - GRD_Next(reSet); - GRD_Next(reSet); - GRD_Next(reSet); - GRD_Next(reSet); - GRD_Next(reSet); - GRD_Next(reSet); - GRD_Next(reSet); - GRD_FreeRe(reSet); - filt = "{\"a\":" + input + "}"; - reSet = nullptr; - projectInfo = R"({})"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - GRD_Next(reSet); - char *valueNew = nullptr; - GRD_GetVal(reSet, &valueNew); - GRD_FreeVal(valueNew); - GRD_FreeRe(reSet); - filt = "{\"person\" : {\"school\":" + input + "}" + "}"; - FindDocumentNextTwiceFuzzTest(filt, R"({})"); -} -} // namespace - -void FindDocumentFuzzTest(const uint8_t *data, size_t size) -{ - GRD_CreateCollect(g_datatest, COLLECT_NAME, OPTION_STRING, 0); - std::string input(reinterpret_cast(data), size); - std::string inputJson11 = "{\"field\":\"" + input + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - Query query = { inputJson11.c_str(), inputJson11.c_str() }; - GRD_ResultSet *reSet = nullptr; - // ResultSet conflict - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_FreeRe(reSet); - reSet = nullptr; - GRD_FindDocument(g_datatest, input.c_str(), query, size, &reSet); - GRD_FreeRe(reSet); - GRD_FindDocument(nullptr, input.c_str(), query, 1, &reSet); - query.filt = nullptr; - GRD_FindDocument(g_datatest, input.c_str(), query, 1, &reSet); - inputJson11 = "{\"field\": 0, \"field2\":" + input + "}"; - query.filt = "{}"; - query.project = inputJson11.c_str(); - reSet = nullptr; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_FreeRe(reSet); - inputJson11 = "{\"" + input + "\": 0}"; - query.project = inputJson11.c_str(); - reSet = nullptr; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_FreeRe(reSet); - inputJson11 = "{\"field\":[\"aaa\"," + input + "]}"; - reSet = nullptr; - query.project = inputJson11.c_str(); - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_FreeRe(reSet); - query.filt = "{\"field\": false}"; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_FreeRe(reSet); - FindDocumentFuzzTestPlus(input); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); -} - -void UpdateDocOneFuzzTest(std::string s, const std::string &input) -{ - std::string inputJson11 = "{\"field5\": \"" + s + "\"}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field5\": \"" + s + s + "\"}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1\": [\"field2\", {\"field3\":\"" + input + "\"}]}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"name\":\"doc6\", \"c0\" : {\"c1\" : true } }"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"name\":\"doc6\"}", inputJson11.c_str(), 1); - inputJson11 = "{\"name\":\"doc7\", \"c0\" : {\"c1\" : null } }"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"name\":\"doc7\"}", inputJson11.c_str(), 1); - inputJson11 = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"name\":\"doc8\"}", inputJson11.c_str(), 1); - - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - GRD_UpDoc(g_datatest, inputJson11.c_str(), "{}", "{}", 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, input.c_str(), "{}", 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, "{}", input.c_str(), 0); - GRD_UpDoc(nullptr, COLLECT_NAME, "{}", "{}", 0); - inputJson11 = "{\"id\":\"2\", \"field\":" + input + "}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field\":" + input + "}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1.field2.field3.field4.field5.field6\":" + input + "}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1\": {\"field2\": {\"field3\": {\"field4\": {\"field5\":" + input + "}}}}}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - s.clear(); - for (int i = 0; i < ((ONE_BYTES * ONE_BYTES) - 1) - NUM_FIFTEEN; i++) { - s += 'a'; - } - inputJson11 = "{\"field5\": \"" + s + "\"}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field5\": \"" + s + s + "\"}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1\": [\"field2\", {\"field3\":\"" + input + "\"}]}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"name\":\"doc6\", \"c0\" : {\"c1\" : true } }"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"name\":\"doc6\"}", "{\"c0.c1\":false}", 1); - inputJson11 = "{\"name\":\"doc7\", \"c0\" : {\"c1\" : null } }"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"name\":\"doc7\"}", "{\"c0.c1\":null}", 1); - inputJson11 = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"name\":\"doc8\"}", "{\"c0.0\":\"ac\"}", 1); -} - -void UpdateDocTwoFuzzTest(const char *newCollName, std::string s, const std::string &input) -{ - std::string inputJson11 = "{\"field5\": \"" + s + "\"}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field5\": \"" + s + s + "\"}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1\": [\"field2\", {\"field3\":\"" + input + "\"}]}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"name\":\"doc6\", \"c0\" : {\"c1\" : true } }"; - GRD_UpDoc(g_datatest, newCollName, "{\"name\":\"doc6\"}", inputJson11.c_str(), 1); - inputJson11 = "{\"name\":\"doc7\", \"c0\" : {\"c1\" : null } }"; - GRD_UpDoc(g_datatest, newCollName, "{\"name\":\"doc7\"}", inputJson11.c_str(), 1); - inputJson11 = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; - GRD_UpDoc(g_datatest, newCollName, "{\"name\":\"doc8\"}", inputJson11.c_str(), 1); - - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - GRD_UpDoc(g_datatest, inputJson11.c_str(), "{}", "{}", 0); - GRD_UpDoc(g_datatest, newCollName, input.c_str(), "{}", 0); - GRD_UpDoc(g_datatest, newCollName, "{}", input.c_str(), 0); - GRD_UpDoc(nullptr, newCollName, "{}", "{}", 0); - inputJson11 = "{\"id\":\"2\", \"field\":" + input + "}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field\":" + input + "}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1.field2.field3.field4.field5.field6\":" + input + "}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1\": {\"field2\": {\"field3\": {\"field4\": {\"field5\":" + input + "}}}}}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - s.clear(); - for (int i = 0; i < ((ONE_BYTES * ONE_BYTES) - 1) - NUM_FIFTEEN; i++) { - s += 'a'; - } - inputJson11 = "{\"field5\": \"" + s + "\"}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field5\": \"" + s + s + "\"}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1\": [\"field2\", {\"field3\":\"" + input + "\"}]}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"name\":\"doc6\", \"c0\" : {\"c1\" : true } }"; - GRD_InsertDocument(g_datatest, newCollName, inputJson11.c_str(), 0); - GRD_UpDoc(g_datatest, newCollName, "{\"name\":\"doc6\"}", "{\"c0.c1\":false}", 1); - inputJson11 = "{\"name\":\"doc7\", \"c0\" : {\"c1\" : null } }"; - GRD_InsertDocument(g_datatest, newCollName, inputJson11.c_str(), 0); - GRD_UpDoc(g_datatest, newCollName, "{\"name\":\"doc7\"}", "{\"c0.c1\":null}", 1); - inputJson11 = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; - GRD_InsertDocument(g_datatest, newCollName, inputJson11.c_str(), 0); - GRD_UpDoc(g_datatest, newCollName, "{\"name\":\"doc8\"}", "{\"c0.0\":\"ac\"}", 1); -} - -void UpdateDocFilterFuzzTest() -{ - const char *filt = "{\"id\" : \"1\"}"; - const char *updata2 = "{\"objectInfo.child.child\" : {\"child\":{\"child\":null}}}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, filt, updata2, 0); - - const char *filt1 = "{\"id\" : \"1\"}"; - const char *updata1 = "{\"id\" : \"6\"}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, filt1, updata1, 0); - - const char *filt2 = "{\"id\" : \"1\"}"; - const char *updata3 = "{\"age$\" : \"21\"}"; - const char *updata4 = "{\"bonus..traffic\" : 100}"; - const char *updata5 = "{\"0item\" : 100}"; - const char *updata6 = "{\"item\" : 1.79769313486232e308}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, filt2, updata3, 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, filt2, updata4, 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, filt2, updata5, 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, filt2, updata6, 0); - - const char *filt3 = "{\"id\" : \"1\"}"; - const char *updata7 = "{\"age\" : 21}"; - GRD_UpDoc(g_datatest, NULL, filt3, updata7, 0); - GRD_UpDoc(g_datatest, "", filt3, updata7, 0); - GRD_UpDoc(NULL, COLLECT_NAME, filt3, updata7, 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, NULL, updata7, 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, filt3, NULL, 0); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); -} - -void UpdateDocFuzzTest(const uint8_t *data, size_t size) -{ - GRD_CreateCollect(g_datatest, COLLECT_NAME, OPTION_STRING, 0); - std::string input(reinterpret_cast(data), size); - std::string inputJson11 = "{\"id\":\"2\", \"field\": \"aaa\", " - "\"subject\":\"aaaaaaaaaaa\", \"test1\": true, " - "\"test2\": null}"; - - GRD_UpDoc(g_datatest, inputJson11.c_str(), "{}", "{}", 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, input.c_str(), "{}", 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, "{}", input.c_str(), 0); - GRD_UpDoc(nullptr, COLLECT_NAME, "{}", "{}", 0); - inputJson11 = "{\"id\":\"2\", \"field\":" + input + "}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field\":" + input + "}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1.field2.field3.field4.field5.field6\":" + input + "}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1\": {\"field2\": {\"field3\": {\"field4\": {\"field5\":" + input + "}}}}}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - std::string s; - for (int i = 0; i < ((ONE_BYTES * ONE_BYTES) - 1) - NUM_FIFTEEN; i++) { - s += 'a'; - } - UpdateDocOneFuzzTest(s, input); - - const char *newCollName = "./student"; - GRD_UpDoc(g_datatest, inputJson11.c_str(), "{}", "{}", 0); - GRD_UpDoc(g_datatest, newCollName, input.c_str(), "{}", 0); - GRD_UpDoc(g_datatest, newCollName, "{}", input.c_str(), 0); - GRD_UpDoc(nullptr, newCollName, "{}", "{}", 0); - inputJson11 = "{\"id\":\"2\", \"field\":" + input + "}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field\":" + input + "}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1.field2.field3.field4.field5.field6\":" + input + "}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1\": {\"field2\": {\"field3\": {\"field4\": {\"field5\":" + input + "}}}}}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - s.clear(); - for (int i = 0; i < ((ONE_BYTES * ONE_BYTES) - 1) - NUM_FIFTEEN; i++) { - s += 'a'; - } - - UpdateDocTwoFuzzTest(newCollName, s, input); - UpdateDocFilterFuzzTest(); -} - -void UpsertNewFuzzTest(const std::string &input, GRD_DB *db1) -{ - GRD_CreateCollect(g_datatest, "student", "", 0); - std::string documentVirtualNew = - "{\"name\": {\"first\":[\"XXX\", \"BBB\", \"CCC\"], \"last\":\"moray\", \"field\":" + input + "}"; - std::string updateDocNew = R""({"name.last.AA.B":"Mnado"})""; - GRD_Upsert(g_datatest, "student", R""({"id":"10001"})"", documentVirtualNew.c_str(), 0); - GRD_Upsert(db1, "student", R""({"id":"10001"})"", updateDocNew.c_str(), 1); - GRD_DropCollect(g_datatest, "student", 0); - - GRD_CreateCollect(g_datatest, "student", "", 0); - documentVirtualNew = "{\"name\":[\"Tmn\", \"BB\", \"Alice\"], \"field\":" + input + "}"; - updateDocNew = R""({"name.first":"GG"})""; - GRD_Upsert(g_datatest, "student", R""({"id":"10002"})"", documentVirtualNew.c_str(), 0); - GRD_Upsert(db1, "student", R""({"id":"10002"})"", updateDocNew.c_str(), 1); -} - -void UpsertFuzzTest(const uint8_t *data, size_t size) -{ - GRD_CreateCollect(g_datatest, COLLECT_NAME, OPTION_STRING, 0); - std::string input(reinterpret_cast(data), size); - std::string inputJson11NoId = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; - std::string inputJson11 = "{\"id\":\"1\", \"field\": " + input + "}"; - - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - GRD_Upsert(g_datatest, input.c_str(), "{}", "{}", 0); - GRD_Upsert(g_datatest, COLLECT_NAME, inputJson11.c_str(), "{}", 0); - inputJson11 = "{\"id\":\"1\", \"field\":" + input + "}"; - GRD_Upsert(g_datatest, COLLECT_NAME, "{\"id\":\"1\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"id\":\"1\", \"field\":\"" + input + "\"}"; - GRD_Upsert(g_datatest, COLLECT_NAME, "{\"id\":\"1\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field\":" + input + "}"; - GRD_Upsert(g_datatest, COLLECT_NAME, "{\"id\":\"1\"}", inputJson11.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, "{\"id\":\"1\"}", inputJson11.c_str(), 1); - GRD_Upsert(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 1); - GRD_Upsert(nullptr, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 1); - GRD_Upsert(g_datatest, COLLECT_NAME, nullptr, inputJson11.c_str(), 1); - GRD_Upsert(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), BATCH_COUNT); - - const char *newCollName = "./student"; - GRD_DB *db1 = nullptr; - GRD_CreateCollect(db1, newCollName, "", 0); - GRD_InsertDocument(db1, newCollName, inputJson11.c_str(), 0); - GRD_Upsert(db1, input.c_str(), "{}", "{}", 0); - GRD_Upsert(db1, newCollName, inputJson11.c_str(), "{}", 0); - inputJson11 = "{\"id\":\"1\", \"field\":" + input + "}"; - GRD_Upsert(db1, newCollName, "{\"id\":\"1\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"id\":\"1\", \"field\":\"" + input + "\"}"; - GRD_Upsert(db1, newCollName, "{\"id\":\"1\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field\":" + input + "}"; - GRD_Upsert(db1, newCollName, "{\"id\":\"1\"}", inputJson11.c_str(), 0); - GRD_Upsert(db1, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - GRD_Upsert(db1, newCollName, "{\"id\":\"1\"}", inputJson11.c_str(), 1); - GRD_Upsert(db1, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 1); - GRD_Upsert(db1, newCollName, "{\"id\":\"newID1999\"}", inputJson11NoId.c_str(), 0); - GRD_Upsert(db1, newCollName, "{\"id\":\"newID1999a\"}", inputJson11NoId.c_str(), 1); - GRD_Upsert(nullptr, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 1); - GRD_Upsert(db1, newCollName, nullptr, inputJson11.c_str(), 1); - GRD_Upsert(db1, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), BATCH_COUNT); - GRD_DropCollect(db1, newCollName, 0); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - - UpsertNewFuzzTest(input, db1); -} - -void DelDocResultFuzzTest(const std::string &input) -{ - const char *filt = "{\"age\" : 15}"; - GRD_DelDoc(g_datatest, COLLECT_NAME, filt, 0); - const char *filt1 = "{\"id\" : \"1\", \"age\" : 15}"; - GRD_DelDoc(g_datatest, COLLECT_NAME, filt1, 0); - std::string filt2 = "{\"id\" : \"1\", \"name\" : " + input + "}"; - GRD_DelDoc(g_datatest, COLLECT_NAME, filt2.c_str(), 1); - GRD_DelDoc(g_datatest, NULL, filt2.c_str(), 0); - GRD_DelDoc(g_datatest, "", filt2.c_str(), 1); - GRD_DelDoc(g_datatest, COLLECT_NAME, filt2.c_str(), 0); - - const char *filt3 = "{\"id\" : \"1\"}"; - GRD_ResultSet *reSet = nullptr; - Query query = { filt3, "{}" }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_DelDoc(g_datatest, COLLECT_NAME, filt3, 0); - - const char *filt4 = "{\"id\" : \"1\"}"; - std::string collectName1(LESS_HALF_BYTES, 'a'); - GRD_CreateCollect(g_datatest, collectName1.c_str(), "", 0); - GRD_DelDoc(g_datatest, collectName1.c_str(), filt4, 0); - GRD_DropCollect(g_datatest, collectName1.c_str(), 0); - GRD_FreeRe(reSet); - - GRD_DelDoc(NULL, COLLECT_NAME, filt2.c_str(), 0); - GRD_DelDoc(g_datatest, NULL, filt2.c_str(), 0); - GRD_DelDoc(g_datatest, "", filt2.c_str(), 0); - GRD_DelDoc(g_datatest, COLLECT_NAME, NULL, 0); - GRD_DelDoc(g_datatest, COLLECT_NAME, "", 0); - GRD_DelDoc(g_datatest, "notExisted", filt2.c_str(), 0); - - std::vector filtVec = { R"({"id" : 1})", R"({"id":[1, 2]})", R"({"id" : {"t1" : 1}})", - R"({"id":null})", R"({"id":true})", R"({"id" : 1.333})", R"({"id" : -2.0})" }; - for (const auto &item : filtVec) { - GRD_DelDoc(g_datatest, COLLECT_NAME, item.c_str(), 0); - } - GRD_DelDoc(g_datatest, COLLECT_NAME, filt2.c_str(), 0); - - std::string filt5 = "{\"subject.info\" : \"" + input + "\"}"; - reSet = nullptr; - query = { filt2.c_str(), "{}" }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_DelDoc(g_datatest, COLLECT_NAME, filt5.c_str(), 0); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - GRD_FreeRe(reSet); -} - -void DelDocFuzzTest(const uint8_t *data, size_t size) -{ - GRD_CreateCollect(g_datatest, COLLECT_NAME, OPTION_STRING, 0); - std::string input(reinterpret_cast(data), size); - std::string inputJson11 = "{\"field\":" + input + "}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - GRD_DelDoc(g_datatest, input.c_str(), "{}", 0); - GRD_DelDoc(g_datatest, nullptr, "{}", 0); - std::string longName = ""; - for (int i = 0; i < MORE_HALF_BYTES; i++) { - longName += 'a'; - } - GRD_DelDoc(g_datatest, "grd_name", "{}", 0); - GRD_DelDoc(g_datatest, longName.c_str(), "{}", 0); - GRD_DelDoc(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - inputJson11 = "{\"field1\":" + input + "}"; - GRD_DelDoc(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - inputJson11 = "{\"field\":\"" + input + "\"}"; - GRD_DelDoc(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - inputJson11 = "{\"field1\":\"" + input + "\"}"; - GRD_DelDoc(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - - const char *documentVirtual1 = "{ \ - \"id\" : \"1\", \ - \"name\": \"xiaoming\", \ - \"address\": \"beijing\", \ - \"age\" : 15, \ - \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ - \"subject\": [\"math\", \"English\", \"music\", {\"info\" : \"exam\"}] \ - }"; - const char *documentVirtual2 = "{ \ - \"id\" : \"2\", \ - \"name\": \"ori\", \ - \"address\": \"beijing\", \ - \"age\" : 15, \ - \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ - \"subject\": [\"math\", \"English\", \"music\"] \ - }"; - const char *documentVirtual3 = "{ \ - \"id\" : \"3\", \ - \"name\": \"David\", \ - \"address\": \"beijing\", \ - \"age\" : 15, \ - \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ - \"subject\": [\"Sing\", \"Jump\", \"Rap\", \"BasketBall\"] \ - }"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual1, 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual2, 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual3, 0); - GRD_DelDoc(g_datatest, COLLECT_NAME, "{}", 0); - - DelDocResultFuzzTest(input); -} - -namespace { -void FindAndRelease(Query query) -{ - GRD_ResultSet *reSet = nullptr; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_Next(reSet); - char *value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); - reSet = nullptr; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_Next(reSet); - value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); - - const char *newCollName = "./student"; - reSet = nullptr; - GRD_FindDocument(g_datatest, newCollName, query, 1, &reSet); - GRD_Next(reSet); - value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); - reSet = nullptr; - GRD_FindDocument(g_datatest, newCollName, query, 0, &reSet); - GRD_Next(reSet); - value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); -} -} // namespace - -void FindAndReleaseFuzzTest(std::string documentVirtual, std::string filt, Query query, const std::string &input) -{ - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual.c_str(), 0); - query.filt = filt.c_str(); - query.project = "{\"field\": 0}"; - FindAndRelease(query); - documentVirtual = "{\"field1.field2\" [false], \"field1.field2.field3\": [3], " - "\"field1.field4\": [null]}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual.c_str(), 0); - query.filt = documentVirtual.c_str(); - query.project = "{\"field\": 0}"; - FindAndRelease(query); - query.project = "{\"field\": 1}"; - FindAndRelease(query); - query.project = "{\"field.field2\": 1}"; - FindAndRelease(query); - documentVirtual = "{\"field1\": {\"field2\": [{\"field3\":\"" + input + "\"}]}}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual.c_str(), 0); - filt = "{\"field1.field2.field3\":\"" + input + "\"}"; - query.filt = filt.c_str(); - query.project = "{\"field1.field2\": 1}"; - FindAndRelease(query); - query.project = "{\"field1.field2\": 0}"; - FindAndRelease(query); - query.project = "{\"field1.field3\": 1}"; - FindAndRelease(query); - query.project = "{\"field1.field3\": 0}"; - FindAndRelease(query); - query.project = "{\"field1.field2.field3\": 0, \"field1.field2.field3\": 0}"; - FindAndRelease(query); - std::string project = "{\"field1\": \"" + input + "\"}"; - query.project = project.c_str(); - FindAndRelease(query); - project = "{\"" + input + "\": true, \"" + input + "\": false}"; - query.project = project.c_str(); - FindAndRelease(query); -} - -void NextFuzzTest(const uint8_t *data, size_t size) -{ - GRD_CreateCollect(g_datatest, COLLECT_NAME, OPTION_STRING, 0); - std::string input(reinterpret_cast(data), size); - std::string inputJson11 = "{" + input + "}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - Query query = { inputJson11.c_str(), "{}" }; - FindAndRelease(query); - std::string stringJson2 = "{ \"id\":\"1\", \"field\":\"" + input + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, stringJson2.c_str(), 0); - query.filt = "{\"id\": \"1\"}"; - FindAndRelease(query); - std::string filt2 = "{ \"id\":\"1\", \"field\":\"" + input + " invalid\"}"; - query.filt = filt2.c_str(); - FindAndRelease(query); - query.filt = "{\"id\": \"3\"}"; - FindAndRelease(query); - std::string stringJson3 = "{ \"id\":\"2\", \"field\": [\"field2\", null, \"abc\", 123]}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, stringJson3.c_str(), 0); - query.filt = "{\"field\": [\"field2\", null, \"abc\", 123]}"; - FindAndRelease(query); - std::string documentVirtual = "{\"field\": [\"" + input + "\",\"" + input + "\",\"" + input + "\"]}"; - std::string filt = "{\"field." + std::to_string(size) + "\":\"" + input + "\"}"; - FindAndReleaseFuzzTest(documentVirtual, filt, query, input); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); -} - -void GetValueFuzzTest(const uint8_t *data, size_t size) -{ - GRD_CreateCollect(g_datatest, COLLECT_NAME, OPTION_STRING, 0); - std::string input(reinterpret_cast(data), size); - std::string inputJson11 = "{" + input + "}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - char *value = nullptr; - Query query = { inputJson11.c_str(), "{}" }; - GRD_ResultSet *reSet = nullptr; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_GetVal(reSet, &value); - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); -} - -void FreeReFuzzTest() -{ - GRD_ResultSet *reSet = nullptr; - GRD_FreeRe(reSet); - reSet = new GRD_ResultSet; - reSet->reSet_ = DocumentDB::ResultSet(); - GRD_FreeRe(reSet); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); -} - -void DbOpenCloseFuzzTest(const char *dbFileVal, const char *configStr, GRD_DB *dbVal) -{ - int ret = GRD_DBOpen(dbFileVal, configStr, GRD_OPEN_CREATE, &dbVal); - if (ret == GRD_OK) { - GRD_DBClose(dbVal, GRD_CLOSE); - } -} - -void DbOpenOneFuzzTest(GRD_DB *dbVal) -{ - std::string path = "./documentVirtualFuzzTest.db"; - int ret = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_ONLY, &dbVal); - if (ret == GRD_OK) { - GRD_DBClose(dbVal, GRD_CLOSE); - } - (void)remove(path.c_str()); - - path = "./documentVirtual.db"; - DbOpenCloseFuzzTest(path.c_str(), R""({"pageSize":64, "redopubbufsize":4033})"", dbVal); - DbOpenCloseFuzzTest(path.c_str(), R""({"pageSize":64, "redopubbufsize":4032})"", dbVal); - DbOpenCloseFuzzTest(path.c_str(), R""({"redopubbufsize":255})"", dbVal); - DbOpenCloseFuzzTest(path.c_str(), R""({"redopubbufsize":16385})"", dbVal); -} - -void DbOpenFuzzTestTest(const uint8_t *data, size_t size) -{ - std::string dbFileData(reinterpret_cast(data), size); - std::string realDbFileData = DB_DIR_PATH + dbFileData; - const char *dbFileVal = realDbFileData.data(); - std::string configStrData(reinterpret_cast(data), size); - const char *configStrVal = configStrData.data(); - GRD_DB *dbVal = nullptr; - - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - std::string stringMax = getMaxString(); - const char *configStrMaxLen = stringMax.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrMaxLen, dbVal); - - std::string fieldStringValue = "{\"bufferPoolSize\": \"1024.5\"}"; - const char *configStrStringValue = fieldStringValue.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrStringValue, dbVal); - - std::string fieldBoolValue = "{\"bufferPoolSize\":}"; - const char *configStrBool = fieldBoolValue.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrBool, dbVal); - - std::string fieldStringValueAppend = "{\"bufferPoolSize\":\"8192\"}"; - const char *configStrStr = fieldStringValueAppend.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrStr, dbVal); - - std::string fieldStringValueFlush = "{\"bufferPoolSize\":\"8192\",\"redoFlushBtTrx\":\"1\"}"; - const char *configStrFlush = fieldStringValueFlush.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrFlush, dbVal); - - std::string fieldStringValueRedoBufsize = "{\"bufferPoolSize\":\"8192\",\"redoBufSize\":\"16384\"}"; - const char *configStrBs = fieldStringValueRedoBufsize.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrBs, dbVal); - - std::string fieldStringValueMaxConnNum = "{\"bufferPoolSize\":\"8192\",\"maxConnNum\":\"1024\"}"; - const char *configStrMcn = fieldStringValueMaxConnNum.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrMcn, dbVal); - - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - std::string fieldStringValueAll = "{\"bufferPoolSize\":\"8192\",\"redoFlushBtTrx\":\"1\",\"redoBufSize\":" - "\"16384\",\"maxConnNum\":\"1024\"}"; - const char *configStrAll = fieldStringValueAll.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrAll, dbVal); - - std::string fieldLowNumber = "{\"bufferPoolSize\": 102}"; - const char *configStrLowNumber = fieldLowNumber.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrLowNumber, dbVal); - - int ret = GRD_DBOpen(nullptr, configStrVal, GRD_OPEN_CREATE, &dbVal); - if (ret == GRD_OK) { - GRD_DBClose(nullptr, GRD_CLOSE); - } - DbOpenCloseFuzzTest(dbFileVal, configStrVal, dbVal); - - DbOpenOneFuzzTest(dbVal); -} - -void DbCloseFuzzTest(const uint8_t *data, size_t size) -{ - std::string dbFileData(reinterpret_cast(data), size); - std::string realDbFileData = DB_DIR_PATH + dbFileData; - const char *dbFileVal = realDbFileData.data(); - std::string configStrData(reinterpret_cast(data), size); - const char *configStrVal = configStrData.data(); - GRD_DB *dbVal = nullptr; - DbOpenCloseFuzzTest(dbFileVal, configStrVal, dbVal); -} - -void DbCloseResultSetFuzzTest() -{ - GRD_DB *db = nullptr; - GRD_DB *db2 = nullptr; - int ret = GRD_DBOpen(TEST_FILE, CONFIG_STRING, GRD_OPEN_CREATE, &db); - int errCode = GRD_DBOpen(TEST_FILE, CONFIG_STRING, GRD_OPEN_CREATE, &db2); - if (ret == GRD_OK) { - GRD_CreateCollect(db, "collection1", "{\"maxdoc\" : 5}", 0); - - GRD_ResultSet *reSet = nullptr; - Query query = { "{}", "{}" }; - GRD_FindDocument(db, "collection1", query, 0, &reSet); - - GRD_FreeRe(reSet); - - GRD_DBClose(db, GRD_CLOSE); - } - - if (errCode == GRD_OK) { - GRD_DBClose(db2, GRD_CLOSE); - } -} - -void CreateCollectionFuzzTest(const uint8_t *data, size_t size) -{ - std::string collectNameData(reinterpret_cast(data), size); - const char *collectNameVal = collectNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); - const char *optionStrVal = optionStrData.data(); - GRD_CreateCollect(nullptr, collectNameVal, optionStrVal, 0); - GRD_CreateCollect(g_datatest, collectNameVal, optionStrVal, 0); - const char *optionStr = nullptr; - GRD_CreateCollect(g_datatest, COLLECT_NAME, optionStr, 0); - GRD_CreateCollect(g_datatest, COLLECT_NAME, "{\"maxdoc\":5, \"unexpected_max_doc\":32}", 0); - GRD_CreateCollect(g_datatest, COLLECT_NAME, "{}", 0); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - std::string optStr = "{\"maxdoc\":" + optionStrData + "}"; - GRD_CreateCollect(g_datatest, COLLECT_NAME, optStr.c_str(), 0); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - GRD_CreateCollect(g_datatest, COLLECT_NAME, optStr.c_str(), MAX_SIZE_NUM_TEST); - optStr = "{\"maxdoc\": 5}"; - GRD_CreateCollect(g_datatest, COLLECT_NAME, optStr.c_str(), 0); - GRD_CreateCollect(g_datatest, COLLECT_NAME, optStr.c_str(), 1); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - GRD_DropCollect(g_datatest, COLLECT_NAME, MAX_SIZE_NUM_TEST); - GRD_DropCollect(g_datatest, collectNameVal, 0); -} - -void DropCollectFuzzTest(const uint8_t *data, size_t size) -{ - std::string collectNameData(reinterpret_cast(data), size); - const char *collectNameVal = collectNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); - const char *optionStrVal = optionStrData.data(); - GRD_CreateCollect(g_datatest, collectNameVal, optionStrVal, 0); - GRD_DropCollect(nullptr, collectNameVal, 0); - GRD_DropCollect(g_datatest, collectNameVal, 0); -} - -void DbFlushFuzzTest(const uint8_t *data, size_t size) -{ - if (data == nullptr) { - return; - } - GRD_DB *db = nullptr; - GRD_DB *db2 = nullptr; - const uint32_t flags = *data; - int ret = GRD_DBOpen(TEST_FILE, CONFIG_STRING, GRD_OPEN_CREATE, &db); - if (ret == GRD_OK) { - GRD_Flush(db, flags); - GRD_DBClose(db, GRD_CLOSE); - } - GRD_Flush(db2, flags); -} - -void TestGrdDbApGrdGetItem002FuzzTest() -{ - const char *config = CONFIG_STRING; - GRD_DB *db = nullptr; - DbOpenCloseFuzzTest(TEST_FILE, config, db); - GRD_Preload(nullptr, COLLECT_NAME); - GRD_Preload(nullptr, "invalid_name"); - GRD_Preload(g_datatest, COLLECT_NAME); - std::string smallPrefix = std::string(SMALL_PREFIX_LENGTH, 'a'); - for (uint32_t i = 0; i < NUM_NINETY_EIGHT; ++i) { - std::string v = smallPrefix + std::to_string(i); - GRD_KVItem key = { &i, sizeof(uint32_t) }; - GRD_KVItem value = { reinterpret_cast(v.data()), static_cast(v.size()) + 1 }; - GRD_KVPut(g_datatest, COLLECT_NAME, &key, &value); - - GRD_KVItem getValue = { nullptr, 0 }; - GRD_KVGet(g_datatest, COLLECT_NAME, &key, &getValue); - GRD_KVFreeItem(&getValue); - - GRD_KVDel(g_datatest, COLLECT_NAME, &key); - } - GRD_Flush(g_datatest, 1); - - uint32_t begin = 0, end = MAX_SIZE_NUM_TEST; - GRD_FilterOptionT option = {}; - option.mode = KV_SCAN_RANGE; - option.begin = { &begin, sizeof(uint32_t) }; - option.end = { &end, sizeof(uint32_t) }; - GRD_ResultSet *reSet = nullptr; - GRD_KVFilter(g_datatest, COLLECT_NAME, &option, &reSet); - - uint32_t keySize, valueSize; - GRD_KVGetSize(reSet, &keySize, &valueSize); - - reSet = nullptr; - uint32_t i = 32; - GRD_KVItem key = { &i, sizeof(uint32_t) }; - GRD_KVScan(g_datatest, COLLECT_NAME, &key, KV_SCAN_EQUAL_OR_LESS_KEY, &reSet); - - GRD_Prev(reSet); - GRD_Next(reSet); - - GRD_FreeRe(reSet); -} - -void TestGrdKvBatchCoupling003FuzzTest() -{ - const char *config = CONFIG_STRING; - GRD_DB *db = nullptr; - DbOpenCloseFuzzTest(TEST_FILE, config, db); - - GRD_ResultSet *reSet = nullptr; - GRD_KVScan(g_datatest, COLLECT_NAME, nullptr, KV_SCAN_PREFIX, &reSet); - - for (uint32_t i = 0; i < CURSOR_COUNT_TEST; i++) { - GRD_Next(reSet); - } - - GRD_KVBatchT *batchDel = nullptr; - std::vector keySet; - std::vector valueSet; - for (uint32_t i = 0; i < VECTOR_SIZE; i++) { - std::string key(MAX_SIZE_NUM_TEST, 'a'); - key += std::to_string(i); - keySet.emplace_back(key); - std::string value = std::to_string(i); - valueSet.emplace_back(value); - } - - for (int j = 0; j < BATCH_COUNT; j++) { - GRD_KVBatchPrepare(BATCH_COUNT, &batchDel); - GRD_KVBatchPut(g_datatest, COLLECT_NAME, batchDel); - for (uint16_t i = 0; i < BATCH_COUNT; i++) { - char *batchKey = const_cast(keySet[CURSOR_COUNT_TEST + j * BATCH_COUNT + i].c_str()); - char *batchValue = const_cast(valueSet[CURSOR_COUNT_TEST + j * BATCH_COUNT + i].c_str()); - GRD_KVBatchPushback(static_cast(batchKey), - static_cast(keySet[CURSOR_COUNT_TEST + j * BATCH_COUNT + i].length()) + 1, - static_cast(batchValue), - static_cast(valueSet[CURSOR_COUNT_TEST + j * BATCH_COUNT + i].length()) + 1, - batchDel); - } - - GRD_KVBatchDel(g_datatest, COLLECT_NAME, batchDel); - - GRD_KVBatchDestroy(batchDel); - } - - GRD_Next(reSet); - GRD_KVItem keyItem = { nullptr, 0 }; - GRD_KVItem valueItem = { nullptr, 0 }; - GRD_Fetch(reSet, &keyItem, &valueItem); - GRD_KVFreeItem(&keyItem); - GRD_KVFreeItem(&valueItem); - GRD_FreeRe(reSet); -} -} // namespace OHOS - -/* FuzzTester entry point */ -extern "C" { -int LLVMFuzzTesterTestOneInput(const uint8_t *data, size_t size) -{ - /* Run your code on data */ - OHOS::SetUpTestCase(); - - OHOS::DbOpenFuzzTestTest(data, size); - OHOS::CreateCollectionFuzzTest(data, size); - OHOS::DropCollectFuzzTest(data, size); - OHOS::InsertDocFuzzTest(data, size); - OHOS::FindDocumentFuzzTest(data, size); - OHOS::UpdateDocFuzzTest(data, size); - OHOS::UpsertFuzzTest(data, size); - OHOS::DelDocFuzzTest(data, size); - OHOS::NextFuzzTest(data, size); - OHOS::GetValueFuzzTest(data, size); - OHOS::FreeReFuzzTest(); - OHOS::TestGrdDbApGrdGetItem002FuzzTest(); - OHOS::TestGrdKvBatchCoupling003FuzzTest(); - OHOS::DbCloseFuzzTest(data, size); - OHOS::DbCloseResultSetFuzzTest(); - OHOS::DbFlushFuzzTest(data, size); - - OHOS::TearDownTestCase(); - return 0; -} -} diff --git a/kv_store/test/fuzztest/kvsync_fuzzer/BUILD.gn b/kv_store/test/fuzztest/kvsync_fuzzer/BUILD.gn deleted file mode 100644 index 7e65b4a2b28c6dd42c1b22824edfe990edb87068..0000000000000000000000000000000000000000 --- a/kv_store/test/fuzztest/kvsync_fuzzer/BUILD.gn +++ /dev/null @@ -1,130 +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. - -#####################hydra-fuzz################### -import("//build/config/features.gni") -import("//build/test.gni") -import("../../../distributeddb.gni") - -##############################fuzztest########################################## -ohos_fuzztest("KvsyncFuzzTest") { - module_out_path = "kv_store/kv_store" - - include_dirs = [ - "../../../test/fuzztest/common", - "../../../test/unittest/common/common", - "../../../test/unittest/common/syncer", - "../../../test/unittest/common/syncer/kv", - "../../../test/unittest/common/storage", - "../../../include", - "../../../interfaces/include", - "../../../interfaces/include/kv", - "../../../interfaces/include/relational", - "../../../interfaces/src", - "../../../interfaces/src/relational", - "../../../storage/include", - "../../../storage/src", - "../../../storage/src/kv", - "../../../storage/src/kv", - "../../../storage/src/gaussdb_rd", - "../../../storage/src/multiver", - "../../../storage/src/operation", - "../../../storage/src/relational", - "../../../storage/src/sqlite", - "../../../storage/src/sqlite/kv", - "../../../storage/src/sqlite/relational", - "../../../storage/src/upgrader", - "../../../common/include", - "../../../common/include/kv", - "../../../common/include/relational", - "../../../common/src", - "../../../common/src/kv", - "../../../communicator/include", - "../../../communicator/src", - "../../../syncer/include", - "../../../syncer/src", - "../../../syncer/src/kv", - "../../../syncer/src/device", - "../../../syncer/src/device/multiver", - "../../../syncer/src/device/singlever", - ] - - cflags = [ - "-g", - "-O0", - "-Wno-unused-variable", - "-fno-omit-frame-pointer", - "--coverage", - ] - - ldflags = [ "--coverage" ] - - cflags_cc = [ "--coverage" ] - - fuzz_config_file = "../kvsync_fuzzer" - - sources = distributeddb_src - sources += [ - "../../../test/fuzztest/common/distributeddb_tools_test.cpp", - "../../../test/fuzztest/common/fuzzer_data.cpp", - "../../../test/fuzztest/kvsync_fuzzer/kvsync_fuzzer.cpp", - "../../../test/unittest/common/common/distributeddb_data_generate_unit_test.cpp", - "../../../test/unittest/common/syncer/kv/virtual_asset_loader.cpp", - "../../../test/unittest/common/syncer/kv/virtual_kv_data_translate.cpp", - "../../../test/unittest/common/syncer/kv/virtual_kv_db.cpp", - ] - - defines = [ - "SQLITE_ENABLE_SNAPSHOT", - "_LARGEFILE64_SOURCE", - "_FILE_OFFSET_BITS=64", - "SQLITE_HAS_CODEC", - "SQLITE_ENABLE_JSON1", - "USING_HILOG_LOGGER", - "USE_SQLITE_SYMBOLS", - "USING_DB_JSON_EXTRACT_AUTOMATICALLY", - "LOW_LEVEL_MEM_DEV", - "JSONCPP_USE_BUILDER", - "OMIT_FLATBUFFER", - "OMIT_MULTI_VER", - "RELATIONAL_STORE", - "SQLITE_DISTRIBUTE_RELATIONAL", - "SQLITE_EXPORT_SYMBOLS", - "SQLITE_ENABLE_DROPTABLE_CALLBACK", - "OPENSSL_SUPPRESS_DEPRECATED", - ] - - deps = [ - "../../../../distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] - - external_deps = [ - "c_utils:utils", - "hilog:libhilog", - "zlib:shared_libz", - ] -} - -############################################################################### - -group("fuzztest") { - testonly = true - deps = [] - deps += [ - # deps file - ":KvsyncFuzzTest", - ] -} diff --git a/kv_store/test/fuzztest/kvsync_fuzzer/kvsync_fuzzer.cpp b/kv_store/test/fuzztest/kvsync_fuzzer/kvsync_fuzzer.cpp deleted file mode 100644 index 239478304543430b8acd92552922ffd4e7533d9b..0000000000000000000000000000000000000000 --- a/kv_store/test/fuzztest/kvsync_fuzzer/kvsync_fuzzer.cpp +++ /dev/null @@ -1,561 +0,0 @@ -/* - * Copyright (c) 2023 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 "kvsync_fuzzer.h" -#include "kv/kv_dbtypes.h" -#include "kv/kv_dbconstant.h" -#include "distributeddbvData_generate_unit_test.h" -#include "distributeddbtools_test.h" -#include "fuzzer_vData.h" -#include "kv_store_nb_kvDelegate.h" -#include "logprint.h" -#include "relational_store_kvDelegate.h" -#include "relational_store_manager.h" -#include "runtime_kvConfig.h" -#include "time_helper.h" -#include "virtual_assetTest_loader.h" -#include "virtual_kv_vData_translate.h" -#include "virtual_kv_db.h" - -namespace OHOS { -using namespace DistributedDB; -using namespace DistributedDBTest; - -static constexpr const int MOD = 1000; // 1000 is mod -class KvSyncContext { -public: - void WaitForFinishTest() - { - std::unique_lock unique(mutex); - LOGI("begin wait"); - cv.wait_for(unique, std::chrono::milliseconds(DBConstant::MAX_TIMEOUT), [this]() { - return finished; - }); - LOGI("end wait"); - } - - void FinishAndNotifyTest() - { - { - std::lock_guard autoLock(mutex); - finished = true; - } - cv.notify_one(); - } - -private: - std::condition_variable cv; - std::mutex mutex; - bool finished = false; -}; -class KvSyncTest { -public: - static void ExecSqlFuzz(sqlite3 *db, const std::string &sql) - { - if (db == nullptr || sql.empty()) { - return; - } - int errCodeTest = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); - if (errCodeTest != SQLITE_OK) { - LOGE("Execute sql failed. err: %d", errCodeTest); - } - } - - static void CreateTableFuzz(sqlite3 *&db) - { - ExecSqlFuzz(db, "PRAGMA journal_modeTest=WAL;"); - ExecSqlFuzz(db, gcreateLocalTableSql); - } - - static void SetKvDbSchemaFuzz(RelationalStoreDelegate *kvDelegate) - { - DataBaseSchema vDataSchema; - const std::vector kvFiled = { - {"name", TYPE_INDEX, true}, {"height", TYPE_INDEX}, - {"married", TYPE_INDEX}, {"photoTest", TYPE_INDEX, false, false}, - {"assert", TYPE_INDEX}, {"asserts", TYPE_INDEX}, {"age", TYPE_INDEX} - }; - TableSchema tableSchemaTest = { - .name = gtable, - .fieldTests = kvFiled - }; - vDataSchema.tables.push_back(tableSchemaTest); - kvDelegate->SetKvDbSchemaFuzz(vDataSchema); - kvDelegate->CreateDistributedTable(gtable, CLOUD_COOPERATION); - } - - static void InitDbData(sqlite3 *&db, const uint8_t *vData, size_t size) - { - sqlite3_stmt *stmt = nullptr; - int errCodeTest = SQLiteUtils::GetStatement(db, ginsertLocalDataSql, stmt); - if (errCodeTest != E_OK) { - return; - } - FuzzerData fuzzerDataTest(vData, size); - uint32_t len = fuzzerDataTest.GetUInt32() % MOD; - for (size_t i = 0; i <= size; ++i) { - std::string idStr = fuzzerDataTest.GetString(len); - errCodeTest = SQLiteUtils::BindTextToStatement(stmt, 1, idStr); - if (errCodeTest != E_OK) { - break; - } - std::vector photoTest = fuzzerDataTest.GetSequence(fuzzerDataTest.GetInt()); - errCodeTest = SQLiteUtils::BindBlobToStatement(stmt, 2, photoTest); // 2 is index of photoTest - if (errCodeTest != E_OK) { - break; - } - errCodeTest = SQLiteUtils::StepWithRetry(stmt); - if (errCodeTest != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - break; - } - SQLiteUtils::ResetStatement(stmt, false, errCodeTest); - } - SQLiteUtils::ResetStatement(stmt, true, errCodeTest); - } - - static Asset GenAsset(const std::string &name, const std::string &hash) - { - Asset assetTest; - assetTest.name = name; - assetTest.hash = hash; - return assetTest; - } - - void InitDbAssetFuzz(const uint8_t *vData, size_t size) - { - if (vData == nullptr || size == 0) { - return; - } - sqlite3_stmt *stmt = nullptr; - int errCodeTest = SQLiteUtils::GetStatement(db, ginsertLocalAssetSql, stmt); - if (errCodeTest != E_OK) { - return; - } - FuzzerData fuzzerDataTest(vData, size); - uint32_t len = fuzzerDataTest.GetUInt32() % MOD; - for (size_t i = 0; i <= size; ++i) { - std::string idStr = fuzzerDataTest.GetString(len); - errCodeTest = SQLiteUtils::BindTextToStatement(stmt, 1, idStr); - if (errCodeTest != E_OK) { - break; - } - std::vector photoTest = fuzzerDataTest.GetSequence(fuzzerDataTest.GetInt()); - errCodeTest = SQLiteUtils::BindBlobToStatement(stmt, 2, photoTest); // 2 is index of photoTest - if (errCodeTest != E_OK) { - break; - } - std::vector assetTest; - RuntimeContext::GetInstance()->AssetToBlob(localAssets[i % size], assetTest); - errCodeTest = SQLiteUtils::BindBlobToStatement(stmt, 3, assetTest); // 3 is index of assert - if (errCodeTest != E_OK) { - break; - } - - std::vector assetTestVec(localAssets.begin() + (i % size), localAssets.end()); - RuntimeContext::GetInstance()->AssetsToBlob(assetTestVec, assetTest); - errCodeTest = SQLiteUtils::BindBlobToStatement(stmt, 4, assetTest); // 4 is index of asserts - if (errCodeTest != E_OK) { - break; - } - errCodeTest = SQLiteUtils::StepWithRetry(stmt); - if (errCodeTest != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - break; - } - SQLiteUtils::ResetStatement(stmt, false, errCodeTest); - } - SQLiteUtils::ResetStatement(stmt, true, errCodeTest); - } - - void InsertKvTableRecordFuzz(int64_t begin, int64_t count, int64_t photoTestSize, bool assetTestIsNull) - { - std::vector photoTest(photoTestSize, 'v'); - std::vector record1; - std::vector extend1; - double randomHeight = 166.0; // 166.0 is random double value - int64_t randomAge = 13L; // 13 is random int64_t value - Timestamp now = TimeHelper::GetSysCurrentTime(); - for (int64_t i = begin; i < begin + count; ++i) { - VBucket vData; - vData.insert_or_assign("name", "Kv" + std::to_string(i)); - vData.insert_or_assign("height", randomHeight); - vData.insert_or_assign("married", false); - vData.insert_or_assign("photoTest", photoTest); - vData.insert_or_assign("age", randomAge); - Asset assetTest = gkvAsset; - assetTest.name = assetTest.name + std::to_string(i); - assetTestIsNull ? vData.insert_or_assign("assert", Nil()) : vData.insert_or_assign("assert", assetTest); - record1.push_back(vData); - VBucket log; - log.insert_or_assign(KvDbConstant::CREATE_FIELD, - static_cast(now / KvDbConstant::TEN_THOUSAND + i)); - log.insert_or_assign(KvDbConstant::MODIFY_FIELD, - static_cast(now / KvDbConstant::TEN_THOUSAND + i)); - log.insert_or_assign(KvDbConstant::DELETE_FIELD, false); - extend1.push_back(log); - } - examKvDb->BatchInsert(gtable, std::move(record1), extend1); - LOGD("insert kv record worker1[primary key]:[kv%" PRId64 " - kv%" PRId64 ")", begin, count); - std::this_thread::sleep_for(std::chrono::milliseconds(count)); - } - - void SetUp() - { - DistributedDBToolsTest::TestDirInit(testDir); - storePathTest = testDir + "/" + gstoreId + gdbSuffix; - LOGI("The test db is:%s", testDir.c_str()); - RuntimeConfig::SetKvTranslate(std::make_shared()); - LOGD("Test dir is %s", testDir.c_str()); - db = RdbTestUtils::CreateDataBase(storePathTest); - if (db == nullptr) { - return; - } - CreateTableFuzz(db); - mgr = std::make_shared("APP_ID", "USER_ID"); - RelationalStoreDelegate::Option optionTest; - mgr->OpenStore(storePathTest, "STORE_ID", optionTest, kvDelegate); - gKvSyncOption.modeTest = SyncMode::SYNC_MODE_CLOUD_MERGE; - gKvSyncOption.users.push_back(DistributedDBUnitTest::USER_ID); - gKvSyncOption.devices.push_back("kv"); - kvConfig.vDataDir = testDir; - gmgr.SetKvStoreConfig(kvConfig); - KvStoreNbDelegate::Option optionTest1; - GetKvStoreFuzz(kvDelegatePtrS1, DistributedDBUnitTest::STORE_ID_1, optionTest1); - KvStoreNbDelegate::Option optionTest2; - GetKvStoreFuzz(kvDelegatePtrS2, DistributedDBUnitTest::STORE_ID_2, optionTest2); - examKvDb = std::make_shared(); - examKvDb1 = std::make_shared(); - examKvDb2 = std::make_shared(); - virtualAssetLoader = std::make_shared(); - kvDelegate->SetKvDB(examKvDb); - kvDelegate->SetIAssetLoader(virtualAssetLoader); - } - - void TearDown() - { - if (kvDelegate != nullptr) { - DBStatus errCodeTest = mgr->CloseStore(kvDelegate); - LOGI("kvDelegate close with errCodeTest %d", static_cast(errCodeTest)); - kvDelegate = nullptr; - } - if (db != nullptr) { - int errCodeTest = sqlite3_close_v2(db); - LOGI("sqlite close with errCodeTest %d", errCodeTest); - } - examKvDb = nullptr; - CloseKvStoreFuzz(kvDelegatePtrS1, DistributedDBUnitTest::STORE_ID_1); - CloseKvStoreFuzz(kvDelegatePtrS2, DistributedDBUnitTest::STORE_ID_2); - examKvDb1 = nullptr; - examKvDb2 = nullptr; - virtualAssetLoader = nullptr; - if (DistributedDBToolsTest::RemoveTestDbFiles(testDir) != 0) { - LOGE("rm test db files error."); - } - } - - void KvBlockSyncFuzz(KvStoreNbDelegate *kvDelegate, DBStatus expectDBStatus, KvSyncOption optionTest, - int expectSyncResult = OK) - { - if (kvDelegate == nullptr) { - return; - } - std::mutex virDataMutex; - std::condition_variable cv; - bool finish = false; - SyncProcess last; - auto callback = [expectDBStatus, &last, &cv, &virDataMutex, &finish, &optionTest]( - const std::map &process) { - size_t notifyCnt = 0; - for (const auto &item : process) { - LOGD("user = %s, dbStatus = %d", item.first.c_str(), item.second.process); - if (item.second.process != DistributedDB::FINISHED) { - continue; - } - { - std::lock_guard autoLock(virDataMutex); - notifyCnt++; - std::set userSet(optionTest.users.begin(), optionTest.users.end()); - if (notifyCnt == userSet.size()) { - finish = true; - last = item.second; - cv.notify_one(); - } - } - } - }; - auto result = kvDelegate->Sync(optionTest, callback); - if (result == OK) { - std::unique_lock unique(virDataMutex); - cv.wait(unique, [&finish]() { - return finish; - }); - } - lastProcess = last; - } - - static DataBaseSchema GetDataBaseSchema(bool invalidSchema) - { - DataBaseSchema schemaTest; - TableSchema tableSchemaTest; - tableSchemaTest.name = invalidSchema ? "invalid_schemaTest_name" : KvDbConstant::CLOUD_KV_TABLE_NAME; - Field fieldTest; - fieldTest.colName = KvDbConstant::CLOUD_KV_FIELD_KEY; - fieldTest.type = TYPE_INDEX; - fieldTest.primary = true; - fieldTest.colName = KvDbConstant::CLOUD_KV_FIELD_DEVICE; - fieldTest.primary = false; - tableSchemaTest.fieldTests.push_back(fieldTest); - tableSchemaTest.fieldTests.push_back(fieldTest); - fieldTest.colName = KvDbConstant::CLOUD_KV_FIELD_ORI_DEVICE; - tableSchemaTest.fieldTests.push_back(fieldTest); - fieldTest.colName = KvDbConstant::CLOUD_KV_FIELD_VALUE; - tableSchemaTest.fieldTests.push_back(fieldTest); - fieldTest.colName = KvDbConstant::CLOUD_KV_FIELD_DEVICE_CREATE_TIME; - fieldTest.type = TYPE_INDEX; - tableSchemaTest.fieldTests.push_back(fieldTest); - schemaTest.tables.push_back(tableSchemaTest); - return schemaTest; - } - - void GetKvStoreFuzz(KvStoreNbDelegate *&kvDelegate, const std::string &storeId, KvDelegate::Option optionTest, - int securityLabel = NOT_SET, bool invalidSchema = false) - { - DBStatus openRet = OK; - optionTest.secOption.securityLabel = securityLabel; - gmgr.GetKvStoreFuzz(storeId, optionTest, [&openRet, &kvDelegate](KvStoreNbDelegate *openDelegate) { - openRet = dbStatus; - kvDelegate = openDelegate; - }); - if (kvDelegate == nullptr) { - return; - } - std::map schemaTests; - schemaTests[DistributedDBUnitTest::USER_ID] = GetDataBaseSchema(invalidSchema); - schemaTests[USER_ID] = GetDataBaseSchema(invalidSchema); - kvDelegate->SetKvDbSchemaFuzz(schemaTests); - std::map> kvDbs; - kvDbs[DistributedDBUnitTest::USER_ID] = examKvDb1; - kvDbs[USER_ID] = examKvDb2; - kvDelegate->SetKvDB(kvDbs); - } - - static void CloseKvStoreFuzz(KvStoreNbDelegate *&kvDelegate, const std::string &storeId) - { - if (kvDelegate != nullptr) { - gmgr.CloseKvStoreFuzz(kvDelegate); - kvDelegate = nullptr; - DBStatus dbStatus = gmgr.DeleteKvStore(storeId); - LOGD("delete kv store dbStatus %d store %s", dbStatus, storeId.c_str()); - } - } - - void BlockSyncFuzz(SyncMode modeTest = SYNC_MODE_CLOUD_MERGE) - { - Query dbQuery = Query::Select().FromTable({ gtable }); - auto kvContext = std::make_shared(); - auto callback = [kvContext](const std::map &onProcess) { - for (const auto &item : onProcess) { - if (item.second.process == ProcessStatus::FINISHED) { - kvContext->FinishAndNotifyTest(); - } - } - }; - DBStatus dbStatus = kvDelegate->Sync({gdeviceKv}, modeTest, dbQuery, callback, DBConstant::MAX_TIMEOUT); - if (dbStatus != OK) { - return; - } - kvContext->WaitForFinishTest(); - } - - void OptionBlockSyncFuzz(const std::vector &devices, SyncMode modeTest = SYNC_MODE_CLOUD_MERGE) - { - Query dbQuery = Query::Select().FromTable({ gtable }); - auto kvContext = std::make_shared(); - auto callback = [kvContext](const std::map &onProcess) { - for (const auto &item : onProcess) { - if (item.second.process == ProcessStatus::FINISHED) { - kvContext->FinishAndNotifyTest(); - } - } - }; - KvSyncOption optionTest; - optionTest.modeTest = modeTest; - optionTest.devices = devices; - optionTest.dbQuery = dbQuery; - optionTest.waitTime = DBConstant::MAX_TIMEOUT; - DBStatus dbStatus = kvDelegate->Sync(optionTest, callback); - if (dbStatus != OK) { - return; - } - kvContext->WaitForFinishTest(); - } - - void NormalSync() - { - BlockSyncFuzz(); - SetKvDbSchemaFuzz(kvDelegate); - BlockSyncFuzz(); - } - - void KvNormalSync() - { - Key key = {'k'}; - Value expectValue = {'v'}; - kvDelegatePtrS1->Put(key, expectValue); - KvBlockSyncFuzz(kvDelegatePtrS1, OK, gKvSyncOption); - KvBlockSyncFuzz(kvDelegatePtrS2, OK, gKvSyncOption); - Value actualValue; - kvDelegatePtrS2->Get(key, actualValue); - } - - void RandomModeSyncFuzz(const uint8_t *vData, size_t size) - { - if (size == 0) { - BlockSyncFuzz(); - return; - } - auto modeTest = static_cast(vData[0]); - LOGI("[RandomModeSyncFuzz] select modeTest %d", static_cast(modeTest)); - BlockSyncFuzz(modeTest); - } - - void DataChangeSyncFuzz(const uint8_t *vData, size_t size) - { - SetKvDbSchemaFuzz(kvDelegate); - if (size == 0) { - return; - } - InitDbData(db, vData, size); - BlockSyncFuzz(); - FuzzerData fuzzerDataTest(vData, size); - KvSyncConfig kvConfig; - int maxUploadSize11 = fuzzerDataTest.GetInt(); - int maxUploadCount = fuzzerDataTest.GetInt(); - kvConfig.maxUploadSize11 = maxUploadSize11; - kvConfig.maxUploadCount = maxUploadCount; - kvDelegate->SetKvSyncConfig(kvConfig); - kvDelegatePtrS1->SetKvSyncConfig(kvConfig); - uint32_t len = fuzzerDataTest.GetUInt32() % MOD; - std::string version = fuzzerDataTest.GetString(len); - kvDelegatePtrS1->SetGenKvVersionCallback([version](const std::string &origin) { - return origin + version; - }); - KvNormalSync(); - int count = fuzzerDataTest.GetInt(); - kvDelegatePtrS1->GetCount(Query::Select(), count); - std::string device = fuzzerDataTest.GetString(len); - kvDelegatePtrS1->GetKvVersion(device); - std::vector devices = fuzzerDataTest.GetStringVector(len); - OptionBlockSyncFuzz(devices); - } - - void InitAssetsFuzz(const uint8_t *vData, size_t size) - { - FuzzerData fuzzerDataTest(vData, size); - uint32_t len = fuzzerDataTest.GetUInt32() % MOD; - for (size_t i = 0; i <= size; ++i) { - std::string nameStr = fuzzerDataTest.GetString(len); - localAssets.push_back(GenAsset(nameStr, std::to_string(vData[0]))); - } - } - - void AssetChangeSyncFuzz(const uint8_t *vData, size_t size) - { - SetKvDbSchemaFuzz(kvDelegate); - if (size == 0) { - return; - } - InitAssetsFuzz(vData, size); - InitDbAssetFuzz(vData, size); - BlockSyncFuzz(); - } - - void RandomModeRemoveDeviceDataFuzz(const uint8_t *vData, size_t size) - { - if (size == 0) { - return; - } - SetKvDbSchemaFuzz(kvDelegate); - int64_t kvCount = 10; - int64_t paddingSize = 10; - InsertKvTableRecordFuzz(0, kvCount, paddingSize, false); - BlockSyncFuzz(); - auto modeTest = static_cast(vData[0]); - LOGI("[RandomModeRemoveDeviceDataFuzz] select modeTest %d", static_cast(modeTest)); - if (modeTest == DEFAULT) { - return; - } - std::string device = ""; - kvDelegate->RemoveDeviceData(device, modeTest); - } -private: - std::string testDir; - std::string storePathTest; - sqlite3 *db = nullptr; - RelationalStoreDelegate *kvDelegate = nullptr; - KvStoreNbDelegate* kvDelegatePtrS1 = nullptr; - KvStoreNbDelegate* kvDelegatePtrS2 = nullptr; - std::shared_ptr examKvDb; - std::shared_ptr examKvDb1 = nullptr; - std::shared_ptr examKvDb2 = nullptr; - std::shared_ptr virtualAssetLoader; - std::shared_ptr mgr; - KvStoreConfig kvConfig; - SyncProcess lastProcess; - Assets localAssets; -}; -KvSyncTest *g_kvSyncFuzzTest = nullptr; - -void Setup() -{ - LOGI("Set up"); - g_kvSyncFuzzTest = new(std::nothrow) KvSyncTest(); - if (g_kvSyncFuzzTest == nullptr) { - return; - } - g_kvSyncFuzzTest->SetUp(); -} - -void TearDown() -{ - LOGI("Tear down"); - g_kvSyncFuzzTest->TearDown(); - if (g_kvSyncFuzzTest != nullptr) { - delete g_kvSyncFuzzTest; - g_kvSyncFuzzTest = nullptr; - } -} - -void CombineFuzzTest(const uint8_t *vData, size_t size) -{ - if (g_kvSyncFuzzTest == nullptr) { - return; - } - g_kvSyncFuzzTest->NormalSync(); - g_kvSyncFuzzTest->KvNormalSync(); - g_kvSyncFuzzTest->RandomModeSyncFuzz(vData, size); - g_kvSyncFuzzTest->DataChangeSyncFuzz(vData, size); - g_kvSyncFuzzTest->AssetChangeSyncFuzz(vData, size); - g_kvSyncFuzzTest->RandomModeRemoveDeviceDataFuzz(vData, size); -} -} - -/* Fuzzer entry point */ -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *vData, size_t size) -{ - OHOS::Setup(); - OHOS::CombineFuzzTest(vData, size); - OHOS::TearDown(); - return 0; -} diff --git a/kv_store/test/fuzztest/kvsync_fuzzer/project.xml b/kv_store/test/fuzztest/kvsync_fuzzer/project.xml deleted file mode 100644 index 1bd6e94e384a119569cdd3efa9503d51f6612fe4..0000000000000000000000000000000000000000 --- a/kv_store/test/fuzztest/kvsync_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 600 - - 4096 - - diff --git a/kv_store/test/fuzztest/singlekvstorestub_fuzzer/BUILD.gn b/kv_store/test/fuzztest/kvutil_fuzzer/BUILD.gn similarity index 82% rename from kv_store/test/fuzztest/singlekvstorestub_fuzzer/BUILD.gn rename to kv_store/test/fuzztest/kvutil_fuzzer/BUILD.gn index d735c3c170323ef0c07260e247d023ee7dbb2980..7c09246a648c953b23301106d5d676475894e9de 100644 --- a/kv_store/test/fuzztest/singlekvstorestub_fuzzer/BUILD.gn +++ b/kv_store/test/fuzztest/kvutil_fuzzer/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2024 Huawei Device Co., Ltd. +# Copyright (c) 2025 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,7 +16,7 @@ import("//build/config/features.gni") import("//build/test.gni") ##############################fuzztest########################################## -ohos_fuzztest("SingleKvStoreStubFuzzTest") { +ohos_fuzztest("KvUtilFuzzTest") { module_out_path = "kv_store/kv_store" include_dirs = [ @@ -26,7 +26,7 @@ ohos_fuzztest("SingleKvStoreStubFuzzTest") { "../../../interfaces/innerkits/distributeddata/include", ] - fuzz_config_file = "../../../test/fuzztest/singlekvstorestub_fuzzer" + fuzz_config_file = "../../../test/fuzztest/kvutil_fuzzer" cflags = [ "-g", @@ -36,14 +36,18 @@ ohos_fuzztest("SingleKvStoreStubFuzzTest") { "-Wno-c99-designator", ] - sources = [ "singlekvstorestub_fuzzer.cpp" ] - - deps = [] + sources = [ + "kvutil_fuzzer.cpp", + ] external_deps = [ "c_utils:utils", + "data_share:datashare_common", + "data_share:datashare_provider", "hilog:libhilog", + "ipc:ipc_single", "kv_store:distributeddata_inner", + "kv_store:distributeddb", ] } @@ -53,7 +57,7 @@ group("fuzztest") { deps = [] deps += [ # deps file - ":SingleKvStoreStubFuzzTest", + ":KvUtilFuzzTest", ] } ############################################################################### diff --git a/kv_store/test/fuzztest/kvutil_fuzzer/corpus/init b/kv_store/test/fuzztest/kvutil_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..7ade8a0faafeaedba7241e7d4a97b8e1f9691932 --- /dev/null +++ b/kv_store/test/fuzztest/kvutil_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 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. + */ + +FUZZ \ No newline at end of file diff --git a/kv_store/test/fuzztest/kvutil_fuzzer/kvutil_fuzzer.cpp b/kv_store/test/fuzztest/kvutil_fuzzer/kvutil_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0dafc3dd6227090b1890aefb9b6947ca46c99996 --- /dev/null +++ b/kv_store/test/fuzztest/kvutil_fuzzer/kvutil_fuzzer.cpp @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2025 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 "kvutil_fuzzer.h" + +#include +#include +#include +#include "distributed_kv_data_manager.h" +#include "fuzzer/FuzzedDataProvider.h" +#include "datashare_predicates.h" +#include "datashare_values_bucket.h" +#include "store_errno.h" +#include "kv_utils.h" + +using namespace OHOS; +using namespace OHOS::DistributedKv; +using namespace OHOS::DataShare; +namespace OHOS { +using ValueType = std::variant>; +static std::shared_ptr singleKvStore_ = nullptr; +static constexpr const char *KEY = "key"; +static constexpr const char *VALUE = "value"; +static constexpr const char *PREFIX = "test_"; +enum DataType { + STRING = 1, + INT64, + BOOL, + DOUBLE, + VECTOR_INT64, +}; + +void SetUpTestCase(void) +{ + DistributedKvDataManager manager; + Options options = { + .createIfMissing = true, + .encrypt = false, + .autoSync = true, + .securityLevel = S1, + .kvStoreType = KvStoreType::SINGLE_VERSION + }; + options.area = EL1; + AppId appId = { "kvstorefuzzertest" }; + options.baseDir = std::string("/data/service/el1/public/database/") + appId.appId; + /* define kvstore(database) name. */ + StoreId storeId = { "fuzzer_single" }; + mkdir(options.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + /* [create and] open and initialize kvstore instance. */ + manager.GetSingleKvStore(options, appId, storeId, singleKvStore_); +} + +void TearDown(void) +{ + (void)remove("/data/service/el1/public/database/kvutilfuzzertest/key"); + (void)remove("/data/service/el1/public/database/kvutilfuzzertest/kvdb"); + (void)remove("/data/service/el1/public/database/kvutilfuzzertest"); +} + +void ToResultSetBridgeFuzz(FuzzedDataProvider &provider) +{ + std::string skey; + std::string svalue; + Entry entry; + std::vector entries; + std::vector keys; + int sum = provider.ConsumeIntegralInRange(0, 10); + for (size_t i = 0; i < sum; i++) { + skey = provider.ConsumeRandomLengthString(); + svalue = provider.ConsumeRandomLengthString(); + entry.key = {PREFIX + skey}; + entry.value = {PREFIX + svalue}; + entries.push_back(entry); + keys.push_back(entry.key); + } + singleKvStore_->PutBatch(entries); + std::shared_ptr resultSet = nullptr; + DataSharePredicates predicates; + predicates.KeyPrefix("test"); + DataQuery query; + auto status = KvUtils::ToQuery(predicates, query); + if (status == Status::SUCCESS) { + status = singleKvStore_->GetResultSet(query, resultSet); + } + KvUtils::ToResultSetBridge(resultSet); + singleKvStore_->DeleteBatch(keys); +} + +void ToEntryFuzz(FuzzedDataProvider &provider) +{ + DataShareValuesBucket bucket {}; + if (provider.ConsumeBool()) { + bucket.Put(KEY, provider.ConsumeRandomLengthString()); + bucket.Put(VALUE, provider.ConsumeRandomLengthString()); + } + auto entry = KvUtils::ToEntry(bucket); +} + +ValueType CreateData(int32_t type, FuzzedDataProvider &provider) +{ + ValueType data; + switch (type) { + case DataType::STRING: + data = provider.ConsumeRandomLengthString(); + break; + case DataType::INT64: + data = provider.ConsumeIntegral(); + break; + case DataType::BOOL: + data = provider.ConsumeBool(); + break; + case DataType::DOUBLE: + data = provider.ConsumeFloatingPoint(); + break; + case DataType::VECTOR_INT64: + data = provider.ConsumeRemainingBytes(); + break; + default: + data = {}; + break; + } + return data; +} + +void ToEntriesFuzz(FuzzedDataProvider &provider) +{ + std::vector buckets; + const uint8_t bucketCount = provider.ConsumeIntegralInRange(1, 10); + DataShareValuesBucket bucket; + ValueType key; + ValueType value; + for (int i = 1; i < bucketCount; ++i) { + auto keyType = provider.ConsumeIntegralInRange(1, 5); + auto valueType = provider.ConsumeIntegralInRange(1, 5); + key = CreateData(keyType, provider); + value = CreateData(valueType, provider); + bucket.Put(KEY, key); + bucket.Put(VALUE, value); + buckets.push_back(std::move(bucket)); + } + auto entry = KvUtils::ToEntries(buckets); +} + +void GetKeysFuzz(FuzzedDataProvider &provider) +{ + std::vector keys; + keys.push_back(provider.ConsumeRandomLengthString()); + keys.push_back(provider.ConsumeRandomLengthString()); + keys.push_back(provider.ConsumeRandomLengthString()); + DataSharePredicates predicates; + predicates.InKeys(keys); + std::vector kvKeys; + KvUtils::GetKeys(predicates, kvKeys); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + /* Run your code on data */ + FuzzedDataProvider provider(data, size); + OHOS::SetUpTestCase(); + OHOS::ToResultSetBridgeFuzz(provider); + OHOS::ToEntryFuzz(provider); + OHOS::ToEntriesFuzz(provider); + OHOS::GetKeysFuzz(provider); + OHOS::TearDown(); + return 0; +} \ No newline at end of file diff --git a/kv_store/test/fuzztest/kvutil_fuzzer/kvutil_fuzzer.h b/kv_store/test/fuzztest/kvutil_fuzzer/kvutil_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..c2d7e4ab06815121e98e29ee570319f535838811 --- /dev/null +++ b/kv_store/test/fuzztest/kvutil_fuzzer/kvutil_fuzzer.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 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 KVUTIL_FUZZER_H +#define KVUTIL_FUZZER_H + +#define FUZZ_PROJECT_NAME "kvutil_fuzzer" + +#endif // KVUTIL_FUZZER_H + diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/project.xml b/kv_store/test/fuzztest/kvutil_fuzzer/project.xml similarity index 95% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/project.xml rename to kv_store/test/fuzztest/kvutil_fuzzer/project.xml index 6e8ad2cfde8f8bda4beb6cabbe7efd8bc3c54eec..66e1dcac475475fb101b6f8670ec699e6e9696aa 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/project.xml +++ b/kv_store/test/fuzztest/kvutil_fuzzer/project.xml @@ -1,5 +1,5 @@ - + + + + LICENSE + + + + + + + + + + \ No newline at end of file diff --git a/relational_store/bundle.json b/relational_store/bundle.json index 81a4db740348a98be8b6ca97db09f76b3fb08939..efbedbbb3c5c59dc2128bdafbb03635df36f5ff5 100644 --- a/relational_store/bundle.json +++ b/relational_store/bundle.json @@ -52,6 +52,7 @@ "access_token", "common_event_service", "c_utils", + "data_share", "device_manager", "eventhandler", "hilog", @@ -66,11 +67,10 @@ "icu", "sqlite", "file_api", - "json" + "json", + "runtime_core" ], - "third_party": [ - "sqlite" - ] + "third_party": [ "sqlite" ] }, "build": { "sub_component": [ @@ -79,8 +79,8 @@ "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb_data_share_adapter:rdb_data_share_adapter", "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb:native_rdb", "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/cloud_data:clouddata", - "//foundation/distributeddatamgr/relational_store/interfaces/ndk/src:native_rdb_ndk", - "//foundation/distributeddatamgr/relational_store/frameworks/cj:cj_relational_store_ffi", + "//foundation/distributeddatamgr/relational_store/interfaces/rdb_ndk_utils:native_rdb_ndk_utils", + "//foundation/distributeddatamgr/relational_store/interfaces/ndk:native_rdb_ndk", "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/dataability:dataability", "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/rdb:rdb", "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/rdb:napi_rdb", @@ -89,12 +89,13 @@ "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/common:commontype_napi", "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/sendablerelationalstore:sendablerelationalstore", "//foundation/distributeddatamgr/relational_store/frameworks/native/icu:build_module", - "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/gdb:native_graphstore", - "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/graphstore:graphstore" + "//foundation/distributeddatamgr/relational_store/frameworks/native/obs_mgr_adapter:rdb_obs_mgr_adapter", + "//foundation/distributeddatamgr/relational_store/frameworks/native/rdb_crypt:relational_store_crypt", + "//foundation/distributeddatamgr/relational_store/frameworks/js/ani/relationalstore:relationalstore_ani_package" ], "inner_kits": [ { - "name": "//foundation/distributeddatamgr/relational_store/interfaces/ndk/src:native_rdb_ndk", + "name": "//foundation/distributeddatamgr/relational_store/interfaces/ndk:native_rdb_ndk", "header": { "header_files": [ "oh_predicates.h", @@ -107,6 +108,15 @@ "header_base": "//foundation/distributeddatamgr/relational_store/interfaces/ndk/include" } }, + { + "name": "//foundation/distributeddatamgr/relational_store/interfaces/rdb_ndk_utils:native_rdb_ndk_utils", + "header": { + "header_files": [ + "rdb_ndk_utils.h" + ], + "header_base": "//foundation/distributeddatamgr/relational_store/interfaces/rdb_ndk_utils/include" + } + }, { "name": "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb:native_rdb", "header": { @@ -114,6 +124,7 @@ "abs_rdb_predicates.h", "abs_result_set.h", "abs_shared_result_set.h", + "knowledge_types.h", "rdb_common.h", "rdb_errno.h", "rdb_helper.h", @@ -180,21 +191,10 @@ } }, { - "name": "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/gdb:native_graphstore", + "name": "//foundation/distributeddatamgr/relational_store/frameworks/cj:cj_relational_store_ffi", "header": { - "header_files": [ - "edge.h", - "gdb_errors.h", - "gdb_helper.h", - "gdb_store.h", - "gdb_store_config.h", - "gdb_transaction.h", - "path.h", - "path_segment.h", - "result.h", - "vertex.h" - ], - "header_base": "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/gdb/include" + "header_files": [], + "header_base": "//foundation/distributeddatamgr/relational_store/frameworks/cj/include" } } ], @@ -206,18 +206,22 @@ "//foundation/distributeddatamgr/relational_store/test/js/relationalstore:unittest", "//foundation/distributeddatamgr/relational_store/test/js/clouddata:cloudtest", "//foundation/distributeddatamgr/relational_store/test/ndk:unittest", + "//foundation/distributeddatamgr/relational_store/test/ndk:fuzztest", + "//foundation/distributeddatamgr/relational_store/test/ets/cloud_data:stage_unittest", "//foundation/distributeddatamgr/relational_store/test/native/appdatafwk:unittest", + "//foundation/distributeddatamgr/relational_store/test/native/clouddata:fuzztest", "//foundation/distributeddatamgr/relational_store/test/native/clouddata:unittest", "//foundation/distributeddatamgr/relational_store/test/native/dataability:unittest", "//foundation/distributeddatamgr/relational_store/test/native/rdb:unittest", + "//foundation/distributeddatamgr/relational_store/test/native/rdb/unittest/mock_obs_manage_test:unittest", + "//foundation/distributeddatamgr/relational_store/test/native/rdb/unittest/dynamic_load_test:unittest", + "//foundation/distributeddatamgr/relational_store/test/native/rdb/unittest/sqlite_statement_test:unittest", + "//foundation/distributeddatamgr/relational_store/test/native/rdb/unittest/mockservice:unittest", "//foundation/distributeddatamgr/relational_store/test/native/rdb:fuzztest", "//foundation/distributeddatamgr/relational_store/test/native/rdb_data_ability_adapter:unittest", "//foundation/distributeddatamgr/relational_store/test/native/rdb_data_share_adapter:unittest", "//foundation/distributeddatamgr/relational_store/test/native/rdb:distributedtest", - "//foundation/distributeddatamgr/relational_store/test/native/gdb:unittest", - "//foundation/distributeddatamgr/relational_store/test/native/gdb:fuzztest", - "//foundation/distributeddatamgr/relational_store/test/js/gdb:performancetest", - "//foundation/distributeddatamgr/relational_store/test/js/gdb:unittest" + "//foundation/distributeddatamgr/relational_store/test/ets/relational_store:stage_unittest" ] } } diff --git a/relational_store/frameworks/cj/BUILD.gn b/relational_store/frameworks/cj/BUILD.gn index 4a01d574ca0c6bd49726abed5c3a314935cc04d8..3450a16619d26b8e23552a13a9958d5bd124adb0 100644 --- a/relational_store/frameworks/cj/BUILD.gn +++ b/relational_store/frameworks/cj/BUILD.gn @@ -55,6 +55,7 @@ ohos_shared_library("cj_relational_store_ffi") { "common_event_service:cesfwk_innerkits", "hilog:libhilog", "hitrace:hitrace_meter", + "ipc:ipc_single", "napi:ace_napi", "napi:cj_bind_ffi", "napi:cj_bind_native", diff --git a/relational_store/frameworks/cj/include/relational_store_ffi.h b/relational_store/frameworks/cj/include/relational_store_ffi.h index 9fb62f3ce07fae1e05110f84cbe7e2602903ae13..a499e27c7f1ec389893f3c10933597d9e8db895f 100644 --- a/relational_store/frameworks/cj/include/relational_store_ffi.h +++ b/relational_store/frameworks/cj/include/relational_store_ffi.h @@ -216,7 +216,7 @@ FFI_EXPORT void FfiOHOSRelationalStoreExecuteSqlBindArgs( FFI_EXPORT ValuesBucket FfiOHOSRelationalStoreGetRow(int64_t id, int32_t *errCode); FFI_EXPORT int32_t FfiOHOSRelationalStoreOn( - int64_t id, const char *event, bool interProcess, void (*callback)(), void (*callbackRef)()); + int64_t id, const char *event, bool interProcess, int64_t callback, void (*callbackRef)()); FFI_EXPORT int32_t FfiOHOSRelationalStoreOnArrStr(int64_t id, int32_t subscribeType, int64_t callbackId); @@ -224,7 +224,7 @@ FFI_EXPORT int32_t FfiOHOSRelationalStoreOnChangeInfo(int64_t id, int32_t subscr FFI_EXPORT int32_t FfiOHOSRelationalStoreOnProgressDetails(int64_t id, int64_t callbackId); -FFI_EXPORT int32_t FfiOHOSRelationalStoreOff(int64_t id, const char *event, bool interProcess, void (*callback)()); +FFI_EXPORT int32_t FfiOHOSRelationalStoreOff(int64_t id, const char *event, bool interProcess, int64_t callback); FFI_EXPORT int32_t FfiOHOSRelationalStoreOffAll(int64_t id, const char *event, bool interProcess); diff --git a/relational_store/frameworks/cj/include/relational_store_impl_rdbpredicatesproxy.h b/relational_store/frameworks/cj/include/relational_store_impl_rdbpredicatesproxy.h index 0fb1ce6dc1beff18742c4d200bb049a3a6336a65..1f3616be1dbf25a8a5f46a9edfa82ab80a269cb2 100644 --- a/relational_store/frameworks/cj/include/relational_store_impl_rdbpredicatesproxy.h +++ b/relational_store/frameworks/cj/include/relational_store_impl_rdbpredicatesproxy.h @@ -97,8 +97,32 @@ public: void NotEqualTo(const char *field, ValueType value); + void NotContains(const char* field, const char* value); + + void NotLike(const char* field, const char* value); + std::shared_ptr GetPredicates(); + void LessThanOrEqualToEx(const char *field, const ValueTypeEx *value); + + void EqualToEx(const char *field, const ValueTypeEx *value); + + void GreaterThanOrEqualToEx(const char *field, const ValueTypeEx *value); + + void GreaterThanEx(const char *field, const ValueTypeEx *value); + + void NotBetweenEx(const char *field, const ValueTypeEx *lowValue, const ValueTypeEx *highValue); + + void LessThanEx(const char *field, const ValueTypeEx *value); + + void BetweenEx(const char *field, const ValueTypeEx *lowValue, const ValueTypeEx *highValue); + + void InEx(const char *field, ValueTypeEx *values, int64_t valuesSize); + + void NotInEx(const char *field, ValueTypeEx *values, int64_t valuesSize); + + void NotEqualToEx(const char *field, const ValueTypeEx *value); + private: std::shared_ptr predicates_; diff --git a/relational_store/frameworks/cj/include/relational_store_impl_rdbstore.h b/relational_store/frameworks/cj/include/relational_store_impl_rdbstore.h index b2edd3f34a1c95a47e3a825c9f060f98a0b04bd6..7e05d9a179b79882b292819c17dd7db5c86b82e5 100644 --- a/relational_store/frameworks/cj/include/relational_store_impl_rdbstore.h +++ b/relational_store/frameworks/cj/include/relational_store_impl_rdbstore.h @@ -34,7 +34,7 @@ namespace Relational { class RdbStoreObserverImpl : public DistributedRdb::RdbStoreObserver { public: enum FuncType : int32_t { NoParam = 0, ParamArrStr, ParamChangeInfo }; - RdbStoreObserverImpl(std::function *callback, const std::function &callbackRef); + RdbStoreObserverImpl(int64_t callback, const std::function &callbackRef); RdbStoreObserverImpl(int64_t id, FuncType type, int32_t mode = DistributedRdb::REMOTE); ~RdbStoreObserverImpl() override = default; void OnChange() override @@ -59,10 +59,10 @@ public: { return callbackId; }; - std::function *GetCallBack(); + int64_t GetCallBack(); private: - std::function *m_callback = nullptr; + int64_t m_callback = 0; std::function m_callbackRef = nullptr; int32_t mode_ = DistributedRdb::REMOTE; int64_t callbackId = 0; @@ -126,21 +126,21 @@ public: NativeRdb::ConflictResolution conflictResolution, int32_t *errCode); std::shared_ptr QuerySql(const char *sql, ValueType *bindArgs, int64_t size); void ExecuteSql(const char *sql, ValueType *bindArgs, int64_t bindArgsSize, int32_t *errCode); - int32_t RegisterObserver(const char *event, bool interProcess, std::function *callback, + int32_t RegisterObserver(const char *event, bool interProcess, int64_t callback, const std::function &callbackRef); int32_t RegisteredObserver(DistributedRdb::SubscribeOption option, std::map>> &observers, - std::function *callback, const std::function &callbackRef); + int64_t callback, const std::function &callbackRef); int32_t RegisterObserverArrStr(int32_t subscribeType, int64_t callbackId); int32_t RegisterObserverChangeInfo(int32_t subscribeType, int64_t callbackId); int32_t RegisterObserverProgressDetails(int64_t callbackId); bool HasRegisteredObserver( - std::function *callback, std::list> &observers); - int32_t UnRegisterObserver(const char *event, bool interProcess, std::function *callback); + int64_t callback, std::list> &observers); + int32_t UnRegisterObserver(const char *event, bool interProcess, int64_t callback); int32_t UnRegisterAllObserver(const char *event, bool interProcess); int32_t UnRegisteredObserver(DistributedRdb::SubscribeOption option, std::map>> &observers, - std::function *callback); + int64_t callback); int32_t UnRegisteredAllObserver(DistributedRdb::SubscribeOption option, std::map>> &observers); int32_t UnRegisterObserverArrStrChangeInfo(int32_t subscribeType, int64_t callbackId); @@ -151,6 +151,13 @@ public: int32_t GetVersion(int32_t &errCode); void SetVersion(int32_t value, int32_t &errCode); ModifyTime GetModifyTime(char *cTable, char *cColumnName, CArrPRIKeyType &cPrimaryKeys, int32_t &errCode); + int32_t GetRebuilt(); + int64_t InsertEx(const char *table, ValuesBucketEx valuesBucket, int32_t conflict, int32_t *errCode); + int32_t UpdateEx(ValuesBucketEx valuesBucket, RdbPredicatesImpl &predicates, + NativeRdb::ConflictResolution conflictResolution, int32_t *errCode); + int32_t BatchInsertEx(int64_t &insertNum, const char *tableName, ValuesBucketEx *valuesBuckets, int64_t valuesSize); + std::shared_ptr QuerySqlEx(const char *sql, ValueTypeEx *bindArgs, int64_t size); + void ExecuteSqlEx(const char *sql, ValueTypeEx *bindArgs, int64_t bindArgsSize, int32_t *errCode); private: friend class OHOS::FFI::RuntimeType; @@ -167,9 +174,13 @@ private: int64_t GetRdbStore(OHOS::AbilityRuntime::Context *context, StoreConfig config, int32_t *errCode); +int64_t GetRdbStoreEx(OHOS::AbilityRuntime::Context *context, const StoreConfigEx *config, int32_t *errCode); + void DeleteRdbStore(OHOS::AbilityRuntime::Context *context, const char *name, int32_t *errCode); void DeleteRdbStoreConfig(OHOS::AbilityRuntime::Context *context, StoreConfig config, int32_t *errCode); + +void DeleteRdbStoreConfigEx(OHOS::AbilityRuntime::Context *context, const StoreConfigEx *config, int32_t *errCode); } // namespace Relational } // namespace OHOS diff --git a/relational_store/frameworks/cj/include/relational_store_impl_resultsetproxy.h b/relational_store/frameworks/cj/include/relational_store_impl_resultsetproxy.h index 041f4f0b4c40981cc35d942a39e5c293aa91b7c9..f7750328c2dbc7e3e3f1be2491e2af4ed945627d 100644 --- a/relational_store/frameworks/cj/include/relational_store_impl_resultsetproxy.h +++ b/relational_store/frameworks/cj/include/relational_store_impl_resultsetproxy.h @@ -87,6 +87,10 @@ public: ValuesBucket GetRow(int32_t *rtnCode); + ValuesBucketEx GetRowEx(int32_t *rtnCode); + + ValueTypeEx GetValue(int32_t columnIndex, int32_t* rtnCode); + std::shared_ptr resultSetValue; private: diff --git a/relational_store/frameworks/cj/include/relational_store_utils.h b/relational_store/frameworks/cj/include/relational_store_utils.h index c76fc43740ec0290ea6851f22c4e087b4a36810c..6a3d1c0c613d49a864140a4d4cf04fbacc80ff0b 100644 --- a/relational_store/frameworks/cj/include/relational_store_utils.h +++ b/relational_store/frameworks/cj/include/relational_store_utils.h @@ -23,8 +23,36 @@ namespace OHOS { namespace Relational { +#define ERROR_VALUE (-1) + char *MallocCString(const std::string &origin); +struct CArrUI8 { + uint8_t *head; + int64_t size; +}; + +struct CArrFloat { + float *head; + int64_t size; +}; + +struct CArrStr { + char **head; + int64_t size; +}; + +struct CryptoParam { + CArrUI8 encryptKey; + int32_t iterNum; + int32_t encryptAlgo; + int32_t hmacAlgo; + int32_t kdfAlgo; + uint32_t cryptoPageSize; +}; + +OHOS::NativeRdb::RdbStoreConfig::CryptoParam ToCCryptoParam(CryptoParam param); + struct StoreConfig { char *name; int32_t securityLevel; @@ -35,6 +63,24 @@ struct StoreConfig { bool autoCleanDirtyData; }; +struct StoreConfigEx { + char *name; + int32_t securityLevel; + bool encrypt; + char *dataGroupId; + char *customDir; + char *rootDir; + bool isSearchable; + bool autoCleanDirtyData; + bool allowRebuild; + bool isReadOnly; + CArrStr pluginLibs; + CryptoParam cryptoParam; + bool vector; + int32_t tokenizer; + bool persist; +}; + struct Asset { const char *name; const char *uri; @@ -50,16 +96,6 @@ struct Assets { int64_t size; }; -struct CArrUI8 { - uint8_t *head; - int64_t size; -}; - -struct CArrStr { - char **head; - int64_t size; -}; - CArrStr VectorToCArrStr(const std::vector &devices); std::vector CArrStrToVector(CArrStr carr); @@ -75,7 +111,38 @@ struct ValueType { uint8_t tag; }; -enum TagType { TYPE_NULL, TYPE_INT, TYPE_DOU, TYPE_STR, TYPE_BOOL, TYPE_BLOB, TYPE_ASSET, TYPE_ASSETS }; +struct BigInt { + CArrUI8 value; + bool sign; +}; + +struct ValueTypeEx { + int64_t integer; + double dou; + char *string; + bool boolean; + CArrUI8 uint8Array; + Asset asset; + Assets assets; + CArrFloat floatArray; + BigInt bigInt; + uint8_t tag; +}; + +std::vector CArrUI8ToVector(CArrUI8 carr); + +enum TagType { + TYPE_NULL, + TYPE_INT, + TYPE_DOU, + TYPE_STR, + TYPE_BOOL, + TYPE_BLOB, + TYPE_ASSET, + TYPE_ASSETS, + TYPE_FLOATARR, + TYPE_BIGINT +}; struct ValuesBucket { char **key; @@ -83,8 +150,16 @@ struct ValuesBucket { int64_t size; }; +struct ValuesBucketEx { + char **key; + ValueTypeEx *value; + int64_t size; +}; + NativeRdb::ValueObject ValueTypeToValueObject(const ValueType &value); +NativeRdb::ValueObject ValueTypeExToValueObject(const ValueTypeEx &value); + struct CArrInt32 { int32_t *head; int64_t size; @@ -98,6 +173,8 @@ struct CArrSyncResult { ValueType ValueObjectToValueType(const NativeRdb::ValueObject &object); +ValueTypeEx ValueObjectToValueTypeEx(const NativeRdb::ValueObject &object); + struct RetPRIKeyType { int64_t integer; double dou; diff --git a/relational_store/frameworks/cj/src/relational_store_ffi.cpp b/relational_store/frameworks/cj/src/relational_store_ffi.cpp index f986a7555c3ac7858e869bed877d780860bce41b..81ff6c782f262bd3376d0fafabffcf45b46951fb 100644 --- a/relational_store/frameworks/cj/src/relational_store_ffi.cpp +++ b/relational_store/frameworks/cj/src/relational_store_ffi.cpp @@ -22,8 +22,6 @@ #include "napi_rdb_js_utils.h" #include "rdb_errno.h" #include "relational_store_utils.h" -#include "rdb_errno.h" -#include "js_utils.h" using namespace OHOS::FFI; @@ -35,6 +33,12 @@ int64_t FfiOHOSRelationalStoreGetRdbStore(OHOS::AbilityRuntime::Context *context return GetRdbStore(context, config, errCode); } +FFI_EXPORT int64_t FfiOHOSRelationalStoreGetRdbStoreEx(OHOS::AbilityRuntime::Context *context, + const StoreConfigEx *config, int32_t *errCode) +{ + return GetRdbStoreEx(context, config, errCode); +} + void FfiOHOSRelationalStoreDeleteRdbStore(OHOS::AbilityRuntime::Context *context, const char *name, int32_t *errCode) { DeleteRdbStore(context, name, errCode); @@ -46,6 +50,12 @@ void FfiOHOSRelationalStoreDeleteRdbStoreConfig( DeleteRdbStoreConfig(context, config, errCode); } +void FfiOHOSRelationalStoreDeleteRdbStoreConfigEx( + OHOS::AbilityRuntime::Context *context, const StoreConfigEx *config, int32_t *errCode) +{ + DeleteRdbStoreConfigEx(context, config, errCode); +} + int64_t FfiOHOSRelationalStoreRdbPredicatesConstructor(const char *tableName) { auto nativeRdbPredicates = FFIData::Create(tableName); @@ -265,6 +275,16 @@ int32_t FfiOHOSRelationalStoreLessThanOrEqualTo(int64_t id, const char *field, V return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreLessThanOrEqualToEx(int64_t id, const char *field, const ValueTypeEx *value) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->LessThanOrEqualToEx(field, value); + return 0; +} + int32_t FfiOHOSRelationalStoreEqualTo(int64_t id, const char *field, ValueType value) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -275,6 +295,16 @@ int32_t FfiOHOSRelationalStoreEqualTo(int64_t id, const char *field, ValueType v return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreEqualToEx(int64_t id, const char *field, const ValueTypeEx *value) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->EqualToEx(field, value); + return 0; +} + int32_t FfiOHOSRelationalStoreGreaterThanOrEqualTo(int64_t id, const char *field, ValueType value) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -285,6 +315,16 @@ int32_t FfiOHOSRelationalStoreGreaterThanOrEqualTo(int64_t id, const char *field return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreGreaterThanOrEqualToEx(int64_t id, const char *field, const ValueTypeEx *value) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->GreaterThanOrEqualToEx(field, value); + return 0; +} + int32_t FfiOHOSRelationalStoreGreaterThan(int64_t id, const char *field, ValueType value) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -295,6 +335,16 @@ int32_t FfiOHOSRelationalStoreGreaterThan(int64_t id, const char *field, ValueTy return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreGreaterThanEx(int64_t id, const char *field, const ValueTypeEx *value) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->GreaterThanEx(field, value); + return 0; +} + int32_t FfiOHOSRelationalStoreNotBetween(int64_t id, const char *field, ValueType lowValue, ValueType highValue) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -305,6 +355,17 @@ int32_t FfiOHOSRelationalStoreNotBetween(int64_t id, const char *field, ValueTyp return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreNotBetweenEx(int64_t id, const char *field, const ValueTypeEx *lowValue, + const ValueTypeEx *highValue) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->NotBetweenEx(field, lowValue, highValue); + return 0; +} + int32_t FfiOHOSRelationalStoreLessThan(int64_t id, const char *field, ValueType value) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -315,6 +376,16 @@ int32_t FfiOHOSRelationalStoreLessThan(int64_t id, const char *field, ValueType return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreLessThanEx(int64_t id, const char *field, const ValueTypeEx *value) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->LessThanEx(field, value); + return 0; +} + int32_t FfiOHOSRelationalStoreBetween(int64_t id, const char *field, ValueType lowValue, ValueType highValue) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -325,6 +396,17 @@ int32_t FfiOHOSRelationalStoreBetween(int64_t id, const char *field, ValueType l return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreBetweenEx(int64_t id, const char *field, const ValueTypeEx *lowValue, + const ValueTypeEx *highValue) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->BetweenEx(field, lowValue, highValue); + return 0; +} + int32_t FfiOHOSRelationalStoreIn(int64_t id, const char *field, ValueType *values, int64_t valuesSize) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -335,6 +417,16 @@ int32_t FfiOHOSRelationalStoreIn(int64_t id, const char *field, ValueType *value return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreInEx(int64_t id, const char *field, ValueTypeEx *values, int64_t valuesSize) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->InEx(field, values, valuesSize); + return 0; +} + int32_t FfiOHOSRelationalStoreNotIn(int64_t id, const char *field, ValueType *values, int64_t valuesSize) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -345,6 +437,16 @@ int32_t FfiOHOSRelationalStoreNotIn(int64_t id, const char *field, ValueType *va return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreNotInEx(int64_t id, const char *field, ValueTypeEx *values, int64_t valuesSize) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->NotInEx(field, values, valuesSize); + return 0; +} + int32_t FfiOHOSRelationalStoreNotEqualTo(int64_t id, const char *field, ValueType value) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -355,9 +457,23 @@ int32_t FfiOHOSRelationalStoreNotEqualTo(int64_t id, const char *field, ValueTyp return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreNotEqualToEx(int64_t id, const char *field, const ValueTypeEx *value) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->NotEqualToEx(field, value); + return 0; +} + + int64_t FfiOHOSRelationalStoreQuery( int64_t id, int64_t predicatesId, char **columns, int64_t columnsSize, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = -1; @@ -370,8 +486,7 @@ int64_t FfiOHOSRelationalStoreQuery( } auto resultSet = nativeRdbStore->Query(*nativeRdbPredicates, columns, columnsSize); if (resultSet == nullptr) { - // If the API version is greater than or equal to 20, throw E_ALREADY_CLOSED. - *errCode = (AppDataMgrJsKit::JSUtils::GetHapVersion() >= 20) ? NativeRdb::E_ALREADY_CLOSED : NativeRdb::E_ERROR; + *errCode = RelationalStoreJsKit::E_INNER_ERROR; return -1; } else { *errCode = RelationalStoreJsKit::OK; @@ -408,6 +523,9 @@ int64_t FfiOHOSRelationalStoreRemoteQuery( int64_t FfiOHOSRelationalStoreDelete(int64_t id, int64_t predicatesId, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = -1; @@ -507,6 +625,9 @@ int32_t FfiOHOSRelationalStoreBeginTransaction(int64_t id) int64_t FfiOHOSRelationalStoreInsert( int64_t id, const char *table, ValuesBucket valuesBucket, int32_t conflict, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = -1; @@ -515,9 +636,26 @@ int64_t FfiOHOSRelationalStoreInsert( return nativeRdbStore->Insert(table, valuesBucket, conflict, errCode); } +FFI_EXPORT int64_t FfiOHOSRelationalStoreInsertEx( + int64_t id, const char *table, ValuesBucketEx valuesBucket, int32_t conflict, int32_t *errCode) +{ + if (errCode == nullptr) { + return -1; + } + auto nativeRdbStore = FFIData::GetData(id); + if (nativeRdbStore == nullptr) { + *errCode = -1; + return -1; + } + return nativeRdbStore->InsertEx(table, valuesBucket, conflict, errCode); +} + int64_t FfiOHOSRelationalStoreUpdate(int64_t id, ValuesBucket valuesBucket, int64_t predicatesId, NativeRdb::ConflictResolution conflictResolution, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeRdbStore = FFIData::GetData(id); auto nativeRdbSPredicates = FFIData::GetData(predicatesId); if (nativeRdbStore == nullptr || nativeRdbSPredicates == nullptr) { @@ -527,8 +665,26 @@ int64_t FfiOHOSRelationalStoreUpdate(int64_t id, ValuesBucket valuesBucket, int6 return nativeRdbStore->Update(valuesBucket, *nativeRdbSPredicates, conflictResolution, errCode); } +FFI_EXPORT int64_t FfiOHOSRelationalStoreUpdateEx(int64_t id, ValuesBucketEx valuesBucket, int64_t predicatesId, + NativeRdb::ConflictResolution conflictResolution, int32_t *errCode) +{ + if (errCode == nullptr) { + return -1; + } + auto nativeRdbStore = FFIData::GetData(id); + auto nativeRdbSPredicates = FFIData::GetData(predicatesId); + if (nativeRdbStore == nullptr || nativeRdbSPredicates == nullptr) { + *errCode = -1; + return -1; + } + return nativeRdbStore->UpdateEx(valuesBucket, *nativeRdbSPredicates, conflictResolution, errCode); +} + void FfiOHOSRelationalStoreExecuteSql(int64_t id, const char *sql, int32_t *errCode) { + if (errCode == nullptr) { + return; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = -1; @@ -539,6 +695,9 @@ void FfiOHOSRelationalStoreExecuteSql(int64_t id, const char *sql, int32_t *errC CArrSyncResult FfiOHOSRelationalStoreSync(int64_t id, int32_t mode, int64_t predicatesId, int32_t *errCode) { + if (errCode == nullptr) { + return CArrSyncResult{ nullptr, nullptr, 0 }; + } auto nativeRdbStore = FFIData::GetData(id); auto nativeRdbPredicates = FFIData::GetData(predicatesId); if (nativeRdbStore == nullptr || nativeRdbPredicates == nullptr) { @@ -559,6 +718,9 @@ CArrStr FfiOHOSRelationalStoreGetAllColumnNames(int64_t id) int32_t FfiOHOSRelationalStoreGetColumnCount(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -569,6 +731,9 @@ int32_t FfiOHOSRelationalStoreGetColumnCount(int64_t id, int32_t *errCode) int32_t FfiOHOSRelationalStoreGetRowCount(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -579,6 +744,9 @@ int32_t FfiOHOSRelationalStoreGetRowCount(int64_t id, int32_t *errCode) int32_t FfiOHOSRelationalStoreGetRowIndex(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -589,6 +757,9 @@ int32_t FfiOHOSRelationalStoreGetRowIndex(int64_t id, int32_t *errCode) bool FfiOHOSRelationalStoreIsAtFirstRow(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -600,6 +771,9 @@ bool FfiOHOSRelationalStoreIsAtFirstRow(int64_t id, int32_t *errCode) bool FfiOHOSRelationalStoreIsAtLastRow(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -611,6 +785,9 @@ bool FfiOHOSRelationalStoreIsAtLastRow(int64_t id, int32_t *errCode) bool FfiOHOSRelationalStoreIsEnded(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -622,6 +799,9 @@ bool FfiOHOSRelationalStoreIsEnded(int64_t id, int32_t *errCode) bool FfiOHOSRelationalStoreIsStarted(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -633,6 +813,9 @@ bool FfiOHOSRelationalStoreIsStarted(int64_t id, int32_t *errCode) bool FfiOHOSRelationalStoreIsClosed(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -644,6 +827,9 @@ bool FfiOHOSRelationalStoreIsClosed(int64_t id, int32_t *errCode) double FfiOHOSRelationalStoreGetDouble(int64_t id, int32_t columnIndex, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return -1; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -654,6 +840,9 @@ double FfiOHOSRelationalStoreGetDouble(int64_t id, int32_t columnIndex, int32_t bool FfiOHOSRelationalStoreGoToRow(int64_t id, int32_t position, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -664,6 +853,9 @@ bool FfiOHOSRelationalStoreGoToRow(int64_t id, int32_t position, int32_t *rtnCod bool FfiOHOSRelationalStoreGoToPreviousRow(int64_t id, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -674,6 +866,9 @@ bool FfiOHOSRelationalStoreGoToPreviousRow(int64_t id, int32_t *rtnCode) bool FfiOHOSRelationalStoreGoToLastRow(int64_t id, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -684,6 +879,9 @@ bool FfiOHOSRelationalStoreGoToLastRow(int64_t id, int32_t *rtnCode) char *FfiOHOSRelationalStoreGetColumnName(int64_t id, int32_t columnIndex, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return nullptr; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -694,6 +892,9 @@ char *FfiOHOSRelationalStoreGetColumnName(int64_t id, int32_t columnIndex, int32 bool FfiOHOSRelationalStoreIsColumnNull(int64_t id, int32_t columnIndex, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -704,6 +905,9 @@ bool FfiOHOSRelationalStoreIsColumnNull(int64_t id, int32_t columnIndex, int32_t Asset FfiOHOSRelationalStoreGetAsset(int64_t id, int32_t columnIndex, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return Asset{ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, 0 }; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -723,6 +927,9 @@ int32_t FfiOHOSRelationalStoreClose(int64_t id) int32_t FfiOHOSRelationalStoreGetColumnIndex(int64_t id, char *columnName, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return -1; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -733,6 +940,9 @@ int32_t FfiOHOSRelationalStoreGetColumnIndex(int64_t id, char *columnName, int32 char *FfiOHOSRelationalStoreGetString(int64_t id, int32_t columnIndex, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return nullptr; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -743,6 +953,9 @@ char *FfiOHOSRelationalStoreGetString(int64_t id, int32_t columnIndex, int32_t * bool FfiOHOSRelationalStoreGoToFirstRow(int64_t id, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -753,6 +966,9 @@ bool FfiOHOSRelationalStoreGoToFirstRow(int64_t id, int32_t *rtnCode) int64_t FfiOHOSRelationalStoreGetLong(int64_t id, int32_t columnIndex, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return -1; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -763,6 +979,9 @@ int64_t FfiOHOSRelationalStoreGetLong(int64_t id, int32_t columnIndex, int32_t * bool FfiOHOSRelationalStoreGoToNextRow(int64_t id, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -773,6 +992,9 @@ bool FfiOHOSRelationalStoreGoToNextRow(int64_t id, int32_t *rtnCode) CArrUI8 FfiOHOSRelationalStoreGetBlob(int64_t id, int32_t columnIndex, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return CArrUI8{ nullptr, 0 }; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -783,6 +1005,9 @@ CArrUI8 FfiOHOSRelationalStoreGetBlob(int64_t id, int32_t columnIndex, int32_t * bool FfiOHOSRelationalStoreGoTo(int64_t id, int32_t offset, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -793,6 +1018,9 @@ bool FfiOHOSRelationalStoreGoTo(int64_t id, int32_t offset, int32_t *rtnCode) Assets FfiOHOSRelationalStoreGetAssets(int64_t id, int32_t columnIndex, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return Assets{ nullptr, 0 }; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -803,6 +1031,9 @@ Assets FfiOHOSRelationalStoreGetAssets(int64_t id, int32_t columnIndex, int32_t ValuesBucket FfiOHOSRelationalStoreGetRow(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return ValuesBucket{ nullptr, nullptr, 0 }; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -811,6 +1042,32 @@ ValuesBucket FfiOHOSRelationalStoreGetRow(int64_t id, int32_t *errCode) return nativeResultSet->GetRow(errCode); } +FFI_EXPORT ValuesBucketEx FfiOHOSRelationalStoreGetRowEx(int64_t id, int32_t *errCode) +{ + if (errCode == nullptr) { + return ValuesBucketEx{ nullptr, nullptr, 0 }; + } + auto nativeResultSet = FFIData::GetData(id); + if (nativeResultSet == nullptr) { + *errCode = -1; + return ValuesBucketEx{ nullptr, nullptr, 0 }; + } + return nativeResultSet->GetRowEx(errCode); +} + +FFI_EXPORT ValueTypeEx FfiOHOSRelationalStoreResultSetGetValue(int64_t id, int32_t columnIndex, int32_t* errCode) +{ + if (errCode == nullptr) { + return ValueTypeEx{ 0 }; + } + auto nativeResultSet = FFIData::GetData(id); + if (nativeResultSet == nullptr) { + *errCode = -1; + return ValueTypeEx{ 0 }; + } + return nativeResultSet->GetValue(columnIndex, errCode); +} + int32_t FfiOHOSRelationalStoreCleanDirtyData(int64_t id, const char *tableName, uint64_t cursor) { auto nativeRdbStore = FFIData::GetData(id); @@ -823,6 +1080,9 @@ int32_t FfiOHOSRelationalStoreCleanDirtyData(int64_t id, const char *tableName, int32_t FfiOHOSRelationalStoreBatchInsert( int64_t id, const char *tableName, ValuesBucket *values, int64_t valuesSize, int64_t *insertNum) { + if (insertNum == nullptr) { + return -1; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { return -1; @@ -830,8 +1090,24 @@ int32_t FfiOHOSRelationalStoreBatchInsert( return nativeRdbStore->BatchInsert(*insertNum, tableName, values, valuesSize); } +FFI_EXPORT int32_t FfiOHOSRelationalStoreBatchInsertEx( + int64_t id, const char *tableName, ValuesBucketEx *values, int64_t valuesSize, int64_t *insertNum) +{ + if (insertNum == nullptr) { + return -1; + } + auto nativeRdbStore = FFIData::GetData(id); + if (nativeRdbStore == nullptr) { + return -1; + } + return nativeRdbStore->BatchInsertEx(*insertNum, tableName, values, valuesSize); +} + int64_t FfiOHOSRelationalStoreQuerySql(int64_t id, const char *sql, ValueType *bindArgs, int64_t size, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = RelationalStoreJsKit::E_INNER_ERROR; @@ -852,9 +1128,38 @@ int64_t FfiOHOSRelationalStoreQuerySql(int64_t id, const char *sql, ValueType *b return nativeResultSet->GetID(); } +FFI_EXPORT int64_t FfiOHOSRelationalStoreQuerySqlEx(int64_t id, const char *sql, ValueTypeEx *bindArgs, int64_t size, + int32_t *errCode) +{ + if (errCode == nullptr) { + return -1; + } + auto nativeRdbStore = FFIData::GetData(id); + if (nativeRdbStore == nullptr) { + *errCode = RelationalStoreJsKit::E_INNER_ERROR; + return -1; + } + auto resultSet = nativeRdbStore->QuerySqlEx(sql, bindArgs, size); + if (resultSet == nullptr) { + *errCode = RelationalStoreJsKit::E_INNER_ERROR; + return -1; + } else { + *errCode = RelationalStoreJsKit::OK; + } + auto nativeResultSet = FFIData::Create(resultSet); + if (nativeResultSet == nullptr) { + *errCode = -1; + return -1; + } + return nativeResultSet->GetID(); +} + void FfiOHOSRelationalStoreExecuteSqlBindArgs( int64_t id, char *sql, ValueType *bindArgs, int64_t bindArgsSize, int32_t *errCode) { + if (errCode == nullptr) { + return; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = -1; @@ -863,15 +1168,29 @@ void FfiOHOSRelationalStoreExecuteSqlBindArgs( nativeRdbStore->ExecuteSql(sql, bindArgs, bindArgsSize, errCode); } +FFI_EXPORT void FfiOHOSRelationalStoreExecuteSqlBindArgsEx( + int64_t id, char *sql, ValueTypeEx *bindArgs, int64_t bindArgsSize, int32_t *errCode) +{ + if (errCode == nullptr) { + return; + } + auto nativeRdbStore = FFIData::GetData(id); + if (nativeRdbStore == nullptr) { + *errCode = -1; + return; + } + nativeRdbStore->ExecuteSqlEx(sql, bindArgs, bindArgsSize, errCode); +} + int32_t FfiOHOSRelationalStoreOn( - int64_t id, const char *event, bool interProcess, void (*callback)(), void (*callbackRef)()) + int64_t id, const char *event, bool interProcess, int64_t callback, void (*callbackRef)()) { auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { return -1; } auto onChange = [lambda = CJLambda::Create(callbackRef)]() -> void { lambda(); }; - return nativeRdbStore->RegisterObserver(event, interProcess, (std::function *)(callback), onChange); + return nativeRdbStore->RegisterObserver(event, interProcess, callback, onChange); } int32_t FfiOHOSRelationalStoreOnArrStr(int64_t id, int32_t subscribeType, int64_t callbackId) @@ -901,13 +1220,13 @@ int32_t FfiOHOSRelationalStoreOnProgressDetails(int64_t id, int64_t callbackId) return nativeRdbStore->RegisterObserverProgressDetails(callbackId); } -int32_t FfiOHOSRelationalStoreOff(int64_t id, const char *event, bool interProcess, void (*callback)()) +int32_t FfiOHOSRelationalStoreOff(int64_t id, const char *event, bool interProcess, int64_t callback) { auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { return -1; } - return nativeRdbStore->UnRegisterObserver(event, interProcess, (std::function *)(callback)); + return nativeRdbStore->UnRegisterObserver(event, interProcess, callback); } int32_t FfiOHOSRelationalStoreOffAll(int64_t id, const char *event, bool interProcess) @@ -975,6 +1294,9 @@ int32_t FfiOHOSRelationalStoreCloudSync(int64_t id, int32_t mode, CArrStr tables int32_t FfiOHOSRelationalStoreGetVersion(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = -1; @@ -985,6 +1307,9 @@ int32_t FfiOHOSRelationalStoreGetVersion(int64_t id, int32_t *errCode) void FfiOHOSRelationalStoreSetVersion(int64_t id, int32_t value, int32_t *errCode) { + if (errCode == nullptr) { + return; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = -1; @@ -996,6 +1321,9 @@ void FfiOHOSRelationalStoreSetVersion(int64_t id, int32_t value, int32_t *errCod ModifyTime FfiOHOSRelationalStoreGetModifyTime( int64_t id, char *cTable, char *cColumnName, CArrPRIKeyType cPrimaryKeys, int32_t *errCode) { + if (errCode == nullptr) { + return ModifyTime{ 0 }; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = -1; @@ -1003,6 +1331,39 @@ ModifyTime FfiOHOSRelationalStoreGetModifyTime( } return nativeRdbStore->GetModifyTime(cTable, cColumnName, cPrimaryKeys, *errCode); } + +FFI_EXPORT int32_t FfiOHOSRelationalStoreRdbPredicatesNotContains(int64_t id, const char *field, const char *value) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->NotContains(field, value); + return 0; +} + +FFI_EXPORT int32_t FfiOHOSRelationalStoreRdbPredicatesNotLike(int64_t id, const char *field, const char *value) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->NotLike(field, value); + return 0; +} + +FFI_EXPORT int32_t FfiOHOSRelationalStoreRdbStoreGetRebuilt(int64_t id, int32_t *errCode) +{ + if (errCode == nullptr) { + return -1; + } + auto nativeRdbStore = FFIData::GetData(id); + if (nativeRdbStore == nullptr) { + *errCode = -1; + return 0; + } + return nativeRdbStore->GetRebuilt(); +} } } // namespace Relational } // namespace OHOS diff --git a/relational_store/frameworks/cj/src/relational_store_impl_rdbpredicatesproxy.cpp b/relational_store/frameworks/cj/src/relational_store_impl_rdbpredicatesproxy.cpp index eefe118d4ed46d8cda87ffe40b7fc5ab0d781fdf..a16988f623694d33aaa3216953fde7ce38e7ca6f 100644 --- a/relational_store/frameworks/cj/src/relational_store_impl_rdbpredicatesproxy.cpp +++ b/relational_store/frameworks/cj/src/relational_store_impl_rdbpredicatesproxy.cpp @@ -20,6 +20,9 @@ namespace OHOS { namespace Relational { RdbPredicatesImpl::RdbPredicatesImpl(const char* tableName) { + if (tableName == nullptr) { + return; + } std::string str = tableName; predicates_ = std::make_shared(str); } @@ -47,36 +50,57 @@ namespace Relational { for (int64_t i = 0; i < devicesSize; i++) { devices.push_back(devicesArray[i]); } + if (predicates_ == nullptr) { + return; + } predicates_->InDevices(devices); } void RdbPredicatesImpl::InAllDevices() { + if (predicates_ == nullptr) { + return; + } predicates_->InAllDevices(); } void RdbPredicatesImpl::BeginWrap() { + if (predicates_ == nullptr) { + return; + } predicates_->BeginWrap(); } void RdbPredicatesImpl::EndWrap() { + if (predicates_ == nullptr) { + return; + } predicates_->EndWrap(); } void RdbPredicatesImpl::Or() { + if (predicates_ == nullptr) { + return; + } predicates_->Or(); } void RdbPredicatesImpl::And() { + if (predicates_ == nullptr) { + return; + } predicates_->And(); } void RdbPredicatesImpl::Contains(const char* field, const char* value) { + if (field == nullptr || value == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; std::string cvalue = value; predicates_->Contains(cfield, cvalue); @@ -84,6 +108,9 @@ namespace Relational { void RdbPredicatesImpl::BeginsWith(const char* field, const char* value) { + if (field == nullptr || value == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; std::string cvalue = value; predicates_->BeginsWith(cfield, cvalue); @@ -91,6 +118,9 @@ namespace Relational { void RdbPredicatesImpl::EndsWith(const char* field, const char* value) { + if (field == nullptr || value == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; std::string cvalue = value; predicates_->EndsWith(cfield, cvalue); @@ -98,18 +128,27 @@ namespace Relational { void RdbPredicatesImpl::IsNull(const char* field) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; predicates_->IsNull(cfield); } void RdbPredicatesImpl::IsNotNull(const char* field) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; predicates_->IsNotNull(cfield); } void RdbPredicatesImpl::Like(const char* field, const char* value) { + if (field == nullptr || value == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; std::string cvalue = value; predicates_->Like(cfield, cvalue); @@ -117,6 +156,9 @@ namespace Relational { void RdbPredicatesImpl::Glob(const char* field, const char* value) { + if (field == nullptr || value == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; std::string cvalue = value; predicates_->Glob(cfield, cvalue); @@ -124,35 +166,56 @@ namespace Relational { void RdbPredicatesImpl::OrderByAsc(const char* field) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; predicates_->OrderByAsc(cfield); } void RdbPredicatesImpl::OrderByDesc(const char* field) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; predicates_->OrderByDesc(cfield); } void RdbPredicatesImpl::Distinct() { + if (predicates_ == nullptr) { + return; + } predicates_->Distinct(); } void RdbPredicatesImpl::LimitAs(int32_t value) { + if (predicates_ == nullptr) { + return; + } predicates_->Limit(value); } void RdbPredicatesImpl::OffsetAs(int32_t rowOffset) { + if (predicates_ == nullptr) { + return; + } predicates_->Offset(rowOffset); } void RdbPredicatesImpl::GroupBy(const char** fieldsArray, int64_t fieldsSize) { + if (fieldsArray == nullptr || predicates_ == nullptr) { + return; + } std::vector fields; for (int64_t i = 0; i < fieldsSize; i++) { + if (fieldsArray[i] == nullptr) { + return; + } fields.push_back(fieldsArray[i]); } predicates_->GroupBy(fields); @@ -160,63 +223,162 @@ namespace Relational { void RdbPredicatesImpl::IndexedBy(const char* field) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; predicates_->IndexedBy(cfield); } void RdbPredicatesImpl::LessThanOrEqualTo(const char* field, ValueType value) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; NativeRdb::ValueObject valueObject = ValueTypeToValueObject(value); predicates_->LessThanOrEqualTo(cfield, valueObject); } + void RdbPredicatesImpl::LessThanOrEqualToEx(const char* field, const ValueTypeEx *value) + { + if (field == nullptr || value == nullptr || predicates_ == nullptr) { + return; + } + std::string cfield = field; + NativeRdb::ValueObject valueObject = ValueTypeExToValueObject(*value); + predicates_->LessThanOrEqualTo(cfield, valueObject); + } + void RdbPredicatesImpl::EqualTo(const char* field, ValueType value) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; NativeRdb::ValueObject valueObject = ValueTypeToValueObject(value); predicates_->EqualTo(cfield, valueObject); } + + void RdbPredicatesImpl::EqualToEx(const char* field, const ValueTypeEx *value) + { + if (field == nullptr || predicates_ == nullptr || value == nullptr) { + return; + } + std::string cfield = field; + NativeRdb::ValueObject valueObject = ValueTypeExToValueObject(*value); + predicates_->EqualTo(cfield, valueObject); + } void RdbPredicatesImpl::GreaterThanOrEqualTo(const char* field, ValueType value) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; NativeRdb::ValueObject valueObject = ValueTypeToValueObject(value); predicates_->GreaterThanOrEqualTo(cfield, valueObject); } + void RdbPredicatesImpl::GreaterThanOrEqualToEx(const char* field, const ValueTypeEx *value) + { + if (field == nullptr || predicates_ == nullptr || value == nullptr) { + return; + } + std::string cfield = field; + NativeRdb::ValueObject valueObject = ValueTypeExToValueObject(*value); + predicates_->GreaterThanOrEqualTo(cfield, valueObject); + } + void RdbPredicatesImpl::GreaterThan(const char* field, ValueType value) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; NativeRdb::ValueObject valueObject = ValueTypeToValueObject(value); predicates_->GreaterThan(cfield, valueObject); } + void RdbPredicatesImpl::GreaterThanEx(const char* field, const ValueTypeEx *value) + { + if (field == nullptr || predicates_ == nullptr || value == nullptr) { + return; + } + std::string cfield = field; + NativeRdb::ValueObject valueObject = ValueTypeExToValueObject(*value); + predicates_->GreaterThan(cfield, valueObject); + } + void RdbPredicatesImpl::NotBetween(const char* field, ValueType lowValue, ValueType highValue) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; NativeRdb::ValueObject lowValueObject = ValueTypeToValueObject(lowValue); NativeRdb::ValueObject highValueObject = ValueTypeToValueObject(highValue); predicates_->NotBetween(cfield, lowValueObject, highValueObject); } + void RdbPredicatesImpl::NotBetweenEx(const char* field, const ValueTypeEx *lowValue, const ValueTypeEx *highValue) + { + if (field == nullptr || predicates_ == nullptr || lowValue == nullptr || highValue == nullptr) { + return; + } + std::string cfield = field; + NativeRdb::ValueObject lowValueObject = ValueTypeExToValueObject(*lowValue); + NativeRdb::ValueObject highValueObject = ValueTypeExToValueObject(*highValue); + predicates_->NotBetween(cfield, lowValueObject, highValueObject); + } + void RdbPredicatesImpl::Between(const char* field, ValueType lowValue, ValueType highValue) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; NativeRdb::ValueObject lowValueObject = ValueTypeToValueObject(lowValue); NativeRdb::ValueObject highValueObject = ValueTypeToValueObject(highValue); predicates_->Between(cfield, lowValueObject, highValueObject); } + void RdbPredicatesImpl::BetweenEx(const char* field, const ValueTypeEx *lowValue, const ValueTypeEx *highValue) + { + if (field == nullptr || predicates_ == nullptr || lowValue == nullptr || highValue == nullptr) { + return; + } + std::string cfield = field; + NativeRdb::ValueObject lowValueObject = ValueTypeExToValueObject(*lowValue); + NativeRdb::ValueObject highValueObject = ValueTypeExToValueObject(*highValue); + predicates_->Between(cfield, lowValueObject, highValueObject); + } + void RdbPredicatesImpl::LessThan(const char* field, ValueType value) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; NativeRdb::ValueObject valueObject = ValueTypeToValueObject(value); predicates_->LessThan(cfield, valueObject); } + void RdbPredicatesImpl::LessThanEx(const char *field, const ValueTypeEx *value) + { + if (field == nullptr || predicates_ == nullptr || value == nullptr) { + return; + } + std::string cfield = field; + NativeRdb::ValueObject valueObject = ValueTypeExToValueObject(*value); + predicates_->LessThan(cfield, valueObject); + } + void RdbPredicatesImpl::In(const char* field, ValueType* values, int64_t valuesSize) { + if (field == nullptr || predicates_ == nullptr || values == nullptr) { + return; + } std::string cfield = field; std::vector valueObjects = std::vector(); for (int64_t i = 0; i < valuesSize; i++) { @@ -225,8 +387,24 @@ namespace Relational { predicates_->In(cfield, valueObjects); } + void RdbPredicatesImpl::InEx(const char* field, ValueTypeEx* values, int64_t valuesSize) + { + if (field == nullptr || predicates_ == nullptr || values == nullptr) { + return; + } + std::string cfield = field; + std::vector valueObjects = std::vector(); + for (int64_t i = 0; i < valuesSize; i++) { + valueObjects.push_back(ValueTypeExToValueObject(values[i])); + } + predicates_->In(cfield, valueObjects); + } + void RdbPredicatesImpl::NotIn(const char* field, ValueType* values, int64_t valuesSize) { + if (field == nullptr || predicates_ == nullptr || values == nullptr) { + return; + } std::string cfield = field; std::vector valueObjects = std::vector(); for (int64_t i = 0; i < valuesSize; i++) { @@ -235,11 +413,57 @@ namespace Relational { predicates_->NotIn(cfield, valueObjects); } + void RdbPredicatesImpl::NotInEx(const char* field, ValueTypeEx* values, int64_t valuesSize) + { + if (field == nullptr || predicates_ == nullptr || values == nullptr) { + return; + } + std::string cfield = field; + std::vector valueObjects = std::vector(); + for (int64_t i = 0; i < valuesSize; i++) { + valueObjects.push_back(ValueTypeExToValueObject(values[i])); + } + predicates_->NotIn(cfield, valueObjects); + } + void RdbPredicatesImpl::NotEqualTo(const char* field, ValueType value) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; NativeRdb::ValueObject valueObject = ValueTypeToValueObject(value); predicates_->NotEqualTo(cfield, valueObject); } + + void RdbPredicatesImpl::NotEqualToEx(const char* field, const ValueTypeEx *value) + { + if (field == nullptr || predicates_ == nullptr || value == nullptr) { + return; + } + std::string cfield = field; + NativeRdb::ValueObject valueObject = ValueTypeExToValueObject(*value); + predicates_->NotEqualTo(cfield, valueObject); + } + + void RdbPredicatesImpl::NotContains(const char* field, const char* value) + { + if (field == nullptr || predicates_ == nullptr || value == nullptr) { + return; + } + std::string cfield = field; + std::string cvalue = value; + predicates_->NotContains(cfield, cvalue); + } + + void RdbPredicatesImpl::NotLike(const char* field, const char* value) + { + if (field == nullptr || predicates_ == nullptr || value == nullptr) { + return; + } + std::string cfield = field; + std::string cvalue = value; + predicates_->NotLike(field, value); + } } } \ No newline at end of file diff --git a/relational_store/frameworks/cj/src/relational_store_impl_rdbstore.cpp b/relational_store/frameworks/cj/src/relational_store_impl_rdbstore.cpp index 44af5f03bb5bd9fa1e0cc9ff60e701536e2b556d..5a3e44c86d7070aee944a465bed769ca5b8503dd 100644 --- a/relational_store/frameworks/cj/src/relational_store_impl_rdbstore.cpp +++ b/relational_store/frameworks/cj/src/relational_store_impl_rdbstore.cpp @@ -31,7 +31,6 @@ #include "rdb_common.h" #include "native_log.h" #include "relational_store_impl_rdbstore.h" -#include "js_utils.h" #ifndef PATH_SPLIT #define PATH_SPLIT '/' @@ -108,8 +107,33 @@ namespace Relational { int64_t mapSize = valuesBucket.size; NativeRdb::ValuesBucket nativeValuesBucket = NativeRdb::ValuesBucket(); + if (valuesBucket.value == nullptr || valuesBucket.key == nullptr) { + return nativeValuesBucket; + } for (int64_t i = 0; i < mapSize; i++) { NativeRdb::ValueObject valueObject = ValueTypeToValueObject(valuesBucket.value[i]); + if (valuesBucket.key[i] == nullptr) { + return nativeValuesBucket; + } + std::string keyStr = valuesBucket.key[i]; + nativeValuesBucket.Put(keyStr, valueObject); + } + return nativeValuesBucket; + } + + NativeRdb::ValuesBucket ConvertFromValueBucketEx(ValuesBucketEx valuesBucket) + { + int64_t mapSize = valuesBucket.size; + NativeRdb::ValuesBucket nativeValuesBucket = NativeRdb::ValuesBucket(); + + if (valuesBucket.value == nullptr || valuesBucket.key == nullptr) { + return nativeValuesBucket; + } + for (int64_t i = 0; i < mapSize; i++) { + NativeRdb::ValueObject valueObject = ValueTypeExToValueObject(valuesBucket.value[i]); + if (valuesBucket.key[i] == nullptr) { + return nativeValuesBucket; + } std::string keyStr = valuesBucket.key[i]; nativeValuesBucket.Put(keyStr, valueObject); } @@ -119,8 +143,14 @@ namespace Relational { std::shared_ptr RdbStoreImpl::Query(RdbPredicatesImpl &predicates, char** column, int64_t columnSize) { + if (column == nullptr) { + return nullptr; + } std::vector columnsVector = std::vector(); for (int64_t i = 0; i < columnSize; i++) { + if (column[i] == nullptr) { + return nullptr; + } columnsVector.push_back(std::string(column[i])); } auto resultSet = rdbStore_->Query(*(predicates.GetPredicates()), columnsVector); @@ -130,11 +160,20 @@ namespace Relational { std::shared_ptr RdbStoreImpl::RemoteQuery(char* device, RdbPredicatesImpl &predicates, char** column, int64_t columnSize) { + if (column == nullptr) { + return nullptr; + } std::vector columnsVector; for (int64_t i = 0; i < columnSize; i++) { + if (column[i] == nullptr) { + return nullptr; + } columnsVector.push_back(std::string(column[i])); } int32_t errCode; + if (predicates.GetPredicates() == nullptr) { + return nullptr; + } auto resultSet = rdbStore_->RemoteQuery(std::string(device), *(predicates.GetPredicates()), columnsVector, errCode); return resultSet; @@ -143,6 +182,9 @@ namespace Relational { int32_t RdbStoreImpl::Update(ValuesBucket valuesBucket, RdbPredicatesImpl &predicates, NativeRdb::ConflictResolution conflictResolution, int32_t *errCode) { + if (errCode == nullptr || rdbStore_ == nullptr || predicates.GetPredicates() == nullptr) { + return -1; + } int32_t affectedRows; NativeRdb::ValuesBucket nativeValuesBucket = ConvertFromValueBucket(valuesBucket); *errCode = rdbStore_->UpdateWithConflictResolution(affectedRows, predicates.GetPredicates()->GetTableName(), @@ -151,8 +193,25 @@ namespace Relational { return affectedRows; } + int32_t RdbStoreImpl::UpdateEx(ValuesBucketEx valuesBucket, RdbPredicatesImpl &predicates, + NativeRdb::ConflictResolution conflictResolution, int32_t *errCode) + { + if (errCode == nullptr || rdbStore_ == nullptr || predicates.GetPredicates() == nullptr) { + return -1; + } + int32_t affectedRows; + NativeRdb::ValuesBucket nativeValuesBucket = ConvertFromValueBucketEx(valuesBucket); + *errCode = rdbStore_->UpdateWithConflictResolution(affectedRows, predicates.GetPredicates()->GetTableName(), + nativeValuesBucket, predicates.GetPredicates()->GetWhereClause(), predicates.GetPredicates()->GetBindArgs(), + conflictResolution); + return affectedRows; + } + int RdbStoreImpl::Delete(RdbPredicatesImpl &predicates, int32_t *errCode) { + if (errCode == nullptr || rdbStore_ == nullptr || predicates.GetPredicates() == nullptr) { + return -1; + } int deletedRows = 0; *errCode = rdbStore_->Delete(deletedRows, *(predicates.GetPredicates())); return deletedRows; @@ -160,8 +219,14 @@ namespace Relational { int32_t RdbStoreImpl::SetDistributedTables(char** tables, int64_t tablesSize) { + if (tables == nullptr || rdbStore_ == nullptr) { + return -1; + } std::vector tablesVector; for (int64_t i = 0; i < tablesSize; i++) { + if (tables[i] == nullptr) { + return -1; + } tablesVector.push_back(std::string(tables[i])); } return rdbStore_->SetDistributedTables(tablesVector, DistributedRdb::DISTRIBUTED_DEVICE, @@ -170,8 +235,14 @@ namespace Relational { int32_t RdbStoreImpl::SetDistributedTables(char** tables, int64_t tablesSize, int32_t type) { + if (tables == nullptr || rdbStore_ == nullptr) { + return -1; + } std::vector tablesVector; for (int64_t i = 0; i < tablesSize; i++) { + if (tables[i] == nullptr) { + return -1; + } tablesVector.push_back(std::string(tables[i])); } return rdbStore_->SetDistributedTables(tablesVector, type, DistributedRdb::DistributedConfig{false}); @@ -180,8 +251,14 @@ namespace Relational { int32_t RdbStoreImpl::SetDistributedTables(char** tables, int64_t tablesSize, int32_t type, DistributedRdb::DistributedConfig &distributedConfig) { + if (tables == nullptr || rdbStore_ == nullptr) { + return -1; + } std::vector tablesVector; for (int64_t i = 0; i < tablesSize; i++) { + if (tables[i] == nullptr) { + return -1; + } tablesVector.push_back(std::string(tables[i])); } return rdbStore_->SetDistributedTables(tablesVector, type, distributedConfig); @@ -189,31 +266,49 @@ namespace Relational { int32_t RdbStoreImpl::RollBack() { + if (rdbStore_ == nullptr) { + return -1; + } return rdbStore_->RollBack(); } int32_t RdbStoreImpl::Commit() { + if (rdbStore_ == nullptr) { + return -1; + } return rdbStore_->Commit(); } int32_t RdbStoreImpl::BeginTransaction() { + if (rdbStore_ == nullptr) { + return -1; + } return rdbStore_->BeginTransaction(); } int32_t RdbStoreImpl::Backup(const char* destName) { + if (rdbStore_ == nullptr || destName == nullptr) { + return -1; + } return rdbStore_->Backup(destName, newKey); } int32_t RdbStoreImpl::Restore(const char* srcName) { + if (rdbStore_ == nullptr || srcName == nullptr) { + return -1; + } return rdbStore_->Restore(srcName, newKey); } char* RdbStoreImpl::ObtainDistributedTableName(const char* device, const char* table) { + if (rdbStore_ == nullptr || device == nullptr || table == nullptr) { + return nullptr; + } int errCode = RelationalStoreJsKit::E_INNER_ERROR; std::string tableName = rdbStore_->ObtainDistributedTableName(device, table, errCode); return MallocCString(tableName); @@ -221,11 +316,17 @@ namespace Relational { int32_t RdbStoreImpl::Emit(const char* event) { + if (rdbStore_ == nullptr || event == nullptr) { + return -1; + } return rdbStore_->Notify(event); } int64_t RdbStoreImpl::Insert(const char* table, ValuesBucket valuesBucket, int32_t conflict, int32_t *errCode) { + if (rdbStore_ == nullptr || table == nullptr || errCode == nullptr) { + return -1; + } std::string tableName = table; int64_t result; NativeRdb::ValuesBucket nativeValuesBucket = ConvertFromValueBucket(valuesBucket); @@ -234,14 +335,33 @@ namespace Relational { return result; } + int64_t RdbStoreImpl::InsertEx(const char* table, ValuesBucketEx valuesBucket, int32_t conflict, int32_t *errCode) + { + if (rdbStore_ == nullptr || table == nullptr || errCode == nullptr) { + return -1; + } + std::string tableName = table; + int64_t result; + NativeRdb::ValuesBucket nativeValuesBucket = ConvertFromValueBucketEx(valuesBucket); + *errCode = rdbStore_->InsertWithConflictResolution(result, tableName, + nativeValuesBucket, NativeRdb::ConflictResolution(conflict)); + return result; + } + void RdbStoreImpl::ExecuteSql(const char* sql, int32_t *errCode) { - *errCode = rdbStore_->ExecuteSql(sql, bindArgs); + if (rdbStore_ == nullptr || sql == nullptr || errCode == nullptr) { + return; + } + *errCode = rdbStore_->ExecuteSql(sql, std::vector()); } int32_t RdbStoreImpl::CleanDirtyData(const char* tableName, uint64_t cursor) { + if (rdbStore_ == nullptr || tableName == nullptr) { + return -1; + } int32_t rtnCode = rdbStore_->CleanDirtyData(tableName, cursor); return rtnCode; } @@ -249,6 +369,9 @@ namespace Relational { int32_t RdbStoreImpl::BatchInsert(int64_t &insertNum, const char* tableName, ValuesBucket* valuesBuckets, int64_t valuesSize) { + if (rdbStore_ == nullptr || tableName == nullptr || valuesBuckets == nullptr) { + return -1; + } std::vector valuesVector; std::string tableNameStr = tableName; if (tableNameStr.empty()) { @@ -262,14 +385,39 @@ namespace Relational { return rtnCode; } + int32_t RdbStoreImpl::BatchInsertEx(int64_t &insertNum, const char* tableName, ValuesBucketEx* valuesBuckets, + int64_t valuesSize) + { + if (rdbStore_ == nullptr || tableName == nullptr || valuesBuckets == nullptr) { + return -1; + } + std::vector valuesVector; + std::string tableNameStr = tableName; + if (tableNameStr.empty()) { + return RelationalStoreJsKit::E_PARAM_ERROR; + } + for (int64_t i = 0; i < valuesSize; i++) { + NativeRdb::ValuesBucket nativeValuesBucket = ConvertFromValueBucketEx(valuesBuckets[i]); + valuesVector.push_back(nativeValuesBucket); + } + int32_t rtnCode = rdbStore_->BatchInsert(insertNum, tableNameStr, valuesVector); + return rtnCode; + } + CArrSyncResult RdbStoreImpl::Sync(int32_t mode, RdbPredicatesImpl &predicates) { DistributedRdb::SyncOption option; option.mode = static_cast(mode); option.isBlock = true; DistributedRdb::SyncResult resMap; + if (rdbStore_ == nullptr) { + return CArrSyncResult{nullptr, nullptr, -1}; + } rdbStore_->Sync(option, *(predicates.GetPredicates()), [&resMap](const DistributedRdb::SyncResult &result) { resMap = result; }); + if (resMap.size() == 0) { + return CArrSyncResult{nullptr, nullptr, -1}; + } char** resultStr = static_cast(malloc(resMap.size() * sizeof(char*))); int32_t* resultNum = static_cast(malloc(resMap.size() * sizeof(int32_t))); if (resultStr == nullptr || resultNum == nullptr) { @@ -288,6 +436,9 @@ namespace Relational { std::shared_ptr RdbStoreImpl::QuerySql(const char *sql, ValueType *bindArgs, int64_t size) { + if (sql == nullptr || bindArgs == nullptr || rdbStore_ == nullptr) { + return nullptr; + } std::string tmpSql = sql; std::vector tmpBindArgs = std::vector(); for (int64_t i = 0; i < size; i++) { @@ -297,8 +448,25 @@ namespace Relational { return result; } + std::shared_ptr RdbStoreImpl::QuerySqlEx(const char *sql, ValueTypeEx *bindArgs, int64_t size) + { + if (sql == nullptr || bindArgs == nullptr || rdbStore_ == nullptr) { + return nullptr; + } + std::string tmpSql = sql; + std::vector tmpBindArgs = std::vector(); + for (int64_t i = 0; i < size; i++) { + tmpBindArgs.push_back(ValueTypeExToValueObject(bindArgs[i])); + } + auto result = rdbStore_->QueryByStep(tmpSql, tmpBindArgs); + return result; + } + void RdbStoreImpl::ExecuteSql(const char* sql, ValueType* bindArgs, int64_t bindArgsSize, int32_t *errCode) { + if (sql == nullptr || bindArgs == nullptr || rdbStore_ == nullptr || errCode == nullptr) { + return; + } std::vector bindArgsObjects = std::vector(); for (int64_t i = 0; i < bindArgsSize; i++) { bindArgsObjects.push_back(ValueTypeToValueObject(bindArgs[i])); @@ -306,7 +474,19 @@ namespace Relational { *errCode = rdbStore_->ExecuteSql(sql, bindArgsObjects); } - int32_t RdbStoreImpl::RegisterObserver(const char *event, bool interProcess, std::function *callback, + void RdbStoreImpl::ExecuteSqlEx(const char* sql, ValueTypeEx* bindArgs, int64_t bindArgsSize, int32_t *errCode) + { + if (sql == nullptr || bindArgs == nullptr || rdbStore_ == nullptr || errCode == nullptr) { + return; + } + std::vector bindArgsObjects = std::vector(); + for (int64_t i = 0; i < bindArgsSize; i++) { + bindArgsObjects.push_back(ValueTypeExToValueObject(bindArgs[i])); + } + *errCode = rdbStore_->ExecuteSql(sql, bindArgsObjects); + } + + int32_t RdbStoreImpl::RegisterObserver(const char *event, bool interProcess, int64_t callback, const std::function& callbackRef) { DistributedRdb::SubscribeOption option; @@ -319,16 +499,19 @@ namespace Relational { return RegisteredObserver(option, localSharedObservers_, callback, callbackRef); } - bool isSameFunction(const std::function *f1, const std::function *f2) + bool isSameFunction(int64_t f1, int64_t f2) { return f1 == f2; } bool RdbStoreImpl::HasRegisteredObserver( - std::function *callback, + int64_t callback, std::list> &observers) { for (auto &it : observers) { + if (it == nullptr) { + return false; + } if (isSameFunction(callback, it->GetCallBack())) { return true; } @@ -336,14 +519,14 @@ namespace Relational { return false; } - RdbStoreObserverImpl::RdbStoreObserverImpl(std::function *callback, + RdbStoreObserverImpl::RdbStoreObserverImpl(int64_t callback, const std::function& callbackRef) { m_callback = callback; m_callbackRef = callbackRef; } - std::function *RdbStoreObserverImpl::GetCallBack() + int64_t RdbStoreObserverImpl::GetCallBack() { return m_callback; } @@ -351,12 +534,15 @@ namespace Relational { int32_t RdbStoreImpl::RegisteredObserver( DistributedRdb::SubscribeOption option, std::map>> &observers, - std::function *callback, const std::function& callbackRef) + int64_t callback, const std::function& callbackRef) { observers.try_emplace(option.event); if (!HasRegisteredObserver(callback, observers[option.event])) { auto localObserver = std::make_shared(callback, callbackRef); - int32_t errCode = rdbStore_->Subscribe(option, localObserver.get()); + if (rdbStore_ == nullptr) { + return -1; + } + int32_t errCode = rdbStore_->Subscribe(option, localObserver); if (errCode != NativeRdb::E_OK) { return errCode; } @@ -376,10 +562,13 @@ namespace Relational { option.event = "dataChange"; auto observer = std::make_shared(callbackId, RdbStoreObserverImpl::ParamArrStr, mode); int32_t errCode = NativeRdb::E_OK; + if (rdbStore_ == nullptr) { + return -1; + } if (option.mode == DistributedRdb::SubscribeMode::LOCAL_DETAIL) { errCode = rdbStore_->SubscribeObserver(option, observer); } else { - errCode = rdbStore_->Subscribe(option, observer.get()); + errCode = rdbStore_->Subscribe(option, observer); } if (errCode == NativeRdb::E_OK) { observers_[mode].push_back(observer); @@ -396,10 +585,13 @@ namespace Relational { option.event = "dataChange"; auto observer = std::make_shared(callbackId, RdbStoreObserverImpl::ParamChangeInfo, mode); int32_t errCode = NativeRdb::E_OK; + if (rdbStore_ == nullptr) { + return -1; + } if (option.mode == DistributedRdb::SubscribeMode::LOCAL_DETAIL) { errCode = rdbStore_->SubscribeObserver(option, observer); } else { - errCode = rdbStore_->Subscribe(option, observer.get()); + errCode = rdbStore_->Subscribe(option, observer); } if (errCode == NativeRdb::E_OK) { observers_[mode].push_back(observer); @@ -411,6 +603,9 @@ namespace Relational { int32_t RdbStoreImpl::RegisterObserverProgressDetails(int64_t callbackId) { auto observer = std::make_shared(callbackId); + if (rdbStore_ == nullptr) { + return -1; + } int errCode = rdbStore_->RegisterAutoSyncCallback(observer); if (errCode == NativeRdb::E_OK) { syncObservers_.push_back(observer); @@ -419,7 +614,7 @@ namespace Relational { return errCode; } - int32_t RdbStoreImpl::UnRegisterObserver(const char *event, bool interProcess, std::function *callback) + int32_t RdbStoreImpl::UnRegisterObserver(const char *event, bool interProcess, int64_t callback) { DistributedRdb::SubscribeOption option; option.event = event; @@ -433,7 +628,7 @@ namespace Relational { int32_t RdbStoreImpl::UnRegisteredObserver(DistributedRdb::SubscribeOption option, std::map>> &observers, - std::function *callback) + int64_t callback) { auto obs = observers.find(option.event); if (obs == observers.end()) { @@ -444,7 +639,7 @@ namespace Relational { auto &list = obs->second; for (auto it = list.begin(); it != list.end(); it++) { if (isSameFunction(callback, (*it)->GetCallBack())) { - int errCode = rdbStore_->UnSubscribe(option, it->get()); + int errCode = rdbStore_->UnSubscribe(option, *it); if (errCode != RelationalStoreJsKit::OK) { return errCode; } @@ -462,6 +657,9 @@ namespace Relational { int32_t RdbStoreImpl::UnRegisterAllObserver(const char *event, bool interProcess) { DistributedRdb::SubscribeOption option; + if (event == nullptr) { + return -1; + } option.event = event; interProcess ? option.mode = DistributedRdb::SubscribeMode::LOCAL_SHARED : option.mode = DistributedRdb::SubscribeMode::LOCAL; @@ -505,10 +703,13 @@ namespace Relational { continue; } int errCode = NativeRdb::E_OK; + if (rdbStore_ == nullptr) { + return -1; + } if (option.mode == DistributedRdb::SubscribeMode::LOCAL_DETAIL) { errCode = rdbStore_->UnsubscribeObserver(option, *it); } else { - errCode = rdbStore_->UnSubscribe(option, it->get()); + errCode = rdbStore_->UnSubscribe(option, *it); } if (errCode != NativeRdb::E_OK) { return errCode; @@ -530,10 +731,13 @@ namespace Relational { continue; } int errCode = NativeRdb::E_OK; + if (rdbStore_ == nullptr) { + return -1; + } if (option.mode == DistributedRdb::SubscribeMode::LOCAL_DETAIL) { errCode = rdbStore_->UnsubscribeObserver(option, *it); } else { - errCode = rdbStore_->UnSubscribe(option, it->get()); + errCode = rdbStore_->UnSubscribe(option, *it); } if (errCode != NativeRdb::E_OK) { return errCode; @@ -555,6 +759,9 @@ namespace Relational { continue; } + if (rdbStore_ == nullptr) { + return -1; + } int32_t errCode = rdbStore_->UnregisterAutoSyncCallback(*it); if (errCode != NativeRdb::E_OK) { return errCode; @@ -571,6 +778,9 @@ namespace Relational { it = syncObservers_.erase(it); continue; } + if (rdbStore_ == nullptr) { + return -1; + } int32_t errCode = rdbStore_->UnregisterAutoSyncCallback(*it); if (errCode != NativeRdb::E_OK) { return errCode; @@ -589,6 +799,9 @@ namespace Relational { auto cFunc = reinterpret_cast(callbackId); auto async = [ lambda = CJLambda::Create(cFunc)](const DistributedRdb::Details &details) -> void { lambda(ToCProgressDetails(details)); }; + if (rdbStore_ == nullptr) { + return -1; + } int32_t errCode = rdbStore_->Sync(option, arr, async); return errCode; } @@ -596,12 +809,18 @@ namespace Relational { int32_t RdbStoreImpl::GetVersion(int32_t& errCode) { int32_t version = 0; + if (rdbStore_ == nullptr) { + return -1; + } errCode = rdbStore_->GetVersion(version); return version; } void RdbStoreImpl::SetVersion(int32_t value, int32_t &errCode) { + if (rdbStore_ == nullptr) { + return; + } errCode = rdbStore_->SetVersion(value); } @@ -611,6 +830,9 @@ namespace Relational { std::string tableName = cTables; std::string columnName = cColumnName; std::vector keys = CArrPRIKeyTypeToPRIKeyArray(cPrimaryKeys); + if (rdbStore_ == nullptr) { + return ModifyTime{0}; + } std::map map = rdbStore_->GetModifyTime(tableName, columnName, keys); if (map.empty()) { @@ -620,6 +842,16 @@ namespace Relational { return MapToModifyTime(map, errCode); } + int32_t RdbStoreImpl::GetRebuilt() + { + auto rebuilt = NativeRdb::RebuiltType::NONE; + if (rdbStore_ == nullptr) { + return -1; + } + rdbStore_->GetRebuilt(rebuilt); + return static_cast(rebuilt); + } + int32_t GetRealPath(AppDataMgrJsKit::JSUtils::RdbConfig &rdbConfig, const AppDataMgrJsKit::JSUtils::ContextParam ¶m, std::shared_ptr abilitycontext) @@ -688,6 +920,25 @@ namespace Relational { rdbConfig.customDir = config.customDir; } + void initRdbConfigEx(AppDataMgrJsKit::JSUtils::RdbConfig &rdbConfig, const StoreConfigEx &config) + { + rdbConfig.isEncrypt = config.encrypt; + rdbConfig.isSearchable = config.isSearchable; + rdbConfig.isAutoClean = config.autoCleanDirtyData; + rdbConfig.securityLevel = static_cast(config.securityLevel); + rdbConfig.dataGroupId = config.dataGroupId; + rdbConfig.name = config.name; + rdbConfig.customDir = config.customDir; + rdbConfig.rootDir = config.rootDir; + rdbConfig.vector = config.vector; + rdbConfig.allowRebuild = config.allowRebuild; + rdbConfig.isReadOnly = config.isReadOnly; + rdbConfig.pluginLibs = CArrStrToVector(config.pluginLibs); + rdbConfig.cryptoParam = ToCCryptoParam(config.cryptoParam); + rdbConfig.tokenizer = static_cast(config.tokenizer); + rdbConfig.persist = config.persist; + } + NativeRdb::RdbStoreConfig getRdbStoreConfig(const AppDataMgrJsKit::JSUtils::RdbConfig &rdbConfig, const AppDataMgrJsKit::JSUtils::ContextParam ¶m) { @@ -710,9 +961,44 @@ namespace Relational { return rdbStoreConfig; } + NativeRdb::RdbStoreConfig getRdbStoreConfigEx(const AppDataMgrJsKit::JSUtils::RdbConfig &rdbConfig, + const AppDataMgrJsKit::JSUtils::ContextParam ¶m) + { + NativeRdb::RdbStoreConfig rdbStoreConfig(rdbConfig.path); + rdbStoreConfig.SetEncryptStatus(rdbConfig.isEncrypt); + rdbStoreConfig.SetSearchable(rdbConfig.isSearchable); + rdbStoreConfig.SetIsVector(rdbConfig.vector); + rdbStoreConfig.SetDBType(rdbConfig.vector ? NativeRdb::DB_VECTOR : NativeRdb::DB_SQLITE); + rdbStoreConfig.SetStorageMode(rdbConfig.persist ? NativeRdb::StorageMode::MODE_DISK : + NativeRdb::StorageMode::MODE_MEMORY); + rdbStoreConfig.SetAutoClean(rdbConfig.isAutoClean); + rdbStoreConfig.SetSecurityLevel(rdbConfig.securityLevel); + rdbStoreConfig.SetDataGroupId(rdbConfig.dataGroupId); + rdbStoreConfig.SetName(rdbConfig.name); + rdbStoreConfig.SetCustomDir(rdbConfig.customDir); + rdbStoreConfig.SetAllowRebuild(rdbConfig.allowRebuild); + rdbStoreConfig.SetReadOnly(rdbConfig.isReadOnly); + rdbStoreConfig.SetIntegrityCheck(NativeRdb::IntegrityCheck::NONE); + rdbStoreConfig.SetTokenizer(rdbConfig.tokenizer); + + if (!param.bundleName.empty()) { + rdbStoreConfig.SetBundleName(param.bundleName); + } + rdbStoreConfig.SetModuleName(param.moduleName); + rdbStoreConfig.SetArea(param.area); + rdbStoreConfig.SetPluginLibs(rdbConfig.pluginLibs); + rdbStoreConfig.SetHaMode(rdbConfig.haMode); + + rdbStoreConfig.SetCryptoParam(rdbConfig.cryptoParam); + return rdbStoreConfig; + } + int64_t GetRdbStore(OHOS::AbilityRuntime::Context* context, StoreConfig config, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } if (context == nullptr) { *errCode = -1; return -1; @@ -742,9 +1028,51 @@ namespace Relational { return nativeRdbStore->GetID(); } + int64_t GetRdbStoreEx(OHOS::AbilityRuntime::Context* context, const StoreConfigEx *config, + int32_t *errCode) + { + if (errCode == nullptr) { + return -1; + } + if (context == nullptr) { + *errCode = ERROR_VALUE; + return ERROR_VALUE; + } + auto abilitycontext = std::make_shared(context->shared_from_this()); + AppDataMgrJsKit::JSUtils::ContextParam param; + initContextParam(param, abilitycontext); + AppDataMgrJsKit::JSUtils::RdbConfig rdbConfig; + initRdbConfigEx(rdbConfig, *config); + if (!rdbConfig.cryptoParam.IsValid()) { + *errCode = RelationalStoreJsKit::E_PARAM_ERROR; + return ERROR_VALUE; + } + + *errCode = GetRealPath(rdbConfig, param, abilitycontext); + if (*errCode != NativeRdb::E_OK) { + return ERROR_VALUE; + } + + DefaultOpenCallback callback; + auto rdbStore = + NativeRdb::RdbHelper::GetRdbStore(getRdbStoreConfigEx(rdbConfig, param), -1, callback, *errCode); + if (*errCode != 0) { + return ERROR_VALUE; + } + auto nativeRdbStore = FFIData::Create(rdbStore); + if (nativeRdbStore == nullptr) { + *errCode = ERROR_VALUE; + return ERROR_VALUE; + } + return nativeRdbStore->GetID(); + } + void DeleteRdbStore(OHOS::AbilityRuntime::Context* context, const char* name, int32_t *errCode) { + if (errCode == nullptr) { + return; + } if (context == nullptr) { *errCode = -1; return; @@ -759,15 +1087,16 @@ namespace Relational { if (*errCode != NativeRdb::E_OK) { return; } - // If the API version is greater than or equal to 20, close the connection. - bool isClose = (AppDataMgrJsKit::JSUtils::GetHapVersion() >= 20); - *errCode = NativeRdb::RdbHelper::DeleteRdbStore(rdbConfig.path, isClose); + *errCode = NativeRdb::RdbHelper::DeleteRdbStore(rdbConfig.path, false); return; } void DeleteRdbStoreConfig(OHOS::AbilityRuntime::Context* context, StoreConfig config, int32_t *errCode) { + if (errCode == nullptr) { + return; + } if (context == nullptr) { *errCode = -1; return; @@ -782,9 +1111,31 @@ namespace Relational { if (*errCode != NativeRdb::E_OK) { return; } - // If the API version is greater than or equal to 20, close the connection. - bool isClose = (AppDataMgrJsKit::JSUtils::GetHapVersion() >= 20); - *errCode = NativeRdb::RdbHelper::DeleteRdbStore(rdbConfig.path, isClose); + *errCode = NativeRdb::RdbHelper::DeleteRdbStore(rdbConfig.path, false); + return; + } + + void DeleteRdbStoreConfigEx(OHOS::AbilityRuntime::Context* context, const StoreConfigEx *config, + int32_t *errCode) + { + if (errCode == nullptr) { + return; + } + if (context == nullptr || config == nullptr) { + *errCode = ERROR_VALUE; + return; + } + auto abilitycontext = std::make_shared(context->shared_from_this()); + AppDataMgrJsKit::JSUtils::ContextParam param; + initContextParam(param, abilitycontext); + AppDataMgrJsKit::JSUtils::RdbConfig rdbConfig; + initRdbConfigEx(rdbConfig, *config); + + *errCode = GetRealPath(rdbConfig, param, abilitycontext); + if (*errCode != NativeRdb::E_OK) { + return; + } + *errCode = NativeRdb::RdbHelper::DeleteRdbStore(rdbConfig.path, false); return; } } diff --git a/relational_store/frameworks/cj/src/relational_store_impl_resultsetproxy.cpp b/relational_store/frameworks/cj/src/relational_store_impl_resultsetproxy.cpp index 368d7937abee29c366143341f8c6f80f5bfbd121..531d0159bbd293cf7278333151e3f984ca786e47 100644 --- a/relational_store/frameworks/cj/src/relational_store_impl_resultsetproxy.cpp +++ b/relational_store/frameworks/cj/src/relational_store_impl_resultsetproxy.cpp @@ -39,6 +39,9 @@ namespace Relational { CArrStr ResultSetImpl::GetAllColumnNames() { std::vector colNames; + if (resultSetValue == nullptr) { + return CArrStr{nullptr, 0}; + } int errCode = resultSetValue->GetAllColumnNames(colNames); if (errCode != RelationalStoreJsKit::OK) { LOGE("GetAllColumnNames failed code: %{public}d", errCode); @@ -67,6 +70,9 @@ namespace Relational { int32_t ResultSetImpl::GetColumnCount() { int32_t count = 0; + if (resultSetValue == nullptr) { + return count; + } int errCode = resultSetValue->GetColumnCount(count); if (errCode != RelationalStoreJsKit::OK) { LOGE("GetColumnCount failed code:%{public}d", errCode); @@ -77,6 +83,9 @@ namespace Relational { int32_t ResultSetImpl::GetRowCount() { int32_t result; + if (resultSetValue == nullptr) { + return -1; + } int errCode = resultSetValue->GetRowCount(result); if (errCode != RelationalStoreJsKit::OK) { LOGE("GetRowCount failed code:%{public}d", errCode); @@ -87,6 +96,9 @@ namespace Relational { int32_t ResultSetImpl::GetRowIndex() { int32_t result; + if (resultSetValue == nullptr) { + return -1; + } int errCode = resultSetValue->GetRowIndex(result); if (errCode != RelationalStoreJsKit::OK) { LOGE("GetRowIndex failed code:%{public}d", errCode); @@ -97,6 +109,9 @@ namespace Relational { bool ResultSetImpl::IsAtFirstRow() { bool result = false; + if (resultSetValue == nullptr) { + return result; + } int errCode = resultSetValue->IsAtFirstRow(result); if (errCode != RelationalStoreJsKit::OK) { LOGE("IsAtFirstRow failed code:%{public}d", errCode); @@ -107,6 +122,9 @@ namespace Relational { bool ResultSetImpl::IsAtLastRow() { bool result = false; + if (resultSetValue == nullptr) { + return result; + } int errCode = resultSetValue->IsAtLastRow(result); if (errCode != RelationalStoreJsKit::OK) { LOGE("IsAtLastRow failed code:%{public}d", errCode); @@ -117,6 +135,9 @@ namespace Relational { bool ResultSetImpl::IsEnded() { bool result = false; + if (resultSetValue == nullptr) { + return result; + } int errCode = resultSetValue->IsEnded(result); if (errCode != RelationalStoreJsKit::OK) { LOGE("IsEnded failed code:%{public}d", errCode); @@ -128,6 +149,9 @@ namespace Relational { bool ResultSetImpl::IsStarted() { bool result = false; + if (resultSetValue == nullptr) { + return result; + } int errCode = resultSetValue->IsStarted(result); if (errCode != RelationalStoreJsKit::OK) { LOGE("IsBegin failed code:%{public}d", errCode); @@ -137,30 +161,45 @@ namespace Relational { bool ResultSetImpl::IsClosed() { + if (resultSetValue == nullptr) { + return false; + } return resultSetValue->IsClosed(); } double ResultSetImpl::GetDouble(int32_t columnIndex, int32_t* rtnCode) { double result = 0.0; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return result; + } *rtnCode = resultSetValue->GetDouble(columnIndex, result); return result; } bool ResultSetImpl::GoToRow(int32_t position, int32_t* rtnCode) { + if (resultSetValue == nullptr || rtnCode == nullptr) { + return false; + } *rtnCode = resultSetValue->GoToRow(position); return *rtnCode == RelationalStoreJsKit::OK; } bool ResultSetImpl::GoToPreviousRow(int32_t* rtnCode) { + if (resultSetValue == nullptr || rtnCode == nullptr) { + return false; + } *rtnCode = resultSetValue->GoToPreviousRow(); return *rtnCode == RelationalStoreJsKit::OK; } bool ResultSetImpl::GoToLastRow(int32_t* rtnCode) { + if (resultSetValue == nullptr || rtnCode == nullptr) { + return false; + } *rtnCode = resultSetValue->GoToLastRow(); return *rtnCode == RelationalStoreJsKit::OK; } @@ -168,6 +207,9 @@ namespace Relational { char* ResultSetImpl::GetColumnName(int32_t columnIndex, int32_t* rtnCode) { std::string result; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return nullptr; + } *rtnCode = resultSetValue->GetColumnName(columnIndex, result); if (*rtnCode != RelationalStoreJsKit::OK) { LOGE("IsAtLastRow failed code:%{public}d", *rtnCode); @@ -178,6 +220,9 @@ namespace Relational { bool ResultSetImpl::IsColumnNull(int32_t columnIndex, int32_t* rtnCode) { bool result; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return false; + } *rtnCode = resultSetValue->IsColumnNull(columnIndex, result); return result; } @@ -185,6 +230,9 @@ namespace Relational { Asset ResultSetImpl::GetAsset(int32_t columnIndex, int32_t* rtnCode) { NativeRdb::ValueObject::Asset asset; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return Asset{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, 0}; + } *rtnCode = resultSetValue->GetAsset(columnIndex, asset); if (*rtnCode != RelationalStoreJsKit::OK) { return Asset{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, 0}; @@ -203,12 +251,18 @@ namespace Relational { int32_t ResultSetImpl::Close() { + if (resultSetValue == nullptr) { + return -1; + } return resultSetValue->Close(); } int32_t ResultSetImpl::GetColumnIndex(char* columnName, int32_t* rtnCode) { int32_t result = -1; + if (resultSetValue == nullptr || rtnCode == nullptr || columnName == nullptr) { + return result; + } *rtnCode = resultSetValue->GetColumnIndex(columnName, result); // If the API version is less than 13, directly return. if (AppDataMgrJsKit::JSUtils::GetHapVersion() < 13 || (*rtnCode == NativeRdb::E_INVALID_ARGS)) { @@ -220,18 +274,27 @@ namespace Relational { char* ResultSetImpl::GetString(int32_t columnIndex, int32_t* rtnCode) { std::string result; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return nullptr; + } *rtnCode = resultSetValue->GetString(columnIndex, result); return MallocCString(result); } bool ResultSetImpl::GoToFirstRow(int32_t* rtnCode) { + if (resultSetValue == nullptr || rtnCode == nullptr) { + return false; + } *rtnCode = resultSetValue->GoToFirstRow(); return *rtnCode == RelationalStoreJsKit::OK; } int64_t ResultSetImpl::GetLong(int32_t columnIndex, int32_t* rtnCode) { + if (resultSetValue == nullptr || rtnCode == nullptr) { + return -1; + } int64_t result; *rtnCode = resultSetValue->GetLong(columnIndex, result); return result; @@ -239,6 +302,9 @@ namespace Relational { bool ResultSetImpl::GoToNextRow(int32_t* rtnCode) { + if (resultSetValue == nullptr || rtnCode == nullptr) { + return false; + } *rtnCode = resultSetValue->GoToNextRow(); return *rtnCode == RelationalStoreJsKit::OK; } @@ -246,6 +312,9 @@ namespace Relational { CArrUI8 ResultSetImpl::GetBlob(int32_t columnIndex, int32_t* rtnCode) { std::vector vec; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return CArrUI8{nullptr, 0}; + } *rtnCode = resultSetValue->GetBlob(columnIndex, vec); if (*rtnCode != RelationalStoreJsKit::OK || vec.size() == 0) { return CArrUI8{nullptr, 0}; @@ -262,6 +331,9 @@ namespace Relational { bool ResultSetImpl::GoTo(int32_t offset, int32_t* rtnCode) { + if (resultSetValue == nullptr || rtnCode == nullptr) { + return false; + } *rtnCode = resultSetValue->GoTo(offset); return *rtnCode == RelationalStoreJsKit::OK; } @@ -269,6 +341,9 @@ namespace Relational { Assets ResultSetImpl::GetAssets(int32_t columnIndex, int32_t* rtnCode) { std::vector assets; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return Assets{nullptr, 0}; + } *rtnCode = resultSetValue->GetAssets(columnIndex, assets); if (*rtnCode != RelationalStoreJsKit::OK || assets.size() == 0) { return Assets{nullptr, 0}; @@ -294,6 +369,9 @@ namespace Relational { ValuesBucket ResultSetImpl::GetRow(int32_t* rtnCode) { NativeRdb::RowEntity rowEntity; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return ValuesBucket{nullptr, nullptr, 0}; + } *rtnCode = resultSetValue->GetRow(rowEntity); if (*rtnCode != E_OK) { return ValuesBucket{nullptr, nullptr, 0}; @@ -321,5 +399,55 @@ namespace Relational { } return result; } + + ValuesBucketEx ResultSetImpl::GetRowEx(int32_t* rtnCode) + { + NativeRdb::RowEntity rowEntity; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return ValuesBucketEx{nullptr, nullptr, 0}; + } + *rtnCode = resultSetValue->GetRow(rowEntity); + if (*rtnCode != E_OK) { + return ValuesBucketEx{nullptr, nullptr, 0}; + } + const std::map map = rowEntity.Get(); + size_t size = map.size(); + if (size == 0) { + return ValuesBucketEx{nullptr, nullptr, 0}; + } + ValuesBucketEx result = ValuesBucketEx { + .key = static_cast(malloc(sizeof(char*) * size)), + .value = static_cast(malloc(sizeof(ValueTypeEx) * size)), + .size = size + }; + if (result.key == nullptr || result.value == nullptr) { + free(result.key); + free(result.value); + return ValuesBucketEx{nullptr, nullptr, ERROR_VALUE}; + } + int64_t i = 0; + for (auto &t : map) { + result.key[i] = MallocCString(t.first); + result.value[i] = ValueObjectToValueTypeEx(t.second); + i++; + } + return result; + } + + ValueTypeEx ResultSetImpl::GetValue(int32_t columnIndex, int32_t* rtnCode) + { + NativeRdb::ValueObject object; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return ValueTypeEx{ 0 }; + } + *rtnCode = NativeRdb::E_ALREADY_CLOSED; + if (resultSetValue != nullptr) { + *rtnCode = resultSetValue->Get(columnIndex, object); + } + if (*rtnCode != E_OK) { + return ValueTypeEx{ 0 }; + } + return ValueObjectToValueTypeEx(object); + } } } \ No newline at end of file diff --git a/relational_store/frameworks/cj/src/relational_store_utils.cpp b/relational_store/frameworks/cj/src/relational_store_utils.cpp index bf7df7f7f242d1eaf76b4c933ae012d27ef4fc68..35bb53e778827ce231070ee9b72fca6ee555754c 100644 --- a/relational_store/frameworks/cj/src/relational_store_utils.cpp +++ b/relational_store/frameworks/cj/src/relational_store_utils.cpp @@ -17,8 +17,23 @@ #include "native_log.h" #include "rdb_store.h" +const int64_t UI64TOUI8 = 8; +const int64_t BITNUMOFUI64 = 64; + namespace OHOS { namespace Relational { + OHOS::NativeRdb::RdbStoreConfig::CryptoParam ToCCryptoParam(CryptoParam param) + { + auto cryptoParam = OHOS::NativeRdb::RdbStoreConfig::CryptoParam(); + cryptoParam.iterNum = param.iterNum; + cryptoParam.encryptAlgo = param.encryptAlgo; + cryptoParam.hmacAlgo = param.hmacAlgo; + cryptoParam.kdfAlgo = param.kdfAlgo; + cryptoParam.cryptoPageSize = param.cryptoPageSize; + cryptoParam.encryptKey_ = CArrUI8ToVector(param.encryptKey); + return cryptoParam; + } + char* MallocCString(const std::string& origin) { if (origin.empty()) { @@ -35,6 +50,9 @@ namespace Relational { NativeRdb::ValueObject ValueTypeToValueObjectBlob(const ValueType& value) { std::vector blob = std::vector(); + if (value.Uint8Array.head == nullptr) { + return NativeRdb::ValueObject(blob); + } for (int64_t j = 0; j < value.Uint8Array.size; j++) { blob.push_back(value.Uint8Array.head[j]); } @@ -61,6 +79,9 @@ namespace Relational { NativeRdb::ValueObject ValueTypeToValueObjectAssets(const ValueType& value) { std::vector assets = std::vector(); + if (value.assets.head == nullptr) { + return assets; + } for (int64_t j = 0; j < value.assets.size; j++) { Asset asset = value.assets.head[j]; std::string modifyTime = asset.modifyTime; @@ -97,6 +118,10 @@ namespace Relational { break; } case TYPE_STR: { + if (value.string == nullptr) { + LOGE("string value is nullptr"); + break; + } valueObject = NativeRdb::ValueObject(value.string); break; } @@ -123,6 +148,152 @@ namespace Relational { return valueObject; } + NativeRdb::ValueObject ValueTypeExToValueObjectBlob(const ValueTypeEx& value) + { + std::vector blob = std::vector(); + if (value.uint8Array.head == nullptr) { + LOGE("the array head is nullptr"); + return NativeRdb::ValueObject(blob); + } + for (int64_t j = 0; j < value.uint8Array.size; j++) { + blob.push_back(value.uint8Array.head[j]); + } + return NativeRdb::ValueObject(blob); + } + + NativeRdb::ValueObject ValueTypeExToValueObjectAsset(const ValueTypeEx& value) + { + std::string modifyTime = value.asset.modifyTime; + std::string size = value.asset.size; + NativeRdb::ValueObject::Asset asset = { + .status = value.asset.status, + .name = value.asset.name, + .uri = value.asset.uri, + .createTime = value.asset.createTime, + .modifyTime = modifyTime, + .size = size, + .hash = modifyTime + "_" + size, + .path = value.asset.path + }; + return NativeRdb::ValueObject(asset); + } + + NativeRdb::ValueObject ValueTypeExToValueObjectAssets(const ValueTypeEx& value) + { + std::vector assets = std::vector(); + if (value.assets.head == nullptr) { + LOGE("the assets head is nullptr"); + return NativeRdb::ValueObject(assets); + } + for (int64_t j = 0; j < value.assets.size; j++) { + Asset asset = value.assets.head[j]; + std::string modifyTime = asset.modifyTime; + std::string size = asset.size; + NativeRdb::ValueObject::Asset nativeAsset = { + .status = asset.status, + .name = asset.name, + .uri = asset.uri, + .createTime = asset.createTime, + .modifyTime = modifyTime, + .size = size, + .hash = modifyTime + "_" + size, + .path = asset.path + }; + assets.push_back(nativeAsset); + } + return NativeRdb::ValueObject(assets); + } + + NativeRdb::ValueObject ValueTypeExToValueObjectFloatArr(const ValueTypeEx& value) + { + std::vector arr = std::vector(); + if (value.floatArray.head == nullptr) { + LOGE("the floatArray head is nullptr"); + return NativeRdb::ValueObject(arr); + } + for (int64_t j = 0; j < value.floatArray.size; j++) { + arr.push_back(value.floatArray.head[j]); + } + return NativeRdb::ValueObject(arr); + } + + NativeRdb::ValueObject ValueTypeExToValueObjectBigInt(const ValueTypeEx& value) + { + std::vector arr = std::vector(); + int64_t firstSize = (value.bigInt.value.size % UI64TOUI8 == 0) ? UI64TOUI8 : + (value.bigInt.value.size % UI64TOUI8); + for (int64_t i = 0; i < ((value.bigInt.value.size + UI64TOUI8 - 1) / UI64TOUI8); i++) { + uint64_t tempValue = 0; + if (i == 0) { + for (int64_t j = 0; j < firstSize; j++) { + tempValue |= + (static_cast(value.bigInt.value.head[j]) << (UI64TOUI8 * (firstSize -j - 1))); + } + } else { + for (int64_t j = 0; j < UI64TOUI8; j++) { + tempValue |= + (static_cast(value.bigInt.value.head[UI64TOUI8 * (i - 1) + firstSize + j]) << + (UI64TOUI8 * ((value.bigInt.value.size - (UI64TOUI8 * (i - 1) + firstSize + j) - 1) % + UI64TOUI8))); + } + } + arr.push_back(tempValue); + } + return NativeRdb::ValueObject(NativeRdb::ValueObject::BigInt(static_cast(value.bigInt.sign), + std::move(arr))); + } + + NativeRdb::ValueObject ValueTypeExToValueObject(const ValueTypeEx& value) + { + NativeRdb::ValueObject valueObject; + switch (value.tag) { + case TYPE_NULL: { + valueObject = NativeRdb::ValueObject(); + break; + } + case TYPE_INT: { + valueObject = NativeRdb::ValueObject(value.integer); + break; + } + case TYPE_DOU: { + valueObject = NativeRdb::ValueObject(value.dou); + break; + } + case TYPE_STR: { + valueObject = NativeRdb::ValueObject(value.string); + break; + } + case TYPE_BOOL: { + valueObject = NativeRdb::ValueObject(value.boolean); + break; + } + case TYPE_BLOB: { + valueObject = ValueTypeExToValueObjectBlob(value); + break; + } + case TYPE_ASSET: { + valueObject = ValueTypeExToValueObjectAsset(value); + break; + } + case TYPE_ASSETS: { + valueObject = ValueTypeExToValueObjectAssets(value); + break; + } + case TYPE_FLOATARR: { + valueObject = ValueTypeExToValueObjectFloatArr(value); + break; + } + case TYPE_BIGINT: { + valueObject = ValueTypeExToValueObjectBigInt(value); + break; + } + default: + valueObject = NativeRdb::ValueObject(); + break; + } + return valueObject; + } + ValueType ValueObjectToValueTypeAsset(const NativeRdb::ValueObject& object) { NativeRdb::ValueObject::Asset val; @@ -143,6 +314,9 @@ namespace Relational { { NativeRdb::ValueObject::Assets val; object.GetAssets(val); + if (val.size() == 0) { + return ValueType {.assets = Assets{nullptr, -1}, .tag = TYPE_ASSETS}; + } Assets assets = Assets {.head = static_cast(malloc(val.size() * sizeof(Asset))), .size = val.size()}; if (assets.head == nullptr) { return ValueType {.assets = Assets{nullptr, -1}, .tag = TYPE_ASSETS}; @@ -189,6 +363,9 @@ namespace Relational { case NativeRdb::ValueObject::TYPE_BLOB: { std::vector val; object.GetBlob(val); + if (val.size() == 0) { + return ValueType {.Uint8Array = CArrUI8 {nullptr, -1}, .tag = TYPE_BLOB}; + } CArrUI8 arr = CArrUI8 {.head = static_cast(malloc(val.size() * sizeof(uint8_t))), .size = val.size()}; if (arr.head == nullptr) { @@ -209,6 +386,141 @@ namespace Relational { } } + ValueTypeEx ValueObjectToValueTypeExBlob(const NativeRdb::ValueObject& object) + { + std::vector val = static_cast>(object); + auto size = val.size(); + if (size == 0) { + return ValueTypeEx {.uint8Array = CArrUI8 {nullptr, ERROR_VALUE}, .tag = TYPE_BLOB}; + } + CArrUI8 arr = CArrUI8 {.head = static_cast(malloc(size * sizeof(uint8_t))), + .size = size}; + if (arr.head == nullptr) { + return ValueTypeEx {.uint8Array = CArrUI8 {nullptr, ERROR_VALUE}, .tag = TYPE_BLOB}; + } + for (size_t i = 0; i < size; i++) { + arr.head[i] = val[i]; + } + return ValueTypeEx {.uint8Array = arr, .tag = TYPE_BLOB}; + } + + ValueTypeEx ValueObjectToValueTypeExAsset(const NativeRdb::ValueObject& object) + { + NativeRdb::ValueObject::Asset val = static_cast(object); + Asset asset = Asset { + .name = MallocCString(val.name), + .uri = MallocCString(val.uri), + .path = MallocCString(val.path), + .createTime = MallocCString(val.createTime), + .modifyTime = MallocCString(val.modifyTime), + .size = MallocCString(val.size), + .status = val.status + }; + return ValueTypeEx {.asset = asset, .tag = TYPE_ASSET}; + } + + ValueTypeEx ValueObjectToValueTypeExAssets(const NativeRdb::ValueObject& object) + { + NativeRdb::ValueObject::Assets val = static_cast(object); + if (val.size() == 0) { + return ValueTypeEx {.assets = Assets{nullptr, ERROR_VALUE}, .tag = TYPE_ASSETS}; + } + Assets assets = Assets {.head = static_cast(malloc(val.size() * sizeof(Asset))), .size = val.size()}; + if (assets.head == nullptr) { + return ValueTypeEx {.assets = Assets{nullptr, ERROR_VALUE}, .tag = TYPE_ASSETS}; + } + for (std::size_t i = 0; i < val.size(); i++) { + assets.head[i] = Asset { + .name = MallocCString(val[i].name), + .uri = MallocCString(val[i].uri), + .path = MallocCString(val[i].path), + .createTime = MallocCString(val[i].createTime), + .modifyTime = MallocCString(val[i].modifyTime), + .size = MallocCString(val[i].size), + .status = static_cast(val[i].status) + }; + } + return ValueTypeEx {.assets = assets, .tag = TYPE_ASSETS}; + } + + ValueTypeEx ValueObjectToValueTypeExFloatArray(const NativeRdb::ValueObject& object) + { + std::vector val = static_cast>(object); + auto size = val.size(); + if (size == 0) { + return ValueTypeEx {.floatArray = CArrFloat {nullptr, ERROR_VALUE}, .tag = TYPE_FLOATARR}; + } + CArrFloat arr = CArrFloat {.head = static_cast(malloc(size * sizeof(float))), + .size = size}; + if (arr.head == nullptr) { + return ValueTypeEx {.floatArray = CArrFloat {nullptr, ERROR_VALUE}, .tag = TYPE_FLOATARR}; + } + for (size_t i = 0; i < size; i++) { + arr.head[i] = val[i]; + } + return ValueTypeEx {.floatArray = arr, .tag = TYPE_FLOATARR}; + } + + ValueTypeEx ValueObjectToValueTypeExBigInt(const NativeRdb::ValueObject& object) + { + NativeRdb::ValueObject::BigInt bigInt = static_cast(object); + int32_t sign = bigInt.Sign(); + std::vector value = bigInt.Value(); + size_t size = value.size(); + if (size == 0) { + return ValueTypeEx {.bigInt = BigInt {CArrUI8 {nullptr, ERROR_VALUE}, ERROR_VALUE}, .tag = TYPE_BIGINT}; + } + uint8_t *head = static_cast(calloc(UI64TOUI8 * size, sizeof(uint8_t))); + if (head == nullptr) { + return ValueTypeEx {.bigInt = BigInt {CArrUI8 {nullptr, ERROR_VALUE}, ERROR_VALUE}, .tag = TYPE_BIGINT}; + } + for (size_t i = 0; i < size; i++) { + for (size_t j = 0; j < UI64TOUI8; j++) { + head[UI64TOUI8 * i + j] |= (value[i] >> (BITNUMOFUI64 - (UI64TOUI8 * (j + 1)))); + } + } + return ValueTypeEx {.bigInt = BigInt {CArrUI8 {head, UI64TOUI8 * size}, sign}, .tag = TYPE_BIGINT}; + } + + ValueTypeEx ValueObjectToValueTypeEx(const NativeRdb::ValueObject& object) + { + switch (object.GetType()) { + case NativeRdb::ValueObject::TYPE_NULL: + return ValueTypeEx {.tag = TYPE_NULL}; + case NativeRdb::ValueObject::TYPE_INT: { + return ValueTypeEx {.integer = static_cast(object), .tag = TYPE_INT}; + } + case NativeRdb::ValueObject::TYPE_DOUBLE: { + return ValueTypeEx {.dou = static_cast(object), .tag = TYPE_DOU}; + } + case NativeRdb::ValueObject::TYPE_STRING: { + return ValueTypeEx {.string = MallocCString(static_cast(object)), .tag = TYPE_STR}; + } + case NativeRdb::ValueObject::TYPE_BOOL: { + return ValueTypeEx {.boolean = static_cast(object), .tag = TYPE_BOOL}; + } + case NativeRdb::ValueObject::TYPE_BLOB: { + return ValueObjectToValueTypeExBlob(object); + } + case NativeRdb::ValueObject::TYPE_ASSET: { + return ValueObjectToValueTypeExAsset(object); + } + case NativeRdb::ValueObject::TYPE_ASSETS: { + return ValueObjectToValueTypeExAssets(object); + } + case NativeRdb::ValueObject::TYPE_VECS: { + return ValueObjectToValueTypeExFloatArray(object); + } + case NativeRdb::ValueObject::TYPE_BIGINT: { + return ValueObjectToValueTypeExBigInt(object); + } + case NativeRdb::ValueObject::TYPE_BUTT: + return ValueTypeEx {.tag = 128}; + default: + return ValueTypeEx {.tag = TYPE_NULL}; + } + } + CArrStr VectorToCArrStr(const std::vector &devices) { CArrStr cArrStr{0}; @@ -239,6 +551,15 @@ namespace Relational { return arr; } + std::vector CArrUI8ToVector(CArrUI8 carr) + { + std::vector arr; + for (int i = 0; i < carr.size; i++) { + arr.push_back(carr.head[i]); + } + return arr; + } + std::variant RetPRIKeyTypeToVariant(RetPRIKeyType &value) { switch (value.tag) { @@ -282,6 +603,9 @@ namespace Relational { { ModifyTime modifyTime{0}; modifyTime.size = static_cast(map.size()); + if (modifyTime.size == 0) { + return ModifyTime{0}; + } modifyTime.key = static_cast(malloc(sizeof(RetPRIKeyType) * modifyTime.size)); modifyTime.value = static_cast(malloc(sizeof(uint64_t) * modifyTime.size)); if (modifyTime.key == nullptr || modifyTime.value == nullptr) { diff --git a/relational_store/frameworks/common/include/delay_actuator.h b/relational_store/frameworks/common/include/delay_actuator.h new file mode 100644 index 0000000000000000000000000000000000000000..efb8a4e3ada3982836a35fae77892458fe5b982f --- /dev/null +++ b/relational_store/frameworks/common/include/delay_actuator.h @@ -0,0 +1,200 @@ +/* +* Copyright (c) 2025 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 COMMON_RDB_INCLUDE_DELAY_ACTUATOR_H +#define COMMON_RDB_INCLUDE_DELAY_ACTUATOR_H +#include +#include +#include "executor_pool.h" +namespace OHOS { +class ActuatorBase : public std::enable_shared_from_this { +public: + static constexpr uint32_t DEFAULT_FIRST_DELAY_INTERVAL = 0; + static constexpr uint32_t DEFAULT_MIN_EXECUTE_INTERVAL = 200; + static constexpr uint32_t DEFAULT_MAX_EXECUTE_INTERVAL = 500; + static const uint32_t INVALID_INTERVAL = UINT32_MAX; + void SetExecutorPool(std::shared_ptr pool) + { + pool_ = std::move(pool); + } + void Suspend() + { + isSuspend_ = true; + } + void Active() + { + isSuspend_ = false; + } + + class Defer final { + public: + Defer(std::vector> actuators) : actuators_(std::move(actuators)) + { + for (auto actuator : actuators_) { + if (actuator) { + actuator->Suspend(); + actuator->StopTimer(false); + } + } + } + Defer(std::shared_ptr actuator) : Defer(std::vector>({actuator})) + {} + ~Defer() + { + for (auto actuator : actuators_) { + if (actuator) { + actuator->Active(); + actuator->StartTimer(); + } + } + } + Defer(const Defer &defer) = delete; + Defer(Defer &&defer) = delete; + Defer &operator=(const Defer &defer) = delete; + Defer &operator=(Defer &&defer) = delete; + void *operator new(size_t size) = delete; + void *operator new[](size_t size) = delete; + void operator delete(void *) = delete; + void operator delete[](void *) = delete; + + private: + std::vector> actuators_; + }; +protected: + ActuatorBase(uint32_t firstInterval = DEFAULT_FIRST_DELAY_INTERVAL, + uint32_t minInterval = DEFAULT_MIN_EXECUTE_INTERVAL, uint32_t maxInterval = DEFAULT_MAX_EXECUTE_INTERVAL) + : firstDelayInterval_(firstInterval), minExecuteInterval_(minInterval), maxExecuteInterval_(maxInterval) + { + } + virtual ~ActuatorBase() + { + StopTimer(true); + } + + void StartTimer() + { + std::lock_guard lock(mutex_); + if (pool_ == nullptr || isSuspend_) { + return; + } + auto weakThis = weak_from_this(); + if (forceTaskId_ == Executor::INVALID_TASK_ID && maxExecuteInterval_ != INVALID_INTERVAL) { + forceTaskId_ = pool_->Schedule(std::chrono::milliseconds(maxExecuteInterval_), [weakThis]() { + auto self = weakThis.lock(); + if (self != nullptr) { + self->ExecuteTask(); + self->lastExecuteTimePoint_ = GetTimeStamp(); + } + }); + } + if (firstDelayInterval_ == INVALID_INTERVAL || minExecuteInterval_ == INVALID_INTERVAL) { + return; + } + if (delayTaskId_ == Executor::INVALID_TASK_ID) { + delayTaskId_ = + pool_->Schedule(std::chrono::milliseconds(lastExecuteTimePoint_ <= GetTimeStamp() - minExecuteInterval_ + ? firstDelayInterval_ + : minExecuteInterval_), + [weakThis]() { + auto self = weakThis.lock(); + if (self != nullptr) { + self->ExecuteTask(); + self->lastExecuteTimePoint_ = GetTimeStamp(); + } + }); + } else { + delayTaskId_ = pool_->Reset(delayTaskId_, std::chrono::milliseconds(minExecuteInterval_)); + } + } + void StopTimer(bool wait) + { + std::lock_guard lock(mutex_); + if (pool_ != nullptr) { + pool_->Remove(forceTaskId_, wait); + pool_->Remove(delayTaskId_, wait); + } + forceTaskId_ = Executor::INVALID_TASK_ID; + delayTaskId_ = Executor::INVALID_TASK_ID; + } + + virtual void ExecuteTask() {}; + static inline uint64_t GetTimeStamp() + { + return std::chrono::duration_cast( + std::chrono::steady_clock::now().time_since_epoch()) + .count(); + } +private: + ExecutorPool::TaskId delayTaskId_ = ExecutorPool::INVALID_TASK_ID; + ExecutorPool::TaskId forceTaskId_ = ExecutorPool::INVALID_TASK_ID; + std::shared_ptr pool_ = nullptr; + bool isSuspend_ = false; + std::atomic_uint64_t lastExecuteTimePoint_ = 0; + uint32_t const firstDelayInterval_ = DEFAULT_FIRST_DELAY_INTERVAL; + uint32_t const minExecuteInterval_ = DEFAULT_MIN_EXECUTE_INTERVAL; + uint32_t const maxExecuteInterval_ = DEFAULT_MAX_EXECUTE_INTERVAL; + mutable std::mutex mutex_; +}; + +template, class Task = std::function> +class DelayActuator : public ActuatorBase { +public: + DelayActuator(MergeFunc mergeFunc = nullptr, uint32_t firstInterval = DEFAULT_FIRST_DELAY_INTERVAL, + uint32_t minInterval = DEFAULT_MIN_EXECUTE_INTERVAL, uint32_t maxInterval = DEFAULT_MAX_EXECUTE_INTERVAL) + : ActuatorBase(firstInterval, minInterval, maxInterval), data_(T()), mergeFunc_(mergeFunc) + { + } + ~DelayActuator() {} + + void SetTask(Task task) + { + task_ = std::move(task); + } + template + void Execute(D &&value) + { + { + std::lock_guard lock(mutex_); + if (mergeFunc_) { + mergeFunc_(data_, std::forward(value)); + } else { + data_ = T{std::move(value)}; + } + } + StartTimer(); + } + +private: + Task task_; + T data_; + MergeFunc mergeFunc_; + std::mutex mutex_; + + void ExecuteTask() override + { + StopTimer(false); + T data; + { + std::lock_guard lock(mutex_); + data = std::move(data_); + data_ = T(); + } + if (task_) { + task_(std::move(data)); + } + } +}; +} // namespace OHOS +#endif // COMMON_RDB_INCLUDE_DELAY_ACTUATOR_H \ No newline at end of file diff --git a/relational_store/frameworks/common/include/logger.h b/relational_store/frameworks/common/include/logger.h index 848ebc57d7396d0190c09b04600f66031e27af29..821f0e6e95104cc10996eda08f59eff84879e32a 100644 --- a/relational_store/frameworks/common/include/logger.h +++ b/relational_store/frameworks/common/include/logger.h @@ -39,20 +39,6 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() return { LOG_CORE, 0xD001650, "SRdb" }; } } // namespace Rdb - -namespace GraphStoreJsKit { -static inline OHOS::HiviewDFX::HiLogLabel LogLabel() -{ - return { LOG_CORE, 0xD001660, "GdbJS" }; -} -} // namespace GraphStoreJsKit - -namespace DistributedDataAip { -static inline OHOS::HiviewDFX::HiLogLabel LogLabel() -{ - return { LOG_CORE, 0xD001660, "GdbNative" }; -} -} // namespace DistributedDataAip } // namespace OHOS #define LOG_DEBUG(fmt, ...) \ diff --git a/relational_store/interfaces/inner_api/gdb/BUILD.gn b/relational_store/frameworks/js/ani/relationalstore/BUILD.gn similarity index 30% rename from relational_store/interfaces/inner_api/gdb/BUILD.gn rename to relational_store/frameworks/js/ani/relationalstore/BUILD.gn index c593c4a0b871e47cfdcf9aee14abc38ad77998b2..f3e7cd53cb1fcc89f2dd7f9582b6484baf66f62d 100644 --- a/relational_store/interfaces/inner_api/gdb/BUILD.gn +++ b/relational_store/frameworks/js/ani/relationalstore/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2024 Huawei Device Co., Ltd. +# Copyright (c) 2025 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 @@ -10,73 +10,74 @@ # 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/config/components/ets_frontend/ets2abc_config.gni") import("//build/ohos.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") -config("native_gdb_public_config") { - visibility = [ ":*" ] - include_dirs = [ - "${relational_store_innerapi_path}/gdb/include", - "${relational_store_innerapi_path}/rdb/include", +ohos_shared_library("relationalstore_ani") { + sources = [ + "src/ani_rdb_entry.cpp", + "src/ani_rdb_error.cpp", + "src/ani_rdb_predicates.cpp", + "src/ani_rdb_store.cpp", + "src/ani_rdb_store_helper.cpp", + "src/ani_result_set.cpp", + "src/ani_utils.cpp", ] -} - -ohos_shared_library("native_graphstore") { - public_configs = [ ":native_gdb_public_config" ] - sanitize = { - boundary_sanitize = true - ubsan = true - cfi = true - cfi_cross_dso = true - debug = false - } - cflags_cc = [ "-fvisibility=hidden" ] include_dirs = [ + "./include", "${relational_store_common_path}/include", - "${relational_store_native_path}/gdb/adapter/include", - "${relational_store_native_path}/gdb/include", - "${relational_store_native_path}/rdb/include", ] - sources = [ - "${relational_store_native_path}/gdb/adapter/src/grd_adapter.cpp", - "${relational_store_native_path}/gdb/adapter/src/grd_adapter_manager.cpp", - "${relational_store_native_path}/gdb/src/connection.cpp", - "${relational_store_native_path}/gdb/src/connection_pool.cpp", - "${relational_store_native_path}/gdb/src/db_helper.cpp", - "${relational_store_native_path}/gdb/src/db_store_impl.cpp", - "${relational_store_native_path}/gdb/src/db_store_manager.cpp", - "${relational_store_native_path}/gdb/src/edge.cpp", - "${relational_store_native_path}/gdb/src/full_result.cpp", - "${relational_store_native_path}/gdb/src/gdb_utils.cpp", - "${relational_store_native_path}/gdb/src/graph_connection.cpp", - "${relational_store_native_path}/gdb/src/graph_statement.cpp", - "${relational_store_native_path}/gdb/src/path.cpp", - "${relational_store_native_path}/gdb/src/path_segment.cpp", - "${relational_store_native_path}/gdb/src/store_config.cpp", - "${relational_store_native_path}/gdb/src/trans_db.cpp", - "${relational_store_native_path}/gdb/src/transaction.cpp", - "${relational_store_native_path}/gdb/src/transaction_impl.cpp", - "${relational_store_native_path}/gdb/src/vertex.cpp", - "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", - "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", - "${relational_store_native_path}/rdb/src/rdb_time_utils.cpp", - "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", - "${relational_store_native_path}/rdb/src/string_utils.cpp", + + deps = [ + "${relational_store_innerapi_path}/rdb:native_rdb", + "${relational_store_innerapi_path}/rdb_data_share_adapter:rdb_data_share_adapter", ] - deps = [] + external_deps = [ + "ability_runtime:abilitykit_native", + "ability_runtime:appkit_native", + "ability_runtime:wantagent_innerkits", "c_utils:utils", - "file_api:securitylabel", + "data_share:datashare_common_lite", "hilog:libhilog", - "hisysevent:libhisysevent", - "hitrace:hitrace_meter", - "huks:libhukssdk", - "json:nlohmann_json_static", + "runtime_core:ani", + "samgr:samgr_proxy", ] - if (arkdata_db_core_is_exists) { - defines = [ "ARKDATA_DB_CORE_IS_EXISTS" ] + + sanitize = { + boundary_sanitize = true + ubsan = true + cfi = true + cfi_cross_dso = true + debug = false } + + subsystem_name = "distributeddatamgr" + part_name = "relational_store" + output_extension = "so" +} + +generate_static_abc("relationalstore_abc") { + base_url = "./ets" + files = [ "./ets/@ohos.data.relationalStore.ets" ] + dst_file = "$target_out_dir/relationalstore.abc" + out_puts = [ "$target_out_dir/relationalstore.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/relationalstore.abc" +} + +ohos_prebuilt_etc("relationalstore_abc_etc") { + source = "$target_out_dir/relationalstore.abc" + module_install_dir = "framework" subsystem_name = "distributeddatamgr" part_name = "relational_store" + deps = [ ":relationalstore_abc" ] +} + +group("relationalstore_ani_package") { + deps = [ + ":relationalstore_abc_etc", + ":relationalstore_ani", + ] } diff --git a/relational_store/frameworks/js/ani/relationalstore/ets/@ohos.data.relationalStore.ets b/relational_store/frameworks/js/ani/relationalstore/ets/@ohos.data.relationalStore.ets new file mode 100644 index 0000000000000000000000000000000000000000..a8228a4a68ec79e659d8fc8afbf3fc626e6cede0 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/ets/@ohos.data.relationalStore.ets @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2025 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 { AsyncCallback, Callback } from '@ohos.base' +import Context from 'application.BaseContext' +import dataSharePredicates from '@ohos.data.dataSharePredicates'; +import { BusinessError } from '@ohos.base'; + +export default namespace relationalStore { + + loadLibrary("relationalstore_ani") + + export enum AssetStatus { + ASSET_NORMAL, + ASSET_INSERT, + ASSET_UPDATE, + ASSET_DELETE, + ASSET_ABNORMAL, + ASSET_DOWNLOADING + } + + export interface Asset { + name: string; + uri: string; + path: string; + createTime: string; + modifyTime: string; + size: string; + status?: AssetStatus; + } + + type Assets = Asset[]; + + type ValueType = null | number | string | boolean | Uint8Array | Asset | Assets | Float32Array | bigint; + + export type ValuesBucket = Record; + + class Cleaner { + static callback(cleaner: Cleaner): void { + cleaner.clean() + } + + constructor(targetPtr: long) { + this.targetPtr = targetPtr + } + + native clean(): void + private targetPtr: long = 0 + } + + class FinalizationAgent { + constructor(obj: T, ptr: long) { + this.register(obj, ptr); + } + + register(obj: T, ptr: long): void { + this.unregisterToken = {}; + this.cleaner = new Cleaner(ptr); + finalizer.register(obj, this.cleaner!, this.unregisterToken); + } + + unregister(): void { + finalizer.unregister(this.unregisterToken); + } + + private cleaner: Cleaner | null = null; + private unregisterToken: object; + } + + let finalizer = new FinalizationRegistry(Cleaner.callback) + + export class RdbPredicates { + private nativePtr: long = 0 + private fzAgent: FinalizationAgent + + constructor(name: string) { + this.initNativePredicates(name) + this.initFinalizer() + } + + private initFinalizer() :void { + this.fzAgent = new FinalizationAgent(this, this.nativePtr) + } + private native initNativePredicates(name: string): void; + } + + export interface ResultSet { + getColumnIndex(columnName: string): number; + getString(columnIndex: number): string; + getLong(columnIndex: number): number; + goToFirstRow(): boolean; + } + + class ResultSetInner implements ResultSet { + private nativePtr: long = 0; + private fzAgent: FinalizationAgent + + private initFinalizer() :void { + this.fzAgent = new FinalizationAgent(this, this.nativePtr) + } + + native getColumnIndex(columnName: string): number; + native getString(columnIndex: number): string; + native getLong(columnIndex: number): number; + native goToFirstRow(): boolean; + } + + export enum SecurityLevel { + S1 = 1, + S2 = 2, + S3 = 3, + S4 = 4 + } + + export interface StoreConfig { + name: string; + securityLevel: SecurityLevel; + encrypt?: boolean; + dataGroupId?: string; + customDir?: string; + autoCleanDirtyData?: boolean; + isSearchable?: boolean; + allowRebuild?: boolean; + vector?: boolean; + isReadOnly?: boolean; + pluginLibs?: Array; + haMode?: HAMode; + cryptoParam?: CryptoParam; + } + + export enum HAMode { + SINGLE = 0, + MAIN_REPLICA + } + + export interface CryptoParam { + encryptionKey: Uint8Array; + iterationCount?: number; + encryptionAlgo?: EncryptionAlgo; + hmacAlgo?: HmacAlgo; + kdfAlgo?: KdfAlgo; + cryptoPageSize?: number; + } + + export enum EncryptionAlgo { + AES_256_GCM = 0, + AES_256_CBC + } + + export enum HmacAlgo { + SHA1 = 0, + SHA256, + SHA512 + } + + export enum KdfAlgo { + KDF_SHA1 = 0, + KDF_SHA256, + KDF_SHA512 + } + + export interface RdbStore { + batchInsert(table: string, values: Array, callback: AsyncCallback): void; + batchInsert(table: string, values: Array): Promise; + batchInsertSync(table: string, values: Array): number; + + deleteSync(predicates: RdbPredicates): number; + delete(predicates: RdbPredicates): Promise; + delete(predicates: RdbPredicates, callback: AsyncCallback): void; + delete(table: string, predicates: dataSharePredicates.DataSharePredicates): Promise; + delete(table: string, predicates: dataSharePredicates.DataSharePredicates, callback: AsyncCallback): void; + + executeSql(sql: string, callback: AsyncCallback): void; + executeSql(sql: string, bindArgs: Array, callback: AsyncCallback): void; + executeSql(sql: string, bindArgs?: Array): Promise; + + beginTransaction(): void; + commit(): void; + rollBack(): void; + + querySqlSync(sql: string, bindArgs?: Array): ResultSet; + } + + class RdbStoreInner implements RdbStore { + private nativePtr: long = 0; + private fzAgent: FinalizationAgent + + private initFinalizer() :void { + this.fzAgent = new FinalizationAgent(this, this.nativePtr) + } + + batchInsert(table: string, values: Array, callback: AsyncCallback): void { + let cb = (): Object => { + let num = this.batchInsertSync(table, values) + return num as Object + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + let error = new BusinessError + error.code = 0 + callback(error, v as number) + }); + p1.catch((err: NullishType): void => { + callback(err as BusinessError, 0 as number) + }); + } + + batchInsert(table: string, values: Array): Promise { + let p = new Promise((resolve: (value: number) => void, reject: (error: Object) => void): void => { + let cb = (): Object => { + let num = this.batchInsertSync(table, values) + return num as Object + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + resolve(v as number); + }); + p1.catch((err: NullishType): void => { + reject(err as Error); + }); + }); + return p + } + native batchInsertSync(table: string, values: Array): number; + + native deleteSync(predicates: RdbPredicates): number; + + delete(predicates: RdbPredicates): Promise { + let p = new Promise((resolve: (data: number) => void, reject: (error: Object) => void): void => { + let cb = (): Object => { + let num = this.deleteSync(predicates) + return num as Object + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + resolve(v as number); + }); + p1.catch((err: NullishType): void => { + reject(err as Error); + }); + }); + return p + } + + delete(predicates: RdbPredicates, callback: AsyncCallback): void { + let cb = (): Object => { + let num = this.deleteSync(predicates) + return num as Object + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + let error = new BusinessError + error.code = 0 + callback(error, v as number) + }); + p1.catch((err: NullishType): void => { + callback(err as BusinessError, 0 as number) + }); + } + + private native deleteShareSync(table: string, predicates: dataSharePredicates.DataSharePredicates): number; + + delete(table: string, predicates: dataSharePredicates.DataSharePredicates): Promise { + let p = new Promise((resolve: (data: number) => void, reject: (error: Object) => void): void => { + let cb = (): Object => { + let num = this.deleteShareSync(table, predicates) + return num as Object + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + resolve(v as number); + }); + p1.catch((err: NullishType): void => { + reject(err as Error); + }); + }); + return p + } + + delete(table: string, predicates: dataSharePredicates.DataSharePredicates, callback: AsyncCallback): void { + let cb = (): Object => { + let num = this.deleteShareSync(table, predicates) + return num as Object + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + let error = new BusinessError + error.code = 0 + callback(error, v as number) + }); + p1.catch((err: NullishType): void => { + callback(err as BusinessError, 0 as number) + }); + } + + executeSql(sql: string, callback: AsyncCallback): void { + let cb = (): undefined => { + this.executeSqlSync(sql) + return undefined + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + let error = new BusinessError + error.code = 0 + callback(error, undefined) + }); + p1.catch((err: NullishType): void => { + callback(err as BusinessError, undefined) + }); + } + + executeSql(sql: string, bindArgs: Array, callback: AsyncCallback): void { + let cb = (): undefined => { + this.executeSqlSync(sql, bindArgs) + return undefined + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + let error = new BusinessError + error.code = 0 + callback(error, undefined) + }); + p1.catch((err: NullishType): void => { + callback(err as BusinessError, undefined) + }); + } + + executeSql(sql: string, bindArgs?: Array): Promise { + let p = new Promise((resolve: (v: NullishType) => void, reject: (error: Object) => void): void => { + let cb = (): undefined => { + this.executeSqlSync(sql, bindArgs) + return undefined + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + resolve(v); + }); + p1.catch((err: NullishType): void => { + reject(err as Error); + }); + }); + return p + } + + private native executeSqlSync(sql: string, args?: Array): void; + + native beginTransaction(): void; + native commit(): void; + native rollBack(): void; + + native querySqlSync(sql: string, bindArgs?: Array): ResultSet; + } + + export native function getRdbStoreSync(context: Context, config: StoreConfig): RdbStore + + export function getRdbStore(context: Context, config: StoreConfig, callback: AsyncCallback): void { + let p1 = taskpool.execute(getRdbStoreSync, context, config); + p1.then((rdb: NullishType): void => { + let error = new BusinessError + error.code = 0 + callback(error, rdb as RdbStore) + }); + p1.catch((err: NullishType): void => { + let rdb = new RdbStoreInner() + callback(err as BusinessError, rdb) + }); + } + export function getRdbStore(context: Context, config: StoreConfig): Promise { + let p = new Promise((resolve: (value: RdbStore) => void, reject: (error: Object) => void): void => { + let p1 = taskpool.execute(getRdbStoreSync, context, config); + p1.then((rdb: NullishType): void => { + resolve(rdb as RdbStore); + }); + p1.catch((err: NullishType): void => { + reject(err as Object); + }); + }); + return p + } +} + diff --git a/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_error.h b/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_error.h new file mode 100644 index 0000000000000000000000000000000000000000..f5bc981bf403379c89f59328feb3864279b6e32f --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_error.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2025 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 ANI_RDB_ERROR_H +#define ANI_RDB_ERROR_H + +#include +#include +#include +#include +#include "logger.h" +#include "rdb_errno.h" + +namespace OHOS { +namespace RelationalStoreAniKit { +constexpr int MAX_INPUT_COUNT = 10; +constexpr int OK = 0; +constexpr int ERR = -1; + +constexpr int E_NON_SYSTEM_APP_ERROR = 202; +constexpr int E_PARAM_ERROR = 401; +constexpr int E_INNER_ERROR = 14800000; +constexpr int E_NOT_STAGE_MODE = 14801001; +constexpr int E_DATA_GROUP_ID_INVALID = 14801002; + +struct JsErrorCode { + int32_t status; + int32_t jsCode; + const char *message; +}; +const std::optional GetJsErrorCode(int32_t errorCode); +ani_object GetAniBusinessError(ani_env *env, int32_t errorCode); +void ThrowBusinessError(ani_env *env, int32_t status); +void ThrowBusinessError(ani_env *env, int32_t status, std::string message); + +} // namespace RelationalStoreAniKit +} // namespace OHOS + +#endif // ANI_RDB_ERROR_H + diff --git a/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_predicates.h b/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_predicates.h new file mode 100644 index 0000000000000000000000000000000000000000..80cf4a684b205be74a3ec718aadef5c449ff6dd7 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_predicates.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 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 ANI_RDB_PREDICATES_H +#define ANI_RDB_PREDICATES_H + +#include "abs_rdb_predicates.h" +#include "ani_utils.h" +#include "rdb_predicates.h" + +namespace OHOS { +namespace RelationalStoreAniKit { + +class PredicatesProxy : public NativeObject { +public: + std::shared_ptr predicates; +}; + +ani_status PredicatesInit(ani_env *env); + +} // namespace RelationalStoreAniKit +} // namespace OHOS + +#endif // ANI_RDB_PREDICATES_H + diff --git a/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_store.h b/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_store.h new file mode 100644 index 0000000000000000000000000000000000000000..dd684a74f6edeffebd6148a4af0e611dc8b7063b --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_store.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 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 ANI_RDB_STORE_H +#define ANI_RDB_STORE_H + +#include +#include "ani_utils.h" +#include "rdb_store.h" + +namespace OHOS { +namespace RelationalStoreAniKit { + +using namespace OHOS::NativeRdb; + +class RdbStoreProxy : public NativeObject { +public: + std::shared_ptr nativeRdb; +}; +ani_status RdbStoreInit(ani_env *env); + +} // namespace RelationalStoreAniKit +} // namespace OHOS +#endif // ANI_RDB_STORE_H + diff --git a/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_store_helper.h b/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_store_helper.h new file mode 100644 index 0000000000000000000000000000000000000000..a4384c598ba441f19ad2c6f96597f8200c63a83a --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_store_helper.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 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 ANI_RDB_STORE_HELPER_H +#define ANI_RDB_STORE_HELPER_H + +#include +#include + +namespace OHOS { +namespace RelationalStoreAniKit { + +using namespace OHOS::NativeRdb; + +ani_status RdbStoreHelperInit(ani_env *env); + +} // namespace RelationalStoreAniKit +} // namespace OHOS +#endif // ANI_RDB_STORE_HELPER_H + diff --git a/relational_store/frameworks/js/ani/relationalstore/include/ani_result_set.h b/relational_store/frameworks/js/ani/relationalstore/include/ani_result_set.h new file mode 100644 index 0000000000000000000000000000000000000000..6c786f7a02fd6caee037c28aabe57413a6de9048 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/include/ani_result_set.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 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 ANI_RESULT_SET_H +#define ANI_RESULT_SET_H + +#include "ani_utils.h" +#include "rdb_helper.h" + +namespace OHOS { +namespace RelationalStoreAniKit { + +class ResultSetProxy : public NativeObject { +public: + std::shared_ptr resultset; +}; + +ani_status ResultSetInit(ani_env *env); + +} // namespace RelationalStoreAniKit +} // namespace OHOS + +#endif //ANI_RESULT_SET_H + diff --git a/relational_store/frameworks/js/ani/relationalstore/include/ani_utils.h b/relational_store/frameworks/js/ani/relationalstore/include/ani_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..0b29da953d6957ee9c976da9ae124d15ad10dcf6 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/include/ani_utils.h @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2025 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 ANI_UTILS_H +#define ANI_UTILS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class AniObjectUtils { +public: + static ani_object Create(ani_env *env, const char *nsName, const char *clsName, ...) + { + ani_object nullobj{}; + + if (env == nullptr) { + return nullobj; + } + + ani_namespace ns; + if (ANI_OK != env->FindNamespace(nsName, &ns)) { + return nullobj; + } + + ani_class cls; + if (ANI_OK != env->Namespace_FindClass(ns, clsName, &cls)) { + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + return nullobj; + } + return obj; + } + + static ani_object Create(ani_env *env, const char *clsName, ...) + { + ani_object nullobj{}; + + if (env == nullptr) { + return nullobj; + } + + ani_class cls; + if (ANI_OK != env->FindClass(clsName, &cls)) { + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + return nullobj; + } + return obj; + } + + static ani_object Create(ani_env *env, ani_class cls, ...) + { + ani_object nullobj{}; + + if (env == nullptr) { + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, cls); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + return nullobj; + } + return obj; + } + + static ani_status CallObjMethod(ani_env *env, const char *ns, const char *cls, const char *method, ani_object obj) + { + if (env == nullptr) { + return ANI_ERROR; + } + + ani_namespace nameSpace; + auto status = env->FindNamespace(ns, &nameSpace); + if (status != ANI_OK) { + return status; + } + + ani_class clazz; + status = env->Namespace_FindClass(nameSpace, cls, &clazz); + if (status != ANI_OK) { + return status; + } + + ani_method objMethod; + status = env->Class_FindMethod(clazz, method, ":V", &objMethod); + if (status != ANI_OK) { + return status; + } + status = env->Object_CallMethod_Void(obj, objMethod); + return status; + } + + template + static ani_status Wrap(ani_env *env, ani_object object, T *nativePtr, const char *propName = "nativePtr") + { + return env->Object_SetFieldByName_Long(object, propName, reinterpret_cast(nativePtr)); + } + + template + static T* Unwrap(ani_env *env, ani_object object, const char *propName = "nativePtr") + { + ani_long nativePtr; + if (ANI_OK != env->Object_GetFieldByName_Long(object, propName, &nativePtr)) { + return nullptr; + } + return reinterpret_cast(nativePtr); + } +}; + +class AniStringUtils { +public: + static std::string ToStd(ani_env *env, ani_string ani_str) + { + if (env == nullptr) { + return std::string(); + } + + ani_size strSize = 0; + auto status = env->String_GetUTF8Size(ani_str, &strSize); + if (ANI_OK != status) { + return std::string(); + } + + std::vector buffer(strSize + 1); // +1 for null terminator + char *utf8Buffer = buffer.data(); + + // String_GetUTF8 Supportted by https://gitee.com/openharmony/arkcompiler_runtime_core/pulls/3416 + ani_size bytesWritten = 0; + status = env->String_GetUTF8(ani_str, utf8Buffer, strSize + 1, &bytesWritten); + if (ANI_OK != status) { + return std::string(); + } + + utf8Buffer[bytesWritten] = '\0'; + std::string content = std::string(utf8Buffer); + return content; + } + + static ani_string ToAni(ani_env *env, const std::string& str) + { + if (env == nullptr) { + return nullptr; + } + ani_string aniStr = nullptr; + if (ANI_OK != env->String_NewUTF8(str.data(), str.size(), &aniStr)) { + return nullptr; + } + return aniStr; + } +}; + +class UnionAccessor { +public: + UnionAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) + { + if (env == nullptr) { + throw std::runtime_error("env is nullptr"); + } + } + + bool IsInstanceOf(const std::string& cls_name) + { + ani_class cls; + env_->FindClass(cls_name.c_str(), &cls); + + ani_boolean ret; + env_->Object_InstanceOf(obj_, cls, &ret); + return ret; + } + + template + bool IsInstanceOfType(); + + template + bool TryConvert(T &value); + + template + bool TryConvertVariant(std::variant &value) + { + return GetNativeValue(value); + } + + template + bool GetNativeValue(T &value) + { + return false; + } + + template + bool GetNativeValue(T &value) + { + First cValue; + auto ret = TryConvert(cValue); + if (ret == true) { + value = cValue; + return ret; + } + return GetNativeValue(value); + } + + template + bool TryConvertArray(std::vector &value); + + bool GetObjectRefPropertyByName(std::string clsName, const char *name, ani_ref &val); + bool GetObjectStringPropertyByName(std::string clsName, const char *name, std::string &val); + bool GetObjectEnumValuePropertyByName(std::string clsName, const char *name, ani_int &val, bool optional = false); + ani_ref AniIteratorNext(ani_ref interator, bool &isSuccess); + +private: + ani_env *env_; + ani_object obj_; +}; + +class OptionalAccessor { +public: + OptionalAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) + { + if (env == nullptr) { + throw std::runtime_error("env is nullptr"); + } + } + + bool IsUndefined() + { + ani_boolean isUndefined; + env_->Reference_IsUndefined(obj_, &isUndefined); + return isUndefined; + } + + template + std::optional Convert(); + +private: + ani_env *env_; + ani_object obj_; +}; + +class NativeObject { +public: + virtual ~NativeObject() = default; +}; + +ani_status CleanerInit(ani_env *env); +#endif diff --git a/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_entry.cpp b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_entry.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac264374df94c60e298945872c3bb1f5f0d16cf6 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_entry.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2025 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 "AniResultSet" +#include +#include +#include "ani_rdb_predicates.h" +#include "ani_rdb_store_helper.h" +#include "ani_result_set.h" +#include "ani_utils.h" +#include "logger.h" + +using namespace OHOS::Rdb; +using namespace OHOS::RelationalStoreAniKit; + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + if (vm == nullptr) { + LOG_ERROR("vm is nullptr."); + return ANI_ERROR; + } + + ani_env *env; + auto status = vm->GetEnv(ANI_VERSION_1, &env); + if (ANI_OK != status) { + LOG_ERROR("Unsupported ANI_VERSION_1 errcode %{public}d", status); + return ANI_ERROR; + } + + status = ResultSetInit(env); + if (ANI_OK != status) { + LOG_ERROR("ResultSetInit failed errcode %{public}d", status); + return ANI_ERROR; + } + + status = RdbStoreHelperInit(env); + if (ANI_OK != status) { + LOG_ERROR("RdbStoreHelperInit failed errcode %{public}d", status); + return ANI_ERROR; + } + + status = RdbStoreInit(env); + if (ANI_OK != status) { + LOG_ERROR("RdbStoreInit failed errcode %{public}d", status); + return ANI_ERROR; + } + + status = PredicatesInit(env); + if (ANI_OK != status) { + LOG_ERROR("PredicatesInit failed errcode %{public}d", status); + return ANI_ERROR; + } + + status = CleanerInit(env); + if (ANI_OK != status) { + LOG_ERROR("CleanerInit failed errcode %{public}d", status); + return ANI_ERROR; + } + + *result = ANI_VERSION_1; + return ANI_OK; +} + diff --git a/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_error.cpp b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_error.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a9bee4a251f10ca8e520dfae8843574e1d175d0c --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_error.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2025 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 "AniRdbError" +#include "ani_rdb_error.h" +#include "logger.h" + +#include +#include +#include + +namespace OHOS { +namespace RelationalStoreAniKit { +using JsErrorCode = OHOS::RelationalStoreAniKit::JsErrorCode; +using namespace OHOS::Rdb; +static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = { + { E_NOT_STAGE_MODE, 14801001, "Only supported in stage mode." }, + { E_DATA_GROUP_ID_INVALID, 14801002, "The data group id is invalid." }, + { NativeRdb::E_NOT_SELECT, 14800019, "The SQL must be a query statement." }, + { NativeRdb::E_COLUMN_OUT_RANGE, 14800013, "Column out of bounds." }, + { NativeRdb::E_INVALID_FILE_PATH, 14800010, "Invalid database path." }, + { NativeRdb::E_ROW_OUT_RANGE, 14800012, "Row out of bounds." }, + { NativeRdb::E_NO_ROW_IN_QUERY, 14800018, "No data meets the condition." }, + { NativeRdb::E_ALREADY_CLOSED, 14800014, "Already closed." }, + { NativeRdb::E_DATABASE_BUSY, 14800015, "The database does not respond." }, + { NativeRdb::E_WAL_SIZE_OVER_LIMIT, 14800047, "The WAL file size over default limit." }, + { NativeRdb::E_GET_DATAOBSMGRCLIENT_FAIL, 14801050, "Failed to get DataObsMgrClient." }, + { NativeRdb::E_TYPE_MISMATCH, 14800051, "The type of the distributed table does not match." }, + { NativeRdb::E_SQLITE_FULL, 14800029, "SQLite: The database is full." }, + { NativeRdb::E_NOT_SUPPORT_THE_SQL, 14800021, "SQLite: Generic error."}, + { NativeRdb::E_ATTACHED_DATABASE_EXIST, 14800016, "The database is already attached." }, + { NativeRdb::E_SQLITE_ERROR, 14800021, "SQLite: Generic error." }, + { NativeRdb::E_SQLITE_CORRUPT, 14800011, "Database corrupted." }, + { NativeRdb::E_SQLITE_ABORT, 14800022, "SQLite: Callback routine requested an abort." }, + { NativeRdb::E_SQLITE_PERM, 14800023, "SQLite: Access permission denied." }, + { NativeRdb::E_SQLITE_BUSY, 14800024, "SQLite: The database file is locked." }, + { NativeRdb::E_SQLITE_LOCKED, 14800025, "SQLite: A table in the database is locked." }, + { NativeRdb::E_SQLITE_NOMEM, 14800026, "SQLite: The database is out of memory." }, + { NativeRdb::E_SQLITE_READONLY, 14800027, "SQLite: Attempt to write a readonly database." }, + { NativeRdb::E_SQLITE_IOERR, 14800028, "SQLite: Some kind of disk I/O error occurred." }, + { NativeRdb::E_SQLITE_CANTOPEN, 14800030, "SQLite: Unable to open the database file." }, + { NativeRdb::E_SQLITE_TOOBIG, 14800031, "SQLite: TEXT or BLOB exceeds size limit." }, + { NativeRdb::E_SQLITE_CONSTRAINT, 14800032, "SQLite: Abort due to constraint violation." }, + { NativeRdb::E_SQLITE_MISMATCH, 14800033, "SQLite: Data type mismatch." }, + { NativeRdb::E_SQLITE_MISUSE, 14800034, "SQLite: Library used incorrectly." }, + { NativeRdb::E_CONFIG_INVALID_CHANGE, 14800017, "Config changed." }, + { NativeRdb::E_NOT_SUPPORT, 801, "Capability not support." }, +}; + +const std::optional GetJsErrorCode(int32_t errorCode) +{ + auto jsErrorCode = JsErrorCode{ errorCode, -1, "" }; + auto iter = std::lower_bound(JS_ERROR_CODE_MSGS, + JS_ERROR_CODE_MSGS + sizeof(JS_ERROR_CODE_MSGS) / sizeof(JS_ERROR_CODE_MSGS[0]), jsErrorCode, + [](const JsErrorCode &jsErrorCode1, const JsErrorCode &jsErrorCode2) { + return jsErrorCode1.status < jsErrorCode2.status; + }); + if (iter < JS_ERROR_CODE_MSGS + sizeof(JS_ERROR_CODE_MSGS) / sizeof(JS_ERROR_CODE_MSGS[0]) && + iter->status == errorCode) { + return *iter; + } + return std::nullopt; +} + +ani_object CreateBusinessErrorObj(ani_env *env, int32_t code, const std::string &msg) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return nullptr; + } + ani_string message; + auto status = env->String_NewUTF8(msg.c_str(), msg.size(), &message); + if (ANI_OK != status) { + LOG_ERROR("String_NewUTF8 failed, errcode %{public}d.", status); + return nullptr; + } + static const char *businessErrorName = "L@ohos/base/BusinessError;"; + ani_class cls; + status = env->FindClass(businessErrorName, &cls); + if (ANI_OK != status) { + LOG_ERROR("Not found class '%{public}s' errcode %{public}d.", businessErrorName, status); + return nullptr; + } + ani_method ctor; + status = env->Class_FindMethod(cls, "", ":V", &ctor); + if (ANI_OK != status) { + LOG_ERROR("Not found ctor of '%{public}s' errcode %{public}d.", businessErrorName, status); + return nullptr; + } + ani_object businessErrorObject; + status = env->Object_New(cls, ctor, &businessErrorObject); + if (ANI_OK != status) { + LOG_ERROR("Can not create business error errcode %{public}d.", status); + return nullptr; + } + status = env->Object_SetFieldByName_Double(businessErrorObject, "code", code); + if (ANI_OK != status) { + LOG_ERROR("Can not set business error code errcode %{public}d.", status); + return nullptr; + } + status = env->Object_SetPropertyByName_Ref(businessErrorObject, "message", message); + if (ANI_OK != status) { + LOG_ERROR("Can not set business error message errcode %{public}d.", status); + return businessErrorObject; + } + + return businessErrorObject; +} + +ani_object GetAniBusinessError(ani_env *env, int32_t errorCode) +{ + auto errInfo = GetJsErrorCode(errorCode); + auto code_ = E_INNER_ERROR; + auto msg_ = "Inner error. Inner code is " + std::to_string(errorCode % E_INNER_ERROR); + if (errInfo.has_value()) { + auto aniError = errInfo.value(); + code_ = aniError.jsCode; + msg_ = aniError.message; + } + + return CreateBusinessErrorObj(env, code_, msg_); +} + +void ThrowBusinessError(ani_env *env, int32_t status) +{ + if (NativeRdb::E_OK == status) { + return; + } + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return; + } + ani_object businessError = GetAniBusinessError(env, status); + if (nullptr == businessError) { + LOG_ERROR("Can not get business error."); + } else { + auto status = env->ThrowError(static_cast(businessError)); + if (status != ANI_OK) { + LOG_ERROR("ThrowError err %{public}d.", status); + } + } +} + +void ThrowBusinessError(ani_env *env, int32_t status, std::string message) +{ + if (OK == status) { + return; + } + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return; + } + ani_object businessError = CreateBusinessErrorObj(env, status, message); + if (nullptr == businessError) { + LOG_ERROR("Can not get business error."); + } else { + auto status = env->ThrowError(static_cast(businessError)); + if (status != ANI_OK) { + LOG_ERROR("ThrowError err %{public}d.", status); + } + } +} + +} // namespace RelationalStoreAniKit +} // namespace OHOS + diff --git a/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_predicates.cpp b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_predicates.cpp new file mode 100644 index 0000000000000000000000000000000000000000..71bea7e8167b33dc4439a0df0a8d0c6d32ecfa7d --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_predicates.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2025 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 "AniRdbPredicates" +#include +#include +#include + +#include "logger.h" +#include "rdb_errno.h" +#include "ani_utils.h" +#include "ani_rdb_predicates.h" +#include "ani_rdb_error.h" + +namespace OHOS { +namespace RelationalStoreAniKit { + +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; + +void InitNativePredicates(ani_env *env, ani_object object, ani_string tableName) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return; + } + auto proxy = new PredicatesProxy(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr."); + return; + } + auto tname = AniStringUtils::ToStd(env, tableName); + proxy->predicates = std::make_shared(tname); + + ani_status status = env->Object_SetFieldByName_Long(object, "nativePtr", reinterpret_cast(proxy)); + if (ANI_OK != status) { + delete proxy; + LOG_ERROR("[ANI] Failed to set nativePtr to predicates object."); + } +} +ani_status PredicatesInit(ani_env *env) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return ANI_ERROR; + } + + static const char *namespaceName = "L@ohos/data/relationalStore/relationalStore;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(namespaceName, &ns)) { + LOG_ERROR("Not found '%{public}s'", namespaceName); + return ANI_ERROR; + } + + ani_class cls; + const char *className = "LRdbPredicates;"; + if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) { + LOG_ERROR("Not found '%{public}s'", className); + return ANI_ERROR; + } + + std::array methods = { + ani_native_function {"initNativePredicates", nullptr, reinterpret_cast(InitNativePredicates)}, + }; + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + LOG_ERROR("Cannot bind native methods to '%{public}s'", className); + return ANI_ERROR; + } + return ANI_OK; +} + +} // namespace RelationalStoreAniKit +} // namespace OHOS + diff --git a/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_store.cpp b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_store.cpp new file mode 100644 index 0000000000000000000000000000000000000000..946050ca8d09283082c57cce0a6fd9aa3012a627 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_store.cpp @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2025 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 "AniRdbStore" +#include +#include +#include + +#include "logger.h" +#include "rdb_errno.h" +#include "ani_utils.h" +#include "ani_result_set.h" +#include "ani_rdb_error.h" +#include "ani_rdb_store_helper.h" +#include "ani_rdb_predicates.h" +#include "rdb_utils.h" + +namespace OHOS { +namespace RelationalStoreAniKit { + +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; + +bool ConvertBindArgs(ani_env *env, ani_object args, std::vector &bindArgs, bool isOptional) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return false; + } + if (isOptional) { + ani_boolean isUndefined = true; + env->Reference_IsUndefined(args, &isUndefined); + if (isUndefined) { + bindArgs.clear(); + return true; + } + } + std::vector valRefs; + UnionAccessor array2Ref(env, args); + bool convertArrayOk = array2Ref.TryConvert(valRefs); + if (!convertArrayOk) { + LOG_ERROR("conver array fail"); + return false; + } + for (const auto& ref : valRefs) { + ani_object valObject = static_cast(ref); + ValueObject valueObject; + UnionAccessor unionAccessor(env, valObject); + bool convertOk = false; + convertOk = unionAccessor.TryConvertVariant(valueObject.value); + if (convertOk) { + bindArgs.push_back(std::move(valueObject)); + } else { + LOG_ERROR("conver ValueObject fail"); + return false; + } + } + return true; +} + +void ExecuteSqlSync(ani_env *env, ani_object object, ani_string sql, ani_object args) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return; + } + + std::vector bindArgs; + + bool convertOk = ConvertBindArgs(env, args, bindArgs, true); + if (!convertOk) { + LOG_ERROR("args conver fail"); + ThrowBusinessError(env, E_PARAM_ERROR, "Unknown parameters."); + return; + } + + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->nativeRdb == nullptr) { + LOG_ERROR("RdbStore should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized."); + return; + } + auto sqlStr = AniStringUtils::ToStd(env, sql); + auto status = proxy->nativeRdb->ExecuteSql(sqlStr, bindArgs); + ThrowBusinessError(env, status); +} + +void BeginTransaction(ani_env *env, ani_object object) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->nativeRdb == nullptr) { + LOG_ERROR("RdbStore should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized."); + return; + } + auto status = proxy->nativeRdb->BeginTransaction(); + ThrowBusinessError(env, status); +} + +void Commit(ani_env *env, ani_object object) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->nativeRdb == nullptr) { + LOG_ERROR("RdbStore should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized."); + return; + } + auto status = proxy->nativeRdb->Commit(); + ThrowBusinessError(env, status); +} + +void RollBack(ani_env *env, ani_object object) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->nativeRdb == nullptr) { + LOG_ERROR("RdbStore should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized."); + return; + } + auto status = proxy->nativeRdb->RollBack(); + ThrowBusinessError(env, status); +} + +ani_double BatchInsert(ani_env *env, ani_object object, ani_string tableName, ani_object values) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return 0; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->nativeRdb == nullptr) { + LOG_ERROR("RdbStore should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized."); + return 0; + } + auto name = AniStringUtils::ToStd(env, tableName); + std::vector valRefs; + UnionAccessor array2Ref(env, values); + array2Ref.TryConvert(valRefs); + ValuesBuckets vbs; + for (const auto& ref : valRefs) { + ani_object recordObj = static_cast(ref); + UnionAccessor recordAccessor(env, recordObj); + ValuesBucket valuesBucket; + recordAccessor.TryConvert(valuesBucket); + vbs.Put(valuesBucket); + } + auto [status, ret] = proxy->nativeRdb->BatchInsert(name, vbs); + ThrowBusinessError(env, status); + return ret; +} + +ani_double DeleteSync(ani_env *env, ani_object object, ani_object predicates) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return 0; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->nativeRdb == nullptr) { + LOG_ERROR("RdbStore should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized."); + return 0; + } + auto nativePredicates = AniObjectUtils::Unwrap(env, predicates); + if (nativePredicates == nullptr || nativePredicates->predicates == nullptr) { + LOG_ERROR("Predicates should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "Predicates uninitialized."); + return 0; + } + int rows = 0; + auto status = proxy->nativeRdb->Delete(rows, *(nativePredicates->predicates)); + ThrowBusinessError(env, status); + return rows; +} + +ani_double DeleteShareSync(ani_env *env, ani_object object, ani_string tableName, ani_object dataSharePredicates) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return 0; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->nativeRdb == nullptr) { + LOG_ERROR("RdbStore should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized."); + return 0; + } + + std::string name = AniStringUtils::ToStd(env, tableName); + + auto cppDataSharePredicates = AniObjectUtils::Unwrap(env, dataSharePredicates); + if (cppDataSharePredicates == nullptr) { + LOG_ERROR("Predicates should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "Predicates uninitialized."); + return 0; + } + RdbPredicates rdbPredicates = RdbDataShareAdapter::RdbUtils::ToPredicates(*cppDataSharePredicates, name); + int rows = 0; + auto status = proxy->nativeRdb->Delete(rows, rdbPredicates); + ThrowBusinessError(env, status); + return rows; +} + +ani_object QuerySqlSync(ani_env *env, ani_object object, ani_string sql, ani_object args) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return nullptr; + } + std::vector bindArgs; + auto sqlStr = AniStringUtils::ToStd(env, sql); + + if (!ConvertBindArgs(env, args, bindArgs, true)) { + LOG_ERROR("args conver fail"); + return nullptr; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->nativeRdb == nullptr) { + ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized."); + return nullptr; + } + auto resultsetProxy = new ResultSetProxy(); + if (resultsetProxy == nullptr) { + ThrowBusinessError(env, E_INNER_ERROR, "Proxy is nullptr."); + return nullptr; + } + resultsetProxy->resultset = proxy->nativeRdb->QueryByStep(sqlStr, bindArgs); + if (resultsetProxy->resultset == nullptr) { + delete resultsetProxy; + ThrowBusinessError(env, E_INNER_ERROR, "QueryByStep returned nullptr."); + return nullptr; + } + + static const char *namespaceName = "L@ohos/data/relationalStore/relationalStore;"; + static const char *className = "LResultSetInner;"; + static const char *initFinalizer = "initFinalizer"; + ani_object obj = AniObjectUtils::Create(env, namespaceName, className); + if (nullptr == obj) { + delete resultsetProxy; + ThrowBusinessError(env, E_INNER_ERROR, "Create ResultSet failed.class: LResultSetInner;"); + return nullptr; + } + ani_status status = AniObjectUtils::Wrap(env, obj, resultsetProxy); + if (ANI_OK != status) { + delete resultsetProxy; + ThrowBusinessError(env, E_INNER_ERROR, "Wrap ResultSet failed.class: LResultSetInner;"); + return nullptr; + } + status = AniObjectUtils::CallObjMethod(env, namespaceName, className, initFinalizer, obj); + if (ANI_OK != status) { + ThrowBusinessError(env, E_INNER_ERROR, "init ResultSet finalizer failed.class: LResultSetInner;"); + return nullptr; + } + return obj; +} + +ani_status RdbStoreInit(ani_env *env) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return ANI_ERROR; + } + static const char *namespaceName = "L@ohos/data/relationalStore/relationalStore;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(namespaceName, &ns)) { + LOG_ERROR("Not found '%{public}s'", namespaceName); + return ANI_ERROR; + } + + static const char *clsName = "LRdbStoreInner;"; + ani_class cls; + if (ANI_OK != env->Namespace_FindClass(ns, clsName, &cls)) { + LOG_ERROR("Not found '%{public}s'", clsName); + return ANI_ERROR; + } + + std::array methods = { + ani_native_function {"batchInsertSync", nullptr, reinterpret_cast(BatchInsert)}, + ani_native_function {"beginTransaction", nullptr, reinterpret_cast(BeginTransaction)}, + ani_native_function {"commit", ":V", reinterpret_cast(Commit)}, + ani_native_function {"rollBack", nullptr, reinterpret_cast(RollBack)}, + ani_native_function {"executeSqlSync", nullptr, reinterpret_cast(ExecuteSqlSync)}, + ani_native_function {"deleteSync", nullptr, reinterpret_cast(DeleteSync)}, + ani_native_function {"deleteShareSync", nullptr, reinterpret_cast(DeleteShareSync)}, + ani_native_function {"querySqlSync", nullptr, reinterpret_cast(QuerySqlSync)}, + }; + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + LOG_ERROR("Cannot bind native methods to '%{public}s'", clsName); + return ANI_ERROR; + } + return ANI_OK; +} + + +} // namespace RelationalStoreAniKit +} // namespace OHOS + diff --git a/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_store_helper.cpp b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_store_helper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ef5a953216b75fb34b0b8751763f694d7d93bedd --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_store_helper.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2025 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 "AniRdbStoreHelper" +#include +#include +#include + +#include "logger.h" +#include "rdb_errno.h" +#include "ani_utils.h" +#include "ani_result_set.h" +#include "ani_rdb_error.h" +#include "ani_rdb_store_helper.h" +#include "rdb_sql_utils.h" + +namespace OHOS { +namespace RelationalStoreAniKit { + +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; + +class DefaultOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &rdbStore) override + { + return E_OK; + } + int OnUpgrade(RdbStore &rdbStore, int oldVersion, int newVersion) override + { + return E_OK; + } +}; + +static ani_object GetRdbStoreSync([[maybe_unused]] ani_env *env, ani_object context, ani_object config) +{ + DefaultOpenCallback callback; + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return nullptr; + } + int errCode = OK; + auto proxy = new RdbStoreProxy(); + if (proxy == nullptr) { + LOG_ERROR("new RdbStoreProxy failed."); + return nullptr; + } + int errorCode = RdbSqlUtils::CreateDirectory("/data/storage/el2/database/rdb"); + if (errorCode != E_OK) { + delete proxy; + ThrowBusinessError(env, E_INNER_ERROR, "CreateDirectory failed."); + return nullptr; + } + auto rdbConfig = RdbStoreConfig("/data/storage/el2/database/rdb/test.db"); + proxy->nativeRdb = RdbHelper::GetRdbStore(rdbConfig, -1, callback, errCode); + if (proxy->nativeRdb == nullptr) { + delete proxy; + ThrowBusinessError(env, E_INNER_ERROR, "RdbHelper returned nullptr."); + return nullptr; + } + static const char *namespaceName = "L@ohos/data/relationalStore/relationalStore;"; + static const char *className = "LRdbStoreInner;"; + static const char *initFinalizer = "initFinalizer"; + ani_object obj = AniObjectUtils::Create(env, namespaceName, className); + if (nullptr == obj) { + delete proxy; + LOG_ERROR("[ANI] Failed to create class '%{public}s' obj", className); + ThrowBusinessError(env, E_INNER_ERROR, "ANI create class."); + return nullptr; + } + ani_status status = AniObjectUtils::Wrap(env, obj, proxy); + if (ANI_OK != status) { + delete proxy; + LOG_ERROR("[ANI] Failed to wrap for class '%{public}s'", className); + ThrowBusinessError(env, E_INNER_ERROR, "ANI SetField."); + return nullptr; + } + status = AniObjectUtils::CallObjMethod(env, namespaceName, className, initFinalizer, obj); + if (ANI_OK != status) { + LOG_ERROR("[ANI] Failed to initFinalizer for class '%{public}s'.", className); + ThrowBusinessError(env, E_INNER_ERROR, "init rdbStore finalizer failed."); + return nullptr; + } + return obj; +} + +ani_status RdbStoreHelperInit(ani_env *env) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return ANI_ERROR; + } + + static const char *namespaceName = "L@ohos/data/relationalStore/relationalStore;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(namespaceName, &ns)) { + LOG_ERROR("Not found '%{public}s'", namespaceName); + return ANI_ERROR; + } + + std::array functions = { + ani_native_function {"getRdbStoreSync", nullptr, reinterpret_cast(GetRdbStoreSync)}, + }; + if (ANI_OK != env->Namespace_BindNativeFunctions(ns, functions.data(), functions.size())) { + LOG_ERROR("Cannot bind native functions to '%{public}s'", namespaceName); + return ANI_ERROR; + } + return ANI_OK; +} + +} // namespace RelationalStoreAniKit +} // namespace OHOS + diff --git a/relational_store/frameworks/js/ani/relationalstore/src/ani_result_set.cpp b/relational_store/frameworks/js/ani/relationalstore/src/ani_result_set.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b1391d5227fbce91e42da93c979a68831472a67a --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/src/ani_result_set.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2025 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 "AniResultSet" +#include +#include +#include + +#include "logger.h" +#include "rdb_errno.h" +#include "ani_utils.h" +#include "ani_result_set.h" +#include "ani_rdb_error.h" + +namespace OHOS { +namespace RelationalStoreAniKit { + +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; + +ani_double GetColumnIndex(ani_env *env, ani_object object, ani_string col_name) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return 0; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->resultset == nullptr) { + LOG_ERROR("ResultSet should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "ResultSet uninitialized."); + return 0; + } + auto name = AniStringUtils::ToStd(env, col_name); + int index; + auto status = proxy->resultset->GetColumnIndex(name, index); + ThrowBusinessError(env, status); + return index; +} + +ani_double GetLong(ani_env *env, ani_object object, ani_double index) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return 0; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->resultset == nullptr) { + LOG_ERROR("ResultSet should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "ResultSet uninitialized."); + return 0; + } + int64_t ret; + auto status = proxy->resultset->GetLong(index, ret); + ThrowBusinessError(env, status); + return ret; +} + +ani_string GetString(ani_env *env, ani_object object, ani_double index) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return nullptr; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->resultset == nullptr) { + LOG_ERROR("ResultSet should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "ResultSet uninitialized."); + return nullptr; + } + std::string ret; + auto status = proxy->resultset->GetString(index, ret); + ThrowBusinessError(env, status); + ani_string retStr; + env->String_NewUTF8(ret.c_str(), ret.size(), &retStr); + return retStr; +} + +ani_boolean GoToFirstRow(ani_env *env, ani_object object) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return false; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->resultset == nullptr) { + LOG_ERROR("ResultSet should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "ResultSet uninitialized."); + return false; + } + auto status = proxy->resultset->GoToFirstRow(); + return (status == ANI_OK); +} + +ani_status ResultSetInit(ani_env *env) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return ANI_ERROR; + } + static const char *namespaceName = "L@ohos/data/relationalStore/relationalStore;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(namespaceName, &ns)) { + LOG_ERROR("Not found '%{public}s", namespaceName); + return ANI_ERROR; + } + + ani_class cls; + const char *className = "LResultSetInner;"; + if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) { + LOG_ERROR("Not found '%{public}s", className); + return ANI_ERROR; + } + + std::array methods = { + ani_native_function {"getColumnIndex", nullptr, reinterpret_cast(GetColumnIndex)}, + ani_native_function {"getLong", nullptr, reinterpret_cast(GetLong)}, + ani_native_function {"getString", nullptr, reinterpret_cast(GetString)}, + ani_native_function {"goToFirstRow", nullptr, reinterpret_cast(GoToFirstRow)}, + }; + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + LOG_ERROR("Cannot bind native methods to '%{public}s", className); + return ANI_ERROR; + } + return ANI_OK; +} + +} // namespace RelationalStoreAniKit +} // namespace OHOS + diff --git a/relational_store/frameworks/js/ani/relationalstore/src/ani_utils.cpp b/relational_store/frameworks/js/ani/relationalstore/src/ani_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c1842608862a1fd820cbfe3a844b3f57bc700a6 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/src/ani_utils.cpp @@ -0,0 +1,636 @@ +/* + * Copyright (c) 2025 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 "AniUtils" +#include "ani_utils.h" +#include "asset_value.h" +#include "big_integer.h" +#include "values_bucket.h" +#include "logger.h" + +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; + + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Boolean;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Int;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Double;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/String;"); +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_GetPropertyByName_Ref failed"); + return false; + } + value.push_back(ref); + } + LOG_DEBUG("convert ref array ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_GetPropertyByName_Ref failed"); + return false; + } + ani_boolean val; + if (ANI_OK != env_->Object_CallMethodByName_Boolean(static_cast(ref), "unboxed", nullptr, &val)) { + LOG_ERROR("Object_CallMethodByName_Boolean unbox failed"); + return false; + } + value.push_back(static_cast(val)); + } + LOG_DEBUG("convert bool array ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_GetPropertyByName_Ref failed"); + return false; + } + ani_int intValue; + if (ANI_OK != env_->Object_CallMethodByName_Int(static_cast(ref), "unboxed", nullptr, &intValue)) { + LOG_ERROR("Object_CallMethodByName_Int unbox failed"); + return false; + } + value.push_back(static_cast(intValue)); + } + LOG_DEBUG("convert int array ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_GetPropertyByName_Ref failed"); + return false; + } + ani_double val; + if (ANI_OK != env_->Object_CallMethodByName_Double(static_cast(ref), "unboxed", nullptr, &val)) { + LOG_ERROR("Object_CallMethodByName_Double unbox failed"); + return false; + } + value.push_back(static_cast(val)); + } + LOG_DEBUG("convert double array ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_ref buffer; + if (ANI_OK != env_->Object_GetFieldByName_Ref(obj_, "buffer", &buffer)) { + LOG_ERROR("Object_GetFieldByName_Ref failed"); + return false; + } + void* data; + size_t size; + if (ANI_OK != env_->ArrayBuffer_GetInfo(static_cast(buffer), &data, &size)) { + LOG_ERROR("ArrayBuffer_GetInfo failed"); + return false; + } + for (size_t i = 0; i < size; i++) { + value.push_back(static_cast(data)[i]); + } + LOG_DEBUG("convert uint8 array ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_ref buffer; + if (ANI_OK != env_->Object_GetFieldByName_Ref(obj_, "buffer", &buffer)) { + LOG_ERROR("Object_GetFieldByName_Ref failed"); + return false; + } + void* data; + size_t size; + if (ANI_OK != env_->ArrayBuffer_GetInfo(static_cast(buffer), &data, &size)) { + LOG_ERROR("ArrayBuffer_GetInfo failed"); + return false; + } + auto count = size / sizeof(float); + for (size_t i = 0; i < count; i++) { + value.push_back(static_cast(data)[i]); + } + LOG_DEBUG("convert float array ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_CallMethodByName_Ref failed"); + return false; + } + value.push_back(AniStringUtils::ToStd(env_, static_cast(ref))); + } + LOG_DEBUG("convert string array ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvert(int &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_int aniValue; + auto ret = env_->Object_CallMethodByName_Int(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast(aniValue); + LOG_DEBUG("convert int ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvert(std::monostate &value) +{ + ani_boolean isNull = false; + auto status = env_->Reference_IsNull(static_cast(obj_), &isNull); + if (ANI_OK == status) { + if (isNull) { + value = std::monostate(); + LOG_DEBUG("convert null ok."); + return true; + } + } + return false; +} + +template<> +bool UnionAccessor::TryConvert(int64_t &value) +{ + return false; +} + +template<> +bool UnionAccessor::TryConvert(double &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast(aniValue); + LOG_DEBUG("convert double ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvert(std::string &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + value = AniStringUtils::ToStd(env_, static_cast(obj_)); + LOG_DEBUG("convert string ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvert(bool &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_boolean aniValue; + auto ret = env_->Object_CallMethodByName_Boolean(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast(aniValue); + LOG_DEBUG("convert bool ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvert>(std::vector &value) +{ + if (!IsInstanceOf("Lescompat/Uint8Array;")) { + return false; + } + return TryConvertArray(value); +} + +bool UnionAccessor::GetObjectRefPropertyByName(std::string clsName, const char *name, ani_ref &val) +{ + ani_class cls; + env_->FindClass(clsName.c_str(), &cls); + ani_method getter; + if (ANI_OK != env_->Class_FindGetter(cls, name, &getter)) { + LOG_ERROR("GetObjectRefPropertyByName Class_FindGetter failed"); + return false; + } + ani_ref ref; + if (ANI_OK != env_->Object_CallMethod_Ref(obj_, getter, &ref)) { + LOG_ERROR("GetObjectRefPropertyByName Object_CallMethod_Ref failed"); + return false; + } + val = ref; + return true; +} + +bool UnionAccessor::GetObjectStringPropertyByName(std::string clsName, const char *name, std::string &val) +{ + ani_ref ref; + auto isOk = GetObjectRefPropertyByName(clsName, name, ref); + if (!isOk) { + LOG_ERROR("GetObjectRefPropertyByName failed"); + return false; + } + val = AniStringUtils::ToStd(env_, static_cast(ref)); + return true; +} + +bool UnionAccessor::GetObjectEnumValuePropertyByName( + std::string clsName, const char *name, ani_int &val, bool optional) +{ + ani_ref ref; + auto isOk = GetObjectRefPropertyByName(clsName, name, ref); + if (!isOk) { + LOG_ERROR("GetObjectRefPropertyByName failed"); + return false; + } + if (optional) { + ani_boolean isUndefined; + auto err = env_->Reference_IsUndefined(ref, &isUndefined); + if (err != ANI_OK) { + LOG_ERROR("Reference_IsUndefined fail."); + return false; + } + if (isUndefined) { + LOG_DEBUG("Optional enum item undefined."); + return true; + } + } + ani_int enumValue; + auto status = env_->EnumItem_GetValue_Int(static_cast(ref), &enumValue); + if (status != ANI_OK) { + LOG_ERROR("EnumItem_GetValue_Int failed"); + return false; + } + val = enumValue; + return true; +} + +template<> +bool UnionAccessor::TryConvert(AssetValue &value) +{ + std::string clsName = "L@ohos/data/relationalStore/relationalStore/Asset;"; + if (!IsInstanceOf(clsName)) { + return false; + } + auto isOk = GetObjectStringPropertyByName(clsName, "name", value.name); + if (!isOk) { + return false; + } + isOk = GetObjectStringPropertyByName(clsName, "uri", value.uri); + if (!isOk) { + return false; + } + isOk = GetObjectStringPropertyByName(clsName, "path", value.path); + if (!isOk) { + return false; + } + isOk = GetObjectStringPropertyByName(clsName, "createTime", value.createTime); + if (!isOk) { + return false; + } + isOk = GetObjectStringPropertyByName(clsName, "modifyTime", value.modifyTime); + if (!isOk) { + return false; + } + isOk = GetObjectStringPropertyByName(clsName, "size", value.size); + if (!isOk) { + return false; + } + ani_int enumVal = 0; + isOk = GetObjectEnumValuePropertyByName(clsName, "status", enumVal, true); + if (!isOk) { + return false; + } + value.status = static_cast(enumVal); + if (value.status != AssetValue::STATUS_DELETE) { + value.status = AssetValue::STATUS_UNKNOWN; + } + value.hash = value.modifyTime + "_" + value.size; + LOG_DEBUG("convert asset ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvert>(std::vector &value) +{ + std::string clsName = "[L@ohos/data/relationalStore/relationalStore/Asset;"; + if (!IsInstanceOf(clsName)) { + return false; + } + ani_size arrayLength; + auto status = env_->Array_GetLength(static_cast(obj_), &arrayLength); + if (status != ANI_OK) { + LOG_ERROR("Array_GetLength failed"); + return false; + } + for (int i = 0; i < int(arrayLength); i++) { + ani_ref result; + status = env_->Array_Get_Ref(static_cast(obj_), i, &result); + if (status != ANI_OK) { + LOG_ERROR("Array_Get_Ref failed"); + return false; + } + ani_object asset = static_cast(result); + UnionAccessor sub(env_, asset); + AssetValue val; + auto isOk = sub.TryConvert(val); + if (!isOk) { + return false; + } + value.push_back(val); + } + LOG_DEBUG("convert assets ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvert>(std::vector &value) +{ + if (!IsInstanceOf("Lescompat/Float32Array;")) { + return false; + } + return TryConvertArray(value); +} + +template<> +bool UnionAccessor::TryConvert(BigInteger &value) +{ + std::string clsName = "Lescompat/BigInt;"; + ani_class cls; + auto status = env_->FindClass(clsName.c_str(), &cls); + if (status != ANI_OK) { + LOG_ERROR("FindClass failed"); + return false; + } + + ani_boolean ret; + env_->Object_InstanceOf(obj_, cls, &ret); + if (!ret) { + return false; + } + + ani_method getLongMethod; + if (ANI_OK != env_->Class_FindMethod(cls, "getLong", ":J", &getLongMethod)) { + LOG_ERROR("Class_FindMethod failed"); + return false; + } + + ani_long longNum; + if (ANI_OK != env_->Object_CallMethod_Long(obj_, getLongMethod, &longNum)) { + LOG_ERROR("Object_CallMethod_Long failed"); + return false; + } + value = BigInteger(longNum); + LOG_DEBUG("convert bigint ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvert>(std::vector &value) +{ + if (!IsInstanceOf("Lescompat/Array;")) { + return false; + } + return TryConvertArray(value); +} + +ani_ref UnionAccessor::AniIteratorNext(ani_ref interator, bool &isSuccess) +{ + ani_ref next; + ani_boolean done; + if (ANI_OK != env_->Object_CallMethodByName_Ref(static_cast(interator), "next", nullptr, &next)) { + LOG_ERROR("Failed to get next key"); + isSuccess = false; + return nullptr; + } + + if (ANI_OK != env_->Object_GetFieldByName_Boolean(static_cast(next), "done", &done)) { + LOG_ERROR("Failed to check iterator done"); + isSuccess = false; + return nullptr; + } + if (done) { + return nullptr; + } + return next; +} + +template<> +bool UnionAccessor::TryConvert(ValuesBucket &value) +{ + if (!IsInstanceOf("Lescompat/Record;")) { + return false; + } + ani_ref keys; + auto status = env_->Object_CallMethodByName_Ref(obj_, "keys", ":Lescompat/IterableIterator;", &keys); + if (status != ANI_OK) { + LOG_ERROR("Object_CallMethodByName_Ref failed"); + } + bool success = true; + ani_ref next = AniIteratorNext(keys, success); + while (next) { + ani_ref key_value; + if (ANI_OK != env_->Object_GetFieldByName_Ref(static_cast(next), "value", &key_value)) { + LOG_ERROR("Failed to get key value"); + success = false; + break; + } + + ani_ref valueObj; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", nullptr, &valueObj, key_value)) { + LOG_ERROR("Failed to get value for key"); + success = false; + break; + } + ani_object recordValue = static_cast(valueObj); + UnionAccessor sub(env_, recordValue); + ValueObject val; + success = sub.TryConvertVariant(val.value); + if (success) { + value.Put(AniStringUtils::ToStd(env_, static_cast(key_value)), val); + } else { + LOG_ERROR("Failed to convert AssetValue"); + break; + } + next = AniIteratorNext(keys, success); + } + return success; +} + +template<> +std::optional OptionalAccessor::Convert() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "doubleValue", nullptr, &aniValue); + if (ret != ANI_OK) { + return std::nullopt; + } + auto value = static_cast(aniValue); + return value; +} + +template<> +std::optional OptionalAccessor::Convert() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_size strSize; + env_->String_GetUTF8Size(static_cast(obj_), &strSize); + + std::vector buffer(strSize + 1); + char* utf8_buffer = buffer.data(); + + ani_size bytes_written = 0; + env_->String_GetUTF8(static_cast(obj_), utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + return content; +} + +static void CleanNativePtr(ani_env *env, ani_object object) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return; + } + ani_long ptr = 0; + if (ANI_OK != env->Object_GetFieldByName_Long(object, "targetPtr", &ptr)) { + LOG_ERROR("Can not get targetPtr."); + return; + } + delete reinterpret_cast(ptr); +} + +ani_status CleanerInit(ani_env *env) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return ANI_ERROR; + } + + static const char *namespaceName = "L@ohos/data/relationalStore/relationalStore;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(namespaceName, &ns)) { + LOG_ERROR("Not found '%{public}s", namespaceName); + return ANI_ERROR; + } + + ani_class cls; + const char *className = "LCleaner;"; + if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) { + LOG_ERROR("Not found '%{public}s", className); + return ANI_ERROR; + } + + std::array methods = { + ani_native_function {"clean", nullptr, reinterpret_cast(CleanNativePtr)}, + }; + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + LOG_ERROR("Cannot bind native methods to '%{public}s", className); + return ANI_ERROR; + } + return ANI_OK; +} diff --git a/relational_store/frameworks/js/napi/cloud_data/BUILD.gn b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn index b9ffc946da2a48976bb806adc5344cff93d6aebc..ab1021d642ebac84ef7a0d4b04dd89ca1846060c 100644 --- a/relational_store/frameworks/js/napi/cloud_data/BUILD.gn +++ b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn @@ -32,18 +32,19 @@ ohos_shared_library("clouddata") { "${cloud_data_napi_path}/src/js_error_utils.cpp", "${cloud_data_napi_path}/src/napi_queue.cpp", "${cloud_data_native_path}/src/cloud_manager.cpp", + "${cloud_data_native_path}/src/cloud_notifier_stub.cpp", "${cloud_data_native_path}/src/cloud_service_proxy.cpp", "${cloud_data_native_path}/src/cloud_types_util.cpp", "${relational_store_napi_path}/common/src/js_df_manager.cpp", + "${relational_store_napi_path}/common/src/js_scope.cpp", "${relational_store_napi_path}/common/src/js_utils.cpp", + "${relational_store_napi_path}/common/src/js_uv_queue.cpp", ] include_dirs = [ "include", "${relational_store_js_common_path}/include", "${cloud_data_native_path}/include", - "${datashare_path}/provider/include", - "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_innerapi_path}/rdb/include", "${relational_store_innerapi_path}/cloud_data/include", @@ -58,9 +59,12 @@ ohos_shared_library("clouddata") { "ability_runtime:abilitykit_native", "ability_runtime:napi_base_context", "c_utils:utils", + "data_share:datashare_common_lite", + "eventhandler:libeventhandler", "hilog:libhilog", "hitrace:hitrace_meter", "ipc:ipc_core", + "kv_store:datamgr_common", "napi:ace_napi", "samgr:samgr_proxy", ] diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_utils.h b/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_utils.h index ca8651c4660cab49c7510e5f14ac840c8b2ab610..9c3b16c1f88c1ac285bcb83706377969208fa6f0 100644 --- a/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_utils.h +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_utils.h @@ -65,6 +65,15 @@ napi_value Convert2JSValue(napi_env env, const StatisticInfo &value); template<> napi_value Convert2JSValue(napi_env env, const CloudSyncInfo &value); + +template<> +napi_value Convert2JSValue(napi_env env, const DistributedRdb::Statistic &value); + +template<> +napi_value Convert2JSValue(napi_env env, const DistributedRdb::TableDetail &value); + +template<> +napi_value Convert2JSValue(napi_env env, const DistributedRdb::ProgressDetail &value); }; // namespace JSUtils } // namespace OHOS::AppDataMgrJsKit #endif // CLOUD_DATA_JS_CLOUD_UTILS_H \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_config.h b/relational_store/frameworks/js/napi/cloud_data/include/js_config.h index f299f1e6729656055d59b42729a119e123cea9ea..6d36cb98c1b43bdc206e61d3f2dc484bfcb522fa 100644 --- a/relational_store/frameworks/js/napi/cloud_data/include/js_config.h +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_config.h @@ -18,8 +18,11 @@ #include "cloud_manager.h" #include "js_const_properties.h" +#include "js_uv_queue.h" +#include "napi_queue.h" namespace OHOS::CloudData { +using namespace OHOS::AppDataMgrJsKit; class JsConfig { public: JsConfig(); @@ -56,6 +59,18 @@ public: static napi_value QueryStatistics(napi_env env, napi_callback_info info); static napi_value SetGlobalCloudStrategy(napi_env env, napi_callback_info info); static napi_value QueryLastSyncInfo(napi_env env, napi_callback_info info); + static napi_value CloudSync(napi_env env, napi_callback_info info); +private: + struct CloudSyncContext : public ContextBase { + std::string bundleName; + std::string storeId; + int32_t syncMode; + napi_ref asyncHolder = nullptr; + std::shared_ptr queue; + }; + static void HandleCloudSyncArgs(napi_env env, napi_callback_info info, std::shared_ptr ctxt); + static uint32_t GetSeqNum(); + static std::atomic seqNum_; }; } // namespace OHOS::CloudData diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_utils.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_utils.cpp index 722e1b588f01c8f7513dd1f88496140b7d81da99..df2b86966ff0a1c5f0da7247950b01ccb32bf586 100644 --- a/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_utils.cpp +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_utils.cpp @@ -269,5 +269,50 @@ napi_value Convert2JSValue(napi_env env, const CloudSyncInfo &value) napi_set_named_property(env, jsValue, "syncStatus", Convert2JSValue(env, value.syncStatus)); return jsValue; } + +template<> +napi_value Convert2JSValue(napi_env env, const DistributedRdb::Statistic &value) +{ + std::vector descriptors = { + DECLARE_JS_PROPERTY(env, "total", value.total), + DECLARE_JS_PROPERTY(env, "success", value.success), + DECLARE_JS_PROPERTY(env, "successful", value.success), + DECLARE_JS_PROPERTY(env, "failed", value.failed), + DECLARE_JS_PROPERTY(env, "remained", value.untreated), + }; + napi_value object = nullptr; + NAPI_CALL_RETURN_ERR( + napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); + return object; +} + +template<> +napi_value Convert2JSValue(napi_env env, const DistributedRdb::TableDetail &value) +{ + std::vector descriptors = { + DECLARE_JS_PROPERTY(env, "upload", value.upload), + DECLARE_JS_PROPERTY(env, "download", value.download), + }; + + napi_value object = nullptr; + NAPI_CALL_RETURN_ERR( + napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); + return object; +} + +template<> +napi_value Convert2JSValue(napi_env env, const DistributedRdb::ProgressDetail &value) +{ + std::vector descriptors = { + DECLARE_JS_PROPERTY(env, "schedule", value.progress), + DECLARE_JS_PROPERTY(env, "code", value.code), + DECLARE_JS_PROPERTY(env, "details", value.details), + }; + + napi_value object = nullptr; + NAPI_CALL_RETURN_ERR( + napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); + return object; +} }; // namespace JSUtils } // namespace OHOS::AppDataMgrJsKit diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp index b840645dd7f727e2cc069805f68209025602ab37..30686bd32411cce589fb88b8a5ffbe7a53fbadf9 100644 --- a/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp @@ -26,11 +26,10 @@ #include "js_strategy_context.h" #include "js_utils.h" #include "logger.h" -#include "napi_queue.h" using namespace OHOS::Rdb; using namespace OHOS::CloudData; -using namespace OHOS::AppDataMgrJsKit; +std::atomic JsConfig::seqNum_{}; JsConfig::JsConfig() { } @@ -435,6 +434,10 @@ napi_value JsConfig::New(napi_env env, napi_callback_info info) } auto finalize = [](napi_env env, void *data, void *hint) { + if (data == nullptr) { + LOG_ERROR("data is nullptr."); + return; + } auto tid = JSDFManager::GetInstance().GetFreedTid(data); if (tid != 0) { LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); @@ -510,6 +513,97 @@ napi_value JsConfig::QueryLastSyncInfo(napi_env env, napi_callback_info info) return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); } +void JsConfig::HandleCloudSyncArgs(napi_env env, napi_callback_info info, std::shared_ptr ctxt) +{ + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { + // less required 4 arguments :: + ASSERT_BUSINESS_ERR(ctxt, argc >= 4, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + // 0 is the index of argument bundleName + int status = JSUtils::Convert2Value(env, argv[0], ctxt->bundleName); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, + "The type of bundleName must be string and not empty."); + // 1 is the index of argument storeId + status = JSUtils::Convert2Value(env, argv[1], ctxt->storeId); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, + "The type of storeId must be string and not empty."); + // 2 is the index of argument syncMode + status = JSUtils::Convert2ValueExt(env, argv[2], ctxt->syncMode); + ASSERT_BUSINESS_ERR( + ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of syncMode must be number."); + // 3 is the index of argument progress, it should be a founction + napi_valuetype valueType = napi_undefined; + napi_status ret = napi_typeof(env, argv[3], &valueType); + ASSERT_BUSINESS_ERR( + ctxt, ret == napi_ok && valueType == napi_function, Status::INVALID_ARGUMENT, + "The type of progress should be function."); + ASSERT_BUSINESS_ERR( + ctxt, napi_create_reference(env, argv[3], 1, &ctxt->asyncHolder) == napi_ok, // 3 means the progress + Status::INVALID_ARGUMENT, "create refrence failed."); + }, true); +} + +/* + * [JS API Prototype] + * [Promise] + * cloudSync(bundleName: string, storeId: string, mode: relationalStore.SyncMode, + * progress: Callback: Promise; + */ +napi_value JsConfig::CloudSync(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + ctxt->queue = std::make_shared(env); + HandleCloudSyncArgs(env, info, ctxt); + ASSERT_NULL(!ctxt->isThrowError, "CloudSync exit"); + + auto execute = [ctxt]() { + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (proxy == nullptr) { + if (state != CloudService::SERVER_UNAVAILABLE) { + state = CloudService::NOT_SUPPORT; + } + ctxt->status = (GenerateNapiError(state, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + return; + } + auto async = [ctxt, queue = ctxt->queue, cb = ctxt->asyncHolder](const DistributedRdb::Details &details) { + if (queue == nullptr || cb == nullptr) { + return; + } + bool repeate = !details.empty() && details.begin()->second.progress != DistributedRdb::SYNC_FINISH; + queue->AsyncCallInOrder({ cb, repeate }, [details](napi_env env, int &argc, napi_value *argv) -> void { + argc = 1; + argv[0] = details.empty() ? nullptr : JSUtils::Convert2JSValue(env, details.begin()->second); + }); + }; + CloudService::Option option; + option.syncMode = ctxt->syncMode; + option.seqNum = GetSeqNum(); + auto status = proxy->CloudSync(ctxt->bundleName, ctxt->storeId, option, async); + if (status == Status::INVALID_ARGUMENT) { + status = Status::INVALID_ARGUMENT_V20; + } + ctxt->status = + (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; + }; + auto output = [env, ctxt](napi_value &result) { + if (ctxt->status != napi_ok && ctxt->asyncHolder != nullptr) { + napi_delete_reference(env, ctxt->asyncHolder); + } + napi_get_undefined(env, &result); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +uint32_t JsConfig::GetSeqNum() +{ + uint32_t value = ++seqNum_; + if (value == 0) { + value = ++seqNum_; + } + return value; +} + napi_value JsConfig::InitConfig(napi_env env, napi_value exports) { auto lambda = []() -> std::vector { @@ -523,6 +617,7 @@ napi_value JsConfig::InitConfig(napi_env env, napi_value exports) DECLARE_NAPI_STATIC_FUNCTION("queryStatistics", JsConfig::QueryStatistics), DECLARE_NAPI_STATIC_FUNCTION("setGlobalCloudStrategy", JsConfig::SetGlobalCloudStrategy), DECLARE_NAPI_STATIC_FUNCTION("queryLastSyncInfo", JsConfig::QueryLastSyncInfo), + DECLARE_NAPI_STATIC_FUNCTION("cloudSync", JsConfig::CloudSync), }; return properties; }; diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_error_utils.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_error_utils.cpp index 5445becc611319238fd5589690b5bb7dea98744e..c99cac0d7423a73b19520a14db5672a9d44b7a9e 100644 --- a/relational_store/frameworks/js/napi/cloud_data/src/js_error_utils.cpp +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_error_utils.cpp @@ -27,7 +27,8 @@ static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = { { Status::INVALID_ARGUMENT, 401, "Parameter error." }, { Status::NOT_SUPPORT, 801, "Not support." }, { Status::PERMISSION_DENIED, 202, "Permission denied, non-system app called system api." }, - { Status::CLOUD_CONFIG_PERMISSION_DENIED, 201, "Permission denied." } + { Status::CLOUD_CONFIG_PERMISSION_DENIED, 201, "Permission denied." }, + { Status::INVALID_ARGUMENT_V20, 14800001, "Invalid args." } }; const std::optional GetJsErrorCode(int32_t errorCode) diff --git a/relational_store/frameworks/js/napi/cloud_extension/BUILD.gn b/relational_store/frameworks/js/napi/cloud_extension/BUILD.gn index 93e7217a1497a9fa53ad3a8b753dd89b29cfbf8f..572bbab8f25e9571c20fd92f5781dc94808372ee 100644 --- a/relational_store/frameworks/js/napi/cloud_extension/BUILD.gn +++ b/relational_store/frameworks/js/napi/cloud_extension/BUILD.gn @@ -13,7 +13,6 @@ import("//build/config/components/ets_frontend/es2abc_config.gni") import("//build/ohos.gni") -import("//foundation/arkui/ace_engine/ace_config.gni") es2abc_gen_abc("gen_cloud_extension_abc") { src_js = rebase_path("cloud_extension_stub.js") diff --git a/relational_store/frameworks/js/napi/common/include/js_uv_queue.h b/relational_store/frameworks/js/napi/common/include/js_uv_queue.h index c99ff5ca8b8bcc6d33413ab95b249728737d5be4..71de0ece9674298a980f7f5c37d1b10f998e92c5 100644 --- a/relational_store/frameworks/js/napi/common/include/js_uv_queue.h +++ b/relational_store/frameworks/js/napi/common/include/js_uv_queue.h @@ -71,10 +71,7 @@ private: static napi_value Resolved(napi_env env, napi_callback_info info); static napi_value Rejected(napi_env env, napi_callback_info info); static napi_value Future(napi_env env, napi_callback_info info, bool exception); - static void DoWork(uv_work_t *work); static void DoExecute(uv_work_t *work); - static void DoUvCallback(uv_work_t *work, int status); - static void DoUvPromise(uv_work_t *work, int status); struct UvEntry { napi_env env_ = nullptr; @@ -93,9 +90,8 @@ private: Result *StealResult(); int32_t GetArgv(napi_value *argv, int32_t max); }; - static Task GenCallbackTask(std::shared_ptr entry); - + static Task GenPromiseTask(std::shared_ptr entry); napi_env env_ = nullptr; uv_loop_s *loop_ = nullptr; std::shared_ptr handler_; diff --git a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_const_properties.h b/relational_store/frameworks/js/napi/common/mock/include/mock.h similarity index 68% rename from relational_store/frameworks/js/napi/graphstore/include/napi_gdb_const_properties.h rename to relational_store/frameworks/js/napi/common/mock/include/mock.h index 02e400e989639ba8c44b5b4aedfe1c9d0ffaa3b0..03ed7faa62a257ed04f7ac32b0ae7818c409491c 100644 --- a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_const_properties.h +++ b/relational_store/frameworks/js/napi/common/mock/include/mock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 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 @@ -12,15 +12,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef SEND_EVENT_MOCK_H +#define SEND_EVENT_MOCK_H +#include -#ifndef OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_CONST_PROPERTIES_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_CONST_PROPERTIES_H - -#include "napi/native_common.h" +#include "event_handler.h" #include "napi/native_api.h" +#include "napi/native_common.h" #include "napi/native_node_api.h" -namespace OHOS::GraphStoreJsKit { -napi_status InitConstProperties(napi_env env, napi_value exports); -} -#endif \ No newline at end of file +napi_status SendEventMock( + napi_env env, const std::function &cb, napi_event_priority priority, const char *name); +#endif //SEND_EVENT_MOCK_H \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/common/mock/include/napi_async_proxy.h b/relational_store/frameworks/js/napi/common/mock/include/napi_async_proxy.h index e3ac9bc552dab4093a49568a6c7dff4f03f2c80d..65d997cb06a315a3de0d62f9ddbd4445bd077599 100644 --- a/relational_store/frameworks/js/napi/common/mock/include/napi_async_proxy.h +++ b/relational_store/frameworks/js/napi/common/mock/include/napi_async_proxy.h @@ -14,6 +14,7 @@ */ #ifndef PREFERENCES_JSKIT_NAPI_ASYNC_PROXY_H #define PREFERENCES_JSKIT_NAPI_ASYNC_PROXY_H +#include #include #include "napi/native_api.h" @@ -61,7 +62,7 @@ public: public: void Init(napi_env env, napi_callback_info info) { - asyncContext = new T(); + asyncContext = new (std::nothrow) T(); if (asyncContext == nullptr) { return; } @@ -101,6 +102,41 @@ public: parserThis(asyncContext->env, thisObj, asyncContext); } + static void OnComplete(napi_env env, napi_status status, void *data) + { + if (data == nullptr) { + return; + } + T *context = (T *)data; + napi_value output = nullptr; + int completeStatus = context->completeFunc(context, output); + napi_value result[RESULT_COUNT] = { 0 }; + if (context->execStatus == OK && completeStatus == OK) { + napi_get_undefined(env, &result[0]); + result[1] = output; + } else { + napi_value message = nullptr; + napi_create_string_utf8(env, "async call failed", NAPI_AUTO_LENGTH, &message); + napi_create_error(env, nullptr, message, &result[0]); + napi_get_undefined(env, &result[1]); + } + if (context->deferred) { + // promise + if (context->execStatus == OK && completeStatus == OK) { + napi_resolve_deferred(env, context->deferred, result[1]); + } else { + napi_reject_deferred(env, context->deferred, result[0]); + } + } else { + // callback + napi_value callback = nullptr; + napi_get_reference_value(env, context->callbackRef, &callback); + napi_value callbackResult = nullptr; + napi_call_function(env, nullptr, callback, RESULT_COUNT, result, &callbackResult); + } + delete context; + } + napi_value DoAsyncWork(std::string resourceName, NapiAsyncExecute execFunc, NapiAsyncComplete completeFunc) { if (asyncContext == nullptr) { @@ -118,42 +154,18 @@ public: napi_create_string_utf8(asyncContext->env, resourceName.c_str(), NAPI_AUTO_LENGTH, &resource); asyncContext->execFunc = execFunc; asyncContext->completeFunc = completeFunc; - NAPI_CALL_BASE(asyncContext->env, napi_create_async_work(asyncContext->env, nullptr, resource, - [](napi_env env, void *data) { - T *context = (T *)data; - context->execStatus = context->execFunc(context); - }, - [](napi_env env, napi_status status, void *data) { - T *context = (T *)data; - napi_value output = nullptr; - int completeStatus = context->completeFunc(context, output); - napi_value result[RESULT_COUNT] = { 0 }; - if (context->execStatus == OK && completeStatus == OK) { - napi_get_undefined(env, &result[0]); - result[1] = output; - } else { - napi_value message = nullptr; - napi_create_string_utf8(env, "async call failed", NAPI_AUTO_LENGTH, &message); - napi_create_error(env, nullptr, message, &result[0]); - napi_get_undefined(env, &result[1]); - } - if (context->deferred) { - // promise - if (context->execStatus == OK && completeStatus == OK) { - napi_resolve_deferred(env, context->deferred, result[1]); - } else { - napi_reject_deferred(env, context->deferred, result[0]); + NAPI_CALL_BASE(asyncContext->env, + napi_create_async_work( + asyncContext->env, nullptr, resource, + [](napi_env env, void *data) { + if (data == nullptr) { + return; } - } else { - // callback - napi_value callback = nullptr; - napi_get_reference_value(env, context->callbackRef, &callback); - napi_value callbackResult = nullptr; - napi_call_function(env, nullptr, callback, RESULT_COUNT, result, &callbackResult); - } - delete context; - }, - (void *)asyncContext, &asyncContext->work), ret); + T *context = (T *)data; + context->execStatus = context->execFunc(context); + }, + OnComplete, (void *)asyncContext, &asyncContext->work), + ret); NAPI_CALL_BASE(asyncContext->env, napi_queue_async_work(asyncContext->env, asyncContext->work), ret); return ret; } diff --git a/relational_store/frameworks/js/napi/common/mock/src/js_ability.cpp b/relational_store/frameworks/js/napi/common/mock/src/js_ability.cpp index 069015e2120fe09f2c48dd9acd62bb98688f96c2..5b1c873cf698632163668988d6ef121df2039548 100644 --- a/relational_store/frameworks/js/napi/common/mock/src/js_ability.cpp +++ b/relational_store/frameworks/js/napi/common/mock/src/js_ability.cpp @@ -33,7 +33,7 @@ Context::Context() #ifdef WINDOWS_PLATFORM baseDir = getenv("TEMP"); if (!baseDir.empty()) { - databaseDir_ = baseDir + "\\HuaweiDevEcoStudioDatabases"; + databaseDir_ = baseDir + "\\Databases"; } #endif @@ -41,7 +41,7 @@ Context::Context() baseDir = getenv("LOGNAME"); baseDir = "/Users/" + baseDir + "/Library/Caches"; if (!baseDir.empty()) { - databaseDir_ = baseDir + "/HuaweiDevEcoStudioDatabases"; + databaseDir_ = baseDir + "/Databases"; } #endif bundleName_ = "com.example.myapplication"; diff --git a/relational_store/frameworks/js/napi/common/mock/src/mock.cpp b/relational_store/frameworks/js/napi/common/mock/src/mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..756d797f10960b436b0b48e3b651ab6d5bc4616a --- /dev/null +++ b/relational_store/frameworks/js/napi/common/mock/src/mock.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2025 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 "mock.h" +#include "uv.h" + +struct UvEntry { + std::function callback; +}; +napi_status SendEventMock(napi_env env, + const std::function& cb, + napi_event_priority priority, + const char* name) +{ + if (env == nullptr || !cb || priority < napi_eprio_vip || priority > napi_eprio_idle) { + return napi_status::napi_invalid_arg; + } + + uv_loop_s *loop = nullptr; + napi_get_uv_event_loop(env, &loop); + if (loop == nullptr) { + return napi_status::napi_invalid_arg; + } + + uv_work_t *work = new (std::nothrow) uv_work_t; + if (work == nullptr) { + return napi_status::napi_invalid_arg; + } + auto entry = new (std::nothrow) UvEntry(); + if (entry == nullptr) { + delete work; + return napi_status::napi_invalid_arg; + } + entry->callback = cb; + work->data = entry; + + int ret = uv_queue_work(loop, work, [](uv_work_t *data) { + return; + }, [](uv_work_t *work, int status) { + if (work == nullptr) { + return; + } + if (work->data == nullptr) { + delete work; + return; + } + auto entry = static_cast(work->data); + if (entry->callback) { + entry->callback(); + } + delete entry; + delete work; + return; + }); + if (ret < 0) { + delete entry; + delete work; + return napi_status::napi_invalid_arg; + } + return napi_ok; +} \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/common/src/js_sendable_utils.cpp b/relational_store/frameworks/js/napi/common/src/js_sendable_utils.cpp index 935e2882a854e442fce35b978c2ea844a36a5229..bd7dfaf9669b19d987ef9edbdeda279b5a329a77 100644 --- a/relational_store/frameworks/js/napi/common/src/js_sendable_utils.cpp +++ b/relational_store/frameworks/js/napi/common/src/js_sendable_utils.cpp @@ -39,7 +39,10 @@ napi_value JSUtils::Convert2Sendable(napi_env env, const std::vector &v LOG_ERROR("napi_create_sendable_arraybuffer failed %{public}d", status); return nullptr; } - if (value.size() != 0) { + if (value.size() > 0) { + if (native == nullptr) { + return nullptr; + } std::copy(value.begin(), value.end(), static_cast(native)); } status = napi_create_sendable_typedarray(env, napi_uint8_array, value.size(), buffer, 0, &jsValue); @@ -85,7 +88,10 @@ napi_value JSUtils::Convert2Sendable(napi_env env, const std::vector &val LOG_ERROR("napi_create_sendable_arraybuffer failed %{public}d", status); return nullptr; } - if (value.size() != 0) { + if (value.size() > 0) { + if (native == nullptr) { + return nullptr; + } std::copy(value.begin(), value.end(), static_cast(native)); } status = napi_create_sendable_typedarray(env, napi_float32_array, value.size(), buffer, 0, &jsValue); @@ -183,6 +189,9 @@ napi_value JSUtils::ToSendableTypedArray(napi_env env, napi_value jsValue) status = napi_create_sendable_arraybuffer(env, length, (void **)&native, &buffer); ASSERT(status == napi_ok, "napi_create_sendable_arraybuffer failed", nullptr); if (length > 0) { + if (native == nullptr || tmp == nullptr) { + return nullptr; + } errno_t result = memcpy_s(native, length, tmp, length); if (result != EOK) { LOG_ERROR("memcpy_s failed, result is %{public}d", result); diff --git a/relational_store/frameworks/js/napi/common/src/js_utils.cpp b/relational_store/frameworks/js/napi/common/src/js_utils.cpp index 188c459f6e1d38c6bfaa6363f01769fbc62914ca..66210da23c4c75ca32dbf63a001d77093c7868c4 100644 --- a/relational_store/frameworks/js/napi/common/src/js_utils.cpp +++ b/relational_store/frameworks/js/napi/common/src/js_utils.cpp @@ -43,7 +43,6 @@ static constexpr JSUtils::JsFeatureSpace FEATURE_NAME_SPACES[] = { { "ohos.data.dataShare", "ZGF0YS5kYXRhU2hhcmU=", false }, { "ohos.data.distributedDataObject", "ZGF0YS5kaXN0cmlidXRlZERhdGFPYmplY3Q=", false }, { "ohos.data.distributedKVStore", "ZGF0YS5kaXN0cmlidXRlZEtWU3RvcmU=", false }, - { "ohos.data.graphStore", "ZGF0YS5ncmFwaFN0b3Jl", true }, { "ohos.data.rdb", "ZGF0YS5yZGI=", true }, { "ohos.data.relationalStore", "ZGF0YS5yZWxhdGlvbmFsU3RvcmU=", true }, }; @@ -376,6 +375,9 @@ napi_value JSUtils::Convert2JSValue(napi_env env, const std::vector &va if (status != napi_ok) { return nullptr; } + if (value.size() > 0 && native == nullptr) { + return nullptr; + } for (size_t i = 0; i < value.size(); i++) { *(static_cast(native) + i) = value[i]; } @@ -445,7 +447,7 @@ napi_value JSUtils::Convert2JSValue(napi_env env, const std::vector &valu if (status != napi_ok) { return nullptr; } - if (native == nullptr) { + if (value.size() > 0 && native == nullptr) { return nullptr; } for (size_t i = 0; i < value.size(); i++) { @@ -680,6 +682,7 @@ napi_value JSUtils::ToJsTypedArray(napi_env env, napi_value sendableValue) status = napi_create_arraybuffer(env, length, (void **)&native, &buffer); ASSERT(status == napi_ok, "napi_create_arraybuffer failed", nullptr); if (length > 0) { + ASSERT(native != nullptr && tmp != nullptr, "native is nullptr.", nullptr); errno_t result = memcpy_s(native, length, tmp, length); if (result != EOK) { LOG_ERROR("memcpy_s failed, result is %{public}d", result); diff --git a/relational_store/frameworks/js/napi/common/src/js_uv_queue.cpp b/relational_store/frameworks/js/napi/common/src/js_uv_queue.cpp index 7996b287d3e26c604b231fba999ca4318a277b17..b6a67f2fdf87cba0e3ffd8161b66c99e3552f046 100644 --- a/relational_store/frameworks/js/napi/common/src/js_uv_queue.cpp +++ b/relational_store/frameworks/js/napi/common/src/js_uv_queue.cpp @@ -19,6 +19,7 @@ #include "js_scope.h" #include "logger.h" +#include "napi/native_node_api.h" namespace OHOS::AppDataMgrJsKit { using namespace OHOS::Rdb; constexpr size_t ARGC_MAX = 6; @@ -39,21 +40,11 @@ UvQueue::~UvQueue() void UvQueue::AsyncCall(UvCallback callback, Args args, Result result) { - if (loop_ == nullptr || callback.IsNull()) { - LOG_ERROR("loop_ or callback is nullptr."); - return; - } - uv_work_t *work = new (std::nothrow) uv_work_t; - if (work == nullptr) { - LOG_ERROR("No memory for uv_work_t."); - return; - } - auto entry = new (std::nothrow) UvEntry(); - if (entry == nullptr) { - delete work; - LOG_ERROR("No memory for UvEntry."); + if (callback.IsNull()) { + LOG_ERROR("callback is nullptr."); return; } + auto entry = std::make_shared(); entry->env_ = env_; entry->object_ = callback.object_; entry->callback_ = callback.callback_; @@ -61,12 +52,9 @@ void UvQueue::AsyncCall(UvCallback callback, Args args, Result result) entry->getter_ = std::move(callback.getter_); entry->args_ = std::move(args); entry->result_ = std::move(result); - work->data = entry; - int ret = uv_queue_work(loop_, work, DoWork, DoUvCallback); - if (ret < 0) { - LOG_ERROR("uv_queue_work failed, errCode:%{public}d", ret); - delete entry; - delete work; + auto status = napi_send_event(env_, GenCallbackTask(entry), napi_eprio_immediate); + if (status != napi_ok) { + LOG_ERROR("Failed to SendEvent, status:%{public}d", status); } } @@ -95,30 +83,17 @@ void UvQueue::AsyncCallInOrder(UvCallback callback, Args args, Result result) void UvQueue::AsyncPromise(UvPromise promise, UvQueue::Args args) { - if (loop_ == nullptr || promise.IsNull()) { - LOG_ERROR("loop_ or promise is nullptr."); - return; - } - uv_work_t *work = new (std::nothrow) uv_work_t; - if (work == nullptr) { - LOG_ERROR("No memory for uv_work_t."); - return; - } - auto entry = new (std::nothrow) UvEntry(); - if (entry == nullptr) { - delete work; - LOG_ERROR("No memory for UvEntry."); + if (promise.IsNull()) { + LOG_ERROR("promise is nullptr."); return; } + auto entry = std::make_shared(); entry->env_ = env_; entry->defer_ = promise.defer_; entry->args_ = std::move(args); - work->data = entry; - int ret = uv_queue_work(loop_, work, DoWork, DoUvPromise); - if (ret < 0) { - LOG_ERROR("uv_queue_work failed, errCode:%{public}d", ret); - delete entry; - delete work; + auto status = napi_send_event(env_, GenPromiseTask(entry), napi_eprio_immediate); + if (status != napi_ok) { + LOG_ERROR("Failed to SendEvent, status:%{public}d", status); } } @@ -170,7 +145,7 @@ napi_value UvQueue::Future(napi_env env, napi_callback_info info, bool exception napi_value argv[ARGC_MAX] = { nullptr }; void *data = nullptr; auto status = napi_get_cb_info(env, info, &argc, argv, nullptr, &data); - if (status != napi_ok) { + if (status != napi_ok || data == nullptr) { return nullptr; } auto *entry = static_cast(data); @@ -181,45 +156,17 @@ napi_value UvQueue::Future(napi_env env, napi_callback_info info, bool exception return nullptr; } -void UvQueue::DoWork(uv_work_t *work) -{ -} - void UvQueue::DoExecute(uv_work_t *work) { + if (work == nullptr) { + return; + } Task *task = static_cast(work->data); work->data = nullptr; (*task)(); delete task; } -void UvQueue::DoUvCallback(uv_work_t *work, int status) -{ - std::shared_ptr entry(static_cast(work->data), [work](UvEntry *data) { - delete data; - delete work; - }); - - GenCallbackTask(entry)(); -} - -void UvQueue::DoUvPromise(uv_work_t *work, int status) -{ - std::shared_ptr entry(static_cast(work->data), [work](UvEntry *data) { - delete data; - delete work; - }); - - Scope scope(entry->env_); - napi_value argv[ARG_BUTT] = { nullptr }; - auto argc = entry->GetArgv(argv, ARG_BUTT); - if (argv[ARG_ERROR] != nullptr || argc != ARG_BUTT) { - napi_reject_deferred(entry->env_, entry->defer_, argv[ARG_ERROR]); - } else { - napi_resolve_deferred(entry->env_, entry->defer_, argv[ARG_DATA]); - } -} - UvQueue::Task UvQueue::GenCallbackTask(std::shared_ptr entry) { return [entry]() { @@ -247,6 +194,23 @@ UvQueue::Task UvQueue::GenCallbackTask(std::shared_ptr entry) }; } +UvQueue::Task UvQueue::GenPromiseTask(std::shared_ptr entry) +{ + return [entry]() { + if (entry == nullptr) { + return; + } + Scope scope(entry->env_); + napi_value argv[ARG_BUTT] = { nullptr }; + auto argc = entry->GetArgv(argv, ARG_BUTT); + if (argv[ARG_ERROR] != nullptr || argc != ARG_BUTT) { + napi_reject_deferred(entry->env_, entry->defer_, argv[ARG_ERROR]); + } else { + napi_resolve_deferred(entry->env_, entry->defer_, argv[ARG_DATA]); + } + }; +} + UvQueue::UvEntry::~UvEntry() { } @@ -315,8 +279,16 @@ void UvQueue::UvEntry::BindPromise(napi_value promise) auto object = StealResult(); napi_value argv[ARGC_MAX] = { nullptr }; - napi_create_function(env_, RESOLVED, RESOLVED_SIZE, Resolved, object, &argv[0]); - napi_create_function(env_, REJECTED, REJECTED_SIZE, Rejected, object, &argv[1]); + auto resolvedStatus = napi_create_function(env_, RESOLVED, RESOLVED_SIZE, Resolved, object, &argv[0]); + auto rejectedStatus = napi_create_function(env_, REJECTED, REJECTED_SIZE, Rejected, object, &argv[1]); + if (resolvedStatus != napi_ok || rejectedStatus != napi_ok) { + if (object) { + delete object; + } + LOG_ERROR("napi_create_function failed. resolvedStat:%{public}d, rejectedStat:%{public}d", resolvedStatus, + rejectedStatus); + return; + } napi_value result = nullptr; // Enter 2 parameters argv[0] and argv[1] status = napi_call_function(env_, promise, then, 2, argv, &result); @@ -330,7 +302,11 @@ UvQueue::Result *UvQueue::UvEntry::StealResult() if (!result_) { return nullptr; } - auto *result = new Result(); + auto *result = new (std::nothrow) Result(); + if (result == nullptr) { + LOG_ERROR("No memory for Result."); + return nullptr; + } *result = std::move(result_); return result; } diff --git a/relational_store/frameworks/js/napi/dataability/BUILD.gn b/relational_store/frameworks/js/napi/dataability/BUILD.gn index 4dc0670f0d37ad15b74e47b832976ce9ae4dcfd1..1259ccf0624deb35daccfda1735423bafc9200e0 100644 --- a/relational_store/frameworks/js/napi/dataability/BUILD.gn +++ b/relational_store/frameworks/js/napi/dataability/BUILD.gn @@ -45,6 +45,7 @@ ohos_shared_library("dataability") { external_deps = [ "hilog:libhilog", + "ipc:ipc_single", "napi:ace_napi", ] diff --git a/relational_store/frameworks/js/napi/dataability/include/napi_async_proxy.h b/relational_store/frameworks/js/napi/dataability/include/napi_async_proxy.h deleted file mode 100644 index b28d51685cd16006f0399320aac5d201da3950cf..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/dataability/include/napi_async_proxy.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * 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 PREFERENCES_JSKIT_NAPI_ASYNC_PROXY_H -#define PREFERENCES_JSKIT_NAPI_ASYNC_PROXY_H -#include - -#include "napi/native_api.h" -#include "napi/native_common.h" -#include "napi/native_node_api.h" -#include "securec.h" - -namespace OHOS { -namespace AppDataMgrJsKit { -constexpr int MAX_INPUT_COUNT = 10; -constexpr int OK = 0; -constexpr int ERR = -1; - -// T inherits AysncContext -template -class NapiAsyncProxy { -public: - constexpr static int RESULT_COUNT = 2; - using InputParser = void (*)(const napi_env &, const napi_value &, T *); - using NapiAsyncExecute = int (*)(T *); - using NapiAsyncComplete = int (*)(T *, napi_value &); - - // AsyncContext base - struct AysncContext { - AysncContext() - { - } - virtual ~AysncContext() - { - if (env == nullptr) { - return; - } - napi_delete_async_work(env, work); - napi_delete_reference(env, callbackRef); - } - napi_env env = nullptr; - napi_callback_info info = nullptr; - napi_async_work work = nullptr; - napi_deferred deferred = nullptr; - napi_ref callbackRef = nullptr; - NapiAsyncExecute execFunc = nullptr; - int execStatus = ERR; - NapiAsyncComplete completeFunc = nullptr; - void *boundObj = nullptr; - }; - -public: - void Init(napi_env env, napi_callback_info info) - { - asyncContext = new T(); - if (asyncContext == nullptr) { - return; - } - asyncContext->env = env; - asyncContext->info = info; - } - - ~NapiAsyncProxy() - { - if (asyncContext == nullptr) { - return; - } - - delete asyncContext; - asyncContext = nullptr; - } - - static void DefParserThis(const napi_env &env, const napi_value &self, T *context) - { - napi_unwrap(env, self, &context->boundObj); - } - - void ParseInputs(const std::vector &parsers, InputParser parserThis = DefParserThis) - { - if (asyncContext == nullptr) { - return; - } - - napi_value thisObj = nullptr; - size_t argc = parsers.size() + 1; - napi_value args[MAX_INPUT_COUNT] = { 0 }; - napi_get_cb_info(asyncContext->env, asyncContext->info, &argc, args, &thisObj, nullptr); - for (size_t i = 0; i < argc && argc <= MAX_INPUT_COUNT; i++) { - if (i >= parsers.size()) { - napi_valuetype valueType = napi_undefined; - napi_typeof(asyncContext->env, args[i], &valueType); - if (valueType == napi_function) { - napi_create_reference(asyncContext->env, args[i], 1, &asyncContext->callbackRef); - } - break; - } - auto *parserFunction = parsers[i]; - if (parserFunction != nullptr) { - parserFunction(asyncContext->env, args[i], this->asyncContext); - } - } - parserThis(asyncContext->env, thisObj, asyncContext); - } - - napi_value DoAsyncWork(std::string resourceName, NapiAsyncExecute execFunc, NapiAsyncComplete completeFunc) - { - if (asyncContext == nullptr) { - return nullptr; - } - - napi_value ret = nullptr; - if (asyncContext->callbackRef == nullptr) { - napi_create_promise(asyncContext->env, &asyncContext->deferred, &ret); - } else { - napi_get_undefined(asyncContext->env, &ret); - } - - napi_value resource = nullptr; - napi_create_string_utf8(asyncContext->env, resourceName.c_str(), NAPI_AUTO_LENGTH, &resource); - asyncContext->execFunc = execFunc; - asyncContext->completeFunc = completeFunc; - NAPI_CALL_BASE(asyncContext->env, napi_create_async_work(asyncContext->env, nullptr, resource, - [](napi_env env, void *data) { - T *context = (T *)data; - context->execStatus = context->execFunc(context); - }, - [](napi_env env, napi_status status, void *data) { - T *context = (T *)data; - napi_value output = nullptr; - int completeStatus = context->completeFunc(context, output); - napi_value result[RESULT_COUNT] = { 0 }; - if (context->execStatus == OK && completeStatus == OK) { - napi_get_undefined(env, &result[0]); - result[1] = output; - } else { - napi_value message = nullptr; - napi_create_string_utf8(env, "async call failed", NAPI_AUTO_LENGTH, &message); - napi_create_error(env, nullptr, message, &result[0]); - napi_get_undefined(env, &result[1]); - } - if (context->deferred) { - // promise - if (context->execStatus == OK && completeStatus == OK) { - napi_resolve_deferred(env, context->deferred, result[1]); - } else { - napi_reject_deferred(env, context->deferred, result[0]); - } - } else { - // callback - napi_value callback = nullptr; - napi_get_reference_value(env, context->callbackRef, &callback); - napi_value callbackResult = nullptr; - napi_call_function(env, nullptr, callback, RESULT_COUNT, result, &callbackResult); - } - delete context; - }, - (void *)asyncContext, &asyncContext->work), ret); - NAPI_CALL_BASE(asyncContext->env, napi_queue_async_work(asyncContext->env, asyncContext->work), ret); - return ret; - } - -private: - T *asyncContext; -}; -} // namespace AppDataMgrJsKit -} // namespace OHOS -#endif diff --git a/relational_store/frameworks/js/napi/dataability/include/napi_data_ability_predicates.h b/relational_store/frameworks/js/napi/dataability/include/napi_data_ability_predicates.h index cbe35b56de3d17b812cb7abafd9d162978662a28..43981161ee8491173134b83fa8183d96cf122e46 100644 --- a/relational_store/frameworks/js/napi/dataability/include/napi_data_ability_predicates.h +++ b/relational_store/frameworks/js/napi/dataability/include/napi_data_ability_predicates.h @@ -90,8 +90,9 @@ private: } // namespace OHOS EXTERN_C_START -__attribute__((visibility("default"))) napi_value NAPI_OHOS_Data_DataAbilityJsKit_DataAbilityPredicatesProxy_NewInstance( - napi_env env, OHOS::NativeRdb::DataAbilityPredicates *predicates); +__attribute__((visibility("default"))) + napi_value NAPI_OHOS_Data_DataAbilityJsKit_DataAbilityPredicatesProxy_NewInstance( + napi_env env, OHOS::NativeRdb::DataAbilityPredicates *predicates); __attribute__((visibility("default"))) OHOS::NativeRdb::DataAbilityPredicates * NAPI_OHOS_Data_DataAbilityJsKit_DataAbilityPredicatesProxy_GetNativeObject(const napi_env env, const napi_value arg); diff --git a/relational_store/frameworks/js/napi/dataability/src/napi_data_ability_predicates.cpp b/relational_store/frameworks/js/napi/dataability/src/napi_data_ability_predicates.cpp index 9b5056735778a2ab34c2bcb80d9da4481fa59cd5..ea5dd04c29ba455ab2dbba1ff79a6e24c9071e43 100644 --- a/relational_store/frameworks/js/napi/dataability/src/napi_data_ability_predicates.cpp +++ b/relational_store/frameworks/js/napi/dataability/src/napi_data_ability_predicates.cpp @@ -12,13 +12,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #define LOG_TAG "DataAbilityPredicatesProxy" #include "napi_data_ability_predicates.h" #include "js_df_manager.h" #include "js_utils.h" #include "logger.h" -#include "napi_async_proxy.h" #include "napi_predicates_utils.h" using namespace OHOS::Rdb; @@ -137,7 +137,7 @@ napi_value DataAbilityPredicatesProxy::NewInstance( DataAbilityPredicatesProxy *proxy = nullptr; status = napi_unwrap(env, instance, reinterpret_cast(&proxy)); - if (status != napi_ok) { + if (status != napi_ok || proxy == nullptr) { LOG_ERROR("DataAbilityPredicatesProxy native instance is nullptr! napi_status:%{public}d!", status); return instance; } @@ -168,6 +168,9 @@ void DataAbilityPredicatesProxy::Destructor(napi_env env, void *nativeObject, vo LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(nativeObject) & LOWER_24_BITS_MASK); } DataAbilityPredicatesProxy *proxy = static_cast(nativeObject); + if (proxy == nullptr) { + return; + } proxy->predicates_ = std::move(nullptr); delete proxy; } @@ -176,8 +179,9 @@ DataAbilityPredicatesProxy::~DataAbilityPredicatesProxy() { } -DataAbilityPredicatesProxy::DataAbilityPredicatesProxy() : predicates_(new DataAbilityPredicates()) +DataAbilityPredicatesProxy::DataAbilityPredicatesProxy() { + predicates_ = std::make_shared(); } std::shared_ptr DataAbilityPredicatesProxy::GetNativePredicates( @@ -805,8 +809,9 @@ napi_value DataAbilityPredicatesProxy::IsSorted(napi_env env, napi_callback_info } // namespace OHOS EXTERN_C_START -__attribute__((visibility("default"))) napi_value NAPI_OHOS_Data_DataAbilityJsKit_DataAbilityPredicatesProxy_NewInstance( - napi_env env, OHOS::NativeRdb::DataAbilityPredicates *predicates) +__attribute__((visibility("default"))) + napi_value NAPI_OHOS_Data_DataAbilityJsKit_DataAbilityPredicatesProxy_NewInstance( + napi_env env, OHOS::NativeRdb::DataAbilityPredicates *predicates) { return OHOS::DataAbilityJsKit::DataAbilityPredicatesProxy::NewInstance( env, std::shared_ptr(predicates)); diff --git a/relational_store/frameworks/js/napi/dataability/src/napi_predicates_utils.cpp b/relational_store/frameworks/js/napi/dataability/src/napi_predicates_utils.cpp index 1a3f4fae1f1eaba0e213090c44742ab51e0f4315..d51c35ddda32af5f2fe814f40ac132701297ec75 100644 --- a/relational_store/frameworks/js/napi/dataability/src/napi_predicates_utils.cpp +++ b/relational_store/frameworks/js/napi/dataability/src/napi_predicates_utils.cpp @@ -45,9 +45,11 @@ napi_value CreateRdbPredicates(napi_env env, napi_callback_info info) NAPI_ASSERT(env, valueType == napi_object, "Table name should be an object."); DataAbilityPredicatesProxy *dataAbilityPredicatesProxy = nullptr; NAPI_CALL(env, napi_unwrap(env, args[1], reinterpret_cast(&dataAbilityPredicatesProxy))); - + NAPI_ASSERT(env, dataAbilityPredicatesProxy != nullptr, "napi_unwrap failed."); auto absPredicates = dataAbilityPredicatesProxy->GetPredicates(); - auto predicates = new NativeRdb::RdbPredicates(tableName); + NAPI_ASSERT(env, absPredicates != nullptr, "absPredicates is nullptr."); + auto predicates = new (std::nothrow) NativeRdb::RdbPredicates(tableName); + NAPI_ASSERT(env, predicates != nullptr, "No memory for RdbPredicates."); NativeRdb::PredicatesUtils::SetWhereClauseAndArgs( predicates, absPredicates->GetWhereClause(), absPredicates->GetBindArgs()); NativeRdb::PredicatesUtils::SetAttributes(predicates, absPredicates->IsDistinct(), absPredicates->GetIndex(), diff --git a/relational_store/frameworks/js/napi/graphstore/include/gdb_common.h b/relational_store/frameworks/js/napi/graphstore/include/gdb_common.h deleted file mode 100644 index 3ba2409305c9ddadd81a3e8319c941d8263adb83..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/graphstore/include/gdb_common.h +++ /dev/null @@ -1,59 +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. - */ - -#ifndef OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_COMMON_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_COMMON_H -#include - -namespace OHOS::GraphStoreJsKit { -enum ColumnType : uint32_t { - - /** - * GRAPH_DB_DATATYPE_LONG: means the column type of the specified column is long. - * - * @syscap - * @since 16 - */ - GRAPH_DB_DATATYPE_LONG = 0, - - /** - * GRAPH_DB_DATATYPE_DOUBLE: means the column type of the specified column is double. - * - * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core - * @since 16 - */ - GRAPH_DB_DATATYPE_DOUBLE, - - /** - * GRAPH_DB_DATATYPE_STRING: means the column type of the specified column is string. - * - * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core - * @since 16 - */ - GRAPH_DB_DATATYPE_STRING, - - /** - * GRAPH_DB_DATATYPE_JSONSTR: means the column type of the specified column is string with json format. - * - * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core - * @since 16 - */ - GRAPH_DB_DATATYPE_JSONSTR, - - GRAPH_DB_DATATYPE_NULL, -}; -} - -#endif \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/include/js_proxy.h b/relational_store/frameworks/js/napi/graphstore/include/js_proxy.h deleted file mode 100644 index 9bbf5b85b1c65ad4fa43af11d3c21635140fd9ef..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/graphstore/include/js_proxy.h +++ /dev/null @@ -1,62 +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. -*/ - -#ifndef OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_JS_PROXY_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_JS_PROXY_H -#include -namespace OHOS::GraphStoreJsKit { -template -class JSCreator { -public: - // This method will be used to call different subclasses for implementation - virtual std::shared_ptr Create() = 0; - -protected: - // It is not allowed to directly use parent class objects for construction and destruction - JSCreator() = default; - ~JSCreator() = default; -}; - -template -class JSProxy { -public: - void SetInstance(std::shared_ptr instance) - { - instance_ = std::move(instance); - } - - std::shared_ptr GetInstance() const - { - return instance_; - } - -protected: - // It is not allowed to directly use parent class objects for construction and destruction - JSProxy() = default; - ~JSProxy() = default; - -private: - std::shared_ptr instance_; -}; - -template -class JSEntity : public JSCreator, public JSProxy { -protected: - // It is not allowed to directly use parent class objects for construction and destruction - JSEntity() = default; - ~JSEntity() = default; -}; -} // namespace OHOS::JSProxy -#endif // OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_JS_PROXY_H diff --git a/relational_store/frameworks/js/napi/graphstore/include/napi_async_call.h b/relational_store/frameworks/js/napi/graphstore/include/napi_async_call.h deleted file mode 100644 index 160200e68e5f936a106445b403beadfddff9ee52..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/graphstore/include/napi_async_call.h +++ /dev/null @@ -1,108 +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. - */ -#ifndef OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_ASYNC_CALL_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_ASYNC_CALL_H - -#include -#include -#include -#include -#include - -#include "gdb_errors.h" -#include "logger.h" -#include "napi/native_api.h" -#include "napi/native_common.h" -#include "napi/native_node_api.h" -#include "napi_gdb_error.h" - -namespace OHOS::GraphStoreJsKit { -using InputAction = std::function; -using OutputAction = std::function; -using ExecuteAction = std::function; -extern bool g_async; -extern bool g_sync; -#define AIP_ASYNC &g_async -#define AIP_SYNC &g_sync - -#define ASYNC_CALL(env, ctx) AsyncCall::Call(env, ctx, __FUNCTION__) -class ContextBase { -public: - struct RecordData { - std::atomic_uint64_t times_{0}; - int64_t lastTime_ = 0; - RecordData() = default; - RecordData(const RecordData &record) - { - times_.store(record.times_); - lastTime_ = record.lastTime_; - } - RecordData& operator= (const RecordData &record) - { - times_.store(record.times_); - lastTime_ = record.lastTime_; - return *this; - } - }; - void SetAction(napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output); - void SetAll(napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output); - void SetError(std::shared_ptr error); - virtual ~ContextBase(); - - napi_env env_ = nullptr; - bool isAsync_ = true; - void *boundObj = nullptr; - std::shared_ptr error; - std::shared_ptr executed_; - const char *fun = nullptr; - - napi_ref self_ = nullptr; - napi_ref callback_ = nullptr; - napi_deferred defer_ = nullptr; - napi_async_work work_ = nullptr; - - int execCode_ = OK; - OutputAction output_ = nullptr; - ExecuteAction exec_ = nullptr; - napi_value result_ = nullptr; - std::shared_ptr keep_; -}; - -class AsyncCall final { -public: - static napi_value Call(napi_env env, std::shared_ptr context, const char *fun); - -private: - enum { ARG_ERROR, ARG_DATA, ARG_BUTT }; - using RecordData = ContextBase::RecordData; - struct Record { - public: - RecordData total_; - RecordData completed_; - uint64_t reportTimes_ = 0; - std::shared_ptr executed_ = std::make_shared(); - }; - static constexpr uint64_t EXCEPT_DELTA = 20; - static void OnExecute(napi_env env, void *data); - static void OnComplete(napi_env env, void *data); - static void OnReturn(napi_env env, napi_status status, void *data); - static void OnComplete(napi_env env, napi_status status, void *data); - static void SetBusinessError(napi_env env, std::shared_ptr error, napi_value *businessError); - static napi_value Async(napi_env env, std::shared_ptr context); - static napi_value Sync(napi_env env, std::shared_ptr context); - static thread_local Record record_; -}; -} // namespace OHOS::GraphStoreJsKit -#endif \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_context.h b/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_context.h deleted file mode 100644 index cd39f8a21d26ca3191aaf21137a7f8a3db9dab2f..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_context.h +++ /dev/null @@ -1,80 +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. -*/ -#ifndef OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_CONTEXT_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_CONTEXT_H - -#include "full_result.h" -#include "gdb_store.h" -#include "gdb_store_config.h" -#include "napi_async_call.h" - -namespace OHOS { -namespace GraphStoreJsKit { -using namespace OHOS::DistributedDataAip; -struct GdbStoreContextBase : public ContextBase { - std::shared_ptr StealGdbStore() - { - auto gdb = std::move(gdbStore); - gdbStore = nullptr; - return gdb; - } - std::shared_ptr gdbStore = nullptr; -}; - -struct ContextParam { - std::string bundleName; - std::string moduleName; - std::string baseDir; - int32_t area = 2; - bool isSystemApp = false; - bool isStageMode = true; -}; - -struct GdbStoreContext : public GdbStoreContextBase { - std::string device; - std::string gql; - std::vector columns; - int64_t int64Output; - int intOutput; - ContextParam param; - StoreConfig config; - std::shared_ptr result; - std::vector keys; - std::string key; - std::string aliasName; - std::string pathName; - std::string srcName; - std::string columnName; - int32_t enumArg; - uint64_t cursor = UINT64_MAX; - int64_t txId = 0; - napi_ref asyncHolder = nullptr; - bool isQueryGql = false; - uint32_t expiredTime = 0; - - GdbStoreContext() : int64Output(0), intOutput(0), enumArg(-1) - { - } - virtual ~GdbStoreContext() - { - } -}; - -struct CreateTransactionContext : public GdbStoreContextBase { - std::shared_ptr transaction; -}; -} // namespace GraphStoreJsKit -} // namespace OHOS -#endif \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_error.h b/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_error.h deleted file mode 100644 index 82c1fe9213ffd94a5cd4512e6040dd341a9b83c7..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_error.h +++ /dev/null @@ -1,179 +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. -*/ -#ifndef OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_ERROR_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_ERROR_H - -#include -#include -#include -#include - -#include "logger.h" - -namespace OHOS::GraphStoreJsKit { -constexpr int MAX_INPUT_COUNT = 10; -constexpr int OK = 0; -constexpr int ERR = -1; - -constexpr int E_NON_SYSTEM_APP_ERROR = 202; -constexpr int E_PARAM_ERROR = 401; -constexpr int E_INNER_ERROR = 31300000; - -struct JsErrorCode { - int32_t status; - int32_t jsCode; - std::string_view message; -}; -std::optional GetJsErrorCode(int32_t errorCode); - -#define GDB_REVT_NOTHING -#define GDB_DO_NOTHING - -#define GDB_NAPI_ASSERT_BASE(env, assertion, error, retVal) \ - do { \ - if (!(assertion)) { \ - if ((error) == nullptr) { \ - LOG_ERROR("throw error: error message is empty"); \ - napi_throw_error((env), nullptr, "error message is empty"); \ - return retVal; \ - } \ - LOG_ERROR("throw error: code = %{public}d , message = %{public}s", (error)->GetCode(), \ - (error)->GetMessage().c_str()); \ - napi_throw_error((env), std::to_string((error)->GetCode()).c_str(), (error)->GetMessage().c_str()); \ - return retVal; \ - } \ - } while (0) - -#define GDB_NAPI_ASSERT(env, assertion, error) GDB_NAPI_ASSERT_BASE(env, assertion, error, nullptr) - -#define CHECK_RETURN_CORE(assertion, theCall, revt) \ - do { \ - if (!(assertion)) { \ - theCall; \ - return revt; \ - } \ - } while (0) - -#define CHECK_RETURN_SET_E(assertion, paramError) \ - CHECK_RETURN_CORE(assertion, context->SetError(paramError), GDB_REVT_NOTHING) - -#define CHECK_RETURN_SET(assertion, paramError) CHECK_RETURN_CORE(assertion, context->SetError(paramError), ERR) - -#define CHECK_RETURN_NULL(assertion) CHECK_RETURN_CORE(assertion, GDB_REVT_NOTHING, nullptr) - -#define CHECK_RETURN_ERR(assertion) CHECK_RETURN_CORE(assertion, GDB_REVT_NOTHING, ERR) - -#define CHECK_RETURN(assertion) CHECK_RETURN_CORE(assertion, GDB_REVT_NOTHING, GDB_REVT_NOTHING) - -class Error { -public: - virtual ~Error() = default; - virtual std::string GetMessage() = 0; - virtual int GetCode() = 0; -}; - -class InnerError : public Error { -public: - explicit InnerError(int code) - { - auto errorMsg = GetJsErrorCode(code); - if (errorMsg.has_value()) { - const auto &napiError = errorMsg.value(); - code_ = napiError.jsCode; - msg_ = napiError.message; - } else { - code_ = E_INNER_ERROR; - msg_ = "Inner error. Inner code is " + std::to_string(code % E_INNER_ERROR); - } - } - - explicit InnerError(const std::string &msg) - { - code_ = E_INNER_ERROR; - msg_ = std::string("Inner error. ") + msg; - } - - std::string GetMessage() override - { - return msg_; - } - - int GetCode() override - { - return code_; - } - -private: - int code_; - std::string msg_; -}; - -class ParamError : public Error { -public: - ParamError(const std::string &needed, const std::string &mustbe) - { - msg_ = "Parameter error. The " + needed + " must be " + mustbe; - }; - - explicit ParamError(const std::string &errMsg) - { - msg_ = "Parameter error." + errMsg; - } - - std::string GetMessage() override - { - return msg_; - }; - - int GetCode() override - { - return E_PARAM_ERROR; - }; - -private: - std::string msg_; -}; - -class NonSystemError : public Error { -public: - NonSystemError() = default; - std::string GetMessage() override - { - return "Permission verification failed, application which is not a system application uses system API."; - } - int GetCode() override - { - return E_NON_SYSTEM_APP_ERROR; - } -}; - -class ParamNumError : public Error { -public: - explicit ParamNumError(std::string wantNum) : wantNum(std::move(wantNum)) {}; - std::string GetMessage() override - { - return "Parameter error. Need " + wantNum + " parameter(s)!"; - }; - int GetCode() override - { - return E_PARAM_ERROR; - }; - -private: - std::string wantNum; -}; -} // namespace OHOS::GraphStoreJsKit - -#endif // GDB_JS_NAPI_ERROR_H \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_js_utils.h b/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_js_utils.h deleted file mode 100644 index db292630561bdaf94a81867fc954b9c7b208cc0b..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_js_utils.h +++ /dev/null @@ -1,80 +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. - */ - -#ifndef OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_JS_UTILS_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_JS_UTILS_H -#include "full_result.h" -#include "gdb_store_config.h" -#include "js_utils.h" -#include "logger.h" -#include "napi_gdb_context.h" - -namespace OHOS::AppDataMgrJsKit::JSUtils { -using namespace GraphStoreJsKit; -using StoreConfig = DistributedDataAip::StoreConfig; -using Vertex = OHOS::DistributedDataAip::Vertex; -using Edge = OHOS::DistributedDataAip::Edge; -using PathSegment = OHOS::DistributedDataAip::PathSegment; -using Path = OHOS::DistributedDataAip::Path; - -#define GRAPH_ASSERT(condition, message, retVal) \ - do { \ - if (!(condition)) { \ - LOG_ERROR("test (" #condition ") failed: " message); \ - return retVal; \ - } \ - } while (0) - -#define NAPI_CALL_RETURN_ERR(theCall, retVal) \ - do { \ - if ((theCall) != napi_ok) { \ - return retVal; \ - } \ - } while (0) - -#ifndef PATH_SPLIT -#define PATH_SPLIT '/' -#endif - -static inline OHOS::HiviewDFX::HiLogLabel LogLabel() -{ - return { LOG_CORE, 0xD001660, "GdbJSUtils" }; -} - -template<> -int32_t Convert2Value(napi_env env, napi_value jsValue, ContextParam &context); - -template<> -int32_t Convert2Value(napi_env env, napi_value jsValue, StoreConfig &config); - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &result); - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &value); - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &edge); - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &pathSegment); - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &path); - -std::tuple> GetRealPath(StoreConfig &config, ContextParam ¶m); -} // namespace OHOS::AppDataMgrJsKit::JSUtils - -#endif \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_store.h b/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_store.h deleted file mode 100644 index 24ee51a971f544c776b3139edbb97acccd6c7024..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_store.h +++ /dev/null @@ -1,69 +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. -*/ -#ifndef OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_STORE_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_STORE_H - -#include -#include -#include -#include - -#include "gdb_store.h" -#include "js_proxy.h" -#include "js_uv_queue.h" -#include "napi/native_api.h" -#include "napi/native_common.h" -#include "napi/native_node_api.h" - -namespace OHOS::GraphStoreJsKit { -using namespace DistributedDataAip; -#define ASSERT_CALL(env, theCall, object) \ - do { \ - if ((theCall) != napi_ok) { \ - delete (object); \ - GET_AND_THROW_LAST_ERROR((env)); \ - return nullptr; \ - } \ - } while (0) - -using Descriptor = std::function(void)>; -class GdbStoreProxy : public GraphStoreJsKit::JSProxy { -public: - static void Init(napi_env env, napi_value exports); - static napi_value NewInstance(napi_env env, std::shared_ptr value, bool isSystemAppCalled); - GdbStoreProxy(); - ~GdbStoreProxy(); - GdbStoreProxy(std::shared_ptr gdbStore); - GdbStoreProxy &operator=(std::shared_ptr GdbStore); - bool IsSystemAppCalled(); - static constexpr int32_t MAX_GQL_LEN = 1024 * 1024; - -private: - static napi_value Initialize(napi_env env, napi_callback_info info); - static napi_value Read(napi_env env, napi_callback_info info); - static napi_value Write(napi_env env, napi_callback_info info); - static napi_value CreateTransaction(napi_env env, napi_callback_info info); - static napi_value Close(napi_env env, napi_callback_info info); - - static Descriptor GetDescriptors(); - - static napi_value New(napi_env env, napi_callback_info info); - static void Destructor(napi_env env, void *nativeObject, void *finalize_hint); - - bool isSystemAppCalled_ = false; - std::shared_ptr queue_; -}; -} // namespace OHOS::GraphStoreJsKit -#endif \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/src/napi_async_call.cpp b/relational_store/frameworks/js/napi/graphstore/src/napi_async_call.cpp deleted file mode 100644 index 9b045ae83f05e4eea80ae7eb1dc3a373190d7dea..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/graphstore/src/napi_async_call.cpp +++ /dev/null @@ -1,247 +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. - */ -#define LOG_TAG "GdbAsyncCall" -#include "napi_async_call.h" - -#include "db_trace.h" -#include "js_native_api_types.h" -#include "logger.h" - -namespace OHOS::GraphStoreJsKit { -bool g_async = true; // do not reset the value, used in DECLARE_NAPI_FUNCTION_WITH_DATA only -bool g_sync = false; // do not reset the value, used in DECLARE_NAPI_FUNCTION_WITH_DATA only -thread_local AsyncCall::Record AsyncCall::record_; -void ContextBase::SetAction( - napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output) -{ - env_ = env; - size_t argc = MAX_INPUT_COUNT; - napi_value self = nullptr; - napi_value argv[MAX_INPUT_COUNT] = { nullptr }; - void *data = nullptr; - napi_status status = napi_get_cb_info(env, info, &argc, argv, &self, &data); - if (status == napi_ok && argc > 0) { - napi_valuetype valueType = napi_undefined; - status = napi_typeof(env, argv[argc - 1], &valueType); - if (status == napi_ok && valueType == napi_function) { - LOG_DEBUG("asyncCall set callback"); - if (argc == 1) { - error = std::make_shared("1"); - } else { - status = napi_create_reference(env, argv[argc - 1], 1, &callback_); - argc = argc - 1; - } - } - } - if (data) { - isAsync_ = *reinterpret_cast(data); - } - - // int -->input_(env, argc, argv, self) - if (status == napi_ok) { - input(env, argc, argv, self); - } else { - error = std::make_shared("Failed to set action."); - } - - // if input return is not ok, then napi_throw_error context error - GDB_NAPI_ASSERT_BASE(env, error == nullptr, error, NAPI_RETVAL_NOTHING); - output_ = std::move(output); - exec_ = std::move(exec); - napi_create_reference(env, self, 1, &self_); -} - -void ContextBase::SetAll( - napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output) -{ - env_ = env; - size_t argc = MAX_INPUT_COUNT; - napi_value self = nullptr; - napi_value argv[MAX_INPUT_COUNT] = { nullptr }; - NAPI_CALL_RETURN_VOID(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); - - // int -->input_(env, argc, argv, self) - input(env, argc, argv, self); - - // if input return is not ok, then napi_throw_error context error - GDB_NAPI_ASSERT_BASE(env, error == nullptr, error, NAPI_RETVAL_NOTHING); - output_ = std::move(output); - exec_ = std::move(exec); - napi_create_reference(env, self, 1, &self_); -} - -void ContextBase::SetError(std::shared_ptr err) -{ - error = err; -} - -ContextBase::~ContextBase() -{ - if (env_ == nullptr) { - return; - } - if (work_ != nullptr) { - napi_delete_async_work(env_, work_); - work_ = nullptr; - } - if (callback_ != nullptr) { - napi_delete_reference(env_, callback_); - callback_ = nullptr; - } - napi_delete_reference(env_, self_); - env_ = nullptr; -} - -void AsyncCall::SetBusinessError(napi_env env, std::shared_ptr error, napi_value *businessError) -{ - LOG_DEBUG("SetBusinessError enter"); - // if error is not inner error - if (error != nullptr) { - napi_value code = nullptr; - napi_value msg = nullptr; - napi_create_int32(env, error->GetCode(), &code); - napi_create_string_utf8(env, error->GetMessage().c_str(), NAPI_AUTO_LENGTH, &msg); - napi_create_error(env, code, msg, businessError); - } -} - -napi_value AsyncCall::Call(napi_env env, std::shared_ptr context, const char *fun) -{ - record_.total_.times_++; - record_.total_.lastTime_ = - std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) - .count(); - context->executed_ = record_.executed_; - context->fun = (fun == nullptr || fun[0] == '\0') ? "RelationalStoreAsyncCall" : fun; - return context->isAsync_ ? Async(env, context) : Sync(env, context); -} - -napi_value AsyncCall::Async(napi_env env, std::shared_ptr context) -{ - napi_value promise = nullptr; - if (context->callback_ == nullptr) { - napi_status status = napi_create_promise(env, &context->defer_, &promise); - GDB_NAPI_ASSERT_BASE(env, status == napi_ok, - std::make_shared("failed(" + std::to_string(status) + ") to create promise"), nullptr); - } else { - napi_get_undefined(env, &promise); - } - context->keep_ = context; - napi_value resource = nullptr; - napi_create_string_utf8(env, context->fun, NAPI_AUTO_LENGTH, &resource); - // create async work, execute function is OnExecute, complete function is OnComplete - napi_create_async_work(env, nullptr, resource, AsyncCall::OnExecute, AsyncCall::OnComplete, - reinterpret_cast(context.get()), &context->work_); - // add async work to execute queue - auto status = napi_queue_async_work_with_qos(env, context->work_, napi_qos_user_initiated); - if (status != napi_ok) { - napi_get_undefined(env, &promise); - } - auto report = (record_.total_.times_.load() - record_.completed_.times_.load()) / EXCEPT_DELTA; - if (report > record_.reportTimes_ && record_.executed_ != nullptr) { - LOG_WARN("Warning:Times:(C:%{public}" PRId64 ", E:%{public}" PRId64 ", F:%{public}" PRId64 ") Last time(" - "C:%{public}" PRId64 ", E:%{public}" PRId64 ", F:%{public}" PRId64 ")", - record_.total_.times_.load(), record_.executed_->times_.load(), record_.completed_.times_.load(), - record_.total_.lastTime_, record_.executed_->lastTime_, record_.completed_.lastTime_); - } - record_.reportTimes_ = report; - return promise; -} - -napi_value AsyncCall::Sync(napi_env env, std::shared_ptr context) -{ - OnExecute(env, reinterpret_cast(context.get())); - OnComplete(env, reinterpret_cast(context.get())); - if (context->execCode_ != DistributedDataAip::E_OK) { - napi_value error; - SetBusinessError(env, context->error, &error); - napi_throw(env, error); - } - return context->result_; -} - -void AsyncCall::OnExecute(napi_env env, void *data) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - ContextBase *context = reinterpret_cast(data); - if (context->executed_ != nullptr) { - context->executed_->times_++; - context->executed_->lastTime_ = - std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) - .count(); - } - if (context->error == nullptr && context->exec_) { - context->execCode_ = context->exec_(); - } - context->exec_ = nullptr; -} - -void AsyncCall::OnComplete(napi_env env, void *data) -{ - ContextBase *context = reinterpret_cast(data); - if (context->execCode_ != DistributedDataAip::E_OK) { - context->SetError(std::make_shared(context->execCode_)); - } - // if async execute status is not napi_ok then un-execute out function - if ((context->error == nullptr) && context->output_) { - context->output_(env, context->result_); - } - context->output_ = nullptr; - record_.completed_.times_++; - record_.completed_.lastTime_ = - std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) - .count(); -} - -void AsyncCall::OnComplete(napi_env env, napi_status status, void *data) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - OnComplete(env, data); - OnReturn(env, status, data); -} - -void AsyncCall::OnReturn(napi_env env, napi_status status, void *data) -{ - ContextBase *context = reinterpret_cast(data); - napi_value result[ARG_BUTT] = { 0 }; - // if out function status is ok then async renturn output data, else return error. - if (context->error == nullptr) { - napi_get_undefined(env, &result[ARG_ERROR]); - if (context->result_ != nullptr) { - result[ARG_DATA] = context->result_; - } else { - napi_get_undefined(env, &result[ARG_DATA]); - } - } else { - SetBusinessError(env, context->error, &result[ARG_ERROR]); - napi_get_undefined(env, &result[ARG_DATA]); - } - if (context->defer_ != nullptr) { - // promise - if (status == napi_ok && (context->error == nullptr)) { - napi_resolve_deferred(env, context->defer_, result[ARG_DATA]); - } else { - napi_reject_deferred(env, context->defer_, result[ARG_ERROR]); - } - } else { - // callback - napi_value callback = nullptr; - napi_get_reference_value(env, context->callback_, &callback); - napi_value returnValue = nullptr; - napi_call_function(env, nullptr, callback, ARG_BUTT, result, &returnValue); - } - context->keep_.reset(); -} -} // namespace OHOS::GraphStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_const_properties.cpp b/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_const_properties.cpp deleted file mode 100644 index 124243c1d1996203e06c4e44631fcd693bb08421..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_const_properties.cpp +++ /dev/null @@ -1,51 +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 "napi_gdb_const_properties.h" - -#include "gdb_common.h" -#include "gdb_store.h" -#include "js_utils.h" - -namespace OHOS::GraphStoreJsKit { -using namespace AppDataMgrJsKit; -using namespace DistributedDataAip; -#define SET_NAPI_PROPERTY(object, prop, value) \ - napi_set_named_property((env), (object), (prop), JSUtils::Convert2JSValue((env), (value))) - -static napi_value ExportSecurityLevel(napi_env env) -{ - napi_value securityLevel = nullptr; - napi_create_object(env, &securityLevel); - - SET_NAPI_PROPERTY(securityLevel, "S1", 1); - SET_NAPI_PROPERTY(securityLevel, "S2", 2); - SET_NAPI_PROPERTY(securityLevel, "S3", 3); - SET_NAPI_PROPERTY(securityLevel, "S4", 4); - - napi_object_freeze(env, securityLevel); - return securityLevel; -} - -napi_status InitConstProperties(napi_env env, napi_value exports) -{ - const napi_property_descriptor properties[] = { - DECLARE_NAPI_PROPERTY("SecurityLevel", ExportSecurityLevel(env)), - }; - - size_t count = sizeof(properties) / sizeof(properties[0]); - return napi_define_properties(env, exports, count, properties); -} -} // namespace OHOS::GraphStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_error.cpp b/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_error.cpp deleted file mode 100644 index 042c9c64a26cc6fd949ddebbf3982e0b93ae3a29..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_error.cpp +++ /dev/null @@ -1,60 +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 "napi_gdb_error.h" - -#include - -#include "gdb_errors.h" - -namespace OHOS::GraphStoreJsKit { -using namespace DistributedDataAip; -static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = { - { E_INVALID_ARGS, 401, "Parameter error." }, - { E_GRD_DATA_CORRUPTED, 31300001, "Database corrupted." }, - { E_GRD_DB_INSTANCE_ABNORMAL, 31300002, "Already closed." }, - { E_DATABASE_BUSY, 31300003, "The database is busy." }, - { E_GRD_FAILED_MEMORY_ALLOCATE, 31300004, "The database is out of memory." }, - { E_GRD_DISK_SPACE_FULL, 31300005, "The database is full." }, - { E_GRD_DUPLICATE_PARAM, 31300006, - "A duplicate graph name, vertex or edge type, or vertex or edge property name exists." }, - { E_GRD_UNDEFINED_PARAM, 31300007, - "The graph name, vertex or edge type, or vertex or edge property is not defined." }, - { E_GRD_INVALID_NAME, 31300008, - "The graph name, vertex or edge type, or vertex or edge property name does not conform to constraints." }, - { E_GRD_SYNTAX_ERROR, 31300009, "The GQL statement syntax error." }, - { E_GRD_SEMANTIC_ERROR, 31300010, "The GQL statement semantic error." }, - { E_GRD_OVER_LIMIT, 31300012, - "The number of graph names, vertex or edge types, or vertex or edge properties exceeds the limit." }, - { E_GRD_DATA_CONFLICT, 31300013, "A conflicting constraint already exists." }, - { E_DBPATH_ACCESS_FAILED, 31300014, "Invalid database path." }, - { E_CONFIG_INVALID_CHANGE, 31300015, "Config changed." }, -}; - -std::optional GetJsErrorCode(int32_t errorCode) -{ - auto jsErrorCode = JsErrorCode{ errorCode, -1, "" }; - auto iter = std::lower_bound(JS_ERROR_CODE_MSGS, - JS_ERROR_CODE_MSGS + sizeof(JS_ERROR_CODE_MSGS) / sizeof(JS_ERROR_CODE_MSGS[0]), jsErrorCode, - [](const JsErrorCode &jsErrorCode1, const JsErrorCode &jsErrorCode2) { - return jsErrorCode1.status < jsErrorCode2.status; - }); - if (iter < JS_ERROR_CODE_MSGS + sizeof(JS_ERROR_CODE_MSGS) / sizeof(JS_ERROR_CODE_MSGS[0]) && - iter->status == errorCode) { - return *iter; - } - return std::nullopt; -} -} // namespace OHOS::GraphStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_js_utils.cpp b/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_js_utils.cpp deleted file mode 100644 index 3034bc9ce9e644f16f393d87c9d93ed8c22b48a8..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_js_utils.cpp +++ /dev/null @@ -1,189 +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. -*/ -#define LOG_TAG "GdbJSUtil" -#include "napi_gdb_js_utils.h" - -#include "gdb_utils.h" -#include "js_ability.h" -#include "securec.h" - -namespace OHOS::AppDataMgrJsKit::JSUtils { -constexpr int MAX_PATH_LENGTH = 1024; - -int32_t GetCurrentAbilityParam(napi_env env, napi_value jsValue, ContextParam ¶m) -{ - std::shared_ptr context = JSAbility::GetCurrentAbility(env, jsValue); - if (context == nullptr) { - return napi_invalid_arg; - } - param.baseDir = context->GetDatabaseDir(); - param.moduleName = context->GetModuleName(); - param.area = context->GetArea(); - param.bundleName = context->GetBundleName(); - param.isSystemApp = context->IsSystemAppCalled(); - return napi_ok; -} - -template<> -int32_t Convert2Value(napi_env env, napi_value jsValue, ContextParam ¶m) -{ - if (jsValue == nullptr) { - LOG_INFO("hasProp is false -> fa stage"); - param.isStageMode = false; - return GetCurrentAbilityParam(env, jsValue, param); - } - - int32_t status = GetNamedProperty(env, jsValue, "stageMode", param.isStageMode); - ASSERT(status == napi_ok, "get stageMode param failed", napi_invalid_arg); - if (!param.isStageMode) { - LOG_WARN("isStageMode is false -> fa stage"); - return GetCurrentAbilityParam(env, jsValue, param); - } - LOG_DEBUG("stage mode branch"); - status = GetNamedProperty(env, jsValue, "databaseDir", param.baseDir); - ASSERT(status == napi_ok, "get databaseDir failed.", napi_invalid_arg); - status = GetNamedProperty(env, jsValue, "area", param.area, true); - ASSERT(status == napi_ok, "get area failed.", napi_invalid_arg); - - napi_value hapInfo = nullptr; - GetNamedProperty(env, jsValue, "currentHapModuleInfo", hapInfo); - if (hapInfo != nullptr) { - status = GetNamedProperty(env, hapInfo, "name", param.moduleName); - ASSERT(status == napi_ok, "get currentHapModuleInfo.name failed.", napi_invalid_arg); - } - - napi_value appInfo = nullptr; - GetNamedProperty(env, jsValue, "applicationInfo", appInfo); - if (appInfo != nullptr) { - status = GetNamedProperty(env, appInfo, "name", param.bundleName); - ASSERT(status == napi_ok, "get applicationInfo.name failed.", napi_invalid_arg); - status = GetNamedProperty(env, appInfo, "systemApp", param.isSystemApp, true); - ASSERT(status == napi_ok, "get applicationInfo.systemApp failed.", napi_invalid_arg); - int32_t hapVersion = JSAbility::GetHapVersion(env, jsValue); - JSUtils::SetHapVersion(hapVersion); - } - return napi_ok; -} - -template<> -int32_t Convert2Value(napi_env env, napi_value jsValue, StoreConfig &config) -{ - std::string name; - auto status = GetNamedProperty(env, jsValue, "name", name); - ASSERT(OK == status, "get name failed.", napi_invalid_arg); - config.SetName(name); - - int32_t securityLevel; - status = GetNamedProperty(env, jsValue, "securityLevel", securityLevel); - ASSERT(OK == status, "get securityLevel failed.", napi_invalid_arg); - config.SetSecurityLevel(securityLevel); - - bool isEncrypt = false; - status = GetNamedProperty(env, jsValue, "encrypt", isEncrypt, true); - ASSERT(OK == status, "get encrypt failed.", napi_invalid_arg); - config.SetEncryptStatus(isEncrypt); - return napi_ok; -} - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &result) -{ - std::vector descriptors = { - DECLARE_JS_PROPERTY(env, "records", result->GetAllData()), - }; - - napi_value object = nullptr; - NAPI_CALL_RETURN_ERR( - napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); - return object; -} - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &vertex) -{ - std::vector descriptors = { - DECLARE_JS_PROPERTY(env, "vid", vertex->GetId()), - DECLARE_JS_PROPERTY(env, "labels", vertex->GetLabels()), - DECLARE_JS_PROPERTY(env, "properties", vertex->GetProperties()), - }; - - napi_value object = nullptr; - NAPI_CALL_RETURN_ERR( - napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); - return object; -} - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &edge) -{ - std::vector descriptors = { - DECLARE_JS_PROPERTY(env, "eid", edge->GetId()), - DECLARE_JS_PROPERTY(env, "type", edge->GetLabel()), - DECLARE_JS_PROPERTY(env, "startVid", edge->GetSourceId()), - DECLARE_JS_PROPERTY(env, "endVid", edge->GetTargetId()), - DECLARE_JS_PROPERTY(env, "properties", edge->GetProperties()), - }; - - napi_value object = nullptr; - NAPI_CALL_RETURN_ERR( - napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); - return object; -} - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &pathSegment) -{ - std::vector descriptors = { - DECLARE_JS_PROPERTY(env, "start", pathSegment->GetSourceVertex()), - DECLARE_JS_PROPERTY(env, "end", pathSegment->GetTargetVertex()), - DECLARE_JS_PROPERTY(env, "edge", pathSegment->GetEdge()), - }; - - napi_value object = nullptr; - NAPI_CALL_RETURN_ERR( - napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); - return object; -} - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &path) -{ - std::vector descriptors = { - DECLARE_JS_PROPERTY(env, "start", path->GetStart()), - DECLARE_JS_PROPERTY(env, "end", path->GetEnd()), - DECLARE_JS_PROPERTY(env, "length", path->GetPathLength()), - DECLARE_JS_PROPERTY(env, "segments", path->GetSegments()), - }; - - napi_value object = nullptr; - NAPI_CALL_RETURN_ERR( - napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); - return object; -} - -std::tuple> GetRealPath(StoreConfig &config, ContextParam ¶m) -{ - CHECK_RETURN_CORE(config.GetName().find(PATH_SPLIT) == std::string::npos, GDB_DO_NOTHING, - std::make_tuple(ERR, std::make_shared("StoreConfig.name", "a database name without path."))); - std::string databaseDir; - databaseDir.append(param.baseDir).append("/gdb"); - auto errorCode = DistributedDataAip::GdbUtils::CreateDirectory(databaseDir); - std::string realPath = databaseDir + "/" + config.GetName(); - CHECK_RETURN_CORE(errorCode == E_OK && realPath.length() <= MAX_PATH_LENGTH, GDB_DO_NOTHING, - std::make_tuple(ERR, std::make_shared("database path", "a valid path."))); - config.SetPath(databaseDir); - return std::make_tuple(E_OK, nullptr); -} -} \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_store.cpp b/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_store.cpp deleted file mode 100644 index 9a05f8c539ac38a09706989d41d8f1fcd70ca1c0..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_store.cpp +++ /dev/null @@ -1,301 +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. -*/ -#define LOG_TAG "GdbStoreProxy" -#include "napi_gdb_store.h" - -#include -#include -#include -#include - -#include "db_trace.h" -#include "js_utils.h" -#include "logger.h" -#include "napi_gdb_context.h" -#include "napi_gdb_error.h" -#include "napi_gdb_js_utils.h" -#include "napi_gdb_transaction.h" - -namespace OHOS::GraphStoreJsKit { - -GdbStoreProxy::GdbStoreProxy() -{ -} - -GdbStoreProxy::~GdbStoreProxy() -{ -} - -GdbStoreProxy::GdbStoreProxy(std::shared_ptr gdbStore) -{ - if (GetInstance() == gdbStore) { - return; - } - SetInstance(std::move(gdbStore)); -} - -GdbStoreProxy &GdbStoreProxy::operator=(std::shared_ptr gdbStore) -{ - if (GetInstance() == gdbStore) { - return *this; - } - SetInstance(std::move(gdbStore)); - return *this; -} - -bool GdbStoreProxy::IsSystemAppCalled() -{ - return isSystemAppCalled_; -} - -Descriptor GdbStoreProxy::GetDescriptors() -{ - return []() -> std::vector { - std::vector properties = { - DECLARE_NAPI_FUNCTION("read", Read), - DECLARE_NAPI_FUNCTION("write", Write), - DECLARE_NAPI_FUNCTION("createTransaction", CreateTransaction), - DECLARE_NAPI_FUNCTION("close", Close), - }; - return properties; - }; -} - -void GdbStoreProxy::Init(napi_env env, napi_value exports) -{ - auto jsCtor = OHOS::AppDataMgrJsKit::JSUtils::DefineClass( - env, "ohos.data.graphStore", "GraphStore", GetDescriptors(), Initialize); - NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, exports, "GraphStore", jsCtor)); -} - -void GdbStoreProxy::Destructor(napi_env env, void *nativeObject, void *finalize_hint) -{ - auto *obj = static_cast(nativeObject); - delete obj; -} - -napi_value GdbStoreProxy::New(napi_env env, napi_callback_info info) -{ - size_t argc = 1; - napi_value argv[1] = { 0 }; - napi_value thisVar = nullptr; - napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr); - - // get native object - auto *obj = new GdbStoreProxy(); - ASSERT_CALL(env, - napi_wrap(env, thisVar, obj, GdbStoreProxy::Destructor, - nullptr, // finalize_hint - nullptr), - obj); - return thisVar; -} - -napi_value GdbStoreProxy::Initialize(napi_env env, napi_callback_info info) -{ - napi_value self = nullptr; - NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &self, nullptr)); - auto finalize = [](napi_env env, void *data, void *hint) { - if (data != hint) { - LOG_ERROR("GdbStoreProxy memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, uintptr_t(data), - uintptr_t(hint)); - return; - } - GdbStoreProxy *proxy = reinterpret_cast(data); - proxy->SetInstance(nullptr); - delete proxy; - }; - auto *proxy = new (std::nothrow) GdbStoreProxy(); - if (proxy == nullptr) { - return nullptr; - } - napi_status status = napi_wrap(env, self, proxy, finalize, proxy, nullptr); - if (status != napi_ok) { - LOG_ERROR("GdbStoreProxy napi_wrap failed! code:%{public}d!", status); - finalize(env, proxy, proxy); - return nullptr; - } - return self; -} - -napi_value GdbStoreProxy::NewInstance(napi_env env, std::shared_ptr value, bool isSystemAppCalled) -{ - if (value == nullptr) { - LOG_ERROR("dbstore is nullptr"); - return nullptr; - } - napi_value cons = OHOS::AppDataMgrJsKit::JSUtils::GetClass(env, "ohos.data.graphStore", "GraphStore"); - if (cons == nullptr) { - LOG_ERROR("Constructor of ResultSet is nullptr!"); - return nullptr; - } - - napi_value instance = nullptr; - auto status = napi_new_instance(env, cons, 0, nullptr, &instance); - if (status != napi_ok) { - LOG_ERROR("GdbStoreProxy::NewInstance napi_new_instance failed! code:%{public}d!", status); - return nullptr; - } - - GdbStoreProxy *proxy = nullptr; - status = napi_unwrap(env, instance, reinterpret_cast(&proxy)); - if (proxy == nullptr) { - LOG_ERROR("GdbStoreProxy::NewInstance native instance is nullptr! code:%{public}d!", status); - return instance; - } - proxy->queue_ = std::make_shared(env); - proxy->SetInstance(std::move(value)); - proxy->isSystemAppCalled_ = isSystemAppCalled; - return instance; -} - -GdbStoreProxy *GetNativeInstance(napi_env env, napi_value self) -{ - GdbStoreProxy *proxy = nullptr; - napi_status status = napi_unwrap(env, self, reinterpret_cast(&proxy)); - if (proxy == nullptr) { - LOG_ERROR("GdbStoreProxy native instance is nullptr! code:%{public}d!", status); - return nullptr; - } - return proxy; -} - -int ParseThis(const napi_env &env, const napi_value &self, const std::shared_ptr &context) -{ - GdbStoreProxy *obj = GetNativeInstance(env, self); - CHECK_RETURN_SET(obj != nullptr, std::make_shared("GdbStore", "not nullptr.")); - CHECK_RETURN_SET(obj->GetInstance() != nullptr, std::make_shared(E_GRD_DB_INSTANCE_ABNORMAL)); - context->boundObj = obj; - context->gdbStore = obj->GetInstance(); - return OK; -} - -int ParseGql(const napi_env env, const napi_value arg, const std::shared_ptr &context) -{ - context->gql = OHOS::AppDataMgrJsKit::JSUtils::Convert2String(env, arg); - CHECK_RETURN_SET(!context->gql.empty(), std::make_shared("gql", "not empty")); - CHECK_RETURN_SET(context->gql.size() <= GdbStoreProxy::MAX_GQL_LEN, - std::make_shared("gql", "too long")); - return OK; -} - -napi_value GdbStoreProxy::Read(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(argc == 1, std::make_shared(" 1 ")); - CHECK_RETURN(OK == ParseThis(env, self, context)); - CHECK_RETURN(OK == ParseGql(env, argv[0], context)); - }; - auto exec = [context]() -> int { - CHECK_RETURN_ERR(context->gdbStore != nullptr); - auto queryResult = context->StealGdbStore()->QueryGql(context->gql); - context->result = queryResult.second; - context->intOutput = queryResult.first; - return OK; - }; - auto output = [context](napi_env env, napi_value &result) { - result = AppDataMgrJsKit::JSUtils::Convert2JSValue(env, context->result); - CHECK_RETURN_SET_E(context->intOutput == OK, std::make_shared(context->intOutput)); - }; - context->SetAction(env, info, input, exec, output); - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} - -napi_value GdbStoreProxy::Write(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(argc == 1, std::make_shared(" 1 ")); - CHECK_RETURN(OK == ParseThis(env, self, context)); - CHECK_RETURN(OK == ParseGql(env, argv[0], context)); - }; - auto exec = [context]() -> int { - CHECK_RETURN_ERR(context->gdbStore != nullptr); - auto executeResult = context->StealGdbStore()->ExecuteGql(context->gql); - context->result = executeResult.second; - context->intOutput = executeResult.first; - return OK; - }; - auto output = [context](napi_env env, napi_value &result) { - result = AppDataMgrJsKit::JSUtils::Convert2JSValue(env, context->result); - CHECK_RETURN_SET_E(context->intOutput == OK, std::make_shared(context->intOutput)); - }; - context->SetAction(env, info, input, exec, output); - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} - -napi_value GdbStoreProxy::CreateTransaction(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(argc == 0, std::make_shared(" 0 ")); - CHECK_RETURN(OK == ParseThis(env, self, context)); - }; - auto exec = [context]() -> int { - CHECK_RETURN_ERR(context->gdbStore != nullptr); - int32_t code = E_ERROR; - std::tie(code, context->transaction) = context->StealGdbStore()->CreateTransaction(); - if (code != E_OK) { - context->transaction = nullptr; - return code; - } - return context->transaction != nullptr ? OK : E_ERROR; - }; - auto output = [context](napi_env env, napi_value &result) { - result = GdbTransactionProxy::NewInstance(env, context->transaction); - CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_INNER_ERROR)); - }; - context->SetAction(env, info, input, exec, output); - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} - -napi_value GdbStoreProxy::Close(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - GdbStoreProxy *proxy = GetNativeInstance(env, self); - CHECK_RETURN_SET(proxy != nullptr, std::make_shared("GdbStore", "not nullptr.")); - if (proxy->GetInstance() == nullptr) { - LOG_WARN("GdbStoreProxy native instance is nullptr!"); - return OK; - } - context->boundObj = proxy; - context->gdbStore = proxy->GetInstance(); - - auto *obj = reinterpret_cast(context->boundObj); - obj->SetInstance(nullptr); - return OK; - }; - auto exec = [context]() -> int { - context->gdbStore = nullptr; - return OK; - }; - auto output = [context](napi_env env, napi_value &result) { - napi_status status = napi_get_undefined(env, &result); - CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); - }; - context->SetAction(env, info, input, exec, output); - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} -} // namespace OHOS::GraphStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_store_helper.cpp b/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_store_helper.cpp deleted file mode 100644 index 50f5df70d3e93283c8ff51a9d3b340a9a8bf746a..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_store_helper.cpp +++ /dev/null @@ -1,109 +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. -*/ -#define LOG_TAG "GdbStoreHelperProxy" -#include "napi_gdb_store_helper.h" - -#include - -#include "db_trace.h" -#include "gdb_helper.h" -#include "logger.h" -#include "napi_gdb_context.h" -#include "napi_gdb_js_utils.h" -#include "napi_gdb_store.h" - -namespace OHOS::GraphStoreJsKit { -using namespace OHOS::DistributedDataAip; - -static constexpr int MAX_GDB_DB_NAME_LENGTH = 128; - -bool IsValidDbName(const std::string &name) -{ - if (name.empty() || name.size() > MAX_GDB_DB_NAME_LENGTH) { - return false; - } - const std::regex pattern("^[a-zA-Z0-9_]+$"); - return std::regex_match(name, pattern); -} - -napi_value GetStore(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context, info](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(argc == 2, std::make_shared(" 2 ")); - int errCode = AppDataMgrJsKit::JSUtils::Convert2Value(env, argv[0], context->param); - CHECK_RETURN_SET_E(OK == errCode, std::make_shared("Illegal context.")); - CHECK_RETURN_SET_E(context->param.isSystemApp, std::make_shared()); - errCode = AppDataMgrJsKit::JSUtils::Convert2Value(env, argv[1], context->config); - CHECK_RETURN_SET_E(OK == errCode, std::make_shared("Illegal StoreConfig or name.")); - CHECK_RETURN_SET_E(IsValidDbName(context->config.GetName()), std::make_shared("Illegal name.")); - auto [code, err] = AppDataMgrJsKit::JSUtils::GetRealPath(context->config, context->param); - CHECK_RETURN_SET_E(OK == code, err); - context->config.SetBundleName(context->param.bundleName); - }; - auto exec = [context]() -> int { - context->gdbStore = GDBHelper::GetDBStore(context->config, context->intOutput); - return OK; - }; - auto output = [context](napi_env env, napi_value &result) { - CHECK_RETURN_SET_E(context->intOutput == OK, std::make_shared(context->intOutput)); - result = GdbStoreProxy::NewInstance(env, context->gdbStore, context->param.isSystemApp); - CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_INNER_ERROR)); - }; - context->SetAction(env, info, input, exec, output); - - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} - -napi_value DeleteStore(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context, info](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(argc == 2, std::make_shared(" 2 ")); - int errCode = AppDataMgrJsKit::JSUtils::Convert2Value(env, argv[0], context->param); - CHECK_RETURN_SET_E(OK == errCode, std::make_shared("Illegal context.")); - CHECK_RETURN_SET_E(context->param.isSystemApp, std::make_shared()); - errCode = AppDataMgrJsKit::JSUtils::Convert2Value(env, argv[1], context->config); - CHECK_RETURN_SET_E(OK == errCode, std::make_shared("Illegal StoreConfig or name.")); - CHECK_RETURN_SET_E(IsValidDbName(context->config.GetName()), std::make_shared("Illegal name.")); - auto [code, err] = AppDataMgrJsKit::JSUtils::GetRealPath(context->config, context->param); - CHECK_RETURN_SET_E(OK == code, err); - }; - auto exec = [context]() -> int { - context->intOutput = GDBHelper::DeleteDBStore(context->config); - return OK; - }; - auto output = [context](napi_env env, napi_value &result) { - CHECK_RETURN_SET_E(context->intOutput == OK, std::make_shared(context->intOutput)); - }; - context->SetAction(env, info, input, exec, output); - - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} - -napi_value InitGdbHelper(napi_env env, napi_value exports) -{ - napi_property_descriptor properties[] = { - DECLARE_NAPI_FUNCTION_WITH_DATA("getStore", GetStore, AIP_ASYNC), - DECLARE_NAPI_FUNCTION_WITH_DATA("deleteStore", DeleteStore, AIP_ASYNC), - }; - NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(*properties), properties)); - return exports; -} -} // namespace OHOS::GraphStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_transaction.cpp b/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_transaction.cpp deleted file mode 100644 index 00d55c10fac99a577f3d5e7bbf9c99a93ebeb579..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_transaction.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* -* Copyright (c) 2025 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 "GdbTransactionProxy" -#include "napi_gdb_transaction.h" - -#include -#include -#include -#include - -#include "db_trace.h" -#include "js_utils.h" -#include "logger.h" -#include "napi_gdb_context.h" -#include "napi_gdb_error.h" -#include "napi_gdb_js_utils.h" - -namespace OHOS::GraphStoreJsKit { -#define ASSERT_RETURN_SET_ERROR(assertion, paramError) \ - CHECK_RETURN_CORE(assertion, SetError(paramError), ERR) - -constexpr int32_t MAX_GQL_LEN = 1024 * 1024; - -constexpr const char *SPACE_NAME = "ohos.data.graphStore"; -constexpr const char *CLASS_NAME = "Transaction"; - -struct TransactionContext : public ContextBase { - void GetInstance(napi_value self) - { - auto status = napi_unwrap(env_, self, reinterpret_cast(&boundObj)); - if (status != napi_ok || boundObj == nullptr) { - LOG_ERROR("GdbTransactionProxy native instance is nullptr! code:%{public}d!", status); - return; - } - transaction_ = reinterpret_cast(boundObj)->GetInstance(); - } - std::shared_ptr StealTransaction() - { - auto trans = std::move(transaction_); - transaction_ = nullptr; - return trans; - } - std::shared_ptr transaction_ = nullptr; -}; - -GdbTransactionProxy::~GdbTransactionProxy() -{ -} - -GdbTransactionProxy::GdbTransactionProxy(std::shared_ptr gdbTransaction) -{ - if (GetInstance() == gdbTransaction) { - return; - } - SetInstance(std::move(gdbTransaction)); -} - -napi_value GdbTransactionProxy::Initialize(napi_env env, napi_callback_info info) -{ - napi_value self = nullptr; - NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &self, nullptr)); - auto *proxy = new (std::nothrow) GdbTransactionProxy(); - if (proxy == nullptr) { - return nullptr; - } - auto finalize = [](napi_env env, void *data, void *hint) { - if (data != hint) { - LOG_ERROR("memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, - uintptr_t(data), uintptr_t(hint)); - return; - } - GdbTransactionProxy *proxy = reinterpret_cast(data); - proxy->SetInstance(nullptr); - delete proxy; - }; - napi_status status = napi_wrap(env, self, proxy, finalize, proxy, nullptr); - if (status != napi_ok) { - LOG_ERROR("napi_wrap failed! code:%{public}d!", status); - finalize(env, proxy, proxy); - return nullptr; - } - return self; -} - -void GdbTransactionProxy::Init(napi_env env, napi_value exports) -{ - auto lambda = []() -> std::vector { - std::vector properties = { - DECLARE_NAPI_FUNCTION("read", Read), - DECLARE_NAPI_FUNCTION("write", Write), - DECLARE_NAPI_FUNCTION("commit", Commit), - DECLARE_NAPI_FUNCTION("rollback", Rollback), - }; - return properties; - }; - auto jsCtor = AppDataMgrJsKit::JSUtils::DefineClass(env, SPACE_NAME, CLASS_NAME, lambda, Initialize); - NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, exports, CLASS_NAME, jsCtor)); -} - -napi_value GdbTransactionProxy::NewInstance(napi_env env, std::shared_ptr value) -{ - if (value == nullptr) { - LOG_ERROR("value is nullptr"); - return nullptr; - } - napi_value cons = AppDataMgrJsKit::JSUtils::GetClass(env, SPACE_NAME, CLASS_NAME); - if (cons == nullptr) { - LOG_ERROR("Constructor of Transaction is nullptr!"); - return nullptr; - } - - napi_value instance = nullptr; - auto status = napi_new_instance(env, cons, 0, nullptr, &instance); - if (status != napi_ok) { - LOG_ERROR("create new instance failed! code:%{public}d!", status); - return nullptr; - } - - GdbTransactionProxy *proxy = nullptr; - status = napi_unwrap(env, instance, reinterpret_cast(&proxy)); - if (status != napi_ok || proxy == nullptr) { - LOG_ERROR("native instance is nullptr! code:%{public}d!", status); - return instance; - } - proxy->SetInstance(std::move(value)); - return instance; -} - -struct ReadWriteContext : public TransactionContext { - int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self) - { - ASSERT_RETURN_SET_ERROR(argc == 1, std::make_shared(" 1 ")); - GetInstance(self); - ASSERT_RETURN_SET_ERROR(transaction_ != nullptr, std::make_shared("transaction", "not nullptr.")); - gql = AppDataMgrJsKit::JSUtils::Convert2String(env, argv[0]); - ASSERT_RETURN_SET_ERROR(!gql.empty(), std::make_shared("gql", "not empty")); - ASSERT_RETURN_SET_ERROR(gql.size() <= MAX_GQL_LEN, - std::make_shared("gql", "too long")); - return OK; - } - std::string gql; - std::shared_ptr result; - int32_t errCode; -}; - -napi_value GdbTransactionProxy::Read(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - context->Parse(env, argc, argv, self); - }; - auto exec = [context]() -> int { - CHECK_RETURN_ERR(context->transaction_ != nullptr); - std::tie(context->errCode, context->result) = context->StealTransaction()->Query(context->gql); - return context->errCode; - }; - auto output = [context](napi_env env, napi_value &result) { - result = AppDataMgrJsKit::JSUtils::Convert2JSValue(env, context->result); - CHECK_RETURN_SET_E(context->errCode == OK, std::make_shared(context->errCode)); - }; - context->SetAction(env, info, input, exec, output); - - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} - -napi_value GdbTransactionProxy::Write(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - context->Parse(env, argc, argv, self); - }; - auto exec = [context]() -> int { - CHECK_RETURN_ERR(context->transaction_ != nullptr); - std::tie(context->errCode, context->result) = context->StealTransaction()->Execute(context->gql); - return context->errCode; - }; - auto output = [context](napi_env env, napi_value &result) { - result = AppDataMgrJsKit::JSUtils::Convert2JSValue(env, context->result); - CHECK_RETURN_SET_E(context->errCode == OK, std::make_shared(context->errCode)); - }; - context->SetAction(env, info, input, exec, output); - - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} - -struct CommitRollbackContext : public TransactionContext { - int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self) - { - GetInstance(self); - ASSERT_RETURN_SET_ERROR(transaction_ != nullptr, std::make_shared("transaction", "a transaction.")); - return OK; - } -}; - -napi_value GdbTransactionProxy::Commit(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - context->Parse(env, argc, argv, self); - }; - auto exec = [context]() -> int { - CHECK_RETURN_ERR(context->transaction_ != nullptr); - return context->StealTransaction()->Commit(); - }; - auto output = [context](napi_env env, napi_value &result) { - napi_status status = napi_get_undefined(env, &result); - CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); - }; - context->SetAction(env, info, input, exec, output); - - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} - -napi_value GdbTransactionProxy::Rollback(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - context->Parse(env, argc, argv, self); - }; - auto exec = [context]() -> int { - CHECK_RETURN_ERR(context->transaction_ != nullptr); - return context->StealTransaction()->Rollback(); - }; - auto output = [context](napi_env env, napi_value &result) { - napi_status status = napi_get_undefined(env, &result); - CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); - }; - context->SetAction(env, info, input, exec, output); - - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} -} // namespace OHOS::GraphStoreJsKit diff --git a/relational_store/frameworks/js/napi/rdb/BUILD.gn b/relational_store/frameworks/js/napi/rdb/BUILD.gn index db0236f0d29626692aab1857f44ab36d4cc607b3..7b122293f18b357311bfc9533a4caa063e804bd0 100644 --- a/relational_store/frameworks/js/napi/rdb/BUILD.gn +++ b/relational_store/frameworks/js/napi/rdb/BUILD.gn @@ -24,7 +24,9 @@ ohos_copy("relational_store_declaration") { ohos_shared_library("napi_rdb") { sources = [ "../common/src/js_df_manager.cpp", + "../common/src/js_scope.cpp", "../common/src/js_utils.cpp", + "../common/src/js_uv_queue.cpp", "src/napi_async_call.cpp", "src/napi_rdb_const_properties.cpp", "src/napi_rdb_js_utils.cpp", @@ -32,14 +34,12 @@ ohos_shared_library("napi_rdb") { "src/napi_rdb_store.cpp", "src/napi_rdb_store_helper.cpp", "src/napi_result_set.cpp", - "src/napi_uv_queue.cpp", "src/napi_values_bucket.cpp", ] if (is_mingw || is_mac) { include_dirs = [ "mock/include", - "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_js_common_path}/mock/include", "${relational_store_napi_path}/rdb/mock/include", @@ -71,12 +71,13 @@ ohos_shared_library("napi_rdb") { "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb:native_rdb", ] - external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps = [ + "bounds_checking_function:libsec_static", + "kv_store:datamgr_common", + ] } else { include_dirs = [ "include", - "${datashare_path}/common/include/", - "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_js_common_path}/include", "${relational_store_napi_path}/rdb/include", @@ -100,8 +101,12 @@ ohos_shared_library("napi_rdb") { "bounds_checking_function:libsec_shared", "c_utils:utils", "common_event_service:cesfwk_innerkits", + "data_share:datashare_common_lite", + "eventhandler:libeventhandler", "hilog:libhilog", "hitrace:hitrace_meter", + "ipc:ipc_single", + "kv_store:datamgr_common", "napi:ace_napi", ] } @@ -151,7 +156,6 @@ ohos_shared_library("rdb") { } else { include_dirs = [ "include", - "${datashare_path}/common/include/", "${relational_store_js_common_path}/include", "${relational_store_napi_path}/rdb/include", ] @@ -168,6 +172,7 @@ ohos_shared_library("rdb") { "ability_runtime:abilitykit_native", "ability_runtime:napi_base_context", "c_utils:utils", + "data_share:datashare_common_lite", "hilog:libhilog", "hitrace:hitrace_meter", "napi:ace_napi", diff --git a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_error.h b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_error.h index 79e174a4f9148da55a449bf6a26d9ac5a74638ff..9c3a913c5b2654372592e94b6dbd25ec90f00103 100644 --- a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_error.h +++ b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_error.h @@ -168,19 +168,6 @@ public: }; }; -class DbCorruptedError : public Error { -public: - DbCorruptedError() = default; - std::string GetMessage() override - { - return "Failed open database, database corrupted."; - }; - int GetCode() override - { - return E_DB_CORRUPTED; - }; -}; - class ResultGetError : public Error { public: ResultGetError() = default; diff --git a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_store_observer.h b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_store_observer.h index 5b14315afa8ce7b8f569b0c5020012df5362c8ab..53f5504a2ac7556d68d2a1c67323245cd2db8f66 100644 --- a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_store_observer.h +++ b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_store_observer.h @@ -15,17 +15,23 @@ #ifndef NAPI_RDB_STORE_OBSERVER_H #define NAPI_RDB_STORE_OBSERVER_H - -#include "napi_uv_queue.h" +#include "js_uv_queue.h" #include "rdb_types.h" -namespace OHOS::RdbJsKit { -class NapiRdbStoreObserver : public DistributedRdb::RdbStoreObserver, public NapiUvQueue { +namespace OHOS::RdbJsKit { +using namespace OHOS::AppDataMgrJsKit; +class NapiRdbStoreObserver : public DistributedRdb::RdbStoreObserver, + public std::enable_shared_from_this { public: - explicit NapiRdbStoreObserver(napi_env env, napi_value callback); + explicit NapiRdbStoreObserver(napi_value callback, std::shared_ptr uvQueue); virtual ~NapiRdbStoreObserver() noexcept; - + bool operator==(napi_value value); void OnChange(const std::vector &devices) override; + void Clear(); + +private: + std::shared_ptr uvQueue_; + napi_ref callback_; }; } // namespace OHOS::RdbJsKit #endif diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_async_call.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_async_call.cpp index 8d23e9294c842a59d1db12ffcdf98207cd1bff7d..0b41ed4c59d783981d6541a9a6192d631848f2b1 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_async_call.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_async_call.cpp @@ -30,13 +30,14 @@ void BaseContext::SetAction( napi_value self = nullptr; napi_value argv[MAX_INPUT_COUNT] = { nullptr }; NAPI_CALL_RETURN_VOID(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); - napi_valuetype valueType = napi_undefined; - napi_typeof(env, argv[argc - 1], &valueType); - if (valueType == napi_function) { - LOG_DEBUG("AsyncCall set callback"); - NAPI_CALL_RETURN_VOID(env, napi_create_reference(env, argv[argc - 1], 1, &callback_)); - argc = argc - 1; + if (argc > 0) { + napi_typeof(env, argv[argc - 1], &valueType); + if (valueType == napi_function) { + LOG_DEBUG("AsyncCall set callback"); + NAPI_CALL_RETURN_VOID(env, napi_create_reference(env, argv[argc - 1], 1, &callback_)); + argc = argc - 1; + } } // int -->input_(env, argc, argv, self) int status = input(env, argc, argv, self); diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_predicates.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_predicates.cpp index 5ec99f3bc7d711ec4b0c1e1a3d4ed29b314f0697..b6d6abee5857d1fe49af9610279d4c9c16c9becc 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_predicates.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_predicates.cpp @@ -177,7 +177,7 @@ napi_value RdbPredicatesProxy::NewInstance(napi_env env, std::shared_ptr(&proxy)); - if (status != napi_ok) { + if (status != napi_ok || proxy == nullptr) { LOG_ERROR("RdbPredicatesProxy::NewInstance native instance is nullptr! napi_status:%{public}d!", status); return instance; } @@ -193,6 +193,9 @@ void RdbPredicatesProxy::Destructor(napi_env env, void *nativeObject, void *) LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(nativeObject) & LOWER_24_BITS_MASK); } RdbPredicatesProxy *proxy = static_cast(nativeObject); + if (proxy == nullptr) { + return; + } proxy->predicates_ = std::move(nullptr); delete proxy; } diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp index 7d3bfdcbf1946355b30d9b1af577c724c6338a58..95e2ee2615d77d98106bbbcec15f82241c054da7 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp @@ -153,6 +153,9 @@ napi_value RdbStoreProxy::InnerInitialize(napi_env env, napi_callback_info info, napi_value self = nullptr; NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &self, nullptr)); auto finalize = [](napi_env env, void *data, void *hint) { + if (data == nullptr) { + return; + } auto tid = JSDFManager::GetInstance().GetFreedTid(data); if (tid != 0) { LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); @@ -586,7 +589,6 @@ napi_value RdbStoreProxy::BatchInsert(napi_env env, napi_callback_info info) }; auto output = [context](napi_env env, napi_value &result) -> int { napi_status status = napi_create_int64(env, context->insertNum, &result); - LOG_DEBUG("RdbStoreProxy::BatchInsert end. tableName is: %{public}s.", context->tableName.c_str()); return (status == napi_ok) ? OK : ERR; }; context->SetAction(env, info, input, exec, output); @@ -744,8 +746,8 @@ napi_value RdbStoreProxy::QuerySql(napi_env env, napi_callback_info info) }; auto exec = [context]() { RdbStoreProxy *obj = reinterpret_cast(context->boundObj); -#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr); +#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) context->resultSet = obj->rdbStore_->QueryByStep(context->sql, context->columns); LOG_ERROR("RdbStoreProxy::QuerySql is nullptr ? %{public}d ", context->resultSet == nullptr); return (context->resultSet != nullptr) ? OK : ERR; @@ -1053,7 +1055,7 @@ napi_value RdbStoreProxy::IsInTransaction(napi_env env, napi_callback_info info) napi_value thisObj = nullptr; napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr); RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj); - NAPI_ASSERT(env, rdbStoreProxy != nullptr, "RdbStoreProxy is nullptr"); + NAPI_ASSERT(env, rdbStoreProxy != nullptr && rdbStoreProxy->rdbStore_ != nullptr, "RdbStoreProxy is nullptr"); bool out = rdbStoreProxy->rdbStore_->IsInTransaction(); LOG_DEBUG("RdbStoreProxy::IsInTransaction out is : %{public}d.", out); return JSUtils::Convert2JSValue(env, out); @@ -1113,7 +1115,7 @@ napi_value RdbStoreProxy::SetDistributedTables(napi_env env, napi_callback_info auto exec = [context]() { LOG_DEBUG("RdbStoreProxy::SetDistributedTables Async."); RdbStoreProxy *obj = reinterpret_cast(context->boundObj); - if (obj == nullptr || obj->rdbStore_.get() == nullptr) { + if (obj == nullptr || obj->rdbStore_ == nullptr) { return ERR; } int res = obj->rdbStore_->SetDistributedTables(context->tablesName); @@ -1147,7 +1149,7 @@ napi_value RdbStoreProxy::ObtainDistributedTableName(napi_env env, napi_callback LOG_DEBUG("RdbStoreProxy::ObtainDistributedTableName Async."); RdbStoreProxy *obj = reinterpret_cast(context->boundObj); int errCode = E_ERROR; - if (obj == nullptr || obj->rdbStore_.get() == nullptr) { + if (obj == nullptr || obj->rdbStore_ == nullptr) { return ERR; } auto name = obj->rdbStore_->ObtainDistributedTableName(context->device, context->tableName, errCode); @@ -1186,9 +1188,11 @@ napi_value RdbStoreProxy::Sync(napi_env env, napi_callback_info info) SyncOption option; option.mode = static_cast(context->enumArg); option.isBlock = true; - if (obj == nullptr || obj->rdbStore_.get() == nullptr) { + if (obj == nullptr || obj->rdbStore_ == nullptr || context->predicatesProxy == nullptr || + context->predicatesProxy->GetPredicates() == nullptr) { return ERR; } + int res = obj->rdbStore_->Sync(option, *context->predicatesProxy->GetPredicates(), [context](const SyncResult &result) { context->syncResult = result; }); LOG_INFO("RdbStoreProxy::Sync res is : %{public}d.", res); @@ -1236,8 +1240,9 @@ void RdbStoreProxy::OnDataChangeEvent(napi_env env, size_t argc, napi_value *arg } SubscribeOption option; option.mode = static_cast(mode); - auto observer = std::make_shared(env, argv[1]); - int errCode = rdbStore_->Subscribe(option, observer.get()); + auto uvQueue = std::make_shared(env); + auto observer = std::make_shared(argv[1], uvQueue); + int errCode = rdbStore_->Subscribe(option, observer); if (errCode != E_OK) { LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: subscribe failed."); return; @@ -1277,7 +1282,8 @@ void RdbStoreProxy::OffDataChangeEvent(napi_env env, size_t argc, napi_value *ar LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: rdbStore_ invalid."); return; } - rdbStore_->UnSubscribe(option, it->get()); + rdbStore_->UnSubscribe(option, *it); + (*it)->Clear(); observers_[mode].erase(it); LOG_INFO("RdbStoreProxy::OffDataChangeEvent: unsubscribe success."); return; diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_observer.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_observer.cpp index 216e2f659a478b273b0f7a1e6850c7ffb34c7c58..d672249d3e3c28b595443ed42d690721a63c7b54 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_observer.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_observer.cpp @@ -22,24 +22,47 @@ using namespace OHOS::Rdb; using namespace OHOS::AppDataMgrJsKit; namespace OHOS::RdbJsKit { -NapiRdbStoreObserver::NapiRdbStoreObserver(napi_env env, napi_value callback) : NapiUvQueue(env, callback) +NapiRdbStoreObserver::NapiRdbStoreObserver(napi_value callback, std::shared_ptr uvQueue) : uvQueue_(uvQueue) { + napi_create_reference(uvQueue_->GetEnv(), callback, 1, &callback_); } NapiRdbStoreObserver::~NapiRdbStoreObserver() noexcept { } +bool NapiRdbStoreObserver::operator==(napi_value value) +{ + return JSUtils::Equal(uvQueue_->GetEnv(), callback_, value); +} + void NapiRdbStoreObserver::OnChange(const std::vector &devices) { - LOG_INFO("NapiRdbStoreObserver::OnChange begin."); - CallFunction([devices](napi_env env, int &argc, napi_value *argv) { - argc = 1; - if (argv == nullptr) { - LOG_ERROR("NapiRdbStoreObserver::CallFunction error."); - return; + LOG_INFO("NapiRdbStoreObserver::OnChange begin"); + auto uvQueue = uvQueue_; + if (uvQueue == nullptr) { + return; + } + uvQueue->AsyncCall({ [observer = shared_from_this()](napi_env env) -> napi_value { + if (observer->callback_ == nullptr) { + return nullptr; } - argv[0] = JSUtils::Convert2JSValue(env, devices); - }); + napi_value callback = nullptr; + napi_get_reference_value(env, observer->callback_, &callback); + return callback; + } }, + [devices](napi_env env, int &argc, napi_value *argv) { + argc = 1; + argv[0] = JSUtils::Convert2JSValue(env, devices); + }); +} + +void NapiRdbStoreObserver::Clear() +{ + if (callback_ == nullptr) { + return; + } + napi_delete_reference(uvQueue_->GetEnv(), callback_); + callback_ = nullptr; } } // namespace OHOS::RdbJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_result_set.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_result_set.cpp index 1c47039cb0a6fd59c1e955e631db7b6f1a48889d..a338a56e2315c2fa4aea5700c266a8b859d393b4 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_result_set.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_result_set.cpp @@ -178,6 +178,9 @@ napi_value ResultSetProxy::InnerInitialize(napi_env env, napi_callback_info info } proxy->apiversion = version; auto finalize = [](napi_env env, void *data, void *hint) { + if (data == nullptr) { + return; + } auto tid = JSDFManager::GetInstance().GetFreedTid(data); if (tid != 0) { LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_uv_queue.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_uv_queue.cpp deleted file mode 100644 index 9badcf03749b41f742ca8492934fcd3cda74d36e..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/rdb/src/napi_uv_queue.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2022 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 "NapiUvQueue" -#include "napi_uv_queue.h" - -#include "logger.h" -#include "uv.h" - -namespace OHOS::RdbJsKit { -using namespace OHOS::Rdb; - -NapiUvQueue::NapiUvQueue(napi_env env, napi_value callback) - : env_(env) -{ - napi_create_reference(env, callback, 1, &callback_); - napi_get_uv_event_loop(env, &loop_); -} - -NapiUvQueue::~NapiUvQueue() -{ - napi_delete_reference(env_, callback_); -} - -bool NapiUvQueue::operator==(napi_value value) -{ - napi_value callback = nullptr; - napi_get_reference_value(env_, callback_, &callback); - - bool isEquals = false; - napi_strict_equals(env_, value, callback, &isEquals); - return isEquals; -} - -void NapiUvQueue::CallFunction(NapiArgsGenerator genArgs) -{ - uv_work_t *work = new (std::nothrow) uv_work_t; - if (work == nullptr) { - return; - } - work->data = this; - this->args = std::move(genArgs); - - int ret = uv_queue_work(loop_, work, [](uv_work_t* work) {}, [](uv_work_t* work, int st) { - auto queue = static_cast(work->data); - napi_handle_scope scope = nullptr; - napi_open_handle_scope(queue->env_, &scope); - if (scope == nullptr) { - delete work; - return; - } - int argc = 0; - napi_value argv[MAX_CALLBACK_ARG_NUM] = { nullptr }; - if (queue->args) { - queue->args(queue->env_, argc, argv); - } - - napi_value callback = nullptr; - napi_get_reference_value(queue->env_, queue->callback_, &callback); - napi_value global = nullptr; - napi_get_global(queue->env_, &global); - napi_value result = nullptr; - napi_status status = napi_call_function(queue->env_, global, callback, argc, argv, &result); - if (status != napi_ok) { - LOG_ERROR("napi_call_function failed, status=%{public}d", status); - } - napi_close_handle_scope(queue->env_, scope); - delete work; - }); - if (ret < 0) { - LOG_ERROR("uv_queue_work failed, errCode:%{public}d", ret); - delete static_cast(work->data); - delete work; - } -} -} // namespace OHOS::RdbJsKit diff --git a/relational_store/frameworks/js/napi/relationalstore/BUILD.gn b/relational_store/frameworks/js/napi/relationalstore/BUILD.gn index 6578c6647d4807d9fb09113ee37ef719c5439f86..65f511aa0b2ea852e5bfeb533a7125ef8e898d0e 100644 --- a/relational_store/frameworks/js/napi/relationalstore/BUILD.gn +++ b/relational_store/frameworks/js/napi/relationalstore/BUILD.gn @@ -30,8 +30,10 @@ sources = [ "src/entry_point.cpp", "src/napi_async_call.cpp", "src/napi_rdb_const_properties.cpp", + "src/napi_rdb_context.cpp", "src/napi_rdb_error.cpp", "src/napi_rdb_js_utils.cpp", + "src/napi_rdb_log_observer.cpp", "src/napi_rdb_predicates.cpp", "src/napi_rdb_sendable_utils.cpp", "src/napi_rdb_statistics_observer.cpp", @@ -39,15 +41,12 @@ sources = [ "src/napi_rdb_store_helper.cpp", "src/napi_result_set.cpp", "src/napi_transaction.cpp", - "src/napi_uv_queue.cpp", ] if (is_ohos) { ohos_shared_library("relationalstore") { include_dirs = [ "include", - "${datashare_path}/common/include/", - "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_js_common_path}/include", "${relational_store_napi_path}/relationalstore/include", @@ -73,9 +72,12 @@ if (is_ohos) { "bounds_checking_function:libsec_shared", "c_utils:utils", "common_event_service:cesfwk_innerkits", + "data_share:datashare_common_lite", "eventhandler:libeventhandler", "hilog:libhilog", "hitrace:hitrace_meter", + "ipc:ipc_single", + "kv_store:datamgr_common", "napi:ace_napi", ] @@ -87,7 +89,6 @@ if (is_ohos) { ohos_shared_library("relationalstore") { include_dirs = [ "mock/include", - "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_js_common_path}/mock/include", "${relational_store_napi_path}/relationalstore/mock/include", @@ -115,7 +116,10 @@ if (is_ohos) { "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb:native_rdb", ] - external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps = [ + "bounds_checking_function:libsec_static", + "kv_store:datamgr_common", + ] subsystem_name = "distributeddatamgr" part_name = "relational_store" @@ -125,7 +129,6 @@ if (is_ohos) { ohos_shared_library("relationalstore") { include_dirs = [ "mock/include", - "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_js_common_path}/mock/include", "${relational_store_napi_path}/relationalstore/mock/include", @@ -137,6 +140,7 @@ if (is_ohos) { cflags_cc = [ "-std=c++17", "-stdlib=libc++", + "-Dnapi_send_event=SendEventMock", ] buildos = "mac" @@ -145,7 +149,10 @@ if (is_ohos) { "CROSS_PLATFORM", ] - sources += [ "${relational_store_js_common_path}/mock/src/js_ability.cpp" ] + sources += [ + "${relational_store_js_common_path}/mock/src/mock.cpp", + "${relational_store_js_common_path}/mock/src/js_ability.cpp", + ] deps = [ "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_${buildos}", @@ -153,7 +160,10 @@ if (is_ohos) { "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb:native_rdb", ] - external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps = [ + "bounds_checking_function:libsec_static", + "kv_store:datamgr_common", + ] subsystem_name = "distributeddatamgr" part_name = "relational_store" @@ -163,7 +173,6 @@ if (is_ohos) { ohos_source_set("data_relationalstore") { include_dirs = [ "mock/include", - "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_js_common_path}/mock/include", "include", @@ -186,6 +195,7 @@ if (is_ohos) { ] sources += [ + "src/napi_rdb_store_observer.cpp", "${relational_store_js_common_path}/mock/src/js_ability.cpp", "//foundation/appframework/ability/ability_runtime/cross_platform/interfaces/inner_api/napi_base_context/src/napi_base_context.cpp", ] @@ -196,7 +206,10 @@ if (is_ohos) { "//foundation/arkui/ace_engine/adapter/android/build:libarkui_android", ] - external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps = [ + "bounds_checking_function:libsec_static", + "kv_store:datamgr_common", + ] subsystem_name = "distributeddatamgr" part_name = "relational_store" @@ -205,7 +218,6 @@ if (is_ohos) { ohos_source_set("data_relationalstore") { include_dirs = [ "mock/include", - "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_js_common_path}/mock/include", "include", @@ -220,6 +232,7 @@ if (is_ohos) { cflags_cc = [ "-std=c++17", "-stdlib=libc++", + "-Dnapi_send_event=SendEventMock", ] defines = [ @@ -227,19 +240,19 @@ if (is_ohos) { "CROSS_PLATFORM", ] - sources += [ "${relational_store_js_common_path}/mock/src/js_ability.cpp" ] + sources += [ + "${relational_store_js_common_path}/mock/src/mock.cpp", + "src/napi_rdb_store_observer.cpp", + "${relational_store_js_common_path}/mock/src/js_ability.cpp", + ] deps = [ + "${kvstore_path}/common:datamgr_common", "${relational_store_innerapi_path}/rdb:native_rdb", "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_ios", "//plugins/libs/napi:napi_ios", ] - external_deps = [ - "bounds_checking_function:libsec_static", - "c_utils:utils", - ] - subsystem_name = "distributeddatamgr" part_name = "relational_store" } diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_context.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_context.h index 5ffd65855134d41f375cc2bf892de372bbe6c6ce..437d24fe5706acb6cbfc214a42823a344eb5e545 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_context.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_context.h @@ -19,6 +19,7 @@ #include "napi_async_call.h" #include "napi_rdb_js_utils.h" #include "napi_rdb_predicates.h" +#include "rdb_store.h" #include "transaction.h" #include "values_buckets.h" @@ -27,12 +28,7 @@ namespace RelationalStoreJsKit { class ResultSetProxy; using namespace OHOS::NativeRdb; struct RdbStoreContextBase : public ContextBase { - std::shared_ptr StealRdbStore() - { - auto rdb = std::move(rdbStore); - rdbStore = nullptr; - return rdb; - } + std::shared_ptr StealRdbStore(); std::shared_ptr rdbStore = nullptr; }; @@ -72,6 +68,7 @@ struct RdbStoreContext : public RdbStoreContextBase { std::map modifyTime; bool isQuerySql = false; uint32_t expiredTime = 0; + NativeRdb::RdbStoreConfig::CryptoParam cryptoParam; RdbStoreContext() : predicatesProxy(nullptr), int64Output(0), intOutput(0), enumArg(-1), @@ -88,6 +85,58 @@ struct CreateTransactionContext : public RdbStoreContextBase { AppDataMgrJsKit::JSUtils::TransactionOptions transactionOptions; std::shared_ptr transaction; }; + +int ParseTransactionOptions( + const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context); +int ParseTableName(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseCursor(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseCryptoParam(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseColumnName(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParsePrimaryKey(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseDevice(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseTablesName(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseSyncModeArg(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseDistributedTypeArg( + const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context); + +int ParseDistributedConfigArg( + const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context); + +int ParseCloudSyncModeArg(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseCallback(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseCloudSyncCallback(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParsePredicates(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseSrcType(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseSrcName(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseColumns(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseBindArgs(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseSql(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseTxId(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseSendableValuesBucket(const napi_env env, const napi_value map, std::shared_ptr context); + +int ParseValuesBucket(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseValuesBuckets(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseConflictResolution(const napi_env env, const napi_value arg, std::shared_ptr context); } // namespace RelationalStoreJsKit } // namespace OHOS #endif // NAPI_RDB_CONTEXT_H \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h index 115c0e27e22462b9850aaf0b93c2df03dc801a2c..21936679f53dc9ab70a147fd253f0538231f5ccb 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h @@ -90,16 +90,16 @@ public: class InnerError : public Error { public: - InnerError(int code) + InnerError(int code, const std::string &msg = "") { auto errorMsg = GetJsErrorCode(code); if (errorMsg.has_value()) { auto napiError = errorMsg.value(); code_ = napiError.jsCode; - msg_ = napiError.message; + msg_ = napiError.message + msg; } else { code_ = E_INNER_ERROR; - msg_ = "Inner error. Inner code is " + std::to_string(code % E_INNER_ERROR); + msg_ = "Inner error."; } } @@ -186,7 +186,7 @@ public: PathError(){}; std::string GetMessage() override { - return "Invalid database path."; + return "Failed to open or delete the database by an invalid database path."; }; int GetCode() override { diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h index 52f7b5ab8d3883e6b8e63a74d5bd5d648dd67224..ddb902235e1128b66dc9923f92227e7fd992b24c 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h @@ -28,6 +28,7 @@ #include "value_object.h" #include "values_bucket.h" #include "values_buckets.h" +#include "rdb_sql_utils.h" namespace OHOS::AppDataMgrJsKit { namespace JSUtils { @@ -39,10 +40,12 @@ using JSChangeInfo = OHOS::RelationalStoreJsKit::NapiRdbStoreObserver::JSChangeI using PRIKey = OHOS::DistributedRdb::RdbStoreObserver::PrimaryKey; using Error = RelationalStoreJsKit::Error; using SecurityLevel = NativeRdb::SecurityLevel; +using SqlInfo = NativeRdb::SqlInfo; using Tokenizer = NativeRdb::Tokenizer; using RdbStoreConfig = NativeRdb::RdbStoreConfig; using BigInt = OHOS::NativeRdb::BigInteger; using SqlExecInfo = DistributedRdb::SqlObserver::SqlExecutionInfo; +using ExceptionMessage = DistributedRdb::SqlErrorObserver::ExceptionMessage; using ValuesBucket = OHOS::NativeRdb::ValuesBucket; using ValuesBuckets = OHOS::NativeRdb::ValuesBuckets; using HAMode = NativeRdb::HAMode; @@ -58,6 +61,7 @@ struct RdbConfig { bool allowRebuild = false; bool isReadOnly = false; bool persist = true; + bool enableSemanticIndex = false; SecurityLevel securityLevel = SecurityLevel::LAST; Tokenizer tokenizer = Tokenizer::NONE_TOKENIZER; std::string dataGroupId; @@ -137,6 +141,10 @@ template<> std::string ToString(const PRIKey &key); template<> napi_value Convert2JSValue(napi_env env, const SqlExecInfo &value); +template<> +napi_value Convert2JSValue(napi_env env, const ExceptionMessage &value); +template<> +napi_value Convert2JSValue(napi_env env, const SqlInfo &sqlinfo); bool IsNapiString(napi_env env, napi_value value); std::tuple> GetRealPath( diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_uv_queue.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_log_observer.h similarity index 50% rename from relational_store/frameworks/js/napi/relationalstore/include/napi_uv_queue.h rename to relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_log_observer.h index 5f3d618bde6027eaada895d4f81bf5b4bfe4bce5..75c688222c3190ce4b839f7e5ba8cd0b14d804cf 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_uv_queue.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_log_observer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2025 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 @@ -12,36 +12,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef RDB_JSKIT_NAPI_RDB_LOG_OBSERVER_H +#define RDB_JSKIT_NAPI_RDB_LOG_OBSERVER_H +#include -#ifndef NAPI_UV_QUEUE_H -#define NAPI_UV_QUEUE_H - -#include - +#include "js_uv_queue.h" #include "napi/native_api.h" #include "napi/native_common.h" #include "napi/native_node_api.h" +#include "rdb_types.h" -namespace OHOS::RelationalStoreJsKit { -class NapiUvQueue { - using NapiArgsGenerator = std::function; - +namespace OHOS { +namespace RelationalStoreJsKit { +class NapiLogObserver + : public DistributedRdb::SqlErrorObserver, public std::enable_shared_from_this { public: - NapiUvQueue(napi_env env, napi_value callback); - - virtual ~NapiUvQueue(); - + NapiLogObserver(napi_env env, napi_value callback, std::shared_ptr uvQueue); + virtual ~NapiLogObserver(); + void Clear(); bool operator==(napi_value value); - - void CallFunction(NapiArgsGenerator genArgs = NapiArgsGenerator()); + void OnErrorLog(const ExceptionMessage &exceptionMessage) override; private: napi_env env_ = nullptr; napi_ref callback_ = nullptr; - NapiArgsGenerator args; - uv_loop_s *loop_ = nullptr; - - static constexpr int MAX_CALLBACK_ARG_NUM = 6; + std::shared_ptr queue_ = nullptr; }; -} // namespace OHOS::RelationalStoreJsKit -#endif \ No newline at end of file + +} // namespace RelationalStoreJsKit +} // namespace OHOS +#endif //RDB_JSKIT_NAPI_RDB_LOG_OBSERVER_H diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_predicates.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_predicates.h index f9c24ecbb5b0622b5307ce4cd98948b8ddee50fa..6aefd2cd81b4d20ceea8b3a00b47e3678628d838 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_predicates.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_predicates.h @@ -105,6 +105,7 @@ private: static napi_value GetBindArgs(napi_env env, napi_callback_info info); static napi_value InDevices(napi_env env, napi_callback_info info); static napi_value InAllDevices(napi_env env, napi_callback_info info); + static napi_value Having(napi_env env, napi_callback_info info); }; } // namespace RelationalStoreJsKit } // namespace OHOS diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_statistics_observer.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_statistics_observer.h index 4b2adf7a169c664f343fb289357ef6ea3b5af271..2707545ff214df381a3109e275b404044a689070 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_statistics_observer.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_statistics_observer.h @@ -39,6 +39,20 @@ private: std::shared_ptr queue_ = nullptr; }; +class NapiPerfStatObserver + : public DistributedRdb::SqlObserver, public std::enable_shared_from_this { +public: + NapiPerfStatObserver(napi_env env, napi_value callback, std::shared_ptr uvQueue); + virtual ~NapiPerfStatObserver(); + void Clear(); + bool operator==(napi_value value); + void OnStatistic(const SqlExecutionInfo &sqlExeInfo) override; + +private: + napi_env env_ = nullptr; + napi_ref callback_ = nullptr; + std::shared_ptr queue_ = nullptr; +}; } // namespace RelationalStoreJsKit } // namespace OHOS #endif //RDB_JSKIT_NAPI_RDB_STATISTICS_OBSERVER_H diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h index 2d506fe50404733fbb2e0b1ad86030a0efd054fc..dde6181fd88537619f47a600d0e28cc82a5b9648 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h @@ -35,17 +35,17 @@ namespace RelationalStoreJsKit { using Descriptor = std::function(void)>; class NapiRdbStoreObserver; class NapiStatisticsObserver; +class NapiPerfStatObserver; +class NapiLogObserver; class RdbStoreProxy : public JSProxy::JSProxy { public: static void Init(napi_env env, napi_value exports); - static napi_value NewInstance(napi_env env, std::shared_ptr value, bool isSystemAppCalled, - const std::string &bundleName); + static napi_value NewInstance(napi_env env, std::shared_ptr value, bool isSystemAppCalled); RdbStoreProxy(); ~RdbStoreProxy(); RdbStoreProxy(std::shared_ptr rdbStore); RdbStoreProxy &operator=(std::shared_ptr rdbStore); bool IsSystemAppCalled(); - std::string GetBundleName(); private: static napi_value Initialize(napi_env env, napi_callback_info info); @@ -81,8 +81,10 @@ private: static napi_value CloudSync(napi_env env, napi_callback_info info); static napi_value GetModifyTime(napi_env env, napi_callback_info info); static napi_value CleanDirtyData(napi_env env, napi_callback_info info); + static napi_value Rekey(napi_env env, napi_callback_info info); static napi_value OnEvent(napi_env env, napi_callback_info info); static napi_value OffEvent(napi_env env, napi_callback_info info); + static napi_value SetLocale(napi_env env, napi_callback_info info); static napi_value Notify(napi_env env, napi_callback_info info); static napi_value QuerySharingResource(napi_env env, napi_callback_info info); static napi_value Close(napi_env env, napi_callback_info info); @@ -100,7 +102,7 @@ private: static void SetBusinessError(napi_env env, std::shared_ptr error, napi_value *businessError); void UnregisterAll(); - static constexpr int EVENT_HANDLE_NUM = 3; + static constexpr int EVENT_HANDLE_NUM = 5; static constexpr int WAIT_TIME_DEFAULT = 2; static constexpr int WAIT_TIME_LIMIT = 300; @@ -129,6 +131,10 @@ private: napi_value UnregisterSyncCallback(napi_env env, size_t argc, napi_value *argv); napi_value OnStatistics(napi_env env, size_t argc, napi_value *argv); napi_value OffStatistics(napi_env env, size_t argc, napi_value *argv); + napi_value OnErrorLog(napi_env env, size_t argc, napi_value *argv); + napi_value OffErrorLog(napi_env env, size_t argc, napi_value *argv); + napi_value OnPerfStat(napi_env env, size_t argc, napi_value *argv); + napi_value OffPerfStat(napi_env env, size_t argc, napi_value *argv); using EventHandle = napi_value (RdbStoreProxy::*)(napi_env, size_t, napi_value *); struct HandleInfo { @@ -138,12 +144,16 @@ private: static constexpr HandleInfo onEventHandlers_[EVENT_HANDLE_NUM] = { { "dataChange", &RdbStoreProxy::OnRemote }, { "autoSyncProgress", &RdbStoreProxy::RegisterSyncCallback }, - { "statistics", &RdbStoreProxy::OnStatistics } + { "statistics", &RdbStoreProxy::OnStatistics }, + { "perfStat", &RdbStoreProxy::OnPerfStat }, + { "sqliteErrorOccurred", &RdbStoreProxy::OnErrorLog } }; static constexpr HandleInfo offEventHandlers_[EVENT_HANDLE_NUM] = { { "dataChange", &RdbStoreProxy::OffRemote }, { "autoSyncProgress", &RdbStoreProxy::UnregisterSyncCallback }, - { "statistics", &RdbStoreProxy::OffStatistics } + { "statistics", &RdbStoreProxy::OffStatistics }, + { "perfStat", &RdbStoreProxy::OffPerfStat }, + { "sqliteErrorOccurred", &RdbStoreProxy::OffErrorLog } }; bool isSystemAppCalled_ = false; @@ -154,7 +164,8 @@ private: std::map>> localSharedObservers_; std::list> syncObservers_; std::list> statisticses_; - std::string bundleName_; + std::list> perfStats_; + std::list> logObservers_; }; } // namespace RelationalStoreJsKit } // namespace OHOS diff --git a/relational_store/frameworks/js/napi/relationalstore/mock/include/napi_rdb_store.h b/relational_store/frameworks/js/napi/relationalstore/mock/include/napi_rdb_store.h index 1122a89f64e58cc655fb31cab60e0bc0705bee75..93397c9a5fab0b28d646f21d66861e63381febd2 100644 --- a/relational_store/frameworks/js/napi/relationalstore/mock/include/napi_rdb_store.h +++ b/relational_store/frameworks/js/napi/relationalstore/mock/include/napi_rdb_store.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 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 @@ -31,17 +31,19 @@ namespace OHOS { namespace RelationalStoreJsKit { using Descriptor = std::function(void)>; +class NapiRdbStoreObserver; +class NapiStatisticsObserver; +class NapiPerfStatObserver; +class NapiLogObserver; class RdbStoreProxy : public JSProxy::JSProxy { public: static void Init(napi_env env, napi_value exports); - static napi_value NewInstance(napi_env env, std::shared_ptr value, bool isSystemAppCalled, - const std::string &bundleName); + static napi_value NewInstance(napi_env env, std::shared_ptr value, bool isSystemAppCalled); RdbStoreProxy(); ~RdbStoreProxy(); RdbStoreProxy(std::shared_ptr rdbStore); RdbStoreProxy &operator=(std::shared_ptr rdbStore); bool IsSystemAppCalled(); - std::string GetBundleName(); private: static Descriptor GetDescriptors(); @@ -54,6 +56,7 @@ private: static napi_value BatchInsertWithConflictResolution(napi_env env, napi_callback_info info); static napi_value Query(napi_env env, napi_callback_info info); static napi_value QuerySql(napi_env env, napi_callback_info info); + static napi_value QuerySync(napi_env env, napi_callback_info info); static napi_value ExecuteSql(napi_env env, napi_callback_info info); static napi_value Execute(napi_env env, napi_callback_info info); static napi_value Backup(napi_env env, napi_callback_info info); @@ -75,13 +78,47 @@ private: static napi_value Restore(napi_env env, napi_callback_info info); static napi_value Close(napi_env env, napi_callback_info info); static napi_value CreateTransaction(napi_env env, napi_callback_info info); + static napi_value Rekey(napi_env env, napi_callback_info info); + static napi_value SetLocale(napi_env env, napi_callback_info info); + static napi_value OnEvent(napi_env env, napi_callback_info info); + static napi_value OffEvent(napi_env env, napi_callback_info info); + + static constexpr int EVENT_HANDLE_NUM = 3; + napi_value RegisteredObserver(napi_env env, const DistributedRdb::SubscribeOption &option, napi_value callback); + napi_value UnRegisteredObserver(napi_env env, const DistributedRdb::SubscribeOption &option, napi_value callback); + napi_value OnStatistics(napi_env env, size_t argc, napi_value *argv); + napi_value OffStatistics(napi_env env, size_t argc, napi_value *argv); + napi_value OnErrorLog(napi_env env, size_t argc, napi_value *argv); + napi_value OffErrorLog(napi_env env, size_t argc, napi_value *argv); + napi_value OnPerfStat(napi_env env, size_t argc, napi_value *argv); + napi_value OffPerfStat(napi_env env, size_t argc, napi_value *argv); + using EventHandle = napi_value (RdbStoreProxy::*)(napi_env, size_t, napi_value *); + struct HandleInfo { + std::string_view event; + EventHandle handle; + }; + static constexpr HandleInfo onEventHandlers_[EVENT_HANDLE_NUM] = { + { "statistics", &RdbStoreProxy::OnStatistics }, + { "perfStat", &RdbStoreProxy::OnPerfStat }, + { "sqliteErrorOccurred", &RdbStoreProxy::OnErrorLog }, + }; + static constexpr HandleInfo offEventHandlers_[EVENT_HANDLE_NUM] = { + { "statistics", &RdbStoreProxy::OffStatistics }, + { "perfStat", &RdbStoreProxy::OffPerfStat }, + { "sqliteErrorOccurred", &RdbStoreProxy::OffErrorLog }, + }; void UnregisterAll(); + int32_t dbType = NativeRdb::DB_SQLITE; std::mutex mutex_; bool isSystemAppCalled_ = false; + std::map>> localObservers_; + std::map>> localSharedObservers_; std::shared_ptr queue_; - std::string bundleName_; - + std::list> statisticses_; + std::list> perfStats_; + std::list> logObservers_; + static constexpr int WAIT_TIME_DEFAULT = 2; static constexpr int WAIT_TIME_LIMIT = 300; }; diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_async_call.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_async_call.cpp index 6e333315f2b8a9b9092333f3841c007401431c7a..4c8ca8f00c0a4d52db6a77a79d7f2d67445888c5 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_async_call.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_async_call.cpp @@ -180,6 +180,10 @@ void AsyncCall::OnExecute(napi_env env, void *data) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); ContextBase *context = reinterpret_cast(data); + if (context == nullptr) { + LOG_ERROR("context is nullptr."); + return; + } if (context->executed_ != nullptr) { context->executed_->times_++; context->executed_->lastTime_ = std::chrono::duration_cast( @@ -194,6 +198,10 @@ void AsyncCall::OnExecute(napi_env env, void *data) void AsyncCall::OnComplete(napi_env env, void *data) { ContextBase *context = reinterpret_cast(data); + if (context == nullptr) { + LOG_ERROR("context is nullptr."); + return; + } if (context->execCode_ != NativeRdb::E_OK) { context->SetError(std::make_shared(context->execCode_)); } @@ -217,6 +225,10 @@ void AsyncCall::OnComplete(napi_env env, napi_status status, void *data) void AsyncCall::OnReturn(napi_env env, napi_status status, void *data) { ContextBase *context = reinterpret_cast(data); + if (context == nullptr) { + LOG_ERROR("context is nullptr."); + return; + } napi_value result[ARG_BUTT] = { 0 }; // if out function status is ok then async renturn output data, else return error. if (context->error == nullptr) { diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_context.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..328296494ec0952020a7eda2208fca90b4389099 --- /dev/null +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_context.cpp @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2025 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 "napi_rdb_context.h" + +using namespace OHOS::RelationalStoreJsKit; + +namespace OHOS { +namespace RelationalStoreJsKit { +constexpr int32_t KEY_INDEX = 0; +constexpr int32_t VALUE_INDEX = 1; +std::shared_ptr RdbStoreContextBase::StealRdbStore() +{ + auto rdb = std::move(rdbStore); + rdbStore = nullptr; + return rdb; +} +int ParseTransactionOptions( + const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context) +{ + context->transactionOptions.transactionType = Transaction::DEFERRED; + if (argc > 0 && !JSUtils::IsNull(env, argv[0])) { + auto status = JSUtils::Convert2Value(env, argv[0], context->transactionOptions); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("options", "a transactionOptions")); + } + return OK; +} +int ParseTableName(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + context->tableName = JSUtils::Convert2String(env, arg); + CHECK_RETURN_SET(!context->tableName.empty(), std::make_shared("table", "not empty string.")); + return OK; +} + +int ParseCursor(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + double cursor = 0; + auto status = JSUtils::Convert2Value(env, arg, cursor); + CHECK_RETURN_SET(status == napi_ok && cursor > 0, std::make_shared("cursor", "valid cursor.")); + context->cursor = static_cast(cursor); + return OK; +} + +int ParseCryptoParam(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + auto status = JSUtils::Convert2Value(env, arg, context->cryptoParam); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("cryptoParam", "valid cryptoParam.")); + return OK; +} + +int ParseColumnName(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + context->columnName = JSUtils::Convert2String(env, arg); + CHECK_RETURN_SET(!context->columnName.empty(), std::make_shared("columnName", "not empty string.")); + return OK; +} + +int ParsePrimaryKey(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + JSUtils::Convert2Value(env, arg, context->keys); + CHECK_RETURN_SET(!context->keys.empty(), std::make_shared("PRIKey", "number or string.")); + return OK; +} + +int ParseDevice(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + context->device = JSUtils::Convert2String(env, arg); + CHECK_RETURN_SET(!context->device.empty(), std::make_shared("device", "not empty")); + return OK; +} + +int ParseSrcType(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + std::string value = ""; + int32_t status = JSUtils::Convert2Value(env, arg, value); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("srcName", "not null")); + context->srcName = value; + return OK; +} + +int ParseTablesName(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + int32_t ret = JSUtils::Convert2Value(env, arg, context->tablesNames); + CHECK_RETURN_SET(ret == napi_ok, std::make_shared("tablesNames", "not empty string.")); + return OK; +} + +int ParseSyncModeArg(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + napi_valuetype type = napi_undefined; + napi_typeof(env, arg, &type); + CHECK_RETURN_SET(type == napi_number, std::make_shared("mode", "a SyncMode Type.")); + napi_status status = napi_get_value_int32(env, arg, &context->enumArg); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("mode", "a SyncMode Type.")); + bool checked = context->enumArg == 0 || context->enumArg == 1; + CHECK_RETURN_SET(checked, std::make_shared("mode", "a SyncMode of device.")); + return OK; +} + +int ParseDistributedTypeArg( + const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context) +{ + context->distributedType = DistributedRdb::DISTRIBUTED_DEVICE; + if (argc > 1) { + auto status = JSUtils::Convert2ValueExt(env, argv[1], context->distributedType); + bool checked = status == napi_ok && context->distributedType >= DistributedRdb::DISTRIBUTED_DEVICE && + context->distributedType <= DistributedRdb::DISTRIBUTED_CLOUD; + CHECK_RETURN_SET(JSUtils::IsNull(env, argv[1]) || checked, + std::make_shared("distributedType", "a DistributedType")); + } + return OK; +} + +int ParseDistributedConfigArg( + const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context) +{ + context->distributedConfig = { false }; + // '2' Ensure that the incoming argv contains 3 parameter + if (argc > 2) { + auto status = JSUtils::Convert2Value(env, argv[2], context->distributedConfig); + bool checked = status == napi_ok || JSUtils::IsNull(env, argv[2]); + CHECK_RETURN_SET(checked, std::make_shared("distributedConfig", "a DistributedConfig type")); + } + return OK; +} + +int ParseCloudSyncModeArg(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + auto status = JSUtils::Convert2ValueExt(env, arg, context->syncMode); + bool checked = (status == napi_ok && context->syncMode >= DistributedRdb::TIME_FIRST && + context->syncMode <= DistributedRdb::CLOUD_FIRST); + CHECK_RETURN_SET(checked, std::make_shared("mode", "a SyncMode of cloud.")); + return OK; +} + +int ParseCallback(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + napi_valuetype valueType = napi_undefined; + napi_status status = napi_typeof(env, arg, &valueType); + CHECK_RETURN_SET( + (status == napi_ok && valueType == napi_function), std::make_shared("callback", "a function.")); + NAPI_CALL_BASE(env, napi_create_reference(env, arg, 1, &context->callback_), ERR); + return OK; +} + +int ParseCloudSyncCallback(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + napi_valuetype valueType = napi_undefined; + napi_typeof(env, arg, &valueType); + CHECK_RETURN_SET(valueType == napi_function, std::make_shared("progress", "a callback type")); + NAPI_CALL_BASE(env, napi_create_reference(env, arg, 1, &context->asyncHolder), ERR); + return OK; +} + +int ParsePredicates(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + auto status = napi_unwrap(env, arg, reinterpret_cast(&context->predicatesProxy)); + CHECK_RETURN_SET(status == napi_ok && context->predicatesProxy != nullptr, + std::make_shared("predicates", "an RdbPredicates.")); + context->tableName = context->predicatesProxy->GetPredicates()->GetTableName(); + context->rdbPredicates = context->predicatesProxy->GetPredicates(); + return OK; +} + +int ParseSrcName(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + context->srcName = JSUtils::Convert2String(env, arg); + CHECK_RETURN_SET(!context->srcName.empty(), std::make_shared("srcName", "not empty")); + return OK; +} + +int ParseColumns(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + napi_valuetype type = napi_undefined; + napi_typeof(env, arg, &type); + if (type == napi_undefined || type == napi_null) { + return OK; + } + int32_t ret = JSUtils::Convert2Value(env, arg, context->columns); + CHECK_RETURN_SET(ret == napi_ok, std::make_shared("columns", "a string array")); + return OK; +} + +int ParseBindArgs(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + context->bindArgs.clear(); + napi_valuetype type = napi_undefined; + napi_typeof(env, arg, &type); + if (type == napi_undefined || type == napi_null) { + return OK; + } + bool isArray = false; + napi_status status = napi_is_array(env, arg, &isArray); + CHECK_RETURN_SET(status == napi_ok && isArray, std::make_shared("values", "a BindArgs array.")); + + uint32_t arrLen = 0; + status = napi_get_array_length(env, arg, &arrLen); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("values", "not empty.")); + for (size_t i = 0; i < arrLen; ++i) { + napi_value element = nullptr; + napi_get_element(env, arg, i, &element); + ValueObject valueObject; + int32_t ret = JSUtils::Convert2Value(env, element, valueObject.value); + CHECK_RETURN_SET(ret == OK, std::make_shared(std::to_string(i), "ValueObject")); + // The blob is an empty vector. + // If the API version is less than 14, and insert null. Otherwise, insert an empty vector. + if (valueObject.GetType() == ValueObject::TYPE_BLOB && JSUtils::GetHapVersion() < 14) { + std::vector tmpValue; + valueObject.GetBlob(tmpValue); + if (tmpValue.empty()) { + valueObject = ValueObject(); + } + } + context->bindArgs.push_back(std::move(valueObject)); + } + return OK; +} + +int ParseSql(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + context->sql = JSUtils::Convert2String(env, arg); + CHECK_RETURN_SET(!context->sql.empty(), std::make_shared("sql", "not empty")); + return OK; +} + +int ParseTxId(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + int64_t txId = 0; + auto status = JSUtils::Convert2ValueExt(env, arg, txId); + CHECK_RETURN_SET(status == napi_ok && txId >= 0, std::make_shared("txId", "not invalid txId")); + context->txId = txId; + return OK; +} + +int ParseSendableValuesBucket(const napi_env env, const napi_value map, std::shared_ptr context) +{ + uint32_t length = 0; + napi_status status = napi_map_get_size(env, map, &length); + auto error = std::make_shared("ValuesBucket is invalid."); + CHECK_RETURN_SET(status == napi_ok && length > 0, error); + napi_value entries = nullptr; + status = napi_map_get_entries(env, map, &entries); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_map_get_entries failed.")); + for (uint32_t i = 0; i < length; ++i) { + napi_value iter = nullptr; + status = napi_map_iterator_get_next(env, entries, &iter); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_map_iterator_get_next failed.")); + napi_value values = nullptr; + status = napi_get_named_property(env, iter, "value", &values); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_named_property value failed.")); + napi_value key = nullptr; + status = napi_get_element(env, values, KEY_INDEX, &key); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_element key failed.")); + std::string keyStr = JSUtils::Convert2String(env, key); + napi_value value = nullptr; + status = napi_get_element(env, values, VALUE_INDEX, &value); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_element value failed.")); + ValueObject valueObject; + int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value); + if (ret == napi_ok) { + context->valuesBucket.Put(keyStr, valueObject); + } else if (ret != napi_generic_failure) { + CHECK_RETURN_SET(false, std::make_shared("The value type of " + keyStr, "invalid.")); + } + } + return OK; +} + +int ParseValuesBucket(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + bool isMap = false; + napi_status status = napi_is_map(env, arg, &isMap); + CHECK_RETURN_SET( + status == napi_ok, std::make_shared("call napi_is_map failed" + std::to_string(status))); + if (isMap) { + return ParseSendableValuesBucket(env, arg, context); + } + napi_value keys = nullptr; + napi_get_all_property_names(env, arg, napi_key_own_only, + static_cast(napi_key_enumerable | napi_key_skip_symbols), napi_key_numbers_to_strings, &keys); + uint32_t arrLen = 0; + status = napi_get_array_length(env, keys, &arrLen); + CHECK_RETURN_SET(status == napi_ok && arrLen > 0, std::make_shared("ValuesBucket is invalid")); + + for (size_t i = 0; i < arrLen; ++i) { + napi_value key = nullptr; + status = napi_get_element(env, keys, i, &key); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("ValuesBucket is invalid.")); + std::string keyStr = JSUtils::Convert2String(env, key); + napi_value value = nullptr; + napi_get_property(env, arg, key, &value); + ValueObject valueObject; + int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value); + // The blob is an empty vector. + // If the API version is less than 14, and insert null. Otherwise, insert an empty vector. + if (ret == napi_ok && valueObject.GetType() == ValueObject::TYPE_BLOB && JSUtils::GetHapVersion() < 14) { + std::vector tmpValue; + valueObject.GetBlob(tmpValue); + if (tmpValue.empty()) { + valueObject = ValueObject(); + } + } + if (ret == napi_ok) { + context->valuesBucket.Put(keyStr, valueObject); + } else if (ret != napi_generic_failure) { + CHECK_RETURN_SET(false, std::make_shared("The value type of " + keyStr, "invalid.")); + } + } + return OK; +} + +int ParseValuesBuckets(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + bool isArray = false; + napi_status status = napi_is_array(env, arg, &isArray); + CHECK_RETURN_SET(status == napi_ok && isArray, std::make_shared("ValuesBuckets is invalid.")); + + uint32_t arrLen = 0; + status = napi_get_array_length(env, arg, &arrLen); + CHECK_RETURN_SET(status == napi_ok && arrLen > 0, std::make_shared("ValuesBuckets is invalid.")); + + for (uint32_t i = 0; i < arrLen; ++i) { + napi_value obj = nullptr; + status = napi_get_element(env, arg, i, &obj); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_element failed.")); + + CHECK_RETURN_ERR(ParseValuesBucket(env, obj, context) == OK); + context->sharedValuesBuckets.Put(context->valuesBucket); + context->valuesBucket.Clear(); + } + return OK; +} + +int ParseConflictResolution(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + int32_t conflictResolution = 0; + napi_get_value_int32(env, arg, &conflictResolution); + int32_t min = static_cast(NativeRdb::ConflictResolution::ON_CONFLICT_NONE); + int32_t max = static_cast(NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE); + bool checked = (conflictResolution >= min) && (conflictResolution <= max); + CHECK_RETURN_SET(checked, std::make_shared("conflictResolution", "a ConflictResolution.")); + context->conflictResolution = static_cast(conflictResolution); + return OK; +} +} // namespace RelationalStoreJsKit +} // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_error.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_error.cpp index d6418cd4a48e22032afa07707e238184feb86c8a..9d41b1c238c08365ab8ed3c574e93ced9f74362f 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_error.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_error.cpp @@ -21,23 +21,25 @@ namespace OHOS { namespace RelationalStoreJsKit { using JsErrorCode = OHOS::RelationalStoreJsKit::JsErrorCode; static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = { + { E_PARAM_ERROR, 401, "Invalid args."}, { E_NOT_STAGE_MODE, 14801001, "The operation is supported in the stage model only." }, { E_DATA_GROUP_ID_INVALID, 14801002, "Invalid data ground ID." }, { NativeRdb::E_NOT_SELECT, 14800019, "The SQL must be a query statement." }, - { NativeRdb::E_COLUMN_OUT_RANGE, 14800013, "Column out of bounds." }, - { NativeRdb::E_INVALID_FILE_PATH, 14800010, "Invalid database path." }, - { NativeRdb::E_ROW_OUT_RANGE, 14800012, "Row out of bounds." }, + { NativeRdb::E_COLUMN_OUT_RANGE, 14800013, "Resultset is empty or column index is out of bounds." }, + { NativeRdb::E_INVALID_FILE_PATH, 14800010, "Failed to open or delete the database by an invalid database path." }, + { NativeRdb::E_ROW_OUT_RANGE, 14800012, "ResultSet is empty or pointer index is out of bounds." }, { NativeRdb::E_NO_ROW_IN_QUERY, 14800018, "No data meets the condition." }, - { NativeRdb::E_ALREADY_CLOSED, 14800014, "Already closed." }, + { NativeRdb::E_ALREADY_CLOSED, 14800014, "The RdbStore or ResultSet is already closed." }, { NativeRdb::E_DATABASE_BUSY, 14800015, "The database does not respond." }, { NativeRdb::E_WAL_SIZE_OVER_LIMIT, 14800047, "The WAL file size over default limit." }, { NativeRdb::E_GET_DATAOBSMGRCLIENT_FAIL, 14801050, "Failed to get DataObsMgrClient." }, { NativeRdb::E_TYPE_MISMATCH, 14800051, "The type of the distributed table does not match." }, { NativeRdb::E_SQLITE_FULL, 14800029, "SQLite: The database is full." }, - { NativeRdb::E_NOT_SUPPORT_THE_SQL, 14800021, "SQLite: Generic error." }, + { NativeRdb::E_NOT_SUPPORT_THE_SQL, 14800021, "SQLite: Generic error. Executed SQL statement is not supported." }, { NativeRdb::E_ATTACHED_DATABASE_EXIST, 14800016, "The database alias already exists." }, - { NativeRdb::E_SQLITE_ERROR, 14800021, "SQLite: Generic error." }, - { NativeRdb::E_SQLITE_CORRUPT, 14800011, "Database corrupted." }, + { NativeRdb::E_SQLITE_ERROR, 14800021, + "SQLite: Generic error. Possible causes: Insert failed or the updated data does not exist." }, + { NativeRdb::E_SQLITE_CORRUPT, 14800011, "Failed to open the database because it is corrupted." }, { NativeRdb::E_SQLITE_ABORT, 14800022, "SQLite: Callback routine requested an abort." }, { NativeRdb::E_SQLITE_PERM, 14800023, "SQLite: Access permission denied." }, { NativeRdb::E_SQLITE_BUSY, 14800024, "SQLite: The database file is locked." }, @@ -50,10 +52,10 @@ static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = { { NativeRdb::E_SQLITE_CONSTRAINT, 14800032, "SQLite: Abort due to constraint violation." }, { NativeRdb::E_SQLITE_MISMATCH, 14800033, "SQLite: Data type mismatch." }, { NativeRdb::E_SQLITE_MISUSE, 14800034, "SQLite: Library used incorrectly." }, - { NativeRdb::E_CONFIG_INVALID_CHANGE, 14800017, "Config changed." }, + { NativeRdb::E_CONFIG_INVALID_CHANGE, 14800017, "StoreConfig is changed." }, { NativeRdb::E_INVALID_SECRET_KEY, 14800020, "The secret key is corrupted or lost." }, { NativeRdb::E_SQLITE_IOERR_FULL, 14800028, "SQLite: Some kind of disk I/O error occurred." }, - { NativeRdb::E_INVALID_ARGS_NEW, 401, "Invalid args." }, + { NativeRdb::E_INVALID_ARGS_NEW, 14800001, "Invalid args." }, { NativeRdb::E_NOT_SUPPORT, 801, "Capability not support." }, }; diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp index bdbf1f38073435832910954476e4dbc287bede6e..85b8062a3ed1e21f3c6bec5d933ee20d63128876 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp @@ -217,6 +217,35 @@ napi_value Convert2JSValue(napi_env env, const DistributedRdb::SqlObserver::SqlE return object; } +template<> +napi_value Convert2JSValue(napi_env env, const ExceptionMessage &value) +{ + std::vector descriptors = { + DECLARE_JS_PROPERTY(env, "code", value.code), + DECLARE_JS_PROPERTY(env, "message", value.message), + DECLARE_JS_PROPERTY(env, "sql", value.sql), + }; + + napi_value object = nullptr; + NAPI_CALL_RETURN_ERR( + napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); + return object; +} + +template<> +napi_value Convert2JSValue(napi_env env, const SqlInfo &sqlInfo) +{ + std::vector descriptors = { + DECLARE_JS_PROPERTY(env, "sql", sqlInfo.sql), + DECLARE_JS_PROPERTY(env, "args", sqlInfo.args), + }; + + napi_value object = nullptr; + NAPI_CALL_RETURN_ERR( + napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); + return object; +} + template<> napi_value Convert2JSValue(napi_env env, const DistributedRdb::Details &details) { @@ -397,6 +426,9 @@ int32_t Convert2Value(napi_env env, napi_value jsValue, RdbConfig &rdbConfig) status = GetNamedProperty(env, jsValue, "persist", rdbConfig.persist, true); ASSERT(OK == status, "get persist failed.", napi_invalid_arg); + + status = GetNamedProperty(env, jsValue, "enableSemanticIndex", rdbConfig.enableSemanticIndex, true); + ASSERT(OK == status, "get enableSemanticIndex failed.", napi_invalid_arg); return napi_ok; } @@ -544,6 +576,8 @@ RdbStoreConfig GetRdbStoreConfig(const RdbConfig &rdbConfig, const ContextParam rdbStoreConfig.SetHaMode(rdbConfig.haMode); rdbStoreConfig.SetCryptoParam(rdbConfig.cryptoParam); + + rdbStoreConfig.SetEnableSemanticIndex(rdbConfig.enableSemanticIndex); return rdbStoreConfig; } diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_log_observer.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_log_observer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c0e3e3c960a539116a0ee73a56971714b064258f --- /dev/null +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_log_observer.cpp @@ -0,0 +1,65 @@ +/* +* Copyright (c) 2025 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 "napi_rdb_log_observer.h" + +#include "napi_rdb_js_utils.h" + +namespace OHOS::RelationalStoreJsKit { +NapiLogObserver::NapiLogObserver( + napi_env env, napi_value callback, std::shared_ptr queue) + : env_(env), queue_(queue) +{ + napi_create_reference(env, callback, 1, &callback_); +} + +NapiLogObserver::~NapiLogObserver() +{ +} + +void NapiLogObserver::Clear() +{ + if (callback_ == nullptr) { + return; + } + napi_delete_reference(env_, callback_); + callback_ = nullptr; +} + +bool NapiLogObserver::operator==(napi_value value) +{ + return JSUtils::Equal(env_, callback_, value); +} + +void NapiLogObserver::OnErrorLog(const ExceptionMessage &exceptionMessage) +{ + auto queue = queue_; + if (queue == nullptr) { + return; + } + queue->AsyncCall({ [observer = shared_from_this()](napi_env env) -> napi_value { + if (observer->callback_ == nullptr) { + return nullptr; + } + napi_value callback = nullptr; + napi_get_reference_value(env, observer->callback_, &callback); + return callback; + } }, + [infos = std::move(exceptionMessage)](napi_env env, int &argc, napi_value *argv) { + argc = 1; + argv[0] = JSUtils::Convert2JSValue(env, infos); + }); +} +} // namespace OHOS::RelationalStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp index a3dd2d34fa120912676f62cb190fdca41db50e53..f20a08fd11707becba2925ec1f222376920f6d95 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp @@ -12,10 +12,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #define LOG_TAG "NapiRdbPredicates" #include "napi_rdb_predicates.h" +#include + #include "js_df_manager.h" +#include "js_native_api.h" +#include "js_native_api_types.h" #include "js_utils.h" #include "logger.h" #include "napi_rdb_error.h" @@ -68,6 +73,7 @@ void RdbPredicatesProxy::Init(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("on", On), DECLARE_NAPI_FUNCTION("clear", Clear), DECLARE_NAPI_FUNCTION("crossJoin", CrossJoin), + DECLARE_NAPI_FUNCTION("having", Having), DECLARE_NAPI_GETTER_SETTER("joinCount", GetJoinCount, SetJoinCount), DECLARE_NAPI_GETTER_SETTER("joinConditions", GetJoinConditions, SetJoinConditions), DECLARE_NAPI_GETTER_SETTER("joinNames", GetJoinTableNames, SetJoinTableNames), @@ -164,7 +170,9 @@ void RdbPredicatesProxy::Destructor(napi_env env, void *nativeObject, void *) LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(nativeObject) & LOWER_24_BITS_MASK); } RdbPredicatesProxy *proxy = static_cast(nativeObject); - + if (proxy == nullptr) { + return; + } proxy->SetInstance(nullptr); delete proxy; } @@ -858,5 +866,35 @@ napi_value RdbPredicatesProxy::InAllDevices(napi_env env, napi_callback_info inf predicatesProxy->GetInstance()->InAllDevices(); return thiz; } + +napi_value RdbPredicatesProxy::Having(napi_env env, napi_callback_info info) +{ + napi_value thiz = nullptr; + // There may be 2 parameters. + size_t argc = 2; + napi_value args[2] = { 0 }; + napi_status status = napi_get_cb_info(env, info, &argc, args, &thiz, nullptr); + RDB_NAPI_ASSERT(env, status == napi_ok && thiz != nullptr, std::make_shared("predicates", "null")); + // Ensure that argc contains 1 or 2 parameters + RDB_NAPI_ASSERT(env, argc >= 1 && argc <= 2, std::make_shared("1 or 2")); + RdbPredicatesProxy *proxy = nullptr; + status = napi_unwrap(env, thiz, reinterpret_cast(&proxy)); + RDB_NAPI_ASSERT( + env, status == napi_ok && proxy && proxy->GetInstance(), std::make_shared("predicates", "null")); + std::string conditions; + int32_t res = JSUtils::Convert2Value(env, args[0], conditions); + RDB_NAPI_ASSERT(env, res == OK && !conditions.empty(), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "conditions cannot be empty")); + std::vector values; + // 2 represents the number of parameters. + if (argc == 2 && !JSUtils::IsNull(env, args[1])) { + int32_t ret = JSUtils::Convert2Value(env, args[1], values); + RDB_NAPI_ASSERT(env, ret == napi_ok, std::make_shared("ags", "a ValueType array.")); + } + RDB_NAPI_ASSERT(env, !proxy->GetInstance()->GetGroup().empty(), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Missing GROUP BY clause.")); + proxy->GetInstance()->Having(conditions, values); + return thiz; +} } // namespace RelationalStoreJsKit -} // namespace OHOS +} // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_statistics_observer.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_statistics_observer.cpp index e7ff21669f0e50022f79682aad2feda2c2c9bcf2..8acd9dfa6a494c7e4cc87063f31192c293b4cf3f 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_statistics_observer.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_statistics_observer.cpp @@ -62,4 +62,49 @@ void NapiStatisticsObserver::OnStatistic(const SqlExecutionInfo &sqlExeInfo) argv[0] = JSUtils::Convert2JSValue(env, infos); }); } + +NapiPerfStatObserver::NapiPerfStatObserver( + napi_env env, napi_value callback, std::shared_ptr queue) + : env_(env), queue_(queue) +{ + napi_create_reference(env, callback, 1, &callback_); +} + +NapiPerfStatObserver::~NapiPerfStatObserver() +{ +} + +void NapiPerfStatObserver::Clear() +{ + if (callback_ == nullptr) { + return; + } + napi_delete_reference(env_, callback_); + callback_ = nullptr; +} + +bool NapiPerfStatObserver::operator==(napi_value value) +{ + return JSUtils::Equal(env_, callback_, value); +} + +void NapiPerfStatObserver::OnStatistic(const SqlExecutionInfo &sqlExeInfo) +{ + auto queue = queue_; + if (queue == nullptr) { + return; + } + queue->AsyncCall({ [observer = shared_from_this()](napi_env env) -> napi_value { + if (observer->callback_ == nullptr) { + return nullptr; + } + napi_value callback = nullptr; + napi_get_reference_value(env, observer->callback_, &callback); + return callback; + } }, + [infos = std::move(sqlExeInfo)](napi_env env, int &argc, napi_value *argv) { + argc = 1; + argv[0] = JSUtils::Convert2JSValue(env, infos); + }); +} } // namespace OHOS::RelationalStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp index 167b9bad5d22856ebf4344b8e4fd1ad9a3406e98..2ade18f5bbb8350e4620d93933d474e1cb9bad48 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 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 @@ -30,15 +30,18 @@ #include "napi_rdb_context.h" #include "napi_rdb_error.h" #include "napi_rdb_js_utils.h" +#include "napi_rdb_log_observer.h" #include "napi_rdb_statistics_observer.h" #include "napi_rdb_store_observer.h" #include "napi_rdb_trace.h" #include "napi_result_set.h" #include "napi_transaction.h" #include "rdb_errno.h" +#include "rdb_sql_log.h" #include "rdb_sql_statistic.h" -#include "rdb_fault_hiview_reporter.h" +#include "rdb_perfStat.h" #include "securec.h" +#include "rdb_types.h" #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) #include "rdb_utils.h" @@ -48,6 +51,7 @@ using namespace OHOS::DataShare; using namespace OHOS::Rdb; using namespace OHOS::AppDataMgrJsKit; using namespace OHOS::AppDataMgrJsKit::JSUtils; +using namespace OHOS::DistributedRdb; #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) using OHOS::DistributedRdb::SubscribeMode; @@ -66,9 +70,6 @@ struct PredicatesProxy { std::shared_ptr predicates_; }; #endif -using Reportor = RdbFaultHiViewReporter; -constexpr int32_t KEY_INDEX = 0; -constexpr int32_t VALUE_INDEX = 1; RdbStoreProxy::RdbStoreProxy() {} @@ -89,7 +90,7 @@ void RdbStoreProxy::UnregisterAll() if (obs == nullptr) { continue; } - rdbStore->UnSubscribe({ static_cast(mode) }, obs.get()); + rdbStore->UnSubscribe({ static_cast(mode) }, obs); } } rdbStore->UnsubscribeObserver({ SubscribeMode::LOCAL_DETAIL }, nullptr); @@ -105,6 +106,9 @@ void RdbStoreProxy::UnregisterAll() for (const auto &obs : statisticses_) { DistributedRdb::SqlStatistic::Unsubscribe(obs); } + for (const auto &obs : logObservers_) { + NativeRdb::SqlLog::Unsubscribe(GetInstance()->GetPath(), obs); + } #endif } @@ -130,11 +134,6 @@ bool RdbStoreProxy::IsSystemAppCalled() return isSystemAppCalled_; } -std::string RdbStoreProxy::GetBundleName() -{ - return bundleName_; -} - bool IsNapiTypeString(napi_env env, size_t argc, napi_value *argv, size_t arg) { if (arg >= argc) { @@ -174,6 +173,10 @@ Descriptor RdbStoreProxy::GetDescriptors() DECLARE_NAPI_FUNCTION("attach", Attach), DECLARE_NAPI_FUNCTION("detach", Detach), DECLARE_NAPI_FUNCTION("createTransaction", CreateTransaction), + DECLARE_NAPI_FUNCTION("setLocale", SetLocale), + DECLARE_NAPI_FUNCTION("rekey", Rekey), + DECLARE_NAPI_FUNCTION("on", OnEvent), + DECLARE_NAPI_FUNCTION("off", OffEvent), }; #if !defined(CROSS_PLATFORM) AddDistributedFunctions(properties); @@ -207,13 +210,17 @@ napi_value RdbStoreProxy::Initialize(napi_env env, napi_callback_info info) napi_value self = nullptr; NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &self, nullptr)); auto finalize = [](napi_env env, void *data, void *hint) { + if (data == nullptr) { + LOG_ERROR("data is nullptr."); + return; + } auto tid = JSDFManager::GetInstance().GetFreedTid(data); if (tid != 0) { LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); } if (data != hint) { - LOG_ERROR("RdbStoreProxy memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, uintptr_t(data), - uintptr_t(hint)); + LOG_ERROR("RdbStoreProxy memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, + uintptr_t(data) & LOWER_24_BITS_MASK, uintptr_t(hint) & LOWER_24_BITS_MASK); return; } RdbStoreProxy *proxy = reinterpret_cast(data); @@ -235,8 +242,7 @@ napi_value RdbStoreProxy::Initialize(napi_env env, napi_callback_info info) return self; } -napi_value RdbStoreProxy::NewInstance( - napi_env env, std::shared_ptr value, bool isSystemAppCalled, const std::string &bundleName) +napi_value RdbStoreProxy::NewInstance(napi_env env, std::shared_ptr value, bool isSystemAppCalled) { if (value == nullptr) { LOG_ERROR("Value is nullptr ? %{public}d", (value == nullptr)); @@ -265,7 +271,6 @@ napi_value RdbStoreProxy::NewInstance( proxy->dbType = value->GetDbType(); proxy->SetInstance(std::move(value)); proxy->isSystemAppCalled_ = isSystemAppCalled; - proxy->bundleName_ = bundleName; return instance; } @@ -290,329 +295,6 @@ int ParserThis(const napi_env &env, const napi_value &self, std::shared_ptr context) -{ - context->tableName = JSUtils::Convert2String(env, arg); - CHECK_RETURN_SET(!context->tableName.empty(), std::make_shared("table", "not empty string.")); - return OK; -} - -int ParseCursor(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - double cursor = 0; - auto status = JSUtils::Convert2Value(env, arg, cursor); - CHECK_RETURN_SET(status == napi_ok && cursor > 0, std::make_shared("cursor", "valid cursor.")); - context->cursor = static_cast(cursor); - return OK; -} - -int ParseColumnName(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - context->columnName = JSUtils::Convert2String(env, arg); - CHECK_RETURN_SET(!context->columnName.empty(), std::make_shared("columnName", "not empty string.")); - return OK; -} - -int ParsePrimaryKey(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - JSUtils::Convert2Value(env, arg, context->keys); - CHECK_RETURN_SET(!context->keys.empty(), std::make_shared("PRIKey", "number or string.")); - return OK; -} - -int ParseDevice(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - context->device = JSUtils::Convert2String(env, arg); - CHECK_RETURN_SET(!context->device.empty(), std::make_shared("device", "not empty")); - return OK; -} - -int ParseTablesName(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - int32_t ret = JSUtils::Convert2Value(env, arg, context->tablesNames); - CHECK_RETURN_SET(ret == napi_ok, std::make_shared("tablesNames", "not empty string.")); - return OK; -} - -int ParseSyncModeArg(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - napi_valuetype type = napi_undefined; - napi_typeof(env, arg, &type); - CHECK_RETURN_SET(type == napi_number, std::make_shared("mode", "a SyncMode Type.")); - napi_status status = napi_get_value_int32(env, arg, &context->enumArg); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("mode", "a SyncMode Type.")); - bool checked = context->enumArg == 0 || context->enumArg == 1; - CHECK_RETURN_SET(checked, std::make_shared("mode", "a SyncMode of device.")); - return OK; -} - -int ParseDistributedTypeArg( - const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context) -{ - context->distributedType = DistributedRdb::DISTRIBUTED_DEVICE; - if (argc > 1) { - auto status = JSUtils::Convert2ValueExt(env, argv[1], context->distributedType); - bool checked = status == napi_ok && context->distributedType >= DistributedRdb::DISTRIBUTED_DEVICE && - context->distributedType <= DistributedRdb::DISTRIBUTED_CLOUD; - CHECK_RETURN_SET(JSUtils::IsNull(env, argv[1]) || checked, - std::make_shared("distributedType", "a DistributedType")); - } - return OK; -} - -int ParseDistributedConfigArg( - const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context) -{ - context->distributedConfig = { false }; - // '2' Ensure that the incoming argv contains 3 parameter - if (argc > 2) { - auto status = JSUtils::Convert2Value(env, argv[2], context->distributedConfig); - bool checked = status == napi_ok || JSUtils::IsNull(env, argv[2]); - CHECK_RETURN_SET(checked, std::make_shared("distributedConfig", "a DistributedConfig type")); - } - return OK; -} - -int ParseCloudSyncModeArg(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - auto status = JSUtils::Convert2ValueExt(env, arg, context->syncMode); - bool checked = (status == napi_ok && context->syncMode >= DistributedRdb::TIME_FIRST && - context->syncMode <= DistributedRdb::CLOUD_FIRST); - CHECK_RETURN_SET(checked, std::make_shared("mode", "a SyncMode of cloud.")); - return OK; -} - -int ParseCallback(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - napi_valuetype valueType = napi_undefined; - napi_status status = napi_typeof(env, arg, &valueType); - CHECK_RETURN_SET( - (status == napi_ok && valueType == napi_function), std::make_shared("callback", "a function.")); - NAPI_CALL_BASE(env, napi_create_reference(env, arg, 1, &context->callback_), ERR); - return OK; -} - -int ParseCloudSyncCallback(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - napi_valuetype valueType = napi_undefined; - napi_typeof(env, arg, &valueType); - CHECK_RETURN_SET(valueType == napi_function, std::make_shared("progress", "a callback type")); - NAPI_CALL_BASE(env, napi_create_reference(env, arg, 1, &context->asyncHolder), ERR); - return OK; -} - -int ParsePredicates(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - auto status = napi_unwrap(env, arg, reinterpret_cast(&context->predicatesProxy)); - CHECK_RETURN_SET(status == napi_ok && context->predicatesProxy != nullptr, - std::make_shared("predicates", "an RdbPredicates.")); - context->tableName = context->predicatesProxy->GetPredicates()->GetTableName(); - context->rdbPredicates = context->predicatesProxy->GetPredicates(); - return OK; -} - -int ParseDataSharePredicates(const napi_env env, const napi_value arg, std::shared_ptr context) -{ -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) - RdbStoreProxy *obj = reinterpret_cast(context->boundObj); - CHECK_RETURN_SET(obj->IsSystemAppCalled(), std::make_shared()); - PredicatesProxy *proxy = nullptr; - napi_status status = napi_unwrap(env, arg, reinterpret_cast(&proxy)); - bool checked = (status == napi_ok) && (proxy != nullptr) && (proxy->predicates_ != nullptr); - CHECK_RETURN_SET(checked, std::make_shared("predicates", "an DataShare Predicates.")); - - std::shared_ptr dsPredicates = proxy->predicates_; - RdbPredicates rdbPredicates = RdbDataShareAdapter::RdbUtils::ToPredicates(*dsPredicates, context->tableName); - context->rdbPredicates = std::make_shared(rdbPredicates); -#endif - return OK; -} - -int ParseSrcName(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - context->srcName = JSUtils::Convert2String(env, arg); - CHECK_RETURN_SET(!context->srcName.empty(), std::make_shared("srcName", "not empty")); - return OK; -} - -int ParseColumns(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - napi_valuetype type = napi_undefined; - napi_typeof(env, arg, &type); - if (type == napi_undefined || type == napi_null) { - return OK; - } - int32_t ret = JSUtils::Convert2Value(env, arg, context->columns); - CHECK_RETURN_SET(ret == napi_ok, std::make_shared("columns", "a string array")); - return OK; -} - -int ParseBindArgs(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - context->bindArgs.clear(); - napi_valuetype type = napi_undefined; - napi_typeof(env, arg, &type); - if (type == napi_undefined || type == napi_null) { - return OK; - } - bool isArray = false; - napi_status status = napi_is_array(env, arg, &isArray); - CHECK_RETURN_SET(status == napi_ok && isArray, std::make_shared("values", "a BindArgs array.")); - - uint32_t arrLen = 0; - status = napi_get_array_length(env, arg, &arrLen); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("values", "not empty.")); - for (size_t i = 0; i < arrLen; ++i) { - napi_value element = nullptr; - napi_get_element(env, arg, i, &element); - ValueObject valueObject; - int32_t ret = JSUtils::Convert2Value(env, element, valueObject.value); - CHECK_RETURN_SET(ret == OK, std::make_shared(std::to_string(i), "ValueObject")); - // The blob is an empty vector. - // If the API version is less than 14, and insert null. Otherwise, insert an empty vector. - if (valueObject.GetType() == ValueObject::TYPE_BLOB && JSUtils::GetHapVersion() < 14) { - std::vector tmpValue; - valueObject.GetBlob(tmpValue); - if (tmpValue.empty()) { - valueObject = ValueObject(); - } - } - context->bindArgs.push_back(std::move(valueObject)); - } - return OK; -} - -int ParseSql(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - context->sql = JSUtils::Convert2String(env, arg); - CHECK_RETURN_SET(!context->sql.empty(), std::make_shared("sql", "not empty")); - return OK; -} - -int ParseTxId(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - int64_t txId = 0; - auto status = JSUtils::Convert2ValueExt(env, arg, txId); - CHECK_RETURN_SET(status == napi_ok && txId >= 0, std::make_shared("txId", "not invalid txId")); - context->txId = txId; - return OK; -} - -int ParseSendableValuesBucket(const napi_env env, const napi_value map, std::shared_ptr context) -{ - uint32_t length = 0; - napi_status status = napi_map_get_size(env, map, &length); - auto error = std::make_shared("ValuesBucket is invalid."); - CHECK_RETURN_SET(status == napi_ok && length > 0, error); - napi_value entries = nullptr; - status = napi_map_get_entries(env, map, &entries); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_map_get_entries failed.")); - for (uint32_t i = 0; i < length; ++i) { - napi_value iter = nullptr; - status = napi_map_iterator_get_next(env, entries, &iter); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_map_iterator_get_next failed.")); - napi_value values = nullptr; - status = napi_get_named_property(env, iter, "value", &values); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_named_property value failed.")); - napi_value key = nullptr; - status = napi_get_element(env, values, KEY_INDEX, &key); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_element key failed.")); - std::string keyStr = JSUtils::Convert2String(env, key); - napi_value value = nullptr; - status = napi_get_element(env, values, VALUE_INDEX, &value); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_element value failed.")); - ValueObject valueObject; - int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value); - if (ret == napi_ok) { - context->valuesBucket.Put(keyStr, valueObject); - } else if (ret != napi_generic_failure) { - CHECK_RETURN_SET(false, std::make_shared("The value type of " + keyStr, "invalid.")); - } - } - return OK; -} - -int ParseValuesBucket(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - bool isMap = false; - napi_status status = napi_is_map(env, arg, &isMap); - CHECK_RETURN_SET( - status == napi_ok, std::make_shared("call napi_is_map failed" + std::to_string(status))); - if (isMap) { - return ParseSendableValuesBucket(env, arg, context); - } - napi_value keys = nullptr; - napi_get_all_property_names(env, arg, napi_key_own_only, - static_cast(napi_key_enumerable | napi_key_skip_symbols), napi_key_numbers_to_strings, &keys); - uint32_t arrLen = 0; - status = napi_get_array_length(env, keys, &arrLen); - CHECK_RETURN_SET(status == napi_ok && arrLen > 0, std::make_shared("ValuesBucket is invalid")); - - for (size_t i = 0; i < arrLen; ++i) { - napi_value key = nullptr; - status = napi_get_element(env, keys, i, &key); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("ValuesBucket is invalid.")); - std::string keyStr = JSUtils::Convert2String(env, key); - napi_value value = nullptr; - napi_get_property(env, arg, key, &value); - ValueObject valueObject; - int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value); - // The blob is an empty vector. - // If the API version is less than 14, and insert null. Otherwise, insert an empty vector. - if (ret == napi_ok && valueObject.GetType() == ValueObject::TYPE_BLOB && JSUtils::GetHapVersion() < 14) { - std::vector tmpValue; - valueObject.GetBlob(tmpValue); - if (tmpValue.empty()) { - valueObject = ValueObject(); - } - auto proxy = reinterpret_cast(context->boundObj); - if (tmpValue.empty() && (proxy != nullptr)) { - Reportor::ReportFault(RdbEmptyBlobEvent(proxy->GetBundleName())); - } - } - if (ret == napi_ok) { - context->valuesBucket.Put(keyStr, valueObject); - } else if (ret != napi_generic_failure) { - CHECK_RETURN_SET(false, std::make_shared("The value type of " + keyStr, "invalid.")); - } - } - return OK; -} - -int ParseValuesBuckets(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - bool isArray = false; - napi_is_array(env, arg, &isArray); - CHECK_RETURN_SET(isArray, std::make_shared("ValuesBuckets is invalid.")); - - uint32_t arrLen = 0; - napi_status status = napi_get_array_length(env, arg, &arrLen); - CHECK_RETURN_SET(status == napi_ok && arrLen > 0, std::make_shared("ValuesBuckets is invalid.")); - - for (uint32_t i = 0; i < arrLen; ++i) { - napi_value obj = nullptr; - status = napi_get_element(env, arg, i, &obj); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_element failed.")); - - CHECK_RETURN_ERR(ParseValuesBucket(env, obj, context) == OK); - context->sharedValuesBuckets.Put(context->valuesBucket); - context->valuesBucket.Clear(); - } - return OK; -} - -int ParseConflictResolution(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - int32_t conflictResolution = 0; - napi_get_value_int32(env, arg, &conflictResolution); - int32_t min = static_cast(NativeRdb::ConflictResolution::ON_CONFLICT_NONE); - int32_t max = static_cast(NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE); - bool checked = (conflictResolution >= min) && (conflictResolution <= max); - CHECK_RETURN_SET(checked, std::make_shared("conflictResolution", "a ConflictResolution.")); - context->conflictResolution = static_cast(conflictResolution); - return OK; -} - napi_value RdbStoreProxy::Insert(napi_env env, napi_callback_info info) { auto context = std::make_shared(); @@ -643,17 +325,6 @@ napi_value RdbStoreProxy::Insert(napi_env env, napi_callback_info info) return ASYNC_CALL(env, context); } -int ParseTransactionOptions( - const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context) -{ - context->transactionOptions.transactionType = Transaction::DEFERRED; - if (argc > 0 && !JSUtils::IsNull(env, argv[0])) { - auto status = JSUtils::Convert2Value(env, argv[0], context->transactionOptions); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("options", "a transactionOptions")); - } - return OK; -} - napi_value RdbStoreProxy::BatchInsert(napi_env env, napi_callback_info info) { auto context = std::make_shared(); @@ -701,8 +372,8 @@ napi_value RdbStoreProxy::BatchInsertWithConflictResolution(napi_env env, napi_c auto exec = [context]() -> int { CHECK_RETURN_ERR(context->rdbStore != nullptr); auto rdbStore = std::move(context->rdbStore); - auto [ret, output] = rdbStore->BatchInsertWithConflictResolution( - context->tableName, context->sharedValuesBuckets, context->conflictResolution); + auto [ret, output] = + rdbStore->BatchInsert(context->tableName, context->sharedValuesBuckets, context->conflictResolution); context->int64Output = output; return ret; }; @@ -715,6 +386,23 @@ napi_value RdbStoreProxy::BatchInsertWithConflictResolution(napi_env env, napi_c return ASYNC_CALL(env, context); } +int ParseDataSharePredicates(const napi_env env, const napi_value arg, std::shared_ptr context) +{ +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) + RdbStoreProxy *obj = reinterpret_cast(context->boundObj); + CHECK_RETURN_SET(obj->IsSystemAppCalled(), std::make_shared()); + PredicatesProxy *proxy = nullptr; + napi_status status = napi_unwrap(env, arg, reinterpret_cast(&proxy)); + bool checked = (status == napi_ok) && (proxy != nullptr) && (proxy->predicates_ != nullptr); + CHECK_RETURN_SET(checked, std::make_shared("predicates", "an DataShare Predicates.")); + + std::shared_ptr dsPredicates = proxy->predicates_; + RdbPredicates rdbPredicates = RdbDataShareAdapter::RdbUtils::ToPredicates(*dsPredicates, context->tableName); + context->rdbPredicates = std::make_shared(rdbPredicates); +#endif + return OK; +} + napi_value RdbStoreProxy::Delete(napi_env env, napi_callback_info info) { auto context = std::make_shared(); @@ -810,8 +498,7 @@ napi_value RdbStoreProxy::Query(napi_env env, napi_callback_info info) context->resultSet = context->rdbStore->Query(*(context->rdbPredicates), context->columns); #endif context->rdbStore = nullptr; - // If the API version is greater than or equal to 20, throw E_ALREADY_CLOSED. - return (context->resultSet != nullptr) ? E_OK : (JSUtils::GetHapVersion() >= 20) ? E_ALREADY_CLOSED : E_ERROR; + return (context->resultSet != nullptr) ? E_OK : E_ERROR; }; auto output = [context](napi_env env, napi_value &result) { result = ResultSetProxy::NewInstance(env, std::move(context->resultSet)); @@ -881,8 +568,7 @@ napi_value RdbStoreProxy::QuerySql(napi_env env, napi_callback_info info) context->resultSet = context->rdbStore->QuerySql(context->sql, context->bindArgs); #endif context->rdbStore = nullptr; - // If the API version is greater than or equal to 20, throw E_ALREADY_CLOSED. - return (context->resultSet != nullptr) ? E_OK : (JSUtils::GetHapVersion() >= 20) ? E_ALREADY_CLOSED : E_ERROR; + return (context->resultSet != nullptr) ? E_OK : E_ERROR; }; auto output = [context](napi_env env, napi_value &result) { result = ResultSetProxy::NewInstance(env, std::move(context->resultSet)); @@ -1272,8 +958,7 @@ napi_value RdbStoreProxy::QueryByStep(napi_env env, napi_callback_info info) auto rdbStore = std::move(context->rdbStore); context->resultSet = context->isQuerySql ? rdbStore->QueryByStep(context->sql, context->bindArgs) : rdbStore->QueryByStep(*(context->rdbPredicates), context->columns); - // If the API version is greater than or equal to 20, throw E_ALREADY_CLOSED. - return (context->resultSet != nullptr) ? E_OK : (JSUtils::GetHapVersion() >= 20) ? E_ALREADY_CLOSED : E_ERROR; + return (context->resultSet != nullptr) ? E_OK : E_ERROR; }; auto output = [context](napi_env env, napi_value &result) { result = ResultSetProxy::NewInstance(env, std::move(context->resultSet)); @@ -1358,43 +1043,25 @@ napi_value RdbStoreProxy::Restore(napi_env env, napi_callback_info info) return ASYNC_CALL(env, context); } -#if !defined(CROSS_PLATFORM) -void RdbStoreProxy::AddDistributedFunctions(std::vector &properties) -{ - properties.push_back(DECLARE_NAPI_FUNCTION("remoteQuery", RemoteQuery)); - properties.push_back(DECLARE_NAPI_FUNCTION("setDistributedTables", SetDistributedTables)); - properties.push_back(DECLARE_NAPI_FUNCTION("obtainDistributedTableName", ObtainDistributedTableName)); - properties.push_back(DECLARE_NAPI_FUNCTION("sync", Sync)); - properties.push_back(DECLARE_NAPI_FUNCTION("cloudSync", CloudSync)); - properties.push_back(DECLARE_NAPI_FUNCTION("getModifyTime", GetModifyTime)); - properties.push_back(DECLARE_NAPI_FUNCTION("cleanDirtyData", CleanDirtyData)); - properties.push_back(DECLARE_NAPI_FUNCTION("on", OnEvent)); - properties.push_back(DECLARE_NAPI_FUNCTION("off", OffEvent)); - properties.push_back(DECLARE_NAPI_FUNCTION("emit", Notify)); - properties.push_back(DECLARE_NAPI_FUNCTION("querySharingResource", QuerySharingResource)); - properties.push_back(DECLARE_NAPI_FUNCTION("lockRow", LockRow)); - properties.push_back(DECLARE_NAPI_FUNCTION("unlockRow", UnlockRow)); - properties.push_back(DECLARE_NAPI_FUNCTION("queryLockedRow", QueryLockedRow)); - properties.push_back(DECLARE_NAPI_FUNCTION("lockCloudContainer", LockCloudContainer)); - properties.push_back(DECLARE_NAPI_FUNCTION("unlockCloudContainer", UnlockCloudContainer)); -} - -napi_value RdbStoreProxy::SetDistributedTables(napi_env env, napi_callback_info info) +napi_value RdbStoreProxy::Rekey(napi_env env, napi_callback_info info) { + LOG_INFO("RdbStoreProxy::Rekey start."); auto context = std::make_shared(); auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(1 <= argc && argc <= 3, std::make_shared("1 - 4")); + CHECK_RETURN_SET_E(argc >= 0 && argc <= 1, std::make_shared("0 - 1")); CHECK_RETURN(OK == ParserThis(env, self, context)); - CHECK_RETURN(OK == ParseTablesName(env, argv[0], context)); - CHECK_RETURN(OK == ParseDistributedTypeArg(env, argc, argv, context)); - CHECK_RETURN(OK == ParseDistributedConfigArg(env, argc, argv, context)); + if (argc == 1 && !JSUtils::IsNull(env, argv[0])) { + CHECK_RETURN(OK == ParseCryptoParam(env, argv[0], context)); + } + CHECK_RETURN_SET_E(context->cryptoParam.IsValid(), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Illegal CryptoParam.")); }; auto exec = [context]() -> int { CHECK_RETURN_ERR(context->rdbStore != nullptr); auto rdbStore = std::move(context->rdbStore); - return rdbStore->SetDistributedTables( - context->tablesNames, context->distributedType, context->distributedConfig); + return rdbStore->Rekey(context->cryptoParam); }; + auto output = [context](napi_env env, napi_value &result) { napi_status status = napi_get_undefined(env, &result); CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); @@ -1405,29 +1072,26 @@ napi_value RdbStoreProxy::SetDistributedTables(napi_env env, napi_callback_info return ASYNC_CALL(env, context); } -napi_value RdbStoreProxy::ObtainDistributedTableName(napi_env env, napi_callback_info info) +napi_value RdbStoreProxy::SetLocale(napi_env env, napi_callback_info info) { auto context = std::make_shared(); auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(argc == 2, std::make_shared("2 or 3")); + CHECK_RETURN_SET_E(argc == 1, std::make_shared("1")); CHECK_RETURN(OK == ParserThis(env, self, context)); - CHECK_RETURN(OK == ParseDevice(env, argv[0], context)); - CHECK_RETURN(OK == ParseTableName(env, argv[1], context)); + CHECK_RETURN(OK == ParseSrcType(env, argv[0], context)); + CHECK_RETURN_SET_E(!context->srcName.empty(), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "locale cannot be empty")); }; auto exec = [context]() -> int { - LOG_DEBUG("RdbStoreProxy::ObtainDistributedTableName Async."); CHECK_RETURN_ERR(context->rdbStore != nullptr); - int errCode = E_ERROR; - context->tableName = - context->rdbStore->ObtainDistributedTableName(context->device, context->tableName, errCode); - context->rdbStore = nullptr; + auto rdbStore = std::move(context->rdbStore); + auto errCode = rdbStore->ConfigLocale(context->srcName); return errCode; }; + auto output = [context](napi_env env, napi_value &result) { - std::string table = context->tableName; - napi_status status = napi_create_string_utf8(env, table.c_str(), table.length(), &result); + napi_status status = napi_get_undefined(env, &result); CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); - LOG_DEBUG("RdbStoreProxy::ObtainDistributedTableName end."); }; context->SetAction(env, info, input, exec, output); @@ -1435,58 +1099,420 @@ napi_value RdbStoreProxy::ObtainDistributedTableName(napi_env env, napi_callback return ASYNC_CALL(env, context); } -napi_value RdbStoreProxy::Sync(napi_env env, napi_callback_info info) +napi_value RdbStoreProxy::OnEvent(napi_env env, napi_callback_info info) { - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(argc == 2, std::make_shared("2 or 3")); - CHECK_RETURN(OK == ParserThis(env, self, context)); - CHECK_RETURN(OK == ParseSyncModeArg(env, argv[0], context)); - CHECK_RETURN(OK == ParsePredicates(env, argv[1], context)); - }; - context->SetAction(env, info, std::move(input), nullptr, nullptr); - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - RdbStoreProxy *obj = reinterpret_cast(context->boundObj); - auto queue = obj->queue_; - napi_value promise = nullptr; - auto defer = context->defer_; - auto callback = context->callback_; - context->callback_ = nullptr; - if (callback == nullptr) { - napi_status status = napi_create_promise(env, &defer, &promise); - RDB_NAPI_ASSERT_BASE(env, status == napi_ok, - std::make_shared("failed(" + std::to_string(status) + ") to create promise"), nullptr); - } else { - napi_get_undefined(env, &promise); - } - auto predicates = *context->predicatesProxy->GetPredicates(); - auto exec = [queue, defer, callback, predicates, rdbStore = std::move(context->rdbStore), - enumArg = context->enumArg]() mutable { - SyncOption option{ static_cast(enumArg), false }; - auto ret = rdbStore->Sync(option, predicates, [queue, defer, callback](const SyncResult &result) { - auto args = [result](napi_env env, int &argc, napi_value *argv) { - argv[1] = JSUtils::Convert2JSValue(env, result); - }; - callback ? queue->AsyncCall({ callback }, args) : queue->AsyncPromise({ defer }, args); - }); - if (ret != NativeRdb::E_OK) { - auto args = [ret](napi_env env, int &argc, napi_value *argv) mutable { - SetBusinessError(env, std::make_shared(ret), &argv[0]); - }; - callback ? queue->AsyncCall({ callback }, args) : queue->AsyncPromise({ defer }, args); - } - }; - queue->Execute(std::move(exec)); - context = nullptr; - return promise; -} + size_t argc = 3; + napi_value argv[3]{}; + napi_value self = nullptr; + int32_t status = napi_get_cb_info(env, info, &argc, argv, &self, nullptr); + // 'argc == 3 || argc == 2' represents the number of parameters is three or two + RDB_NAPI_ASSERT(env, status == napi_ok && (argc == 3 || argc == 2), std::make_shared("2 or 3")); -void RdbStoreProxy::SetBusinessError(napi_env env, std::shared_ptr error, napi_value *businessError) -{ - if (error != nullptr) { - napi_value code = nullptr; - napi_value msg = nullptr; - napi_create_int32(env, error->GetCode(), &code); + auto proxy = GetNativeInstance(env, self); + RDB_NAPI_ASSERT(env, proxy != nullptr, std::make_shared("RdbStore", "valid")); + RDB_NAPI_ASSERT(env, proxy->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); + + std::string event; + // 'argv[0]' represents a event + status = JSUtils::Convert2Value(env, argv[0], event); + RDB_NAPI_ASSERT( + env, status == napi_ok && !event.empty(), std::make_shared("event", "a not empty string.")); + for (auto &eventInfo : onEventHandlers_) { + if (eventInfo.event == event) { + return (proxy->*(eventInfo.handle))(env, argc - 1, argv + 1); + } + } + // 'argc == 3' represents the number of parameters is three + RDB_NAPI_ASSERT(env, status == napi_ok && argc == 3, std::make_shared("3")); + bool valueBool = false; + status = JSUtils::Convert2Value(env, argv[1], valueBool); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("interProcess", "a boolean.")); + napi_valuetype type = napi_undefined; + // 'argv[2]' is observer function + napi_typeof(env, argv[2], &type); + RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("observer", "function")); + DistributedRdb::SubscribeOption option; + option.event = event; + option.mode = valueBool ? DistributedRdb::SubscribeMode::LOCAL_SHARED : DistributedRdb::SubscribeMode::LOCAL; + // 'argv[2]' represents a callback function + return proxy->RegisteredObserver(env, option, argv[2]); +} + +napi_value RdbStoreProxy::OffEvent(napi_env env, napi_callback_info info) +{ + size_t argc = 3; + // 'argv[3]' represents an array containing three elements + napi_value argv[3] = { nullptr }; + napi_value self = nullptr; + int32_t status = napi_get_cb_info(env, info, &argc, argv, &self, nullptr); + // '1 <= argc && argc <= 3' represents the number of parameters is 1 - 3 + RDB_NAPI_ASSERT(env, status == napi_ok && 1 <= argc && argc <= 3, std::make_shared("1 - 3")); + + auto proxy = GetNativeInstance(env, self); + RDB_NAPI_ASSERT(env, proxy != nullptr, std::make_shared("RdbStore", "valid")); + RDB_NAPI_ASSERT(env, proxy->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); + + std::string event; + status = JSUtils::Convert2Value(env, argv[0], event); + RDB_NAPI_ASSERT( + env, status == napi_ok && !event.empty(), std::make_shared("event", "a not empty string.")); + for (auto &eventInfo : offEventHandlers_) { + if (eventInfo.event == event) { + return (proxy->*(eventInfo.handle))(env, argc - 1, argv + 1); + } + } + // 'argc >= 2' represents the number of parameters is two or three + RDB_NAPI_ASSERT(env, status == napi_ok && argc >= 2, std::make_shared("2 or 3")); + bool valueBool = false; + status = JSUtils::Convert2Value(env, argv[1], valueBool); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("interProcess", "a boolean.")); + + // 'argc == 3' represents determine whether the value of variable 'argc' is equal to '3' + if (argc == 3) { + napi_valuetype type = napi_undefined; + // 'argv[2]' represents a callback function + napi_typeof(env, argv[2], &type); + RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("observer", "function")); + } + SubscribeOption option; + option.event = event; + valueBool ? option.mode = SubscribeMode::LOCAL_SHARED : option.mode = SubscribeMode::LOCAL; + // 'argv[2]' represents a callback function, 'argc == 3' represents determine if 'argc' is equal to '3' + return proxy->UnRegisteredObserver(env, option, argc == 3 ? argv[2] : nullptr); +} + +napi_value RdbStoreProxy::OnStatistics(napi_env env, size_t argc, napi_value *argv) +{ + napi_valuetype type = napi_undefined; + napi_typeof(env, argv[0], &type); + RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("statistics", "function")); + bool result = std::any_of(statisticses_.begin(), statisticses_.end(), + [argv](std::shared_ptr obs) { return obs && *obs == argv[0]; }); + if (result) { + LOG_DEBUG("Duplicate subscribe."); + return nullptr; + } + auto observer = std::make_shared(env, argv[0], queue_); + int errCode = DistributedRdb::SqlStatistic::Subscribe(observer); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + statisticses_.push_back(std::move(observer)); + LOG_INFO("Statistics subscribe success."); + return nullptr; +} + +napi_value RdbStoreProxy::OffStatistics(napi_env env, size_t argc, napi_value *argv) +{ + napi_valuetype type; + napi_typeof(env, argv[0], &type); + RDB_NAPI_ASSERT(env, type == napi_function || type == napi_undefined || type == napi_null, + std::make_shared("statistics", "function")); + + auto it = statisticses_.begin(); + while (it != statisticses_.end()) { + if (*it == nullptr) { + it = statisticses_.erase(it); + LOG_WARN("statisticsObserver is nullptr."); + continue; + } + if (type == napi_function && !(**it == argv[0])) { + ++it; + continue; + } + int errCode = DistributedRdb::SqlStatistic::Unsubscribe(*it); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + (*it)->Clear(); + it = statisticses_.erase(it); + } + return nullptr; +} + +napi_value RdbStoreProxy::OnPerfStat(napi_env env, size_t argc, napi_value *argv) +{ + RDB_NAPI_ASSERT(env, this->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); + int32_t dbType = this->GetInstance()->GetDbType(); + RDB_NAPI_ASSERT(env, dbType == DB_SQLITE, std::make_shared(NativeRdb::E_NOT_SUPPORT)); + napi_valuetype type = napi_undefined; + napi_typeof(env, argv[0], &type); + RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("perfStat", "function")); + bool result = std::any_of(perfStats_.begin(), perfStats_.end(), + [argv](std::shared_ptr obs) { return obs && *obs == argv[0]; }); + if (result) { + LOG_DEBUG("Duplicate subscribe."); + return nullptr; + } + auto observer = std::make_shared(env, argv[0], queue_); + std::string path = this->GetInstance()->GetPath(); + int errCode = DistributedRdb::PerfStat::Subscribe(path, observer); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + perfStats_.push_back(std::move(observer)); + LOG_DEBUG("perfStats_ subscribe success."); + return nullptr; +} + +napi_value RdbStoreProxy::OffPerfStat(napi_env env, size_t argc, napi_value *argv) +{ + RDB_NAPI_ASSERT(env, this->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); + int32_t dbType = this->GetInstance()->GetDbType(); + RDB_NAPI_ASSERT(env, dbType == DB_SQLITE, std::make_shared(NativeRdb::E_NOT_SUPPORT)); + napi_valuetype type; + napi_typeof(env, argv[0], &type); + RDB_NAPI_ASSERT(env, type == napi_function || type == napi_undefined || type == napi_null, + std::make_shared("perfStat", "function")); + + auto it = perfStats_.begin(); + while (it != perfStats_.end()) { + if (*it == nullptr) { + it = perfStats_.erase(it); + LOG_WARN("perfStatsObserver is nullptr."); + continue; + } + if (type == napi_function && !(**it == argv[0])) { + ++it; + continue; + } + std::string path = this->GetInstance()->GetPath(); + int errCode = DistributedRdb::PerfStat::Unsubscribe(path, *it); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + (*it)->Clear(); + it = perfStats_.erase(it); + } + return nullptr; +} + +napi_value RdbStoreProxy::OnErrorLog(napi_env env, size_t argc, napi_value *argv) +{ + RDB_NAPI_ASSERT(env, this->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); + int32_t dbType = this->GetInstance()->GetDbType(); + RDB_NAPI_ASSERT(env, dbType == DB_SQLITE, std::make_shared(NativeRdb::E_NOT_SUPPORT)); + napi_valuetype type = napi_undefined; + napi_typeof(env, argv[0], &type); + RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("sqliteErrorOccurred", "function")); + bool result = std::any_of(logObservers_.begin(), logObservers_.end(), + [argv](std::shared_ptr obs) { return obs && *obs == argv[0]; }); + if (result) { + LOG_DEBUG("Duplicate subscribe."); + return nullptr; + } + auto observer = std::make_shared(env, argv[0], queue_); + std::string dbPath = this->GetInstance()->GetPath(); + int errCode = NativeRdb::SqlLog::Subscribe(dbPath, observer); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + logObservers_.push_back(std::move(observer)); + LOG_DEBUG("sqliteErrorOccurred subscribe success."); + return nullptr; +} + +napi_value RdbStoreProxy::OffErrorLog(napi_env env, size_t argc, napi_value *argv) +{ + RDB_NAPI_ASSERT(env, this->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); + int32_t dbType = this->GetInstance()->GetDbType(); + RDB_NAPI_ASSERT(env, dbType == DB_SQLITE, std::make_shared(NativeRdb::E_NOT_SUPPORT)); + napi_valuetype type; + napi_typeof(env, argv[0], &type); + RDB_NAPI_ASSERT(env, type == napi_function || type == napi_undefined || type == napi_null, + std::make_shared("sqliteErrorOccurred", "function")); + + auto it = logObservers_.begin(); + while (it != logObservers_.end()) { + if (*it == nullptr) { + it = logObservers_.erase(it); + LOG_WARN("logObserver is nullptr."); + continue; + } + if (type == napi_function && !(**it == argv[0])) { + ++it; + continue; + } + std::string dbPath = this->GetInstance()->GetPath(); + int errCode = NativeRdb::SqlLog::Unsubscribe(dbPath, *it); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + (*it)->Clear(); + it = logObservers_.erase(it); + } + return nullptr; +} + +napi_value RdbStoreProxy::RegisteredObserver( + napi_env env, const DistributedRdb::SubscribeOption &option, napi_value callback) +{ + auto &observers = option.mode == SubscribeMode::LOCAL ? localObservers_ : localSharedObservers_; + observers.try_emplace(option.event); + auto &list = observers.find(option.event)->second; + bool result = + std::any_of(list.begin(), list.end(), [callback](const auto &observer) { return *observer == callback; }); + if (result) { + LOG_INFO("Duplicate subscribe event: %{public}s", option.event.c_str()); + return nullptr; + } + + auto uvQueue = std::make_shared(env); + auto localObserver = std::make_shared(callback, uvQueue); + int errCode = GetInstance()->Subscribe(option, localObserver); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + observers[option.event].push_back(localObserver); + LOG_INFO("Subscribe success event: %{public}s", option.event.c_str()); + return nullptr; +} + +napi_value RdbStoreProxy::UnRegisteredObserver( + napi_env env, const DistributedRdb::SubscribeOption &option, napi_value callback) +{ + auto &observers = option.mode == SubscribeMode::LOCAL ? localObservers_ : localSharedObservers_; + auto obs = observers.find(option.event); + if (obs == observers.end()) { + LOG_INFO("Observer not found, event: %{public}s", option.event.c_str()); + return nullptr; + } + + if (callback) { + auto &list = obs->second; + for (auto it = list.begin(); it != list.end(); it++) { + if (**it == callback) { + int errCode = GetInstance()->UnSubscribe(option, *it); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + list.erase(it); + break; + } + } + if (list.empty()) { + observers.erase(option.event); + } + } else { + int errCode = GetInstance()->UnSubscribe(option, nullptr); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + observers.erase(option.event); + } + LOG_INFO("Unsubscribe success, event: %{public}s", option.event.c_str()); + return nullptr; +} + +#if !defined(CROSS_PLATFORM) +void RdbStoreProxy::AddDistributedFunctions(std::vector &properties) +{ + properties.push_back(DECLARE_NAPI_FUNCTION("remoteQuery", RemoteQuery)); + properties.push_back(DECLARE_NAPI_FUNCTION("setDistributedTables", SetDistributedTables)); + properties.push_back(DECLARE_NAPI_FUNCTION("obtainDistributedTableName", ObtainDistributedTableName)); + properties.push_back(DECLARE_NAPI_FUNCTION("sync", Sync)); + properties.push_back(DECLARE_NAPI_FUNCTION("cloudSync", CloudSync)); + properties.push_back(DECLARE_NAPI_FUNCTION("getModifyTime", GetModifyTime)); + properties.push_back(DECLARE_NAPI_FUNCTION("cleanDirtyData", CleanDirtyData)); + properties.push_back(DECLARE_NAPI_FUNCTION("emit", Notify)); + properties.push_back(DECLARE_NAPI_FUNCTION("querySharingResource", QuerySharingResource)); + properties.push_back(DECLARE_NAPI_FUNCTION("lockRow", LockRow)); + properties.push_back(DECLARE_NAPI_FUNCTION("unlockRow", UnlockRow)); + properties.push_back(DECLARE_NAPI_FUNCTION("queryLockedRow", QueryLockedRow)); + properties.push_back(DECLARE_NAPI_FUNCTION("lockCloudContainer", LockCloudContainer)); + properties.push_back(DECLARE_NAPI_FUNCTION("unlockCloudContainer", UnlockCloudContainer)); +} + +napi_value RdbStoreProxy::SetDistributedTables(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + CHECK_RETURN_SET_E(1 <= argc && argc <= 3, std::make_shared("1 - 4")); + CHECK_RETURN(OK == ParserThis(env, self, context)); + CHECK_RETURN(OK == ParseTablesName(env, argv[0], context)); + CHECK_RETURN(OK == ParseDistributedTypeArg(env, argc, argv, context)); + CHECK_RETURN(OK == ParseDistributedConfigArg(env, argc, argv, context)); + }; + auto exec = [context]() -> int { + CHECK_RETURN_ERR(context->rdbStore != nullptr); + auto rdbStore = std::move(context->rdbStore); + return rdbStore->SetDistributedTables( + context->tablesNames, context->distributedType, context->distributedConfig); + }; + auto output = [context](napi_env env, napi_value &result) { + napi_status status = napi_get_undefined(env, &result); + CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); + }; + context->SetAction(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return ASYNC_CALL(env, context); +} + +napi_value RdbStoreProxy::ObtainDistributedTableName(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + CHECK_RETURN_SET_E(argc == 2, std::make_shared("2 or 3")); + CHECK_RETURN(OK == ParserThis(env, self, context)); + CHECK_RETURN(OK == ParseDevice(env, argv[0], context)); + CHECK_RETURN(OK == ParseTableName(env, argv[1], context)); + }; + auto exec = [context]() -> int { + LOG_DEBUG("RdbStoreProxy::ObtainDistributedTableName Async."); + CHECK_RETURN_ERR(context->rdbStore != nullptr); + int errCode = E_ERROR; + context->tableName = + context->rdbStore->ObtainDistributedTableName(context->device, context->tableName, errCode); + context->rdbStore = nullptr; + return errCode; + }; + auto output = [context](napi_env env, napi_value &result) { + std::string table = context->tableName; + napi_status status = napi_create_string_utf8(env, table.c_str(), table.length(), &result); + CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); + LOG_DEBUG("RdbStoreProxy::ObtainDistributedTableName end."); + }; + context->SetAction(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return ASYNC_CALL(env, context); +} + +napi_value RdbStoreProxy::Sync(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + CHECK_RETURN_SET_E(argc == 2, std::make_shared("2 or 3")); + CHECK_RETURN(OK == ParserThis(env, self, context)); + CHECK_RETURN(OK == ParseSyncModeArg(env, argv[0], context)); + CHECK_RETURN(OK == ParsePredicates(env, argv[1], context)); + }; + context->SetAction(env, info, std::move(input), nullptr, nullptr); + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + RdbStoreProxy *obj = reinterpret_cast(context->boundObj); + auto queue = obj->queue_; + napi_value promise = nullptr; + auto defer = context->defer_; + auto callback = context->callback_; + context->callback_ = nullptr; + if (callback == nullptr) { + napi_status status = napi_create_promise(env, &defer, &promise); + RDB_NAPI_ASSERT_BASE(env, status == napi_ok, + std::make_shared("failed(" + std::to_string(status) + ") to create promise"), nullptr); + } else { + napi_get_undefined(env, &promise); + } + auto predicates = *context->predicatesProxy->GetPredicates(); + auto exec = [queue, defer, callback, predicates, rdbStore = std::move(context->rdbStore), + enumArg = context->enumArg]() mutable { + SyncOption option{ static_cast(enumArg), false }; + auto ret = rdbStore->Sync(option, predicates, [queue, defer, callback](const SyncResult &result) { + auto args = [result](napi_env env, int &argc, napi_value *argv) { + argv[1] = JSUtils::Convert2JSValue(env, result); + }; + callback ? queue->AsyncCall({ callback }, args) : queue->AsyncPromise({ defer }, args); + }); + if (ret != NativeRdb::E_OK) { + auto args = [ret](napi_env env, int &argc, napi_value *argv) mutable { + SetBusinessError(env, std::make_shared(ret), &argv[0]); + }; + callback ? queue->AsyncCall({ callback }, args) : queue->AsyncPromise({ defer }, args); + } + }; + queue->Execute(std::move(exec)); + context = nullptr; + return promise; +} + +void RdbStoreProxy::SetBusinessError(napi_env env, std::shared_ptr error, napi_value *businessError) +{ + if (error != nullptr) { + napi_value code = nullptr; + napi_value msg = nullptr; + napi_create_int32(env, error->GetCode(), &code); napi_create_string_utf8(env, error->GetMessage().c_str(), NAPI_AUTO_LENGTH, &msg); napi_create_error(env, code, msg, businessError); } @@ -1624,6 +1650,9 @@ napi_value RdbStoreProxy::CleanDirtyData(napi_env env, napi_callback_info info) napi_value RdbStoreProxy::OnRemote(napi_env env, size_t argc, napi_value *argv) { + // argc must be greater than or equal to 2 to be valid + RDB_NAPI_ASSERT(env, argc >= 2 && argv != nullptr, + std::make_shared(" argc is less than 2 or argv is nullptr")); napi_valuetype type = napi_undefined; int32_t mode = SubscribeMode::SUBSCRIBE_MODE_MAX; napi_get_value_int32(env, argv[0], &mode); @@ -1648,7 +1677,7 @@ napi_value RdbStoreProxy::OnRemote(napi_env env, size_t argc, napi_value *argv) if (option.mode == SubscribeMode::LOCAL_DETAIL) { errCode = GetInstance()->SubscribeObserver(option, observer); } else { - errCode = GetInstance()->Subscribe(option, observer.get()); + errCode = GetInstance()->Subscribe(option, observer); } RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); observers_[mode].push_back(observer); @@ -1656,28 +1685,6 @@ napi_value RdbStoreProxy::OnRemote(napi_env env, size_t argc, napi_value *argv) return nullptr; } -napi_value RdbStoreProxy::RegisteredObserver( - napi_env env, const DistributedRdb::SubscribeOption &option, napi_value callback) -{ - auto &observers = option.mode == SubscribeMode::LOCAL ? localObservers_ : localSharedObservers_; - observers.try_emplace(option.event); - auto &list = observers.find(option.event)->second; - bool result = - std::any_of(list.begin(), list.end(), [callback](const auto &observer) { return *observer == callback; }); - if (result) { - LOG_INFO("Duplicate subscribe event: %{public}s", option.event.c_str()); - return nullptr; - } - - auto uvQueue = std::make_shared(env); - auto localObserver = std::make_shared(callback, uvQueue); - int errCode = GetInstance()->Subscribe(option, localObserver.get()); - RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); - observers[option.event].push_back(localObserver); - LOG_INFO("Subscribe success event: %{public}s", option.event.c_str()); - return nullptr; -} - napi_value RdbStoreProxy::OffRemote(napi_env env, size_t argc, napi_value *argv) { napi_valuetype type = napi_undefined; @@ -1711,7 +1718,7 @@ napi_value RdbStoreProxy::OffRemote(napi_env env, size_t argc, napi_value *argv) if (option.mode == SubscribeMode::LOCAL_DETAIL) { errCode = GetInstance()->UnsubscribeObserver(option, *it); } else { - errCode = GetInstance()->UnSubscribe(option, it->get()); + errCode = GetInstance()->UnSubscribe(option, *it); } RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); (*it)->Clear(); @@ -1721,118 +1728,6 @@ napi_value RdbStoreProxy::OffRemote(napi_env env, size_t argc, napi_value *argv) return nullptr; } -napi_value RdbStoreProxy::UnRegisteredObserver( - napi_env env, const DistributedRdb::SubscribeOption &option, napi_value callback) -{ - auto &observers = option.mode == SubscribeMode::LOCAL ? localObservers_ : localSharedObservers_; - auto obs = observers.find(option.event); - if (obs == observers.end()) { - LOG_INFO("Observer not found, event: %{public}s", option.event.c_str()); - return nullptr; - } - - if (callback) { - auto &list = obs->second; - for (auto it = list.begin(); it != list.end(); it++) { - if (**it == callback) { - int errCode = GetInstance()->UnSubscribe(option, it->get()); - RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); - list.erase(it); - break; - } - } - if (list.empty()) { - observers.erase(option.event); - } - } else { - int errCode = GetInstance()->UnSubscribe(option, nullptr); - RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); - observers.erase(option.event); - } - LOG_INFO("Unsubscribe success, event: %{public}s", option.event.c_str()); - return nullptr; -} - -napi_value RdbStoreProxy::OnEvent(napi_env env, napi_callback_info info) -{ - size_t argc = 3; - napi_value argv[3]{}; - napi_value self = nullptr; - int32_t status = napi_get_cb_info(env, info, &argc, argv, &self, nullptr); - // 'argc == 3 || argc == 2' represents the number of parameters is three or two - RDB_NAPI_ASSERT(env, status == napi_ok && (argc == 3 || argc == 2), std::make_shared("2 or 3")); - - auto proxy = GetNativeInstance(env, self); - RDB_NAPI_ASSERT(env, proxy != nullptr, std::make_shared("RdbStore", "valid")); - RDB_NAPI_ASSERT(env, proxy->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); - - std::string event; - // 'argv[0]' represents a event - status = JSUtils::Convert2Value(env, argv[0], event); - RDB_NAPI_ASSERT( - env, status == napi_ok && !event.empty(), std::make_shared("event", "a not empty string.")); - for (auto &eventInfo : onEventHandlers_) { - if (eventInfo.event == event) { - return (proxy->*(eventInfo.handle))(env, argc - 1, argv + 1); - } - } - - bool valueBool = false; - status = JSUtils::Convert2Value(env, argv[1], valueBool); - RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("interProcess", "a boolean.")); - napi_valuetype type = napi_undefined; - // 'argv[2]' is observer function - napi_typeof(env, argv[2], &type); - RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("observer", "function")); - SubscribeOption option; - option.event = event; - option.mode = valueBool ? SubscribeMode::LOCAL_SHARED : SubscribeMode::LOCAL; - // 'argv[2]' represents a callback function - return proxy->RegisteredObserver(env, option, argv[2]); -} - -napi_value RdbStoreProxy::OffEvent(napi_env env, napi_callback_info info) -{ - size_t argc = 3; - // 'argv[3]' represents an array containing three elements - napi_value argv[3] = { nullptr }; - napi_value self = nullptr; - int32_t status = napi_get_cb_info(env, info, &argc, argv, &self, nullptr); - // '1 <= argc && argc <= 3' represents the number of parameters is 1 - 3 - RDB_NAPI_ASSERT(env, status == napi_ok && 1 <= argc && argc <= 3, std::make_shared("1 - 3")); - - auto proxy = GetNativeInstance(env, self); - RDB_NAPI_ASSERT(env, proxy != nullptr, std::make_shared("RdbStore", "valid")); - RDB_NAPI_ASSERT(env, proxy->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); - - std::string event; - status = JSUtils::Convert2Value(env, argv[0], event); - RDB_NAPI_ASSERT( - env, status == napi_ok && !event.empty(), std::make_shared("event", "a not empty string.")); - for (auto &eventInfo : offEventHandlers_) { - if (eventInfo.event == event) { - return (proxy->*(eventInfo.handle))(env, argc - 1, argv + 1); - } - } - - bool valueBool = false; - status = JSUtils::Convert2Value(env, argv[1], valueBool); - RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("interProcess", "a boolean.")); - - // 'argc == 3' represents determine whether the value of variable 'argc' is equal to '3' - if (argc == 3) { - napi_valuetype type = napi_undefined; - // 'argv[2]' represents a callback function - napi_typeof(env, argv[2], &type); - RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("observer", "function")); - } - SubscribeOption option; - option.event = event; - valueBool ? option.mode = SubscribeMode::LOCAL_SHARED : option.mode = SubscribeMode::LOCAL; - // 'argv[2]' represents a callback function, 'argc == 3' represents determine if 'argc' is equal to '3' - return proxy->UnRegisteredObserver(env, option, argc == 3 ? argv[2] : nullptr); -} - napi_value RdbStoreProxy::Notify(napi_env env, napi_callback_info info) { size_t argc = 1; @@ -1929,51 +1824,6 @@ napi_value RdbStoreProxy::UnregisterSyncCallback(napi_env env, size_t argc, napi return nullptr; } -napi_value RdbStoreProxy::OnStatistics(napi_env env, size_t argc, napi_value *argv) -{ - napi_valuetype type = napi_undefined; - napi_typeof(env, argv[0], &type); - RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("statistics", "function")); - bool result = std::any_of(statisticses_.begin(), statisticses_.end(), - [argv](std::shared_ptr obs) { return obs && *obs == argv[0]; }); - if (result) { - LOG_DEBUG("Duplicate subscribe."); - return nullptr; - } - auto observer = std::make_shared(env, argv[0], queue_); - int errCode = DistributedRdb::SqlStatistic::Subscribe(observer); - RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); - statisticses_.push_back(std::move(observer)); - LOG_DEBUG("Statistics subscribe success."); - return nullptr; -} - -napi_value RdbStoreProxy::OffStatistics(napi_env env, size_t argc, napi_value *argv) -{ - napi_valuetype type; - napi_typeof(env, argv[0], &type); - RDB_NAPI_ASSERT(env, type == napi_function || type == napi_undefined || type == napi_null, - std::make_shared("statistics", "function")); - - auto it = statisticses_.begin(); - while (it != statisticses_.end()) { - if (*it == nullptr) { - it = statisticses_.erase(it); - LOG_WARN("statisticsObserver is nullptr."); - continue; - } - if (type == napi_function && !(**it == argv[0])) { - ++it; - continue; - } - int errCode = DistributedRdb::SqlStatistic::Unsubscribe(*it); - RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); - (*it)->Clear(); - it = statisticses_.erase(it); - } - return nullptr; -} - RdbStoreProxy::SyncObserver::SyncObserver( napi_env env, napi_value callback, std::shared_ptr queue) : env_(env), queue_(queue) @@ -2068,8 +1918,7 @@ napi_value RdbStoreProxy::QueryLockedRow(napi_env env, napi_callback_info info) context->rdbPredicates->EqualTo(AbsRdbPredicates::LOCK_STATUS, AbsRdbPredicates::LOCK_CHANGED)->EndWrap(); context->resultSet = context->rdbStore->QueryByStep(*(context->rdbPredicates), context->columns); context->rdbStore = nullptr; - // If the API version is greater than or equal to 20, throw E_ALREADY_CLOSED. - return (context->resultSet != nullptr) ? E_OK : (JSUtils::GetHapVersion() >= 20) ? E_ALREADY_CLOSED : E_ERROR; + return (context->resultSet != nullptr) ? E_OK : E_ERROR; }; auto output = [context](napi_env env, napi_value &result) { result = ResultSetProxy::NewInstance(env, std::move(context->resultSet)); diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp index 83c547adfc3615e1be94af68ce71dd51339ea098..d3682a3a5ff73ee15fcf9451a50b018dbd7b38cb 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp @@ -16,12 +16,14 @@ #include "napi_rdb_store_helper.h" #include +#include #include #include #include #include "logger.h" #include "napi_async_call.h" +#include "napi_rdb_context.h" #include "napi_rdb_error.h" #include "napi_rdb_js_utils.h" #include "napi_rdb_store.h" @@ -29,6 +31,8 @@ #include "rdb_errno.h" #include "rdb_open_callback.h" #include "rdb_store_config.h" +#include "rdb_sql_utils.h" +#include "sqlite_sql_builder.h" #include "unistd.h" using namespace OHOS::Rdb; @@ -38,8 +42,17 @@ using namespace OHOS::AppDataMgrJsKit::JSUtils; namespace OHOS { namespace RelationalStoreJsKit { +constexpr int32_t PARAM_LENGTH_MAX = 256; +constexpr int32_t VALUESBUCKET_LENGTH_MAX = 1000; using ContextParam = AppDataMgrJsKit::JSUtils::ContextParam; +const std::map ERR_STRING_MAP = { + { E_EMPTY_TABLE_NAME, "The table must be not empty string." }, + { E_EMPTY_VALUES_BUCKET, "Bucket must not be empty." }, + { E_INVALID_CONFLICT_FLAG, "Conflict flag is not correct." }, + { E_INVALID_ARGS, "The ValueBucket contains Assets and conflictResolution is REPLACE." }, +}; + class DefaultOpenCallback : public RdbOpenCallback { public: int OnCreate(RdbStore &rdbStore) override @@ -96,7 +109,7 @@ napi_value GetRdbStore(napi_env env, napi_callback_info info) return errCode; }; auto output = [context](napi_env env, napi_value &result) { - result = RdbStoreProxy::NewInstance(env, context->proxy, context->param.isSystemApp, context->param.bundleName); + result = RdbStoreProxy::NewInstance(env, context->proxy, context->param.isSystemApp); CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_ERROR)); }; context->SetAction(env, info, input, exec, output); @@ -134,16 +147,15 @@ napi_value DeleteRdbStore(napi_env env, napi_callback_info info) CHECK_RETURN_SET_E(OK == code, err); }; auto exec = [context]() -> int { - // If the API version is greater than or equal to 20, close the connection. RdbStoreConfig storeConfig = GetRdbStoreConfig(context->config, context->param); if (context->onlyPath) { storeConfig.SetDBType(DB_SQLITE); - int errCodeSqlite = RdbHelper::DeleteRdbStore(storeConfig, JSUtils::GetHapVersion() >= 20); + int errCodeSqlite = RdbHelper::DeleteRdbStore(storeConfig, false); storeConfig.SetDBType(DB_VECTOR); - int errCodeVector = RdbHelper::DeleteRdbStore(storeConfig, JSUtils::GetHapVersion() >= 20); + int errCodeVector = RdbHelper::DeleteRdbStore(storeConfig, false); return (errCodeSqlite == E_OK && errCodeVector == E_OK) ? E_OK : E_REMOVE_FILE; } - return RdbHelper::DeleteRdbStore(storeConfig, JSUtils::GetHapVersion() >= 20); + return RdbHelper::DeleteRdbStore(storeConfig, false); }; auto output = [context](napi_env env, napi_value &result) { napi_status status = napi_create_int64(env, OK, &result); @@ -176,6 +188,211 @@ napi_value IsTokenizerSupported(napi_env env, napi_callback_info info) return JSUtils::Convert2JSValue(env, result); } +static std::string GetErrorString(int errcode) +{ + if (ERR_STRING_MAP.find(errcode) != ERR_STRING_MAP.end()) { + return ERR_STRING_MAP.at(errcode); + } + return std::string(); +} + +int CheckTableName(const std::string &tableName) +{ + if (tableName.size() > PARAM_LENGTH_MAX) { + return ERR; + } + return OK; +} + +int CheckPredicatesWhereClause(const std::string &whereClause) +{ + if (whereClause.size() > PARAM_LENGTH_MAX) { + return ERR; + } + return OK; +} + +int CheckValuesBucket(const ValuesBucket &valuesBucket) +{ + if (valuesBucket.values_.size() > VALUESBUCKET_LENGTH_MAX) { + return ERR; + } + for (const auto &[key, val] : valuesBucket.values_) { + if (key.size() > PARAM_LENGTH_MAX) { + return ERR; + } + } + return OK; +} + +int CheckColumns(const std::vector &columns) +{ + if (columns.size() > VALUESBUCKET_LENGTH_MAX) { + return ERR; + } + for (const auto &key : columns) { + if (key.size() > PARAM_LENGTH_MAX) { + return ERR; + } + } + return OK; +} + +napi_value GetInsertSqlInfo(napi_env env, napi_callback_info info) +{ + LOG_DEBUG("GetInsertSqlInfo begin"); + size_t argc = 3; + napi_value argv[3]{}; + napi_value self = nullptr; + napi_get_cb_info(env, info, &argc, argv, &self, nullptr); + //2 or 3 is number of input parameters. If no, an error is reported. + RDB_NAPI_ASSERT(env, (argc == 2 || argc == 3), std::make_shared("2 or 3")); + auto context = std::make_shared(); + RDB_NAPI_ASSERT(env, + (OK == ParseTableName(env, argv[0], context)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "The table must be not empty string.")); + RDB_NAPI_ASSERT(env, + (OK == ParseValuesBucket(env, argv[1], context)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Bucket must not be empty.")); + RDB_NAPI_ASSERT( + env, (OK == CheckTableName(context->tableName)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Table is too long.")); + RDB_NAPI_ASSERT(env, + (OK == CheckValuesBucket(context->valuesBucket)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "ValuesBucket is too long.")); + ConflictResolution conflict = ConflictResolution::ON_CONFLICT_NONE; + //3 is number of input parameters, Third parameter is ConflictResolution + if (argc == 3) { + //2 is indicates the third input parameter. + auto status = ParseConflictResolution(env, argv[2], context); + RDB_NAPI_ASSERT(env, + (OK == status), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "ConflictResolution is invalid.")); + conflict = context->conflictResolution; + } + + auto [errcode, sqlInfo] = RdbSqlUtils::GetInsertSqlInfo(context->tableName, context->valuesBucket, conflict); + RDB_NAPI_ASSERT( + env, errcode == E_OK, std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, GetErrorString(errcode))); + LOG_DEBUG("GetInsertSqlInfo end"); + return Convert2JSValue(env, sqlInfo); +} + +napi_value GetUpdateSqlInfo(napi_env env, napi_callback_info info) +{ + LOG_DEBUG("GetUpdateSqlInfo Begin."); + size_t argc = 3; + napi_value argv[3]{}; + napi_value self = nullptr; + napi_get_cb_info(env, info, &argc, argv, &self, nullptr); + //2 or 3 is number of input parameters. If no, an error is reported. + RDB_NAPI_ASSERT(env, (argc == 2 || argc == 3), std::make_shared("2 or 3")); + auto context = std::make_shared(); + RDB_NAPI_ASSERT(env, + (OK == ParsePredicates(env, argv[0], context)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Predicates is empty.")); + RDB_NAPI_ASSERT(env, + (OK == ParseValuesBucket(env, argv[1], context)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Bucket must not be empty.")); + ConflictResolution conflict = ConflictResolution::ON_CONFLICT_NONE; + //3 is number of input parameters, Third parameter is ConflictResolution + if (argc == 3) { + //2 is indicates the third input parameter. + auto status = ParseConflictResolution(env, argv[2], context); + RDB_NAPI_ASSERT(env, + (OK == status), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "ConflictResolution is invalid.")); + conflict = context->conflictResolution; + } + auto predicates = context->rdbPredicates; + RDB_NAPI_ASSERT(env, + (!predicates->GetTableName().empty()), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "The table must be not empty string.")); + RDB_NAPI_ASSERT(env, + (OK == CheckPredicatesWhereClause(predicates->GetWhereClause())), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Columns in predicates is too much.")); + RDB_NAPI_ASSERT( + env, (OK == CheckTableName(predicates->GetTableName())), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Table is too long.")); + RDB_NAPI_ASSERT(env, + (OK == CheckValuesBucket(context->valuesBucket)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "ValuesBucket is too long.")); + auto [errcode, sqlInfo] = RdbSqlUtils::GetUpdateSqlInfo(*predicates, context->valuesBucket, conflict); + RDB_NAPI_ASSERT( + env, errcode == E_OK, std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, GetErrorString(errcode))); + LOG_DEBUG("GetUpdateSqlInfo end."); + return Convert2JSValue(env, sqlInfo); +} + +napi_value GetDeleteSqlInfo(napi_env env, napi_callback_info info) +{ + LOG_DEBUG("GetDeleteSqlInfo start"); + auto context = std::make_shared(); + size_t argc = 1; + napi_value argv[1]{}; + napi_value self = nullptr; + napi_get_cb_info(env, info, &argc, argv, &self, nullptr); + RDB_NAPI_ASSERT(env, argc == 1, std::make_shared("1")); + RDB_NAPI_ASSERT(env, + (OK == ParsePredicates(env, argv[0], context)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "predicates is empty.")); + auto predicates = context->rdbPredicates; + RDB_NAPI_ASSERT(env, + (!predicates->GetTableName().empty()), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "The table must be not empty string.")); + RDB_NAPI_ASSERT( + env, (OK == CheckTableName(predicates->GetTableName())), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Table is too long.")); + RDB_NAPI_ASSERT(env, + (OK == CheckPredicatesWhereClause(predicates->GetWhereClause())), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Columns in predicates is too much.")); + auto [errcode, sqlInfo] = RdbSqlUtils::GetDeleteSqlInfo(*predicates); + RDB_NAPI_ASSERT( + env, errcode == E_OK, std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, GetErrorString(errcode))); + LOG_DEBUG("GetDeleteSqlInfo end"); + return Convert2JSValue(env, sqlInfo); +} + +napi_value GetQuerySqlInfo(napi_env env, napi_callback_info info) +{ + LOG_DEBUG("GetQuerySqlInfo start"); + auto context = std::make_shared(); + size_t argc = 2; + napi_value argv[2]{}; + napi_value self = nullptr; + napi_get_cb_info(env, info, &argc, argv, &self, nullptr); + //1 or 2 is number of input parameters. If no, an error is reported. + RDB_NAPI_ASSERT(env, (argc == 1 || argc == 2), std::make_shared("1 or 2")); + RDB_NAPI_ASSERT(env, + (OK == ParsePredicates(env, argv[0], context)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "predicates is empty.")); + //2 is number of input parameters + if (argc == 2) { + auto status = ParseColumns(env, argv[1], context); + RDB_NAPI_ASSERT(env, + (OK == status), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Columns is not a string array.")); + } + auto predicates = context->rdbPredicates; + auto columns = context->columns; + RDB_NAPI_ASSERT(env, + (!predicates->GetTableName().empty()), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "The table must be not empty string.")); + RDB_NAPI_ASSERT(env, + (OK == CheckPredicatesWhereClause(predicates->GetWhereClause())), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Columns in predicates is too much.")); + RDB_NAPI_ASSERT(env, + (OK == CheckTableName(predicates->GetTableName())), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Table is too long.")); + RDB_NAPI_ASSERT(env, (OK == CheckColumns(columns)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Columns is too long.")); + auto [errcode, sqlInfo] = RdbSqlUtils::GetQuerySqlInfo(*predicates, columns); + RDB_NAPI_ASSERT( + env, errcode == E_OK, std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, GetErrorString(errcode))); + LOG_DEBUG("GetQuerySqlInfo end"); + return Convert2JSValue(env, sqlInfo); +} + napi_value InitRdbHelper(napi_env env, napi_value exports) { napi_property_descriptor properties[] = { @@ -185,6 +402,10 @@ napi_value InitRdbHelper(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION_WITH_DATA("deleteRdbStoreSync", DeleteRdbStore, SYNC), DECLARE_NAPI_FUNCTION_WITH_DATA("isVectorSupported", IsVectorSupported, SYNC), DECLARE_NAPI_FUNCTION_WITH_DATA("isTokenizerSupported", IsTokenizerSupported, SYNC), + DECLARE_NAPI_FUNCTION_WITH_DATA("getInsertSqlInfo", GetInsertSqlInfo, SYNC), + DECLARE_NAPI_FUNCTION_WITH_DATA("getUpdateSqlInfo", GetUpdateSqlInfo, SYNC), + DECLARE_NAPI_FUNCTION_WITH_DATA("getDeleteSqlInfo", GetDeleteSqlInfo, SYNC), + DECLARE_NAPI_FUNCTION_WITH_DATA("getQuerySqlInfo", GetQuerySqlInfo, SYNC), }; NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(*properties), properties)); return exports; diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp index 2e464046aeb023887efc564b36b7cecf7a6dc227..984f272aaefd5a0677f8d889af2aebfcd1a7de78 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp @@ -13,16 +13,16 @@ * limitations under the License. */ -#include -#include "js_native_api.h" -#include "js_native_api_types.h" #define LOG_TAG "ResultSetProxy" #include "napi_result_set.h" #include #include +#include #include "js_df_manager.h" +#include "js_native_api.h" +#include "js_native_api_types.h" #include "js_utils.h" #include "logger.h" #include "napi_rdb_error.h" @@ -95,13 +95,17 @@ napi_value ResultSetProxy::Initialize(napi_env env, napi_callback_info info) return nullptr; } auto finalize = [](napi_env env, void *data, void *hint) { + if (data == nullptr) { + LOG_ERROR("data is nullptr."); + return; + } auto tid = JSDFManager::GetInstance().GetFreedTid(data); if (tid != 0) { LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); } if (data != hint) { - LOG_ERROR("RdbStoreProxy memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, uintptr_t(data), - uintptr_t(hint)); + LOG_ERROR("RdbStoreProxy memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, + uintptr_t(data) & LOWER_24_BITS_MASK, uintptr_t(hint) & LOWER_24_BITS_MASK); return; } ResultSetProxy *proxy = reinterpret_cast(data); @@ -256,7 +260,7 @@ napi_value ResultSetProxy::GetColumnType(napi_env env, napi_callback_info info) errCode = result->GetColumnType(context->columnIndex, context->columnType); } if (errCode == E_INVALID_ARGS) { - return E_INVALID_ARGS_NEW; + return E_PARAM_ERROR; } return errCode; }; @@ -368,9 +372,6 @@ napi_value ResultSetProxy::GoToRow(napi_env env, napi_callback_info info) if (resultSet != nullptr) { errCode = resultSet->GoToRow(position); } - // If the API version is less than 13, directly return. - RDB_NAPI_ASSERT(env, JSUtils::GetHapVersion() < 13 || (errCode == E_ROW_OUT_RANGE || errCode == E_OK), - std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } @@ -383,9 +384,6 @@ napi_value ResultSetProxy::GoTo(napi_env env, napi_callback_info info) if (resultSet != nullptr) { errCode = resultSet->GoTo(offset); } - // If the API version is less than 13, directly return. - RDB_NAPI_ASSERT(env, JSUtils::GetHapVersion() < 13 || (errCode == E_ROW_OUT_RANGE || errCode == E_OK), - std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } @@ -397,9 +395,6 @@ napi_value ResultSetProxy::GoToFirstRow(napi_env env, napi_callback_info info) if (resultSet != nullptr) { errCode = resultSet->GoToFirstRow(); } - // If the API version is less than 13, directly return. - RDB_NAPI_ASSERT(env, JSUtils::GetHapVersion() < 13 || (errCode == E_ROW_OUT_RANGE || errCode == E_OK), - std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } @@ -411,9 +406,6 @@ napi_value ResultSetProxy::GoToLastRow(napi_env env, napi_callback_info info) if (resultSet != nullptr) { errCode = resultSet->GoToLastRow(); } - // If the API version is less than 13, directly return. - RDB_NAPI_ASSERT(env, JSUtils::GetHapVersion() < 13 || (errCode == E_ROW_OUT_RANGE || errCode == E_OK), - std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } @@ -425,9 +417,6 @@ napi_value ResultSetProxy::GoToNextRow(napi_env env, napi_callback_info info) if (resultSet != nullptr) { errCode = resultSet->GoToNextRow(); } - // If the API version is less than 13, directly return. - RDB_NAPI_ASSERT(env, JSUtils::GetHapVersion() < 13 || (errCode == E_ROW_OUT_RANGE || errCode == E_OK), - std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } @@ -439,9 +428,6 @@ napi_value ResultSetProxy::GoToPreviousRow(napi_env env, napi_callback_info info if (resultSet != nullptr) { errCode = resultSet->GoToPreviousRow(); } - // If the API version is less than 13, directly return. - RDB_NAPI_ASSERT(env, JSUtils::GetHapVersion() < 13 || (errCode == E_ROW_OUT_RANGE || errCode == E_OK), - std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } @@ -586,9 +572,6 @@ napi_value ResultSetProxy::GetColumnIndex(napi_env env, napi_callback_info info) if (resultSet != nullptr) { errCode = resultSet->GetColumnIndex(input, result); } - // If the API version is less than 13, directly return. - RDB_NAPI_ASSERT(env, JSUtils::GetHapVersion() < 13 || (errCode == E_INVALID_ARGS || errCode == E_OK), - std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, result); } @@ -602,8 +585,6 @@ napi_value ResultSetProxy::GetColumnName(napi_env env, napi_callback_info info) if (resultSet != nullptr) { errCode = resultSet->GetColumnName(columnIndex, result); } - // If the API version is less than 13, directly return. - RDB_NAPI_ASSERT(env, JSUtils::GetHapVersion() < 13 || errCode == E_OK, std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, result); } diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_transaction.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_transaction.cpp index cdf204703aab7484c857982ac858057ef5b8810a..582af0bfe435850a235eec5bee46af749720d692 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_transaction.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_transaction.cpp @@ -282,12 +282,17 @@ napi_value TransactionProxy::Initialize(napi_env env, napi_callback_info info) return nullptr; } auto finalize = [](napi_env env, void *data, void *hint) { + if (data == nullptr) { + LOG_ERROR("data is nullptr."); + return; + } auto tid = JSDFManager::GetInstance().GetFreedTid(data); if (tid != 0) { LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); } if (data != hint) { - LOG_ERROR("Memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, uintptr_t(data), uintptr_t(hint)); + LOG_ERROR("Memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, + uintptr_t(data) & LOWER_24_BITS_MASK, uintptr_t(hint) & LOWER_24_BITS_MASK); return; } TransactionProxy *proxy = reinterpret_cast(data); @@ -596,7 +601,7 @@ napi_value TransactionProxy::BatchInsertWithConflictResolution(napi_env env, nap }; auto exec = [context]() -> int { CHECK_RETURN_ERR(context->transaction_ != nullptr); - auto [code, insertRows] = context->StealTransaction()->BatchInsertWithConflictResolution( + auto [code, insertRows] = context->StealTransaction()->BatchInsert( context->tableName, context->valuesBuckets, context->conflictResolution); context->insertRows = insertRows; return code; @@ -647,7 +652,7 @@ napi_value TransactionProxy::Query(napi_env env, napi_callback_info info) return (context->resultSet != nullptr) ? E_OK : E_ALREADY_CLOSED; }; auto output = [context](napi_env env, napi_value &result) { - result = ResultSetProxy::NewInstance(env, context->resultSet); + result = ResultSetProxy::NewInstance(env, std::move(context->resultSet)); CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_ERROR)); }; context->SetAction(env, info, input, exec, output); @@ -693,7 +698,7 @@ napi_value TransactionProxy::QuerySql(napi_env env, napi_callback_info info) return (context->resultSet != nullptr) ? E_OK : E_ALREADY_CLOSED; }; auto output = [context](napi_env env, napi_value &result) { - result = ResultSetProxy::NewInstance(env, context->resultSet); + result = ResultSetProxy::NewInstance(env, std::move(context->resultSet)); CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_ERROR)); }; context->SetAction(env, info, input, exec, output); diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_uv_queue.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_uv_queue.cpp deleted file mode 100644 index adc23eb4c57e237bcabdd7b94b08d2567fdb7919..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_uv_queue.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2022 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 "NapiUvQueue" -#include "napi_uv_queue.h" - -#include "logger.h" -#include "uv.h" - -namespace OHOS::RelationalStoreJsKit { -using namespace OHOS::Rdb; - -NapiUvQueue::NapiUvQueue(napi_env env, napi_value callback) : env_(env) -{ - napi_create_reference(env, callback, 1, &callback_); - napi_get_uv_event_loop(env, &loop_); -} - -NapiUvQueue::~NapiUvQueue() -{ - napi_delete_reference(env_, callback_); -} - -bool NapiUvQueue::operator==(napi_value value) -{ - napi_value callback = nullptr; - napi_get_reference_value(env_, callback_, &callback); - - bool isEquals = false; - napi_strict_equals(env_, value, callback, &isEquals); - return isEquals; -} - -void NapiUvQueue::CallFunction(NapiArgsGenerator genArgs) -{ - uv_work_t *work = new (std::nothrow) uv_work_t; - if (work == nullptr) { - return; - } - work->data = this; - this->args = std::move(genArgs); - - int ret = uv_queue_work(loop_, work, [](uv_work_t* work) {}, [](uv_work_t* work, int st) { - auto queue = static_cast(work->data); - napi_handle_scope scope = nullptr; - if (queue == nullptr) { - return; - } - napi_open_handle_scope(queue->env_, &scope); - if (scope == nullptr) { - delete work; - return; - } - int argc = 0; - napi_value argv[MAX_CALLBACK_ARG_NUM] = { nullptr }; - if (queue->args) { - queue->args(queue->env_, argc, argv); - } - - napi_value callback = nullptr; - napi_get_reference_value(queue->env_, queue->callback_, &callback); - napi_value global = nullptr; - napi_get_global(queue->env_, &global); - napi_value result = nullptr; - napi_status status = napi_call_function(queue->env_, global, callback, argc, argv, &result); - if (status != napi_ok) { - LOG_ERROR("napi_call_function failed, status=%{public}d", status); - } - napi_close_handle_scope(queue->env_, scope); - delete work; - }); - if (ret < 0) { - LOG_ERROR("uv_queue_work failed, errCode:%{public}d", ret); - delete static_cast(work->data); - delete work; - } -} -} // namespace OHOS::RelationalStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/sendablerelationalstore/BUILD.gn b/relational_store/frameworks/js/napi/sendablerelationalstore/BUILD.gn index 9742fe000886c4ada1ad41e7813316c36d3d4989..2150a164c398c9b5f2a00c7758d2a89e9d40b30b 100644 --- a/relational_store/frameworks/js/napi/sendablerelationalstore/BUILD.gn +++ b/relational_store/frameworks/js/napi/sendablerelationalstore/BUILD.gn @@ -51,6 +51,7 @@ ohos_shared_library("sendablerelationalstore") { "bounds_checking_function:libsec_shared", "hilog:libhilog", "hitrace:hitrace_meter", + "ipc:ipc_single", "napi:ace_napi", ] diff --git a/relational_store/frameworks/js/napi/sendablerelationalstore/src/napi_rdb_store_convert_utils.cpp b/relational_store/frameworks/js/napi/sendablerelationalstore/src/napi_rdb_store_convert_utils.cpp index 8565f0ce9c41c3936a822b5a288408912c8db11a..0c9937216d2353897ff7b81952ab9646cadd096a 100644 --- a/relational_store/frameworks/js/napi/sendablerelationalstore/src/napi_rdb_store_convert_utils.cpp +++ b/relational_store/frameworks/js/napi/sendablerelationalstore/src/napi_rdb_store_convert_utils.cpp @@ -142,6 +142,69 @@ napi_value ToSendableAsset(napi_env env, napi_callback_info info) return Convert2Sendable(env, args[0]); } +napi_value FromSendableValues(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = { nullptr }; + napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + RDB_NAPI_ASSERT(env, status == napi_ok && argc == 1, std::make_shared("1")); + + bool isArray = false; + status = napi_is_array(env, args[0], &isArray); + RDB_NAPI_ASSERT(env, status == napi_ok && isArray, + std::make_shared("values is invalid" + std::to_string(status))); + + uint32_t length = 0; + status = napi_get_array_length(env, args[0], &length); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("napi_get_array_length failed.")); + napi_value outArray; + status = napi_create_array(env, &outArray); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("napi_create_array failed.")); + for (uint32_t i = 0; i < length; ++i) { + napi_value item = nullptr; + status = napi_get_element(env, args[0], i, &item); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("napi_get_element failed.")); + napi_value jsvalue = Convert2JSValue(env, item); + status = napi_set_element(env, outArray, i, jsvalue); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("napi_set_element failed.")); + } + return outArray; +} + +napi_value ToSendableValues(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = { nullptr }; + napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + RDB_NAPI_ASSERT(env, status == napi_ok && argc == 1, std::make_shared("1")); + + bool isArray = false; + status = napi_is_array(env, args[0], &isArray); + RDB_NAPI_ASSERT(env, status == napi_ok && isArray, + std::make_shared("values is invalid" + std::to_string(status))); + + uint32_t length = 0; + status = napi_get_array_length(env, args[0], &length); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("napi_get_array_length failed.")); + + napi_value outArray; + status = napi_create_sendable_array(env, &outArray); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("napi_create_sendable_array failed.")); + for (uint32_t i = 0; i < length; ++i) { + napi_value item = nullptr; + status = napi_get_element(env, args[0], i, &item); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("napi_get_element failed.")); + ValueObject object; + status = (napi_status)Convert2Value(env, item, object); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("Convert2Value failed.")); + napi_value sendablevalue = Convert2Sendable(env, object); + + status = napi_set_element(env, outArray, i, sendablevalue); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("napi_set_element failed.")); + } + return outArray; +} + napi_value InitRdbStoreUtils(napi_env env, napi_value exports) { napi_property_descriptor properties[] = { @@ -149,6 +212,8 @@ napi_value InitRdbStoreUtils(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("toSendableValuesBucket", ToSendableValuesBucket), DECLARE_NAPI_FUNCTION("fromSendableAsset", FromSendableAsset), DECLARE_NAPI_FUNCTION("toSendableAsset", ToSendableAsset), + DECLARE_NAPI_FUNCTION("fromSendableValues", FromSendableValues), + DECLARE_NAPI_FUNCTION("toSendableValues", ToSendableValues), }; NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(*properties), properties)); return exports; diff --git a/relational_store/frameworks/native/appdatafwk/src/serializable.cpp b/relational_store/frameworks/native/appdatafwk/src/serializable.cpp index 2a90ec7d9604d037ee8f5571c82102a630efc156..af42f1d6e3df9525ca9ee19fa003ebb843aab2ae 100644 --- a/relational_store/frameworks/native/appdatafwk/src/serializable.cpp +++ b/relational_store/frameworks/native/appdatafwk/src/serializable.cpp @@ -141,6 +141,16 @@ bool Serializable::GetValue(const json &node, const std::string &name, Serializa return value.Unmarshal(subNode); } +bool Serializable::GetValue(const json &node, const std::string &name, double &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_number_float()) { + return false; + } + subNode.get_to(value); + return true; +} + bool Serializable::SetValue(json &node, const std::string &value) { node = value; @@ -188,6 +198,12 @@ bool Serializable::SetValue(json &node, const Serializable &value) return value.Marshal(node); } +bool Serializable::SetValue(json &node, const double &value) +{ + node = value; + return true; +} + const Serializable::json &Serializable::GetSubNode(const json &node, const std::string &name) { static const json jsonNull = json::value_t::null; diff --git a/relational_store/frameworks/native/appdatafwk/src/shared_block.cpp b/relational_store/frameworks/native/appdatafwk/src/shared_block.cpp index 18cdfc1841f1b80c43bcae0eb0a3901f5c533446..8e76b974f87d572d9d610ad9a5a844d99c855530 100644 --- a/relational_store/frameworks/native/appdatafwk/src/shared_block.cpp +++ b/relational_store/frameworks/native/appdatafwk/src/shared_block.cpp @@ -155,7 +155,10 @@ int SharedBlock::Clear() mHeader->startPos_ = 0; mHeader->lastPos_ = 0; mHeader->blockPos_ = 0; - memset_s(mHeader->groupOffset, sizeof(mHeader->groupOffset), 0, sizeof(mHeader->groupOffset)); + auto result = memset_s(mHeader->groupOffset, sizeof(mHeader->groupOffset), 0, sizeof(mHeader->groupOffset)); + if (result != EOK) { + LOG_ERROR("memset_s failed, error code is %{public}d", result); + } mHeader->groupOffset[0] = sizeof(SharedBlockHeader); return SHARED_BLOCK_OK; } @@ -303,7 +306,7 @@ int SharedBlock::PutBigInt(uint32_t row, uint32_t column, const void *value, siz int SharedBlock::PutBlobOrString(uint32_t row, uint32_t column, const void *value, size_t size, int32_t type) { - if (UNLIKELY(row >= mHeader->rowNums || column >= mHeader->columnNums)) { + if (UNLIKELY(row >= mHeader->rowNums || column >= mHeader->columnNums || value == nullptr)) { LOG_ERROR("Failed to read row %{public}" PRIu32 ", column %{public}" PRIu32 " from a SharedBlock" " which has %{public}" PRIu32 " rows, %{public}" PRIu32 " columns.", row, column, mHeader->rowNums, mHeader->columnNums); @@ -391,7 +394,7 @@ int SharedBlock::PutNull(uint32_t row, uint32_t column) size_t SharedBlock::SetRawData(const void *rawData, size_t size) { - if (UNLIKELY(size <= 0)) { + if (UNLIKELY(size <= 0 || rawData == nullptr)) { LOG_ERROR("SharedBlock rawData is less than or equal to 0M"); return SHARED_BLOCK_INVALID_OPERATION; } @@ -409,6 +412,9 @@ size_t SharedBlock::SetRawData(const void *rawData, size_t size) std::string SharedBlock::CellUnit::GetString(SharedBlock *block) const { + if (UNLIKELY(block == nullptr)) { + return ""; + } auto value = static_cast(block->OffsetToPtr(cell.stringOrBlobValue.offset, cell.stringOrBlobValue.size)); if (cell.stringOrBlobValue.size < 1 || value == nullptr) { return ""; @@ -418,6 +424,9 @@ std::string SharedBlock::CellUnit::GetString(SharedBlock *block) const std::vector SharedBlock::CellUnit::GetBlob(SharedBlock *block) const { + if (UNLIKELY(block == nullptr)) { + return {}; + } auto value = reinterpret_cast(block->OffsetToPtr(cell.stringOrBlobValue.offset, cell.stringOrBlobValue.size)); return std::vector(value, value + cell.stringOrBlobValue.size); @@ -425,6 +434,9 @@ std::vector SharedBlock::CellUnit::GetBlob(SharedBlock *block) const const uint8_t *SharedBlock::CellUnit::GetRawData(SharedBlock *block) const { + if (UNLIKELY(block == nullptr)) { + return nullptr; + } return static_cast(block->OffsetToPtr(cell.stringOrBlobValue.offset, cell.stringOrBlobValue.size)); } } // namespace AppDataFwk diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_notifier_stub.h b/relational_store/frameworks/native/cloud_data/include/cloud_notifier_stub.h new file mode 100644 index 0000000000000000000000000000000000000000..fecfcf0119b7bfdffc4d094ee05cacccabd39bdb --- /dev/null +++ b/relational_store/frameworks/native/cloud_data/include/cloud_notifier_stub.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025 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_CLOUD_CLOUD_NOTIFIER_STUB_H +#define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_NOTIFIER_STUB_H + +#include "cloud_notifier.h" +#include "iremote_broker.h" +#include "iremote_stub.h" + +namespace OHOS::CloudData { +using namespace DistributedRdb; +using NotifierCode = DistributedRdb::RelationalStore::ICloudNotifierInterfaceCode; + +class CloudNotifierStubBroker : public ICloudNotifier, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.CloudData.ICloudNotifier"); +}; + +class CloudNotifierStub : public IRemoteStub { +public: + using SyncCompleteHandler = std::function; + explicit CloudNotifierStub(const SyncCompleteHandler &syncComplete); + virtual ~CloudNotifierStub() noexcept; + + int OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) override; + int32_t OnComplete(uint32_t seqNum, Details &&result) override; + +private: + int32_t OnCompleteInner(MessageParcel& data, MessageParcel& reply); + bool CheckInterfaceToken(MessageParcel& data); + + using RequestHandle = int32_t (CloudNotifierStub::*)(MessageParcel&, MessageParcel&); + static constexpr RequestHandle HANDLES[static_cast(NotifierCode::CLOUD_NOTIFIER_CMD_MAX)] = { + [static_cast(NotifierCode::CLOUD_NOTIFIER_CMD_SYNC_COMPLETE)] = &CloudNotifierStub::OnCompleteInner, + }; + + SyncCompleteHandler completeNotifier_; +}; +} // namespace OHOS::CloudData +#endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_NOTIFIER_STUB_H diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h index 780c5dd2b1cb1a4b53a7659f5be62cd55dff8afd..9db4d1f9f32227f7f357d28e0cd4e6017d6dd6f5 100644 --- a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h +++ b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h @@ -16,11 +16,14 @@ #ifndef OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_PROXY_H #define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_PROXY_H +#include "concurrent_map.h" #include "icloud_service.h" #include "iremote_object.h" #include "iremote_proxy.h" +#include "cloud_notifier_stub.h" namespace OHOS::CloudData { +using namespace DistributedRdb; class CloudServiceProxy : public IRemoteProxy { public: explicit CloudServiceProxy(const sptr &object); @@ -52,9 +55,17 @@ public: int32_t SetCloudStrategy(Strategy strategy, const std::vector &values) override; std::pair QueryLastSyncInfo( const std::string &id, const std::string &bundleName, const std::string &storeId) override; + int32_t CloudSync(const std::string &bundleName, const std::string &storeId, const Option &option, + const AsyncDetail &async) override; + int32_t InitNotifier(sptr notifier) override; + int32_t InitNotifier(); private: + int32_t DoAsync(const std::string &bundleName, const std::string &storeId, Option option); + void OnSyncComplete(uint32_t seqNum, Details &&result); sptr remote_; + sptr notifier_; + ConcurrentMap syncCallbacks_; }; } // namespace OHOS::CloudData #endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_PROXY_H \ No newline at end of file diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h b/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h index e0ab11dd7b760b6791054e9723b9592ebcc8835d..b524724c4c6dd6894dfc6378f83cc2c9b0e9cd9b 100644 --- a/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h +++ b/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h @@ -16,6 +16,7 @@ #ifndef OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_UTIL_H #define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_UTIL_H #include "cloud_types.h" +#include "cloud_service.h" #include "common_types.h" #include "itypes_util.h" #include "values_bucket.h" @@ -33,6 +34,7 @@ using StatisticInfo = OHOS::CloudData::StatisticInfo; using CommonAsset = CommonType::Asset; using Strategy = OHOS::CloudData::Strategy; using CloudSyncInfo = OHOS::CloudData::CloudSyncInfo; +using Option = OHOS::CloudData::CloudService::Option; template<> bool Marshalling(const Participant &input, MessageParcel &data); @@ -85,5 +87,10 @@ template<> bool Marshalling(const CloudSyncInfo &input, MessageParcel &data); template<> bool Unmarshalling(CloudSyncInfo &output, MessageParcel &data); + +template<> +bool Marshalling(const Option &input, MessageParcel &data); +template<> +bool Unmarshalling(Option &output, MessageParcel &data); } // namespace OHOS::ITypesUtil #endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_UTIL_H \ No newline at end of file diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp index 36ec5bc4c4dc6fb14bc0d221aa057da1ed8e8ad9..cd8c42edf6d1e405cb0166f83f7758cabea1bb43 100644 --- a/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp +++ b/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 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 @@ -32,7 +32,6 @@ public: ~DataMgrService() = default; sptr GetFeatureInterface(const std::string &name) override; }; - class CloudDeath : public IRemoteObject::DeathRecipient { public: explicit CloudDeath(std::function action) : action_(std::move(action)) {}; @@ -92,6 +91,10 @@ std::pair> CloudManager::GetCloudService( if (proxy == nullptr) { return std::make_pair(CloudService::Status::FEATURE_UNAVAILABLE, nullptr); } + if (proxy->InitNotifier() != CloudService::Status::SUCCESS) { + LOG_ERROR("Init notifier failed."); + return { CloudService::Status::ERROR, nullptr }; + } cloudService_ = std::shared_ptr(proxy.GetRefPtr(), [holder = proxy](const auto *) {}); if (cloudService_ == nullptr) { diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_notifier_stub.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_notifier_stub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e897f5e4742438faacd23e9263f4db77b721704a --- /dev/null +++ b/relational_store/frameworks/native/cloud_data/src/cloud_notifier_stub.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2025 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 "CloudNotifierStub" + +#include "cloud_notifier_stub.h" + +#include + +#include "cloud_service.h" +#include "itypes_util.h" +#include "logger.h" + +namespace OHOS::CloudData { +using namespace Rdb; +CloudNotifierStub::CloudNotifierStub(const SyncCompleteHandler &completeNotifier) + : IRemoteStub(), completeNotifier_(completeNotifier) +{ +} + +CloudNotifierStub::~CloudNotifierStub() noexcept +{ +} + +bool CloudNotifierStub::CheckInterfaceToken(MessageParcel &data) +{ + auto localDescriptor = GetDescriptor(); + auto remoteDescriptor = data.ReadInterfaceToken(); + if (remoteDescriptor != localDescriptor) { + LOG_ERROR("interface token is not equal."); + return false; + } + return true; +} + +int CloudNotifierStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + LOG_DEBUG("code:%{public}u, callingPid:%{public}d", code, IPCSkeleton::GetCallingPid()); + if (!CheckInterfaceToken(data)) { + return CloudService::ERROR; + } + + if (code < static_cast(NotifierCode::CLOUD_NOTIFIER_CMD_MAX)) { + return (this->*HANDLES[code])(data, reply); + } + + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} + +int32_t CloudNotifierStub::OnCompleteInner(MessageParcel &data, MessageParcel &reply) +{ + uint32_t seqNum = 0; + Details result; + if (!ITypesUtil::Unmarshal(data, seqNum, result)) { + LOG_ERROR("read sync result failed."); + return CloudService::ERROR; + } + return OnComplete(seqNum, std::move(result)); +} + +int32_t CloudNotifierStub::OnComplete(uint32_t seqNum, Details &&result) +{ + if (completeNotifier_) { + completeNotifier_(seqNum, std::move(result)); + } + return CloudService::SUCCESS; +} +} // namespace OHOS::CloudData diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp index 51d4c2e6e72c124e8cf5a377fd76d86650f1892a..95985dcef58ea522f3d8f59f447a5b763c073730 100644 --- a/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp +++ b/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp @@ -271,4 +271,75 @@ std::pair CloudServiceProxy::QueryLastSyncInfo( ITypesUtil::Unmarshal(reply, results); return { status, results }; } + +int32_t CloudServiceProxy::DoAsync(const std::string &bundleName, const std::string &storeId, Option option) +{ + MessageParcel reply; + int32_t status = IPC_SEND(TRANS_CLOUD_SYNC, reply, bundleName, storeId, option); + if (status != SUCCESS) { + LOG_ERROR( + "Status:0x%{public}x bundleName:%{public}s storeId:%{public}.3s syncMode:%{public}d seqNum:%{public}u", + status, bundleName.c_str(), storeId.c_str(), option.syncMode, option.seqNum); + } + return status; +} + +int32_t CloudServiceProxy::InitNotifier(sptr notifier) +{ + MessageParcel reply; + int32_t status = IPC_SEND(TRANS_INIT_NOTIFIER, reply, notifier); + if (status != SUCCESS) { + LOG_ERROR("Status:0x%{public}x", status); + } + return status; +} + +int32_t CloudServiceProxy::InitNotifier() +{ + notifier_ = new (std::nothrow) CloudNotifierStub([this](uint32_t seqNum, Details &&result) { + OnSyncComplete(seqNum, std::move(result)); + }); + if (notifier_ == nullptr) { + LOG_ERROR("create notifier failed"); + return ERROR; + } + auto status = InitNotifier(notifier_->AsObject()); + if (status != SUCCESS) { + notifier_ = nullptr; + LOG_ERROR("init notifier failed."); + return status; + } + return SUCCESS; +} + +void CloudServiceProxy::OnSyncComplete(uint32_t seqNum, Details &&result) +{ + syncCallbacks_.ComputeIfPresent(seqNum, [&result](const auto &key, const AsyncDetail &callback) { + auto finished = result.empty() || (result.begin()->second.progress == SYNC_FINISH); + if (callback != nullptr) { + callback(std::move(result)); + } + return !finished; + }); +} + +int32_t CloudServiceProxy::CloudSync(const std::string &bundleName, const std::string &storeId, + const Option &option, const AsyncDetail &async) +{ + LOG_INFO("cloud sync start, bundleName = %{public}s, seqNum = %{public}u", bundleName.c_str(), option.seqNum); + if (bundleName.empty() || storeId.empty() || option.syncMode < DistributedRdb::TIME_FIRST || + option.syncMode > DistributedRdb::CLOUD_FIRST || async == nullptr) { + LOG_ERROR("invalid args, bundleName = %{public}s", bundleName.c_str()); + return INVALID_ARGUMENT; + } + if (!syncCallbacks_.Insert(option.seqNum, async)) { + LOG_ERROR("register progress failed, bundleName = %{public}s", bundleName.c_str()); + return ERROR; + } + auto status = DoAsync(bundleName, storeId, option); + if (status != SUCCESS) { + syncCallbacks_.Erase(option.seqNum); + } + return status; +} } // namespace OHOS::CloudData diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp index abf93c05f96a2532f5a44e3a4913f8f74302f063..70859e24805e2b352fc5c73d3e4c88e556745401 100644 --- a/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp +++ b/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp @@ -152,4 +152,15 @@ bool Unmarshalling(CloudSyncInfo &output, MessageParcel &data) { return Unmarshal(data, output.startTime, output.finishTime, output.code, output.syncStatus); } + +template<> +bool Marshalling(const Option &input, MessageParcel &data) +{ + return Marshal(data, input.syncMode, input.seqNum); +} +template<> +bool Unmarshalling(Option &output, MessageParcel &data) +{ + return Unmarshal(data, output.syncMode, output.seqNum); +} } // namespace OHOS::ITypesUtil \ No newline at end of file diff --git a/relational_store/frameworks/native/dfx/include/rdb_dfx_errno.h b/relational_store/frameworks/native/dfx/include/rdb_dfx_errno.h index eec0d0cea5d7758054c685c0711f5bed4bf14d5b..f8028dd43f2f4262fd3c2acd8ee46c39e9f53f4b 100644 --- a/relational_store/frameworks/native/dfx/include/rdb_dfx_errno.h +++ b/relational_store/frameworks/native/dfx/include/rdb_dfx_errno.h @@ -68,6 +68,58 @@ static constexpr int E_DFX_SET_JOURNAL_FAIL = (E_DFX_BASE + 0x8); */ static constexpr int E_DFX_DUMP_INFO = (E_DFX_BASE + 0x9); +/** +* @brief The base code of the exception dfx huks error code, base value is 0x1A28100. +*/ +constexpr int E_DFX_HUKS_BASE = E_DFX_BASE + 0x100; + +/** + * @brief The root key of the encrypted database is faulty. + */ +static constexpr int E_ROOT_KEY_FAULT = (E_DFX_HUKS_BASE + 0x4e); + +/** + * @brief The root key of the encrypted database cannot be loaded. + */ +static constexpr int E_ROOT_KEY_NOT_LOAD = (E_DFX_HUKS_BASE + 0x4f); + +/** + * @brief The working key of the encrypted database is faulty. + */ +static constexpr int E_WORK_KEY_FAIL = (E_DFX_HUKS_BASE + 0x50); + +/** + * @brief Failed to encrypt the working key. + */ +static constexpr int E_WORK_KEY_ENCRYPT_FAIL = (E_DFX_HUKS_BASE + 0x51); + +/** + * @brief Failed to decrypt the working key. + */ +static constexpr int E_WORK_KEY_DECRYPT_FAIL = (E_DFX_HUKS_BASE + 0x52); + +/** + * @brief Failed to open the sqlite database using the working key. + */ +static constexpr int E_SET_ENCRYPT_FAIL = (E_DFX_HUKS_BASE + 0x53); + +/** + * @brief Failed to open the sqlite database using the working new key. + */ +static constexpr int E_SET_NEW_ENCRYPT_FAIL = (E_DFX_HUKS_BASE + 0x54); + +/** + * @brief Failed to open the sqlite database using the working service key. + */ +static constexpr int E_SET_SERVICE_ENCRYPT_FAIL = (E_DFX_HUKS_BASE + 0x55); + +/** + * @brief Only use for dfx, print dump info. + */ +static constexpr int E_DFX_HUKS_GEN_RANDOM_FAIL = (E_DFX_HUKS_BASE + 0x56); + +static constexpr int E_DFX_LENGTH_PARAM_CHECK_FAIL = (E_DFX_HUKS_BASE + 0x57); + } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/dfx/include/rdb_fault_hiview_reporter.h b/relational_store/frameworks/native/dfx/include/rdb_fault_hiview_reporter.h index 96eb7713266b416eca1fc1acefa80d1a6259772d..50a8d9505c6ee5ca12cef8822caecf01e16fadc2 100644 --- a/relational_store/frameworks/native/dfx/include/rdb_fault_hiview_reporter.h +++ b/relational_store/frameworks/native/dfx/include/rdb_fault_hiview_reporter.h @@ -63,7 +63,7 @@ static constexpr const char *FT_SQLITE = "SQLITE"; static constexpr const char *BUNDLE_NAME_COMMON = "common"; -class API_EXPORT RdbFaultEvent { +class RdbFaultEvent { public: RdbFaultEvent(const std::string &faultType, int32_t errorCode, const std::string &bundleName, const std::string &custLog); @@ -73,6 +73,7 @@ public: int32_t GetErrCode() const { return errorCode_; } std::string GetLogInfo() const { return custLog_; }; virtual void Report() const; + virtual ~RdbFaultEvent() = default; protected: void SetBundleName(const std::string &name) { bundleName_ = name; }; @@ -99,13 +100,7 @@ private: bool printDbInfo_; }; -class API_EXPORT RdbEmptyBlobEvent : public RdbFaultEvent { -public: - RdbEmptyBlobEvent(const std::string &bundleName); - virtual void Report() const override; -}; - -class API_EXPORT RdbFaultHiViewReporter { +class RdbFaultHiViewReporter { public: using Collector = int32_t (*)(const RdbStoreConfig &config, std::map&, DistributedRdb::RdbDfxInfo&); @@ -118,6 +113,8 @@ public: static void ReportRestore(const RdbCorruptedEvent &eventInfo, bool repair = true); static bool IsReportCorruptedFault(const std::string &dbPath); static std::string GetBundleName(const std::string &bundleName, const std::string &storeName); + static void ReportRAGFault(const std::string &errMsg, const std::string &functionName, + const std::string &bundleName, const int faultType, const int errCode); private: static void Update(std::map &localInfos, const std::map &infos); diff --git a/relational_store/frameworks/native/dfx/src/rdb_fault_hiview_reporter.cpp b/relational_store/frameworks/native/dfx/src/rdb_fault_hiview_reporter.cpp index e561d799f9415cf55c45260d48fe89748ba2c9f3..1706ea091fec0773cbcf97529d3c6f352b5cf092 100644 --- a/relational_store/frameworks/native/dfx/src/rdb_fault_hiview_reporter.cpp +++ b/relational_store/frameworks/native/dfx/src/rdb_fault_hiview_reporter.cpp @@ -21,29 +21,27 @@ #include #include +#include #include #include #include -#include -#include "accesstoken_kit.h" #include "connection.h" #include "hisysevent_c.h" -#include "ipc_skeleton.h" #include "logger.h" #include "rdb_errno.h" +#include "rdb_time_utils.h" #include "sqlite_global_config.h" #include "sqlite_utils.h" -#include "rdb_time_utils.h" namespace OHOS::NativeRdb { using namespace OHOS::Rdb; -using namespace Security::AccessToken; static constexpr const char *CORRUPTED_EVENT = "DATABASE_CORRUPTED"; static constexpr const char *FAULT_EVENT = "DISTRIBUTED_DATA_RDB_FAULT"; static constexpr const char *DISTRIBUTED_DATAMGR = "DISTDATAMGR"; static constexpr const char *DB_CORRUPTED_POSTFIX = ".corruptedflg"; static constexpr int MAX_FAULT_TIMES = 1; +static constexpr const char *RAG_FAULT_EVENT_NAME = "ARKDATA_RAG_FRAMEWORK_FAULT"; RdbFaultHiViewReporter::Collector RdbFaultHiViewReporter::collector_ = nullptr; RdbFaultCode RdbFaultHiViewReporter::faultCounters_[] = { @@ -52,19 +50,12 @@ RdbFaultCode RdbFaultHiViewReporter::faultCounters_[] = { { E_SQLITE_CORRUPT, 0 }, { E_SQLITE_PERM, 0 }, { E_SQLITE_BUSY, 0 }, + { E_SQLITE_LOCKED, 0 }, { E_SQLITE_NOMEM, 0 }, { E_SQLITE_IOERR, 0 }, { E_SQLITE_CANTOPEN, 0 }, { E_SQLITE_CONSTRAINT, 0 }, { E_SQLITE_NOT_DB, 0 }, - { E_ROOT_KEY_FAULT, 0 }, - { E_ROOT_KEY_NOT_LOAD, 0 }, - { E_WORK_KEY_FAIL, 0 }, - { E_WORK_KEY_ENCRYPT_FAIL, 0 }, - { E_WORK_KEY_DECRYPT_FAIL, 0 }, - { E_SET_ENCRYPT_FAIL, 0 }, - { E_SET_NEW_ENCRYPT_FAIL, 0 }, - { E_SET_SERVICE_ENCRYPT_FAIL, 0 }, { E_CHECK_POINT_FAIL, 0 }, { E_SQLITE_META_RECOVERED, 0 }, { E_DFX_IS_NOT_CREATE, 0 }, @@ -76,8 +67,29 @@ RdbFaultCode RdbFaultHiViewReporter::faultCounters_[] = { { E_DFX_GET_JOURNAL_FAIL, 0 }, { E_DFX_SET_JOURNAL_FAIL, 0 }, { E_DFX_DUMP_INFO, 0 }, + { E_ROOT_KEY_FAULT, 0 }, + { E_ROOT_KEY_NOT_LOAD, 0 }, + { E_WORK_KEY_FAIL, 0 }, + { E_WORK_KEY_ENCRYPT_FAIL, 0 }, + { E_WORK_KEY_DECRYPT_FAIL, 0 }, + { E_SET_ENCRYPT_FAIL, 0 }, + { E_SET_NEW_ENCRYPT_FAIL, 0 }, + { E_SET_SERVICE_ENCRYPT_FAIL, 0 }, + { E_DFX_HUKS_GEN_RANDOM_FAIL, 0 }, }; +//static constexpr bool IsIncreasing() +//{ +// for (size_t i = 1; i < sizeof(faultCounters_) / sizeof(RdbFaultCode); i++) { +// if (faultCounters_[i].nativeCode <= faultCounters_[i - 1].nativeCode) { +// return false; +// } +// } +// return true; +//} +//// JS_ERROR_CODE_MSGS must ensure increment +//static_assert(IsIncreasing()); + bool RdbFaultHiViewReporter::memCorruptReportedFlg_ = false; void RdbFaultHiViewReporter::ReportCorruptedOnce(const RdbCorruptedEvent &eventInfo) @@ -134,6 +146,32 @@ void RdbFaultHiViewReporter::ReportCorrupted(const RdbCorruptedEvent &eventInfo) OH_HiSysEvent_Write(DISTRIBUTED_DATAMGR, CORRUPTED_EVENT, HISYSEVENT_FAULT, params, size); } +void RdbFaultHiViewReporter::ReportRAGFault(const std::string &errMsg, const std::string &functionName, + const std::string &bundleName, const int faultType, const int errCode) +{ + std::string appendix = ""; + HiSysEventParam params[] = { + { .name = "FAULT_TYPE", .t = HISYSEVENT_INT32, .v = { .ui32 = static_cast(faultType) }, .arraySize = 0 }, + { .name = "ERROR_CODE", .t = HISYSEVENT_INT32, .v = { .ui32 = static_cast(errCode) }, .arraySize = 0 }, + { .name = "ERROR_MESSAGE", + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(errMsg.c_str()) }, + .arraySize = 0 }, + { .name = "BUNDLE_NAME", + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(bundleName.c_str()) }, + .arraySize = 0 }, + { .name = "FUNCTION_NAME", + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(functionName.c_str()) }, + .arraySize = 0 }, + { .name = "APPENDIX", .t = HISYSEVENT_STRING, .v = { .s = const_cast(appendix.c_str()) }, .arraySize = 0 }, + }; + + OH_HiSysEvent_Write( + DISTRIBUTED_DATAMGR, RAG_FAULT_EVENT_NAME, HISYSEVENT_FAULT, params, sizeof(params) / sizeof(params[0])); +} + bool RdbFaultHiViewReporter::IsReportCorruptedFault(const std::string &dbPath) { if (dbPath.empty() || memCorruptReportedFlg_) { @@ -154,7 +192,7 @@ void RdbFaultHiViewReporter::CreateCorruptedFlag(const std::string &dbPath) return; } std::string flagFilename = dbPath + DB_CORRUPTED_POSTFIX; - int fd = creat(flagFilename.c_str(), S_IRWXU | S_IRWXG); + int fd = creat(flagFilename.c_str(), S_IRUSR | S_IWUSR); if (fd == -1) { LOG_WARN("Creat corrupted flg fail, flgname=%{public}s, errno=%{public}d", SqliteUtils::Anonymous(flagFilename).c_str(), errno); @@ -240,14 +278,6 @@ std::string RdbFaultHiViewReporter::GetBundleName(const std::string &bundleName, if (!bundleName.empty()) { return bundleName; } - auto tokenId = IPCSkeleton::GetCallingTokenID(); - auto tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId); - if ((tokenType == TOKEN_NATIVE) || (tokenType == TOKEN_SHELL)) { - NativeTokenInfo tokenInfo; - if (AccessTokenKit::GetNativeTokenInfo(tokenId, tokenInfo) == 0) { - return tokenInfo.processName; - } - } return SqliteUtils::Anonymous(storeName); } @@ -319,29 +349,6 @@ RdbFaultDbFileEvent::RdbFaultDbFileEvent(const std::string &faultType, int32_t e { } -RdbEmptyBlobEvent::RdbEmptyBlobEvent(const std::string &bundleName) - : RdbFaultEvent(FT_CURD, E_SQLITE_FULL, "", "The input blob is empty") -{ - SetBundleName(bundleName); -} - -void RdbEmptyBlobEvent::Report() const -{ - std::string occurTime = RdbTimeUtils::GetCurSysTimeWithMs(); - std::string bundleName = GetBundleName(); - std::string faultType = GetFaultType(); - std::string appendInfo = GetLogInfo(); - HiSysEventParam params[] = { - { .name = "FAULT_TIME", .t = HISYSEVENT_STRING, .v = { .s = occurTime.data() }, .arraySize = 0 }, - { .name = "FAULT_TYPE", .t = HISYSEVENT_STRING, .v = { .s = faultType.data() }, .arraySize = 0 }, - { .name = "BUNDLE_NAME", .t = HISYSEVENT_STRING, .v = { .s = bundleName.data() }, .arraySize = 0 }, - { .name = "ERROR_CODE", .t = HISYSEVENT_INT32, .v = { .ui32 = E_SQLITE_FULL }, .arraySize = 0 }, - { .name = "APPENDIX", .t = HISYSEVENT_STRING, .v = { .s = appendInfo.data() }, .arraySize = 0 }, - }; - auto size = sizeof(params) / sizeof(params[0]); - OH_HiSysEvent_Write(DISTRIBUTED_DATAMGR, FAULT_EVENT, HISYSEVENT_FAULT, params, size); -} - void RdbFaultDbFileEvent::Report() const { std::string occurTime = RdbTimeUtils::GetCurSysTimeWithMs(); diff --git a/relational_store/frameworks/native/dfx/src/rdb_radar_reporter.cpp b/relational_store/frameworks/native/dfx/src/rdb_radar_reporter.cpp index 8e872841d37618cdd32183f40f1e4fa12b4923d6..acc8a5e045f4b2a21b31faaa2c9dabec1a0511eb 100644 --- a/relational_store/frameworks/native/dfx/src/rdb_radar_reporter.cpp +++ b/relational_store/frameworks/native/dfx/src/rdb_radar_reporter.cpp @@ -15,15 +15,11 @@ #include "rdb_radar_reporter.h" -#include "accesstoken_kit.h" #include "hisysevent_c.h" -#include "ipc_skeleton.h" #include "rdb_errno.h" namespace OHOS::NativeRdb { -using namespace Security::AccessToken; - static constexpr const char *ORG_PKG_VALUE = "distributeddata"; static constexpr const char *EVENT_NAME = "DISTRIBUTED_RDB_BEHAVIOR"; static constexpr const char *UNKNOW = "unknow"; @@ -91,16 +87,7 @@ std::string RdbRadar::GetHostPkgInfo() if (!hostPkg_.empty()) { return hostPkg_; } - auto tokenId = IPCSkeleton::GetCallingTokenID(); - auto tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId); - if ((tokenType == TOKEN_NATIVE) || (tokenType == TOKEN_SHELL)) { - NativeTokenInfo tokenInfo; - if (AccessTokenKit::GetNativeTokenInfo(tokenId, tokenInfo) == 0) { - hostPkg_ = tokenInfo.processName; - } - } else { - hostPkg_ = bundleName_; - } + hostPkg_ = bundleName_; return hostPkg_; } } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/dfx/src/rdb_stat_reporter.cpp b/relational_store/frameworks/native/dfx/src/rdb_stat_reporter.cpp index c56e3757f6c7035abeb1e3d9a3d6cb08d0107d5d..9e7ab49170fa012e677a32d0de6c5cd7a4e538e0 100644 --- a/relational_store/frameworks/native/dfx/src/rdb_stat_reporter.cpp +++ b/relational_store/frameworks/native/dfx/src/rdb_stat_reporter.cpp @@ -58,10 +58,12 @@ RdbStatReporter::~RdbStatReporter() auto loadedReportTime = reportTime_.load(); auto reportInterval = std::chrono::duration_cast(endTime - loadedReportTime).count(); statEvent_.costTime = GetTimeType(static_cast(duration)); - if (statEvent_.costTime > TIME_LEVEL_NONE && reportInterval >= WAIT_TIME) { + if (statEvent_.costTime > TIME_LEVEL_NONE && + (loadedReportTime == std::chrono::steady_clock::time_point() || reportInterval >= WAIT_TIME)) { auto pool = TaskExecutor::GetInstance().GetExecutor(); if (pool == nullptr) { LOG_WARN("task pool err when RdbStatReporter"); + return; } pool->Execute([report = std::move(reportFunc_), statEvent = std::move(statEvent_)]() { (*report)(statEvent); diff --git a/relational_store/frameworks/native/dlopen_rdb/BUILD.gn b/relational_store/frameworks/native/dlopen_rdb/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..0497be36e92f65418cb3f646635d568a0bf9bf1b --- /dev/null +++ b/relational_store/frameworks/native/dlopen_rdb/BUILD.gn @@ -0,0 +1,52 @@ +# Copyright (c) 2025 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("//build/ohos/ace/ace.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +group("build_module") { + deps = [] + if (relational_store_rdb_support_icu) { + deps += [ ":dlopen_rdb_demo" ] + } +} + +ohos_shared_library("dlopen_rdb_demo") { + branch_protector_ret = "pac_ret" + sanitize = { + boundary_sanitize = true + ubsan = true + cfi = true + cfi_cross_dso = true + debug = false + } + + ldflags = [ "-Wl,--exclude-libs,ALL" ] + cflags_cc = [ "-fvisibility=hidden" ] + + include_dirs = [ + "${relational_store_common_path}/include", + "${relational_store_innerapi_path}/rdb/include", + ] + + sources = [ "${relational_store_native_path}/dlopen_rdb/dlopen_rdb.cpp" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "relational_store:native_rdb", + ] + subsystem_name = "distributeddatamgr" + part_name = "relational_store" +} diff --git a/relational_store/frameworks/native/dlopen_rdb/dlopen_rdb.cpp b/relational_store/frameworks/native/dlopen_rdb/dlopen_rdb.cpp new file mode 100644 index 0000000000000000000000000000000000000000..714d090fb494b06ca1b2ec69d926cfb91178fdd6 --- /dev/null +++ b/relational_store/frameworks/native/dlopen_rdb/dlopen_rdb.cpp @@ -0,0 +1,177 @@ +/* +* Copyright (c) 2025 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 "Dlopen_RDB" + +#include +#include + +#include "logger.h" +#include "rdb_helper.h" +#include "rdb_visibility.h" + +using namespace OHOS::DistributedRdb; +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; +API_EXPORT int32_t Demo(const std::string &dbPath) asm("Demo"); +class RdbHelperTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string CREATE_TABLE_TEST; +}; + +const std::string RdbHelperTestOpenCallback::CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, " + "blobType BLOB)"; + +int RdbHelperTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_TEST); +} + +int RdbHelperTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} +class DemoRdbStoreObserver : public RdbStoreObserver { +public: + virtual ~DemoRdbStoreObserver(){}; + void OnChange(const std::vector &devices) override + { + LOG_INFO("OnChange devices"); + } + void OnChange(const Origin &origin, const PrimaryFields &fields, ChangeInfo &&changeInfo) override + { + LOG_INFO("OnChange store:%{public}s", origin.store.c_str()); + } + void OnChange() override + { + LOG_INFO("OnChange null"); + } +}; + +class Subscriber { +public: + Subscriber(std::shared_ptr store) : rdbstore_(store) + { + if (rdbstore_ == nullptr) { + return; + } + SubscribeOption option; + option.mode = SubscribeMode::LOCAL; + rdbstore_->Subscribe(option, localObs_); + + option.mode = SubscribeMode::LOCAL_SHARED; + option.event = "demoTest"; + rdbstore_->Subscribe(option, localSharedObs_); + + option.mode = SubscribeMode::LOCAL_DETAIL; + rdbstore_->SubscribeObserver(option, localDetailObs_); + } + ~Subscriber() + { + if (rdbstore_ == nullptr) { + return; + } + SubscribeOption option; + option.mode = SubscribeMode::LOCAL; + rdbstore_->UnSubscribe(option, localObs_); + + option.mode = SubscribeMode::LOCAL_SHARED; + option.event = "demoTest"; + rdbstore_->UnSubscribe(option, localSharedObs_); + + option.mode = SubscribeMode::LOCAL_DETAIL; + rdbstore_->UnsubscribeObserver(option, localDetailObs_); + } + +private: + std::shared_ptr rdbstore_; + std::shared_ptr localObs_ = std::make_shared(); + std::shared_ptr localSharedObs_ = std::make_shared(); + std::shared_ptr localDetailObs_ = std::make_shared(); +}; + +int32_t Crud(std::shared_ptr rdbStore) +{ + int64_t id; + ValuesBucket values; + int deletedRows; + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = rdbStore->Insert(id, "test", values); + if (ret != E_OK) { + return ret; + } + values.PutString("name", "update"); + values.PutInt("age", 20); + int changedRows = -1; + AbsRdbPredicates predicates("test"); + ret = rdbStore->Update(changedRows, values, predicates); + if (ret != E_OK) { + return ret; + } + + auto result = rdbStore->Query(predicates); + + if (result == nullptr) { + return E_ERROR; + } + + int32_t rowCount = -1; + ret = result->GetRowCount(rowCount); + if (ret != E_OK) { + return ret; + } + + ret = rdbStore->Delete(deletedRows, "test", "id = 1", std::vector()); + if (ret != E_OK) { + return ret; + } +} + +int32_t Demo(const std::string &dbPath) +{ + RdbStoreConfig config(dbPath); + config.SetName("dlopenTest.db"); + config.SetEncryptStatus(true); + std::string bundleName = "com.ohos.dlopenTest"; + config.SetBundleName(bundleName); + int errCode = E_OK; + + RdbHelperTestOpenCallback helper; + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + + if (rdbStore == nullptr) { + return E_ERROR; + } + Subscriber subscriber(rdbStore); + + errCode = rdbStore->Notify("demoTest"); + if (errCode != E_OK) { + return errCode; + } + + errCode = Crud(rdbStore); + if (errCode != E_OK) { + return errCode; + } +} \ No newline at end of file diff --git a/kv_store/test/fuzztest/singlekvstorestub_fuzzer/singlekvstorestub_fuzzer.h b/relational_store/frameworks/native/dlopen_rdb/dlopen_rdb.h similarity index 74% rename from kv_store/test/fuzztest/singlekvstorestub_fuzzer/singlekvstorestub_fuzzer.h rename to relational_store/frameworks/native/dlopen_rdb/dlopen_rdb.h index b2652170a3aa9922d6cd4b5c11abc4fc675e96b9..86b400aee27825f5bae2ea5af3ef20681d1457ec 100644 --- a/kv_store/test/fuzztest/singlekvstorestub_fuzzer/singlekvstorestub_fuzzer.h +++ b/relational_store/frameworks/native/dlopen_rdb/dlopen_rdb.h @@ -12,11 +12,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef LDBPROJ_DLOPEN_RDB_H +#define LDBPROJ_DLOPEN_RDB_H -#ifndef SINGLEKVSTORESTUB_FUZZER_H -#define SINGLEKVSTORESTUB_FUZZER_H - -#define FUZZ_PROJECT_NAME "singlekvstorestub_fuzzer" - -#endif // SINGLEKVSTORESTUB_FUZZER_H +namespace OHOS { +namespace DistributedData { +class dlopen_rdb { +}; +} // namespace DistributedData +} // namespace OHOS +#endif //LDBPROJ_DLOPEN_RDB_H diff --git a/relational_store/frameworks/native/gdb/adapter/include/grd_adapter.h b/relational_store/frameworks/native/gdb/adapter/include/grd_adapter.h deleted file mode 100644 index a59ed59bafad0dcd29d058b87ad35e999d5bc85b..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/adapter/include/grd_adapter.h +++ /dev/null @@ -1,64 +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. - */ - -#ifndef OHOS_DISTRIBUTED_DATA_OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRD_ADAPTER_H -#define OHOS_DISTRIBUTED_DATA_OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRD_ADAPTER_H - -#include -#include -#include -#include - -#include "full_result.h" -#include "statement.h" -#include "grd_type_export.h" - -namespace OHOS::DistributedDataAip { - -class GrdAdapter { -public: - static ColumnType TransColType(int grdColType); - static int Open(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB **db); - static int Repair(const char *dbPath, const char *configStr); - static int Close(GRD_DB *db, uint32_t flags); - - /* graph */ - static int32_t Prepare(GRD_DB *db, const char *str, uint32_t strLen, GRD_StmtT **stmt, const char **unusedStr); - static int32_t Reset(GRD_StmtT *stmt); - static int32_t Finalize(GRD_StmtT *stmt); - - static int32_t Step(GRD_StmtT *stmt); - static uint32_t ColumnCount(GRD_StmtT *stmt); - static GRD_DbDataTypeE ColumnType(GRD_StmtT *stmt, uint32_t idx); - static uint32_t ColumnBytes(GRD_StmtT *stmt, uint32_t idx); - static char *ColumnName(GRD_StmtT *stmt, uint32_t idx); - static GRD_DbValueT ColumnValue(GRD_StmtT *stmt, uint32_t idx); - static int64_t ColumnInt64(GRD_StmtT *stmt, uint32_t idx); - static int32_t ColumnInt(GRD_StmtT *stmt, uint32_t idx); - static double ColumnDouble(GRD_StmtT *stmt, uint32_t idx); - static const char *ColumnText(GRD_StmtT *stmt, uint32_t idx); - - static int Backup(GRD_DB *db, const char *backupDbFile, const std::vector &encryptedKey); - static int Restore(const char *dbFile, const char *backupDbFile, const std::vector &encryptedKey); - static int Rekey(const char *dbFile, const char *configStr, const std::vector &encryptedKey); - -private: - static int TransErrno(int err); - - static std::map GRD_ERRNO_MAP; -}; - -} // namespace OHOS::DistributedDataAip -#endif \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/adapter/include/grd_adapter_manager.h b/relational_store/frameworks/native/gdb/adapter/include/grd_adapter_manager.h deleted file mode 100644 index 2f6eac3f37a0ab43502afa783c7c02dee8c96a4c..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/adapter/include/grd_adapter_manager.h +++ /dev/null @@ -1,77 +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. -*/ - -#ifndef OHOS_DISTRIBUTED_DATA_OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRD_ADAPTER_MANAGER_H -#define OHOS_DISTRIBUTED_DATA_OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRD_ADAPTER_MANAGER_H - -#include "grd_type_export.h" - -namespace OHOS::DistributedDataAip { - -typedef int32_t (*Open)(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB **db); -typedef int32_t (*Close)(GRD_DB *db, uint32_t flags); -typedef int32_t (*Repair)(const char *dbPath, const char *configStr); - -typedef int32_t (*Prepare)(GRD_DB *db, const char *str, uint32_t strLen, GRD_StmtT **stmt, const char **unusedStr); -typedef int32_t (*Reset)(GRD_StmtT *stmt); -typedef int32_t (*Finalize)(GRD_StmtT *stmt); - -typedef int32_t (*Step)(GRD_StmtT *stmt); -typedef uint32_t (*ColumnCount)(GRD_StmtT *stmt); -typedef GRD_DbDataTypeE (*GetColumnType)(GRD_StmtT *stmt, uint32_t idx); -typedef uint32_t (*ColumnBytes)(GRD_StmtT *stmt, uint32_t idx); -typedef char *(*ColumnName)(GRD_StmtT *stmt, uint32_t idx); -typedef GRD_DbValueT (*ColumnValue)(GRD_StmtT *stmt, uint32_t idx); -typedef int64_t (*ColumnInt64)(GRD_StmtT *stmt, uint32_t idx); -typedef int32_t (*ColumnInt)(GRD_StmtT *stmt, uint32_t idx); -typedef double (*ColumnDouble)(GRD_StmtT *stmt, uint32_t idx); -typedef const char *(*ColumnText)(GRD_StmtT *stmt, uint32_t idx); - -typedef int32_t (*Backup)(GRD_DB *db, const char *backupDbFile, GRD_CipherInfoT *cipherInfo); -typedef int32_t (*Restore)(const char *dbFile, const char *backupDbFile, GRD_CipherInfoT *cipherInfo); -typedef int32_t (*Rekey)(const char *dbFile, const char *configStr, GRD_CipherInfoT *cipherInfo); - -struct GrdAdapterHolder { - Open Open = nullptr; - Close Close = nullptr; - Repair Repair = nullptr; - - Prepare Prepare = nullptr; - Reset Reset = nullptr; - Finalize Finalize = nullptr; - Step Step = nullptr; - ColumnCount ColumnCount = nullptr; - GetColumnType GetColumnType = nullptr; - ColumnBytes ColumnBytes = nullptr; - ColumnName ColumnName = nullptr; - ColumnValue ColumnValue = nullptr; - ColumnInt64 ColumnInt64 = nullptr; - ColumnInt ColumnInt = nullptr; - ColumnDouble ColumnDouble = nullptr; - ColumnText ColumnText = nullptr; - - Backup Backup = nullptr; - Restore Restore = nullptr; - Rekey Rekey = nullptr; -}; - -bool IsSupportArkDataDb(); -GrdAdapterHolder GetAdapterHolder(); - -static void *g_library = nullptr; - -} // namespace OHOS::DistributedDataAip - -#endif // OHOS_DISTRIBUTED_DATA_OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRD_ADAPTER_MANAGER_H diff --git a/relational_store/frameworks/native/gdb/adapter/src/grd_adapter.cpp b/relational_store/frameworks/native/gdb/adapter/src/grd_adapter.cpp deleted file mode 100644 index 1b2129ce6a8b0c4a98a5732e8d966154f8bcee21..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/adapter/src/grd_adapter.cpp +++ /dev/null @@ -1,388 +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. - */ -#define LOG_TAG "GrdAdapter" - -#include "grd_adapter.h" - -#include -#include - -#include "gdb_errors.h" -#include "gdb_utils.h" -#include "grd_adapter_manager.h" -#include "grd_error.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { - -static GrdAdapterHolder g_adapterHolder; - -std::map GrdAdapter::GRD_ERRNO_MAP = { - { GRD_OK, E_OK }, - { GRD_REBUILD_DATABASE, E_OK }, - { GRD_NO_DATA, E_GRD_NO_DATA }, - { GRD_DATA_CORRUPTED, E_GRD_DATA_CORRUPTED }, - { GRD_INVALID_FILE_FORMAT, E_GRD_INVALID_FILE_FORMAT }, - { GRD_PRIMARY_KEY_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_RESTRICT_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_CONSTRAINT_CHECK_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_NOT_SUPPORT, E_GRD_NOT_SUPPORT }, - { GRD_OVER_LIMIT, E_GRD_OVER_LIMIT }, - { GRD_INVALID_ARGS, E_GRD_INVALID_ARGS }, - { GRD_FAILED_FILE_OPERATION, E_GRD_FAILED_FILE_OPERATION }, - { GRD_INSUFFICIENT_SPACE, E_GRD_DISK_SPACE_FULL }, - { GRD_RESOURCE_BUSY, E_DATABASE_BUSY }, - { GRD_DB_BUSY, E_DATABASE_BUSY }, - { GRD_FAILED_MEMORY_ALLOCATE, E_GRD_FAILED_MEMORY_ALLOCATE }, - { GRD_CRC_CHECK_DISABLED, E_GRD_CRC_CHECK_DISABLED }, - { GRD_DISK_SPACE_FULL, E_GRD_DISK_SPACE_FULL }, - - { GRD_PERMISSION_DENIED, E_GRD_PERMISSION_DENIED }, - { GRD_PASSWORD_UNMATCHED, E_GRD_PASSWORD_UNMATCHED }, - { GRD_PASSWORD_NEED_REKEY, E_GRD_PASSWORD_NEED_REKEY }, - - { GRD_NAME_TOO_LONG, E_GRD_INVALID_NAME }, - { GRD_INVALID_TABLE_DEFINITION, E_GRD_SEMANTIC_ERROR }, - { GRD_SEMANTIC_ERROR, E_GRD_SEMANTIC_ERROR }, - { GRD_SYNTAX_ERROR, E_GRD_SYNTAX_ERROR }, - { GRD_WRONG_STMT_OBJECT, E_GRD_WRONG_STMT_OBJECT }, - { GRD_DATA_CONFLICT, E_GRD_DATA_CONFLICT }, - - { GRD_INNER_ERR, E_GRD_INNER_ERR }, - { GRD_FAILED_MEMORY_RELEASE, E_GRD_FAILED_MEMORY_RELEASE }, - { GRD_NOT_AVAILABLE, E_GRD_NOT_AVAILABLE }, - { GRD_INVALID_FORMAT, E_GRD_SEMANTIC_ERROR }, - { GRD_TIME_OUT, E_DATABASE_BUSY }, - { GRD_DB_INSTANCE_ABNORMAL, E_GRD_DB_INSTANCE_ABNORMAL }, - { GRD_CIPHER_ERROR, E_GRD_CIPHER_ERROR }, - { GRD_DUPLICATE_TABLE, E_GRD_DUPLICATE_PARAM }, - { GRD_DUPLICATE_OBJECT, E_GRD_DUPLICATE_PARAM }, - { GRD_DUPLICATE_COLUMN, E_GRD_DUPLICATE_PARAM }, - { GRD_UNDEFINE_COLUMN, E_GRD_UNDEFINED_PARAM }, - { GRD_UNDEFINED_OBJECT, E_GRD_UNDEFINED_PARAM }, - { GRD_UNDEFINED_TABLE, E_GRD_UNDEFINED_PARAM }, - { GRD_INVALID_CONFIG_VALUE, E_CONFIG_INVALID_CHANGE }, - { GRD_REQUEST_TIME_OUT, E_DATABASE_BUSY }, - { GRD_DATATYPE_MISMATCH, E_GRD_SEMANTIC_ERROR }, - { GRD_UNIQUE_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_INVALID_BIND_VALUE, E_GRD_INVALID_BIND_VALUE }, - { GRD_JSON_OPERATION_NOT_SUPPORT, E_GRD_SEMANTIC_ERROR }, - { GRD_MODEL_NOT_SUPPORT, E_GRD_SEMANTIC_ERROR }, - { GRD_FEATURE_NOT_SUPPORTED, E_GRD_SEMANTIC_ERROR }, - { GRD_JSON_LEN_LIMIT, E_GRD_DATA_CONFLICT }, - { GRD_SUBSCRIPTION_EXCEEDED_LIMIT, E_GRD_INNER_ERR }, - { GRD_SYNC_EXCEED_TASK_QUEUE_LIMIT, E_DATABASE_BUSY }, - { GRD_SHARED_OBJ_ENABLE_UNDO_EXCEED_LIMIT, E_GRD_INNER_ERR }, - { GRD_TABLE_LIMIT_EXCEEDED, E_GRD_OVER_LIMIT }, - { GRD_FIELD_TYPE_NOT_MATCH, E_GRD_SEMANTIC_ERROR }, - { GRD_LARGE_JSON_NEST, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_JSON_TYPE, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_OPERATOR, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_PROJECTION_FIELD, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_PROJECTION_VALUE, E_GRD_SEMANTIC_ERROR }, - { GRD_DB_NOT_EXIST, E_GRD_DB_NOT_EXIST }, - { GRD_INVALID_VALUE, E_GRD_INVALID_ARGS }, - { GRD_SHARED_OBJ_NOT_EXIST, E_GRD_DATA_NOT_FOUND }, - { GRD_SUBSCRIBE_NOT_EXIST, E_GRD_DATA_NOT_FOUND }, - { GRD_COLLECTION_NOT_EXIST, E_GRD_DATA_NOT_FOUND }, - { GRD_RESULTSET_BUSY, E_DATABASE_BUSY }, - { GRD_RECORD_NOT_FOUND, E_GRD_DATA_NOT_FOUND }, - { GRD_FIELD_NOT_FOUND, E_GRD_DATA_NOT_FOUND }, - { GRD_ARRAY_INDEX_NOT_FOUND, E_GRD_DATA_NOT_FOUND }, - { GRD_RESULT_SET_NOT_AVAILABLE, E_GRD_DATA_NOT_FOUND }, - { GRD_SHARED_OBJ_UNDO_NOT_AVAILABLE, E_GRD_DATA_NOT_FOUND }, - { GRD_SHARED_OBJ_REDO_NOT_AVAILABLE, E_GRD_DATA_NOT_FOUND }, - { GRD_INVALID_JSON_FORMAT, E_GRD_DATA_CONFLICT }, - { GRD_INVALID_KEY_FORMAT, E_GRD_INVALID_NAME }, - { GRD_INVALID_COLLECTION_NAME, E_GRD_INVALID_NAME }, - { GRD_INVALID_EQUIP_ID, E_GRD_SEMANTIC_ERROR }, - { GRD_KEY_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_FIELD_TYPE_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_SHARED_OBJ_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_SUBSCRIBE_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_EQUIP_ID_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_SHARED_OBJ_ENABLE_UNDO_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_SCHEMA_CHANGED, E_CONFIG_INVALID_CHANGE }, - { GRD_DATA_EXCEPTION, E_GRD_DATA_EXCEPTION }, - { GRD_FIELD_OVERFLOW, E_GRD_SEMANTIC_ERROR }, - { GRD_DIVISION_BY_ZERO, E_GRD_SYNTAX_ERROR }, - { GRD_TRANSACTION_ROLLBACK, E_GRD_TRANSACTION_ROLLBACK }, - { GRD_NO_ACTIVE_TRANSACTION, E_GRD_NO_ACTIVE_TRANSACTION }, - { GRD_ACTIVE_TRANSACTION, E_GRD_ACTIVE_TRANSACTION }, -}; - -int GrdAdapter::TransErrno(int err) -{ - if (err > 0) { - return err; - } - auto result = GRD_ERRNO_MAP.find(err); - if (result != GRD_ERRNO_MAP.end()) { - return result->second; - } - return E_GRD_INNER_ERR; -} - -ColumnType GrdAdapter::TransColType(int grdColType) -{ - switch (grdColType) { - case GRD_DB_DATATYPE_INTEGER: - return ColumnType::TYPE_INTEGER; - case GRD_DB_DATATYPE_FLOAT: - return ColumnType::TYPE_FLOAT; - case GRD_DB_DATATYPE_TEXT: - return ColumnType::TYPE_TEXT; - case GRD_DB_DATATYPE_BLOB: - return ColumnType::TYPE_BLOB; - case GRD_DB_DATATYPE_FLOATVECTOR: - return ColumnType::TYPE_FLOATVECTOR; - case GRD_DB_DATATYPE_JSONSTR: - return ColumnType::TYPE_JSONSTR; - case GRD_DB_DATATYPE_NULL: - return ColumnType::TYPE_NULL; - default: - LOG_ERROR("trans failed. GRD_DbDataTypeE=%{public}d.", grdColType); - return ColumnType::TYPE_NULL; - } -} - -int GrdAdapter::Open(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB **db) -{ - if (g_adapterHolder.Open == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Open == nullptr) { - return E_NOT_SUPPORT; - } - auto ret = g_adapterHolder.Open(dbPath, configStr, flags, db); - return TransErrno(ret); -} - -int GrdAdapter::Close(GRD_DB *db, uint32_t flags) -{ - if (g_adapterHolder.Close == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Close == nullptr) { - return E_NOT_SUPPORT; - } - auto ret = g_adapterHolder.Close(db, flags); - LOG_DEBUG("Close ret=%{public}d", ret); - return TransErrno(ret); -} - -int GrdAdapter::Repair(const char *dbPath, const char *configStr) -{ - if (g_adapterHolder.Repair == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Repair == nullptr) { - return E_NOT_SUPPORT; - } - return E_NOT_SUPPORT; -} - -int GrdAdapter::Backup(GRD_DB *db, const char *backupDbFile, const std::vector &encryptedKey) -{ - if (g_adapterHolder.Backup == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Backup == nullptr) { - return E_NOT_SUPPORT; - } - return E_NOT_SUPPORT; -} - -int GrdAdapter::Restore(const char *dbFile, const char *backupDbFile, const std::vector &encryptedKey) -{ - if (g_adapterHolder.Restore == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Restore == nullptr) { - return E_NOT_SUPPORT; - } - return E_NOT_SUPPORT; -} - -int GrdAdapter::Rekey(const char *dbFile, const char *configStr, const std::vector &encryptedKey) -{ - if (g_adapterHolder.Rekey == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Rekey == nullptr) { - return E_NOT_SUPPORT; - } - if (encryptedKey.empty()) { - return E_GRD_INVALID_ARGS; - } - int32_t ret = E_OK; - GRD_CipherInfoT info = { 0 }; - const size_t keySize = encryptedKey.size() * 2 + 1; // 2 hex number can represent a uint8_t, 1 is for '\0' - std::vector key(keySize); - info.hexPassword = GdbUtils::GetEncryptKey(encryptedKey, key.data(), keySize); - ret = g_adapterHolder.Rekey(dbFile, configStr, &info); - key.assign(keySize, 0); - return TransErrno(ret); -} - -int32_t GrdAdapter::Prepare(GRD_DB *db, const char *str, uint32_t strLen, GRD_StmtT **stmt, const char **unusedStr) -{ - if (g_adapterHolder.Prepare == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Prepare == nullptr) { - return E_NOT_SUPPORT; - } - int32_t ret = g_adapterHolder.Prepare(db, str, strLen, stmt, unusedStr); - return TransErrno(ret); -} - -int32_t GrdAdapter::Reset(GRD_StmtT *stmt) -{ - if (g_adapterHolder.Reset == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Reset == nullptr) { - return E_NOT_SUPPORT; - } - return TransErrno(g_adapterHolder.Reset(stmt)); -} - -int32_t GrdAdapter::Finalize(GRD_StmtT *stmt) -{ - if (g_adapterHolder.Finalize == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Finalize == nullptr) { - return E_NOT_SUPPORT; - } - int32_t ret = g_adapterHolder.Finalize(stmt); - LOG_DEBUG("Finalize ret=%{public}d", ret); - return TransErrno(ret); -} - -int32_t GrdAdapter::Step(GRD_StmtT *stmt) -{ - if (g_adapterHolder.Step == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Step == nullptr) { - return E_NOT_SUPPORT; - } - int32_t ret = g_adapterHolder.Step(stmt); - LOG_DEBUG("Step ret=%{public}d", ret); - return TransErrno(ret); -} - -uint32_t GrdAdapter::ColumnCount(GRD_StmtT *stmt) -{ - if (g_adapterHolder.ColumnCount == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnCount == nullptr) { - return E_NOT_SUPPORT; - } - return g_adapterHolder.ColumnCount(stmt); -} - -GRD_DbDataTypeE GrdAdapter::ColumnType(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.GetColumnType == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.GetColumnType == nullptr) { - return GRD_DB_DATATYPE_NULL; - } - return g_adapterHolder.GetColumnType(stmt, idx); -} - -uint32_t GrdAdapter::ColumnBytes(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnBytes == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnBytes == nullptr) { - return E_NOT_SUPPORT; - } - return g_adapterHolder.ColumnBytes(stmt, idx); -} - -char *GrdAdapter::ColumnName(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnName == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnName == nullptr) { - return nullptr; - } - return g_adapterHolder.ColumnName(stmt, idx); -} - -GRD_DbValueT GrdAdapter::ColumnValue(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnValue == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnValue == nullptr) { - return {}; - } - return g_adapterHolder.ColumnValue(stmt, idx); -} - -int64_t GrdAdapter::ColumnInt64(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnInt64 == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnInt64 == nullptr) { - return 0; - } - return g_adapterHolder.ColumnInt64(stmt, idx); -} - -int32_t GrdAdapter::ColumnInt(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnInt == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnInt == nullptr) { - return 0; - } - return g_adapterHolder.ColumnInt(stmt, idx); -} - -double GrdAdapter::ColumnDouble(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnDouble == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnDouble == nullptr) { - return 0; - } - return g_adapterHolder.ColumnDouble(stmt, idx); -} - -const char *GrdAdapter::ColumnText(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnText == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnText == nullptr) { - return nullptr; - } - return g_adapterHolder.ColumnText(stmt, idx); -} - -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/adapter/src/grd_adapter_manager.cpp b/relational_store/frameworks/native/gdb/adapter/src/grd_adapter_manager.cpp deleted file mode 100644 index a2859a2a1b9cb20109ba07a6f4831da680530f1d..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/adapter/src/grd_adapter_manager.cpp +++ /dev/null @@ -1,69 +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. -*/ -#define LOG_TAG "GrdAdapter" -#include - -#include "grd_adapter_manager.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { -void GrdAdapterHolderInit(GrdAdapterHolder &adapterHolder) -{ - adapterHolder.Open = (Open)dlsym(g_library, "GRD_DBOpen"); - adapterHolder.Close = (Close)dlsym(g_library, "GRD_DBClose"); - adapterHolder.Repair = (Repair)dlsym(g_library, "GRD_DBRepair"); - adapterHolder.Backup = (Backup)dlsym(g_library, "GRD_DBBackup"); - adapterHolder.Restore = (Restore)dlsym(g_library, "GRD_DBRestore"); - adapterHolder.Rekey = (Rekey)dlsym(g_library, "GRD_DBRekey"); - - adapterHolder.Prepare = (Prepare)dlsym(g_library, "GRD_GqlPrepare"); - adapterHolder.Reset = (Reset)dlsym(g_library, "GRD_GqlReset"); - adapterHolder.Finalize = (Finalize)dlsym(g_library, "GRD_GqlFinalize"); - adapterHolder.Step = (Step)dlsym(g_library, "GRD_GqlStep"); - adapterHolder.ColumnCount = (ColumnCount)dlsym(g_library, "GRD_GqlColumnCount"); - adapterHolder.GetColumnType = (GetColumnType)dlsym(g_library, "GRD_GqlColumnType"); - adapterHolder.ColumnBytes = (ColumnBytes)dlsym(g_library, "GRD_GqlColumnBytes"); - adapterHolder.ColumnName = (ColumnName)dlsym(g_library, "GRD_GqlColumnName"); - adapterHolder.ColumnValue = (ColumnValue)dlsym(g_library, "GRD_GqlColumnValue"); - adapterHolder.ColumnInt64 = (ColumnInt64)dlsym(g_library, "GRD_GqlColumnInt64"); - adapterHolder.ColumnInt = (ColumnInt)dlsym(g_library, "GRD_GqlColumnInt"); - adapterHolder.ColumnDouble = (ColumnDouble)dlsym(g_library, "GRD_GqlColumnDouble"); - adapterHolder.ColumnText = (ColumnText)dlsym(g_library, "GRD_GqlColumnText"); -} - -bool IsSupportArkDataDb() -{ -#ifdef ARKDATA_DB_CORE_IS_EXISTS - return true; -#else - return false; -#endif -} - -GrdAdapterHolder GetAdapterHolder() -{ - GrdAdapterHolder adapterHolder; - if (g_library == nullptr) { - g_library = dlopen("libarkdata_db_core.z.so", RTLD_LAZY); - } - if (g_library == nullptr) { - LOG_WARN("use default db kernel"); - return adapterHolder; - } - GrdAdapterHolderInit(adapterHolder); - return adapterHolder; -} - -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/include/connection.h b/relational_store/frameworks/native/gdb/include/connection.h deleted file mode 100644 index 52f5eaf16c9d34cb7762d98ce364290b56b7f2f2..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/include/connection.h +++ /dev/null @@ -1,44 +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. - */ - -#ifndef OHOS_DISTRIBUTED_DATA_NATIVE_GDB_CONNECTION_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_CONNECTION_H - -#include "gdb_store_config.h" -#include "statement.h" - -namespace OHOS::DistributedDataAip { -class StoreConfig; -class Statement; -class Connection { -public: - using SConn = std::shared_ptr; - using Stmt = std::shared_ptr; - using Creator = std::pair (*)(const StoreConfig &config, bool isWriter); - static std::pair Create(const StoreConfig &config, bool isWriter); - static int32_t RegisterCreator(DBType dbType, Creator creator); - - int32_t SetId(int32_t id); - int32_t GetId() const; - virtual ~Connection() = default; - virtual std::pair CreateStatement(const std::string &gql, std::shared_ptr conn) = 0; - virtual DBType GetDBType() const = 0; - virtual bool IsWriter() const = 0; - -private: - int32_t id_ = 0; -}; -} // namespace OHOS::DistributedDataAip -#endif // OHOS_DISTRIBUTED_DATA_NATIVE_GDB_CONNECTION_H \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/include/connection_pool.h b/relational_store/frameworks/native/gdb/include/connection_pool.h deleted file mode 100644 index 2da03e16384daf0ed9cb0170d8235505c6d98f90..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/include/connection_pool.h +++ /dev/null @@ -1,121 +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. - */ - -#ifndef OHOS_DISTRIBUTED_DATA_NATIVE_GDB_CONNECTION_POOL_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_CONNECTION_POOL_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "connection.h" -#include "gdb_store_config.h" - -namespace OHOS::DistributedDataAip { -class ConnectionPool : public std::enable_shared_from_this { -public: - using SharedConn = std::shared_ptr; - static constexpr std::chrono::milliseconds INVALID_TIME = std::chrono::milliseconds(0); - static std::shared_ptr Create(const StoreConfig &config, int &errCode); - ~ConnectionPool(); - std::pair> CreateTransConn(); - SharedConn Acquire(bool isReadOnly, std::chrono::milliseconds ms = INVALID_TIME); - // this interface is only provided for resultSet - SharedConn AcquireRef(bool isReadOnly, std::chrono::milliseconds ms = INVALID_TIME); - int32_t Dump(bool isWriter, const char *header); - int RestartReaders(); - void CloseAllConnections(); - - explicit ConnectionPool(const StoreConfig &storeConfig); - -private: - struct ConnNode { - bool using_ = false; - int32_t tid_ = 0; - int32_t id_ = 0; - std::chrono::steady_clock::time_point time_ = std::chrono::steady_clock::now(); - std::shared_ptr connect_; - - explicit ConnNode(std::shared_ptr conn); - std::shared_ptr GetConnect(); - int64_t GetUsingTime() const; - bool IsWriter() const; - int32_t Unused(int32_t count, bool timeout); - }; - - struct Container { - using Creator = std::function>()>; - static constexpr int32_t MAX_RIGHT = 0x4FFFFFFF; - static constexpr int32_t MIN_TRANS_ID = 10000; - bool disable_ = true; - int max_ = 0; - int total_ = 0; - int count_ = 0; - int trans_ = 0; - int32_t left_ = 0; - int32_t right_ = 0; - std::chrono::seconds timeout_; - std::list> nodes_; - std::list> details_; - std::mutex mutex_; - std::condition_variable cond_; - Creator creator_ = nullptr; - std::pair> Initialize( - Creator creator, int32_t max, int32_t timeout, bool disable, bool acquire = false); - std::shared_ptr Acquire(std::chrono::milliseconds milliS); - std::pair> Create(); - - void Disable(); - void Enable(); - int32_t Release(std::shared_ptr node); - int32_t Drop(std::shared_ptr node); - int32_t Clear(); - bool IsFull(); - int32_t Dump(const char *header, int32_t count); - - private: - int32_t ExtendNode(); - int32_t RelDetails(std::shared_ptr node); - }; - - std::pair> Init(bool isAttach = false, bool needWriter = false); - int32_t GetMaxReaders(const StoreConfig &config); - std::shared_ptr Convert2AutoConn(std::shared_ptr node, bool isTrans = false); - void ReleaseNode(std::shared_ptr node, bool reuse = true); - - static constexpr uint32_t CHECK_POINT_INTERVAL = 5; // 5 min - static constexpr uint32_t ITER_V1 = 5000; - static constexpr uint32_t ITERS_COUNT = 2; - static constexpr uint32_t MAX_TRANS = 4; - const StoreConfig &config_; - Container writers_; - Container readers_; - int32_t maxReader_ = 0; - - std::condition_variable transCondition_; - std::atomic isInTransaction_ = false; - std::atomic transCount_ = 0; - std::atomic failedTime_; -}; - -} // namespace OHOS::DistributedDataAip -#endif diff --git a/relational_store/frameworks/native/gdb/include/db_store_impl.h b/relational_store/frameworks/native/gdb/include/db_store_impl.h deleted file mode 100644 index a50062fb5fc1393c928b856750d8f09a2df1446a..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/include/db_store_impl.h +++ /dev/null @@ -1,50 +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. - */ - -#ifndef OHOS_DISTRIBUTED_DATA_NATIVE_GDB_DB_STORE_IMPL_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_DB_STORE_IMPL_H - -#include -#include - -#include "connection.h" -#include "connection_pool.h" -#include "gdb_store.h" -#include "gdb_store_config.h" -#include "gdb_transaction.h" - -namespace OHOS::DistributedDataAip { -class DBStoreImpl final : public DBStore { -public: - explicit DBStoreImpl(StoreConfig config); - ~DBStoreImpl(); - std::pair> QueryGql(const std::string &gql) override; - std::pair> ExecuteGql(const std::string &gql) override; - std::pair> CreateTransaction() override; - int32_t Close() override; - int32_t InitConn(); - -private: - std::shared_ptr GetConnectionPool(); - void SetConnectionPool(std::shared_ptr connectionPool); - - std::mutex mutex_; - std::mutex transMutex_; - StoreConfig config_; - std::shared_ptr connectionPool_ = nullptr; - std::list> transactions_; -}; -} // namespace OHOS::DistributedDataAip -#endif diff --git a/relational_store/frameworks/native/gdb/include/db_store_manager.h b/relational_store/frameworks/native/gdb/include/db_store_manager.h deleted file mode 100644 index e5cef31d84fb8f89595055bca6499df419271481..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/include/db_store_manager.h +++ /dev/null @@ -1,54 +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. - */ -#ifndef OHOS_DISTRIBUTED_DATA_NATIVE_GDB_DB_STORE_MANAGER_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_DB_STORE_MANAGER_H -#include -#include - -#include "db_store_impl.h" - -namespace OHOS::DistributedDataAip { -class StoreManager { -public: - static StoreManager &GetInstance(); - ~StoreManager(); - std::shared_ptr GetDBStore(const StoreConfig &config, int &errCode); - void Clear(); - bool Delete(const std::string &path); - -private: - StoreManager(); - bool DeleteFile(const std::string &path); - int SetSecurityLabel(const StoreConfig &config); - std::string GetSecurityLevelValue(SecurityLevel securityLevel); - std::string GetFileSecurityLevel(const std::string &filePath); - bool IsValidName(const std::string& name); - bool IsValidSecurityLevel(const int32_t securityLevel); - std::mutex mutex_; - std::string bundleName_; - std::map> storeCache_; - static constexpr const char *GRD_POST_FIXES[] = { - "", - ".redo", - ".undo", - ".ctrl", - ".ctrl.dwr", - ".safe", - ".map", - ".corruptedflg", - }; -}; -} // namespace OHOS::DistributedDataAip -#endif \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/include/full_result.h b/relational_store/frameworks/native/gdb/include/full_result.h deleted file mode 100644 index 648ebaf9f2793588c8ebdf08b5461779c5240dc7..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/include/full_result.h +++ /dev/null @@ -1,45 +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. - */ -#ifndef OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_FULLRESULT_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_FULLRESULT_H - -#include -#include -#include -#include -#include -#include - -#include "edge.h" -#include "gdb_store_config.h" -#include "nlohmann/json.hpp" -#include "path.h" -#include "result.h" -#include "vertex.h" - -namespace OHOS::DistributedDataAip { -class Statement; -class FullResult final : public Result { -public: - FullResult() = default; - std::vector> GetAllData() const override; - int32_t InitData(std::shared_ptr stmt); - -private: - std::pair> GetRow(std::shared_ptr stmt); - std::vector> data_; -}; -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_FULLRESULT_H diff --git a/relational_store/frameworks/native/gdb/include/gdb_utils.h b/relational_store/frameworks/native/gdb/include/gdb_utils.h deleted file mode 100644 index 055e91c3b66d89a5076ec5674ad587fb59c3c12c..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/include/gdb_utils.h +++ /dev/null @@ -1,41 +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. - */ - -#ifndef OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GDB_UTILS_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GDB_UTILS_H -#include - -#include "rdb_visibility.h" - -namespace OHOS::DistributedDataAip { -class API_EXPORT GdbUtils { -public: - static bool IsTransactionGql(const std::string &gql); - static int CreateDirectory(const std::string &databaseDir); - static std::string Anonymous(const std::string &srcFile); - static void ClearAndZeroString(std::string &str); - static std::string GetConfigStr(const std::vector &keys, bool isEncrypt); - static const char *GetEncryptKey(const std::vector &encryptedKey, char outBuff[], size_t outBufSize); -private: - static constexpr int DIR_RWXRWS__X = 0771; - static constexpr const char *GRD_OPEN_CONFIG_STR = - R"("pageSize": 8, "crcCheckEnable": 0, "defaultIsolationLevel": 3, "redoFlushByTrx": 1, )" - R"("metaInfoBak": 1, "maxConnNum": 500, "bufferPoolSize": 10240)"; - static std::string GetAnonymousName(const std::string& fileName); - static std::string AnonyDigits(const std::string& fileName); -}; -} - -#endif \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/include/graph_connection.h b/relational_store/frameworks/native/gdb/include/graph_connection.h deleted file mode 100644 index 670a5a1d8a105294f6da234588b31ebc9fc8a6a9..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/include/graph_connection.h +++ /dev/null @@ -1,55 +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. - */ - -#ifndef OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_CONNECTION_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_CONNECTION_H - -#include -#include -#include - -#include "connection.h" -#include "gdb_store_config.h" -#include "grd_adapter.h" - -namespace OHOS::DistributedDataAip { -class GraphConnection : public Connection { -public: - static std::pair> Create(const StoreConfig &config, bool isWriter); - GraphConnection(const StoreConfig &config, bool isWriter); - ~GraphConnection() override; - std::pair CreateStatement(const std::string &gql, std::shared_ptr conn) override; - DBType GetDBType() const override; - bool IsWriter() const override; - -private: - static constexpr uint32_t NO_ITER = 0; - static constexpr uint32_t ITER_V1 = 5000; - static constexpr uint32_t ITERS[] = { NO_ITER, ITER_V1 }; - static constexpr uint32_t ITERS_COUNT = sizeof(ITERS) / sizeof(ITERS[0]); - - static const int32_t regCreator_; - - int InnerOpen(const StoreConfig &config); - int32_t ResetKey(const StoreConfig &config); - bool IsEncryptInvalidChanged(const StoreConfig &config); - GRD_DB *dbHandle_ = nullptr; - const StoreConfig config_; - bool isWriter_ = false; -}; - -} // namespace OHOS::DistributedDataAip - -#endif // OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_CONNECTION_H diff --git a/relational_store/frameworks/native/gdb/include/graph_statement.h b/relational_store/frameworks/native/gdb/include/graph_statement.h deleted file mode 100644 index 5f4d3c2385066b7e186624a908a5d4dc6ef0f994..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/include/graph_statement.h +++ /dev/null @@ -1,52 +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. - */ - -#ifndef OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_STATEMENT_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_STATEMENT_H - -#ifndef JSON_NOEXCEPTION -#define JSON_NOEXCEPTION -#endif -#include "connection.h" -#include "grd_adapter.h" -#include "nlohmann/json.hpp" -#include "statement.h" - -namespace OHOS::DistributedDataAip { -class GraphStatement final : public Statement { -public: - GraphStatement(GRD_DB *db, const std::string &gql, std::shared_ptr conn, int32_t &errCode); - ~GraphStatement(); - - int32_t Prepare() override; - int32_t Step() override; - int32_t Finalize() override; - - uint32_t GetColumnCount() const override; - std::pair GetColumnName(int32_t index) const override; - std::pair GetColumnType(int32_t index) const override; - std::pair GetColumnValue(int32_t index) const override; - - bool IsReady() const override; - -private: - std::shared_ptr conn_; - std::string gql_; - GRD_Stmt *stmtHandle_ = nullptr; - GRD_DB *dbHandle_ = nullptr; - static GraphValue ParseJsonStr(const std::string &jsonStr, int32_t &errCode) ; -}; -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_STATEMENT_H diff --git a/relational_store/frameworks/native/gdb/include/statement.h b/relational_store/frameworks/native/gdb/include/statement.h deleted file mode 100644 index 89d29ae4b3160a7af6077f87339b4af10b1f38bf..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/include/statement.h +++ /dev/null @@ -1,55 +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. - */ - -#ifndef OHOS_DISTRIBUTED_DATA_NATIVE_GDB_STATEMENT_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_STATEMENT_H -#include -#include -#include -#include -#include - -#include "full_result.h" - -namespace OHOS::DistributedDataAip { -/** - * @brief Indicates the column type. - * - * Value returned by getColumnType(int) - */ -enum class ColumnType : int { - TYPE_INTEGER = 0, - TYPE_FLOAT, - TYPE_TEXT, - TYPE_BLOB, - TYPE_FLOATVECTOR, - TYPE_JSONSTR, - TYPE_NULL, -}; -class Statement { -public: - virtual int32_t Prepare() = 0; - virtual int32_t Step() = 0; - virtual int32_t Finalize() = 0; - - virtual uint32_t GetColumnCount() const = 0; - virtual std::pair GetColumnName(int32_t index) const = 0; - virtual std::pair GetColumnType(int32_t index) const = 0; - virtual std::pair GetColumnValue(int32_t index) const = 0; - - virtual bool IsReady() const = 0; -}; -} // namespace OHOS::DistributedDataAip -#endif //ARKDATA_INTELLIGENCE_PLATFORM_STATEMENT_H \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/src/connection.cpp b/relational_store/frameworks/native/gdb/src/connection.cpp deleted file mode 100644 index 52e6d8a4ddc9341f515272f59839c879c6030312..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/src/connection.cpp +++ /dev/null @@ -1,62 +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 "connection.h" - -#include "gdb_errors.h" - -namespace OHOS::DistributedDataAip { -static Connection::Creator g_creators[static_cast(DBType::DB_BUTT)] = { nullptr, nullptr }; - -std::pair> Connection::Create(const StoreConfig &config, const bool isWriter) -{ - auto dbType = config.GetDbType(); - if (dbType < DBType::DB_GRAPH || dbType >= DBType::DB_BUTT) { - return { E_NOT_SUPPORT, nullptr }; - } - - auto creator = g_creators[static_cast(dbType)]; - if (creator == nullptr) { - return { E_NOT_SUPPORT, nullptr }; - } - - return creator(config, isWriter); -} - -int32_t Connection::RegisterCreator(DBType dbType, Creator creator) -{ - if (dbType < DBType::DB_GRAPH || dbType >= DBType::DB_BUTT) { - return E_NOT_SUPPORT; - } - - if (g_creators[static_cast(dbType)] != nullptr) { - return E_OK; - } - - g_creators[static_cast(dbType)] = creator; - return E_OK; -} - -int Connection::SetId(int id) -{ - id_ = id; - return id_; -} - -int Connection::GetId() const -{ - return id_; -} - -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/src/connection_pool.cpp b/relational_store/frameworks/native/gdb/src/connection_pool.cpp deleted file mode 100644 index 24ea15cbf020eeb25b2f96e447d5843a8171f35e..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/src/connection_pool.cpp +++ /dev/null @@ -1,475 +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. - */ -#define LOG_TAG "GdbConnPool" -#include "connection_pool.h" - -#include -#include - -#include "gdb_errors.h" -#include "gdb_utils.h" -#include "logger.h" -#include "rdb_store_config.h" - -namespace OHOS::DistributedDataAip { -using namespace std::chrono; - -std::shared_ptr ConnectionPool::Create(const StoreConfig &config, int &errCode) -{ - std::shared_ptr pool = std::make_shared(config); - if (pool == nullptr) { - LOG_ERROR("ConnectionPool::Create new failed, pool is nullptr."); - errCode = E_INIT_CONN_POOL_FAILED; - return nullptr; - } - std::shared_ptr conn; - for (uint32_t retry = 0; retry < ITERS_COUNT; ++retry) { - std::tie(errCode, conn) = pool->Init(); - if (errCode != E_GRD_DATA_CORRUPTED) { - break; - } - config.SetIter(ITER_V1); - } - return errCode == E_OK ? pool : nullptr; -} - -ConnectionPool::ConnectionPool(const StoreConfig &storeConfig) : config_(storeConfig), writers_(), readers_() -{ -} - -std::pair> ConnectionPool::Init(bool isAttach, bool needWriter) -{ - std::pair> result; - auto &[errCode, conn] = result; - config_.GenerateEncryptedKey(); - // write connect count is 1 - std::shared_ptr node; - std::tie(errCode, node) = writers_.Initialize( - [this, isAttach]() { return Connection::Create(config_, true); }, 1, config_.GetWriteTime(), true, needWriter); - conn = Convert2AutoConn(node); - if (errCode != E_OK) { - return result; - } - - maxReader_ = GetMaxReaders(config_); - LOG_DEBUG("ConnectionPool::Init maxReader=%{public}d", maxReader_); - // max read connect count is 64 - if (maxReader_ > 64) { - LOG_ERROR("maxReader is too big. maxReader=%{public}d", maxReader_); - return { E_ARGS_READ_CON_OVERLOAD, nullptr }; - } - auto [ret, nodeRead] = readers_.Initialize([this, isAttach]() { return Connection::Create(config_, false); }, - maxReader_, config_.GetReadTime(), maxReader_ == 0); - errCode = ret; - return result; -} - -ConnectionPool::~ConnectionPool() -{ - LOG_DEBUG("enter"); - CloseAllConnections(); -} - -int32_t ConnectionPool::GetMaxReaders(const StoreConfig &config) -{ - return config.GetReadConSize(); -} - -std::shared_ptr ConnectionPool::Convert2AutoConn(std::shared_ptr node, bool isTrans) -{ - if (node == nullptr) { - return nullptr; - } - - auto conn = node->GetConnect(); - if (conn == nullptr) { - return nullptr; - } - if (isTrans) { - transCount_++; - } - - return std::shared_ptr(conn.get(), [pool = weak_from_this(), node, isTrans](auto *) mutable { - auto realPool = pool.lock(); - if (realPool == nullptr) { - return; - } - realPool->ReleaseNode(node, !isTrans); - if (isTrans) { - realPool->transCount_--; - } - node = nullptr; - }); -} - -void ConnectionPool::CloseAllConnections() -{ - writers_.Clear(); - readers_.Clear(); -} - -std::pair> ConnectionPool::CreateTransConn() -{ - if (transCount_ >= MAX_TRANS) { - writers_.Dump("NO TRANS", transCount_ + isInTransaction_); - return { E_DATABASE_BUSY, nullptr }; - } - auto [errCode, node] = writers_.Create(); - return { errCode, Convert2AutoConn(node, true) }; -} - -std::shared_ptr ConnectionPool::Acquire(bool isReadOnly, std::chrono::milliseconds ms) -{ - Container *container = (isReadOnly && maxReader_ != 0) ? &readers_ : &writers_; - auto node = container->Acquire(ms); - if (node == nullptr) { - const char *header = (isReadOnly && maxReader_ != 0) ? "readers_" : "writers_"; - container->Dump(header, transCount_ + isInTransaction_); - return nullptr; - } - return Convert2AutoConn(node); -} - -std::shared_ptr ConnectionPool::AcquireRef(bool isReadOnly, std::chrono::milliseconds ms) -{ - if (maxReader_ != 0) { - return Acquire(isReadOnly, ms); - } - auto node = writers_.Acquire(ms); - if (node == nullptr) { - writers_.Dump("writers_", transCount_ + isInTransaction_); - return nullptr; - } - auto conn = node->connect_; - writers_.Release(node); - return {conn.get(), [pool = weak_from_this(), conn](Connection *) { - auto realPool = pool.lock(); - if (realPool == nullptr) { - return; - } - realPool->writers_.cond_.notify_all(); - }}; -} - -void ConnectionPool::ReleaseNode(std::shared_ptr node, bool reuse) -{ - if (node == nullptr) { - return; - } - auto now = steady_clock::now(); - auto timeout = now > (failedTime_.load() + minutes(CHECK_POINT_INTERVAL)) || now < failedTime_.load() || - failedTime_.load() == steady_clock::time_point(); - auto transCount = transCount_ + isInTransaction_; - auto remainCount = reuse ? transCount : transCount - 1; - auto errCode = node->Unused(remainCount, timeout); - if (errCode == E_DATABASE_BUSY) { - writers_.Dump("WAL writers_", transCount); - readers_.Dump("WAL readers_", transCount); - } - LOG_DEBUG( - "ConnectionPool::ReleaseNode reuse=%{public}d,timeout=%{public}d,remainCount=%{public}d,isWriter=%{public}d", - reuse, timeout, remainCount, node->IsWriter()); - - if (node->IsWriter() && errCode != E_NOT_SUPPORT) { - failedTime_ = errCode != E_OK ? now : steady_clock::time_point(); - } - - auto &container = node->IsWriter() ? writers_ : readers_; - if (reuse) { - container.Release(node); - } else { - container.Drop(node); - } -} - -int ConnectionPool::RestartReaders() -{ - readers_.Clear(); - auto [errCode, node] = readers_.Initialize( - [this]() { return Connection::Create(config_, false); }, maxReader_, config_.GetReadTime(), maxReader_ == 0); - return errCode; -} - -int32_t ConnectionPool::Dump(bool isWriter, const char *header) -{ - Container *container = (isWriter || maxReader_ == 0) ? &writers_ : &readers_; - container->Dump(header, transCount_ + isInTransaction_); - return E_OK; -} - -ConnectionPool::ConnNode::ConnNode(std::shared_ptr conn) : connect_(std::move(conn)) -{ -} - -std::shared_ptr ConnectionPool::ConnNode::GetConnect() -{ - tid_ = gettid(); - time_ = steady_clock::now(); - return connect_; -} - -int64_t ConnectionPool::ConnNode::GetUsingTime() const -{ - auto time = steady_clock::now() - time_; - return duration_cast(time).count(); -} - -int32_t ConnectionPool::ConnNode::Unused(int32_t count, bool timeout) -{ - time_ = steady_clock::now(); - if (connect_ == nullptr) { - return E_OK; - } - time_ = steady_clock::now(); - if (!connect_->IsWriter()) { - tid_ = 0; - } - return E_OK; -} - -bool ConnectionPool::ConnNode::IsWriter() const -{ - if (connect_ != nullptr) { - return connect_->IsWriter(); - } - return false; -} - -std::pair> ConnectionPool::Container::Initialize( - Creator creator, int32_t max, int32_t timeout, bool disable, bool acquire) -{ - std::shared_ptr connNode = nullptr; - { - std::unique_lock lock(mutex_); - disable_ = disable; - max_ = max; - creator_ = std::move(creator); - timeout_ = std::chrono::seconds(timeout); - for (int i = 0; i < max; ++i) { - auto errCode = ExtendNode(); - if (errCode != E_OK) { - nodes_.clear(); - details_.clear(); - return { errCode, nullptr }; - } - } - - if (acquire && count_ > 0) { - connNode = nodes_.back(); - nodes_.pop_back(); - count_--; - } - } - cond_.notify_all(); - return { E_OK, connNode }; -} - -std::shared_ptr ConnectionPool::Container::Acquire(std::chrono::milliseconds milliS) -{ - auto interval = (milliS == INVALID_TIME) ? timeout_ : milliS; - std::unique_lock lock(mutex_); - LOG_DEBUG("count %{public}d max %{public}d total %{public}d left %{public}d right%{public}d", count_, max_, total_, - left_, right_); - if (max_ == 0) { - return nullptr; - } - auto waiter = [this]() -> bool { - if (count_ > 0) { - return true; - } - - if (disable_) { - return false; - } - return ExtendNode() == E_OK; - }; - if (cond_.wait_for(lock, interval, waiter)) { - if (nodes_.empty()) { - LOG_ERROR("nodes is empty.count %{public}d max %{public}d total %{public}d left %{public}d right%{public}d", - count_, max_, total_, left_, right_); - count_ = 0; - return nullptr; - } - auto node = nodes_.back(); - nodes_.pop_back(); - count_--; - return node; - } - return nullptr; -} - -std::pair> ConnectionPool::Container::Create() -{ - std::unique_lock lock(mutex_); - if (creator_ == nullptr) { - return { E_NOT_SUPPORT, nullptr }; - } - - auto [errCode, conn] = creator_(); - if (conn == nullptr) { - return { errCode, nullptr }; - } - - auto node = std::make_shared(conn); - if (node == nullptr) { - return { E_ERROR, nullptr }; - } - node->id_ = MIN_TRANS_ID + trans_; - conn->SetId(node->id_); - details_.push_back(node); - trans_++; - return { E_OK, node }; -} - -int32_t ConnectionPool::Container::ExtendNode() -{ - if (creator_ == nullptr) { - return E_ERROR; - } - auto [errCode, conn] = creator_(); - if (conn == nullptr) { - return errCode; - } - auto node = std::make_shared(conn); - node->id_ = right_++; - conn->SetId(node->id_); - nodes_.push_back(node); - details_.push_back(node); - count_++; - total_++; - return E_OK; -} - -void ConnectionPool::Container::Disable() -{ - disable_ = true; - cond_.notify_one(); -} - -void ConnectionPool::Container::Enable() -{ - disable_ = false; - cond_.notify_one(); -} - -int32_t ConnectionPool::Container::Release(std::shared_ptr node) -{ - { - std::unique_lock lock(mutex_); - if (node->id_ < left_ || node->id_ >= right_) { - return E_OK; - } - if (count_ == max_) { - total_ = total_ > count_ ? total_ - 1 : count_; - RelDetails(node); - } else { - nodes_.push_front(node); - count_++; - } - } - cond_.notify_one(); - return E_OK; -} - -int32_t ConnectionPool::Container::Drop(std::shared_ptr node) -{ - { - std::unique_lock lock(mutex_); - RelDetails(node); - } - cond_.notify_one(); - return E_OK; -} - -int32_t ConnectionPool::Container::RelDetails(std::shared_ptr node) -{ - for (auto it = details_.begin(); it != details_.end();) { - auto detailNode = it->lock(); - if (detailNode == nullptr || detailNode->id_ == node->id_) { - it = details_.erase(it); - } else { - it++; - } - } - return E_OK; -} - -int32_t ConnectionPool::Container::Clear() -{ - std::list> nodes; - std::list> details; - { - std::unique_lock lock(mutex_); - nodes = std::move(nodes_); - details = std::move(details_); - disable_ = true; - total_ = 0; - count_ = 0; - if (right_ > MAX_RIGHT) { - right_ = 0; - } - left_ = right_; - creator_ = nullptr; - } - nodes.clear(); - details.clear(); - LOG_DEBUG( - "Container::Clear success count=%{public}d, max=%{public}d, total=%{public}d, left=%{public}d, " - "right=%{public}d", count_, max_, total_, left_, right_); - return 0; -} - -bool ConnectionPool::Container::IsFull() -{ - std::unique_lock lock(mutex_); - return total_ == count_; -} - -int32_t ConnectionPool::Container::Dump(const char *header, int32_t count) -{ - std::string info; - std::vector> details; - std::string title = "B_M_T_C[" + std::to_string(count) + "," + std::to_string(max_) + "," + - std::to_string(total_) + "," + std::to_string(count_) + "]"; - { - std::unique_lock lock(mutex_); - details.reserve(details_.size()); - for (auto &detail : details_) { - auto node = detail.lock(); - if (node == nullptr) { - continue; - } - details.push_back(node); - } - } - - for (auto &node : details) { - info.append("<") - .append(std::to_string(node->id_)) - .append(",") - .append(std::to_string(node->tid_)) - .append(",") - .append(std::to_string(node->GetUsingTime())) - .append(">"); - // 256 represent that limit to info length - if (info.size() > 256) { - LOG_WARN("%{public}s %{public}s:%{public}s", header, title.c_str(), info.c_str()); - info.clear(); - } - } - LOG_WARN("%{public}s %{public}s:%{public}s", header, title.c_str(), info.c_str()); - return 0; -} -} // namespace OHOS::DistributedDataAip \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/src/db_store_impl.cpp b/relational_store/frameworks/native/gdb/src/db_store_impl.cpp deleted file mode 100644 index bb7808dc3c123d093f7eaf1a37cff142a5665ed6..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/src/db_store_impl.cpp +++ /dev/null @@ -1,187 +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. - */ -#define LOG_TAG "GdbStore" -#include "db_store_impl.h" - -#include - -#include "connection.h" -#include "db_trace.h" -#include "gdb_errors.h" -#include "gdb_transaction.h" -#include "gdb_utils.h" -#include "logger.h" -#include "transaction_impl.h" - -namespace OHOS::DistributedDataAip { - -constexpr int32_t MAX_GQL_LEN = 1024 * 1024; - -DBStoreImpl::DBStoreImpl(StoreConfig config) : config_(std::move(config)) -{ -} - -DBStoreImpl::~DBStoreImpl() -{ - LOG_DEBUG("DBStoreImpl enter"); - Close(); -} - -std::shared_ptr DBStoreImpl::GetConnectionPool() -{ - std::lock_guard lock(mutex_); - return connectionPool_; -} - -void DBStoreImpl::SetConnectionPool(std::shared_ptr connectionPool) -{ - std::lock_guard lock(mutex_); - connectionPool_ = connectionPool; -} - -int32_t DBStoreImpl::InitConn() -{ - if (GetConnectionPool() != nullptr) { - LOG_INFO("connectionPool_ is not nullptr"); - return E_OK; - } - int errCode; - auto connectionPool = ConnectionPool::Create(config_, errCode); - if (errCode != E_OK || connectionPool == nullptr) { - LOG_ERROR("Create conn failed, ret=%{public}d", errCode); - return errCode; - } - SetConnectionPool(connectionPool); - return E_OK; -} - -std::pair> DBStoreImpl::QueryGql(const std::string &gql) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - if (gql.empty() || gql.length() > MAX_GQL_LEN) { - LOG_ERROR("Gql is empty or length is too long."); - return { E_INVALID_ARGS, nullptr }; - } - if (GdbUtils::IsTransactionGql(gql)) { - LOG_ERROR("Transaction related statements are not supported."); - return { E_INVALID_ARGS, nullptr }; - } - auto connectionPool = GetConnectionPool(); - if (connectionPool == nullptr) { - LOG_ERROR("The connpool is nullptr."); - return { E_STORE_HAS_CLOSED, std::make_shared() }; - } - auto conn = connectionPool->AcquireRef(true); - if (conn == nullptr) { - LOG_ERROR("Get conn failed"); - return { E_ACQUIRE_CONN_FAILED, std::make_shared() }; - } - auto [ret, stmt] = conn->CreateStatement(gql, conn); - if (ret != E_OK || stmt == nullptr) { - LOG_ERROR("Create stmt failed, ret=%{public}d", ret); - return { ret, std::make_shared() }; - } - - auto result = std::make_shared(); - ret = result->InitData(stmt); - if (ret != E_OK) { - LOG_ERROR("Get FullResult failed, ret=%{public}d", ret); - return { ret, std::make_shared() }; - } - - return { E_OK, result }; -} - -std::pair> DBStoreImpl::ExecuteGql(const std::string &gql) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - if (gql.empty() || gql.length() > MAX_GQL_LEN) { - LOG_ERROR("Gql is empty or length is too long."); - return { E_INVALID_ARGS, std::make_shared() }; - } - if (GdbUtils::IsTransactionGql(gql)) { - LOG_ERROR("Transaction related statements are not supported."); - return { E_INVALID_ARGS, std::make_shared() }; - } - auto connectionPool = GetConnectionPool(); - if (connectionPool == nullptr) { - LOG_ERROR("The connpool is nullptr."); - return { E_STORE_HAS_CLOSED, std::make_shared() }; - } - auto conn = connectionPool->AcquireRef(false); - if (conn == nullptr) { - LOG_ERROR("Get conn failed"); - return { E_ACQUIRE_CONN_FAILED, std::make_shared() }; - } - auto [ret, stmt] = conn->CreateStatement(gql, conn); - if (ret != E_OK || stmt == nullptr) { - LOG_ERROR("Create stmt failed, ret=%{public}d", ret); - return { ret, std::make_shared() }; - } - ret = stmt->Step(); - if (ret != E_OK) { - LOG_ERROR("Step stmt failed, ret=%{public}d", ret); - } - return { ret, std::make_shared() }; -} - -std::pair> DBStoreImpl::CreateTransaction() -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto connectionPool = GetConnectionPool(); - if (connectionPool == nullptr) { - LOG_ERROR("The connpool is nullptr."); - return { E_STORE_HAS_CLOSED, nullptr }; - } - auto [ret, conn] = connectionPool->CreateTransConn(); - if (ret != E_OK || conn == nullptr) { - LOG_ERROR("Get conn failed"); - return { ret, nullptr }; - } - std::shared_ptr trans; - std::tie(ret, trans) = TransactionImpl::Create(conn); - if (ret != E_OK || trans == nullptr) { - LOG_ERROR("Create trans failed, ret=%{public}d", ret); - return { ret, nullptr }; - } - - std::lock_guard lock(transMutex_); - for (auto it = transactions_.begin(); it != transactions_.end();) { - if (it->expired()) { - it = transactions_.erase(it); - } else { - it++; - } - } - transactions_.push_back(trans); - return { ret, trans }; -} - -int32_t DBStoreImpl::Close() -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - SetConnectionPool(nullptr); - - std::lock_guard lock(transMutex_); - for (auto &trans : transactions_) { - auto realTrans = trans.lock(); - if (realTrans) { - (void)realTrans->Close(); - } - } - transactions_ = {}; - return E_OK; -} -} // namespace OHOS::DistributedDataAip \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/src/db_store_manager.cpp b/relational_store/frameworks/native/gdb/src/db_store_manager.cpp deleted file mode 100644 index aa23280122f8859f6da57be38829ff0356e6d30c..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/src/db_store_manager.cpp +++ /dev/null @@ -1,182 +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. - */ -#define LOG_TAG "GdbStoreManager" -#include "db_store_manager.h" - -#include - -#include - -#include "gdb_errors.h" -#include "db_store_impl.h" -#include "gdb_utils.h" -#include "logger.h" -#include "security_label.h" - -namespace OHOS::DistributedDataAip { -StoreManager &StoreManager::GetInstance() -{ - static StoreManager manager; - return manager; -} - -StoreManager::StoreManager() = default; - -StoreManager::~StoreManager() -{ - Clear(); -} - -bool StoreManager::IsValidName(const std::string &name) -{ - const std::regex pattern("^[a-zA-Z0-9_]+$"); - return std::regex_match(name, pattern); -} - -bool StoreManager::IsValidSecurityLevel(const int32_t securityLevel) -{ - return securityLevel >= SecurityLevel::S1 && securityLevel <= SecurityLevel::S4; -} - -std::shared_ptr StoreManager::GetDBStore(const StoreConfig &config, int &errCode) -{ - if (!IsValidName(config.GetName())) { - LOG_ERROR("GetDBStore failed. Invalid name"); - errCode = E_GRD_INVAILD_NAME_ERR; - return nullptr; - } - if (!IsValidSecurityLevel(config.GetSecurityLevel())) { - LOG_ERROR("GetDBStore failed. Invalid securityLevel: %{public}d", config.GetSecurityLevel()); - errCode = E_INVALID_ARGS; - return nullptr; - } - std::lock_guard lock(mutex_); - auto path = config.GetFullPath(); - if (storeCache_.find(path) != storeCache_.end()) { - std::shared_ptr dbStore = storeCache_[path].lock(); - if (dbStore != nullptr) { - LOG_ERROR("GetDBStore reuse success."); - return dbStore; - } - storeCache_.erase(path); - } - // open and store DBStore - std::shared_ptr dbStore = std::make_shared(config); - errCode = dbStore->InitConn(); - if (errCode != E_OK) { - LOG_ERROR("GetDBStore InitConn failed, name=%{public}s, errCode=%{public}d", - GdbUtils::Anonymous(config.GetName()).c_str(), errCode); - return nullptr; - } - errCode = SetSecurityLabel(config); - if (errCode != E_OK) { - LOG_ERROR("GetDBStore SetSecurityLabel failed, errCode=%{public}d", errCode); - return nullptr; - } - storeCache_[path] = dbStore; - return dbStore; -} - -void StoreManager::Clear() -{ - std::lock_guard lock(mutex_); - auto iter = storeCache_.begin(); - while (iter != storeCache_.end()) { - if (auto store = iter->second.lock()) { - store->Close(); - } - iter = storeCache_.erase(iter); - } - storeCache_.clear(); -} - -bool StoreManager::Delete(const std::string &path) -{ - LOG_DEBUG("Delete file, path=%{public}s", GdbUtils::Anonymous(path).c_str()); - { - std::lock_guard lock(mutex_); - auto item = storeCache_.find(path); - if (item != storeCache_.end()) { - if (auto store = item->second.lock()) { - store->Close(); - } - storeCache_.erase(path); // clean invalid store ptr - } - } - - bool deleteResult = true; - for (auto &suffix : GRD_POST_FIXES) { - deleteResult = DeleteFile(path + suffix) && deleteResult; - } - return deleteResult; -} - -bool StoreManager::DeleteFile(const std::string &path) -{ - if (access(path.c_str(), 0) != 0) { - LOG_WARN("access return, path=%{public}s", GdbUtils::Anonymous(path).c_str()); - return true; - } - auto ret = remove(path.c_str()); - if (ret != 0) { - LOG_ERROR("remove file failed errno %{public}d ret %{public}d %{public}s", errno, ret, - GdbUtils::Anonymous(path).c_str()); - return false; - } - return true; -} - -int StoreManager::SetSecurityLabel(const StoreConfig &config) -{ - if (config.GetSecurityLevel() >= SecurityLevel::S1 && config.GetSecurityLevel() <= SecurityLevel::S4) { - auto toSetLevel = GetSecurityLevelValue(static_cast(config.GetSecurityLevel())); - auto errCode = - FileManagement::ModuleSecurityLabel::SecurityLabel::SetSecurityLabel(config.GetFullPath(), toSetLevel) - ? E_OK - : E_CONFIG_INVALID_CHANGE; - if (errCode != E_OK) { - auto currentLevel = GetFileSecurityLevel(config.GetFullPath()); - LOG_ERROR( - "Set security level:%{public}s -> %{public}s, result=%{public}d, errno=%{public}d, name=%{public}s.", - currentLevel.c_str(), toSetLevel.c_str(), errCode, errno, - GdbUtils::Anonymous(config.GetName()).c_str()); - } - return errCode; - } - return E_OK; -} - -std::string StoreManager::GetSecurityLevelValue(SecurityLevel securityLevel) -{ - switch (securityLevel) { - case SecurityLevel::S1: - return "s1"; - case SecurityLevel::S2: - return "s2"; - case SecurityLevel::S3: - return "s3"; - case SecurityLevel::S4: - return "s4"; - default: - return ""; - } -} - -std::string StoreManager::GetFileSecurityLevel(const std::string &filePath) -{ - return FileManagement::ModuleSecurityLabel::SecurityLabel::GetSecurityLabel(filePath); -} - -} // namespace OHOS::DistributedDataAip \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/src/edge.cpp b/relational_store/frameworks/native/gdb/src/edge.cpp deleted file mode 100644 index 1b3fb582ddea929326b1ab327ad7912f93be60fb..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/src/edge.cpp +++ /dev/null @@ -1,104 +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. - */ -#define LOG_TAG "GdbEdge" -#include - -#include "gdb_errors.h" -#include "full_result.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { -Edge::Edge() : Vertex(), sourceId_("0"), targetId_("0") -{ -} - -Edge::Edge(std::string id, std::string label, std::string sourceId, std::string targetId) - : Vertex(std::move(id), std::move(label)), sourceId_(std::move(sourceId)), targetId_(std::move(targetId)) -{ -} - -Edge::Edge(const std::shared_ptr &element, std::string sourceId, std::string targetId) - : sourceId_(std::move(sourceId)), targetId_(std::move(targetId)) -{ - if (element != nullptr) { - id_ = element->GetId(); - label_ = element->GetLabel(); - properties_ = element->GetProperties(); - } -} - -std::string Edge::GetSourceId() const -{ - return sourceId_; -} - -void Edge::SetSourceId(std::string sourceId) -{ - sourceId_ = std::move(sourceId); -} - -std::string Edge::GetTargetId() const -{ - return targetId_; -} - -void Edge::SetTargetId(std::string targetId) -{ - targetId_ = std::move(targetId); -} - -std::string Edge::GetIdFromJson(const std::string &key, const nlohmann::json &json, int32_t &errCode) -{ - if (key.empty() || (!json.at(key).is_string() && !json.at(key).is_number())) { - LOG_ERROR("edge start or end id is not number or string. jsonStr=%{public}s", json.dump().c_str()); - errCode = E_PARSE_JSON_FAILED; - return ""; - } - errCode = E_OK; - if (json.at(key).is_number()) { - auto sourceId = json.at(key).get(); - return std::to_string(sourceId); - } - if (json.at(key).is_string()) { - return json.at(key).get(); - } - errCode = E_PARSE_JSON_FAILED; - return ""; -} - -std::shared_ptr Edge::Parse(const nlohmann::json &json, int32_t &errCode) -{ - if (!json.contains(Edge::SOURCEID) || !json.contains(Edge::TARGETID)) { - LOG_ERROR("edge format error. jsonStr=%{public}s", json.dump().c_str()); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - errCode = E_OK; - std::shared_ptr element = Vertex::Parse(json, errCode); - if (errCode != E_OK || element == nullptr) { - LOG_ERROR("parse edge element failed. jsonStr=%{public}s", json.dump().c_str()); - return nullptr; - } - auto sourceId = Edge::GetIdFromJson(Edge::SOURCEID, json, errCode); - if (errCode != E_OK) { - return nullptr; - } - auto targetId = Edge::GetIdFromJson(Edge::TARGETID, json, errCode); - if (errCode != E_OK) { - return nullptr; - } - return std::make_shared(element, sourceId, targetId); -} -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/src/full_result.cpp b/relational_store/frameworks/native/gdb/src/full_result.cpp deleted file mode 100644 index fdc8a0261de31e914712e76a858c2d36de80ab39..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/src/full_result.cpp +++ /dev/null @@ -1,73 +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. - */ -#define LOG_TAG "GdbDataSet" -#include "full_result.h" - -#include "gdb_errors.h" -#include "statement.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { -int32_t FullResult::InitData(std::shared_ptr stmt) -{ - if (stmt == nullptr) { - return E_STATEMENT_EMPTY; - } - data_ = std::vector>(); - int32_t errCode = stmt->Step(); - while (errCode == E_OK) { - auto [ret, oneResult] = GetRow(stmt); - if (ret != E_OK) { - return ret; - } - data_.emplace_back(oneResult); - errCode = stmt->Step(); - } - return (errCode == E_GRD_NO_DATA) ? E_OK : errCode; -} - -std::vector> FullResult::GetAllData() const -{ - return data_; -} -std::pair> FullResult::GetRow(std::shared_ptr stmt) -{ - std::unordered_map res; - if (stmt == nullptr) { - return { E_STATEMENT_EMPTY, res }; - } - auto columnCount = stmt->GetColumnCount(); - if (columnCount == 0) { - LOG_ERROR("GetKeys failed ret=%{public}d.", E_NO_DATA); - return { E_NO_DATA, res }; - } - - for (uint32_t i = 0; i < columnCount; i++) { - auto [ret, key] = stmt->GetColumnName(i); - if (ret != E_OK) { - LOG_ERROR("GetKeys failed ret=%{public}d.", ret); - return { ret, res }; - } - auto [err, value] = stmt->GetColumnValue(i); - if (err != E_OK) { - LOG_ERROR("GetValue failed, key=%{public}s, ret=%{public}d.", key.c_str(), err); - return { err, res }; - } - res.emplace(key, value); - } - return { E_OK, res }; -} - -} // namespace OHOS::DistributedDataAip \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/src/gdb_utils.cpp b/relational_store/frameworks/native/gdb/src/gdb_utils.cpp deleted file mode 100644 index ee35ad149873c8ae774700c35c330789ec24c4b3..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/src/gdb_utils.cpp +++ /dev/null @@ -1,186 +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. - */ - -#define LOG_TAG "RdbGqlUtils" -#include "gdb_utils.h" - -#include -#include -#include -#include - -#include "gdb_errors.h" - -namespace OHOS::DistributedDataAip { -constexpr int32_t CONTINUOUS_DIGITS_MINI_SIZE = 5; -constexpr int32_t FILE_PATH_MINI_SIZE = 6; -constexpr int32_t AREA_MINI_SIZE = 4; -constexpr int32_t AREA_OFFSET_SIZE = 5; -constexpr int32_t PRE_OFFSET_SIZE = 1; -constexpr int32_t PREFIX_POS = 0; -constexpr int32_t PREFIX_LEN = 3; - -bool GdbUtils::IsTransactionGql(const std::string &gql) -{ - auto prefix = gql.substr(PREFIX_POS, PREFIX_LEN); - if (prefix == "STA" || prefix == "COM" || prefix == "ROL") { - return true; - } - return false; -} - -int GdbUtils::CreateDirectory(const std::string &databaseDir) -{ - std::string tempDirectory = databaseDir; - std::vector directories; - - size_t pos = tempDirectory.find('/'); - while (pos != std::string::npos) { - std::string directory = tempDirectory.substr(0, pos); - directories.push_back(directory); - tempDirectory = tempDirectory.substr(pos + 1); - pos = tempDirectory.find('/'); - } - directories.push_back(tempDirectory); - - std::string databaseDirectory; - for (const std::string &directory : directories) { - databaseDirectory += "/" + directory; - if (access(databaseDirectory.c_str(), F_OK) != 0) { - if (mkdir(databaseDirectory.c_str(), DIR_RWXRWS__X)) { - return E_CREATE_FOLDER_FAIT; - } - } - } - return E_OK; -} - -std::string GdbUtils::Anonymous(const std::string &srcFile) -{ - auto pre = srcFile.find("/"); - auto end = srcFile.rfind("/"); - if (pre == std::string::npos || end - pre < FILE_PATH_MINI_SIZE) { - return GetAnonymousName(srcFile); - } - auto path = srcFile.substr(pre, end - pre); - auto area = path.find("/el"); - if (area == std::string::npos || area + AREA_MINI_SIZE > path.size()) { - path = ""; - } else if (area + AREA_OFFSET_SIZE < path.size()) { - path = path.substr(area, AREA_MINI_SIZE) + "/***"; - } else { - path = path.substr(area, AREA_MINI_SIZE); - } - std::string fileName = srcFile.substr(end); // rdb file name - fileName = GetAnonymousName(fileName); - return srcFile.substr(0, pre + PRE_OFFSET_SIZE) + "***" + path + fileName; -} - -std::string GdbUtils::GetAnonymousName(const std::string &fileName) -{ - std::vector alnum; - std::vector noAlnum; - std::string alnumStr; - std::string noAlnumStr; - for (const auto &letter : fileName) { - if (isxdigit(letter)) { - if (!noAlnumStr.empty()) { - noAlnum.push_back(noAlnumStr); - noAlnumStr.clear(); - alnum.push_back(""); - } - alnumStr += letter; - } else { - if (!alnumStr.empty()) { - alnum.push_back(alnumStr); - alnumStr.clear(); - noAlnum.push_back(""); - } - noAlnumStr += letter; - } - } - if (!alnumStr.empty()) { - alnum.push_back(alnumStr); - noAlnum.push_back(""); - } - if (!noAlnumStr.empty()) { - noAlnum.push_back(alnumStr); - alnum.push_back(""); - } - std::string res = ""; - for (size_t i = 0; i < alnum.size(); ++i) { - res += (AnonyDigits(alnum[i]) + noAlnum[i]); - } - return res; -} - -std::string GdbUtils::AnonyDigits(const std::string &fileName) -{ - std::string::size_type digitsNum = fileName.size(); - if (digitsNum < CONTINUOUS_DIGITS_MINI_SIZE) { - return fileName; - } - constexpr std::string::size_type longDigits = 7; - std::string::size_type endDigitsNum = 4; - std::string::size_type shortEndDigitsNum = 3; - std::string name = fileName; - std::string last = ""; - if (digitsNum >= CONTINUOUS_DIGITS_MINI_SIZE && digitsNum < longDigits) { - last = name.substr(name.size() - shortEndDigitsNum); - } else { - last = name.substr(name.size() - endDigitsNum); - } - - return "***" + last; -} - -void GdbUtils::ClearAndZeroString(std::string &str) -{ - str.clear(); - std::fill(str.begin(), str.end(), char(0)); -} - -std::string GdbUtils::GetConfigStr(const std::vector &keys, bool isEncrypt) -{ - std::string config = "{"; - if (isEncrypt) { - const size_t keyBuffSize = keys.size() * 2 + 1; // 2 hex number can represent a uint8_t, 1 is for '\0' - std::vector keyBuff(keyBuffSize); - config += "\"isEncrypted\":1,"; - config += "\"hexPassword\":\""; - config += GetEncryptKey(keys, keyBuff.data(), keyBuffSize); - config += "\","; - keyBuff.assign(keyBuffSize, 0); - } - config += GRD_OPEN_CONFIG_STR; - config += "}"; - return config; -} - -const char *GdbUtils::GetEncryptKey(const std::vector &encryptedKey, char outBuff[], size_t outBufSize) -{ - char *buffer = nullptr; - auto keySize = encryptedKey.size(); - for (size_t i = 0; i < keySize; i++) { - buffer = (char *)(outBuff + i * 2); // each uint8_t will convert to 2 hex char - // each uint8_t will convert to 2 hex char - errno_t err = snprintf_s(buffer, outBufSize - i * 2, outBufSize - i * 2, "%02x", encryptedKey[i]); - if (err < 0) { - return nullptr; - } - } - return outBuff; -} -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/src/graph_connection.cpp b/relational_store/frameworks/native/gdb/src/graph_connection.cpp deleted file mode 100644 index a0a0fcf3c41dc3750fcbd184c5590a994e02b4eb..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/src/graph_connection.cpp +++ /dev/null @@ -1,170 +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. - */ -#define LOG_TAG "GdbConn" -#include "graph_connection.h" - -#include - -#include -#include - -#include "gdb_errors.h" -#include "gdb_utils.h" -#include "graph_statement.h" -#include "logger.h" -#include "rdb_security_manager.h" -#include "securec.h" - -namespace OHOS::DistributedDataAip { -__attribute__((used)) -const int32_t GraphConnection::regCreator_ = Connection::RegisterCreator(DBType::DB_GRAPH, GraphConnection::Create); - -std::pair> GraphConnection::Create(const StoreConfig &config, bool isWriter) -{ - LOG_DEBUG("GraphConnection::Create start, name=%{public}s, isWriter=%{public}d", - GdbUtils::Anonymous(config.GetName()).c_str(), isWriter); - std::pair> result = { E_INNER_ERROR, nullptr }; - auto &[errCode, conn] = result; - for (size_t i = 0; i < ITERS_COUNT; i++) { - std::shared_ptr connection = std::make_shared(config, isWriter); - if (connection == nullptr) { - LOG_ERROR("Open new failed, connection is nullptr. name=%{public}s", - GdbUtils::Anonymous(config.GetName()).c_str()); - return result; - } - errCode = connection->InnerOpen(config); - if (errCode == E_OK) { - conn = connection; - break; - } - if (errCode == E_GRD_INVALID_ARGS && connection->IsEncryptInvalidChanged(config)) { - errCode = E_CONFIG_INVALID_CHANGE; - break; - } - } - return result; -} - -GraphConnection::GraphConnection(const StoreConfig &config, bool isWriter) : config_(config), isWriter_(isWriter) -{ -} - -GraphConnection::~GraphConnection() -{ - LOG_DEBUG("enter"); - if (dbHandle_ != nullptr) { - int errCode = GrdAdapter::Close(dbHandle_, 0); - if (errCode != E_OK) { - LOG_ERROR("could not close database, err=%{public}d", errCode); - } - dbHandle_ = nullptr; - } -} - -int GraphConnection::InnerOpen(const StoreConfig &config) -{ - std::string dbPath = config.GetFullPath(); - std::vector newKey = config.GetNewEncryptKey(); - if (!newKey.empty()) { - // NewKey exists, oldKey has expired, ResetKey is required - newKey.assign(newKey.size(), 0); - auto errCode = ResetKey(config); - if (errCode != E_OK) { - LOG_ERROR("Can not reset key %{public}d.", errCode); - return errCode; - } - } - std::vector key = config.GetEncryptKey(); - std::string configJson = GdbUtils::GetConfigStr(key, config.IsEncrypt()); - LOG_DEBUG( - "GraphConnection::InnerOpen: dbPath=%{public}s, configJson=%{public}s", - GdbUtils::Anonymous(dbPath).c_str(), configJson.c_str()); - int32_t errCode = GrdAdapter::Open(dbPath.c_str(), configJson.c_str(), GRD_DB_OPEN_CREATE, &dbHandle_); - if (errCode == E_GRD_PASSWORD_NEED_REKEY) { - // Upgrading from non encrypted to encrypted, requires Rekey first and then Open - errCode = GrdAdapter::Rekey(dbPath.c_str(), GdbUtils::GetConfigStr({}, false).c_str(), key); - if (errCode != E_OK) { - key.assign(key.size(), 0); - GdbUtils::ClearAndZeroString(configJson); - LOG_ERROR("Can not rekey graph db %{public}d.", errCode); - return errCode; - } - errCode = GrdAdapter::Open(dbPath.c_str(), configJson.c_str(), GRD_DB_OPEN_CREATE, &dbHandle_); - } - key.assign(key.size(), 0); - GdbUtils::ClearAndZeroString(configJson); - if (errCode != E_OK) { - LOG_ERROR("Can not open graph db, name=%{public}s, errCode=%{public}d.", - GdbUtils::Anonymous(config.GetName()).c_str(), errCode); - return errCode; - } - return errCode; -} - -std::pair GraphConnection::CreateStatement( - const std::string &gql, std::shared_ptr connection) -{ - int32_t ret; - auto stmt = std::make_shared(dbHandle_, gql, connection, ret); - if (ret != E_OK) { - return { ret, nullptr }; - } - return { ret, stmt }; -} - -DBType GraphConnection::GetDBType() const -{ - return DBType::DB_GRAPH; -} - -bool GraphConnection::IsWriter() const -{ - return isWriter_; -} - -int32_t GraphConnection::ResetKey(const StoreConfig &config) -{ - if (!IsWriter()) { - return E_OK; - } - std::string dbPath = config.GetFullPath(); - std::vector key = config.GetEncryptKey(); - std::vector newKey = config.GetNewEncryptKey(); - std::string configStr = GdbUtils::GetConfigStr(key, config.IsEncrypt()); - auto errCode = GrdAdapter::Rekey(dbPath.c_str(), configStr.c_str(), newKey); - GdbUtils::ClearAndZeroString(configStr); - key.assign(key.size(), 0); - newKey.assign(newKey.size(), 0); - if (errCode != E_OK) { - LOG_ERROR("Rekey failed, err = %{public}d, errno = %{public}d", errCode, errno); - NativeRdb::RdbSecurityManager::GetInstance().DelKeyFile( - config.GetFullPath(), NativeRdb::RdbSecurityManager::KeyFileType::PUB_KEY_FILE_NEW_KEY); - return errCode; - } - config.ChangeEncryptKey(); - return E_OK; -} - -bool GraphConnection::IsEncryptInvalidChanged(const StoreConfig &config) -{ - if (config.GetFullPath().empty() || config.IsEncrypt()) { - LOG_WARN("Config has no path or config is encrypted, path: %{public}s, isEncrypt: %{public}d", - GdbUtils::Anonymous(config.GetFullPath()).c_str(), config.IsEncrypt()); - return false; - } - return NativeRdb::RdbSecurityManager::GetInstance().IsKeyFileExists(config.GetFullPath(), - NativeRdb::RdbSecurityManager::KeyFileType::PUB_KEY_FILE); -} -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/src/graph_statement.cpp b/relational_store/frameworks/native/gdb/src/graph_statement.cpp deleted file mode 100644 index d1d0b3ce4beed4e7e85cb296c08271bac1891c90..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/src/graph_statement.cpp +++ /dev/null @@ -1,200 +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. - */ -#define LOG_TAG "GdbStmt" -#include "graph_statement.h" - -#include - -#include "gdb_errors.h" -#include "connection.h" -#include "full_result.h" -#include "grd_error.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { -GraphStatement::GraphStatement(GRD_DB *db, const std::string &gql, std::shared_ptr conn, int32_t &errCode) - : conn_(conn), gql_(gql), dbHandle_(db) -{ - errCode = E_OK; - if (db == nullptr || gql.empty()) { - errCode = E_PREPARE_CHECK_FAILED; - return; - } - - errCode = GrdAdapter::Prepare(dbHandle_, gql_.c_str(), gql_.size(), &stmtHandle_, nullptr); - if (errCode != E_OK) { - LOG_ERROR("GRD_GqlPrepare failed. ret=%{public}d", errCode); - if (stmtHandle_ != nullptr) { - GrdAdapter::Finalize(stmtHandle_); - } - } -} - -GraphStatement::~GraphStatement() -{ - Finalize(); -} - -int32_t GraphStatement::Prepare() -{ - if (dbHandle_ == nullptr || gql_.empty()) { - return E_PREPARE_CHECK_FAILED; - } - - int32_t ret = GrdAdapter::Prepare(dbHandle_, gql_.c_str(), gql_.size(), &stmtHandle_, nullptr); - if (ret != E_OK) { - LOG_ERROR("GRD_GqlPrepare failed. ret=%{public}d", ret); - } - return ret; -} - -int32_t GraphStatement::Step() -{ - if (stmtHandle_ == nullptr) { - return E_STEP_CHECK_FAILED; - } - int32_t ret = GrdAdapter::Step(stmtHandle_); - if (ret != E_OK && ret != E_GRD_NO_DATA) { - LOG_ERROR("GRD_GqlStep failed. ret=%{public}d", ret); - } - return ret; -} - -int32_t GraphStatement::Finalize() -{ - if (stmtHandle_ == nullptr) { - return E_OK; - } - int32_t ret = GrdAdapter::Finalize(stmtHandle_); - if (ret != E_OK) { - LOG_ERROR("GRD_GqlFinalize failed. ret=%{public}d", ret); - return ret; - } - stmtHandle_ = nullptr; - gql_ = ""; - return E_OK; -} - -uint32_t GraphStatement::GetColumnCount() const -{ - if (stmtHandle_ == nullptr) { - return E_STATEMENT_EMPTY; - } - return GrdAdapter::ColumnCount(stmtHandle_); -} - -std::pair GraphStatement::GetColumnName(int32_t index) const -{ - if (stmtHandle_ == nullptr) { - return { E_STATEMENT_EMPTY, "" }; - } - const char *name = GrdAdapter::ColumnName(stmtHandle_, index); - if (name == nullptr) { - LOG_ERROR("column_name is null. index=%{public}d", index); - return { E_GETTED_COLNAME_EMPTY, "" }; - } - return { E_OK, name }; -} - -std::pair GraphStatement::GetColumnType(int32_t index) const -{ - if (stmtHandle_ == nullptr) { - return { E_STATEMENT_EMPTY, ColumnType::TYPE_NULL }; - } - GRD_DbDataTypeE type = GrdAdapter::ColumnType(stmtHandle_, index); - return { E_OK, GrdAdapter::TransColType(type) }; -} - -GraphValue GraphStatement::ParseJsonStr(const std::string &jsonStr, int32_t &errCode) -{ - if (jsonStr.empty()) { - LOG_WARN("parse json string. jsonStr is empty"); - errCode = E_OK; - return nullptr; - } - nlohmann::json json = nlohmann::json::parse(jsonStr, nullptr, false); - if (json.is_discarded()) { - LOG_ERROR("parse json string failed. jsonStr=%{public}s", jsonStr.c_str()); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - - errCode = E_OK; - if (json.is_null()) { - LOG_WARN("parse json string. jsonStr is empty"); - return nullptr; - } - if (!json.is_object()) { - LOG_ERROR("json format error. jsonStr=%{public}s", jsonStr.c_str()); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - - if (json.contains(Path::SEGMENTS)) { - return Path::Parse(json, errCode); - } - if (json.contains(Edge::SOURCEID) && json.contains(Edge::TARGETID)) { - return Edge::Parse(json, errCode); - } - return Vertex::Parse(json, errCode); -} - -std::pair GraphStatement::GetColumnValue(int32_t index) const -{ - if (stmtHandle_ == nullptr) { - return { E_STATEMENT_EMPTY, nullptr }; - } - ColumnType type = GetColumnType(index).second; - GraphValue value; - - auto ret = 0; - switch (type) { - case ColumnType::TYPE_INTEGER: - value = GrdAdapter::ColumnInt(stmtHandle_, index); - break; - case ColumnType::TYPE_FLOAT: - value = GrdAdapter::ColumnDouble(stmtHandle_, index); - break; - case ColumnType::TYPE_JSONSTR: { - auto text = ""; - text = GrdAdapter::ColumnText(stmtHandle_, index); - value = ParseJsonStr(text, ret); - if (ret != E_OK) { - LOG_ERROR("ParseJsonStr failed. index=%{public}d, ret=%{public}d", index, ret); - return { ret, nullptr }; - } - break; - } - case ColumnType::TYPE_TEXT: - value = GrdAdapter::ColumnText(stmtHandle_, index); - break; - case ColumnType::TYPE_BLOB: - LOG_ERROR("not support blob type. index=%{public}d", index); - return { E_NOT_SUPPORT, nullptr }; - case ColumnType::TYPE_FLOATVECTOR: - LOG_ERROR("not support float vector type. index=%{public}d", index); - return { E_NOT_SUPPORT, nullptr }; - case ColumnType::TYPE_NULL: - default: - value = nullptr; - } - return { E_OK, value }; -} - -bool GraphStatement::IsReady() const -{ - return !gql_.empty() && stmtHandle_ != nullptr && dbHandle_ != nullptr; -} -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/src/path.cpp b/relational_store/frameworks/native/gdb/src/path.cpp deleted file mode 100644 index d390b319d052658590c0f6d64121018a312c276c..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/src/path.cpp +++ /dev/null @@ -1,111 +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. - */ -#define LOG_TAG "GdbPath" -#include "path.h" - -#include "gdb_errors.h" -#include "path_segment.h" -#include "grd_error.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { -Path::Path(std::shared_ptr start, std::shared_ptr end) : start_(start), end_(end) -{ - pathLen_ = 0; -} - -Path::Path(std::shared_ptr start, std::shared_ptr end, uint32_t pathLen, - std::vector> segments) - : pathLen_(pathLen), start_(start), end_(end), segments_(std::move(segments)) -{ -} - -Path::Path() : pathLen_(0), start_(nullptr), end_(nullptr), segments_() -{ -} - -uint32_t Path::GetPathLength() const -{ - return pathLen_; -} - -void Path::SetPathLength(uint32_t pathLen) -{ - this->pathLen_ = pathLen; -} - -std::shared_ptr Path::GetStart() const -{ - return start_; -} - -void Path::SetStart(std::shared_ptr start) -{ - this->start_ = start; -} - -std::shared_ptr Path::GetEnd() const -{ - return end_; -} - -void Path::SetEnd(std::shared_ptr end) -{ - this->end_ = end; -} - -const std::vector> &Path::GetSegments() const -{ - return segments_; -} - -std::shared_ptr Path::Parse(const nlohmann::json &json, int32_t &errCode) -{ - if (!json.contains(Path::PATHLEN) || !json.contains(Path::START) || !json.at(Path::START).is_object() || - !json.contains(Path::END) || !json.at(Path::END).is_object() || !json.contains(Path::SEGMENTS) || - !json.at(Path::SEGMENTS).is_array() || !json.at(Path::PATHLEN).is_number_unsigned()) { - LOG_ERROR("path format error. jsonStr=%{public}s", json.dump().c_str()); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - errCode = E_OK; - - auto pathLen = json.at(Path::PATHLEN).get(); - auto start = Vertex::Parse(json.at(Path::START), errCode); - if (errCode != E_OK) { - return nullptr; - } - - auto end = Vertex::Parse(json.at(Path::END), errCode); - if (errCode != E_OK) { - return nullptr; - } - auto pathSegments = std::vector>(); - for (const auto &item : json.at(Path::SEGMENTS)) { - if (!item.is_object()) { - LOG_ERROR("pathItem format error. jsonStr=%{public}s", json.dump().c_str()); - return nullptr; - } - auto pathSegment = PathSegment::Parse(item, errCode); - if (errCode != E_OK) { - return nullptr; - } - pathSegments.push_back(pathSegment); - } - errCode = E_OK; - return std::make_shared(start, end, pathLen, pathSegments); - ; -} -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/src/path_segment.cpp b/relational_store/frameworks/native/gdb/src/path_segment.cpp deleted file mode 100644 index a4c501eb63aff826abe9b896a80c3642f6b945df..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/src/path_segment.cpp +++ /dev/null @@ -1,94 +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. - */ -#define LOG_TAG "GdbPath" -#include "path_segment.h" - -#include "gdb_errors.h" -#include "grd_error.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { -PathSegment::PathSegment() : sourceVertex_(nullptr), edge_(nullptr), targetVertex_(nullptr) -{ -} - -PathSegment::PathSegment( - std::shared_ptr sourceVertex, std::shared_ptr targetVertex, std::shared_ptr edge) - : sourceVertex_(sourceVertex), edge_(edge), targetVertex_(targetVertex) -{ -} - -std::shared_ptr PathSegment::GetSourceVertex() const -{ - return sourceVertex_; -} - -void PathSegment::SetSourceVertex(std::shared_ptr vertex) -{ - sourceVertex_ = vertex; -} - -std::shared_ptr PathSegment::GetEdge() const -{ - return edge_; -} - -void PathSegment::SetEdge(std::shared_ptr edge) -{ - this->edge_ = edge; -} - -std::shared_ptr PathSegment::GetTargetVertex() const -{ - return targetVertex_; -} - -void PathSegment::SetTargetVertex(std::shared_ptr vertex) -{ - targetVertex_ = vertex; -} - -std::shared_ptr PathSegment::Parse(const nlohmann::json &json, int32_t &errCode) -{ - if (!json.contains(PathSegment::SOURCE_VERTEX) || !json.at(PathSegment::SOURCE_VERTEX).is_object() || - !json.contains(PathSegment::EDGE) || !json.at(PathSegment::EDGE).is_object() || - !json.contains(PathSegment::TARGET_VERTEX) || !json.at(PathSegment::TARGET_VERTEX).is_object()) { - LOG_ERROR("pathSegment format error. jsonStr=%{public}s", json.dump().c_str()); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - errCode = E_OK; - std::shared_ptr segment = std::make_shared(); - auto sourceVertex = Vertex::Parse(json.at(PathSegment::SOURCE_VERTEX), errCode); - if (errCode != E_OK) { - return nullptr; - } - segment->SetSourceVertex(sourceVertex); - - auto edge = Edge::Parse(json.at(PathSegment::EDGE), errCode); - if (errCode != E_OK) { - return nullptr; - } - segment->SetEdge(edge); - - auto targetVertex = Vertex::Parse(json.at(PathSegment::TARGET_VERTEX), errCode); - if (errCode != E_OK) { - return nullptr; - } - segment->SetTargetVertex(targetVertex); - - return segment; -} -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/src/store_config.cpp b/relational_store/frameworks/native/gdb/src/store_config.cpp deleted file mode 100644 index cda3da4cbf56760d358a269e5a66a79485c8ff1e..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/src/store_config.cpp +++ /dev/null @@ -1,196 +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. - */ -#define LOG_TAG "GdbStoreConfig" -#include - -#include "gdb_errors.h" -#include "gdb_store_config.h" -#include "gdb_utils.h" -#include "logger.h" -#include "rdb_security_manager.h" - -namespace OHOS::DistributedDataAip { -StoreConfig::StoreConfig( - std::string name, std::string path, DBType dbType, bool isEncrypt, const std::vector &encryptKey) - : name_(std::move(name)), path_(std::move(path)), dbType_(dbType), isEncrypt_(isEncrypt), encryptKey_(encryptKey) -{ -} - -StoreConfig::~StoreConfig() -{ - ClearEncryptKey(); -} - -void StoreConfig::SetName(std::string name) -{ - name_ = std::move(name); -} - -void StoreConfig::SetPath(std::string path) -{ - path_ = std::move(path); -} - -void StoreConfig::SetDbType(DBType dbType) -{ - dbType_ = dbType; -} - -void StoreConfig::SetEncryptStatus(const bool status) -{ - isEncrypt_ = status; -} - -bool StoreConfig::IsEncrypt() const -{ - return isEncrypt_; -} - -std::string StoreConfig::GetFullPath() const -{ - return path_ + "/" + name_ + ".db"; -} - -std::string StoreConfig::GetPath() const -{ - return path_; -} - -std::string StoreConfig::GetName() const -{ - return name_; -} - -DBType StoreConfig::GetDbType() const -{ - return dbType_; -} - -int32_t StoreConfig::GetIter() const -{ - return iter_; -} - -void StoreConfig::SetIter(int32_t iter) const -{ - iter_ = iter; -} - -int StoreConfig::GetWriteTime() const -{ - return writeTimeout_; -} - -void StoreConfig::SetWriteTime(int timeout) -{ - writeTimeout_ = std::max(MIN_TIMEOUT, std::min(MAX_TIMEOUT, timeout)); -} - -int StoreConfig::GetReadTime() const -{ - return readTimeout_; -} - -void StoreConfig::SetReadTime(int timeout) -{ - readTimeout_ = std::max(MIN_TIMEOUT, std::min(MAX_TIMEOUT, timeout)); -} - -int StoreConfig::GetReadConSize() const -{ - return readConSize_; -} - -void StoreConfig::SetReadConSize(int readConSize) -{ - readConSize_ = readConSize; -} - -void StoreConfig::SetSecurityLevel(int32_t securityLevel) -{ - securityLevel_ = securityLevel; -} - -int32_t StoreConfig::GetSecurityLevel() const -{ - return securityLevel_; -} - -int StoreConfig::SetBundleName(const std::string &bundleName) -{ - if (bundleName.empty()) { - return E_ERROR; - } - bundleName_ = bundleName; - return E_OK; -} - -std::string StoreConfig::GetBundleName() const -{ - return bundleName_; -} - -std::vector StoreConfig::GetEncryptKey() const -{ - return encryptKey_; -} - -std::vector StoreConfig::GetNewEncryptKey() const -{ - return newEncryptKey_; -} - -void StoreConfig::GenerateEncryptedKey() const -{ - if (!IsEncrypt()) { - return; - } - auto rdbConfig = std::make_shared(GetFullPath()); - if (rdbConfig == nullptr) { - LOG_ERROR("rdbConfig is nullptr. path:%{public}s", GdbUtils::Anonymous(GetFullPath()).c_str()); - return; - } - rdbConfig->SetBundleName(bundleName_); - rdbConfig->SetEncryptStatus(true); - auto errCode = rdbConfig->Initialize(); - if (errCode != E_OK) { - LOG_ERROR("rdbConfig init encrypt failed. errCode:%{public}d, path:%{public}s", - errCode, GdbUtils::Anonymous(GetFullPath()).c_str()); - return; - } - encryptKey_.assign(encryptKey_.size(), 0); - encryptKey_ = rdbConfig->GetEncryptKey(); - newEncryptKey_.assign(newEncryptKey_.size(), 0); - newEncryptKey_ = rdbConfig->GetNewEncryptKey(); -} - -void StoreConfig::ClearEncryptKey() -{ - encryptKey_.assign(encryptKey_.size(), 0); - newEncryptKey_.assign(newEncryptKey_.size(), 0); -} - -void StoreConfig::ChangeEncryptKey() const -{ - NativeRdb::RdbSecurityManager::GetInstance().ChangeKeyFile(GetFullPath()); - if (newEncryptKey_.empty()) { - return; - } - encryptKey_.assign(encryptKey_.size(), 0); - encryptKey_ = newEncryptKey_; - newEncryptKey_.assign(newEncryptKey_.size(), 0); - newEncryptKey_.resize(0); -} -} // namespace OHOS::DistributedDataAip \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/src/trans_db.cpp b/relational_store/frameworks/native/gdb/src/trans_db.cpp deleted file mode 100644 index 3c9a6804fd401ee5d4a1ea9c028d9c321e4b0b7f..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/src/trans_db.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2025 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 "TransDB" -#include "trans_db.h" - -#include "gdb_errors.h" -#include "db_trace.h" -#include "gdb_utils.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { - -constexpr int32_t MAX_GQL_LEN = 1024 * 1024; - -TransDB::TransDB(std::shared_ptr connection) : conn_(connection) -{ -} - -std::pair> TransDB::QueryGql(const std::string &gql) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - if (gql.empty() || gql.length() > MAX_GQL_LEN) { - LOG_ERROR("Gql is empty or length is too long."); - return { E_INVALID_ARGS, std::make_shared() }; - } - if (GdbUtils::IsTransactionGql(gql)) { - LOG_ERROR("Transaction related statements are not supported."); - return { E_INVALID_ARGS, std::make_shared() }; - } - - auto [errCode, statement] = GetStatement(gql); - if (errCode != E_OK || statement == nullptr) { - return { errCode, std::make_shared() }; - } - - auto result = std::make_shared(); - errCode = result->InitData(statement); - if (errCode != E_OK) { - LOG_ERROR("Get FullResult failed, errCode=%{public}d", errCode); - return { errCode, std::make_shared() }; - } - - return { errCode, result }; -} - -std::pair> TransDB::ExecuteGql(const std::string &gql) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - if (gql.empty() || gql.length() > MAX_GQL_LEN) { - LOG_ERROR("Gql is empty or length is too long."); - return { E_INVALID_ARGS, std::make_shared() }; - } - if (GdbUtils::IsTransactionGql(gql)) { - LOG_ERROR("Transaction related statements are not supported."); - return { E_INVALID_ARGS, std::make_shared() }; - } - - auto [errCode, statement] = GetStatement(gql); - if (errCode != E_OK || statement == nullptr) { - return { errCode, std::make_shared() }; - } - - errCode = statement->Step(); - if (errCode != E_OK) { - LOG_ERROR("Step statement failed, errCode=%{public}d", errCode); - } - return { errCode, std::make_shared() }; -} - -std::pair> TransDB::GetStatement(const std::string &gql) const -{ - auto connection = conn_.lock(); - if (connection == nullptr) { - return { E_GRD_DB_INSTANCE_ABNORMAL, nullptr }; - } - return connection->CreateStatement(gql, connection); -} - -std::pair> TransDB::CreateTransaction() -{ - return { E_NOT_SUPPORT, nullptr }; -} - -int32_t TransDB::Close() -{ - return E_NOT_SUPPORT; -} -} // namespace OHOS::DistributedDataAip \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/src/transaction_impl.cpp b/relational_store/frameworks/native/gdb/src/transaction_impl.cpp deleted file mode 100644 index 22faf2b3f16d31f81c2b74a057b092da8dc7e03d..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/src/transaction_impl.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2025 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 "GdbTrans" -#include "transaction_impl.h" - -#include - -#include "gdb_errors.h" -#include "db_trace.h" -#include "logger.h" -#include "trans_db.h" - -namespace OHOS::DistributedDataAip { - -constexpr const char *START_GQL = "START TRANSACTION;"; -constexpr const char *COMMIT_GQL = "COMMIT;"; -constexpr const char *ROLLBACK_GQL = "ROLLBACK;"; - -__attribute__((used)) -const int32_t TransactionImpl::regCreator_ = Transaction::RegisterCreator(TransactionImpl::Create); - -TransactionImpl::TransactionImpl(std::shared_ptr connection) - : connection_(std::move(connection)) -{ -} - -TransactionImpl::~TransactionImpl() -{ - CloseInner(); -} - -std::pair> TransactionImpl::Create(std::shared_ptr conn) -{ - if (conn == nullptr) { - LOG_ERROR("conn is nullptr"); - return { E_ERROR, nullptr }; - } - auto trans = std::make_shared(std::move(conn)); - if (trans == nullptr) { - LOG_ERROR("trans is nullptr"); - return { E_ERROR, nullptr }; - } - auto errorCode = trans->Start(); - if (errorCode != E_OK) { - LOG_ERROR("transaction start failed, errorCode=%{public}d", errorCode); - return { errorCode, nullptr }; - } - return { E_OK, trans }; -} - -int32_t TransactionImpl::Start() -{ - std::lock_guard lock(mutex_); - store_ = std::make_shared(connection_); - if (store_ == nullptr) { - LOG_ERROR("create trans db failed"); - return E_ERROR; - } - - if (connection_ == nullptr) { - LOG_ERROR("connection already closed"); - return E_GRD_DB_INSTANCE_ABNORMAL; - } - - auto [errorCode, statement] = connection_->CreateStatement(START_GQL, connection_); - if (errorCode != E_OK || statement == nullptr) { - LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode); - CloseInner(); - return errorCode; - } - errorCode = statement->Step(); - if (errorCode != E_OK) { - LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode); - CloseInner(); - return errorCode; - } - return E_OK; -} - -int32_t TransactionImpl::Commit() -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - std::lock_guard lock(mutex_); - if (connection_ == nullptr) { - LOG_ERROR("connection already closed"); - return E_GRD_DB_INSTANCE_ABNORMAL; - } - - auto [errorCode, statement] = connection_->CreateStatement(COMMIT_GQL, connection_); - if (errorCode != E_OK || statement == nullptr) { - LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode); - CloseInner(); - return errorCode; - } - - errorCode = statement->Step(); - CloseInner(); - if (errorCode != E_OK) { - LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode); - return errorCode; - } - return E_OK; -} - -int32_t TransactionImpl::Rollback() -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - std::lock_guard lock(mutex_); - if (connection_ == nullptr) { - LOG_ERROR("connection already closed"); - return E_GRD_DB_INSTANCE_ABNORMAL; - } - - auto [errorCode, statement] = connection_->CreateStatement(ROLLBACK_GQL, connection_); - if (errorCode != E_OK || statement == nullptr) { - LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode); - CloseInner(); - return errorCode; - } - - errorCode = statement->Step(); - CloseInner(); - if (errorCode != E_OK) { - LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode); - return errorCode; - } - return E_OK; -} - -int32_t TransactionImpl::CloseInner() -{ - std::lock_guard lock(mutex_); - store_ = nullptr; - connection_ = nullptr; - return E_OK; -} - -int32_t TransactionImpl::Close() -{ - return Rollback(); -} - -std::shared_ptr TransactionImpl::GetStore() -{ - std::lock_guard lock(mutex_); - return store_; -} - -std::pair> TransactionImpl::Query(const std::string &gql) -{ - auto store = GetStore(); - if (store == nullptr) { - LOG_ERROR("transaction already close"); - return { E_GRD_DB_INSTANCE_ABNORMAL, std::make_shared() }; - } - return store->QueryGql(gql); -} - -std::pair> TransactionImpl::Execute(const std::string &gql) -{ - auto store = GetStore(); - if (store == nullptr) { - LOG_ERROR("transaction already close"); - return { E_GRD_DB_INSTANCE_ABNORMAL, std::make_shared() }; - } - return store->ExecuteGql(gql); -} -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/src/vertex.cpp b/relational_store/frameworks/native/gdb/src/vertex.cpp deleted file mode 100644 index ffdb97d5e8c54a10b94ae944ac6a2fd81d84951b..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/gdb/src/vertex.cpp +++ /dev/null @@ -1,122 +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. - */ -#define LOG_TAG "GdbElement" -#include - -#include "gdb_errors.h" -#include "full_result.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { -Vertex::Vertex() : id_("0"), properties_() -{ -} - -Vertex::Vertex(std::string id, std::string label) : id_(std::move(id)), label_(std::move(label)) -{ - labels_.emplace_back(label_); -} - -Vertex::Vertex(std::string id, std::string label, - const std::unordered_map &properties) - : id_(std::move(id)), label_(std::move(label)), properties_(properties) -{ - labels_.emplace_back(label_); -} - -std::string Vertex::GetId() const -{ - return id_; -} - -void Vertex::SetId(std::string id) -{ - id_ = std::move(id); -} - -const std::string &Vertex::GetLabel() const -{ - return label_; -} - -const std::vector &Vertex::GetLabels() const -{ - return labels_; -} - -void Vertex::SetLabel(const std::string &label) -{ - label_ = label; - labels_.emplace_back(label); -} - -const std::unordered_map &Vertex::GetProperties() const -{ - return properties_; -} - -void Vertex::SetProperty(const std::string &key, PropType value) -{ - properties_[key] = std::move(value); -} - -std::shared_ptr Vertex::Parse(const nlohmann::json &json, int32_t &errCode) -{ - std::shared_ptr element = std::make_shared(); - if (!json.contains(Vertex::LABEL) || !json.contains(Vertex::ID) || - !json.contains(Vertex::PROPERTIES) || !json.at(Vertex::PROPERTIES).is_object()) { - LOG_ERROR("element format error."); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - - if (json.at(Vertex::ID).is_number()) { - auto id = json.at(Vertex::ID).get(); - element->SetId(std::to_string(id)); - } else if (json.at(Vertex::ID).is_string()) { - auto id = json.at(Vertex::ID).get(); - element->SetId(id); - } else { - LOG_ERROR("element id is not number or string."); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - if (!json.at(Vertex::LABEL).is_string()) { - LOG_ERROR("element label is not string."); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - element->SetLabel(json.at(Vertex::LABEL).get()); - for (const auto &[key, value] : json.at(Vertex::PROPERTIES).items()) { - if (value.is_string()) { - element->SetProperty(key, value.get()); - } else if (value.is_number_integer()) { - element->SetProperty(key, value.get()); - } else if (value.is_number_float()) { - element->SetProperty(key, value.get()); - } else if (value.is_boolean()) { - element->SetProperty(key, value.get()); - } else if (value.is_null()) { - element->SetProperty(key, nullptr); - } else { - LOG_ERROR("element property value type is not supported."); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - } - errCode = E_OK; - return element; -} -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/icu/BUILD.gn b/relational_store/frameworks/native/icu/BUILD.gn index ee35d546789045b14704959c79e47862d2d18ea1..f2f4587d0d0e4302412648a9263d9a43e9a13ef5 100644 --- a/relational_store/frameworks/native/icu/BUILD.gn +++ b/relational_store/frameworks/native/icu/BUILD.gn @@ -38,6 +38,7 @@ ohos_shared_library("relational_store_icu") { "${relational_store_common_path}/include", "${relational_store_native_path}/icu/include", "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/rdb/include", ] sources = [ "${relational_store_native_path}/icu/src/icu_collect.cpp" ] diff --git a/relational_store/frameworks/native/icu/include/icu_collect.h b/relational_store/frameworks/native/icu/include/icu_collect.h index b8f0976745f92d3fe16d24a59547096907fb4e12..b68aad6055d69a39c3f664fc37a3d764f85c41d1 100644 --- a/relational_store/frameworks/native/icu/include/icu_collect.h +++ b/relational_store/frameworks/native/icu/include/icu_collect.h @@ -23,7 +23,7 @@ namespace OHOS::NativeRdb { class ICUCollect { public: - static int32_t Local(sqlite3 *dbHandle, const std::string &str); + static int32_t Locale(sqlite3 *dbHandle, const std::string &str); private: static int Collate8Compare(void *p, int n1, const void *v1, int n2, const void *v2); diff --git a/relational_store/frameworks/native/icu/src/icu_collect.cpp b/relational_store/frameworks/native/icu/src/icu_collect.cpp index b948c921bdd2c2d8b0ecf816ce8b761b18f9d532..d9d2d2fdeb13bfc86a906bfdf22a63d1e277191e 100644 --- a/relational_store/frameworks/native/icu/src/icu_collect.cpp +++ b/relational_store/frameworks/native/icu/src/icu_collect.cpp @@ -17,17 +17,26 @@ #include #include +#include #include "ohos/init_data.h" #include "logger.h" #include "rdb_errno.h" #include "rdb_visibility.h" #include "sqlite3.h" +#include "sqlite_errno.h" -API_EXPORT int32_t ConfigICULocal(sqlite3 *, const std::string &str) asm("ConfigICULocal"); -int32_t ConfigICULocal(sqlite3 *handle, const std::string &str) +API_EXPORT int32_t ConfigICULocale(sqlite3 *, const std::string &str) asm("ConfigICULocale"); +API_EXPORT int32_t CleanUp() asm("CleanUp"); +int32_t ConfigICULocale(sqlite3 *handle, const std::string &str) { - return OHOS::NativeRdb::ICUCollect::Local(handle, str); + return OHOS::NativeRdb::ICUCollect::Locale(handle, str); +} + +int32_t CleanUp() +{ + u_cleanup(); + return OHOS::NativeRdb::E_OK; } namespace OHOS::NativeRdb { @@ -62,26 +71,34 @@ void ICUCollect::LocalizedCollatorDestroy(void *collator) ucol_close(reinterpret_cast(collator)); } -int32_t ICUCollect::Local(sqlite3 *dbHandle, const std::string &str) +int32_t ICUCollect::Locale(sqlite3 *dbHandle, const std::string &str) { UErrorCode status = U_ZERO_ERROR; SetHwIcuDirectory(); UCollator *collator = ucol_open(str.c_str(), &status); + if (status == U_USING_DEFAULT_WARNING || status == U_ILLEGAL_ARGUMENT_ERROR) { + LOG_ERROR("A resource bundle lookup returned a result from the root locale, locale:%{public}s.", str.c_str()); + ucol_close(collator); + return E_INVALID_ARGS_NEW; + } if (U_FAILURE(status)) { LOG_ERROR("Can not open collator, status:%{public}d.", status); + ucol_close(collator); return E_ERROR; } ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_PRIMARY, &status); if (U_FAILURE(status)) { LOG_ERROR("Set attribute of collator failed, status:%{public}d.", status); + ucol_close(collator); return E_ERROR; } int err = sqlite3_create_collation_v2(dbHandle, "LOCALES", SQLITE_UTF8, collator, ICUCollect::Collate8Compare, (void (*)(void *))ICUCollect::LocalizedCollatorDestroy); if (err != SQLITE_OK) { LOG_ERROR("SCreate collator in sqlite3 failed err:%{public}d.", err); - return err; + ucol_close(collator); + return SQLiteError::ErrNo(err); } return E_OK; } diff --git a/relational_store/frameworks/native/obs_mgr_adapter/BUILD.gn b/relational_store/frameworks/native/obs_mgr_adapter/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..8de7d7b0bf3220448a1077b967861bcbe19685bb --- /dev/null +++ b/relational_store/frameworks/native/obs_mgr_adapter/BUILD.gn @@ -0,0 +1,50 @@ +# Copyright (c) 2025 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("//build/ohos/ace/ace.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +group("build_module") { + deps = [ ":rdb_obs_mgr_adapter" ] +} + +ohos_shared_library("rdb_obs_mgr_adapter") { + branch_protector_ret = "pac_ret" + sanitize = { + boundary_sanitize = true + ubsan = true + cfi = true + cfi_cross_dso = true + debug = false + } + + ldflags = [ "-Wl,--exclude-libs,ALL" ] + cflags_cc = [ "-fvisibility=hidden" ] + + include_dirs = [ + "${relational_store_common_path}/include", + "${relational_store_innerapi_path}/rdb/include", + ] + + sources = [ "${relational_store_native_path}/obs_mgr_adapter/obs_mgr_adapter.cpp" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + ] + subsystem_name = "distributeddatamgr" + part_name = "relational_store" +} diff --git a/relational_store/frameworks/native/obs_mgr_adapter/obs_mgr_adapter.cpp b/relational_store/frameworks/native/obs_mgr_adapter/obs_mgr_adapter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b016f24991f235b7d38c37b681426cb1e67c9a3 --- /dev/null +++ b/relational_store/frameworks/native/obs_mgr_adapter/obs_mgr_adapter.cpp @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2025 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 "ObsMgrAdapter" +#include "obs_mgr_adapter.h" + +#include +#include +#include + +#include "concurrent_map.h" +#include "data_ability_observer_stub.h" +#include "dataobs_mgr_client.h" +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_types.h" +#include "rdb_visibility.h" + +using namespace OHOS::DistributedRdb; +API_EXPORT int32_t Register(const std::string &uri, std::shared_ptr observer) asm("Register"); +API_EXPORT int32_t Unregister(const std::string &uri, std::shared_ptr observer) asm("Unregister"); +API_EXPORT int32_t NotifyChange(const std::string &uri) asm("NotifyChange"); +API_EXPORT bool CleanUp() asm("CleanUp"); +namespace OHOS::NativeRdb { +using namespace OHOS::Rdb; +constexpr int32_t MAX_RETRY = 100; +class RdbStoreLocalSharedObserver : public AAFwk::DataAbilityObserverStub { +public: + explicit RdbStoreLocalSharedObserver(std::shared_ptr observer) : observer_(observer){}; + virtual ~RdbStoreLocalSharedObserver(){}; + void OnChange() override + { + if (observer_ == nullptr) { + LOG_ERROR("observer_ is null."); + return; + } + observer_->OnChange(); + } + + bool operator==(std::shared_ptr observer) + { + if (observer == nullptr) { + return false; + } + return observer_ == observer; + } + +private: + std::shared_ptr observer_ = nullptr; +}; + +static std::string Anonymous(const std::string &uri) +{ + return std::string(uri).substr(uri.rfind("/") + 1, uri.size()); +} + +class ObsMgrAdapterImpl { +public: + ObsMgrAdapterImpl() = default; + static int32_t RegisterObserver(const std::string &uri, std::shared_ptr observer); + static int32_t UnregisterObserver(const std::string &uri, std::shared_ptr observer); + static int32_t NotifyChange(const std::string &uri); + static bool Clean(); + +private: + static void RemoveObserver(const std::string &uri, sptr observer); + static void AddObserver(const std::string &uri, const std::list> &observers); + static void PushReleaseObs(wptr obs); + static bool CleanReleaseObs(bool force = false); + static ConcurrentMap>> obs_; + static std::mutex mutex_; + static std::list> releaseObs_; +}; + +ConcurrentMap>> ObsMgrAdapterImpl::obs_; +std::mutex ObsMgrAdapterImpl::mutex_; +std::list> ObsMgrAdapterImpl::releaseObs_; +int32_t ObsMgrAdapterImpl::RegisterObserver(const std::string &uri, std::shared_ptr observer) +{ + sptr localSharedObserver; + int32_t code = E_OK; + obs_.Compute(uri, [&localSharedObserver, &observer, &uri, &code](const auto &key, auto &obs) { + for (auto it = obs.begin(); it != obs.end();) { + if (*it == nullptr) { + it = obs.erase(it); + continue; + } + if ((**it) == observer) { + LOG_WARN("Duplicate subscribe, uri:%{public}s", Anonymous(uri).c_str()); + code = RDB_OBS_DUPLICATE_SUB; + return !obs.empty(); + } + ++it; + } + localSharedObserver = new (std::nothrow) RdbStoreLocalSharedObserver(observer); + if (localSharedObserver == nullptr) { + LOG_ERROR("no memory! uri:%{public}s", Anonymous(uri).c_str()); + code = E_ERROR; + return !obs.empty(); + } + obs.push_back(localSharedObserver); + return !obs.empty(); + }); + if (localSharedObserver == nullptr) { + return code; + } + auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); + if (client == nullptr) { + RemoveObserver(uri, localSharedObserver); + LOG_ERROR("Failed to get DataObsMgrClient, uri:%{public}s", Anonymous(uri).c_str()); + return E_GET_DATAOBSMGRCLIENT_FAIL; + } + code = client->RegisterObserver(Uri(uri), localSharedObserver); + if (code != 0) { + RemoveObserver(uri, localSharedObserver); + LOG_ERROR("Subscribe failed. code:%{public}d, uri:%{public}s", code, Anonymous(uri).c_str()); + return E_ERROR; + } + return E_OK; +} + +int32_t ObsMgrAdapterImpl::UnregisterObserver(const std::string &uri, std::shared_ptr observer) +{ + std::list> localSharedObservers; + obs_.Compute(uri, [&localSharedObservers, &observer](const auto &key, auto &obs) { + for (auto it = obs.begin(); it != obs.end();) { + if (*it == nullptr) { + it = obs.erase(it); + continue; + } + if ((**it) == observer || observer == nullptr) { + localSharedObservers.push_back(std::move(*it)); + it = obs.erase(it); + continue; + } + ++it; + } + return !obs.empty(); + }); + if (localSharedObservers.empty()) { + return E_OK; + } + auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); + if (client == nullptr) { + AddObserver(uri, localSharedObservers); + LOG_ERROR("Failed to get DataObsMgrClient, uri:%{public}s", Anonymous(uri).c_str()); + return E_GET_DATAOBSMGRCLIENT_FAIL; + } + for (auto it = localSharedObservers.begin(); it != localSharedObservers.end();) { + if (*it == nullptr) { + it = localSharedObservers.erase(it); + continue; + } + int32_t err = client->UnregisterObserver(Uri(uri), *it); + if (err != 0) { + AddObserver(uri, localSharedObservers); + LOG_ERROR("UnregisterObserver failed. code:%{public}d, uri:%{public}s", err, Anonymous(uri).c_str()); + return err; + } + PushReleaseObs(*it); + it = localSharedObservers.erase(it); + } + CleanReleaseObs(); + return E_OK; +} + +int32_t ObsMgrAdapterImpl::NotifyChange(const std::string &uri) +{ + auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); + if (client == nullptr) { + LOG_ERROR("Failed to get DataObsMgrClient, uri:%{public}s", Anonymous(uri).c_str()); + return E_GET_DATAOBSMGRCLIENT_FAIL; + } + auto err = client->NotifyChange(Uri(uri)); + if (err != 0) { + LOG_ERROR("Notify failed, uri:%{public}s", Anonymous(uri).c_str()); + return E_ERROR; + } + return E_OK; +} + +bool ObsMgrAdapterImpl::Clean() +{ + auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); + if (client == nullptr) { + LOG_ERROR("Failed to get DataObsMgrClient"); + return obs_.Empty() && CleanReleaseObs(true); + } + obs_.EraseIf([client](const auto &key, auto &observer) { + for (auto it = observer.begin(); it != observer.end();) { + if (*it == nullptr) { + it = observer.erase(it); + continue; + } + int32_t err = client->UnregisterObserver(Uri(key), *it); + if (err != 0) { + LOG_ERROR("UnregisterObserver failed. code:%{public}d, uri:%{public}s", err, Anonymous(key).c_str()); + ++it; + continue; + } + PushReleaseObs(*it); + it = observer.erase(it); + } + return observer.empty(); + }); + return obs_.Empty() && CleanReleaseObs(true); +} + +void ObsMgrAdapterImpl::RemoveObserver(const std::string &uri, sptr observer) +{ + obs_.ComputeIfPresent(uri, [&observer](const auto &key, auto &obs) { + for (auto it = obs.begin(); it != obs.end();) { + if (*it == nullptr) { + it = obs.erase(it); + continue; + } + if (observer == nullptr || (*it) == observer) { + it = obs.erase(it); + continue; + } + ++it; + } + return !obs.empty(); + }); +} + +void ObsMgrAdapterImpl::AddObserver( + const std::string &uri, const std::list> &observers) +{ + obs_.Compute(uri, [&observers](const auto &key, auto &obs) { + obs.insert(obs.end(), observers.begin(), observers.end()); + return !obs.empty(); + }); +} + +void ObsMgrAdapterImpl::PushReleaseObs(wptr obs) +{ + std::lock_guard lock(mutex_); + releaseObs_.push_back(obs); +} + +bool ObsMgrAdapterImpl::CleanReleaseObs(bool force) +{ + std::lock_guard lock(mutex_); + int32_t retry = 0; + do { + auto it = releaseObs_.begin(); + while (it != releaseObs_.end()) { + if (it->promote()) { + ++it; + } else { + it = releaseObs_.erase(it); + } + } + if (!force) { + break; + } + retry++; + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } while (retry < MAX_RETRY && !releaseObs_.empty()); + if (force && !releaseObs_.empty()) { + LOG_ERROR("Failed to release obs, size:%{public}zu, retry:%{public}d", releaseObs_.size(), retry); + return false; + } + return true; +} +} // namespace OHOS::NativeRdb + +int32_t Register(const std::string &uri, std::shared_ptr observer) +{ + return OHOS::NativeRdb::ObsMgrAdapterImpl::RegisterObserver(uri, observer); +} + +int32_t Unregister(const std::string &uri, std::shared_ptr observer) +{ + return OHOS::NativeRdb::ObsMgrAdapterImpl::UnregisterObserver(uri, observer); +} + +int32_t NotifyChange(const std::string &uri) +{ + return OHOS::NativeRdb::ObsMgrAdapterImpl::NotifyChange(uri); +} + +bool CleanUp() +{ + return OHOS::NativeRdb::ObsMgrAdapterImpl::Clean(); +} \ No newline at end of file diff --git a/relational_store/frameworks/native/obs_mgr_adapter/obs_mgr_adapter.h b/relational_store/frameworks/native/obs_mgr_adapter/obs_mgr_adapter.h new file mode 100644 index 0000000000000000000000000000000000000000..2623fdf16bc60d1d91d8be323d1f245e5728691b --- /dev/null +++ b/relational_store/frameworks/native/obs_mgr_adapter/obs_mgr_adapter.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 HOS_NATIVE_RDB_OBS_MGR_ADAPTER_H +#define HOS_NATIVE_RDB_OBS_MGR_ADAPTER_H +#include +namespace OHOS::NativeRdb { +constexpr int32_t RDB_OBS_DUPLICATE_SUB = -1; +} // namespace OHOS::NativeRdb +#endif //HOS_NATIVE_RDB_OBS_MGR_ADAPTER_H diff --git a/relational_store/frameworks/native/rdb/include/connection.h b/relational_store/frameworks/native/rdb/include/connection.h index dd8e291e3c670cf1e60d6fb34dc5a210a6892686..a218566b205f37aac619959413815b45984232a1 100644 --- a/relational_store/frameworks/native/rdb/include/connection.h +++ b/relational_store/frameworks/native/rdb/include/connection.h @@ -22,7 +22,9 @@ #include #include +#include "knowledge_types.h" #include "rdb_common.h" +#include "rdb_store_config.h" #include "rdb_types.h" #include "statement.h" @@ -42,17 +44,17 @@ public: using Repairer = int32_t (*)(const RdbStoreConfig &config); using Deleter = int32_t (*)(const RdbStoreConfig &config); using Collector = std::map (*)(const RdbStoreConfig &config); - using Restorer = int32_t (*)(const RdbStoreConfig &config, const std::string &srcPath, const std::string &destPath); + using ReplicaChecker = int32_t (*)(const RdbStoreConfig &config); static std::pair Create(const RdbStoreConfig &config, bool isWriter); static int32_t Repair(const RdbStoreConfig &config); static int32_t Delete(const RdbStoreConfig &config); - static int32_t Restore(const RdbStoreConfig &config, const std::string &srcPath, const std::string &destPath); static std::map Collect(const RdbStoreConfig &config); + static int32_t CheckReplicaIntegrity(const RdbStoreConfig &config); static int32_t RegisterCreator(int32_t dbType, Creator creator); static int32_t RegisterRepairer(int32_t dbType, Repairer repairer); static int32_t RegisterDeleter(int32_t dbType, Deleter deleter); static int32_t RegisterCollector(int32_t dbType, Collector collector); - static int32_t RegisterRestorer(int32_t dbType, Restorer restorer); + static int32_t RegisterReplicaChecker(int32_t dbType, ReplicaChecker replicaChecker); int32_t SetId(int32_t id); int32_t GetId() const; @@ -61,24 +63,31 @@ public: virtual ~Connection() = default; virtual int32_t VerifyAndRegisterHook(const RdbStoreConfig &config) = 0; virtual std::pair CreateStatement(const std::string &sql, SConn conn) = 0; + virtual std::pair CreateReplicaStatement(const std::string &sql, SConn conn) = 0; + virtual int CheckReplicaForRestore() = 0; virtual int32_t GetDBType() const = 0; virtual bool IsWriter() const = 0; - virtual int32_t ReSetKey(const RdbStoreConfig &config) = 0; + virtual int32_t ResetKey(const RdbStoreConfig &config) = 0; virtual int32_t TryCheckPoint(bool timeout) = 0; + virtual int32_t Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) = 0; virtual int32_t LimitWalSize() = 0; virtual int32_t ConfigLocale(const std::string &localeStr) = 0; virtual int32_t CleanDirtyData(const std::string &table, uint64_t cursor) = 0; virtual int32_t SubscribeTableChanges(const Notifier ¬ifier) = 0; virtual int32_t GetMaxVariable() const = 0; virtual int32_t GetJournalMode() = 0; - virtual int32_t ClearCache() = 0; + virtual int32_t ClearCache(bool isForceClear = false) = 0; virtual int32_t Subscribe(const std::shared_ptr &observer) = 0; virtual int32_t Unsubscribe(const std::shared_ptr &observer) = 0; virtual int32_t Backup(const std::string &databasePath, const std::vector &destEncryptKey, bool isAsync, - SlaveStatus &slaveStatus) = 0; + std::shared_ptr slaveStatus, bool verifyDb = true) = 0; virtual int32_t Restore( - const std::string &databasePath, const std::vector &destEncryptKey, SlaveStatus &slaveStatus) = 0; - virtual ExchangeStrategy GenerateExchangeStrategy(const SlaveStatus &status) = 0; + const std::string &databasePath, const std::vector &destEncryptKey, + std::shared_ptr slaveStatus) = 0; + virtual ExchangeStrategy GenerateExchangeStrategy(std::shared_ptr status, bool isRelpay = true) = 0; + virtual int SetKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema &schema) = 0; + virtual int CleanDirtyLog(const std::string &table, uint64_t cursor) = 0; + virtual int RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) = 0; private: int32_t id_ = 0; diff --git a/relational_store/frameworks/native/rdb/include/connection_pool.h b/relational_store/frameworks/native/rdb/include/connection_pool.h index a85a7eb95ce404d1ba86325ba7d41dd725b09d18..8121d12a6882761e5e5026b84018cef97adf3c2b 100644 --- a/relational_store/frameworks/native/rdb/include/connection_pool.h +++ b/relational_store/frameworks/native/rdb/include/connection_pool.h @@ -31,6 +31,7 @@ #include "connection.h" #include "rdb_common.h" #include "rdb_store_config.h" +#include "delay_actuator.h" namespace OHOS { class ExecutorPool; namespace NativeRdb { @@ -54,9 +55,11 @@ public: int32_t Dump(bool isWriter, const char *header); int RestartConns(); + int ReopenConns(); int ConfigLocale(const std::string &localeStr); int ChangeDbFileForRestore(const std::string &newPath, const std::string &backupPath, - const std::vector &newKey, SlaveStatus &slaveStatus); + const std::vector &newKey, std::shared_ptr slaveStatus); + int Rekey(const RdbStoreConfig::CryptoParam &cryptoParam); std::stack &GetTransactionStack(); std::mutex &GetTransactionStackMutex(); int AcquireTransaction(); @@ -71,7 +74,7 @@ private: int32_t tid_ = 0; int32_t id_ = 0; std::chrono::steady_clock::time_point time_ = std::chrono::steady_clock::now(); - std::shared_ptr connect_; + const std::shared_ptr connect_; explicit ConnNode(std::shared_ptr conn); std::shared_ptr GetConnect(); @@ -125,7 +128,9 @@ private: int32_t GetMaxReaders(const RdbStoreConfig &config); std::shared_ptr Convert2AutoConn(std::shared_ptr node, bool isTrans = false); void ReleaseNode(std::shared_ptr node, bool reuse = true); - int RestoreMasterDb(const std::string &newPath, const std::string &backupPath, SlaveStatus &slaveStatus); + int RestoreByDbSqliteType(const std::string &newPath, const std::string &backupPath, + std::shared_ptr slaveStatus); + int RestoreMasterDb(const std::string &newPath, const std::string &backupPath); bool CheckIntegrity(const std::string &dbPath); void DelayClearTrans(); @@ -135,6 +140,12 @@ private: static constexpr uint32_t ITERS_COUNT = 2; static constexpr uint32_t MAX_TRANS = 4; static constexpr std::chrono::steady_clock::duration TRANS_CLEAR_INTERVAL = std::chrono::seconds(150); + static constexpr uint32_t FIRST_DELAY_INTERVAL = ActuatorBase::INVALID_INTERVAL; + static constexpr uint32_t MIN_EXECUTE_INTERVAL = ActuatorBase::INVALID_INTERVAL; + static constexpr uint32_t MAX_EXECUTE_INTERVAL = 30000; // 30000ms + std::shared_ptr>, + std::function> &out, std::shared_ptr &&input)>>> + clearActuator_; const RdbStoreConfig &config_; RdbStoreConfig attachConfig_; Container writers_; diff --git a/relational_store/frameworks/native/rdb/include/delay_notify.h b/relational_store/frameworks/native/rdb/include/delay_notify.h index 3ac0f7368ebb346ef803d651a10c54d6b77233e1..c2f1d685e63319012d2968e37a7991e518928bd2 100644 --- a/relational_store/frameworks/native/rdb/include/delay_notify.h +++ b/relational_store/frameworks/native/rdb/include/delay_notify.h @@ -28,7 +28,7 @@ namespace OHOS { class ExecutorPool; namespace NativeRdb { -class DelayNotify { +class DelayNotify : public std::enable_shared_from_this { public: using Task = std::function; using Time = std::chrono::steady_clock::time_point; diff --git a/relational_store/frameworks/native/rdb/include/global_resource.h b/relational_store/frameworks/native/rdb/include/global_resource.h new file mode 100644 index 0000000000000000000000000000000000000000..8217b63add65ede50701f4e60451013b0dd60c80 --- /dev/null +++ b/relational_store/frameworks/native/rdb/include/global_resource.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 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 NATIVE_RDB_GLOBAL_RESOURCE_H +#define NATIVE_RDB_GLOBAL_RESOURCE_H +#include +namespace OHOS { +namespace NativeRdb { +class GlobalResource { +public: + enum CleanType { + CLEAN_HEAD = 0, + DB_CLIENT = CLEAN_HEAD, + OPEN_SSL, + ICU, + OBS, + IPC, + CLEAN_BUTT + }; + using Cleaner = int32_t (*)(); + static int32_t RegisterClean(CleanType type, Cleaner clean); + static int32_t CleanUp(int32_t type); +}; + +} // namespace NativeRdb +} // namespace OHOS +#endif // NATIVE_RDB_GLOBAL_RESOURCE_H diff --git a/relational_store/frameworks/native/rdb/include/grd_api_manager.h b/relational_store/frameworks/native/rdb/include/grd_api_manager.h index 51a01de1fafe4ec2b391fa8b5a47648de82652c0..d9f2e10a4b95c5d90a107b648c2e655dc204b2fe 100644 --- a/relational_store/frameworks/native/rdb/include/grd_api_manager.h +++ b/relational_store/frameworks/native/rdb/include/grd_api_manager.h @@ -58,7 +58,8 @@ typedef int32_t (*DBRestore)(const char *dbFile, const char *backupDbFile, GRD_C typedef int32_t (*DBReKey)(const char *dbFile, const char *configStr, GRD_CipherInfoT *cipherInfo); typedef GRD_DbValueT (*DBGetConfig)(GRD_DB *db, GRD_ConfigTypeE type); typedef int32_t (*DBSetConfig)(GRD_DB *db, GRD_ConfigTypeE type, GRD_DbValueT value); -typedef int32_t (*DBSqlRegistryThreadPool)(GRD_DB *db, GRD_ThreadPool *threadPool); +typedef int32_t (*DBSqlRegistryThreadPool)(GRD_DB *db, GRD_DbThreadPoolT *threadPool); +typedef int32_t (*DBSqlRegistryClusterAlgo)(GRD_DB *db, const char *clstAlgoName, GRD_ClusterAlgoFunc func); struct GRD_APIInfo { DBOpen DBOpenApi = nullptr; @@ -92,6 +93,7 @@ struct GRD_APIInfo { DBGetConfig DBGetConfigApi = nullptr; DBSetConfig DBSetConfigApi = nullptr; DBSqlRegistryThreadPool DBSqlRegistryThreadPool = nullptr; + DBSqlRegistryClusterAlgo DBSqlRegistryClusterAlgo = nullptr; }; API_EXPORT bool IsUsingArkData(); diff --git a/relational_store/frameworks/native/rdb/include/grd_type_export.h b/relational_store/frameworks/native/rdb/include/grd_type_export.h index dedcdf5275a9f48efdb940eee9cf52da20a95011..42a086d24444fbcd08eac88d8c17ed90309e912f 100644 --- a/relational_store/frameworks/native/rdb/include/grd_type_export.h +++ b/relational_store/frameworks/native/rdb/include/grd_type_export.h @@ -30,10 +30,36 @@ typedef struct GRD_DB GRD_DB; typedef struct GRD_SqlStmt GRD_SqlStmt; typedef struct GRD_Stmt GRD_StmtT; -typedef void (*GRD_ScheduleFunc)(void *func, void *param); -typedef struct GRD_ThreadPool { - GRD_ScheduleFunc schedule; -} GRD_ThreadPoolT; +typedef uint64_t (*GRD_DbScheduleFunc)(void *func, void *param); +typedef bool (*GRD_DbRemoveFunc)(uint64_t taskId, bool wait); +typedef struct GRD_DbThreadPool { + GRD_DbScheduleFunc schedule; + GRD_DbRemoveFunc remove; +} GRD_DbThreadPoolT; + +typedef struct GRD_ClstAlgoPara { + /* Input Parameters */ + uint16_t featureDim; // Feature vector dimension, currently supports 256D only + uint32_t oldFeaturesNum; // Number of historical cluster center vectors + float *oldFeatures; // Array of historical cluster center vectors, + // stored in row-major order (length: oldFeaturesNum * dim) + const int32_t *oldClstGroupId; // Cluster ID for each historical vector (length: oldFeaturesNum) + const int32_t *oldClstVecNum; // Number of vectors in each historical cluster (length: oldFeaturesNum) + + uint32_t newFeaturesNum; // Number of newly collected vectors + float *newFeatures; // Array of new feature vectors + // stored in row-major order (length: newFeaturesNum * dim) + int32_t newClusterIdStart; // Starting cluster ID for new clusters, usually the maximum old cluster ID plus one + + /* Customization Parameters */ + void *customParams; // Developers need to communicate with the database development team before using it + + /* Output Parameters */ + int32_t *clusterResult; // Clustering result array, indicating the assigned cluster ID for each new vector + // (length: newFeaturesNum) +} GRD_ClstAlgoParaT; + +typedef int32_t (*GRD_ClusterAlgoFunc)(GRD_ClstAlgoParaT *para); /** * @brief Open database config diff --git a/relational_store/frameworks/native/rdb/include/irdb_service.h b/relational_store/frameworks/native/rdb/include/irdb_service.h index 88682d63373ccbde85e516946a5acb3a972b7c25..efce9f83c67f948c46dde7930618f0f590f525b2 100644 --- a/relational_store/frameworks/native/rdb/include/irdb_service.h +++ b/relational_store/frameworks/native/rdb/include/irdb_service.h @@ -32,7 +32,9 @@ class IKvStoreDataService : public IRemoteBroker { public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedKv.IKvStoreDataService"); virtual sptr GetFeatureInterface(const std::string &name) = 0; - virtual int32_t RegisterDeathObserver(const std::string &bundleName, sptr observer) = 0; + virtual int32_t RegisterDeathObserver( + const std::string &bundleName, sptr observer, const std::string &featureName) = 0; + virtual int32_t Exit(const std::string &featureName) = 0; }; } // namespace OHOS::DistributedRdb #endif diff --git a/relational_store/frameworks/native/gdb/include/transaction_impl.h b/relational_store/frameworks/native/rdb/include/knowledge_schema_helper.h similarity index 38% rename from relational_store/frameworks/native/gdb/include/transaction_impl.h rename to relational_store/frameworks/native/rdb/include/knowledge_schema_helper.h index fdaaa64acc0b3121bf25366063e83255565e6251..ef6a25019ff03df6d3e564fd3a6d4610e1ba7399 100644 --- a/relational_store/frameworks/native/gdb/include/transaction_impl.h +++ b/relational_store/frameworks/native/rdb/include/knowledge_schema_helper.h @@ -12,44 +12,42 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef ARKDATA_INTELLIGENCE_PLATFORM_TRANSACTION_IMPL_H -#define ARKDATA_INTELLIGENCE_PLATFORM_TRANSACTION_IMPL_H + +#ifndef DISTRIBUTED_RDB_KNOWLEDGE_SCHEMA_HELPER_H +#define DISTRIBUTED_RDB_KNOWLEDGE_SCHEMA_HELPER_H #include -#include #include +#include +#include -#include "connection.h" -#include "gdb_store_config.h" -#include "gdb_transaction.h" -#include "result.h" +#include "knowledge_types.h" +#include "rdb_types.h" -namespace OHOS::DistributedDataAip { -class DBStore; -class TransactionImpl : public Transaction { +namespace OHOS::NativeRdb { +class KnowledgeSchemaHelper : public std::enable_shared_from_this { public: - TransactionImpl(std::shared_ptr connection); - ~TransactionImpl() override; - - int32_t Commit() override; - int32_t Rollback() override; - int32_t Close() override; - - std::pair> Query(const std::string &gql) override; - std::pair> Execute(const std::string &gql) override; - - static std::pair> Create(std::shared_ptr conn); + KnowledgeSchemaHelper() = default; + ~KnowledgeSchemaHelper(); + void Init(const RdbStoreConfig &config, const DistributedRdb::RdbKnowledgeSchema &schema); + std::pair GetRdbKnowledgeSchema(const std::string &dbName); + void DonateKnowledgeData(); + void Close(); private: - int32_t Start(); - int32_t CloseInner(); - std::shared_ptr GetStore(); - - std::recursive_mutex mutex_; - std::shared_ptr store_; - std::shared_ptr connection_; - - static const int32_t regCreator_; -}; -} // namespace OHOS::DistributedDataAip + void LoadKnowledgeLib(); + void LoadKnowledgeSchemaManager(void *handle); + bool IsLoadLib() const; + void StartTask(); + + mutable std::shared_mutex libMutex_; + DistributedRdb::IKnowledgeSchemaManager *schemaManager_ = nullptr; + bool inited_ = false; +#ifndef CROSS_PLATFORM + void *dlHandle_ = nullptr; #endif + std::string bundleName_ = ""; + std::string dbName_ = ""; +}; +} +#endif // DISTRIBUTED_RDB_KNOWLEDGE_SCHEMA_HELPER_H diff --git a/relational_store/frameworks/native/rdb/include/rd_connection.h b/relational_store/frameworks/native/rdb/include/rd_connection.h index 7d0da643e753f60dbf2926b9311262d892e83ed5..0f4315d97fe91bd7ce716a4fff4281cfd9d40e24 100644 --- a/relational_store/frameworks/native/rdb/include/rd_connection.h +++ b/relational_store/frameworks/native/rdb/include/rd_connection.h @@ -39,38 +39,40 @@ public: ~RdConnection(); int32_t VerifyAndRegisterHook(const RdbStoreConfig &config) override; std::pair CreateStatement(const std::string &sql, SConn conn) override; + std::pair CreateReplicaStatement(const std::string &sql, SConn conn) override; + int CheckReplicaForRestore() override; int32_t GetDBType() const override; bool IsWriter() const override; - int32_t ReSetKey(const RdbStoreConfig &config) override; + int32_t ResetKey(const RdbStoreConfig &config) override; int32_t TryCheckPoint(bool timeout) override; int32_t LimitWalSize() override; + int32_t Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) override; int32_t ConfigLocale(const std::string &localeStr) override; int32_t CleanDirtyData(const std::string &table, uint64_t cursor) override; int32_t SubscribeTableChanges(const Notifier ¬ifier) override; int32_t GetMaxVariable() const override; int32_t GetJournalMode() override; - int32_t ClearCache() override; + int32_t ClearCache(bool isForceClear = false) override; int32_t Subscribe(const std::shared_ptr &observer) override; int32_t Unsubscribe(const std::shared_ptr &observer) override; int32_t Backup(const std::string &databasePath, const std::vector &destEncryptKey, bool isAsync, - SlaveStatus &slaveStatus) override; + std::shared_ptr slaveStatus, bool verifyDb = true) override; int32_t Restore(const std::string &databasePath, const std::vector &destEncryptKey, - SlaveStatus &slaveStatus) override; - ExchangeStrategy GenerateExchangeStrategy(const SlaveStatus &status) override; + std::shared_ptr slaveStatus) override; + ExchangeStrategy GenerateExchangeStrategy(std::shared_ptr status, bool isRelpay) override; + int SetKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema &schema) override; + int CleanDirtyLog(const std::string &table, uint64_t cursor) override; + int RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) override; private: - static void CheckConfig(std::shared_ptr conn, const RdbStoreConfig &config); - static void ExecuteSet(std::shared_ptr conn, const std::string ¶mName, int num); - - static constexpr int MAX_VARIABLE_NUM = 500; + static constexpr int MAX_VARIABLE_NUM = 32766; static constexpr const char *GRD_OPEN_CONFIG_STR = "\"pageSize\":8, \"crcCheckEnable\":0, \"redoFlushByTrx\":1, \"bufferPoolSize\":10240," - "\"sharedModeEnable\":1, \"metaInfoBak\":1, \"maxConnNum\":500"; + "\"sharedModeEnable\":1, \"metaInfoBak\":1, \"maxConnNum\":500, \"defaultIsolationLevel\":2"; static constexpr uint32_t NO_ITER = 0; static constexpr uint32_t ITER_V1 = 5000; static constexpr uint32_t ITERS[] = { NO_ITER, ITER_V1 }; static constexpr uint32_t ITERS_COUNT = sizeof(ITERS) / sizeof(ITERS[0]); - static constexpr int NCANDIDATES_DEFAULT_NUM = 128; static const int32_t regCreator_; static const int32_t regRepairer_; static const int32_t regDeleter_; diff --git a/relational_store/frameworks/native/rdb/include/rd_statement.h b/relational_store/frameworks/native/rdb/include/rd_statement.h index fcba0f5b59dc96062d296e7b5a850b60a713d27b..9e8a09f35d3dbb7e2bbed1d6d994573a347d257a 100644 --- a/relational_store/frameworks/native/rdb/include/rd_statement.h +++ b/relational_store/frameworks/native/rdb/include/rd_statement.h @@ -51,6 +51,7 @@ public: bool ReadOnly() const override; bool SupportBlockInfo() const override; int32_t FillBlockInfo(SharedBlockInfo *info) const override; + std::pair> GetRows(uint32_t maxCount) override; void GetProperties(); private: diff --git a/relational_store/frameworks/native/rdb/include/rd_utils.h b/relational_store/frameworks/native/rdb/include/rd_utils.h index 1e759ac4d759ea9b9b611b3efcecdbf4569e1f93..16a62e796642b8393bfc76dc91ff9baf0a4ea84f 100644 --- a/relational_store/frameworks/native/rdb/include/rd_utils.h +++ b/relational_store/frameworks/native/rdb/include/rd_utils.h @@ -40,6 +40,22 @@ public: static int RdSqlFinalize(GRD_SqlStmt *stmt); static int RdSqlBindBlob(GRD_SqlStmt *stmt, uint32_t idx, const void *val, int32_t len, void (*freeFunc)(void *)); + /** + * @brief Binds a text buffer to a parameter in a prepared SQL statement + * + * This function binds a text data buffer to a parameter placeholder in a SQL prepared statement. + * Typically used to replace "?" placeholders in SQL statements with actual values before execution. + * + * @param stmt Pointer to the prepared statement object. Must be properly initialized. + * @param idx 1-based parameter index (SQL parameter numbering starts at 1). + * @param val Pointer to the data buffer to bind. Can be text. + * @param len The actual length of the val cannot be greater than the actual length of the val. + * @param freeFunc Memory disposal callback + * @return int Operation status code: + * - 0: Success + * - Non-zero: Error code (see implementation-specific definitions) + * @note The prepared statement must be in a state that accepts parameter binding. + */ static int RdSqlBindText(GRD_SqlStmt *stmt, uint32_t idx, const void *val, int32_t len, void (*freeFunc)(void *)); static int RdSqlBindInt(GRD_SqlStmt *stmt, uint32_t idx, int32_t val); static int RdSqlBindInt64(GRD_SqlStmt *stmt, uint32_t idx, int64_t val); @@ -72,8 +88,9 @@ public: static int RdDbSetVersion(GRD_DB *db, GRD_ConfigTypeE type, int version); static int RdSqlRegistryThreadPool(GRD_DB *db); + static int RdSqlRegistryClusterAlgo(GRD_DB *db, const char *clstAlgoName, GRD_ClusterAlgoFunc func); private: - static GRD_ThreadPoolT threadPool_; + static GRD_DbThreadPoolT threadPool_; }; } // namespace NativeRdb diff --git a/relational_store/frameworks/native/rdb/include/rdb_icu_manager.h b/relational_store/frameworks/native/rdb/include/rdb_icu_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..d079da921b1e014a64ce802cf078ac6ab0e2afec --- /dev/null +++ b/relational_store/frameworks/native/rdb/include/rdb_icu_manager.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 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_RELATIONAL_STORE_FRAMEWORKS_NATIVE_ICU_MANAGER_H +#define OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_ICU_MANAGER_H +#include +#include +#include +struct sqlite3; +namespace OHOS { +namespace NativeRdb { +class RdbICUManager { +public: + static RdbICUManager &GetInstance(); + int32_t ConfigLocale(sqlite3 *, const std::string &); +private: + RdbICUManager(); + ~RdbICUManager(); + int32_t CleanUp(); + using ConfigICULocaleFunc = int32_t(*)(sqlite3 *, const std::string &); + using CleanUpFunc = int32_t(*)(); + struct ICUAPIInfo { + ConfigICULocaleFunc configIcuLocaleFunc = nullptr; + CleanUpFunc cleanUpFunc = nullptr; + }; + ICUAPIInfo GetApiInfo(); + std::mutex mutex_; + void *handle_ = nullptr; + ICUAPIInfo apiInfo_; +}; + +} // namespace NativeRdb +} // namespace OHOS +#endif //LDBPROJ_RDB_ICU_MANAGER_H diff --git a/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h b/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h index dd0ee95a872920fc257851909ffa4a2037af2c24..af71706dc7da4e953112414328beed6fab403047 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h +++ b/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h @@ -63,6 +63,10 @@ private: void ResetServiceHandle(); + int32_t CleanUp(); + + static sptr LinkToDeath(const sptr &remote); + static std::shared_ptr GetDistributedDataManager(const std::string &bundleName); std::mutex mutex_; @@ -76,7 +80,12 @@ public: explicit RdbStoreDataServiceProxy(const sptr &impl); ~RdbStoreDataServiceProxy() = default; sptr GetFeatureInterface(const std::string &name) override; - int32_t RegisterDeathObserver(const std::string &bundleName, sptr observer) override; + int32_t RegisterDeathObserver(const std::string &bundleName, sptr observer, + const std::string &featureName = DistributedRdb::RdbService::SERVICE_NAME) override; + int32_t Exit(const std::string &featureName = DistributedRdb::RdbService::SERVICE_NAME) override; + +private: + sptr clientDeathObserver_; }; } // namespace OHOS::DistributedRdb #endif diff --git a/relational_store/frameworks/native/rdb/include/rdb_obs_manager.h b/relational_store/frameworks/native/rdb/include/rdb_obs_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..a4d8ec578f75d0b07273e3538b4a02bda5542693 --- /dev/null +++ b/relational_store/frameworks/native/rdb/include/rdb_obs_manager.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 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_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_OBS_MANAGER_H +#define OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_OBS_MANAGER_H +#include +#include +#include + +#include "concurrent_map.h" +#include "rdb_types.h" + +namespace OHOS::NativeRdb { +class RdbObsManager { +public: + RdbObsManager() = default; + virtual ~RdbObsManager(); + int32_t Register(const std::string &uri, std::shared_ptr rdbStoreObserver); + int32_t Unregister(const std::string &uri, std::shared_ptr rdbStoreObserver); + int32_t Notify(const std::string &uri); + +private: + using RegisterFunc = int32_t (*)(const std::string &, std::shared_ptr); + using UnregisterFunc = int32_t (*)(const std::string &, std::shared_ptr); + using NotifyFunc = int32_t (*)(const std::string &); + using CleanFunc = bool (*)(); + struct ObsAPIInfo { + RegisterFunc registerFunc = nullptr; + UnregisterFunc unregisterFunc = nullptr; + NotifyFunc notifyFunc = nullptr; + CleanFunc cleanFunc = nullptr; + }; + static ObsAPIInfo GetApiInfo(); + static int32_t CleanUp(); + static std::mutex mutex_; + static ObsAPIInfo apiInfo_; + static void *handle_; + ConcurrentMap>> obs_; +}; +} // namespace OHOS::NativeRdb +#endif //OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_OBS_MANAGER_H diff --git a/relational_store/frameworks/native/rdb/include/rdb_perfStat.h b/relational_store/frameworks/native/rdb/include/rdb_perfStat.h new file mode 100644 index 0000000000000000000000000000000000000000..14a1afa284a04a801f5f6138469580a2a595550c --- /dev/null +++ b/relational_store/frameworks/native/rdb/include/rdb_perfStat.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2025 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_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_PERFSTAT_H +#define OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_PERFSTAT_H +#include +#include +#include +#include +#include + +#include "rdb_types.h" +#include "rdb_visibility.h" + +namespace OHOS { +template +class ConcurrentMap; +namespace DistributedRdb { +class PerfStat { +public: + struct ThreadParam { + int32_t suspenders_ = 0; + size_t size_ = 0; + }; + enum Step : int32_t { + STEP_TOTAL, + STEP_TOTAL_REF, + STEP_TOTAL_RES, + STEP_WAIT, + STEP_PREPARE, + STEP_EXECUTE, + STEP_TRANS_START, + STEP_TRANS, + STEP_TRANS_END, + STEP_BUTT, + }; + API_EXPORT static int Subscribe(const std::string &storeId, std::shared_ptr observer); + API_EXPORT static int Unsubscribe(const std::string &storeId, std::shared_ptr observer); + static uint32_t GenerateId(); + static void Pause(uint32_t seqId = 0); + static void Resume(uint32_t seqId = 0); + + ~PerfStat(); + PerfStat(const std::string &storeId, const std::string &sql, int32_t step, uint32_t seqId = 0, size_t size = 0); + +private: + using SqlExecInfo = SqlObserver::SqlExecutionInfo; + using Release = std::function; + void FormatSql(const std::string& sql); + static Release GetRelease(int32_t step, uint32_t seqId, const std::string &storeId); + static void Merge(uint32_t seqId, SqlExecInfo *execInfo); + static void Notify(SqlExecInfo *execInfo, const std::string &storeId); + static bool IsPaused(); + static size_t GetSize(); + static void SetSize(size_t size); + static ConcurrentMap>> observers_; + static ConcurrentMap> execInfos_; + static bool enabled_; + static std::atomic_uint32_t seqId_; + static std::shared_mutex mutex_; + static std::map threadParams_; + + int32_t step_ = 0; + uint64_t key_ = 0; + std::chrono::steady_clock::time_point time_; + std::shared_ptr execInfo_; +}; +} // namespace DistributedRdb +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_PERFSTAT_H \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/include/rdb_security_manager.h b/relational_store/frameworks/native/rdb/include/rdb_security_manager.h index af98a09f562b2037e4e7e54178c4ce0bc3e1d3f1..d0efae2a93522bb8e390ae24fe78b1d92cf88aca 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_security_manager.h +++ b/relational_store/frameworks/native/rdb/include/rdb_security_manager.h @@ -26,20 +26,35 @@ #include #include -#include "hks_type.h" - namespace OHOS::NativeRdb { struct RdbSecretKeyData { - uint8_t distributed = 0; + static constexpr uint32_t CURRENT_VERSION = 1; + uint8_t distributed = CURRENT_VERSION; time_t timeValue{}; std::vector secretKey{}; RdbSecretKeyData() = default; ~RdbSecretKeyData() { + distributed = 0; + timeValue = time_t(); secretKey.assign(secretKey.size(), 0); } }; +struct RdbSecretContent { + static constexpr uint32_t MAGIC_NUMBER_V2 = 0x6B6B6B6B; + static constexpr uint32_t NONCE_VALUE_SIZE = 12; + uint32_t magicNum = MAGIC_NUMBER_V2; + std::vector nonceValue{}; + std::vector encryptValue{}; + RdbSecretContent() = default; + ~RdbSecretContent() + { + nonceValue.assign(nonceValue.size(), 0); + encryptValue.assign(encryptValue.size(), 0); + } +}; + class RdbPassword final { public: RdbPassword(); @@ -63,6 +78,12 @@ private: class RdbSecurityManager { public: + enum HksErrCode { + HKS_SUCCESS = 0, + HKS_FAILURE = -1, + HKS_ERROR_NOT_EXIST = -13, + }; + enum KeyFileType : int32_t { PUB_KEY_FILE = 0, PUB_KEY_FILE_NEW_KEY, @@ -75,7 +96,7 @@ public: const std::string &GetKeyFile(KeyFileType type); int32_t InitKeyPath(); int32_t DestroyLock(); - int32_t Lock(); + int32_t Lock(bool isBlock = true); int32_t Unlock(); private: @@ -98,36 +119,39 @@ private: ~RdbSecurityManager(); bool HasRootKey(); - int GenerateRootKey(const std::vector &rootKeyAlias); + void* GetHandle(); + int32_t GenerateRootKey(const std::vector &rootKeyAlias); int32_t CheckRootKeyExists(std::vector &rootKeyAlias); - std::vector EncryptWorkKey(std::vector &key); - bool DecryptWorkKey(std::vector &source, std::vector &key); + std::pair EncryptWorkKey(const std::vector &key); + std::vector DecryptWorkKey(const std::vector &key, const std::vector &nonce); + void ReportCryptFault(int32_t code, const std::string &message); std::vector GenerateRootKeyAlias(const std::string &bundleName); static bool InitPath(const std::string &fileDir); std::vector GenerateRandomNum(int32_t len); bool SaveSecretKeyToFile(const std::string &keyFile, const std::vector &workey = {}); - bool SaveSecretKeyToDisk(const std::string &keyPath, RdbSecretKeyData &keyData); + bool SaveSecretKeyToDisk(const std::string &keyPath, const RdbSecretContent &secretContent); RdbPassword LoadSecretKeyFromFile(const std::string &keyFile); bool LoadSecretKeyFromDisk(const std::string &keyPath, RdbSecretKeyData &keyData); + bool LoadSecretKeyFromDiskV1(const std::string &keyPath, RdbSecretKeyData &keyData); + std::pair UnpackV1(const std::vector &content); + std::pair UnpackV2(const std::vector &content); + std::pair DecryptV1(const RdbSecretContent &content); + std::pair DecryptV2(const RdbSecretContent &content); bool IsKeyFileEmpty(const std::string &keyFile); static bool IsKeyExpired(const time_t &createTime); std::vector GetRootKeyAlias(); std::string GetBundleNameByAlias(); std::string GetBundleNameByAlias(const std::vector &rootKeyAlias); void SetRootKeyAlias(std::vector rootKeyAlias); - int32_t HksLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, - const struct HksBlob *inData, struct HksBlob *outData); - int32_t HksEncryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, - const struct HksBlob *plainText, struct HksBlob *cipherText); - int32_t HksDecryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, - const struct HksBlob *cipherText, struct HksBlob *plainText); + std::string ReplaceSuffix(const std::string& str); static constexpr char const *SUFFIX_KEY_LOCK = ".key_lock"; - static constexpr char const *SUFFIX_PUB_KEY = ".pub_key"; + static constexpr char const *SUFFIX_PUB_KEY = ".pub_key_v1"; static constexpr char const *SUFFIX_PUB_KEY_NEW = ".pub_key.new"; + static constexpr const char *SUFFIX_PUB_KEY_OLD = ".pub_key"; + static constexpr const char *SUFFIX_PUB_TMP_NEW_KEY = ".pub_key.new.bk"; static constexpr const char *RDB_ROOT_KEY_ALIAS_PREFIX = "DistributedDataRdb"; static constexpr const char *RDB_HKS_BLOB_TYPE_NONCE = "Z5s0Bo571Koq"; - static constexpr const char *RDB_HKS_BLOB_TYPE_AAD = "RdbClientAAD"; static constexpr uint32_t TIMES = 4; static constexpr uint32_t MAX_UPDATE_SIZE = 64; static constexpr uint32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES; @@ -140,10 +164,10 @@ private: std::mutex rootKeyMutex_; std::vector rootKeyAlias_{}; - std::vector nonce_; - std::vector aad_; std::mutex mutex_; std::atomic hasRootKey_ = false; + void *handle_; + std::mutex handleMutex_; }; } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h index 244cf49133596a0b67d03ff5f2f9a9e87c3a75a0..1c74a0363f36abc5b3524b694dcba08509d18ce2 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h +++ b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h @@ -20,6 +20,7 @@ #include #include +#include #include "concurrent_map.h" #include "irdb_service.h" @@ -29,7 +30,7 @@ namespace OHOS::DistributedRdb { class RdbServiceProxy : public IRemoteProxy { public: struct ObserverParam { - RdbStoreObserver *observer = nullptr; + std::weak_ptr observer; std::string bundleName; SubscribeOption subscribeOption{ SubscribeMode::REMOTE }; }; @@ -40,8 +41,10 @@ public: }; using SyncObservers = ConcurrentMap>; explicit RdbServiceProxy(const sptr &object); + ~RdbServiceProxy(); - std::string ObtainDistributedTableName(const std::string &device, const std::string &table) override; + std::string ObtainDistributedTableName( + const RdbSyncerParam ¶m, const std::string &device, const std::string &table) override; int32_t InitNotifier(const RdbSyncerParam ¶m); @@ -53,10 +56,11 @@ public: int32_t Sync(const RdbSyncerParam ¶m, const Option &option, const PredicatesMemo &predicates, const AsyncDetail &async) override; - int32_t Subscribe(const RdbSyncerParam ¶m, const SubscribeOption &option, RdbStoreObserver *observer) override; + int32_t Subscribe(const RdbSyncerParam ¶m, const SubscribeOption &option, + std::shared_ptr observer) override; - int32_t UnSubscribe( - const RdbSyncerParam ¶m, const SubscribeOption &option, RdbStoreObserver *observer) override; + int32_t UnSubscribe(const RdbSyncerParam ¶m, const SubscribeOption &option, + std::shared_ptr observer) override; int32_t RegisterAutoSyncCallback( const RdbSyncerParam ¶m, std::shared_ptr observer) override; @@ -101,6 +105,7 @@ public: int32_t VerifyPromiseInfo(const RdbSyncerParam ¶m) override; SyncObservers ExportSyncObservers(); void ImportSyncObservers(SyncObservers &SyncObservers); + void OnRemoteDeadSyncComplete(); private: using ChangeInfo = RdbStoreObserver::ChangeInfo; diff --git a/relational_store/frameworks/native/rdb/include/rdb_sql_log.h b/relational_store/frameworks/native/rdb/include/rdb_sql_log.h new file mode 100644 index 0000000000000000000000000000000000000000..9e09eb65011719186dc2f61c717d762d71e3ea3e --- /dev/null +++ b/relational_store/frameworks/native/rdb/include/rdb_sql_log.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 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_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_SQL_LOG_H +#define OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_SQL_LOG_H +#include +#include +#include +#include + +#include "rdb_types.h" +#include "rdb_visibility.h" + +namespace OHOS { +template +class ConcurrentMap; +namespace NativeRdb { +using ExceptionMessage = DistributedRdb::SqlErrorObserver::ExceptionMessage; +using SqlErrorObserver = DistributedRdb::SqlErrorObserver; +class SqlLog { +public: + SqlLog(); + ~SqlLog(); + API_EXPORT static int Subscribe(const std::string storeId, std::shared_ptr observer); + API_EXPORT static int Unsubscribe(const std::string storeId, std::shared_ptr observer); + static void Notify(const std::string &storeId, const ExceptionMessage &exceptionMessage); + static void Pause(); + static void Resume(); +private: + static bool IsPause(); + static ConcurrentMap>> observerSets_; + static std::atomic enabled_; + static std::shared_mutex mutex_; + static std::map suspenders_; +}; +} // namespace NativeRdb +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_SQL_LOG_H diff --git a/relational_store/frameworks/native/rdb/include/rdb_sql_statistic.h b/relational_store/frameworks/native/rdb/include/rdb_sql_statistic.h index c5926b7e589d7d80351f416ffcd74b996ff88d38..02c99daff95e65513ac3aec0da02f37197b94415 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_sql_statistic.h +++ b/relational_store/frameworks/native/rdb/include/rdb_sql_statistic.h @@ -39,7 +39,6 @@ public: }; API_EXPORT static int Subscribe(std::shared_ptr observer); API_EXPORT static int Unsubscribe(std::shared_ptr observer); - static uint32_t GenerateId(); SqlStatistic(const std::string &sql, int32_t step, uint32_t seqId = 0); ~SqlStatistic(); diff --git a/relational_store/frameworks/native/rdb/include/rdb_store_impl.h b/relational_store/frameworks/native/rdb/include/rdb_store_impl.h index 7088ea05c158151fb41af26eaa02b12ef0ed097c..2313cb98069a4ba295acf1384791689e0440dfb6 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_store_impl.h +++ b/relational_store/frameworks/native/rdb/include/rdb_store_impl.h @@ -25,9 +25,10 @@ #include "concurrent_map.h" #include "connection_pool.h" -#include "data_ability_observer_stub.h" -#include "dataobs_mgr_client.h" +#include "knowledge_schema_helper.h" #include "rdb_errno.h" +#include "rdb_obs_manager.h" +#include "rdb_open_callback.h" #include "rdb_service.h" #include "rdb_store.h" #include "rdb_store_config.h" @@ -43,52 +44,40 @@ class ExecutorPool; namespace OHOS::NativeRdb { class DelayNotify; class RdbStoreLocalDbObserver; +using RdbStoreObserver = DistributedRdb::RdbStoreObserver; class RdbStoreLocalObserver { public: - explicit RdbStoreLocalObserver(DistributedRdb::RdbStoreObserver *observer) : observer_(observer) {}; + explicit RdbStoreLocalObserver(std::shared_ptr observer) : observer_(observer) {}; virtual ~RdbStoreLocalObserver() {}; void OnChange() { - observer_->OnChange(); + auto obs = observer_.lock(); + if (obs != nullptr) { + obs->OnChange(); + } } - DistributedRdb::RdbStoreObserver *getObserver() + std::shared_ptr getObserver() { - return observer_; + return observer_.lock(); } private: - DistributedRdb::RdbStoreObserver *observer_ = nullptr; -}; - -class RdbStoreLocalSharedObserver : public AAFwk::DataAbilityObserverStub { -public: - explicit RdbStoreLocalSharedObserver(DistributedRdb::RdbStoreObserver *observer) : observer_(observer) {}; - virtual ~RdbStoreLocalSharedObserver() {}; - void OnChange() override - { - observer_->OnChange(); - } - DistributedRdb::RdbStoreObserver *getObserver() - { - return observer_; - } - -private: - DistributedRdb::RdbStoreObserver *observer_ = nullptr; + std::weak_ptr observer_; }; class RdbStoreImpl : public RdbStore { public: RdbStoreImpl(const RdbStoreConfig &config); - RdbStoreImpl(const RdbStoreConfig &config, int &errCode); ~RdbStoreImpl() override; + int32_t Init(int version, RdbOpenCallback &openCallback); std::pair Insert(const std::string &table, const Row &row, Resolution resolution) override; std::pair BatchInsert(const std::string &table, const ValuesBuckets &rows) override; - std::pair BatchInsertWithConflictResolution( - const std::string &table, const ValuesBuckets &rows, Resolution resolution) override; - std::pair Update(const std::string &table, const Row &row, const std::string &where, const Values &args, - Resolution resolution) override; - int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) override; + std::pair BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution) override; + std::pair Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) override; + std::pair Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) override; std::shared_ptr QuerySql(const std::string &sql, const Values &args) override; std::shared_ptr QueryByStep(const std::string &sql, const Values &args, bool preCount) override; std::shared_ptr RemoteQuery( @@ -97,6 +86,7 @@ public: const AbsRdbPredicates &predicates, const Fields &columns) override; int ExecuteSql(const std::string &sql, const Values &args) override; std::pair Execute(const std::string &sql, const Values &args, int64_t trxId) override; + std::pair ExecuteExt(const std::string &sql, const Values &args) override; int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const Values &args) override; int ExecuteAndGetString(std::string &outValue, const std::string &sql, const Values &args) override; int ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, const Values &args) override; @@ -116,17 +106,18 @@ public: bool IsMemoryRdb() const override; bool IsHoldingConnection() override; bool IsSlaveDiffFromMaster() const override; - int Backup(const std::string &databasePath, const std::vector &encryptKey) override; + int Backup(const std::string &databasePath, const std::vector &encryptKey, bool verifyDb) override; int Restore(const std::string &backupPath, const std::vector &newKey) override; int Count(int64_t &outValue, const AbsRdbPredicates &predicates) override; int SetDistributedTables(const std::vector &tables, int32_t type, const DistributedRdb::DistributedConfig &distributedConfig) override; + int32_t Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) override; std::string ObtainDistributedTableName(const std::string &device, const std::string &table, int &errCode) override; int Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncBrief &async) override; int Sync(const SyncOption &option, const std::vector &tables, const AsyncDetail &async) override; int Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncDetail &async) override; - int Subscribe(const SubscribeOption &option, RdbStoreObserver *observer) override; - int UnSubscribe(const SubscribeOption &option, RdbStoreObserver *observer) override; + int Subscribe(const SubscribeOption &option, std::shared_ptr observer) override; + int UnSubscribe(const SubscribeOption &option, std::shared_ptr observer) override; int SubscribeObserver(const SubscribeOption &option, const std::shared_ptr &observer) override; int UnsubscribeObserver(const SubscribeOption &option, const std::shared_ptr &observer) override; int RegisterAutoSyncCallback(std::shared_ptr observer) override; @@ -147,10 +138,13 @@ public: int InterruptBackup() override; int32_t GetBackupStatus() const override; std::pair> CreateTransaction(int32_t type) override; + int CleanDirtyLog(const std::string &table, uint64_t cursor) override; + int InitKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema &schema) override; + int RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) override; // not virtual functions / const RdbStoreConfig &GetConfig(); - int ConfigLocale(const std::string &localeStr); + int ConfigLocale(const std::string &localeStr) override; std::string GetName(); std::string GetFileType(); int32_t ExchangeSlaverToMaster(); @@ -179,15 +173,20 @@ private: }; static void AfterOpen(const RdbParam ¶m, int32_t retry = 0); + int32_t ProcessOpenCallback(int version, RdbOpenCallback &openCallback); + int32_t CreatePool(bool &created); static void RegisterDataChangeCallback( std::shared_ptr delayNotifier, std::weak_ptr connPool, int retry); int InnerOpen(); void InitReportFunc(const RdbParam ¶m); void InitSyncerParam(const RdbStoreConfig &config, bool created); + int32_t SetSecurityLabel(const RdbStoreConfig &config); int ExecuteByTrxId(const std::string &sql, int64_t trxId, bool closeConnAfterExecute = false, const std::vector &bindArgs = {}); + std::pair HandleResults( + std::shared_ptr &&statement, const std::string &sql, int32_t code, int sqlType); std::pair HandleDifferentSqlTypes( - std::shared_ptr statement, const std::string &sql, const ValueObject &object, int sqlType); + std::shared_ptr &&statement, const std::string &sql, int32_t code, int sqlType); int CheckAttach(const std::string &sql); std::pair BeginExecuteSql(const std::string &sql); int GetDataBasePath(const std::string &databasePath, std::string &backupFilePath); @@ -195,20 +194,21 @@ private: static int InnerSync(const RdbParam ¶m, const Options &option, const Memo &predicates, const AsyncDetail &async); int InnerBackup(const std::string &databasePath, - const std::vector &destEncryptKey = std::vector()); + const std::vector &destEncryptKey = std::vector(), bool verifyDb = true); ModifyTime GetModifyTimeByRowId(const std::string &logTable, std::vector &keys); - Uri GetUri(const std::string &event); - int SubscribeLocal(const SubscribeOption &option, RdbStoreObserver *observer); - int SubscribeLocalShared(const SubscribeOption &option, RdbStoreObserver *observer); + std::string GetUri(const std::string &event); + int SubscribeLocal(const SubscribeOption &option, std::shared_ptr observer); + int SubscribeLocalShared(const SubscribeOption &option, std::shared_ptr observer); int32_t SubscribeLocalDetail(const SubscribeOption &option, const std::shared_ptr &observer); - int SubscribeRemote(const SubscribeOption &option, RdbStoreObserver *observer); - int UnSubscribeLocal(const SubscribeOption &option, RdbStoreObserver *observer); - int UnSubscribeLocalShared(const SubscribeOption &option, RdbStoreObserver *observer); + int SubscribeRemote(const SubscribeOption &option, std::shared_ptr observer); + int UnSubscribeLocal(const SubscribeOption &option, std::shared_ptr observer); + int UnSubscribeLocalShared(const SubscribeOption &option, std::shared_ptr observer); int32_t UnsubscribeLocalDetail(const SubscribeOption &option, const std::shared_ptr &observer); - int UnSubscribeRemote(const SubscribeOption &option, RdbStoreObserver *observer); + int UnSubscribeRemote(const SubscribeOption &option, std::shared_ptr observer); int RegisterDataChangeCallback(); void InitDelayNotifier(); - std::pair> CreateWritableConn(); + void TryDump(int32_t code, const char *dumpHeader); + static std::pair> CreateWritableConn(const RdbStoreConfig &config); std::vector CreateBackupBindArgs( const std::string &databasePath, const std::vector &destEncryptKey); std::pair GetStatement(const std::string &sql, std::shared_ptr conn) const; @@ -227,23 +227,39 @@ private: int HandleCloudSyncAfterSetDistributedTables( const std::vector &tables, const DistributedRdb::DistributedConfig &distributedConfig); std::pair> GetConn(bool isRead); - void HandleSchemaDDL(std::shared_ptr statement, - std::shared_ptr pool, const std::string &sql, int32_t &errCode); + std::pair ExecuteForRow(const std::string &sql, const Values &args); + static Results GenerateResult(int32_t code, std::shared_ptr statement, bool isDML = true); + static std::shared_ptr GetValues(std::shared_ptr statement); + int32_t HandleSchemaDDL(std::shared_ptr &&statement, const std::string &sql); void BatchInsertArgsDfx(int argsSize); + void SetKnowledgeSchema(); + std::shared_ptr GetKnowledgeSchemaHelper(); + void SwitchOver(bool isUseReplicaDb); + bool TryAsyncRepair(); + bool IsUseAsyncRestore(const std::string &newPath, const std::string &backupPath); + int StartAsyncRestore(std::shared_ptr pool) const; + int StartAsyncBackupIfNeed(std::shared_ptr slaveStatus); + int RestoreInner(const std::string &destPath, const std::vector &newKey, + std::shared_ptr pool); + static int32_t RestoreWithPool(std::shared_ptr pool, const std::string &path); + static bool IsKnowledgeDataChange(const DistributedRdb::RdbChangedData &rdbChangedData); + static bool IsNotifyService(const DistributedRdb::RdbChangedData &rdbChangedData); static constexpr char SCHEME_RDB[] = "rdb://"; static constexpr uint32_t EXPANSION = 2; - static inline constexpr uint32_t INTERVAL = 10; + static inline constexpr uint32_t INTERVAL = 200; + static inline constexpr uint32_t MAX_RETURNING_ROWS = 1024; static inline constexpr uint32_t RETRY_INTERVAL = 5; // s static inline constexpr int32_t MAX_RETRY_TIMES = 5; static constexpr const char *ROW_ID = "ROWID"; bool isOpen_ = false; bool isReadOnly_ = false; - bool isMemoryRdb_; - std::atomic hasRegisterDataChange_ = false; + bool isMemoryRdb_ = false; + bool isUseReplicaDb_ = false; uint32_t rebuild_ = RebuiltType::NONE; - SlaveStatus slaveStatus_ = SlaveStatus::UNDEFINED; + int32_t initStatus_ = -1; + const std::shared_ptr slaveStatus_ = std::make_shared(SlaveStatus::UNDEFINED); int64_t vSchema_ = 0; std::atomic newTrxId_ = 1; const RdbStoreConfig config_; @@ -257,15 +273,19 @@ private: mutable std::shared_mutex rwMutex_; mutable std::shared_mutex poolMutex_; std::mutex mutex_; + std::mutex initMutex_; std::shared_ptr connectionPool_ = nullptr; std::shared_ptr delayNotifier_ = nullptr; std::shared_ptr cloudInfo_ = std::make_shared(); + RdbObsManager obsManger_; std::map>> localObservers_; - std::map>> localSharedObservers_; std::list> localDetailObservers_; ConcurrentMap attachedInfo_; ConcurrentMap> trxConnMap_ = {}; std::list> transactions_; + std::mutex helperMutex_; + std::shared_ptr knowledgeSchemaHelper_; + std::atomic isKnowledgeSchemaReady_{false}; }; } // namespace OHOS::NativeRdb #endif diff --git a/relational_store/frameworks/native/rdb/include/rdb_store_manager.h b/relational_store/frameworks/native/rdb/include/rdb_store_manager.h index 2fecfd5840cc79548dff37499e2c47d3d074648a..58c3a68c18afd7a6d6dce8520cbc941a5a2044ea 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_store_manager.h +++ b/relational_store/frameworks/native/rdb/include/rdb_store_manager.h @@ -37,30 +37,32 @@ public: std::shared_ptr GetRdbStore( const RdbStoreConfig &config, int &errCode, int version, RdbOpenCallback &openCallback); void Clear(); + void Init(); + bool Destroy(); bool Remove(const std::string &path, bool shouldClose); bool Delete(const RdbStoreConfig &config, bool shouldClose); - int SetSecurityLabel(const RdbStoreConfig &config); private: using Param = DistributedRdb::RdbSyncerParam; using Info = DistributedRdb::RdbDebugInfo; using DebugInfos = std::map; using DfxInfo = DistributedRdb::RdbDfxInfo; - int ProcessOpenCallback(RdbStore &rdbStore, int version, RdbOpenCallback &openCallback); bool IsConfigInvalidChanged(const std::string &path, RdbStoreConfig &config); int32_t GetParamFromService(DistributedRdb::RdbSyncerParam ¶m); - static bool IsPermitted(const DistributedRdb::RdbSyncerParam ¶m); - static int32_t CheckConfig(const RdbStoreConfig &config); + bool IsPermitted(const DistributedRdb::RdbSyncerParam ¶m, const std::string &path); + int32_t CheckConfig(const RdbStoreConfig &config, const std::string &path); static Param GetSyncParam(const RdbStoreConfig &config); static int32_t Collector(const RdbStoreConfig &config, DebugInfos &debugInfos, DfxInfo &dfxInfo); - std::shared_ptr GetStoreFromCache(const std::string &path); - std::pair> OpenStore(const RdbStoreConfig &config, const std::string &path); + std::shared_ptr GetStoreFromCache(const std::string &path, + const RdbStoreConfig &config, int &errCode); static constexpr uint32_t BUCKET_MAX_SIZE = 4; + static constexpr uint32_t PROMISEINFO_CACHE_SIZE = 32; static const bool regCollector_; std::mutex mutex_; std::map> storeCache_; LRUBucket configCache_; + LRUBucket promiseInfoCache_; }; } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/include/share_block.h b/relational_store/frameworks/native/rdb/include/share_block.h index 830344c93d598179b6e86529f25b475982df7f43..2b7bbd98805f10027b7d043c73f4617504bba16d 100644 --- a/relational_store/frameworks/native/rdb/include/share_block.h +++ b/relational_store/frameworks/native/rdb/include/share_block.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 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 @@ -20,9 +20,10 @@ #include -#include "shared_block.h" - namespace OHOS { +namespace AppDataFwk { +class SharedBlock; +} namespace NativeRdb { #ifdef __cplusplus extern "C" { diff --git a/relational_store/frameworks/native/rdb/include/sqlite_connection.h b/relational_store/frameworks/native/rdb/include/sqlite_connection.h index b1ab71eff175ce6c65744a67b22cabd5a856fdb8..07b808a0ebdf462eaefae2bf4a001812c62d4dba 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_connection.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_connection.h @@ -23,6 +23,7 @@ #include #include +#include "concurrent_map.h" #include "connection.h" #include "rdb_store_config.h" #include "sqlite3sym.h" @@ -43,35 +44,43 @@ public: static int32_t Delete(const RdbStoreConfig &config); static int32_t Delete(const std::string &path); static int32_t Repair(const RdbStoreConfig &config); - static int32_t Restore(const RdbStoreConfig &config, const std::string &srcPath, const std::string &destPath); static std::map Collect(const RdbStoreConfig &config); - SqliteConnection(const RdbStoreConfig &config, bool isWriteConnection); + static int32_t CheckReplicaIntegrity(const RdbStoreConfig &config); + static int32_t ClientCleanUp(); + static int32_t OpenSSLCleanUp(); + SqliteConnection(const RdbStoreConfig &config, bool isWriteConnection, bool isSlave = false); ~SqliteConnection(); int32_t VerifyAndRegisterHook(const RdbStoreConfig &config) override; int TryCheckPoint(bool timeout) override; int LimitWalSize() override; int ConfigLocale(const std::string &localeStr) override; int CleanDirtyData(const std::string &table, uint64_t cursor) override; - int ReSetKey(const RdbStoreConfig &config) override; + int ResetKey(const RdbStoreConfig &config) override; int32_t GetJournalMode() override; std::pair CreateStatement(const std::string &sql, SConn conn) override; + std::pair CreateReplicaStatement(const std::string &sql, SConn conn) override; + int CheckReplicaForRestore() override; + int32_t Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) override; bool IsWriter() const override; int SubscribeTableChanges(const Notifier ¬ifier) override; int GetMaxVariable() const override; int32_t GetDBType() const override; - int32_t ClearCache() override; + int32_t ClearCache(bool isForceClear = false) override; int32_t Subscribe(const std::shared_ptr &observer) override; int32_t Unsubscribe(const std::shared_ptr &observer) override; int32_t Backup(const std::string &databasePath, const std::vector &destEncryptKey, bool isAsync, - SlaveStatus &slaveStatus) override; + std::shared_ptr slaveStatus, bool verifyDb = true) override; int32_t Restore(const std::string &databasePath, const std::vector &destEncryptKey, - SlaveStatus &slaveStatus) override; - ExchangeStrategy GenerateExchangeStrategy(const SlaveStatus &status) override; - + std::shared_ptr slaveStatus) override; + ExchangeStrategy GenerateExchangeStrategy(std::shared_ptr status, bool isRelpay) override; + int SetKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema &schema) override; + int CleanDirtyLog(const std::string &table, uint64_t cursor) override; + static bool IsSupportBinlog(const RdbStoreConfig &config); protected: std::pair ExecuteForValue( const std::string &sql, const std::vector &bindArgs = std::vector()); int ExecuteSql(const std::string &sql, const std::vector &bindArgs = std::vector()); + int RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) override; private: struct Suffix { @@ -91,17 +100,19 @@ private: int SetEncryptKey(const std::vector &key, const RdbStoreConfig &config); int SetServiceKey(const RdbStoreConfig &config, int32_t errCode); int SetEncryptAgo(const RdbStoreConfig &config); + int SetEncryptAgo(const RdbStoreConfig::CryptoParam &cryptoParam); int SetJournalMode(const RdbStoreConfig &config); int SetAutoCheckpoint(const RdbStoreConfig &config); int SetWalFile(const RdbStoreConfig &config); int SetWalSyncMode(const std::string &syncMode); int SetTokenizer(const RdbStoreConfig &config); + int SetBinlog(); void LimitPermission(const RdbStoreConfig &config, const std::string &dbPath) const; int SetPersistWal(const RdbStoreConfig &config); int SetBusyTimeout(int timeout); - int SetCrcCheck(const RdbStoreConfig &config); void SetDwrEnable(const RdbStoreConfig &config); + void SetIsSupportBinlog(bool isSupport); int RegDefaultFunctions(sqlite3 *dbHandle); int SetCustomFunctions(const RdbStoreConfig &config); @@ -114,36 +125,55 @@ private: RdbStoreConfig GetSlaveRdbStoreConfig(const RdbStoreConfig &rdbConfig); std::pair> CreateSlaveConnection( const RdbStoreConfig &config, SlaveOpenPolicy slaveOpenPolicy); - int ExchangeSlaverToMaster(bool isRestore, bool verifyDb, SlaveStatus &status); + int ExchangeSlaverToMaster(bool isRestore, bool verifyDb, std::shared_ptr curStatus); int ExchangeVerify(bool isRestore); - int SqliteNativeBackup(bool isRestore, SlaveStatus &curStatus); + int SqliteBackupStep(bool isRestore, sqlite3_backup *pBackup, std::shared_ptr curStatus); + int SqliteNativeBackup(bool isRestore, std::shared_ptr curStatus); int VeritySlaveIntegrity(); bool IsDbVersionBelowSlave(); int RegisterStoreObs(); int RegisterClientObs(); int RegisterHookIfNecessary(); + std::pair CreateStatementInner(const std::string &sql, SConn conn, + sqlite3 *db, bool isFromReplica); + void ReplayBinlog(const RdbStoreConfig &config); + ExchangeStrategy CompareWithSlave(int64_t mCount, int64_t mIdxCount); static std::pair> InnerCreate( - const RdbStoreConfig &config, bool isWrite); - static int CopyDb(const RdbStoreConfig &config, const std::string &srcPath, const std::string &destPath); + const RdbStoreConfig &config, bool isWrite, bool isReusableReplica = false); + static void BinlogOnErrFunc(void *pCtx, int errNo, char *errMsg, const char *dbPath); + static void BinlogCloseHandle(sqlite3 *dbHandle); + static int CheckPathExist(const std::string &dbPath); + static int BinlogOpenHandle(const std::string &dbPath, sqlite3 *&dbHandle, bool isMemoryRdb); + static void BinlogSetConfig(sqlite3 *dbHandle); + static void BinlogOnFullFunc(void *pCtx, unsigned short currentCount, const char *dbPath); + static void ReplayBinlog(const std::string &dbPath, + std::shared_ptr slaveConn, bool isNeedClean); + static std::string GetBinlogFolderPath(const std::string &dbPath); + static constexpr const char *BINLOG_FOLDER_SUFFIX = "_binlog"; static constexpr SqliteConnection::Suffix FILE_SUFFIXES[] = { { "", "DB" }, { "-shm", "SHM" }, { "-wal", "WAL" }, { "-dwr", "DWR" }, { "-journal", "JOURNAL" }, { "-slaveFailure", nullptr }, { "-syncInterrupt", nullptr }, - { ".corruptedflg", nullptr }, { "-compare", nullptr } }; + { ".corruptedflg", nullptr }, { "-compare", nullptr }, { "-walcompress", nullptr }, + { "-journalcompress", nullptr }, { "-shmcompress", nullptr } }; static constexpr int CHECKPOINT_TIME = 500; static constexpr int DEFAULT_BUSY_TIMEOUT_MS = 2000; static constexpr int BACKUP_PAGES_PRE_STEP = 12800; // 1024 * 4 * 12800 == 50m static constexpr int BACKUP_PRE_WAIT_TIME = 10; + static constexpr int RESTORE_PRE_WAIT_TIME = 100; static constexpr ssize_t SLAVE_WAL_SIZE_LIMIT = 2147483647; // 2147483647 = 2g - 1 static constexpr ssize_t SLAVE_INTEGRITY_CHECK_LIMIT = 524288000; // 524288000 == 1024 * 1024 * 500 + static constexpr unsigned short BINLOG_FILE_NUMS_LIMIT = 2; + static constexpr uint32_t BINLOG_FILE_SIZE_LIMIT = 1024 * 1024 * 4; // 4194304 == 1024 * 1024 * 4 static constexpr uint32_t NO_ITER = 0; static constexpr uint32_t DB_INDEX = 0; static constexpr uint32_t WAL_INDEX = 2; - static constexpr uint32_t ITER_V1 = 5000; - static constexpr uint32_t SQLITE_CKSUMVFS_RESERVE_BYTES = 8; static const int32_t regCreator_; static const int32_t regRepairer_; static const int32_t regDeleter_; static const int32_t regCollector_; - static const int32_t regRestorer_; + static const int32_t regReplicaChecker_; + static const int32_t regDbClientCleaner_; + static const int32_t regOpenSSLCleaner_; + static ConcurrentMap> reusableReplicas_; using EventHandle = int (SqliteConnection::*)(); struct HandleInfo { RegisterType Type; @@ -159,6 +189,9 @@ private: bool isWriter_; bool isReadOnly_; bool isConfigured_ = false; + bool isSupportBinlog_ = false; + bool isSlave_ = false; + bool isReplay_ = false; JournalMode mode_ = JournalMode::MODE_WAL; int maxVariableNumber_; std::shared_ptr slaveConnection_; diff --git a/relational_store/frameworks/native/rdb/include/sqlite_errno.h b/relational_store/frameworks/native/rdb/include/sqlite_errno.h index 8e643e53f64f7b09d35a36819607f4feec7641d1..6ecde0d1f9221d6b5e821c2c3cb8f94b28ed34ea 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_errno.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_errno.h @@ -27,10 +27,14 @@ #endif namespace OHOS { namespace NativeRdb { -const static std::map ERROR_CODE_MAPPINT_TABLE = { +struct SQLiteErrorCode { + int sqliteError; + int rdbError; +}; +static constexpr SQLiteErrorCode SQLiteErrorCodes[] = { { SQLITE_ERROR, E_SQLITE_ERROR }, - { SQLITE_ABORT, E_SQLITE_ABORT }, { SQLITE_PERM, E_SQLITE_PERM }, + { SQLITE_ABORT, E_SQLITE_ABORT }, { SQLITE_BUSY, E_SQLITE_BUSY }, { SQLITE_LOCKED, E_SQLITE_LOCKED }, { SQLITE_NOMEM, E_SQLITE_NOMEM }, @@ -38,26 +42,49 @@ const static std::map ERROR_CODE_MAPPINT_TABLE = { { SQLITE_IOERR, E_SQLITE_IOERR }, { SQLITE_CORRUPT, E_SQLITE_CORRUPT }, { SQLITE_FULL, E_SQLITE_FULL }, - { SQLITE_SCHEMA, E_SQLITE_SCHEMA }, { SQLITE_CANTOPEN, E_SQLITE_CANTOPEN }, + { SQLITE_SCHEMA, E_SQLITE_SCHEMA }, { SQLITE_TOOBIG, E_SQLITE_TOOBIG }, { SQLITE_CONSTRAINT, E_SQLITE_CONSTRAINT }, { SQLITE_MISMATCH, E_SQLITE_MISMATCH }, { SQLITE_MISUSE, E_SQLITE_MISUSE }, { SQLITE_NOTADB, E_SQLITE_CORRUPT }, - { SQLITE_DONE, E_NO_MORE_ROWS }, - { SQLITE_ROW, E_OK }, { SQLITE_META_RECOVERED, E_SQLITE_META_RECOVERED }, + { SQLITE_ROW, E_OK }, + { SQLITE_DONE, E_NO_MORE_ROWS }, }; + +static constexpr bool IsIncreasing() +{ + for (size_t i = 1; i < sizeof(SQLiteErrorCodes) / sizeof(SQLiteErrorCode); i++) { + if (SQLiteErrorCodes[i].sqliteError <= SQLiteErrorCodes[i - 1].sqliteError) { + return false; + } + } + return true; +} +// JS_ERROR_CODE_MSGS must ensure increment +static_assert(IsIncreasing()); + +static int GetRdbErrorCode(int32_t errorCode) +{ + auto jsErrorCode = SQLiteErrorCode{ errorCode, -errorCode }; + auto iter = std::lower_bound(SQLiteErrorCodes, + SQLiteErrorCodes + sizeof(SQLiteErrorCodes) / sizeof(SQLiteErrorCodes[0]), jsErrorCode, + [](const SQLiteErrorCode &jsErrorCode1, const SQLiteErrorCode &jsErrorCode2) { + return jsErrorCode1.sqliteError < jsErrorCode2.sqliteError; + }); + if (iter < SQLiteErrorCodes + sizeof(SQLiteErrorCodes) / sizeof(SQLiteErrorCodes[0]) && + iter->sqliteError == errorCode) { + return iter->rdbError; + } + return -errorCode; +} class SQLiteError { public: static int ErrNo(int sqliteErr) { - auto iter = ERROR_CODE_MAPPINT_TABLE.find(sqliteErr); - if (iter != ERROR_CODE_MAPPINT_TABLE.end()) { - return iter->second; - } - return -sqliteErr; + return GetRdbErrorCode(sqliteErr); } }; } // namespace NativeRdb diff --git a/relational_store/frameworks/native/rdb/include/sqlite_sql_builder.h b/relational_store/frameworks/native/rdb/include/sqlite_sql_builder.h index d4c636a0700f73e38a60b51f1958c914c456e708..2a2f92fb2072705af778538bd1026e1c16ec079d 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_sql_builder.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_sql_builder.h @@ -30,25 +30,21 @@ public: using BatchRefSqls = std::vector>>>; SqliteSqlBuilder(); ~SqliteSqlBuilder(); - static std::string BuildUpdateString(const ValuesBucket &values, const std::string &tableName, - const std::vector &whereArgs, const std::string &index, const std::string &whereClause, - const std::string &group, const std::string &order, int limit, int offset, std::vector &bindArgs, - ConflictResolution conflictResolution); static int BuildQueryString(bool distinct, const std::string &table, const std::string &joinClause, const std::vector &columns, const std::string &whereClause, const std::string &groupBy, const std::string &indexName, const std::string &orderBy, const int &limit, const int &offset, std::string &outSql); - static std::string BuildSqlStringFromPredicates(const std::string &index, const std::string &joinClause, - const std::string &whereClause, const std::string &group, const std::string &order, int limit, int offset); static std::string BuildQueryString(const AbsRdbPredicates &predicates, const std::vector &columns); static std::string BuildCountString(const AbsRdbPredicates &predicates); - static std::string BuildSqlStringFromPredicates(const AbsPredicates &predicates); + static std::string BuildClauseFromPredicates(const AbsRdbPredicates &predicates); static std::string BuildCursorQueryString(const AbsRdbPredicates &predicates, const std::vector &columns, const std::string &logTable, const std::pair &queryStatus); static std::string BuildLockRowQueryString( const AbsRdbPredicates &predicates, const std::vector &columns, const std::string &logTable); static std::string GetSqlArgs(size_t size); + static void AppendReturning(std::string &sql, const std::vector &fields); + static BatchRefSqls GenerateSqls(const std::string &table, const ValuesBuckets &buckets, int limit, ConflictResolution resolution = ConflictResolution::ON_CONFLICT_REPLACE); static void UpdateAssetStatus(const ValueObject &value, int32_t status); @@ -60,12 +56,13 @@ private: std::string &builder, const std::string &name, const std::string &clause, const std::string &table = ""); static void AppendColumns( std::string &builder, const std::vector &columns, const std::string &table = ""); - + static void AppendLimitAndOffset(std::string &builder, int limit, int offset); + static std::string GetSelectClause(const std::vector &columns, bool IsDistinct, + const std::string &ast, const std::string &table = ""); static constexpr const char *SHARING_RESOURCE = "sharing_resource"; static constexpr uint32_t EXPANSION = 2; static ValueObject nullObject_; static std::reference_wrapper nullRef_; - static std::string HandleTable(const std::string &tableName); }; } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/include/sqlite_statement.h b/relational_store/frameworks/native/rdb/include/sqlite_statement.h index e66eee1475304005dcac2ac820c9a0197593a611..d230ebf6f34310a72bfe9aed68eab8ea65b5ad62 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_statement.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_statement.h @@ -36,7 +36,7 @@ public: static constexpr int COLUMN_TYPE_FLOATS = 1002; static constexpr int COLUMN_TYPE_BIGINT = 1003; - SqliteStatement(); + SqliteStatement(const RdbStoreConfig *config = nullptr); ~SqliteStatement(); int Prepare(const std::string &sql) override; int Bind(const std::vector &args) override; @@ -54,6 +54,7 @@ public: std::pair GetColumnType(int index) const override; std::pair GetSize(int index) const override; std::pair GetColumn(int index) const override; + std::pair> GetRows(uint32_t maxCount) override; bool ReadOnly() const override; bool SupportBlockInfo() const override; int32_t FillBlockInfo(SharedBlockInfo *info) const override; @@ -94,6 +95,7 @@ private: void TableReport(const std::string &errMsg, const std::string &bundleName, ErrMsgState state); void ColumnReport(const std::string &errMsg, const std::string &bundleName, ErrMsgState state); void HandleErrMsg(const std::string &errMsg, const std::string &dbPath, const std::string &bundleName); + void TryNotifyErrorLog(const int &errCode, sqlite3 *dbHandle, const std::string &sql); static constexpr uint32_t BUFFER_LEN = 16; diff --git a/relational_store/frameworks/native/rdb/include/sqlite_utils.h b/relational_store/frameworks/native/rdb/include/sqlite_utils.h index cb25c4786b39e8fcfd73f59ac53351a4cf965c61..8467b59bee248b0e8398e4d0ca3068fdfdb4d89e 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_utils.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_utils.h @@ -51,9 +51,12 @@ public: static constexpr int DISABLE_LOAD_EXTENSION = 0; static constexpr int ENABLE_LOAD_EXTENSION = 1; static constexpr int MAX_LOAD_EXTENSION_COUNT = 16; + static constexpr int PATH_DEPTH = 3; static constexpr const char *REP = "#_"; static constexpr const char *SLAVE_FAILURE = "-slaveFailure"; static constexpr const char *SLAVE_INTERRUPT = "-syncInterrupt"; + static constexpr const char *SLAVE_RESTORE = "-restoring"; + static constexpr ssize_t SLAVE_ASYNC_REPAIR_CHECK_LIMIT = 1073741824; // 1073741824 = 1024 * 1024 * 1024 static int GetSqlStatementType(const std::string &sql); static bool IsSupportSqlForExecute(int sqlType); @@ -61,16 +64,23 @@ public: static bool IsSpecial(int sqlType); static const char *GetConflictClause(int conflictResolution); static std::string StrToUpper(const std::string &s); - static void Replace(std::string &src, const std::string &rep, const std::string &dst); + static std::string Replace(const std::string &src, const std::string &rep, const std::string &dst); static bool DeleteFile(const std::string &filePath); static bool RenameFile(const std::string &srcFile, const std::string &destFile); static bool CopyFile(const std::string &srcFile, const std::string &destFile); - static std::string Anonymous(const std::string &srcFile); + static size_t DeleteFolder(const std::string &folderPath); + API_EXPORT static std::string Anonymous(const std::string &srcFile); + static std::string SqlAnonymous(const std::string &sql); + static std::string GetArea(const std::string &srcFile); static ssize_t GetFileSize(const std::string &fileName); static bool IsSlaveDbName(const std::string &fileName); static std::string GetSlavePath(const std::string &name); static int SetSlaveInvalid(const std::string &dbPath); static int SetSlaveInterrupted(const std::string &dbPath); + static int SetSlaveRestoring(const std::string &dbPath, bool isRestore = true); + static bool IsSlaveRestoring(const std::string &dbPath); + static ssize_t GetDecompressedSize(const std::string &dbPath); + static bool IsSlaveLarge(const std::string &dbPath); static bool IsSlaveInvalid(const std::string &dbPath); static bool IsSlaveInterrupted(const std::string &dbPath); static void SetSlaveValid(const std::string &dbPath); @@ -90,6 +100,8 @@ public: static std::string FormatDebugInfo(const std::map &debugs, const std::string &header); static std::string FormatDebugInfoBrief(const std::map &debugs, const std::string &header); static std::string FormatDfxInfo(const DfxInfo &dfxInfo); + static std::string GetParentModes(const std::string &path, int pathDepth = PATH_DEPTH); + static std::string GetFileStatInfo(const DebugInfo &debugInfo); private: struct SqlType { @@ -118,9 +130,11 @@ private: static constexpr const char *ON_CONFLICT_CLAUSE[CONFLICT_CLAUSE_COUNT] = { "", " OR ROLLBACK", " OR ABORT", " OR FAIL", " OR IGNORE", " OR REPLACE" }; - static std::string GetAnonymousName(const std::string& fileName); - static std::string AnonyDigits(const std::string& fileName); - static std::string GetFileStatInfo(const DebugInfo &debugInfo); + static std::string GetAnonymousName(const std::string &fileName); + static std::string AnonymousDigits(const std::string &digits); + static bool IsKeyword(const std::string& word); + static std::string GetModeInfo(uint32_t st_mode); + static int GetPageCountCallback(void *data, int argc, char **argv, char **azColName); }; } // namespace NativeRdb diff --git a/relational_store/frameworks/native/rdb/include/statement.h b/relational_store/frameworks/native/rdb/include/statement.h index d766fb6fee794d0b4f0884ddb54bc7121fd16690..199cb7a35236361eb7d29bbd204910a7fd3f1479 100644 --- a/relational_store/frameworks/native/rdb/include/statement.h +++ b/relational_store/frameworks/native/rdb/include/statement.h @@ -21,6 +21,7 @@ #include #include "value_object.h" +#include "values_bucket.h" namespace OHOS::NativeRdb { struct SharedBlockInfo; class Statement { @@ -50,6 +51,7 @@ public: virtual std::pair GetColumnType(int32_t index) const = 0; virtual std::pair GetSize(int32_t index) const = 0; virtual std::pair GetColumn(int32_t index) const = 0; + virtual std::pair> GetRows(uint32_t maxCount = 1024) = 0; virtual bool ReadOnly() const = 0; virtual bool SupportBlockInfo() const = 0; virtual int32_t FillBlockInfo(SharedBlockInfo *info) const = 0; diff --git a/relational_store/frameworks/native/rdb/include/string_utils.h b/relational_store/frameworks/native/rdb/include/string_utils.h index b231fed6f7b5437eacafacd6a98b0406f76a54fb..1322af55de97b2177971b31c8d5aec9cd6b2c98a 100644 --- a/relational_store/frameworks/native/rdb/include/string_utils.h +++ b/relational_store/frameworks/native/rdb/include/string_utils.h @@ -31,6 +31,7 @@ public: static std::string ExtractFilePath(const std::string &fileFullName); static std::string ExtractFileName(const std::string &fileFullName); static std::string TruncateAfterFirstParen(const std::string& str); + static std::string GetParentPath(const std::string &path); static bool IsEmpty(std::string source) { return (source.empty()); diff --git a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_transaction.h b/relational_store/frameworks/native/rdb/include/suspender.h similarity index 33% rename from relational_store/frameworks/js/napi/graphstore/include/napi_gdb_transaction.h rename to relational_store/frameworks/native/rdb/include/suspender.h index 9856562316281468576890574de3d7b1dbcda65a..0db4df5c40bba82ee7c9151cc31ad1fbe67d6da2 100644 --- a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_transaction.h +++ b/relational_store/frameworks/native/rdb/include/suspender.h @@ -12,37 +12,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_TRANSACTION_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_TRANSACTION_H -#include -#include -#include -#include - -#include "gdb_transaction.h" -#include "js_proxy.h" -#include "js_uv_queue.h" -#include "napi/native_api.h" -#include "napi/native_common.h" -#include "napi/native_node_api.h" - -namespace OHOS::GraphStoreJsKit { -using Transaction = DistributedDataAip::Transaction; -class GdbTransactionProxy final : public GraphStoreJsKit::JSProxy { +#ifndef OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_SUSPENDER_H +#define OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_SUSPENDER_H +namespace OHOS { +namespace NativeRdb { +class Suspender { public: - GdbTransactionProxy() = default; - ~GdbTransactionProxy(); - explicit GdbTransactionProxy(std::shared_ptr gdbTransaction); - static void Init(napi_env env, napi_value exports); - static napi_value NewInstance(napi_env env, std::shared_ptr value); + enum Flag { + SQL_STATISTIC = 0x1, + SQL_LOG = 0x2, + }; + Suspender(Flag flag); + ~Suspender(); private: - static napi_value Initialize(napi_env env, napi_callback_info info); - static napi_value Read(napi_env env, napi_callback_info info); - static napi_value Write(napi_env env, napi_callback_info info); - static napi_value Commit(napi_env env, napi_callback_info info); - static napi_value Rollback(napi_env env, napi_callback_info info); + Flag flag_; }; -} // namespace OHOS::GraphStoreJsKit -#endif \ No newline at end of file +} // namespace DistributedRdb +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_SUSPENDER_H diff --git a/relational_store/frameworks/native/rdb/include/trans_db.h b/relational_store/frameworks/native/rdb/include/trans_db.h index de97806c88c23e204d949a8b096fbd8ee9714494..4c1da0b986b92455d7da6440f483e2ac45dac6d1 100644 --- a/relational_store/frameworks/native/rdb/include/trans_db.h +++ b/relational_store/frameworks/native/rdb/include/trans_db.h @@ -23,28 +23,34 @@ namespace OHOS::NativeRdb { class TransDB : public RdbStore { public: - TransDB(std::shared_ptr conn, const std::string &name); + TransDB(std::shared_ptr conn, const std::string &path); std::pair Insert(const std::string &table, const Row &row, Resolution resolution) override; std::pair BatchInsert(const std::string &table, const RefRows &rows) override; - std::pair BatchInsertWithConflictResolution( - const std::string &table, const ValuesBuckets &rows, Resolution resolution) override; - std::pair Update(const std::string &table, const Row &row, const std::string &where, const Values &args, - Resolution resolution) override; - int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) override; + std::pair BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution) override; + std::pair Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) override; + std::pair Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) override; std::shared_ptr QuerySql(const std::string &sql, const Values &args) override; std::shared_ptr QueryByStep(const std::string &sql, const Values &args, bool preCount) override; std::pair Execute(const std::string &sql, const Values &args, int64_t trxId) override; + std::pair ExecuteExt(const std::string &sql, const Values &args) override; int GetVersion(int &version) override; int SetVersion(int version) override; int Sync(const SyncOption &option, const std::vector &tables, const AsyncDetail &async) override; private: std::pair> GetStatement(const std::string &sql) const; + void HandleSchemaDDL(std::shared_ptr statement); + static inline constexpr uint32_t MAX_RETURNING_ROWS = 1024; + static Results GenerateResult(int32_t code, std::shared_ptr statement, bool isDML = true); + static std::shared_ptr GetValues(std::shared_ptr statement); int32_t maxArgs_ = 0; int64_t vSchema_ = 0; std::weak_ptr conn_; - std::string name_; + std::string path_; }; } // namespace OHOS::NativeRdb #endif // NATIVE_RDB_TRANS_DB_H \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/include/transaction_impl.h b/relational_store/frameworks/native/rdb/include/transaction_impl.h index 954e3e6a5b4daaf1b494db49c9a1585c91a51708..330fd3d6900fd4c04b5a9164f6dbd95f59eb66ab 100644 --- a/relational_store/frameworks/native/rdb/include/transaction_impl.h +++ b/relational_store/frameworks/native/rdb/include/transaction_impl.h @@ -26,7 +26,7 @@ namespace OHOS::NativeRdb { class RdbStore; class TransactionImpl : public Transaction { public: - TransactionImpl(std::shared_ptr connection, const std::string &name); + TransactionImpl(std::shared_ptr connection, const std::string &path); ~TransactionImpl() override; int32_t Commit() override; @@ -36,22 +36,19 @@ public: std::pair Insert(const std::string &table, const Row &row, Resolution resolution) override; std::pair BatchInsert(const std::string &table, const Rows &rows) override; std::pair BatchInsert(const std::string &table, const RefRows &rows) override; - std::pair BatchInsertWithConflictResolution( - const std::string &table, const RefRows &rows, Resolution resolution) override; - std::pair Update(const std::string &table, const Row &row, const std::string &where, const Values &args, - Resolution resolution) override; - std::pair Update( - const Row &row, const AbsRdbPredicates &predicates, Resolution resolution) override; - std::pair Delete( - const std::string &table, const std::string &whereClause, const Values &args) override; - std::pair Delete(const AbsRdbPredicates &predicates) override; + std::pair BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution) override; + std::pair Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) override; + std::pair Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) override; std::shared_ptr QueryByStep(const std::string &sql, const Values &args, bool preCount) override; std::shared_ptr QueryByStep(const AbsRdbPredicates &predicates, const Fields &columns, bool preCount) override; std::pair Execute(const std::string &sql, const Values &args) override; - + std::pair ExecuteExt(const std::string &sql, const Values &args) override; static std::pair> Create( - int32_t type, std::shared_ptr connection, const std::string &name); + int32_t type, std::shared_ptr connection, const std::string &path); private: static std::string GetBeginSql(int32_t type); @@ -60,7 +57,8 @@ private: std::shared_ptr GetStore(); void AddResultSet(std::weak_ptr resultSet); - std::string name_; + std::string path_; + uint32_t seqId_ = 0; std::recursive_mutex mutex_; std::shared_ptr store_; std::shared_ptr connection_; diff --git a/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h b/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h index 6ed5797e3b3a60b8028ed4dd76a31694f3001838..258565897047a19885d221449e9faca25a2dce38 100644 --- a/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h +++ b/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h @@ -27,6 +27,8 @@ #include "abs_shared_result_set.h" #include "concurrent_map.h" #include "connection_pool.h" +#include "knowledge_schema_helper.h" +#include "rdb_open_callback.h" #include "rdb_store.h" #include "rdb_store_config.h" #include "sqlite_statement.h" @@ -36,19 +38,21 @@ class DelayNotify; class RdbStoreImpl : public RdbStore { public: RdbStoreImpl(const RdbStoreConfig &config); - RdbStoreImpl(const RdbStoreConfig &config, int &errCode); ~RdbStoreImpl() override; + int32_t Init(int version, RdbOpenCallback &openCallback); std::pair Insert(const std::string &table, const Row &row, Resolution resolution) override; std::pair BatchInsert(const std::string &table, const ValuesBuckets &rows) override; - std::pair BatchInsertWithConflictResolution( - const std::string &table, const ValuesBuckets &rows, Resolution resolution) override; - std::pair Update(const std::string &table, const Row &row, const std::string &where, const Values &args, - Resolution resolution) override; - int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) override; + std::pair BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution) override; + std::pair Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) override; + std::pair Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) override; std::shared_ptr QuerySql(const std::string &sql, const Values &args) override; std::shared_ptr QueryByStep(const std::string &sql, const Values &args, bool preCount) override; int ExecuteSql(const std::string &sql, const Values &args) override; std::pair Execute(const std::string &sql, const Values &args, int64_t trxId) override; + std::pair ExecuteExt(const std::string &sql, const Values &args) override; int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const Values &args) override; int ExecuteAndGetString(std::string &outValue, const std::string &sql, const Values &args) override; int ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, const Values &args) override; @@ -68,7 +72,7 @@ public: bool IsMemoryRdb() const override; bool IsHoldingConnection() override; bool IsSlaveDiffFromMaster() const override; - int Backup(const std::string &databasePath, const std::vector &encryptKey) override; + int Backup(const std::string &databasePath, const std::vector &encryptKey, bool verifyDb) override; int Restore(const std::string &backupPath, const std::vector &newKey) override; int Count(int64_t &outValue, const AbsRdbPredicates &predicates) override; int GetRebuilt(RebuiltType &rebuilt) override; @@ -79,8 +83,12 @@ public: int32_t GetBackupStatus() const override; int32_t GetDbType() const override; std::pair> CreateTransaction(int32_t type) override; + int CleanDirtyLog(const std::string &table, uint64_t cursor) override; + int InitKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema &schema) override; + int RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) override; + const RdbStoreConfig &GetConfig(); - int ConfigLocale(const std::string &localeStr); + int ConfigLocale(const std::string &localeStr) override; std::string GetName(); std::string GetFileType(); int32_t ExchangeSlaverToMaster(); @@ -104,19 +112,24 @@ private: }; int InnerOpen(); + int32_t ProcessOpenCallback(int version, RdbOpenCallback &openCallback); + int32_t CreatePool(bool &created); void InitReportFunc(const RdbParam ¶m); void InitSyncerParam(const RdbStoreConfig &config, bool created); + int32_t SetSecurityLabel(const RdbStoreConfig &config); int ExecuteByTrxId(const std::string &sql, int64_t trxId, bool closeConnAfterExecute = false, const std::vector &bindArgs = {}); + std::pair HandleResults( + std::shared_ptr &&statement, const std::string &sql, int32_t code, int sqlType); std::pair HandleDifferentSqlTypes( - std::shared_ptr statement, const std::string &sql, const ValueObject &object, int sqlType); + std::shared_ptr &&statement, const std::string &sql, int32_t code, int sqlType); int CheckAttach(const std::string &sql); std::pair BeginExecuteSql(const std::string &sql); int GetDataBasePath(const std::string &databasePath, std::string &backupFilePath); void DoCloudSync(const std::string &table); int InnerBackup(const std::string& databasePath, - const std::vector &destEncryptKey = std::vector()); - std::pair> CreateWritableConn(); + const std::vector &destEncryptKey = std::vector(), bool verifyDb = true); + static std::pair> CreateWritableConn(const RdbStoreConfig &config); std::vector CreateBackupBindArgs( const std::string &databasePath, const std::vector &destEncryptKey); std::pair GetStatement(const std::string &sql, std::shared_ptr conn) const; @@ -129,27 +142,45 @@ private: int GetSlaveName(const std::string &dbName, std::string &backupFilePath); bool TryGetMasterSlaveBackupPath(const std::string &srcPath, std::string &destPath, bool isRestore = false); void NotifyDataChange(); + void TryDump(int32_t code, const char *dumpHeader); int GetDestPath(const std::string &backupPath, std::string &destPath); std::shared_ptr GetPool() const; int HandleCloudSyncAfterSetDistributedTables( const std::vector &tables, const DistributedRdb::DistributedConfig &distributedConfig); std::pair> GetConn(bool isRead); - void HandleSchemaDDL(std::shared_ptr statement, - std::shared_ptr pool, const std::string &sql, int32_t &errCode); + std::pair ExecuteForRow(const std::string &sql, const Values &args); + static Results GenerateResult(int32_t code, std::shared_ptr statement, bool isDML = true); + static std::shared_ptr GetValues(std::shared_ptr statement); + int32_t HandleSchemaDDL(std::shared_ptr &&statement, const std::string &sql); void BatchInsertArgsDfx(int argsSize); + void SetKnowledgeSchema(); + std::shared_ptr GetKnowledgeSchemaHelper(); + void SwitchOver(bool isUseReplicaDb); + bool TryAsyncRepair(); + bool IsUseAsyncRestore(const std::string &newPath, const std::string &backupPath); + int StartAsyncRestore(std::shared_ptr pool) const; + int StartAsyncBackupIfNeed(std::shared_ptr slaveStatus); + int RestoreInner(const std::string &destPath, const std::vector &newKey, + std::shared_ptr pool); + static int32_t RestoreWithPool(std::shared_ptr pool, const std::string &path); + static bool IsKnowledgeDataChange(const DistributedRdb::RdbChangedData &rdbChangedData); + static bool IsNotifyService(const DistributedRdb::RdbChangedData &rdbChangedData); static constexpr char SCHEME_RDB[] = "rdb://"; static constexpr uint32_t EXPANSION = 2; static inline constexpr uint32_t INTERVAL = 10; + static inline constexpr uint32_t MAX_RETURNING_ROWS = 1024; static inline constexpr uint32_t RETRY_INTERVAL = 5; // s static inline constexpr int32_t MAX_RETRY_TIMES = 5; static constexpr const char *ROW_ID = "ROWID"; bool isOpen_ = false; bool isReadOnly_ = false; - bool isMemoryRdb_; + bool isMemoryRdb_ = false; + bool isUseReplicaDb_ = false; uint32_t rebuild_ = RebuiltType::NONE; - SlaveStatus slaveStatus_ = SlaveStatus::UNDEFINED; + int32_t initStatus_ = -1; + const std::shared_ptr slaveStatus_ = std::make_shared(SlaveStatus::UNDEFINED); int64_t vSchema_ = 0; std::atomic newTrxId_ = 1; const RdbStoreConfig config_; @@ -161,12 +192,18 @@ private: std::string fileType_; mutable std::shared_mutex poolMutex_; std::mutex mutex_; + std::mutex initMutex_; std::shared_ptr connectionPool_ = nullptr; std::shared_ptr delayNotifier_ = nullptr; std::shared_ptr cloudInfo_ = std::make_shared(); ConcurrentMap attachedInfo_; ConcurrentMap> trxConnMap_ = {}; std::list> transactions_; + mutable std::mutex schemaMutex_; + std::shared_ptr knowledgeSchema_; + std::mutex helperMutex_; + std::shared_ptr knowledgeSchemaHelper_; + std::atomic isKnowledgeSchemaReady_{false}; }; } // namespace OHOS::NativeRdb #endif diff --git a/relational_store/frameworks/native/rdb/mock/include/task_executor.h b/relational_store/frameworks/native/rdb/mock/include/task_executor.h deleted file mode 100644 index 5f6426aa54c873d0ba527a524dd68a83ab02fad1..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/rdb/mock/include/task_executor.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -* Copyright (c) 2023 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 DISTRIBUTED_NATIVE_RDB_TASK_EXECUTOR_H -#define DISTRIBUTED_NATIVE_RDB_TASK_EXECUTOR_H -#include -#include -#include -namespace OHOS { -class ExecutorPool { -public: - using TaskId = uint64_t; - using Task = std::function; - using Duration = std::chrono::steady_clock::duration; - static constexpr Duration INVALID_DURATION = std::chrono::milliseconds(0); - static constexpr TaskId INVALID_TASK_ID = static_cast(0l); - static constexpr uint64_t UNLIMITED_TIMES = std::numeric_limits::max(); - ExecutorPool(size_t max, size_t min) - { - } - ~ExecutorPool() - { - } - - TaskId Execute(Task task) - { - return INVALID_TASK_ID; - } - - TaskId Schedule(Duration delay, Task task) - { - return INVALID_TASK_ID; - } - - TaskId Schedule(Task task, Duration interval) - { - return INVALID_TASK_ID; - } - - TaskId Schedule(Task task, Duration delay, Duration interval) - { - return INVALID_TASK_ID; - } - - TaskId Schedule(Task task, Duration delay, Duration interval, uint64_t times) - { - return INVALID_TASK_ID; - } - - bool Remove(TaskId taskId, bool wait = false) - { - return true; - } - - TaskId Reset(TaskId taskId, Duration interval) - { - return INVALID_TASK_ID; - } -}; -namespace NativeRdb { -class TaskExecutor { -public: - using TaskId = ExecutorPool::TaskId; - using Task = std::function; - using Duration = std::chrono::steady_clock::duration; - static constexpr TaskId INVALID_TASK_ID = ExecutorPool::INVALID_TASK_ID; - - static TaskExecutor &GetInstance(); - std::shared_ptr GetExecutor(); - void SetExecutor(std::shared_ptr executor); - -private: - TaskExecutor(); - ~TaskExecutor(); - std::shared_ptr pool_; -}; -} // namespace NativeRdb -} // namespace OHOS -#endif // DISTRIBUTED_DATA_TASK_EXECUTOR_H diff --git a/relational_store/frameworks/native/rdb/mock/src/rdb_fault_hiview_reporter.cpp b/relational_store/frameworks/native/rdb/mock/src/rdb_fault_hiview_reporter.cpp index 2dc6a2b79235c627b9befa36590adffc63ade3ae..feca850787463364e3066838895958f982056776 100644 --- a/relational_store/frameworks/native/rdb/mock/src/rdb_fault_hiview_reporter.cpp +++ b/relational_store/frameworks/native/rdb/mock/src/rdb_fault_hiview_reporter.cpp @@ -47,6 +47,14 @@ void RdbFaultHiViewReporter::DeleteCorruptedFlag(const std::string &dbPath) (void)dbPath; } +void RdbFaultHiViewReporter::ReportRAGFault(const std::string &errMsg, const std::string &functionName, + const std::string &bundleName, const int faultType, const int errCode) +{ + (void)errMsg; + (void)functionName; + (void)bundleName; +} + RdbCorruptedEvent RdbFaultHiViewReporter::Create( const RdbStoreConfig &config, int32_t errCode, const std::string &appendix, bool needSyncParaFromSrv) { @@ -95,15 +103,6 @@ void RdbFaultEvent::Report() const { } -RdbEmptyBlobEvent::RdbEmptyBlobEvent(const std::string &bundleName) - : RdbFaultEvent("", 0, "", "") -{ -} - -void RdbEmptyBlobEvent::Report() const -{ -} - RdbFaultDbFileEvent::RdbFaultDbFileEvent(const std::string &faultType, int32_t errorCode, const RdbStoreConfig &config, const std::string &custLog, bool printDbInfo) : RdbFaultEvent(faultType, errorCode, "", custLog), config_(config) { diff --git a/relational_store/frameworks/native/rdb/mock/src/task_executor.cpp b/relational_store/frameworks/native/rdb/mock/src/task_executor.cpp index a0139a30d4020b756a40b1eb6077f491b1c46fde..f7ea6e491726d3c80e9df38319d314d5ef2501cc 100644 --- a/relational_store/frameworks/native/rdb/mock/src/task_executor.cpp +++ b/relational_store/frameworks/native/rdb/mock/src/task_executor.cpp @@ -16,7 +16,7 @@ #include "task_executor.h" namespace OHOS::NativeRdb { -TaskExecutor::TaskExecutor() : pool_(nullptr) +TaskExecutor::TaskExecutor() { } @@ -31,13 +31,34 @@ TaskExecutor &TaskExecutor::GetInstance() return instance; } +void TaskExecutor::Init() +{ + std::unique_lock lock(mutex_); + if (pool_ != nullptr) { + return; + } + pool_ = std::make_shared(MAX_THREADS, MIN_THREADS, "TaskExecutorRDB"); +}; + std::shared_ptr TaskExecutor::GetExecutor() { + std::unique_lock lock(mutex_); + if (pool_ == nullptr) { + pool_ = std::make_shared(MAX_THREADS, MIN_THREADS, "TaskExecutorRDB"); + } return pool_; } void TaskExecutor::SetExecutor(std::shared_ptr executor) { + std::unique_lock lock(mutex_); pool_ = executor; }; + +bool TaskExecutor::Stop() +{ + std::unique_lock lock(mutex_); + pool_ = nullptr; + return true; +} } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/abs_predicates.cpp b/relational_store/frameworks/native/rdb/src/abs_predicates.cpp index 08b297d123b2f4df97271a45c43f21551e806a1f..9fa79ff1f71e12a794ca862b44e5f557ad9f02ba 100644 --- a/relational_store/frameworks/native/rdb/src/abs_predicates.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_predicates.cpp @@ -255,6 +255,20 @@ AbsPredicates *AbsPredicates::Glob(const std::string &field, const std::string & return this; } +/** + * Configures to match the specified field whose data type is String and the value not contains a wildcard. + */ +AbsPredicates *AbsPredicates::NotGlob(const std::string &field, const std::string &value) +{ + if (!CheckParameter("notGlob", field, { value })) { + return this; + } + CheckIsNeedAnd(); + whereClause += field + " NOT GLOB ? "; + bindArgs.push_back(ValueObject(value)); + return this; +} + /** * Restricts the value of the field to be unequal to the specified value. */ @@ -481,6 +495,16 @@ AbsPredicates *AbsPredicates::NotIn(const std::string &field, const std::vector< return NotIn(field, bindArgs); } +AbsPredicates *AbsPredicates::Having(const std::string &conditions, const std::vector &values) +{ + if (!CheckParameter("having", conditions, {})) { + return this; + } + havingClause = conditions; + bindArgs.insert(bindArgs.end(), values.begin(), values.end()); + return this; +} + /** * Configures to match the specified field whose data type is String array and values are out of a given range. */ @@ -561,7 +585,7 @@ void AbsPredicates::AppendWhereClauseWithInOrNotIn( std::string AbsPredicates::GetStatement() const { - return SqliteSqlBuilder::BuildSqlStringFromPredicates(*this); + return ""; } std::string AbsPredicates::GetWhereClause() const @@ -653,5 +677,10 @@ std::string AbsPredicates::GetIndex() const { return index; } + +std::string AbsPredicates::GetHaving() const +{ + return havingClause; +} } // namespace NativeRdb } // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/abs_rdb_predicates.cpp b/relational_store/frameworks/native/rdb/src/abs_rdb_predicates.cpp index 2ffa84daef740ce2a86af599f1ad64580157b45d..e34e428470cff608d20444da5877b94e35b2ac19 100644 --- a/relational_store/frameworks/native/rdb/src/abs_rdb_predicates.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_rdb_predicates.cpp @@ -19,6 +19,7 @@ #include "logger.h" #include "rdb_trace.h" +#include "sqlite_sql_builder.h" namespace OHOS::NativeRdb { using namespace OHOS::Rdb; @@ -304,6 +305,11 @@ AbsRdbPredicates *AbsRdbPredicates::Glob(const std::string &field, const std::st predicates_.AddOperation(DistributedRdb::GLOB, field, value); return (AbsRdbPredicates *)AbsPredicates::Glob(field, value); } +AbsRdbPredicates *AbsRdbPredicates::NotGlob(const std::string &field, const std::string &value) +{ + predicates_.AddOperation(DistributedRdb::NOT_GLOB, field, value); + return (AbsRdbPredicates *)AbsPredicates::NotGlob(field, value); +} AbsRdbPredicates *AbsRdbPredicates::Distinct() { predicates_.AddOperation(DistributedRdb::DISTINCT, "", ""); @@ -333,4 +339,8 @@ AbsRdbPredicates *AbsRdbPredicates::NotIn(const std::string &field, const std::v predicates_.AddOperation(DistributedRdb::NOT_IN, field, vals); return (AbsRdbPredicates *)AbsPredicates::NotIn(field, values); } +std::string AbsRdbPredicates::GetStatement() const +{ + return SqliteSqlBuilder::BuildClauseFromPredicates(*this); +} } // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp index 467fdc7189aebdb2cb5e5171b20e650f2a4e87e7..d8dc46d4e123c06ffc9c110077177d4dc007ebec 100644 --- a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp @@ -118,7 +118,7 @@ int AbsResultSet::GetAllColumnNames(std::vector &columnNames) } columnNames.resize(columnCount_); for (auto &[name, index] : columnMap_) { - if (index > columnCount_) { + if (index >= columnCount_) { continue; } columnNames[index] = name; @@ -392,8 +392,7 @@ int AbsResultSet::GetColumnIndex(const std::string &columnName, int &columnIndex return E_OK; } - std::string lowerName = columnName; - SqliteUtils::Replace(lowerName, SqliteUtils::REP, ""); + std::string lowerName = SqliteUtils::Replace(columnName, SqliteUtils::REP, ""); auto periodIndex = lowerName.rfind('.'); if (periodIndex != std::string::npos) { lowerName = lowerName.substr(periodIndex + 1); diff --git a/relational_store/frameworks/native/rdb/src/cache_result_set.cpp b/relational_store/frameworks/native/rdb/src/cache_result_set.cpp index 50e8720ac539eb7d664a1e3501fbfadaeacb76aa..a4f9b0a35b2082b59300d34eae5263c36d61f3dc 100644 --- a/relational_store/frameworks/native/rdb/src/cache_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/cache_result_set.cpp @@ -25,6 +25,9 @@ #include "rdb_trace.h" namespace OHOS { namespace NativeRdb { +CacheResultSet::CacheResultSet() : row_(0), maxRow_(0), maxCol_(0) +{ +} CacheResultSet::CacheResultSet(std::vector &&valueBuckets) : row_(0), maxCol_(0), valueBuckets_(std::move(valueBuckets)) { diff --git a/relational_store/frameworks/native/rdb/src/connection.cpp b/relational_store/frameworks/native/rdb/src/connection.cpp index 5588fa22fa5c0b15041036abd5d3296c033b355c..8f36eefb6daf792bb59548c28749d0865d73d778 100644 --- a/relational_store/frameworks/native/rdb/src/connection.cpp +++ b/relational_store/frameworks/native/rdb/src/connection.cpp @@ -22,7 +22,7 @@ static Connection::Creator g_creators[DB_BUTT] = { nullptr, nullptr }; static Connection::Repairer g_repairers[DB_BUTT] = { nullptr, nullptr }; static Connection::Deleter g_fileDeleter[DB_BUTT] = { nullptr, nullptr }; static Connection::Collector g_collectors[DB_BUTT] = { nullptr, nullptr }; -static Connection::Restorer g_restorer[DB_BUTT] = { nullptr, nullptr }; +static Connection::ReplicaChecker g_replicaCheckers[DB_BUTT] = { nullptr, nullptr }; std::pair> Connection::Create(const RdbStoreConfig &config, bool isWriter) { auto dbType = config.GetDBType(); @@ -82,19 +82,18 @@ std::map Connection::Collect(const RdbStoreConfig return collector(config); } -int32_t Connection::Restore(const RdbStoreConfig &config, const std::string &srcPath, const std::string &destPath) +int32_t Connection::CheckReplicaIntegrity(const RdbStoreConfig &config) { auto dbType = config.GetDBType(); if (dbType < static_cast(DB_SQLITE) || dbType >= static_cast(DB_BUTT)) { return E_INVALID_ARGS; } - - auto restorer = g_restorer[dbType]; - if (restorer == nullptr) { + auto replicaChecker = g_replicaCheckers[dbType]; + if (replicaChecker == nullptr) { return E_NOT_SUPPORT; } - return restorer(config, srcPath, destPath); + return replicaChecker(config); } int32_t Connection::RegisterCreator(int32_t dbType, Creator creator) @@ -153,17 +152,17 @@ int32_t Connection::RegisterCollector(int32_t dbType, Collector collector) return E_OK; } -int32_t Connection::RegisterRestorer(int32_t dbType, Restorer restorer) +int32_t Connection::RegisterReplicaChecker(int32_t dbType, ReplicaChecker replicaChecker) { if (dbType < static_cast(DB_SQLITE) || dbType >= static_cast(DB_BUTT)) { return E_INVALID_ARGS; } - if (g_restorer[dbType] != nullptr) { + if (g_replicaCheckers[dbType] != nullptr) { return E_OK; } - g_restorer[dbType] = restorer; + g_replicaCheckers[dbType] = replicaChecker; return E_OK; } diff --git a/relational_store/frameworks/native/rdb/src/connection_pool.cpp b/relational_store/frameworks/native/rdb/src/connection_pool.cpp index 8eff9a1cbeef3d2b9a2732f06c73c3bf1743e781..c993f066bdf3b6abbc8c5f08cbf309cdc97e4698 100644 --- a/relational_store/frameworks/native/rdb/src/connection_pool.cpp +++ b/relational_store/frameworks/native/rdb/src/connection_pool.cpp @@ -30,6 +30,7 @@ #include "rdb_errno.h" #include "rdb_fault_hiview_reporter.h" #include "rdb_sql_statistic.h" +#include "rdb_perfStat.h" #include "sqlite_global_config.h" #include "sqlite_utils.h" #include "task_executor.h" @@ -43,8 +44,10 @@ using ConnPool = ConnectionPool; using SharedConn = std::shared_ptr; using SharedConns = std::vector>; using SqlStatistic = DistributedRdb::SqlStatistic; +using PerfStat = DistributedRdb::PerfStat; using Reportor = RdbFaultHiViewReporter; constexpr int32_t TRANSACTION_TIMEOUT(2); +constexpr int64_t WAIT_TIME = 2; std::shared_ptr ConnPool::Create(const RdbStoreConfig &config, int &errCode) { @@ -64,11 +67,11 @@ std::shared_ptr ConnPool::Create(const RdbStoreConfig &config, int &er } std::string dbPath; (void)SqliteGlobalConfig::GetDbPath(config, dbPath); - LOG_INFO("code:%{public}d app[%{public}s:%{public}s] path[%{public}s] " + LOG_INFO("code:%{public}d app[%{public}s:%{public}s] area[%{public}s] " "cfg[%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d]" "%{public}s", errCode, config.GetBundleName().c_str(), config.GetModuleName().c_str(), - SqliteUtils::Anonymous(dbPath).c_str(), config.GetDBType(), config.GetHaMode(), config.IsEncrypt(), + SqliteUtils::GetArea(dbPath).c_str(), config.GetDBType(), config.GetHaMode(), config.IsEncrypt(), config.GetArea(), config.GetSecurityLevel(), config.GetRoleType(), config.IsReadOnly(), SqliteUtils::FormatDebugInfoBrief(Connection::Collect(config), SqliteUtils::Anonymous(config.GetName())).c_str()); @@ -112,6 +115,31 @@ ConnPool::ConnectionPool(const RdbStoreConfig &storeConfig) attachConfig_.SetJournalMode(JournalMode::MODE_TRUNCATE); trans_.right_ = Container::MIN_TRANS_ID; trans_.left_ = trans_.right_; + clearActuator_ = std::make_shared>, + std::function> & out, std::shared_ptr && input)>>>( + [](auto &out, std::shared_ptr &&input) { + for (auto &node : out) { + if (node.lock() == input) { + return; + } + } + out.push_back(std::move(input)); + }, + FIRST_DELAY_INTERVAL, + MIN_EXECUTE_INTERVAL, + MAX_EXECUTE_INTERVAL); + clearActuator_->SetExecutorPool(TaskExecutor::GetInstance().GetExecutor()); + clearActuator_->SetTask([](std::vector> &&nodes) { + for (auto &node : nodes) { + auto realNode = node.lock(); + if (realNode == nullptr || realNode->connect_ == nullptr) { + continue; + } + realNode->connect_->ClearCache(true); + } + return E_OK; + }); } std::pair> ConnPool::Init(bool isAttach, bool needWriter) @@ -156,6 +184,7 @@ std::pair> ConnPool::Init(bool isAttach, bo ConnPool::~ConnectionPool() { + clearActuator_ = nullptr; CloseAllConnections(); } @@ -231,6 +260,7 @@ void ConnPool::SetInTransaction(bool isInTransaction) std::pair> ConnPool::CreateTransConn(bool limited) { + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_WAIT); if (transCount_.load() >= MAX_TRANS && limited) { trans_.Dump("NO TRANS", transCount_ + isInTransaction_); writers_.Dump("NO TRANS WRITE", transCount_ + isInTransaction_); @@ -246,19 +276,21 @@ std::pair> ConnPool::CreateTransConn(bool l std::shared_ptr ConnPool::AcquireConnection(bool isReadOnly) { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_WAIT); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_WAIT); return Acquire(isReadOnly); } std::pair ConnPool::AcquireAll(int32_t time) { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_WAIT); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_WAIT); using namespace std::chrono; std::pair result; auto &[writer, readers] = result; auto interval = duration_cast(seconds(time)); auto start = steady_clock::now(); auto [res, writerNodes] = writers_.AcquireAll(interval); - if (!res) { + if (!res || writerNodes.empty()) { return {}; } writer = Convert2AutoConn(writerNodes.front()); @@ -316,6 +348,7 @@ std::shared_ptr ConnPool::Acquire(bool isReadOnly, std::chrono::millisecon SharedConn ConnPool::AcquireRef(bool isReadOnly, std::chrono::milliseconds ms) { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_WAIT); + PerfStat perfStat(config_.GetPath(), "", SqlStatistic::Step::STEP_WAIT); if (maxReader_ != 0) { return Acquire(isReadOnly, ms); } @@ -352,7 +385,6 @@ void ConnPool::ReleaseNode(std::shared_ptr node, bool isTrans) trans_.Dump("WAL trans_", transCount); readers_.Dump("WAL readers_", transCount); } - if (node->IsWriter() && (errCode != E_INNER_WARNING && errCode != E_NOT_SUPPORT)) { failedTime_ = errCode != E_OK ? now : steady_clock::time_point(); } @@ -363,6 +395,9 @@ void ConnPool::ReleaseNode(std::shared_ptr node, bool isTrans) auto &container = node->IsWriter() ? writers_ : readers_; container.Release(node); } + if (clearActuator_ != nullptr) { + clearActuator_->Execute>(std::move(node)); + } } int ConnPool::AcquireTransaction() @@ -407,6 +442,17 @@ int ConnPool::RestartConns() return errCode; } +int ConnPool::ReopenConns() +{ + CloseAllConnections(); + auto initRes = Init(); + if (initRes.first != E_OK) { + LOG_ERROR("Init fail, errCode:%{public}d", initRes.first); + return initRes.first; + } + return E_OK; +} + /** * The database locale. */ @@ -416,14 +462,18 @@ int ConnPool::ConfigLocale(const std::string &localeStr) if (errCode != E_OK) { return errCode; } - return writers_.ConfigLocale(localeStr); + errCode = writers_.ConfigLocale(localeStr); + if (errCode != E_OK) { + return errCode; + } + return trans_.ConfigLocale(localeStr); } /** * Rename the backed up database. */ int ConnPool::ChangeDbFileForRestore(const std::string &newPath, const std::string &backupPath, - const std::vector &newKey, SlaveStatus &slaveStatus) + const std::vector &newKey, std::shared_ptr slaveStatus) { if (!writers_.IsFull() || config_.GetPath() == backupPath || newPath == backupPath) { LOG_ERROR("Connection pool is busy now!"); @@ -451,12 +501,13 @@ int ConnPool::ChangeDbFileForRestore(const std::string &newPath, const std::stri } return retVal; } - return RestoreMasterDb(newPath, backupPath, slaveStatus); + return RestoreByDbSqliteType(newPath, backupPath, slaveStatus); } -int ConnPool::RestoreMasterDb(const std::string &newPath, const std::string &backupPath, SlaveStatus &slaveStatus) +int ConnPool::RestoreByDbSqliteType(const std::string &newPath, const std::string &backupPath, + std::shared_ptr slaveStatus) { - if (SqliteUtils::IsSlaveDbName(backupPath) && config_.GetHaMode() == HAMode::MAIN_REPLICA) { + if (SqliteUtils::IsSlaveDbName(backupPath) && config_.GetHaMode() != HAMode::SINGLE) { auto connection = AcquireConnection(false); if (connection == nullptr) { return E_DATABASE_BUSY; @@ -464,8 +515,34 @@ int ConnPool::RestoreMasterDb(const std::string &newPath, const std::string &bac return connection->Restore(backupPath, {}, slaveStatus); } + return RestoreMasterDb(newPath, backupPath); +} + +int ConnPool::RestoreMasterDb(const std::string &newPath, const std::string &backupPath) +{ + if (!CheckIntegrity(backupPath)) { + LOG_ERROR("backup file is corrupted, %{public}s", SqliteUtils::Anonymous(backupPath).c_str()); + return E_SQLITE_CORRUPT; + } + auto walFile = backupPath + "-wal"; + if (SqliteUtils::GetFileSize(walFile) != 0) { + LOG_ERROR("Wal file exist."); + return E_SQLITE_CORRUPT; + } + + SqliteUtils::DeleteFile(backupPath + "-shm"); + SqliteUtils::DeleteFile(backupPath + "-wal"); + CloseAllConnections(); - int ret = Connection::Restore(config_, backupPath, newPath); + Connection::Delete(config_); + + if (config_.GetPath() != newPath) { + RdbStoreConfig config(newPath); + config.SetPath(newPath); + Connection::Delete(config); + } + + bool copyRet = SqliteUtils::CopyFile(backupPath, newPath); int32_t errCode = E_OK; std::shared_ptr pool; for (uint32_t retry = 0; retry < ITERS_COUNT; ++retry) { @@ -485,7 +562,37 @@ int ConnPool::RestoreMasterDb(const std::string &newPath, const std::string &bac LOG_WARN("Restore failed! rebuild res:%{public}d, path:%{public}s.", errCode, SqliteUtils::Anonymous(backupPath).c_str()); } - return ret == E_OK ? errCode : ret; + return copyRet ? errCode : E_ERROR; +} + +int ConnPool::Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) +{ + int errCode = E_OK; + auto [connection, readers] = AcquireAll(WAIT_TIME); + if (connection == nullptr) { + return E_DATABASE_BUSY; + } + CloseAllConnections(); + auto key = config_.GetEncryptKey(); + readers.clear(); + + errCode = connection->Rekey(cryptoParam); + if (errCode != E_OK) { + LOG_ERROR("ReKey failed, err = %{public}d", errCode); + key.assign(key.size(), 0); + return errCode; + } + config_.ResetEncryptKey(cryptoParam.encryptKey_); + connection = nullptr; + auto initRes = Init(); + if (initRes.first != E_OK) { + LOG_ERROR("Init fail, errCode:%{public}d", initRes.first); + config_.ResetEncryptKey(key); + key.assign(key.size(), 0); + initRes = Init(); + return initRes.first; + } + return E_OK; } std::stack &ConnPool::GetTransactionStack() @@ -572,10 +679,13 @@ void ConnPool::Container::InitMembers(Creator creator, int32_t max, int32_t time std::pair> ConnPool::Container::Initialize( Creator creator, int32_t max, int32_t timeout, bool disable, bool acquire) { - InitMembers(creator, max, timeout, disable); std::shared_ptr connNode = nullptr; { std::unique_lock lock(mutex_); + disable_ = disable; + max_ = max; + creator_ = creator; + timeout_ = std::chrono::seconds(timeout); for (int i = 0; i < max_; ++i) { auto errCode = ExtendNode(); if (errCode != E_OK) { @@ -598,16 +708,18 @@ std::pair> ConnPool::Container::Ini int32_t ConnPool::Container::ConfigLocale(const std::string &locale) { std::unique_lock lock(mutex_); - if (total_ != count_) { - return E_DATABASE_BUSY; - } for (auto it = details_.begin(); it != details_.end();) { auto conn = it->lock(); if (conn == nullptr || conn->connect_ == nullptr) { it = details_.erase(it); continue; } - conn->connect_->ConfigLocale(locale); + int32_t errCode = conn->connect_->ConfigLocale(locale); + if (errCode != E_OK) { + LOG_ERROR("ConfigLocale failed %{public}d", errCode); + return errCode; + } + ++it; } return E_OK; } diff --git a/relational_store/frameworks/native/rdb/src/delay_notify.cpp b/relational_store/frameworks/native/rdb/src/delay_notify.cpp index 336af2186440633e46e0d421f573b323b8ce3836..3fbb9b1f1741262127e31dbb413d49a232c2706d 100644 --- a/relational_store/frameworks/native/rdb/src/delay_notify.cpp +++ b/relational_store/frameworks/native/rdb/src/delay_notify.cpp @@ -29,7 +29,7 @@ DelayNotify::~DelayNotify() return; } if (delaySyncTaskId_ != TaskExecutor::INVALID_TASK_ID) { - pool_->Remove(delaySyncTaskId_); + pool_->Remove(delaySyncTaskId_, true); } if (task_ != nullptr && changedData_.tableData.size() > 0) { DistributedRdb::RdbNotifyConfig rdbNotifyConfig; @@ -48,7 +48,7 @@ void DelayNotify::UpdateNotify(const DistributedRdb::RdbChangedData &changedData { std::lock_guard lock(mutex_); for (auto &[k, v] : changedData.tableData) { - if (!v.isTrackedDataChange && !v.isP2pSyncDataChange) { + if (!v.isTrackedDataChange && !v.isP2pSyncDataChange && !v.isKnowledgeDataChange) { continue; } auto it = changedData_.tableData.find(k); @@ -88,8 +88,14 @@ void DelayNotify::StartTimer() } if (delaySyncTaskId_ == TaskExecutor::INVALID_TASK_ID) { + std::weak_ptr delayNotify = shared_from_this(); delaySyncTaskId_ = pool_->Schedule(std::chrono::milliseconds(autoSyncInterval_), - [this]() { ExecuteTask(); }); + [delayNotify]() { + auto lockedDelayNotify = delayNotify.lock(); + if (lockedDelayNotify != nullptr) { + lockedDelayNotify->ExecuteTask(); + } + }); } else { delaySyncTaskId_ = pool_->Reset(delaySyncTaskId_, std::chrono::milliseconds(autoSyncInterval_)); diff --git a/relational_store/frameworks/native/rdb/src/global_resource.cpp b/relational_store/frameworks/native/rdb/src/global_resource.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ab9b15532e626e874df525f673e0cc75191d0930 --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/global_resource.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 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 "global_resource" +#include "global_resource.h" + +#include "rdb_errno.h" + +namespace OHOS::NativeRdb { +static GlobalResource::Cleaner g_cleaners[GlobalResource::CLEAN_BUTT]; +int32_t GlobalResource::RegisterClean(CleanType type, Cleaner clean) +{ + if (type < static_cast(GlobalResource::ICU) || type >= static_cast(GlobalResource::CLEAN_BUTT) || + clean == nullptr) { + return E_INVALID_ARGS; + } + + if (g_cleaners[type] != nullptr) { + return E_OK; + } + + g_cleaners[type] = clean; + return E_OK; +} + +int32_t GlobalResource::CleanUp(int32_t type) +{ + if (type < static_cast(GlobalResource::CLEAN_HEAD) || + type >= static_cast(GlobalResource::CLEAN_BUTT)) { + return E_INVALID_ARGS; + } + + int32_t ret = E_OK; + if (g_cleaners[type] != nullptr) { + ret = g_cleaners[type](); + } + + return ret; +} +} // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/grd_api_manager.cpp b/relational_store/frameworks/native/rdb/src/grd_api_manager.cpp index 5b401c3ad2fa2fe5c759128549c8f764a842d35f..04d7ea2aa64181ba8bdce82cc24def520d2b0258 100644 --- a/relational_store/frameworks/native/rdb/src/grd_api_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/grd_api_manager.cpp @@ -62,7 +62,8 @@ void GRD_DBApiInitEnhance(GRD_APIInfo &GRD_DBApiInfo) GRD_DBApiInfo.DBReKeyApi = (DBReKey)dlsym(g_library, "GRD_DBRekey"); GRD_DBApiInfo.DBGetConfigApi = (DBGetConfig)dlsym(g_library, "GRD_GetConfig"); GRD_DBApiInfo.DBSetConfigApi = (DBSetConfig)dlsym(g_library, "GRD_SetConfig"); - GRD_DBApiInfo.DBSqlRegistryThreadPool = (DBSqlRegistryThreadPool)dlsym(g_library, "GRD_SqlRegistryThreadPool"); + GRD_DBApiInfo.DBSqlRegistryThreadPool = (DBSqlRegistryThreadPool)dlsym(g_library, "GRD_DbRegistryThreadPool"); + GRD_DBApiInfo.DBSqlRegistryClusterAlgo = (DBSqlRegistryClusterAlgo)dlsym(g_library, "GRD_SqlRegistryClusterAlgo"); #endif } diff --git a/relational_store/frameworks/native/rdb/src/knowledge_schema_helper.cpp b/relational_store/frameworks/native/rdb/src/knowledge_schema_helper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f99fe863b41fdb7e7920d8a26903acb330c3185c --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/knowledge_schema_helper.cpp @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2025 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 "KnowledgeSchemaHelper" +#include "knowledge_schema_helper.h" + +#ifndef CROSS_PLATFORM +#include +#endif +#include +#include +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_fault_hiview_reporter.h" +#include "sqlite_utils.h" +#include "task_executor.h" + +namespace OHOS::NativeRdb { +using namespace OHOS::Rdb; + +static constexpr int AIP_MODULE_ID = 13; +constexpr ErrCode AIP_ERR_OFFSET = ErrCodeOffset(SUBSYS_DISTRIBUTEDDATAMNG, AIP_MODULE_ID); +constexpr int32_t KNOWLEDGE_BASE_ERROR_CODE_OFFSET{ 20000 }; +constexpr ErrCode KNOWLEDGE_BASE_FAIL = AIP_ERR_OFFSET + KNOWLEDGE_BASE_ERROR_CODE_OFFSET; +constexpr ErrCode KNOWLEDGE_SCHEMA_NOT_VALID = KNOWLEDGE_BASE_FAIL + 1; + +KnowledgeSchemaHelper::~KnowledgeSchemaHelper() +{ + std::unique_lock writeLock(libMutex_); + if (schemaManager_ != nullptr) { + schemaManager_->StopTask(dbName_); + delete schemaManager_; + schemaManager_ = nullptr; + } +#ifndef CROSS_PLATFORM + if (dlHandle_ != nullptr) { + dlclose(dlHandle_); + dlHandle_ = nullptr; + } +#endif +} + +void KnowledgeSchemaHelper::Init(const RdbStoreConfig &config, const DistributedRdb::RdbKnowledgeSchema &schema) +{ + LoadKnowledgeLib(); + if (!IsLoadLib()) { + LOG_WARN("skip init by miss lib"); + return; + } + std::unique_lock writeLock(libMutex_); + if (schemaManager_ == nullptr) { + LOG_WARN("skip init by miss manager"); + return; + } + schemaManager_->Init(config, schema); + bundleName_ = config.GetBundleName(); + dbName_ = config.GetName(); + inited_ = true; +} + +std::pair KnowledgeSchemaHelper::GetRdbKnowledgeSchema( + const std::string &dbName) +{ + std::pair res; + auto &[errCode, schema] = res; + LoadKnowledgeLib(); + if (!IsLoadLib()) { + LOG_WARN("skip get donate data by miss lib"); + errCode = E_ERROR; + return res; + } + std::shared_lock readLock(libMutex_); + if (schemaManager_ == nullptr) { + LOG_WARN("skip get donate data by miss manager"); + errCode = E_ERROR; + return res; + } + errCode = E_OK; + auto kSchema = schemaManager_->GetRdbKnowledgeSchema(dbName); + if (kSchema == nullptr) { + LOG_WARN("unable to get knowledge schema."); + RdbFaultHiViewReporter::ReportRAGFault("Parse knowledge schema failed", "ParseRdbKnowledgeSchema", bundleName_, + KNOWLEDGE_BASE_FAIL, KNOWLEDGE_SCHEMA_NOT_VALID); + errCode = E_ERROR; + return res; + } + schema = *kSchema; + return res; +} + +void KnowledgeSchemaHelper::DonateKnowledgeData() +{ + if (!inited_) { + LOG_WARN("knowledge schema helper not init."); + return; + } + LoadKnowledgeLib(); + if (!IsLoadLib()) { + LOG_WARN("skip donate data by miss lib"); + return; + } + auto executor = TaskExecutor::GetInstance().GetExecutor(); + if (executor == nullptr) { + LOG_WARN("skip donate data by miss pool"); + return; + } + std::shared_lock readLock(libMutex_); + if (schemaManager_ == nullptr) { + LOG_WARN("skip donate data by miss manager"); + return; + } + std::weak_ptr helper = shared_from_this(); + executor->Execute([helper]() { + auto realHelper = helper.lock(); + if (realHelper == nullptr) { + LOG_WARN("knowledge helper is null"); + return; + } + realHelper->StartTask(); + }); +} + +void KnowledgeSchemaHelper::LoadKnowledgeLib() +{ +#ifndef CROSS_PLATFORM + std::unique_lock writeLock(libMutex_); + if (dlHandle_ != nullptr) { + return; + } + auto handle = dlopen("libaip_knowledge_process.z.so", RTLD_LAZY); + if (handle != nullptr) { + LoadKnowledgeSchemaManager(handle); + dlHandle_ = handle; + } else { + LOG_WARN("unable to load lib, errno: %{public}d, %{public}s", errno, dlerror()); + } +#endif +} + +void KnowledgeSchemaHelper::LoadKnowledgeSchemaManager(void *handle) +{ +#ifndef CROSS_PLATFORM + typedef DistributedRdb::IKnowledgeSchemaManager* (*CreateKnowledgeSchemaManager)(); + auto creator = (CreateKnowledgeSchemaManager)(dlsym(handle, "CreateKnowledgeSchemaManager")); + if (creator == nullptr) { + LOG_WARN("unable to load creator, errno: %{public}d, %{public}s", errno, dlerror()); + return; + } + schemaManager_ = creator(); + if (schemaManager_ != nullptr) { + LOG_INFO("load creator success"); + } else { + LOG_WARN("load creator failed with oom"); + } +#endif +} + +bool KnowledgeSchemaHelper::IsLoadLib() const +{ +#ifndef CROSS_PLATFORM + std::shared_lock readLock(libMutex_); + return dlHandle_ != nullptr; +#else + return false; +#endif +} + +void KnowledgeSchemaHelper::StartTask() +{ + DistributedRdb::IKnowledgeSchemaManager *manager = nullptr; + { + std::shared_lock readLock(libMutex_); + if (schemaManager_ == nullptr) { + LOG_WARN("skip execute donate data by miss manager"); + return; + } + manager = schemaManager_; + } + manager->StartTask(dbName_); +} + +void KnowledgeSchemaHelper::Close() +{ + std::unique_lock writeLock(libMutex_); + if (schemaManager_ != nullptr) { + schemaManager_->StopTask(dbName_); + } +} +} \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rd_connection.cpp b/relational_store/frameworks/native/rdb/src/rd_connection.cpp index f84b475c4fd32206761a989517586b8f3e84efc0..b7c6348f653d17b4a6f3bf51f3f71c8e612742a0 100644 --- a/relational_store/frameworks/native/rdb/src/rd_connection.cpp +++ b/relational_store/frameworks/native/rdb/src/rd_connection.cpp @@ -35,6 +35,7 @@ __attribute__((used)) const int32_t RdConnection::regRepairer_ = Connection::RegisterRepairer(DB_VECTOR, RdConnection::Repair); __attribute__((used)) const int32_t RdConnection::regDeleter_ = Connection::RegisterDeleter(DB_VECTOR, RdConnection::Delete); +constexpr int CONFIG_SIZE_EXCEPT_ENCRYPT = 167; // When modifying config, this item needs to be modified std::pair> RdConnection::Create(const RdbStoreConfig &config, bool isWrite) { @@ -53,33 +54,12 @@ std::pair> RdConnection::Create(const RdbSt errCode = connection->InnerOpen(config); if (errCode == E_OK) { conn = connection; - CheckConfig(connection, config); break; } } return result; } -void RdConnection::CheckConfig(std::shared_ptr conn, const RdbStoreConfig &config) -{ - if (config.GetNcandidates() != NCANDIDATES_DEFAULT_NUM) { - ExecuteSet(conn, "diskann_probe_ncandidates", config.GetNcandidates()); - } -} - -void RdConnection::ExecuteSet(std::shared_ptr conn, const std::string ¶mName, int num) -{ - std::string sql = "SET " + paramName + " = " + std::to_string(num); - auto [errCode, stmt] = conn->CreateStatement(sql, conn); - if (errCode != E_OK || stmt == nullptr) { - LOG_ERROR("Create statement failed, paramName: %{public}s, errCode: %{public}d", - paramName.c_str(), errCode); - return; - } - stmt->Step(); - stmt->Finalize(); -} - int32_t RdConnection::Repair(const RdbStoreConfig &config) { std::string dbPath = ""; @@ -140,12 +120,13 @@ std::string RdConnection::GetConfigStr(const std::vector &keys, bool is std::string config = "{"; if (isEncrypt) { const size_t keyBuffSize = keys.size() * 2 + 1; // 2 hex number can represent a uint8_t, 1 is for '/0' + config.reserve(CONFIG_SIZE_EXCEPT_ENCRYPT + keyBuffSize); char keyBuff[keyBuffSize]; config += "\"isEncrypted\":1,"; config += "\"hexPassword\":\""; config += RdUtils::GetEncryptKey(keys, keyBuff, keyBuffSize); config += "\","; - (void)memset_s(keyBuff, keyBuffSize, 0, keyBuffSize); + std::fill(keyBuff, keyBuff + keyBuffSize, 0); } config += RdConnection::GRD_OPEN_CONFIG_STR; config += "}"; @@ -163,7 +144,7 @@ int RdConnection::InnerOpen(const RdbStoreConfig &config) std::vector newKey = config.GetNewEncryptKey(); if (!newKey.empty()) { newKey.assign(newKey.size(), 0); - errCode = ReSetKey(config); + errCode = ResetKey(config); if (errCode != E_OK) { LOG_ERROR("Can not reset key %{public}d.", errCode); return errCode; @@ -222,6 +203,17 @@ std::pair RdConnection::CreateStatement(const std:: return { ret, stmt }; } +std::pair RdConnection::CreateReplicaStatement([[gnu::unused]] const std::string &sql, + [[gnu::unused]] Connection::SConn conn) +{ + return { E_NOT_SUPPORT, nullptr }; +} + +int RdConnection::CheckReplicaForRestore() +{ + return E_NOT_SUPPORT; +} + int32_t RdConnection::GetDBType() const { return DB_VECTOR; @@ -232,7 +224,7 @@ bool RdConnection::IsWriter() const return isWriter_; } -int32_t RdConnection::ReSetKey(const RdbStoreConfig &config) +int32_t RdConnection::ResetKey(const RdbStoreConfig &config) { if (!IsWriter()) { return E_OK; @@ -280,6 +272,11 @@ int32_t RdConnection::CleanDirtyData(const std::string &table, uint64_t cursor) return E_NOT_SUPPORT; } +int32_t RdConnection::Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) +{ + return E_NOT_SUPPORT; +} + int32_t RdConnection::SubscribeTableChanges(const Connection::Notifier ¬ifier) { return E_NOT_SUPPORT; @@ -295,7 +292,7 @@ int32_t RdConnection::GetJournalMode() return E_NOT_SUPPORT; } -int32_t RdConnection::ClearCache() +int32_t RdConnection::ClearCache(bool isForceClear) { return E_NOT_SUPPORT; } @@ -311,7 +308,7 @@ int32_t RdConnection::Unsubscribe(const std::shared_ptr &destEncryptKey, bool isAsync, - SlaveStatus &slaveStatus) + std::shared_ptr slaveStatus, bool verifyDb) { if (!destEncryptKey.empty() && !config_.IsEncrypt()) { return RdUtils::RdDbBackup(dbHandle_, databasePath.c_str(), destEncryptKey); @@ -326,7 +323,8 @@ int32_t RdConnection::Backup(const std::string &databasePath, const std::vector< } int32_t RdConnection::Restore( - const std::string &databasePath, const std::vector &destEncryptKey, SlaveStatus &slaveStatus) + const std::string &databasePath, const std::vector &destEncryptKey, + std::shared_ptr slaveStatus) { auto ret = RdUtils::RdDbClose(dbHandle_, 0); if (ret != E_OK) { @@ -344,7 +342,8 @@ int32_t RdConnection::Restore( if (ret != E_OK) { LOG_ERROR("Restore failed, original datapath:%{public}s, restorepath:%{public}s, errcode:%{public}d", - config_.GetPath().c_str(), databasePath.c_str(), ret); + SqliteUtils::Anonymous(config_.GetPath()).c_str(), + SqliteUtils::Anonymous(databasePath).c_str(), ret); return ret; } @@ -356,9 +355,31 @@ int32_t RdConnection::Restore( return ret; } -ExchangeStrategy RdConnection::GenerateExchangeStrategy(const SlaveStatus &status) +ExchangeStrategy RdConnection::GenerateExchangeStrategy(std::shared_ptr status, bool isRelpay) { return ExchangeStrategy::NOT_HANDLE; } + +int RdConnection::SetKnowledgeSchema([[gnu::unused]] const DistributedRdb::RdbKnowledgeSchema &schema) +{ + return E_NOT_SUPPORT; +} + +int RdConnection::CleanDirtyLog([[gnu::unused]] const std::string &table, [[gnu::unused]] uint64_t cursor) +{ + return E_NOT_SUPPORT; +} + +int RdConnection::RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) +{ + int errCode = + RdUtils::RdSqlRegistryClusterAlgo(dbHandle_, clstAlgoName.c_str(), reinterpret_cast(func)); + if (errCode != E_OK) { + LOG_ERROR("Can not registry cluster func in rd db %{public}d.", errCode); + return errCode; + } + return E_OK; +} + } // namespace NativeRdb } // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rd_statement.cpp b/relational_store/frameworks/native/rdb/src/rd_statement.cpp index be0b5b0ef1d23326811d96f31a0177ce32eba2a4..98ec42218f5866aaec781b003d991355b1b1cde3 100644 --- a/relational_store/frameworks/native/rdb/src/rd_statement.cpp +++ b/relational_store/frameworks/native/rdb/src/rd_statement.cpp @@ -515,5 +515,10 @@ void RdStatement::GetProperties() { columnCount_ = RdUtils::RdSqlColCnt(stmtHandle_); } + +std::pair> RdStatement::GetRows(uint32_t maxCount) +{ + return { E_NOT_SUPPORT, {} }; +} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/rd_utils.cpp b/relational_store/frameworks/native/rdb/src/rd_utils.cpp index db615d28e6d6ea8d90c26ff55d432da4e1e8c48d..0dd705a5d51b76909ed1e2d4d4b4adfa5e0d0193 100644 --- a/relational_store/frameworks/native/rdb/src/rd_utils.cpp +++ b/relational_store/frameworks/native/rdb/src/rd_utils.cpp @@ -35,7 +35,7 @@ using namespace OHOS::Rdb; static GRD_APIInfo GRD_KVApiInfo; -GRD_ThreadPoolT RdUtils::threadPool_ = { 0 }; +GRD_DbThreadPoolT RdUtils::threadPool_ = { 0 }; struct GrdErrnoPair { int32_t grdCode; @@ -284,7 +284,12 @@ int RdUtils::RdSqlBindBlob(GRD_SqlStmt *stmt, uint32_t idx, const void *val, int if (freeFunc == nullptr) { freeFunc = RdSqlFreeBlob; } - return TransferGrdErrno(GRD_KVApiInfo.DBSqlBindBlob(stmt, idx, tmpVal, len, freeFunc)); + int result = TransferGrdErrno(GRD_KVApiInfo.DBSqlBindBlob(stmt, idx, tmpVal, len, freeFunc)); + if (result != E_OK) { + LOG_ERROR("DBSqlBindBlob failed, error code: %{public}d", result); + freeFunc(tmpVal); + } + return result; } void RdSqlFreeCharStr(void *charStr) @@ -300,7 +305,7 @@ int RdUtils::RdSqlBindText(GRD_SqlStmt *stmt, uint32_t idx, const void *val, int if (GRD_KVApiInfo.DBSqlBindText == nullptr) { return E_NOT_SUPPORT; } - if (len <= 0) { + if (len < 0) { LOG_ERROR("Invalid len %{public}d", len); return E_INVALID_ARGS; } @@ -317,7 +322,12 @@ int RdUtils::RdSqlBindText(GRD_SqlStmt *stmt, uint32_t idx, const void *val, int if (freeFunc == nullptr) { freeFunc = RdSqlFreeCharStr; } - return TransferGrdErrno(GRD_KVApiInfo.DBSqlBindText(stmt, idx, tmpVal, len, freeFunc)); + int result = TransferGrdErrno(GRD_KVApiInfo.DBSqlBindText(stmt, idx, tmpVal, len, freeFunc)); + if (result != E_OK) { + LOG_ERROR("DBSqlBindText failed, error code: %{public}d", result); + freeFunc(tmpVal); + } + return result; } int RdUtils::RdSqlBindInt(GRD_SqlStmt *stmt, uint32_t idx, int32_t val) @@ -394,7 +404,12 @@ int RdUtils::RdSqlBindFloatVector(GRD_SqlStmt *stmt, uint32_t idx, float *val, u if (freeFunc == nullptr) { freeFunc = RdSqlFreeFloatArr; } - return TransferGrdErrno(GRD_KVApiInfo.DBSqlBindFloatVector(stmt, idx, tmpVal, dim, freeFunc)); + int result = TransferGrdErrno(GRD_KVApiInfo.DBSqlBindFloatVector(stmt, idx, tmpVal, dim, freeFunc)); + if (result != E_OK) { + LOG_ERROR("DBSqlBindFloatVector failed, error code: %{public}d", result); + freeFunc(tmpVal); + } + return result; } int RdUtils::RdSqlStep(GRD_SqlStmt *stmt) @@ -639,17 +654,28 @@ int RdUtils::RdDbSetVersion(GRD_DB *db, GRD_ConfigTypeE type, int version) return TransferGrdErrno(GRD_KVApiInfo.DBSetConfigApi(db, type, value)); } -static void Schedule(void *func, void *param) +static uint64_t Schedule(void *func, void *param) { auto pool = TaskExecutor::GetInstance().GetExecutor(); if (pool == nullptr) { - LOG_ERROR("pool is nullptr"); - return; + LOG_ERROR("|Schedule| pool is nullptr"); + return static_cast(TaskExecutor::INVALID_TASK_ID); } - pool->Execute([func, param]() { + TaskExecutor::TaskId taskId = pool->Execute([func, param]() { void (*funcPtr)(void *) = reinterpret_cast(func); funcPtr(param); }); + return static_cast(taskId); +} + +static bool Remove(uint64_t taskId, bool wait) +{ + auto pool = TaskExecutor::GetInstance().GetExecutor(); + if (pool == nullptr) { + LOG_ERROR("|Remove| pool is nullptr"); + return false; + } + return pool->Remove(taskId, wait); } int RdUtils::RdSqlRegistryThreadPool(GRD_DB *db) @@ -661,9 +687,22 @@ int RdUtils::RdSqlRegistryThreadPool(GRD_DB *db) LOG_ERROR("registry threadPool ptr is nullptr"); return E_NOT_SUPPORT; } - RdUtils::threadPool_.schedule = reinterpret_cast(Schedule); + RdUtils::threadPool_.schedule = reinterpret_cast(Schedule); + RdUtils::threadPool_.remove = reinterpret_cast(Remove); return TransferGrdErrno(GRD_KVApiInfo.DBSqlRegistryThreadPool(db, &threadPool_)); } +int RdUtils::RdSqlRegistryClusterAlgo(GRD_DB *db, const char *clstAlgoName, GRD_ClusterAlgoFunc func) +{ + if (GRD_KVApiInfo.DBSqlRegistryClusterAlgo == nullptr) { + GRD_KVApiInfo = GetApiInfoInstance(); + } + if (GRD_KVApiInfo.DBSqlRegistryClusterAlgo == nullptr) { + LOG_ERROR("registry ClusterAlgo ptr is nullptr"); + return E_NOT_SUPPORT; + } + return TransferGrdErrno(GRD_KVApiInfo.DBSqlRegistryClusterAlgo(db, clstAlgoName, func)); +} + } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/rdb_helper.cpp b/relational_store/frameworks/native/rdb/src/rdb_helper.cpp index 67e4d1f97fcad60ae6f914a5371bd114b7b91fd7..6741e8b7f92a09533d3857872293c5a68513aa60 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_helper.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_helper.cpp @@ -15,6 +15,7 @@ #define LOG_TAG "RdbHelper" #include "rdb_helper.h" +#include "global_resource.h" #include "logger.h" #include "rdb_errno.h" #include "rdb_fault_hiview_reporter.h" @@ -28,12 +29,13 @@ #include "security_policy.h" #endif #include "rdb_fault_hiview_reporter.h" +#include namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; using Reportor = RdbFaultHiViewReporter; - +static_assert(ErrCodeOffset(SUBSYS_DISTRIBUTEDDATAMNG, 2) == DISTRIBUTEDDATAMGR_RDB_ERR_OFFSET); std::shared_ptr RdbHelper::GetRdbStore( const RdbStoreConfig &config, int version, RdbOpenCallback &openCallback, int &errCode) { @@ -41,7 +43,9 @@ std::shared_ptr RdbHelper::GetRdbStore( SqliteGlobalConfig::InitSqliteGlobalConfig(); auto rdb = RdbStoreManager::GetInstance().GetRdbStore(config, errCode, version, openCallback); if (errCode != E_OK) { - Reportor::ReportFault(RdbFaultDbFileEvent(FT_OPEN, errCode, config, "LOG:RdbHelper::GetRdbStore", true)); + Reportor::ReportFault(RdbFaultDbFileEvent(FT_OPEN, errCode, config, + SqliteUtils::FormatDebugInfoBrief(Connection::Collect(config), SqliteUtils::Anonymous(config.GetName())), + true)); } return rdb; @@ -53,6 +57,40 @@ void RdbHelper::ClearCache() RdbStoreManager::GetInstance().Clear(); } +bool RdbHelper::Init() +{ + LOG_INFO("Init start"); + RdbStoreManager::GetInstance().Init(); + return true; +} + +bool RdbHelper::Destroy(const DestroyOption &option) +{ + LOG_INFO("Destroy resource start"); + bool ret = RdbStoreManager::GetInstance().Destroy(); + if (option.cleanICU && GlobalResource::CleanUp(GlobalResource::ICU) != E_OK) { + LOG_WARN("CleanUp ICU failed"); + ret = false; + } + if (option.cleanOpenSSL && GlobalResource::CleanUp(GlobalResource::OPEN_SSL) != E_OK) { + LOG_WARN("CleanUp OPEN_SSL failed"); + ret = false; + } + if (GlobalResource::CleanUp(GlobalResource::DB_CLIENT) != E_OK) { + LOG_WARN("CleanUp DB_CLIENT failed"); + ret = false; + } + if (GlobalResource::CleanUp(GlobalResource::OBS) != E_OK) { + LOG_WARN("CleanUp OBS failed"); + ret = false; + } + if (GlobalResource::CleanUp(GlobalResource::IPC) != E_OK) { + LOG_WARN("CleanUp IPC failed"); + ret = false; + } + return ret; +} + int RdbHelper::DeleteRdbStore(const std::string &dbFileName, bool shouldClose) { RdbStoreConfig config(dbFileName); diff --git a/relational_store/frameworks/native/rdb/src/rdb_icu_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_icu_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..43e4e2e5d4360f2351e35c6fe588f0b6dcef68a6 --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/rdb_icu_manager.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2025 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 "RdbICUManager" +#include "rdb_icu_manager.h" + +#include + +#include "global_resource.h" +#include "logger.h" +#include "rdb_errno.h" +namespace OHOS::NativeRdb { +using namespace OHOS::Rdb; +RdbICUManager &RdbICUManager::GetInstance() +{ + static RdbICUManager instance; + return instance; +} + +int32_t RdbICUManager::ConfigLocale(sqlite3 *db, const std::string &localeStr) +{ + auto handle = GetApiInfo(); + if (handle.configIcuLocaleFunc == nullptr) { + LOG_ERROR("dlsym(ConfigLocal) failed!"); + return E_NOT_SUPPORT; + } + return handle.configIcuLocaleFunc(db, localeStr); +} + +RdbICUManager::RdbICUManager() +{ + handle_ = nullptr; +} + +RdbICUManager::~RdbICUManager() +{ + if (handle_ != nullptr) { + dlclose(handle_); + handle_ = nullptr; + } +} + +int32_t RdbICUManager::CleanUp() +{ + auto handle = GetApiInfo(); + if (handle.cleanUpFunc == nullptr) { + LOG_ERROR("dlsym(CleanUp) failed!"); + return E_NOT_SUPPORT; + } + auto code = handle.cleanUpFunc(); + if (code != E_OK) { + return code; + } + std::lock_guard lock(mutex_); + dlclose(handle_); + handle_ = nullptr; + apiInfo_.cleanUpFunc = nullptr; + apiInfo_.configIcuLocaleFunc = nullptr; + return E_OK; +} + +RdbICUManager::ICUAPIInfo RdbICUManager::GetApiInfo() +{ + std::lock_guard lock(mutex_); + if (handle_ != nullptr) { + return apiInfo_; + } + handle_ = dlopen("librelational_store_icu.z.so", RTLD_LAZY); + if (handle_ == nullptr) { + LOG_ERROR("dlopen(librelational_store_icu) failed!"); + return apiInfo_; + } + GlobalResource::RegisterClean(GlobalResource::ICU, []() { return RdbICUManager::GetInstance().CleanUp(); }); + apiInfo_.configIcuLocaleFunc = reinterpret_cast(dlsym(handle_, "ConfigICULocale")); + apiInfo_.cleanUpFunc = reinterpret_cast(dlsym(handle_, "CleanUp")); + return apiInfo_; +} +} // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp index ed6d1f80c3d0f0ae2b22244b2a0add5475f85cf5..552400134b5f0147d7d09b71c083cffdf720a524 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp @@ -17,6 +17,7 @@ #include +#include "global_resource.h" #include "ipc_skeleton.h" #include "irdb_service.h" #include "iservice_registry.h" @@ -31,7 +32,7 @@ using namespace OHOS::Rdb; using RdbServiceProxy = DistributedRdb::RdbServiceProxy; using namespace OHOS::NativeRdb; using namespace OHOS::DistributedRdb::RelationalStore; - +constexpr int32_t MAX_RETRY = 100; class DeathStub : public IRemoteBroker { public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedRdb.DeathStub"); @@ -57,21 +58,22 @@ std::shared_ptr RdbManagerImpl::GetDistributedDataMana sptr observer = new (std::nothrow) DeathStubImpl(); dataService->RegisterDeathObserver(bundleName, observer); - return std::shared_ptr(dataService.GetRefPtr(), [dataService, observer](const auto *) {}); + return std::shared_ptr(dataService.GetRefPtr(), [dataService](const auto *) {}); } -static void LinkToDeath(const sptr &remote) +sptr RdbManagerImpl::LinkToDeath(const sptr &remote) { auto &manager = RdbManagerImpl::GetInstance(); sptr deathRecipient = new (std::nothrow) RdbManagerImpl::ServiceDeathRecipient(&manager); if (deathRecipient == nullptr) { LOG_ERROR("New ServiceDeathRecipient failed."); - return; + return nullptr; } if (!remote->AddDeathRecipient(deathRecipient)) { LOG_ERROR("Add death recipient failed."); } + return deathRecipient; } RdbManagerImpl::RdbManagerImpl() @@ -129,10 +131,16 @@ std::pair> RdbManagerImpl::GetRdbService(co } sptr serviceBase = rdbService; - LinkToDeath(serviceBase->AsObject()); + auto deathRecipient = LinkToDeath(serviceBase->AsObject()); // the rdbService is not null, so rdbService.GetRefPtr() is not null; - rdbService_ = std::shared_ptr(rdbService.GetRefPtr(), [rdbService](const auto *) {}); + rdbService_ = std::shared_ptr(rdbService.GetRefPtr(), [rdbService, deathRecipient](const auto *) { + sptr serviceBase = rdbService; + serviceBase->AsObject()->RemoveDeathRecipient(deathRecipient); + }); param_ = param; + GlobalResource::RegisterClean(GlobalResource::IPC, []() { + return RdbManagerImpl::GetInstance().CleanUp(); + }); return { E_OK, rdbService_ }; } @@ -144,8 +152,12 @@ void RdbManagerImpl::OnRemoteDied() return; } auto proxy = std::static_pointer_cast(rdbService_); + if (proxy == nullptr) { + return; + } auto observers = proxy->ExportObservers(); auto syncObservers = proxy->ExportSyncObservers(); + proxy->OnRemoteDeadSyncComplete(); ResetServiceHandle(); std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME)); @@ -168,6 +180,25 @@ void RdbManagerImpl::ResetServiceHandle() rdbService_ = nullptr; } +int32_t RdbManagerImpl::CleanUp() +{ + std::lock_guard lock(mutex_); + if (distributedDataMgr_ != nullptr) { + auto code = distributedDataMgr_->Exit(); + if (code != E_OK) { + LOG_ERROR("Exit failed.code:%{public}d!", code); + return code; + } + } + distributedDataMgr_ = nullptr; + if (rdbService_.use_count() > 1) { + LOG_WARN("RdbService has other in use:%{public}ld!", rdbService_.use_count()); + return E_ERROR; + } + rdbService_ = nullptr; + return E_OK; +} + RdbStoreDataServiceProxy::RdbStoreDataServiceProxy(const sptr &impl) : IRemoteProxy(impl) { @@ -204,7 +235,8 @@ sptr RdbStoreDataServiceProxy::GetFeatureInterface(const std::str return remoteObject; } -int32_t RdbStoreDataServiceProxy::RegisterDeathObserver(const std::string &bundleName, sptr observer) +int32_t RdbStoreDataServiceProxy::RegisterDeathObserver( + const std::string &bundleName, sptr observer, const std::string &featureName) { MessageParcel data; if (!data.WriteInterfaceToken(RdbStoreDataServiceProxy::GetDescriptor())) { @@ -212,7 +244,7 @@ int32_t RdbStoreDataServiceProxy::RegisterDeathObserver(const std::string &bundl return E_ERROR; } - if (!ITypesUtil::Marshal(data, bundleName, observer)) { + if (!ITypesUtil::Marshal(data, bundleName, observer, featureName)) { LOG_ERROR("Write descriptor failed."); return E_ERROR; } @@ -228,6 +260,46 @@ int32_t RdbStoreDataServiceProxy::RegisterDeathObserver(const std::string &bundl int32_t status = E_ERROR; ITypesUtil::Unmarshal(reply, status); + if (status == E_OK) { + clientDeathObserver_ = observer; + } + return status; +} + +int32_t RdbStoreDataServiceProxy::Exit(const std::string &featureName) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(RdbStoreDataServiceProxy::GetDescriptor())) { + LOG_ERROR("Write descriptor failed."); + return E_ERROR; + } + + if (!ITypesUtil::Marshal(data, featureName)) { + LOG_ERROR("Write descriptor failed."); + return E_ERROR; + } + + MessageParcel reply; + MessageOption mo{ MessageOption::TF_SYNC }; + int32_t error = Remote()->SendRequest(static_cast(KvStoreInterfaceCode::FEATURE_EXIT), data, reply, mo); + if (error != 0) { + LOG_ERROR("SendRequest returned %{public}d", error); + return E_ERROR; + } + + int32_t status = E_ERROR; + ITypesUtil::Unmarshal(reply, status); + if (status == E_OK) { + int32_t retry = 0; + while (clientDeathObserver_ != nullptr && clientDeathObserver_->GetSptrRefCount() > 1 && retry < MAX_RETRY) { + retry++; + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + if (clientDeathObserver_ != nullptr && clientDeathObserver_->GetSptrRefCount() > 1) { + LOG_WARN("observer still in use! count:%{public}d", clientDeathObserver_->GetSptrRefCount()); + return E_ERROR; + } + } return status; } } // namespace OHOS::DistributedRdb diff --git a/relational_store/frameworks/native/rdb/src/rdb_obs_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_obs_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4cf9b09d9d32130c26f4c49b2a0d99e5ba2094f0 --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/rdb_obs_manager.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2025 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 "RdbObsManager" + +#include "rdb_obs_manager.h" + +#include + +#include "global_resource.h" +#include "logger.h" +#include "obs_mgr_adapter.h" +#include "rdb_errno.h" +#include "sqlite_utils.h" + +namespace OHOS::NativeRdb { +using RdbStoreObserver = DistributedRdb::RdbStoreObserver; +using namespace OHOS::Rdb; +std::mutex RdbObsManager::mutex_; +RdbObsManager::ObsAPIInfo RdbObsManager::apiInfo_; +void *RdbObsManager::handle_ = nullptr; +RdbObsManager::~RdbObsManager() +{ + if (obs_.Empty()) { + return; + } + auto handle = GetApiInfo(); + if (handle.unregisterFunc == nullptr) { + LOG_ERROR("dlsym(Unregister) failed"); + return; + } + obs_.ForEach([handle](const auto &key, auto &value) { + for (auto &obs : value) { + handle.unregisterFunc(key, obs); + } + return false; + }); +} + +RdbObsManager::ObsAPIInfo RdbObsManager::GetApiInfo() +{ + std::lock_guard lock(mutex_); + if (handle_ != nullptr) { + return apiInfo_; + } + handle_ = dlopen("librdb_obs_mgr_adapter.z.so", RTLD_LAZY); + if (handle_ == nullptr) { + LOG_ERROR("dlopen(librdb_obs_mgr_adapter) failed(%{public}d)!", errno); + return apiInfo_; + } + GlobalResource::RegisterClean(GlobalResource::OBS, CleanUp); + apiInfo_.registerFunc = reinterpret_cast(dlsym(handle_, "Register")); + apiInfo_.unregisterFunc = reinterpret_cast(dlsym(handle_, "Unregister")); + apiInfo_.notifyFunc = reinterpret_cast(dlsym(handle_, "NotifyChange")); + apiInfo_.cleanFunc = reinterpret_cast(dlsym(handle_, "CleanUp")); + return apiInfo_; +} + +int32_t RdbObsManager::CleanUp() +{ + auto handle = GetApiInfo(); + if (handle.cleanFunc == nullptr) { + LOG_ERROR("dlsym(CleanUp) fail!"); + return E_ERROR; + } + if (!handle.cleanFunc()) { + return E_ERROR; + } + std::lock_guard lock(mutex_); + dlclose(handle_); + handle_ = nullptr; + apiInfo_.registerFunc = nullptr; + apiInfo_.unregisterFunc = nullptr; + apiInfo_.notifyFunc = nullptr; + apiInfo_.cleanFunc = nullptr; + return E_OK; +} + +int32_t RdbObsManager::Register(const std::string &uri, std::shared_ptr obs) +{ + auto handle = GetApiInfo(); + if (handle.registerFunc == nullptr) { + LOG_ERROR("dlsym(Register) fail!, uri:%{public}s", SqliteUtils::Anonymous(uri).c_str()); + return E_ERROR; + } + auto code = handle.registerFunc(uri, obs); + if (code == E_OK) { + obs_.Compute(uri, [obs](const auto &key, auto &value) { + value.push_back(obs); + return !value.empty(); + }); + return E_OK; + } + return code == RDB_OBS_DUPLICATE_SUB ? E_OK : code; +} + +int32_t RdbObsManager::Unregister(const std::string &uri, std::shared_ptr obs) +{ + auto handle = GetApiInfo(); + if (handle.unregisterFunc == nullptr) { + LOG_ERROR("dlsym(Unregister) fail!, uri:%{public}s", SqliteUtils::Anonymous(uri).c_str()); + return E_ERROR; + } + auto code = handle.unregisterFunc(uri, obs); + if (code != E_OK) { + return code; + } + obs_.Compute(uri, [obs](const auto &key, auto &value) { + if (obs == nullptr) { + value.clear(); + } + for (auto it = value.begin(); it != value.end();) { + if (*it == obs) { + value.erase(it); + break; + } + ++it; + } + return !value.empty(); + }); + return code; +} + +int32_t RdbObsManager::Notify(const std::string &uri) +{ + auto handle = GetApiInfo(); + if (handle.notifyFunc == nullptr) { + LOG_ERROR("dlsym(NotifyChange) fail! uri:%{public}s", SqliteUtils::Anonymous(uri).c_str()); + return E_ERROR; + } + return handle.notifyFunc(uri); +} + +} // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_perfStat.cpp b/relational_store/frameworks/native/rdb/src/rdb_perfStat.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bf6c2ba8232eed0e030eff305963dbfc92fa4a7d --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/rdb_perfStat.cpp @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2025 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 "RdbPerfStat" +#include "rdb_perfStat.h" + +#include + +#include "concurrent_map.h" +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_platform.h" +#include "sqlite_utils.h" +#include "task_executor.h" +namespace OHOS::DistributedRdb { +using namespace OHOS::Rdb; +using namespace OHOS::NativeRdb; +using SqlExecInfo = SqlObserver::SqlExecutionInfo; +std::shared_mutex PerfStat::mutex_; +std::map PerfStat::threadParams_; +ConcurrentMap>> PerfStat::observers_; +ConcurrentMap> PerfStat::execInfos_; +bool PerfStat::enabled_ = false; +std::atomic_uint32_t PerfStat::seqId_ = 0; +int PerfStat::Subscribe(const std::string &storeId, std::shared_ptr observer) +{ + observers_.Compute(storeId, [observer](const auto &, auto &observers) { + observers.insert(observer); + enabled_ = true; + return true; + }); + return E_OK; +} + +int PerfStat::Unsubscribe(const std::string &storeId, std::shared_ptr observer) +{ + observers_.ComputeIfPresent(storeId, [observer](const auto &key, auto &observers) { + observers.erase(observer); + return !observers.empty(); + }); + observers_.DoActionIfEmpty([]() { + enabled_ = false; + execInfos_.Clear(); + std::unique_lock lock(mutex_); + threadParams_.clear(); + }); + return E_OK; +} + +uint32_t PerfStat::GenerateId() +{ + return ++seqId_; +} + +PerfStat::PerfStat(const std::string &storeId, const std::string &sql, int32_t step, uint32_t seqId, size_t size) +{ + if (!enabled_ || IsPaused()) { + return; + } + auto storeObservers = observers_.Find(storeId); + if (!storeObservers.first) { + return; + } + + step_ = step; + key_ = (seqId == 0) ? GetThreadId() : uint64_t(seqId); + time_ = std::chrono::steady_clock::now(); + + if (step == STEP_TOTAL || step == STEP_TRANS || step == STEP_TRANS_END) { + execInfo_ = std::shared_ptr(new (std::nothrow) SqlExecInfo(), GetRelease(step, seqId, storeId)); + execInfos_.Insert(GetThreadId(), execInfo_); + } else { + auto it = execInfos_.Find(key_); + if (it.first) { + execInfo_ = it.second; + } + } + + if (execInfo_ == nullptr && seqId != 0) { + auto it = execInfos_.Find(GetThreadId()); + execInfo_ = it.second; + } + + if (step_ == STEP_TRANS_START && execInfo_ != nullptr) { + execInfos_.Insert(seqId, execInfo_); + } + + if ((step_ == STEP_TOTAL || step_ == STEP_TRANS) && size > 0) { + SetSize(size); + } + + if (step_ == STEP_PREPARE && !sql.empty() && execInfo_ != nullptr) { + FormatSql(sql); + } +} + +PerfStat::~PerfStat() +{ + if (!enabled_ || IsPaused()) { + return; + } + if (execInfo_ == nullptr) { + return; + } + + auto interval = std::chrono::duration_cast(std::chrono::steady_clock::now() - time_); + switch (step_) { + case STEP_WAIT: + execInfo_->waitTime_ += interval.count(); + break; + case STEP_PREPARE: + execInfo_->prepareTime_ += interval.count(); + break; + case STEP_EXECUTE: + execInfo_->executeTime_ += interval.count(); + break; + case STEP_TOTAL: + SetSize(0); + [[fallthrough]]; + case STEP_TOTAL_RES: + execInfo_->totalTime_ += interval.count(); + execInfos_.Erase(key_); + break; + case STEP_TRANS: + execInfo_->totalTime_ += interval.count(); + execInfos_.Erase(GetThreadId()); + SetSize(0); + break; + case STEP_TRANS_END: + execInfo_->totalTime_ += interval.count(); + execInfos_.Erase(GetThreadId()); + execInfo_ = nullptr; + execInfos_.Erase(key_); + break; + default: + execInfo_->totalTime_ += interval.count(); + break; + } +} + +PerfStat::Release PerfStat::GetRelease(int32_t step, uint32_t seqId, const std::string &storeId) +{ + switch (step) { + case STEP_TRANS: + [[fallthrough]]; + case STEP_TRANS_END: + return [seqId](SqlExecInfo *execInfo) { + Merge(seqId, execInfo); + }; + default: + return [seqId, storeId](SqlExecInfo *execInfo) { + Notify(execInfo, storeId); + }; + } +} + +void PerfStat::Merge(uint32_t seqId, SqlExecInfo *execInfo) +{ + if (execInfo == nullptr) { + return; + } + if (execInfo->sql_.empty()) { + delete execInfo; + return; + } + execInfos_.ComputeIfPresent(seqId, [execInfo](const auto &, std::shared_ptr info) { + info->totalTime_ += execInfo->totalTime_; + info->waitTime_ += execInfo->waitTime_; + info->prepareTime_ += execInfo->prepareTime_; + info->executeTime_ += execInfo->executeTime_; + info->sql_.insert(info->sql_.end(), execInfo->sql_.begin(), execInfo->sql_.end()); + return true; + }); + delete execInfo; +} + +void PerfStat::Notify(SqlExecInfo *execInfo, const std::string &storeId) +{ + if (execInfo == nullptr) { + return; + } + if (execInfo->sql_.empty()) { + delete execInfo; + return; + } + auto executor = TaskExecutor::GetInstance().GetExecutor(); + if (executor == nullptr) { + delete execInfo; + return; + } + executor->Execute([info = std::move(*execInfo), storeId]() { + std::set> sqlObservers; + observers_.ComputeIfPresent(storeId, [&sqlObservers](const auto &, auto &observers) { + sqlObservers = observers; + return true; + }); + for (auto &obs : sqlObservers) { + if (obs != nullptr) { + obs->OnStatistic(info); + } + } + }); + delete execInfo; +} +void PerfStat::Pause(uint32_t seqId) +{ + std::unique_lock lock(mutex_); + threadParams_[GetThreadId()].suspenders_ = std::max(1, threadParams_[GetThreadId()].suspenders_ + 1); +} +void PerfStat::Resume(uint32_t seqId) +{ + std::unique_lock lock(mutex_); + threadParams_[GetThreadId()].suspenders_ = std::max(0, threadParams_[GetThreadId()].suspenders_ - 1); +} + +void PerfStat::FormatSql(const std::string &sql) +{ + auto size = GetSize(); + if (size == 0) { + execInfo_->sql_.emplace_back(sql); + return; + } + if (size > 0 && execInfo_->sql_.size() > 0) { + return; + } + size_t firstPos = sql.find("),("); + if (firstPos != std::string::npos) { + std::string newSql = sql.substr(0, firstPos + 1); + newSql.append(",...,").append(std::to_string(size)); + execInfo_->sql_.emplace_back(std::move(newSql)); + return; + } + execInfo_->sql_.emplace_back(sql); +} + +bool PerfStat::IsPaused() +{ + std::shared_lock lock(mutex_); + auto it = threadParams_.find(GetThreadId()); + return it != threadParams_.end() && it->second.suspenders_ > 0; +} + +size_t PerfStat::GetSize() +{ + std::shared_lock lock(mutex_); + auto it = threadParams_.find(GetThreadId()); + return it != threadParams_.end() ? it->second.size_ : 0; +} + +void PerfStat::SetSize(size_t size) +{ + std::unique_lock lock(mutex_); + threadParams_[GetThreadId()].size_ = size; +} +} // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_security_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_security_manager.cpp index 68a0be70b6bdb1ca25fe596305187d2329c89c72..4ef3ae6cbe1f6e09f1d12ce7486e4e3b05ce0fc2 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_security_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_security_manager.cpp @@ -15,6 +15,8 @@ #define LOG_TAG "RdbSecurityManager" #include "rdb_security_manager.h" +#include +#include #include #include #include @@ -25,20 +27,25 @@ #include "directory_ex.h" #include "file_ex.h" -#include "hks_api.h" -#include "hks_param.h" #include "logger.h" #include "rdb_errno.h" #include "rdb_platform.h" #include "rdb_sql_utils.h" +#include "rdb_store_manager.h" #include "sqlite_utils.h" #include "string_utils.h" #include "rdb_fault_hiview_reporter.h" +#include "relational_store_crypt.h" namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; -using Reportor = RdbFaultHiViewReporter; +using Reporter = RdbFaultHiViewReporter; +using CheckRootKeyExistsFunc = int32_t (*)(std::vector &); +using GenerateRootKeyFunc = int32_t (*)(const std::vector &, RDBCryptoFault &); +using EncryptFunc = std::vector (*)(const RDBCryptoParam &, RDBCryptoFault &); +using DecryptFunc = std::vector (*)(const RDBCryptoParam &, RDBCryptoFault &); +using GenerateRandomNumFunc = std::vector (*)(uint32_t); RdbPassword::RdbPassword() = default; @@ -129,311 +136,114 @@ std::string RdbSecurityManager::GetBundleNameByAlias(const std::vector return ""; } -int32_t RdbSecurityManager::HksLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, - const struct HksBlob *inData, struct HksBlob *outData) +RdbSecurityManager::RdbSecurityManager() { - if (outData->size < inData->size * TIMES) { - HksAbort(handle, paramSet); - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_FAIL, GetBundleNameByAlias(), - "HksLoopUpdate out size not enough")); - return HKS_ERROR_INVALID_ARGUMENT; - } + handle_ = nullptr; +}; - struct HksBlob input = { MAX_UPDATE_SIZE, inData->data }; - uint8_t *end = inData->data + inData->size - 1; - outData->size = 0; - struct HksBlob output = { MAX_OUTDATA_SIZE, outData->data }; - while (input.data <= end) { - if (input.data + MAX_UPDATE_SIZE > end) { - input.size = end - input.data + 1; - break; - } - auto result = HksUpdate(handle, paramSet, &input, &output); - if (result != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_FAIL, GetBundleNameByAlias(), - "HksUpdate ret=" + std::to_string(result))); - LOG_ERROR("HksUpdate Failed."); - return HKS_FAILURE; - } - - output.data += output.size; - outData->size += output.size; - input.data += MAX_UPDATE_SIZE; - } - output.size = input.size * TIMES; - auto result = HksFinish(handle, paramSet, &input, &output); - if (result != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_FAIL, GetBundleNameByAlias(), - "HksFinish ret=" + std::to_string(result))); - LOG_ERROR("HksFinish Failed."); - return HKS_FAILURE; - } - outData->size += output.size; - return HKS_SUCCESS; -} - -int32_t RdbSecurityManager::HksEncryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, - const struct HksBlob *plainText, struct HksBlob *cipherText) +RdbSecurityManager::~RdbSecurityManager() { - uint8_t handle[sizeof(uint64_t)] = { 0 }; - struct HksBlob handleBlob = { sizeof(uint64_t), handle }; - int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr); - if (result != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_ENCRYPT_FAIL, - GetBundleNameByAlias(), "Encrypt HksInit ret=" + std::to_string(result))); - LOG_ERROR("HksEncrypt failed with error %{public}d", result); - return result; + if (handle_ != nullptr) { + dlclose(handle_); + handle_ = nullptr; } - return HksLoopUpdate(&handleBlob, paramSet, plainText, cipherText); } -int32_t RdbSecurityManager::HksDecryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, - const struct HksBlob *cipherText, struct HksBlob *plainText) -{ - uint8_t handle[sizeof(uint64_t)] = { 0 }; - struct HksBlob handleBlob = { sizeof(uint64_t), handle }; - int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr); - if (result != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(), - "Decrypt HksInit ret=" + std::to_string(result))); - LOG_ERROR("HksEncrypt failed with error %{public}d", result); - return result; - } - result = HksLoopUpdate(&handleBlob, paramSet, cipherText, plainText); - if (result != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(), - "Decrypt HksLoopUpdate ret=" + std::to_string(result))); - } - return result; -} - -RdbSecurityManager::RdbSecurityManager() - : nonce_(RDB_HKS_BLOB_TYPE_NONCE, RDB_HKS_BLOB_TYPE_NONCE + strlen(RDB_HKS_BLOB_TYPE_NONCE)), - aad_(RDB_HKS_BLOB_TYPE_AAD, RDB_HKS_BLOB_TYPE_AAD + strlen(RDB_HKS_BLOB_TYPE_AAD)) {}; - -RdbSecurityManager::~RdbSecurityManager() = default; - std::vector RdbSecurityManager::GenerateRandomNum(int32_t len) { - std::random_device randomDevice; - std::uniform_int_distribution distribution(0, std::numeric_limits::max()); - std::vector key(len); - for (int32_t i = 0; i < len; i++) { - key[i] = static_cast(distribution(randomDevice)); + auto handle = GetHandle(); + if (handle == nullptr) { + return {}; } - return key; + auto generateRandomNum = reinterpret_cast(dlsym(handle, "generateRandomNum")); + if (generateRandomNum == nullptr) { + LOG_ERROR("dlsym GenerateRandomNum failed(%{public}d)!", errno); + return {}; + } + auto rootKeyAlias = GetRootKeyAlias(); + auto ret = generateRandomNum(len); + return ret; } bool RdbSecurityManager::SaveSecretKeyToFile(const std::string &keyFile, const std::vector &workey) { LOG_INFO("begin keyFile%{public}s.", SqliteUtils::Anonymous(keyFile).c_str()); if (!HasRootKey()) { - Reportor::ReportFault(RdbFaultEvent(FT_OPEN, E_ROOT_KEY_NOT_LOAD, GetBundleNameByAlias(), "not root key")); + Reporter::ReportFault(RdbFaultEvent(FT_OPEN, E_ROOT_KEY_NOT_LOAD, GetBundleNameByAlias(), "not root key")); LOG_ERROR("Root key not exists!"); return false; } + std::vector key = workey.empty() ? GenerateRandomNum(RDB_KEY_SIZE) : workey; + if (key.empty()) { + return false; + } RdbSecretKeyData keyData; keyData.timeValue = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now()); - keyData.distributed = 0; - keyData.secretKey = EncryptWorkKey(key); - - if (keyData.secretKey.empty()) { - Reportor::ReportFault(RdbFaultEvent(FT_OPEN, E_WORK_KEY_FAIL, GetBundleNameByAlias(), "key is empty")); + std::vector keyContent; + keyContent.push_back(char(keyData.distributed)); + keyContent.insert(keyContent.end(), reinterpret_cast(&keyData.timeValue), + reinterpret_cast(&keyData.timeValue) + sizeof(keyData.timeValue)); + keyContent.insert(keyContent.end(), key.begin(), key.end()); + auto [res, secretContent] = EncryptWorkKey(keyContent); + if (!res) { + LOG_ERROR("EncryptWorkKey failed, keyFile%{public}s", SqliteUtils::Anonymous(keyFile).c_str()); + keyContent.assign(keyContent.size(), 0); + key.assign(key.size(), 0); + return false; + } + if (secretContent.encryptValue.empty()) { + Reporter::ReportFault(RdbFaultEvent(FT_OPEN, E_WORK_KEY_FAIL, GetBundleNameByAlias(), "key is empty")); LOG_ERROR("Key size is 0"); + keyContent.assign(keyContent.size(), 0); key.assign(key.size(), 0); return false; } + keyContent.assign(keyContent.size(), 0); key.assign(key.size(), 0); - return SaveSecretKeyToDisk(keyFile, keyData); + auto keyFileOld = ReplaceSuffix(keyFile); + auto ret = SaveSecretKeyToDisk(keyFile, secretContent); + if (!ret) { + LOG_ERROR("Save key to file fail, ret:%{public}d", ret); + return false; + } + return SqliteUtils::DeleteFile(keyFileOld); } -bool RdbSecurityManager::SaveSecretKeyToDisk(const std::string &keyPath, RdbSecretKeyData &keyData) +bool RdbSecurityManager::SaveSecretKeyToDisk(const std::string &keyPath, const RdbSecretContent &secretContent) { LOG_INFO("begin keyPath:%{public}s.", SqliteUtils::Anonymous(keyPath).c_str()); - std::vector distributedInByte = { &keyData.distributed, &keyData.distributed + sizeof(uint8_t) }; - std::vector timeInByte = { reinterpret_cast(&keyData.timeValue), - reinterpret_cast(&keyData.timeValue) + sizeof(time_t) }; - std::vector secretKeyInChar; - secretKeyInChar.insert(secretKeyInChar.end(), distributedInByte.begin(), distributedInByte.end()); - secretKeyInChar.insert(secretKeyInChar.end(), timeInByte.begin(), timeInByte.end()); - secretKeyInChar.insert(secretKeyInChar.end(), keyData.secretKey.begin(), keyData.secretKey.end()); + std::string secretKeyInString; + secretKeyInString.append(reinterpret_cast(&secretContent.magicNum), sizeof(uint32_t)); + secretKeyInString.append( + reinterpret_cast(secretContent.nonceValue.data()), secretContent.nonceValue.size()); + secretKeyInString.append( + reinterpret_cast(secretContent.encryptValue.data()), secretContent.encryptValue.size()); bool ret; { std::lock_guard lock(mutex_); - ret = SaveBufferToFile(keyPath, secretKeyInChar); + auto fd = open(keyPath.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + ret = SaveStringToFd(fd, secretKeyInString); + if (fd >= 0) { + close(fd); + } } if (!ret) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_FAIL, GetBundleNameByAlias(), - "save fail errno=" + std::to_string(errno))); + Reporter::ReportFault(RdbFaultEvent( + FT_EX_FILE, E_WORK_KEY_FAIL, GetBundleNameByAlias(), "save fail errno=" + std::to_string(errno))); } return ret; } -int RdbSecurityManager::GenerateRootKey(const std::vector &rootKeyAlias) -{ - LOG_INFO("RDB GenerateRootKey begin."); - std::vector tempRootKeyAlias = rootKeyAlias; - struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), tempRootKeyAlias.data() }; - struct HksParamSet *params = nullptr; - int32_t ret = HksInitParamSet(¶ms); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_ROOT_KEY_FAULT, GetBundleNameByAlias(rootKeyAlias), - "generator root key, HksInitParamSet ret=" + std::to_string(ret))); - LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret); - return ret; - } - - struct HksParam hksParam[] = { - { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, - { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, - { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, - { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, - { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, - { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, - { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, - }; - - ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_ROOT_KEY_FAULT, GetBundleNameByAlias(rootKeyAlias), - "HksAddParams ret=" + std::to_string(ret))); - LOG_ERROR("HksAddParams-client failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return ret; - } - - ret = HksBuildParamSet(¶ms); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_ROOT_KEY_FAULT, GetBundleNameByAlias(rootKeyAlias), - "HksBuildParamSet ret=" + std::to_string(ret))); - LOG_ERROR("HksBuildParamSet-client failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return ret; - } - - ret = HksGenerateKey(&rootKeyName, params, nullptr); - HksFreeParamSet(¶ms); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_ROOT_KEY_FAULT, GetBundleNameByAlias(rootKeyAlias), - "HksGenerateKey ret=" + std::to_string(ret))); - LOG_ERROR("HksGenerateKey-client failed with error %{public}d", ret); - } - return ret; -} - -std::vector RdbSecurityManager::EncryptWorkKey(std::vector &key) -{ - std::vector rootKeyAlias = GetRootKeyAlias(); - struct HksBlob blobAad = { uint32_t(aad_.size()), aad_.data() }; - struct HksBlob blobNonce = { uint32_t(nonce_.size()), nonce_.data() }; - struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), rootKeyAlias.data() }; - struct HksBlob plainKey = { uint32_t(key.size()), key.data() }; - struct HksParamSet *params = nullptr; - int32_t ret = HksInitParamSet(¶ms); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_ENCRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias), - "Encrypt HksInitParamSet ret=" + std::to_string(ret))); - LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret); - return {}; - } - struct HksParam hksParam[] = {{ .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, - { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT }, - { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, - { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, - { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, - { .tag = HKS_TAG_NONCE, .blob = blobNonce }, - { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, - { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }}; - - ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_ENCRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias), - "Encrypt HksAddParams ret=" + std::to_string(ret))); - LOG_ERROR("HksAddParams failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return {}; - } - - ret = HksBuildParamSet(¶ms); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_ENCRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias), - "Encrypt HksBuildParamSet ret=" + std::to_string(ret))); - LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return {}; - } - std::vector encryptedKey(plainKey.size * TIMES + 1); - struct HksBlob cipherText = { uint32_t(encryptedKey.size()), encryptedKey.data() }; - ret = HksEncryptThreeStage(&rootKeyName, params, &plainKey, &cipherText); - (void)HksFreeParamSet(¶ms); - if (ret != HKS_SUCCESS) { - encryptedKey.assign(encryptedKey.size(), 0); - LOG_ERROR("HksEncrypt failed with error %{public}d", ret); - return {}; - } - encryptedKey.resize(cipherText.size); - return encryptedKey; -} - -bool RdbSecurityManager::DecryptWorkKey(std::vector &source, std::vector &key) +void RdbSecurityManager::ReportCryptFault(int32_t code, const std::string &message) { - std::vector rootKeyAlias = GetRootKeyAlias(); - struct HksBlob blobAad = { uint32_t(aad_.size()), &(aad_[0]) }; - struct HksBlob blobNonce = { uint32_t(nonce_.size()), &(nonce_[0]) }; - struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), &(rootKeyAlias[0]) }; - struct HksBlob encryptedKeyBlob = { uint32_t(source.size() - AEAD_LEN), source.data() }; - struct HksBlob blobAead = { AEAD_LEN, source.data() + source.size() - AEAD_LEN }; - struct HksParamSet *params = nullptr; - int32_t ret = HksInitParamSet(¶ms); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias), - "HksInitParamSet ret=" + std::to_string(ret))); - LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret); - return false; - } - struct HksParam hksParam[] = { - { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, - { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }, - { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, - { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, - { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, - { .tag = HKS_TAG_NONCE, .blob = blobNonce }, - { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, - { .tag = HKS_TAG_AE_TAG, .blob = blobAead }, - { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, - }; - ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias), - "HksAddParams ret=" + std::to_string(ret))); - LOG_ERROR("HksAddParams failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return false; - } - - ret = HksBuildParamSet(¶ms); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias), - "HksBuildParamSet ret=" + std::to_string(ret))); - LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return false; - } - key.resize(encryptedKeyBlob.size * TIMES + 1); - struct HksBlob plainKeyBlob = { uint32_t(key.size()), key.data() }; - ret = HksDecryptThreeStage(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob); - (void)HksFreeParamSet(¶ms); - if (ret != HKS_SUCCESS) { - key.assign(key.size(), 0); - LOG_ERROR("HksDecrypt failed with error %{public}d", ret); - return false; + if (message.empty()) { + return; } - key.resize(plainKeyBlob.size); - return true; + Reporter::ReportFault(RdbFaultEvent(FT_EX_HUKS, code, GetBundleNameByAlias(), message)); } int32_t RdbSecurityManager::Init(const std::string &bundleName) @@ -465,44 +275,85 @@ int32_t RdbSecurityManager::Init(const std::string &bundleName) int32_t RdbSecurityManager::CheckRootKeyExists(std::vector &rootKeyAlias) { - LOG_DEBUG("RDB checkRootKeyExist begin."); - struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), rootKeyAlias.data() }; - struct HksParamSet *params = nullptr; - int32_t ret = HksInitParamSet(¶ms); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret); - return ret; - } - - struct HksParam hksParam[] = { - { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, - { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, - { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, - { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, - { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, - { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, - { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, - }; - - ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksAddParams failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return ret; - } - - ret = HksBuildParamSet(¶ms); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return ret; - } - - ret = HksKeyExist(&rootKeyName, params); - HksFreeParamSet(¶ms); + auto handle = GetHandle(); + if (handle == nullptr) { + return E_NOT_SUPPORT; + } + auto creatorCheck = reinterpret_cast(dlsym(handle, "checkRootKeyExists")); + if (creatorCheck == nullptr) { + LOG_ERROR("CheckRootKeyExists failed(%{public}d)!", errno); + return E_NOT_SUPPORT; + } + return creatorCheck(rootKeyAlias); +} + +int32_t RdbSecurityManager::GenerateRootKey(const std::vector &rootKeyAlias) +{ + auto handle = GetHandle(); + if (handle == nullptr) { + return E_NOT_SUPPORT; + } + RDBCryptoFault rdbFault; + auto generateRootKey = reinterpret_cast(dlsym(handle, "generateRootKey")); + if (generateRootKey == nullptr) { + LOG_ERROR("dlsym GenerateRootKey failed(%{public}d)!", errno); + return E_NOT_SUPPORT; + } + auto ret = generateRootKey(rootKeyAlias, rdbFault); + ReportCryptFault(rdbFault.code, rdbFault.message); return ret; } +std::pair RdbSecurityManager::EncryptWorkKey(const std::vector &key) +{ + RdbSecretContent rdbSecretContent; + auto handle = GetHandle(); + if (handle == nullptr) { + return { false, rdbSecretContent }; + } + RDBCryptoFault rdbFault; + auto encrypt = reinterpret_cast(dlsym(handle, "encrypt")); + if (encrypt == nullptr) { + LOG_ERROR("dlsym Encrypt failed(%{public}d)!", errno); + return { false, rdbSecretContent }; + } + auto rootKeyAlias = GetRootKeyAlias(); + RDBCryptoParam param; + param.KeyValue = key; + param.rootAlias = rootKeyAlias; + param.nonceValue = GenerateRandomNum(RdbSecretContent::NONCE_VALUE_SIZE); + if (param.nonceValue.empty()) { + return { false, rdbSecretContent }; + } + auto encryptKey = encrypt(param, rdbFault); + rdbSecretContent.nonceValue = param.nonceValue; + rdbSecretContent.encryptValue = encryptKey; + ReportCryptFault(rdbFault.code, rdbFault.message); + return { true, rdbSecretContent }; +} + +std::vector RdbSecurityManager::DecryptWorkKey( + const std::vector &key, const std::vector &nonce) +{ + auto handle = GetHandle(); + if (handle == nullptr) { + return {}; + } + RDBCryptoFault rdbFault; + auto decrypt = reinterpret_cast(dlsym(handle, "decrypt")); + if (decrypt == nullptr) { + LOG_ERROR("dlsym Decrypt failed(%{public}d)!", errno); + return {}; + } + RDBCryptoParam param; + param.KeyValue = key; + param.nonceValue = nonce; + param.rootAlias = GetRootKeyAlias(); + auto decryptKey = decrypt(param, rdbFault); + ReportCryptFault(rdbFault.code, rdbFault.message); + return decryptKey; +} + bool RdbSecurityManager::InitPath(const std::string &fileDir) { constexpr mode_t DEFAULT_UMASK = 0002; @@ -512,11 +363,11 @@ bool RdbSecurityManager::InitPath(const std::string &fileDir) umask(DEFAULT_UMASK); auto ret = MkDir(fileDir, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); if (ret != 0 && errno != EEXIST) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_FAIL, + Reporter::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_FAIL, RdbSecurityManager::GetInstance().GetBundleNameByAlias(), "mkdir err, ret=" + std::to_string(ret) + ",errno=" + std::to_string(errno) + ",fileDir=" + SqliteUtils::Anonymous(fileDir))); - LOG_ERROR("mkdir error:%{public}d, dbDir:%{public}s", errno, SqliteUtils::Anonymous(fileDir).c_str()); + LOG_ERROR("mkdir error:%{public}d, area:%{public}s", errno, SqliteUtils::GetArea(fileDir).c_str()); return false; } return true; @@ -524,82 +375,78 @@ bool RdbSecurityManager::InitPath(const std::string &fileDir) RdbPassword RdbSecurityManager::LoadSecretKeyFromFile(const std::string &keyFile) { - auto ret = access(keyFile.c_str(), F_OK); - if (ret != 0) { - auto anonymousFile = SqliteUtils::Anonymous(keyFile); - Reportor::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(), - "access " + anonymousFile + " fail, ret=" + std::to_string(ret) + ",errno=" + std::to_string(errno))); - LOG_ERROR("Not exists. errno:%{public}d, file:%{public}s", errno, anonymousFile.c_str()); - return {}; - } - + auto keyFileOld = ReplaceSuffix(keyFile); + RdbPassword rdbPasswd; RdbSecretKeyData keyData; - if (!LoadSecretKeyFromDisk(keyFile, keyData)) { - Reportor::ReportFault(RdbFaultEvent(FT_OPEN, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(), - "LoadSecretKeyFromDisk fail,errno=" + std::to_string(errno))); - LOG_ERROR("Load key failed."); - return {}; + if (access(keyFile.c_str(), F_OK) == 0) { + if (LoadSecretKeyFromDiskV1(keyFile, keyData) && !keyData.secretKey.empty()) { + rdbPasswd.isKeyExpired = IsKeyExpired(keyData.timeValue); + rdbPasswd.SetValue(keyData.secretKey.data(), keyData.secretKey.size()); + return rdbPasswd; + } } - - std::vector key; - if (!DecryptWorkKey(keyData.secretKey, key)) { - Reportor::ReportFault(RdbFaultEvent(FT_OPEN, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(), - "DecryptWorkKey fail,errno=" + std::to_string(errno))); - LOG_ERROR("Decrypt key failed!"); - return {}; + if (LoadSecretKeyFromDisk(keyFileOld, keyData) && !keyData.secretKey.empty()) { + rdbPasswd.isKeyExpired = IsKeyExpired(keyData.timeValue); + rdbPasswd.SetValue(keyData.secretKey.data(), keyData.secretKey.size()); + return rdbPasswd; } - - RdbPassword rdbPasswd; - rdbPasswd.isKeyExpired = IsKeyExpired(keyData.timeValue); - rdbPasswd.SetValue(key.data(), key.size()); - key.assign(key.size(), 0); - return rdbPasswd; + return {}; } bool RdbSecurityManager::LoadSecretKeyFromDisk(const std::string &keyPath, RdbSecretKeyData &keyData) { - LOG_DEBUG("begin keyPath:%{public}s.", SqliteUtils::Anonymous(keyPath).c_str()); std::vector content; { std::lock_guard lock(mutex_); if (!LoadBufferFromFile(keyPath, content) || content.empty()) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(), + Reporter::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(), "LoadBufferFromFile fail, errno=" + std::to_string(errno))); LOG_ERROR("LoadBufferFromFile failed!"); return false; } } - - auto size = content.size(); - std::size_t offset = 0; - auto iter = content.begin(); - if (offset + 1 >= static_cast(size)) { + auto [res, rdbSecretContent] = UnpackV1(content); + if (!res) { + LOG_ERROR("UnpackV1 failed:%{public}s.", SqliteUtils::Anonymous(keyPath).c_str()); return false; } - keyData.distributed = *iter; - iter++; - offset++; - - std::vector createTime; - if (offset + static_cast(sizeof(time_t) / sizeof(uint8_t)) >= size) { + std::tie(res, keyData) = DecryptV1(rdbSecretContent); + if (!res) { + LOG_ERROR("DecryptV1 failed:%{public}s.", SqliteUtils::Anonymous(keyPath).c_str()); return false; } - offset += sizeof(time_t) / sizeof(uint8_t); - for (std::size_t i = 0; i < sizeof(time_t) / sizeof(uint8_t); i++) { - createTime.push_back(*iter); - iter++; + std::string keyPathV1; + std::string oldSuffix = std::string(SUFFIX_PUB_KEY_OLD); + if (keyPath.length() >= oldSuffix.length() && + keyPath.compare(keyPath.length() - oldSuffix.length(), oldSuffix.length(), oldSuffix) == 0) { + keyPathV1 = keyPath.substr(0, keyPath.length() - oldSuffix.length()) + SUFFIX_PUB_KEY; } + SaveSecretKeyToFile(keyPathV1, keyData.secretKey); + return true; +} - if (createTime.size() == sizeof(time_t)) { - keyData.timeValue = *reinterpret_cast(&createTime[0]); +bool RdbSecurityManager::LoadSecretKeyFromDiskV1(const std::string &keyPath, RdbSecretKeyData &keyData) +{ + std::vector content; + { + std::lock_guard lock(mutex_); + if (!LoadBufferFromFile(keyPath, content) || content.empty()) { + Reporter::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(), + "LoadBufferFromFile fail, errno=" + std::to_string(errno))); + LOG_ERROR("LoadBufferFromFile failed!"); + return false; + } } - - if (offset + AEAD_LEN >= static_cast(size)) { + auto [res, rdbSecretContent] = UnpackV2(content); + if (!res) { + LOG_ERROR("UnpackV2 failed:%{public}s.", SqliteUtils::Anonymous(keyPath).c_str()); + return false; + } + std::tie(res, keyData) = DecryptV2(rdbSecretContent); + if (!res) { + LOG_ERROR("DecryptV2 failed:%{public}s.", SqliteUtils::Anonymous(keyPath).c_str()); return false; } - offset = size; - keyData.secretKey.insert(keyData.secretKey.end(), iter, content.end()); - return true; } @@ -607,8 +454,9 @@ RdbPassword RdbSecurityManager::GetRdbPassword(const std::string &dbPath, KeyFil { KeyFiles keyFiles(dbPath); keyFiles.Lock(); - auto &keyFile = keyFiles.GetKeyFile(keyFileType); - if (IsKeyFileEmpty(keyFile)) { + auto keyFile = keyFiles.GetKeyFile(keyFileType); + auto keyFileOld = ReplaceSuffix(keyFile); + if (IsKeyFileEmpty(keyFile) && IsKeyFileEmpty(keyFileOld)) { keyFiles.InitKeyPath(); if (!SaveSecretKeyToFile(keyFile)) { keyFiles.Unlock(); @@ -616,8 +464,9 @@ RdbPassword RdbSecurityManager::GetRdbPassword(const std::string &dbPath, KeyFil return {}; } } + auto rdbPassword = LoadSecretKeyFromFile(keyFile); keyFiles.Unlock(); - return LoadSecretKeyFromFile(keyFile); + return rdbPassword; } std::vector RdbSecurityManager::GenerateRootKeyAlias(const std::string &bundlename) @@ -641,6 +490,8 @@ void RdbSecurityManager::DelAllKeyFiles(const std::string &dbPath) std::lock_guard lock(mutex_); SqliteUtils::DeleteFile(keyFiles.GetKeyFile(PUB_KEY_FILE)); SqliteUtils::DeleteFile(keyFiles.GetKeyFile(PUB_KEY_FILE_NEW_KEY)); + SqliteUtils::DeleteFile(ReplaceSuffix(keyFiles.GetKeyFile(PUB_KEY_FILE))); + SqliteUtils::DeleteFile(ReplaceSuffix(keyFiles.GetKeyFile(PUB_KEY_FILE_NEW_KEY))); } keyFiles.Unlock(); keyFiles.DestroyLock(); @@ -700,6 +551,18 @@ bool RdbSecurityManager::HasRootKey() return hasRootKey_; } +void* RdbSecurityManager::GetHandle() +{ + std::lock_guard lock(handleMutex_); + if (handle_ == nullptr) { + handle_ = dlopen("librelational_store_crypt.z.so", RTLD_LAZY); + if (handle_ == nullptr) { + LOG_ERROR("crypto dlopen failed errno is %{public}d", errno); + } + } + return handle_; +} + bool RdbSecurityManager::IsKeyFileEmpty(const std::string &keyFile) { struct stat fileInfo; @@ -728,13 +591,116 @@ int32_t RdbSecurityManager::RestoreKeyFile(const std::string &dbPath, const std: return E_OK; } +std::pair RdbSecurityManager::UnpackV1(const std::vector &content) +{ + RdbSecretContent rdbSecretContent; + rdbSecretContent.magicNum = 0; + rdbSecretContent.nonceValue = { RDB_HKS_BLOB_TYPE_NONCE, + RDB_HKS_BLOB_TYPE_NONCE + strlen(RDB_HKS_BLOB_TYPE_NONCE) }; + rdbSecretContent.encryptValue = { content.begin(), content.end() }; + return { true, rdbSecretContent }; +} + +std::pair RdbSecurityManager::UnpackV2(const std::vector &content) +{ + std::pair result; + auto &[res, rdbSecretContent] = result; + rdbSecretContent.magicNum = RdbSecretContent::MAGIC_NUMBER_V2; + res = false; + auto size = content.size(); + std::size_t offset = sizeof(rdbSecretContent.magicNum); + if (offset >= static_cast(size)) { + return result; + } + if (offset + RdbSecretContent::NONCE_VALUE_SIZE >= static_cast(size)) { + return result; + } + rdbSecretContent.nonceValue = { content.begin() + offset, + content.begin() + offset + RdbSecretContent::NONCE_VALUE_SIZE }; + offset += RdbSecretContent::NONCE_VALUE_SIZE; + rdbSecretContent.encryptValue = { content.begin() + offset, content.end() }; + res = true; + return result; +} + +std::pair RdbSecurityManager::DecryptV1(const RdbSecretContent &content) +{ + RdbSecretKeyData keyData; + auto size = content.encryptValue.size(); + std::size_t offset = 0; + auto iter = content.encryptValue.begin(); + if (offset + 1 >= static_cast(size)) { + return { false, keyData }; + } + keyData.distributed = *iter; + iter++; + offset++; + + std::vector createTime; + if (offset + static_cast(sizeof(time_t) / sizeof(uint8_t)) >= size) { + return { false, keyData }; + } + offset += sizeof(time_t) / sizeof(uint8_t); + for (std::size_t i = 0; i < sizeof(time_t) / sizeof(uint8_t); i++) { + createTime.push_back(*iter); + iter++; + } + + if (createTime.size() == sizeof(time_t)) { + keyData.timeValue = *reinterpret_cast(&createTime[0]); + } + + if (offset + AEAD_LEN >= static_cast(size)) { + return { false, keyData }; + } + std::vector key = { iter, content.encryptValue.end() }; + keyData.secretKey = DecryptWorkKey(key, content.nonceValue); + key.assign(key.size(), 0); + return { true, keyData }; +} + +std::pair RdbSecurityManager::DecryptV2(const RdbSecretContent &content) +{ + RdbSecretKeyData keyData; + std::vector value = DecryptWorkKey(content.encryptValue, content.nonceValue); + std::shared_ptr autoClean = + std::shared_ptr("autoClean", [&value](const char *) mutable { value.assign(value.size(), 0); }); + auto size = value.size(); + std::size_t offset = 0; + auto iter = value.begin(); + if (offset + 1 >= static_cast(size)) { + return { false, keyData }; + } + keyData.distributed = *iter; + iter++; + offset++; + + std::vector createTime; + if (offset + static_cast(sizeof(time_t) / sizeof(uint8_t)) >= size) { + return { false, keyData }; + } + offset += sizeof(time_t) / sizeof(uint8_t); + for (std::size_t i = 0; i < sizeof(time_t) / sizeof(uint8_t); i++) { + createTime.push_back(*iter); + iter++; + } + + if (createTime.size() == sizeof(time_t)) { + keyData.timeValue = *reinterpret_cast(&createTime[0]); + } + + if (offset + AEAD_LEN >= static_cast(size)) { + return { false, keyData }; + } + keyData.secretKey = { iter, value.end() }; + return { true, keyData }; +} + RdbSecurityManager::KeyFiles::KeyFiles(const std::string &dbPath, bool openFile) { const std::string dbKeyDir = StringUtils::ExtractFilePath(dbPath) + "key/"; const std::string lockDir = StringUtils::ExtractFilePath(dbPath) + "lock/"; - if (!InitPath(lockDir)) { - LOG_ERROR("lockDir failed, errno:%{public}d, dir:%{public}s.", errno, SqliteUtils::Anonymous(lockDir).c_str()); - } + bool isDirCreate = InitPath(lockDir); const std::string dbName = RemoveSuffix(StringUtils::ExtractFileName(dbPath)); lock_ = lockDir + dbName + SUFFIX_KEY_LOCK; keys_[PUB_KEY_FILE] = dbKeyDir + dbName + SUFFIX_PUB_KEY; @@ -742,8 +708,8 @@ RdbSecurityManager::KeyFiles::KeyFiles(const std::string &dbPath, bool openFile) if (!openFile) { return; } - lockFd_ = open(lock_.c_str(), O_RDONLY | O_CREAT, S_IRWXU | S_IRWXG); - if (lockFd_ < 0) { + lockFd_ = open(lock_.c_str(), O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (lockFd_ < 0 && isDirCreate) { LOG_WARN("open failed, errno:%{public}d, file:%{public}s.", errno, SqliteUtils::Anonymous(lock_).c_str()); } } @@ -774,17 +740,19 @@ int32_t RdbSecurityManager::KeyFiles::InitKeyPath() return E_OK; } -int32_t RdbSecurityManager::KeyFiles::Lock() +int32_t RdbSecurityManager::KeyFiles::Lock(bool isBlock) { if (lockFd_ < 0) { return E_INVALID_FILE_PATH; } int32_t errCode; + int lockType = isBlock ? LOCK_EX : LOCK_EX | LOCK_NB; do { - errCode = flock(lockFd_, LOCK_EX); + errCode = flock(lockFd_, lockType); } while (errCode < 0 && errno == EINTR); if (errCode < 0) { - LOG_WARN("lock failed, errno:%{public}d, dir:%{public}s.", errno, SqliteUtils::Anonymous(lock_).c_str()); + LOG_WARN("lock failed, type:%{public}d, errno:%{public}d, dir:%{public}s.", lockType, errno, + SqliteUtils::Anonymous(lock_).c_str()); return E_ERROR; } return E_OK; @@ -815,5 +783,19 @@ int32_t RdbSecurityManager::KeyFiles::DestroyLock() SqliteUtils::DeleteFile(lock_); return E_OK; } + +std::string RdbSecurityManager::ReplaceSuffix(const std::string &str) +{ + std::string oldSuffix = std::string(SUFFIX_PUB_KEY); + std::string newSuffix = std::string(SUFFIX_PUB_KEY_NEW); + if (str.length() >= oldSuffix.length() && + str.compare(str.length() - oldSuffix.length(), oldSuffix.length(), oldSuffix) == 0) { + return str.substr(0, str.length() - oldSuffix.length()) + SUFFIX_PUB_KEY_OLD; + } else if (str.length() >= newSuffix.length() && + str.compare(str.length() - newSuffix.length(), newSuffix.length(), newSuffix) == 0) { + return str.substr(0, str.length() - newSuffix.length()) + SUFFIX_PUB_TMP_NEW_KEY; + } + return str; +} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp index dacd16bc15a662b52914a70740c88229a1b8eb58..a8a3b9c3f11f8893153ee05ed63e3dc7617d183b 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp @@ -15,6 +15,7 @@ #define LOG_TAG "RdbServiceProxy" #include "rdb_service_proxy.h" +#include #include "itypes_util.h" #include "logger.h" #include "result_set_proxy.h" @@ -24,7 +25,7 @@ namespace OHOS::DistributedRdb { using namespace OHOS::Rdb; using SqliteUtils = OHOS::NativeRdb::SqliteUtils; using RdbServiceCode = OHOS::DistributedRdb::RelationalStore::RdbServiceInterfaceCode; - +constexpr int32_t MAX_RETRY = 100; #define IPC_SEND(code, reply, ...) \ ({ \ int32_t __status = RDB_OK; \ @@ -56,9 +57,18 @@ RdbServiceProxy::RdbServiceProxy(const sptr &object) remote_ = Remote(); } -std::string RdbServiceProxy::ObtainDistributedTableName(const std::string &device, const std::string &table) +std::string RdbServiceProxy::ObtainDistributedTableName( + const RdbSyncerParam ¶m, const std::string &device, const std::string &table) { - return ""; + MessageParcel reply; + int32_t status = + IPC_SEND(static_cast(RdbServiceCode::RDB_SERVICE_CMD_OBTAIN_TABLE), reply, param, device, table); + std::string distributedTableName; + if (status != RDB_OK || !ITypesUtil::Unmarshal(reply, distributedTableName)) { + LOG_ERROR("status:%{public}d, device:%{public}s, table:%{public}s", status, + SqliteUtils::Anonymous(device).c_str(), SqliteUtils::Anonymous(table).c_str()); + } + return distributedTableName; } int32_t RdbServiceProxy::InitNotifier(const RdbSyncerParam ¶m) @@ -209,7 +219,7 @@ std::string RdbServiceProxy::RemoveSuffix(const std::string &name) } int32_t RdbServiceProxy::Subscribe( - const RdbSyncerParam ¶m, const SubscribeOption &option, RdbStoreObserver *observer) + const RdbSyncerParam ¶m, const SubscribeOption &option, std::shared_ptr observer) { if (observer == nullptr) { return RDB_ERROR; @@ -224,7 +234,7 @@ int32_t RdbServiceProxy::Subscribe( auto name = RemoveSuffix(param.storeName_); observers_.Compute(name, [observer, ¶m, &option](const auto &key, std::list &value) { for (const auto &element : value) { - if (element.observer == observer) { + if (element.observer.lock() == observer) { LOG_ERROR("duplicate observer, storeName:%{public}s", SqliteUtils::Anonymous(key).c_str()); return true; } @@ -247,7 +257,7 @@ int32_t RdbServiceProxy::DoSubscribe(const RdbSyncerParam ¶m, const Subscrib } int32_t RdbServiceProxy::UnSubscribe( - const RdbSyncerParam ¶m, const SubscribeOption &option, RdbStoreObserver *observer) + const RdbSyncerParam ¶m, const SubscribeOption &option, std::shared_ptr observer) { if (observer == nullptr) { LOG_ERROR("observer is null."); @@ -259,7 +269,7 @@ int32_t RdbServiceProxy::UnSubscribe( auto name = RemoveSuffix(param.storeName_); observers_.ComputeIfPresent(name, [observer](const auto &key, std::list &value) { LOG_INFO("before remove size=%{public}d", static_cast(value.size())); - value.remove_if([observer](const ObserverParam ¶m) { return param.observer == observer; }); + value.remove_if([observer](const ObserverParam ¶m) { return param.observer.lock() == observer; }); LOG_INFO("after remove size=%{public}d", static_cast(value.size())); return !(value.empty()); }); @@ -323,7 +333,7 @@ void RdbServiceProxy::ImportObservers(Observers &observers) for (const auto ¶m : value) { syncerParam.bundleName_ = param.bundleName; syncerParam.storeName_ = key; - Subscribe(syncerParam, param.subscribeOption, param.observer); + Subscribe(syncerParam, param.subscribeOption, param.observer.lock()); } return false; }); @@ -504,12 +514,31 @@ void RdbServiceProxy::OnDataChange( const auto &key, const std::list &value) mutable { auto size = value.size(); for (const auto ¶ms : value) { - params.observer->OnChange(origin, primaries, --size > 0 ? ChangeInfo(info) : std::move(info)); + auto obs = params.observer.lock(); + size--; + if (obs != nullptr) { + obs->OnChange(origin, primaries, size > 0 ? ChangeInfo(info) : std::move(info)); + } } return !value.empty(); }); } +void RdbServiceProxy::OnRemoteDeadSyncComplete() +{ + std::map result; + result.insert(std::pair("", {Progress::SYNC_FINISH, ProgressCode::UNKNOWN_ERROR})); + auto callbacks = std::move(syncCallbacks_); + callbacks.ForEach([&result](const auto &key, const AsyncDetail &callback) { + LOG_INFO("remote dead, compensate progress notification"); + std::map copyResult = result; + if (callback != nullptr) { + callback(std::move(result)); + } + return false; + }); +} + void RdbServiceProxy::OnSyncComplete(uint32_t seqNum, Details &&result) { syncCallbacks_.ComputeIfPresent(seqNum, [&result](const auto &key, const AsyncDetail &callback) { @@ -672,4 +701,16 @@ int32_t RdbServiceProxy::VerifyPromiseInfo(const RdbSyncerParam ¶m) } return status; } + +RdbServiceProxy::~RdbServiceProxy() +{ + int32_t retry = 0; + while (notifier_ != nullptr && notifier_->GetSptrRefCount() > 1 && retry < MAX_RETRY) { + retry++; + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + if (notifier_ != nullptr && notifier_->GetSptrRefCount() > 1) { + LOG_WARN("notifier_ has other in use:%{public}d!", notifier_->GetSptrRefCount()); + } +} } // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_sql_log.cpp b/relational_store/frameworks/native/rdb/src/rdb_sql_log.cpp new file mode 100644 index 0000000000000000000000000000000000000000..05106a55ed64818aa72eb34db8252372aad290b0 --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/rdb_sql_log.cpp @@ -0,0 +1,106 @@ +/* +* Copyright (c) 2025 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 "RdbSqlLog" + +#include "rdb_sql_log.h" + +#include "concurrent_map.h" +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_platform.h" +#include "task_executor.h" + +namespace OHOS::NativeRdb { +ConcurrentMap>> SqlLog::observerSets_; +std::atomic SqlLog::enabled_ = false; +std::shared_mutex SqlLog::mutex_; +std::map SqlLog::suspenders_; +int SqlLog::Subscribe(const std::string storeId, std::shared_ptr observer) +{ + observerSets_.Compute(storeId, [observer](const std::string& key, auto& observers) { + observers.insert(observer); + enabled_ = true; + return true; + }); + return E_OK; +} + +int SqlLog::Unsubscribe(const std::string storeId, std::shared_ptr observer) +{ + observerSets_.ComputeIfPresent(storeId, + [observer](const std::string& key, std::set>& observers) { + observers.erase(observer); + return observer !=nullptr && !observers.empty(); + }); + observerSets_.DoActionIfEmpty([]() { + enabled_ = false; + }); + return E_OK; +} + +void SqlLog::Notify(const std::string &storeId, const ExceptionMessage &exceptionMessage) +{ + if (!enabled_ || IsPause()) { + return; + } + if (!observerSets_.Contains(storeId)) { + return; + } + auto executor = TaskExecutor::GetInstance().GetExecutor(); + if (executor == nullptr) { + return; + } + executor->Execute([exceptionMessage, storeId]() { + auto it = observerSets_.Find(storeId); + if (!it.first) { + return; + } + for (const auto &observer: it.second) { + if (observer) { + observer->OnErrorLog(exceptionMessage); + } + } + }); +} + +void SqlLog::Pause() +{ + std::unique_lock lock(mutex_); + suspenders_[GetThreadId()] = std::max(1, ++suspenders_[GetThreadId()]); +} + +void SqlLog::Resume() +{ + std::unique_lock lock(mutex_); + suspenders_[GetThreadId()] = std::max(0, --suspenders_[GetThreadId()]); +} + +bool SqlLog::IsPause() +{ + std::shared_lock lock(mutex_); + auto it = suspenders_.find(GetThreadId()); + return it != suspenders_.end() && it->second > 0; +} + +SqlLog::SqlLog() +{ +} + +SqlLog::~SqlLog() +{ +} + +} \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_sql_statistic.cpp b/relational_store/frameworks/native/rdb/src/rdb_sql_statistic.cpp index 94dbe863bd201a5e368b72585262a05c06225a4e..e7568fa5489835e1abaa2a6a73252b7c17fb8c90 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_sql_statistic.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_sql_statistic.cpp @@ -50,11 +50,6 @@ int SqlStatistic::Unsubscribe(std::shared_ptr observer) return E_OK; } -uint32_t SqlStatistic::GenerateId() -{ - return ++seqId_; -} - SqlStatistic::SqlStatistic(const std::string &sql, int32_t step, uint32_t seqId) { if (!enabled_) { diff --git a/relational_store/frameworks/native/rdb/src/rdb_sql_utils.cpp b/relational_store/frameworks/native/rdb/src/rdb_sql_utils.cpp index 798b23ce4345f023418ab958d5f069db0f0b534e..dbf2dffb5ec1e989dbe028d301b38fc102b8a7ff 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_sql_utils.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_sql_utils.cpp @@ -54,10 +54,12 @@ int RdbSqlUtils::CreateDirectory(const std::string &databaseDir) databaseDirectory = databaseDirectory + "/" + directory; if (access(databaseDirectory.c_str(), F_OK) != 0) { if (MkDir(databaseDirectory)) { - LOG_ERROR("failed to mkdir errno[%{public}d] %{public}s", errno, - SqliteUtils::Anonymous(databaseDirectory).c_str()); + LOG_ERROR("failed to mkdir errno[%{public}d] %{public}s, parent dir modes: %{public}s", errno, + SqliteUtils::Anonymous(databaseDirectory).c_str(), + SqliteUtils::GetParentModes(databaseDirectory).c_str()); RdbFaultHiViewReporter::ReportFault(RdbFaultEvent(FT_EX_FILE, E_CREATE_FOLDER_FAIL, BUNDLE_NAME_COMMON, - "failed to mkdir errno[ " + std::to_string(errno) + "]," + databaseDirectory)); + "failed to mkdir errno[ " + std::to_string(errno) + "]," + databaseDirectory + + "parent dir modes:" + SqliteUtils::GetParentModes(databaseDirectory))); return E_CREATE_FOLDER_FAIL; } // Set the default ACL attribute to the database root directory to ensure that files created by the server @@ -126,5 +128,128 @@ std::string RdbSqlUtils::BuildQueryString(const AbsRdbPredicates &predicates, co { return SqliteSqlBuilder::BuildQueryString(predicates, columns); } + +std::pair RdbSqlUtils::GetInsertSqlInfo(const std::string &table, const Row &row, Resolution resolution) +{ + SqlInfo sqlInfo; + if (table.empty()) { + return std::make_pair(E_EMPTY_TABLE_NAME, sqlInfo); + } + + if (row.IsEmpty()) { + return std::make_pair(E_EMPTY_VALUES_BUCKET, sqlInfo); + } + + auto conflictClause = SqliteUtils::GetConflictClause(static_cast(resolution)); + if (conflictClause == nullptr) { + return std::make_pair(E_INVALID_CONFLICT_FLAG, sqlInfo); + } + std::string sql; + sql.append("INSERT").append(conflictClause).append(" INTO ").append(table).append("("); + size_t bindArgsSize = row.values_.size(); + std::vector bindArgs; + bindArgs.reserve(bindArgsSize); + const char *split = ""; + for (const auto &[key, val] : row.values_) { + sql.append(split).append(key); + if (val.GetType() == ValueObject::TYPE_ASSETS && resolution == ConflictResolution::ON_CONFLICT_REPLACE) { + return std::make_pair(E_INVALID_ARGS, sqlInfo); + } + SqliteSqlBuilder::UpdateAssetStatus(val, AssetValue::STATUS_INSERT); + bindArgs.push_back(val); // columnValue + split = ","; + } + + sql.append(") VALUES ("); + if (bindArgsSize > 0) { + sql.append(SqliteSqlBuilder::GetSqlArgs(bindArgsSize)); + } + + sql.append(")"); + sqlInfo.sql = std::move(sql); + sqlInfo.args = std::move(bindArgs); + return std::make_pair(E_OK, sqlInfo); +} + +std::pair RdbSqlUtils::GetUpdateSqlInfo(const AbsRdbPredicates &predicates, const Row &row, + Resolution resolution, const std::vector &returningFields) +{ + SqlInfo sqlInfo; + auto table = predicates.GetTableName(); + auto args = predicates.GetBindArgs(); + auto where = predicates.GetWhereClause(); + if (table.empty()) { + return std::make_pair(E_EMPTY_TABLE_NAME, sqlInfo); + } + + if (row.IsEmpty()) { + return std::make_pair(E_EMPTY_VALUES_BUCKET, sqlInfo); + } + + auto clause = SqliteUtils::GetConflictClause(static_cast(resolution)); + if (clause == nullptr) { + return std::make_pair(E_INVALID_CONFLICT_FLAG, sqlInfo); + } + std::string sql; + sql.append("UPDATE").append(clause).append(" ").append(table).append(" SET "); + std::vector tmpBindArgs; + size_t tmpBindSize = row.values_.size() + args.size(); + tmpBindArgs.reserve(tmpBindSize); + const char *split = ""; + for (auto &[key, val] : row.values_) { + sql.append(split); + if (val.GetType() == ValueObject::TYPE_ASSETS) { + sql.append(key).append("=merge_assets(").append(key).append(", ?)"); // columnName + } else if (val.GetType() == ValueObject::TYPE_ASSET) { + sql.append(key).append("=merge_asset(").append(key).append(", ?)"); // columnName + } else { + sql.append(key).append("=?"); // columnName + } + tmpBindArgs.push_back(val); // columnValue + split = ","; + } + if (!where.empty()) { + sql.append(" WHERE ").append(where); + } + if (!returningFields.empty()) { + SqliteSqlBuilder::AppendReturning(sql, returningFields); + } + tmpBindArgs.insert(tmpBindArgs.end(), args.begin(), args.end()); + + sqlInfo.sql = std::move(sql); + sqlInfo.args = std::move(tmpBindArgs); + return std::make_pair(E_OK, sqlInfo); +} + +std::pair RdbSqlUtils::GetDeleteSqlInfo( + const AbsRdbPredicates &predicates, const std::vector &returningFields) +{ + SqlInfo sqlInfo; + auto table = predicates.GetTableName(); + auto where = predicates.GetWhereClause(); + if (table.empty()) { + return std::make_pair(E_EMPTY_TABLE_NAME, sqlInfo); + } + std::string sql; + sql.append("DELETE FROM ").append(table); + if (!where.empty()) { + sql.append(" WHERE ").append(where); + } + if (!returningFields.empty()) { + SqliteSqlBuilder::AppendReturning(sql, returningFields); + } + sqlInfo.sql = std::move(sql); + sqlInfo.args = predicates.GetBindArgs(); + return std::make_pair(E_OK, sqlInfo); +} + +std::pair RdbSqlUtils::GetQuerySqlInfo(const AbsRdbPredicates &predicates, const Fields &columns) +{ + SqlInfo sqlInfo; + std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); + sqlInfo.sql = std::move(sql); + sqlInfo.args = predicates.GetBindArgs(); + return std::make_pair(E_OK, sqlInfo); +} } // namespace NativeRdb } // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_store.cpp b/relational_store/frameworks/native/rdb/src/rdb_store.cpp index f97c56c44e0f27729a236f844e640af3cc317d74..f22e9786807b9918cb2bc2feb5d1b5501465bc59 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store.cpp @@ -14,10 +14,12 @@ */ #include "rdb_store.h" +#include "logger.h" #include "sqlite_sql_builder.h" #include "sqlite_utils.h" #include "traits.h" namespace OHOS::NativeRdb { +using namespace OHOS::Rdb; RdbStore::ModifyTime::ModifyTime( std::shared_ptr result, std::map, PRIKey> hashKeys, bool isFromRowId) : result_(std::move(result)), hash_(std::move(hashKeys)), isFromRowId_(isFromRowId) @@ -138,6 +140,12 @@ int RdbStore::Replace(int64_t &outRowId, const std::string &table, const Row &ro return errCode; } +// Old version implementation, cannot be modified +std::pair RdbStore::BatchInsert(const std::string &table, const RefRows &rows) +{ + return { E_NOT_SUPPORT, -1 }; +} + int RdbStore::BatchInsert(int64_t &outInsertNum, const std::string &table, const Rows &rows) { ValuesBuckets refRows; @@ -151,13 +159,14 @@ int RdbStore::BatchInsert(int64_t &outInsertNum, const std::string &table, const return errCode; } -std::pair RdbStore::BatchInsert(const std::string &table, const RefRows &rows) +std::pair RdbStore::BatchInsert(const std::string &table, const RefRows &rows, Resolution resolution) { - return { E_NOT_SUPPORT, -1 }; + auto [code, result] = BatchInsert(table, rows, {}, resolution); + return { code, result.changed }; } -std::pair RdbStore::BatchInsertWithConflictResolution( - const std::string &table, const RdbStore::RefRows &rows, RdbStore::Resolution resolution) +std::pair RdbStore::BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution) { return { E_NOT_SUPPORT, -1 }; } @@ -165,12 +174,11 @@ std::pair RdbStore::BatchInsertWithConflictResolution( std::pair RdbStore::Update( const std::string &table, const Row &row, const std::string &where, const Values &args, Resolution resolution) { - (void)table; - (void)row; - (void)where; - (void)args; - (void)resolution; - return { E_NOT_SUPPORT, 0 }; + AbsRdbPredicates predicates(table); + predicates.SetWhereClause(where); + predicates.SetBindArgs(args); + auto [code, result] = Update(row, predicates, {}, resolution); + return { code, result.changed }; } int RdbStore::Update( @@ -194,6 +202,12 @@ int RdbStore::Update( return Update(changedRows, table, row, whereClause, ToValues(args)); }; +std::pair RdbStore::Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) +{ + return { E_NOT_SUPPORT, -1 }; +} + int RdbStore::UpdateWithConflictResolution(int &changedRows, const std::string &table, const Row &row, const std::string &whereClause, const Olds &args, Resolution resolution) { @@ -224,6 +238,23 @@ int RdbStore::Delete(int &deletedRows, const AbsRdbPredicates &predicates) return Delete(deletedRows, predicates.GetTableName(), predicates.GetWhereClause(), predicates.GetBindArgs()); } +int RdbStore::Delete( + int &deletedRows, const std::string &table, const std::string &whereClause, const RdbStore::Values &args) +{ + AbsRdbPredicates predicates(table); + predicates.SetWhereClause(whereClause); + predicates.SetBindArgs(args); + auto [code, result] = Delete(predicates); + deletedRows = result.changed; + return code; +} + +std::pair RdbStore::Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) +{ + return { E_NOT_SUPPORT, -1 }; +} + std::shared_ptr RdbStore::Query(int &errCode, bool distinct, const std::string &table, const Fields &columns, const std::string &whereClause, const Values &args, const std::string &groupBy, const std::string &indexName, const std::string &orderBy, const int &limit, const int &offset) @@ -242,8 +273,7 @@ std::shared_ptr RdbStore::Query(const AbsRdbPredicates &pred std::string sql; std::pair queryStatus = { ColHasSpecificField(columns), predicates.HasSpecificField() }; if (queryStatus.first || queryStatus.second) { - std::string table = predicates.GetTableName(); - std::string logTable = GetLogTableName(table); + std::string logTable = GetLogTableName(predicates.GetTableName()); sql = SqliteSqlBuilder::BuildCursorQueryString(predicates, columns, logTable, queryStatus); } else { sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); @@ -265,7 +295,8 @@ std::shared_ptr RdbStore::QueryByStep(const AbsRdbPredicates &predica bool preCount) { std::string sql; - if (predicates.HasSpecificField()) { + std::pair queryStatus = { ColHasSpecificField(columns), predicates.HasSpecificField() }; + if (queryStatus.first || queryStatus.second) { std::string table = predicates.GetTableName(); std::string logTable = GetLogTableName(table); sql = SqliteSqlBuilder::BuildLockRowQueryString(predicates, columns, logTable); @@ -304,6 +335,11 @@ std::pair RdbStore::Execute(const std::string &sql, const return { E_NOT_SUPPORT, ValueObject() }; } +std::pair RdbStore::ExecuteExt(const std::string &sql, const Values &args) +{ + return { E_NOT_SUPPORT, -1 }; +} + int RdbStore::ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const Values &args) { auto [errCode, value] = Execute(sql, args); @@ -342,6 +378,12 @@ int RdbStore::ExecuteForChangedRowCount(int64_t &outValue, const std::string &sq int RdbStore::Backup(const std::string &databasePath, const std::vector &encryptKey) { + return Backup(databasePath, encryptKey, true); +} + +int RdbStore::Backup(const std::string &databasePath, const std::vector &encryptKey, bool verifyDb) +{ + (void)verifyDb; (void)databasePath; (void)encryptKey; return E_NOT_SUPPORT; @@ -446,6 +488,12 @@ int RdbStore::SetDistributedTables( return E_NOT_SUPPORT; } +int RdbStore::Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) +{ + (void)cryptoParam; + return E_NOT_SUPPORT; +} + std::string RdbStore::ObtainDistributedTableName(const std::string &device, const std::string &table, int &errCode) { errCode = E_NOT_SUPPORT; @@ -476,14 +524,14 @@ int RdbStore::Sync(const SyncOption &option, const AbsRdbPredicates &predicate, return E_NOT_SUPPORT; } -int RdbStore::Subscribe(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStore::Subscribe(const SubscribeOption &option, std::shared_ptr observer) { (void)option; (void)observer; return E_NOT_SUPPORT; } -int RdbStore::UnSubscribe(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStore::UnSubscribe(const SubscribeOption &option, std::shared_ptr observer) { (void)option; (void)observer; @@ -607,4 +655,27 @@ std::string RdbStore::GetLogTableName(const std::string &tableName) { return "naturalbase_rdb_aux_" + tableName + "_log"; } + +int RdbStore::CleanDirtyLog([[gnu::unused]] const std::string &table, [[gnu::unused]] uint64_t cursor) +{ + return E_NOT_SUPPORT; +} + +int RdbStore::ConfigLocale(const std::string &localeStr) +{ + (void)localeStr; + return E_NOT_SUPPORT; +} + +int RdbStore::InitKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema &schema) +{ + return E_NOT_SUPPORT; +} + +int RdbStore::RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) +{ + (void)func; + (void)clstAlgoName; + return E_NOT_SUPPORT; +} } // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp index a8cf560c83f7e73a49136b3178a1f7a39e681869..37188f9df10a77504ee2404aea78d9aead85bf93 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp @@ -16,6 +16,7 @@ #include "rdb_store_config.h" #include +#include #include "logger.h" #include "rdb_errno.h" @@ -27,6 +28,8 @@ namespace OHOS::NativeRdb { using namespace OHOS::Rdb; +// this is modifications to be made in the future. +static std::mutex g_mutex; RdbStoreConfig::RdbStoreConfig(const std::string &name, StorageMode storageMode, bool isReadOnly, const std::vector &encryptKey, const std::string &journalMode, const std::string &syncMode, @@ -360,6 +363,12 @@ std::vector RdbStoreConfig::GetEncryptKey() const return cryptoParam_.encryptKey_; } +void RdbStoreConfig::ResetEncryptKey(const std::vector &encryptKey) const +{ + cryptoParam_.encryptKey_.assign(cryptoParam_.encryptKey_.size(), 0); + cryptoParam_.encryptKey_ = encryptKey; +} + void RdbStoreConfig::ChangeEncryptKey() const { RdbSecurityManager::GetInstance().ChangeKeyFile(GetPath()); @@ -393,6 +402,7 @@ int32_t RdbStoreConfig::GenerateEncryptedKey() const name = std::string(path_).substr(0, path_.rfind("/") + 1); } using KeyFileType = RdbSecurityManager::KeyFileType; + std::lock_guard lock(g_mutex); auto errCode = RdbSecurityManager::GetInstance().Init(name); if (errCode != E_OK) { RdbFaultHiViewReporter::ReportFault(RdbFaultDbFileEvent(FT_OPEN, E_ROOT_KEY_FAULT, *this, @@ -511,9 +521,9 @@ void RdbStoreConfig::SetWriteTime(int timeout) writeTimeout_ = std::max(MIN_TIMEOUT, std::min(MAX_TIMEOUT, timeout)); } -bool RdbStoreConfig::IsLocalOnly() const +bool RdbStoreConfig::IsCustomEncryptParam() const { - return localOnly_; + return customEncryptParam_; } int RdbStoreConfig::GetReadTime() const @@ -566,24 +576,24 @@ IntegrityCheck RdbStoreConfig::GetIntegrityCheck() const return checkType_; } -void RdbStoreConfig::SetPluginLibs(const std::vector &pluginLibs) +int32_t RdbStoreConfig::GetIter() const { - pluginLibs_ = pluginLibs; + return cryptoParam_.iterNum; } -std::vector RdbStoreConfig::GetPluginLibs() const +void RdbStoreConfig::SetIter(int32_t iter) const { - return pluginLibs_; + cryptoParam_.iterNum = iter; } -int32_t RdbStoreConfig::GetIter() const +void RdbStoreConfig::SetPluginLibs(const std::vector &pluginLibs) { - return cryptoParam_.iterNum; + pluginLibs_ = pluginLibs; } -void RdbStoreConfig::SetIter(int32_t iter) const +std::vector RdbStoreConfig::GetPluginLibs() const { - cryptoParam_.iterNum = iter; + return pluginLibs_; } int32_t RdbStoreConfig::GetHaMode() const @@ -606,7 +616,6 @@ void RdbStoreConfig::SetPromiseInfo(PromiseInfo promiseInfo) promiseInfo_ = promiseInfo; } - Tokenizer RdbStoreConfig::GetTokenizer() const { return tokenizer_; @@ -622,6 +631,16 @@ ssize_t RdbStoreConfig::GetWalLimitSize() const return walLimitSize_; } +void RdbStoreConfig::SetEnableSemanticIndex(bool enableSemanticIndex) +{ + enableSemanticIndex_ = enableSemanticIndex; +} + +bool RdbStoreConfig::GetEnableSemanticIndex() const +{ + return enableSemanticIndex_; +} + void RdbStoreConfig::SetWalLimitSize(ssize_t size) { if (size < GlobalExpr::DB_WAL_DEFAULT_SIZE) { @@ -653,12 +672,12 @@ void RdbStoreConfig::SetClearMemorySize(int32_t size) std::string RdbStoreConfig::GetCollatorLocales() const { - return loacles_; + return collatorLocales_.Get(); } -void RdbStoreConfig::SetCollatorLocales(const std::string &loacles) +void RdbStoreConfig::SetCollatorLocales(const std::string &locales) const { - loacles_ = loacles; + collatorLocales_.Set(locales); } ssize_t RdbStoreConfig::GetCheckpointSize() const @@ -690,7 +709,7 @@ void RdbStoreConfig::SetCryptoParam(RdbStoreConfig::CryptoParam cryptoParam) { cryptoParam_ = cryptoParam; if (!(cryptoParam_.encryptKey_.empty())) { - localOnly_ = true; + customEncryptParam_ = true; } } @@ -699,16 +718,6 @@ RdbStoreConfig::CryptoParam RdbStoreConfig::GetCryptoParam() const return cryptoParam_; } -int RdbStoreConfig::GetNcandidates() const -{ - return ncandidates_; -} - -void RdbStoreConfig::SetNcandidates(int ncandidates) -{ - ncandidates_ = ncandidates; -} - RdbStoreConfig::CryptoParam::CryptoParam() = default; RdbStoreConfig::CryptoParam::~CryptoParam() diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp index e6371c60bf908086592fa610110f418a16e9b15d..4dce2c8ccbef00f79c0211654f9e05d14e776459 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp @@ -15,6 +15,8 @@ #define LOG_TAG "RdbStoreImpl" #include "rdb_store_impl.h" +#include +#include #include #include @@ -32,14 +34,18 @@ #include "connection_pool.h" #include "delay_notify.h" #include "directory_ex.h" +#include "knowledge_schema_helper.h" #include "logger.h" #include "rdb_common.h" #include "rdb_errno.h" #include "rdb_fault_hiview_reporter.h" #include "rdb_local_db_observer.h" +#include "rdb_perfStat.h" #include "rdb_radar_reporter.h" #include "rdb_stat_reporter.h" #include "rdb_security_manager.h" +#include "rdb_sql_log.h" +#include "rdb_sql_utils.h" #include "rdb_sql_statistic.h" #include "rdb_store.h" #include "rdb_trace.h" @@ -47,23 +53,24 @@ #include "relational_store_client.h" #include "sqlite_global_config.h" #include "sqlite_sql_builder.h" -#include "sqlite_statement.h" #include "sqlite_utils.h" #include "step_result_set.h" +#include "suspender.h" #include "task_executor.h" #include "traits.h" #include "transaction.h" #include "values_buckets.h" #if !defined(CROSS_PLATFORM) #include "raw_data_parser.h" -#include "rdb_device_manager_adapter.h" #include "rdb_manager_impl.h" #include "relational_store_manager.h" -#include "runtime_config.h" #include "security_policy.h" #include "sqlite_shared_result_set.h" #endif +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) +#include "security_policy.h" +#endif #ifdef WINDOWS_PLATFORM #define ISFILE(filePath) ((filePath.find("\\") == std::string::npos)) #else @@ -75,9 +82,11 @@ namespace OHOS::NativeRdb { using namespace OHOS::Rdb; using namespace std::chrono; using SqlStatistic = DistributedRdb::SqlStatistic; +using PerfStat = DistributedRdb::PerfStat; using RdbNotifyConfig = DistributedRdb::RdbNotifyConfig; using Reportor = RdbFaultHiViewReporter; -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) + +#if !defined(CROSS_PLATFORM) using RdbMgr = DistributedRdb::RdbManagerImpl; #endif @@ -85,6 +94,7 @@ static constexpr const char *BEGIN_TRANSACTION_SQL = "begin;"; static constexpr const char *COMMIT_TRANSACTION_SQL = "commit;"; static constexpr const char *ROLLBACK_TRANSACTION_SQL = "rollback;"; static constexpr const char *BACKUP_RESTORE = "backup.restore"; +static constexpr const char *ASYNC_RESTORE = "-async.restore"; constexpr int64_t TIME_OUT = 1500; void RdbStoreImpl::InitSyncerParam(const RdbStoreConfig &config, bool created) @@ -116,13 +126,16 @@ void RdbStoreImpl::InitSyncerParam(const RdbStoreConfig &config, bool created) int RdbStoreImpl::InnerOpen() { isOpen_ = true; -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) - if (isReadOnly_ || isMemoryRdb_ || config_.IsLocalOnly()) { +#if !defined(CROSS_PLATFORM) + // Only owner mode can store metadata information. + if (isReadOnly_ || isMemoryRdb_ || config_.IsCustomEncryptParam() || (config_.GetRoleType() != OWNER)) { return E_OK; } - + if (config_.GetEnableSemanticIndex()) { + SetKnowledgeSchema(); + } AfterOpen(syncerParam_); - if (config_.GetDBType() == DB_VECTOR || !config_.IsSearchable()) { + if (config_.GetDBType() == DB_VECTOR || (!config_.IsSearchable() && !config_.GetEnableSemanticIndex())) { return E_OK; } int errCode = RegisterDataChangeCallback(); @@ -172,6 +185,12 @@ void RdbStoreImpl::Close() } transactions_ = {}; } + { + std::lock_guard autoLock(helperMutex_); + if (knowledgeSchemaHelper_ != nullptr) { + knowledgeSchemaHelper_->Close(); + } + } } std::shared_ptr RdbStoreImpl::GetPool() const @@ -194,7 +213,7 @@ std::pair> RdbStoreImpl::GetConn(bool isRea return { E_OK, connection }; } -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) +#if !defined(CROSS_PLATFORM) void RdbStoreImpl::AfterOpen(const RdbParam ¶m, int32_t retry) { auto [err, service] = RdbMgr::GetInstance().GetRdbService(param); @@ -202,10 +221,13 @@ void RdbStoreImpl::AfterOpen(const RdbParam ¶m, int32_t retry) return; } if (err != E_OK || service == nullptr) { - LOG_ERROR("GetRdbService failed, err: %{public}d, storeName: %{public}s.", err, - SqliteUtils::Anonymous(param.storeName_).c_str()); + if (err != E_INVALID_ARGS) { + LOG_ERROR("GetRdbService failed, err: %{public}d, storeName: %{public}s.", err, + SqliteUtils::Anonymous(param.storeName_).c_str()); + } auto pool = TaskExecutor::GetInstance().GetExecutor(); - if (err == E_SERVICE_NOT_FOUND && pool != nullptr && retry++ < MAX_RETRY_TIMES) { + if (err == E_SERVICE_NOT_FOUND && pool != nullptr && retry < MAX_RETRY_TIMES) { + retry++; pool->Schedule(std::chrono::seconds(RETRY_INTERVAL), [param, retry]() { AfterOpen(param, retry); }); @@ -399,6 +421,55 @@ int RdbStoreImpl::SetDistributedTables( return HandleCloudSyncAfterSetDistributedTables(tables, distributedConfig); } +int32_t RdbStoreImpl::Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) +{ + if (config_.GetDBType() == DB_VECTOR || isReadOnly_ || isMemoryRdb_) { + return E_NOT_SUPPORT; + } + if (!cryptoParam.IsValid()) { + LOG_ERROR("Invalid crypto param, name:%{public}s", SqliteUtils::Anonymous(config_.GetName()).c_str()); + return E_INVALID_ARGS_NEW; + } + if (!config_.IsEncrypt() || !config_.GetCryptoParam().Equal(cryptoParam) || + (config_.IsCustomEncryptParam() == cryptoParam.encryptKey_.empty())) { + LOG_ERROR("Not supported! name:%{public}s, [%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}u]" + "->[%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}u]", + SqliteUtils::Anonymous(config_.GetName()).c_str(), config_.GetCryptoParam().encryptKey_.empty(), + config_.GetCryptoParam().iterNum, config_.GetCryptoParam().encryptAlgo, config_.GetCryptoParam().hmacAlgo, + config_.GetCryptoParam().kdfAlgo, config_.GetCryptoParam().cryptoPageSize, cryptoParam.encryptKey_.empty(), + cryptoParam.iterNum, cryptoParam.encryptAlgo, cryptoParam.hmacAlgo, + cryptoParam.kdfAlgo, cryptoParam.cryptoPageSize); + return E_NOT_SUPPORT; + } + + auto pool = GetPool(); + if (pool == nullptr) { + LOG_ERROR("Database already closed."); + return E_ALREADY_CLOSED; + } + +#if !defined(CROSS_PLATFORM) + auto [err, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); + if (service != nullptr) { + service->Disable(syncerParam_); + } +#endif + LOG_INFO("Start rekey, name:%{public}s, IsCustomEncrypt:%{public}d. ", + SqliteUtils::Anonymous(config_.GetName()).c_str(), config_.IsCustomEncryptParam()); + auto errCode = pool->Rekey(cryptoParam); +#if !defined(CROSS_PLATFORM) + if (service != nullptr) { + service->Enable(syncerParam_); + if (errCode == E_OK && !config_.IsCustomEncryptParam()) { + auto syncerParam = syncerParam_; + syncerParam.password_ = config_.GetEncryptKey(); + service->AfterOpen(syncerParam); + } + } +#endif + return errCode; +} + int RdbStoreImpl::HandleCloudSyncAfterSetDistributedTables( const std::vector &tables, const DistributedRdb::DistributedConfig &distributedConfig) { @@ -436,21 +507,14 @@ std::string RdbStoreImpl::ObtainDistributedTableName(const std::string &device, if (config_.GetDBType() == DB_VECTOR || isMemoryRdb_) { return ""; } - std::string uuid; - DeviceManagerAdaptor::RdbDeviceManagerAdaptor &deviceManager = - DeviceManagerAdaptor::RdbDeviceManagerAdaptor::GetInstance(syncerParam_.bundleName_); - errCode = deviceManager.GetEncryptedUuidByNetworkId(device, uuid); - if (errCode != E_OK) { - LOG_ERROR("GetUuid is failed."); + auto [err, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); + if (err != E_OK || service == nullptr) { + errCode = err; return ""; } - - auto translateCall = [uuid](const std::string &oriDevId, const DistributedDB::StoreInfo &info) { - return uuid; - }; - DistributedDB::RuntimeConfig::SetTranslateToDeviceIdCallback(translateCall); - - return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table); + auto tableName = service->ObtainDistributedTableName(syncerParam_, device, table); + errCode = tableName.empty() ? E_ERROR : E_OK; + return tableName; } int RdbStoreImpl::Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncBrief &callback) @@ -508,7 +572,7 @@ int RdbStoreImpl::InnerSync( return E_OK; } -Uri RdbStoreImpl::GetUri(const std::string &event) +std::string RdbStoreImpl::GetUri(const std::string &event) { std::string rdbUri; if (config_.GetDataGroupId().empty()) { @@ -516,10 +580,10 @@ Uri RdbStoreImpl::GetUri(const std::string &event) } else { rdbUri = SCHEME_RDB + config_.GetDataGroupId() + "/" + path_ + "/" + event; } - return Uri(rdbUri); + return rdbUri; } -int RdbStoreImpl::SubscribeLocal(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::SubscribeLocal(const SubscribeOption &option, std::shared_ptr observer) { std::lock_guard lock(mutex_); localObservers_.try_emplace(option.event); @@ -535,31 +599,9 @@ int RdbStoreImpl::SubscribeLocal(const SubscribeOption &option, RdbStoreObserver return E_OK; } -int RdbStoreImpl::SubscribeLocalShared(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::SubscribeLocalShared(const SubscribeOption &option, std::shared_ptr observer) { - std::lock_guard lock(mutex_); - localSharedObservers_.try_emplace(option.event); - auto &list = localSharedObservers_.find(option.event)->second; - for (auto it = list.begin(); it != list.end(); it++) { - if ((*it)->getObserver() == observer) { - LOG_ERROR("Duplicate subscribe."); - return E_OK; - } - } - - auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); - if (client == nullptr) { - LOG_ERROR("Failed to get DataObsMgrClient."); - return E_GET_DATAOBSMGRCLIENT_FAIL; - } - sptr localSharedObserver(new (std::nothrow) RdbStoreLocalSharedObserver(observer)); - int32_t err = client->RegisterObserver(GetUri(option.event), localSharedObserver); - if (err != 0) { - LOG_ERROR("Subscribe failed."); - return err; - } - localSharedObservers_[option.event].push_back(std::move(localSharedObserver)); - return E_OK; + return obsManger_.Register(GetUri(option.event), observer); } int32_t RdbStoreImpl::SubscribeLocalDetail( @@ -591,7 +633,7 @@ int32_t RdbStoreImpl::SubscribeLocalDetail( return E_OK; } -int RdbStoreImpl::SubscribeRemote(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::SubscribeRemote(const SubscribeOption &option, std::shared_ptr observer) { auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); if (errCode != E_OK) { @@ -600,7 +642,7 @@ int RdbStoreImpl::SubscribeRemote(const SubscribeOption &option, RdbStoreObserve return service->Subscribe(syncerParam_, option, observer); } -int RdbStoreImpl::Subscribe(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::Subscribe(const SubscribeOption &option, std::shared_ptr observer) { if (config_.GetDBType() == DB_VECTOR) { return E_NOT_SUPPORT; @@ -617,7 +659,7 @@ int RdbStoreImpl::Subscribe(const SubscribeOption &option, RdbStoreObserver *obs return SubscribeRemote(option, observer); } -int RdbStoreImpl::UnSubscribeLocal(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::UnSubscribeLocal(const SubscribeOption &option, std::shared_ptr observer) { std::lock_guard lock(mutex_); auto obs = localObservers_.find(option.event); @@ -643,40 +685,9 @@ int RdbStoreImpl::UnSubscribeLocal(const SubscribeOption &option, RdbStoreObserv return E_OK; } -int RdbStoreImpl::UnSubscribeLocalShared(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::UnSubscribeLocalShared(const SubscribeOption &option, std::shared_ptr observer) { - std::lock_guard lock(mutex_); - auto obs = localSharedObservers_.find(option.event); - if (obs == localSharedObservers_.end()) { - return E_OK; - } - - auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); - if (client == nullptr) { - LOG_ERROR("Failed to get DataObsMgrClient."); - return E_GET_DATAOBSMGRCLIENT_FAIL; - } - - auto &list = obs->second; - for (auto it = list.begin(); it != list.end();) { - if (observer == nullptr || (*it)->getObserver() == observer) { - int32_t err = client->UnregisterObserver(GetUri(option.event), *it); - if (err != 0) { - LOG_ERROR("UnSubscribeLocalShared failed."); - return err; - } - it = list.erase(it); - if (observer != nullptr) { - break; - } - } else { - it++; - } - } - if (list.empty()) { - localSharedObservers_.erase(option.event); - } - return E_OK; + return obsManger_.Unregister(GetUri(option.event), observer); } int32_t RdbStoreImpl::UnsubscribeLocalDetail( @@ -706,7 +717,7 @@ int32_t RdbStoreImpl::UnsubscribeLocalDetail( return E_OK; } -int RdbStoreImpl::UnSubscribeRemote(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::UnSubscribeRemote(const SubscribeOption &option, std::shared_ptr observer) { auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); if (errCode != E_OK) { @@ -715,7 +726,7 @@ int RdbStoreImpl::UnSubscribeRemote(const SubscribeOption &option, RdbStoreObser return service->UnSubscribe(syncerParam_, option, observer); } -int RdbStoreImpl::UnSubscribe(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::UnSubscribe(const SubscribeOption &option, std::shared_ptr observer) { if (config_.GetDBType() == DB_VECTOR) { return E_NOT_SUPPORT; @@ -767,12 +778,7 @@ int RdbStoreImpl::Notify(const std::string &event) if (isMemoryRdb_) { return E_OK; } - auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); - if (client == nullptr) { - LOG_ERROR("Failed to get DataObsMgrClient."); - return E_GET_DATAOBSMGRCLIENT_FAIL; - } - int32_t err = client->NotifyChange(GetUri(event)); + int32_t err = obsManger_.Notify(GetUri(event)); if (err != 0) { LOG_ERROR("Notify failed."); } @@ -826,9 +832,21 @@ void RdbStoreImpl::InitDelayNotifier() LOG_ERROR("Init delay notifier failed."); return; } + std::weak_ptr helper = GetKnowledgeSchemaHelper(); delayNotifier_->SetExecutorPool(TaskExecutor::GetInstance().GetExecutor()); - delayNotifier_->SetTask([param = syncerParam_](const DistributedRdb::RdbChangedData &rdbChangedData, - const RdbNotifyConfig &rdbNotifyConfig) -> int { + delayNotifier_->SetTask([param = syncerParam_, helper = helper]( + const DistributedRdb::RdbChangedData &rdbChangedData, const RdbNotifyConfig &rdbNotifyConfig) -> int { + if (IsKnowledgeDataChange(rdbChangedData)) { + auto realHelper = helper.lock(); + if (realHelper == nullptr) { + LOG_WARN("knowledge helper is nullptr"); + return E_OK; + } + realHelper->DonateKnowledgeData(); + } + if (!IsNotifyService(rdbChangedData)) { + return E_OK; + } auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(param); if (errCode == E_NOT_SUPPORT) { return errCode; @@ -865,7 +883,8 @@ void RdbStoreImpl::RegisterDataChangeCallback( if (conn == nullptr) { relConnPool->Dump(true, "DATACHANGE"); auto pool = TaskExecutor::GetInstance().GetExecutor(); - if (pool != nullptr && retry++ < MAX_RETRY_TIMES) { + if (pool != nullptr && retry < MAX_RETRY_TIMES) { + retry++; pool->Schedule(std::chrono::seconds(1), [delayNotifier, connPool, retry]() { RegisterDataChangeCallback(delayNotifier, connPool, retry); }); } @@ -895,13 +914,12 @@ int RdbStoreImpl::GetHashKeyForLockRow(const AbsRdbPredicates &predicates, std:: sql.append(table).append(".ROWID = ").append(logTable).append(".data_key"); auto whereClause = predicates.GetWhereClause(); if (!whereClause.empty()) { - SqliteUtils::Replace(whereClause, SqliteUtils::REP, logTable + "."); - sql.append(" WHERE ").append(whereClause); + sql.append(" WHERE ").append(SqliteUtils::Replace(whereClause, SqliteUtils::REP, logTable + ".")); } auto result = QuerySql(sql, predicates.GetBindArgs()); if (result == nullptr) { - return E_ALREADY_CLOSED ; + return E_ALREADY_CLOSED; } int count = 0; if (result->GetRowCount(count) != E_OK) { @@ -932,6 +950,7 @@ int RdbStoreImpl::ModifyLockStatus(const AbsRdbPredicates &predicates, bool isLo LOG_ERROR("GetHashKeyForLockRow failed, err is %{public}d.", ret); return ret; } + Suspender suspender(Suspender::SQL_LOG); auto [err, statement] = GetStatement(GlobalExpr::PRAGMA_VERSION); if (statement == nullptr || err != E_OK) { return err; @@ -1007,27 +1026,87 @@ RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config) isReadOnly_ = config.IsReadOnly() || config.GetRoleType() == VISITOR; } -RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config, int &errCode) - : isMemoryRdb_(config.IsMemoryRdb()), config_(config), name_(config.GetName()), - fileType_(config.GetDatabaseFileType()) +int32_t RdbStoreImpl::ProcessOpenCallback(int version, RdbOpenCallback &openCallback) { - isReadOnly_ = config.IsReadOnly() || config.GetRoleType() == VISITOR; - SqliteGlobalConfig::GetDbPath(config_, path_); - bool created = access(path_.c_str(), F_OK) != 0; + DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + int32_t errCode = E_OK; + if (version == -1) { + return errCode; + } + + int32_t currentVersion; + errCode = GetVersion(currentVersion); + if (errCode != E_OK) { + return errCode; + } + + if (version == currentVersion) { + return openCallback.OnOpen(*this); + } + + if (currentVersion == 0) { + errCode = openCallback.OnCreate(*this); + } else if (version > currentVersion) { + errCode = openCallback.OnUpgrade(*this, currentVersion, version); + } else { + errCode = openCallback.OnDowngrade(*this, currentVersion, version); + } + + if (errCode == E_OK) { + errCode = SetVersion(version); + } + + if (errCode != E_OK) { + LOG_ERROR("openCallback failed. version: %{public}d -> %{public}d, errCode:%{public}d", + currentVersion, version, errCode); + return errCode; + } + + return openCallback.OnOpen(*this); +} + +bool RdbStoreImpl::TryAsyncRepair() +{ + std::string slavePath = SqliteUtils::GetSlavePath(path_); + if (!IsUseAsyncRestore(path_, slavePath)) { + return false; + } + + int errCode = Connection::CheckReplicaIntegrity(config_); + if (errCode != E_OK) { + return false; + } + + SqliteUtils::DeleteDirtyFiles(path_); + auto pool = ConnectionPool::Create(config_, errCode); + if (errCode != E_OK) { + LOG_WARN("create new connection failed"); + return false; + } + connectionPool_ = pool; + errCode = StartAsyncRestore(pool); + if (errCode != E_OK) { + return false; + } + rebuild_ = RebuiltType::REPAIRED; + + Reportor::ReportRestore(Reportor::Create(config_, E_OK, "RestoreType:Rebuild", false), false); + return true; +} +int32_t RdbStoreImpl::CreatePool(bool &created) +{ + int32_t errCode = E_OK; connectionPool_ = ConnectionPool::Create(config_, errCode); if (connectionPool_ == nullptr && (errCode == E_SQLITE_CORRUPT || errCode == E_INVALID_SECRET_KEY) && !isReadOnly_) { LOG_ERROR("database corrupt, errCode:0x%{public}x, %{public}s, %{public}s", errCode, SqliteUtils::Anonymous(name_).c_str(), SqliteUtils::FormatDebugInfoBrief(Connection::Collect(config_), "master").c_str()); -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) - RdbParam param; - param.bundleName_ = config_.GetBundleName(); - param.storeName_ = config_.GetName(); - param.subUser_ = config_.GetSubUser(); - auto [err, service] = RdbMgr::GetInstance().GetRdbService(param); +#if !defined(CROSS_PLATFORM) + InitSyncerParam(config_, false); + auto [err, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); if (service != nullptr) { - service->Disable(param); + service->Disable(syncerParam_); } #endif config_.SetIter(0); @@ -1036,23 +1115,71 @@ RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config, int &errCode) RdbSecurityManager::GetInstance().RestoreKeyFile(path_, key); key.assign(key.size(), 0); } - std::tie(rebuild_, connectionPool_) = ConnectionPool::HandleDataCorruption(config_, errCode); + + if (TryAsyncRepair()) { + errCode = E_OK; + } else { + std::tie(rebuild_, connectionPool_) = ConnectionPool::HandleDataCorruption(config_, errCode); + } created = true; -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) +#if !defined(CROSS_PLATFORM) if (service != nullptr) { - service->Enable(param); + service->Enable(syncerParam_); } #endif } + return errCode; +} + +int32_t RdbStoreImpl::SetSecurityLabel(const RdbStoreConfig &config) +{ + if (config.IsMemoryRdb()) { + return E_OK; + } +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) + return SecurityPolicy::SetSecurityLabel(config); +#endif + return E_OK; +} + +int32_t RdbStoreImpl::Init(int version, RdbOpenCallback &openCallback) +{ + if (initStatus_ != -1) { + return initStatus_; + } + std::lock_guard lock(initMutex_); + if (initStatus_ != -1) { + return initStatus_; + } + int32_t errCode = E_OK; + bool created = access(path_.c_str(), F_OK) != 0; + errCode = CreatePool(created); if (connectionPool_ == nullptr || errCode != E_OK) { connectionPool_ = nullptr; LOG_ERROR("Create connPool failed, err is %{public}d, path:%{public}s", errCode, SqliteUtils::Anonymous(path_).c_str()); - return; + return errCode; } InitSyncerParam(config_, created); InitReportFunc(syncerParam_); InnerOpen(); + + if (config_.GetRoleType() == OWNER && !config_.IsReadOnly()) { + errCode = SetSecurityLabel(config_); + if (errCode != E_OK) { + return errCode; + } + (void) ExchangeSlaverToMaster(); + SwitchOver(true); + errCode = ProcessOpenCallback(version, openCallback); + SwitchOver(false); + if (errCode != E_OK) { + LOG_ERROR("Callback fail, path:%{public}s code:%{public}d", SqliteUtils::Anonymous(path_).c_str(), errCode); + return errCode; + } + } + initStatus_ = errCode; + return initStatus_; } RdbStoreImpl::~RdbStoreImpl() @@ -1066,6 +1193,10 @@ RdbStoreImpl::~RdbStoreImpl() } } transactions_ = {}; + if (knowledgeSchemaHelper_ != nullptr) { + knowledgeSchemaHelper_->Close(); + } + *slaveStatus_ = SlaveStatus::DB_CLOSING; } const RdbStoreConfig &RdbStoreImpl::GetConfig() @@ -1079,44 +1210,16 @@ std::pair RdbStoreImpl::Insert(const std::string &table, const Row if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { return { E_NOT_SUPPORT, -1 }; } - if (table.empty()) { - return { E_EMPTY_TABLE_NAME, -1 }; - } - - if (row.IsEmpty()) { - return { E_EMPTY_VALUES_BUCKET, -1 }; - } - - auto conflictClause = SqliteUtils::GetConflictClause(static_cast(resolution)); - if (conflictClause == nullptr) { - return { E_INVALID_CONFLICT_FLAG, -1 }; - } RdbStatReporter reportStat(RDB_PERF, INSERT, config_, reportFunc_); SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); - std::string sql; - sql.append("INSERT").append(conflictClause).append(" INTO ").append(table).append("("); - size_t bindArgsSize = row.values_.size(); - std::vector bindArgs; - bindArgs.reserve(bindArgsSize); - const char *split = ""; - for (const auto &[key, val] : row.values_) { - sql.append(split).append(key); - if (val.GetType() == ValueObject::TYPE_ASSETS && resolution == ConflictResolution::ON_CONFLICT_REPLACE) { - return { E_INVALID_ARGS, -1 }; - } - SqliteSqlBuilder::UpdateAssetStatus(val, AssetValue::STATUS_INSERT); - bindArgs.push_back(val); // columnValue - split = ","; - } - - sql.append(") VALUES ("); - if (bindArgsSize > 0) { - sql.append(SqliteSqlBuilder::GetSqlArgs(bindArgsSize)); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL); + auto [status, sqlInfo] = RdbSqlUtils::GetInsertSqlInfo(table, row, resolution); + if (status != E_OK) { + return { status, -1 }; } - sql.append(")"); int64_t rowid = -1; - auto errCode = ExecuteForLastInsertedRowId(rowid, sql, bindArgs); + auto errCode = ExecuteForLastInsertedRowId(rowid, sqlInfo.sql, sqlInfo.args); if (errCode == E_OK) { DoCloudSync(table); } @@ -1126,7 +1229,7 @@ std::pair RdbStoreImpl::Insert(const std::string &table, const Row std::pair RdbStoreImpl::BatchInsert(const std::string &table, const ValuesBuckets &rows) { - if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { + if (isReadOnly_) { return { E_NOT_SUPPORT, -1 }; } @@ -1136,6 +1239,7 @@ std::pair RdbStoreImpl::BatchInsert(const std::string &table, cons RdbStatReporter reportStat(RDB_PERF, BATCHINSERT, config_, reportFunc_); SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL, 0, rows.RowSize()); auto pool = GetPool(); if (pool == nullptr) { return { E_ALREADY_CLOSED, -1 }; @@ -1148,8 +1252,8 @@ std::pair RdbStoreImpl::BatchInsert(const std::string &table, cons auto executeSqlArgs = SqliteSqlBuilder::GenerateSqls(table, rows, conn->GetMaxVariable()); BatchInsertArgsDfx(static_cast(executeSqlArgs.size())); if (executeSqlArgs.empty()) { - LOG_ERROR("empty, table=%{public}s, values:%{public}zu, max number:%{public}d.", table.c_str(), rows.RowSize(), - conn->GetMaxVariable()); + LOG_ERROR("empty, table=%{public}s, values:%{public}zu, max number:%{public}d.", + SqliteUtils::Anonymous(table).c_str(), rows.RowSize(), conn->GetMaxVariable()); return { E_INVALID_ARGS, -1 }; } PauseDelayNotify pauseDelayNotify(delayNotifier_); @@ -1157,7 +1261,7 @@ std::pair RdbStoreImpl::BatchInsert(const std::string &table, cons auto [errCode, statement] = GetStatement(sql, conn); if (statement == nullptr) { LOG_ERROR("statement is nullptr, errCode:0x%{public}x, args:%{public}zu, table:%{public}s, " - "app self can check the SQL", errCode, bindArgs.size(), table.c_str()); + "app self can check the SQL", errCode, bindArgs.size(), SqliteUtils::Anonymous(table).c_str()); return { E_OK, -1 }; } for (const auto &args : bindArgs) { @@ -1168,7 +1272,7 @@ std::pair RdbStoreImpl::BatchInsert(const std::string &table, cons } if (errCode != E_OK) { LOG_ERROR("failed, errCode:%{public}d,args:%{public}zu,table:%{public}s,app self can check the SQL", - errCode, bindArgs.size(), table.c_str()); + errCode, bindArgs.size(), SqliteUtils::Anonymous(table).c_str()); return { E_OK, -1 }; } } @@ -1186,8 +1290,8 @@ void RdbStoreImpl::BatchInsertArgsDfx(int argsSize) } } -std::pair RdbStoreImpl::BatchInsertWithConflictResolution( - const std::string &table, const ValuesBuckets &rows, Resolution resolution) +std::pair RdbStoreImpl::BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution) { if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { return { E_NOT_SUPPORT, -1 }; @@ -1197,7 +1301,9 @@ std::pair RdbStoreImpl::BatchInsertWithConflictResolution( return { E_OK, 0 }; } + RdbStatReporter reportStat(RDB_PERF, BATCHINSERT, config_, reportFunc_); SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL, 0, rows.RowSize()); auto pool = GetPool(); if (pool == nullptr) { return { E_ALREADY_CLOSED, -1 }; @@ -1211,113 +1317,76 @@ std::pair RdbStoreImpl::BatchInsertWithConflictResolution( // To ensure atomicity, execute SQL only once if (sqlArgs.size() != 1 || sqlArgs.front().second.size() != 1) { auto [fields, values] = rows.GetFieldsAndValues(); - LOG_ERROR("invalid args, table=%{public}s, rows:%{public}zu, fields:%{public}zu, max:%{public}d.", - table.c_str(), rows.RowSize(), fields != nullptr ? fields->size() : 0, conn->GetMaxVariable()); + LOG_ERROR("invalid! rows:%{public}zu, table:%{public}s, fields:%{public}zu, max:%{public}d.", rows.RowSize(), + SqliteUtils::Anonymous(table).c_str(), fields != nullptr ? fields->size() : 0, conn->GetMaxVariable()); return { E_INVALID_ARGS, -1 }; } auto &[sql, bindArgs] = sqlArgs.front(); + SqliteSqlBuilder::AppendReturning(sql, returningFields); auto [errCode, statement] = GetStatement(sql, conn); if (statement == nullptr) { LOG_ERROR("statement is nullptr, errCode:0x%{public}x, args:%{public}zu, table:%{public}s, " - "app self can check the SQL", errCode, bindArgs.size(), table.c_str()); + "app self can check the SQL", errCode, bindArgs.size(), SqliteUtils::Anonymous(table).c_str()); return { errCode, -1 }; } PauseDelayNotify pauseDelayNotify(delayNotifier_); - auto args = std::ref(bindArgs.front()); - errCode = statement->Execute(args); + errCode = statement->Execute(std::ref(bindArgs.front())); if (errCode == E_SQLITE_LOCKED || errCode == E_SQLITE_BUSY) { pool->Dump(true, "BATCH"); return { errCode, -1 }; } if (errCode != E_OK) { LOG_ERROR("failed,errCode:%{public}d,table:%{public}s,args:%{public}zu,resolution:%{public}d.", errCode, - table.c_str(), args.get().size(), static_cast(resolution)); - return { errCode, errCode == E_SQLITE_CONSTRAINT ? int64_t(statement->Changes()) : -1 }; + SqliteUtils::Anonymous(table).c_str(), bindArgs.front().size(), static_cast(resolution)); } - conn = nullptr; - DoCloudSync(table); - return { E_OK, int64_t(statement->Changes()) }; + auto result = GenerateResult(errCode, statement); + if (result.changed > 0) { + DoCloudSync(table); + } + return { errCode, result }; } -std::pair RdbStoreImpl::Update( - const std::string &table, const Row &row, const std::string &where, const Values &args, Resolution resolution) +std::pair RdbStoreImpl::Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { return { E_NOT_SUPPORT, -1 }; } - if (table.empty()) { - return { E_EMPTY_TABLE_NAME, -1 }; - } - - if (row.IsEmpty()) { - return { E_EMPTY_VALUES_BUCKET, -1 }; - } - - auto clause = SqliteUtils::GetConflictClause(static_cast(resolution)); - if (clause == nullptr) { - return { E_INVALID_CONFLICT_FLAG, -1 }; - } RdbStatReporter reportStat(RDB_PERF, UPDATE, config_, reportFunc_); SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); - std::string sql; - sql.append("UPDATE").append(clause).append(" ").append(table).append(" SET "); - std::vector tmpBindArgs; - size_t tmpBindSize = row.values_.size() + args.size(); - tmpBindArgs.reserve(tmpBindSize); - const char *split = ""; - for (auto &[key, val] : row.values_) { - sql.append(split); - if (val.GetType() == ValueObject::TYPE_ASSETS) { - sql.append(key).append("=merge_assets(").append(key).append(", ?)"); // columnName - } else if (val.GetType() == ValueObject::TYPE_ASSET) { - sql.append(key).append("=merge_asset(").append(key).append(", ?)"); // columnName - } else { - sql.append(key).append("=?"); // columnName - } - tmpBindArgs.push_back(val); // columnValue - split = ","; + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL); + auto [status, sqlInfo] = RdbSqlUtils::GetUpdateSqlInfo(predicates, row, resolution, returningFields); + if (status != E_OK) { + return { status, -1 }; } - - if (!where.empty()) { - sql.append(" WHERE ").append(where); + auto [code, result] = ExecuteForRow(sqlInfo.sql, sqlInfo.args); + if (result.changed > 0) { + DoCloudSync(predicates.GetTableName()); } - - tmpBindArgs.insert(tmpBindArgs.end(), args.begin(), args.end()); - - int64_t changes = 0; - auto errCode = ExecuteForChangedRowCount(changes, sql, tmpBindArgs); - if (errCode == E_OK) { - DoCloudSync(table); - } - return { errCode, int32_t(changes) }; + return { code, result }; } -int RdbStoreImpl::Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) +std::pair RdbStoreImpl::Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { - return E_NOT_SUPPORT; - } - if (table.empty()) { - return E_EMPTY_TABLE_NAME; + return { E_NOT_SUPPORT, -1 }; } - RdbStatReporter reportStat(RDB_PERF, DELETE, config_, reportFunc_); SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); - std::string sql; - sql.append("DELETE FROM ").append(table); - if (!whereClause.empty()) { - sql.append(" WHERE ").append(whereClause); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL); + auto [status, sqlInfo] = RdbSqlUtils::GetDeleteSqlInfo(predicates, returningFields); + if (status != E_OK) { + return { status, -1 }; } - int64_t changes = 0; - auto errCode = ExecuteForChangedRowCount(changes, sql, args); - if (errCode != E_OK) { - return errCode; + + auto [code, result] = ExecuteForRow(sqlInfo.sql, predicates.GetBindArgs()); + if (result.changed > 0) { + DoCloudSync(predicates.GetTableName()); } - deletedRows = changes; - DoCloudSync(table); - return E_OK; + return { code, result }; } std::shared_ptr RdbStoreImpl::QuerySql(const std::string &sql, const Values &bindArgs) @@ -1327,7 +1396,8 @@ std::shared_ptr RdbStoreImpl::QuerySql(const std::string &sq return nullptr; } SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL); +#if !defined(CROSS_PLATFORM) auto start = std::chrono::steady_clock::now(); auto pool = GetPool(); if (pool == nullptr) { @@ -1345,13 +1415,14 @@ std::shared_ptr RdbStoreImpl::QuerySql(const std::string &sq std::shared_ptr RdbStoreImpl::QueryByStep(const std::string &sql, const Values &args, bool preCount) { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL); auto start = std::chrono::steady_clock::now(); auto pool = GetPool(); if (pool == nullptr) { LOG_ERROR("Database already closed."); return nullptr; } -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) +#if !defined(CROSS_PLATFORM) return std::make_shared(start, connectionPool_->AcquireRef(true), sql, args, preCount); #else return std::make_shared(start, connectionPool_->AcquireRef(true), sql, args, false); @@ -1382,25 +1453,33 @@ void WriteToCompareFile(const std::string &dbPath, const std::string &bundleName } } -void RdbStoreImpl::HandleSchemaDDL(std::shared_ptr statement, - std::shared_ptr pool, const std::string &sql, int32_t &errCode) +int32_t RdbStoreImpl::HandleSchemaDDL(std::shared_ptr &&statement, const std::string &sql) { statement->Reset(); + Suspender suspender(Suspender::SQL_STATISTIC); statement->Prepare("PRAGMA schema_version"); auto [err, version] = statement->ExecuteForValue(); statement = nullptr; if (vSchema_ < static_cast(version)) { - LOG_INFO("db:%{public}s exe DDL schema<%{public}" PRIi64 "->%{public}" PRIi64 - "> app self can check the SQL.", + LOG_INFO("db:%{public}s exe DDL schema<%{public}" PRIi64 "->%{public}" PRIi64 ">", SqliteUtils::Anonymous(name_).c_str(), vSchema_, static_cast(version)); vSchema_ = version; - errCode = pool->RestartConns(); if (!isMemoryRdb_) { std::string dbPath = config_.GetPath(); std::string bundleName = config_.GetBundleName(); WriteToCompareFile(dbPath, bundleName, sql); } + statement = nullptr; + if (config_.GetEnableSemanticIndex() && !isKnowledgeSchemaReady_) { + SetKnowledgeSchema(); + } + auto pool = GetPool(); + if (pool == nullptr) { + return E_ALREADY_CLOSED; + } + return pool->RestartConns(); } + return E_OK; } int RdbStoreImpl::ExecuteSql(const std::string &sql, const Values &args) @@ -1415,25 +1494,20 @@ int RdbStoreImpl::ExecuteSql(const std::string &sql, const Values &args) } RdbStatReporter reportStat(RDB_PERF, EXECUTESQL, config_, reportFunc_); SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL); auto [errCode, statement] = BeginExecuteSql(sql); if (statement == nullptr) { return errCode; } - auto pool = GetPool(); - if (pool == nullptr) { - return E_ALREADY_CLOSED; - } errCode = statement->Execute(args); if (errCode != E_OK) { LOG_ERROR("failed,error:0x%{public}x app self can check the SQL.", errCode); - if (errCode == E_SQLITE_LOCKED || errCode == E_SQLITE_BUSY) { - pool->Dump(true, "EXECUTE"); - } + TryDump(errCode, "EXECUTE"); return errCode; } int sqlType = SqliteUtils::GetSqlStatementType(sql); if (sqlType == SqliteUtils::STATEMENT_DDL) { - HandleSchemaDDL(statement, pool, sql, errCode); + HandleSchemaDDL(std::move(statement), sql); } statement = nullptr; if (errCode == E_OK && (sqlType == SqliteUtils::STATEMENT_UPDATE || sqlType == SqliteUtils::STATEMENT_INSERT)) { @@ -1451,6 +1525,7 @@ std::pair RdbStoreImpl::Execute(const std::string &sql, co RdbStatReporter reportStat(RDB_PERF, EXECUTE, config_, reportFunc_); SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL); int sqlType = SqliteUtils::GetSqlStatementType(sql); if (!SqliteUtils::IsSupportSqlForExecute(sqlType)) { LOG_ERROR("Not support the sqlType: %{public}d, app self can check the SQL", sqlType); @@ -1461,48 +1536,34 @@ std::pair RdbStoreImpl::Execute(const std::string &sql, co return { ExecuteByTrxId(sql, trxId, false, args), ValueObject() }; } - auto pool = GetPool(); - if (pool == nullptr) { - return { E_ALREADY_CLOSED, object }; - } - auto conn = pool->AcquireConnection(false); - if (pool == nullptr) { - return { E_DATABASE_BUSY, object }; - } - - auto [errCode, statement] = GetStatement(sql, conn); - if (errCode != E_OK) { - return { errCode, object }; + auto [errCode, statement] = GetStatement(sql, false); + if (errCode != E_OK || statement == nullptr) { + return { errCode != E_OK ? errCode : E_ERROR, object }; } errCode = statement->Execute(args); - if (errCode != E_OK) { - LOG_ERROR("failed,error:0x%{public}x app self can check the SQL.", errCode); - if (errCode == E_SQLITE_LOCKED || errCode == E_SQLITE_BUSY) { - pool->Dump(true, "EXECUTE"); - } - return { errCode, object }; - } - + TryDump(errCode, "EXECUTE"); if (config_.IsVector()) { return { errCode, object }; } - return HandleDifferentSqlTypes(statement, sql, object, sqlType); + return HandleDifferentSqlTypes(std::move(statement), sql, errCode, sqlType); } std::pair RdbStoreImpl::HandleDifferentSqlTypes( - std::shared_ptr statement, const std::string &sql, const ValueObject &object, int sqlType) + std::shared_ptr &&statement, const std::string &sql, int32_t code, int sqlType) { - int32_t errCode = E_OK; + if (code != E_OK) { + return { code, ValueObject() }; + } if (sqlType == SqliteUtils::STATEMENT_INSERT) { int64_t outValue = statement->Changes() > 0 ? statement->LastInsertRowId() : -1; - return { errCode, ValueObject(outValue) }; + return { code, ValueObject(outValue) }; } if (sqlType == SqliteUtils::STATEMENT_UPDATE) { int outValue = statement->Changes(); - return { errCode, ValueObject(outValue) }; + return { code, ValueObject(outValue) }; } if (sqlType == SqliteUtils::STATEMENT_PRAGMA) { @@ -1512,19 +1573,47 @@ std::pair RdbStoreImpl::HandleDifferentSqlTypes( if (statement->GetColumnCount() > 1) { LOG_ERROR("Not support the sql:app self can check the SQL, column count more than 1"); - return { E_NOT_SUPPORT_THE_SQL, object }; + return { E_NOT_SUPPORT_THE_SQL, ValueObject() }; } } - auto pool = GetPool(); - if (pool == nullptr) { - return { E_ALREADY_CLOSED, object }; + if (sqlType == SqliteUtils::STATEMENT_DDL) { + HandleSchemaDDL(std::move(statement), sql); + } + return { code, ValueObject() }; +} + +std::pair RdbStoreImpl::ExecuteExt(const std::string &sql, const Values &args) +{ + if (isReadOnly_ || config_.IsVector()) { + return { E_NOT_SUPPORT, -1 }; } + RdbStatReporter reportStat(RDB_PERF, EXECUTE, config_, reportFunc_); + SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + int sqlType = SqliteUtils::GetSqlStatementType(sql); + if (!SqliteUtils::IsSupportSqlForExecute(sqlType)) { + LOG_ERROR("Not support the sqlType: %{public}d, app self can check the SQL", sqlType); + return { E_NOT_SUPPORT_THE_SQL, -1 }; + } + auto [errCode, statement] = GetStatement(sql, false); + if (errCode != E_OK) { + return { errCode, -1 }; + } + errCode = statement->Execute(args); + TryDump(errCode, "ExecuteExt"); + return HandleResults(std::move(statement), sql, errCode, sqlType); +} + +std::pair RdbStoreImpl::HandleResults( + std::shared_ptr &&statement, const std::string &sql, int32_t code, int sqlType) +{ + Results result = GenerateResult( + code, statement, sqlType == SqliteUtils::STATEMENT_INSERT || sqlType == SqliteUtils::STATEMENT_UPDATE); if (sqlType == SqliteUtils::STATEMENT_DDL) { - HandleSchemaDDL(statement, pool, sql, errCode); + HandleSchemaDDL(std::move(statement), sql); } - return { errCode, object }; + return { code, result }; } int RdbStoreImpl::ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const Values &args) @@ -1594,32 +1683,35 @@ int RdbStoreImpl::ExecuteForLastInsertedRowId(int64_t &outValue, const std::stri LOG_WARN("total[%{public}" PRId64 "] stmt[%{public}" PRId64 "] exec[%{public}" PRId64 "] result[%{public}" PRId64 "] " "sql[%{public}s]", - totalCostTime, prepareCost, execCost, resultCost, SqliteUtils::Anonymous(sql).c_str()); + totalCostTime, prepareCost, execCost, resultCost, SqliteUtils::SqlAnonymous(sql).c_str()); } return E_OK; } -int RdbStoreImpl::ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, const Values &args) +std::pair RdbStoreImpl::ExecuteForRow(const std::string &sql, const Values &args) { if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { - return E_NOT_SUPPORT; + return { E_NOT_SUPPORT, -1 }; } auto [errCode, statement] = GetStatement(sql, false); if (statement == nullptr) { - return errCode; + return { errCode, -1 }; } errCode = statement->Execute(args); - if (errCode == E_OK) { - outValue = statement->Changes(); - return E_OK; - } if (errCode == E_SQLITE_LOCKED || errCode == E_SQLITE_BUSY) { auto pool = GetPool(); if (pool != nullptr) { pool->Dump(true, "UPG DEL"); } } - return errCode; + return { errCode, GenerateResult(errCode, statement) }; +} + +int RdbStoreImpl::ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, const Values &args) +{ + auto [code, result] = ExecuteForRow(sql, args); + outValue = result.changed; + return code; } int RdbStoreImpl::GetDataBasePath(const std::string &databasePath, std::string &backupFilePath) @@ -1664,16 +1756,17 @@ int RdbStoreImpl::GetSlaveName(const std::string &path, std::string &backupFileP /** * Backup a database from a specified encrypted or unencrypted database file. + * Support skipping verification. */ -int RdbStoreImpl::Backup(const std::string &databasePath, const std::vector &encryptKey) +int RdbStoreImpl::Backup(const std::string &databasePath, const std::vector &encryptKey, bool verifyDb) { - LOG_INFO("Backup db: %{public}s.", SqliteUtils::Anonymous(config_.GetName()).c_str()); + LOG_INFO("Backup db: %{public}s, verify: %{public}d.", SqliteUtils::Anonymous(config_.GetName()).c_str(), verifyDb); if (isReadOnly_ || isMemoryRdb_) { return E_NOT_SUPPORT; } std::string backupFilePath; if (TryGetMasterSlaveBackupPath(databasePath, backupFilePath)) { - return InnerBackup(backupFilePath, encryptKey); + return InnerBackup(backupFilePath, encryptKey, verifyDb); } int ret = GetDataBasePath(databasePath, backupFilePath); @@ -1737,7 +1830,8 @@ std::vector RdbStoreImpl::CreateBackupBindArgs( /** * Backup a database from a specified encrypted or unencrypted database file. */ -int RdbStoreImpl::InnerBackup(const std::string &databasePath, const std::vector &destEncryptKey) +int RdbStoreImpl::InnerBackup( + const std::string &databasePath, const std::vector &destEncryptKey, bool verifyDb) { if (isReadOnly_) { return E_NOT_SUPPORT; @@ -1750,10 +1844,13 @@ int RdbStoreImpl::InnerBackup(const std::string &databasePath, const std::vector if (config_.GetHaMode() != HAMode::SINGLE && SqliteUtils::IsSlaveDbName(databasePath)) { auto [errCode, conn] = GetConn(false); - return errCode != E_OK ? errCode : conn->Backup(databasePath, {}, false, slaveStatus_); + return errCode != E_OK ? errCode : conn->Backup(databasePath, {}, false, slaveStatus_, verifyDb); } - - auto [result, conn] = CreateWritableConn(); + Suspender suspender(Suspender::SQL_LOG); + auto config = config_; + config.SetHaMode(HAMode::SINGLE); + config.SetCreateNecessary(false); + auto [result, conn] = CreateWritableConn(config); if (result != E_OK) { return result; } @@ -1766,7 +1863,7 @@ int RdbStoreImpl::InnerBackup(const std::string &databasePath, const std::vector } std::vector bindArgs = CreateBackupBindArgs(databasePath, destEncryptKey); - auto [errCode, statement] = conn->CreateStatement(GlobalExpr::ATTACH_BACKUP_SQL, conn); + auto [errCode, statement] = GetStatement(GlobalExpr::ATTACH_BACKUP_SQL, conn); errCode = statement->Execute(bindArgs); if (errCode != E_OK) { return errCode; @@ -1800,7 +1897,7 @@ std::pair RdbStoreImpl::BeginExecuteSql(const std:: return { E_DATABASE_BUSY, nullptr }; } - auto [errCode, statement] = conn->CreateStatement(sql, conn); + auto [errCode, statement] = GetStatement(sql, conn); if (statement == nullptr) { return { errCode, nullptr }; } @@ -1855,7 +1952,8 @@ int RdbStoreImpl::SetDefaultEncryptAlgo(const ConnectionPool::SharedConn &conn, std::string sql = std::string(GlobalExpr::CIPHER_DEFAULT_ATTACH_CIPHER_PREFIX) + SqliteUtils::EncryptAlgoDescription(config.GetEncryptAlgo()) + std::string(GlobalExpr::ALGO_SUFFIX); - auto [errCode, statement] = conn->CreateStatement(sql, conn); + Suspender suspender(Suspender::SQL_LOG); + auto [errCode, statement] = GetStatement(sql, conn); errCode = SetDefaultEncryptSql(statement, sql, config); if (errCode != E_OK) { return errCode; @@ -1896,6 +1994,7 @@ int RdbStoreImpl::AttachInner(const RdbStoreConfig &config, const std::string &a if (pool == nullptr) { return E_ALREADY_CLOSED; } + Suspender suspender(Suspender::SQL_LOG); auto [conn, readers] = pool->AcquireAll(waitTime); if (conn == nullptr) { return E_DATABASE_BUSY; @@ -1921,7 +2020,7 @@ int RdbStoreImpl::AttachInner(const RdbStoreConfig &config, const std::string &a return ret; } bindArgs.emplace_back(ValueObject(key)); - auto [errCode, statement] = conn->CreateStatement(GlobalExpr::ATTACH_WITH_KEY_SQL, conn); + auto [errCode, statement] = GetStatement(GlobalExpr::ATTACH_WITH_KEY_SQL, conn); if (statement == nullptr || errCode != E_OK) { LOG_ERROR("Attach get statement failed, code is %{public}d", errCode); return E_ERROR; @@ -1929,7 +2028,7 @@ int RdbStoreImpl::AttachInner(const RdbStoreConfig &config, const std::string &a return statement->Execute(bindArgs); } - auto [errCode, statement] = conn->CreateStatement(GlobalExpr::ATTACH_SQL, conn); + auto [errCode, statement] = GetStatement(GlobalExpr::ATTACH_SQL, conn); if (statement == nullptr || errCode != E_OK) { LOG_ERROR("Attach get statement failed, code is %{public}d", errCode); return errCode; @@ -1975,7 +2074,7 @@ std::pair RdbStoreImpl::Attach( } else if (err != E_OK) { LOG_ERROR("failed, errCode[%{public}d] fileName[%{public}s] attachName[%{public}s] attach fileName" "[%{public}s]", - err, SqliteUtils::Anonymous(config_.GetName()).c_str(), attachName.c_str(), + err, SqliteUtils::Anonymous(config_.GetName()).c_str(), SqliteUtils::Anonymous(attachName).c_str(), SqliteUtils::Anonymous(config.GetName()).c_str()); return { err, 0 }; } @@ -1993,7 +2092,7 @@ std::pair RdbStoreImpl::Detach(const std::string &attachName, if (!attachedInfo_.Contains(attachName)) { return { E_OK, attachedInfo_.Size() }; } - + Suspender suspender(Suspender::SQL_LOG); auto pool = GetPool(); if (pool == nullptr) { return { E_ALREADY_CLOSED, 0 }; @@ -2005,7 +2104,7 @@ std::pair RdbStoreImpl::Detach(const std::string &attachName, std::vector bindArgs; bindArgs.push_back(ValueObject(attachName)); - auto [errCode, statement] = connection->CreateStatement(GlobalExpr::DETACH_SQL, connection); + auto [errCode, statement] = GetStatement(GlobalExpr::DETACH_SQL, connection); if (statement == nullptr || errCode != E_OK) { LOG_ERROR("Detach get statement failed, errCode %{public}d", errCode); return { errCode, 0 }; @@ -2013,7 +2112,7 @@ std::pair RdbStoreImpl::Detach(const std::string &attachName, errCode = statement->Execute(bindArgs); if (errCode != E_OK) { LOG_ERROR("failed, errCode[%{public}d] fileName[%{public}s] attachName[%{public}s] attach", errCode, - SqliteUtils::Anonymous(config_.GetName()).c_str(), attachName.c_str()); + SqliteUtils::Anonymous(config_.GetName()).c_str(), SqliteUtils::Anonymous(attachName).c_str()); return { errCode, 0 }; } @@ -2037,6 +2136,7 @@ std::pair RdbStoreImpl::Detach(const std::string &attachName, */ int RdbStoreImpl::GetVersion(int &version) { + Suspender suspender(Suspender::SQL_LOG); auto [errCode, statement] = GetStatement(GlobalExpr::PRAGMA_VERSION, isReadOnly_); if (statement == nullptr) { return errCode; @@ -2058,6 +2158,7 @@ int RdbStoreImpl::SetVersion(int version) if (isReadOnly_) { return E_NOT_SUPPORT; } + Suspender suspender(Suspender::SQL_LOG); std::string sql = std::string(GlobalExpr::PRAGMA_VERSION) + " = " + std::to_string(version); auto [errCode, statement] = GetStatement(sql); if (statement == nullptr) { @@ -2113,7 +2214,6 @@ std::pair RdbStoreImpl::BeginTrans() if (!config_.IsVector() || isReadOnly_) { return { E_NOT_SUPPORT, 0 }; } - int64_t tmpTrxId = 0; auto pool = GetPool(); if (pool == nullptr) { @@ -2222,7 +2322,6 @@ int RdbStoreImpl::ExecuteByTrxId( if (ret != E_OK) { LOG_ERROR("transaction id: %{public}" PRIu64 ", storeName: %{public}s, errCode: %{public}d" PRIu64, trxId, SqliteUtils::Anonymous(name_).c_str(), ret); - trxConnMap_.Erase(trxId); return ret; } if (closeConnAfterExecute) { @@ -2261,7 +2360,8 @@ int RdbStoreImpl::Commit() std::string sqlStr = transaction.GetCommitStr(); if (sqlStr.size() <= 1) { LOG_WARN("id: %{public}zu, storeName: %{public}s, sql: %{public}s", transactionId, - SqliteUtils::Anonymous(name_).c_str(), sqlStr.c_str()); + SqliteUtils::Anonymous(name_).c_str(), + SqliteUtils::SqlAnonymous(sqlStr).c_str()); pool->GetTransactionStack().pop(); return E_OK; } @@ -2324,7 +2424,7 @@ int RdbStoreImpl::CheckAttach(const std::string &sql) if (sqlType != "ATT") { return E_OK; } - + Suspender suspender(Suspender::SQL_LOG); auto [errCode, statement] = GetStatement(GlobalExpr::PRAGMA_JOUR_MODE_EXP); if (statement == nullptr) { return errCode; @@ -2377,7 +2477,7 @@ std::string RdbStoreImpl::GetName() void RdbStoreImpl::DoCloudSync(const std::string &table) { -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) +#if !defined(CROSS_PLATFORM) auto needSync = cloudInfo_->Change(table); if (!needSync) { return; @@ -2422,6 +2522,7 @@ int RdbStoreImpl::ConfigLocale(const std::string &localeStr) if (pool == nullptr) { return E_ALREADY_CLOSED; } + config_.SetCollatorLocales(localeStr); return pool->ConfigLocale(localeStr); } @@ -2443,6 +2544,128 @@ int RdbStoreImpl::GetDestPath(const std::string &backupPath, std::string &destPa return E_OK; } +void RdbStoreImpl::SwitchOver(bool isUseReplicaDb) +{ + isUseReplicaDb_ = isUseReplicaDb; +} + +bool RdbStoreImpl::IsUseAsyncRestore(const std::string &newPath, const std::string &backupPath) +{ + if (config_.GetPath() == backupPath || newPath == backupPath || + config_.GetDBType() == DB_VECTOR || config_.GetHaMode() == HAMode::SINGLE || + !SqliteUtils::IsSlaveDbName(backupPath) || !SqliteUtils::IsSlaveLarge(config_.GetPath())) { + return false; + } + return true; +} + +int32_t RdbStoreImpl::RestoreWithPool(std::shared_ptr pool, const std::string &path) +{ + if (pool == nullptr) { + return E_OK; + } + auto connection = pool->AcquireConnection(false); + if (connection == nullptr) { + return E_DATABASE_BUSY; + } + pool->ReopenConns(); + auto curStatus = std::make_shared(SlaveStatus::UNDEFINED); + return connection->Restore(path, {}, curStatus); +} + +int RdbStoreImpl::StartAsyncRestore(std::shared_ptr pool) const +{ + auto keyFilesPtr = std::make_shared(path_ + ASYNC_RESTORE); + SqliteUtils::SetSlaveRestoring(path_); + auto err = keyFilesPtr->Lock(false); + if (err == E_OK) { + auto taskPool = TaskExecutor::GetInstance().GetExecutor(); + if (taskPool == nullptr) { + LOG_ERROR("Get thread pool failed"); + keyFilesPtr->Unlock(); + return E_ERROR; + } + taskPool->Execute([keyFilesPtr, config = config_, pool] { + auto dbPath = config.GetPath(); + LOG_INFO("async restore started for %{public}s", SqliteUtils::Anonymous(dbPath).c_str()); + auto result = RdbStoreImpl::RestoreWithPool(pool, dbPath); + if (result != E_OK) { + LOG_WARN("async restore failed, retry once, %{public}d", result); + result = RdbStoreImpl::RestoreWithPool(pool, dbPath); + } + if (result != E_OK) { + LOG_WARN("async restore failed, %{public}d", result); + SqliteUtils::SetSlaveInvalid(dbPath); + } + SqliteUtils::SetSlaveRestoring(dbPath, false); + if (pool != nullptr) { + pool->ReopenConns(); + } + keyFilesPtr->Unlock(); + }); + + return E_OK; + } + LOG_WARN("Get process lock failed. Async restore is started in another process, %{public}s", + SqliteUtils::Anonymous(path_).c_str()); + return E_OK; +} + +int RdbStoreImpl::StartAsyncBackupIfNeed(std::shared_ptr slaveStatus) +{ + auto taskPool = TaskExecutor::GetInstance().GetExecutor(); + if (taskPool == nullptr) { + LOG_ERROR("Get thread pool failed"); + return E_ERROR; + } + auto config = config_; + config.SetCreateNecessary(false); + taskPool->Execute([config, slaveStatus] { + if (*slaveStatus == SlaveStatus::DB_CLOSING) { + return; + } + auto [result, conn] = CreateWritableConn(config); + if (result != E_OK || conn == nullptr) { + return; + } + auto strategy = conn->GenerateExchangeStrategy(slaveStatus); + if (*slaveStatus == SlaveStatus::DB_CLOSING) { + return; + } + LOG_INFO("async exchange st:%{public}d,", strategy); + if (strategy == ExchangeStrategy::BACKUP) { + (void)conn->Backup({}, {}, false, slaveStatus); + } + }); + return E_OK; +} + +int RdbStoreImpl::RestoreInner(const std::string &destPath, const std::vector &newKey, + std::shared_ptr pool) +{ + bool isUseAsync = IsUseAsyncRestore(path_, destPath); + LOG_INFO("restore start, using async=%{public}d", isUseAsync); + if (!isUseAsync) { + auto err = pool->ChangeDbFileForRestore(path_, destPath, newKey, slaveStatus_); + LOG_INFO("restore finished, sync mode rc=%{public}d", err); + return err; + } + + auto connection = pool->AcquireConnection(false); + if (connection == nullptr) { + LOG_WARN("Failed to obtain writer for async restore"); + return E_DATABASE_BUSY; + } + + int errCode = connection->CheckReplicaForRestore(); + if (errCode != E_OK) { + return errCode; + } + errCode = StartAsyncRestore(pool); + LOG_INFO("restore finished, async mode rc=%{public}d", errCode); + return errCode; +} + int RdbStoreImpl::Restore(const std::string &backupPath, const std::vector &newKey) { LOG_INFO("Restore db: %{public}s.", SqliteUtils::Anonymous(config_.GetName()).c_str()); @@ -2467,16 +2690,16 @@ int RdbStoreImpl::Restore(const std::string &backupPath, const std::vectorDisable(syncerParam_); } #endif bool corrupt = Reportor::IsReportCorruptedFault(path_); - int errCode = pool->ChangeDbFileForRestore(path_, destPath, newKey, slaveStatus_); + int errCode = RestoreInner(destPath, newKey, pool); keyFiles.Unlock(); -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) +#if !defined(CROSS_PLATFORM) SecurityPolicy::SetSecurityLabel(config_); if (service != nullptr) { service->Enable(syncerParam_); @@ -2497,11 +2720,8 @@ int RdbStoreImpl::Restore(const std::string &backupPath, const std::vector> RdbStoreImpl::CreateWritableConn() +std::pair> RdbStoreImpl::CreateWritableConn(const RdbStoreConfig &config) { - auto config = config_; - config.SetHaMode(HAMode::SINGLE); - config.SetCreateNecessary(false); auto [result, conn] = Connection::Create(config, true); if (result != E_OK || conn == nullptr) { LOG_ERROR("create connection failed, err:%{public}d", result); @@ -2516,6 +2736,32 @@ std::pair> RdbStoreImpl::GetStatement( if (conn == nullptr) { return { E_DATABASE_BUSY, nullptr }; } + + if (config_.GetHaMode() != HAMode::SINGLE && SqliteUtils::IsSlaveRestoring(config_.GetPath())) { + auto keyFiles = RdbSecurityManager::KeyFiles(config_.GetPath() + ASYNC_RESTORE); + int32_t ret = keyFiles.Lock(false); + if (ret != E_OK) { + if (isUseReplicaDb_) { + LOG_INFO("Use replica statement, %{public}s", SqliteUtils::Anonymous(config_.GetPath()).c_str()); + return conn->CreateReplicaStatement(sql, conn); + } + return { E_DATABASE_BUSY, nullptr }; + } + SqliteUtils::SetSlaveRestoring(config_.GetPath(), false); + (void)keyFiles.Unlock(); + auto strategy = conn->GenerateExchangeStrategy(slaveStatus_); + LOG_WARN("Got lock file but process is not in restore, mark removed, st:%{public}d, %{public}s", + strategy, SqliteUtils::Anonymous(config_.GetPath()).c_str()); + if (strategy != ExchangeStrategy::RESTORE) { + return conn->CreateStatement(sql, conn); + } + auto result = conn->CheckReplicaForRestore(); + if (result == E_OK) { + result = StartAsyncRestore(GetPool()); + return conn->CreateReplicaStatement(sql, conn); + } + } + return conn->CreateStatement(sql, conn); } @@ -2529,7 +2775,7 @@ std::pair> RdbStoreImpl::GetStatement(const if (conn == nullptr) { return { E_DATABASE_BUSY, nullptr }; } - return conn->CreateStatement(sql, conn); + return GetStatement(sql, conn); } int RdbStoreImpl::GetRebuilt(RebuiltType &rebuilt) @@ -2543,8 +2789,8 @@ int RdbStoreImpl::InterruptBackup() if (config_.GetHaMode() != HAMode::MANUAL_TRIGGER) { return E_NOT_SUPPORT; } - if (slaveStatus_ == SlaveStatus::BACKING_UP) { - slaveStatus_ = SlaveStatus::BACKUP_INTERRUPT; + if (*slaveStatus_ == SlaveStatus::BACKING_UP) { + *slaveStatus_ = SlaveStatus::BACKUP_INTERRUPT; return E_OK; } return E_CANCEL; @@ -2555,7 +2801,7 @@ int32_t RdbStoreImpl::GetBackupStatus() const if (config_.GetHaMode() != HAMode::MANUAL_TRIGGER && config_.GetHaMode() != HAMode::MAIN_REPLICA) { return SlaveStatus::UNDEFINED; } - return slaveStatus_; + return *slaveStatus_; } bool RdbStoreImpl::TryGetMasterSlaveBackupPath(const std::string &srcPath, std::string &destPath, bool isRestore) @@ -2590,18 +2836,20 @@ int32_t RdbStoreImpl::ExchangeSlaverToMaster() if (errCode != E_OK) { return errCode; } - auto strategy = conn->GenerateExchangeStrategy(slaveStatus_); + auto strategy = conn->GenerateExchangeStrategy(slaveStatus_, false); if (strategy != ExchangeStrategy::NOT_HANDLE) { LOG_WARN("exchange st:%{public}d, %{public}s,", strategy, SqliteUtils::Anonymous(config_.GetName()).c_str()); } int ret = E_OK; - if (strategy == ExchangeStrategy::RESTORE) { + if (strategy == ExchangeStrategy::RESTORE && !SqliteUtils::IsSlaveRestoring(config_.GetPath())) { conn = nullptr; // disable is required before restore ret = Restore({}, {}); } else if (strategy == ExchangeStrategy::BACKUP) { // async backup ret = conn->Backup({}, {}, true, slaveStatus_); + } else if (strategy == ExchangeStrategy::PENDING_BACKUP) { + ret = StartAsyncBackupIfNeed(slaveStatus_); } return ret; } @@ -2616,17 +2864,17 @@ std::pair> RdbStoreImpl::CreateTransaction if (isReadOnly_) { return { E_NOT_SUPPORT, nullptr }; } - auto pool = GetPool(); if (pool == nullptr) { return { E_ALREADY_CLOSED, nullptr }; } + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL); auto [errCode, conn] = pool->CreateTransConn(); if (conn == nullptr) { return { errCode, nullptr }; } std::shared_ptr trans; - std::tie(errCode, trans) = Transaction::Create(type, conn, config_.GetName()); + std::tie(errCode, trans) = Transaction::Create(type, conn, config_.GetPath()); if (trans == nullptr) { if (errCode == E_SQLITE_LOCKED || errCode == E_SQLITE_BUSY) { pool->Dump(true, "TRANS"); @@ -2646,6 +2894,68 @@ std::pair> RdbStoreImpl::CreateTransaction return { errCode, trans }; } +int RdbStoreImpl::CleanDirtyLog(const std::string &table, uint64_t cursor) +{ + if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR) || isMemoryRdb_) { + LOG_ERROR("Not support. table:%{public}s, isRead:%{public}d, dbType:%{public}d, isMemoryRdb:%{public}d.", + SqliteUtils::Anonymous(table).c_str(), isReadOnly_, config_.GetDBType(), isMemoryRdb_); + return E_NOT_SUPPORT; + } + auto [errCode, conn] = GetConn(false); + if (errCode != E_OK || conn == nullptr) { + LOG_ERROR("The database is busy or closed errCode:%{public}d", errCode); + return errCode; + } + return conn->CleanDirtyLog(table, cursor); +} + +std::shared_ptr RdbStoreImpl::GetValues(std::shared_ptr statement) +{ + if (statement == nullptr) { + return nullptr; + } + auto [code, rows] = statement->GetRows(MAX_RETURNING_ROWS); + auto size = rows.size(); + std::shared_ptr result = std::make_shared(std::move(rows)); + // The correct number of changed rows can only be obtained after completing the step + while (code == E_OK && size == MAX_RETURNING_ROWS) { + std::tie(code, rows) = statement->GetRows(MAX_RETURNING_ROWS); + size = rows.size(); + } + return result; +} + +Results RdbStoreImpl::GenerateResult(int32_t code, std::shared_ptr statement, bool isDML) +{ + Results result{ -1 }; + if (statement == nullptr) { + return result; + } + // There are no data changes in other scenarios + if (code == E_OK) { + result.results = GetValues(statement); + result.changed = isDML ? statement->Changes() : 0; + } + if (code == E_SQLITE_CONSTRAINT) { + result.changed = statement->Changes(); + } + if (isDML && result.changed <= 0) { + result.results = std::make_shared(); + } + return result; +} + +void RdbStoreImpl::TryDump(int32_t code, const char *dumpHeader) +{ + if (code != E_SQLITE_LOCKED && code != E_SQLITE_BUSY) { + return; + } + auto pool = GetPool(); + if (pool != nullptr) { + pool->Dump(true, dumpHeader); + } +} + int32_t RdbStoreImpl::CloudTables::AddTables(const std::vector &tables) { std::lock_guard lock(mutex_); @@ -2692,4 +3002,87 @@ std::set RdbStoreImpl::CloudTables::Steal() } return result; } + +void RdbStoreImpl::SetKnowledgeSchema() +{ + auto [errCode, schema] = GetKnowledgeSchemaHelper()->GetRdbKnowledgeSchema(config_.GetName()); + if (errCode != E_OK) { + return; + } + auto [ret, conn] = GetConn(false); + if (ret != E_OK) { + LOG_ERROR("The database is busy or closed when set knowledge schema ret %{public}d.", ret); + return; + } + if (isKnowledgeSchemaReady_) { + return; + } + ret = conn->SetKnowledgeSchema(schema); + if (ret != E_OK) { + LOG_ERROR("Set knowledge schema failed %{public}d.", ret); + return; + } + isKnowledgeSchemaReady_ = true; + auto helper = GetKnowledgeSchemaHelper(); + helper->Init(config_, schema); + helper->DonateKnowledgeData(); +} + +int RdbStoreImpl::InitKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema &schema) +{ + auto [ret, conn] = GetConn(false); + if (ret != E_OK) { + LOG_ERROR("The database is busy or closed when set knowledge schema ret %{public}d.", ret); + return ret; + } + ret = conn->SetKnowledgeSchema(schema); + if (ret != E_OK) { + LOG_ERROR("Set knowledge schema failed %{public}d.", ret); + return ret; + } + return E_OK; +} + +std::shared_ptr RdbStoreImpl::GetKnowledgeSchemaHelper() +{ + std::lock_guard autoLock(helperMutex_); + if (knowledgeSchemaHelper_ == nullptr) { + knowledgeSchemaHelper_ = std::make_shared(); + } + return knowledgeSchemaHelper_; +} + +bool RdbStoreImpl::IsKnowledgeDataChange(const DistributedRdb::RdbChangedData &rdbChangedData) +{ + for (const auto &item : rdbChangedData.tableData) { + if (item.second.isKnowledgeDataChange) { + return true; + } + } + return false; +} + +bool RdbStoreImpl::IsNotifyService(const DistributedRdb::RdbChangedData &rdbChangedData) +{ + for (const auto &item : rdbChangedData.tableData) { + if (item.second.isP2pSyncDataChange || item.second.isTrackedDataChange) { + return true; + } + } + return false; +} + +int RdbStoreImpl::RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) +{ + if (!config_.IsVector() || isMemoryRdb_ || isReadOnly_) { + return E_NOT_SUPPORT; + } + + auto [ret, conn] = GetConn(false); + if (ret != E_OK) { + LOG_ERROR("The database is busy or closed when RegisterAlgo ret %{public}d.", ret); + return ret; + } + return conn->RegisterAlgo(clstAlgoName, func); +} } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp index 283e63ce5e1eb24d6fbcee1e673ab96e6a309818..752119982f150c35dfe3269d30b904e36f323cec 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp @@ -54,20 +54,42 @@ RdbStoreManager::~RdbStoreManager() Clear(); } -RdbStoreManager::RdbStoreManager() : configCache_(BUCKET_MAX_SIZE) +RdbStoreManager::RdbStoreManager() : configCache_(BUCKET_MAX_SIZE), promiseInfoCache_(PROMISEINFO_CACHE_SIZE) { } -std::shared_ptr RdbStoreManager::GetStoreFromCache(const std::string &path) +std::shared_ptr RdbStoreManager::GetStoreFromCache(const std::string &path, + const RdbStoreConfig &config, int &errCode) { + std::lock_guard lock(mutex_); + std::shared_ptr rdbStore = nullptr; auto it = storeCache_.find(path); if (it == storeCache_.end()) { - return nullptr; + rdbStore = std::make_shared(config); + storeCache_[path] = rdbStore; + return rdbStore; } - std::shared_ptr rdbStore = it->second.lock(); + + rdbStore = it->second.lock(); if (rdbStore == nullptr) { - storeCache_.erase(it); - return nullptr; + rdbStore = std::make_shared(config); + storeCache_[path] = rdbStore; + return rdbStore; + } + + if (!(rdbStore->GetConfig() == config)) { + auto log = RdbStoreConfig::FormatCfg(rdbStore->GetConfig(), config); + LOG_WARN("Diff config! app[%{public}s:%{public}s] path[%{public}s] cfg[%{public}s]", + config.GetBundleName().c_str(), config.GetModuleName().c_str(), SqliteUtils::Anonymous(path).c_str(), + log.c_str()); + Reportor::ReportFault(RdbFaultDbFileEvent(FT_OPEN, E_CONFIG_INVALID_CHANGE, config, log)); + if (rdbStore->GetConfig().IsMemoryRdb() || config.IsMemoryRdb()) { + errCode = E_CONFIG_INVALID_CHANGE; + rdbStore = nullptr; + return rdbStore; + } + rdbStore = std::make_shared(config); + storeCache_[path] = rdbStore; } return rdbStore; } @@ -75,54 +97,45 @@ std::shared_ptr RdbStoreManager::GetStoreFromCache(const std::stri std::shared_ptr RdbStoreManager::GetRdbStore( const RdbStoreConfig &config, int &errCode, int version, RdbOpenCallback &openCallback) { - errCode = CheckConfig(config); - if (errCode != E_OK) { - return nullptr; - } std::string path; errCode = SqliteGlobalConfig::GetDbPath(config, path); if (errCode != E_OK) { return nullptr; } - // TOD this lock should only work on storeCache_, add one more lock for connectionPool - std::lock_guard lock(mutex_); - std::shared_ptr rdbStore = GetStoreFromCache(path); - if (rdbStore != nullptr && rdbStore->GetConfig() == config) { - return rdbStore; + errCode = CheckConfig(config, path); + if (errCode != E_OK) { + return nullptr; } - if (rdbStore != nullptr) { - auto log = RdbStoreConfig::FormatCfg(rdbStore->GetConfig(), config); - LOG_WARN("Diff config! app[%{public}s:%{public}s] path[%{public}s] cfg[%{public}s]", - config.GetBundleName().c_str(), config.GetModuleName().c_str(), SqliteUtils::Anonymous(path).c_str(), - log.c_str()); - Reportor::ReportFault(RdbFaultDbFileEvent(FT_OPEN, E_CONFIG_INVALID_CHANGE, config, log)); - if (rdbStore->GetConfig().IsMemoryRdb() || config.IsMemoryRdb()) { - errCode = E_CONFIG_INVALID_CHANGE; - return nullptr; - } - storeCache_.erase(path); + std::shared_ptr rdbStore = nullptr; + RdbStoreConfig modifyConfig = config; + if (config.GetRoleType() == OWNER && IsConfigInvalidChanged(path, modifyConfig)) { + errCode = E_CONFIG_INVALID_CHANGE; rdbStore = nullptr; + return rdbStore; } - std::tie(errCode, rdbStore) = OpenStore(config, path); - if (errCode != E_OK || rdbStore == nullptr) { - return nullptr; + rdbStore = GetStoreFromCache(path, modifyConfig, errCode); + if (rdbStore == nullptr) { + return rdbStore; } - if (rdbStore->GetConfig().GetRoleType() == OWNER && !rdbStore->GetConfig().IsReadOnly()) { - errCode = SetSecurityLabel(rdbStore->GetConfig()); - if (errCode != E_OK) { - return nullptr; + errCode = rdbStore->Init(version, openCallback); + if (errCode != E_OK) { + if (modifyConfig.IsEncrypt() != config.IsEncrypt()) { + rdbStore = nullptr; + rdbStore = GetStoreFromCache(path, config, errCode); + if (rdbStore == nullptr) { + return rdbStore; + } + errCode = rdbStore->Init(version, openCallback); } - (void)rdbStore->ExchangeSlaverToMaster(); - errCode = ProcessOpenCallback(*rdbStore, version, openCallback); - if (errCode != E_OK) { - LOG_ERROR("Callback fail, path:%{public}s code:%{public}d", SqliteUtils::Anonymous(path).c_str(), errCode); - return nullptr; + if (errCode != E_OK || rdbStore == nullptr) { + rdbStore = nullptr; + return rdbStore; } } + if (!rdbStore->GetConfig().IsMemoryRdb()) { configCache_.Set(path, GetSyncParam(rdbStore->GetConfig())); } - storeCache_.insert_or_assign(std::move(path), rdbStore); return rdbStore; } @@ -132,7 +145,7 @@ bool RdbStoreManager::IsConfigInvalidChanged(const std::string &path, RdbStoreCo return false; } if (config.GetBundleName().empty()) { - LOG_WARN("Config has no bundleName, path: %{public}s", SqliteUtils::Anonymous(path).c_str()); + LOG_WARN("no bundleName"); return false; } Param lastParam = GetSyncParam(config); @@ -140,6 +153,7 @@ bool RdbStoreManager::IsConfigInvalidChanged(const std::string &path, RdbStoreCo LOG_WARN("Not found config cache, path: %{public}s", SqliteUtils::Anonymous(path).c_str()); return false; }; + configCache_.Set(path, lastParam); // The lastParam is possible that the same named db parameters of different paths when GetParamFromService if (lastParam.customDir_ != config.GetCustomDir() || lastParam.hapName_ != config.GetModuleName() || lastParam.area_ != config.GetArea()) { @@ -158,6 +172,7 @@ bool RdbStoreManager::IsConfigInvalidChanged(const std::string &path, RdbStoreCo LOG_WARN("Reset encrypt, storePath %{public}s, input:%{public}d original:%{public}d", SqliteUtils::Anonymous(path).c_str(), config.IsEncrypt(), lastParam.isEncrypt_); config.SetEncryptStatus(lastParam.isEncrypt_); + config.SetAllowRebuild(false); } return false; } @@ -201,9 +216,14 @@ int32_t RdbStoreManager::GetParamFromService(DistributedRdb::RdbSyncerParam &par return E_ERROR; } -bool RdbStoreManager::IsPermitted(const DistributedRdb::RdbSyncerParam ¶m) +bool RdbStoreManager::IsPermitted(const DistributedRdb::RdbSyncerParam ¶m, const std::string &path) { #if !defined(CROSS_PLATFORM) + bool result = false; + // ToDo: Scenario for handling cache refresh + if (promiseInfoCache_.Get(path, result)) { + return true; + }; auto [err, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(param); if (err == E_NOT_SUPPORT) { return false; @@ -214,6 +234,7 @@ bool RdbStoreManager::IsPermitted(const DistributedRdb::RdbSyncerParam ¶m) } err = service->VerifyPromiseInfo(param); if (err == DistributedRdb::RDB_OK) { + promiseInfoCache_.Set(path, true); return true; } LOG_ERROR("failed, bundleName:%{public}s, store:%{public}s, err:%{public}d.", param.bundleName_.c_str(), @@ -224,14 +245,34 @@ bool RdbStoreManager::IsPermitted(const DistributedRdb::RdbSyncerParam ¶m) void RdbStoreManager::Clear() { + configCache_.ResetCapacity(0); + configCache_.ResetCapacity(BUCKET_MAX_SIZE); + promiseInfoCache_.ResetCapacity(0); + promiseInfoCache_.ResetCapacity(PROMISEINFO_CACHE_SIZE); std::lock_guard lock(mutex_); auto iter = storeCache_.begin(); while (iter != storeCache_.end()) { + auto rdbStore = iter->second.lock(); + if (rdbStore.use_count() > 1) { + LOG_WARN("store[%{public}s] in use by %{public}ld holders", + SqliteUtils::Anonymous(rdbStore->GetPath()).c_str(), rdbStore.use_count()); + } iter = storeCache_.erase(iter); } storeCache_.clear(); } +void RdbStoreManager::Init() +{ + TaskExecutor::GetInstance().Init(); +} + +bool RdbStoreManager::Destroy() +{ + Clear(); + return TaskExecutor::GetInstance().Stop(); +} + bool RdbStoreManager::Remove(const std::string &path, bool shouldClose) { std::lock_guard lock(mutex_); @@ -239,7 +280,7 @@ bool RdbStoreManager::Remove(const std::string &path, bool shouldClose) auto it = storeCache_.find(path); if (it != storeCache_.end()) { auto rdbStore = it->second.lock(); - LOG_INFO("store in use by %{public}ld holders", storeCache_[path].lock().use_count()); + LOG_INFO("store in use by %{public}ld holders", rdbStore.use_count()); if (rdbStore && shouldClose) { rdbStore->Close(); } @@ -250,44 +291,6 @@ bool RdbStoreManager::Remove(const std::string &path, bool shouldClose) return false; } -int RdbStoreManager::ProcessOpenCallback(RdbStore &rdbStore, int version, RdbOpenCallback &openCallback) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - int errCode = E_OK; - if (version == -1) { - return errCode; - } - - int currentVersion; - errCode = rdbStore.GetVersion(currentVersion); - if (errCode != E_OK) { - return errCode; - } - - if (version == currentVersion) { - return openCallback.OnOpen(rdbStore); - } - - if (currentVersion == 0) { - errCode = openCallback.OnCreate(rdbStore); - } else if (version > currentVersion) { - errCode = openCallback.OnUpgrade(rdbStore, currentVersion, version); - } else { - errCode = openCallback.OnDowngrade(rdbStore, currentVersion, version); - } - - if (errCode == E_OK) { - errCode = rdbStore.SetVersion(version); - } - - if (errCode != E_OK) { - LOG_ERROR("RdbHelper ProcessOpenCallback set new version failed."); - return errCode; - } - - return openCallback.OnOpen(rdbStore); -} - bool RdbStoreManager::Delete(const RdbStoreConfig &config, bool shouldClose) { auto path = config.GetPath(); @@ -298,6 +301,9 @@ bool RdbStoreManager::Delete(const RdbStoreConfig &config, bool shouldClose) param.bundleName_ = config.GetBundleName(); param.storeName_ = *tokens.rbegin(); param.subUser_ = config.GetSubUser(); + param.area_ = config.GetArea(); + param.hapName_ = config.GetModuleName(); + param.customDir_ = config.GetCustomDir(); auto [err, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(param); if (err != E_OK || service == nullptr) { LOG_DEBUG("GetRdbService failed, err is %{public}d.", err); @@ -314,17 +320,6 @@ bool RdbStoreManager::Delete(const RdbStoreConfig &config, bool shouldClose) return Remove(path, shouldClose); } -int RdbStoreManager::SetSecurityLabel(const RdbStoreConfig &config) -{ - if (config.IsMemoryRdb()) { - return E_OK; - } -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) - return SecurityPolicy::SetSecurityLabel(config); -#endif - return E_OK; -} - int32_t RdbStoreManager::Collector(const RdbStoreConfig &config, DebugInfos &debugInfos, DfxInfo &dfxInfo) { #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) @@ -353,9 +348,9 @@ int32_t RdbStoreManager::Collector(const RdbStoreConfig &config, DebugInfos &deb return E_OK; } -int32_t RdbStoreManager::CheckConfig(const RdbStoreConfig &config) +int32_t RdbStoreManager::CheckConfig(const RdbStoreConfig &config, const std::string &path) { - if (config.GetRoleType() == VISITOR_WRITE && !IsPermitted(GetSyncParam(config))) { + if (config.GetRoleType() == VISITOR_WRITE && !IsPermitted(GetSyncParam(config), path)) { return E_NOT_SUPPORT; } if (config.IsMemoryRdb()) { @@ -369,23 +364,5 @@ int32_t RdbStoreManager::CheckConfig(const RdbStoreConfig &config) return E_OK; } -std::pair> RdbStoreManager::OpenStore( - const RdbStoreConfig &config, const std::string &path) -{ - RdbStoreConfig modifyConfig = config; - if (modifyConfig.GetRoleType() == OWNER && IsConfigInvalidChanged(path, modifyConfig)) { - return { E_CONFIG_INVALID_CHANGE, nullptr }; - } - - std::pair> result = { E_ERROR, nullptr }; - auto &[errCode, store] = result; - store = std::make_shared(modifyConfig, errCode); - if (errCode != E_OK && modifyConfig.IsEncrypt() != config.IsEncrypt()) { - LOG_WARN("Failed to OpenStore using modifyConfig. path:%{public}s, rc=%{public}d", - SqliteUtils::Anonymous(path).c_str(), errCode); - store = std::make_shared(config, errCode); // retry with input config - } - return result; -} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/share_block.cpp b/relational_store/frameworks/native/rdb/src/share_block.cpp index cfc30293e684b07a24e99129801f7e9e95739d7e..f2049745a02c52abfa9768df52ef3917cdf85663 100644 --- a/relational_store/frameworks/native/rdb/src/share_block.cpp +++ b/relational_store/frameworks/native/rdb/src/share_block.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 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 @@ -20,6 +20,7 @@ #include #include "logger.h" +#include "shared_block.h" #include "shared_block_serializer_info.h" #include "sqlite_errno.h" #include "sqlite_utils.h" diff --git a/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp b/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp index b8a3c73225e110db30ee16180414015deca20212..88517787084f9322054e2cc0a8c80526fbcb2802 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp @@ -26,12 +26,15 @@ #include #include +#include "global_resource.h" #include "logger.h" #include "raw_data_parser.h" #include "rdb_errno.h" #include "rdb_fault_hiview_reporter.h" +#include "rdb_icu_manager.h" #include "rdb_local_db_observer.h" #include "rdb_security_manager.h" +#include "rdb_sql_log.h" #include "rdb_sql_statistic.h" #include "rdb_store_config.h" #include "relational_store_client.h" @@ -40,6 +43,7 @@ #include "sqlite_errno.h" #include "sqlite_global_config.h" #include "sqlite_utils.h" +#include "suspender.h" #include "value_object.h" #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) #include "rdb_manager_impl.h" @@ -58,13 +62,15 @@ constexpr SqliteConnection::Suffix SqliteConnection::FILE_SUFFIXES[]; constexpr int SqliteConnection::DEFAULT_BUSY_TIMEOUT_MS; constexpr int SqliteConnection::BACKUP_PAGES_PRE_STEP; // 1024 * 4 * 12800 == 50m constexpr int SqliteConnection::BACKUP_PRE_WAIT_TIME; +constexpr int SqliteConnection::RESTORE_PRE_WAIT_TIME; constexpr ssize_t SqliteConnection::SLAVE_WAL_SIZE_LIMIT; constexpr ssize_t SqliteConnection::SLAVE_INTEGRITY_CHECK_LIMIT; constexpr uint32_t SqliteConnection::NO_ITER; +constexpr unsigned short SqliteConnection::BINLOG_FILE_NUMS_LIMIT; +constexpr uint32_t SqliteConnection::BINLOG_FILE_SIZE_LIMIT; constexpr uint32_t SqliteConnection::DB_INDEX; constexpr uint32_t SqliteConnection::WAL_INDEX; -constexpr uint32_t SqliteConnection::ITER_V1; -constexpr uint32_t SqliteConnection::SQLITE_CKSUMVFS_RESERVE_BYTES; +ConcurrentMap> SqliteConnection::reusableReplicas_ = {}; __attribute__((used)) const int32_t SqliteConnection::regCreator_ = Connection::RegisterCreator(DB_SQLITE, SqliteConnection::Create); __attribute__((used)) @@ -73,23 +79,32 @@ __attribute__((used)) const int32_t SqliteConnection::regDeleter_ = Connection::RegisterDeleter(DB_SQLITE, SqliteConnection::Delete); __attribute__((used)) const int32_t SqliteConnection::regCollector_ = Connection::RegisterCollector(DB_SQLITE, SqliteConnection::Collect); -__attribute__((used)) -const int32_t SqliteConnection::regRestorer_ = Connection::RegisterRestorer(DB_SQLITE, SqliteConnection::Restore); +__attribute__((used)) const int32_t SqliteConnection::regReplicaChecker_ = + Connection::RegisterReplicaChecker(DB_SQLITE, SqliteConnection::CheckReplicaIntegrity); +__attribute__((used)) const int32_t SqliteConnection::regDbClientCleaner_ = + GlobalResource::RegisterClean(GlobalResource::DB_CLIENT, SqliteConnection::ClientCleanUp); +__attribute__((used)) const int32_t SqliteConnection::regOpenSSLCleaner_ = + GlobalResource::RegisterClean(GlobalResource::OPEN_SSL, SqliteConnection::OpenSSLCleanUp); std::pair> SqliteConnection::Create(const RdbStoreConfig &config, bool isWrite) { std::pair> result = { E_ERROR, nullptr }; auto &[errCode, conn] = result; - std::tie(errCode, conn) = InnerCreate(config, isWrite); + std::tie(errCode, conn) = InnerCreate(config, isWrite, true); return result; } int32_t SqliteConnection::Delete(const RdbStoreConfig &config) { auto path = config.GetPath(); + auto binlogFolder = GetBinlogFolderPath(path); + size_t num = SqliteUtils::DeleteFolder(binlogFolder); + if (num > 0 && IsSupportBinlog(config)) { + LOG_INFO("removed %{public}zu binlog related items", num); + } auto slavePath = SqliteUtils::GetSlavePath(path); - Delete(path); Delete(slavePath); + Delete(path); return E_OK; } @@ -133,8 +148,8 @@ std::map SqliteConnection::Collect(const RdbStore return collection; } -SqliteConnection::SqliteConnection(const RdbStoreConfig &config, bool isWriteConnection) - : dbHandle_(nullptr), isWriter_(isWriteConnection), isReadOnly_(false), maxVariableNumber_(0), +SqliteConnection::SqliteConnection(const RdbStoreConfig &config, bool isWriteConnection, bool isSlave) + : dbHandle_(nullptr), isWriter_(isWriteConnection), isReadOnly_(false), isSlave_(isSlave), maxVariableNumber_(0), config_(config) { backupId_ = TaskExecutor::INVALID_TASK_ID; @@ -152,12 +167,12 @@ std::pair> SqliteConnection::CreateSl bool walOverLimit = bugInfo.find(FILE_SUFFIXES[WAL_INDEX].debug_) != bugInfo.end() && bugInfo[FILE_SUFFIXES[WAL_INDEX].debug_].size_ > SLAVE_WAL_SIZE_LIMIT; LOG_INFO("slave cfg:[%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d]%{public}s " - "%{public}s,[%{public}d,%{public}d,%{public}d,%{public}d]", + "%{public}s,[%{public}d,%{public}d,%{public}d,%{public}d,%{public}d]", config.GetDBType(), config.GetHaMode(), config.IsEncrypt(), config.GetArea(), config.GetSecurityLevel(), config.GetRoleType(), config.IsReadOnly(), SqliteUtils::FormatDebugInfoBrief(bugInfo, SqliteUtils::Anonymous(config.GetName())).c_str(), SqliteUtils::FormatDebugInfoBrief(Connection::Collect(config_), "master").c_str(), isSlaveExist, - isSlaveLockExist, hasFailure, walOverLimit); + isSlaveLockExist, hasFailure, walOverLimit, IsSupportBinlog(config_)); if (config.GetHaMode() == HAMode::MANUAL_TRIGGER && (slaveOpenPolicy == SlaveOpenPolicy::OPEN_IF_DB_VALID && (!isSlaveExist || isSlaveLockExist || hasFailure || walOverLimit))) { if (walOverLimit) { @@ -167,7 +182,8 @@ std::pair> SqliteConnection::CreateSl return result; } - std::shared_ptr connection = std::make_shared(config, true); + std::shared_ptr connection = std::make_shared(config, true, true); + connection->SetIsSupportBinlog(IsSupportBinlog(config_)); errCode = connection->InnerOpen(config); if (errCode != E_OK) { SqliteUtils::SetSlaveInvalid(config_.GetPath()); @@ -243,18 +259,19 @@ int SqliteConnection::InnerOpen(const RdbStoreConfig &config) } #endif isReadOnly_ = !isWriter_ || config.IsReadOnly(); - int openFileFlags = config.IsReadOnly() ? (SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) - : (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX); + uint32_t openFileFlags = config.IsReadOnly() ? (SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) + : (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX); if (config.IsMemoryRdb()) { openFileFlags |= SQLITE_OPEN_URI; } - errCode = OpenDatabase(dbPath, openFileFlags); + errCode = OpenDatabase(dbPath, static_cast(openFileFlags)); if (errCode != E_OK) { Reportor::ReportFault(RdbFaultDbFileEvent(FT_OPEN, errCode, config, "", true)); return errCode; } maxVariableNumber_ = sqlite3_limit(dbHandle_, SQLITE_LIMIT_VARIABLE_NUMBER, -1); + errCode = Configure(config, dbPath); isConfigured_ = true; if (errCode != E_OK) { @@ -273,7 +290,7 @@ int SqliteConnection::InnerOpen(const RdbStoreConfig &config) if (errCode == E_OK && static_cast(checkResult) != "ok") { LOG_ERROR("%{public}s integrity check result is %{public}s, sql:%{public}s", SqliteUtils::Anonymous(config.GetName()).c_str(), static_cast(checkResult).c_str(), - sql); + SqliteUtils::SqlAnonymous(sql).c_str()); Reportor::ReportCorruptedOnce(Reportor::Create(config, errCode, static_cast(checkResult))); } } @@ -283,10 +300,28 @@ int SqliteConnection::InnerOpen(const RdbStoreConfig &config) int32_t SqliteConnection::OpenDatabase(const std::string &dbPath, int openFileFlags) { - int errCode = sqlite3_open_v2(dbPath.c_str(), &dbHandle_, openFileFlags, nullptr); + const char *option = isSlave_ && isSupportBinlog_ ? "compressvfs" : nullptr; + int errCode = sqlite3_open_v2(dbPath.c_str(), &dbHandle_, openFileFlags, option); if (errCode != SQLITE_OK) { LOG_ERROR("fail to open database errCode=%{public}d, dbPath=%{public}s, flags=%{public}d, errno=%{public}d", errCode, SqliteUtils::Anonymous(dbPath).c_str(), openFileFlags, errno); + if (isSlave_ && errCode == SQLITE_WARNING && + sqlite3_extended_errcode(dbHandle_) == SQLITE_WARNING_NOTCOMPRESSDB) { + LOG_WARN("slave db is not using compress"); + return E_SQLITE_CORRUPT; + } + if (errCode == SQLITE_CANTOPEN) { + std::pair fileInfo = SqliteUtils::Stat(dbPath); + if (fileInfo.first != E_OK) { + LOG_ERROR("The stat error, errno=%{public}d, parent dir modes: %{public}s", errno, + SqliteUtils::GetParentModes(dbPath).c_str()); + } + Reportor::ReportFault(RdbFaultDbFileEvent(FT_OPEN, E_SQLITE_CANTOPEN, config_, + "failed to openDB errno[ " + std::to_string(errno) + "]," + + SqliteUtils::GetFileStatInfo(fileInfo.second) + + "parent dir modes:" + SqliteUtils::GetParentModes(dbPath), + true)); + } #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) auto const pos = dbPath.find_last_of("\\/"); if (pos != std::string::npos) { @@ -360,6 +395,7 @@ int SqliteConnection::SetCustomScalarFunction(const std::string &functionName, i int SqliteConnection::Configure(const RdbStoreConfig &config, std::string &dbPath) { + Suspender suspender(Suspender::SQL_STATISTIC); // there is a read-only dependency if (!config.GetCollatorLocales().empty()) { ConfigLocale(config.GetCollatorLocales()); @@ -369,12 +405,7 @@ int SqliteConnection::Configure(const RdbStoreConfig &config, std::string &dbPat return E_OK; } - auto errCode = SetCrcCheck(config); - if (errCode != E_OK) { - return errCode; - } - - errCode = RegDefaultFunctions(dbHandle_); + auto errCode = RegDefaultFunctions(dbHandle_); if (errCode != E_OK) { return errCode; } @@ -480,26 +511,75 @@ int SqliteConnection::RegisterClientObs() return E_OK; } -std::pair> SqliteConnection::CreateStatement( - const std::string &sql, std::shared_ptr conn) +int32_t SqliteConnection::CheckReplicaIntegrity(const RdbStoreConfig &config) { - std::shared_ptr statement = std::make_shared(); + std::shared_ptr connection = std::make_shared(config, true); + if (connection == nullptr) { + return E_ERROR; + } + RdbStoreConfig rdbSlaveStoreConfig = connection->GetSlaveRdbStoreConfig(config); + if (access(rdbSlaveStoreConfig.GetPath().c_str(), F_OK) != 0) { + return E_NOT_SUPPORT; + } + auto [ret, conn] = connection->CreateSlaveConnection(rdbSlaveStoreConfig, SlaveOpenPolicy::FORCE_OPEN); + if (ret != E_OK) { + return ret; + } + connection->slaveConnection_ = conn; + if (IsSupportBinlog(config)) { + SqliteConnection::ReplayBinlog(config.GetPath(), conn, false); + } + return connection->VeritySlaveIntegrity(); +} + +int SqliteConnection::CheckReplicaForRestore() +{ + return ExchangeVerify(true); +} + +std::pair> SqliteConnection::CreateStatement(const std::string &sql, + std::shared_ptr conn) +{ + return CreateStatementInner(sql, conn, dbHandle_, false); +} + +std::pair> SqliteConnection::CreateReplicaStatement(const std::string &sql, + std::shared_ptr conn) +{ + sqlite3 *db = dbHandle_; + RdbStoreConfig rdbSlaveStoreConfig = GetSlaveRdbStoreConfig(config_); + if (slaveConnection_ == nullptr && access(rdbSlaveStoreConfig.GetPath().c_str(), F_OK) == 0) { + auto [errCode, slaveConn] = CreateSlaveConnection(rdbSlaveStoreConfig, SlaveOpenPolicy::FORCE_OPEN); + if (errCode == E_OK) { + slaveConnection_ = slaveConn; + db = slaveConnection_->dbHandle_; + } + LOG_INFO("create slave conn ret=%{public}d, %{public}d", errCode, IsWriter()); + } + return CreateStatementInner(sql, conn, db, true); +} + +std::pair> SqliteConnection::CreateStatementInner(const std::string &sql, + std::shared_ptr conn, sqlite3 *db, bool isFromReplica) +{ + std::shared_ptr statement = std::make_shared(&config_); // When memory is not cleared, quick_check reads memory pages and detects damage but does not report it - if (sql == INTEGRITIES[1] && dbHandle_ != nullptr && mode_ == JournalMode::MODE_WAL) { - sqlite3_db_release_memory(dbHandle_); + if (sql == INTEGRITIES[1] && db != nullptr && mode_ == JournalMode::MODE_WAL) { + sqlite3_db_release_memory(db); } - statement->config_ = &config_; - int errCode = statement->Prepare(dbHandle_, sql); + int errCode = statement->Prepare(db, sql); if (errCode != E_OK) { return { errCode, nullptr }; } statement->conn_ = conn; - if (slaveConnection_ && IsWriter()) { + if (!isFromReplica && slaveConnection_ && IsWriter() && !IsSupportBinlog(config_) && + !SqliteUtils::IsSlaveRestoring(config_.GetPath())) { auto slaveStmt = std::make_shared(); if (sql == INTEGRITIES[1] && dbHandle_ != nullptr && mode_ == JournalMode::MODE_WAL) { sqlite3_db_release_memory(dbHandle_); } slaveStmt->config_ = &slaveConnection_->config_; + slaveStmt->conn_ = slaveConnection_; errCode = slaveStmt->Prepare(slaveConnection_->dbHandle_, sql); if (errCode != E_OK) { LOG_WARN("prepare slave stmt failed:%{public}d, app self can check the SQL", errCode); @@ -526,9 +606,10 @@ int SqliteConnection::SubscribeTableChanges(const Connection::Notifier ¬ifier int32_t status = RegisterClientObserver(dbHandle_, [notifier](const ClientChangedData &clientData) { DistributedRdb::RdbChangedData rdbChangedData; for (auto &[key, val] : clientData.tableData) { - if (val.isTrackedDataChange || val.isP2pSyncDataChange) { + if (val.isTrackedDataChange || val.isP2pSyncDataChange || val.isKnowledgeDataChange) { rdbChangedData.tableData[key].isTrackedDataChange = val.isTrackedDataChange; rdbChangedData.tableData[key].isP2pSyncDataChange = val.isP2pSyncDataChange; + rdbChangedData.tableData[key].isKnowledgeDataChange = val.isKnowledgeDataChange; } } notifier(rdbChangedData); @@ -565,6 +646,7 @@ int SqliteConnection::SetPageSize(const RdbStoreConfig &config) } int targetValue = config.GetPageSize(); + Suspender suspender(Suspender::SQL_LOG); auto [errCode, object] = ExecuteForValue("PRAGMA page_size"); if (errCode != E_OK) { LOG_ERROR("SetPageSize fail to get page size : %{public}d", errCode); @@ -584,24 +666,29 @@ int SqliteConnection::SetPageSize(const RdbStoreConfig &config) int SqliteConnection::SetEncryptAgo(const RdbStoreConfig &config) { - if (!config.GetCryptoParam().IsValid()) { - LOG_ERROR("Invalid crypto param: %{public}s, %{public}d, %{public}d, %{public}d, %{public}d, %{public}u", - SqliteUtils::Anonymous(config.GetName()).c_str(), config.GetCryptoParam().iterNum, - config.GetCryptoParam().encryptAlgo, config.GetCryptoParam().hmacAlgo, config.GetCryptoParam().kdfAlgo, - config.GetCryptoParam().cryptoPageSize); + return SetEncryptAgo(config.GetCryptoParam()); +} + +int SqliteConnection::SetEncryptAgo(const RdbStoreConfig::CryptoParam &cryptoParam) +{ + if (!cryptoParam.IsValid()) { + LOG_ERROR("Invalid crypto param: %{public}d, %{public}d, %{public}d, %{public}d, %{public}u", + cryptoParam.iterNum, cryptoParam.encryptAlgo, cryptoParam.hmacAlgo, cryptoParam.kdfAlgo, + cryptoParam.cryptoPageSize); return E_INVALID_ARGS; } - if (config.GetIter() != NO_ITER) { - auto errCode = ExecuteSql(std::string(GlobalExpr::CIPHER_ALGO_PREFIX) + - SqliteUtils::EncryptAlgoDescription(config.GetEncryptAlgo()) + - std::string(GlobalExpr::ALGO_SUFFIX)); + if (cryptoParam.iterNum != NO_ITER) { + auto errCode = + ExecuteSql(std::string(GlobalExpr::CIPHER_ALGO_PREFIX) + + SqliteUtils::EncryptAlgoDescription(static_cast(cryptoParam.encryptAlgo)) + + std::string(GlobalExpr::ALGO_SUFFIX)); if (errCode != E_OK) { LOG_ERROR("set cipher algo failed, err = %{public}d", errCode); return errCode; } - errCode = ExecuteSql(std::string(GlobalExpr::CIPHER_KDF_ITER) + std::to_string(config.GetIter())); + errCode = ExecuteSql(std::string(GlobalExpr::CIPHER_KDF_ITER) + std::to_string(cryptoParam.iterNum)); if (errCode != E_OK) { LOG_ERROR("set kdf iter number V1 failed, err = %{public}d", errCode); return errCode; @@ -609,7 +696,7 @@ int SqliteConnection::SetEncryptAgo(const RdbStoreConfig &config) } auto errCode = ExecuteSql(std::string(GlobalExpr::CODEC_HMAC_ALGO_PREFIX) + - SqliteUtils::HmacAlgoDescription(config.GetCryptoParam().hmacAlgo) + + SqliteUtils::HmacAlgoDescription(cryptoParam.hmacAlgo) + std::string(GlobalExpr::ALGO_SUFFIX)); if (errCode != E_OK) { LOG_ERROR("set codec hmac algo failed, err = %{public}d", errCode); @@ -617,7 +704,7 @@ int SqliteConnection::SetEncryptAgo(const RdbStoreConfig &config) } errCode = ExecuteSql(std::string(GlobalExpr::CODEC_KDF_ALGO_PREFIX) + - SqliteUtils::KdfAlgoDescription(config.GetCryptoParam().kdfAlgo) + + SqliteUtils::KdfAlgoDescription(cryptoParam.kdfAlgo) + std::string(GlobalExpr::ALGO_SUFFIX)); if (errCode != E_OK) { LOG_ERROR("set codec kdf algo failed, err = %{public}d", errCode); @@ -625,7 +712,7 @@ int SqliteConnection::SetEncryptAgo(const RdbStoreConfig &config) } errCode = ExecuteSql( - std::string(GlobalExpr::CODEC_PAGE_SIZE_PREFIX) + std::to_string(config.GetCryptoParam().cryptoPageSize)); + std::string(GlobalExpr::CODEC_PAGE_SIZE_PREFIX) + std::to_string(cryptoParam.cryptoPageSize)); if (errCode != E_OK) { LOG_ERROR("set codec page size failed, err = %{public}d", errCode); return errCode; @@ -639,7 +726,44 @@ int SqliteConnection::SetEncryptAgo(const RdbStoreConfig &config) return E_OK; } -int SqliteConnection::ReSetKey(const RdbStoreConfig &config) +int SqliteConnection::Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) +{ + std::vector key; + RdbPassword rdbPwd; + int errCode = E_OK; + if (cryptoParam.encryptKey_.empty()) { + rdbPwd = RdbSecurityManager::GetInstance().GetRdbPassword( + config_.GetPath(), RdbSecurityManager::PUB_KEY_FILE_NEW_KEY); + key = std::vector(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize()); + } else { + key = cryptoParam.encryptKey_; + } + if (key.empty()) { + LOG_ERROR("key is empty"); + return E_ERROR; + } + errCode = sqlite3_rekey(dbHandle_, static_cast(key.data()), static_cast(key.size())); + if (errCode != SQLITE_OK) { + key.assign(key.size(), 0); + LOG_ERROR("ReKey failed, err = %{public}d, name = %{public}s", errCode, + SqliteUtils::Anonymous(config_.GetName()).c_str()); + return SQLiteError::ErrNo(errCode); + } + errCode = SetEncryptAgo(cryptoParam); + if (errCode != E_OK) { + key.assign(key.size(), 0); + LOG_ERROR("ReKey failed, err = %{public}d, name = %{public}s", errCode, + SqliteUtils::Anonymous(config_.GetName()).c_str()); + return errCode; + } + if (cryptoParam.encryptKey_.empty()) { + RdbSecurityManager::GetInstance().ChangeKeyFile(config_.GetPath()); + } + key.assign(key.size(), 0); + return E_OK; +} + +int SqliteConnection::ResetKey(const RdbStoreConfig &config) { if (!IsWriter()) { return E_OK; @@ -658,24 +782,6 @@ int SqliteConnection::ReSetKey(const RdbStoreConfig &config) return E_OK; } -int SqliteConnection::SetCrcCheck(const RdbStoreConfig &config) -{ - if (config.IsEncrypt() || config.IsMemoryRdb()) { - return E_OK; - } - int n = -1; - auto errCode = SQLiteError::ErrNo(sqlite3_file_control(dbHandle_, 0, SQLITE_FCNTL_RESERVE_BYTES, &n)); - if (errCode != E_OK) { - LOG_ERROR("failed to set sqlite reserved bytes(SQLITE_FCNTL_RESERVE_BYTES), errCode=%{public}d", errCode); - return errCode; - } - if (n == 0) { - n = SQLITE_CKSUMVFS_RESERVE_BYTES; - (void)sqlite3_file_control(dbHandle_, 0, SQLITE_FCNTL_RESERVE_BYTES, &n); - } - return E_OK; -} - void SqliteConnection::SetDwrEnable(const RdbStoreConfig &config) { if (config.IsEncrypt() || config.IsMemoryRdb()) { @@ -733,7 +839,7 @@ int SqliteConnection::SetEncrypt(const RdbStoreConfig &config) } if (!newKey.empty()) { - ReSetKey(config); + ResetKey(config); } newKey.assign(newKey.size(), 0); return E_OK; @@ -749,13 +855,13 @@ int SqliteConnection::SetEncryptKey(const std::vector &key, const RdbSt if (errCode != SQLITE_OK) { return SQLiteError::ErrNo(errCode); } - + Suspender suspender(Suspender::SQL_LOG); errCode = SetEncryptAgo(config); if (errCode != E_OK) { return errCode; } - if (IsWriter()) { + if (IsWriter() || config.IsReadOnly()) { ValueObject version; std::tie(errCode, version) = ExecuteForValue(GlobalExpr::PRAGMA_VERSION); if (errCode != E_OK || version.GetType() == ValueObject::TYPE_NULL) { @@ -821,7 +927,7 @@ int SqliteConnection::SetJournalMode(const RdbStoreConfig &config) if (errCode != E_OK) { LOG_ERROR("SetJournalMode fail to get journal mode : %{public}d, errno %{public}d", errCode, errno); Reportor::ReportFault(RdbFaultEvent(FT_OPEN, E_DFX_GET_JOURNAL_FAIL, config_.GetBundleName(), - "PRAGMA journal_mode get fail: " + std::to_string(errCode) + "," + std::to_string(errno))); + "PRAGMA journal_mode get fail: " + std::to_string(errCode) + "," + std::to_string(errno))); // errno: 28 No space left on device return (errCode == E_SQLITE_IOERR && sqlite3_system_errno(dbHandle_) == 28) ? E_SQLITE_IOERR_FULL : errCode; } @@ -899,6 +1005,7 @@ int SqliteConnection::SetWalFile(const RdbStoreConfig &config) if (!IsWriter()) { return E_OK; } + Suspender suspender(Suspender::SQL_LOG); auto [errCode, version] = ExecuteForValue(GlobalExpr::PRAGMA_VERSION); if (errCode != E_OK) { return errCode; @@ -912,7 +1019,7 @@ int SqliteConnection::SetWalSyncMode(const std::string &syncMode) if (syncMode.length() != 0) { targetValue = syncMode; } - + Suspender suspender(Suspender::SQL_LOG); auto [errCode, object] = ExecuteForValue("PRAGMA synchronous"); if (errCode != E_OK) { LOG_ERROR("get wal sync mode fail, errCode:%{public}d", errCode); @@ -957,18 +1064,21 @@ std::pair SqliteConnection::ExecuteForValue( return { errCode, object }; } -int SqliteConnection::ClearCache() +int SqliteConnection::ClearCache(bool isForceClear) { if (dbHandle_ != nullptr && mode_ == JournalMode::MODE_WAL) { - int usedBytes = 0; - int nEnyry = 0; - int errCode = sqlite3_db_status(dbHandle_, SQLITE_DBSTATUS_CACHE_USED, &usedBytes, &nEnyry, 0); - if (errCode == SQLITE_OK && usedBytes > config_.GetClearMemorySize()) { + auto getUsedBytes = [dbHandle = dbHandle_]() -> int { + int usedBytes = 0; + int nEntry = 0; + sqlite3_db_status(dbHandle, SQLITE_DBSTATUS_CACHE_USED, &usedBytes, &nEntry, 0); + return usedBytes; + }; + if (isForceClear || getUsedBytes() > config_.GetClearMemorySize()) { sqlite3_db_release_memory(dbHandle_); } } if (slaveConnection_) { - int errCode = slaveConnection_->ClearCache(); + int errCode = slaveConnection_->ClearCache(isForceClear); if (errCode != E_OK) { LOG_ERROR("slaveConnection clearCache failed:%{public}d", errCode); } @@ -996,18 +1106,7 @@ void SqliteConnection::LimitPermission(const RdbStoreConfig &config, const std:: int SqliteConnection::ConfigLocale(const std::string &localeStr) { - static void *handle = dlopen("librelational_store_icu.z.so", RTLD_LAZY); - if (handle == nullptr) { - LOG_ERROR("dlopen(librelational_store_icu) failed(%{public}d)!", errno); - return E_NOT_SUPPORT; - } - auto func = reinterpret_cast(dlsym(handle, "ConfigICULocal")); - if (func == nullptr) { - LOG_ERROR("dlsym(librelational_store_icu) failed(%{public}d)!", errno); - return E_ERROR; - } - func(dbHandle_, localeStr); - return E_OK; + return RdbICUManager::GetInstance().ConfigLocale(dbHandle_, localeStr); } int SqliteConnection::CleanDirtyData(const std::string &table, uint64_t cursor) @@ -1109,10 +1208,10 @@ int32_t SqliteConnection::Unsubscribe(const std::shared_ptr &destEncryptKey, - bool isAsync, SlaveStatus &slaveStatus) + bool isAsync, std::shared_ptr slaveStatus, bool verifyDb) { - if (slaveStatus == SlaveStatus::BACKING_UP) { - LOG_INFO("backing up, return:%{public}s", config_.GetName().c_str()); + if (*slaveStatus == SlaveStatus::BACKING_UP) { + LOG_INFO("backing up, return:%{public}s", SqliteUtils::Anonymous(config_.GetName()).c_str()); return E_OK; } LOG_INFO( @@ -1125,8 +1224,9 @@ int32_t SqliteConnection::Backup(const std::string &databasePath, const std::vec return errCode; } slaveConnection_ = conn; + reusableReplicas_.InsertOrAssign(rdbSlaveStoreConfig.GetPath(), conn); } - return ExchangeSlaverToMaster(false, true, slaveStatus); + return ExchangeSlaverToMaster(false, verifyDb, slaveStatus); } if (backupId_ == TaskExecutor::INVALID_TASK_ID) { @@ -1135,7 +1235,7 @@ int32_t SqliteConnection::Backup(const std::string &databasePath, const std::vec LOG_WARN("task pool err when restore"); return E_OK; } - backupId_ = pool->Execute([this, &slaveStatus]() { + backupId_ = pool->Execute([this, slaveStatus]() { auto [err, conn] = InnerCreate(config_, true); if (err != E_OK) { return; @@ -1151,7 +1251,8 @@ int32_t SqliteConnection::Backup(const std::string &databasePath, const std::vec } int32_t SqliteConnection::Restore( - const std::string &databasePath, const std::vector &destEncryptKey, SlaveStatus &slaveStatus) + const std::string &databasePath, const std::vector &destEncryptKey, + std::shared_ptr slaveStatus) { return ExchangeSlaverToMaster(true, true, slaveStatus); }; @@ -1239,42 +1340,69 @@ int SqliteConnection::SetServiceKey(const RdbStoreConfig &config, int32_t errCod return errCode; } -int SqliteConnection::ExchangeSlaverToMaster(bool isRestore, bool verifyDb, SlaveStatus &curStatus) +int SqliteConnection::ExchangeSlaverToMaster(bool isRestore, bool verifyDb, std::shared_ptr curStatus) { - curStatus = SlaveStatus::BACKING_UP; + *curStatus = SlaveStatus::BACKING_UP; int err = verifyDb ? ExchangeVerify(isRestore) : E_OK; if (err != E_OK) { - curStatus = SlaveStatus::UNDEFINED; + *curStatus = SlaveStatus::UNDEFINED; + return err; + } + + err = SqliteNativeBackup(isRestore, curStatus); + if (err != E_OK) { return err; } - return SqliteNativeBackup(isRestore, curStatus); + if (!isRestore && IsSupportBinlog(config_) && config_.GetHaMode() != HAMode::SINGLE) { + LOG_INFO("reset binlog start"); + sqlite3_db_config(dbHandle_, SQLITE_DBCONFIG_ENABLE_BINLOG, nullptr); + SetBinlog(); + err = sqlite3_clean_binlog(dbHandle_, BinlogFileCleanModeE::BINLOG_FILE_CLEAN_ALL_MODE); + if (err != SQLITE_OK) { + sqlite3_db_config(dbHandle_, SQLITE_DBCONFIG_ENABLE_BINLOG, nullptr); + SqliteUtils::SetSlaveInvalid(config_.GetPath()); + } + LOG_INFO("reset binlog finished, %{public}d", err); + } + return E_OK; } -int SqliteConnection::SqliteNativeBackup(bool isRestore, SlaveStatus &curStatus) + +int SqliteConnection::SqliteBackupStep(bool isRestore, sqlite3_backup *pBackup, std::shared_ptr curStatus) { - sqlite3 *dbFrom = isRestore ? dbHandle_ : slaveConnection_->dbHandle_; - sqlite3 *dbTo = isRestore ? slaveConnection_->dbHandle_ : dbHandle_; - sqlite3_backup *pBackup = sqlite3_backup_init(dbFrom, "main", dbTo, "main"); - if (pBackup == nullptr) { - LOG_WARN("slave backup init failed"); - curStatus = SlaveStatus::UNDEFINED; - return E_OK; + int sleepTime = BACKUP_PRE_WAIT_TIME; + if (isRestore) { + sleepTime = SqliteUtils::IsSlaveRestoring(config_.GetPath()) ? RESTORE_PRE_WAIT_TIME : 0; } int rc = SQLITE_OK; do { - if (!isRestore && curStatus == SlaveStatus::BACKUP_INTERRUPT) { + if (!isRestore && (*curStatus == SlaveStatus::BACKUP_INTERRUPT || *curStatus == SlaveStatus::DB_CLOSING)) { rc = E_CANCEL; break; } rc = sqlite3_backup_step(pBackup, BACKUP_PAGES_PRE_STEP); - LOG_INFO("backup slave process cur/total:%{public}d/%{public}d, rs:%{public}d, isRestore:%{public}d", + LOG_INFO("backup slave process cur/total:%{public}d/%{public}d, rs:%{public}d,isRestore:%{public}d,%{public}d", sqlite3_backup_pagecount(pBackup) - sqlite3_backup_remaining(pBackup), sqlite3_backup_pagecount(pBackup), - rc, isRestore); - if (!isRestore) { - sqlite3_sleep(BACKUP_PRE_WAIT_TIME); + rc, isRestore, sleepTime); + if (sleepTime > 0) { + sqlite3_sleep(sleepTime); } } while (sqlite3_backup_pagecount(pBackup) != 0 && (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED)); (void)sqlite3_backup_finish(pBackup); + return rc; +} + +int SqliteConnection::SqliteNativeBackup(bool isRestore, std::shared_ptr curStatus) +{ + sqlite3 *dbFrom = isRestore ? dbHandle_ : slaveConnection_->dbHandle_; + sqlite3 *dbTo = isRestore ? slaveConnection_->dbHandle_ : dbHandle_; + sqlite3_backup *pBackup = sqlite3_backup_init(dbFrom, "main", dbTo, "main"); + if (pBackup == nullptr) { + LOG_WARN("slave backup init failed"); + *curStatus = SlaveStatus::UNDEFINED; + return E_OK; + } + int rc = SqliteBackupStep(isRestore, pBackup, curStatus); if (rc != SQLITE_DONE) { LOG_ERROR("backup slave err:%{public}d, isRestore:%{public}d", rc, isRestore); if (!isRestore) { @@ -1283,7 +1411,7 @@ int SqliteConnection::SqliteNativeBackup(bool isRestore, SlaveStatus &curStatus) slaveConnection_ = nullptr; (void)SqliteConnection::Delete(slaveConfig.GetPath()); } - curStatus = SlaveStatus::BACKUP_INTERRUPT; + *curStatus = SlaveStatus::BACKUP_INTERRUPT; Reportor::ReportCorrupted(Reportor::Create(slaveConfig, SQLiteError::ErrNo(rc), "ErrorType: slaveBackup")); } return rc == E_CANCEL ? E_CANCEL : SQLiteError::ErrNo(rc); @@ -1291,60 +1419,87 @@ int SqliteConnection::SqliteNativeBackup(bool isRestore, SlaveStatus &curStatus) rc = isRestore ? TryCheckPoint(true) : slaveConnection_->TryCheckPoint(true); if (rc != E_OK && config_.GetHaMode() == HAMode::MANUAL_TRIGGER) { if (!isRestore) { - curStatus = SlaveStatus::BACKUP_INTERRUPT; + *curStatus = SlaveStatus::BACKUP_INTERRUPT; } LOG_WARN("CheckPoint failed err:%{public}d, isRestore:%{public}d", rc, isRestore); return E_OK; } - curStatus = SlaveStatus::BACKUP_FINISHED; + *curStatus = SlaveStatus::BACKUP_FINISHED; SqliteUtils::SetSlaveValid(config_.GetPath()); LOG_INFO("backup slave success, isRestore:%{public}d", isRestore); return E_OK; } -ExchangeStrategy SqliteConnection::GenerateExchangeStrategy(const SlaveStatus &status) +ExchangeStrategy SqliteConnection::GenerateExchangeStrategy(std::shared_ptr status, bool isRelpay) { if (dbHandle_ == nullptr || slaveConnection_ == nullptr || slaveConnection_->dbHandle_ == nullptr || - config_.GetHaMode() == HAMode::SINGLE || status == SlaveStatus::BACKING_UP) { + config_.GetHaMode() == HAMode::SINGLE || *status == SlaveStatus::BACKING_UP) { return ExchangeStrategy::NOT_HANDLE; } - static const std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';"; + const std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';"; + const std::string qIndexSql = "SELECT COUNT(*) FROM sqlite_master WHERE type='index';"; auto [mRet, mObj] = ExecuteForValue(querySql); - if (mRet == E_SQLITE_CORRUPT) { + auto [mIdxRet, mIdxObj] = ExecuteForValue(qIndexSql); + if (mRet == E_SQLITE_CORRUPT || mIdxRet == E_SQLITE_CORRUPT) { LOG_WARN("main abnormal, err:%{public}d", mRet); return ExchangeStrategy::RESTORE; } int64_t mCount = static_cast(mObj); + int64_t mIdxCount = static_cast(mIdxObj); // trigger mode only does restore, not backup if (config_.GetHaMode() == HAMode::MANUAL_TRIGGER) { return mCount == 0 ? ExchangeStrategy::RESTORE : ExchangeStrategy::NOT_HANDLE; } - auto [sRet, sObj] = slaveConnection_->ExecuteForValue(querySql); - if (sRet == E_SQLITE_CORRUPT) { - LOG_WARN("slave db abnormal, need backup, err:%{public}d", sRet); - return ExchangeStrategy::BACKUP; + if (*status == SlaveStatus::DB_CLOSING) { + return ExchangeStrategy::NOT_HANDLE; } - if (status == SlaveStatus::DB_NOT_EXITS || status == SlaveStatus::BACKUP_INTERRUPT) { + if (*status == SlaveStatus::BACKUP_INTERRUPT) { return ExchangeStrategy::BACKUP; } - int64_t sCount = static_cast(sObj); - if ((mCount == sCount) && !SqliteUtils::IsSlaveInvalid(config_.GetPath())) { - LOG_INFO("equal, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount); - return ExchangeStrategy::NOT_HANDLE; + if (IsSupportBinlog(config_)) { + if (isRelpay) { + SqliteConnection::ReplayBinlog(config_.GetPath(), slaveConnection_, false); + } else if (mCount == 0) { + LOG_INFO("main empty"); + return ExchangeStrategy::RESTORE; + } else { + return ExchangeStrategy::PENDING_BACKUP; + } } - if (mCount == 0) { - LOG_INFO("main empty, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount); - return ExchangeStrategy::RESTORE; + return CompareWithSlave(mCount, mIdxCount); +} + +int SqliteConnection::SetKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema &schema) +{ + DistributedDB::DBStatus status = DistributedDB::DBStatus::OK; + for (const auto &table : schema.tables) { + DistributedDB::KnowledgeSourceSchema sourceSchema; + sourceSchema.tableName = table.tableName; + for (const auto &item : table.knowledgeFields) { + sourceSchema.knowledgeColNames.insert(item.columnName); + } + sourceSchema.extendColNames = std::set(table.referenceFields.begin(), + table.referenceFields.end()); + status = SetKnowledgeSourceSchema(dbHandle_, sourceSchema); + if (status != DistributedDB::DBStatus::OK) { + return E_ERROR; + } } - LOG_INFO("backup, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount); - return ExchangeStrategy::BACKUP; + return E_OK; } -int32_t SqliteConnection::Repair(const RdbStoreConfig &config) +int SqliteConnection::CleanDirtyLog(const std::string &table, uint64_t cursor) { - if (config.GetHaMode() == HAMode::MANUAL_TRIGGER) { - return SqliteConnection::Restore(config, SqliteUtils::GetSlavePath(config.GetPath()), config.GetPath()); + if (table.empty()) { + LOG_ERROR("table is empty"); + return E_INVALID_ARGS; } + auto status = CleanDeletedData(dbHandle_, table, cursor); + return status == DistributedDB::DBStatus::OK ? E_OK : E_ERROR; +} + +int32_t SqliteConnection::Repair(const RdbStoreConfig &config) +{ std::shared_ptr connection = std::make_shared(config, true); if (connection == nullptr) { return E_ERROR; @@ -1358,6 +1513,9 @@ int32_t SqliteConnection::Repair(const RdbStoreConfig &config) return ret; } connection->slaveConnection_ = conn; + if (IsSupportBinlog(config)) { + SqliteConnection::ReplayBinlog(config.GetPath(), conn, false); + } ret = connection->VeritySlaveIntegrity(); if (ret != E_OK) { return ret; @@ -1369,11 +1527,12 @@ int32_t SqliteConnection::Repair(const RdbStoreConfig &config) return ret; } connection->TryCheckPoint(true); - SlaveStatus curStatus; + std::shared_ptr curStatus = std::make_shared(SlaveStatus::UNDEFINED); ret = connection->ExchangeSlaverToMaster(true, false, curStatus); if (ret != E_OK) { - LOG_ERROR("repair failed, [%{public}s]->[%{public}s], err:%{public}d", rdbSlaveStoreConfig.GetName().c_str(), - SqliteUtils::Anonymous(config.GetName()).c_str(), ret); + auto slavePath = SqliteUtils::GetSlavePath(config.GetPath()); + LOG_ERROR("repair failed, [%{public}s]->[%{public}s], err:%{public}d", + SqliteUtils::Anonymous(slavePath).c_str(), SqliteUtils::Anonymous(config.GetName()).c_str(), ret); } else { LOG_INFO("repair main success:%{public}s", SqliteUtils::Anonymous(config.GetPath()).c_str()); } @@ -1383,6 +1542,7 @@ int32_t SqliteConnection::Repair(const RdbStoreConfig &config) int SqliteConnection::ExchangeVerify(bool isRestore) { if (isRestore) { + SqliteConnection::ReplayBinlog(config_); int err = VeritySlaveIntegrity(); if (err != E_OK) { return err; @@ -1391,7 +1551,7 @@ int SqliteConnection::ExchangeVerify(bool isRestore) return E_OK; } if (SqliteUtils::IsSlaveInvalid(config_.GetPath())) { - LOG_ERROR("incomplete slave, %{public}s", config_.GetName().c_str()); + LOG_ERROR("incomplete slave, %{public}s", SqliteUtils::Anonymous(config_.GetName()).c_str()); return E_SQLITE_CORRUPT; } return E_OK; @@ -1400,7 +1560,8 @@ int SqliteConnection::ExchangeVerify(bool isRestore) return E_ALREADY_CLOSED; } if (access(config_.GetPath().c_str(), F_OK) != 0) { - LOG_WARN("main no exist, isR:%{public}d, %{public}s", isRestore, config_.GetName().c_str()); + LOG_WARN("main no exist, isR:%{public}d, %{public}s", isRestore, + SqliteUtils::Anonymous(config_.GetName()).c_str()); return E_DB_NOT_EXIST; } auto [cRet, cObj] = ExecuteForValue(INTEGRITIES[1]); // 1 is quick_check @@ -1414,7 +1575,7 @@ int SqliteConnection::ExchangeVerify(bool isRestore) } std::pair> SqliteConnection::InnerCreate( - const RdbStoreConfig &config, bool isWrite) + const RdbStoreConfig &config, bool isWrite, bool isReusableReplica) { std::pair> result = { E_ERROR, nullptr }; auto &[errCode, conn] = result; @@ -1432,8 +1593,13 @@ std::pair> SqliteConnection::InnerCre if (isWrite && config.GetHaMode() != HAMode::SINGLE) { RdbStoreConfig slaveCfg = connection->GetSlaveRdbStoreConfig(config); auto [err, slaveConn] = connection->CreateSlaveConnection(slaveCfg, SlaveOpenPolicy::OPEN_IF_DB_VALID); - if (err == E_OK) { - conn->slaveConnection_ = slaveConn; + if (err != E_OK) { + return result; + } + conn->slaveConnection_ = slaveConn; + conn->SetBinlog(); + if (isReusableReplica) { + reusableReplicas_.InsertOrAssign(slaveCfg.GetPath(), slaveConn); } } return result; @@ -1453,7 +1619,7 @@ int SqliteConnection::VeritySlaveIntegrity() if (SqliteUtils::IsSlaveInterrupted(config_.GetPath())) { return E_SQLITE_CORRUPT; } - + Suspender suspender(Suspender::SQL_LOG); std::string sql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';"; auto [err, obj] = slaveConnection_->ExecuteForValue(sql); auto val = std::get_if(&obj.value); @@ -1470,9 +1636,14 @@ int SqliteConnection::VeritySlaveIntegrity() mCount = static_cast(*val); } } - bool isSlaveDbOverLimit = bugInfo.find(FILE_SUFFIXES[DB_INDEX].debug_) != bugInfo.end() && - bugInfo[FILE_SUFFIXES[DB_INDEX].debug_].size_ > SLAVE_INTEGRITY_CHECK_LIMIT; - if (isSlaveDbOverLimit && mCount == 0L) { + ssize_t slaveSize = 0; + if (IsSupportBinlog(config_)) { + slaveSize = SqliteUtils::GetDecompressedSize(slaveCfg.GetPath()); + } + if (slaveSize == 0 && bugInfo.find(FILE_SUFFIXES[DB_INDEX].debug_) != bugInfo.end()) { + slaveSize = bugInfo[FILE_SUFFIXES[DB_INDEX].debug_].size_; + } + if ((slaveSize > SLAVE_INTEGRITY_CHECK_LIMIT && mCount == 0L) || IsSupportBinlog(config_)) { return SqliteUtils::IsSlaveInvalid(config_.GetPath()) ? E_SQLITE_CORRUPT : E_OK; } @@ -1491,11 +1662,11 @@ bool SqliteConnection::IsDbVersionBelowSlave() if (slaveConnection_ == nullptr) { return false; } - + Suspender suspender(Suspender::SQL_LOG); auto [cRet, cObj] = ExecuteForValue("SELECT COUNT(*) FROM sqlite_master WHERE type='table';"); auto cVal = std::get_if(&cObj.value); if (cRet == E_SQLITE_CORRUPT || (cVal != nullptr && (static_cast(*cVal) == 0L))) { - LOG_INFO("main empty, %{public}d, %{public}s", cRet, config_.GetName().c_str()); + LOG_INFO("main empty, %{public}d, %{public}s", cRet, SqliteUtils::Anonymous(config_.GetName()).c_str()); return true; } @@ -1511,90 +1682,237 @@ bool SqliteConnection::IsDbVersionBelowSlave() return false; } -int SqliteConnection::CopyDb(const RdbStoreConfig &config, const std::string &srcPath, const std::string &destPath) +void SqliteConnection::BinlogOnErrFunc(void *pCtx, int errNo, char *errMsg, const char *dbPath) { - RdbStoreConfig srcConfig(config); - srcConfig.SetPath(srcPath); - srcConfig.SetIntegrityCheck(IntegrityCheck::FULL); - srcConfig.SetHaMode(HAMode::SINGLE); - auto [ret, conn] = Connection::Create(srcConfig, true); - if (ret == E_SQLITE_CORRUPT && srcConfig.IsEncrypt() && srcConfig.GetIter() != ITER_V1) { - srcConfig.SetIter(ITER_V1); - std::tie(ret, conn) = Connection::Create(srcConfig, true); + if (dbPath == nullptr) { + LOG_WARN("path is null"); + return; } - if (ret != E_OK) { - LOG_ERROR("backup file is corrupted, %{public}s", SqliteUtils::Anonymous(srcPath).c_str()); - return E_SQLITE_CORRUPT; + std::string dbPathStr(dbPath); + LOG_WARN("binlog failed, mark invalid %{public}s", SqliteUtils::Anonymous(dbPathStr).c_str()); + SqliteUtils::SetSlaveInvalid(dbPathStr); +} + +int SqliteConnection::BinlogOpenHandle(const std::string &dbPath, sqlite3 *&dbHandle, bool isMemoryRdb) +{ + uint32_t openFileFlags = (SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX); + if (isMemoryRdb) { + openFileFlags |= SQLITE_OPEN_URI; } - conn = nullptr; + sqlite3 *db = nullptr; + int err = sqlite3_open_v2(dbPath.c_str(), &db, static_cast(openFileFlags), nullptr); + if (err != SQLITE_OK) { + LOG_ERROR("open binlog handle error. rc=%{public}d, errno=%{public}d, p=%{public}s", + err, errno, SqliteUtils::Anonymous(dbPath).c_str()); + sqlite3_close_v2(db); + return E_INVALID_FILE_PATH; + } + dbHandle = db; + return E_OK; +} - auto walFile = srcPath + "-wal"; - if (SqliteUtils::GetFileSize(walFile) != 0) { - LOG_ERROR("Wal file exist."); - return E_SQLITE_CORRUPT; +void SqliteConnection::BinlogCloseHandle(sqlite3 *dbHandle) +{ + if (dbHandle != nullptr) { + int errCode = sqlite3_close_v2(dbHandle); + if (errCode != SQLITE_OK) { + LOG_ERROR("could not close binlog handle err = %{public}d, errno = %{public}d", errCode, errno); + } } - SqliteUtils::DeleteFile(srcPath + "-shm"); - SqliteUtils::DeleteFile(srcPath + "-wal"); - Connection::Delete(config); +} - if (config.GetPath() != destPath) { - RdbStoreConfig dstConfig(destPath); - Connection::Delete(dstConfig); +int SqliteConnection::CheckPathExist(const std::string &dbPath) +{ + bool isDbFileExist = access(dbPath.c_str(), F_OK) == 0; + if (!isDbFileExist) { + LOG_ERROR("db %{public}s not exist errno is %{public}d", + SqliteUtils::Anonymous(dbPath).c_str(), errno); + return E_DB_NOT_EXIST; } + return E_OK; +} - if (!SqliteUtils::CopyFile(srcPath, destPath)) { - return E_ERROR; +void SqliteConnection::BinlogSetConfig(sqlite3 *dbHandle) +{ + Sqlite3BinlogConfig binLogConfig = { + .mode = Sqlite3BinlogMode::ROW, + .fullCallbackThreshold = BINLOG_FILE_NUMS_LIMIT, + .maxFileSize = BINLOG_FILE_SIZE_LIMIT, + .xErrorCallback = &BinlogOnErrFunc, + .xLogFullCallback = nullptr, + .callbackCtx = nullptr, + }; + + int err = sqlite3_db_config(dbHandle, SQLITE_DBCONFIG_ENABLE_BINLOG, &binLogConfig); + if (err != SQLITE_OK) { + LOG_ERROR("set binlog config error. err=%{public}d, errno=%{public}d", err, errno); + } +} + +void SqliteConnection::BinlogOnFullFunc(void *pCtx, unsigned short currentCount, const char *dbPath) +{ + if (dbPath == nullptr) { + LOG_WARN("path is null"); + return; + } + auto pool = TaskExecutor::GetInstance().GetExecutor(); + if (pool == nullptr) { + LOG_WARN("get pool failed"); + return; + } + std::string dbPathStr(dbPath); + auto [found, weakPtr] = reusableReplicas_.Find(SqliteUtils::GetSlavePath(dbPathStr)); + if (!found) { + LOG_WARN("no replica connection for %{public}s", SqliteUtils::Anonymous(dbPath).c_str()); + return; + } + auto slaveConn = weakPtr.lock(); + if (slaveConn == nullptr) { + LOG_WARN("replica connection expired for %{public}s", SqliteUtils::Anonymous(dbPath).c_str()); + return; + } + pool->Execute([dbPathStr, slaveConn] { + SqliteConnection::ReplayBinlog(dbPathStr, slaveConn, true); + }); +} + +int SqliteConnection::SetBinlog() +{ + if (!IsSupportBinlog(config_)) { + return E_OK; + } + Sqlite3BinlogConfig binLogConfig = { + .mode = Sqlite3BinlogMode::ROW, + .fullCallbackThreshold = BINLOG_FILE_NUMS_LIMIT, + .maxFileSize = BINLOG_FILE_SIZE_LIMIT, + .xErrorCallback = &BinlogOnErrFunc, + .xLogFullCallback = &BinlogOnFullFunc, + .callbackCtx = nullptr, + }; + + LOG_INFO("binlog: open %{public}s", SqliteUtils::Anonymous(config_.GetPath()).c_str()); + int err = sqlite3_db_config(dbHandle_, SQLITE_DBCONFIG_ENABLE_BINLOG, &binLogConfig); + if (err != SQLITE_OK) { + LOG_ERROR("set binlog error. err=%{public}d, errno=%{public}d", err, errno); + return err; } return E_OK; } -int32_t SqliteConnection::Restore(const RdbStoreConfig &config, const std::string &srcPath, const std::string &destPath) +void SqliteConnection::ReplayBinlog(const std::string &dbPath, + std::shared_ptr slaveConn, bool isNeedClean) { - if (config.GetHaMode() == HAMode::SINGLE || !SqliteUtils::IsSlaveDbName(srcPath)) { - return SqliteConnection::CopyDb(config, srcPath, destPath); + auto errCode = SqliteConnection::CheckPathExist(dbPath); + if (errCode != E_OK) { + LOG_WARN("main db does not exist, %{public}d", errCode); + return; } - std::shared_ptr connection = std::make_shared(config, true); - if (connection == nullptr) { - return E_ERROR; + if (slaveConn == nullptr || slaveConn->dbHandle_ == nullptr) { + LOG_WARN("backup db does not exist, %{public}d", slaveConn == nullptr); + return; } - RdbStoreConfig slaveConfig = connection->GetSlaveRdbStoreConfig(config); - if (access(slaveConfig.GetPath().c_str(), F_OK) != 0) { - return E_NOT_SUPPORT; + sqlite3 *dbFrom = nullptr; + errCode = SqliteConnection::BinlogOpenHandle(dbPath, dbFrom, false); + if (errCode != E_OK) { + return; } - auto [ret, conn] = connection->CreateSlaveConnection(slaveConfig, SlaveOpenPolicy::FORCE_OPEN); - if (ret != E_OK) { - return ret; + SqliteConnection::BinlogSetConfig(dbFrom); + errCode = SQLiteError::ErrNo(sqlite3_replay_binlog(dbFrom, slaveConn->dbHandle_)); + if (errCode != E_OK) { + LOG_WARN("async replay err:%{public}d", errCode); + } else if (isNeedClean) { + errCode = SQLiteError::ErrNo(sqlite3_clean_binlog(dbFrom, BinlogFileCleanModeE::BINLOG_FILE_CLEAN_READ_MODE)); + LOG_INFO("clean finished, %{public}d, %{public}s", errCode, SqliteUtils::Anonymous(dbPath).c_str()); } - connection->slaveConnection_ = conn; + SqliteConnection::BinlogCloseHandle(dbFrom); + return; +} - int openMainRes = connection->InnerOpen(config); - ret = connection->VeritySlaveIntegrity(); - if (ret != E_OK) { - return ret; +void SqliteConnection::ReplayBinlog(const RdbStoreConfig &config) +{ + if (!IsSupportBinlog(config)) { + return; } - if (openMainRes == E_OK && SqliteUtils::IsSlaveInvalid(config.GetPath()) && !connection->IsDbVersionBelowSlave()) { - return E_SQLITE_CORRUPT; + if (slaveConnection_ == nullptr) { + LOG_WARN("back up does not exist"); + return; + } + if (SqliteConnection::CheckPathExist(config.GetPath()) != E_OK) { + LOG_WARN("main db does not exist"); + return; + } + int err = SQLiteError::ErrNo(sqlite3_replay_binlog(dbHandle_, slaveConnection_->dbHandle_)); + if (err != E_OK) { + LOG_WARN("replay err:%{public}d", err); } + return; +} - ret = SQLiteError::ErrNo(sqlite3_wal_checkpoint_v2(connection->slaveConnection_->dbHandle_, nullptr, - SQLITE_CHECKPOINT_TRUNCATE, nullptr, nullptr)); - if (ret != E_OK) { - LOG_ERROR("chk %{public}d %{public}d %{public}s", ret, errno, SqliteUtils::Anonymous(config.GetName()).c_str()); - return ret; +void SqliteConnection::SetIsSupportBinlog(bool isSupport) +{ + isSupportBinlog_ = isSupport; +} + +bool SqliteConnection::IsSupportBinlog(const RdbStoreConfig &config) +{ +#if !defined(CROSS_PLATFORM) + if (sqlite3_is_support_binlog == nullptr) { + return false; + } + if (sqlite3_is_support_binlog(config.GetName().c_str()) != SQLITE_OK) { + return false; } - connection->slaveConnection_ = nullptr; - connection = nullptr; + return !config.IsEncrypt() && !config.IsMemoryRdb(); +#else + return false; +#endif +} - if (!SqliteUtils::RenameFile(slaveConfig.GetPath(), config.GetPath())) { - LOG_ERROR("rename %{public}d %{public}s", errno, SqliteUtils::Anonymous(config.GetName()).c_str()); - return E_ERROR; +std::string SqliteConnection::GetBinlogFolderPath(const std::string &dbPath) +{ + std::string suffix(BINLOG_FOLDER_SUFFIX); + return dbPath + suffix; +} + +ExchangeStrategy SqliteConnection::CompareWithSlave(int64_t mCount, int64_t mIdxCount) +{ + const std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';"; + const std::string qIndexSql = "SELECT COUNT(*) FROM sqlite_master WHERE type='index';"; + auto [sRet, sObj] = slaveConnection_->ExecuteForValue(querySql); + auto [sInxRet, sInxObj] = slaveConnection_->ExecuteForValue(qIndexSql); + if (sRet == E_SQLITE_CORRUPT || sInxRet == E_SQLITE_CORRUPT) { + LOG_WARN("slave db abnormal, need backup, err:%{public}d", sRet); + return ExchangeStrategy::BACKUP; } - for (auto &suffix : FILE_SUFFIXES) { - if (suffix.suffix_ != nullptr && !std::string(suffix.suffix_).empty()) { - SqliteUtils::DeleteFile(config.GetPath() + suffix.suffix_); - } + int64_t sCount = static_cast(sObj); + int64_t sIdxCount = static_cast(sInxObj); + if ((mCount == sCount && mIdxCount == sIdxCount) && !SqliteUtils::IsSlaveInvalid(config_.GetPath())) { + LOG_INFO("equal, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount); + return ExchangeStrategy::NOT_HANDLE; + } + if (mCount == 0) { + LOG_INFO("main empty, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount); + return ExchangeStrategy::RESTORE; } - Connection::Delete(slaveConfig.GetPath()); + LOG_INFO("backup, main:[%{public}" PRId64 ",%{public}" PRId64 "], slave:[%{public}" PRId64 ",%{public}" PRId64 "]", + mCount, mIdxCount, sCount, sIdxCount); + return ExchangeStrategy::BACKUP; +} + +int SqliteConnection::RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) +{ + return E_NOT_SUPPORT; +} + +int32_t SqliteConnection::ClientCleanUp() +{ + Clean(false); + return E_OK; +} + +int32_t SqliteConnection::OpenSSLCleanUp() +{ + Clean(true); return E_OK; } } // namespace NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/sqlite_global_config.cpp b/relational_store/frameworks/native/rdb/src/sqlite_global_config.cpp index d75a12369123a33aa0093b7aee3797a8299210a4..760643456144c59651bed9f88b0820bb483d0987 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_global_config.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_global_config.cpp @@ -63,6 +63,10 @@ SqliteGlobalConfig::SqliteGlobalConfig() SqliteGlobalConfig::~SqliteGlobalConfig() { + sqlite3_unregister_cksumvfs(); + sqlite3_config(SQLITE_CONFIG_CORRUPTION, nullptr, nullptr); + sqlite3_config(SQLITE_CONFIG_LOG, nullptr, nullptr); + LOG_INFO("Destruct."); } void SqliteGlobalConfig::Corruption(void *arg, const void *msg) @@ -82,21 +86,22 @@ void SqliteGlobalConfig::Log(const void *data, int err, const char *msg) if (errType == 0 || errType == SQLITE_CONSTRAINT || errType == SQLITE_SCHEMA || errType == SQLITE_NOTICE || err == SQLITE_WARNING_AUTOINDEX) { if (verboseLog) { - LOG_INFO("Error(%{public}d) %{public}s ", err, SqliteUtils::Anonymous(msg).c_str()); + LOG_INFO("Error(%{public}d) %{public}s ", err, SqliteUtils::SqlAnonymous(msg).c_str()); } } else if (errType == SQLITE_WARNING) { - LOG_WARN("WARNING(%{public}d) %{public}s ", err, SqliteUtils::Anonymous(msg).c_str()); + LOG_WARN("WARNING(%{public}d) %{public}s ", err, SqliteUtils::SqlAnonymous(msg).c_str()); } else { - LOG_ERROR("Error(%{public}d) errno is:%{public}d %{public}s.", err, errno, SqliteUtils::Anonymous(msg).c_str()); + LOG_ERROR("Error(%{public}d) errno is:%{public}d %{public}s.", err, errno, + SqliteUtils::SqlAnonymous(msg).c_str()); SqliteErrReport(err, msg); } } void SqliteGlobalConfig::SqliteErrReport(int err, const char *msg) { - int lowErr = (err & 0xFF); + auto lowErr = static_cast(err) & 0xFF; if (lowErr == SQLITE_NOMEM || lowErr == SQLITE_INTERRUPT || lowErr == SQLITE_FULL || lowErr == SQLITE_SCHEMA || - lowErr == SQLITE_NOLFS || lowErr == SQLITE_AUTH || lowErr == SQLITE_BUSY || lowErr == SQLITE_LOCKED || + lowErr == SQLITE_NOLFS || lowErr == SQLITE_AUTH || lowErr == SQLITE_BUSY || lowErr == SQLITE_LOCKED || lowErr == SQLITE_IOERR || lowErr == SQLITE_CANTOPEN) { std::string log(msg == nullptr ? "" : SqliteUtils::Anonymous(msg).c_str()); log.append(",errcode=").append(std::to_string(err)).append(",errno=").append(std::to_string(errno)); diff --git a/relational_store/frameworks/native/rdb/src/sqlite_shared_result_set.cpp b/relational_store/frameworks/native/rdb/src/sqlite_shared_result_set.cpp index 14a523fb9091c24f5c8417e3eac841f07c1ce447..962b2214a5609021afa8fb35b4ecf3f8b91eb89a 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_shared_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_shared_result_set.cpp @@ -64,8 +64,8 @@ SqliteSharedResultSet::SqliteSharedResultSet( int64_t countCost = duration_cast(endTime - countBegin).count(); LOG_WARN("total[%{public}" PRId64 "]<%{public}" PRId64 ",%{public}" PRId64 ",%{public}" PRId64 "> rowCount[%{public}d] sql[%{public}s] path[%{public}s]", - totalCost, acquireCost, prepareCost, countCost, rowCount_, qrySql_.c_str(), - SqliteUtils::Anonymous(path).c_str()); + totalCost, acquireCost, prepareCost, countCost, rowCount_, + SqliteUtils::SqlAnonymous(qrySql_).c_str(), SqliteUtils::Anonymous(path).c_str()); } } @@ -84,7 +84,7 @@ std::pair, int> SqliteSharedResultSet::PrepareStep() auto type = SqliteUtils::GetSqlStatementType(qrySql_); if (type == SqliteUtils::STATEMENT_ERROR) { - LOG_ERROR("invalid sql_ %{public}s!", qrySql_.c_str()); + LOG_ERROR("invalid sql_ %{public}s, type: %{public}d", SqliteUtils::SqlAnonymous(qrySql_).c_str(), type); lastErr_ = E_INVALID_ARGS; return { nullptr, E_INVALID_ARGS }; } @@ -96,7 +96,7 @@ std::pair, int> SqliteSharedResultSet::PrepareStep() } if (!statement->ReadOnly()) { - LOG_ERROR("failed, %{public}s is not query sql!", SqliteUtils::Anonymous(qrySql_).c_str()); + LOG_ERROR("failed, %{public}s is not query sql!", SqliteUtils::SqlAnonymous(qrySql_).c_str()); lastErr_ = E_NOT_SELECT; return { nullptr, E_NOT_SELECT }; } @@ -117,8 +117,8 @@ SqliteSharedResultSet::~SqliteSharedResultSet() {} std::pair> SqliteSharedResultSet::GetColumnNames() { if (isClosed_) { - LOG_ERROR( - "fail, result set has been closed, ret %{public}d, sql %{public}s", E_ALREADY_CLOSED, qrySql_.c_str()); + LOG_ERROR("fail, result set has been closed, ret %{public}d, sql %{public}s", + E_ALREADY_CLOSED, SqliteUtils::SqlAnonymous(qrySql_).c_str()); return { E_ALREADY_CLOSED, {} }; } @@ -155,8 +155,8 @@ int SqliteSharedResultSet::Close() int SqliteSharedResultSet::OnGo(int oldPosition, int newPosition) { if (isClosed_) { - LOG_ERROR( - "fail, result set has been closed, ret %{public}d, sql %{public}s", E_ALREADY_CLOSED, qrySql_.c_str()); + LOG_ERROR("fail, result set has been closed, ret %{public}d, sql %{public}s", + E_ALREADY_CLOSED, SqliteUtils::SqlAnonymous(qrySql_).c_str()); return E_ALREADY_CLOSED; } auto sharedBlock = GetBlock(); diff --git a/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp b/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp index 2653f870db68c029b13f1321d0d5731bd3f73a5f..8cdc44574c0c125b1477c6ab450619e4b9064079 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp @@ -36,38 +36,6 @@ std::reference_wrapper SqliteSqlBuilder::nullRef_ = SqliteSqlBuilde SqliteSqlBuilder::SqliteSqlBuilder() {} SqliteSqlBuilder::~SqliteSqlBuilder() {} -/** - * Build a count SQL string using the given condition for SQLite. - */ -std::string SqliteSqlBuilder::BuildUpdateString(const ValuesBucket &values, const std::string &tableName, - const std::vector &whereArgs, const std::string &index, const std::string &whereClause, - const std::string &group, const std::string &order, int limit, int offset, std::vector &bindArgs, - ConflictResolution conflictResolution) -{ - std::string sql; - - sql.append("UPDATE") - .append(g_onConflictClause[static_cast(conflictResolution)]) - .append(" ") - .append(HandleTable(tableName)) - .append(" SET "); - const char *split = ""; - for (auto &[key, val] : values.values_) { - sql.append(split); - sql.append(key).append("=?"); - bindArgs.push_back(val); - split = ","; - } - - if (!whereArgs.empty()) { - for (size_t i = 0; i < whereArgs.size(); i++) { - bindArgs.push_back(ValueObject(whereArgs[i])); - } - } - sql.append(BuildSqlStringFromPredicates(index, "", whereClause, group, order, limit, offset)); - return sql; -} - /** * Build a query SQL string using the given condition for SQLite. */ @@ -78,58 +46,27 @@ int SqliteSqlBuilder::BuildQueryString(bool distinct, const std::string &table, if (table.empty()) { return E_EMPTY_TABLE_NAME; } - - std::string sql; - sql.append("SELECT "); - if (distinct) { - sql.append("DISTINCT "); - } - if (columns.size() != 0) { - AppendColumns(sql, columns); - } else { - sql.append("* "); - } - sql.append("FROM ") - .append(HandleTable(table)) - .append(BuildSqlStringFromPredicates(indexName, joinClause, whereClause, groupBy, orderBy, limit, offset)); - outSql = sql; - + outSql = GetSelectClause(columns, distinct, "*"); + AppendClause(outSql, " FROM ", table); + AppendClause(outSql, " INDEXED BY ", indexName); + AppendClause(outSql, " ", joinClause); + AppendClause(outSql, " WHERE ", whereClause); + AppendClause(outSql, " GROUP BY ", groupBy); + AppendClause(outSql, " ORDER BY ", orderBy); + AppendLimitAndOffset(outSql, limit, offset); return E_OK; } -std::string SqliteSqlBuilder::BuildSqlStringFromPredicates(const std::string &index, const std::string &joinClause, - const std::string &whereClause, const std::string &group, const std::string &order, int limit, int offset) +std::string SqliteSqlBuilder::BuildClauseFromPredicates(const AbsRdbPredicates &predicates) { std::string sqlString; - - std::string limitStr = (limit == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(limit); - std::string offsetStr = (offset == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(offset); - - AppendClause(sqlString, " INDEXED BY ", index); - AppendClause(sqlString, " ", joinClause); - AppendClause(sqlString, " WHERE ", whereClause); - AppendClause(sqlString, " GROUP BY ", group); - AppendClause(sqlString, " ORDER BY ", order); - AppendClause(sqlString, " LIMIT ", limitStr); - AppendClause(sqlString, " OFFSET ", offsetStr); - - return sqlString; -} - -std::string SqliteSqlBuilder::BuildSqlStringFromPredicates(const AbsPredicates &predicates) -{ - std::string limitStr = - (predicates.GetLimit() == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(predicates.GetLimit()); - std::string offsetStr = - (predicates.GetOffset() == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(predicates.GetOffset()); - - std::string sqlString; AppendClause(sqlString, " INDEXED BY ", predicates.GetIndex()); + AppendClause(sqlString, " ", predicates.GetJoinClause()); AppendClause(sqlString, " WHERE ", predicates.GetWhereClause()); AppendClause(sqlString, " GROUP BY ", predicates.GetGroup()); + AppendClause(sqlString, " HAVING ", predicates.GetHaving()); AppendClause(sqlString, " ORDER BY ", predicates.GetOrder()); - AppendClause(sqlString, " LIMIT ", limitStr); - AppendClause(sqlString, " OFFSET ", offsetStr); + AppendLimitAndOffset(sqlString, predicates.GetLimit(), predicates.GetOffset()); return sqlString; } @@ -171,53 +108,63 @@ void SqliteSqlBuilder::AppendColumns( } } +void SqliteSqlBuilder::AppendLimitAndOffset(std::string &builder, int limit, int offset) +{ + std::string limitStr = (limit == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(limit); + std::string offsetStr = (offset == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(offset); + AppendClause(builder, " LIMIT ", limitStr); + AppendClause(builder, " OFFSET ", offsetStr); +} + +std::string SqliteSqlBuilder::GetSelectClause( + const std::vector &columns, bool IsDistinct, const std::string &ast, const std::string &table) +{ + std::string sql; + sql.append("SELECT "); + if (IsDistinct) { + sql.append("DISTINCT "); + } + if (!columns.empty()) { + AppendColumns(sql, columns, table); + } else { + sql.append(table + ast); + } + return sql; +} + std::string SqliteSqlBuilder::BuildQueryString( const AbsRdbPredicates &predicates, const std::vector &columns) { - bool distinct = predicates.IsDistinct(); - std::string tableName = predicates.GetTableName(); - std::string joinClauseStr = predicates.GetJoinClause(); - std::string whereClauseStr = predicates.GetWhereClause(); - std::string groupStr = predicates.GetGroup(); - std::string indexStr = predicates.GetIndex(); - std::string orderStr = predicates.GetOrder(); - int limit = predicates.GetLimit(); - int offset = predicates.GetOffset(); - std::string sqlStr; - BuildQueryString(distinct, tableName, joinClauseStr, columns, whereClauseStr, groupStr, indexStr, orderStr, limit, - offset, sqlStr); + if (predicates.GetTableName().empty()) { + return ""; + } + + std::string sqlStr = GetSelectClause(columns, predicates.IsDistinct(), "*"); + AppendClause(sqlStr, " FROM ", predicates.GetTableName()); + sqlStr.append(BuildClauseFromPredicates(predicates)); return sqlStr; } std::string SqliteSqlBuilder::BuildCountString(const AbsRdbPredicates &predicates) { std::string tableName = predicates.GetTableName(); - return "SELECT COUNT(*) FROM " + HandleTable(tableName) + BuildSqlStringFromPredicates(predicates); + return "SELECT COUNT(*) FROM " + tableName + BuildClauseFromPredicates(predicates); } std::string SqliteSqlBuilder::BuildCursorQueryString(const AbsRdbPredicates &predicates, const std::vector &columns, const std::string &logTable, const std::pair &queryStatus) { - std::string sql; - std::string table = HandleTable(predicates.GetTableName()); - auto logName = HandleTable(logTable); + std::string table = predicates.GetTableName(); + auto logName = logTable; if (table.empty() || logName.empty()) { - return sql; - } - sql.append("SELECT "); - if (predicates.IsDistinct()) { - sql.append("DISTINCT "); - } - if (!columns.empty()) { - AppendColumns(sql, columns, table); - } else { - sql.append(table + ".*"); + return ""; } + std::string sql = GetSelectClause(columns, predicates.IsDistinct(), ".*", table); + logName += "."; if (queryStatus.first) { - std::string field = DistributedRdb::Field::SHARING_RESOURCE_FIELD; - SqliteUtils::Replace(field, SqliteUtils::REP, ""); - SqliteUtils::Replace(sql, table + "." + DistributedRdb::Field::SHARING_RESOURCE_FIELD, - logName + "." + SHARING_RESOURCE + " AS " + field); + std::string field = SqliteUtils::Replace(DistributedRdb::Field::SHARING_RESOURCE_FIELD, SqliteUtils::REP, ""); + sql = SqliteUtils::Replace(sql, table + "." + DistributedRdb::Field::SHARING_RESOURCE_FIELD, + logName + SHARING_RESOURCE + " AS " + field); } if (queryStatus.second) { sql.append(", " + logTable + ".cursor"); @@ -231,61 +178,39 @@ std::string SqliteSqlBuilder::BuildCursorQueryString(const AbsRdbPredicates &pre AppendClause(sql, " INDEXED BY ", predicates.GetIndex()); sql.append(" INNER JOIN ").append(logTable).append(" ON ").append(table) .append(".ROWID = ").append(logTable).append(".data_key"); - auto whereClause = predicates.GetWhereClause(); - SqliteUtils::Replace(whereClause, SqliteUtils::REP, logName + "."); - AppendClause(sql, " WHERE ", whereClause); + + AppendClause(sql, " WHERE ", SqliteUtils::Replace(predicates.GetWhereClause(), SqliteUtils::REP, logName)); AppendClause(sql, " GROUP BY ", predicates.GetGroup(), table); - auto order = predicates.GetOrder(); - SqliteUtils::Replace(order, SqliteUtils::REP, logName + "."); - AppendClause(sql, " ORDER BY ", order); - int limit = predicates.GetLimit(); - auto limitClause = (limit == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(limit); - int offset = predicates.GetOffset(); - auto offsetClause = (offset == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(offset); - AppendClause(sql, " LIMIT ", limitClause); - AppendClause(sql, " OFFSET ", offsetClause); + AppendClause(sql, " HAVING ", SqliteUtils::Replace(predicates.GetHaving(), SqliteUtils::REP, logName)); + AppendClause(sql, " ORDER BY ", SqliteUtils::Replace(predicates.GetOrder(), SqliteUtils::REP, logName)); + AppendLimitAndOffset(sql, predicates.GetLimit(), predicates.GetOffset()); return sql; } std::string SqliteSqlBuilder::BuildLockRowQueryString( const AbsRdbPredicates &predicates, const std::vector &columns, const std::string &logTable) { - std::string sql; - std::string table = HandleTable(predicates.GetTableName()); - auto logName = HandleTable(logTable); + std::string table = predicates.GetTableName(); + auto logName = logTable; if (table.empty() || logName.empty()) { - return sql; - } - sql.append("SELECT "); - if (predicates.IsDistinct()) { - sql.append("DISTINCT "); - } - if (!columns.empty()) { - AppendColumns(sql, columns, table); - } else { - sql.append(table + ".*"); + return ""; } + std::string sql = GetSelectClause(columns, predicates.IsDistinct(), ".*", table); sql.append(" FROM ").append(table); AppendClause(sql, " INDEXED BY ", predicates.GetIndex()); sql.append(" INNER JOIN ").append(logName).append(" ON "); - sql.append(table).append(".ROWID = ").append(logName).append(".data_key"); + logName += "."; + sql.append(table).append(".ROWID = ").append(logName).append("data_key"); auto whereClause = predicates.GetWhereClause(); if (whereClause.empty()) { - sql.append(" WHERE ").append(logName).append(".status = 2 OR ").append(logName).append(".status = 3 "); + sql.append(" WHERE ").append(logName).append("status = 2 OR ").append(logName).append("status = 3 "); } else { - SqliteUtils::Replace(whereClause, SqliteUtils::REP, logName + "."); - AppendClause(sql, " WHERE ", whereClause); + AppendClause(sql, " WHERE ", SqliteUtils::Replace(whereClause, SqliteUtils::REP, logName)); } AppendClause(sql, " GROUP BY ", predicates.GetGroup(), table); - auto order = predicates.GetOrder(); - SqliteUtils::Replace(order, SqliteUtils::REP, logName + "."); - AppendClause(sql, " ORDER BY ", order); - int limit = predicates.GetLimit(); - auto limitClause = (limit == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(limit); - int offset = predicates.GetOffset(); - auto offsetClause = (offset == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(offset); - AppendClause(sql, " LIMIT ", limitClause); - AppendClause(sql, " OFFSET ", offsetClause); + AppendClause(sql, " HAVING ", SqliteUtils::Replace(predicates.GetHaving(), SqliteUtils::REP, logName)); + AppendClause(sql, " ORDER BY ", SqliteUtils::Replace(predicates.GetOrder(), SqliteUtils::REP, logName)); + AppendLimitAndOffset(sql, predicates.GetLimit(), predicates.GetOffset()); return sql; } @@ -369,18 +294,6 @@ SqliteSqlBuilder::BatchRefSqls SqliteSqlBuilder::MakeExecuteSqls( return executeSqls; } -std::string SqliteSqlBuilder::HandleTable(const std::string &tableName) -{ - if (tableName.empty()) { - return tableName; - } - std::regex validName("^([a-zA-Z_][a-zA-Z0-9_\\.\\ ]*)$"); - if (std::regex_match(tableName, validName)) { - return tableName; - } - return "'" + tableName + "'"; -} - void SqliteSqlBuilder::UpdateAssetStatus(const ValueObject &val, int32_t status) { if (val.GetType() == ValueObject::TYPE_ASSET) { @@ -398,5 +311,17 @@ void SqliteSqlBuilder::UpdateAssetStatus(const ValueObject &val, int32_t status) } } } + +void SqliteSqlBuilder::AppendReturning(std::string &sql, const std::vector &fields) +{ + if (fields.empty()) { + return; + } + sql.append(" returning "); + for (const auto &field : fields) { + sql.append(field).append(","); + } + sql.pop_back(); +} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp b/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp index 429ab25d23dbd67e93f9d163de276da02aac2cee..16c24715da016b202bc17ab4a35447eb6e7cc674 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp @@ -26,7 +26,10 @@ #include "raw_data_parser.h" #include "rdb_errno.h" #include "rdb_fault_hiview_reporter.h" +#include "rdb_sql_log.h" #include "rdb_sql_statistic.h" +#include "rdb_perfStat.h" +#include "rdb_types.h" #include "relational_store_client.h" #include "remote_result_set.h" #include "share_block.h" @@ -43,6 +46,7 @@ namespace NativeRdb { using namespace OHOS::Rdb; using namespace std::chrono; using SqlStatistic = DistributedRdb::SqlStatistic; +using PerfStat = DistributedRdb::PerfStat; using Reportor = RdbFaultHiViewReporter; // Setting Data Precision constexpr SqliteStatement::Action SqliteStatement::ACTIONS[ValueObject::TYPE_MAX]; @@ -52,16 +56,21 @@ static constexpr const char *ERR_MSG[] = { "no such column:", "has no column named" }; -SqliteStatement::SqliteStatement() : readOnly_(false), columnCount_(0), numParameters_(0), stmt_(nullptr), sql_("") + +SqliteStatement::SqliteStatement(const RdbStoreConfig *config) + : readOnly_(false), columnCount_(0), numParameters_(0), stmt_(nullptr), sql_(""), config_(config) { - seqId_ = SqlStatistic::GenerateId(); + seqId_ = PerfStat::GenerateId(); SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL_REF, seqId_); + PerfStat perfStat((config_ != nullptr) ? config_->GetPath() : "", "", SqlStatistic::Step::STEP_TOTAL_REF, seqId_); } SqliteStatement::~SqliteStatement() { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL_RES, seqId_); + PerfStat perfStat((config_ != nullptr) ? config_->GetPath() : "", "", PerfStat::Step::STEP_TOTAL_RES, seqId_); Finalize(); + slave_ = nullptr; conn_ = nullptr; config_ = nullptr; } @@ -120,6 +129,18 @@ void SqliteStatement::HandleErrMsg(const std::string &errMsg, const std::string } } } +void SqliteStatement::TryNotifyErrorLog(const int &errCode, sqlite3 *dbHandle, const std::string &sql) +{ + if (errCode == SQLITE_ROW || errCode == SQLITE_DONE || errCode == SQLITE_OK) { + return ; + } + std::string errMsg(sqlite3_errmsg(dbHandle)); + DistributedRdb::SqlErrorObserver::ExceptionMessage exceMessage; + exceMessage.code = errCode; + exceMessage.message = std::move(errMsg); + exceMessage.sql = sql; + NativeRdb::SqlLog::Notify(config_->GetPath(), exceMessage); +} int SqliteStatement::Prepare(sqlite3 *dbHandle, const std::string &newSql) { @@ -129,9 +150,11 @@ int SqliteStatement::Prepare(sqlite3 *dbHandle, const std::string &newSql) // prepare the new sqlite3_stmt sqlite3_stmt *stmt = nullptr; SqlStatistic sqlStatistic(newSql, SqlStatistic::Step::STEP_PREPARE, seqId_); + PerfStat perfStat((config_ != nullptr) ? config_->GetPath() : "", newSql, PerfStat::Step::STEP_PREPARE, seqId_); int errCode = sqlite3_prepare_v2(dbHandle, newSql.c_str(), newSql.length(), &stmt, nullptr); if (errCode != SQLITE_OK) { std::string errMsg(sqlite3_errmsg(dbHandle)); + TryNotifyErrorLog(errCode, dbHandle, newSql); if (errMsg.size() != 0) { HandleErrMsg(errMsg, config_->GetPath(), config_->GetBundleName()); } @@ -223,6 +246,7 @@ int SqliteStatement::BindArgs(const std::vector &bindArgs) int SqliteStatement::BindArgs(const std::vector> &bindArgs) { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_PREPARE, seqId_); + PerfStat perfStat((config_ != nullptr) ? config_->GetPath() : "", "", PerfStat::Step::STEP_PREPARE, seqId_); if (bound_) { sqlite3_reset(stmt_); sqlite3_clear_bindings(stmt_); @@ -237,7 +261,8 @@ int SqliteStatement::BindArgs(const std::vector &args) if (count > numParameters_) { LOG_ERROR("bind args count(%{public}d) > numParameters(%{public}d), sql: %{public}s", count, numParameters_, - sql_.c_str()); + SqliteUtils::SqlAnonymous(sql_).c_str()); return E_INVALID_BIND_ARGS_COUNT; } @@ -353,8 +378,11 @@ int SqliteStatement::Step() int SqliteStatement::InnerStep() { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_EXECUTE, seqId_); + PerfStat perfStat((config_ != nullptr) ? config_->GetPath() : "", "", PerfStat::Step::STEP_EXECUTE, seqId_); auto errCode = sqlite3_step(stmt_); int ret = SQLiteError::ErrNo(errCode); + auto db = sqlite3_db_handle(stmt_); + TryNotifyErrorLog(errCode, db, sql_); if (config_ != nullptr && (errCode == SQLITE_CORRUPT || (errCode == SQLITE_NOTADB && config_->GetIter() != 0))) { Reportor::ReportCorruptedOnce(Reportor::Create(*config_, ret, (errCode == SQLITE_CORRUPT ? SqliteGlobalConfig::GetLastCorruptionMsg() : "SqliteStatement::InnerStep"))); @@ -416,7 +444,7 @@ int32_t SqliteStatement::Execute(const std::vector(args.size()); if (count != numParameters_) { LOG_ERROR("bind args count(%{public}d) > numParameters(%{public}d), sql is %{public}s", count, numParameters_, - sql_.c_str()); + SqliteUtils::SqlAnonymous(sql_).c_str()); return E_INVALID_BIND_ARGS_COUNT; } @@ -440,7 +468,8 @@ int32_t SqliteStatement::Execute(const std::vectorExecute(args); if (errCode != E_OK) { - LOG_ERROR( - "slave execute error:%{public}d, sql is %{public}s, errno %{public}d", errCode, sql_.c_str(), errno); + LOG_ERROR("slave execute error:%{public}d, sql is %{public}s, errno %{public}d", + errCode, SqliteUtils::SqlAnonymous(sql_).c_str(), errno); SqliteUtils::SetSlaveInvalid(config_->GetPath()); } } @@ -602,6 +631,43 @@ std::pair SqliteStatement::GetColumn(int index) const return { E_OK, GetValueFromBlob(index, type) }; } +std::pair> SqliteStatement::GetRows(uint32_t maxCount) +{ + auto colCount = GetColumnCount(); + if (colCount <= 0) { + return { E_OK, {} }; + } + std::vector valuesBuckets; + std::vector colNames; + colNames.reserve(colCount); + for (int i = 0; i < colCount; i++) { + auto [code, colName] = GetColumnName(i); + if (code != E_OK) { + LOG_ERROR("GetColumnName ret %{public}d", code); + return { code, {} }; + } + colNames.push_back(std::move(colName)); + } + int32_t status = 0; + do { + if (valuesBuckets.size() >= maxCount) { + break; + } + ValuesBucket value; + for (int32_t i = 0; i < colCount; i++) { + auto [code, val] = GetColumn(i); + if (code != E_OK) { + LOG_WARN("GetColumn failed, errCode:%{public}d", code); + continue; + } + value.Put(colNames[i], std::move(val)); + } + valuesBuckets.push_back(std::move(value)); + status = InnerStep(); + } while (status == E_OK); + return { status, valuesBuckets }; +} + ValueObject SqliteStatement::GetValueFromBlob(int32_t index, int32_t type) const { int size = sqlite3_column_bytes(stmt_, index); @@ -650,6 +716,7 @@ bool SqliteStatement::SupportBlockInfo() const int32_t SqliteStatement::FillBlockInfo(SharedBlockInfo *info) const { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_EXECUTE, seqId_); + PerfStat perfStat((config_ != nullptr) ? config_->GetPath() : "", "", PerfStat::Step::STEP_EXECUTE, seqId_); if (info == nullptr) { return E_INVALID_ARGS; } @@ -660,6 +727,15 @@ int32_t SqliteStatement::FillBlockInfo(SharedBlockInfo *info) const errCode = FillSharedBlock(info, stmt_); } if (errCode != E_OK) { + if (config_ != nullptr) { + Reportor::ReportFault(RdbFaultDbFileEvent(FT_CURD, errCode, *config_, + "FillBlockInfo", true)); + } + auto ret = (config_ != nullptr && errCode == E_SQLITE_CORRUPT); + if (ret) { + Reportor::ReportCorruptedOnce(Reportor::Create(*config_, errCode, + "FillBlockInfo: " + SqliteGlobalConfig::GetLastCorruptionMsg())); + } return errCode; } if (!ResetStatement(info, stmt_)) { @@ -795,7 +871,9 @@ int SqliteStatement::InnerFinalize() return E_OK; } + auto db = sqlite3_db_handle(stmt_); int errCode = sqlite3_finalize(stmt_); + TryNotifyErrorLog(errCode, db, sql_); stmt_ = nullptr; sql_ = ""; readOnly_ = false; diff --git a/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp b/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp index 9a5fb81f85bc8da97af0c16b0852378e91c97f1b..0fed2908d52f3e4335a965cf24b667a88ba0c4d4 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp @@ -16,6 +16,7 @@ #include "sqlite_utils.h" #include +#include #include #include #include @@ -27,6 +28,11 @@ #include #include #include +#if !defined(CROSS_PLATFORM) +#include +#include +#include "relational/relational_store_sqlite_ext.h" +#endif #include #include #include @@ -42,7 +48,6 @@ namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; - /* A continuous number must contain at least eight digits, because the employee ID has eight digits, and the mobile phone number has 11 digits. The UUID is longer */ constexpr int32_t CONTINUOUS_DIGITS_MINI_SIZE = 6; @@ -54,9 +59,75 @@ constexpr int32_t DISPLAY_BYTE = 2; constexpr int32_t PREFIX_LENGTH = 3; constexpr int32_t FILE_MAX_SIZE = 20 * 1024; +constexpr int32_t HEAD_SIZE = 3; +constexpr int32_t END_SIZE = 3; +constexpr int32_t MIN_SIZE = HEAD_SIZE + END_SIZE + 3; +constexpr const char *REPLACE_CHAIN = "***"; +constexpr const unsigned char MAX_PRINTABLE_BYTE = 0x7F; + constexpr SqliteUtils::SqlType SqliteUtils::SQL_TYPE_MAP[]; constexpr const char *SqliteUtils::ON_CONFLICT_CLAUSE[]; +constexpr const char *SQL_KEYWORD[] = { "ABORT", "ABS", "ACTION", "ADD", "AFTER", "ALIAS", "ALL", "ALTER", "ALWAYS", + "AMBIGUOUS", "ANALYZE", "AND", "AS", "ASC", "ATTACH", "AUTOINCREMENT", "AVG", "BEFORE", "BEGIN", "BETWEEN", "BIG", + "BIGINT", "BLOB", "BOOLEAN", "BY", "CASCADE", "CASE", "CAST", "CEIL", "CEILING", "CHARACTER", "CHECK", "CLOB", + "COALESCE", "COLLATE", "COLUMN", "COMMIT", "CONCAT", "CONFLICT", "CONSTRAINT", "COUNT", "CREATE", "CROSS", + "CURRENT", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DATE", "DATETIME", "DECIMAL", + "DEFAULT", "DEFERRABLE", "DEFERRED", "DELETE", "DESC", "DETACH", "DIGIT", "DISTINCT", "DO", "DOUBLE", "DROP", "E", + "EACH", "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUDE", "EXCLUSIVE", "EXISTS", "EXP", "EXPLAIN", "EXPR", "FAIL", + "FALSE", "FILENAME", "FILTER", "FIRST", "FLOAT", "FLOOR", "FOLLOWING", "FOR", "FOREIGN", "FROM", "FULL", + "GENERATED", "GLOB", "GROUP", "GROUPS", "GROUP_CONCAT", "HAVING", "HEXDIGIT", "IF", "IFNULL", "IGNORE", "IMMEDIATE", + "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", "INSERT", "INSTEAD", "INSTR", "INT", "INT2", "INT8", "INTEGER", + "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "JULIANDAY", "KEY", "LAST", "LEFT", "LENGTH", "LIKE", "LIMIT", "LN", + "LOG", "LOWER", "LTRIM", "MATCH", "MATERIALIZED", "MAX", "MEDIUMINT", "MIN", "NAME", "NATIVE", "NATURAL", "NCHAR", + "NEWLINE", "NO", "NOT", "NOTHING", "NOTNULL", "NULL", "NULLIF", "NULLS", "NUMERIC", "NVARCHAR", "OF", "OFFSET", + "ON", "OR", "ORDER", "OTHERS", "OUTER", "OVER", "PARTITION", "PLAN", "POWER", "PRAGMA", "PRECEDING", "PRECISION", + "PRIMARY", "QUERY", "RAISE", "RANDOM", "RANGE", "REAL", "RECURSIVE", "REFERENCES", "REGEXP", "REINDEX", "RELEASE", + "RENAME", "REPLACE", "RESTRICT", "RETURNING", "RIGHT", "ROLLBACK", "ROUND", "ROW", "ROWID", "ROWS", "RTRIM", + "SAVEPOINT", "SELECT", "SET", "SMALLINT", "SQRT", "STORED", "STRFTIME", "STRICT", "SUBSTR", "SUM", "TABLE", "TEMP", + "TEMPORARY", "TEXT", "THEN", "TIES", "TIME", "TINYINT", "TO", "TOTAL", "TRANSACTION", "TRIGGER", "TRIM", "TRUE", + "TYPEOF", "UNBOUNDED", "UNION", "UNIQUE", "UNSIGNED", "UPDATE", "UPPER", "USING", "VACUUM", "VALUES", "VARCHAR", + "VARYING", "VIEW", "VIRTUAL", "WHEN", "WHERE", "WINDOW", "WITH", "WITHOUT" }; + +constexpr const char *WHILE_KEYWORDS[] = { "ABORTS", "ACQLOCK", "ALREADY", "AT", "BUSYLINE", "CHANGED", "CURLOCK", + "DBREF", "DEL", "DUPLICATE", "ENABLE", "ERRNO", "ERROR", "FAILED", "FD", "FILE", "FILELOCK", "FRAMES", "F_RDLCK", + "F_WRLCK", "GO", "HANDLELOCKS", "HAS", "IDX", "LEN", "LINE", "LITERAL", "LOCKCNT", "LOCKS", "MISUSE", "MONITOR", + "NEAR", "NONE", "PID", "PROCESSLOCK", "QUOTED", "READ", "RECOVERED", "SCHEMA", "SHARED_FIRST", "SQLITE", + "STATEMENT", "STRING", "SUCH", "SYNTAX", "TID", "TRX", "TYPE", "WAL", "WAL_DMS", "WARNING", "WRITE", "WRONG" }; + +constexpr int32_t WordCompare(const char *a, const char *b) +{ + while (*a && *b && (*a == *b)) { + ++a; + ++b; + } + return static_cast(*a) - static_cast(*b); +} + +constexpr bool IsLexSorted(const char *const *keyword, size_t size) +{ + for (size_t i = 1; i < size; ++i) { + if (WordCompare(keyword[i - 1], keyword[i]) >= 0) { + return false; + } + } + return true; +} + +bool IsMatchKeyword(const char *const *keyword, size_t size, const char *str) +{ + auto it = std::lower_bound( + keyword, keyword + size, str, [](const char *a, const char *b) { return WordCompare(a, b) < 0; }); + if (it != keyword + size && WordCompare(*it, str) == 0) { + return true; + } + return false; +} + +// ensure lexicographical order +static_assert(IsLexSorted(SQL_KEYWORD, sizeof(SQL_KEYWORD) / sizeof(char*))); +static_assert(IsLexSorted(WHILE_KEYWORDS, sizeof(WHILE_KEYWORDS) / sizeof(char*))); + int SqliteUtils::GetSqlStatementType(const std::string &sql) { /* the sql string length less than 3 can not be any type sql */ @@ -89,16 +160,18 @@ std::string SqliteUtils::StrToUpper(const std::string &s) return str; } -void SqliteUtils::Replace(std::string &src, const std::string &rep, const std::string &dst) +std::string SqliteUtils::Replace(const std::string &src, const std::string &rep, const std::string &dst) { if (src.empty() || rep.empty()) { - return; + return ""; } + auto res = src; size_t pos = 0; - while ((pos = src.find(rep, pos)) != std::string::npos) { - src.replace(pos, rep.length(), dst); + while ((pos = res.find(rep, pos)) != std::string::npos) { + res.replace(pos, rep.length(), dst); pos += dst.length(); } + return res; } bool SqliteUtils::IsSupportSqlForExecute(int sqlType) @@ -172,53 +245,55 @@ bool SqliteUtils::CopyFile(const std::string &srcFile, const std::string &destFi return true; } +size_t SqliteUtils::DeleteFolder(const std::string &folderPath) +{ +#if !defined(CROSS_PLATFORM) + std::error_code ec; + size_t count = std::filesystem::remove_all(folderPath, ec); + auto errorCount = static_cast(-1); + if (count == errorCount) { + LOG_WARN("remove folder, %{public}d, %{public}s, %{public}s", ec.value(), + ec.message().c_str(), Anonymous(folderPath).c_str()); + count = 0; + } + return count; +#else + return 0; +#endif +} + +bool SqliteUtils::IsKeyword(const std::string &word) +{ + return IsMatchKeyword(SQL_KEYWORD, sizeof(SQL_KEYWORD) / sizeof(char *), StrToUpper(word).c_str()) || + IsMatchKeyword(WHILE_KEYWORDS, sizeof(WHILE_KEYWORDS) / sizeof(char *), StrToUpper(word).c_str()); +} + std::string SqliteUtils::GetAnonymousName(const std::string &fileName) { - std::vector alnum; - std::vector noAlnum; - std::string alnumStr; - std::string noAlnumStr; - for (const auto &letter : fileName) { - if (isxdigit(letter)) { - if (!noAlnumStr.empty()) { - noAlnum.push_back(noAlnumStr); - noAlnumStr.clear(); - alnum.push_back(""); - } - alnumStr += letter; - } else { - if (!alnumStr.empty()) { - alnum.push_back(alnumStr); - alnumStr.clear(); - noAlnum.push_back(""); - } - noAlnumStr += letter; - } - } - if (!alnumStr.empty()) { - alnum.push_back(alnumStr); - noAlnum.push_back(""); + if (fileName.empty()) { + return ""; } - if (!noAlnumStr.empty()) { - noAlnum.push_back(noAlnumStr); - alnum.push_back(""); + + if (fileName.length() <= HEAD_SIZE) { + return fileName.substr(0, 1) + "**"; } - std::string res = ""; - for (size_t i = 0; i < alnum.size(); ++i) { - res += (AnonyDigits(alnum[i]) + noAlnum[i]); + + if (fileName.length() < MIN_SIZE) { + return (fileName.substr(0, HEAD_SIZE) + REPLACE_CHAIN); } - return res; + + return (fileName.substr(0, HEAD_SIZE) + REPLACE_CHAIN + fileName.substr(fileName.length() - END_SIZE, END_SIZE)); } -std::string SqliteUtils::AnonyDigits(const std::string &fileName) +std::string SqliteUtils::AnonymousDigits(const std::string &digits) { - std::string::size_type digitsNum = fileName.size(); + std::string::size_type digitsNum = digits.size(); if (digitsNum < CONTINUOUS_DIGITS_MINI_SIZE) { - return fileName; + return digits; } std::string::size_type endDigitsNum = 4; std::string::size_type shortEndDigitsNum = 3; - std::string name = fileName; + std::string name = digits; std::string last = ""; if (digitsNum == CONTINUOUS_DIGITS_MINI_SIZE) { last = name.substr(name.size() - shortEndDigitsNum); @@ -228,6 +303,53 @@ std::string SqliteUtils::AnonyDigits(const std::string &fileName) return "***" + last; } +std::string ByteAnonymous(const std::string &input) +{ + std::string output; + bool maskCurrent = false; + for (unsigned char byte : input) { + if (byte > MAX_PRINTABLE_BYTE) { + if (!maskCurrent) { + output += "***"; + maskCurrent = true; + } + } else { + output.push_back(static_cast(byte)); + maskCurrent = false; + } + } + return output; +} + +std::string SqliteUtils::SqlAnonymous(const std::string &sql) +{ + std::ostringstream result; + std::regex idRegex(R"(\b[a-zA-Z0-9_]+\b)"); + auto begin = std::sregex_iterator(sql.begin(), sql.end(), idRegex); + auto end = std::sregex_iterator(); + + size_t lastPos = 0; + for (auto it = begin; it != end; ++it) { + std::smatch match = *it; + std::string word = match.str(); + size_t pos = static_cast(match.position()); + + result << ByteAnonymous(sql.substr(lastPos, pos - lastPos)); + + lastPos = pos + word.length(); + if (std::regex_match(word, std::regex(R"(\b[0-9a-fA-F]+\b)"))) { + result << AnonymousDigits(word); + } else if (IsKeyword(word)) { + result << std::move(word); + } else { + result << GetAnonymousName(word); + } + } + + result << ByteAnonymous(sql.substr(lastPos)); + return result.str(); +} + std::string SqliteUtils::Anonymous(const std::string &srcFile) { auto pre = srcFile.find("/"); @@ -244,9 +366,22 @@ std::string SqliteUtils::Anonymous(const std::string &srcFile) } else { path = path.substr(area, AREA_MINI_SIZE); } - std::string fileName = srcFile.substr(end); // rdb file name + std::string fileName = srcFile.substr(end + 1); // rdb file name fileName = GetAnonymousName(fileName); - return srcFile.substr(0, pre + PRE_OFFSET_SIZE) + "***" + path + fileName; + return srcFile.substr(0, pre + PRE_OFFSET_SIZE) + "***" + path + "/" + fileName; +} + +std::string SqliteUtils::GetArea(const std::string &srcFile) +{ + size_t start = srcFile.find("/el"); + if (start == std::string::npos) { + return ""; + } + size_t end = srcFile.find("/", start + 1); + if (end != std::string::npos) { + return srcFile.substr(start + 1, end - start - 1); + } + return ""; } ssize_t SqliteUtils::GetFileSize(const std::string &fileName) @@ -361,6 +496,77 @@ bool SqliteUtils::IsSlaveInterrupted(const std::string &dbPath) return access((dbPath + SLAVE_INTERRUPT).c_str(), F_OK) == 0; } +int SqliteUtils::GetPageCountCallback(void *data, int argc, char **argv, char **azColName) +{ + int64_t *count = (int64_t *)data; + if (argc > 0 && argv[0] != NULL) { + char *endptr = nullptr; + *count = static_cast(strtoll(argv[0], &endptr, 10)); // 10 means decimal + } + return 0; +} + +ssize_t SqliteUtils::GetDecompressedSize(const std::string &dbPath) +{ + sqlite3 *dbHandle = nullptr; + int errCode = sqlite3_open_v2(dbPath.c_str(), &dbHandle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX, nullptr); + if (errCode != SQLITE_OK) { + LOG_WARN("failed to open %{public}s to calculate size", Anonymous(dbPath).c_str()); + sqlite3_close_v2(dbHandle); + return 0; + } + int64_t pageCount = 0; + errCode = sqlite3_exec(dbHandle, "SELECT COUNT(1) FROM vfs_pages;", GetPageCountCallback, &pageCount, nullptr); + sqlite3_close_v2(dbHandle); + if (errCode != SQLITE_OK) { + LOG_WARN("failed to get page count, %{public}s", Anonymous(dbPath).c_str()); + return 0; + } + auto size = pageCount * 4096; + if (size > SSIZE_MAX) { + LOG_WARN("actual size overflow:%{public}" PRId64, size); + return SSIZE_MAX; + } + return (ssize_t)size; +} + +bool SqliteUtils::IsSlaveLarge(const std::string &dbPath) +{ + auto slavePath = GetSlavePath(dbPath); + if (sqlite3_is_support_binlog(StringUtils::ExtractFileName(dbPath).c_str()) == SQLITE_OK) { + auto size = GetDecompressedSize(slavePath); + if (size > 0) { + return size > SLAVE_ASYNC_REPAIR_CHECK_LIMIT; + } + } + std::pair fileInfo = Stat(slavePath); + if (fileInfo.first == E_OK) { + return fileInfo.second.size_ > SLAVE_ASYNC_REPAIR_CHECK_LIMIT; + } + return false; +} + +int SqliteUtils::SetSlaveRestoring(const std::string &dbPath, bool isRestore) +{ + if (IsSlaveRestoring(dbPath)) { + if (!isRestore) { + std::remove((dbPath + SLAVE_RESTORE).c_str()); + } + return E_OK; + } + std::ofstream src((dbPath + SLAVE_RESTORE).c_str(), std::ios::binary); + if (src.is_open()) { + src.close(); + return E_OK; + } + return E_ERROR; +} + +bool SqliteUtils::IsSlaveRestoring(const std::string &dbPath) +{ + return access((dbPath + SLAVE_RESTORE).c_str(), F_OK) == 0; +} + void SqliteUtils::SetSlaveValid(const std::string &dbPath) { std::remove((dbPath + SLAVE_INTERRUPT).c_str()); @@ -419,13 +625,12 @@ std::string SqliteUtils::ReadFileHeader(const std::string &filePath) std::string SqliteUtils::GetFileStatInfo(const DebugInfo &debugInfo) { std::stringstream oss; - const uint32_t permission = 0777; oss << " dev:0x" << std::hex << debugInfo.dev_ << " ino:0x" << std::hex << debugInfo.inode_; if (debugInfo.inode_ != debugInfo.oldInode_ && debugInfo.oldInode_ != 0) { oss << "<>0x" << std::hex << debugInfo.oldInode_; } - oss << " mode:0" << std::oct << (debugInfo.mode_ & permission) << " size:" << std::dec << debugInfo.size_ - << " uid:" << std::dec << debugInfo.uid_ << " gid:" << std::dec << debugInfo.gid_ + oss << " " << GetModeInfo(debugInfo.mode_) << " size:" << std::dec << debugInfo.size_ << " uid:" << std::dec + << debugInfo.uid_ << " gid:" << std::dec << debugInfo.gid_ << " atim:" << RdbTimeUtils::GetTimeWithMs(debugInfo.atime_.sec_, debugInfo.atime_.nsec_) << " mtim:" << RdbTimeUtils::GetTimeWithMs(debugInfo.mtime_.sec_, debugInfo.mtime_.nsec_) << " ctim:" << RdbTimeUtils::GetTimeWithMs(debugInfo.ctime_.sec_, debugInfo.ctime_.nsec_); @@ -573,7 +778,8 @@ std::string SqliteUtils::FormatDebugInfoBrief(const std::map"; + oss << "<" << name << ",0x" << std::hex << debugInfo.inode_ << "," << std::dec << debugInfo.size_ << "," + << std::oct << debugInfo.mode_ << ">"; } return oss.str(); } @@ -583,5 +789,46 @@ std::string SqliteUtils::FormatDfxInfo(const DfxInfo &dfxInfo) oss << "LastOpen:" << dfxInfo.lastOpenTime_ << "," << "CUR_USER:" << dfxInfo.curUserId_; return oss.str(); } + +std::string SqliteUtils::GetModeInfo(uint32_t st_mode) +{ + std::ostringstream oss; + const uint32_t permission = 0777; + oss << "mode:"; + if (S_ISDIR(st_mode)) + oss << 'd'; + else + oss << '-'; + + oss << std::setw(PREFIX_LENGTH) << std::setfill('0') << std::oct << (st_mode & permission); + + return oss.str(); +} + +std::string SqliteUtils::GetParentModes(const std::string &path, int pathDepth) +{ + std::vector> dirModes; + std::string currentPath = path; + + for (int i = 0; i < pathDepth; ++i) { + currentPath = StringUtils::GetParentPath(currentPath); + if (currentPath == "/" || currentPath.empty()) { + break; + } + + std::string dirName = StringUtils::ExtractFileName(currentPath); + struct stat st {}; + dirModes.emplace_back(dirName, (stat(currentPath.c_str(), &st) == 0) ? GetModeInfo(st.st_mode) : "access_fail"); + } + std::string result; + for (auto it = dirModes.rbegin(); it != dirModes.rend(); ++it) { + if (!result.empty()) { + result += " <- "; + } + result += (it->first.size() > PREFIX_LENGTH ? it->first.substr(0, PREFIX_LENGTH) + "***" : it->first) + ":" + + it->second; + } + return result.empty() ? "no_parent" : result; +} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/step_result_set.cpp b/relational_store/frameworks/native/rdb/src/step_result_set.cpp index 32161b4325accf0239f2a96ca93de24cc48825b2..520d6a2052a9c3f9d37145efc66547678ccb740e 100644 --- a/relational_store/frameworks/native/rdb/src/step_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/step_result_set.cpp @@ -67,7 +67,7 @@ StepResultSet::StepResultSet(Time start, Conn conn, const std::string &sql, cons int64_t countCost = std::chrono::duration_cast(queryEnd - prepareEnd).count(); LOG_WARN("total[%{public}" PRId64 "]<%{public}" PRId64 ",%{public}" PRId64 ",%{public}" PRId64 "> count[%{public}d] sql[%{public}s]", - totalCost, acquireCost, prepareCost, countCost, rowCount_, SqliteUtils::Anonymous(sql_).c_str()); + totalCost, acquireCost, prepareCost, countCost, rowCount_, SqliteUtils::SqlAnonymous(sql_).c_str()); } } @@ -93,7 +93,7 @@ int StepResultSet::PrepareStep() auto type = SqliteUtils::GetSqlStatementType(sql_); if (type == SqliteUtils::STATEMENT_ERROR) { - LOG_ERROR("invalid sql_ %{public}s!", SqliteUtils::Anonymous(sql_).c_str()); + LOG_ERROR("invalid sql_ %{public}s!", SqliteUtils::SqlAnonymous(sql_).c_str()); lastErr_ = E_INVALID_ARGS; return lastErr_; } @@ -101,11 +101,12 @@ int StepResultSet::PrepareStep() auto [errCode, statement] = conn_->CreateStatement(sql_, conn_); if (statement == nullptr || errCode != E_OK) { lastErr_ = errCode; + LOG_ERROR("CreateStatement failed. sql_ %{public}s!", SqliteUtils::SqlAnonymous(sql_).c_str()); return E_STATEMENT_NOT_PREPARED; } if (!statement->ReadOnly()) { - LOG_ERROR("failed, %{public}s is not query sql!", SqliteUtils::Anonymous(sql_).c_str()); + LOG_ERROR("failed, %{public}s is not query sql!", SqliteUtils::SqlAnonymous(sql_).c_str()); lastErr_ = E_NOT_SELECT; return lastErr_; } diff --git a/relational_store/frameworks/native/rdb/src/string_utils.cpp b/relational_store/frameworks/native/rdb/src/string_utils.cpp index 27ebb6609e62202cd773a4645c2e44a5122d74c1..7e527910ffb697f11993ee5dc332d0ef9dac9191 100644 --- a/relational_store/frameworks/native/rdb/src/string_utils.cpp +++ b/relational_store/frameworks/native/rdb/src/string_utils.cpp @@ -70,13 +70,29 @@ std::string StringUtils::ExtractFileName(const std::string &fileFullName) return std::string(fileFullName).substr(fileFullName.rfind("/") + 1, fileFullName.size()); } -std::string StringUtils::TruncateAfterFirstParen(const std::string& str) +std::string StringUtils::TruncateAfterFirstParen(const std::string &str) { size_t pos = str.find('('); return (pos != std::string::npos) ? str.substr(0, pos) : str; } -StringUtils::StringUtils() {} -StringUtils::~StringUtils() {} +std::string StringUtils::GetParentPath(const std::string &path) +{ + size_t pos = path.find_last_of("/\\"); + if (pos == std::string::npos) { + return ""; + } + if (pos == 0) { + return "/"; + } + return path.substr(0, pos); +} + +StringUtils::StringUtils() +{ +} +StringUtils::~StringUtils() +{ +} } // namespace NativeRdb } // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/src/entry_point.cpp b/relational_store/frameworks/native/rdb/src/suspender.cpp similarity index 37% rename from relational_store/frameworks/js/napi/graphstore/src/entry_point.cpp rename to relational_store/frameworks/native/rdb/src/suspender.cpp index 18d4d98ea3f92c0d833255fd9f9e6d7250a15c0a..cfc9ae59f4c4e337e39afc0207ea17c7b7f9bebb 100644 --- a/relational_store/frameworks/js/napi/graphstore/src/entry_point.cpp +++ b/relational_store/frameworks/native/rdb/src/suspender.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2024 Huawei Device Co., Ltd. +* Copyright (c) 2025 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 @@ -12,43 +12,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "napi/native_api.h" -#include "napi_gdb_const_properties.h" -#include "napi_gdb_store.h" -#include "napi_gdb_store_helper.h" -#include "napi_gdb_transaction.h" -using namespace OHOS::GraphStoreJsKit; +#define LOG_TAG "Suspender" +#include "suspender.h" +#include "rdb_sql_log.h" +#include "rdb_perfStat.h" -EXTERN_C_START -/* - * function for module exports - */ -static napi_value Init(napi_env env, napi_value exports) +namespace OHOS::NativeRdb { +Suspender::Suspender(Flag flag) : flag_(flag) { - InitGdbHelper(env, exports); - GdbStoreProxy::Init(env, exports); - GdbTransactionProxy::Init(env, exports); - InitConstProperties(env, exports); - return exports; + if ((flag_ & SQL_STATISTIC) != 0) { + DistributedRdb::PerfStat::Pause(); + } + if ((flag_ & SQL_LOG) != 0) { + SqlLog::Pause(); + } } -EXTERN_C_END - -/* - * Module define - */ -static napi_module _module = { .nm_version = 1, - .nm_flags = 0, - .nm_filename = nullptr, - .nm_register_func = Init, - .nm_modname = "data.graphStore", - .nm_priv = ((void *)0), - .reserved = { 0 } }; - -/* - * Module register function - */ -static __attribute__((constructor)) void RegisterModule(void) +Suspender::~Suspender() { - napi_module_register(&_module); -} \ No newline at end of file + if ((flag_ & SQL_STATISTIC) != 0) { + DistributedRdb::PerfStat::Resume(); + } + if ((flag_ & SQL_LOG) != 0) { + SqlLog::Resume(); + } +} +} // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/task_executor.cpp b/relational_store/frameworks/native/rdb/src/task_executor.cpp index 888169cf121a4a6124dde62eef7aa776717cca38..102406ef151a177afa77eb3ee076bc322c961e45 100644 --- a/relational_store/frameworks/native/rdb/src/task_executor.cpp +++ b/relational_store/frameworks/native/rdb/src/task_executor.cpp @@ -13,12 +13,15 @@ * limitations under the License. */ +#define LOG_TAG "TaskExecutor" #include "task_executor.h" +#include "logger.h" + namespace OHOS::NativeRdb { +using namespace OHOS::Rdb; TaskExecutor::TaskExecutor() { - pool_ = std::make_shared(MAX_THREADS, MIN_THREADS); } TaskExecutor::~TaskExecutor() @@ -32,16 +35,39 @@ TaskExecutor &TaskExecutor::GetInstance() return instance; } +void TaskExecutor::Init() +{ + std::unique_lock lock(mutex_); + if (pool_ != nullptr) { + return; + } + pool_ = std::make_shared(MAX_THREADS, MIN_THREADS, "TaskExecutorRDB"); +}; + std::shared_ptr TaskExecutor::GetExecutor() { - std::shared_lock lock(rwMutex_); + std::unique_lock lock(mutex_); + if (pool_ == nullptr) { + pool_ = std::make_shared(MAX_THREADS, MIN_THREADS, "TaskExecutorRDB"); + } return pool_; } void TaskExecutor::SetExecutor(std::shared_ptr executor) { - std::unique_lock lock(rwMutex_); + std::unique_lock lock(mutex_); pool_ = executor; -}; +} + +bool TaskExecutor::Stop() +{ + std::unique_lock lock(mutex_); + if (pool_ != nullptr && pool_.use_count() > 1) { + LOG_WARN("There are other threads using the thread pool. count:%{public}ld", pool_.use_count()); + return false; + } + pool_ = nullptr; + return true; +} } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/trans_db.cpp b/relational_store/frameworks/native/rdb/src/trans_db.cpp index b7cb37a8cf17b86ad933fa41a3c9c3d756325b4b..7751d319df51f86b72172d98b225f5b14505b47a 100644 --- a/relational_store/frameworks/native/rdb/src/trans_db.cpp +++ b/relational_store/frameworks/native/rdb/src/trans_db.cpp @@ -15,6 +15,7 @@ #define LOG_TAG "TransDB" #include "trans_db.h" +#include "cache_result_set.h" #include "logger.h" #include "rdb_sql_statistic.h" #include "rdb_trace.h" @@ -27,7 +28,7 @@ namespace OHOS::NativeRdb { using namespace OHOS::Rdb; using namespace DistributedRdb; -TransDB::TransDB(std::shared_ptr conn, const std::string &name) : conn_(conn), name_(name) +TransDB::TransDB(std::shared_ptr conn, const std::string &path) : conn_(conn), path_(path) { maxArgs_ = conn->GetMaxVariable(); } @@ -82,7 +83,8 @@ std::pair TransDB::BatchInsert(const std::string &table, const Ref auto batchInfo = SqliteSqlBuilder::GenerateSqls(table, rows, maxArgs_); if (table.empty() || batchInfo.empty()) { - LOG_ERROR("empty,table=%{public}s,rows:%{public}zu,max:%{public}d.", table.c_str(), rows.RowSize(), maxArgs_); + LOG_ERROR("empty,table=%{public}s,rows:%{public}zu,max:%{public}d.", SqliteUtils::Anonymous(table).c_str(), + rows.RowSize(), maxArgs_); return { E_INVALID_ARGS, -1 }; } @@ -97,15 +99,15 @@ std::pair TransDB::BatchInsert(const std::string &table, const Ref continue; } LOG_ERROR("failed(0x%{public}x) db:%{public}s table:%{public}s args:%{public}zu", errCode, - SqliteUtils::Anonymous(name_).c_str(), table.c_str(), args.size()); + SqliteUtils::Anonymous(path_).c_str(), SqliteUtils::Anonymous(table).c_str(), args.size()); return { errCode, -1 }; } } return { E_OK, int64_t(rows.RowSize()) }; } -std::pair TransDB::BatchInsertWithConflictResolution( - const std::string &table, const ValuesBuckets &rows, Resolution resolution) +std::pair TransDB::BatchInsert(const std::string &table, const ValuesBuckets &rows, + const std::vector &returningFields, Resolution resolution) { if (rows.RowSize() == 0) { return { E_OK, 0 }; @@ -115,31 +117,32 @@ std::pair TransDB::BatchInsertWithConflictResolution( if (sqlArgs.size() != 1 || sqlArgs.front().second.size() != 1) { auto [fields, values] = rows.GetFieldsAndValues(); LOG_ERROR("invalid args, table=%{public}s, rows:%{public}zu, fields:%{public}zu, max:%{public}d.", - table.c_str(), rows.RowSize(), fields != nullptr ? fields->size() : 0, maxArgs_); + SqliteUtils::Anonymous(table).c_str(), rows.RowSize(), fields != nullptr ? fields->size() : 0, maxArgs_); return { E_INVALID_ARGS, -1 }; } auto &[sql, bindArgs] = sqlArgs.front(); + SqliteSqlBuilder::AppendReturning(sql, returningFields); auto [errCode, statement] = GetStatement(sql); if (statement == nullptr) { LOG_ERROR("statement is nullptr, errCode:0x%{public}x, args:%{public}zu, table:%{public}s.", errCode, - bindArgs.size(), table.c_str()); + bindArgs.size(), SqliteUtils::Anonymous(table).c_str()); return { errCode, -1 }; } auto args = std::ref(bindArgs.front()); errCode = statement->Execute(args); if (errCode != E_OK) { LOG_ERROR("failed,errCode:%{public}d,table:%{public}s,args:%{public}zu,resolution:%{public}d.", errCode, - table.c_str(), args.get().size(), static_cast(resolution)); - return { errCode, errCode == E_SQLITE_CONSTRAINT ? int64_t(statement->Changes()) : -1 }; + SqliteUtils::Anonymous(table).c_str(), args.get().size(), static_cast(resolution)); } - return { E_OK, int64_t(statement->Changes()) }; + return { errCode, GenerateResult(errCode, statement) }; } -std::pair TransDB::Update( - const std::string &table, const Row &row, const std::string &where, const Values &args, Resolution resolution) +std::pair TransDB::Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); auto clause = SqliteUtils::GetConflictClause(static_cast(resolution)); + auto table = predicates.GetTableName(); if (table.empty() || row.IsEmpty() || clause == nullptr) { return { E_INVALID_ARGS, 0 }; } @@ -147,6 +150,7 @@ std::pair TransDB::Update( std::string sql("UPDATE"); sql.append(clause).append(" ").append(table).append(" SET "); std::vector totalArgs; + auto args = predicates.GetBindArgs(); totalArgs.reserve(row.values_.size() + args.size()); const char *split = ""; for (auto &[key, val] : row.values_) { @@ -161,53 +165,58 @@ std::pair TransDB::Update( totalArgs.push_back(val); split = ","; } - + auto where = predicates.GetWhereClause(); if (!where.empty()) { sql.append(" WHERE ").append(where); } - + SqliteSqlBuilder::AppendReturning(sql, returningFields); totalArgs.insert(totalArgs.end(), args.begin(), args.end()); auto [errCode, statement] = GetStatement(sql); - if (statement == nullptr) { - return { errCode, 0 }; + if (errCode != E_OK || statement == nullptr) { + return { errCode != E_OK ? errCode : E_ERROR, -1 }; } errCode = statement->Execute(totalArgs); if (errCode != E_OK) { - return { errCode, 0 }; + LOG_ERROR("failed,errCode:%{public}d,table:%{public}s,returningFields:%{public}zu,resolution:%{public}d.", + errCode, SqliteUtils::Anonymous(table).c_str(), returningFields.size(), static_cast(resolution)); } - return { errCode, int32_t(statement->Changes()) }; + return { errCode, GenerateResult(errCode, statement) }; } -int TransDB::Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) +std::pair TransDB::Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + auto table = predicates.GetTableName(); if (table.empty()) { - return E_INVALID_ARGS; + return { E_INVALID_ARGS, -1 }; } std::string sql; sql.append("DELETE FROM ").append(table); + auto whereClause = predicates.GetWhereClause(); if (!whereClause.empty()) { sql.append(" WHERE ").append(whereClause); } + SqliteSqlBuilder::AppendReturning(sql, returningFields); auto [errCode, statement] = GetStatement(sql); - if (statement == nullptr) { - return errCode; + if (errCode != E_OK || statement == nullptr) { + return { errCode != E_OK ? errCode : E_ERROR, -1 }; } - errCode = statement->Execute(args); + errCode = statement->Execute(predicates.GetBindArgs()); if (errCode != E_OK) { - return errCode; + LOG_ERROR("failed,errCode:%{public}d,table:%{public}s,returningFields:%{public}zu.", errCode, + SqliteUtils::Anonymous(table).c_str(), returningFields.size()); } - deletedRows = statement->Changes(); - return E_OK; + return { errCode, GenerateResult(errCode, statement) }; } std::shared_ptr TransDB::QuerySql(const std::string &sql, const Values &args) { #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) auto start = std::chrono::steady_clock::now(); - return std::make_shared(start, conn_.lock(), sql, args, name_); + return std::make_shared(start, conn_.lock(), sql, args, path_); #else (void)sql; (void)args; @@ -227,7 +236,7 @@ std::pair TransDB::Execute(const std::string &sql, const V ValueObject object; int sqlType = SqliteUtils::GetSqlStatementType(sql); if (!SqliteUtils::IsSupportSqlForExecute(sqlType) && !SqliteUtils::IsSpecial(sqlType)) { - LOG_ERROR("Not support the sql:app self can check the SQL"); + LOG_ERROR("Not support the sql:app self can check the SQL, sqlType:%{public}d", sqlType); return { E_INVALID_ARGS, object }; } @@ -259,19 +268,53 @@ std::pair TransDB::Execute(const std::string &sql, const V } if (sqlType == SqliteUtils::STATEMENT_DDL) { - statement->Reset(); - statement->Prepare("PRAGMA schema_version"); - auto [err, version] = statement->ExecuteForValue(); - if (vSchema_ < static_cast(version)) { - LOG_INFO("db:%{public}s exe DDL schema<%{public}" PRIi64 "->%{public}" PRIi64 - "> app self can check the SQL.", - SqliteUtils::Anonymous(name_).c_str(), vSchema_, static_cast(version)); - vSchema_ = version; - } + HandleSchemaDDL(statement); } return { errCode, object }; } +std::pair TransDB::ExecuteExt(const std::string &sql, const Values &args) +{ + ValueObject object; + int sqlType = SqliteUtils::GetSqlStatementType(sql); + if (!SqliteUtils::IsSupportSqlForExecute(sqlType) && !SqliteUtils::IsSpecial(sqlType)) { + LOG_ERROR("Not support the sql:app self can check the SQL"); + return { E_INVALID_ARGS, -1 }; + } + auto [errCode, statement] = GetStatement(sql); + if (errCode != E_OK || statement == nullptr) { + return { errCode != E_OK ? errCode : E_ERROR, -1 }; + } + + errCode = statement->Execute(args); + auto result = GenerateResult( + errCode, statement, sqlType == SqliteUtils::STATEMENT_INSERT || sqlType == SqliteUtils::STATEMENT_UPDATE); + if (errCode != E_OK) { + LOG_ERROR("failed,app self can check the SQL, error:0x%{public}x.", errCode); + return { errCode, result }; + } + + if (sqlType == SqliteUtils::STATEMENT_DDL) { + HandleSchemaDDL(statement); + } + return { errCode, result }; +} + +void TransDB::HandleSchemaDDL(std::shared_ptr statement) +{ + if (statement == nullptr) { + return; + } + statement->Reset(); + statement->Prepare("PRAGMA schema_version"); + auto [err, version] = statement->ExecuteForValue(); + if (vSchema_ < static_cast(version)) { + LOG_INFO("db:%{public}s exe DDL schema<%{public}" PRIi64 "->%{public}" PRIi64 ">", + SqliteUtils::Anonymous(path_).c_str(), vSchema_, static_cast(version)); + vSchema_ = version; + } +} + int TransDB::GetVersion(int &version) { return E_NOT_SUPPORT; @@ -298,4 +341,40 @@ std::pair> TransDB::GetStatement(const std:: } return connection->CreateStatement(sql, connection); } + +Results TransDB::GenerateResult(int32_t code, std::shared_ptr statement, bool isDML) +{ + Results result{ -1 }; + if (statement == nullptr) { + return result; + } + // There are no data changes in other scenarios + if (code == E_OK) { + result.results = GetValues(statement); + result.changed = isDML ? statement->Changes() : 0; + } + if (code == E_SQLITE_CONSTRAINT) { + result.changed = statement->Changes(); + } + if (isDML && result.changed <= 0) { + result.results = std::make_shared(); + } + return result; +} + +std::shared_ptr TransDB::GetValues(std::shared_ptr statement) +{ + if (statement == nullptr) { + return nullptr; + } + auto [code, rows] = statement->GetRows(MAX_RETURNING_ROWS); + auto size = rows.size(); + std::shared_ptr result = std::make_shared(std::move(rows)); + // The correct number of changed rows can only be obtained after completing the step + while (code == E_OK && size == MAX_RETURNING_ROWS) { + std::tie(code, rows) = statement->GetRows(MAX_RETURNING_ROWS); + size = rows.size(); + } + return result; +} } // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/transaction.cpp b/relational_store/frameworks/native/rdb/src/transaction.cpp index 420049c3580da5cb316ee3ab33f6a7e6b56c6879..0b44cdc2b123de054fe51714ee46d8012914e9f3 100644 --- a/relational_store/frameworks/native/rdb/src/transaction.cpp +++ b/relational_store/frameworks/native/rdb/src/transaction.cpp @@ -16,10 +16,10 @@ namespace OHOS::NativeRdb { std::pair> Transaction::Create( - int32_t type, std::shared_ptr connection, const std::string &name) + int32_t type, std::shared_ptr connection, const std::string &path) { if (creator_ != nullptr) { - return creator_(type, std::move(connection), name); + return creator_(type, std::move(connection), path); } return { E_ERROR, nullptr }; } @@ -29,4 +29,70 @@ int32_t Transaction::RegisterCreator(Creator creator) creator_ = std::move(creator); return E_OK; } + +std::pair Transaction::BatchInsert( + const std::string &table, const RefRows &rows, Resolution resolution) +{ + auto [code, result] = BatchInsert(table, rows, {}, resolution); + return { code, result.changed }; +} + +std::pair Transaction::BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution) +{ + return { E_NOT_SUPPORT, -1 }; +} + +std::pair Transaction::Update( + const std::string &table, const Row &row, const std::string &where, const Values &args, Resolution resolution) +{ + AbsRdbPredicates predicates(table); + predicates.SetWhereClause(where); + predicates.SetBindArgs(args); + return Update(row, predicates, resolution); +} + +std::pair Transaction::Update( + const Row &row, const AbsRdbPredicates &predicates, Resolution resolution) +{ + auto [code, result] = Update(row, predicates, {}, resolution); + return { code, result.changed }; +} + +std::pair Transaction::Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) +{ + return { E_NOT_SUPPORT, -1 }; +} + +std::pair Transaction::Delete( + const std::string &table, const std::string &whereClause, const Values &args) +{ + AbsRdbPredicates predicates(table); + predicates.SetWhereClause(whereClause); + predicates.SetBindArgs(args); + return Delete(predicates); +} + +std::pair Transaction::Delete(const AbsRdbPredicates &predicates) +{ + auto [code, result] = Delete(predicates, {}); + return { code, result.changed }; +} + +std::pair Transaction::Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) +{ + return { E_NOT_SUPPORT, -1 }; +} + +std::pair Transaction::Execute(const std::string &sql, const Values &args) +{ + return { E_NOT_SUPPORT, -1 }; +} + +std::pair Transaction::ExecuteExt(const std::string &sql, const Values &args) +{ + return { E_NOT_SUPPORT, -1 }; +} } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/transaction_impl.cpp b/relational_store/frameworks/native/rdb/src/transaction_impl.cpp index b9b7adc148c4c667821afdbc9697c429191efba4..b2dfbde3b2e2042ccca813f5c0f4450197f0b7fb 100644 --- a/relational_store/frameworks/native/rdb/src/transaction_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/transaction_impl.cpp @@ -21,16 +21,19 @@ #include "rdb_errno.h" #include "rdb_store.h" #include "trans_db.h" +#include "rdb_perfStat.h" using namespace OHOS::Rdb; namespace OHOS::NativeRdb { - +using PerfStat = DistributedRdb::PerfStat; __attribute__((used)) const int32_t TransactionImpl::regCreator_ = Transaction::RegisterCreator(TransactionImpl::Create); -TransactionImpl::TransactionImpl(std::shared_ptr connection, const std::string &name) - : name_(name), connection_(std::move(connection)) +TransactionImpl::TransactionImpl(std::shared_ptr connection, const std::string &path) + : path_(path), connection_(std::move(connection)) { + seqId_ = PerfStat::GenerateId(); + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS_START, seqId_); } TransactionImpl::~TransactionImpl() @@ -38,6 +41,7 @@ TransactionImpl::~TransactionImpl() // If the user does not commit the transaction, the next time using this connection to create the transaction will // fail. Here, we attempt to roll back during the transaction object decomposition to prevent this situation // from happening. + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS_END, seqId_); if (connection_ == nullptr) { return; } @@ -45,9 +49,9 @@ TransactionImpl::~TransactionImpl() } std::pair> TransactionImpl::Create( - int32_t type, std::shared_ptr connection, const std::string &name) + int32_t type, std::shared_ptr connection, const std::string &path) { - auto trans = std::make_shared(std::move(connection), name); + auto trans = std::make_shared(std::move(connection), path); if (trans == nullptr) { return { E_ERROR, nullptr }; } @@ -71,7 +75,7 @@ std::string TransactionImpl::GetBeginSql(int32_t type) int32_t TransactionImpl::Begin(int32_t type) { std::lock_guard lock(mutex_); - store_ = std::make_shared(connection_, name_); + store_ = std::make_shared(connection_, path_); if (store_ == nullptr) { return E_ERROR; } @@ -98,6 +102,7 @@ int32_t TransactionImpl::Begin(int32_t type) int32_t TransactionImpl::Commit() { std::lock_guard lock(mutex_); + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS_END, seqId_); if (connection_ == nullptr) { LOG_ERROR("connection already closed"); return E_ALREADY_CLOSED; @@ -112,8 +117,8 @@ int32_t TransactionImpl::Commit() errorCode = statement->Execute(); if (errorCode != E_OK) { - CloseInner(false); LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode); + CloseInner(false); return errorCode; } CloseInner(); @@ -123,6 +128,7 @@ int32_t TransactionImpl::Commit() int32_t TransactionImpl::Rollback() { std::lock_guard lock(mutex_); + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS_END, seqId_); if (connection_ == nullptr) { LOG_ERROR("connection already closed"); return E_ALREADY_CLOSED; @@ -137,8 +143,8 @@ int32_t TransactionImpl::Rollback() errorCode = statement->Execute(); if (errorCode != E_OK) { - CloseInner(false); LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode); + CloseInner(false); return errorCode; } CloseInner(); @@ -175,6 +181,7 @@ std::shared_ptr TransactionImpl::GetStore() std::pair TransactionImpl::Insert(const std::string &table, const Row &row, Resolution resolution) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); @@ -185,6 +192,7 @@ std::pair TransactionImpl::Insert(const std::string &table, const std::pair TransactionImpl::BatchInsert(const std::string &table, const Rows &rows) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_, rows.size()); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); @@ -197,6 +205,7 @@ std::pair TransactionImpl::BatchInsert(const std::string &tabl std::pair TransactionImpl::BatchInsert(const std::string &table, const RefRows &rows) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_, rows.RowSize()); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); @@ -205,63 +214,40 @@ std::pair TransactionImpl::BatchInsert(const std::string &table, c return store->BatchInsert(table, rows); } -std::pair TransactionImpl::BatchInsertWithConflictResolution( - const std::string &table, const RefRows &rows, Resolution resolution) +std::pair TransactionImpl::BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_, rows.RowSize()); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); return { E_ALREADY_CLOSED, -1 }; } - return store->BatchInsertWithConflictResolution(table, rows, resolution); + return store->BatchInsert(table, rows, returningFields, resolution); } -std::pair TransactionImpl::Update( - const std::string &table, const Row &row, const std::string &where, const Values &args, Resolution resolution) +std::pair TransactionImpl::Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); return { E_ALREADY_CLOSED, -1 }; } - return store->Update(table, row, where, args, resolution); + return store->Update(row, predicates, returningFields, resolution); } -std::pair TransactionImpl::Update( - const Row &row, const AbsRdbPredicates &predicates, Resolution resolution) +std::pair TransactionImpl::Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); return { E_ALREADY_CLOSED, -1 }; } - return store->Update( - predicates.GetTableName(), row, predicates.GetWhereClause(), predicates.GetBindArgs(), resolution); -} - -std::pair TransactionImpl::Delete( - const std::string &table, const std::string &whereClause, const Values &args) -{ - auto store = GetStore(); - if (store == nullptr) { - LOG_ERROR("transaction already close"); - return { E_ALREADY_CLOSED, -1 }; - } - int deletedRows{}; - auto errorCode = store->Delete(deletedRows, table, whereClause, args); - return { errorCode, deletedRows }; -} - -std::pair TransactionImpl::Delete(const AbsRdbPredicates &predicates) -{ - auto store = GetStore(); - if (store == nullptr) { - LOG_ERROR("transaction already close"); - return { E_ALREADY_CLOSED, -1 }; - } - int deletedRows{}; - auto errorCode = store->Delete(deletedRows, predicates); - return { errorCode, deletedRows }; + return store->Delete(predicates, returningFields); } void TransactionImpl::AddResultSet(std::weak_ptr resultSet) @@ -272,6 +258,7 @@ void TransactionImpl::AddResultSet(std::weak_ptr resultSet) std::shared_ptr TransactionImpl::QueryByStep(const std::string &sql, const Values &args, bool preCount) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); @@ -287,6 +274,7 @@ std::shared_ptr TransactionImpl::QueryByStep(const std::string &sql, std::shared_ptr TransactionImpl::QueryByStep( const AbsRdbPredicates &predicates, const Fields &columns, bool preCount) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); @@ -301,6 +289,7 @@ std::shared_ptr TransactionImpl::QueryByStep( std::pair TransactionImpl::Execute(const std::string &sql, const Values &args) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); @@ -308,4 +297,14 @@ std::pair TransactionImpl::Execute(const std::string &sql, } return store->Execute(sql, args); } + +std::pair TransactionImpl::ExecuteExt(const std::string &sql, const Values &args) +{ + auto store = GetStore(); + if (store == nullptr) { + LOG_ERROR("transaction already close"); + return { E_ALREADY_CLOSED, -1 }; + } + return store->ExecuteExt(sql, args); +} } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/values_bucket.cpp b/relational_store/frameworks/native/rdb/src/values_bucket.cpp index ae2f7d4b6019252b3f8d71c7610bb2b942b30d0c..41d68696447a200a428297e22412414f79d19afc 100644 --- a/relational_store/frameworks/native/rdb/src/values_bucket.cpp +++ b/relational_store/frameworks/native/rdb/src/values_bucket.cpp @@ -91,6 +91,11 @@ void ValuesBucket::Put(const std::string &columnName, const ValueObject &value) values_.insert_or_assign(columnName, value); } +void ValuesBucket::Put(const std::string &columnName, ValueObject &&value) +{ + values_.insert_or_assign(columnName, std::move(value)); +} + void ValuesBucket::Delete(const std::string &columnName) { values_.erase(columnName); diff --git a/relational_store/frameworks/native/rdb/src/values_buckets.cpp b/relational_store/frameworks/native/rdb/src/values_buckets.cpp index c04f5ae9f534672aba7bdf8d785bb05a32d1c3ec..f226531fdadd90133938d0e981aef5cec0549872 100644 --- a/relational_store/frameworks/native/rdb/src/values_buckets.cpp +++ b/relational_store/frameworks/native/rdb/src/values_buckets.cpp @@ -24,6 +24,22 @@ ValuesBuckets::ValuesBuckets() values_ = std::make_shared>(); } +ValuesBuckets::ValuesBuckets(const std::vector &rows) : ValuesBuckets() +{ + buckets_.reserve(rows.size()); + for (const auto &bucket : rows) { + Put(bucket); + } +} + +ValuesBuckets::ValuesBuckets(std::vector &&rows) noexcept : ValuesBuckets() +{ + buckets_.reserve(rows.size()); + for (auto &bucket : rows) { + Put(std::move(bucket)); + } +} + size_t ValuesBuckets::RowSize() const { return buckets_.size(); @@ -34,6 +50,18 @@ std::pair ValuesBuckets::G return { fields_, values_ }; } +void ValuesBuckets::Reserve(int32_t size) +{ + buckets_.reserve(size); +} + +void ValuesBuckets::Clear() +{ + buckets_.clear(); + fields_->clear(); + values_->clear(); +} + void ValuesBuckets::Put(const ValuesBucket &bucket) { BucketType row; @@ -46,6 +74,18 @@ void ValuesBuckets::Put(const ValuesBucket &bucket) buckets_.push_back(std::move(row)); } +void ValuesBuckets::Put(ValuesBucket &&bucket) +{ + BucketType row; + for (auto &[field, value] : bucket.values_) { + auto fieldResult = fields_->insert(std::move(field)); + auto valueResult = values_->insert(std::move(value)); + row.insert(std::make_pair(std::ref(const_cast(*fieldResult.first)), + std::ref(const_cast(*valueResult.first)))); + } + buckets_.push_back(std::move(row)); +} + std::pair ValuesBuckets::Get(size_t row, const FieldType &field) const { ValueObject empty; diff --git a/relational_store/frameworks/native/rdb_crypt/BUILD.gn b/relational_store/frameworks/native/rdb_crypt/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..543039d367d1fc1969fb1abeda86d78492d7a75e --- /dev/null +++ b/relational_store/frameworks/native/rdb_crypt/BUILD.gn @@ -0,0 +1,46 @@ +# Copyright (c) 2025 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("//build/ohos/ace/ace.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +ohos_shared_library("relational_store_crypt") { +part_name = "relational_store" +sanitize = { + boundary_sanitize = true + ubsan = true + cfi = true + cfi_cross_dso = true + debug = false +} + +sources = [ + "${relational_store_native_path}/rdb_crypt/relational_store_crypt.cpp", +] +include_dirs = [ + "${relational_store_common_path}/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/rdb_crypt", + "${relational_store_native_path}/rdb/include", + "${relational_store_native_path}/dfx/include", +] +ldflags = [ "-Wl,--exclude-libs,ALL" ] +cflags_cc = [ "-fvisibility=hidden" ] + +external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "huks:libhukssdk", +] +subsystem_name = "distributeddatamgr" +} \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb_crypt/relational_store_crypt.cpp b/relational_store/frameworks/native/rdb_crypt/relational_store_crypt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4aeabef4ea90b0c7606de20aa30c98fbc4fd3147 --- /dev/null +++ b/relational_store/frameworks/native/rdb_crypt/relational_store_crypt.cpp @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2025 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 "relational_store_crypt.h" +#define LOG_TAG "RDBCryptoFault" + +#include +#include +#include + +#include "rdb_dfx_errno.h" +#include "hks_api.h" +#include "hks_param.h" +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_visibility.h" + +using RDBCryptoFault = OHOS::NativeRdb::RDBCryptoFault; +using RdbSecretContent = OHOS::NativeRdb::RdbSecretContent; +namespace OHOS { +namespace NativeRdb { +class RDBCrypto { +public: + static int32_t CheckRootKeyExists(std::vector &rootKeyAlias); + static int32_t GenerateRootKey(const std::vector &rootKeyAlias, RDBCryptoFault &rdbFault); + static std::vector Encrypt(const RDBCryptoParam ¶m, RDBCryptoFault &rdbFault); + static std::vector Decrypt(const RDBCryptoParam ¶m, RDBCryptoFault &rdbFault); + static std::vector GenerateRandomNum(uint32_t len); +}; +} // namespace NativeRdb +} // namespace OHOS +API_EXPORT int32_t CheckRootKeyExists(std::vector &rootKeyAlias) asm("checkRootKeyExists"); +API_EXPORT int32_t GenerateRootKey(const std::vector &rootKeyAlias, RDBCryptoFault &rdbFault) asm( + "generateRootKey"); +API_EXPORT std::vector Encrypt(const OHOS::NativeRdb::RDBCryptoParam ¶m, RDBCryptoFault &rdbFault) asm( + "encrypt"); +API_EXPORT std::vector Decrypt(const OHOS::NativeRdb::RDBCryptoParam ¶m, RDBCryptoFault &rdbFault) asm( + "decrypt"); +API_EXPORT std::vector GenerateRandomNum(int32_t &len) asm("generateRandomNum"); +int32_t CheckRootKeyExists(std::vector &rootKeyAlias) +{ + return OHOS::NativeRdb::RDBCrypto::CheckRootKeyExists(rootKeyAlias); +} +int32_t GenerateRootKey(const std::vector &rootKeyAlias, RDBCryptoFault &rdbFault) +{ + return OHOS::NativeRdb::RDBCrypto::GenerateRootKey(rootKeyAlias, rdbFault); +} +std::vector Encrypt(const OHOS::NativeRdb::RDBCryptoParam ¶m, RDBCryptoFault &rdbFault) +{ + return OHOS::NativeRdb::RDBCrypto::Encrypt(param, rdbFault); +} +std::vector Decrypt(const OHOS::NativeRdb::RDBCryptoParam ¶m, RDBCryptoFault &rdbFault) +{ + return OHOS::NativeRdb::RDBCrypto::Decrypt(param, rdbFault); +} +std::vector GenerateRandomNum(uint32_t len) +{ + return OHOS::NativeRdb::RDBCrypto::GenerateRandomNum(len); +} +namespace OHOS { +namespace NativeRdb { +using namespace OHOS::Rdb; +constexpr const char *RDB_HKS_BLOB_TYPE_NONCE = "Z5s0Bo571Koq"; +constexpr const char *RDB_HKS_BLOB_TYPE_AAD = "RdbClientAAD"; +constexpr uint32_t TIMES = 4; +constexpr uint32_t MAX_UPDATE_SIZE = 64; +constexpr uint32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES; +constexpr uint8_t AEAD_LEN = 16; +static std::vector g_nonce(RDB_HKS_BLOB_TYPE_NONCE, RDB_HKS_BLOB_TYPE_NONCE + strlen(RDB_HKS_BLOB_TYPE_NONCE)); +static std::vector g_add(RDB_HKS_BLOB_TYPE_AAD, RDB_HKS_BLOB_TYPE_AAD + strlen(RDB_HKS_BLOB_TYPE_AAD)); + +RDBCryptoFault GetDfxFault(int32_t code, const std::string &message) +{ + RDBCryptoFault rdbDfxFault; + rdbDfxFault.code = code; + rdbDfxFault.message = message; + return rdbDfxFault; +} + +int32_t HksLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData, + struct HksBlob *outData, RDBCryptoFault &rdbFault) +{ + if (outData->size < inData->size * TIMES) { + HksAbort(handle, paramSet); + rdbFault = GetDfxFault(E_WORK_KEY_FAIL, "HksLoopUpdate out size not enough"); + return HKS_ERROR_INVALID_ARGUMENT; + } + + struct HksBlob input = { MAX_UPDATE_SIZE, inData->data }; + uint8_t *end = inData->data + inData->size - 1; + outData->size = 0; + struct HksBlob output = { MAX_OUTDATA_SIZE, outData->data }; + while (input.data <= end) { + if (input.data + MAX_UPDATE_SIZE > end) { + input.size = end - input.data + 1; + break; + } + auto result = HksUpdate(handle, paramSet, &input, &output); + if (result != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_FAIL, "HksUpdate ret=" + std::to_string(result)); + LOG_ERROR("HksUpdate Failed."); + return HKS_FAILURE; + } + + output.data += output.size; + outData->size += output.size; + input.data += MAX_UPDATE_SIZE; + } + output.size = input.size * TIMES; + auto result = HksFinish(handle, paramSet, &input, &output); + if (result != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_FAIL, "HksFinish ret=" + std::to_string(result)); + LOG_ERROR("HksFinish Failed."); + return HKS_FAILURE; + } + outData->size += output.size; + return HKS_SUCCESS; +} + +int32_t HksDecryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, + const struct HksBlob *cipherText, struct HksBlob *plainText, RDBCryptoFault &rdbFault) +{ + uint8_t handle[sizeof(uint64_t)] = { 0 }; + struct HksBlob handleBlob = { sizeof(uint64_t), handle }; + int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr); + if (result != HKS_SUCCESS) { + LOG_ERROR("HksEncrypt failed with error %{public}d", result); + rdbFault = GetDfxFault(E_WORK_KEY_DECRYPT_FAIL, "Decrypt HksInit ret=" + std::to_string(result)); + return result; + } + result = HksLoopUpdate(&handleBlob, paramSet, cipherText, plainText, rdbFault); + if (result != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_DECRYPT_FAIL, "Decrypt HksLoopUpdate ret=" + std::to_string(result)); + } + return result; +} + +int32_t HksEncryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, + const struct HksBlob *plainText, struct HksBlob *cipherText, RDBCryptoFault &rdbFault) +{ + uint8_t handle[sizeof(uint64_t)] = { 0 }; + struct HksBlob handleBlob = { sizeof(uint64_t), handle }; + int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr); + if (result != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_ENCRYPT_FAIL, "Decrypt HksInit ret=" + std::to_string(result)); + LOG_ERROR("HksEncrypt failed with error %{public}d", result); + return result; + } + return HksLoopUpdate(&handleBlob, paramSet, plainText, cipherText, rdbFault); +} + +std::vector CreateHksParams(const HksBlob &blobNonce, const HksBlob &blobAad, const HksBlob &blobAead) +{ + std::vector params; + params.push_back(HksParam{ .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }); + params.push_back(HksParam{ .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }); + params.push_back(HksParam{ .tag = HKS_TAG_DIGEST, .uint32Param = 0 }); + params.push_back(HksParam{ .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }); + params.push_back(HksParam{ .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }); + params.push_back(HksParam{ .tag = HKS_TAG_NONCE, .blob = blobNonce }); + params.push_back(HksParam{ .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }); + params.push_back(HksParam{ .tag = HKS_TAG_AE_TAG, .blob = blobAead }); + params.push_back(HksParam{ .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }); + return params; +} + +int32_t RDBCrypto::CheckRootKeyExists(std::vector &rootKeyAlias) +{ + LOG_DEBUG("RDB checkRootKeyExist begin."); + struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), rootKeyAlias.data() }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret); + return ret; + } + + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, + }; + + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return ret; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return ret; + } + + ret = HksKeyExist(&rootKeyName, params); + HksFreeParamSet(¶ms); + return ret; +} + +int32_t RDBCrypto::GenerateRootKey(const std::vector &rootKeyAlias, RDBCryptoFault &rdbFault) +{ + LOG_INFO("RDB GenerateRootKey begin."); + std::vector tempRootKeyAlias = rootKeyAlias; + struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), tempRootKeyAlias.data() }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_ROOT_KEY_FAULT, "generator root key, HksInitParamSet ret=" + std::to_string(ret)); + LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret); + return ret; + } + + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, + }; + + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_ROOT_KEY_FAULT, "HksAddParams ret=" + std::to_string(ret)); + LOG_ERROR("HksAddParams-client failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return ret; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_ROOT_KEY_FAULT, "HksBuildParamSet ret=" + std::to_string(ret)); + LOG_ERROR("HksBuildParamSet-client failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return ret; + } + + ret = HksGenerateKey(&rootKeyName, params, nullptr); + HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_ROOT_KEY_FAULT, "HksGenerateKey ret=" + std::to_string(ret)); + LOG_ERROR("HksGenerateKey-client failed with error %{public}d", ret); + } + return ret; +} + +std::vector CreateEncryptHksParams(const HksBlob &blobNonce, const HksBlob &blobAad) +{ + std::vector params; + params.push_back(HksParam{ .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }); + params.push_back(HksParam{ .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT }); + params.push_back(HksParam{ .tag = HKS_TAG_DIGEST, .uint32Param = 0 }); + params.push_back(HksParam{ .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }); + params.push_back(HksParam{ .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }); + params.push_back(HksParam{ .tag = HKS_TAG_NONCE, .blob = blobNonce }); + params.push_back(HksParam{ .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }); + params.push_back(HksParam{ .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }); + return params; +} + +std::vector RDBCrypto::Encrypt(const RDBCryptoParam ¶m, RDBCryptoFault &rdbFault) +{ + std::vector tempRootKeyAlias(param.rootAlias); + std::vector tempKey(param.KeyValue); + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_ENCRYPT_FAIL, "Encrypt HksInitParamSet ret=" + std::to_string(ret)); + LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret); + tempKey.assign(tempKey.size(), 0); + return {}; + } + struct HksBlob blobAad = { uint32_t(g_add.size()), g_add.data() }; + struct HksBlob rootKeyName = { uint32_t(tempRootKeyAlias.size()), tempRootKeyAlias.data() }; + struct HksBlob plainKey = { uint32_t(tempKey.size()), tempKey.data() }; + struct HksBlob blobNonce = { uint32_t(param.nonceValue.size()), const_cast(&(param.nonceValue[0])) }; + + auto hksParams = CreateEncryptHksParams(blobNonce, blobAad); + ret = HksAddParams(params, hksParams.data(), hksParams.size()); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_ENCRYPT_FAIL, "Encrypt HksAddParams ret=" + std::to_string(ret)); + LOG_ERROR("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + tempKey.assign(tempKey.size(), 0); + return {}; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_ENCRYPT_FAIL, "Encrypt HksBuildParamSet ret=" + std::to_string(ret)); + LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + tempKey.assign(tempKey.size(), 0); + return {}; + } + std::vector encryptedKey(plainKey.size * TIMES + 1); + struct HksBlob cipherText = { uint32_t(encryptedKey.size()), encryptedKey.data() }; + ret = HksEncryptThreeStage(&rootKeyName, params, &plainKey, &cipherText, rdbFault); + (void)HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + encryptedKey.assign(encryptedKey.size(), 0); + tempKey.assign(tempKey.size(), 0); + return {}; + } + encryptedKey.resize(cipherText.size); + tempKey.assign(tempKey.size(), 0); + return encryptedKey; +} + +std::vector RDBCrypto::Decrypt(const RDBCryptoParam ¶m, RDBCryptoFault &rdbFault) +{ + std::vector tempRootKeyAlias(param.rootAlias); + std::vector source(param.KeyValue); + struct HksBlob blobAad = { uint32_t(g_add.size()), &(g_add[0]) }; + struct HksBlob blobNonce = { uint32_t(param.nonceValue.size()), const_cast(&(param.nonceValue[0])) }; + struct HksBlob rootKeyName = { uint32_t(tempRootKeyAlias.size()), &(tempRootKeyAlias[0]) }; + struct HksBlob encryptedKeyBlob = { uint32_t(source.size() - AEAD_LEN), source.data() }; + struct HksBlob blobAead = { AEAD_LEN, source.data() + source.size() - AEAD_LEN }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_DECRYPT_FAIL, "HksInitParamSet ret=" + std::to_string(ret)); + LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret); + return {}; + } + auto hksParams = CreateHksParams(blobNonce, blobAad, blobAead); + ret = HksAddParams(params, hksParams.data(), hksParams.size()); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_DECRYPT_FAIL, "HksAddParams ret=" + std::to_string(ret)); + LOG_ERROR("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return {}; + } + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_DECRYPT_FAIL, "HksBuildParamSet ret=" + std::to_string(ret)); + LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return {}; + } + std::vector decryptKey(encryptedKeyBlob.size * TIMES + 1); + struct HksBlob plainKeyBlob = { uint32_t(decryptKey.size()), decryptKey.data() }; + ret = HksDecryptThreeStage(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob, rdbFault); + (void)HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + decryptKey.assign(decryptKey.size(), 0); + LOG_ERROR("HksDecrypt failed with error %{public}d", ret); + return {}; + } + decryptKey.resize(plainKeyBlob.size); + return decryptKey; +} + +std::vector RDBCrypto::GenerateRandomNum(uint32_t len) +{ + std::vector value(len, 0); + struct HksBlob blobValue = { .size = len, .data = &(value[0]) }; + auto ret = HksGenerateRandom(nullptr, &blobValue); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksGenerateRandom failed, status: %{public}d", ret); + return {}; + } + return value; +} +} // namespace NativeRdb +} // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb_crypt/relational_store_crypt.h b/relational_store/frameworks/native/rdb_crypt/relational_store_crypt.h new file mode 100644 index 0000000000000000000000000000000000000000..e0cc26d4c21827f0a10c1b7300a763c39bfddd23 --- /dev/null +++ b/relational_store/frameworks/native/rdb_crypt/relational_store_crypt.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025 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 RELATIONAL_STORE_CRYPT_H +#define RELATIONAL_STORE_CRYPT_H + +#include +#include +#include + +#include "rdb_security_manager.h" + +namespace OHOS { +namespace NativeRdb { +struct RDBCryptoFault { + int32_t code; + std::string message; +}; +struct RDBCryptoParam { + std::vector rootAlias; + std::vector nonceValue; + std::vector KeyValue; + RDBCryptoParam() = default; + ~RDBCryptoParam() + { + nonceValue.assign(nonceValue.size(), 0); + KeyValue.assign(KeyValue.size(), 0); + } +}; +} // namespace OHOS::NativeRdb +} // OHOS + +#endif // RELATIONAL_STORE_CRYPT_H \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/appdatafwk/BUILD.gn b/relational_store/interfaces/inner_api/appdatafwk/BUILD.gn index f327747e5012a2c25850ef57b44bd308221ba86a..6293105941def0f26135a3fcae7b275b3a39b743 100644 --- a/relational_store/interfaces/inner_api/appdatafwk/BUILD.gn +++ b/relational_store/interfaces/inner_api/appdatafwk/BUILD.gn @@ -39,7 +39,6 @@ config("common_public_config") { include_dirs = [ "include", "${relational_store_common_path}/include", - "//third_party/json/single_include", ] } @@ -63,6 +62,11 @@ if (is_android || is_ios) { ":appdatafwk_public_config", ] + deps = [ + "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_${target_os}", + "//third_party/json:nlohmann_json_static", + ] + subsystem_name = "distributeddatamgr" part_name = "relational_store" @@ -98,6 +102,10 @@ if (is_android || is_ios) { ":common_public_config", ":appdatafwk_public_config", ] + external_deps = [ + "json:nlohmann_json_static", + "hilog:libhilog", + ] subsystem_name = "distributeddatamgr" part_name = "relational_store" @@ -127,6 +135,7 @@ ohos_shared_library("native_appdatafwk") { external_deps = [ "c_utils:utils", + "json:nlohmann_json_static", "hilog:libhilog", "ipc:ipc_single", ] diff --git a/relational_store/interfaces/inner_api/appdatafwk/include/serializable.h b/relational_store/interfaces/inner_api/appdatafwk/include/serializable.h index b4fd7f8f8f48ecc489cf6f8fb9fd4441d1d9bffb..f8293bbb49c133fb217bb922da0426a81d9c9f62 100644 --- a/relational_store/interfaces/inner_api/appdatafwk/include/serializable.h +++ b/relational_store/interfaces/inner_api/appdatafwk/include/serializable.h @@ -59,6 +59,7 @@ public: API_EXPORT static bool GetValue(const json &node, const std::string &name, bool &value); API_EXPORT static bool GetValue(const json &node, const std::string &name, std::vector &value); API_EXPORT static bool GetValue(const json &node, const std::string &name, Serializable &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, double &value); API_EXPORT static bool SetValue(json &node, const std::string &value); API_EXPORT static bool SetValue(json &node, const uint32_t &value); API_EXPORT static bool SetValue(json &node, const int32_t &value); @@ -67,6 +68,7 @@ public: API_EXPORT static bool SetValue(json &node, const bool &value); API_EXPORT static bool SetValue(json &node, const std::vector &value); API_EXPORT static bool SetValue(json &node, const Serializable &value); + API_EXPORT static bool SetValue(json &node, const double &value); protected: API_EXPORT ~Serializable() = default; diff --git a/relational_store/interfaces/inner_api/appdatafwk/include/shared_block.h b/relational_store/interfaces/inner_api/appdatafwk/include/shared_block.h index edae9b8132cb9690cc91162fbdb9f13aa5f5ab7f..6bfde2c1ef920e0c31146689d2110e86ff970c6e 100644 --- a/relational_store/interfaces/inner_api/appdatafwk/include/shared_block.h +++ b/relational_store/interfaces/inner_api/appdatafwk/include/shared_block.h @@ -36,7 +36,7 @@ static const uint32_t INVALID_ROW_RECORD = 0xFFFFFFFF; * This class stores a set of rows from a database in a buffer, * which is used as the set of query result. */ -class API_EXPORT SharedBlock { +class SharedBlock { public: /** * @brief Cell Unit types. @@ -98,21 +98,8 @@ public: API_EXPORT const uint8_t *GetRawData(SharedBlock *block) const; } __attribute((packed)); - /** - * @brief Constructor. - */ - API_EXPORT SharedBlock(const std::string &name, sptr ashmem, size_t size, bool readOnly); - - /** - * @brief Destructor. - */ API_EXPORT ~SharedBlock(); - /** - * @brief Init current shared block. - */ - API_EXPORT bool Init(); - /** * @brief Create a shared block. */ @@ -193,6 +180,9 @@ public: */ API_EXPORT const char *GetCellUnitValueString(CellUnit *cellUnit, size_t *outSizeIncludingNull) { + if (cellUnit == nullptr || outSizeIncludingNull == nullptr) { + return nullptr; + } *outSizeIncludingNull = cellUnit->cell.stringOrBlobValue.size; return static_cast( OffsetToPtr(cellUnit->cell.stringOrBlobValue.offset, cellUnit->cell.stringOrBlobValue.size)); @@ -203,6 +193,9 @@ public: */ API_EXPORT const void *GetCellUnitValueBlob(CellUnit *cellUnit, size_t *outSize) { + if (cellUnit == nullptr || outSize == nullptr) { + return nullptr; + } *outSize = cellUnit->cell.stringOrBlobValue.size; return OffsetToPtr(cellUnit->cell.stringOrBlobValue.offset, cellUnit->cell.stringOrBlobValue.size); } @@ -365,6 +358,10 @@ private: SharedBlockHeader *mHeader; + SharedBlock(const std::string &name, sptr ashmem, size_t size, bool readOnly); + + bool Init(); + /** * Allocate a portion of the block. Returns the offset of the allocation. * Returns 0 if there isn't enough space. diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_notifier.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_notifier.h new file mode 100644 index 0000000000000000000000000000000000000000..1fdcbc67cddcf5ebf90d1316a2788ceeb52e6220 --- /dev/null +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_notifier.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 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_CLOUD_CLOUD_NOTIFIER_H +#define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_NOTIFIER_H + +#include "cloud_types.h" +#include "distributeddata_relational_store_ipc_interface_code.h" +#include "rdb_types.h" + +namespace OHOS::CloudData { +class ICloudNotifier { +public: + virtual int32_t OnComplete(uint32_t seqNum, DistributedRdb::Details &&result) = 0; +}; +} // namespace OHOS::CloudData +#endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_NOTIFIER_H diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h index 1351c79556543f0ea40dc35716d20905028320c6..2ecc08abc337f8947900328e85158db33c157b1c 100644 --- a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h @@ -24,6 +24,7 @@ #include "cloud_types.h" #include "common_types.h" +#include "iremote_broker.h" #include "rdb_types.h" #include "values_bucket.h" namespace OHOS { @@ -42,6 +43,7 @@ public: TRANS_QUERY_STATISTICS, TRANS_QUERY_LAST_SYNC_INFO, TRANS_SET_GLOBAL_CLOUD_STRATEGY, + TRANS_CLOUD_SYNC, TRANS_CONFIG_BUTT, TRANS_SHARE_HEAD = TRANS_CONFIG_BUTT, TRANS_ALLOC_RESOURCE_AND_SHARE = TRANS_SHARE_HEAD, @@ -56,6 +58,7 @@ public: TRANS_SHARE_BUTT, TRANS_CLIENT_HEAD = TRANS_SHARE_BUTT, TRANS_SET_CLOUD_STRATEGY = TRANS_CLIENT_HEAD, + TRANS_INIT_NOTIFIER, TRANS_CLIENT_BUTT, TRANS_BUTT = TRANS_CLIENT_BUTT, }; @@ -91,6 +94,12 @@ public: CLOUD_INFO_INVALID, SCHEMA_INVALID, STRATEGY_BLOCKING, + INVALID_ARGUMENT_V20, + }; + + struct Option { + int32_t syncMode; + uint32_t seqNum = 0; }; static const int INVALID_USER_ID = -1; @@ -124,6 +133,9 @@ public: virtual int32_t SetCloudStrategy(Strategy strategy, const std::vector &values) = 0; virtual std::pair QueryLastSyncInfo( const std::string &id, const std::string &bundleName, const std::string &storeId) = 0; + virtual int32_t CloudSync(const std::string &bundleName, const std::string &storeId, const Option &option, + const DistributedRdb::AsyncDetail &async) = 0; + virtual int32_t InitNotifier(sptr notifier) = 0; inline static constexpr const char *SERVICE_NAME = "cloud"; }; diff --git a/relational_store/interfaces/inner_api/dataability/BUILD.gn b/relational_store/interfaces/inner_api/dataability/BUILD.gn index 97d6ef4f53295b653ec271768a980f8ce8d32f45..0c06a5e91be260cd0ae2f92c0f5c8a69fd66a308 100644 --- a/relational_store/interfaces/inner_api/dataability/BUILD.gn +++ b/relational_store/interfaces/inner_api/dataability/BUILD.gn @@ -58,7 +58,10 @@ ohos_shared_library("native_dataability") { configs = [ ":native_dataability_config" ] if (!(host_os == "linux" && host_cpu == "arm64")) { - deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + deps = [ + "${relational_store_innerapi_path}/rdb:native_rdb", + "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", + ] } external_deps = [ diff --git a/relational_store/interfaces/inner_api/dataability/include/data_ability_predicates.h b/relational_store/interfaces/inner_api/dataability/include/data_ability_predicates.h index aeb0553b06126db2bcc6d9ebab9b3f98b768da7a..0e2f460197d39d2e2395df6c88077c41ecb4163c 100644 --- a/relational_store/interfaces/inner_api/dataability/include/data_ability_predicates.h +++ b/relational_store/interfaces/inner_api/dataability/include/data_ability_predicates.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef NATIVE_RDB_DATD_ABILITY_PREDICATES_H -#define NATIVE_RDB_DATD_ABILITY_PREDICATES_H +#ifndef NATIVE_RDB_DATA_ABILITY_PREDICATES_H +#define NATIVE_RDB_DATA_ABILITY_PREDICATES_H #include diff --git a/relational_store/interfaces/inner_api/gdb/include/gdb_errors.h b/relational_store/interfaces/inner_api/gdb/include/gdb_errors.h deleted file mode 100644 index 7ad53617b67aa1438c98b17643085122494892bf..0000000000000000000000000000000000000000 --- a/relational_store/interfaces/inner_api/gdb/include/gdb_errors.h +++ /dev/null @@ -1,102 +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. - */ - -#ifndef OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GDB_ERRORS_H -#define OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GDB_ERRORS_H - -#include "errors.h" - -namespace OHOS { -namespace DistributedDataAip { -enum { - AIP_MODULE_SERVICE_ID = 0x08, -}; - -constexpr ErrCode DISTRIBUTEDDATAMGR_GDB_ERR_OFFSET = ErrCodeOffset(SUBSYS_DISTRIBUTEDDATAMNG, AIP_MODULE_SERVICE_ID); - -/** -* @brief The error code in the correct case. -*/ -constexpr int E_OK = 0; - -/** -* @brief The base code of the exception error code. -*/ -constexpr int E_BASE = DISTRIBUTEDDATAMGR_GDB_ERR_OFFSET; - -/** -* @brief The error code for common exceptions. -*/ -constexpr int E_ERROR = E_BASE; - -constexpr int E_INVALID_ARGS = (E_BASE + 0x1); -constexpr int E_NOT_SUPPORT = (E_BASE + 0x2); - -/* GRD error */ - -constexpr int E_GRD_NO_DATA = (E_BASE + 0x3); -constexpr int E_GRD_DATA_CORRUPTED = (E_BASE + 0x4); -constexpr int E_GRD_DB_INSTANCE_ABNORMAL = (E_BASE + 0x5); -constexpr int E_DATABASE_BUSY = (E_BASE + 0x6); -constexpr int E_GRD_FAILED_MEMORY_ALLOCATE = (E_BASE + 0x7); -constexpr int E_GRD_DISK_SPACE_FULL = (E_BASE + 0x8); -constexpr int E_GRD_DUPLICATE_PARAM = (E_BASE + 0x9); -constexpr int E_GRD_UNDEFINED_PARAM = (E_BASE + 0xa); -constexpr int E_GRD_INVALID_NAME = (E_BASE + 0xb); -constexpr int E_GRD_SYNTAX_ERROR = (E_BASE + 0xc); -constexpr int E_GRD_SEMANTIC_ERROR = (E_BASE + 0xd); -constexpr int E_GRD_OVER_LIMIT = (E_BASE + 0xe); - -constexpr int E_GRD_INVALID_ARGS = (E_BASE + 0xf); -constexpr int E_GRD_FAILED_FILE_OPERATION = (E_BASE + 0x10); -constexpr int E_GRD_CRC_CHECK_DISABLED = (E_BASE + 0x11); -constexpr int E_GRD_PERMISSION_DENIED = (E_BASE + 0x12); -constexpr int E_GRD_PASSWORD_UNMATCHED = (E_BASE + 0x13); -constexpr int E_GRD_PASSWORD_NEED_REKEY = (E_BASE + 0x14); -constexpr int E_GRD_WRONG_STMT_OBJECT = (E_BASE + 0x15); -constexpr int E_GRD_DATA_CONFLICT = (E_BASE + 0x16); -constexpr int E_GRD_INNER_ERR = (E_BASE + 0x17); -constexpr int E_GRD_FAILED_MEMORY_RELEASE = (E_BASE + 0x18); -constexpr int E_GRD_NOT_AVAILABLE = (E_BASE + 0x19); -constexpr int E_GRD_CIPHER_ERROR = (E_BASE + 0x1a); -constexpr int E_ARGS_READ_CON_OVERLOAD = (E_BASE + 0x1b); -constexpr int E_GRD_INVALID_FILE_FORMAT = (E_BASE + 0x1c); -constexpr int E_GRD_INVALID_BIND_VALUE = (E_BASE + 0x1d); -constexpr int E_GRD_DB_NOT_EXIST = (E_BASE + 0x1e); -constexpr int E_GRD_DATA_NOT_FOUND = (E_BASE + 0x1f); -constexpr int E_GRD_DATA_EXCEPTION = (E_BASE + 0x20); -constexpr int E_GRD_TRANSACTION_ROLLBACK = (E_BASE + 0x21); -constexpr int E_GRD_NO_ACTIVE_TRANSACTION = (E_BASE + 0x22); -constexpr int E_GRD_ACTIVE_TRANSACTION = (E_BASE + 0x23); - -constexpr int E_ACQUIRE_CONN_FAILED = (E_BASE + 0x24); -constexpr int E_PREPARE_CHECK_FAILED = (E_BASE + 0x25); -constexpr int E_STEP_CHECK_FAILED = (E_BASE + 0x26); -constexpr int E_GETTED_COLNAME_EMPTY = (E_BASE + 0x27); -constexpr int E_PARSE_JSON_FAILED = (E_BASE + 0x28); -constexpr int E_INNER_ERROR = (E_BASE + 0x29); -constexpr int E_NO_DATA = (E_BASE + 0x2a); -constexpr int E_DBPATH_ACCESS_FAILED = (E_BASE + 0x2b); -constexpr int E_INIT_CONN_POOL_FAILED = (E_BASE + 0x2c); -constexpr int E_CONFIG_INVALID_CHANGE = (E_BASE + 0x2d); -constexpr int E_GRD_INVAILD_NAME_ERR = (E_BASE + 0x2e); -constexpr int E_CREATE_FOLDER_FAIT = (E_BASE + 0x3f); -constexpr int E_STATEMENT_EMPTY = (E_BASE + 0x30); -constexpr int E_STORE_HAS_CLOSED = (E_BASE + 0x31); -constexpr int E_GRD_NOT_SUPPORT = (E_BASE + 0x32); -} // namespace DistributedDataAip -} // namespace OHOS - -#endif // OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GDB_ERRORS_H \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/gdb/include/gdb_store.h b/relational_store/interfaces/inner_api/gdb/include/gdb_store.h deleted file mode 100644 index fc251b5090a3748c0cec00c796a1401f408b2d56..0000000000000000000000000000000000000000 --- a/relational_store/interfaces/inner_api/gdb/include/gdb_store.h +++ /dev/null @@ -1,33 +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. - */ - -#ifndef OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_DB_STORE_H -#define OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_DB_STORE_H -#include "gdb_transaction.h" -#include "rdb_visibility.h" -#include "result.h" - -namespace OHOS::DistributedDataAip { -class API_EXPORT DBStore { -public: - API_EXPORT virtual std::pair> QueryGql(const std::string &gql) = 0; - API_EXPORT virtual std::pair> ExecuteGql(const std::string &gql) = 0; - API_EXPORT virtual std::pair> CreateTransaction() = 0; - API_EXPORT virtual int32_t Close() = 0; - - virtual ~DBStore() = default; -}; -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_DB_STORE_H diff --git a/relational_store/interfaces/inner_api/gdb/include/gdb_store_config.h b/relational_store/interfaces/inner_api/gdb/include/gdb_store_config.h deleted file mode 100644 index 89962ccf31e39b9e3360a6544342bd7b38b03444..0000000000000000000000000000000000000000 --- a/relational_store/interfaces/inner_api/gdb/include/gdb_store_config.h +++ /dev/null @@ -1,102 +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. - */ - -#ifndef OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_STORE_CONFIG_H -#define OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_STORE_CONFIG_H - -#include -#include -#include - -#include "rdb_store_config.h" -#include "rdb_visibility.h" - -namespace OHOS::DistributedDataAip { -enum SecurityLevel : int32_t { - S1 = 1, - S2, - S3, - S4, - LAST, -}; - -enum class DBType : int { - /** - * The graph database. - */ - DB_GRAPH, - - /** - * The vector database. - */ - DB_VECTOR, - /** - * The BUTT of database. - */ - DB_BUTT -}; - -class StoreConfig { -public: - API_EXPORT StoreConfig() = default; - API_EXPORT ~StoreConfig(); - API_EXPORT StoreConfig(std::string name, std::string path, DBType dbType = DBType::DB_GRAPH, bool isEncrypt = false, - const std::vector &encryptKey = std::vector()); - API_EXPORT void SetName(std::string name); - API_EXPORT void SetPath(std::string path); - API_EXPORT void SetDbType(DBType dbType); - API_EXPORT void SetEncryptStatus(bool status); - API_EXPORT void SetSecurityLevel(int32_t securityLevel); - API_EXPORT bool IsEncrypt() const; - API_EXPORT std::string GetFullPath() const; - API_EXPORT std::string GetPath() const; - API_EXPORT std::string GetName() const; - API_EXPORT int32_t GetSecurityLevel() const; - API_EXPORT DBType GetDbType() const; - API_EXPORT void SetIter(int32_t iter) const; - API_EXPORT int32_t GetIter() const; - API_EXPORT int GetWriteTime() const; - API_EXPORT void SetWriteTime(int timeout); - API_EXPORT int GetReadTime() const; - API_EXPORT void SetReadTime(int timeout); - API_EXPORT int GetReadConSize() const; - API_EXPORT void SetReadConSize(int readConSize); - API_EXPORT std::vector GetEncryptKey() const; - API_EXPORT int SetBundleName(const std::string &bundleName); - API_EXPORT std::string GetBundleName() const; - void GenerateEncryptedKey() const; - std::vector GetNewEncryptKey() const; - void ChangeEncryptKey() const; - -private: - std::string name_; - std::string path_; - std::string bundleName_; - DBType dbType_ = DBType::DB_GRAPH; - bool isEncrypt_ = false; - mutable std::vector encryptKey_{}; - mutable std::vector newEncryptKey_{}; - mutable int32_t iter_ = 0; - int32_t writeTimeout_ = 2; // seconds - int32_t readTimeout_ = 1; // seconds - int32_t readConSize_ = 4; - int32_t securityLevel_ = SecurityLevel::S1; - - static constexpr int MAX_TIMEOUT = 300; // seconds - static constexpr int MIN_TIMEOUT = 1; // seconds - void ClearEncryptKey(); -}; -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_STORE_CONFIG_H \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/gdb/include/path.h b/relational_store/interfaces/inner_api/gdb/include/path.h deleted file mode 100644 index d7095e2d70276b1b8e2a7dcfad6650911f212f6a..0000000000000000000000000000000000000000 --- a/relational_store/interfaces/inner_api/gdb/include/path.h +++ /dev/null @@ -1,62 +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. -*/ - -#ifndef OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_PATH_H -#define OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_PATH_H -#include -#include -#include -#include -#include -#include - -#include "edge.h" -#include "nlohmann/json.hpp" -#include "path_segment.h" -#include "rdb_visibility.h" -#include "vertex.h" - -namespace OHOS::DistributedDataAip { -class Path { -public: - API_EXPORT Path(); - API_EXPORT Path(std::shared_ptr start, std::shared_ptr end); - API_EXPORT Path(std::shared_ptr start, std::shared_ptr end, uint32_t pathLen, - std::vector> segments); - - static std::shared_ptr Parse(const nlohmann::json &json, int32_t &errCode); - - API_EXPORT uint32_t GetPathLength() const; - API_EXPORT void SetPathLength(uint32_t pathLen); - API_EXPORT std::shared_ptr GetStart() const; - API_EXPORT void SetStart(std::shared_ptr start); - API_EXPORT std::shared_ptr GetEnd() const; - API_EXPORT void SetEnd(std::shared_ptr end); - API_EXPORT const std::vector> &GetSegments() const; - - static constexpr const char *PATHLEN = "length"; - static constexpr const char *START = "start"; - static constexpr const char *END = "end"; - static constexpr const char *SEGMENTS = "segments"; - -private: - uint32_t pathLen_; - std::shared_ptr start_; - std::shared_ptr end_; - std::vector> segments_; -}; - -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_PATH_H diff --git a/relational_store/interfaces/inner_api/gdb/include/path_segment.h b/relational_store/interfaces/inner_api/gdb/include/path_segment.h deleted file mode 100644 index 31e00a005b87ea59f300ea88b022e27b5400e3e0..0000000000000000000000000000000000000000 --- a/relational_store/interfaces/inner_api/gdb/include/path_segment.h +++ /dev/null @@ -1,56 +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. -*/ - -#ifndef OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_PATH_SEGMENT_H -#define OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_PATH_SEGMENT_H -#include -#include -#include -#include -#include -#include - -#include "edge.h" -#include "rdb_visibility.h" -#include "vertex.h" - -namespace OHOS::DistributedDataAip { -class PathSegment { -public: - API_EXPORT PathSegment(); - API_EXPORT PathSegment(std::shared_ptr sourceVertex, std::shared_ptr targetVertex, - std::shared_ptr edge); - static std::shared_ptr Parse(const nlohmann::json &json, int32_t &errCode); - - API_EXPORT std::shared_ptr GetSourceVertex() const; - API_EXPORT void SetSourceVertex(std::shared_ptr vertex); - - API_EXPORT std::shared_ptr GetEdge() const; - API_EXPORT void SetEdge(std::shared_ptr edge); - - API_EXPORT std::shared_ptr GetTargetVertex() const; - API_EXPORT void SetTargetVertex(std::shared_ptr vertex); - - static constexpr const char *SOURCE_VERTEX = "start"; - static constexpr const char *TARGET_VERTEX = "end"; - static constexpr const char *EDGE = "relationship"; - -private: - std::shared_ptr sourceVertex_; - std::shared_ptr edge_; - std::shared_ptr targetVertex_; -}; -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_PATH_SEGMENT_H diff --git a/relational_store/interfaces/inner_api/gdb/include/vertex.h b/relational_store/interfaces/inner_api/gdb/include/vertex.h deleted file mode 100644 index f4f28882eaf6646f401adc358f5eab4c5169d5a4..0000000000000000000000000000000000000000 --- a/relational_store/interfaces/inner_api/gdb/include/vertex.h +++ /dev/null @@ -1,58 +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. -*/ - -#ifndef OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_VERTEX_H -#define OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_VERTEX_H -#include -#include -#include -#include -#include -#include - -#include "nlohmann/json.hpp" -#include "rdb_visibility.h" - -namespace OHOS::DistributedDataAip { -using PropType = std::variant; -class Vertex { -public: - API_EXPORT Vertex(); - API_EXPORT Vertex(std::string id, std::string label); - API_EXPORT Vertex(std::string id, std::string label, const std::unordered_map &properties); - static std::shared_ptr Parse(const nlohmann::json &json, int32_t &errCode); - - API_EXPORT std::string GetId() const; - API_EXPORT void SetId(std::string id); - - API_EXPORT const std::string &GetLabel() const; - API_EXPORT const std::vector &GetLabels() const; - API_EXPORT void SetLabel(const std::string &label); - - API_EXPORT const std::unordered_map &GetProperties() const; - API_EXPORT void SetProperty(const std::string &key, PropType value); - - static constexpr const char *ID = "identity"; - static constexpr const char *LABEL = "label"; - static constexpr const char *PROPERTIES = "properties"; - -protected: - std::string id_; - std::string label_; - std::vector labels_; - std::unordered_map properties_; -}; -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_VERTEX_H diff --git a/relational_store/interfaces/inner_api/rdb/BUILD.gn b/relational_store/interfaces/inner_api/rdb/BUILD.gn index 3888a55dda81799833438e164f210a3b08f1e274..c28fbde16aa7df10fb052bddb117d57d399d1a7c 100644 --- a/relational_store/interfaces/inner_api/rdb/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# Copyright (c) 2021-2025 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 @@ -24,11 +24,17 @@ base_sources = [ "${relational_store_native_path}/rdb/src/connection.cpp", "${relational_store_native_path}/rdb/src/connection_pool.cpp", "${relational_store_native_path}/rdb/src/delay_notify.cpp", + "${relational_store_native_path}/rdb/src/global_resource.cpp", + "${relational_store_native_path}/rdb/src/knowledge_schema_helper.cpp", "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", "${relational_store_native_path}/rdb/src/rdb_helper.cpp", + "${relational_store_native_path}/rdb/src/rdb_icu_manager.cpp", "${relational_store_native_path}/rdb/src/rdb_local_db_observer.cpp", + "${relational_store_native_path}/rdb/src/rdb_obs_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_perfStat.cpp", "${relational_store_native_path}/rdb/src/rdb_predicates.cpp", "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_log.cpp", "${relational_store_native_path}/rdb/src/rdb_sql_statistic.cpp", "${relational_store_native_path}/rdb/src/rdb_sql_utils.cpp", "${relational_store_native_path}/rdb/src/rdb_store.cpp", @@ -43,6 +49,7 @@ base_sources = [ "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", "${relational_store_native_path}/rdb/src/step_result_set.cpp", "${relational_store_native_path}/rdb/src/string_utils.cpp", + "${relational_store_native_path}/rdb/src/suspender.cpp", "${relational_store_native_path}/rdb/src/trans_db.cpp", "${relational_store_native_path}/rdb/src/transaction.cpp", "${relational_store_native_path}/rdb/src/transaction_impl.cpp", @@ -67,9 +74,10 @@ if (is_ohos && !build_ohos_sdk) { include_dirs = [ "include", "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb_crypt", "${relational_store_native_path}/rdb/include", "${relational_store_native_path}/dfx/include", - "${relational_store_native_path}/rdb_device_manager_adapter/include", + "${relational_store_native_path}/obs_mgr_adapter", ] defines = [ @@ -83,11 +91,6 @@ if (is_ohos && !build_ohos_sdk) { defined(global_parts_info.distributeddatamgr_arkdata_database_core)) { defines += [ "ARKDATA_DATABASE_CORE_ENABLE" ] } - include_dirs += [ - "${kvstore_path}/common", - "${kvstore_interface_path}", - "${distributedfile_path}/mod_securitylabel", - ] } config("native_rdb_public_config") { @@ -97,6 +100,8 @@ if (is_ohos && !build_ohos_sdk) { "include", "${relational_store_native_path}/rdb/include", "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", + "${relational_store_innerapi_path}/appdatafwk/include", "../cloud_data/include", "../common_type/include", ] @@ -138,27 +143,24 @@ if (is_ohos && !build_ohos_sdk) { "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", "${relational_store_native_path}/rdb/src/task_executor.cpp", - "${relational_store_native_path}/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp", ] - public_deps = [ + deps = [ "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", "${relational_store_innerapi_path}/appdatafwk:relational_common_base", ] external_deps = [ - "ability_base:zuri", - "ability_runtime:dataobs_manager", - "access_token:libaccesstoken_sdk", "c_utils:utils", - "device_manager:devicemanagersdk", + "file_api:securitylabel", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", - "huks:libhukssdk", "ipc:ipc_core", + "json:nlohmann_json_static", "kv_store:database_utils", - "kv_store:distributeddb", + "kv_store:datamgr_common", + "kv_store:distributeddb_client", "samgr:samgr_proxy", "sqlite:sqlite", "sqlite:sqliteicu", @@ -211,7 +213,6 @@ if (is_ohos && !build_ohos_sdk) { "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", "${relational_store_native_path}/rdb/src/task_executor.cpp", - "${relational_store_native_path}/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp", ] public_deps = [ @@ -220,18 +221,16 @@ if (is_ohos && !build_ohos_sdk) { ] external_deps = [ - "ability_base:zuri", - "ability_runtime:dataobs_manager", - "access_token:libaccesstoken_sdk", "c_utils:utils", - "device_manager:devicemanagersdk", + "file_api:securitylabel", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", - "huks:libhukssdk", "ipc:ipc_core", + "json:nlohmann_json_static", "kv_store:database_utils", - "kv_store:distributeddb", + "kv_store:datamgr_common", + "kv_store:distributeddb_client", "samgr:samgr_proxy", "sqlite:sqlite", "sqlite:sqliteicu", @@ -248,6 +247,7 @@ if (is_ohos && !build_ohos_sdk) { include_dirs = [ "${relational_store_mock_path}/frameworks/native/rdb", + "${relational_store_mock_path}/frameworks/native/rdb/common", "${relational_store_mock_path}/frameworks/native/win32", "mock/include", "${relational_store_common_path}/include", @@ -255,8 +255,10 @@ if (is_ohos && !build_ohos_sdk) { "//commonlibrary/c_utils/base/include", "include", "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "${relational_store_native_path}/rdb_crypt", "${relational_store_native_path}/rdb/include", "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", "//third_party/libuv/src/win", ] @@ -273,6 +275,7 @@ if (is_ohos && !build_ohos_sdk) { include_dirs += [ "//foundation/distributeddatamgr/kv_store/frameworks/common", "//third_party/sqlite/include", + "//third_party/json/single_include", ] libs = [ "//prebuilts/mingw-w64/ohos/linux-x86_64/clang-mingw/x86_64-w64-mingw32/lib/libws2_32.a" ] } @@ -304,6 +307,7 @@ if (is_ohos && !build_ohos_sdk) { deps = [ "${relational_store_innerapi_path}/appdatafwk:relational_common_base", "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_windows", + "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner_executor", "//third_party/sqlite:sqlite_sdk", ] @@ -327,6 +331,7 @@ if (is_ohos && !build_ohos_sdk) { deps = [ "${relational_store_innerapi_path}/appdatafwk:relational_common_base", "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_windows", + "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner_executor", "//third_party/sqlite:sqlite_sdk", ] cflags_cc = [ "-std=c++17" ] @@ -342,14 +347,17 @@ if (is_ohos && !build_ohos_sdk) { include_dirs = [ "${relational_store_mock_path}/frameworks/native/rdb", + "${relational_store_mock_path}/frameworks/native/rdb/common", "mock/include", "${relational_store_common_path}/include", "${relational_store_native_path}/rdb/mock/include", "//commonlibrary/c_utils/base/include", "include", "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "${relational_store_native_path}/rdb_crypt", "${relational_store_native_path}/rdb/include", "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", ] cflags = [ "-includemock.h" ] @@ -365,6 +373,7 @@ if (is_ohos && !build_ohos_sdk) { include_dirs += [ "//foundation/distributeddatamgr/kv_store/frameworks/common", "//third_party/sqlite/include", + "//third_party/json/single_include", ] } @@ -393,6 +402,7 @@ if (is_ohos && !build_ohos_sdk) { deps = [ "${relational_store_innerapi_path}/appdatafwk:relational_common_base", "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_mac", + "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner_executor", "//third_party/sqlite:sqlite_sdk", ] cflags_cc = [ "-std=c++17" ] @@ -415,6 +425,7 @@ if (is_ohos && !build_ohos_sdk) { deps = [ "${relational_store_innerapi_path}/appdatafwk:relational_common_base", "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_mac", + "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner_executor", "//third_party/sqlite:sqlite_sdk", ] cflags_cc = [ "-std=c++17" ] @@ -430,13 +441,16 @@ if (is_ohos && !build_ohos_sdk) { include_dirs = [ "${relational_store_mock_path}/frameworks/native/rdb", + "${relational_store_mock_path}/frameworks/native/rdb/common", "${distributedfile_path}/mod_securitylabel", "${relational_store_common_path}/include", "${relational_store_innerapi_path}/rdb/mock/include", "${relational_store_native_path}/rdb/mock/include", "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/rdb_crypt", "${relational_store_native_path}/rdb/include", "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", ] cflags = [ "-includemock.h" ] @@ -455,9 +469,11 @@ if (is_ohos && !build_ohos_sdk) { "${relational_store_native_path}/mock/rdb/include", "${relational_store_native_path}/rdb/include", "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", "../cloud_data/include", "../common_type/include", "//commonlibrary/c_utils/base/include", + "//third_party/json/single_include", ] } @@ -481,6 +497,7 @@ if (is_ohos && !build_ohos_sdk) { deps = [ "${relational_store_innerapi_path}/appdatafwk:relational_common_base", "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_android", + "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner_executor", "//third_party/sqlite:sqlite_static", ] cflags_cc = [ "-std=c++17" ] @@ -494,13 +511,16 @@ if (is_ohos && !build_ohos_sdk) { include_dirs = [ "${relational_store_mock_path}/frameworks/native/rdb", + "${relational_store_mock_path}/frameworks/native/rdb/common", "${distributedfile_path}/mod_securitylabel", "${relational_store_common_path}/include", "${relational_store_innerapi_path}/rdb/mock/include", "${relational_store_native_path}/rdb/mock/include", "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/rdb_crypt", "${relational_store_native_path}/rdb/include", "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", ] cflags = [ "-includemock.h" ] @@ -518,9 +538,11 @@ if (is_ohos && !build_ohos_sdk) { "include", "${relational_store_native_path}/rdb/include", "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", "../cloud_data/include", "../common_type/include", "//commonlibrary/c_utils/base/include", + "//third_party/json/single_include", ] } @@ -543,6 +565,7 @@ if (is_ohos && !build_ohos_sdk) { deps = [ "${relational_store_innerapi_path}/appdatafwk:relational_common_base", "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_ios", + "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner_executor", "//third_party/sqlite:sqlite_static", ] diff --git a/relational_store/interfaces/inner_api/rdb/include/abs_predicates.h b/relational_store/interfaces/inner_api/rdb/include/abs_predicates.h index 104f3c07aa5849167261dde8e38c83902208f9d9..47bfa0ef6bf9b068f808b70e68a2715db506f6a7 100644 --- a/relational_store/interfaces/inner_api/rdb/include/abs_predicates.h +++ b/relational_store/interfaces/inner_api/rdb/include/abs_predicates.h @@ -45,7 +45,6 @@ public: BUTT }; - API_EXPORT std::string GetStatement() const; API_EXPORT std::string GetWhereClause() const; API_EXPORT void SetWhereClause(const std::string &whereClause); [[deprecated("Use GetBindArgs() instead.")]] @@ -64,6 +63,7 @@ public: API_EXPORT bool IsNeedAnd() const; API_EXPORT bool IsSorted() const; API_EXPORT bool HasSpecificField() const; + API_EXPORT std::string GetHaving() const; public: API_EXPORT virtual void Clear(); @@ -82,6 +82,7 @@ public: API_EXPORT virtual AbsPredicates *Like(const std::string &field, const std::string &value); API_EXPORT virtual AbsPredicates *NotLike(const std::string &field, const std::string &value); API_EXPORT virtual AbsPredicates *Glob(const std::string &field, const std::string &value); + API_EXPORT virtual AbsPredicates *NotGlob(const std::string &field, const std::string &value); API_EXPORT virtual AbsPredicates *Between( const std::string &field, const ValueObject &low, const ValueObject &high); API_EXPORT virtual AbsPredicates *NotBetween( @@ -104,6 +105,9 @@ public: [[deprecated("Use NotIn(const std::string &, const std::vector &) instead.")]] API_EXPORT virtual AbsPredicates *NotIn(const std::string &field, const std::vector &values); API_EXPORT virtual AbsPredicates *NotIn(const std::string &field, const std::vector &values); + API_EXPORT virtual AbsPredicates *Having( + const std::string &conditions, const std::vector &values = {}); + API_EXPORT virtual std::string GetStatement() const; private: static constexpr const char *LOG_ORIGIN_FIELD = "#_flag"; @@ -113,6 +117,7 @@ private: std::string order; std::string group; std::string index; + std::string havingClause; int limit; int offset; bool distinct; diff --git a/relational_store/interfaces/inner_api/rdb/include/abs_rdb_predicates.h b/relational_store/interfaces/inner_api/rdb/include/abs_rdb_predicates.h index b99b5c99a81f12c5eb121c98a9c2305c4e936c02..05694fb3e4df30ae159d55a3eed0f18ea2e27c78 100644 --- a/relational_store/interfaces/inner_api/rdb/include/abs_rdb_predicates.h +++ b/relational_store/interfaces/inner_api/rdb/include/abs_rdb_predicates.h @@ -49,7 +49,7 @@ public: API_EXPORT ~AbsRdbPredicates() override {} /** - * @brief Initalzie AbsRdbPredicates object. + * @brief Clear AbsRdbPredicates object. */ API_EXPORT void Clear() override; @@ -213,6 +213,13 @@ public: */ API_EXPORT AbsRdbPredicates *Glob(const std::string &field, const std::string &value) override; + /** + * @brief Adds an Glob condition to the remote AbsRdbPredicates. + * + * This method is similar to glob of the SQL statement. + */ + API_EXPORT AbsRdbPredicates *NotGlob(const std::string &field, const std::string &value) override; + /** * @brief Adds an Distinct condition to the remote AbsRdbPredicates. * @@ -313,6 +320,8 @@ public: */ API_EXPORT virtual void SetJoinCount(int joinCount); + API_EXPORT std::string GetStatement() const override; + static constexpr const char *LOCK_STATUS = "#_status"; static constexpr int LOCKED = 2; static constexpr int LOCK_CHANGED = 3; diff --git a/relational_store/interfaces/inner_api/rdb/include/cache_result_set.h b/relational_store/interfaces/inner_api/rdb/include/cache_result_set.h index 219637c3b52d01f007a0a563ce86c4955ae258cd..49298201608db48c0865654e3d3e2380c5268ec7 100644 --- a/relational_store/interfaces/inner_api/rdb/include/cache_result_set.h +++ b/relational_store/interfaces/inner_api/rdb/include/cache_result_set.h @@ -41,6 +41,10 @@ namespace NativeRdb { */ class API_EXPORT CacheResultSet : public ResultSet { public: + /** + * @brief Constructor. + */ + API_EXPORT CacheResultSet(); /** * @brief Constructor. */ diff --git a/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h b/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h index 7d3138638b7a58c27b6a8bcaec88bb3b9349ca29..7238f001bd0d53cb4fb2db8139b98a981dfbbe38 100644 --- a/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h +++ b/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h @@ -60,12 +60,18 @@ enum class IResultSetInterfaceCode { enum class KvStoreInterfaceCode { GET_FEATURE_INTERFACE = 0, REGISTER_DEATH_OBSERVER, + FEATURE_EXIT = 3, }; enum class CloudKvStoreInterfaceCode { GET_FEATURE_INTERFACE = 0 }; +enum class ICloudNotifierInterfaceCode { + CLOUD_NOTIFIER_CMD_SYNC_COMPLETE = 0, + CLOUD_NOTIFIER_CMD_MAX +}; + enum class RdbServiceInterfaceCode { RDB_SERVICE_CMD_OBTAIN_TABLE, RDB_SERVICE_CMD_INIT_NOTIFIER, diff --git a/relational_store/interfaces/inner_api/rdb/include/knowledge_types.h b/relational_store/interfaces/inner_api/rdb/include/knowledge_types.h new file mode 100644 index 0000000000000000000000000000000000000000..a4079f410044d2ee25e22d72a85ddaeb88551de5 --- /dev/null +++ b/relational_store/interfaces/inner_api/rdb/include/knowledge_types.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2025 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 DISTRIBUTED_RDB_KNOWLEDGE_TYPES_H +#define DISTRIBUTED_RDB_KNOWLEDGE_TYPES_H + +#include +#include +#include +#include "rdb_store_config.h" + +namespace OHOS::DistributedRdb { + +constexpr int DEFAULT_CHUNK_SIZE = 3072; +constexpr int DEFAULT_SEGMENT_SIZE = 300; +constexpr double DEFAULT_OVERLAP_RATIO = 0.1; +constexpr int DEFAULT_TEXT_EMBEDDING_MAX_CNT = 50; +constexpr int DEFAULT_IMAGE_EMBEDDING_MAX_CNT = 10; +constexpr int DEFAULT_PARSE_FILE_MAX_CNT = 10; + +struct RdbKnowledgeParser { + std::string type; + std::string path; +}; + +struct RdbKnowledgeField { + std::string columnName; + std::vector type; + std::vector parser; + std::string description; +}; + +struct RdbKnowledgeTable { + std::string tableName; + std::string tokenizer; + std::vector referenceFields; + std::vector knowledgeFields; + std::unordered_map> pipelineHandlers; +}; + +struct RdbKnowledgeProcess { + struct { + std::string modelVersion; + } embeddingModelCfgs; + struct { + int chunkSize{DEFAULT_CHUNK_SIZE}; + int segmentSize{DEFAULT_SEGMENT_SIZE}; + double overlapRatio{DEFAULT_OVERLAP_RATIO}; + } chunkSplitter; + struct { + int textEmbeddingMaxCnt{DEFAULT_TEXT_EMBEDDING_MAX_CNT}; + int imageEmbeddingMaxCnt{DEFAULT_IMAGE_EMBEDDING_MAX_CNT}; + int parseFileMaxCnt{DEFAULT_PARSE_FILE_MAX_CNT}; + } perRecordLimit; +}; + +struct RdbKnowledgeSchema { + int64_t version = 0; + std::string dbName; + std::vector tables; + RdbKnowledgeProcess knowledgeProcess; +}; + +class API_EXPORT IKnowledgeSchemaManager { +public: + API_EXPORT virtual ~IKnowledgeSchemaManager() = default; + + /** + * @brief Init with database config and schema. + */ + API_EXPORT virtual void Init(const NativeRdb::RdbStoreConfig &config, + const DistributedRdb::RdbKnowledgeSchema &schema) = 0; + + /** + * @brief Start build knowledge data task. + */ + API_EXPORT virtual void StartTask(const std::string &dbName) = 0; + + /** + * @brief Stop build knowledge data task. + */ + API_EXPORT virtual void StopTask(const std::string &dbName) = 0; + + /** + * @brief Get rdb knowledge schema. + */ + API_EXPORT virtual std::shared_ptr GetRdbKnowledgeSchema(const std::string &dbName) = 0; +}; +} +#endif // DISTRIBUTED_RDB_KNOWLEDGE_TYPES_H \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_common.h b/relational_store/interfaces/inner_api/rdb/include/rdb_common.h index f2897ee3234a4fbb257ae1579813d3ecb1faed46..16383629e1466af19f69ab3cfff18349c8c84456 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_common.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_common.h @@ -42,16 +42,17 @@ enum RebuiltType : uint32_t { enum SlaveStatus : uint32_t { UNDEFINED, - DB_NOT_EXITS, BACKING_UP, BACKUP_INTERRUPT, BACKUP_FINISHED, + DB_CLOSING, }; enum ExchangeStrategy : uint32_t { NOT_HANDLE, BACKUP, RESTORE, + PENDING_BACKUP, }; } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h b/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h index 04beefee28037860e088ea8ceeb9f05f6be2c9a6..c15e6b0a2d932b3c8673f46b0bcb314673b3b321 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h @@ -406,7 +406,7 @@ static constexpr int E_SQLITE_SCHEMA = (E_BASE + 0x48); static constexpr int E_CANCEL = (E_BASE + 0x49); /** - * @brief The key parameter is invalid. + * @brief The secret key is corrupted or lost. */ static constexpr int E_INVALID_SECRET_KEY = (E_BASE + 0x4a); @@ -425,46 +425,6 @@ static constexpr int E_INNER_WARNING = (E_BASE + 0x4c); */ static constexpr int E_SQLITE_NOT_DB = (E_BASE + 0x4d); -/** - * @brief The root key of the encrypted database is faulty. - */ -static constexpr int E_ROOT_KEY_FAULT = (E_BASE + 0x4e); - -/** - * @brief The root key of the encrypted database cannot be loaded. - */ -static constexpr int E_ROOT_KEY_NOT_LOAD = (E_BASE + 0x4f); - -/** - * @brief The working key of the encrypted database is faulty. - */ -static constexpr int E_WORK_KEY_FAIL = (E_BASE + 0x50); - -/** - * @brief Failed to encrypt the working key. - */ -static constexpr int E_WORK_KEY_ENCRYPT_FAIL = (E_BASE + 0x51); - -/** - * @brief Failed to decrypt the working key. - */ -static constexpr int E_WORK_KEY_DECRYPT_FAIL = (E_BASE + 0x52); - -/** - * @brief Failed to open the sqlite database using the working key. - */ -static constexpr int E_SET_ENCRYPT_FAIL = (E_BASE + 0x53); - -/** - * @brief Failed to open the sqlite database using the working new key. - */ -static constexpr int E_SET_NEW_ENCRYPT_FAIL = (E_BASE + 0x54); - -/** - * @brief Failed to open the sqlite database using the working service key. - */ -static constexpr int E_SET_SERVICE_ENCRYPT_FAIL = (E_BASE + 0x55); - /** * @brief Database WAL file check point failed. */ diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_helper.h b/relational_store/interfaces/inner_api/rdb/include/rdb_helper.h index bf425e1d90397b648ba4a7d84ccd1d2be5ecfb40..27526166bc329e65faa81f7aa31d5ae54e8e7319 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_helper.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_helper.h @@ -72,6 +72,26 @@ public: * @return Returns {@code true} if the custom tokenizer is supported; returns {@code false} otherwise. */ API_EXPORT static bool IsSupportedTokenizer(Tokenizer tokenizer); + + struct DestroyOption { + bool cleanOpenSSL = false; + bool cleanICU = false; + }; + /** + * @brief initialization resources. + * + * @note Create pool initialization resources. + */ + API_EXPORT static bool Init(); + + /** + * @brief Clean up resources before dlclose. + * + * @note This interface is only used to release resources before calling dlclose, and can only be called before + * actually uninstalling rdb. Please manually release all resources obtained from rdb (rdbStore, resultSet, + * transaction, etc.) before calling, and then dlopen again to use them normally + */ + API_EXPORT static bool Destroy(const DestroyOption &option = { false, false }); }; } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_open_callback.h b/relational_store/interfaces/inner_api/rdb/include/rdb_open_callback.h index 7d30983569341e03cbf89aabddc8246a0fc9f134..87c55dfcc1e1fa5e48bf7e14a7e84b4a7fb98e1b 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_open_callback.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_open_callback.h @@ -75,6 +75,11 @@ public: { return 0; } + + /** + * @brief Virtual destructor to ensure proper cleanup of derived class objects. + */ + virtual ~RdbOpenCallback() = default; }; } // namespace NativeRdb diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h index 0ff7932453436484240f847097d3592743ecfc09..fac046672bdbb7d457493e4f99d61fbc4382bd81 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h @@ -20,6 +20,7 @@ #include #include "distributeddata_relational_store_ipc_interface_code.h" +#include "iremote_object.h" #include "rdb_notifier.h" #include "rdb_types.h" #include "result_set.h" @@ -38,7 +39,8 @@ public: using ResultSet = NativeRdb::ResultSet; inline static constexpr const char *SERVICE_NAME = "relational_store"; - virtual std::string ObtainDistributedTableName(const std::string &device, const std::string &table) = 0; + virtual std::string ObtainDistributedTableName( + const RdbSyncerParam ¶m, const std::string &device, const std::string &table) = 0; virtual int32_t SetDistributedTables(const RdbSyncerParam ¶m, const std::vector &tables, const std::vector &references, bool isRebuild, int32_t type = DISTRIBUTED_DEVICE) = 0; @@ -47,10 +49,10 @@ public: const AsyncDetail &async) = 0; virtual int32_t Subscribe( - const RdbSyncerParam ¶m, const SubscribeOption &option, RdbStoreObserver *observer) = 0; + const RdbSyncerParam ¶m, const SubscribeOption &option, std::shared_ptr observer) = 0; virtual int32_t UnSubscribe( - const RdbSyncerParam ¶m, const SubscribeOption &option, RdbStoreObserver *observer) = 0; + const RdbSyncerParam ¶m, const SubscribeOption &option, std::shared_ptr observer) = 0; virtual int32_t RegisterAutoSyncCallback( const RdbSyncerParam ¶m, std::shared_ptr observer) = 0; @@ -95,6 +97,8 @@ public: virtual int32_t VerifyPromiseInfo(const RdbSyncerParam ¶m) = 0; virtual int32_t ReportStatistic(const RdbSyncerParam ¶m, const RdbStatEvent &statEvent) = 0; + + virtual ~RdbService() = default; }; } // namespace DistributedRdb } // namespace OHOS diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_sql_utils.h b/relational_store/interfaces/inner_api/rdb/include/rdb_sql_utils.h index fb5475c94d1ee5530a72a4d5c69af1c345171df2..038bd14286e0876e2dbafc794f87180d8d4e19c2 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_sql_utils.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_sql_utils.h @@ -15,10 +15,27 @@ #ifndef NATIVE_RDB_SQL_UTILS_H #define NATIVE_RDB_SQL_UTILS_H +#include +#include #include "abs_rdb_predicates.h" +#include "rdb_common.h" +#include "rdb_predicates.h" +#include "values_bucket.h" +#include "value_object.h" namespace OHOS { namespace NativeRdb { +struct SqlInfo { + std::string sql; + std::vector args; +}; + +using Values = std::vector; +using Row = ValuesBucket; +using Rows = std::vector; +using Fields = std::vector; +using Resolution = ConflictResolution; + class API_EXPORT RdbSqlUtils { public: /** @@ -47,6 +64,13 @@ public: * @brief build query sql string. */ static std::string BuildQueryString(const AbsRdbPredicates &predicates, const std::vector &columns); + + static std::pair GetInsertSqlInfo(const std::string &table, const Row &row, Resolution resolution); + static std::pair GetUpdateSqlInfo(const AbsRdbPredicates &predicates, const Row &row, + Resolution resolution, const std::vector &returningFields = {}); + static std::pair GetDeleteSqlInfo( + const AbsRdbPredicates &predicates, const std::vector &returningFields = {}); + static std::pair GetQuerySqlInfo(const AbsRdbPredicates &predicates, const Fields &columns); }; } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_store.h b/relational_store/interfaces/inner_api/rdb/include/rdb_store.h index 03f56597aa712f0bf26686fae6860a90dfdbbb37..6dc118213c81c49b60a24abce263721456bdff40 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_store.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_store.h @@ -28,6 +28,7 @@ #include "rdb_errno.h" #include "rdb_store_config.h" #include "rdb_types.h" +#include "knowledge_types.h" #include "result_set.h" #include "transaction.h" #include "value_object.h" @@ -80,6 +81,11 @@ public: */ using DetailProgressObserver = DistributedRdb::DetailProgressObserver; + /** + * @brief Use RdbKnowledgeSchema replace DistributedRdb::RdbKnowledgeSchema namespace. + */ + using RdbKnowledgeSchema = DistributedRdb::RdbKnowledgeSchema; + /** * @brief Use Date replace DistributedRdb::Date namespace. */ @@ -204,8 +210,23 @@ public: * @param values Indicates the rows of data {@link ValuesBuckets} to be inserted into the table. * @param resolution Indicates the {@link ConflictResolution} to insert data into the table. */ - virtual std::pair BatchInsertWithConflictResolution( - const std::string &table, const RefRows &rows, Resolution resolution); + virtual std::pair BatchInsert(const std::string &table, const RefRows &rows, Resolution resolution); + + /** + * @brief Inserts a batch of data into the target table. + * + * @param table Indicates the target table. + * @param rows Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param returningFields Indicates the returning fields. + * @param resolution Indicates the {@link ConflictResolution} to insert data into the table. + * @return Return the inserted result. Contains error codes, affected rows, + * and returningField values for inserting data + * @warning 1. When using returningField, it is not recommended to use the ON_CONFLICT_FAIL strategy. This will + * result in returned results that do not match expectations. 2.When the number of affected rows exceeds 1024, + * only the first 1024 returningFields will be returned + */ + virtual std::pair BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution = NO_ACTION); /** * @brief Updates data in the database based on specified conditions. @@ -240,6 +261,23 @@ public: */ virtual int Update(int &changedRows, const Row &row, const AbsRdbPredicates &predicates); + /** + * @brief Updates data in the database based on a a specified instance object of AbsRdbPredicates. + * + * @param row Indicates the row of data to be updated in the database. + * The key-value pairs are associated with column names of the database table. + * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. + * @param returningFields Indicates the returning fields. + * @param resolution Indicates the {@link ConflictResolution} to insert data into the table. + * @return Return the updated result. Contains error code, number of affected rows, + * and value of returningField after update + * @warning 1. When using returningField, it is not recommended to use the ON_CONFLICT_FAIL strategy. This will + * result in returned results that do not match expectations. 2.When the number of affected rows exceeds 1024, + * only the first 1024 returningFields will be returned + */ + virtual std::pair Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution = NO_ACTION); + /** * @brief Updates data in the database based on specified conditions. * @@ -306,8 +344,19 @@ public: * @param args Indicates the where arguments. */ virtual int Delete( - int &deletedRows, const std::string &table, const std::string &whereClause = "", const Values &args = {}) = 0; + int &deletedRows, const std::string &table, const std::string &whereClause = "", const Values &args = {}); + /** + * @brief Deletes data from the database based on a specified instance object of AbsRdbPredicates. + * + * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. + * @param returningFields Indicates the returning fields. + * @return Return the deleted result. Contains error code, number of affected rows, + * and value of returningField before delete + * @warning When the number of affected rows exceeds 1024, only the first 1024 returningFields will be returned. + */ + virtual std::pair Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields = {}); /** * @brief Queries data in the database based on specified conditions. * @@ -366,7 +415,7 @@ public: * * @param sql Indicates the SQL statement to execute. * @param args Indicates the selection arguments. - * @param preCount IIndicates whether to calculate the count during query. + * @param preCount Indicates whether to calculate the count during query. */ virtual std::shared_ptr QueryByStep(const std::string &sql, const Values &args = {}, bool preCount = true) = 0; @@ -376,7 +425,7 @@ public: * * @param predicates Indicates the specified query condition by the instance object of {@link AbsRdbPredicates}. * @param columns Indicates the columns to query. If the value is empty array, the query applies to all columns. - * @param preCount IIndicates whether to calculate the count during query. + * @param preCount Indicates whether to calculate the count during query. */ virtual std::shared_ptr QueryByStep(const AbsRdbPredicates &predicates, const Fields &columns = {}, bool preCount = true); @@ -418,6 +467,17 @@ public: */ virtual std::pair Execute(const std::string &sql, const Values &args = {}, int64_t trxId = 0); + /** + * @brief Executes an SQL statement that contains specified parameters and + * get two values of type int and ValueObject. + * + * @param sql Indicates the SQL statement to execute. + * @param returningField Indicates the fieldName of result. + * @param args Indicates the {@link ValueObject} values of the parameters in the SQL statement. + * @return Return the result. Contains error code, number of affected rows, and value of returningField + */ + virtual std::pair ExecuteExt(const std::string &sql, const Values &args = {}); + /** * @brief Executes an SQL statement that contains specified parameters and get a long integer value. * @@ -460,6 +520,15 @@ public: */ virtual int Backup(const std::string &databasePath, const std::vector &encryptKey = {}); + /** + * @brief Restores a database from a specified encrypted or unencrypted database file. + * + * @param databasePath Indicates the database file path. + * @param encryptKey Indicates the database encrypt key. + * @param verifyDb Indicates whether to check the integrity of the database. + */ + virtual int Backup(const std::string &databasePath, const std::vector &encryptKey, bool verifyDb); + /** * @brief Attaches a database. * @@ -538,6 +607,13 @@ public: */ virtual bool IsReadOnly() const; + /** + * @brief Changes the key used to encrypt the database. + * + * @param Crypto parameters + */ + virtual int32_t Rekey(const RdbStoreConfig::CryptoParam &cryptoParam); + /** * @brief Check the current database is memory database. */ @@ -597,12 +673,12 @@ public: /** * @brief Subscribe to event changes. */ - virtual int Subscribe(const SubscribeOption &option, RdbStoreObserver *observer); + virtual int Subscribe(const SubscribeOption &option, std::shared_ptr observer); /** * @brief UnSubscribe to event changes. */ - virtual int UnSubscribe(const SubscribeOption &option, RdbStoreObserver *observer); + virtual int UnSubscribe(const SubscribeOption &option, std::shared_ptr observer); /** * @brief SubscribeObserver to event changes. @@ -702,6 +778,26 @@ public: */ virtual int SetSearchable(bool isSearchable); + virtual int CleanDirtyLog(const std::string &table, uint64_t cursor = 0); + + virtual int InitKnowledgeSchema(const RdbKnowledgeSchema &schema); + + /** + * @brief Support for collations in different languages. + * + * @param locale Represents Language related to the locale, for example, zh. + * The value complies with the ISO 639 standard. + */ + virtual int ConfigLocale(const std::string &localeStr); + + /** + * @brief Register a customized cluster algo to db + * + * @param clstAlgoName name of function + * @param func ptr of function + */ + virtual int RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func); + protected: virtual std::string GetLogTableName(const std::string &tableName); }; diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h b/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h index 56416e4b4fdfef456c731028cfdbcd756ae9f6f9..d3e4a677b43e73398821a6f88b4bc44b9c309562 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h @@ -218,20 +218,20 @@ public: bool Get(RegisterType type) { uint8_t bit = type % sizeof(uint8_t); - std::lock_guard LockGuard(mutex_); + std::lock_guard lockGuard(mutex_); return (1 << bit) & info_; } void Set(RegisterType type, bool state) { uint8_t bit = type % sizeof(uint8_t); - std::lock_guard LockGuard(mutex_); + std::lock_guard lockGuard(mutex_); info_ |= 1 << bit; } bool operator==(const RegisterInfo& info) { - std::lock_guard LockGuard(mutex_); + std::lock_guard lockGuard(mutex_); return info_ == info.info_; } private: @@ -239,6 +239,32 @@ private: std::mutex mutex_; }; +struct CollatorLocales { + CollatorLocales() + { + locales_ = ""; + } + explicit CollatorLocales(const CollatorLocales &collatorLocales) + { + locales_ = collatorLocales.Get(); + } + std::string Get() const + { + std::lock_guard lockGuard(localesMutex_); + return locales_; + } + + void Set(const std::string &locales) + { + std::lock_guard lockGuard(localesMutex_); + locales_ = locales; + } + +private: + std::string locales_; + mutable std::mutex localesMutex_; +}; + /** * @brief Use DistributedType replace OHOS::DistributedRdb::RdbDistributedType. */ @@ -262,6 +288,30 @@ struct PromiseInfo { std::vector permissionNames_ = {}; }; +struct ClstAlgoParaT { + /* Input Parameters */ + uint16_t featureDim; // Feature vector dimension, currently supports 256D only + uint32_t oldFeaturesNum; // Number of historical cluster center vectors + float *oldFeatures; // Array of historical cluster center vectors, + // stored in row-major order (length: oldFeaturesNum * dim) + const int32_t *oldClstGroupId; // Cluster ID for each historical vector (length: oldFeaturesNum) + const int32_t *oldClstVecNum; // Number of vectors in each historical cluster (length: oldFeaturesNum) + + uint32_t newFeaturesNum; // Number of newly collected vectors + float *newFeatures; // Array of new feature vectors + // stored in row-major order (length: newFeaturesNum * dim) + int32_t newClusterIdStart; // Starting cluster ID for new clusters, usually the maximum old cluster ID plus one + + /* Customization Parameters */ + void *customParams; // Developers need to communicate with the database development team before using it + + /* Output Parameters */ + int32_t *clusterResult; // Clustering result array, indicating the assigned cluster ID for each new vector + // (length: newFeaturesNum) +}; + +using ClusterAlgoFunc = int32_t (*)(ClstAlgoParaT *para); + /** * Manages relational database configurations. */ @@ -280,6 +330,12 @@ public: API_EXPORT CryptoParam(); API_EXPORT ~CryptoParam(); API_EXPORT bool IsValid() const; + bool Equal(const CryptoParam &other) const + { + bool baseEqual = encryptAlgo == other.encryptAlgo && hmacAlgo == other.hmacAlgo && + kdfAlgo == other.kdfAlgo && cryptoPageSize == other.cryptoPageSize; + return (other.iterNum == 0) ? baseEqual : (iterNum == other.iterNum && baseEqual); + } }; /** @@ -562,6 +618,8 @@ public: void RestoreEncryptKey(const std::vector &encryptKey) const; + void ResetEncryptKey(const std::vector &encryptKey) const; + /** * @brief Obtains the encrypt key in this {@code StoreConfig} object. */ @@ -615,7 +673,7 @@ public: /** * @brief Obtains the cryptoParam field in this {@code StoreConfig} object. */ - bool IsLocalOnly() const; + bool IsCustomEncryptParam() const; /** * @brief Set the isVector field in this {@code StoreConfig} object. @@ -748,7 +806,7 @@ public: std::string GetCollatorLocales() const; - void SetCollatorLocales(const std::string &loacles); + void SetCollatorLocales(const std::string &locales) const; int32_t GetHaMode() const; @@ -768,10 +826,6 @@ public: void EnableRekey(bool enable); - int GetNcandidates() const; - - void SetNcandidates(int ncandidates); - std::string ToString() const; static std::string FormatCfg(const RdbStoreConfig &first, const RdbStoreConfig &second); @@ -781,6 +835,10 @@ public: bool GetRegisterInfo(RegisterType type) const; bool IsEqualRegisterInfo(const RdbStoreConfig& config) const; + + void SetEnableSemanticIndex(bool enableSemanticIndex); + + bool GetEnableSemanticIndex() const; private: void ClearEncryptKey(); int32_t GenerateEncryptedKey() const; @@ -793,7 +851,8 @@ private: bool isAutoClean_ = true; bool isVector_ = false; bool autoRekey_ = false; - bool localOnly_ = false; + bool customEncryptParam_ = false; + bool enableSemanticIndex_ = false; int32_t journalSize_; int32_t pageSize_; int32_t readConSize_ = 4; @@ -819,7 +878,7 @@ private: ssize_t checkpointSize_; ssize_t startCheckpointSize_; int32_t clearMemorySize_; - std::string loacles_; + mutable CollatorLocales collatorLocales_; // distributed rdb std::string bundleName_; std::string moduleName_; @@ -829,7 +888,6 @@ private: mutable std::vector newEncryptKey_{}; std::map customScalarFunctions_; std::vector pluginLibs_{}; - int ncandidates_ = 128; static constexpr int MAX_TIMEOUT = 300; // seconds static constexpr int MIN_TIMEOUT = 1; // seconds diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h index 2f2d68f5d59c2267ae318f3ad571ff6176b6ab97..c3b0bc160762507b801c6c5a790d21352cb8bfa0 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h @@ -24,7 +24,10 @@ #include #include -namespace OHOS::DistributedRdb { +#include "values_buckets.h" + +namespace OHOS { +namespace DistributedRdb { enum RdbStatus { RDB_OK, RDB_ERROR, @@ -231,6 +234,7 @@ enum RdbPredicateOperator { NOT_CONTAINS, NOT_LIKE, ASSETS_ONLY, + NOT_GLOB, OPERATOR_MAX }; @@ -371,6 +375,7 @@ struct Field { struct RdbChangeProperties { bool isTrackedDataChange = false; bool isP2pSyncDataChange = false; + bool isKnowledgeDataChange = false; }; struct RdbChangedData { @@ -389,5 +394,27 @@ public: virtual ~SqlObserver() = default; virtual void OnStatistic(const SqlExecutionInfo &info) = 0; }; -} // namespace OHOS::DistributedRdb + +class SqlErrorObserver { +public: + struct ExceptionMessage { + int32_t code = 0; + std::string message; + std::string sql; + }; + virtual ~SqlErrorObserver() = default; + virtual void OnErrorLog(const ExceptionMessage &message) = 0; +}; +} // namespace DistributedRdb +namespace NativeRdb { +class ResultSet; +struct Results { + Results(int32_t count) : changed(count) + { + } + int32_t changed = -1; + std::shared_ptr results; +}; +} // namespace NativeRdb +} // namespace OHOS #endif \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/include/task_executor.h b/relational_store/interfaces/inner_api/rdb/include/task_executor.h similarity index 79% rename from relational_store/frameworks/native/rdb/include/task_executor.h rename to relational_store/interfaces/inner_api/rdb/include/task_executor.h index 4f3d8d27555dc3cbc32991b97490bb98bbf934b2..ee89412bda9e6008dd2fee8de00b04861d3d8974 100644 --- a/relational_store/frameworks/native/rdb/include/task_executor.h +++ b/relational_store/interfaces/inner_api/rdb/include/task_executor.h @@ -15,7 +15,10 @@ #ifndef DISTRIBUTED_NATIVE_RDB_TASK_EXECUTOR_H #define DISTRIBUTED_NATIVE_RDB_TASK_EXECUTOR_H #include "executor_pool.h" -namespace OHOS::NativeRdb { +#include "rdb_visibility.h" +namespace OHOS { +//class ExecutorPool; +namespace NativeRdb { class TaskExecutor { public: using TaskId = ExecutorPool::TaskId; @@ -23,17 +26,20 @@ public: using Duration = std::chrono::steady_clock::duration; static constexpr TaskId INVALID_TASK_ID = ExecutorPool::INVALID_TASK_ID; - static TaskExecutor &GetInstance(); + API_EXPORT static TaskExecutor &GetInstance(); std::shared_ptr GetExecutor(); - void SetExecutor(std::shared_ptr executor); + API_EXPORT void SetExecutor(std::shared_ptr executor); + void Init(); + bool Stop(); private: size_t MAX_THREADS = 2; size_t MIN_THREADS = 0; TaskExecutor(); ~TaskExecutor(); - mutable std::shared_mutex rwMutex_; + std::mutex mutex_; std::shared_ptr pool_; }; -} // namespace OHOS::NativeRdb +} // namespace NativeRdb +} // namespace OHOS #endif // DISTRIBUTED_DATA_TASK_EXECUTOR_H diff --git a/relational_store/interfaces/inner_api/rdb/include/transaction.h b/relational_store/interfaces/inner_api/rdb/include/transaction.h index 04563e9ba390f49a1c3e7e266758cfea5d2a81eb..eb8804471d4a107f051aac4237f10bce79f1954c 100644 --- a/relational_store/interfaces/inner_api/rdb/include/transaction.h +++ b/relational_store/interfaces/inner_api/rdb/include/transaction.h @@ -77,7 +77,7 @@ public: int32_t type, std::shared_ptr connection, const std::string &)>; static std::pair> Create( - int32_t type, std::shared_ptr connection, const std::string &name); + int32_t type, std::shared_ptr connection, const std::string &path); static int32_t RegisterCreator(Creator creator); virtual ~Transaction() = default; @@ -119,9 +119,24 @@ public: * @param rows Indicates the rows of data {@link RefRows} to be inserted into the table. * @param resolution Indicates the {@link ConflictResolution} to insert data into the table. */ - virtual std::pair BatchInsertWithConflictResolution( - const std::string &table, const RefRows &rows, Resolution resolution) = 0; + virtual std::pair BatchInsert( + const std::string &table, const RefRows &rows, Resolution resolution); + /** + * @brief Inserts a batch of data into the target table. + * + * @param table Indicates the target table. + * @param rows Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param returningFields Indicates the returning fields. + * @param resolution Indicates the {@link ConflictResolution} to insert data into the table. + * @return Return the inserted result. Contains error codes, affected rows, + * and returningField values for inserting data + * @warning 1. When using returningField, it is not recommended to use the ON_CONFLICT_FAIL strategy. This will + * result in returned results that do not match expectations. 2.When the number of affected rows exceeds 1024, + * only the first 1024 returningFields will be returned + */ + virtual std::pair BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution = NO_ACTION); /** * @brief Updates data in the database based on specified conditions. * @@ -132,7 +147,7 @@ public: * @param args Indicates the where arguments. */ virtual std::pair Update(const std::string &table, const Row &row, const std::string &where = "", - const Values &args = {}, Resolution resolution = NO_ACTION) = 0; + const Values &args = {}, Resolution resolution = NO_ACTION); /** * @brief Updates data in the database based on a a specified instance object of AbsRdbPredicates. @@ -142,7 +157,24 @@ public: * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. */ virtual std::pair Update( - const Row &row, const AbsRdbPredicates &predicates, Resolution resolution = NO_ACTION) = 0; + const Row &row, const AbsRdbPredicates &predicates, Resolution resolution = NO_ACTION); + + /** + * @brief Updates data in the database based on a a specified instance object of AbsRdbPredicates. + * + * @param row Indicates the row of data to be updated in the database. + * The key-value pairs are associated with column names of the database table. + * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. + * @param returningFields Indicates the returning fields. + * @param resolution Indicates the {@link ConflictResolution} to insert data into the table. + * @return Return the updated result. Contains error code, number of affected rows, + * and value of returningField after update + * @warning 1. When using returningField, it is not recommended to use the ON_CONFLICT_FAIL strategy. This will + * result in returned results that do not match expectations. 2.When the number of affected rows exceeds 1024, + * only the first 1024 returningFields will be returned + */ + virtual std::pair Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution = NO_ACTION); /** * @brief Deletes data from the database based on specified conditions. @@ -152,21 +184,33 @@ public: * @param args Indicates the where arguments. */ virtual std::pair Delete( - const std::string &table, const std::string &whereClause = "", const Values &args = {}) = 0; + const std::string &table, const std::string &whereClause = "", const Values &args = {}); /** * @brief Deletes data from the database based on a specified instance object of AbsRdbPredicates. * * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. */ - virtual std::pair Delete(const AbsRdbPredicates &predicates) = 0; + virtual std::pair Delete(const AbsRdbPredicates &predicates); + + /** + * @brief Deletes data from the database based on a specified instance object of AbsRdbPredicates. + * + * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. + * @param returningFields Indicates the returning fields. + * @return Return the deleted result. Contains error code, number of affected rows, + * and value of returningField before delete + * @warning When the number of affected rows exceeds 1024, only the first 1024 returningFields will be returned. + */ + virtual std::pair Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields); /** * @brief Queries data in the database based on SQL statement. * * @param sql Indicates the SQL statement to execute. * @param args Indicates the selection arguments. - * @param preCount IIndicates whether to calculate the count during query. + * @param preCount Indicates whether to calculate the count during query. */ virtual std::shared_ptr QueryByStep(const std::string &sql, const Values &args = {}, bool preCount = true) = 0; @@ -176,7 +220,7 @@ public: * * @param predicates Indicates the specified query condition by the instance object of {@link AbsRdbPredicates}. * @param columns Indicates the columns to query. If the value is empty array, the query applies to all columns. - * @param preCount IIndicates whether to calculate the count during query. + * @param preCount Indicates whether to calculate the count during query. */ virtual std::shared_ptr QueryByStep(const AbsRdbPredicates &predicates, const Fields &columns = {}, bool preCount = true) = 0; @@ -188,7 +232,17 @@ public: * @param sql Indicates the SQL statement to execute. * @param args Indicates the {@link ValueObject} values of the parameters in the SQL statement. */ - virtual std::pair Execute(const std::string &sql, const Values &args = {}) = 0; + virtual std::pair Execute(const std::string &sql, const Values &args = {}); + + /** + * @brief Executes an SQL statement that contains specified parameters and + * get two values of type int and ValueObject. + * + * @param sql Indicates the SQL statement to execute. + * @param args Indicates the {@link ValueObject} values of the parameters in the SQL statement. + * @warning When the number of affected rows exceeds 1024, only the first 1024 returningFields will be returned. + */ + virtual std::pair ExecuteExt(const std::string &sql, const Values &args = {}); private: static inline Creator creator_; diff --git a/relational_store/interfaces/inner_api/rdb/include/values_bucket.h b/relational_store/interfaces/inner_api/rdb/include/values_bucket.h index f8250d763ee8edaa76bcc03f46ef0e793d4118ee..0981de32f809654bd13343cc2a787369901d10af 100644 --- a/relational_store/interfaces/inner_api/rdb/include/values_bucket.h +++ b/relational_store/interfaces/inner_api/rdb/include/values_bucket.h @@ -113,6 +113,14 @@ public: */ API_EXPORT void Put(const std::string &columnName, const ValueObject &value); + /** + * @brief Put the integer double bool string bytes asset asset and so on + * to this {@code ValuesBucket} object for the given column name. + * + * @param columnName Indicates the name of the column. + */ + API_EXPORT void Put(const std::string &columnName, ValueObject &&value); + /** * @brief Delete the ValueObject object for the given column name. * diff --git a/relational_store/interfaces/inner_api/rdb/include/values_buckets.h b/relational_store/interfaces/inner_api/rdb/include/values_buckets.h index e776b9fb6ebd2986524daa70e7128a394a8fbc9f..beb146052877c2f91270ceee72716c42790c2d48 100644 --- a/relational_store/interfaces/inner_api/rdb/include/values_buckets.h +++ b/relational_store/interfaces/inner_api/rdb/include/values_buckets.h @@ -34,13 +34,19 @@ public: using BucketType = std::map>; API_EXPORT ValuesBuckets(); + API_EXPORT ValuesBuckets(const std::vector &rows); + API_EXPORT ValuesBuckets(std::vector &&rows) noexcept; API_EXPORT size_t RowSize() const; API_EXPORT std::pair GetFieldsAndValues() const; + API_EXPORT void Reserve(int32_t size); API_EXPORT void Put(const ValuesBucket &bucket); + API_EXPORT void Put(ValuesBucket &&bucket); API_EXPORT std::pair Get(size_t row, const FieldType &field) const; + API_EXPORT void Clear(); + private: FieldsType fields_; ValuesType values_; diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h b/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h index a239f28fbd8845057152836414db14b12a574a2f..8fd52182177c18433b0d3886d6da69fee8322939 100644 --- a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h +++ b/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h @@ -21,6 +21,10 @@ #include #include #include + +#include "rdb_types.h" +#include "rdb_visibility.h" + namespace OHOS::NativeRdb { enum class IntegrityCheck { NONE, @@ -128,20 +132,20 @@ public: bool Get(RegisterType type) { uint8_t bit = type % sizeof(uint8_t); - std::lock_guard LockGuard(mutex_); + std::lock_guard lockGuard(mutex_); return (1 << bit) & info_; } void Set(RegisterType type, bool state) { uint8_t bit = type % sizeof(uint8_t); - std::lock_guard LockGuard(mutex_); + std::lock_guard lockGuard(mutex_); info_ |= 1 << bit; } bool operator==(const RegisterInfo& info) { - std::lock_guard LockGuard(mutex_); + std::lock_guard lockGuard(mutex_); return info_ == info.info_; } private: @@ -149,6 +153,32 @@ private: std::mutex mutex_; }; +struct CollatorLocales { + CollatorLocales() + { + locales_ = ""; + } + explicit CollatorLocales(const CollatorLocales &collatorLocales) + { + locales_ = collatorLocales.Get(); + } + std::string Get() const + { + std::lock_guard lockGuard(localesMutex_); + return locales_; + } + + void Set(const std::string &locales) + { + std::lock_guard lockGuard(localesMutex_); + locales_ = locales; + } + +private: + std::string locales_; + mutable std::mutex localesMutex_; +}; + using ScalarFunction = std::function &)>; struct ScalarFunctionInfo { @@ -164,6 +194,30 @@ struct PromiseInfo { std::vector permissionNames_ = {}; }; +struct ClstAlgoParaT { + /* Input Parameters */ + uint16_t featureDim; // Feature vector dimension, currently supports 256D only + uint32_t oldFeaturesNum; // Number of historical cluster center vectors + float *oldFeatures; // Array of historical cluster center vectors, + // stored in row-major order (length: oldFeaturesNum * dim) + const int32_t *oldClstGroupId; // Cluster ID for each historical vector (length: oldFeaturesNum) + const int32_t *oldClstVecNum; // Number of vectors in each historical cluster (length: oldFeaturesNum) + + uint32_t newFeaturesNum; // Number of newly collected vectors + float *newFeatures; // Array of new feature vectors + // stored in row-major order (length: newFeaturesNum * dim) + int32_t newClusterIdStart; // Starting cluster ID for new clusters, usually the maximum old cluster ID plus one + + /* Customization Parameters */ + void *customParams; // Developers need to communicate with the database development team before using it + + /* Output Parameters */ + int32_t *clusterResult; // Clustering result array, indicating the assigned cluster ID for each new vector + // (length: newFeaturesNum) +}; + +using ClusterAlgoFunc = int32_t (*)(ClstAlgoParaT *para); + class RdbStoreConfig { public: struct CryptoParam { @@ -197,7 +251,7 @@ public: bool IsReadOnly() const; bool IsMemoryRdb() const; - bool IsLocalOnly() const; + bool IsCustomEncryptParam() const; std::string GetDatabaseFileType() const; SecurityLevel GetSecurityLevel() const; void SetEncryptStatus(const bool status); @@ -238,6 +292,7 @@ public: void SetReadConSize(int readConSize); void SetEncryptKey(const std::vector &encryptKey); void RestoreEncryptKey(const std::vector &encryptKey) const; + void ResetEncryptKey(const std::vector &encryptKey) const; std::vector GetEncryptKey() const; void ChangeEncryptKey() const; std::vector GetNewEncryptKey() const; @@ -313,7 +368,7 @@ public: int32_t GetClearMemorySize() const; void SetClearMemorySize(int32_t size); std::string GetCollatorLocales() const; - void SetCollatorLocales(const std::string &loacles); + void SetCollatorLocales(const std::string &locales) const; int32_t GetSubUser() const; void SetSubUser(int32_t subUser); void SetHaMode(int32_t haMode); @@ -322,13 +377,13 @@ public: CryptoParam GetCryptoParam() const; void SetJournalMode(const std::string &journalMode); void EnableRekey(bool enable); - int GetNcandidates() const; - void SetNcandidates(int ncandidates); std::string ToString() const; static std::string FormatCfg(const RdbStoreConfig &first, const RdbStoreConfig &second); void SetRegisterInfo(RegisterType type, bool state) const; bool GetRegisterInfo(RegisterType type) const; bool IsEqualRegisterInfo(const RdbStoreConfig& config) const; + void SetEnableSemanticIndex(bool enableSemanticIndex); + bool GetEnableSemanticIndex() const; private: void ClearEncryptKey(); @@ -342,7 +397,8 @@ private: bool isAutoClean_ = true; bool isVector_ = false; bool autoRekey_ = false; - bool localOnly_ = false; + bool customEncryptParam_ = false; + bool enableSemanticIndex_ = false; int32_t journalSize_; int32_t pageSize_; int32_t readConSize_ = 4; @@ -368,7 +424,7 @@ private: ssize_t checkpointSize_; ssize_t startCheckpointSize_; int32_t clearMemorySize_; - std::string loacles_; + mutable CollatorLocales collatorLocales_; // distributed rdb std::string bundleName_; std::string moduleName_; @@ -378,7 +434,6 @@ private: mutable std::vector newEncryptKey_{}; std::map customScalarFunctions_; std::vector pluginLibs_{}; - int ncandidates_ = 128; static constexpr int MAX_TIMEOUT = 300; // seconds static constexpr int MIN_TIMEOUT = 1; // seconds diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/values_bucket.h b/relational_store/interfaces/inner_api/rdb/mock/include/values_bucket.h index 5aea40090ef2d7b0bfd1eac549a61e37dec05ddb..904d632dab17bbdde70b1997ed77d38122e8c536 100644 --- a/relational_store/interfaces/inner_api/rdb/mock/include/values_bucket.h +++ b/relational_store/interfaces/inner_api/rdb/mock/include/values_bucket.h @@ -109,6 +109,14 @@ public: */ void Put(const std::string &columnName, const ValueObject &value); + /** + * @brief Put the integer double bool string bytes asset asset and so on + * to this {@code ValuesBucket} object for the given column name. + * + * @param columnName Indicates the name of the column. + */ + void Put(const std::string &columnName, ValueObject &&value); + /** * @brief Delete the ValueObject object for the given column name. * diff --git a/relational_store/interfaces/inner_api/rdb_data_ability_adapter/BUILD.gn b/relational_store/interfaces/inner_api/rdb_data_ability_adapter/BUILD.gn index 8fdebcc47abcc9c69ae5dddb453c0fce4aeaeb8c..d55ed2d25c1be2382b4d87700569726f045c6617 100644 --- a/relational_store/interfaces/inner_api/rdb_data_ability_adapter/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb_data_ability_adapter/BUILD.gn @@ -20,10 +20,8 @@ config("rdb_data_ability_adapter_config") { } include_dirs = [ "include", - "${datashare_path}/common/include/", "${relational_store_innerapi_path}/rdb/include", "${relational_store_native_path}/rdb/include", - "${common_tool_path}/", ] } @@ -57,7 +55,13 @@ ohos_shared_library("rdb_data_ability_adapter") { "${relational_store_innerapi_path}/rdb:native_rdb", ] - external_deps = [ "c_utils:utils" ] + external_deps = [ + "c_utils:utils", + "data_share:datashare_common_lite", + "ipc:ipc_single", + "json:nlohmann_json_static", + "kv_store:datamgr_common", + ] public_configs = [ ":rdb_data_ability_adapter_public_config" ] diff --git a/relational_store/interfaces/inner_api/rdb_data_share_adapter/BUILD.gn b/relational_store/interfaces/inner_api/rdb_data_share_adapter/BUILD.gn index 13a5441150b83d27fc9f84fcd1431f37f45cbdd7..71d2d85604d4ccf456aabd1f5142c61fc97540f2 100644 --- a/relational_store/interfaces/inner_api/rdb_data_share_adapter/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb_data_share_adapter/BUILD.gn @@ -22,12 +22,10 @@ config("rdb_data_share_adapter_config") { } include_dirs = [ "include", - "${datashare_path}/common/include/", "${relational_store_common_path}/include", "${relational_store_innerapi_path}/rdb/include", "${relational_store_native_path}/rdb_data_share_adapter/include", "${relational_store_native_path}/rdb/include", - "${common_tool_path}/", ] } @@ -35,7 +33,6 @@ config("rdb_data_share_adapter_public_config") { visibility = [ ":*" ] include_dirs = [ "include", - "${datashare_path}/provider/include", ] } @@ -63,7 +60,10 @@ ohos_shared_library("rdb_data_share_adapter") { external_deps = [ "c_utils:utils", + "data_share:datashare_common_lite", "hilog:libhilog", + "json:nlohmann_json_static", + "kv_store:datamgr_common", ] public_configs = [ ":rdb_data_share_adapter_public_config" ] diff --git a/relational_store/interfaces/inner_api/rdb_data_share_adapter/include/rdb_utils.h b/relational_store/interfaces/inner_api/rdb_data_share_adapter/include/rdb_utils.h index 00c3741006501acf9e04793c04a3eda316c44538..7d3986a9b5ba830b0378cd5b07b04b0d6684c4ab 100644 --- a/relational_store/interfaces/inner_api/rdb_data_share_adapter/include/rdb_utils.h +++ b/relational_store/interfaces/inner_api/rdb_data_share_adapter/include/rdb_utils.h @@ -155,7 +155,7 @@ RDB_UTILS_DISABLE_WARNING("-Wc99-designator") [DataShare::SQL_IN] = &RdbUtils::In, [DataShare::NOT_IN] = &RdbUtils::NotIn, [DataShare::LIKE] = &RdbUtils::Like, - [DataShare::UNLIKE] = &RdbUtils::NoSupport, + [DataShare::UNLIKE] = &RdbUtils::NotLike, [DataShare::ORDER_BY_ASC] = &RdbUtils::OrderByAsc, [DataShare::ORDER_BY_DESC] = &RdbUtils::OrderByDesc, [DataShare::LIMIT] = &RdbUtils::Limit, diff --git a/relational_store/frameworks/js/napi/graphstore/BUILD.gn b/relational_store/interfaces/ndk/BUILD.gn similarity index 38% rename from relational_store/frameworks/js/napi/graphstore/BUILD.gn rename to relational_store/interfaces/ndk/BUILD.gn index e970ce11fb95b2d30b2beb91e7d6ee1378167075..58c8261d25c2dcdd51379c95a52d913ed481be67 100644 --- a/relational_store/frameworks/js/napi/graphstore/BUILD.gn +++ b/relational_store/interfaces/ndk/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2024 Huawei Device Co., Ltd. +# Copyright (c) 2023 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 @@ -14,7 +14,8 @@ import("//build/ohos.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") -ohos_shared_library("graphstore") { +ohos_shared_library("native_rdb_ndk") { + branch_protector_ret = "pac_ret" sanitize = { boundary_sanitize = true ubsan = true @@ -22,42 +23,46 @@ ohos_shared_library("graphstore") { cfi_cross_dso = true debug = false } - cflags_cc = [ "-fvisibility=hidden" ] + include_dirs = [ + "include", + "${relational_store_base_path}/interfaces/ndk", "${relational_store_common_path}/include", - "${relational_store_frameworks_path}/js/napi/common/include", - "${relational_store_frameworks_path}/js/napi/graphstore/include", - "${relational_store_native_path}/gdb/include", "${relational_store_native_path}/rdb/include", + "${relational_store_native_path}/dfx/include", ] sources = [ - "${relational_store_frameworks_path}/js/napi/common/src/js_ability.cpp", - "${relational_store_frameworks_path}/js/napi/common/src/js_scope.cpp", - "${relational_store_frameworks_path}/js/napi/common/src/js_utils.cpp", - "${relational_store_frameworks_path}/js/napi/common/src/js_uv_queue.cpp", - "${relational_store_frameworks_path}/js/napi/graphstore/src/entry_point.cpp", - "${relational_store_frameworks_path}/js/napi/graphstore/src/napi_async_call.cpp", - "${relational_store_frameworks_path}/js/napi/graphstore/src/napi_gdb_const_properties.cpp", - "${relational_store_frameworks_path}/js/napi/graphstore/src/napi_gdb_error.cpp", - "${relational_store_frameworks_path}/js/napi/graphstore/src/napi_gdb_js_utils.cpp", - "${relational_store_frameworks_path}/js/napi/graphstore/src/napi_gdb_store.cpp", - "${relational_store_frameworks_path}/js/napi/graphstore/src/napi_gdb_store_helper.cpp", - "${relational_store_frameworks_path}/js/napi/graphstore/src/napi_gdb_transaction.cpp", + "src/convertor_error_code.cpp", + "src/modify_time_cursor.cpp", + "src/oh_data_utils.cpp", + "src/oh_data_value.cpp", + "src/oh_data_values.cpp", + "src/oh_data_values_buckets.cpp", + "src/oh_rdb_crypto_param.cpp", + "src/oh_rdb_transaction.cpp", + "src/relational_asset.cpp", + "src/relational_cursor.cpp", + "src/relational_predicates.cpp", + "src/relational_predicates_objects.cpp", + "src/relational_store.cpp", + "src/relational_values_bucket.cpp", + ] + + defines = [ "API_EXPORT=__attribute__((visibility (\"default\")))" ] + + deps = [ + "${relational_store_base_path}/interfaces/rdb_ndk_utils:native_rdb_ndk_utils", + "${relational_store_innerapi_path}/rdb:native_rdb" ] - deps = [ "${relational_store_innerapi_path}/gdb:native_graphstore" ] + external_deps = [ - "ability_runtime:abilitykit_native", - "ability_runtime:extensionkit_native", - "ability_runtime:napi_base_context", "c_utils:utils", - "eventhandler:libeventhandler", "hilog:libhilog", - "hisysevent:libhisysevent", - "hitrace:hitrace_meter", - "napi:ace_napi", + "json:nlohmann_json_static", + "kv_store:datamgr_common", ] - subsystem_name = "distributeddatamgr" + relative_install_dir = "ndk" part_name = "relational_store" - relative_install_dir = "module/data" + subsystem_name = "distributeddatamgr" } diff --git a/relational_store/interfaces/ndk/include/oh_data_value.h b/relational_store/interfaces/ndk/include/oh_data_value.h index 59d4de3357277de5781af1a400d4685333619e61..d3ab007ca18ccfc686f4dcdba8bcb0110c6f3947 100644 --- a/relational_store/interfaces/ndk/include/oh_data_value.h +++ b/relational_store/interfaces/ndk/include/oh_data_value.h @@ -125,7 +125,7 @@ typedef struct OH_Data_Value OH_Data_Value; * @see OH_Value_Destroy. * @since 16 */ -OH_Data_Value *OH_Value_Create(); +OH_Data_Value *OH_Value_Create(void); /** * @brief Destroys an OH_Data_Value instance object. @@ -266,7 +266,8 @@ int OH_Value_GetType(OH_Data_Value *value, OH_ColumnType *type); * @brief Check whether the data is empty from OH_Data_Value object. * * @param value Represents a pointer to an instance of OH_Data_Value. - * @param val Represents empty data flag. It is an output parameter. Ture is empty, false is not empty. + * @param val Represents empty data flag. It is an output parameter. + * The value true means that the data is empty, and false means the opposite. * @return Returns the error code. * Returns {@link RDB_OK} if the execution is successful. * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. diff --git a/relational_store/interfaces/ndk/include/oh_data_values.h b/relational_store/interfaces/ndk/include/oh_data_values.h index 6f16bd72bce6eaf8c959c8bb3bcd7385a0b2ad6a..7075ea98dad02f247628a2251da46d2c43872ae4 100644 --- a/relational_store/interfaces/ndk/include/oh_data_values.h +++ b/relational_store/interfaces/ndk/include/oh_data_values.h @@ -62,7 +62,7 @@ typedef struct OH_Data_Values OH_Data_Values; * @see OH_Values_Destroy. * @since 16 */ -OH_Data_Values *OH_Values_Create(); +OH_Data_Values *OH_Values_Create(void); /** * @brief Destroys an OH_Data_Values instance object. @@ -243,7 +243,8 @@ int OH_Values_Get(OH_Data_Values *values, int index, OH_Data_Value **val); * * @param values Represents a pointer to an instance of OH_Data_Values. * @param index Represents the zero-based index of target data in values. - * @param val Represents empty data flag. It is an output parameter. Ture is empty, false is not empty. + * @param val Represents empty data flag. It is an output parameter. + * The value true means that the data is empty, and false means the opposite. * @return Returns the error code. * Returns {@link RDB_OK} if the execution is successful. * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. diff --git a/relational_store/interfaces/ndk/include/oh_data_values_buckets.h b/relational_store/interfaces/ndk/include/oh_data_values_buckets.h index e3cb1bcdb17bae741b10a6b983f69a6ac374d484..b32d76148353a81882d22bf104f17f8a4adaff14 100644 --- a/relational_store/interfaces/ndk/include/oh_data_values_buckets.h +++ b/relational_store/interfaces/ndk/include/oh_data_values_buckets.h @@ -61,7 +61,7 @@ typedef struct OH_Data_VBuckets OH_Data_VBuckets; * @see OH_VBuckets_Destroy. * @since 16 */ -OH_Data_VBuckets *OH_VBuckets_Create(); +OH_Data_VBuckets *OH_VBuckets_Create(void); /** * @brief Destroys an OH_Data_VBuckets instance object. @@ -99,7 +99,7 @@ int OH_VBuckets_PutRow(OH_Data_VBuckets *buckets, const OH_VBucket *row); int OH_VBuckets_PutRows(OH_Data_VBuckets *buckets, const OH_Data_VBuckets *rows); /** - * @brief Add an OH_Data_VBuckets to OH_Data_VBuckets object. + * @brief Gets the number of rows in OH_Data_VBuckets object. * * @param buckets Represents a pointer to an instance of OH_Data_VBuckets. * @param count Represents the count of OH_VBucket in OH_Data_VBuckets. It is an output parameter. diff --git a/relational_store/interfaces/ndk/include/oh_predicates.h b/relational_store/interfaces/ndk/include/oh_predicates.h index 28808e30ba072bae4ffa1ff8521c7abea8da7bdb..487f2967c84d7c0487423ed4819faf81599ee093 100644 --- a/relational_store/interfaces/ndk/include/oh_predicates.h +++ b/relational_store/interfaces/ndk/include/oh_predicates.h @@ -37,10 +37,12 @@ * @since 10 */ -#include #include -#include "oh_value_object.h" +#include + +#include "oh_data_values.h" +#include "oh_value_object.h" #ifdef __cplusplus extern "C" { #endif @@ -396,6 +398,60 @@ typedef struct OH_Predicates { int (*destroy)(OH_Predicates *predicates); } OH_Predicates; +/** + * @brief Sets the OH_Predicates to specify conditions to filter grouped results that will appear in the final result. + * + * @param predicates Represents a pointer to an instance of OH_Predicates. + * @param conditions Indicates filter conditions in the having clause. + * @param values Indicates a pointer to an instance of OH_Data_Values. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 +*/ +int OH_Predicates_Having(OH_Predicates *predicates, const char *conditions, const OH_Data_Values *values); + +/** + * @brief Sets the OH_Predicates to match the field whose data type is string and value is not like the specified value. + * This method is similar to "Not like" of the SQL statement. + * + * @param predicates Represents a pointer to an instance of OH_Predicates. + * @param field Indicates the column name in the database table. + * @param pattern Indicates the value to compare against. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 +*/ +int OH_Predicates_NotLike(OH_Predicates *predicates, const char *field, const char *pattern); + +/** + * @brief Sets the OH_Predicates to match the specified field whose data type is string and the value contains + * a wildcard. Different from like, the input parameters of this method are case-sensitive. + * + * @param predicates Represents a pointer to an instance of OH_Predicates. + * @param field Indicates the column name in the database table. + * @param pattern Indicates the value to match with the predicate. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 +*/ +int OH_Predicates_Glob(OH_Predicates *predicates, const char *field, const char *pattern); + +/** + * @brief Sets the OH_Predicates to not match the specified field whose data type is string and the value contains + * a wildcard. Different from not like, the input parameters of this method are case-sensitive. + * + * @param predicates Represents a pointer to an instance of OH_Predicates. + * @param field Indicates the column name in the database table. + * @param pattern Indicates the value to compare against. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 +*/ +int OH_Predicates_NotGlob(OH_Predicates *predicates, const char *field, const char *pattern); #ifdef __cplusplus }; #endif diff --git a/relational_store/interfaces/ndk/include/oh_rdb_crypto_param.h b/relational_store/interfaces/ndk/include/oh_rdb_crypto_param.h new file mode 100644 index 0000000000000000000000000000000000000000..3968b60754de8c8f0b6c1d2204e5edcc625df5c7 --- /dev/null +++ b/relational_store/interfaces/ndk/include/oh_rdb_crypto_param.h @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2025 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. + */ + +/** + * @addtogroup RDB + * @{ + * + * @brief The relational database (RDB) store manages data based on relational models. + * With the underlying SQLite database, the RDB store provides a complete mechanism for managing local databases. + * To satisfy different needs in complicated scenarios, the RDB store offers a series of APIs for performing operations + * such as adding, deleting, modifying, and querying data, and supports direct execution of SQL statements. + * + * @since 10 + */ + +/** + * @file oh_rdb_crypto_param.h + * + * @brief Provides functions and enumerations related to cryptographic parameters of the relational database. + * + * @kit ArkData + * @library libnative_rdb_ndk.z.so + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * + * @since 20 + */ + +#ifndef OH_RDB_CRYPTO_PARAM_H +#define OH_RDB_CRYPTO_PARAM_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Enumerates the database encryption algorithms. + * + * @since 20 + */ +typedef enum Rdb_EncryptionAlgo { + /** + * @brief Indicates the database is encrypted using RDB_AES_256_GCM. + * + * @since 20 + */ + RDB_AES_256_GCM = 0, + /** + * @brief Indicates the database is encrypted using RDB_AES_256_CBC. + * + * @since 20 + */ + RDB_AES_256_CBC, +} Rdb_EncryptionAlgo; + +/** + * @brief Enumerates the supported HMAC algorithm when opening a database. + * + * @since 20 + */ +typedef enum Rdb_HmacAlgo { + /** + * @brief RDB_HMAC_SHA1 algorithm. + * + * @since 20 + */ + RDB_HMAC_SHA1 = 0, + /** + * @brief RDB_HMAC_SHA256 algorithm. + * + * @since 20 + */ + RDB_HMAC_SHA256, + /** + * @brief RDB_HMAC_SHA512 algorithm. + * + * @since 20 + */ + RDB_HMAC_SHA512, +} Rdb_HmacAlgo; + +/** + * @brief Enumerates the supported KDF algorithm when opening a database. + * + * @since 20 + */ +typedef enum Rdb_KdfAlgo { + /** + * @brief RDB_KDF_SHA1 algorithm. + * + * @since 20 + */ + RDB_KDF_SHA1 = 0, + /** + * @brief RDB_KDF_SHA256 algorithm. + * + * @since 20 + */ + RDB_KDF_SHA256, + /** + * @brief RDB_KDF_SHA512 algorithm. + * + * @since 20 + */ + RDB_KDF_SHA512, +} Rdb_KdfAlgo; + +/** + * @brief Specifies the cryptographic parameters used when opening an encrypted database. + * + * @since 20 + */ +typedef struct OH_Rdb_CryptoParam OH_Rdb_CryptoParam; + +/** + * @brief Creates an OH_Rdb_CryptoParam instance object. + * + * @return Returns a pointer to OH_Rdb_CryptoParam instance when the execution is successful. + * Otherwise, nullptr is returned. The memory must be released through the OH_Rdb_DestroyCryptoParam + * interface after the use is complete. + * @see OH_Rdb_DestroyCryptoParam. + * @since 20 + */ +OH_Rdb_CryptoParam *OH_Rdb_CreateCryptoParam(void); + +/** + * @brief Destroys an OH_Rdb_CryptoParam instance object. + * + * @param param Represents a pointer to an instance of OH_Rdb_CryptoParam. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Rdb_DestroyCryptoParam(OH_Rdb_CryptoParam *param); + +/** + * @brief Sets key data to the OH_Rdb_CryptoParam object. + * + * @param param Represents a pointer to an instance of OH_Rdb_CryptoParam. + * @param key Represents a pointer to array data. + * @param length Represents the size of key array. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Crypto_SetEncryptionKey(OH_Rdb_CryptoParam *param, const uint8_t *key, int32_t length); + +/** + * @brief Sets the number of KDF iterations used when opening an encrypted database. + * + * @param param Represents a pointer to an instance of OH_Rdb_CryptoParam. + * @param iteration Represents a pointer to array data. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Crypto_SetIteration(OH_Rdb_CryptoParam *param, int64_t iteration); + +/** + * @brief Sets the encryption algorithm when opening an encrypted database. + * + * @param param Represents a pointer to an instance of OH_Rdb_CryptoParam. + * @param algo Represents the encryption algorithm. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Crypto_SetEncryptionAlgo(OH_Rdb_CryptoParam *param, int32_t algo); + +/** + * @brief Sets the HMAC algorithm when opening an encrypted database. + * + * @param param Represents a pointer to an instance of OH_Rdb_CryptoParam. + * @param algo Represents the HMAC algorithm. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Crypto_SetHmacAlgo(OH_Rdb_CryptoParam *param, int32_t algo); + +/** + * @brief Sets the KDF algorithm when opening an encrypted database. + * + * @param param Represents a pointer to an instance of OH_Rdb_CryptoParam. + * @param algo Represents the KDF algorithm. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Crypto_SetKdfAlgo(OH_Rdb_CryptoParam *param, int32_t algo); + +/** + * @brief Sets the page size used when opening an encrypted database. + * + * @param param Represents a pointer to an instance of OH_Rdb_CryptoParam. + * @param size Represents the page size. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Crypto_SetCryptoPageSize(OH_Rdb_CryptoParam *param, int64_t size); + +#ifdef __cplusplus +}; +#endif +#endif +/** @} */ diff --git a/relational_store/interfaces/ndk/include/oh_rdb_transaction.h b/relational_store/interfaces/ndk/include/oh_rdb_transaction.h index d8960c5239756fb97eaa9e9e964bf3aaf072e478..2067da26e044444723ca1e7930cddb0c3ed2f7a9 100644 --- a/relational_store/interfaces/ndk/include/oh_rdb_transaction.h +++ b/relational_store/interfaces/ndk/include/oh_rdb_transaction.h @@ -98,30 +98,30 @@ typedef struct OH_Rdb_Transaction OH_Rdb_Transaction; * @see OH_RdbTrans_DestroyOptions. * @since 16 */ -OH_RDB_TransOptions *OH_RdbTrans_CreateOptions(); +OH_RDB_TransOptions *OH_RdbTrans_CreateOptions(void); /** * @brief Destroys an OH_RDB_TransOptions instance object. * - * @param opitons Represents a pointer to an instance of OH_RDB_TransOptions. + * @param options Represents a pointer to an instance of OH_RDB_TransOptions. * @return Returns the error code. * Returns {@link RDB_OK} if the execution is successful. * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. * @since 16 */ -int OH_RdbTrans_DestroyOptions(OH_RDB_TransOptions *opitons); +int OH_RdbTrans_DestroyOptions(OH_RDB_TransOptions *options); /** - * @brief Sets integer data to the opitons object. + * @brief Sets integer data to the options object. * - * @param opitons Represents a pointer to an instance of OH_RDB_TransOptions. + * @param options Represents a pointer to an instance of OH_RDB_TransOptions. * @param type Represents relation database transaction type. * @return Returns the error code. * Returns {@link RDB_OK} if the execution is successful. * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. * @since 16 */ -int OH_RdbTransOption_SetType(OH_RDB_TransOptions *opitons, OH_RDB_TransType type); +int OH_RdbTransOption_SetType(OH_RDB_TransOptions *options, OH_RDB_TransType type); /** * @brief Commits a transaction of a relational database. @@ -191,6 +191,36 @@ int OH_RdbTrans_Rollback(OH_Rdb_Transaction *trans); */ int OH_RdbTrans_Insert(OH_Rdb_Transaction *trans, const char *table, const OH_VBucket *row, int64_t *rowId); +/** + * @brief Inserts a row of data into the target table and support conflict resolution. + * + * @param trans Represents a pointer to an instance of OH_Rdb_Transaction. + * @param table Represents the target table. + * @param row Represents the row data to be inserted into the table. + * @param resolution Represents the resolution when conflict occurs. + * @param rowId Represents row line number when insert successfully. + * @return Returns the status code of the execution. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_ERROR} database common error. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * Returns {@link RDB_E_ALREADY_CLOSED} database already closed. + * Returns {@link RDB_E_WAL_SIZE_OVER_LIMIT} the WAL file size over default limit. + * Returns {@link RDB_E_SQLITE_FULL} SQLite: The database is full. + * Returns {@link RDB_E_SQLITE_CORRUPT} database corrupted. + * Returns {@link RDB_E_SQLITE_PERM} SQLite: Access permission denied. + * Returns {@link RDB_E_SQLITE_BUSY} SQLite: The database file is locked. + * Returns {@link RDB_E_SQLITE_LOCKED} SQLite: A table in the database is locked. + * Returns {@link RDB_E_SQLITE_NOMEM} SQLite: The database is out of memory. + * Returns {@link RDB_E_SQLITE_READONLY} SQLite: Attempt to write a readonly database. + * Returns {@link RDB_E_SQLITE_IOERR} SQLite: Some kind of disk I/O error occurred. + * Returns {@link RDB_E_SQLITE_TOO_BIG} SQLite: TEXT or BLOB exceeds size limit. + * Returns {@link RDB_E_SQLITE_MISMATCH} SQLite: Data type mismatch. + * Returns {@link RDB_E_SQLITE_CONSTRAINT} SQLite: Abort due to constraint violation. + * @since 20 + */ +int OH_RdbTrans_InsertWithConflictResolution(OH_Rdb_Transaction *trans, const char *table, const OH_VBucket *row, + Rdb_ConflictResolution resolution, int64_t *rowId); + /** * @brief Inserts a batch of data into the target table. * @@ -248,6 +278,35 @@ int OH_RdbTrans_BatchInsert(OH_Rdb_Transaction *trans, const char *table, const */ int OH_RdbTrans_Update(OH_Rdb_Transaction *trans, const OH_VBucket *row, const OH_Predicates *predicates, int64_t *changes); +/** + * @brief Updates data in the database based on specified conditions and support conflict resolution. + * + * @param trans Represents a pointer to an instance of OH_Rdb_Transaction. + * @param row Represents the row data to be updated into the table. + * @param predicates Represents the specified update condition by the instance object of OH_Predicates. + * @param resolution Represents the resolution when conflict occurs. + * @param changes Represents the number of successful insertions. + * @return Returns the status code of the execution. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_ERROR} database common error. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * Returns {@link RDB_E_ALREADY_CLOSED} database already closed. + * Returns {@link RDB_E_WAL_SIZE_OVER_LIMIT} the WAL file size over default limit. + * Returns {@link RDB_E_SQLITE_FULL} SQLite: The database is full. + * Returns {@link RDB_E_SQLITE_CORRUPT} database corrupted. + * Returns {@link RDB_E_SQLITE_PERM} SQLite: Access permission denied. + * Returns {@link RDB_E_SQLITE_BUSY} SQLite: The database file is locked. + * Returns {@link RDB_E_SQLITE_LOCKED} SQLite: A table in the database is locked. + * Returns {@link RDB_E_SQLITE_NOMEM} SQLite: The database is out of memory. + * Returns {@link RDB_E_SQLITE_READONLY} SQLite: Attempt to write a readonly database. + * Returns {@link RDB_E_SQLITE_IOERR} SQLite: Some kind of disk I/O error occurred. + * Returns {@link RDB_E_SQLITE_TOO_BIG} SQLite: TEXT or BLOB exceeds size limit. + * Returns {@link RDB_E_SQLITE_MISMATCH} SQLite: Data type mismatch. + * Returns {@link RDB_E_SQLITE_CONSTRAINT} SQLite: Abort due to constraint violation. + * @since 20 + */ +int OH_RdbTrans_UpdateWithConflictResolution(OH_Rdb_Transaction *trans, const OH_VBucket *row, + const OH_Predicates *predicates, Rdb_ConflictResolution resolution, int64_t *changes); /** * @brief Deletes data from the database based on specified conditions diff --git a/relational_store/interfaces/ndk/include/relational_store.h b/relational_store/interfaces/ndk/include/relational_store.h index 5469911200637b80030f10a9330bd3d92bfb016e..d03f49b90387af5601393616538483d14180d7fd 100644 --- a/relational_store/interfaces/ndk/include/relational_store.h +++ b/relational_store/interfaces/ndk/include/relational_store.h @@ -43,6 +43,7 @@ #include "oh_values_bucket.h" #include "oh_rdb_transaction.h" #include "oh_rdb_types.h" +#include "oh_rdb_crypto_param.h" #ifdef __cplusplus extern "C" { @@ -319,6 +320,19 @@ int OH_Rdb_SetSecurityLevel(OH_Rdb_ConfigV2 *config, int securityLevel); */ int OH_Rdb_SetArea(OH_Rdb_ConfigV2 *config, int area); +/** + * @brief Set whether the database enable the capabilities for semantic indexing processing. + * + * @param config Represents a pointer to {@link OH_Rdb_ConfigV2} instance. + * Indicates the configuration of the database related to this RDB store. + * @param enableSemanticIndex Indicates whether the database enable the capabilities for semantic indexing processing. + * @return Returns the status code of the execution. Successful execution returns RDB_OK, + * {@link RDB_OK} - success. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * @since 20 + */ +int OH_Rdb_SetSemanticIndex(OH_Rdb_ConfigV2 *config, bool enableSemanticIndex); + /** * @brief Set property dbType into config * @param config Represents a pointer to {@link OH_Rdb_ConfigV2} instance. @@ -330,6 +344,56 @@ int OH_Rdb_SetArea(OH_Rdb_ConfigV2 *config, int area); * @since 14 */ int OH_Rdb_SetDbType(OH_Rdb_ConfigV2 *config, int dbType); + +/** + * @brief Sets the customized directory relative to the database. + * + * @param config Represents a pointer to a configuration of the database related to this relation database store. + * @param customDir Represents the customized relative to the database directory, the value cannot exceed 128 bytes. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Rdb_SetCustomDir(OH_Rdb_ConfigV2 *config, const char *customDir); + +/** + * @brief Sets the relation database store is read-only mode. + * + * @param config Represents a pointer to a configuration of the database related to this relation database store. + * @param readOnly Represents whether the relation database store is read-only. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Rdb_SetReadOnly(OH_Rdb_ConfigV2 *config, bool readOnly); + +/** + * @brief Sets the dynamic libraries with capabilities such as Full-Text Search (FTS). + * + * @param config Represents a pointer to a configuration of the database related to this relation database store. + * @param plugins Represents the dynamic libraries. + * @param length the size of plugins that the maximum value is 16. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Rdb_SetPlugins(OH_Rdb_ConfigV2 *config, const char **plugins, int32_t length); + +/** + * @brief Sets the custom encryption parameters. + * + * @param config Represents a pointer to a configuration of the database related to this relation database store. + * @param cryptoParam Represents the custom encryption parameters. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Rdb_SetCryptoParam(OH_Rdb_ConfigV2 *config, const OH_Rdb_CryptoParam *cryptoParam); + /** * @brief Check if a tokenizer is supported or not. * @@ -370,7 +434,7 @@ int OH_Rdb_SetPersistent(OH_Rdb_ConfigV2 *config, bool isPersistent); /** * @brief Get support db type list - * @param typeCount The output parameter, which is used to recieve the length of the support db type array. + * @param typeCount The output parameter, which is used to receive the length of the support db type array. * @return Return Rdb_DBType array contains supported db type, array length is number of support type * @since 14 */ @@ -499,6 +563,36 @@ int OH_Rdb_DeleteStoreV2(const OH_Rdb_ConfigV2 *config); */ int OH_Rdb_Insert(OH_Rdb_Store *store, const char *table, OH_VBucket *valuesBucket); +/** + * @brief Inserts a row of data into the target table and support conflict resolution. + * + * @param store Represents a pointer to an OH_Rdb_Store instance. + * @param table Represents the target table. + * @param row Represents the row data to be inserted into the table. + * @param resolution Represents the resolution when conflict occurs. + * @param rowId Represents the number of successful insertion. + * @return Returns the status code of the execution. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_ERROR} database common error. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * Returns {@link RDB_E_ALREADY_CLOSED} database already closed. + * Returns {@link RDB_E_WAL_SIZE_OVER_LIMIT} the WAL file size over default limit. + * Returns {@link RDB_E_SQLITE_FULL} SQLite: The database is full. + * Returns {@link RDB_E_SQLITE_CORRUPT} database corrupted. + * Returns {@link RDB_E_SQLITE_PERM} SQLite: Access permission denied. + * Returns {@link RDB_E_SQLITE_BUSY} SQLite: The database file is locked. + * Returns {@link RDB_E_SQLITE_LOCKED} SQLite: A table in the database is locked. + * Returns {@link RDB_E_SQLITE_NOMEM} SQLite: The database is out of memory. + * Returns {@link RDB_E_SQLITE_READONLY} SQLite: Attempt to write a readonly database. + * Returns {@link RDB_E_SQLITE_IOERR} SQLite: Some kind of disk I/O error occurred. + * Returns {@link RDB_E_SQLITE_TOO_BIG} SQLite: TEXT or BLOB exceeds size limit. + * Returns {@link RDB_E_SQLITE_MISMATCH} SQLite: Data type mismatch. + * Returns {@link RDB_E_SQLITE_CONSTRAINT} SQLite: Abort due to constraint violation. + * @since 20 + */ +int OH_Rdb_InsertWithConflictResolution(OH_Rdb_Store *store, const char *table, OH_VBucket *row, + Rdb_ConflictResolution resolution, int64_t *rowId); + /** * @brief Inserts a batch of data into the target table. * @@ -544,6 +638,35 @@ int OH_Rdb_BatchInsert(OH_Rdb_Store *store, const char *table, * @since 10 */ int OH_Rdb_Update(OH_Rdb_Store *store, OH_VBucket *valuesBucket, OH_Predicates *predicates); +/** + * @brief Updates data in the database based on specified conditions and support conflict resolution. + * + * @param store Represents a pointer to an OH_Rdb_Store instance. + * @param row Represents the row data to be inserted into the table. + * @param predicates Represents a pointer to an link OH_Predicates instance. + * @param resolution Represents the resolution when conflict occurs. + * @param changes Represents the number of successful update. + * @return Returns the status code of the execution. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_ERROR} database common error. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * Returns {@link RDB_E_ALREADY_CLOSED} database already closed. + * Returns {@link RDB_E_WAL_SIZE_OVER_LIMIT} the WAL file size over default limit. + * Returns {@link RDB_E_SQLITE_FULL} SQLite: The database is full. + * Returns {@link RDB_E_SQLITE_CORRUPT} database corrupted. + * Returns {@link RDB_E_SQLITE_PERM} SQLite: Access permission denied. + * Returns {@link RDB_E_SQLITE_BUSY} SQLite: The database file is locked. + * Returns {@link RDB_E_SQLITE_LOCKED} SQLite: A table in the database is locked. + * Returns {@link RDB_E_SQLITE_NOMEM} SQLite: The database is out of memory. + * Returns {@link RDB_E_SQLITE_READONLY} SQLite: Attempt to write a readonly database. + * Returns {@link RDB_E_SQLITE_IOERR} SQLite: Some kind of disk I/O error occurred. + * Returns {@link RDB_E_SQLITE_TOO_BIG} SQLite: TEXT or BLOB exceeds size limit. + * Returns {@link RDB_E_SQLITE_MISMATCH} SQLite: Data type mismatch. + * Returns {@link RDB_E_SQLITE_CONSTRAINT} SQLite: Abort due to constraint violation. + * @since 20 + */ +int OH_Rdb_UpdateWithConflictResolution(OH_Rdb_Store *store, OH_VBucket *row, OH_Predicates *predicates, + Rdb_ConflictResolution resolution, int64_t *changes); /** * @brief Deletes data from the database based on specified conditions. @@ -597,7 +720,7 @@ int OH_Rdb_Execute(OH_Rdb_Store *store, const char *sql); * @return Returns the status code of the execution. * {@link RDB_OK} - success. * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. - * {@link RDB_E_NOT_SUPPORTED} - The error code for not supprt. + * {@link RDB_E_NOT_SUPPORTED} - The error code for not support. * @see OH_Rdb_Store. * @since 14 */ @@ -659,7 +782,7 @@ int OH_Rdb_Commit(OH_Rdb_Store *store); * @return Returns the status code of the execution. * {@link RDB_OK} - success. * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. - * {@link RDB_E_NOT_SUPPORTED} - The error code for not supprt. + * {@link RDB_E_NOT_SUPPORTED} - The error code for not support. * @see OH_Rdb_Store. * @since 14 */ @@ -673,7 +796,7 @@ int OH_Rdb_BeginTransWithTrxId(OH_Rdb_Store *store, int64_t *trxId); * @return Returns the status code of the execution. * {@link RDB_OK} - success. * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. - * {@link RDB_E_NOT_SUPPORTED} - The error code for not supprt. + * {@link RDB_E_NOT_SUPPORTED} - The error code for not support. * @see OH_Rdb_Store. * @since 14 */ @@ -687,7 +810,7 @@ int OH_Rdb_RollBackByTrxId(OH_Rdb_Store *store, int64_t trxId); * @return Returns the status code of the execution. * {@link RDB_OK} - success. * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. - * {@link RDB_E_NOT_SUPPORTED} - The error code for not supprt. + * {@link RDB_E_NOT_SUPPORTED} - The error code for not support. * @see OH_Rdb_Store. * @since 14 */ @@ -1264,7 +1387,7 @@ int OH_Rdb_CloudSync(OH_Rdb_Store *store, Rdb_SyncMode mode, const char *tables[ * A callback will be invoked when there is a notification of the automatic synchronization progress. * * @param store Indicates the pointer to the target {@Link OH_Rdb_Store} instance. -* @param observer The {@link Rdb_SyncObserver} for the automatic synchornizaiton progress +* @param observer The {@link Rdb_SyncObserver} for the automatic synchronization progress * Indicates the callback invoked to return the automatic synchronization progress. * @return Returns the status code of the execution. See {@link OH_Rdb_ErrCode}. * {@link RDB_OK} - success. @@ -1402,6 +1525,85 @@ int OH_Rdb_ExecuteV2(OH_Rdb_Store *store, const char *sql, const OH_Data_Values */ OH_Cursor *OH_Rdb_ExecuteQueryV2(OH_Rdb_Store *store, const char *sql, const OH_Data_Values *args); +/** + * @brief Attaches a database file to the currently linked database. + * + * @param store Represents a pointer to an OH_Rdb_Store instance. + * @param config Represents a pointer to an OH_Rdb_ConfigV2 configuration of the database related to this RDB store. + * @param attachName Represents the alias of the database. + * @param waitTime Represents the maximum time allowed for attaching the database, valid range is 1 to 300. + * @param attachedNumber Represents the number of attached databases, It is an output parameter. + * @return Returns the status code of the execution. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_ERROR} database common error. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * Returns {@link RDB_E_ALREADY_CLOSED} database already closed. + * Returns {@link RDB_E_NOT_SUPPORTED} - The error code for not support. + * Returns {@link RDB_E_DATABASE_BUSY} database does not respond. + * Returns {@link RDB_E_SQLITE_FULL} SQLite: The database is full. + * Returns {@link RDB_E_SQLITE_CORRUPT} database corrupted. + * Returns {@link RDB_E_SQLITE_PERM} SQLite: Access permission denied. + * Returns {@link RDB_E_SQLITE_BUSY} SQLite: The database file is locked. + * Returns {@link RDB_E_SQLITE_LOCKED} SQLite: A table in the database is locked. + * Returns {@link RDB_E_SQLITE_NOMEM} SQLite: The database is out of memory. + * Returns {@link RDB_E_SQLITE_READONLY} SQLite: Attempt to write a readonly database. + * Returns {@link RDB_E_SQLITE_IOERR} SQLite: Some kind of disk I/O error occurred. + * Returns {@link RDB_E_SQLITE_TOO_BIG} SQLite: TEXT or BLOB exceeds size limit. + * Returns {@link RDB_E_SQLITE_MISMATCH} SQLite: Data type mismatch. + * Returns {@link RDB_E_SQLITE_CONSTRAINT} SQLite: Abort due to constraint violation. + * @since 20 + */ +int OH_Rdb_Attach(OH_Rdb_Store *store, const OH_Rdb_ConfigV2 *config, const char *attachName, int64_t waitTime, + size_t *attachedNumber); + +/** + * @brief Detaches a database from this database. + * + * @param store Represents a pointer to an OH_Rdb_Store instance. + * @param attachName Represents the alias of the database. + * @param waitTime Represents the maximum time allowed for detaching the database, valid range is 1 to 300. + * @param attachedNumber Represents the number of attached databases, It is an output parameter. + * @return Returns the status code of the execution. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_ERROR} database common error. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * Returns {@link RDB_E_ALREADY_CLOSED} database already closed. + * Returns {@link RDB_E_NOT_SUPPORTED} - The error code for not support. + * Returns {@link RDB_E_DATABASE_BUSY} database does not respond. + * Returns {@link RDB_E_SQLITE_FULL} SQLite: The database is full. + * Returns {@link RDB_E_SQLITE_CORRUPT} database corrupted. + * Returns {@link RDB_E_SQLITE_PERM} SQLite: Access permission denied. + * Returns {@link RDB_E_SQLITE_BUSY} SQLite: The database file is locked. + * Returns {@link RDB_E_SQLITE_LOCKED} SQLite: A table in the database is locked. + * Returns {@link RDB_E_SQLITE_NOMEM} SQLite: The database is out of memory. + * Returns {@link RDB_E_SQLITE_READONLY} SQLite: Attempt to write a readonly database. + * Returns {@link RDB_E_SQLITE_IOERR} SQLite: Some kind of disk I/O error occurred. + * Returns {@link RDB_E_SQLITE_TOO_BIG} SQLite: TEXT or BLOB exceeds size limit. + * Returns {@link RDB_E_SQLITE_MISMATCH} SQLite: Data type mismatch. + * Returns {@link RDB_E_SQLITE_CONSTRAINT} SQLite: Abort due to constraint violation. + * @see OH_Rdb_Store, OH_Rdb_ErrCode. + * @since 20 + */ +int OH_Rdb_Detach(OH_Rdb_Store *store, const char *attachName, int64_t waitTime, size_t *attachedNumber); + +/** + * @brief Support for collations in different languages. + * + * @param store Represents a pointer to an {@link OH_Rdb_Store} instance. + * @param locale Language related to the locale, for example, zh. The value complies with the ISO 639 standard. + * @return Returns a specific error code. + * {@link RDB_OK} if the execution is successful. + * {@link RDB_ERR} - Indicates that the function execution exception. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * {@link RDB_E_ALREADY_CLOSED} database already closed. + * {@link RDB_E_SQLITE_BUSY} SQLite: The database file is locked. + * {@link RDB_E_SQLITE_NOMEM} SQLite: The database is out of memory. + * Specific error codes can be referenced {@link OH_Rdb_ErrCode}. + * @see OH_Rdb_Store. + * @since 20 + */ +int OH_Rdb_SetLocale(OH_Rdb_Store *store, const char *locale); + #ifdef __cplusplus }; #endif diff --git a/relational_store/interfaces/ndk/relational_store_inner_types.h b/relational_store/interfaces/ndk/relational_store_inner_types.h new file mode 100644 index 0000000000000000000000000000000000000000..1faf3c9a0e739651a6537762b025a6d735ec64d4 --- /dev/null +++ b/relational_store/interfaces/ndk/relational_store_inner_types.h @@ -0,0 +1,42 @@ +/* +* Copyright (c) 2025 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 RELATIONAL_STORE_INNER_TYPES_H +#define RELATIONAL_STORE_INNER_TYPES_H +#include +#include + +#include "rdb_store_config.h" +#include "relational_store.h" +constexpr int RDB_CONFIG_V2_MAGIC_CODE = 0xDBCF2ADE; +struct OH_Rdb_ConfigV2 { + int magicNum = RDB_CONFIG_V2_MAGIC_CODE; + std::string dataBaseDir = ""; + std::string storeName = ""; + std::string bundleName = ""; + std::string moduleName = ""; + bool isEncrypt = false; + bool persist = true; + int securityLevel = 0; + int area = 0; + int dbType = RDB_SQLITE; + int token = RDB_NONE_TOKENIZER; + std::string customDir = ""; + bool readOnly = false; + std::vector pluginLibs{}; + OHOS::NativeRdb::RdbStoreConfig::CryptoParam cryptoParam; + bool enableSemanticIndex = false; +}; +#endif // RELATIONAL_STORE_INNER_TYPES_H diff --git a/relational_store/interfaces/ndk/src/oh_data_define.h b/relational_store/interfaces/ndk/src/oh_data_define.h index 425b9412d40f0b68bc8a385159a33fdef05841c3..8cfc07c4aeeaa3e1a4c96dafa8bf28613c4b2ac4 100644 --- a/relational_store/interfaces/ndk/src/oh_data_define.h +++ b/relational_store/interfaces/ndk/src/oh_data_define.h @@ -22,6 +22,7 @@ #include "transaction.h" #include "oh_predicates.h" #include "oh_rdb_transaction.h" +#include "rdb_store_config.h" struct OH_Rdb_Transaction { static constexpr int64_t OH_RDB_TRANS_ID = 0x10000000; @@ -62,4 +63,12 @@ struct OH_Data_VBuckets { std::vector rows_; bool IsValid() const; }; + +struct OH_Rdb_CryptoParam { + static constexpr int64_t OH_CRYPTO_PARAM_ID = 0x10005000; + int64_t id = OH_CRYPTO_PARAM_ID; + + OHOS::NativeRdb::RdbStoreConfig::CryptoParam cryptoParam; + bool IsValid() const; +}; #endif diff --git a/relational_store/interfaces/ndk/src/oh_data_value.cpp b/relational_store/interfaces/ndk/src/oh_data_value.cpp index 0c2993bb2578976087fae465f6b877578ea3399a..ec98e42d87c2e0c6bfc078abda27e29ddffcd506 100644 --- a/relational_store/interfaces/ndk/src/oh_data_value.cpp +++ b/relational_store/interfaces/ndk/src/oh_data_value.cpp @@ -58,7 +58,7 @@ static int CheckValueType(const OH_Data_Value *value, int32_t type) return RDB_OK; } -OH_Data_Value *OH_Value_Create() +OH_Data_Value *OH_Value_Create(void) { OH_Data_Value *value = new (std::nothrow) OH_Data_Value; if (value == nullptr) { diff --git a/relational_store/interfaces/ndk/src/oh_data_values.cpp b/relational_store/interfaces/ndk/src/oh_data_values.cpp index e284bb4d05ba2faf055bf423c37e5d57109dca84..5675ea95f3f7c8716d788dd675f1a27a585f2de9 100644 --- a/relational_store/interfaces/ndk/src/oh_data_values.cpp +++ b/relational_store/interfaces/ndk/src/oh_data_values.cpp @@ -42,7 +42,7 @@ static bool IsValidValuesElement(OH_Data_Values *values, int index) return true; } -OH_Data_Values *OH_Values_Create() +OH_Data_Values *OH_Values_Create(void) { OH_Data_Values *values = new (std::nothrow) OH_Data_Values; return values; diff --git a/relational_store/interfaces/ndk/src/oh_data_values_buckets.cpp b/relational_store/interfaces/ndk/src/oh_data_values_buckets.cpp index d1bdf1fc86fb207291f71b6fb8264cadc740d8b9..5be4eaf3a6cf0e631334da2b367f7d44c9b38a24 100644 --- a/relational_store/interfaces/ndk/src/oh_data_values_buckets.cpp +++ b/relational_store/interfaces/ndk/src/oh_data_values_buckets.cpp @@ -34,7 +34,7 @@ static bool IsValidVBuckets(const OH_Data_VBuckets *vbuckets) return ret; } -OH_Data_VBuckets *OH_VBuckets_Create() +OH_Data_VBuckets *OH_VBuckets_Create(void) { OH_Data_VBuckets *vbuckets = new (std::nothrow) OH_Data_VBuckets; if (vbuckets == nullptr) { diff --git a/relational_store/interfaces/ndk/src/oh_rdb_crypto_param.cpp b/relational_store/interfaces/ndk/src/oh_rdb_crypto_param.cpp new file mode 100644 index 0000000000000000000000000000000000000000..657ab9fd9f5581539481c591ecfa68570102e49e --- /dev/null +++ b/relational_store/interfaces/ndk/src/oh_rdb_crypto_param.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2025 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 "OhRdbCryptoParam" +#include "oh_rdb_crypto_param.h" +#include +#include "oh_data_define.h" +#include "relational_store_error_code.h" + +using namespace OHOS::DistributedRdb; +using namespace OHOS::NativeRdb; + +bool OH_Rdb_CryptoParam::IsValid() const +{ + return id == OH_CRYPTO_PARAM_ID; +} + +OH_Rdb_CryptoParam *OH_Rdb_CreateCryptoParam(void) +{ + OH_Rdb_CryptoParam *value = new (std::nothrow) OH_Rdb_CryptoParam; + if (value == nullptr) { + return nullptr; + } + return value; +} + +int OH_Rdb_DestroyCryptoParam(OH_Rdb_CryptoParam *cryptoParam) +{ + if (cryptoParam == nullptr || !cryptoParam->IsValid()) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + delete cryptoParam; + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Crypto_SetEncryptionKey(OH_Rdb_CryptoParam *param, const uint8_t *key, int32_t length) +{ + if (param == nullptr || !param->IsValid()) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + if (key == nullptr || length == 0) { + param->cryptoParam.encryptKey_.assign(param->cryptoParam.encryptKey_.size(), 0); + } else { + param->cryptoParam.encryptKey_ = std::vector{ key, key + length }; + } + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Crypto_SetIteration(OH_Rdb_CryptoParam *param, int64_t iteration) +{ + if (param == nullptr || !param->IsValid() || iteration < 0) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + param->cryptoParam.iterNum = static_cast(iteration); + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Crypto_SetEncryptionAlgo(OH_Rdb_CryptoParam *param, int32_t algo) +{ + if (param == nullptr || !param->IsValid() || + (algo != static_cast(RDB_AES_256_GCM) && + algo != static_cast(RDB_AES_256_CBC))) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + param->cryptoParam.encryptAlgo = algo; + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Crypto_SetHmacAlgo(OH_Rdb_CryptoParam *param, int32_t algo) +{ + if (param == nullptr || !param->IsValid() || + algo < static_cast(RDB_HMAC_SHA1) || algo > static_cast(RDB_HMAC_SHA512)) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + param->cryptoParam.hmacAlgo = algo; + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Crypto_SetKdfAlgo(OH_Rdb_CryptoParam *param, int32_t algo) +{ + if (param == nullptr || !param->IsValid() || + algo < static_cast(RDB_KDF_SHA1) || algo > static_cast(RDB_KDF_SHA512)) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + param->cryptoParam.kdfAlgo = algo; + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Crypto_SetCryptoPageSize(OH_Rdb_CryptoParam *param, int64_t size) +{ + if (param == nullptr || !param->IsValid() || size < 0) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + uint32_t value = static_cast(size); + if (!((value != 0) && ((value & RdbStoreConfig::DB_INVALID_CRYPTO_PAGE_SIZE_MASK) == 0) && + (value & (value - 1)) == 0)) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + param->cryptoParam.cryptoPageSize = value; + return OH_Rdb_ErrCode::RDB_OK; +} \ No newline at end of file diff --git a/relational_store/interfaces/ndk/src/oh_rdb_transaction.cpp b/relational_store/interfaces/ndk/src/oh_rdb_transaction.cpp index 943967e4a094b7e4f10fc3d7c026f23fabf2c5ad..f5c3ea8737a22c55b4ca44449038d07e511dd665 100644 --- a/relational_store/interfaces/ndk/src/oh_rdb_transaction.cpp +++ b/relational_store/interfaces/ndk/src/oh_rdb_transaction.cpp @@ -41,7 +41,7 @@ static bool IsValidRdbTransOptions(const OH_RDB_TransOptions *options) return ret; } -OH_RDB_TransOptions *OH_RdbTrans_CreateOptions() +OH_RDB_TransOptions *OH_RdbTrans_CreateOptions(void) { OH_RDB_TransOptions *value = new (std::nothrow) OH_RDB_TransOptions; if (value == nullptr) { @@ -52,22 +52,22 @@ OH_RDB_TransOptions *OH_RdbTrans_CreateOptions() return value; } -int OH_RdbTrans_DestroyOptions(OH_RDB_TransOptions *opitons) +int OH_RdbTrans_DestroyOptions(OH_RDB_TransOptions *options) { - if (!IsValidRdbTransOptions(opitons)) { + if (!IsValidRdbTransOptions(options)) { return RDB_E_INVALID_ARGS; } - delete opitons; + delete options; return RDB_OK; } -int OH_RdbTransOption_SetType(OH_RDB_TransOptions *opitons, OH_RDB_TransType type) +int OH_RdbTransOption_SetType(OH_RDB_TransOptions *options, OH_RDB_TransType type) { - if (!IsValidRdbTransOptions(opitons) || type < RDB_TRANS_DEFERRED || type >= RDB_TRANS_BUTT) { + if (!IsValidRdbTransOptions(options) || type < RDB_TRANS_DEFERRED || type >= RDB_TRANS_BUTT) { LOG_ERROR("invalid options, type=%{public}d.", type); return RDB_E_INVALID_ARGS; } - opitons->type_ = type; + options->type_ = type; return RDB_OK; } @@ -138,8 +138,7 @@ int OH_RdbTrans_BatchInsert(OH_Rdb_Transaction *trans, const char *table, const } datas.Put(valuesBucket->Get()); } - auto [errCode, count] = - trans->trans_->BatchInsertWithConflictResolution(table, datas, Utils::ConvertConflictResolution(resolution)); + auto [errCode, count] = trans->trans_->BatchInsert(table, datas, Utils::ConvertConflictResolution(resolution)); *changes = count; if (errCode != E_OK) { LOG_ERROR("batch insert fail, errCode=%{public}d count=%{public}" PRId64, errCode, count); @@ -276,4 +275,41 @@ bool OH_RDB_TransOptions::IsValid() const return false; } return id == OH_TRANS_OPTION_ID; +} + +int OH_RdbTrans_InsertWithConflictResolution(OH_Rdb_Transaction *trans, const char *table, const OH_VBucket *row, + Rdb_ConflictResolution resolution, int64_t *rowId) +{ + auto valuesBucket = RelationalValuesBucket::GetSelf(const_cast(row)); + if (!IsValidRdbTrans(trans) || table == nullptr || valuesBucket == nullptr || rowId == nullptr || + resolution < RDB_CONFLICT_NONE || resolution > RDB_CONFLICT_REPLACE) { + return RDB_E_INVALID_ARGS; + } + + auto [err, id] = trans->trans_->Insert(table, valuesBucket->Get(), Utils::ConvertConflictResolution(resolution)); + *rowId = id; + if (err != E_OK) { + LOG_ERROR("insert with conflict resolution fail,errCode=%{public}x,resolution=%{public}d,id=%{public}" PRId64, + err, resolution, id); + } + return ConvertorErrorCode::GetInterfaceCode(err); +} + +int OH_RdbTrans_UpdateWithConflictResolution(OH_Rdb_Transaction *trans, const OH_VBucket *row, + const OH_Predicates *predicates, Rdb_ConflictResolution resolution, int64_t *changes) +{ + auto rdbPredicate = RelationalPredicate::GetSelf(const_cast(predicates)); + auto rdbValuesBucket = RelationalValuesBucket::GetSelf(const_cast(row)); + if (!IsValidRdbTrans(trans) || rdbValuesBucket == nullptr || rdbPredicate == nullptr || changes == nullptr || + resolution < RDB_CONFLICT_NONE || resolution > RDB_CONFLICT_REPLACE) { + return RDB_E_INVALID_ARGS; + } + auto [err, count] = trans->trans_->Update(rdbValuesBucket->Get(), rdbPredicate->Get(), + Utils::ConvertConflictResolution(resolution)); + *changes = count; + if (err != E_OK) { + LOG_ERROR("update with conflict resolution fail, errCode=%{public}x,resolution=%{public}d,count=%{public}d", + err, resolution, count); + } + return ConvertorErrorCode::GetInterfaceCode(err); } \ No newline at end of file diff --git a/relational_store/interfaces/ndk/src/relational_predicates.cpp b/relational_store/interfaces/ndk/src/relational_predicates.cpp index 5ae556650f7ab7e58b270786f0fd40955d0c1e70..a8d82c669604c080093d87f3d9749a87fb835ad0 100644 --- a/relational_store/interfaces/ndk/src/relational_predicates.cpp +++ b/relational_store/interfaces/ndk/src/relational_predicates.cpp @@ -17,7 +17,9 @@ #include +#include "convertor_error_code.h" #include "logger.h" +#include "oh_data_define.h" #include "oh_predicates.h" #include "relational_predicates_objects.h" #include "relational_store_error_code.h" @@ -377,3 +379,59 @@ RelationalPredicate *RelationalPredicate::GetSelf(OH_Predicates *predicates) } } // namespace RdbNdk } // namespace OHOS + +using namespace OHOS::RdbNdk; +using namespace OHOS::NativeRdb; +int OH_Predicates_Having(OH_Predicates *predicates, const char *conditions, const OH_Data_Values *values) +{ + auto self = RelationalPredicate::GetSelf(predicates); + if (self == nullptr || conditions == nullptr || (values != nullptr && !values->IsValid())) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + if (self->Get().GetGroup().empty() || strlen(conditions) == 0) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + if (values == nullptr) { + self->Get().Having(conditions); + return OH_Rdb_ErrCode::RDB_OK; + } + std::vector datas; + for (auto &value : values->values_) { + if (!value.IsValid()) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + datas.push_back(value.value_); + } + self->Get().Having(conditions, datas); + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Predicates_NotLike(OH_Predicates *predicates, const char *field, const char *pattern) +{ + auto self = RelationalPredicate::GetSelf(predicates); + if (self == nullptr || field == nullptr || pattern == nullptr) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + self->Get().NotLike(field, pattern); + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Predicates_Glob(OH_Predicates *predicates, const char *field, const char *pattern) +{ + auto self = RelationalPredicate::GetSelf(predicates); + if (self == nullptr || field == nullptr || pattern == nullptr) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + self->Get().Glob(field, pattern); + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Predicates_NotGlob(OH_Predicates *predicates, const char *field, const char *pattern) +{ + auto self = RelationalPredicate::GetSelf(predicates); + if (self == nullptr || field == nullptr || pattern == nullptr) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + self->Get().NotGlob(field, pattern); + return OH_Rdb_ErrCode::RDB_OK; +} diff --git a/relational_store/interfaces/ndk/src/relational_predicates_objects.cpp b/relational_store/interfaces/ndk/src/relational_predicates_objects.cpp index 378c363bd461230734a79f899fef7f24164061e3..3b6316a05a29cf4c1f5fb41fc58db84d4f5658ee 100644 --- a/relational_store/interfaces/ndk/src/relational_predicates_objects.cpp +++ b/relational_store/interfaces/ndk/src/relational_predicates_objects.cpp @@ -23,6 +23,7 @@ namespace OHOS { namespace RdbNdk { // The class id used to uniquely identify the OH_VObject class. constexpr int RDB_PREDICATES_OBJECTS_CID = 1234565; + int RelationalPredicatesObjects::PutInt64(OH_VObject *objects, int64_t *value, uint32_t count) { auto self = GetSelf(objects); diff --git a/relational_store/interfaces/ndk/src/relational_store.cpp b/relational_store/interfaces/ndk/src/relational_store.cpp index c66b7efa481b73d74213da69e0bdd4ada184948b..5072916c5bead1d54f2f342222e61373b683816c 100644 --- a/relational_store/interfaces/ndk/src/relational_store.cpp +++ b/relational_store/interfaces/ndk/src/relational_store.cpp @@ -19,9 +19,12 @@ #include "grd_api_manager.h" #include "logger.h" #include "modify_time_cursor.h" +#include "oh_data_define.h" +#include "oh_data_utils.h" #include "raw_data_parser.h" #include "rdb_errno.h" #include "rdb_helper.h" +#include "rdb_ndk_utils.h" #include "rdb_predicates.h" #include "rdb_sql_utils.h" #include "rdb_store_config.h" @@ -30,37 +33,26 @@ #include "relational_predicates_objects.h" #include "relational_store_error_code.h" #include "relational_store_impl.h" +#include "relational_store_inner_types.h" #include "relational_types_v0.h" #include "relational_values_bucket.h" #include "securec.h" #include "sqlite_global_config.h" -#include "oh_data_define.h" -#include "oh_data_utils.h" #include "values_buckets.h" +#include "sqlite_utils.h" using namespace OHOS::RdbNdk; using namespace OHOS::DistributedRdb; -constexpr int RDB_STORE_CID = 1234560; // The class id used to uniquely identify the OH_Rdb_Store class. +constexpr int RDB_STORE_CID = 1234560; // The class id used to uniquely identify the OH_Rdb_Store class. constexpr int RDB_CONFIG_SIZE_V0 = 41; constexpr int RDB_CONFIG_SIZE_V1 = 45; -constexpr int RDB_CONFIG_V2_MAGIC_CODE = 0xDBCF2ADE; +constexpr int RDB_ATTACH_WAIT_TIME_MIN = 1; +constexpr int RDB_ATTACH_WAIT_TIME_MAX = 300; +constexpr int RDB_CONFIG_PLUGINS_MAX = 16; +constexpr int RDB_CONFIG_CUST_DIR_MAX_LEN = 128; static int g_supportDbTypes[] = { RDB_SQLITE, RDB_CAYLEY }; -struct OH_Rdb_ConfigV2 { - int magicNum = RDB_CONFIG_V2_MAGIC_CODE; - std::string dataBaseDir = ""; - std::string storeName = ""; - std::string bundleName = ""; - std::string moduleName = ""; - bool isEncrypt = false; - bool persist = true; - int securityLevel = 0; - int area = 0; - int dbType = RDB_SQLITE; - int token = RDB_NONE_TOKENIZER; -}; - OH_Rdb_ConfigV2 *OH_Rdb_CreateConfig() { return new (std::nothrow) OH_Rdb_ConfigV2(); @@ -165,6 +157,17 @@ int OH_Rdb_SetArea(OH_Rdb_ConfigV2 *config, int area) return OH_Rdb_ErrCode::RDB_OK; } +int OH_Rdb_SetSemanticIndex(OH_Rdb_ConfigV2 *config, bool isEnable) +{ + if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) { + LOG_ERROR("config is null %{public}d or magic num not valid %{public}x when set SemanticIndex.", + (config == nullptr), (config == nullptr ? 0 : config->magicNum)); + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + config->enableSemanticIndex = isEnable; + return OH_Rdb_ErrCode::RDB_OK; +} + int OH_Rdb_SetDbType(OH_Rdb_ConfigV2 *config, int dbType) { if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE) || @@ -180,6 +183,47 @@ int OH_Rdb_SetDbType(OH_Rdb_ConfigV2 *config, int dbType) return OH_Rdb_ErrCode::RDB_OK; } +int OH_Rdb_SetCustomDir(OH_Rdb_ConfigV2 *config, const char *customDir) +{ + if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE) || customDir == nullptr || + strlen(customDir) > RDB_CONFIG_CUST_DIR_MAX_LEN) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + config->customDir = customDir; + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Rdb_SetReadOnly(OH_Rdb_ConfigV2 *config, bool readOnly) +{ + if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + config->readOnly = readOnly; + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Rdb_SetPlugins(OH_Rdb_ConfigV2 *config, const char **plugins, int32_t length) +{ + if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE) || plugins == nullptr || + length > RDB_CONFIG_PLUGINS_MAX) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + for (int i = 0; i < length; i++) { + config->pluginLibs.push_back(plugins[i]); + } + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Rdb_SetCryptoParam(OH_Rdb_ConfigV2 *config, const OH_Rdb_CryptoParam *cryptoParam) +{ + if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE) || + cryptoParam == nullptr || !cryptoParam->IsValid()) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + config->cryptoParam = cryptoParam->cryptoParam; + return OH_Rdb_ErrCode::RDB_OK; +} + int OH_Rdb_IsTokenizerSupported(Rdb_Tokenizer tokenizer, bool *isSupported) { if (tokenizer < RDB_NONE_TOKENIZER || tokenizer > RDB_CUSTOM_TOKENIZER) { @@ -263,6 +307,9 @@ int RelationalStore::SubscribeAutoSyncProgress(const Rdb_ProgressObserver *callb return OH_Rdb_ErrCode::RDB_OK; } auto obs = std::make_shared(callback); + if (store_ == nullptr) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } int errCode = store_->RegisterAutoSyncCallback(obs); if (errCode == NativeRdb::E_OK) { LOG_ERROR("subscribe failed."); @@ -275,6 +322,9 @@ int RelationalStore::SubscribeAutoSyncProgress(const Rdb_ProgressObserver *callb int RelationalStore::UnsubscribeAutoSyncProgress(const Rdb_ProgressObserver *callback) { std::lock_guard lock(mutex_); + if (store_ == nullptr) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } for (auto it = callbacks_.begin(); it != callbacks_.end();) { if (callback != nullptr && !(**it == callback)) { ++it; @@ -355,59 +405,6 @@ RelationalStore *GetRelationalStore(OH_Rdb_Store *store) return static_cast(store); } -// caller must ensure token is valid -static OHOS::NativeRdb::Tokenizer ConvertTokenizer2Native(Rdb_Tokenizer token) -{ - if (token == Rdb_Tokenizer::RDB_NONE_TOKENIZER) { - return OHOS::NativeRdb::Tokenizer::NONE_TOKENIZER; - } - if (token == Rdb_Tokenizer::RDB_ICU_TOKENIZER) { - return OHOS::NativeRdb::Tokenizer::ICU_TOKENIZER; - } - if (token == Rdb_Tokenizer::RDB_CUSTOM_TOKENIZER) { - return OHOS::NativeRdb::Tokenizer::CUSTOM_TOKENIZER; - } - return OHOS::NativeRdb::Tokenizer::TOKENIZER_END; -} - -static OHOS::NativeRdb::RdbStoreConfig GetRdbStoreConfig(const OH_Rdb_ConfigV2 *config, int *errCode) -{ - if (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE || (config->persist && - ((OHOS::NativeRdb::SecurityLevel(config->securityLevel) < OHOS::NativeRdb::SecurityLevel::S1 || - OHOS::NativeRdb::SecurityLevel(config->securityLevel) >= OHOS::NativeRdb::SecurityLevel::LAST))) || - (config->area < RDB_SECURITY_AREA_EL1 || config->area > RDB_SECURITY_AREA_EL5) || - (config->dbType < RDB_SQLITE || config->dbType > RDB_CAYLEY) || - (config->token < RDB_NONE_TOKENIZER || config->token > RDB_CUSTOM_TOKENIZER)) { - *errCode = OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; - LOG_ERROR("Config magic number is not valid %{public}x or securityLevel %{public}d area %{public}d" - "dbType %{public}d token %{public}d ret %{public}d persist %{public}d", - config->magicNum, config->securityLevel, config->area, config->dbType, config->token, *errCode, - config->persist); - return OHOS::NativeRdb::RdbStoreConfig(""); - } - std::string realPath = !config->persist ? config->dataBaseDir: - OHOS::NativeRdb::RdbSqlUtils::GetDefaultDatabasePath(config->dataBaseDir, config->storeName, *errCode); - if (*errCode != 0) { - *errCode = ConvertorErrorCode::NativeToNdk(*errCode); - LOG_ERROR("Get database path failed from new config, ret %{public}d ", *errCode); - return OHOS::NativeRdb::RdbStoreConfig(""); - } - OHOS::NativeRdb::RdbStoreConfig rdbStoreConfig(realPath); - if (!config->storeName.empty()) { - rdbStoreConfig.SetName(config->storeName); - } - rdbStoreConfig.SetSecurityLevel(OHOS::NativeRdb::SecurityLevel(config->securityLevel)); - rdbStoreConfig.SetEncryptStatus(config->isEncrypt); - rdbStoreConfig.SetArea(config->area - 1); - rdbStoreConfig.SetIsVector(config->dbType == RDB_CAYLEY); - rdbStoreConfig.SetBundleName(config->bundleName); - rdbStoreConfig.SetName(config->storeName); - rdbStoreConfig.SetTokenizer(ConvertTokenizer2Native(static_cast(config->token))); - rdbStoreConfig.SetStorageMode( - config->persist ? OHOS::NativeRdb::StorageMode::MODE_DISK : OHOS::NativeRdb::StorageMode::MODE_MEMORY); - return rdbStoreConfig; -} - OH_Rdb_Store *OH_Rdb_GetOrOpen(const OH_Rdb_Config *config, int *errCode) { if (config == nullptr || config->selfSize > RDB_CONFIG_SIZE_V1 || errCode == nullptr) { @@ -440,7 +437,7 @@ OH_Rdb_Store *OH_Rdb_GetOrOpen(const OH_Rdb_Config *config, int *errCode) OHOS::NativeRdb::RdbHelper::GetRdbStore(rdbStoreConfig, -1, callback, *errCode); *errCode = ConvertorErrorCode::NativeToNdk(*errCode); if (store == nullptr) { - LOG_ERROR("Get RDB Store fail %{public}s", realPath.c_str()); + LOG_ERROR("Get RDB Store fail %{public}s", OHOS::NativeRdb::SqliteUtils::Anonymous(realPath).c_str()); return nullptr; } return new (std::nothrow) RelationalStore(store); @@ -454,8 +451,10 @@ OH_Rdb_Store *OH_Rdb_CreateOrOpen(const OH_Rdb_ConfigV2 *config, int *errCode) (config == nullptr), (config == nullptr ? 0 : config->magicNum), (errCode == nullptr)); return nullptr; } - OHOS::NativeRdb::RdbStoreConfig rdbStoreConfig = GetRdbStoreConfig(config, errCode); - if (*errCode != OH_Rdb_ErrCode::RDB_OK) { + + auto [ret, rdbStoreConfig] = RdbNdkUtils::GetRdbStoreConfig(config); + if (ret != OHOS::NativeRdb::E_OK) { + *errCode = ret; return nullptr; } MainOpenCallback callback; @@ -463,7 +462,8 @@ OH_Rdb_Store *OH_Rdb_CreateOrOpen(const OH_Rdb_ConfigV2 *config, int *errCode) OHOS::NativeRdb::RdbHelper::GetRdbStore(rdbStoreConfig, -1, callback, *errCode); *errCode = ConvertorErrorCode::NativeToNdk(*errCode); if (store == nullptr) { - LOG_ERROR("Get RDB Store fail %{public}s", rdbStoreConfig.GetPath().c_str()); + LOG_ERROR("Get RDB Store fail %{public}s", + OHOS::NativeRdb::SqliteUtils::Anonymous(rdbStoreConfig.GetPath()).c_str()); return nullptr; } return new (std::nothrow) RelationalStore(store); @@ -538,7 +538,7 @@ int OH_Rdb_BatchInsert(OH_Rdb_Store *store, const char *table, } datas.Put(valuesBucket->Get()); } - auto [errCode, count] = rdbStore->GetStore()->BatchInsertWithConflictResolution(table, + auto [errCode, count] = rdbStore->GetStore()->BatchInsert(table, datas, Utils::ConvertConflictResolution(resolution)); *changes = count; if (errCode != OHOS::NativeRdb::E_OK) { @@ -821,7 +821,7 @@ int RelationalStore::DoSubScribe(Rdb_SubscribeType type, const Rdb_DataObserver auto ndkObserver = std::make_shared(observer, type); int subscribeResult = (type == RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS) ? store_->SubscribeObserver(subscribeOption, ndkObserver) - : store_->Subscribe(subscribeOption, ndkObserver.get()); + : store_->Subscribe(subscribeOption, ndkObserver); if (subscribeResult != OHOS::NativeRdb::E_OK) { LOG_ERROR("subscribe failed."); } else { @@ -843,7 +843,7 @@ int RelationalStore::DoUnsubScribe(Rdb_SubscribeType type, const Rdb_DataObserve } auto subscribeOption = SubscribeOption{ .mode = NDKUtils::GetSubscribeType(type), .event = "data_change" }; int errCode = (type == RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS) ? store_->UnsubscribeObserver(subscribeOption, *it) - : store_->UnSubscribe(subscribeOption, it->get()); + : store_->UnSubscribe(subscribeOption, *it); if (errCode != NativeRdb::E_OK) { LOG_ERROR("unsubscribe failed."); return ConvertorErrorCode::NativeToNdk(errCode); @@ -903,7 +903,10 @@ Rdb_TableDetails *RelationalProgressDetails::GetTableDetails(int paraVersion) if (detailsV0 == nullptr) { return nullptr; } - (void)memset_s(detailsV0, length, 0, length); + auto result = memset_s(detailsV0, length, 0, length); + if (result != EOK) { + LOG_ERROR("memset_s failed, error code is %{public}d", result); + } int index = 0; for (const auto &pair : tableDetails_) { detailsV0[index].table = pair.first.c_str(); @@ -1037,7 +1040,6 @@ OH_Cursor *OH_Rdb_QueryLockedRow( auto rdbStore = GetRelationalStore(store); auto predicate = RelationalPredicate::GetSelf(predicates); if (rdbStore == nullptr || predicate == nullptr) { - LOG_ERROR("rdbStore or predicate is nullptr."); return nullptr; } std::vector columns; @@ -1282,8 +1284,81 @@ void NDKStoreObserver::ConvertKeyInfoData( bool NDKStoreObserver::operator==(const Rdb_DataObserver *other) { - if (other == nullptr) { + if (other == nullptr || observer_ == nullptr) { return false; } return other->context == observer_->context && &(other->callback) == &(observer_->callback); +} + +int OH_Rdb_InsertWithConflictResolution(OH_Rdb_Store *store, const char *table, OH_VBucket *row, + Rdb_ConflictResolution resolution, int64_t *rowId) +{ + auto rdbStore = GetRelationalStore(store); + auto bucket = RelationalValuesBucket::GetSelf(row); + if (rdbStore == nullptr || table == nullptr || bucket == nullptr || rowId == nullptr || + resolution < RDB_CONFLICT_NONE || resolution > RDB_CONFLICT_REPLACE) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + auto [errCode, count] = rdbStore->GetStore()->Insert(table, bucket->Get(), + Utils::ConvertConflictResolution(resolution)); + *rowId = count; + return ConvertorErrorCode::GetInterfaceCode(errCode); +} + +int OH_Rdb_UpdateWithConflictResolution(OH_Rdb_Store *store, OH_VBucket *row, OH_Predicates *predicates, + Rdb_ConflictResolution resolution, int64_t *changes) +{ + auto rdbStore = GetRelationalStore(store); + auto bucket = RelationalValuesBucket::GetSelf(row); + auto predicate = RelationalPredicate::GetSelf(predicates); + if (rdbStore == nullptr || bucket == nullptr || predicate == nullptr || changes == nullptr || + resolution < RDB_CONFLICT_NONE || resolution > RDB_CONFLICT_REPLACE) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + int changedRows = 0; + auto errCode = rdbStore->GetStore()->UpdateWithConflictResolution(changedRows, + predicate->Get().GetTableName(), bucket->Get(), predicate->Get().GetWhereClause(), + predicate->Get().GetBindArgs(), Utils::ConvertConflictResolution(resolution)); + *changes = changedRows; + return ConvertorErrorCode::GetInterfaceCode(errCode); +} + +int OH_Rdb_Attach(OH_Rdb_Store *store, const OH_Rdb_ConfigV2 *config, const char *attachName, int64_t waitTime, + size_t *attachedNumber) +{ + auto rdbStore = GetRelationalStore(store); + if (rdbStore == nullptr || config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE) || + attachName == nullptr || waitTime < RDB_ATTACH_WAIT_TIME_MIN || waitTime > RDB_ATTACH_WAIT_TIME_MAX || + attachedNumber == nullptr) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + auto [ret, rdbStoreConfig] = RdbNdkUtils::GetRdbStoreConfig(config); + if (ret != OHOS::NativeRdb::E_OK) { + return ConvertorErrorCode::NativeToNdk(ret); + } + auto [errCode, size] = rdbStore->GetStore()->Attach(rdbStoreConfig, attachName, static_cast(waitTime)); + *attachedNumber = size; + return ConvertorErrorCode::GetInterfaceCode(errCode); +} + +int OH_Rdb_Detach(OH_Rdb_Store *store, const char *attachName, int64_t waitTime, size_t *attachedNumber) +{ + auto rdbStore = GetRelationalStore(store); + if (rdbStore == nullptr || attachName == nullptr || + waitTime < RDB_ATTACH_WAIT_TIME_MIN || waitTime > RDB_ATTACH_WAIT_TIME_MAX || attachedNumber == nullptr) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + auto [errCode, size] = rdbStore->GetStore()->Detach(attachName, static_cast(waitTime)); + *attachedNumber = size; + return ConvertorErrorCode::GetInterfaceCode(errCode); +} + +int OH_Rdb_SetLocale(OH_Rdb_Store *store, const char *locale) +{ + auto rdbStore = GetRelationalStore(store); + if (rdbStore == nullptr || locale == nullptr) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + auto errCode = rdbStore->GetStore()->ConfigLocale(locale); + return ConvertorErrorCode::GetInterfaceCode(errCode); } \ No newline at end of file diff --git a/relational_store/interfaces/ndk/src/BUILD.gn b/relational_store/interfaces/rdb_ndk_utils/BUILD.gn similarity index 65% rename from relational_store/interfaces/ndk/src/BUILD.gn rename to relational_store/interfaces/rdb_ndk_utils/BUILD.gn index 9ce64297c43a634e087092728c919c7f5d2d3080..ba7ffff0278c75226142a09027cae27a7a2d0ff5 100644 --- a/relational_store/interfaces/ndk/src/BUILD.gn +++ b/relational_store/interfaces/rdb_ndk_utils/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. +# Copyright (c) 2025 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 @@ -14,7 +14,14 @@ import("//build/ohos.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") -ohos_shared_library("native_rdb_ndk") { +config("native_rdb_ndk_utils_public_config") { + visibility = [ ":*" ] + + include_dirs = [ + "include", + ] +} +ohos_shared_library("native_rdb_ndk_utils") { branch_protector_ret = "pac_ret" sanitize = { boundary_sanitize = true @@ -25,26 +32,11 @@ ohos_shared_library("native_rdb_ndk") { } include_dirs = [ - "../include", - "${kvstore_path}/common", + "${relational_store_base_path}/interfaces/ndk", + "${relational_store_base_path}/interfaces/ndk/include", "${relational_store_common_path}/include", - "${relational_store_native_path}/rdb/include", - ] - sources = [ - "convertor_error_code.cpp", - "modify_time_cursor.cpp", - "oh_data_utils.cpp", - "oh_data_value.cpp", - "oh_data_values.cpp", - "oh_data_values_buckets.cpp", - "oh_rdb_transaction.cpp", - "relational_asset.cpp", - "relational_cursor.cpp", - "relational_predicates.cpp", - "relational_predicates_objects.cpp", - "relational_store.cpp", - "relational_values_bucket.cpp", ] + sources = [ "src/rdb_ndk_utils.cpp" ] defines = [ "API_EXPORT=__attribute__((visibility (\"default\")))" ] @@ -53,9 +45,10 @@ ohos_shared_library("native_rdb_ndk") { external_deps = [ "c_utils:utils", "hilog:libhilog", + "kv_store:datamgr_common", ] + public_configs = [ ":native_rdb_ndk_utils_public_config" ] - relative_install_dir = "ndk" part_name = "relational_store" subsystem_name = "distributeddatamgr" } diff --git a/relational_store/interfaces/rdb_ndk_utils/include/rdb_ndk_utils.h b/relational_store/interfaces/rdb_ndk_utils/include/rdb_ndk_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..218aecd129e8a914705515d99b883fd3b28f2bd4 --- /dev/null +++ b/relational_store/interfaces/rdb_ndk_utils/include/rdb_ndk_utils.h @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2025 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 RDB_NDK_UTILS_H +#define RDB_NDK_UTILS_H +#include "rdb_store_config.h" +typedef struct OH_Rdb_ConfigV2 OH_Rdb_ConfigV2; +namespace OHOS::RdbNdk { +class API_EXPORT RdbNdkUtils { +public: + static std::pair GetRdbStoreConfig(const OH_Rdb_ConfigV2 *config); +}; +} // namespace OHOS::RdbNdk +#endif // RDB_NDK_UTILS_H \ No newline at end of file diff --git a/relational_store/interfaces/rdb_ndk_utils/src/rdb_ndk_utils.cpp b/relational_store/interfaces/rdb_ndk_utils/src/rdb_ndk_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa238754094ea5f35dc1b9a7a6947f8fec8d1126 --- /dev/null +++ b/relational_store/interfaces/rdb_ndk_utils/src/rdb_ndk_utils.cpp @@ -0,0 +1,90 @@ +/* +* Copyright (c) 2025 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 "RdbNdkUtils" +#include "rdb_ndk_utils.h" + +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_sql_utils.h" +#include "relational_store_inner_types.h" + +namespace OHOS::RdbNdk { +// caller must ensure token is valid +static OHOS::NativeRdb::Tokenizer ConvertTokenizer2Native(Rdb_Tokenizer token) +{ + if (token == Rdb_Tokenizer::RDB_NONE_TOKENIZER) { + return OHOS::NativeRdb::Tokenizer::NONE_TOKENIZER; + } + if (token == Rdb_Tokenizer::RDB_ICU_TOKENIZER) { + return OHOS::NativeRdb::Tokenizer::ICU_TOKENIZER; + } + if (token == Rdb_Tokenizer::RDB_CUSTOM_TOKENIZER) { + return OHOS::NativeRdb::Tokenizer::CUSTOM_TOKENIZER; + } + return OHOS::NativeRdb::Tokenizer::TOKENIZER_END; +} + +std::pair RdbNdkUtils::GetRdbStoreConfig(const OH_Rdb_ConfigV2 *config) +{ + if (config == nullptr || config->magicNum != RDB_CONFIG_V2_MAGIC_CODE || (config->persist && + ((OHOS::NativeRdb::SecurityLevel(config->securityLevel) < OHOS::NativeRdb::SecurityLevel::S1 || + OHOS::NativeRdb::SecurityLevel(config->securityLevel) >= OHOS::NativeRdb::SecurityLevel::LAST))) || + (config->area < RDB_SECURITY_AREA_EL1 || config->area > RDB_SECURITY_AREA_EL5) || + (config->dbType < RDB_SQLITE || config->dbType > RDB_CAYLEY) || + (config->token < RDB_NONE_TOKENIZER || config->token > RDB_CUSTOM_TOKENIZER)) { + if (config != nullptr) { + LOG_ERROR("Config magic number is not valid %{public}x or securityLevel %{public}d area %{public}d" + " dbType %{public}d token %{public}d persist %{public}d" + " readOnly %{public}d", + config->magicNum, config->securityLevel, config->area, config->dbType, config->token, + config->persist, config->readOnly); + } else { + LOG_ERROR("Config is null"); + } + return { OHOS::NativeRdb::E_INVALID_ARGS, OHOS::NativeRdb::RdbStoreConfig("") }; + } + + std::string realPath; + int32_t code = OHOS::NativeRdb::E_OK; + if (config->persist) { + std::tie(realPath, code) = OHOS::NativeRdb::RdbSqlUtils::GetDefaultDatabasePath( + config->dataBaseDir, config->storeName, config->customDir); + } else { + realPath = config->dataBaseDir; + } + + if (code != OHOS::NativeRdb::E_OK) { + LOG_ERROR("Get database path failed from new config, ret %{public}d ", code); + return { OHOS::NativeRdb::E_INVALID_ARGS, OHOS::NativeRdb::RdbStoreConfig("") }; + } + OHOS::NativeRdb::RdbStoreConfig rdbStoreConfig(realPath); + rdbStoreConfig.SetSecurityLevel(OHOS::NativeRdb::SecurityLevel(config->securityLevel)); + rdbStoreConfig.SetEncryptStatus(config->isEncrypt); + rdbStoreConfig.SetArea(config->area - 1); + rdbStoreConfig.SetIsVector(config->dbType == RDB_CAYLEY); + rdbStoreConfig.SetBundleName(config->bundleName); + rdbStoreConfig.SetName(config->storeName); + rdbStoreConfig.SetTokenizer(ConvertTokenizer2Native(static_cast(config->token))); + rdbStoreConfig.SetStorageMode( + config->persist ? OHOS::NativeRdb::StorageMode::MODE_DISK : OHOS::NativeRdb::StorageMode::MODE_MEMORY); + rdbStoreConfig.SetCustomDir(config->customDir); + rdbStoreConfig.SetReadOnly(config->readOnly); + rdbStoreConfig.SetPluginLibs(config->pluginLibs); + rdbStoreConfig.SetCryptoParam(config->cryptoParam); + rdbStoreConfig.SetEnableSemanticIndex(config->enableSemanticIndex); + return { OHOS::NativeRdb::E_OK, rdbStoreConfig }; +} +} // namespace OHOS::RdbNdk \ No newline at end of file diff --git a/relational_store/rdbmock/frameworks/native/rdb/concurrent_map.h b/relational_store/rdbmock/frameworks/native/rdb/common/concurrent_map.h similarity index 100% rename from relational_store/rdbmock/frameworks/native/rdb/concurrent_map.h rename to relational_store/rdbmock/frameworks/native/rdb/common/concurrent_map.h diff --git a/relational_store/rdbmock/frameworks/native/rdb/file_ex.h b/relational_store/rdbmock/frameworks/native/rdb/file_ex.h index d2102fcbef7f67657684a4d22ef1c1e879c23fa4..ab6de135610cc41366eb098120b5544541433c02 100644 --- a/relational_store/rdbmock/frameworks/native/rdb/file_ex.h +++ b/relational_store/rdbmock/frameworks/native/rdb/file_ex.h @@ -19,7 +19,7 @@ #include #include -static bool SaveBufferToFile(const std::string &filePath, const std::vector &content, bool truncated = true) +static bool SaveStringToFd(int fd, const std::string& content) { return true; } diff --git a/relational_store/rdbmock/frameworks/native/rdb/relational_store_client.h b/relational_store/rdbmock/frameworks/native/rdb/relational_store_client.h index cc94d3259faed01012529a10b8881f084ba3406d..2ba9fab4a603c4f2b0ac656ad5bd9cfe65735d85 100644 --- a/relational_store/rdbmock/frameworks/native/rdb/relational_store_client.h +++ b/relational_store/rdbmock/frameworks/native/rdb/relational_store_client.h @@ -17,6 +17,7 @@ #define RELATIONAL_STORE_RELATIONAL_STORE_CLIENT_H #include +#include #include "sqlite3sym.h" #include "store_observer.h" @@ -57,4 +58,18 @@ void UnregisterDbHook(sqlite3 *db); DistributedDB::DBStatus CreateDataChangeTempTrigger(sqlite3 *db); +namespace DistributedDB { +struct KnowledgeSourceSchema { + std::string tableName; + std::set extendColNames; + std::set knowledgeColNames; +}; +} + +DistributedDB::DBStatus SetKnowledgeSourceSchema(sqlite3 *db, const DistributedDB::KnowledgeSourceSchema &schema); + +DistributedDB::DBStatus CleanDeletedData(sqlite3 *db, const std::string &tableName, uint64_t cursor); + +void Clean(bool isOpenSslClean); + #endif //RELATIONAL_STORE_RELATIONAL_STORE_CLIENT_H diff --git a/relational_store/rdbmock/frameworks/native/rdb/sys/file.h b/relational_store/rdbmock/frameworks/native/rdb/sys/file.h index 525ff1e41c7dc18af306044a29a963c80875b058..eee8a7da3dd2726925b17281e9ba4ca01a0964be 100644 --- a/relational_store/rdbmock/frameworks/native/rdb/sys/file.h +++ b/relational_store/rdbmock/frameworks/native/rdb/sys/file.h @@ -23,6 +23,10 @@ #ifndef LOCK_UN #define LOCK_UN 1 #endif + +#ifndef LOCK_NB +#define LOCK_NB 4 +#endif #ifdef __cplusplus extern "C" { #endif diff --git a/relational_store/rdbmock/frameworks/native/win32/dlfcn.cpp b/relational_store/rdbmock/frameworks/native/win32/dlfcn.cpp index 62abb46b1dd896d72aa565562da4c14ac0b088a0..121026149384b9e7cd3291b44f3578dc7efdb39a 100644 --- a/relational_store/rdbmock/frameworks/native/win32/dlfcn.cpp +++ b/relational_store/rdbmock/frameworks/native/win32/dlfcn.cpp @@ -21,6 +21,11 @@ void *dlopen(const char *pathName, int mode) }; void *dlsym(void *handle, const char *funcName) +{ + return nullptr; +}; + +void *dlclose(void *handle) { return nullptr; }; \ No newline at end of file diff --git a/relational_store/rdbmock/frameworks/native/win32/dlfcn.h b/relational_store/rdbmock/frameworks/native/win32/dlfcn.h index f0fc3b50d0f071e4ef13a95748dfe0aab0f21b35..e29758f29f2518a9e7cfdb3bf3ceaffcb626597b 100644 --- a/relational_store/rdbmock/frameworks/native/win32/dlfcn.h +++ b/relational_store/rdbmock/frameworks/native/win32/dlfcn.h @@ -28,6 +28,7 @@ extern "C" { void *dlopen(const char *pathName, int mode); void *dlsym(void *handle, const char *funcName); +void *dlclose(void *handle); #ifdef __cplusplus } #endif diff --git a/relational_store/relational_store.gni b/relational_store/relational_store.gni index d5c7eb3e65c12905e3af2bcbd73e547e335221d8..55ba743925493a7ca4614987af639136750fea01 100644 --- a/relational_store/relational_store.gni +++ b/relational_store/relational_store.gni @@ -28,6 +28,9 @@ relational_store_base_path = "//foundation/distributeddatamgr/relational_store" relational_store_mock_path = "${relational_store_base_path}/rdbmock" +relational_store_mock_test_path = + "${relational_store_base_path}/test/native/rdb/mock" + relational_store_js_common_path = "${relational_store_base_path}/frameworks/js/napi/common" @@ -60,10 +63,12 @@ sdk_c_path = "//interface/sdk_c/distributeddatamgr" plugins_path = "//plugins" -relational_store_frameworks_path = "${relational_store_base_path}/frameworks" - -plugins_path = "//plugins" - foundation_systemabilitymgr_path = "//foundation/systemabilitymgr/" base_security_dataclassification_path = "//base/security/dataclassification" + +datashare_base_path = "//foundation/distributeddatamgr/data_share" + +datashare_common_native_path = "${datashare_base_path}/frameworks/native/common" + +datashare_innerapi_path = "${datashare_base_path}/interfaces/inner_api" \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/AppScope/app.json b/relational_store/test/ets/cloud_data/AppScope/app.json new file mode 100644 index 0000000000000000000000000000000000000000..8bbcec32ed0bc97c333c1b4d2a73fe30d454cc07 --- /dev/null +++ b/relational_store/test/ets/cloud_data/AppScope/app.json @@ -0,0 +1,21 @@ +{ + "app":{ + "bundleName":"com.clouddata.configtest", + "vendor":"example", + "versionCode":1000000, + "versionName":"1.0.0", + "debug":false, + "icon":"$media:icon", + "label":"$string:app_name", + "description":"$string:description_application", + "distributedNotificationEnabled":true, + "keepAlive":true, + "singleUser":true, + "minAPIVersion":8, + "targetAPIVersion":8, + "car":{ + "apiCompatibleVersion":8, + "singleUser":false + } + } +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/AppScope/resources/base/element/string.json b/relational_store/test/ets/cloud_data/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..7582400300637774fc34de3264bac10e577a2008 --- /dev/null +++ b/relational_store/test/ets/cloud_data/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string":[ + { + "name":"app_name", + "value":"ohosProject" + } + ] +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/BUILD.gn b/relational_store/test/ets/cloud_data/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..d57ca3d53cb808514227b7fed0e79b91f415240b --- /dev/null +++ b/relational_store/test/ets/cloud_data/BUILD.gn @@ -0,0 +1,48 @@ +# Copyright (C) 2025 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/test.gni") + +ohos_js_stage_unittest("CloudConfigEtsTest") { + hap_profile = "entry/src/main/module.json" + deps = [ + ":stageetstest_js_assets", + ":stageetstest_resources", + ] + ets2abc = true + certificate_profile = "signature/openharmony_sx.p7b" + hap_name = "CloudConfigEtsTest" + subsystem_name = "distributeddatamgr" + part_name = "relational_store" + module_out_path = "relational_store/relational_store/relational_store_ets" +} + +ohos_app_scope("stageetstest_app_profile") { + app_profile = "AppScope/app.json" + sources = [ "AppScope/resources" ] +} + +ohos_js_assets("stageetstest_js_assets") { + source_dir = "entry/src/main/ets" +} + +ohos_resources("stageetstest_resources") { + sources = [ "entry/src/main/resources" ] + deps = [ ":stageetstest_app_profile" ] + hap_profile = "entry/src/main/module.json" +} + +group("stage_unittest") { + testonly = true + deps = [ ":CloudConfigEtsTest" ] +} diff --git a/relational_store/test/ets/cloud_data/Test.json b/relational_store/test/ets/cloud_data/Test.json new file mode 100644 index 0000000000000000000000000000000000000000..4d6ad28d1a459fe93fb217a0a0383ecfe200f481 --- /dev/null +++ b/relational_store/test/ets/cloud_data/Test.json @@ -0,0 +1,26 @@ +{ + "description": "Configuration for hjunit demo Tests", + "driver": { + "type": "OHJSUnitTest", + "test-timeout": "180000", + "bundle-name": "com.clouddata.configtest", + "module-name": "testModule", + "shell-timeout": "600000", + "testcase-timeout": 70000 + }, + "kits": [ + { + "test-file-name": [ + "CloudConfigEtsTest.hap" + ], + "type": "AppInstallKit", + "cleanup-apps": true + }, + { + "type": "ShellKit", + "teardown-command":[ + "bm uninstall -n com.clouddata.configtest" + ] + } + ] +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/ets/Application/AbilityStage.ts b/relational_store/test/ets/cloud_data/entry/src/main/ets/Application/AbilityStage.ts new file mode 100644 index 0000000000000000000000000000000000000000..d7d5f024d16d5ce76b8564793bc273123bba3c68 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/ets/Application/AbilityStage.ts @@ -0,0 +1,22 @@ +// Copyright (c) 2025 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 AbilityStage from "@ohos.app.ability.AbilityStage" + +export default class MyAbilityStage extends AbilityStage { + onCreate() { + console.log('[Demo] MyAbilityStage onCreate'); + globalThis.stageOnCreateRun = 1; + globalThis.stageContext = this.context; + } +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/ets/MainAbility/MainAbility.ts b/relational_store/test/ets/cloud_data/entry/src/main/ets/MainAbility/MainAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..586e4fffe66d34cd006fe6b2a541d35a150461c4 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/ets/MainAbility/MainAbility.ts @@ -0,0 +1,50 @@ +// Copyright (c) 2025 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 Ability from '@ohos.app.ability.UIAbility' + +export default class MainAbility extends Ability { + onCreate(want, launchParam){ + // Ability is creating, initialize resources for this ability + console.log('[Demo] MainAbility onCreate'); + globalThis.abilityWant = want; + } + + onDestroy() { + // Ability is destroying, release resources for this ability + console.log('[Demo] MainAbility onDestroy'); + } + + onWindowStageCreate(windowStage) { + // Main window is created, set main page for this ability + console.log('[Demo] MainAbility onWindowStageCreate'); + globalThis.abilityContext = this.context; + globalThis.cacheDir = this.context.cacheDir; + windowStage.setUIContent(this.context, "MainAbility/pages/index/index", null); + } + + onWindowStageDestroy() { + //Main window is destroyed, release UI related resources + console.log('[Demo] MainAbility onWindowStageDestroy'); + } + + onForeground() { + // Ability has brought to foreground + console.log('[Demo] MainAbility onForeground'); + } + + onBackground() { + // Ability has back to background + console.log('[Demo] MainAbility onBackground'); + } +}; \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/ets/MainAbility/pages/index/index.ets b/relational_store/test/ets/cloud_data/entry/src/main/ets/MainAbility/pages/index/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..f42bd5a837ac96284147c51615c4b2ec29da3087 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/ets/MainAbility/pages/index/index.ets @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 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 router from '@ohos.router'; + +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' +import { Hypium } from '@ohos/hypium' +import testsuite from '../../../test/List.test' + + +@Entry +@Component +struct Index { + + aboutToAppear(){ + console.info("start run testcase!!!!") + var abilityDelegator: any + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var abilityDelegatorArguments: any + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + console.info('start run testcase!!!') + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) + } + + build() { + Flex({ direction:FlexDirection.Column, alignItems:ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('Hello World') + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(25) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(() => { + + }) + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/ets/TestAbility/TestAbility.ts b/relational_store/test/ets/cloud_data/entry/src/main/ets/TestAbility/TestAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..65891485ef8a01369162047fc26e6e02addaba24 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/ets/TestAbility/TestAbility.ts @@ -0,0 +1,43 @@ +// Copyright (c) 2025 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 Ability from '@ohos.app.ability.UIAbility' + +export default class TestAbility extends Ability { + onCreate(want, launchParam) { + console.log('TestAbility onCreate'); + } + + onDestroy() { + console.log('TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage) { + console.log('TestAbility onWindowStageCreate'); + windowStage.setUIContent(this.context, 'TestAbility/pages/index', null); + + globalThis.abilityContext = this.context; + } + + onWindowStageDestroy() { + console.log('TestAbility onWindowStageDestroy'); + } + + onForeground() { + console.log('TestAbility onForeground'); + } + + onBackground() { + console.log('TestAbility onBackground'); + } +}; \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/ets/TestAbility/pages/index.ets b/relational_store/test/ets/cloud_data/entry/src/main/ets/TestAbility/pages/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..fc1b5b89db261fdd9b28eb1e7805d88c0c220aaf --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/ets/TestAbility/pages/index.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 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 router from '@ohos.router'; + +@Entry +@Component +struct Index { + aboutToAppear() { + console.info('TestAbility index aboutToAppear') + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts b/relational_store/test/ets/cloud_data/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts new file mode 100644 index 0000000000000000000000000000000000000000..25d9a6df79f39c76741d7f95719ab694c8f0dce0 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,71 @@ +// Copyright (c) 2025 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 TestRunner from '@ohos.application.testRunner' +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +function translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s it', + '-s level', '-s testType', '-s size', '-s timeout' + ]) + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams = `${targetParams} ${key} ${parameters[key]}` + } + } + return targetParams.trim() +} + +async function onAbilityCreateCallback() { + console.log('onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + console.info('addAbilityMonitorCallback : ' + JSON.stringify(err)); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + console.info("OpenHarmonyTestRunner OnPrepare "); + } + + async onRun() { + console.log('OpenHarmonyTestRunner onRun run') + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.MainAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a com.acts.request.MainAbility' + ' -b ' + abilityDelegatorArguments.bundleName + cmd += ' '+translateParamsToString(abilityDelegatorArguments.parameters) + console.info('cmd : '+ cmd) + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + console.info('executeShellCommand : err : ' + JSON.stringify(err)); + console.info('executeShellCommand : data : ' + d.stdResult); + console.info('executeShellCommand : data : ' + d.exitCode); + }) + console.info('OpenHarmonyTestRunner onRun end'); + } +}; \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/ets/test/CloudConfigEtsTest.test.ets b/relational_store/test/ets/cloud_data/entry/src/main/ets/test/CloudConfigEtsTest.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..31e6632f73cb0e73edf802e07ab64250ac3cdb72 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/ets/test/CloudConfigEtsTest.test.ets @@ -0,0 +1,510 @@ +/** + * Copyright (c) 2025 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 impligetProfileByAbilityEmptyAbilityCalled. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-nocheck +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from "@ohos/hypium" +import cloudData from '@ohos.data.cloudData'; +import relationalStore from '@ohos.data.relationalStore'; + +export default function CloudConfigEtsTest() { + describe('CloudConfigEtsTest', function () { + beforeAll(function () { + console.info('beforeAll called'); + }) + + afterAll(function () { + console.info('afterAll called'); + }) + + beforeEach(function () { + console.info('beforeEach called'); + }) + + afterEach(async function () { + console.info('afterEach called'); + }) + + /** + * @tc.name CloudSync001 + * @tc.desc Test Js Api cloudSync + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync001', 0, async function (done) { + console.info('CloudSync001'); + function Progress(detail) { + console.log('CloudSync001 Progress: ' + JSON.Stringify(detail)); + } + try { + // cloud config permission denied + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync001 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 202).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync002 + * @tc.desc Test Js Api cloudSync with diff syncMode + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync002', 0, async function (done) { + console.info('CloudSync002'); + function Progress(detail) { + console.log('CloudSync002 Progress: ' + JSON.Stringify(detail)); + } + try { + // cloud config permission denied + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_NATIVE_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync002 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 202).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync003 + * @tc.desc Test Js Api cloudSync with diff syncMode + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync003', 0, async function (done) { + console.info('CloudSync003'); + function Progress(detail) { + console.log('CloudSync003 Progress: ' + JSON.Stringify(detail)); + } + try { + // cloud config permission denied + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_CLOUD_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync003 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 202).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync004 + * @tc.desc Test Js Api cloudSync, invalid param, no progress + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync004', 0, async function (done) { + console.info('CloudSync004'); + try { + // Parameter error. The number of parameters is incorrect. + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync004 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync005 + * @tc.desc Test Js Api cloudSync, invalid param, empty storeId + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync005', 0, async function (done) { + console.info('CloudSync005'); + function Progress(detail) { + console.log('CloudSync005 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. storeId can not empty. + await cloudData.Config.cloudSync("bundleName", "", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync005 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 14800001).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync006 + * @tc.desc Test Js Api cloudSync, invalid param, storeId is null + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync006', 0, async function (done) { + console.info('CloudSync006'); + function Progress(detail) { + console.log('CloudSync006 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of storeId must be string and not empty. + await cloudData.Config.cloudSync("bundleName", null, relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync006 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync007 + * @tc.desc Test Js Api cloudSync, invalid param, storeId is undefined + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync007', 0, async function (done) { + console.info('CloudSync007'); + function Progress(detail) { + console.log('CloudSync007 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of storeId must be string and not empty. + await cloudData.Config.cloudSync("bundleName", undefined, relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync007 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync008 + * @tc.desc Test Js Api cloudSync, invalid param, storeId is invalid type + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync008', 0, async function (done) { + console.info('CloudSync008'); + function Progress(detail) { + console.log('CloudSync008 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of storeId must be string. + await cloudData.Config.cloudSync("bundleName", 10, relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync008 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync009 + * @tc.desc Test Js Api cloudSync, invalid param, wrong syncMode + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync009', 0, async function (done) { + console.info('CloudSync009'); + function Progress(detail) { + console.log('CloudSync009 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The syncMode is invalid. + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_PUSH, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync009 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 14800001).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync010 + * @tc.desc Test Js Api cloudSync, invalid param, wrong syncMode + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync010', 0, async function (done) { + console.info('CloudSync010'); + function Progress(detail) { + console.log('CloudSync010 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The syncMode is invalid. + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_PULL, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync010 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 14800001).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync011 + * @tc.desc Test Js Api cloudSync, invalid param, wrong syncMode + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync011', 0, async function (done) { + console.info('CloudSync011'); + function Progress(detail) { + console.log('CloudSync011 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The syncMode is invalid. + await cloudData.Config.cloudSync("bundleName", "storeId", 100, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync011 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 14800001).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync012 + * @tc.desc Test Js Api cloudSync, invalid param, wrong syncMode + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync012', 0, async function (done) { + console.info('CloudSync012'); + function Progress(detail) { + console.log('CloudSync012 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of syncMode must be number. + await cloudData.Config.cloudSync("bundleName", "storeId", "syncMode", Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync012 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync013 + * @tc.desc Test Js Api cloudSync, invalid param, syncMode is null. + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync013', 0, async function (done) { + console.info('CloudSync013'); + function Progress(detail) { + console.log('CloudSync013 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of syncMode must be number. + await cloudData.Config.cloudSync("bundleName", "storeId", null, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync013 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync014 + * @tc.desc Test Js Api cloudSync, invalid param, syncMode is undefined. + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync014', 0, async function (done) { + console.info('CloudSync014'); + function Progress(detail) { + console.log('CloudSync014 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of syncMode must be number. + await cloudData.Config.cloudSync("bundleName", "storeId", undefined, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync014 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync015 + * @tc.desc Test Js Api cloudSync, invalid param, empty bundleName + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync015', 0, async function (done) { + console.info('CloudSync015'); + function Progress(detail) { + console.log('CloudSync015 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. bundleName can not be empty. + await cloudData.Config.cloudSync("", "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync015 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 14800001).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync016 + * @tc.desc Test Js Api cloudSync, invalid param, bundleName is null + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync016', 0, async function (done) { + console.info('CloudSync016'); + function Progress(detail) { + console.log('CloudSync016 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of bundleName must be string and not empty. + await cloudData.Config.cloudSync(null, "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync016 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync017 + * @tc.desc Test Js Api cloudSync, invalid param, bundleName is undefined + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync017', 0, async function (done) { + console.info('CloudSync017'); + function Progress(detail) { + console.log('CloudSync017 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of bundleName must be string and not empty. + await cloudData.Config.cloudSync(undefined, "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync017 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync018 + * @tc.desc Test Js Api cloudSync, invalid param, bundleName is invalid type + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync018', 0, async function (done) { + console.info('CloudSync018'); + function Progress(detail) { + console.log('CloudSync018 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of bundleName must be string. + await cloudData.Config.cloudSync(5, "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync018 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync019 + * @tc.desc Test Js Api cloudSync, invalid param, progress is null + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync019', 0, async function (done) { + console.info('CloudSync019'); + try { + // Parameter error. The type progress should be function. + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, null); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync019 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync020 + * @tc.desc Test Js Api cloudSync, invalid param, progress is undefined + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync020', 0, async function (done) { + console.info('CloudSync020'); + try { + // Parameter error. The type progress should be function. + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, undefined); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync020 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync021 + * @tc.desc Test Js Api cloudSync, invalid param, progress is undefined + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync021', 0, async function (done) { + console.info('CloudSync021'); + try { + // Parameter error. The type progress should be function. + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, 123); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync021 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/ets/test/List.test.ets b/relational_store/test/ets/cloud_data/entry/src/main/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..c5070bd55f62120324d1d66f3d090caa85c3e9d2 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 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 CloudConfigEtsTest from './CloudConfigEtsTest.test.ets'; + +export default function testsuite() { + CloudConfigEtsTest(); +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/module.json b/relational_store/test/ets/cloud_data/entry/src/main/module.json new file mode 100644 index 0000000000000000000000000000000000000000..cd018fac4a11e9b66da9b642276efc034e81e07e --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/module.json @@ -0,0 +1,62 @@ +{ + "module": { + "name": "testModule", + "type": "entry", + "srcEntrance": "./ets/Application/AbilityStage.ts", + "description": "$string:testModule_entry_dsc", + "mainElement": "com.acts.request.MainAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "uiSyntax": "ets", + "pages": "$profile:main_pages", + "metadata": [ + { + "name": "ArkTSPartialUpdate", + "value": "false" + } + ], + "abilities": [ + { + "name": "com.acts.request.MainAbility", + "srcEntrance": "./ets/MainAbility/MainAbility.ts", + "description": "$string:testModule_entry_main", + "icon": "$media:icon", + "label": "$string:entry_label", + "visible": true, + "launchType": "singleton", + "orientation": "portrait", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities":[ + "entity.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.CLOUDDATA_CONFIG", + "reason": "$string:permission_reason", + "usedScene": { + "abilities": ["MainAbility"], + "when": "always" + } + } + ], + "metadata": [ + { + "name": "MetaData1", + "value": "MetaDataValue", + "resource": "$profile:shortcuts_config" + } + ] + } +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/resources/base/element/string.json b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..1f38082b57ac77e75ad509b48bca4a40317071f2 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/element/string.json @@ -0,0 +1,44 @@ +{ + "string": [ + { + "name": "testModule_entry_dsc", + "value": "i am an entry for testModule" + }, + { + "name": "testModule_entry_main", + "value": "the testModule entry ability" + }, + { + "name": "entry_label", + "value": "ActsContextTest" + }, + { + "name": "form_description", + "value": "my form" + }, + { + "name": "serviceability_description", + "value": "my whether" + }, + { + "name": "description_application", + "value": "demo for test" + }, + { + "name": "app_name", + "value": "Demo" + }, + { + "name": "form_FormAbility_desc", + "value": "form_description" + }, + { + "name": "form_FormAbility_label", + "value": "form_label" + }, + { + "name": "permission_reason", + "value": "Need permission" + } + ] +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/resources/base/media/icon.png b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..474a55588fd7216113dd42073aadf254d4dba023 Binary files /dev/null and b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/media/icon.png differ diff --git a/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/form_config.json b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/form_config.json new file mode 100644 index 0000000000000000000000000000000000000000..5990f17107b27d41616cb65b6de8ed82831e9056 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/form_config.json @@ -0,0 +1,6 @@ +{ + "src": [ + "MainAbility/pages/index/index", + "MainAbility/pages/second/second" + ] +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/form_config1.txt b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/form_config1.txt new file mode 100644 index 0000000000000000000000000000000000000000..32f9ff7dc213b28017875b2e4679071350a74d1d --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/form_config1.txt @@ -0,0 +1 @@ +{"src": ["MainAbility/pages/index/index","MainAbility/pages/second/second"]} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/invalid.txt b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/invalid.txt new file mode 100644 index 0000000000000000000000000000000000000000..5e41923e1ac6e571ec07b759f9e82fdb730b2f16 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/invalid.txt @@ -0,0 +1,3 @@ +{ + "src": ["MainAbility/pages/index/index"] +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/main_pages.json b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..ceb075cd80946aade673d707aac904fb8998bce9 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "MainAbility/pages/index/index" + ] +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/shortcuts_config.json b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/shortcuts_config.json new file mode 100644 index 0000000000000000000000000000000000000000..ceb075cd80946aade673d707aac904fb8998bce9 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/shortcuts_config.json @@ -0,0 +1,5 @@ +{ + "src": [ + "MainAbility/pages/index/index" + ] +} \ No newline at end of file diff --git a/relational_store/test/js/gdb/performance/openharmony_sx.p7b b/relational_store/test/ets/cloud_data/signature/openharmony_sx.p7b similarity index 50% rename from relational_store/test/js/gdb/performance/openharmony_sx.p7b rename to relational_store/test/ets/cloud_data/signature/openharmony_sx.p7b index 9be1e98fa4c0c28ca997ed660112fa16b194f0f5..5417cc6844ca22af15cd65131d02657d64a3219e 100644 Binary files a/relational_store/test/js/gdb/performance/openharmony_sx.p7b and b/relational_store/test/ets/cloud_data/signature/openharmony_sx.p7b differ diff --git a/relational_store/test/ets/relational_store/AppScope/app.json b/relational_store/test/ets/relational_store/AppScope/app.json new file mode 100644 index 0000000000000000000000000000000000000000..d20832378281e69084f56f872348abdb9d249bb5 --- /dev/null +++ b/relational_store/test/ets/relational_store/AppScope/app.json @@ -0,0 +1,21 @@ +{ + "app":{ + "bundleName":"com.example.myapplication", + "vendor":"example", + "versionCode":1000000, + "versionName":"1.0.0", + "debug":false, + "icon":"$media:icon", + "label":"$string:app_name", + "description":"$string:description_application", + "distributedNotificationEnabled":true, + "keepAlive":true, + "singleUser":true, + "minAPIVersion":8, + "targetAPIVersion":8, + "car":{ + "apiCompatibleVersion":8, + "singleUser":false + } + } +} diff --git a/relational_store/test/ets/relational_store/AppScope/resources/base/element/string.json b/relational_store/test/ets/relational_store/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..7582400300637774fc34de3264bac10e577a2008 --- /dev/null +++ b/relational_store/test/ets/relational_store/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string":[ + { + "name":"app_name", + "value":"ohosProject" + } + ] +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/BUILD.gn b/relational_store/test/ets/relational_store/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..dbf11e4cc5a12f67f7256eec4aee8a6e56e0f0c7 --- /dev/null +++ b/relational_store/test/ets/relational_store/BUILD.gn @@ -0,0 +1,48 @@ +# Copyright (c) 2025 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/test.gni") + +ohos_js_stage_unittest("ActsRelationalStoreEtsTest") { + hap_profile = "entry/src/main/module.json" + deps = [ + ":stageprejstest_js_assets", + ":stageprejstest_resources", + ] + ets2abc = true + certificate_profile = "signature/openharmony_sx.p7b" + hap_name = "ActsRelationalStoreEtsTest" + subsystem_name = "distributeddatamgr" + part_name = "relational_store" + module_out_path = "relational_store/relational_store/relational_store_ets" +} + +ohos_app_scope("stageprejstest_app_profile") { + app_profile = "AppScope/app.json" + sources = [ "AppScope/resources" ] +} + +ohos_js_assets("stageprejstest_js_assets") { + source_dir = "entry/src/main/ets" +} + +ohos_resources("stageprejstest_resources") { + sources = [ "entry/src/main/resources" ] + deps = [ ":stageprejstest_app_profile" ] + hap_profile = "entry/src/main/module.json" +} + +group("stage_unittest") { + testonly = true + deps = [ ":ActsRelationalStoreEtsTest" ] +} diff --git a/relational_store/test/ets/relational_store/Test.json b/relational_store/test/ets/relational_store/Test.json new file mode 100644 index 0000000000000000000000000000000000000000..13676f07018fd0d7ca99f6b37c03119a00094f2f --- /dev/null +++ b/relational_store/test/ets/relational_store/Test.json @@ -0,0 +1,27 @@ +{ + "description": "Configuration for hjunit demo Tests", + "driver": { + "type": "OHJSUnitTest", + "test-timeout": "180000", + "bundle-name": "com.example.myapplication", + "module-name": "testModule", + "shell-timeout": "600000", + "testcase-timeout": 70000 + }, + "kits": [ + { + "test-file-name": [ + "ActsRelationalStoreEtsTest.hap" + ], + "type": "AppInstallKit", + "cleanup-apps": true + }, + { + "type": "ShellKit", + "teardown-command":[ + "bm uninstall -n com.example.myapplication" + ] + } + ] +} + diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/Application/AbilityStage.ts b/relational_store/test/ets/relational_store/entry/src/main/ets/Application/AbilityStage.ts new file mode 100644 index 0000000000000000000000000000000000000000..f983d3d90c81341a1f8ea003a59bc5611b86e10e --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/Application/AbilityStage.ts @@ -0,0 +1,22 @@ +// Copyright (c) 2025 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 AbilityStage from "@ohos.app.ability.AbilityStage" + +export default class MyAbilityStage extends AbilityStage { + onCreate() { + console.log('[Demo] MyAbilityStage onCreate'); + globalThis.stageOnCreateRun = 1; + globalThis.stageContext = this.context; + } +} diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/MainAbility/MainAbility.ts b/relational_store/test/ets/relational_store/entry/src/main/ets/MainAbility/MainAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..d6390dc9518a38ff03b1b7f1bf5a0a5a3ef7415b --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/MainAbility/MainAbility.ts @@ -0,0 +1,49 @@ +// Copyright (c) 2025 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 Ability from '@ohos.app.ability.UIAbility' + +export default class MainAbility extends Ability { + onCreate(want, launchParam){ + // Ability is creating, initialize resources for this ability + console.log('[Demo] MainAbility onCreate'); + globalThis.abilityWant = want; + } + + onDestroy() { + // Ability is destroying, release resources for this ability + console.log('[Demo] MainAbility onDestroy'); + } + + onWindowStageCreate(windowStage) { + // Main window is created, set main page for this ability + console.log('[Demo] MainAbility onWindowStageCreate'); + globalThis.abilityContext = this.context; + windowStage.setUIContent(this.context, "MainAbility/pages/index/index", null); + } + + onWindowStageDestroy() { + //Main window is destroyed, release UI related resources + console.log('[Demo] MainAbility onWindowStageDestroy'); + } + + onForeground() { + // Ability has brought to foreground + console.log('[Demo] MainAbility onForeground'); + } + + onBackground() { + // Ability has back to background + console.log('[Demo] MainAbility onBackground'); + } +}; \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/MainAbility/pages/index/index.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/MainAbility/pages/index/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..7155d50a8f6f9cae3fc2c4de52b0b9476cc934d5 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/MainAbility/pages/index/index.ets @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 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 router from '@ohos.router'; + +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' +import { Hypium } from '@ohos/hypium' +import testsuite from '../../../test/List.test' + + +@Entry +@Component +struct Index { + + aboutToAppear(){ + console.info("start run testcase!!!!") + let abilityDelegator: any + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + let abilityDelegatorArguments: any + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + console.info('start run testcase!!!') + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) + } + + build() { + Flex({ direction:FlexDirection.Column, alignItems:ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('Hello World') + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(25) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(() => { + + }) + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/TestAbility/TestAbility.ts b/relational_store/test/ets/relational_store/entry/src/main/ets/TestAbility/TestAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..65891485ef8a01369162047fc26e6e02addaba24 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/TestAbility/TestAbility.ts @@ -0,0 +1,43 @@ +// Copyright (c) 2025 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 Ability from '@ohos.app.ability.UIAbility' + +export default class TestAbility extends Ability { + onCreate(want, launchParam) { + console.log('TestAbility onCreate'); + } + + onDestroy() { + console.log('TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage) { + console.log('TestAbility onWindowStageCreate'); + windowStage.setUIContent(this.context, 'TestAbility/pages/index', null); + + globalThis.abilityContext = this.context; + } + + onWindowStageDestroy() { + console.log('TestAbility onWindowStageDestroy'); + } + + onForeground() { + console.log('TestAbility onForeground'); + } + + onBackground() { + console.log('TestAbility onBackground'); + } +}; \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/TestAbility/pages/index.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/TestAbility/pages/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..fc1b5b89db261fdd9b28eb1e7805d88c0c220aaf --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/TestAbility/pages/index.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 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 router from '@ohos.router'; + +@Entry +@Component +struct Index { + aboutToAppear() { + console.info('TestAbility index aboutToAppear') + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts b/relational_store/test/ets/relational_store/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts new file mode 100644 index 0000000000000000000000000000000000000000..a1f107a98ecbd8074b0a7b37c833907c33bf056d --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,71 @@ +// Copyright (c) 2025 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 TestRunner from '@ohos.application.testRunner' +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +function translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s it', + '-s level', '-s testType', '-s size', '-s timeout' + ]) + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams = `${targetParams} ${key} ${parameters[key]}` + } + } + return targetParams.trim() +} + +async function onAbilityCreateCallback() { + console.log('onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + console.info('addAbilityMonitorCallback : ' + JSON.stringify(err)); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + console.info("OpenHarmonyTestRunner OnPrepare "); + } + + async onRun() { + console.log('OpenHarmonyTestRunner onRun run') + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.MainAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a com.example.myapplication.MainAbility' + ' -b ' + abilityDelegatorArguments.bundleName + cmd += ' '+translateParamsToString(abilityDelegatorArguments.parameters) + console.info('cmd : '+ cmd) + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + console.info('executeShellCommand : err : ' + JSON.stringify(err)); + console.info('executeShellCommand : data : ' + d.stdResult); + console.info('executeShellCommand : data : ' + d.exitCode); + }) + console.info('OpenHarmonyTestRunner onRun end'); + } +}; \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/List.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..41df574fa751eb6d473cac326ae4be99e53d0cf7 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/List.test.ets @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 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 RdbPredicatesEtsTest from './RdbstorePredicatesEts.test.ets'; +import RdbPredicatesPrefEtsTest from './RdbPredicatesPerfEts.test.ets'; +import RelationalStoreDataGroupId from './RdbGroupIdEts.test.ets'; +import PerfStatEtsTest from './RdbstorePerfStatEts.test.ets'; +import RdbRekeyEtsTest from './RdbstoreRekeyEts.test.ets'; +import RdbStoreErrorlogTest from './RdbOnErrorLog.test.ets'; +import RDBstoreGetSqlInfoTest from './RdbstoreGetSqlInfoEts.test.ets'; +import RdbStoreTransactionTest from './RdbStoreTransaction.test.ets'; +import RdbstoreTransactionJsunit from './RdbstoreTransactionJsunit.test.ets'; +import RdbStoreTransInsertJsunit from './RdbStoreTransInsertJsunit.test.ets'; +import RdbStoreTransJsunit from './RdbStoreTransJsunit.test.ets'; +import ExecuteSqlTest from './RdbStoreExecuteSql.test.ets'; +import RdbstoreCustomTokenizerTest from './RdbstoreCustomTokenizerEts.ets'; +import SetLocaleEtsTest from './RdbstoreSetLocaleEts.test.ets'; +import RelationalStoreEtsTest from './RelationalStoreEtsTest.test.ets' +export default function testsuite() { + RdbPredicatesEtsTest(); + RdbPredicatesPrefEtsTest(); + RelationalStoreDataGroupId(); + PerfStatEtsTest(); + RdbRekeyEtsTest(); + RdbStoreErrorlogTest(); + RDBstoreGetSqlInfoTest(); + RdbStoreTransactionTest(); + RdbstoreTransactionJsunit(); + RdbStoreTransInsertJsunit(); + RdbStoreTransJsunit(); + ExecuteSqlTest(); + RdbstoreCustomTokenizerTest(); + SetLocaleEtsTest(); + RelationalStoreEtsTest(); +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbGroupIdEts.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbGroupIdEts.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..46aeec4def702de531d67305b6109306080b6cc9 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbGroupIdEts.test.ets @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level, Size, TestType } from "@ohos/hypium"; +import relationalStore from '@ohos.data.relationalStore'; +import common from "@ohos.app.ability.common" +import contextConstant from '@ohos.app.ability.contextConstant'; +let context: common.UIAbilityContext + +const TAG = "[RDB_GROUPID_TEST]"; +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT NOT NULL, " + + "age INTEGER, " + + "salary REAL, " + + "blobType BLOB)"; + +async function crudTest(store:relationalStore.RdbStore):Promise +{ + await store?.executeSql(CREATE_TABLE_TEST); + let values:relationalStore.ValuesBucket = { + name:"zhangsan", + age:20, + salary:1.5 + } + let insertNum:number = await store?.insert("test", values) as number; + expect(insertNum).assertEqual(1); + let pre:relationalStore.RdbPredicates = new relationalStore.RdbPredicates("test"); + let resultSet:relationalStore.ResultSet = await store?.query(pre) as relationalStore.ResultSet; + expect(resultSet.rowCount).assertEqual(1); + expect(resultSet.goToFirstRow()).assertEqual(true); + let row:relationalStore.ValuesBucket = resultSet.getRow(); + expect(row.name).assertEqual("zhangsan"); + resultSet.close(); + + values.name = "lisi"; + pre.equalTo("name", "zhangsan"); + let updateNum:number = await store?.update(values, pre) as number; + expect(updateNum).assertEqual(1); + let pre1:relationalStore.RdbPredicates = new relationalStore.RdbPredicates("test"); + resultSet = await store?.query(pre1) as relationalStore.ResultSet; + expect(resultSet.goToFirstRow()).assertEqual(true); + row = resultSet.getRow(); + expect(row.name).assertEqual("lisi"); + resultSet.close(); + + pre1.equalTo("name", "lisi"); + let deleteNum:number = await store?.delete(pre1) as number; + expect(deleteNum).assertEqual(1); + resultSet = await store?.query(pre) as relationalStore.ResultSet; + expect(resultSet.rowCount).assertEqual(0); + resultSet.close(); +} + +export default function RelationalStoreDataGroupId() { + describe('relationalStoreDataGroupId', () => { + beforeAll(() => { + console.info(TAG + 'beforeAll') + context = globalThis.abilityContext; + }) + + beforeEach(() => { + console.info(TAG + 'beforeEach') + }) + + afterEach(() => { + console.info(TAG + 'afterEach') + }) + + afterAll(async () => { + console.info(TAG + 'afterAll') + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.number SUB_DistributedData_RelationalStore_SDK_GetRdbStoreJsAPITest_0100 + * @tc.name relationalStore dataGroupId null test + * @tc.desc relationalStore getRdbStore dataGroupId null test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 0 + */ + it('SUB_DDM_RelationalStore_DataGroupId_0100', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL0, async () => { + const STORE_CONFIG: relationalStore.StoreConfig = { + name: "RdbTest.db", + securityLevel: relationalStore.SecurityLevel.S1, + dataGroupId: null, + }; + try { + let rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + console.info(TAG, `Get RdbStore successfully.`); + expect(rdbStore != undefined).assertTrue(); + await relationalStore.deleteRdbStore(context, STORE_CONFIG); + } catch (errInfo) { + console.error(TAG, `failed, code is ${errInfo.code},message is ${errInfo.message}`); + expect().assertFail(); + } + }) + + /** + * @tc.number SUB_DistributedData_RelationalStore_SDK_GetRdbStoreJsAPITest_0200 + * @tc.name relationalStore dataGroupId undefined callback test + * @tc.desc relationalStore getRdbStore dataGroupId undefined test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 0 + */ + it('SUB_DDM_RelationalStore_DataGroupId_0200', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL0, async () => { + const STORE_CONFIG: relationalStore.StoreConfig = { + name: "RdbTest.db", + securityLevel: relationalStore.SecurityLevel.S1, + dataGroupId: undefined, + }; + try { + let rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + console.info(TAG, `Get RdbStore successfully.`); + expect(rdbStore != undefined).assertTrue(); + await relationalStore.deleteRdbStore(context, STORE_CONFIG); + } catch (errInfo) { + expect().assertFail(); + } + }) + + + /** + * @tc.number SUB_DistributedData_RelationalStore_SDK_GetRdbStoreJsAPITest_0300 + * @tc.name relationalStore dataGroupId callback test + * @tc.desc relationalStore getRdbStore dataGroupId test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 0 + */ + it('SUB_DDM_RelationalStore_DataGroupId_0300', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL0, async () => { + const STORE_CONFIG: relationalStore.StoreConfig = { + name: "RdbTest.db", + securityLevel: relationalStore.SecurityLevel.S1, + dataGroupId: '112233', + }; + try { + await relationalStore.getRdbStore(context, STORE_CONFIG); + console.info(TAG, `Get RdbStore successfully.`); + expect().assertFail(); + } catch (errInfo) { + console.error(TAG, `failed, code is ${errInfo.code},message is ${errInfo.message}`); + expect(errInfo.code == 14801002).assertTrue(); + } + }) + + /** + * @tc.number SUB_DistributedData_RelationalStore_SDK_GetRdbStoreJsAPITest_0400 + * @tc.name relationalStore dataGroupId callback test + * @tc.desc relationalStore deleteRdbStore dataGroupId test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 0 + */ + it('SUB_DDM_RelationalStore_DataGroupId_0400', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL0, async () => { + const STORE_CONFIG: relationalStore.StoreConfig = { + name: "RdbTest.db", + securityLevel: relationalStore.SecurityLevel.S1, + dataGroupId: '123456', + }; + try { + let rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + console.info(TAG, `Get RdbStore successfully.`); + expect(rdbStore != undefined).assertTrue(); + await relationalStore.deleteRdbStore(context, STORE_CONFIG); + } catch (errInfo) { + console.error(TAG, `failed, code is ${errInfo.code},message is ${errInfo.message}`); + expect().assertFail(); + } + }) + + /** + * @tc.number SUB_DistributedData_RelationalStore_SDK_GetRdbStoreJsAPITest_0400 + * @tc.name relationalStore dataGroupId callback test + * @tc.desc relationalStore deleteRdbStore dataGroupId test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 0 + */ + it('SUB_DDM_RelationalStore_DataGroupId_0400', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL0, async () => { + const STORE_CONFIG: relationalStore.StoreConfig = { + name: "RdbTest.db", + securityLevel: relationalStore.SecurityLevel.S1, + dataGroupId: '123456', + }; + try { + let rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + console.info(TAG, `Get RdbStore successfully.`); + expect(rdbStore != undefined).assertTrue(); + await relationalStore.deleteRdbStore(context, STORE_CONFIG); + } catch (errInfo) { + console.error(TAG, `failed, code is ${errInfo.code},message is ${errInfo.message}`); + expect().assertFail(); + } + }) + + /** + * @tc.number SUB_DistributedData_RelationalStore_SDK_GetRdbStoreJsAPITest_0500 + * @tc.name relationalStore dataGroupId el3 test + * @tc.desc relationalStore deleteRdbStore dataGroupId test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 0 + */ + it('SUB_DDM_RelationalStore_DataGroupId_0500', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL0, async () => { + const STORE_CONFIG: relationalStore.StoreConfig = { + name: "RdbTest.db", + securityLevel: relationalStore.SecurityLevel.S1, + dataGroupId: '123456', + }; + let contextEl3:Context = context.createAreaModeContext(contextConstant.AreaMode.EL3); + let groupDir:string = await contextEl3.getGroupDir("123456"); + console.info(TAG, "DataGroupId groupDir:" + groupDir); + try { + let store:relationalStore.RdbStore = await relationalStore.getRdbStore(contextEl3, STORE_CONFIG); + await crudTest(store); + await relationalStore.deleteRdbStore(contextEl3, STORE_CONFIG); + } catch (errInfo) { + console.error(TAG, `failed, code is ${errInfo.code},message is ${errInfo.message}`); + expect().assertFail(); + } + }) + + /** + * @tc.number SUB_DistributedData_RelationalStore_SDK_GetRdbStoreJsAPITest_0600 + * @tc.name relationalStore dataGroupId el4 test + * @tc.desc relationalStore deleteRdbStore dataGroupId test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 0 + */ + it('SUB_DDM_RelationalStore_DataGroupId_0600', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL0, async () => { + const STORE_CONFIG: relationalStore.StoreConfig = { + name: "RdbTest.db", + securityLevel: relationalStore.SecurityLevel.S1, + dataGroupId: '123456', + }; + let contextEl4:Context = context.createAreaModeContext(contextConstant.AreaMode.EL4); + let groupDir:string = await contextEl4.getGroupDir("123456"); + console.info(TAG, "DataGroupId groupDir:" + groupDir); + try { + let store:relationalStore.RdbStore = await relationalStore.getRdbStore(contextEl4, STORE_CONFIG); + await crudTest(store); + await relationalStore.deleteRdbStore(contextEl4, STORE_CONFIG); + } catch (errInfo) { + console.error(TAG, `failed, code is ${errInfo.code},message is ${errInfo.message}`); + expect().assertFail(); + } + }) + console.info(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbOnErrorLog.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbOnErrorLog.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..72d3b3ba1eecdb5bbb85ea722e21ef704f331b7f --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbOnErrorLog.test.ets @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level, Size, TestType } from "@ohos/hypium"; +import data_relationalStore from '@ohos.data.relationalStore'; +import abilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; + +let context = abilityDelegatorRegistry.getAbilityDelegator().getAppContext().getApplicationContext(); +const TAG = "[RELATIONAL_STORE_ON_ERROR]" +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; +const CREATE_TABLE_TEST4 = "CREATE TABLE IF NOT EXISTS users (" + "id INTEGER PRIMARY KEY," + "username TEXT UNIQUE," + + "email TEXT NOT NULL)"; +const STORE_CONFIG: data_relationalStore.StoreConfig = { + name: "sqliteErrorOccurred.db", + securityLevel: data_relationalStore.SecurityLevel.S1, +} + +let rdbStore: data_relationalStore.RdbStore; + +export default function rdbStoreSqliteErrorOccurredTest() { + describe('rdbStoreSqliteErrorOccurredTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll') + }) + beforeEach(async (done: Function) => { + console.info(TAG + 'beforeEach') + rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); + await rdbStore.executeSql(CREATE_TABLE_TEST); + await rdbStore.executeSql(CREATE_TABLE_TEST4); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucketUser: data_relationalStore.ValuesBucket = { + "username": 'user1', + "email": 'user1@example.com', + }; + await rdbStore.insert("users", valueBucketUser); + const valueBucket: data_relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket); + done(); + }) + + afterEach(async (done: Function) => { + console.info(TAG + 'afterEach') + try { + rdbStore.off('sqliteErrorOccurred'); + await rdbStore.close(); + } catch (err) { + console.log(`afterEach error, failed code:${err.code},message:${err.message}`); + } + await data_relationalStore.deleteRdbStore(context, "sqliteErrorOccurred.db"); + done(); + }) + afterAll(async () => { + console.info(TAG + 'afterAll') + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.number SUB_DDM_AppDataFWK_JSRDB_OnsqliteErrorOccurred_0001 + * @tc.name Normal test case of OnsqliteErrorOccurred Already closed + * @tc.desc 1.create db 2.close db 3.OnsqliteErrorOccurred + */ + it('testRdbStoreOnsqliteErrorOccurred0001', 0, async (done: Function) => { + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0001 start *************"); + try { + rdbStore.close(); + let exceptionMessage: data_relationalStore.ExceptionMessage; + rdbStore.on('sqliteErrorOccurred', exceptionMessage => { + console.log(`error log is ${exceptionMessage.code}`) + }); + } catch (err) { + expect(err.code == 14800014).assertTrue(); + console.error(`error is failed code:${err.code},message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0001 end *************"); + }) + + /** + * @tc.number SUB_DDM_AppDataFWK_JSRDB_OnsqliteErrorOccurred_0002 + * @tc.name Normal test case of OnsqliteErrorOccurred SQLITE_ERROR + * @tc.desc 1.OnsqliteErrorOccurred 2.execute sql with SQLITE_ERROR + */ + it('testRdbStoreOnsqliteErrorOccurred0002', 0, async (done: Function) => { + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0002 start *************"); + try { + let exceptionMessage: data_relationalStore.ExceptionMessage; + rdbStore.on('sqliteErrorOccurred', exceptionMessage => { + let sqliteCode = exceptionMessage.code; + let sqliteMessage = exceptionMessage.message; + let errSQL = exceptionMessage.sql; + console.info(`error log is ${sqliteCode}, errMessage is ${sqliteMessage}, errSQL is ${errSQL}`); + expect(sqliteCode == 1).assertTrue(); + expect(sqliteMessage == "table test has no column named exsc").assertTrue(); + expect(errSQL == "INSERT INTO test(age,blobType,exsc,name,salary) VALUES (?,?,?,?,?)").assertTrue(); + done(); + }); + console.log(`sqliteErrorOccurred on is success`); + } catch (err) { + console.error(`sqliteErrorOccurred on is failed ${err.code}`); + } + try { + let u8: Uint8Array = new Uint8Array([1, 2, 3]); + const valueBucket: data_relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + "exsc": 100, + } + await rdbStore.insert("test", valueBucket); + expect(true).assertFail(); + } catch (err) { + console.error(`sqliteErrorOccurred on is failed code:${err.code},message:${err.message}`); + expect(err.code == 14800021).assertTrue(); + } + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0002 end *************"); + }) + + /** + * @tc.number SUB_DDM_AppDataFWK_JSRDB_OnsqliteErrorOccurred_0003 + * @tc.name Normal test case of OnsqliteErrorOccurred SQLITE_MISMATCH + * @tc.desc 1.Insert data + */ + it('testRdbStoreOnsqliteErrorOccurred0003', 0, async (done: Function) => { + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0003 start *************"); + try { + let exceptionMessage: data_relationalStore.ExceptionMessage; + rdbStore.on('sqliteErrorOccurred', exceptionMessage => { + let sqliteCode = exceptionMessage.code; + let sqliteMessage = exceptionMessage.message; + let errSQL = exceptionMessage.sql; + expect(sqliteCode == 20).assertTrue(); + expect(sqliteMessage == "datatype mismatch").assertTrue(); + expect(errSQL == "INSERT INTO test(age,blobType,id,name,salary) VALUES (?,?,?,?,?)").assertTrue(); + console.info(`errCode is ${sqliteCode}, errMessage is ${sqliteMessage}, errSQL is ${errSQL}`); + done(); + }); + } catch (err) { + console.error(`err log failed, code is ${err.code},message is ${err.message}`); + expect(true).assertFail(); + } + let u8 = new Uint8Array([1, 2, 3]); + let transaction = await rdbStore?.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + try { + const valueBucket: data_relationalStore.ValuesBucket = { + "id": "test", + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + let row = transaction?.insertSync("test", valueBucket); + console.log(TAG + "testRdbStoreOnsqliteErrorOccurred0003 insert row:" + row); + expect(true).assertFail(); + await transaction?.commit(); + } catch (e) { + await transaction?.rollback(); + console.log(TAG + e + " code: " + e.code); + expect(e.code == 14800033).assertTrue(); + console.log(TAG + "testRdbStoreOnsqliteErrorOccurred0003 failed"); + } + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0003 end *************"); + }) + + /** + * @tc.number SUB_DDM_AppDataFWK_JSRDB_OnsqliteErrorOccurred_0004 + * @tc.name Normal test case of OnsqliteErrorOccurred performance + * @tc.desc 1.Insert data + */ + it('testRdbStoreOnsqliteErrorOccurred0004', 0, async (done: Function) => { + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0004 start *************"); + try { + let averageTime = 0; + let startTime = new Date().getTime(); + for (let i = 0; i < 2000; ++i) { + let exceptionMessage: data_relationalStore.ExceptionMessage | undefined = undefined; + rdbStore.on('sqliteErrorOccurred', exceptionMessage => { + }); + } + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / 2000; + expect(averageTime < 1000).assertTrue(); + console.info(TAG + " testRdbStoreOnsqliteErrorOccurred0004 average time is: " + averageTime + " μs"); + } catch (err) { + console.error(`on err log failed, code is ${err.code},message is ${err.message}`); + expect(true).assertFail(); + } + rdbStore.off('sqliteErrorOccurred'); + done(); + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0004 end *************"); + }) + + /** + * @tc.number SUB_DDM_AppDataFWK_JSRDB_OnsqliteErrorOccurred_0005 + * @tc.name Normal test case of OnsqliteErrorOccurred and offsqliteErrorOccurred + * @tc.desc 1.Insert data + */ + it('testRdbStoreOnsqliteErrorOccurred0005', 0, async (done: Function) => { + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0005 start *************"); + try { + let exceptionMessage: data_relationalStore.ExceptionMessage; + rdbStore.on('sqliteErrorOccurred', exceptionMessage => { + expect(exceptionMessage.code === 0).assertTrue(); + }); + rdbStore.off('sqliteErrorOccurred'); + } catch (err) { + console.error(`sqliteErrorOccurred on is failed ${err.code}`); + } + try { + let u8: Uint8Array = new Uint8Array([1, 2, 3]); + const valueBucket: data_relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + "exsc": 100, + } + await rdbStore.insert("test", valueBucket); + expect().assertFail(); + } catch (err) { + console.error(`sqliteErrorOccurred on is failed code:${err.code},message:${err.message}`); + expect(true).assertTrue(); + } + done(); + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0005 end *************"); + }) + + /** + * @tc.number SUB_DDM_AppDataFWK_JSRDB_OnsqliteErrorOccurred_0006 + * @tc.name Abormal test case of OnErrorlog + * @tc.desc 1.Insert data + */ + it('testRdbStoreOnsqliteErrorOccurred0006', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0006 start *************"); + if (!data_relationalStore.isVectorSupported()) { + done() + return + } + let STORE_CONFIG1: data_relationalStore.StoreConfig = { + name: 'rdbStore2.db', + securityLevel: data_relationalStore.SecurityLevel.S1, + vector: true, + }; + let rdbStore1 = await data_relationalStore.getRdbStore(context, STORE_CONFIG1) + try{ + rdbStore1.on('sqliteErrorOccurred', exceptionMessage => { + expect().assertFail(); + }); + expect().assertFail(); + done(); + } catch (err){ + expect(err.code).assertEqual("801"); + done() + } + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0006 end *************"); + }) + + /** + * @tc.number SUB_DDM_AppDataFWK_JSRDB_OnsqliteErrorOccurred_0007 + * @tc.name Abnormal test case of offErrorlog + * @tc.desc 1.Insert data + */ + it('testRdbStoreOnsqliteErrorOccurred0007', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0007 start *************"); + if (!data_relationalStore.isVectorSupported()) { + done() + return + } + let STORE_CONFIG1: data_relationalStore.StoreConfig = { + name: 'rdbStore2.db', + securityLevel: data_relationalStore.SecurityLevel.S1, + vector: true, + }; + let rdbStore1 = await data_relationalStore.getRdbStore(context, STORE_CONFIG1) + try{ + rdbStore1.off('sqliteErrorOccurred'); + expect().assertFail(); + done(); + } catch (err){ + expect(err.code).assertEqual("801"); + done() + } + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0007 end *************"); + }) + + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/js/gdb/performance/src/GdbHelperPromisePerf.js b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbPredicatesPerfEts.test.ets similarity index 30% rename from relational_store/test/js/gdb/performance/src/GdbHelperPromisePerf.js rename to relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbPredicatesPerfEts.test.ets index 7bba8fc6266d532b84543f3dcef5ec089224ed3f..e65e75d67d7edd8c47111c42e209843a56cc5960 100644 --- a/relational_store/test/js/gdb/performance/src/GdbHelperPromisePerf.js +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbPredicatesPerfEts.test.ets @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Huawei Device Co., Ltd. + * Copyright (C) 2025 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 @@ -12,65 +12,48 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert } from 'deccjsunit/index'; -import graphStore from '@ohos.data.graphStore'; -import featureAbility from '@ohos.ability.featureAbility'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; +import relationalStore from '@ohos.data.relationalStore' import deviceInfo from '@ohos.deviceInfo'; -const TAG = "[GDBHELPER_PROMISE]"; -const DB_NAME = "gdbPromise"; -const STORE_CONFIG = { - name: DB_NAME, - securityLevel: graphStore.SecurityLevel.S1 -} -let context = featureAbility.getContext(); -let store; +const TAG = "[RDB_PREDICATES_PERF]"; const BASE_COUNT = 2000; // loop times -const BASE_LINE_TABLE = 2500; // callback tablet base line -const BASE_LINE_PHONE = 3000; // callback phone base line -const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; +const HAVING_BASE_LINE_TABLE = 50; // callback tablet base line +const HAVING_BASE_LINE_PHONE = 100; // callback phone base line +const HAVING_BASE_LINE = (deviceInfo.deviceType == "tablet") ? HAVING_BASE_LINE_TABLE : HAVING_BASE_LINE_PHONE; -describe('gdbHelperPromisePerf', () => { +export default function RdbPredicatesPrefEtsTest() { + describe('rdbPredicatesPrefEtsTest', () => { beforeAll(async () => { - console.info(TAG + 'beforeAll'); - }) + console.info(TAG + 'beforeAll'); + }); beforeEach(async () => { - console.info(TAG + 'beforeEach'); - }) + console.info(TAG + 'beforeEach'); + }); afterEach(async () => { - console.info(TAG + 'afterEach'); - }) + console.info(TAG + 'afterEach'); + }); afterAll(async () => { - console.info(TAG + 'afterAll'); - await store.close(); - await graphStore.deleteStore(context, STORE_CONFIG); - }) + console.info(TAG + 'afterAll'); + }); console.log(TAG + "*************Unit Test Begin*************"); - it('Perf_Gdb_GetStore_Promise_001', 0, async () => { - let averageTime = 0; - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - await graphStore.getStore(context, STORE_CONFIG); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the getStore_Promise average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); + it('SUB_DDM_PERF_RDB_Predicates_having', 0, async (done:Function) => { + let conditions: string = "data"; + let predicates:relationalStore.RdbPredicates = new relationalStore.RdbPredicates("tableName"); + predicates.groupBy(["data1"]); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + predicates.having(conditions); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_having average time is: " + averageTime + " μs"); + expect(averageTime < HAVING_BASE_LINE).assertTrue(); + done(); }) - it('Perf_Gdb_DeleteStore_Promise_001', 0, async () => { - let averageTime = 0; - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - await graphStore.deleteStore(context, STORE_CONFIG); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the deleteStore_Promise average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - console.info(TAG + "*************Unit Test End*************") - }) -}) \ No newline at end of file + console.log(TAG + "*************Unit Test End*************"); + }) +} diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreExecuteSql.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreExecuteSql.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0ff88650634703b0f07780a7c5668b2092d315e9 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreExecuteSql.test.ets @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' +import relationalStore from '@ohos.data.relationalStore' + +let context = globalThis.abilityContext; + +const TAG = "[RELATIONAL_STORE_TRANSACTION_JSKITS_TEST]" + +const STORE_CONFIG = { + name: "executeSqlTest.db", + securityLevel: relationalStore.SecurityLevel.S1, +} + +let rdbStore: relationalStore.RdbStore | undefined; + +export default function ExecuteSqlTest() { + describe('executeSqlTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll') + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + }) + + beforeEach(async () => { + console.info(TAG + 'beforeEach') + }) + + afterEach(async () => { + console.info(TAG + 'afterEach') + }) + + afterAll(async () => { + console.info(TAG + 'afterAll') + rdbStore = undefined; + await relationalStore.deleteRdbStore(context, "executeSqlTest.db"); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.number concurrentExecuteDDLSQLTest0001 + * @tc.name Normal test case of executeSql, create table in multi-threaded environment + * @tc.desc execute DDL by executeSql + */ + it('concurrentExecuteDDLSQLTest0001', 0, async () => { + console.log(TAG + "************* concurrentExecuteDDLSQLTest0001 start *************"); + const CREATE_TABLE = "CREATE TABLE IF NOT EXISTS test"; + const CREATE_TABLE_COLUMN = "(id INTEGER PRIMARY KEY, name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"; + const CREATE_INDEX = "CREATE INDEX IF NOT EXISTS indexTest"; + const CREATE_INDEX_TABLE = "ON test"; + const CREATE_INDEX_COLUMN = "(age)"; + + try { + await Promise.all(new Array(50).fill(0).map(async (value, index) => { + if (rdbStore == undefined) { + expect(null).assertFail(); + return; + } + await rdbStore.executeSql(CREATE_TABLE + index + " " + CREATE_TABLE_COLUMN); + await rdbStore.executeSql(CREATE_INDEX + index + " " + CREATE_INDEX_TABLE + index + " " + CREATE_INDEX_COLUMN); + })) + expect(true).assertTrue(); + } catch (error) { + console.error(`${TAG} error in concurrentExecuteDDLSQLTest0001, code: ${error?.code} message: ${error?.message}`); + expect(null).assertFail(); + } + console.log(TAG + "************* concurrentExecuteDDLSQLTest0001 end *************"); + }) + console.log(TAG + "*************Unit Test End*************"); + }) +} diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransInsertJsunit.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransInsertJsunit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..fd8302e4a270e2e9e3db7dd5be939e523f640f57 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransInsertJsunit.test.ets @@ -0,0 +1,947 @@ +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' +import data_relationalStore from '@ohos.data.relationalStore' +import ability_featureAbility from '@ohos.ability.featureAbility' + +var context = globalThis.abilityContext; + +const TAG = "[RELATIONAL_STORE_TRANSACTION_JSKITS_TEST]" +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; + +const STORE_CONFIG = { + name: "TransactionTest.db", + securityLevel: data_relationalStore.SecurityLevel.S3, +} + +var rdbStore = undefined; + +export default function () { + describe('rdbStoreTransactionJsunitTest', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll') + rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + }) + + beforeEach(async function () { + console.info(TAG + 'beforeEach') + + }) + + afterEach(async function () { + console.info(TAG + 'afterEach') + await rdbStore.executeSql("DELETE FROM test"); + }) + + afterAll(async function () { + console.info(TAG + 'afterAll') + rdbStore = null + await data_relationalStore.deleteRdbStore(context, "TransactionTest.db"); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + + it('testRdbTransInsert0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsert0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsert0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsert0001 failed"); + } + + console.log(TAG + "************* testRdbTransInsert0001 end *************"); + done(); + }) + + it('testRdbTransInsert0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsert0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsert0002 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsert0002 failed"); + } + + console.log(TAG + "************* testRdbTransInsert0002 end *************"); + done(); + }) + + it('testRdbTransInsert0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsert0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsert0003 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsert0003 failed"); + } + + console.log(TAG + "************* testRdbTransInsert0003 end *************"); + done(); + }) + + it('testRdbTransInsert0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsert0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsert0011 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsert0011 failed"); + } + + console.log(TAG + "************* testRdbTransInsert0011 end *************"); + done(); + }) + + it('testRdbTransInsert0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsert0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsert0012 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsert0012 failed"); + } + + console.log(TAG + "************* testRdbTransInsert0012 end *************"); + done(); + }) + + it('testRdbTransInsert0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsert0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsert0013 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsert0013 failed"); + } + + console.log(TAG + "************* testRdbTransInsert0013 end *************"); + done(); + }) + + it('testRdbTransInsertSync0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsertSync0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = rdbTrans.insertSync("test", valueBucket); + expect(1).assertEqual(rowId); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsertSync0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsertSync0001 failed"); + } + + console.log(TAG + "************* testRdbTransInsertSync0001 end *************"); + done(); + }) + + it('testRdbTransInsertSync0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsertSync0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = rdbTrans.insertSync("test", valueBucket); + expect(1).assertEqual(rowId); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsertSync0002 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsertSync0002 failed"); + } + + console.log(TAG + "************* testRdbTransInsertSync0002 end *************"); + done(); + }) + + it('testRdbTransInsertSync0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsertSync0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = rdbTrans.insertSync("test", valueBucket); + expect(1).assertEqual(rowId); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsertSync0003 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsertSync0003 failed"); + } + + console.log(TAG + "************* testRdbTransInsertSync0003 end *************"); + done(); + }) + + it('testRdbTransInsertSync0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsertSync0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = rdbTrans.insertSync("test", valueBucket); + expect(1).assertEqual(rowId); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsertSync0011 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsertSync0011 failed"); + } + + console.log(TAG + "************* testRdbTransInsertSync0011 end *************"); + done(); + }) + + it('testRdbTransInsertSync0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsertSync0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = rdbTrans.insertSync("test", valueBucket); + expect(1).assertEqual(rowId); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsertSync0012 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsertSync0012 failed"); + } + + console.log(TAG + "************* testRdbTransInsertSync0012 end *************"); + done(); + }) + + it('testRdbTransInsertSync0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsertSync0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = rdbTrans.insertSync("test", valueBucket); + expect(1).assertEqual(rowId); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsertSync0013 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsertSync0013 failed"); + } + + console.log(TAG + "************* testRdbTransInsertSync0013 end *************"); + done(); + }) + + it('testRdbTransBatchInsert0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsert0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = await rdbTrans.batchInsert("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsert0001 result count " + resultSet.rowCount); + expect(100).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsert0001 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsert0001 end *************"); + done(); + }) + + it('testRdbTransBatchInsert0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsert0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = await rdbTrans.batchInsert("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsert0002 result count " + resultSet.rowCount); + expect(100).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsert0002 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsert0002 end *************"); + done(); + }) + + it('testRdbTransBatchInsert0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsert0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = await rdbTrans.batchInsert("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsert0003 result count " + resultSet.rowCount); + expect(100).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsert0003 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsert0003 end *************"); + done(); + }) + + it('testRdbTransBatchInsert0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsert0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = await rdbTrans.batchInsert("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsert0011 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsert0011 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsert0011 end *************"); + done(); + }) + + it('testRdbTransBatchInsert0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsert0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = await rdbTrans.batchInsert("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsert0012 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsert0012 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsert0012 end *************"); + done(); + }) + + it('testRdbTransBatchInsert0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsert0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = await rdbTrans.batchInsert("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsert0013 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsert0013 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsert0013 end *************"); + done(); + }) + + it('testRdbTransBatchInsertSync0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsertSync0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsertSync0001 result count " + resultSet.rowCount); + expect(100).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsertSync0001 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsertSync0001 end *************"); + done(); + }) + + it('testRdbTransBatchInsertSync0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsertSync0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsertSync0002 result count " + resultSet.rowCount); + expect(100).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsertSync0002 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsertSync0002 end *************"); + done(); + }) + + it('testRdbTransBatchInsertSync0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsertSync0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsertSync0003 result count " + resultSet.rowCount); + expect(100).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsertSync0003 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsertSync0003 end *************"); + done(); + }) + + it('testRdbTransBatchInsertSync0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsertSync0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsertSync0011 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsertSync0011 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsertSync0011 end *************"); + done(); + }) + + it('testRdbTransBatchInsertSync0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsertSync0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsertSync0012 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsertSync0012 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsertSync0012 end *************"); + done(); + }) + + it('testRdbTransBatchInsertSync0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsertSync0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsertSync0013 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsertSync0013 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsertSync0013 end *************"); + done(); + }) + + it('testRdbTransUpdate0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdate0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbTrans.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.update({ age: 20 }, updatePredicates); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdate0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(20); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdate0001 failed"); + } + + console.log(TAG + "************* testRdbTransUpdate0001 end *************"); + done(); + }) + + it('testRdbTransUpdate0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdate0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbTrans.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.update({ age: 20 }, updatePredicates); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdate0002 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(20); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdate0002 failed"); + } + + console.log(TAG + "************* testRdbTransUpdate0002 end *************"); + done(); + }) + + it('testRdbTransUpdate0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdate0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbTrans.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.update({ age: 20 }, updatePredicates); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdate0003 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(20); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdate0003 failed"); + } + + console.log(TAG + "************* testRdbTransUpdate0003 end *************"); + done(); + }) + + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransJsunit.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransJsunit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..4f88f7f1013436aa7c5b610e103ec0a722451a1b --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransJsunit.test.ets @@ -0,0 +1,1988 @@ +/* + * 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. + */ + +// @ts-nocheck +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' +import data_relationalStore from '@ohos.data.relationalStore' + +var context = globalThis.abilityContext; + +const TAG = "[RELATIONAL_STORE_TRANSACTION_JSKITS_TEST]" +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; + +const STORE_CONFIG = { + name: "TransactionTest.db", + securityLevel: data_relationalStore.SecurityLevel.S3, +} + +var rdbStore = undefined; + +async function insertInThread(context, transType, insertCount = 1) { + const TAG = "[RELATIONAL_STORE_JS_KITS_TEST]" + let rdbTrans; + try { + rdbTrans = await rdbStore.createTransaction({ + transactionType: transType + }); + console.log(TAG + 'insertInThread after createTrans'); + + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(insertCount).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }); + const resultCount = await rdbTrans.batchInsert("test", valueBuckets); + await rdbTrans.commit(); + console.log(TAG + 'insertInThread after commit'); + return resultCount; + } catch (err) { + if (rdbTrans) { + rdbTrans.rollback(); + } + console.error(TAG + "************* testRdbTransInsert error thread insert *************"); + console.error(TAG + JSON.stringify(err)); + return err.code; + } +} + +async function queryInThread(context, transType, querySql) { + const TAG = "[RELATIONAL_STORE_JS_KITS_TEST]" + let rdbTrans; + try { + rdbTrans = await rdbStore.createTransaction({ + transactionType: transType + }); + + const resultSet = await rdbTrans.querySql(querySql); + const rowCount = resultSet.rowCount; + + await rdbTrans.commit(); + return rowCount; + } catch (err) { + if (rdbTrans) { + rdbTrans.rollback(); + } + console.error(TAG + "************* testRdbTransInsert error thread insert *************"); + console.error(TAG + JSON.stringify(err)); + return err.code; + } +} + +export default function () { + describe('rdbStoreTransactionJsunitTest', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll') + rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + }) + + beforeEach(async function () { + console.info(TAG + 'beforeEach') + + }) + + afterEach(async function () { + console.info(TAG + 'afterEach') + await rdbStore.executeSql("DELETE FROM test"); + }) + + afterAll(async function () { + console.info(TAG + 'afterAll') + rdbStore = null + await data_relationalStore.deleteRdbStore(context, "TransactionTest.db"); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + it('testRdbTransUpdate0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdate0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbStore.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.update({ age: 20 }, updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdate0011 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(18); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdate0011 failed"); + } + + console.log(TAG + "************* testRdbTransUpdate0011 end *************"); + done(); + }) + + it('testRdbTransUpdate0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdate0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbStore.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.update({ age: 20 }, updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdate0012 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(18); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdate0012 failed"); + } + + console.log(TAG + "************* testRdbTransUpdate0012 end *************"); + done(); + }) + + it('testRdbTransUpdate0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdate0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbStore.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.update({ age: 20 }, updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdate0013 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(18); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdate0013 failed"); + } + + console.log(TAG + "************* testRdbTransUpdate0013 end *************"); + done(); + }) + + it('testRdbTransUpdateSync0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdateSync0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbTrans.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + rdbTrans.updateSync({ age: 20 }, updatePredicates); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdateSync0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(20); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdateSync0001 failed"); + } + + console.log(TAG + "************* testRdbTransUpdateSync0001 end *************"); + done(); + }) + + it('testRdbTransUpdateSync0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdateSync0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbTrans.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + rdbTrans.updateSync({ age: 20 }, updatePredicates); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdateSync0002 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(20); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdateSync0002 failed"); + } + + console.log(TAG + "************* testRdbTransUpdateSync0002 end *************"); + done(); + }) + + it('testRdbTransUpdateSync0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdateSync0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbTrans.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + rdbTrans.updateSync({ age: 20 }, updatePredicates); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdateSync0003 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(20); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdateSync0003 failed"); + } + + console.log(TAG + "************* testRdbTransUpdateSync0003 end *************"); + done(); + }) + + it('testRdbTransUpdateSync0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdateSync0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbStore.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + rdbTrans.updateSync({ age: 20 }, updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdateSync0011 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(18); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdateSync0011 failed"); + } + + console.log(TAG + "************* testRdbTransUpdateSync0011 end *************"); + done(); + }) + + it('testRdbTransUpdateSync0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdateSync0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbStore.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + rdbTrans.updateSync({ age: 20 }, updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdateSync0012 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(18); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdateSync0012 failed"); + } + + console.log(TAG + "************* testRdbTransUpdateSync0012 end *************"); + done(); + }) + + it('testRdbTransUpdateSync0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdateSync0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbStore.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + rdbTrans.updateSync({ age: 20 }, updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdateSync0013 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(18); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdateSync0013 failed"); + } + + console.log(TAG + "************* testRdbTransUpdateSync0013 end *************"); + done(); + }) + + it('testRdbTransDelete0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransDelete0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = await rdbTrans.delete(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDelete0001 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDelete0001 failed"); + } + + console.log(TAG + "************* testRdbTransDelete0001 end *************"); + done(); + }) + + it('testRdbTransDelete0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransDelete0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = await rdbTrans.delete(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDelete0002 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDelete0002 failed"); + } + + console.log(TAG + "************* testRdbTransDelete0002 end *************"); + done(); + }) + + it('testRdbTransDelete0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransDelete0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = await rdbTrans.delete(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDelete0003 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDelete0003 failed"); + } + + console.log(TAG + "************* testRdbTransDelete0003 end *************"); + done(); + }) + + it('testRdbTransDelete0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransDelete0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.delete(updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDelete0011 result count " + resultSet.rowCount); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDelete0011 failed"); + } + + console.log(TAG + "************* testRdbTransDelete0011 end *************"); + done(); + }) + + it('testRdbTransDelete0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransDelete0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.delete(updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDelete0012 result count " + resultSet.rowCount); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDelete0012 failed"); + } + + console.log(TAG + "************* testRdbTransDelete0012 end *************"); + done(); + }) + + it('testRdbTransDelete0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransDelete0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.delete(updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDelete0013 result count " + resultSet.rowCount); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDelete0013 failed"); + } + + console.log(TAG + "************* testRdbTransDelete0013 end *************"); + done(); + }) + + it('testRdbTransDeleteSync0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransDeleteSync0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = rdbTrans.deleteSync(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDeleteSync0001 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDeleteSync0001 failed"); + } + + console.log(TAG + "************* testRdbTransDeleteSync0001 end *************"); + done(); + }) + + it('testRdbTransDeleteSync0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransDeleteSync0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = rdbTrans.deleteSync(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDeleteSync0002 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDeleteSync0002 failed"); + } + + console.log(TAG + "************* testRdbTransDeleteSync0002 end *************"); + done(); + }) + + it('testRdbTransDeleteSync0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransDeleteSync0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = rdbTrans.deleteSync(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDeleteSync0003 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDeleteSync0003 failed"); + } + + console.log(TAG + "************* testRdbTransDeleteSync0003 end *************"); + done(); + }) + + it('testRdbTransDeleteSync0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransDeleteSync0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = rdbTrans.deleteSync(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDeleteSync0011 result count " + resultSet.rowCount); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDeleteSync0011 failed"); + } + + console.log(TAG + "************* testRdbTransDeleteSync0011 end *************"); + done(); + }) + + it('testRdbTransDeleteSync0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransDeleteSync0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = rdbTrans.deleteSync(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDeleteSync0012 result count " + resultSet.rowCount); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDeleteSync0012 failed"); + } + + console.log(TAG + "************* testRdbTransDeleteSync0012 end *************"); + done(); + }) + + it('testRdbTransDeleteSync0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransDeleteSync0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = rdbTrans.deleteSync(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDeleteSync0013 result count " + resultSet.rowCount); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDeleteSync0013 failed"); + } + + console.log(TAG + "************* testRdbTransDeleteSync0013 end *************"); + done(); + }) + + it('testRdbTransQuery0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransQuery0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbTrans.query(predicates); + console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + await rdbTrans.commit(); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransQuery0001 failed"); + } + + console.log(TAG + "************* testRdbTransQuery0001 end *************"); + done(); + }) + + it('testRdbTransQuery0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransQuery0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbTrans.query(predicates); + console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + await rdbTrans.commit(); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransQuery0002 failed"); + } + + console.log(TAG + "************* testRdbTransQuery0002 end *************"); + done(); + }) + + it('testRdbTransQuery0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransQuery0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbTrans.query(predicates); + console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + await rdbTrans.commit(); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransQuery0003 failed"); + } + + console.log(TAG + "************* testRdbTransQuery0003 end *************"); + done(); + }) + + it('testRdbTransQuery0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransQuery0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbTrans.querySync(predicates); + console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + await rdbTrans.commit(); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransQuery0011 failed"); + } + + console.log(TAG + "************* testRdbTransQuery0011 end *************"); + done(); + }) + + it('testRdbTransQuery0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransQuery0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbTrans.querySync(predicates); + console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + await rdbTrans.commit(); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransQuery0012 failed"); + } + + console.log(TAG + "************* testRdbTransQuery0012 end *************"); + done(); + }) + + it('testRdbTransQuery0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransQuery0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbTrans.querySync(predicates); + console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + await rdbTrans.commit(); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransQuery0013 failed"); + } + + console.log(TAG + "************* testRdbTransQuery0013 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0001 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0001 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0001 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0002 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0002 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0002 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0003 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0003 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0003 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0004', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0004 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + console.log(TAG + "before second trans create"); + const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); + console.log(TAG + "after second trans create"); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + console.log(TAG + "before query predicates create"); + let predicates = new data_relationalStore.RdbPredicates("test"); + console.log(TAG + "after query predicates create"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0004 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0004 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0004 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0005', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0005 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0005 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0005 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0005 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0006', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0006 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0006 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0006 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0006 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0007', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0007 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0007 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0007 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0007 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0008', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0008 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await insertInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 10); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0008 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0008 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0008 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0009', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0009 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await insertInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 10); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0009 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0009 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0009 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const rowCount = await queryInThread(context, data_relationalStore.TransactionType.DEFERRED, 'select * from test'); + expect(rowCount).assertEqual(0); + + await rdbTrans.commit(); + + { + const rowCount = await queryInThread(context, data_relationalStore.TransactionType.DEFERRED, 'select * from test'); + expect(rowCount).assertEqual(10); + } + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0001 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0001 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0001 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const rowCount = await queryInThread(context, data_relationalStore.TransactionType.DEFERRED, 'select * from test'); + expect(rowCount).assertEqual(0); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0002 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0002 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0002 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + + await rdbStore.batchInsert('test', valueBuckets); + + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const rowCount = await queryInThread(context, data_relationalStore.TransactionType.DEFERRED, 'select * from test'); + expect(rowCount).assertEqual(10); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0003 result count " + resultSet.rowCount); + expect(20).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0003 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0003 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0004', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0004 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await queryInThread(context, data_relationalStore.TransactionType.IMMEDIATE, 'select * from test'); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0004 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0004 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0004 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0005', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0005 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await queryInThread(context, data_relationalStore.TransactionType.IMMEDIATE, 'select * from test'); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0005 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0005 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0005 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0006', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0006 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await queryInThread(context, data_relationalStore.TransactionType.IMMEDIATE, 'select * from test'); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0006 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0006 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0006 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0007', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0007 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await queryInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 'select * from test'); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0007 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0007 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0007 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0008', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0008 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await queryInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 'select * from test'); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0008 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0008 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0008 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0009', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0009 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await queryInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 'select * from test'); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0009 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0009 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0009 end *************"); + done(); + }) + + /** + * @tc.name rdb transaction insert test + * @tc.number testRdbTransactionInsert0001 + * @tc.desc rdb transaction insert & commit, the result comes out is 3 items; + */ + it('testRdbTransactionInsert0001', 0, async (done) => { + console.log(TAG + "************* testRdbStoreInsert0001 start *************"); + const u8 = new Uint8Array([1, 2, 3]); + try { + const rdbTrans = await rdbStore.createTransaction(); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransactionInsert0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransactionInsert0001 failed"); + } + done(); + console.log(TAG + "************* testRdbTransactionInsert0001 end *************"); + }) + + /** + * @tc.name rdb transaction insert test + * @tc.number testRdbTransactionInsert0001 + * @tc.desc rdb transaction insert & commit, the result comes out is 3 items; + */ + it('testRdbTransactionInsert0002', 0, async (done) => { + console.log(TAG + "************* testRdbStoreInsert0002 start *************"); + const u8 = new Uint8Array([1, 2, 3]); + try { + const trans = await rdbStore.createTransaction(); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await trans.insert("test", valueBucket); + const valueBucket1 = { + "name": "zhangsan", + "age": 20, + "salary": 9.5, + "blobType": u8, + }; + await trans.insert("test", valueBucket1); + const valueBucket2 = { + "name": "wangwu", + "age": 16, + "salary": 99, + "blobType": u8, + }; + await trans.insert("test", valueBucket2); + await trans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "testRdbTransactionInsert0002 failed"); + } + done(); + console.log(TAG + "************* testRdbTransactionInsert0002 end *************"); + }) + + /** + * @tc.name rdb transaction insert test + * @tc.number testRdbTransactionInsert0002 + * @tc.desc while using transaction to insert values, querying the db, + * the result comes out is 0; + */ + it('testRdbTransactionInsert0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransactionInsert0003 start *************"); + const u8 = new Uint8Array([1, 2, 3]); + try { + const trans = await rdbStore.createTransaction(); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await trans.insert("test", valueBucket); + const valueBucket1 = { + "name": "zhangsan", + "age": 20, + "salary": 9.5, + "blobType": u8, + }; + await trans.insert("test", valueBucket1); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await trans.query(predicates); + expect(2).assertEqual(resultSet.rowCount); + resultSet.close(); + const valueBucket2 = { + "name": "wangwu", + "age": 16, + "salary": 99, + "blobType": u8, + }; + await trans.insert("test", valueBucket2); + await trans.commit(); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "testRdbTransactionInsert0003 failed"); + } + done(); + console.log(TAG + "************* testRdbTransactionInsert0003 end *************"); + }) + + /** + * @tc.number testRdbTransactionInsert0004 + * @tc.name Abnormal test case of transaction insert, if catch exception then rollback + * @tc.desc 1.Execute beginTransaction + * 2.Insert data (primary key conflict) + * 3.Execute rollBack + * 4.Query data + */ + it('testRdbTransactionRollBack0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransactionRollBack0001 start *************"); + const u8 = new Uint8Array([1, 2, 3]); + const trans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + try { + const valueBucket = { + "id": 1, + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await trans.insert("test", valueBucket); + await trans.insert("test", valueBucket); + trans.commit(); + } catch (e) { + trans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransactionRollBack0001 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } + done(); + console.log(TAG + "************* testRdbTransactionRollBack0001 end *************"); + }) + + /** + * @tc.number testRdbTransactionInsert0005 + * @tc.name Normal test case of transaction, begin transactions within a transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute beginTransaction + * 4.Insert data + * 5.Execute rollBack + * 6.Insert data + * 7.Execute commit + * 8.Query data + */ + it('testRdbTransactionMulti0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransactionMulti0003 start *************"); + const u8 = new Uint8Array([1, 2, 3]); + let trans = await rdbStore.createTransaction(); + const trans2 = await rdbStore.createTransaction(); + try { + const valueBucket = { + "id": 1, + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await trans.insert("test", valueBucket); + console.log(TAG + "before second create trans"); + console.log(TAG + "after second create trans"); + const valueBucket1 = { + "name": "zhangsan", + "age": 20, + "salary": 220.5, + "blobType": u8, + }; + await trans2.insert("test", valueBucket1); + } catch (e) { + expect(e.code).assertEqual(14800024) + await trans.rollback(); + await trans2.rollback(); + console.log(TAG + "testRdbTransactionMulti0003 rollback ***** "); + } + done(); + console.log(TAG + "************* testRdbTransactionMulti0003 end *************"); + }) + + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransaction.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransaction.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0170d9e87f62a5051096c5e1a328b2155a245303 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransaction.test.ets @@ -0,0 +1,2729 @@ +/* + * 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. + */ + +// @ts-nocheck +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' +import data_relationalStore from '@ohos.data.relationalStore' + +var context = globalThis.abilityContext; + +const TAG = "[RELATIONAL_STORE_TRANSACTION_JSKITS_TEST]" +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; +const CREATE_TABLE_TEST1 = "CREATE TABLE IF NOT EXISTS test1 (" + "id INTEGER PRIMARY KEY, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; + +const STORE_CONFIG = { + name: "TransactionTest.db", + securityLevel: data_relationalStore.SecurityLevel.S1, +} + +var rdbStore = undefined; + +export default function () { + describe('rdbStoreTransactionTest', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll') + rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + }) + + beforeEach(async function () { + await rdbStore.executeSql(CREATE_TABLE_TEST); + console.info(TAG + 'beforeEach') + }) + + afterEach(async function () { + try { + await rdbStore.executeSql("DELETE FROM test"); + } catch (error) { + console.error(`${TAG} error in afterEach, code: ${error?.code} message: ${error?.message}`); + } + console.info(TAG + 'afterEach') + }) + + afterAll(async function () { + console.info(TAG + 'afterAll') + rdbStore = null + await data_relationalStore.deleteRdbStore(context, "TransactionTest.db"); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.number testTransactionInsert0001 + * @tc.name Normal test case of transactions, insert a row of data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute commit + * 4.Query data + */ + it('testTransactionInsert0001', 0, async function (done) { + console.log(TAG + "************* testTransactionInsert0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var num = await transaction.insert("test", valueBucket) + expect(1).assertEqual(num); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await transaction.query(predicates) + console.log(TAG + "testTransactionInsert0001 result count " + resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) + resultSet.close() + await transaction.commit() + } catch (e) { + await transaction.commit() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionInsert0001 failed"); + } + done() + console.log(TAG + "************* testTransactionInsert0001 end *************"); + }) + + /** + * @tc.number testTransactionInsert0002 + * @tc.name Abnormal test case of transaction, insert a type mismatch data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute commit + */ + it('testTransactionInsert0002', 0, async function (done) { + console.log(TAG + "************* testTransactionInsert0002 start *************"); + let u8 = new Uint8Array([1, 2, 3]); + let transaction = await rdbStore?.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + try { + const valueBucket = { + "id": "test", + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + let row = transaction?.insertSync("test", valueBucket); + console.log(TAG + "testTransactionInsert0002 insert row:" + row); + expect(null).assertFail(); + await transaction?.commit(); + } catch (e) { + await transaction?.rollback(); + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800033) + console.log(TAG + "testTransactionInsert0002 failed"); + } + done(); + console.log(TAG + "************* testTransactionInsert0002 end *************"); + }) + + /** + * @tc.number testTransactionInsert0003 + * @tc.name Abnormal test case of transaction, insert with an abnormal table + * @tc.desc 1.Execute beginTransaction + * 2.Insert data to a no exist table + * 3.Execute commit + */ + it('testTransactionInsert0003', 0, async function (done) { + console.log(TAG + "************* testTransactionInsert0003 start *************"); + let u8 = new Uint8Array([1, 2, 3]); + let transaction = await rdbStore?.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + try { + const valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + let row = await transaction?.insert("testNotExist", valueBucket); + console.log(TAG + "testTransactionInsert0003 insert row:" + row); + expect(null).assertFail(); + await transaction?.commit(); + } catch (e) { + await transaction?.rollback(); + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800021) + console.log(TAG + "testTransactionInsert0003 failed"); + } + done(); + console.log(TAG + "************* testTransactionInsert0003 end *************"); + }) + + /** + * @tc.number testTransactionInsert0004 + * @tc.name Abnormal test case of transaction, insert an more attribute data + * @tc.desc 1.Execute beginTransaction + * 2.Insert insert an more attribute data + * 3.Execute commit + */ + it('testTransactionInsert0004', 0, async function (done) { + console.log(TAG + "************* testTransactionInsert0004 start *************"); + let u8 = new Uint8Array([1, 2, 3]); + let transaction = await rdbStore?.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + try { + const valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + "notExist": "test" + }; + let row = transaction?.insertSync("test", valueBucket); + console.log(TAG + "testTransactionInsert0004 insert row:" + row); + expect(null).assertFail(); + await transaction?.commit(); + } catch (e) { + await transaction?.rollback(); + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800021) + console.log(TAG + "testTransactionInsert0004 failed"); + } + done(); + console.log(TAG + "************* testTransactionInsert0004 end *************"); + }) + + /** + * @tc.number testTransactionBatchInsert0001 + * @tc.name Normal test case of transactions, insert a row of data + * @tc.desc 1.Execute beginTransaction + * 2.BatchInsert data + * 3.Execute commit + * 4.Query data + */ + it('testTransactionBatchInsert0001', 0, async function (done) { + console.log(TAG + "************* testTransactionBatchInsert0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + for (let i = 0; i < 2; i++) { + valueBucketArray.push(valueBucket); + } + var num = await transaction.batchInsert("test", valueBucketArray) + expect(2).assertEqual(num); + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testTransactionBatchInsert0001 result count " + resultSet.rowCount) + expect(2).assertEqual(resultSet.rowCount) + resultSet.close() + + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionBatchInsert0001 failed"); + } + done() + console.log(TAG + "************* testTransactionBatchInsert0001 end *************"); + }) + + /** + * @tc.number testTransactionUpdate0001 + * @tc.name Normal test case of transactions, insert and update a row of data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 2.Update data + * 3.Execute commit + * 4.Query data + */ + it('testTransactionUpdate0001', 0, async function (done) { + console.log(TAG + "************* testTransactionUpdate0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket) + + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi"); + const updateValueBucket = { + "name": "update", + "age": 28, + "salary": 25, + "blobType": u8, + } + var num = await transaction.update(updateValueBucket, predicates) + expect(1).assertEqual(num); + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testTransactionUpdate0001 result count " + resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) + expect(true).assertEqual(resultSet.goToFirstRow()) + const name = resultSet.getString(resultSet.getColumnIndex("name")) + expect("update").assertEqual(name); + const age = resultSet.getLong(resultSet.getColumnIndex("age")) + expect(28).assertEqual(age); + const salary = resultSet.getLong(resultSet.getColumnIndex("salary")) + expect(25).assertEqual(salary); + resultSet.close() + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionUpdate0001 failed"); + } + done() + console.log(TAG + "************* testTransactionUpdate0001 end *************"); + }) + + /** + * @tc.number testTransactionDelete0001 + * @tc.name Normal test case of transactions, insert and update a row of data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 2.Delete data + * 3.Execute commit + * 4.Query data + */ + it('testTransactionDelete0001', 0, async function (done) { + console.log(TAG + "************* testTransactionDelete0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket) + + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi"); + var num = await transaction.delete(predicates) + expect(1).assertEqual(num); + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testTransactionDelete0001 result count " + resultSet.rowCount) + expect(0).assertEqual(resultSet.rowCount) + resultSet.close() + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionDelete0001 failed"); + } + done() + console.log(TAG + "************* testTransactionDelete0001 end *************"); + }) + + /** + * @tc.number testExecute0001 + * @tc.name Normal test case of Execute, check integrity for store + * @tc.desc 1. Execute sql: PRAGMA integrity_check + * 2. Check returned value + */ + it('testExecute0001', 0, async function (done) { + console.info(TAG + "************* testExecute0001 start *************"); + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + try { + let ret = await transaction.execute("PRAGMA integrity_check"); + expect("ok").assertEqual(ret); + await transaction.commit(); + } catch (err) { + await transaction.rollback(); + expect(null).assertFail(); + console.error(`integrity_check failed, code:${err.code}, message: ${err.message}`); + } + done(); + console.info(TAG + "************* testExecute0001 end *************"); + }) + + + /** + * @tc.number testExecute0002 + * @tc.name Normal test case of ExecuteSql + * @tc.desc 1.Insert data + * 2.ExecuteSql(delete age = "18" OR "20") + * 3.QuerySql + */ + it('testExecute0002', 0, async function (done) { + console.log(TAG + "************* testExecute0002 start *************"); + var transaction = await rdbStore.createTransaction() + var u8 = new Uint8Array([1, 2, 3]) + try { + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + for (let i = 0; i < 3; i++) { + valueBucket.age = valueBucket.age + 1; + var row = await transaction.insert("test", valueBucket) + console.log(TAG + "testExecute0002 insert row " + row) + } + await transaction.execute("DELETE FROM test WHERE age = ? OR age = ?", [21, 20]) + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testExecute0002 transaction.querySql result count " + resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) + expect(true).assertEqual(resultSet.goToFirstRow()) + const age = resultSet.getLong(resultSet.getColumnIndex("age")) + expect(19).assertEqual(age); + await resultSet.close() + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testExecute0002 failed"); + } + done(); + console.log(TAG + "************* testExecute0002 end *************"); + } + ) + + /** + * @tc.number testExecute0003 + * @tc.name Normal test case of ExecuteSql + * @tc.desc 1.Insert data (param is long string) + * 2.Query data + * 3.ExecuteSql (delete age = 19 AND name = nameStr) + * 4.Query data + */ + it('ExecuteSqlTest0003', 0, async function (done) { + console.log(TAG + "************* testExecute0003 start *************"); + var u8 = new Uint8Array([3, 4, 5]) + var transaction = await rdbStore.createTransaction() + var nameStr = "lisi" + "e".repeat(2000) + "zhangsan" + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var row = await transaction.insert("test", valueBucket) + console.log(TAG + "testExecute0003 insert row " + row) + valueBucket.name = nameStr + for (let i = 0; i < 2; i++) { + row = await transaction.insert("test", valueBucket) + valueBucket.age = valueBucket.age + 1; + console.log(TAG + "testExecute0003 insert row " + row) + } + { + let predicates = await new data_relationalStore.RdbPredicates("test") + predicates.equalTo("name", nameStr) + let querySqlPromise = transaction.query(predicates) + querySqlPromise.then(async (resultSet) => { + expect(2).assertEqual(resultSet.rowCount) + resultSet.close() + }).catch((err) => { + expect(null).assertFail(); + }) + await querySqlPromise + } + { + let executeSqlPromise = transaction.execute("DELETE FROM test WHERE age = 19 AND name ='" + nameStr + "'") + executeSqlPromise.then(async () => { + console.log(TAG + "executeSql done."); + }).catch((err) => { + console.log(TAG + "executeSql failed. " + err); + expect(null).assertFail(); + }) + await executeSqlPromise + } + await transaction.commit(); + { + let predicates = await new data_relationalStore.RdbPredicates("test") + predicates.equalTo("name", nameStr) + let querySqlPromise = rdbStore.query(predicates) + querySqlPromise.then(async (resultSet) => { + console.log(TAG + "testExecute0003 rdbStore.querySql result count " + resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) + expect(true).assertEqual(resultSet.goToFirstRow()) + const name = resultSet.getString(resultSet.getColumnIndex("name")) + expect(nameStr).assertEqual(name) + expect(2012).assertEqual(name.length) + expect(18).assertEqual(resultSet.getLong(resultSet.getColumnIndex("age"))) + expect(100.5).assertEqual(resultSet.getDouble(resultSet.getColumnIndex("salary"))) + const blobType = resultSet.getBlob(resultSet.getColumnIndex("blobType")) + expect(3).assertEqual(blobType[0]) + resultSet.close(); + done(); + }).catch((err) => { + console.log(TAG + err); + expect(null).assertFail(); + }) + await querySqlPromise + } + done(); + console.log(TAG + "************* testExecute0003 end *************"); + }) + + /** + * @tc.number testExecute0004 + * @tc.name Normal test case of ExecuteSql, drop table + * @tc.desc 1.Insert data + * 2.ExecuteSql (drop table) + */ + it('testExecute0004', 0, async function (done) { + console.log(TAG + "************* testExecute0004 start *************"); + var u8 = new Uint8Array([3, 4, 5]) + var transaction = await rdbStore.createTransaction() + try { + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + for (let i = 0; i < 3; i++) { + valueBucket.age = valueBucket.age + 1; + valueBucketArray.push(valueBucket); + } + var num = await transaction.batchInsert("test", valueBucketArray) + expect(3).assertEqual(num); + await transaction.execute("DROP TABLE IF EXISTS test") + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testExecute0004 transaction.querySql result count " + resultSet.rowCount) + expect(resultSet.rowCount < 1).assertTrue() + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testExecute0004 failed"); + } + done(); + console.log(TAG + "************* testExecute0004 end *************"); + }) + + /** + * @tc.number testExecute0005 + * @tc.name Normal test case of executeSql and querySql, PRAGMA user_version + * @tc.desc 1.Set user_version + * 2.Get user_version + */ + it('testExecute0005', 0, async function (done) { + console.log(TAG + "************* testExecute0005 start *************"); + // 2 is used to set the store version + var transaction = await rdbStore.createTransaction() + try { + await transaction.execute("PRAGMA user_version = 2") + let resultSet = await transaction.querySql("PRAGMA user_version"); + console.log(TAG + "testExecute0005 transaction.querySql result count " + resultSet.rowCount) + resultSet.goToFirstRow(); + expect(2).assertEqual(resultSet.getLong(0)) + resultSet.close(); + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testExecute0005 failed"); + } + done(); + console.log(TAG + "************* testExecute0005 end *************"); + }) + + /** + * @tc.number testExecute0006 + * @tc.name Normal test case of executeSql and querySql, PRAGMA table_info + * @tc.desc 1.Get table_info + * 2.Check table_info + */ + it('testExecute0006', 0, async function (done) { + console.log(TAG + "************* testExecute0006 start *************"); + var transaction = await rdbStore.createTransaction() + try { + let resultSet = await transaction.querySql("PRAGMA table_info(test)"); + console.log(TAG + "testExecute0006 transaction.querySql result count " + resultSet.rowCount) + resultSet.goToFirstRow(); + expect(0).assertEqual(resultSet.getLong(0)) + expect("id").assertEqual(resultSet.getString(1)) + expect("INTEGER").assertEqual(resultSet.getString(2)) + resultSet.goToNextRow(); + expect(1).assertEqual(resultSet.getLong(0)) + expect("name").assertEqual(resultSet.getString(1)) + expect("TEXT").assertEqual(resultSet.getString(2)) + expect(1).assertEqual(resultSet.getLong(3)) + resultSet.goToNextRow(); + expect(2).assertEqual(resultSet.getLong(0)) + expect("age").assertEqual(resultSet.getString(1)) + expect("INTEGER").assertEqual(resultSet.getString(2)) + resultSet.goToNextRow(); + expect(3).assertEqual(resultSet.getLong(0)) + expect("salary").assertEqual(resultSet.getString(1)) + expect("REAL").assertEqual(resultSet.getString(2)) + resultSet.goToNextRow(); + expect(4).assertEqual(resultSet.getLong(0)) + expect("blobType").assertEqual(resultSet.getString(1)) + expect("BLOB").assertEqual(resultSet.getString(2)) + resultSet.close(); + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testExecute0006 failed"); + } + done(); + console.log(TAG + "************* testExecute0006 end *************"); + }) + + /** + * @tc.number testExecute0007 + * @tc.name Normal test case of executeSql, if spaces before the sql + * @tc.desc 1.Set user_version + * 2.Get user_version + */ + it('testExecute0007', 0, async function (done) { + console.log(TAG + "************* testExecute0007 start *************"); + var transaction = await rdbStore.createTransaction() + try { + // 2 is used to set the store version + await transaction.execute(" PRAGMA user_version = 2") + let resultSet = await transaction.querySql("PRAGMA user_version"); + console.log(TAG + "testExecute0007 transaction.querySql1 result count " + resultSet.rowCount) + resultSet.goToFirstRow(); + expect(2).assertEqual(resultSet.getLong(0)) + + await transaction.execute("\r\nPRAGMA user_version = 3") + resultSet = await transaction.querySql("PRAGMA user_version"); + console.log(TAG + "testExecute0007 transaction.querySql2 result count " + resultSet.rowCount) + resultSet.goToFirstRow(); + expect(3).assertEqual(resultSet.getLong(0)) + resultSet.close(); + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testExecute0007 failed"); + } + done(); + console.log(TAG + "************* testExecute0007 end *************"); + }) + + /** + * @tc.number testTransactionSyncInterface0001 + * @tc.name Normal test case of transactions, insert a row of data + * @tc.desc 1.Execute beginTransaction + * 2.BatchInsertSync data + * 3.InsertSync data + * 4.UpdateSync data + * 5.DeleteSync data + * 6.Execute commit + * 7.querySqlSync + * 7.ExecuteSync + */ + it('testTransactionSyncInterface0001', 0, async function (done) { + console.log(TAG + "************* testTransactionSyncInterface0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var num = await transaction.insertSync("test", valueBucket, data_relationalStore.ConflictResolution.ON_CONFLICT_REPLACE); + expect(1).assertEqual(num); + const updateValueBucket = { + "name": "update", + "age": 28, + "salary": 25, + "blobType": u8, + } + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi") + num = await transaction.updateSync(updateValueBucket, predicates) + expect(1).assertEqual(num); + + let deletePredicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "update") + num = await transaction.deleteSync(deletePredicates); + expect(1).assertEqual(num); + + let resultSet = await transaction.querySqlSync("select * from test") + console.log(TAG + "testTransactionSyncInterface0001 result count " + resultSet.rowCount) + expect(0).assertEqual(resultSet.rowCount) + resultSet.close() + + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionSyncInterface0001 failed"); + } + done() + console.log(TAG + "************* testTransactionSyncInterface0001 end *************"); + }) + + /** + * @tc.number testTransactionRollback0001 + * @tc.name Normal test case of transactions, insert and update a row of data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.rollback data + * 4.Query data + */ + it('testTransactionRollback0001', 0, async function (done) { + console.log(TAG + "************* testTransactionRollback0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket) + + await transaction.rollback() + + let resultSet = rdbStore.querySqlSync("select * from test") + console.log(TAG + "testTransactionRollback0001 result count " + resultSet.rowCount) + expect(0).assertEqual(resultSet.rowCount) + resultSet.close() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionRollback0001 failed"); + } + done() + console.log(TAG + "************* testTransactionRollback0001 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0001 + * @tc.name testTransactionIsolation. EXCLUSIVE and EXCLUSIVE + * @tc.desc 1.begin EXCLUSIVE Transaction + * 2.begin EXCLUSIVE Transaction again + * 3.throw 14800024 + */ + it('testTransactionIsolation0001', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0001 start *************"); + var exclusiveTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + try { + var trans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + trans.commit(); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0001 failed"); + } catch (e) { + await exclusiveTrans.rollback(); + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + console.log(TAG + "testTransactionIsolation0001 success"); + } + done() + console.log(TAG + "************* testTransactionIsolation0001 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0002 + * @tc.name testTransactionIsolation. DEFERRED and EXCLUSIVE + * @tc.desc 1.begin DEFERRED Transaction + * 2.begin EXCLUSIVE Transaction again + * 3.insert data with EXCLUSIVE Transaction + * 4.query data with DEFERRED Transaction -> no data + * 5.execute commit with EXCLUSIVE Transaction + * 6.query data with DEFERRED Transaction -> no data -> why? step 4 start isolation + * 7.query data with Rdb -> has data + */ + it('testTransactionIsolation0002', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0002 start *************"); + var deferredTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + var exclusiveTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + var insertRow = await exclusiveTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0002 exclusiveTrans.insert row " + insertRow) + expect(1).assertEqual(insertRow) + + var resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0002 deferredTrans querySqlSync before exclusiveTrans commit count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close() + + await exclusiveTrans.commit(); + + resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0002 deferredTrans querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + + resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0002 rdbStore querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close() + + } catch (e) { + exclusiveTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "insert failed"); + } + await deferredTrans.commit(); + } catch (e) { + await deferredTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0002 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0002 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0003 + * @tc.name testTransactionIsolation. IMMEDIATE and rdbStore + * @tc.desc 1.begin IMMEDIATE Transaction + * 2.insert data with rdbStore -> busy + * 3.insert data with IMMEDIATE Transaction + * 4.execute commit with IMMEDIATE Transaction + * 5.query data with rdbStore -> has data + */ + it('testTransactionIsolation0003', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0003 start *************"); + var immediateTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + try { + await rdbStore.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0003 rdbStore.insert success "); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + console.log(TAG + "insert failed"); + } + var insertRow = await immediateTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0003 immediateTrans.insert row " + insertRow); + expect(insertRow).assertEqual(1); + + await immediateTrans.commit(); + + var resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0003 querySqlSync count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + await immediateTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0003 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0003 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0004 + * @tc.name testTransactionIsolation. DEFERRED and rdbStore + * @tc.desc 1.begin DEFERRED Transaction + * 2.insert data with rdbStore + * 3.insert data with DEFERRED Transaction + * 4.query data with rdbStore -> has 2 row + * 5.insert data with rdbStore again -> busy + * 6.query data with DEFERRED Transaction -> has 2 row + * 7.execute commit with DEFERRED Transaction + * 8.insert data with rdbStore again + * 9.query data with rdbStore -> has 3 row + */ + it('testTransactionIsolation0004', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0004 start *************"); + var deferredTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + await rdbStore.insert("test", valueBucket); + + await deferredTrans.insert("test", valueBucket); + + var resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0004 rdbStore.querySqlSync count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + + try { + await rdbStore.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0004 insert success "); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + console.log(TAG + "insert failed"); + } + resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0004 deferredTrans.querySqlSync count " + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + + await deferredTrans.commit(); + + await rdbStore.insert("test", valueBucket); + + resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0004 rdbStore.querySqlSync after deferredTrans commit count " + resultSet.rowCount); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + await deferredTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0004 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0004 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0005 + * @tc.name testTransactionIsolation. DEFERRED and IMMEDIATE + * @tc.desc 1.begin DEFERRED Transaction + * 2.begin IMMEDIATE Transaction + * 3.insert data with DEFERRED Transaction -> busy + * 4.insert data with IMMEDIATE Transaction + * 5.execute commit with IMMEDIATE Transaction + * 6.insert data with DEFERRED Transaction + * 7.execute commit with DEFERRED Transaction + * 8.query data with rdbStore -> has 4 row + */ + it('testTransactionIsolation0005', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0005 start *************"); + var deferredTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + var immediateTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + try { + await deferredTrans.insert("test", valueBucket); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + console.log(TAG + "insert failed"); + } + var insertRow = await immediateTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0005 immediateTrans.insert row " + insertRow); + expect(1).assertEqual(insertRow); + + await immediateTrans.commit(); + + insertRow = await deferredTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0005 deferredTrans.insert after immediateTrans.commit row " + insertRow); + expect(2).assertEqual(insertRow); + + await deferredTrans.commit(); + + var resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0005 querySqlSync count " + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + await immediateTrans.rollback(); + await deferredTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0005 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0005 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0006 + * @tc.name testTransactionIsolation. DEFERRED and DEFERRED + * @tc.desc 1.insert data with rdbStore + * 2.begin DEFERRED Transaction1 + * 3.begin DEFERRED Transaction2 + * 4.update data with DEFERRED Transaction1 + * 5.delete data with DEFERRED Transaction2 -> busy + * 6.execute commit with DEFERRED Transaction1 + * 7.query data with DEFERRED Transaction2 -> has updated data + * 8.delete data with DEFERRED Transaction2 + * 9.execute commit with DEFERRED Transaction2 + * 10.query data with rdbStore -> has 0 row + */ + it('testTransactionIsolation0006', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0006 start *************"); + var deferredTrans1 = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + var deferredTrans2 = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + var rowId = await rdbStore.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0006 insert row " + rowId); + expect(1).assertEqual(rowId); + + const updateValueBucket = { + "name": "deferredTrans1", + "age": 18, + "salary": 100.5, + } + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi") + rowId = await deferredTrans1.updateSync(updateValueBucket, predicates) + console.log(TAG + "testTransactionIsolation0006 insert row " + rowId); + expect(1).assertEqual(rowId); + + let deletePredicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("age", "18"); + try { + await deferredTrans2.delete(deletePredicates) + console.log(TAG + "testTransactionIsolation0006 deferredTrans2.delete success "); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + console.log(TAG + "insert failed"); + } + + await deferredTrans1.commit(); + + var resultSet = deferredTrans2.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0006 deferredTrans2.querySqlSync count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToFirstRow()) + const name = resultSet.getString(resultSet.getColumnIndex("name")) + expect("deferredTrans1").assertEqual(name); + resultSet.close() + + var num = await deferredTrans2.deleteSync(deletePredicates) + console.log(TAG + "testTransactionIsolation0006 delete num " + num); + expect(1).assertEqual(num); + + await deferredTrans2.commit(); + + resultSet = rdbStore.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0006 rdbStore.querySqlSync count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + await deferredTrans2.rollback(); + await deferredTrans1.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0006 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0006 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0007 + * @tc.name testTransactionIsolation. DEFERRED and EXCLUSIVE + * @tc.desc 1.begin DEFERRED Transaction1 + * 2.begin EXCLUSIVE Transaction + * 3.insert data with EXCLUSIVE Transaction + * 4.execute commit with EXCLUSIVE Transaction + * 5.query data with DEFERRED1 Transaction -> has data + * 6.begin DEFERRED Transaction2 + * 7.query data with DEFERRED2 Transaction -> has data + */ + it('testTransactionIsolation0007', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0007 start *************"); + var deferredTrans1 = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + var exclusiveTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + var insertRow = await exclusiveTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0007 exclusiveTrans.insert row " + insertRow) + expect(1).assertEqual(insertRow) + await exclusiveTrans.commit(); + + var resultSet = deferredTrans1.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0007 deferredTrans1 querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + + var deferredTrans2 = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + resultSet = deferredTrans2.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0007 deferredTrans2 querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + deferredTrans2.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "querySqlSync failed"); + } + + } catch (e) { + exclusiveTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "insert failed"); + } + await deferredTrans1.commit(); + } catch (e) { + await deferredTrans1.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0007 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0007 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0008 + * @tc.name testTransactionIsolation. DEFERRED and rdbStore + * @tc.desc 1.begin DEFERRED Transaction + * 2.insert data with rdbStore + * 3.query data with DEFERRED Transaction -> has 1 data + * 4.begin EXCLUSIVE Transaction -> busy + * 5.insert data with DEFERRED Transaction + * 6.execute commit with DEFERRED Transaction + * 7.begin EXCLUSIVE Transaction + * 8.query data with EXCLUSIVE Transaction -> has 2 data + */ + it('testTransactionIsolation0008', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0008 start *************"); + var deferredTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + await rdbStore.insert("test", valueBucket); + + var resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0008 querySqlSync1 count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close() + try { + var exclusiveTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + console.log(TAG + "begin EXCLUSIVE success abnormal"); + await exclusiveTrans.rollback(); + } catch (e) { + console.log(TAG + e); + console.log(TAG + "begin EXCLUSIVE failed"); + expect(true).assertFail(); + } + var rowId = await deferredTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0008 deferredTrans.insert row " + rowId) + expect(2).assertEqual(rowId); + + await deferredTrans.commit(); + + try { + var exclusiveTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + console.log(TAG + "begin EXCLUSIVE success"); + try { + resultSet = exclusiveTrans.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0008 exclusiveTrans.querySqlSync count " + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "exclusiveTrans.querySqlSync failed"); + } + exclusiveTrans.rollback(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "begin EXCLUSIVE failed"); + } + } catch (e) { + await deferredTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0008 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0008 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0009 + * @tc.name testTransactionIsolation. DEFERRED and DEFERRED + * @tc.desc 1.insert data with rdbStore + * 2.begin DEFERRED Transaction1 + * 3.begin DEFERRED Transaction2 + * 4.update data to update1 with DEFERRED Transaction1 + * 5.query data with DEFERRED Transaction2 -> has before update data + * 6.update update1 to update2 with DEFERRED Transaction1 + * 7.execute commit with DEFERRED Transaction1 + * 8.query data with DEFERRED Transaction2 -> has before update data + * 9.delete data with DEFERRED Transaction2 -> busy + * 10.execute commit with DEFERRED Transaction2 + * 11.query data with rdbStore -> has 1 row + */ + it('testTransactionIsolation0009', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0009 start *************"); + var deferredTrans1 = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + var deferredTrans2 = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + var rowId = await rdbStore.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0009 insert row " + rowId); + expect(1).assertEqual(rowId); + + const updateValueBucket1 = { + "name": "update1", + "age": 18, + "salary": 100.5, + } + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi") + var num = await deferredTrans1.updateSync(updateValueBucket1, predicates) + console.log(TAG + "testTransactionIsolation0009 updateSync 1 num " + num); + expect(1).assertEqual(num); + + var resultSet = deferredTrans2.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0009 deferredTrans2.querySqlSync1 count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToFirstRow()) + var name = resultSet.getString(resultSet.getColumnIndex("name")) + expect("lisi").assertEqual(name); + resultSet.close() + + const updateValueBucket2 = { + "name": "update2", + "age": 18, + "salary": 100.5, + } + predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "update1") + var num = await deferredTrans1.updateSync(updateValueBucket2, predicates) + console.log(TAG + "testTransactionIsolation0009 updateSync 2 num " + num); + expect(1).assertEqual(num); + + await deferredTrans1.commit(); + + resultSet = deferredTrans2.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0009 deferredTrans2.querySqlSync2 count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToFirstRow()) + name = resultSet.getString(resultSet.getColumnIndex("name")) + expect("lisi").assertEqual(name); + resultSet.close() + + let deletePredicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("age", "18"); + try { + num = await deferredTrans2.delete(deletePredicates) + console.log(TAG + "testTransactionIsolation0009 delete num " + num); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + } + await deferredTrans2.commit(); + + resultSet = rdbStore.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0009 rdbStore.querySqlSync count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + await deferredTrans2.rollback(); + await deferredTrans1.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0009 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0009 end *************"); + }) + + /** + * @tc.number testTransactionEnd0001 + * @tc.name Query data with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute commit + * 4.Query data with transaction -> throw 14800014 + */ + it('testTransactionEnd0001', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var num = await transaction.insert("test", valueBucket) + expect(1).assertEqual(num); + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await transaction.query(predicates) + console.log(TAG + "testTransactionEnd0001 result count " + resultSet.rowCount) + expect(null).assertFail() + resultSet.close() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0001 end *************"); + }) + + /** + * @tc.number testTransactionEnd0002 + * @tc.name Query data with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Query data with transaction -> get resultSet + * 4.Execute commit + * 5.resultSet go to first row -> throw 14800014 + */ + it('testTransactionEnd0002', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0002 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + let resultSet; + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var num = await transaction.insert("test", valueBucket) + expect(1).assertEqual(num); + + let predicates = new data_relationalStore.RdbPredicates("test"); + resultSet = await transaction.query(predicates) + console.log(TAG + "testTransactionEnd0002 result count " + resultSet.rowCount) + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + expect(false).assertEqual(resultSet.goToFirstRow()) + done() + console.log(TAG + "************* testTransactionEnd0002 end *************"); + }) + + /** + * @tc.number testTransactionEnd0003 + * @tc.name Insert data with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute commit + * 4.Insert data with closed transaction -> throw 14800014 + */ + it('testTransactionEnd0003', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0003 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + try { + var rowId = await transaction.insert("test", valueBucket) + expect(1).assertEqual(rowId); + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + rowId = await transaction.insert("test", valueBucket) + console.log(TAG + "testTransactionEnd0003 insert rowId " + rowId) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0003 end *************"); + }) + + /** + * @tc.number testTransactionEnd0004 + * @tc.name Update data with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute rollback + * 4.Update data with closed transaction -> throw 14800014 + */ + it('testTransactionEnd0004', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0004 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var rowId = await transaction.insert("test", valueBucket) + expect(1).assertEqual(rowId); + await transaction.rollback() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi"); + const updateValueBucket = { + "name": "update", + "age": 28, + "salary": 25, + "blobType": u8, + } + rowId = await transaction.update(updateValueBucket, predicates) + console.log(TAG + "testTransactionEnd0004 update rowId " + rowId) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0004 end *************"); + }) + + /** + * @tc.number testTransactionEnd0005 + * @tc.name Delete data with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute rollback + * 4.Delete data with closed transaction -> throw 14800014 + */ + it('testTransactionEnd0005', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0005 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var rowId = await transaction.insert("test", valueBucket) + expect(1).assertEqual(rowId); + await transaction.rollback() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi"); + var num = transaction.deleteSync(predicates) + console.log(TAG + "testTransactionEnd0005 delete num " + num) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0005 end *************"); + }) + + /** + * @tc.number testTransactionEnd0006 + * @tc.name Execute Sql with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute rollback + * 4.Execute Sql with closed transaction -> throw 14800014 + */ + it('testTransactionEnd0006', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0006 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var rowId = await transaction.insert("test", valueBucket) + expect(1).assertEqual(rowId); + await transaction.rollback() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + let ret = transaction.executeSync("PRAGMA integrity_check"); + console.log(TAG + "testTransactionEnd0006 executeSync PRAGMA integrity_check: " + ret) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0006 end *************"); + }) + + /** + * @tc.number testTransactionEnd0007 + * @tc.name Execute Sql with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute rollback + * 4.Commit with closed transaction -> throw 14800014 + */ + it('testTransactionEnd0007', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0007 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var rowId = await transaction.insert("test", valueBucket) + expect(1).assertEqual(rowId); + await transaction.rollback() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + await transaction.commit(); + console.log(TAG + "testTransactionEnd0007 commit success") + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0007 end *************"); + }) + + /** + * @tc.number testTransactionBusy0001 + * @tc.name Abnormal test case of createTransaction + * @tc.desc 1.Execute beginTransaction 5 times + */ + it('testTransactionBusy0001', 0, async function (done) { + console.log(TAG + "************* testTransactionBusy0001 start *************"); + let transactions = []; + try { + for (let i = 0; i < 5; i++) { + transactions.push(await rdbStore?.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + })); + console.log(TAG + "testTransactionBusy0001 createTransaction success. i " + i); + } + } catch (e) { + console.log(TAG + e + " code: " + e.code); + // expect(e.code).assertEqual(14800000) + expect(e.code).assertEqual(14800015) + console.log(TAG + "testTransactionBusy0001 failed"); + } + done(); + transactions.forEach(element => { + element?.rollback(); + console.log(TAG + "testTransactionBusy0001 rollback"); + }); + console.log(TAG + "************* testTransactionBusy0001 end *************"); + }) + + /** + * @tc.number testTransactionWithReadOnlyStore0001 + * @tc.name createTransactionWithReadOnlyStore + * @tc.desc 1.Get a readOnly store + * 2.createTransaction with readOnly store + */ + it('testTransactionWithReadOnlyStore0001', 0, async function (done) { + console.log(TAG + "************* testTransactionWithReadOnlyStore0001 start *************"); + let storeConfig = { + name: "ReadOnlyTransactionTest.db", + securityLevel: data_relationalStore.SecurityLevel.S1, + } + let store = await data_relationalStore.getRdbStore(context, storeConfig); + await store.close() + storeConfig.isReadOnly = true; + let readOnlyStore = await data_relationalStore.getRdbStore(context, storeConfig); + expect(readOnlyStore === null).assertFalse(); + try { + let transaction = await readOnlyStore?.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + console.log(TAG + "testTransactionWithReadOnlyStore0001 createTransaction success"); + const valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + }; + let row = transaction?.insertSync("test", valueBucket); + console.log(TAG + "testTransactionWithReadOnlyStore0001 insert row:" + row); + await transaction?.rollback(); + expect(null).assertFail(); + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(801) + console.log(TAG + "testTransactionWithReadOnlyStore0001 success"); + } + await data_relationalStore.deleteRdbStore(context, storeConfig); + done(); + console.log(TAG + "************* testTransactionWithReadOnlyStore0001 end *************"); + }) + + /** + * @tc.number testbatchInsertWithConflictResolutionInTransaction0001 + * @tc.name batchInsertWithConflictResolutionInTransaction + * @tc.desc normal batch insert with ON_CONFLICT_NONE + */ + it('testbatchInsertWithConflictResolutionInTransaction0001', 0, async function (done) { + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + for (let i = 0; i < 2; i++) { + valueBucketArray.push(valueBucket); + } + var num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_NONE) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num1 " + num) + expect(2).assertEqual(num); + + num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num2 " + num) + expect(2).assertEqual(num); + + num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_ABORT) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num3 " + num) + expect(2).assertEqual(num); + + num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_FAIL) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num4 " + num) + expect(2).assertEqual(num); + + num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_IGNORE) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num5 " + num) + expect(2).assertEqual(num); + + num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_REPLACE) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num6 " + num) + expect(2).assertEqual(num); + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 result count " + resultSet.rowCount) + expect(12).assertEqual(resultSet.rowCount) + resultSet.close() + + await transaction.commit() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + await transaction.rollback() + expect(null).assertFail() + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 failed"); + } + done() + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0001 end *************"); + }) + + /** + * @tc.number testbatchInsertWithConflictResolutionInTransaction0011 + * @tc.name batchInsertWithConflictResolutionInTransaction + * @tc.desc conflict batch insert with ON_CONFLICT_NONE + */ + it('testbatchInsertWithConflictResolutionInTransaction0011', 0, async function (done) { + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0011 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "id": 2, + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket); + let valueBucketArray = new Array(); + for (let i = 0; i < 5; i++) { + var vb = { ...valueBucket }; + vb.id = i; + valueBucketArray.push(vb); + } + let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_NONE) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0011 failed num " + num); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(14800032).assertEqual(e.code) + await transaction.rollback() + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0011 success"); + } + done() + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0011 end *************"); + }) + + /** + * @tc.number testbatchInsertWithConflictResolutionInTransaction0012 + * @tc.name batchInsertWithConflictResolutionInTransaction + * @tc.desc conflict batch insert with ON_CONFLICT_ABORT + */ + it('testbatchInsertWithConflictResolutionInTransaction0012', 0, async function (done) { + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0012 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "id": 2, + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket); + let valueBucketArray = new Array(); + for (let i = 0; i < 5; i++) { + var vb = { ...valueBucket }; + vb.id = i; + valueBucketArray.push(vb); + } + let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_ABORT) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0012 failed num " + num); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(14800032).assertEqual(e.code) + await transaction.rollback() + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0012 success"); + } + done() + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0012 end *************"); + }) + + /** + * @tc.number testbatchInsertWithConflictResolutionInTransaction0013 + * @tc.name batchInsertWithConflictResolutionInTransaction + * @tc.desc conflict batch insert with ON_CONFLICT_FAIL + */ + it('testbatchInsertWithConflictResolutionInTransaction0013', 0, async function (done) { + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0013 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "id": 2, + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket); + let valueBucketArray = new Array(); + for (let i = 0; i < 5; i++) { + var vb = { ...valueBucket }; + vb.id = i; + valueBucketArray.push(vb); + } + let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_FAIL) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0013 failed num " + num); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(14800032).assertEqual(e.code) + await transaction.rollback() + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0013 success"); + } + done() + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0013 end *************"); + }) + + /** + * @tc.number testbatchInsertWithConflictResolutionInTransaction0014 + * @tc.name batchInsertWithConflictResolutionInTransaction + * @tc.desc conflict batch insert with ON_CONFLICT_IGNORE + */ + it('testbatchInsertWithConflictResolutionInTransaction0014', 0, async function (done) { + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0014 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "id": 2, + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket); + let valueBucketArray = new Array(); + for (let i = 0; i < 5; i++) { + var vb = { ...valueBucket }; + vb.id = i; + valueBucketArray.push(vb); + } + let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_IGNORE) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0014 success num " + num); + expect(4).assertEqual(num) + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0014 result count " + resultSet.rowCount) + expect(5).assertEqual(resultSet.rowCount) + resultSet.close() + + await transaction.commit() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + await transaction.rollback() + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0014 failed"); + expect(null).assertFail() + } + done() + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0014 end *************"); + }) + + /** + * @tc.number testbatchInsertWithConflictResolutionInTransaction0015 + * @tc.name batchInsertWithConflictResolutionInTransaction + * @tc.desc conflict batch insert with ON_CONFLICT_REPLACE + */ + it('testbatchInsertWithConflictResolutionInTransaction0015', 0, async function (done) { + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0015 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "id": 2, + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket); + let valueBucketArray = new Array(); + for (let i = 0; i < 5; i++) { + var vb = { ...valueBucket }; + vb.id = i; + valueBucketArray.push(vb); + } + let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_REPLACE) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0015 success num " + num); + expect(5).assertEqual(num) + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0015 result count " + resultSet.rowCount) + expect(5).assertEqual(resultSet.rowCount) + resultSet.close() + + await transaction.commit() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + await transaction.rollback() + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0015 failed"); + expect(null).assertFail() + } + done() + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0015 end *************"); + }) + + /** + * @tc.number testON_CONFLICT_ROLLBACKInTransaction0021 + * @tc.name InsertWithON_CONFLICT_ROLLBACKInTransaction + * @tc.desc conflict insert with ON_CONFLICT_ROLLBACK + */ + it('testON_CONFLICT_ROLLBACKInTransaction0021', 0, async function (done) { + console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0021 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": null, + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var num = await transaction.insert("test", valueBucket, + data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK); + console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0021 fail num " + num); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800032) + try { + await transaction.rollback() + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800021); + } + console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0021 success"); + } + done() + console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0021 end *************"); + }) + + /** + * @tc.number testON_CONFLICT_ROLLBACKInTransaction0022 + * @tc.name InsertWithON_CONFLICT_ROLLBACKInTransaction + * @tc.desc conflict insert with ON_CONFLICT_ROLLBACK + */ + it('testON_CONFLICT_ROLLBACKInTransaction0022', 0, async function (done) { + console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0022 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var num = await transaction.insert("test", valueBucket); + console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0022 insert num " + num) + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "zhangsan"); + const updateValueBucket = { + "name": null, + "age": 28, + "salary": 25, + "blobType": u8, + } + await transaction.update(updateValueBucket, predicates, data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800032) + try { + await transaction.rollback() + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800021); + } + console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0022 success"); + } + done() + console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0022 end *************"); + }) + + /** + * @tc.number testON_CONFLICT_ROLLBACKInTransaction0023 + * @tc.name BatchInsertWithON_CONFLICT_ROLLBACKInTransaction + * @tc.desc conflict insert with ON_CONFLICT_ROLLBACK + */ + it('testON_CONFLICT_ROLLBACKInTransaction0023', 0, async function (done) { + console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0023 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": null, + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + valueBucketArray.push(valueBucket); + var num = transaction.batchInsertWithConflictResolutionSync("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK); + console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0023 insert num " + num) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800032) + try { + await transaction.rollback() + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800021); + } + console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0023 success"); + + } + done() + console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0023 end *************"); + }) + + /** + * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 + * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs + * @tc.desc batch Insert With ConflictResolution with Invalid Args + */ + it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031', 0, async function (done) { + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction(); + try { + const valueBucket = { + "name": "bbb", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + valueBucketArray.push(valueBucket); + var num = await transaction.batchInsertWithConflictResolution(123, valueBucket, + data_relationalStore.ConflictResolution.ON_CONFLICT_ABORT); + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 insert num " + num) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(String(e.code)).assertEqual(String(401)) + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 success"); + } + await transaction.rollback(); + done() + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 end *************"); + }) + + /** + * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 + * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs + * @tc.desc batch Insert With ConflictResolution with Invalid Args + */ + it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032', 0, async function (done) { + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 start *************"); + var transaction = await rdbStore.createTransaction(); + try { + var num = transaction.batchInsertWithConflictResolutionSync("table", undefined, + data_relationalStore.ConflictResolution.ON_CONFLICT_FAIL); + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 insert num " + num) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(String(e.code)).assertEqual(String(401)) + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 success"); + } + await transaction.rollback(); + done() + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 end *************"); + }) + + /** + * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 + * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs + * @tc.desc batch Insert With ConflictResolution with Invalid Args + */ + it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033', 0, async function (done) { + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + valueBucketArray.push(valueBucket); + var num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, "abc"); + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 insert num " + num) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(String(e.code)).assertEqual(String(401)) + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 success"); + } + await transaction.rollback(); + done() + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 end *************"); + }) + + /** + * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 + * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs + * @tc.desc batch Insert With ConflictResolution with Invalid Args + */ + it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034', 0, async function (done) { + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + valueBucketArray.push(valueBucket); + var num = transaction.batchInsertWithConflictResolutionSync("test", valueBucketArray); + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 insert num " + num) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(String(e.code)).assertEqual(String(401)) + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 success"); + } + await transaction.rollback(); + done() + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 end *************"); + }) + + /** + * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 + * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs + * @tc.desc batch Insert With ConflictResolution with Invalid Args + */ + it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035', 0, async function (done) { + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + let rows = 32768 / 4 + 1; + for (let i = 0; i < rows; i++) { + valueBucketArray.push(valueBucket); + } + var num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, data_relationalStore.ConflictResolution.ON_CONFLICT_NONE); + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 insert num " + num) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(String(e.code)).assertEqual(String(14800000)) + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 success"); + } + await transaction.rollback(); + done() + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 end *************"); + }) + + /** + * @tc.number testSqliteLocked0001 + * @tc.name testSqliteLocked + * @tc.desc Drop the table before closing the resultSet after querying the data + */ + it('testSqliteLocked0001', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0001 start *************"); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + await transaction.execute('DROP TABLE test'); + console.error(TAG + 'drop table success but testSqliteLocked0001 failed'); + await transaction.commit(); + expect(null).assertFail() + } catch (err) { + console.info(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(String(err.code)).assertEqual(String(14800025)) + console.info(TAG + "testSqliteLocked0001 success"); + } + resultSet.close(); + done() + console.log(TAG + "************* testSqliteLocked0001 end *************"); + }) + + /** + * @tc.number testSqliteLocked0002 + * @tc.name testSqliteLocked + * @tc.desc Drop the table before closing the resultSet after querying the data + */ + it('testSqliteLocked0002', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0002 start *************"); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount - 1; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + await transaction.execute('DROP TABLE test'); + console.error(TAG + 'drop table success but testSqliteLocked0002 failed'); + await transaction.commit(); + expect(null).assertFail() + } catch (err) { + console.info(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(String(err.code)).assertEqual(String(14800025)) + console.info(TAG + "testSqliteLocked0002 success"); + } + resultSet.close(); + done() + console.log(TAG + "************* testSqliteLocked0002 end *************"); + }) + + /** + * @tc.number testSqliteLocked0003 + * @tc.name testSqliteLocked + * @tc.desc Drop the table after querying the data and closing the resultSet + */ + it('testSqliteLocked0003', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0003 start *************"); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + resultSet.close(); + + await transaction.execute('DROP TABLE test'); + console.info(TAG + 'testSqliteLocked0003 success'); + await transaction.commit(); + } catch (err) { + console.error(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(null).assertFail() + console.error(TAG + "testSqliteLocked0003 failed"); + } + done() + console.log(TAG + "************* testSqliteLocked0003 end *************"); + }) + + /** + * @tc.number testSqliteLocked0004 + * @tc.name testSqliteLocked + * @tc.desc Drop the index before closing the resultSet after querying the data + */ + it('testSqliteLocked0004', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0004 start *************"); + + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + await rdbStore.execute('CREATE INDEX test_index ON test(age)'); + + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + await transaction.execute('DROP INDEX test_index'); + console.error(TAG + 'drop table success but testSqliteLocked0004 failed'); + await transaction.commit(); + expect(null).assertFail() + } catch (err) { + console.info(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(String(err.code)).assertEqual(String(14800025)) + console.info(TAG + "testSqliteLocked0004 success"); + } + resultSet.close(); + await rdbStore.execute('DROP INDEX test_index'); + done() + console.log(TAG + "************* testSqliteLocked0004 end *************"); + }) + + /** + * @tc.number testSqliteLocked0005 + * @tc.name testSqliteLocked + * @tc.desc Drop the index before closing the resultSet after querying the data + */ + it('testSqliteLocked0005', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0005 start *************"); + + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + await rdbStore.execute('CREATE INDEX test_index ON test(age)'); + + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount - 1; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + await transaction.execute('DROP INDEX test_index'); + console.error(TAG + 'drop table success but testSqliteLocked0005 failed'); + await transaction.commit(); + expect(null).assertFail() + } catch (err) { + console.info(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(String(err.code)).assertEqual(String(14800025)) + console.info(TAG + "testSqliteLocked0005 success"); + } + resultSet.close(); + await rdbStore.execute('DROP INDEX test_index'); + done() + console.log(TAG + "************* testSqliteLocked0005 end *************"); + }) + + /** + * @tc.number testSqliteLocked0006 + * @tc.name testSqliteLocked + * @tc.desc Drop the index after querying the data and closing the resultSet + */ + it('testSqliteLocked0006', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0006 start *************"); + + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + await rdbStore.execute('CREATE INDEX test_index ON test(age)'); + + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + resultSet.close(); + + await transaction.execute('DROP INDEX test_index'); + console.info(TAG + 'testSqliteLocked0006 success'); + await transaction.commit(); + } catch (err) { + console.info(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(null).assertFail() + console.error(TAG + "testSqliteLocked0006 failed"); + } + done() + console.log(TAG + "************* testSqliteLocked0006 end *************"); + }) + + /** + * @tc.number testSqliteLocked0007 + * @tc.name testSqliteLocked + * @tc.desc Drop the table before closing the resultSet after querying the data + */ + it('testSqliteLocked0007', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0007 start *************"); + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + resultSet.close(); + + await transaction.execute('DROP TABLE test'); + console.info(TAG + 'testSqliteLocked0007 success'); + await transaction.commit(); + } catch (err) { + console.error(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(null).assertFail(); + console.error(TAG + "testSqliteLocked0007 failed"); + } + done() + console.log(TAG + "************* testSqliteLocked0007 end *************"); + }) + + /** + * @tc.number testSqliteLocked0008 + * @tc.name testSqliteLocked + * @tc.desc Drop the index before closing the resultSet after querying the data + */ + it('testSqliteLocked0008', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0008 start *************"); + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + await rdbStore.execute('CREATE INDEX test_index ON test(age)'); + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + resultSet.close(); + + await transaction.execute('DROP INDEX test_index'); + console.info(TAG + 'testSqliteLocked0008 success'); + await transaction.commit(); + } catch (err) { + console.error(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(null).assertFail(); + console.error(TAG + "testSqliteLocked0008 failed"); + } + done() + console.log(TAG + "************* testSqliteLocked0008 end *************"); + }) + + /** + * @tc.number testSqliteLocked0009 + * @tc.name testSqliteLocked + * @tc.desc Drop the table before closing the resultSet after querying the data + */ + it('testSqliteLocked0009', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0009 start *************"); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + await rdbStore.execute(CREATE_TABLE_TEST1); + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + await transaction.execute('DROP TABLE test1'); + console.error(TAG + 'drop table success but testSqliteLocked0009 failed'); + await transaction.commit(); + expect(null).assertFail() + } catch (err) { + console.info(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(String(err.code)).assertEqual(String(14800025)) + console.info(TAG + "testSqliteLocked0009 success"); + } + resultSet.close(); + done() + console.log(TAG + "************* testSqliteLocked0009 end *************"); + }) + + /** + * @tc.number testSqliteLocked0010 + * @tc.name testSqliteLocked + * @tc.desc Drop the table before closing the resultSet after querying the data + */ + it('testSqliteLocked0010', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0010 start *************"); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + await rdbStore.execute(CREATE_TABLE_TEST1); + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + + await transaction.execute('DROP TABLE test1'); + console.info(TAG + 'testSqliteLocked0010 success'); + await transaction.commit(); + } catch (err) { + console.error(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(null).assertFail() + console.error(TAG + "testSqliteLocked0010 failed"); + } + resultSet.close(); + done() + console.log(TAG + "************* testSqliteLocked0010 end *************"); + }) + + /** + * @tc.number testSqliteLocked0011 + * @tc.name testSqliteLocked + * @tc.desc Drop the table before closing the resultSet after querying the data + */ + it('testSqliteLocked0011', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0011 start *************"); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + let ret = resultSet.goToNextRow(); + expect(false).assertEqual(ret); + + await transaction.execute('DROP TABLE test'); + console.error(TAG + 'testSqliteLocked0011 success'); + await transaction.commit(); + } catch (err) { + console.info(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(null).assertFail() + console.info(TAG + "testSqliteLocked0011 failed"); + } + resultSet.close(); + done() + console.log(TAG + "************* testSqliteLocked0011 end *************"); + }) + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreCustomTokenizerEts.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreCustomTokenizerEts.ets new file mode 100644 index 0000000000000000000000000000000000000000..8de1abb81338480b36826ea94c956d58c86df3ac --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreCustomTokenizerEts.ets @@ -0,0 +1,350 @@ +/* + * Copyright (C) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; +import relationalStore from '@ohos.data.relationalStore' +import common from "@ohos.app.ability.common" +let context: common.UIAbilityContext + +const TAG = "[RDB_CUSTOM_TOKENIZER_TEST]"; + +export default function RdbStoreCustomTokenizerTest() { + describe('rdbStoreCustomTokenizerEtsTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll'); + context = globalThis.abilityContext; + }); + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + }); + afterEach(async () => { + console.info(TAG + 'afterEach'); + }); + afterAll(async () => { + console.info(TAG + 'afterAll'); + }); + + console.log(TAG + "*************Unit Test Begin*************"); + /** + * @tc.number rdbStoreCustomTokenizerEtsTest + * @tc.name CustomTokenizerTest001 + * @tc.desc Test a single long word + */ + it('CustomTokenizerTest001', 0, async () => { + console.log(TAG + "************* CustomTokenizerTest001 start *************"); + try { + let store: relationalStore.RdbStore | undefined = undefined; + const storeConfig: relationalStore.StoreConfig = { + name: "MyStore.db", + securityLevel: relationalStore.SecurityLevel.S3 + }; + let customType = relationalStore.Tokenizer.CUSTOM_TOKENIZER; + let customTypeSupported = relationalStore.isTokenizerSupported(customType); + if (customTypeSupported) { + storeConfig.tokenizer = customType; + } else { + console.info('not support custom tokenizer.'); + return true; + } + store = await relationalStore.getRdbStore(context, storeConfig); + if (store == undefined) { + expect().assertFail(); + return false; + } + + let createTableSql = "CREATE VIRTUAL TABLE example USING fts5(content, " + + "tokenize = 'customtokenizer cut_mode short_words')"; + await store.executeSql(createTableSql); + + let insertValueSql = "INSERT INTO example VALUES('电子邮件')"; + await store.executeSql(insertValueSql); + + let words: string[] = ["电子", "邮件", "电子邮件"]; + for (const word of words) { + let resultSet = await store.querySql("SELECT * FROM example WHERE content MATCH ?;", [word]); + expect(1).assertEqual(resultSet.rowCount); + } + + let dropTableSql = "DROP TABLE IF EXISTS example"; + await store.executeSql(dropTableSql); + await store.close(); + } catch (err) { + console.log("errcode: " + err.code); + expect().assertFail(); + } + console.log(TAG + "************* CustomTokenizerTest001 end *************"); + return true; + }); + + /** + * @tc.number rdbStoreCustomTokenizerEtsTest + * @tc.name CustomTokenizerTest002 + * @tc.desc Test if there is a long word in a sentence + */ + it('CustomTokenizerTest002', 0, async () => { + console.log(TAG + "************* CustomTokenizerTest002 start *************"); + try { + let store: relationalStore.RdbStore | undefined = undefined; + const storeConfig: relationalStore.StoreConfig = { + name: "MyStore.db", + securityLevel: relationalStore.SecurityLevel.S3 + }; + let customType = relationalStore.Tokenizer.CUSTOM_TOKENIZER; + let customTypeSupported = relationalStore.isTokenizerSupported(customType); + if (customTypeSupported) { + storeConfig.tokenizer = customType; + } else { + console.info('not support custom tokenizer.'); + return true; + } + store = await relationalStore.getRdbStore(context, storeConfig); + if (store == undefined) { + expect().assertFail(); + return false; + } + + let createTableSql = "CREATE VIRTUAL TABLE example USING fts5(content, " + + "tokenize = 'customtokenizer cut_mode short_words')"; + await store.executeSql(createTableSql); + + let insertValueSql = "INSERT INTO example VALUES('这是一封电子邮件')"; + await store.executeSql(insertValueSql); + + let words: string[] = ["电子", "邮件", "电子邮件"]; + for (const word of words) { + let resultSet = await store.querySql("SELECT * FROM example WHERE content MATCH ?;", [word]); + expect(1).assertEqual(resultSet.rowCount); + } + + let dropTableSql = "DROP TABLE IF EXISTS example"; + await store.executeSql(dropTableSql); + await store.close(); + } catch (err) { + console.log("errcode: " + err.code); + expect().assertFail(); + } + console.log(TAG + "************* CustomTokenizerTest002 end *************"); + return true; + }); + + /** + * @tc.number rdbStoreCustomTokenizerEtsTest + * @tc.name CustomTokenizerTest003 + * @tc.desc Test multiple long words + */ + it('CustomTokenizerTest003', 0, async () => { + console.log(TAG + "************* CustomTokenizerTest003 start *************"); + try { + let store: relationalStore.RdbStore | undefined = undefined; + const storeConfig: relationalStore.StoreConfig = { + name: "MyStore.db", + securityLevel: relationalStore.SecurityLevel.S3 + }; + let customType = relationalStore.Tokenizer.CUSTOM_TOKENIZER; + let customTypeSupported = relationalStore.isTokenizerSupported(customType); + if (customTypeSupported) { + storeConfig.tokenizer = customType; + } else { + console.info('not support custom tokenizer.'); + return true; + } + store = await relationalStore.getRdbStore(context, storeConfig); + if (store == undefined) { + expect().assertFail(); + return false; + } + + let createTableSql = "CREATE VIRTUAL TABLE example USING fts5(content, " + + "tokenize = 'customtokenizer cut_mode short_words')"; + await store.executeSql(createTableSql); + + let insertValueSql = "INSERT INTO example VALUES('这是一封关于少数民族的电子邮件')"; + await store.executeSql(insertValueSql); + + let words: string[] = ["电子", "邮件", "电子邮件", "少数", "民族", "少数民族"]; + for (const word of words) { + let resultSet = await store.querySql("SELECT * FROM example WHERE content MATCH ?;", [word]); + expect(1).assertEqual(resultSet.rowCount); + } + + let dropTableSql = "DROP TABLE IF EXISTS example"; + await store.executeSql(dropTableSql); + await store.close(); + } catch (err) { + console.log("errcode: " + err.code); + expect().assertFail(); + } + console.log(TAG + "************* CustomTokenizerTest003 end *************"); + return true; + }); + + /** + * @tc.number rdbStoreCustomTokenizerEtsTest + * @tc.name CustomTokenizerTest004 + * @tc.desc Test repeated long words + */ + it('CustomTokenizerTest004', 0, async () => { + console.log(TAG + "************* CustomTokenizerTest004 start *************"); + try { + let store: relationalStore.RdbStore | undefined = undefined; + const storeConfig: relationalStore.StoreConfig = { + name: "MyStore.db", + securityLevel: relationalStore.SecurityLevel.S3 + }; + let customType = relationalStore.Tokenizer.CUSTOM_TOKENIZER; + let customTypeSupported = relationalStore.isTokenizerSupported(customType); + if (customTypeSupported) { + storeConfig.tokenizer = customType; + } else { + console.info('not support custom tokenizer.'); + return true; + } + store = await relationalStore.getRdbStore(context, storeConfig); + if (store == undefined) { + expect().assertFail(); + return false; + } + + let createTableSql = "CREATE VIRTUAL TABLE example USING fts5(content, " + + "tokenize = 'customtokenizer cut_mode short_words')"; + await store.executeSql(createTableSql); + + let insertValueSql = "INSERT INTO example VALUES('华中师范大学是一所位于武汉市的全日制综合性师范大学')"; + await store.executeSql(insertValueSql); + + let words: string[] = ["华中", "中师", "师范", "武汉", "武汉市", "师范大学"]; + for (const word of words) { + let resultSet = await store.querySql("SELECT * FROM example WHERE content MATCH ?;", [word]); + expect(1).assertEqual(resultSet.rowCount); + } + + let dropTableSql = "DROP TABLE IF EXISTS example"; + await store.executeSql(dropTableSql); + await store.close(); + } catch (err) { + console.log("errcode: " + err.code); + expect().assertFail(); + } + console.log(TAG + "************* CustomTokenizerTest004 end *************"); + return true; + }); + + /** + * @tc.number rdbStoreCustomTokenizerEtsTest + * @tc.name CustomTokenizerTest005 + * @tc.desc Test intermediate words + */ + it('CustomTokenizerTest005', 0, async () => { + console.log(TAG + "************* CustomTokenizerTest005 start *************"); + try { + let store: relationalStore.RdbStore | undefined = undefined; + const storeConfig: relationalStore.StoreConfig = { + name: "MyStore.db", + securityLevel: relationalStore.SecurityLevel.S3 + }; + let customType = relationalStore.Tokenizer.CUSTOM_TOKENIZER; + let customTypeSupported = relationalStore.isTokenizerSupported(customType); + if (customTypeSupported) { + storeConfig.tokenizer = customType; + } else { + console.info('not support custom tokenizer.'); + return true; + } + store = await relationalStore.getRdbStore(context, storeConfig); + if (store == undefined) { + expect().assertFail(); + return false; + } + + let createTableSql = "CREATE VIRTUAL TABLE example USING fts5(content, " + + "tokenize = 'customtokenizer cut_mode short_words')"; + await store.executeSql(createTableSql); + + let insertValueSql = "INSERT INTO example VALUES('中华人民共和国')"; + await store.executeSql(insertValueSql); + + let words: string[] = ["中华", "华人", "人民", "共和", "共和国", "中华人民共和国"]; + for (const word of words) { + let resultSet = await store.querySql("SELECT * FROM example WHERE content MATCH ?;", [word]); + expect(1).assertEqual(resultSet.rowCount); + } + let noMatchWord = "人民共和国"; + let noMatchResultSet = await store.querySql("SELECT * FROM example WHERE content MATCH ?;", [noMatchWord]); + expect(0).assertEqual(noMatchResultSet.rowCount); + + let dropTableSql = "DROP TABLE IF EXISTS example"; + await store.executeSql(dropTableSql); + await store.close(); + } catch (err) { + console.log("errcode: " + err.code); + expect().assertFail(); + } + console.log(TAG + "************* CustomTokenizerTest005 end *************"); + return true; + }); + + /** + * @tc.number rdbStoreCustomTokenizerEtsTest + * @tc.name CustomTokenizerTest006 + * @tc.desc Test in both Chinese and English + */ + it('CustomTokenizerTest006', 0, async () => { + console.log(TAG + "************* CustomTokenizerTest006 start *************"); + try { + let store: relationalStore.RdbStore | undefined = undefined; + const storeConfig: relationalStore.StoreConfig = { + name: "MyStore.db", + securityLevel: relationalStore.SecurityLevel.S3 + }; + let customType = relationalStore.Tokenizer.CUSTOM_TOKENIZER; + let customTypeSupported = relationalStore.isTokenizerSupported(customType); + if (customTypeSupported) { + storeConfig.tokenizer = customType; + } else { + console.info('not support custom tokenizer.'); + return true; + } + store = await relationalStore.getRdbStore(context, storeConfig); + if (store == undefined) { + expect().assertFail(); + return false; + } + + let createTableSql = "CREATE VIRTUAL TABLE example USING fts5(content, " + + "tokenize = 'customtokenizer cut_mode short_words')"; + await store.executeSql(createTableSql); + + let insertValueSql = "INSERT INTO example VALUES('武汉市长江大桥Wuhan Yangtze River Bridge是武汉市最长的桥')"; + await store.executeSql(insertValueSql); + + let words: string[] = ["长江", "大桥", "Wuhan", "Yangtze", "武汉市"]; + for (const word of words) { + let resultSet = await store.querySql("SELECT * FROM example WHERE content MATCH ?;", [word]); + expect(1).assertEqual(resultSet.rowCount); + } + + let dropTableSql = "DROP TABLE IF EXISTS example"; + await store.executeSql(dropTableSql); + await store.close(); + } catch (err) { + console.log("errcode: " + err.code); + expect().assertFail(); + } + console.log(TAG + "************* CustomTokenizerTest006 end *************"); + return true; + }); + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetRowForFlutterEts.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetRowForFlutterEts.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f8d67d68d1e3ea0da17f3d68cbb2a4eb5e45362f --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetRowForFlutterEts.test.ets @@ -0,0 +1,306 @@ + +/* + * Copyright (C) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level, Size, TestType, + Assert } from "@ohos/hypium"; +import relationalStore from '@ohos.data.relationalStore'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { ValuesBucket } from "@ohos.data.ValuesBucket"; + + +const TAG = "[STAGE_RELATIONAL_STORE_JSKITS_TEST]"; +let rdbStore:relationalStore.RdbStore | undefined = undefined; + +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + + "id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, salary REAL, blobType BLOB, data1 asset)"; + +const STORE_CONFIG: relationalStore.StoreConfig = { + name: "rdbStore.db", + securityLevel: relationalStore.SecurityLevel.S1, +} + +const delegator = AbilityDelegatorRegistry.getAbilityDelegator(); +const context = delegator.getAppContext().getApplicationContext(); + + +export default function getRowForFlutterEtsTest() { + describe('getRowForFlutterEtsTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll') + }) + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore?.executeSql(CREATE_TABLE_TEST); + }) + afterEach(async () => { + console.info(TAG + 'afterEach'); + await relationalStore.deleteRdbStore(context, "rdbStore.db"); + }) + afterAll(async () => { + console.info(TAG + 'afterAll'); + }) + + + /** + * @tc.name testRdbStoreGetRowForFlutter + * @tc.number testRdbStoreGetRowForFlutter_0001 + * @tc.desc integer greater than Number.MAX_SAFE_INTEGER test + */ + it('testRdbStoreGetRowForFlutter_0001', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0001 start *************"); + let valueNum = Number.MAX_SAFE_INTEGER.toString() + 0; + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket: ValuesBucket = { + 'age': valueNum, + } + try { + let rowId = await rdbStore.insert("test", valueBucket); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + let res = resultSet.getRowForFlutter(); + expect(valueNum).assertEqual(res.age); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0001 end *************"); + }) + + /** + * @tc.name testRdbStoreGetRowForFlutter + * @tc.number testRdbStoreGetRowForFlutter_0002 + * @tc.desc integer is Number.MAX_SAFE_INTEGER test + */ + it('testRdbStoreGetRowForFlutter_0002', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0002 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': Number.MAX_SAFE_INTEGER, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + let res = resultSet.getRowForFlutter(); + expect(Number.MAX_SAFE_INTEGER).assertEqual(res.age); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0002 end *************"); + }) + + /** + * @tc.name testRdbStoreGetRowForFlutter + * @tc.number testRdbStoreGetRowForFlutter_0003 + * @tc.desc integer less than Number.MAX_SAFE_INTEGER test + */ + it('testRdbStoreGetrowForFlutter_0003', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0003 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': 500, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + let res = resultSet.getRowForFlutter(); + expect(500).assertEqual(res.age); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0003 end *************"); + }) + + /** + * @tc.name testRdbStoreGetRowForFlutter + * @tc.number testRdbStoreGetRowForFlutter_0004 + * @tc.desc integer greater than Number.MIN_SAFE_INTEGER test + */ + it('testRdbStoreGetRowForFlutter_0004', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0004 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': -500, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + let res = resultSet.getRowForFlutter(); + expect(-500).assertEqual(res.age); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0004 end *************"); + }) + + /** + * @tc.name testRdbStoreGetRowForFlutter + * @tc.number testRdbStoreGetRowForFlutter_0005 + * @tc.desc integer is Number.MIN_SAFE_INTEGER test + */ + it('testRdbStoreGetRowForFlutter_0005', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0005 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': Number.MIN_SAFE_INTEGER, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + let res = resultSet.getRowForFlutter(); + expect(Number.MIN_SAFE_INTEGER).assertEqual(res.age); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0005 end *************"); + }) + + /** + * @tc.name testRdbStoreGetRowForFlutter + * @tc.number testRdbStoreGetRowForFlutter_0006 + * @tc.desc integer less than Number.MIN_SAFE_INTEGER test + */ + it('testRdbStoreGetRowForFlutter_0006', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0006 start *************"); + let valueNum = Number.MIN_SAFE_INTEGER.toString() + 0; + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': valueNum, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + let res = resultSet.getRowForFlutter(); + expect(valueNum).assertEqual(res.age); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0006 end *************"); + }) + + /** + * @tc.name testRdbStoreGetRowForFlutter + * @tc.number testRdbStoreGetRowForFlutter_0007 + * @tc.desc other types test + */ + it('testRdbStoreGetRowForFlutter_0007', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0007 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const asset1: relationalStore.Asset = { + name: "name1", + uri: "uri1", + createTime: "createTime1", + modifyTime: "modifyTime1", + size: "size1", + path: "path1", + } + const valueBucket1: relationalStore.ValuesBucket = { + 'name': 'test', + 'age': 18, + 'salary': 100.5, + 'blobType': true, + 'data1': asset1, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + let res = resultSet.getRowForFlutter(); + expect('test').assertEqual(res.name); + expect(18).assertEqual(res.age); + expect(100.5).assertEqual(res.salary); + const assets2 = res["data1"] as relationalStore.Asset; + expect(asset1.name).assertEqual(assets2.name); + expect(asset1.uri).assertEqual(assets2.uri); + expect(asset1.createTime).assertEqual(assets2.createTime); + expect(asset1.modifyTime).assertEqual(assets2.modifyTime); + expect(asset1.size).assertEqual(assets2.size); + expect(asset1.path).assertEqual(assets2.path); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0007 end *************"); + }) + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetSqlInfoEts.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetSqlInfoEts.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..6894e7c7b816bf8fef7b7cc74d6706c91a28e685 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetSqlInfoEts.test.ets @@ -0,0 +1,727 @@ +/* + * Copyright (C) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; +import relationalStore from '@ohos.data.relationalStore'; +import sendableRelationalStore from '@ohos.data.sendableRelationalStore'; + +const TAG = "[RDB_GETSQL_TEST]"; +const bucket1000: relationalStore.ValuesBucket = {}; +for(let i = 0; i < 1001; i++) { + bucket1000["test" + i] = i; +} +export default function RDBstoreGetSqlInfoTest() { + describe('rdbstoreGetSqlInfoTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll'); + }); + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + }); + afterEach(async () => { + console.info(TAG + 'afterEach'); + }); + afterAll(async () => { + console.info(TAG + 'afterAll'); + }); + + console.log(TAG + "*************Unit Test Begin*************"); + /** + * @tc.number testGetInsertSqlInfo + * @tc.name Get Insert SQL Info + * @tc.desc Tests the functionality of generating an INSERT SQL statement and its arguments. + */ + it('testGetInsertSqlInfo', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfo start *************"); + try { + const bucket: relationalStore.ValuesBucket = { + name: "Logitech", + age: "18", + sex: "man", + desc: "asserter" + }; + const info: relationalStore.SqlInfo = relationalStore.getInsertSqlInfo( + "USER", + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(info.sql).assertEqual("INSERT INTO USER(age,desc,name,sex) VALUES (?,?,?,?)"); + expect(info.args[0]).assertEqual("18"); + expect(info.args[1]).assertEqual("asserter"); + expect(info.args[2]).assertEqual("Logitech"); + expect(info.args[3]).assertEqual("man"); + console.log(TAG + "************* testGetInsertSqlInfo end *************"); + } catch (e){ + expect(null).assertFail(); + console.log(TAG + "************* testGetInsertSqlInfo end *************"); + } + }); + + /** + * @tc.number testGetInsertSqlInfoTabkleNameTooLong + * @tc.name Get Insert SQL Info tablename length must less then 256 + * @tc.desc Verifies that an error is thrown when the tablename is too long. + */ + it('testGetInsertSqlInfoTabkleNameTooLong', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfoTabkleNameTooLong start *************"); + const bucket: relationalStore.ValuesBucket = { + name: "Logitech", + age: "18", + sex: "man", + desc: "asserter" + }; + let tableName: string = "x".repeat(257); + try { + relationalStore.getInsertSqlInfo( + tableName, + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetInsertSqlInfoTabkleNameTooLong end *************"); + } + }); + + /** + * @tc.number testGetInsertSqlInfoBucketTooLong + * @tc.name Get Insert SQL Info Bucket length must less then 1000 + * @tc.desc Verifies that an error is thrown when the bucket is too long. + */ + it('testGetInsertSqlInfoBucketTooLong', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfoBucketTooLong start *************"); + try { + relationalStore.getInsertSqlInfo( + "user", + bucket1000, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetInsertSqlInfoBucketTooLong end *************"); + } + }); + + /** + * @tc.number testGetInsertSqlInfoBucketColumnTooLong + * @tc.name Get Insert SQL Info bucket key length must less then 256 + * @tc.desc Verifies that an error is thrown when the bucket Column is too long. + */ + it('testGetInsertSqlInfoBucketColumnTooLong', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfoBucketColumnTooLong start *************"); + let tableName: string = "a".repeat(257); + const bucket: relationalStore.ValuesBucket = { + name: tableName, + age: "18", + sex: "man", + desc: "asserter" + }; + bucket[tableName] = "tableName" + try { + relationalStore.getInsertSqlInfo( + "user", + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetInsertSqlInfoBucketColumnTooLong end *************"); + } + }); + + /** + * @tc.number testGetInsertSqlInfoTableNameIsEmpty + * @tc.name Get Insert SQL Info table Is empty + * @tc.desc Verifies that an error is thrown when the table is empty or null. + */ + it('testGetInsertSqlInfoTableNameIsEmpty', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfoTableNameIsEmpty start *************"); + const bucket: relationalStore.ValuesBucket = { + name: "tableName", + age: "18", + sex: "man", + desc: "asserter" + }; + try { + relationalStore.getInsertSqlInfo( + "", + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetInsertSqlInfoTableNameIsEmpty end *************"); + } + }); + + /** + * @tc.number testGetInsertSqlInfoConflictResolutionIsNotEmpty + * @tc.name Get Insert SQL Info + * @tc.desc Verifies that an error is thrown when the ConflictResolution is not empty. + */ + it('testGetInsertSqlInfoConflictResolutionIsNotEmpty', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfoConflictResolutionIsNotEmpty start *************"); + try { + const bucket: relationalStore.ValuesBucket = { + name: "tableName", + age: "18", + sex: "man", + desc: "asserter" + }; + const info: relationalStore.SqlInfo = relationalStore.getInsertSqlInfo( + "tableName", + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(info.sql).assertEqual("INSERT INTO tableName(age,desc,name,sex) VALUES (?,?,?,?)"); + console.log(TAG + "************* testGetInsertSqlInfoConflictResolutionIsNotEmpty end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetInsertSqlInfoConflictResolutionIsNotEmpty end *************"); + } + }); + + /** + * @tc.number testGetInsertSqlInfoBucketIsNull + * @tc.name Get Insert SQL Info Bucket Is Null + * @tc.desc Verifies that an error is thrown when the bucket is empty or null. + */ + it('testGetInsertSqlInfoBucketIsNull', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfoBucketIsNull start *************"); + const bucket: relationalStore.ValuesBucket = {}; + try { + relationalStore.getInsertSqlInfo( + "USER", + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetInsertSqlInfoBucketIsNull end *************"); + } + }); + + /** + * @tc.number testGetInsertSqlInfoBucketIsAssets + * @tc.name Get Insert SQL Info Bucket contains Assets + * @tc.desc Verifies that an error is thrown when the bucket contains Assets & ON_CONFLICT_REPLACE. + */ + it('testGetInsertSqlInfoBucketIsAssets', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfoBucketIsAssets start *************"); + const values: relationalStore.Assets = [ + { + name: "a", + uri: "b", + path: "c", + createTime: "d", + modifyTime: "e", + size: "f", + status: relationalStore.AssetStatus.ASSET_INSERT + } + ]; + const bucket: relationalStore.ValuesBucket = { + value: values + }; + try { + relationalStore.getInsertSqlInfo( + "ASSETS", + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_REPLACE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetInsertSqlInfoBucketIsAssets end *************"); + } + }); + + /** + * @tc.number testGetInsertSqlInfoBucketIsAssets2 + * @tc.name Get Insert SQL Info Bucket contains Assets + * @tc.desc Verifies that an error is thrown when the bucket contains Assets & ON_CONFLICT_IGNORE. + */ + it('testGetInsertSqlInfoBucketIsAssets2', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfoBucketIsAssets start *************"); + try { + const values: relationalStore.Assets = [ + { + name: "a", + uri: "b", + path: "c", + createTime: "d", + modifyTime: "e", + size: "f", + status: relationalStore.AssetStatus.ASSET_INSERT + } + ]; + const bucket: relationalStore.ValuesBucket = { + value: values + }; + const info: relationalStore.SqlInfo = relationalStore.getInsertSqlInfo( + "USER", + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_IGNORE + ); + const assets = info.args[0] as relationalStore.Assets; + expect(info.sql).assertEqual("INSERT OR IGNORE INTO USER(value) VALUES (?)"); + expect(assets.length).assertEqual(values.length); + expect(assets[0].name).assertEqual(values[0].name); + expect(assets[0].uri).assertEqual(values[0].uri); + expect(assets[0].path).assertEqual(values[0].path); + expect(assets[0].createTime).assertEqual(values[0].createTime); + expect(assets[0].modifyTime).assertEqual(values[0].modifyTime); + expect(assets[0].size).assertEqual(values[0].size); + expect(assets[0].status).assertEqual(values[0].status); + console.log(TAG + "************* testGetInsertSqlInfo end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetInsertSqlInfo end *************"); + } + }); + + /** + * @tc.number testGetUpdateSqlInfo + * @tc.name Get Update SQL Info + * @tc.desc Verifies `getUpdateSqlInfo` function correctly generates an UPDATE SQL statement and its arguments. + */ + it('testGetUpdateSqlInfo', 0, async () => { + console.log(TAG + "************* testGetUpdateSqlInfo start *************"); + try { + const bucket: relationalStore.ValuesBucket = { + name: "Logitech", + age: "18", + sex: "man", + desc: "asserter" + }; + const predicates = new relationalStore.RdbPredicates("users"); + const info: relationalStore.SqlInfo = relationalStore.getUpdateSqlInfo( + predicates, + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(info.sql).assertEqual("UPDATE users SET age=?,desc=?,name=?,sex=?"); + expect(info.args[0]).assertEqual("18"); + expect(info.args[1]).assertEqual("asserter"); + expect(info.args[2]).assertEqual("Logitech"); + expect(info.args[3]).assertEqual("man"); + console.log(TAG + "************* testGetUpdateSqlInfo end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetUpdateSqlInfo end *************"); + } + }); + + /** + * @tc.number testGetUpdateSqlInfoBucketIsNull + * @tc.name Get Update SQL Info Bucket Is Null + * @tc.desc Verifies that an error is thrown when the bucket is empty. + */ + it('testGetUpdateSqlInfoBucketIsNull', 0, async () => { + console.log(TAG + "************* testGetUpdateSqlInfoBucketIsNull start *************"); + const predicates = new relationalStore.RdbPredicates("users"); + const bucket: relationalStore.ValuesBucket = {}; + try { + relationalStore.getUpdateSqlInfo( + predicates, + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetUpdateSqlInfoBucketIsNull end *************"); + } + }); + + /** + * @tc.number testGetUpdateSqlInfoBucketTooLong + * @tc.name Get Update SQL Info Bucket length must less then 1000 + * @tc.desc Verifies that an error is thrown when the bucket is too long. + */ + it('testGetUpdateSqlInfoBucketTooLong', 0, async () => { + console.log(TAG + "************* testGetUpdateSqlInfoBucketTooLong start *************"); + const predicates = new relationalStore.RdbPredicates("users"); + try { + relationalStore.getUpdateSqlInfo( + predicates, + bucket1000, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetUpdateSqlInfoBucketTooLong end *************"); + } + }); + + /** + * @tc.number testGetUpdateSqlInfoBucketCloumnTooLong + * @tc.name Get Update SQL Info the column in bucket length must less then 256 + * @tc.desc Verifies that an error is thrown when the column in bucket is too long. + */ + it('testGetUpdateSqlInfoBucketCloumnTooLong', 0, async () => { + console.log(TAG + "************* testGetUpdateSqlInfoBucketCloumnTooLong start *************"); + const predicates = new relationalStore.RdbPredicates("users"); + let tableName: string = "a".repeat(257); + const bucket: relationalStore.ValuesBucket = { + age: "18", + sex: "man", + desc: "asserter" + }; + bucket[tableName] = "tableName"; + try { + relationalStore.getUpdateSqlInfo( + predicates, + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetUpdateSqlInfoBucketCloumnTooLong end *************"); + } + }); + + /** + * @tc.number testGetUpdateSqlInfoTableTooLong + * @tc.name Get Update SQL Info Bucket Is Null + * @tc.desc Verifies that an error is thrown when the tablename is too long. + */ + it('testGetUpdateSqlInfoTableTooLong', 0, async () => { + console.log(TAG + "************* testGetUpdateSqlInfoTableTooLong start *************"); + let tableName: string = "a".repeat(257); + for(let i = 0; i < 256; i++) { + tableName = tableName + "a"; + } + const predicates = new relationalStore.RdbPredicates(tableName); + const bucket: relationalStore.ValuesBucket = { + name: "tableName", + age: "18", + sex: "man", + desc: "asserter" + }; + try { + relationalStore.getUpdateSqlInfo( + predicates, + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetUpdateSqlInfoTableTooLong end *************"); + } + }); + + /** + * @tc.number testGetUpdateSqlInfoWhereClauseTooLong + * @tc.name Get Update SQL Info Bucket Is Null + * @tc.desc Verifies that an error is thrown when the WhereClause is too long. + */ + it('testGetUpdateSqlInfoWhereClauseTooLong', 0, async () => { + console.log(TAG + "************* testGetUpdateSqlInfoWhereClauseTooLong start *************"); + let tableName: string = ""; + for(let i = 0; i < 256; i++) { + tableName = tableName + "a"; + } + const predicates = new relationalStore.RdbPredicates("tableName"); + predicates.equalTo(tableName, "user"); + const bucket: relationalStore.ValuesBucket = { + name: "tableName", + age: "18", + sex: "man", + desc: "asserter" + }; + try { + relationalStore.getUpdateSqlInfo( + predicates, + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetUpdateSqlInfoWhereClauseTooLong end *************"); + } + }); + + /** + * @tc.number testGetUpdateSqlInfoConflictResolutionIsNotEmpty + * @tc.name Get Update SQL Info Bucket Is Null + * @tc.desc Verifies that an error is thrown when the Conflict is not empty. + */ + it('testGetUpdateSqlInfoConflictResolutionIsNotEmpty', 0, async () => { + console.log(TAG + "************* testGetUpdateSqlInfoConflictResolutionIsNotEmpty start *************"); + try { + const predicates = new relationalStore.RdbPredicates("tableName"); + predicates.equalTo("tableName", "user"); + const bucket: relationalStore.ValuesBucket = { + name: "tableName", + age: "18", + sex: "man", + desc: "asserter" + }; + const info: relationalStore.SqlInfo = relationalStore.getUpdateSqlInfo( + predicates, + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(info.sql).assertEqual("UPDATE tableName SET age=?,desc=?,name=?,sex=? WHERE tableName = ? "); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetUpdateSqlInfoConflictResolutionIsEmpty end *************"); + } + }); + + /** + * @tc.number testGetDeleteSqlInfo + * @tc.name Get Delete SQL Info + * @tc.desc Verifies that the generated delete SQL statement is correct when the table name is provided. + */ + it('testGetDeleteSqlInfo', 0, async () => { + console.log(TAG + "************* testGetDeleteSqlInfo start *************"); + try { + const predicates = new relationalStore.RdbPredicates("users"); + const info: relationalStore.SqlInfo = relationalStore.getDeleteSqlInfo(predicates); + expect(info.sql).assertEqual("DELETE FROM users"); + console.log(TAG + "************* testGetDeleteSqlInfo end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetDeleteSqlInfo end *************"); + } + }); + + /** + * @tc.number testGetDeleteSqlInfo2 + * @tc.name Get Delete SQL Info Table Name Must Be Not Empty + * @tc.desc Verifies that the generated delete SQL statement is correct when the table name is provided. + */ + it('testGetDeleteSqlInfo2', 0, async () => { + console.log(TAG + "************* testGetDeleteSqlInfo2 start *************"); + try { + const predicates = new relationalStore.RdbPredicates("users"); + predicates.equalTo("tableName", "a"); + predicates.notEqualTo("age", 18) + const info: relationalStore.SqlInfo = relationalStore.getDeleteSqlInfo(predicates); + expect(info.sql).assertEqual("DELETE FROM users WHERE tableName = ? AND age <> ? "); + expect(info.args[0]).assertEqual("a"); + expect(info.args[1]).assertEqual(18); + console.log(TAG + "************* testGetDeleteSqlInfo2 end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetQuerySqlInfo end *************"); + } + }); + + /** + * @tc.number testGetDeleteSqlInfoTableNameTooLong + * @tc.name Get Delete SQL Info Table Name length Must less then 256 + * @tc.desc Verifies that an error is thrown when the table name is too long. + */ + it('testGetDeleteSqlInfoTableNameTooLong', 0, async () => { + console.log(TAG + "************* testGetDeleteSqlInfoTableNameTooLong start *************"); + try { + let tableName: string = "a".repeat(257); + const predicates = new relationalStore.RdbPredicates(tableName); + relationalStore.getDeleteSqlInfo(predicates); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetDeleteSqlInfoTableNameTooLong end *************"); + } + }); + + /** + * @tc.number testGetDeleteSqlInfoValueTooLong + * @tc.name Get Delete SQL Info value Must less then 256 + * @tc.desc Verifies that an error is thrown when the value is too long. + */ + it('testGetDeleteSqlInfoValueTooLong', 0, async () => { + console.log(TAG + "************* testGetDeleteSqlInfoValueTooLong start *************"); + try { + let tableName: string = "a".repeat(257); + const predicates = new relationalStore.RdbPredicates("tableName"); + predicates.equalTo(tableName, "a"); + relationalStore.getDeleteSqlInfo(predicates); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetDeleteSqlInfoValueTooLong end *************"); + } + }); + + /** + * @tc.number testGetQuerySqlInfo + * @tc.name Get Query SQL Info + * @tc.desc Verifies that the generated query SQL statement is correct with default columns. + */ + it('testGetQuerySqlInfo', 0, async () => { + console.log(TAG + "************* testGetQuerySqlInfo start *************"); + try { + const predicates = new relationalStore.RdbPredicates("users"); + const info: relationalStore.SqlInfo = relationalStore.getQuerySqlInfo(predicates); + expect(info.sql).assertEqual("SELECT * FROM users"); + console.log(TAG + "************* testGetQuerySqlInfo end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetQuerySqlInfo end *************"); + } + }); + + /** + * @tc.number testGetQuerySqlInfoColumnsIsNullList + * @tc.name Get Query SQL Info Columns Is Null List + * @tc.desc Verifies that the generated query SQL statement is correct when an empty column list is provided. + */ + it('testGetQuerySqlInfoColumnsIsNullList', 0, async () => { + console.log(TAG + "************* testGetQuerySqlInfoColumnsIsNullList start *************"); + try { + const predicates = new relationalStore.RdbPredicates("users"); + const info: relationalStore.SqlInfo = relationalStore.getQuerySqlInfo(predicates, []); + expect(info.sql).assertEqual("SELECT * FROM users"); + console.log(TAG + "************* testGetQuerySqlInfoColumnsIsNullList end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetQuerySqlInfoColumnsIsNullList end *************"); + } + }); + + /** + * @tc.number testGetQuerySqlInfoByColumns + * @tc.name Get Query SQL Info By Columns + * @tc.desc Verifies that the generated query SQL statement is correct when specific columns are provided. + */ + it('testGetQuerySqlInfoByColumns', 0, async () => { + console.log(TAG + "************* testGetQuerySqlInfoByColumns start *************"); + try { + const predicates = new relationalStore.RdbPredicates("users"); + const info: relationalStore.SqlInfo = relationalStore.getQuerySqlInfo(predicates, ["name", "age"]); + expect(info.sql).assertEqual("SELECT name, age FROM users"); + console.log(TAG + "************* testGetQuerySqlInfoByColumns end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetQuerySqlInfoByColumns end *************"); + } + }); + + /** + * @tc.number testGetQuerySqlInfoTableNameTooLong + * @tc.name Get Query SQL Info Table Name length must less then 256 + * @tc.desc Verifies that an error is thrown when the Table is too Long. + */ + it('testGetQuerySqlInfoTableNameTooLong', 0, async () => { + console.log(TAG + "************* testGetQuerySqlInfoTableNameTooLong start *************"); + try { + let tableName: string = "a".repeat(257); + const predicates = new relationalStore.RdbPredicates(tableName); + relationalStore.getQuerySqlInfo(predicates); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetQuerySqlInfoTableNameTooLong end *************"); + } + }); + + /** + * @tc.number testGetQuerySqlInfoWhereClauseTooLong + * @tc.name Get Query SQL Info WhereClause length is less then 256 + * @tc.desc Verifies that an error is thrown when the WhereClause is too long. + */ + it('testGetQuerySqlInfoWhereClauseTooLong', 0, async () => { + console.log(TAG + "************* testGetQuerySqlInfoWhereClauseTooLong start *************"); + try { + let tableName: string = "a".repeat(257); + const predicates = new relationalStore.RdbPredicates("tableName"); + predicates.equalTo(tableName, "a"); + relationalStore.getQuerySqlInfo(predicates); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetQuerySqlInfoWhereClauseTooLong end *************"); + } + }); + + /** + * @tc.number testGetQuerySqlInfoColumnsNotstringarray + * @tc.name Get Query SQL Info Columns must be a string array + * @tc.desc Verifies that an error is thrown when the Columns is not a string array. + */ + it('testGetQuerySqlInfoColumnsNotstringarray', 0, async () => { + console.log(TAG + "************* testGetQuerySqlInfoColumnsNotstringarray start *************"); + try { + const predicates = new relationalStore.RdbPredicates("tableName"); + predicates.equalTo("tableName", "a"); + const info: relationalStore.SqlInfo = relationalStore.getQuerySqlInfo(predicates, ["3", "4"]); + expect(info.sql).assertEqual("SELECT 3, 4 FROM tableName WHERE tableName = ? "); + expect(info.args[0]).assertEqual('a'); + console.log(TAG + "************* testGetQuerySqlInfoColumnsNotstringarray end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetQuerySqlInfoColumnsNotstringarray end *************"); + } + }); + + /** + * @tc.number testGetQuerySqlInfoColumnsTooLong + * @tc.name Get Query SQL Info Columns length Must less then 1000 + * @tc.desc Verifies that an error is thrown when the Columns is too length. + */ + it('testGetQuerySqlInfoColumnsTooLong', 0, async () => { + console.log(TAG + "************* testGetQuerySqlInfoColumnsTooLong start *************"); + try { + const colums:string[] = new Array(1003); + for(let i = 0; i < colums.length; i++) { + colums[i] = "a"; + } + const predicates = new relationalStore.RdbPredicates("tableName"); + predicates.equalTo("tableName", "a"); + relationalStore.getQuerySqlInfo(predicates, colums); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetQuerySqlInfoColumnsTooLong end *************"); + } + }); + + /** + * @tc.number testToSendableValues + * @tc.name Test To Sendable Values + * @tc.desc Verifies that converting an array of values to sendable values works correctly. + */ + it('testToSendableValues', 0, async () => { + console.log(TAG + "************* testToSendableValues start *************"); + try { + const array: relationalStore.ValueType[] = []; + array.push(1); + array.push(2); + array.push("aaaaaaa"); + const values = sendableRelationalStore.toSendableValues(array); + expect(values.length).assertEqual(3); + expect(values[0]).assertEqual(1); + expect(values[1]).assertEqual(2); + expect(values[2]).assertEqual("aaaaaaa"); + console.log(TAG + "************* testToSendableValues end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testToSendableValues end *************"); + } + }); + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetValueForFlutterEts.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetValueForFlutterEts.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..b8d8461839388cf82181f2357a3d5fbce3c0966b --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetValueForFlutterEts.test.ets @@ -0,0 +1,299 @@ + +/* + * Copyright (C) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level, Size, TestType, + Assert } from "@ohos/hypium"; +import relationalStore from '@ohos.data.relationalStore'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { ValuesBucket } from "@ohos.data.ValuesBucket"; + + +const TAG = "[STAGE_RELATIONAL_STORE_JSKITS_TEST]"; +let rdbStore:relationalStore.RdbStore | undefined = undefined; + +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + + "id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, salary REAL, blobType BLOB, data1 asset)"; + +const STORE_CONFIG: relationalStore.StoreConfig = { + name: "rdbStore.db", + securityLevel: relationalStore.SecurityLevel.S1, +} + +const delegator = AbilityDelegatorRegistry.getAbilityDelegator(); +const context = delegator.getAppContext().getApplicationContext(); + + +export default function getValueForFlutterEtsTest() { + describe('getValueForFlutterEtsTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll') + }) + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore?.executeSql(CREATE_TABLE_TEST); + }) + afterEach(async () => { + console.info(TAG + 'afterEach'); + await relationalStore.deleteRdbStore(context, "rdbStore.db"); + }) + afterAll(async () => { + console.info(TAG + 'afterAll'); + }) + + + /** + * @tc.name testRdbStoreGetValueForFlutter + * @tc.number testRdbStoreGetValueForFlutter_0001 + * @tc.desc integer greater than Number.MAX_SAFE_INTEGER test + */ + it('testRdbStoreGetValueForFlutter_0001', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0001 start *************"); + let valueNum = Number.MAX_SAFE_INTEGER.toString() + 0; + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': valueNum, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + expect(valueNum).assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('age'))); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0001 end *************"); + }) + + /** + * @tc.name testRdbStoreGetValueForFlutter + * @tc.number testRdbStoreGetValueForFlutter_0002 + * @tc.desc integer is Number.MAX_SAFE_INTEGER test + */ + it('testRdbStoreGetValueForFlutter_0002', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0002 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': Number.MAX_SAFE_INTEGER, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + expect(Number.MAX_SAFE_INTEGER).assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('age'))); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0002 end *************"); + }) + + /** + * @tc.name testRdbStoreGetValueForFlutter + * @tc.number testRdbStoreGetValueForFlutter_0003 + * @tc.desc integer less than Number.MAX_SAFE_INTEGER test + */ + it('testRdbStoreGetValueForFlutter_0003', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0003 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': 100, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + expect(100).assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('age'))); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0003 end *************"); + }) + + /** + * @tc.name testRdbStoreGetValueForFlutter + * @tc.number testRdbStoreGetValueForFlutter_0004 + * @tc.desc integer greater than Number.MIN_SAFE_INTEGER test + */ + it('testRdbStoreGetValueForFlutter_0004', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0004 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': -100, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + expect(-100).assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('age'))); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0004 end *************"); + }) + + /** + * @tc.name testRdbStoreGetValueForFlutter + * @tc.number testRdbStoreGetValueForFlutter_0005 + * @tc.desc integer is Number.MIN_SAFE_INTEGER test + */ + it('testRdbStoreGetValueForFlutter_0005', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0005 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': Number.MIN_SAFE_INTEGER, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + expect(Number.MIN_SAFE_INTEGER).assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('age'))); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0005 end *************"); + }) + + /** + * @tc.name testRdbStoreGetValueForFlutter + * @tc.number testRdbStoreGetValueForFlutter_0006 + * @tc.desc integer less than Number.MIN_SAFE_INTEGER test + */ + it('testRdbStoreGetValueForFlutter_0006', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0006 start *************"); + let valueNum = Number.MIN_SAFE_INTEGER.toString() + 0; + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': valueNum, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + expect(valueNum).assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('age'))); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0006 end *************"); + }) + + /** + * @tc.name testRdbStoreGetValueForFlutter + * @tc.number testRdbStoreGetValueForFlutter_0007 + * @tc.desc other types test + */ + it('testRdbStoreGetValueForFlutter_0007', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0007 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const asset1: relationalStore.Asset = { + name: "name1", + uri: "uri1", + createTime: "createTime1", + modifyTime: "modifyTime1", + size: "size1", + path: "path1", + } + const valueBucket1: relationalStore.ValuesBucket = { + 'name': 'test', + 'age': 18, + 'salary': 100, + 'blobType': true, + 'data1': asset1, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + expect('test').assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('name'))); + expect(18).assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('age'))); + expect(1).assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('blobType'))); + const assets2 = resultSet.getValueForFlutter(resultSet.getColumnIndex('data1')) as relationalStore.Asset; + expect(asset1.name).assertEqual(assets2.name); + expect(asset1.uri).assertEqual(assets2.uri); + expect(asset1.createTime).assertEqual(assets2.createTime); + expect(asset1.modifyTime).assertEqual(assets2.modifyTime); + expect(asset1.size).assertEqual(assets2.size); + expect(asset1.path).assertEqual(assets2.path); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0007 end *************"); + }) + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstorePerfStatEts.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstorePerfStatEts.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..02fbd83d8c71214bd701a40297bb01ebfe47cdc6 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstorePerfStatEts.test.ets @@ -0,0 +1,671 @@ + +/* + * Copyright (C) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level, Size, TestType } from "@ohos/hypium"; +import relationalStore from '@ohos.data.relationalStore'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; + +const TAG = "[STAGE_RELATIONAL_STORE_JSKITS_TEST]"; +let rdbStore:relationalStore.RdbStore | undefined = undefined; + +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL)"; + +const STORE_CONFIG: relationalStore.StoreConfig = { + name: "rdbStore.db", + securityLevel: relationalStore.SecurityLevel.S1, +} + +const delegator = AbilityDelegatorRegistry.getAbilityDelegator(); +const context = delegator.getAppContext().getApplicationContext(); + + +export default function PerfStatEtsTest() { + describe('perfStatEtsTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll') + }) + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore?.executeSql(CREATE_TABLE_TEST); + const valueBucket: relationalStore.ValuesBucket = { + 'name': 'zhangsan', + 'age': 18, + 'salary': 25000, + }; + await rdbStore?.insert('test', valueBucket); + await new Promise(resolve => setTimeout(resolve, 1000)); + }) + afterEach(async () => { + console.info(TAG + 'afterEach'); + try { + rdbStore?.off('perfStat'); + } catch (err) { + expect(err.code).assertEqual("14800014"); + } + await relationalStore.deleteRdbStore(context, "rdbStore.db"); + }) + afterAll(async () => { + console.info(TAG + 'afterAll'); + }) + + + /** + * @tc.name Normal case for perfStat insert data execution time + * @tc.number testRdbStorePerfStat_0001 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0001', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0001 start *************"); + rdbStore?.on('perfStat', async (SqlExeInfo) => { + expect('INSERT INTO test(age,name,salary) VALUES (?,?,?)').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }) + const valueBucket: relationalStore.ValuesBucket = { + 'name': 'zhangsan', + 'age': 18, + 'salary': 25000, + }; + let rowId = await rdbStore?.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + console.log(TAG + "************* testRdbStorePerfStat_0001 end *************"); + }) + + /** + * @tc.name Normal case for perfStat update data execution time + * @tc.number testRdbStorePerfStat_0002 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0002', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0002 start *************"); + rdbStore?.on('perfStat', async (SqlExeInfo) => { + expect('UPDATE test SET age=?,name=?,salary=? WHERE id = ? ').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }) + + const valueBucket: relationalStore.ValuesBucket = { + 'name': 'lisi', + 'age': 18, + 'salary': 25000, + }; + let predicates = new relationalStore.RdbPredicates('test'); + predicates.equalTo('id', 1); + let rowId = await rdbStore?.update(valueBucket, predicates); + expect(1).assertEqual(rowId); + console.log(TAG + "************* testRdbStorePerfStat_0002 end *************"); + }) + + /** + * @tc.name Normal case for perfStat delete data execution time + * @tc.number testRdbStorePerfStat_0003 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0003', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0003 start *************"); + rdbStore?.on('perfStat', async (SqlExeInfo) => { + expect('DELETE FROM test WHERE id = ? ').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }) + + + let predicates = new relationalStore.RdbPredicates('test'); + predicates.equalTo('id', 1); + let rowId = await rdbStore?.delete(predicates); + expect(1).assertEqual(rowId); + console.log(TAG + "************* testRdbStorePerfStat_0003 end *************"); + }) + + /** + * @tc.name Normal case for perfStat executeSql data execution time + * @tc.number testRdbStorePerfStat_0004 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0004', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0004 start *************"); + rdbStore?.on('perfStat', async (SqlExeInfo) => { + expect('CREATE TABLE IF NOT EXISTS EMPLOYEE (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }) + + const SQL_CREATE_TABLE1 = "CREATE TABLE IF NOT EXISTS EMPLOYEE (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT NOT NULL)"; // 建表Sql语句 + await rdbStore?.executeSql(SQL_CREATE_TABLE1) + console.log(TAG + "************* testRdbStorePerfStat_0004 end *************"); + }) + + /** + * @tc.name Normal case for perfStat execute data execution time + * @tc.number testRdbStorePerfStat_0005 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0005', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0005 start *************"); + rdbStore?.on('perfStat', async (SqlExeInfo) => { + expect('PRAGMA quick_check').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }) + await rdbStore?.execute("PRAGMA quick_check") + console.log(TAG + "************* testRdbStorePerfStat_0005 end *************"); + }) + + /** + * @tc.name Normal case for perfStat update data execution time + * @tc.number testRdbStorePerfStat_0006 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0006', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0006 start *************"); + rdbStore?.on('perfStat', async (SqlExeInfo) => { + expect('SELECT * FROM test').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }) + let predicates = new relationalStore.RdbPredicates('test'); + await rdbStore?.query(predicates); + console.log(TAG + "************* testRdbStorePerfStat_0006 end *************"); + }) + + /** + * @tc.name Normal case for perfStat querySql data execution time + * @tc.number testRdbStorePerfStat_0007 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0007', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0007 start *************"); + rdbStore?.on('perfStat', async (SqlExeInfo) => { + expect('SELECT * FROM test').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }) + await rdbStore?.querySql("SELECT * FROM test"); + console.log(TAG + "************* testRdbStorePerfStat_0007 end *************"); + }) + + /** + * @tc.name Normal case for perfStat update querySql execution time + * @tc.number testRdbStorePerfStat_0008 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0008', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0008 start *************"); + rdbStore?.on('perfStat', async (SqlExeInfo) => { + expect('with test1 as (select * from test) select * from test').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }) + await rdbStore?.querySql("with test1 as (select * from test) select * from test"); + console.log(TAG + "************* testRdbStorePerfStat_0008 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0009 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0009', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0009 start *************"); + let observer1 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect('SELECT * FROM test').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }; + + let observer2 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + + rdbStore?.on('perfStat', observer1) + await rdbStore?.querySql("SELECT * FROM test"); + // done() + console.log(TAG + "************* testRdbStorePerfStat_0009 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0010 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0010', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0010 start *************"); + let observer1 = async (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect('SELECT * FROM test').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + await new Promise(resolve => setTimeout(resolve, 2000)); + done() + }; + + let observer2 = async (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect('SELECT * FROM test').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + await new Promise(resolve => setTimeout(resolve, 2000)); + done() + }; + + rdbStore?.on('perfStat', observer1) + rdbStore?.on('perfStat', observer2) + await rdbStore?.querySql("SELECT * FROM test"); + console.log(TAG + "************* testRdbStorePerfStat_0010 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0011 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0011', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0011 start *************"); + let observer = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect('INSERT INTO test(age,name,salary) VALUES (?,?,?)').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }; + let observer1 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect('INSERT INTO test(age,name,salary) VALUES (?,?,?)').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }; + rdbStore?.on('perfStat', observer) + rdbStore?.on('statistics', observer1) + const valueBucket1: relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + } + await rdbStore?.insert("test", valueBucket1) + rdbStore?.off('statistics') + console.log(TAG + "************* testRdbStorePerfStat_0011 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0012 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0012', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0012 start *************"); + let observer = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect('INSERT INTO test(age,name,salary) VALUES (?,?,?)').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }; + let observer1 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + rdbStore?.on('statistics', observer1) + rdbStore?.off('statistics') + await new Promise(resolve => setTimeout(resolve, 1000)); + rdbStore?.on('perfStat', observer) + const valueBucket1: relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + } + await rdbStore?.insert("test", valueBucket1) + console.log(TAG + "************* testRdbStorePerfStat_0012 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0013 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0013', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0013 start *************"); + let observer = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect(SqlExeInfo.sql.length > 0).assertTrue(); + done() + }; + let observer1 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + rdbStore?.on('perfStat', observer1) + rdbStore?.off('perfStat') + rdbStore?.on('statistics', observer) + const valueBucket1: relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + } + await rdbStore?.insert("test", valueBucket1) + await new Promise(resolve => setTimeout(resolve, 1000)); + rdbStore?.off('statistics') + console.log(TAG + "************* testRdbStorePerfStat_0013 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0014 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0014', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0014 start *************"); + let observer1 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + let observer2 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + + rdbStore?.on('perfStat', observer1) + rdbStore?.off('perfStat') + rdbStore?.on('perfStat', observer2) + rdbStore?.off('perfStat') + await new Promise(resolve => setTimeout(resolve, 1000)); + await rdbStore?.querySql("SELECT * FROM test"); + done() + console.log(TAG + "************* testRdbStorePerfStat_0014 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0015 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0015', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0015 start *************"); + let observer1 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + let observer2 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect('SELECT * FROM test').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }; + + rdbStore?.on('perfStat', observer1) + rdbStore?.off('perfStat', observer1) + rdbStore?.on('perfStat', observer2) + await new Promise(resolve => setTimeout(resolve, 1000)); + await rdbStore?.querySql("SELECT * FROM test"); + console.log(TAG + "************* testRdbStorePerfStat_0015 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0016 + * @tc.desc 1. Register callback for perfStat + + */ + it('testRdbStorePerfStat_0016', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0016 start *************"); + let store2: relationalStore.RdbStore | undefined = undefined; + let STORE_CONFIG2: relationalStore.StoreConfig = { + name: 'test2.db', + securityLevel: relationalStore.SecurityLevel.S1 + }; + store2 = await relationalStore.getRdbStore(context, STORE_CONFIG2) + await store2?.executeSql(CREATE_TABLE_TEST); + let timerId = -1; + let observer1 = async (sqlExecutionInfo : relationalStore.SqlExecutionInfo) => { + expect('INSERT INTO test(age,name,salary) VALUES (?,?,?)').assertEqual(sqlExecutionInfo.sql[0]); + expect(1).assertEqual(sqlExecutionInfo.sql.length); + if (timerId > 0) { + clearTimeout(timerId); + expect().assertFail(); + } + timerId = setTimeout(done, 2000); + }; + rdbStore?.on('perfStat',observer1) + + const valueBucket: relationalStore.ValuesBucket = { + 'name': 'zhangsan', + 'age': 18, + 'salary': 25000, + }; + let rowId = await rdbStore?.insert('test', valueBucket); + expect(2).assertEqual(rowId); + let rowId2 = await store2?.insert('test', valueBucket); + expect(1).assertEqual(rowId2); + console.log(TAG + "************* testRdbStorePerfStat_0016 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0001 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0017', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0017 start *************"); + let store2: relationalStore.RdbStore | undefined = undefined; + let STORE_CONFIG2: relationalStore.StoreConfig = { + name: 'test2.db', + securityLevel: relationalStore.SecurityLevel.S1 + }; + let timerId = -1; + let observer1 = async (sqlExecutionInfo : relationalStore.SqlExecutionInfo) => { + if (timerId = -1) { + clearTimeout(timerId); + expect().assertFail(); + } + }; + rdbStore?.on('perfStat',observer1) + store2 = await relationalStore.getRdbStore(context, STORE_CONFIG2) + timerId = setTimeout(done, 2000); + console.log(TAG + "************* testRdbStorePerfStat_0017 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0001 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0018', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0018 start *************"); + let observer1 = async (sqlExecutionInfo : relationalStore.SqlExecutionInfo) => { + expect(4).assertEqual(sqlExecutionInfo.sql.length); + done() + }; + rdbStore?.on('perfStat',observer1) + + const rdbTrans = await rdbStore?.createTransaction(); + const valueBucket1: relationalStore.ValuesBucket = { + 'name': 'zhangsan', + 'age': 18, + 'salary': 25000, + }; + await rdbTrans?.insert('test', valueBucket1) + await rdbTrans?.insert("test", valueBucket1) + await rdbTrans?.commit(); + console.log(TAG + "************* testRdbStorePerfStat_0018 end *************"); + }) + + /** + * @tc.name Normal case for perfStat update data execution time + * @tc.number testRdbStorePerfStat_0019 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0019', 0, async () => { + console.log(TAG + "************* testRdbStorePerfStat_0019 start *************"); + let observer = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + + rdbStore?.close(); + try { + rdbStore?.on('perfStat', observer); + } catch (err) { + expect(err.code).assertEqual("14800014"); + } + console.log(TAG + "************* testRdbStorePerfStat_0019 end *************"); + }) + + /** + * @tc.name Normal case for perfStat batchInsert data execution time + * @tc.number testRdbStorePerfStat_0020 + * @tc.desc 1. Register callback for perfStat + * 2. Update data + */ + it('testRdbStorePerfStat_0020', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0020 start *************"); + let observer = (sqlExecutionInfo : relationalStore.SqlExecutionInfo) => { + expect(1).assertEqual(sqlExecutionInfo.sql.length); + done() + }; + rdbStore?.on('perfStat', observer); + const valueBucket1: relationalStore.ValuesBucket = { + 'id': 1, + 'name': 'zhangsan', + 'age': 13, + }; + const valueBucket2: relationalStore.ValuesBucket = { + 'id': 2, + 'name': 'zhangsan', + 'age': 13, + }; + const valueBucket3: relationalStore.ValuesBucket = { + 'id': 5, + 'name': 'zhangsan', + 'age': 13, + }; + let valueBuckets = new Array(valueBucket1, valueBucket2, valueBucket3); + await rdbStore?.batchInsert("test", valueBuckets); + console.log(TAG + "************* testRdbStorePerfStat_0020 end *************"); + }) + + /** + * @tc.name Normal case for perfStat batchInsert data execution time + * @tc.number testRdbStorePerfStat_0021 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0021', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0021 start *************"); + let observer = (sqlExecutionInfo : relationalStore.SqlExecutionInfo) => { + expect('INSERT OR REPLACE INTO test (age,id,name) VALUES (?,?,?),...,3').assertEqual(sqlExecutionInfo.sql[1]); + expect(3).assertEqual(sqlExecutionInfo.sql.length); + done() + }; + rdbStore?.on('perfStat', observer); + const rdbTrans = await rdbStore?.createTransaction(); + const valueBucket1: relationalStore.ValuesBucket = { + 'id': 1, + 'name': 'zhangsan', + 'age': 13, + }; + const valueBucket2: relationalStore.ValuesBucket = { + 'id': 2, + 'name': 'zhangsan', + 'age': 13, + }; + const valueBucket3: relationalStore.ValuesBucket = { + 'id': 5, + 'name': 'zhangsan', + 'age': 13, + }; + let valueBuckets = new Array(valueBucket1, valueBucket2, valueBucket3); + await rdbTrans?.batchInsert("test", valueBuckets); + await rdbTrans?.commit(); + console.log(TAG + "************* testRdbStorePerfStat_0021 end *************"); + }) + + /** + * @tc.name Normal case for perfStat batchInsert data execution time + * @tc.number testRdbStorePerfStat_0022 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0022', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0022 start *************"); + let observer = (sqlExecutionInfo : relationalStore.SqlExecutionInfo) => { + expect('INSERT OR REPLACE INTO test (age,name) VALUES (?,?),...,30000').assertEqual(sqlExecutionInfo.sql[1]); + expect(3).assertEqual(sqlExecutionInfo.sql.length); + done() + }; + rdbStore?.on('perfStat', observer); + const rdbTrans = await rdbStore?.createTransaction(); + + let valueBuckets : relationalStore.ValuesBucket[] = new Array(); + const valueBucket1: relationalStore.ValuesBucket = { + 'name': 'zhangsan', + 'age': 13, + }; + for (let i = 0; i < 30000; i++) { + valueBuckets.push(valueBucket1) + } + await rdbTrans?.batchInsert("test", valueBuckets); + await rdbTrans?.commit(); + console.log(TAG + "************* testRdbStorePerfStat_0022 end *************"); + }) + + /** + * @tc.name Abnormal case for perfStat + * @tc.number testRdbStorePerfStat_0023 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0023', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0023 start *************"); + if (!relationalStore.isVectorSupported()) { + done() + return + } + let observer = (sqlExecutionInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + let STORE_CONFIG1: relationalStore.StoreConfig = { + name: 'rdbStore2.db', + securityLevel: relationalStore.SecurityLevel.S1, + vector: true, + }; + let rdbStore1 = await relationalStore.getRdbStore(context, STORE_CONFIG1) + try{ + rdbStore1.on('perfStat', observer); + expect().assertFail(); + done(); + } catch (err){ + expect(err.code).assertEqual("801"); + done() + } + console.log(TAG + "************* testRdbStorePerfStat_0023 end *************"); + }) + + /** + * @tc.name Abnormal case for perfStat + * @tc.number testRdbStorePerfStat_0024 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0024', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0024 start *************"); + if (!relationalStore.isVectorSupported()) { + done() + return + } + let observer = (sqlExecutionInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + let STORE_CONFIG1: relationalStore.StoreConfig = { + name: 'rdbStore2.db', + securityLevel: relationalStore.SecurityLevel.S1, + vector: true, + }; + let rdbStore1 = await relationalStore.getRdbStore(context, STORE_CONFIG1) + try{ + rdbStore1.off('perfStat', observer); + expect().assertFail(); + done(); + } catch (err){ + expect(err.code).assertEqual("801"); + done() + } + console.log(TAG + "************* testRdbStorePerfStat_0024 end *************"); + }) + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstorePredicatesEts.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstorePredicatesEts.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..dab7011c13df60c9f02d6c0ce2a78433031b42fc --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstorePredicatesEts.test.ets @@ -0,0 +1,369 @@ +/* + * Copyright (C) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; +import relationalStore from '@ohos.data.relationalStore' +const TAG = "[STAGE_RELATIONAL_STORE_JSKITS_TEST]"; +const STORE_CONFIG: relationalStore.StoreConfig = { + name: "Predicates.db", + securityLevel: relationalStore.SecurityLevel.S1, +}; +const SQL_CREATE_TABLE = + 'CREATE TABLE IF NOT EXISTS orders (id INTEGER PRIMARY KEY AUTOINCREMENT, customer_id INTEGER, amount INTEGER)'; +let rdbStore: relationalStore.RdbStore | undefined = undefined; + +async function preData():Promise +{ + const INSERT_SQL = + 'INSERT INTO orders (customer_id, amount) VALUES' + + '(1, 1500), (1, 2000), (1, 3000), (2, 800), (2, 1200), (3, 1500), (3, 2000), (3, 2500), (3, 1000)'; + await rdbStore?.executeSql(INSERT_SQL); +} + +export default function RdbPredicatesEtsTest() { + describe('rdbPredicatesEtsTest', () => { + beforeAll(async () => { + rdbStore = await relationalStore.getRdbStore(globalThis.abilityContext, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + console.info(TAG + 'beforeAll'); + }); + beforeEach(async () => { + await rdbStore?.executeSql(SQL_CREATE_TABLE); + await preData(); + console.info(TAG + 'beforeEach'); + }); + afterEach(async () => { + await rdbStore?.executeSql('DROP TABLE IF EXISTS orders'); + console.info(TAG + 'afterEach'); + }); + afterAll(async () => { + rdbStore = undefined; + await relationalStore.deleteRdbStore(globalThis.abilityContext, "Predicates.db"); + console.info(TAG + 'afterAll'); + }); + + console.log(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_001 + * @tc.name Verify no placeholders and pass in empty args in the scenario + * @tc.desc 1.Execute having("total > 5000 AND count >= 3", []) + * 2.Query data + */ + it('testHaving001', 0, async () => { + console.log(TAG + "************* testHaving001 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having("total > 5000 AND count >= 3", []); + let resultSet:relationalStore.ResultSet = + rdbStore?.querySync(predicates, ["customer_id", "COUNT(*) AS count", "SUM(amount) AS total"]) as relationalStore.ResultSet; + console.info(TAG + 'testHaving001 rowCount ' + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToNextRow()); + let row:relationalStore.ValuesBucket = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving001 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(1); + expect(row.total).assertEqual(6500); + expect(true).assertEqual(resultSet.goToNextRow()); + row = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving001 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(3); + expect(row.total).assertEqual(7000); + resultSet.close(); + console.log(TAG + " testHaving001 having success"); + } catch (e) { + console.error(TAG + " testHaving001 having failed" + e); + expect(true).assertFail(); + } + console.log(TAG + "************* testHaving001 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_002 + * @tc.name Verify scenarios without placeholders and without passing args + * @tc.desc 1.Execute having("total > 5000 AND count >= 3") + * 2.Query data + */ + it('testHaving002', 0, async () => { + console.log(TAG + "************* testHaving002 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having("total > 5000 AND count >= 3"); + let resultSet:relationalStore.ResultSet = + rdbStore?.querySync(predicates, ["customer_id", "COUNT(*) AS count", "SUM(amount) AS total"]) as relationalStore.ResultSet; + console.info(TAG + 'testHaving002 rowCount ' + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToNextRow()); + let row:relationalStore.ValuesBucket = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving002 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(1); + expect(row.total).assertEqual(6500); + expect(true).assertEqual(resultSet.goToNextRow()); + row = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving002 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(3); + expect(row.total).assertEqual(7000); + resultSet.close(); + console.log(TAG + " testHaving002 having success"); + } catch (e) { + console.error(TAG + " testHaving002 having failed" + e); + expect(true).assertFail(); + } + console.log(TAG + "************* testHaving002 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_003 + * @tc.name Verify the absence of placeholders and null passing scenarios for args + * @tc.desc 1.Execute having("SALARY = 1.2", null) + * 2.Query data + */ + it('testHaving003', 0, async () => { + console.log(TAG + "************* testHaving003 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having("total > 5000 AND count >= 3", null); + let resultSet:relationalStore.ResultSet = + rdbStore?.querySync(predicates, ["customer_id", "COUNT(*) AS count", "SUM(amount) AS total"]) as relationalStore.ResultSet; + console.info(TAG + 'testHaving003 rowCount ' + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToNextRow()); + let row:relationalStore.ValuesBucket = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving003 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(1); + expect(row.total).assertEqual(6500); + expect(true).assertEqual(resultSet.goToNextRow()); + row = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving003 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(3); + expect(row.total).assertEqual(7000); + resultSet.close(); + console.log(TAG + " testHaving003 having success"); + } catch (e) { + console.error(TAG + " testHaving003 having failed" + e); + expect(true).assertFail(); + } + console.log(TAG + "************* testHaving001 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_004 + * @tc.name Verify the absence of placeholders and undefined passing scenarios for args + * @tc.desc 1.Execute having("SALARY = 1.2", undefined) + * 2.Query data + */ + it('testHaving004', 0, async () => { + console.log(TAG + "************* testHaving001 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having("total > 5000 AND count >= 3", undefined); + let resultSet:relationalStore.ResultSet = + rdbStore?.querySync(predicates, ["customer_id", "COUNT(*) AS count", "SUM(amount) AS total"]) as relationalStore.ResultSet; + console.info(TAG + 'testHaving004 rowCount ' + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToNextRow()); + let row:relationalStore.ValuesBucket = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving004 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(1); + expect(row.total).assertEqual(6500); + expect(true).assertEqual(resultSet.goToNextRow()); + row = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving004 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(3); + expect(row.total).assertEqual(7000); + resultSet.close(); + console.log(TAG + " testHaving004 having success"); + } catch (e) { + console.error(TAG + " testHaving004 having failed" + e); + expect(true).assertFail(); + } + console.log(TAG + "************* testHaving004 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_005 + * @tc.name Normal test case for predicate, testing 'having' passing in null condition + * @tc.desc 1.Execute having("") + * 2.Query data + */ + it('testHaving005', 0, async () => { + console.log(TAG + "************* testHaving005 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having(""); + console.log(TAG + " testHaving005 having success"); + expect(true).assertFail(); + } catch (e) { + console.error(TAG + " testHaving005 having failed" + e); + expect(e.code == 14800001).assertTrue(); + } + console.log(TAG + "************* testHaving005 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_006 + * @tc.name Test conditions for passing in illegal SQL + * @tc.desc 1.Execute having("SALARY == 1.2") + * 2.Query data + */ + it('testHaving006', 0, async () => { + console.log(TAG + "************* testHaving006 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having("SALARY == 1.2"); + let resultSet:relationalStore.ResultSet = rdbStore?.querySync(predicates) as relationalStore.ResultSet; + expect(false).assertEqual(resultSet.goToFirstRow()); + resultSet.getRow(); + console.log(TAG + " testHaving006 having success"); + resultSet.close(); + expect(true).assertFail(); + } catch (e) { + console.error(TAG + " testHaving006 having failed. " + e.msg + e.code); + expect(e.code == 14800021).assertTrue(); + } + console.log(TAG + "************* testHaving006 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_007 + * @tc.name When there are placeholders in the test condition statement, passing in an ARG that does not match the + * number of placeholders. + * @tc.desc 1.Execute having(total > ? AND count >= ?", [5000]) + * 2.Query data + */ + it('testHaving007', 0, async () => { + console.log(TAG + "************* testHaving007 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having("total > ? AND count >= ?"); + let resultSet:relationalStore.ResultSet = + await rdbStore?.querySync(predicates, ["customer_id", "COUNT(*) AS count", "SUM(amount) AS total"]) as relationalStore.ResultSet; + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + console.log(TAG + " testHaving007 having success"); + } catch (e) { + console.error(TAG + " testHaving007 having failed " + e); + expect(true).assertFail(); + } + console.log(TAG + "************* testHaving007 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_008 + * @tc.name Call 'having' when 'group by' is missing. + * @tc.desc Execute having(total > ? AND count >= ?", [5000, 3]) + */ + it('testHaving008', 0, async () => { + console.log(TAG + "************* testHaving008 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.having("total > ? AND count >= ?", [5000, 3]); + console.log(TAG + " testHaving008 having success"); + expect(true).assertFail(); + } catch (e) { + console.error(TAG + " testHaving008 having failed" + e); + expect(e.code == 14800001).assertTrue(); + } + console.log(TAG + "************* testHaving008 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_009 + * @tc.name Test using placeholder scenarios. + * @tc.desc 1.Execute having(total > ? AND count >= ?", [5000, 3]) + * 2.Query data + */ + it('testHaving009', 0, async () => { + console.log(TAG + "************* testHaving009 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having("total > ? AND count >= ?", [5000, 3]); + let resultSet:relationalStore.ResultSet = + rdbStore?.querySync(predicates, ["customer_id", "COUNT(*) AS count", "SUM(amount) AS total"]) as relationalStore.ResultSet; + console.info(TAG + 'testHaving009 rowCount ' + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToNextRow()); + let row:relationalStore.ValuesBucket = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving009 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(1); + expect(row.total).assertEqual(6500); + expect(true).assertEqual(resultSet.goToNextRow()); + row = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving009 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(3); + expect(row.total).assertEqual(7000); + resultSet.close(); + console.log(TAG + " testHaving009 having success"); + } catch (e) { + console.error(TAG + " testHaving009 having failed" + e); + expect(true).assertFail(); + } + console.log(TAG + "************* testHaving009 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_010 + * @tc.name Test using placeholder scenarios. + * @tc.desc Multi threaded testing + */ + it('testHaving010', 0, async (done:Function) => { + console.log(TAG + "************* testHaving010 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having("total > ? AND count >= ?", [5000, 3]); + let count:number = 200; + for (let i = 0; i <= count; ++i) { + rdbStore?.query(predicates, ["customer_id", "COUNT(*) AS count", "SUM(amount) AS total"]) + .then((resultSet:relationalStore.ResultSet)=>{ + expect(2).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToNextRow()); + let row:relationalStore.ValuesBucket = resultSet.getRow() as relationalStore.ValuesBucket; + expect(row.customer_id).assertEqual(1); + expect(row.total).assertEqual(6500); + expect(true).assertEqual(resultSet.goToNextRow()); + row = resultSet.getRow() as relationalStore.ValuesBucket; + expect(row.customer_id).assertEqual(3); + expect(row.total).assertEqual(7000); + resultSet.close(); + count--; + if (count == 0) { + done(); + } + }).catch((e:BusinessError)=>{ + console.error(TAG + " testHaving010 having failed query: " + e); + done(); + expect(true).assertFail(); + }); + } + console.log(TAG + " testHaving010 having success"); + } catch (e) { + console.error(TAG + " testHaving010 having failed: " + e); + done(); + expect(true).assertFail(); + } + console.log(TAG + "************* testHaving010 end *************"); + }); + + console.log(TAG + "*************Unit Test End*************"); + }) +} diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreRekeyEts.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreRekeyEts.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..d67650b38e5a8451482300fd685e2773824d8246 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreRekeyEts.test.ets @@ -0,0 +1,862 @@ +/* + * Copyright (C) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; +import data_relationalStore from '@ohos.data.relationalStore' + +const TAG = "[RDB_REKEY_TEST]"; +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; + +export default function RdbstoreRekeysEtsTest() { + describe('rdbstoreRekeyEtsTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll'); + }); + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + }); + afterEach(async () => { + console.info(TAG + 'afterEach'); + }); + afterAll(async () => { + console.info(TAG + 'afterAll'); + }); + + console.log(TAG + "*************Unit Test Begin*************"); + /** + * @tc.number testRekey + * @tc.name testRekey0001 + * @tc.desc invalid parameters test + */ + it('testRekey0001', 0, async () => { + console.log(TAG + "************* testRekey0001 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testCrypt0001.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + iterationCount: -1, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect("14800001").assertEqual(e.code); + console.log(TAG + "************* testRekey0001 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0002 + * @tc.desc invalid parameters test + */ + it('testRekey0002', 0, async () => { + console.log(TAG + "************* testRekey0002 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0002.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + encryptionAlgo: -1, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect("14800001").assertEqual(e.code); + console.log(TAG + "************* testRekey0002 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0003 + * @tc.desc invalid parameters test + */ + it('testRekey0003', 0, async () => { + console.log(TAG + "************* testRekey0003 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0003.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + hmacAlgo: -1, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect("14800001").assertEqual(e.code); + console.log(TAG + "************* testRekey0003 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0004 + * @tc.desc invalid parameters test + */ + it('testRekey0004', 0, async () => { + console.log(TAG + "************* testRekey0004 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0004.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + kdfAlgo: -1, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect("14800001").assertEqual(e.code); + console.log(TAG + "************* testRekey0004 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0005 + * @tc.desc invalid parameters test + */ + it('testRekey0005', 0, async () => { + console.log(TAG + "************* testRekey0005 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0005.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + cryptoPageSize: -1, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect("14800001").assertEqual(e.code); + console.log(TAG + "************* testRekey0005 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0006 + * @tc.desc non-encrypted database rekey test + */ + it('testRekey0006', 0, async () => { + console.log(TAG + "************* testRekey0006 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0006.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0006 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0007 + * @tc.desc exception iterationCount test + */ + it('testRekey0007', 0, async () => { + console.log(TAG + "************* testRekey0007 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0007.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + iterationCount: 500, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0007 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0008 + * @tc.desc exception encryptionAlgo test + */ + it('testRekey0008', 0, async () => { + console.log(TAG + "************* testRekey0008 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0008.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + encryptionAlgo: 1, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0008 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0009 + * @tc.desc exception hmacAlgo test + */ + it('testRekey0009', 0, async () => { + console.log(TAG + "************* testRekey0009 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0009.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + hmacAlgo: 2, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0009 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0010 + * @tc.desc exception kdfAlgo test + */ + it('testRekey0010', 0, async () => { + console.log(TAG + "************* testRekey0010 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0010.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + kdfAlgo: 2, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0010 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0011 + * @tc.desc exception cryptoPageSize test + */ + it('testRekey0011', 0, async () => { + console.log(TAG + "************* testRekey0011 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0011.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + cryptoPageSize: 2048, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0011 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0012 + * @tc.desc custom encrypt rekey test + */ + it('testRekey0012', 0, async () => { + console.log(TAG + "************* testRekey0012 start *************"); + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([1, 2, 3, 4, 5, 6]), + }; + + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0012.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + cryptoParam: cryptoParam, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + await rdbStore.executeSql(CREATE_TABLE_TEST); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([6, 5, 4, 3, 2, 1]), + }; + + try { + await rdbStore.rekey(cryptoParam1); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: data_relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket); + const valueBucket1: data_relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 19, + "salary": 200.5, + "blobType": u8, + } + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("NAME", "zhangsan"); + await rdbStore.update(valueBucket1, predicates) + await rdbStore.delete(predicates); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(false).assertTrue(); + console.log(TAG + "************* testRekey0012 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0013 + * @tc.desc custom encrypt rekey test + */ + it('testRekey0013', 0, async () => { + console.log(TAG + "************* testRekey0013 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0013.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([6, 5, 4, 3, 2, 1]), + }; + + try { + await rdbStore.rekey(cryptoParam1); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0013 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0014 + * @tc.desc rekey test + */ + it('testRekey0014', 0, async () => { + console.log(TAG + "************* testRekey0014 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0014.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + await rdbStore.executeSql(CREATE_TABLE_TEST); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + }; + + try { + await rdbStore.rekey(cryptoParam1); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: data_relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket); + const valueBucket1: data_relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 19, + "salary": 200.5, + "blobType": u8, + } + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("NAME", "zhangsan"); + await rdbStore.update(valueBucket1, predicates) + await rdbStore.delete(predicates); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(false).assertTrue(); + console.log(TAG + "************* testRekey0014 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0015 + * @tc.desc rekey test + */ + it('testRekey0015', 0, async () => { + console.log(TAG + "************* testRekey0015 start *************"); + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([6, 5, 4, 3, 2, 1]), + }; + + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0015.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + cryptoParam: cryptoParam, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + }; + + try { + await rdbStore.rekey(cryptoParam1); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0015 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0016 + * @tc.desc transaction rekey test + */ + it('testRekey0016', 0, async () => { + console.log(TAG + "************* testRekey0016 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0016.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let SQL_CREATE_TABLE = + 'CREATE TABLE IF NOT EXISTS employee (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER)'; + await rdbStore.executeSql(SQL_CREATE_TABLE); + + let transaction = await rdbStore?.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + }; + + try { + const valueBucket: data_relationalStore.ValuesBucket = { + "id": 1, + "name": "lisi", + "age": 18, + } + await transaction.insert("employee", valueBucket) + await rdbStore.rekey(cryptoParam1); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(14800015)); + console.log(TAG + "************* testRekey0016 end *************"); + } + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0017 + * @tc.desc transaction rekey test + */ + it('testRekey0017', 0, async () => { + console.log(TAG + "************* testRekey0017 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0017.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let SQL_CREATE_TABLE = + 'CREATE TABLE IF NOT EXISTS employee (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER)'; + await rdbStore.executeSql(SQL_CREATE_TABLE); + + let transaction = await rdbStore?.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + }; + + try { + const valueBucket: data_relationalStore.ValuesBucket = { + "id": 1, + "name": "lisi", + "age": 18, + } + await transaction.insert("employee", valueBucket) + await rdbStore.rekey(cryptoParam1); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(14800015)); + console.log(TAG + "************* testRekey0017 end *************"); + } + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0018 + * @tc.desc other parameters rekey test + */ + it('testRekey0018', 0, async () => { + console.log(TAG + "************* testRekey0018 start *************"); + let storeConfig : data_relationalStore.StoreConfig= { + name: "testRekey0018.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + try { + await rdbStore.rekey(undefined); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(false).assertTrue(); + console.log(TAG + "************* testRekey0018 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0019 + * @tc.desc other parameters rekey test + */ + it('testRekey0019', 0, async () => { + console.log(TAG + "************* testRekey0019 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0019.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + try { + await rdbStore.rekey(null); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(false).assertTrue(); + console.log(TAG + "************* testRekey0019 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0020 + * @tc.desc other parameters rekey test + */ + it('testRekey0020', 0, async () => { + console.log(TAG + "************* testRekey0020 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0020.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + try { + await rdbStore.rekey(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(false).assertTrue(); + console.log(TAG + "************* testRekey0020 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0021 + * @tc.desc other parameters rekey test + */ + it('testRekey0021', 0, async () => { + console.log(TAG + "************* testRekey0021 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0021.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + await rdbStore.executeSql(CREATE_TABLE_TEST); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + }; + + try { + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: data_relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket); + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "zhangsan"); + const resultSet = await rdbStore.query(predicates); + resultSet.goToNextRow(); + await rdbStore.rekey(cryptoParam1); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(14800015)); + console.log(TAG + "************* testRekey0021 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0022 + * @tc.desc exception iterationCount test + */ + it('testRekey0022', 0, async () => { + console.log(TAG + "************* testRekey0022 start *************"); + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([6, 5, 4, 3, 2, 1]), + }; + + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0022.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + cryptoParam: cryptoParam + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([1, 2, 3, 4, 5, 6]), + iterationCount: 500, + }; + + try { + await rdbStore.rekey(cryptoParam1); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0022 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0023 + * @tc.desc exception encryptionAlgo test + */ + it('testRekey0023', 0, async () => { + console.log(TAG + "************* testRekey0023 start *************"); + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([6, 5, 4, 3, 2, 1]), + }; + + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0023.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + cryptoParam: cryptoParam + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([1, 2, 3, 4, 5, 6]), + encryptionAlgo: 1, + }; + + try { + await rdbStore.rekey(cryptoParam1); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0023 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0024 + * @tc.desc exception hmacAlgo test + */ + it('testRekey0024', 0, async () => { + console.log(TAG + "************* testRekey0024 start *************"); + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([6, 5, 4, 3, 2, 1]), + }; + + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0024.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + cryptoParam: cryptoParam + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([1, 2, 3, 4, 5, 6]), + hmacAlgo: 2, + }; + + try { + await rdbStore.rekey(cryptoParam1); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0024 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0025 + * @tc.desc exception kdfAlgo test + */ + it('testRekey0025', 0, async () => { + console.log(TAG + "************* testRekey0025 start *************"); + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([6, 5, 4, 3, 2, 1]), + }; + + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0025.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + cryptoParam: cryptoParam + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([1, 2, 3, 4, 5, 6]), + kdfAlgo: 2, + }; + + try { + await rdbStore.rekey(cryptoParam1); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0025 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreSetLocaleEts.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreSetLocaleEts.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..ef90ae6dacbbe27cac5ada840f7e404033718e04 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreSetLocaleEts.test.ets @@ -0,0 +1,226 @@ + +/* + * Copyright (C) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level, Size, TestType } from "@ohos/hypium"; +import relationalStore from '@ohos.data.relationalStore'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; + + +const TAG = "[STAGE_RELATIONAL_STORE_JSKITS_TEST]"; +let rdbStore:relationalStore.RdbStore | undefined = undefined; + +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL)"; + +const STORE_CONFIG: relationalStore.StoreConfig = { + name: "rdbStore.db", + securityLevel: relationalStore.SecurityLevel.S1, +} + +const delegator = AbilityDelegatorRegistry.getAbilityDelegator(); +const context = delegator.getAppContext().getApplicationContext(); + + +export default function SetLocaleEtsTest() { + describe('SetLocaleEtsTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll') + }) + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore?.executeSql(CREATE_TABLE_TEST); + const valueBucket: relationalStore.ValuesBucket = { + 'name': '张三', + 'age': 18, + 'salary': 25000, + }; + const valueBucket1: relationalStore.ValuesBucket = { + 'name': '李四', + 'age': 18, + 'salary': 25000, + }; + const valueBucket2: relationalStore.ValuesBucket = { + 'name': '王五', + 'age': 18, + 'salary': 25000, + }; + await rdbStore?.insert('test', valueBucket); + await rdbStore?.insert('test', valueBucket1); + await rdbStore?.insert('test', valueBucket2); + + }) + afterEach(async () => { + console.info(TAG + 'afterEach'); + await relationalStore.deleteRdbStore(context, "rdbStore.db"); + }) + afterAll(async () => { + console.info(TAG + 'afterAll'); + }) + + + /** + * @tc.name Normal case + * @tc.number testRdbStoreSetLocale_0001 + */ + it('testRdbStoreSetLocale_0001', 0, async () => { + console.log(TAG + "************* testRdbStoreSetLocale_0001 start *************"); + try { + await rdbStore?.setLocale("zh"); + let resultSet = await rdbStore?.querySql("select * from test order by name collate LOCALES") + resultSet?.goToNextRow() + + expect('李四').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + resultSet?.goToNextRow() + expect('王五').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + resultSet?.goToNextRow() + expect('张三').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + } catch (e) { + console.error(`message is ${e.message} code ${e.code}`); + expect().assertFail(); + } + console.log(TAG + "************* testRdbStoreSetLocale_0001 end *************"); + }) + + /** + * @tc.name Abnormal case + * @tc.number testRdbStoreSetLocale_0002 + */ + it('testRdbStoreSetLocale_0002', 0, async () => { + console.log(TAG + "************* testRdbStoreSetLocale_0002 start *************"); + try { + await rdbStore?.close(); + await rdbStore?.setLocale("zh"); + } catch (e) { + console.error(`message is ${e.message} code ${e.code}`); + expect(e.code).assertEqual("14800014");; + } + console.log(TAG + "************* testRdbStoreSetLocale_0002 end *************"); + }) + + /** + * @tc.name Abnormal case + * @tc.number testRdbStoreSetLocale_0003 + */ + it('testRdbStoreSetLocale_0003', 0, async () => { + console.log(TAG + "************* testRdbStoreSetLocale_0003 start *************"); + try { + await rdbStore?.setLocale("111"); + } catch (e) { + console.error(`message is ${e.message} code ${e.code}`); + expect(e.code).assertEqual(14800001); + } + console.log(TAG + "************* testRdbStoreSetLocale_0003 end *************"); + }) + + /** + * @tc.name Normal case + * @tc.number testRdbStoreSetLocale_0004 + */ + it('testRdbStoreSetLocale_0004', 0, async () => { + console.log(TAG + "************* testRdbStoreSetLocale_0004 start *************"); + try { + for (let i = 0; i < 10; i++) { + await rdbStore?.querySql("select * from test") + } + await rdbStore?.setLocale("zh"); + let resultSet = await rdbStore?.querySql("select * from test order by name collate LOCALES") + resultSet?.goToNextRow() + + expect('李四').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + resultSet?.goToNextRow() + expect('王五').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + resultSet?.goToNextRow() + expect('张三').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + } catch (e) { + console.error(`message is ${e.message} code ${e.code}`); + expect().assertFail(); + } + console.log(TAG + "************* testRdbStoreSetLocale_0004 end *************"); + }) + + /** + * @tc.name Normal case + * @tc.number testRdbStoreSetLocale_0005 + */ + it('testRdbStoreSetLocale_0005', 0, async () => { + console.log(TAG + "************* testRdbStoreSetLocale_0005 start *************"); + try { + await rdbStore?.setLocale("zh"); + const rdbTrans = await rdbStore?.createTransaction(); + let resultSet = await rdbTrans?.querySql("select * from test order by name collate LOCALES") + console.log(`mmy rowCount ${resultSet?.rowCount}`) + resultSet?.goToNextRow() + expect('李四').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + resultSet?.goToNextRow() + expect('王五').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + resultSet?.goToNextRow() + expect('张三').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + await rdbTrans?.commit(); + } catch (e) { + console.error(`message is ${e.message} code ${e.code}`); + expect().assertFail(); + } + console.log(TAG + "************* testRdbStoreSetLocale_0005 end *************"); + }) + + /** + * @tc.name Abnormal case + * @tc.number testRdbStoreSetLocale_0006 + */ + it('testRdbStoreSetLocale_0006', 0, async () => { + console.log(TAG + "************* testRdbStoreSetLocale_0006 start *************"); + try { + await rdbStore?.setLocale(""); + } catch (e) { + console.error(`message is ${e.message} code ${e.code}`); + expect(e.code).assertEqual("14800001"); + } + console.log(TAG + "************* testRdbStoreSetLocale_0006 end *************"); + }) + + /** + * @tc.name Abnormal case + * @tc.number testRdbStoreSetLocale_0007 + */ + it('testRdbStoreSetLocale_0007', 0, async () => { + console.log(TAG + "************* testRdbStoreSetLocale_0007 start *************"); + try { + await rdbStore?.setLocale(null); + } catch (e) { + console.error(`message is ${e.message} code ${e.code}`); + expect(e.code).assertEqual("401"); + } + console.log(TAG + "************* testRdbStoreSetLocale_0007 end *************"); + }) + + /** + * @tc.name Abnormal case + * @tc.number testRdbStoreSetLocale_0008 + */ + it('testRdbStoreSetLocale_0008', 0, async () => { + console.log(TAG + "************* testRdbStoreSetLocale_0008 start *************"); + try { + await rdbStore?.setLocale(undefined); + } catch (e) { + console.error(`message is ${e.message} code ${e.code}`); + expect(e.code).assertEqual("401"); + } + console.log(TAG + "************* testRdbStoreSetLocale_0008 end *************"); + }) + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreTransactionJsunit.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreTransactionJsunit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..b395ccb67136b43a0273f793a52e471ab79356d9 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreTransactionJsunit.test.ets @@ -0,0 +1,339 @@ +/* + * 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. + */ + +// @ts-nocheck +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' +import data_relationalStore from '@ohos.data.relationalStore' +var context = globalThis.abilityContext; + +const TAG = "[RELATIONAL_STORE_JSKITS_TEST]" +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; + +const STORE_CONFIG = { + name: "TransactionInsertTest.db", + securityLevel: data_relationalStore.SecurityLevel.S1, +} + +var rdbStore = undefined; + +export default function () { + describe('rdbStoreTransactionTest', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll') + rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + }) + + beforeEach(async function () { + console.info(TAG + 'beforeEach') + + }) + + afterEach(async function () { + console.info(TAG + 'afterEach') + await rdbStore.executeSql("DELETE FROM test"); + }) + + afterAll(async function () { + console.info(TAG + 'afterAll') + rdbStore = null + await data_relationalStore.deleteRdbStore(context, "TransactionInsertTest.db"); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.number testRdbTransactionInsert0001 + * @tc.name Normal test case of transactions, insert a row of data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute commit + * 4.Query data + */ + it('testRdbTransactionInsert0001', 0, async function (done) { + console.log(TAG + "************* testRdbStoreInsert0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + try { + rdbStore.beginTransaction() + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket) + + rdbStore.commit() + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates) + console.log(TAG + "testRdbTransactionInsert0001 result count " + resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) + resultSet.close() + } catch (e) { + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testRdbTransactionInsert0001 failed"); + } + done() + console.log(TAG + "************* testRdbTransactionInsert0001 end *************"); + }) + + /** + * @tc.number testRdbTransactionInsert0002 + * @tc.name Normal test case of transaction, insert three rows of data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute commit + * 4.Query data + */ + it('testRdbTransactionInsert0002', 0, async function (done) { + console.log(TAG + "************* testRdbStoreInsert0002 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + try { + rdbStore.beginTransaction() + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket) + + const valueBucket1 = { + "name": "zhangsan", + "age": 20, + "salary": 9.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket1) + + + const valueBucket2 = { + "name": "wangwu", + "age": 16, + "salary": 99, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket2) + + rdbStore.commit() + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates) + expect(3).assertEqual(resultSet.rowCount) + resultSet.close() + } catch (e) { + expect(null).assertFail() + console.log(TAG + "testRdbTransactionInsert0002 failed"); + } + done() + console.log(TAG + "************* testRdbTransactionInsert0002 end *************"); + }) + + + /** + * @tc.number testRdbTransactionInsert0003 + * @tc.name Normal test case of transaction, query data before commit + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Query data (expect 0 row) + * 4.Insert data + * 5.Execute commit + */ + it('testRdbTransactionInsert0003', 0, async function (done) { + console.log(TAG + "************* testRdbTransactionInsert0003 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + try { + rdbStore.beginTransaction() + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket) + + const valueBucket1 = { + "name": "zhangsan", + "age": 20, + "salary": 9.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket1) + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates) + expect(0).assertEqual(resultSet.rowCount) + resultSet.close() + const valueBucket2 = { + "name": "wangwu", + "age": 16, + "salary": 99, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket2) + + rdbStore.commit() + } catch (e) { + expect(null).assertFail() + console.log(TAG + "testRdbTransactionInsert0003 failed"); + } + done() + console.log(TAG + "************* testRdbTransactionInsert0003 end *************"); + }) + + /** + * @tc.number testRdbTransactionInsert0004 + * @tc.name Abnormal test case of transaction insert, if catch exception then rollback + * @tc.desc 1.Execute beginTransaction + * 2.Insert data (primary key conflict) + * 3.Execute rollBack + * 4.Query data + */ + it('testRdbTransactionRollBack0001', 0, async function (done) { + console.log(TAG + "************* testRdbTransactionRollBack0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + try { + rdbStore.beginTransaction() + const valueBucket = { + "id": 1, + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket) + await rdbStore.insert("test", valueBucket) + + rdbStore.commit() + } catch (e) { + rdbStore.rollBack() + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates) + console.log(TAG + "testRdbTransactionRollBack0001 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount) + resultSet.close() + } + done() + console.log(TAG + "************* testRdbTransactionRollBack0001 end *************"); + }) + + /** + * @tc.number testRdbTransactionInsert0005 + * @tc.name Normal test case of transaction, begin transactions within a transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute beginTransaction + * 4.Insert data + * 5.Execute rollBack + * 6.Insert data + * 7.Execute commit + * 8.Query data + */ + it('testRdbTransactionMulti0003', 0, async function (done) { + console.log(TAG + "************* testRdbTransactionMulti0003 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + try { + rdbStore.beginTransaction() + const valueBucket = { + "id": 1, + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket); + + rdbStore.beginTransaction() + const valueBucket1 = { + "name": "zhangsan", + "age": 20, + "salary": 220.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket1) + + rdbStore.rollBack() + + await rdbStore.insert("test", valueBucket) + rdbStore.commit() + + let predicates = new data_relationalStore.RdbPredicates("test"); + let ret = await rdbStore.query(predicates) + expect(1).assertEqual(ret.rowCount) + ret.close() + } catch (e) { + rdbStore.rollBack() + console.log(TAG + "testRdbTransactionMulti0003 rollback ***** "); + } + done() + console.log(TAG + "************* testRdbTransactionMulti0003 end *************"); + }) + + /** + * @tc.number testRdbTransactionSetVersion001 + * @tc.name Normal test case of transaction, GetVersion before transaction submission + * @tc.desc 1.Execute beginTransaction + * 2.setVersion + * 3.GetVersion + * 4.commit + */ + it('testRdbTransactionSetVersion001', 0, async function (done) { + console.log(TAG + "************* testRdbTransactionSetVersion001 start *************"); + try { + rdbStore.beginTransaction() + let version:number = rdbStore.version; + rdbStore.version = version + 1; + expect(rdbStore.version).assertEqual(version + 1); + rdbStore.commit() + } catch (e) { + rdbStore.rollBack(); + expect().assertFail(); + console.log(TAG + "testRdbTransactionSetVersion001 rollback ***** " + e); + } + done() + console.log(TAG + "************* testRdbTransactionSetVersion001 end *************"); + }) + + /** + * @tc.number testRdbTransactionSetVersion002 + * @tc.name Normal test case of transaction, query version after transaction submission + * @tc.desc 1.Execute beginTransaction + * 2.setVersion + * 3.commit + * 4.GetVersion + */ + it('testRdbTransactionSetVersion002', 0, async function (done) { + console.log(TAG + "************* testRdbTransactionSetVersion002 start *************"); + try { + rdbStore.beginTransaction(); + let version:number = rdbStore.version; + rdbStore.version = version + 1; + rdbStore.commit(); + expect(rdbStore.version).assertEqual(version + 1); + } catch (e) { + rdbStore.rollBack() + expect().assertFail(); + console.log(TAG + "testRdbTransactionSetVersion002 rollback ***** " + e); + } + done() + console.log(TAG + "************* testRdbTransactionSetVersion002 end *************"); + }) + + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RelationalStoreEtsTest.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RelationalStoreEtsTest.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..68a9a2a371c10a6aa318f86dd1ac6ca96a30b95b --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RelationalStoreEtsTest.test.ets @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2025 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. + */ + +// @ts-nocheck +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' +import relationalStore from '@ohos.data.relationalStore' +var context = globalThis.abilityContext; +const TAG = "[ttt]" +const STORE_CONFIG: relationalStore.StoreConfig = { + name: "RdbTest.db", + securityLevel: relationalStore.SecurityLevel.S3 +}; +const CREATE_TABLE_TEST = + "CREATE TABLE IF NOT EXISTS EMPLOYEE (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB, float32 floatvector(128))"; + +let store: relationalStore.RdbStore | undefined = undefined; + +export default function RelationalStoreEtsTest() { + describe('relationalStoreEtsTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll'); + }); + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + try { + store = await relationalStore.getRdbStore(context, STORE_CONFIG) + console.info(TAG + 'Get RdbStore successfully.'); + (store as relationalStore.RdbStore).executeSql(CREATE_TABLE_TEST); + } catch (err) { + console.error(TAG + `Get RdbStore failed, code is ${err.code},message is ${err.message}`); + } + + }); + afterEach(async () => { + console.info(TAG + 'afterEach'); + store = undefined; + await relationalStore.deleteRdbStore(context, "RdbTest.db"); + }); + afterAll(async () => { + console.info(TAG + 'afterAll'); + }); + console.info(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.name testRdbStoreGetvalueEtstest0100 + * @tc.number SUB_DistributedData_RelationalStore_SDK_getValueEtsAPI16Test_0200 + * @tc.desc RelationalStore getValue test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 2 + */ + it('testRdbStoreGetvalueEtstest0100', 0, async (done: Function) => { + console.info(TAG + "************* testRdbStoreGetvalueEtstest0100 start *************"); + let float32Array = new Float32Array(); + const valueBucket: relationalStore.ValuesBucket = { + "name": "zhangsan", + "float32":float32Array, + }; + try { + let rowId = await (store as relationalStore.RdbStore).insert("EMPLOYEE", valueBucket) + console.info(TAG + `Insert is successful, val = ${rowId}`); + let resultSet: relationalStore.ResultSet | undefined = undefined; + let predicates = new relationalStore.RdbPredicates("EMPLOYEE"); + let result = await (store as relationalStore.RdbStore).query(predicates) + resultSet = result; + console.info(TAG + `rowCount = ${resultSet.rowCount}`); + expect((resultSet as relationalStore.ResultSet).goToFirstRow()).assertTrue(); + console.info(TAG + `Index = ${(resultSet as relationalStore.ResultSet).getColumnIndex("float32")}`); + const codes = (resultSet as relationalStore.ResultSet).getValue((resultSet as relationalStore.ResultSet).getColumnIndex("float32")); + console.info(TAG + "codes:" + codes) + expect(codes).assertInstanceOf("Float32Array"); + const row = (resultSet as relationalStore.ResultSet).getRow(); + console.info(TAG + "row.float32:" + JSON.stringify(row.float32)); + expect(row.float32).assertInstanceOf("Float32Array"); + resultSet = undefined; + done() + } catch (err) { + console.error(TAG + `Insert is failed, code is ${err.code},message is ${err.message}`); + expect().assertFail() + } + console.info(TAG + "************* testRdbStoreGetvalueEtstest0100 end *************"); + }); + console.info(TAG + " *************Unit Test End*************"); + }) +} diff --git a/relational_store/test/ets/relational_store/entry/src/main/module.json b/relational_store/test/ets/relational_store/entry/src/main/module.json new file mode 100644 index 0000000000000000000000000000000000000000..ddcf38c515253c81d6b9f045ac3712f424bcf778 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/module.json @@ -0,0 +1,74 @@ +{ + "module": { + "name": "testModule", + "type": "entry", + "srcEntrance": "./ets/Application/AbilityStage.ts", + "description": "$string:testModule_entry_dsc", + "mainElement": "com.example.myapplication.MainAbility", + "deviceTypes": [ + "default", + "tablet", + "2in1", + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "uiSyntax": "ets", + "pages": "$profile:main_pages", + "metadata": [ + { + "name": "ArkTSPartialUpdate", + "value": "false" + }, + { + "name": "MetaData1", + "value": "MetaDataValue", + "resource": "$profile:shortcuts_config" + } + ], + "abilities": [ + { + "name": "com.example.myapplication.MainAbility", + "srcEntrance": "./ets/MainAbility/MainAbility.ts", + "description": "$string:testModule_entry_main", + "icon": "$media:icon", + "label": "$string:entry_label", + "visible": true, + "launchType": "singleton", + "orientation": "portrait", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.GET_BUNDLE_INFO", + "reason": "$string:permission_reason", + "usedScene": { + "abilities": [ + "MainAbility" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.READ_CALENDAR", + "reason": "$string:permission_reason", + "usedScene": { + "abilities": [ + "MainAbility" + ], + "when": "inuse" + } + } + ] + } +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/resources/base/element/string.json b/relational_store/test/ets/relational_store/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..a4e9ba5b8d282aa4e86eb9389bf7c535226fd1c4 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/resources/base/element/string.json @@ -0,0 +1,44 @@ +{ + "string": [ + { + "name": "testModule_entry_dsc", + "value": "i am an entry for testModule" + }, + { + "name": "testModule_entry_main", + "value": "the testModule entry ability" + }, + { + "name": "entry_label", + "value": "ActsContextTest" + }, + { + "name": "form_description", + "value": "my form" + }, + { + "name": "serviceability_description", + "value": "my whether" + }, + { + "name": "description_application", + "value": "demo for test" + }, + { + "name": "app_name", + "value": "Demo" + }, + { + "name": "form_FormAbility_desc", + "value": "form_description" + }, + { + "name": "form_FormAbility_label", + "value": "form_label" + }, + { + "name": "permission_reason", + "value": "Need permission" + } + ] +} diff --git a/relational_store/test/ets/relational_store/entry/src/main/resources/base/media/icon.png b/relational_store/test/ets/relational_store/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..474a55588fd7216113dd42073aadf254d4dba023 Binary files /dev/null and b/relational_store/test/ets/relational_store/entry/src/main/resources/base/media/icon.png differ diff --git a/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/form_config.json b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/form_config.json new file mode 100644 index 0000000000000000000000000000000000000000..1441277b93b418db9ab1064ae0bc28ad9bcd7138 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/form_config.json @@ -0,0 +1,5 @@ +{ + "src": [ + "MainAbility/pages/index/index" + ] +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/form_config1.txt b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/form_config1.txt new file mode 100644 index 0000000000000000000000000000000000000000..2e4f770aa44e67b3132da9aa3fc50497746bb6d3 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/form_config1.txt @@ -0,0 +1 @@ +{"src": ["MainAbility/pages/index/index"]} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/invalid.txt b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/invalid.txt new file mode 100644 index 0000000000000000000000000000000000000000..09c1570004f88bfeff64278cb625045911a912b7 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/invalid.txt @@ -0,0 +1,3 @@ +{ + "src": [MainAbility/pages/index/index"] +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/main_pages.json b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..ceb075cd80946aade673d707aac904fb8998bce9 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "MainAbility/pages/index/index" + ] +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/shortcuts_config.json b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/shortcuts_config.json new file mode 100644 index 0000000000000000000000000000000000000000..ceb075cd80946aade673d707aac904fb8998bce9 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/shortcuts_config.json @@ -0,0 +1,5 @@ +{ + "src": [ + "MainAbility/pages/index/index" + ] +} \ No newline at end of file diff --git a/relational_store/test/js/gdb/unittest/openharmony_sx.p7b b/relational_store/test/ets/relational_store/signature/openharmony_sx.p7b similarity index 50% rename from relational_store/test/js/gdb/unittest/openharmony_sx.p7b rename to relational_store/test/ets/relational_store/signature/openharmony_sx.p7b index 9be1e98fa4c0c28ca997ed660112fa16b194f0f5..2fac054162b97eb332cb3074f30f216db6701d27 100644 Binary files a/relational_store/test/js/gdb/unittest/openharmony_sx.p7b and b/relational_store/test/ets/relational_store/signature/openharmony_sx.p7b differ diff --git a/relational_store/test/js/gdb/performance/src/GdbStorePromisePerf.js b/relational_store/test/js/gdb/performance/src/GdbStorePromisePerf.js deleted file mode 100644 index e77064e74d620d5ce48df0b7a9e548efd1a89a3a..0000000000000000000000000000000000000000 --- a/relational_store/test/js/gdb/performance/src/GdbStorePromisePerf.js +++ /dev/null @@ -1,130 +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. -*/ - -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert } from 'deccjsunit/index'; -import graphStore from '@ohos.data.graphStore'; -import featureAbility from '@ohos.ability.featureAbility'; -import deviceInfo from '@ohos.deviceInfo'; - -const TAG = "[GDBSTORE_PROMISE]"; -const CREATE_GRAPH_TEST = - "CREATE GRAPH test {(person:Person {name STRING, age INT}), (person) -[:FRIEND]-> (person)};"; -const DB_NAME = "gdbStorePromise"; -const STORE_CONFIG = { - name: DB_NAME, - securityLevel: graphStore.SecurityLevel.S1 -} -let context = featureAbility.getContext(); -let store; -const BASE_COUNT = 1000; // loop times -const BASE_LINE_TABLE = 2500; // callback tablet base line -const BASE_LINE_PHONE = 3000; // callback phone base line -const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; - -describe('gdbStorePromisePerf', () => { - beforeAll(async () => { - console.info(TAG + 'beforeAll'); - await graphStore.deleteStore(context, STORE_CONFIG); - store = await graphStore.getStore(context, STORE_CONFIG); - }) - beforeEach(async () => { - console.info(TAG + 'beforeEach'); - await store.write(CREATE_GRAPH_TEST); - }) - afterEach(async () => { - console.info(TAG + 'afterEach'); - await store.write("DROP GRAPH test"); - }) - afterAll(async () => { - console.info(TAG + 'afterAll'); - await store.close(); - await graphStore.deleteStore(context, STORE_CONFIG); - }) - - console.log(TAG + "*************Unit Test Begin*************"); - - it('Perf_Gdb_Write_Promise_001', 0, async () => { - console.info(TAG + "************* testPerfGdbWritePromise001 start *************"); - let averageTime = 0; - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - let INSERT = "INSERT (:Person {name: 'name_" + (i + 1) + "', age:" + (i + 1) + "});"; - await store.write(INSERT); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the write_INSERT_Promise average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - console.info(TAG + "************* testPerfGdbWritePromise001 end *************"); - }) - - it('Perf_Gdb_Write_Promise_002', 0, async () => { - console.info(TAG + "************* testPerfGdbWritePromise002 start *************"); - for (let i = 0; i < BASE_COUNT; i++) { - let INSERT = "INSERT (:Person {name: 'name_" + (i + 1) + "', age:" + (i + 1) + "});"; - await store.write(INSERT); - } - let averageTime = 0; - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - let UPDATE = "MATCH (n:Person {name: 'name_" + (i + 1) + "' }) SET n.age = " + (i + 2) + ";"; - await store.write(UPDATE); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the write_UPDATE_Promise average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - console.info(TAG + "************* testPerfGdbWritePromise002 end *************"); - }) - - it('Perf_Gdb_Write_Promise_003', 0, async () => { - console.info(TAG + "************* testPerfGdbWritePromise003 start *************"); - for (let i = 0; i < BASE_COUNT; i++) { - let INSERT = "INSERT (:Person {name: 'name_" + (i + 1) + "', age:" + (i + 1) + "});"; - await store.write(INSERT); - } - let averageTime = 0; - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - let DELETE = "MATCH (n:Person {name: 'name_" + (i + 1) + "' }) DETACH DELETE n;"; - await store.write(DELETE); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the write_DELETE_Promise average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - console.info(TAG + "************* testPerfGdbWritePromise003 end *************"); - }) - - it('Perf_Gdb_Read_Promise_001', 0, async () => { - console.info(TAG + "************* testPerfGdbReadPromise001 start *************"); - for (let i = 0; i < BASE_COUNT; i++) { - let INSERT = "INSERT (:Person {name: 'name_" + (i + 1) + "', age:" + (i + 1) + "});"; - await store.write(INSERT); - } - let averageTime = 0; - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - let QUERY = "MATCH (n:Person {name: 'name_" + (i + 1) + "' }) RETURN n;"; - await store.read(QUERY); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the read_Query_Vertex_Promise average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - console.info(TAG + "************* testPerfGdbReadPromise001 end *************"); - }) - console.info(TAG + "*************Unit Test End*************") -}) \ No newline at end of file diff --git a/relational_store/test/js/gdb/unittest/config.json b/relational_store/test/js/gdb/unittest/config.json deleted file mode 100644 index ea58402783388eac606d7347d88ebc401476a50d..0000000000000000000000000000000000000000 --- a/relational_store/test/js/gdb/unittest/config.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "app": { - "bundleName": "com.example.myapplication", - "vendor": "example", - "version": { - "code": 1, - "name": "1.0" - }, - "apiVersion": { - "compatible": 4, - "target": 5 - } - }, - "deviceConfig": {}, - "module": { - "package": "com.example.myapplication", - "name": ".MyApplication", - "deviceType": [ - "tablet", - "2in1", - "default", - "phone" - ], - "distro": { - "deliveryWithInstall": true, - "moduleName": "entry", - "moduleType": "entry" - }, - "abilities": [ - { - "visible": true, - "skills": [ - { - "entities": [ - "entity.system.home" - ], - "actions": [ - "action.system.home" - ] - } - ], - "name": "com.example.myapplication.MainAbility", - "icon": "$media:icon", - "description": "$string:mainability_description", - "label": "MyApplication", - "type": "page", - "launchType": "standard" - } - ], - "js": [ - { - "pages": [ - "pages/index/index" - ], - "name": "default", - "window": { - "designWidth": 720, - "autoDesignWidth": false - } - } - ] - } - } - \ No newline at end of file diff --git a/relational_store/test/js/gdb/unittest/src/GdbStoreGdbStoreJsunit.test.js b/relational_store/test/js/gdb/unittest/src/GdbStoreGdbStoreJsunit.test.js deleted file mode 100644 index f6ea11ba9705f08cbed21d7ee51a9884f3286bbb..0000000000000000000000000000000000000000 --- a/relational_store/test/js/gdb/unittest/src/GdbStoreGdbStoreJsunit.test.js +++ /dev/null @@ -1,422 +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. - */ - -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' -import graphStore from '@ohos.data.graphStore' -import ability_featureAbility from '@ohos.ability.featureAbility' - -const TAG = "[GRAPH_STORE_JSKITS_TEST]"; -const context = ability_featureAbility.getContext(); -const CREATE_GRAPH_TEST = "CREATE GRAPH test {(person:Person {name STRING, age INT}), (person) -[:Friend]-> (person)};" -const STORE_CONFIG = { - name: "graphstore", - securityLevel: graphStore.SecurityLevel.S1, -}; - -describe('graphStoreTest', () => { - beforeAll(async () => { - console.info(TAG + 'beforeAll'); - }) - - beforeEach(async () => { - console.info(TAG + 'beforeEach'); - }) - - afterEach(async () => { - console.info(TAG + 'afterEach'); - await graphStore.deleteStore(context, STORE_CONFIG); - }) - - afterAll(async () => { - console.info(TAG + 'afterAll'); - }) - - console.info(TAG + "*************Unit Test Begin*************"); - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0001 - * @tc.desc graph store getStore test - */ - it('testGraphStore0001', 0, async () => { - console.info(TAG + "************* testGraphStore0001 start *************"); - try { - let store = await graphStore.getStore(context, STORE_CONFIG); - await store.close(); - await graphStore.deleteStore(context, STORE_CONFIG); - } catch (e) { - console.error(TAG + "graphStore test_1 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStore0001 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0002 - * @tc.desc graph store getStore and write - */ - it('testGraphStore0002', 0, async () => { - console.info(TAG + "************* testGraphStore0002 start *************"); - try { - let store = await graphStore.getStore(context, STORE_CONFIG); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - await graphStore.deleteStore(context, STORE_CONFIG); - } catch (e) { - console.error(TAG + "graphStore test_2 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStore0002 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0003 - * @tc.desc graph store getStore with wrong storeConfig name - */ - it('testGraphStore0003', 0, async () => { - console.info(TAG + "************* testGraphStore0003 start *************"); - let storeConfig = { - name: "/wrong/graphstore", - securityLevel: graphStore.SecurityLevel.S1, - }; - try { - let store = await graphStore.getStore(context, storeConfig); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - await graphStore.deleteStore(context, storeConfig); - expect().assertFail(); - } catch (e) { - expect('401').assertEqual(e.code); - } - console.info(TAG + "************* testGraphStore0003 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0004 - * @tc.desc graph store getStore with securityLevel - */ - it('testGraphStore0004', 0, async () => { - console.info(TAG + "************* testGraphStore0004 start *************"); - let storeConfig = { - name: "secure", - securityLevel: graphStore.SecurityLevel.S3, - }; - try { - let store = await graphStore.getStore(context, storeConfig); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - await graphStore.deleteStore(context, storeConfig); - } catch (e) { - console.error(TAG + "graphStore test_4 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStore0004 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0005 - * @tc.desc graph store getStore with invalid securityLevel - */ - it('testGraphStore0005', 0, async () => { - console.info(TAG + "************* testGraphStore0005 start *************"); - let storeConfig = { - name: "secure", - securityLevel: 0, - }; - try { - //expect getStore failed - let store = await graphStore.getStore(context, storeConfig); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - await graphStore.deleteStore(context, storeConfig); - expect().assertFail(); - } catch (e) { - expect(401).assertEqual(e.code); - } - console.info(TAG + "************* testGraphStore0005 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0006 - * @tc.desc graph store getStore with 1 param - */ - it('testGraphStore0006', 0, async () => { - console.info(TAG + "************* testGraphStore0006 start *************"); - try { - //expect getStore failed - let store = await graphStore.getStore(STORE_CONFIG); - expect().assertFail(); - } catch (e) { - expect('401').assertEqual(e.code); - } - console.info(TAG + "************* testGraphStore0006 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0007 - * @tc.desc graph store getStore name has db Suffix - */ - it('testGraphStore0007', 0, async () => { - console.info(TAG + "************* testGraphStore0007 start *************"); - let storeConfig = { - name: "suffix.db", - securityLevel: graphStore.SecurityLevel.S1, - } - try { - // expect get store failed - let store = await graphStore.getStore(context, storeConfig); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - await graphStore.deleteStore(context, storeConfig); - expect().assertFail(); - } catch (e) { - expect(31300000).assertEqual(e.code); - } - console.info(TAG + "************* testGraphStore0007 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0008 - * @tc.desc graph store getStore with null storeConfig name - */ - it('testGraphStore0008', 0, async () => { - console.info(TAG + "************* testGraphStore0008 start *************"); - let storeConfig = { - securityLevel: graphStore.SecurityLevel.S1, - } - try { - // expect get store failed - let store = await graphStore.getStore(context, storeConfig); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - await graphStore.deleteStore(context, storeConfig); - expect().assertFail(); - } catch (e) { - expect('401').assertEqual(e.code); - } - console.info(TAG + "************* testGraphStore0008 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0009 - * @tc.desc graph store getStore name has special characters - */ - it('testGraphStore0009', 0, async () => { - console.info(TAG + "************* testGraphStore0009 start *************"); - let storeConfig = { - name: "char*@#!(.&", - securityLevel: graphStore.SecurityLevel.S1, - } - try { - // expect get store failed - let store = await graphStore.getStore(context, storeConfig); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - await graphStore.deleteStore(context, storeConfig); - expect().assertFail(); - } catch (e) { - expect(31300000).assertEqual(e.code); - } - console.info(TAG + "************* testGraphStore0009 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0010 - * @tc.desc graph store getStore SecurityLevel S2->S1 - */ - it('testGraphStore0010', 0, async () => { - console.info(TAG + "************* testGraphStore0010 start *************"); - let storeConfig = { - name: "graphstore", - securityLevel: graphStore.SecurityLevel.S2, - } - try { - let store = await graphStore.getStore(context, storeConfig); - await store.close(); - store = await graphStore.getStore(context, STORE_CONFIG); - expect().assertFail(); - } catch (e) { - expect(401).assertEqual(e.code); - } - await graphStore.deleteStore(context, storeConfig); - console.info(TAG + "************* testGraphStore0010 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0011 - * @tc.desc graph store getStore SecurityLevel S1->S2 - */ - it('testGraphStore0011', 0, async () => { - console.info(TAG + "************* testGraphStore0011 start *************"); - let storeConfig = { - name: "graphstore", - securityLevel: graphStore.SecurityLevel.S2, - } - try { - let store = await graphStore.getStore(context, STORE_CONFIG); - await store.close(); - store = await graphStore.getStore(context, storeConfig); - await store.close(); - await graphStore.deleteStore(context, storeConfig); - } catch (e) { - console.error(TAG + "graphStore test_11 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStore0011 end *************"); - }) - - /** - * @tc.name graph store deleteStore test - * @tc.number GdbStoreGdbStoreJsunitTest0012 - * @tc.desc graph store deleteStore test - */ - it('testGraphStore0012', 0, async () => { - console.info(TAG + "************* testGraphStore0012 start *************"); - let store = await graphStore.getStore(context, STORE_CONFIG); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - try { - await graphStore.deleteStore(context, STORE_CONFIG); - } catch (e) { - console.error(TAG + "graphStore test_12 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStore0012 end *************"); - }) - - /** - * @tc.name graph store deleteStore test - * @tc.number GdbStoreGdbStoreJsunitTest0013 - * @tc.desc graph store deleteStore with wrong store name - */ - it('testGraphStore0013', 0, async () => { - console.info(TAG + "************* testGraphStore0013 start *************"); - let storeConfig = { - name: "/wrong/graphstore", - securityLevel: graphStore.SecurityLevel.S1, - } - let store = await graphStore.getStore(context, STORE_CONFIG); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - try { - await graphStore.deleteStore(context, storeConfig); - expect().assertFail(); - } catch (e) { - expect('401').assertEqual(e.code); - } - console.info(TAG + "************* testGraphStore0013 end *************"); - }) - - /** - * @tc.name graph store deleteStore test - * @tc.number GdbStoreGdbStoreJsunitTest0014 - * @tc.desc graph store deleteStore with different store name - */ - it('testGraphStore0014', 0, async () => { - console.info(TAG + "************* testGraphStore0014 start *************"); - let storeConfig = { - name: "teststore", - securityLevel: graphStore.SecurityLevel.S1, - } - let store = await graphStore.getStore(context, STORE_CONFIG); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - try { - // delete success - await graphStore.deleteStore(context, storeConfig); - } catch (e) { - expect().assertFail(); - } - console.info(TAG + "************* testGraphStore0014 end *************"); - }) - - /** - * @tc.name graph store deleteStore test - * @tc.number GdbStoreGdbStoreJsunitTest0015 - * @tc.desc graph store deleteStore with different securityLevel - */ - it('testGraphStore0015', 0, async () => { - console.info(TAG + "************* testGraphStore0015 start *************"); - let storeConfig = { - name: "graphstore", - securityLevel: graphStore.SecurityLevel.S4, - } - let store = await graphStore.getStore(context, STORE_CONFIG); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - try { - // delete success - await graphStore.deleteStore(context, storeConfig); - } catch (e) { - expect().assertFail(); - } - console.info(TAG + "************* testGraphStore0015 end *************"); - }) - - /** - * @tc.name graph store deleteStore test - * @tc.number GdbStoreGdbStoreJsunitTest0016 - * @tc.desc graph store deleteStore with 1 param - */ - it('testGraphStore0016', 0, async () => { - console.info(TAG + "************* testGraphStore0016 start *************"); - let store = await graphStore.getStore(context, STORE_CONFIG); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - try { - await graphStore.deleteStore(context); - expect().assertFail(); - } catch (e) { - expect('401').assertEqual(e.code); - } - console.info(TAG + "************* testGraphStore0016 end *************"); - }) - - console.info(TAG + "*************Unit Test End*************"); -}) diff --git a/relational_store/test/js/gdb/unittest/src/GdbStoreReadWriteJsunit.test.js b/relational_store/test/js/gdb/unittest/src/GdbStoreReadWriteJsunit.test.js deleted file mode 100644 index 17cb922e14b96194f3d9a58d1525453c6a9ba052..0000000000000000000000000000000000000000 --- a/relational_store/test/js/gdb/unittest/src/GdbStoreReadWriteJsunit.test.js +++ /dev/null @@ -1,936 +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. - */ - -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' -import graphStore from '@ohos.data.graphStore' -import ability_featureAbility from '@ohos.ability.featureAbility' - -const TAG = "[GRAPH_STORE_JSKITS_TEST]"; -const context = ability_featureAbility.getContext(); -const CREATE_GRAPH_TEST = "CREATE GRAPH test {(person:Person {name STRING, age INT}), (person) -[:Friend]-> (person)};" -const STORE_CONFIG = { - name: "readwritegraph", - securityLevel: graphStore.SecurityLevel.S1, -}; - -describe('graphStoreReadWriteTest', () => { - let store; - beforeAll(async () => { - console.info(TAG + 'beforeAll'); - await graphStore.deleteStore(context, STORE_CONFIG); - store = await graphStore.getStore(context, STORE_CONFIG); - }) - - beforeEach(async () => { - console.info(TAG + 'beforeEach'); - await store.write(CREATE_GRAPH_TEST); - }) - - afterEach(async () => { - console.info(TAG + 'afterEach'); - await store.write("DROP GRAPH test"); - }) - - afterAll(async () => { - console.info(TAG + 'afterAll'); - await store.close(); - await graphStore.deleteStore(context, STORE_CONFIG); - }) - - console.info(TAG + "*************Unit Test Begin*************"); - - /** - * @tc.name graph store close test - * @tc.number GdbStoreCloseTest0001 - * @tc.desc graph store close test - */ - it('testGraphStoreClose0001', 0, async () => { - console.info(TAG + "************* testGraphStoreClose0001 start *************"); - let storeConfig = { - name: "closeStore", - securityLevel: graphStore.SecurityLevel.S1, - }; - let closestore = await graphStore.getStore(context, storeConfig); - await closestore.write(CREATE_GRAPH_TEST); - await closestore.write("INSERT (:Person {name: 'name_1', age: 11});"); - await closestore.write("DROP GRAPH test"); - try { - await closestore.close(); - } catch (e) { - console.error(TAG + "close test failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - await graphStore.deleteStore(context, storeConfig); - console.info(TAG + "************* testGraphStoreClose0001 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0001 - * @tc.desc graph store write insert - */ - it('testGraphStoreWrite0001', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0001 start *************"); - try { - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1) -[:Friend]-> (p2);" - ); - let result = await store.read("MATCH (p:Person) where p.age < 30 RETURN p") - if (result.records) { - expect(2).assertEqual(result.records.length); - } else { - console.error(TAG + "write test1 INSERT vertex failed."); - expect().assertFail(); - } - let path = await store.read( - "MATCH path = (p1:Person {name: 'name_1'})-[]-(p2:Person {name: 'name_2'}) RETURN path;" - ); - if (path.records) { - expect(1).assertEqual(path.records.length); - } else { - console.error(TAG + "write test1 INSERT edge failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "write test1 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreWrite0001 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0002 - * @tc.desc graph store write update - */ - it('testGraphStoreWrite0002', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0002 start *************"); - try { - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1) -[:Friend]-> (p2);" - ); - await store.write("MATCH (p1:Person {name: 'name_1'}) SET p1.age = 21;"); - await store.write("MATCH (p2:Person {name: 'name_2'}) SET p2.name = 'Aname';"); - await store.write("MATCH (n:Person {name: 'name_1'})-[r:Friend]->(m:Person) SET m.age = 32"); - - let p1 = await store.read("MATCH (p1:Person) where p1.name = 'name_1' RETURN p1;"); - if (p1.records) { - expect(1).assertEqual(p1.records.length); - let temp = p1.records[0]; - let vertex = temp["p1"]; - expect('1').assertEqual(vertex.vid); - let proper = vertex.properties; - expect(21).assertEqual(proper["AGE"]); - expect('name_1').assertEqual(proper["NAME"]); - } else { - console.error(TAG + "write test2 read data1 failed."); - expect().assertFail(); - } - - let p2 = await store.read("MATCH (p2:Person) where p2.name = 'name_2' RETURN p2;"); - if (p2.records) { - expect(0).assertEqual(p2.records.length); - } else { - console.error(TAG + "write test2 read data2 failed."); - expect().assertFail(); - } - - let p3 = await store.read("MATCH (p3:Person) where p3.name = 'Aname' RETURN p3;"); - if (p3.records) { - expect(1).assertEqual(p3.records.length); - let temp = p3.records[0]; - let vertex = temp["p3"]; - expect('2').assertEqual(vertex.vid); - let proper = vertex.properties; - expect(32).assertEqual(proper["AGE"]); - expect('Aname').assertEqual(proper["NAME"]); - } else { - console.error(TAG + "write test2 read data3 failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "write test2 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreWrite0002 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0003 - * @tc.desc graph store write delete - */ - it('testGraphStoreWrite0003', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0003 start *************"); - try { - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1) -[:Friend]-> (p2);" - ); - await store.write("MATCH (p:Person {name: 'name_1'}) DETACH DELETE p;"); - // read - let p = await store.read("MATCH (p:Person) where p.age < 30 RETURN p"); - if (p.records) { - expect(1).assertEqual(p.records.length); - } else { - console.error(TAG + "write test3 read data1 failed."); - expect().assertFail(); - } - - let path = await store.read( - "MATCH path = (p1:Person {name: 'name_1'})-[]-(p2:Person {name: 'name_2'}) RETURN path;" - ) - if (path.records) { - expect(0).assertEqual(path.records.length); - } else { - console.error(TAG + "write test3 read data2 failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "write test3 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreWrite0003 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0004 - * @tc.desc graph store write with 2 params - */ - it('testGraphStoreWrite0004', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0004 start *************"); - try { - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - let INSERT1 = "INSERT (:Person {name: 'name_3', age: 33});" - let INSERT2 = "INSERT (:Person {name: 'name_4', age: 44});" - await store.write(INSERT1, INSERT2); - expect().assertFail(); - } catch (e) { - expect('401').assertEqual(e.code); - // read - let p = await store.read("MATCH (p:Person) where p.age < 50 RETURN p"); - if (p.records) { - expect(2).assertEqual(p.records.length); - } else { - console.error(TAG + "write test4 read data failed."); - expect().assertFail(); - } - } - console.info(TAG + "************* testGraphStoreWrite0004 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0005 - * @tc.desc graph store close before write - */ - it('testGraphStoreWrite0005', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0005 start *************"); - let storeConfig = { - name: "closeStore", - securityLevel: graphStore.SecurityLevel.S1, - }; - let closestore = await graphStore.getStore(context, storeConfig); - await closestore.write(CREATE_GRAPH_TEST); - try { - await closestore.write("INSERT (:Person {name: 'name_1', age: 11});"); - let p = await closestore.read("MATCH (p:Person) where p.age < 30 RETURN p"); - if (p.records) { - expect(1).assertEqual(p.records.length); - } else { - console.error(TAG + "write test5 read data failed."); - expect().assertFail(); - } - await closestore.close(); - await closestore.write("INSERT (:Person {name: 'name_2', age: 22});"); - expect().assertFail(); - } catch (e) { - expect('31300002').assertEqual(e.code); - } - await graphStore.deleteStore(context, storeConfig); - console.info(TAG + "************* testGraphStoreWrite0005 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0006 - * @tc.desc graph store write with duplicate type - */ - it('testGraphStoreWrite0006', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0006 start *************") - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - let INSERT = "INSERT (:Person {name: 'name_3', name: 'name_4', age: 33});" - try { - //insert failed but no error - await store.write(INSERT); - let result = await store.write("MATCH (p:Person) where p.age = 33 RETURN p;"); - if (result.records) { - expect(0).assertEqual(result.records.length); - } - } catch (e) { - console.error(TAG + "write test6 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreWrite0006 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0007 - * @tc.desc graph store write with undefined type - */ - it('testGraphStoreWrite0007', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0007 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - let UPDATE = "MATCH (p:Person {name: 'name_1'}) DETACH DELETE p_error" - try { - await store.write(UPDATE); - expect().assertFail(); - } catch (e) { - expect(31300007).assertEqual(e.code); - // read - let p = await store.read("MATCH (p:Person) where p.age < 50 RETURN p"); - if (p.records) { - expect(2).assertEqual(p.records.length); - } else { - console.error(TAG + "write test7 read data failed."); - expect().assertFail(); - } - } - console.info(TAG + "************* testGraphStoreWrite0007 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0008 - * @tc.desc graph store write with GQL statement syntax error - */ - it('testGraphStoreWrite0008', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0008 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - let INSERT = "INSERT (:ZOO {name: 'name_3', age: 33);" - try { - await store.write(INSERT); - expect().assertFail(); - } catch (e) { - expect(31300009).assertEqual(e.code); - // read - let p = await store.read("MATCH (p:Person) where p.age < 50 RETURN p"); - if (p.records) { - expect(2).assertEqual(p.records.length); - } else { - console.error(TAG + "write test8 read data failed."); - expect().assertFail(); - } - } - console.info(TAG + "************* testGraphStoreWrite0008 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0009 - * @tc.desc graph store write with GQL statement semantic error - */ - it('testGraphStoreWrite0009', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0009 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - let UPDATE = "MATCH (p1:Person {name: 'name_1'}) SET p1.age = 'six';" - try { - await store.write(UPDATE); - expect().assertFail(); - } catch (e) { - expect(31300010).assertEqual(e.code); - // read - let p = await store.read("MATCH (p:Person) where p.age < 50 RETURN p"); - if (p.records) { - expect(2).assertEqual(p.records.length); - let temp = p.records[0]; - let vertex = temp["p"]; - expect('1').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_1').assertEqual(proper["NAME"]); - expect(11).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "write test9 read data failed."); - expect().assertFail(); - } - } - console.info(TAG + "************* testGraphStoreWrite0009 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0010 - * @tc.desc graph store write and update null data - */ - it('testGraphStoreWrite0010', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0010 start *************"); - await store.write("INSERT (:Person {name: 'name_1'});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - let data = await store.read("MATCH (p:Person) where p.age < 50 RETURN p"); - if (data.records) { - expect(1).assertEqual(data.records.length); - let temp = data.records[0]; - let vertex = temp["p"]; - expect('2').assertEqual(vertex.vid); - let proper = vertex.properties; - expect(22).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "write test10 INSERT data failed."); - expect().assertFail(); - } - let UPDATE1 = "MATCH (p1:Person {name: 'name_1'}) SET p1.age = 16;" - let UPDATE2 = "MATCH (p2:Person {name: 'name_2'}) SET p2.age = 16, p2.name = null;" - try { - await store.write(UPDATE1); - await store.write(UPDATE2); - data = await store.read("MATCH (p:Person) where p.age < 50 RETURN p"); - if (data.records) { - expect(2).assertEqual(data.records.length); - let temp = data.records[0]; - let vertex = temp["p"]; - expect('1').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_1').assertEqual(proper["NAME"]); - expect(16).assertEqual(proper["AGE"]); - - temp = data.records[1]; - vertex = temp["p"]; - expect('2').assertEqual(vertex.vid); - proper = vertex.properties; - // name undefined - expect(16).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "write test10 read data failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "write test10 update null data failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreWrite0010 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0011 - * @tc.desc graph store write create too many graphs - */ - it('testGraphStoreWrite0011', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0011 start *************"); - try { - await store.write("CREATE GRAPH test1 {(company:Company {rowid INT, name STRING}) };"); - expect().assertFail(); - } catch (e) { - expect(31300012).assertEqual(e.code); - } - console.info(TAG + "************* testGraphStoreWrite0011 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0012 - * @tc.desc graph store write delete the vertexs of a relation - */ - it('testGraphStoreWrite0012', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0012 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 33});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p3:Person {name: 'name_3'}) INSERT (p1) -[:Friend]-> (p3);" - ); - let data = await store.read("MATCH (p:Person) where p.age < 50 RETURN p"); - if (data.records) { - expect(3).assertEqual(data.records.length); - } else { - console.error(TAG + "write test12 INSERT data failed."); - expect().assertFail(); - } - let DELETE = "MATCH (p:Person)-[:Friend]->(relatedP:Person) DETACH DELETE p, relatedP;" - try { - await store.write(DELETE); - data = await store.read("MATCH (p:Person) where p.age < 50 RETURN p"); - // read data - if (data.records) { - expect(1).assertEqual(data.records.length); - let temp = data.records[0]; - let vertex = temp["p"]; - expect('2').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_2').assertEqual(proper["NAME"]); - expect(22).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "write test12 read data failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "write test12 delete failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreWrite0012 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0001 - * @tc.desc graph store read query vertex test - */ - it('testGraphStoreRead0001', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0001 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 22});"); - try { - let p = await store.read("MATCH (p:Person {age: 22}) RETURN p;"); - if (p.records) { - expect(2).assertEqual(p.records.length); - let temp = p.records[0]; - let vertex = temp["p"]; - expect('2').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_2').assertEqual(proper["NAME"]); - expect(22).assertEqual(proper["AGE"]); - - temp = p.records[1]; - vertex = temp["p"]; - expect('3').assertEqual(vertex.vid); - proper = vertex.properties; - expect('name_3').assertEqual(proper["NAME"]); - expect(22).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "read test1 query failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "read test1 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreRead0001 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0002 - * @tc.desc graph store read query null data test - */ - it('testGraphStoreRead0002', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0002 start *************"); - await store.write("INSERT (:Person {age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 22});"); - try { - let p = await store.read("MATCH (p:Person {age: 11}) RETURN p;"); - if (p.records) { - expect(1).assertEqual(p.records.length); - let temp = p.records[0]; - let vertex = temp["p"]; - expect('1').assertEqual(vertex.vid); - let proper = vertex.properties; - // name undefined - expect(11).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "read test2 query null data failed."); - expect().assertFail(); - } - - p = await store.read("MATCH (p:Person {age: 22}) RETURN p;"); - if (p.records) { - expect(2).assertEqual(p.records.length); - let temp = p.records[0]; - let vertex = temp["p"]; - expect('2').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_2').assertEqual(proper["NAME"]); - expect(22).assertEqual(proper["AGE"]); - - temp = p.records[1]; - vertex = temp["p"]; - proper = vertex.properties; - expect('name_3').assertEqual(proper["NAME"]); - } else { - console.error(TAG + "read test2 query null data failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "read test2 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreRead0002 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0003 - * @tc.desc graph store read by relation - */ - it('testGraphStoreRead0003', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0003 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 22});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1)-[:Friend]->(p2);" - ) - try { - let data = await store.read( - "MATCH (p1:Person {age: 11})-[r:Friend]->(p2:Person {name :'name_2'}) RETURN p1, r, p2;" - ); - if (data.records) { - expect(1).assertEqual(data.records.length); - let temp = data.records[0]; - let vertex = temp["p1"]; - expect('1').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_1').assertEqual(proper["NAME"]); - expect(11).assertEqual(proper["AGE"]); - - let edge = temp["r"]; - expect('4').assertEqual(edge.eid); - expect('1').assertEqual(edge.startVid); - expect('2').assertEqual(edge.endVid); - - vertex = temp["p2"]; - expect('2').assertEqual(vertex.vid); - proper = vertex.properties; - expect(22).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "read test3 query relation failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "read test3 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreRead0003 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0004 - * @tc.desc graph store read by where statement - */ - it('testGraphStoreRead0004', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0004 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 22});"); - try { - let data = await store.read("MATCH (p:Person) where p.age >= 22 RETURN p;"); - if (data.records) { - expect(2).assertEqual(data.records.length); - let temp = data.records[0]; - let vertex = temp["p"]; - expect('2').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_2').assertEqual(proper["NAME"]); - expect(22).assertEqual(proper["AGE"]); - - temp = data.records[1]; - vertex = temp["p"]; - expect('3').assertEqual(vertex.vid); - proper = vertex.properties; - expect('name_3').assertEqual(proper["NAME"]); - } else { - console.error(TAG + "read test4 query by where failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "read test4 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreRead0004 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0005 - * @tc.desc graph store read by where statement - */ - it('testGraphStoreRead0005', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0005 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 22});"); - try { - let data = await store.read("MATCH (p:Person) where p.age < 22 RETURN p;"); - if (data.records) { - expect(1).assertEqual(data.records.length); - let temp = data.records[0]; - let vertex = temp["p"]; - expect('1').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_1').assertEqual(proper["NAME"]); - expect(11).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "read test5 query by where failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "read test5 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreRead0005 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0006 - * @tc.desc graph store read by where statement - */ - it('testGraphStoreRead0006', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0006 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 33});"); - try { - let data = await store.read("MATCH (p:Person) where p.age <> 22 RETURN p;"); - if (data.records) { - expect(2).assertEqual(data.records.length); - let temp = data.records[0]; - let vertex = temp["p"]; - expect('1').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_1').assertEqual(proper["NAME"]); - expect(11).assertEqual(proper["AGE"]); - - temp = data.records[1]; - vertex = temp["p"]; - expect('3').assertEqual(vertex.vid); - proper = vertex.properties; - expect('name_3').assertEqual(proper["NAME"]); - expect(33).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "read test6 query by where failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "read test6 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreRead0006 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0007 - * @tc.desc graph store read by like statement - */ - it('testGraphStoreRead0007', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0007 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 33});"); - try { - let data = await store.read("MATCH (p:Person) where p.name like 'name_%' RETURN p;"); - if (data.records) { - expect(3).assertEqual(data.records.length); - let temp = data.records[0]; - let vertex = temp["p"]; - expect('1').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_1').assertEqual(proper["NAME"]); - expect(11).assertEqual(proper["AGE"]); - - temp = data.records[1]; - vertex = temp["p"]; - expect('2').assertEqual(vertex.vid); - proper = vertex.properties; - expect('name_2').assertEqual(proper["NAME"]); - expect(22).assertEqual(proper["AGE"]); - - temp = data.records[2]; - vertex = temp["p"]; - expect('3').assertEqual(vertex.vid); - proper = vertex.properties; - expect('name_3').assertEqual(proper["NAME"]); - expect(33).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "read test7 query by like failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "read test7 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreRead0007 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0008 - * @tc.desc graph store read path - */ - it('testGraphStoreRead0008', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0008 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 33});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1) -[:Friend]-> (p2);" - ); - await store.write( - "MATCH (p2:Person {name: 'name_2'}), (p3:Person {name: 'name_3'}) INSERT (p2) -[:Friend]-> (p3);" - ); - try { - let data = await store.read( - "MATCH path = (a:Person {name: 'name_1'})-[]->{2,2}(b:Person {name: 'name_3'}) RETURN a, b, path;" - ); - if (data.records) { - expect(1).assertEqual(data.records.length); - let temp = data.records[0]; - - let vertex1 = temp["a"]; - expect('1').assertEqual(vertex1.vid); - let proper = vertex1.properties; - expect('name_1').assertEqual(proper["NAME"]); - expect(11).assertEqual(proper["AGE"]); - - let vertex2 = temp["b"]; - expect('3').assertEqual(vertex2.vid); - proper = vertex2.properties; - expect('name_3').assertEqual(proper["NAME"]); - expect(33).assertEqual(proper["AGE"]); - - let path = temp["path"]; - expect(2).assertEqual(path.length); - let segments = path.segments; - expect(JSON.stringify(vertex1)).assertEqual(JSON.stringify(segments[0].start)); - expect(JSON.stringify(vertex2)).assertEqual(JSON.stringify(segments[1].end)); - - let edge = segments[1].edge; - expect('5').assertEqual(edge.eid); - expect('2').assertEqual(edge.startVid); - expect('3').assertEqual(edge.endVid); - } else { - console.error(TAG + "read test8 query path failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "read test8 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreRead0008 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0009 - * @tc.desc graph store read with 2 params - */ - it('testGraphStoreRead0009', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0009 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1) -[:Friend]-> (p2);" - ); - - let MATCH1 = "MATCH (p1:Person {name: 'name_1'}) RETURN p1;" - let MATCH2 = "MATCH (p2:Person {name: 'name_2'}) RETURN p2;" - try { - let result = await store.read(MATCH1, MATCH2); - expect().assertFail(); - } catch (e) { - expect('401').assertEqual(e.code); - } - console.info(TAG + "************* testGraphStoreRead0009 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0010 - * @tc.desc graph store close before read - */ - it('testGraphStoreRead0010', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0010 start *************"); - let storeConfig = { - name: "closeStore", - securityLevel: graphStore.SecurityLevel.S1, - }; - let closestore = await graphStore.getStore(context, storeConfig); - await closestore.write(CREATE_GRAPH_TEST); - await closestore.write("INSERT (:Person {name: 'name_1', age: 11});"); - await closestore.write("INSERT (:Person {name: 'name_2', age: 22});"); - await closestore.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1) -[:Friend]-> (p2);" - ); - await closestore.close(); - let MATCH = "MATCH (p1:Person {name: 'name_1'}) RETURN p1;" - try { - let result = await closestore.read(MATCH); - expect().assertFail(); - } catch (e) { - expect('31300002').assertEqual(e.code); - } - await graphStore.deleteStore(context, storeConfig); - console.info(TAG + "************* testGraphStoreRead0010 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0011 - * @tc.desc graph store read with undefined type - */ - it('testGraphStoreRead0011', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0011 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1) -[:Friend]-> (p2);" - ); - let MATCH = "MATCH path = (p1:ZOO {name: 'name_1'})-[]-(p2:Person {name: 'name_2'}) RETURN path;" - try { - let result = await store.read(MATCH); - expect().assertFail(); - } catch (e) { - expect(31300007).assertEqual(e.code); - } - console.info(TAG + "************* testGraphStoreRead0011 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0012 - * @tc.desc graph store read with GQL statement syntax error - */ - it('testGraphStoreRead0012', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0012 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1) -[:Friend]-> (p2);" - ); - try { - let result = await store.read("MATCH (p:Person {name: 'name_1}) RETURN p"); - expect().assertFail(); - } catch (e) { - expect(31300009).assertEqual(e.code); - } - console.info(TAG + "************* testGraphStoreRead0012 end *************"); - }) - console.info(TAG + "*************Unit Test End*************"); -}) \ No newline at end of file diff --git a/relational_store/test/js/rdb/unittest/src/RdbStoreDistributedJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbStoreDistributedJsunit.test.js index bf46e3edd2675b3e9cb37c0eb53afd911abef13e..893febf9d9c65969827dd22843377bc6edc53d1a 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbStoreDistributedJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbStoreDistributedJsunit.test.js @@ -208,9 +208,9 @@ describe('rdbStoreDistributedTest', function () { const name = await resultSet.getString(resultSet.getColumnIndex("name")) const age = await resultSet.getLong(resultSet.getColumnIndex("age")) - await expect(1).assertEqual(id); - await expect("Jim").assertEqual(name); - await expect(30).assertEqual(age); + expect(1).assertEqual(id); + expect("Jim").assertEqual(name); + expect(30).assertEqual(age); resultSet.close(); expect(true).assertEqual(resultSet.isClosed) } catch (e) { diff --git a/relational_store/test/js/rdb/unittest/src/RdbstoreCreateDeleteWithFAContextJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstoreCreateDeleteWithFAContextJsunit.test.js index 3e2f4ec3e1565b3ed84101204cb249ebe006d870..8cbc09df51b8fa3101bb4c487d57be59b096e6cd 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbstoreCreateDeleteWithFAContextJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbstoreCreateDeleteWithFAContextJsunit.test.js @@ -100,14 +100,8 @@ describe('rdbStoreCreateDeleteWithFAContextTest', function () { { let predicates = await new dataRdb.RdbPredicates("test") predicates.equalTo("name", "zhangsan") - let deletePromise = rdbStore.delete(predicates) - deletePromise.then(async (ret) => { - await expect(1).assertEqual(ret) - await console.log(TAG + "Delete done: " + ret) - }).catch((err) => { - expect(null).assertFail() - }) - await deletePromise + let ret = await rdbStore.delete(predicates) + expect(1).assertEqual(ret) } await rdbStore.executeSql("DELETE FROM test"); rdbStore = null diff --git a/relational_store/test/js/rdb/unittest/src/RdbstoreDeleteJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstoreDeleteJsunit.test.js index ec3de69e2960b0433989b8560026e24b28686ca8..05292f9c7d88cc3377f2bc83d0ff0edfccfda9e7 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbstoreDeleteJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbstoreDeleteJsunit.test.js @@ -134,14 +134,8 @@ describe('rdbStoreDeleteTest', function () { { let predicates = await new dataRdb.RdbPredicates("test") predicates.equalTo("name", "zhangsan") - let deletePromise = rdbStore.delete(predicates) - deletePromise.then(async (ret) => { - await expect(1).assertEqual(ret) - await console.log(TAG + "Delete done: " + ret) - }).catch((err) => { - expect(null).assertFail() - }) - await deletePromise + let ret = await rdbStore.delete(predicates) + expect(1).assertEqual(ret) } done() console.log(TAG + "************* testRdbStoreDelete0002 end *************"); diff --git a/relational_store/test/js/rdb/unittest/src/RdbstoreEncryptionJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstoreEncryptionJsunit.test.js index b054febfc56bc4abc81c1995e55d1661c609880f..21c359881b81e6507ae696318ddbb6540d9b35b0 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbstoreEncryptionJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbstoreEncryptionJsunit.test.js @@ -101,7 +101,7 @@ describe('rdbEncryptTest', function () { * @tc.desc RDB create encrypt db test */ it('RdbEncryptTest_0010', 0, async function () { - await console.log(TAG + "************* RdbEncryptTest_0010 start *************") + console.log(TAG + "************* RdbEncryptTest_0010 start *************") try { context = ability_featureAbility.getContext() await data_rdb.getRdbStore(context, STORE_CONFIG_ENCRYPT, 1); @@ -109,7 +109,7 @@ describe('rdbEncryptTest', function () { console.log(TAG + `failed, errcode:${JSON.stringify(err)}.`); expect(null).assertFail(); } - await console.log(TAG + "************* RdbEncryptTest_0010 end *************") + console.log(TAG + "************* RdbEncryptTest_0010 end *************") }) /** @@ -118,7 +118,7 @@ describe('rdbEncryptTest', function () { * @tc.desc RDB create unencrypted db test */ it('RdbEncryptTest_0020', 0, async function () { - await console.log(TAG + "************* RdbEncryptTest_0020 start *************") + console.log(TAG + "************* RdbEncryptTest_0020 start *************") context = ability_featureAbility.getContext() try { await data_rdb.getRdbStore(context, STORE_CONFIG_UNENCRYPT, 1); @@ -126,7 +126,7 @@ describe('rdbEncryptTest', function () { console.log(TAG + `failed, errcode:${JSON.stringify(err)}.`); expect(null).assertFail(); } - await console.log(TAG + "************* RdbEncryptTest_0020 end *************") + console.log(TAG + "************* RdbEncryptTest_0020 end *************") }) @@ -136,7 +136,7 @@ describe('rdbEncryptTest', function () { * @tc.desc RDB encrypt function test */ it('RdbEncryptTest_0030', 0, async function () { - await console.log(TAG + "************* RdbEncryptTest_0030 start *************") + console.log(TAG + "************* RdbEncryptTest_0030 start *************") context = ability_featureAbility.getContext() let rdbStore = await CreateRdbStore(context, STORE_CONFIG_ENCRYPT) let predicates = new data_rdb.RdbPredicates("test") @@ -159,7 +159,7 @@ describe('rdbEncryptTest', function () { resultSet = null rdbStore = null } - await console.log(TAG + "************* RdbEncryptTest_0030 end *************") + console.log(TAG + "************* RdbEncryptTest_0030 end *************") }) /** @@ -213,7 +213,7 @@ describe('rdbEncryptTest', function () { * 4. query db1 and db2 */ it('RdbEncryptTest_0050', 0, async function () { - await console.info(TAG + "************* RdbEncryptTest_0050 start *************") + console.info(TAG + "************* RdbEncryptTest_0050 start *************") context = ability_featureAbility.getContext() let rdbStore1; let rdbStore2; diff --git a/relational_store/test/js/rdb/unittest/src/RdbstorePredicatesComplexFiledJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstorePredicatesComplexFiledJsunit.test.js index 80ffc25410e327e9892c006f557c4178d8e35e03..3396fce7143f4ab344d1925c9d8f74fdc73a985a 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbstorePredicatesComplexFiledJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbstorePredicatesComplexFiledJsunit.test.js @@ -75,12 +75,12 @@ describe('rdbStorePredicatesComplexFiledTest', function () { let count = await resultSet.getLong(resultSet.getColumnIndex("num count")) let birthday = await resultSet.getString(resultSet.getColumnIndex("birthday")) expect(2).assertEqual(count); - await expect("2022-09-01").assertEqual(birthday) + expect("2022-09-01").assertEqual(birthday) expect(true).assertEqual(resultSet.goToNextRow()) count = await resultSet.getLong(resultSet.getColumnIndex("num count")) birthday = await resultSet.getString(resultSet.getColumnIndex("birthday")) expect(3).assertEqual(count); - await expect("2022-09-02").assertEqual(birthday) + expect("2022-09-02").assertEqual(birthday) expect(false).assertEqual(resultSet.goToNextRow()) resultSet.close(); done(); @@ -102,12 +102,12 @@ describe('rdbStorePredicatesComplexFiledTest', function () { let count = await resultSet.getLong(resultSet.getColumnIndex("numcount")) let birthday = await resultSet.getString(resultSet.getColumnIndex("birthday")) expect(3).assertEqual(count); - await expect("2022-09-02").assertEqual(birthday) + expect("2022-09-02").assertEqual(birthday) expect(true).assertEqual(resultSet.goToNextRow()) count = await resultSet.getLong(resultSet.getColumnIndex("numcount")) birthday = await resultSet.getString(resultSet.getColumnIndex("birthday")) expect(2).assertEqual(count); - await expect("2022-09-01").assertEqual(birthday) + expect("2022-09-01").assertEqual(birthday) expect(false).assertEqual(resultSet.goToNextRow()) resultSet.close(); done(); diff --git a/relational_store/test/js/rdb/unittest/src/RdbstoreStoreExcuteSqlJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstoreStoreExcuteSqlJsunit.test.js index 60c72b019b591be3da2dd430335ef11b0af9b27e..26d15cd567c43da5b7b9418ee21ec5a4ea85afcb 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbstoreStoreExcuteSqlJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbstoreStoreExcuteSqlJsunit.test.js @@ -88,7 +88,7 @@ describe('rdbStoreExcuteSqlTest', function () { let querySqlPromise = rdbStore.querySql("SELECT * FROM test") querySqlPromise.then(async (resultSet) => { - await expect(0).assertEqual(resultSet.rowCount) + expect(0).assertEqual(resultSet.rowCount) resultSet.close() done(); }).catch((err) => { @@ -139,7 +139,7 @@ describe('rdbStoreExcuteSqlTest', function () { await rdbStore.executeSql("DELETE FROM test WHERE name = 'lisi'") let querySqlPromise = rdbStore.querySql("SELECT * FROM test") querySqlPromise.then(async (resultSet) => { - await expect(1).assertEqual(resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) resultSet.close() done(); }).catch((err) => { @@ -193,7 +193,7 @@ describe('rdbStoreExcuteSqlTest', function () { predicates.equalTo("name", nameStr) let querySqlPromise = rdbStore.query(predicates) querySqlPromise.then(async (resultSet) => { - await expect(2).assertEqual(resultSet.rowCount) + expect(2).assertEqual(resultSet.rowCount) resultSet.close() }).catch((err) => { expect(null).assertFail(); @@ -203,7 +203,7 @@ describe('rdbStoreExcuteSqlTest', function () { { let executeSqlPromise = rdbStore.executeSql("DELETE FROM test WHERE age = 19 AND name ='" + nameStr + "'") executeSqlPromise.then(async () => { - await console.log(TAG + "executeSql done."); + console.log(TAG + "executeSql done."); }).catch((err) => { expect(null).assertFail(); }) @@ -212,7 +212,7 @@ describe('rdbStoreExcuteSqlTest', function () { { let querySqlPromise = rdbStore.querySql("SELECT * FROM test WHERE name ='" + nameStr + "'") querySqlPromise.then(async (resultSet) => { - await expect(1).assertEqual(resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) expect(true).assertEqual(resultSet.goToFirstRow()) const name = resultSet.getString(resultSet.getColumnIndex("name")) const age = resultSet.getLong(resultSet.getColumnIndex("age")) diff --git a/relational_store/test/js/rdb/unittest/src/RdbstoreUpdateJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstoreUpdateJsunit.test.js index 63339ec739cf037fc474b849eb25f9df1c0ebedc..9834848e14f4a5f21aa35b9f7f41b4305783030f 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbstoreUpdateJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbstoreUpdateJsunit.test.js @@ -75,8 +75,8 @@ describe('rdbStoreUpdateTest', function () { let predicates = await new dataRdb.RdbPredicates("test") await predicates.equalTo("id", "1") let ret = await rdbStore.update(valueBucket, predicates) - await expect(1).assertEqual(ret); - await console.log(TAG + "update done: " + ret); + expect(1).assertEqual(ret); + console.log(TAG + "update done: " + ret); predicates = await new dataRdb.RdbPredicates("test") let resultSet = await rdbStore.query(predicates) @@ -88,14 +88,14 @@ describe('rdbStoreUpdateTest', function () { const salary = await resultSet.getDouble(resultSet.getColumnIndex("salary")) const blobType = await resultSet.getBlob(resultSet.getColumnIndex("blobType")) - await expect(1).assertEqual(id); - await expect("lisi").assertEqual(name); - await expect(20).assertEqual(age); - await expect(200.5).assertEqual(salary); - await expect(4).assertEqual(blobType[0]); - await expect(5).assertEqual(blobType[1]); - await expect(6).assertEqual(blobType[2]); - await expect(false).assertEqual(resultSet.goToNextRow()) + expect(1).assertEqual(id); + expect("lisi").assertEqual(name); + expect(20).assertEqual(age); + expect(200.5).assertEqual(salary); + expect(4).assertEqual(blobType[0]); + expect(5).assertEqual(blobType[1]); + expect(6).assertEqual(blobType[2]); + expect(false).assertEqual(resultSet.goToNextRow()) } finally { resultSet.close() resultSet = null @@ -246,8 +246,8 @@ describe('rdbStoreUpdateTest', function () { let predicates = await new dataRdb.RdbPredicates("test") await predicates.equalTo("name", "xiaoming") let ret = await rdbStore.update(valueBucket, predicates) - await expect(1).assertEqual(ret); - await console.log(TAG + "update done: " + ret); + expect(1).assertEqual(ret); + console.log(TAG + "update done: " + ret); predicates = await new dataRdb.RdbPredicates("test") predicates.equalTo("age", 20) @@ -255,7 +255,7 @@ describe('rdbStoreUpdateTest', function () { try { expect(true).assertEqual(resultSet.goToFirstRow()) const name = await resultSet.getString(resultSet.getColumnIndex("name")) - await expect(nameStr).assertEqual(name); + expect(nameStr).assertEqual(name); } finally { resultSet.close() resultSet = null @@ -296,8 +296,8 @@ describe('rdbStoreUpdateTest', function () { let predicates = await new dataRdb.RdbPredicates("test") await predicates.equalTo("name", "xiaohua") let ret = await rdbStore.update(valueBucket, predicates) - await expect(1).assertEqual(ret); - await console.log(TAG + "update done: " + ret); + expect(1).assertEqual(ret); + console.log(TAG + "update done: " + ret); predicates = await new dataRdb.RdbPredicates("test") predicates.equalTo("age", 19) @@ -305,7 +305,7 @@ describe('rdbStoreUpdateTest', function () { try { expect(true).assertEqual(resultSet.goToFirstRow()) const name = await resultSet.getString(resultSet.getColumnIndex("name")) - await expect(nameStr).assertEqual(name); + expect(nameStr).assertEqual(name); } finally { resultSet.close() resultSet = null @@ -346,8 +346,8 @@ describe('rdbStoreUpdateTest', function () { let predicates = await new dataRdb.RdbPredicates("test") await predicates.equalTo("name", "xiaocan") let ret = await rdbStore.update(valueBucket, predicates); - await expect(1).assertEqual(ret); - await console.log(TAG + "update done: " + ret); + expect(1).assertEqual(ret); + console.log(TAG + "update done: " + ret); predicates = await new dataRdb.RdbPredicates("test") predicates.equalTo("age", 21) @@ -355,7 +355,7 @@ describe('rdbStoreUpdateTest', function () { try { expect(true).assertEqual(resultSet.goToFirstRow()) const name = await resultSet.getString(resultSet.getColumnIndex("name")) - await expect(nameStr).assertEqual(name); + expect(nameStr).assertEqual(name); } finally { resultSet.close() resultSet = null diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreDataChange.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreDataChange.test.js index 912f4ce8dc79aff981a9aecc61031ac4632f3bba..448be97232a290aa89d6eee062984befad3c83d4 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreDataChange.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreDataChange.test.js @@ -546,5 +546,69 @@ describe('RdbStoreDataChangeTest', function () { console.info(TAG + "************* testRdbStoreDataChange0011 end *************"); }) + /** + * @tc.name Normal case for multi observer + * @tc.number testRdbStoreOn0001 + * @tc.desc 1. Register and cancel registration concurrent testing + * + */ + it('testRdbStoreDataChange0011', 0, async function (done) { + console.info(TAG + "************* testRdbStoreOn0001 start *************"); + function observer() { + console.info(TAG + "observer1"); + }; + for (let i = 0; i < 500; ++i) { + rdbStore.on("concurrencyTest", true, observer) + rdbStore.emit("concurrencyTest"); + rdbStore.off("concurrencyTest", true, observer); + } + done(); + console.info(TAG + "************* testRdbStoreOn0001 end *************"); + }) + + /** + * @tc.name off parameters number error + * @tc.number testRdbStoreDataChange0012 + * @tc.desc UnRegister error parameters number test + * + */ + it('testRdbStoreDataChange0012', 0, async function (done) { + console.info(TAG + "************* testRdbStoreDataChange0012 start *************"); + function observer() { + console.info(TAG + "observer1"); + }; + try { + rdbStore.off("errorParametersNumberTest"); + expect(false).assertTrue() + } catch (err) { + console.error("off parameters error, err: code=" + err.code + " message=" + err.message) + expect(true).assertTrue() + } + done(); + console.info(TAG + "************* testRdbStoreDataChange0012 end *************"); + }) + + /** + * @tc.name on parameters number error + * @tc.number testRdbStoreDataChange0013 + * @tc.desc Register error parameters number test + * + */ + it('testRdbStoreDataChange0013', 0, async function (done) { + console.info(TAG + "************* testRdbStoreDataChange0013 start *************"); + function observer() { + console.info(TAG + "observer1"); + }; + try { + rdbStore.on("errorParametersNumberTest", true); + expect(false).assertTrue() + } catch (err) { + console.error("on parameters error, err: code=" + err.code + " message=" + err.message) + expect(true).assertTrue() + } + done(); + console.info(TAG + "************* testRdbStoreDataChange0013 end *************"); + }) + console.info(TAG + "*************Unit Test End*************"); }) diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreRdExecuteJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreRdExecuteJsunit.test.js index c303f9b39b692d8baac82b99c4572714edc757af..4682a6aae482cd6999a78f8df923d1beb318e052 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreRdExecuteJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreRdExecuteJsunit.test.js @@ -87,6 +87,72 @@ const vec10 = '[10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,3 '78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,' + '110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137]'; +const clstVec0 = '[0.12,-0.05,0.23,-0.17,0.08,0.31,-0.02,0.14,-0.11,0.25,0.03,-0.19,0.07,0.29,-0.08,0.16,0.21,-0.03,' + + '0.09,-0.14,0.27,0.05,-0.22,0.11,0.18,-0.07,0.13,-0.09,0.24,0.01,-0.16,0.04,0.12,-0.05,0.23,-0.17,0.08,0.31,-0.02,' + + '0.14,-0.11,0.25,0.03,-0.19,0.07,0.29,-0.08,0.16,0.21,-0.03,0.09,-0.14,0.27,0.05,-0.22,0.11,0.18,-0.07,0.13,-0.09,' + + '0.24,0.01,-0.16,0.04,0.12,-0.05,0.23,-0.17,0.08,0.31,-0.02,0.14,-0.11,0.25,0.03,-0.19,0.07,0.29,-0.08,0.16,0.21,' + + '-0.03,0.09,-0.14,0.27,0.05,-0.22,0.11,0.18,-0.07,0.13,-0.09,0.24,0.01,-0.16,0.04,0.12,-0.05,0.23,-0.17,0.08,0.31,' + + '-0.02,0.14,-0.11,0.25,0.03,-0.19,0.07,0.29,-0.08,0.16,0.21,-0.03,0.09,-0.14,0.27,0.05,-0.22,0.11,0.18,-0.07,0.13,' + + '-0.09,0.24,0.01,-0.16,0.04,0.12,-0.05,0.23,-0.17,0.08,0.31,-0.02,0.14,-0.11,0.25,0.03,-0.19,0.07,0.29,-0.08,0.16,' + + '0.21,-0.03,0.09,-0.14,0.27,0.05,-0.22,0.11,0.18,-0.07,0.13,-0.09,0.24,0.01,-0.16,0.04,0.12,-0.05,0.23,-0.17,0.08,' + + '0.31,-0.02,0.14,-0.11,0.25,0.03,-0.19,0.07,0.29,-0.08,0.16,0.21,-0.03,0.09,-0.14,0.27,0.05,-0.22,0.11,0.18,-0.07,' + + '0.13,-0.09,0.24,0.01,-0.16,0.04,0.12,-0.05,0.23,-0.17,0.08,0.31,-0.02,0.14,-0.11,0.25,0.03,-0.19,0.07,0.29,-0.08,' + + '0.16,0.21,-0.03,0.09,-0.14,0.27,0.05,-0.22,0.11,0.18,-0.07,0.13,-0.09,0.24,0.01,-0.16,0.04,0.12,-0.05,0.23,-0.17,' + + '0.08,0.31,-0.02,0.14,-0.11,0.25,0.03,-0.19,0.07,0.29,-0.08,0.16,0.21,-0.03,0.09,-0.14,0.27,0.05,-0.22,0.11,0.18,' + + '-0.07,0.13,-0.09,0.24,0.01,-0.16,0.04]'; +const clstVec1 = '[-0.08,0.15,-0.22,0.07,0.19,-0.03,0.11,-0.14,0.26,0.02,-0.18,0.09,0.13,-0.06,0.21,-0.11,0.04,0.17,' + + '-0.09,0.23,-0.15,0.08,0.12,-0.07,0.24,0.01,-0.19,0.05,0.16,-0.04,0.14,-0.12,-0.08,0.15,-0.22,0.07,0.19,-0.03,' + + '0.11,-0.14,0.26,0.02,-0.18,0.09,0.13,-0.06,0.21,-0.11,0.04,0.17,-0.09,0.23,-0.15,0.08,0.12,-0.07,0.24,0.01,-0.19,' + + '0.05,0.16,-0.04,0.14,-0.12,-0.08,0.15,-0.22,0.07,0.19,-0.03,0.11,-0.14,0.26,0.02,-0.18,0.09,0.13,-0.06,0.21,-0.11,' + + '0.04,0.17,-0.09,0.23,-0.15,0.08,0.12,-0.07,0.24,0.01,-0.19,0.05,0.16,-0.04,0.14,-0.12,-0.08,0.15,-0.22,0.07,0.19,' + + '-0.03,0.11,-0.14,0.26,0.02,-0.18,0.09,0.13,-0.06,0.21,-0.11,0.04,0.17,-0.09,0.23,-0.15,0.08,0.12,-0.07,0.24,0.01,' + + '-0.19,0.05,0.16,-0.04,0.14,-0.12,-0.08,0.15,-0.22,0.07,0.19,-0.03,0.11,-0.14,0.26,0.02,-0.18,0.09,0.13,-0.06,0.21,' + + '-0.11,0.04,0.17,-0.09,0.23,-0.15,0.08,0.12,-0.07,0.24,0.01,-0.19,0.05,0.16,-0.04,0.14,-0.12,-0.08,0.15,-0.22,0.07,' + + '0.19,-0.03,0.11,-0.14,0.26,0.02,-0.18,0.09,0.13,-0.06,0.21,-0.11,0.04,0.17,-0.09,0.23,-0.15,0.08,0.12,-0.07,0.24,' + + '0.01,-0.19,0.05,0.16,-0.04,0.14,-0.12,-0.08,0.15,-0.22,0.07,0.19,-0.03,0.11,-0.14,0.26,0.02,-0.18,0.09,0.13,-0.06,' + + '0.21,-0.11,0.04,0.17,-0.09,0.23,-0.15,0.08,0.12,-0.07,0.24,0.01,-0.19,0.05,0.16,-0.04,0.14,-0.12,-0.08,0.15,-0.22,' + + '0.07,0.19,-0.03,0.11,-0.14,0.26,0.02,-0.18,0.09,0.13,-0.06,0.21,-0.11,0.04,0.17,-0.09,0.23,-0.15,0.08,0.12,-0.07,' + + '0.24,0.01,-0.19,0.05,0.16,-0.04,0.14,-0.12]'; +const clstVec2 = '[0.15,-0.12,0.18,-0.09,0.22,0.04,-0.17,0.11,0.07,-0.14,0.23,-0.06,0.19,0.02,-0.21,0.08,0.13,-0.11,' + + '0.16,-0.07,0.24,0.03,-0.18,0.09,0.12,-0.13,0.17,-0.05,0.25,0.01,-0.19,0.07,0.15,-0.12,0.18,-0.09,0.22,0.04,-0.17,' + + '0.11,0.07,-0.14,0.23,-0.06,0.19,0.02,-0.21,0.08,0.13,-0.11,0.16,-0.07,0.24,0.03,-0.18,0.09,0.12,-0.13,0.17,-0.05,' + + '0.25,0.01,-0.19,0.07,0.15,-0.12,0.18,-0.09,0.22,0.04,-0.17,0.11,0.07,-0.14,0.23,-0.06,0.19,0.02,-0.21,0.08,0.13,' + + '-0.11,0.16,-0.07,0.24,0.03,-0.18,0.09,0.12,-0.13,0.17,-0.05,0.25,0.01,-0.19,0.07,0.15,-0.12,0.18,-0.09,0.22,0.04,' + + '-0.17,0.11,0.07,-0.14,0.23,-0.06,0.19,0.02,-0.21,0.08,0.13,-0.11,0.16,-0.07,0.24,0.03,-0.18,0.09,0.12,-0.13,0.17,' + + '-0.05,0.25,0.01,-0.19,0.07,0.15,-0.12,0.18,-0.09,0.22,0.04,-0.17,0.11,0.07,-0.14,0.23,-0.06,0.19,0.02,-0.21,0.08,' + + '0.13,-0.11,0.16,-0.07,0.24,0.03,-0.18,0.09,0.12,-0.13,0.17,-0.05,0.25,0.01,-0.19,0.07,0.15,-0.12,0.18,-0.09,0.22,' + + '0.04,-0.17,0.11,0.07,-0.14,0.23,-0.06,0.19,0.02,-0.21,0.08,0.13,-0.11,0.16,-0.07,0.24,0.03,-0.18,0.09,0.12,-0.13,' + + '0.17,-0.05,0.25,0.01,-0.19,0.07,0.15,-0.12,0.18,-0.09,0.22,0.04,-0.17,0.11,0.07,-0.14,0.23,-0.06,0.19,0.02,-0.21,' + + '0.08,0.13,-0.11,0.16,-0.07,0.24,0.03,-0.18,0.09,0.12,-0.13,0.17,-0.05,0.25,0.01,-0.19,0.07,0.15,-0.12,0.18,-0.09,' + + '0.22,0.04,-0.17,0.11,0.07,-0.14,0.23,-0.06,0.19,0.02,-0.21,0.08,0.13,-0.11,0.16,-0.07,0.24,0.03,-0.18,0.09,0.12,' + + '-0.13,0.17,-0.05,0.25,0.01,-0.19,0.07]'; +const clstVec3 = '[-0.21,0.08,0.14,-0.19,0.05,0.17,-0.12,0.23,-0.07,0.11,0.16,-0.14,0.09,0.22,-0.04,0.18,-0.11,0.13,' + + '0.15,-0.16,0.07,0.24,-0.02,0.19,-0.09,0.12,0.17,-0.13,0.08,0.21,-0.05,0.15,-0.21,0.08,0.14,-0.19,0.05,0.17,-0.12,' + + '0.23,-0.07,0.11,0.16,-0.14,0.09,0.22,-0.04,0.18,-0.11,0.13,0.15,-0.16,0.07,0.24,-0.02,0.19,-0.09,0.12,0.17,-0.13,' + + '0.08,0.21,-0.05,0.15,-0.21,0.08,0.14,-0.19,0.05,0.17,-0.12,0.23,-0.07,0.11,0.16,-0.14,0.09,0.22,-0.04,0.18,-0.11,' + + '0.13,0.15,-0.16,0.07,0.24,-0.02,0.19,-0.09,0.12,0.17,-0.13,0.08,0.21,-0.05,0.15,-0.21,0.08,0.14,-0.19,0.05,0.17,' + + '-0.12,0.23,-0.07,0.11,0.16,-0.14,0.09,0.22,-0.04,0.18,-0.11,0.13,0.15,-0.16,0.07,0.24,-0.02,0.19,-0.09,0.12,0.17,' + + '-0.13,0.08,0.21,-0.05,0.15,-0.21,0.08,0.14,-0.19,0.05,0.17,-0.12,0.23,-0.07,0.11,0.16,-0.14,0.09,0.22,-0.04,0.18,' + + '-0.11,0.13,0.15,-0.16,0.07,0.24,-0.02,0.19,-0.09,0.12,0.17,-0.13,0.08,0.21,-0.05,0.15,-0.21,0.08,0.14,-0.19,0.05,' + + '0.17,-0.12,0.23,-0.07,0.11,0.16,-0.14,0.09,0.22,-0.04,0.18,-0.11,0.13,0.15,-0.16,0.07,0.24,-0.02,0.19,-0.09,0.12,' + + '0.17,-0.13,0.08,0.21,-0.05,0.15,-0.21,0.08,0.14,-0.19,0.05,0.17,-0.12,0.23,-0.07,0.11,0.16,-0.14,0.09,0.22,-0.04,' + + '0.18,-0.11,0.13,0.15,-0.16,0.07,0.24,-0.02,0.19,-0.09,0.12,0.17,-0.13,0.08,0.21,-0.05,0.15,-0.21,0.08,0.14,-0.19,' + + '0.05,0.17,-0.12,0.23,-0.07,0.11,0.16,-0.14,0.09,0.22,-0.04,0.18,-0.11,0.13,0.15,-0.16,0.07,0.24,-0.02,0.19,-0.09,' + + '0.12,0.17,-0.13,0.08,0.21,-0.05,0.15]'; +const clstVec4 = '[0.07,-0.18,0.12,0.15,-0.09,0.21,-0.14,0.06,0.17,-0.11,0.19,-0.07,0.13,0.16,-0.12,0.08,0.22,' + + '-0.05,0.14,-0.17,0.09,0.18,-0.13,0.11,0.15,-0.08,0.2,-0.04,0.16,-0.14,0.1,0.19,0.07,-0.18,0.12,0.15,-0.09,' + + '0.21,-0.14,0.06,0.17,-0.11,0.19,-0.07,0.13,0.16,-0.12,0.08,0.22,-0.05,0.14,-0.17,0.09,0.18,-0.13,0.11,0.15,' + + '-0.08,0.2,-0.04,0.16,-0.14,0.1,0.19,0.07,-0.18,0.12,0.15,-0.09,0.21,-0.14,0.06,0.17,-0.11,0.19,-0.07,0.13,' + + '0.16,-0.12,0.08,0.22,-0.05,0.14,-0.17,0.09,0.18,-0.13,0.11,0.15,-0.08,0.2,-0.04,0.16,-0.14,0.1,0.19,0.07,' + + '-0.18,0.12,0.15,-0.09,0.21,-0.14,0.06,0.17,-0.11,0.19,-0.07,0.13,0.16,-0.12,0.08,0.22,-0.05,0.14,-0.17,0.09,' + + '0.18,-0.13,0.11,0.15,-0.08,0.2,-0.04,0.16,-0.14,0.1,0.19,0.07,-0.18,0.12,0.15,-0.09,0.21,-0.14,0.06,0.17,' + + '-0.11,0.19,-0.07,0.13,0.16,-0.12,0.08,0.22,-0.05,0.14,-0.17,0.09,0.18,-0.13,0.11,0.15,-0.08,0.2,-0.04,0.16,' + + '-0.14,0.1,0.19,0.07,-0.18,0.12,0.15,-0.09,0.21,-0.14,0.06,0.17,-0.11,0.19,-0.07,0.13,0.16,-0.12,0.08,0.22,' + + '-0.05,0.14,-0.17,0.09,0.18,-0.13,0.11,0.15,-0.08,0.2,-0.04,0.16,-0.14,0.1,0.19,0.07,-0.18,0.12,0.15,-0.09,' + + '0.21,-0.14,0.06,0.17,-0.11,0.19,-0.07,0.13,0.16,-0.12,0.08,0.22,-0.05,0.14,-0.17,0.09,0.18,-0.13,0.11,0.15,' + + '-0.08,0.2,-0.04,0.16,-0.14,0.1,0.19,0.07,-0.18,0.12,0.15,-0.09,0.21,-0.14,0.06,0.17,-0.11,0.19,-0.07,0.13,' + + '0.16,-0.12,0.08,0.22,-0.05,0.14,-0.17,0.09,0.18,-0.13,0.11,0.15,-0.08,0.2,-0.04,0.16,-0.14,0.1,0.19]'; + let isSupportVector = false; let store; let context = ability_featureAbility.getContext() @@ -813,5 +879,211 @@ describe('rdbStoreRdExecuteTest', function () { console.log(TAG + "************* testVectorSubSelectFailed0009 end *************"); }); + /** + * @tc.name testVectorClusterIndexSuccess0001 + * @tc.number SUB_DISTRIBUTEDDATAMGR_RDB_JSVectorStore_ClusterIndex_success_0001 + * @tc.desc create cluster index and insert 10 vec, then query from table and check. + */ + it('testVectorClusterInsertSuccess0001', 0, async function () { + console.log(TAG + "************* testVectorClusterInsertSuccess0001 start *************"); + if (!isSupportVector) { + expect(isSupportVector).assertFalse(); + return; + } + + try { + await store?.execute("create table cluster_vec_10 (id int PRIMARY KEY, repr floatvector(256));"); + } catch (e) { + console.error(TAG + `create table cluster_vec_10 failed. errcode: ${e.code}`); + } + + try { + await store?.execute("create index cluster_index on cluster_vec_10 using IVFCLUSTER(repr COSINE);"); + } catch (e) { + console.error(TAG + `create cluster index failed. errcode: ${e.code}`); + } + + try { + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (0, '${clstVec0}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (1, '${clstVec1}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (2, '${clstVec2}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (3, '${clstVec3}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (4, '${clstVec4}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (5, '${clstVec0}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (6, '${clstVec1}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (7, '${clstVec2}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (8, '${clstVec3}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (9, '${clstVec4}');`); + } catch (e) { + console.error(TAG + `insert face vector in table failed. errcode: ${e.code}`); + } + + const selectSql = `select id, repr, CLUSTER_ID(repr) from cluster_vec_10;`; + const result = await store?.querySql(selectSql); + expect(result?.rowCount).assertEqual(10); + try { + while (result?.goToNextRow()) { + let id = result.getValue(0); + let tmpVec = result.getValue(1); + let clstId = result.getValue(2); + console.log(TAG + "id: " + id?.toString() + "clstId: " + clstId?.toString()); + } + result?.getValue(10); + expect().assertFail(); + result?.close(); + } catch (e) { + console.error(TAG + `testVectorClusterInsertSuccess0001 failed. err: ${JSON.stringify(e)}`); + result?.close(); + expect(14800012 == e.code).assertTrue(); + } + console.log(TAG + "************* testVectorClusterInsertSuccess0001 end *************"); + }); + + /** + * @tc.name testVectorClusterIndexSuccess0002 + * @tc.number SUB_DISTRIBUTEDDATAMGR_RDB_JSVectorStore_ClusterIndex_success_0002 + * @tc.desc insert 10 vec, run cluster, then query from table and check. + */ + it('testVectorClusterIndexSuccess0002', 0, async function () { + console.log(TAG + "************* testVectorClusterIndexSuccess0002 start *************"); + if (!isSupportVector) { + expect(isSupportVector).assertFalse(); + return; + } + + try { + await store?.execute("create table cluster_vec_10 (id int PRIMARY KEY, repr floatvector(256));"); + } catch (e) { + console.error(TAG + `create table cluster_vec_10 failed. errcode: ${e.code}`); + } + + try { + await store?.execute("create index cluster_index on cluster_vec_10 using IVFCLUSTER(repr COSINE);"); + } catch (e) { + console.error(TAG + `create cluster index failed. errcode: ${e.code}`); + } + + try { + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (0, '${clstVec0}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (1, '${clstVec1}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (2, '${clstVec2}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (3, '${clstVec3}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (4, '${clstVec4}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (5, '${clstVec0}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (6, '${clstVec1}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (7, '${clstVec2}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (8, '${clstVec3}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (9, '${clstVec4}');`); + } catch (e) { + console.error(TAG + `insert face vector in table failed. errcode: ${e.code}`); + } + + try { + await store?.execute("PRAGMA CLUSTER_RUN cluster_vec_10.cluster_index;"); + await new Promise(resolve => setTimeout(resolve, 50)); // wait 50ms for cluster build exec + } catch (e) { + console.error(TAG + `run cluster build failed. errcode: ${e.code}`); + } + + const selectSql = `select id, repr, CLUSTER_ID(repr) from cluster_vec_10;`; + const result = await store?.querySql(selectSql); + expect(result?.rowCount).assertEqual(10); + try { + while (result?.goToNextRow()) { + let id = result.getValue(0); + let tmpVec = result.getValue(1); + let clstId = result.getValue(2); + console.log(TAG + "id: " + id?.toString() + "clstId: " + clstId?.toString()); + } + result?.getValue(10); + expect().assertFail(); + result?.close(); + } catch (e) { + console.error(TAG + `testVectorClusterIndexSuccess0002 failed. err: ${JSON.stringify(e)}`); + result?.close(); + expect(14800012 == e.code).assertTrue(); + } + console.log(TAG + "************* testVectorClusterIndexSuccess0002 end *************"); + }); + + /** + * @tc.name testVectorClusterIndexSuccess0003 + * @tc.number SUB_DISTRIBUTEDDATAMGR_RDB_JSVectorStore_ClusterIndex_success_0003 + * @tc.desc insert 5 vec, run cluster, then insert 5 vec, run cluster again. + */ + it('testVectorClusterIndexSuccess0003', 0, async function () { + console.log(TAG + "************* testVectorClusterIndexSuccess0003 start *************"); + if (!isSupportVector) { + expect(isSupportVector).assertFalse(); + return; + } + + try { + await store?.execute("create table cluster_vec_10 (id int PRIMARY KEY, repr floatvector(256));"); + } catch (e) { + console.error(TAG + `create table cluster_vec_10 failed. errcode: ${e.code}`); + } + + try { + await store?.execute("create index cluster_index on using IVFCLUSTER(repr COSINE);"); + } catch (e) { + console.error(TAG + `create cluster index failed. errcode: ${e.code}`); + } + + try { + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (0, '${clstVec0}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (1, '${clstVec1}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (2, '${clstVec2}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (3, '${clstVec3}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (4, '${clstVec4}');`); + } catch (e) { + console.error(TAG + `insert face vector in table failed. errcode: ${e.code}`); + } + + try { + await store?.execute("PRAGMA CLUSTER_RUN cluster_vec_10.cluster_index;"); + await new Promise(resolve => setTimeout(resolve, 50)); // wait 50ms for cluster build exec + } catch (e) { + console.error(TAG + `run cluster build failed. errcode: ${e.code}`); + } + + try { + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (5, '${clstVec0}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (6, '${clstVec1}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (7, '${clstVec2}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (8, '${clstVec3}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (9, '${clstVec4}');`); + } catch (e) { + console.error(TAG + `insert face vector in table failed. errcode: ${e.code}`); + } + + try { + await store?.execute("PRAGMA CLUSTER_RUN cluster_vec_10.cluster_index;"); + await new Promise(resolve => setTimeout(resolve, 50)); // wait 50ms for cluster build exec + } catch (e) { + console.error(TAG + `run cluster build failed. errcode: ${e.code}`); + } + + const selectSql = `select id, repr, CLUSTER_ID(repr) from cluster_vec_10;`; + const result = await store?.querySql(selectSql); + expect(result?.rowCount).assertEqual(10); + try { + while (result?.goToNextRow()) { + let id = result.getValue(0); + let tmpVec = result.getValue(1); + let clstId = result.getValue(2); + console.log(TAG + "id: " + id?.toString() + "clstId: " + clstId?.toString()); + } + result?.getValue(10); + expect().assertFail(); + result?.close(); + } catch (e) { + console.error(TAG + `testVectorClusterIndexSuccess0003 failed. err: ${JSON.stringify(e)}`); + result?.close(); + expect(14800012 == e.code).assertTrue(); + } + console.log(TAG + "************* testVectorClusterIndexSuccess0003 end *************"); + }); + console.log(TAG + "*************Unit Test End*************"); }) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreReadOnlyJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreReadOnlyJsunit.test.js index ede3df40d1cd526566b33aa9c2f2d7ed53d0da7d..b904e98a4466bb139d256856f74c07fd5082e892 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreReadOnlyJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreReadOnlyJsunit.test.js @@ -51,6 +51,7 @@ describe('rdbStoreReadOnlyTest', function () { try { await relationalStore.deleteRdbStore(context, STORE_CONFIG); let rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore === null).assertFalse(); const CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; @@ -69,6 +70,7 @@ describe('rdbStoreReadOnlyTest', function () { beforeEach(async function () { store = await relationalStore.getRdbStore(context, STORE_CONFIG2); + expect(rdbStore === null).assertFalse(); console.info(TAG + 'beforeEach'); }) diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetJsunit.test.js index 9607f4210965885cfdfa5bd67dea663f34f9ef8e..abc734771417a074249469e252a9cca7fe7c33ed 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetJsunit.test.js @@ -812,28 +812,6 @@ describe('rdbResultSetTest', function () { console.log(TAG + "************* testGoToFirstRow0003 end *************"); }) - /** - * @tc.name resultSet goToFirstRow with no result test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0103 - * @tc.desc resultSet goToFirstRow with no result test - */ - it('testGoToFirstRow0004', 0, async function (done) { - console.log(TAG + "************* testGoToFirstRow0004 start *************"); - - let predicates = await new data_relationalStore.RdbPredicates("test") - let resultSet = await rdbStore.query(predicates) - resultSet.close() - try { - resultSet.goToFirstRow() - } catch (e) { - expect(e.code).assertFail("14800014"); - } - - resultSet = null - done(); - console.log(TAG + "************* testGoToFirstRow0004 end *************"); - }) - /** * @tc.name resultSet goToLastRow test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0110 @@ -891,27 +869,6 @@ describe('rdbResultSetTest', function () { }) - /** - * @tc.name resultSet goToLastRow with no result test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0113 - * @tc.desc resultSet goToLastRow with no result test - */ - it('testGoToLastRow0004', 0, async function (done) { - console.log(TAG + "************* testGoToLastRow0004 start *************"); - let predicates = await new data_relationalStore.RdbPredicates("test") - predicates.equalTo("name", "wangwu"); - let resultSet = await rdbStore.query(predicates) - resultSet.close() - try { - resultSet.goToLastRow() - } catch (error) { - expect(error.code).assertEqual("14800014") - } - resultSet = null; - done(); - console.log(TAG + "************* testGoToLastRow0004 end *************"); - }) - /** * @tc.name resultSet goToNextRow test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0120 @@ -997,29 +954,6 @@ describe('rdbResultSetTest', function () { }) - /** - * @tc.name resultSet goToNextRow with no result test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0124 - * @tc.desc resultSet goToNextRow with no result test - */ - it('testGoToNextRow0005', 0, async function (done) { - console.log(TAG + "************* testGoToNextRow0005 start *************"); - - let predicates = await new data_relationalStore.RdbPredicates("test") - let resultSet = await rdbStore.query(predicates) - resultSet.close() - try { - resultSet.goToNextRow() - } catch (error) { - expect(error.code).assertEqual("14800014") - } - - resultSet = null; - done(); - console.log(TAG + "************* testGoToNextRow0005 end *************"); - - }) - /** * @tc.name resultSet goToPreviousRow test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0130 @@ -1104,28 +1038,6 @@ describe('rdbResultSetTest', function () { }) - /** - * @tc.name resultSet goToPreviousRow with no result test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0134 - * @tc.desc resultSet goToPreviousRow with no result test - */ - it('testGoToPreviousRow0005', 0, async function (done) { - console.log(TAG + "************* testGoToPreviousRow0005 start *************"); - - let predicates = await new data_relationalStore.RdbPredicates("test") - let resultSet = await rdbStore.query(predicates) - resultSet.close() - try { - resultSet.goToPreviousRow() - } catch (error) { - expect(error).assertEqual("14800014") - } - resultSet = null; - done(); - console.log(TAG + "************* testGoToPreviousRow0005 end *************"); - - }) - /** * @tc.name resultSet goTo test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0140 @@ -1215,31 +1127,6 @@ describe('rdbResultSetTest', function () { }) - /** - * @tc.name resultSet goTo after last row test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0144 - * @tc.desc resultSet goTo after last row test - */ - it('testGoTo0005', 0, async function (done) { - console.log(TAG + "************* testGoTo0005 start *************"); - - let predicates = await new data_relationalStore.RdbPredicates("test") - predicates.equalTo("name", "wangwu"); - let resultSet = await rdbStore.query(predicates) - resultSet.close() - - try { - resultSet.goTo(1) - } catch (error) { - expect(error.code).assertEqual("14800014") - } - - resultSet = null; - done(); - console.log(TAG + "************* testGoTo0005 end *************"); - - }) - /** * @tc.name resultSet goToRow test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0150 @@ -1308,31 +1195,6 @@ describe('rdbResultSetTest', function () { }) - /** - * @tc.name resultSet goToRow with no result test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0154 - * @tc.desc resultSet goToRow with no result test - */ - it('testGoToRow0005', 0, async function (done) { - console.log(TAG + "************* testGoToRow0005 start *************"); - - let predicates = await new data_relationalStore.RdbPredicates("test") - predicates.equalTo("name", "wangwu"); - let resultSet = await rdbStore.query(predicates) - - resultSet.close() - try { - resultSet.goToRow(1) - } catch (error) { - expect(error.code).assertEqual("14800014") - } - - resultSet = null; - done(); - console.log(TAG + "************* testGoToRow0005 end *************"); - - }) - /** * @tc.name resultSet goToRow after last row test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0153 @@ -1853,28 +1715,6 @@ describe('rdbResultSetTest', function () { }) - /** - * @tc.name resultSet getColumnIndex test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0204 - * @tc.desc resultSet getColumnIndex test - */ - it('testGetColumnIndex0005', 0, async function (done) { - console.log(TAG + "************* testGetColumnIndex0005 start *************"); - - let predicates = await new data_relationalStore.RdbPredicates("test") - let resultSet = await rdbStore.query(predicates) - resultSet.close() - try { - resultSet.getColumnIndex("dataX") - } catch (error) { - expect(error.code).assertEqual("14800014") - } - resultSet = null; - done(); - console.log(TAG + "************* testGetColumnIndex0005 end *************"); - - }) - /** * @tc.name resultSet getColumnName test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0210 @@ -1959,28 +1799,6 @@ describe('rdbResultSetTest', function () { }) - /** - * @tc.name resultSet getColumnName test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0214 - * @tc.desc resultSet getColumnName test - */ - it('testGetColumnName0005', 0, async function (done) { - console.log(TAG + "************* testGetColumnName0005 start *************"); - - let predicates = await new data_relationalStore.RdbPredicates("test") - let resultSet = await rdbStore.query(predicates) - resultSet.close() - try { - resultSet.getColumnName(10) - } catch (error) { - expect(error.code).assertEqual("14800014") - } - resultSet = null; - done(); - console.log(TAG + "************* testGetColumnName0005 end *************"); - - }) - /** * @tc.name resultSet close test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0220 diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreStatisticsJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreStatisticsJsunit.test.js index 79318b0adeb3eafd149246e86232be209bba2f79..1e87c3a3088259d5e0642bc5689ea8e7e9cf4c09 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreStatisticsJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreStatisticsJsunit.test.js @@ -280,7 +280,7 @@ describe('RdbStoreStatisticsTest', function () { console.info(TAG + "************* testRdbStoreStatistics0006 start *************"); try { rdbStore.on('statistics', (SqlExeInfo) => { - expect().assertFail(); + expect('INSERT INTO test(age,blobType,salary) VALUES (?,?,?)').assertEqual(SqlExeInfo.sql[0]); done(); }) } catch (err) { @@ -300,7 +300,6 @@ describe('RdbStoreStatisticsTest', function () { } catch (error) { expect(14800032).assertEqual(error.code); console.error(TAG + `insert fail, code:${error.code}, message: ${error.message}`); - done(); } console.info(TAG + "************* testRdbStoreStatistics0006 end *************"); }) diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransInsertJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransInsertJsunit.test.js deleted file mode 100644 index 4326a9342338c23fe0cecb24fcb9d420f957e41d..0000000000000000000000000000000000000000 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransInsertJsunit.test.js +++ /dev/null @@ -1,945 +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. - */ - -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' -import data_relationalStore from '@ohos.data.relationalStore' -import ability_featureAbility from '@ohos.ability.featureAbility' - -var context = ability_featureAbility.getContext() - -const TAG = "[RELATIONAL_STORE_TRANSACTION_JSKITS_TEST]" -const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + - "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; - -const STORE_CONFIG = { - name: "TransactionTest.db", - securityLevel: data_relationalStore.SecurityLevel.S3, -} - -var rdbStore = undefined; - -describe('rdbStoreTransactionJsunitTest', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll') - rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); - await rdbStore.executeSql(CREATE_TABLE_TEST, null); - }) - - beforeEach(async function () { - console.info(TAG + 'beforeEach') - - }) - - afterEach(async function () { - console.info(TAG + 'afterEach') - await rdbStore.executeSql("DELETE FROM test"); - }) - - afterAll(async function () { - console.info(TAG + 'afterAll') - rdbStore = null - await data_relationalStore.deleteRdbStore(context, "TransactionTest.db"); - }) - - console.log(TAG + "*************Unit Test Begin*************"); - - - it('testRdbTransInsert0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsert0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsert0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsert0001 failed"); - } - - console.log(TAG + "************* testRdbTransInsert0001 end *************"); - done(); - }) - - it('testRdbTransInsert0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsert0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsert0002 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsert0002 failed"); - } - - console.log(TAG + "************* testRdbTransInsert0002 end *************"); - done(); - }) - - it('testRdbTransInsert0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsert0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsert0003 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsert0003 failed"); - } - - console.log(TAG + "************* testRdbTransInsert0003 end *************"); - done(); - }) - - it('testRdbTransInsert0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsert0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsert0011 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsert0011 failed"); - } - - console.log(TAG + "************* testRdbTransInsert0011 end *************"); - done(); - }) - - it('testRdbTransInsert0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsert0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsert0012 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsert0012 failed"); - } - - console.log(TAG + "************* testRdbTransInsert0012 end *************"); - done(); - }) - - it('testRdbTransInsert0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsert0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsert0013 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsert0013 failed"); - } - - console.log(TAG + "************* testRdbTransInsert0013 end *************"); - done(); - }) - - it('testRdbTransInsertSync0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsertSync0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = rdbTrans.insertSync("test", valueBucket); - expect(1).assertEqual(rowId); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsertSync0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsertSync0001 failed"); - } - - console.log(TAG + "************* testRdbTransInsertSync0001 end *************"); - done(); - }) - - it('testRdbTransInsertSync0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsertSync0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = rdbTrans.insertSync("test", valueBucket); - expect(1).assertEqual(rowId); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsertSync0002 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsertSync0002 failed"); - } - - console.log(TAG + "************* testRdbTransInsertSync0002 end *************"); - done(); - }) - - it('testRdbTransInsertSync0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsertSync0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = rdbTrans.insertSync("test", valueBucket); - expect(1).assertEqual(rowId); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsertSync0003 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsertSync0003 failed"); - } - - console.log(TAG + "************* testRdbTransInsertSync0003 end *************"); - done(); - }) - - it('testRdbTransInsertSync0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsertSync0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = rdbTrans.insertSync("test", valueBucket); - expect(1).assertEqual(rowId); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsertSync0011 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsertSync0011 failed"); - } - - console.log(TAG + "************* testRdbTransInsertSync0011 end *************"); - done(); - }) - - it('testRdbTransInsertSync0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsertSync0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = rdbTrans.insertSync("test", valueBucket); - expect(1).assertEqual(rowId); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsertSync0012 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsertSync0012 failed"); - } - - console.log(TAG + "************* testRdbTransInsertSync0012 end *************"); - done(); - }) - - it('testRdbTransInsertSync0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsertSync0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = rdbTrans.insertSync("test", valueBucket); - expect(1).assertEqual(rowId); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsertSync0013 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsertSync0013 failed"); - } - - console.log(TAG + "************* testRdbTransInsertSync0013 end *************"); - done(); - }) - - it('testRdbTransBatchInsert0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsert0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = await rdbTrans.batchInsert("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsert0001 result count " + resultSet.rowCount); - expect(100).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsert0001 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsert0001 end *************"); - done(); - }) - - it('testRdbTransBatchInsert0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsert0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = await rdbTrans.batchInsert("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsert0002 result count " + resultSet.rowCount); - expect(100).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsert0002 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsert0002 end *************"); - done(); - }) - - it('testRdbTransBatchInsert0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsert0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = await rdbTrans.batchInsert("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsert0003 result count " + resultSet.rowCount); - expect(100).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsert0003 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsert0003 end *************"); - done(); - }) - - it('testRdbTransBatchInsert0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsert0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = await rdbTrans.batchInsert("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsert0011 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsert0011 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsert0011 end *************"); - done(); - }) - - it('testRdbTransBatchInsert0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsert0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = await rdbTrans.batchInsert("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsert0012 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsert0012 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsert0012 end *************"); - done(); - }) - - it('testRdbTransBatchInsert0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsert0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = await rdbTrans.batchInsert("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsert0013 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsert0013 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsert0013 end *************"); - done(); - }) - - it('testRdbTransBatchInsertSync0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsertSync0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsertSync0001 result count " + resultSet.rowCount); - expect(100).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsertSync0001 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsertSync0001 end *************"); - done(); - }) - - it('testRdbTransBatchInsertSync0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsertSync0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsertSync0002 result count " + resultSet.rowCount); - expect(100).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsertSync0002 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsertSync0002 end *************"); - done(); - }) - - it('testRdbTransBatchInsertSync0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsertSync0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsertSync0003 result count " + resultSet.rowCount); - expect(100).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsertSync0003 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsertSync0003 end *************"); - done(); - }) - - it('testRdbTransBatchInsertSync0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsertSync0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsertSync0011 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsertSync0011 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsertSync0011 end *************"); - done(); - }) - - it('testRdbTransBatchInsertSync0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsertSync0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsertSync0012 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsertSync0012 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsertSync0012 end *************"); - done(); - }) - - it('testRdbTransBatchInsertSync0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsertSync0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsertSync0013 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsertSync0013 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsertSync0013 end *************"); - done(); - }) - - it('testRdbTransUpdate0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdate0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbTrans.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.update({ age: 20 }, updatePredicates); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdate0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(20); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdate0001 failed"); - } - - console.log(TAG + "************* testRdbTransUpdate0001 end *************"); - done(); - }) - - it('testRdbTransUpdate0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdate0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbTrans.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.update({ age: 20 }, updatePredicates); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdate0002 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(20); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdate0002 failed"); - } - - console.log(TAG + "************* testRdbTransUpdate0002 end *************"); - done(); - }) - - it('testRdbTransUpdate0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdate0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbTrans.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.update({ age: 20 }, updatePredicates); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdate0003 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(20); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdate0003 failed"); - } - - console.log(TAG + "************* testRdbTransUpdate0003 end *************"); - done(); - }) - - console.log(TAG + "*************Unit Test End*************"); -}) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransJsunit.test.js deleted file mode 100644 index 4d150faa36760a0a8c656da683f46342d6fa0045..0000000000000000000000000000000000000000 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransJsunit.test.js +++ /dev/null @@ -1,1986 +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. - */ - -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' -import data_relationalStore from '@ohos.data.relationalStore' -import ability_featureAbility from '@ohos.ability.featureAbility' - -var context = ability_featureAbility.getContext() - -const TAG = "[RELATIONAL_STORE_TRANSACTION_JSKITS_TEST]" -const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + - "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; - -const STORE_CONFIG = { - name: "TransactionTest.db", - securityLevel: data_relationalStore.SecurityLevel.S3, -} - -var rdbStore = undefined; - -async function insertInThread(context, transType, insertCount = 1) { - const TAG = "[RELATIONAL_STORE_JS_KITS_TEST]" - let rdbTrans; - try { - rdbTrans = await rdbStore.createTransaction({ - transactionType: transType - }); - console.log(TAG + 'insertInThread after createTrans'); - - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(insertCount).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }); - const resultCount = await rdbTrans.batchInsert("test", valueBuckets); - await rdbTrans.commit(); - console.log(TAG + 'insertInThread after commit'); - return resultCount; - } catch (err) { - if (rdbTrans) { - rdbTrans.rollback(); - } - console.error(TAG + "************* testRdbTransInsert error thread insert *************"); - console.error(TAG + JSON.stringify(err)); - return err.code; - } -} - -async function queryInThread(context, transType, querySql) { - const TAG = "[RELATIONAL_STORE_JS_KITS_TEST]" - let rdbTrans; - try { - rdbTrans = await rdbStore.createTransaction({ - transactionType: transType - }); - - const resultSet = await rdbTrans.querySql(querySql); - const rowCount = resultSet.rowCount; - - await rdbTrans.commit(); - return rowCount; - } catch (err) { - if (rdbTrans) { - rdbTrans.rollback(); - } - console.error(TAG + "************* testRdbTransInsert error thread insert *************"); - console.error(TAG + JSON.stringify(err)); - return err.code; - } -} - -describe('rdbStoreTransactionJsunitTest', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll') - rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); - await rdbStore.executeSql(CREATE_TABLE_TEST, null); - }) - - beforeEach(async function () { - console.info(TAG + 'beforeEach') - - }) - - afterEach(async function () { - console.info(TAG + 'afterEach') - await rdbStore.executeSql("DELETE FROM test"); - }) - - afterAll(async function () { - console.info(TAG + 'afterAll') - rdbStore = null - await data_relationalStore.deleteRdbStore(context, "TransactionTest.db"); - }) - - console.log(TAG + "*************Unit Test Begin*************"); - - it('testRdbTransUpdate0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdate0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbStore.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.update({ age: 20 }, updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdate0011 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(18); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdate0011 failed"); - } - - console.log(TAG + "************* testRdbTransUpdate0011 end *************"); - done(); - }) - - it('testRdbTransUpdate0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdate0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbStore.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.update({ age: 20 }, updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdate0012 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(18); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdate0012 failed"); - } - - console.log(TAG + "************* testRdbTransUpdate0012 end *************"); - done(); - }) - - it('testRdbTransUpdate0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdate0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbStore.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.update({ age: 20 }, updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdate0013 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(18); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdate0013 failed"); - } - - console.log(TAG + "************* testRdbTransUpdate0013 end *************"); - done(); - }) - - it('testRdbTransUpdateSync0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdateSync0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbTrans.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - rdbTrans.updateSync({ age: 20 }, updatePredicates); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdateSync0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(20); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdateSync0001 failed"); - } - - console.log(TAG + "************* testRdbTransUpdateSync0001 end *************"); - done(); - }) - - it('testRdbTransUpdateSync0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdateSync0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbTrans.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - rdbTrans.updateSync({ age: 20 }, updatePredicates); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdateSync0002 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(20); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdateSync0002 failed"); - } - - console.log(TAG + "************* testRdbTransUpdateSync0002 end *************"); - done(); - }) - - it('testRdbTransUpdateSync0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdateSync0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbTrans.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - rdbTrans.updateSync({ age: 20 }, updatePredicates); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdateSync0003 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(20); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdateSync0003 failed"); - } - - console.log(TAG + "************* testRdbTransUpdateSync0003 end *************"); - done(); - }) - - it('testRdbTransUpdateSync0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdateSync0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbStore.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - rdbTrans.updateSync({ age: 20 }, updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdateSync0011 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(18); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdateSync0011 failed"); - } - - console.log(TAG + "************* testRdbTransUpdateSync0011 end *************"); - done(); - }) - - it('testRdbTransUpdateSync0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdateSync0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbStore.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - rdbTrans.updateSync({ age: 20 }, updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdateSync0012 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(18); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdateSync0012 failed"); - } - - console.log(TAG + "************* testRdbTransUpdateSync0012 end *************"); - done(); - }) - - it('testRdbTransUpdateSync0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdateSync0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbStore.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - rdbTrans.updateSync({ age: 20 }, updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdateSync0013 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(18); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdateSync0013 failed"); - } - - console.log(TAG + "************* testRdbTransUpdateSync0013 end *************"); - done(); - }) - - it('testRdbTransDelete0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransDelete0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = await rdbTrans.delete(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDelete0001 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDelete0001 failed"); - } - - console.log(TAG + "************* testRdbTransDelete0001 end *************"); - done(); - }) - - it('testRdbTransDelete0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransDelete0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = await rdbTrans.delete(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDelete0002 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDelete0002 failed"); - } - - console.log(TAG + "************* testRdbTransDelete0002 end *************"); - done(); - }) - - it('testRdbTransDelete0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransDelete0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = await rdbTrans.delete(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDelete0003 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDelete0003 failed"); - } - - console.log(TAG + "************* testRdbTransDelete0003 end *************"); - done(); - }) - - it('testRdbTransDelete0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransDelete0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.delete(updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDelete0011 result count " + resultSet.rowCount); - expect(3).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDelete0011 failed"); - } - - console.log(TAG + "************* testRdbTransDelete0011 end *************"); - done(); - }) - - it('testRdbTransDelete0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransDelete0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.delete(updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDelete0012 result count " + resultSet.rowCount); - expect(3).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDelete0012 failed"); - } - - console.log(TAG + "************* testRdbTransDelete0012 end *************"); - done(); - }) - - it('testRdbTransDelete0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransDelete0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.delete(updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDelete0013 result count " + resultSet.rowCount); - expect(3).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDelete0013 failed"); - } - - console.log(TAG + "************* testRdbTransDelete0013 end *************"); - done(); - }) - - it('testRdbTransDeleteSync0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransDeleteSync0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = rdbTrans.deleteSync(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDeleteSync0001 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDeleteSync0001 failed"); - } - - console.log(TAG + "************* testRdbTransDeleteSync0001 end *************"); - done(); - }) - - it('testRdbTransDeleteSync0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransDeleteSync0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = rdbTrans.deleteSync(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDeleteSync0002 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDeleteSync0002 failed"); - } - - console.log(TAG + "************* testRdbTransDeleteSync0002 end *************"); - done(); - }) - - it('testRdbTransDeleteSync0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransDeleteSync0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = rdbTrans.deleteSync(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDeleteSync0003 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDeleteSync0003 failed"); - } - - console.log(TAG + "************* testRdbTransDeleteSync0003 end *************"); - done(); - }) - - it('testRdbTransDeleteSync0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransDeleteSync0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = rdbTrans.deleteSync(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDeleteSync0011 result count " + resultSet.rowCount); - expect(3).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDeleteSync0011 failed"); - } - - console.log(TAG + "************* testRdbTransDeleteSync0011 end *************"); - done(); - }) - - it('testRdbTransDeleteSync0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransDeleteSync0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = rdbTrans.deleteSync(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDeleteSync0012 result count " + resultSet.rowCount); - expect(3).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDeleteSync0012 failed"); - } - - console.log(TAG + "************* testRdbTransDeleteSync0012 end *************"); - done(); - }) - - it('testRdbTransDeleteSync0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransDeleteSync0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = rdbTrans.deleteSync(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDeleteSync0013 result count " + resultSet.rowCount); - expect(3).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDeleteSync0013 failed"); - } - - console.log(TAG + "************* testRdbTransDeleteSync0013 end *************"); - done(); - }) - - it('testRdbTransQuery0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransQuery0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbTrans.query(predicates); - console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - await rdbTrans.commit(); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransQuery0001 failed"); - } - - console.log(TAG + "************* testRdbTransQuery0001 end *************"); - done(); - }) - - it('testRdbTransQuery0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransQuery0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbTrans.query(predicates); - console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - await rdbTrans.commit(); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransQuery0002 failed"); - } - - console.log(TAG + "************* testRdbTransQuery0002 end *************"); - done(); - }) - - it('testRdbTransQuery0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransQuery0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbTrans.query(predicates); - console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - await rdbTrans.commit(); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransQuery0003 failed"); - } - - console.log(TAG + "************* testRdbTransQuery0003 end *************"); - done(); - }) - - it('testRdbTransQuery0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransQuery0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbTrans.querySync(predicates); - console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - await rdbTrans.commit(); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransQuery0011 failed"); - } - - console.log(TAG + "************* testRdbTransQuery0011 end *************"); - done(); - }) - - it('testRdbTransQuery0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransQuery0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbTrans.querySync(predicates); - console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - await rdbTrans.commit(); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransQuery0012 failed"); - } - - console.log(TAG + "************* testRdbTransQuery0012 end *************"); - done(); - }) - - it('testRdbTransQuery0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransQuery0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbTrans.querySync(predicates); - console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - await rdbTrans.commit(); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransQuery0013 failed"); - } - - console.log(TAG + "************* testRdbTransQuery0013 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0001 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0001 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0001 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0002 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0002 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0002 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0003 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0003 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0003 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0004', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0004 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - console.log(TAG + "before second trans create"); - const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); - console.log(TAG + "after second trans create"); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - console.log(TAG + "before query predicates create"); - let predicates = new data_relationalStore.RdbPredicates("test"); - console.log(TAG + "after query predicates create"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0004 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0004 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0004 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0005', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0005 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0005 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0005 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0005 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0006', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0006 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0006 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0006 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0006 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0007', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0007 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0007 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0007 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0007 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0008', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0008 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await insertInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 10); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0008 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0008 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0008 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0009', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0009 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await insertInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 10); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0009 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0009 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0009 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const rowCount = await queryInThread(context, data_relationalStore.TransactionType.DEFERRED, 'select * from test'); - expect(rowCount).assertEqual(0); - - await rdbTrans.commit(); - - { - const rowCount = await queryInThread(context, data_relationalStore.TransactionType.DEFERRED, 'select * from test'); - expect(rowCount).assertEqual(10); - } - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0001 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0001 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0001 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const rowCount = await queryInThread(context, data_relationalStore.TransactionType.DEFERRED, 'select * from test'); - expect(rowCount).assertEqual(0); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0002 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0002 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0002 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - - await rdbStore.batchInsert('test', valueBuckets); - - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const rowCount = await queryInThread(context, data_relationalStore.TransactionType.DEFERRED, 'select * from test'); - expect(rowCount).assertEqual(10); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0003 result count " + resultSet.rowCount); - expect(20).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0003 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0003 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0004', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0004 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await queryInThread(context, data_relationalStore.TransactionType.IMMEDIATE, 'select * from test'); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0004 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0004 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0004 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0005', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0005 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await queryInThread(context, data_relationalStore.TransactionType.IMMEDIATE, 'select * from test'); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0005 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0005 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0005 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0006', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0006 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await queryInThread(context, data_relationalStore.TransactionType.IMMEDIATE, 'select * from test'); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0006 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0006 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0006 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0007', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0007 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await queryInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 'select * from test'); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0007 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0007 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0007 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0008', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0008 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await queryInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 'select * from test'); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0008 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0008 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0008 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0009', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0009 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await queryInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 'select * from test'); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0009 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0009 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0009 end *************"); - done(); - }) - - /** - * @tc.name rdb transaction insert test - * @tc.number testRdbTransactionInsert0001 - * @tc.desc rdb transaction insert & commit, the result comes out is 3 items; - */ - it('testRdbTransactionInsert0001', 0, async (done) => { - console.log(TAG + "************* testRdbStoreInsert0001 start *************"); - const u8 = new Uint8Array([1, 2, 3]); - try { - const rdbTrans = await rdbStore.createTransaction(); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransactionInsert0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransactionInsert0001 failed"); - } - done(); - console.log(TAG + "************* testRdbTransactionInsert0001 end *************"); - }) - - /** - * @tc.name rdb transaction insert test - * @tc.number testRdbTransactionInsert0001 - * @tc.desc rdb transaction insert & commit, the result comes out is 3 items; - */ - it('testRdbTransactionInsert0002', 0, async (done) => { - console.log(TAG + "************* testRdbStoreInsert0002 start *************"); - const u8 = new Uint8Array([1, 2, 3]); - try { - const trans = await rdbStore.createTransaction(); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await trans.insert("test", valueBucket); - const valueBucket1 = { - "name": "zhangsan", - "age": 20, - "salary": 9.5, - "blobType": u8, - }; - await trans.insert("test", valueBucket1); - const valueBucket2 = { - "name": "wangwu", - "age": 16, - "salary": 99, - "blobType": u8, - }; - await trans.insert("test", valueBucket2); - await trans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - expect(3).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - expect(null).assertFail(); - console.log(TAG + "testRdbTransactionInsert0002 failed"); - } - done(); - console.log(TAG + "************* testRdbTransactionInsert0002 end *************"); - }) - - /** - * @tc.name rdb transaction insert test - * @tc.number testRdbTransactionInsert0002 - * @tc.desc while using transaction to insert values, querying the db, - * the result comes out is 0; - */ - it('testRdbTransactionInsert0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransactionInsert0003 start *************"); - const u8 = new Uint8Array([1, 2, 3]); - try { - const trans = await rdbStore.createTransaction(); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await trans.insert("test", valueBucket); - const valueBucket1 = { - "name": "zhangsan", - "age": 20, - "salary": 9.5, - "blobType": u8, - }; - await trans.insert("test", valueBucket1); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await trans.query(predicates); - expect(2).assertEqual(resultSet.rowCount); - resultSet.close(); - const valueBucket2 = { - "name": "wangwu", - "age": 16, - "salary": 99, - "blobType": u8, - }; - await trans.insert("test", valueBucket2); - await trans.commit(); - } catch (e) { - expect(null).assertFail(); - console.log(TAG + "testRdbTransactionInsert0003 failed"); - } - done(); - console.log(TAG + "************* testRdbTransactionInsert0003 end *************"); - }) - - /** - * @tc.number testRdbTransactionInsert0004 - * @tc.name Abnormal test case of transaction insert, if catch exception then rollback - * @tc.desc 1.Execute beginTransaction - * 2.Insert data (primary key conflict) - * 3.Execute rollBack - * 4.Query data - */ - it('testRdbTransactionRollBack0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransactionRollBack0001 start *************"); - const u8 = new Uint8Array([1, 2, 3]); - const trans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - try { - const valueBucket = { - "id": 1, - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await trans.insert("test", valueBucket); - await trans.insert("test", valueBucket); - trans.commit(); - } catch (e) { - trans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransactionRollBack0001 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } - done(); - console.log(TAG + "************* testRdbTransactionRollBack0001 end *************"); - }) - - /** - * @tc.number testRdbTransactionInsert0005 - * @tc.name Normal test case of transaction, begin transactions within a transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute beginTransaction - * 4.Insert data - * 5.Execute rollBack - * 6.Insert data - * 7.Execute commit - * 8.Query data - */ - it('testRdbTransactionMulti0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransactionMulti0003 start *************"); - const u8 = new Uint8Array([1, 2, 3]); - let trans = await rdbStore.createTransaction(); - const trans2 = await rdbStore.createTransaction(); - try { - const valueBucket = { - "id": 1, - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await trans.insert("test", valueBucket); - console.log(TAG + "before second create trans"); - console.log(TAG + "after second create trans"); - const valueBucket1 = { - "name": "zhangsan", - "age": 20, - "salary": 220.5, - "blobType": u8, - }; - await trans2.insert("test", valueBucket1); - } catch (e) { - expect(e.code).assertEqual(14800024) - await trans.rollback(); - await trans2.rollback(); - console.log(TAG + "testRdbTransactionMulti0003 rollback ***** "); - } - done(); - console.log(TAG + "************* testRdbTransactionMulti0003 end *************"); - }) - - console.log(TAG + "*************Unit Test End*************"); -}) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransaction.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransaction.test.js deleted file mode 100644 index 0f07730e6e31e0489ab0767d0fc22e05f66425d4..0000000000000000000000000000000000000000 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransaction.test.js +++ /dev/null @@ -1,2239 +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. - */ - -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' -import data_relationalStore from '@ohos.data.relationalStore' -import ability_featureAbility from '@ohos.ability.featureAbility' - -var context = ability_featureAbility.getContext() - -const TAG = "[RELATIONAL_STORE_TRANSACTION_JSKITS_TEST]" -const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + - "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; - -const STORE_CONFIG = { - name: "TransactionTest.db", - securityLevel: data_relationalStore.SecurityLevel.S1, -} - -var rdbStore = undefined; - -describe('rdbStoreTransactionTest', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll') - rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); - await rdbStore.executeSql(CREATE_TABLE_TEST, null); - }) - - beforeEach(async function () { - await rdbStore.executeSql(CREATE_TABLE_TEST); - console.info(TAG + 'beforeEach') - }) - - afterEach(async function () { - await rdbStore.executeSql("DELETE FROM test"); - console.info(TAG + 'afterEach') - }) - - afterAll(async function () { - console.info(TAG + 'afterAll') - rdbStore = null - await data_relationalStore.deleteRdbStore(context, "TransactionTest.db"); - }) - - console.log(TAG + "*************Unit Test Begin*************"); - - /** - * @tc.number testTransactionInsert0001 - * @tc.name Normal test case of transactions, insert a row of data - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute commit - * 4.Query data - */ - it('testTransactionInsert0001', 0, async function (done) { - console.log(TAG + "************* testTransactionInsert0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var num = await transaction.insert("test", valueBucket) - expect(1).assertEqual(num); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await transaction.query(predicates) - console.log(TAG + "testTransactionInsert0001 result count " + resultSet.rowCount) - expect(1).assertEqual(resultSet.rowCount) - resultSet.close() - await transaction.commit() - } catch (e) { - await transaction.commit() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionInsert0001 failed"); - } - done() - console.log(TAG + "************* testTransactionInsert0001 end *************"); - }) - - /** - * @tc.number testTransactionInsert0002 - * @tc.name Abnormal test case of transaction, insert a type mismatch data - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute commit - */ - it('testTransactionInsert0002', 0, async function (done) { - console.log(TAG + "************* testTransactionInsert0002 start *************"); - let u8 = new Uint8Array([1, 2, 3]); - let transaction = await rdbStore?.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - try { - const valueBucket = { - "id": "test", - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - let row = transaction?.insertSync("test", valueBucket); - console.log(TAG + "testTransactionInsert0002 insert row:" + row); - expect(null).assertFail(); - await transaction?.commit(); - } catch (e) { - await transaction?.rollback(); - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800033) - console.log(TAG + "testTransactionInsert0002 failed"); - } - done(); - console.log(TAG + "************* testTransactionInsert0002 end *************"); - }) - - /** - * @tc.number testTransactionInsert0003 - * @tc.name Abnormal test case of transaction, insert with an abnormal table - * @tc.desc 1.Execute beginTransaction - * 2.Insert data to a no exist table - * 3.Execute commit - */ - it('testTransactionInsert0003', 0, async function (done) { - console.log(TAG + "************* testTransactionInsert0003 start *************"); - let u8 = new Uint8Array([1, 2, 3]); - let transaction = await rdbStore?.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - try { - const valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - let row = await transaction?.insert("testNotExist", valueBucket); - console.log(TAG + "testTransactionInsert0003 insert row:" + row); - expect(null).assertFail(); - await transaction?.commit(); - } catch (e) { - await transaction?.rollback(); - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800021) - console.log(TAG + "testTransactionInsert0003 failed"); - } - done(); - console.log(TAG + "************* testTransactionInsert0003 end *************"); - }) - - /** - * @tc.number testTransactionInsert0004 - * @tc.name Abnormal test case of transaction, insert an more attribute data - * @tc.desc 1.Execute beginTransaction - * 2.Insert insert an more attribute data - * 3.Execute commit - */ - it('testTransactionInsert0004', 0, async function (done) { - console.log(TAG + "************* testTransactionInsert0004 start *************"); - let u8 = new Uint8Array([1, 2, 3]); - let transaction = await rdbStore?.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - try { - const valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - "notExist": "test" - }; - let row = transaction?.insertSync("test", valueBucket); - console.log(TAG + "testTransactionInsert0004 insert row:" + row); - expect(null).assertFail(); - await transaction?.commit(); - } catch (e) { - await transaction?.rollback(); - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800021) - console.log(TAG + "testTransactionInsert0004 failed"); - } - done(); - console.log(TAG + "************* testTransactionInsert0004 end *************"); - }) - - /** - * @tc.number testTransactionBatchInsert0001 - * @tc.name Normal test case of transactions, insert a row of data - * @tc.desc 1.Execute beginTransaction - * 2.BatchInsert data - * 3.Execute commit - * 4.Query data - */ - it('testTransactionBatchInsert0001', 0, async function (done) { - console.log(TAG + "************* testTransactionBatchInsert0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - let valueBucketArray = new Array(); - for (let i = 0; i < 2; i++) { - valueBucketArray.push(valueBucket); - } - var num = await transaction.batchInsert("test", valueBucketArray) - expect(2).assertEqual(num); - - let resultSet = await transaction.querySql("select * from test") - console.log(TAG + "testTransactionBatchInsert0001 result count " + resultSet.rowCount) - expect(2).assertEqual(resultSet.rowCount) - resultSet.close() - - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionBatchInsert0001 failed"); - } - done() - console.log(TAG + "************* testTransactionBatchInsert0001 end *************"); - }) - - /** - * @tc.number testTransactionUpdate0001 - * @tc.name Normal test case of transactions, insert and update a row of data - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 2.Update data - * 3.Execute commit - * 4.Query data - */ - it('testTransactionUpdate0001', 0, async function (done) { - console.log(TAG + "************* testTransactionUpdate0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await transaction.insert("test", valueBucket) - - let predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "lisi"); - const updateValueBucket = { - "name": "update", - "age": 28, - "salary": 25, - "blobType": u8, - } - var num = await transaction.update(updateValueBucket, predicates) - expect(1).assertEqual(num); - - let resultSet = await transaction.querySql("select * from test") - console.log(TAG + "testTransactionUpdate0001 result count " + resultSet.rowCount) - expect(1).assertEqual(resultSet.rowCount) - expect(true).assertEqual(resultSet.goToFirstRow()) - const name = resultSet.getString(resultSet.getColumnIndex("name")) - expect("update").assertEqual(name); - const age = resultSet.getLong(resultSet.getColumnIndex("age")) - expect(28).assertEqual(age); - const salary = resultSet.getLong(resultSet.getColumnIndex("salary")) - expect(25).assertEqual(salary); - resultSet.close() - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionUpdate0001 failed"); - } - done() - console.log(TAG + "************* testTransactionUpdate0001 end *************"); - }) - - /** - * @tc.number testTransactionDelete0001 - * @tc.name Normal test case of transactions, insert and update a row of data - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 2.Delete data - * 3.Execute commit - * 4.Query data - */ - it('testTransactionDelete0001', 0, async function (done) { - console.log(TAG + "************* testTransactionDelete0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await transaction.insert("test", valueBucket) - - let predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "lisi"); - var num = await transaction.delete(predicates) - expect(1).assertEqual(num); - - let resultSet = await transaction.querySql("select * from test") - console.log(TAG + "testTransactionDelete0001 result count " + resultSet.rowCount) - expect(0).assertEqual(resultSet.rowCount) - resultSet.close() - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionDelete0001 failed"); - } - done() - console.log(TAG + "************* testTransactionDelete0001 end *************"); - }) - - /** - * @tc.number testExecute0001 - * @tc.name Normal test case of Execute, check integrity for store - * @tc.desc 1. Execute sql: PRAGMA integrity_check - * 2. Check returned value - */ - it('testExecute0001', 0, async function (done) { - console.info(TAG + "************* testExecute0001 start *************"); - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - try { - let ret = await transaction.execute("PRAGMA integrity_check"); - expect("ok").assertEqual(ret); - await transaction.commit(); - } catch (err) { - await transaction.rollback(); - expect(null).assertFail(); - console.error(`integrity_check failed, code:${err.code}, message: ${err.message}`); - } - done(); - console.info(TAG + "************* testExecute0001 end *************"); - }) - - - /** - * @tc.number testExecute0002 - * @tc.name Normal test case of ExecuteSql - * @tc.desc 1.Insert data - * 2.ExecuteSql(delete age = "18" OR "20") - * 3.QuerySql - */ - it('testExecute0002', 0, async function (done) { - console.log(TAG + "************* testExecute0002 start *************"); - var transaction = await rdbStore.createTransaction() - var u8 = new Uint8Array([1, 2, 3]) - try { - var valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - for (let i = 0; i < 3; i++) { - valueBucket.age = valueBucket.age + 1; - var row = await transaction.insert("test", valueBucket) - console.log(TAG + "testExecute0002 insert row " + row) - } - await transaction.execute("DELETE FROM test WHERE age = ? OR age = ?", [21, 20]) - - let resultSet = await transaction.querySql("select * from test") - console.log(TAG + "testExecute0002 transaction.querySql result count " + resultSet.rowCount) - expect(1).assertEqual(resultSet.rowCount) - expect(true).assertEqual(resultSet.goToFirstRow()) - const age = resultSet.getLong(resultSet.getColumnIndex("age")) - expect(19).assertEqual(age); - await resultSet.close() - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testExecute0002 failed"); - } - done(); - console.log(TAG + "************* testExecute0002 end *************"); - } - ) - - /** - * @tc.number testExecute0003 - * @tc.name Normal test case of ExecuteSql - * @tc.desc 1.Insert data (param is long string) - * 2.Query data - * 3.ExecuteSql (delete age = 19 AND name = nameStr) - * 4.Query data - */ - it('ExecuteSqlTest0003', 0, async function (done) { - console.log(TAG + "************* testExecute0003 start *************"); - var u8 = new Uint8Array([3, 4, 5]) - var transaction = await rdbStore.createTransaction() - var nameStr = "lisi" + "e".repeat(2000) + "zhangsan" - var valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var row = await transaction.insert("test", valueBucket) - console.log(TAG + "testExecute0003 insert row " + row) - valueBucket.name = nameStr - for (let i = 0; i < 2; i++) { - row = await transaction.insert("test", valueBucket) - valueBucket.age = valueBucket.age + 1; - console.log(TAG + "testExecute0003 insert row " + row) - } - { - let predicates = await new data_relationalStore.RdbPredicates("test") - predicates.equalTo("name", nameStr) - let querySqlPromise = transaction.query(predicates) - querySqlPromise.then(async (resultSet) => { - expect(2).assertEqual(resultSet.rowCount) - resultSet.close() - }).catch((err) => { - expect(null).assertFail(); - }) - await querySqlPromise - } - { - let executeSqlPromise = transaction.execute("DELETE FROM test WHERE age = 19 AND name ='" + nameStr + "'") - executeSqlPromise.then(async () => { - console.log(TAG + "executeSql done."); - }).catch((err) => { - console.log(TAG + "executeSql failed. " + err); - expect(null).assertFail(); - }) - await executeSqlPromise - } - await transaction.commit(); - { - let predicates = await new data_relationalStore.RdbPredicates("test") - predicates.equalTo("name", nameStr) - let querySqlPromise = rdbStore.query(predicates) - querySqlPromise.then(async (resultSet) => { - console.log(TAG + "testExecute0003 rdbStore.querySql result count " + resultSet.rowCount) - expect(1).assertEqual(resultSet.rowCount) - expect(true).assertEqual(resultSet.goToFirstRow()) - const name = resultSet.getString(resultSet.getColumnIndex("name")) - expect(nameStr).assertEqual(name) - expect(2012).assertEqual(name.length) - expect(18).assertEqual(resultSet.getLong(resultSet.getColumnIndex("age"))) - expect(100.5).assertEqual(resultSet.getDouble(resultSet.getColumnIndex("salary"))) - const blobType = resultSet.getBlob(resultSet.getColumnIndex("blobType")) - expect(3).assertEqual(blobType[0]) - resultSet.close(); - done(); - }).catch((err) => { - console.log(TAG + err); - expect(null).assertFail(); - }) - await querySqlPromise - } - done(); - console.log(TAG + "************* testExecute0003 end *************"); - }) - - /** - * @tc.number testExecute0004 - * @tc.name Normal test case of ExecuteSql, drop table - * @tc.desc 1.Insert data - * 2.ExecuteSql (drop table) - */ - it('testExecute0004', 0, async function (done) { - console.log(TAG + "************* testExecute0004 start *************"); - var u8 = new Uint8Array([3, 4, 5]) - var transaction = await rdbStore.createTransaction() - try { - var valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - let valueBucketArray = new Array(); - for (let i = 0; i < 3; i++) { - valueBucket.age = valueBucket.age + 1; - valueBucketArray.push(valueBucket); - } - var num = await transaction.batchInsert("test", valueBucketArray) - expect(3).assertEqual(num); - await transaction.execute("DROP TABLE IF EXISTS test") - - let resultSet = await transaction.querySql("select * from test") - console.log(TAG + "testExecute0004 transaction.querySql result count " + resultSet.rowCount) - expect(resultSet.rowCount < 1).assertTrue() - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testExecute0004 failed"); - } - done(); - console.log(TAG + "************* testExecute0004 end *************"); - }) - - /** - * @tc.number testExecute0005 - * @tc.name Normal test case of executeSql and querySql, PRAGMA user_version - * @tc.desc 1.Set user_version - * 2.Get user_version - */ - it('testExecute0005', 0, async function (done) { - console.log(TAG + "************* testExecute0005 start *************"); - // 2 is used to set the store version - var transaction = await rdbStore.createTransaction() - try { - await transaction.execute("PRAGMA user_version = 2") - let resultSet = await transaction.querySql("PRAGMA user_version"); - console.log(TAG + "testExecute0005 transaction.querySql result count " + resultSet.rowCount) - resultSet.goToFirstRow(); - expect(2).assertEqual(resultSet.getLong(0)) - resultSet.close(); - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testExecute0005 failed"); - } - done(); - console.log(TAG + "************* testExecute0005 end *************"); - }) - - /** - * @tc.number testExecute0006 - * @tc.name Normal test case of executeSql and querySql, PRAGMA table_info - * @tc.desc 1.Get table_info - * 2.Check table_info - */ - it('testExecute0006', 0, async function (done) { - console.log(TAG + "************* testExecute0006 start *************"); - var transaction = await rdbStore.createTransaction() - try { - let resultSet = await transaction.querySql("PRAGMA table_info(test)"); - console.log(TAG + "testExecute0006 transaction.querySql result count " + resultSet.rowCount) - resultSet.goToFirstRow(); - expect(0).assertEqual(resultSet.getLong(0)) - expect("id").assertEqual(resultSet.getString(1)) - expect("INTEGER").assertEqual(resultSet.getString(2)) - resultSet.goToNextRow(); - expect(1).assertEqual(resultSet.getLong(0)) - expect("name").assertEqual(resultSet.getString(1)) - expect("TEXT").assertEqual(resultSet.getString(2)) - expect(1).assertEqual(resultSet.getLong(3)) - resultSet.goToNextRow(); - expect(2).assertEqual(resultSet.getLong(0)) - expect("age").assertEqual(resultSet.getString(1)) - expect("INTEGER").assertEqual(resultSet.getString(2)) - resultSet.goToNextRow(); - expect(3).assertEqual(resultSet.getLong(0)) - expect("salary").assertEqual(resultSet.getString(1)) - expect("REAL").assertEqual(resultSet.getString(2)) - resultSet.goToNextRow(); - expect(4).assertEqual(resultSet.getLong(0)) - expect("blobType").assertEqual(resultSet.getString(1)) - expect("BLOB").assertEqual(resultSet.getString(2)) - resultSet.close(); - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testExecute0006 failed"); - } - done(); - console.log(TAG + "************* testExecute0006 end *************"); - }) - - /** - * @tc.number testExecute0007 - * @tc.name Normal test case of executeSql, if spaces before the sql - * @tc.desc 1.Set user_version - * 2.Get user_version - */ - it('testExecute0007', 0, async function (done) { - console.log(TAG + "************* testExecute0007 start *************"); - var transaction = await rdbStore.createTransaction() - try { - // 2 is used to set the store version - await transaction.execute(" PRAGMA user_version = 2") - let resultSet = await transaction.querySql("PRAGMA user_version"); - console.log(TAG + "testExecute0007 transaction.querySql1 result count " + resultSet.rowCount) - resultSet.goToFirstRow(); - expect(2).assertEqual(resultSet.getLong(0)) - - await transaction.execute("\r\nPRAGMA user_version = 3") - resultSet = await transaction.querySql("PRAGMA user_version"); - console.log(TAG + "testExecute0007 transaction.querySql2 result count " + resultSet.rowCount) - resultSet.goToFirstRow(); - expect(3).assertEqual(resultSet.getLong(0)) - resultSet.close(); - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testExecute0007 failed"); - } - done(); - console.log(TAG + "************* testExecute0007 end *************"); - }) - - /** - * @tc.number testTransactionSyncInterface0001 - * @tc.name Normal test case of transactions, insert a row of data - * @tc.desc 1.Execute beginTransaction - * 2.BatchInsertSync data - * 3.InsertSync data - * 4.UpdateSync data - * 5.DeleteSync data - * 6.Execute commit - * 7.querySqlSync - * 7.ExecuteSync - */ - it('testTransactionSyncInterface0001', 0, async function (done) { - console.log(TAG + "************* testTransactionSyncInterface0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var num = await transaction.insertSync("test", valueBucket, data_relationalStore.ConflictResolution.ON_CONFLICT_REPLACE); - expect(1).assertEqual(num); - const updateValueBucket = { - "name": "update", - "age": 28, - "salary": 25, - "blobType": u8, - } - let predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "lisi") - num = await transaction.updateSync(updateValueBucket, predicates) - expect(1).assertEqual(num); - - let deletePredicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "update") - num = await transaction.deleteSync(deletePredicates); - expect(1).assertEqual(num); - - let resultSet = await transaction.querySqlSync("select * from test") - console.log(TAG + "testTransactionSyncInterface0001 result count " + resultSet.rowCount) - expect(0).assertEqual(resultSet.rowCount) - resultSet.close() - - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionSyncInterface0001 failed"); - } - done() - console.log(TAG + "************* testTransactionSyncInterface0001 end *************"); - }) - - /** - * @tc.number testTransactionRollback0001 - * @tc.name Normal test case of transactions, insert and update a row of data - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.rollback data - * 4.Query data - */ - it('testTransactionRollback0001', 0, async function (done) { - console.log(TAG + "************* testTransactionRollback0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await transaction.insert("test", valueBucket) - - await transaction.rollback() - - let resultSet = rdbStore.querySqlSync("select * from test") - console.log(TAG + "testTransactionRollback0001 result count " + resultSet.rowCount) - expect(0).assertEqual(resultSet.rowCount) - resultSet.close() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionRollback0001 failed"); - } - done() - console.log(TAG + "************* testTransactionRollback0001 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0001 - * @tc.name testTransactionIsolation. EXCLUSIVE and EXCLUSIVE - * @tc.desc 1.begin EXCLUSIVE Transaction - * 2.begin EXCLUSIVE Transaction again - * 3.throw 14800024 - */ - it('testTransactionIsolation0001', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0001 start *************"); - var exclusiveTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - try { - var trans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - trans.commit(); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0001 failed"); - } catch (e) { - await exclusiveTrans.rollback(); - console.log(TAG + e); - expect(e.code).assertEqual(14800024) - console.log(TAG + "testTransactionIsolation0001 success"); - } - done() - console.log(TAG + "************* testTransactionIsolation0001 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0002 - * @tc.name testTransactionIsolation. DEFERRED and EXCLUSIVE - * @tc.desc 1.begin DEFERRED Transaction - * 2.begin EXCLUSIVE Transaction again - * 3.insert data with EXCLUSIVE Transaction - * 4.query data with DEFERRED Transaction -> no data - * 5.execute commit with EXCLUSIVE Transaction - * 6.query data with DEFERRED Transaction -> no data -> why? step 4 start isolation - * 7.query data with Rdb -> has data - */ - it('testTransactionIsolation0002', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0002 start *************"); - var deferredTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - var exclusiveTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - } - var insertRow = await exclusiveTrans.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0002 exclusiveTrans.insert row " + insertRow) - expect(1).assertEqual(insertRow) - - var resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0002 deferredTrans querySqlSync before exclusiveTrans commit count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close() - - await exclusiveTrans.commit(); - - resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0002 deferredTrans querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - - resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0002 rdbStore querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close() - - } catch (e) { - exclusiveTrans.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "insert failed"); - } - await deferredTrans.commit(); - } catch (e) { - await deferredTrans.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0002 failed"); - } - done() - console.log(TAG + "************* testTransactionIsolation0002 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0003 - * @tc.name testTransactionIsolation. IMMEDIATE and rdbStore - * @tc.desc 1.begin IMMEDIATE Transaction - * 2.insert data with rdbStore -> busy - * 3.insert data with IMMEDIATE Transaction - * 4.execute commit with IMMEDIATE Transaction - * 5.query data with rdbStore -> has data - */ - it('testTransactionIsolation0003', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0003 start *************"); - var immediateTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - } - try { - await rdbStore.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0003 rdbStore.insert success "); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e); - expect(e.code).assertEqual(14800024) - console.log(TAG + "insert failed"); - } - var insertRow = await immediateTrans.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0003 immediateTrans.insert row " + insertRow); - expect(insertRow).assertEqual(1); - - await immediateTrans.commit(); - - var resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0003 querySqlSync count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close() - } catch (e) { - await immediateTrans.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0003 failed"); - } - done() - console.log(TAG + "************* testTransactionIsolation0003 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0004 - * @tc.name testTransactionIsolation. DEFERRED and rdbStore - * @tc.desc 1.begin DEFERRED Transaction - * 2.insert data with rdbStore - * 3.insert data with DEFERRED Transaction - * 4.query data with rdbStore -> has 2 row - * 5.insert data with rdbStore again -> busy - * 6.query data with DEFERRED Transaction -> has 2 row - * 7.execute commit with DEFERRED Transaction - * 8.insert data with rdbStore again - * 9.query data with rdbStore -> has 3 row - */ - it('testTransactionIsolation0004', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0004 start *************"); - var deferredTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - } - await rdbStore.insert("test", valueBucket); - - await deferredTrans.insert("test", valueBucket); - - var resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0004 rdbStore.querySqlSync count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - - try { - await rdbStore.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0004 insert success "); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e); - expect(e.code).assertEqual(14800024) - console.log(TAG + "insert failed"); - } - resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0004 deferredTrans.querySqlSync count " + resultSet.rowCount); - expect(2).assertEqual(resultSet.rowCount); - - await deferredTrans.commit(); - - await rdbStore.insert("test", valueBucket); - - resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0004 rdbStore.querySqlSync after deferredTrans commit count " + resultSet.rowCount); - expect(3).assertEqual(resultSet.rowCount); - resultSet.close() - } catch (e) { - await deferredTrans.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0004 failed"); - } - done() - console.log(TAG + "************* testTransactionIsolation0004 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0005 - * @tc.name testTransactionIsolation. DEFERRED and IMMEDIATE - * @tc.desc 1.begin DEFERRED Transaction - * 2.begin IMMEDIATE Transaction - * 3.insert data with DEFERRED Transaction -> busy - * 4.insert data with IMMEDIATE Transaction - * 5.execute commit with IMMEDIATE Transaction - * 6.insert data with DEFERRED Transaction - * 7.execute commit with DEFERRED Transaction - * 8.query data with rdbStore -> has 4 row - */ - it('testTransactionIsolation0005', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0005 start *************"); - var deferredTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - var immediateTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - } - try { - await deferredTrans.insert("test", valueBucket); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e); - expect(e.code).assertEqual(14800024) - console.log(TAG + "insert failed"); - } - var insertRow = await immediateTrans.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0005 immediateTrans.insert row " + insertRow); - expect(1).assertEqual(insertRow); - - await immediateTrans.commit(); - - insertRow = await deferredTrans.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0005 deferredTrans.insert after immediateTrans.commit row " + insertRow); - expect(2).assertEqual(insertRow); - - await deferredTrans.commit(); - - var resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0005 querySqlSync count " + resultSet.rowCount); - expect(2).assertEqual(resultSet.rowCount); - resultSet.close() - } catch (e) { - await immediateTrans.rollback(); - await deferredTrans.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0005 failed"); - } - done() - console.log(TAG + "************* testTransactionIsolation0005 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0006 - * @tc.name testTransactionIsolation. DEFERRED and DEFERRED - * @tc.desc 1.insert data with rdbStore - * 2.begin DEFERRED Transaction1 - * 3.begin DEFERRED Transaction2 - * 4.update data with DEFERRED Transaction1 - * 5.delete data with DEFERRED Transaction2 -> busy - * 6.execute commit with DEFERRED Transaction1 - * 7.query data with DEFERRED Transaction2 -> has updated data - * 8.delete data with DEFERRED Transaction2 - * 9.execute commit with DEFERRED Transaction2 - * 10.query data with rdbStore -> has 0 row - */ - it('testTransactionIsolation0006', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0006 start *************"); - var deferredTrans1 = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - var deferredTrans2 = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - } - var rowId = await rdbStore.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0006 insert row " + rowId); - expect(1).assertEqual(rowId); - - const updateValueBucket = { - "name": "deferredTrans1", - "age": 18, - "salary": 100.5, - } - let predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "lisi") - rowId = await deferredTrans1.updateSync(updateValueBucket, predicates) - console.log(TAG + "testTransactionIsolation0006 insert row " + rowId); - expect(1).assertEqual(rowId); - - let deletePredicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("age", "18"); - try { - await deferredTrans2.delete(deletePredicates) - console.log(TAG + "testTransactionIsolation0006 deferredTrans2.delete success "); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e); - expect(e.code).assertEqual(14800024) - console.log(TAG + "insert failed"); - } - - await deferredTrans1.commit(); - - var resultSet = deferredTrans2.querySqlSync("select * from test"); - console.log(TAG + "testTransactionIsolation0006 deferredTrans2.querySqlSync count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - expect(true).assertEqual(resultSet.goToFirstRow()) - const name = resultSet.getString(resultSet.getColumnIndex("name")) - expect("deferredTrans1").assertEqual(name); - resultSet.close() - - var num = await deferredTrans2.deleteSync(deletePredicates) - console.log(TAG + "testTransactionIsolation0006 delete num " + num); - expect(1).assertEqual(num); - - await deferredTrans2.commit(); - - resultSet = rdbStore.querySqlSync("select * from test"); - console.log(TAG + "testTransactionIsolation0006 rdbStore.querySqlSync count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close() - } catch (e) { - await deferredTrans2.rollback(); - await deferredTrans1.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0006 failed"); - } - done() - console.log(TAG + "************* testTransactionIsolation0006 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0007 - * @tc.name testTransactionIsolation. DEFERRED and EXCLUSIVE - * @tc.desc 1.begin DEFERRED Transaction1 - * 2.begin EXCLUSIVE Transaction - * 3.insert data with EXCLUSIVE Transaction - * 4.execute commit with EXCLUSIVE Transaction - * 5.query data with DEFERRED1 Transaction -> has data - * 6.begin DEFERRED Transaction2 - * 7.query data with DEFERRED2 Transaction -> has data - */ - it('testTransactionIsolation0007', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0007 start *************"); - var deferredTrans1 = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - var exclusiveTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - } - var insertRow = await exclusiveTrans.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0007 exclusiveTrans.insert row " + insertRow) - expect(1).assertEqual(insertRow) - await exclusiveTrans.commit(); - - var resultSet = deferredTrans1.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0007 deferredTrans1 querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - - var deferredTrans2 = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - resultSet = deferredTrans2.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0007 deferredTrans2 querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close() - } catch (e) { - deferredTrans2.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "querySqlSync failed"); - } - - } catch (e) { - exclusiveTrans.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "insert failed"); - } - await deferredTrans1.commit(); - } catch (e) { - await deferredTrans1.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0007 failed"); - } - done() - console.log(TAG + "************* testTransactionIsolation0007 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0008 - * @tc.name testTransactionIsolation. DEFERRED and rdbStore - * @tc.desc 1.begin DEFERRED Transaction - * 2.insert data with rdbStore - * 3.query data with DEFERRED Transaction -> has 1 data - * 4.begin EXCLUSIVE Transaction -> busy - * 5.insert data with DEFERRED Transaction - * 6.execute commit with DEFERRED Transaction - * 7.begin EXCLUSIVE Transaction - * 8.query data with EXCLUSIVE Transaction -> has 2 data - */ - it('testTransactionIsolation0008', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0008 start *************"); - var deferredTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - } - await rdbStore.insert("test", valueBucket); - - var resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0008 querySqlSync1 count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close() - try { - var exclusiveTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - console.log(TAG + "begin EXCLUSIVE success abnormal"); - await exclusiveTrans.rollback(); - } catch (e) { - console.log(TAG + e); - console.log(TAG + "begin EXCLUSIVE failed"); - expect(true).assertFail(); - } - var rowId = await deferredTrans.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0008 deferredTrans.insert row " + rowId) - expect(2).assertEqual(rowId); - - await deferredTrans.commit(); - - try { - var exclusiveTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - console.log(TAG + "begin EXCLUSIVE success"); - try { - resultSet = exclusiveTrans.querySqlSync("select * from test"); - console.log(TAG + "testTransactionIsolation0008 exclusiveTrans.querySqlSync count " + resultSet.rowCount); - expect(2).assertEqual(resultSet.rowCount); - resultSet.close() - } catch (e) { - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "exclusiveTrans.querySqlSync failed"); - } - exclusiveTrans.rollback(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "begin EXCLUSIVE failed"); - } - } catch (e) { - await deferredTrans.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0008 failed"); - } - done() - console.log(TAG + "************* testTransactionIsolation0008 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0009 - * @tc.name testTransactionIsolation. DEFERRED and DEFERRED - * @tc.desc 1.insert data with rdbStore - * 2.begin DEFERRED Transaction1 - * 3.begin DEFERRED Transaction2 - * 4.update data to update1 with DEFERRED Transaction1 - * 5.query data with DEFERRED Transaction2 -> has before update data - * 6.update update1 to update2 with DEFERRED Transaction1 - * 7.execute commit with DEFERRED Transaction1 - * 8.query data with DEFERRED Transaction2 -> has before update data - * 9.delete data with DEFERRED Transaction2 -> busy - * 10.execute commit with DEFERRED Transaction2 - * 11.query data with rdbStore -> has 1 row - */ - it('testTransactionIsolation0009', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0009 start *************"); - var deferredTrans1 = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - var deferredTrans2 = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - } - var rowId = await rdbStore.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0009 insert row " + rowId); - expect(1).assertEqual(rowId); - - const updateValueBucket1 = { - "name": "update1", - "age": 18, - "salary": 100.5, - } - let predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "lisi") - var num = await deferredTrans1.updateSync(updateValueBucket1, predicates) - console.log(TAG + "testTransactionIsolation0009 updateSync 1 num " + num); - expect(1).assertEqual(num); - - var resultSet = deferredTrans2.querySqlSync("select * from test"); - console.log(TAG + "testTransactionIsolation0009 deferredTrans2.querySqlSync1 count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - expect(true).assertEqual(resultSet.goToFirstRow()) - var name = resultSet.getString(resultSet.getColumnIndex("name")) - expect("lisi").assertEqual(name); - resultSet.close() - - const updateValueBucket2 = { - "name": "update2", - "age": 18, - "salary": 100.5, - } - predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "update1") - var num = await deferredTrans1.updateSync(updateValueBucket2, predicates) - console.log(TAG + "testTransactionIsolation0009 updateSync 2 num " + num); - expect(1).assertEqual(num); - - await deferredTrans1.commit(); - - resultSet = deferredTrans2.querySqlSync("select * from test"); - console.log(TAG + "testTransactionIsolation0009 deferredTrans2.querySqlSync2 count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - expect(true).assertEqual(resultSet.goToFirstRow()) - name = resultSet.getString(resultSet.getColumnIndex("name")) - expect("lisi").assertEqual(name); - resultSet.close() - - let deletePredicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("age", "18"); - try { - num = await deferredTrans2.delete(deletePredicates) - console.log(TAG + "testTransactionIsolation0009 delete num " + num); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e); - expect(e.code).assertEqual(14800024) - } - await deferredTrans2.commit(); - - resultSet = rdbStore.querySqlSync("select * from test"); - console.log(TAG + "testTransactionIsolation0009 rdbStore.querySqlSync count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close() - } catch (e) { - await deferredTrans2.rollback(); - await deferredTrans1.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0009 failed"); - } - done() - console.log(TAG + "************* testTransactionIsolation0009 end *************"); - }) - - /** - * @tc.number testTransactionEnd0001 - * @tc.name Query data with closed transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute commit - * 4.Query data with transaction -> throw 14800014 - */ - it('testTransactionEnd0001', 0, async function (done) { - console.log(TAG + "************* testTransactionEnd0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var num = await transaction.insert("test", valueBucket) - expect(1).assertEqual(num); - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e + " code: " + e.code); - expect(null).assertFail() - } - try { - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await transaction.query(predicates) - console.log(TAG + "testTransactionEnd0001 result count " + resultSet.rowCount) - expect(null).assertFail() - resultSet.close() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800014) - } - done() - console.log(TAG + "************* testTransactionEnd0001 end *************"); - }) - - /** - * @tc.number testTransactionEnd0002 - * @tc.name Query data with closed transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Query data with transaction -> get resultSet - * 4.Execute commit - * 5.resultSet go to first row -> throw 14800014 - */ - it('testTransactionEnd0002', 0, async function (done) { - console.log(TAG + "************* testTransactionEnd0002 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - let resultSet; - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var num = await transaction.insert("test", valueBucket) - expect(1).assertEqual(num); - - let predicates = new data_relationalStore.RdbPredicates("test"); - resultSet = await transaction.query(predicates) - console.log(TAG + "testTransactionEnd0002 result count " + resultSet.rowCount) - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e + " code: " + e.code); - expect(null).assertFail() - } - expect(false).assertEqual(resultSet.goToFirstRow()) - done() - console.log(TAG + "************* testTransactionEnd0002 end *************"); - }) - - /** - * @tc.number testTransactionEnd0003 - * @tc.name Insert data with closed transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute commit - * 4.Insert data with closed transaction -> throw 14800014 - */ - it('testTransactionEnd0003', 0, async function (done) { - console.log(TAG + "************* testTransactionEnd0003 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - try { - var rowId = await transaction.insert("test", valueBucket) - expect(1).assertEqual(rowId); - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e + " code: " + e.code); - expect(null).assertFail() - } - try { - rowId = await transaction.insert("test", valueBucket) - console.log(TAG + "testTransactionEnd0003 insert rowId " + rowId) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800014) - } - done() - console.log(TAG + "************* testTransactionEnd0003 end *************"); - }) - - /** - * @tc.number testTransactionEnd0004 - * @tc.name Update data with closed transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute rollback - * 4.Update data with closed transaction -> throw 14800014 - */ - it('testTransactionEnd0004', 0, async function (done) { - console.log(TAG + "************* testTransactionEnd0004 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var rowId = await transaction.insert("test", valueBucket) - expect(1).assertEqual(rowId); - await transaction.rollback() - } catch (e) { - await transaction.rollback() - console.log(TAG + e + " code: " + e.code); - expect(null).assertFail() - } - try { - let predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "lisi"); - const updateValueBucket = { - "name": "update", - "age": 28, - "salary": 25, - "blobType": u8, - } - rowId = await transaction.update(updateValueBucket, predicates) - console.log(TAG + "testTransactionEnd0004 update rowId " + rowId) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800014) - } - done() - console.log(TAG + "************* testTransactionEnd0004 end *************"); - }) - - /** - * @tc.number testTransactionEnd0005 - * @tc.name Delete data with closed transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute rollback - * 4.Delete data with closed transaction -> throw 14800014 - */ - it('testTransactionEnd0005', 0, async function (done) { - console.log(TAG + "************* testTransactionEnd0005 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var rowId = await transaction.insert("test", valueBucket) - expect(1).assertEqual(rowId); - await transaction.rollback() - } catch (e) { - await transaction.rollback() - console.log(TAG + e + " code: " + e.code); - expect(null).assertFail() - } - try { - let predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "lisi"); - var num = transaction.deleteSync(predicates) - console.log(TAG + "testTransactionEnd0005 delete num " + num) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800014) - } - done() - console.log(TAG + "************* testTransactionEnd0005 end *************"); - }) - - /** - * @tc.number testTransactionEnd0006 - * @tc.name Execute Sql with closed transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute rollback - * 4.Execute Sql with closed transaction -> throw 14800014 - */ - it('testTransactionEnd0006', 0, async function (done) { - console.log(TAG + "************* testTransactionEnd0006 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var rowId = await transaction.insert("test", valueBucket) - expect(1).assertEqual(rowId); - await transaction.rollback() - } catch (e) { - await transaction.rollback() - console.log(TAG + e + " code: " + e.code); - expect(null).assertFail() - } - try { - let ret = transaction.executeSync("PRAGMA integrity_check"); - console.log(TAG + "testTransactionEnd0006 executeSync PRAGMA integrity_check: " + ret) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800014) - } - done() - console.log(TAG + "************* testTransactionEnd0006 end *************"); - }) - - /** - * @tc.number testTransactionEnd0007 - * @tc.name Execute Sql with closed transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute rollback - * 4.Commit with closed transaction -> throw 14800014 - */ - it('testTransactionEnd0007', 0, async function (done) { - console.log(TAG + "************* testTransactionEnd0007 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var rowId = await transaction.insert("test", valueBucket) - expect(1).assertEqual(rowId); - await transaction.rollback() - } catch (e) { - await transaction.rollback() - console.log(TAG + e + " code: " + e.code); - expect(null).assertFail() - } - try { - await transaction.commit(); - console.log(TAG + "testTransactionEnd0007 commit success") - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800014) - } - done() - console.log(TAG + "************* testTransactionEnd0007 end *************"); - }) - - /** - * @tc.number testTransactionBusy0001 - * @tc.name Abnormal test case of createTransaction - * @tc.desc 1.Execute beginTransaction 5 times - */ - it('testTransactionBusy0001', 0, async function (done) { - console.log(TAG + "************* testTransactionBusy0001 start *************"); - let transactions = []; - try { - for (let i = 0; i < 5; i++) { - transactions.push(await rdbStore?.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - })); - console.log(TAG + "testTransactionBusy0001 createTransaction success. i " + i); - } - } catch (e) { - console.log(TAG + e + " code: " + e.code); - // expect(e.code).assertEqual(14800000) - expect(e.code).assertEqual(14800015) - console.log(TAG + "testTransactionBusy0001 failed"); - } - done(); - transactions.forEach(element => { - element?.rollback(); - console.log(TAG + "testTransactionBusy0001 rollback"); - }); - console.log(TAG + "************* testTransactionBusy0001 end *************"); - }) - - /** - * @tc.number testTransactionWithReadOnlyStore0001 - * @tc.name createTransactionWithReadOnlyStore - * @tc.desc 1.Get a readOnly store - * 2.createTransaction with readOnly store - */ - it('testTransactionWithReadOnlyStore0001', 0, async function (done) { - console.log(TAG + "************* testTransactionWithReadOnlyStore0001 start *************"); - let storeConfig = { - name: "ReadOnlyTransactionTest.db", - securityLevel: data_relationalStore.SecurityLevel.S1, - } - let store = await data_relationalStore.getRdbStore(context, storeConfig); - await store.close() - storeConfig.isReadOnly = true; - let readOnlyStore = await data_relationalStore.getRdbStore(context, storeConfig); - expect(readOnlyStore === null).assertFalse(); - try { - let transaction = await readOnlyStore?.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - console.log(TAG + "testTransactionWithReadOnlyStore0001 createTransaction success"); - const valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - }; - let row = transaction?.insertSync("test", valueBucket); - console.log(TAG + "testTransactionWithReadOnlyStore0001 insert row:" + row); - await transaction?.rollback(); - expect(null).assertFail(); - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(801) - console.log(TAG + "testTransactionWithReadOnlyStore0001 success"); - } - await data_relationalStore.deleteRdbStore(context, storeConfig); - done(); - console.log(TAG + "************* testTransactionWithReadOnlyStore0001 end *************"); - }) - - /** - * @tc.number testbatchInsertWithConflictResolutionInTransaction0001 - * @tc.name batchInsertWithConflictResolutionInTransaction - * @tc.desc normal batch insert with ON_CONFLICT_NONE - */ - it('testbatchInsertWithConflictResolutionInTransaction0001', 0, async function (done) { - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - let valueBucketArray = new Array(); - for (let i = 0; i < 2; i++) { - valueBucketArray.push(valueBucket); - } - var num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_NONE) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num1 " + num) - expect(2).assertEqual(num); - - num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num2 " + num) - expect(2).assertEqual(num); - - num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_ABORT) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num3 " + num) - expect(2).assertEqual(num); - - num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_FAIL) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num4 " + num) - expect(2).assertEqual(num); - - num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_IGNORE) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num5 " + num) - expect(2).assertEqual(num); - - num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_REPLACE) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num6 " + num) - expect(2).assertEqual(num); - - let resultSet = await transaction.querySql("select * from test") - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 result count " + resultSet.rowCount) - expect(12).assertEqual(resultSet.rowCount) - resultSet.close() - - await transaction.commit() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - await transaction.rollback() - expect(null).assertFail() - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 failed"); - } - done() - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0001 end *************"); - }) - - /** - * @tc.number testbatchInsertWithConflictResolutionInTransaction0011 - * @tc.name batchInsertWithConflictResolutionInTransaction - * @tc.desc conflict batch insert with ON_CONFLICT_NONE - */ - it('testbatchInsertWithConflictResolutionInTransaction0011', 0, async function (done) { - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0011 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "id" : 2, - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await transaction.insert("test", valueBucket); - let valueBucketArray = new Array(); - for (let i = 0; i < 5; i++) { - var vb = {...valueBucket}; - vb.id = i; - valueBucketArray.push(vb); - } - let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_NONE) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0011 failed num " + num); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(14800032).assertEqual(e.code) - await transaction.rollback() - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0011 success"); - } - done() - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0011 end *************"); - }) - - /** - * @tc.number testbatchInsertWithConflictResolutionInTransaction0012 - * @tc.name batchInsertWithConflictResolutionInTransaction - * @tc.desc conflict batch insert with ON_CONFLICT_ABORT - */ - it('testbatchInsertWithConflictResolutionInTransaction0012', 0, async function (done) { - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0012 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "id" : 2, - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await transaction.insert("test", valueBucket); - let valueBucketArray = new Array(); - for (let i = 0; i < 5; i++) { - var vb = {...valueBucket}; - vb.id = i; - valueBucketArray.push(vb); - } - let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_ABORT) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0012 failed num " + num); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(14800032).assertEqual(e.code) - await transaction.rollback() - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0012 success"); - } - done() - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0012 end *************"); - }) - - /** - * @tc.number testbatchInsertWithConflictResolutionInTransaction0013 - * @tc.name batchInsertWithConflictResolutionInTransaction - * @tc.desc conflict batch insert with ON_CONFLICT_FAIL - */ - it('testbatchInsertWithConflictResolutionInTransaction0013', 0, async function (done) { - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0013 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "id" : 2, - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await transaction.insert("test", valueBucket); - let valueBucketArray = new Array(); - for (let i = 0; i < 5; i++) { - var vb = {...valueBucket}; - vb.id = i; - valueBucketArray.push(vb); - } - let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_FAIL) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0013 failed num " + num); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(14800032).assertEqual(e.code) - await transaction.rollback() - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0013 success"); - } - done() - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0013 end *************"); - }) - - /** - * @tc.number testbatchInsertWithConflictResolutionInTransaction0014 - * @tc.name batchInsertWithConflictResolutionInTransaction - * @tc.desc conflict batch insert with ON_CONFLICT_IGNORE - */ - it('testbatchInsertWithConflictResolutionInTransaction0014', 0, async function (done) { - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0014 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "id" : 2, - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await transaction.insert("test", valueBucket); - let valueBucketArray = new Array(); - for (let i = 0; i < 5; i++) { - var vb = {...valueBucket}; - vb.id = i; - valueBucketArray.push(vb); - } - let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_IGNORE) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0014 success num " + num); - expect(4).assertEqual(num) - - let resultSet = await transaction.querySql("select * from test") - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0014 result count " + resultSet.rowCount) - expect(5).assertEqual(resultSet.rowCount) - resultSet.close() - - await transaction.commit() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - await transaction.rollback() - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0014 failed"); - expect(null).assertFail() - } - done() - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0014 end *************"); - }) - - /** - * @tc.number testbatchInsertWithConflictResolutionInTransaction0015 - * @tc.name batchInsertWithConflictResolutionInTransaction - * @tc.desc conflict batch insert with ON_CONFLICT_REPLACE - */ - it('testbatchInsertWithConflictResolutionInTransaction0015', 0, async function (done) { - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0015 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "id" : 2, - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await transaction.insert("test", valueBucket); - let valueBucketArray = new Array(); - for (let i = 0; i < 5; i++) { - var vb = {...valueBucket}; - vb.id = i; - valueBucketArray.push(vb); - } - let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_REPLACE) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0015 success num " + num); - expect(5).assertEqual(num) - - let resultSet = await transaction.querySql("select * from test") - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0015 result count " + resultSet.rowCount) - expect(5).assertEqual(resultSet.rowCount) - resultSet.close() - - await transaction.commit() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - await transaction.rollback() - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0015 failed"); - expect(null).assertFail() - } - done() - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0015 end *************"); - }) - - /** - * @tc.number testON_CONFLICT_ROLLBACKInTransaction0021 - * @tc.name InsertWithON_CONFLICT_ROLLBACKInTransaction - * @tc.desc conflict insert with ON_CONFLICT_ROLLBACK - */ - it('testON_CONFLICT_ROLLBACKInTransaction0021', 0, async function (done) { - console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0021 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "name": null, - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var num = await transaction.insert("test", valueBucket, - data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK); - console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0021 fail num " + num); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800032) - try { - await transaction.rollback() - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800021); - } - console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0021 success"); - } - done() - console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0021 end *************"); - }) - - /** - * @tc.number testON_CONFLICT_ROLLBACKInTransaction0022 - * @tc.name InsertWithON_CONFLICT_ROLLBACKInTransaction - * @tc.desc conflict insert with ON_CONFLICT_ROLLBACK - */ - it('testON_CONFLICT_ROLLBACKInTransaction0022', 0, async function (done) { - console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0022 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var num = await transaction.insert("test", valueBucket); - console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0022 insert num " + num) - let predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "zhangsan"); - const updateValueBucket = { - "name": null, - "age": 28, - "salary": 25, - "blobType": u8, - } - await transaction.update(updateValueBucket, predicates, data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800032) - try { - await transaction.rollback() - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800014); - } - console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0022 success"); - } - done() - console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0022 end *************"); - }) - - /** - * @tc.number testON_CONFLICT_ROLLBACKInTransaction0023 - * @tc.name BatchInsertWithON_CONFLICT_ROLLBACKInTransaction - * @tc.desc conflict insert with ON_CONFLICT_ROLLBACK - */ - it('testON_CONFLICT_ROLLBACKInTransaction0023', 0, async function (done) { - console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0023 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "name": null, - "age": 18, - "salary": 100.5, - "blobType": u8, - } - let valueBucketArray = new Array(); - valueBucketArray.push(valueBucket); - var num = transaction.batchInsertWithConflictResolutionSync("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK); - console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0023 insert num " + num) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800032) - try { - await transaction.rollback() - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800021); - } - console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0023 success"); - } - done() - console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0023 end *************"); - }) - - /** - * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 - * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs - * @tc.desc batch Insert With ConflictResolution with Invalid Args - */ - it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031', 0, async function (done) { - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction(); - try { - const valueBucket = { - "name": "bbb", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - let valueBucketArray = new Array(); - valueBucketArray.push(valueBucket); - var num = await transaction.batchInsertWithConflictResolution(123, valueBucket, - data_relationalStore.ConflictResolution.ON_CONFLICT_ABORT); - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 insert num " + num) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(String(e.code)).assertEqual(String(401)) - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 success"); - } - await transaction.rollback(); - done() - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 end *************"); - }) - - /** - * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 - * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs - * @tc.desc batch Insert With ConflictResolution with Invalid Args - */ - it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032', 0, async function (done) { - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 start *************"); - var transaction = await rdbStore.createTransaction(); - try { - var num = transaction.batchInsertWithConflictResolutionSync("table", undefined, - data_relationalStore.ConflictResolution.ON_CONFLICT_FAIL); - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 insert num " + num) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(String(e.code)).assertEqual(String(401)) - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 success"); - } - await transaction.rollback(); - done() - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 end *************"); - }) - - /** - * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 - * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs - * @tc.desc batch Insert With ConflictResolution with Invalid Args - */ - it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033', 0, async function (done) { - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "name": "aaa", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - let valueBucketArray = new Array(); - valueBucketArray.push(valueBucket); - var num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, "abc"); - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 insert num " + num) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(String(e.code)).assertEqual(String(401)) - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 success"); - } - await transaction.rollback(); - done() - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 end *************"); - }) - - /** - * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 - * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs - * @tc.desc batch Insert With ConflictResolution with Invalid Args - */ - it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034', 0, async function (done) { - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "name": "aaa", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - let valueBucketArray = new Array(); - valueBucketArray.push(valueBucket); - var num = transaction.batchInsertWithConflictResolutionSync("test", valueBucketArray); - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 insert num " + num) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(String(e.code)).assertEqual(String(401)) - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 success"); - } - await transaction.rollback(); - done() - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 end *************"); - }) - - /** - * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 - * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs - * @tc.desc batch Insert With ConflictResolution with Invalid Args - */ - it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035', 0, async function (done) { - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "name": "aaa", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - let valueBucketArray = new Array(); - let rows = 32768 / 4 + 1; - for (let i = 0; i < rows; i++) { - valueBucketArray.push(valueBucket); - } - var num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, data_relationalStore.ConflictResolution.ON_CONFLICT_NONE); - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 insert num " + num) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(String(e.code)).assertEqual(String(14800000)) - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 success"); - } - await transaction.rollback(); - done() - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 end *************"); - }) - - console.log(TAG + "*************Unit Test End*************"); -}) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstoreConcurrentQueryWithCrud.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstoreConcurrentQueryWithCrud.test.js index cf01c404ec7b52b3b31a806d327954ad78f609d8..42b60537f5d2d28238b6f9d20a0f1e2def3eb326 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstoreConcurrentQueryWithCrud.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbstoreConcurrentQueryWithCrud.test.js @@ -78,8 +78,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(7); done(); @@ -115,8 +115,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(7); done(); @@ -150,6 +150,7 @@ describe('QueryWithCrudTest', function () { const age = resultSet.getString(resultSet.getColumnIndex("age")); console.log(TAG + "age:" + age); expect().assertFail(); + done(); } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); @@ -190,8 +191,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(0); done(); @@ -234,6 +235,7 @@ describe('QueryWithCrudTest', function () { const age = resultSet.getString(resultSet.getColumnIndex("age")); console.log(TAG + "age:" + age); expect().assertFail(); + done(); } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); @@ -282,14 +284,52 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(9); done(); console.log(TAG + "************* QueryWithDelete006 end *************"); }) + /** + * @tc.name Concurrent query and delet test + * @tc.number QueryWithDelete007 + * @tc.desc 10 records with a total of less than 2M data, + * delete 10 records, rowCount equals 0 records. + */ + it('QueryWithDelete007', 0, async function (done) { + console.log(TAG + "************* QueryWithDelete007 start *************"); + let u8 = new Uint8Array(Array(1).fill(1)); + for (let i = 0; i < 10; i++) { + const valueBucket = { + "name": "zhangsan" + String(i), + "age": i, + "salary": 100.5, + "blobType": u8, + }; + await rdbStore.insert("test", valueBucket); + } + let predicates = new relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + predicates.between('age', 0, 9); + let deleteRows = await rdbStore.delete(predicates); + expect(deleteRows).assertEqual(10); + try { + while (resultSet.goToNextRow()) { + const age = resultSet.getString(resultSet.getColumnIndex("age")); + console.log(TAG + "age:" + age); + } + } catch (err) { + console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); + expect().assertFail(); + done(); + } + expect(resultSet.rowCount).assertEqual(0); + done(); + console.log(TAG + "************* QueryWithDelete007 end *************"); + }) + /** * @tc.name Concurrent query and insert test * @tc.number QueryWithInsert001 @@ -328,8 +368,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(7); done(); @@ -376,8 +416,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(9); done(); @@ -421,6 +461,7 @@ describe('QueryWithCrudTest', function () { const age = resultSet.getString(resultSet.getColumnIndex("age")); console.log(TAG + "age:" + age); expect().assertFail(); + done(); } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); @@ -470,8 +511,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(1); done(); @@ -560,8 +601,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(10); done(); @@ -603,8 +644,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(10); done(); @@ -648,8 +689,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(2); done(); @@ -693,8 +734,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } console.log(TAG + "rowCount:" + resultSet.rowCount); done(); diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstoreEncryptionJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstoreEncryptionJsunit.test.js index a62a80d59ced0017af8f53fb6f847816d4cbc98a..5ca13c1a26437604dfb3c21b390bf01dfd780ab7 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstoreEncryptionJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbstoreEncryptionJsunit.test.js @@ -115,7 +115,7 @@ async function CreateRdbStoreAndInsertData(context, store_config) { "y": 1 } let insertPromise = rdbStore.insert("t", valueBucket) - insertPromise.then(async (ret) => { + await insertPromise.then(async (ret) => { expect(1).assertEqual(ret) }) return rdbStore diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstoreRdbstoreJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstoreRdbstoreJsunit.test.js index 72b830c57c6fbf0e240efae7a6964618b836aa80..adf60174bff085d201fa0b30d79b253d13cb8db1 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstoreRdbstoreJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbstoreRdbstoreJsunit.test.js @@ -239,9 +239,9 @@ describe('rdbStoreTest', function () { } await data_relationalStore.getRdbStore(context, config1); - try { await data_relationalStore.getRdbStore(context, config2); + done(); } catch (err) { console.log(TAG + "************* testRdbStore0009 end *************"); } @@ -1387,7 +1387,7 @@ describe('rdbStoreTest', function () { done(); } }) - + /** * @tc.name tokenizer supported test * @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_0051 diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstoreTransactionJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstoreTransactionJsunit.test.js deleted file mode 100644 index c5c595ad31aa13ba0f18c485266b8bb14d1e76cb..0000000000000000000000000000000000000000 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstoreTransactionJsunit.test.js +++ /dev/null @@ -1,288 +0,0 @@ -/* - * 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. - */ - -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' -import data_relationalStore from '@ohos.data.relationalStore' -import ability_featureAbility from '@ohos.ability.featureAbility' -var context = ability_featureAbility.getContext() - -const TAG = "[RELATIONAL_STORE_JSKITS_TEST]" -const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + - "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; - -const STORE_CONFIG = { - name: "TransactionInsertTest.db", - securityLevel: data_relationalStore.SecurityLevel.S1, -} - -var rdbStore = undefined; - -describe('rdbStoreTransactionTest', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll') - rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); - await rdbStore.executeSql(CREATE_TABLE_TEST, null); - }) - - beforeEach(async function () { - console.info(TAG + 'beforeEach') - - }) - - afterEach(async function () { - console.info(TAG + 'afterEach') - await rdbStore.executeSql("DELETE FROM test"); - }) - - afterAll(async function () { - console.info(TAG + 'afterAll') - rdbStore = null - await data_relationalStore.deleteRdbStore(context, "TransactionInsertTest.db"); - }) - - console.log(TAG + "*************Unit Test Begin*************"); - - /** - * @tc.number testRdbTransactionInsert0001 - * @tc.name Normal test case of transactions, insert a row of data - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute commit - * 4.Query data - */ - it('testRdbTransactionInsert0001', 0, async function (done) { - console.log(TAG + "************* testRdbStoreInsert0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - try { - rdbStore.beginTransaction() - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket) - - rdbStore.commit() - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates) - console.log(TAG + "testRdbTransactionInsert0001 result count " + resultSet.rowCount) - expect(1).assertEqual(resultSet.rowCount) - resultSet.close() - } catch (e) { - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testRdbTransactionInsert0001 failed"); - } - done() - console.log(TAG + "************* testRdbTransactionInsert0001 end *************"); - }) - - /** - * @tc.number testRdbTransactionInsert0002 - * @tc.name Normal test case of transaction, insert three rows of data - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute commit - * 4.Query data - */ - it('testRdbTransactionInsert0002', 0, async function (done) { - console.log(TAG + "************* testRdbStoreInsert0002 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - try { - rdbStore.beginTransaction() - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket) - - const valueBucket1 = { - "name": "zhangsan", - "age": 20, - "salary": 9.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket1) - - - const valueBucket2 = { - "name": "wangwu", - "age": 16, - "salary": 99, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket2) - - rdbStore.commit() - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates) - expect(3).assertEqual(resultSet.rowCount) - resultSet.close() - } catch (e) { - expect(null).assertFail() - console.log(TAG + "testRdbTransactionInsert0002 failed"); - } - done() - console.log(TAG + "************* testRdbTransactionInsert0002 end *************"); - }) - - - /** - * @tc.number testRdbTransactionInsert0003 - * @tc.name Normal test case of transaction, query data before commit - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Query data (expect 0 row) - * 4.Insert data - * 5.Execute commit - */ - it('testRdbTransactionInsert0003', 0, async function (done) { - console.log(TAG + "************* testRdbTransactionInsert0003 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - try { - rdbStore.beginTransaction() - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket) - - const valueBucket1 = { - "name": "zhangsan", - "age": 20, - "salary": 9.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket1) - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates) - expect(0).assertEqual(resultSet.rowCount) - resultSet.close() - const valueBucket2 = { - "name": "wangwu", - "age": 16, - "salary": 99, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket2) - - rdbStore.commit() - } catch (e) { - expect(null).assertFail() - console.log(TAG + "testRdbTransactionInsert0003 failed"); - } - done() - console.log(TAG + "************* testRdbTransactionInsert0003 end *************"); - }) - - /** - * @tc.number testRdbTransactionInsert0004 - * @tc.name Abnormal test case of transaction insert, if catch exception then rollback - * @tc.desc 1.Execute beginTransaction - * 2.Insert data (primary key conflict) - * 3.Execute rollBack - * 4.Query data - */ - it('testRdbTransactionRollBack0001', 0, async function (done) { - console.log(TAG + "************* testRdbTransactionRollBack0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - try { - rdbStore.beginTransaction() - const valueBucket = { - "id": 1, - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket) - await rdbStore.insert("test", valueBucket) - - rdbStore.commit() - } catch (e) { - rdbStore.rollBack() - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates) - console.log(TAG + "testRdbTransactionRollBack0001 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount) - resultSet.close() - } - done() - console.log(TAG + "************* testRdbTransactionRollBack0001 end *************"); - }) - - /** - * @tc.number testRdbTransactionInsert0005 - * @tc.name Normal test case of transaction, begin transactions within a transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute beginTransaction - * 4.Insert data - * 5.Execute rollBack - * 6.Insert data - * 7.Execute commit - * 8.Query data - */ - it('testRdbTransactionMulti0003', 0, async function (done) { - console.log(TAG + "************* testRdbTransactionMulti0003 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - try { - rdbStore.beginTransaction() - const valueBucket = { - "id": 1, - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket); - - rdbStore.beginTransaction() - const valueBucket1 = { - "name": "zhangsan", - "age": 20, - "salary": 220.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket1) - - rdbStore.rollBack() - - await rdbStore.insert("test", valueBucket) - rdbStore.commit() - - let predicates = new data_relationalStore.RdbPredicates("test"); - let ret = await rdbStore.query(predicates) - expect(1).assertEqual(ret.rowCount) - ret.close() - } catch (e) { - rdbStore.rollBack() - console.log(TAG + "testRdbTransactionMulti0003 rollback ***** "); - } - done() - console.log(TAG + "************* testRdbTransactionMulti0003 end *************"); - }) - - console.log(TAG + "*************Unit Test End*************"); - -}) \ No newline at end of file diff --git a/relational_store/test/native/appdatafwk/BUILD.gn b/relational_store/test/native/appdatafwk/BUILD.gn index 3d7893bfba4df4e361a43a69d65a93765e8a31d2..a59a48a134ce5537abf0a7fd83e208445dfb87e7 100644 --- a/relational_store/test/native/appdatafwk/BUILD.gn +++ b/relational_store/test/native/appdatafwk/BUILD.gn @@ -30,11 +30,16 @@ config("module_private_config") { ohos_unittest("NativeAppDataFwkTest") { module_out_path = module_output_path - sources = [ "unittest/serializable_test.cpp" ] + sources = [ + "${relational_store_native_path}/appdatafwk/src/serializable.cpp", + "unittest/serializable_test.cpp", + ] configs = [ ":module_private_config" ] external_deps = [ + "json:nlohmann_json_static", + "googletest:gtest_main", "hilog:libhilog", "relational_store:native_appdatafwk", ] @@ -43,7 +48,6 @@ ohos_unittest("NativeAppDataFwkTest") { "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", "${relational_store_innerapi_path}/appdatafwk:relational_common_base", "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", ] } diff --git a/relational_store/test/native/appdatafwk/unittest/serializable_test.cpp b/relational_store/test/native/appdatafwk/unittest/serializable_test.cpp index 4744e929a51fb690bca4710a513148bb005870ba..4eea909404c7a5b261d9435ec792e01acc27c03f 100644 --- a/relational_store/test/native/appdatafwk/unittest/serializable_test.cpp +++ b/relational_store/test/native/appdatafwk/unittest/serializable_test.cpp @@ -222,4 +222,141 @@ HWTEST_F(SerializableTest, ToJson_04, TestSize.Level1) Serializable::json result = Serializable::ToJson(jsonStr); ASSERT_FALSE(result.is_discarded()); } + +/** +* @tc.name: ToJson_05 +* @tc.desc: test string to json of value with numeric type. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, ToJson_05, TestSize.Level1) +{ + std::string jsonStr = "{\"key\": 10}"; + Serializable::json result = Serializable::ToJson(jsonStr); + uint64_t uint64Value; + bool ret = Serializable::GetValue(result, "key", uint64Value); + ASSERT_TRUE(ret); + + std::string jsonStr2 = "{\"key\": 10.0}"; + Serializable::json result2 = Serializable::ToJson(jsonStr2); + double doubleValue; + ret = Serializable::GetValue(result2, "key", doubleValue); + ASSERT_TRUE(ret); +} + +/** +* @tc.name: GetValueTest001 +* @tc.desc: Test to json when type not match. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, GetValueTest001, TestSize.Level1) +{ + std::string jsonStr = "{\"key\": 10}"; + Serializable::json result = Serializable::ToJson(jsonStr); + + std::string value; + bool ret = Serializable::GetValue(result, "key", value); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(result, "notExist", value); + ASSERT_FALSE(ret); + + std::string jsonStr2 = "{\"key\": \"str\"}"; + Serializable::json strResult = Serializable::ToJson(jsonStr2); + int32_t intValue; + ret = Serializable::GetValue(strResult, "key", intValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", intValue); + ASSERT_FALSE(ret); + + uint32_t uintValue; + ret = Serializable::GetValue(strResult, "key", uintValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", uintValue); + ASSERT_FALSE(ret); + + uint64_t uint64Value; + ret = Serializable::GetValue(strResult, "key", uint64Value); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", uint64Value); + ASSERT_FALSE(ret); + + int64_t int64Value; + ret = Serializable::GetValue(strResult, "key", int64Value); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", int64Value); + ASSERT_FALSE(ret); + + bool boolValue; + ret = Serializable::GetValue(strResult, "key", boolValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", boolValue); + ASSERT_FALSE(ret); + + double doubleValue; + ret = Serializable::GetValue(strResult, "key", doubleValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", doubleValue); + ASSERT_FALSE(ret); + + std::vector arrayValue; + ret = Serializable::GetValue(strResult, "key", arrayValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", arrayValue); + ASSERT_FALSE(ret); +} + +/** +* @tc.name: BoundaryTest +* @tc.desc: test boundary. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, BoundaryTest, TestSize.Level1) +{ + struct TestBoundary : public Serializable { + int32_t int32Val; + uint32_t uint32Val; + int64_t int64Val; + uint64_t uint64Val; + bool Marshal(json &node) const override + { + SetValue(node[GET_NAME(int32Val)], int32Val); + SetValue(node[GET_NAME(uint32Val)], uint32Val); + SetValue(node[GET_NAME(int64Val)], int64Val); + SetValue(node[GET_NAME(uint64Val)], uint64Val); + return true; + } + bool Unmarshal(const json &node) override + { + bool success = true; + success = GetValue(node, GET_NAME(int32Val), int32Val) && success; + success = GetValue(node, GET_NAME(uint32Val), uint32Val) && success; + success = GetValue(node, GET_NAME(int64Val), int64Val) && success; + success = GetValue(node, GET_NAME(uint64Val), uint64Val) && success; + return success; + } + }; + TestBoundary in, out; + in.int32Val = INT32_MIN; + in.uint32Val = 0; + in.int64Val = INT64_MIN; + in.uint64Val = 0; + + auto json = to_string(in.Marshall()); + out.Unmarshall(json); + EXPECT_EQ(out.int32Val, in.int32Val); + EXPECT_EQ(out.uint32Val, in.uint32Val); + EXPECT_EQ(out.int64Val, in.int64Val); + EXPECT_EQ(out.uint64Val, in.uint64Val); + + in.int32Val = INT32_MAX; + in.uint32Val = UINT32_MAX; + in.int64Val = INT64_MAX; + in.uint64Val = UINT64_MAX; + + json = to_string(in.Marshall()); + out.Unmarshall(json); + EXPECT_EQ(out.int32Val, in.int32Val); + EXPECT_EQ(out.uint32Val, in.uint32Val); + EXPECT_EQ(out.int64Val, in.int64Val); + EXPECT_EQ(out.uint64Val, in.uint64Val); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/relational_store/test/native/clouddata/BUILD.gn b/relational_store/test/native/clouddata/BUILD.gn index 357e75821a686708a700de27401d07214f2e3f98..e390161b739dcbb6861d580640baa57c3d9b9a2a 100644 --- a/relational_store/test/native/clouddata/BUILD.gn +++ b/relational_store/test/native/clouddata/BUILD.gn @@ -25,6 +25,7 @@ config("module_private_config") { "${relational_store_innerapi_path}/cloud_data/include", "${relational_store_innerapi_path}/common_type/include", "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/rdb_crypt", ] } @@ -33,6 +34,7 @@ ohos_unittest("NativeCloudDataTest") { sources = [ "${cloud_data_native_path}/src/cloud_manager.cpp", + "${cloud_data_native_path}/src/cloud_notifier_stub.cpp", "${cloud_data_native_path}/src/cloud_service_proxy.cpp", "${cloud_data_native_path}/src/cloud_types_util.cpp", "unittest/cloud_data_test.cpp", @@ -54,16 +56,14 @@ ohos_unittest("NativeCloudDataTest") { "access_token:libtoken_setproc", "access_token:libtokenid_sdk", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_mgr", "samgr:samgr_proxy", ] - deps = [ - "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", - ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] } ############################################################################### @@ -73,3 +73,13 @@ group("unittest") { deps = [ ":NativeCloudDataTest" ] } ############################################################################### + +group("fuzztest") { + testonly = true + deps = [] + deps += [ + "fuzztest/cloudnotifierstub_fuzzer:fuzztest", + ] +} + +############################################################################### diff --git a/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/BUILD.gn b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..6111e8da552b2ceda1c2bd5ea373c3fc9aedee1f --- /dev/null +++ b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/BUILD.gn @@ -0,0 +1,60 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("CloudNotifierStubFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/cloud_data/include", + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer" + + sources = [ + "${cloud_data_native_path}/src/cloud_notifier_stub.cpp", + "${relational_store_native_path}/rdb/src/rdb_types_util.cpp", + "cloudnotifierstub_fuzzer.cpp" + ] + + deps = [ "${relational_store_innerapi_path}/cloud_data:cloud_data_inner" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [ ":CloudNotifierStubFuzzTest" ] +} +############################################################################### diff --git a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/gdbstore_fuzzer.cpp b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/cloudnotifierstub_fuzzer.cpp similarity index 40% rename from relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/gdbstore_fuzzer.cpp rename to relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/cloudnotifierstub_fuzzer.cpp index 880eca299b20c75446c040574ad927f687063646..096187c4dd618742c6534cbaf819941c485e1b6b 100644 --- a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/gdbstore_fuzzer.cpp +++ b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/cloudnotifierstub_fuzzer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 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 @@ -12,57 +12,38 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include -#include "gdbstore_fuzzer.h" - -#include "gdb_helper.h" +#include "cloud_notifier_stub.h" using namespace OHOS; -using namespace OHOS::DistributedDataAip; - +using namespace OHOS::CloudData; namespace OHOS { -const std::string DATABASE_NAME = "gdbStoreFuzz"; -const std::string DATABASE_PATH = "/data/test"; -StoreConfig config_(DATABASE_NAME, DATABASE_PATH); - -std::shared_ptr GetStore() -{ - int errCode = 0; - auto store = GDBHelper::GetDBStore(config_, errCode); - return store; -} - -void GdbQueryFuzz(const uint8_t *data, size_t size) -{ - std::string gql(data, data + size); - auto store = GetStore(); - if (store == nullptr) { - return; - } - store->QueryGql(gql); - GDBHelper::DeleteDBStore(config_); -} +const std::u16string INTERFACE_TOKEN = u"OHOS.CloudData.ICloudNotifier"; +constexpr uint32_t CODE_MIN = 0; +constexpr uint32_t CODE_MAX = 2; -void GdbExecuteFuzz(const uint8_t *data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { - std::string gql(data, data + size); - auto store = GetStore(); - if (store == nullptr) { - return; - } - store->ExecuteGql(gql); - GDBHelper::DeleteDBStore(config_); + auto syncCompleteHandler = [](uint32_t, Details &&) {}; + std::shared_ptr notifierStub = std::make_shared(syncCompleteHandler); + uint32_t code = provider.ConsumeIntegralInRange(CODE_MIN, CODE_MAX); + std::vector remainingData = provider.ConsumeRemainingBytes(); + MessageParcel request; + request.WriteInterfaceToken(INTERFACE_TOKEN); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); + request.RewindRead(0); + MessageParcel reply; + MessageOption option; + notifierStub->OnRemoteRequest(code, request, reply, option); + return true; } } // namespace OHOS /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - /* Run your code on data */ - if (data == nullptr) { - return 0; - } - OHOS::GdbQueryFuzz(data, size); - OHOS::GdbExecuteFuzz(data, size); + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); return 0; } \ No newline at end of file diff --git a/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/cloudnotifierstub_fuzzer.h b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/cloudnotifierstub_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..49d25c3abc0bdfc0ff11fe8bd43e564f03b1779f --- /dev/null +++ b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/cloudnotifierstub_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 CLOUD_NOTIFIER_STUB_FUZZER_H +#define CLOUD_NOTIFIER_STUB_FUZZER_H + +#define FUZZ_PROJECT_NAME "cloudnotifierstub_fuzzer" + +#endif // CLOUD_NOTIFIER_STUB_FUZZER_H diff --git a/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/corpus/init b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2aea1356e3c3b3ee6e12ad3f72640897d769d02e --- /dev/null +++ b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ diff --git a/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/project.xml b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/clouddata/unittest/cloud_data_test.cpp b/relational_store/test/native/clouddata/unittest/cloud_data_test.cpp index 0db6e691697d2c665c8c96a7f994f1f1747c1c94..8b583154dad38388e97bdac8bcd20911d641d6c6 100644 --- a/relational_store/test/native/clouddata/unittest/cloud_data_test.cpp +++ b/relational_store/test/native/clouddata/unittest/cloud_data_test.cpp @@ -13,20 +13,27 @@ * limitations under the License. */ +#define LOG_TAG "CloudDataTest" + +#include #include #include #include "accesstoken_kit.h" #include "cloud_manager.h" +#include "cloud_notifier_stub.h" +#include "cloud_service_proxy.h" #include "cloud_types.h" #include "cloud_types_util.h" #include "logger.h" +#include "rdb_types.h" #include "token_setproc.h" namespace OHOS::CloudData { using namespace testing::ext; using namespace OHOS::Security::AccessToken; using namespace OHOS::Rdb; +using namespace DistributedRdb; uint64_t g_selfTokenID = 0; static constexpr const char *TEST_BUNDLE_NAME = "bundleName"; static constexpr const char *TEST_ACCOUNT_ID = "testId"; @@ -146,18 +153,68 @@ public: { SetSelfTokenID(g_selfTokenID); } + + static std::mutex syncCompleteLock_; + static std::condition_variable syncCompleteCv_; + static int32_t progressStatus_; + static int32_t code_; + static constexpr uint32_t delayTime = 2000; }; +std::mutex CloudDataTest::syncCompleteLock_; +std::condition_variable CloudDataTest::syncCompleteCv_; +int32_t CloudDataTest::progressStatus_ = Progress::SYNC_BEGIN; +int32_t CloudDataTest::code_ = ProgressCode::SUCCESS; + void CloudDataTest::SetUpTestCase(void) { + LOG_INFO("SetUpTestCase in."); g_selfTokenID = GetSelfTokenID(); } void CloudDataTest::TearDownTestCase(void) { + LOG_INFO("TearDownTestCase in."); SetSelfTokenID(g_selfTokenID); } +/* * + * @tc.name: CloudSync_SyncComplete_001 + * @tc.desc: Test the CloudSync API with syncComplete callback + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync_SyncComplete_001, TestSize.Level1) +{ + AllocSystemHapToken(g_systemPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&details) { + ASSERT_NE(details.size(), 0); + progressStatus_ = details.begin()->second.progress; + code_ = details.begin()->second.code; + LOG_INFO("CloudSync_SyncComplete_001, progressStatus_:%{public}d, code_:%{public}d", progressStatus_, code_); + if (progressStatus_ == Progress::SYNC_FINISH) { + LOG_INFO("CloudSync_SyncComplete_001, start to notify, progressStatus_:%{public}d, code_:%{public}d", + progressStatus_, code_); + std::unique_lock lock(syncCompleteLock_); + syncCompleteCv_.notify_one(); + } + }; + int32_t syncMode = 4; // 4 is native_first + uint32_t seqNum = 101; + auto status = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, { syncMode, seqNum }, progress); + EXPECT_EQ(status, CloudService::SUCCESS); + std::unique_lock lock(syncCompleteLock_); + auto result = syncCompleteCv_.wait_for(lock, std::chrono::milliseconds(CloudDataTest::delayTime), [] { + LOG_INFO("CloudSync_SyncComplete_001, wait_for in, progressStatus_:%{public}d, code_:%{public}d", + progressStatus_, code_); + return progressStatus_ == Progress::SYNC_FINISH && code_ == ProgressCode::CLOUD_DISABLED; + }); + EXPECT_TRUE(result); + LOG_INFO("CloudSync_SyncComplete_001 test end."); +} + /* * * @tc.name: CloudDataTest_001 * @tc.desc: Test the system application permissions of the QueryStatistics API @@ -180,7 +237,7 @@ HWTEST_F(CloudDataTest, CloudDataTest_001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, CloudDataTest_002, TestSize.Level0) +HWTEST_F(CloudDataTest, CloudDataTest_002, TestSize.Level1) { AllocSystemHapToken(g_notPermissonPolicy); auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -196,7 +253,7 @@ HWTEST_F(CloudDataTest, CloudDataTest_002, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, CloudDataTest_003, TestSize.Level0) +HWTEST_F(CloudDataTest, CloudDataTest_003, TestSize.Level1) { AllocSystemHapToken(g_systemPolicy); auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -259,7 +316,7 @@ HWTEST_F(CloudDataTest, ChangeAppSwitch001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, Clean001, TestSize.Level0) +HWTEST_F(CloudDataTest, Clean001, TestSize.Level1) { AllocSystemHapToken(g_systemPolicy); auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -276,7 +333,7 @@ HWTEST_F(CloudDataTest, Clean001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, NotifyDataChange001, TestSize.Level0) +HWTEST_F(CloudDataTest, NotifyDataChange001, TestSize.Level1) { AllocSystemHapToken(g_systemPolicy); auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -291,7 +348,7 @@ HWTEST_F(CloudDataTest, NotifyDataChange001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, NotifyDataChange002, TestSize.Level0) +HWTEST_F(CloudDataTest, NotifyDataChange002, TestSize.Level1) { AllocSystemHapToken(g_systemPolicy); auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -306,7 +363,7 @@ HWTEST_F(CloudDataTest, NotifyDataChange002, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, SetGlobalCloudStrategy001, TestSize.Level0) +HWTEST_F(CloudDataTest, SetGlobalCloudStrategy001, TestSize.Level1) { AllocSystemHapToken(g_systemPolicy); auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -338,7 +395,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, QueryLastSyncInfo002, TestSize.Level0) +HWTEST_F(CloudDataTest, QueryLastSyncInfo002, TestSize.Level1) { AllocSystemHapToken(g_notPermissonPolicy); auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -514,7 +571,7 @@ HWTEST_F(CloudDataTest, ChangeConfirmation001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, SetCloudStrategy001, TestSize.Level0) +HWTEST_F(CloudDataTest, SetCloudStrategy001, TestSize.Level1) { AllocNormalHapToken(g_normalPolicy); auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -528,4 +585,230 @@ HWTEST_F(CloudDataTest, SetCloudStrategy001, TestSize.Level0) ret = proxy->SetCloudStrategy(strategy, values); EXPECT_EQ(ret, CloudService::SUCCESS); } + +/* * + * @tc.name: CloudSync001 + * @tc.desc: Test the invalid param of the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync001, TestSize.Level1) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto ret = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, {}, nullptr); // no progress + EXPECT_EQ(ret, CloudService::INVALID_ARGUMENT); + LOG_INFO("CloudSync001 test end."); +} + +/* * + * @tc.name: CloudSync002 + * @tc.desc: Test the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync002, TestSize.Level1) +{ + AllocSystemHapToken(g_systemPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&) {}; + auto status = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, {}, progress); + EXPECT_EQ(status, CloudService::INVALID_ARGUMENT); // invalid syncMode + LOG_INFO("CloudSync002 test end."); +} + +/* * + * @tc.name: CloudSync003 + * @tc.desc: Test the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync003, TestSize.Level1) +{ + AllocSystemHapToken(g_systemPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&) {}; + int32_t syncMode = 4; // 4 is native_first + uint32_t seqNum = 10; + auto status = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, { syncMode, seqNum }, progress); + EXPECT_EQ(status, CloudService::SUCCESS); + LOG_INFO("CloudSync003 test end."); +} + +/* * + * @tc.name: CloudSync004 + * @tc.desc: Test the hap permission of the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync004, TestSize.Level1) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&) {}; + int32_t syncMode = 4; // 4 is native_first + uint32_t seqNum = 100; + auto status = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, { syncMode, seqNum }, progress); + EXPECT_EQ(status, CloudService::PERMISSION_DENIED); + LOG_INFO("CloudSync004 test end."); +} + +/* * + * @tc.name: CloudSync005 + * @tc.desc: Test the permissions of the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync005, TestSize.Level1) +{ + AllocSystemHapToken(g_notPermissonPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&) {}; + int32_t syncMode = 4; // 4 is native_first + uint32_t seqNum = 1000; + auto status = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, { syncMode, seqNum }, progress); + EXPECT_EQ(status, CloudService::CLOUD_CONFIG_PERMISSION_DENIED); + LOG_INFO("CloudSync005 test end."); +} + +/* * + * @tc.name: CloudSync006 + * @tc.desc: Test the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync006, TestSize.Level1) +{ + AllocSystemHapToken(g_systemPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&) {}; + int32_t syncMode = 4; // 4 is native_first + uint32_t seqNum = 20; + auto status = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, { syncMode, seqNum }, progress); + EXPECT_EQ(status, CloudService::SUCCESS); + + // same seqNum, register progress failed. + status = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, { syncMode, seqNum }, progress); + EXPECT_EQ(status, CloudService::ERROR); + LOG_INFO("CloudSync006 test end."); +} + +/* * + * @tc.name: CloudSync007 + * @tc.desc: Test the invalid param of the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync007, TestSize.Level1) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&) {}; + int32_t syncMode = 4; // 4 is native_first + uint32_t seqNum = 21; + auto ret = proxy->CloudSync("", TEST_STORE_ID, { syncMode, seqNum }, progress); // bundleName is empty + EXPECT_EQ(ret, CloudService::INVALID_ARGUMENT); + LOG_INFO("CloudSync007 test end."); +} + +/* * + * @tc.name: CloudSync008 + * @tc.desc: Test the invalid param of the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync008, TestSize.Level1) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&) {}; + int32_t syncMode = 4; // 4 is native_first + uint32_t seqNum = 22; + auto ret = proxy->CloudSync(TEST_BUNDLE_NAME, "", { syncMode, seqNum }, progress); // storeId is empty + EXPECT_EQ(ret, CloudService::INVALID_ARGUMENT); + LOG_INFO("CloudSync008 test end."); +} + +/* * + * @tc.name: CloudSync009 + * @tc.desc: Test the invalid param of the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync009, TestSize.Level1) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&) {}; + int32_t syncMode = 10; + uint32_t seqNum = 22; + auto ret = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, { syncMode, seqNum }, progress); // invalid syncMode + EXPECT_EQ(ret, CloudService::INVALID_ARGUMENT); + LOG_INFO("CloudSync009 test end."); +} + +/* * + * @tc.name: InitNotifier001 + * @tc.desc: Test the InitNotifier API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, InitNotifier001, TestSize.Level1) +{ + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + sptr notifier = nullptr; + auto status = proxy->InitNotifier(notifier); // can not Marshalling a 'nullptr' + EXPECT_EQ(status, CloudService::IPC_PARCEL_ERROR); + LOG_INFO("InitNotifier001 test end."); +} + +/* * + * @tc.name: InitNotifier002 + * @tc.desc: Test the InitNotifier API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, InitNotifier002, TestSize.Level1) +{ + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + sptr notifier = new (std::nothrow) CloudNotifierStub(nullptr); + auto status = proxy->InitNotifier(notifier); + EXPECT_EQ(status, CloudService::SUCCESS); + LOG_INFO("InitNotifier002 test end."); +} + +/* * + * @tc.name: MarshallingOptionTest + * @tc.desc: Test the Marshalling interface + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, MarshallingOptionTest, TestSize.Level1) +{ + LOG_INFO("MarshallingOptionTest test in."); + CloudData::CloudService::Option input; + input.syncMode = 4; + input.seqNum = 10; + MessageParcel parcel; + bool ret = ITypesUtil::Marshalling(input, parcel); + EXPECT_TRUE(ret); + + CloudData::CloudService::Option output; + ret = ITypesUtil::Unmarshalling(output, parcel); + EXPECT_TRUE(ret); + EXPECT_EQ(output.syncMode, input.syncMode); + EXPECT_EQ(output.seqNum, input.seqNum); + LOG_INFO("MarshallingOptionTest test end."); +} } // namespace OHOS::CloudData \ No newline at end of file diff --git a/relational_store/test/native/dataability/BUILD.gn b/relational_store/test/native/dataability/BUILD.gn index 375dcf415026a16801a657731e238ccb031f5a91..a34491e49fa9996fd7caec510b19c21f277d517d 100644 --- a/relational_store/test/native/dataability/BUILD.gn +++ b/relational_store/test/native/dataability/BUILD.gn @@ -22,7 +22,6 @@ config("module_private_config") { include_dirs = [ "${relational_store_native_path}/dataability/include", "${relational_store_innerapi_path}/dataability/include", - "//commonlibrary/c_utils/base/include", ] } @@ -35,15 +34,13 @@ ohos_unittest("NativeDataAbilityTest") { external_deps = [ "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "relational_store:native_dataability", "relational_store:native_rdb", ] - deps = [ - "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", - ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] } ############################################################################### diff --git a/relational_store/test/native/gdb/BUILD.gn b/relational_store/test/native/gdb/BUILD.gn deleted file mode 100644 index 4b1f8e90cd486bd789186fcfce650b176180a302..0000000000000000000000000000000000000000 --- a/relational_store/test/native/gdb/BUILD.gn +++ /dev/null @@ -1,221 +0,0 @@ -# Copyright (c) 2025 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/test.gni") -import("//foundation/distributeddatamgr/relational_store/relational_store.gni") - -module_output_path = "relational_store/relational_store/native_gdb" - -base_sources = [ - "${relational_store_native_path}/gdb/adapter/src/grd_adapter.cpp", - "${relational_store_native_path}/gdb/adapter/src/grd_adapter_manager.cpp", - "${relational_store_native_path}/gdb/src/connection.cpp", - "${relational_store_native_path}/gdb/src/connection_pool.cpp", - "${relational_store_native_path}/gdb/src/db_helper.cpp", - "${relational_store_native_path}/gdb/src/db_store_impl.cpp", - "${relational_store_native_path}/gdb/src/db_store_manager.cpp", - "${relational_store_native_path}/gdb/src/edge.cpp", - "${relational_store_native_path}/gdb/src/full_result.cpp", - "${relational_store_native_path}/gdb/src/gdb_utils.cpp", - "${relational_store_native_path}/gdb/src/graph_connection.cpp", - "${relational_store_native_path}/gdb/src/graph_statement.cpp", - "${relational_store_native_path}/gdb/src/path.cpp", - "${relational_store_native_path}/gdb/src/path_segment.cpp", - "${relational_store_native_path}/gdb/src/store_config.cpp", - "${relational_store_native_path}/gdb/src/trans_db.cpp", - "${relational_store_native_path}/gdb/src/transaction.cpp", - "${relational_store_native_path}/gdb/src/transaction_impl.cpp", - "${relational_store_native_path}/gdb/src/vertex.cpp", - "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", - "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", - "${relational_store_native_path}/rdb/src/rdb_time_utils.cpp", - "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", - "${relational_store_native_path}/rdb/src/string_utils.cpp", -] - -############################################################################### - -ohos_unittest("NativeGdbTest") { - module_out_path = module_output_path - - include_dirs = [ - "${relational_store_common_path}/include", - "${relational_store_innerapi_path}/gdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${relational_store_native_path}/gdb/include", - "${relational_store_native_path}/gdb/adapter/include", - "${relational_store_native_path}/rdb/include", - ] - - sources = base_sources - sources += [ - "unittest/gdb_encrypt_test.cpp", - "unittest/gdb_execute_test.cpp", - "unittest/gdb_function_test.cpp", - "unittest/gdb_grdapi_test.cpp", - "unittest/gdb_multi_thread_test.cpp", - "unittest/gdb_query_test.cpp", - "unittest/gdb_transaction_test.cpp", - ] - - external_deps = [ - "c_utils:utils", - "file_api:securitylabel", - "googletest:gtest_main", - "hilog:libhilog", - "hisysevent:libhisysevent", - "hitrace:hitrace_meter", - "huks:libhukssdk", - "json:nlohmann_json_static", - "kv_store:distributeddata_inner", - ] - if (arkdata_db_core_is_exists) { - defines = [ "ARKDATA_DB_CORE_IS_EXISTS" ] - } -} - -ohos_unittest("NativeGdbAdaptTest") { - module_out_path = module_output_path - - include_dirs = [ - "${relational_store_common_path}/include", - "${relational_store_innerapi_path}/gdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${relational_store_native_path}/gdb/include", - "${relational_store_native_path}/gdb/adapter/include", - "${relational_store_native_path}/rdb/include", - ] - - sources = base_sources - sources += [ "unittest/gdb_adapt_test.cpp" ] - - external_deps = [ - "c_utils:utils", - "file_api:securitylabel", - "googletest:gmock", - "googletest:gtest_main", - "hilog:libhilog", - "hisysevent:libhisysevent", - "hitrace:hitrace_meter", - "huks:libhukssdk", - "json:nlohmann_json_static", - "kv_store:distributeddata_inner", - ] - if (arkdata_db_core_is_exists) { - defines = [ "ARKDATA_DB_CORE_IS_EXISTS" ] - } -} - -ohos_unittest("NativeGdbGrdAdapterTest") { - module_out_path = module_output_path - - include_dirs = [ - "${relational_store_common_path}/include", - "${relational_store_innerapi_path}/gdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${relational_store_native_path}/gdb/include", - "${relational_store_native_path}/gdb/adapter/include", - "${relational_store_native_path}/rdb/include", - ] - - sources = [ - "${relational_store_native_path}/gdb/adapter/src/grd_adapter_manager.cpp", - "${relational_store_native_path}/gdb/src/connection.cpp", - "${relational_store_native_path}/gdb/src/connection_pool.cpp", - "${relational_store_native_path}/gdb/src/db_helper.cpp", - "${relational_store_native_path}/gdb/src/db_store_impl.cpp", - "${relational_store_native_path}/gdb/src/db_store_manager.cpp", - "${relational_store_native_path}/gdb/src/edge.cpp", - "${relational_store_native_path}/gdb/src/full_result.cpp", - "${relational_store_native_path}/gdb/src/gdb_utils.cpp", - "${relational_store_native_path}/gdb/src/graph_connection.cpp", - "${relational_store_native_path}/gdb/src/graph_statement.cpp", - "${relational_store_native_path}/gdb/src/path.cpp", - "${relational_store_native_path}/gdb/src/path_segment.cpp", - "${relational_store_native_path}/gdb/src/store_config.cpp", - "${relational_store_native_path}/gdb/src/trans_db.cpp", - "${relational_store_native_path}/gdb/src/transaction.cpp", - "${relational_store_native_path}/gdb/src/transaction_impl.cpp", - "${relational_store_native_path}/gdb/src/vertex.cpp", - "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", - "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", - "${relational_store_native_path}/rdb/src/rdb_time_utils.cpp", - "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", - "${relational_store_native_path}/rdb/src/string_utils.cpp", - "mock/grd_adapter.cpp", - "unittest/gdb_grd_adapter_test.cpp", - ] - - external_deps = [ - "c_utils:utils", - "file_api:securitylabel", - "googletest:gmock", - "googletest:gtest_main", - "hilog:libhilog", - "hisysevent:libhisysevent", - "hitrace:hitrace_meter", - "huks:libhukssdk", - "json:nlohmann_json_static", - ] - - if (arkdata_db_core_is_exists) { - defines = [ "ARKDATA_DB_CORE_IS_EXISTS" ] - } -} - -ohos_unittest("NativeGdbStoreConfigTest") { - module_out_path = module_output_path - - include_dirs = [ - "${relational_store_common_path}/include", - "${relational_store_innerapi_path}/gdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${relational_store_native_path}/gdb/include", - "${relational_store_native_path}/rdb/include", - ] - - sources = [ - "${relational_store_native_path}/gdb/src/store_config.cpp", - "unittest/gdb_store_config_test.cpp", - ] - - external_deps = [ - "c_utils:utils", - "googletest:gtest_main", - "hilog:libhilog", - "huks:libhukssdk", - ] - if (arkdata_db_core_is_exists) { - defines = [ "ARKDATA_DB_CORE_IS_EXISTS" ] - } -} - -############################################################################### -group("unittest") { - testonly = true - - deps = [ - ":NativeGdbAdaptTest", - ":NativeGdbGrdAdapterTest", - ":NativeGdbStoreConfigTest", - ":NativeGdbTest", - ] -} - -############################################################################### - -group("fuzztest") { - testonly = true - deps = [] - deps += [ "fuzztest/gdbstore_fuzzer:fuzztest" ] -} -############################################################################### diff --git a/relational_store/test/native/gdb/mock/grd_adapter.cpp b/relational_store/test/native/gdb/mock/grd_adapter.cpp deleted file mode 100644 index 35d4e81ff8360e298c9bf0a1bbe8910d5a1218ee..0000000000000000000000000000000000000000 --- a/relational_store/test/native/gdb/mock/grd_adapter.cpp +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Copyright (c) 2025 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 "grd_adapter.h" - -#include -#include - -#include "gdb_errors.h" -#include "gdb_utils.h" -#include "grd_adapter_manager.h" -#include "grd_error.h" - -namespace OHOS::DistributedDataAip { - -static GrdAdapterHolder g_adapterHolder; - -int32_t GrdAdapter::errorCode_[FuncName::ALL] = { GRD_OK }; - -std::map GrdAdapter::GRD_ERRNO_MAP = { - { GRD_OK, E_OK }, - { GRD_REBUILD_DATABASE, E_OK }, - { GRD_NO_DATA, E_GRD_NO_DATA }, - { GRD_DATA_CORRUPTED, E_GRD_DATA_CORRUPTED }, - { GRD_INVALID_FILE_FORMAT, E_GRD_INVALID_FILE_FORMAT }, - { GRD_PRIMARY_KEY_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_RESTRICT_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_CONSTRAINT_CHECK_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_NOT_SUPPORT, E_GRD_NOT_SUPPORT }, - { GRD_OVER_LIMIT, E_GRD_OVER_LIMIT }, - { GRD_INVALID_ARGS, E_GRD_INVALID_ARGS }, - { GRD_FAILED_FILE_OPERATION, E_GRD_FAILED_FILE_OPERATION }, - { GRD_INSUFFICIENT_SPACE, E_GRD_DISK_SPACE_FULL }, - { GRD_RESOURCE_BUSY, E_DATABASE_BUSY }, - { GRD_DB_BUSY, E_DATABASE_BUSY }, - { GRD_FAILED_MEMORY_ALLOCATE, E_GRD_FAILED_MEMORY_ALLOCATE }, - { GRD_CRC_CHECK_DISABLED, E_GRD_CRC_CHECK_DISABLED }, - { GRD_DISK_SPACE_FULL, E_GRD_DISK_SPACE_FULL }, - - { GRD_PERMISSION_DENIED, E_GRD_PERMISSION_DENIED }, - { GRD_PASSWORD_UNMATCHED, E_GRD_PASSWORD_UNMATCHED }, - { GRD_PASSWORD_NEED_REKEY, E_GRD_PASSWORD_NEED_REKEY }, - - { GRD_NAME_TOO_LONG, E_GRD_INVALID_NAME }, - { GRD_INVALID_TABLE_DEFINITION, E_GRD_SEMANTIC_ERROR }, - { GRD_SEMANTIC_ERROR, E_GRD_SEMANTIC_ERROR }, - { GRD_SYNTAX_ERROR, E_GRD_SYNTAX_ERROR }, - { GRD_WRONG_STMT_OBJECT, E_GRD_WRONG_STMT_OBJECT }, - { GRD_DATA_CONFLICT, E_GRD_DATA_CONFLICT }, - - { GRD_INNER_ERR, E_GRD_INNER_ERR }, - { GRD_FAILED_MEMORY_RELEASE, E_GRD_FAILED_MEMORY_RELEASE }, - { GRD_NOT_AVAILABLE, E_GRD_NOT_AVAILABLE }, - { GRD_INVALID_FORMAT, E_GRD_SEMANTIC_ERROR }, - { GRD_TIME_OUT, E_DATABASE_BUSY }, - { GRD_DB_INSTANCE_ABNORMAL, E_GRD_DB_INSTANCE_ABNORMAL }, - { GRD_CIPHER_ERROR, E_GRD_CIPHER_ERROR }, - { GRD_DUPLICATE_TABLE, E_GRD_DUPLICATE_PARAM }, - { GRD_DUPLICATE_OBJECT, E_GRD_DUPLICATE_PARAM }, - { GRD_DUPLICATE_COLUMN, E_GRD_DUPLICATE_PARAM }, - { GRD_UNDEFINE_COLUMN, E_GRD_UNDEFINED_PARAM }, - { GRD_UNDEFINED_OBJECT, E_GRD_UNDEFINED_PARAM }, - { GRD_UNDEFINED_TABLE, E_GRD_UNDEFINED_PARAM }, - { GRD_INVALID_CONFIG_VALUE, E_CONFIG_INVALID_CHANGE }, - { GRD_REQUEST_TIME_OUT, E_DATABASE_BUSY }, - { GRD_DATATYPE_MISMATCH, E_GRD_SEMANTIC_ERROR }, - { GRD_UNIQUE_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_INVALID_BIND_VALUE, E_GRD_INVALID_BIND_VALUE }, - { GRD_JSON_OPERATION_NOT_SUPPORT, E_GRD_SEMANTIC_ERROR }, - { GRD_MODEL_NOT_SUPPORT, E_GRD_SEMANTIC_ERROR }, - { GRD_FEATURE_NOT_SUPPORTED, E_GRD_SEMANTIC_ERROR }, - { GRD_JSON_LEN_LIMIT, E_GRD_DATA_CONFLICT }, - { GRD_SUBSCRIPTION_EXCEEDED_LIMIT, E_GRD_INNER_ERR }, - { GRD_SYNC_EXCEED_TASK_QUEUE_LIMIT, E_DATABASE_BUSY }, - { GRD_SHARED_OBJ_ENABLE_UNDO_EXCEED_LIMIT, E_GRD_INNER_ERR }, - { GRD_TABLE_LIMIT_EXCEEDED, E_GRD_OVER_LIMIT }, - { GRD_FIELD_TYPE_NOT_MATCH, E_GRD_SEMANTIC_ERROR }, - { GRD_LARGE_JSON_NEST, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_JSON_TYPE, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_OPERATOR, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_PROJECTION_FIELD, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_PROJECTION_VALUE, E_GRD_SEMANTIC_ERROR }, - { GRD_DB_NOT_EXIST, E_GRD_DB_NOT_EXIST }, - { GRD_INVALID_VALUE, E_GRD_INVALID_ARGS }, - { GRD_SHARED_OBJ_NOT_EXIST, E_GRD_DATA_NOT_FOUND }, - { GRD_SUBSCRIBE_NOT_EXIST, E_GRD_DATA_NOT_FOUND }, - { GRD_COLLECTION_NOT_EXIST, E_GRD_DATA_NOT_FOUND }, - { GRD_RESULTSET_BUSY, E_DATABASE_BUSY }, - { GRD_RECORD_NOT_FOUND, E_GRD_DATA_NOT_FOUND }, - { GRD_FIELD_NOT_FOUND, E_GRD_DATA_NOT_FOUND }, - { GRD_ARRAY_INDEX_NOT_FOUND, E_GRD_DATA_NOT_FOUND }, - { GRD_RESULT_SET_NOT_AVAILABLE, E_GRD_DATA_NOT_FOUND }, - { GRD_SHARED_OBJ_UNDO_NOT_AVAILABLE, E_GRD_DATA_NOT_FOUND }, - { GRD_SHARED_OBJ_REDO_NOT_AVAILABLE, E_GRD_DATA_NOT_FOUND }, - { GRD_INVALID_JSON_FORMAT, E_GRD_DATA_CONFLICT }, - { GRD_INVALID_KEY_FORMAT, E_GRD_INVALID_NAME }, - { GRD_INVALID_COLLECTION_NAME, E_GRD_INVALID_NAME }, - { GRD_INVALID_EQUIP_ID, E_GRD_SEMANTIC_ERROR }, - { GRD_KEY_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_FIELD_TYPE_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_SHARED_OBJ_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_SUBSCRIBE_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_EQUIP_ID_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_SHARED_OBJ_ENABLE_UNDO_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_SCHEMA_CHANGED, E_CONFIG_INVALID_CHANGE }, - { GRD_DATA_EXCEPTION, E_GRD_DATA_EXCEPTION }, - { GRD_FIELD_OVERFLOW, E_GRD_SEMANTIC_ERROR }, - { GRD_DIVISION_BY_ZERO, E_GRD_SYNTAX_ERROR }, - { GRD_TRANSACTION_ROLLBACK, E_GRD_TRANSACTION_ROLLBACK }, - { GRD_NO_ACTIVE_TRANSACTION, E_GRD_NO_ACTIVE_TRANSACTION }, - { GRD_ACTIVE_TRANSACTION, E_GRD_ACTIVE_TRANSACTION }, -}; - -int GrdAdapter::TransErrno(int err) -{ - if (err > 0) { - return err; - } - auto result = GRD_ERRNO_MAP.find(err); - if (result != GRD_ERRNO_MAP.end()) { - return result->second; - } - return E_GRD_INNER_ERR; -} - -void GrdAdapter::SetErrorCode(FuncName func, int32_t err) -{ - if (func == FuncName::ALL) { - for (int i = FuncName::PREPARE; i < FuncName::ALL; i++) { - errorCode_[i] = err; - } - } else { - errorCode_[func] = err; - } -} - -int32_t GrdAdapter::Prepare(GRD_DB *db, const char *str, uint32_t strLen, GRD_StmtT **stmt, const char **unusedStr) -{ - if (errorCode_[FuncName::PREPARE] == GRD_OK) { - if (g_adapterHolder.Prepare == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Prepare == nullptr) { - return E_NOT_SUPPORT; - } - int32_t ret = g_adapterHolder.Prepare(db, str, strLen, stmt, unusedStr); - return TransErrno(ret); - } - return TransErrno(errorCode_[FuncName::PREPARE]); -} - -int32_t GrdAdapter::Step(GRD_StmtT *stmt) -{ - if (errorCode_[FuncName::STEP] == GRD_OK) { - if (g_adapterHolder.Step == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Step == nullptr) { - return E_NOT_SUPPORT; - } - int32_t ret = g_adapterHolder.Step(stmt); - return TransErrno(ret); - } - return TransErrno(errorCode_[FuncName::STEP]); -} - -int32_t GrdAdapter::Finalize(GRD_StmtT *stmt) -{ - if (errorCode_[FuncName::FINALIZE] == GRD_OK) { - if (g_adapterHolder.Finalize == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Finalize == nullptr) { - return E_NOT_SUPPORT; - } - int32_t ret = g_adapterHolder.Finalize(stmt); - return TransErrno(ret); - } - return TransErrno(errorCode_[FuncName::FINALIZE]); -} - -int32_t GrdAdapter::Rekey(const char *dbFile, const char *configStr, const std::vector &encryptedKey) -{ - if (errorCode_[FuncName::REKEY] == GRD_OK) { - if (g_adapterHolder.Rekey == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Rekey == nullptr) { - return E_NOT_SUPPORT; - } - if (encryptedKey.empty()) { - return E_GRD_INVALID_ARGS; - } - int32_t ret = E_OK; - GRD_CipherInfoT info = { 0 }; - const size_t keySize = encryptedKey.size() * 2 + 1; - std::vector key(keySize); - info.hexPassword = GdbUtils::GetEncryptKey(encryptedKey, key.data(), keySize); - ret = g_adapterHolder.Rekey(dbFile, configStr, &info); - key.assign(keySize, 0); - return TransErrno(ret); - } - return TransErrno(errorCode_[FuncName::REKEY]); -} - -ColumnType GrdAdapter::TransColType(int grdColType) -{ - switch (grdColType) { - case GRD_DB_DATATYPE_INTEGER: - return ColumnType::TYPE_INTEGER; - case GRD_DB_DATATYPE_FLOAT: - return ColumnType::TYPE_FLOAT; - case GRD_DB_DATATYPE_TEXT: - return ColumnType::TYPE_TEXT; - case GRD_DB_DATATYPE_BLOB: - return ColumnType::TYPE_BLOB; - case GRD_DB_DATATYPE_FLOATVECTOR: - return ColumnType::TYPE_FLOATVECTOR; - case GRD_DB_DATATYPE_JSONSTR: - return ColumnType::TYPE_JSONSTR; - case GRD_DB_DATATYPE_NULL: - return ColumnType::TYPE_NULL; - default: - return ColumnType::TYPE_NULL; - } -} - -int GrdAdapter::Open(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB **db) -{ - if (g_adapterHolder.Open == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Open == nullptr) { - return E_NOT_SUPPORT; - } - auto ret = g_adapterHolder.Open(dbPath, configStr, flags, db); - return TransErrno(ret); -} - -int GrdAdapter::Close(GRD_DB *db, uint32_t flags) -{ - if (g_adapterHolder.Close == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Close == nullptr) { - return E_NOT_SUPPORT; - } - auto ret = g_adapterHolder.Close(db, flags); - return TransErrno(ret); -} - -int GrdAdapter::Repair(const char *dbPath, const char *configStr) -{ - if (g_adapterHolder.Repair == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Repair == nullptr) { - return E_NOT_SUPPORT; - } - return E_NOT_SUPPORT; -} - -int GrdAdapter::Backup(GRD_DB *db, const char *backupDbFile, const std::vector &encryptedKey) -{ - if (g_adapterHolder.Backup == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Backup == nullptr) { - return E_NOT_SUPPORT; - } - return E_NOT_SUPPORT; -} - -int GrdAdapter::Restore(const char *dbFile, const char *backupDbFile, const std::vector &encryptedKey) -{ - if (g_adapterHolder.Restore == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Restore == nullptr) { - return E_NOT_SUPPORT; - } - return E_NOT_SUPPORT; -} - -int32_t GrdAdapter::Reset(GRD_StmtT *stmt) -{ - if (g_adapterHolder.Reset == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Reset == nullptr) { - return E_NOT_SUPPORT; - } - return TransErrno(g_adapterHolder.Reset(stmt)); -} - -uint32_t GrdAdapter::ColumnCount(GRD_StmtT *stmt) -{ - if (g_adapterHolder.ColumnCount == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnCount == nullptr) { - return E_NOT_SUPPORT; - } - return g_adapterHolder.ColumnCount(stmt); -} - -GRD_DbDataTypeE GrdAdapter::ColumnType(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.GetColumnType == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.GetColumnType == nullptr) { - return GRD_DB_DATATYPE_NULL; - } - return g_adapterHolder.GetColumnType(stmt, idx); -} - -uint32_t GrdAdapter::ColumnBytes(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnBytes == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnBytes == nullptr) { - return E_NOT_SUPPORT; - } - return g_adapterHolder.ColumnBytes(stmt, idx); -} - -char *GrdAdapter::ColumnName(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnName == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnName == nullptr) { - return nullptr; - } - return g_adapterHolder.ColumnName(stmt, idx); -} - -GRD_DbValueT GrdAdapter::ColumnValue(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnValue == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnValue == nullptr) { - return {}; - } - return g_adapterHolder.ColumnValue(stmt, idx); -} - -int64_t GrdAdapter::ColumnInt64(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnInt64 == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnInt64 == nullptr) { - return 0; - } - return g_adapterHolder.ColumnInt64(stmt, idx); -} - -int32_t GrdAdapter::ColumnInt(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnInt == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnInt == nullptr) { - return 0; - } - return g_adapterHolder.ColumnInt(stmt, idx); -} - -double GrdAdapter::ColumnDouble(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnDouble == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnDouble == nullptr) { - return 0; - } - return g_adapterHolder.ColumnDouble(stmt, idx); -} - -const char *GrdAdapter::ColumnText(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnText == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnText == nullptr) { - return nullptr; - } - return g_adapterHolder.ColumnText(stmt, idx); -} -} - diff --git a/relational_store/test/native/gdb/mock/grd_adapter.h b/relational_store/test/native/gdb/mock/grd_adapter.h deleted file mode 100644 index c1b1054715b9eb1b7d5cb44212f32dd88ed4188b..0000000000000000000000000000000000000000 --- a/relational_store/test/native/gdb/mock/grd_adapter.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2025 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_NATIVE_MOCK_GRD_ADAPTER_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_MOCK_GRD_ADAPTER_H - -#include -#include -#include -#include - -#include "full_result.h" -#include "grd_error.h" -#include "grd_type_export.h" -#include "statement.h" - -namespace OHOS::DistributedDataAip { -class GrdAdapter { -public: - enum FuncName : int32_t { - PREPARE = 0, - STEP, - FINALIZE, - REKEY, - ALL - }; - - static void SetErrorCode(FuncName func, int32_t err); - - static int32_t Prepare(GRD_DB *db, const char *str, uint32_t strLen, GRD_StmtT **stmt, const char **unusedStr); - static int32_t Step(GRD_StmtT *stmt); - static int32_t Finalize(GRD_StmtT *stmt); - static int32_t Rekey(const char *dbFile, const char *configStr, const std::vector &encryptedKey); - - static ColumnType TransColType(int grdColType); - static int Open(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB **db); - static int Repair(const char *dbPath, const char *configStr); - static int Close(GRD_DB *db, uint32_t flags); - static int32_t Reset(GRD_StmtT *stmt); - static uint32_t ColumnCount(GRD_StmtT *stmt); - static GRD_DbDataTypeE ColumnType(GRD_StmtT *stmt, uint32_t idx); - static uint32_t ColumnBytes(GRD_StmtT *stmt, uint32_t idx); - static char *ColumnName(GRD_StmtT *stmt, uint32_t idx); - static GRD_DbValueT ColumnValue(GRD_StmtT *stmt, uint32_t idx); - static int64_t ColumnInt64(GRD_StmtT *stmt, uint32_t idx); - static int32_t ColumnInt(GRD_StmtT *stmt, uint32_t idx); - static double ColumnDouble(GRD_StmtT *stmt, uint32_t idx); - static const char *ColumnText(GRD_StmtT *stmt, uint32_t idx); - - static int Backup(GRD_DB *db, const char *backupDbFile, const std::vector &encryptedKey); - static int Restore(const char *dbFile, const char *backupDbFile, const std::vector &encryptedKey); - -private: - static int TransErrno(int err); - - static int32_t errorCode_[FuncName::ALL]; - static std::map GRD_ERRNO_MAP; -}; -} -#endif // OHOS_DISTRIBUTED_DATA_NATIVE_MOCK_GRD_ADAPTER_H - diff --git a/relational_store/test/native/gdb/unittest/gdb_adapt_test.cpp b/relational_store/test/native/gdb/unittest/gdb_adapt_test.cpp deleted file mode 100644 index d480ad837eca67cd43c8d66f5448900c05b0e8fd..0000000000000000000000000000000000000000 --- a/relational_store/test/native/gdb/unittest/gdb_adapt_test.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) 2025 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 -#include - -#include "gmock/gmock.h" -#include "grd_adapter_manager.h" -#include "grd_adapter.h" -#include "gdb_store.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; -using ::testing::Return; -using ::testing::NiceMock; -class MockDlsym { -public: - MOCK_METHOD(void *, dlopen, (const char *fileName, int flag)); - MOCK_METHOD(void *, dlsym, (void *handle, const char *symbol)); -}; - -NiceMock *mockDlsym; - -extern "C" { - // mock dlopen - void *dlopen(const char *fileName, int flag) - { - if (mockDlsym == nullptr) { - mockDlsym = new NiceMock(); - } - return mockDlsym->dlopen(fileName, flag); - } - - // mock dlsym - void *dlsym(void *handle, const char *symbol) - { - if (mockDlsym == nullptr) { - mockDlsym = new NiceMock(); - } - return mockDlsym->dlsym(handle, symbol); - } -} - -class GdbAdaptTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - void MockAllSymbols(); - static const std::string databaseName; - static const std::string databasePath; - const std::vector> mockSymbols = { - {"GRD_DBOpen", reinterpret_cast(0x1111)}, - {"GRD_DBClose", reinterpret_cast(0x2222)}, - {"GRD_DBRepair", reinterpret_cast(0x3333)}, - {"GRD_GqlPrepare", reinterpret_cast(0x4444)}, - {"GRD_GqlReset", reinterpret_cast(0x5555)}, - {"GRD_GqlFinalize", reinterpret_cast(0x6666)}, - {"GRD_GqlStep", reinterpret_cast(0x7777)}, - {"GRD_GqlColumnCount", reinterpret_cast(0x8888)}, - {"GRD_GqlColumnType", reinterpret_cast(0x9999)}, - {"GRD_GqlColumnBytes", reinterpret_cast(0xaaaa)}, - {"GRD_GqlColumnName", reinterpret_cast(0xbbbb)}, - {"GRD_GqlColumnValue", reinterpret_cast(0xcccc)}, - {"GRD_GqlColumnInt64", reinterpret_cast(0xdddd)}, - {"GRD_GqlColumnInt", reinterpret_cast(0xeeee)}, - {"GRD_GqlColumnDouble", reinterpret_cast(0xffff)}, - {"GRD_GqlColumnText", reinterpret_cast(0x1112)}, - {"GRD_DBBackup", reinterpret_cast(0x1222)}, - {"GRD_DBRestore", reinterpret_cast(0x1333)}, - {"GRD_DBRekey", reinterpret_cast(0x1444)}, - }; -}; - -const std::string GdbAdaptTest::databaseName = "execute_test"; -const std::string GdbAdaptTest::databasePath = "/data"; - -void GdbAdaptTest::SetUpTestCase(void) -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } - mockDlsym = new NiceMock(); -} - -void GdbAdaptTest::TearDownTestCase(void) -{ - delete mockDlsym; - mockDlsym = nullptr; -} - -void GdbAdaptTest::SetUp() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } -} - -void GdbAdaptTest::TearDown() -{ -} - -void GdbAdaptTest::MockAllSymbols() -{ - EXPECT_CALL(*mockDlsym, dlopen(::testing::_, RTLD_LAZY)) - .WillRepeatedly(Return(reinterpret_cast(0x1234))); - - for (const auto &symbol : mockSymbols) { - EXPECT_CALL(*mockDlsym, dlsym(::testing::_, ::testing::StrEq(symbol.first.c_str()))) - .WillRepeatedly(Return(symbol.second)); - } -} - -/** - * @tc.name: GdbAdaptTest_Dlopen01 - * @tc.desc: No Mock All Symbols - * @tc.type: FUNC - */ -HWTEST_F(GdbAdaptTest, GdbAdaptTest_Dlopen01, TestSize.Level2) -{ - GetAdapterHolder(); - EXPECT_CALL(*mockDlsym, dlopen(::testing::_, RTLD_LAZY)) - .WillRepeatedly(Return(reinterpret_cast(0x1234))); - GrdAdapterHolder holder = GetAdapterHolder(); - EXPECT_EQ(holder.Open, nullptr); - EXPECT_EQ(holder.Close, nullptr); - EXPECT_EQ(holder.Repair, nullptr); - EXPECT_EQ(holder.Prepare, nullptr); - EXPECT_EQ(holder.Reset, nullptr); - EXPECT_EQ(holder.Finalize, nullptr); - EXPECT_EQ(holder.Step, nullptr); - EXPECT_EQ(holder.ColumnCount, nullptr); - EXPECT_EQ(holder.GetColumnType, nullptr); - EXPECT_EQ(holder.ColumnBytes, nullptr); - EXPECT_EQ(holder.ColumnName, nullptr); - EXPECT_EQ(holder.ColumnValue, nullptr); - EXPECT_EQ(holder.ColumnInt64, nullptr); - EXPECT_EQ(holder.ColumnInt, nullptr); - EXPECT_EQ(holder.ColumnDouble, nullptr); - EXPECT_EQ(holder.ColumnText, nullptr); - EXPECT_EQ(holder.Backup, nullptr); - EXPECT_EQ(holder.Restore, nullptr); - EXPECT_EQ(holder.Rekey, nullptr); - GrdAdapter::Open(databaseName.c_str(), databasePath.c_str(), 1, nullptr); - GrdAdapter::Close(nullptr, 1); - GrdAdapter::Repair(databasePath.c_str(), {}); - GrdAdapter::Prepare(nullptr, databaseName.c_str(), 1, nullptr, nullptr); - GrdAdapter::Reset(nullptr); - GrdAdapter::Finalize(nullptr); - GrdAdapter::Step(nullptr); - GrdAdapter::ColumnCount(nullptr); - GrdAdapter::ColumnType(nullptr, 1); - GrdAdapter::ColumnBytes(nullptr, 1); - GrdAdapter::ColumnName(nullptr, 1); - GrdAdapter::ColumnValue(nullptr, 1); - GrdAdapter::ColumnInt64(nullptr, 1); - GrdAdapter::ColumnInt(nullptr, 1); - GrdAdapter::ColumnDouble(nullptr, 1); - GrdAdapter::ColumnText(nullptr, 1); - GrdAdapter::Backup(nullptr, databaseName.c_str(), {}); - GrdAdapter::Restore(nullptr, databaseName.c_str(), {}); - GrdAdapter::Rekey(nullptr, databaseName.c_str(), {}); -} - -/** - * @tc.name: GdbAdaptTest_Dlopen02 - * @tc.desc: Mock All Symbols test. - * @tc.type: FUNC - */ -HWTEST_F(GdbAdaptTest, GdbAdaptTest_Dlopen02, TestSize.Level2) -{ - EXPECT_CALL(*mockDlsym, dlopen(::testing::_, RTLD_LAZY)) - .WillRepeatedly(Return(reinterpret_cast(0x1234))); - MockAllSymbols(); - GrdAdapterHolder holder = GetAdapterHolder(); - EXPECT_NE(holder.Open, nullptr); - EXPECT_NE(holder.Close, nullptr); - EXPECT_NE(holder.Repair, nullptr); - EXPECT_NE(holder.Prepare, nullptr); - EXPECT_NE(holder.Reset, nullptr); - EXPECT_NE(holder.Finalize, nullptr); - EXPECT_NE(holder.Step, nullptr); - EXPECT_NE(holder.ColumnCount, nullptr); - EXPECT_NE(holder.GetColumnType, nullptr); - EXPECT_NE(holder.ColumnBytes, nullptr); - EXPECT_NE(holder.ColumnName, nullptr); - EXPECT_NE(holder.ColumnValue, nullptr); - EXPECT_NE(holder.ColumnInt64, nullptr); - EXPECT_NE(holder.ColumnInt, nullptr); - EXPECT_NE(holder.ColumnDouble, nullptr); - EXPECT_NE(holder.ColumnText, nullptr); - EXPECT_NE(holder.Backup, nullptr); - EXPECT_NE(holder.Restore, nullptr); - EXPECT_NE(holder.Rekey, nullptr); -} \ No newline at end of file diff --git a/relational_store/test/native/gdb/unittest/gdb_encrypt_test.cpp b/relational_store/test/native/gdb/unittest/gdb_encrypt_test.cpp deleted file mode 100644 index 1455157145d15a82bb05f6cb221510f45fd019a4..0000000000000000000000000000000000000000 --- a/relational_store/test/native/gdb/unittest/gdb_encrypt_test.cpp +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (c) 2025 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 -#include -#include -#include -#include - -#include "gdb_errors.h" -#include "db_store_impl.h" -#include "db_store_manager.h" -#include "edge.h" -#include "grd_adapter.h" -#include "grd_adapter_manager.h" -#include "gdb_helper.h" -#include "gdb_store.h" -#include "gdb_utils.h" -#include "graph_statement.h" -#include "graph_connection.h" -#include "path.h" -#include "result.h" -#include "vertex.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; -class GdbEncryptTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase(); - void SetUp(); - void TearDown(); - void VerifyPersonInfo(const GraphValue &person, const std::string &name, const int32_t &age); - static const std::string createGraphGql; - static const std::string databasePath; -}; -const std::string GdbEncryptTest::databasePath = "/data"; -const std::string GdbEncryptTest::createGraphGql = "CREATE GRAPH test { " - "(person:Person {name STRING, age INT, sex BOOL DEFAULT false})," - "(dog:Dog {name STRING, age INT}), " - "(person) -[:Friend]-> (person) " - "};"; - -void GdbEncryptTest::SetUpTestCase() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } -} - -void GdbEncryptTest::TearDownTestCase() -{ -} - -void GdbEncryptTest::SetUp() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } -} - -void GdbEncryptTest::TearDown() -{ -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_DeaultIsUnencrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "DeaultIsUnencrypt"; - std::string dbPath = databasePath; - // DeaultIsUnencrypt - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - store->Close(); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_Unencrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "Unencrypt"; - std::string dbPath = databasePath; - // Unencryptdb - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, false); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - store->Close(); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_Encrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "Encrypt"; - std::string dbPath = databasePath; - // Unencryptdb - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, true); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - store->Close(); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_UnencryptToEncrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "UnencryptToEncrypt"; - std::string dbPath = databasePath; - // Unencryptdb - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, false); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - result.second = nullptr; - store->Close(); - StoreManager::GetInstance().Clear(); - // Unencryptdb to encryptdb - config.SetEncryptStatus(true); - store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - if (store != nullptr) { - result = store->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 22}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_2", 22); - store->Close(); - } - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_EncryptToUnencrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "EncryptToUnencrypt"; - std::string dbPath = databasePath; - // encryptdb - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, true); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - store->Close(); - StoreManager::GetInstance().Clear(); - // encryptdb to Unencryptdb - config.SetEncryptStatus(false); - store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_CONFIG_INVALID_CHANGE); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_DefaultToEncrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "DefaultToEncrypt"; - std::string dbPath = databasePath; - // Unencryptdb - auto config = StoreConfig(dbName, dbPath); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - result.second = nullptr; - store->Close(); - StoreManager::GetInstance().Clear(); - // Unencryptdb to encryptdb - config.SetEncryptStatus(true); - store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - if (store != nullptr) { - result = store->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 22}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_2", 22); - store->Close(); - } - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_EncryptToEncrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "EncryptToUnencrypt"; - std::string dbPath = databasePath; - // encryptdb - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, true); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - store->Close(); - StoreManager::GetInstance().Clear(); - // encryptdb to encryptdb - config.SetEncryptStatus(true); - store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 22}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_2", 22); - store->Close(); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_UnencryptToUnencrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "UnencryptToEncrypt"; - std::string dbPath = databasePath; - // Unencryptdb - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, false); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - store->Close(); - StoreManager::GetInstance().Clear(); - // Unencryptdb to Unencryptdb - config.SetEncryptStatus(false); - store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 22}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_2", 22); - store->Close(); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_DefaultToUnencrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "UnencryptToEncrypt"; - std::string dbPath = databasePath; - // Unencryptdb - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - store->Close(); - StoreManager::GetInstance().Clear(); - // Unencryptdb to Unencryptdb - config.SetEncryptStatus(false); - store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 22}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_2", 22); - store->Close(); - GDBHelper::DeleteDBStore(config); -} - -void GdbEncryptTest::VerifyPersonInfo(const GraphValue &person, const std::string &name, const int32_t &age) -{ - auto expectSize = 3; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), expectSize); - - auto nameDb = personVertex->GetProperties().find("name"); - ASSERT_NE(nameDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(nameDb->second)); - EXPECT_EQ(std::get(nameDb->second), name); - - auto ageDb = personVertex->GetProperties().find("age"); - ASSERT_NE(ageDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(ageDb->second)); - EXPECT_EQ(std::get(ageDb->second), age); - - auto sex = personVertex->GetProperties().find("sex"); - ASSERT_NE(sex, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(sex->second)); - EXPECT_EQ(std::get(sex->second), 0); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_Config, TestSize.Level1) -{ - std::string dbName = "UnencryptToEncrypt"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH); - EXPECT_EQ(config.IsEncrypt(), false); - config.GenerateEncryptedKey(); - EXPECT_EQ(config.GetEncryptKey().size(), 0); - EXPECT_EQ(config.GetNewEncryptKey().size(), 0); - - config.SetBundleName(""); - EXPECT_EQ(config.GetBundleName(), ""); - config.SetEncryptStatus(true); - EXPECT_EQ(config.IsEncrypt(), true); - config.SetBundleName("test_name"); - EXPECT_EQ(config.GetBundleName(), "test_name"); - // empty return E_ERROR - EXPECT_EQ(config.SetBundleName(""), E_ERROR); - EXPECT_EQ(config.GetBundleName(), "test_name"); - - config.GenerateEncryptedKey(); - // not exists bundleName, failed - EXPECT_EQ(config.GetEncryptKey().size(), 0); - EXPECT_EQ(config.GetNewEncryptKey().size(), 0); - config.ChangeEncryptKey(); - config.GenerateEncryptedKey(); - config.ChangeEncryptKey(); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_Config_Test, TestSize.Level1) -{ - std::string dbName = "ConfigTest"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, true); - EXPECT_EQ(config.IsEncrypt(), true); - config.GenerateEncryptedKey(); - ASSERT_TRUE(config.GetEncryptKey().size() > 0); - EXPECT_EQ(config.GetNewEncryptKey().size(), 0); - // newkey is empty, not change key - config.ChangeEncryptKey(); - ASSERT_TRUE(config.GetEncryptKey().size() > 0); - EXPECT_EQ(config.GetNewEncryptKey().size(), 0); -} \ No newline at end of file diff --git a/relational_store/test/native/gdb/unittest/gdb_execute_test.cpp b/relational_store/test/native/gdb/unittest/gdb_execute_test.cpp deleted file mode 100644 index 8db220683a24637cc713e01260d07e21247997c4..0000000000000000000000000000000000000000 --- a/relational_store/test/native/gdb/unittest/gdb_execute_test.cpp +++ /dev/null @@ -1,2043 +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 - -#include -#include -#include -#include -#include - -#include "gdb_errors.h" -#include "db_store_impl.h" -#include "edge.h" -#include "grd_adapter.h" -#include "grd_adapter_manager.h" -#include "gdb_helper.h" -#include "gdb_store.h" -#include "gdb_utils.h" -#include "graph_statement.h" -#include "graph_connection.h" -#include "path.h" -#include "result.h" -#include "vertex.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; -class GdbExecuteTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase(); - void SetUp(); - void TearDown(); - void VerifyPersonInfo(const GraphValue &person, const std::string &name, const int32_t &age); - void MatchAndVerifyPerson(const std::string &name, const int32_t &age); - - static const std::string databaseName; - static const std::string databasePath; - static std::shared_ptr store_; - static const std::string createGraphGql; - static const std::shared_ptr databaseConfig; - static const std::string pathJsonString; -}; -std::shared_ptr GdbExecuteTest::store_; -const std::string GdbExecuteTest::databaseName = "execute_test"; -const std::string GdbExecuteTest::databasePath = "/data"; -const std::string GdbExecuteTest::createGraphGql = "CREATE GRAPH test { " - "(person:Person {name STRING, age INT, sex BOOL DEFAULT false})," - "(dog:Dog {name STRING, age INT}), " - "(person) -[:Friend]-> (person) " - "};"; -const std::string GdbExecuteTest::pathJsonString = R"({ - "start": { - "label": "PERSON", - "identity": 1, - "properties": { - "AGE": 32, - "SALARY": 75.35, - "NAME": "Alice", - "GENDER": "Female", - "PHONENUMBERS": false, - "EMAILS": null - } - }, - "end": { - "label": "PERSON", - "identity": 2, - "properties": { - "AGE": 28, - "SALARY": 65000, - "NAME": "Bob", - "GENDER": "Male", - "PHONENUMBERS": "123456789", - "EMAILS": "bob@example.com" - } - }, - "relationship": { - "label": "鐩寸郴浜插睘", - "identity": 3, - "start": 1, - "end": 2, - "properties": { - "NUM": 4, - "PINYIN": "zhixiqinshu" - } - } - })"; - -void GdbExecuteTest::SetUpTestCase() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } - int errCode = E_OK; - auto config = StoreConfig(databaseName, databasePath); - GDBHelper::DeleteDBStore(config); - - GdbExecuteTest::store_ = GDBHelper::GetDBStore(config, errCode); -} - -void GdbExecuteTest::TearDownTestCase() -{ - GDBHelper::DeleteDBStore(StoreConfig(databaseName, databasePath)); - store_ = nullptr; -} - -void GdbExecuteTest::SetUp() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } - auto result = store_->ExecuteGql(createGraphGql); -} - -void GdbExecuteTest::TearDown() -{ - if (store_ != nullptr) { - auto result = store_->ExecuteGql("DROP GRAPH test"); - } -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStoreVector, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath, DBType::DB_VECTOR); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_NOT_SUPPORT); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStoreButt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath, DBType::DB_BUTT); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_NOT_SUPPORT); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStoreReadConSize, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - config.SetReadConSize(0); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStoreReadConSizeMax, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - config.SetReadConSize(500); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_ARGS_READ_CON_OVERLOAD); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_NameHasdbSuffix, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success.db"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_NE(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_NameHasDBSuffix, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success.DB"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_NE(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_NameHasSpecialChar, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "suc@!#$*(cess."; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_NE(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_PathOkEmptyName, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = ""; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_NE(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_NotFoundPath, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success"; - std::string dbPath = "/test/path1/"; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_GRD_FAILED_FILE_OPERATION); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_PathErrorEmptyName, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = ""; - std::string dbPath = "/test/path2"; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_GRD_INVAILD_NAME_ERR); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_Empty_Path, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = databaseName; - std::string dbPath = ""; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_GRD_FAILED_FILE_OPERATION); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_Empty_NameAndPath, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = ""; - std::string dbPath = ""; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_GRD_INVAILD_NAME_ERR); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_OK, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "execute_test_ok"; - std::string dbPath = "/data"; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_OK_PathRepeat, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "execute_test_ok_2"; - std::string dbPath = "/data"; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_LongName, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = ""; - for (int32_t i = 0; i < 1000000; i++) { - dbName += "A"; - } - std::string dbPath = "/test/path2"; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_GRD_FAILED_FILE_OPERATION); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_LongNamePathOk, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = ""; - for (int32_t i = 0; i < 1000000; i++) { - dbName += "A"; - } - std::string dbPath = "/data"; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_GRD_SEMANTIC_ERROR); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_LongPath, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = ""; - for (int32_t i = 0; i < 30; i++) { - dbName += "A"; - } - std::string dbPath = "/test/path2"; - for (int32_t i = 0; i < 3000000; i++) { - dbPath += "A"; - } - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_GRD_SEMANTIC_ERROR); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_InVaildSecurityLevel, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "tttt"; - std::string dbPath = "/data"; - - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(-3); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_INVALID_ARGS); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_InVaildSecurityLevel02, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "tttt"; - std::string dbPath = "/data"; - - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(0); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_INVALID_ARGS); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_InVaildSecurityLevel03, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "tttt"; - std::string dbPath = "/data"; - - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(500); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_INVALID_ARGS); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_SecurityLevel, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "tttt"; - std::string dbPath = "/data"; - - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(3); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_SecurityLevelLast, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "tttt"; - std::string dbPath = "/data"; - - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(SecurityLevel::LAST); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_INVALID_ARGS); - store = nullptr; - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_GetSecurityLeve, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "tttt03"; - std::string dbPath = "/data"; - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(SecurityLevel::S2); - auto level = config.GetSecurityLevel(); - EXPECT_EQ(level, SecurityLevel::S2); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - - store = nullptr; - GDBHelper::DeleteDBStore(config); - - config.SetSecurityLevel(SecurityLevel::LAST); - level = config.GetSecurityLevel(); - EXPECT_EQ(level, SecurityLevel::LAST); - store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(errCode, E_INVALID_ARGS); - EXPECT_EQ(store, nullptr); - store = nullptr; - GDBHelper::DeleteDBStore(config); -} - -/** - * @tc.name: GdbStore_GetDBStore_SecurityLevel03 - * @tc.desc: test StoreConfig SetSecurityLevel S2->S1 - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_SecurityLevel02, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "tttt02"; - std::string dbPath = "/data"; - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(SecurityLevel::S2); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - store = nullptr; - - auto invalidConfig = config; - invalidConfig.SetSecurityLevel(SecurityLevel::S1); - store = GDBHelper::GetDBStore(invalidConfig, errCode); - EXPECT_EQ(errCode, E_CONFIG_INVALID_CHANGE); - EXPECT_EQ(store, nullptr); - store = nullptr; - GDBHelper::DeleteDBStore(config); -} - -/** - * @tc.name: GdbStore_GetDBStore_SecurityLevel03 - * @tc.desc: test StoreConfig SetSecurityLevel S2->S3 - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_SecurityLevel03, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "tttt02"; - std::string dbPath = "/data"; - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(SecurityLevel::S2); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - store = nullptr; - - auto invalidConfig = config; - invalidConfig.SetSecurityLevel(SecurityLevel::S3); - store = GDBHelper::GetDBStore(invalidConfig, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - store = nullptr; - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_NoInsertQuery, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 0); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_AfterClose, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_OK; - std::string dbName = "ttttclose"; - std::string dbPath = "/data"; - - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(SecurityLevel::S3); - - auto store = GDBHelper::GetDBStore(config, errCode); - ASSERT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto ret = store->Close(); - EXPECT_EQ(E_OK, ret); - EXPECT_NE(store, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store_->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GDBHelper::DeleteDBStore(config); -} - -/** - * @tc.name: GdbStore_GetDBStore_AfterDrop - * @tc.desc: test GdbStore AfterDrop Insert - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_AfterDrop, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_OK; - std::string dbName = "ttttdrop"; - std::string dbPath = "/data"; - - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(SecurityLevel::S3); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - - auto result = store_->ExecuteGql("DROP GRAPH test;"); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - - result = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_GRD_UNDEFINED_PARAM); - result = store_->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - GDBHelper::DeleteDBStore(config); -} - -/** - * @tc.name: GdbStore_Execute_001 - * @tc.desc: test GdbStore Execute - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_Execute_LongName, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store_->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - std::string name = "name2"; - for (int32_t i = 0; i < 300; i++) { - name += "A"; - } - result = store_->ExecuteGql("INSERT (:Person {name: '" + name + "', age: 11});"); - ASSERT_EQ(result.first, E_OK); - result = store_->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 2); - - std::string name2 = "name2"; - for (int32_t i = 0; i < 3000000; i++) { - name2 += "A"; - } - result = store_->ExecuteGql("INSERT (:Person {name: '" + name2 + "', age: 11});"); - ASSERT_EQ(result.first, E_INVALID_ARGS); - result = store_->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 2); -} - -/** - * @tc.name: GdbStore_Execute_001 - * @tc.desc: test GdbStore Execute - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_Execute_001, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_1", 11); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_2", 22); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_3', age: 33});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_3", 33); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_2'}), (p2:Person {name: 'name_3'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - - result = store_->QueryGql("MATCH (person:Person)-[relation:Friend]->() RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - auto data = result.second->GetAllData(); - GraphValue person = data[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - - auto result2 = - store_->QueryGql("MATCH path=(a:Person {name: 'name_1'})-[]->{2, 2}(b:Person {name: 'name_3'}) RETURN path;"); - ASSERT_EQ(result2.first, E_OK); - EXPECT_EQ(result2.second->GetAllData().size(), 1); - - GraphValue path = result2.second->GetAllData()[0]["path"]; - ASSERT_TRUE(std::holds_alternative>(path)); - - auto pathPath = std::get>(path); - EXPECT_EQ(pathPath->GetPathLength(), 2); -} - -/** - * @tc.name: GdbStore_Execute_001 - * @tc.desc: test GdbStore Execute - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_Execute_002, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_3', age: 33});"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_2'}), (p2:Person {name: 'name_3'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_3'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - - result = store_->QueryGql( - "MATCH (person:Person {name: 'name_1'})-[relation:Friend]->(d) where d.age > 25 RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - - GraphValue relation = result.second->GetAllData()[0]["relation"]; - ASSERT_TRUE(std::holds_alternative>(relation)); - auto relationGraphEdge = std::get>(relation); - EXPECT_EQ(relationGraphEdge->GetLabel(), "Friend"); -} - -void GdbExecuteTest::MatchAndVerifyPerson(const std::string &name, const int32_t &age) -{ - ASSERT_NE(store_, nullptr); - auto gql = "MATCH (person:Person {name: '" + name + "'}) RETURN person;"; - auto result = store_->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, name, age); -} - -void GdbExecuteTest::VerifyPersonInfo(const GraphValue &person, const std::string &name, const int32_t &age) -{ - auto expectSize = 3; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), expectSize); - - auto nameDb = personVertex->GetProperties().find("name"); - ASSERT_NE(nameDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(nameDb->second)); - EXPECT_EQ(std::get(nameDb->second), name); - - auto ageDb = personVertex->GetProperties().find("age"); - ASSERT_NE(ageDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(ageDb->second)); - EXPECT_EQ(std::get(ageDb->second), age); - - auto sex = personVertex->GetProperties().find("sex"); - ASSERT_NE(sex, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(sex->second)); - EXPECT_EQ(std::get(sex->second), 0); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Updata, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_1", 11); - - result = store_->ExecuteGql("MATCH (p1:Person {name: 'name_1'}) SET p1.name = 'name_1_modify';"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_1_modify", 11); - - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_1_modify'}) SET p1.name = 'name_1_modify2', p1.age=100 + 11;"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_1_modify2", 111); - - result = store_->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_2", 22); - result = store_->ExecuteGql("MATCH (p2:Person {name: 'name_2'}) SET p2 = {name: 'name_2_modify_all', age: 99};"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_2_modify_all", 99); - - result = store_->ExecuteGql("MATCH (p1:Person {name: 'name_1_modify2'}), (p2:Person {name: 'name_2_modify_all'}) " - "INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = - store_->ExecuteGql("MATCH (n:Person {name: 'name_1_modify2'})-[r:Friend]->(m:Person ) SET m.name = 'name_3';"); - MatchAndVerifyPerson("name_3", 99); - EXPECT_EQ(result.first, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_UpdataNull, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'hahaha', age: 987});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("hahaha", 987); - // update name = null - result = store_->ExecuteGql("MATCH (p1:Person {name: 'hahaha'}) SET p1 = {age: 666};"); - EXPECT_EQ(result.first, E_OK); - result = store_->QueryGql("MATCH (person:Person {age: 666}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), 2); - - auto nameDb = personVertex->GetProperties().find("name"); - ASSERT_EQ(nameDb, personVertex->GetProperties().end()); - - auto ageDb = personVertex->GetProperties().find("age"); - ASSERT_NE(ageDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(ageDb->second)); - EXPECT_EQ(std::get(ageDb->second), 666); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_UpdataNull02, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'hahaha', age: 987});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("hahaha", 987); - // update name = null - result = store_->ExecuteGql("MATCH (p1:Person {name: 'hahaha'}) SET p1.age = 666, p1.name = null;"); - EXPECT_EQ(result.first, E_OK); - result = store_->QueryGql("MATCH (person:Person {age: 666}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), 2); - - auto nameDb = personVertex->GetProperties().find("name"); - ASSERT_EQ(nameDb, personVertex->GetProperties().end()); - - auto ageDb = personVertex->GetProperties().find("age"); - ASSERT_NE(ageDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(ageDb->second)); - EXPECT_EQ(std::get(ageDb->second), 666); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Updata_MatchFail, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'zhangsan001', age: 10});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("zhangsan001", 10); - - result = store_->ExecuteGql("MATCH (p1:Person {name: 'notFound'}) SET p1.name = 'name_1_modify';"); - EXPECT_EQ(result.first, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Updata_AgeError, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_4', age: 44});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_4", 44); - - result = store_->ExecuteGql("MATCH (p1:Person {name: 'name_4'}) SET p1.age = 'string_age';"); - EXPECT_EQ(result.first, E_GRD_SEMANTIC_ERROR); - // update failed, no change - MatchAndVerifyPerson("name_4", 44); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Updata_ColumnError, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto result = store_->ExecuteGql("INSERT (:PersonErr {name: true, age: 44});"); - EXPECT_EQ(result.first, E_GRD_UNDEFINED_PARAM); - - auto gql = "MATCH (person:Person) RETURN person;"; - result = store_->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 0); - - result = store_->ExecuteGql("INSERT (:Person {name: true, age: 44});"); - EXPECT_EQ(result.first, E_GRD_SEMANTIC_ERROR); - gql = "MATCH (person:Person) RETURN person;"; - result = store_->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 0); - - result = store_->ExecuteGql("INSERT (:Person {name: 'zhangsan', age: 'error'});"); - EXPECT_EQ(result.first, E_GRD_SEMANTIC_ERROR); - gql = "MATCH (person:Person) RETURN person;"; - result = store_->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 0); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Delete, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto result = store_->ExecuteGql("INSERT (:Person {name: 'zhangsan_delete', age: 10});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("zhangsan_delete", 10); - - result = store_->ExecuteGql("MATCH (p:Person {name: 'zhangsan_delete'}) DETACH DELETE p;"); - EXPECT_EQ(result.first, E_OK); - auto gql = "MATCH (person:Person {name: 'zhangsan_delete'}) RETURN person;"; - result = store_->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 0); - // Double Delete - result = store_->ExecuteGql("MATCH (p:Person {name: 'zhangsan_delete'}) DETACH DELETE p;"); - EXPECT_EQ(result.first, E_OK); - gql = "MATCH (person:Person {name: 'zhangsan_delete'}) RETURN person;"; - result = store_->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 0); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Delete_NotFound, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'zhangsan_delete', age: 10});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("zhangsan_delete", 10); - - result = store_->ExecuteGql("MATCH (p:Person {name: 'notFound'}) DETACH DELETE p;"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("zhangsan_delete", 10); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Delete_PError, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'delete_error', age: 11});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("delete_error", 11); - - result = store_->ExecuteGql("MATCH (p:Person {name: 'delete_error'}) DETACH DELETE p_error;"); - EXPECT_EQ(result.first, E_GRD_UNDEFINED_PARAM); - MatchAndVerifyPerson("delete_error", 11); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Delete_Related, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto result = store_->ExecuteGql("INSERT (:Person {name: 'delete_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("delete_1", 11); - result = store_->ExecuteGql("INSERT (:Person {name: 'delete_2', age: 22});"); - MatchAndVerifyPerson("delete_2", 22); - EXPECT_EQ(result.first, E_OK); - - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'delete_1'}), (p2:Person {name: 'delete_2'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = - store_->QueryGql("MATCH (person:Person {name: 'delete_1'})-[relation:Friend]->() RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), 3); - auto name = personVertex->GetProperties().find("name"); - ASSERT_NE(name, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(name->second)); - EXPECT_EQ(std::get(name->second), "delete_1"); - - auto age = personVertex->GetProperties().find("age"); - ASSERT_NE(age, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(age->second)); - EXPECT_EQ(std::get(age->second), 11); - - result = store_->ExecuteGql("MATCH (p:Person)-[:Friend]->(relatedPerson:Person) DETACH DELETE p, relatedPerson;"); - EXPECT_EQ(result.first, E_OK); - result = - store_->QueryGql("MATCH (person:Person {name: 'delete_1'})-[relation:Friend]->() RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 0); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Delete_Related_Error, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto result = store_->ExecuteGql("INSERT (:Person {name: 'delete_3', age: 11});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("delete_3", 11); - result = store_->ExecuteGql("INSERT (:Person {name: 'delete_4', age: 22});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("delete_4", 22); - - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'delete_3'}), (p2:Person {name: 'delete_4'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = - store_->QueryGql("MATCH (person:Person {name: 'delete_3'})-[relation:Friend]->() RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), 3); - auto name = personVertex->GetProperties().find("name"); - ASSERT_NE(name, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(name->second)); - EXPECT_EQ(std::get(name->second), "delete_3"); - - // No Friend_Error, delete Eror - result = - store_->ExecuteGql("MATCH (p:Person)-[:Friend_Error]->(relatedPerson:Person) DETACH DELETE p, relatedPerson;"); - EXPECT_EQ(result.first, E_GRD_UNDEFINED_PARAM); - // p:Person, but delete p_error - result = - store_->ExecuteGql("MATCH (p:Person)-[:Friend]->(relatedPerson:Person) DETACH DELETE p_error, relatedPerson;"); - EXPECT_EQ(result.first, E_GRD_UNDEFINED_PARAM); - //relatedPerson:Person, but delete relatedPerson_error - result = - store_->ExecuteGql("MATCH (p:Person)-[:Friend]->(relatedPerson:Person) DETACH DELETE p, relatedPerson_error;"); - EXPECT_EQ(result.first, E_GRD_UNDEFINED_PARAM); - - result = store_->ExecuteGql("MATCH (p:Person)-[:Friend]->(relatedPerson:Person) DETACH DELETE relatedPerson, p;"); - EXPECT_EQ(result.first, E_OK); - // delete success, data.size == 0 - result = - store_->QueryGql("MATCH (person:Person {name: 'delete_3'})-[relation:Friend]->() RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 0); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_QueryGql, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'zhangsan_111', age: 11, sex: true});"); - EXPECT_EQ(result.first, E_OK); - - result = store_->QueryGql("MATCH (person:Person {name: 'zhangsan_111'}) RETURN person;"); - EXPECT_EQ(result.first, E_OK); - - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue personErr = result.second->GetAllData()[0]["personErr"]; - // No personErr - ASSERT_TRUE(std::holds_alternative(personErr)); - - GraphValue person = result.second->GetAllData()[0]["person"]; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - ASSERT_NE(personVertex->GetLabel(), "error_label"); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - // size = 4 {name, age, sex, identity} - ASSERT_EQ(personVertex->GetProperties().size(), 3); - - auto name = personVertex->GetProperties().find("name"); - ASSERT_NE(name, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(name->second)); - EXPECT_EQ(std::get(name->second), "zhangsan_111"); - - auto age = personVertex->GetProperties().find("age"); - ASSERT_NE(age, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(age->second)); - EXPECT_EQ(std::get(age->second), 11); - - auto sex = personVertex->GetProperties().find("sex"); - ASSERT_NE(sex, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(sex->second)); - EXPECT_EQ(std::get(sex->second), 1); - // No Propertie is OTHER, equal End - auto other = personVertex->GetProperties().find("OTHER"); - EXPECT_EQ(other, personVertex->GetProperties().end()); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_QueryGql_2, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto result = store_->ExecuteGql("INSERT (:Person {name: 'lisi_1', age: 66});"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql("INSERT (:Person {name: 'lisi_2', age: 66, sex: true});"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql("INSERT (:Dog {name: 'xiaohuang1', age: 66});"); - EXPECT_EQ(result.first, E_OK); - result = store_->QueryGql("MATCH (person:Person{age: 66}) RETURN person;"); - EXPECT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - - GraphValue person = result.second->GetAllData()[0]["person"]; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), 3); - auto name = personVertex->GetProperties().find("name"); - ASSERT_NE(name, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(name->second)); - EXPECT_EQ(std::get(name->second), "lisi_1"); - auto age = personVertex->GetProperties().find("age"); - ASSERT_NE(age, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(age->second)); - EXPECT_EQ(std::get(age->second), 66); - auto sex = personVertex->GetProperties().find("sex"); - ASSERT_NE(sex, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(age->second)); - EXPECT_EQ(std::get(sex->second), 0); - - person = result.second->GetAllData()[1]["person"]; - ASSERT_TRUE(std::holds_alternative>(person)); - personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), 3); - name = personVertex->GetProperties().find("name"); - ASSERT_NE(name, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(name->second)); - EXPECT_EQ(std::get(name->second), "lisi_2"); - age = personVertex->GetProperties().find("age"); - ASSERT_NE(age, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(age->second)); - EXPECT_EQ(std::get(age->second), 66); - sex = personVertex->GetProperties().find("sex"); - ASSERT_NE(sex, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(age->second)); - EXPECT_EQ(std::get(sex->second), 1); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_ParseEdge, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_ERROR; - // no start, no end - nlohmann::json json = nlohmann::json::parse("{\"name\" : \"zhangsan\"}", nullptr, false); - ASSERT_FALSE(json.is_discarded()); - ASSERT_FALSE(json.is_null()); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - // no identity - std::string jsonStr = "{\"start\" : 1, \"end\" : 2}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - // ok - jsonStr = "{\"start\" : 1, \"end\" : 2, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // start is AA - jsonStr = "{\"start\" : \"AA\", \"end\" : 2, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // end is B - jsonStr = "{\"start\" : 1, \"end\" : \"B\", \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // identity is C - jsonStr = "{\"start\" : 1, \"end\" : 2, \"label\":\"COMPANY\",\"identity\":\"C\"," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // label is 222 - jsonStr = "{\"start\" : 1, \"end\" : 2, \"label\":222,'identity':3,\"properties\":{\"NAME\":\"myCompany3\"," - "\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - // key4 is null - jsonStr = - "{\"start\" : 1, \"end\" : 2, \"label\":\"COMPANY\",\"identity\":2," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":4.5,\"SEX\":true,\"key1\":true,\"key2\":[], \"key3\":{}, " - "\"key4\": null}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_PathSegment, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_ERROR; - // NO start and end - nlohmann::json json = nlohmann::json::parse("{\"name\" : \"zhangsan\"}", nullptr, false); - ASSERT_FALSE(json.is_discarded()); - ASSERT_FALSE(json.is_null()); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - // no relationship - std::string jsonStr = "{\"start\" : {}, \"end\" : {}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"end\" : {}, \"relationship\":{}, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"end\" : {}, \"relationship\":{}, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"end\" : {}, \"relationship\":{}, \"label\":\"COMPANY\",\"identity\":\"C\"," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"end\" : {}, \"relationship\":{}, \"label\":222,\"identity\":2," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"end\" : {}, \"relationship\":{}, \"label\":\"COMPANY\",\"identity\":2," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":4.5,\"SEX\":true,\"key1\":true,\"key2\":[], " - "\"key3\":{}, \"key4\": null}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - json = nlohmann::json::parse(pathJsonString, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_PathSegment02, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_ERROR; - nlohmann::json json = nlohmann::json::parse(pathJsonString, nullptr, false); - PathSegment::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // identity:A, E_OK - std::string jsonStr = - "{\"start\":{\"label\":\"PERSON\",\"identity\":\"A\",\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":2,\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - - // label:2, E_PARSE_JSON_FAILED - jsonStr = - "{\"start\":{\"label\":2,\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":2,\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - - // relationship->start:B, E_OK - jsonStr = - "{\"start\":{\"label\":\"PERSON\",\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":\"B\",\"end\":2,\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - - // relationship->end:C, E_OK - jsonStr = - "{\"start\":{\"label\":\"PERSON\",\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":\"C\",\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_PathSegment03, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_ERROR; - nlohmann::json json = nlohmann::json::parse(pathJsonString, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_OK); - // end no label:PERSON and identity: A - std::string jsonStr = - "{\"start\":{\"label\":\"PERSON\",\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"identity\":\"A\",\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":2,\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : 1, \"end\" : {}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"relationship\" : 1}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"relationship\" : {}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"relationship\" : {}, \"end\" : 1}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"relationship\" : {}, \"end\" : {}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_PathSegment04, TestSize.Level1) -{ - int errCode = E_ERROR; - nlohmann::json json = nlohmann::json::parse(pathJsonString, nullptr, false); - PathSegment::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // identity:A, E_OK - std::string jsonStr = - "{\"start\":{\"label\":\"PERSON\",\"identity\":{},\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":2,\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - std::shared_ptr sourceVertex; - std::shared_ptr targetVertex; - std::shared_ptr edge; - auto paths = std::make_shared(sourceVertex, targetVertex, edge); - EXPECT_NE(paths, nullptr); - EXPECT_EQ(sourceVertex, paths->GetSourceVertex()); - EXPECT_EQ(edge, paths->GetEdge()); - EXPECT_EQ(targetVertex, paths->GetTargetVertex()); - jsonStr = - "{\"start\":{\"label\":\"PERSON\",\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Path01, TestSize.Level1) -{ - std::shared_ptr start = std::make_shared(); - std::shared_ptr end = std::make_shared(); - auto path = std::make_shared(); - path = std::make_shared(start, end); - EXPECT_NE(path, nullptr); - path->SetPathLength(1); - EXPECT_EQ(1, path->GetPathLength()); - path->SetStart(std::make_shared("1", "HAHA")); - EXPECT_EQ("1", path->GetStart()->GetId()); - EXPECT_EQ("HAHA", path->GetStart()->GetLabel()); - auto labels = path->GetStart()->GetLabels(); - EXPECT_EQ(1, labels.size()); - - path->SetEnd(std::make_shared("2", "HAHA2")); - EXPECT_EQ("2", path->GetEnd()->GetId()); - EXPECT_EQ("HAHA2", path->GetEnd()->GetLabel()); - auto segment = path->GetSegments(); - EXPECT_EQ(segment.size(), 0); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Path02, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_ERROR; - nlohmann::json json = nlohmann::json::parse(pathJsonString, nullptr, false); - Path::Parse(json, errCode); - // no length - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - // identity:A, E_OK - std::string jsonStr = - "{\"length\": 1,\"start\":{\"label\":\"PERSON\",\"identity\":3,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\"}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":2,\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}},\"segments\":[{\"start\":{\"label\":\"PERSON\"," - "\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":\"C\",\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}}}]}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Path::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - - // label:2, E_PARSE_JSON_FAILED - jsonStr = - "{\"length\": 1,\"start\":{\"label\":2,\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":2,\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}},\"segments\":[{}]}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Path::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Path03, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_ERROR; - nlohmann::json json = nlohmann::json::parse(pathJsonString, nullptr, false); - Path::Parse(json, errCode); - // no length - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - // relationship->start:B, E_OK - auto jsonStr = - "{\"length\": 1,\"start\":{\"label\":\"PERSON\",\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":\"B\",\"end\":2,\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}},\"segments\":[{}]}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Path::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - - // relationship->end:C, E_OK - jsonStr = - "{\"length\": 1,\"start\":{\"label\":\"PERSON\",\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":\"C\",\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}},\"segments\":[{\"start\":{\"label\":\"PERSON\",\"identity\":1," - "\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":\"C\",\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}}}]}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Path::Parse(json, errCode); - ASSERT_EQ(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Vertex, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_ERROR; - // no start, no end - nlohmann::json json = nlohmann::json::parse("{\"name\" : \"zhangsan\"}", nullptr, false); - ASSERT_FALSE(json.is_discarded()); - ASSERT_FALSE(json.is_null()); - Vertex::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - // no identity - std::string jsonStr = "{\"start\" : 1, \"end\" : 2}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Vertex::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - // ok - jsonStr = "{\"start\" : 1, \"end\" : 2, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Vertex::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // start is AA - jsonStr = "{\"start\" : \"AA\", \"end\" : 2, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Vertex::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // end is B - jsonStr = "{\"start\" : 1, \"end\" : \"B\", \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Vertex::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // identity is C - jsonStr = "{\"start\" : 1, \"end\" : 2, \"label\":\"COMPANY\",\"identity\":\"C\"," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Vertex::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // label is 222 - jsonStr = "{\"start\" : 1, \"end\" : 2, \"label\":222,'identity':3,\"properties\":{\"NAME\":\"myCompany3\"," - "\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Vertex::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - // key4 is null - jsonStr = - "{\"start\" : 1, \"end\" : 2, \"label\":\"COMPANY\",\"identity\":2," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":4.5,\"SEX\":true,\"key1\":true,\"key2\":[], \"key3\":{}, " - "\"key4\": null}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Vertex::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Vertex02, TestSize.Level1) -{ - Vertex vertex; - Vertex vertex2("1", "PERSON"); - ASSERT_EQ(vertex2.GetLabel(), "PERSON"); - vertex2.SetLabel("PERSON1"); - ASSERT_EQ(vertex2.GetLabel(), "PERSON1"); - std::unordered_map properties; - Vertex vertex3("1", "PERSON2", properties); - ASSERT_EQ(vertex3.GetLabel(), "PERSON2"); - vertex3.SetLabel("PERSON3"); - ASSERT_EQ(vertex3.GetLabel(), "PERSON3"); -} - -/** - * @tc.name: GdbStore_Execute_PathChange - * @tc.desc: test Path Change - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_Execute_PathChange, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - MatchAndVerifyPerson("name_1", 11); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - MatchAndVerifyPerson("name_2", 22); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_3', age: 33});"); - MatchAndVerifyPerson("name_3", 33); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_4', age: 44});"); - MatchAndVerifyPerson("name_4", 44); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_3'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_4'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_2'}), (p2:Person {name: 'name_3'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_2'}), (p2:Person {name: 'name_4'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_3'}), (p2:Person {name: 'name_4'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - - result = - store_->QueryGql("MATCH path=(a:Person {name: 'name_1'})-[]->{0, 3}(b:Person) RETURN path;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 8); - - GraphValue path = result.second->GetAllData()[0]["path"]; - ASSERT_TRUE(std::holds_alternative>(path)); -} - -/** - * @tc.name: GdbStore_Execute_PathChangeRing - * @tc.desc: Querying a Trail with a Ring - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_Execute_PathChangeRing, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - MatchAndVerifyPerson("name_1", 11); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - MatchAndVerifyPerson("name_2", 22); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_3', age: 33});"); - MatchAndVerifyPerson("name_3", 33); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_2'}), (p2:Person {name: 'name_3'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_3'}), (p2:Person {name: 'name_1'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - - result = - store_->QueryGql("MATCH path=(a:Person {name: 'name_1'})-[]->{0, 3}(b:Person) RETURN path;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 4); - - GraphValue path = result.second->GetAllData()[0]["path"]; - ASSERT_TRUE(std::holds_alternative>(path)); -} - -/** - * @tc.name: GdbStore_Execute_AllGraph - * @tc.desc: test All Graph - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_Execute_AllGraph, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - std::string name = "zhangsanfeng"; - for (int32_t i = 0; i < 50; i++) { - auto nameInner = name + "_" + std::to_string(i); - auto result = store_->ExecuteGql("INSERT (:Person {name: '" + nameInner + "', age: 11});"); - MatchAndVerifyPerson(nameInner, 11); - for (int32_t j = 0; j < 100; j++) { - auto nameOut = nameInner + "_" + std::to_string(j); - result = store_->ExecuteGql("INSERT (:Person {name: '" + nameOut + "', age: 22});"); - MatchAndVerifyPerson(nameOut, 22); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: '" + nameInner + "'}), (p2:Person {name: '" + nameOut + "'}) " - "INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - } - } - auto result = - store_->QueryGql("MATCH path=(a:Person)-[]->{0, 3}(b:Person) RETURN path;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 10050); - GraphValue path = result.second->GetAllData()[0]["path"]; - ASSERT_TRUE(std::holds_alternative>(path)); - - auto gql = "MATCH (person:Person) RETURN person;"; - result = store_->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 5050); -} - -/** - * @tc.name: GdbStore_Execute_SelfPath - * @tc.desc: test Self Path - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_Execute_SelfPath, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_111', age: 11});"); - MatchAndVerifyPerson("name_111", 11); - - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_111'}), (p2:Person {name: 'name_111'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - - result = store_->QueryGql("MATCH path=(a:Person {name: 'name_111'})-[]->{0, 3}(b:Person) RETURN path;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - - GraphValue path = result.second->GetAllData()[0]["path"]; - ASSERT_TRUE(std::holds_alternative>(path)); -} - -/** - * @tc.name: GdbStore_Execute_SelfPath - * @tc.desc: test Self Path - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_Execute_SelfPath02, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_test_001', age: 11});"); - MatchAndVerifyPerson("name_test_001", 11); - - result = store_->ExecuteGql("INSERT (:Person {name: 'name_test_001', age: 11});"); - - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_test_001'}), (p2:Person {name: 'name_test_001'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_test_001'}), (p2:Person {name: 'name_test_001'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - - result = - store_->QueryGql("MATCH path=(a:Person {name: 'name_test_001'})-[]->{0, 3}(b:Person) RETURN path;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 126); - - GraphValue path = result.second->GetAllData()[0]["path"]; - ASSERT_TRUE(std::holds_alternative>(path)); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_StoreConfigSetName, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success01"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - config.SetName("success01_update"); - EXPECT_EQ("success01_update", config.GetName()); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(StoreConfig("success01_update", databasePath)); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_StoreConfigSetPath, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success01"; - std::string dbPath = "/test/test"; - auto config = StoreConfig(dbName, dbPath); - config.SetPath(databasePath); - EXPECT_EQ(databasePath, config.GetPath()); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(StoreConfig(dbName, databasePath)); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_StoreConfigSetDbType, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success01"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - config.SetDbType(DBType::DB_GRAPH); - EXPECT_EQ(config.GetDbType(), DBType::DB_GRAPH); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(StoreConfig(dbName, databasePath)); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_StoreConfigSetEncryptStatus, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success01"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - config.SetEncryptStatus(true); - ASSERT_TRUE(config.IsEncrypt()); - config.SetEncryptStatus(false); - ASSERT_TRUE(!config.IsEncrypt()); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(StoreConfig(dbName, databasePath)); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_StoreConfigSetReadTime, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success01"; - std::string dbPath = databasePath; - std::vector encryptKey = std::vector(); - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, true, encryptKey); - config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, false, encryptKey); - config.SetReadTime(3); - EXPECT_EQ(config.GetReadTime(), 3); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(StoreConfig(dbName, databasePath)); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_UtilsTest, TestSize.Level1) -{ - int errCode = E_OK; - errCode = GdbUtils::CreateDirectory(""); - EXPECT_EQ(errCode, E_OK); - errCode = GdbUtils::CreateDirectory("dir1"); - EXPECT_EQ(errCode, E_CREATE_FOLDER_FAIT); - GdbUtils::CreateDirectory("dir1/dir2"); - EXPECT_EQ(errCode, E_CREATE_FOLDER_FAIT); - GdbUtils::CreateDirectory("dir1/dir2/dir3"); - EXPECT_EQ(errCode, E_CREATE_FOLDER_FAIT); - GdbUtils::CreateDirectory("/dir1/dir2/dir3"); - EXPECT_EQ(errCode, E_CREATE_FOLDER_FAIT); - GdbUtils::CreateDirectory("/data/"); - EXPECT_EQ(errCode, E_CREATE_FOLDER_FAIT); - GdbUtils::CreateDirectory("/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2" - "/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2" - "/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2" - "/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2" - "/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2" - "/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2" - "/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2"); - EXPECT_EQ(errCode, E_CREATE_FOLDER_FAIT); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_UtilsAnonymousTest, TestSize.Level1) -{ - auto ret = GdbUtils::Anonymous("fileName"); - EXPECT_EQ(ret, "fileName"); - ret = GdbUtils::Anonymous("dir1/shortPath"); - EXPECT_EQ(ret, "dir1/shortPa"); - ret = GdbUtils::Anonymous("dir1/el1/longPath"); - EXPECT_EQ(ret, "dir1/el1/longPa"); - ret = GdbUtils::Anonymous("el1/l"); - EXPECT_EQ(ret, "el1"); - ret = GdbUtils::Anonymous( - "dir1/el1/longPath/longPath/longPath/longPath/longPath/longPath/longPath/longPath/longPath/longPath/longPath"); - EXPECT_EQ(ret, "dir1/***/el1/***/longPa"); - ret = GdbUtils::Anonymous("/data/dir1/dir2/dir3"); - EXPECT_EQ(ret, "/***/dir3"); - ret = GdbUtils::Anonymous("/data/el1/dir2"); - EXPECT_EQ(ret, "/***/el1/dir2"); - ret = GdbUtils::Anonymous("/data/app/el1/0/base/com.my.hmos.arkwebcore"); - EXPECT_EQ(ret, "/***/el1/***/com.my.hmos.arkwebcore"); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_StatementTest, TestSize.Level1) -{ - auto errCode = E_OK; - std::string gql = "INSERT (:Person {name: 'name_test_001', age: 11});"; - GraphStatement statement(nullptr, "", nullptr, errCode); - EXPECT_EQ(errCode, E_PREPARE_CHECK_FAILED); - - GRD_DB *dbHandle; - auto ret = std::make_shared(dbHandle, gql, nullptr, errCode); - EXPECT_NE(ret, nullptr); - errCode = ret->Prepare(); - EXPECT_EQ(errCode, E_PREPARE_CHECK_FAILED); - - errCode = ret->Step(); - EXPECT_EQ(errCode, E_STEP_CHECK_FAILED); - - errCode = ret->Finalize(); - EXPECT_EQ(errCode, E_OK); - - errCode = ret->GetColumnCount(); - EXPECT_EQ(errCode, E_STATEMENT_EMPTY); - - auto pair = ret->GetColumnName(0); - EXPECT_EQ(pair.first, E_STATEMENT_EMPTY); - pair = ret->GetColumnName(0); - EXPECT_EQ(pair.first, E_STATEMENT_EMPTY); - pair = ret->GetColumnName(3); - EXPECT_EQ(pair.first, E_STATEMENT_EMPTY); - pair = ret->GetColumnName(9); - EXPECT_EQ(pair.first, E_STATEMENT_EMPTY); - - auto pair1 = ret->GetColumnValue(0); - EXPECT_EQ(pair1.first, E_STATEMENT_EMPTY); - pair1 = ret->GetColumnValue(3); - EXPECT_EQ(pair1.first, E_STATEMENT_EMPTY); - pair1 = ret->GetColumnValue(100); - EXPECT_EQ(pair1.first, E_STATEMENT_EMPTY); - - errCode = ret->IsReady(); - EXPECT_EQ(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_StatementTest02, TestSize.Level1) -{ - auto errCode = E_OK; - std::string gql = "INSERT (:Person {name: 'name_test_001', age: 11});"; - - auto ret = std::make_shared(nullptr, gql, nullptr, errCode); - EXPECT_NE(ret, nullptr); - errCode = ret->Prepare(); - EXPECT_EQ(errCode, E_PREPARE_CHECK_FAILED); - - errCode = ret->Step(); - EXPECT_EQ(errCode, E_STEP_CHECK_FAILED); - - errCode = ret->Finalize(); - EXPECT_EQ(errCode, E_OK); - - errCode = ret->GetColumnCount(); - EXPECT_EQ(errCode, E_STATEMENT_EMPTY); - - auto pair = ret->GetColumnName(0); - EXPECT_EQ(pair.first, E_STATEMENT_EMPTY); - - auto pair1 = ret->GetColumnValue(0); - EXPECT_EQ(pair1.first, E_STATEMENT_EMPTY); - - errCode = ret->IsReady(); - EXPECT_EQ(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_FullResult, TestSize.Level1) -{ - auto fullResult = std::make_shared(); - EXPECT_NE(fullResult, nullptr); - auto errCode = fullResult->InitData(nullptr); - EXPECT_EQ(errCode, E_STATEMENT_EMPTY); - fullResult = std::make_shared(); - EXPECT_NE(fullResult, nullptr); - auto statement = std::make_shared(nullptr, "", nullptr, errCode); - errCode = fullResult->InitData(statement); - EXPECT_EQ(errCode, E_STEP_CHECK_FAILED); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_EdgeTest, TestSize.Level1) -{ - auto errCode = E_ERROR; - auto edge = std::make_shared(); - EXPECT_NE(edge, nullptr); - edge = std::make_shared(std::make_shared(), "2", "3"); - EXPECT_NE(edge, nullptr); - edge = std::make_shared(nullptr, "2", "3"); - EXPECT_NE(edge, nullptr); - edge = std::make_shared("1", "PERSON", "2", "3"); - EXPECT_NE(edge, nullptr); - edge->SetSourceId("22"); - EXPECT_EQ("22", edge->GetSourceId()); - edge->SetTargetId("33"); - EXPECT_EQ("33", edge->GetTargetId()); - - auto jsonStr = "{\"start\" : 1, \"end\" : 2, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - nlohmann::json json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - - jsonStr = "{\"start\" : {}, \"end\" : 2, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : 1, \"end\" : {}, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Connect, TestSize.Level1) -{ - auto errCode = E_ERROR; - errCode = Connection::RegisterCreator(DBType::DB_BUTT, nullptr); - EXPECT_EQ(errCode, E_NOT_SUPPORT); - errCode = Connection::RegisterCreator(static_cast(-1), nullptr); - EXPECT_EQ(errCode, E_NOT_SUPPORT); - auto func = [](const StoreConfig& config, bool isWriter) { - std::pair> ret = std::make_pair( - static_cast(DBType::DB_GRAPH), nullptr); - return ret; - }; - errCode = Connection::RegisterCreator(DBType::DB_GRAPH, func); - EXPECT_EQ(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_DBStore01, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "execute_test_ok_2"; - std::string dbPath = "/data"; - auto config = StoreConfig(dbName, dbPath); - - auto store = std::make_shared(config); - EXPECT_NE(store, nullptr); - errCode = store->InitConn(); - EXPECT_EQ(errCode, E_OK); - errCode = store->InitConn(); - EXPECT_EQ(errCode, E_OK); - const std::string gql = "INSERT (:Person {name: 'name_1', age: 11});"; - auto [err, result] = store->QueryGql(gql); - EXPECT_EQ(err, E_GRD_UNDEFINED_PARAM); - auto [err1, result1] = store->ExecuteGql(gql); - EXPECT_EQ(err1, E_GRD_UNDEFINED_PARAM); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_NameErre01, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("DROP GRAPH test"); - EXPECT_EQ(result.first, E_OK); - - std::string createGql = "CREATE GRAPH test {(person:"; - for (int i = 0; i < 129; ++i) { - createGql += "i"; - } - createGql += " {name STRING, age INT}), (person) -[:FRIEND]-> (person)};"; - result = store_->ExecuteGql(createGql); - EXPECT_EQ(result.first, E_GRD_INVALID_NAME); -} - -HWTEST_F(GdbExecuteTest, GdbStore_NameErre02, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("DROP GRAPH test"); - EXPECT_EQ(result.first, E_OK); - - std::string createGql = - "CREATE GRAPH test {(anon_person: Person {name STRING, age INT}), (person) -[:Friend]-> (person)};"; - result = store_->ExecuteGql(createGql); - EXPECT_EQ(result.first, E_GRD_SEMANTIC_ERROR); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Conflict01, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("DROP GRAPH test"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "CREATE GRAPH test {(person: Person {id INT, name STRING}),(person) -[:Friend]-> (person)};"); - EXPECT_EQ(result.first, E_OK); - - result = store_->ExecuteGql("CREATE UNIQUE INDEX index_person_id ON person(id);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql("INSERT (:Person {id: 1, name: 'name_1'});"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql("INSERT (:Person {id: 1, name: 'name_2'});"); - EXPECT_EQ(result.first, E_GRD_DATA_CONFLICT); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_UtilsStringTest, TestSize.Level1) -{ - std::string str = "abcd"; - GdbUtils::ClearAndZeroString(str); - EXPECT_EQ(str, ""); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_UtilsConfigTest, TestSize.Level1) -{ - std::vector keys = {1, 2, 3, 4, 5, 6, 7, 8}; - auto ret = GdbUtils::GetConfigStr(keys, false); - EXPECT_EQ(ret, R"({"pageSize": 8, "crcCheckEnable": 0, "defaultIsolationLevel": 3, )" - R"("redoFlushByTrx": 1, "metaInfoBak": 1, "maxConnNum": 500, "bufferPoolSize": 10240})"); - - ret = GdbUtils::GetConfigStr(keys, true); - EXPECT_EQ(ret, R"({"isEncrypted":1,"hexPassword":"0102030405060708",)" - R"("pageSize": 8, "crcCheckEnable": 0, "defaultIsolationLevel": 3, )" - R"("redoFlushByTrx": 1, "metaInfoBak": 1, "maxConnNum": 500, "bufferPoolSize": 10240})"); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_UtilsKeyTest, TestSize.Level1) -{ - std::vector keys = {1, 2, 3, 4, 5, 6, 7, 8}; - const size_t keyBuffSize = keys.size() * 2 + 1; // 2 hex number can represent a uint8_t, 1 is for '\0' - std::vector keyBuff(keyBuffSize); - auto ret = GdbUtils::GetEncryptKey(keys, keyBuff.data(), keyBuffSize); - std::string hexString(ret, ret + keyBuffSize - 1); - EXPECT_EQ(hexString, "0102030405060708"); -} \ No newline at end of file diff --git a/relational_store/test/native/gdb/unittest/gdb_function_test.cpp b/relational_store/test/native/gdb/unittest/gdb_function_test.cpp deleted file mode 100644 index 228bdad4a3843fa503f3efc4b8f74b44e7521e86..0000000000000000000000000000000000000000 --- a/relational_store/test/native/gdb/unittest/gdb_function_test.cpp +++ /dev/null @@ -1,204 +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. -*/ - -#define LOG_TAG "GdbFuncTest" -#include - -#include - -#include "gdb_errors.h" -#include "connection_pool.h" -#include "gdb_helper.h" -#include "grd_adapter_manager.h" -#include "logger.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; -class GdbFuncTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase(); - void SetUp(); - void TearDown(); -}; - -void GdbFuncTest::SetUpTestCase() -{ - LOG_INFO("SetUpTestCase"); -} - -void GdbFuncTest::TearDownTestCase() -{ - LOG_INFO("TearDownTestCase"); -} - -void GdbFuncTest::SetUp() -{ - LOG_INFO("SetUp"); - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - } -} - -void GdbFuncTest::TearDown() -{ - LOG_INFO("TearDown"); -} - -HWTEST_F(GdbFuncTest, GdbStore_Func_OpenClose01, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "testReopendb"; - std::string dbPath = "/data"; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - - auto result = store->QueryGql(""); - EXPECT_NE(result.first, E_OK); - - store->Close(); - result = store->QueryGql("abc"); - EXPECT_NE(result.first, E_OK); - - store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(errCode, E_OK); - - GDBHelper::DeleteDBStore(config); - - auto store1 = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - result = store1->ExecuteGql( - "CREATE GRAPH test {(person: Person {name STRING, age INT, sex BOOL DEFAULT false})}"); - EXPECT_EQ(result.first, E_OK); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbFuncTest, GdbStore_Func_CreateConnPool01, TestSize.Level1) -{ - int32_t errCode = E_OK; - auto config = StoreConfig("test", "/data", DBType::DB_VECTOR); - auto connectionPool = ConnectionPool::Create(config, errCode); - EXPECT_EQ(errCode, E_NOT_SUPPORT); -} - -HWTEST_F(GdbFuncTest, GdbStore_Func_CreateConnPool02, TestSize.Level1) -{ - int32_t errCode = E_OK; - auto config = StoreConfig("test", "/data", DBType::DB_GRAPH); - config.SetIter(0); - EXPECT_EQ(config.GetIter(), 0); - auto connectionPool = ConnectionPool::Create(config, errCode); - EXPECT_EQ(errCode, E_OK); -} - -HWTEST_F(GdbFuncTest, GdbStore_Func_CreateConnPool03, TestSize.Level1) -{ - int32_t errCode = E_OK; - auto config = StoreConfig("test", "/data", DBType::DB_GRAPH); - config.SetReadConSize(0); - auto connectionPool = ConnectionPool::Create(config, errCode); - EXPECT_EQ(errCode, E_OK); - - auto connRead1 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead1, nullptr); - EXPECT_EQ(connRead1->GetDBType(), DBType::DB_GRAPH); - auto connRead2 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead2, nullptr); - auto connRead3 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead3, nullptr); - - auto connWrite1 = connectionPool->AcquireRef(false); - EXPECT_NE(connWrite1, nullptr); - auto connWrite2 = connectionPool->AcquireRef(false); - EXPECT_NE(connWrite2, nullptr); - auto connWrite3 = connectionPool->AcquireRef(false); - EXPECT_NE(connWrite3, nullptr); - - connWrite1 = nullptr; - connWrite2 = nullptr; - connWrite3 = nullptr; - auto connWrite4 = connectionPool->AcquireRef(false); - EXPECT_NE(connWrite4, nullptr); - - connectionPool->CloseAllConnections(); - - connRead1 = connectionPool->AcquireRef(true); - EXPECT_EQ(connRead1, nullptr); - - connWrite1 = connectionPool->AcquireRef(false); - EXPECT_EQ(connWrite1, nullptr); -} - -HWTEST_F(GdbFuncTest, GdbStore_Func_CreateConnPool04, TestSize.Level1) -{ - int32_t errCode = E_OK; - auto config = StoreConfig("test", "/data", DBType::DB_GRAPH); - config.SetReadConSize(65); - auto connectionPool = ConnectionPool::Create(config, errCode); - EXPECT_EQ(errCode, E_ARGS_READ_CON_OVERLOAD); -} - -HWTEST_F(GdbFuncTest, GdbStore_Func_CreateConnPool05, TestSize.Level1) -{ - int32_t errCode = E_OK; - auto config = StoreConfig("test", "/data", DBType::DB_GRAPH); - auto connectionPool = ConnectionPool::Create(config, errCode); - EXPECT_EQ(errCode, E_OK); - - errCode = connectionPool->Dump(true, "header"); - EXPECT_EQ(errCode, E_OK); - - errCode = connectionPool->RestartReaders(); - EXPECT_EQ(errCode, E_OK); - - auto connRead1 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead1, nullptr); - EXPECT_NE(connRead1->GetId(), -1); - auto connRead2 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead2, nullptr); - auto connRead3 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead3, nullptr); - auto connRead4 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead4, nullptr); - auto connRead5 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead5, nullptr); - auto connRead6 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead6, nullptr); - - auto connWrite1 = connectionPool->AcquireRef(false); - EXPECT_NE(connWrite1, nullptr); - auto connWrite2 = connectionPool->AcquireRef(false); - EXPECT_EQ(connWrite2, nullptr); - auto connWrite3 = connectionPool->AcquireRef(false); - EXPECT_EQ(connWrite3, nullptr); - - connWrite1 = nullptr; - connWrite2 = nullptr; - connWrite3 = nullptr; - auto connWrite4 = connectionPool->AcquireRef(false); - EXPECT_NE(connWrite4, nullptr); - - connectionPool->CloseAllConnections(); - - connRead1 = connectionPool->AcquireRef(true); - EXPECT_EQ(connRead1, nullptr); - - connWrite1 = connectionPool->AcquireRef(false); - EXPECT_EQ(connWrite1, nullptr); -} \ No newline at end of file diff --git a/relational_store/test/native/gdb/unittest/gdb_grd_adapter_test.cpp b/relational_store/test/native/gdb/unittest/gdb_grd_adapter_test.cpp deleted file mode 100644 index 3a60a496f11964be46318988ef54cf93d4d7558b..0000000000000000000000000000000000000000 --- a/relational_store/test/native/gdb/unittest/gdb_grd_adapter_test.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Copyright (c) 2025 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 -#include -#include -#include -#include - -#include "gdb_errors.h" -#include "db_store_manager.h" -#include "edge.h" -#include "full_result.h" -#include "gdb_helper.h" -#include "gdb_store.h" -#include "gdb_transaction.h" -#include "grd_adapter_manager.h" -#include "path.h" -#include "result.h" -#include "vertex.h" -#include "../mock/grd_adapter.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; - -using FuncName = GrdAdapter::FuncName; - -class GdbGrdAdapterTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase() {} - void SetUp(); - void TearDown() {} - - void CheckPrepareStepErrCode(int32_t grdErr, int32_t gdbErr, FuncName func); - void CheckRekeyErrCode(int32_t grdErr, int32_t gdbErr); - - void GetStore(const std::string &name); - void DeleteStore(const std::string &name); - - static const std::string path; - static const std::string createGraphGql; - static const std::string executeGql; - static const std::string queryGql; - - static std::shared_ptr store_; -}; - -const std::string GdbGrdAdapterTest::path = "/data"; - -const std::string GdbGrdAdapterTest::createGraphGql = "CREATE GRAPH test { " - "(person:Person {name STRING, age INT, sex BOOL DEFAULT false})," - "(dog:Dog {name STRING, age INT}), " - "(person) -[:Friend]-> (person) " - "};"; - -const std::string GdbGrdAdapterTest::executeGql = "INSERT (:Person {name: 'name_1', age: 11});"; -const std::string GdbGrdAdapterTest::queryGql = "MATCH (person:Person {name: 'name_1'}) RETURN person;"; - -std::shared_ptr GdbGrdAdapterTest::store_; - -static constexpr int32_t MAX_LEN = 128; -static constexpr int32_t MAX_PROP_CNT = 1024; - -void GdbGrdAdapterTest::SetUpTestCase() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } -} - -void GdbGrdAdapterTest::SetUp() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } -} - -void GdbGrdAdapterTest::GetStore(const std::string &name) -{ - auto config = StoreConfig(name, path); - GDBHelper::DeleteDBStore(config); - - int32_t errorCode = E_OK; - store_ = GDBHelper::GetDBStore(config, errorCode); - ASSERT_NE(store_, nullptr); - ASSERT_EQ(errorCode, E_OK); - - auto [errCode, result] = store_->ExecuteGql(createGraphGql); - ASSERT_EQ(errCode, E_OK); - - GrdAdapter::SetErrorCode(FuncName::ALL, GRD_OK); -} - -void GdbGrdAdapterTest::DeleteStore(const std::string &name) -{ - auto config = StoreConfig(name, path); - GDBHelper::DeleteDBStore(config); - - store_ = nullptr; -} - -void GdbGrdAdapterTest::CheckPrepareStepErrCode(int32_t grdErr, int32_t gdbErr, FuncName func) -{ - std::string name = "prepare_step_test"; - GetStore(name); - ASSERT_NE(store_, nullptr); - - GrdAdapter::SetErrorCode(func, grdErr); - - auto [errCode, result] = store_->ExecuteGql(executeGql); - EXPECT_EQ(errCode, gdbErr); - - std::tie(errCode, result) = store_->QueryGql(queryGql); - if (func == FuncName::STEP && grdErr == GRD_NO_DATA) { - EXPECT_EQ(errCode, E_OK); - } else { - EXPECT_EQ(errCode, gdbErr); - } - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, gdbErr); - EXPECT_EQ(trans, nullptr); - - GrdAdapter::SetErrorCode(func, GRD_OK); - - std::tie(err, trans) = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - - GrdAdapter::SetErrorCode(func, grdErr); - - std::tie(errCode, result) = trans->Execute(executeGql); - EXPECT_EQ(errCode, gdbErr); - - std::tie(errCode, result) = trans->Query(queryGql); - if (func == FuncName::STEP && grdErr == GRD_NO_DATA) { - EXPECT_EQ(errCode, E_OK); - } else { - EXPECT_EQ(errCode, gdbErr); - } - - errCode = trans->Commit(); - EXPECT_EQ(errCode, gdbErr); - - GrdAdapter::SetErrorCode(func, GRD_OK); - - std::tie(err, trans) = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - - GrdAdapter::SetErrorCode(func, grdErr); - - errCode = trans->Rollback(); - EXPECT_EQ(errCode, gdbErr); - - GrdAdapter::SetErrorCode(func, GRD_OK); - - DeleteStore(name); -} - -void GdbGrdAdapterTest::CheckRekeyErrCode(int32_t grdErr, int32_t gdbErr) -{ - std::string name = "rekey_test"; - GetStore(name); - ASSERT_NE(store_, nullptr); - - auto errCode = store_->Close(); - EXPECT_EQ(errCode, E_OK); - StoreManager::GetInstance().Clear(); - - GrdAdapter::SetErrorCode(FuncName::REKEY, grdErr); - - auto config = StoreConfig(name, path, DBType::DB_GRAPH, true); - store_ = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(errCode, gdbErr); - EXPECT_EQ(store_, nullptr); - - GrdAdapter::SetErrorCode(FuncName::REKEY, GRD_OK); - - DeleteStore(name); -} - -/** - * @tc.name: GdbGrdAdapterTest001 - * @tc.desc: test Prepare returned the following error code - * @tc.type: FUNC - */ -HWTEST_F(GdbGrdAdapterTest, GdbGrdAdapterTest001, TestSize.Level1) -{ - std::map errCodeMap = { - { GRD_INVALID_ARGS, E_GRD_INVALID_ARGS }, - { GRD_SYNTAX_ERROR, E_GRD_SYNTAX_ERROR }, - { GRD_SEMANTIC_ERROR, E_GRD_SEMANTIC_ERROR }, - { GRD_OVER_LIMIT, E_GRD_OVER_LIMIT }, - { GRD_FAILED_MEMORY_ALLOCATE, E_GRD_FAILED_MEMORY_ALLOCATE }, - { GRD_MODEL_NOT_SUPPORT, E_GRD_SEMANTIC_ERROR }, - { GRD_FEATURE_NOT_SUPPORTED, E_GRD_SEMANTIC_ERROR }, - { GRD_DATATYPE_MISMATCH, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_VALUE, E_GRD_INVALID_ARGS }, - { GRD_NAME_TOO_LONG, E_GRD_INVALID_NAME }, - { GRD_DUPLICATE_TABLE, E_GRD_DUPLICATE_PARAM }, - { GRD_DUPLICATE_OBJECT, E_GRD_DUPLICATE_PARAM }, - { GRD_INVALID_CONFIG_VALUE, E_CONFIG_INVALID_CHANGE }, - { GRD_DUPLICATE_COLUMN, E_GRD_DUPLICATE_PARAM }, - { GRD_UNDEFINE_COLUMN, E_GRD_UNDEFINED_PARAM }, - { GRD_UNDEFINED_OBJECT, E_GRD_UNDEFINED_PARAM }, - { GRD_UNDEFINED_TABLE, E_GRD_UNDEFINED_PARAM }, - }; - - for (auto [grdErr, gdbErr] : errCodeMap) { - CheckPrepareStepErrCode(grdErr, gdbErr, FuncName::PREPARE); - } -} - -/** - * @tc.name: GdbGrdAdapterTest002 - * @tc.desc: test Step returned the following error code - * @tc.type: FUNC - */ -HWTEST_F(GdbGrdAdapterTest, GdbGrdAdapterTest002, TestSize.Level1) -{ - std::map errCodeMap = { - { GRD_NO_DATA, E_GRD_NO_DATA }, - { GRD_INVALID_TABLE_DEFINITION, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_ARGS, E_GRD_INVALID_ARGS }, - { GRD_INVALID_CONFIG_VALUE, E_CONFIG_INVALID_CHANGE }, - { GRD_DATATYPE_MISMATCH, E_GRD_SEMANTIC_ERROR }, - { GRD_DIVISION_BY_ZERO, E_GRD_SYNTAX_ERROR }, - { GRD_MODEL_NOT_SUPPORT, E_GRD_SEMANTIC_ERROR }, - { GRD_FEATURE_NOT_SUPPORTED, E_GRD_SEMANTIC_ERROR }, - { GRD_FIELD_OVERFLOW, E_GRD_SEMANTIC_ERROR }, - { GRD_FILE_OPERATE_FAILED, E_GRD_INNER_ERR }, - { GRD_INSUFFICIENT_RESOURCES, E_GRD_INNER_ERR }, - { GRD_RESOURCE_BUSY, E_DATABASE_BUSY }, - { GRD_OVER_LIMIT, E_GRD_OVER_LIMIT }, - { GRD_REQUEST_TIME_OUT, E_DATABASE_BUSY }, - { GRD_RESTRICT_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_NO_ACTIVE_TRANSACTION, E_GRD_NO_ACTIVE_TRANSACTION }, - { GRD_TRANSACTION_ROLLBACK, E_GRD_TRANSACTION_ROLLBACK }, - { GRD_ACTIVE_TRANSACTION, E_GRD_ACTIVE_TRANSACTION }, - { GRD_UNIQUE_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_PRIMARY_KEY_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_UNDEFINED_TABLE, E_GRD_UNDEFINED_PARAM }, - { GRD_UNDEFINED_OBJECT, E_GRD_UNDEFINED_PARAM }, - { GRD_DUPLICATE_TABLE, E_GRD_DUPLICATE_PARAM }, - { GRD_DUPLICATE_OBJECT, E_GRD_DUPLICATE_PARAM }, - { GRD_DATA_CORRUPTED, E_GRD_DATA_CORRUPTED }, - { GRD_THIRD_PARTY_FUNCTION_EXECUTE_FAILED, E_GRD_INNER_ERR }, - { GRD_SCHEMA_CHANGED, E_CONFIG_INVALID_CHANGE }, - }; - - for (auto [grdErr, gdbErr] : errCodeMap) { - CheckPrepareStepErrCode(grdErr, gdbErr, FuncName::STEP); - } -} - -/** - * @tc.name: GdbGrdAdapterTest003 - * @tc.desc: test ReKey returned the following error code - * @tc.type: FUNC - */ -HWTEST_F(GdbGrdAdapterTest, GdbGrdAdapterTest003, TestSize.Level1) -{ - std::map errCodeMap = { - { GRD_INVALID_ARGS, E_GRD_INVALID_ARGS }, - { GRD_INNER_ERR, E_GRD_INNER_ERR }, - { GRD_NO_DATA, E_GRD_NO_DATA }, - { GRD_RESOURCE_BUSY, E_DATABASE_BUSY }, - { GRD_SYSTEM_ERR, E_GRD_INNER_ERR }, - { GRD_INVALID_FORMAT, E_GRD_SEMANTIC_ERROR }, - { GRD_INSUFFICIENT_SPACE, E_GRD_DISK_SPACE_FULL }, - { GRD_DB_INSTANCE_ABNORMAL, E_GRD_DB_INSTANCE_ABNORMAL }, - { GRD_DB_BUSY, E_DATABASE_BUSY }, - { GRD_DATA_CORRUPTED, E_GRD_DATA_CORRUPTED }, - }; - - for (auto [grdErr, gdbErr] : errCodeMap) { - CheckRekeyErrCode(grdErr, gdbErr); - } -} - -/** - * @tc.name: GdbGrdAdapterTest004 - * @tc.desc: test whether the error code returned by Prepare when using the following gql is correct - * @tc.type: FUNC - */ -HWTEST_F(GdbGrdAdapterTest, GdbGrdAdapterTest004, TestSize.Level1) -{ - std::string duplicateObjectGql = "CREATE GRAPH test { " - "(person:Person {name STRING, age INT, age DOUBLE})," - "(person) -[:Friend]-> (person) " - "};"; - std::map errCodeMap = { - { "INSERT (:Person {});", E_GRD_SYNTAX_ERROR }, // GRD_SYNTAX_ERROR - { "INSERT ();", E_GRD_SEMANTIC_ERROR }, // GRD_SEMANTIC_ERROR - { "INSERT (:Person {name: 11, age: 'age_11'});", E_GRD_SEMANTIC_ERROR }, // GRD_DATATYPE_MISMATCH - { "DROP GRAPH nonexistent_graph;", E_GRD_UNDEFINED_PARAM }, // GRD_UNDEFINE_COLUMN - { "MATCH (a: Person {name: 'Alf'}) SET a.nationality='EN'", E_GRD_UNDEFINED_PARAM }, // GRD_UNDEFINED_OBJECT - { "INSERT (:Student {name: 'name_1', age: 11});", E_GRD_UNDEFINED_PARAM }, // GRD_UNDEFINED_TABLE - { duplicateObjectGql, E_GRD_DUPLICATE_PARAM }, // GRD_DUPLICATE_OBJECT - }; - - for (auto [gql, gdbErr] : errCodeMap) { - std::string name = "prepare_test"; - GetStore(name); - ASSERT_NE(store_, nullptr); - - auto [errCode, result] = store_->ExecuteGql(gql); - EXPECT_EQ(errCode, gdbErr); - - DeleteStore(name); - } -} - -/** - * @tc.name: GdbGrdAdapterTest005 - * @tc.desc: test whether the error code returned by Prepare when using the following gql is correct - * @tc.type: FUNC - */ -HWTEST_F(GdbGrdAdapterTest, GdbGrdAdapterTest005, TestSize.Level1) -{ - std::string graphName = "test_"; - for (int i = 0; i < MAX_LEN; i++) { - graphName += "a"; - } - std::string nameTooLongGql = "CREATE GRAPH " + graphName + " { " - "(person:Person {name STRING, age INT, sex BOOL DEFAULT false})," - "(person) -[:Friend]-> (person) " - "};"; - std::string duplicateTableGql = "CREATE GRAPH test { " - "(person:Person {name STRING, age INT, sex BOOL DEFAULT false})," - "(student:Person {name STRING, age INT}), " - "(person) -[:Friend]-> (person) " - "};"; - std::string duplicateColumnGql = "CREATE GRAPH test { " - "(person:Person {name STRING, age INT, age DOUBLE})," - "(person) -[:Friend]-> (person) " - "};"; - std::map errCodeMap = { - { nameTooLongGql, E_GRD_INVALID_NAME }, // GRD_NAME_TOO_LONG - { duplicateTableGql, E_GRD_DUPLICATE_PARAM }, // GRD_DUPLICATE_TABLE - { duplicateColumnGql, E_GRD_DUPLICATE_PARAM }, // GRD_DUPLICATE_COLUMN - }; - - for (auto [gql, gdbErr] : errCodeMap) { - std::string name = "prepare_test"; - auto config = StoreConfig(name, path); - GDBHelper::DeleteDBStore(config); - - int32_t errorCode = E_OK; - store_ = GDBHelper::GetDBStore(config, errorCode); - ASSERT_NE(store_, nullptr); - ASSERT_EQ(errorCode, E_OK); - - auto [errCode, result] = store_->ExecuteGql(gql); - EXPECT_EQ(errCode, gdbErr); - - DeleteStore(name); - } -} - -/** - * @tc.name: GdbGrdAdapterTest006 - * @tc.desc: test whether the error code returned by Step when using the following gql is correct - * @tc.type: FUNC - */ -HWTEST_F(GdbGrdAdapterTest, GdbGrdAdapterTest006, TestSize.Level1) -{ - std::map errCodeMap = { - { "MATCH (p:Person {age: 11}) RETURN p.age / 0;", E_GRD_SYNTAX_ERROR }, // GRD_DIVISION_BY_ZERO - { "MATCH (p:Person {age: 11}) SET p.age=9223372036854775808;", E_GRD_SEMANTIC_ERROR }, // GRD_FIELD_OVERFLOW - }; - - for (auto [gql, gdbErr] : errCodeMap) { - std::string name = "step_test"; - GetStore(name); - ASSERT_NE(store_, nullptr); - - auto [errCode, result] = store_->ExecuteGql(executeGql); - EXPECT_EQ(errCode, E_OK); - - std::tie(errCode, result) = store_->ExecuteGql(gql); - EXPECT_EQ(errCode, gdbErr); - - DeleteStore(name); - } -} - -/** - * @tc.name: GdbGrdAdapterTest007 - * @tc.desc: test whether the error code returned by Step when using the following gql is correct - * @tc.type: FUNC - */ -HWTEST_F(GdbGrdAdapterTest, GdbGrdAdapterTest007, TestSize.Level1) -{ - std::string name = "step_test"; - auto config = StoreConfig(name, path); - GDBHelper::DeleteDBStore(config); - - int32_t errorCode = E_OK; - store_ = GDBHelper::GetDBStore(config, errorCode); - ASSERT_NE(store_, nullptr); - ASSERT_EQ(errorCode, E_OK); - - std::string overLimitGql = "CREATE GRAPH test { (person:Person {"; - for (int i = 0; i < MAX_PROP_CNT; i++) { - overLimitGql += "name" + std::to_string(i) + " STRING, "; - } - overLimitGql += "age INT, sex BOOL DEFAULT false}) };"; - - auto [errCode, result] = store_->ExecuteGql(overLimitGql); - EXPECT_EQ(errCode, E_GRD_OVER_LIMIT); // GRD_OVER_LIMIT - - DeleteStore(name); -} - -/** - * @tc.name: GdbGrdAdapterTest008 - * @tc.desc: test whether the error code returned by Step when using the following gql is correct - * @tc.type: FUNC - */ -HWTEST_F(GdbGrdAdapterTest, GdbGrdAdapterTest008, TestSize.Level1) -{ - std::string name = "step_test"; - GetStore(name); - ASSERT_NE(store_, nullptr); - - auto [errCode, result] = store_->ExecuteGql("CREATE UNIQUE INDEX nameIndex ON Person(name);"); - EXPECT_EQ(errCode, E_OK); - - std::tie(errCode, result) = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(errCode, E_OK); - - std::tie(errCode, result) = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 22});"); - EXPECT_EQ(errCode, E_GRD_DATA_CONFLICT); // GRD_UNIQUE_VIOLATION - - DeleteStore(name); -} diff --git a/relational_store/test/native/gdb/unittest/gdb_grdapi_test.cpp b/relational_store/test/native/gdb/unittest/gdb_grdapi_test.cpp deleted file mode 100644 index f9088256ca644c5a903fdeed55be28c7a8a2fbab..0000000000000000000000000000000000000000 --- a/relational_store/test/native/gdb/unittest/gdb_grdapi_test.cpp +++ /dev/null @@ -1,187 +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. -*/ - -#define LOG_TAG "GdbGrdApiTest" -#include -#include - -#include -#include -#include - -#include "gdb_errors.h" -#include "db_store_manager.h" -#include "gdb_helper.h" -#include "grd_adapter.h" -#include "grd_adapter_manager.h" -#include "grd_error.h" -#include "logger.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; -class GdbGrdApiTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase(); - void SetUp(); - void TearDown(); -}; - -void GdbGrdApiTest::SetUpTestCase() -{ - LOG_INFO("SetUpTestCase"); -} - -void GdbGrdApiTest::TearDownTestCase() -{ - LOG_INFO("TearDownTestCase"); -} - -void GdbGrdApiTest::SetUp() -{ - LOG_INFO("SetUp"); - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - } -} - -void GdbGrdApiTest::TearDown() -{ - LOG_INFO("TearDown"); -} - -HWTEST_F(GdbGrdApiTest, GdbStore_GrdApi_TransType01, TestSize.Level1) -{ - auto type = GrdAdapter::TransColType(GRD_DB_DATATYPE_INTEGER); - EXPECT_EQ(type, ColumnType::TYPE_INTEGER); - type = GrdAdapter::TransColType(GRD_DB_DATATYPE_FLOAT); - EXPECT_EQ(type, ColumnType::TYPE_FLOAT); - type = GrdAdapter::TransColType(GRD_DB_DATATYPE_TEXT); - EXPECT_EQ(type, ColumnType::TYPE_TEXT); - type = GrdAdapter::TransColType(GRD_DB_DATATYPE_BLOB); - EXPECT_EQ(type, ColumnType::TYPE_BLOB); - type = GrdAdapter::TransColType(GRD_DB_DATATYPE_FLOATVECTOR); - EXPECT_EQ(type, ColumnType::TYPE_FLOATVECTOR); - type = GrdAdapter::TransColType(GRD_DB_DATATYPE_JSONSTR); - EXPECT_EQ(type, ColumnType::TYPE_JSONSTR); - type = GrdAdapter::TransColType(GRD_DB_DATATYPE_NULL); - EXPECT_EQ(type, ColumnType::TYPE_NULL); - type = GrdAdapter::TransColType(-1); - EXPECT_EQ(type, ColumnType::TYPE_NULL); - type = GrdAdapter::TransColType(7); - EXPECT_EQ(type, ColumnType::TYPE_NULL); -} - -HWTEST_F(GdbGrdApiTest, GdbStore_GrdApi_NotUsed01, TestSize.Level1) -{ - std::string createGql = "CREATE GRAPH test {(person:Person {name STRING} )};"; - std::string dbPath = "/data/test.db"; - std::string backupPath = "/data/testBackup.db"; - GDBHelper::DeleteDBStore({"test", "/data"}); - if (g_library != nullptr) { - dlclose(g_library); - } - GRD_DB *db = nullptr; - auto ret = GrdAdapter::Open(dbPath.c_str(), "", GRD_DB_OPEN_CREATE, &db); - EXPECT_EQ(ret, E_OK); - - if (g_library != nullptr) { - dlclose(g_library); - } - std::vector entryKey = { 't', 'e', 's', 't' }; - ret = GrdAdapter::Backup(db, backupPath.c_str(), entryKey); - EXPECT_EQ(ret, E_NOT_SUPPORT); - - if (g_library != nullptr) { - dlclose(g_library); - } - ret = GrdAdapter::Close(db, 0); - EXPECT_EQ(ret, E_OK); - - if (g_library != nullptr) { - dlclose(g_library); - } - ret = GrdAdapter::Restore(dbPath.c_str(), backupPath.c_str(), entryKey); - EXPECT_EQ(ret, E_NOT_SUPPORT); - - if (g_library != nullptr) { - dlclose(g_library); - } - ret = GrdAdapter::Repair(dbPath.c_str(), ""); - EXPECT_EQ(ret, E_NOT_SUPPORT); - - if (g_library != nullptr) { - dlclose(g_library); - } - ret = GrdAdapter::Rekey(dbPath.c_str(), "", std::vector()); - EXPECT_EQ(ret, E_GRD_INVALID_ARGS); - GDBHelper::DeleteDBStore({"test", "/data"}); -} - -HWTEST_F(GdbGrdApiTest, GdbStore_GrdApi_NotUsed02, TestSize.Level1) -{ - std::string createGql = "CREATE GRAPH test {(person:Person {name STRING} )};"; - std::string dbPath = "/data/test.db"; - std::string backupPath = "/data/testBackup.db"; - GDBHelper::DeleteDBStore({"test", "/data"}); - GRD_DB *db = nullptr; - if (g_library != nullptr) { - dlclose(g_library); - } - auto ret = GrdAdapter::Open(dbPath.c_str(), "", GRD_DB_OPEN_CREATE, &db); - EXPECT_EQ(ret, E_OK); - - if (g_library != nullptr) { - dlclose(g_library); - } - GRD_Stmt *stmt = nullptr; - ret = GrdAdapter::Prepare(db, createGql.c_str(), createGql.size(), &stmt, nullptr); - EXPECT_EQ(ret, E_OK); - - if (g_library != nullptr) { - dlclose(g_library); - } - ret = GrdAdapter::Reset(stmt); - EXPECT_EQ(ret, E_OK); - - if (g_library != nullptr) { - dlclose(g_library); - } - auto result = GrdAdapter::ColumnBytes(stmt, 0); - EXPECT_EQ(result, 0); - - if (g_library != nullptr) { - dlclose(g_library); - } - auto result2 = GrdAdapter::ColumnInt64(stmt, 0); - EXPECT_EQ(result2, 0); - - result2 = GrdAdapter::ColumnInt(stmt, 0); - EXPECT_EQ(result2, 0); - - auto result3 = GrdAdapter::ColumnDouble(stmt, 0); - EXPECT_EQ(result3, 0.0); - - if (g_library != nullptr) { - dlclose(g_library); - } - auto value = GrdAdapter::ColumnValue(stmt, 0); - EXPECT_EQ(value.type, GRD_DB_DATATYPE_NULL); - ret = StoreManager::GetInstance().Delete(dbPath); - EXPECT_EQ(ret, 1); - ret = StoreManager::GetInstance().Delete(backupPath); - EXPECT_EQ(ret, 1); - GDBHelper::DeleteDBStore({"test", "/data"}); -} \ No newline at end of file diff --git a/relational_store/test/native/gdb/unittest/gdb_multi_thread_test.cpp b/relational_store/test/native/gdb/unittest/gdb_multi_thread_test.cpp deleted file mode 100644 index 6eded7742e3a7ee5f9d769a91cda48bf2480e00d..0000000000000000000000000000000000000000 --- a/relational_store/test/native/gdb/unittest/gdb_multi_thread_test.cpp +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (c) 2025 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 -#include -#include -#include -#include - -#include "gdb_errors.h" -#include "executor_pool.h" -#include "grd_adapter_manager.h" -#include "gdb_helper.h" -#include "gdb_store.h" -#include "path.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; -class GdbMultiThreadTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - void VerifyPersonInfo(const GraphValue &person, const std::string &name, const int32_t &age); - void MatchAndVerifyPerson(const std::string &name, const int32_t &age, std::shared_ptr store); - void MultiThreadExecuteInsert(std::shared_ptr store); - void MultiThreadExecuteDBStore(); - void MultiThreadInsertRelation(std::shared_ptr store); - void MultiThreadQueryRelation(std::shared_ptr store); - std::string RandomString(size_t length); - -protected: - std::atomic counter; - static const std::string databaseName; - static const std::string databasePath; - static const std::string createGraphGql; - std::shared_ptr executors_; -}; -const std::string GdbMultiThreadTest::databaseName = "execute_test"; -const std::string GdbMultiThreadTest::databasePath = "/data"; -const std::string GdbMultiThreadTest::createGraphGql = "CREATE GRAPH test { " - "(person:Person {name STRING, age INT, sex BOOL DEFAULT false})," - "(dog:Dog {name STRING, age INT}), " - "(person) -[:Friend]-> (person) " - "};"; - -void GdbMultiThreadTest::SetUpTestCase(void) -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } -} - -void GdbMultiThreadTest::TearDownTestCase(void) -{ -} - -void GdbMultiThreadTest::SetUp() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } - int32_t maxThread = 5; - int32_t minThread = 0; - executors_ = std::make_shared(maxThread, minThread); -} - -void GdbMultiThreadTest::TearDown() -{ - executors_ = nullptr; -} - -/** - * @tc.name: MultiThread_GetDBStore_0001 - * @tc.desc: Start two threads to open the database. - * @tc.type: FUNC - */ -HWTEST_F(GdbMultiThreadTest, MultiThread_GetDBStore_0001, TestSize.Level2) -{ - counter.store(0); - MultiThreadExecuteDBStore(); - MultiThreadExecuteDBStore(); - while (true) { - if (counter.load() == 100) { - break; - } - } -} - -/** - * @tc.name: MultiThreadExecuteDBStore - * @tc.desc: Start the database in the current thread for 50 times. - * @tc.type: FUNC - */ -void GdbMultiThreadTest::MultiThreadExecuteDBStore() -{ - executors_->Execute([this]() { - int errCode = E_OK; - std::string dbName = RandomString(10) + RandomString(10); - constexpr int32_t COUNT = 50; - for (uint32_t j = 0; j < COUNT; j++) { - auto config = StoreConfig(dbName + std::to_string(j), databasePath); - GDBHelper::DeleteDBStore(config); - auto store = GDBHelper::GetDBStore(config, errCode); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(store, nullptr); - EXPECT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - - result = store->ExecuteGql("DROP GRAPH test"); - EXPECT_NE(store, nullptr); - EXPECT_EQ(result.first, E_OK); - GDBHelper::DeleteDBStore(config); - counter.fetch_add(1, std::memory_order_relaxed); - } - }); -} - -/** - * @tc.name: MultiThread_GetDBStore_0002 - * @tc.desc: Start two threads to test the insertion Vertex and Edge. - * @tc.type: FUNC - */ -HWTEST_F(GdbMultiThreadTest, MultiThread_GetDBStore_0002, TestSize.Level2) -{ - int errCode = E_OK; - auto config = StoreConfig(databaseName + "test22", databasePath); - auto store = GDBHelper::GetDBStore(config, errCode); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(store, nullptr); - EXPECT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - counter.store(0); - MultiThreadExecuteInsert(store); - sleep(1); - MultiThreadExecuteInsert(store); - while (true) { - // counter ++ 200 - if (counter.load() == 200) { - break; - } - } - sleep(1); - result = store->ExecuteGql("DROP GRAPH test"); - EXPECT_NE(store, nullptr); - EXPECT_EQ(result.first, E_OK); - GDBHelper::DeleteDBStore(config); -} - -/** - * @tc.name: MultiThreadExecuteInsert - * @tc.desc: Start threads to test the insertion Vertex and Edge. - * @tc.type: FUNC - */ -void GdbMultiThreadTest::MultiThreadExecuteInsert(std::shared_ptr store) -{ - executors_->Execute([this, &store]() { - std::string nameStr = RandomString(10) + RandomString(10); - constexpr int32_t MAX_COUNT = 100; - for (uint32_t j = 0; j < MAX_COUNT; j++) { - std::string name = nameStr + std::to_string(j); - auto result = store->ExecuteGql("INSERT (:Person {name: '" + name + "', age: 11});"); - EXPECT_EQ(result.first, E_OK); - constexpr int32_t AGE_11 = 11; - MatchAndVerifyPerson(name, AGE_11, store); - - std::string name2 = name + std::to_string(j); - result = store->ExecuteGql("INSERT (:Person {name: '" + name2 + "', age: 22});"); - EXPECT_EQ(result.first, E_OK); - constexpr int32_t AGE = 22; - MatchAndVerifyPerson(name2, AGE, store); - - std::string name3 = name2 + std::to_string(j); - result = store->ExecuteGql("INSERT (:Person {name: '" + name3 + "', age: 33});"); - EXPECT_EQ(result.first, E_OK); - constexpr int32_t AGE_33 = 33; - MatchAndVerifyPerson(name3, AGE_33, store); - - result = store->ExecuteGql("MATCH (p1:Person {name: '" + name + "'}), (p2:Person {name: '" + name2 + - "'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("MATCH (p1:Person {name: '" + name2 + "'}), (p2:Person {name: '" + name3 + - "'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - - result = store->QueryGql( - "MATCH (person:Person {name: '" + name + "'})-[relation:Friend]->() RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - - auto result2 = store->QueryGql("MATCH path=(a:Person {name: '" + name + - "'})-[]->{2, 2}(b:Person {name: '" + name3 + "'}) RETURN path;"); - ASSERT_EQ(result2.first, E_OK); - counter.fetch_add(1, std::memory_order_relaxed); - } - }); -} - -/** - * @tc.name: MultiThread_GetDBStore_0003 - * @tc.desc: Start two threads to insert edges of the same Vertex, and start another thread to query edges. - * @tc.type: FUNC - */ -HWTEST_F(GdbMultiThreadTest, MultiThread_GetDBStore_0003, TestSize.Level2) -{ - int errCode = E_OK; - auto config = StoreConfig(databaseName + "test33", databasePath); - auto store = GDBHelper::GetDBStore(config, errCode); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(store, nullptr); - EXPECT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - counter.store(0); - - std::string name = "zhangsan"; - result = store->ExecuteGql("INSERT (:Person {name: '" + name + "', age: 11});"); - EXPECT_EQ(result.first, E_OK); - constexpr int32_t AGE_11 = 11; - MatchAndVerifyPerson(name, AGE_11, store); - //insert Vertex and edge - MultiThreadInsertRelation(store); - MultiThreadInsertRelation(store); - sleep(1); - //query Vertex and edge - MultiThreadExecuteInsert(store); - while (true) { - if (counter.load() == 300) { - break; - } - } - // query match count is 200 - result = - store->QueryGql("MATCH (person:Person {name: '" + name + "'})-[relation:Friend]->() RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 200); - - result = store->ExecuteGql("DROP GRAPH test"); - EXPECT_NE(store, nullptr); - EXPECT_EQ(result.first, E_OK); - GDBHelper::DeleteDBStore(config); -} - -void GdbMultiThreadTest::MultiThreadInsertRelation(std::shared_ptr store) -{ - executors_->Execute([this, &store]() { - std::string nameStr = RandomString(10) + RandomString(10); - std::string name = "zhangsan"; - constexpr int32_t MAX_COUNT = 100; - for (uint32_t j = 0; j < MAX_COUNT; j++) { - std::string name2 = nameStr + std::to_string(j); - auto result = store->ExecuteGql("INSERT (:Person {name: '" + name2 + "', age: 22});"); - EXPECT_EQ(result.first, E_OK); - constexpr int32_t AGE = 22; - MatchAndVerifyPerson(name2, AGE, store); - - result = store->ExecuteGql("MATCH (p1:Person {name: '" + name + "'}), (p2:Person {name: '" + name2 + - "'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - counter.fetch_add(1, std::memory_order_relaxed); - } - }); -} - -void GdbMultiThreadTest::MultiThreadQueryRelation(std::shared_ptr store) -{ - executors_->Execute([this, &store]() { - std::string name = "zhangsan"; - constexpr int32_t MAX_COUNT = 100; - for (uint32_t j = 0; j < MAX_COUNT; j++) { - auto result = store->QueryGql( - "MATCH (person:Person {name: '" + name + "'})-[relation:Friend]->() RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - counter.fetch_add(1, std::memory_order_relaxed); - } - }); -} - -std::string GdbMultiThreadTest::RandomString(size_t length) -{ - const std::string letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(0, letters.size() - 1); - - std::string randomStr; - for (size_t i = 0; i < length; ++i) { - randomStr.push_back(letters[dis(gen)]); - } - return randomStr; -} - -void GdbMultiThreadTest::MatchAndVerifyPerson( - const std::string &name, const int32_t &age, std::shared_ptr store) -{ - EXPECT_NE(store, nullptr); - auto gql = "MATCH (person:Person {name: '" + name + "', age: " + std::to_string(age) + "}) RETURN person;"; - auto result = store->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - ASSERT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, name, age); -} - -void GdbMultiThreadTest::VerifyPersonInfo(const GraphValue &person, const std::string &name, const int32_t &age) -{ - auto expectSize = 3; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), expectSize); - - auto nameDb = personVertex->GetProperties().find("name"); - ASSERT_NE(nameDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(nameDb->second)); - EXPECT_EQ(std::get(nameDb->second), name); - - auto ageDb = personVertex->GetProperties().find("age"); - ASSERT_NE(ageDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(ageDb->second)); - EXPECT_EQ(std::get(ageDb->second), age); - - auto sex = personVertex->GetProperties().find("sex"); - ASSERT_NE(sex, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(sex->second)); - EXPECT_EQ(std::get(sex->second), 0); -} \ No newline at end of file diff --git a/relational_store/test/native/gdb/unittest/gdb_query_test.cpp b/relational_store/test/native/gdb/unittest/gdb_query_test.cpp deleted file mode 100644 index eac39961ba77af774cb4f3499b1942b860ba09fc..0000000000000000000000000000000000000000 --- a/relational_store/test/native/gdb/unittest/gdb_query_test.cpp +++ /dev/null @@ -1,646 +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 - -#include -#include -#include -#include -#include - -#include "gdb_errors.h" -#include "gdb_helper.h" -#include "gdb_store.h" -#include "grd_adapter_manager.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; -class GdbQueryTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase(); - void SetUp(); - void TearDown(); - void InsertCompany(const std::string &name, const int32_t &founded); - void MatchAndVerifyCompany(const std::string &name, const int32_t &founded); - void VerifyCompanyInfo(const GraphValue &company, const std::string &name, const int32_t &founded); - - static const std::string databaseName; - static const std::string databasePath; - static std::shared_ptr store_; - static const std::string createGraphGql; - static const std::string createGraphGql2; - static const std::shared_ptr databaseConfig; -}; -std::shared_ptr GdbQueryTest::store_; -const std::string GdbQueryTest::databaseName = "test_gdb"; -const std::string GdbQueryTest::databasePath = "/data"; -const std::string GdbQueryTest::createGraphGql = "CREATE GRAPH companyGraph { " - "(company:Company {name STRING, founded INT}), " - "(department:Department {name STRING}), " - "(employee:Employee {name STRING, position STRING}), " - "(project:Project {name STRING, budget INT}), " - "(company) -[:HAS_DEPARTMENT]-> (department), " - "(department) -[:HAS_EMPLOYEE]-> (employee), " - "(employee) -[:WORKS_ON]-> (project), " - "(department) -[:HAS_PROJECT]-> (project) " - "};"; -const std::string GdbQueryTest::createGraphGql2 = "CREATE GRAPH companyGraph2 {" - "(company:Company {name STRING, founded INT}) };"; -void GdbQueryTest::SetUpTestCase() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - } - int errCode = E_OK; - auto config = StoreConfig(databaseName, databasePath); - GDBHelper::DeleteDBStore(config); - - GdbQueryTest::store_ = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(GdbQueryTest::store_, nullptr); - EXPECT_EQ(errCode, E_OK); -} - -void GdbQueryTest::TearDownTestCase() -{ - GDBHelper::DeleteDBStore(StoreConfig(databaseName, databasePath)); - store_ = nullptr; -} - -void GdbQueryTest::SetUp() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - } - auto result = store_->ExecuteGql(createGraphGql); - EXPECT_EQ(result.first, E_OK); -} - -void GdbQueryTest::TearDown() -{ - if (store_ != nullptr) { - auto result = store_->ExecuteGql("DROP GRAPH companyGraph"); - } -} - -HWTEST_F(GdbQueryTest, GdbStore_Test_CreateHaveRowId, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto createGql = "CREATE GRAPH companyGraph3 {" - "(company:Company {rowid INT, name STRING, founded INT}) };"; - auto result = store_->ExecuteGql(createGql); - EXPECT_EQ(result.first, E_GRD_OVER_LIMIT); -} - -/** - * @tc.name: GdbStore_Test_CreateLimitDb - * @tc.desc: Too many graphs can be created for only one graph in a library. Failed to create too many graphs. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_Test_CreateLimitDb, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - // Too many graphs can be created for only one graph in a library. Failed to create too many graphs. - auto result = store_->ExecuteGql(createGraphGql2); - EXPECT_EQ(result.first, E_GRD_OVER_LIMIT); -} - -/** - * @tc.name: GdbStore_QuertTest_001 - * @tc.desc: To test the function of querying an employee. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_001, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - // Insert Employee - const std::string insertEmployeeQuery = "INSERT (:Employee {name: 'John Doe11', position: 'Software Engineer'});"; - auto result = store_->ExecuteGql(insertEmployeeQuery); - EXPECT_EQ(result.first, E_OK); - - // Verifying the Employee Vertex - result = store_->QueryGql("MATCH (e:Employee {name: 'John Doe11'}) RETURN e;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - - GraphValue employee = result.second->GetAllData()[0]["e"]; - ASSERT_TRUE(std::holds_alternative>(employee)); - auto employeeVertex = std::get>(employee); - EXPECT_EQ(employeeVertex->GetLabel(), "Employee"); - - auto name = employeeVertex->GetProperties().find("name"); - ASSERT_NE(name, employeeVertex->GetProperties().end()); - EXPECT_EQ(std::get(name->second), "John Doe11"); - - auto position = employeeVertex->GetProperties().find("position"); - ASSERT_NE(position, employeeVertex->GetProperties().end()); - EXPECT_EQ(std::get(position->second), "Software Engineer"); -} - -/** - * @tc.name: GdbStore_QuertTest_002 - * @tc.desc: To test the function of querying an Employee and Project and Relation. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_002, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - // insert Employee - auto result = store_->ExecuteGql("INSERT (:Employee {name: 'John Doe', position: 'Software Engineer'});"); - EXPECT_EQ(result.first, E_OK); - // insert Project - result = store_->ExecuteGql("INSERT (:Project {name: 'Project Alpha'});"); - EXPECT_EQ(result.first, E_OK); - - // Associating an Employee with a Project, WORKS_ON - const std::string insertRelationQuery = - "MATCH (e:Employee {name: 'John Doe'}), (p:Project {name: 'Project Alpha'}) " - "INSERT (e)-[:WORKS_ON]->(p);"; - result = store_->ExecuteGql(insertRelationQuery); - EXPECT_EQ(result.first, E_OK); - - // Querying and Verifying the Relationship Existence - result = store_->QueryGql("MATCH (e:Employee {name: 'John Doe'})-[r:WORKS_ON]->" - "(p:Project {name: 'Project Alpha'}) RETURN e, r, p;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - - // Verifying the Employee Vertex - GraphValue employee = result.second->GetAllData()[0]["e"]; - ASSERT_TRUE(std::holds_alternative>(employee)); - auto employeeVertex = std::get>(employee); - EXPECT_EQ(employeeVertex->GetLabel(), "Employee"); - - // Verifying Project Vertex - GraphValue project = result.second->GetAllData()[0]["p"]; - ASSERT_TRUE(std::holds_alternative>(project)); - auto projectVertex = std::get>(project); - EXPECT_EQ(projectVertex->GetLabel(), "Project"); - - // Validate Relationships - GraphValue relation = result.second->GetAllData()[0]["r"]; - ASSERT_TRUE(std::holds_alternative>(relation)); - auto relationship = std::get>(relation); - EXPECT_EQ(relationship->GetSourceId(), "1"); - EXPECT_EQ(relationship->GetTargetId(), "2"); -} - -/** - * @tc.name: MatchAndVerifyCompany - * @tc.desc: Match And Verify that company information meets expectations - * @tc.type: FUNC - */ -void GdbQueryTest::MatchAndVerifyCompany(const std::string &name, const int32_t &founded) -{ - ASSERT_NE(store_, nullptr); - auto gql = "MATCH (company:Company {name: '" + name + "'}) RETURN company;"; - auto result = store_->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, name, founded); -} - -/** - * @tc.name: VerifyCompanyInfo - * @tc.desc: Verify that company information meets expectations - * @tc.type: FUNC - */ -void GdbQueryTest::VerifyCompanyInfo(const GraphValue &company, const std::string &name, const int32_t &founded) -{ - auto expectSize = 2; - ASSERT_TRUE(std::holds_alternative>(company)); - auto companyVertex = std::get>(company); - EXPECT_EQ(companyVertex->GetLabel(), "Company"); - ASSERT_EQ(companyVertex->GetProperties().size(), expectSize); - - auto nameDb = companyVertex->GetProperties().find("name"); - ASSERT_NE(nameDb, companyVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(nameDb->second)); - EXPECT_EQ(std::get(nameDb->second), name); - - auto foundedDb = companyVertex->GetProperties().find("founded"); - ASSERT_NE(foundedDb, companyVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(foundedDb->second)); - EXPECT_EQ(std::get(foundedDb->second), founded); -} - -/** - * @tc.name: InsertCompany - * @tc.desc: Insert Company Information - * @tc.type: FUNC - */ -void GdbQueryTest::InsertCompany(const std::string &name, const int32_t &founded) -{ - ASSERT_NE(store_, nullptr); - auto result = - store_->ExecuteGql("INSERT (:Company {name: '" + name + "', founded: " + std::to_string(founded) + "});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyCompany(name, founded); -} - -/** - * @tc.name: GdbStore_QuertTest_WhereInMatch - * @tc.desc: Verify the where condition in match. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_WhereInMatch, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("myCompany3", 2011); - // where condition in match. - auto result = store_->QueryGql("MATCH (company:Company where company.founded > 2000) RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany2", 2001); - - GraphValue company1 = result.second->GetAllData()[1]["company"]; - VerifyCompanyInfo(company1, "myCompany3", 2011); -} - -/** - * @tc.name: GdbStore_QuertTest_WhereOutsideMatch - * @tc.desc: Validate where condition outside match - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_WhereOutsideMatch, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("myCompany3", 2011); - // where condition outside match - auto result = store_->QueryGql("MATCH (company:Company) where company.founded != 2001 RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany", 1991); - - GraphValue company1 = result.second->GetAllData()[1]["company"]; - VerifyCompanyInfo(company1, "myCompany3", 2011); -} - -/** - * @tc.name: GdbStore_QuertTest_WhereAppendAnd - * @tc.desc: Verify that the where condition is appended to the AND statement outside the match condition. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_WhereAppendAnd, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("myCompany3", 2011); - // Verify that the where condition is appended to the AND statement outside the match condition. - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.founded != 2001 and company.name <> 'myCompany3' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany", 1991); -} - -/** - * @tc.name: GdbStore_QuertTest_WhereOutsideAndInsideMatch - * @tc.desc: Validate where conditions outside and inside match - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_WhereOutsideAndInsideMatch, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("myCompany3", 2011); - // Validate where conditions outside and inside match - auto result = store_->QueryGql("MATCH (company:Company where company.founded != 2001 ) " - " where company.name <> 'myCompany3' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany", 1991); -} - -/** - * @tc.name: GdbStore_QuertTest_WhereStartAnd - * @tc.desc: The validation condition is outside and inside match, but outside it starts with and, not where. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_WhereStartAnd, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("myCompany3", 2011); - // The validation condition is outside and inside match, but outside it starts with and, not where. - auto result = store_->QueryGql("MATCH (company:Company where company.founded != 2001 ) " - " AND company.name <> 'myCompany3' RETURN company;"); - ASSERT_EQ(result.first, E_GRD_SYNTAX_ERROR); - EXPECT_EQ(result.second->GetAllData().size(), 0); -} - -/** - * @tc.name: GdbStore_QuertTest_WhereByMatch - * @tc.desc: Use {} to transfer query conditions in match. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_WhereByMatch, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("myCompany3", 2011); - // The validation condition is outside and inside match, but outside it starts with and, not where. - auto result = store_->QueryGql("MATCH (company:Company {founded: 2001} ) " - " where company.name = 'myCompany2' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany2", 2001); -} - -/** - * @tc.name: GdbStore_QuertTest_WhereOperators - * @tc.desc: Verify that operators are supported in the where condition. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_WhereOperators, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("myCompany3", 2011); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.founded >= 2000+1 and company.founded < 2012 -1 RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany2", 2001); - - result = store_->QueryGql("MATCH (company:Company) " - "where company.founded > 2 * 1000 +1 and company.founded < 2 * 1000 +12 RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany3", 2011); -} - -/** - * @tc.name: GdbStore_QuertTest_PostLike - * @tc.desc: Verify that the matching starts with a fixed character and ends with any number of other characters. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_PostLike, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("aimyCompany", 2011); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.name like 'myCompany%' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany", 1991); - - company = result.second->GetAllData()[1]["company"]; - VerifyCompanyInfo(company, "myCompany2", 2001); -} - -/** - * @tc.name: GdbStore_QuertTest_WhereLike - * @tc.desc: Matches contain specific characters. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_Like, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("aimyCompany", 2011); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.name like '%myCompany%' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 3); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany", 1991); - - company = result.second->GetAllData()[1]["company"]; - VerifyCompanyInfo(company, "myCompany2", 2001); - - company = result.second->GetAllData()[2]["company"]; - VerifyCompanyInfo(company, "aimyCompany", 2011); -} - -/** - * @tc.name: GdbStore_QuertTest_BeferLike - * @tc.desc: Matches any number of other characters before the end of a fixed character. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_BeferLike, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("aimyCompany", 2011); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.name like '%myCompany' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany", 1991); - - company = result.second->GetAllData()[1]["company"]; - VerifyCompanyInfo(company, "aimyCompany", 2011); -} - -/** - * @tc.name: GdbStore_QuertTest_MatchesCharacter - * @tc.desc: Matches a character - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_MatchesCharacter, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("amyCompany", 2001); - InsertCompany("amyCompanya", 2002); - InsertCompany("abmyCompanyab", 2003); - InsertCompany("abmyCompany", 2004); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.name like '_myCompany' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "amyCompany", 2001); -} - -/** - * @tc.name: GdbStore_QuertTest_MatchesCharacter02 - * @tc.desc: Matches a character - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_MatchesCharacter02, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("amyCompany", 2001); - InsertCompany("amyCompanya", 2002); - InsertCompany("abmyCompanyab", 2003); - InsertCompany("abmyCompany", 2004); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.name like '_myCompany_' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "amyCompanya", 2002); -} - -/** - * @tc.name: GdbStore_QuertTest_MatchesCharacter03 - * @tc.desc: Matches a character - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_MatchesCharacter03, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - InsertCompany("myCompany", 1991); - InsertCompany("myCompanya", 2001); - InsertCompany("myCompanyab", 2002); - InsertCompany("amyCompanya", 2003); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.name like 'myCompany_' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompanya", 2001); -} - -/** - * @tc.name: GdbStore_QuertTest_In - * @tc.desc: Match conditions in - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_In, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - InsertCompany("myCompany", 1991); - InsertCompany("myCompany1", 2001); - InsertCompany("myCompany2", 2002); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.founded in (2001, 2002, 9999) RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany1", 2001); - - company = result.second->GetAllData()[1]["company"]; - VerifyCompanyInfo(company, "myCompany2", 2002); -} - -/** - * @tc.name: GdbStore_QuertTest_In01 - * @tc.desc: Match conditions in - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_NotIn, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - InsertCompany("myCompany", 1991); - InsertCompany("myCompany1", 2001); - InsertCompany("myCompany2", 2002); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.founded not in (2001, 9999) RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany", 1991); - - company = result.second->GetAllData()[1]["company"]; - VerifyCompanyInfo(company, "myCompany2", 2002); -} - -/** - * @tc.name: GdbStore_QuertTest_IsNull - * @tc.desc: Match conditions in - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_IsNull, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto result = store_->ExecuteGql("INSERT (:Employee {name: 'zhangsan', position: 'Software'});"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql("INSERT (:Employee {name: 'zhangsan1', position: 'Software1'});"); - EXPECT_EQ(result.first, E_OK); - // 寮簊chema涓嬪叾浠栨湭濉瓧娈典负null - result = store_->ExecuteGql("MATCH (e:Employee {name: 'zhangsan'}) SET e = {position: 'SoftwareNew'};"); - EXPECT_EQ(result.first, E_OK); - result = store_->QueryGql("MATCH (e:Employee) " - "where e.name IS NULL RETURN e;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["e"]; - ASSERT_TRUE(std::holds_alternative>(company)); - auto companyVertex = std::get>(company); - EXPECT_EQ(companyVertex->GetLabel(), "Employee"); - ASSERT_EQ(companyVertex->GetProperties().size(), 1); - - auto nameDb = companyVertex->GetProperties().find("name"); - EXPECT_EQ(nameDb, companyVertex->GetProperties().end()); - - auto foundedDb = companyVertex->GetProperties().find("position"); - ASSERT_NE(foundedDb, companyVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(foundedDb->second)); - EXPECT_EQ(std::get(foundedDb->second), "SoftwareNew"); -} - -/** - * @tc.name: GdbStore_QuertTest_IsNotNull - * @tc.desc: Match conditions in - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_IsNotNull, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto result = store_->ExecuteGql("INSERT (:Company {founded: 1991});"); - EXPECT_EQ(result.first, E_OK); - InsertCompany("myCompany1", 2001); - InsertCompany("myCompany2", 2002); - result = store_->QueryGql("MATCH (company:Company) " - "where company.name IS NOT NULL RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany1", 2001); - - company = result.second->GetAllData()[1]["company"]; - VerifyCompanyInfo(company, "myCompany2", 2002); -} \ No newline at end of file diff --git a/relational_store/test/native/gdb/unittest/gdb_transaction_test.cpp b/relational_store/test/native/gdb/unittest/gdb_transaction_test.cpp deleted file mode 100644 index 71626cbe5bfcf9d59507cb5de29a1d692c4b0095..0000000000000000000000000000000000000000 --- a/relational_store/test/native/gdb/unittest/gdb_transaction_test.cpp +++ /dev/null @@ -1,802 +0,0 @@ -/* - * Copyright (c) 2025 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 "gdb_transaction.h" - -#include - -#include -#include -#include -#include -#include - -#include "edge.h" -#include "full_result.h" -#include "gdb_errors.h" -#include "gdb_helper.h" -#include "gdb_store.h" -#include "grd_adapter_manager.h" -#include "path.h" -#include "result.h" -#include "vertex.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; - -using Transaction = OHOS::DistributedDataAip::Transaction; - -class GdbTransactionTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase(); - void SetUp(); - void TearDown(); - void InsertPerson(const std::string &name, const int32_t &age, std::shared_ptr trans = nullptr); - void MatchAndVerifyPerson(const std::string &name, const int32_t &age, - std::shared_ptr trans = nullptr, bool hasData = true); - void VerifyPersonInfo(const GraphValue &person, const std::string &name, const int32_t &age); - - static const std::string databaseName; - static const std::string databasePath; - - static const std::string createGraphGql; - - static std::shared_ptr store_; -}; - -const std::string GdbTransactionTest::databaseName = "transaction_test"; -const std::string GdbTransactionTest::databasePath = "/data"; - -const std::string GdbTransactionTest::createGraphGql = "CREATE GRAPH test { " - "(person:Person {name STRING, age INT, sex BOOL DEFAULT false})," - "(dog:Dog {name STRING, age INT}), " - "(person) -[:Friend]-> (person) " - "};"; - -std::shared_ptr GdbTransactionTest::store_; - -static constexpr int32_t MAX_GQL_LEN = 1024 * 1024; - -static constexpr int32_t MAX_CNT = 4; -static constexpr int32_t MAX_DATA_CNT = 200; - -static constexpr int32_t BUSY_TIMEOUT = 2; -static constexpr int32_t EXECUTE_INTERVAL = 3; -static constexpr int32_t READ_INTERVAL = 100; - -void GdbTransactionTest::SetUpTestCase() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } - int errCode = E_OK; - auto config = StoreConfig(databaseName, databasePath); - GDBHelper::DeleteDBStore(config); - - GdbTransactionTest::store_ = GDBHelper::GetDBStore(config, errCode); -} - -void GdbTransactionTest::TearDownTestCase() -{ - GDBHelper::DeleteDBStore(StoreConfig(databaseName, databasePath)); - GdbTransactionTest::store_ = nullptr; -} - -void GdbTransactionTest::SetUp() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } - auto result = store_->ExecuteGql(createGraphGql); -} - -void GdbTransactionTest::TearDown() -{ - if (store_ != nullptr) { - auto result = store_->ExecuteGql("DROP GRAPH test"); - } -} - -void GdbTransactionTest::InsertPerson(const std::string &name, const int32_t &age, std::shared_ptr trans) -{ - ASSERT_NE(store_, nullptr); - int32_t errCode = E_OK; - std::shared_ptr result = std::make_shared(); - std::string gql = "INSERT (:Person {name: '" + name + "', age: " + std::to_string(age) + "});"; - if (trans == nullptr) { - std::tie(errCode, result) = store_->ExecuteGql(gql); - } else { - ASSERT_NE(trans, nullptr); - std::tie(errCode, result) = trans->Execute(gql); - } - EXPECT_EQ(errCode, E_OK); -} - -void GdbTransactionTest::MatchAndVerifyPerson(const std::string &name, const int32_t &age, - std::shared_ptr trans, bool hasData) -{ - ASSERT_NE(store_, nullptr); - int32_t errCode = E_OK; - std::shared_ptr result = std::make_shared(); - std::string gql = "MATCH (person:Person {name: '" + name + "'}) RETURN person;"; - if (trans == nullptr) { - std::tie(errCode, result) = store_->QueryGql(gql); - } else { - ASSERT_NE(trans, nullptr); - std::tie(errCode, result) = trans->Query(gql); - } - ASSERT_EQ(errCode, E_OK); - ASSERT_NE(result, nullptr); - if (!hasData) { - EXPECT_EQ(result->GetAllData().size(), 0); - return; - } - EXPECT_EQ(result->GetAllData().size(), 1); - GraphValue person = result->GetAllData()[0]["person"]; - VerifyPersonInfo(person, name, age); -} - -void GdbTransactionTest::VerifyPersonInfo(const GraphValue &person, const std::string &name, const int32_t &age) -{ - auto expectSize = 3; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), expectSize); - - auto nameDb = personVertex->GetProperties().find("name"); - ASSERT_NE(nameDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(nameDb->second)); - EXPECT_EQ(std::get(nameDb->second), name); - - auto ageDb = personVertex->GetProperties().find("age"); - ASSERT_NE(ageDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(ageDb->second)); - EXPECT_EQ(std::get(ageDb->second), age); - - auto sex = personVertex->GetProperties().find("sex"); - ASSERT_NE(sex, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(sex->second)); - EXPECT_EQ(std::get(sex->second), 0); -} - -/** - * @tc.name: GdbTransactionTest001_CreateTransaction_Normal - * @tc.desc: test CreateTransaction - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest001_CreateTransaction_Normal, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err1, trans1] = store_->CreateTransaction(); - EXPECT_EQ(err1, E_OK); - EXPECT_NE(trans1, nullptr); - - auto [err2, trans2] = store_->CreateTransaction(); - EXPECT_EQ(err2, E_OK); - EXPECT_NE(trans2, nullptr); - - auto [err3, trans3] = store_->CreateTransaction(); - EXPECT_EQ(err3, E_OK); - EXPECT_NE(trans3, nullptr); - - auto [err4, trans4] = store_->CreateTransaction(); - EXPECT_EQ(err4, E_OK); - EXPECT_NE(trans4, nullptr); - - err4 = trans4->Commit(); - EXPECT_EQ(err4, E_OK); - - auto [err5, trans5] = store_->CreateTransaction(); - EXPECT_EQ(err5, E_OK); - EXPECT_NE(trans5, nullptr); -} - -/** - * @tc.name: GdbTransactionTest002_CreateTransaction_Abnormal - * @tc.desc: test CreateTransaction upper bound - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest002_CreateTransaction_Abnormal, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err1, trans1] = store_->CreateTransaction(); - EXPECT_EQ(err1, E_OK); - EXPECT_NE(trans1, nullptr); - - auto [err2, trans2] = store_->CreateTransaction(); - EXPECT_EQ(err2, E_OK); - EXPECT_NE(trans2, nullptr); - - auto [err3, trans3] = store_->CreateTransaction(); - EXPECT_EQ(err3, E_OK); - EXPECT_NE(trans3, nullptr); - - auto [err4, trans4] = store_->CreateTransaction(); - EXPECT_EQ(err4, E_OK); - EXPECT_NE(trans4, nullptr); - - auto [err5, trans5] = store_->CreateTransaction(); - EXPECT_EQ(err5, E_DATABASE_BUSY); - EXPECT_EQ(trans5, nullptr); -} - -/** - * @tc.name: GdbTransactionTest003_Query_Execute_Normal - * @tc.desc: test Transaction::Query and Transaction::Execute - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest003_Query_Execute_Normal, TestSize.Level1) -{ - InsertPerson("name_1", 11); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - - MatchAndVerifyPerson("name_1", 11, trans); - - InsertPerson("name_2", 22, trans); - - MatchAndVerifyPerson("name_2", 22, trans); -} - -/** - * @tc.name: GdbTransactionTest004_Query_Execute_Abnormal - * @tc.desc: test Transaction::Query and Transaction::Execute with invalid gql - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest004_Query_Execute_Abnormal, TestSize.Level1) -{ - InsertPerson("name_1", 11); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - - int32_t errCode = E_OK; - std::shared_ptr result = std::make_shared(); - std::string gql = ""; - std::tie(errCode, result) = trans->Query(gql); - EXPECT_EQ(errCode, E_INVALID_ARGS); - - std::tie(errCode, result) = trans->Execute(gql); - EXPECT_EQ(errCode, E_INVALID_ARGS); - - for (int i = 0; i <= MAX_GQL_LEN; i++) { - gql += "I"; - } - std::tie(errCode, result) = trans->Query(gql); - EXPECT_EQ(errCode, E_INVALID_ARGS); - - std::tie(errCode, result) = trans->Execute(gql); - EXPECT_EQ(errCode, E_INVALID_ARGS); - - gql = "MATCH (person:Person {name: 11}) RETURN person;"; - std::tie(errCode, result) = trans->Query(gql); - EXPECT_EQ(errCode, E_GRD_SEMANTIC_ERROR); - - std::tie(err, trans) = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - gql = "INSERT (:Person {name: 11, age: 'name_1'});"; - std::tie(errCode, result) = trans->Execute(gql); - EXPECT_EQ(errCode, E_GRD_SEMANTIC_ERROR); - - std::tie(err, trans) = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - gql = "MATCH;"; - std::tie(errCode, result) = trans->Query(gql); - EXPECT_EQ(errCode, E_GRD_SYNTAX_ERROR); - - std::tie(err, trans) = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - gql = "INSERT;"; - std::tie(errCode, result) = trans->Execute(gql); - EXPECT_EQ(errCode, E_GRD_SYNTAX_ERROR); -} - -/** - * @tc.name: GdbTransactionTest005_Commit_Normal - * @tc.desc: test Transaction::Commit - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest005_Commit_Normal, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - - InsertPerson("name_1", 11, trans); - - auto gql = "MATCH (person:Person {name: 'name_1'}) RETURN person;"; - auto result = store_->QueryGql(gql); - EXPECT_EQ(result.first, E_DATABASE_BUSY); - - auto errCode = trans->Commit(); - EXPECT_EQ(errCode, E_OK); - - MatchAndVerifyPerson("name_1", 11); -} - -/** - * @tc.name: GdbTransactionTest006_Commit_Abnormal - * @tc.desc: test Transaction::Commit - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest006_Commit_Abnormal, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - - auto errCode = trans->Commit(); - EXPECT_EQ(errCode, E_OK); - - errCode = trans->Commit(); - EXPECT_EQ(errCode, E_GRD_DB_INSTANCE_ABNORMAL); -} - -/** - * @tc.name: GdbTransactionTest007_Rollback_Normal - * @tc.desc: test Transaction::Rollback - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest007_Rollback_Normal, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - - InsertPerson("name_1", 11, trans); - - auto gql = "MATCH (person:Person {name: 'name_1'}) RETURN person;"; - auto result = store_->QueryGql(gql); - EXPECT_EQ(result.first, E_DATABASE_BUSY); - - auto errCode = trans->Rollback(); - EXPECT_EQ(errCode, E_OK); - - MatchAndVerifyPerson("name_1", 11, nullptr, false); -} - -/** - * @tc.name: GdbTransactionTest008_Rollback_Abnormal - * @tc.desc: test Transaction::Rollback - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest008_Rollback_Abnormal, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - - auto errCode = trans->Rollback(); - EXPECT_EQ(errCode, E_OK); - - errCode = trans->Rollback(); - EXPECT_EQ(errCode, E_GRD_DB_INSTANCE_ABNORMAL); -} - -/** - * @tc.name: GdbTransactionTest009_Isolation001 - * @tc.desc: test Transaction - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest009_Isolation001, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err1, trans1] = store_->CreateTransaction(); - EXPECT_EQ(err1, E_OK); - EXPECT_NE(trans1, nullptr); - - auto [err2, trans2] = store_->CreateTransaction(); - EXPECT_EQ(err2, E_OK); - EXPECT_NE(trans2, nullptr); - - InsertPerson("name_1", 11, trans1); - - auto gql = "MATCH (person:Person {name: 'name_1'}) RETURN person;"; - auto [errCode, result] = trans2->Query(gql); - EXPECT_EQ(errCode, E_DATABASE_BUSY); -} - -/** - * @tc.name: GdbTransactionTest010_Isolation002 - * @tc.desc: test Transaction - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest010_Isolation002, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err1, trans1] = store_->CreateTransaction(); - EXPECT_EQ(err1, E_OK); - EXPECT_NE(trans1, nullptr); - - auto [err2, trans2] = store_->CreateTransaction(); - EXPECT_EQ(err2, E_OK); - EXPECT_NE(trans2, nullptr); - - InsertPerson("name_1", 11, trans1); - - ASSERT_NE(trans1, nullptr); - auto errCode = trans1->Commit(); - EXPECT_EQ(errCode, E_OK); - - MatchAndVerifyPerson("name_1", 11, trans2); -} - -/** - * @tc.name: GdbTransactionTest011_Isolation003 - * @tc.desc: test Transaction - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest011_Isolation003, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err1, trans1] = store_->CreateTransaction(); - EXPECT_EQ(err1, E_OK); - EXPECT_NE(trans1, nullptr); - - auto [err2, trans2] = store_->CreateTransaction(); - EXPECT_EQ(err2, E_OK); - EXPECT_NE(trans2, nullptr); - - InsertPerson("name_1", 11, trans1); - - ASSERT_NE(trans1, nullptr); - auto errCode = trans1->Rollback(); - EXPECT_EQ(errCode, E_OK); - - MatchAndVerifyPerson("name_1", 11, trans2, false); -} - -/** - * @tc.name: GdbTransactionTest012_Isolation004 - * @tc.desc: test Transaction - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest012_Isolation004, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err1, trans1] = store_->CreateTransaction(); - EXPECT_EQ(err1, E_OK); - EXPECT_NE(trans1, nullptr); - - auto [err2, trans2] = store_->CreateTransaction(); - EXPECT_EQ(err2, E_OK); - EXPECT_NE(trans2, nullptr); - - InsertPerson("name_1", 11, trans1); - - ASSERT_NE(trans2, nullptr); - int32_t errCode = E_OK; - std::shared_ptr result = std::make_shared(); - std::tie(errCode, result) = trans2->Execute("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(errCode, E_DATABASE_BUSY); - - errCode = trans1->Commit(); - EXPECT_EQ(errCode, E_OK); - - InsertPerson("name_2", 22, trans2); -} - -/** - * @tc.name: GdbTransactionTest013_Close - * @tc.desc: test Close - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest013_Close, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - - InsertPerson("name_1", 11, trans); - - ASSERT_NE(store_, nullptr); - int32_t errCode = store_->Close(); - EXPECT_EQ(errCode, E_OK); - store_ = nullptr; - - auto config = StoreConfig(databaseName, databasePath); - store_ = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store_, nullptr); - - MatchAndVerifyPerson("name_1", 11, nullptr, false); -} - -/** - * @tc.name: GdbTransactionTest014_StartTransByExecute - * @tc.desc: test Execute("START TRANSACTION;"), Execute("COMMIT") and Execute("ROLLBACK") - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest014_StartTransByExecute001, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err, result] = store_->ExecuteGql("START TRANSACTION;"); - EXPECT_EQ(err, E_INVALID_ARGS); - - std::tie(err, result) = store_->ExecuteGql("COMMIT;"); - EXPECT_EQ(err, E_INVALID_ARGS); - - std::tie(err, result) = store_->ExecuteGql("ROLLBACK;"); - EXPECT_EQ(err, E_INVALID_ARGS); -} - -/** - * @tc.name: GdbTransactionTest015_TransactionNestification - * @tc.desc: test Transaction Nestification - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest015_TransactionNestification, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err1, trans1] = store_->CreateTransaction(); - EXPECT_EQ(err1, E_OK); - EXPECT_NE(trans1, nullptr); - - auto result = trans1->Execute("START TRANSACTION;"); - EXPECT_EQ(result.first, E_INVALID_ARGS); -} - -/** - * @tc.name: GdbTransactionTest016_TransactionMultiThread - * @tc.desc: test Transaction MultiThread - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest016_TransactionMultiThread, TestSize.Level1) -{ - std::thread th[MAX_CNT]; - for (int32_t i = 0; i < MAX_CNT; i++) { - th[i] = std::thread([this, i] () { - ASSERT_NE(store_, nullptr); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - - InsertPerson("name_" + std::to_string(i), i, trans); - - err = trans->Commit(); - EXPECT_EQ(err, E_OK); - }); - } - - for (int32_t i = 0; i < MAX_CNT; i++) { - th[i].join(); - } - - for (int32_t i = 0; i < MAX_CNT; i++) { - MatchAndVerifyPerson("name_" + std::to_string(i), i); - } -} - -/** - * @tc.name: GdbTransactionTest017_TransactionMultiThread - * @tc.desc: test Transaction MultiThread write busy(Unable to obtain lock in 2 seconds) - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest017_TransactionMultiThread, TestSize.Level1) -{ - std::thread th[MAX_CNT]; - std::atomic_int insertCnt = 0; - std::atomic_int insertIndex = -1; - for (int32_t i = 0; i < MAX_CNT; i++) { - th[i] = std::thread([this, i, &insertCnt, &insertIndex] () { - ASSERT_NE(store_, nullptr); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - - std::shared_ptr result = std::make_shared(); - std::string age = std::to_string(i); - std::string name = "name_" + age; - std::string gql = "INSERT (:Person {name: '" + name + "', age: " + age + "});"; - std::tie(err, result) = trans->Execute(gql); - if (err == E_OK && insertCnt.load() == 0) { - insertCnt++; - insertIndex.store(i); - } else { - EXPECT_EQ(err, E_DATABASE_BUSY); - } - - std::this_thread::sleep_for(std::chrono::seconds(BUSY_TIMEOUT)); - - err = trans->Commit(); - EXPECT_EQ(err, E_OK); - }); - } - - for (int32_t i = 0; i < MAX_CNT; i++) { - th[i].join(); - } - - for (int32_t i = 0; i < MAX_CNT; i++) { - if (i == insertIndex.load()) { - MatchAndVerifyPerson("name_" + std::to_string(i), i); - } else { - MatchAndVerifyPerson("name_" + std::to_string(i), i, nullptr, false); - } - } - - EXPECT_EQ(insertCnt, 1); -} - -/** - * @tc.name: GdbTransactionTest018_TransactionMultiThread - * @tc.desc: test Transaction MultiThread Trasaction.write and Transaction.read - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest018_TransactionMultiThread, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - std::thread writeThread([this] () { - for (int i = 0; i < MAX_DATA_CNT; i++) { - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - InsertPerson("name_" + std::to_string(i), i, trans); - err = trans->Commit(); - EXPECT_EQ(err, E_OK); - std::this_thread::sleep_for(std::chrono::milliseconds(EXECUTE_INTERVAL)); - } - }); - - std::thread readThread([this] () { - std::this_thread::sleep_for(std::chrono::milliseconds(READ_INTERVAL)); - for (int i = 0; i < MAX_DATA_CNT; i++) { - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - MatchAndVerifyPerson("name_" + std::to_string(i), i, trans); - err = trans->Rollback(); - EXPECT_EQ(err, E_OK); - std::this_thread::sleep_for(std::chrono::milliseconds(EXECUTE_INTERVAL)); - } - }); - - writeThread.join(); - readThread.join(); -} - -/** - * @tc.name: GdbTransactionTest019_TransactionMultiThread - * @tc.desc: test Transaction MultiThread GraphStore.write and Transaction.read - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest019_TransactionMultiThread, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - std::thread writeThread([this] () { - for (int i = 0; i < MAX_DATA_CNT; i++) { - InsertPerson("name_" + std::to_string(i), i); - std::this_thread::sleep_for(std::chrono::milliseconds(EXECUTE_INTERVAL)); - } - }); - - std::thread readThread([this] () { - std::this_thread::sleep_for(std::chrono::milliseconds(READ_INTERVAL)); - for (int i = 0; i < MAX_DATA_CNT; i++) { - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - MatchAndVerifyPerson("name_" + std::to_string(i), i, trans); - err = trans->Rollback(); - EXPECT_EQ(err, E_OK); - std::this_thread::sleep_for(std::chrono::milliseconds(EXECUTE_INTERVAL)); - } - }); - - writeThread.join(); - readThread.join(); -} - -/** - * @tc.name: GdbTransactionTest020_TransactionMultiThread - * @tc.desc: test Transaction MultiThread Trasaction.write and GraphStore.read - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest020_TransactionMultiThread, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - std::thread writeThread([this] () { - for (int i = 0; i < MAX_DATA_CNT; i++) { - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - InsertPerson("name_" + std::to_string(i), i, trans); - err = trans->Commit(); - EXPECT_EQ(err, E_OK); - std::this_thread::sleep_for(std::chrono::milliseconds(EXECUTE_INTERVAL)); - } - }); - - std::thread readThread([this] () { - std::this_thread::sleep_for(std::chrono::milliseconds(READ_INTERVAL)); - for (int i = 0; i < MAX_DATA_CNT; i++) { - MatchAndVerifyPerson("name_" + std::to_string(i), i); - std::this_thread::sleep_for(std::chrono::milliseconds(EXECUTE_INTERVAL)); - } - }); - - writeThread.join(); - readThread.join(); -} - -/** - * @tc.name: GdbTransactionTest021_TransactionMultiThread - * @tc.desc: test Transaction MultiThread Trasaction.write and GraphStore.write - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest021_TransactionMultiThread, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - std::thread transWriteThread([this] () { - for (int i = 0; i < MAX_DATA_CNT; i++) { - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - InsertPerson("name_trans_" + std::to_string(i), i, trans); - err = trans->Commit(); - EXPECT_EQ(err, E_OK); - std::this_thread::sleep_for(std::chrono::milliseconds(EXECUTE_INTERVAL)); - } - }); - - std::thread writeThread([this] () { - for (int i = 0; i < MAX_DATA_CNT; i++) { - InsertPerson("name_" + std::to_string(i), i); - std::this_thread::sleep_for(std::chrono::milliseconds(EXECUTE_INTERVAL)); - } - }); - - transWriteThread.join(); - writeThread.join(); - - for (int i = 0; i < MAX_DATA_CNT; i++) { - MatchAndVerifyPerson("name_trans_" + std::to_string(i), i); - MatchAndVerifyPerson("name_" + std::to_string(i), i); - } -} diff --git a/relational_store/test/native/rdb/BUILD.gn b/relational_store/test/native/rdb/BUILD.gn index 5a785407ffc0b0138dd2a51ac87d9c0cfc96ce82..5b78a5429662ee6d868a035142135363678639aa 100644 --- a/relational_store/test/native/rdb/BUILD.gn +++ b/relational_store/test/native/rdb/BUILD.gn @@ -21,14 +21,13 @@ config("module_private_config") { include_dirs = [ "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb_crypt", "${relational_store_native_path}/rdb/include", "${relational_store_innerapi_path}/rdb/include", "${relational_store_native_path}/dfx/include", "${relational_store_native_path}/rdb/src", "${relational_store_innerapi_path}/appdatafwk/include", - "//commonlibrary/c_utils/base/include", - "${common_tool_path}/", - "${kvstore_interface_path}", + "${relational_store_base_path}/test/native/rdb/unittest", ] defines = [ "RELATIONAL_STORE" ] @@ -48,17 +47,18 @@ ohos_unittest("NativeRdbMultiThreadTest") { "ability_base:zuri", "ability_runtime:dataobs_manager", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "huks:libhukssdk", "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddata_inner", "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", ] - deps = [ - "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", - "//third_party/sqlite:sqlite", - ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] } ohos_unittest("NativeRdbMultiProcessTest") { @@ -75,6 +75,7 @@ ohos_unittest("NativeRdbMultiProcessTest") { "${relational_store_native_path}/dfx/include", "${relational_store_native_path}/rdb/src", "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/test/native/rdb/unittest", ] defines = [ "RELATIONAL_STORE" ] @@ -87,7 +88,49 @@ ohos_unittest("NativeRdbMultiProcessTest") { "hilog:libhilog", "huks:libhukssdk", "ipc:ipc_core", + "kv_store:datamgr_common", "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] +} + +ohos_unittest("NativeRdbLogTest") { + module_out_path = module_output_path + + sources = [ + "unittest/common.cpp", + "unittest/rdb_error_log_test/get_rdb_store_test.cpp", + "unittest/rdb_error_log_test/rdb_error_log_test.cpp", + "unittest/rdb_error_log_test/rdb_perfStat_test.cpp", + ] + sources += [ + "../../../frameworks/native/rdb/src/suspender.cpp", + "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", + ] + include_dirs = [ + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_base_path}/test/native/rdb/unittest", + ] + + defines = [ "RELATIONAL_STORE" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "googletest:gtest", + "googletest:gtest_main", + "hilog:libhilog", + "huks:libhukssdk", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "kv_store:distributeddb_client", "sqlite:sqlite", ] @@ -110,6 +153,8 @@ ohos_unittest("NativeRdbTest") { "unittest/rd_utils_test.cpp", "unittest/rdb_attach_test.cpp", "unittest/rdb_bigint_test.cpp", + "unittest/rdb_callback_icu_test.cpp", + "unittest/rdb_concurrent_querywithcurd_test.cpp", "unittest/rdb_corrupt_test.cpp", "unittest/rdb_delete_test.cpp", "unittest/rdb_distributed_test.cpp", @@ -128,6 +173,7 @@ ohos_unittest("NativeRdbTest") { "unittest/rdb_rd_data_aging_test.cpp", "unittest/rdb_read_only_test.cpp", "unittest/rdb_security_manager_test.cpp", + "unittest/rdb_service_proxy_test.cpp", "unittest/rdb_sql_utils_test.cpp", "unittest/rdb_sqlite_shared_result_set_test.cpp", "unittest/rdb_step_result_get_row_test.cpp", @@ -149,38 +195,61 @@ ohos_unittest("NativeRdbTest") { "unittest/sqlite_utils_test.cpp", "unittest/transaction_test.cpp", "unittest/value_object_test.cpp", + "unittest/delay_notify_test.cpp", ] + if (is_ohos) { + sources += [ + "unittest/rdb_double_write_binlog_test.cpp", + ] + } + sources += [ - "../../../frameworks/native/rdb/mock/src/rdb_fault_hiview_reporter.cpp", - "../../../frameworks/native/rdb/src/base_transaction.cpp", - "../../../frameworks/native/rdb/src/connection.cpp", - "../../../frameworks/native/rdb/src/connection_pool.cpp", - "../../../frameworks/native/rdb/src/grd_api_manager.cpp", - "../../../frameworks/native/rdb/src/raw_data_parser.cpp", - "../../../frameworks/native/rdb/src/rd_connection.cpp", - "../../../frameworks/native/rdb/src/rd_statement.cpp", - "../../../frameworks/native/rdb/src/rd_utils.cpp", - "../../../frameworks/native/rdb/src/rdb_local_db_observer.cpp", - "../../../frameworks/native/rdb/src/rdb_manager_impl.cpp", - "../../../frameworks/native/rdb/src/rdb_notifier_stub.cpp", - "../../../frameworks/native/rdb/src/rdb_security_manager.cpp", - "../../../frameworks/native/rdb/src/rdb_service_proxy.cpp", - "../../../frameworks/native/rdb/src/rdb_sql_statistic.cpp", - "../../../frameworks/native/rdb/src/result_set_proxy.cpp", - "../../../frameworks/native/rdb/src/share_block.cpp", - "../../../frameworks/native/rdb/src/shared_block_serializer_info.cpp", - "../../../frameworks/native/rdb/src/sqlite_connection.cpp", - "../../../frameworks/native/rdb/src/sqlite_default_function.cpp", - "../../../frameworks/native/rdb/src/sqlite_global_config.cpp", - "../../../frameworks/native/rdb/src/sqlite_shared_result_set.cpp", - "../../../frameworks/native/rdb/src/sqlite_sql_builder.cpp", - "../../../frameworks/native/rdb/src/sqlite_statement.cpp", - "../../../frameworks/native/rdb/src/sqlite_utils.cpp", - "../../../frameworks/native/rdb/src/step_result_set.cpp", - "../../../frameworks/native/rdb/src/string_utils.cpp", - "../../../frameworks/native/rdb/src/task_executor.cpp", - "../../../frameworks/native/rdb/src/trans_db.cpp", + "${relational_store_native_path}/appdatafwk/src/serializable.cpp", + "${relational_store_native_path}/appdatafwk/src/general_endian.cpp", + "${relational_store_native_path}/appdatafwk/src/shared_block.cpp", + "${relational_store_native_path}/dfx/src/rdb_radar_reporter.cpp", + "${relational_store_native_path}/dfx/src/rdb_stat_reporter.cpp", + "${relational_store_native_path}/rdb/src/delay_notify.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_impl.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_fault_hiview_reporter.cpp", + "${relational_store_native_path}/rdb/src/base_transaction.cpp", + "${relational_store_native_path}/rdb/src/connection.cpp", + "${relational_store_native_path}/rdb/src/connection_pool.cpp", + "${relational_store_native_path}/rdb/src/grd_api_manager.cpp", + "${relational_store_native_path}/rdb/src/global_resource.cpp", + "${relational_store_native_path}/rdb/src/knowledge_schema_helper.cpp", + "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", + "${relational_store_native_path}/rdb/src/rd_connection.cpp", + "${relational_store_native_path}/rdb/src/rd_statement.cpp", + "${relational_store_native_path}/rdb/src/rd_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_icu_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_local_db_observer.cpp", + "${relational_store_native_path}/rdb/src/rdb_manager_impl.cpp", + "${relational_store_native_path}/rdb/src/rdb_notifier_stub.cpp", + "${relational_store_native_path}/rdb/src/rdb_obs_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_perfStat.cpp", + "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_service_proxy.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_log.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_statistic.cpp", + "${relational_store_native_path}/rdb/src/rdb_time_utils.cpp", + "${relational_store_native_path}/rdb/src/result_set_proxy.cpp", + "${relational_store_native_path}/rdb/src/security_policy.cpp", + "${relational_store_native_path}/rdb/src/share_block.cpp", + "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", + "${relational_store_native_path}/rdb/src/sqlite_connection.cpp", + "${relational_store_native_path}/rdb/src/sqlite_default_function.cpp", + "${relational_store_native_path}/rdb/src/sqlite_global_config.cpp", + "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/sqlite_sql_builder.cpp", + "${relational_store_native_path}/rdb/src/sqlite_statement.cpp", + "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", + "${relational_store_native_path}/rdb/src/step_result_set.cpp", + "${relational_store_native_path}/rdb/src/string_utils.cpp", + "${relational_store_native_path}/rdb/src/suspender.cpp", + "${relational_store_native_path}/rdb/src/task_executor.cpp", + "${relational_store_native_path}/rdb/src/trans_db.cpp", ] configs = [ ":module_private_config" ] @@ -188,20 +257,160 @@ ohos_unittest("NativeRdbTest") { external_deps = [ "ability_base:zuri", "ability_runtime:dataobs_manager", + "json:nlohmann_json_static", "c_utils:utils", + "file_api:securitylabel", + "googletest:gtest_main", "hilog:libhilog", - "huks:libhukssdk", + "hisysevent:libhisysevent", "ipc:ipc_core", + "kv_store:datamgr_common", "kv_store:distributeddata_inner", "kv_store:distributeddb", + "kv_store:distributeddb_client", "samgr:samgr_proxy", + "sqlite:sqlite", ] - deps = [ - "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", - "//third_party/sqlite:sqlite", + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] +} + +ohos_unittest("NativeRdbSecurityManagerTest") { + module_out_path = module_output_path + + cflags = [ + "-fno-access-control", # Ignore Private Member Access Control ] + + include_dirs = [ + "${relational_store_native_path}/obs_mgr_adapter", + "${relational_store_native_path}/icu/include", + ] + + sources = [ + "unittest/rdb_encrypt_upgrade_test.cpp", + ] + + sources += [ + "${relational_store_native_path}/appdatafwk/src/serializable.cpp", + "${relational_store_native_path}/appdatafwk/src/general_endian.cpp", + "${relational_store_native_path}/appdatafwk/src/shared_block.cpp", + "${relational_store_native_path}/dfx/src/rdb_radar_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_fault_hiview_reporter.cpp", + "${relational_store_native_path}/dfx/src/rdb_stat_reporter.cpp", + "${relational_store_native_path}/obs_mgr_adapter/obs_mgr_adapter.cpp", + "${relational_store_native_path}/rdb/src/abs_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_result_set.cpp", + "${relational_store_native_path}/rdb/src/abs_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/base_transaction.cpp", + "${relational_store_native_path}/rdb/src/big_integer.cpp", + "${relational_store_native_path}/rdb/src/cache_result_set.cpp", + "${relational_store_native_path}/rdb/src/connection.cpp", + "${relational_store_native_path}/rdb/src/connection_pool.cpp", + "${relational_store_native_path}/rdb/src/delay_notify.cpp", + "${relational_store_native_path}/rdb/src/grd_api_manager.cpp", + "${relational_store_native_path}/rdb/src/global_resource.cpp", + "${relational_store_native_path}/rdb/src/knowledge_schema_helper.cpp", + "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", + "${relational_store_native_path}/rdb/src/rd_connection.cpp", + "${relational_store_native_path}/rdb/src/rd_statement.cpp", + "${relational_store_native_path}/rdb/src/rd_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_icu_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_helper.cpp", + "${relational_store_native_path}/rdb/src/rdb_local_db_observer.cpp", + "${relational_store_native_path}/rdb/src/rdb_manager_impl.cpp", + "${relational_store_native_path}/rdb/src/rdb_notifier_stub.cpp", + "${relational_store_native_path}/rdb/src/rdb_obs_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_perfStat.cpp", + "${relational_store_native_path}/rdb/src/rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_service_proxy.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_log.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_statistic.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_store.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_impl.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_time_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_types_util.cpp", + "${relational_store_native_path}/rdb/src/result_set_proxy.cpp", + "${relational_store_native_path}/rdb/src/security_policy.cpp", + "${relational_store_native_path}/rdb/src/share_block.cpp", + "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", + "${relational_store_native_path}/rdb/src/sqlite_connection.cpp", + "${relational_store_native_path}/rdb/src/sqlite_default_function.cpp", + "${relational_store_native_path}/rdb/src/sqlite_global_config.cpp", + "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/sqlite_sql_builder.cpp", + "${relational_store_native_path}/rdb/src/sqlite_statement.cpp", + "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", + "${relational_store_native_path}/rdb/src/step_result_set.cpp", + "${relational_store_native_path}/rdb/src/string_utils.cpp", + "${relational_store_native_path}/rdb/src/suspender.cpp", + "${relational_store_native_path}/rdb/src/task_executor.cpp", + "${relational_store_native_path}/rdb/src/trans_db.cpp", + "${relational_store_native_path}/rdb/src/transaction.cpp", + "${relational_store_native_path}/rdb/src/transaction_impl.cpp", + "${relational_store_native_path}/rdb/src/value_object.cpp", + "${relational_store_native_path}/rdb/src/values_bucket.cpp", + "${relational_store_native_path}/rdb/src/values_buckets.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "json:nlohmann_json_static", + "c_utils:utils", + "file_api:securitylabel", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "huks:libhukssdk", + "ipc:ipc_core", + "kv_store:database_utils", + "kv_store:datamgr_common", + "kv_store:distributeddata_inner", + "kv_store:distributeddb_client", + "samgr:samgr_proxy", + "sqlite:sqlite", + ] +} + +ohos_unittest("DelayActuatorTest") { + module_out_path = module_output_path + + sources = [ + "unittest/delay_actuator_test.cpp", + ] + include_dirs = [ + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_base_path}/test/native/rdb/unittest", + ] + + defines = [ "RELATIONAL_STORE" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "googletest:gtest", + "googletest:gtest_main", + "hilog:libhilog", + "huks:libhukssdk", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] } ############################################################################### @@ -209,9 +418,12 @@ group("unittest") { testonly = true deps = [ + ":DelayActuatorTest", + ":NativeRdbLogTest", ":NativeRdbMultiProcessTest", ":NativeRdbMultiThreadTest", ":NativeRdbTest", + ":NativeRdbSecurityManagerTest", ] } @@ -221,10 +433,36 @@ group("fuzztest") { testonly = true deps = [] deps += [ + "fuzztest/rdbhelper_fuzzer:fuzztest", "fuzztest/rdbimpl_fuzzer:fuzztest", "fuzztest/rdbrdutils_fuzzer:fuzztest", "fuzztest/rdbstore_fuzzer:fuzztest", "fuzztest/rdstatement_fuzzer:fuzztest", + "fuzztest/returning_fuzzer:fuzztest", + "fuzztest/sharedblock_fuzzer:fuzztest", + "fuzztest/transdb_fuzzer:fuzztest", + "fuzztest/transaction_fuzzer:fuzztest", + "fuzztest/big_integer_test_ut2fuzz:fuzztest", + "fuzztest/cache_result_set_test_ut2fuzz:fuzztest", + "fuzztest/cloud_data_test_ut2fuzz:fuzztest", + "fuzztest/connection_test_ut2fuzz:fuzztest", + "fuzztest/rdb_attach_test_ut2fuzz:fuzztest", + "fuzztest/rdb_bigint_test_ut2fuzz:fuzztest", + "fuzztest/rdb_callback_icu_test_ut2fuzz:fuzztest", + "fuzztest/rdb_corrupt_test_ut2fuzz:fuzztest", + "fuzztest/rdb_delete_test_ut2fuzz:fuzztest", + "fuzztest/rdb_distributed_test_ut2fuzz:fuzztest", + "fuzztest/rdb_double_write_test_ut2fuzz:fuzztest", + "fuzztest/rdbsqlutils_fuzzer:fuzztest", + "fuzztest/storeconfig_fuzzer:fuzztest", + "fuzztest/absrdbpredicates_fuzzer:fuzztest", + "fuzztest/abssharedresultset_fuzzer:fuzztest", + "fuzztest/abspredicates_fuzzer:fuzztest", + "fuzztest/absresultset_fuzzer:fuzztest", + "fuzztest/rdbpredicates_fuzzer:fuzztest", + "fuzztest/valueobject_fuzzer:fuzztest", + "fuzztest/valuesbucket_fuzzer:fuzztest", + "fuzztest/valuesbuckets_fuzzer:fuzztest", ] } diff --git a/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/BUILD.gn b/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/BUILD.gn index 39778e1a1cbc7abeae09e2778bd2c03a99b94a2e..307ff2d630eb6946c9da8491f3d11a79e34d8065 100644 --- a/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/BUILD.gn +++ b/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/BUILD.gn @@ -20,20 +20,12 @@ config("module_private_config") { visibility = [ ":*" ] include_dirs = [ + "${relational_store_common_path}/include", "${relational_store_native_path}/rdb/include", "${relational_store_innerapi_path}/rdb/include", "${relational_store_native_path}/rdb/src", "${relational_store_innerapi_path}/appdatafwk/include", - "//commonlibrary/c_utils/base/include", - "${common_tool_path}/", ] - - if (relational_store_rdb_support_icu) { - include_dirs += [ - "//third_party/icu/icu4c/source/i18n", - "//third_party/icu/icu4c/source/common", - ] - } } ohos_distributedtest("DistributedTest") { @@ -48,18 +40,23 @@ ohos_distributedtest("DistributedTest") { "ability_runtime:dataobs_manager", "c_utils:utils", "device_manager:devicemanagersdk", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:datamgr_common", "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", ] - deps = [ - "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", - "//third_party/icu/icu4c:shared_icui18n", - "//third_party/icu/icu4c:shared_icuuc", - "//third_party/sqlite:sqlite", - ] + if (relational_store_rdb_support_icu) { + external_deps += [ + "icu:shared_icui18n", + "icu:shared_icuuc", + ] + } + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] } ohos_distributedtest("DistributedTestAgent") { @@ -72,18 +69,23 @@ ohos_distributedtest("DistributedTestAgent") { "ability_runtime:dataobs_manager", "c_utils:utils", "device_manager:devicemanagersdk", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:datamgr_common", "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", ] - deps = [ - "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", - "//third_party/icu/icu4c:shared_icui18n", - "//third_party/icu/icu4c:shared_icuuc", - "//third_party/sqlite:sqlite", - ] + if (relational_store_rdb_support_icu) { + external_deps += [ + "icu:shared_icui18n", + "icu:shared_icuuc", + ] + } + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] } ############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..13ca94210afe8514733ba20d21c2bc147d082200 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/BUILD.gn @@ -0,0 +1,64 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("abspredicates_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/abspredicates_fuzzer" + + sources = [ "abspredicates_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":abspredicates_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/abspredicates_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/abspredicates_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..50a95e4c430a9f36e6e4bcc238b4111c49c51fd7 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/abspredicates_fuzzer.cpp @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2025 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 "abspredicates_fuzzer.h" + +#include + +#include +#include + +#include "abs_shared_result_set.h" +#include "ashmem.h" +#include "rd_statement.h" +#include "rdb_errno.h" +#include "rdb_store_config.h" +#include "rdb_store_impl.h" +#include "rdb_types.h" +#include "refbase.h" +#include "shared_block.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +// Define constants +#define MAX_STRING_LENGTH 50 +#define MAX_VECTOR_SIZE 10 + +namespace OHOS { + +std::vector ConsumeRandomLengthValueObjectVector(FuzzedDataProvider &provider) +{ + const int loopsMin = 0; + const int loopsMax = 100; + size_t loops = provider.ConsumeIntegralInRange(loopsMin, loopsMax); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t value = provider.ConsumeIntegral(); + ValueObject obj(value); + columns.emplace_back(obj); + } + return columns; +} + +std::vector ConsumeRandomLengthStringVector(FuzzedDataProvider &provider) +{ + const int loopsMin = 0; + const int loopsMax = 100; + size_t loops = provider.ConsumeIntegralInRange(loopsMin, loopsMax); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t length = provider.ConsumeIntegral(); + auto bytes = provider.ConsumeBytes(length); + columns.emplace_back(bytes.begin(), bytes.end()); + } + return columns; +} + +void TestSetWhereClause(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string whereClause = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.SetWhereClause(whereClause); +} + +void TestSetBindArgs(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::vector valueObjects = ConsumeRandomLengthValueObjectVector(provider); + predicates.SetBindArgs(valueObjects); +} + +void TestSetOrder(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string order = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.SetOrder(order); +} + +void TestLimit(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + int limit = provider.ConsumeIntegral(); + predicates.Limit(limit); +} + +void TestLimitWithOffset(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + int offset = provider.ConsumeIntegral(); + int limit = provider.ConsumeIntegral(); + predicates.Limit(offset, limit); +} + +void TestOffset(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + int offset = provider.ConsumeIntegral(); + predicates.Offset(offset); +} + +void TestGroupBy(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::vector fields = ConsumeRandomLengthStringVector(provider); + predicates.GroupBy(fields); +} + +void TestIndexedBy(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string indexName = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.IndexedBy(indexName); +} + +void TestHaving(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string conditions = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::vector valueObjects = ConsumeRandomLengthValueObjectVector(provider); + predicates.Having(conditions, valueObjects); +} + +void TestIn(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::vector valueObjects = ConsumeRandomLengthValueObjectVector(provider); + predicates.In(field, valueObjects); +} + +void TestNotIn(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::vector valueObjects = ConsumeRandomLengthValueObjectVector(provider); + predicates.NotIn(field, valueObjects); +} + +void TestBetween(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + int32_t value1 = provider.ConsumeIntegral(); + ValueObject obj1(value1); + int32_t value2 = provider.ConsumeIntegral(); + ValueObject obj2(value2); + predicates.Between(field, obj1, obj2); +} + +void TestNotBetween(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + int32_t value1 = provider.ConsumeIntegral(); + ValueObject obj1(value1); + int32_t value2 = provider.ConsumeIntegral(); + ValueObject obj2(value2); + predicates.NotBetween(field, obj1, obj2); +} + +void TestGreaterThan(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + ValueObject valueObject = provider.ConsumeIntegral(); + predicates.GreaterThan(field, valueObject); +} + +void TestLessThan(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + ValueObject valueObject = provider.ConsumeIntegral(); + predicates.LessThan(field, valueObject); +} + +void TestGreaterThanOrEqualTo(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + ValueObject valueObject = provider.ConsumeIntegral(); + predicates.GreaterThanOrEqualTo(field, valueObject); +} + +void TestLessThanOrEqualTo(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + ValueObject valueObject = provider.ConsumeIntegral(); + predicates.LessThanOrEqualTo(field, valueObject); +} + +void TestOrderByAsc(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.OrderByAsc(field); +} + +void TestOrderByDesc(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.OrderByDesc(field); +} + +void TestEqualTo(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + ValueObject valueObject = provider.ConsumeIntegral(); + predicates.EqualTo(field, valueObject); +} + +void TestNotEqualTo(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + ValueObject valueObject = provider.ConsumeIntegral(); + predicates.NotEqualTo(field, valueObject); +} + +void TestContains(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.Contains(field, value); +} + +void TestNotContains(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.NotContains(field, value); +} + +void TestBeginsWith(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.BeginsWith(field, value); +} + +void TestEndsWith(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.EndsWith(field, value); +} + +void TestIsNull(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.IsNull(field); +} + +void TestIsNotNull(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.IsNotNull(field); +} + +void TestLike(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.Like(field, value); +} + +void TestNotLike(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.NotLike(field, value); +} + +void TestGlob(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.Glob(field, value); +} + +void TestNotGlob(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.NotGlob(field, value); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::NativeRdb::AbsPredicates predicates; + + // Call test functions + OHOS::TestSetWhereClause(provider, predicates); + OHOS::TestSetBindArgs(provider, predicates); + OHOS::TestSetOrder(provider, predicates); + OHOS::TestLimit(provider, predicates); + OHOS::TestLimitWithOffset(provider, predicates); + OHOS::TestOffset(provider, predicates); + OHOS::TestGroupBy(provider, predicates); + OHOS::TestIndexedBy(provider, predicates); + OHOS::TestHaving(provider, predicates); + OHOS::TestIn(provider, predicates); + OHOS::TestNotIn(provider, predicates); + OHOS::TestBetween(provider, predicates); + OHOS::TestNotBetween(provider, predicates); + OHOS::TestGreaterThan(provider, predicates); + OHOS::TestLessThan(provider, predicates); + OHOS::TestGreaterThanOrEqualTo(provider, predicates); + OHOS::TestLessThanOrEqualTo(provider, predicates); + OHOS::TestOrderByAsc(provider, predicates); + OHOS::TestOrderByDesc(provider, predicates); + OHOS::TestEqualTo(provider, predicates); + OHOS::TestNotEqualTo(provider, predicates); + OHOS::TestContains(provider, predicates); + OHOS::TestNotContains(provider, predicates); + OHOS::TestBeginsWith(provider, predicates); + OHOS::TestEndsWith(provider, predicates); + OHOS::TestIsNull(provider, predicates); + OHOS::TestIsNotNull(provider, predicates); + OHOS::TestLike(provider, predicates); + OHOS::TestNotLike(provider, predicates); + OHOS::TestGlob(provider, predicates); + OHOS::TestNotGlob(provider, predicates); + + return 0; +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/abspredicates_fuzzer.h b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/abspredicates_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..6f52f567951340ef36bc576fbc7d43be5f328f45 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/abspredicates_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 ABSPREDICATES_FUZZER_H +#define ABSPREDICATES_FUZZER_H + +#define FUZZ_PROJECT_NAME "abspredicates_fuzzer" + +#endif // ABSPREDICATES_FUZZER_H diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/corpus/init similarity index 92% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/corpus/init rename to relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/corpus/init index bc977bd9738ee9a70b362067f57a9c63d3adb801..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/corpus/init +++ b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/corpus/init @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2025 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 diff --git a/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..7dece9a55680bfd12916c67172c5ab7f6c1c958c --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("absrdbpredicates_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/absrdbpredicates_fuzzer" + + sources = [ "absrdbpredicates_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":absrdbpredicates_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/absrdbpredicates_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/absrdbpredicates_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..989633b1aa724cbbc2f7f6aac4787ced7d85b9d9 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/absrdbpredicates_fuzzer.cpp @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2025 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 +#include + +#include "abs_rdb_predicates.h" +#include "rdb_types.h" + + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +static const int FOR_LOOP_MIN = 0; +static const int FOR_LOOP_MAX = 10; +static const int RANDOM_STRING_LENGTH = 30; + +namespace OHOS { +void FuzzInDevices(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::vector devices; + size_t numDevices = provider.ConsumeIntegralInRange(FOR_LOOP_MIN, FOR_LOOP_MAX); + for (size_t i = 0; i < numDevices; ++i) { + devices.push_back(provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH)); + } + predicates.InDevices(devices); +} + +void FuzzEqualTo(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + ValueObject value(provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH)); + predicates.EqualTo(field, value); +} + +void FuzzNotEqualTo(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + ValueObject value(provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH)); + predicates.NotEqualTo(field, value); +} + +void FuzzInStringVector(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::vector values; + size_t numValues = provider.ConsumeIntegralInRange(FOR_LOOP_MIN, FOR_LOOP_MAX); + for (size_t i = 0; i < numValues; ++i) { + values.push_back(provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH)); + } + predicates.In(field, values); +} + +void FuzzInValueObjectVector(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::vector values; + size_t numValues = provider.ConsumeIntegralInRange(FOR_LOOP_MIN, FOR_LOOP_MAX); + for (size_t i = 0; i < numValues; ++i) { + ValueObject value(provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH)); + values.push_back(value); + } + predicates.In(field, values); +} + +void FuzzContains(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.Contains(field, value); +} + +void FuzzNotContains(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.NotContains(field, value); +} + +void FuzzBeginsWith(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.BeginsWith(field, value); +} + +void FuzzEndsWith(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.EndsWith(field, value); +} + +void FuzzLike(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.Like(field, value); +} + +void FuzzNotLike(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.NotLike(field, value); +} + +void FuzzGlob(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.Glob(field, value); +} + +void FuzzNotGlob(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.NotGlob(field, value); +} + +void FuzzNotInStringVector(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::vector values; + size_t numValues = provider.ConsumeIntegralInRange(FOR_LOOP_MIN, FOR_LOOP_MAX); + for (size_t i = 0; i < numValues; ++i) { + values.push_back(provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH)); + } + predicates.NotIn(field, values); +} + +void FuzzNotInValueObjectVector(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::vector values; + size_t numValues = provider.ConsumeIntegralInRange(FOR_LOOP_MIN, FOR_LOOP_MAX); + for (size_t i = 0; i < numValues; ++i) { + ValueObject value(provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH)); + values.push_back(value); + } + predicates.NotIn(field, values); +} + +void FuzzOrderByAsc(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.OrderByAsc(field); +} + +void FuzzOrderByDesc(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.OrderByDesc(field); +} + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + + // Create an instance of AbsRdbPredicates + std::string tableName = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + AbsRdbPredicates predicates(tableName); + + // Fuzzing for InDevices + OHOS::FuzzInDevices(provider, predicates); + + // Fuzzing for EqualTo + OHOS::FuzzEqualTo(provider, predicates); + + // Fuzzing for NotEqualTo + OHOS::FuzzNotEqualTo(provider, predicates); + + // Fuzzing for In (string vector) + OHOS::FuzzInStringVector(provider, predicates); + + // Fuzzing for In (ValueObject vector) + OHOS::FuzzInValueObjectVector(provider, predicates); + + // Fuzzing for Contains + OHOS::FuzzContains(provider, predicates); + + // Fuzzing for NotContains + OHOS::FuzzNotContains(provider, predicates); + + // Fuzzing for BeginsWith + OHOS::FuzzBeginsWith(provider, predicates); + + // Fuzzing for EndsWith + OHOS::FuzzEndsWith(provider, predicates); + + // Fuzzing for Like + OHOS::FuzzLike(provider, predicates); + + // Fuzzing for NotLike + OHOS::FuzzNotLike(provider, predicates); + + // Fuzzing for Glob + OHOS::FuzzGlob(provider, predicates); + + // Fuzzing for NotGlob + OHOS::FuzzNotGlob(provider, predicates); + + // Fuzzing for NotIn (string vector) + OHOS::FuzzNotInStringVector(provider, predicates); + + // Fuzzing for NotIn (ValueObject vector) + OHOS::FuzzNotInValueObjectVector(provider, predicates); + + // Fuzzing for OrderByAsc + OHOS::FuzzOrderByAsc(provider, predicates); + + // Fuzzing for OrderByDesc + OHOS::FuzzOrderByDesc(provider, predicates); + + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/absrdbpredicates_fuzzer.h b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/absrdbpredicates_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..51c074ec6740bf173a035d58fd131e0df0d40f4c --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/absrdbpredicates_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 ABSRDBPREDICATES_FUZZER_H +#define ABSRDBPREDICATES_FUZZER_H + +#define FUZZ_PROJECT_NAME "absrdbpredicates_fuzzer" + +#endif // ABSRDBPREDICATES_FUZZER_H diff --git a/kv_store/test/fuzztest/jsonservice_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/corpus/init similarity index 92% rename from kv_store/test/fuzztest/jsonservice_fuzzer/corpus/init rename to relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/corpus/init index e7c3fecd8d4d4816e40088113a2316bb9eb2e13f..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 100644 --- a/kv_store/test/fuzztest/jsonservice_fuzzer/corpus/init +++ b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/corpus/init @@ -1,4 +1,4 @@ -# Copyright (c) 2024 Huawei Device Co., Ltd. +# Copyright (c) 2025 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 diff --git a/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..b3101f01cb47f78a75d8f03a63ab4490868a2708 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("absresultset_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/absresultset_fuzzer" + + sources = [ "absresultset_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":absresultset_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/absresultset_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/absresultset_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d3d48248af05e1776acd47e61c5ee4f6c08e98d4 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/absresultset_fuzzer.cpp @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2025 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 "absresultset_fuzzer.h" + +#include + +#include +#include +#include +#include "abs_result_set.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + +// Define constants +#define MAX_STRING_LENGTH 50 +#define MAX_VECTOR_SIZE 10 + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +namespace OHOS { + +static const std::string RDB_PATH = "/data/test/absresultsetFuzzerTest.db"; +static const std::string CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, " + "blobType BLOB)"; + +class AbsresultsetFuzzerTestCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +int AbsresultsetFuzzerTestCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_TEST); +} + +int AbsresultsetFuzzerTestCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +std::vector ConsumeRandomLengthValueObjectVector(FuzzedDataProvider &provider) +{ + const int loopsMin = 0; + const int loopsMax = 100; + size_t loops = provider.ConsumeIntegralInRange(loopsMin, loopsMax); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t value = provider.ConsumeIntegral(); + ValueObject obj(value); + columns.emplace_back(obj); + } + return columns; +} + +std::vector ConsumeRandomLengthStringVector(FuzzedDataProvider &provider) +{ + const int loopsMin = 0; + const int loopsMax = 100; + size_t loops = provider.ConsumeIntegralInRange(loopsMin, loopsMax); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t length = provider.ConsumeIntegral(); + auto bytes = provider.ConsumeBytes(length); + columns.emplace_back(bytes.begin(), bytes.end()); + } + return columns; +} + +void TestGetBlob(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + std::vector blob; + resultSet->GetBlob(columnIndex, blob); +} + +void TestGetString(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + std::string value; + resultSet->GetString(columnIndex, value); +} + +void TestGetInt(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + int value; + resultSet->GetInt(columnIndex, value); +} + +void TestGetLong(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + int64_t value; + resultSet->GetLong(columnIndex, value); +} + +void TestGetDouble(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + double value; + resultSet->GetDouble(columnIndex, value); +} + +void TestGetAsset(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int32_t columnIndex = provider.ConsumeIntegral(); + ValueObject::Asset value; + resultSet->GetAsset(columnIndex, value); +} + +void TestGetAssets(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int32_t columnIndex = provider.ConsumeIntegral(); + ValueObject::Assets value; + resultSet->GetAssets(columnIndex, value); +} + +void TestGetFloat32Array(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int32_t columnIndex = provider.ConsumeIntegral(); + ValueObject::FloatVector value; + resultSet->GetFloat32Array(columnIndex, value); +} + +void TestIsColumnNull(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + bool isNull; + resultSet->IsColumnNull(columnIndex, isNull); +} + +void TestGetRow(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + RowEntity rowEntity; + resultSet->GetRow(rowEntity); +} + +void TestGoToRow(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int position = provider.ConsumeIntegral(); + resultSet->GoToRow(position); +} + +void TestGetColumnType(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + ColumnType columnType; + resultSet->GetColumnType(columnIndex, columnType); +} + +void TestGetRowIndex(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int position; + resultSet->GetRowIndex(position); +} + +void TestGoTo(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int offset = provider.ConsumeIntegral(); + resultSet->GoTo(offset); +} + +void TestGoToFirstRow(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + resultSet->GoToFirstRow(); +} + +void TestGoToLastRow(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + resultSet->GoToLastRow(); +} + +void TestGoToNextRow(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + resultSet->GoToNextRow(); +} + +void TestGoToPreviousRow(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + resultSet->GoToPreviousRow(); +} + +void TestIsAtFirstRow(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + bool result; + resultSet->IsAtFirstRow(result); +} + +void TestIsAtLastRow(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + bool result; + resultSet->IsAtLastRow(result); +} + +void TestIsStarted(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + bool result; + resultSet->IsStarted(result); +} + +void TestIsEnded(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + bool result; + resultSet->IsEnded(result); +} + +void TestGetColumnCount(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int count; + resultSet->GetColumnCount(count); +} + +void TestGetColumnIndex(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + std::string columnName = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + int columnIndex; + resultSet->GetColumnIndex(columnName, columnIndex); +} + +void TestGetColumnName(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + std::string columnName; + resultSet->GetColumnName(columnIndex, columnName); +} + +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + RdbHelper::DeleteRdbStore(RDB_PATH); + RdbStoreConfig config(RDB_PATH); + config.SetHaMode(HAMode::MAIN_REPLICA); + config.SetReadOnly(false); + AbsresultsetFuzzerTestCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + if (store == nullptr || errCode != E_OK) { + return 0; + } + std::vector selectionArgs; + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test", selectionArgs); + if (resultSet == nullptr) { + return 0; + } + + // Call test functions + OHOS::TestGetBlob(provider, resultSet); + OHOS::TestGetString(provider, resultSet); + OHOS::TestGetInt(provider, resultSet); + OHOS::TestGetLong(provider, resultSet); + OHOS::TestGetDouble(provider, resultSet); + OHOS::TestGetAsset(provider, resultSet); + OHOS::TestGetAssets(provider, resultSet); + OHOS::TestGetFloat32Array(provider, resultSet); + OHOS::TestIsColumnNull(provider, resultSet); + OHOS::TestGetRow(provider, resultSet); + OHOS::TestGoToRow(provider, resultSet); + OHOS::TestGetColumnType(provider, resultSet); + OHOS::TestGetRowIndex(provider, resultSet); + OHOS::TestGoTo(provider, resultSet); + OHOS::TestGoToFirstRow(provider, resultSet); + OHOS::TestGoToLastRow(provider, resultSet); + OHOS::TestGoToNextRow(provider, resultSet); + OHOS::TestGoToPreviousRow(provider, resultSet); + OHOS::TestIsAtFirstRow(provider, resultSet); + OHOS::TestIsAtLastRow(provider, resultSet); + OHOS::TestIsStarted(provider, resultSet); + OHOS::TestIsEnded(provider, resultSet); + OHOS::TestGetColumnCount(provider, resultSet); + OHOS::TestGetColumnIndex(provider, resultSet); + OHOS::TestGetColumnName(provider, resultSet); + return 0; +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/absresultset_fuzzer.h b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/absresultset_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..36cea0eee5e241132599cf3474f6161876e45723 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/absresultset_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 ABSRESULTSET_FUZZER_H +#define ABSRESULTSET_FUZZER_H + +#define FUZZ_PROJECT_NAME "absresultset_fuzzer" + +#endif // ABSRESULTSET_FUZZER_H diff --git a/kv_store/test/fuzztest/kvsync_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/corpus/init similarity index 92% rename from kv_store/test/fuzztest/kvsync_fuzzer/corpus/init rename to relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/corpus/init index e4ceac1bcd4e3b3427eb63cea0c28304064333cc..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 100644 --- a/kv_store/test/fuzztest/kvsync_fuzzer/corpus/init +++ b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/corpus/init @@ -1,4 +1,4 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. +# Copyright (c) 2025 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 diff --git a/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..1ee817aef201eb9a608b60d98f7a7a8fba837ddf --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("abssharedresultset_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/abssharedresultset_fuzzer" + + sources = [ "abssharedresultset_fuzzer.cpp" ] + + deps = [ + "${relational_store_innerapi_path}/rdb:native_rdb", + "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":abssharedresultset_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/abssharedresultset_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/abssharedresultset_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fd89cf563a2a7f7945441395af9f49d12abb682e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/abssharedresultset_fuzzer.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2025 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 "abssharedresultset_fuzzer.h" + +#include + +#include +#include + +#include "abs_shared_result_set.h" +#include "rdb_types.h" +#include "ashmem.h" +#include "rd_statement.h" +#include "rdb_errno.h" +#include "rdb_store_config.h" +#include "rdb_store_impl.h" +#include "refbase.h" +#include "shared_block.h" + + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +static const size_t DEFAULT_BLOCK_SIZE = 1 * 1024 * 1024; + +namespace OHOS { +void FuzzGetString(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + std::string value; + resultSet.GetString(columnIndex, value); +} + +void FuzzGet(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + int32_t columnIndex = provider.ConsumeIntegral(); + ValueObject value; + resultSet.Get(columnIndex, value); +} + +void FuzzGetSize(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + size_t size; + resultSet.GetSize(columnIndex, size); +} + +void FuzzGetColumnType(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + ColumnType columnType; + resultSet.GetColumnType(columnIndex, columnType); +} + +void FuzzGoToRow(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + int position = provider.ConsumeIntegral(); + resultSet.GoToRow(position); +} + +void FuzzGetRowCount(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + int count; + resultSet.GetRowCount(count); +} + +void FuzzGetBlock(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + resultSet.GetBlock(); +} + +void FuzzOnGo(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + int oldRowIndex = provider.ConsumeIntegral(); + int newRowIndex = provider.ConsumeIntegral(); + resultSet.OnGo(oldRowIndex, newRowIndex); +} + +void FuzzSetBlock(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + AppDataFwk::SharedBlock *block = nullptr; + std::string sharedBlockName = "SharedBlockFuzzTestBlock"; + auto errcode = AppDataFwk::SharedBlock::Create(sharedBlockName, DEFAULT_BLOCK_SIZE, block); + if (errcode != AppDataFwk::SharedBlock::SHARED_BLOCK_OK) { + return; + } + resultSet.SetBlock(block); +} + +void FuzzClose(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + resultSet.Close(); +} + +void FuzzHasBlock(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + resultSet.HasBlock(); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + + // Create an instance of AbsSharedResultSet + const int randomStringLength = 30; + std::string tableName = provider.ConsumeRandomLengthString(randomStringLength); + AbsSharedResultSet resultSet(tableName); + + // Fuzzing for GetString + OHOS::FuzzGetString(provider, resultSet); + + // Fuzzing for Get + OHOS::FuzzGet(provider, resultSet); + + // Fuzzing for GetSize + OHOS::FuzzGetSize(provider, resultSet); + + // Fuzzing for GetColumnType + OHOS::FuzzGetColumnType(provider, resultSet); + + // Fuzzing for GoToRow + OHOS::FuzzGoToRow(provider, resultSet); + + // Fuzzing for GetRowCount + OHOS::FuzzGetRowCount(provider, resultSet); + + // Fuzzing for GetBlock + OHOS::FuzzGetBlock(provider, resultSet); + + // Fuzzing for OnGo + OHOS::FuzzOnGo(provider, resultSet); + + // Fuzzing for SetBlock + OHOS::FuzzSetBlock(provider, resultSet); + + // Fuzzing for Close + OHOS::FuzzClose(provider, resultSet); + + // Fuzzing for HasBlock + OHOS::FuzzHasBlock(provider, resultSet); + + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/abssharedresultset_fuzzer.h b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/abssharedresultset_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..1d434c8815ce30ad8683b271f17fd643ba238372 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/abssharedresultset_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 ABSSHAREDRESULTSET_FUZZER_H +#define ABSSHAREDRESULTSET_FUZZER_H + +#define FUZZ_PROJECT_NAME "abssharedresultset_fuzzer" + +#endif // ABSSHAREDRESULTSET_FUZZER_H diff --git a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/corpus/init similarity index 92% rename from relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/corpus/init rename to relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/corpus/init index e7c3fecd8d4d4816e40088113a2316bb9eb2e13f..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 100644 --- a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/corpus/init +++ b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/corpus/init @@ -1,4 +1,4 @@ -# Copyright (c) 2024 Huawei Device Co., Ltd. +# Copyright (c) 2025 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 diff --git a/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/BUILD.gn b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3520d8663ebc144665e0201c66a24e43a09f5cba --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("big_integer_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/big_integer_test_ut2fuzz" + + sources = [ "big_integer_test_ut2fuzz.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":big_integer_test_ut2fuzz", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/big_integer_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/big_integer_test_ut2fuzz.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f0bb82e3bfc5214c75fbb30265e226f1c23a789 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/big_integer_test_ut2fuzz.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025 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 "big_integer_test_ut2fuzz.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "big_integer.h" +#include "connection_pool.h" +#include "trans_db.h" + + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +void BigIntegerFuzzTest(FuzzedDataProvider &fdp) +{ + // Test primary constructor with int64_t + auto bi1 = OHOS::NativeRdb::BigInteger(fdp.ConsumeIntegral()); + + // Test (sign, vector) constructor + std::vector vec; + while (fdp.remaining_bytes() >= sizeof(uint64_t)) { + vec.push_back(fdp.ConsumeIntegral()); + } + auto bi2 = OHOS::NativeRdb::BigInteger( + fdp.ConsumeIntegralInRange(-1, 1), + std::move(vec) + ); + + // Validate copy semantics + auto bi3 = OHOS::NativeRdb::BigInteger(bi1); + bi3 = bi2; // Test assignment operator + + // Stress test move semantics + auto bi4 = OHOS::NativeRdb::BigInteger(std::move(bi2)); + bi1 = std::move(bi3); + + // Verify core operations + (void)(bi1 == bi4); // Compare equality + (void)(bi1 < bi4); // Compare ordering + + // Exercise all public methods + (void)bi1.Sign(); // Validate sign retrieval + (void)bi1.Size(); // Check array size + (void)bi1.TrueForm(); // Access raw data + (void)bi1.Value(); // Test value copy +} + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::BigIntegerFuzzTest(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/big_integer_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/big_integer_test_ut2fuzz.h new file mode 100644 index 0000000000000000000000000000000000000000..c424c456667077d280da25fe7c543163a7f1c49f --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/big_integer_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 BIG_INTEGER_TEST_UT2FUZZ_H +#define BIG_INTEGER_TEST_UT2FUZZ_H + +#define FUZZ_PROJECT_NAME "big_integer_test_ut2fuzz" + +#endif // BIG_INTEGER_TEST_UT2FUZZ_H diff --git a/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2aea1356e3c3b3ee6e12ad3f72640897d769d02e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/BUILD.gn b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..8223697504709460a0058a5474947b18956c504b --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("cache_result_set_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz" + + sources = [ "cache_result_set_test_ut2fuzz.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":cache_result_set_test_ut2fuzz", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/cache_result_set_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/cache_result_set_test_ut2fuzz.cpp new file mode 100644 index 0000000000000000000000000000000000000000..47f8792d5025c882e94cc63a05f4e6dc05793ed8 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/cache_result_set_test_ut2fuzz.cpp @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2025 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 "cache_result_set_test_ut2fuzz.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "big_integer.h" +#include "cache_result_set.h" +#include "connection_pool.h" +#include "rdb_errno.h" +#include "trans_db.h" +#include "value_object.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +void CreateValuesBuckets(FuzzedDataProvider &fdp, std::vector &valuesBuckets) +{ + ValuesBucket valuesBucket; + { + std::string columnName = fdp.ConsumeRandomLengthString(); + std::string columnValue = fdp.ConsumeRandomLengthString(); + valuesBucket.PutString(columnName, columnValue); + } + { + std::string columnName = fdp.ConsumeRandomLengthString(); + valuesBucket.PutInt(columnName, fdp.ConsumeIntegral()); + } + { + std::string columnName = fdp.ConsumeRandomLengthString(); + valuesBucket.PutLong(columnName, fdp.ConsumeIntegral()); + } + { + std::string columnName = fdp.ConsumeRandomLengthString(); + double value = fdp.ConsumeFloatingPoint(); + valuesBucket.PutDouble(columnName, value); + } + { + uint32_t status = fdp.ConsumeIntegralInRange( + AssetValue::Status::STATUS_UNKNOWN, AssetValue::Status::STATUS_BUTT); + AssetValue asset{ + .version = fdp.ConsumeIntegral(), + .status = status, + .expiresTime = fdp.ConsumeIntegral(), + .id = fdp.ConsumeRandomLengthString(), + .name = fdp.ConsumeRandomLengthString(), + .uri = fdp.ConsumeRandomLengthString(), + .createTime = fdp.ConsumeRandomLengthString(), + .modifyTime = fdp.ConsumeRandomLengthString(), + .size = fdp.ConsumeRandomLengthString(), + .hash = fdp.ConsumeRandomLengthString(), + .path = fdp.ConsumeRandomLengthString(), + }; + ValueObject valueObject = ValueObject(asset); + ValueObject::Asset value = ValueObject::Asset(valueObject); + std::string columnName = fdp.ConsumeRandomLengthString(); + valuesBucket.Put(columnName, value); + } + valuesBuckets.push_back(std::move(valuesBucket)); +} + +void CacheResultSetTestGetRowCountTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + int count = fdp.ConsumeIntegral(); + cacheResultSet.GetRowCount(count); +} + +void CacheResultSetTestGetAllColumnNamesTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + std::vector columnNamesTmp = {}; + cacheResultSet.GetAllColumnNames(columnNamesTmp); +} + +void CacheResultSetTestGetStringTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + int columnIndex = fdp.ConsumeIntegral(); + std::string value; + cacheResultSet.GetString(columnIndex, value); +} + +void CacheResultSetTestGetIntTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + int columnIndex = fdp.ConsumeIntegral(); + int value = 0; + cacheResultSet.GetInt(columnIndex, value); +} + +void CacheResultSetTestGetLongTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + int columnIndex = fdp.ConsumeIntegral(); + int64_t value = 0; + cacheResultSet.GetLong(columnIndex, value); +} + +void CacheResultSetTestGetDoubleTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + int columnIndex = fdp.ConsumeIntegral(); + double value = 0; + cacheResultSet.GetDouble(columnIndex, value); +} + +void CacheResultSetTestGetAssetTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + int32_t columnIndex = fdp.ConsumeIntegral(); + ValueObject::Asset valueOut = {}; + cacheResultSet.GetAsset(columnIndex, valueOut); +} + +void CacheResultSetTestGetTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + int32_t columnIndex = fdp.ConsumeIntegral(); + ValueObject value; + cacheResultSet.Get(columnIndex, value); + int res = 0; + value.GetInt(res); +} + +void CacheResultSetTestIsColumnNullTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + int32_t columnIndex = fdp.ConsumeIntegral(); + bool isNull = fdp.ConsumeBool(); + cacheResultSet.IsColumnNull(columnIndex, isNull); +} + +void CacheResultSetTestGetRowTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + RowEntity rowEntity; + cacheResultSet.GetRow(rowEntity); +} + +void CacheResultSetTestGoToRowTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + int32_t columnIndex = fdp.ConsumeIntegral(); + cacheResultSet.GoToRow(columnIndex); +} + +void CacheResultSetTestGetColumnTypeTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + int32_t columnIndex = fdp.ConsumeIntegral(); + ColumnType columnType = ColumnType::TYPE_INTEGER; + cacheResultSet.GetColumnType(columnIndex, columnType); +} + +void CacheResultSetTestGetRowIndexTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + int32_t columnIndex = fdp.ConsumeIntegral(); + cacheResultSet.GetRowIndex(columnIndex); +} + +void CacheResultSetTestGoToTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + int32_t offset = fdp.ConsumeIntegral(); + cacheResultSet.GoTo(offset); + std::string value; + cacheResultSet.GetString(fdp.ConsumeIntegral(), value); + cacheResultSet.GoToRow(fdp.ConsumeIntegral()); + cacheResultSet.GetString(fdp.ConsumeIntegral(), value); + cacheResultSet.GoTo(fdp.ConsumeIntegral()); +} + +void CacheResultSetTestGoToFirstRowTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + cacheResultSet.GoToFirstRow(); + int position = fdp.ConsumeIntegral(); + cacheResultSet.GetRowIndex(position); +} + +void CacheResultSetTestGoToLastRowTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + cacheResultSet.GoToLastRow(); + int position = fdp.ConsumeIntegral(); + cacheResultSet.GetRowIndex(position); +} + +void CacheResultSetTestGoToNextRowTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + cacheResultSet.GoToNextRow(); + int position = fdp.ConsumeIntegral(); + cacheResultSet.GetRowIndex(position); +} + +void CacheResultSetTestGoToPreviousRowTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + int offset = fdp.ConsumeIntegral(); + int position = fdp.ConsumeIntegral(); + cacheResultSet.GoToRow(position); + cacheResultSet.GoTo(offset); + cacheResultSet.GoToPreviousRow(); +} + +void CacheResultSetTestIsAtFirstRowTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + bool result = fdp.ConsumeBool(); + cacheResultSet.IsAtFirstRow(result); + cacheResultSet.GoToNextRow(); + cacheResultSet.IsAtLastRow(result); +} + +void CacheResultSetTestIsAtLastRowTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + bool result = fdp.ConsumeBool(); + cacheResultSet.IsAtLastRow(result); + cacheResultSet.GoToNextRow(); + cacheResultSet.IsAtLastRow(result); +} + +void CacheResultSetTestIsStartedTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + bool result = fdp.ConsumeBool(); + cacheResultSet.IsStarted(result); +} + +void CacheResultSetTestIsEndedTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + bool result = fdp.ConsumeBool(); + cacheResultSet.IsEnded(result); +} + +void CacheResultSetTestGetColumnCountTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + int count = fdp.ConsumeIntegral(); + cacheResultSet.GetColumnCount(count); +} + +void CacheResultSetTestGetColumnIndexTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + std::string columnName = fdp.ConsumeRandomLengthString(); + int columnIndex = 0; + cacheResultSet.GetColumnIndex(columnName, columnIndex); +} + +void CacheResultSetTestGetColumnNameTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + std::string columnName; + const int index = 0; + cacheResultSet.GetColumnName(index, columnName); +} + +void CacheResultSetTestGetSizeTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + int32_t columnIndex = fdp.ConsumeIntegral(); + size_t size = 0; + cacheResultSet.GetSize(columnIndex, size); +} + + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::CacheResultSetTestGetRowCountTest001(fdp); + OHOS::CacheResultSetTestGetAllColumnNamesTest001(fdp); + OHOS::CacheResultSetTestGetStringTest001(fdp); + OHOS::CacheResultSetTestGetIntTest001(fdp); + OHOS::CacheResultSetTestGetLongTest001(fdp); + OHOS::CacheResultSetTestGetDoubleTest001(fdp); + OHOS::CacheResultSetTestGetAssetTest001(fdp); + OHOS::CacheResultSetTestGetTest001(fdp); + OHOS::CacheResultSetTestIsColumnNullTest001(fdp); + OHOS::CacheResultSetTestGetRowTest001(fdp); + OHOS::CacheResultSetTestGetColumnTypeTest001(fdp); + OHOS::CacheResultSetTestGetRowIndexTest001(fdp); + OHOS::CacheResultSetTestGoToTest001(fdp); + OHOS::CacheResultSetTestGoToFirstRowTest001(fdp); + OHOS::CacheResultSetTestGoToLastRowTest001(fdp); + OHOS::CacheResultSetTestGoToNextRowTest001(fdp); + OHOS::CacheResultSetTestGoToPreviousRowTest001(fdp); + OHOS::CacheResultSetTestIsAtFirstRowTest001(fdp); + OHOS::CacheResultSetTestIsAtLastRowTest001(fdp); + OHOS::CacheResultSetTestIsStartedTest001(fdp); + OHOS::CacheResultSetTestIsEndedTest001(fdp); + OHOS::CacheResultSetTestGetColumnCountTest001(fdp); + OHOS::CacheResultSetTestGetColumnIndexTest001(fdp); + OHOS::CacheResultSetTestGetColumnNameTest001(fdp); + OHOS::CacheResultSetTestGetSizeTest001(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/cache_result_set_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/cache_result_set_test_ut2fuzz.h new file mode 100644 index 0000000000000000000000000000000000000000..c07d7e7c989a2377485a20e6a3754147cac770b6 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/cache_result_set_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 CACHE_RESULT_SET_TEST_UT2FUZZ_H +#define CACHE_RESULT_SET_TEST_UT2FUZZ_H + +#define FUZZ_PROJECT_NAME "cache_result_set_test_ut2fuzz" + +#endif // CACHE_RESULT_SET_TEST_UT2FUZZ_H diff --git a/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2aea1356e3c3b3ee6e12ad3f72640897d769d02e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/BUILD.gn similarity index 49% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/BUILD.gn rename to relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/BUILD.gn index 718d50aecced404f6d079460538794d983cd3c0a..aad6b95193a3788c7aed16db60533aecabb60552 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/BUILD.gn +++ b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2025 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 @@ -17,27 +17,19 @@ import("//build/test.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") ##############################fuzztest########################################## -ohos_fuzztest("RddbrepairFuzzerTest") { +ohos_fuzztest("cloud_data_test_ut2fuzz") { module_out_path = "relational_store/relational_store" - include_dirs = [ + include_dirs = [ "${relational_store_native_path}/rdb/include", + "${relational_store_base_path}/interfaces/ndk/include", "${relational_store_innerapi_path}/rdb/include", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb/include", - "${common_tool_path}/", - "//third_party/sqlite/include", - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", - "${foundation_systemabilitymgr_path}/safwk/services/safwk/include", - "${foundation_systemabilitymgr_path}/samgr/interfaces/innerkits/samgr_proxy/include", - "${base_security_dataclassification_path}/interfaces/innerkits/datatransmitmgr/include", - "//third_party/json/single_include", - "//third_party/googletest/googletest/include/gtest", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${cloud_data_native_path}/include", + "${relational_store_innerapi_path}/cloud_data/include", + "${relational_store_innerapi_path}/common_type/include", ] cflags = [ @@ -47,22 +39,32 @@ ohos_fuzztest("RddbrepairFuzzerTest") { "-fno-omit-frame-pointer", ] - fuzz_config_file = "${relational_store_base_path}/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer" + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz" - sources = [ "rddbrepair_fuzzer.cpp" ] - - deps = [ - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb:distributeddb", - "${distributeddata_base_path}/relational_store/interfaces/inner_api/rdb:native_rdb_static", - "//third_party/jsoncpp:jsoncpp", + sources = [ + "${cloud_data_native_path}/src/cloud_types_util.cpp", + "${cloud_data_native_path}/src/cloud_manager.cpp", + "${cloud_data_native_path}/src/cloud_notifier_stub.cpp", + "${cloud_data_native_path}/src/cloud_service_proxy.cpp", + "cloud_data_test_ut2fuzz.cpp", ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + external_deps = [ "ability_base:zuri", "ability_runtime:dataobs_manager", "c_utils:utils", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:datamgr_common", + "sqlite:sqlite", + "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", + "access_token:libtokenid_sdk", + "samgr:samgr_proxy", ] } @@ -72,7 +74,7 @@ group("fuzztest") { deps = [] deps += [ # deps file - ":RddbrepairFuzzerTest", + ":cloud_data_test_ut2fuzz", ] } ############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/cloud_data_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/cloud_data_test_ut2fuzz.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c02bde62d158a90bf5399996058630df73ddb973 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/cloud_data_test_ut2fuzz.cpp @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2025 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_data_test_ut2fuzz.h" + +#include +#include + +#include +#include +#include + +#include "accesstoken_kit.h" +#include "cloud_manager.h" +#include "cloud_types.h" +#include "cloud_types_util.h" +#include "logger.h" +#include "token_setproc.h" + + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::Rdb; +using namespace OHOS::CloudData; +namespace OHOS { + +static constexpr const char *TEST_BUNDLE_NAME = "bundleName"; +static constexpr const char *TEST_ACCOUNT_ID = "testId"; + +void AllocSystemHapToken(const HapPolicyParams &policy) +{ + HapInfoParams info = { .userID = 100, + .bundleName = "ohos.clouddatatest.demo", + .instIndex = 0, + .appIDDesc = "ohos.clouddatatest.demo", + .isSystemApp = true }; + auto token = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(token.tokenIDEx); +} + +void AllocNormalHapToken(const HapPolicyParams &policy) +{ + HapInfoParams info = { .userID = 100, + .bundleName = "ohos.clouddatatest.demo", + .instIndex = 0, + .appIDDesc = "ohos.clouddatatest.demo", + .isSystemApp = false }; + auto token = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(token.tokenIDEx); +} + +HapPolicyParams g_normalPolicy = { .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { { .permissionName = "ohos.permission.CLOUDDATA_CONFIG", + .bundleName = "ohos.clouddatatest.demo", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "ohos.clouddatatest.demo", + .descriptionId = 1 } }, + .permStateList = { { .permissionName = "ohos.permission.CLOUDDATA_CONFIG", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } } } }; + +HapPolicyParams g_systemPolicy = { .apl = APL_SYSTEM_BASIC, + .domain = "test.domain", + .permList = { { .permissionName = "ohos.permission.CLOUDDATA_CONFIG", + .bundleName = "ohos.clouddatatest.demo", + .grantMode = 1, + .availableLevel = APL_SYSTEM_BASIC, + .label = "label", + .labelId = 1, + .description = "ohos.clouddatatest.demo", + .descriptionId = 1 } }, + .permStateList = { { .permissionName = "ohos.permission.CLOUDDATA_CONFIG", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } } } }; + +HapPolicyParams g_notPermissonPolicy = { .apl = APL_SYSTEM_BASIC, + .domain = "test.domain", + .permList = { { .permissionName = "ohos.permission.TEST", + .bundleName = "ohos.clouddatatest.demo", + .grantMode = 1, + .availableLevel = APL_SYSTEM_BASIC, + .label = "label", + .labelId = 1, + .description = "ohos.clouddatatest.demo", + .descriptionId = 1 } }, + .permStateList = { { .permissionName = "ohos.permission.TEST", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } } } }; + +CloudData::Participants CreateParticipants(FuzzedDataProvider &fdp) +{ + Privilege privilege; + privilege.writable = fdp.ConsumeBool(); + privilege.readable = fdp.ConsumeBool(); + privilege.creatable = fdp.ConsumeBool(); + privilege.deletable = fdp.ConsumeBool(); + privilege.shareable = fdp.ConsumeBool(); + + Participant participant; + participant.identity = fdp.ConsumeRandomLengthString(); + participant.role = fdp.ConsumeIntegralInRange(Role::ROLE_NIL, Role::ROLE_BUTT); + participant.state = fdp.ConsumeIntegralInRange(Confirmation::CFM_NIL, Confirmation::CFM_BUTT); + participant.privilege = privilege; + participant.attachInfo = fdp.ConsumeRandomLengthString(); + + CloudData::Participants participants; + participants.push_back(participant); + return participants; +} + +void CloudDataTestCloudDataTest001(FuzzedDataProvider &fdp) +{ + AllocSystemHapToken(g_systemPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + std::map switches; + switches.emplace(TEST_BUNDLE_NAME, fdp.ConsumeIntegral()); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + proxy->EnableCloud(TEST_ACCOUNT_ID, switches); +} + +void CloudDataTestChangeAppSwitch001(FuzzedDataProvider &fdp) +{ + AllocSystemHapToken(g_systemPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + proxy->ChangeAppSwitch(TEST_ACCOUNT_ID, TEST_BUNDLE_NAME, fdp.ConsumeIntegral()); +} + +void CloudDataTestClean001(FuzzedDataProvider &fdp) +{ + AllocSystemHapToken(g_systemPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::map actions; + actions.emplace(TEST_BUNDLE_NAME, fdp.ConsumeIntegral()); + proxy->Clean(TEST_ACCOUNT_ID, actions); +} + +void CloudDataTestNotifyDataChange001(FuzzedDataProvider &fdp) +{ + AllocSystemHapToken(g_systemPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string eventId = fdp.ConsumeRandomLengthString(); + std::string extraData = fdp.ConsumeRandomLengthString(); + int32_t userId = fdp.ConsumeIntegral(); + proxy->NotifyDataChange(eventId, extraData, userId); +} + +void CloudDataTestShare001(FuzzedDataProvider &fdp) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string sharingRes = fdp.ConsumeRandomLengthString(); + + CloudData::Participants participants = CreateParticipants(fdp); + CloudData::Results results; + proxy->Share(sharingRes, participants, results); +} + +void CloudDataTestUnshare001(FuzzedDataProvider &fdp) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string sharingRes = fdp.ConsumeRandomLengthString(); + + CloudData::Participants participants = CreateParticipants(fdp); + CloudData::Results results; + proxy->Unshare(sharingRes, participants, results); +} + +void CloudDataTestExit001(FuzzedDataProvider &fdp) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string sharingRes = fdp.ConsumeRandomLengthString(); + std::pair result; + proxy->Exit(sharingRes, result); +} + +void CloudDataTestChangePrivilege001(FuzzedDataProvider &fdp) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string sharingRes = fdp.ConsumeRandomLengthString(); + CloudData::Participants participants = CreateParticipants(fdp); + CloudData::Results results; + proxy->ChangePrivilege(sharingRes, participants, results); +} + +void CloudDataTestQuery001(FuzzedDataProvider &fdp) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string sharingRes = fdp.ConsumeRandomLengthString(); + CloudData::QueryResults result; + proxy->Query(sharingRes, result); +} + +void CloudDataTestQueryByInvitation001(FuzzedDataProvider &fdp) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string invitation = fdp.ConsumeRandomLengthString(); + CloudData::QueryResults result; + proxy->QueryByInvitation(invitation, result); +} + +void CloudDataTestConfirmInvitation001(FuzzedDataProvider &fdp) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string sharingRes = fdp.ConsumeRandomLengthString(); + int32_t confirmation = fdp.ConsumeIntegral(); + std::tuple result; + proxy->ConfirmInvitation(sharingRes, confirmation, result); +} + +void CloudDataTestChangeConfirmation001(FuzzedDataProvider &fdp) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string sharingRes = fdp.ConsumeRandomLengthString(); + int32_t confirmation = fdp.ConsumeIntegral(); + std::pair result; + proxy->ChangeConfirmation(sharingRes, confirmation, result); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::CloudDataTestCloudDataTest001(fdp); + OHOS::CloudDataTestChangeAppSwitch001(fdp); + OHOS::CloudDataTestClean001(fdp); + OHOS::CloudDataTestNotifyDataChange001(fdp); + OHOS::CloudDataTestShare001(fdp); + OHOS::CloudDataTestUnshare001(fdp); + OHOS::CloudDataTestExit001(fdp); + OHOS::CloudDataTestChangePrivilege001(fdp); + OHOS::CloudDataTestQuery001(fdp); + OHOS::CloudDataTestQueryByInvitation001(fdp); + OHOS::CloudDataTestConfirmInvitation001(fdp); + OHOS::CloudDataTestChangeConfirmation001(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/cloud_data_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/cloud_data_test_ut2fuzz.h new file mode 100644 index 0000000000000000000000000000000000000000..fe3ee7319ee1677a77261c0527d04bf88ed5f7e2 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/cloud_data_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 CLOUD_DATA_TEST_UT2FUZZ_H +#define CLOUD_DATA_TEST_UT2FUZZ_H + +#define FUZZ_PROJECT_NAME "cloud_data_test_ut2fuzz" + +#endif // CLOUD_DATA_TEST_UT2FUZZ_H diff --git a/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2aea1356e3c3b3ee6e12ad3f72640897d769d02e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/BUILD.gn b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..75023b65f241d10b59ab9c43d5f5a4e9b7af3101 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/BUILD.gn @@ -0,0 +1,62 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("connection_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ "${relational_store_native_path}/rdb/include" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/connection_test_ut2fuzz" + + sources = [ + "${relational_store_native_path}/rdb/src/connection.cpp", + "connection_test_ut2fuzz.cpp", + ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":connection_test_ut2fuzz", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/transfergrderrno_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/connection_test_ut2fuzz.cpp similarity index 50% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/transfergrderrno_fuzzer.cpp rename to relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/connection_test_ut2fuzz.cpp index b7d963fb9826069bda357c0f9b23c983d80634ef..ac15d09eb4dca616e7c4509db7f3e7403ae2da7a 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/transfergrderrno_fuzzer.cpp +++ b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/connection_test_ut2fuzz.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2025 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 @@ -12,34 +12,42 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "connection_test_ut2fuzz.h" -#include "rd_utils.h" +#include +#include "connection.h" + +#include +#include + +#include "grd_type_export.h" #include "rdb_errno.h" #include "rdb_store_config.h" -#include "rdb_store_impl.h" + + using namespace OHOS; using namespace OHOS::NativeRdb; namespace OHOS { -uint32_t ConvertToUint32(const uint8_t *ptr, size_t size) +void ConnectionTestConnectionTest001(FuzzedDataProvider &fdp) { - if (ptr == nullptr || (size < sizeof(uint32_t))) { - return 0; - } - return *(reinterpret_cast(ptr)); + RdbStoreConfig config(fdp.ConsumeRandomLengthString()); + config.SetDBType(OHOS::NativeRdb::DBType::DB_BUTT); + Connection::Create(config, fdp.ConsumeBool()); } -void RdUtilsTransferGrdErrnoFuzz(const uint8_t *data, size_t size) +void ConnectionTestConnectionTest002(FuzzedDataProvider &fdp) { - int err = ConvertToUint32(data, size); - RdUtils::TransferGrdErrno(err); + RdbStoreConfig config(fdp.ConsumeRandomLengthString()); + config.SetDBType(OHOS::NativeRdb::DBType::DB_BUTT); + Connection::Repair(config); } } // namespace OHOS -/* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - /* Run your code on data */ - OHOS::RdUtilsTransferGrdErrnoFuzz(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::ConnectionTestConnectionTest001(fdp); + OHOS::ConnectionTestConnectionTest002(fdp); return 0; } diff --git a/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/connection_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/connection_test_ut2fuzz.h new file mode 100644 index 0000000000000000000000000000000000000000..7a36efcc5f4db3fb4924657f41544df0c5f03c8a --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/connection_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 CONNECTION_TEST_UT2FUZZ_H +#define CONNECTION_TEST_UT2FUZZ_H + +#define FUZZ_PROJECT_NAME "connection_test_ut2fuzz" + +#endif // CONNECTION_TEST_UT2FUZZ_H diff --git a/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2aea1356e3c3b3ee6e12ad3f72640897d769d02e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/BUILD.gn similarity index 69% rename from relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/BUILD.gn rename to relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/BUILD.gn index cc3e3cb83c8d1293d7c65f3097cb4cb0af31f0e8..682eece91fde8bebfce0922975d165537b7299dc 100644 --- a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/BUILD.gn +++ b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2025 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 @@ -17,15 +17,10 @@ import("//build/test.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") ##############################fuzztest########################################## -ohos_fuzztest("GdbStoreFuzzTest") { +ohos_fuzztest("rdb_attach_test_ut2fuzz") { module_out_path = "relational_store/relational_store" - include_dirs = [ - "${relational_store_innerapi_path}/gdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${relational_store_native_path}/gdb/adapter/include", - "${relational_store_native_path}/gdb/include", - ] + include_dirs = [ "${relational_store_native_path}/rdb/include" ] cflags = [ "-g", @@ -35,15 +30,20 @@ ohos_fuzztest("GdbStoreFuzzTest") { ] fuzz_config_file = - "${relational_store_base_path}/test/native/gdb/fuzztest/gdbstore_fuzzer" + "${relational_store_base_path}/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz" - sources = [ "gdbstore_fuzzer.cpp" ] + sources = [ "rdb_attach_test_ut2fuzz.cpp" ] - deps = [ "${relational_store_innerapi_path}/gdb:native_graphstore" ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", "hilog:libhilog", - "json:nlohmann_json_static", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", ] } @@ -53,7 +53,7 @@ group("fuzztest") { deps = [] deps += [ # deps file - ":GdbStoreFuzzTest", + ":rdb_attach_test_ut2fuzz", ] } ############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2aea1356e3c3b3ee6e12ad3f72640897d769d02e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/rdb_attach_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/rdb_attach_test_ut2fuzz.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3a4fe5a8983ec629cb8a09f6301fa05daee34f62 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/rdb_attach_test_ut2fuzz.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2025 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 "rdb_attach_test_ut2fuzz.h" + +#include + +#include +#include + +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +static const std::string MAIN_DATABASE_NAME = "/data/test/main.db"; +static const std::string ATTACHED_DATABASE_NAME = "/data/test/attached.db"; +static const std::string ENCRYPT_ATTACHED_DATABASE_NAME = "/data/test/encrypt_attached.db"; +static const int BUSY_TIMEOUT = 2; + +class MainOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string createTableSql; +}; + +std::string const MainOpenCallback::createTableSql = "CREATE TABLE IF NOT EXISTS test1(id INTEGER PRIMARY KEY " + "AUTOINCREMENT, name TEXT NOT NULL)"; + +int MainOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(createTableSql); +} + +int MainOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +class AttachedOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string createTableSql; +}; + +std::string const AttachedOpenCallback::createTableSql = "CREATE TABLE IF NOT EXISTS test2(id INTEGER PRIMARY KEY " + "AUTOINCREMENT, name TEXT NOT NULL)"; + +int AttachedOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(createTableSql); +} + +int AttachedOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void SetUpTestCase(void) +{ + RdbStoreConfig attachedConfig(ATTACHED_DATABASE_NAME); + AttachedOpenCallback attachedHelper; + int errCode = E_OK; + std::shared_ptr attachedStore = RdbHelper::GetRdbStore(attachedConfig, 1, attachedHelper, errCode); +} + +void TearDownTestCase(void) +{ + RdbHelper::DeleteRdbStore(MAIN_DATABASE_NAME); + RdbHelper::DeleteRdbStore(ATTACHED_DATABASE_NAME); +} + +void QueryCheck1(std::shared_ptr &store) +{ + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test1"); + if (resultSet == nullptr) { + return; + } + int ret = resultSet->GoToNextRow(); + int columnIndex; + int intVal; + ret = resultSet->GetColumnIndex("id", columnIndex); + ret = resultSet->GetInt(columnIndex, intVal); + std::string strVal; + ret = resultSet->GetColumnIndex("name", columnIndex); + ret = resultSet->GetString(columnIndex, strVal); + resultSet = store->QuerySql("SELECT * FROM test2"); + ret = resultSet->GoToNextRow(); + ret = resultSet->GetColumnIndex("id", columnIndex); + ret = resultSet->GetInt(columnIndex, intVal); + ret = resultSet->GetColumnIndex("name", columnIndex); + ret = resultSet->GetString(columnIndex, strVal); +} + +void QueryCheck2(std::shared_ptr &store) +{ + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test1"); + if (resultSet == nullptr) { + return; + } + int ret = resultSet->GoToNextRow(); + int columnIndex; + int intVal; + ret = resultSet->GetColumnIndex("id", columnIndex); + ret = resultSet->GetInt(columnIndex, intVal); + std::string strVal; + ret = resultSet->GetColumnIndex("name", columnIndex); + ret = resultSet->GetString(columnIndex, strVal); + resultSet = store->QuerySql("SELECT * FROM test2"); +} + +void RdbAttachTestRdbStoreAttach001(FuzzedDataProvider &fdp) +{ + int errCode = E_OK; + AttachedOpenCallback attachedHelper; + RdbStoreConfig encryptAttachedConfig(ENCRYPT_ATTACHED_DATABASE_NAME); + encryptAttachedConfig.SetEncryptStatus(fdp.ConsumeBool()); + std::shared_ptr encryptAttachedStore = + RdbHelper::GetRdbStore(encryptAttachedConfig, 1, attachedHelper, errCode); + if (encryptAttachedStore == nullptr) { + return; + } + encryptAttachedStore = nullptr; + const std::string attachedName = "attached"; + RdbStoreConfig config(MAIN_DATABASE_NAME); + MainOpenCallback helper; + + std::shared_ptr store1 = RdbHelper::GetRdbStore(config, 1, helper, errCode); + if (store1 == nullptr) { + return; + } + + store1->Attach(encryptAttachedConfig, attachedName, BUSY_TIMEOUT); + + int64_t id; + ValuesBucket values; + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutString(fdp.ConsumeRandomLengthString(), fdp.ConsumeRandomLengthString()); + store1->Insert(id, fdp.ConsumeRandomLengthString(), values); + + QueryCheck1(store1); + + store1->Detach(attachedName); + + QueryCheck2(store1); + RdbHelper::DeleteRdbStore(ENCRYPT_ATTACHED_DATABASE_NAME); +} + +void RdbAttachTestRdbStoreAttach002(FuzzedDataProvider &fdp) +{ + const std::string attachedName = "attached"; + RdbStoreConfig config(fdp.ConsumeRandomLengthString()); + config.SetStorageMode(StorageMode::MODE_MEMORY); + MainOpenCallback helper; + int errCode = E_OK; + std::shared_ptr mainMemDb = RdbHelper::GetRdbStore(config, 1, helper, errCode); + if (mainMemDb == nullptr) { + return; + } + + RdbStoreConfig attachedConfig(fdp.ConsumeRandomLengthString()); + std::shared_ptr walDb = RdbHelper::GetRdbStore(attachedConfig, 1, helper, errCode); + if (walDb == nullptr) { + return; + } + + std::string sql = fdp.ConsumeRandomLengthString(); + auto code = walDb->ExecuteSql(sql); + + mainMemDb->Attach(attachedConfig, attachedName, BUSY_TIMEOUT); + + ValueObject val; + std::tie(code, val) = + mainMemDb->Execute(fdp.ConsumeRandomLengthString(), { fdp.ConsumeIntegral(), "memDbName" }); + auto result = mainMemDb->QuerySql(fdp.ConsumeRandomLengthString()); + + int index = fdp.ConsumeIntegral(); + result->GetColumnIndex(fdp.ConsumeRandomLengthString(), index); + std::string name; + result->GetString(index, name); + result->Close(); + mainMemDb->Detach(attachedName); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::RdbAttachTestRdbStoreAttach001(fdp); + OHOS::RdbAttachTestRdbStoreAttach002(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/rdb_attach_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/rdb_attach_test_ut2fuzz.h new file mode 100644 index 0000000000000000000000000000000000000000..b5d77fef3d9da2941f28063aa14929ca9c2aa737 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/rdb_attach_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 RDB_ATTACH_TEST_UT2FUZZ +#define RDB_ATTACH_TEST_UT2FUZZ + +#define FUZZ_PROJECT_NAME "rdb_attach_test_ut2fuzz" + +#endif // RDB_ATTACH_TEST_UT2FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..9a0d5876688afcdfb870af754f62bc530b2b4346 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("rdb_bigint_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz" + + sources = [ "rdb_bigint_test_ut2fuzz.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":rdb_bigint_test_ut2fuzz", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2aea1356e3c3b3ee6e12ad3f72640897d769d02e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/rdb_bigint_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/rdb_bigint_test_ut2fuzz.cpp new file mode 100644 index 0000000000000000000000000000000000000000..48a4f8959afe57bf13dfd6c0cf243435c5d3c378 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/rdb_bigint_test_ut2fuzz.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025 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 "rdb_bigint_test_ut2fuzz.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "big_integer.h" +#include "connection_pool.h" +#include "trans_db.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +namespace OHOS { + +void BigIntegerFuzzTest(FuzzedDataProvider &fdp) +{ + // Test primary constructor with int64_t + auto bi1 = NativeRdb::BigInteger(fdp.ConsumeIntegral()); + + // Test (sign, vector) constructor + std::vector vec; + while (fdp.remaining_bytes() >= sizeof(uint64_t)) { + vec.push_back(fdp.ConsumeIntegral()); + } + auto bi2 = NativeRdb::BigInteger( + fdp.ConsumeIntegralInRange(-1, 1), + std::move(vec) + ); + + // Validate copy semantics + auto bi3 = NativeRdb::BigInteger(bi1); + bi3 = bi2; // Test assignment operator + + // Stress test move semantics + auto bi4 = NativeRdb::BigInteger(std::move(bi2)); + bi1 = std::move(bi3); + + // Verify core operations + (void)(bi1 == bi4); // Compare equality + (void)(bi1 < bi4); // Compare ordering + + // Exercise all public methods + (void)bi1.Sign(); // Validate sign retrieval + (void)bi1.Size(); // Check array size + (void)bi1.TrueForm(); // Access raw data + (void)bi1.Value(); // Test value copy +} + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::BigIntegerFuzzTest(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/rdb_bigint_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/rdb_bigint_test_ut2fuzz.h new file mode 100644 index 0000000000000000000000000000000000000000..8282ff370577559c663fb4d3b4db22266f10464f --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/rdb_bigint_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 RDB_BIGINT_TEST_UT2FUZZ +#define RDB_BIGINT_TEST_UT2FUZZ + +#define FUZZ_PROJECT_NAME "rdb_bigint_test_ut2fuzz" + +#endif // RDB_BIGINT_TEST_UT2FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..d7a2ef6f255fc3088d150ff8ad9363d3b5e90263 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/BUILD.gn @@ -0,0 +1,59 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("rdb_callback_icu_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ "${relational_store_native_path}/rdb/include" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz" + + sources = [ "rdb_callback_icu_test_ut2fuzz.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":rdb_callback_icu_test_ut2fuzz", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2aea1356e3c3b3ee6e12ad3f72640897d769d02e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/rdb_callback_icu_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/rdb_callback_icu_test_ut2fuzz.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f2a5c001f906a0eefc70d151aa3da629c74410dc --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/rdb_callback_icu_test_ut2fuzz.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2025 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 "rdb_callback_icu_test_ut2fuzz.h" + +#include + +#include +#include + +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +static const std::string PATH_NAME = "/data/test/rdb_callback_icu_test.db"; + +class OpenCallbackIcu : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + int OnDowngrade(RdbStore &store, int oldVersion, int newVersion) override; + int OnOpen(RdbStore &store) override; + + static std::string CreateTableSQL(const std::string &tableName); + static std::string DropTableSQL(const std::string &tableName); +}; + +std::string OpenCallbackIcu::CreateTableSQL(const std::string &tableName) +{ + return "CREATE VIRTUAL TABLE IF NOT EXISTS " + tableName + " USING fts4(name, content, tokenize=icu zh_CN);"; +} + +std::string OpenCallbackIcu::DropTableSQL(const std::string &tableName) +{ + return "DROP TABLE IF EXISTS " + tableName + ";"; +} + +int OpenCallbackIcu::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CreateTableSQL("test1")); +} + +int OpenCallbackIcu::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +int OpenCallbackIcu::OnDowngrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +int OpenCallbackIcu::OnOpen(RdbStore &store) +{ + return E_OK; +} + +void RdbCallbackIcuTestRdbCallbackIcu01(FuzzedDataProvider &fdp) +{ + RdbStoreConfig config(PATH_NAME); + config.SetTokenizer(ICU_TOKENIZER); + OpenCallbackIcu helper; + + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + if (store == nullptr) { + return; + } + + const char *sqlCreateTable = "CREATE VIRTUAL TABLE example USING fts4(name, content, tokenize=icu zh_CN);"; + int ret = store->ExecuteSql(sqlCreateTable); + + const char *sqlInsert1 = + "INSERT INTO example(name, content) VALUES('文档1', '这是一个测试文档,用于测试中文文本的分词和索引。');"; + ret = store->ExecuteSql(sqlInsert1); + + const char *sqlInsert2 = + "INSERT INTO example(name, content) VALUES('文档2', '我们将使用这个示例来演示如何在SQLite中进行全文搜索。');"; + ret = store->ExecuteSql(sqlInsert2); + + const char *sqlInsert3 = + "INSERT INTO example(name, content) VALUES('文档3', 'ICU分词器能够很好地处理中文文本的分词和分析。');"; + ret = store->ExecuteSql(sqlInsert3); + + const char *sqlQuery = "SELECT * FROM example WHERE example MATCH '测试';"; + ret = store->ExecuteSql(sqlQuery); + + std::shared_ptr resultSet = store->QuerySql(sqlQuery); + if (resultSet == nullptr) { + return; + } + + ret = resultSet->GoToNextRow(); + + int columnIndex; + std::string strVal; + + ret = resultSet->GetColumnIndex(fdp.ConsumeRandomLengthString(), columnIndex); + + ret = resultSet->GetString(columnIndex, strVal); + + ret = resultSet->GetColumnIndex(fdp.ConsumeRandomLengthString(), columnIndex); + + ret = resultSet->GetString(columnIndex, strVal); + + ret = resultSet->GoToNextRow(); + + ret = resultSet->Close(); +} + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::RdbCallbackIcuTestRdbCallbackIcu01(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/rdb_callback_icu_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/rdb_callback_icu_test_ut2fuzz.h new file mode 100644 index 0000000000000000000000000000000000000000..d15c46ba9af79dd659f140ece6cce7617dee2a2d --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/rdb_callback_icu_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 RDB_CALLBACK_ICU_TEST_UT2FUZZ +#define RDB_CALLBACK_ICU_TEST_UT2FUZZ + +#define FUZZ_PROJECT_NAME "rdb_callback_icu_test_ut2fuzz" + +#endif // RDB_CALLBACK_ICU_TEST_UT2FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..64d3f5be44d28fb7baad37ea01d54615a0b3c7a6 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/BUILD.gn @@ -0,0 +1,59 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("rdb_corrupt_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ "${relational_store_native_path}/rdb/include" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz" + + sources = [ "rdb_corrupt_test_ut2fuzz.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":rdb_corrupt_test_ut2fuzz", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2aea1356e3c3b3ee6e12ad3f72640897d769d02e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/rdb_corrupt_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/rdb_corrupt_test_ut2fuzz.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b09a0ed7cb8ecc7626c747d058bac7c1088aba9d --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/rdb_corrupt_test_ut2fuzz.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except 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 "rdb_corrupt_test_ut2fuzz.h" + +#include +#include + +#include +#include +#include +#include + +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +namespace OHOS { + +static const std::string PATH_NAME = "/data/test/corrupt_test.db"; + +class CorruptTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary " + "REAL, blobType BLOB)"; +}; + +int CorruptTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(createTableTest); +} + +int CorruptTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void SetUp(std::shared_ptr &store) +{ + RdbHelper::ClearCache(); + RdbHelper::DeleteRdbStore(PATH_NAME); + RdbStoreConfig sqliteSharedRstConfig(PATH_NAME); + CorruptTestOpenCallback openCallback; + int errCode = E_OK; + store = RdbHelper::GetRdbStore(sqliteSharedRstConfig, 1, openCallback, errCode); + if (store == nullptr) { + return; + } + RdbHelper::ClearCache(); +} + +void TearDown(void) +{ + RdbHelper::ClearCache(); + RdbHelper::DeleteRdbStore(PATH_NAME); +} + +void DestroyDbFile(const std::string &filePath, size_t offset, size_t len, unsigned char ch) +{ + constexpr size_t MAX_CORRUPT_SIZE = 2048; + len = std::min(len, MAX_CORRUPT_SIZE); + + std::vector buf; + buf.reserve(len); + buf.assign(len, static_cast(ch)); + + std::ofstream f(filePath, std::ios::binary | std::ios::in | std::ios::out); + if (!f) + return; + + f.seekp(offset); + f.write(buf.data(), len); +} + +void RdbCorruptTestRdbCorruptTest001(FuzzedDataProvider &fdp) +{ + std::shared_ptr store; + SetUp(store); + if (store == nullptr) { + return; + } + + constexpr size_t MAX_FILE_SIZE = 4096; + size_t offset = fdp.ConsumeIntegralInRange(0, MAX_FILE_SIZE / 2); + size_t len = fdp.ConsumeIntegralInRange(1, MAX_FILE_SIZE - offset); + DestroyDbFile(PATH_NAME, offset, len, fdp.ConsumeIntegral()); + + CorruptTestOpenCallback sqliteCallback; + RdbStoreConfig sqliteConfig(PATH_NAME); + int errCode = E_OK; + store = RdbHelper::GetRdbStore(sqliteConfig, 1, sqliteCallback, errCode); + if (store == nullptr) { + return; + } + + std::shared_ptr resultSet = store->QueryByStep("SELECT * FROM test"); + if (resultSet == nullptr) { + return; + } + + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + if (errCode != E_OK) { + break; + } + } + resultSet->Close(); + TearDown(); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::RdbCorruptTestRdbCorruptTest001(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/rdb_corrupt_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/rdb_corrupt_test_ut2fuzz.h new file mode 100644 index 0000000000000000000000000000000000000000..5eb7c1e5cd108bf3a945a9c09a5baf830f9f6c34 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/rdb_corrupt_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 RDB_CORRUPT_TEST_UT2FUZZ +#define RDB_CORRUPT_TEST_UT2FUZZ + +#define FUZZ_PROJECT_NAME "rdb_corrupt_test_ut2fuzz" + +#endif // RDB_CORRUPT_TEST_UT2FUZZ diff --git a/kv_store/test/fuzztest/distributedkvdataservice_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/BUILD.gn similarity index 63% rename from kv_store/test/fuzztest/distributedkvdataservice_fuzzer/BUILD.gn rename to relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/BUILD.gn index 45dd0620af978c08c38ca765a1a25e8008111b9a..cc9d62728574173e2190817e1097e9a3a9d57e25 100644 --- a/kv_store/test/fuzztest/distributedkvdataservice_fuzzer/BUILD.gn +++ b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2024 Huawei Device Co., Ltd. +# Copyright (c) 2025 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 @@ -14,35 +14,36 @@ #####################hydra-fuzz################### import("//build/config/features.gni") import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") ##############################fuzztest########################################## -ohos_fuzztest("DistributedKvDataServiceFuzzTest") { - module_out_path = "kv_store/kv_store" - - include_dirs = [ - "../../../frameworks/common", - "../../../frameworks/innerkitsimpl/distributeddatafwk/include", - "../../../frameworks/innerkitsimpl/distributeddatafwk/src", - "../../../interfaces/innerkits/distributeddata/include", - ] +ohos_fuzztest("rdb_delete_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" - fuzz_config_file = "../../../test/fuzztest/distributedkvdataservice_fuzzer" + include_dirs = [ "${relational_store_native_path}/rdb/include" ] cflags = [ "-g", "-O0", "-Wno-unused-variable", "-fno-omit-frame-pointer", - "-Wno-c99-designator", ] - sources = [ "distributedkvdataservice_fuzzer.cpp" ] - deps = [] + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz" + + sources = [ "rdb_delete_test_ut2fuzz.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", "c_utils:utils", "hilog:libhilog", - "kv_store:distributeddata_inner", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", ] } @@ -52,7 +53,7 @@ group("fuzztest") { deps = [] deps += [ # deps file - ":DistributedKvDataServiceFuzzTest", + ":rdb_delete_test_ut2fuzz", ] } ############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2aea1356e3c3b3ee6e12ad3f72640897d769d02e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/rdb_delete_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/rdb_delete_test_ut2fuzz.cpp new file mode 100644 index 0000000000000000000000000000000000000000..685582c2f01c59b7bb466d67865e6e2161c60fed --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/rdb_delete_test_ut2fuzz.cpp @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2025 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 "rdb_delete_test_ut2fuzz.h" + +#include +#include + +#include +#include +#include +#include + +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +static const std::string DATABASE_NAME = "/data/test/delete_test.db"; +std::shared_ptr store_; +std::shared_ptr memDBStore_; + +struct RowData { + int id; + std::string name; + int age; + double salary; + std::vector blobType; + AssetValue asset; + std::vector assets; +}; + +class DeleteTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; +constexpr const char *CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test" + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary " + "REAL, blobType BLOB)"; +int DeleteTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_TEST); +} + +int DeleteTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +ValuesBucket SetRowData(const RowData &rowData) +{ + ValuesBucket value; + value.PutInt("id", rowData.id); + value.PutString("name", rowData.name); + value.PutInt("age", rowData.age); + value.PutDouble("salary", rowData.salary); + value.PutBlob("blobType", rowData.blobType); + return value; +} + +void SetUpTestCase(void) +{ + int errCode = E_OK; + RdbHelper::DeleteRdbStore(DATABASE_NAME); + RdbStoreConfig config(DATABASE_NAME); + DeleteTestOpenCallback helper; + store_ = RdbHelper::GetRdbStore(config, 1, helper, errCode); + store_->ExecuteSql("DELETE FROM test"); + + config.SetStorageMode(StorageMode::MODE_MEMORY); + memDBStore_ = RdbHelper::GetRdbStore(config, 1, helper, errCode); +} + +void TearDownTestCase(void) +{ + RdbStoreConfig config(DATABASE_NAME); + RdbHelper::DeleteRdbStore(config); + config.SetStorageMode(StorageMode::MODE_MEMORY); + RdbHelper::DeleteRdbStore(config); +} + +void RdbDeleteTestRdbStoreDelete001(FuzzedDataProvider &fdp) +{ + SetUpTestCase(); + std::shared_ptr store = store_; + if (store == NULL) { + return; + } + + int64_t id; + int deletedRows; + + const RowData rowData[3] = { { 1, "zhangsan", 18, 100.5, std::vector{ 1, 2, 3 } }, + { 2, "lisi", 19, 200.5, std::vector{ 4, 5, 6 } }, + { 3, "wangyjing", 20, 300.5, std::vector{ 7, 8, 9 } } }; + + const int indexZero = 0; + store->Insert(id, fdp.ConsumeRandomLengthString(), SetRowData(rowData[indexZero])); + + const int indexOne = 1; + store->Insert(id, fdp.ConsumeRandomLengthString(), SetRowData(rowData[indexOne])); + + const int indexTwo = 2; + store->Insert(id, fdp.ConsumeRandomLengthString(), SetRowData(rowData[indexTwo])); + + store->Delete(deletedRows, fdp.ConsumeRandomLengthString(), fdp.ConsumeRandomLengthString()); + + std::shared_ptr resultSet = + store->QuerySql("SELECT * FROM test WHERE id = ?", std::vector{ "1" }); + + resultSet->GoToNextRow(); + + resultSet->Close(); + + resultSet = store->QuerySql("SELECT * FROM test WHERE id = ?", std::vector{ "2" }); + + resultSet->GoToFirstRow(); + + resultSet->GoToNextRow(); + + resultSet->Close(); + + resultSet = store->QuerySql("SELECT * FROM test WHERE id = 3", std::vector()); + + resultSet->GoToFirstRow(); + + resultSet->GoToNextRow(); + + resultSet->Close(); + TearDownTestCase(); +} + +void RdbDeleteTestRdbStoreDelete002(FuzzedDataProvider &fdp) +{ + SetUpTestCase(); + std::shared_ptr store = store_; + if (store == NULL) { + return; + } + + int64_t id; + ValuesBucket values; + int deletedRows; + + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutString(fdp.ConsumeRandomLengthString(), std::string(fdp.ConsumeRandomLengthString())); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutDouble(fdp.ConsumeRandomLengthString(), fdp.ConsumeFloatingPoint()); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + store->Insert(id, fdp.ConsumeRandomLengthString(), values); + + values.Clear(); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutString(fdp.ConsumeRandomLengthString(), std::string(fdp.ConsumeRandomLengthString())); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutDouble(fdp.ConsumeRandomLengthString(), fdp.ConsumeFloatingPoint()); + values.PutBlob("blobType", std::vector{ 4, 5, 6 }); + store->Insert(id, fdp.ConsumeRandomLengthString(), values); + + values.Clear(); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutString(fdp.ConsumeRandomLengthString(), std::string(fdp.ConsumeRandomLengthString())); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutDouble(fdp.ConsumeRandomLengthString(), fdp.ConsumeFloatingPoint()); + values.PutBlob("blobType", std::vector{ 7, 8, 9 }); + store->Insert(id, fdp.ConsumeRandomLengthString(), values); + + store->Delete(deletedRows, fdp.ConsumeRandomLengthString()); + + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + if (resultSet == NULL) { + return; + } + resultSet->GoToNextRow(); + resultSet->Close(); + TearDownTestCase(); +} + +void RdbDeleteTestRdbStoreDelete003(FuzzedDataProvider &fdp) +{ + SetUpTestCase(); + std::shared_ptr store = store_; + if (store == NULL) { + return; + } + + int64_t id; + ValuesBucket values; + int deletedRows; + + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutString(fdp.ConsumeRandomLengthString(), std::string(fdp.ConsumeRandomLengthString())); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutDouble(fdp.ConsumeRandomLengthString(), fdp.ConsumeFloatingPoint()); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + store->Insert(id, fdp.ConsumeRandomLengthString(), values); + + store->Delete(deletedRows, "", "id = ?", std::vector{ "1" }); + + store->Delete(deletedRows, "wrongTable", "id = ?", std::vector{ "1" }); + + store->Delete(deletedRows, "test", "wrong sql id = ?", std::vector{ "1" }); + + store->Delete(deletedRows, "test", "id = 1", std::vector()); + TearDownTestCase(); +} + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::RdbDeleteTestRdbStoreDelete001(fdp); + OHOS::RdbDeleteTestRdbStoreDelete002(fdp); + OHOS::RdbDeleteTestRdbStoreDelete003(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/rdb_delete_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/rdb_delete_test_ut2fuzz.h new file mode 100644 index 0000000000000000000000000000000000000000..2c4a4075675da51dbc271985e3bd0642ab7c6656 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/rdb_delete_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 RDB_DELETE_TEST_UT2FUZZ +#define RDB_DELETE_TEST_UT2FUZZ + +#define FUZZ_PROJECT_NAME "rdb_delete_test_ut2fuzz" + +#endif // RDB_DELETE_TEST_UT2FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..a5790bbc296e503789a0072c177d3283db6ae74f --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/BUILD.gn @@ -0,0 +1,59 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("rdb_distributed_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ "${relational_store_native_path}/rdb/include" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz" + + sources = [ "rdb_distributed_test_ut2fuzz.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":rdb_distributed_test_ut2fuzz", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2aea1356e3c3b3ee6e12ad3f72640897d769d02e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/rdb_distributed_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/rdb_distributed_test_ut2fuzz.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2b735ea4f691f662c931a2923da1712412ba7bf3 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/rdb_distributed_test_ut2fuzz.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2025 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 "rdb_distributed_test_ut2fuzz.h" + +#include +#include +#include +#include + +#include +#include + +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +static const std::string DATABASE_NAME = "/data/test/distributed_rdb.db"; +static std::shared_ptr rdbStore; + +class TestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override + { + std::string sql = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT," + "name TEXT NOT NULL," + "age INTEGER," + "salary REAL," + "data BLOB)"; + store.ExecuteSql(sql); + return 0; + } + + int OnOpen(RdbStore &store) override + { + return 0; + } + + int OnUpgrade(RdbStore &store, int currentVersion, int targetVersion) override + { + return 0; + } +}; + +void SetUpTestCase(void) +{ + int errCode = 0; + std::string path = DATABASE_NAME; + RdbHelper::DeleteRdbStore(path); + int fd = open(path.c_str(), O_CREAT, S_IRWXU | S_IRWXG); + if (fd < 0) { + return; + } + if (fd > 0) { + close(fd); + } + const int ddmsGroupId = 1000; + chown(path.c_str(), 0, ddmsGroupId); + + RdbStoreConfig config(path); + config.SetBundleName("com.example.distributed.rdb"); + config.SetName(DATABASE_NAME); + TestOpenCallback callback; + rdbStore = RdbHelper::GetRdbStore(config, 1, callback, errCode); + rdbStore->ExecuteSql("DELETE FROM test"); +} + +void TearDownTestCase(void) +{ + rdbStore->ExecuteSql("DELETE FROM test"); + RdbHelper::DeleteRdbStore(DATABASE_NAME); +} + +void RdbStoreDistributedTestRdbStoreDistributedTest001(FuzzedDataProvider &fdp) +{ + SetUpTestCase(); + int errCode; + std::vector tables; + OHOS::DistributedRdb::DistributedConfig distributedConfig; + + rdbStore->SetDistributedTables(tables, fdp.ConsumeIntegral(), distributedConfig); + tables.push_back(fdp.ConsumeRandomLengthString()); + rdbStore->SetDistributedTables(tables, fdp.ConsumeIntegral(), distributedConfig); + + std::string path = DATABASE_NAME; + RdbHelper::DeleteRdbStore(path); + RdbStoreConfig config(path); + TestOpenCallback callback; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, callback, errCode); + if (store == NULL) { + return; + } + + store->SetDistributedTables(tables, fdp.ConsumeIntegral(), distributedConfig); + + RdbHelper::DeleteRdbStore(path); + + TearDownTestCase(); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::RdbStoreDistributedTestRdbStoreDistributedTest001(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/rdb_distributed_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/rdb_distributed_test_ut2fuzz.h new file mode 100644 index 0000000000000000000000000000000000000000..879618565987e2ec6b85ccb2174cc56ed1e5c973 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/rdb_distributed_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 RDB_DISTRIBUTED_TEST_UT2FUZZ +#define RDB_DISTRIBUTED_TEST_UT2FUZZ + +#define FUZZ_PROJECT_NAME "rdb_distributed_test_ut2fuzz" + +#endif // RDB_DISTRIBUTED_TEST_UT2FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..5214a0af235ab96c4c85ece3da80d83dc2f5f008 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/BUILD.gn @@ -0,0 +1,59 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("rdb_double_write_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ "${relational_store_native_path}/rdb/include" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz" + + sources = [ "rdb_double_write_test_ut2fuzz.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":rdb_double_write_test_ut2fuzz", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2aea1356e3c3b3ee6e12ad3f72640897d769d02e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/rdb_double_write_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/rdb_double_write_test_ut2fuzz.cpp new file mode 100644 index 0000000000000000000000000000000000000000..779652a77b13f8b8c9d55618549b64a103ea3275 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/rdb_double_write_test_ut2fuzz.cpp @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2025 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 "rdb_double_write_test_ut2fuzz.h" + +#include +#include +#include + +#include +#include + +#include "file_ex.h" +#include "rdb_common.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "sqlite_utils.h" +#include "sys/types.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +static const std::string DATABASE_NAME = "/data/test/dual_write_test.db"; +static const std::string SLAVE_DATABASE_NAME = "/data/test/dual_write_test_slave.db"; +std::shared_ptr store = nullptr; +std::shared_ptr slaveStore = nullptr; +std::shared_ptr store3 = nullptr; + +class DoubleWriteTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string createTableTest; +}; + +const std::string DoubleWriteTestOpenCallback::createTableTest = + std::string("CREATE TABLE IF NOT EXISTS test ") + std::string("(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary " + "REAL, blobType BLOB)"); + +int DoubleWriteTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(createTableTest); +} + +int DoubleWriteTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void SetUpTestCase(void) +{ +} + +void TearDownTestCase(void) +{ + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(DATABASE_NAME); +} + +void InitDb() +{ + int errCode = E_OK; + RdbStoreConfig config(DATABASE_NAME); + config.SetHaMode(HAMode::MAIN_REPLICA); + DoubleWriteTestOpenCallback helper; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + + RdbStoreConfig slaveConfig(SLAVE_DATABASE_NAME); + DoubleWriteTestOpenCallback slaveHelper; + slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); + store->ExecuteSql("DELETE FROM test"); + slaveStore->ExecuteSql("DELETE FROM test"); +} + +void CheckAge(std::shared_ptr &resultSet) +{ + int columnIndex; + int intVal; + ColumnType columnType; + int ret = resultSet->GetColumnIndex("age", columnIndex); + ret = resultSet->GetColumnType(columnIndex, columnType); + + ret = resultSet->GetInt(columnIndex, intVal); +} + +void CheckSalary(std::shared_ptr &resultSet) +{ + int columnIndex; + double dVal; + ColumnType columnType; + int ret = resultSet->GetColumnIndex("salary", columnIndex); + + ret = resultSet->GetColumnType(columnIndex, columnType); + + ret = resultSet->GetDouble(columnIndex, dVal); +} + +void CheckBlob(std::shared_ptr &resultSet) +{ + int columnIndex; + std::vector blob; + ColumnType columnType; + int ret = resultSet->GetColumnIndex("blobType", columnIndex); + + ret = resultSet->GetColumnType(columnIndex, columnType); + + ret = resultSet->GetBlob(columnIndex, blob); +} + +void CheckNumber( + std::shared_ptr &store, int num, int errCode, const std::string &tableName) +{ + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM " + tableName); + int countNum; + resultSet->GetRowCount(countNum); +} + +void CheckResultSet(std::shared_ptr &store) +{ + std::shared_ptr resultSet = + store->QuerySql("SELECT * FROM test WHERE name = ?", std::vector{ "zhangsan" }); + + int columnIndex; + int intVal; + std::string strVal; + ColumnType columnType; + int position; + int ret = resultSet->GetRowIndex(position); + + ret = resultSet->GetColumnType(0, columnType); + + ret = resultSet->GoToFirstRow(); + + ret = resultSet->GetColumnIndex("id", columnIndex); + + ret = resultSet->GetColumnType(columnIndex, columnType); + + ret = resultSet->GetInt(columnIndex, intVal); + + ret = resultSet->GetColumnIndex("name", columnIndex); + + ret = resultSet->GetColumnType(columnIndex, columnType); + + ret = resultSet->GetString(columnIndex, strVal); + + CheckAge(resultSet); + CheckSalary(resultSet); + CheckBlob(resultSet); + + ret = resultSet->GoToNextRow(); + + ret = resultSet->GetColumnType(columnIndex, columnType); + + ret = resultSet->Close(); +} + +void RdbDoubleWriteTestRdbStoreDoubleWrite001(FuzzedDataProvider &fdp) +{ + InitDb(); + int64_t id; + ValuesBucket values; + + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutString(fdp.ConsumeRandomLengthString(), std::string(fdp.ConsumeRandomLengthString())); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutDouble(fdp.ConsumeRandomLengthString(), fdp.ConsumeFloatingPoint()); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store->Insert(id, "test", values); + + values.Clear(); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutString(fdp.ConsumeRandomLengthString(), std::string(fdp.ConsumeRandomLengthString())); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutDouble(fdp.ConsumeRandomLengthString(), fdp.ConsumeFloatingPoint()); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + ret = store->Insert(id, "test", values); + + values.Clear(); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutString(fdp.ConsumeRandomLengthString(), std::string(fdp.ConsumeRandomLengthString())); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutDouble(fdp.ConsumeRandomLengthString(), fdp.ConsumeFloatingPoint()); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + ret = store->Insert(id, "test", values); + + CheckResultSet(slaveStore); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::RdbDoubleWriteTestRdbStoreDoubleWrite001(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/rdb_double_write_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/rdb_double_write_test_ut2fuzz.h new file mode 100644 index 0000000000000000000000000000000000000000..97861890454c906c5815ba058325b384e1efe23d --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/rdb_double_write_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 RDB_DOUBLE_WRITE_TEST_UT2FUZZ +#define RDB_DOUBLE_WRITE_TEST_UT2FUZZ + +#define FUZZ_PROJECT_NAME "rdb_double_write_test_ut2fuzz" + +#endif // RDB_DOUBLE_WRITE_TEST_UT2FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..97054c665dd37314cba415a9e3849947a8730409 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/BUILD.gn @@ -0,0 +1,60 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("RdbHelperFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ "${relational_store_native_path}/rdb/include" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdbhelper_fuzzer" + + sources = [ "rdbhelper_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":RdbHelperFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..14cddafc02dab1563ad53641643adc8357882071 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 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. + */ + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..880527c382b58c7a7aa6a92ee3ae33134ac32922 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/project.xml @@ -0,0 +1,26 @@ + + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/rdbhelper_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/rdbhelper_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cfdb230f6758bb416481ac7def18410351982dfd --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/rdbhelper_fuzzer.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2025 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 +#include +#include +#include +#include + +#include + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +class FuzzRdbOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &rdbStore) override + { + return 0; + } + int OnUpgrade(RdbStore &rdbStore, int currentVersion, int targetVersion) override + { + return 0; + } + int OnOpen(RdbStore &rdbStore) override + { + return 0; + } + int OnDowngrade(RdbStore &rdbStore, int currentVersion, int targetVersion) override + { + return 0; + } +}; + +void ExecuteSqlFuzzTest(FuzzedDataProvider &provider) +{ + std::string path = provider.ConsumeRandomLengthString(); + RdbStoreConfig config(path); + config.SetReadOnly(provider.ConsumeBool()); + config.SetPageSize(provider.ConsumeIntegral()); + config.SetBundleName(provider.ConsumeRandomLengthString()); + config.SetSearchable(provider.ConsumeBool()); + config.SetStorageMode(provider.ConsumeBool() ? StorageMode::MODE_MEMORY : StorageMode::MODE_DISK); + + FuzzRdbOpenCallback openCallback; + int errCode = 0; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, openCallback, errCode); + if (!store) { + return; + } + + { + std::string sql = provider.ConsumeRandomLengthString(); + store->ExecuteSql(sql); + } + + ValuesBucket valuesBucket; + { + std::string columnName = provider.ConsumeRandomLengthString(); + valuesBucket.PutInt(columnName, provider.ConsumeIntegral()); + } + + { + std::string columnName = provider.ConsumeRandomLengthString(); + valuesBucket.PutInt(columnName, provider.ConsumeIntegral()); + } + + int64_t outRowId = 0; + std::string tableName = provider.ConsumeRandomLengthString(); + store->Insert(outRowId, tableName, valuesBucket); +} + +void OnDowngradeFuzzTest(FuzzedDataProvider &provider) +{ + // Construct RdbStoreConfig + std::string path = provider.ConsumeRandomLengthString(); + RdbStoreConfig config(path); + config.SetHaMode(provider.ConsumeIntegral()); + + // Construct RdbOpenCallback + FuzzRdbOpenCallback openCallback; + + // Construct RdbStore + int errCode = 0; + std::shared_ptr rdbStore = + RdbHelper::GetRdbStore(config, provider.ConsumeIntegral(), openCallback, errCode); + if (!rdbStore) { + return; + } + + // Test GetBackupStatus + rdbStore->GetBackupStatus(); + + // Test InterruptBackup + rdbStore->InterruptBackup(); + + // Test OnOpen + openCallback.OnOpen(*rdbStore); + + // Test OnDowngrade + openCallback.OnDowngrade(*rdbStore, provider.ConsumeIntegral(), provider.ConsumeIntegral()); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::ExecuteSqlFuzzTest(provider); + OHOS::OnDowngradeFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/rdbhelper_fuzzer.h b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/rdbhelper_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..b86cb138d0dd3a801e32b89c06a22ef3c1d0e5ab --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/rdbhelper_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 RDBHELPER_FUZZER_H +#define RDBHELPER_FUZZER_H + +#define FUZZ_PROJECT_NAME "rdbhelper_fuzzer" + +#endif // RDBHELPER_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/BUILD.gn index 7b03f3c3c097a58f722e956977eadfefde70d117..67355c3fad411c890a12419d20a97bfe86895606 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/BUILD.gn +++ b/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2025 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 @@ -22,22 +22,7 @@ ohos_fuzztest("RdbImplFuzzTest") { include_dirs = [ "${relational_store_native_path}/rdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb/include", - "${common_tool_path}/", - "//third_party/sqlite/include", - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", - "${foundation_systemabilitymgr_path}/safwk/services/safwk/include", - "${foundation_systemabilitymgr_path}/samgr/interfaces/innerkits/samgr_proxy/include", - "${base_security_dataclassification_path}/interfaces/innerkits/datatransmitmgr/include", - "//third_party/json/single_include", - "//third_party/googletest/googletest/include/gtest", + "${relational_store_common_path}/include", ] cflags = [ @@ -52,11 +37,7 @@ ohos_fuzztest("RdbImplFuzzTest") { sources = [ "rdbimpl_fuzzer.cpp" ] - deps = [ - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb:distributeddb", - "${distributeddata_base_path}/relational_store/interfaces/inner_api/rdb:native_rdb_static", - "//third_party/jsoncpp:jsoncpp", - ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] external_deps = [ "ability_base:zuri", @@ -64,6 +45,10 @@ ohos_fuzztest("RdbImplFuzzTest") { "c_utils:utils", "hilog:libhilog", "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", ] } diff --git a/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/corpus/init index bc977bd9738ee9a70b362067f57a9c63d3adb801..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/corpus/init +++ b/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/corpus/init @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2025 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 diff --git a/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/project.xml index 6e8ad2cfde8f8bda4beb6cabbe7efd8bc3c54eec..66e1dcac475475fb101b6f8670ec699e6e9696aa 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/project.xml +++ b/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/project.xml @@ -1,5 +1,5 @@ - + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/rdbpredicates_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/rdbpredicates_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..910116364854ebbbd1ebfb0e96f5a5055df6c546 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/rdbpredicates_fuzzer.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2025 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 "rdb_predicates.h" + + +#define LOOPS_MIN 0 +#define LOOPS_MAX 100 + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +namespace OHOS { +std::vector ConsumeRandomLengthStringVector(FuzzedDataProvider &provider) +{ + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t length = provider.ConsumeIntegral(); + auto bytes = provider.ConsumeBytes(length); + columns.emplace_back(bytes.begin(), bytes.end()); + } + return columns; +} + +void RdbPredicatesCrossJoinFuzz(FuzzedDataProvider &provider) +{ + std::string tableName = provider.ConsumeRandomLengthString(); + RdbPredicates predicates(tableName); + std::string joinTableName = provider.ConsumeRandomLengthString(); + predicates.CrossJoin(joinTableName); +} + +void RdbPredicatesInnerJoinFuzz(FuzzedDataProvider &provider) +{ + std::string tableName = provider.ConsumeRandomLengthString(); + RdbPredicates predicates(tableName); + std::string joinTableName = provider.ConsumeRandomLengthString(); + predicates.InnerJoin(joinTableName); +} + +void RdbPredicatesLeftOuterJoinFuzz(FuzzedDataProvider &provider) +{ + std::string tableName = provider.ConsumeRandomLengthString(); + RdbPredicates predicates(tableName); + std::string joinTableName = provider.ConsumeRandomLengthString(); + predicates.LeftOuterJoin(joinTableName); +} + +void RdbPredicatesUsingFuzz(FuzzedDataProvider &provider) +{ + std::string tableName = provider.ConsumeRandomLengthString(); + RdbPredicates predicates(tableName); + std::vector fields = ConsumeRandomLengthStringVector(provider); + predicates.Using(fields); +} + +void RdbPredicatesOnFuzz(FuzzedDataProvider &provider) +{ + std::string tableName = provider.ConsumeRandomLengthString(); + RdbPredicates predicates(tableName); + std::vector clauses = ConsumeRandomLengthStringVector(provider); + predicates.On(clauses); +} + +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::RdbPredicatesCrossJoinFuzz(provider); + OHOS::RdbPredicatesInnerJoinFuzz(provider); + OHOS::RdbPredicatesLeftOuterJoinFuzz(provider); + OHOS::RdbPredicatesUsingFuzz(provider); + OHOS::RdbPredicatesOnFuzz(provider); + return 0; +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/rdbpredicates_fuzzer.h b/relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/rdbpredicates_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..43733bbaa4df40ac11ad160686257b5cc940fe01 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/rdbpredicates_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 RDBPREDICATES_FUZZER_H +#define RDBPREDICATES_FUZZER_H + +#define FUZZ_PROJECT_NAME "rdbpredicates_fuzzer" + +#endif // RDBPREDICATES_FUZZER_H diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/BUILD.gn index 64301965b8e952f8a02e7fc35d529163c3f474d4..58bb507075f636af77546afbe419fed27f4863c0 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/BUILD.gn +++ b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2025 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 @@ -15,13 +15,62 @@ import("//build/config/features.gni") import("//build/test.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("RdbRdUtilsFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdbrdutils_fuzzer" + + sources = [ + "${relational_store_native_path}/rdb/mock/src/rdb_fault_hiview_reporter.cpp", + "${relational_store_native_path}/rdb/src/grd_api_manager.cpp", + "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", + "${relational_store_native_path}/rdb/src/rd_statement.cpp", + "${relational_store_native_path}/rdb/src/rd_utils.cpp", + "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", + "rdbrdutils_fuzzer.cpp", + ] + + deps = [ + "${relational_store_innerapi_path}/appdatafwk:relational_common_base", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "json:nlohmann_json_static", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### group("fuzztest") { testonly = true - deps = [ - "rddbopen_fuzzer:fuzztest", - "rddbrepair_fuzzer:fuzztest", - "transfergrderrno_fuzzer:fuzztest", - "transfergrdtypetocoltype_fuzzer:fuzztest", + deps = [] + deps += [ + # deps file + ":RdbRdUtilsFuzzTest", ] } ############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rdbrdutils_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rdbrdutils_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c9341bfa1b9391394c648f528aaf47e6ca469e99 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rdbrdutils_fuzzer.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2025 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 "rdbrdutils_fuzzer.h" + +#include + +#include "rd_utils.h" +#include "rdb_errno.h" +#include "rdb_store_config.h" +#include "rdb_store_impl.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +static const int MIN_BLOB_SIZE = 1; +static const int MAX_BLOB_SIZE = 200; + +GRD_DB *CreateDBHandle(FuzzedDataProvider &provider) +{ + GRD_DB *dbHandle = nullptr; + std::string dbPath = provider.ConsumeRandomLengthString(); + std::string configStr = provider.ConsumeRandomLengthString(); + uint32_t flags = provider.ConsumeIntegral(); + RdUtils::RdDbOpen(dbPath.c_str(), configStr.c_str(), flags, &dbHandle); + return dbHandle; +} + +GRD_SqlStmt *CreateSqlStmt(GRD_DB *dbHandle, FuzzedDataProvider &provider) +{ + GRD_SqlStmt *stmtHandle = nullptr; + std::string str = provider.ConsumeRandomLengthString(); + RdUtils::RdSqlPrepare(dbHandle, str.c_str(), str.size(), &stmtHandle, nullptr); + RdUtils::RdSqlReset(stmtHandle); + RdUtils::RdSqlFinalize(stmtHandle); + return stmtHandle; +} + +void RdSqlBindBlobFuzzTest(GRD_SqlStmt *stmtHandle, FuzzedDataProvider &provider) +{ + size_t blobSize = provider.ConsumeIntegralInRange(MIN_BLOB_SIZE, MAX_BLOB_SIZE); + void *val = static_cast(new uint8_t[blobSize]); + provider.ConsumeData(val, blobSize); + + uint32_t idx = provider.ConsumeIntegral(); + RdUtils::RdSqlBindBlob(stmtHandle, idx, val, blobSize, nullptr); + delete[] static_cast(val); + val = nullptr; +} + +void RdbRdUtilsFuzzer(FuzzedDataProvider &provider) +{ + GRD_DB *dbHandle = CreateDBHandle(provider); + + std::string dbPath = provider.ConsumeRandomLengthString(); + std::string configStr = provider.ConsumeRandomLengthString(); + RdUtils::RdDbRepair(dbPath.c_str(), configStr.c_str()); + + { + int err = provider.ConsumeIntegral(); + RdUtils::TransferGrdErrno(err); + } + + { + int err = provider.ConsumeIntegral(); + RdUtils::TransferGrdTypeToColType(err); + } + + GRD_SqlStmt *stmtHandle = CreateSqlStmt(dbHandle, provider); + RdSqlBindBlobFuzzTest(stmtHandle, provider); + + { + uint32_t idx = provider.ConsumeIntegral(); + std::string str = provider.ConsumeRandomLengthString(); + RdUtils::RdSqlBindText(stmtHandle, idx, str.c_str(), str.length(), nullptr); + } + + { + uint32_t idx = provider.ConsumeIntegral(); + int32_t val = provider.ConsumeIntegral(); + RdUtils::RdSqlBindInt(stmtHandle, idx, val); + } + + { + uint32_t idx = provider.ConsumeIntegral(); + int64_t val = provider.ConsumeIntegral(); + RdUtils::RdSqlBindInt64(stmtHandle, idx, val); + } + + { + uint32_t idx = provider.ConsumeIntegral(); + double val = provider.ConsumeFloatingPoint(); + RdUtils::RdSqlBindDouble(stmtHandle, idx, val); + } + + { + uint32_t idx = provider.ConsumeIntegral(); + RdUtils::RdSqlBindNull(stmtHandle, idx); + } + + { + float ftVec[1]; + ftVec[0] = provider.ConsumeFloatingPoint(); + uint32_t idx = provider.ConsumeIntegral(); + RdUtils::RdSqlBindFloatVector(stmtHandle, idx, ftVec, 1, nullptr); + } + + uint32_t flags = provider.ConsumeIntegral(); + RdUtils::RdDbClose(dbHandle, flags); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + /* Run your code on data */ + FuzzedDataProvider provider(data, size); + OHOS::RdbRdUtilsFuzzer(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rdbrdutils_fuzzer.h b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rdbrdutils_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..1e4b22b2deb70cda30499261a83d2284fdecb1c7 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rdbrdutils_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 RDBRDUTILS_FUZZER_H +#define RDBRDUTILS_FUZZER_H + +#define FUZZ_PROJECT_NAME "rdutils_fuzzer" + +#endif // RDBRDUTILS_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/rddbopen_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/rddbopen_fuzzer.cpp deleted file mode 100644 index a48423641f5459d5cad9793b03f429c8d8e5c000..0000000000000000000000000000000000000000 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/rddbopen_fuzzer.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2022 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 "rd_utils.h" -#include "rdb_errno.h" -#include "rdb_store_config.h" -#include "rdb_store_impl.h" - -#define DOUBLE_SIZE 8 -#define INT_SIZE 4 - -using namespace OHOS; -using namespace OHOS::NativeRdb; -namespace OHOS { - -uint32_t ConvertToUint32(const uint8_t *ptr, size_t size) -{ - if (ptr == nullptr || (size < sizeof(uint32_t))) { - return 0; - } - return *(reinterpret_cast(ptr)); -} - -int32_t ConvertToInt32(const uint8_t *ptr, size_t size) -{ - if (ptr == nullptr || (size < sizeof(int32_t))) { - return 0; - } - return *(reinterpret_cast(ptr)); -} - -int64_t ConvertToInt64(const uint8_t *ptr, size_t size) -{ - if (ptr == nullptr || (size < sizeof(int64_t))) { - return 0; - } - return *(reinterpret_cast(ptr)); -} - -double ConvertToDouble(const uint8_t *ptr, size_t size) -{ - if (ptr == nullptr || size < DOUBLE_SIZE) { - return 0; - } - double fa = 0; - uint8_t uc[DOUBLE_SIZE]; - for (int i = 0; i < DOUBLE_SIZE; i++) { - uc[i] = ptr[i]; - } - errno_t err = memcpy_s(&fa, DOUBLE_SIZE, uc, DOUBLE_SIZE); - if (err < 0) { - return 0; - } - return fa; -} - -float ConvertToFloat(const uint8_t *ptr, size_t size) -{ - if (ptr == nullptr || size < INT_SIZE) { - return 0; - } - float fa = 0; - uint8_t uc[INT_SIZE]; - for (int i = 0; i < INT_SIZE; i++) { - uc[i] = ptr[i]; - } - errno_t err = memcpy_s(&fa, INT_SIZE, uc, INT_SIZE); - if (err < 0) { - return 0; - } - return fa; -} - -void RdDbOpenFuzzer(const uint8_t *data, size_t size) -{ - uint32_t unit32t = ConvertToUint32(data, size); - int32_t nit32t = ConvertToInt32(data, size); - int32_t nit64t = ConvertToInt64(data, size); - double doubleValue = ConvertToDouble(data, size); - GRD_DB *dbHandle_ = nullptr; - RdUtils::RdDbOpen(reinterpret_cast(data), reinterpret_cast(data), unit32t, &dbHandle_); - GRD_SqlStmt *stmtHandle = nullptr; - RdUtils::RdSqlPrepare(dbHandle_, reinterpret_cast(data), size, &stmtHandle, nullptr); - RdUtils::RdSqlReset(stmtHandle); - RdUtils::RdSqlFinalize(stmtHandle); - RdUtils::RdSqlBindBlob(stmtHandle, unit32t, static_cast(data), size, nullptr); - RdUtils::RdSqlBindText(stmtHandle, unit32t, static_cast(data), size, nullptr); - RdUtils::RdSqlBindInt(stmtHandle, unit32t, nit32t); - RdUtils::RdSqlBindInt64(stmtHandle, unit32t, nit64t); - RdUtils::RdSqlBindDouble(stmtHandle, unit32t, doubleValue); - RdUtils::RdSqlBindNull(stmtHandle, unit32t); - float ft = ConvertToFloat(data, size); - float ftVec[1]; - ftVec[0] = ft; - RdUtils::RdSqlBindFloatVector(stmtHandle, unit32t, ftVec, 1, nullptr); - RdUtils::RdDbClose(dbHandle_, unit32t); -} -} // namespace OHOS - -/* Fuzzer entry point */ -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - /* Run your code on data */ - OHOS::RdDbOpenFuzzer(data, size); - return 0; -} diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/BUILD.gn deleted file mode 100644 index 9ebe4ea45b1bf2d3e7c6e41ad801406187a00e50..0000000000000000000000000000000000000000 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/BUILD.gn +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (c) 2022 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. - -#####################hydra-fuzz################### -import("//build/config/features.gni") -import("//build/test.gni") -import("//foundation/distributeddatamgr/relational_store/relational_store.gni") - -##############################fuzztest########################################## -ohos_fuzztest("RdbRdUtilsTransferGrdErrnoFuzzTest") { - module_out_path = "relational_store/relational_store" - - include_dirs = [ - "${relational_store_native_path}/rdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb/include", - "${common_tool_path}/", - "//third_party/sqlite/include", - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", - "${foundation_systemabilitymgr_path}/safwk/services/safwk/include", - "${foundation_systemabilitymgr_path}/samgr/interfaces/innerkits/samgr_proxy/include", - "${base_security_dataclassification_path}/interfaces/innerkits/datatransmitmgr/include", - "//third_party/json/single_include", - "//third_party/googletest/googletest/include/gtest", - ] - - cflags = [ - "-g", - "-O0", - "-Wno-unused-variable", - "-fno-omit-frame-pointer", - ] - - fuzz_config_file = "${relational_store_base_path}/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer" - - sources = [ "transfergrderrno_fuzzer.cpp" ] - - deps = [ - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb:distributeddb", - "${distributeddata_base_path}/relational_store/interfaces/inner_api/rdb:native_rdb_static", - "//third_party/jsoncpp:jsoncpp", - ] - - external_deps = [ - "ability_base:zuri", - "ability_runtime:dataobs_manager", - "c_utils:utils", - "hilog:libhilog", - "ipc:ipc_core", - ] -} - -############################################################################### -group("fuzztest") { - testonly = true - deps = [] - deps += [ - # deps file - ":RdbRdUtilsTransferGrdErrnoFuzzTest", - ] -} -############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/corpus/init deleted file mode 100644 index bc977bd9738ee9a70b362067f57a9c63d3adb801..0000000000000000000000000000000000000000 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2022 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. - -FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/project.xml deleted file mode 100644 index 6e8ad2cfde8f8bda4beb6cabbe7efd8bc3c54eec..0000000000000000000000000000000000000000 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/transfergrderrno_fuzzer.h b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/transfergrderrno_fuzzer.h deleted file mode 100644 index 6f11ac7c37f8caff94ee9192adbc67c8d1e419f7..0000000000000000000000000000000000000000 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/transfergrderrno_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2022 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 TRANSFER_GRD_FUZZER_H -#define TRANSFER_GRD_FUZZER_H - -#define FUZZ_PROJECT_NAME "transfergrderrno_fuzzer" - -#endif // TRANSFER_GRD_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/BUILD.gn deleted file mode 100644 index a897d9835ae44c82f9a20f8eab8d8d85a8b142c8..0000000000000000000000000000000000000000 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/BUILD.gn +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (c) 2022 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. - -#####################hydra-fuzz################### -import("//build/config/features.gni") -import("//build/test.gni") -import("//foundation/distributeddatamgr/relational_store/relational_store.gni") - -##############################fuzztest########################################## -ohos_fuzztest("TransferGrdTypeToColTypeFuzzTest") { - module_out_path = "relational_store/relational_store" - - include_dirs = [ - "${relational_store_native_path}/rdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb/include", - "${common_tool_path}/", - "//third_party/sqlite/include", - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", - "${foundation_systemabilitymgr_path}/safwk/services/safwk/include", - "${foundation_systemabilitymgr_path}/samgr/interfaces/innerkits/samgr_proxy/include", - "${base_security_dataclassification_path}/interfaces/innerkits/datatransmitmgr/include", - "//third_party/json/single_include", - "//third_party/googletest/googletest/include/gtest", - ] - - cflags = [ - "-g", - "-O0", - "-Wno-unused-variable", - "-fno-omit-frame-pointer", - ] - - fuzz_config_file = "${relational_store_base_path}/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer" - - sources = [ "transfergrdtypetocoltype_fuzzer.cpp" ] - - deps = [ - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb:distributeddb", - "${distributeddata_base_path}/relational_store/interfaces/inner_api/rdb:native_rdb_static", - "//third_party/jsoncpp:jsoncpp", - ] - - external_deps = [ - "ability_base:zuri", - "ability_runtime:dataobs_manager", - "c_utils:utils", - "hilog:libhilog", - "ipc:ipc_core", - ] -} - -############################################################################### -group("fuzztest") { - testonly = true - deps = [] - deps += [ - # deps file - ":TransferGrdTypeToColTypeFuzzTest", - ] -} -############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/project.xml deleted file mode 100644 index 6e8ad2cfde8f8bda4beb6cabbe7efd8bc3c54eec..0000000000000000000000000000000000000000 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/transfergrdtypetocoltype_fuzzer.h b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/transfergrdtypetocoltype_fuzzer.h deleted file mode 100644 index 6ec5dc5d03685ab632e4426c842ea311f8eb48d0..0000000000000000000000000000000000000000 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/transfergrdtypetocoltype_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2022 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 TRANSFERGRDTYPETOCOLTYPE_FUZZER_H -#define TRANSFERGRDTYPETOCOLTYPE_FUZZER_H - -#define FUZZ_PROJECT_NAME "transfergrdtypetocoltype_fuzzer" - -#endif // TRANSFERGRDTYPETOCOLTYPE_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..6856e78611ec0a1603fecc9072ac6cd252cb8d80 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("rdbsqlutils_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdbsqlutils_fuzzer" + + sources = [ "rdbsqlutils_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":rdbsqlutils_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/rdbsqlutils_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/rdbsqlutils_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d1e1cd2feee2128f0e5a99d4149fb738adfac65 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/rdbsqlutils_fuzzer.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2025 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 "rdbsqlutils_fuzzer.h" + +#include +#include +#include +#include + +#include +#include +#include + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +ConflictResolution GetConflictResolution(FuzzedDataProvider &provider) +{ + int min = static_cast(ConflictResolution::ON_CONFLICT_NONE); + int max = static_cast(ConflictResolution::ON_CONFLICT_REPLACE); + int enumInt = provider.ConsumeIntegralInRange(min, max); + ConflictResolution resolution = static_cast(enumInt); + return resolution; +} + +std::vector ConsumeRandomLengthValueObjectVector(FuzzedDataProvider &provider) +{ + const int loopsMin = 0; + const int loopsMax = 100; + size_t loops = provider.ConsumeIntegralInRange(loopsMin, loopsMax); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t value = provider.ConsumeIntegral(); + ValueObject obj(value); + columns.emplace_back(obj); + } + return columns; +} + +std::vector ConsumeRandomLengthStringVector(FuzzedDataProvider &provider) +{ + const int loopsMin = 0; + const int loopsMax = 100; + size_t loops = provider.ConsumeIntegralInRange(loopsMin, loopsMax); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t length = provider.ConsumeIntegral(); + auto bytes = provider.ConsumeBytes(length); + columns.emplace_back(bytes.begin(), bytes.end()); + } + return columns; +} + +// Fuzz CreateDirectory +void FuzzCreateDirectory(FuzzedDataProvider &provider) +{ + std::string databaseDir = provider.ConsumeRandomLengthString(); + RdbSqlUtils::CreateDirectory(databaseDir); +} + +// Fuzz GetDefaultDatabasePath +void FuzzGetDefaultDatabasePath(FuzzedDataProvider &provider) +{ + std::string baseDir = provider.ConsumeRandomLengthString(); + std::string name = provider.ConsumeRandomLengthString(); + std::string customDir = provider.ConsumeRandomLengthString(); + RdbSqlUtils::GetDefaultDatabasePath(baseDir, name, customDir); +} + +// Fuzz GetCustomDatabasePath +void FuzzGetCustomDatabasePath(FuzzedDataProvider &provider) +{ + std::string rootDir = provider.ConsumeRandomLengthString(); + std::string name = provider.ConsumeRandomLengthString(); + std::string customDir = provider.ConsumeRandomLengthString(); + RdbSqlUtils::GetCustomDatabasePath(rootDir, name, customDir); +} + +// Fuzz GetDefaultDatabasePath with errorCode +void FuzzGetDefaultDatabasePathWithErrorCode(FuzzedDataProvider &provider) +{ + std::string baseDir = provider.ConsumeRandomLengthString(); + std::string name = provider.ConsumeRandomLengthString(); + int errorCode = 0; + RdbSqlUtils::GetDefaultDatabasePath(baseDir, name, errorCode); +} + +// Fuzz BuildQueryString +void FuzzBuildQueryString(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(); + AbsRdbPredicates predicates(table); + std::vector columns = ConsumeRandomLengthStringVector(provider); + RdbSqlUtils::BuildQueryString(predicates, columns); +} + +// Fuzz GetInsertSqlInfo +void FuzzGetInsertSqlInfo(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(); + Row row; + ConflictResolution resolution = GetConflictResolution(provider); + RdbSqlUtils::GetInsertSqlInfo(table, row, resolution); +} + +// Fuzz GetUpdateSqlInfo +void FuzzGetUpdateSqlInfo(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(); + AbsRdbPredicates predicates(table); + Row row; + ConflictResolution resolution = GetConflictResolution(provider); + std::vector returningFields; + RdbSqlUtils::GetUpdateSqlInfo(predicates, row, resolution, returningFields); +} + +// Fuzz GetDeleteSqlInfo +void FuzzGetDeleteSqlInfo(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(); + AbsRdbPredicates predicates(table); + std::vector returningFields; + RdbSqlUtils::GetDeleteSqlInfo(predicates, returningFields); +} + +// Fuzz GetQuerySqlInfo +void FuzzGetQuerySqlInfo(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(); + AbsRdbPredicates predicates(table); + Fields columns = ConsumeRandomLengthStringVector(provider); + RdbSqlUtils::GetQuerySqlInfo(predicates, columns); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::FuzzCreateDirectory(provider); + OHOS::FuzzGetDefaultDatabasePath(provider); + OHOS::FuzzGetCustomDatabasePath(provider); + OHOS::FuzzGetDefaultDatabasePathWithErrorCode(provider); + OHOS::FuzzBuildQueryString(provider); + OHOS::FuzzGetInsertSqlInfo(provider); + OHOS::FuzzGetUpdateSqlInfo(provider); + OHOS::FuzzGetDeleteSqlInfo(provider); + OHOS::FuzzGetQuerySqlInfo(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/rdbsqlutils_fuzzer.h b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/rdbsqlutils_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..6d46e08422baff1345e67ccabdc485c5ca04e73b --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/rdbsqlutils_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 RDBSQLUTILS_FUZZER_H +#define RDBSQLUTILS_FUZZER_H + +#define FUZZ_PROJECT_NAME "rdbsqlutils_fuzzer" + +#endif // RDBSQLUTILS_FUZZER_H diff --git a/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/BUILD.gn index a30acba39bfe7325bce537efff1acc73b52446c7..10a3691279d0b15679403cc5f8430a6475653db5 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/BUILD.gn +++ b/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2025 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 @@ -34,9 +34,17 @@ ohos_fuzztest("RdbStoreFuzzTest") { sources = [ "rdbstore_fuzzer.cpp" ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", "hilog:libhilog", - "relational_store:native_rdb", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", ] } diff --git a/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/corpus/init index bc977bd9738ee9a70b362067f57a9c63d3adb801..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/corpus/init +++ b/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/corpus/init @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2025 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 diff --git a/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/project.xml index 6e8ad2cfde8f8bda4beb6cabbe7efd8bc3c54eec..66e1dcac475475fb101b6f8670ec699e6e9696aa 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/project.xml +++ b/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/project.xml @@ -1,5 +1,5 @@ - + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/returning_fuzzer/returning_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/returning_fuzzer/returning_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..66b4c39cadc5dcbe1659defb1e91abb9beefe6b6 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/returning_fuzzer/returning_fuzzer.cpp @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2025 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 "rdb_errno.h" +#define LOG_TAG "RETURNING_FUZZER" +#include "returning_fuzzer.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "abs_predicates.h" +#include "abs_rdb_predicates.h" +#include "connection_pool.h" +#include "logger.h" +#include "trans_db.h" +#include "value_object.h" +#include "values_buckets.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; + +namespace OHOS { + +static const int MIN_BLOB_SIZE = 1; +static const int MAX_BLOB_SIZE = 200; +static const std::string TABLE_NAME = "test"; +static const std::string DATABASE_NAME = "/data/test/returningFuzz.db"; +static const std::string CREATE_TABLE_SQL = + "CREATE TABLE IF NOT EXISTS test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"; + +class ReturningFuzzTest { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + + static std::shared_ptr store_; +}; + +class RdbTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +std::shared_ptr ReturningFuzzTest::store_ = nullptr; + +int RdbTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_SQL); +} + +int RdbTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void ReturningFuzzTest::SetUpTestCase(void) +{ + int errCode = E_OK; + RdbStoreConfig config(DATABASE_NAME); + config.SetSecurityLevel(SecurityLevel::S3); + config.SetBundleName("com.example.returningfuzz"); + RdbTestOpenCallback helper; + ReturningFuzzTest::store_ = RdbHelper::GetRdbStore(config, 1, helper, errCode); + + if (store_ == nullptr || errCode != E_OK) { + return; + } +} + +void ReturningFuzzTest::TearDownTestCase(void) +{ + if (RdbHelper::DeleteRdbStore(DATABASE_NAME) != E_OK) { + return; + } +} + +std::vector GetColumns(FuzzedDataProvider &provider, int max = 10, int min = 1) +{ + std::vector columns; + int colCount = provider.ConsumeIntegralInRange(min, max); + for (int i = 0; i < colCount; i++) { + columns.push_back(provider.ConsumeRandomLengthString()); + } + return columns; +} + +ValuesBucket MakeRandomBucket(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + size_t strLength = provider.ConsumeIntegralInRange(1, 16); + int fieldCount = provider.ConsumeIntegralInRange(1, 5); + for (int i = 0; i < fieldCount; ++i) { + std::string key = provider.ConsumeRandomLengthString(strLength); + int type = provider.ConsumeIntegralInRange(0, 2); + if (type == 0) { + bucket.Put(key, provider.ConsumeIntegral()); + } else if (type == 1) { + bucket.Put(key, provider.ConsumeRandomLengthString(strLength)); + } else { + int blobSize = provider.ConsumeIntegralInRange(MIN_BLOB_SIZE, MAX_BLOB_SIZE); + std::vector blob = + provider.ConsumeBytes(provider.ConsumeIntegralInRange(0, blobSize)); + bucket.PutBlob(key, blob); + } + } + return bucket; +} + +Transaction::TransactionType GetRandomTransactionType(FuzzedDataProvider &provider) +{ + return provider.PickValueInArray({ + Transaction::DEFERRED, + Transaction::IMMEDIATE, + Transaction::EXCLUSIVE + }); +} + +ConflictResolution GetRandomConflictResolution(FuzzedDataProvider &provider) +{ + return provider.PickValueInArray({ + ConflictResolution::ON_CONFLICT_NONE, + ConflictResolution::ON_CONFLICT_ROLLBACK, + ConflictResolution::ON_CONFLICT_ABORT, + ConflictResolution::ON_CONFLICT_REPLACE, + ConflictResolution::ON_CONFLICT_IGNORE, + ConflictResolution::ON_CONFLICT_FAIL + }); +} + +void BatchInsertReturningFuzz(FuzzedDataProvider &provider, std::shared_ptr store) +{ + std::string valName = provider.ConsumeRandomLengthString(); + int valAge = provider.ConsumeIntegral(); + double valSalary = provider.ConsumeFloatingPoint(); + + ValuesBuckets rows; + ValuesBucket value; + value.PutString("name", valName); + value.PutInt("age", valAge); + value.PutDouble("salary", valSalary); + rows.Put(value); + + size_t blobSize = provider.ConsumeIntegralInRange(MIN_BLOB_SIZE, MAX_BLOB_SIZE); + std::vector blobData = provider.ConsumeBytes(blobSize); + value.PutBlob("blobType", blobData); + + auto resolution = GetRandomConflictResolution(provider); + + auto columns = GetColumns(provider); + auto [codeReturning, result] = store->BatchInsert(TABLE_NAME, rows, columns, resolution); + + auto [ret, trans] = store->CreateTransaction(GetRandomTransactionType(provider)); + + if (ret != E_OK || trans == nullptr) { + LOG_ERROR("Failed to create transaction, error code: %{public}d", ret); + return; + } + + trans->BatchInsert(TABLE_NAME, rows, columns, resolution); + + trans->Commit(); +} + +void UpdateReturningFuzz(FuzzedDataProvider &provider, std::shared_ptr store) +{ + std::string valName = provider.ConsumeRandomLengthString(); + int valAge = provider.ConsumeIntegral(); + double valSalary = provider.ConsumeFloatingPoint(); + + ValuesBucket values; + values.PutString("name", valName); + values.PutInt("age", valAge); + values.PutDouble("salary", valSalary); + + size_t blobSize = provider.ConsumeIntegralInRange(MIN_BLOB_SIZE, MAX_BLOB_SIZE); + std::vector blobData = provider.ConsumeBytes(blobSize); + values.PutBlob("blobType", blobData); + + AbsRdbPredicates predicates(TABLE_NAME); + predicates.EqualTo("name", ValueObject(provider.ConsumeRandomLengthString())); + auto returningFields = GetColumns(provider); + + store->Update(values, predicates, returningFields); + + auto [ret, trans] = store->CreateTransaction(GetRandomTransactionType(provider)); + + if (ret != E_OK || trans == nullptr) { + LOG_ERROR("Failed to create transaction, error code: %{public}d", ret); + return; + } + + AbsRdbPredicates predicates2(TABLE_NAME); + predicates2.EqualTo("name", ValueObject(provider.ConsumeRandomLengthString())); + auto returningFields2 = GetColumns(provider); + + trans->Update(values, predicates2, returningFields2); + trans->Commit(); +} + +void DeleteReturningFuzz(FuzzedDataProvider &provider, std::shared_ptr store) +{ + AbsRdbPredicates predicates(TABLE_NAME); + predicates.EqualTo("name", ValueObject(provider.ConsumeRandomLengthString())); + auto returningFields = GetColumns(provider); + + store->Delete(predicates, returningFields); + + auto [ret, trans] = store->CreateTransaction(GetRandomTransactionType(provider)); + + if (ret != E_OK || trans == nullptr) { + LOG_ERROR("Failed to create transaction, error code: %{public}d", ret); + return; + } + AbsRdbPredicates predicates2(TABLE_NAME); + predicates2.EqualTo("name", ValueObject(provider.ConsumeRandomLengthString())); + auto returningFields2 = GetColumns(provider); + trans->Delete(predicates2, returningFields2); + trans->Rollback(); +} + +void ExecuteExtReturningFuzz(FuzzedDataProvider &provider, std::shared_ptr store) +{ + std::string sql = provider.ConsumeRandomLengthString(); + + std::vector bindArgs; + bindArgs.push_back(ValueObject(provider.ConsumeIntegral())); + bindArgs.push_back(ValueObject(provider.ConsumeRandomLengthString())); + bindArgs.push_back(ValueObject(provider.ConsumeIntegral())); + bindArgs.push_back(ValueObject(provider.ConsumeFloatingPoint())); + + size_t blobSize = provider.ConsumeIntegralInRange(MIN_BLOB_SIZE, MAX_BLOB_SIZE); + std::vector blobData = provider.ConsumeBytes(blobSize); + bindArgs.push_back(ValueObject(blobData)); + + auto returning = provider.PickValueInArray({ + "id", + "name", + "age", + "salary", + }); + + store->ExecuteExt("INSERT INTO test(id, name, age, salary) VALUES (?, ?, ?, ?) returning " + returning, bindArgs); + store->ExecuteExt("UPDATE test set name = ? where name = ? RETURNING " + returning, bindArgs); + store->ExecuteExt("DELETE FROM test where name = ? RETURNING " + returning, bindArgs); + + auto [ret, trans] = store->CreateTransaction(GetRandomTransactionType(provider)); + + if (ret != E_OK || trans == nullptr) { + LOG_ERROR("Failed to create transaction, error code: %{public}d", ret); + return; + } + + trans->ExecuteExt("INSERT INTO test(id, name, age, salary) VALUES (?, ?, ?, ?) returning " + returning, bindArgs); + trans->ExecuteExt("UPDATE test set name = ? where name = ? RETURNING " + returning, bindArgs); + trans->ExecuteExt("DELETE FROM test where name = ? RETURNING " + returning, bindArgs); + trans->Rollback(); +} + +void ValuesBucketFuzz(FuzzedDataProvider &provider) +{ + int rowCount = provider.ConsumeIntegralInRange(0, 10); + std::vector buckets; + for (int i = 0; i < rowCount; ++i) { + buckets.push_back(MakeRandomBucket(provider)); + } + + ValuesBuckets vb1; + ValuesBuckets vb2(buckets); + ValuesBuckets vb3(std::move(buckets)); + + for (int i = 0; i < rowCount; ++i) { + vb1.Put(MakeRandomBucket(provider)); + } + + vb1.RowSize(); + std::string field = provider.ConsumeRandomLengthString(); + vb1.GetFieldsAndValues(); + int32_t size = static_cast(provider.ConsumeIntegral()); + vb1.Reserve(size); + vb1.Clear(); +} + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::ReturningFuzzTest::SetUpTestCase(); + OHOS::BatchInsertReturningFuzz(provider, ReturningFuzzTest::store_); + OHOS::UpdateReturningFuzz(provider, ReturningFuzzTest::store_); + OHOS::DeleteReturningFuzz(provider, ReturningFuzzTest::store_); + OHOS::ExecuteExtReturningFuzz(provider, ReturningFuzzTest::store_); + OHOS::ValuesBucketFuzz(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/returning_fuzzer/returning_fuzzer.h b/relational_store/test/native/rdb/fuzztest/returning_fuzzer/returning_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..c6881a3c61632dab1221467ed85f71d93caa9dde --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/returning_fuzzer/returning_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 RETURNING_FUZZER_H +#define RETURNING_FUZZER_H + +#define FUZZ_PROJECT_NAME "returning_fuzzer" + +#endif // RETURNING_FUZZER_H diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/BUILD.gn similarity index 50% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/BUILD.gn rename to relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/BUILD.gn index 772d2847f081292e39db60ad3cd3a0648ba454af..1664e10f00c5b1aa0364d64d6128895320b2fcfc 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/BUILD.gn +++ b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2025 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 @@ -17,27 +17,12 @@ import("//build/test.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") ##############################fuzztest########################################## -ohos_fuzztest("RddbopenFuzzTest") { +ohos_fuzztest("SharedBlockFuzzTest") { module_out_path = "relational_store/relational_store" include_dirs = [ "${relational_store_native_path}/rdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb/include", - "${common_tool_path}/", - "//third_party/sqlite/include", - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", - "${foundation_systemabilitymgr_path}/safwk/services/safwk/include", - "${foundation_systemabilitymgr_path}/samgr/interfaces/innerkits/samgr_proxy/include", - "${base_security_dataclassification_path}/interfaces/innerkits/datatransmitmgr/include", - "//third_party/json/single_include", - "//third_party/googletest/googletest/include/gtest", + "${relational_store_common_path}/include", ] cflags = [ @@ -47,14 +32,13 @@ ohos_fuzztest("RddbopenFuzzTest") { "-fno-omit-frame-pointer", ] - fuzz_config_file = "${relational_store_base_path}/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer" + fuzz_config_file = "${relational_store_base_path}/test/native/rdb/fuzztest/sharedblock_fuzzer" - sources = [ "rddbopen_fuzzer.cpp" ] + sources = [ "sharedblock_fuzzer.cpp" ] deps = [ - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb:distributeddb", - "${distributeddata_base_path}/relational_store/interfaces/inner_api/rdb:native_rdb_static", - "//third_party/jsoncpp:jsoncpp", + "${relational_store_innerapi_path}/rdb:native_rdb", + "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", ] external_deps = [ @@ -63,6 +47,10 @@ ohos_fuzztest("RddbopenFuzzTest") { "c_utils:utils", "hilog:libhilog", "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", ] } @@ -72,7 +60,7 @@ group("fuzztest") { deps = [] deps += [ # deps file - ":RddbopenFuzzTest", + ":SharedBlockFuzzTest", ] } ############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/sharedblock_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/sharedblock_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d29ad97fe03cfd5f9c805edc12754a65177b407 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/sharedblock_fuzzer.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2025 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 "sharedblock_fuzzer.h" + +#include + +#include "ashmem.h" +#include "rd_statement.h" +#include "rdb_errno.h" +#include "rdb_store_config.h" +#include "rdb_store_impl.h" +#include "refbase.h" +#include "shared_block.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +static const size_t DEFAULT_BLOCK_SIZE = 1 * 1024 * 1024; +static const int MIN_BLOB_SIZE = 1; +static const int MAX_BLOB_SIZE = 200; +namespace OHOS { + +void SharedBlockPutFuzz(std::shared_ptr sharedBlock, FuzzedDataProvider &provider) +{ + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + int64_t value = provider.ConsumeIntegral(); + sharedBlock->PutLong(row, column, value); + } + + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + double value = provider.ConsumeFloatingPoint(); + sharedBlock->PutDouble(row, column, value); + } + + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + size_t size = provider.ConsumeIntegralInRange(MIN_BLOB_SIZE, MAX_BLOB_SIZE); + std::vector value = provider.ConsumeBytes(size); + sharedBlock->PutAsset(row, column, value.data(), value.size()); + } + + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + size_t size = provider.ConsumeIntegralInRange(MIN_BLOB_SIZE, MAX_BLOB_SIZE); + std::vector value = provider.ConsumeBytes(size); + sharedBlock->PutAssets(row, column, value.data(), value.size()); + } + + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + float item = provider.ConsumeFloatingPoint(); + std::vector value; + value.push_back(item); + sharedBlock->PutFloats(row, column, value.data(), value.size()); + } + + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + int value = provider.ConsumeIntegral(); + ValueObject bigIntItem(value); + std::vector bigIntList; + bigIntList.push_back(bigIntItem); + sharedBlock->PutBigInt(row, column, bigIntList.data(), bigIntList.size()); + } +} + +void SharedBlockFuzz(FuzzedDataProvider &provider) +{ + AppDataFwk::SharedBlock *block = nullptr; + std::string sharedBlockName = "SharedBlockFuzzTestBlock"; + auto errcode = AppDataFwk::SharedBlock::Create(sharedBlockName, DEFAULT_BLOCK_SIZE, block); + if (errcode != AppDataFwk::SharedBlock::SHARED_BLOCK_OK) { + return; + } + std::shared_ptr sharedBlock = std::shared_ptr(block); + + // Prepare a dummy CellUnit + AppDataFwk::SharedBlock::CellUnit cellUnit; + cellUnit.type = provider.ConsumeIntegral(); // Arbitrary type + cellUnit.cell.stringOrBlobValue.offset = provider.ConsumeIntegral(); + cellUnit.cell.stringOrBlobValue.size = provider.ConsumeIntegral(); + + uint32_t numColumns = provider.ConsumeIntegral(); + sharedBlock->SetColumnNum(numColumns); + sharedBlock->AllocRow(); + sharedBlock->FreeLastRow(); + + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + size_t blobSize = provider.ConsumeIntegralInRange(MIN_BLOB_SIZE, MAX_BLOB_SIZE); + std::vector blobData = provider.ConsumeBytes(blobSize); + sharedBlock->PutBlob(row, column, blobData.data(), blobData.size()); + } + + { + size_t outSizeIncludingNull = 0; + sharedBlock->GetCellUnitValueString(&cellUnit, &outSizeIncludingNull); + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + std::string value = provider.ConsumeRandomLengthString(); + size_t sizeIncludingNull = provider.ConsumeIntegral(); + sharedBlock->PutString(row, column, value.c_str(), sizeIncludingNull); + } + SharedBlockPutFuzz(sharedBlock, provider); + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + sharedBlock->PutNull(row, column); + } + + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + sharedBlock->GetCellUnit(row, column); + } + // Fuzz GetUsedBytes + sharedBlock->GetUsedBytes(); + + // Fuzz GetCellUnitValueBlob + size_t blobSize = 0; + sharedBlock->GetCellUnitValueBlob(&cellUnit, &blobSize); + + // Fuzz Size + sharedBlock->Size(); + + // Fuzz SetRawData + std::vector remaining_data = provider.ConsumeRemainingBytes(); + sharedBlock->SetRawData(remaining_data.data(), remaining_data.size()); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + /* Run your code on data */ + FuzzedDataProvider provider(data, size); + OHOS::SharedBlockFuzz(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/sharedblock_fuzzer.h b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/sharedblock_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..91a29763304026c2d620e6a764bb634567efacb2 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/sharedblock_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 SHAREDBLOCK_FUZZER_H +#define SHAREDBLOCK_FUZZER_H + +#define FUZZ_PROJECT_NAME "sharedblock_fuzzer" + +#endif // RDSTATEMENT_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..c423d89164248f27bab1be64da08e6ccbed33041 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("storeconfig_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/storeconfig_fuzzer" + + sources = [ "storeconfig_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":storeconfig_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/storeconfig_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/storeconfig_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aff9ab1e4334fb31d28acdcbbe33348e0a80fac6 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/storeconfig_fuzzer.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2025 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 "storeconfig_fuzzer.h" + +#include + +#include + +#include "rdb_store_config.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +void FuzzSetPath(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + std::string path = provider.ConsumeRandomLengthString(); + config.SetPath(path); +} + +void FuzzSetJournalMode(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + JournalMode min = JournalMode::MODE_DELETE; + int intValueMin = static_cast(min); + + JournalMode max = JournalMode::MODE_OFF; + int intValueMax = static_cast(max); + + JournalMode journalMode = static_cast(provider.ConsumeIntegralInRange(intValueMin, intValueMax)); + config.SetJournalMode(journalMode); +} + +void FuzzSetReadOnly(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + bool readOnly = provider.ConsumeBool(); + config.SetReadOnly(readOnly); +} + +void FuzzSetStorageMode(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + StorageMode min = StorageMode::MODE_MEMORY; + int intValueMin = static_cast(min); + + StorageMode max = StorageMode::MODE_DISK; + int intValueMax = static_cast(max); + + StorageMode storageMode = static_cast(provider.ConsumeIntegralInRange(intValueMin, intValueMax)); + config.SetStorageMode(storageMode); +} + +void FuzzSetDatabaseFileType(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + DatabaseFileType min = DatabaseFileType::NORMAL; + int intValueMin = static_cast(min); + + DatabaseFileType max = DatabaseFileType::CORRUPT; + int intValueMax = static_cast(max); + + DatabaseFileType databaseFileType = + static_cast(provider.ConsumeIntegralInRange(intValueMin, intValueMax)); + config.SetDatabaseFileType(databaseFileType); +} + +void FuzzSetSecurityLevel(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + SecurityLevel min = SecurityLevel::S1; + int intValueMin = static_cast(min); + + SecurityLevel max = SecurityLevel::S4; + int intValueMax = static_cast(max); + + SecurityLevel securityLevel = + static_cast(provider.ConsumeIntegralInRange(intValueMin, intValueMax)); + config.SetSecurityLevel(securityLevel); +} + +void FuzzSetCreateNecessary(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + bool isCreateNecessary = provider.ConsumeBool(); + config.SetCreateNecessary(isCreateNecessary); +} + +void FuzzSetTokenizer(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + Tokenizer min = Tokenizer::NONE_TOKENIZER; + int intValueMin = static_cast(min); + + Tokenizer max = Tokenizer::TOKENIZER_END; + int intValueMax = static_cast(max); + + Tokenizer tokenizer = static_cast(provider.ConsumeIntegralInRange(intValueMin, intValueMax)); + config.SetTokenizer(tokenizer); +} + +void FuzzSetEncryptKey(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + const int min = 0; + const int max = 100; + std::vector encryptKey(provider.ConsumeIntegralInRange(min, max)); + config.SetEncryptKey(encryptKey); +} + +void FuzzSetEncryptAlgo(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + EncryptAlgo min = EncryptAlgo::AES_256_GCM; + int intValueMin = static_cast(min); + + EncryptAlgo max = EncryptAlgo::AES_256_CBC; + int intValueMax = static_cast(max); + + EncryptAlgo encryptAlgo = static_cast(provider.ConsumeIntegralInRange(intValueMin, intValueMax)); + config.SetEncryptAlgo(encryptAlgo); +} + +void FuzzSetJournalSize(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + const int min = 1; + const int max = 1024 * 1024; + int journalSize = provider.ConsumeIntegralInRange(min, max); + config.SetJournalSize(journalSize); +} + +void FuzzSetPageSize(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + const int min = 1; + const int max = 4096; + int pageSize = provider.ConsumeIntegralInRange(min, max); + config.SetPageSize(pageSize); +} + +void FuzzSetScalarFunction(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + std::string functionName = provider.ConsumeRandomLengthString(); + const int min = 1; + const int max = 5; + int argc = provider.ConsumeIntegralInRange(min, max); + ScalarFunction function = [](const std::vector &args) -> std::string { + return args.empty() ? "" : args[0]; + }; + config.SetScalarFunction(functionName, argc, function); +} + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + + // Generate random inputs + std::string path = provider.ConsumeRandomLengthString(); + int intValueMin = static_cast(StorageMode::MODE_MEMORY); + int intValueMax = static_cast(StorageMode::MODE_DISK); + StorageMode storageMode = static_cast(provider.ConsumeIntegralInRange(intValueMin, intValueMax)); + bool readOnly = provider.ConsumeBool(); + const int min = 0; + const int max = 100; + std::vector encryptKey(provider.ConsumeIntegralInRange(min, max)); + std::string journalMode = provider.ConsumeRandomLengthString(); + std::string syncMode = provider.ConsumeRandomLengthString(); + std::string databaseFileType = provider.ConsumeRandomLengthString(); + SecurityLevel securityLevel = static_cast( + provider.ConsumeIntegralInRange(static_cast(SecurityLevel::S1), static_cast(SecurityLevel::S4))); + bool isCreateNecessary = provider.ConsumeBool(); + bool autoCheck = provider.ConsumeBool(); + const int journalSizeMin = 1; + const int journalSizeMax = 1024 * 1024; + int journalSize = provider.ConsumeIntegralInRange(journalSizeMin, journalSizeMax); + const int pageSizeMin = 1; + const int pageSizeMax = 1024 * 1024; + int pageSize = provider.ConsumeIntegralInRange(pageSizeMin, pageSizeMax); + + RdbStoreConfig config(path, storageMode, readOnly, encryptKey, journalMode, syncMode, databaseFileType, + securityLevel, isCreateNecessary, autoCheck, journalSize, pageSize); + + // Fuzzing individual methods + OHOS::FuzzSetPath(provider, config); + OHOS::FuzzSetJournalMode(provider, config); + OHOS::FuzzSetReadOnly(provider, config); + OHOS::FuzzSetStorageMode(provider, config); + OHOS::FuzzSetDatabaseFileType(provider, config); + OHOS::FuzzSetSecurityLevel(provider, config); + OHOS::FuzzSetCreateNecessary(provider, config); + OHOS::FuzzSetTokenizer(provider, config); + OHOS::FuzzSetEncryptKey(provider, config); + OHOS::FuzzSetEncryptAlgo(provider, config); + OHOS::FuzzSetJournalSize(provider, config); + OHOS::FuzzSetPageSize(provider, config); + OHOS::FuzzSetScalarFunction(provider, config); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/storeconfig_fuzzer.h b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/storeconfig_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..c8925a7497977a2ec5fc979c0e5b4d479be4f49b --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/storeconfig_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 STORECONFIG_FUZZER_H +#define STORECONFIG_FUZZER_H + +#define FUZZ_PROJECT_NAME "storeconfig_fuzzer" + +#endif // STORECONFIG_FUZZER_H diff --git a/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..8b447b8d4f8af91823fcae94bfc1cb7360805e2a --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/BUILD.gn @@ -0,0 +1,64 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("TransactionFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/transaction_fuzzer" + + sources = [ "transaction_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":TransactionFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/transaction_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/transaction_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bbc2797fa793a8fba5d4023f53da7734f2b647d2 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/transaction_fuzzer.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2025 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 "transaction_fuzzer.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "connection_pool.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "trans_db.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +static const std::string RDB_PATH = "/data/test/transactionFuzzTest.db"; +static const std::string CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, " + "blobType BLOB)"; + +class TransactionTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +int TransactionTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_TEST); +} + +int TransactionTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void TransactionCommitFailFuzzTest(FuzzedDataProvider &provider) +{ + RdbHelper::DeleteRdbStore(RDB_PATH); + RdbStoreConfig config(RDB_PATH); + config.SetHaMode(HAMode::MAIN_REPLICA); + config.SetReadOnly(false); + TransactionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + if (store == nullptr || errCode != E_OK) { + return; + } + + store->Execute("DROP TABLE IF EXISTS test1"); + auto res = store->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)"); + if (res.first != E_OK) { + return; + } + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + if (transaction == nullptr || ret != E_OK) { + return; + } + + Transaction::Row row; + row.Put("id", provider.ConsumeIntegral()); + row.Put("name", provider.ConsumeRandomLengthString()); + auto result = transaction->Insert("test1", row); + const int count = 1; + if (result.first != E_OK || result.second != count) { + return; + } + + // Constructing a Commit Failure Scenario + std::string walFile = RDB_PATH + "-wal"; + + // Disabling wal File Operations + std::string chattrAddiCmd = "chattr +i " + walFile; + system(chattrAddiCmd.c_str()); + + ret = transaction->Commit(); + if (ret == E_OK) { + return; + } + + // Enable the wal file operation. + std::string chattrSubiCmd = "chattr -i " + walFile; + system(chattrSubiCmd.c_str()); + + RdbHelper::DeleteRdbStore(RDB_PATH); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::TransactionCommitFailFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/transaction_fuzzer.h b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/transaction_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..b6a1ea6447de5e8490df49d6b6a3c543bb564dc2 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/transaction_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 TRANSACTION_FUZZER_H +#define TRANSACTION_FUZZER_H + +#define FUZZ_PROJECT_NAME "transaction_fuzzer" + +#endif // TRANSACTION_FUZZER_H diff --git a/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..79a8c13a10e586641f03efd06e95162176146b17 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("TransDBFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/transdb_fuzzer" + + sources = [ "transdb_fuzzer.cpp" ] + + deps = [ + "${relational_store_innerapi_path}/rdb:native_rdb", + "${relational_store_innerapi_path}/rdb:native_rdb_static", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":TransDBFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..44d06ec6fcccfddd3873077401852dc2d8222072 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/corpus/init @@ -0,0 +1 @@ +# Copyright (c) 2025 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. FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/transdb_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/transdb_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0ea460f9295da715c44b86b65912aed617457627 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/transdb_fuzzer.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2025 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 "transdb_fuzzer.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "connection_pool.h" +#include "trans_db.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +static constexpr const char *CREATE_TABLE = "CREATE TABLE IF NOT EXISTS TEST (id INT PRIMARY KEY, name TEXT, " + "extend BLOB, code REAL, years UNLIMITED INT, attachment ASSET, " + "attachments ASSETS)"; +static constexpr const char *DROP_TABLE = "DROP TABLE IF EXISTS TEST"; +static constexpr const char *TABLE_NAME = "TEST"; +static const int MIN_ROWS_SIZE = 1; +static const int MAX_ROWS_SIZE = 50; + +void FillDataToValuesBucket(FuzzedDataProvider &provider, ValuesBucket &value) +{ + std::string valName = provider.ConsumeRandomLengthString(); + int valAge = provider.ConsumeIntegral(); + double valSalary = provider.ConsumeFloatingPoint(); + + value.PutString("name", valName); + value.PutInt("age", valAge); + value.PutDouble("salary", valSalary); +} + +void FillDataToValuesBuckets(FuzzedDataProvider &provider, ValuesBuckets &values) +{ + uint32_t loopTimes = provider.ConsumeIntegralInRange(MIN_ROWS_SIZE, MAX_ROWS_SIZE); + for (uint32_t i = 0; i < loopTimes; i++) { + ValuesBucket value; + FillDataToValuesBucket(provider, value); + values.Put(value); + } +} + +void TransDbExecuteFuzzTest(std::shared_ptr transDB, FuzzedDataProvider &provider) +{ + if (transDB == nullptr) { + return; + } + transDB->Execute(DROP_TABLE); + transDB->Execute(CREATE_TABLE); + std::string sql = provider.ConsumeRandomLengthString(); + transDB->Execute(sql); +} + +ConflictResolution GetConflictResolution(FuzzedDataProvider &provider) +{ + int min = static_cast(ConflictResolution::ON_CONFLICT_NONE); + int max = static_cast(ConflictResolution::ON_CONFLICT_REPLACE); + int enumInt = provider.ConsumeIntegralInRange(min, max); + ConflictResolution resolution = static_cast(enumInt); + return resolution; +} + +void TransDbInsertFuzzTest(std::shared_ptr transDB, FuzzedDataProvider &provider) +{ + if (transDB == nullptr) { + return; + } + ValuesBucket value; + FillDataToValuesBucket(provider, value); + + { + ConflictResolution resolution = GetConflictResolution(provider); + transDB->Insert(TABLE_NAME, value, resolution); + } + + ValuesBuckets rows; + FillDataToValuesBuckets(provider, rows); + transDB->BatchInsert(TABLE_NAME, rows); + + { + ConflictResolution resolution = GetConflictResolution(provider); + transDB->BatchInsert(TABLE_NAME, rows, resolution); + } +} + +void TransDbFuzzTest(FuzzedDataProvider &provider) +{ + std::string path = provider.ConsumeRandomLengthString(); + RdbStoreConfig config(path); + config.SetHaMode(provider.ConsumeIntegral()); + int errCode = 0; + std::shared_ptr connPool = ConnectionPool::Create(config, errCode); + if (connPool == nullptr) { + return; + } + auto [err, conn] = connPool->CreateTransConn(); + if (err != E_OK || conn == nullptr) { + return; + } + std::shared_ptr transDB = std::make_shared(conn, config.GetName()); + if (transDB == nullptr) { + return; + } + TransDbExecuteFuzzTest(transDB, provider); + TransDbInsertFuzzTest(transDB, provider); +} + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::TransDbFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/transdb_fuzzer.h b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/transdb_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..1305c5bda204a70e9000523199ed064d1394e42e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/transdb_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 TRANSDB_FUZZER_H +#define TRANSDB_FUZZER_H + +#define FUZZ_PROJECT_NAME "transdb_fuzzer" + +#endif // TRANSDB_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3900a0996c13f68ba156b4bbcac47b8f441cec06 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("valueobject_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/valueobject_fuzzer" + + sources = [ "valueobject_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":valueobject_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/valueobject_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/valueobject_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f7f524241b1b1dd0b7d5dfc5e2874450d7817cda --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/valueobject_fuzzer.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2025 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 "valueobject_fuzzer.h" + +#include + +#include "value_object.h" + +#define LOOPS_MIN 0 +#define LOOPS_MAX 100 + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +namespace OHOS { +std::vector ConsumeRandomLengthAssetValueVector(FuzzedDataProvider &provider) +{ + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + uint32_t status = provider.ConsumeIntegralInRange( + AssetValue::Status::STATUS_UNKNOWN, AssetValue::Status::STATUS_BUTT); + AssetValue asset{ + .version = provider.ConsumeIntegral(), + .status = status, + .expiresTime = provider.ConsumeIntegral(), + .id = provider.ConsumeRandomLengthString(), + .name = provider.ConsumeRandomLengthString(), + .uri = provider.ConsumeRandomLengthString(), + .createTime = provider.ConsumeRandomLengthString(), + .modifyTime = provider.ConsumeRandomLengthString(), + .size = provider.ConsumeRandomLengthString(), + .hash = provider.ConsumeRandomLengthString(), + .path = provider.ConsumeRandomLengthString(), + }; + columns.emplace_back(asset); + } + return columns; +} + +std::vector ConsumeFloatingPointVector(FuzzedDataProvider &provider) +{ + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + float value = provider.ConsumeFloatingPoint(); + columns.push_back(value); + } + return columns; +} + +void ValueObjectGetIntFuzz(FuzzedDataProvider &provider) +{ + int32_t value = provider.ConsumeIntegral(); + ValueObject obj(value); + int val; + obj.GetInt(val); +} + +void ValueObjectGetLongFuzz(FuzzedDataProvider &provider) +{ + int64_t value = provider.ConsumeIntegral(); + ValueObject obj(value); + int64_t val; + obj.GetLong(val); +} + +void ValueObjectGetDoubleFuzz(FuzzedDataProvider &provider) +{ + double value = provider.ConsumeFloatingPoint(); + ValueObject obj(value); + double val; + obj.GetDouble(val); +} + +void ValueObjectGetBoolFuzz(FuzzedDataProvider &provider) +{ + bool value = provider.ConsumeBool(); + ValueObject obj(value); + bool val; + obj.GetBool(val); +} + +void ValueObjectGetStringFuzz(FuzzedDataProvider &provider) +{ + std::string value = provider.ConsumeRandomLengthString(); + ValueObject obj(value); + std::string val; + obj.GetString(val); +} + +void ValueObjectGetBlobFuzz(FuzzedDataProvider &provider) +{ + size_t length = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector blob = provider.ConsumeBytes(length); + ValueObject obj(blob); + std::vector val; + obj.GetBlob(val); +} + +void ValueObjectGetAssetFuzz(FuzzedDataProvider &provider) +{ + uint32_t status = + provider.ConsumeIntegralInRange(AssetValue::Status::STATUS_UNKNOWN, AssetValue::Status::STATUS_BUTT); + AssetValue asset{ + .version = provider.ConsumeIntegral(), + .status = status, + .expiresTime = provider.ConsumeIntegral(), + .id = provider.ConsumeRandomLengthString(), + .name = provider.ConsumeRandomLengthString(), + .uri = provider.ConsumeRandomLengthString(), + .createTime = provider.ConsumeRandomLengthString(), + .modifyTime = provider.ConsumeRandomLengthString(), + .size = provider.ConsumeRandomLengthString(), + .hash = provider.ConsumeRandomLengthString(), + .path = provider.ConsumeRandomLengthString(), + }; + + ValueObject obj(asset); + AssetValue val; + obj.GetAsset(val); +} + +void ValueObjectGetAssetsFuzz(FuzzedDataProvider &provider) +{ + std::vector assets = ConsumeRandomLengthAssetValueVector(provider); + ValueObject obj(assets); + std::vector val; + obj.GetAssets(val); +} + +void ValueObjectGetVecsFuzz(FuzzedDataProvider &provider) +{ + std::vector vecs = ConsumeFloatingPointVector(provider); + ValueObject obj(vecs); + std::vector val; + obj.GetVecs(val); +} + +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::ValueObjectGetIntFuzz(provider); + OHOS::ValueObjectGetLongFuzz(provider); + OHOS::ValueObjectGetDoubleFuzz(provider); + OHOS::ValueObjectGetBoolFuzz(provider); + OHOS::ValueObjectGetStringFuzz(provider); + OHOS::ValueObjectGetBlobFuzz(provider); + OHOS::ValueObjectGetAssetFuzz(provider); + OHOS::ValueObjectGetAssetsFuzz(provider); + OHOS::ValueObjectGetVecsFuzz(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/valueobject_fuzzer.h b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/valueobject_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..7e51b02bbee204147068933341c03da55f4a0a28 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/valueobject_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 VALUEOBJECT_FUZZER_H +#define VALUEOBJECT_FUZZER_H + +#define FUZZ_PROJECT_NAME "valueobject_fuzzer" + +#endif // VALUEOBJECT_FUZZER_H diff --git a/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..f26360712b43fc00d631cd2dc5da229af87cc6da --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("valuesbucket_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/valuesbucket_fuzzer" + + sources = [ "valuesbucket_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":valuesbucket_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/valuesbucket_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/valuesbucket_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d86ef7351dba53fd652b868f5da8aaaf8670c692 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/valuesbucket_fuzzer.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2025 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 "valuesbucket_fuzzer.h" + +#include + +#include "value_object.h" +#include "values_bucket.h" + + +#define LOOPS_MIN 0 +#define LOOPS_MAX 100 + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +namespace OHOS { + +void ValuesBucketPutStringFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + std::string value = provider.ConsumeRandomLengthString(); + bucket.PutString(columnName, value); +} + +void ValuesBucketPutIntFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + int value = provider.ConsumeIntegral(); + bucket.PutInt(columnName, value); +} + +void ValuesBucketPutLongFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + int64_t value = provider.ConsumeIntegral(); + bucket.PutLong(columnName, value); +} + +void ValuesBucketPutDoubleFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + double value = provider.ConsumeFloatingPoint(); + bucket.PutDouble(columnName, value); +} + +void ValuesBucketPutBoolFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + bool value = provider.ConsumeBool(); + bucket.PutBool(columnName, value); +} + +void ValuesBucketPutBlobFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + size_t length = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector value = provider.ConsumeBytes(length); + bucket.PutBlob(columnName, value); +} + +void ValuesBucketPutNullFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + bucket.PutNull(columnName); +} + +void ValuesBucketPutValueObjectFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + ValueObject value(provider.ConsumeIntegral()); + bucket.Put(columnName, value); +} + +void ValuesBucketPutValueObjectMoveFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + ValueObject value(provider.ConsumeIntegral()); + bucket.Put(columnName, std::move(value)); +} + +void ValuesBucketDeleteFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + bucket.Delete(columnName); +} + +void ValuesBucketGetObjectFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + ValueObject value(provider.ConsumeIntegral()); + bucket.Put(columnName, value); + ValueObject output; + bucket.GetObject(columnName, output); +} + +void ValuesBucketHasColumnFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + bucket.HasColumn(columnName); +} + +void ValuesBucketGetAllFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + ValueObject value(provider.ConsumeIntegral()); + bucket.Put(columnName, value); + std::map output; + bucket.GetAll(output); +} + +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::ValuesBucketPutStringFuzz(provider); + OHOS::ValuesBucketPutIntFuzz(provider); + OHOS::ValuesBucketPutLongFuzz(provider); + OHOS::ValuesBucketPutDoubleFuzz(provider); + OHOS::ValuesBucketPutBoolFuzz(provider); + OHOS::ValuesBucketPutBlobFuzz(provider); + OHOS::ValuesBucketPutNullFuzz(provider); + OHOS::ValuesBucketPutValueObjectFuzz(provider); + OHOS::ValuesBucketPutValueObjectMoveFuzz(provider); + OHOS::ValuesBucketDeleteFuzz(provider); + OHOS::ValuesBucketGetObjectFuzz(provider); + OHOS::ValuesBucketHasColumnFuzz(provider); + OHOS::ValuesBucketGetAllFuzz(provider); + return 0; +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/valuesbucket_fuzzer.h b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/valuesbucket_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..4c598ba9a1d7a46f3c7aa86411e8219aa779a4c9 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/valuesbucket_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 VALUESBUCKET_FUZZER_H +#define VALUESBUCKET_FUZZER_H + +#define FUZZ_PROJECT_NAME "valuesbucket_fuzzer" + +#endif // VALUESBUCKET_FUZZER_H diff --git a/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..eb74a7ac6d1ee4c51bd7e985888a58bacedd04f2 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("valuesbuckets_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/valuesbuckets_fuzzer" + + sources = [ "valuesbuckets_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":valuesbuckets_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/valuesbuckets_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/valuesbuckets_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b85c1c35f18c1c219d68a54c66978b3bd16cc28e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/valuesbuckets_fuzzer.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2025 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 "valuesbuckets_fuzzer.h" + +#include + +#include "value_object.h" +#include "values_bucket.h" +#include "values_buckets.h" + +#define LOOPS_MIN 0 +#define LOOPS_MAX 10 + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +namespace OHOS { + +std::vector ConsumeRandomLengthValueObjectVector(FuzzedDataProvider &provider) +{ + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t value = provider.ConsumeIntegral(); + ValueObject obj(value); + columns.emplace_back(obj); + } + return columns; +} + +std::vector ConsumeRandomLengthStringVector(FuzzedDataProvider &provider) +{ + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t length = provider.ConsumeIntegral(); + auto bytes = provider.ConsumeBytes(length); + columns.emplace_back(bytes.begin(), bytes.end()); + } + return columns; +} + +void ValuesBucketsReserveFuzz(FuzzedDataProvider &provider) +{ + ValuesBuckets buckets; + int32_t size = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + buckets.Reserve(size); +} + +void ValuesBucketsPutFuzz(FuzzedDataProvider &provider) +{ + ValuesBuckets buckets; + std::vector fields = ConsumeRandomLengthStringVector(provider); + std::vector values = ConsumeRandomLengthValueObjectVector(provider); + size_t loopsNum = fields.size(); + if (loopsNum > values.size()) { + loopsNum = values.size(); + } + ValuesBucket bucket; + for (size_t i = 0; i < loopsNum; i++) { + bucket.Put(fields[i], values[i]); + } + buckets.Put(bucket); +} + +void ValuesBucketsGetFuzz(FuzzedDataProvider &provider) +{ + ValuesBuckets buckets; + std::vector fields = ConsumeRandomLengthStringVector(provider); + std::vector values = ConsumeRandomLengthValueObjectVector(provider); + size_t loopsNum = fields.size(); + if (loopsNum > values.size()) { + loopsNum = values.size(); + } + ValuesBucket bucket; + for (size_t i = 0; i < loopsNum; ++i) { + bucket.Put(fields[i], values[i]); + } + buckets.Put(bucket); + size_t row = provider.ConsumeIntegral(); + std::string field = provider.ConsumeRandomLengthString(); + buckets.Get(row, field); +} + +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::ValuesBucketsReserveFuzz(provider); + OHOS::ValuesBucketsPutFuzz(provider); + OHOS::ValuesBucketsGetFuzz(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/valuesbuckets_fuzzer.h b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/valuesbuckets_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..724fa86b9536c93e6bccb0bff55bccb32904589e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/valuesbuckets_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 VALUESBUCKETS_FUZZER_H +#define VALUESBUCKETS_FUZZER_H + +#define FUZZ_PROJECT_NAME "valuesbuckets_fuzzer" + +#endif // VALUESBUCKETS_FUZZER_H diff --git a/relational_store/test/native/rdb/mock/connection_mock.h b/relational_store/test/native/rdb/mock/connection_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..57511a6eba484befebeb08e6c59b0a7d072b5516 --- /dev/null +++ b/relational_store/test/native/rdb/mock/connection_mock.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 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_CONNECTION_MOCK_H +#define OHOS_CONNECTION_MOCK_H + +#include "connection.h" + +namespace DistributedDB { +class StoreObserver; +} +namespace OHOS::NativeRdb { +class RdbStoreConfig; +class Statement; +class MockConnection : public Connection { +public: + using Info = DistributedRdb::RdbDebugInfo; + using SConn = std::shared_ptr; + using Stmt = std::shared_ptr; + using Notifier = std::function; + using Creator = std::pair (*)(const RdbStoreConfig &config, bool isWriter); + using Repairer = int32_t (*)(const RdbStoreConfig &config); + using Deleter = int32_t (*)(const RdbStoreConfig &config); + using Collector = std::map (*)(const RdbStoreConfig &config); + using Restorer = int32_t (*)(const RdbStoreConfig &config, const std::string &srcPath, const std::string &destPath); + using ReplicaChecker = int32_t (*)(const RdbStoreConfig &config); + + MOCK_METHOD(int32_t, VerifyAndRegisterHook, (const RdbStoreConfig &config), (override)); + MOCK_METHOD((std::pair), CreateStatement, (const std::string &sql, SConn conn), (override)); + MOCK_METHOD((std::pair), CreateReplicaStatement, + (const std::string &sql, SConn conn), (override)); + MOCK_METHOD(int, CheckReplicaForRestore, (), (override)); + MOCK_METHOD(int32_t, Rekey, (const RdbStoreConfig::CryptoParam &cryptoParam), (override)); + MOCK_METHOD(int32_t, GetDBType, (), (const, override)); + MOCK_METHOD(bool, IsWriter, (), (const, override)); + MOCK_METHOD(int32_t, ResetKey, (const RdbStoreConfig &config), (override)); + MOCK_METHOD(int32_t, TryCheckPoint, (bool timeout), (override)); + MOCK_METHOD(int32_t, LimitWalSize, (), (override)); + MOCK_METHOD(int32_t, ConfigLocale, (const std::string &localeStr), (override)); + MOCK_METHOD(int32_t, CleanDirtyData, (const std::string &table, uint64_t cursor), (override)); + MOCK_METHOD(int32_t, SubscribeTableChanges, (const Notifier ¬ifier), (override)); + MOCK_METHOD(int32_t, GetMaxVariable, (), (const, override)); + MOCK_METHOD(int32_t, GetJournalMode, (), (override)); + MOCK_METHOD(int32_t, ClearCache, (bool isForceClear), (override)); + MOCK_METHOD(int32_t, Subscribe, (const std::shared_ptr &observer), (override)); + MOCK_METHOD(int32_t, Unsubscribe, (const std::shared_ptr &observer), (override)); + MOCK_METHOD(int32_t, Backup, + (const std::string &databasePath, const std::vector &destEncryptKey, bool isAsync, + std::shared_ptr slaveStatus, bool verifyDb), + (override)); + MOCK_METHOD(int32_t, Restore, + (const std::string &databasePath, const std::vector &destEncryptKey, + std::shared_ptr slaveStatus), + (override)); + MOCK_METHOD(ExchangeStrategy, GenerateExchangeStrategy, (std::shared_ptr status, + bool isReplay), (override)); + MOCK_METHOD(int, SetKnowledgeSchema, (const DistributedRdb::RdbKnowledgeSchema &schema), (override)); + MOCK_METHOD(int, CleanDirtyLog, (const std::string &table, uint64_t cursor), (override)); + MOCK_METHOD(int, RegisterAlgo, (const std::string &clstAlgoName, ClusterAlgoFunc func), (override)); +}; +} // namespace OHOS::NativeRdb +#endif // OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_INCLUDE_CONNECTION_H diff --git a/relational_store/test/native/rdb/mock/dataobs_mgr_client_mock.cpp b/relational_store/test/native/rdb/mock/dataobs_mgr_client_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9b89dd623f51c5a4be3b6c44db74517493189302 --- /dev/null +++ b/relational_store/test/native/rdb/mock/dataobs_mgr_client_mock.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 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 "dataobs_mgr_client_mock.h" + +namespace OHOS { +namespace AAFwk { +std::shared_ptr DataObsMgrClient::GetInstance() +{ + if (IDataObsMgrClient::dataObsMgrClient == nullptr) { + return nullptr; + } + return IDataObsMgrClient::dataObsMgrClient->GetInstance(); +} + +ErrCode DataObsMgrClient::NotifyChange(const Uri &uri, int userId, DataObsOption opt) +{ + if (IDataObsMgrClient::dataObsMgrClient == nullptr) { + return DATAOBS_SERVICE_NOT_CONNECTED; + } + return IDataObsMgrClient::dataObsMgrClient->NotifyChange(uri, userId, opt); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb_device_manager_adapter/include/rdb_device_manager_adapter.h b/relational_store/test/native/rdb/mock/dataobs_mgr_client_mock.h similarity index 42% rename from relational_store/frameworks/native/rdb_device_manager_adapter/include/rdb_device_manager_adapter.h rename to relational_store/test/native/rdb/mock/dataobs_mgr_client_mock.h index 7d0929e4a66bd4cea204f9bb5a1c8507c37502e0..d5835c174bef67a9e23f8aaf1a61e72cb18f49e6 100644 --- a/relational_store/frameworks/native/rdb_device_manager_adapter/include/rdb_device_manager_adapter.h +++ b/relational_store/test/native/rdb/mock/dataobs_mgr_client_mock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * 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 @@ -13,35 +13,29 @@ * limitations under the License. */ -#ifndef RDB_DEVICE_MANAGER_ADAPTER_H -#define RDB_DEVICE_MANAGER_ADAPTER_H +#ifndef OHOS_ABILITY_RUNTIME_DATAOBS_MGR_CLIENT_MOCK_H +#define OHOS_ABILITY_RUNTIME_DATAOBS_MGR_CLIENT_MOCK_H -#include "device_manager.h" -#include "device_manager_callback.h" +#include + +#include "dataobs_mgr_client.h" namespace OHOS { -namespace DeviceManagerAdaptor { -class RdbDeviceManagerAdaptor { +namespace AAFwk { +class IDataObsMgrClient { public: - static RdbDeviceManagerAdaptor &GetInstance(const std::string &packageName); - int GetEncryptedUuidByNetworkId(const std::string &networkId, std::string &uuid); - -private: - RdbDeviceManagerAdaptor(const std::string &packageName); - ~RdbDeviceManagerAdaptor(); + IDataObsMgrClient(){}; + virtual ~IDataObsMgrClient(){}; + virtual ErrCode NotifyChange(const Uri &uri, int32_t userId = -1, DataObsOption opt = DataObsOption()) = 0; + virtual std::shared_ptr GetInstance() = 0; - void Init(); - void UnInit(); - - std::string packageName_; + static inline std::shared_ptr dataObsMgrClient = nullptr; }; - -class InitDeviceManagerCallback final : public DistributedHardware::DmInitCallback { +class MockDataObsMgrClient : public IDataObsMgrClient { public: - InitDeviceManagerCallback() {}; - ~InitDeviceManagerCallback() {}; - void OnRemoteDied() override {}; + MOCK_METHOD((std::shared_ptr), GetInstance, (), (override)); + MOCK_METHOD(ErrCode, NotifyChange, (const Uri &uri, int32_t userId, DataObsOption opt), (override)); }; -} // namespace DeviceManagerAdaptor +} // namespace AAFwk } // namespace OHOS -#endif // RDB_DEVICE_MANAGER_ADAPTER_H +#endif \ No newline at end of file diff --git a/relational_store/test/native/rdb/mock/rdb_manager_impl_mock.cpp b/relational_store/test/native/rdb/mock/rdb_manager_impl_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..708124629b4332c82c8e2f0192037bfe23091e90 --- /dev/null +++ b/relational_store/test/native/rdb/mock/rdb_manager_impl_mock.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 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 "rdb_manager_impl_mock.h" +namespace OHOS::DistributedRdb { + +RdbManagerImpl::RdbManagerImpl() +{ +} + +RdbManagerImpl::~RdbManagerImpl() +{ +} + +RdbManagerImpl &RdbManagerImpl::GetInstance() +{ + static RdbManagerImpl manager; + return manager; +} +std::pair> RdbManagerImpl::GetRdbService(const RdbSyncerParam ¶m) +{ + if (BRdbManagerImpl::rdbManagerImpl == nullptr) { + return { NativeRdb::E_ERROR, nullptr }; + } + return BRdbManagerImpl::rdbManagerImpl->GetRdbService(param); +} +} // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/relational_store/test/native/rdb/mock/rdb_manager_impl_mock.h b/relational_store/test/native/rdb/mock/rdb_manager_impl_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..ec0471852eafad5b886fe7652444eb6a61edcc17 --- /dev/null +++ b/relational_store/test/native/rdb/mock/rdb_manager_impl_mock.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 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 DISTRIBUTED_RDB_RDB_MANAGER_MOCK_H +#define DISTRIBUTED_RDB_RDB_MANAGER_MOCK_H + +#include + +#include "rdb_manager_impl.h" +namespace OHOS::DistributedRdb { +class BRdbManagerImpl { +public: + BRdbManagerImpl() = default; + virtual ~BRdbManagerImpl() = default; + virtual std::pair> GetRdbService(const RdbSyncerParam ¶m) = 0; + +public: + static inline std::shared_ptr rdbManagerImpl = nullptr; +}; +class MockRdbManagerImpl : public BRdbManagerImpl { +public: + MOCK_METHOD( + (std::pair>), GetRdbService, (const RdbSyncerParam ¶m), (override)); +}; +} // namespace OHOS::DistributedRdb +#endif \ No newline at end of file diff --git a/relational_store/test/native/rdb/mock/rdb_service_mock.h b/relational_store/test/native/rdb/mock/rdb_service_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..13952d09b1a7d09bf5b2404ca5b6ede9ed3d0ea7 --- /dev/null +++ b/relational_store/test/native/rdb/mock/rdb_service_mock.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2025 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 DISTRIBUTED_RDB_RDB_SERVICE_MOCK_H +#define DISTRIBUTED_RDB_RDB_SERVICE_MOCK_H + +#include + +#include "iremote_object.h" +#include "rdb_service.h" + +namespace OHOS { +namespace DistributedRdb { +class MockRdbService : public RdbService { +public: + MOCK_METHOD(std::string, ObtainDistributedTableName, + (const RdbSyncerParam ¶m, const std::string &device, const std::string &table), (override)); + MOCK_METHOD(int32_t, SetDistributedTables, + (const RdbSyncerParam ¶m, const std::vector &tables, const std::vector &references, + bool isRebuild, int32_t type), + (override)); + MOCK_METHOD(int32_t, Sync, + (const RdbSyncerParam ¶m, const Option &option, const PredicatesMemo &predicates, const AsyncDetail &async), + (override)); + MOCK_METHOD(int32_t, Subscribe, + (const RdbSyncerParam ¶m, const SubscribeOption &option, std::shared_ptr observer), + (override)); + MOCK_METHOD(int32_t, UnSubscribe, + (const RdbSyncerParam ¶m, const SubscribeOption &option, std::shared_ptr observer), + (override)); + MOCK_METHOD(int32_t, RegisterAutoSyncCallback, + (const RdbSyncerParam ¶m, std::shared_ptr observer), (override)); + MOCK_METHOD(int32_t, UnregisterAutoSyncCallback, + (const RdbSyncerParam ¶m, std::shared_ptr observer), (override)); + MOCK_METHOD((std::pair>), RemoteQuery, + (const RdbSyncerParam ¶m, const std::string &device, const std::string &sql, + const std::vector &selectionArgs), + (override)); + MOCK_METHOD(int32_t, InitNotifier, (const RdbSyncerParam ¶m, sptr notifier), (override)); + + MOCK_METHOD(int32_t, BeforeOpen, (RdbSyncerParam & param), (override)); + + MOCK_METHOD(int32_t, AfterOpen, (const RdbSyncerParam ¶m), (override)); + + MOCK_METHOD(int32_t, Delete, (const RdbSyncerParam ¶m), (override)); + + MOCK_METHOD((std::pair>), QuerySharingResource, + (const RdbSyncerParam ¶m, const PredicatesMemo &predicates, const std::vector &columns), + (override)); + + MOCK_METHOD(int32_t, NotifyDataChange, + (const RdbSyncerParam ¶m, const RdbChangedData &rdbChangedData, const RdbNotifyConfig &rdbNotifyConfig), + (override)); + + MOCK_METHOD(int32_t, SetSearchable, (const RdbSyncerParam ¶m, bool isSearchable), (override)); + + MOCK_METHOD(int32_t, Disable, (const RdbSyncerParam ¶m), (override)); + + MOCK_METHOD(int32_t, Enable, (const RdbSyncerParam ¶m), (override)); + + MOCK_METHOD( + int32_t, GetPassword, (const RdbSyncerParam ¶m, std::vector> &password), (override)); + + MOCK_METHOD((std::pair), LockCloudContainer, (const RdbSyncerParam ¶m), (override)); + + MOCK_METHOD(int32_t, UnlockCloudContainer, (const RdbSyncerParam ¶m), (override)); + + MOCK_METHOD(int32_t, GetDebugInfo, + (const RdbSyncerParam ¶m, (std::map & debugInfo)), (override)); + + MOCK_METHOD(int32_t, GetDfxInfo, (const RdbSyncerParam ¶m, RdbDfxInfo &dfxInfo), (override)); + + MOCK_METHOD(int32_t, VerifyPromiseInfo, (const RdbSyncerParam ¶m), (override)); + + MOCK_METHOD(int32_t, ReportStatistic, (const RdbSyncerParam ¶m, const RdbStatEvent &statEvent), (override)); +}; +} // namespace DistributedRdb +} // namespace OHOS +#endif \ No newline at end of file diff --git a/relational_store/test/native/rdb/mock/statement_mock.h b/relational_store/test/native/rdb/mock/statement_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..966bb9b656438b0c96d289e774f8baccf5834966 --- /dev/null +++ b/relational_store/test/native/rdb/mock/statement_mock.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2025 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_STATEMENT_MOCK_H +#define OHOS_STATEMENT_MOCK_H + +#include + +#include "statement.h" + +namespace OHOS::NativeRdb { +struct SharedBlockInfo; +class MockStatement : public Statement { +public: + MOCK_METHOD(int32_t, Prepare, (const std::string &sql), (override)); + MOCK_METHOD(int32_t, Bind, (const std::vector &args), (override)); + MOCK_METHOD((std::pair), Count, (), (override)); + MOCK_METHOD(int32_t, Step, (), (override)); + MOCK_METHOD(int32_t, Reset, (), (override)); + MOCK_METHOD(int32_t, Finalize, (), (override)); + MOCK_METHOD(int32_t, Execute, (const std::vector &args), (override)); + MOCK_METHOD(int32_t, Execute, (const std::vector> &args), (override)); + MOCK_METHOD((std::pair), ExecuteForValue, (const std::vector &args), (override)); + MOCK_METHOD(int32_t, Changes, (), (const, override)); + MOCK_METHOD(int64_t, LastInsertRowId, (), (const, override)); + MOCK_METHOD(int32_t, GetColumnCount, (), (const, override)); + MOCK_METHOD((std::pair), GetColumnName, (int32_t index), (const, override)); + MOCK_METHOD((std::pair), GetColumnType, (int32_t index), (const, override)); + MOCK_METHOD((std::pair), GetSize, (int32_t index), (const, override)); + MOCK_METHOD((std::pair), GetColumn, (int32_t index), (const, override)); + MOCK_METHOD((std::pair>), GetRows, (uint32_t maxCount), (override)); + MOCK_METHOD(bool, ReadOnly, (), (const, override)); + MOCK_METHOD(bool, SupportBlockInfo, (), (const, override)); + MOCK_METHOD(int32_t, FillBlockInfo, (SharedBlockInfo * info), (const, override)); + MOCK_METHOD(int, ModifyLockStatus, + (const std::string &table, const std::vector> &hashKeys, bool isLock), (override)); +}; +} // namespace OHOS::NativeRdb +#endif // OHOS_STATEMENT_MOCK_H diff --git a/relational_store/test/native/rdb/unittest/connection_test.cpp b/relational_store/test/native/rdb/unittest/connection_test.cpp index dbe45772cee1aba026e08bce601d0d133c35a860..cd33a26e151f11b987cbc4d56760e449642d61ac 100644 --- a/relational_store/test/native/rdb/unittest/connection_test.cpp +++ b/relational_store/test/native/rdb/unittest/connection_test.cpp @@ -20,9 +20,15 @@ #include #include +#include "common.h" #include "grd_type_export.h" #include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "rdb_store.h" #include "rdb_store_config.h" +#include "sqlite_connection.h" +#include "sqlite_global_config.h" using namespace testing::ext; using namespace OHOS::NativeRdb; @@ -32,10 +38,29 @@ class ConnectionTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); - void SetUp(void) {}; - void TearDown(void) {}; + void SetUp(void){}; + void TearDown(void){}; + static const std::string rdbStorePath; }; +const std::string ConnectionTest::rdbStorePath = RDB_TEST_PATH + "connection_ut_test.db"; + +class ConnectionTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +int ConnectionTestOpenCallback::OnCreate(RdbStore &store) +{ + return E_OK; +} + +int ConnectionTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + void ConnectionTest::SetUpTestCase(void) { } @@ -51,7 +76,8 @@ void ConnectionTest::TearDownTestCase(void) */ HWTEST_F(ConnectionTest, Connection_Test_001, TestSize.Level1) { - RdbStoreConfig config("/data/test/connection_ut_test.db"); + SqliteGlobalConfig::InitSqliteGlobalConfig(); + RdbStoreConfig config(rdbStorePath); config.SetDBType(OHOS::NativeRdb::DBType::DB_BUTT); auto [errCode, connection] = Connection::Create(config, true); EXPECT_EQ(errCode, E_INVALID_ARGS); @@ -70,7 +96,7 @@ HWTEST_F(ConnectionTest, Connection_Test_001, TestSize.Level1) */ HWTEST_F(ConnectionTest, Connection_Test_002, TestSize.Level1) { - RdbStoreConfig config("/data/test/connection_ut_test.db"); + RdbStoreConfig config(rdbStorePath); config.SetDBType(OHOS::NativeRdb::DBType::DB_BUTT); int ret = Connection::Repair(config); EXPECT_EQ(ret, E_INVALID_ARGS); @@ -79,4 +105,184 @@ HWTEST_F(ConnectionTest, Connection_Test_002, TestSize.Level1) ret = Connection::Repair(config); EXPECT_EQ(ret, E_NOT_SUPPORT); } + +/** + * @tc.name: SetEncryptAgo_Test_001 + * @tc.desc: The test case is to test whether the param is available. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, SetEncryptAgo_Test_001, TestSize.Level2) +{ + int errCode; + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, true); + config.SetIter(-1); + errCode = conn->SetEncryptAgo(config); + EXPECT_EQ(errCode, E_INVALID_ARGS); +} + +/** + * @tc.name: ResetKey_Test_001 + * @tc.desc: The test case is to test whether ResetKey is a write connection. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, ReSetKey_Test_001, TestSize.Level2) +{ + int errCode; + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, false); + errCode = conn->ResetKey(config); + EXPECT_EQ(errCode, E_OK); +} + +/** + * @tc.name: SetEncrypt_Test_001 + * @tc.desc: The test case is to test whether SetEncrypt is a memory RDB. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, SetEncrypt_Test_001, TestSize.Level2) +{ + int errCode; + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, true); + config.SetEncryptStatus(true); + config.SetStorageMode(StorageMode::MODE_MEMORY); + errCode = conn->SetEncrypt(config); + EXPECT_EQ(errCode, E_NOT_SUPPORT); +} + +/** + * @tc.name: RegDefaultFunctions_Test_001 + * @tc.desc: The testCase of RegDefaultFunctions. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, RegDefaultFunctions_Test_001, TestSize.Level2) +{ + int errCode; + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, true); + errCode = conn->RegDefaultFunctions(nullptr); + EXPECT_EQ(errCode, SQLITE_OK); +} + +/** + * @tc.name: SetTokenizer_Test_001 + * @tc.desc: The testCase of SetTokenizer. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, SetTokenizer_Test_001, TestSize.Level2) +{ + int errCode; + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, true); + config.SetTokenizer(TOKENIZER_END); + errCode = conn->SetTokenizer(config); + EXPECT_EQ(errCode, E_INVALID_ARGS); +} + +/** + * @tc.name: Backup_Test_001 + * @tc.desc: The testCase of Backup. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, Backup_Test_001, TestSize.Level2) +{ + int errCode; + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, true); + std::shared_ptr slaveStatus = std::make_shared(SlaveStatus::BACKING_UP); + errCode = conn->Backup("test", { 1, 2, 3 }, true, slaveStatus); + EXPECT_EQ(errCode, E_OK); + EXPECT_EQ(*slaveStatus, BACKING_UP); +} + +/** + * @tc.name: ExchangeVerify_Test_001 + * @tc.desc: The testCase of ExchangeVerify. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, ExchangeVerify_Test_001, TestSize.Level2) +{ + int errCode; + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, true); + errCode = conn->ExchangeVerify(false); + EXPECT_EQ(errCode, E_ALREADY_CLOSED); +} + +/** + * @tc.name: VeritySlaveIntegrity_Test_001 + * @tc.desc: The testCase of VeritySlaveIntegrity. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, VeritySlaveIntegrity_Test_001, TestSize.Level2) +{ + int errCode; + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, true); + errCode = conn->VeritySlaveIntegrity(); + EXPECT_EQ(errCode, E_ALREADY_CLOSED); +} + +/** + * @tc.name: IsDbVersionBelowSlave_Test_001 + * @tc.desc: The testCase of IsDbVersionBelowSlave. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, IsDbVersionBelowSlave_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, true); + bool res = conn->IsDbVersionBelowSlave(); + EXPECT_EQ(res, false); +} + +/** + * @tc.name: CheckReplicaIntegrity_Test_001 + * @tc.desc: The testCase of CheckReplicaIntegrity. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, CheckReplicaIntegrity_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(rdbStorePath); + config.SetDBType(OHOS::NativeRdb::DBType::DB_BUTT); + EXPECT_EQ(Connection::CheckReplicaIntegrity(config), E_INVALID_ARGS); + + config.SetDBType(OHOS::NativeRdb::DBType::DB_VECTOR); + EXPECT_EQ(Connection::CheckReplicaIntegrity(config), E_NOT_SUPPORT); +} + +/** + * @tc.name: CheckReplicaIntegrity_Test_002 + * @tc.desc: The testCase of CheckReplicaIntegrity. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, CheckReplicaIntegrity_Test_002, TestSize.Level2) +{ + RdbHelper::DeleteRdbStore(rdbStorePath); + RdbStoreConfig config(rdbStorePath); + config.SetDBType(OHOS::NativeRdb::DBType::DB_SQLITE); + config.SetHaMode(HAMode::SINGLE); + EXPECT_EQ(Connection::CheckReplicaIntegrity(config), E_NOT_SUPPORT); + RdbHelper::DeleteRdbStore(rdbStorePath); +} + +static int32_t MockReplicaChecker(const RdbStoreConfig &config) +{ + return E_OK; +} + +/** + * @tc.name: RegisterReplicaChecker_Test_001 + * @tc.desc: The testCase of RegisterReplicaChecker. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, RegisterReplicaChecker_Test_001, TestSize.Level2) +{ + EXPECT_EQ(Connection::RegisterReplicaChecker(OHOS::NativeRdb::DBType::DB_BUTT, nullptr), E_INVALID_ARGS); + EXPECT_EQ(Connection::RegisterReplicaChecker(OHOS::NativeRdb::DBType::DB_VECTOR, MockReplicaChecker), E_OK); + EXPECT_EQ(Connection::RegisterReplicaChecker(OHOS::NativeRdb::DBType::DB_VECTOR, MockReplicaChecker), E_OK); + EXPECT_EQ(Connection::RegisterReplicaChecker(OHOS::NativeRdb::DBType::DB_SQLITE, MockReplicaChecker), E_OK); + EXPECT_EQ(Connection::RegisterReplicaChecker(OHOS::NativeRdb::DBType::DB_SQLITE, MockReplicaChecker), E_OK); +} } // namespace Test \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/delay_actuator_test.cpp b/relational_store/test/native/rdb/unittest/delay_actuator_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4f8049a03a72f0af1541f961c26a442530b1aa41 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/delay_actuator_test.cpp @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2025 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 "delay_actuator.h" +#include "block_data.h" + +#include +using namespace testing::ext; +namespace OHOS::Test { +class DelayActuatorTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +/** +* @tc.name: Execute_001 +* @tc.desc: Execute normally +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(DelayActuatorTest, Execute_001, TestSize.Level0) +{ + auto delayActuator = std::make_shared>(nullptr, ActuatorBase::DEFAULT_MIN_EXECUTE_INTERVAL); + delayActuator->SetExecutorPool(std::make_shared(1, 1)); + auto blockData = std::make_shared>(2, 0); + delayActuator->SetTask([blockData](int data) { + blockData->SetValue(data); + return 0; + }); + delayActuator->Execute(1); + EXPECT_EQ(blockData->GetValue(), 1); +} + +/** +* @tc.name: Execute_002 +* @tc.desc: When triggered once, the Task is executed normally with delayInterval_ delay +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(DelayActuatorTest, Execute_002, TestSize.Level0) +{ + uint32_t firstDelay = 1500; + uint32_t minInterval = 2000; + uint32_t maxInterval = 3000; + auto delayActuator = std::make_shared>(nullptr, firstDelay, minInterval, maxInterval); + delayActuator->SetExecutorPool(std::make_shared(1, 1)); + auto blockData = std::make_shared>(1, 0); + delayActuator->SetTask([blockData](int data) { + blockData->SetValue(data); + return 0; + }); + delayActuator->Execute(1); + EXPECT_EQ(blockData->GetValue(), 0); + EXPECT_EQ(blockData->GetValue(), 1); +} + +/** +* @tc.name: Execute_003 +* @tc.desc: When triggered multiple times, the Task is executed normally with forceInterval_ delay +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(DelayActuatorTest, Execute_003, TestSize.Level0) +{ + uint32_t firstDelay = 200; + uint32_t minInterval = 200; + uint32_t maxInterval = 600; + auto delayActuator = std::make_shared>(nullptr, firstDelay, minInterval, maxInterval); + delayActuator->SetExecutorPool(std::make_shared(1, 1)); + auto blockData = std::make_shared>(0, 0); + delayActuator->SetTask([blockData](int data) { + blockData->SetValue(data); + return 0; + }); + for (int i = 0; i < 5; i++) { + delayActuator->Execute(std::move(i)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + EXPECT_EQ(blockData->GetValue(), 0); + } + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + EXPECT_EQ(blockData->GetValue(), 4); +} + +/** +* @tc.name: Execute_004 +* @tc.desc: Execute task after Defer deconstruction +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(DelayActuatorTest, Execute_004, TestSize.Level0) +{ + auto delayActuator = std::make_shared>(nullptr, ActuatorBase::DEFAULT_MIN_EXECUTE_INTERVAL); + delayActuator->SetExecutorPool(std::make_shared(1, 1)); + auto blockData = std::make_shared>(1, 0); + delayActuator->SetTask([blockData](int data) { + blockData->SetValue(data); + return 0; + }); + { + ActuatorBase::Defer defer(delayActuator); + for (int i = 0; i < 3; i++) { + delayActuator->Execute(std::move(i)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + EXPECT_EQ(blockData->GetValue(), 0); + } + } + EXPECT_EQ(blockData->GetValue(), 2); +} + +/** +* @tc.name: Execute_005 +* @tc.desc: When triggered multiple times, use mergeFunc to merge parameters +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(DelayActuatorTest, Execute_005, TestSize.Level0) +{ + auto delayActuator = std::make_shared>( + [](int& out, int&& input) { + out += input; + }, + 100, 100, 300); + delayActuator->SetExecutorPool(std::make_shared(1, 1)); + auto blockData = std::make_shared>(0, 0); + delayActuator->SetTask([blockData](int data) { + blockData->SetValue(data); + return 0; + }); + for (int i = 0; i < 5; i++) { + delayActuator->Execute(std::move(i)); + EXPECT_EQ(blockData->GetValue(), 0); + } + std::this_thread::sleep_for(std::chrono::milliseconds(300)); + EXPECT_EQ(blockData->GetValue(), 10); +} + +/** +* @tc.name: Execute_006 +* @tc.desc: Testing MergeFunc for complex types +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(DelayActuatorTest, Execute_006, TestSize.Level0) +{ + using DelayActuatorT = DelayActuator>; + auto delayActuator = std::make_shared( + [](auto& out, std::map&& input) { + for (auto& [k, v] : input) { + out[k] += std::move(v); + } + }, + 100); + delayActuator->SetExecutorPool(std::make_shared(1, 1)); + auto blockData = std::make_shared>>(3); + delayActuator->SetTask([blockData](const std::map& data) { + blockData->SetValue(data); + return 0; + }); + std::map data; + int len = 10; + for (int i = 0; i < len; i++) { + data.insert_or_assign(std::to_string(i), "t"); + delayActuator->Execute(std::move(data)); + } + auto val = blockData->GetValue(); + EXPECT_EQ(val.size(), len); + for (auto& [k, v] : val) { + EXPECT_EQ(v, std::string(len--, 't')); + } +} + +/** +* @tc.name: Execute_007 +* @tc.desc: Testing delay of first execution and minimum interval +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(DelayActuatorTest, Execute_007, TestSize.Level0) +{ + uint32_t firstDelay = 50; + uint32_t minInterval = 1500; + uint32_t maxInterval = 5000; + auto delayActuator = std::make_shared>(nullptr, firstDelay, minInterval, maxInterval); + delayActuator->SetExecutorPool(std::make_shared(1, 1)); + auto blockData = std::make_shared>(1, 0); + delayActuator->SetTask([blockData](int data) { + blockData->SetValue(data); + return 0; + }); + delayActuator->Execute(1); + EXPECT_EQ(blockData->GetValue(), 1); + blockData->Clear(0); + delayActuator->Execute(2); + EXPECT_EQ(blockData->GetValue(), 0); + blockData->Clear(0); + EXPECT_EQ(blockData->GetValue(), 2); +} +} // namespace OHOS::Test diff --git a/relational_store/test/native/rdb/unittest/delay_notify_test.cpp b/relational_store/test/native/rdb/unittest/delay_notify_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..23198da3b01757c50b1ad31b132b87cf538e72ec --- /dev/null +++ b/relational_store/test/native/rdb/unittest/delay_notify_test.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2025 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 "DelayNotifyTest" +#include + +#include "logger.h" +#include "common.h" +#include "executor_pool.h" +#include "rdb_helper.h" +#include "rdb_store_impl.h" +#include "delay_notify.h" +#include "block_data.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; +using namespace OHOS::DistributedRdb; +class DelayNotifyTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DelayNotifyTest::SetUpTestCase(void) +{ +} + +void DelayNotifyTest::TearDownTestCase(void) +{ +} + +void DelayNotifyTest::SetUp() +{ +} + +void DelayNotifyTest::TearDown() +{ +} + +/** +* @tc.name: StartTimer_Test_001 +* @tc.desc: Check the normal process of starting the timer. +* @tc.type: FUNC +*/ +HWTEST_F(DelayNotifyTest, StartTimer_Test_001, TestSize.Level1) +{ + auto delayNotifier = std::make_shared(); + delayNotifier->SetExecutorPool(std::make_shared(5, 0)); + auto block = std::make_shared>(1, false); + delayNotifier->SetTask([block](const RdbChangedData &, const RdbNotifyConfig &){ + block->SetValue(true); + return 0; + }); + delayNotifier->isFull_ = true; + delayNotifier->UpdateNotify(RdbChangedData()); + EXPECT_TRUE(block->GetValue()); +} + +/** +* @tc.name: StartTimer_Test_002 +* @tc.desc: Check if the function ExecuteTask() can avoid crashing when the delayNotify is destructed prematurely +* in the main process of starting the timer. +* @tc.type: FUNC +*/ +HWTEST_F(DelayNotifyTest, StartTimer_Test_002, TestSize.Level1) +{ + auto delayNotifier = std::make_shared(); + auto pool = std::make_shared(5, 0); + delayNotifier->SetExecutorPool(pool); + auto block = std::make_shared>(1, false); + delayNotifier->SetTask([block](const RdbChangedData &, const RdbNotifyConfig &){ + block->SetValue(true); + return 0; + }); + delayNotifier->UpdateNotify(RdbChangedData()); + delayNotifier->delaySyncTaskId_ = OHOS::ExecutorPool::INVALID_TASK_ID; + delayNotifier.reset(); + ASSERT_NO_FATAL_FAILURE(EXPECT_FALSE(block->GetValue())); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/dynamic_load_test/BUILD.gn b/relational_store/test/native/rdb/unittest/dynamic_load_test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..f08d43e09e616a292f259910a1912360422360f0 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/dynamic_load_test/BUILD.gn @@ -0,0 +1,151 @@ +# Copyright (c) 2025 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/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +module_output_path = "relational_store/relational_store/native_rdb" + +############################################################################### +config("module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${relational_store_mock_path}/frameworks/native/rdb/common", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", + "${relational_store_native_path}/rdb/src", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_native_path}/rdb_crypt", + "${relational_store_native_path}/rdb_device_manager_adapter/include", + "${relational_store_base_path}/test/native/rdb/unittest", + ] + + defines = [ + "RELATIONAL_STORE", + ] +} + +ohos_unittest("DynamicLoadTest") { + module_out_path = module_output_path + + cflags = [ + "-fno-access-control", # Ignore Private Member Access Control + ] + + sources = [ "dynamic_load_test.cpp" ] + + sources += [ + "${relational_store_native_path}/rdb/src/rdb_manager_impl.cpp", + "${relational_store_native_path}/dfx/src/rdb_radar_reporter.cpp", + "${relational_store_native_path}/dfx/src/rdb_stat_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_fault_hiview_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_time_utils.cpp", + "${relational_store_native_path}/rdb/src/abs_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_result_set.cpp", + "${relational_store_native_path}/rdb/src/abs_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/base_transaction.cpp", + "${relational_store_native_path}/rdb/src/big_integer.cpp", + "${relational_store_native_path}/rdb/src/cache_result_set.cpp", + "${relational_store_native_path}/rdb/src/connection.cpp", + "${relational_store_native_path}/rdb/src/connection_pool.cpp", + "${relational_store_native_path}/rdb/src/delay_notify.cpp", + "${relational_store_native_path}/rdb/src/grd_api_manager.cpp", + "${relational_store_native_path}/rdb/src/global_resource.cpp", + "${relational_store_native_path}/rdb/src/knowledge_schema_helper.cpp", + "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", + "${relational_store_native_path}/rdb/src/rd_connection.cpp", + "${relational_store_native_path}/rdb/src/rd_statement.cpp", + "${relational_store_native_path}/rdb/src/rd_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_helper.cpp", + "${relational_store_native_path}/rdb/src/rdb_icu_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_local_db_observer.cpp", + "${relational_store_native_path}/rdb/src/rdb_notifier_stub.cpp", + "${relational_store_native_path}/rdb/src/rdb_obs_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_perfStat.cpp", + "${relational_store_native_path}/rdb/src/rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_service_proxy.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_log.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_statistic.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_store.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_impl.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_types_util.cpp", + "${relational_store_native_path}/rdb/src/result_set_proxy.cpp", + "${relational_store_native_path}/rdb/src/security_policy.cpp", + "${relational_store_native_path}/rdb/src/share_block.cpp", + "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", + "${relational_store_native_path}/rdb/src/sqlite_connection.cpp", + "${relational_store_native_path}/rdb/src/sqlite_default_function.cpp", + "${relational_store_native_path}/rdb/src/sqlite_global_config.cpp", + "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/sqlite_sql_builder.cpp", + "${relational_store_native_path}/rdb/src/sqlite_statement.cpp", + "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", + "${relational_store_native_path}/rdb/src/step_result_set.cpp", + "${relational_store_native_path}/rdb/src/string_utils.cpp", + "${relational_store_native_path}/rdb/src/suspender.cpp", + "${relational_store_native_path}/rdb/src/task_executor.cpp", + "${relational_store_native_path}/rdb/src/trans_db.cpp", + "${relational_store_native_path}/rdb/src/transaction.cpp", + "${relational_store_native_path}/rdb/src/transaction_impl.cpp", + "${relational_store_native_path}/rdb/src/value_object.cpp", + "${relational_store_native_path}/rdb/src/values_bucket.cpp", + "${relational_store_native_path}/rdb/src/values_buckets.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "c_utils:utils", + "file_api:securitylabel", + "googletest:gmock", + "googletest:gtest", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "huks:libhukssdk", + "ipc:ipc_core", + "ipc:ipc_single", + "json:nlohmann_json_static", + "kv_store:database_utils", + "kv_store:datamgr_common", + "kv_store:distributeddata_inner", + "kv_store:distributeddb_client", + "samgr:samgr_proxy", + "sqlite:sqlite", + "sqlite:sqliteicu", + ] + + deps = [ + "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", + "${relational_store_innerapi_path}/appdatafwk:relational_common_base", + ] +} + +############################################################################### +group("unittest") { + testonly = true + + deps = [ ":DynamicLoadTest" ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/unittest/dynamic_load_test/dynamic_load_test.cpp b/relational_store/test/native/rdb/unittest/dynamic_load_test/dynamic_load_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ce1e527c219d6b6f40296ae1489eac9afe31f80a --- /dev/null +++ b/relational_store/test/native/rdb/unittest/dynamic_load_test/dynamic_load_test.cpp @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2025 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 + +#include "block_data.h" +#include "global_resource.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_manager_impl.h" +#include "rdb_open_callback.h" +#include "rdb_store_impl.h" +#include "rdb_store_manager.h" +#include "sqlite_connection.h" +#include "task_executor.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::DistributedRdb; +const std::string RDB_TEST_PATH = "/data/test/"; +class OpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override + { + return E_OK; + } + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override + { + return E_OK; + } +}; + +class RdbDynamicLoadTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void RdbDynamicLoadTest::SetUpTestCase(void) +{ +} + +void RdbDynamicLoadTest::TearDownTestCase(void) +{ +} + +void RdbDynamicLoadTest::SetUp(void) +{ +} + +void RdbDynamicLoadTest::TearDown(void) +{ +} + +class RdbDynamicLoadTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string CREATE_TABLE_TEST; +}; +const std::string RdbDynamicLoadTestOpenCallback::CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, " + "blobType BLOB)"; + +int RdbDynamicLoadTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_TEST); +} + +int RdbDynamicLoadTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +/** + * @tc.name: DynamicLoading001 + * @tc.desc: Dynamic loading test + * @tc.type: FUNC + */ +HWTEST_F(RdbDynamicLoadTest, DynamicLoading001, TestSize.Level1) +{ + EXPECT_TRUE(RdbHelper::Init()); + + const std::string dbPath = RDB_TEST_PATH + "DynamicLoading.db"; + RdbStoreConfig config(dbPath); + config.SetBundleName("com.ohos.config.DynamicLoading"); + int errCode = E_ERROR; + RdbDynamicLoadTestOpenCallback helper; + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(rdbStore, nullptr); + + EXPECT_FALSE(RdbStoreManager::GetInstance().storeCache_.empty()); + EXPECT_NE(RdbManagerImpl::GetInstance().distributedDataMgr_, nullptr); + EXPECT_NE(RdbManagerImpl::GetInstance().rdbService_, nullptr); + EXPECT_NE(TaskExecutor::GetInstance().pool_, nullptr); + rdbStore = nullptr; + EXPECT_TRUE(RdbHelper::Destroy()); + + EXPECT_TRUE(RdbStoreManager::GetInstance().storeCache_.empty()); + EXPECT_EQ(RdbManagerImpl::GetInstance().distributedDataMgr_, nullptr); + EXPECT_EQ(RdbManagerImpl::GetInstance().rdbService_, nullptr); + EXPECT_EQ(TaskExecutor::GetInstance().pool_, nullptr); + EXPECT_TRUE(RdbHelper::Init()); + EXPECT_NE(TaskExecutor::GetInstance().pool_, nullptr); +} + +/** + * @tc.name: DynamicLoading002 + * @tc.desc: Dynamic loading test + * @tc.type: FUNC + */ +HWTEST_F(RdbDynamicLoadTest, DynamicLoading002, TestSize.Level1) +{ + EXPECT_TRUE(RdbHelper::Init()); + + const std::string dbPath = RDB_TEST_PATH + "DynamicLoading.db"; + RdbStoreConfig config(dbPath); + config.SetBundleName("com.ohos.config.DynamicLoading"); + int errCode = E_ERROR; + RdbDynamicLoadTestOpenCallback helper; + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(rdbStore, nullptr); + + EXPECT_FALSE(RdbStoreManager::GetInstance().storeCache_.empty()); + EXPECT_NE(RdbManagerImpl::GetInstance().distributedDataMgr_, nullptr); + EXPECT_NE(RdbManagerImpl::GetInstance().rdbService_, nullptr); + EXPECT_NE(TaskExecutor::GetInstance().pool_, nullptr); + OHOS::NativeRdb::RdbHelper::DestroyOption destroyOption; + destroyOption.cleanICU = true; + rdbStore = nullptr; + EXPECT_TRUE(RdbHelper::Destroy(destroyOption)); + + EXPECT_TRUE(RdbStoreManager::GetInstance().storeCache_.empty()); + EXPECT_EQ(RdbManagerImpl::GetInstance().distributedDataMgr_, nullptr); + EXPECT_EQ(RdbManagerImpl::GetInstance().rdbService_, nullptr); + EXPECT_EQ(TaskExecutor::GetInstance().pool_, nullptr); +} + +/** + * @tc.name: ObsManger001 + * @tc.desc: Destroy when the subscription is not cancelled + * @tc.type: FUNC + */ +HWTEST_F(RdbDynamicLoadTest, ObsManger001, TestSize.Level1) +{ + const std::string dbPath = RDB_TEST_PATH + "ObsManger001.db"; + RdbStoreConfig config(dbPath); + config.SetBundleName("com.ohos.config.DynamicLoading"); + int errCode = E_ERROR; + RdbDynamicLoadTestOpenCallback helper; + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(rdbStore, nullptr); + std::shared_ptr autoRelease = + std::shared_ptr("ObsManger001", [config](const char *) { RdbHelper::DeleteRdbStore(config); }); + std::shared_ptr observer; + auto status = rdbStore->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer" }, observer); + EXPECT_EQ(status, E_OK); + ASSERT_NO_FATAL_FAILURE(EXPECT_FALSE(RdbHelper::Destroy())); + ASSERT_NO_FATAL_FAILURE(EXPECT_FALSE(RdbHelper::Destroy())); + rdbStore = nullptr; + ASSERT_NO_FATAL_FAILURE(EXPECT_TRUE(RdbHelper::Destroy())); + auto rdbStoreNew = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(rdbStore, rdbStoreNew); +} + +/** + * @tc.name: ObsManger002 + * @tc.desc: Destroy after the database is closed + * @tc.type: FUNC + */ +HWTEST_F(RdbDynamicLoadTest, ObsManger002, TestSize.Level1) +{ + const std::string dbPath = RDB_TEST_PATH + "ObsManger002.db"; + RdbStoreConfig config(dbPath); + config.SetBundleName("com.ohos.config.DynamicLoading"); + int errCode = E_ERROR; + RdbDynamicLoadTestOpenCallback helper; + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(rdbStore, nullptr); + std::shared_ptr autoRelease = + std::shared_ptr("ObsManger002", [config](const char *) { RdbHelper::DeleteRdbStore(config); }); + std::shared_ptr observer; + auto status = rdbStore->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer" }, observer); + EXPECT_EQ(status, E_OK); + rdbStore = nullptr; + ASSERT_NO_FATAL_FAILURE(EXPECT_TRUE(RdbHelper::Destroy())); +} + +/** + * @tc.name: ICUManager001 + * @tc.desc: Destroy ICU + * @tc.type: FUNC + */ +HWTEST_F(RdbDynamicLoadTest, ICUManager001, TestSize.Level1) +{ + const std::string dbPath = RDB_TEST_PATH + "ICUManager001.db"; + RdbStoreConfig config(dbPath); + config.SetBundleName("com.ohos.config.DynamicLoading"); + int errCode = E_ERROR; + RdbDynamicLoadTestOpenCallback helper; + config.SetCollatorLocales("zh_CN"); + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(rdbStore, nullptr); + std::shared_ptr autoRelease = + std::shared_ptr("ICUManager001", [config](const char *) { RdbHelper::DeleteRdbStore(config); }); + rdbStore->ExecuteSql("CREATE TABLE ICUManager (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, " + "data2 INTEGER);"); + int64_t id; + ValuesBucket valuesBucket; + valuesBucket.PutString("data1", "张三"); + valuesBucket.PutInt("data2", 20); + errCode = rdbStore->Insert(id, "ICUManager", valuesBucket); + EXPECT_EQ(errCode, E_OK); + rdbStore = nullptr; + RdbHelper::DestroyOption option; + option.cleanICU = true; + ASSERT_NO_FATAL_FAILURE(EXPECT_TRUE(RdbHelper::Destroy(option))); +} + +using CheckOnChangeFunc = std::function; +class SubObserver : public RdbStoreObserver { +public: + virtual ~SubObserver() + { + } + void OnChange(const std::vector &devices) override + { + } + void OnChange(const Origin &origin, const PrimaryFields &fields, RdbStoreObserver::ChangeInfo &&info) override; + void OnChange() override + { + } + void RegisterCallback(const CheckOnChangeFunc &callback); + +private: + CheckOnChangeFunc checkOnChangeFunc_; +}; + +void SubObserver::OnChange(const Origin &origin, const PrimaryFields &fields, RdbStoreObserver::ChangeInfo &&info) +{ + if (checkOnChangeFunc_) { + checkOnChangeFunc_(info); + } +} + +void SubObserver::RegisterCallback(const CheckOnChangeFunc &callback) +{ + checkOnChangeFunc_ = callback; +} + +/** + * @tc.name: DbClient001 + * @tc.desc: Destroy DbClient + * @tc.type: FUNC + */ +HWTEST_F(RdbDynamicLoadTest, DbClient001, TestSize.Level1) +{ + const std::string dbPath = RDB_TEST_PATH + "DbClient001.db"; + RdbStoreConfig config(dbPath); + config.SetBundleName("com.ohos.config.DynamicLoading"); + int errCode = E_ERROR; + RdbDynamicLoadTestOpenCallback helper; + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(rdbStore, nullptr); + std::shared_ptr autoRelease = + std::shared_ptr("DbClient001", [config](const char *) { RdbHelper::DeleteRdbStore(config); }); + auto obs = std::make_shared(); + auto flag = std::make_shared>(false, 3); + obs->RegisterCallback([flag](RdbStoreObserver::ChangeInfo &changeInfo) { + flag->SetValue(true); + return; + }); + errCode = rdbStore->Subscribe({ SubscribeMode::LOCAL_DETAIL }, obs); + EXPECT_EQ(errCode, E_OK); + int64_t id; + ValuesBucket valuesBucket; + valuesBucket.PutString("name", "bob"); + valuesBucket.PutInt("age", 20); + errCode = rdbStore->Insert(id, "test", valuesBucket); + EXPECT_EQ(errCode, E_OK); + EXPECT_EQ(flag->GetValue(), true); + rdbStore = nullptr; + ASSERT_NO_FATAL_FAILURE(EXPECT_TRUE(RdbHelper::Destroy())); +} + +/** + * @tc.name: OpenSSL001 + * @tc.desc: Destroy OpenSSL + * @tc.type: FUNC + */ +HWTEST_F(RdbDynamicLoadTest, OpenSSL001, TestSize.Level1) +{ + const std::string dbPath = RDB_TEST_PATH + "OpenSSL001.db"; + RdbStoreConfig config(dbPath); + config.SetBundleName("com.ohos.config.DynamicLoading"); + config.SetEncryptStatus(true); + int errCode = E_ERROR; + RdbDynamicLoadTestOpenCallback helper; + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(rdbStore, nullptr); + std::shared_ptr autoRelease = + std::shared_ptr("OpenSSL001", [config](const char *) { RdbHelper::DeleteRdbStore(config); }); + int64_t id; + ValuesBucket valuesBucket; + valuesBucket.PutString("name", "bob"); + valuesBucket.PutInt("age", 20); + errCode = rdbStore->Insert(id, "test", valuesBucket); + EXPECT_EQ(errCode, E_OK); + rdbStore = nullptr; + RdbHelper::DestroyOption option; + option.cleanOpenSSL = true; + ASSERT_NO_FATAL_FAILURE(EXPECT_TRUE(RdbHelper::Destroy(option))); +} + +/** + * @tc.name: GlobalResource001 + * @tc.desc: GlobalResource CleanUp invalid args + * @tc.type: FUNC + */ +HWTEST_F(RdbDynamicLoadTest, GlobalResource001, TestSize.Level1) +{ + EXPECT_EQ(GlobalResource::CleanUp(-1), E_INVALID_ARGS); + EXPECT_EQ(GlobalResource::CleanUp(GlobalResource::CLEAN_BUTT), E_INVALID_ARGS); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/mock_obs_manage_test/BUILD.gn b/relational_store/test/native/rdb/unittest/mock_obs_manage_test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..630cc7535bfc14616f52d6f3823fe2d31395d976 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/mock_obs_manage_test/BUILD.gn @@ -0,0 +1,156 @@ +# Copyright (c) 2025 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/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +module_output_path = "relational_store/relational_store/native_rdb" + +############################################################################### +config("module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${relational_store_mock_path}/frameworks/native/rdb/common", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", + "${relational_store_native_path}/rdb_crypt", + "${relational_store_native_path}/rdb/src", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_native_path}/rdb_device_manager_adapter/include", + "${relational_store_base_path}/test/native/rdb/unittest", + ] + + defines = [ + "RELATIONAL_STORE", + ] +} + +base_sources = [ + "${relational_store_native_path}/rdb/src/rdb_manager_impl.cpp", + "${relational_store_native_path}/dfx/src/rdb_radar_reporter.cpp", + "${relational_store_native_path}/dfx/src/rdb_stat_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_fault_hiview_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_time_utils.cpp", + "${relational_store_native_path}/rdb/src/abs_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_result_set.cpp", + "${relational_store_native_path}/rdb/src/abs_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/base_transaction.cpp", + "${relational_store_native_path}/rdb/src/big_integer.cpp", + "${relational_store_native_path}/rdb/src/cache_result_set.cpp", + "${relational_store_native_path}/rdb/src/connection.cpp", + "${relational_store_native_path}/rdb/src/connection_pool.cpp", + "${relational_store_native_path}/rdb/src/delay_notify.cpp", + "${relational_store_native_path}/rdb/src/grd_api_manager.cpp", + "${relational_store_native_path}/rdb/src/knowledge_schema_helper.cpp", + "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", + "${relational_store_native_path}/rdb/src/rd_connection.cpp", + "${relational_store_native_path}/rdb/src/rd_statement.cpp", + "${relational_store_native_path}/rdb/src/rd_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_helper.cpp", + "${relational_store_native_path}/rdb/src/rdb_icu_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_local_db_observer.cpp", + "${relational_store_native_path}/rdb/src/rdb_notifier_stub.cpp", + "${relational_store_native_path}/rdb/src/rdb_obs_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_perfStat.cpp", + "${relational_store_native_path}/rdb/src/rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_service_proxy.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_log.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_statistic.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_store.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_impl.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_types_util.cpp", + "${relational_store_native_path}/rdb/src/result_set_proxy.cpp", + "${relational_store_native_path}/rdb/src/security_policy.cpp", + "${relational_store_native_path}/rdb/src/share_block.cpp", + "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", + "${relational_store_native_path}/rdb/src/sqlite_connection.cpp", + "${relational_store_native_path}/rdb/src/sqlite_default_function.cpp", + "${relational_store_native_path}/rdb/src/sqlite_global_config.cpp", + "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/sqlite_sql_builder.cpp", + "${relational_store_native_path}/rdb/src/sqlite_statement.cpp", + "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", + "${relational_store_native_path}/rdb/src/step_result_set.cpp", + "${relational_store_native_path}/rdb/src/string_utils.cpp", + "${relational_store_native_path}/rdb/src/suspender.cpp", + "${relational_store_native_path}/rdb/src/task_executor.cpp", + "${relational_store_native_path}/rdb/src/trans_db.cpp", + "${relational_store_native_path}/rdb/src/transaction.cpp", + "${relational_store_native_path}/rdb/src/transaction_impl.cpp", + "${relational_store_native_path}/rdb/src/value_object.cpp", + "${relational_store_native_path}/rdb/src/values_bucket.cpp", + "${relational_store_native_path}/rdb/src/values_buckets.cpp", +] + +ohos_unittest("GlobalResourceTest") { + module_out_path = module_output_path + + cflags = [ + "-fno-access-control", # Ignore Private Member Access Control + ] + + sources = base_sources + + sources += [ + "global_resource_test.cpp", + "mock_global_resource.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "c_utils:utils", + "file_api:securitylabel", + "googletest:gmock", + "googletest:gtest", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "huks:libhukssdk", + "ipc:ipc_core", + "ipc:ipc_single", + "json:nlohmann_json_static", + "kv_store:database_utils", + "kv_store:datamgr_common", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "samgr:samgr_proxy", + "sqlite:sqlite", + "sqlite:sqliteicu", + ] + + deps = [ + "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", + "${relational_store_innerapi_path}/appdatafwk:relational_common_base", + ] +} + +############################################################################### +group("unittest") { + testonly = true + + deps = [ ":GlobalResourceTest" ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/unittest/mock_obs_manage_test/global_resource_test.cpp b/relational_store/test/native/rdb/unittest/mock_obs_manage_test/global_resource_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e09b364b55eda64f2ee263393c5e8e181ca03914 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/mock_obs_manage_test/global_resource_test.cpp @@ -0,0 +1,66 @@ +/* +* Copyright (c) 2025 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 + +#include "rdb_helper.h" + +#include "mock_global_resource.h" + +using namespace testing::ext; +using namespace testing; +using namespace OHOS::NativeRdb; + +class GlobalResourceTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline std::shared_ptr mockGlobalResource; +}; + +void GlobalResourceTest::SetUpTestCase(void) +{ + mockGlobalResource = std::make_shared(); +} + +void GlobalResourceTest::TearDownTestCase(void) +{ + mockGlobalResource = nullptr; +} + +void GlobalResourceTest::SetUp() +{ +} + +void GlobalResourceTest::TearDown() +{ +} + +/** +* @tc.name: GlobalResourceTest_CleanUp01 +* @tc.desc: No Mock All Symbols +* @tc.type: FUNC +*/ +HWTEST_F(GlobalResourceTest, GlobalResourceTest_CleanUp01, TestSize.Level2) +{ + EXPECT_CALL(*mockGlobalResource, CleanUp(_)).WillRepeatedly(Return(E_ERROR)); + OHOS::NativeRdb::RdbHelper::DestroyOption destroyOption; + destroyOption.cleanICU = true; + destroyOption.cleanOpenSSL = true; + EXPECT_FALSE(RdbHelper::Destroy(destroyOption)); +} diff --git a/relational_store/test/native/rdb/unittest/mock_obs_manage_test/mock_global_resource.cpp b/relational_store/test/native/rdb/unittest/mock_obs_manage_test/mock_global_resource.cpp new file mode 100644 index 0000000000000000000000000000000000000000..31891508d59296258477520b748b7a5b317dee6f --- /dev/null +++ b/relational_store/test/native/rdb/unittest/mock_obs_manage_test/mock_global_resource.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 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 "mock_global_resource.h" +#include "rdb_errno.h" +namespace OHOS::NativeRdb { + +int32_t GlobalResource::CleanUp(int32_t type) +{ + if (BGlobalResource::globalResource_ == nullptr) { + return NativeRdb::E_ERROR; + } + return BGlobalResource::globalResource_->CleanUp(type); +} + +int32_t GlobalResource::RegisterClean(GlobalResource::CleanType type, GlobalResource::Cleaner clean) +{ + if (BGlobalResource::globalResource_ == nullptr) { + return NativeRdb::E_ERROR; + } + return BGlobalResource::globalResource_->RegisterClean(type, clean); +} +} // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/mock_obs_manage_test/mock_global_resource.h b/relational_store/test/native/rdb/unittest/mock_obs_manage_test/mock_global_resource.h new file mode 100644 index 0000000000000000000000000000000000000000..aa739184115cd4bd64ba8f57dc4b96fb5544b3c2 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/mock_obs_manage_test/mock_global_resource.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 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 DISTRIBUTED_GLOBAL_RESOURCE_MOCK_H +#define DISTRIBUTED_GLOBAL_RESOURCE_MOCK_H + +#include + +#include "global_resource.h" +namespace OHOS::NativeRdb { +class BGlobalResource { +public: + BGlobalResource() = default; + virtual ~BGlobalResource() = default; + virtual int32_t CleanUp(int32_t type) = 0; + virtual int32_t RegisterClean(GlobalResource::CleanType type, GlobalResource::Cleaner clean) = 0; + +public: + static inline std::shared_ptr globalResource_ = nullptr; +}; + +class MockGlobalResource : public BGlobalResource { +public: + MOCK_METHOD(int32_t, CleanUp, (int32_t type), (override)); + MOCK_METHOD(int32_t, RegisterClean, + (GlobalResource::CleanType type, GlobalResource::Cleaner clean), (override)); +}; +} // namespace OHOS::NativeRdb +#endif \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/mockservice/BUILD.gn b/relational_store/test/native/rdb/unittest/mockservice/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..fb0732b53f1752dc2dfcf3c0dede867fd87766f5 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/mockservice/BUILD.gn @@ -0,0 +1,154 @@ +# Copyright (c) 2025 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/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +module_output_path = "relational_store/relational_store/native_rdb" + +############################################################################### +config("module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", + "${relational_store_native_path}/rdb/src", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_native_path}/rdb_crypt", + "${relational_store_native_path}/rdb_device_manager_adapter/include", + "${relational_store_base_path}/test/native/rdb/unittest", + "${relational_store_mock_test_path}/", + "${relational_store_mock_path}/frameworks/native/rdb/common", + ] + + defines = [ + "RELATIONAL_STORE", + "private=public", + ] +} + +ohos_unittest("NativeRdbConditionTest") { + module_out_path = module_output_path + + cflags = [ + "-fno-access-control", # Ignore Private Member Access Control + ] + + sources = [ "rdb_store_impl_test.cpp" ] + + sources += [ + "${relational_store_mock_test_path}/dataobs_mgr_client_mock.cpp", + "${relational_store_mock_test_path}/rdb_manager_impl_mock.cpp", + "${relational_store_native_path}/dfx/src/rdb_radar_reporter.cpp", + "${relational_store_native_path}/dfx/src/rdb_stat_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_fault_hiview_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_time_utils.cpp", + "${relational_store_native_path}/rdb/src/abs_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_result_set.cpp", + "${relational_store_native_path}/rdb/src/abs_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/base_transaction.cpp", + "${relational_store_native_path}/rdb/src/big_integer.cpp", + "${relational_store_native_path}/rdb/src/cache_result_set.cpp", + "${relational_store_native_path}/rdb/src/connection.cpp", + "${relational_store_native_path}/rdb/src/connection_pool.cpp", + "${relational_store_native_path}/rdb/src/delay_notify.cpp", + "${relational_store_native_path}/rdb/src/grd_api_manager.cpp", + "${relational_store_native_path}/rdb/src/global_resource.cpp", + "${relational_store_native_path}/rdb/src/knowledge_schema_helper.cpp", + "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", + "${relational_store_native_path}/rdb/src/rd_connection.cpp", + "${relational_store_native_path}/rdb/src/rd_statement.cpp", + "${relational_store_native_path}/rdb/src/rd_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_helper.cpp", + "${relational_store_native_path}/rdb/src/rdb_icu_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_local_db_observer.cpp", + "${relational_store_native_path}/rdb/src/rdb_obs_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_notifier_stub.cpp", + "${relational_store_native_path}/rdb/src/rdb_perfStat.cpp", + "${relational_store_native_path}/rdb/src/rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_service_proxy.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_log.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_statistic.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_store.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_impl.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_types_util.cpp", + "${relational_store_native_path}/rdb/src/result_set_proxy.cpp", + "${relational_store_native_path}/rdb/src/security_policy.cpp", + "${relational_store_native_path}/rdb/src/share_block.cpp", + "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", + "${relational_store_native_path}/rdb/src/sqlite_connection.cpp", + "${relational_store_native_path}/rdb/src/sqlite_default_function.cpp", + "${relational_store_native_path}/rdb/src/sqlite_global_config.cpp", + "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/sqlite_sql_builder.cpp", + "${relational_store_native_path}/rdb/src/sqlite_statement.cpp", + "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", + "${relational_store_native_path}/rdb/src/step_result_set.cpp", + "${relational_store_native_path}/rdb/src/string_utils.cpp", + "${relational_store_native_path}/rdb/src/suspender.cpp", + "${relational_store_native_path}/rdb/src/task_executor.cpp", + "${relational_store_native_path}/rdb/src/trans_db.cpp", + "${relational_store_native_path}/rdb/src/transaction.cpp", + "${relational_store_native_path}/rdb/src/transaction_impl.cpp", + "${relational_store_native_path}/rdb/src/value_object.cpp", + "${relational_store_native_path}/rdb/src/values_bucket.cpp", + "${relational_store_native_path}/rdb/src/values_buckets.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "c_utils:utils", + "file_api:securitylabel", + "googletest:gmock", + "googletest:gtest", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "huks:libhukssdk", + "ipc:ipc_core", + "ipc:ipc_single", + "json:nlohmann_json_static", + "kv_store:database_utils", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "samgr:samgr_proxy", + "sqlite:sqlite", + "sqlite:sqliteicu", + ] + + deps = [ + "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", + "${relational_store_innerapi_path}/appdatafwk:relational_common_base", + ] +} + +############################################################################### +group("unittest") { + testonly = true + + deps = [ ":NativeRdbConditionTest" ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/unittest/mockservice/rdb_store_impl_test.cpp b/relational_store/test/native/rdb/unittest/mockservice/rdb_store_impl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..70d3dae6ee2f269345caa0c157f6a48c54d7a7a8 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/mockservice/rdb_store_impl_test.cpp @@ -0,0 +1,1853 @@ +/* + * Copyright (c) 2025 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 "rdb_store_impl.h" + +#include +#include + +#include "common.h" +#include "connection_mock.h" +#include "dataobs_mgr_client_mock.h" +#include "delay_notify.h" +#include "grd_api_manager.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_manager_impl_mock.h" +#include "rdb_open_callback.h" +#include "rdb_service_mock.h" +#include "rdb_sql_statistic.h" +#include "rdb_store_config.h" +#include "rdb_types.h" +#include "statement_mock.h" +#include "task_executor.h" + +using namespace testing::ext; +using namespace testing; +using namespace OHOS::NativeRdb; +using namespace OHOS::DistributedRdb; +using namespace OHOS::AAFwk; +using CheckOnChangeFunc = std::function; +using ValueObjects = std::vector; +class SubObserver : public RdbStoreObserver { +public: + virtual ~SubObserver() + { + } + void OnChange(const std::vector &devices){}; + void OnChange(const Origin &origin, const PrimaryFields &fields, RdbStoreObserver::ChangeInfo &&changeInfo){}; + void OnChange(){}; + void RegisterCallback(const CheckOnChangeFunc &callback); + uint32_t count = 0; + +private: + CheckOnChangeFunc checkOnChangeFunc_; +}; +class RdbStoreImplConditionTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static std::shared_ptr observer_; + static const std::string DATABASE_NAME; + static const std::string DATABASE_BACKUP_NAME; + static const std::string DEFAULT_DATABASE_NAME; + static inline std::shared_ptr mockRdbManagerImpl = nullptr; + static inline std::shared_ptr mockDataObsMgrClient = nullptr; + static inline std::shared_ptr mockStatement = nullptr; + static inline std::shared_ptr mockConnection = nullptr; + +protected: + std::shared_ptr store_; +}; + +const std::string RdbStoreImplConditionTest::DATABASE_NAME = RDB_TEST_PATH + "rdb_store_impl_condition_test.db"; +const std::string RdbStoreImplConditionTest::DATABASE_BACKUP_NAME = + RDB_TEST_PATH + "rdb_store_impl_condition_test_backup.db"; +const std::string RdbStoreImplConditionTest::DEFAULT_DATABASE_NAME = RDB_TEST_PATH + "default_condition_test.db"; + +std::shared_ptr RdbStoreImplConditionTest::observer_ = nullptr; + +class RdbStoreImplConditionTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string CREATE_TABLE_TEST; +}; + +const std::string RdbStoreImplConditionTestOpenCallback::CREATE_TABLE_TEST = + std::string("CREATE TABLE IF NOT EXISTS employee ") + std::string("(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary " + "REAL, blobType BLOB)"); + +int RdbStoreImplConditionTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_TEST); +} + +int RdbStoreImplConditionTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void RdbStoreImplConditionTest::SetUpTestCase(void) +{ + if (observer_ == nullptr) { + observer_ = std::make_shared(); + } + mockRdbManagerImpl = std::make_shared(); + BRdbManagerImpl::rdbManagerImpl = mockRdbManagerImpl; + mockDataObsMgrClient = std::make_shared(); + IDataObsMgrClient::dataObsMgrClient = mockDataObsMgrClient; + mockStatement = std::make_shared(); + mockConnection = std::make_shared(); +} + +void RdbStoreImplConditionTest::TearDownTestCase(void) +{ + mockRdbManagerImpl = nullptr; + BRdbManagerImpl::rdbManagerImpl = nullptr; + mockDataObsMgrClient = nullptr; + IDataObsMgrClient::dataObsMgrClient = nullptr; + mockStatement = nullptr; + mockConnection = nullptr; +} + +void RdbStoreImplConditionTest::SetUp(void) +{ + int errCode; + RdbStoreConfig config(RdbStoreImplConditionTest::DEFAULT_DATABASE_NAME); + RdbStoreImplConditionTestOpenCallback helper; + store_ = RdbHelper::GetRdbStore(config, 0, helper, errCode); + EXPECT_NE(store_, nullptr); + EXPECT_EQ(errCode, E_OK); +} + +void RdbStoreImplConditionTest::TearDown(void) +{ + store_ = nullptr; + RdbHelper::ClearCache(); + int errCode = RdbHelper::DeleteRdbStore(DEFAULT_DATABASE_NAME); + EXPECT_EQ(E_OK, errCode); + errCode = RdbHelper::DeleteRdbStore(DATABASE_NAME); + EXPECT_EQ(E_OK, errCode); +} + +/* * + * @tc.name: Rdb_RemoteQueryTest_003 + * @tc.desc: Abnormal testCase for RemoteQuery + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Rdb_RemoteQueryTest_003, TestSize.Level2) +{ + int errCode = E_OK; + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 1); + + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetName("RdbStore_impl_test.db"); + config.SetBundleName("com.example.distributed.rdb"); + config.SetDBType(DB_SQLITE); + config.SetStorageMode(StorageMode::MODE_MEMORY); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + EXPECT_EQ(E_OK, errCode); + + // GetRdbService succeeded if configuration file has already been configured + auto ret = store->RemoteQuery("", predicates, {}, errCode); + ASSERT_EQ(nullptr, ret); + + store = nullptr; + RdbHelper::DeleteRdbStore(RdbStoreImplConditionTest::DATABASE_NAME); +} + +/* * + * @tc.name: Rdb_RemoteQueryTest_005 + * @tc.desc: Abnormal testCase for RemoteQuery + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Rdb_RemoteQueryTest_005, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)) + .WillRepeatedly(Return(std::make_pair(E_NOT_SUPPORT, mockRdbService))); + int errCode = E_OK; + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 1); + + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetName("RdbStore_impl_test.db"); + config.SetBundleName("com.example.distributed.rdb"); + config.SetDBType(DB_SQLITE); + config.SetStorageMode(StorageMode::MODE_DISK); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(nullptr, store); + EXPECT_EQ(E_OK, errCode); + // GetRdbService succeeded if configuration file has already been configured + auto ret = store->RemoteQuery("", predicates, {}, errCode); + ASSERT_EQ(nullptr, ret); + + store = nullptr; + RdbHelper::DeleteRdbStore(RdbStoreImplConditionTest::DATABASE_NAME); +} + +/* * + * @tc.name: NotifyDataChangeTest_005 + * @tc.desc: Abnormal testCase for NotifyDataChange + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, NotifyDataChangeTest_005, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::CLIENT_OBSERVER, true); + auto storeImpl = std::make_shared(config); + storeImpl->NotifyDataChange(); + EXPECT_EQ(storeImpl->config_.GetRegisterInfo(RegisterType::CLIENT_OBSERVER), true); +} + +/* * + * @tc.name: NotifyDataChangeTest_006 + * @tc.desc: Abnormal testCase for NotifyDataChange + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, NotifyDataChangeTest_006, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(true); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::CLIENT_OBSERVER, true); + auto storeImpl = std::make_shared(config); + storeImpl->NotifyDataChange(); + EXPECT_EQ(storeImpl->config_.GetRegisterInfo(RegisterType::CLIENT_OBSERVER), true); +} + +/* * + * @tc.name: NotifyDataChangeTest_007 + * @tc.desc: Abnormal testCase for NotifyDataChange + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, NotifyDataChangeTest_007, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(true); + config.SetDBType(DB_VECTOR); + config.SetRegisterInfo(RegisterType::CLIENT_OBSERVER, true); + auto storeImpl = std::make_shared(config); + storeImpl->NotifyDataChange(); + EXPECT_EQ(storeImpl->config_.GetRegisterInfo(RegisterType::CLIENT_OBSERVER), true); +} + +/* * + * @tc.name: NotifyDataChangeTest_009 + * @tc.desc: Abnormal testCase for NotifyDataChange + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, NotifyDataChangeTest_009, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(true); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::OBSERVER_END, true); + auto storeImpl = std::make_shared(config); + storeImpl->NotifyDataChange(); + EXPECT_EQ(storeImpl->config_.GetRegisterInfo(RegisterType::CLIENT_OBSERVER), true); +} + +/* * + * @tc.name: ObtainDistributedTableNameTest_003 + * @tc.desc: Abnormal testCase for ObtainDistributedTableName + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ObtainDistributedTableNameTest_003, TestSize.Level2) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetDBType(DB_SQLITE); + config.SetStorageMode(StorageMode::MODE_MEMORY); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr); + EXPECT_EQ(errCode, E_OK); + auto tableName = store->ObtainDistributedTableName("123", "test", errCode); + EXPECT_EQ(tableName, ""); +} + +/* * + * @tc.name: GetUriTest_001 + * @tc.desc: Abnormal testCase for GetUri + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, GetUriTest_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetDataGroupId("123"); + auto storeImlp = std::make_shared(config); + auto uri = storeImlp->GetUri("test"); + EXPECT_EQ(uri, "rdb://123//data/test/rdb_store_impl_condition_test.db/test"); +} + +/* * + * @tc.name: Rdb_QuerySharingResourceTest_004 + * @tc.desc: QuerySharingResource testCase + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Rdb_QuerySharingResourceTest_004, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, QuerySharingResource(_, _, _)).WillOnce(Return(std::make_pair(E_ERROR, nullptr))); + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetName("RdbStore_impl_test.db"); + config.SetBundleName("com.example.distributed.rdb"); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr); + EXPECT_EQ(errCode, E_OK); + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 1); + + auto ret = store->QuerySharingResource(predicates, {}); + EXPECT_EQ(E_ERROR, ret.first); + EXPECT_EQ(nullptr, ret.second); +} + +/* * + * @tc.name: Rdb_QuerySharingResourceTest_005 + * @tc.desc: QuerySharingResource testCase + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Rdb_QuerySharingResourceTest_005, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, QuerySharingResource(_, _, _)).WillOnce(Return(std::make_pair(E_OK, nullptr))); + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetName("RdbStore_impl_test.db"); + config.SetBundleName("com.example.distributed.rdb"); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr); + EXPECT_EQ(errCode, E_OK); + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 1); + + auto ret = store->QuerySharingResource(predicates, {}); + EXPECT_EQ(E_OK, ret.first); + EXPECT_EQ(nullptr, ret.second); +} + +/* * + * @tc.name: CleanDirtyDataTest_002 + * @tc.desc: Abnormal testCase for CleanDirtyData + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Abnormal_CleanDirtyDataTest_002, TestSize.Level2) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetDBType(DB_SQLITE); + config.SetStorageMode(StorageMode::MODE_DISK); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(nullptr, store); + EXPECT_EQ(E_OK, errCode); + std::string table = ""; + uint64_t cursor = UINT64_MAX; + errCode = store->CleanDirtyData(table, cursor); + EXPECT_EQ(E_INVALID_ARGS, errCode); +} + +/* * + * @tc.name: CleanDirtyDataTest_003 + * @tc.desc: Abnormal testCase for CleanDirtyData + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Abnormal_CleanDirtyDataTest_003, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(true); + config.SetDBType(DB_VECTOR); + config.SetStorageMode(StorageMode::MODE_DISK); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(nullptr, store); + EXPECT_EQ(E_OK, errCode); + std::string table = ""; + uint64_t cursor = UINT64_MAX; + errCode = store->CleanDirtyData(table, cursor); + EXPECT_EQ(E_NOT_SUPPORT, errCode); +} + +/* * + * @tc.name: CleanDirtyDataTest_006 + * @tc.desc: Abnormal testCase for CleanDirtyData + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Abnormal_CleanDirtyDataTest_006, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetDBType(DB_VECTOR); + config.SetStorageMode(StorageMode::MODE_DISK); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(nullptr, store); + EXPECT_EQ(E_OK, errCode); + std::string table = ""; + uint64_t cursor = UINT64_MAX; + errCode = store->CleanDirtyData(table, cursor); + EXPECT_EQ(E_NOT_SUPPORT, errCode); +} + +/* * + * @tc.name: CleanDirtyDataTest_007 + * @tc.desc: Abnormal testCase for CleanDirtyData + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Abnormal_CleanDirtyDataTest_007, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(true); + config.SetDBType(DB_VECTOR); + config.SetStorageMode(StorageMode::MODE_DISK); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(nullptr, store); + EXPECT_EQ(E_OK, errCode); + std::string table = ""; + uint64_t cursor = UINT64_MAX; + errCode = store->CleanDirtyData(table, cursor); + EXPECT_EQ(E_NOT_SUPPORT, errCode); +} + +/* * + * @tc.name: CleanDirtyDataTest_009 + * @tc.desc: Abnormal testCase for CleanDirtyData + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Abnormal_CleanDirtyDataTest_009, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetDBType(DB_VECTOR); + config.SetStorageMode(StorageMode::MODE_DISK); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(nullptr, store); + EXPECT_EQ(E_OK, errCode); + std::string table = ""; + uint64_t cursor = UINT64_MAX; + errCode = store->CleanDirtyData(table, cursor); + EXPECT_EQ(E_NOT_SUPPORT, errCode); +} + +/* * + * @tc.name: CleanDirtyDataTest_010 + * @tc.desc: Abnormal testCase for CleanDirtyData + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Abnormal_CleanDirtyDataTest_010, TestSize.Level2) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetDBType(DB_SQLITE); + config.SetStorageMode(StorageMode::MODE_MEMORY); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(nullptr, store); + EXPECT_EQ(E_OK, errCode); + std::string table = ""; + uint64_t cursor = UINT64_MAX; + errCode = store->CleanDirtyData(table, cursor); + EXPECT_EQ(E_NOT_SUPPORT, errCode); +} + +/** + * @tc.name: RdbStoreSubscribeRemote_001 + * @tc.desc: RdbStoreSubscribe + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, RdbStoreSubscribeRemote_001, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetDBType(DB_VECTOR); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(observer_, nullptr) << "observer is null"; + auto status = store->Subscribe({ SubscribeMode::REMOTE, "observer" }, observer_); + EXPECT_EQ(status, E_NOT_SUPPORT); + status = store->UnSubscribe({ SubscribeMode::REMOTE, "observer" }, observer_); + EXPECT_EQ(status, E_NOT_SUPPORT); +} + +/** + * @tc.name: RdbStoreSubscribeRemote_002 + * @tc.desc: RdbStoreSubscribe + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, RdbStoreSubscribeRemote_002, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetDBType(DB_SQLITE); + config.SetStorageMode(StorageMode::MODE_MEMORY); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(observer_, nullptr) << "observer is null"; + auto status = store->Subscribe({ SubscribeMode::REMOTE, "observer" }, observer_); + EXPECT_EQ(status, E_NOT_SUPPORT); + status = store->UnSubscribe({ SubscribeMode::REMOTE, "observer" }, observer_); + EXPECT_EQ(status, E_NOT_SUPPORT); +} + +/** + * @tc.name: SetDistributedTables_Test_001 + * @tc.desc: Abnormal testCase of SetDistributedTables + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDistributedTables_Test_001, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, SetDistributedTables(_, _, _, _, _)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::STORE_OBSERVER, true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector tables; + OHOS::DistributedRdb::DistributedConfig distributedConfig; + + tables.push_back("employee"); + errCode = store->SetDistributedTables(tables, DISTRIBUTED_DEVICE, distributedConfig); + EXPECT_EQ(E_OK, errCode); +} + +/** + * @tc.name: RdbStore_Distributed_Test_002 + * @tc.desc: Abnormal testCase of SetDistributedTables + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDistributedTables_Test_002, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, SetDistributedTables(_, _, _, _, _)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::CLIENT_OBSERVER, true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector tables; + OHOS::DistributedRdb::DistributedConfig distributedConfig; + + tables.push_back("employee"); + errCode = store->SetDistributedTables(tables, DISTRIBUTED_DEVICE, distributedConfig); + EXPECT_EQ(E_OK, errCode); +} + +/** + * @tc.name: SetDistributedTables_Test_003 + * @tc.desc: Abnormal testCase of SetDistributedTables + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDistributedTables_Test_003, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, SetDistributedTables(_, _, _, _, _)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::CLIENT_OBSERVER, true); + config.SetAllowRebuild(true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector tables; + OHOS::DistributedRdb::DistributedConfig distributedConfig; + distributedConfig.enableCloud = true; + distributedConfig.autoSync = true; + tables.push_back("employee"); + errCode = store->SetDistributedTables(tables, DISTRIBUTED_CLOUD, distributedConfig); + EXPECT_EQ(E_OK, errCode); +} + +/** + * @tc.name: SetDistributedTables_Test_004 + * @tc.desc: Abnormal testCase of SetDistributedTables + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDistributedTables_Test_004, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, SetDistributedTables(_, _, _, _, _)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::CLIENT_OBSERVER, true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector tables; + OHOS::DistributedRdb::DistributedConfig distributedConfig; + distributedConfig.enableCloud = true; + distributedConfig.autoSync = true; + tables.push_back("employee"); + errCode = store->SetDistributedTables(tables, DISTRIBUTED_CLOUD, distributedConfig); + EXPECT_EQ(E_OK, errCode); +} + +/** + * @tc.name: SetDistributedTables_Test_005 + * @tc.desc: Abnormal testCase of SetDistributedTables + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDistributedTables_Test_005, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, SetDistributedTables(_, _, _, _, _)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::STORE_OBSERVER, true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector tables; + OHOS::DistributedRdb::DistributedConfig distributedConfig; + distributedConfig.enableCloud = true; + distributedConfig.autoSync = false; + tables.push_back("employee"); + errCode = store->SetDistributedTables(tables, DISTRIBUTED_CLOUD, distributedConfig); + EXPECT_EQ(E_OK, errCode); +} + +/** + * @tc.name: SetDistributedTables_Test_006 + * @tc.desc: Abnormal testCase of SetDistributedTables + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDistributedTables_Test_006, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, SetDistributedTables(_, _, _, _, _)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::STORE_OBSERVER, true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector tables; + OHOS::DistributedRdb::DistributedConfig distributedConfig; + distributedConfig.enableCloud = false; + distributedConfig.autoSync = false; + tables.push_back("employee"); + errCode = store->SetDistributedTables(tables, DISTRIBUTED_CLOUD, distributedConfig); + EXPECT_EQ(E_OK, errCode); +} + +/** + * @tc.name: SetDistributedTables_Test_007 + * @tc.desc: Abnormal testCase of SetDistributedTables + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDistributedTables_Test_007, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, SetDistributedTables(_, _, _, _, _)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::STORE_OBSERVER, true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector tables; + OHOS::DistributedRdb::DistributedConfig distributedConfig; + distributedConfig.enableCloud = false; + distributedConfig.autoSync = true; + tables.push_back("employee"); + errCode = store->SetDistributedTables(tables, DISTRIBUTED_CLOUD, distributedConfig); + EXPECT_EQ(E_OK, errCode); +} + +/** + * @tc.name: Notify_Test_001 + * @tc.desc: Abnormal testCase of Notify + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Notify_Test_001, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::string event = "test"; + auto res = store->Notify(event); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: Notify_Test_002 + * @tc.desc: Abnormal testCase of Notify + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Notify_Test_002, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_MEMORY); + config.SetDBType(DB_SQLITE); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::string event = "test"; + auto res = store->Notify(event); + EXPECT_EQ(E_OK, res); +} + +/** + * @tc.name: Notify_Test_004 + * @tc.desc: Abnormal testCase of Notify + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Notify_Test_004, TestSize.Level2) +{ + //mock client->NotifyChange(GetUri(event)) + auto dataObsMgrClient = std::make_shared(); + EXPECT_CALL(*mockDataObsMgrClient, GetInstance()).WillOnce(Return(dataObsMgrClient)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::string event = "test"; + auto res = store->Notify(event); + EXPECT_EQ(E_OK, res); +} + +/** + * @tc.name: SetSearchable_Test_001 + * @tc.desc: Abnormal testCase of SetSearchable + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetSearchable_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_MEMORY); + config.SetDBType(DB_SQLITE); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + auto res = store->SetSearchable(true); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: SetSearchable_Test_002 + * @tc.desc: Abnormal testCase of SetSearchable + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetSearchable_Test_002, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + auto res = store->SetSearchable(true); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: RegisterAutoSyncCallback_Test_001 + * @tc.desc: Abnormal testCase of RegisterAutoSyncCallback + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, RegisterAutoSyncCallback_Test_001, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::shared_ptr observer; + auto res = store->RegisterAutoSyncCallback(observer); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: RegisterAutoSyncCallback_Test_002 + * @tc.desc: Abnormal testCase of RegisterAutoSyncCallback + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, RegisterAutoSyncCallback_Test_002, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_MEMORY); + config.SetDBType(DB_SQLITE); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::shared_ptr observer; + auto res = store->RegisterAutoSyncCallback(observer); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: RegisterAutoSyncCallback_Test_003 + * @tc.desc: Abnormal testCase of RegisterAutoSyncCallback + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, RegisterAutoSyncCallback_Test_003, TestSize.Level2) +{ + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_ERROR, nullptr))); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::shared_ptr observer; + auto res = store->RegisterAutoSyncCallback(observer); + EXPECT_EQ(E_ERROR, res); +} + +/** + * @tc.name: UnregisterAutoSyncCallback_Test_001 + * @tc.desc: Abnormal testCase of UnregisterAutoSyncCallback + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, UnregisterAutoSyncCallback_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_MEMORY); + config.SetDBType(DB_SQLITE); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::shared_ptr observer; + auto res = store->UnregisterAutoSyncCallback(observer); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: UnregisterAutoSyncCallback_Test_002 + * @tc.desc: Abnormal testCase of UnregisterAutoSyncCallback + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, UnregisterAutoSyncCallback_Test_002, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::shared_ptr observer; + auto res = store->UnregisterAutoSyncCallback(observer); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: UnregisterAutoSyncCallback_Test_003 + * @tc.desc: Abnormal testCase of UnregisterAutoSyncCallback + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, UnregisterAutoSyncCallback_Test_003, TestSize.Level2) +{ + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_ERROR, nullptr))); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::shared_ptr observer; + auto res = store->UnregisterAutoSyncCallback(observer); + EXPECT_EQ(E_ERROR, res); +} + +/** + * @tc.name: RegisterDataChangeCallback_Test_001 + * @tc.desc: Abnormal testCase of RegisterDataChangeCallback + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, RegisterDataChangeCallback_Test_001, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + auto storeImpl = std::make_shared(config); + storeImpl->connectionPool_ = nullptr; + auto res = storeImpl->RegisterDataChangeCallback(); + EXPECT_EQ(E_ALREADY_CLOSED, res); +} + +/** + * @tc.name: ModifyLockStatus_Test_001 + * @tc.desc: Abnormal testCase of ModifyLockStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ModifyLockStatusk_Test_001, TestSize.Level2) +{ + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + store = nullptr; + store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(true); + AbsRdbPredicates predicates(""); + auto res = store->ModifyLockStatus(predicates, false); + EXPECT_EQ(E_EMPTY_TABLE_NAME, res); +} + +/** + * @tc.name: ModifyLockStatus_Test_002 + * @tc.desc: Abnormal testCase of ModifyLockStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ModifyLockStatusk_Test_002, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + config.SetReadOnly(true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + AbsRdbPredicates predicates(""); + auto res = store->ModifyLockStatus(predicates, false); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: ModifyLockStatus_Test_003 + * @tc.desc: Abnormal testCase of ModifyLockStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ModifyLockStatusk_Test_003, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + config.SetReadOnly(false); + config.SetIsVector(true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + AbsRdbPredicates predicates(""); + auto res = store->ModifyLockStatus(predicates, false); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: ModifyLockStatus_Test_004 + * @tc.desc: Abnormal testCase of ModifyLockStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ModifyLockStatusk_Test_004, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_MEMORY); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + AbsRdbPredicates predicates(""); + auto res = store->ModifyLockStatus(predicates, false); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: ModifyLockStatus_Test_005 + * @tc.desc: Abnormal testCase of ModifyLockStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ModifyLockStatusk_Test_005, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + AbsRdbPredicates predicates(""); + auto res = store->ModifyLockStatus(predicates, false); + EXPECT_EQ(E_EMPTY_TABLE_NAME, res); +} + +/** + * @tc.name: ModifyLockStatus_Test_006 + * @tc.desc: Abnormal testCase of ModifyLockStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ModifyLockStatusk_Test_006, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + AbsRdbPredicates predicates("test"); + auto res = store->ModifyLockStatus(predicates, false); + EXPECT_EQ(E_NO_ROW_IN_QUERY, res); +} + +/** + * @tc.name: ModifyLockStatus_Test_007 + * @tc.desc: Abnormal testCase of ModifyLockStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ModifyLockStatusk_Test_007, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + AbsRdbPredicates predicates("test"); + auto res = store->ModifyLockStatus(predicates, false); + EXPECT_EQ(E_NO_ROW_IN_QUERY, res); +} + +/** + * @tc.name: LockCloudContainer_Test_001 + * @tc.desc: Abnormal testCase of LockCloudContainer + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, LockCloudContainer_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_MEMORY); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + auto res1 = store->LockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res1.first); + auto res2 = store->UnlockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res2); +} + +/** + * @tc.name: LockCloudContainer_Test_002 + * @tc.desc: Abnormal testCase of LockCloudContainer + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, LockCloudContainer_Test_002, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + config.SetReadOnly(false); + config.SetIsVector(true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + auto res1 = store->LockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res1.first); + auto res2 = store->UnlockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res2); +} + +/** + * @tc.name: LockCloudContainer_Test_003 + * @tc.desc: Abnormal testCase of LockCloudContainer + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, LockCloudContainer_Test_003, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + config.SetReadOnly(true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + auto res1 = store->LockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res1.first); + auto res2 = store->UnlockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res2); +} + +/** + * @tc.name: LockCloudContainer_Test_004 + * @tc.desc: Abnormal testCase of LockCloudContainer + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, LockCloudContainer_Test_004, TestSize.Level2) +{ + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + store = nullptr; + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(true); + store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + auto res1 = store->LockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res1.first); + auto res2 = store->UnlockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res2); +} + +/** + * @tc.name: LockCloudContainer_Test_005 + * @tc.desc: Abnormal testCase of LockCloudContainer + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, LockCloudContainer_Test_005, TestSize.Level2) +{ + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_NOT_SUPPORT, nullptr))); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + auto res1 = store->LockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res1.first); + auto res2 = store->UnlockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res2); +} + +/** + * @tc.name: Vector_Test_001 + * @tc.desc: Abnormal testCase of VectorDB + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Vector_Test_001, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetDBType(DB_VECTOR); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + const std::string sql; + const ValueObjects bindArgs; + auto res1 = store->QuerySql(sql, bindArgs); + ASSERT_EQ(nullptr, res1); + const AbsRdbPredicates predicates("test"); + int64_t outValue; + std::string valueString; + auto res2 = store->Count(outValue, predicates); + EXPECT_EQ(E_NOT_SUPPORT, res2); + auto res3 = store->ExecuteAndGetString(valueString, sql, bindArgs); + EXPECT_EQ(E_NOT_SUPPORT, res3); +} + +/** + * @tc.name: ExecuteForChangedRowCount_Test_001 + * @tc.desc: Abnormal testCase of ExecuteForChangedRowCount + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ExecuteForChangedRowCount_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + store = nullptr; + config.SetDBType(DB_SQLITE); + config.SetReadOnly(true); + store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + int64_t outValue; + const std::string sql; + const ValueObjects bindArgs; + auto res = store->ExecuteForChangedRowCount(outValue, sql, bindArgs); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: ExecuteForChangedRowCount_Test_002 + * @tc.desc: Abnormal testCase of ExecuteForChangedRowCount + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ExecuteForChangedRowCount_Test_002, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetDBType(DB_VECTOR); + config.SetReadOnly(true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + int64_t outValue; + const std::string sql; + const ValueObjects bindArgs; + auto res = store->ExecuteForChangedRowCount(outValue, sql, bindArgs); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: ExecuteForChangedRowCount_Test_003 + * @tc.desc: Abnormal testCase of ExecuteForChangedRowCount + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ExecuteForChangedRowCount_Test_003, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetDBType(DB_VECTOR); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + int64_t outValue; + const std::string sql; + const ValueObjects bindArgs; + auto res = store->ExecuteForChangedRowCount(outValue, sql, bindArgs); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: SetDefaultEncryptSql_Test_001 + * @tc.desc: Abnormal testCase of SetDefaultEncryptSql + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDefaultEncryptSql_Test_001, TestSize.Level2) +{ + EXPECT_CALL(*mockStatement, Prepare(_)).WillOnce(Return(E_ERROR)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + auto storeImpl = std::make_shared(config); + const std::string sql = "SELECT * FROM employee"; + auto res = storeImpl->SetDefaultEncryptSql(mockStatement, sql, config); + EXPECT_EQ(E_ERROR, res); +} + +/** + * @tc.name: SetDefaultEncryptSql_Test_002 + * @tc.desc: Abnormal testCase of SetDefaultEncryptSql + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDefaultEncryptSql_Test_002, TestSize.Level2) +{ + std::vector args; + EXPECT_CALL(*mockStatement, Prepare(_)).WillOnce(Return(E_OK)); + EXPECT_CALL(*mockStatement, Execute(args)).WillOnce(Return(E_SQLITE_BUSY)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + auto storeImpl = std::make_shared(config); + const std::string sql = "SELECT * FROM employee"; + auto res = storeImpl->SetDefaultEncryptSql(mockStatement, sql, config); + EXPECT_EQ(E_SQLITE_BUSY, res); +} + +/** + * @tc.name: SetDefaultEncryptAlgo_Test_001 + * @tc.desc: Abnormal testCase of SetDefaultEncryptAlgo + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDefaultEncryptAlgo_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->SetDefaultEncryptAlgo(nullptr, config); + EXPECT_EQ(E_DATABASE_BUSY, res); +} + +/** + * @tc.name: SetDefaultEncryptAlgo_Test_002 + * @tc.desc: Abnormal testCase of SetDefaultEncryptAlgo + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDefaultEncryptAlgo_Test_002, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + RdbStoreConfig::CryptoParam cryptoParam; + config.SetCryptoParam(cryptoParam); + config.SetIter(-1); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->SetDefaultEncryptAlgo(mockConnection, config); + EXPECT_EQ(E_INVALID_ARGS, res); +} + +/** + * @tc.name: SetDefaultEncryptAlgo_Test_003 + * @tc.desc: Abnormal testCase of SetDefaultEncryptAlgo + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDefaultEncryptAlgo_Test_003, TestSize.Level2) +{ + EXPECT_CALL(*mockConnection, CreateStatement(_, _)).WillOnce(Return(std::make_pair(E_OK, mockStatement))); + EXPECT_CALL(*mockStatement, Prepare(_)).WillOnce(Return(E_ERROR)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + RdbStoreConfig::CryptoParam cryptoParam; + config.SetCryptoParam(cryptoParam); + config.SetIter(1); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->SetDefaultEncryptAlgo(mockConnection, config); + EXPECT_EQ(E_ERROR, res); +} + +/** + * @tc.name: SetDefaultEncryptAlgo_Test_004 + * @tc.desc: Abnormal testCase of SetDefaultEncryptAlgo + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDefaultEncryptAlgo_Test_004, TestSize.Level2) +{ + EXPECT_CALL(*mockConnection, CreateStatement(_, _)).WillOnce(Return(std::make_pair(E_OK, mockStatement))); + std::vector args; + EXPECT_CALL(*mockStatement, Prepare(_)).WillOnce(Return(E_OK)).WillOnce(Return(E_ERROR)); + EXPECT_CALL(*mockStatement, Execute(args)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + RdbStoreConfig::CryptoParam cryptoParam; + config.SetCryptoParam(cryptoParam); + config.SetIter(1); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->SetDefaultEncryptAlgo(mockConnection, config); + EXPECT_EQ(E_ERROR, res); +} + +/** + * @tc.name: SetDefaultEncryptAlgo_Test_005 + * @tc.desc: Abnormal testCase of SetDefaultEncryptAlgo + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDefaultEncryptAlgo_Test_005, TestSize.Level2) +{ + EXPECT_CALL(*mockConnection, CreateStatement(_, _)).WillOnce(Return(std::make_pair(E_OK, mockStatement))); + std::vector args; + EXPECT_CALL(*mockStatement, Prepare(_)).WillOnce(Return(E_OK)).WillOnce(Return(E_OK)).WillOnce(Return(E_ERROR)); + EXPECT_CALL(*mockStatement, Execute(args)).WillOnce(Return(E_OK)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + RdbStoreConfig::CryptoParam cryptoParam; + config.SetCryptoParam(cryptoParam); + config.SetIter(1); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->SetDefaultEncryptAlgo(mockConnection, config); + EXPECT_EQ(E_ERROR, res); +} + +/** + * @tc.name: SetDefaultEncryptAlgo_Test_006 + * @tc.desc: Abnormal testCase of SetDefaultEncryptAlgo + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDefaultEncryptAlgo_Test_006, TestSize.Level2) +{ + EXPECT_CALL(*mockConnection, CreateStatement(_, _)).WillOnce(Return(std::make_pair(E_OK, mockStatement))); + std::vector args; + EXPECT_CALL(*mockStatement, Prepare(_)) + .WillOnce(Return(E_OK)) + .WillOnce(Return(E_OK)) + .WillOnce(Return(E_OK)) + .WillOnce(Return(E_ERROR)); + EXPECT_CALL(*mockStatement, Execute(args)).WillOnce(Return(E_OK)).WillOnce(Return(E_OK)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + RdbStoreConfig::CryptoParam cryptoParam; + config.SetCryptoParam(cryptoParam); + config.SetIter(1); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->SetDefaultEncryptAlgo(mockConnection, config); + EXPECT_EQ(E_ERROR, res); +} + +/** + * @tc.name: Backup_Test_001 + * @tc.desc: Abnormal testCase of Backup + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Backup_Test_001, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetReadOnly(false); + config.SetHaMode(HAMode::SINGLE); + config.SetIter(1); + config.SetEncryptStatus(true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector encryptKey; + auto res = store->Backup(RdbStoreImplConditionTest::DATABASE_BACKUP_NAME, encryptKey); + EXPECT_EQ(E_OK, res); +} + +/** + * @tc.name: Backup_Test_002 + * @tc.desc: Abnormal testCase of Backup + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Backup_Test_002, TestSize.Level2) +{ + std::vector args; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetReadOnly(false); + config.SetHaMode(HAMode::SINGLE); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector encryptKey; + auto res = store->Backup(RdbStoreImplConditionTest::DATABASE_BACKUP_NAME, encryptKey); + EXPECT_EQ(E_OK, res); +} + +/** + * @tc.name: Attach_Test_001 + * @tc.desc: Abnormal testCase of Attach + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Attach_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetEncryptStatus(true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + RdbStoreConfig config1(RdbStoreImplConditionTest::DATABASE_NAME); + config1.SetReadOnly(false); + config1.SetDBType(DB_SQLITE); + config1.SetHaMode(HAMode::SINGLE); + config1.SetStorageMode(StorageMode::MODE_DISK); + config1.SetEncryptStatus(false); + auto res = store->Attach(config1, "test", 0); + EXPECT_EQ(E_NOT_SUPPORT, res.first); +} + +/** + * @tc.name: ExecuteByTrxId_Test_001 + * @tc.desc: Abnormal testCase of ExecuteByTrxId + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ExecuteByTrxId_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetIsVector(true); + auto storeImpl = std::make_shared(config); + std::vector bindArgs; + auto res = storeImpl->ExecuteByTrxId("sql", 0, false); + EXPECT_EQ(E_INVALID_ARGS, res); +} + +/** + * @tc.name: ExecuteByTrxId_Test_002 + * @tc.desc: Abnormal testCase of ExecuteByTrxId + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ExecuteByTrxId_Test_002, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetIsVector(true); + auto storeImpl = std::make_shared(config); + std::vector bindArgs; + auto res = storeImpl->ExecuteByTrxId("sql", 1, false); + EXPECT_EQ(E_INVALID_ARGS, res); +} + +/** + * @tc.name: Restore_Test_001 + * @tc.desc: Abnormal testCase of Restore + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Restore_Test_001, TestSize.Level2) +{ + std::vector newKey; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(true); + config.SetStorageMode(StorageMode::MODE_MEMORY); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->Restore("test.db", newKey); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: Restore_Test_002 + * @tc.desc: Abnormal testCase of Restore + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Restore_Test_002, TestSize.Level2) +{ + std::vector newKey; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetStorageMode(StorageMode::MODE_MEMORY); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->Restore("test.db", newKey); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: Restore_Test_003 + * @tc.desc: Abnormal testCase of Restore + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Restore_Test_003, TestSize.Level2) +{ + std::vector newKey; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(true); + config.SetStorageMode(StorageMode::MODE_DISK); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->Restore("test.db", newKey); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: GetStatement_Test_001 + * @tc.desc: Abnormal testCase of GetStatement + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, GetStatement_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + auto storeImpl = std::make_shared(config); + const std::string sql = "ATTACH DATABASE 'database.db';"; + auto res = storeImpl->GetStatement(sql, nullptr); + EXPECT_EQ(E_DATABASE_BUSY, res.first); +} + +/** + * @tc.name: InterruptBackup_Test_001 + * @tc.desc: Abnormal testCase of InterruptBackup + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, InterruptBackup_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetHaMode(HAMode::SINGLE); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->InterruptBackup(); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: InterruptBackup_Test_003 + * @tc.desc: Abnormal testCase of InterruptBackup + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, InterruptBackup_Test_003, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetHaMode(HAMode::MANUAL_TRIGGER); + auto storeImpl = std::make_shared(config); + *(storeImpl->slaveStatus_) = BACKING_UP; + auto res = storeImpl->InterruptBackup(); + EXPECT_EQ(E_OK, res); +} + +/** + * @tc.name: GetBackupStatus_Test_001 + * @tc.desc: Abnormal testCase of GetBackupStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, GetBackupStatus_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetHaMode(HAMode::SINGLE); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->GetBackupStatus(); + EXPECT_EQ(UNDEFINED, res); +} + +/** + * @tc.name: GetBackupStatus_Test_002 + * @tc.desc: Abnormal testCase of GetBackupStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, GetBackupStatus_Test_002, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetHaMode(HAMode::MANUAL_TRIGGER); + auto storeImpl = std::make_shared(config); + *(storeImpl->slaveStatus_) = BACKING_UP; + auto res = storeImpl->GetBackupStatus(); + EXPECT_EQ(BACKING_UP, res); +} + +/** + * @tc.name: CleanDirtyLog_Test_001 + * @tc.desc: Abnormal testCase of CleanDirtyLog + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, CleanDirtyLog_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_MEMORY); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + uint64_t cursor = 0; + auto res = store->CleanDirtyLog("test", cursor); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: CleanDirtyLog_Test_002 + * @tc.desc: Abnormal testCase of CleanDirtyLog + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, CleanDirtyLog_Test_002, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + uint64_t cursor = 0; + auto res = store->CleanDirtyLog("test", cursor); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: CleanDirtyLog_Test_004 + * @tc.desc: Abnormal testCase of CleanDirtyLog + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, CleanDirtyLog_Test_004, TestSize.Level2) +{ + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + store = nullptr; + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(true); + store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + uint64_t cursor = 0; + auto res = store->CleanDirtyLog("test", cursor); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: CloudTables::Change_Test_001 + * @tc.desc: Abnormal testCase of CloudTables::Change + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, CloudTables_Change_Test_001, TestSize.Level2) +{ + auto cloudTables = std::make_shared(); + std::string table = ""; + auto res = cloudTables->Change(table); + EXPECT_EQ(false, res); + cloudTables->AddTables({ "test1" }); + std::string table1 = "test"; + res = cloudTables->Change(table1); + EXPECT_EQ(false, res); + cloudTables->AddTables({ "test" }); + std::string table2 = "test"; + res = cloudTables->Change(table2); + EXPECT_EQ(true, res); + res = cloudTables->Change(table); + EXPECT_EQ(false, res); +} + +/** + * @tc.name: RdbStore_GetValues_002 + * @tc.desc: test RdbStore GetValues + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, RdbStore_GetValues_002, TestSize.Level1) +{ + EXPECT_EQ(OHOS::NativeRdb::RdbStoreImpl::GetValues(nullptr), nullptr); + uint32_t maxReturningRows = 1024; + std::vector valuesBuckets; + EXPECT_CALL(*mockStatement, GetRows(maxReturningRows)) + .WillOnce(Return(std::make_pair(E_ERROR, valuesBuckets))); + auto resultSet = RdbStoreImpl::GetValues(mockStatement); + ASSERT_NE(nullptr, resultSet); + int rowCount = -1; + ASSERT_EQ(resultSet->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); +} + +/** + * @tc.name: RdbStore_GetValues_003 + * @tc.desc: test RdbStore GetValues + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, RdbStore_GetValues_003, TestSize.Level1) +{ + uint32_t maxReturningRows = 1024; + auto [code, statement] = + static_cast(store_.get())->GetStatement("PRAGMA user_version = 1;", true); + ASSERT_EQ(E_OK, code); + ASSERT_NE(nullptr, statement); + auto [ret, valuesBucket] = statement->GetRows(maxReturningRows); + ASSERT_EQ(E_OK, ret); + + std::vector valuesBuckets; + for (int i = 0; i < maxReturningRows; i++) { + ValuesBucket valuesBucket; + valuesBucket.Put("name", "test"); + valuesBuckets.push_back(std::move(valuesBucket)); + } + + EXPECT_CALL(*mockStatement, GetRows(maxReturningRows)) + .WillOnce(Return(std::make_pair(E_OK, valuesBuckets))) + .WillOnce(Return(std::make_pair(E_NO_MORE_ROWS, valuesBuckets))); + auto resultSet = RdbStoreImpl::GetValues(mockStatement); + ASSERT_NE(nullptr, resultSet); + int rowCount = -1; + ASSERT_EQ(resultSet->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1024); +} diff --git a/relational_store/test/native/rdb/unittest/multiThread/rdb_connection_rd_test.cpp b/relational_store/test/native/rdb/unittest/multiThread/rdb_connection_rd_test.cpp index d9a99944e21c4f4c0a78890a6a6d3b269714dfce..49fe3814228049b28f755a769cd04f201b2db87e 100644 --- a/relational_store/test/native/rdb/unittest/multiThread/rdb_connection_rd_test.cpp +++ b/relational_store/test/native/rdb/unittest/multiThread/rdb_connection_rd_test.cpp @@ -19,7 +19,7 @@ #include #include -#include "../common.h" +#include "common.h" #include "block_data.h" #include "executor_pool.h" #include "rd_utils.h" diff --git a/relational_store/test/native/rdb/unittest/multiThread/rdb_connection_test.cpp b/relational_store/test/native/rdb/unittest/multiThread/rdb_connection_test.cpp index e42b3214f0dee23b162218846ed925f0f17f2492..e9f7a6a9d171586922d9aa50ff509edab5f3cf6b 100644 --- a/relational_store/test/native/rdb/unittest/multiThread/rdb_connection_test.cpp +++ b/relational_store/test/native/rdb/unittest/multiThread/rdb_connection_test.cpp @@ -19,7 +19,7 @@ #include #include -#include "../common.h" +#include "common.h" #include "block_data.h" #include "executor_pool.h" #include "rdb_errno.h" diff --git a/relational_store/test/native/rdb/unittest/multiThread/rdb_store_multiprocess_createDB_test.cpp b/relational_store/test/native/rdb/unittest/multiThread/rdb_store_multiprocess_createDB_test.cpp index 6758a23ee88f08d295990dcae0a39eaee89dd1a2..2b58b803d5d276814d9313216b0c87a9892970f4 100644 --- a/relational_store/test/native/rdb/unittest/multiThread/rdb_store_multiprocess_createDB_test.cpp +++ b/relational_store/test/native/rdb/unittest/multiThread/rdb_store_multiprocess_createDB_test.cpp @@ -25,7 +25,7 @@ #include #include -#include "../common.h" +#include "common.h" #include "rdb_errno.h" #include "rdb_helper.h" #include "rdb_open_callback.h" diff --git a/relational_store/test/native/rdb/unittest/rd_utils_test.cpp b/relational_store/test/native/rdb/unittest/rd_utils_test.cpp index a7f3c32b7b729ce19d5c11d8023fb6f860cae4ab..e9c32ce608cfa6d71e94e3fb7def3bd8dd76bbcc 100644 --- a/relational_store/test/native/rdb/unittest/rd_utils_test.cpp +++ b/relational_store/test/native/rdb/unittest/rd_utils_test.cpp @@ -19,14 +19,43 @@ #include #include +#include #include +#include #include +#include +#include "grd_api_manager.h" #include "grd_type_export.h" +#include "rdb_helper.h" +#include "task_executor.h" using namespace testing::ext; using namespace OHOS::NativeRdb; +static std::mutex g_mutex; +static std::unordered_set allocatedAddresses; +static bool g_isRecord = false; + +void *operator new[](size_t size, const std::nothrow_t &tag) noexcept +{ + void *ptr = std::malloc(size); + if (g_isRecord && ptr != nullptr) { + std::lock_guard lock(g_mutex); + allocatedAddresses.insert(ptr); + } + return ptr; +} + +void operator delete[](void *ptr) noexcept +{ + if (g_isRecord && ptr != nullptr) { + std::lock_guard lock(g_mutex); + allocatedAddresses.erase(ptr); + } + std::free(ptr); +} + namespace Test { class RdUtilsTest : public testing::Test { public: @@ -38,10 +67,21 @@ public: void RdUtilsTest::SetUpTestCase(void) { + std::lock_guard lock(g_mutex); + g_isRecord = true; } void RdUtilsTest::TearDownTestCase(void) { + std::lock_guard lock(g_mutex); + g_isRecord = false; +} + +static void ScheduleMock(void *param) +{ + (void)param; + int sleepTime = 20; + std::this_thread::sleep_for(std::chrono::seconds(sleepTime)); } /** @@ -65,4 +105,109 @@ HWTEST_F(RdUtilsTest, RdUtils_Test_002, TestSize.Level1) EXPECT_EQ(RdUtils::TransferGrdTypeToColType(GRD_DB_DATATYPE_FLOATVECTOR), ColumnType::TYPE_FLOAT32_ARRAY); EXPECT_EQ(RdUtils::TransferGrdTypeToColType(GRD_DB_DATATYPE_NULL), ColumnType::TYPE_NULL); } + +/** + * @tc.name: RdUtils_Test_003 + * @tc.desc: Test RdSqlRegistryThreadPool + * @tc.type: FUNC + */ +HWTEST_F(RdUtilsTest, RdUtils_Test_003, TestSize.Level1) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + std::string dbPath = "/data/test/execute_test.db"; + std::string configStr = "{}"; + RdbHelper::DeleteRdbStore(dbPath); + + GRD_DB *db = nullptr; + EXPECT_EQ(RdUtils::RdDbOpen(dbPath.c_str(), configStr.c_str(), GRD_DB_OPEN_CREATE, &db), E_OK); + ASSERT_EQ(RdUtils::RdSqlRegistryThreadPool(db), E_OK); + + ASSERT_NE(RdUtils::threadPool_.schedule, nullptr); + ASSERT_NE(RdUtils::threadPool_.remove, nullptr); + +// TaskExecutor::TaskId taskId = RdUtils::threadPool_.schedule(reinterpret_cast(ScheduleMock), nullptr); +// ASSERT_NE(static_cast(taskId), TaskExecutor::INVALID_TASK_ID); + + int sleepTime = 2; + std::this_thread::sleep_for(std::chrono::seconds(sleepTime)); + +// bool ret = RdUtils::threadPool_.remove(static_cast(taskId), false); + // expect false because this task is running, will remove from exec list +// ASSERT_FALSE(ret); + + EXPECT_EQ(RdUtils::RdDbClose(db, 0), E_OK); + RdbHelper::DeleteRdbStore(dbPath); +} + +/** + * @tc.name: RdUtils_Test_004 + * @tc.desc: Test bind empty string + * @tc.type: FUNC + */ +HWTEST_F(RdUtilsTest, RdUtils_Test_004, TestSize.Level1) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + GRD_SqlStmt *stmt = nullptr; + uint32_t idx = 0; + const char *str = ""; + EXPECT_EQ(RdUtils::RdSqlBindText(stmt, idx, str, -1, nullptr), E_INVALID_ARGS); + EXPECT_EQ(RdUtils::RdSqlBindText(stmt, idx, str, 0, nullptr), E_INVALID_ARGS); +} + +/** + * @tc.name: RdUtils_Test_005 + * @tc.desc: Test RdSqlBindBlob + * @tc.type: FUNC + */ +HWTEST_F(RdUtilsTest, RdUtils_Test_005, TestSize.Level0) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + GRD_SqlStmt *stmtHandle = nullptr; + const uint8_t testData[] = { 0x05, 0x06 }; + const int32_t dataLen = sizeof(testData); + auto ret = RdUtils::RdSqlBindBlob(stmtHandle, 1, testData, dataLen, nullptr); + EXPECT_EQ(ret, E_INVALID_ARGS); + EXPECT_TRUE(allocatedAddresses.empty()); +} + +/** + * @tc.name: RdUtils_Test_006 + * @tc.desc: Test RdSqlBindBlob + * @tc.type: FUNC + */ +HWTEST_F(RdUtilsTest, RdUtils_Test_006, TestSize.Level0) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + GRD_SqlStmt *stmtHandle = nullptr; + const char *testStr = "Test"; + auto ret = RdUtils::RdSqlBindText(stmtHandle, 1, testStr, strlen(testStr), nullptr); + EXPECT_EQ(ret, E_INVALID_ARGS); + EXPECT_TRUE(allocatedAddresses.empty()); +} + +/** + * @tc.name: RdUtils_Test_007 + * @tc.desc: Test RdSqlBindFloatVector + * @tc.type: FUNC + */ +HWTEST_F(RdUtilsTest, RdUtils_Test_007, TestSize.Level0) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + GRD_SqlStmt *stmtHandle = nullptr; + float testData[] = { 1.1f, 2.2f, 3.3f }; + uint32_t dim = sizeof(testData) / sizeof(float); + auto ret = RdUtils::RdSqlBindFloatVector(stmtHandle, 2, testData, dim, nullptr); + EXPECT_EQ(ret, E_INVALID_ARGS); + EXPECT_TRUE(allocatedAddresses.empty()); +} } // namespace Test diff --git a/relational_store/test/native/rdb/unittest/rdb_callback_icu_test.cpp b/relational_store/test/native/rdb/unittest/rdb_callback_icu_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..50cc488c3bcf320f6d7e072153ccc2fa572ef1cb --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_callback_icu_test.cpp @@ -0,0 +1,166 @@ +/* + * 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 "RdbCallbackIcuTest" +#include + +#include + +#include "common.h" +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + +using namespace testing::ext; +using namespace OHOS::Rdb; +using namespace OHOS::NativeRdb; + +class RdbCallbackIcuTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static const std::string databaseName; +}; + +const std::string RdbCallbackIcuTest::databaseName = RDB_TEST_PATH + "open_helper.db"; + +void RdbCallbackIcuTest::SetUpTestCase(void) +{ +} + +void RdbCallbackIcuTest::TearDownTestCase(void) +{ + RdbHelper::DeleteRdbStore(RdbCallbackIcuTest::databaseName); +} + +void RdbCallbackIcuTest::SetUp(void) +{ +} + +void RdbCallbackIcuTest::TearDown(void) +{ + RdbHelper::ClearCache(); +} + +class OpenCallbackIcu : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + int OnDowngrade(RdbStore &store, int oldVersion, int newVersion) override; + int OnOpen(RdbStore &store) override; + + static std::string CreateTableSQL(const std::string &tableName); + static std::string DropTableSQL(const std::string &tableName); +}; + +std::string OpenCallbackIcu::CreateTableSQL(const std::string &tableName) +{ + return "CREATE VIRTUAL TABLE IF NOT EXISTS " + tableName + " USING fts4(name, content, tokenize=icu zh_CN);"; +} + +std::string OpenCallbackIcu::DropTableSQL(const std::string &tableName) +{ + return "DROP TABLE IF EXISTS " + tableName + ";"; +} + +int OpenCallbackIcu::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CreateTableSQL("test1")); +} + +int OpenCallbackIcu::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +int OpenCallbackIcu::OnDowngrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +int OpenCallbackIcu::OnOpen(RdbStore &store) +{ + return E_OK; +} + +/** + * @tc.name: RdbCallbackIcu_01 + * @tc.desc: test RdbCallbackIcu + * @tc.type: FUNC + */ +HWTEST_F(RdbCallbackIcuTest, RdbCallbackIcu_01, TestSize.Level1) +{ + RdbStoreConfig config(RdbCallbackIcuTest::databaseName); + config.SetTokenizer(ICU_TOKENIZER); + OpenCallbackIcu helper; + + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + const char *sqlCreateTable = "CREATE VIRTUAL TABLE example USING fts4(name, content, tokenize=icu zh_CN);"; + int ret = store->ExecuteSql(sqlCreateTable); + EXPECT_EQ(ret, E_OK); + + const char *sqlInsert1 = + "INSERT INTO example(name, content) VALUES('文档1', '这是一个测试文档,用于测试中文文本的分词和索引。');"; + ret = store->ExecuteSql(sqlInsert1); + EXPECT_EQ(ret, E_OK); + + const char *sqlInsert2 = + "INSERT INTO example(name, content) VALUES('文档2', '我们将使用这个示例来演示如何在SQLite中进行全文搜索。');"; + ret = store->ExecuteSql(sqlInsert2); + EXPECT_EQ(ret, E_OK); + + const char *sqlInsert3 = + "INSERT INTO example(name, content) VALUES('文档3', 'ICU分词器能够很好地处理中文文本的分词和分析。');"; + ret = store->ExecuteSql(sqlInsert3); + EXPECT_EQ(ret, E_OK); + + const char *sqlQuery = "SELECT * FROM example WHERE example MATCH '测试';"; + ret = store->ExecuteSql(sqlQuery); + EXPECT_EQ(ret, E_OK); + + std::shared_ptr resultSet = store->QuerySql(sqlQuery); + ASSERT_NE(resultSet, nullptr); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + + int columnIndex; + std::string strVal; + + ret = resultSet->GetColumnIndex("name", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ("文档1", strVal); + + ret = resultSet->GetColumnIndex("content", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ("这是一个测试文档,用于测试中文文本的分词和索引。", strVal); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ROW_OUT_RANGE); + + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_concurrent_querywithcurd_test.cpp b/relational_store/test/native/rdb/unittest/rdb_concurrent_querywithcurd_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e6817c35e9dbe7d048119a2aa8b5a9cd8938f7d --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_concurrent_querywithcurd_test.cpp @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2025 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 "common.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "values_bucket.h" +using namespace testing::ext; +using namespace OHOS::NativeRdb; +namespace Test { +class QueryWithCrudTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(void); + void TearDown(void); + void InsertData(int rowCount, int size); + static std::shared_ptr rdbStore_; + static constexpr const char *DATABASE_PATH = "/data/test/queryWithCrud_test.db"; + static constexpr const char *CREATE_TABLE = "CREATE TABLE IF NOT EXISTS test(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"; + static constexpr const char *DROP_TABLE = "DROP TABLE IF EXISTS test"; + const double SALARY = 100.5; + + class RdbCallback : public RdbOpenCallback { + public: + int OnCreate(RdbStore &store) override + { + return E_OK; + } + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override + { + return E_OK; + } + }; +}; +std::shared_ptr QueryWithCrudTest::rdbStore_; +void QueryWithCrudTest::SetUpTestCase(void) +{ + int errCode = E_OK; + RdbCallback callback; + RdbStoreConfig config(DATABASE_PATH); + RdbHelper::DeleteRdbStore(DATABASE_PATH); + rdbStore_ = RdbHelper::GetRdbStore(config, 1, callback, errCode); + ASSERT_NE(rdbStore_, nullptr); +} + +void QueryWithCrudTest::TearDownTestCase(void) +{ + rdbStore_ = nullptr; + RdbHelper::DeleteRdbStore(DATABASE_PATH); +} +void QueryWithCrudTest::SetUp(void) +{ + rdbStore_->ExecuteSql(DROP_TABLE); + rdbStore_->ExecuteSql(CREATE_TABLE); +} + +void QueryWithCrudTest::TearDown(void) +{ + rdbStore_->ExecuteSql(DROP_TABLE); +} +void QueryWithCrudTest::InsertData(int rowCount, int size) +{ + EXPECT_GT(rowCount, 0); + EXPECT_GT(size, 0); + int64_t id; + ValuesBucket values; + std::vector u8(size, 1); + std::vector valuesBuckets; + for (int i = 0; i < rowCount; i++) { + values.Put("name", "zhangsan" + std::to_string(i)); + values.Put("age", i); + values.Put("salary", SALARY); + values.Put("blobType", u8); + valuesBuckets.push_back(values); + } + auto ret = rdbStore_->BatchInsert(id, "test", valuesBuckets); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(id, rowCount); +} +/** + * @tc.name: QueryWithDelete_001 + * @tc.desc: 10 records with a total of less than 2M data, + * delete 3 records, rowCount equals 7 records. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithDelete_001, TestSize.Level1) +{ + InsertData(10, 1); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.Between("age", 5, 7); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 3); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 7); +} + +/** + * @tc.name: QueryWithDelete_002 + * @tc.desc: 10 pieces of 1M data, delete 3 pieces, rowCount equals 7 pieces. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithDelete_002, TestSize.Level1) +{ + InsertData(10, 1024 * 1024); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.Between("age", 5, 7); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 3); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 7); +} + +/** + * @tc.name: QueryWithDelete_003 + * @tc.desc: Single data exceeding 2M can return an error normally + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithDelete_003, TestSize.Level1) +{ + InsertData(2, 1024 * 1024 * 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.EqualTo("age", 1); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 1); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ERROR); +} + +/** + * @tc.name: QueryWithDelete_004 + * @tc.desc: 2 pieces of single 2M data, delete 2 pieces, rowCount equals 0. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithDelete_004, TestSize.Level1) +{ + InsertData(2, 1024 * 1024 * 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.Between("age", 0, 1); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 2); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 0); +} + +/** + * @tc.name: QueryWithDelete_005 + * @tc.desc: 10 pieces of data, one of which is greater than 2M, the other 1M, + * delete 9 pieces of data less than 1M, expect an error. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithDelete_005, TestSize.Level1) +{ + InsertData(9, 2); + InsertData(1, 1024 * 1024 * 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.Between("id", 1, 9); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 9); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ERROR); +} + +/** + * @tc.name: QueryWithDelete_006 + * @tc.desc: 10 pieces of data, one of which is greater than 2M, the other 1M, + * delete data greater than 2M, rowCount is 9. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithDelete_006, TestSize.Level1) +{ + InsertData(9, 2); + InsertData(1, 1024 * 1024 * 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.EqualTo("id", 10); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 1); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 9); +} + +/** + * @tc.name: QueryWithDelete_007 + * @tc.desc: 10 records with a total of less than 2M data, + * delete 10 records, rowCount equals 0 records. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithDelete_007, TestSize.Level1) +{ + InsertData(10, 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 10); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 0); +} + +/** + * @tc.name: QueryWithInsert_001 + * @tc.desc: 10 pieces of data with a total size less than 2M, delete 3 pieces, + * insert 1 piece of data with a single size less than 1M, rowCount is equal to 8. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithInsert_001, TestSize.Level1) +{ + InsertData(10, 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.Between("age", 5, 7); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 3); + EXPECT_EQ(res, E_OK); + InsertData(1, 2); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 8); +} + +/** + * @tc.name: QueryWithInsert_002 + * @tc.desc: 10 pieces of data with a total size less than 2M, delete 4 pieces, + * insert 3 pieces of data with a single size less than 2M, rowCount is equal to 9. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithInsert_002, TestSize.Level1) +{ + InsertData(10, 1024 * 1024); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.Between("age", 1, 4); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 4); + EXPECT_EQ(res, E_OK); + InsertData(3, 2); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 9); +} + +/** + * @tc.name: QueryWithInsert_003 + * @tc.desc: 3 pieces of data larger than 2M, delete 2 pieces, + * insert 1 piece of data smaller than 1M, expect an error. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithInsert_003, TestSize.Level1) +{ + InsertData(3, 1024 * 1024 * 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.Between("age", 0, 1); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 2); + EXPECT_EQ(res, E_OK); + InsertData(1, 2); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ERROR); +} + +/** + * @tc.name: QueryWithInsert_004 + * @tc.desc: 2 pieces of data larger than 2M, delete 2 pieces, + * insert 1 piece of data smaller than 1M, rowCount is equal to 1. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithInsert_004, TestSize.Level1) +{ + InsertData(2, 1024 * 1024 * 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 2); + EXPECT_EQ(res, E_OK); + InsertData(1, 2); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 1); +} + +/** + * @tc.name: QueryWithInsert_005 + * @tc.desc: 10 pieces of data with a total of less than 2M, delete 6 pieces, + * insert 1 pieces of data with a single value greater than 2M, expect an error. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithInsert_005, TestSize.Level1) +{ + InsertData(10, 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.Between("age", 0, 5); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 6); + EXPECT_EQ(res, E_OK); + InsertData(1, 1024 * 1024 * 2); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ERROR); +} + +/** + * @tc.name: QueryWithUpdate_001 + * @tc.desc: 10 records with a total of less than 2M data, updated 3 records, rowCount is 10. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithUpdate_001, TestSize.Level1) +{ + InsertData(10, 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + int updatedRows; + ValuesBucket values; + std::vector u8(2, 1); + predicates.Between("age", 0, 2); + values.Put("name", "zhangsan30"); + values.Put("age", 30); + values.Put("salary", SALARY); + values.Put("blobType", u8); + auto res = rdbStore_->Update(updatedRows, values, predicates); + EXPECT_EQ(updatedRows, 3); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 10); +} + +/** + * @tc.name: QueryWithUpdate_002 + * @tc.desc: 10 pieces of single data less than 1M, update 3 pieces, rowCount is 10. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithUpdate_002, TestSize.Level1) +{ + InsertData(10, 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + int updatedRows; + ValuesBucket values; + std::vector bigU8(1024 * 1024 * 2, 1); + predicates.Between("age", 0, 2); + values.Put("name", "zhangsan30"); + values.Put("age", 30); + values.Put("salary", SALARY); + values.Put("blobType", bigU8); + auto res = rdbStore_->Update(updatedRows, values, predicates); + EXPECT_EQ(updatedRows, 3); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ERROR); +} + +/** + * @tc.name: QueryWithUpdate_003 + * @tc.desc: 2 pieces of data larger than 2M, update 2 pieces of data smaller than 1M, + * rowCount is 2. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithUpdate_003, TestSize.Level1) +{ + InsertData(2, 1024 * 1024 * 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + int updatedRows; + ValuesBucket values; + std::vector u8(2, 1); + predicates.Between("age", 0, 1); + values.Put("name", "zhangsan30"); + values.Put("age", 30); + values.Put("salary", SALARY); + values.Put("blobType", u8); + auto res = rdbStore_->Update(updatedRows, values, predicates); + EXPECT_EQ(updatedRows, 2); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 2); +} +} // namespace Test diff --git a/relational_store/test/native/rdb/unittest/rdb_corrupt_test.cpp b/relational_store/test/native/rdb/unittest/rdb_corrupt_test.cpp index 944af040cd0b9aa24a3d7bd219f327dc583b2988..f2958a38be1e6c0cb31ff67dfffaa2d91d497028 100644 --- a/relational_store/test/native/rdb/unittest/rdb_corrupt_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_corrupt_test.cpp @@ -41,6 +41,7 @@ public: void GenerateData(int count); static void DestroyDbFile(const std::string &filePath, size_t offset, size_t len, unsigned char ch); static constexpr const char *DATABASE_NAME = "corrupt_test.db"; + static constexpr int DB_FILE_HEADER_LENGTH = 100; std::shared_ptr store_; }; @@ -137,4 +138,21 @@ HWTEST_F(RdbCorruptTest, RdbCorruptTest001, TestSize.Level2) } EXPECT_EQ(errCode, E_SQLITE_CORRUPT); } + +/** + * @tc.name: RdbCorruptTest002 + * @tc.desc: test Rdb verify db file header's reserved bytes + * @tc.type: FUNC + */ +HWTEST_F(RdbCorruptTest, RdbCorruptTest002, TestSize.Level2) +{ + std::fstream f; + f.open(RDB_TEST_PATH + DATABASE_NAME); + f.seekp(0, std::ios::beg); + char buf[DB_FILE_HEADER_LENGTH] = {0}; + f.read(buf, sizeof(buf)); + f.close(); + // 20 is the offset of reserved bytes field + EXPECT_EQ((unsigned int)buf[20], 0); +} } // namespace Test \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_delete_test.cpp b/relational_store/test/native/rdb/unittest/rdb_delete_test.cpp index b60c4a9b0a266c46b9cf9b1339a7b5f934e23e34..b217af1b89a4120f92bb43dce010cb14aa46eb84 100644 --- a/relational_store/test/native/rdb/unittest/rdb_delete_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_delete_test.cpp @@ -15,8 +15,10 @@ #include +#include #include +#include "abs_rdb_predicates.h" #include "common.h" #include "rdb_errno.h" #include "rdb_helper.h" @@ -92,6 +94,7 @@ void RdbDeleteTest::TearDownTestCase(void) void RdbDeleteTest::SetUp(void) { store_ = *GetParam(); + ASSERT_NE(store_, nullptr); store_->ExecuteSql("DELETE FROM test"); } @@ -106,36 +109,34 @@ void RdbDeleteTest::TearDown(void) */ HWTEST_P(RdbDeleteTest, RdbStore_Delete_001, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int64_t id; int deletedRows; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[2])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[2])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); - ret = store->Delete(deletedRows, "test", "id = 1"); + ret = store_->Delete(deletedRows, "test", "id = 1"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, deletedRows); std::shared_ptr resultSet = - store->QuerySql("SELECT * FROM test WHERE id = ?", std::vector{ "1" }); + store_->QuerySql("SELECT * FROM test WHERE id = ?", std::vector{ "1" }); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_ROW_OUT_RANGE); ret = resultSet->Close(); EXPECT_EQ(ret, E_OK); - resultSet = store->QuerySql("SELECT * FROM test WHERE id = ?", std::vector{ "2" }); + resultSet = store_->QuerySql("SELECT * FROM test WHERE id = ?", std::vector{ "2" }); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToFirstRow(); EXPECT_EQ(ret, E_OK); @@ -144,7 +145,7 @@ HWTEST_P(RdbDeleteTest, RdbStore_Delete_001, TestSize.Level1) ret = resultSet->Close(); EXPECT_EQ(ret, E_OK); - resultSet = store->QuerySql("SELECT * FROM test WHERE id = 3", std::vector()); + resultSet = store_->QuerySql("SELECT * FROM test WHERE id = 3", std::vector()); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToFirstRow(); EXPECT_EQ(ret, E_OK); @@ -161,8 +162,6 @@ HWTEST_P(RdbDeleteTest, RdbStore_Delete_001, TestSize.Level1) */ HWTEST_P(RdbDeleteTest, RdbStore_Delete_002, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; int deletedRows; @@ -172,7 +171,7 @@ HWTEST_P(RdbDeleteTest, RdbStore_Delete_002, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); + int ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -182,7 +181,7 @@ HWTEST_P(RdbDeleteTest, RdbStore_Delete_002, TestSize.Level1) values.PutInt("age", 19); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->Insert(id, "test", values); + ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -192,15 +191,15 @@ HWTEST_P(RdbDeleteTest, RdbStore_Delete_002, TestSize.Level1) values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->Insert(id, "test", values); + ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); - ret = store->Delete(deletedRows, "test"); + ret = store_->Delete(deletedRows, "test"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, deletedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_ROW_OUT_RANGE); @@ -215,8 +214,6 @@ HWTEST_P(RdbDeleteTest, RdbStore_Delete_002, TestSize.Level1) */ HWTEST_P(RdbDeleteTest, RdbStore_Delete_003, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; int deletedRows; @@ -226,23 +223,306 @@ HWTEST_P(RdbDeleteTest, RdbStore_Delete_003, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); + int ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Delete(deletedRows, "", "id = ?", std::vector{ "1" }); + ret = store_->Delete(deletedRows, "", "id = ?", std::vector{ "1" }); EXPECT_EQ(ret, E_EMPTY_TABLE_NAME); - ret = store->Delete(deletedRows, "wrongTable", "id = ?", std::vector{ "1" }); + ret = store_->Delete(deletedRows, "wrongTable", "id = ?", std::vector{ "1" }); EXPECT_EQ(ret, E_SQLITE_ERROR); - ret = store->Delete(deletedRows, "test", "wrong sql id = ?", std::vector{ "1" }); + ret = store_->Delete(deletedRows, "test", "wrong sql id = ?", std::vector{ "1" }); EXPECT_EQ(ret, E_SQLITE_ERROR); - ret = store->Delete(deletedRows, "test", "id = 1", std::vector()); + ret = store_->Delete(deletedRows, "test", "id = 1", std::vector()); EXPECT_EQ(ret, E_OK); EXPECT_EQ(deletedRows, 1); } +/** + * @tc.name: RdbStore_Delete_With_Returning_001 + * @tc.desc: normal test + * @tc.type: FUNC + */ +HWTEST_P(RdbDeleteTest, RdbStore_Delete_With_Returning_001, TestSize.Level1) +{ + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store_->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + AbsRdbPredicates predicates("test"); + auto [status, res] = store_->Delete(predicates, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(res.changed, 1); + + int rowCount = -1; + ASSERT_EQ(res.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(res.results->GetColumnIndex("id", columnIndex), E_OK); + int64_t value; + ASSERT_EQ(res.results->GetLong(columnIndex, value), E_OK); + EXPECT_EQ(value, 1); +} + +/** + * @tc.name: RdbStore_Delete_With_Returning_002 + * @tc.desc: abnormal test, delete over returning limit + * @tc.type: FUNC + */ +HWTEST_P(RdbDeleteTest, RdbStore_Delete_With_Returning_002, TestSize.Level1) +{ + ValuesBuckets rows; + for (int i = 0; i < 1124; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto ret = store_->BatchInsert("test", rows); + EXPECT_EQ(ret.first, E_OK); + EXPECT_EQ(ret.second, 1124); + + AbsRdbPredicates predicates("test"); + auto [code, res] = store_->Delete(predicates, { "id" }); + EXPECT_EQ(code, E_OK); + EXPECT_EQ(res.changed, 1124); + int rowCount = -1; + ASSERT_EQ(res.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1024); +} + +/** + * @tc.name: RdbStore_Delete_With_Returning_003 + * @tc.desc: abnormal test, delete with returning field is string + * @tc.type: FUNC + */ +HWTEST_P(RdbDeleteTest, RdbStore_Delete_With_Returning_003, TestSize.Level1) +{ + ValuesBuckets rows; + for (int i = 0; i < 15; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim" + std::to_string(i)); + rows.Put(row); + } + auto ret = store_->BatchInsert("test", rows); + EXPECT_EQ(ret.first, E_OK); + EXPECT_EQ(ret.second, 15); + + AbsRdbPredicates predicates("test"); + auto [status, res] = store_->Delete(predicates, { "name" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(res.changed, 15); + + int rowCount = -1; + ASSERT_EQ(res.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 15); + int columnIndex = -1; + ASSERT_EQ(res.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + int i = 0; + while (i < 15) { + ASSERT_EQ(res.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "Jim" + std::to_string(i++)); + if (i < 15) { + ASSERT_EQ(res.results->GoToNextRow(), E_OK); + } + } +} + +/** + * @tc.name: RdbStore_Delete_With_Returning_004 + * @tc.desc: abnormal test, delete with returning field is blob + * @tc.type: FUNC + */ +HWTEST_P(RdbDeleteTest, RdbStore_Delete_With_Returning_004, TestSize.Level1) +{ + ValuesBuckets rows; + for (int i = 0; i < 15; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim" + std::to_string(i)); + std::vector blob(i + 1); + std::iota(blob.begin(), blob.end(), 1); + row.PutBlob("blobType", blob); + rows.Put(row); + } + auto ret = store_->BatchInsert("test", rows); + EXPECT_EQ(ret.first, E_OK); + EXPECT_EQ(ret.second, 15); + + AbsRdbPredicates predicates("test"); + auto [status, res] = store_->Delete(predicates, { "blobType" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(res.changed, 15); + + int rowCount = -1; + ASSERT_EQ(res.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 15); + int columnIndex = -1; + ASSERT_EQ(res.results->GetColumnIndex("blobType", columnIndex), E_OK); + int i = 0; + while (i < 15) { + std::vector blob; + ASSERT_EQ(res.results->GetBlob(columnIndex, blob), E_OK); + std::vector expectedBlob(++i); + std::iota(expectedBlob.begin(), expectedBlob.end(), 1); + EXPECT_EQ(blob, expectedBlob); + if (i < 15) { + ASSERT_EQ(res.results->GoToNextRow(), E_OK); + } + } +} + +/** + * @tc.name: RdbStore_Delete_With_Returning_005 + * @tc.desc: abnormal test, delete with returning field is not exist + * @tc.type: FUNC + */ +HWTEST_P(RdbDeleteTest, RdbStore_Delete_With_Returning_005, TestSize.Level1) +{ + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store_->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + AbsRdbPredicates predicates("test"); + auto [status, res] = store_->Delete(predicates, { "notExist" }); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(res.changed, -1); + ASSERT_EQ(res.results, nullptr); +} + +/** + * @tc.name: RdbStore_Delete_With_Returning_006 + * @tc.desc: abnormal test, delete with returning field is not exist + * @tc.type: FUNC + */ +HWTEST_P(RdbDeleteTest, RdbStore_Delete_With_Returning_006, TestSize.Level1) +{ + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store_->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 100); + auto [status, res] = store_->Delete(predicates, { "notExist" }); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(res.changed, -1); + ASSERT_EQ(res.results, nullptr); +} + +/** + * @tc.name: RdbStore_Delete_With_Returning_007 + * @tc.desc: normal test. delete from virtual table with returning + * @tc.type: FUNC + */ +HWTEST_P(RdbDeleteTest, RdbStore_Delete_With_Returning_007, TestSize.Level1) +{ + auto [execRet, execResult] = + store_->Execute("CREATE VIRTUAL TABLE IF NOT EXISTS articles USING fts5(title, content);"); + ASSERT_EQ(execRet, E_OK); + ValuesBuckets rows; + ValuesBucket row; + row.Put("title", "fts5"); + row.Put("content", "test virtual tables"); + rows.Put(std::move(row)); + auto [insertStatus, result] = + store_->BatchInsert("articles", rows, NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(insertStatus, E_OK); + + AbsRdbPredicates predicates("articles"); + predicates.EqualTo("title", "fts5"); + auto [status, res] = store_->Delete(predicates, { "title" }); + // DELETE RETURNING is not available on virtual tables + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(res.changed, -1); + + store_->Execute("Drop TABLE articles"); +} + +/** + * @tc.name: RdbStore_Delete_With_Returning_008 + * @tc.desc: normal test. delete with returning and trigger + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbDeleteTest, RdbStore_Delete_With_Returning_008, TestSize.Level1) +{ + auto [code, result1] = store_->Execute( + "CREATE TRIGGER before_delete BEFORE DELETE ON test" + " BEGIN UPDATE test SET name = 'li' WHERE name = 'wang'; END"); + + EXPECT_EQ(code, E_OK); + + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 200); + row.Put("name", "wang"); + rows.Put(std::move(row)); + row.Put("id", 201); + row.Put("name", "zhang"); + rows.Put(std::move(row)); + + auto [insertStatus, result] = + store_->BatchInsert("test", rows, { "name" }, NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(insertStatus, E_OK); + EXPECT_EQ(result.changed, 2); + + AbsRdbPredicates predicates("test"); + predicates.EqualTo("name", "zhang"); + auto [status, res] = store_->Delete(predicates, { "name" }); + + EXPECT_EQ(status, E_OK); + EXPECT_EQ(res.changed, 1); + int rowCount = -1; + ASSERT_EQ(res.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(res.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + ASSERT_EQ(res.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "zhang"); + + // Check the trigger effect + auto resultSet = store_->QuerySql("select name from test where id = 200"); + + rowCount = -1; + resultSet->GetRowCount(rowCount); + ASSERT_EQ(rowCount, 1); + ASSERT_EQ(resultSet->GoToNextRow(), E_OK); + columnIndex = -1; + resultSet->GetColumnIndex("name", columnIndex); + + value.clear(); + EXPECT_EQ(E_OK, resultSet->GetString(columnIndex, value)); + EXPECT_EQ(value, "li"); + + store_->Execute("DROP TRIGGER IF EXISTS before_delete"); +} INSTANTIATE_TEST_SUITE_P(DeleteTest, RdbDeleteTest, testing::Values(&g_store, &g_memDb)); } // namespace OHOS::RdbDeleteTest diff --git a/relational_store/test/native/rdb/unittest/rdb_distributed_test.cpp b/relational_store/test/native/rdb/unittest/rdb_distributed_test.cpp index aeaa88e36561ec584c31803c3be834675bba037b..34fc5c78d1890ce116dd7218bbed75b5108b2026 100644 --- a/relational_store/test/native/rdb/unittest/rdb_distributed_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_distributed_test.cpp @@ -185,7 +185,7 @@ HWTEST_F(RdbStoreDistributedTest, RdbStore_Distributed_002, TestSize.Level2) EXPECT_NE(nullptr, rdbStore); int errCode; EXPECT_EQ("", rdbStore->ObtainDistributedTableName("", "employee", errCode)); - EXPECT_EQ(-1, errCode); + EXPECT_EQ(E_ERROR, errCode); } /** @@ -198,7 +198,7 @@ HWTEST_F(RdbStoreDistributedTest, RdbStore_Distributed_003, TestSize.Level2) EXPECT_NE(nullptr, rdbStore); int errCode; EXPECT_EQ("", rdbStore->ObtainDistributedTableName("123456", "employee", errCode)); - EXPECT_EQ(-1, errCode); + EXPECT_EQ(E_ERROR, errCode); } /** diff --git a/relational_store/test/native/rdb/unittest/rdb_double_write_binlog_test.cpp b/relational_store/test/native/rdb/unittest/rdb_double_write_binlog_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..680a7b1b357572afb9c91b372acc960561e809e3 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_double_write_binlog_test.cpp @@ -0,0 +1,1460 @@ +/* + * Copyright (c) 2025 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 "RdbDoubleWriteBinlogTest" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "file_ex.h" +#include "logger.h" +#include "rdb_common.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "relational/relational_store_sqlite_ext.h" +#include "sqlite3.h" +#include "sqlite_connection.h" +#include "sqlite_utils.h" +#include "sqlite_global_config.h" +#include "sys/types.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; + +class RdbDoubleWriteBinlogTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static void CheckNumber( + std::shared_ptr &store, int num, int errCode = E_OK, const std::string &tableName = "test"); + static bool CheckFolderExist(const std::string &path); + void RemoveFolder(const std::string &path); + static void Insert(int64_t start, int count, bool isSlave = false, int dataSize = 0); + static void InsertNativeConn(sqlite3 *db, int64_t start, int count, int dataSize = 0); + void Update(int64_t start, int count, bool isSlave = false, int dataSize = 0); + void CheckProcess(std::shared_ptr &store); + void DeleteDbFile(const RdbStoreConfig &config); + void PutValue(std::shared_ptr &store, const std::string &data, int64_t id, int age); + static void WaitForBackupFinish(int32_t expectStatus, int maxTimes = 4000); + static void WaitForBinlogDelete(int maxTimes = 1000); + static void WaitForBinlogReplayFinish(); + void InitDb(HAMode mode = HAMode::MAIN_REPLICA, bool isOpenSlave = true); + int64_t GetRestoreTime(HAMode haMode, bool isOpenSlave = true); + + static const std::string databaseName; + static const std::string slaveDatabaseName; + static const std::string binlogDatabaseName; + static std::shared_ptr store; + static std::shared_ptr slaveStore; + static const std::string insertSql; + + enum SlaveStatus : uint32_t { + UNDEFINED, + BACKING_UP, + BACKUP_INTERRUPT, + BACKUP_FINISHED, + DB_CLOSING, + }; +}; + +const std::string RdbDoubleWriteBinlogTest::databaseName = RDB_TEST_PATH + "dual_write_binlog_test.db"; +const std::string RdbDoubleWriteBinlogTest::slaveDatabaseName = RDB_TEST_PATH + "dual_write_binlog_test_slave.db"; +const std::string RdbDoubleWriteBinlogTest::binlogDatabaseName = RDB_TEST_PATH + "dual_write_binlog_test.db_binlog"; +std::shared_ptr RdbDoubleWriteBinlogTest::store = nullptr; +std::shared_ptr RdbDoubleWriteBinlogTest::slaveStore = nullptr; +const std::string RdbDoubleWriteBinlogTest::insertSql = "INSERT INTO test(id, name, age, salary, blobType) VALUES" + "(?,?,?,?,?)"; + +const int CHECKAGE = 18; +const double CHECKCOLUMN = 100.5; +const int CHANGENUM = 12; +const int BINLOG_DELETE_PER_WAIT_TIME = 100000; // 100000us = 100ms +const int BINLOG_REPLAY_WAIT_TIME = 2; // 2s + +class DoubleWriteBinlogTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string createTableTest; +}; + +const std::string DoubleWriteBinlogTestOpenCallback::createTableTest = + std::string("CREATE TABLE IF NOT EXISTS test ") + std::string("(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary " + "REAL, blobType BLOB)"); + +int DoubleWriteBinlogTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(DoubleWriteBinlogTestOpenCallback::createTableTest); +} + +int DoubleWriteBinlogTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void RdbDoubleWriteBinlogTest::SetUpTestCase(void) +{ +} + +void RdbDoubleWriteBinlogTest::TearDownTestCase(void) +{ +} + +void RdbDoubleWriteBinlogTest::SetUp(void) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (!SqliteConnection::IsSupportBinlog(config)) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + testing::UnitTest *test = testing::UnitTest::GetInstance(); + ASSERT_NE(test, nullptr); + const testing::TestInfo *testInfo = test->current_test_info(); + ASSERT_NE(testInfo, nullptr); + LOG_INFO("---- double writebinlog test: %{public}s.%{public}s run start.", + testInfo->test_case_name(), testInfo->name()); +} + +void RdbDoubleWriteBinlogTest::TearDown(void) +{ + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName); + WaitForBinlogDelete(); + testing::UnitTest *test = testing::UnitTest::GetInstance(); + ASSERT_NE(test, nullptr); + const testing::TestInfo *testInfo = test->current_test_info(); + ASSERT_NE(testInfo, nullptr); + LOG_INFO("---- double writebinlog test: %{public}s.%{public}s run end.", + testInfo->test_case_name(), testInfo->name()); +} + +void RdbDoubleWriteBinlogTest::InitDb(HAMode mode, bool isOpenSlave) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + config.SetHaMode(mode); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(RdbDoubleWriteBinlogTest::store, nullptr); + store->ExecuteSql("DELETE FROM test"); + + if (isOpenSlave) { + RdbStoreConfig slaveConfig(RdbDoubleWriteBinlogTest::slaveDatabaseName); + DoubleWriteBinlogTestOpenCallback slaveHelper; + RdbDoubleWriteBinlogTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); + ASSERT_NE(RdbDoubleWriteBinlogTest::slaveStore, nullptr); + slaveStore->ExecuteSql("DELETE FROM test"); + } +} + +void RdbDoubleWriteBinlogTest::Insert(int64_t start, int count, bool isSlave, int dataSize) +{ + ValuesBucket values; + int64_t id = start; + int ret = E_OK; + for (int i = 0; i < count; i++) { + values.Clear(); + values.PutInt("id", id); + if (dataSize > 0) { + values.PutString("name", std::string(dataSize, 'a')); + } else { + values.PutString("name", std::string("zhangsan")); + } + values.PutInt("age", CHECKAGE); + values.PutDouble("salary", CHECKCOLUMN); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + if (isSlave) { + ret = slaveStore->Insert(id, "test", values); + } else { + ret = store->Insert(id, "test", values); + } + EXPECT_EQ(ret, E_OK); + id++; + } +} + +void RdbDoubleWriteBinlogTest::InsertNativeConn(sqlite3 *db, int64_t start, int count, int dataSize) +{ + int64_t id = start; + sqlite3_stmt *stat = nullptr; + EXPECT_EQ(sqlite3_prepare_v2(db, RdbDoubleWriteBinlogTest::insertSql.c_str(), -1, &stat, nullptr), SQLITE_OK); + for (int i = 0; i < count; i++) { + // bind parameters, 1 is the sequence number of field + sqlite3_bind_int(stat, 1, id); + std::string nameStr; + if (dataSize > 0) { + nameStr = std::string(dataSize, 'a'); + } else { + nameStr = std::string("zhangsan"); + } + // bind parameters, 2 is the sequence number of field + sqlite3_bind_text(stat, 2, nameStr.c_str(), -1, SQLITE_STATIC); + // bind parameters, 3 is the sequence number of field + sqlite3_bind_int(stat, 3, CHECKAGE); + // bind parameters, 4 is the sequence number of field + sqlite3_bind_double(stat, 4, CHECKCOLUMN); + uint8_t blob[] = { 1, 2, 3 }; + // bind parameters, 5 is the sequence number of field + sqlite3_bind_blob(stat, 5, blob, sizeof(blob), nullptr); + EXPECT_EQ(sqlite3_step(stat), SQLITE_DONE); + sqlite3_reset(stat); + id++; + } + sqlite3_finalize(stat); +} + +void RdbDoubleWriteBinlogTest::Update(int64_t start, int count, bool isSlave, int dataSize) +{ + ValuesBucket values; + int64_t id = start; + int age = 20; + int ret = E_OK; + for (int i = 0; i < count; i++) { + values.Clear(); + values.PutInt("id", id); + if (dataSize > 0) { + values.PutString("name", std::string(dataSize, 'a')); + } else { + values.PutString("name", std::string("zhangsan")); + } + values.PutInt("age", age); + values.PutDouble("salary", CHECKCOLUMN); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + if (isSlave) { + ret = slaveStore->Replace(id, "test", values); + } else { + ret = store->Replace(id, "test", values); + } + EXPECT_EQ(ret, E_OK); + id++; + } +} + +void RdbDoubleWriteBinlogTest::WaitForBackupFinish(int32_t expectStatus, int maxTimes) +{ + int32_t curStatus = store->GetBackupStatus(); + int tryTimes = 0; + while (curStatus != expectStatus && (++tryTimes <= maxTimes)) { + usleep(50000); // 50000 delay + curStatus = store->GetBackupStatus(); + } + LOG_INFO("----------cur backup Status:%{public}d---------", curStatus); + ASSERT_EQ(curStatus, expectStatus); +} + +void RdbDoubleWriteBinlogTest::WaitForBinlogDelete(int maxTimes) +{ + int waitTimes = 0; + while (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName) && waitTimes < maxTimes) { + usleep(BINLOG_DELETE_PER_WAIT_TIME); + waitTimes++; + LOG_INFO("---- Binlog replay in progress, waiting for finish"); + RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName); + } + EXPECT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); +} + +void RdbDoubleWriteBinlogTest::WaitForBinlogReplayFinish() +{ + sleep(BINLOG_REPLAY_WAIT_TIME); +} + +void RdbDoubleWriteBinlogTest::CheckNumber( + std::shared_ptr &store, int num, int errCode, const std::string &tableName) +{ + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM " + tableName); + ASSERT_NE(resultSet, nullptr); + int countNum; + int ret = resultSet->GetRowCount(countNum); + EXPECT_EQ(ret, errCode); + EXPECT_EQ(num, countNum); +} + +bool RdbDoubleWriteBinlogTest::CheckFolderExist(const std::string &path) +{ + if (access(path.c_str(), F_OK) != 0) { + return false; + } + return true; +} + +void RdbDoubleWriteBinlogTest::RemoveFolder(const std::string &path) +{ + std::filesystem::path folder(path); + for (const auto &entry : std::filesystem::directory_iterator(folder)) { + if (entry.is_directory()) { + RemoveFolder(entry.path()); + } else { + std::filesystem::remove(entry.path()); + } + } + std::filesystem::remove(folder); +} + +typedef int (*GtForkCallbackT)(const char *arg); +static pid_t GtFork(GtForkCallbackT callback, const char *arg) +{ + pid_t pid = fork(); + if (pid == 0) { + int ret = callback(arg); + _exit(ret); + } + return pid; +} + +static int InsertProcess(const char *arg) +{ + std::string test = std::string(arg); + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + int errCode = E_OK; + config.SetHaMode(HAMode::MAIN_REPLICA); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(RdbDoubleWriteBinlogTest::store, nullptr); + int64_t id = 11; + int count = 1000; + RdbDoubleWriteBinlogTest::Insert(id, count); + int32_t num = 1010; + RdbDoubleWriteBinlogTest::CheckNumber(RdbDoubleWriteBinlogTest::store, num); + return 0; +} + +static int InsertTwoProcess(const char *arg) +{ + std::string test = std::string(arg); + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + int errCode = E_OK; + config.SetHaMode(HAMode::MAIN_REPLICA); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(RdbDoubleWriteBinlogTest::store, nullptr); + bool isBinlogExist = RdbDoubleWriteBinlogTest::CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + EXPECT_TRUE(isBinlogExist); + int count = 10; + for (int i = 0; i < count; i++) { + errCode = RdbDoubleWriteBinlogTest::store->Backup(std::string(""), {}); + } + return 0; +} + +static int InsertManualProcess(const char *arg) +{ + std::string test = std::string(arg); + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + int errCode = E_OK; + config.SetHaMode(HAMode::MANUAL_TRIGGER); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(RdbDoubleWriteBinlogTest::store, nullptr); + int64_t id = 11; + int count = 1000; + RdbDoubleWriteBinlogTest::Insert(id, count); + int32_t num = 1010; + RdbDoubleWriteBinlogTest::CheckNumber(RdbDoubleWriteBinlogTest::store, num); + return 0; +} + +static int InsertManualTwoProcess(const char *arg) +{ + std::string test = std::string(arg); + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + int errCode = E_OK; + config.SetHaMode(HAMode::MANUAL_TRIGGER); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(RdbDoubleWriteBinlogTest::store, nullptr); + bool isBinlogExist = RdbDoubleWriteBinlogTest::CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + EXPECT_TRUE(isBinlogExist); + int count = 10; + for (int i = 0; i < count; i++) { + errCode = RdbDoubleWriteBinlogTest::store->Backup(std::string(""), {}); + } + return 0; +} + +void RdbDoubleWriteBinlogTest::CheckProcess(std::shared_ptr &store) +{ + int64_t changeId = 2; + int changeCount = 4; + Update(changeId, changeCount); + int deletedRows; + store->Delete(deletedRows, "test", "id == 8"); + store->Delete(deletedRows, "test", "id == 9"); + int ret = store->BeginTransaction(); + EXPECT_EQ(ret, E_OK); + std::string sqlCreateIndex = "CREATE INDEX id_index ON test (id);"; + store->ExecuteSql(sqlCreateIndex.c_str()); + ret = store->Commit(); + EXPECT_EQ(ret, E_OK); + ret = store->BeginTransaction(); + EXPECT_EQ(ret, E_OK); + changeId = CHANGENUM; + Update(changeId, changeCount); + store->Delete(deletedRows, "test", "id == 18"); + store->Delete(deletedRows, "test", "id == 19"); + ret = store->RollBack(); + EXPECT_EQ(ret, E_OK); +} + +void RdbDoubleWriteBinlogTest::DeleteDbFile(const RdbStoreConfig &config) +{ + std::string dbFile; + auto errCode = SqliteGlobalConfig::GetDbPath(config, dbFile); + if (errCode != E_OK || dbFile.empty()) { + return; + } + std::ifstream binFile(dbFile); + if (binFile.is_open()) { + std::string content((std::istreambuf_iterator(binFile)), (std::istreambuf_iterator())); + std::remove(dbFile.c_str()); + } +} + +void RdbDoubleWriteBinlogTest::PutValue(std::shared_ptr &store, const std::string &data, int64_t id, int age) +{ + ValuesBucket values; + values.PutInt("id", id); + values.PutString("name", data); + values.PutInt("age", age); + values.PutDouble("salary", CHECKCOLUMN); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_001, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + config.SetHaMode(HAMode::MAIN_REPLICA); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + ASSERT_TRUE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + store = nullptr; + RdbHelper::DeleteRdbStore(config); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_002, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + config.SetHaMode(HAMode::MANUAL_TRIGGER); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_FALSE(isBinlogExist); + errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_003, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + config.SetHaMode(HAMode::MAIN_REPLICA); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + int64_t id = 1; + int count = 10; + Insert(id, count); + store = nullptr; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isSlaveDbFileExist = OHOS::FileExists(RdbDoubleWriteBinlogTest::slaveDatabaseName); + ASSERT_TRUE(isSlaveDbFileExist); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_004, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + config.SetHaMode(HAMode::MANUAL_TRIGGER); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + int64_t id = 1; + int count = 10; + Insert(id, count); + store = nullptr; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isSlaveDbFileExist = OHOS::FileExists(RdbDoubleWriteBinlogTest::slaveDatabaseName); + ASSERT_FALSE(isSlaveDbFileExist); + errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + isSlaveDbFileExist = OHOS::FileExists(RdbDoubleWriteBinlogTest::slaveDatabaseName); + ASSERT_TRUE(isSlaveDbFileExist); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_005, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(); + int64_t id = 1; + int count = 10; + Insert(id, count); + Insert(id, count, true); + store = nullptr; + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_006, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + int errCode = E_OK; + config.SetHaMode(HAMode::MANUAL_TRIGGER); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + store->ExecuteSql("DELETE FROM test"); + + // open slave for conflict by compress + sqlite3 *db = nullptr; + int rc = sqlite3_open_v2(RdbDoubleWriteBinlogTest::slaveDatabaseName.c_str(), + &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); + EXPECT_EQ(rc, SQLITE_OK); + EXPECT_NE(db, nullptr); + sqlite3_close_v2(db); + + int64_t id = 1; + int count = 10; + Insert(id, count); + store = nullptr; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_007, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(); + int64_t id = 1; + int count = 10; + Insert(id, count); + Insert(id, count, true); + + SqliteUtils::SetSlaveInvalid(RdbDoubleWriteBinlogTest::databaseName); + std::string failureFlagPath = RdbDoubleWriteBinlogTest::databaseName + +"-slaveFailure"; + bool isFlagFileExists = OHOS::FileExists(failureFlagPath); + ASSERT_TRUE(isFlagFileExists); + store = nullptr; + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_008, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + int errCode = E_OK; + config.SetHaMode(HAMode::MANUAL_TRIGGER); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + store->ExecuteSql("DELETE FROM test"); + + // open slave for conflict by compress + sqlite3 *db = nullptr; + int rc = sqlite3_open_v2(RdbDoubleWriteBinlogTest::slaveDatabaseName.c_str(), + &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); + EXPECT_EQ(rc, SQLITE_OK); + EXPECT_NE(db, nullptr); + sqlite3_close_v2(db); + + int64_t id = 1; + int count = 10; + Insert(id, count); + + SqliteUtils::SetSlaveInvalid(RdbDoubleWriteBinlogTest::databaseName); + std::string failureFlagPath = RdbDoubleWriteBinlogTest::databaseName + +"-slaveFailure"; + bool isFlagFileExists = OHOS::FileExists(failureFlagPath); + ASSERT_TRUE(isFlagFileExists); + store = nullptr; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_FALSE(isBinlogExist); + errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_009, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(HAMode::MAIN_REPLICA, false); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + int64_t id = 1; + int count = 10; + Insert(id, count); + + store = nullptr; + config.SetHaMode(HAMode::MAIN_REPLICA); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); + id = 11; + Insert(id, count); + WaitForBinlogReplayFinish(); + store = nullptr; + DeleteDbFile(config); + + config.SetHaMode(HAMode::MAIN_REPLICA); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + WaitForBackupFinish(BACKUP_FINISHED); + WaitForBinlogReplayFinish(); + int32_t num = 20; + RdbDoubleWriteBinlogTest::CheckNumber(store, num); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_010, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + int errCode = E_OK; + config.SetHaMode(HAMode::MANUAL_TRIGGER); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + store->ExecuteSql("DELETE FROM test"); + + int64_t id = 1; + int count = 10; + Insert(id, count); + + // open slave for conflict by compress + sqlite3 *db = nullptr; + int rc = sqlite3_open_v2(RdbDoubleWriteBinlogTest::slaveDatabaseName.c_str(), + &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "compressvfs"); + EXPECT_EQ(rc, SQLITE_OK); + EXPECT_NE(db, nullptr); + const char *ddl = DoubleWriteBinlogTestOpenCallback::createTableTest.c_str(); + EXPECT_EQ(sqlite3_exec(db, ddl, nullptr, nullptr, nullptr), SQLITE_OK); + InsertNativeConn(db, id, count); + sqlite3_close_v2(db); + + store = nullptr; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + WaitForBinlogReplayFinish(); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); + id = 11; + Insert(id, count); + store = nullptr; + DeleteDbFile(config); + + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + WaitForBackupFinish(BACKUP_FINISHED); + int32_t num = 20; + RdbDoubleWriteBinlogTest::CheckNumber(store, num); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_011, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(HAMode::MAIN_REPLICA, false); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + int64_t id = 1; + int count = 10; + Insert(id, count); + + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); + id = 11; + Insert(id, count); + int32_t num = 20; + RdbDoubleWriteBinlogTest::CheckNumber(store, num); + CheckProcess(store); + + store = nullptr; + DeleteDbFile(config); + + config.SetHaMode(HAMode::MAIN_REPLICA); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + WaitForBackupFinish(BACKUP_FINISHED); + WaitForBinlogReplayFinish(); + num = 18; + RdbDoubleWriteBinlogTest::CheckNumber(store, num); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_012, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + + InitDb(HAMode::MAIN_REPLICA, false); + int64_t id = 1; + int count = 10; + Insert(id, count); + + config.SetHaMode(HAMode::MANUAL_TRIGGER); + DoubleWriteBinlogTestOpenCallback helper; + int errCode = E_OK; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); + id = 11; + Insert(id, count); + int32_t num = 20; + RdbDoubleWriteBinlogTest::CheckNumber(store, num); + CheckProcess(store); + + store = nullptr; + DeleteDbFile(config); + + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + WaitForBackupFinish(BACKUP_FINISHED); + num = 18; + RdbDoubleWriteBinlogTest::CheckNumber(store, num); +} + +static int Callback(void *data, int argc, char **argv, char **azColName) +{ + int64_t *count = (int64_t *)data; + if (argc > 0 && argv[0] != NULL) { + *count = atoi(argv[0]); + } + return 0; +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_013, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + int errCode = E_OK; + config.SetHaMode(HAMode::MAIN_REPLICA); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + + bool isSlaveDbFileExists = OHOS::FileExists(RdbDoubleWriteBinlogTest::slaveDatabaseName); + ASSERT_TRUE(isSlaveDbFileExists); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); + + int64_t id = 1; + int count = 20; + Insert(id, count); + CheckProcess(store); + + int64_t num = 18; + RdbDoubleWriteBinlogTest::CheckNumber(store, num); + errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + + // open slave for conflict by compress + sqlite3 *db = nullptr; + int rc = sqlite3_open_v2(RdbDoubleWriteBinlogTest::slaveDatabaseName.c_str(), + &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "compressvfs"); + EXPECT_EQ(rc, SQLITE_OK); + EXPECT_NE(db, nullptr); + + count = 0; + rc = sqlite3_exec(db, "SELECT COUNT(1) FROM test;", Callback, &count, nullptr); + EXPECT_EQ(rc, SQLITE_OK); + EXPECT_EQ(count, num); + sqlite3_close_v2(db); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_014, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + int errCode = E_OK; + config.SetHaMode(HAMode::MANUAL_TRIGGER); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + + bool isSlaveDbFileExists = OHOS::FileExists(RdbDoubleWriteBinlogTest::slaveDatabaseName); + ASSERT_FALSE(isSlaveDbFileExists); + errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + WaitForBackupFinish(BACKUP_FINISHED); + isSlaveDbFileExists = OHOS::FileExists(RdbDoubleWriteBinlogTest::slaveDatabaseName); + ASSERT_TRUE(isSlaveDbFileExists); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); + + int64_t id = 1; + int count = 20; + Insert(id, count); + CheckProcess(store); + + int64_t num = 18; + RdbDoubleWriteBinlogTest::CheckNumber(store, num); + errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + + // open slave for conflict by compress + sqlite3 *db = nullptr; + int rc = sqlite3_open_v2(RdbDoubleWriteBinlogTest::slaveDatabaseName.c_str(), + &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "compressvfs"); + EXPECT_EQ(rc, SQLITE_OK); + EXPECT_NE(db, nullptr); + count = 0; + rc = sqlite3_exec(db, "SELECT COUNT(1) FROM test;", Callback, &count, nullptr); + EXPECT_EQ(rc, SQLITE_OK); + EXPECT_EQ(count, num); + sqlite3_close_v2(db); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_015, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(); + int64_t id = 1; + int count = 10; + Insert(id, count); + store = nullptr; + std::string test = "lisi"; + pid_t pid1 = GtFork(InsertProcess, test.c_str()); + ASSERT_GT(pid1, 0); + InsertTwoProcess(test.c_str()); + int status; +// waitpid(pid1, &status, 0); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_016, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + int errCode = E_OK; + config.SetHaMode(HAMode::MANUAL_TRIGGER); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + store->ExecuteSql("DELETE FROM test"); + int64_t id = 1; + int count = 10; + Insert(id, count); + EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); + ASSERT_TRUE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + + RdbStoreConfig slaveConfig(RdbDoubleWriteBinlogTest::slaveDatabaseName); + DoubleWriteBinlogTestOpenCallback slaveHelper; + RdbDoubleWriteBinlogTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); + EXPECT_NE(slaveStore, nullptr); + + store = nullptr; + std::string test = "lisi"; + pid_t pid1 = GtFork(InsertManualProcess, test.c_str()); + ASSERT_GT(pid1, 0); + InsertManualTwoProcess(test.c_str()); + int status; +// waitpid(pid1, &status, 0); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_017, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(); + int64_t id = 1; + int count = 10; + Insert(id, count); + store = nullptr; + + config.SetHaMode(HAMode::MAIN_REPLICA); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); + + size_t bigSize = 1024 * 1024 * 128; + std::string data(bigSize, 'a'); + PutValue(store, data, 11, 18); + PutValue(store, data, 12, 19); + + store = nullptr; + id = 13; + for (int i = 0; i < count; i++) { + config.SetHaMode(HAMode::MAIN_REPLICA); + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + PutValue(store, data, id, CHECKAGE); + store = nullptr; + id++; + } + WaitForBinlogReplayFinish(); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_018, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(); + int64_t id = 1; + int count = 10; + Insert(id, count); + store = nullptr; + + config.SetHaMode(HAMode::MAIN_REPLICA); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); + + size_t bigSize = 1024 * 1024 * 13; + std::string data(bigSize, 'a'); + + store = nullptr; + id = 11; + for (int i = 0; i < count; i++) { + config.SetHaMode(HAMode::MAIN_REPLICA); + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + PutValue(store, data, id, CHECKAGE); + store = nullptr; + id++; + } + WaitForBinlogReplayFinish(); +} + +/** + * @tc.name: RdbStore_Binlog_019 + * @tc.desc: open MAIN_REPLICA db when replica is invalid, + * then batch insert new data and test main and replica are the same + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_019, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + InitDb(); + int64_t id = 1; + int count = 10; + Insert(id, count); + store = nullptr; + slaveStore = nullptr; + SqliteUtils::SetSlaveInvalid(RdbDoubleWriteBinlogTest::databaseName); + + LOG_INFO("---- open db when slave is invalid to trigger backup"); + config.SetHaMode(HAMode::MAIN_REPLICA); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + WaitForBinlogReplayFinish(); + LOG_INFO("---- insert after backup after wait"); + int totalCount = count; + id += totalCount; + count = 1000; // 1000 is one batch + Insert(id, count); + totalCount += count; + EXPECT_TRUE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + EXPECT_FALSE(SqliteUtils::IsSlaveInvalid(RdbDoubleWriteBinlogTest::databaseName)); + RdbDoubleWriteBinlogTest::CheckNumber(store, totalCount); + store = nullptr; + SqliteUtils::DeleteFile(databaseName); + LOG_INFO("---- check for data count after restore"); + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + RdbDoubleWriteBinlogTest::CheckNumber(store, totalCount); +} + +static int MockCleanBinlog(sqlite3* db, BinlogFileCleanModeE mode) +{ + return SQLITE_ERROR; +} + +static int MockSupportBinlogOff(const char *name) +{ + return SQLITE_ERROR; +} +/** + * @tc.name: RdbStore_Binlog_020 + * @tc.desc: test backup when binlog clean failed will mark slave invalid + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_020, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + InitDb(); + int64_t id = 1; + int count = 10; + Insert(id, count); + +// LOG_INFO("---- let binlog clean return ERROR"); +// auto originalApi = sqlite3_export_extra_symbols; +// struct sqlite3_api_routines_extra mockApi = *sqlite3_export_extra_symbols; +// mockApi.clean_binlog = MockCleanBinlog; +// sqlite3_export_extra_symbols = &mockApi; +// +// LOG_INFO("---- binlog clean failed should mark invalid"); +// EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); +// EXPECT_TRUE(SqliteUtils::IsSlaveInvalid(RdbDoubleWriteBinlogTest::databaseName)); +// sqlite3_export_extra_symbols = originalApi; +} + +/** + * @tc.name: RdbStore_Binlog_021 + * @tc.desc: test delete rdb store will work if binlog is not supported + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_021, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + InitDb(); + int64_t id = 1; + int count = 10; + Insert(id, count); + store = nullptr; + slaveStore = nullptr; + + LOG_INFO("---- let support binlog becomes off"); + struct sqlite3_api_routines_relational mockApi = *sqlite3_export_relational_symbols; + mockApi.is_support_binlog = MockSupportBinlogOff; + auto originalApi = sqlite3_export_relational_symbols; + sqlite3_export_relational_symbols = &mockApi; + + LOG_INFO("---- rdb delete store should return ok"); + EXPECT_EQ(RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName), E_OK); + sqlite3_export_relational_symbols = originalApi; +} + +static int64_t GetInsertTime(std::shared_ptr &rdbStore, int repeat, size_t dataSize) +{ + size_t bigSize = dataSize; + std::string data(bigSize, 'a'); + + LOG_INFO("---- start insert ----"); + int64_t totalCost = 0; + for (int64_t id = 0; id < repeat; id++) { + ValuesBucket values; + values.PutInt("id", id); + values.PutString("name", data); + values.PutInt("age", id); + values.PutDouble("salary", CHECKCOLUMN); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + auto begin = std::chrono::high_resolution_clock::now(); + int ret = rdbStore->Insert(id, "test", values); + auto stop = std::chrono::high_resolution_clock::now(); + EXPECT_EQ(ret, E_OK); + totalCost += std::chrono::duration_cast(stop - begin).count(); + } + return totalCost; +} + +static int64_t GetUpdateTime(std::shared_ptr &rdbStore, int batchSize, int repeat, size_t dataSize) +{ + size_t bigSize = dataSize; + std::string data(bigSize, 'b'); + LOG_INFO("---- start update ----"); + int64_t totalCost = 0; + for (int i = 0; i < repeat; i++) { + int start = i * batchSize; + int end = (i + 1) * batchSize; + std::string sql = "update test set name = '" + data + "' where id >= " + std::to_string(start) + + " and id < " + std::to_string(end) + ";"; + auto begin = std::chrono::high_resolution_clock::now(); + int ret = rdbStore->ExecuteSql(sql); + auto stop = std::chrono::high_resolution_clock::now(); + EXPECT_EQ(ret, E_OK); + totalCost += std::chrono::duration_cast(stop - begin).count(); + } + return totalCost; +} + +static int64_t GetDeleteTime(std::shared_ptr &rdbStore, int batchSize, int repeat) +{ + LOG_INFO("---- start delete ----"); + int64_t totalCost = 0; + for (int i = 0; i < repeat; i++) { + int start = i * batchSize; + int end = (i + 1) * batchSize; + std::string sql = + "delete from test where id >= " + std::to_string(start) + " and id < " + std::to_string(end) + ";"; + auto begin = std::chrono::high_resolution_clock::now(); + int ret = rdbStore->ExecuteSql(sql); + auto stop = std::chrono::high_resolution_clock::now(); + EXPECT_EQ(ret, E_OK); + totalCost += std::chrono::duration_cast(stop - begin).count(); + } + return totalCost; +} + +int64_t RdbDoubleWriteBinlogTest::GetRestoreTime(HAMode haMode, bool isOpenSlave) +{ + InitDb(haMode, isOpenSlave); + EXPECT_NE(store, nullptr); + if (haMode == HAMode::MANUAL_TRIGGER) { + int errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + } + int id = 1; + int totalCount = 20000; + int size = 1024; + Insert(id, totalCount, false, size); + store = nullptr; + + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + DoubleWriteBinlogTestOpenCallback helper; + config.SetHaMode(haMode); + DeleteDbFile(config); + + int errCode = E_OK; + auto begin = std::chrono::high_resolution_clock::now(); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + auto stop = std::chrono::high_resolution_clock::now(); + EXPECT_NE(store, nullptr); + return std::chrono::duration_cast(stop - begin).count(); +} + +/** + * @tc.name: RdbStore_Binlog_Performance_001 + * @tc.desc: test performance of insert, update, query and delete in main_replica + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_Performance_001, TestSize.Level2) +{ + LOG_INFO("----RdbStore_Binlog_Performance_001 start----"); + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(HAMode::SINGLE); + EXPECT_NE(store, nullptr); + if (!CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + return; + } + + int totalCount = 20000; + int dataSize = 1024; + int batchSize = 10; + auto T1_2 = GetInsertTime(store, totalCount, dataSize); + auto T2_2 = GetUpdateTime(store, batchSize, totalCount / batchSize, dataSize); + auto T3_2 = GetDeleteTime(store, batchSize, totalCount / batchSize); + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName); + WaitForBinlogDelete(); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + + InitDb(HAMode::MAIN_REPLICA); + EXPECT_NE(store, nullptr); + + auto T1 = GetInsertTime(store, totalCount, dataSize); + auto T2 = GetUpdateTime(store, batchSize, totalCount / batchSize, dataSize); + auto T3 = GetDeleteTime(store, batchSize, totalCount / batchSize); + + EXPECT_LT(T1, T1_2 * 1.8); + EXPECT_LT(T2, T2_2 * 1.8); + EXPECT_LT(T3, T3_2 * 1.8); + LOG_INFO("----RdbStore_Binlog_Performance_001----, %{public}" PRId64 ", %{public}" PRId64 ", %{public}" PRId64 ",", + T1, T2, T3); + LOG_INFO("----RdbStore_Binlog_Performance_001----, %{public}" PRId64 ", %{public}" PRId64 ", %{public}" PRId64 ",", + T1_2, T2_2, T3_2); +} + +/** + * @tc.name: RdbStore_Binlog_Performance_002 + * @tc.desc: test performance of insert, update, query and delete in mannual_trigger + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_Performance_002, TestSize.Level2) +{ + LOG_INFO("----RdbStore_Binlog_Performance_002 start----"); + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(HAMode::SINGLE); + ASSERT_NE(store, nullptr); + + int totalCount = 20000; + int dataSize = 200; + int batchSize = 1; + auto T1_2 = GetInsertTime(store, totalCount, dataSize); + auto T2_2 = GetUpdateTime(store, batchSize, totalCount / batchSize, dataSize); + auto T3_2 = GetDeleteTime(store, batchSize, totalCount / batchSize); + + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName); + WaitForBinlogDelete(); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + + InitDb(HAMode::MANUAL_TRIGGER); + EXPECT_NE(store, nullptr); + int errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + if (!CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + return; + } + + auto T1 = GetInsertTime(store, totalCount, dataSize); + auto T2 = GetUpdateTime(store, batchSize, totalCount / batchSize, dataSize); + auto T3 = GetDeleteTime(store, batchSize, totalCount / batchSize); + + EXPECT_LT(T1, T1_2 * 1.8); + EXPECT_LT(T2, T2_2 * 1.8); + EXPECT_LT(T3, T3_2 * 1.8); + LOG_INFO("----RdbStore_Binlog_Performance_002----, %{public}" PRId64 ", %{public}" PRId64 ", %{public}" PRId64 ",", + T1, T2, T3); + LOG_INFO("----RdbStore_Binlog_Performance_002----, %{public}" PRId64 ", %{public}" PRId64 ", %{public}" PRId64 ",", + T1_2, T2_2, T3_2); +} + +/** + * @tc.name: RdbStore_Binlog_Performance_003 + * @tc.desc: test performance of insert, update, query and delete in main_replica with large data + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_Performance_003, TestSize.Level2) +{ + LOG_INFO("----RdbStore_Binlog_Performance_003 start----"); + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(HAMode::SINGLE); + EXPECT_NE(store, nullptr); + + int totalCount = 200; + int dataSize = 1024 * 1024; + int batchSize = 10; + auto T1_2 = GetInsertTime(store, totalCount, dataSize); + auto T2_2 = GetUpdateTime(store, batchSize, totalCount / batchSize, dataSize); + auto T3_2 = GetDeleteTime(store, batchSize, totalCount / batchSize); + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName); + WaitForBinlogDelete(); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + + InitDb(HAMode::MAIN_REPLICA); + EXPECT_NE(store, nullptr); + if (!CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + return; + } + + auto T1 = GetInsertTime(store, totalCount, dataSize); + auto T2 = GetUpdateTime(store, batchSize, totalCount / batchSize, dataSize); + auto T3 = GetDeleteTime(store, batchSize, totalCount / batchSize); + + EXPECT_LT(T1, T1_2 * 1.8); + EXPECT_LT(T2, T2_2 * 1.8); + EXPECT_LT(T3, T3_2 * 1.8); + LOG_INFO("----RdbStore_Binlog_Performance_003----, %{public}" PRId64 ", %{public}" PRId64 ", %{public}" PRId64 ",", + T1, T2, T3); + LOG_INFO("----RdbStore_Binlog_Performance_003----, %{public}" PRId64 ", %{public}" PRId64 ", %{public}" PRId64 ",", + T1_2, T2_2, T3_2); +} + +/** + * @tc.name: RdbStore_Binlog_Performance_004 + * @tc.desc: test performance of insert, update, query and delete in mannual_trigger with large data + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_Performance_004, TestSize.Level2) +{ + LOG_INFO("----RdbStore_Binlog_Performance_004 start----"); + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(HAMode::SINGLE); + EXPECT_NE(store, nullptr); + + int totalCount = 200; + int dataSize = 1024 * 1024; + int batchSize = 10; + auto T1_2 = GetInsertTime(store, totalCount, dataSize); + auto T2_2 = GetUpdateTime(store, batchSize, totalCount / batchSize, dataSize); + auto T3_2 = GetDeleteTime(store, batchSize, totalCount / batchSize); + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName); + WaitForBinlogDelete(); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + + InitDb(HAMode::MANUAL_TRIGGER); + ASSERT_NE(store, nullptr); + int errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + if (!CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + return; + } + + auto T1 = GetInsertTime(store, totalCount, dataSize); + auto T2 = GetUpdateTime(store, batchSize, totalCount / batchSize, dataSize); + auto T3 = GetDeleteTime(store, batchSize, totalCount / batchSize); + + EXPECT_LT(T1, T1_2 * 1.8); + EXPECT_LT(T2, T2_2 * 1.8); + EXPECT_LT(T3, T3_2 * 1.8); + LOG_INFO("----RdbStore_Binlog_Performance_004----, %{public}" PRId64 ", %{public}" PRId64 ", %{public}" PRId64 ",", + T1, T2, T3); + LOG_INFO("----RdbStore_Binlog_Performance_004----, %{public}" PRId64 ", %{public}" PRId64 ", %{public}" PRId64 ",", + T1_2, T2_2, T3_2); +} + +/** + * @tc.name: RdbStore_Binlog_Performance_005 + * @tc.desc: test performance of restore in main_replica + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_Performance_005, TestSize.Level3) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + struct sqlite3_api_routines_relational mockApi = *sqlite3_export_relational_symbols; + mockApi.is_support_binlog = MockSupportBinlogOff; + auto originalApi = sqlite3_export_relational_symbols; + sqlite3_export_relational_symbols = &mockApi; + EXPECT_EQ(SqliteConnection::IsSupportBinlog(config), false); + LOG_INFO("----RdbStore_Binlog_Performance_005 binlog off----"); + auto T1 = GetRestoreTime(HAMode::MAIN_REPLICA); + + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName); + WaitForBinlogDelete(); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + sqlite3_export_relational_symbols = originalApi; + EXPECT_EQ(SqliteConnection::IsSupportBinlog(config), true); + LOG_INFO("----RdbStore_Binlog_Performance_005 binlog on----"); + auto T1_2 = GetRestoreTime(HAMode::MAIN_REPLICA); + EXPECT_GT(T1 * 1.8, T1_2); + LOG_INFO("----RdbStore_Binlog_Performance_005----, %{public}" PRId64 ", %{public}" PRId64 ",", T1, T1_2); +} + +/** + * @tc.name: RdbStore_Binlog_Performance_006 + * @tc.desc: test performance of restore in mannual_trigger + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_Performance_006, TestSize.Level3) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + struct sqlite3_api_routines_relational mockApi = *sqlite3_export_relational_symbols; + mockApi.is_support_binlog = MockSupportBinlogOff; + auto originalApi = sqlite3_export_relational_symbols; + sqlite3_export_relational_symbols = &mockApi; + EXPECT_EQ(SqliteConnection::IsSupportBinlog(config), false); + LOG_INFO("----RdbStore_Binlog_Performance_006 binlog off----"); + auto T1 = GetRestoreTime(HAMode::MANUAL_TRIGGER, false); + + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName); + WaitForBinlogDelete(); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + sqlite3_export_relational_symbols = originalApi; + EXPECT_EQ(SqliteConnection::IsSupportBinlog(config), true); + LOG_INFO("----RdbStore_Binlog_Performance_006 binlog on----"); + auto T1_2 = GetRestoreTime(HAMode::MANUAL_TRIGGER, false); + EXPECT_GT(T1 * 1.8, T1_2); + LOG_INFO("----RdbStore_Binlog_Performance_006----, %{public}" PRId64 ", %{public}" PRId64 ",", T1, T1_2); +} diff --git a/relational_store/test/native/rdb/unittest/rdb_double_write_concurrent_test.cpp b/relational_store/test/native/rdb/unittest/rdb_double_write_concurrent_test.cpp index 4ab065f3957a7e01f19882f3405c1655e6102eb7..394a1969efe0b7a63e748c1cd631d3d0e97bae5c 100644 --- a/relational_store/test/native/rdb/unittest/rdb_double_write_concurrent_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_double_write_concurrent_test.cpp @@ -66,10 +66,10 @@ protected: enum SlaveStatus : uint32_t { UNDEFINED, - DB_NOT_EXITS, BACKING_UP, BACKUP_INTERRUPT, BACKUP_FINISHED, + DB_CLOSING, }; }; diff --git a/relational_store/test/native/rdb/unittest/rdb_double_write_test.cpp b/relational_store/test/native/rdb/unittest/rdb_double_write_test.cpp index 4438c31676b2b6c26b20a7e75d4693d30647688e..8cb38c9f2bb33d5cb92a4a3fc351bbc2778b1d03 100644 --- a/relational_store/test/native/rdb/unittest/rdb_double_write_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_double_write_test.cpp @@ -1,1172 +1,1787 @@ -/* - * 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. - */ -#define LOG_TAG "RdbDoubleWriteTest" -#include -#include -#include - -#include -#include - -#include "common.h" -#include "file_ex.h" -#include "logger.h" -#include "rdb_common.h" -#include "rdb_errno.h" -#include "rdb_helper.h" -#include "rdb_open_callback.h" -#include "sqlite_utils.h" -#include "sys/types.h" - -using namespace testing::ext; -using namespace OHOS::NativeRdb; -using namespace OHOS::Rdb; - -class RdbDoubleWriteTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - void CheckResultSet(std::shared_ptr &store); - void CheckAge(std::shared_ptr &resultSet); - void CheckSalary(std::shared_ptr &resultSet); - void CheckBlob(std::shared_ptr &resultSet); - void CheckNumber( - std::shared_ptr &store, int num, int errCode = E_OK, const std::string &tableName = "test"); - void Insert(int64_t start, int count, bool isSlave = false, int dataSize = 0); - void WaitForBackupFinish(int32_t expectStatus, int maxTimes = 400); - void TryInterruptBackup(); - void InitDb(); - - static const std::string DATABASE_NAME; - static const std::string SLAVE_DATABASE_NAME; - static std::shared_ptr store; - static std::shared_ptr slaveStore; - static std::shared_ptr store3; - - enum SlaveStatus : uint32_t { - UNDEFINED, - DB_NOT_EXITS, - BACKING_UP, - BACKUP_INTERRUPT, - BACKUP_FINISHED, - }; -}; - -const std::string RdbDoubleWriteTest::DATABASE_NAME = RDB_TEST_PATH + "dual_write_test.db"; -const std::string RdbDoubleWriteTest::SLAVE_DATABASE_NAME = RDB_TEST_PATH + "dual_write_test_slave.db"; -std::shared_ptr RdbDoubleWriteTest::store = nullptr; -std::shared_ptr RdbDoubleWriteTest::slaveStore = nullptr; -std::shared_ptr RdbDoubleWriteTest::store3 = nullptr; -const int BLOB_SIZE = 3; -const uint8_t EXPECTED_BLOB_DATA[]{ 1, 2, 3 }; -const int CHECKAGE = 18; -const double CHECKCOLUMN = 100.5; - -class DoubleWriteTestOpenCallback : public RdbOpenCallback { -public: - int OnCreate(RdbStore &store) override; - int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; - static const std::string CREATE_TABLE_TEST; -}; - -const std::string DoubleWriteTestOpenCallback::CREATE_TABLE_TEST = - std::string("CREATE TABLE IF NOT EXISTS test ") + std::string("(id INTEGER PRIMARY KEY AUTOINCREMENT, " - "name TEXT NOT NULL, age INTEGER, salary " - "REAL, blobType BLOB)"); - -int DoubleWriteTestOpenCallback::OnCreate(RdbStore &store) -{ - return store.ExecuteSql(CREATE_TABLE_TEST); -} - -int DoubleWriteTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) -{ - return E_OK; -} - -void RdbDoubleWriteTest::SetUpTestCase(void) -{ -} - -void RdbDoubleWriteTest::TearDownTestCase(void) -{ -} - -void RdbDoubleWriteTest::SetUp(void) -{ -} - -void RdbDoubleWriteTest::TearDown(void) -{ - store = nullptr; - slaveStore = nullptr; - RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME); -} - -void RdbDoubleWriteTest::InitDb() -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MAIN_REPLICA); - DoubleWriteTestOpenCallback helper; - RdbDoubleWriteTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(RdbDoubleWriteTest::store, nullptr); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - store->ExecuteSql("DELETE FROM test"); - slaveStore->ExecuteSql("DELETE FROM test"); -} - -/** - * @tc.name: RdbStore_DoubleWrite_001 - * @tc.desc: test RdbStore doubleWrite - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_001, TestSize.Level1) -{ - InitDb(); - int64_t id; - ValuesBucket values; - - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(1, id); - - values.Clear(); - values.PutInt("id", 2); - values.PutString("name", std::string("lisi")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(2, id); - - values.Clear(); - values.PutInt("id", 3); - values.PutString("name", std::string("lisi")); - values.PutInt("age", 20L); - values.PutDouble("salary", 100.5f); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, id); - - RdbDoubleWriteTest::CheckResultSet(slaveStore); -} - -void RdbDoubleWriteTest::Insert(int64_t start, int count, bool isSlave, int dataSize) -{ - ValuesBucket values; - int64_t id = start; - int ret = E_OK; - for (int i = 0; i < count; i++) { - values.Clear(); - values.PutInt("id", id); - if (dataSize > 0) { - values.PutString("name", std::string(dataSize, 'a')); - } else { - values.PutString("name", std::string("zhangsan")); - } - values.PutInt("age", CHECKAGE); - values.PutDouble("salary", CHECKCOLUMN); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - if (isSlave) { - ret = slaveStore->Insert(id, "test", values); - } else { - ret = store->Insert(id, "test", values); - } - EXPECT_EQ(ret, E_OK); - id++; - } -} - -void RdbDoubleWriteTest::WaitForBackupFinish(int32_t expectStatus, int maxTimes) -{ - int32_t curStatus = store->GetBackupStatus(); - int tryTimes = 0; - while (curStatus != expectStatus && (++tryTimes <= maxTimes)) { - usleep(50000); // 50000 delay - curStatus = store->GetBackupStatus(); - } - LOG_INFO("----------cur backup Status:%{public}d---------", curStatus); - ASSERT_EQ(curStatus, expectStatus); -} - -void RdbDoubleWriteTest::TryInterruptBackup() -{ - int err = store->InterruptBackup(); - int tryTimes = 0; - while (err != E_OK && (++tryTimes <= 1000)) { // 1000 is try time - usleep(10000); // 10000 delay - err = store->InterruptBackup(); - } - EXPECT_EQ(err, E_OK); - LOG_INFO("----------interrupt backup---------"); -} - -void RdbDoubleWriteTest::CheckResultSet(std::shared_ptr &store) -{ - std::shared_ptr resultSet = - store->QuerySql("SELECT * FROM test WHERE name = ?", std::vector{ "zhangsan" }); - EXPECT_NE(resultSet, nullptr); - - int columnIndex; - int intVal; - std::string strVal; - ColumnType columnType; - int position; - int ret = resultSet->GetRowIndex(position); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(position, -1); - - ret = resultSet->GetColumnType(0, columnType); - EXPECT_EQ(ret, E_ROW_OUT_RANGE); - - ret = resultSet->GoToFirstRow(); - EXPECT_EQ(ret, E_OK); - - ret = resultSet->GetColumnIndex("id", columnIndex); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(columnIndex, 0); - ret = resultSet->GetColumnType(columnIndex, columnType); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(1, intVal); - - ret = resultSet->GetColumnIndex("name", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnType(columnIndex, columnType); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(columnType, ColumnType::TYPE_STRING); - ret = resultSet->GetString(columnIndex, strVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ("zhangsan", strVal); - - RdbDoubleWriteTest::CheckAge(resultSet); - RdbDoubleWriteTest::CheckSalary(resultSet); - RdbDoubleWriteTest::CheckBlob(resultSet); - - ret = resultSet->GoToNextRow(); - EXPECT_EQ(ret, E_ROW_OUT_RANGE); - - ret = resultSet->GetColumnType(columnIndex, columnType); - EXPECT_EQ(ret, E_ROW_OUT_RANGE); - - ret = resultSet->Close(); - EXPECT_EQ(ret, E_OK); -} - -void RdbDoubleWriteTest::CheckAge(std::shared_ptr &resultSet) -{ - int columnIndex; - int intVal; - ColumnType columnType; - int ret = resultSet->GetColumnIndex("age", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnType(columnIndex, columnType); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(CHECKAGE, intVal); -} - -void RdbDoubleWriteTest::CheckSalary(std::shared_ptr &resultSet) -{ - int columnIndex; - double dVal; - ColumnType columnType; - int ret = resultSet->GetColumnIndex("salary", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnType(columnIndex, columnType); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(columnType, ColumnType::TYPE_FLOAT); - ret = resultSet->GetDouble(columnIndex, dVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(CHECKCOLUMN, dVal); -} - -void RdbDoubleWriteTest::CheckBlob(std::shared_ptr &resultSet) -{ - int columnIndex; - std::vector blob; - ColumnType columnType; - int ret = resultSet->GetColumnIndex("blobType", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnType(columnIndex, columnType); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(columnType, ColumnType::TYPE_BLOB); - ret = resultSet->GetBlob(columnIndex, blob); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(BLOB_SIZE, static_cast(blob.size())); - for (int i = 0; i < BLOB_SIZE; i++) { - EXPECT_EQ(EXPECTED_BLOB_DATA[i], blob[i]); - } -} - -void RdbDoubleWriteTest::CheckNumber( - std::shared_ptr &store, int num, int errCode, const std::string &tableName) -{ - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM " + tableName); - ASSERT_NE(resultSet, nullptr); - int countNum; - int ret = resultSet->GetRowCount(countNum); - EXPECT_EQ(ret, errCode); - EXPECT_EQ(num, countNum); -} - -/** - * @tc.name: RdbStore_DoubleWrite_003 - * @tc.desc: test RdbStore execute - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_003, TestSize.Level1) -{ - InitDb(); - - int64_t id; - ValuesBucket values; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 25); - values.PutDouble("salary", CHECKCOLUMN); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - auto [ret2, outValue2] = store->Execute("UPDATE test SET age= 18 WHERE id = 1"); - EXPECT_EQ(E_OK, ret2); - - RdbDoubleWriteTest::CheckResultSet(slaveStore); -} - -/** - * @tc.name: RdbStore_DoubleWrite_004 - * @tc.desc: test RdbStore updata - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_004, TestSize.Level1) -{ - InitDb(); - - int64_t id; - - ValuesBucket values; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 25); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); - - int changedRows; - values.Clear(); - values.PutInt("age", 18); - ret = store->Update(changedRows, "test", values); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(1, changedRows); - - RdbDoubleWriteTest::CheckResultSet(slaveStore); -} - -/** - * @tc.name: RdbStore_DoubleWrite_005 - * @tc.desc: test RdbStore delete - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_005, TestSize.Level1) -{ - InitDb(); - - ValuesBucket values; - int64_t id; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(1, id); - - values.Clear(); - values.PutInt("id", 2); - values.PutString("name", std::string("lisi")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(2, id); - - values.Clear(); - values.PutInt("id", 3); - values.PutString("name", std::string("lisi")); - values.PutInt("age", 20L); - values.PutDouble("salary", 100.5f); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, id); - - int deletedRows; - ret = store->Delete(deletedRows, "test", "id = 2"); - ret = store->Delete(deletedRows, "test", "id = 3"); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(1, deletedRows); - - RdbDoubleWriteTest::CheckNumber(slaveStore, 1); -} - -/** - * @tc.name: RdbStore_DoubleWrite_007 - * @tc.desc: open SINGLE db, write, close, open MAIN_REPLICA db, check slave - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_007, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::SINGLE); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(store, nullptr); - - int64_t id = 10; - int count = 100; - Insert(id, count); - - store = nullptr; - config.SetHaMode(HAMode::MAIN_REPLICA); - RdbDoubleWriteTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(RdbDoubleWriteTest::store, nullptr); - - WaitForBackupFinish(BACKUP_FINISHED); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - - RdbDoubleWriteTest::CheckNumber(RdbDoubleWriteTest::slaveStore, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_008 - * @tc.desc: open MAIN_REPLICA db, write, close, corrupt, reopen db allow rebuild, db returns to normal - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_008, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_008 insert finish"); - - store = nullptr; - - std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); - ASSERT_TRUE(file.is_open() == true); - file.seekp(30, std::ios::beg); - ASSERT_TRUE(file.good() == true); - char bytes[2] = { 0x6, 0x6 }; - file.write(bytes, 2); - ASSERT_TRUE(file.good() == true); - file.close(); - LOG_INFO("RdbStore_DoubleWrite_008 corrupt db finish"); - - SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); - SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MAIN_REPLICA); - config.SetAllowRebuild(true); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - RebuiltType rebuiltType; - store->GetRebuilt(rebuiltType); - EXPECT_EQ(rebuiltType, RebuiltType::REPAIRED); - LOG_INFO("RdbStore_DoubleWrite_008 reopen db finish"); - - RdbDoubleWriteTest::CheckNumber(store, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_009 - * @tc.desc: open MAIN_REPLICA db, write, slave db has 100 more data than main db, restore, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_009, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - Insert(id, 100); - id = 200; - Insert(id, 100, true); - RdbDoubleWriteTest::CheckNumber(store, 100); - RdbDoubleWriteTest::CheckNumber(slaveStore, 200); - EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); - RdbDoubleWriteTest::CheckNumber(store, 200); -} - -/** - * @tc.name: RdbStore_DoubleWrite_010 - * @tc.desc: open MAIN_REPLICA db, write, close all, corrupt slave, open MAIN_REPLICA db, slave returns to normal - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_010, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_010 insert finish"); - - slaveStore = nullptr; - store = nullptr; - - std::fstream file(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); - ASSERT_TRUE(file.is_open() == true); - file.seekp(30, std::ios::beg); - ASSERT_TRUE(file.good() == true); - char bytes[2] = { 0x6, 0x6 }; - file.write(bytes, 2); - ASSERT_TRUE(file.good() == true); - file.close(); - LOG_INFO("RdbStore_DoubleWrite_010 corrupt db finish"); - SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); - SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); - - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MAIN_REPLICA); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - LOG_INFO("RdbStore_DoubleWrite_010 reopen main db finish"); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - LOG_INFO("RdbStore_DoubleWrite_010 reopen slave db finish"); - WaitForBackupFinish(BACKUP_FINISHED); - RdbDoubleWriteTest::CheckNumber(slaveStore, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_011 - * @tc.desc: open MAIN_REPLICA db, write, close slave, corrupt slave, backup, check slave - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_011, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_011 insert finish"); - - slaveStore = nullptr; - - std::fstream file(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); - ASSERT_TRUE(file.is_open() == true); - file.seekp(30, std::ios::beg); - ASSERT_TRUE(file.good() == true); - char bytes[2] = { 0x6, 0x6 }; - file.write(bytes, 2); - ASSERT_TRUE(file.good() == true); - file.close(); - LOG_INFO("RdbStore_DoubleWrite_011 corrupt db finish"); - - EXPECT_NE(store->Backup(std::string(""), {}), E_OK); - LOG_INFO("RdbStore_DoubleWrite_011 backup db finish"); - EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - int errCode; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - LOG_INFO("RdbStore_DoubleWrite_011 reopen slave db finish"); - - RdbDoubleWriteTest::CheckNumber(slaveStore, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_012 - * @tc.desc: test RdbStore transaction - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_012, TestSize.Level1) -{ - InitDb(); - - int err = store->BeginTransaction(); - EXPECT_EQ(err, E_OK); - int64_t id; - ValuesBucket values; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 25); - values.PutDouble("salary", CHECKCOLUMN); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - auto [ret2, outValue2] = store->Execute("UPDATE test SET age= 18 WHERE id = 1"); - EXPECT_EQ(E_OK, ret2); - err = store->Commit(); - EXPECT_EQ(err, E_OK); - - RdbDoubleWriteTest::CheckResultSet(slaveStore); -} - -/** - * @tc.name: RdbStore_DoubleWrite_013 - * @tc.desc: open MANUAL_TRIGGER db, open slave, write, slave is empty, backup, check slave, write, check slave - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_013, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MANUAL_TRIGGER); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - LOG_INFO("RdbStore_DoubleWrite_013 reopen main db finish"); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - LOG_INFO("RdbStore_DoubleWrite_013 reopen slave db finish"); - - int64_t id = 10; - int count = 100; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_013 insert finish"); - - RdbDoubleWriteTest::CheckNumber(slaveStore, 0); - - errCode = store->Backup(std::string(""), {}); - EXPECT_EQ(errCode, E_OK); - LOG_INFO("RdbStore_DoubleWrite_013 backup finish"); - - RdbDoubleWriteTest::CheckNumber(slaveStore, count); - - id = 1000; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_013 insert finish"); - RdbDoubleWriteTest::CheckNumber(slaveStore, 200); // 200 is all count -} - -/** - * @tc.name: RdbStore_DoubleWrite_014 - * @tc.desc: open MANUAL_TRIGGER db, write, backup, open slave, check slave, write, check slave - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_014, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MANUAL_TRIGGER); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - LOG_INFO("RdbStore_DoubleWrite_014 reopen main db finish"); - - int64_t id = 10; - int count = 100; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_014 insert finish"); - - errCode = store->Backup(std::string(""), {}); - EXPECT_EQ(errCode, E_OK); - LOG_INFO("RdbStore_DoubleWrite_014 backup finish"); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - LOG_INFO("RdbStore_DoubleWrite_014 reopen slave db finish"); - - RdbDoubleWriteTest::CheckNumber(slaveStore, count); - - id = 1000; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_014 insert finish"); - RdbDoubleWriteTest::CheckNumber(slaveStore, 200); // 200 is all count -} - -/** - * @tc.name: RdbStore_DoubleWrite_015 - * @tc.desc: open MAIN_REPLICA db, write, close, corrupt, slave create table, open MAIN_REPLICA db. check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_015, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - ValuesBucket values; - for (int i = 0; i < count; i++) { - id++; - values.Clear(); - values.PutInt("id", id); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - } - LOG_INFO("RdbStore_DoubleWrite_015 insert finish"); - - store = nullptr; - - std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); - ASSERT_TRUE(file.is_open() == true); - file.seekp(30, std::ios::beg); - ASSERT_TRUE(file.good() == true); - char bytes[2] = { 0x6, 0x6 }; - file.write(bytes, 2); - ASSERT_TRUE(file.good() == true); - file.close(); - LOG_INFO("RdbStore_DoubleWrite_015 corrupt db finish"); - SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); - SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); - - int errCode = slaveStore->ExecuteSql("CREATE TABLE IF NOT EXISTS xx (id INTEGER PRIMARY KEY AUTOINCREMENT," - "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"); - EXPECT_EQ(errCode, E_OK); - EXPECT_EQ(slaveStore->Insert(id, "xx", values), E_OK); - - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MAIN_REPLICA); - config.SetAllowRebuild(true); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - LOG_INFO("RdbStore_DoubleWrite_015 reopen db finish"); - - RdbDoubleWriteTest::CheckNumber(store, 1, E_OK, std::string("xx")); - RdbDoubleWriteTest::CheckNumber(store, count); - RdbDoubleWriteTest::CheckNumber(slaveStore, 1, E_OK, std::string("xx")); - RdbDoubleWriteTest::CheckNumber(slaveStore, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_016 - * @tc.desc: open MAIN_REPLICA db, write, close, delete db file, reopen, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_016, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_016 insert finish"); - - store = nullptr; - LOG_INFO("RdbStore_DoubleWrite_016 close finish"); - - SqliteUtils::DeleteFile(DATABASE_NAME); - SqliteUtils::DeleteFile(DATABASE_NAME + "-shm"); - SqliteUtils::DeleteFile(DATABASE_NAME + "-wal"); - LOG_INFO("RdbStore_DoubleWrite_016 delete db file finish"); - - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MAIN_REPLICA); - DoubleWriteTestOpenCallback helper; - int errCode; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - LOG_INFO("RdbStore_DoubleWrite_016 reopen db finish"); - - WaitForBackupFinish(BACKUP_FINISHED); - - RdbDoubleWriteTest::CheckNumber(store, count); - RdbDoubleWriteTest::CheckNumber(slaveStore, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_018 - * @tc.desc: open MAIN_REPLICA db, update slave, insert, M succ && S failed, - * check failureFlag, backup, check failureFlag - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_018, TestSize.Level1) -{ - InitDb(); - - int64_t id; - ValuesBucket values; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 25); - values.PutDouble("salary", CHECKCOLUMN); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - - auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 3 WHERE id = 1"); - EXPECT_EQ(E_OK, ret2); - - int64_t id2; - ValuesBucket values2; - values2.PutInt("id", 3); - values2.PutString("name", std::string("zhangsan")); - values2.PutInt("age", 25); - values2.PutDouble("salary", CHECKCOLUMN); - values2.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret3 = store->Insert(id2, "test", values2); - EXPECT_EQ(E_OK, ret3); - std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + +"-slaveFailure"; - bool isFlagFileExists = OHOS::FileExists(failureFlagPath); - ASSERT_TRUE(isFlagFileExists); - ASSERT_TRUE(store->IsSlaveDiffFromMaster()); - - int errCode; - errCode = store->Backup(std::string(""), {}); - EXPECT_EQ(errCode, E_OK); - isFlagFileExists = OHOS::FileExists(failureFlagPath); - ASSERT_FALSE(isFlagFileExists); -} - -/** - * @tc.name: RdbStore_DoubleWrite_019 - * @tc.desc: open MAIN_REPLICA db, update slave, insert, M succ && S failed, - * check failureFlag, reopen, check failureFlag - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_019, TestSize.Level1) -{ - InitDb(); - - int64_t id; - ValuesBucket values; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 25); - values.PutDouble("salary", CHECKCOLUMN); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - - auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 3 WHERE id = 1"); - EXPECT_EQ(E_OK, ret2); - - int64_t id2; - ValuesBucket values2; - values2.PutInt("id", 3); - values2.PutString("name", std::string("zhangsan")); - values2.PutInt("age", 25); - values2.PutDouble("salary", CHECKCOLUMN); - values2.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret3 = store->Insert(id2, "test", values2); - EXPECT_EQ(E_OK, ret3); - std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + +"-slaveFailure"; - bool isFlagFileExists = OHOS::FileExists(failureFlagPath); - ASSERT_TRUE(isFlagFileExists); - ASSERT_TRUE(store->IsSlaveDiffFromMaster()); - - store = nullptr; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MAIN_REPLICA); - config.SetAllowRebuild(true); - DoubleWriteTestOpenCallback helper; - int errCode; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - WaitForBackupFinish(BACKUP_FINISHED); - store = nullptr; - isFlagFileExists = OHOS::FileExists(failureFlagPath); - ASSERT_FALSE(isFlagFileExists); -} - -/** - * @tc.name: RdbStore_DoubleWrite_026 - * @tc.desc: open MANUAL_TRIGGER db, write, restore, insert, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_026, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MANUAL_TRIGGER); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - - int64_t id = 10; - int count = 100; - Insert(id, count); - - EXPECT_EQ(store->Restore(std::string(""), {}), E_INVALID_FILE_PATH); - - id = 2000; - Insert(id, count); - RdbDoubleWriteTest::CheckNumber(store, count + count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_027 - * @tc.desc: open MANUAL_TRIGGER db, write, close, corrupt db, reopen, insert, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_027, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MANUAL_TRIGGER); - config.SetAllowRebuild(true); - DoubleWriteTestOpenCallback helper; - - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - - EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); - - int64_t id = 10; - int count = 100; - Insert(id, count); - RdbDoubleWriteTest::CheckNumber(slaveStore, count); - - store = nullptr; - - std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); - ASSERT_TRUE(file.is_open() == true); - file.seekp(30, std::ios::beg); - ASSERT_TRUE(file.good() == true); - char bytes[2] = { 0x6, 0x6 }; - file.write(bytes, 2); - ASSERT_TRUE(file.good() == true); - file.close(); - - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - - id = 1000; - Insert(id, count); - RdbDoubleWriteTest::CheckNumber(store, count + count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_029 - * @tc.desc: open db, write, corrupt slave db, backup, backup, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_029, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - Insert(id, count); - - std::fstream slaveFile(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::trunc); - ASSERT_TRUE(slaveFile.is_open() == true); - slaveFile << "0000"; - slaveFile.flush(); - slaveFile.close(); - - std::fstream slaveWalFile(SLAVE_DATABASE_NAME + "-wal", std::ios::in | std::ios::out | std::ios::trunc); - ASSERT_TRUE(slaveWalFile.is_open() == true); - slaveWalFile << "0000"; - slaveWalFile.flush(); - slaveWalFile.close(); - - EXPECT_NE(store->Backup(std::string(""), {}), E_OK); - LOG_INFO("RdbStore_DoubleWrite_029 backup again"); - EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); - - RdbDoubleWriteTest::CheckNumber(store, count); - RdbDoubleWriteTest::CheckNumber(slaveStore, -1, E_SQLITE_CORRUPT); - - int errCode = E_OK; - slaveStore = nullptr; - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - - RdbDoubleWriteTest::CheckNumber(slaveStore, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_030 - * @tc.desc: open db, write, update slave, insert, check failure, restore, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_030, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - Insert(id, count); - - auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 666 WHERE id = 22"); - EXPECT_EQ(E_OK, ret2); - - id = 666; - Insert(id, 1); - - std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + +"-slaveFailure"; - bool isFlagFileExists = OHOS::FileExists(failureFlagPath); - ASSERT_TRUE(isFlagFileExists); - - EXPECT_NE(store->Restore(std::string(""), {}), E_OK); - - RdbDoubleWriteTest::CheckNumber(store, count + 1); - RdbDoubleWriteTest::CheckNumber(slaveStore, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_031 - * @tc.desc: open db, delete main.db, deleteRdbStore, check slave db - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_031, TestSize.Level1) -{ - InitDb(); - remove(RdbDoubleWriteTest::DATABASE_NAME.c_str()); - RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME); - EXPECT_NE(access(RdbDoubleWriteTest::SLAVE_DATABASE_NAME.c_str(), F_OK), 0); -} - -/** - * @tc.name: RdbStore_DoubleWrite_032 - * @tc.desc: open db, delete main.db, deleteRdbStore, check slave db - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_032, TestSize.Level1) -{ - InitDb(); - remove(RdbDoubleWriteTest::DATABASE_NAME.c_str()); - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - RdbHelper::DeleteRdbStore(config); - EXPECT_NE(access(RdbDoubleWriteTest::SLAVE_DATABASE_NAME.c_str(), F_OK), 0); -} - -/** - * @tc.name: RdbStore_DoubleWrite_033 - * @tc.desc: open db, write, close, corrupt, open SINGLE db, check - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_033, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - Insert(id, count); - - store = nullptr; - slaveStore = nullptr; - - std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); - ASSERT_TRUE(file.is_open() == true); - file.seekp(30, std::ios::beg); - ASSERT_TRUE(file.good() == true); - char bytes[2] = { 0x6, 0x6 }; - file.write(bytes, 2); - ASSERT_TRUE(file.good() == true); - file.close(); - - SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); - SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::SINGLE); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - - RebuiltType rebuiltType; - store->GetRebuilt(rebuiltType); - EXPECT_EQ(rebuiltType, RebuiltType::REPAIRED); - - RdbDoubleWriteTest::CheckNumber(store, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_034 - * @tc.desc: open MANUAL_TRIGGER db, write, backup, insert, check count, restore, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_034, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MANUAL_TRIGGER); - config.SetAllowRebuild(true); - DoubleWriteTestOpenCallback helper; - - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - - int64_t id = 10; - int count = 100; - Insert(id, count); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); - RdbDoubleWriteTest::CheckNumber(slaveStore, count); - - id = 1000; - Insert(id, count, true); - RdbDoubleWriteTest::CheckNumber(store, count); - RdbDoubleWriteTest::CheckNumber(slaveStore, count + count); - slaveStore = nullptr; - - EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); - RdbDoubleWriteTest::CheckNumber(store, count + count); - - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - RdbDoubleWriteTest::CheckNumber(slaveStore, 0L); -} \ No newline at end of file +///* +// * 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. +// */ +// +//#define LOG_TAG "RdbDoubleWriteTest" +//#include +//#include +//#include +//#include +// +//#include +//#include +// +//#include "common.h" +//#include "file_ex.h" +//#include "grd_api_manager.h" +//#include "logger.h" +//#include "rdb_common.h" +//#include "rdb_errno.h" +//#include "rdb_helper.h" +//#include "rdb_open_callback.h" +//#include "rdb_security_manager.h" +//#ifndef CROSS_PLATFORM +//#include "relational/relational_store_sqlite_ext.h" +//#endif +//#include "sqlite_connection.h" +//#include "sqlite_utils.h" +//#include "sys/types.h" +// +//using namespace testing::ext; +//using namespace OHOS::NativeRdb; +//using namespace OHOS::Rdb; +// +//class RdbDoubleWriteTest : public testing::Test { +//public: +// static void SetUpTestCase(void); +// static void TearDownTestCase(void); +// void SetUp(); +// void TearDown(); +// void CheckResultSet(std::shared_ptr &store); +// void CheckAge(std::shared_ptr &resultSet); +// void CheckSalary(std::shared_ptr &resultSet); +// void CheckBlob(std::shared_ptr &resultSet); +// void CheckNumber( +// std::shared_ptr &store, int num, int errCode = E_OK, const std::string &tableName = "test"); +// void Insert(int64_t start, int count, bool isSlave = false, int dataSize = 0); +// void WaitForBackupFinish(int32_t expectStatus, int maxTimes = 400); +// void WaitForAsyncRepairFinish(int maxTimes = 400); +// void TryInterruptBackup(); +// void InitDb(HAMode mode = HAMode::MAIN_REPLICA, bool isOpenSlave = true); +// +// static const std::string DATABASE_NAME; +// static const std::string SLAVE_DATABASE_NAME; +// static std::shared_ptr store; +// static std::shared_ptr slaveStore; +// static std::shared_ptr store3; +// static const struct sqlite3_api_routines_extra *originalExtraApi; +// static struct sqlite3_api_routines_extra mockExtraApi; +//#ifndef CROSS_PLATFORM +// static const struct sqlite3_api_routines_relational *originalKvApi; +// static struct sqlite3_api_routines_relational mockKvApi; +//#endif +// +// enum SlaveStatus : uint32_t { +// UNDEFINED, +// BACKING_UP, +// BACKUP_INTERRUPT, +// BACKUP_FINISHED, +// DB_CLOSING, +// }; +//}; +// +//const std::string RdbDoubleWriteTest::DATABASE_NAME = RDB_TEST_PATH + "dual_write_test.db"; +//const std::string RdbDoubleWriteTest::SLAVE_DATABASE_NAME = RDB_TEST_PATH + "dual_write_test_slave.db"; +//std::shared_ptr RdbDoubleWriteTest::store = nullptr; +//std::shared_ptr RdbDoubleWriteTest::slaveStore = nullptr; +//std::shared_ptr RdbDoubleWriteTest::store3 = nullptr; +//const struct sqlite3_api_routines_extra *RdbDoubleWriteTest::originalExtraApi = sqlite3_export_extra_symbols; +//struct sqlite3_api_routines_extra RdbDoubleWriteTest::mockExtraApi = *sqlite3_export_extra_symbols; +//#ifndef CROSS_PLATFORM +//const struct sqlite3_api_routines_relational *RdbDoubleWriteTest::originalKvApi = sqlite3_export_relational_symbols; +//struct sqlite3_api_routines_relational RdbDoubleWriteTest::mockKvApi = *sqlite3_export_relational_symbols; +//#endif +//const int BLOB_SIZE = 3; +//const uint8_t EXPECTED_BLOB_DATA[]{ 1, 2, 3 }; +//const int CHECKAGE = 18; +//const double CHECKCOLUMN = 100.5; +//const int HUGE_DATA_SIZE = 6 * 1024 * 1024; // 1MB +// +//class DoubleWriteTestOpenCallback : public RdbOpenCallback { +//public: +// int OnCreate(RdbStore &store) override; +// int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +// int OnOpen(RdbStore &rdbStore) override; +// static const std::string CREATE_TABLE_TEST; +//}; +// +//const std::string DoubleWriteTestOpenCallback::CREATE_TABLE_TEST = +// std::string("CREATE TABLE IF NOT EXISTS test ") + std::string("(id INTEGER PRIMARY KEY AUTOINCREMENT, " +// "name TEXT NOT NULL, age INTEGER, salary " +// "REAL, blobType BLOB)"); +// +//int DoubleWriteTestOpenCallback::OnCreate(RdbStore &store) +//{ +// return store.ExecuteSql(CREATE_TABLE_TEST); +//} +// +//int DoubleWriteTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +//{ +// return E_OK; +//} +// +//int DoubleWriteTestOpenCallback::OnOpen(RdbStore &rdbStore) +//{ +// int version = 0; +// rdbStore.GetVersion(version); +// EXPECT_TRUE(version > -1); +// return E_OK; +//} +// +//static int MockNotSupportBinlog(const char *notUsed) +//{ +// return SQLITE_ERROR; +//} +// +//static int MockSupportBinlog(const char *notUsed) +//{ +// return SQLITE_OK; +//} +// +//#ifndef CROSS_PLATFORM +//static int MockNotSupportBinlogWithParam(const char *name) +//{ +// return SQLITE_ERROR; +//} +// +//static int MockSupportBinlogWithParam(const char *name) +//{ +// return SQLITE_OK; +//} +//#endif +//static int MockReplayBinlog(sqlite3 *srcDb, sqlite3 *destDb) +//{ +// return SQLITE_OK; +//} +// +//static int MockCleanBinlog(sqlite3 *db, BinlogFileCleanModeE mode) +//{ +// return SQLITE_OK; +//} +// +//void RdbDoubleWriteTest::SetUpTestCase(void) +//{ +//} +// +//void RdbDoubleWriteTest::TearDownTestCase(void) +//{ +//} +// +//void RdbDoubleWriteTest::SetUp(void) +//{ +// mockExtraApi.is_support_binlog = MockNotSupportBinlog; +// mockExtraApi.replay_binlog = MockReplayBinlog; +// mockExtraApi.clean_binlog = MockCleanBinlog; +// sqlite3_export_extra_symbols = &mockExtraApi; +//#ifndef CROSS_PLATFORM +// mockKvApi.is_support_binlog = MockNotSupportBinlogWithParam; +// sqlite3_export_relational_symbols = &mockKvApi; +//#endif +// store = nullptr; +// slaveStore = nullptr; +// RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME); +//} +// +//void RdbDoubleWriteTest::TearDown(void) +//{ +// RdbDoubleWriteTest::WaitForAsyncRepairFinish(); +// store = nullptr; +// slaveStore = nullptr; +// RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME); +// sqlite3_export_extra_symbols = originalExtraApi; +//#ifndef CROSS_PLATFORM +// sqlite3_export_relational_symbols = originalKvApi; +//#endif +//} +// +//void RdbDoubleWriteTest::InitDb(HAMode mode, bool isOpenSlave) +//{ +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(mode); +// DoubleWriteTestOpenCallback helper; +// RdbDoubleWriteTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// ASSERT_NE(RdbDoubleWriteTest::store, nullptr); +// store->ExecuteSql("DELETE FROM test"); +// +// if (isOpenSlave) { +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// ASSERT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// slaveStore->ExecuteSql("DELETE FROM test"); +// } +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_001 +// * @tc.desc: test RdbStore doubleWrite +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_001, TestSize.Level1) +//{ +// InitDb(); +// int64_t id; +// ValuesBucket values; +// +// values.PutInt("id", 1); +// values.PutString("name", std::string("zhangsan")); +// values.PutInt("age", 18); +// values.PutDouble("salary", 100.5); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(1, id); +// +// values.Clear(); +// values.PutInt("id", 2); +// values.PutString("name", std::string("lisi")); +// values.PutInt("age", 18); +// values.PutDouble("salary", 100.5); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(2, id); +// +// values.Clear(); +// values.PutInt("id", 3); +// values.PutString("name", std::string("lisi")); +// values.PutInt("age", 20L); +// values.PutDouble("salary", 100.5f); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(3, id); +// +// RdbDoubleWriteTest::CheckResultSet(slaveStore); +//} +// +//void RdbDoubleWriteTest::Insert(int64_t start, int count, bool isSlave, int dataSize) +//{ +// ValuesBucket values; +// int64_t id = start; +// int ret = E_OK; +// for (int i = 0; i < count; i++) { +// values.Clear(); +// values.PutInt("id", id); +// if (dataSize > 0) { +// values.PutString("name", std::string(dataSize, 'a')); +// } else { +// values.PutString("name", std::string("zhangsan")); +// } +// values.PutInt("age", CHECKAGE); +// values.PutDouble("salary", CHECKCOLUMN); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// if (isSlave) { +// ret = slaveStore->Insert(id, "test", values); +// } else { +// ret = store->Insert(id, "test", values); +// } +// EXPECT_EQ(ret, E_OK); +// id++; +// } +//} +// +//void RdbDoubleWriteTest::WaitForBackupFinish(int32_t expectStatus, int maxTimes) +//{ +// int32_t curStatus = store->GetBackupStatus(); +// int tryTimes = 0; +// while (curStatus != expectStatus && (++tryTimes <= maxTimes)) { +// usleep(50000); // 50000 delay +// curStatus = store->GetBackupStatus(); +// } +// LOG_INFO("----------cur backup Status:%{public}d---------", curStatus); +// ASSERT_EQ(curStatus, expectStatus); +//} +// +//void RdbDoubleWriteTest::WaitForAsyncRepairFinish(int maxTimes) +//{ +// LOG_INFO("---- start wait for async finish----"); +// sleep(1); +// int tryTimes = 0; +// auto keyFiles = RdbSecurityManager::KeyFiles(DATABASE_NAME + "-async.restore"); +// while (keyFiles.Lock(false) != E_OK && (++tryTimes <= maxTimes)) { +// sleep(1); +// } +// LOG_INFO("---- end wait for async finish ----, %{public}d", tryTimes); +//} +// +//void RdbDoubleWriteTest::TryInterruptBackup() +//{ +// int err = store->InterruptBackup(); +// int tryTimes = 0; +// while (err != E_OK && (++tryTimes <= 1000)) { // 1000 is try time +// usleep(10000); // 10000 delay +// err = store->InterruptBackup(); +// } +// EXPECT_EQ(err, E_OK); +// LOG_INFO("----------interrupt backup---------"); +//} +// +//void RdbDoubleWriteTest::CheckResultSet(std::shared_ptr &store) +//{ +// std::shared_ptr resultSet = +// store->QuerySql("SELECT * FROM test WHERE name = ?", std::vector{ "zhangsan" }); +// EXPECT_NE(resultSet, nullptr); +// +// int columnIndex; +// int intVal; +// std::string strVal; +// ColumnType columnType; +// int position; +// int ret = resultSet->GetRowIndex(position); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(position, -1); +// +// ret = resultSet->GetColumnType(0, columnType); +// EXPECT_EQ(ret, E_ROW_OUT_RANGE); +// +// ret = resultSet->GoToFirstRow(); +// EXPECT_EQ(ret, E_OK); +// +// ret = resultSet->GetColumnIndex("id", columnIndex); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(columnIndex, 0); +// ret = resultSet->GetColumnType(columnIndex, columnType); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER); +// ret = resultSet->GetInt(columnIndex, intVal); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(1, intVal); +// +// ret = resultSet->GetColumnIndex("name", columnIndex); +// EXPECT_EQ(ret, E_OK); +// ret = resultSet->GetColumnType(columnIndex, columnType); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(columnType, ColumnType::TYPE_STRING); +// ret = resultSet->GetString(columnIndex, strVal); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ("zhangsan", strVal); +// +// RdbDoubleWriteTest::CheckAge(resultSet); +// RdbDoubleWriteTest::CheckSalary(resultSet); +// RdbDoubleWriteTest::CheckBlob(resultSet); +// +// ret = resultSet->GoToNextRow(); +// EXPECT_EQ(ret, E_ROW_OUT_RANGE); +// +// ret = resultSet->GetColumnType(columnIndex, columnType); +// EXPECT_EQ(ret, E_ROW_OUT_RANGE); +// +// ret = resultSet->Close(); +// EXPECT_EQ(ret, E_OK); +//} +// +//void RdbDoubleWriteTest::CheckAge(std::shared_ptr &resultSet) +//{ +// int columnIndex; +// int intVal; +// ColumnType columnType; +// int ret = resultSet->GetColumnIndex("age", columnIndex); +// EXPECT_EQ(ret, E_OK); +// ret = resultSet->GetColumnType(columnIndex, columnType); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER); +// ret = resultSet->GetInt(columnIndex, intVal); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(CHECKAGE, intVal); +//} +// +//void RdbDoubleWriteTest::CheckSalary(std::shared_ptr &resultSet) +//{ +// int columnIndex; +// double dVal; +// ColumnType columnType; +// int ret = resultSet->GetColumnIndex("salary", columnIndex); +// EXPECT_EQ(ret, E_OK); +// ret = resultSet->GetColumnType(columnIndex, columnType); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(columnType, ColumnType::TYPE_FLOAT); +// ret = resultSet->GetDouble(columnIndex, dVal); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(CHECKCOLUMN, dVal); +//} +// +//void RdbDoubleWriteTest::CheckBlob(std::shared_ptr &resultSet) +//{ +// int columnIndex; +// std::vector blob; +// ColumnType columnType; +// int ret = resultSet->GetColumnIndex("blobType", columnIndex); +// EXPECT_EQ(ret, E_OK); +// ret = resultSet->GetColumnType(columnIndex, columnType); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(columnType, ColumnType::TYPE_BLOB); +// ret = resultSet->GetBlob(columnIndex, blob); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(BLOB_SIZE, static_cast(blob.size())); +// for (int i = 0; i < BLOB_SIZE; i++) { +// EXPECT_EQ(EXPECTED_BLOB_DATA[i], blob[i]); +// } +//} +// +//void RdbDoubleWriteTest::CheckNumber( +// std::shared_ptr &store, int num, int errCode, const std::string &tableName) +//{ +// std::shared_ptr resultSet = store->QuerySql("SELECT * FROM " + tableName); +// ASSERT_NE(resultSet, nullptr); +// int countNum; +// int ret = resultSet->GetRowCount(countNum); +// EXPECT_EQ(ret, errCode); +// EXPECT_EQ(num, countNum); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_003 +// * @tc.desc: test RdbStore execute +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_003, TestSize.Level1) +//{ +// InitDb(); +// +// int64_t id; +// ValuesBucket values; +// values.PutInt("id", 1); +// values.PutString("name", std::string("zhangsan")); +// values.PutInt("age", 25); +// values.PutDouble("salary", CHECKCOLUMN); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// auto [ret2, outValue2] = store->Execute("UPDATE test SET age= 18 WHERE id = 1"); +// EXPECT_EQ(E_OK, ret2); +// +// RdbDoubleWriteTest::CheckResultSet(slaveStore); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_004 +// * @tc.desc: test RdbStore updata +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_004, TestSize.Level1) +//{ +// InitDb(); +// +// int64_t id; +// +// ValuesBucket values; +// values.PutInt("id", 1); +// values.PutString("name", std::string("zhangsan")); +// values.PutInt("age", 25); +// values.PutDouble("salary", 100.5); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret = store->Insert(id, "test", values); +// +// int changedRows; +// values.Clear(); +// values.PutInt("age", 18); +// ret = store->Update(changedRows, "test", values); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(1, changedRows); +// +// RdbDoubleWriteTest::CheckResultSet(slaveStore); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_005 +// * @tc.desc: test RdbStore delete +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_005, TestSize.Level1) +//{ +// InitDb(); +// +// ValuesBucket values; +// int64_t id; +// values.PutInt("id", 1); +// values.PutString("name", std::string("zhangsan")); +// values.PutInt("age", 18); +// values.PutDouble("salary", 100.5); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(1, id); +// +// values.Clear(); +// values.PutInt("id", 2); +// values.PutString("name", std::string("lisi")); +// values.PutInt("age", 18); +// values.PutDouble("salary", 100.5); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(2, id); +// +// values.Clear(); +// values.PutInt("id", 3); +// values.PutString("name", std::string("lisi")); +// values.PutInt("age", 20L); +// values.PutDouble("salary", 100.5f); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(3, id); +// +// int deletedRows; +// ret = store->Delete(deletedRows, "test", "id = 2"); +// ret = store->Delete(deletedRows, "test", "id = 3"); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(1, deletedRows); +// +// RdbDoubleWriteTest::CheckNumber(slaveStore, 1); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_007 +// * @tc.desc: open SINGLE db, write, close, open MAIN_REPLICA db, check slave +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_007, TestSize.Level1) +//{ +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::SINGLE); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_NE(store, nullptr); +// +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// +// store = nullptr; +// config.SetHaMode(HAMode::MAIN_REPLICA); +// RdbDoubleWriteTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_NE(RdbDoubleWriteTest::store, nullptr); +// +// WaitForBackupFinish(BACKUP_FINISHED); +// +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// +// RdbDoubleWriteTest::CheckNumber(RdbDoubleWriteTest::slaveStore, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_008 +// * @tc.desc: open MAIN_REPLICA db, write, close, corrupt, reopen db allow rebuild, db returns to normal +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_008, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_008 insert finish"); +// +// store = nullptr; +// +// std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// LOG_INFO("RdbStore_DoubleWrite_008 corrupt db finish"); +// +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// config.SetAllowRebuild(true); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// RebuiltType rebuiltType; +// store->GetRebuilt(rebuiltType); +// EXPECT_EQ(rebuiltType, RebuiltType::REPAIRED); +// LOG_INFO("RdbStore_DoubleWrite_008 reopen db finish"); +// +// RdbDoubleWriteTest::CheckNumber(store, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_009 +// * @tc.desc: open MAIN_REPLICA db, write, slave db has 100 more data than main db, restore, check count +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_009, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// Insert(id, 100); +// id = 200; +// Insert(id, 100, true); +// RdbDoubleWriteTest::CheckNumber(store, 100); +// RdbDoubleWriteTest::CheckNumber(slaveStore, 200); +// EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); +// RdbDoubleWriteTest::CheckNumber(store, 200); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_010 +// * @tc.desc: open MAIN_REPLICA db, write, close all, corrupt slave, open MAIN_REPLICA db, slave returns to normal +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_010, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_010 insert finish"); +// +// slaveStore = nullptr; +// store = nullptr; +// +// std::fstream file(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// LOG_INFO("RdbStore_DoubleWrite_010 corrupt db finish"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); +// +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_010 reopen main db finish"); +// +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_010 reopen slave db finish"); +// WaitForBackupFinish(BACKUP_FINISHED); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_011 +// * @tc.desc: open MAIN_REPLICA db, write, close slave, corrupt slave, backup, check slave +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_011, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_011 insert finish"); +// +// slaveStore = nullptr; +// +// std::fstream file(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// LOG_INFO("RdbStore_DoubleWrite_011 corrupt db finish"); +// +// EXPECT_NE(store->Backup(std::string(""), {}), E_OK); +// LOG_INFO("RdbStore_DoubleWrite_011 backup db finish"); +// EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); +// +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// int errCode; +// RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_011 reopen slave db finish"); +// +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_012 +// * @tc.desc: test RdbStore transaction +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_012, TestSize.Level1) +//{ +// InitDb(); +// +// int err = store->BeginTransaction(); +// EXPECT_EQ(err, E_OK); +// int64_t id; +// ValuesBucket values; +// values.PutInt("id", 1); +// values.PutString("name", std::string("zhangsan")); +// values.PutInt("age", 25); +// values.PutDouble("salary", CHECKCOLUMN); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// auto [ret2, outValue2] = store->Execute("UPDATE test SET age= 18 WHERE id = 1"); +// EXPECT_EQ(E_OK, ret2); +// err = store->Commit(); +// EXPECT_EQ(err, E_OK); +// +// RdbDoubleWriteTest::CheckResultSet(slaveStore); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_013 +// * @tc.desc: open MANUAL_TRIGGER db, open slave, write, slave is empty, backup, check slave, write, check slave +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_013, TestSize.Level1) +//{ +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_013 reopen main db finish"); +// +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_013 reopen slave db finish"); +// +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_013 insert finish"); +// +// RdbDoubleWriteTest::CheckNumber(slaveStore, 0); +// +// errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// LOG_INFO("RdbStore_DoubleWrite_013 backup finish"); +// +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// +// id = 1000; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_013 insert finish"); +// RdbDoubleWriteTest::CheckNumber(slaveStore, 200); // 200 is all count +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_014 +// * @tc.desc: open MANUAL_TRIGGER db, write, backup, open slave, check slave, write, check slave +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_014, TestSize.Level1) +//{ +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_014 reopen main db finish"); +// +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_014 insert finish"); +// +// errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// LOG_INFO("RdbStore_DoubleWrite_014 backup finish"); +// +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_014 reopen slave db finish"); +// +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// +// id = 1000; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_014 insert finish"); +// RdbDoubleWriteTest::CheckNumber(slaveStore, 200); // 200 is all count +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_015 +// * @tc.desc: open MAIN_REPLICA db, write, close, corrupt, slave create table, open MAIN_REPLICA db. check count +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_015, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// int count = 100; +// ValuesBucket values; +// for (int i = 0; i < count; i++) { +// id++; +// values.Clear(); +// values.PutInt("id", id); +// values.PutString("name", std::string("zhangsan")); +// values.PutInt("age", 18); +// values.PutDouble("salary", CHECKCOLUMN); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// } +// LOG_INFO("RdbStore_DoubleWrite_015 insert finish"); +// +// store = nullptr; +// +// std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// LOG_INFO("RdbStore_DoubleWrite_015 corrupt db finish"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); +// +// int errCode = slaveStore->ExecuteSql("CREATE TABLE IF NOT EXISTS xx (id INTEGER PRIMARY KEY AUTOINCREMENT," +// "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"); +// EXPECT_EQ(errCode, E_OK); +// EXPECT_EQ(slaveStore->Insert(id, "xx", values), E_OK); +// +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// config.SetAllowRebuild(true); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_015 reopen db finish"); +// +// RdbDoubleWriteTest::CheckNumber(store, 1, E_OK, std::string("xx")); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, 1, E_OK, std::string("xx")); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_016 +// * @tc.desc: open MAIN_REPLICA db, write, close, delete db file, reopen, check count +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_016, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_016 insert finish"); +// +// store = nullptr; +// LOG_INFO("RdbStore_DoubleWrite_016 close finish"); +// +// SqliteUtils::DeleteFile(DATABASE_NAME); +// SqliteUtils::DeleteFile(DATABASE_NAME + "-shm"); +// SqliteUtils::DeleteFile(DATABASE_NAME + "-wal"); +// LOG_INFO("RdbStore_DoubleWrite_016 delete db file finish"); +// +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// DoubleWriteTestOpenCallback helper; +// int errCode; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_016 reopen db finish"); +// +// WaitForBackupFinish(BACKUP_FINISHED); +// +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_018 +// * @tc.desc: open MAIN_REPLICA db, update slave, insert, M succ && S failed, +// * check failureFlag, backup, check failureFlag +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_018, TestSize.Level1) +//{ +// InitDb(); +// +// int64_t id; +// ValuesBucket values; +// values.PutInt("id", 1); +// values.PutString("name", std::string("zhangsan")); +// values.PutInt("age", 25); +// values.PutDouble("salary", CHECKCOLUMN); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// +// auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 3 WHERE id = 1"); +// EXPECT_EQ(E_OK, ret2); +// +// int64_t id2; +// ValuesBucket values2; +// values2.PutInt("id", 3); +// values2.PutString("name", std::string("zhangsan")); +// values2.PutInt("age", 25); +// values2.PutDouble("salary", CHECKCOLUMN); +// values2.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret3 = store->Insert(id2, "test", values2); +// EXPECT_EQ(E_OK, ret3); +// std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + +"-slaveFailure"; +// bool isFlagFileExists = OHOS::FileExists(failureFlagPath); +// ASSERT_TRUE(isFlagFileExists); +// ASSERT_TRUE(store->IsSlaveDiffFromMaster()); +// +// int errCode; +// errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// isFlagFileExists = OHOS::FileExists(failureFlagPath); +// ASSERT_FALSE(isFlagFileExists); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_019 +// * @tc.desc: open MAIN_REPLICA db, update slave, insert, M succ && S failed, +// * check failureFlag, reopen, check failureFlag +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_019, TestSize.Level1) +//{ +// InitDb(); +// +// int64_t id; +// ValuesBucket values; +// values.PutInt("id", 1); +// values.PutString("name", std::string("zhangsan")); +// values.PutInt("age", 25); +// values.PutDouble("salary", CHECKCOLUMN); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// +// auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 3 WHERE id = 1"); +// EXPECT_EQ(E_OK, ret2); +// +// int64_t id2; +// ValuesBucket values2; +// values2.PutInt("id", 3); +// values2.PutString("name", std::string("zhangsan")); +// values2.PutInt("age", 25); +// values2.PutDouble("salary", CHECKCOLUMN); +// values2.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret3 = store->Insert(id2, "test", values2); +// EXPECT_EQ(E_OK, ret3); +// std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + +"-slaveFailure"; +// bool isFlagFileExists = OHOS::FileExists(failureFlagPath); +// ASSERT_TRUE(isFlagFileExists); +// ASSERT_TRUE(store->IsSlaveDiffFromMaster()); +// +// store = nullptr; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// config.SetAllowRebuild(true); +// DoubleWriteTestOpenCallback helper; +// int errCode; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// WaitForBackupFinish(BACKUP_FINISHED); +// store = nullptr; +// isFlagFileExists = OHOS::FileExists(failureFlagPath); +// ASSERT_FALSE(isFlagFileExists); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_026 +// * @tc.desc: open MANUAL_TRIGGER db, write, restore, insert, check count +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_026, TestSize.Level1) +//{ +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// +// EXPECT_EQ(store->Restore(std::string(""), {}), E_INVALID_FILE_PATH); +// +// id = 2000; +// Insert(id, count); +// RdbDoubleWriteTest::CheckNumber(store, count + count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_027 +// * @tc.desc: open MANUAL_TRIGGER db, write, close, corrupt db, reopen, insert, check count +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_027, TestSize.Level1) +//{ +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// config.SetAllowRebuild(true); +// DoubleWriteTestOpenCallback helper; +// +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// +// store = nullptr; +// +// std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// +// id = 1000; +// Insert(id, count); +// RdbDoubleWriteTest::CheckNumber(store, count + count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_029 +// * @tc.desc: open db, write, corrupt slave db, backup, backup, check count +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_029, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// +// std::fstream slaveFile(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::trunc); +// ASSERT_TRUE(slaveFile.is_open() == true); +// slaveFile << "0000"; +// slaveFile.flush(); +// slaveFile.close(); +// +// std::fstream slaveWalFile(SLAVE_DATABASE_NAME + "-wal", std::ios::in | std::ios::out | std::ios::trunc); +// ASSERT_TRUE(slaveWalFile.is_open() == true); +// slaveWalFile << "0000"; +// slaveWalFile.flush(); +// slaveWalFile.close(); +// +// EXPECT_NE(store->Backup(std::string(""), {}), E_OK); +// LOG_INFO("RdbStore_DoubleWrite_029 backup again"); +// EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); +// +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, -1, E_SQLITE_CORRUPT); +// +// int errCode = E_OK; +// slaveStore = nullptr; +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_030 +// * @tc.desc: open db, write, update slave, insert, check failure, restore, check count +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_030, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// +// auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 666 WHERE id = 22"); +// EXPECT_EQ(E_OK, ret2); +// +// id = 666; +// Insert(id, 1); +// +// std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + +"-slaveFailure"; +// bool isFlagFileExists = OHOS::FileExists(failureFlagPath); +// ASSERT_TRUE(isFlagFileExists); +// +// EXPECT_NE(store->Restore(std::string(""), {}), E_OK); +// +// RdbDoubleWriteTest::CheckNumber(store, count + 1); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_031 +// * @tc.desc: open db, delete main.db, deleteRdbStore, check slave db +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_031, TestSize.Level1) +//{ +// InitDb(); +// remove(RdbDoubleWriteTest::DATABASE_NAME.c_str()); +// RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME); +// EXPECT_NE(access(RdbDoubleWriteTest::SLAVE_DATABASE_NAME.c_str(), F_OK), 0); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_032 +// * @tc.desc: open db, delete main.db, deleteRdbStore, check slave db +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_032, TestSize.Level1) +//{ +// InitDb(); +// remove(RdbDoubleWriteTest::DATABASE_NAME.c_str()); +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// RdbHelper::DeleteRdbStore(config); +// EXPECT_NE(access(RdbDoubleWriteTest::SLAVE_DATABASE_NAME.c_str(), F_OK), 0); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_033 +// * @tc.desc: open db, write, close, corrupt, open SINGLE db, check +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_033, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// +// store = nullptr; +// slaveStore = nullptr; +// +// std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::SINGLE); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// +// RebuiltType rebuiltType; +// store->GetRebuilt(rebuiltType); +// EXPECT_EQ(rebuiltType, RebuiltType::REPAIRED); +// +// RdbDoubleWriteTest::CheckNumber(store, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_034 +// * @tc.desc: open db, close, open SINGLE db, create index, write, reopen, check slave db +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_034, TestSize.Level1) +//{ +// InitDb(); +// store = nullptr; +// slaveStore = nullptr; +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::SINGLE); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// EXPECT_EQ(store->ExecuteSql("CREATE index age_index ON test(age);"), E_OK); +// int64_t id = 10; +// int count = 10; +// Insert(id, count); +// store = nullptr; +// +// config.SetHaMode(HAMode::MAIN_REPLICA); +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// ASSERT_NE(store, nullptr); +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// ASSERT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// WaitForBackupFinish(BACKUP_FINISHED); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// store = nullptr; +// slaveStore = nullptr; +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Manual_Trigger_Not_Verify_Db +// * @tc.desc: open MANUAL_TRIGGER db, write, corrupt db, check backup with verify and no verify +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Manual_Trigger_Not_Verify_Db, TestSize.Level0) +//{ +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_Manual_Trigger_Not_Verify_Db reopen main db finish"); +// +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_Manual_Trigger_Not_Verify_Db insert finish"); +// +// RdbDoubleWriteTest::CheckNumber(store, count); +// store = nullptr; +// +// std::fstream file(RdbDoubleWriteTest::DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open()); +// +// file.seekp(0x2000, std::ios::beg); +// ASSERT_TRUE(file.good()); +// +// char bytes[128]; +// std::fill_n(bytes, 128, 0xff); +// file.write(bytes, 128); +// file.flush(); +// file.close(); +// LOG_INFO("RdbStore_DoubleWrite_Manual_Trigger_Not_Verify_Db corrupt db finish"); +// +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// +// errCode = store->Backup(std::string("")); +// EXPECT_EQ(errCode, E_SQLITE_CORRUPT); +// +// errCode = store->Backup(std::string(""), {}, false); +// EXPECT_EQ(errCode, E_OK); +// store = nullptr; +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_001 +// * @tc.desc: test db is deleted while open huge database, in MANUAL_TRIGGER +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_001, TestSize.Level3) +//{ +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_001 ----"); +// InitDb(HAMode::MANUAL_TRIGGER); +// int errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: close store ----"); +// store = nullptr; +// slaveStore = nullptr; +// LOG_INFO("---- step 3: remove db file ----"); +// remove(RdbDoubleWriteTest::DATABASE_NAME.c_str()); +// LOG_INFO("---- step 4: reopen and trigger restore ----"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// if (errCode != E_SQLITE_BUSY) { +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("---- step 5: execute sql while restore ----"); +// EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY); +// LOG_INFO("---- step 6: check db count ----"); +// RdbDoubleWriteTest::WaitForAsyncRepairFinish(); +// RdbDoubleWriteTest::CheckNumber(store, count); +// } +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_001 ----"); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_002 +// * @tc.desc: test db is deleted while open huge database, in MAIN_REPLICA +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_002, TestSize.Level3) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_002 ----"); +// InitDb(); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: close store ----"); +// store = nullptr; +// slaveStore = nullptr; +// LOG_INFO("---- step 3: remove db file ----"); +// remove(RdbDoubleWriteTest::DATABASE_NAME.c_str()); +// LOG_INFO("---- step 4: reopen and trigger restore ----"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// if (errCode != E_SQLITE_BUSY) { +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("---- step 5: execute sql while restore ----"); +// EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY); +// LOG_INFO("---- step 6: check db count ----"); +// RdbDoubleWriteTest::WaitForAsyncRepairFinish(); +// RdbDoubleWriteTest::CheckNumber(store, count); +// } +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_002 ----"); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_003 +// * @tc.desc: test async restore for huge db in MAIN_REPLICA +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_003, TestSize.Level3) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_003 ----"); +// InitDb(); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: corrupt store ----"); +// std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// LOG_INFO("---- step 3: manually trigger repair ----"); +// EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); +// EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY); +// LOG_INFO("---- step 4: check db count ----"); +// RdbDoubleWriteTest::WaitForAsyncRepairFinish(); +// RdbDoubleWriteTest::CheckNumber(store, count); +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_003 ----"); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_004 +// * @tc.desc: test async restore for huge db in MANUAL_TRIGGER +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_004, TestSize.Level3) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_004 ----"); +// InitDb(HAMode::MANUAL_TRIGGER); +// int errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: corrupt store ----"); +// std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// LOG_INFO("---- step 3: manually trigger repair ----"); +// EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); +// EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY); +// LOG_INFO("---- step 4: check db count ----"); +// RdbDoubleWriteTest::WaitForAsyncRepairFinish(); +// RdbDoubleWriteTest::CheckNumber(store, count); +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_004 ----"); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_005 +// * @tc.desc: test restore is called while doing async restore +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_005, TestSize.Level3) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_005 ----"); +// InitDb(HAMode::MANUAL_TRIGGER); +// int errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: corrupt store ----"); +// std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// LOG_INFO("---- step 3: manually trigger repair ----"); +// EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); +// EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY); +// LOG_INFO("---- step 4: trigger repair again ----"); +// EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); +// LOG_INFO("---- step 5: check db count ----"); +// RdbDoubleWriteTest::WaitForAsyncRepairFinish(); +// RdbDoubleWriteTest::CheckNumber(store, count); +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_005 ----"); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_006 +// * @tc.desc: test call restore for huge db when slave db is corrupted +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_006, TestSize.Level3) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_006 ----"); +// InitDb(HAMode::MANUAL_TRIGGER); +// int errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: corrupt store ----"); +// std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// LOG_INFO("---- step 3: mark backup db corrupted ----"); +// SqliteUtils::SetSlaveInvalid(DATABASE_NAME); +// EXPECT_TRUE(SqliteUtils::IsSlaveInvalid(DATABASE_NAME)); +// LOG_INFO("---- step 4: manually trigger repair ----"); +// EXPECT_EQ(store->Restore(std::string(""), {}), E_SQLITE_CORRUPT); +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_006 ----"); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_007 +// * @tc.desc: test execsql when restore mark is abnormal +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_007, TestSize.Level3) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_007 ----"); +// InitDb(HAMode::MANUAL_TRIGGER); +// int errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: mark backup db as restoring ----"); +// SqliteUtils::SetSlaveRestoring(DATABASE_NAME); +// EXPECT_TRUE(SqliteUtils::IsSlaveRestoring(DATABASE_NAME)); +// LOG_INFO("---- step 3: manually trigger create statement should remove the mark ----"); +// EXPECT_EQ(store->ExecuteSql("select * from test;"), E_OK); +// EXPECT_FALSE(SqliteUtils::IsSlaveRestoring(DATABASE_NAME)); +// LOG_INFO("---- step 4: lock database for restoring and trigger create statement should not remove the mark ----"); +// SqliteUtils::SetSlaveRestoring(DATABASE_NAME); +// EXPECT_TRUE(SqliteUtils::IsSlaveRestoring(DATABASE_NAME)); +// auto keyFiles = RdbSecurityManager::KeyFiles(DATABASE_NAME + "-async.restore"); +// EXPECT_EQ(keyFiles.Lock(false), E_OK); +// LOG_INFO("---- step 5: manually trigger create statement should not remove the mark ----"); +// EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY); +// EXPECT_TRUE(SqliteUtils::IsSlaveRestoring(DATABASE_NAME)); +// SqliteUtils::SetSlaveRestoring(DATABASE_NAME, false); +// keyFiles.Unlock(); +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_007 ----"); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_008 +// * @tc.desc: test trigger async repair +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_008, TestSize.Level3) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_008 ----"); +// InitDb(HAMode::MANUAL_TRIGGER); +// int errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: corrupt both slave and master db ----"); +// store = nullptr; +// slaveStore = nullptr; +// EXPECT_TRUE(SqliteUtils::CopyFile(DATABASE_NAME + "-dwr", DATABASE_NAME)); +// std::fstream file(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// file.seekp(1, std::ios::beg); +// std::vector null_buffer(count, '\0'); +// file.write(null_buffer.data(), count); +// file.close(); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); +// SqliteUtils::SetSlaveInvalid(DATABASE_NAME); +// EXPECT_TRUE(SqliteUtils::IsSlaveInvalid(DATABASE_NAME)); +// +// LOG_INFO("---- step 3: reopen should give E_SQLITE_CORRUPT ----"); +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_SQLITE_CORRUPT); +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_008 ----"); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_009 +// * @tc.desc: test trigger async repair +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_009, TestSize.Level3) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_009 ----"); +// InitDb(HAMode::MANUAL_TRIGGER); +// int errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: corrupt master db ----"); +// store = nullptr; +// slaveStore = nullptr; +// EXPECT_TRUE(SqliteUtils::CopyFile(DATABASE_NAME + "-dwr", DATABASE_NAME)); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); +// LOG_INFO("---- step 3: reopen should give ok ----"); +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// if (errCode != E_SQLITE_BUSY) { +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("---- step 4: trigger statement should busy ----"); +// EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY); +// store = nullptr; +// } +// LOG_INFO("---- step 5: check db count ----"); +// RdbDoubleWriteTest::WaitForAsyncRepairFinish(); +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// ASSERT_NE(store, nullptr); +// RdbDoubleWriteTest::CheckNumber(store, count); +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_009 ----"); +//} +// +///* +// * @tc.name: RdbStore_Mock_Binlog_001 +// * @tc.desc: test call backup and restore when binlog is supported +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_Mock_Binlog_001, TestSize.Level0) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// mockExtraApi.is_support_binlog = MockSupportBinlog; +// sqlite3_export_extra_symbols = &mockExtraApi; +//#ifndef CROSS_PLATFORM +// mockKvApi.is_support_binlog = MockSupportBinlogWithParam; +// sqlite3_export_relational_symbols = &mockKvApi; +//#endif +// +// InitDb(HAMode::MANUAL_TRIGGER, false); +// EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); +// EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); +//} +// +///* +// * @tc.name: RdbStore_Mock_Binlog_002 +// * @tc.desc: test call CheckReplicaIntegrity when binlog is supported +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_Mock_Binlog_002, TestSize.Level0) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// mockExtraApi.is_support_binlog = MockSupportBinlog; +// sqlite3_export_extra_symbols = &mockExtraApi; +//#ifndef CROSS_PLATFORM +// mockKvApi.is_support_binlog = MockSupportBinlogWithParam; +// sqlite3_export_relational_symbols = &mockKvApi; +//#endif +// InitDb(HAMode::MAIN_REPLICA, false); +// store = nullptr; +// +// // open slave for conflict by compress +// sqlite3 *db = nullptr; +// int rc = sqlite3_open_v2(RdbDoubleWriteTest::SLAVE_DATABASE_NAME.c_str(), +// &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "compressvfs"); +// EXPECT_EQ(rc, SQLITE_OK); +// EXPECT_NE(db, nullptr); +// const char *ddl = DoubleWriteTestOpenCallback::CREATE_TABLE_TEST.c_str(); +// EXPECT_EQ(sqlite3_exec(db, ddl, nullptr, nullptr, nullptr), SQLITE_OK); +// sqlite3_close_v2(db); +// +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// EXPECT_EQ(Connection::CheckReplicaIntegrity(config), E_OK); +//} +// +///** +// * @tc.name: CreateReplicaStatement_Test_001 +// * @tc.desc: Normal testCase of CreateReplicaStatement. +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, CreateReplicaStatement_Test_001, TestSize.Level2) +//{ +// InitDb(); +// +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// auto [errCode, readConn] = SqliteConnection::Create(config, false); +// EXPECT_EQ(errCode, SQLITE_OK); +// ASSERT_NE(readConn, nullptr); +// auto [err, statement] = readConn->CreateReplicaStatement("select * from test;", readConn); +// EXPECT_EQ(err, SQLITE_OK); +// EXPECT_NE(statement, nullptr); +// statement = nullptr; +// readConn = nullptr; +//} +// +///** +// * @tc.name: CreateReplicaStatement_Test_002 +// * @tc.desc: Abnormal testCase of CreateReplicaStatement. +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, CreateReplicaStatement_Test_002, TestSize.Level2) +//{ +// InitDb(); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// auto [errCode, readConn] = SqliteConnection::Create(config, false); +// EXPECT_EQ(errCode, SQLITE_OK); +// ASSERT_NE(readConn, nullptr); +// auto [err, statement] = readConn->CreateReplicaStatement("select * from test;", readConn); +// EXPECT_EQ(err, SQLITE_OK); +// EXPECT_NE(statement, nullptr); +// statement = nullptr; +// readConn = nullptr; +//} +// +///** +// * @tc.name: CreateReplicaStatement_Test_003 +// * @tc.desc: Abnormal testCase of CreateReplicaStatement. +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, CreateReplicaStatement_Test_003, TestSize.Level2) +//{ +// InitDb(); +// EXPECT_TRUE(SqliteUtils::CopyFile(SLAVE_DATABASE_NAME + "-dwr", SLAVE_DATABASE_NAME)); +// +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// auto [errCode, readConn] = SqliteConnection::Create(config, false); +// EXPECT_EQ(errCode, SQLITE_OK); +// ASSERT_NE(readConn, nullptr); +// auto [err, statement] = readConn->CreateReplicaStatement("select * from test;", readConn); +// EXPECT_EQ(err, SQLITE_OK); +// EXPECT_NE(statement, nullptr); +//} diff --git a/relational_store/test/native/rdb/unittest/rdb_encrypt_decrypt_test.cpp b/relational_store/test/native/rdb/unittest/rdb_encrypt_decrypt_test.cpp index 530c711ca0a5860dab115eba2aa978828c4f29e1..c0655302bd51e37bc3111aac6d46681e539c47a3 100644 --- a/relational_store/test/native/rdb/unittest/rdb_encrypt_decrypt_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_encrypt_decrypt_test.cpp @@ -193,7 +193,7 @@ HWTEST_F(RdbEncryptTest, RdbStore_Encrypt_04, TestSize.Level1) int errCode; std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); EXPECT_NE(store, nullptr); - std::string keyPath = RDB_TEST_PATH + "key/encrypted.pub_key"; + std::string keyPath = RDB_TEST_PATH + "key/encrypted.pub_key_v1"; int ret = access(keyPath.c_str(), F_OK); EXPECT_EQ(ret, 0); @@ -356,7 +356,7 @@ HWTEST_F(RdbEncryptTest, RdbStore_Encrypt_010, TestSize.Level1) EXPECT_NE(store, nullptr); EXPECT_EQ(errCode, E_OK); - std::string keyPath = RDB_TEST_PATH + "key/encrypted.pub_key"; + std::string keyPath = RDB_TEST_PATH + "key/encrypted.pub_key_v1"; int ret = access(keyPath.c_str(), F_OK); EXPECT_EQ(ret, 0); @@ -529,4 +529,151 @@ HWTEST_F(RdbEncryptTest, KeyFilePath_test_001, TestSize.Level2) EXPECT_EQ(E_OK, store2->Backup(RdbEncryptTest::ENCRYPTED_DATABASE_BACKUP_NAME2)); EXPECT_EQ(E_OK, store2->Restore(RdbEncryptTest::ENCRYPTED_DATABASE_BACKUP_NAME2)); +} + +/** + * @tc.name: KeyCorruptTest + * @tc.desc: test key file corrupt readonly + * @tc.type: FUNC + */ +HWTEST_F(RdbEncryptTest, KeyCorruptTest_01, TestSize.Level1) +{ + RdbStoreConfig config1(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + config1.SetEncryptStatus(true); + config1.SetBundleName("com.example.TestEncrypt1"); + EncryptTestOpenCallback helper1; + int errCode = E_ERROR; + std::shared_ptr store1 = RdbHelper::GetRdbStore(config1, 1, helper1, errCode); + ASSERT_NE(nullptr, store1); + ASSERT_EQ(E_OK, errCode); + int64_t id; + int ret = store1->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + store1 = nullptr; + + RdbSecurityManager::KeyFiles keyFile(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + std::string file = keyFile.GetKeyFile(RdbSecurityManager::KeyFileType::PUB_KEY_FILE); + ASSERT_TRUE(OHOS::FileExists(file)); + std::vector keyfileData; + ASSERT_TRUE(OHOS::LoadBufferFromFile(file, keyfileData)); + + std::vector keyCorrupted = keyfileData; + // fill bytes of keyfile index 10 to 19 with 0 + for (size_t i = 10; i < 20 && i < keyCorrupted.size(); ++i) { + keyCorrupted[i] = 0; + } + ASSERT_TRUE(OHOS::SaveBufferToFile(file, keyCorrupted)); + + RdbStoreConfig config2(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + config2.SetEncryptStatus(true); + config2.SetBundleName("com.example.TestEncrypt1"); + config2.SetReadOnly(true); + EncryptTestOpenCallback helper2; + std::shared_ptr store2 = RdbHelper::GetRdbStore(config2, 1, helper2, errCode); + ASSERT_NE(nullptr, store2); + ASSERT_EQ(E_OK, errCode); + + std::shared_ptr resultSet = store2->QuerySql("SELECT * FROM test"); + ASSERT_NE(nullptr, resultSet); + ret = resultSet->GoToFirstRow(); + EXPECT_EQ(ret, E_OK); + RowEntity rowEntity; + ASSERT_EQ(E_OK, resultSet->GetRow(rowEntity)); + ASSERT_EQ(1, int(rowEntity.Get("id"))); + resultSet->Close(); + store2 = nullptr; +} + +/** + * @tc.name: KeyCorruptTest + * @tc.desc: test key file not exist when readonly + * @tc.type: FUNC + */ +HWTEST_F(RdbEncryptTest, KeyCorruptTest_02, TestSize.Level1) +{ + RdbStoreConfig config1(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + config1.SetEncryptStatus(true); + config1.SetBundleName("com.example.TestEncrypt1"); + EncryptTestOpenCallback helper1; + int errCode = E_ERROR; + std::shared_ptr store1 = RdbHelper::GetRdbStore(config1, 1, helper1, errCode); + ASSERT_NE(nullptr, store1); + ASSERT_EQ(E_OK, errCode); + int64_t id; + int ret = store1->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + store1 = nullptr; + + RdbSecurityManager::KeyFiles keyFile(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + std::string file = keyFile.GetKeyFile(RdbSecurityManager::KeyFileType::PUB_KEY_FILE); + ASSERT_TRUE(OHOS::FileExists(file)); + std::remove(file.c_str()); + ASSERT_FALSE(OHOS::FileExists(file)); + + RdbStoreConfig config2(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + config2.SetEncryptStatus(true); + config2.SetBundleName("com.example.TestEncrypt1"); + config2.SetReadOnly(true); + EncryptTestOpenCallback helper2; + std::shared_ptr store2 = RdbHelper::GetRdbStore(config2, 1, helper2, errCode); + ASSERT_NE(nullptr, store2); + ASSERT_EQ(E_OK, errCode); + + std::shared_ptr resultSet = store2->QuerySql("SELECT * FROM test"); + ASSERT_NE(nullptr, resultSet); + ret = resultSet->GoToFirstRow(); + EXPECT_EQ(ret, E_OK); + RowEntity rowEntity; + ASSERT_EQ(E_OK, resultSet->GetRow(rowEntity)); + ASSERT_EQ(1, int(rowEntity.Get("id"))); + resultSet->Close(); + store2 = nullptr; +} + +/** + * @tc.name: KeyCorruptTest + * @tc.desc: test save key data to file failed + * @tc.type: FUNC + */ +HWTEST_F(RdbEncryptTest, KeyCorruptTest_03, TestSize.Level0) +{ + RdbStoreConfig config1(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + config1.SetEncryptStatus(true); + config1.SetBundleName("com.example.TestEncrypt1"); + EncryptTestOpenCallback helper1; + int errCode = E_ERROR; + std::shared_ptr store1 = RdbHelper::GetRdbStore(config1, 1, helper1, errCode); + ASSERT_NE(nullptr, store1); + ASSERT_EQ(E_OK, errCode); + store1 = nullptr; + + RdbSecurityManager::KeyFiles keyFile(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + std::string file = keyFile.GetKeyFile(RdbSecurityManager::KeyFileType::PUB_KEY_FILE); + ASSERT_TRUE(OHOS::FileExists(file)); + std::vector keyfileData; + ASSERT_TRUE(OHOS::LoadBufferFromFile(file, keyfileData)); + + std::vector keyCorrupted = keyfileData; + // fill bytes of keyfile index 10 to 19 with 0 + for (size_t i = 10; i < 20 && i < keyCorrupted.size(); ++i) { + keyCorrupted[i] = 0; + } + ASSERT_TRUE(OHOS::SaveBufferToFile(file, keyCorrupted)); + + std::string chattrAddiCmd = "chattr +i " + file; + ASSERT_EQ(E_OK, system(chattrAddiCmd.c_str())); + + RdbStoreConfig config2(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + config2.SetEncryptStatus(true); + config2.SetBundleName("com.example.TestEncrypt1"); + EncryptTestOpenCallback helper2; + std::shared_ptr store2 = RdbHelper::GetRdbStore(config2, 1, helper2, errCode); + ASSERT_NE(nullptr, store2); + ASSERT_EQ(E_OK, errCode); + + // Enable the wal file operation. + std::string chattrSubiCmd = "chattr -i " + file; + ASSERT_EQ(E_OK, system(chattrSubiCmd.c_str())); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_encrypt_upgrade_test.cpp b/relational_store/test/native/rdb/unittest/rdb_encrypt_upgrade_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..030cf26ad169949d10b72026cc5206b6327a25b8 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_encrypt_upgrade_test.cpp @@ -0,0 +1,460 @@ +/* +* Copyright (c) 2025 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 "RdbEncryptUpgradeTest" +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "block_data.h" +#include "common.h" +#include "file_ex.h" +#include "hks_api.h" +#include "hks_param.h" +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "rdb_security_manager.h" +#include "sqlite_utils.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; +class RdbEncryptUpgradeTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + static std::string RemoveSuffix(const std::string &name); + std::vector EncryptV0(std::vector &key, std::vector rootKeyAlias); + bool SaveSecretKeyToV0(const std::string &keyPath, RdbSecretKeyData &keyData); + int32_t HksLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, + const struct HksBlob *inData, struct HksBlob *outData); + int32_t HksEncryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, + const struct HksBlob *plainText, struct HksBlob *cipherText); + + static const std::string encryptedDatabaseName; + static const std::string encryptedDatabasePath; + static const std::string encryptedDatabaseKeyDir; + std::mutex mutex_; +}; + +const std::string RdbEncryptUpgradeTest::encryptedDatabaseName = "encrypted.db"; +const std::string RdbEncryptUpgradeTest::encryptedDatabasePath = RDB_TEST_PATH + encryptedDatabaseName; +const std::string RdbEncryptUpgradeTest::encryptedDatabaseKeyDir = RDB_TEST_PATH + "key/"; +static constexpr uint32_t TIMES = 4; +static constexpr uint32_t MAX_UPDATE_SIZE = 64; +static constexpr uint32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES; +static constexpr const char *RDB_HKS_BLOB_TYPE_NONCE = "Z5s0Bo571Koq"; +static constexpr const char *RDB_HKS_BLOB_TYPE_AAD = "RdbClientAAD"; + +class RdbEncryptUpgradeTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string createTableTest; +}; + +std::string const RdbEncryptUpgradeTestOpenCallback::createTableTest = "CREATE TABLE IF NOT EXISTS test " + "(id INTEGER PRIMARY KEY " + "AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, " + "salary " + "REAL, blobType BLOB)"; + +int RdbEncryptUpgradeTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(createTableTest); +} + +int RdbEncryptUpgradeTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void RdbEncryptUpgradeTest::SetUpTestCase() +{ +} + +void RdbEncryptUpgradeTest::TearDownTestCase() +{ +} + +void RdbEncryptUpgradeTest::SetUp() +{ + RdbHelper::ClearCache(); + RdbHelper::DeleteRdbStore(RdbEncryptUpgradeTest::encryptedDatabasePath); +} + +void RdbEncryptUpgradeTest::TearDown() +{ + RdbHelper::ClearCache(); + RdbHelper::DeleteRdbStore(RdbEncryptUpgradeTest::encryptedDatabasePath); +} + +std::string RdbEncryptUpgradeTest::RemoveSuffix(const std::string &name) +{ + std::string suffix(".db"); + auto pos = name.rfind(suffix); + if (pos == std::string::npos || pos < name.length() - suffix.length()) { + return name; + } + return { name, 0, pos }; +} + +int32_t RdbEncryptUpgradeTest::HksLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, + const struct HksBlob *inData, struct HksBlob *outData) +{ + if (outData->size < inData->size * TIMES) { + return HKS_ERROR_INVALID_ARGUMENT; + } + + struct HksBlob input = { MAX_UPDATE_SIZE, inData->data }; + uint8_t *end = inData->data + inData->size - 1; + outData->size = 0; + struct HksBlob output = { MAX_OUTDATA_SIZE, outData->data }; + while (input.data <= end) { + if (input.data + MAX_UPDATE_SIZE > end) { + input.size = end - input.data + 1; + break; + } + auto result = HksUpdate(handle, paramSet, &input, &output); + if (result != HKS_SUCCESS) { + LOG_ERROR("HksUpdate Failed."); + return HKS_FAILURE; + } + + output.data += output.size; + outData->size += output.size; + input.data += MAX_UPDATE_SIZE; + } + output.size = input.size * TIMES; + auto result = HksFinish(handle, paramSet, &input, &output); + if (result != HKS_SUCCESS) { + LOG_ERROR("HksFinish Failed."); + return HKS_FAILURE; + } + outData->size += output.size; + return HKS_SUCCESS; +} + +int32_t RdbEncryptUpgradeTest::HksEncryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, + const struct HksBlob *plainText, struct HksBlob *cipherText) +{ + uint8_t handle[sizeof(uint64_t)] = { 0 }; + struct HksBlob handleBlob = { sizeof(uint64_t), handle }; + int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr); + if (result != HKS_SUCCESS) { + LOG_ERROR("bai: HksEncrypt failed with error %{public}d", result); + return result; + } + return HksLoopUpdate(&handleBlob, paramSet, plainText, cipherText); +} + +std::vector RdbEncryptUpgradeTest::EncryptV0(std::vector &key, std::vector rootKeyAlias) +{ + std::vector nonce_(RDB_HKS_BLOB_TYPE_NONCE, RDB_HKS_BLOB_TYPE_NONCE + strlen(RDB_HKS_BLOB_TYPE_NONCE)); + std::vector aad_(RDB_HKS_BLOB_TYPE_AAD, RDB_HKS_BLOB_TYPE_AAD + strlen(RDB_HKS_BLOB_TYPE_AAD)); + struct HksBlob blobAad = { uint32_t(aad_.size()), aad_.data() }; + struct HksBlob blobNonce = { uint32_t(nonce_.size()), nonce_.data() }; + struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), rootKeyAlias.data() }; + struct HksBlob plainKey = { uint32_t(key.size()), key.data() }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret); + return {}; + } + struct HksParam hksParam[] = {{ .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_NONCE, .blob = blobNonce }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }}; + + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return {}; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return {}; + } + std::vector encryptedKey(plainKey.size * TIMES + 1); + struct HksBlob cipherText = { uint32_t(encryptedKey.size()), encryptedKey.data() }; + ret = HksEncryptThreeStage(&rootKeyName, params, &plainKey, &cipherText); + (void)HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + encryptedKey.assign(encryptedKey.size(), 0); + LOG_ERROR("bai: HksEncrypt failed with error %{public}d", ret); + return {}; + } + encryptedKey.resize(cipherText.size); + LOG_ERROR("bai: EncryptOld success "); + return encryptedKey; +} + +bool RdbEncryptUpgradeTest::SaveSecretKeyToV0(const std::string &keyPath, RdbSecretKeyData &keyData) +{ + LOG_INFO("begin keyPath:%{public}s.", SqliteUtils::Anonymous(keyPath).c_str()); + + std::string secretKeyInString; + secretKeyInString.append(reinterpret_cast(&keyData.distributed), sizeof(uint8_t)); + secretKeyInString.append(reinterpret_cast(&keyData.timeValue), sizeof(time_t)); + secretKeyInString.append(reinterpret_cast(keyData.secretKey.data()), keyData.secretKey.size()); + bool ret; + { + std::lock_guard lock(mutex_); + auto fd = open(keyPath.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (fd >= 0) { + ret = OHOS::SaveStringToFd(fd, secretKeyInString); + close(fd); + } else { + ret = false; + } + } + return ret; +} + + +/** +* @tc.name: OTATest_001 +* @tc.desc: getRdbStore ota test +* @tc.type: FUNC +*/ +HWTEST_F(RdbEncryptUpgradeTest, OTATest_001, TestSize.Level1) +{ + RdbStoreConfig config(RdbEncryptUpgradeTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetEncryptStatus(true); + RdbEncryptUpgradeTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + std::string keyPathV1 = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; + bool isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_TRUE(isFileExists); + store = nullptr; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + store = nullptr; + + RdbSecretKeyData keyDataV1; + auto res = RdbSecurityManager::GetInstance().LoadSecretKeyFromDiskV1(keyPathV1, keyDataV1); + ASSERT_EQ(res, true); + std::string keyPathV0 = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + RdbSecretKeyData keyDataV0; + keyDataV0.timeValue = keyDataV1.timeValue; + keyDataV0.distributed = 0; + auto rootKeyAlias = RdbSecurityManager::GetInstance().GetRootKeyAlias(); + auto ret = RdbSecurityManager::GetInstance().CheckRootKeyExists(rootKeyAlias); + ASSERT_NE(ret, HKS_ERROR_NOT_EXIST); + keyDataV0.secretKey = EncryptV0(keyDataV1.secretKey, rootKeyAlias); + res = SaveSecretKeyToV0(keyPathV0, keyDataV0); + ASSERT_EQ(res, true); + isFileExists = OHOS::FileExists(keyPathV0); + ASSERT_TRUE(isFileExists); + + SqliteUtils::DeleteFile(keyPathV1); + isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_FALSE(isFileExists); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_TRUE(isFileExists); + isFileExists = OHOS::FileExists(keyPathV0); + ASSERT_FALSE(isFileExists); +} + + +/** +* @tc.name: OTATest_002 +* @tc.desc: keyFileV1 corrupted ota test +* @tc.type: FUNC +*/ +HWTEST_F(RdbEncryptUpgradeTest, OTATest_002, TestSize.Level1) +{ + RdbStoreConfig config(RdbEncryptUpgradeTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetEncryptStatus(true); + RdbEncryptUpgradeTestOpenCallback helper; + int errCode = E_OK; + RdbHelper::DeleteRdbStore(config); + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + std::string keyPathV1 = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; + bool isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_TRUE(isFileExists); + store = nullptr; + + RdbSecretKeyData keyDataV1; + auto res = RdbSecurityManager::GetInstance().LoadSecretKeyFromDiskV1(keyPathV1, keyDataV1); + ASSERT_EQ(res, true); + std::string keyPathV0 = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + RdbSecretKeyData keyDataV0; + keyDataV0.timeValue = keyDataV1.timeValue; + keyDataV0.distributed = 0; + auto rootKeyAlias = RdbSecurityManager::GetInstance().GetRootKeyAlias(); + auto ret = RdbSecurityManager::GetInstance().CheckRootKeyExists(rootKeyAlias); + ASSERT_NE(ret, HKS_ERROR_NOT_EXIST); + keyDataV0.secretKey = EncryptV0(keyDataV1.secretKey, rootKeyAlias); + res = SaveSecretKeyToV0(keyPathV0, keyDataV0); + ASSERT_EQ(res, true); + isFileExists = OHOS::FileExists(keyPathV0); + ASSERT_TRUE(isFileExists); + + std::vector keyfileData; + ASSERT_TRUE(OHOS::LoadBufferFromFile(keyPathV1, keyfileData)); + std::vector keyCorrupted = keyfileData; + for (size_t i = 10; i < 20 && i < keyCorrupted.size(); ++i) { + keyCorrupted[i] = 0; + } + ASSERT_TRUE(OHOS::SaveBufferToFile(keyPathV1, keyCorrupted)); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_TRUE(isFileExists); + isFileExists = OHOS::FileExists(keyPathV0); + ASSERT_FALSE(isFileExists); +} + +/** +* @tc.name: OTATest_003 +* @tc.desc: keyFileV1 and keyFile exit ota test +* @tc.type: FUNC +*/ +HWTEST_F(RdbEncryptUpgradeTest, OTATest_003, TestSize.Level1) +{ + RdbStoreConfig config(RdbEncryptUpgradeTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetEncryptStatus(true); + RdbEncryptUpgradeTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + std::string keyPathV1 = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; + bool isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_TRUE(isFileExists); + store = nullptr; + + RdbSecretKeyData keyDataV1; + auto res = RdbSecurityManager::GetInstance().LoadSecretKeyFromDiskV1(keyPathV1, keyDataV1); + ASSERT_EQ(res, true); + std::string keyPathV0 = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + RdbSecretKeyData keyDataV0; + keyDataV0.timeValue = keyDataV1.timeValue; + keyDataV0.distributed = 0; + auto rootKeyAlias = RdbSecurityManager::GetInstance().GetRootKeyAlias(); + auto ret = RdbSecurityManager::GetInstance().CheckRootKeyExists(rootKeyAlias); + ASSERT_NE(ret, HKS_ERROR_NOT_EXIST); + keyDataV0.secretKey = EncryptV0(keyDataV1.secretKey, rootKeyAlias); + res = SaveSecretKeyToV0(keyPathV0, keyDataV0); + ASSERT_EQ(res, true); + isFileExists = OHOS::FileExists(keyPathV0); + ASSERT_TRUE(isFileExists); + + SqliteUtils::DeleteFile(keyPathV1); + isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_FALSE(isFileExists); + auto fd = open(keyPathV1.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + ASSERT_GT(fd, 0); + isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_TRUE(isFileExists); + + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_TRUE(isFileExists); + isFileExists = OHOS::FileExists(keyPathV0); + ASSERT_FALSE(isFileExists); +} + +/** +* @tc.name: OTATest_004 +* @tc.desc: query after getRdbStore ota test +* @tc.type: FUNC +*/ +HWTEST_F(RdbEncryptUpgradeTest, OTATest_004, TestSize.Level1) +{ + RdbStoreConfig config(RdbEncryptUpgradeTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetEncryptStatus(true); + RdbEncryptUpgradeTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"); + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + std::string keyPathV1 = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; + store = nullptr; + + RdbSecretKeyData keyDataV1; + auto res = RdbSecurityManager::GetInstance().LoadSecretKeyFromDiskV1(keyPathV1, keyDataV1); + ASSERT_EQ(res, true); + std::string keyPathV0 = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + RdbSecretKeyData keyDataV0; + keyDataV0.timeValue = keyDataV1.timeValue; + keyDataV0.distributed = 0; + auto rootKeyAlias = RdbSecurityManager::GetInstance().GetRootKeyAlias(); + ret = RdbSecurityManager::GetInstance().CheckRootKeyExists(rootKeyAlias); + ASSERT_NE(ret, HKS_ERROR_NOT_EXIST); + keyDataV0.secretKey = EncryptV0(keyDataV1.secretKey, rootKeyAlias); + res = SaveSecretKeyToV0(keyPathV0, keyDataV0); + ASSERT_EQ(res, true); + + SqliteUtils::DeleteFile(keyPathV1); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + auto resultSet = store->QueryByStep("SELECT * FROM test1"); + ASSERT_NE(resultSet, nullptr); + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + ASSERT_EQ(rowCount, 1); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_error_log_test/get_rdb_store_test.cpp b/relational_store/test/native/rdb/unittest/rdb_error_log_test/get_rdb_store_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..609d473f9d12d08935ea477f1484c3b0c7b5de12 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_error_log_test/get_rdb_store_test.cpp @@ -0,0 +1,594 @@ +/* + * Copyright (c) 2025 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 + +#include +#include +#include + +#include "common.h" +#include "block_data.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "rdb_sql_log.h" +#include "rdb_store.h" +#include "rdb_store_manager.h" +#include "rdb_types.h" +#include "executor_pool.h" +#include "shared_block.h" +#include "sqlite_utils.h" +#include "values_bucket.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::DistributedRdb; + +static constexpr int32_t MAX_THREAD = 8; +static constexpr int32_t MID_THREAD = 4; +static constexpr int32_t SLEEP_TIME = 500; +static constexpr int32_t MAX_SLEEP_TIME = 2000; +static constexpr int32_t JOURNAL_MAX_SIZE = 4096; +static constexpr int32_t JOURNAL_MIN_SIZE = 1024; +static constexpr double DEFAULT_SALARY = 100.5; +static constexpr int32_t AGE_NUM = 18; + +class RdbStoreStoreMultiTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static std::shared_ptr CreateRDB(const std::string &path, + bool encrypt = false, const std::string &bundleName = ""); + static std::shared_ptr CreateRDBSleep(const std::string &path, + bool encrypt = false, const std::string &bundleName = ""); + static void InsertData(std::shared_ptr rdbStore); + static void QueryData(std::shared_ptr rdbStore); +}; + + +void RdbStoreStoreMultiTest::SetUpTestCase(void) +{ +} + +void RdbStoreStoreMultiTest::TearDownTestCase(void) +{ +} + +void RdbStoreStoreMultiTest::SetUp() +{ +} + +void RdbStoreStoreMultiTest::TearDown() +{ +} + +class RDBCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +int RDBCallback::OnCreate(RdbStore &store) +{ + return E_OK; +} + +int RDBCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +class CallbackSleep : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +int CallbackSleep::OnCreate(RdbStore &store) +{ + std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME)); + return E_OK; +} + +int CallbackSleep::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME)); + return E_OK; +} + +std::shared_ptr RdbStoreStoreMultiTest::CreateRDB(const std::string &path, + bool encrypt, const std::string &bundleName) +{ + int version = 1; + RdbStoreConfig config(path); + config.SetEncryptStatus(encrypt); + config.SetBundleName(bundleName); + RDBCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, version, helper, errCode); + EXPECT_NE(store, nullptr); + return store; +} + +std::shared_ptr RdbStoreStoreMultiTest::CreateRDBSleep(const std::string &path, + bool encrypt, const std::string &bundleName) +{ + int version = 1; + RdbStoreConfig config(path); + config.SetEncryptStatus(encrypt); + config.SetBundleName(bundleName); + CallbackSleep helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, version, helper, errCode); + EXPECT_NE(store, nullptr); + return store; +} + +void RdbStoreStoreMultiTest::InsertData(std::shared_ptr rdbStore) +{ + const std::string createTable = + std::string("CREATE TABLE IF NOT EXISTS test ") + std::string("(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary " + "REAL, blobType BLOB)"); + rdbStore->Execute(createTable); + int64_t id; + ValuesBucket values; + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", AGE_NUM); + values.PutDouble("salary", DEFAULT_SALARY); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = rdbStore->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); +} + +void RdbStoreStoreMultiTest::QueryData(std::shared_ptr rdbStore) +{ + std::shared_ptr resultSet = rdbStore->QuerySql("select * from test"); + int ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + int columnIndex; + std::string strVal; + + ret = resultSet->GetColumnIndex("name", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ("zhangsan", strVal); +} + +std::string g_dbPaths[MAX_THREAD] = { "/data/test/store1.db", "/data/test/store2.db", + "/data/test/store3.db", "/data/test/store4.db", "/data/test/store5.db", + "/data/test/store6.db", "/data/test/store7.db", "/data/test/store8.db" }; + +std::string g_dbBundlenames[MAX_THREAD] = { "com.ohos.test1", "com.ohos.test2", + "com.ohos.test3", "com.ohos.test4", "com.ohos.test5", + "com.ohos.test6", "com.ohos.test7", "com.ohos.test8" }; + +/** + * @tc.name: GetRdbStoreTest_001 + * @tc.desc: test Multithreading calls GetRdbStore with same store + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_001, TestSize.Level1) +{ + std::string path = "/data/test/store.db"; + std::shared_ptr stores[MAX_THREAD]; + std::thread threads[MAX_THREAD]; + for (int i = 0; i < MAX_THREAD; ++i) { + threads[i] = std::thread([i, &stores, &path]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDB(path); + }); + } + for (auto& t : threads) { + if (t.joinable()) { + t.join(); + } + } + EXPECT_EQ(stores[0], stores[1]); + EXPECT_EQ(stores[1], stores[2]); + EXPECT_EQ(stores[2], stores[3]); + EXPECT_EQ(stores[3], stores[4]); + EXPECT_EQ(stores[4], stores[5]); + EXPECT_EQ(stores[5], stores[6]); + EXPECT_EQ(stores[6], stores[7]); + RdbHelper::DeleteRdbStore(path); +} + +/** + * @tc.name: GetRdbStoreTest_002 + * @tc.desc: test Multithreading calls GetRdbStore with same encrypt store + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_002, TestSize.Level1) +{ + std::string path = "/data/test/encryptStore.db"; + std::string bundleName = "com.ohos.test"; + std::shared_ptr stores[MAX_THREAD]; + std::thread threads[MAX_THREAD]; + for (int i = 0; i < MAX_THREAD; ++i) { + threads[i] = std::thread([i, &stores, &path, &bundleName]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDB(path, true, bundleName); + }); + } + for (auto& t : threads) { + if (t.joinable()) { + t.join(); + } + } + + EXPECT_EQ(stores[0], stores[1]); + EXPECT_EQ(stores[1], stores[2]); + EXPECT_EQ(stores[2], stores[3]); + EXPECT_EQ(stores[3], stores[4]); + EXPECT_EQ(stores[4], stores[5]); + EXPECT_EQ(stores[5], stores[6]); + EXPECT_EQ(stores[6], stores[7]); + RdbHelper::DeleteRdbStore(path); +} + +/** + * @tc.name: GetRdbStoreTest_003 + * @tc.desc: test Multithreading calls GetRdbStore with diff store + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_003, TestSize.Level1) +{ + std::shared_ptr stores[MAX_THREAD]; + std::thread threads[MAX_THREAD]; + for (int i = 0; i < MID_THREAD; ++i) { + threads[i] = std::thread([i, &stores]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDB(g_dbPaths[i]); + }); + } + for (int i = MID_THREAD; i < MAX_THREAD; ++i) { + threads[i] = std::thread([i, &stores]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDBSleep(g_dbPaths[i]); + }); + } + for (int i = 0; i < MAX_THREAD; ++i) { + if (threads[i].joinable()) { + threads[i].join(); + } + EXPECT_NE(stores[i], nullptr); + } + std::this_thread::sleep_for(std::chrono::milliseconds(MAX_SLEEP_TIME)); + for (int i = 0; i < MAX_THREAD; ++i) { + RdbHelper::DeleteRdbStore(g_dbPaths[i]); + } +} + +/** + * @tc.name: GetRdbStoreTest_004 + * @tc.desc: test Multithreading calls GetRdbStore with diff encrypt store + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_004, TestSize.Level1) +{ + std::string bundleName = "com.ohos.test"; + std::shared_ptr stores[MAX_THREAD]; + std::thread threads[MAX_THREAD]; + for (int i = 0; i < MID_THREAD; ++i) { + threads[i] = std::thread([i, &stores, &bundleName]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDB(g_dbPaths[i], true, bundleName); + }); + } + for (int i = MID_THREAD; i < MAX_THREAD; ++i) { + threads[i] = std::thread([i, &stores, &bundleName]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDBSleep(g_dbPaths[i], true, bundleName); + }); + } + for (int i = 0; i < MAX_THREAD; ++i) { + if (threads[i].joinable()) { + threads[i].join(); + } + EXPECT_NE(stores[i], nullptr); + } + std::this_thread::sleep_for(std::chrono::milliseconds(MAX_SLEEP_TIME)); + for (int i = 0; i < MAX_THREAD; ++i) { + RdbHelper::DeleteRdbStore(g_dbPaths[i]); + } +} + +/** + * @tc.name: GetRdbStoreTest_005 + * @tc.desc: test Multithreading calls GetRdbStore with diff encrypt store and store + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_005, TestSize.Level1) +{ + std::string bundleName = "com.ohos.test"; + std::shared_ptr stores[MAX_THREAD]; + std::thread threads[MAX_THREAD]; + for (int i = 0; i < MID_THREAD; ++i) { + threads[i] = std::thread([i, &stores, &bundleName]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDB(g_dbPaths[i]); + }); + } + for (int i = MID_THREAD; i < MAX_THREAD; ++i) { + threads[i] = std::thread([i, &stores, &bundleName]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDBSleep(g_dbPaths[i], true, bundleName); + }); + } + for (int i = 0; i < MAX_THREAD; ++i) { + if (threads[i].joinable()) { + threads[i].join(); + } + EXPECT_NE(stores[i], nullptr); + } + std::this_thread::sleep_for(std::chrono::milliseconds(MAX_SLEEP_TIME)); + for (int i = 0; i < MAX_THREAD; ++i) { + RdbHelper::DeleteRdbStore(g_dbPaths[i]); + } +} + +/** + * @tc.name: GetRdbStoreTest_006 + * @tc.desc: test Multithreading calls GetRdbStore with diff encrypt store with diff bundlename + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_006, TestSize.Level1) +{ + std::shared_ptr stores[MAX_THREAD]; + std::thread threads[MAX_THREAD]; + for (int i = 0; i < MAX_THREAD; ++i) { + threads[i] = std::thread([i, &stores]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDB(g_dbPaths[i], true, g_dbBundlenames[i]); + }); + } + for (int i = 0; i < MAX_THREAD; ++i) { + if (threads[i].joinable()) { + threads[i].join(); + } + EXPECT_NE(stores[i], nullptr); + } + std::this_thread::sleep_for(std::chrono::milliseconds(MAX_SLEEP_TIME)); + for (int i = 0; i < MAX_THREAD; ++i) { + RdbHelper::DeleteRdbStore(g_dbPaths[i]); + } +} + +/** + * @tc.name: GetRdbStoreTest_007 + * @tc.desc: test Multithreading calls GetRdbStore with diff config + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_007, TestSize.Level1) +{ + std::string path = "/data/test/encrypt07store.db"; + int version = 1; + RdbStoreConfig configA(path); + configA.SetEncryptStatus(true); + configA.SetBundleName("com.ohos.test"); + RDBCallback helper; + int errCode = E_OK; + std::shared_ptr storeA = RdbHelper::GetRdbStore(configA, version, helper, errCode); + EXPECT_NE(storeA, nullptr); + RdbStoreStoreMultiTest::InsertData(storeA); + storeA = nullptr; + + RdbStoreConfig configB(path); + configB.SetEncryptStatus(false); + configB.SetBundleName("com.ohos.test"); + std::shared_ptr storeB = RdbHelper::GetRdbStore(configB, version, helper, errCode); + EXPECT_NE(storeB, nullptr); + RdbStoreStoreMultiTest::QueryData(storeB); + + RdbHelper::DeleteRdbStore(path); +} + +/** + * @tc.name: GetRdbStoreTest_008 + * @tc.desc: test Multithreading calls GetRdbStore with diff config + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_008, TestSize.Level1) +{ + std::string path = "/data/test/store.db"; + int version = 1; + RdbStoreConfig configA(path); + configA.SetJournalSize(JOURNAL_MAX_SIZE); + configA.SetBundleName("com.ohos.test"); + RDBCallback helper; + int errCode = E_OK; + std::shared_ptr storeA = RdbHelper::GetRdbStore(configA, version, helper, errCode); + EXPECT_NE(storeA, nullptr); + + RdbStoreConfig configB(path); + configB.SetBundleName("com.ohos.test"); + configB.SetJournalSize(JOURNAL_MIN_SIZE); + std::shared_ptr storeB = RdbHelper::GetRdbStore(configB, version, helper, errCode); + EXPECT_NE(storeB, nullptr); + EXPECT_NE(storeA, storeB); + + std::shared_ptr storeC = RdbHelper::GetRdbStore(configB, version, helper, errCode); + EXPECT_EQ(storeB, storeC); + RdbHelper::DeleteRdbStore(path); +} + +/** + * @tc.name: GetRdbStoreTest_009 + * @tc.desc: test Multithreading calls GetRdbStore with diff config and allowRebuild + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_009, TestSize.Level1) +{ + std::string path = "/data/test/encrypt09store.db"; + int version = 1; + RdbStoreConfig configA(path); + configA.SetEncryptStatus(false); + configA.SetAllowRebuild(true); + configA.SetBundleName("com.ohos.test"); + RDBCallback helper; + int errCode = E_OK; + std::shared_ptr storeA = RdbHelper::GetRdbStore(configA, version, helper, errCode); + ASSERT_NE(storeA, nullptr); + RdbStoreStoreMultiTest::InsertData(storeA); + storeA = nullptr; + + RdbStoreConfig configB(path); + configB.SetEncryptStatus(true); + configB.SetAllowRebuild(true); + configB.SetBundleName("com.ohos.test"); + std::shared_ptr storeB = RdbHelper::GetRdbStore(configB, version, helper, errCode); + ASSERT_NE(storeB, nullptr); + auto rebuilt = RebuiltType::NONE; + storeB->GetRebuilt(rebuilt); + EXPECT_EQ(rebuilt, RebuiltType::NONE); + RdbStoreStoreMultiTest::QueryData(storeB); + + RdbHelper::DeleteRdbStore(path); +} + +/** + * @tc.name: GetRdbStoreTest_010 + * @tc.desc: 1. Create encrypted and non-encrypted databases + * 2. Insert a piece of data into a non-encrypted database + * 3. Delete encrypted database + * 4. Rename the non-encrypted database as an encrypted database + * 5. Open with non-encrypted parameters to query data + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_010, TestSize.Level1) +{ + std::string path1 = "/data/test/encrypt10store.db"; + std::string path1Wal = "/data/test/encrypt10store.db-wal"; + std::string path1Shm = "/data/test/encrypt10store.db-shm"; + std::string path2 = "/data/test/10store.db"; + std::string path2Wal = "/data/test/10store.db-wal"; + std::string path2Shm = "/data/test/10store.db-shm"; + int version = 1; + RdbStoreConfig configA(path1); + configA.SetEncryptStatus(true); + configA.SetAllowRebuild(true); + configA.SetBundleName("com.ohos.test"); + RDBCallback helper; + int errCode = E_OK; + std::shared_ptr storeA = RdbHelper::GetRdbStore(configA, version, helper, errCode); + ASSERT_NE(storeA, nullptr); + storeA = nullptr; + + RdbStoreConfig configB(path2); + configB.SetEncryptStatus(false); + configB.SetAllowRebuild(true); + configB.SetBundleName("com.ohos.test"); + std::shared_ptr storeB = RdbHelper::GetRdbStore(configB, version, helper, errCode); + ASSERT_NE(storeB, nullptr); + RdbStoreStoreMultiTest::InsertData(storeB); + storeB = nullptr; + // Delete the encrypted database path1, rename the database path2 to path1. + SqliteUtils::DeleteFile(path1); + SqliteUtils::DeleteFile(path1Wal); + SqliteUtils::DeleteFile(path1Shm); + SqliteUtils::RenameFile(path2, path1); + SqliteUtils::RenameFile(path2Wal, path1Wal); + SqliteUtils::RenameFile(path2Shm, path1Shm); + // The current database of path1 is actually a non-encrypted database, + // and the data content is the original data content of path2. + configA.SetEncryptStatus(false); + storeA = RdbHelper::GetRdbStore(configA, version, helper, errCode); + ASSERT_NE(storeA, nullptr); + RdbStoreStoreMultiTest::QueryData(storeA); + storeA = nullptr; + + RdbHelper::DeleteRdbStore(path1); +} + + +/** + * @tc.name: GetRdbStoreTest_011 + * @tc.desc: 1. Create encrypted and non-encrypted databases + * 2. Insert a piece of data into a non-encrypted database + * 3. Delete encrypted database + * 4. Rename the non-encrypted database as an encrypted database + * 5. Open with encrypted parameters to query data + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_011, TestSize.Level1) +{ + std::string path1 = "/data/test/encrypt11store.db"; + std::string path1Wal = "/data/test/encrypt11store.db-wal"; + std::string path1Shm = "/data/test/encrypt11store.db-shm"; + std::string path2 = "/data/test/11store.db"; + std::string path2Wal = "/data/test/11store.db-wal"; + std::string path2Shm = "/data/test/11store.db-shm"; + int version = 1; + RdbStoreConfig configA(path1); + configA.SetEncryptStatus(true); + configA.SetAllowRebuild(true); + configA.SetBundleName("com.ohos.test"); + RDBCallback helper; + int errCode = E_OK; + std::shared_ptr storeA = RdbHelper::GetRdbStore(configA, version, helper, errCode); + ASSERT_NE(storeA, nullptr); + storeA = nullptr; + + RdbStoreConfig configB(path2); + configB.SetEncryptStatus(false); + configB.SetAllowRebuild(true); + configB.SetBundleName("com.ohos.test"); + std::shared_ptr storeB = RdbHelper::GetRdbStore(configB, version, helper, errCode); + ASSERT_NE(storeB, nullptr); + RdbStoreStoreMultiTest::InsertData(storeB); + storeB = nullptr; + // Delete the encrypted database path1, rename the database path2 to path1, and open path1. + SqliteUtils::DeleteFile(path1); + SqliteUtils::DeleteFile(path1Wal); + SqliteUtils::DeleteFile(path1Shm); + SqliteUtils::RenameFile(path2, path1); + SqliteUtils::RenameFile(path2Wal, path1Wal); + SqliteUtils::RenameFile(path2Shm, path1Shm); + // The current database of path1 is actually a non-encrypted database, and it cannot be opened + // using encryption parameters. The reconstruction was successful, but there is no data in the table. + storeA = RdbHelper::GetRdbStore(configA, version, helper, errCode); + ASSERT_NE(storeA, nullptr); + RebuiltType rebuiltType; + storeA->GetRebuilt(rebuiltType); + EXPECT_EQ(rebuiltType, RebuiltType::REBUILT); + std::shared_ptr resultSet = storeA->QuerySql("select * from test"); + int ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_SQLITE_ERROR); + storeA = nullptr; + + RdbHelper::DeleteRdbStore(path1); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_error_log_test/rdb_error_log_test.cpp b/relational_store/test/native/rdb/unittest/rdb_error_log_test/rdb_error_log_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..48800db5fe89a1b2b185b43af7de055c594fa2ad --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_error_log_test/rdb_error_log_test.cpp @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2025 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 + +#include "common.h" +#include "block_data.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "rdb_sql_log.h" +#include "rdb_store_manager.h" +#include "rdb_types.h" +#include "executor_pool.h" +#include "shared_block.h" +#include "sqlite_shared_result_set.h" +#include "step_result_set.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::DistributedRdb; +static constexpr int32_t MAX_THREAD = 5; +static constexpr int32_t MIN_THREAD = 0; +static std::string g_createTable = "CREATE TABLE IF NOT EXISTS test " +"(id INTEGER PRIMARY KEY AUTOINCREMENT, " +"name TEXT NOT NULL, age INTEGER, salary " +"REAL, blobType BLOB)"; +static std::string g_databaseName = "/data/test/subscribe.db"; + +class RdbStoreLogSubTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static std::shared_ptr CreateRDB(int version); + static std::shared_ptr store; +}; + +std::shared_ptr RdbStoreLogSubTest::store = nullptr; + +void RdbStoreLogSubTest::SetUpTestCase(void) +{ + RdbHelper::DeleteRdbStore(g_databaseName); + store = CreateRDB(1); +} + +void RdbStoreLogSubTest::TearDownTestCase(void) +{ + store = nullptr; + RdbHelper::DeleteRdbStore(g_databaseName); +} + +void RdbStoreLogSubTest::SetUp() +{ +} + +void RdbStoreLogSubTest::TearDown() +{ +} + +class Callback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +int Callback::OnCreate(RdbStore &store) +{ + return E_OK; +} + +int Callback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +std::shared_ptr RdbStoreLogSubTest::CreateRDB(int version) +{ + RdbStoreConfig config(g_databaseName); + config.SetBundleName("subscribe_test"); + config.SetArea(0); + config.SetCreateNecessary(true); + config.SetDistributedType(RDB_DEVICE_COLLABORATION); + config.SetSecurityLevel(OHOS::NativeRdb::SecurityLevel::S1); + Callback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, version, helper, errCode); + EXPECT_NE(store, nullptr); + return store; +} + +class OnErrorObserver : public SqlErrorObserver { +public: + void OnErrorLog(const ExceptionMessage &message) override; + ExceptionMessage GetLastMessage(); + void SetBlockData(std::shared_ptr> block); + +private: + std::shared_ptr> block_; + ExceptionMessage lastMessage; +}; + + +void OnErrorObserver::OnErrorLog(const ExceptionMessage &message) +{ + lastMessage = message; + if (block_) { + block_->SetValue(true); + } +} + +ExceptionMessage OnErrorObserver::GetLastMessage() +{ + return lastMessage; +} + +void OnErrorObserver::SetBlockData(std::shared_ptr> block) +{ + block_ = block; +} + + +/** + * @tc.name: RdbStoreSubscribeLog001 + * @tc.desc: test sqliteErrorOccurred observer when SQLITE_ERROR + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreLogSubTest, RdbStoreSubscribeLog001, TestSize.Level1) +{ + auto observer = std::make_shared(); + SqlLog::Subscribe(g_databaseName, observer); + std::shared_ptr> block = std::make_shared>(3, false); + observer->SetBlockData(block); + ValuesBucket values; + int64_t id; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + auto ret = store->Insert(id, "sqliteLog", values); + EXPECT_NE(ret, E_OK); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(observer->GetLastMessage().code, 1); + EXPECT_EQ(observer->GetLastMessage().message, "no such table: sqliteLog"); + EXPECT_EQ(observer->GetLastMessage().sql, "INSERT INTO sqliteLog(age,id,name) VALUES (?,?,?)"); +} + +/** + * @tc.name: RdbStoreSubscribeLog002 + * @tc.desc: test sqliteErrorOccurred observer when SQLITE_CONSTRAINT + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreLogSubTest, RdbStoreSubscribeLog002, TestSize.Level1) +{ + auto observer = std::make_shared(); + constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS errorlog_test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"; + auto ret = store->ExecuteSql(createTableTest); + EXPECT_EQ(ret, E_OK); + ValuesBucket values; + int64_t id; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + ret = store->Insert(id, "errorlog_test", values); + EXPECT_EQ(ret, E_OK); + std::shared_ptr> block = std::make_shared>(3, false); + SqlLog::Subscribe(g_databaseName, observer); + observer->SetBlockData(block); + ret = store->Insert(id, "errorlog_test", values); + EXPECT_NE(ret, E_OK); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(observer->GetLastMessage().code, 19); + EXPECT_EQ(observer->GetLastMessage().message, "UNIQUE constraint failed: errorlog_test.id"); + EXPECT_EQ(observer->GetLastMessage().sql, "INSERT INTO errorlog_test(age,id,name) VALUES (?,?,?)"); +} + +/** + * @tc.name: RdbStoreSubscribeLog003 + * @tc.desc: test sqliteErrorOccurred observer when SQLITE_BUSY + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreLogSubTest, RdbStoreSubscribeLog003, TestSize.Level1) +{ + auto observer = std::make_shared(); + std::string tableName = "OnErrorLogTable"; + auto res = store->Execute( + "CREATE TABLE " + tableName + " (id INTEGER PRIMARY KEY CHECK (id >= 3 OR id <= 1), name TEXT NOT NULL)"); + ASSERT_EQ(res.first, E_OK); + + auto [code, transaction] = store->CreateTransaction(Transaction::IMMEDIATE); + ASSERT_EQ(code, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + SqlLog::Subscribe(g_databaseName, observer); + std::shared_ptr> block = std::make_shared>(3, false); + observer->SetBlockData(block); + auto result = store->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); + ASSERT_EQ(result.first, E_SQLITE_BUSY); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(observer->GetLastMessage().code, 5); + EXPECT_EQ(observer->GetLastMessage().message, "database is locked"); + EXPECT_EQ( + observer->GetLastMessage().sql, "INSERT INTO OnErrorLogTable (id,name) VALUES (?,?),(?,?),(?,?),(?,?),(?,?)"); +} + +/** + * @tc.name: RdbStoreSubscribeLog004 + * @tc.desc: test sqliteErrorOccurred observer when SQLITE_LOCKED + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ + HWTEST_F(RdbStoreLogSubTest, RdbStoreSubscribeLog004, TestSize.Level1) + { + auto observer = std::make_shared(); + std::string dbPath = RDB_TEST_PATH + "errorlog.db"; + int errCode = E_OK; + RdbStoreConfig memoryConfig(dbPath); + Callback helper; + memoryConfig.SetStorageMode(StorageMode::MODE_MEMORY); + std::shared_ptr memoryStore = RdbHelper::GetRdbStore(memoryConfig, 1, helper, errCode); + auto res = memoryStore->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)"); + ASSERT_EQ(res.first, E_OK); + auto [ret1, transaction1] = memoryStore->CreateTransaction(Transaction::IMMEDIATE); + ASSERT_EQ(ret1, E_OK); + ASSERT_NE(transaction1, nullptr); + + auto [ret, transaction] = memoryStore->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + Transaction::Row row; + row.Put("id", i); + row.Put("name", "Jim_batchInsert"); + rows.Put(row); + } + SqlLog::Subscribe(dbPath, observer); + std::shared_ptr> block = std::make_shared>(3, false); + observer->SetBlockData(block); + auto result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_NONE); + ASSERT_EQ(result.first, E_SQLITE_LOCKED); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(observer->GetLastMessage().code, 6); + EXPECT_EQ(observer->GetLastMessage().message, "database table is locked"); + EXPECT_EQ(observer->GetLastMessage().sql, "INSERT INTO test1 (id,name) VALUES (?,?),(?,?),(?,?),(?,?),(?,?)"); +} + +/** + * @tc.name: RdbStoreSubscribeLog005 + * @tc.desc: test sqliteErrorOccurred observer when SQLITE_SCHEMA + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreLogSubTest, RdbStoreSubscribeLog005, TestSize.Level1) +{ + auto observer = std::make_shared(); + store->ExecuteSql(g_createTable); + std::shared_ptr executors; + std::shared_ptr> block1 = std::make_shared>(3, false); + executors = std::make_shared(MAX_THREAD, MIN_THREAD); + auto taskId1 = executors->Execute([storeCopy = store, block1]() { + constexpr const char *createTable = "CREATE TABLE test"; + constexpr const char *createTableColumn = " (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, " + "blobType BLOB)"; + int32_t errCode = E_ERROR; + for (uint32_t i = 0; i < 2000; i++) { + errCode = storeCopy->ExecuteSql(createTable + std::to_string(i) + createTableColumn); + if (errCode != E_OK) { + break; + } + } + block1->SetValue(errCode); + }); + std::shared_ptr> block = std::make_shared>(3, false); + SqlLog::Subscribe(g_databaseName, observer); + observer->SetBlockData(block); + std::shared_ptr> block2 = std::make_shared>(3, false); + auto taskId2 = executors->Execute([storeCopy = store, block2]() { + int32_t errCode = E_ERROR; + for (uint32_t i = 0; i < 2000; i++) { + auto resultSet = storeCopy->QueryByStep("SELECT * FROM test"); + int rowCount = -1; + errCode = resultSet->GetRowCount(rowCount); + resultSet->Close(); + if (errCode != E_OK && errCode != E_SQLITE_SCHEMA) { + break; + } + } + auto code = (errCode == E_OK || errCode == E_SQLITE_SCHEMA) ? E_OK : errCode; + block2->SetValue(code); + }); + EXPECT_EQ(block1->GetValue(), E_OK); + EXPECT_EQ(block2->GetValue(), E_OK); + EXPECT_NE(taskId1, taskId2); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(observer->GetLastMessage().code, 17); + EXPECT_EQ(observer->GetLastMessage().message, "database schema has changed"); + EXPECT_EQ(observer->GetLastMessage().sql, "SELECT * FROM test"); +} + +/** + * @tc.name: RdbStoreSubscribeLog006 + * @tc.desc: test sqliteErrorOccurred observer when SQLITE_FULL + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreLogSubTest, RdbStoreSubscribeLog006, TestSize.Level1) +{ + auto observer = std::make_shared(); + store->ExecuteSql(g_createTable); + auto [code, maxPageCount] = store->Execute("PRAGMA max_page_count;"); + auto recover = std::shared_ptr("recover", [defPageCount = maxPageCount, + storeCopy = store](const char *) { + storeCopy->Execute("PRAGMA max_page_count = " + static_cast(defPageCount) + ";"); + }); + std::tie(code, maxPageCount) = store->Execute("PRAGMA max_page_count = 256;"); + ValuesBucket row; + row.Put("name", std::string(1024 * 1024, 'e')); + std::shared_ptr> block = std::make_shared>(3, false); + SqlLog::Subscribe(g_databaseName, observer); + observer->SetBlockData(block); + auto result = store->Insert("test", row, ConflictResolution::ON_CONFLICT_NONE); + ASSERT_EQ(result.first, E_SQLITE_FULL); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(observer->GetLastMessage().code, 13); + EXPECT_EQ(observer->GetLastMessage().message, "database or disk is full"); + EXPECT_EQ(observer->GetLastMessage().sql, "INSERT INTO test(name) VALUES (?)"); +} + +/** + * @tc.name: RdbStoreSubscribeLog007 + * @tc.desc: test sqliteErrorOccurred observer when off observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreLogSubTest, RdbStoreSubscribeLog007, TestSize.Level1) +{ + auto observer = std::make_shared(); + SqlLog::Subscribe(g_databaseName, observer); + std::shared_ptr> block = std::make_shared>(3, false); + observer->SetBlockData(block); + SqlLog::Unsubscribe(g_databaseName, observer); + ValuesBucket values; + int64_t id; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + auto ret = store->Insert(id, "sqliteLog", values); + EXPECT_NE(ret, E_OK); + EXPECT_EQ(block->GetValue(), false); + EXPECT_EQ(observer->GetLastMessage().code, 0); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_error_log_test/rdb_perfStat_test.cpp b/relational_store/test/native/rdb/unittest/rdb_error_log_test/rdb_perfStat_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c2fa3db10bba6d36b6c621818f9423d643335fc8 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_error_log_test/rdb_perfStat_test.cpp @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2025 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 "RdbPerfStatTest" +#include + +#include +#include +#include + +#include "block_data.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "rdb_store_manager.h" +#include "rdb_types.h" +#include "logger.h" +#include "rdb_platform.h" +#include "rdb_perfStat.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::DistributedRdb; +using namespace OHOS::Rdb; + +class PerfStatObserver : public SqlObserver { +public: + virtual ~PerfStatObserver() + { + } + void OnStatistic(const SqlExecutionInfo &info); + void SetBlockData(std::shared_ptr> block); + SqlExecutionInfo perfInfo_; +private: + std::shared_ptr> block_; +}; + +class RdbPerfStatTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static const std::string databasePath; + static std::shared_ptr CreateRDB(int version); + static std::shared_ptr store; + static std::shared_ptr sqlObserver_; +}; + +const std::string RdbPerfStatTest::databasePath = "/data/test/perfStat.db"; +std::shared_ptr RdbPerfStatTest::store = nullptr; +std::shared_ptr RdbPerfStatTest::sqlObserver_ = nullptr; +void RdbPerfStatTest::SetUpTestCase(void) +{ + RdbHelper::DeleteRdbStore(databasePath); + store = CreateRDB(1); + if (sqlObserver_ == nullptr) { + sqlObserver_ = std::make_shared(); + } +} + +void RdbPerfStatTest::TearDownTestCase(void) +{ + store = nullptr; + RdbHelper::DeleteRdbStore(databasePath); +} + +void RdbPerfStatTest::SetUp() +{ +} + +void RdbPerfStatTest::TearDown() +{ +} + +class PerfStatCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +int PerfStatCallback::OnCreate(RdbStore &store) +{ + return E_OK; +} + +int PerfStatCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void PerfStatObserver::OnStatistic(const PerfStatObserver::SqlExecutionInfo &info) +{ + perfInfo_ = info; + if (block_) { + block_->SetValue(true); + } +} + +void PerfStatObserver::SetBlockData(std::shared_ptr> block) +{ + block_ = block; +} + +std::shared_ptr RdbPerfStatTest::CreateRDB(int version) +{ + RdbStoreConfig config(RdbPerfStatTest::databasePath); + config.SetBundleName("subscribe_test"); + config.SetArea(0); + config.SetCreateNecessary(true); + config.SetDistributedType(RDB_DEVICE_COLLABORATION); + config.SetSecurityLevel(OHOS::NativeRdb::SecurityLevel::S1); + PerfStatCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, version, helper, errCode); + EXPECT_NE(store, nullptr); + constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS perfStat_test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"; + store->ExecuteSql(createTableTest); + return store; +} + +/** + * @tc.name: RdbPerfStat001 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat001, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + ValuesBucket values; + int64_t id; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); // 18 is random age + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + status = store->Insert(id, "perfStat_test", values); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(id, 1); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat002 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat002, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + int id; + ValuesBucket values; + values.PutString("name", std::string("zhangsan_update2")); + values.PutInt("age", 20); // 20 is random age + AbsRdbPredicates predicates("perfStat_test"); + predicates.EqualTo("id", 1); + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + status = store->Update(id, values, predicates); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(id, 1); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat003 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat003, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + int id; + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + status = store->Delete(id, "perfStat_test", "id = ?", std::vector{ "1" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(id, 1); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat004 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat004, TestSize.Level1) +{ + int num = 3; + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + int64_t id; + std::vector values; + for (int i = 0; i < num; i++) { + ValuesBucket value; + value.PutInt("id", i); + value.PutString("name", std::string("zhangsan")); + value.PutInt("age", 18); // 18 is random age + values.push_back(value); + } + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + status = store->BatchInsert(id, "perfStat_test", values); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(id, num); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat005 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat005, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS perfStat_test2 " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"; + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + status = store->ExecuteSql(createTableTest); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_[0], createTableTest); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat006 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat006, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + constexpr const char *pargmaTest = "PRAGMA quick_check"; + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + store->Execute(pargmaTest); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_[0], pargmaTest); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat007 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat007, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + std::shared_ptr resultSet = store->QueryByStep("SELECT * FROM perfStat_test"); + ASSERT_NE(resultSet, nullptr); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat008 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat008, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM perfStat_test"); + ASSERT_NE(resultSet, nullptr); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat009 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat009, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + AbsRdbPredicates predicates("perfStat_test"); + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + std::shared_ptr resultSet = store->Query(predicates); + ASSERT_NE(resultSet, nullptr); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat010 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat010, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + EXPECT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBucket value; + value.PutString("name", std::string("zhangsan")); + value.PutInt("age", 18); // 18 is random age + + auto result = transaction->Insert("perfStat_test", value); + EXPECT_EQ(result.first, E_OK); + ret = transaction->Commit(); + EXPECT_EQ(ret, E_OK); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 3); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat011 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat011, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + EXPECT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + int num = 3; + std::vector values; + for (int i = 0; i < num; i++) { + ValuesBucket value; + value.PutInt("id", i); + value.PutString("name", std::string("zhangsan")); + value.PutInt("age", 18); // 18 is random age + values.push_back(value); + } + auto result = transaction->BatchInsert("perfStat_test", values); + EXPECT_EQ(result.first, E_OK); + ret = transaction->Commit(); + EXPECT_EQ(ret, E_OK); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 3); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_execute_rd_test.cpp b/relational_store/test/native/rdb/unittest/rdb_execute_rd_test.cpp index 58b218b052895c69c6ef50b986a17c3973307f48..7c478c7bfe363520fa9655b2cc5ac919460bfd88 100644 --- a/relational_store/test/native/rdb/unittest/rdb_execute_rd_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_execute_rd_test.cpp @@ -13,7 +13,6 @@ limitations under the License. */ #include -#include #include #include "common.h" @@ -45,6 +44,10 @@ const std::string RdbExecuteRdTest::databaseName = RDB_TEST_PATH + "execute_test const std::string RdbExecuteRdTest::restoreDatabaseName = RDB_TEST_PATH + "execute_test_restore.db"; const std::string RdbExecuteRdTest::backupDatabaseName = RDB_TEST_PATH + "execute_test_backup.db"; std::shared_ptr RdbExecuteRdTest::store = nullptr; +const bool IS_TESTING_PERFORMANCE = false; +const int BATCH_TOTAL_SIZE = IS_TESTING_PERFORMANCE ? 12000 : 120; +const int BATCH_SIZE = IS_TESTING_PERFORMANCE ? 100 : 10; +const int MAX_VARIABLE_NUM = 32766; class ExecuteTestOpenRdCallback : public RdbOpenCallback { public: @@ -80,8 +83,6 @@ void RdbExecuteRdTest::SetUp(void) RdbStoreConfig config(RdbExecuteRdTest::databaseName); config.SetIsVector(true); config.SetEncryptStatus(GetParam()); - int num = 300; - config.SetNcandidates(num); ExecuteTestOpenRdCallback helper; RdbExecuteRdTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); EXPECT_NE(RdbExecuteRdTest::store, nullptr); @@ -94,11 +95,6 @@ void RdbExecuteRdTest::TearDown(void) RdbHelper::DeleteRdbStore(RdbExecuteRdTest::databaseName); } -// 随机数生成器 -std::random_device g_rd; // 用于获取随机种子 -std::mt19937 g_gen(g_rd()); // 以随机设备作为种子的Mersenne Twister生成器 -std::uniform_real_distribution<> dis(-1.0, 1.0); // 定义一个均匀分布的实数范围 - /** @tc.name: RdbStore_Execute_001 @tc.desc: test RdbStore Execute in vector mode @@ -262,7 +258,7 @@ HWTEST_P(RdbExecuteRdTest, RdbStore_Execute_006, TestSize.Level1) std::string dbPath = "/data/test/execute_test1.db"; std::string configStr = "{\"pageSize\":8, \"crcCheckEnable\":0, \"redoFlushByTrx\":1, \"bufferPoolSize\":10240," - "\"sharedModeEnable\":1, \"metaInfoBak\":1, \"maxConnNum\":500 }"; + "\"sharedModeEnable\":1, \"metaInfoBak\":1, \"maxConnNum\":500, \"defaultIsolationLevel\":2 }"; GRD_DB *db2 = nullptr; GRD_DB *db4 = nullptr; @@ -935,43 +931,65 @@ HWTEST_P(RdbExecuteRdTest, RdbStore_Execute_018, TestSize.Level1) } /** - * @tc.name: RdbStore_Execute_019 - * @tc.desc: test RdbStore Execute in vector mode - * @tc.type: FUNC - */ +@tc.name: RdbStore_Execute_019 +@tc.desc: test RdbStore Execute in vector mode, empty string bind case. +@tc.type: FUNC +*/ HWTEST_P(RdbExecuteRdTest, RdbStore_Execute_019, TestSize.Level1) { + std::string sqlCreateTable + = "CREATE TABLE IF NOT EXISTS testEmptyString (id INTEGER PRIMARY KEY, name text, repr floatvector(8));"; + std::string sqlInsert = "INSERT INTO testEmptyString VALUES(?, ?, ?);"; + std::string sqlQuery = "SELECT id FROM testEmptyString"; std::shared_ptr &store = RdbExecuteRdTest::store; - const char *sqlCreateTable = "CREATE TABLE vecTable(inode int primary key, embedding floatvector(4));"; - auto res = store->Execute(sqlCreateTable); - EXPECT_EQ(E_OK, res.first); + std::vector floatVector = { 1.2, 0.3, 3.2, 1.6, 2.5, 3.1, 0.8, 0.4 }; + std::vector bindArgs = std::vector{ ValueObject(1), ValueObject(""), ValueObject(floatVector)}; - const char *sqlCreateIndex = "CREATE INDEX diskann_cos_idx ON vecTable USING GSDISKANN(embedding COSINE);"; - res = store->Execute(sqlCreateIndex); - EXPECT_EQ(E_OK, res.first); + EXPECT_EQ(store->Execute(sqlCreateTable).first, E_OK); + EXPECT_EQ(store->Execute(sqlInsert, bindArgs).first, E_OK); - std::string sqlInsert = "INSERT INTO vecTable VALUES(1, '[1,2,-3,4]'), (2, '[2,2,-3,4]'), (3, '[3,2,3,4]'), (4, " - "'[4,2,3,4]'), (5, '[5,2,-3,4]')"; - for (int i = 6; i <= 1000; i++) { - std::string tmpStr = ", (" + std::to_string(i) + ", '[" + std::to_string(dis(g_gen)) + "," + - std::to_string(dis(g_gen)) + "," + std::to_string(dis(g_gen)) + "," + - std::to_string(dis(g_gen)) + "]')"; - sqlInsert.append(tmpStr); - } - sqlInsert.append(";"); - res = store->Execute(sqlInsert); - EXPECT_EQ(E_OK, res.first); + std::shared_ptr resultSet = store->QueryByStep(sqlQuery); + ASSERT_NE(resultSet, nullptr); + int32_t rowCount = 0; + EXPECT_EQ(resultSet->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1); +} - const char *sqlSelect = "SELECT inode, embedding, embedding<=>'[1,1,1,1]' AS score FROM vecTable ORDER BY " - "embedding<=>'[1,1,1,1]' LIMIT 501;"; - std::shared_ptr resultSet = store->QueryByStep(sqlSelect, std::vector()); - EXPECT_NE(resultSet, nullptr); - int count = 0; - resultSet->GetRowCount(count); - EXPECT_EQ(count, 299); - const char *sqlDelete = "DELETE FROM vecTable"; - res = store->Execute(sqlDelete); - EXPECT_EQ(E_OK, res.first); +/** + * @tc.name: RdbStore_Execute_020 + * @tc.desc: Vector database transaction testing. If the SQL execution fails, the transaction is not closed. + * @tc.type: FUNC +*/ +HWTEST_P(RdbExecuteRdTest, RdbStore_Execute_020, TestSize.Level0) +{ + std::shared_ptr &store = RdbExecuteRdTest::store; + std::string sqlCreateTable = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, repr floatvector(8));"; + std::string sqlInsert1 = "INSERT INTO test VALUES(1, '[1.2, 0.3, 3.2, 1.6, 2.5, 3.1, 0.8, 0.4]');"; + std::string sqlInsert2 = "INSERT INTO test VALUES(2, '[1.2, 0.3, 3.2, 1.6, 2.5, 3.1, 0.8, 0.4]');"; + std::string sqlQuery = "SELECT id FROM test order by repr <-> '[1.1, 0.3, 2.2, 6.6, 1.5, 3.1, 0.6, 0.2]' limit 3;"; + + std::pair res = {}; + res = store->Execute(sqlCreateTable, {}, 0); + EXPECT_EQ(res.first, E_OK); + + auto [ret1, transId1] = store->BeginTrans(); + EXPECT_EQ(ret1, E_OK); + EXPECT_GE(transId1, 0); + + res = store->Execute(sqlInsert1, {}, transId1); + EXPECT_EQ(res.first, E_OK); + + auto [ret2, transId2] = store->BeginTrans(); + EXPECT_EQ(ret2, E_OK); + EXPECT_GE(transId2, 0); + + res = store->Execute(sqlInsert2, {}, transId2); + EXPECT_EQ(res.first, E_DATABASE_BUSY); + + EXPECT_EQ(store->Commit(transId2), E_OK); + EXPECT_EQ(store->Commit(transId1), E_OK); + res = store->Execute("DROP TABLE test;", {}, 0); + EXPECT_EQ(res.first, E_OK); } /* * @@ -1050,4 +1068,349 @@ HWTEST_P(RdbExecuteRdTest, Rdb_BackupRestoreTest_001, TestSize.Level2) HWTEST_P(RdbExecuteRdTest, Rdb_IsUsingArkDataTest_001, TestSize.Level2) { EXPECT_EQ(OHOS::NativeRdb::RdbHelper::IsSupportArkDataDb(), true); -} \ No newline at end of file +} + +/** + * @tc.name: RdbStore_BatchInsert_001 + * @tc.desc: test RdbStore BatchInsert in vector mode + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, RdbStore_BatchInsert_001, TestSize.Level1) +{ + std::shared_ptr &store = RdbExecuteRdTest::store; + std::string sqlCreateTable = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, repr floatvector(8));"; + std::string sqlQuery = "SELECT * FROM test order by repr <-> '[1.1, 0.3, 2.2, 6.6, 1.5, 3.1, 0.6, 0.2]' limit 3;"; + + std::pair res = {}; + std::pair resBatch = {}; + res = store->Execute(sqlCreateTable.c_str(), {}, 0); + EXPECT_EQ(res.first, E_OK); + std::vector vec = {1.2, 0.3, 3.2, 1.6, 2.5, 3.1, 0.8, 0.4}; + + int id = 0; + std::cout << "Start BatchInsert" << std::endl; + auto start = std::chrono::high_resolution_clock::now(); + + for (int32_t batch = 0; batch < BATCH_TOTAL_SIZE / BATCH_SIZE; batch++) { + ValuesBuckets rows; + for (int32_t i = 0; i < BATCH_SIZE; i++) { + ValuesBucket row; + row.PutInt("id", id++); + row.Put("repr", vec); + rows.Put(row); + } + resBatch = store->BatchInsert("test", rows); + EXPECT_EQ(resBatch.first, E_OK); + EXPECT_EQ(resBatch.second, BATCH_SIZE); + } + + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration duration = end - start; + std::cout << "Insert Cost Time: " << duration.count() << " seconds" << std::endl; + std::cout << "Ops: " << BATCH_TOTAL_SIZE / (duration.count() * 1000) << " Kops/s" << std::endl; + + std::shared_ptr resultSet = store->QueryByStep(sqlQuery.c_str(), std::vector()); + + int32_t resCnt = 0; + int32_t resId = -1; + while (resultSet->GoToNextRow() == E_OK) { + ValueObject::FloatVector floatVector = {}; + resultSet->GetInt(0, resId); // 0 is the index of primary INTEGER column in select projection + resultSet->GetFloat32Array(1, floatVector); // 1 is the index of vector column in select projection + EXPECT_EQ(resCnt, resId); + EXPECT_EQ(vec.size(), floatVector.size()); + for (size_t i = 0; i < floatVector.size(); i++) { + EXPECT_FLOAT_EQ(vec[i], floatVector[i]); + } + resCnt++; + } + EXPECT_EQ(3, resCnt); // Expect 3 result due to limit 3 + + res = store->Execute("DROP TABLE test;", {}, 0); + EXPECT_EQ(res.first, E_OK); +} + +/** + * @tc.name: RdbStore_BatchInsert_002 + * @tc.desc: test RdbStore BatchInsert performance in vector mode + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, RdbStore_BatchInsert_002, TestSize.Level1) +{ + std::string testStr2k = R"( +{"$type":"root", "width":"1260.000000", "height":"2720.000000", "$resolution":"3.250000", "pageUrl":"pages/AppIndex", +"$attrs":{"enabled":"1", "focusable":"1"}, "$children":[{"$type":"__Common__", "$rect":"[0.00, 0.00], +[1260.00, 2720.00]", "$attrs":{}, "$children":[{"$type":"Navigation", "$rect":"[0.00, 0.00], [1260.00, 2720.00]", +"$attrs":{"id":"mixnavigator", "enabled":"1", "focusable":"1"}, "$children":[{"$type":"NavigationContent", "$rect":" +[0.00, 0.00], [1260.00, 2720.00]", "$attrs":{}, "$children":[{"$type":"NavDestination", "$rect":"[0.00, 0.00], +[1260.00, 2720.00]", "$attrs":{"enabled":"1", "focusable":"1"}, "$children":[{"$type":"NavDestinationContent", +"$rect":"[0.00, 0.00], [1260.00, 2720.00]", "$attrs":{"enabled":"1", "focusable":"1"}, "$children":[{"$type":"Stack", +"$rect":"[0.00, 0.00], [1260.00, 2720.00]", "$attrs":{"enabled":"1", "focusable":"1"}, "$children":[{"$type": +"__Common__", "$rect":"[0.00, 0.00], [1260.00, 2629.00]", "$attrs":{}, "$children":[{"$type":"Stack", "$rect":" +[0.00, 0.00], [1260.00, 2629.00]", "$attrs":{"enabled":"1", "focusable":"1"}, "$children":[{"$type":"Stack", "$rect":" +[0.00, 0.00], [1260.00, 2629.00]", "$attrs":{"id":"0", "enabled":"1", "focusable":"1"}, "$children":[{"$type":"Column", +"$rect":"[0.00, 0.00], [1260.00, 2629.00]", "$attrs":{"id":"1", "enabled":"1", "focusable":"1"}, "$children":[{"$type": +"Tabs", "$rect":"[0.00, 0.00], [1260.00, 2629.00]", "$attrs":{"enabled":"1", "focusable":"1"}, "$children":[{"$type": +"Swiper", "$rect":"[0.00, 0.00], [1260.00, 2460.00]", "$attrs":{"enabled":"1", "focusable":"1"}, "$children":[{"$type": +"TabContent", "$rect":"[0.00, 0.00], [1260.00, 2460.00]", "$attrs":{}, "$children":[{"$type":"Column", "$rect":" +[0.00, 0.00], [1260.00, 2460.00]", "$attrs":{"id":"14", "enabled":"1", "focusable":"1"}, "$children":[{"$type": +"Column", "$rect":"[0.00, 0.00], [1260.00, 2460.00]", "$attrs":{""}, "$children":[{"$attrs":{"id":"540", "enabled":"1", +"focusable":"1"}, "$children":[{"$type":"GridCol", "$children":[{"$type":"Column", "$rect":"[0.00, 2460.00], +[315.00, 2629.00]", "$attrs":{"enabled":"1", "focusable":"0"}, "$children":[{")"; + + std::shared_ptr &store = RdbExecuteRdTest::store; + std::string sqlCreateTable = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, name TEXT);"; + + std::pair res = {}; + std::pair resBatch = {}; + res = store->Execute(sqlCreateTable.c_str(), {}, 0); + EXPECT_EQ(res.first, E_OK); + + int id = 0; + std::cout << "Start BatchInsert" << std::endl; + auto start = std::chrono::high_resolution_clock::now(); + + for (int32_t batch = 0; batch < BATCH_TOTAL_SIZE / BATCH_SIZE; batch++) { + ValuesBuckets rows; + for (int32_t i = 0; i < BATCH_SIZE; i++) { + ValuesBucket row; + row.PutInt("id", id++); + row.PutString("name", testStr2k); + rows.Put(row); + } + resBatch = store->BatchInsert("test", rows); + EXPECT_EQ(resBatch.first, E_OK); + EXPECT_EQ(resBatch.second, BATCH_SIZE); + } + + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration duration = end - start; + std::cout << "Insert Cost Time: " << duration.count() << " seconds" << std::endl; + std::cout << "Ops: " << BATCH_TOTAL_SIZE / (duration.count() * 1000) << " Kops/s" << std::endl; + + res = store->Execute("DROP TABLE test;", {}, 0); + EXPECT_EQ(res.first, E_OK); +} + +/** + * @tc.name: RdbStore_BatchInsert_003 + * @tc.desc: test RdbStore BatchInsert performance in vector mode + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, RdbStore_BatchInsert_003, TestSize.Level1) +{ + std::string testStr2k = R"({"$type":"root"})"; + + std::shared_ptr &store = RdbExecuteRdTest::store; + std::string sqlCreateTable = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, name TEXT);"; + + std::pair res = {}; + std::pair resBatch = {}; + res = store->Execute(sqlCreateTable.c_str(), {}, 0); + EXPECT_EQ(res.first, E_OK); + + int id = 0; + std::cout << "Start BatchInsert" << std::endl; + auto start = std::chrono::high_resolution_clock::now(); + int maxVariableNum = MAX_VARIABLE_NUM / 2; + + for (int32_t batch = 0; batch < 1; batch++) { + ValuesBuckets rows; + for (int32_t i = 0; i < maxVariableNum; i++) { + ValuesBucket row; + row.PutInt("id", id++); + row.PutString("name", testStr2k); + rows.Put(row); + } + resBatch = store->BatchInsert("test", rows); + EXPECT_EQ(resBatch.first, E_OK); + EXPECT_EQ(resBatch.second, maxVariableNum); + } + + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration duration = end - start; + std::cout << "Insert Cost Time: " << duration.count() << " seconds" << std::endl; + std::cout << "Ops: " << maxVariableNum / (duration.count() * 1000) << " Kops/s" << std::endl; + + res = store->Execute("DROP TABLE test;", {}, 0); + EXPECT_EQ(res.first, E_OK); +} + +constexpr uint16_t CLUSTER_INDEX_DIM = 256; + +int32_t ClusterAlgoByEvenNumber(ClstAlgoParaT *para) +{ + int *result = para->clusterResult; + const int specialId = 985; + for (uint32_t i = 0; i < para->newFeaturesNum; i++) { + result[i] = specialId; + } + std::cout << "ClusterAlgoByEvenNumber exec!" << std::endl; + return 0; +} + +/** + * @tc.name: RdbStore_RegisterAlgo_001 + * @tc.desc: test RdbStore RegisterAlgo in vector mode + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, RdbStore_RegisterAlgo_001, TestSize.Level1) +{ + std::shared_ptr &store = RdbExecuteRdTest::store; + std::string algoName = "clst_algo_v0"; + int ret = store->RegisterAlgo(algoName, nullptr); + EXPECT_EQ(ret, E_NO_MORE_ROWS); + ret = store->RegisterAlgo(algoName, ClusterAlgoByEvenNumber); + EXPECT_EQ(ret, E_OK); + + std::string sqlCreateTable = + "CREATE TABLE test(id int primary key, repr floatvector(" + std::to_string(CLUSTER_INDEX_DIM) + "));"; + std::string sqlCreateIndex = + "CREATE INDEX ivfcluster_l2_idx ON test USING IVFCLUSTER(repr L2) with (CLUSTER_ALGO='clst_algo_v0');"; + std::string sqlSelect = "SELECT id, repr, CLUSTER_ID(repr) from test;"; + + std::pair res = {}; + res = store->Execute(sqlCreateTable.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + + res = store->Execute(sqlCreateIndex.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + + for (uint16_t i = 0; i < EXPEC_INSERT_CNT_FOR; i++) { + std::string sqlInsert = "INSERT INTO test VALUES(1000000" + std::to_string(i) + ", '" + + GetRandVector(MAX_INT_PART, CLUSTER_INDEX_DIM) + "');"; + res = store->Execute(sqlInsert.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + } + + ret = store->RegisterAlgo(algoName, nullptr); + EXPECT_EQ(ret, E_OK); + + res = store->Execute("DROP TABLE test;", {}, 0); + EXPECT_EQ(res.first, E_OK); +} + +/** + * @tc.name: RdbStore_RegisterAlgo_002 + * @tc.desc: test RdbStore RegisterAlgo in vector mode + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, RdbStore_RegisterAlgo_002, TestSize.Level1) +{ + std::shared_ptr &store = RdbExecuteRdTest::store; + std::string algoName = "clst_algo_v0"; + int ret = store->RegisterAlgo(algoName, ClusterAlgoByEvenNumber); + EXPECT_EQ(ret, E_OK); + + std::string sqlCreateTable = + "CREATE TABLE test(id int primary key, repr floatvector(" + std::to_string(CLUSTER_INDEX_DIM) + "));"; + std::string sqlCreateIndex = + "CREATE INDEX ivfcluster_l2_idx ON test USING IVFCLUSTER(repr L2) with (CLUSTER_ALGO='clst_algo_v0');"; + std::string sqlSelect = "SELECT id, repr, CLUSTER_ID(repr) from test;"; + + std::pair res = {}; + res = store->Execute(sqlCreateTable.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + + res = store->Execute(sqlCreateIndex.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + + for (uint16_t i = 0; i < EXPEC_INSERT_CNT_FOR; i++) { + std::string sqlInsert = "INSERT INTO test VALUES(1000000" + std::to_string(i) + ", '" + + GetRandVector(MAX_INT_PART, CLUSTER_INDEX_DIM) + "');"; + res = store->Execute(sqlInsert.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + } + + std::string sqlRunCluster = "PRAGMA CLUSTER_RUN test.ivfcluster_l2_idx;"; + res = store->Execute(sqlRunCluster.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + + std::shared_ptr resultSet = store->QueryByStep(sqlSelect.c_str(), std::vector()); + EXPECT_NE(resultSet, nullptr); + + int32_t resCnt = 0; + while (resultSet->GoToNextRow() == E_OK) { + resCnt++; + } + EXPECT_EQ(EXPEC_INSERT_CNT_FOR, resCnt); + + res = store->Execute("DROP TABLE test;", {}, 0); + EXPECT_EQ(res.first, E_OK); +} + +/** + * @tc.name: RdbStore_RegisterAlgo_003 + * @tc.desc: test sqlite don't support RegisterAlgo + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, RdbStore_RegisterAlgo_003, TestSize.Level1) +{ + RdbExecuteRdTest::store = nullptr; + RdbHelper::DeleteRdbStore(RdbExecuteRdTest::databaseName); + + int errCode = E_OK; + RdbHelper::DeleteRdbStore(RdbExecuteRdTest::databaseName); + RdbStoreConfig config(RdbExecuteRdTest::databaseName); + config.SetIsVector(false); + config.SetEncryptStatus(GetParam()); + ExecuteTestOpenRdCallback helper; + RdbExecuteRdTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(RdbExecuteRdTest::store, nullptr); + EXPECT_EQ(errCode, E_OK); + + std::shared_ptr &store = RdbExecuteRdTest::store; + + std::string sqlCreateTable = + "CREATE TABLE test(id int primary key, repr int);"; + + std::pair res = {}; + res = store->Execute(sqlCreateTable.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + + std::string algoName = "clst_algo_v0"; + int ret = store->RegisterAlgo(algoName, ClusterAlgoByEvenNumber); + EXPECT_EQ(ret, E_NOT_SUPPORT); + + res = store->Execute("DROP TABLE test;", {}, 0); + EXPECT_EQ(res.first, E_OK); +} + +/** + * @tc.name: RdbStore_RegisterAlgo_004 + * @tc.desc: test don't support RegisterAlgo + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, RdbStore_RegisterAlgo_004, TestSize.Level1) +{ + RdbExecuteRdTest::store = nullptr; + RdbHelper::DeleteRdbStore(RdbExecuteRdTest::databaseName); + + int errCode = E_OK; + RdbStoreConfig config(RdbExecuteRdTest::databaseName); + config.SetIsVector(true); + config.SetReadOnly(true); + config.SetEncryptStatus(GetParam()); + ExecuteTestOpenRdCallback helper; + RdbExecuteRdTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(RdbExecuteRdTest::store, nullptr); + EXPECT_EQ(errCode, E_OK); + + std::string algoName = "clst_algo_v0"; + int ret = RdbExecuteRdTest::store->RegisterAlgo(algoName, ClusterAlgoByEvenNumber); + EXPECT_EQ(ret, E_NOT_SUPPORT); +} + +/** + * @tc.name: RdbStore_RegisterAlgo_005 + * @tc.desc: test RegisterAlgo after deleteRdbStore + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, RdbStore_RegisterAlgo_005, TestSize.Level1) +{ + RdbHelper::DeleteRdbStore(RdbExecuteRdTest::databaseName); + std::shared_ptr &store = RdbExecuteRdTest::store; + std::string algoName = "clst_algo_v0"; + int ret = store->RegisterAlgo(algoName, ClusterAlgoByEvenNumber); + EXPECT_EQ(ret, E_ALREADY_CLOSED); +} diff --git a/relational_store/test/native/rdb/unittest/rdb_execute_test.cpp b/relational_store/test/native/rdb/unittest/rdb_execute_test.cpp index bf7693853384b0712842dea91efec97917a688a5..3ec06694628ac5a6394794a86c607bef80f4d1c5 100644 --- a/relational_store/test/native/rdb/unittest/rdb_execute_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_execute_test.cpp @@ -21,6 +21,7 @@ #include "rdb_errno.h" #include "rdb_helper.h" #include "rdb_open_callback.h" +#include "value_object.h" using namespace testing::ext; using namespace OHOS::NativeRdb; @@ -95,12 +96,14 @@ void RdbExecuteTest::TearDownTestCase(void) void RdbExecuteTest::SetUp(void) { store_ = *GetParam(); + ASSERT_NE(store_, nullptr); store_->ExecuteSql(CREATE_TABLE_TEST); } void RdbExecuteTest::TearDown(void) { store_ = *GetParam(); + ASSERT_NE(store_, nullptr); store_->ExecuteSql("DROP TABLE test"); } @@ -111,8 +114,6 @@ void RdbExecuteTest::TearDown(void) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_001, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; @@ -121,7 +122,7 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_001, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); + int ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -131,7 +132,7 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_001, TestSize.Level1) values.PutInt("age", 19); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->Insert(id, "test", values); + ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -141,27 +142,27 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_001, TestSize.Level1) values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->Insert(id, "test", values); + ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); int64_t count; - ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); + ret = store_->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(count, 3); - ret = store->ExecuteSql("DELETE FROM test WHERE age = ? OR age = ?", + ret = store_->ExecuteSql("DELETE FROM test WHERE age = ? OR age = ?", std::vector{ ValueObject(std::string("18")), ValueObject(std ::string("20")) }); EXPECT_EQ(ret, E_OK); - ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test where age = 19"); + ret = store_->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test where age = 19"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(count, 1); - ret = store->ExecuteSql("DELETE FROM test WHERE age = 19"); + ret = store_->ExecuteSql("DELETE FROM test WHERE age = 19"); EXPECT_EQ(ret, E_OK); - ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); + ret = store_->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(count, 0); } @@ -173,48 +174,46 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_001, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_002, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[2])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[2])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); int64_t count; - ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test", std::vector()); + ret = store_->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test", std::vector()); EXPECT_EQ(ret, E_OK); EXPECT_EQ(count, 3); - ret = store->ExecuteSql("DELETE FROM test WHERE age = ? OR age = ?", + ret = store_->ExecuteSql("DELETE FROM test WHERE age = ? OR age = ?", std::vector{ ValueObject(std::string("18")), ValueObject(std ::string("20")) }); EXPECT_EQ(ret, E_OK); - ret = store->ExecuteAndGetLong( + ret = store_->ExecuteAndGetLong( count, "SELECT COUNT(*) FROM test where age = ?", std::vector{ ValueObject(std::string("19")) }); EXPECT_EQ(ret, E_OK); EXPECT_EQ(count, 1); - ret = store->ExecuteSql("DELETE FROM test WHERE age = 19"); + ret = store_->ExecuteSql("DELETE FROM test WHERE age = 19"); EXPECT_EQ(ret, E_OK); - ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test", std::vector()); + ret = store_->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test", std::vector()); EXPECT_EQ(ret, E_OK); EXPECT_EQ(count, 0); - ret = store->ExecuteSql("DROP TABLE IF EXISTS test"); + ret = store_->ExecuteSql("DROP TABLE IF EXISTS test"); EXPECT_EQ(ret, E_OK); - ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); + ret = store_->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); EXPECT_EQ(ret, E_SQLITE_ERROR); } @@ -225,20 +224,18 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_002, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_003, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int64_t pageSize; - int ret = store->ExecuteAndGetLong(pageSize, "PRAGMA page_size"); + int ret = store_->ExecuteAndGetLong(pageSize, "PRAGMA page_size"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(pageSize, 4096); int64_t journalSize; - ret = store->ExecuteAndGetLong(journalSize, "PRAGMA journal_size_limit"); + ret = store_->ExecuteAndGetLong(journalSize, "PRAGMA journal_size_limit"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(journalSize, 1048576); std::string journalMode; - ret = store->ExecuteAndGetString(journalMode, "PRAGMA journal_mode"); + ret = store_->ExecuteAndGetString(journalMode, "PRAGMA journal_mode"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(journalMode, GetParam()->mode); } @@ -253,7 +250,7 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_004, TestSize.Level4) std::shared_ptr store = *GetParam(); std::string outValue; - int ret = store->ExecuteAndGetString(outValue, "BEGIN;"); + int ret = store_->ExecuteAndGetString(outValue, "BEGIN;"); EXPECT_NE(E_OK, ret); } @@ -265,9 +262,8 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_004, TestSize.Level4) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_005, TestSize.Level4) { - std::shared_ptr store = *GetParam(); int64_t outValue; - int ret = store->ExecuteForLastInsertedRowId(outValue, "", {}); + int ret = store_->ExecuteForLastInsertedRowId(outValue, "", {}); EXPECT_NE(E_OK, ret); } @@ -278,9 +274,8 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_005, TestSize.Level4) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_006, TestSize.Level4) { - std::shared_ptr store = *GetParam(); int64_t outValue; - int ret = store->ExecuteForChangedRowCount(outValue, "", {}); + int ret = store_->ExecuteForChangedRowCount(outValue, "", {}); EXPECT_NE(E_OK, ret); } @@ -291,9 +286,7 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_006, TestSize.Level4) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_007, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - - auto [ret, outValue] = store->Execute("PRAGMA integrity_check"); + auto [ret, outValue] = store_->Execute("PRAGMA integrity_check"); EXPECT_EQ(E_OK, ret); EXPECT_EQ(ValueObjectType::TYPE_STRING, outValue.GetType()); @@ -309,9 +302,7 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_007, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_008, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - - auto [ret, outValue] = store->Execute("PRAGMA quick_check"); + auto [ret, outValue] = store_->Execute("PRAGMA quick_check"); EXPECT_EQ(E_OK, ret); EXPECT_EQ(ValueObjectType::TYPE_STRING, outValue.GetType()); @@ -327,11 +318,9 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_008, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_009, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - // set user_version as 5 - store->SetVersion(5); - auto [ret, outValue] = store->Execute("PRAGMA user_version"); + store_->SetVersion(5); + auto [ret, outValue] = store_->Execute("PRAGMA user_version"); EXPECT_EQ(E_OK, ret); EXPECT_EQ(ValueObjectType::TYPE_INT, outValue.GetType()); @@ -340,7 +329,7 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_009, TestSize.Level1) EXPECT_EQ(5, outputResult); // set user_version as 0 - store->SetVersion(0); + store_->SetVersion(0); } /** @@ -350,10 +339,11 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_009, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0010, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - - auto [ret, outValue] = store->Execute("SELECT * FROM test"); + auto [ret, outValue] = store_->Execute("SELECT * FROM test"); EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, ret); + + auto [code, result] = store_->ExecuteExt("SELECT * FROM test"); + EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, code); } /** @@ -363,11 +353,9 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0010, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0011, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - std::vector args = { ValueObject(std::string("tt")), ValueObject(int(28)), ValueObject(double(50000.0)) }; - auto [ret, outValue] = store->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?);", args); + auto [ret, outValue] = store_->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?);", args); EXPECT_EQ(E_OK, ret); EXPECT_EQ(ValueObjectType::TYPE_INT, outValue.GetType()); @@ -384,12 +372,10 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0011, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0012, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - std::vector args = { ValueObject(std::string("tt")), ValueObject(int(28)), ValueObject(double(50000.0)), ValueObject(std::string("ttt")), ValueObject(int(58)), ValueObject(double(500080.0)) }; - auto [ret, outValue] = store->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?)", args); + auto [ret, outValue] = store_->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?)", args); EXPECT_EQ(E_OK, ret); EXPECT_EQ(ValueObjectType::TYPE_INT, outValue.GetType()); @@ -407,12 +393,10 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0012, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0013, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - std::vector args = { ValueObject(std::string("tt")), ValueObject(int(28)), ValueObject(double(50000.0)), ValueObject(std::string("ttt")), ValueObject(int(58)), ValueObject(double(500080.0)) }; - auto [ret1, outValue1] = store->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?)", args); + auto [ret1, outValue1] = store_->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?)", args); EXPECT_EQ(E_OK, ret1); EXPECT_EQ(ValueObjectType::TYPE_INT, outValue1.GetType()); @@ -421,7 +405,7 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0013, TestSize.Level1) // 2 represent that the last data is inserted in the second row EXPECT_EQ(2, outputResult); - auto [ret2, outValue2] = store->Execute("UPDATE test SET name='dd' WHERE id = 2"); + auto [ret2, outValue2] = store_->Execute("UPDATE test SET name='dd' WHERE id = 2"); EXPECT_EQ(E_OK, ret2); EXPECT_EQ(ValueObjectType::TYPE_INT, outValue2.GetType()); @@ -437,12 +421,10 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0013, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0014, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - std::vector args = { ValueObject(std::string("tt")), ValueObject(int(28)), ValueObject(double(50000.0)), ValueObject(std::string("ttt")), ValueObject(int(82)), ValueObject(double(500080.0)) }; - auto [ret1, outValue1] = store->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?)", args); + auto [ret1, outValue1] = store_->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?)", args); EXPECT_EQ(E_OK, ret1); EXPECT_EQ(ValueObjectType::TYPE_INT, outValue1.GetType()); @@ -451,7 +433,7 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0014, TestSize.Level1) // 2 represent that the last data is inserted in the second row EXPECT_EQ(2, outputResult); - auto [ret2, outValue2] = store->Execute("DELETE FROM test"); + auto [ret2, outValue2] = store_->Execute("DELETE FROM test"); EXPECT_EQ(E_OK, ret2); EXPECT_EQ(ValueObjectType::TYPE_INT, outValue2.GetType()); @@ -467,22 +449,23 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0014, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0015, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - - auto [ret1, outValue1] = store->Execute("ATTACH DATABASE 'execute_attach_test.db' AS 'attach.db'"); + auto [ret1, outValue1] = store_->Execute("ATTACH DATABASE 'execute_attach_test.db' AS 'attach.db'"); EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, ret1); - auto [ret2, outValue2] = store->Execute("DETACH DATABASE 'attach.db'"); + auto [ret2, outValue2] = store_->Execute("DETACH DATABASE 'attach.db'"); EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, ret2); - auto [ret3, outValue3] = store->Execute("BEGIN TRANSACTION"); + auto [ret3, outValue3] = store_->Execute("BEGIN TRANSACTION"); EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, ret3); - auto [ret4, outValue4] = store->Execute("COMMIT"); + auto [ret4, outValue4] = store_->Execute("COMMIT"); EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, ret4); - auto [ret5, outValue5] = store->Execute("ROLLBACK"); + auto [ret5, outValue5] = store_->Execute("ROLLBACK"); EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, ret5); + + auto [ret6, outValue6] = store_->ExecuteExt("ROLLBACK"); + EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, ret6); } /** @@ -492,7 +475,6 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0015, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0016, TestSize.Level1) { - std::shared_ptr store = *GetParam(); int64_t intOutValue; constexpr const char *CREATE_TABLE_TEST2 = "CREATE TABLE IF NOT EXISTS test2 " @@ -503,11 +485,11 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0016, TestSize.Level1) constexpr const char *TEST_TABLE_IS_EXIST = "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='test2'"; - auto [ret1, outValue1] = store->Execute(CREATE_TABLE_TEST2); + auto [ret1, outValue1] = store_->Execute(CREATE_TABLE_TEST2); EXPECT_EQ(E_OK, ret1); EXPECT_EQ(ValueObjectType::TYPE_NULL, outValue1.GetType()); - std::shared_ptr resultSet = store->QuerySql(TEST_TABLE_IS_EXIST); + std::shared_ptr resultSet = store_->QuerySql(TEST_TABLE_IS_EXIST); EXPECT_NE(nullptr, resultSet); resultSet->GoToFirstRow(); // 0 represent that get count of table test in the first row @@ -516,11 +498,14 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0016, TestSize.Level1) EXPECT_EQ(1, intOutValue); resultSet->Close(); - auto [ret2, outValue2] = store->Execute(DROP_TABLE_TEST2); + auto [ret2, outValue2] = store_->ExecuteExt(DROP_TABLE_TEST2); EXPECT_EQ(E_OK, ret2); - EXPECT_EQ(ValueObjectType::TYPE_NULL, outValue2.GetType()); + EXPECT_EQ(0, outValue2.changed); + int rowCount = -1; + outValue2.results->GetRowCount(rowCount); + EXPECT_EQ(0, rowCount); - resultSet = store->QuerySql(TEST_TABLE_IS_EXIST); + resultSet = store_->QuerySql(TEST_TABLE_IS_EXIST); EXPECT_NE(nullptr, resultSet); resultSet->GoToFirstRow(); // 0 represent that get count of table test in the first column @@ -537,7 +522,6 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0016, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0017, TestSize.Level1) { - std::shared_ptr store = *GetParam(); int64_t intOutValue; int intOutResultSet; @@ -547,24 +531,24 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0017, TestSize.Level1) "blobType BLOB)"; constexpr const char *DROP_TABLE_TEST2 = "DROP TABLE test2"; - auto [ret1, outValue1] = store->Execute(CREATE_TABLE_TEST2); + auto [ret1, outValue1] = store_->Execute(CREATE_TABLE_TEST2); EXPECT_EQ(E_OK, ret1); std::vector args = { ValueObject("tt"), ValueObject(28), ValueObject(50000) }; - auto [ret2, outValue2] = store->Execute("INSERT INTO test2(name, age, salary) VALUES (?, ?, ?)", args); + auto [ret2, outValue2] = store_->Execute("INSERT INTO test2(name, age, salary) VALUES (?, ?, ?)", args); EXPECT_EQ(E_OK, ret2); outValue2.GetLong(intOutValue); // 1 represent that the last data is inserted in the first row EXPECT_EQ(1, intOutValue); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test2"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test2"); EXPECT_NE(nullptr, resultSet); EXPECT_EQ(E_OK, resultSet->GetRowCount(intOutResultSet)); // 1 represent that the row number of resultSet EXPECT_EQ(1, intOutResultSet); resultSet->Close(); - auto [ret3, outValue3] = store->Execute(DROP_TABLE_TEST2); + auto [ret3, outValue3] = store_->Execute(DROP_TABLE_TEST2); EXPECT_EQ(E_OK, ret3); } @@ -575,10 +559,9 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0017, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0018, TestSize.Level1) { - std::shared_ptr store = *GetParam(); ValueObject outValue; - auto [ret1, outValue1] = store->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?)"); + auto [ret1, outValue1] = store_->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?)"); EXPECT_NE(E_OK, ret1); } @@ -589,15 +572,13 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0018, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0019, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - // set user_version as 5 - auto [ret, outValue] = store->Execute("PRAGMA user_version=5"); + auto [ret, outValue] = store_->Execute("PRAGMA user_version=5"); EXPECT_EQ(E_OK, ret); EXPECT_EQ(ValueObjectType::TYPE_NULL, outValue.GetType()); // set user_version as 0 - std::tie(ret, outValue) = store->Execute("PRAGMA user_version=0"); + std::tie(ret, outValue) = store_->Execute("PRAGMA user_version=0"); EXPECT_EQ(E_OK, ret); EXPECT_EQ(ValueObjectType::TYPE_NULL, outValue.GetType()); } @@ -609,12 +590,275 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0019, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0020, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - - auto [ret, outValue] = store->Execute("PRAGMA table_info(test)"); + auto [ret, outValue] = store_->Execute("PRAGMA table_info(test)"); EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, ret); } +/** + * @tc.name: RdbStore_Execute_0021 + * @tc.desc: Normal testCase for Execute insert, update and delete 2 rows with returning + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteTest, RdbStore_Execute_0021, TestSize.Level1) +{ + std::vector args = { "tt", 28, 50000.0, "ttt", 58, 500080.0 }; + auto [status, result] = + store_->ExecuteExt("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?) returning name", args); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 2); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 2); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "tt"); + ASSERT_EQ(result.results->GoToNextRow(), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "ttt"); + + std::tie(status, result) = + store_->ExecuteExt("update test set name = ? where name = ? returning name", {"update", "tt"}); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "update"); + + std::tie(status, result) = store_->ExecuteExt("delete from test returning name"); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 2); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 2); + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "update"); + ASSERT_EQ(result.results->GoToNextRow(), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "ttt"); +} + +/** + * @tc.name: RdbStore_Execute_0022 + * @tc.desc: Normal testCase for Execute insert, update and delete over limit with returning + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteTest, RdbStore_Execute_0022, TestSize.Level1) +{ + std::vector args = { "0", 0 }; + std::string sql = "INSERT INTO test(name, age) VALUES (?, ?)"; + for (int32_t i = 1; i < 1025; i++) { + sql.append(", (?, ?)"); + args.push_back(std::to_string(i)); + args.push_back(i); + } + auto [status, result] = store_->ExecuteExt(sql + " returning name", args); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1024); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "0"); + ASSERT_EQ(result.results->GoToRow(1000), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "1000"); + + std::tie(status, result) = store_->ExecuteExt("update test set name = ? returning name", { "update" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1024); + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "update"); + + + std::tie(status, result) = store_->ExecuteExt("delete from test returning name"); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1024); + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "update"); +} + +/** + * @tc.name: RdbStore_Execute_0023 + * @tc.desc: normal testCase for Execute insert, update and delete 0 rows with returning + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteTest, RdbStore_Execute_0023, TestSize.Level1) +{ + std::vector args = { 1, "tt", 28, 50000.0 }; + auto [status, result] = + store_->ExecuteExt("INSERT INTO test(id, name, age, salary) VALUES (?, ?, ?, ?) returning id", args); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("id", columnIndex), E_OK); + int64_t value; + ASSERT_EQ(result.results->GetLong(columnIndex, value), E_OK); + EXPECT_EQ(value, 1); + + std::tie(status, result) = + store_->ExecuteExt("INSERT INTO test(id, name, age, salary) VALUES (?, ?, ?, ?) returning id", args); + EXPECT_EQ(status, E_SQLITE_CONSTRAINT); + EXPECT_EQ(result.changed, 0); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); + + std::tie(status, result) = + store_->ExecuteExt("update test set name = ? where name = ? returning name", { "update", "noExist" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); + + std::tie(status, result) = store_->ExecuteExt("delete from test where name = ? returning name", { "noExist" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); +} + +/** + * @tc.name: RdbStore_Execute_0024 + * @tc.desc: abnormal testCase for Execute insert, update and delete with returning field not exist + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteTest, RdbStore_Execute_0024, TestSize.Level1) +{ + std::vector args = { 1, "tt", 28, 50000.0 }; + auto [status, result] = + store_->ExecuteExt("INSERT INTO test(id, name, age, salary) VALUES (?, ?, ?, ?) returning noExist", args); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + ASSERT_EQ(result.results, nullptr); + + std::tie(status, result) = + store_->ExecuteExt("update test set name = ? where name = ? returning noExist", { "update", "noExist" }); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + ASSERT_EQ(result.results, nullptr); + + std::tie(status, result) = store_->ExecuteExt("delete from test where name = ? returning noExist", { "noExist" }); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + ASSERT_EQ(result.results, nullptr); +} + +/** + * @tc.name: RdbStore_Execute_0025 + * @tc.desc: normal test. batch insert into virtual table with returning + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbExecuteTest, RdbStore_Execute_0025, TestSize.Level1) +{ + store_->Execute("CREATE VIRTUAL TABLE IF NOT EXISTS articles USING fts5(title, content);"); + + std::vector args = { "title", "content" }; + auto [status, result] = + store_->ExecuteExt("INSERT INTO articles(title, content) VALUES (?, ?) returning title", args); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("title", columnIndex), E_OK); + std::string value; + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "title"); + + std::vector args2 = { "title2", "title" }; + std::tie(status, result) = + store_->ExecuteExt("UPDATE articles set title = ? where title = ? returning title", args2); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + ASSERT_EQ(result.results, nullptr); + + // DELETE RETURNING is not available on virtual tables + std::tie(status, result) = store_->ExecuteExt("DELETE FROM articles where title = ? returning title", { "title" }); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + ASSERT_EQ(result.results, nullptr); + store_->Execute("Drop TABLE articles"); +} + +/** + * @tc.name: RdbStore_Execute_0026 + * @tc.desc: normal test. create trigger before update, delete data in trigger, then update data + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbExecuteTest, RdbStore_Execute_0026, TestSize.Level1) +{ + auto [code, result1] = store_->Execute( + "CREATE TRIGGER before_update BEFORE UPDATE ON test" + " BEGIN DELETE FROM test WHERE name = 'wang'; END"); + + EXPECT_EQ(code, E_OK); + + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 200); + row.Put("name", "wang"); + rows.Put(std::move(row)); + row.Put("id", 201); + row.Put("name", "zhang"); + rows.Put(std::move(row)); + + auto [insertStatus, insertResult] = + store_->BatchInsert("test", rows, { "name" }, NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(insertStatus, E_OK); + EXPECT_EQ(insertResult.changed, 2); + + std::vector args2 = { "liu", "zhang" }; + auto [status, res] = + store_->ExecuteExt("UPDATE test set name = ? where name = ? returning name", args2); + + EXPECT_EQ(status, E_OK); + EXPECT_EQ(res.changed, 1); + int rowCount = -1; + ASSERT_EQ(res.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(res.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + ASSERT_EQ(res.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "liu"); + + // Check the trigger effect + auto resultSet = store_->QuerySql("select name from test where id = 200"); + + rowCount = -1; + resultSet->GetRowCount(rowCount); + ASSERT_EQ(rowCount, 0); + store_->Execute("DROP TRIGGER IF EXISTS before_update"); +} + INSTANTIATE_TEST_SUITE_P(ExecuteTest, RdbExecuteTest, testing::Values(&g_store, &g_memDb)); } // namespace OHOS::RdbExecuteTest \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_helper_test.cpp b/relational_store/test/native/rdb/unittest/rdb_helper_test.cpp index 663d8b3320da61682dbfb765e5663f057be1aec7..988c376baa594f0b6891ffb21b090afc29f4507e 100644 --- a/relational_store/test/native/rdb/unittest/rdb_helper_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_helper_test.cpp @@ -428,6 +428,9 @@ HWTEST_F(RdbHelperTest, DeleteDatabase_014, TestSize.Level0) auto [ret2, outValue] = store->Execute(RdbHelperTestOpenCallback::CREATE_TABLE_TEST); EXPECT_EQ(ret2, E_ALREADY_CLOSED); + + auto [code, result] = store->ExecuteExt(RdbHelperTestOpenCallback::CREATE_TABLE_TEST); + EXPECT_EQ(code, E_ALREADY_CLOSED); } /** @@ -614,6 +617,29 @@ HWTEST_F(RdbHelperTest, DeleteDatabase_023, TestSize.Level0) ASSERT_EQ(result.first, E_ALREADY_CLOSED); } +/** + * @tc.name: DeleteDatabase_024 + * @tc.desc: BatchInsert after deleteRdbStore + * @tc.type: FUNC + */ +HWTEST_F(RdbHelperTest, DeleteDatabase_024, TestSize.Level0) +{ + InitDb(); + ValuesBuckets rows; + + int ret = RdbHelper::DeleteRdbStore(RdbHelperTest::rdbStorePath); + EXPECT_EQ(ret, E_OK); + + for (int32_t i = 0; i < 10; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto result = store->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_NONE); + EXPECT_EQ(result.first, E_ALREADY_CLOSED); +} + /** * @tc.name: getrdbstore_001 * @tc.desc: get db file with a invalid path @@ -804,4 +830,4 @@ HWTEST_F(RdbHelperTest, GetDatabase_007, TestSize.Level0) // Ensure that two databases not equal EXPECT_NE(rdbStore1, rdbStore2); -} \ No newline at end of file +} diff --git a/relational_store/test/native/rdb/unittest/rdb_insert_test.cpp b/relational_store/test/native/rdb/unittest/rdb_insert_test.cpp index 52b9eb3e7b80ffd9d123b01ffd943b1fbcda3e62..4ea6ed3b6fe3e12c01940eac533db89071da71af 100644 --- a/relational_store/test/native/rdb/unittest/rdb_insert_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_insert_test.cpp @@ -22,6 +22,8 @@ #include "rdb_errno.h" #include "rdb_helper.h" #include "rdb_open_callback.h" +#include "result_set.h" +#include "values_buckets.h" using namespace testing::ext; using namespace OHOS::NativeRdb; @@ -75,6 +77,24 @@ int InsertTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVe return E_OK; } +std::vector GetColumnValues(std::shared_ptr resultSet, const std::string &filed) +{ + std::vector res; + if (resultSet->GoToFirstRow() != E_OK) { + return res; + } + int32_t colIndex = -1; + if (resultSet->GetColumnIndex(filed, colIndex) != E_OK) { + return res; + } + do { + ValueObject value; + EXPECT_EQ(resultSet->Get(colIndex, value), E_OK); + res.push_back(value); + } while (resultSet->GoToNextRow() == E_OK); + return res; +} + void RdbStoreInsertTest::SetUpTestCase(void) { int errCode = E_OK; @@ -100,6 +120,7 @@ void RdbStoreInsertTest::TearDownTestCase(void) void RdbStoreInsertTest::SetUp(void) { store_ = *GetParam(); + ASSERT_NE(store_, nullptr); store_->ExecuteSql("DELETE FROM test"); } @@ -112,10 +133,8 @@ void RdbStoreInsertTest::TearDown(void) * @tc.desc: test RdbStore insert * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_001, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_001, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; @@ -124,7 +143,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_001, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); + int ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -134,7 +153,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_001, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Insert(id, "test", values); + ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -144,18 +163,18 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_001, TestSize.Level1) values.PutInt("age", 20L); values.PutDouble("salary", 100.5f); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Insert(id, "test", values); + ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); - RdbStoreInsertTest::CheckResultSet(store); + RdbStoreInsertTest::CheckResultSet(store_); } void RdbStoreInsertTest::CheckResultSet(std::shared_ptr &store) { std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test WHERE name = ?", std::vector{ "zhangsan" }); - EXPECT_NE(resultSet, nullptr); + ASSERT_NE(resultSet, nullptr); int columnIndex; int intVal; @@ -258,10 +277,8 @@ void RdbStoreInsertTest::CheckBlob(std::shared_ptr &resultSet) * @tc.desc: test RdbStore insert * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_002, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_002, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; values.PutInt("id", 1); @@ -269,10 +286,10 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_002, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "", values); // empty table name + int ret = store_->Insert(id, "", values); // empty table name EXPECT_EQ(ret, E_EMPTY_TABLE_NAME); - ret = store->Insert(id, "wrongTable", values); // no such table + ret = store_->Insert(id, "wrongTable", values); // no such table EXPECT_EQ(ret, E_SQLITE_ERROR); } @@ -281,13 +298,11 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_002, TestSize.Level1) * @tc.desc: test RdbStore insert * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_003, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_003, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket emptyBucket; - int ret = store->Insert(id, "test", emptyBucket); + int ret = store_->Insert(id, "test", emptyBucket); EXPECT_EQ(ret, E_EMPTY_VALUES_BUCKET); ValuesBucket values; @@ -296,7 +311,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_003, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("wrongColumn", 100.5); // no such column values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Insert(id, "test", values); + ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_SQLITE_ERROR); } @@ -305,18 +320,16 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_003, TestSize.Level1) * @tc.desc: test RdbStore replace * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_001, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_001, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; - int ret = store->Replace(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Replace(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -356,14 +369,12 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_001, TestSize.Level1) * @tc.desc: test RdbStore replace * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_002, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_002, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -373,11 +384,11 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_002, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Replace(id, "test", values); + ret = store_->Replace(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -417,10 +428,8 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_002, TestSize.Level1) * @tc.desc: test RdbStore Replace * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_003, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_003, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; values.PutInt("id", 1); @@ -428,10 +437,10 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_003, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Replace(id, "", values); // empty table name + int ret = store_->Replace(id, "", values); // empty table name EXPECT_EQ(ret, E_EMPTY_TABLE_NAME); - ret = store->Replace(id, "wrongTable", values); // no such table + ret = store_->Replace(id, "wrongTable", values); // no such table EXPECT_EQ(ret, E_SQLITE_ERROR); } @@ -440,13 +449,11 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_003, TestSize.Level1) * @tc.desc: test RdbStore Replace * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_004, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_004, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket emptyBucket; - int ret = store->Replace(id, "test", emptyBucket); + int ret = store_->Replace(id, "test", emptyBucket); EXPECT_EQ(ret, E_EMPTY_VALUES_BUCKET); ValuesBucket values; @@ -455,7 +462,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_004, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("wrongColumn", 100.5); // no such column values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Replace(id, "test", values); + ret = store_->Replace(id, "test", values); EXPECT_EQ(ret, E_SQLITE_ERROR); } @@ -464,17 +471,15 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_004, TestSize.Level1) * @tc.desc: test RdbStore replace * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_005, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_005, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; - int ret = store->Replace(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Replace(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -511,14 +516,12 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_005, TestSize.Level1) * @tc.desc: test RdbStore replace * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_006, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_006, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -528,11 +531,11 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_006, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Replace(id, "test", values); + ret = store_->Replace(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -569,10 +572,8 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_006, TestSize.Level1) * @tc.desc: test RdbStore InsertWithConflictResolution * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_001_002, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_001_002, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; @@ -583,7 +584,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_001_002, Test values.PutBlob("blobType", std::vector{ 1, 2, 3 }); // default is ConflictResolution::ON_CONFLICT_NONE - int ret = store->InsertWithConflictResolution(id, "test", values); + int ret = store_->InsertWithConflictResolution(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -593,7 +594,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_001_002, Test values.PutInt("age", 18); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->InsertWithConflictResolution(id, "test", values); + ret = store_->InsertWithConflictResolution(id, "test", values); EXPECT_EQ(ret, E_SQLITE_CONSTRAINT); } @@ -602,10 +603,8 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_001_002, Test * @tc.desc: test RdbStore InsertWithConflictResolution * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_003_004, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_003_004, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; @@ -614,7 +613,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_003_004, Test values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_ROLLBACK); + int ret = store_->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_ROLLBACK); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -624,7 +623,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_003_004, Test values.PutInt("age", 18); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_ROLLBACK); + ret = store_->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_ROLLBACK); EXPECT_EQ(ret, E_SQLITE_CONSTRAINT); } @@ -633,10 +632,8 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_003_004, Test * @tc.desc: test RdbStore InsertWithConflictResolution * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_005, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_005, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; @@ -645,7 +642,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_005, TestSize values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_IGNORE); + int ret = store_->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_IGNORE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -655,7 +652,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_005, TestSize values.PutInt("age", 18); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_IGNORE); + ret = store_->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_IGNORE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(id, -1); } @@ -665,14 +662,12 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_005, TestSize * @tc.desc: test RdbStore InsertWithConflictResolution * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_006, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_006, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; - int ret = store->InsertWithConflictResolution( + int ret = store_->InsertWithConflictResolution( id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0]), ConflictResolution::ON_CONFLICT_REPLACE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -683,11 +678,11 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_006, TestSize values.PutInt("age", 18); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_REPLACE); + ret = store_->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_REPLACE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(id, 1); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -727,14 +722,12 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_006, TestSize * @tc.desc: test RdbStore InsertWithConflictResolution * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_007, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_007, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; - int ret = store->InsertWithConflictResolution( + int ret = store_->InsertWithConflictResolution( id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0]), ConflictResolution::ON_CONFLICT_REPLACE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -745,11 +738,11 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_007, TestSize values.PutInt("age", 18); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_REPLACE); + ret = store_->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_REPLACE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(id, 1); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -786,23 +779,21 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_007, TestSize * @tc.desc: Abnormal testCase of InsertWithConflictResolution, if conflictResolution is invalid * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_008, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_008, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id = 0; ValuesBucket values; values.PutInt("id", 1); values.PutInt("age", 18); - int ret = store->InsertWithConflictResolution(id, "test", values, static_cast(6)); + int ret = store_->InsertWithConflictResolution(id, "test", values, static_cast(6)); EXPECT_EQ(E_INVALID_CONFLICT_FLAG, ret); EXPECT_EQ(0, id); values.Clear(); values.PutInt("id", 1); values.PutInt("age", 18); - ret = store->InsertWithConflictResolution(id, "test", values, static_cast(-1)); + ret = store_->InsertWithConflictResolution(id, "test", values, static_cast(-1)); EXPECT_EQ(E_INVALID_CONFLICT_FLAG, ret); EXPECT_EQ(0, id); } @@ -814,7 +805,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_008, TestSize * @tc.require: * @tc.author: */ -HWTEST_P(RdbStoreInsertTest, OverLimitWithInsert_001, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, OverLimitWithInsert_001, TestSize.Level0) { std::shared_ptr store = *GetParam(); auto [code, maxPageCount] = store->Execute("PRAGMA max_page_count;"); @@ -829,5 +820,654 @@ HWTEST_P(RdbStoreInsertTest, OverLimitWithInsert_001, TestSize.Level1) ASSERT_EQ(result.first, E_SQLITE_FULL); } +/** + * @tc.name: BatchInsert_001 + * @tc.desc: normal test + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_001, TestSize.Level0) +{ + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto [status, result] = store_->BatchInsert("test", rows, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 5); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 5); + auto values = GetColumnValues(result.results, "id"); + ASSERT_EQ(values.size(), 5); + for (int i = 0; i < 5; i++) { + int val = -1; + EXPECT_EQ(values[i].GetInt(val), E_OK); + EXPECT_EQ(val, i); + } +} + +/** + * @tc.name: BatchInsert_002 + * @tc.desc: abnormal test. batch insert with returning and conflict IGNORE + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_002, TestSize.Level0) +{ + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + ValuesBucket row; + row.Put("id", 2); + row.Put("name", "Jim"); + auto res = store_->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 2); + std::string returningField = "id"; + auto [status, result] = + store_->BatchInsert("test", rows, { returningField }, ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 4); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 4); + auto values = GetColumnValues(result.results, returningField); + ASSERT_EQ(values.size(), 4); + for (size_t i = 0; i < values.size(); i++) { + int val = -1; + EXPECT_EQ(values[i].GetInt(val), E_OK); + EXPECT_EQ(val, i + (i >= 2)); + } +} + +/** + * @tc.name: BatchInsert_003 + * @tc.desc: abnormal test. batch insert with returning and conflict fail. + * When using the fail strategy, if the constraint is violated, the correct result cannot be obtained + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_003, TestSize.Level0) +{ + std::vector rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.push_back(std::move(row)); + } + ValuesBucket row; + row.Put("id", 2); + row.Put("name", "Jim"); + auto res = store_->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 2); + auto [status, result] = store_->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_FAIL); + EXPECT_EQ(status, E_SQLITE_CONSTRAINT); + EXPECT_EQ(result.changed, 2); + EXPECT_EQ(result.results, nullptr); +} + +/** + * @tc.name: BatchInsert_004 + * @tc.desc: abnormal test. batch insert with returning and conflict replace + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_004, TestSize.Level0) +{ + std::vector rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.push_back(std::move(row)); + } + ValuesBucket row; + row.Put("id", 2); + row.Put("name", "Jim"); + auto res = store_->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 2); + std::string returningField = "id"; + auto [status, result] = store_->BatchInsert( + "test", ValuesBuckets(std::move(rows)), { returningField }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 5); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 5); + auto values = GetColumnValues(result.results, returningField); + ASSERT_EQ(values.size(), 5); + for (size_t i = 0; i < 5; i++) { + int val = -1; + EXPECT_EQ(values[i].GetInt(val), E_OK); + EXPECT_EQ(val, i); + } +} + +/** + * @tc.name: BatchInsert_005 + * @tc.desc: abnormal test. batch insert with over returning limit + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_005, TestSize.Level0) +{ + ValuesBuckets rows; + rows.Reserve(1025); + for (int i = 0; i < 1025; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(std::move(row)); + } + auto [status, result] = store_->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1024); + auto values = GetColumnValues(result.results, "id"); + ASSERT_EQ(values.size(), 1024); + for (size_t i = 0; i < 1024; i++) { + EXPECT_EQ(int(values[i]), i); + } +} + +/** + * @tc.name: BatchInsert_006 + * @tc.desc: abnormal test. batch insert with returning non-existent fields + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_006, TestSize.Level0) +{ + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(std::move(row)); + } + std::string returningField = "notExist"; + auto [status, result] = + store_->BatchInsert("test", rows, { returningField }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + ASSERT_EQ(result.results, nullptr); +} + +/** + * @tc.name: BatchInsert_007 + * @tc.desc: abnormal test. batch insert with returning and no changed rows + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_007, TestSize.Level0) +{ + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 2); + row.Put("name", "Jim"); + auto res = store_->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 2); + rows.Put(std::move(row)); + auto [status, result] = store_->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 0); +} + +/** + * @tc.name: BatchInsert_008 + * @tc.desc: normal test. batch insert with returning rowId + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_008, TestSize.Level0) +{ + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 2); + row.Put("name", "Jim"); + rows.Put(std::move(row)); + // rowId can use in retuning, but get column not include rowId + auto [status, result] = store_->BatchInsert("test", rows, { "rowId", "rowid", "RowId", "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("id")), 2); +} + +/** + * @tc.name: BatchInsert_009 + * @tc.desc: normal test. batch insert with returning * + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_009, TestSize.Level0) +{ + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 2); + row.Put("name", "Jim"); + row.Put("age", 18); + row.PutDouble("salary", 100.5); + std::vector blob{ 1, 2, 3 }; + row.PutBlob("blobType", blob); + rows.Put(std::move(row)); + auto [status, result] = + store_->BatchInsert("test", rows, { "*" }, NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("id")), 2); + EXPECT_EQ(std::string(rowEntity.Get("name")), "Jim"); + EXPECT_EQ(int(rowEntity.Get("age")), 18); + EXPECT_NEAR(double(rowEntity.Get("salary")), 100.5, std::numeric_limits::epsilon()); + EXPECT_EQ(std::vector(rowEntity.Get("blobType")), blob); +} + +/** + * @tc.name: BatchInsert_010 + * @tc.desc: normal test. batch insert with returning complex field + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_010, TestSize.Level0) +{ + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 2); + row.Put("name", "Jim"); + row.PutDouble("salary", 100.5); + rows.Put(std::move(row)); + auto [status, result] = store_->BatchInsert("test", rows, { "id", "name", "salary * 1.1 AS bonusSalary" }, + NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("id")), 2); + EXPECT_EQ(std::string(rowEntity.Get("name")), "Jim"); + EXPECT_NEAR(double(rowEntity.Get("bonusSalary")), 100.5 * 1.1, std::numeric_limits::epsilon()); +} + +/** + * @tc.name: BatchInsert_011 + * @tc.desc: normal test. batch insert with returning complex field + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_011, TestSize.Level1) +{ + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 1); + row.Put("name", "Jim"); + row.Put("age", 18); + row.PutDouble("salary", 110.5); + rows.Put(std::move(row)); + row.Clear(); + row.Put("id", 2); + row.Put("name", "Bob"); + row.Put("age", 22); + row.PutDouble("salary", 90); + rows.Put(std::move(row)); + auto [status, result] = store_->BatchInsert("test", rows, + { "id", "name", "(salary < 100) AS lowSalary", "age > 18 as adult" }, + NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 2); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 2); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("id")), 1); + EXPECT_EQ(std::string(rowEntity.Get("name")), "Jim"); + EXPECT_EQ(bool(rowEntity.Get("lowSalary")), false); + EXPECT_EQ(bool(rowEntity.Get("adult")), false); + + EXPECT_EQ(result.results->GoToNextRow(), E_OK); + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("id")), 2); + EXPECT_EQ(std::string(rowEntity.Get("name")), "Bob"); + EXPECT_EQ(bool(rowEntity.Get("lowSalary")), true); + EXPECT_EQ(bool(rowEntity.Get("adult")), true); +} + +/** + * @tc.name: BatchInsert_012 + * @tc.desc: normal test. batch insert with returning function + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_012, TestSize.Level1) +{ + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 20); + row.Put("name", "Jim"); + row.PutDouble("salary", 100.5); + rows.Put(std::move(row)); + auto [status, result] = store_->BatchInsert("test", rows, { "id", "name", "datetime('now') AS createdTime" }, + NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("id")), 20); + EXPECT_EQ(std::string(rowEntity.Get("name")), "Jim"); + EXPECT_EQ(rowEntity.Get("createdTime").GetType(), ValueObject::TYPE_STRING); + EXPECT_FALSE(std::string(rowEntity.Get("createdTime")).empty()); +} + +/** + * @tc.name: BatchInsert_013 + * @tc.desc: normal test. batch insert into virtual table with returning + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_013, TestSize.Level1) +{ + store_->Execute("CREATE VIRTUAL TABLE IF NOT EXISTS articles USING fts5(title, content);"); + ValuesBuckets rows; + ValuesBucket row; + row.Put("title", "fts5"); + row.Put("content", "test virtual tables"); + rows.Put(std::move(row)); + auto [status, result] = + store_->BatchInsert("articles", rows, { "title" }, NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(std::string(rowEntity.Get("title")), "fts5"); + store_->Execute("Drop TABLE articles"); +} + +/** + * @tc.name: BatchInsert_014 + * @tc.desc: normal test. batch insert with returning and trigger + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_014, TestSize.Level1) +{ + auto [code, result1] = store_->Execute("CREATE TRIGGER after_name_insert AFTER INSERT ON test" + " BEGIN UPDATE test SET name = 'after trigger' WHERE name = 'BatchInsert_014'; END"); + + EXPECT_EQ(code, E_OK); + + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 200); + row.Put("name", "BatchInsert_014"); + rows.Put(std::move(row)); + auto [status, result] = + store_->BatchInsert("test", rows, { "name" }, NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(std::string(rowEntity.Get("name")), "BatchInsert_014"); + + auto resultSet = store_->QuerySql("select name from test where id = 200"); + int rowCount = -1; + resultSet->GetRowCount(rowCount); + resultSet->GoToFirstRow(); + EXPECT_EQ(resultSet->GetRow(rowEntity), E_OK); + EXPECT_EQ(std::string(rowEntity.Get("name")), "after trigger"); + store_->Execute("DROP TRIGGER IF EXISTS after_name_insert"); +} + +/** + * @tc.name: BatchInsert_015 + * @tc.desc: normal test. batch insert with returning and sub query + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_015, TestSize.Level1) +{ + store_->Execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT);"); + store_->Execute("CREATE TABLE IF NOT EXISTS logs (id INTEGER PRIMARY KEY, action TEXT);"); + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 200); + row.Put("action", "BatchInsert_015"); + rows.Put(std::move(row)); + auto [status, changed] = store_->BatchInsert("logs", rows); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(changed, 1); + Results result{ -1 }; + row.Clear(); + rows.Clear(); + row.Put("id", 1); + row.Put("name", "BatchInsert_015"); + rows.Put(std::move(row)); + std::tie(status, result) = store_->BatchInsert("users", rows, + { "(SELECT COUNT(*) FROM logs WHERE action = name) AS count" }, + NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("count")), 1); + store_->Execute("DROP TABLE users"); + store_->Execute("DROP TABLE logs"); +} + +/** + * @tc.name: BatchInsert_016 + * @tc.desc: abnormal test. batch insert with max returning limit + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_016, TestSize.Level0) +{ + int maxRowCount = 1024; + ValuesBuckets rows; + rows.Reserve(maxRowCount); + for (int i = 0; i < maxRowCount; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(std::move(row)); + } + auto [status, result] = + store_->BatchInsert("test", ValuesBuckets(rows), {"id", "name"}, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, maxRowCount); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, maxRowCount); + for (size_t i = 0; i < maxRowCount; i++) { + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("id")), i); + EXPECT_EQ(std::string(rowEntity.Get("name")), "Jim"); + if (i != maxRowCount - 1) { + ASSERT_EQ(result.results->GoToNextRow(), E_OK); + } + } +} + +/** + * @tc.name: BatchInsert_017 + * @tc.desc: abnormal test. batch insert with max returning limit + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_017, TestSize.Level0) +{ + int maxRowCount = 1024; + ValuesBuckets rows; + rows.Reserve(maxRowCount); + for (int i = 0; i < maxRowCount; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(std::move(row)); + } + auto [status, result] = + store_->BatchInsert("test", ValuesBuckets(rows), {"id", "name"}, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, maxRowCount); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, maxRowCount); + + std::tie(status, result) = + store_->ExecuteExt("UPDATE test SET name = 'Tim' WHERE name = 'Jim' RETURNING id, name"); + + EXPECT_EQ(result.changed, maxRowCount); + count = 0; + EXPECT_EQ(result.results->GetRowCount(count), E_OK); + EXPECT_EQ(count, maxRowCount); + for (size_t i = 0; i < maxRowCount; i++) { + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("id")), i); + EXPECT_EQ(std::string(rowEntity.Get("name")), "Tim"); + if (i != maxRowCount - 1) { + ASSERT_EQ(result.results->GoToNextRow(), E_OK); + } + } +} + +/** + * @tc.name: BatchInsert_018 + * @tc.desc: abnormal test. batch insert with max returning limit + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_018, TestSize.Level0) +{ + int maxRowCount = 1024; + ValuesBuckets rows; + rows.Reserve(maxRowCount); + for (int i = 0; i < maxRowCount; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(std::move(row)); + } + auto [status, result] = + store_->BatchInsert("test", ValuesBuckets(rows), {"id", "name"}, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, maxRowCount); + + std::tie(status, result) = + store_->ExecuteExt("update test set name = ? where name = ?", { "Tim", "Jim" }); + + EXPECT_NE(result.results, nullptr); + EXPECT_EQ(result.changed, maxRowCount); + int32_t count = 0; + EXPECT_EQ(result.results->GetRowCount(count), E_OK); + EXPECT_EQ(count, 0); +} +/** + * @tc.name: BatchInsert_019 + * @tc.desc: normal test. batch insert with returning and trigger + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_019, TestSize.Level1) +{ + auto [code, result1] = store_->Execute("CREATE TRIGGER after_name_insert AFTER INSERT ON test" + " BEGIN UPDATE test SET name = 'after trigger' WHERE name = 'BatchInsert_014'; END"); + + EXPECT_EQ(code, E_OK); + + auto [status, result] = + store_->ExecuteExt("INSERT INTO test (id, name) VALUES (200, 'BatchInsert_014') RETURNING name;"); + + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(std::string(rowEntity.Get("name")), "BatchInsert_014"); + + auto resultSet = store_->QuerySql("select name from test where id = 200"); + int rowCount = -1; + resultSet->GetRowCount(rowCount); + resultSet->GoToFirstRow(); + EXPECT_EQ(resultSet->GetRow(rowEntity), E_OK); + EXPECT_EQ(std::string(rowEntity.Get("name")), "after trigger"); + store_->Execute("DROP TRIGGER IF EXISTS after_name_insert"); +} INSTANTIATE_TEST_SUITE_P(InsertTest, RdbStoreInsertTest, testing::Values(&g_store, &g_memDb)); } // namespace OHOS::RdbStoreInsertTest \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_memory_db_test.cpp b/relational_store/test/native/rdb/unittest/rdb_memory_db_test.cpp index db4521130dbe9b7986227d2bc572855f5b93789e..62835c619b1fb7394a875f092cd1feb4a021ff8a 100644 --- a/relational_store/test/native/rdb/unittest/rdb_memory_db_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_memory_db_test.cpp @@ -400,27 +400,27 @@ HWTEST_F(RdbMemoryDbTest, CRUDWithMemoryDb_003, TestSize.Level1) row.Put("name", "Jim_batchInsert"); rows.Put(row); } - auto result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_SQLITE_LOCKED); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_SQLITE_LOCKED); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_SQLITE_LOCKED); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_SQLITE_LOCKED); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_SQLITE_LOCKED); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_SQLITE_LOCKED); ASSERT_EQ(result.second, -1); } diff --git a/relational_store/test/native/rdb/unittest/rdb_predicates_test.cpp b/relational_store/test/native/rdb/unittest/rdb_predicates_test.cpp index 0b4b25067b0027a2579ab8e6770ed2468e40173f..017be1f0d26da9962206c6cc185890af5efa028d 100644 --- a/relational_store/test/native/rdb/unittest/rdb_predicates_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_predicates_test.cpp @@ -353,7 +353,12 @@ const std::string ALL_DATA_TYPE_INSERT_SQL = "primShortValue, primFloatValue, primDoubleValue, " "primBooleanValue, primByteValue, primCharValue, `orderr`) " "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);"; - +const std::string HAVING_CREATE_SQL = + "CREATE TABLE IF NOT EXISTS orders (id INTEGER PRIMARY KEY AUTOINCREMENT, customer_id INTEGER, amount INTEGER)"; +const std::string HAVING_INSERT_SQL = + "INSERT INTO orders (customer_id, amount) VALUES (1, 1500), (1, 2000), (1, 3000), (2, 800), (2, 1200), (3, 1500)," + " (3, 2000), (3, 2500), (3, 1000)"; +const std::string HAVING_DROP_SQL = "DROP TABLE IF EXISTS orders"; class PredicateTestOpenCallback : public RdbOpenCallback { public: int OnCreate(RdbStore &store) override; @@ -2483,7 +2488,7 @@ HWTEST_F(RdbStorePredicateTest, RdbStore_GetString_001, TestSize.Level1) store->ExecuteSql("DELETE FROM person"); } -/* * +/** * @tc.name: RdbStore_GetString_002 * @tc.desc: Normal testCase of RdbPredicates for GetString * @tc.type: FUNC @@ -2518,4 +2523,125 @@ HWTEST_F(RdbStorePredicateTest, RdbStore_GetString_002, TestSize.Level1) resultSet->Close(); store->ExecuteSql("DELETE FROM person"); +} + +/** + * @tc.name: RdbStore_Having_001 + * @tc.desc: Verify scenarios without placeholders and without passing values + * 1.Execute Having("total > 5000 AND count >= 3") + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbStorePredicateTest, RdbStore_Having_001, TestSize.Level1) +{ + store->Execute(HAVING_CREATE_SQL); + store->Execute(HAVING_INSERT_SQL); + RdbPredicates predicates("orders"); + predicates.GroupBy({ "customer_id" }); + predicates.Having("total > 5000 AND count >= 3"); + auto resultSet = store->Query(predicates, { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total" }); + EXPECT_EQ(resultSet->GoToNextRow(), E_OK); + RowEntity rowEntity; + EXPECT_EQ(resultSet->GetRow(rowEntity), E_OK); + EXPECT_TRUE(rowEntity.Get("customer_id") == ValueObject(1)); + EXPECT_TRUE(rowEntity.Get("total") == ValueObject(6500)); // 6500 means total price. + + EXPECT_EQ(resultSet->GoToNextRow(), E_OK); + RowEntity rowEntity1; + EXPECT_EQ(resultSet->GetRow(rowEntity1), E_OK); + EXPECT_TRUE(rowEntity1.Get("customer_id") == ValueObject(3)); // 3 means customer id. + EXPECT_TRUE(rowEntity1.Get("total") == ValueObject(7000)); // 7000 means total price. + store->ExecuteSql(HAVING_DROP_SQL); +} + +/** + * @tc.name: RdbStore_Having_002 + * @tc.desc: Verify scenarios without placeholders and without passing args. + * 1.Execute having("") + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbStorePredicateTest, RdbStore_Having_002, TestSize.Level1) +{ + store->Execute(HAVING_CREATE_SQL); + store->Execute(HAVING_INSERT_SQL); + RdbPredicates predicates("orders"); + predicates.GroupBy({ "customer_id" }); + // When conditions are passed empty, 'having' does not take effect. + predicates.Having(""); + auto resultSet = store->Query(predicates, { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total" }); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 3); // 3 means row count. + store->ExecuteSql(HAVING_DROP_SQL); +} + + /** + * @tc.name: RdbStore_Having_003 + * @tc.desc: Test conditions for passing in illegal SQL + * 1.Execute Having("SALARY == 1.2") + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbStorePredicateTest, RdbStore_Having_003, TestSize.Level1) +{ + store->Execute(HAVING_CREATE_SQL); + store->Execute(HAVING_INSERT_SQL); + RdbPredicates predicates("orders"); + predicates.GroupBy({ "customer_id" }); + predicates.Having("SALARY == 1.2"); + auto resultSet = store->Query(predicates, { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total" }); + int count; + EXPECT_EQ(resultSet->GetRowCount(count), E_SQLITE_ERROR); + store->ExecuteSql(HAVING_DROP_SQL); +} + +/** + * @tc.name: RdbStore_Having_004 + * @tc.desc: Verify scenarios without placeholders and without passing values + * 1.Execute Having(total > ? AND count >= ?", {5000}) + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbStorePredicateTest, RdbStore_Having_004, TestSize.Level1) +{ + store->Execute(HAVING_CREATE_SQL); + store->Execute(HAVING_INSERT_SQL); + RdbPredicates predicates("orders"); + predicates.GroupBy({ "customer_id" }); + predicates.Having("total > ? AND count >= ?", { 5000 }); + auto resultSet = store->Query(predicates, { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total" }); + int count = -1; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 0); + store->ExecuteSql(HAVING_DROP_SQL); +} + +/** + * @tc.name: RdbStore_Having_005 + * @tc.desc: Test using placeholder scenarios. + * 1.Execute Having(total > ? AND count >= ?", {5000, 3}) + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbStorePredicateTest, RdbStore_Having_005, TestSize.Level1) +{ + store->Execute(HAVING_CREATE_SQL); + store->Execute(HAVING_INSERT_SQL); + RdbPredicates predicates("orders"); + predicates.GroupBy({ "customer_id" }); + predicates.Having("total > ? AND count >= ?", {5000, 3}); // 5000 means lower limit of total price. + auto resultSet = store->Query(predicates, { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total" }); + EXPECT_EQ(resultSet->GoToNextRow(), E_OK); + RowEntity rowEntity; + EXPECT_EQ(resultSet->GetRow(rowEntity), E_OK); + EXPECT_TRUE(rowEntity.Get("customer_id") == ValueObject(1)); + EXPECT_TRUE(rowEntity.Get("total") == ValueObject(6500)); // 6500 means total price. + + EXPECT_EQ(resultSet->GoToNextRow(), E_OK); + RowEntity rowEntity1; + EXPECT_EQ(resultSet->GetRow(rowEntity1), E_OK); + EXPECT_TRUE(rowEntity1.Get("customer_id") == ValueObject(3)); // 3 means customer id. + EXPECT_TRUE(rowEntity1.Get("total") == ValueObject(7000)); // 7000 means total price. + store->ExecuteSql(HAVING_DROP_SQL); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_read_only_test.cpp b/relational_store/test/native/rdb/unittest/rdb_read_only_test.cpp index 1552f2f9883260fcf1bbb62a128ef3fdde510ed2..99c20f94c162ad25add0608594f94f92fd217ff5 100644 --- a/relational_store/test/native/rdb/unittest/rdb_read_only_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_read_only_test.cpp @@ -252,6 +252,9 @@ HWTEST_F(RdbReadOnlyTest, RdbStore_ReadOnly_0008, TestSize.Level1) std::tie(ret, object) = store->Execute("PRAGMA user_version=2"); EXPECT_EQ(E_NOT_SUPPORT, ret); + + auto [code, result] = store->ExecuteExt("PRAGMA user_version=2"); + EXPECT_EQ(E_NOT_SUPPORT, code); } /** @@ -512,7 +515,7 @@ HWTEST_F(RdbReadOnlyTest, RdbStore_ReadOnly_0022, TestSize.Level1) /** * @tc.name: RdbStore_ReadOnly_0023 - * @tc.desc: test BatchInsertWithConflictResolution + * @tc.desc: test BatchInsert * @tc.type: FUNC */ HWTEST_F(RdbReadOnlyTest, RdbStore_ReadOnly_0023, TestSize.Level1) @@ -525,17 +528,17 @@ HWTEST_F(RdbReadOnlyTest, RdbStore_ReadOnly_0023, TestSize.Level1) row.Put("name", "Jim"); rows.Put(row); } - auto ret = store->BatchInsertWithConflictResolution("test", rows, ConflictResolution::ON_CONFLICT_NONE); + auto ret = store->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_NONE); EXPECT_EQ(E_NOT_SUPPORT, ret.first); - ret = store->BatchInsertWithConflictResolution("test", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + ret = store->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); EXPECT_EQ(E_NOT_SUPPORT, ret.first); - ret = store->BatchInsertWithConflictResolution("test", rows, ConflictResolution::ON_CONFLICT_ABORT); + ret = store->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_ABORT); EXPECT_EQ(E_NOT_SUPPORT, ret.first); - ret = store->BatchInsertWithConflictResolution("test", rows, ConflictResolution::ON_CONFLICT_FAIL); + ret = store->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_FAIL); EXPECT_EQ(E_NOT_SUPPORT, ret.first); - ret = store->BatchInsertWithConflictResolution("test", rows, ConflictResolution::ON_CONFLICT_IGNORE); + ret = store->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_IGNORE); EXPECT_EQ(E_NOT_SUPPORT, ret.first); - ret = store->BatchInsertWithConflictResolution("test", rows, ConflictResolution::ON_CONFLICT_REPLACE); + ret = store->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_REPLACE); EXPECT_EQ(E_NOT_SUPPORT, ret.first); } diff --git a/relational_store/test/native/rdb/unittest/rdb_security_manager_test.cpp b/relational_store/test/native/rdb/unittest/rdb_security_manager_test.cpp index cf8b1f7a2544a8cb2d3147dabcf0ff3aabfc561a..d6b028a9c2a66e3c7e5bfe76f2c4127691688e67 100644 --- a/relational_store/test/native/rdb/unittest/rdb_security_manager_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_security_manager_test.cpp @@ -157,4 +157,48 @@ HWTEST_F(RdbSecurityManagerTest, LoadSecretKeyFromDiskTest, TestSize.Level1) RdbHelper::DeleteRdbStore(config); } + +/** + * @tc.name: LockNoBlockTest001 + * @tc.desc: Abnormal test for LockNB + * @tc.type: FUNC + */ +HWTEST_F(RdbSecurityManagerTest, LockNBTest001, TestSize.Level1) +{ + std::string lockPath = dbFile_ + "-LockNBTest001"; + RdbSecurityManager::KeyFiles keyFiles(lockPath); + EXPECT_EQ(keyFiles.DestroyLock(), E_OK); + EXPECT_NE(keyFiles.Lock(false), E_OK); +} + +/** + * @tc.name: LockNBTest002 + * @tc.desc: test LockNB return E_ERROR when called from another fd + * @tc.type: FUNC + */ +HWTEST_F(RdbSecurityManagerTest, LockNBTest002, TestSize.Level1) +{ + RdbSecurityManager::KeyFiles keyFiles(dbFile_); + EXPECT_EQ(keyFiles.Lock(false), E_OK); + std::thread thread([dbFile = dbFile_]() { + RdbSecurityManager::KeyFiles keyFiles(dbFile); + EXPECT_EQ(keyFiles.Lock(false), E_ERROR); + keyFiles.Unlock(); + }); + sleep(1); + thread.join(); + keyFiles.Unlock(); +} + +/** + * @tc.name: InitPathTest + * @tc.desc: test init path test + * @tc.type: FUNC + */ +HWTEST_F(RdbSecurityManagerTest, InitPathTest, TestSize.Level1) +{ + std::string filePath("system/test"); + bool ret = RdbSecurityManager::InitPath(filePath); + EXPECT_FALSE(ret); +} } // namespace Test \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_service_proxy_test.cpp b/relational_store/test/native/rdb/unittest/rdb_service_proxy_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..597c2436b25288afeba3db39f0e3c4f00133a676 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_service_proxy_test.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025 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 "rdb_service_proxy.h" + +#include + +#include "rdb_manager_impl.h" +#include "rdb_service.h" +#include "rdb_types.h" + +using namespace testing::ext; +using namespace OHOS::DistributedRdb; +namespace Test { +class RdbServiceProxyTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(void){}; + void TearDown(void){}; +}; + +/** + * @tc.name: OnRemoteDeadSyncComplete + * @tc.desc: OnRemoteDeadSyncComplete callback is executed + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceProxyTest, OnRemoteDeadSyncComplete, TestSize.Level1) +{ + RdbSyncerParam param; + param.bundleName_ = "com.example.test"; + param.storeName_ = "test.db"; + auto [status, service] = RdbManagerImpl::GetInstance().GetRdbService(param); + ASSERT_NE(service, nullptr); + + auto callback = [](const Details &details) { + ASSERT_NE(details.size(), 0); + EXPECT_TRUE(details.begin()->first.empty()); + EXPECT_EQ(details.begin()->second.progress, Progress::SYNC_FINISH); + EXPECT_EQ(details.begin()->second.code, ProgressCode::UNKNOWN_ERROR); + }; + + RdbService::Option option; + option.seqNum = 1; + auto proxy = std::static_pointer_cast(service); + ASSERT_NE(proxy, nullptr); + proxy->syncCallbacks_.Insert(option.seqNum, callback); + proxy->OnRemoteDeadSyncComplete(); +} +} // namespace Test \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_sql_utils_test.cpp b/relational_store/test/native/rdb/unittest/rdb_sql_utils_test.cpp index b65786233b4512fa945960128e9f9d1ab97d7ffc..6ef1d5f638d2e16ded33295ac3eff1bdd12e568b 100644 --- a/relational_store/test/native/rdb/unittest/rdb_sql_utils_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_sql_utils_test.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#define LOG_TAG "RdbSqlUtilsTest" #include "rdb_sql_utils.h" #include @@ -22,11 +23,14 @@ #include "grd_type_export.h" #include "rd_utils.h" +#include "logger.h" #include "sqlite_sql_builder.h" #include "values_buckets.h" +#include "rdb_predicates.h" using namespace testing::ext; using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; class RdbSqlUtilsTest : public testing::Test { public: @@ -61,23 +65,172 @@ HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_Test_001, TestSize.Level1) } /** - * @tc.name: RdbStore_UpdateSqlBuilder_001 - * @tc.desc: test RdbStore UpdateSqlBuilder + * @tc.name: RdbStore_GetInsertSqlInfo_001 + * @tc.desc: test RdbStore GetInsertSqlInfo * @tc.type: FUNC */ -HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_UpdateSqlBuilder_001, TestSize.Level1) +HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_GetInsertSqlInfo_001, TestSize.Level1) { ValuesBucket values; values.PutString("name", std::string("zhangsan")); values.PutInt("age", 20); values.PutDouble("salary", 300.5); + std::pair result = RdbSqlUtils::GetInsertSqlInfo("", values, ConflictResolution::ON_CONFLICT_NONE); + EXPECT_EQ(result.first, E_EMPTY_TABLE_NAME); +} + +/** + * @tc.name: RdbStore_GetInsertSqlInfo_002 + * @tc.desc: test RdbStore GetInsertSqlInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_GetInsertSqlInfo_002, TestSize.Level1) +{ + ValuesBucket values; + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + ValuesBucket emptyValues; + + std::pair result = + RdbSqlUtils::GetInsertSqlInfo("temp", emptyValues, ConflictResolution::ON_CONFLICT_NONE); + EXPECT_EQ(result.first, E_EMPTY_VALUES_BUCKET); +} + +/** + * @tc.name: RdbStore_GetInsertSqlInfo_003 + * @tc.desc: test RdbStore GetInsertSqlInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_GetInsertSqlInfo_003, TestSize.Level1) +{ + ValuesBucket values; + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + + std::pair result = + RdbSqlUtils::GetInsertSqlInfo("temp", values, ConflictResolution::ON_CONFLICT_NONE); + LOG_INFO("INSERT SQL is %{public}s", result.second.sql.c_str()); + EXPECT_EQ(result.first, E_OK); +} + +/** + * @tc.name: RdbStore_GetInsertSqlInfo_004 + * @tc.desc: test RdbStore GetInsertSqlInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_GetInsertSqlInfo_004, TestSize.Level1) +{ + ValuesBucket values; + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + + AssetValue assetVal; + assetVal.id = "123"; + assetVal.name = "kkk"; + std::vector assets; + assets.emplace_back(assetVal); + + ValueObject vo(assets); + values.Put("kkk", vo); + std::pair result = + RdbSqlUtils::GetInsertSqlInfo("temp", values, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(result.first, E_INVALID_ARGS); +} + +/** + * @tc.name: RdbStore_GetUpdateSqlInfo_001 + * @tc.desc: test RdbStore GetUpdateSqlInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_GetUpdateSqlInfo_001, TestSize.Level1) +{ + std::vector returningFields; + RdbPredicates predicates(""); + ValuesBucket bucketValues; + bucketValues.PutString("name", std::string("zhangsan")); + bucketValues.PutInt("age", 20); + bucketValues.PutDouble("salary", 300.5); + std::vector emptyValues; + std::pair result = RdbSqlUtils::GetUpdateSqlInfo( + predicates, bucketValues, ConflictResolution::ON_CONFLICT_NONE, returningFields); + EXPECT_EQ(result.first, E_EMPTY_TABLE_NAME); +} - std::vector bindArgs; - std::string updateSql = SqliteSqlBuilder::BuildUpdateString(values, "test", std::vector{ "19" }, "", - "age = ?", "", "", INT_MIN, INT_MIN, bindArgs, ConflictResolution::ON_CONFLICT_NONE); - EXPECT_EQ(updateSql, "UPDATE test SET age=?,name=?,salary=? WHERE age = ?"); +/** + * @tc.name: RdbStore_GetUpdateSqlInfo_002 + * @tc.desc: test RdbStore GetUpdateSqlInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_GetUpdateSqlInfo_002, TestSize.Level1) +{ + std::vector returningFields; + RdbPredicates predicates("temp"); + ValuesBucket bucketValues; + bucketValues.PutString("name", std::string("zhangsan")); + bucketValues.PutInt("age", 20); + bucketValues.PutDouble("salary", 300.5); + ValuesBucket emptyBucketValues; + std::vector emptyValues; - updateSql = SqliteSqlBuilder::BuildUpdateString(values, "test", std::vector{}, "", "", "", "", - INT_MIN, INT_MIN, bindArgs, ConflictResolution::ON_CONFLICT_NONE); - EXPECT_EQ(updateSql, "UPDATE test SET age=?,name=?,salary=?"); + std::pair result = RdbSqlUtils::GetUpdateSqlInfo( + predicates, emptyBucketValues, ConflictResolution::ON_CONFLICT_NONE, returningFields); + EXPECT_EQ(result.first, E_EMPTY_VALUES_BUCKET); } + +/** + * @tc.name: RdbStore_GetUpdateSqlInfo_003 + * @tc.desc: test RdbStore GetUpdateSqlInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_GetUpdateSqlInfo_003, TestSize.Level1) +{ + std::vector returningFields; + RdbPredicates predicates("temp"); + ValuesBucket bucketValues; + bucketValues.PutString("name", std::string("zhangsan")); + bucketValues.PutInt("age", 20); + bucketValues.PutDouble("salary", 300.5); + std::vector values; + ValueObject object; + values.push_back(object); + predicates.EqualTo("name", "wangwu"); + predicates.SetBindArgs(values); + std::pair result = RdbSqlUtils::GetUpdateSqlInfo( + predicates, bucketValues, ConflictResolution::ON_CONFLICT_NONE, returningFields); + LOG_INFO("UPDATE SQL is %{public}s", result.second.sql.c_str()); + EXPECT_EQ(result.first, E_OK); +} + +/** + * @tc.name: RdbStore_GetDeleteSqlInfo_001 + * @tc.desc: test RdbStore GetDeleteSqlInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_GetDeleteSqlInfo_001, TestSize.Level1) +{ + std::vector returningFields; + RdbPredicates predicates(""); + std::pair result = RdbSqlUtils::GetDeleteSqlInfo(predicates, returningFields); + EXPECT_EQ(result.first, E_EMPTY_TABLE_NAME); +} + +/** + * @tc.name: RdbStore_GetDeleteSqlInfo_002 + * @tc.desc: test RdbStore GetDeleteSqlInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqlUtilsTest, GetDeleteSqlInfo_002, TestSize.Level1) +{ + std::vector returningFields; + std::vector emptyValues; + RdbPredicates predicates("temp"); + predicates.EqualTo("name", "wangwu"); + predicates.SetBindArgs(emptyValues); + std::pair result = + RdbSqlUtils::GetDeleteSqlInfo(predicates, returningFields); + LOG_INFO("DELETE SQL is %{public}s", result.second.sql.c_str()); + EXPECT_EQ(result.first, E_OK); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_sqlite_shared_result_set_test.cpp b/relational_store/test/native/rdb/unittest/rdb_sqlite_shared_result_set_test.cpp index 5ac955a280f3c1eb4d1cfccbc9d52f1b36a73f26..e1d387a48d729c50ee652fb18170db035ccef791 100644 --- a/relational_store/test/native/rdb/unittest/rdb_sqlite_shared_result_set_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_sqlite_shared_result_set_test.cpp @@ -15,7 +15,9 @@ #include +#include #include +#include #include "common.h" #include "rdb_errno.h" @@ -29,6 +31,8 @@ using namespace testing::ext; using namespace OHOS::NativeRdb; using Asset = ValueObject::Asset; using Assets = ValueObject::Assets; +using ValueObjects = std::vector; +using Time = std::chrono::steady_clock::time_point; class RdbSqliteSharedResultSetTest : public testing::Test { public: static void SetUpTestCase(void); @@ -117,14 +121,14 @@ void RdbSqliteSharedResultSetTest::GenerateDefaultTable() values.PutBlob("data4", std::vector{ 66 }); // set uint8_t value 66 values.Put("data5", asset); values.Put("data6", assets); - values.Put("data7", std::vector(1, 0.5)); // set float value 0.5 + values.Put("data7", std::vector(1, 0.5)); // set float value 0.5 values.Put("data8", BigInteger(0)); store->Insert(id, "test", values); values.Clear(); values.PutInt("id", 2); // set int value 2 values.PutString("data1", std::string("2")); - values.PutInt("data2", -5); // set int value -5 + values.PutInt("data2", -5); // set int value -5 values.PutDouble("data3", 2.5); // set float value 2.5 values.PutBlob("data4", std::vector{}); store->Insert(id, "test", values); @@ -132,7 +136,7 @@ void RdbSqliteSharedResultSetTest::GenerateDefaultTable() values.Clear(); values.PutInt("id", 3); // set int value 3 values.PutString("data1", std::string("hello world")); - values.PutInt("data2", 3); // set int value 3 + values.PutInt("data2", 3); // set int value 3 values.PutDouble("data3", 1.8); // set float value 1.8 values.PutBlob("data4", std::vector{}); store->Insert(id, "test", values); @@ -1643,4 +1647,51 @@ HWTEST_F(RdbSqliteSharedResultSetTest, Sqlite_Shared_Result_Set_039, TestSize.Le rstSet->GetColumnType(8, colType); EXPECT_EQ(colType, ColumnType::TYPE_NULL); rstSet->Close(); +} + +/** + * @tc.name: Sqlite_Shared_Result_Set_003 + * @tc.desc: Abnormal testCase of PrepareStep + * @tc.type: FUNC + */ +HWTEST_F(RdbSqliteSharedResultSetTest, SqliteSharedResultSet_003, TestSize.Level2) +{ + ValueObjects values = {}; + Time start = std::chrono::steady_clock::now(); + auto sqliteSharedRst = std::make_shared( + start, nullptr, SqliteSharedOpenCallback::CREATE_TABLE_TEST, values, DATABASE_NAME); + auto res = sqliteSharedRst->PrepareStep(); + ASSERT_EQ(res.first, nullptr); + EXPECT_EQ(res.second, E_ALREADY_CLOSED); +} + +/** + * @tc.name: Sqlite_Shared_Result_Set_004 + * @tc.desc: Abnormal testCase of GetColumnNames + * @tc.type: FUNC + */ +HWTEST_F(RdbSqliteSharedResultSetTest, SqliteSharedResultSet_004, TestSize.Level2) +{ + ValueObjects values = {}; + Time start = std::chrono::steady_clock::now(); + auto sqliteSharedRst = std::make_shared( + start, nullptr, SqliteSharedOpenCallback::CREATE_TABLE_TEST, values, DATABASE_NAME); + auto res = sqliteSharedRst->GetColumnNames(); + EXPECT_EQ(res.first, E_ALREADY_CLOSED); + EXPECT_TRUE(res.second.empty()); +} + +/** + * @tc.name: Sqlite_Shared_Result_Set_005 + * @tc.desc: Abnormal testCase of OnGo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqliteSharedResultSetTest, SqliteSharedResultSet_005, TestSize.Level2) +{ + ValueObjects values = {}; + Time start = std::chrono::steady_clock::now(); + auto sqliteSharedRst = std::make_shared( + start, nullptr, SqliteSharedOpenCallback::CREATE_TABLE_TEST, values, DATABASE_NAME); + auto res = sqliteSharedRst->OnGo(0, 0); + EXPECT_EQ(res, E_ALREADY_CLOSED); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp b/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp index f6b63608643ad7cf94ecfdb24b188ef83ee84633..863bfd4dd31bdf11b4e911df20426bf3f8f6e0fc 100644 --- a/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp @@ -2150,22 +2150,22 @@ HWTEST_F(RdbStepResultSetTest, Abnormal_CacheResultSet004, TestSize.Level1) } /** - * @tc.name: Abnormal_CacheResultSet004 + * @tc.name: Invalid_TableName * @tc.desc: Abnormal testcase of CacheResultSet, if CacheResultSet is Empty * @tc.type: FUNC */ HWTEST_F(RdbStepResultSetTest, Invalid_TableName, TestSize.Level1) { - auto sql = "create table if not exists 'table_-1' (id INTEGER PRIMARY KEY AUTOINCREMENT)"; + auto sql = "create table if not exists 'test_name' (id INTEGER PRIMARY KEY AUTOINCREMENT)"; auto ret = store->ExecuteSql(sql); EXPECT_EQ(E_OK, ret); int64_t rowId = 0; ValuesBucket bucket{}; bucket.Put("id", 1); - ret = store->Insert(rowId, "'table_-1'", bucket); + ret = store->Insert(rowId, "test_name", bucket); EXPECT_EQ(E_OK, ret); EXPECT_EQ(rowId, 1); - AbsRdbPredicates predicates("table_-1"); + AbsRdbPredicates predicates("test_name where id = 1"); auto resultSet = store->Query(predicates, {}); EXPECT_NE(resultSet, nullptr); auto rowCount = 0; diff --git a/relational_store/test/native/rdb/unittest/rdb_store_backup_restore_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_backup_restore_test.cpp index 67efdc0a552b58927429a7ecb32371d9ed14e514..f41531b7320b7eff5aaa6452631ad8f9d8869861 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_backup_restore_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_backup_restore_test.cpp @@ -320,7 +320,7 @@ HWTEST_F(RdbStoreBackupRestoreTest, Rdb_BackupRestoreTest_005, TestSize.Level2) store = nullptr; CorruptDoubleWriteStore(); store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); + ASSERT_EQ(errCode, E_OK); int deletedRows = 0; ret = store->Delete(deletedRows, "test", "id = 1"); diff --git a/relational_store/test/native/rdb/unittest/rdb_store_config_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_config_test.cpp index ecdbac62214a870f9a215e05c687faec8177889e..3f9b3250e31d5059db97bcb488cba6717e7751ca 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_config_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_config_test.cpp @@ -1276,4 +1276,37 @@ HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_038, TestSize.Level2) resultSet1->GoToNextRow(); resultSet1->GetString(1, strValue1); EXPECT_EQ(strValue1, "张三"); +} + +/* * + * @tc.name: RdbStoreConfigGetEnableSemanticIndex_001 + * @tc.desc: test RdbStoreConfigGetEnableSemanticIndex + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_039, TestSize.Level2) +{ + const std::string dbPath = RDB_TEST_PATH + "config_test.db"; + RdbStoreConfig config(dbPath); + + bool ret = config.GetEnableSemanticIndex(); + EXPECT_EQ(ret, false); +} + +/* * + * @tc.name: RdbStoreConfigSetEnableSemanticIndex_001 + * @tc.desc: test RdbStoreConfigSetEnableSemanticIndex + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_040, TestSize.Level2) +{ + const std::string dbPath = RDB_TEST_PATH + "config_test.db"; + RdbStoreConfig config(dbPath); + + bool enableSemanticIndex = true; + config.SetEnableSemanticIndex(enableSemanticIndex); + EXPECT_EQ(enableSemanticIndex, config.GetEnableSemanticIndex()); + + enableSemanticIndex = false; + config.SetEnableSemanticIndex(enableSemanticIndex); + EXPECT_EQ(enableSemanticIndex, config.GetEnableSemanticIndex()); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_store_impl_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_impl_test.cpp index 1ee2e704eb76f6ba5c5136e397884ce86784d0ed..fa47f70ee38b9886b738f003e94187a9da0b56cc 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_impl_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_impl_test.cpp @@ -20,16 +20,17 @@ #include #include -#include "types.h" -#include "single_kvstore.h" -#include "distributed_kv_data_manager.h" #include "common.h" +#include "distributed_kv_data_manager.h" +#include "grd_api_manager.h" #include "rdb_errno.h" #include "rdb_helper.h" #include "rdb_open_callback.h" #include "relational_store_delegate.h" #include "relational_store_manager.h" +#include "single_kvstore.h" #include "sqlite_connection.h" +#include "types.h" using namespace testing::ext; using namespace OHOS::NativeRdb; @@ -491,6 +492,34 @@ HWTEST_F(RdbStoreImplTest, Rdb_SqlitConnectionTest_001, TestSize.Level2) EXPECT_NE(nullptr, connection); } +/** + * @tc.name: Rdb_RdConnectionTest_001 + * @tc.desc: The testCase of vector database for replica. + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, Rdb_RdConnectionTest_001, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + const std::string databaseName = RDB_TEST_PATH + "RdConnectionOpenTest.db"; + RdbStoreConfig config(databaseName); + config.SetDBType(OHOS::NativeRdb::DBType::DB_VECTOR); + RdbStoreImplTestOpenCallback helper; + int openErr = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, openErr); + EXPECT_EQ(E_OK, openErr); + + auto [errCode, connection] = Connection::Create(config, true); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(connection, nullptr); + auto [err, statement] = connection->CreateReplicaStatement("test", connection); + EXPECT_EQ(err, E_NOT_SUPPORT); + EXPECT_EQ(statement, nullptr); + EXPECT_EQ(connection->CheckReplicaForRestore(), E_NOT_SUPPORT); + RdbHelper::DeleteRdbStore(databaseName); +} + /* * * @tc.name: Rdb_ConnectionPoolTest_001 * @tc.desc: Abnormal testCase for ConfigLocale @@ -516,7 +545,7 @@ HWTEST_F(RdbStoreImplTest, Rdb_ConnectionPoolTest_001, TestSize.Level2) auto connection = connectionPool->AcquireConnection(true); EXPECT_NE(nullptr, connection); errCode = connectionPool->ConfigLocale("AbnormalTest"); - EXPECT_EQ(OHOS::NativeRdb::E_DATABASE_BUSY, errCode); + EXPECT_EQ(OHOS::NativeRdb::E_INVALID_ARGS_NEW, errCode); store = nullptr; RdbHelper::DeleteRdbStore(DATABASE_NAME); @@ -584,7 +613,7 @@ HWTEST_F(RdbStoreImplTest, Rdb_ConnectionPoolTest_0023, TestSize.Level2) // newPath == currentPath, writeConnectionUsed == true auto connection = connectionPool->AcquireConnection(false); - SlaveStatus curStatus; + std::shared_ptr curStatus = std::make_shared(SlaveStatus::UNDEFINED); errCode = connectionPool->ChangeDbFileForRestore(newPath, backupPath, newKey, curStatus); EXPECT_EQ(E_ERROR, errCode); connection = nullptr; @@ -597,6 +626,58 @@ HWTEST_F(RdbStoreImplTest, Rdb_ConnectionPoolTest_0023, TestSize.Level2) EXPECT_EQ(E_ERROR, errCode); } +/* * + * @tc.name: Rdb_ConnectionPoolTest_004 + * @tc.desc: Abnormal testCase for ReopenConns + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, Rdb_ConnectionPoolTest_004, TestSize.Level2) +{ + const std::string databaseName = RDB_TEST_PATH + "ConnectionTest004.db"; + int errCode = E_OK; + RdbStoreConfig config(databaseName); + config.SetReadConSize(1); + config.SetStorageMode(StorageMode::MODE_DISK); + auto connectionPool = ConnectionPool::Create(config, errCode); + ASSERT_NE(nullptr, connectionPool); + EXPECT_EQ(E_OK, errCode); + + config.SetReadConSize(65); + EXPECT_NE(E_OK, connectionPool->ReopenConns()); +} + +/* * + * @tc.name: Rdb_ConnectionPoolTest_005 + * @tc.desc: Abnormal repair when pool create fails + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, Rdb_ConnectionPoolTest_005, TestSize.Level2) +{ + const std::string databaseName = RDB_TEST_PATH + "ConnectionTest005.db"; + RdbHelper::DeleteRdbStore(databaseName); + int errCode = E_OK; + RdbStoreConfig config(databaseName); + config.SetReadConSize(1); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetHaMode(HAMode::MAIN_REPLICA); + + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + store->ExecuteSql(CREATE_TABLE_TEST); + store = nullptr; + + auto connectionPool = ConnectionPool::Create(config, errCode); + ASSERT_NE(nullptr, connectionPool); + EXPECT_EQ(E_OK, errCode); + auto connection = connectionPool->AcquireConnection(false); + ASSERT_NE(nullptr, connection); + + config.SetReadConSize(128); + EXPECT_EQ(E_OK, connection->Repair(config)); + RdbHelper::DeleteRdbStore(databaseName); +} + HWTEST_F(RdbStoreImplTest, NotifyDataChangeTest_001, TestSize.Level2) { const std::string DATABASE_NAME = RDB_TEST_PATH + "SqlitConnectionOpenTest.db"; @@ -1079,13 +1160,13 @@ HWTEST_F(RdbStoreImplTest, CreateTransaction_004, TestSize.Level1) } /* * - * @tc.name: BatchInsertWithConflictResolution_001 - * @tc.desc: BatchInsertWithConflictResolution when violation the unique constraint. + * @tc.name: BatchInsert_001 + * @tc.desc: BatchInsert when violation the unique constraint. * @tc.type: FUNC */ -HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_001, TestSize.Level1) +HWTEST_F(RdbStoreImplTest, BatchInsert_001, TestSize.Level1) { - std::string tableName = "BatchInsertWithConflictResolutionTest"; + std::string tableName = "BatchInsertTest"; store_->Execute("DROP TABLE IF EXISTS " + tableName); auto res = store_->Execute("CREATE TABLE " + tableName + " (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)"); @@ -1104,27 +1185,27 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_001, TestSize.Level auto result = store_->Insert(tableName, row); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 5); @@ -1136,13 +1217,13 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_001, TestSize.Level } /* * - * @tc.name: BatchInsertWithConflictResolution_002 - * @tc.desc: BatchInsertWithConflictResolution when violation the not null constraint. + * @tc.name: BatchInsert_002 + * @tc.desc: BatchInsert when violation the not null constraint. * @tc.type: FUNC */ -HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_002, TestSize.Level1) +HWTEST_F(RdbStoreImplTest, BatchInsert_002, TestSize.Level1) { - std::string tableName = "BatchInsertWithConflictResolutionTest"; + std::string tableName = "BatchInsertTest"; store_->Execute("DROP TABLE IF EXISTS " + tableName); auto res = store_->Execute("CREATE TABLE " + tableName + " (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)"); @@ -1155,27 +1236,27 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_002, TestSize.Level row.Put("name", i == 2 ? ValueObject() : "Jim"); rows.Put(row); } - auto result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); @@ -1187,13 +1268,13 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_002, TestSize.Level } /* * - * @tc.name: BatchInsertWithConflictResolution_003 - * @tc.desc: BatchInsertWithConflictResolution when violation the PRIMARY constraint. + * @tc.name: BatchInsert_003 + * @tc.desc: BatchInsert when violation the PRIMARY constraint. * @tc.type: FUNC */ -HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_003, TestSize.Level1) +HWTEST_F(RdbStoreImplTest, BatchInsert_003, TestSize.Level1) { - std::string tableName = "BatchInsertWithConflictResolutionTest"; + std::string tableName = "BatchInsertTest"; store_->Execute("DROP TABLE IF EXISTS " + tableName); auto res = store_->Execute("CREATE TABLE " + tableName + " (id TEXT PRIMARY KEY, name TEXT NOT NULL)"); @@ -1212,27 +1293,27 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_003, TestSize.Level auto result = store_->Insert(tableName, row); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 5); @@ -1244,13 +1325,13 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_003, TestSize.Level } /* * - * @tc.name: BatchInsertWithConflictResolution_004 - * @tc.desc: BatchInsertWithConflictResolution when violation the check constraint. + * @tc.name: BatchInsert_004 + * @tc.desc: BatchInsert when violation the check constraint. * @tc.type: FUNC */ -HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_004, TestSize.Level1) +HWTEST_F(RdbStoreImplTest, BatchInsert_004, TestSize.Level1) { - std::string tableName = "BatchInsertWithConflictResolutionTest"; + std::string tableName = "BatchInsertTest"; store_->Execute("DROP TABLE IF EXISTS " + tableName); auto res = store_->Execute( "CREATE TABLE " + tableName + " (id INTEGER PRIMARY KEY CHECK (id >= 3 OR id <= 1), name TEXT NOT NULL)"); @@ -1263,27 +1344,27 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_004, TestSize.Level row.Put("name", "Jim"); rows.Put(row); } - auto result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); @@ -1295,13 +1376,13 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_004, TestSize.Level } /* * - * @tc.name: BatchInsertWithConflictResolution_005 - * @tc.desc: BatchInsertWithConflictResolution when busy. + * @tc.name: BatchInsert_005 + * @tc.desc: BatchInsert when busy. * @tc.type: FUNC */ -HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_005, TestSize.Level1) +HWTEST_F(RdbStoreImplTest, BatchInsert_005, TestSize.Level1) { - std::string tableName = "BatchInsertWithConflictResolutionTest"; + std::string tableName = "BatchInsertTest"; store_->Execute("DROP TABLE IF EXISTS " + tableName); auto res = store_->Execute( "CREATE TABLE " + tableName + " (id INTEGER PRIMARY KEY CHECK (id >= 3 OR id <= 1), name TEXT NOT NULL)"); @@ -1318,27 +1399,27 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_005, TestSize.Level row.Put("name", "Jim"); rows.Put(row); } - auto result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); @@ -1350,13 +1431,13 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_005, TestSize.Level } /* * - * @tc.name: BatchInsertWithConflictResolution_006 - * @tc.desc: Normal BatchInsertWithConflictResolution. + * @tc.name: BatchInsert_006 + * @tc.desc: Normal BatchInsert. * @tc.type: FUNC */ -HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_006, TestSize.Level1) +HWTEST_F(RdbStoreImplTest, BatchInsert_006, TestSize.Level1) { - std::string tableName = "BatchInsertWithConflictResolutionTest"; + std::string tableName = "BatchInsertTest"; store_->Execute("DROP TABLE IF EXISTS " + tableName); auto res = store_->Execute("CREATE TABLE " + tableName + " (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)"); @@ -1364,15 +1445,15 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_006, TestSize.Level ValuesBuckets rows; - auto result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 0); for (int i = 0; i < 5; i++) { @@ -1381,15 +1462,15 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_006, TestSize.Level rows.Put(row); } - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 5); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 5); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 5); @@ -1401,13 +1482,13 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_006, TestSize.Level } /* * - * @tc.name: BatchInsertWithConflictResolution_007 - * @tc.desc: over limit params BatchInsertWithConflictResolution. + * @tc.name: BatchInsert_007 + * @tc.desc: over limit params BatchInsert. * @tc.type: FUNC */ -HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_007, TestSize.Level1) +HWTEST_F(RdbStoreImplTest, BatchInsert_007, TestSize.Level1) { - std::string tableName = "BatchInsertWithConflictResolutionTest"; + std::string tableName = "BatchInsertTest"; store_->Execute("DROP TABLE IF EXISTS " + tableName); auto res = store_->Execute("CREATE TABLE " + tableName + " (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)"); @@ -1422,27 +1503,27 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_007, TestSize.Level row.Put("name", "Jim"); rows.Put(row); } - auto result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); @@ -1545,4 +1626,214 @@ HWTEST_F(RdbStoreImplTest, RdbStore_Crypt_001, TestSize.Level1) rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); EXPECT_EQ(errCode, E_SQLITE_CORRUPT); -} \ No newline at end of file +} + +/** + * @tc.name: RdbStore_ClearDirtyLog_001 + * @tc.desc: test RdbStore ClearDirtyLog + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, RdbStore_ClearDirtyLog_001, TestSize.Level1) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME); + config.SetBundleName(""); + config.SetEnableSemanticIndex(true); + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + ASSERT_NE(store, nullptr); + errCode = store->ExecuteSql(CREATE_TABLE_TEST); + EXPECT_EQ(errCode, E_OK); + errCode = store->CleanDirtyLog("test", 0); + EXPECT_EQ(errCode, E_OK); + errCode = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(errCode, E_OK); +} + +/** + * @tc.name: RdbStore_ConfigLocale_001 + * @tc.desc: test RdbStore ConfigLocale + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, RdbStore_ConfigLocale_001, TestSize.Level1) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME); + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + ASSERT_NE(store, nullptr); + errCode = store->ExecuteSql("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, " + "data2 INTEGER);"); + EXPECT_EQ(errCode, E_OK); + errCode = store->ConfigLocale("111"); + EXPECT_EQ(errCode, E_INVALID_ARGS_NEW); + int64_t id; + ValuesBucket valuesBucket; + valuesBucket.PutString("data1", "张三"); + valuesBucket.PutInt("data2", 20); + errCode = store->Insert(id, "test1", valuesBucket); + EXPECT_EQ(errCode, E_OK); + + ValuesBucket valuesBucket1; + valuesBucket1.PutString("data1", "李四"); + valuesBucket1.PutInt("data2", 20); + errCode = store->Insert(id, "test1", valuesBucket1); + EXPECT_EQ(errCode, E_OK); + + std::vector columns; + AbsRdbPredicates predicates("test1"); + predicates.OrderByAsc("data1 COLLATE LOCALES"); + std::shared_ptr resultSet = store->Query(predicates, columns); + ASSERT_NE(resultSet, nullptr); + std::string strValue; + errCode = resultSet->GoToNextRow(); + EXPECT_EQ(errCode, E_SQLITE_ERROR); + errCode = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(errCode, E_OK); +} + +/** + * @tc.name: RdbStore_ConfigLocale_002 + * @tc.desc: test RdbStore ConfigLocale + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, RdbStore_ConfigLocale_002, TestSize.Level1) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME); + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + ASSERT_NE(store, nullptr); + errCode = store->ExecuteSql("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, " + "data2 INTEGER);"); + EXPECT_EQ(errCode, E_OK); + errCode = store->ConfigLocale("zh"); + EXPECT_EQ(errCode, E_OK); + + int64_t id; + ValuesBucket valuesBucket; + valuesBucket.PutString("data1", "张三"); + valuesBucket.PutInt("data2", 20); + errCode = store->Insert(id, "test1", valuesBucket); + + ValuesBucket valuesBucket1; + valuesBucket1.PutString("data1", "李四"); + valuesBucket1.PutInt("data2", 20); + errCode = store->Insert(id, "test1", valuesBucket1); + EXPECT_EQ(errCode, E_OK); + + std::vector columns; + AbsRdbPredicates predicates("test1"); + predicates.OrderByAsc("data1 COLLATE LOCALES"); + std::shared_ptr resultSet = store->Query(predicates, columns); + ASSERT_NE(nullptr, resultSet); + std::string strValue; + resultSet->GoToNextRow(); + resultSet->GetString(1, strValue); + EXPECT_EQ(strValue, "李四"); + + resultSet->GoToNextRow(); + resultSet->GetString(1, strValue); + EXPECT_EQ(strValue, "张三"); + errCode = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(errCode, E_OK); +} + +/** + * @tc.name: RdbStore_ConfigLocale_003 + * @tc.desc: test RdbStore ConfigLocale + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, RdbStore_ConfigLocale_003, TestSize.Level1) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME); + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + ASSERT_NE(store, nullptr); + errCode = store->ExecuteSql("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, " + "data2 INTEGER);"); + EXPECT_EQ(errCode, E_OK); + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + EXPECT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + errCode = store->ConfigLocale("zh"); + EXPECT_EQ(errCode, E_OK); + + ValuesBucket valuesBucket; + valuesBucket.PutString("data1", "张三"); + valuesBucket.PutInt("data2", 20); + auto result = transaction->Insert("test1", valuesBucket); + EXPECT_EQ(result.first, E_OK); + ValuesBucket valuesBucket1; + valuesBucket1.PutString("data1", "李四"); + valuesBucket1.PutInt("data2", 20); + result = transaction->Insert("test1", valuesBucket1); + EXPECT_EQ(result.first, E_OK); + std::vector columns; + AbsRdbPredicates predicates("test1"); + predicates.OrderByAsc("data1 COLLATE LOCALES"); + auto resultSet = transaction->QueryByStep("SELECT * FROM test1 order by data1 COLLATE LOCALES");; + ASSERT_NE(nullptr, resultSet); + std::string strValue; + resultSet->GoToNextRow(); + resultSet->GetString(1, strValue); + EXPECT_EQ(strValue, "李四"); + + resultSet->GoToNextRow(); + resultSet->GetString(1, strValue); + EXPECT_EQ(strValue, "张三"); + errCode = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(errCode, E_OK); +} +/** + * @tc.name: RdbStore_InitKnowledgeSchema_001 + * @tc.desc: test RdbStore InitKnowledgeSchema + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, RdbStore_InitKnowledgeSchema_001, TestSize.Level1) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME); + config.SetBundleName(""); + config.SetEnableSemanticIndex(true); + OHOS::DistributedRdb::RdbKnowledgeSchema schema; + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + ASSERT_NE(store, nullptr); + + errCode = store->InitKnowledgeSchema(schema); + EXPECT_EQ(errCode, E_OK); +} + +/** + * @tc.name: RdbStore_InitKnowledgeSchema_002 + * @tc.desc: test RdbStore SetKnowledgeSchema when create table + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, RdbStore_InitKnowledgeSchema_002, TestSize.Level1) +{ + store_ = nullptr; + int errCode = RdbHelper::DeleteRdbStore(DATABASE_NAME); + EXPECT_EQ(E_OK, errCode); + + RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME); + config.SetBundleName(""); + config.SetEnableSemanticIndex(true); + OHOS::DistributedRdb::RdbKnowledgeSchema schema; + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + ASSERT_NE(store, nullptr); + + std::pair ret = store->Execute(std::string(CREATE_TABLE_TEST)); + ASSERT_EQ(ret.first, E_OK); + + ret = store->Execute(std::string(CREATE_TABLE_TEST)); + ASSERT_EQ(ret.first, E_OK); +} diff --git a/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp index 71f4495c836e0f7b68da6f3037cd0afa31c2d3ba..8c28ac409f08d10071bc00ce8dd5b42d3a44ef10 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp @@ -12,18 +12,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#define LOG_TAG "RdbRekeyTest" #include #include #include #include +#include #include #include #include +#include +#include "block_data.h" #include "common.h" #include "file_ex.h" +#include "logger.h" #include "rdb_errno.h" #include "rdb_helper.h" #include "rdb_open_callback.h" @@ -32,6 +36,7 @@ using namespace testing::ext; using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; class RdbRekeyTest : public testing::Test { public: static void SetUpTestCase(); @@ -130,7 +135,7 @@ std::chrono::system_clock::time_point RdbRekeyTest::GetKeyFileDate(const std::st { std::chrono::system_clock::time_point timePoint; std::string name = RemoveSuffix(dbName); - auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key"; + auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key_v1"; if (!OHOS::FileExists(keyPath)) { return timePoint; } @@ -151,7 +156,7 @@ std::chrono::system_clock::time_point RdbRekeyTest::GetKeyFileDate(const std::st bool RdbRekeyTest::ChangeKeyFileDate(const std::string &dbName, int rep) { std::string name = RemoveSuffix(dbName); - auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key"; + auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key_v1"; if (!OHOS::FileExists(keyPath)) { return false; } @@ -172,7 +177,7 @@ bool RdbRekeyTest::ChangeKeyFileDate(const std::string &dbName, int rep) bool RdbRekeyTest::SaveNewKey(const string &dbName) { std::string name = RemoveSuffix(dbName); - auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key"; + auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key_v1"; auto newKeyPath = RDB_TEST_PATH + "key/" + name + ".pub_key.new"; if (!OHOS::FileExists(keyPath)) { return false; @@ -251,7 +256,7 @@ void RdbRekeyTest::CheckQueryData(std::shared_ptr &store) */ HWTEST_F(RdbRekeyTest, Rdb_Rekey_01, TestSize.Level1) { - std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key.new"; bool isFileExists = OHOS::FileExists(keyPath); @@ -260,9 +265,6 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_01, TestSize.Level1) bool isFileDateChanged = ChangeKeyFileDate(encryptedDatabaseName, RdbRekeyTest::HOURS_EXPIRED); ASSERT_TRUE(isFileDateChanged); - auto changedDate = GetKeyFileDate(encryptedDatabaseName); - ASSERT_TRUE(std::chrono::system_clock::now() - changedDate > std::chrono::hours(RdbRekeyTest::HOURS_EXPIRED)); - RdbStoreConfig config = GetRdbConfig(RdbRekeyTest::encryptedDatabasePath); RekeyTestOpenCallback helper; int errCode = E_OK; @@ -275,8 +277,6 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_01, TestSize.Level1) isFileExists = OHOS::FileExists(newKeyPath); ASSERT_FALSE(isFileExists); - auto newDate = GetKeyFileDate(encryptedDatabaseName); - ASSERT_TRUE(std::chrono::system_clock::now() - newDate < std::chrono::seconds(2)); CheckQueryData(store); } @@ -287,7 +287,7 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_01, TestSize.Level1) */ HWTEST_F(RdbRekeyTest, Rdb_Rekey_02, TestSize.Level1) { - std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; bool isFileExists = OHOS::FileExists(keyPath); ASSERT_TRUE(isFileExists); @@ -313,7 +313,7 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_02, TestSize.Level1) */ HWTEST_F(RdbRekeyTest, Rdb_Rekey_03, TestSize.Level1) { - std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key.new"; bool isFileExists = OHOS::FileExists(keyPath); @@ -344,20 +344,15 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_03, TestSize.Level1) */ HWTEST_F(RdbRekeyTest, Rdb_Rekey_04, TestSize.Level1) { - std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key.new"; bool isFileExists = OHOS::FileExists(keyPath); ASSERT_TRUE(isFileExists); - auto keyFileDate = GetKeyFileDate(encryptedDatabaseName); - bool isFileDateChanged = ChangeKeyFileDate(encryptedDatabaseName, -RdbRekeyTest::HOURS_EXPIRED); ASSERT_TRUE(isFileDateChanged); - auto changedDate = GetKeyFileDate(encryptedDatabaseName); - ASSERT_GT(changedDate, keyFileDate); - RdbStoreConfig config = GetRdbConfig(RdbRekeyTest::encryptedDatabasePath); RekeyTestOpenCallback helper; int errCode; @@ -369,9 +364,6 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_04, TestSize.Level1) isFileExists = OHOS::FileExists(newKeyPath); ASSERT_FALSE(isFileExists); - keyFileDate = GetKeyFileDate(encryptedDatabaseName); - ASSERT_EQ(changedDate, keyFileDate); - CheckQueryData(store); } @@ -382,20 +374,15 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_04, TestSize.Level1) */ HWTEST_F(RdbRekeyTest, Rdb_Rekey_RenameFailed_05, TestSize.Level1) { - std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key.new"; bool isFileExists = OHOS::FileExists(keyPath); ASSERT_TRUE(isFileExists); - auto keyFileDate = GetKeyFileDate(encryptedDatabaseName); - bool isFileDateChanged = ChangeKeyFileDate(encryptedDatabaseName, RdbRekeyTest::HOURS_LONG_LONG_AGO); ASSERT_TRUE(isFileDateChanged); - auto changedDate = GetKeyFileDate(encryptedDatabaseName); - ASSERT_GT(keyFileDate, changedDate); - RdbStoreConfig config = GetRdbConfig(RdbRekeyTest::encryptedDatabasePath); RekeyTestOpenCallback helper; int errCode = E_OK; @@ -418,7 +405,7 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_RenameFailed_05, TestSize.Level1) */ HWTEST_F(RdbRekeyTest, Rdb_Rekey_06, TestSize.Level1) { - std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key.new"; bool isFileExists = OHOS::FileExists(keyPath); @@ -464,7 +451,7 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_07, TestSize.Level1) ASSERT_NE(store, nullptr); ASSERT_EQ(errCode, E_OK); - std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; bool isFileExists = OHOS::FileExists(keyPath); ASSERT_TRUE(isFileExists); struct stat fileStat; @@ -510,7 +497,7 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_08, TestSize.Level1) ASSERT_NE(store, nullptr); ASSERT_EQ(errCode, E_OK); - std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; bool isFileExists = OHOS::FileExists(keyPath); ASSERT_TRUE(isFileExists); struct stat fileStat; @@ -536,4 +523,677 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_08, TestSize.Level1) } ASSERT_EQ(inodeNumber1, inodeNumber2); +} + +/** +** +* @tc.name: Rdb_Delete_Rekey_Test_009 +* @tc.desc: test rekey the encrypted database +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_009, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetAllowRebuild(false); + config.SetEncryptStatus(true); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"); + + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + RdbStoreConfig::CryptoParam cryptoParam1; + cryptoParam1.iterNum = -1; + errCode = store->Rekey(cryptoParam1); + ASSERT_EQ(errCode, E_INVALID_ARGS_NEW); + + RdbStoreConfig::CryptoParam cryptoParam2; + cryptoParam2.encryptAlgo = -1; + errCode = store->Rekey(cryptoParam2); + ASSERT_EQ(errCode, E_INVALID_ARGS_NEW); + + RdbStoreConfig::CryptoParam cryptoParam3; + cryptoParam3.hmacAlgo = -1; + errCode = store->Rekey(cryptoParam3); + ASSERT_EQ(errCode, E_INVALID_ARGS_NEW); + + RdbStoreConfig::CryptoParam cryptoParam4; + cryptoParam4.kdfAlgo = -1; + errCode = store->Rekey(cryptoParam4); + ASSERT_EQ(errCode, E_INVALID_ARGS_NEW); + + RdbStoreConfig::CryptoParam cryptoParam5; + cryptoParam5.cryptoPageSize = -1; + errCode = store->Rekey(cryptoParam5); + ASSERT_EQ(errCode, E_INVALID_ARGS_NEW); + + values.Clear(); + values.PutInt("id", 2); + values.PutString("name", std::string("lisi")); + values.PutInt("age", 19); + ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_010 +* @tc.desc: test rekey the encrypted database +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_010, TestSize.Level1) +{ + const std::string encryptedDatabaseName1 = "encrypted1.db"; + const std::string encryptedDatabasePath1 = RDB_TEST_PATH + encryptedDatabaseName1; + RdbStoreConfig config(encryptedDatabasePath1); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"); + + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan1")); + values.PutInt("age", 50); + values.PutDouble("salary", 263); + values.PutBlob("blobType", std::vector{ 1, 2, 3, 4, 5}); + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + RdbStoreConfig::CryptoParam cryptoParam; + auto isEncrypt = config.IsEncrypt(); + ASSERT_EQ(isEncrypt, false); + errCode = store->Rekey(cryptoParam); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + cryptoParam.encryptKey_ = std::vector{ 1, 2, 3, 4, 5, 6 }; + errCode = store->Rekey(cryptoParam); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + values.Clear(); + values.PutInt("id", 2); + values.PutString("name", std::string("lisi1")); + values.PutInt("age", 191); + values.PutDouble("salary", 2001.5); + values.PutBlob("blobType", std::vector{ 4, 5, 6, 7 }); + ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + + auto resultSet = store->QueryByStep("SELECT * FROM test1"); + ASSERT_NE(resultSet, nullptr); + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + ASSERT_EQ(rowCount, 2); + + ret = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_011 +* @tc.desc: test rekey other parameters +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_011, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetBundleName("com.example.test_rekey"); + config.SetEncryptStatus(true); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"); + + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("1zhangsan")); + values.PutInt("age", 118); + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + RdbStoreConfig::CryptoParam cryptoParam1; + cryptoParam1.iterNum = 500; + errCode = store->Rekey(cryptoParam1); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + RdbStoreConfig::CryptoParam cryptoParam2; + cryptoParam2.encryptAlgo = EncryptAlgo::AES_256_CBC; + errCode = store->Rekey(cryptoParam2); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + RdbStoreConfig::CryptoParam cryptoParam3; + cryptoParam3.hmacAlgo = HmacAlgo::SHA512; + errCode = store->Rekey(cryptoParam3); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + RdbStoreConfig::CryptoParam cryptoParam4; + cryptoParam4.kdfAlgo = KdfAlgo::KDF_SHA512; + errCode = store->Rekey(cryptoParam4); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + RdbStoreConfig::CryptoParam cryptoParam5; + cryptoParam5.cryptoPageSize = 2048; + errCode = store->Rekey(cryptoParam5); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + ret = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_12 +* @tc.desc: test custom encrypt rekey +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_012, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetEncryptStatus(true); + RdbStoreConfig::CryptoParam cryptoParam; + cryptoParam.encryptKey_ = std::vector{ 1, 2, 3, 4, 5, 6 }; + config.SetCryptoParam(cryptoParam); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"); + + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + RdbStoreConfig::CryptoParam newCryptoParam; + newCryptoParam.encryptKey_ = std::vector{ 6, 2, 3, 4, 5, 1 }; + errCode = store->Rekey(newCryptoParam); + ASSERT_EQ(errCode, E_OK); + + values.Clear(); + values.PutInt("id", 2); + values.PutString("name", std::string("lisi")); + values.PutInt("age", 19); + ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + + store = nullptr; + config.SetCryptoParam(newCryptoParam); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + auto resultSet = store->QueryByStep("SELECT * FROM test1"); + ASSERT_NE(resultSet, nullptr); + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + ASSERT_EQ(rowCount, 2); + + RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); +} + + +/** +* @tc.name: Rdb_Delete_Rekey_Test_013 +* @tc.desc: test rekey +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_013, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetEncryptStatus(true); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"); + + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + int changedRows; + values.Clear(); + values.PutInt("age", 30); + ret = store->Update(changedRows, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, changedRows); + + RdbStoreConfig::CryptoParam cryptoParam; + cryptoParam.encryptKey_ = std::vector{ 1, 2, 3, 4, 5, 6 }; + errCode = store->Rekey(cryptoParam); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + values.Clear(); + values.PutInt("id", 2); + values.PutString("name", std::string("lisi")); + values.PutInt("age", 19); + ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + + values.Clear(); + values.PutInt("age", 60); + ret = store->Update(changedRows, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, changedRows); + + ret = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_014 +* @tc.desc: test rekey +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_014, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetEncryptStatus(true); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"); + + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + RdbStoreConfig::CryptoParam cryptoParam; + errCode = store->Rekey(cryptoParam); + ASSERT_EQ(errCode, E_OK); + + values.Clear(); + values.PutInt("id", 2); + values.PutString("name", std::string("lisi")); + values.PutInt("age", 19); + ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + + int changedRows = 0; + AbsRdbPredicates predicates("test1"); + predicates.EqualTo("id", 1); + ret = store->Delete(changedRows, predicates); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(changedRows, 1); + + store = nullptr; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + auto resultSet = store->QueryByStep("SELECT * FROM test1"); + ASSERT_NE(resultSet, nullptr); + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + ASSERT_EQ(rowCount, 1); +} + + +/** +* @tc.name: Rdb_Delete_Rekey_Test_015 +* @tc.desc: test rekey +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_015, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetEncryptStatus(true); + RdbStoreConfig::CryptoParam cryptoParam; + cryptoParam.encryptKey_ = std::vector{ 1, 2, 3, 4, 5, 6 }; + config.SetCryptoParam(cryptoParam); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + RdbHelper::DeleteRdbStore(config); + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"); + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + RdbStoreConfig::CryptoParam newCryptoParam; + errCode = store->Rekey(newCryptoParam); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + values.Clear(); + values.PutInt("id", 2); + values.PutString("name", std::string("lisi")); + values.PutInt("age", 19); + ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + + store = nullptr; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + auto resultSet = store->QueryByStep("SELECT * FROM test1"); + ASSERT_NE(resultSet, nullptr); + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + ASSERT_EQ(rowCount, 2); + + RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_016 +* @tc.desc: test transaction rekey +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_016, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetAllowRebuild(false); + config.SetEncryptStatus(true); + RdbStoreConfig::CryptoParam cryptoParam; + cryptoParam.encryptKey_ = std::vector{ 1, 2, 3, 4, 5, 6 }; + config.SetCryptoParam(cryptoParam); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + RdbHelper::DeleteRdbStore(config); + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"); + + auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + ASSERT_EQ(result.first, E_OK); + ASSERT_EQ(1, result.second); + + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; + bool isFileExists = OHOS::FileExists(keyPath); + ASSERT_FALSE(isFileExists); + + RdbStoreConfig::CryptoParam newCryptoParam; + newCryptoParam.encryptKey_ = std::vector{ 6, 5, 4, 3, 2, 1 }; + errCode = store->Rekey(newCryptoParam); + ASSERT_EQ(errCode, E_DATABASE_BUSY); + + result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ASSERT_EQ(result.first, E_OK); + ASSERT_EQ(2, result.second); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + ASSERT_NE(resultSet, nullptr); + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + ASSERT_EQ(rowCount, 2); + + ret = transaction->Commit(); + ASSERT_EQ(ret, E_OK); + + resultSet = store->QueryByStep("SELECT * FROM test"); + ASSERT_NE(resultSet, nullptr); + resultSet->GetRowCount(rowCount); + EXPECT_EQ(rowCount, 2); + + RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_017 +* @tc.desc: test transaction rekey +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_017, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetAllowRebuild(false); + config.SetEncryptStatus(true); + RdbStoreConfig::CryptoParam cryptoParam; + config.SetCryptoParam(cryptoParam); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + RdbHelper::DeleteRdbStore(config); + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + ASSERT_EQ(result.first, E_OK); + ASSERT_EQ(1, result.second); + + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; + bool isFileExists = OHOS::FileExists(keyPath); + ASSERT_TRUE(isFileExists); + + RdbStoreConfig::CryptoParam newCryptoParam; + errCode = store->Rekey(newCryptoParam); + ASSERT_EQ(errCode, E_DATABASE_BUSY); + + result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ASSERT_EQ(result.first, E_OK); + ASSERT_EQ(2, result.second); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + ASSERT_NE(resultSet, nullptr); + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + ASSERT_EQ(rowCount, 2); + + ret = transaction->Commit(); + ASSERT_EQ(ret, E_OK); + + resultSet = store->QueryByStep("SELECT * FROM test"); + ASSERT_NE(resultSet, nullptr); + resultSet->GetRowCount(rowCount); + EXPECT_EQ(rowCount, 2); + + RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_018 +* @tc.desc: rekey test +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_018, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetEncryptStatus(true); + config.SetReadOnly(true); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + RdbStoreConfig::CryptoParam cryptoParam1; + + errCode = store->Rekey(cryptoParam1); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + int ret = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_019 +* @tc.desc: mutltiThread rekey test +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_019, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + RdbStoreConfig::CryptoParam cryptoParam; + cryptoParam.encryptKey_ = std::vector{ 1, 2, 3, 4, 5, 6 }; + config.SetCryptoParam(cryptoParam); + config.SetBundleName("com.example.test_rekey"); + config.SetEncryptStatus(true); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + auto blockResult = std::make_shared>(3, false); + std::thread thread([store, blockResult]() { + RdbStoreConfig::CryptoParam cryptoParam; + cryptoParam.encryptKey_ = std::vector{ 6, 2, 3, 4, 5, 1 }; + int ret1 = store->Rekey(cryptoParam); + LOG_INFO("Rdb_Rekey_020 thread Rekey finish, code:%{public}d", ret1); + blockResult->SetValue(true); + }); + thread.detach(); + RdbStoreConfig::CryptoParam cryptoParam2; + cryptoParam2.encryptKey_ = std::vector{ 6, 5, 3, 4, 2, 1 }; + int ret2 = store->Rekey(cryptoParam2); + LOG_INFO("Rdb_Rekey_020 main Rekey finish, code:%{public}d", ret2); + EXPECT_TRUE(blockResult->GetValue()); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"); + + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan1")); + values.PutInt("age", 50); + values.PutDouble("salary", 263); + values.PutBlob("blobType", std::vector{ 1, 2, 3, 4, 5 }); + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + int changedRows; + values.Clear(); + values.PutInt("age", 30); + ret = store->Update(changedRows, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, changedRows); + + auto resultSet = store->QueryByStep("SELECT * FROM test1"); + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + ASSERT_EQ(rowCount, 1); +} + +/** +* @tc.name: Rdb_UnpackV2_Test_001 +* @tc.desc: unpackV2 test +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, UnpackV2Test, TestSize.Level1) +{ + RdbSecurityManager manager; + std::vector content; + auto result = manager.UnpackV2(content); + EXPECT_FALSE(result.first); + EXPECT_EQ(result.second.nonceValue.size(), 0); + EXPECT_EQ(result.second.encryptValue.size(), 0); + + uint32_t magicNum = RdbSecretContent::MAGIC_NUMBER_V2; + char* magicPtr = reinterpret_cast(&magicNum); + content.insert(content.end(), magicPtr, magicPtr + sizeof(magicNum)); + + const size_t nonceSize = RdbSecretContent::NONCE_VALUE_SIZE - 1; + std::vector nonce(nonceSize, 'N'); + content.insert(content.end(), nonce.begin(), nonce.end()); + + result = manager.UnpackV2(content); + + EXPECT_FALSE(result.first); + EXPECT_EQ(result.second.nonceValue.size(), 0); + EXPECT_EQ(result.second.encryptValue.size(), 0); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_store_subscribe_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_subscribe_test.cpp index debd883b5a9d0520ed4d40f58ba06b50ab35ede1..9f7c8097498024ef2f01e926ecb60dcaa5f15244 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_subscribe_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_subscribe_test.cpp @@ -17,6 +17,7 @@ #include #include +#include "block_data.h" #include "common.h" #include "rdb_errno.h" #include "rdb_helper.h" @@ -45,6 +46,22 @@ public: private: CheckOnChangeFunc checkOnChangeFunc_; }; +class LocalShareObserver : public RdbStoreObserver { +public: + explicit LocalShareObserver(std::function func) : callback_(func) + { + } + void OnChange(const std::vector &devices){}; + void OnChange() + { + if (callback_ != nullptr) { + callback_(); + } + }; + +private: + std::function callback_; +}; class StatisticsObserver : public SqlObserver { public: @@ -186,7 +203,6 @@ std::shared_ptr RdbStoreSubTest::CreateRDB(int version) Callback helper; int errCode = E_OK; std::shared_ptr store = RdbHelper::GetRdbStore(config, version, helper, errCode); - EXPECT_NE(store, nullptr); return store; } @@ -223,11 +239,11 @@ void RdbStoreSubTest::RegisterCheckUpdateCallback(const std::vectorSubscribe({ SubscribeMode::REMOTE, "observer" }, observer_.get()); + auto status = store->Subscribe({ SubscribeMode::REMOTE, "observer" }, observer_); EXPECT_EQ(status, E_OK); - status = store->UnSubscribe({ SubscribeMode::REMOTE, "observer" }, observer_.get()); + status = store->UnSubscribe({ SubscribeMode::REMOTE, "observer" }, observer_); EXPECT_EQ(status, E_OK); } @@ -240,11 +256,11 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeRemote, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeCloud, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; - auto status = store->Subscribe({ SubscribeMode::CLOUD, "observer" }, observer_.get()); + auto status = store->Subscribe({ SubscribeMode::CLOUD, "observer" }, observer_); EXPECT_EQ(status, E_OK); - status = store->UnSubscribe({ SubscribeMode::CLOUD, "observer" }, observer_.get()); + status = store->UnSubscribe({ SubscribeMode::CLOUD, "observer" }, observer_); EXPECT_EQ(status, E_OK); } @@ -257,11 +273,11 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeCloud, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeCloudDetail, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; - auto status = store->Subscribe({ SubscribeMode::CLOUD_DETAIL, "observer" }, observer_.get()); + auto status = store->Subscribe({ SubscribeMode::CLOUD_DETAIL, "observer" }, observer_); EXPECT_EQ(status, E_OK); - status = store->UnSubscribe({ SubscribeMode::CLOUD_DETAIL, "observer" }, observer_.get()); + status = store->UnSubscribe({ SubscribeMode::CLOUD_DETAIL, "observer" }, observer_); EXPECT_EQ(status, E_OK); } @@ -274,12 +290,12 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeCloudDetail, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocal, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; - auto status = store->Subscribe({ SubscribeMode::LOCAL, "observer1" }, observer_.get()); - store->Subscribe({ SubscribeMode::LOCAL, "observer1" }, observer_.get()); + auto status = store->Subscribe({ SubscribeMode::LOCAL, "observer1" }, observer_); + store->Subscribe({ SubscribeMode::LOCAL, "observer1" }, observer_); EXPECT_EQ(status, E_OK); - store->Subscribe({ SubscribeMode::LOCAL, "observer2" }, observer_.get()); + store->Subscribe({ SubscribeMode::LOCAL, "observer2" }, observer_); EXPECT_EQ(status, E_OK); status = store->Notify("observer1"); @@ -292,9 +308,9 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocal, TestSize.Level1) int count; resultSet->GetRowCount(count); EXPECT_EQ(observer_->count, count); - status = store->UnSubscribe({ SubscribeMode::LOCAL, "nonexistent" }, observer_.get()); + status = store->UnSubscribe({ SubscribeMode::LOCAL, "nonexistent" }, observer_); EXPECT_EQ(status, E_OK); - status = store->UnSubscribe({ SubscribeMode::LOCAL, "observer1" }, observer_.get()); + status = store->UnSubscribe({ SubscribeMode::LOCAL, "observer1" }, observer_); EXPECT_EQ(status, E_OK); status = store->UnSubscribe({ SubscribeMode::LOCAL, "nonexistent" }, nullptr); EXPECT_EQ(status, E_OK); @@ -305,25 +321,26 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocal, TestSize.Level1) } /** - * @tc.name: RdbStoreSubscribeLocalShared + * @tc.name: RdbStoreSubscribeLocalShared001 * @tc.desc: RdbStoreSubscribe * @tc.type: FUNC * @tc.require: * @tc.author: */ -HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared, TestSize.Level1) +HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared001, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; - auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer1" }, observer_.get()); - store->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer1" }, observer_.get()); + auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer1" }, observer_); + EXPECT_EQ(status, E_OK); + status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer1" }, observer_); EXPECT_EQ(status, E_OK); - store->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer2" }, observer_.get()); + status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer2" }, observer_); EXPECT_EQ(status, E_OK); - status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "nonexistent" }, observer_.get()); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "nonexistent" }, observer_); EXPECT_EQ(status, E_OK); - status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "observer1" }, observer_.get()); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "observer1" }, observer_); EXPECT_EQ(status, E_OK); status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "nonexistent" }, nullptr); EXPECT_EQ(status, E_OK); @@ -331,6 +348,181 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared, TestSize.Level1) EXPECT_EQ(status, E_OK); } +/** + * @tc.name: RdbStoreSubscribeLocalShared002 + * @tc.desc: RdbStoreSubscribe + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared002, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + auto block = std::make_shared>(5, false); + auto callback = [block]() { block->SetValue(true); }; + auto observer = std::make_shared(callback); + auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared002" }, observer); + EXPECT_EQ(status, E_OK); + status = store->Notify("RdbStoreSubscribeLocalShared002"); + EXPECT_EQ(status, E_OK); + EXPECT_TRUE(block->GetValue()); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared002" }, observer); +} + +/** + * @tc.name: RdbStoreSubscribeLocalShared003 + * @tc.desc: RdbStoreSubscribe + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared003, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + auto count = std::make_shared>(0); + auto callback = [count]() { count->fetch_add(1); }; + auto observer = std::make_shared(callback); + auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared003" }, observer); + EXPECT_EQ(status, E_OK); + status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared003" }, observer); + EXPECT_EQ(status, E_OK); + status = store->Notify("RdbStoreSubscribeLocalShared003"); + EXPECT_EQ(status, E_OK); + std::this_thread::sleep_for(std::chrono::seconds(3)); + EXPECT_EQ(count->load(), 1); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared003" }, observer); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbStoreSubscribeLocalShared004 + * @tc.desc: UnSubscribe all + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared004, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + auto count = std::make_shared>(0); + auto callback = [count]() { count->fetch_add(1); }; + auto observer1 = std::make_shared(callback); + auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared004" }, observer1); + EXPECT_EQ(status, E_OK); + auto observer2 = std::make_shared(callback); + status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared004" }, observer2); + EXPECT_EQ(status, E_OK); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared004" }, nullptr); + EXPECT_EQ(status, E_OK); + status = store->Notify("RdbStoreSubscribeLocalShared004"); + EXPECT_EQ(status, E_OK); + std::this_thread::sleep_for(std::chrono::seconds(3)); + EXPECT_EQ(count->load(), 0); +} + +/** + * @tc.name: RdbStoreSubscribeLocalShared005 + * @tc.desc: Subscribe after UnSubscribe + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared005, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + auto block = std::make_shared>(3, false); + auto callback = [block]() { block->SetValue(true); }; + auto observer = std::make_shared(callback); + auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared005" }, observer); + EXPECT_EQ(status, E_OK); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared005" }, observer); + EXPECT_EQ(status, E_OK); + status = store->Notify("RdbStoreSubscribeLocalShared005"); + EXPECT_EQ(status, E_OK); + EXPECT_FALSE(block->GetValue()); + + status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared005" }, observer); + EXPECT_EQ(status, E_OK); + block->Clear(false); + status = store->Notify("RdbStoreSubscribeLocalShared005"); + EXPECT_EQ(status, E_OK); + EXPECT_TRUE(block->GetValue()); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared005" }, nullptr); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbStoreSubscribeLocalShared006 + * @tc.desc: Different db Subscribe same uri + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared006, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + RdbStoreConfig config(RDB_TEST_PATH + "RdbStoreSubscribeLocalShared006.db"); + config.SetBundleName("subscribe_test"); + Callback helper; + int errCode = E_ERROR; + std::shared_ptr localStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(localStore, nullptr); + ASSERT_EQ(errCode, E_OK); + + auto count = std::make_shared>(0); + auto callback = [count]() { count->fetch_add(1); }; + auto observer = std::make_shared(callback); + auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared006" }, observer); + EXPECT_EQ(status, E_OK); + status = localStore->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared006" }, observer); + EXPECT_EQ(status, E_OK); + + status = store->Notify("RdbStoreSubscribeLocalShared006"); + EXPECT_EQ(status, E_OK); + std::this_thread::sleep_for(std::chrono::seconds(3)); + EXPECT_EQ(count->load(), 1); + status = localStore->Notify("RdbStoreSubscribeLocalShared006"); + EXPECT_EQ(status, E_OK); + std::this_thread::sleep_for(std::chrono::seconds(3)); + EXPECT_EQ(count->load(), 2); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared006" }, nullptr); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(RdbHelper::DeleteRdbStore(config), E_OK); +} + +/** + * @tc.name: RdbStoreSubscribeLocalShared007 + * @tc.desc: Subscribe to the same URI with different obs, then cancel all at once + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared007, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + auto count = std::make_shared>(0); + auto callback = [count]() { count->fetch_add(1); }; + auto observer1 = std::make_shared(callback); + auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared007" }, observer1); + EXPECT_EQ(status, E_OK); + + auto observer2 = std::make_shared(callback); + status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared007" }, observer2); + EXPECT_EQ(status, E_OK); + + status = store->Notify("RdbStoreSubscribeLocalShared007"); + EXPECT_EQ(status, E_OK); + std::this_thread::sleep_for(std::chrono::seconds(3)); + EXPECT_EQ(count->load(), 2); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared007" }, nullptr); + EXPECT_EQ(status, E_OK); + + status = store->Notify("RdbStoreSubscribeLocalShared007"); + EXPECT_EQ(status, E_OK); + std::this_thread::sleep_for(std::chrono::seconds(3)); + EXPECT_EQ(count->load(), 2); +} + /** * @tc.name: RdbStoreSubscribeLocalDetail001 * @tc.desc: test local observer onchange when insert data @@ -340,7 +532,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail001, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS local_test " "(id INTEGER PRIMARY KEY AUTOINCREMENT, " @@ -392,7 +584,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail001, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail002, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_); EXPECT_EQ(status, E_OK); @@ -440,7 +632,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail002, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail003, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_); EXPECT_EQ(status, E_OK); @@ -474,7 +666,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail003, TestSize.Level1) HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail004, TestSize.Level1) { int num = 10; - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_); EXPECT_EQ(status, E_OK); @@ -517,7 +709,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail004, TestSize.Level1) HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail005, TestSize.Level1) { int num = 1; - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_); EXPECT_EQ(status, E_OK); @@ -568,7 +760,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail005, TestSize.Level1) HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail006, TestSize.Level1) { int num = 20; - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS local_test2" "(id INTEGER PRIMARY KEY AUTOINCREMENT, " @@ -621,7 +813,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail006, TestSize.Level1) HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail007, TestSize.Level1) { int num = 20; - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS local_test3" "(id INTEGER PRIMARY KEY AUTOINCREMENT, " @@ -678,7 +870,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail007, TestSize.Level1) HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail008, TestSize.Level1) { int num = 20; - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS local_test4" "(id INTEGER PRIMARY KEY AUTOINCREMENT, " @@ -723,7 +915,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail008, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail009, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, nullptr); EXPECT_EQ(status, E_OK); @@ -749,7 +941,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail009, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics001, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS statistics_test " "(id INTEGER PRIMARY KEY AUTOINCREMENT, " @@ -784,7 +976,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics001, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics002, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; auto status = SqlStatistic::Subscribe(sqlObserver_); EXPECT_EQ(status, E_OK); @@ -811,7 +1003,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics002, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics003, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; auto status = SqlStatistic::Subscribe(sqlObserver_); EXPECT_EQ(status, E_OK); @@ -836,7 +1028,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics003, TestSize.Level1) HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics004, TestSize.Level1) { int num = 10; - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; auto status = SqlStatistic::Subscribe(sqlObserver_); EXPECT_EQ(status, E_OK); @@ -866,7 +1058,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics004, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics005, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; auto status = SqlStatistic::Subscribe(sqlObserver_); EXPECT_EQ(status, E_OK); @@ -897,7 +1089,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics005, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics006, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; auto status = SqlStatistic::Subscribe(sqlObserver_); EXPECT_EQ(status, E_OK); @@ -917,7 +1109,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics006, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics007, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; auto status = SqlStatistic::Subscribe(sqlObserver_); EXPECT_EQ(status, E_OK); @@ -937,7 +1129,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics007, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics008, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; auto status = SqlStatistic::Subscribe(sqlObserver_); EXPECT_EQ(status, E_OK); @@ -956,7 +1148,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics008, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics009, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; std::string value = "with test as (select * from statistics_test) select * from test1"; auto status = SqlStatistic::Subscribe(sqlObserver_); @@ -976,7 +1168,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics009, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics010, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; auto status = SqlStatistic::Subscribe(nullptr); EXPECT_EQ(status, E_OK); @@ -989,7 +1181,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics010, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStore_RegisterAutoSyncCallbackAndRdbStore_UnregisterAutoSyncCallback_001, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; auto obs = std::make_shared(); auto status = store->RegisterAutoSyncCallback(obs); EXPECT_EQ(status, E_OK); diff --git a/relational_store/test/native/rdb/unittest/rdb_update_test.cpp b/relational_store/test/native/rdb/unittest/rdb_update_test.cpp index 585eb590321ef08f4c912a6aa70132762de77306..dcc37793b757bac3fd727e71941ea979b601e3e8 100644 --- a/relational_store/test/native/rdb/unittest/rdb_update_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_update_test.cpp @@ -99,6 +99,7 @@ void RdbStoreUpdateTest::TearDownTestCase(void) void RdbStoreUpdateTest::SetUp(void) { store_ = *GetParam(); + ASSERT_NE(store_, nullptr); store_->ExecuteSql("DELETE FROM test"); } @@ -114,13 +115,11 @@ void RdbStoreUpdateTest::TearDown(void) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_001, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -130,11 +129,11 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_001, TestSize.Level1) values.PutInt("age", 20); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->Update(changedRows, "test", values, "id = ?", std::vector{ "1" }); + ret = store_->Update(changedRows, "test", values, "id = ?", std::vector{ "1" }); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToFirstRow(); @@ -155,28 +154,26 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_001, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_002, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; int changedRows; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); values.Clear(); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->Update(changedRows, "test", values); + ret = store_->Update(changedRows, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -201,8 +198,6 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_002, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_003, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int changedRows; ValuesBucket values; values.PutInt("id", 1); @@ -210,10 +205,10 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_003, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Update(changedRows, "", values, "", std::vector()); // empty table name + int ret = store_->Update(changedRows, "", values, "", std::vector()); // empty table name EXPECT_EQ(ret, E_EMPTY_TABLE_NAME); - ret = store->Update(changedRows, "wrongTable", values, "", std::vector()); // no such table + ret = store_->Update(changedRows, "wrongTable", values, "", std::vector()); // no such table EXPECT_EQ(ret, E_SQLITE_ERROR); } @@ -224,11 +219,9 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_003, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_004, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int changedRows; ValuesBucket emptyBucket; - int ret = store->Update(changedRows, "test", emptyBucket); + int ret = store_->Update(changedRows, "test", emptyBucket); EXPECT_EQ(ret, E_EMPTY_VALUES_BUCKET); ValuesBucket values; @@ -237,7 +230,7 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_004, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("wrongColumn", 100.5); // no such column values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Update(changedRows, "test", values, "", std::vector()); + ret = store_->Update(changedRows, "test", values, "", std::vector()); EXPECT_EQ(ret, E_SQLITE_ERROR); } @@ -248,17 +241,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_004, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_005, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Update(changedRows, "test", values, "id = ?", std::vector{ "1" }); + ret = store_->Update(changedRows, "test", values, "id = ?", std::vector{ "1" }); EXPECT_EQ(ret, E_EMPTY_VALUES_BUCKET); } @@ -269,8 +260,6 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_005, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_006, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; @@ -281,15 +270,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_006, TestSize.Level1) values.PutInt("age", 20); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Update(changedRows, "test", values, "id = ?", std::vector{ "1" }); + ret = store_->Update(changedRows, "test", values, "id = ?", std::vector{ "1" }); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToFirstRow(); @@ -310,21 +299,20 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_006, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_007, TestSize.Level1) { - std::shared_ptr store = *GetParam(); ValuesBucket values; AssetValue value{ .version = 1, .name = "123", .uri = "your test path", .createTime = "13", .modifyTime = "13" }; int changedRows; int64_t id; values.PutNull("assetType"); - int ret = store->Insert(id, "test", values); + int ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); values.Clear(); values.Put("assetType", value); - ret = store->Update(changedRows, "test", values); + ret = store_->Update(changedRows, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToFirstRow(); @@ -348,7 +336,6 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_007, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_008, TestSize.Level1) { - std::shared_ptr store = *GetParam(); ValuesBucket values; AssetValue valueDef{ .version = 0, @@ -361,15 +348,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_008, TestSize.Level1) int changedRows; int64_t id; values.Put("assetType", valueDef); - int ret = store->Insert(id, "test", values); + int ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(4, id); values.Clear(); values.Put("assetType", value); - ret = store->Update(changedRows, "test", values); + ret = store_->Update(changedRows, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToFirstRow(); @@ -388,7 +375,6 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_008, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_009, TestSize.Level1) { - std::shared_ptr store = *GetParam(); ValuesBucket values; AssetValue valueDef{ .version = 0, .status = AssetValue::STATUS_NORMAL, @@ -403,15 +389,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_009, TestSize.Level1) int changedRows; int64_t id; values.Put("assetType", valueDef); - int ret = store->Insert(id, "test", values); + int ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(5, id); values.Clear(); values.Put("assetType", value); - ret = store->Update(changedRows, "test", values); + ret = store_->Update(changedRows, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToFirstRow(); EXPECT_EQ(ret, E_OK); @@ -435,7 +421,6 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_009, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_010, TestSize.Level1) { - std::shared_ptr store = *GetParam(); ValuesBucket values; std::vector assetsDef{ { .version = 0, .name = "123", .uri = "my test path", .createTime = "12", .modifyTime = "12" } @@ -447,13 +432,13 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_010, TestSize.Level1) int changedRows; int64_t id; values.Put("assetsType", assetsDef); - int ret = store->Insert(id, "test", values); + int ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(6, id); values.Clear(); values.Put("assetsType", assets); - ret = store->Update(changedRows, "test", values); + ret = store_->Update(changedRows, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); } @@ -465,17 +450,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_010, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_001, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -485,11 +468,11 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_001, TestSize values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = 19"); + ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = 19"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -514,17 +497,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_001, TestSize */ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_002, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -534,11 +515,11 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_002, TestSize values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, + ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, ConflictResolution::ON_CONFLICT_NONE); EXPECT_EQ(ret, E_SQLITE_CONSTRAINT); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -563,17 +544,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_002, TestSize */ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_003, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -583,12 +562,12 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_003, TestSize values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, + ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, ConflictResolution::ON_CONFLICT_ROLLBACK); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -613,17 +592,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_003, TestSize */ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_004, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -633,11 +610,11 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_004, TestSize values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, + ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, ConflictResolution::ON_CONFLICT_ROLLBACK); EXPECT_EQ(ret, E_SQLITE_CONSTRAINT); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -662,17 +639,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_004, TestSize */ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_005, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -682,12 +657,12 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_005, TestSize values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, + ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, ConflictResolution::ON_CONFLICT_REPLACE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -712,17 +687,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_005, TestSize */ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_006, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -730,12 +703,12 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_006, TestSize values.PutString("name", std::string("zhangsan")); values.PutInt("age", 20); values.PutDouble("salary", 300.5); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, + ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, ConflictResolution::ON_CONFLICT_REPLACE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(changedRows, 1); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -757,19 +730,17 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_006, TestSize */ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_007, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int changedRows = 0; int64_t id = -1; ValuesBucket values; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); values.PutInt("id", 2); values.PutInt("age", 19); - ret = store->UpdateWithConflictResolution( + ret = store_->UpdateWithConflictResolution( changedRows, "test", values, "age = ?", std::vector{ "18" }, static_cast(6)); EXPECT_EQ(E_INVALID_CONFLICT_FLAG, ret); EXPECT_EQ(0, changedRows); @@ -777,7 +748,7 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_007, TestSize values.Clear(); values.PutInt("id", 2); values.PutInt("age", 19); - ret = store->UpdateWithConflictResolution( + ret = store_->UpdateWithConflictResolution( changedRows, "test", values, "age = ?", std::vector{ "18" }, static_cast(-1)); EXPECT_EQ(E_INVALID_CONFLICT_FLAG, ret); EXPECT_EQ(0, changedRows); @@ -865,5 +836,300 @@ HWTEST_P(RdbStoreUpdateTest, OverLimitWithUpdate_001, TestSize.Level1) ASSERT_EQ(result, E_SQLITE_FULL); } +/** + * @tc.name: UpdateWithReturning_001 + * @tc.desc: normal test + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_001, TestSize.Level1) +{ + int64_t id; + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + ValuesBucket values; + values.PutInt("id", 2); + values.PutString("name", std::string("lisi")); + values.PutInt("age", 20); + values.PutDouble("salary", 200.5); + values.PutBlob("blobType", std::vector{ 4, 5, 6 }); + AbsRdbPredicates predicates("test"); + auto [status, result] = store_->Update(values, predicates, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("id", columnIndex), E_OK); + int val = -1; + ASSERT_EQ(result.results->GetInt(columnIndex, val), E_OK); +} + +/** + * @tc.name: UpdateWithReturning_002 + * @tc.desc: abnormal test, update with conflict ignore and partial Success + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_002, TestSize.Level1) +{ + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim_" + std::to_string(i)); + rows.Put(row); + } + auto [status, result] = store_->BatchInsert("test", rows, {}, ConflictResolution::ON_CONFLICT_REPLACE); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(result.changed, 5); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(0, rowCount); + + ValuesBucket row; + row.PutString("name", "Jim_3"); + row.PutInt("age", 20); + row.PutDouble("salary", 200.5); + row.PutBlob("blobType", std::vector{ 4, 5, 6 }); + AbsRdbPredicates predicates("test"); + predicates.In("id", { 1, 2, 3 }); + std::tie(status, result) = store_->Update(row, predicates, { "name" }, ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(1, rowCount); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + std::string val; + ASSERT_EQ(result.results->GetString(columnIndex, val), E_OK); + ASSERT_EQ(val, "Jim_3"); +} + +/** + * @tc.name: UpdateWithReturning_003 + * @tc.desc: abnormal test, update with conflict abort and failed + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_003, TestSize.Level1) +{ + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim_" + std::to_string(i)); + rows.Put(row); + } + auto [status, result] = store_->BatchInsert("test", rows, {}, ConflictResolution::ON_CONFLICT_REPLACE); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(result.changed, 5); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(0, rowCount); + + ValuesBucket row; + row.PutString("name", "Jim_3"); + row.PutInt("age", 20); + row.PutDouble("salary", 200.5); + row.PutBlob("blobType", std::vector{ 4, 5, 6 }); + AbsRdbPredicates predicates("test"); + predicates.In("id", { 1, 2, 3 }); + std::tie(status, result) = store_->Update(row, predicates, { "blobType" }, ConflictResolution::ON_CONFLICT_ABORT); + EXPECT_EQ(status, E_SQLITE_CONSTRAINT); + EXPECT_EQ(result.changed, 0); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(0, rowCount); +} + +/** + * @tc.name: UpdateWithReturning_004 + * @tc.desc: abnormal test, update over returning limit + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_004, TestSize.Level1) +{ + ValuesBuckets rows; + for (int i = 0; i < 1124; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim_" + std::to_string(i)); + rows.Put(row); + } + auto [status, result] = store_->BatchInsert("test", rows, {}, ConflictResolution::ON_CONFLICT_REPLACE); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(result.changed, 1124); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(0, rowCount); + + ValuesBucket row; + row.PutInt("age", 20); + row.PutDouble("salary", 200.5); + row.PutBlob("blobType", std::vector{ 4, 5, 6 }); + AbsRdbPredicates predicates("test"); + std::tie(status, result) = store_->Update(row, predicates, { "age" }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1124); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1024); +} + +/** + * @tc.name: UpdateWithReturning_005 + * @tc.desc: abnormal test, update with returning no exist field + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_005, TestSize.Level1) +{ + int64_t id; + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + ValuesBucket values; + values.PutString("name", std::string("lisi")); + values.PutInt("age", 20); + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 10000); + auto [status, result] = store_->Update(values, predicates, { "noExist" }); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + EXPECT_EQ(result.results, nullptr); +} + +/** + * @tc.name: UpdateWithReturning_006 + * @tc.desc: abnormal test, update 0 rows + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_006, TestSize.Level1) +{ + int64_t id; + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + ValuesBucket values; + values.PutString("name", std::string("lisi")); + values.PutInt("age", 20); + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 10000); + auto [status, result] = store_->Update(values, predicates, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(0, rowCount); +} + + +/** + * @tc.name: UpdateWithReturning_007 + * @tc.desc: abnormal test, update 0 rows + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_007, TestSize.Level1) +{ + store_->Execute("CREATE VIRTUAL TABLE IF NOT EXISTS articles USING fts5(title, content);"); + ValuesBuckets rows; + ValuesBucket row; + row.Put("title", "fts5"); + row.Put("content", "test virtual tables"); + rows.Put(std::move(row)); + auto [status, result] = + store_->BatchInsert("articles", rows, { "title" }, NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + + AbsRdbPredicates predicates("test"); + predicates.EqualTo("title", "fts5"); + ValuesBucket values; + values.PutString("title", "fts5 updated"); + + std::tie(status, result) = store_->Update(values, predicates, { "title" }); + // UPDATE RETURNING is not available on virtual tables + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + EXPECT_EQ(result.results, nullptr); + + store_->Execute("Drop TABLE articles"); +} + +/** + * @tc.name: UpdateWithReturning_008 + * @tc.desc: normal test. create trigger before update, delete data in trigger, then update data + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_008, TestSize.Level1) +{ + auto [code, result1] = store_->Execute( + "CREATE TRIGGER before_update BEFORE UPDATE ON test" + " BEGIN DELETE FROM test WHERE name = 'wang'; END"); + + EXPECT_EQ(code, E_OK); + + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 200); + row.Put("name", "wang"); + rows.Put(std::move(row)); + row.Put("id", 201); + row.Put("name", "zhang"); + rows.Put(std::move(row)); + + auto [insertStatus, insertResult] = + store_->BatchInsert("test", rows, { "name" }, NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(insertStatus, E_OK); + EXPECT_EQ(insertResult.changed, 2); + + auto predicates = AbsRdbPredicates("test"); + predicates.EqualTo("name", "zhang"); + ValuesBucket values; + values.PutString("name", "liu"); + + auto [status, res] = + store_->Update(values, predicates, { "name" }); + + EXPECT_EQ(status, E_OK); + EXPECT_EQ(res.changed, 1); + int rowCount = -1; + ASSERT_EQ(res.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(res.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + ASSERT_EQ(res.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "liu"); + + // Check the trigger effect + auto resultSet = store_->QuerySql("select name from test where id = 200"); + + rowCount = -1; + resultSet->GetRowCount(rowCount); + ASSERT_EQ(rowCount, 0); + store_->Execute("DROP TRIGGER IF EXISTS before_update"); +} + INSTANTIATE_TEST_SUITE_P(UpdateTest, RdbStoreUpdateTest, testing::Values(&g_store, &g_memDb)); } // namespace OHOS::RdbStoreUpdateTest \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_utils_test.cpp b/relational_store/test/native/rdb/unittest/rdb_utils_test.cpp index bee28ab34d1ffd3b0fab7a6101175d505a26b327..3dbcd42353a74ea6c5a5b2b16cb553d5c26f9eed 100644 --- a/relational_store/test/native/rdb/unittest/rdb_utils_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_utils_test.cpp @@ -136,4 +136,22 @@ HWTEST_F(RdbUtilsTest, GetSqlStatementType_002, TestSize.Level1) EXPECT_EQ(SqliteUtils::STATEMENT_SELECT, SqliteUtils::GetSqlStatementType(" select * from text")); EXPECT_EQ(SqliteUtils::STATEMENT_UPDATE, SqliteUtils::GetSqlStatementType("\r\nupdate test set id = ?")); EXPECT_EQ(SqliteUtils::STATEMENT_OTHER, SqliteUtils::GetSqlStatementType("~!@# attach database ? as ?")); +} + +/** + * @tc.name: GetAreaTest + * @tc.desc: Test get area + * @tc.type: FUNC + */ +HWTEST_F(RdbUtilsTest, GetAreaTest, TestSize.Level1) +{ + std::string srcFile("data/app/el2/database"); + auto area = SqliteUtils::GetArea(srcFile); + EXPECT_EQ(area, "el2"); + std::string dirFile("data/app/database"); + area = SqliteUtils::GetArea(dirFile); + EXPECT_EQ(area, ""); + std::string dirSrcFile("data/app/el2database"); + area = SqliteUtils::GetArea(dirSrcFile); + EXPECT_EQ(area, ""); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/sqlite_statement_test/BUILD.gn b/relational_store/test/native/rdb/unittest/sqlite_statement_test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..04118e0f45f64da8f62c03187bbf9168ae3b447f --- /dev/null +++ b/relational_store/test/native/rdb/unittest/sqlite_statement_test/BUILD.gn @@ -0,0 +1,153 @@ +# Copyright (c) 2025 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/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +module_output_path = "relational_store/relational_store/native_rdb" + +############################################################################### +config("module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${relational_store_mock_path}/frameworks/native/rdb/common", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", + "${relational_store_native_path}/rdb/src", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_native_path}/rdb_crypt", + "${relational_store_native_path}/rdb_device_manager_adapter/include", + "${relational_store_base_path}/test/native/rdb/unittest", + ] + + defines = [ + "RELATIONAL_STORE", + ] +} + +ohos_unittest("SqliteStatementTest") { + module_out_path = module_output_path + + cflags = [ + "-fno-access-control", # Ignore Private Member Access Control + ] + + sources = [ + "sqlite_statement_test.cpp", + "mock_shared_block_test.cpp", + ] + + sources += [ + "${relational_store_native_path}/rdb/src/rdb_manager_impl.cpp", + "${relational_store_native_path}/dfx/src/rdb_radar_reporter.cpp", + "${relational_store_native_path}/dfx/src/rdb_stat_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_fault_hiview_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_time_utils.cpp", + "${relational_store_native_path}/rdb/src/abs_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_result_set.cpp", + "${relational_store_native_path}/rdb/src/abs_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/base_transaction.cpp", + "${relational_store_native_path}/rdb/src/big_integer.cpp", + "${relational_store_native_path}/rdb/src/cache_result_set.cpp", + "${relational_store_native_path}/rdb/src/connection.cpp", + "${relational_store_native_path}/rdb/src/connection_pool.cpp", + "${relational_store_native_path}/rdb/src/delay_notify.cpp", + "${relational_store_native_path}/rdb/src/grd_api_manager.cpp", + "${relational_store_native_path}/rdb/src/global_resource.cpp", + "${relational_store_native_path}/rdb/src/knowledge_schema_helper.cpp", + "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", + "${relational_store_native_path}/rdb/src/rd_connection.cpp", + "${relational_store_native_path}/rdb/src/rd_statement.cpp", + "${relational_store_native_path}/rdb/src/rd_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_helper.cpp", + "${relational_store_native_path}/rdb/src/rdb_icu_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_local_db_observer.cpp", + "${relational_store_native_path}/rdb/src/rdb_notifier_stub.cpp", + "${relational_store_native_path}/rdb/src/rdb_obs_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_perfStat.cpp", + "${relational_store_native_path}/rdb/src/rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_service_proxy.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_log.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_statistic.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_store.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_impl.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_types_util.cpp", + "${relational_store_native_path}/rdb/src/result_set_proxy.cpp", + "${relational_store_native_path}/rdb/src/security_policy.cpp", + "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", + "${relational_store_native_path}/rdb/src/sqlite_connection.cpp", + "${relational_store_native_path}/rdb/src/sqlite_default_function.cpp", + "${relational_store_native_path}/rdb/src/sqlite_global_config.cpp", + "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/sqlite_sql_builder.cpp", + "${relational_store_native_path}/rdb/src/sqlite_statement.cpp", + "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", + "${relational_store_native_path}/rdb/src/step_result_set.cpp", + "${relational_store_native_path}/rdb/src/string_utils.cpp", + "${relational_store_native_path}/rdb/src/suspender.cpp", + "${relational_store_native_path}/rdb/src/task_executor.cpp", + "${relational_store_native_path}/rdb/src/trans_db.cpp", + "${relational_store_native_path}/rdb/src/transaction.cpp", + "${relational_store_native_path}/rdb/src/transaction_impl.cpp", + "${relational_store_native_path}/rdb/src/value_object.cpp", + "${relational_store_native_path}/rdb/src/values_bucket.cpp", + "${relational_store_native_path}/rdb/src/values_buckets.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "c_utils:utils", + "file_api:securitylabel", + "googletest:gmock", + "googletest:gtest", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "huks:libhukssdk", + "ipc:ipc_core", + "ipc:ipc_single", + "json:nlohmann_json_static", + "kv_store:database_utils", + "kv_store:datamgr_common", + "kv_store:distributeddata_inner", + "kv_store:distributeddb_client", + "samgr:samgr_proxy", + "sqlite:sqlite", + "sqlite:sqliteicu", + ] + + deps = [ + "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", + "${relational_store_innerapi_path}/appdatafwk:relational_common_base", + ] +} + +############################################################################### +group("unittest") { + testonly = true + + deps = [ ":SqliteStatementTest" ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/unittest/sqlite_statement_test/mock_shared_block_test.cpp b/relational_store/test/native/rdb/unittest/sqlite_statement_test/mock_shared_block_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b7b26f173629ccf166398f09657944f8a902dfe3 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/sqlite_statement_test/mock_shared_block_test.cpp @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2025 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 + +#include "share_block.h" +#include "logger.h" +#include "sqlite_errno.h" +namespace OHOS { +namespace NativeRdb { +using namespace OHOS::Rdb; + +int SeriAddRow(void *pCtx, int addedRows) +{ + (void)pCtx; + (void)addedRows; + return E_ERROR; +} + +int SeriReset(void *pCtx, int startPos) +{ + (void)pCtx; + (void)startPos; + return E_ERROR; +} + +int SeriFinish(void *pCtx, int addedRows, int totalRows) +{ + (void)pCtx; + (void)addedRows; + (void)totalRows; + return E_ERROR; +} + +int SeriPutString(void *pCtx, int addedRows, int column, const char *text, int size) +{ + (void)pCtx; + (void)addedRows; + (void)column; + (void)text; + (void)size; + return E_ERROR; +} + +int SeriPutLong(void *pCtx, int addedRows, int column, sqlite3_int64 value) +{ + (void)pCtx; + (void)addedRows; + (void)column; + (void)value; + return E_ERROR; +} + +int SeriPutDouble(void *pCtx, int addedRows, int column, double value) +{ + (void)pCtx; + (void)addedRows; + (void)column; + (void)value; + return E_ERROR; +} + +int SeriPutBlob(void *pCtx, int addedRows, int column, const void *blob, int len) +{ + (void)pCtx; + (void)addedRows; + (void)column; + (void)blob; + (void)len; + return E_ERROR; +} + +int SeriPutNull(void *pCtx, int addedRows, int column) +{ + (void)pCtx; + (void)addedRows; + (void)column; + return E_ERROR; +} + +int SeriPutOther(void *pCtx, int addedRows, int column) +{ + (void)pCtx; + (void)addedRows; + (void)column; + return E_ERROR; +} + +int ClearSharedBlock(AppDataFwk::SharedBlock *sharedBlock) +{ + (void)sharedBlock; + return E_ERROR; +} + +int SharedBlockSetColumnNum(AppDataFwk::SharedBlock *sharedBlock, int columnNum) +{ + (void)sharedBlock; + (void)columnNum; + return E_ERROR; +} + +int FillSharedBlockOpt(SharedBlockInfo *info, sqlite3_stmt *stmt) +{ + (void)info; + (void)stmt; + return E_ERROR; +} + +int FillSharedBlock(SharedBlockInfo *info, sqlite3_stmt *stmt) +{ + (void)info; + (void)stmt; + return E_ERROR; +} + +void FillRow(SharedBlockInfo *info, sqlite3_stmt *stmt) +{ + (void)info; + (void)stmt; +} + +FillOneRowResult FillOneRow( + AppDataFwk::SharedBlock *sharedBlock, sqlite3_stmt *statement, int numColumns, int startPos, int addedRows) +{ + (void)sharedBlock; + (void)statement; + (void)numColumns; + (void)startPos; + (void)addedRows; + FillOneRowResult result = FILL_ONE_ROW_SUCESS; + return result; +} + +FillOneRowResult FillOneRowOfString( + AppDataFwk::SharedBlock *sharedBlock, sqlite3_stmt *statement, int startPos, int addedRows, int pos) +{ + (void)sharedBlock; + (void)statement; + (void)startPos; + (void)addedRows; + (void)pos; + FillOneRowResult result = FILL_ONE_ROW_SUCESS; + return result; +} + +FillOneRowResult FillOneRowOfLong( + AppDataFwk::SharedBlock *sharedBlock, sqlite3_stmt *statement, int startPos, int addedRows, int pos) +{ + (void)sharedBlock; + (void)statement; + (void)startPos; + (void)addedRows; + (void)pos; + FillOneRowResult result = FILL_ONE_ROW_SUCESS; + return result; +} + +FillOneRowResult FillOneRowOfFloat( + AppDataFwk::SharedBlock *sharedBlock, sqlite3_stmt *statement, int startPos, int addedRows, int pos) +{ + (void)sharedBlock; + (void)statement; + (void)startPos; + (void)addedRows; + (void)pos; + FillOneRowResult result = FILL_ONE_ROW_SUCESS; + return result; +} + +FillOneRowResult FillOneRowOfBlob( + AppDataFwk::SharedBlock *sharedBlock, sqlite3_stmt *statement, int startPos, int addedRows, int pos) +{ + (void)sharedBlock; + (void)statement; + (void)startPos; + (void)addedRows; + (void)pos; + FillOneRowResult result = FILL_ONE_ROW_SUCESS; + return result; +} + +FillOneRowResult FillOneRowOfNull( + AppDataFwk::SharedBlock *sharedBlock, sqlite3_stmt *statement, int startPos, int addedRows, int pos) +{ + (void)sharedBlock; + (void)statement; + (void)startPos; + (void)addedRows; + (void)pos; + FillOneRowResult result = FILL_ONE_ROW_SUCESS; + return result; +} + +bool ResetStatement(SharedBlockInfo *info, sqlite3_stmt *stmt) +{ + (void)info; + (void)stmt; + return true; +} + +int DefAddRow(void *pCtx, int addedRows) +{ + return SQLITE_FULL; +} + +int DefReset(void *pCtx, int startPos) +{ + return SQLITE_OK; +} + +int DefFinish(void *pCtx, int addedRows, int totalRows) +{ + return SQLITE_OK; +} + +int DefPutString(void *pCtx, int addedRows, int column, const char *text, int size) +{ + return SQLITE_FULL; +} + +int DefPutLong(void *pCtx, int addedRows, int column, sqlite3_int64 value) +{ + return SQLITE_FULL; +} + +int DefPutDouble(void *pCtx, int addedRows, int column, double value) +{ + return SQLITE_FULL; +} + +int DefPutBlob(void *pCtx, int addedRows, int column, const void *blob, int len) +{ + return SQLITE_FULL; +} + +int DefPutNull(void *pCtx, int addedRows, int column) +{ + return SQLITE_FULL; +} + +int DefPutOther(void *pCtx, int addedRows, int column) +{ + return SQLITE_FULL; +} + +void DefFillRow(SharedBlockInfo *info, sqlite3_stmt *stmt) +{ + (void)info; + (void)stmt; +} +} // namespace NativeRdb +} // namespace OHOS \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/sqlite_statement_test/sqlite_statement_test.cpp b/relational_store/test/native/rdb/unittest/sqlite_statement_test/sqlite_statement_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3cd045da8ae3c3f58b8f82f2671fccb14ba7f76f --- /dev/null +++ b/relational_store/test/native/rdb/unittest/sqlite_statement_test/sqlite_statement_test.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2025 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 "sqlite_statement.h" + +#include +#include + +#include +#include +#include + +#include "block_data.h" +#include "common.h" +#include "executor_pool.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "rdb_sql_log.h" +#include "rdb_store.h" +#include "rdb_store_manager.h" +#include "rdb_types.h" +#include "sqlite_utils.h" +#include "values_bucket.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::DistributedRdb; + +class RdbSqliteStatementTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void RdbSqliteStatementTest::SetUpTestCase(void) +{ +} + +void RdbSqliteStatementTest::TearDownTestCase(void) +{ +} + +void RdbSqliteStatementTest::SetUp(void) +{ +} + +void RdbSqliteStatementTest::TearDown(void) +{ +} +/** + * @tc.name: SqliteStatement001 + * @tc.desc: RdbSqliteStatementTest FillBlockInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqliteStatementTest, SqliteStatement001, TestSize.Level0) +{ + sqlite3 *db = nullptr; + int rc = sqlite3_open("/data/test/SqliteStatement001.db", &db); + ASSERT_NE(db, nullptr); + EXPECT_EQ(rc, SQLITE_OK); + const char *sqlCreate = "CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY)"; + char *errMsg = nullptr; + rc = sqlite3_exec(db, sqlCreate, NULL, NULL, &errMsg); + sqlite3_stmt *stmt; + const char *sql = "select id from users;"; + rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); + + SharedBlockInfo info(nullptr); + info.isCountAllRows = true; + info.isFull = true; + info.totalRows = -1; + SqliteStatement statem; + statem.stmt_ = stmt; + int errCode = statem.FillBlockInfo(&info); + EXPECT_EQ(errCode, E_ERROR); + statem.stmt_ = nullptr; + sqlite3_finalize(stmt); + rc = sqlite3_close(db); + EXPECT_EQ(rc, SQLITE_OK); +} + +/** + * @tc.name: SqliteStatement002 + * @tc.desc: RdbSqliteStatementTest FillBlockInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqliteStatementTest, SqliteStatement002, TestSize.Level0) +{ + const char *dbPath = "/data/test/SqliteStatement002.db"; + RdbStoreConfig rdbConfig(dbPath); + sqlite3 *db = nullptr; + int rc = sqlite3_open(dbPath, &db); + ASSERT_NE(db, nullptr); + EXPECT_EQ(rc, SQLITE_OK); + const char *sqlCreate = "CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY)"; + char *errMsg = nullptr; + rc = sqlite3_exec(db, sqlCreate, NULL, NULL, &errMsg); + sqlite3_stmt *stmt; + const char *sql = "select id from users;"; + rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); + + SharedBlockInfo info(nullptr); + info.isCountAllRows = true; + info.isFull = true; + info.totalRows = -1; + SqliteStatement statem(&rdbConfig); + statem.stmt_ = stmt; + int errCode = statem.FillBlockInfo(&info); + EXPECT_EQ(errCode, E_ERROR); + statem.stmt_ = nullptr; + sqlite3_finalize(stmt); + rc = sqlite3_close(db); + EXPECT_EQ(rc, SQLITE_OK); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/sqlite_utils_test.cpp b/relational_store/test/native/rdb/unittest/sqlite_utils_test.cpp index ba5bf657e236d3f999df7cc6917d9cdf9afabaec..134c7b39d4808625ddc39bd57648645a9aa02b03 100644 --- a/relational_store/test/native/rdb/unittest/sqlite_utils_test.cpp +++ b/relational_store/test/native/rdb/unittest/sqlite_utils_test.cpp @@ -41,122 +41,181 @@ void SqliteUtilsTest::TearDownTestCase(void) HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_001, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("30005245854585524412855412_rdb_test.db"), "***5412_rdb_test.db"); -} - -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_002, TestSize.Level1) -{ - EXPECT_EQ(SqliteUtils::Anonymous("rdb_test_30005245854585524412855412.db"), "rdb_test_***5412.db"); -} - -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_003, TestSize.Level1) -{ - EXPECT_EQ(SqliteUtils::Anonymous("rdb_30005245854585524412855412_test.db"), "rdb_***5412_test.db"); -} - -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_004, TestSize.Level1) -{ - EXPECT_EQ(SqliteUtils::Anonymous("rdb_300052_test.db"), "rdb_***052_test.db"); -} - -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_005, TestSize.Level1) -{ - EXPECT_EQ(SqliteUtils::Anonymous("rdb_30005_test.db"), "rdb_30005_test.db"); -} - -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_006, TestSize.Level1) -{ - EXPECT_EQ(SqliteUtils::Anonymous("rdb_3000523_test.db"), "rdb_***0523_test.db"); + EXPECT_EQ(SqliteUtils::Anonymous("30005245854585524412855412_rdb_test.db"), "300***.db"); } HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_007, TestSize.Level1) { EXPECT_EQ( SqliteUtils::Anonymous("file /data/stage/el2/database/rdb/ddddddd/30005245854585524412855412_rdb_test.db"), - "file /***/el2/***/***5412_rdb_test.db"); -} - -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_008, TestSize.Level1) -{ - EXPECT_EQ(SqliteUtils::Anonymous("file /data/stage/database/rdb/ddddddd/30005245854585524412855412_rdb_test.db"), - "file /***/***5412_rdb_test.db"); + "file /***/el2/***/300***.db"); } HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_009, TestSize.Level1) { EXPECT_EQ( SqliteUtils::Anonymous("file /data/stage/el2/database/rdb/ddddddd/3E00mnj5H54efg5G4K1ABC5412_rdb_test.db"), - "file /***/el2/***/3E00mnj5H54efg5G4K***5412_rdb_test.db"); + "file /***/el2/***/3E0***.db"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_010, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0011, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("/data/stage/el2/database/rdb/ddddddd/3E00mnj5H54efg5G4K1ABC5412_rdb_test.db"), - "/***/el2/***/3E00mnj5H54efg5G4K***5412_rdb_test.db"); + EXPECT_EQ(SqliteUtils::Anonymous("30005245854585524412855412.db"), "300***.db"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0011, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0013, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("30005245854585524412855412.db"), "***5412.db"); + EXPECT_EQ(SqliteUtils::Anonymous("123edf4.db"), "123***.db"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0012, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0016, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("thequickbrownfoxjumpoverthelazydog.db"), "thequickbrownfoxjumpoverthelazydog.db"); + EXPECT_EQ(SqliteUtils::Anonymous("__23edf__.db"), "__2***.db"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0013, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0021, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("123edf4.db"), "***edf4.db"); + EXPECT_EQ(SqliteUtils::Anonymous("linker_reborn.db-wal"), "lin***wal"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0014, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0022, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("K123edfK.db"), "K***edfK.db"); + EXPECT_EQ(SqliteUtils::Anonymous("linker_grow.db-wal"), "lin***wal"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0015, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0023, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("K23edfK.db"), "K23edfK.db"); + EXPECT_EQ(SqliteUtils::Anonymous("file /data/stage/el2/database/rdb/ddddddd/linker_reborn.db-wal"), + "file /***/el2/***/lin***wal"); +} + +HWTEST_F(SqliteUtilsTest, Anonymous_001, TestSize.Level0) +{ + EXPECT_EQ(SqliteUtils::Anonymous(""), ""); + EXPECT_EQ(SqliteUtils::Anonymous("x"), "x**"); + EXPECT_EQ(SqliteUtils::Anonymous("xx"), "x**"); + EXPECT_EQ(SqliteUtils::Anonymous("xxx"), "x**"); + EXPECT_EQ(SqliteUtils::Anonymous("xxxx"), "xxx***"); + EXPECT_EQ(SqliteUtils::Anonymous("xxxxx"), "xxx***"); + EXPECT_EQ(SqliteUtils::Anonymous("xxxxxx"), "xxx***"); + EXPECT_EQ(SqliteUtils::Anonymous("xxxxxxx"), "xxx***"); + EXPECT_EQ(SqliteUtils::Anonymous("xxxxxxxx"), "xxx***"); + EXPECT_EQ(SqliteUtils::Anonymous("xxxxxxxxx"), "xxx***xxx"); + EXPECT_EQ(SqliteUtils::Anonymous("xxxxxxxxxx"), "xxx***xxx"); +} + +HWTEST_F(SqliteUtilsTest, SqlAnonymous_001, TestSize.Level0) +{ + EXPECT_EQ(SqliteUtils::SqlAnonymous("SELECT * FROM users WHERE id = 1"), "SELECT * FROM use*** WHERE i** = 1"); + EXPECT_EQ(SqliteUtils::SqlAnonymous( + "statement abort at 11: [ SELECT COUNT(1) AS count FROM Photos WHERE type = 'screenshot'"), + "statement abort at 11: [ SELECT COUNT(1) AS count FROM Pho*** WHERE type = 'scr***hot'"); + EXPECT_EQ(SqliteUtils::SqlAnonymous("errno is:25 ambiguous column name:" + " name in \"SELECT name FROM tableA JOIN tableB ON tableA.id = tableB.a_id;\""), + "errno is:25 ambiguous column name:" + " name in \"SELECT name FROM tab*** JOIN tab*** ON tab***.i** = tab***.a_i***;\""); + EXPECT_EQ( + SqliteUtils::SqlAnonymous("errno is:25 ambiguous column name:" + " story in \"SELECT story FROM tableA JOIN tableB ON tableA.id = tableB.a_id;\""), + "errno is:25 ambiguous column name:" + " sto*** in \"SELECT sto*** FROM tab*** JOIN tab*** ON tab***.i** = tab***.a_i***;\""); + EXPECT_EQ(SqliteUtils::SqlAnonymous( + "errno is:25 2 values for 1 columns in \"INSERT INTO tableA(story) Values(1, '你好中文字符')\"."), + "errno is:25 2 values for 1 col*** in \"INSERT INTO tab***(sto***) Values(1, '***')\"."); + EXPECT_EQ( + SqliteUtils::SqlAnonymous("errno is:0 no such table: CommonAddressModel in" + " \"SELECT * FROM CommonAddressModel WHERE addressType IN (? , ?)AND uid = ? \""), + "errno is:0 no such table: Com***del in \"SELECT * FROM Com***del WHERE add***ype IN (? , ?)AND u** = ? \""); + EXPECT_EQ(SqliteUtils::SqlAnonymous("abort at 14 in [INSERT INTO SETTINGSDATA(KEYWORD,VALUE) VALUES (?,?)]: " + "UNIQUE constraint failed: SETTINGSDATA.KEYWORD"), + "abort at 14 in [INSERT INTO SET***ATA(KEY***,VAL***) VALUES (?,?)]: " + "UNIQUE constraint failed: SET***ATA.KEY***"); + EXPECT_EQ(SqliteUtils::SqlAnonymous("error is:2 misuse at line 57f4b3 if [6cd587f]"), + "error is:2 misuse at line ***4b3 if [***587f]"); + + EXPECT_EQ(SqliteUtils::SqlAnonymous("[SQLite]BusyLine:63706, idx:0, type:4, fileLock:0, len:1, handleLocks:none"), + "[SQLite]BusyLine:63706, idx:0, type:4, fileLock:0, len:1, handleLocks:none"); + EXPECT_EQ(SqliteUtils::SqlAnonymous("[SQLite]acqLock:1, dbRef:2, lockCnt:2, curLock:1, processLock:0"), + "[SQLite]acqLock:1, dbRef:2, lockCnt:2, curLock:1, processLock:0"); + EXPECT_EQ(SqliteUtils::SqlAnonymous("[SQLite]Trx locks: "), + "[SQLite]Trx locks: "); + EXPECT_EQ(SqliteUtils::SqlAnonymous("hello 简体中文 world"), "hel*** *** wor***"); + EXPECT_EQ(SqliteUtils::SqlAnonymous("hello简体cplus中文world"), "hel******cpl******wor***"); +} + +HWTEST_F(SqliteUtilsTest, SqlAnonymous_002, TestSize.Level0) +{ + EXPECT_EQ(SqliteUtils::SqlAnonymous( + "[SQLite]Wal locks: " + ""), + "[SQLite]Wal locks: " + ""); + EXPECT_EQ(SqliteUtils::SqlAnonymous( + "statement aborts at 32: [UPDATE SETTINGSDATA SET KEYWORD=?,VALUE=? WHERE KEYWORD = ? ]" + " database schema has changed"), + "statement aborts at 32: [UPDATE SET***ATA SET KEY***=?,VAL***=? WHERE KEY*** = ? ]" + " database schema has changed"); + EXPECT_EQ( + SqliteUtils::SqlAnonymous("abort at 14 in [INSERT INTO USER_SETTINGSDATA_100(KEYWORD,VALUE) VALUES (?,?)]: " + "UNIQUE constraint failed: USER_SETTINGSDATA_100.KEYWORD"), + "abort at 14 in [INSERT INTO USE***100(KEY***,VAL***) VALUES (?,?)]: " + "UNIQUE constraint failed: USE***100.KEY***"); + EXPECT_EQ(SqliteUtils::SqlAnonymous( + "errno is:2 near \"IF\": syntax error in \"CREATE TRIGGER IF NOT EXISTS [update_contact_data_version]" + " AFTER UPDATE ON [contact_data] BEGIN IF UPDATE [version] RETURN; UPDATE [contact_data] " + "SET [version] = [OLD].[version] + 1 WHERE [id] = [OLD].[id]; END\"."), + "errno is:2 near \"IF\": syntax error in \"CREATE TRIGGER IF NOT EXISTS [upd***ion]" + " AFTER UPDATE ON [con***ata] BEGIN IF UPDATE [ver***] RET***; UPDATE [con***ata] " + "SET [ver***] = [O**].[ver***] + 1 WHERE [i**] = [O**].[i**]; END\"."); + EXPECT_EQ(SqliteUtils::SqlAnonymous("Fd 7 enable del monitor go wrong, errno = 13"), + "Fd 7 enable del monitor go wrong, errno = 13"); + EXPECT_EQ(SqliteUtils::SqlAnonymous( + "errno is:95 duplicate column name: Timestamp in \"ALTER TABLE BSD ADD COLUMN Timestamp TE."), + "errno is:95 duplicate column name: Tim***amp in \"ALTER TABLE B** ADD COLUMN Tim***amp T**."); + EXPECT_EQ( + SqliteUtils::SqlAnonymous("recovered 9 frames from WAL file /data/storage/el1/database/entry/hello.db-wal"), + "recovered 9 frames from WAL file /dat***/sto***/e**/database/ent***/hel***.db-wal"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0016, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqlAnonymous_003, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("__23edf__.db"), "__23edf__.db"); + EXPECT_EQ(SqliteUtils::SqlAnonymous("30005245854585524412855412 123edf4 30005 300052"), + "***5412 ***edf4 30005 ***052"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0017, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0024, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("K3edfK.db"), "K3edfK.db"); + EXPECT_EQ(0, SqliteUtils::DeleteFolder("non_exist_folder/random123")); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0018, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0025, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("K23564edfK.db"), "K***4edfK.db"); + EXPECT_NE(0, SqliteUtils::SetSlaveRestoring("non_exist_folder/non_exist_file")); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0019, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, HandleNormalPath, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("K235648edfK.db"), "K***8edfK.db"); + EXPECT_EQ(SqliteUtils::GetParentModes("/data/service/el1/public/database/distributeddata/meta", 3), + "pub***:mode:d711 <- dat***:mode:d711 <- dis***:mode:d770"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0020, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, ExceedPathDepth, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("K2356489edfK.db"), "K***9edfK.db"); + EXPECT_EQ(SqliteUtils::GetParentModes("a/backup/c", 5), "a:access_fail <- bac***:access_fail"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0021, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, UnixRootPath, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("linker_reborn.db-wal"), "linker_reborn.db-wal"); + EXPECT_EQ(SqliteUtils::GetParentModes("/", 1), "no_parent"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0022, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, AccessFailureCase, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("linker_grow.db-wal"), "linker_grow.db-wal"); + EXPECT_NE(SqliteUtils::GetParentModes("a/non_existing_path", 1).find("access_fail"), std::string::npos); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0023, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, LongDirectoryName, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("file /data/stage/el2/database/rdb/ddddddd/linker_reborn.db-wal"), - "file /***/el2/***/linker_reborn.db-wal"); -} \ No newline at end of file + std::string longName(20, 'a'); + EXPECT_NE(SqliteUtils::GetParentModes(longName + "/b", 1).find("aaa***"), std::string::npos); +} diff --git a/relational_store/test/native/rdb/unittest/transaction_test.cpp b/relational_store/test/native/rdb/unittest/transaction_test.cpp index 657f227287dde8506f43c60ea2de8e6c5d01a5ff..e2c1fd5cac68b7862c5c77118f093c72e05fd192 100644 --- a/relational_store/test/native/rdb/unittest/transaction_test.cpp +++ b/relational_store/test/native/rdb/unittest/transaction_test.cpp @@ -16,7 +16,9 @@ #include #include +#include +#include "abs_rdb_predicates.h" #include "common.h" #include "rdb_errno.h" #include "rdb_helper.h" @@ -29,6 +31,9 @@ static const std::string DATABASE_NAME = RDB_TEST_PATH + "transaction_test.db"; static const char CREATE_TABLE_SQL[] = "CREATE TABLE IF NOT EXISTS test " "(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"; +static const char CREATE_TABLE1_SQL[] = + "CREATE TABLE IF NOT EXISTS test1 " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"; class TransactionTest : public testing::Test { public: @@ -64,8 +69,8 @@ void TransactionTest::SetUpTestCase() RdbStoreConfig config(DATABASE_NAME); TransactionTestOpenCallback helper; TransactionTest::store_ = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(TransactionTest::store_, nullptr); - EXPECT_EQ(errCode, E_OK); + ASSERT_NE(TransactionTest::store_, nullptr); + ASSERT_EQ(errCode, E_OK); } void TransactionTest::TearDownTestCase() @@ -76,6 +81,7 @@ void TransactionTest::TearDownTestCase() void TransactionTest::SetUp() { + ASSERT_NE(store_, nullptr); store_->Execute("DELETE FROM test"); } @@ -527,7 +533,7 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_011, TestSize.Level1) auto result = transaction->Insert("test1", row); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); ASSERT_EQ(transaction->Commit(), E_SQLITE_ERROR); @@ -568,7 +574,7 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_012, TestSize.Level1) auto result = transaction->Insert("test1", row); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); ASSERT_EQ(transaction->Commit(), E_OK); @@ -609,7 +615,7 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_013, TestSize.Level1) auto result = transaction->Insert("test1", row); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 2); ASSERT_EQ(transaction->Commit(), E_OK); @@ -650,7 +656,7 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_014, TestSize.Level1) auto result = transaction->Insert("test1", row); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 4); ASSERT_EQ(transaction->Commit(), E_OK); @@ -699,7 +705,7 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_015, TestSize.Level1) auto result = transaction->Insert("test1", row); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 5); ASSERT_EQ(transaction->Commit(), E_OK); @@ -748,7 +754,7 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_016, TestSize.Level1) auto result = transaction->Insert("test1", row); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); // ON_CONFLICT_REPLACE is equivalent to ON_CONFLICT_ABORT after failure ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); @@ -790,27 +796,27 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_017, TestSize.Level1) row.Put("name", "Jim_batchInsert"); rows.Put(row); } - auto result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); } @@ -841,34 +847,34 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_018, TestSize.Level1) row.Put("name", "Jim_batchInsert"); rows.Put(row); } - auto result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); } /** * @tc.name: RdbStore_Transaction_019 - * @tc.desc: Normal BatchInsertWithConflictResolution + * @tc.desc: Normal BatchInsert * @tc.type: FUNC */ HWTEST_F(TransactionTest, RdbStore_Transaction_019, TestSize.Level1) @@ -882,13 +888,13 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_019, TestSize.Level1) ASSERT_NE(transaction, nullptr); ValuesBuckets rows; - auto result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 0); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 0); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 0); for (int i = 0; i < 2; i++) { @@ -896,13 +902,13 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_019, TestSize.Level1) row.Put("name", "Jim_batchInsert"); rows.Put(row); } - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); @@ -974,8 +980,7 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_021, TestSize.Level1) ret = transaction->Commit(); EXPECT_EQ(ret, E_OK); - auto [err, rows] = transaction->Insert( - "test", UTUtils::SetRowData(UTUtils::g_rowData[0]), Transaction::NO_ACTION); + auto [err, rows] = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]), Transaction::NO_ACTION); EXPECT_EQ(err, E_ALREADY_CLOSED); } @@ -1032,7 +1037,7 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_023, TestSize.Level1) /** * @tc.name: RdbStore_Transaction_024 - * @tc.desc: Abnormal testcase of BatchInsertWithConflictResolution after commit. + * @tc.desc: Abnormal testcase of BatchInsert after commit. * @tc.type: FUNC */ HWTEST_F(TransactionTest, RdbStore_Transaction_024, TestSize.Level1) @@ -1053,9 +1058,11 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_024, TestSize.Level1) row.Put("name", "Jim"); rows.Put(row); } - auto result = transaction->BatchInsertWithConflictResolution( - "test", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + auto result = transaction->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_ALREADY_CLOSED); + + auto res = transaction->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_ROLLBACK); + ASSERT_EQ(res.first, E_ALREADY_CLOSED); } /** @@ -1170,6 +1177,9 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_029, TestSize.Level1) auto result = transaction->Execute(CREATE_TABLE_SQL); ASSERT_EQ(result.first, E_ALREADY_CLOSED); + + auto res = transaction->ExecuteExt(CREATE_TABLE_SQL); + ASSERT_EQ(res.first, E_ALREADY_CLOSED); } /** @@ -1193,4 +1203,1404 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_030, TestSize.Level1) ret = transaction->Rollback(); EXPECT_EQ(ret, E_ALREADY_CLOSED); -} \ No newline at end of file +} + +/** + * @tc.name: RdbStore_Transaction_031 + * @tc.desc: normal testcase of batch insert with returning 1. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_031, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + ValuesBuckets rows; + for (int i = 0; i < 1; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + std::string returningField = "id"; + auto [status, result] = transaction->BatchInsert("test", rows, { returningField }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1); + + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex(returningField, columnIndex), E_OK); + int value = -1; + result.results->GetInt(columnIndex, value); + EXPECT_EQ(value, 0); + ret = transaction->Commit(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_032 + * @tc.desc: normal testcase of batch insert with returning 0. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_032, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 2); + row.Put("name", "Jim"); + auto res = transaction->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 2); + rows.Put(row); + auto [status, result] = transaction->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 0); + ret = transaction->Commit(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_033 + * @tc.desc: normal testcase of batch insert with returning overlimit. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_033, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 1025; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto [status, result] = transaction->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + int rowCount = -1; + int maxRowCount = 1024; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, maxRowCount); + int colIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("id", colIndex), E_OK); + for (size_t i = 0; i < maxRowCount; i++) { + int value = -1; + ASSERT_EQ(result.results->GetInt(colIndex, value), E_OK); + EXPECT_EQ(value, i); + if (i != maxRowCount - 1) { + ASSERT_EQ(result.results->GoToNextRow(), E_OK); + } + } + + ret = transaction->Commit(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_034 + * @tc.desc: normal testcase of batch insert with not exist returning field. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_034, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::IMMEDIATE); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto [status, result] = + transaction->BatchInsert("test", rows, { "notExist" }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + ASSERT_EQ(result.results, nullptr); + + ret = transaction->Commit(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_035 + * @tc.desc: normal testcase of batch insert with Busy. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_035, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [res, transactionImme] = store->CreateTransaction(Transaction::IMMEDIATE); + ASSERT_EQ(res, E_OK); + ASSERT_NE(transactionImme, nullptr); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto [status, result] = transaction->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_SQLITE_BUSY); + EXPECT_EQ(result.changed, -1); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 0); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_036 + * @tc.desc: normal testcase of update with returning 1. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_036, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + Transaction::Row row; + row.Put("id", 1); + row.Put("name", "Jim"); + auto res = transaction->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 1); + + row.Put("name", "Bob"); + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 1); + auto [status, result] = transaction->Update(row, predicates, { "id" }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("id", columnIndex), E_OK); + int value = -1; + ASSERT_EQ(result.results->GetInt(columnIndex, value), E_OK); + EXPECT_EQ(value, 1); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_037 + * @tc.desc: abnormal testcase of update with returning 0. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_037, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + Transaction::Row row; + row.Put("id", 1); + row.Put("name", "Jim"); + auto res = transaction->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 1); + + row.Put("name", "Bob"); + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 2); + auto [status, result] = transaction->Update(row, predicates, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 0); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_038 + * @tc.desc: abnormal testcase of update with returning overlimit. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_038, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 1025; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto res = transaction->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(res.first, E_OK); + EXPECT_EQ(res.second, 1025); + + ValuesBucket row; + row.Put("name", "Tom"); + + AbsRdbPredicates predicates("test"); + auto [status, result] = transaction->Update(row, predicates, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1024); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_039 + * @tc.desc: abnormal testcase of update with returning not exist field. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_039, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 2; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto res = transaction->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(res.first, E_OK); + EXPECT_EQ(res.second, 2); + + ValuesBucket row; + row.Put("name", "Tom"); + + AbsRdbPredicates predicates("test"); + auto [status, result] = transaction->Update(row, predicates, { "notExist" }); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + ASSERT_EQ(result.results, nullptr); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_040 + * @tc.desc: abnormal testcase of update with Busy. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_040, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [res, transactionImme] = store->CreateTransaction(Transaction::IMMEDIATE); + ASSERT_EQ(res, E_OK); + ASSERT_NE(transactionImme, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto [status, result] = + transactionImme->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 5); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 5); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBucket row; + row.Put("name", "Tom"); + AbsRdbPredicates predicates("test"); + std::tie(status, result) = transaction->Update(row, predicates, { "id" }); + EXPECT_EQ(status, E_SQLITE_BUSY); + EXPECT_EQ(result.changed, -1); + + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 0); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_041 + * @tc.desc: normal testcase of delete with returning 1. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_041, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + Transaction::Row row; + row.Put("id", 1); + row.Put("name", "Jim"); + auto res = transaction->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 1); + + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 1); + auto [status, result] = transaction->Delete(predicates, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("id", columnIndex), E_OK); + int value = -1; + ASSERT_EQ(result.results->GetInt(columnIndex, value), E_OK); + EXPECT_EQ(value, 1); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_042 + * @tc.desc: normal testcase of delete with returning 0. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_042, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + Transaction::Row row; + row.Put("id", 1); + row.Put("name", "Jim"); + auto res = transaction->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 1); + + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 2); + auto [status, result] = transaction->Delete(predicates, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 0); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_043 + * @tc.desc: abnormal testcase of delete with returning over limit. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_043, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 1025; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto [status, result] = transaction->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1024); + + AbsRdbPredicates predicates("test"); + std::tie(status, result) = transaction->Delete(predicates, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1024); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_044 + * @tc.desc: abnormal testcase of delete with returning no exist field. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_044, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 2; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto [status, result] = transaction->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_ROLLBACK); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 2); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 2); + + AbsRdbPredicates predicates("test"); + std::tie(status, result) = transaction->Delete(predicates, { "noExist" }); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + + ASSERT_EQ(result.results, nullptr); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_045 + * @tc.desc: normal testcase of execute with returning over limit. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_045, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + std::vector args = { "tt", 28, 50000.0, "ttt", 58, 500080.0 }; + auto [status, result] = + transaction->ExecuteExt("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?) returning name", args); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 2); + + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 2); + + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "tt"); + ASSERT_EQ(result.results->GoToNextRow(), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "ttt"); + + std::tie(status, result) = + transaction->ExecuteExt("update test set name = ? where name = ? returning name", { "update", "tt" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1); + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + result.results->GetString(columnIndex, value); + EXPECT_EQ(value, "update"); + + std::tie(status, result) = transaction->ExecuteExt("delete from test returning name"); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 2); + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 2); + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "update"); + ASSERT_EQ(result.results->GoToNextRow(), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "ttt"); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_046 + * @tc.desc: abnormal testcase of execute with returning. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_046, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::IMMEDIATE); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + std::vector args = { "0", 0 }; + std::string sql = "INSERT INTO test(name, age) VALUES (?, ?)"; + for (int32_t i = 1; i < 1025; i++) { + sql.append(", (?, ?)"); + args.push_back(std::to_string(i)); + args.push_back(i); + } + auto [status, result] = transaction->ExecuteExt(sql + " returning name", args); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1024); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "0"); + ASSERT_EQ(result.results->GoToRow(1000), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "1000"); + + std::tie(status, result) = transaction->ExecuteExt("update test set name = ? returning name", { "update" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1024); + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "update"); + + std::tie(status, result) = transaction->ExecuteExt("delete from test returning name", {}); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1024); + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "update"); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_047 + * @tc.desc: normal testcase of execute with returning 0 rows. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_047, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + std::vector args = { 1, "tt", 28, 50000.0 }; + auto [status, result] = + transaction->ExecuteExt("INSERT INTO test(id, name, age, salary) VALUES (?, ?, ?, ?) returning id", args); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("id", columnIndex), E_OK); + int64_t value; + ASSERT_EQ(result.results->GetLong(columnIndex, value), E_OK); + EXPECT_EQ(value, 1); + std::tie(status, result) = + transaction->ExecuteExt("INSERT INTO test(id, name, age, salary) VALUES (?, ?, ?, ?) returning id", args); + EXPECT_EQ(status, E_SQLITE_CONSTRAINT); + EXPECT_EQ(result.changed, 0); + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); + + std::tie(status, result) = + transaction->ExecuteExt("update test set name = ? where name = ? returning name", { "update", "noExist" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); + + std::tie(status, result) = transaction->ExecuteExt("delete from test where name = ? returning name", { "noExist" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_048 + * @tc.desc: abnormal testcase of execute busy with returning. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_048, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [res, immeTrans] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(res, E_OK); + ASSERT_NE(immeTrans, nullptr); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + std::vector args = { 1, "tt", 28, 50000.0 }; + auto [status, result] = + transaction->ExecuteExt("INSERT INTO test(id, name, age, salary) VALUES (?, ?, ?, ?) returning id", args); + EXPECT_EQ(status, E_SQLITE_BUSY); + EXPECT_EQ(result.changed, -1); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); + + std::tie(status, result) = + transaction->ExecuteExt("update test set name = ? where name = ? returning name", { "update", "noExist" }); + EXPECT_EQ(status, E_SQLITE_BUSY); + EXPECT_EQ(result.changed, -1); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); + + + std::tie(status, result) = transaction->ExecuteExt("delete from test where name = ? returning name", { "noExist" }); + EXPECT_EQ(status, E_SQLITE_BUSY); + EXPECT_EQ(result.changed, -1); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_049 + * @tc.desc: Crash Occurs When Test Commit Fails + * This test case constructs a transaction commit failure scenario. + * A special command is used to operate the database file. + * To avoid affecting other test cases, this test case uses an independent database file. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_049, TestSize.Level1) +{ + const std::string dbPath = RDB_TEST_PATH + "transaction049_test.db"; + RdbHelper::DeleteRdbStore(dbPath); + RdbStoreConfig config(dbPath); + config.SetHaMode(HAMode::MAIN_REPLICA); // Dual-write must be enabled. + config.SetReadOnly(false); + TransactionTestOpenCallback helper; + int errCode = E_OK; + const int version = 1; + std::shared_ptr storePtr = RdbHelper::GetRdbStore(config, version, helper, errCode); + EXPECT_NE(storePtr, nullptr); + EXPECT_EQ(errCode, E_OK); + + storePtr->Execute("DROP TABLE IF EXISTS test1"); + auto res = storePtr->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)"); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = storePtr->CreateTransaction(Transaction::IMMEDIATE); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + const int idValue = 1; + Transaction::Row row; + row.Put("id", idValue); + row.Put("name", "Jim"); + auto result = transaction->Insert("test1", row); + ASSERT_EQ(result.first, E_OK); + const int count = 1; + ASSERT_EQ(result.second, count); + + // Constructing a Commit Failure Scenario + std::string walFile = dbPath + "-wal"; + + // Disabling wal File Operations + std::string chattrAddiCmd = "chattr +i " + walFile; + system(chattrAddiCmd.c_str()); + + ret = transaction->Commit(); + EXPECT_NE(ret, E_OK); + + // Enable the wal file operation. + std::string chattrSubiCmd = "chattr -i " + walFile; + system(chattrSubiCmd.c_str()); + + RdbHelper::DeleteRdbStore(dbPath); +} + +/** + * @tc.name: RdbStore_Transaction_050 + * @tc.desc: abnormal testcase of trigger delete with returning in trans. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_050, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [res, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(res, E_OK); + ASSERT_NE(transaction, nullptr); + + auto [code, result1] = transaction->Execute( + "CREATE TRIGGER before_update BEFORE UPDATE ON test" + " BEGIN DELETE FROM test WHERE name = 'wang'; END"); + EXPECT_EQ(code, E_OK); + + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 200); + row.Put("name", "wang"); + rows.Put(std::move(row)); + row.Put("id", 201); + row.Put("name", "zhang"); + rows.Put(std::move(row)); + + auto [status, result] = + transaction->BatchInsert("test", rows, { "name" }, ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 2); + ASSERT_NE(result.results, nullptr); + + auto predicates = AbsRdbPredicates("test"); + predicates.EqualTo("name", "zhang"); + ValuesBucket values; + values.PutString("name", "liu"); + + std::tie(status, result) = transaction->Update(values, predicates, { "name" }); + + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "liu"); + + // Check the trigger effect + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + + rowCount = -1; + resultSet->GetRowCount(rowCount); + ASSERT_EQ(rowCount, 1); + + transaction->Execute("DROP TRIGGER IF EXISTS before_update"); + + int ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_051 + * @tc.desc: abnormal testcase of trigger update with returning in trans. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_051, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [res, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(res, E_OK); + ASSERT_NE(transaction, nullptr); + + auto [code, result1] = transaction->Execute( + "CREATE TRIGGER before_delete BEFORE DELETE ON test" + " BEGIN UPDATE test SET name = 'li' WHERE name = 'zhao'; END"); + EXPECT_EQ(code, E_OK); + + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 201); + row.Put("name", "zhang"); + rows.Put(std::move(row)); + row.Put("id", 202); + row.Put("name", "zhao"); + rows.Put(std::move(row)); + + auto [status, result] = + transaction->BatchInsert("test", rows, { "name" }, ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 2); + ASSERT_NE(result.results, nullptr); + + AbsRdbPredicates predicates("test"); + predicates.EqualTo("name", "zhang"); + std::tie(status, result) = transaction->Delete(predicates, { "name" }); + + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + std::string value; + ASSERT_EQ(result.results->GetString(0, value), E_OK); + EXPECT_EQ(value, "zhang"); + + // Check the trigger effect + AbsRdbPredicates predicates1("test"); + predicates1.EqualTo("id", 202); + auto queryResult = transaction->QueryByStep(predicates1, { "name" }); + + rowCount = -1; + queryResult->GetRowCount(rowCount); + ASSERT_EQ(rowCount, 1); + ASSERT_EQ(queryResult->GoToNextRow(), E_OK); + + value.clear(); + EXPECT_EQ(E_OK, queryResult->GetString(0, value)); + EXPECT_EQ(value, "li"); + + transaction->Execute("DROP TRIGGER IF EXISTS before_update"); + + int ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_052 + * @tc.desc: abnormal testcase of virtual table with returning in transaction. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_052, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + auto [createTableStatus, createTableresult] = + store->Execute("CREATE VIRTUAL TABLE IF NOT EXISTS articles USING fts5(title, content);"); + + auto [res, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(res, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + ValuesBucket row; + row.Put("title", "fts5"); + row.Put("content", "test virtual tables"); + rows.Put(std::move(row)); + auto [status, result] = + transaction->BatchInsert("articles", rows, {"title"}, ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(std::string(rowEntity.Get("title")), "fts5"); + + AbsRdbPredicates predicates("test"); + predicates.EqualTo("title", "fts5"); + ValuesBucket values; + values.PutString("title", "fts5 updated"); + + std::tie(status, result) = transaction->Update(values, predicates, { "title" }); + // UPDATE RETURNING is not available on virtual tables + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + EXPECT_EQ(result.results, nullptr); + + std::tie(status, result) = store_->Delete(predicates, { "title" }); + // DELETE RETURNING is not available on virtual tables + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + + transaction->Execute("Drop TABLE articles"); + EXPECT_EQ(transaction->Rollback(), E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_053 + * @tc.desc: abnormal testcase of drop the table before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_053, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + int rowCount = 0; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + auto [rs, obj] = transaction->Execute("DROP TABLE test"); + ASSERT_EQ(rs, E_SQLITE_LOCKED); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + rs = transaction->Rollback(); + ASSERT_EQ(rs, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_054 + * @tc.desc: abnormal testcase of drop the table before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_054, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + int rowCount = 0; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount - 1; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + auto [rs, obj] = transaction->Execute("DROP TABLE test"); + ASSERT_EQ(rs, E_SQLITE_LOCKED); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + rs = transaction->Rollback(); + ASSERT_EQ(rs, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_055 + * @tc.desc: normal testcase of drop the table after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_055, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [rt, object] = store->Execute(CREATE_TABLE1_SQL); + ASSERT_EQ(rt, E_OK); + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test1", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test1", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test1"); + int rowCount = 0; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + ret = resultSet->Close(); + ASSERT_EQ(ret, E_OK); + + auto [rs, obj] = transaction->Execute("DROP TABLE test1"); + ASSERT_EQ(rs, E_OK); + + rs = transaction->Commit(); + ASSERT_EQ(rs, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_056 + * @tc.desc: abnormal testcase of drop the index before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_056, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [rt, object] = store->Execute("CREATE INDEX test_index ON test(age)"); + ASSERT_EQ(rt, E_OK); + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + int rowCount = 0; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + auto [rs, obj] = transaction->Execute("DROP INDEX test_index"); + ASSERT_EQ(rs, E_SQLITE_LOCKED); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + rs = transaction->Rollback(); + ASSERT_EQ(rs, E_OK); + + std::tie(rt, object) = store->Execute("DROP INDEX test_index"); + ASSERT_EQ(rt, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_057 + * @tc.desc: abnormal testcase of drop the index before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_057, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [rt, object] = store->Execute("CREATE INDEX test_index ON test(age)"); + ASSERT_EQ(rt, E_OK); + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + int rowCount = 0; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount - 1; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + auto [rs, obj] = transaction->Execute("DROP INDEX test_index"); + ASSERT_EQ(rs, E_SQLITE_LOCKED); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + rs = transaction->Rollback(); + ASSERT_EQ(rs, E_OK); + + std::tie(rt, object) = store->Execute("DROP INDEX test_index"); + ASSERT_EQ(rt, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_058 + * @tc.desc: normal testcase of drop the index after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_058, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [rt, object] = store->Execute("CREATE INDEX test_index ON test(age)"); + ASSERT_EQ(rt, E_OK); + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + int rowCount = 0; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + ret = resultSet->Close(); + ASSERT_EQ(ret, E_OK); + + auto [rs, obj] = transaction->Execute("DROP INDEX test_index"); + ASSERT_EQ(rs, E_OK); + + rs = transaction->Commit(); + ASSERT_EQ(rs, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_059 + * @tc.desc: normal testcase of drop the table after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_059, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [rt, object] = store->Execute(CREATE_TABLE1_SQL); + ASSERT_EQ(rt, E_OK); + + auto [res, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(res, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test1"); + int rowCount = 0; + auto ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + auto [rs, obj] = transaction->Execute("DROP TABLE test1"); + ASSERT_EQ(rs, E_OK); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + + rs = transaction->Commit(); + ASSERT_EQ(rs, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_060 + * @tc.desc: normal testcase of drop the index after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_060, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [rt, object] = store->Execute("CREATE INDEX test_index ON test(age)"); + ASSERT_EQ(rt, E_OK); + + auto [res, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(res, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + int rowCount = 0; + auto ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + auto [rs, obj] = transaction->Execute("DROP INDEX test_index"); + ASSERT_EQ(rs, E_OK); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + + rs = transaction->Commit(); + ASSERT_EQ(rs, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_061 + * @tc.desc: abnormal testcase of drop the table before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_061, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [rt, object] = store->Execute(CREATE_TABLE1_SQL); + ASSERT_EQ(rt, E_OK); + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + int rowCount = 0; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + auto [rs, obj] = transaction->Execute("DROP TABLE test1"); + ASSERT_EQ(rs, E_SQLITE_LOCKED); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + rs = transaction->Rollback(); + ASSERT_EQ(rs, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_062 + * @tc.desc: abnormal testcase of drop the table before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_062, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + + auto [rs, obj] = transaction->Execute("DROP TABLE test"); + ASSERT_EQ(rs, E_OK); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + rs = transaction->Rollback(); + ASSERT_EQ(rs, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_063 + * @tc.desc: normal testcase of drop the table before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_063, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + int rowCount = 0; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + ret = resultSet->GoToNextRow(); + ASSERT_NE(ret, E_OK); + + auto [rs, obj] = transaction->Execute("DROP TABLE test"); + ASSERT_EQ(rs, E_OK); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + rs = transaction->Rollback(); + ASSERT_EQ(rs, E_OK); +} diff --git a/relational_store/test/native/rdb_data_ability_adapter/BUILD.gn b/relational_store/test/native/rdb_data_ability_adapter/BUILD.gn index 2f8e645bd7a82a3f14be8381a483ca6024a8284d..51c3ad6cc30d2628516e7e2169bd44e541bd0990 100644 --- a/relational_store/test/native/rdb_data_ability_adapter/BUILD.gn +++ b/relational_store/test/native/rdb_data_ability_adapter/BUILD.gn @@ -11,7 +11,6 @@ # See the License for the specific language governing permissions and # limitations under the License. import("//build/test.gni") -import("//foundation/distributeddatamgr/data_share/datashare.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") module_output_path = @@ -22,10 +21,8 @@ config("module_private_config") { visibility = [ ":*" ] include_dirs = [ - "${datashare_innerapi_path}/common/include", "${relational_store_innerapi_path}/dataability/include", "${relational_store_innerapi_path}/rdb_data_ability_adapter/include", - "//commonlibrary/c_utils/base/include", ] } @@ -38,15 +35,15 @@ ohos_unittest("NativeDataAbilityAdapterTest") { external_deps = [ "c_utils:utils", + "data_share:datashare_common_lite", + "googletest:gtest_main", "hilog:libhilog", + "ipc:ipc_single", "relational_store:native_dataability", "relational_store:rdb_data_ability_adapter", ] - deps = [ - "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", - ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] } ############################################################################### diff --git a/relational_store/test/native/rdb_data_share_adapter/BUILD.gn b/relational_store/test/native/rdb_data_share_adapter/BUILD.gn index 70a8a93b8ba2c690fcfc88e0ef9dd73d213ae094..e00a6209078301205a645a7ad1e3de76aa945a55 100644 --- a/relational_store/test/native/rdb_data_share_adapter/BUILD.gn +++ b/relational_store/test/native/rdb_data_share_adapter/BUILD.gn @@ -11,7 +11,6 @@ # See the License for the specific language governing permissions and # limitations under the License. import("//build/test.gni") -import("//foundation/distributeddatamgr/data_share/datashare.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") module_output_path = "relational_store/relational_store/rdb_data_share_adapter" @@ -23,27 +22,16 @@ config("module_private_config") { include_dirs = [ "${relational_store_common_path}/include", "${relational_store_native_path}/rdb_data_share_adapter/include", - "${datashare_common_native_path}/include", "${relational_store_innerapi_path}/rdb/src", "${relational_store_innerapi_path}/rdb_data_share_adapter/src", - "${datashare_base_path}/interfaces/inner_api/common/include", - "${datashare_base_path}/interfaces/inner_api/consumer/include", - "${datashare_base_path}/interfaces/inner_api/provider/include", "${relational_store_innerapi_path}/rdb/include", "${relational_store_innerapi_path}/rdb_data_share_adapter/include", - "//commonlibrary/c_utils/base/include", ] cflags = [ "-fno-access-control", #Ignore Private Member Access Control ] - if (relational_store_rdb_support_icu) { - include_dirs += [ - "//third_party/icu/icu4c/source/i18n", - "//third_party/icu/icu4c/source/common", - ] - } } ohos_unittest("RdbDataShareAdapterTest") { @@ -55,16 +43,22 @@ ohos_unittest("RdbDataShareAdapterTest") { external_deps = [ "c_utils:utils", + "data_share:datashare_common_lite", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "ipc:ipc_single", "relational_store:rdb_data_share_adapter", ] - deps = [ - "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", - "//third_party/icu/icu4c:shared_icui18n", - "//third_party/icu/icu4c:shared_icuuc", - ] + if (relational_store_rdb_support_icu) { + external_deps += [ + "icu:shared_icui18n", + "icu:shared_icuuc", + ] + } + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] } ############################################################################### diff --git a/relational_store/test/native/rdb_data_share_adapter/unittest/rdb_data_share_adapter_test.cpp b/relational_store/test/native/rdb_data_share_adapter/unittest/rdb_data_share_adapter_test.cpp index 2c4ee8c1ef1403b2d3e5378efc401e67344e6c95..210881ee156729accf199924e31a30e539162562 100644 --- a/relational_store/test/native/rdb_data_share_adapter/unittest/rdb_data_share_adapter_test.cpp +++ b/relational_store/test/native/rdb_data_share_adapter/unittest/rdb_data_share_adapter_test.cpp @@ -1,524 +1,788 @@ -/* - * Copyright (c) 2022 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 "RdbDataShareAdapterTest" -#include - -#include - -#include "datashare_predicates.h" -#include "logger.h" -#include "rdb_errno.h" -#include "rdb_helper.h" -#include "rdb_open_callback.h" -#include "rdb_utils.h" - -using namespace testing::ext; -using namespace OHOS::Rdb; -using namespace OHOS::NativeRdb; -using namespace OHOS::DataShare; -using namespace OHOS::RdbDataShareAdapter; - -class RdbDataShareAdapterTest : public testing::Test { -public: - static void SetUpTestCase(void); - - static void TearDownTestCase(void); - - void SetUp(); - - void TearDown(); - - void GenerateDefaultTable(); - - void GenerateDefaultEmptyTable(); - - int ResultSize(std::shared_ptr resultSet); - - static const std::string DATABASE_NAME; - static std::shared_ptr store; - static const std::string RDB_ADAPTER_TEST_PATH; -}; - -const std::string RdbDataShareAdapterTest::RDB_ADAPTER_TEST_PATH = "/data/test/"; -const std::string RdbDataShareAdapterTest::DATABASE_NAME = RDB_ADAPTER_TEST_PATH + "rdbDataShareAdapter_test.db"; -std::shared_ptr RdbDataShareAdapterTest::store = nullptr; - -class RdbStepSharedResultSetOpenCallback : public RdbOpenCallback { -public: - int OnCreate(RdbStore &store) override; - - int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; - - static const std::string CREATE_TABLE_TEST; -}; - -int RdbStepSharedResultSetOpenCallback::OnCreate(RdbStore &store) -{ - return OHOS::NativeRdb::E_OK; -} - -int RdbStepSharedResultSetOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) -{ - return OHOS::NativeRdb::E_OK; -} - -void RdbDataShareAdapterTest::SetUpTestCase(void) -{ - int errCode = OHOS::NativeRdb::E_OK; - RdbStoreConfig config(RdbDataShareAdapterTest::DATABASE_NAME); - RdbStepSharedResultSetOpenCallback helper; - RdbDataShareAdapterTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(RdbDataShareAdapterTest::store, nullptr); - EXPECT_EQ(errCode, OHOS::NativeRdb::E_OK); -} - -void RdbDataShareAdapterTest::TearDownTestCase(void) -{ - RdbHelper::DeleteRdbStore(RdbDataShareAdapterTest::DATABASE_NAME); -} - -void RdbDataShareAdapterTest::SetUp(void) -{ - store->ExecuteSql("DROP TABLE IF EXISTS test"); -} - -void RdbDataShareAdapterTest::TearDown(void) -{ - RdbHelper::ClearCache(); -} - -void RdbDataShareAdapterTest::GenerateDefaultTable() -{ - std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, ") + - std::string("data2 INTEGER, data3 FLOAT, data4 BLOB);"); - store->ExecuteSql(createTableSql); - - std::string insertSql = "INSERT INTO test (data1, data2, data3, data4) VALUES (?, ?, ?, ?);"; - - /* insert first entry data */ - uint8_t uValue = 66; - std::vector typeBlob; - typeBlob.push_back(uValue); - store->ExecuteSql(insertSql, std::vector{ ValueObject(std::string("hello")), ValueObject((int)10), - ValueObject((double)1.0), ValueObject((std::vector)typeBlob) }); - - /* insert second entry data */ - typeBlob.clear(); - store->ExecuteSql(insertSql, std::vector{ - ValueObject(std::string("2")), ValueObject((int)-5), ValueObject((double)2.5), - ValueObject() // set double value 2.5 - }); - - /* insert third entry data */ - store->ExecuteSql(insertSql, std::vector{ - ValueObject(std::string("hello world")), ValueObject((int)3), ValueObject((double)1.8), - ValueObject(std::vector{ 4, 5, 6 }) // set int value 3, double 1.8 - }); - - /* insert four entry data */ - store->ExecuteSql(insertSql, std::vector{ - ValueObject(std::string("new world")), ValueObject((int)5), - ValueObject((double)5.8), ValueObject() // set int value 5, double 5.8 - }); -} - -void RdbDataShareAdapterTest::GenerateDefaultEmptyTable() -{ - std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, ") + - std::string("data2 INTEGER, data3 FLOAT, data4 BLOB);"); - store->ExecuteSql(createTableSql); -} - -int RdbDataShareAdapterTest::ResultSize(std::shared_ptr resultSet) -{ - if (resultSet->GoToFirstRow() != OHOS::NativeRdb::E_OK) { - return 0; - } - int count = 1; - while (resultSet->GoToNextRow() == OHOS::NativeRdb::E_OK) { - count++; - } - return count; -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_001 - * @tc.desc: test RdbDataShareAdapter - * @tc.type: FUNC - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_001, TestSize.Level1) -{ - GenerateDefaultTable(); - - std::shared_ptr resultSet = store->QueryByStep("SELECT * FROM test"); - EXPECT_NE(resultSet, nullptr); - int rowCount; - resultSet.get()->GetRowCount(rowCount); - LOG_INFO("result row count: %{public}d", rowCount); - EXPECT_NE(rowCount, 0); - auto bridge = OHOS::RdbDataShareAdapter::RdbUtils::ToResultSetBridge(resultSet); - EXPECT_NE(bridge, nullptr); -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_002 - * @tc.desc: normal testcase of RdbDataShareAdapter - * @tc.type: FUNC - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_002, TestSize.Level1) -{ - GenerateDefaultTable(); - - std::string table = "test"; - std::string column = "data1"; - std::string value = "hello"; - DataSharePredicates predicates; - predicates.EqualTo(column, value); - std::vector columns; - auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); - int rowCount; - allDataTypes.get()->GetRowCount(rowCount); - EXPECT_EQ(rowCount, 1); -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_003 - * @tc.desc: normal testcase of RdbDataShareAdapter - * @tc.type: FUNC - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_003, TestSize.Level1) -{ - GenerateDefaultTable(); - - std::string table = "test"; - OHOS::DataShare::DataSharePredicates predicates; - predicates.GreaterThan("data2", -5); - std::vector columns; - auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); - int rdbRowCount; - allDataTypes.get()->GetRowCount(rdbRowCount); - EXPECT_EQ(rdbRowCount, 3); - - allDataTypes->GoToFirstRow(); - - std::string strValue; - allDataTypes->GetString(1, strValue); - EXPECT_EQ("hello", strValue); - - int intValue; - allDataTypes->GetInt(2, intValue); - EXPECT_EQ(intValue, 10); - - std::vector blobValue; - uint8_t blobData = 66; - allDataTypes->GetBlob(4, blobValue); - EXPECT_EQ(blobData, blobValue[0]); - - allDataTypes->GoToNextRow(); - allDataTypes->GetBlob(4, blobValue); - EXPECT_EQ(3, static_cast(blobValue.size())); - blobData = 5; - EXPECT_EQ(blobData, blobValue[1]); -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_004 - * @tc.desc: normal testcase of RdbDataShareAdapter - * @tc.type: FUNC - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_004, TestSize.Level1) -{ - GenerateDefaultTable(); - - std::string table = "test"; - OHOS::DataShare::DataSharePredicates predicates; - predicates.SetWhereClause("`data2` > ?"); - predicates.SetWhereArgs(std::vector{ "-5" }); - predicates.SetOrder("data3"); - std::vector columns; - auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); - int rowCount; - allDataTypes.get()->GetRowCount(rowCount); - EXPECT_EQ(rowCount, 3); - - allDataTypes->GoToFirstRow(); - - std::string strValue; - allDataTypes->GetString(1, strValue); - EXPECT_EQ("hello", strValue); - - int intValue; - allDataTypes->GetInt(2, intValue); - EXPECT_EQ(intValue, 10); - - std::vector blobValue; - allDataTypes->GetBlob(4, blobValue); - EXPECT_EQ(1, static_cast(blobValue.size())); - - allDataTypes->GoToNextRow(); - - allDataTypes->GetString(1, strValue); - EXPECT_EQ("hello world", strValue); - - allDataTypes->GetInt(2, intValue); - EXPECT_EQ(intValue, 3); - - allDataTypes->GetBlob(4, blobValue); - EXPECT_EQ(3, static_cast(blobValue.size())); - uint8_t blobData = 5; - EXPECT_EQ(blobData, blobValue[1]); -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_005 - * @tc.desc: normal testcase of RdbDataShareAdapter - * @tc.type: FUNC - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_005, TestSize.Level1) -{ - GenerateDefaultTable(); - DataShareValuesBucket values; - int64_t id; - int changedRows; - values.Put("data1", std::string("tulip")); - values.Put("data2", 100); - values.Put("data3", 50.5); - values.Put("data4", std::vector{ 20, 21, 22 }); - - int ret = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); - EXPECT_EQ(ret, OHOS::NativeRdb::E_OK); - EXPECT_EQ(5, id); - - std::string table = "test"; - OHOS::DataShare::DataSharePredicates predicates; - std::string value = "tulip"; - predicates.EqualTo("data1", value); - std::vector columns; - auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); - int rowCount; - allDataTypes.get()->GetRowCount(rowCount); - EXPECT_EQ(rowCount, 1); - - allDataTypes.get()->Close(); - - values.Clear(); - values.Put("data3", 300.5); - values.Put("data4", std::vector{ 17, 18, 19 }); - ret = store->Update( - changedRows, "test", RdbUtils::ToValuesBucket(values), "data1 = ?", std::vector{ "tulip" }); - EXPECT_EQ(ret, OHOS::NativeRdb::E_OK); - EXPECT_EQ(1, changedRows); - - allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); - allDataTypes->GoToFirstRow(); - - double doubleVal; - allDataTypes->GetDouble(3, doubleVal); - EXPECT_EQ(300.5, doubleVal); - - int deletedRows; - ret = store->Delete(deletedRows, RdbUtils::ToPredicates(predicates, table)); - EXPECT_EQ(ret, OHOS::NativeRdb::E_OK); - EXPECT_EQ(1, deletedRows); -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_006 - * @tc.desc: normal testcase of RdbDataShareAdapter - * @tc.type: FUNC - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_006, TestSize.Level1) -{ - GenerateDefaultTable(); - - std::string table = "test"; - OHOS::DataShare::DataSharePredicates predicates; - predicates.Limit(1, 2); - std::vector columns; - auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); - int rdbRowCount; - allDataTypes.get()->GetRowCount(rdbRowCount); - EXPECT_EQ(rdbRowCount, 1); - - allDataTypes->GoToFirstRow(); - - std::string strValue; - allDataTypes->GetString(1, strValue); - EXPECT_EQ("hello world", strValue); - - int intValue; - allDataTypes->GetInt(2, intValue); - EXPECT_EQ(intValue, 3); - - double doubleValue; - allDataTypes->GetDouble(3, doubleValue); - EXPECT_EQ(doubleValue, 1.8); - - std::vector blobValue; - uint8_t blobData1 = 4; - uint8_t blobData2 = 5; - uint8_t blobData3 = 6; - allDataTypes->GetBlob(4, blobValue); - EXPECT_EQ(3, static_cast(blobValue.size())); - EXPECT_EQ(blobData1, blobValue[0]); - EXPECT_EQ(blobData2, blobValue[1]); - EXPECT_EQ(blobData3, blobValue[2]); -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_007 - * @tc.desc: normal testcase of RdbDataShareAdapter - * @tc.type: FUNC - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_007, TestSize.Level1) -{ - std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT,") + - std::string("age INTEGER, salary REAL);"); - store->ExecuteSql(createTableSql); - - DataShareValuesBucket values; - int64_t id; - values.Put("name", std::string("zhangsan")); - values.Put("age", INT64_MIN); - values.Put("salary", DBL_MIN); - int ret1 = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); - EXPECT_EQ(ret1, OHOS::NativeRdb::E_OK); - EXPECT_EQ(1, id); - - values.Clear(); - values.Put("name", std::string("lisi")); - values.Put("age", INT64_MAX); - values.Put("salary", DBL_MAX); - int ret2 = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); - EXPECT_EQ(ret2, OHOS::NativeRdb::E_OK); - EXPECT_EQ(2, id); - - std::string table = "test"; - OHOS::DataShare::DataSharePredicates predicates; - std::vector columns; - auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); - - allDataTypes->GoToFirstRow(); - int64_t int64Value; - allDataTypes->GetLong(2, int64Value); - EXPECT_EQ(int64Value, INT64_MIN); - - double doubleVal; - allDataTypes->GetDouble(3, doubleVal); - EXPECT_EQ(doubleVal, DBL_MIN); - - allDataTypes->GoToNextRow(); - - allDataTypes->GetLong(2, int64Value); - EXPECT_EQ(int64Value, INT64_MAX); - - allDataTypes->GetDouble(3, doubleVal); - EXPECT_EQ(doubleVal, DBL_MAX); -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_008 - * @tc.desc: normal testcase of query double - * @tc.type: test double for high accuracy - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_008, TestSize.Level1) -{ - std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 double,") + - std::string("data2 double, data3 TEXT);"); - store->ExecuteSql(createTableSql); - - ValuesBucket values; - int64_t id; - double data1 = 1.777777777777; - double data2 = 1.888888888888; - std::string data3 = "zh-has"; - std::string tableName = "test"; - - values.PutDouble("data1", data1); - values.PutDouble("data2", data2); - values.PutString("data3", data3); - int ret = store->Insert(id, tableName, values); - EXPECT_EQ(ret, OHOS::NativeRdb::E_OK); - EXPECT_EQ(1, id); - - OHOS::DataShare::DataSharePredicates predicates; - predicates.BeginWrap() - ->EqualTo("data1", data1) - ->And() - ->EqualTo("data2", data2) - ->And() - ->EqualTo("data3", data3) - ->EndWrap(); - std::vector columns; - auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, tableName), columns); - int rowCount; - int ok = allDataTypes->GetRowCount(rowCount); - EXPECT_EQ(ok, OHOS::NativeRdb::E_OK); - EXPECT_EQ(1, rowCount); -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_009 - * @tc.desc: normal testcase of RdbDataShareAdapter - * @tc.type: FUNC - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_009, TestSize.Level1) -{ - std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT,") + - std::string("age INTEGER, salary REAL);"); - store->ExecuteSql(createTableSql); - - DataShareValuesBucket values; - int64_t id; - values.Put("name", std::string("zhangsan")); - values.Put("age", INT64_MIN); - values.Put("salary", DBL_MIN); - int ret1 = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); - EXPECT_EQ(ret1, OHOS::NativeRdb::E_OK); - EXPECT_EQ(1, id); - - values.Clear(); - values.Put("name", std::string("lisi")); - values.Put("age", INT64_MAX); - values.Put("salary", DBL_MAX); - int ret2 = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); - EXPECT_EQ(ret2, OHOS::NativeRdb::E_OK); - EXPECT_EQ(2, id); - - std::string table = "test"; - OHOS::DataShare::OperationItem item; - item.singleParams = {}; - RdbPredicates predicates("test"); - RdbUtils::EqualTo(item, predicates); - std::vector columns; - std::shared_ptr allPerson = store->Query(predicates, columns); - EXPECT_EQ(2, ResultSize(allPerson)); - - RdbUtils::GreaterThan(item, predicates); - allPerson = store->Query(predicates, columns); - EXPECT_EQ(2, ResultSize(allPerson)); - - RdbUtils::Limit(item, predicates); - allPerson = store->Query(predicates, columns); - EXPECT_EQ(2, ResultSize(allPerson)); - - RdbUtils::NotEqualTo(item, predicates); - allPerson = store->Query(predicates, columns); - EXPECT_EQ(2, ResultSize(allPerson)); - - RdbUtils::LessThan(item, predicates); - allPerson = store->Query(predicates, columns); - EXPECT_EQ(2, ResultSize(allPerson)); -} +///* +// * Copyright (c) 2022 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 "RdbDataShareAdapterTest" +//#include +//#include +// +//#include +// +//#include "datashare_predicates.h" +//#include "logger.h" +//#include "rdb_errno.h" +//#include "rdb_helper.h" +//#include "rdb_open_callback.h" +//#include "rdb_utils.h" +// +//using namespace testing::ext; +//using namespace OHOS::Rdb; +//using namespace OHOS::NativeRdb; +//using namespace OHOS::DataShare; +//using namespace OHOS::RdbDataShareAdapter; +// +//class RdbDataShareAdapterTest : public testing::Test { +//public: +// static void SetUpTestCase(void); +// +// static void TearDownTestCase(void); +// +// void SetUp(); +// +// void TearDown(); +// +// void GenerateDefaultTable(); +// +// void GenerateDefaultEmptyTable(); +// +// int ResultSize(std::shared_ptr resultSet); +// +// static const std::string DATABASE_NAME; +// static std::shared_ptr store; +// static const std::string RDB_ADAPTER_TEST_PATH; +//}; +// +//const std::string RdbDataShareAdapterTest::RDB_ADAPTER_TEST_PATH = "/data/test/"; +//const std::string RdbDataShareAdapterTest::DATABASE_NAME = RDB_ADAPTER_TEST_PATH + "rdbDataShareAdapter_test.db"; +//std::shared_ptr RdbDataShareAdapterTest::store = nullptr; +// +//class RdbStepSharedResultSetOpenCallback : public RdbOpenCallback { +//public: +// int OnCreate(RdbStore &store) override; +// +// int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +// +// static const std::string CREATE_TABLE_TEST; +//}; +// +//int RdbStepSharedResultSetOpenCallback::OnCreate(RdbStore &store) +//{ +// return OHOS::NativeRdb::E_OK; +//} +// +//int RdbStepSharedResultSetOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +//{ +// return OHOS::NativeRdb::E_OK; +//} +// +//void RdbDataShareAdapterTest::SetUpTestCase(void) +//{ +// int errCode = OHOS::NativeRdb::E_OK; +// RdbStoreConfig config(RdbDataShareAdapterTest::DATABASE_NAME); +// RdbStepSharedResultSetOpenCallback helper; +// RdbDataShareAdapterTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_NE(RdbDataShareAdapterTest::store, nullptr); +// EXPECT_EQ(errCode, OHOS::NativeRdb::E_OK); +//} +// +//void RdbDataShareAdapterTest::TearDownTestCase(void) +//{ +// RdbHelper::DeleteRdbStore(RdbDataShareAdapterTest::DATABASE_NAME); +//} +// +//void RdbDataShareAdapterTest::SetUp(void) +//{ +// store->ExecuteSql("DROP TABLE IF EXISTS test"); +//} +// +//void RdbDataShareAdapterTest::TearDown(void) +//{ +// RdbHelper::ClearCache(); +//} +// +//void RdbDataShareAdapterTest::GenerateDefaultTable() +//{ +// std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, ") + +// std::string("data2 INTEGER, data3 FLOAT, data4 BLOB);"); +// store->ExecuteSql(createTableSql); +// +// std::string insertSql = "INSERT INTO test (data1, data2, data3, data4) VALUES (?, ?, ?, ?);"; +// +// /* insert first entry data */ +// uint8_t uValue = 66; +// std::vector typeBlob; +// typeBlob.push_back(uValue); +// store->ExecuteSql(insertSql, std::vector{ ValueObject(std::string("hello")), ValueObject((int)10), +// ValueObject((double)1.0), ValueObject((std::vector)typeBlob) }); +// +// /* insert second entry data */ +// typeBlob.clear(); +// store->ExecuteSql(insertSql, std::vector{ +// ValueObject(std::string("2")), ValueObject((int)-5), ValueObject((double)2.5), +// ValueObject() // set double value 2.5 +// }); +// +// /* insert third entry data */ +// store->ExecuteSql( +// insertSql, std::vector{ +// ValueObject(std::string("hello world")), ValueObject((int)3), ValueObject((double)1.8), +// ValueObject(std::vector{ 4, 5, 6 }) // set int value 3, double 1.8 +// }); +// +// /* insert four entry data */ +// store->ExecuteSql(insertSql, std::vector{ +// ValueObject(std::string("new world")), ValueObject((int)5), +// ValueObject((double)5.8), ValueObject() // set int value 5, double 5.8 +// }); +//} +// +//void RdbDataShareAdapterTest::GenerateDefaultEmptyTable() +//{ +// std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, ") + +// std::string("data2 INTEGER, data3 FLOAT, data4 BLOB);"); +// store->ExecuteSql(createTableSql); +//} +// +//int RdbDataShareAdapterTest::ResultSize(std::shared_ptr resultSet) +//{ +// if (resultSet->GoToFirstRow() != OHOS::NativeRdb::E_OK) { +// return 0; +// } +// int count = 1; +// while (resultSet->GoToNextRow() == OHOS::NativeRdb::E_OK) { +// count++; +// } +// return count; +//} +// +//OperationItem RdbDataShareAdapterTest::CreateOperationItem(int operation, +// const std::vector &singleParams = {}, const std::vector &multiParams = {}) +//{ +// OperationItem item; +// item.operation = operation; +// item.singleParams = singleParams; +// item.multiParams = multiParams; +// return item; +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_001 +// * @tc.desc: test RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_001, TestSize.Level1) +//{ +// GenerateDefaultTable(); +// +// std::shared_ptr resultSet = store->QueryByStep("SELECT * FROM test"); +// EXPECT_NE(resultSet, nullptr); +// int rowCount; +// resultSet.get()->GetRowCount(rowCount); +// LOG_INFO("result row count: %{public}d", rowCount); +// EXPECT_NE(rowCount, 0); +// auto bridge = OHOS::RdbDataShareAdapter::RdbUtils::ToResultSetBridge(resultSet); +// EXPECT_NE(bridge, nullptr); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_002 +// * @tc.desc: normal testcase of RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_002, TestSize.Level1) +//{ +// GenerateDefaultTable(); +// +// std::string table = "test"; +// std::string column = "data1"; +// std::string value = "hello"; +// DataSharePredicates predicates; +// predicates.EqualTo(column, value); +// std::vector columns; +// auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); +// int rowCount; +// allDataTypes.get()->GetRowCount(rowCount); +// EXPECT_EQ(rowCount, 1); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_003 +// * @tc.desc: normal testcase of RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_003, TestSize.Level1) +//{ +// GenerateDefaultTable(); +// +// std::string table = "test"; +// OHOS::DataShare::DataSharePredicates predicates; +// predicates.GreaterThan("data2", -5); +// std::vector columns; +// auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); +// int rdbRowCount; +// allDataTypes.get()->GetRowCount(rdbRowCount); +// EXPECT_EQ(rdbRowCount, 3); +// +// allDataTypes->GoToFirstRow(); +// +// std::string strValue; +// allDataTypes->GetString(1, strValue); +// EXPECT_EQ("hello", strValue); +// +// int intValue; +// allDataTypes->GetInt(2, intValue); +// EXPECT_EQ(intValue, 10); +// +// std::vector blobValue; +// uint8_t blobData = 66; +// allDataTypes->GetBlob(4, blobValue); +// EXPECT_EQ(blobData, blobValue[0]); +// +// allDataTypes->GoToNextRow(); +// allDataTypes->GetBlob(4, blobValue); +// EXPECT_EQ(3, static_cast(blobValue.size())); +// blobData = 5; +// EXPECT_EQ(blobData, blobValue[1]); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_004 +// * @tc.desc: normal testcase of RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_004, TestSize.Level1) +//{ +// GenerateDefaultTable(); +// +// std::string table = "test"; +// OHOS::DataShare::DataSharePredicates predicates; +// predicates.SetWhereClause("`data2` > ?"); +// predicates.SetWhereArgs(std::vector{ "-5" }); +// predicates.SetOrder("data3"); +// std::vector columns; +// auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); +// int rowCount; +// allDataTypes.get()->GetRowCount(rowCount); +// EXPECT_EQ(rowCount, 3); +// +// allDataTypes->GoToFirstRow(); +// +// std::string strValue; +// allDataTypes->GetString(1, strValue); +// EXPECT_EQ("hello", strValue); +// +// int intValue; +// allDataTypes->GetInt(2, intValue); +// EXPECT_EQ(intValue, 10); +// +// std::vector blobValue; +// allDataTypes->GetBlob(4, blobValue); +// EXPECT_EQ(1, static_cast(blobValue.size())); +// +// allDataTypes->GoToNextRow(); +// +// allDataTypes->GetString(1, strValue); +// EXPECT_EQ("hello world", strValue); +// +// allDataTypes->GetInt(2, intValue); +// EXPECT_EQ(intValue, 3); +// +// allDataTypes->GetBlob(4, blobValue); +// EXPECT_EQ(3, static_cast(blobValue.size())); +// uint8_t blobData = 5; +// EXPECT_EQ(blobData, blobValue[1]); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_005 +// * @tc.desc: normal testcase of RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_005, TestSize.Level1) +//{ +// GenerateDefaultTable(); +// DataShareValuesBucket values; +// int64_t id; +// int changedRows; +// values.Put("data1", std::string("tulip")); +// values.Put("data2", 100); +// values.Put("data3", 50.5); +// values.Put("data4", std::vector{ 20, 21, 22 }); +// +// int ret = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); +// EXPECT_EQ(ret, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(5, id); +// +// std::string table = "test"; +// OHOS::DataShare::DataSharePredicates predicates; +// std::string value = "tulip"; +// predicates.EqualTo("data1", value); +// std::vector columns; +// auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); +// int rowCount; +// allDataTypes.get()->GetRowCount(rowCount); +// EXPECT_EQ(rowCount, 1); +// +// allDataTypes.get()->Close(); +// +// values.Clear(); +// values.Put("data3", 300.5); +// values.Put("data4", std::vector{ 17, 18, 19 }); +// ret = store->Update( +// changedRows, "test", RdbUtils::ToValuesBucket(values), "data1 = ?", std::vector{ "tulip" }); +// EXPECT_EQ(ret, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(1, changedRows); +// +// allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); +// allDataTypes->GoToFirstRow(); +// +// double doubleVal; +// allDataTypes->GetDouble(3, doubleVal); +// EXPECT_EQ(300.5, doubleVal); +// +// int deletedRows; +// ret = store->Delete(deletedRows, RdbUtils::ToPredicates(predicates, table)); +// EXPECT_EQ(ret, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(1, deletedRows); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_006 +// * @tc.desc: normal testcase of RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_006, TestSize.Level1) +//{ +// GenerateDefaultTable(); +// +// std::string table = "test"; +// OHOS::DataShare::DataSharePredicates predicates; +// predicates.Limit(1, 2); +// std::vector columns; +// auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); +// int rdbRowCount; +// allDataTypes.get()->GetRowCount(rdbRowCount); +// EXPECT_EQ(rdbRowCount, 1); +// +// allDataTypes->GoToFirstRow(); +// +// std::string strValue; +// allDataTypes->GetString(1, strValue); +// EXPECT_EQ("hello world", strValue); +// +// int intValue; +// allDataTypes->GetInt(2, intValue); +// EXPECT_EQ(intValue, 3); +// +// double doubleValue; +// allDataTypes->GetDouble(3, doubleValue); +// EXPECT_EQ(doubleValue, 1.8); +// +// std::vector blobValue; +// uint8_t blobData1 = 4; +// uint8_t blobData2 = 5; +// uint8_t blobData3 = 6; +// allDataTypes->GetBlob(4, blobValue); +// EXPECT_EQ(3, static_cast(blobValue.size())); +// EXPECT_EQ(blobData1, blobValue[0]); +// EXPECT_EQ(blobData2, blobValue[1]); +// EXPECT_EQ(blobData3, blobValue[2]); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_007 +// * @tc.desc: normal testcase of RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_007, TestSize.Level1) +//{ +// std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT,") + +// std::string("age INTEGER, salary REAL);"); +// store->ExecuteSql(createTableSql); +// +// DataShareValuesBucket values; +// int64_t id; +// values.Put("name", std::string("zhangsan")); +// values.Put("age", INT64_MIN); +// values.Put("salary", DBL_MIN); +// int ret1 = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); +// EXPECT_EQ(ret1, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(1, id); +// +// values.Clear(); +// values.Put("name", std::string("lisi")); +// values.Put("age", INT64_MAX); +// values.Put("salary", DBL_MAX); +// int ret2 = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); +// EXPECT_EQ(ret2, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(2, id); +// +// std::string table = "test"; +// OHOS::DataShare::DataSharePredicates predicates; +// std::vector columns; +// auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); +// +// allDataTypes->GoToFirstRow(); +// int64_t int64Value; +// allDataTypes->GetLong(2, int64Value); +// EXPECT_EQ(int64Value, INT64_MIN); +// +// double doubleVal; +// allDataTypes->GetDouble(3, doubleVal); +// EXPECT_EQ(doubleVal, DBL_MIN); +// +// allDataTypes->GoToNextRow(); +// +// allDataTypes->GetLong(2, int64Value); +// EXPECT_EQ(int64Value, INT64_MAX); +// +// allDataTypes->GetDouble(3, doubleVal); +// EXPECT_EQ(doubleVal, DBL_MAX); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_008 +// * @tc.desc: normal testcase of query double +// * @tc.type: test double for high accuracy +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_008, TestSize.Level1) +//{ +// std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 double,") + +// std::string("data2 double, data3 TEXT);"); +// store->ExecuteSql(createTableSql); +// +// ValuesBucket values; +// int64_t id; +// double data1 = 1.777777777777; +// double data2 = 1.888888888888; +// std::string data3 = "zh-has"; +// std::string tableName = "test"; +// +// values.PutDouble("data1", data1); +// values.PutDouble("data2", data2); +// values.PutString("data3", data3); +// int ret = store->Insert(id, tableName, values); +// EXPECT_EQ(ret, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(1, id); +// +// OHOS::DataShare::DataSharePredicates predicates; +// predicates.BeginWrap() +// ->EqualTo("data1", data1) +// ->And() +// ->EqualTo("data2", data2) +// ->And() +// ->EqualTo("data3", data3) +// ->EndWrap(); +// std::vector columns; +// auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, tableName), columns); +// int rowCount; +// int ok = allDataTypes->GetRowCount(rowCount); +// EXPECT_EQ(ok, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(1, rowCount); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_009 +// * @tc.desc: normal testcase of RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_009, TestSize.Level1) +//{ +// std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT,") + +// std::string("age INTEGER, salary REAL);"); +// store->ExecuteSql(createTableSql); +// +// DataShareValuesBucket values; +// int64_t id; +// values.Put("name", std::string("zhangsan")); +// values.Put("age", INT64_MIN); +// values.Put("salary", DBL_MIN); +// int ret1 = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); +// EXPECT_EQ(ret1, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(1, id); +// +// values.Clear(); +// values.Put("name", std::string("lisi")); +// values.Put("age", INT64_MAX); +// values.Put("salary", DBL_MAX); +// int ret2 = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); +// EXPECT_EQ(ret2, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(2, id); +// +// std::string table = "test"; +// OHOS::DataShare::OperationItem item; +// item.singleParams = {}; +// RdbPredicates predicates("test"); +// RdbUtils::EqualTo(item, predicates); +// std::vector columns; +// std::shared_ptr allPerson = store->Query(predicates, columns); +// EXPECT_EQ(2, ResultSize(allPerson)); +// +// RdbUtils::GreaterThan(item, predicates); +// allPerson = store->Query(predicates, columns); +// EXPECT_EQ(2, ResultSize(allPerson)); +// +// RdbUtils::Limit(item, predicates); +// allPerson = store->Query(predicates, columns); +// EXPECT_EQ(2, ResultSize(allPerson)); +// +// RdbUtils::NotEqualTo(item, predicates); +// allPerson = store->Query(predicates, columns); +// EXPECT_EQ(2, ResultSize(allPerson)); +// +// RdbUtils::LessThan(item, predicates); +// allPerson = store->Query(predicates, columns); +// EXPECT_EQ(2, ResultSize(allPerson)); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_010 +// * @tc.desc: normal testcase of RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_010, TestSize.Level1) +//{ +// GenerateDefaultTable(); +// +// std::string table = "test"; +// std::string column = "data1"; +// std::string value = "%hello%"; +// DataSharePredicates predicates; +// predicates.Unlike(column, value); +// std::vector columns; +// auto result = store->Query(RdbUtils::ToPredicates(predicates, table), columns); +// int rowCount = 0; +// if (result.get() != nullptr) { +// result.get()->GetRowCount(rowCount); +// } +// EXPECT_EQ(rowCount, 2); +//} +// +//void RdbDataShareAdapterTest::LessThanTest(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, LessThan(testing::_, testing::_)).Times(1); +// auto item = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::LessThan(item, predicates); +//} +// +//void RdbDataShareAdapterTest::GreaterThanOrEqualTo(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, GreaterThanOrEqualTo(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, { "John" }); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::GreaterThanOrEqualTo(item1, predicates); +// RdbUtils::GreaterThanOrEqualTo(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::LessThanOrEqualTo(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, LessThanOrEqualTo(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, { "John" }); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::LessThanOrEqualTo(item1, predicates); +// RdbUtils::LessThanOrEqualTo(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::IsNull(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, IsNull(testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::IsNull(item1, predicates); +// RdbUtils::IsNull(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::IsNotNull(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, IsNotNull(testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::IsNotNull(item1, predicates); +// RdbUtils::IsNotNull(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::In(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, In(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0); +// auto item2 = CreateOperationItem(0, { "test_table", "John" }); +// auto item3 = CreateOperationItem(0, {}, { std::vector{ "zhangSan" }, std::vector{ 1, 2, 3 } }); +// auto item4 = CreateOperationItem( +// 0, { "test_table", 2 }, { std::vector{ "zhangSan" }, std::vector{ 1, 2, 3 } }); +// RdbUtils::In(item1, predicates); +// RdbUtils::In(item2, predicates); +// RdbUtils::In(item3, predicates); +// RdbUtils::In(item4, predicates); +//} +// +//void RdbDataShareAdapterTest::NotIn(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, NotIn(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0); +// auto item2 = CreateOperationItem(0, { "test_table", "John" }); +// auto item3 = CreateOperationItem(0, {}, { std::vector{ "zhangSan" }, std::vector{ 1, 2, 3 } }); +// auto item4 = CreateOperationItem( +// 0, { "test_table", 2 }, { std::vector{ "zhangSan" }, std::vector{ 1, 2, 3 } }); +// RdbUtils::NotIn(item1, predicates); +// RdbUtils::NotIn(item2, predicates); +// RdbUtils::NotIn(item3, predicates); +// RdbUtils::NotIn(item4, predicates); +//} +// +//void RdbDataShareAdapterTest::Like(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, Like(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::Like(item1, predicates); +// RdbUtils::Like(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::NotLike(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, NotLike(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::NotLike(item1, predicates); +// RdbUtils::NotLike(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::OrderByAsc(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, OrderByAsc(testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::OrderByAsc(item1, predicates); +// RdbUtils::OrderByAsc(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::OrderByDesc(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, OrderByDesc(testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::OrderByDesc(item1, predicates); +// RdbUtils::OrderByDesc(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::Offset(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, Offset(testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::Offset(item1, predicates); +// RdbUtils::Offset(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::BeginsWith(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, BeginsWith(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::BeginsWith(item1, predicates); +// RdbUtils::BeginsWith(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::EndsWith(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, EndsWith(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::EndsWith(item1, predicates); +// RdbUtils::EndsWith(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::GroupBy(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, GroupBy(testing::_)).Times(1); +// auto item1 = CreateOperationItem(0); +// auto item2 = CreateOperationItem(0, {}, { std::vector{ "zhangSan" }, std::vector{ 1, 2, 3 } }); +// RdbUtils::GroupBy(item1, predicates); +// RdbUtils::GroupBy(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::IndexedBy(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, IndexedBy(testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::IndexedBy(item1, predicates); +// RdbUtils::IndexedBy(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::Contains(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, Contains(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::Contains(item1, predicates); +// RdbUtils::Contains(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::NotContains(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, NotContains(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::NotContains(item1, predicates); +// RdbUtils::NotContains(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::Glob(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, Glob(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::Glob(item1, predicates); +// RdbUtils::Glob(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::Between(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, Between(testing::_, testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", 1, true }); +// RdbUtils::Between(item1, predicates); +// RdbUtils::Between(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::NotBetween(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, NotBetween(testing::_, testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", 1, true }); +// RdbUtils::NotBetween(item1, predicates); +// RdbUtils::NotBetween(item2, predicates); +//} +// +///** +// * @tc.name: RdbUtils_Operation_Test +// * @tc.desc: Test all operation handlers in RdbUtils +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, RdbUtils_Operation_Test, TestSize.Level1) +//{ +// LOG_INFO("RdbUtils_Operation_Test start"); +// MockRdbPredicates predicates("test_table"); +// LessThanTest(predicates); +// GreaterThanOrEqualTo(predicates); +// LessThanOrEqualTo(predicates); +// IsNull(predicates); +// IsNotNull(predicates); +// In(predicates); +// NotIn(predicates); +// Like(predicates); +// NotLike(predicates); +// OrderByAsc(predicates); +// OrderByDesc(predicates); +// Offset(predicates); +// BeginsWith(predicates); +// EndsWith(predicates); +// GroupBy(predicates); +// IndexedBy(predicates); +// Contains(predicates); +// NotContains(predicates); +// Glob(predicates); +// Between(predicates); +// NotBetween(predicates); +//} diff --git a/relational_store/test/ndk/BUILD.gn b/relational_store/test/ndk/BUILD.gn index dfd58ab18557eaeffdb1701be18b4852bfcadc6c..d93ce60b043805143fb51af7f7d6ad010b9d2b39 100644 --- a/relational_store/test/ndk/BUILD.gn +++ b/relational_store/test/ndk/BUILD.gn @@ -20,7 +20,7 @@ config("module_private_config") { visibility = [ ":*" ] include_dirs = [ - "${kvstore_path}/common", + "${relational_store_base_path}/interfaces/ndk", "${relational_store_base_path}/interfaces/ndk/include", "${relational_store_innerapi_path}/rdb/include", "${relational_store_innerapi_path}/appdatafwk/include", @@ -35,7 +35,10 @@ ohos_unittest("NativeRdbNdkTest") { sources = [ "unittest/rdb_asset_test.cpp", + "unittest/rdb_crypto_param_test.cpp", "unittest/rdb_cursor_test.cpp", + "unittest/rdb_performance_test.cpp", + "unittest/rdb_predicates_pref_test.cpp", "unittest/rdb_predicates_test.cpp", "unittest/rdb_store_configv2_test.cpp", "unittest/rdb_store_test.cpp", @@ -49,13 +52,15 @@ ohos_unittest("NativeRdbNdkTest") { "access_token:libaccesstoken_sdk", "access_token:libtoken_setproc", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", + "kv_store:datamgr_common", ] deps = [ - "${relational_store_base_path}/interfaces/ndk/src:native_rdb_ndk", + "${relational_store_base_path}/interfaces/rdb_ndk_utils:native_rdb_ndk_utils", + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", ] } @@ -65,3 +70,24 @@ group("unittest") { deps = [ ":NativeRdbNdkTest" ] } + +group("fuzztest") { + testonly = true + deps = [] + deps += [ + "fuzztest/datavalue_fuzzer:fuzztest", + "fuzztest/ohrdbtransaction_fuzzer:fuzztest", + "fuzztest/relationalstore_fuzzer:fuzztest", + "fuzztest/relationalstorecapi_fuzzer:fuzztest", + "fuzztest/valuebucket_fuzzer:fuzztest", + "fuzztest/valueobject_fuzzer:fuzztest", + "fuzztest/ohpredicates_fuzzer:fuzztest", + "fuzztest/dataasset_fuzzer:fuzztest", + "fuzztest/oh_cursor_fuzzer:fuzztest", + "fuzztest/oh_data_value_fuzzer:fuzztest", + "fuzztest/oh_data_values_buckets_fuzzer:fuzztest", + "fuzztest/oh_data_values_fuzzer:fuzztest", + "fuzztest/oh_predicates_fuzzer:fuzztest", + "fuzztest/oh_rdb_crypto_param_fuzzer:fuzztest", + ] +} diff --git a/relational_store/test/ndk/fuzztest/dataasset_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..18084f8004acf79dd4eef83714b9a5e6b8e87707 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("dataasset_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = "${relational_store_base_path}/test/ndk/fuzztest/dataasset_fuzzer" + + sources = [ "dataasset_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":dataasset_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/dataasset_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..64d7767e6e29d3de338406d4a2ab136a8e9bf9e9 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/dataasset_fuzzer/dataasset_fuzzer.cpp b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/dataasset_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..38ccdfbf5790c531939571d4e505cd98b0f588f4 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/dataasset_fuzzer.cpp @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2025 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 "dataasset_fuzzer.h" + +#include + +#include "data_asset.h" +#include "grd_api_manager.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + +#define MAX_STRING_LENGTH 20 + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +namespace OHOS { +void OH_Data_Asset_SetNameFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + std::string name = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + OH_Data_Asset_SetName(asset, name.c_str()); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_SetName(nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_SetUriFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + std::string uri = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + OH_Data_Asset_SetUri(asset, uri.c_str()); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_SetUri(nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_SetPathFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + std::string path = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + OH_Data_Asset_SetPath(asset, path.c_str()); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_SetPath(nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_SetCreateTimeFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + int64_t createTime = provider.ConsumeIntegral(); + OH_Data_Asset_SetCreateTime(asset, createTime); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_SetCreateTime(nullptr, 0); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_SetModifyTimeFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + int64_t modifyTime = provider.ConsumeIntegral(); + OH_Data_Asset_SetModifyTime(asset, modifyTime); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_SetModifyTime(nullptr, 0); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_SetSizeFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + size_t size = provider.ConsumeIntegral(); + OH_Data_Asset_SetSize(asset, size); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_SetSize(nullptr, 0); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_SetStatusFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + const int min = 0; + const int max = 6; + Data_AssetStatus status = static_cast(provider.ConsumeIntegralInRange(min, max)); + OH_Data_Asset_SetStatus(asset, status); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_SetStatus(nullptr, Data_AssetStatus::ASSET_NULL); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_GetNameFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + char name[MAX_STRING_LENGTH]; + size_t length = MAX_STRING_LENGTH; + OH_Data_Asset_GetName(asset, name, &length); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_GetName(nullptr, nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_GetUriFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + char uri[MAX_STRING_LENGTH]; + size_t length = MAX_STRING_LENGTH; + OH_Data_Asset_GetUri(asset, uri, &length); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_GetUri(nullptr, nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_GetPathFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + char path[MAX_STRING_LENGTH]; + size_t length = MAX_STRING_LENGTH; + OH_Data_Asset_GetPath(asset, path, &length); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_GetPath(nullptr, nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_GetCreateTimeFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + int64_t createTime; + OH_Data_Asset_GetCreateTime(asset, &createTime); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_GetCreateTime(nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_GetModifyTimeFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + int64_t modifyTime; + OH_Data_Asset_GetModifyTime(asset, &modifyTime); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_GetModifyTime(nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_GetSizeFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + size_t size; + OH_Data_Asset_GetSize(asset, &size); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_GetSize(nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_GetStatusFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + Data_AssetStatus status; + OH_Data_Asset_GetStatus(asset, &status); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_GetStatus(nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + OHOS::OH_Data_Asset_SetNameFuzz(provider); + OHOS::OH_Data_Asset_SetUriFuzz(provider); + OHOS::OH_Data_Asset_SetPathFuzz(provider); + OHOS::OH_Data_Asset_SetCreateTimeFuzz(provider); + OHOS::OH_Data_Asset_SetModifyTimeFuzz(provider); + OHOS::OH_Data_Asset_SetSizeFuzz(provider); + OHOS::OH_Data_Asset_SetStatusFuzz(provider); + OHOS::OH_Data_Asset_GetNameFuzz(provider); + OHOS::OH_Data_Asset_GetUriFuzz(provider); + OHOS::OH_Data_Asset_GetPathFuzz(provider); + OHOS::OH_Data_Asset_GetCreateTimeFuzz(provider); + OHOS::OH_Data_Asset_GetModifyTimeFuzz(provider); + OHOS::OH_Data_Asset_GetSizeFuzz(provider); + OHOS::OH_Data_Asset_GetStatusFuzz(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/dataasset_fuzzer/dataasset_fuzzer.h b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/dataasset_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..a51abea68e1dae046e1125bbdebc30405ddbc101 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/dataasset_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 DATAASSET_FUZZER_H +#define DATAASSET_FUZZER_H + +#define FUZZ_PROJECT_NAME "dataasset_fuzzer" + +#endif // DATAASSET_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/dataasset_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/datavalue_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..ea8a320b913b7b97109d5f6a9a35599affd86445 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/BUILD.gn @@ -0,0 +1,70 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("DataValueFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/ndk/fuzztest/datavalue_fuzzer" + + sources = [ "datavalue_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":DataValueFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/datavalue_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/datavalue_fuzzer/datavalue_fuzzer.cpp b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/datavalue_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8fcf2278bbfd7d7ecf98503119b3c4285cc6d64f --- /dev/null +++ b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/datavalue_fuzzer.cpp @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2025 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 "datavalue_fuzzer.h" + +#include + +#include "grd_api_manager.h" +#include "oh_data_value.h" +#include "oh_value_object.h" +#include "oh_values_bucket.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +void OHValuePutAssetsFuzzTest(FuzzedDataProvider &provider, OH_Data_Value *value) +{ + const int minCount = 1; + const int maxCount = 50; + size_t count = provider.ConsumeIntegralInRange(minCount, maxCount); + Data_Asset **assets = OH_Data_Asset_CreateMultiple(count); + if (assets == nullptr) { + return; + } + for (size_t i = 0; i < count; i++) { + int64_t value = provider.ConsumeIntegral(); + OH_Data_Asset_SetCreateTime(assets[i], value); + } + OH_Value_PutAssets(value, assets, count); + OH_Data_Asset_DestroyMultiple(assets, count); +} + +void OHValuePutFloatVectorFuzzTest(FuzzedDataProvider &provider, OH_Data_Value *value) +{ + const int minFloatVectorSize = 1; + const int maxFloatVectorSize = 100; + size_t floatVectorSize = provider.ConsumeIntegralInRange(minFloatVectorSize, maxFloatVectorSize); + std::vector floatVector(floatVectorSize); + for (size_t i = 0; i < floatVectorSize; i++) { + floatVector[i] = provider.ConsumeFloatingPoint(); + } + OH_Value_PutFloatVector(value, floatVector.data(), floatVectorSize); +} + +void OHValuePutUnlimitedIntFuzzTest(FuzzedDataProvider &provider, OH_Data_Value *value) +{ + const int minSign = 0; + const int maxSign = 1; + int sign = provider.ConsumeIntegralInRange(minSign, maxSign); + const int minUnlimitedIntSize = 1; + const int maxUnlimitedIntSize = 10; + size_t unlimitedIntSize = provider.ConsumeIntegralInRange(minUnlimitedIntSize, maxUnlimitedIntSize); + std::vector trueForm(unlimitedIntSize); + for (size_t i = 0; i < unlimitedIntSize; i++) { + trueForm[i] = provider.ConsumeIntegral(); + } + OH_Value_PutUnlimitedInt(value, sign, trueForm.data(), unlimitedIntSize); +} + +void DataValuePutFuzzTest(FuzzedDataProvider &provider, OH_Data_Value *value) +{ + if (value == nullptr) { + return; + } + // Test OH_Value_PutNull + { + OH_Value_PutNull(value); + } + + // Test OH_Value_PutInt + { + int64_t intValue = provider.ConsumeIntegral(); + OH_Value_PutInt(value, intValue); + } + + // Test OH_Value_PutReal + { + double realValue = provider.ConsumeFloatingPoint(); + OH_Value_PutReal(value, realValue); + } + + // Test OH_Value_PutText + { + std::string textValue = provider.ConsumeRandomLengthString(); + OH_Value_PutText(value, textValue.c_str()); + } + + // Test OH_Value_PutBlob + { + const int minBlobSize = 1; + const int maxBlobSize = 50; + size_t blobSize = provider.ConsumeIntegralInRange(minBlobSize, maxBlobSize); + std::vector blobData = provider.ConsumeBytes(blobSize); + OH_Value_PutBlob(value, blobData.data(), blobData.size()); + } + + // Test OH_Value_PutAsset + { + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + OH_Value_PutAsset(value, asset); + OH_Data_Asset_DestroyOne(asset); + } + + // Test OH_Value_PutAssets + OHValuePutAssetsFuzzTest(provider, value); + + // Test OH_Value_PutFloatVector + OHValuePutFloatVectorFuzzTest(provider, value); + + // Test OH_Value_PutUnlimitedInt + OHValuePutUnlimitedIntFuzzTest(provider, value); +} + +void OHValueGetAssetsFuzzTest(OH_Data_Value *value) +{ + size_t assetsSize; + OH_Value_GetAssetsCount(value, &assetsSize); + + Data_Asset **assets = OH_Data_Asset_CreateMultiple(assetsSize); + if (assets == nullptr) { + return; + } + size_t assetsOutLen; + OH_Value_GetAssets(value, assets, assetsSize, &assetsOutLen); + OH_Data_Asset_DestroyMultiple(assets, assetsSize); +} + +void DataValueGetFuzzTestPartOne(OH_Data_Value *value) +{ + if (value == nullptr) { + return; + } + // Test OH_Value_GetType + { + OH_ColumnType type; + OH_Value_GetType(value, &type); + } + + // Test OH_Value_IsNull + { + bool isNull; + OH_Value_IsNull(value, &isNull); + } + + // Test OH_Value_GetInt + { + int64_t intValue; + OH_Value_GetInt(value, &intValue); + } + + // Test OH_Value_GetReal + { + double realValue; + OH_Value_GetReal(value, &realValue); + } + + // Test OH_Value_GetText + { + const char *textValue; + OH_Value_GetText(value, &textValue); + } + + // Test OH_Value_GetBlob + { + const uint8_t *blobValue; + size_t blobLength; + OH_Value_GetBlob(value, &blobValue, &blobLength); + } + + // Test OH_Value_GetAsset + { + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + OH_Value_GetAsset(value, asset); + OH_Data_Asset_DestroyOne(asset); + } + + // Test OH_Value_GetAssetsCount + { + size_t assetsCount; + OH_Value_GetAssetsCount(value, &assetsCount); + } + + // Test OH_Value_GetAssets + OHValueGetAssetsFuzzTest(value); + + // Test OH_Value_GetFloatVectorCount + { + size_t floatVectorCount; + OH_Value_GetFloatVectorCount(value, &floatVectorCount); + } +} + +void DataValueGetFuzzTestPartTwo(OH_Data_Value *value) +{ + if (value == nullptr) { + return; + } + // Test OH_Value_GetFloatVector + { + size_t floatVectorSize; + OH_Value_GetFloatVectorCount(value, &floatVectorSize); + const size_t maxMallocSize = 100; + if (floatVectorSize > maxMallocSize) { + floatVectorSize = maxMallocSize; + } + float *floatVector = (float *)malloc(floatVectorSize * sizeof(float)); + if (floatVector == nullptr) { + return; + } + size_t floatVectorOutLen; + OH_Value_GetFloatVector(value, floatVector, floatVectorSize, &floatVectorOutLen); + free(floatVector); + } + + // Test OH_Value_GetUnlimitedIntBand + { + size_t unlimitedIntBand; + OH_Value_GetUnlimitedIntBand(value, &unlimitedIntBand); + } + + // Test OH_Value_GetUnlimitedInt + { + size_t unlimitedIntSize; + OH_Value_GetUnlimitedIntBand(value, &unlimitedIntSize); + const size_t maxMallocSize = 100; + if (unlimitedIntSize > maxMallocSize) { + unlimitedIntSize = maxMallocSize; + } + uint64_t *trueForm = (uint64_t *)malloc(unlimitedIntSize * sizeof(uint64_t)); + if (trueForm == nullptr) { + return; + } + size_t unlimitedIntOutLen; + int sign; + OH_Value_GetUnlimitedInt(value, &sign, trueForm, unlimitedIntSize, &unlimitedIntOutLen); + free(trueForm); + } +} + +void DataValueFuzzTest(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + DataValuePutFuzzTest(provider, value); + DataValueGetFuzzTestPartOne(value); + DataValueGetFuzzTestPartTwo(value); + // Destroy the OH_Data_Value instance + OH_Value_Destroy(value); +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + DataValueFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/datavalue_fuzzer/datavalue_fuzzer.h b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/datavalue_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..7e3addd8febcfd0b727de84fc75f50b71701ea76 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/datavalue_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 DATAVALUE_FUZZER_H +#define DATAVALUE_FUZZER_H + +#define FUZZ_PROJECT_NAME "datavalue_fuzzer" + +#endif // DATAVALUE_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/datavalue_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..d88cd51007ced3137c51d030a774b38341cc74a5 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("oh_cursor_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = "${relational_store_base_path}/test/ndk/fuzztest/oh_cursor_fuzzer" + + sources = [ "oh_cursor_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":oh_cursor_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..64d7767e6e29d3de338406d4a2ab136a8e9bf9e9 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/oh_cursor_fuzzer.cpp b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/oh_cursor_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e4d9eecbf3e43cce661201f8e8d6462775c9b8ab --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/oh_cursor_fuzzer.cpp @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2025 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 "oh_cursor_fuzzer.h" + +#include +#include +#include +#include + +#include "grd_api_manager.h" +#include "oh_cursor.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + + +#define COLUMN_INDEX_MIN 0 +#define COLUMN_INDEX_MAX 10 +static constexpr const char *RDB_TEST_PATH = "/data/storage/el2/database/com.ohos.example.distributedndk/entry/"; + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +namespace OHOS { + +OH_Cursor *GetOH_Cursor() +{ + OH_Rdb_Config config; + config.dataBaseDir = RDB_TEST_PATH; + config.storeName = "rdb_store_oh_cursor_fuzzer_test.db"; + config.bundleName = "com.ohos.example.distributedndk"; + config.moduleName = ""; + config.securityLevel = OH_Rdb_SecurityLevel::S1; + config.isEncrypt = false; + config.selfSize = sizeof(OH_Rdb_Config); + config.area = RDB_SECURITY_AREA_EL1; + int chmodValue = 0770; + mkdir(config.dataBaseDir, chmodValue); + + int errCode = 0; + char table[] = "test"; + static OH_Rdb_Store *ndkStore = OH_Rdb_GetOrOpen(&config, &errCode); + + char createTableSql[] = "CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, data2 INTEGER, " + "data3 FLOAT, data4 BLOB, data5 TEXT);"; + OH_Rdb_Execute(ndkStore, createTableSql); + + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putInt64(valueBucket, "id", 1); + valueBucket->putText(valueBucket, "data1", "zhangSan"); + // init row one data2 value 12800 + valueBucket->putInt64(valueBucket, "data2", 12800); + // init row one data3 value 100.1 + valueBucket->putReal(valueBucket, "data3", 100.1); + uint8_t arr[] = { 1, 2, 3, 4, 5 }; + int len = sizeof(arr) / sizeof(arr[0]); + valueBucket->putBlob(valueBucket, "data4", arr, len); + valueBucket->putText(valueBucket, "data5", "ABCDEFG"); + OH_Rdb_Insert(ndkStore, table, valueBucket); + + char querySql[] = "SELECT * FROM test"; + static OH_Cursor *cursor = OH_Rdb_ExecuteQuery(ndkStore, querySql); + return cursor; +} + +OH_ColumnType GetOH_ColumnType(FuzzedDataProvider &provider) +{ + int min = static_cast(OH_ColumnType::TYPE_NULL); + int max = static_cast(OH_ColumnType::TYPE_UNLIMITED_INT); + int enumInt = provider.ConsumeIntegralInRange(min, max); + OH_ColumnType type = static_cast(enumInt); + return type; +} + +void OH_Cursor_GetColumnCountFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int count = provider.ConsumeIntegral(); + cursor->getColumnCount(cursor, &count); +} + +void OH_Cursor_GetColumnTypeFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + OH_ColumnType columnType = GetOH_ColumnType(provider); + cursor->getColumnType(cursor, columnIndex, &columnType); +} + +void OH_Cursor_GetColumnIndexFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + std::string name = provider.ConsumeRandomLengthString(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + cursor->getColumnIndex(cursor, name.c_str(), &columnIndex); +} + +void OH_Cursor_GetColumnNameFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + char name[10]; + const int length = 10; + cursor->getColumnName(cursor, columnIndex, name, length); +} + +void OH_Cursor_GetRowCountFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int count = provider.ConsumeIntegral(); + cursor->getRowCount(cursor, &count); +} + +void OH_Cursor_GoToNextRowFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + cursor->goToNextRow(cursor); +} + +void OH_Cursor_GetSizeFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + size_t size = provider.ConsumeIntegral(); + cursor->getSize(cursor, columnIndex, &size); +} + +void OH_Cursor_GetTextFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + char value = provider.ConsumeIntegral(); + int length = provider.ConsumeIntegral(); + cursor->getText(cursor, columnIndex, &value, length); +} + +void OH_Cursor_GetInt64Fuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + int64_t value = provider.ConsumeIntegral(); + cursor->getInt64(cursor, columnIndex, &value); +} + +void OH_Cursor_GetRealFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + double value = provider.ConsumeFloatingPoint(); + cursor->getReal(cursor, columnIndex, &value); +} + +void OH_Cursor_GetBlobFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + unsigned char value = provider.ConsumeIntegral(); + int length = provider.ConsumeIntegral(); + cursor->getBlob(cursor, columnIndex, &value, length); +} + +void OH_Cursor_IsNullFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + bool isNull = provider.ConsumeBool(); + cursor->isNull(cursor, columnIndex, &isNull); +} + +void OH_Cursor_GetAssetFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + cursor->getAsset(cursor, columnIndex, asset); + OH_Data_Asset_DestroyOne(asset); +} + +void OH_Cursor_GetAssetsFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + uint32_t length = provider.ConsumeIntegral(); + cursor->getAssets(cursor, columnIndex, &asset, &length); + OH_Data_Asset_DestroyOne(asset); +} + +void OH_Cursor_GetAssetsCountFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + uint32_t count = provider.ConsumeIntegral(); + cursor->getAssetsCount(cursor, columnIndex, &count); +} + +void OH_Cursor_GetFloatVectorCountFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + size_t length = provider.ConsumeIntegral(); + OH_Cursor_GetFloatVectorCount(cursor, columnIndex, &length); +} + +void OH_Cursor_GetFloatVectorFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + float val = provider.ConsumeFloatingPoint(); + size_t inLen = provider.ConsumeIntegral(); + size_t outLen = provider.ConsumeIntegral(); + OH_Cursor_GetFloatVector(cursor, columnIndex, &val, inLen, &outLen); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + OHOS::OH_Cursor_GetColumnCountFuzz(provider); + OHOS::OH_Cursor_GetColumnTypeFuzz(provider); + OHOS::OH_Cursor_GetColumnIndexFuzz(provider); + OHOS::OH_Cursor_GetColumnNameFuzz(provider); + OHOS::OH_Cursor_GetRowCountFuzz(provider); + OHOS::OH_Cursor_GoToNextRowFuzz(provider); + OHOS::OH_Cursor_GetSizeFuzz(provider); + OHOS::OH_Cursor_GetTextFuzz(provider); + OHOS::OH_Cursor_GetInt64Fuzz(provider); + OHOS::OH_Cursor_GetRealFuzz(provider); + OHOS::OH_Cursor_GetBlobFuzz(provider); + OHOS::OH_Cursor_IsNullFuzz(provider); + OHOS::OH_Cursor_GetAssetFuzz(provider); + OHOS::OH_Cursor_GetAssetsFuzz(provider); + OHOS::OH_Cursor_GetAssetsCountFuzz(provider); + OHOS::OH_Cursor_GetFloatVectorCountFuzz(provider); + OHOS::OH_Cursor_GetFloatVectorFuzz(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/oh_cursor_fuzzer.h b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/oh_cursor_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..50368086782a2934efd6215840cd86b488fe8fe1 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/oh_cursor_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 OH_CURSOR_FUZZER_H +#define OH_CURSOR_FUZZER_H + +#define FUZZ_PROJECT_NAME "oh_cursor_fuzzer" + +#endif // OH_CURSOR_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..994ba471c5e0a309f079e0b0eb1a83c9e808edd0 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("oh_data_value_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = "${relational_store_base_path}/test/ndk/fuzztest/oh_data_value_fuzzer" + + sources = [ "oh_data_value_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":oh_data_value_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..64d7767e6e29d3de338406d4a2ab136a8e9bf9e9 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/oh_data_value_fuzzer.cpp b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/oh_data_value_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ad434734421fd7b1794ef4431e15d0a275ce2eb --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/oh_data_value_fuzzer.cpp @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2025 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 "oh_data_value_fuzzer.h" + +#include + +#include "grd_api_manager.h" +#include "oh_data_value.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + + +#define BLOBSIZE_MIN 1 +#define BLOBSIZE_MAX 10 + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +namespace OHOS { +void OH_Value_DestroyFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = provider.ConsumeBool() ? OH_Value_Create() : nullptr; + OH_Value_Destroy(value); +} + +void OH_Value_PutNullFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + OH_Value_PutNull(value); + OH_Value_Destroy(value); + + OH_Value_PutNull(nullptr); + OH_Value_Destroy(nullptr); +} + +void OH_Value_PutIntFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + int64_t val = provider.ConsumeIntegral(); + OH_Value_PutInt(value, val); + OH_Value_Destroy(value); + + OH_Value_PutInt(nullptr, 0); + OH_Value_Destroy(nullptr); +} + +void OH_Value_PutRealFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + double val = provider.ConsumeFloatingPoint(); + OH_Value_PutReal(value, val); + OH_Value_Destroy(value); + + OH_Value_PutReal(nullptr, 0); + OH_Value_Destroy(nullptr); +} + +void OH_Value_PutTextFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + std::string val = provider.ConsumeRandomLengthString(); + OH_Value_PutText(value, val.c_str()); + OH_Value_Destroy(value); + + OH_Value_PutText(nullptr, nullptr); + OH_Value_Destroy(nullptr); +} + +void OH_Value_PutBlobFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + size_t blobSize = provider.ConsumeIntegralInRange(BLOBSIZE_MIN, BLOBSIZE_MAX); + std::vector blobData = provider.ConsumeBytes(blobSize); + blobData.resize(blobSize); + OH_Value_PutBlob(value, blobData.data(), blobSize); + OH_Value_Destroy(value); + + OH_Value_PutBlob(nullptr, nullptr, 0); + OH_Value_Destroy(nullptr); +} + +void OH_Value_PutAssetFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + OH_Value_Destroy(value); + return; + } + OH_Value_PutAsset(value, asset); + OH_Value_Destroy(value); + + OH_Value_PutAsset(nullptr, nullptr); + OH_Value_Destroy(nullptr); +} + +void OH_Value_PutAssetsFuzz(FuzzedDataProvider &provider) +{ + size_t count = provider.ConsumeIntegralInRange(BLOBSIZE_MIN, BLOBSIZE_MAX); + Data_Asset **assets = OH_Data_Asset_CreateMultiple(count); + if (assets == nullptr) { + return; + } + for (size_t i = 0; i < count; i++) { + int64_t value = provider.ConsumeIntegral(); + OH_Data_Asset_SetCreateTime(assets[i], value); + } + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + OH_Data_Asset_DestroyMultiple(assets, count); + return; + } + OH_Value_PutAssets(value, assets, count); + OH_Value_Destroy(value); + OH_Data_Asset_DestroyMultiple(assets, count); + + OH_Value_PutAssets(nullptr, nullptr, 0); + OH_Value_Destroy(nullptr); + OH_Data_Asset_DestroyMultiple(nullptr, 0); +} + +void OH_Value_PutFloatVectorFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + size_t length = provider.ConsumeIntegralInRange(BLOBSIZE_MIN, BLOBSIZE_MAX); + float floatArr[length]; + for (int i = 0; i < length; i++) { + float val = provider.ConsumeFloatingPoint(); + floatArr[i] = val; + } + OH_Value_PutFloatVector(value, floatArr, length); + OH_Value_Destroy(value); + + OH_Value_PutFloatVector(nullptr, nullptr, 0); + OH_Value_Destroy(nullptr); +} + +void OH_Value_PutUnlimitedIntFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + int sign = provider.ConsumeBool() ? 0 : 1; + size_t length = provider.ConsumeIntegralInRange(BLOBSIZE_MIN, BLOBSIZE_MAX); + uint64_t trueForm[length]; + for (int i = 0; i < length; i++) { + uint64_t trueFormValue = provider.ConsumeIntegral(); + trueForm[i] = trueFormValue; + } + OH_Value_PutUnlimitedInt(value, sign, trueForm, length); + OH_Value_Destroy(value); + + OH_Value_PutUnlimitedInt(nullptr, 0, nullptr, 0); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetTypeFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + OH_ColumnType type; + OH_Value_GetType(value, &type); + OH_Value_Destroy(value); + + OH_Value_GetType(nullptr, &type); + OH_Value_Destroy(nullptr); +} + +void OH_Value_IsNullFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + bool val; + OH_Value_IsNull(value, &val); + OH_Value_Destroy(value); + + OH_Value_IsNull(nullptr, &val); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetIntFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + int64_t val; + OH_Value_GetInt(value, &val); + OH_Value_Destroy(value); + + OH_Value_GetInt(nullptr, &val); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetRealFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + double val; + OH_Value_GetReal(value, &val); + OH_Value_Destroy(value); + + OH_Value_GetReal(nullptr, &val); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetTextFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + const char *textValue; + OH_Value_GetText(value, &textValue); + OH_Value_Destroy(value); + + OH_Value_GetText(nullptr, &textValue); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetBlobFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + const uint8_t *val; + size_t length; + OH_Value_GetBlob(value, &val, &length); + OH_Value_Destroy(value); + + OH_Value_GetBlob(nullptr, &val, &length); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetAssetFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + OH_Value_Destroy(value); + return; + } + OH_Value_GetAsset(value, asset); + OH_Value_Destroy(value); + OH_Data_Asset_DestroyOne(asset); + + OH_Value_GetAsset(nullptr, nullptr); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetAssetsCountFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + size_t length = provider.ConsumeIntegral(); + OH_Value_GetAssetsCount(value, &length); + OH_Value_Destroy(value); + + OH_Value_GetAssetsCount(nullptr, &length); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetAssetsFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + size_t inLen = provider.ConsumeIntegralInRange(BLOBSIZE_MIN, BLOBSIZE_MAX); + Data_Asset *val = OH_Data_Asset_CreateOne(); + if (val == nullptr) { + OH_Value_Destroy(value); + return; + } + size_t outLen = provider.ConsumeIntegral(); + OH_Value_GetAssets(value, &val, inLen, &outLen); + OH_Value_Destroy(value); + OH_Data_Asset_DestroyOne(val); + + OH_Value_GetAssets(nullptr, nullptr, 0, nullptr); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetFloatVectorCountFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + size_t length = provider.ConsumeIntegral(); + OH_Value_GetFloatVectorCount(value, &length); + OH_Value_Destroy(value); + + OH_Value_GetFloatVectorCount(nullptr, nullptr); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetFloatVectorFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + size_t inLen = provider.ConsumeIntegralInRange(BLOBSIZE_MIN, BLOBSIZE_MAX); + float *val = new float[inLen]; + size_t outLen = provider.ConsumeIntegral(); + OH_Value_GetFloatVector(value, val, inLen, &outLen); + delete[] val; + OH_Value_Destroy(value); + + OH_Value_GetFloatVector(nullptr, nullptr, 0, nullptr); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetUnlimitedIntBandFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + size_t length = provider.ConsumeIntegral(); + OH_Value_GetUnlimitedIntBand(value, &length); + OH_Value_Destroy(value); + + OH_Value_GetUnlimitedIntBand(nullptr, nullptr); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetUnlimitedIntFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + int sign = provider.ConsumeIntegral(); + size_t inLen = provider.ConsumeIntegralInRange(BLOBSIZE_MIN, BLOBSIZE_MAX); + uint64_t *trueForm = new uint64_t[inLen]; + size_t outLen = provider.ConsumeIntegral(); + OH_Value_GetUnlimitedInt(value, &sign, trueForm, inLen, &outLen); + delete[] trueForm; + OH_Value_Destroy(value); + + OH_Value_GetUnlimitedInt(nullptr, nullptr, nullptr, 0, nullptr); + OH_Value_Destroy(nullptr); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + OHOS::OH_Value_DestroyFuzz(provider); + OHOS::OH_Value_PutNullFuzz(provider); + OHOS::OH_Value_PutIntFuzz(provider); + OHOS::OH_Value_PutRealFuzz(provider); + OHOS::OH_Value_PutTextFuzz(provider); + OHOS::OH_Value_PutBlobFuzz(provider); + OHOS::OH_Value_PutAssetFuzz(provider); + OHOS::OH_Value_PutAssetsFuzz(provider); + OHOS::OH_Value_PutFloatVectorFuzz(provider); + OHOS::OH_Value_PutUnlimitedIntFuzz(provider); + OHOS::OH_Value_GetTypeFuzz(provider); + OHOS::OH_Value_IsNullFuzz(provider); + OHOS::OH_Value_GetIntFuzz(provider); + OHOS::OH_Value_GetRealFuzz(provider); + OHOS::OH_Value_GetTextFuzz(provider); + OHOS::OH_Value_GetBlobFuzz(provider); + OHOS::OH_Value_GetAssetFuzz(provider); + OHOS::OH_Value_GetAssetsCountFuzz(provider); + OHOS::OH_Value_GetAssetsFuzz(provider); + OHOS::OH_Value_GetFloatVectorCountFuzz(provider); + OHOS::OH_Value_GetFloatVectorFuzz(provider); + OHOS::OH_Value_GetUnlimitedIntBandFuzz(provider); + OHOS::OH_Value_GetUnlimitedIntFuzz(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/oh_data_value_fuzzer.h b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/oh_data_value_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..01b63c5eb24c686f9e15b191745639e838bee4ef --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/oh_data_value_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 OH_DATA_VALUE_FUZZER_H +#define OH_DATA_VALUE_FUZZER_H + +#define FUZZ_PROJECT_NAME "oh_data_value_fuzzer" + +#endif // OH_DATA_VALUE_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..af3c6c0f4b36b3cea787d75a008a7335a45d9042 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("oh_data_values_buckets_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = "${relational_store_base_path}/test/ndk/fuzztest/oh_data_values_buckets_fuzzer" + + sources = [ "oh_data_values_buckets_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":oh_data_values_buckets_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..64d7767e6e29d3de338406d4a2ab136a8e9bf9e9 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/oh_data_values_buckets_fuzzer.cpp b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/oh_data_values_buckets_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..53e2e2beadc512be3bd4b3b9f92da3fd84f0fb8f --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/oh_data_values_buckets_fuzzer.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2025 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 "oh_data_values_buckets_fuzzer.h" + +#include + +#include "grd_api_manager.h" +#include "oh_data_value.h" +#include "oh_data_values_buckets.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + + +#define LENGTH_MIN 1 +#define LENGTH_MAX 10 + +#define STRING_MAX 10 + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +namespace OHOS { + +OH_VBucket *CreateRandomVBucket(FuzzedDataProvider &provider) +{ + OH_VBucket *vBucket = OH_Rdb_CreateValuesBucket(); + if (vBucket == nullptr) { + return nullptr; + } + std::string column = provider.ConsumeRandomLengthString(STRING_MAX); + int64_t value = provider.ConsumeIntegral(); + if (column.empty()) { + vBucket->destroy(vBucket); + return nullptr; + } + vBucket->putInt64(vBucket, column.c_str(), value); + return vBucket; +} + +OH_Data_VBuckets *CreateRandomVBuckets(FuzzedDataProvider &provider) +{ + OH_Data_VBuckets *vBuckets = OH_VBuckets_Create(); + if (vBuckets == nullptr) { + return nullptr; + } + OH_VBucket *vBucket = CreateRandomVBucket(provider); + if (vBucket != nullptr) { + OH_VBuckets_PutRow(vBuckets, vBucket); + } + return vBuckets; +} + +void OH_VBuckets_PutRowFuzz(FuzzedDataProvider &provider) +{ + OH_Data_VBuckets *vBuckets = OH_VBuckets_Create(); + if (vBuckets == nullptr) { + return; + } + + OH_VBucket *vBucket = CreateRandomVBucket(provider); + if (vBucket != nullptr) { + OH_VBuckets_PutRow(vBuckets, vBucket); + vBucket->destroy(vBucket); + } + OH_VBuckets_Destroy(vBuckets); + + OH_VBuckets_Destroy(nullptr); +} + +void OH_VBuckets_PutRowsFuzz(FuzzedDataProvider &provider) +{ + OH_Data_VBuckets *vBuckets = OH_VBuckets_Create(); + if (vBuckets == nullptr) { + return; + } + + OH_Data_VBuckets *rows = CreateRandomVBuckets(provider); + if (rows != nullptr) { + OH_VBuckets_PutRows(vBuckets, rows); + OH_VBuckets_Destroy(rows); + } + + OH_VBuckets_Destroy(vBuckets); +} + +void OH_VBuckets_RowCountFuzz(FuzzedDataProvider &provider) +{ + OH_Data_VBuckets *vBuckets = CreateRandomVBuckets(provider); + if (vBuckets == nullptr) { + return; + } + size_t count; + OH_VBuckets_RowCount(vBuckets, &count); + OH_VBuckets_Destroy(vBuckets); +} + +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + OHOS::OH_VBuckets_PutRowFuzz(provider); + OHOS::OH_VBuckets_PutRowsFuzz(provider); + OHOS::OH_VBuckets_RowCountFuzz(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/oh_data_values_buckets_fuzzer.h b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/oh_data_values_buckets_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..7e1294c078dd908a967af9b5c8373824d9846067 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/oh_data_values_buckets_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 OH_DATA_VALUES_BUCKETS_FUZZER_H +#define OH_DATA_VALUES_BUCKETS_FUZZER_H + +#define FUZZ_PROJECT_NAME "oh_data_values_buckets_fuzzer" + +#endif // OH_DATA_VALUES_BUCKETS_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..0bd598f1d32c211897620eb58263abd61992c1e4 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("oh_data_values_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = "${relational_store_base_path}/test/ndk/fuzztest/oh_data_values_fuzzer" + + sources = [ "oh_data_values_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":oh_data_values_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..64d7767e6e29d3de338406d4a2ab136a8e9bf9e9 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/oh_data_values_fuzzer.cpp b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/oh_data_values_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..805ffe83b57dc7683cc819f789081fb73b1521d1 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/oh_data_values_fuzzer.cpp @@ -0,0 +1,550 @@ +/* + * Copyright (c) 2025 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 "oh_data_values_fuzzer.h" + +#include + +#include "grd_api_manager.h" +#include "oh_data_value.h" +#include "oh_data_values.h" +#include "oh_data_values_buckets.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + + +#define LOOPS_MIN 1 +#define LOOPS_MAX 10 + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +namespace OHOS { + +OH_Data_Values *CreateRandomDataValues(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return nullptr; + } + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + for (size_t i = 0; i < loops; ++i) { + int64_t intValue = provider.ConsumeIntegral(); + double realValue = provider.ConsumeFloatingPoint(); + std::string textValue = provider.ConsumeRandomLengthString(); + size_t blobLength = provider.ConsumeIntegral(); + std::vector blobValue = provider.ConsumeBytes(blobLength); + + OH_Values_PutInt(values, intValue); + OH_Values_PutReal(values, realValue); + OH_Values_PutText(values, textValue.c_str()); + OH_Values_PutBlob(values, blobValue.data(), blobValue.size()); + } + return values; +} + +void OH_Values_PutFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + OH_Data_Value *dataValue = OH_Value_Create(); + if (dataValue != nullptr) { + OH_Values_Put(values, dataValue); + OH_Values_Put(values, nullptr); + OH_Values_Put(nullptr, dataValue); + } + + OH_Values_Destroy(values); + OH_Value_Destroy(dataValue); + + OH_Values_Put(nullptr, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutNullFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + + OH_Values_PutNull(values); + OH_Values_Destroy(values); + + OH_Values_PutNull(nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutIntFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + + int64_t intValue = provider.ConsumeIntegral(); + OH_Values_PutInt(values, intValue); + OH_Values_Destroy(values); + + OH_Values_PutInt(nullptr, 0); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutRealFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + + double realValue = provider.ConsumeFloatingPoint(); + OH_Values_PutReal(values, realValue); + OH_Values_Destroy(values); + + OH_Values_PutReal(nullptr, 0); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutTextFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + + std::string textValue = provider.ConsumeRandomLengthString(); + OH_Values_PutText(values, textValue.c_str()); + OH_Values_PutText(values, nullptr); + OH_Values_PutText(nullptr, textValue.c_str()); + OH_Values_Destroy(values); + + OH_Values_PutText(nullptr, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutBlobFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + size_t blobLength = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector blobValue = provider.ConsumeBytes(blobLength); + OH_Values_PutBlob(values, blobValue.data(), blobValue.size()); + OH_Values_Destroy(values); + + OH_Values_PutBlob(nullptr, nullptr, 0); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutAssetFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + OH_Values_Destroy(values); + return; + } + OH_Values_PutAsset(values, asset); + OH_Values_Destroy(values); + OH_Data_Asset_DestroyOne(asset); + + OH_Values_PutAsset(nullptr, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutAssetsFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector assets; + for (size_t i = 0; i < loops; i++) { + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + continue; + } + assets.push_back(asset); + } + + if (!assets.empty()) { + OH_Values_PutAssets(values, assets.data(), assets.size()); + } + + OH_Values_Destroy(values); + for (size_t i = 0; i < assets.size(); i++) { + Data_Asset *asset = assets[i]; + OH_Data_Asset_DestroyOne(asset); + } + + OH_Values_PutAssets(nullptr, nullptr, 0); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutFloatVectorFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector floatVector(loops); + for (size_t i = 0; i < loops; ++i) { + floatVector[i] = provider.ConsumeFloatingPoint(); + } + + OH_Values_PutFloatVector(values, floatVector.data(), floatVector.size()); + OH_Values_Destroy(values); + + OH_Values_PutFloatVector(nullptr, nullptr, 0); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutUnlimitedIntFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + + int sign = provider.ConsumeIntegral(); + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector trueForm(loops); + for (size_t i = 0; i < loops; ++i) { + trueForm[i] = provider.ConsumeIntegral(); + } + + OH_Values_PutUnlimitedInt(values, sign, trueForm.data(), trueForm.size()); + OH_Values_Destroy(values); + + OH_Values_PutUnlimitedInt(nullptr, 0, nullptr, 0); + OH_Values_Destroy(nullptr); +} + +void OH_Values_CountFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + size_t count; + OH_Values_Count(values, &count); + OH_Values_Destroy(values); + + OH_Values_Count(nullptr, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetTypeFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + OH_ColumnType type; + OH_Values_GetType(values, index, &type); + OH_Values_Destroy(values); + + OH_Values_GetType(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + OH_Data_Value *dataValue; + OH_Values_Get(values, index, &dataValue); + OH_Values_Destroy(values); + + OH_Values_Get(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_IsNullFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + bool isNull; + OH_Values_IsNull(values, index, &isNull); + OH_Values_Destroy(values); + + OH_Values_IsNull(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetIntFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + int64_t intValue; + OH_Values_GetInt(values, index, &intValue); + OH_Values_Destroy(values); + + OH_Values_GetInt(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetRealFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + double realValue; + OH_Values_GetReal(values, index, &realValue); + OH_Values_Destroy(values); + + OH_Values_GetReal(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetTextFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + const char *textValue; + OH_Values_GetText(values, index, &textValue); + OH_Values_Destroy(values); + + OH_Values_GetText(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetBlobFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + const uint8_t *blobValue; + size_t blobLength; + OH_Values_GetBlob(values, index, &blobValue, &blobLength); + OH_Values_Destroy(values); + + OH_Values_GetBlob(nullptr, 0, nullptr, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetAssetFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset != nullptr) { + OH_Values_GetAsset(values, index, asset); + } + OH_Values_Destroy(values); + OH_Data_Asset_DestroyOne(asset); + + OH_Values_GetAsset(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetAssetsCountFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + size_t count; + OH_Values_GetAssetsCount(values, index, &count); + OH_Values_Destroy(values); + + OH_Values_GetAssetsCount(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetAssetsFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + size_t inLen; + OH_Values_GetAssetsCount(values, index, &inLen); + if (inLen > 0) { + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + OH_Values_Destroy(values); + return; + } + size_t outLen; + OH_Values_GetAssets(values, index, &asset, inLen, &outLen); + OH_Data_Asset_DestroyOne(asset); + } + + OH_Values_Destroy(values); + + OH_Values_GetAssets(nullptr, 0, nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetFloatVectorCountFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + size_t count; + OH_Values_GetFloatVectorCount(values, index, &count); + OH_Values_Destroy(values); + + OH_Values_GetFloatVectorCount(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetFloatVectorFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + size_t inLen; + OH_Values_GetFloatVectorCount(values, index, &inLen); + if (inLen > 0) { + float *floatVector = new float[inLen]; + size_t outLen; + OH_Values_GetFloatVector(values, index, floatVector, inLen, &outLen); + delete[] floatVector; + } + + OH_Values_Destroy(values); + + OH_Values_GetFloatVector(nullptr, 0, nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetUnlimitedIntBandFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + size_t count; + OH_Values_GetUnlimitedIntBand(values, index, &count); + OH_Values_Destroy(values); + + OH_Values_GetUnlimitedIntBand(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetUnlimitedIntFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + size_t inLen; + OH_Values_GetUnlimitedIntBand(values, index, &inLen); + if (inLen > 0) { + int sign; + uint64_t *trueForm = new uint64_t[inLen]; + size_t outLen; + OH_Values_GetUnlimitedInt(values, index, &sign, trueForm, inLen, &outLen); + delete[] trueForm; + } + + OH_Values_Destroy(values); + + OH_Values_GetUnlimitedInt(nullptr, 0, nullptr, nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + OHOS::OH_Values_PutFuzz(provider); + OHOS::OH_Values_PutNullFuzz(provider); + OHOS::OH_Values_PutIntFuzz(provider); + OHOS::OH_Values_PutRealFuzz(provider); + OHOS::OH_Values_PutTextFuzz(provider); + OHOS::OH_Values_PutBlobFuzz(provider); + OHOS::OH_Values_PutAssetFuzz(provider); + OHOS::OH_Values_PutAssetsFuzz(provider); + OHOS::OH_Values_PutFloatVectorFuzz(provider); + OHOS::OH_Values_PutUnlimitedIntFuzz(provider); + OHOS::OH_Values_CountFuzz(provider); + OHOS::OH_Values_GetTypeFuzz(provider); + OHOS::OH_Values_GetFuzz(provider); + OHOS::OH_Values_IsNullFuzz(provider); + OHOS::OH_Values_GetIntFuzz(provider); + OHOS::OH_Values_GetRealFuzz(provider); + OHOS::OH_Values_GetTextFuzz(provider); + OHOS::OH_Values_GetBlobFuzz(provider); + OHOS::OH_Values_GetAssetFuzz(provider); + OHOS::OH_Values_GetAssetsCountFuzz(provider); + OHOS::OH_Values_GetAssetsFuzz(provider); + OHOS::OH_Values_GetFloatVectorCountFuzz(provider); + OHOS::OH_Values_GetFloatVectorFuzz(provider); + OHOS::OH_Values_GetUnlimitedIntBandFuzz(provider); + OHOS::OH_Values_GetUnlimitedIntFuzz(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/oh_data_values_fuzzer.h b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/oh_data_values_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..1fb1e57e47e6960b24b4b6ab4f6be0a887317956 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/oh_data_values_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 OH_DATA_VALUES_FUZZER_H +#define OH_DATA_VALUES_FUZZER_H + +#define FUZZ_PROJECT_NAME "oh_data_values_fuzzer" + +#endif // OH_DATA_VALUES_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..d39cf55627eda87cf8b762173bbdbc15f21cc1e8 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("oh_predicates_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = "${relational_store_base_path}/test/ndk/fuzztest/oh_predicates_fuzzer" + + sources = [ "oh_predicates_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":oh_predicates_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..64d7767e6e29d3de338406d4a2ab136a8e9bf9e9 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/oh_predicates_fuzzer.cpp b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/oh_predicates_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5969a0a1844a4e2281966706c9b1d4a3b935656c --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/oh_predicates_fuzzer.cpp @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2025 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 "oh_predicates_fuzzer.h" + +#include + +#include "grd_api_manager.h" +#include "oh_data_value.h" +#include "oh_data_values.h" +#include "oh_data_values_buckets.h" +#include "oh_predicates.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +#define LENGTH_MIN 1 +#define LENGTH_MAX 10 + +#define STRING_LENGTH_MAX 20 + +namespace OHOS { + +std::vector ConsumeRandomLengthValueObjectVector(FuzzedDataProvider &provider) +{ + size_t loops = provider.ConsumeIntegralInRange(LENGTH_MIN, LENGTH_MAX); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + OH_VObject *obj = OH_Rdb_CreateValueObject(); + columns.emplace_back(obj); + } + return columns; +} + +void TestOH_Predicates_equalTo(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->equalTo(predicates, field.c_str(), obj); + predicates->destroy(predicates); +} + +void TestOH_Predicates_notEqualTo(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->notEqualTo(predicates, field.c_str(), obj); + predicates->destroy(predicates); +} + +void TestOH_Predicates_beginWrap(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + predicates->beginWrap(predicates); + predicates->destroy(predicates); +} + +void TestOH_Predicates_endWrap(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + predicates->endWrap(predicates); + predicates->destroy(predicates); +} + +void TestOH_Predicates_orOperate(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + predicates->orOperate(predicates); + predicates->destroy(predicates); +} + +void TestOH_Predicates_andOperate(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + predicates->andOperate(predicates); + predicates->destroy(predicates); +} + +void TestOH_Predicates_isNull(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->isNull(predicates, field.c_str()); + predicates->destroy(predicates); +} + +void TestOH_Predicates_isNotNull(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->isNotNull(predicates, field.c_str()); + predicates->destroy(predicates); +} + +void TestOH_Predicates_like(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->like(predicates, field.c_str(), obj); + predicates->destroy(predicates); + obj->destroy(obj); +} + +void TestOH_Predicates_between(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->between(predicates, field.c_str(), obj); + predicates->destroy(predicates); + obj->destroy(obj); +} + +void TestOH_Predicates_notBetween(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->notBetween(predicates, field.c_str(), obj); + predicates->destroy(predicates); + obj->destroy(obj); +} + +void TestOH_Predicates_greaterThan(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->greaterThan(predicates, field.c_str(), obj); + predicates->destroy(predicates); + obj->destroy(obj); +} + +void TestOH_Predicates_lessThan(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->lessThan(predicates, field.c_str(), obj); + predicates->destroy(predicates); + obj->destroy(obj); +} + +void TestOH_Predicates_greaterThanOrEqualTo(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->greaterThanOrEqualTo(predicates, field.c_str(), obj); + predicates->destroy(predicates); + obj->destroy(obj); +} + +void TestOH_Predicates_lessThanOrEqualTo(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->lessThanOrEqualTo(predicates, field.c_str(), obj); + predicates->destroy(predicates); + obj->destroy(obj); +} + +void TestOH_Predicates_orderBy(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_OrderType type = static_cast(provider.ConsumeIntegral()); + predicates->orderBy(predicates, field.c_str(), type); + predicates->destroy(predicates); + obj->destroy(obj); +} + +void TestOH_Predicates_distinct(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + predicates->distinct(predicates); + predicates->destroy(predicates); +} + +void TestOH_Predicates_limit(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + unsigned int value = provider.ConsumeIntegral(); + predicates->limit(predicates, value); + predicates->destroy(predicates); +} + +void TestOH_Predicates_offset(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + unsigned int rowOffset = provider.ConsumeIntegral(); + predicates->offset(predicates, rowOffset); + predicates->destroy(predicates); +} + +void TestOH_Predicates_groupBy(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + size_t loops = provider.ConsumeIntegralInRange(LENGTH_MIN, LENGTH_MAX); + const char *fields[loops]; + for (size_t i = 0; i < loops; ++i) { + static std::string fieldsString = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX).c_str(); + fields[i] = fieldsString.c_str(); + } + predicates->groupBy(predicates, fields, loops); + predicates->destroy(predicates); +} + +void TestOH_Predicates_in(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + std::vector values = ConsumeRandomLengthValueObjectVector(provider); + for (auto value : values) { + predicates->in(predicates, field.c_str(), value); + value->destroy(value); + } + predicates->destroy(predicates); +} + +void TestOH_Predicates_notIn(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + std::vector values = ConsumeRandomLengthValueObjectVector(provider); + for (auto value : values) { + predicates->notIn(predicates, field.c_str(), value); + value->destroy(value); + } + predicates->destroy(predicates); +} + +void TestOH_Predicates_Having(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + std::string conditions = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Data_Values *values = OH_Values_Create(); + OH_Predicates_Having(predicates, conditions.c_str(), values); + predicates->destroy(predicates); +} + +void TestOH_Predicates_NotLike(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + std::string pattern = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates_NotLike(predicates, field.c_str(), pattern.c_str()); + predicates->destroy(predicates); +} + +void TestOH_Predicates_Glob(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + std::string pattern = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates_Glob(predicates, field.c_str(), pattern.c_str()); + predicates->destroy(predicates); +} + +void TestOH_Predicates_NotGlob(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + std::string pattern = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates_NotGlob(predicates, field.c_str(), pattern.c_str()); + predicates->destroy(predicates); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + OHOS::TestOH_Predicates_equalTo(provider); + OHOS::TestOH_Predicates_notEqualTo(provider); + OHOS::TestOH_Predicates_beginWrap(provider); + OHOS::TestOH_Predicates_endWrap(provider); + OHOS::TestOH_Predicates_orOperate(provider); + OHOS::TestOH_Predicates_andOperate(provider); + OHOS::TestOH_Predicates_isNull(provider); + OHOS::TestOH_Predicates_isNotNull(provider); + OHOS::TestOH_Predicates_like(provider); + OHOS::TestOH_Predicates_between(provider); + OHOS::TestOH_Predicates_notBetween(provider); + OHOS::TestOH_Predicates_greaterThan(provider); + OHOS::TestOH_Predicates_lessThan(provider); + OHOS::TestOH_Predicates_greaterThanOrEqualTo(provider); + OHOS::TestOH_Predicates_lessThanOrEqualTo(provider); + OHOS::TestOH_Predicates_orderBy(provider); + OHOS::TestOH_Predicates_distinct(provider); + OHOS::TestOH_Predicates_limit(provider); + OHOS::TestOH_Predicates_offset(provider); + OHOS::TestOH_Predicates_groupBy(provider); + OHOS::TestOH_Predicates_in(provider); + OHOS::TestOH_Predicates_notIn(provider); + OHOS::TestOH_Predicates_Having(provider); + OHOS::TestOH_Predicates_NotLike(provider); + OHOS::TestOH_Predicates_Glob(provider); + OHOS::TestOH_Predicates_NotGlob(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/oh_predicates_fuzzer.h b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/oh_predicates_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..a229e34049a4d2c6165891b2a18d02fff73ad98d --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/oh_predicates_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 OH_PREDICATES_FUZZER_H +#define OH_PREDICATES_FUZZER_H + +#define FUZZ_PROJECT_NAME "oh_predicates_fuzzer" + +#endif // OH_PREDICATES_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3cb6405237c2b5352e3fb04608fb1264563be75b --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("oh_rdb_crypto_param_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = "${relational_store_base_path}/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer" + + sources = [ "oh_rdb_crypto_param_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":oh_rdb_crypto_param_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..64d7767e6e29d3de338406d4a2ab136a8e9bf9e9 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/oh_rdb_crypto_param_fuzzer.cpp b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/oh_rdb_crypto_param_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f8d69fe7966ae8b34d6a84dbce1929d2dfeb0593 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/oh_rdb_crypto_param_fuzzer.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2025 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 "oh_rdb_crypto_param_fuzzer.h" + +#include + +#include "grd_api_manager.h" +#include "oh_data_value.h" +#include "oh_data_values.h" +#include "oh_data_values_buckets.h" +#include "oh_predicates.h" +#include "oh_rdb_crypto_param.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + +#define LENGTH_MIN 1 +#define LENGTH_MAX 10 + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; +using namespace std; + +namespace OHOS { + +void OH_Rdb_DestroyCryptoParamFuzz(FuzzedDataProvider &provider) +{ + OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam(); + if (param != nullptr) { + OH_Rdb_DestroyCryptoParam(param); + } + OH_Rdb_DestroyCryptoParam(nullptr); +} + +void OH_Crypto_SetEncryptionKeyFuzz(FuzzedDataProvider &provider) +{ + OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam(); + if (param != nullptr) { + size_t bytesSize = provider.ConsumeIntegralInRange(LENGTH_MIN, LENGTH_MAX); + std::vector blobData = provider.ConsumeBytes(bytesSize); + OH_Crypto_SetEncryptionKey(param, blobData.data(), blobData.size()); + } + OH_Rdb_DestroyCryptoParam(param); +} + +void OH_Crypto_SetIterationFuzz(FuzzedDataProvider &provider) +{ + OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam(); + if (param != nullptr) { + const int64_t iteration = provider.ConsumeIntegral(); + OH_Crypto_SetIteration(param, iteration); + } + OH_Rdb_DestroyCryptoParam(param); +} + +void OH_Crypto_SetEncryptionAlgoFuzz(FuzzedDataProvider &provider) +{ + OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam(); + if (param != nullptr) { + const int32_t algo = provider.ConsumeIntegral(); + OH_Crypto_SetEncryptionAlgo(param, algo); + } + OH_Rdb_DestroyCryptoParam(param); +} + +void OH_Crypto_SetHmacAlgoFuzz(FuzzedDataProvider &provider) +{ + OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam(); + if (param != nullptr) { + const int32_t algo = provider.ConsumeIntegral(); + OH_Crypto_SetHmacAlgo(param, algo); + } + OH_Rdb_DestroyCryptoParam(param); +} + +void OH_Crypto_SetKdfAlgoFuzz(FuzzedDataProvider &provider) +{ + OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam(); + if (param != nullptr) { + const int32_t algo = provider.ConsumeIntegral(); + OH_Crypto_SetKdfAlgo(param, algo); + } + OH_Rdb_DestroyCryptoParam(param); +} + +void OH_Crypto_SetCryptoPageSizeFuzz(FuzzedDataProvider &provider) +{ + OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam(); + if (param != nullptr) { + const int64_t size = provider.ConsumeIntegral(); + OH_Crypto_SetCryptoPageSize(param, size); + } + OH_Rdb_DestroyCryptoParam(param); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::OH_Rdb_DestroyCryptoParamFuzz(provider); + OHOS::OH_Crypto_SetEncryptionKeyFuzz(provider); + OHOS::OH_Crypto_SetIterationFuzz(provider); + OHOS::OH_Crypto_SetEncryptionAlgoFuzz(provider); + OHOS::OH_Crypto_SetHmacAlgoFuzz(provider); + OHOS::OH_Crypto_SetKdfAlgoFuzz(provider); + OHOS::OH_Crypto_SetCryptoPageSizeFuzz(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/oh_rdb_crypto_param_fuzzer.h b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/oh_rdb_crypto_param_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..824febacc09121d0811ef8d43dd7e53f0962f6bf --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/oh_rdb_crypto_param_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 OH_RDB_CRYPTO_PARAM_FUZZER_H +#define OH_RDB_CRYPTO_PARAM_FUZZER_H + +#define FUZZ_PROJECT_NAME "oh_rdb_crypto_param_fuzzer" + +#endif // OH_RDB_CRYPTO_PARAM_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..9df548a6d91e9890788fe4a4d2433a321e3feab7 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("OHPredicatesFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/ndk/fuzztest/ohpredicates_fuzzer" + + sources = [ "ohpredicates_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":OHPredicatesFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/ohpredicates_fuzzer.cpp b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/ohpredicates_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c3cdb861b1b21deaddf5d356d2f4e83e65883a1 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/ohpredicates_fuzzer.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 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 "ohpredicates_fuzzer.h" +#include +#include "oh_predicates.h" +#include "relational_store.h" +#include + +void OhPredicatesFuzzTest(FuzzedDataProvider &provider) +{ + static bool runEndFlag = false; + std::string tableName = provider.ConsumeRandomLengthString(); + std::string field = provider.ConsumeRandomLengthString(); + std::string pattern = provider.ConsumeRandomLengthString(); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates(tableName.c_str()); + OH_Predicates_NotLike(predicates, field.c_str(), pattern.c_str()); + OH_Predicates_Glob(predicates, field.c_str(), pattern.c_str()); + OH_Predicates_NotGlob(predicates, field.c_str(), pattern.c_str()); + + if (!runEndFlag) { + runEndFlag = true; + std::cout << "OhPredicatesFuzzTest end" << std::endl; + } + if (predicates != nullptr) { + predicates->destroy(predicates); + } +} + + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + /* Run your code on data */ + FuzzedDataProvider provider(data, size); + + // Test OH_Predicates_NotLike, OH_Predicates_Glob, OH_Predicates_NotGlob + OhPredicatesFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/ohpredicates_fuzzer.h b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/ohpredicates_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..f4f89da15a20e63769c566711c85c7b84c2251d3 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/ohpredicates_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 OHPREDICATES_FUZZER_H +#define OHPREDICATES_FUZZER_H + +#define FUZZ_PROJECT_NAME "ohpredicates_fuzzer" + +#endif // OHPREDICATES_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..9abc24caf7fa08474173d027b90e434c7e62d668 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/BUILD.gn @@ -0,0 +1,70 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("OHRdbTransactionFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/ndk/fuzztest/ohrdbtransaction_fuzzer" + + sources = [ "ohrdbtransaction_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":OHRdbTransactionFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2aea1356e3c3b3ee6e12ad3f72640897d769d02e --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ diff --git a/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/ohrdbtransaction_fuzzer.cpp b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/ohrdbtransaction_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fa1e2cadc2475e177c1e2dfb76a208aa51173406 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/ohrdbtransaction_fuzzer.cpp @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2025 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 "grd_api_manager.h" +#include "oh_rdb_transaction.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" +#include "ohrdbtransaction_fuzzer.h" +#include + +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +// Helper function to create an OH_Rdb_Config structure with random data +OH_Rdb_Config *CreateRandomConfig(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = new OH_Rdb_Config(); + config->selfSize = sizeof(OH_Rdb_Config); + config->dataBaseDir = strdup(provider.ConsumeRandomLengthString().c_str()); + config->storeName = strdup(provider.ConsumeRandomLengthString().c_str()); + config->bundleName = strdup(provider.ConsumeRandomLengthString().c_str()); + config->moduleName = strdup(provider.ConsumeRandomLengthString().c_str()); + config->isEncrypt = provider.ConsumeBool(); + config->securityLevel = provider.ConsumeIntegralInRange(S1, S4); + config->area = provider.ConsumeIntegralInRange(RDB_SECURITY_AREA_EL1, RDB_SECURITY_AREA_EL5); + return config; +} + +void ReleaseConfig(OH_Rdb_Config *config) +{ + if (config == nullptr) { + return; + } + if (config->dataBaseDir != nullptr) { + free(static_cast(const_cast(config->dataBaseDir))); + } + if (config->storeName != nullptr) { + free(static_cast(const_cast(config->storeName))); + } + if (config->bundleName != nullptr) { + free(static_cast(const_cast(config->bundleName))); + } + if (config->moduleName != nullptr) { + free(static_cast(const_cast(config->moduleName))); + } + delete config; + config = nullptr; +} + +OH_RDB_TransOptions *CreateRandomTransOptions(FuzzedDataProvider &provider) +{ + OH_RDB_TransOptions *options = OH_RdbTrans_CreateOptions(); + if (options == nullptr) { + return nullptr; + } + OH_RDB_TransType type = + static_cast(provider.ConsumeIntegralInRange(RDB_TRANS_DEFERRED, RDB_TRANS_BUTT)); + OH_RdbTransOption_SetType(options, type); + return options; +} + +OH_VBucket *CreateRandomVBucket(FuzzedDataProvider &provider) +{ + OH_VBucket *vBucket = OH_Rdb_CreateValuesBucket(); + if (vBucket == nullptr) { + return nullptr; + } + const int minLen = 1; + const int maxLen = 50; + size_t len = provider.ConsumeIntegralInRange(minLen, maxLen); + for (size_t i = 0; i < len; i++) { + std::string column = provider.ConsumeRandomLengthString(); + int64_t value = provider.ConsumeIntegral(); + vBucket->putInt64(vBucket, column.c_str(), value); + } + return vBucket; +} + +std::vector g_randomVBuckets; +OH_Data_VBuckets *CreateRandomVBuckets(FuzzedDataProvider &provider) +{ + const int minRowCount = 1; + const int maxRowCount = 5; + g_randomVBuckets.clear(); + size_t rowCount = provider.ConsumeIntegralInRange(minRowCount, maxRowCount); + OH_Data_VBuckets *list = OH_VBuckets_Create(); + for (size_t i = 0; i < rowCount; i++) { + OH_VBucket *valueBucket = CreateRandomVBucket(provider); + g_randomVBuckets.push_back(valueBucket); + OH_VBuckets_PutRow(list, valueBucket); + } + return list; +} + +void DeleteCapiValueBuckets(OH_Data_VBuckets *rows) +{ + OH_VBuckets_Destroy(rows); + for (auto row : g_randomVBuckets) { + if (row != nullptr) { + row->destroy(row); + } + } + g_randomVBuckets.clear(); +} + +OH_VObject *CreateTransVObject(FuzzedDataProvider &provider) +{ + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + if (valueObject == nullptr) { + return nullptr; + } + std::string value = provider.ConsumeRandomLengthString(); + valueObject->putText(valueObject, value.c_str()); + return valueObject; +} + +OH_Predicates* GetCapiTransPredicates(FuzzedDataProvider &provider, std::string table) +{ + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return nullptr; + } + std::string value = provider.ConsumeRandomLengthString(); + OH_VObject *valueObject = CreateTransVObject(provider); + if (valueObject == nullptr) { + predicates->destroy(predicates); + return nullptr; + } + predicates->equalTo(predicates, value.c_str(), valueObject); + valueObject->destroy(valueObject); + return predicates; +} + +void DeleteCapiTransPredicates(OH_Predicates *predicates) +{ + if (predicates == nullptr) { + return; + } + predicates->destroy(predicates); +} + +void TransactionFuzzTest(FuzzedDataProvider &provider) +{ + static bool runEndFlag = false; + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + OH_RDB_TransOptions *options = CreateRandomTransOptions(provider); + OH_Rdb_Transaction *trans = nullptr; + OH_Rdb_CreateTransaction(store, options, &trans); + OH_RdbTrans_Commit(trans); + OH_RdbTrans_Rollback(trans); + std::string table = provider.ConsumeRandomLengthString(); + int64_t rowId = 0; + OH_VBucket *valueBucket = CreateRandomVBucket(provider); + OH_RdbTrans_Insert(trans, table.c_str(), valueBucket, &rowId); + OH_Data_VBuckets *list = CreateRandomVBuckets(provider); + std::string batchTable = provider.ConsumeRandomLengthString(); + int64_t changes; + Rdb_ConflictResolution resolution = static_cast( + provider.ConsumeIntegralInRange(RDB_CONFLICT_NONE, RDB_CONFLICT_REPLACE)); + OH_RdbTrans_BatchInsert(trans, batchTable.c_str(), list, resolution, &changes); + OH_RdbTrans_InsertWithConflictResolution(trans, table.c_str(), valueBucket, resolution, &rowId); + OH_Predicates *predicate = GetCapiTransPredicates(provider, table); + OH_RdbTrans_UpdateWithConflictResolution(trans, valueBucket, predicate, resolution, &rowId); + DeleteCapiTransPredicates(predicate); + DeleteCapiValueBuckets(list); + OH_Rdb_CloseStore(store); + ReleaseConfig(config); + OH_RdbTrans_DestroyOptions(options); + if (valueBucket != nullptr) { + valueBucket->destroy(valueBucket); + } + OH_RdbTrans_Destroy(trans); + if (!runEndFlag) { + runEndFlag = true; + std::cout << "TransactionFuzzTest end" << std::endl; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + TransactionFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/ohrdbtransaction_fuzzer.h b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/ohrdbtransaction_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..b5d77e84a3f9bba988d4087ae2cdcc3eb4937a91 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/ohrdbtransaction_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 OH_RDB_TRANSACTION_FUZZER_H +#define OH_RDB_TRANSACTION_FUZZER_H + +#define FUZZ_PROJECT_NAME "ohrdbtransaction_fuzzer" + +#endif // OH_RDB_TRANSACTION_FUZZER_H diff --git a/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..8fd3218b42b55e47c729417a966a63f7bcb65dab --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/BUILD.gn @@ -0,0 +1,72 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("RelationalStoreFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/ndk/fuzztest/relationalstore_fuzzer" + + sources = [ "relationalstore_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":RelationalStoreFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/relationalstore_fuzzer.cpp b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/relationalstore_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d50f1c549a8f0d59f3e182f995971e04ae7ade7b --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/relationalstore_fuzzer.cpp @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2025 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 "relationalstore_fuzzer.h" + +#include +#include +#include + +#include "grd_api_manager.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" +#include "accesstoken_kit.h" + +static constexpr const char *RDB_TEST_PATH = "/data/storage/el2/database/com.ohos.example.distributedndk/entry/"; + +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; +using namespace OHOS::Security::AccessToken; + +void CreateAndSetCryptoParam(FuzzedDataProvider &provider, OH_Rdb_ConfigV2 *config) +{ + if (config == nullptr) { + return; + } + OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam(); + int32_t length = provider.ConsumeIntegral(); + std::vector key = provider.ConsumeBytes(length); + int64_t iterator = provider.ConsumeIntegral(); + int32_t algo = provider.ConsumeIntegral(); + int64_t size = provider.ConsumeIntegral(); + + OH_Crypto_SetEncryptionKey(param, key.data(), key.size()); + OH_Crypto_SetIteration(param, iterator); + OH_Crypto_SetEncryptionAlgo(param, algo); + OH_Crypto_SetHmacAlgo(param, algo); + OH_Crypto_SetKdfAlgo(param, algo); + OH_Crypto_SetCryptoPageSize(param, size); + OH_Rdb_SetCryptoParam(config, param); + if (param != nullptr) { + OH_Rdb_DestroyCryptoParam(param); + } +} + +constexpr int RDB_CONFIG_PLUGINS_MAX = 16; +void CreateAndSetPlugins(FuzzedDataProvider &provider, OH_Rdb_ConfigV2 *config) +{ + uint32_t count = provider.ConsumeIntegralInRange(0, RDB_CONFIG_PLUGINS_MAX); + std::vector plugins; + for (uint32_t i = 0; i < count; i++) { + plugins.push_back(provider.ConsumeRandomLengthString()); + } + const char *arr[RDB_CONFIG_PLUGINS_MAX] = {nullptr}; + for (size_t i = 0; i < count; ++i) { + arr[i] = plugins[i].c_str(); + } + OH_Rdb_SetPlugins(config, arr, count); +} + +void AppendApi20ConfigV2(FuzzedDataProvider &provider, struct OH_Rdb_ConfigV2 *configV2) +{ + if (configV2 == nullptr) { + return; + } + bool readOnly = provider.ConsumeBool(); + OH_Rdb_SetReadOnly(configV2, readOnly); + std::string customDir = provider.ConsumeRandomLengthString(); + OH_Rdb_SetCustomDir(configV2, customDir.c_str()); + CreateAndSetPlugins(provider, configV2); + CreateAndSetCryptoParam(provider, configV2); +} + +struct OH_Rdb_ConfigV2 *CreateOHRdbConfigV2(FuzzedDataProvider &provider) +{ + struct OH_Rdb_ConfigV2 *configV2 = OH_Rdb_CreateConfig(); + if (configV2 == nullptr) { + return nullptr; + } + std::string databaseDir = provider.ConsumeRandomLengthString(); + OH_Rdb_SetDatabaseDir(configV2, databaseDir.c_str()); + std::string storeName = provider.ConsumeRandomLengthString(); + OH_Rdb_SetStoreName(configV2, storeName.c_str()); + std::string bundleName = provider.ConsumeRandomLengthString(); + OH_Rdb_SetBundleName(configV2, bundleName.c_str()); + std::string bmoduleName = provider.ConsumeRandomLengthString(); + OH_Rdb_SetModuleName(configV2, bmoduleName.c_str()); + bool isEncrypted = provider.ConsumeBool(); + OH_Rdb_SetEncrypted(configV2, isEncrypted); + int securityLevel = provider.ConsumeIntegral(); + OH_Rdb_SetSecurityLevel(configV2, securityLevel); + int area = provider.ConsumeIntegral(); + OH_Rdb_SetArea(configV2, area); + int dbType = provider.ConsumeIntegral(); + OH_Rdb_SetDbType(configV2, dbType); + + Rdb_Tokenizer tokenizer = + static_cast(provider.ConsumeIntegralInRange(RDB_NONE_TOKENIZER, RDB_CUSTOM_TOKENIZER)); + bool isSupported = false; + OH_Rdb_IsTokenizerSupported(tokenizer, &isSupported); + { + Rdb_Tokenizer tokenizer = + static_cast(provider.ConsumeIntegralInRange(RDB_NONE_TOKENIZER, RDB_CUSTOM_TOKENIZER)); + OH_Rdb_SetTokenizer(configV2, tokenizer); + } + bool isPersistent = provider.ConsumeBool(); + OH_Rdb_SetPersistent(configV2, isPersistent); + int typeCount = 0; + OH_Rdb_GetSupportedDbType(&typeCount); + return configV2; +} + +OH_VObject *CreateOHVObject(FuzzedDataProvider &provider) +{ + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + if (valueObject == nullptr) { + return nullptr; + } + std::string value = provider.ConsumeRandomLengthString(); + valueObject->putText(valueObject, value.c_str()); + return valueObject; +} + +OH_VBucket *CreateOHVBucket(FuzzedDataProvider &provider) +{ + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + if (valueBucket == nullptr) { + return nullptr; + } + { + std::string key = provider.ConsumeRandomLengthString(); + int64_t value = provider.ConsumeIntegral(); + valueBucket->putInt64(valueBucket, key.c_str(), value); + } + { + std::string key = provider.ConsumeRandomLengthString(); + std::string value = provider.ConsumeRandomLengthString(); + valueBucket->putText(valueBucket, key.c_str(), value.c_str()); + } + { + std::string key = provider.ConsumeRandomLengthString(); + float value = provider.ConsumeFloatingPoint(); + valueBucket->putReal(valueBucket, key.c_str(), value); + } + { + std::string key = provider.ConsumeRandomLengthString(); + const int minBlobSize = 1; + const int maxBlobSize = 50; + size_t blobSize = provider.ConsumeIntegralInRange(minBlobSize, maxBlobSize); + std::vector blobData = provider.ConsumeBytes(blobSize); + valueBucket->putBlob(valueBucket, key.c_str(), blobData.data(), blobData.size()); + } + return valueBucket; +} + +void RelationalStoreCAPIFuzzTest(FuzzedDataProvider &provider) +{ + struct OH_Rdb_ConfigV2 *configV2 = CreateOHRdbConfigV2(provider); + if (configV2 == nullptr) { + return; + } + OH_VObject *valueObject = CreateOHVObject(provider); + if (valueObject == nullptr) { + return; + } + std::string table = provider.ConsumeRandomLengthString(); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + { + std::string value = provider.ConsumeRandomLengthString(); + predicates->equalTo(predicates, value.c_str(), valueObject); + } + + OH_VBucket *valueBucket = CreateOHVBucket(provider); + if (valueBucket == nullptr) { + return; + } + + int errCode = 0; + static OH_Rdb_Store *OHRdbStore = OH_Rdb_CreateOrOpen(configV2, &errCode); + { + table = provider.ConsumeRandomLengthString(); + OH_Rdb_Insert(OHRdbStore, table.c_str(), valueBucket); + } + OH_Data_VBuckets *list = OH_VBuckets_Create(); + OH_VBuckets_PutRow(list, valueBucket); + { + table = provider.ConsumeRandomLengthString(); + Rdb_ConflictResolution resolution = static_cast( + provider.ConsumeIntegralInRange(RDB_CONFLICT_NONE, RDB_CONFLICT_REPLACE)); + int64_t changes = 0; + OH_Rdb_BatchInsert(OHRdbStore, table.c_str(), list, resolution, &changes); + } + OH_Rdb_Update(OHRdbStore, valueBucket, predicates); + valueBucket->destroy(valueBucket); + predicates->destroy(predicates); + valueObject->destroy(valueObject); + OH_VBuckets_Destroy(list); + OH_Rdb_CloseStore(OHRdbStore); + OH_Rdb_DeleteStoreV2(configV2); + OH_Rdb_DestroyConfig(configV2); +} + +void RelationalConfigV2Capi20FuzzTest(FuzzedDataProvider &provider) +{ + static bool runEndFlag = false; + struct OH_Rdb_ConfigV2 *configV2 = CreateOHRdbConfigV2(provider); + if (configV2 == nullptr) { + return; + } + AppendApi20ConfigV2(provider, configV2); + OH_Rdb_DestroyConfig(configV2); + if (!runEndFlag) { + runEndFlag = true; + std::cout << "RelationalConfigV2Capi20FuzzTest end" << std::endl; + } +} + +OH_Rdb_ConfigV2* g_normalConfig = nullptr; +void MockHap(void) +{ + HapInfoParams info = { + .userID = 100, + .bundleName = "com.example.distributed", + .instIndex = 0, + .appIDDesc = "com.example.distributed" + }; + PermissionDef infoManagerTestPermDef = { + .permissionName = "ohos.permission.test", + .bundleName = "com.example.distributed", + .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); +} + +OH_Rdb_Store *GetFuzzerNormalStore() +{ + MockHap(); + // 0770 is permission + mkdir(RDB_TEST_PATH, 0770); + g_normalConfig = OH_Rdb_CreateConfig(); + OH_Rdb_SetDatabaseDir(g_normalConfig, RDB_TEST_PATH); + OH_Rdb_SetStoreName(g_normalConfig, "rdb_store_test.db"); + OH_Rdb_SetBundleName(g_normalConfig, "com.ohos.example.distributedndk"); + OH_Rdb_SetEncrypted(g_normalConfig, false); + OH_Rdb_SetSecurityLevel(g_normalConfig, OH_Rdb_SecurityLevel::S1); + OH_Rdb_SetArea(g_normalConfig, RDB_SECURITY_AREA_EL1); + int errCode = 0; + OH_Rdb_Store *store = OH_Rdb_CreateOrOpen(g_normalConfig, &errCode); + return store; +} + +void DeleteFuzzerNormalStroe(OH_Rdb_Store *store) +{ + if (store != nullptr) { + delete store; + } + OH_Rdb_DeleteStoreV2(g_normalConfig); + OH_Rdb_DestroyConfig(g_normalConfig); + g_normalConfig = nullptr; +} + + +void InitFuzzerNormalStore(OH_Rdb_Store *store) +{ + if (store == nullptr) { + return; + } + char createTableSql[] = "CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, data2 INTEGER, " + "data3 FLOAT, data4 BLOB, data5 TEXT);"; + OH_Rdb_Execute(store, createTableSql); +} + +OH_VBucket* GetFuzzerNormalValuesBucket() +{ + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putInt64(valueBucket, "id", 1); + valueBucket->putText(valueBucket, "data1", "zhangSan"); + // 12800 stub number + valueBucket->putInt64(valueBucket, "data2", 12800); + // 100.1 stub number + valueBucket->putReal(valueBucket, "data3", 100.1); + valueBucket->putText(valueBucket, "data5", "ABCDEFG"); + return valueBucket; +} + +void DeleteFuzzerNormalValuesBucket(OH_VBucket *valueBucket) +{ + if (valueBucket == nullptr) { + return; + } + valueBucket->destroy(valueBucket); +} + +OH_Predicates* GetCapi20Predicates(FuzzedDataProvider &provider, std::string table) +{ + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return nullptr; + } + std::string value = provider.ConsumeRandomLengthString(); + OH_VObject *valueObject = CreateOHVObject(provider); + if (valueObject == nullptr) { + predicates->destroy(predicates); + return nullptr; + } + predicates->equalTo(predicates, value.c_str(), valueObject); + valueObject->destroy(valueObject); + return predicates; +} + +void DeleteCapi20Predicates(OH_Predicates *predicates) +{ + if (predicates != nullptr) { + return; + } + predicates->destroy(predicates); +} + + +void RelationalStoreCapi20FuzzTest(FuzzedDataProvider &provider) +{ + static bool runEndFlag = false; + int64_t rowId; + std::string table = "test"; + Rdb_ConflictResolution resolution = static_cast( + provider.ConsumeIntegralInRange(RDB_CONFLICT_NONE, RDB_CONFLICT_REPLACE)); + + OH_Rdb_Store *store = GetFuzzerNormalStore(); + OH_VBucket *valueBucket = GetFuzzerNormalValuesBucket(); + OH_Predicates *predicates = GetCapi20Predicates(provider, table); + do { + if (store == nullptr || valueBucket == nullptr || predicates == nullptr) { + break; + } + OH_Rdb_InsertWithConflictResolution(store, table.c_str(), valueBucket, resolution, &rowId); + OH_Rdb_UpdateWithConflictResolution(store, valueBucket, predicates, resolution, &rowId); + if (!runEndFlag) { + runEndFlag = true; + std::cout << "RelationalStoreCapi20FuzzTest end" << std::endl; + } + } while (0); + + DeleteCapi20Predicates(predicates); + DeleteFuzzerNormalValuesBucket(valueBucket); + DeleteFuzzerNormalStroe(store); +} + +void RelationalStoreAttatchFuzzTest(FuzzedDataProvider &provider) +{ + static bool runEndFlag = false; + OH_Rdb_Store *store = GetFuzzerNormalStore(); + OH_Rdb_ConfigV2 *attachConfig = OH_Rdb_CreateConfig(); + int64_t waitTime = provider.ConsumeIntegral(); + do { + if (store == nullptr || attachConfig == nullptr) { + break; + } + OH_Rdb_SetDatabaseDir(attachConfig, RDB_TEST_PATH); + OH_Rdb_SetStoreName(attachConfig, "rdb_attach_store_test.db"); + OH_Rdb_SetBundleName(attachConfig, "com.ohos.example.distributedndk"); + OH_Rdb_SetEncrypted(attachConfig, false); + OH_Rdb_SetSecurityLevel(attachConfig, OH_Rdb_SecurityLevel::S1); + OH_Rdb_SetArea(attachConfig, RDB_SECURITY_AREA_EL1); + + size_t attachedNumber = 0; + OH_Rdb_Attach(store, attachConfig, "attach_test", waitTime, &attachedNumber); + OH_Rdb_Detach(store, "attach_test", waitTime, &attachedNumber); + if (!runEndFlag) { + runEndFlag = true; + std::cout << "RelationalStoreAttatchFuzzTest end" << std::endl; + } + } while (0); + + OH_Rdb_DestroyConfig(attachConfig); + DeleteFuzzerNormalStroe(store); +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + /* Run your code on data */ + FuzzedDataProvider provider(data, size); + + RelationalStoreCAPIFuzzTest(provider); + + // Test OH_Rdb_SetCryptoParam + RelationalConfigV2Capi20FuzzTest(provider); + + // Test OH_Rdb_InsertWithConflictResolution and OH_Rdb_UpdateWithConflictResolution + RelationalStoreCapi20FuzzTest(provider); + + // Test OH_Rdb_Attach and OH_Rdb_Detach + RelationalStoreAttatchFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/relationalstore_fuzzer.h b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/relationalstore_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..b947b8d142c913f69508a9c36d443670ed59223a --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/relationalstore_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 RELATIONALSTORE_FUZZER_H +#define RELATIONALSTORE_FUZZER_H + +#define FUZZ_PROJECT_NAME "relationalstore_fuzzer" + +#endif // RELATIONALSTORE_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..da459f3c8125a90e50a28377058934c38fc72575 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("RelationalStoreCAPIFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = "${relational_store_base_path}/test/ndk/fuzztest/relationalstorecapi_fuzzer" + + sources = [ "relationalstorecapi_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":RelationalStoreCAPIFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/relationalstorecapi_fuzzer.cpp b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/relationalstorecapi_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a2917e02642efd2498115cf72bdfb14fc11e86d8 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/relationalstorecapi_fuzzer.cpp @@ -0,0 +1,526 @@ +/* + * Copyright (c) 2025 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 "relationalstorecapi_fuzzer.h" + +#include + +#include + +#include "grd_api_manager.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +// Helper function to create an OH_Rdb_Config structure with random data +OH_Rdb_Config *CreateRandomConfig(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = new OH_Rdb_Config(); + config->selfSize = sizeof(OH_Rdb_Config); + config->dataBaseDir = strdup(provider.ConsumeRandomLengthString().c_str()); + config->storeName = strdup(provider.ConsumeRandomLengthString().c_str()); + config->bundleName = strdup(provider.ConsumeRandomLengthString().c_str()); + config->moduleName = strdup(provider.ConsumeRandomLengthString().c_str()); + config->isEncrypt = provider.ConsumeBool(); + config->securityLevel = provider.ConsumeIntegralInRange(S1, S4); + config->area = provider.ConsumeIntegralInRange(RDB_SECURITY_AREA_EL1, RDB_SECURITY_AREA_EL5); + return config; +} + +void ReleaseConfig(OH_Rdb_Config *config) +{ + if (config == nullptr) { + return; + } + if (config->dataBaseDir != nullptr) { + free(static_cast(const_cast(config->dataBaseDir))); + } + if (config->storeName != nullptr) { + free(static_cast(const_cast(config->storeName))); + } + if (config->bundleName != nullptr) { + free(static_cast(const_cast(config->bundleName))); + } + if (config->moduleName != nullptr) { + free(static_cast(const_cast(config->moduleName))); + } + delete config; + config = nullptr; +} + +// Helper function to create an OH_Rdb_ConfigV2 structure with random data +OH_Rdb_ConfigV2 *CreateRandomConfigV2(FuzzedDataProvider &provider) +{ + OH_Rdb_ConfigV2 *configV2 = OH_Rdb_CreateConfig(); + std::string databaseDir = provider.ConsumeRandomLengthString(); + OH_Rdb_SetDatabaseDir(configV2, databaseDir.c_str()); + std::string storeName = provider.ConsumeRandomLengthString(); + OH_Rdb_SetStoreName(configV2, storeName.c_str()); + std::string bundleName = provider.ConsumeRandomLengthString(); + OH_Rdb_SetBundleName(configV2, bundleName.c_str()); + std::string bmoduleName = provider.ConsumeRandomLengthString(); + OH_Rdb_SetModuleName(configV2, bmoduleName.c_str()); + bool isEncrypted = provider.ConsumeBool(); + OH_Rdb_SetEncrypted(configV2, isEncrypted); + int securityLevel = provider.ConsumeIntegral(); + OH_Rdb_SetSecurityLevel(configV2, securityLevel); + int area = provider.ConsumeIntegral(); + OH_Rdb_SetArea(configV2, area); + int dbType = provider.ConsumeIntegral(); + OH_Rdb_SetDbType(configV2, dbType); + + Rdb_Tokenizer tokenizer = + static_cast(provider.ConsumeIntegralInRange(RDB_NONE_TOKENIZER, RDB_CUSTOM_TOKENIZER)); + bool isSupported = false; + OH_Rdb_IsTokenizerSupported(tokenizer, &isSupported); + { + Rdb_Tokenizer tokenizer = + static_cast(provider.ConsumeIntegralInRange(RDB_NONE_TOKENIZER, RDB_CUSTOM_TOKENIZER)); + OH_Rdb_SetTokenizer(configV2, tokenizer); + } + bool isPersistent = provider.ConsumeBool(); + OH_Rdb_SetPersistent(configV2, isPersistent); + return configV2; +} + +// Helper function to create an OH_Predicates structure with random data +OH_Predicates *CreateRandomPredicates(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return nullptr; + } + + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + { + std::string value = provider.ConsumeRandomLengthString(); + valueObject->putText(valueObject, value.c_str()); + } + + { + std::string value = provider.ConsumeRandomLengthString(); + predicates->equalTo(predicates, value.c_str(), valueObject); + } + + return predicates; +} + +// Helper function to create an OH_VBucket structure with random data +OH_VBucket *CreateRandomVBucket(FuzzedDataProvider &provider) +{ + OH_VBucket *vBucket = OH_Rdb_CreateValuesBucket(); + if (vBucket == nullptr) { + return nullptr; + } + const int minLen = 1; + const int maxLen = 50; + size_t len = provider.ConsumeIntegralInRange(minLen, maxLen); + for (size_t i = 0; i < len; i++) { + std::string column = provider.ConsumeRandomLengthString(); + int64_t value = provider.ConsumeIntegral(); + vBucket->putInt64(vBucket, column.c_str(), value); + } + return vBucket; +} + +// Helper function to create an OH_Rdb_TransOptions structure with random data +OH_RDB_TransOptions *CreateRandomTransOptions(FuzzedDataProvider &provider) +{ + OH_RDB_TransOptions *options = OH_RdbTrans_CreateOptions(); + OH_RDB_TransType type = + static_cast(provider.ConsumeIntegralInRange(RDB_TRANS_DEFERRED, RDB_TRANS_BUTT)); + OH_RdbTransOption_SetType(options, type); + return options; +} + +void OHRdbCreateOrOpenFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + // Test OH_Rdb_CloseStore + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbCreateOrOpenV2FuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_ConfigV2 *config = CreateRandomConfigV2(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_CreateOrOpen(config, &errCode); + if (store != nullptr) { + // Test OH_Rdb_CloseStore + OH_Rdb_CloseStore(store); + } +} + +void OHRdbSetVersionFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + int version = provider.ConsumeIntegral(); + OH_Rdb_SetVersion(store, version); + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbQueryLockedRowFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + OH_Predicates *predicates = CreateRandomPredicates(provider); + if (predicates != nullptr) { + const int minColumnCount = 1; + const int maxColumnCount = 50; + size_t columnCount = provider.ConsumeIntegralInRange(minColumnCount, maxColumnCount); + const char **columnNames = new const char *[columnCount]; + std::vector> columnStorage(columnCount); + + for (size_t i = 0; i < columnCount; ++i) { + std::string columnName = provider.ConsumeRandomLengthString(); + columnStorage[i] = std::make_unique(columnName.size() + 1); + std::copy(columnName.begin(), columnName.end(), columnStorage[i].get()); + columnStorage[i][columnName.size()] = '\0'; + columnNames[i] = columnStorage[i].get(); + } + OH_Cursor *cursor = OH_Rdb_QueryLockedRow(store, predicates, columnNames, columnCount); + if (cursor != nullptr) { + cursor->destroy(cursor); + } + predicates->destroy(predicates); + delete[] columnNames; + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbUnlockRowFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + OH_Predicates *predicates = CreateRandomPredicates(provider); + if (predicates != nullptr) { + OH_Rdb_UnlockRow(store, predicates); + predicates->destroy(predicates); + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbExecuteQueryV2FuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + std::string sql = provider.ConsumeRandomLengthString(); + OH_Data_Values *args = nullptr; // Simplified for fuzzing + OH_Cursor *cursor = OH_Rdb_ExecuteQueryV2(store, sql.c_str(), args); + if (cursor != nullptr) { + cursor->destroy(cursor); + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbBatchInsertFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + std::string table = provider.ConsumeRandomLengthString(); + const int minRowCount = 1; + const int maxRowCount = 5; + size_t rowCount = provider.ConsumeIntegralInRange(minRowCount, maxRowCount); + OH_Data_VBuckets *list = OH_VBuckets_Create(); + for (size_t i = 0; i < rowCount; i++) { + OH_VBuckets_PutRow(list, CreateRandomVBucket(provider)); + } + int64_t changes; + Rdb_ConflictResolution resolution = static_cast( + provider.ConsumeIntegralInRange(RDB_CONFLICT_NONE, RDB_CONFLICT_REPLACE)); + OH_Rdb_BatchInsert(store, table.c_str(), list, resolution, &changes); + OH_VBuckets_Destroy(list); + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbUpdateFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + OH_VBucket *valuesBucket = CreateRandomVBucket(provider); + OH_Predicates *predicates = CreateRandomPredicates(provider); + if (valuesBucket != nullptr && predicates != nullptr) { + OH_Rdb_Update(store, valuesBucket, predicates); + predicates->destroy(predicates); + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbLockRowFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + OH_Predicates *predicates = CreateRandomPredicates(provider); + if (predicates != nullptr) { + OH_Rdb_LockRow(store, predicates); + predicates->destroy(predicates); + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbCreateTransactionFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + OH_RDB_TransOptions *options = CreateRandomTransOptions(provider); + OH_Rdb_Transaction *trans = nullptr; + OH_Rdb_CreateTransaction(store, options, &trans); + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbCommitByTrxIdFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + int64_t trxId = provider.ConsumeIntegral(); + OH_Rdb_CommitByTrxId(store, trxId); + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbBackupFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + std::string databasePath = provider.ConsumeRandomLengthString(); + OH_Rdb_Backup(store, databasePath.c_str()); + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbUnsubscribeAutoSyncProgressFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + Rdb_ProgressObserver *observer = nullptr; // Simplified for fuzzing + OH_Rdb_UnsubscribeAutoSyncProgress(store, observer); + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbUnsubscribeFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + Rdb_SubscribeType type = static_cast( + provider.ConsumeIntegralInRange(RDB_SUBSCRIBE_TYPE_CLOUD, RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS)); + Rdb_DataObserver *observer = nullptr; // Simplified for fuzzing + OH_Rdb_Unsubscribe(store, type, observer); + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbExecuteV2FuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + std::string sql = provider.ConsumeRandomLengthString(100); + OH_Data_Values *values = OH_Values_Create(); + int value = provider.ConsumeIntegral(); + OH_Values_PutInt(values, value); + OH_Data_Value *result = nullptr; + OH_Rdb_ExecuteV2(store, sql.c_str(), values, &result); + if (values != nullptr) { + OH_Values_Destroy(values); + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbFindModifyTimeFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + std::string tableName = provider.ConsumeRandomLengthString(50); + std::string columnName = provider.ConsumeRandomLengthString(50); + OH_VObject *values = OH_Rdb_CreateValueObject(); + if (values != nullptr) { + OH_Cursor *cursor = OH_Rdb_FindModifyTime(store, tableName.c_str(), columnName.c_str(), values); + if (cursor != nullptr) { + cursor->destroy(cursor); + } + values->destroy(values); + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbGetFloatVectorCountFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + std::string sql = provider.ConsumeRandomLengthString(); + OH_Data_Values *args = nullptr; // Simplified for fuzzing + OH_Cursor *cursor = OH_Rdb_ExecuteQueryV2(store, sql.c_str(), args); + if (cursor != nullptr) { + int columnIndex = provider.ConsumeIntegral(); + size_t length = provider.ConsumeIntegral(); + OH_Cursor_GetFloatVectorCount(cursor, columnIndex, &length); + cursor->destroy(cursor); + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbGetFloatVectorFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + std::string sql = provider.ConsumeRandomLengthString(); + OH_Data_Values *args = nullptr; // Simplified for fuzzing + OH_Cursor *cursor = OH_Rdb_ExecuteQueryV2(store, sql.c_str(), args); + if (cursor != nullptr) { + int columnIndex = provider.ConsumeIntegral(); + float *val = new float(); + size_t inLen = provider.ConsumeIntegral(); + size_t outLen = provider.ConsumeIntegral(); + OH_Cursor_GetFloatVector(cursor, columnIndex, val, inLen, &outLen); + delete val; + cursor->destroy(cursor); + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void RelationalStoreFuzzTest(FuzzedDataProvider &provider) +{ + // Test OH_Rdb_CreateOrOpen + OHRdbCreateOrOpenFuzzTest(provider); + + // Test OH_Rdb_CreateOrOpenV2 + OHRdbCreateOrOpenV2FuzzTest(provider); + + // Test OH_Rdb_SetVersion + OHRdbSetVersionFuzzTest(provider); + + // Test OH_Rdb_QueryLockedRow + OHRdbQueryLockedRowFuzzTest(provider); + + // Test OH_Rdb_UnlockRow + OHRdbUnlockRowFuzzTest(provider); + + // Test OH_Rdb_ExecuteQueryV2 + OHRdbExecuteQueryV2FuzzTest(provider); + + // Test OH_Rdb_BatchInsert + OHRdbBatchInsertFuzzTest(provider); + + // Test OH_Rdb_Update + OHRdbUpdateFuzzTest(provider); + + // Test OH_Rdb_LockRow + OHRdbLockRowFuzzTest(provider); + + // Test OH_Rdb_CreateTransaction + OHRdbCreateTransactionFuzzTest(provider); + + // Test OH_Rdb_CommitByTrxId + OHRdbCommitByTrxIdFuzzTest(provider); + + // Test OH_Rdb_Backup + OHRdbBackupFuzzTest(provider); + + // Test OH_Rdb_UnsubscribeAutoSyncProgress + OHRdbUnsubscribeAutoSyncProgressFuzzTest(provider); + + // Test OH_Rdb_Unsubscribe + OHRdbUnsubscribeFuzzTest(provider); + + // Test OH_Rdb_ExecuteV2 + OHRdbExecuteV2FuzzTest(provider); + + // Test OH_Rdb_FindModifyTime + OHRdbFindModifyTimeFuzzTest(provider); + + // Test OH_Cursor_GetFloatVectorCount + OHRdbGetFloatVectorCountFuzzTest(provider); + + // Test OH_Cursor_GetFloatVector + OHRdbGetFloatVectorFuzzTest(provider); +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + RelationalStoreFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/relationalstorecapi_fuzzer.h b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/relationalstorecapi_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..2703e1819fd089caabbe9b5f3c5338a9ae468803 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/relationalstorecapi_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 RELATIONALSTORECAPI_FUZZER_H +#define RELATIONALSTORECAPI_FUZZER_H + +#define FUZZ_PROJECT_NAME "relationalstorecapi_fuzzer" + +#endif // RELATIONALSTORECAPI_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..fb8046cc30c0a138a3f791ee7555f8eba43d42b4 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/BUILD.gn @@ -0,0 +1,70 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("ValueBucketFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/ndk/fuzztest/valuebucket_fuzzer" + + sources = [ "valuebucket_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":ValueBucketFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/valuebucket_fuzzer.cpp b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/valuebucket_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..742a9c432a55365a958641f0860014acfcafd254 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/valuebucket_fuzzer.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2025 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 "valuebucket_fuzzer.h" + +#include + +#include "grd_api_manager.h" +#include "oh_value_object.h" +#include "oh_values_bucket.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + + +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +void putTextFuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + std::string value = provider.ConsumeRandomLengthString(); + valueBucket->putText(valueBucket, field.c_str(), value.c_str()); +} + +void putInt64FuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + int64_t value = provider.ConsumeIntegral(); + valueBucket->putInt64(valueBucket, field.c_str(), value); +} + +void putRealFuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + double value = static_cast(provider.ConsumeFloatingPoint()); + valueBucket->putReal(valueBucket, field.c_str(), value); +} + +void putBlobFuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + const int minBlobSize = 1; + const int maxBlobSize = 50; + size_t blobSize = provider.ConsumeIntegralInRange(minBlobSize, maxBlobSize); + std::vector value = provider.ConsumeBytes(blobSize); + valueBucket->putBlob(valueBucket, field.c_str(), value.data(), value.size()); +} + +void putNullFuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + valueBucket->putNull(valueBucket, field.c_str()); +} + +void putAssetFuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + int64_t value = provider.ConsumeIntegral(); + OH_Data_Asset_SetCreateTime(asset, value); + OH_VBucket_PutAsset(valueBucket, field.c_str(), asset); + OH_Data_Asset_DestroyOne(asset); // Destroy the asset +} + +void putAssetsFuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + const int minCount = 1; + const int maxCount = 50; + size_t count = provider.ConsumeIntegralInRange(minCount, maxCount); + Data_Asset **assets = OH_Data_Asset_CreateMultiple(count); + if (assets == nullptr) { + return; + } + for (size_t i = 0; i < count; i++) { + int64_t value = provider.ConsumeIntegral(); + OH_Data_Asset_SetCreateTime(assets[i], value); + } + OH_VBucket_PutAssets(valueBucket, field.c_str(), assets, count); + OH_Data_Asset_DestroyMultiple(assets, count); // Free the array of pointers +} + +void putFloatVectorFuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + const int minLen = 1; + const int maxLen = 50; + size_t len = provider.ConsumeIntegralInRange(minLen, maxLen); + std::vector vec(len); + for (size_t i = 0; i < len; i++) { + vec[i] = provider.ConsumeFloatingPoint(); + } + OH_VBucket_PutFloatVector(valueBucket, field.c_str(), vec.data(), len); +} + +void putUnlimitedIntFuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + const int minSign = 0; + const int maxSign = 1; + int sign = provider.ConsumeIntegralInRange(minSign, maxSign); + const int minLen = 1; + const int maxLen = 50; + size_t len = provider.ConsumeIntegralInRange(minLen, maxLen); + std::vector trueForm(len); + for (size_t i = 0; i < len; i++) { + trueForm[i] = provider.ConsumeIntegral(); + } + OH_VBucket_PutUnlimitedInt(valueBucket, field.c_str(), sign, trueForm.data(), len); +} + +void ValueBucketFuzzTest(FuzzedDataProvider &provider) +{ + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + if (valueBucket == nullptr) { + return; + } + + // Test putText + putTextFuzzTest(provider, valueBucket); + + // Test putInt64 + putInt64FuzzTest(provider, valueBucket); + + // Test putReal + putRealFuzzTest(provider, valueBucket); + + // Test putBlob + putBlobFuzzTest(provider, valueBucket); + + // Test putNull + putNullFuzzTest(provider, valueBucket); + + // Test putAsset + putAssetFuzzTest(provider, valueBucket); + + // Test putAssets + putAssetsFuzzTest(provider, valueBucket); + + // Test putFloatVector + putFloatVectorFuzzTest(provider, valueBucket); + + // Test putUnlimitedInt + putUnlimitedIntFuzzTest(provider, valueBucket); + + // Test clear + valueBucket->clear(valueBucket); + + // Destroy valueBucket + valueBucket->destroy(valueBucket); +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + ValueBucketFuzzTest(provider); + return 0; +} \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/valuebucket_fuzzer.h b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/valuebucket_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..6e6b24dfad4c3ee28f30a9c8d4d2b56f1a61827a --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/valuebucket_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 VALUEBUCKET_FUZZER_H +#define VALUEBUCKET_FUZZER_H + +#define FUZZ_PROJECT_NAME "valuebucket_fuzzer" + +#endif // VALUEBUCKET_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/valueobject_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3cae1a5f5df1111f0815165a67e75b95af4ca73f --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/BUILD.gn @@ -0,0 +1,70 @@ +# Copyright (c) 2025 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("ValueObjectFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/ndk/fuzztest/valueobject_fuzzer" + + sources = [ "valueobject_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":ValueObjectFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/valueobject_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/valueobject_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/valueobject_fuzzer/valueobject_fuzzer.cpp b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/valueobject_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a66d8e2b2f2f6ce093a150fc69bf9e7ec31ac2b --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/valueobject_fuzzer.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2025 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 "valueobject_fuzzer.h" + +#include + +#include "grd_api_manager.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + + +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +void ValueObjectFuzzTest(FuzzedDataProvider &provider) +{ + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + if (valueObject == nullptr) { + return; + } + + // Test putText + { + std::string value = provider.ConsumeRandomLengthString(); + valueObject->putText(valueObject, value.c_str()); + } + + // Test putInt64 + { + const int minArraySize = 1; + const int maxArraySize = 50; + size_t arraySize = provider.ConsumeIntegralInRange(minArraySize, maxArraySize); + std::vector array(arraySize); + for (size_t i = 0; i < arraySize; i++) { + array[i] = provider.ConsumeIntegral(); + } + valueObject->putInt64(valueObject, array.data(), array.size()); + } + + // Test putDouble + { + const int minArraySize = 1; + const int maxArraySize = 50; + size_t arraySize = provider.ConsumeIntegralInRange(minArraySize, maxArraySize); + std::vector array(arraySize); + for (size_t i = 0; i < arraySize; i++) { + array[i] = static_cast(provider.ConsumeFloatingPoint()); + } + valueObject->putDouble(valueObject, array.data(), array.size()); + } + + // Test putTexts + { + const int minArraySize = 1; + const int maxArraySize = 50; + size_t arraySize = provider.ConsumeIntegralInRange(minArraySize, maxArraySize); + + // Use std::vector to manage memory + std::vector> stringStorage(arraySize); + const char **array = new const char *[arraySize]; + + for (size_t i = 0; i < arraySize; i++) { + std::string value = provider.ConsumeRandomLengthString(); + + // Allocate memory for each string + stringStorage[i] = std::make_unique(value.size() + 1); + std::copy(value.begin(), value.end(), stringStorage[i].get()); + stringStorage[i][value.size()] = '\0'; // Ensure the string is null-terminated + + // Assign the pointer to array + array[i] = stringStorage[i].get(); + } + + // Use array + valueObject->putTexts(valueObject, array, arraySize); + + // Free the array pointer + delete[] array; + } + + // Destroy valueObject + valueObject->destroy(valueObject); +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + ValueObjectFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/valueobject_fuzzer/valueobject_fuzzer.h b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/valueobject_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..554cdecba5fb2593df387644fd69e59757ccd068 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/valueobject_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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 VALUEOBJECT_FUZZER_H +#define VALUEOBJECT_FUZZER_H + +#define FUZZ_PROJECT_NAME "valueobject_fuzzer" + +#endif // VALUEOBJECT_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/unittest/rdb_crypto_param_test.cpp b/relational_store/test/ndk/unittest/rdb_crypto_param_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a2501fe22f19bac8647444226a05840978899562 --- /dev/null +++ b/relational_store/test/ndk/unittest/rdb_crypto_param_test.cpp @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2025 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 +#include +#include +#include "relational_store_error_code.h" +#include "common.h" +#include "oh_rdb_crypto_param.h" +#include "oh_data_define.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; + +class RdbCryptoParamTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static void InitRdbConfig() + { + } +}; + +void RdbCryptoParamTest::SetUpTestCase(void) +{ +} + +void RdbCryptoParamTest::TearDownTestCase(void) +{ +} + +void RdbCryptoParamTest::SetUp(void) +{ +} + +void RdbCryptoParamTest::TearDown(void) +{ +} + +/** + * @tc.name: RDB_Crypto_Param_test_001 + * @tc.desc: Normal testCase of OH_Rdb_CreateCryptoParam and OH_Rdb_DestroyCryptoParam. + * @tc.type: FUNC + */ +HWTEST_F(RdbCryptoParamTest, RDB_Crypto_Param_test_001, TestSize.Level1) +{ + auto obj = OH_Rdb_CreateCryptoParam(); + EXPECT_NE(obj, NULL); + + auto ret = OH_Rdb_DestroyCryptoParam(nullptr); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Rdb_CryptoParam wrong; + wrong.id = 1; + ret = OH_Rdb_DestroyCryptoParam(&wrong); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_DestroyCryptoParam(obj); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Crypto_Param_test_002 + * @tc.desc: Normal testCase of OH_Crypto_SetEncryptionKey. + * @tc.type: FUNC + */ +HWTEST_F(RdbCryptoParamTest, RDB_Crypto_Param_test_002, TestSize.Level1) +{ + OH_Rdb_CryptoParam *obj = OH_Rdb_CreateCryptoParam(); + EXPECT_NE(obj, NULL); + + const uint8_t key[] = "12345678"; + auto ret = OH_Crypto_SetEncryptionKey(nullptr, key, sizeof(key) - 1); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Crypto_SetEncryptionKey(obj, key, sizeof(key) - 1); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(obj->cryptoParam.encryptKey_.size(), sizeof(key) - 1); + ret = OH_Rdb_DestroyCryptoParam(obj); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Crypto_Param_test_003 + * @tc.desc: Normal testCase of OH_Crypto_SetIteration. + * @tc.type: FUNC + */ +HWTEST_F(RdbCryptoParamTest, RDB_Crypto_Param_test_003, TestSize.Level1) +{ + OH_Rdb_CryptoParam *obj = OH_Rdb_CreateCryptoParam(); + EXPECT_NE(obj, NULL); + + // -1 is iteration times + auto ret = OH_Crypto_SetIteration(obj, -1); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + // 1000 is iteration times + ret = OH_Crypto_SetIteration(obj, 1000); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(obj->cryptoParam.iterNum, 1000); + ret = OH_Rdb_DestroyCryptoParam(obj); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Crypto_Param_test_004 + * @tc.desc: Normal testCase of OH_Crypto_SetEncryptionAlgo. + * @tc.type: FUNC + */ +HWTEST_F(RdbCryptoParamTest, RDB_Crypto_Param_test_004, TestSize.Level1) +{ + OH_Rdb_CryptoParam *obj = OH_Rdb_CreateCryptoParam(); + EXPECT_NE(obj, NULL); + + // 2 is invalid encryption + auto ret = OH_Crypto_SetEncryptionAlgo(obj, 2); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Crypto_SetEncryptionAlgo(obj, RDB_AES_256_CBC); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(obj->cryptoParam.encryptAlgo, RDB_AES_256_CBC); + ret = OH_Rdb_DestroyCryptoParam(obj); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Crypto_Param_test_005 + * @tc.desc: Normal testCase of OH_Crypto_SetHmacAlgo. + * @tc.type: FUNC + */ +HWTEST_F(RdbCryptoParamTest, RDB_Crypto_Param_test_005, TestSize.Level1) +{ + OH_Rdb_CryptoParam *obj = OH_Rdb_CreateCryptoParam(); + EXPECT_NE(obj, NULL); + + // 3 is invalid hdc + auto ret = OH_Crypto_SetHmacAlgo(obj, 3); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Crypto_SetHmacAlgo(obj, RDB_HMAC_SHA512); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(obj->cryptoParam.hmacAlgo, RDB_HMAC_SHA512); + + ret = OH_Rdb_DestroyCryptoParam(obj); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Crypto_Param_test_006 + * @tc.desc: Normal testCase of OH_Crypto_SetKdfAlgo. + * @tc.type: FUNC + */ +HWTEST_F(RdbCryptoParamTest, RDB_Crypto_Param_test_006, TestSize.Level1) +{ + OH_Rdb_CryptoParam *obj = OH_Rdb_CreateCryptoParam(); + EXPECT_NE(obj, NULL); + + // 3 is invalid kdf + auto ret = OH_Crypto_SetKdfAlgo(obj, 3); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Crypto_SetKdfAlgo(obj, RDB_KDF_SHA512); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(obj->cryptoParam.kdfAlgo, RDB_KDF_SHA512); + ret = OH_Rdb_DestroyCryptoParam(obj); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Crypto_Param_test_007 + * @tc.desc: Normal testCase of OH_Crypto_SetCryptoPageSize. + * @tc.type: FUNC + */ +HWTEST_F(RdbCryptoParamTest, RDB_Crypto_Param_test_007, TestSize.Level1) +{ + OH_Rdb_CryptoParam *obj = OH_Rdb_CreateCryptoParam(); + EXPECT_NE(obj, NULL); + + int64_t pageSize = -1; + auto ret = OH_Crypto_SetCryptoPageSize(obj, pageSize); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + pageSize = 1023; + ret = OH_Crypto_SetCryptoPageSize(obj, pageSize); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + pageSize = 0; + ret = OH_Crypto_SetCryptoPageSize(obj, pageSize); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + pageSize = 1024; + ret = OH_Crypto_SetCryptoPageSize(obj, pageSize); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(obj->cryptoParam.cryptoPageSize, pageSize); + + pageSize = 4096; + ret = OH_Crypto_SetCryptoPageSize(obj, pageSize); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(obj->cryptoParam.cryptoPageSize, pageSize); + ret = OH_Rdb_DestroyCryptoParam(obj); + EXPECT_EQ(ret, RDB_OK); +} \ No newline at end of file diff --git a/relational_store/test/ndk/unittest/rdb_cursor_test.cpp b/relational_store/test/ndk/unittest/rdb_cursor_test.cpp index 1840d11ab0d91a637589dc24cabc2fa3ef92f77b..b68a4e1297f1b5b260361535f3767b99f4fc84ed 100644 --- a/relational_store/test/ndk/unittest/rdb_cursor_test.cpp +++ b/relational_store/test/ndk/unittest/rdb_cursor_test.cpp @@ -328,8 +328,8 @@ HWTEST_F(RdbNativeCursorTest, RDB_Native_cursor_test_004, TestSize.Level1) size_t size = 0; cursor->getSize(cursor, 0, &size); - char data1Value[size + 1]; - cursor->getText(cursor, 0, data1Value, size + 1); + char data1Value[size]; + cursor->getText(cursor, 0, data1Value, size); EXPECT_EQ(strcmp(data1Value, "zhangSan"), 0); int64_t data2Value; @@ -349,9 +349,9 @@ HWTEST_F(RdbNativeCursorTest, RDB_Native_cursor_test_004, TestSize.Level1) cursor->goToNextRow(cursor); cursor->getSize(cursor, 0, &size); - char data1Value_1[size + 1]; - cursor->getText(cursor, 0, data1Value_1, size + 1); - EXPECT_EQ(strcmp(data1Value_1, "liSi"), 0); + char data1Value1[size]; + cursor->getText(cursor, 0, data1Value1, size); + EXPECT_EQ(strcmp(data1Value1, "liSi"), 0); cursor->getInt64(cursor, 1, &data2Value); EXPECT_EQ(data2Value, 13800); diff --git a/relational_store/test/ndk/unittest/rdb_performance_test.cpp b/relational_store/test/ndk/unittest/rdb_performance_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3fecf3bc3e61b1da73b172d7778d571c4020ea66 --- /dev/null +++ b/relational_store/test/ndk/unittest/rdb_performance_test.cpp @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2025 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 +#include +#include +#include +#include "accesstoken_kit.h" +#include "common.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" +#include "token_setproc.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::RdbNdk; + +static constexpr int64_t BASE_COUNT = 1000; // loop times +static constexpr int64_t RDB_INSERT_BASELINE = 3000; +static constexpr int64_t RDB_UPDATE_BASELINE = 3000; +static constexpr int64_t TRANS_INSERT_BASELINE = 3000; +static constexpr int64_t TRANS_UPDATE_BASELINE = 3000; +static constexpr int64_t RDB_ATTACH_BASELINE = 6000; // attach and detach two interfaces together. + +class RdbPerformanceTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static void InitRdbConfig() + { + config_.dataBaseDir = RDB_TEST_PATH; + config_.storeName = "rdb_store_test.db"; + config_.bundleName = "com.ohos.example.distributedndk"; + config_.moduleName = ""; + config_.securityLevel = OH_Rdb_SecurityLevel::S1; + config_.isEncrypt = false; + config_.selfSize = sizeof(OH_Rdb_Config); + config_.area = RDB_SECURITY_AREA_EL1; + } + static OH_Rdb_Config config_; + static void MockHap(void); +}; + +static OH_Rdb_Store *g_performanStore = nullptr; +static OH_RDB_TransOptions *g_options = nullptr; +OH_Rdb_Config RdbPerformanceTest::config_ = { 0 }; + +void RdbPerformanceTest::MockHap(void) +{ + HapInfoParams info = { + .userID = 100, + .bundleName = "com.example.distributed", + .instIndex = 0, + .appIDDesc = "com.example.distributed" + }; + PermissionDef infoManagerTestPermDef = { + .permissionName = "ohos.permission.test", + .bundleName = "com.example.distributed", + .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 RdbPerformanceTest::SetUpTestCase(void) +{ + MockHap(); + InitRdbConfig(); + // 0770 is permission + mkdir(config_.dataBaseDir, 0770); + int errCode = 0; + g_performanStore = OH_Rdb_GetOrOpen(&config_, &errCode); + EXPECT_NE(g_performanStore, NULL); + + g_options = OH_RdbTrans_CreateOptions(); + EXPECT_NE(g_options, nullptr); + int ret = OH_RdbTransOption_SetType(g_options, RDB_TRANS_BUTT); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_RdbTransOption_SetType(g_options, RDB_TRANS_DEFERRED); + EXPECT_EQ(ret, RDB_OK); +} + +void RdbPerformanceTest::TearDownTestCase(void) +{ + int errCode = OH_Rdb_CloseStore(g_performanStore); + EXPECT_EQ(errCode, 0); + errCode = OH_Rdb_DeleteStore(&config_); + EXPECT_EQ(errCode, 0); + + OH_RdbTrans_DestroyOptions(g_options); + g_options = nullptr; +} + +void RdbPerformanceTest::SetUp(void) +{ + char createTableSql[] = "CREATE TABLE store_test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, data2 INTEGER, " + "data3 FLOAT, data4 BLOB, data5 TEXT);"; + int errCode = OH_Rdb_Execute(g_performanStore, createTableSql); + EXPECT_EQ(errCode, 0); + + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putInt64(valueBucket, "id", 1); + valueBucket->putText(valueBucket, "data1", "zhangSan"); + // 12800 test value. + valueBucket->putInt64(valueBucket, "data2", 12800); + // 100.1 test value. + valueBucket->putReal(valueBucket, "data3", 100.1); + uint8_t arr[] = { 1, 2, 3, 4, 5 }; + int len = sizeof(arr) / sizeof(arr[0]); + valueBucket->putBlob(valueBucket, "data4", arr, len); + valueBucket->putText(valueBucket, "data5", "ABCDEFG"); + errCode = OH_Rdb_Insert(g_performanStore, "store_test", valueBucket); + EXPECT_EQ(errCode, 1); + + char querySql[] = "SELECT * FROM store_test"; + OH_Cursor *cursor = OH_Rdb_ExecuteQuery(g_performanStore, querySql); + + int rowCount = 0; + cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(rowCount, 1); + cursor->destroy(cursor); + valueBucket->destroy(valueBucket); +} + +void RdbPerformanceTest::TearDown(void) +{ + char dropTableSql[] = "DROP TABLE IF EXISTS store_test"; + int errCode = OH_Rdb_Execute(g_performanStore, dropTableSql); + EXPECT_EQ(errCode, 0); +} + +/* * + * @tc.name: Trans_InsertWithConflictResolution_test_001 + * @tc.desc: test OH_RdbTrans_InsertWithConflictResolution interface performance. + * @tc.type: FUNC + */ +HWTEST_F(RdbPerformanceTest, Trans_InsertWithConflictResolution_test_001, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + const char *table = "store_test"; + int ret = OH_Rdb_CreateTransaction(g_performanStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putText(valueBucket, "data1", "test_name4"); + // init is data2 is 14800 + valueBucket->putInt64(valueBucket, "data2", 14800); + // init is data2 is 300.1 + valueBucket->putReal(valueBucket, "data3", 300.1); + valueBucket->putText(valueBucket, "data5", "ABCDEFGHI"); + int64_t rowId = -1; + + auto now = std::chrono::system_clock::now().time_since_epoch(); + int64_t start = std::chrono::duration_cast(now).count(); + + for (int i = 0; i < BASE_COUNT; i++) { + ret = OH_RdbTrans_InsertWithConflictResolution(trans, table, valueBucket, RDB_CONFLICT_ROLLBACK, &rowId); + EXPECT_EQ(ret, RDB_OK); + } + + now = std::chrono::system_clock::now().time_since_epoch(); + int64_t summaryTime = (std::chrono::duration_cast(now).count() - start); + int64_t averageTime = summaryTime / BASE_COUNT; + + EXPECT_LE(averageTime, RDB_INSERT_BASELINE); + + valueBucket->destroy(valueBucket); + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/* * + * @tc.name: Trans_UpdateWithConflictResolution_test_002 + * @tc.desc: test OH_RdbTrans_UpdateWithConflictResolution interface performance. + * @tc.type: FUNC + */ +HWTEST_F(RdbPerformanceTest, Trans_UpdateWithConflictResolution_test_002, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + const char *table = "store_test"; + int ret = OH_Rdb_CreateTransaction(g_performanStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + // new row + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putText(valueBucket, "data1", "liSi"); + // init data2 value is 13800 + valueBucket->putInt64(valueBucket, "data2", 13800); + // init data3 value is 200.1 + valueBucket->putReal(valueBucket, "data3", 200.1); + valueBucket->putNull(valueBucket, "data5"); + + // create predicates + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table); + // create match data + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + const char *data1Value = "zhangSan"; + valueObject->putText(valueObject, data1Value); + predicates->equalTo(predicates, "data1", valueObject); + + // update + int64_t changes = -1; + auto now = std::chrono::system_clock::now().time_since_epoch(); + int64_t start = std::chrono::duration_cast(now).count(); + + for (int i = 0; i < BASE_COUNT; i++) { + ret = OH_RdbTrans_UpdateWithConflictResolution(trans, valueBucket, predicates, RDB_CONFLICT_REPLACE, &changes); + EXPECT_EQ(ret, RDB_OK); + } + + now = std::chrono::system_clock::now().time_since_epoch(); + int64_t summaryTime = (std::chrono::duration_cast(now).count() - start); + int64_t averageTime = summaryTime / BASE_COUNT; + + EXPECT_LE(averageTime, RDB_UPDATE_BASELINE); + + // destroy + valueObject->destroy(valueObject); + valueBucket->destroy(valueBucket); + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/* * + * @tc.name: RDB_InsertWithConflictResolution_test_003 + * @tc.desc: test OH_Rdb_InsertWithConflictResolution interface performance. + * @tc.type: FUNC + */ +HWTEST_F(RdbPerformanceTest, RDB_InsertWithConflictResolution_test_003, TestSize.Level1) +{ + int ret = 0; + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putText(valueBucket, "data1", "liSi"); + valueBucket->putInt64(valueBucket, "data2", 13800); + valueBucket->putReal(valueBucket, "data3", 200.1); + valueBucket->putText(valueBucket, "data5", "ABCDEFGH"); + int64_t rowId = 0; + + auto now = std::chrono::system_clock::now().time_since_epoch(); + int64_t start = std::chrono::duration_cast(now).count(); + + for (int i = 0; i < BASE_COUNT; i++) { + ret = OH_Rdb_InsertWithConflictResolution(g_performanStore, "store_test", valueBucket, RDB_CONFLICT_ROLLBACK, + &rowId); + EXPECT_EQ(ret, RDB_OK); + } + + now = std::chrono::system_clock::now().time_since_epoch(); + int64_t summaryTime = (std::chrono::duration_cast(now).count() - start); + int64_t averageTime = summaryTime / BASE_COUNT; + + EXPECT_LE(averageTime, TRANS_INSERT_BASELINE); + + valueBucket->destroy(valueBucket); +} + +/* * + * @tc.name: RDB_UpdateWithConflictResolution_test_004 + * @tc.desc: test OH_Rdb_UpdateWithConflictResolution interface performance. + * @tc.type: FUNC + */ +HWTEST_F(RdbPerformanceTest, RDB_UpdateWithConflictResolution_test_004, TestSize.Level1) +{ + int ret = 0; + OH_Predicates *predicates = OH_Rdb_CreatePredicates("store_test"); + EXPECT_NE(predicates, NULL); + + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + EXPECT_NE(valueObject, NULL); + const char *data1Value = "zhangSan"; + valueObject->putText(valueObject, data1Value); + + predicates->equalTo(predicates, "data1", valueObject); + + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + EXPECT_NE(valueBucket, NULL); + valueBucket->putText(valueBucket, "data1", "liSi"); + valueBucket->putInt64(valueBucket, "data2", 13800); + valueBucket->putReal(valueBucket, "data3", 200.1); + valueBucket->putNull(valueBucket, "data5"); + + int64_t chgs = 0; + auto now = std::chrono::system_clock::now().time_since_epoch(); + int64_t start = std::chrono::duration_cast(now).count(); + + for (int i = 0; i < BASE_COUNT; i++) { + ret = OH_Rdb_UpdateWithConflictResolution(g_performanStore, valueBucket, predicates, RDB_CONFLICT_ROLLBACK, + &chgs); + EXPECT_EQ(ret, RDB_OK); + } + + now = std::chrono::system_clock::now().time_since_epoch(); + int64_t summaryTime = (std::chrono::duration_cast(now).count() - start); + int64_t averageTime = summaryTime / BASE_COUNT; + + EXPECT_LE(averageTime, TRANS_UPDATE_BASELINE); + + valueObject->destroy(valueObject); + valueBucket->destroy(valueBucket); + predicates->destroy(predicates); +} + +/* * + * @tc.name: RDB_AttachAndDetach_test_005 + * @tc.desc: Normal testCase of OH_Rdb_InsertWithConflictResolution errcode. + * @tc.type: FUNC + */ +HWTEST_F(RdbPerformanceTest, RDB_AttachAndDetach_test_005, TestSize.Level1) +{ + auto attachConfig = OH_Rdb_CreateConfig(); + ASSERT_NE(attachConfig, nullptr); + OH_Rdb_SetDatabaseDir(attachConfig, RDB_TEST_PATH); + OH_Rdb_SetStoreName(attachConfig, "rdb_attach_store_test.db"); + OH_Rdb_SetBundleName(attachConfig, "com.ohos.example.distributedndk"); + OH_Rdb_SetEncrypted(attachConfig, false); + OH_Rdb_SetSecurityLevel(attachConfig, OH_Rdb_SecurityLevel::S1); + OH_Rdb_SetArea(attachConfig, RDB_SECURITY_AREA_EL1); + + int errCode = 0; + auto tmpStore = OH_Rdb_CreateOrOpen(attachConfig, &errCode); + EXPECT_NE(tmpStore, NULL); + OH_Rdb_CloseStore(tmpStore); + + size_t attachedNumber = 0; + auto now = std::chrono::system_clock::now().time_since_epoch(); + int64_t start = std::chrono::duration_cast(now).count(); + for (int i = 0; i < BASE_COUNT; i++) { + auto ret = OH_Rdb_Attach(g_performanStore, attachConfig, "rdb_attach_test", 3, &attachedNumber); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_Detach(g_performanStore, "rdb_attach_test", 3, &attachedNumber); + EXPECT_EQ(ret, RDB_OK); + } + + now = std::chrono::system_clock::now().time_since_epoch(); + int64_t summaryTime = (std::chrono::duration_cast(now).count() - start); + int64_t averageTime = summaryTime / BASE_COUNT; + + EXPECT_LE(averageTime, RDB_ATTACH_BASELINE); +} \ No newline at end of file diff --git a/relational_store/test/ndk/unittest/rdb_predicates_pref_test.cpp b/relational_store/test/ndk/unittest/rdb_predicates_pref_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b65080836b23c600af03cf67201a9ccdb899da5b --- /dev/null +++ b/relational_store/test/ndk/unittest/rdb_predicates_pref_test.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 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 "RdbNdkPredicatesPrefTest" +#include +#include +#include + +#include +#include + +#include "logger.h" +#include "relational_store.h" +using namespace testing::ext; +using namespace OHOS::Rdb; +class RdbNdkPredicatesPrefTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; +const int BASE_COUNT = 2000; +const int HAVING_BASE_LINE = 10; +void RdbNdkPredicatesPrefTest::SetUpTestCase(void) +{ +} + +void RdbNdkPredicatesPrefTest::TearDownTestCase(void) +{ +} + +void RdbNdkPredicatesPrefTest::SetUp(void) +{ +} + +void RdbNdkPredicatesPrefTest::TearDown(void) +{ +} + +/** + * @tc.name: RDB_predicates_pref_test_having + * @tc.desc: Performance testing of basic scenarios for the Having interface + * @tc.type: FUNC + */ +HWTEST_F(RdbNdkPredicatesPrefTest, RDB_predicates_pref_test_having, TestSize.Level1) +{ + OH_Predicates *predicates = OH_Rdb_CreatePredicates("test"); + const char *columnNames[] = { "data" }; + predicates->groupBy(predicates, columnNames, 1); + auto start = std::chrono::high_resolution_clock::now(); + for (int i = 0; i < BASE_COUNT; i++) { + OH_Predicates_Having(predicates, "data", nullptr); + } + auto end = std::chrono::high_resolution_clock::now(); + auto total = std::chrono::duration_cast(end - start).count(); + double averageTime = static_cast(total) / BASE_COUNT; + LOG_INFO("the predicates_pref_test_having average time is %{public}f", averageTime); + ASSERT_TRUE(averageTime < HAVING_BASE_LINE); +} \ No newline at end of file diff --git a/relational_store/test/ndk/unittest/rdb_predicates_test.cpp b/relational_store/test/ndk/unittest/rdb_predicates_test.cpp index 41b88b36405a64f58950f90468da09c3dd99ef8c..4bb1f506825a39a497301e153f05167e767fb8a6 100644 --- a/relational_store/test/ndk/unittest/rdb_predicates_test.cpp +++ b/relational_store/test/ndk/unittest/rdb_predicates_test.cpp @@ -20,10 +20,10 @@ #include #include "common.h" +#include "oh_data_define.h" #include "oh_value_object.h" #include "relational_store.h" #include "relational_store_error_code.h" - using namespace testing::ext; using namespace OHOS::NativeRdb; @@ -48,6 +48,12 @@ public: OH_Rdb_Store *predicatesTestRdbStore_; OH_Rdb_Config RdbNativePredicatesTest::config_ = { 0 }; +const char HAVING_CREATE_SQL[] = + "CREATE TABLE IF NOT EXISTS orders (id INTEGER PRIMARY KEY AUTOINCREMENT, customer_id INTEGER, amount INTEGER)"; +const char HAVING_INSERT_SQL[] = + "INSERT INTO orders (customer_id, amount) VALUES (1, 1500), (1, 2000), (1, 3000), (2, 800), (2, 1200), (3, 1500)," + " (3, 2000), (3, 2500), (3, 1000)"; +const char HAVING_DROP_SQL[] = "DROP TABLE IF EXISTS orders"; void RdbNativePredicatesTest::SetUpTestCase(void) { InitRdbConfig(); @@ -154,12 +160,12 @@ HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_002, TestSize.Level const char *data1Value = "zhangSan"; valueObject->putText(valueObject, data1Value); predicates->notEqualTo(predicates, "data1", valueObject); - EXPECT_EQ(errCode, 0); OH_Cursor *cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, NULL, 0); EXPECT_NE(cursor, NULL); int rowCount = 0; errCode = cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(errCode, 0); EXPECT_EQ(rowCount, 2); valueObject->destroy(valueObject); @@ -198,8 +204,8 @@ HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_003, TestSize.Level size_t size = 0; cursor->getSize(cursor, 1, &size); - char data1Value[size + 1]; - cursor->getText(cursor, 1, data1Value, size + 1); + char data1Value[size]; + cursor->getText(cursor, 1, data1Value, size); EXPECT_EQ(strcmp(data1Value, "liSi"), 0); int64_t data2Value; @@ -215,9 +221,9 @@ HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_003, TestSize.Level EXPECT_EQ(isNull, true); cursor->getSize(cursor, 5, &size); - char data5Value_1[size + 1]; - cursor->getText(cursor, 5, data5Value_1, size + 1); - EXPECT_EQ(strcmp(data5Value_1, "ABCDEFGH"), 0); + char data5Value1[size]; + cursor->getText(cursor, 5, data5Value1, size); + EXPECT_EQ(strcmp(data5Value1, "ABCDEFGH"), 0); cursor->goToNextRow(cursor); cursor->getInt64(cursor, 0, &id); @@ -769,4 +775,353 @@ HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_021, TestSize.Level errCode = valueObject->destroy(nullptr); EXPECT_EQ(errCode, OH_Rdb_ErrCode::RDB_E_INVALID_ARGS); valueObject->destroy(valueObject); -} \ No newline at end of file +} + +/** + * @tc.name: RDB_Native_predicates_test_025 + * @tc.desc: Normal testCase of Predicates for having check params. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_025, TestSize.Level1) +{ + OH_Data_Values wrongValues; + OH_Predicates wrongPredicates; + wrongPredicates.id = 1; + + auto ret = OH_Predicates_Having(nullptr, "data5", &wrongValues); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_Having(&wrongPredicates, "data5", &wrongValues); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates("test"); + EXPECT_NE(predicates, nullptr); + + // test missing group by clause. + ret = OH_Predicates_Having(predicates, "data5", &wrongValues); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + const char *columnNames[] = { "data1"}; + predicates->groupBy(predicates, columnNames, 1); + + ret = OH_Predicates_Having(predicates, nullptr, &wrongValues); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_Having(predicates, "", &wrongValues); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_Having(predicates, "data5", nullptr); + EXPECT_EQ(ret, RDB_OK); + + OH_Data_Value value; + value.id = 1; + wrongValues.values_.push_back(value); + ret = OH_Predicates_Having(predicates, "data5", &wrongValues); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + wrongValues.id = 1; + ret = OH_Predicates_Having(predicates, "data5", &wrongValues); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + predicates->destroy(predicates); +} + +/** + * @tc.name: RDB_Native_predicates_test_026 + * @tc.desc: Verify scenarios without placeholders and without passing values + * 1.Execute OH_Predicates_Having(predicates, "total > 5000 AND count >= 3") + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_026, TestSize.Level1) +{ + auto errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_CREATE_SQL); + EXPECT_EQ(errCode, RDB_OK); + errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_INSERT_SQL); + EXPECT_EQ(errCode, RDB_OK); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates("orders"); + EXPECT_NE(predicates, nullptr); + const char *columnNames[] = { "customer_id"}; + predicates->groupBy(predicates, columnNames, 1); + errCode = OH_Predicates_Having(predicates, "total > 5000 AND count >= 3", nullptr); + EXPECT_EQ(errCode, RDB_OK); + + const char *columnNames1[] = { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total"}; + // 3 represents the number of columns. + OH_Cursor *cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, columnNames1, 3); + + EXPECT_EQ(cursor->goToNextRow(cursor), RDB_OK); + int64_t value; + EXPECT_EQ(cursor->getInt64(cursor, 0, &value), E_OK); + EXPECT_EQ(value, 1); + EXPECT_EQ(cursor->getInt64(cursor, 2, &value), E_OK); // 2 represents the total in the third column. + EXPECT_EQ(value, 6500); // 6500 means total price. + + EXPECT_EQ(cursor->goToNextRow(cursor), RDB_OK); + EXPECT_EQ(cursor->getInt64(cursor, 0, &value), E_OK); + EXPECT_EQ(value, 3); + EXPECT_EQ(cursor->getInt64(cursor, 2, &value), E_OK); // 2 represents the total in the third column. + EXPECT_EQ(value, 7000); // 7000 means total price. + + predicates->destroy(predicates); + cursor->destroy(cursor); + errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_DROP_SQL); + EXPECT_EQ(errCode, RDB_OK); +} + + /** + * @tc.name: RDB_Native_predicates_test_028 + * @tc.desc: Test conditions for passing in illegal SQL + * 1.Execute OH_Predicates_Having(predicates, "SALARY == 1.2") + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_028, TestSize.Level1) +{ + auto errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_CREATE_SQL); + EXPECT_EQ(errCode, RDB_OK); + errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_INSERT_SQL); + EXPECT_EQ(errCode, RDB_OK); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates("orders"); + EXPECT_NE(predicates, nullptr); + const char *columnNames[] = { "customer_id"}; + predicates->groupBy(predicates, columnNames, 1); + errCode = OH_Predicates_Having(predicates, "SALARY == 1.2", nullptr); + EXPECT_EQ(errCode, RDB_OK); + + const char *columnNames1[] = { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total"}; + // 3 represents the number of columns. + OH_Cursor *cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, columnNames1, 3); + int count; + EXPECT_EQ(cursor->getRowCount(cursor, &count), RDB_E_ERROR); + + predicates->destroy(predicates); + cursor->destroy(cursor); + errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_DROP_SQL); + EXPECT_EQ(errCode, RDB_OK); +} + +/** + * @tc.name: RDB_Native_predicates_test_029 + * @tc.desc: Verify scenarios without placeholders and without passing values + * 1.Execute OH_Predicates_Having(predicates, total > ? AND count >= ?", {5000}) + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_029, TestSize.Level1) +{ + auto errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_CREATE_SQL); + EXPECT_EQ(errCode, RDB_OK); + errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_INSERT_SQL); + EXPECT_EQ(errCode, RDB_OK); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates("orders"); + EXPECT_NE(predicates, nullptr); + const char *columnNames[] = { "customer_id"}; + predicates->groupBy(predicates, columnNames, 1); + + auto values = OH_Values_Create(); + OH_Values_PutInt(values, 5000); + + errCode = OH_Predicates_Having(predicates, "total > ? AND count >= ?", values); + EXPECT_EQ(errCode, RDB_OK); + + const char *columnNames1[] = { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total"}; + // 3 represents the number of columns. + OH_Cursor *cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, columnNames1, 3); + int count = -1; + EXPECT_EQ(cursor->getRowCount(cursor, &count), RDB_OK); + EXPECT_EQ(count, 0); + + predicates->destroy(predicates); + cursor->destroy(cursor); + errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_DROP_SQL); + EXPECT_EQ(errCode, RDB_OK); +} + +/** + * @tc.name: RDB_Native_predicates_test_030 + * @tc.desc: Test using placeholder scenarios. + * 1.Execute OH_Predicates_Having(predicates, total > ? AND count >= ?", {5000, 3}) + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_030, TestSize.Level1) +{ + auto errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_CREATE_SQL); + EXPECT_EQ(errCode, RDB_OK); + errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_INSERT_SQL); + EXPECT_EQ(errCode, RDB_OK); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates("orders"); + EXPECT_NE(predicates, nullptr); + const char *columnNames[] = { "customer_id"}; + predicates->groupBy(predicates, columnNames, 1); + auto values = OH_Values_Create(); + OH_Values_PutInt(values, 5000); + OH_Values_PutInt(values, 3); + errCode = OH_Predicates_Having(predicates, "total > ? AND count >= ?", values); + EXPECT_EQ(errCode, RDB_OK); + + const char *columnNames1[] = { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total"}; + // 3 represents the number of columns. + OH_Cursor *cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, columnNames1, 3); + + EXPECT_EQ(cursor->goToNextRow(cursor), RDB_OK); + int64_t value; + EXPECT_EQ(cursor->getInt64(cursor, 0, &value), E_OK); + EXPECT_EQ(value, 1); + EXPECT_EQ(cursor->getInt64(cursor, 2, &value), E_OK); // 2 represents the total in the third column. + EXPECT_EQ(value, 6500); // 6500 means total price. + + EXPECT_EQ(cursor->goToNextRow(cursor), RDB_OK); + EXPECT_EQ(cursor->getInt64(cursor, 0, &value), E_OK); + EXPECT_EQ(value, 3); + EXPECT_EQ(cursor->getInt64(cursor, 2, &value), E_OK); // 2 represents the total in the third column. + EXPECT_EQ(value, 7000); // 7000 means total price. + + predicates->destroy(predicates); + cursor->destroy(cursor); + errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_DROP_SQL); + EXPECT_EQ(errCode, RDB_OK); +} + +/** + * @tc.name: RDB_Native_predicates_test_031 + * @tc.desc: Normal testCase of Predicates for notLike. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_031, TestSize.Level1) +{ + int errCode = 0; + const char *data5Value = "BBCD%"; + const char *data2Value = "12%"; + + auto ret = OH_Predicates_NotLike(nullptr, "data5", data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Predicates wrong; + wrong.id = 1; + ret = OH_Predicates_NotLike(&wrong, "data5", data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates("test"); + EXPECT_NE(predicates, nullptr); + + ret = OH_Predicates_NotLike(predicates, nullptr, data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_NotLike(predicates, "data5", nullptr); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_NotLike(predicates, "data5", data5Value); + ret = OH_Predicates_NotLike(predicates, "data2", data2Value); + + OH_Cursor *cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, NULL, 0); + EXPECT_NE(cursor, NULL); + int rowCount = 0; + errCode = cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(rowCount, 2); + + predicates->destroy(predicates); + cursor->destroy(cursor); +} + +/** + * @tc.name: RDB_Native_predicates_test_032 + * @tc.desc: Normal testCase of Predicates for glob. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_032, TestSize.Level1) +{ + int errCode = 0; + const char *data5Value = "aBCD*"; + const char *data5Value2 = "ABCD*"; + + auto ret = OH_Predicates_Glob(nullptr, "data5", data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Predicates wrong; + wrong.id = 1; + ret = OH_Predicates_Glob(&wrong, "data5", data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates("test"); + EXPECT_NE(predicates, nullptr); + + ret = OH_Predicates_Glob(predicates, nullptr, data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_Glob(predicates, "data5", nullptr); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_Glob(predicates, "data5", data5Value); + OH_Cursor *cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, NULL, 0); + EXPECT_NE(cursor, NULL); + int rowCount = 0; + errCode = cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(rowCount, 0); + cursor->destroy(cursor); + predicates->destroy(predicates); + + predicates = OH_Rdb_CreatePredicates("test"); + EXPECT_NE(predicates, nullptr); + ret = OH_Predicates_Glob(predicates, "data5", data5Value2); + cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, NULL, 0); + EXPECT_NE(cursor, NULL); + rowCount = 0; + errCode = cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(rowCount, 3); + cursor->destroy(cursor); + predicates->destroy(predicates); +} + +/** + * @tc.name: RDB_Native_predicates_test_033 + * @tc.desc: Normal testCase of Predicates for glob. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_033, TestSize.Level1) +{ + int errCode = 0; + const char *data5Value = "aBCD*"; + const char *data5Value2 = "ABCD*"; + + auto ret = OH_Predicates_NotGlob(nullptr, "data5", data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Predicates wrong; + wrong.id = 1; + ret = OH_Predicates_NotGlob(&wrong, "data5", data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates("test"); + EXPECT_NE(predicates, nullptr); + + ret = OH_Predicates_NotGlob(predicates, nullptr, data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_NotGlob(predicates, "data5", nullptr); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_NotGlob(predicates, "data5", data5Value); + OH_Cursor *cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, NULL, 0); + EXPECT_NE(cursor, NULL); + int rowCount = 0; + errCode = cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(rowCount, 3); + cursor->destroy(cursor); + predicates->destroy(predicates); + + predicates = OH_Rdb_CreatePredicates("test"); + EXPECT_NE(predicates, nullptr); + ret = OH_Predicates_NotGlob(predicates, "data5", data5Value2); + cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, NULL, 0); + EXPECT_NE(cursor, NULL); + rowCount = 0; + errCode = cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(rowCount, 0); + cursor->destroy(cursor); + predicates->destroy(predicates); +} diff --git a/relational_store/test/ndk/unittest/rdb_store_configv2_test.cpp b/relational_store/test/ndk/unittest/rdb_store_configv2_test.cpp index 9775bd32f6e5655ba5e1f32ef2a4eac5679d16de..b99f6651a55eb7558a0877eaaf7dd29e384a8c73 100644 --- a/relational_store/test/ndk/unittest/rdb_store_configv2_test.cpp +++ b/relational_store/test/ndk/unittest/rdb_store_configv2_test.cpp @@ -21,10 +21,14 @@ #include "accesstoken_kit.h" #include "common.h" #include "grd_api_manager.h" +#include "oh_data_utils.h" #include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_ndk_utils.h" #include "relational_store.h" #include "relational_store_error_code.h" #include "relational_store_impl.h" +#include "relational_store_inner_types.h" #include "token_setproc.h" using namespace testing::ext; @@ -144,7 +148,7 @@ HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_003, TestSize.Level1) const int *supportTypeList = OH_Rdb_GetSupportedDbType(&numType); EXPECT_NE(supportTypeList, nullptr); EXPECT_TRUE(((!OHOS::NativeRdb::IsUsingArkData()) && numType == 1) || // 1 means only contain RDB_SQLITE - ((OHOS::NativeRdb::IsUsingArkData()) && numType == 2)); // 2 means both contain RDB_SQLITE and RDB_CAYLEY + ((OHOS::NativeRdb::IsUsingArkData()) && numType == 2)); // 2 means both contain RDB_SQLITE and RDB_CAYLEY EXPECT_EQ(RDB_SQLITE, supportTypeList[0]); if (OHOS::NativeRdb::IsUsingArkData()) { EXPECT_EQ(RDB_CAYLEY, supportTypeList[1]); // 1st element must be RDB_CAYLEY @@ -189,6 +193,8 @@ HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_004, TestSize.Level1) EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetDbType(config, 0)); // 0 is invalid db type level EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetDbType(config, 6)); // 6 is invalid db type level EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetDbType(config, -1)); // -1 is invalid db type level + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetSemanticIndex(config, true)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetSemanticIndex(config, false)); const int *supportList = OH_Rdb_GetSupportedDbType(nullptr); EXPECT_EQ(nullptr, supportList); @@ -314,3 +320,319 @@ HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_007, TestSize.Level1) EXPECT_EQ(errCode, OH_Rdb_ErrCode::RDB_OK); OH_Rdb_DestroyConfig(config); } + +/** + * @tc.name: RDB_ICU_TEST001 + * @tc.desc: test apis of icu + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_ICU_TEST001, TestSize.Level1) +{ + mkdir(RDB_TEST_PATH, 0770); + auto config = InitRdbConfig(); + + // invalid param test + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, + OH_Rdb_SetTokenizer(config, static_cast(Rdb_Tokenizer::RDB_NONE_TOKENIZER - 1))); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, + OH_Rdb_SetTokenizer(config, static_cast(Rdb_Tokenizer::RDB_CUSTOM_TOKENIZER + 1))); + + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetTokenizer(config, Rdb_Tokenizer::RDB_NONE_TOKENIZER)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetTokenizer(config, Rdb_Tokenizer::RDB_CUSTOM_TOKENIZER)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetTokenizer(config, Rdb_Tokenizer::RDB_ICU_TOKENIZER)); + + int numType = 0; + const int *supportTypeList = OH_Rdb_GetSupportedDbType(&numType); + EXPECT_NE(supportTypeList, nullptr); + if (numType == 2) { + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetDbType(config, RDB_CAYLEY)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_NOT_SUPPORTED, + + OH_Rdb_SetTokenizer(config, Rdb_Tokenizer::RDB_ICU_TOKENIZER)); + } + + OH_Rdb_DestroyConfig(config); +} + +/** + * @tc.name: RDB_ICU_TEST002 + * @tc.desc: test apis of icu + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_ICU_TEST002, TestSize.Level1) +{ + mkdir(RDB_TEST_PATH, 0770); + int errCode = 0; + auto config = InitRdbConfig(); + + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetTokenizer(config, Rdb_Tokenizer::RDB_ICU_TOKENIZER)); + auto storeConfigV2TestRdbStore = OH_Rdb_CreateOrOpen(config, &errCode); + EXPECT_NE(storeConfigV2TestRdbStore, NULL); + + char createTableSql[] = "CREATE VIRTUAL TABLE example USING fts4(name, content, tokenize=icu zh_CN);"; + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_Execute(storeConfigV2TestRdbStore, createTableSql)); + + char insertSql1[] = + "INSERT INTO example(name, content) VALUES('文档1', '这是一个测试文档,用于测试中文文本的分词和索引。');"; + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_Execute(storeConfigV2TestRdbStore, insertSql1)); + + char insertSql2[] = + "INSERT INTO example(name, content) VALUES('文档2', '我们将使用这个示例来演示如何在SQLite中进行全文搜索。');"; + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_Execute(storeConfigV2TestRdbStore, insertSql2)); + + char insertSql3[] = + "INSERT INTO example(name, content) VALUES('文档3', 'ICU分词器能够很好地处理中文文本的分词和分析。');"; + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_Execute(storeConfigV2TestRdbStore, insertSql3)); + + char querySql[] = "SELECT * FROM example WHERE example MATCH '测试';"; + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_Execute(storeConfigV2TestRdbStore, querySql)); + + OH_Cursor *cursor = OH_Rdb_ExecuteQuery(storeConfigV2TestRdbStore, querySql); + EXPECT_NE(cursor, nullptr); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, cursor->goToNextRow(cursor)); + + int columnIndex = -1; + errCode = cursor->getColumnIndex(cursor, "name", &columnIndex); + EXPECT_EQ(columnIndex, 0); + char name[10]; + errCode = cursor->getColumnName(cursor, columnIndex, name, 10); + EXPECT_EQ(strcmp(name, "name"), 0); + + size_t size = 0; + cursor->getSize(cursor, columnIndex, &size); + char data1Value[size + 1]; + cursor->getText(cursor, columnIndex, data1Value, size + 1); + EXPECT_EQ(strcmp(data1Value, "文档1"), 0); + + errCode = cursor->getColumnIndex(cursor, "content", &columnIndex); + char name2[10]; + errCode = cursor->getColumnName(cursor, columnIndex, name2, 10); + EXPECT_EQ(strcmp(name2, "content"), 0); + + cursor->getSize(cursor, columnIndex, &size); + char data2Value[size + 1]; + cursor->getText(cursor, columnIndex, data2Value, size + 1); + EXPECT_EQ(strcmp(data2Value, "这是一个测试文档,用于测试中文文本的分词和索引。"), 0); + + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_CloseStore(storeConfigV2TestRdbStore)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_DeleteStoreV2(config)); + OH_Rdb_DestroyConfig(config); +} + +/** + * @tc.name: RDB_Native_store_test_009 + * @tc.desc: test apis of config interface OH_Rdb_SetCustomDir. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_009, TestSize.Level1) +{ + const char *customDir = "test"; + auto ret = OH_Rdb_SetCustomDir(nullptr, customDir); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_SetCustomDir(nullptr, "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Rdb_ConfigV2 *confg = OH_Rdb_CreateConfig(); + EXPECT_NE(confg, nullptr); + ret = OH_Rdb_SetCustomDir(confg, nullptr); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_SetCustomDir(confg, customDir); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_DestroyConfig(confg); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Native_store_test_010 + * @tc.desc: test apis of config interface OH_Rdb_SetReadOnly. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_010, TestSize.Level1) +{ + OH_Rdb_ConfigV2 *confg = OH_Rdb_CreateConfig(); + EXPECT_NE(confg, nullptr); + + auto ret = OH_Rdb_SetReadOnly(nullptr, true); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_SetReadOnly(confg, true); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_SetReadOnly(confg, false); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_DestroyConfig(confg); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Native_store_test_011 + * @tc.desc: test apis of config interface OH_Rdb_SetPlugins. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_011, TestSize.Level1) +{ + OH_Rdb_ConfigV2 *confg = OH_Rdb_CreateConfig(); + EXPECT_NE(confg, nullptr); + + const char *plugins[] = { "1" }; + auto ret = OH_Rdb_SetPlugins(nullptr, plugins, 1); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_SetPlugins(confg, nullptr, 1); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_SetPlugins(confg, plugins, 0); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_SetPlugins(confg, plugins, 1); + EXPECT_EQ(ret, RDB_OK); + + const char *pluginsNew[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "0", "x" }; + ret = OH_Rdb_SetPlugins(confg, pluginsNew, sizeof(pluginsNew) / sizeof(pluginsNew[0]) - 1); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_SetPlugins(confg, pluginsNew, sizeof(pluginsNew) / sizeof(pluginsNew[0])); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_DestroyConfig(confg); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Native_store_test_012 + * @tc.desc: test apis of config interface OH_Rdb_SetCryptoParam. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_012, TestSize.Level1) +{ + OH_Rdb_ConfigV2 *confg = OH_Rdb_CreateConfig(); + EXPECT_NE(confg, nullptr); + + OH_Rdb_CryptoParam *crypto = OH_Rdb_CreateCryptoParam(); + EXPECT_NE(crypto, NULL); + + auto ret = OH_Rdb_SetCryptoParam(nullptr, crypto); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_SetCryptoParam(confg, nullptr); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_SetCryptoParam(confg, crypto); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_DestroyCryptoParam(crypto); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_DestroyConfig(confg); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Native_store_test_013 + * @tc.desc: abnormal test of RdbNdkUtils::GetRdbStoreConfig, when config is null. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_013, TestSize.Level1) +{ + auto [errCode, rdbConfig] = RdbNdkUtils::GetRdbStoreConfig(nullptr); + EXPECT_EQ(errCode, OHOS::NativeRdb::E_INVALID_ARGS); +} + +/** + * @tc.name: RDB_Native_store_test_014 + * @tc.desc: abnormal test of RdbNdkUtils::GetRdbStoreConfig, when securityLevel overlimit. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_014, TestSize.Level1) +{ + OH_Rdb_ConfigV2 *config = OH_Rdb_CreateConfig(); + EXPECT_NE(config, nullptr); + std::shared_ptr autoRelease = std::shared_ptr("RDB_Native_store_test_014", + [config](const char *) { + OH_Rdb_DestroyConfig(config); + }); + EXPECT_EQ(OH_Rdb_SetPersistent(config, true), RDB_OK); + config->securityLevel = -1; + auto [errCode1, _] = RdbNdkUtils::GetRdbStoreConfig(config); + EXPECT_EQ(errCode1, OHOS::NativeRdb::E_INVALID_ARGS); + + config->securityLevel = 10; + auto [errCode2, __] = RdbNdkUtils::GetRdbStoreConfig(config); + EXPECT_EQ(errCode2, OHOS::NativeRdb::E_INVALID_ARGS); +} + +/** + * @tc.name: RDB_Native_store_test_015 + * @tc.desc: abnormal test of RdbNdkUtils::GetRdbStoreConfig, when securityLevel overlimit. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_015, TestSize.Level1) +{ + OH_Rdb_ConfigV2 *config = OH_Rdb_CreateConfig(); + EXPECT_NE(config, nullptr); + std::shared_ptr autoRelease = std::shared_ptr("RDB_Native_store_test_015", + [config](const char *) { + OH_Rdb_DestroyConfig(config); + }); + EXPECT_EQ(OH_Rdb_SetPersistent(config, false), RDB_OK); + config->area = -1; + auto [errCode1, _] = RdbNdkUtils::GetRdbStoreConfig(config); + EXPECT_EQ(errCode1, OHOS::NativeRdb::E_INVALID_ARGS); + + config->area = 10; + auto [errCode2, __] = RdbNdkUtils::GetRdbStoreConfig(config); + EXPECT_EQ(errCode2, OHOS::NativeRdb::E_INVALID_ARGS); +} + +/** + * @tc.name: RDB_Native_store_test_016 + * @tc.desc: abnormal test of RdbNdkUtils::GetRdbStoreConfig, when dbType overlimit. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_016, TestSize.Level1) +{ + OH_Rdb_ConfigV2 *config = OH_Rdb_CreateConfig(); + EXPECT_NE(config, nullptr); + std::shared_ptr autoRelease = std::shared_ptr("RDB_Native_store_test_016", + [config](const char *) { + OH_Rdb_DestroyConfig(config); + }); + EXPECT_EQ(OH_Rdb_SetPersistent(config, true), RDB_OK); + EXPECT_EQ(OH_Rdb_SetSecurityLevel(config, S1), RDB_OK); + config->dbType = -1; + auto [errCode1, _] = RdbNdkUtils::GetRdbStoreConfig(config); + EXPECT_EQ(errCode1, OHOS::NativeRdb::E_INVALID_ARGS); + + config->dbType = 10; + auto [errCode2, __] = RdbNdkUtils::GetRdbStoreConfig(config); + EXPECT_EQ(errCode2, OHOS::NativeRdb::E_INVALID_ARGS); +} + +/** + * @tc.name: RDB_Native_store_test_017 + * @tc.desc: abnormal test of RdbNdkUtils::GetRdbStoreConfig, when token overlimit. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_017, TestSize.Level1) +{ + OH_Rdb_ConfigV2 *config = OH_Rdb_CreateConfig(); + EXPECT_NE(config, nullptr); + std::shared_ptr autoRelease = std::shared_ptr("RDB_Native_store_test_017", + [config](const char *) { + OH_Rdb_DestroyConfig(config); + }); + EXPECT_EQ(OH_Rdb_SetPersistent(config, true), RDB_OK); + EXPECT_EQ(OH_Rdb_SetSecurityLevel(config, S1), RDB_OK); + config->token = -1; + auto [errCode1, _] = RdbNdkUtils::GetRdbStoreConfig(config); + EXPECT_EQ(errCode1, OHOS::NativeRdb::E_INVALID_ARGS); + + config->token = 10; + auto [errCode2, __] = RdbNdkUtils::GetRdbStoreConfig(config); + EXPECT_EQ(errCode2, OHOS::NativeRdb::E_INVALID_ARGS); +} diff --git a/relational_store/test/ndk/unittest/rdb_store_test.cpp b/relational_store/test/ndk/unittest/rdb_store_test.cpp index 274db39035c68d9e5b350ed6f853c6a4a395dfa9..208bf1d9c6a5d6c0ab41fff0586cad716b6c56c7 100644 --- a/relational_store/test/ndk/unittest/rdb_store_test.cpp +++ b/relational_store/test/ndk/unittest/rdb_store_test.cpp @@ -188,9 +188,10 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_001, TestSize.Level1) size_t size = 0; cursor->getSize(cursor, 1, &size); - char data1Value_1[size + 1]; - cursor->getText(cursor, 1, data1Value_1, size + 1); - EXPECT_EQ(strcmp(data1Value_1, "liSi"), 0); + EXPECT_EQ(size, 5); + char data1Value1[size]; + cursor->getText(cursor, 1, data1Value1, size); + EXPECT_EQ(strcmp(data1Value1, "liSi"), 0); int64_t data2Value; cursor->getInt64(cursor, 2, &data2Value); @@ -253,9 +254,10 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_002, TestSize.Level1) size_t size = 0; cursor->getSize(cursor, 1, &size); - char data1Value_1[size + 1]; - cursor->getText(cursor, 1, data1Value_1, size + 1); - EXPECT_EQ(strcmp(data1Value_1, "liSi"), 0); + EXPECT_EQ(size, 5); + char data1Value1[size]; + cursor->getText(cursor, 1, data1Value1, size); + EXPECT_EQ(strcmp(data1Value1, "liSi"), 0); int64_t data2Value; cursor->getInt64(cursor, 2, &data2Value); @@ -270,8 +272,8 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_002, TestSize.Level1) EXPECT_EQ(isNull, true); cursor->getSize(cursor, 5, &size); - char data5Value[size + 1]; - cursor->getText(cursor, 5, data5Value, size + 1); + char data5Value[size]; + cursor->getText(cursor, 5, data5Value, size); EXPECT_EQ(strcmp(data5Value, "ABCDEFGH"), 0); valueObject->destroy(valueObject); @@ -598,9 +600,9 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_0010, TestSize.Level1) size_t size = 0; cursor->getSize(cursor, 1, &size); - char data1Value_1[size + 1]; - cursor->getText(cursor, 1, data1Value_1, size + 1); - EXPECT_EQ(strcmp(data1Value_1, "zhangSan"), 0); + char data1Value1[size]; + cursor->getText(cursor, 1, data1Value1, size); + EXPECT_EQ(strcmp(data1Value1, "zhangSan"), 0); int64_t data2Value; cursor->getInt64(cursor, 2, &data2Value); @@ -679,7 +681,6 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_013, TestSize.Level1) constexpr int TABLE_COUNT = 1; const char *table[TABLE_COUNT]; table[0] = "store_test"; - EXPECT_EQ(table[0], "store_test"); Rdb_ProgressObserver observer; void *context = nullptr; observer.context = &context; @@ -1054,6 +1055,7 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_023, TestSize.Level1) predicates->clear(predicates); errCode = OH_Rdb_UnlockRow(storeTestRdbStore_, predicates); EXPECT_EQ(errCode, OH_Rdb_ErrCode::RDB_E_NO_ROW_IN_QUERY); + cursor->destroy(cursor); predicates->clear(predicates); cursor = OH_Rdb_QueryLockedRow(storeTestRdbStore_, predicates, NULL, 0); @@ -1685,4 +1687,189 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_037, TestSize.Level1) EXPECT_EQ(rowCount, 1); cursor->destroy(cursor); valueBucket->destroy(valueBucket); -} \ No newline at end of file +} + +/** + * @tc.name: RDB_Native_store_test_039 + * @tc.desc: normal testCase for OH_Rdb_InsertWithConflictResolution. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_039, TestSize.Level1) +{ + int errCode = 0; + OH_Rdb_Store *store = storeTestRdbStore_; + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putInt64(valueBucket, "id", 2); + valueBucket->putText(valueBucket, "data1", "liSi"); + valueBucket->putInt64(valueBucket, "data2", 13800); + valueBucket->putReal(valueBucket, "data3", 200.1); + valueBucket->putText(valueBucket, "data5", "ABCDEFGH"); + int64_t rowId = 0; + errCode = OH_Rdb_InsertWithConflictResolution(nullptr, "store_test", valueBucket, RDB_CONFLICT_ROLLBACK, &rowId); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + + errCode = OH_Rdb_InsertWithConflictResolution(store, nullptr, valueBucket, RDB_CONFLICT_ROLLBACK, &rowId); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + + errCode = OH_Rdb_InsertWithConflictResolution(store, "store_test", nullptr, RDB_CONFLICT_ROLLBACK, &rowId); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + + errCode = OH_Rdb_InsertWithConflictResolution(store, "store_test", valueBucket, + static_cast(0), &rowId); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + + errCode = OH_Rdb_InsertWithConflictResolution(store, "store_test", valueBucket, + static_cast(RDB_CONFLICT_REPLACE + 1), &rowId); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + + errCode = OH_Rdb_InsertWithConflictResolution(store, "store_test", valueBucket, RDB_CONFLICT_ROLLBACK, nullptr); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + + errCode = OH_Rdb_InsertWithConflictResolution(store, "store_test", valueBucket, RDB_CONFLICT_ROLLBACK, &rowId); + EXPECT_EQ(errCode, RDB_OK); + EXPECT_EQ(rowId, 2); + + valueBucket->destroy(valueBucket); +} + +/** + * @tc.name: RDB_Native_store_test_040 + * @tc.desc: normal testCase for OH_Rdb_UpdateWithConflictResolution. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_040, TestSize.Level1) +{ + int errCode = 0; + OH_Rdb_Store *store = storeTestRdbStore_; + OH_Predicates *predicates = OH_Rdb_CreatePredicates("store_test"); + EXPECT_NE(predicates, NULL); + + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + EXPECT_NE(valueObject, NULL); + const char *data1Value = "zhangSan"; + valueObject->putText(valueObject, data1Value); + + predicates->equalTo(predicates, "data1", valueObject); + + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + EXPECT_NE(valueBucket, NULL); + valueBucket->putText(valueBucket, "data1", "liSi"); + valueBucket->putInt64(valueBucket, "data2", 13800); + valueBucket->putReal(valueBucket, "data3", 200.1); + valueBucket->putNull(valueBucket, "data5"); + + int64_t chgs = 0; + errCode = OH_Rdb_UpdateWithConflictResolution(nullptr, valueBucket, predicates, RDB_CONFLICT_ROLLBACK, &chgs); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + errCode = OH_Rdb_UpdateWithConflictResolution(store, nullptr, predicates, RDB_CONFLICT_ROLLBACK, &chgs); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + errCode = OH_Rdb_UpdateWithConflictResolution(store, valueBucket, nullptr, RDB_CONFLICT_ROLLBACK, nullptr); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + errCode = OH_Rdb_UpdateWithConflictResolution(store, valueBucket, predicates, RDB_CONFLICT_ROLLBACK, &chgs); + EXPECT_EQ(errCode, RDB_OK); + EXPECT_EQ(chgs, 1); + + predicates->clear(predicates); + OH_Cursor *cursor = OH_Rdb_Query(storeTestRdbStore_, predicates, NULL, 0); + EXPECT_NE(cursor, NULL); + + int rowCount = 0; + cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(rowCount, 1); + + errCode = cursor->goToNextRow(cursor); + EXPECT_EQ(errCode, 0); + + size_t size = 0; + cursor->getSize(cursor, 1, &size); + EXPECT_EQ(size, 5); + char data1Value1[size]; + cursor->getText(cursor, 1, data1Value1, size); + EXPECT_STREQ(data1Value1, "liSi"); + + valueObject->destroy(valueObject); + valueBucket->destroy(valueBucket); + predicates->destroy(predicates); + cursor->destroy(cursor); +} + +static OH_Rdb_ConfigV2 *g_attachConfig = nullptr; +static void CreateAttachDatabase() +{ + g_attachConfig = OH_Rdb_CreateConfig(); + ASSERT_NE(g_attachConfig, nullptr); + OH_Rdb_SetDatabaseDir(g_attachConfig, RDB_TEST_PATH); + OH_Rdb_SetStoreName(g_attachConfig, "rdb_attach_store_test.db"); + OH_Rdb_SetBundleName(g_attachConfig, "com.ohos.example.distributedndk"); + OH_Rdb_SetEncrypted(g_attachConfig, false); + OH_Rdb_SetSecurityLevel(g_attachConfig, OH_Rdb_SecurityLevel::S1); + OH_Rdb_SetArea(g_attachConfig, RDB_SECURITY_AREA_EL1); + + int errCode = 0; + auto tmpStore = OH_Rdb_CreateOrOpen(g_attachConfig, &errCode); + EXPECT_NE(tmpStore, NULL); + OH_Rdb_CloseStore(tmpStore); +} + +static void DeleteAttachDatabase() +{ + EXPECT_EQ(OH_Rdb_DeleteStoreV2(g_attachConfig), 0); + OH_Rdb_DestroyConfig(g_attachConfig); + g_attachConfig = nullptr; +} + +/** + * @tc.name: RDB_Native_store_test_041 + * @tc.desc: normal testCase for OH_Rdb_Attach、OH_Rdb_Detach. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_041, TestSize.Level1) +{ + CreateAttachDatabase(); + + size_t attachedNumber = 0; + auto ret = OH_Rdb_Attach(nullptr, g_attachConfig, "rdb_attach_test", 3, &attachedNumber); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Attach(storeTestRdbStore_, nullptr, "rdb_attach_test", 3, &attachedNumber); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Attach(storeTestRdbStore_, g_attachConfig, nullptr, 3, &attachedNumber); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Attach(storeTestRdbStore_, g_attachConfig, "rdb_attach_test", 0, &attachedNumber); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Attach(storeTestRdbStore_, g_attachConfig, "rdb_attach_test", 3, nullptr); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Attach(storeTestRdbStore_, g_attachConfig, "rdb_attach_test", 3, &attachedNumber); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(attachedNumber, 1); + + ret = OH_Rdb_Detach(nullptr, "rdb_attach_test", 3, &attachedNumber); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Detach(storeTestRdbStore_, nullptr, 3, &attachedNumber); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Detach(storeTestRdbStore_, "rdb_attach_test", 0, &attachedNumber); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Detach(storeTestRdbStore_, "rdb_attach_test", 3, nullptr); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Detach(storeTestRdbStore_, "rdb_attach_test", 3, &attachedNumber); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(attachedNumber, 0); + + DeleteAttachDatabase(); +} + +/** + * @tc.name: RDB_Native_store_test_042 + * @tc.desc: normal testCase for OH_Rdb_SetLocale. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_042, TestSize.Level1) +{ + int errCode = 0; + OH_Rdb_Store *store = storeTestRdbStore_; + errCode = OH_Rdb_SetLocale(nullptr, "zh"); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + errCode = OH_Rdb_SetLocale(store, nullptr); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + errCode = OH_Rdb_SetLocale(store, "zh"); + EXPECT_EQ(errCode, RDB_OK); +} diff --git a/relational_store/test/ndk/unittest/rdb_transaction_capi_test.cpp b/relational_store/test/ndk/unittest/rdb_transaction_capi_test.cpp index bac6a33ae015fb2028fe6dc38611e225057a1e46..227df9130dc66c5e79194b4a58e45d4c5ac318b9 100644 --- a/relational_store/test/ndk/unittest/rdb_transaction_capi_test.cpp +++ b/relational_store/test/ndk/unittest/rdb_transaction_capi_test.cpp @@ -840,4 +840,551 @@ HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_014, TestSize.Level1) ret = OH_VBucket_PutUnlimitedInt(valueBucket, "data2", 1, trueForm, 3); EXPECT_EQ(ret, RDB_OK); valueBucket->destroy(valueBucket); +} + +/** + * @tc.name: RDB_Transaction_capi_test_016 + * @tc.desc: Normal testCase of store transaction for OH_RdbTrans_InsertWithConflictResolution + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_016, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + const char *table = "test"; + int ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + // new row + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putText(valueBucket, "data1", "liSi"); + // init data2 value is 13800 + valueBucket->putInt64(valueBucket, "data2", 13800); + // init data3 value is 200.1 + valueBucket->putReal(valueBucket, "data3", 200.1); + valueBucket->putNull(valueBucket, "data5"); + + // create predicates + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table); + // create match data + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + const char *data1Value = "zhangSan"; + valueObject->putText(valueObject, data1Value); + predicates->equalTo(predicates, "data1", valueObject); + + // update + int64_t changes = -1; + ret = OH_RdbTrans_InsertWithConflictResolution(trans, table, valueBucket, + static_cast(0), &changes); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_RdbTrans_UpdateWithConflictResolution(trans, valueBucket, predicates, RDB_CONFLICT_REPLACE, &changes); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(changes, 1); + + // destroy + valueObject->destroy(valueObject); + valueBucket->destroy(valueBucket); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + + +/** + * @tc.name: RDB_Transaction_capi_test_017 + * @tc.desc: Normal testCase of store transaction for OH_RdbTrans_InsertWithConflictResolution and OH_RdbTrans_Rollback + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_017, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + const char *table = "test"; + int ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putText(valueBucket, "data1", "test_name4"); + // init is data2 is 14800 + valueBucket->putInt64(valueBucket, "data2", 14800); + // init is data2 is 300.1 + valueBucket->putReal(valueBucket, "data3", 300.1); + valueBucket->putText(valueBucket, "data5", "ABCDEFGHI"); + int64_t rowId = -1; + ret = OH_RdbTrans_InsertWithConflictResolution(trans, table, valueBucket, + static_cast(0), &rowId); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_RdbTrans_InsertWithConflictResolution(trans, table, valueBucket, RDB_CONFLICT_ROLLBACK, &rowId); + EXPECT_EQ(ret, RDB_OK); + // expect value is 4 + EXPECT_EQ(rowId, 4); + + ret = OH_RdbTrans_Rollback(trans); + EXPECT_EQ(ret, RDB_OK); + + valueBucket->destroy(valueBucket); + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_024 + * @tc.desc: Normal testCase of store transaction for OH_RdbTrans_InsertWithConflictResolution and OH_RdbTrans_Commit + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_024, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + const char *table = "test"; + int ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + EXPECT_NE(valueBucket, nullptr); + valueBucket->putText(valueBucket, "data1", "test_name4"); + // init is data2 is 14800 + valueBucket->putInt64(valueBucket, "data2", 14800); + // init is data2 is 300.1 + valueBucket->putReal(valueBucket, "data3", 300.1); + valueBucket->putText(valueBucket, "data5", "ABCDEFGHI"); + int64_t rowId = -1; + ret = OH_RdbTrans_InsertWithConflictResolution(trans, table, valueBucket, + static_cast(0), &rowId); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_RdbTrans_InsertWithConflictResolution(trans, table, valueBucket, RDB_CONFLICT_ROLLBACK, &rowId); + EXPECT_EQ(ret, RDB_OK); + // expect value is 4 + EXPECT_EQ(rowId, 4); + + ret = OH_RdbTrans_Commit(trans); + EXPECT_EQ(ret, RDB_OK); + + valueBucket->destroy(valueBucket); + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_025 + * @tc.desc: Abnormal testCase of drop the table before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_025, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + int ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + + const char *sql = "DROP TABLE test"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_E_SQLITE_LOCKED); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Rollback(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_026 + * @tc.desc: Abnormal testCase of drop the table before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_026, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + int ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + + const char *sql = "DROP TABLE test"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_E_SQLITE_LOCKED); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Rollback(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_027 + * @tc.desc: Normal testCase of drop the table after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_027, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + + char createTableSql[] = "CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, data2 INTEGER, " + "data3 FLOAT, data4 BLOB, data5 TEXT);"; + int ret = OH_Rdb_Execute(g_transStore, createTableSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + + cursor->destroy(cursor); + + const char *sql = "DROP TABLE test1"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Commit(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_028 + * @tc.desc: Abnormal testCase of drop the index before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_028, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + + char createIndexSql[] = "CREATE INDEX test_index ON test(data2);"; + int ret = OH_Rdb_Execute(g_transStore, createIndexSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + + const char *sql = "DROP INDEX test_index"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_E_SQLITE_LOCKED); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Rollback(trans); + EXPECT_EQ(ret, RDB_OK); + + char dropIndexSql[] = "DROP INDEX test_index;"; + ret = OH_Rdb_Execute(g_transStore, dropIndexSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_029 + * @tc.desc: Abnormal testCase of drop the index before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_029, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + + char createIndexSql[] = "CREATE INDEX test_index ON test(data2);"; + int ret = OH_Rdb_Execute(g_transStore, createIndexSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + + const char *sql = "DROP INDEX test_index"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_E_SQLITE_LOCKED); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Rollback(trans); + EXPECT_EQ(ret, RDB_OK); + + char dropIndexSql[] = "DROP INDEX test_index;"; + ret = OH_Rdb_Execute(g_transStore, dropIndexSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_030 + * @tc.desc: Abnormal testCase of drop the index after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_030, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + + char createIndexSql[] = "CREATE index test_index ON test(data2);"; + int ret = OH_Rdb_Execute(g_transStore, createIndexSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + + cursor->destroy(cursor); + + const char *sql = "DROP INDEX test_index"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Commit(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_031 + * @tc.desc: Normal testCase of drop the table after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_031, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + + char createTableSql[] = "CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, data2 INTEGER, " + "data3 FLOAT, data4 BLOB, data5 TEXT);"; + int ret = OH_Rdb_Execute(g_transStore, createTableSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test1"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_NE(ret, RDB_OK); + + const char *sql = "DROP TABLE test1"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_OK); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Commit(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_032 + * @tc.desc: Normal testCase of drop the index after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_032, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + + char createIndexSql[] = "CREATE index test_index ON test(data2);"; + int ret = OH_Rdb_Execute(g_transStore, createIndexSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test1"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_NE(ret, RDB_OK); + + const char *sql = "DROP INDEX test_index"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_OK); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Commit(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_033 + * @tc.desc: Abnormal testCase of drop the table after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_033, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + + char createTableSql[] = "CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, data2 INTEGER, " + "data3 FLOAT, data4 BLOB, data5 TEXT);"; + int ret = OH_Rdb_Execute(g_transStore, createTableSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test1"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_NE(ret, RDB_OK); + + const char *sql = "DROP TABLE test"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_OK); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Rollback(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_034 + * @tc.desc: Abnormal testCase of drop the table after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_034, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + + int ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + const char *sql = "DROP TABLE test1"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_OK); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Rollback(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_035 + * @tc.desc: Normal testCase of drop the table before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_035, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + int ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + int rowCount = 0; + ret = cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(ret, RDB_OK); + + for (int i = 0; i < rowCount; i++) { + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + } + + ret = cursor->goToNextRow(cursor); + EXPECT_NE(ret, RDB_OK); + + const char *sql = "DROP TABLE test"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_OK); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Commit(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); } \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 600b26e02c059f6d45cf30e8d2878824dc016684..7b18ae65088680fe077712a5db4115ed3e2d0bcd 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,12 +4,13 @@ project(LDBTest) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_FLAGS "-std=c++1y -fvisibility=default -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} -fno-access-control") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-access-control -D__CJSON_USE_INT64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--no-as-needed -ldl") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=0 -fpermissive -Wa,-mbig-obj") 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 -Wattributes") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") +add_definitions(-D__CJSON_USE_INT64) include_directories(${CMAKE_SOURCE_DIR}/utils_native/base/include) include_directories(${CMAKE_SOURCE_DIR}/utils_native/safwk/native/include) @@ -31,8 +32,18 @@ set(links secure mock app adapter svcFwk service) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) enable_testing() +#************************************************CommonTest start************************************************# +#aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/common/test KvStoreTestSrc) +# +#aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest KvStoreTestSrc) +add_executable(CommonTest ${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/common/test/executor_pool_test.cpp) +target_link_libraries(CommonTest gtest_main gmock_main gcov) +target_include_directories(CommonTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/common) +target_include_directories(CommonTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/interfaces/innerkits/distributeddata/include) +#************************************************CommonTest end************************************************# + #************************************************KVDBTest start************************************************# -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/innerkitsimpl/kvdb/test KvStoreTestSrc) +#aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/innerkitsimpl/kvdb/test KvStoreTestSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/innerkitsimpl/kvdb/test/mock/src KvStoreTestSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/common/test KvStoreTestSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest KvStoreTestSrc) @@ -56,11 +67,13 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/dis aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest DataMgrTestSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/test/mock DataMgrTestSrc) #list(REMOVE_ITEM DataMgrTestSrc "../datamgr_service/services/distributeddataservice/service/test/unittest/cloud/device_manger_adapter_mock.cpp") -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/test DataMgrTestSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/framework/test DataMgrTestSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/adapter/test DataMgrTestSrc) +#aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/test DataMgrTestSrc) +#aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/adapter/test DataMgrTestSrc) add_executable(DataMgrServiceTest ${DataMgrTestSrc} ${mainSrc} ${serviceSrc}) target_link_libraries(DataMgrServiceTest ${links} gtest gtest_main gmock_main gcov relational_store data_share preferences distributeddb data_object kvdb udmf) +#add_executable(DataMgrServiceTest ${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp) +#target_link_libraries(DataMgrServiceTest svcFwk gtest gtest_main) +target_compile_definitions(DataMgrServiceTest PUBLIC -D__CJSON_USE_INT64) target_include_directories(DataMgrServiceTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/adapter/account/src) target_include_directories(DataMgrServiceTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/adapter/communicator/src) target_include_directories(DataMgrServiceTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/backup/include) @@ -128,18 +141,18 @@ target_include_directories(PerferencesTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/. #************************************************PerferencesTest end************************************************# #************************************************DataShareTest start************************************************# -file(GLOB_RECURSE dataShareTestSrc ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/test/native/unittest/*.cpp) -add_executable(DataShareTest ${dataShareTestSrc} ${mainSrc} ${serviceSrc}) -target_link_libraries(DataShareTest ${links} gtest_main gcov data_share service) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/common/include) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/test/native/unittest/mediadatashare_test/include) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/consumer/controller/common) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/consumer/controller/provider/include) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/consumer/controller/service/include) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/consumer/include) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/permission/include) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/provider/include) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/proxy/include) +#file(GLOB_RECURSE dataShareTestSrc ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/test/native/unittest/*.cpp) +#add_executable(DataShareTest ${dataShareTestSrc} ${mainSrc} ${serviceSrc}) +#target_link_libraries(DataShareTest ${links} gtest_main gcov data_share service) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/common/include) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/test/native/unittest/mediadatashare_test/include) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/consumer/controller/common) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/consumer/controller/provider/include) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/consumer/controller/service/include) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/consumer/include) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/permission/include) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/provider/include) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/proxy/include) #************************************************DataShareTest end************************************************# #************************************************DataObjectTest start************************************************# @@ -170,7 +183,7 @@ target_include_directories(UdmfTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../kv_st aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/test/mock CloudTestSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/test/unittest/cloud CloudTestSrc) add_executable(CloudTest ${CloudTestSrc} ${mainSrc} ${serviceSrc}) -target_link_libraries(CloudTest gtest_main gmock_main gcov svcFwk distributeddb kvdb service app) +target_link_libraries(CloudTest gtest_main gmock gcov svcFwk distributeddb kvdb service app) target_include_directories(CloudTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/test) target_include_directories(CloudTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/backup/include) target_include_directories(CloudTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/bootstrap/include) diff --git a/udmf/BUILD.gn b/udmf/BUILD.gn index 5c7a57c8d71280384055650f62e6953fdd5676ba..28eefe11cf1cf828da1649ab8af2ad8a8c90565d 100644 --- a/udmf/BUILD.gn +++ b/udmf/BUILD.gn @@ -17,9 +17,12 @@ group("udmf_packages") { if (is_standard_system) { deps = [ "interfaces/components:udmfcomponents", + "interfaces/innerkits:pixelmap_wrapper", "interfaces/innerkits:udmf_client", "interfaces/innerkits:utd_client", + "interfaces/innerkits/aipcore:aip_core_mgr_static", "interfaces/jskits:intelligence_napi", + "interfaces/jskits:rag_napi", "interfaces/jskits:udmf_data_napi", "interfaces/jskits:unifieddatachannel_napi", "interfaces/jskits:uniformtypedescriptor_napi", @@ -34,6 +37,7 @@ group("unittest") { deps = [ "framework/common/unittest:unittest", "framework/innerkitsimpl/test/unittest:unittest", + "framework/jskitsimpl/test:stage_unittest", "framework/jskitsimpl/unittest:unittest", "framework/ndkimpl/unittest:unittest", ] @@ -42,5 +46,8 @@ group("unittest") { group("fuzztest") { testonly = true - deps = [ "framework/innerkitsimpl/test/fuzztest:fuzztest" ] + deps = [ + "framework/innerkitsimpl/test/fuzztest:fuzztest", + "framework/ndkimpl/udmf_fuzzer:fuzztest", + ] } diff --git a/udmf/CMakeLists.txt b/udmf/CMakeLists.txt index b2e32d4692a1dafdbb0816863c617cf3ffe97be0..0c18d1218abfdc653adba15dec6f8d337b94edb5 100644 --- a/udmf/CMakeLists.txt +++ b/udmf/CMakeLists.txt @@ -18,6 +18,7 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/convert list(REMOVE_ITEM udmf_src "${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/convert/data_params_conversion.cpp") aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/data udmf_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/dynamic udmf_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/service udmf_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/jskitsimpl/common udmf_channel_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/jskitsimpl/data udmf_channel_src) @@ -46,6 +47,7 @@ target_include_directories(udmf PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/in target_include_directories(udmf PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/innerkits/common) target_include_directories(udmf PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/innerkits/convert) target_include_directories(udmf PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/innerkits/data) +target_include_directories(udmf PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/innerkits/dynamic) target_include_directories(udmf PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/client) target_include_directories(udmf PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/framework/ndkimpl/data) diff --git a/udmf/CODEOWNERS b/udmf/CODEOWNERS index df88964efef9d3dce49f19b89c6619b634b1162b..23f246b11a9c82959e32b9107049b97a9cc4a92c 100644 --- a/udmf/CODEOWNERS +++ b/udmf/CODEOWNERS @@ -11,5 +11,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -# any change to framework/service/distributeddata_udmf_ipc_interface_code.h needs to be reviewed by @leonchan5 -framework/service/distributeddata_udmf_ipc_interface_code.h @leonchan5 \ No newline at end of file +# any change to framework/service/distributeddata_udmf_ipc_interface_code.h needs to be reviewed by @leonchan5 liubao6@huawei.com +framework/service/distributeddata_udmf_ipc_interface_code.h @leonchan5 liubao6@huawei.com \ No newline at end of file diff --git a/udmf/adapter/BUILD.gn b/udmf/adapter/BUILD.gn index 8208f369c8650a9e508cc7a78432dca359854ac8..9813e3b2ac9be7a25d92d3af07d976f725993674 100644 --- a/udmf/adapter/BUILD.gn +++ b/udmf/adapter/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2024 Huawei Device Co., Ltd. +# Copyright (c) 2024-2025 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 @@ -14,6 +14,10 @@ import("//build/ohos.gni") import("//foundation/distributeddatamgr/udmf/adapter/arkui_x_udmf.gni") import("//foundation/distributeddatamgr/udmf/udmf.gni") +third_party_skia_path = "${third_party_path}/skia" +if (udmf_feature_upgrade_skia) { + third_party_skia_path = "${third_party_path}/skia/m133" +} config("udmf_client_config") { include_dirs = [ "${udmf_interfaces_path}/innerkits/client", @@ -69,14 +73,18 @@ config("arkui_x_udmf_config") { "${arkui_x_graphic_surface_path}/interfaces/inner_api/common", "${arkui_x_graphic_surface_path}/interfaces/inner_api/surface", "${arkui_x_graphic_surface_path}/interfaces/inner_api/utils", - "${third_party_path}/skia", + "${third_party_skia_path}", + "${udmf_interfaces_path}/innerkits/dynamic", ] - defines = [ "CROSS_PLATFORM" ] + if (udmf_feature_upgrade_skia) { + defines += [ "USE_M133_SKIA" ] + } } arkui_x_public_source = [ "${udmf_framework_path}/innerkitsimpl/client/getter_system.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", "${udmf_framework_path}/innerkitsimpl/common/unified_key.cpp", "${udmf_framework_path}/innerkitsimpl/data/application_defined_record.cpp", "${udmf_framework_path}/innerkitsimpl/data/audio.cpp", @@ -87,7 +95,6 @@ arkui_x_public_source = [ "${udmf_framework_path}/innerkitsimpl/data/image.cpp", "${udmf_framework_path}/innerkitsimpl/data/link.cpp", "${udmf_framework_path}/innerkitsimpl/data/plain_text.cpp", - "${udmf_framework_path}/innerkitsimpl/data/preset_type_descriptors.cpp", "${udmf_framework_path}/innerkitsimpl/data/system_defined_appitem.cpp", "${udmf_framework_path}/innerkitsimpl/data/system_defined_form.cpp", "${udmf_framework_path}/innerkitsimpl/data/system_defined_pixelmap.cpp", @@ -101,13 +108,14 @@ arkui_x_public_source = [ "${udmf_framework_path}/common/graph.cpp", "${udmf_root_path}/adapter/framework/innerkitsimpl/common/unified_meta.cpp", "${udmf_root_path}/adapter/framework/innerkitsimpl/client/utd_client.cpp", + "${udmf_framework_path}/common/base32_utils.cpp", + "${udmf_framework_path}/common/custom_utd_json_parser.cpp", + "${udmf_framework_path}/common/custom_utd_store.cpp", + "${udmf_root_path}/adapter/framework/innerkitsimpl/client/preset_type_descriptors.cpp", ] ohos_source_set("arkui_x_udmf_data") { sources = [ - "${udmf_framework_path}/common/base32_utils.cpp", - "${udmf_framework_path}/common/custom_utd_json_parser.cpp", - "${udmf_framework_path}/common/custom_utd_store.cpp", "${udmf_framework_path}/common/utd_cfgs_checker.cpp", "${udmf_root_path}/adapter/framework/common/udmf_utils.cpp", ] @@ -140,6 +148,7 @@ ohos_source_set("arkui_x_udmf_data_inner") { "${arkui_path}/napi/:ace_napi", "${arkui_x_c_utils_path}/base:utilsbase", "${arkui_x_hilog_path}/interfaces/native/innerkits:libhilog_${target_os}", + "${third_party_path}/cJSON:cjson_static", ] configs = [ @@ -166,10 +175,11 @@ config("arkui_x_udmf_napi_config") { "${arkui_x_graphic_surface_path}/interfaces/inner_api/utils", "${arkui_x_graphic_2d_path}/utils/color_manager/export", "${arkui_x_graphic_2d_path}/rosen/modules/platform/ipc_core", - "${third_party_path}/skia", + "${third_party_skia_path}", ] + defines = [ "CROSS_PLATFORM" ] if (current_os == "ios") { - defines = [ "IOS_PLATFORM" ] + defines += [ "IOS_PLATFORM" ] } } @@ -180,6 +190,9 @@ ohos_source_set("arkui_x_uniformtypedescriptor") { "${udmf_root_path}/adapter/framework/innerkitsimpl/client", ] + if (udmf_feature_upgrade_skia) { + defines = [ "USE_M133_SKIA" ] + } sources = [ "${udmf_framework_path}/jskitsimpl/common/napi_data_utils.cpp", "${udmf_framework_path}/jskitsimpl/common/napi_error_utils.cpp", @@ -253,6 +266,9 @@ ohos_source_set("arkui_x_unifieddatachannel") { "${ability_runtime_cross_platform_path}/interfaces/inner_api/want:want_params_config", ] + if (udmf_feature_upgrade_skia) { + defines = [ "USE_M133_SKIA" ] + } deps = [ ":arkui_x_udmf_data", "${ability_runtime_cross_platform_path}/interfaces/inner_api/want:cross_platform_want_params", @@ -301,7 +317,9 @@ ohos_source_set("arkui_x_udmf_data_napi") { ":arkui_x_udmf_napi_config", "${ability_runtime_cross_platform_path}/interfaces/inner_api/want:want_params_config", ] - + if (udmf_feature_upgrade_skia) { + defines = [ "USE_M133_SKIA" ] + } deps = [ ":arkui_x_udmf_data_inner", "${ability_runtime_cross_platform_path}/frameworks/js/napi/napi_common:napi_common", diff --git a/udmf/adapter/arkui_x_udmf.gni b/udmf/adapter/arkui_x_udmf.gni index e629b3a11a3dee32571716c526525a9e1cf4c94c..7d5f715af607cb349559a456c078a13dca8e88dd 100644 --- a/udmf/adapter/arkui_x_udmf.gni +++ b/udmf/adapter/arkui_x_udmf.gni @@ -11,6 +11,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +declare_args() { + udmf_feature_upgrade_skia = false +} ability_runtime_cross_platform_path = "//foundation/appframework/ability/ability_runtime/cross_platform" diff --git a/udmf/adapter/framework/innerkitsimpl/client/preset_type_descriptors.cpp b/udmf/adapter/framework/innerkitsimpl/client/preset_type_descriptors.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d7007c433516e9b9b683f50481bd460e7db1042b --- /dev/null +++ b/udmf/adapter/framework/innerkitsimpl/client/preset_type_descriptors.cpp @@ -0,0 +1,3346 @@ +/* + * Copyright (c) 2025 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 "preset_type_descriptors.h" + +namespace OHOS { +namespace UDMF { +constexpr const char *REFERENCE_URL = ""; + +PresetTypeDescriptors::PresetTypeDescriptors() +{ + InitDescriptors(); +} + +PresetTypeDescriptors::~PresetTypeDescriptors() +{ +} + +PresetTypeDescriptors &PresetTypeDescriptors::GetInstance() +{ + static PresetTypeDescriptors instance; + return instance; +} + +std::vector &PresetTypeDescriptors::GetPresetTypes() +{ + return typeDescriptors_; +} + +void PresetTypeDescriptors::InitDescriptors() +{ + std::lock_guard lock(mutex_); + typeDescriptors_ = { + {"general.entity", + {}, + {}, + {}, + "Base type for physical hierarchy.", + REFERENCE_URL, + ""}, + {"general.object", + {}, + {}, + {"*/*"}, + "Base type for logical hierarchy.", + REFERENCE_URL, + ""}, + {"general.composite-object", + {"general.object"}, + {}, + {}, + "Base type for mixed object. For example, a PDF file contains both text and special formatting data.", + REFERENCE_URL, + ""}, + {"general.text", + {"general.object"}, + {}, + {"text/*"}, + "Base type for all text.", + REFERENCE_URL, + ""}, + {"general.plain-text", + {"general.text"}, + {".txt", ".text"}, + {"text/plain"}, + "Text of unspecified encoding, with no markup.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_txt"}, + {"general.html", + {"general.text"}, + {".html", ".htm"}, + {"text/html"}, + "HTML text.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_html"}, + {"general.hyperlink", + {"general.text"}, + {}, + {}, + "Hyperlink.", + REFERENCE_URL, + ""}, + {"general.xml", + {"general.text"}, + {".xml"}, + {"text/xml"}, + "XML text.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_xml"}, + {"com.real.smil", + {"general.xml"}, + {".smil"}, + {"application/smil"}, + "Real synchronized multimedia integration language.", + REFERENCE_URL, + ""}, + {"general.source-code", + {"general.text"}, + {}, + {}, + "Generic source code.", + REFERENCE_URL, + ""}, + {"general.script", + {"general.source-code"}, + {}, + {}, + "Base type for scripting language source code.", + REFERENCE_URL, + ""}, + {"general.shell-script", + {"general.script"}, + {".sh", ".command"}, + {"text/x-shellscript"}, + "Shell script.", + REFERENCE_URL, + ""}, + {"general.csh-script", + {"general.shell-script"}, + {".csh"}, + {"text/x-csh"}, + "C-shell script.", + REFERENCE_URL, + ""}, + {"general.perl-script", + {"general.shell-script"}, + {".pl", ".pm"}, + {"text/x-perl-script"}, + "Perl script.", + REFERENCE_URL, + ""}, + {"general.php-script", + {"general.shell-script"}, + {".php", ".php3", ".php4", ".ph3", ".ph4", ".phtml"}, + {"text/x-php-script", "text/php", "application/php"}, + "PHP script.", + REFERENCE_URL, + ""}, + {"general.python-script", + {"general.shell-script"}, + {".py"}, + {"text/x-python-script"}, + "Python script.", + REFERENCE_URL, + ""}, + {"general.ruby-script", + {"general.shell-script"}, + {".rb", ".rbw"}, + {"text/ruby-script"}, + "Ruby script.", + REFERENCE_URL, + ""}, + {"general.type-script", + {"general.source-code"}, + {".ts"}, + {}, + "TypeScript source code.", + REFERENCE_URL, + ""}, + {"general.java-script", + {"general.source-code"}, + {".js", ".jscript", ".javascript"}, + {"text/javascript"}, + "JavaScript source code.", + REFERENCE_URL, + ""}, + {"general.c-header", + {"general.source-code"}, + {".h"}, + {"text/x-chdr"}, + "C header file.", + REFERENCE_URL, + ""}, + {"general.c-source", + {"general.source-code"}, + {".c"}, + {"text/x-csrc"}, + "C source code.", + REFERENCE_URL, + ""}, + {"general.c-plus-plus-header", + {"general.source-code"}, + {".hpp", ".h++", ".hxx", ".hh"}, + {"text/x-c++hdr"}, + "C++ header file.", + REFERENCE_URL, + ""}, + {"general.c-plus-plus-source", + {"general.source-code"}, + {".cp", ".cpp", ".c++", ".cc", ".cxx"}, + {"text/x-c++src"}, + "C++ source code.", + REFERENCE_URL, + ""}, + {"general.java-source", + {"general.source-code"}, + {".java", ".jav"}, + {"text/x-java"}, + "Java source code.", + REFERENCE_URL, + ""}, + {"general.markdown", + {"general.text"}, + {".md", ".markdown", ".markdn", ".mdown"}, + {"text/markdown"}, + "Markdown format.", + REFERENCE_URL, + ""}, + {"general.ebook", + {"general.composite-object"}, + {}, + {}, + "Base type for ebook.", + REFERENCE_URL, + ""}, + {"general.epub", + {"general.ebook"}, + {".epub"}, + {"application/epub+zip"}, + "Electronic publication (EPUB) format.", + REFERENCE_URL, + ""}, + {"com.amazon.azw", + {"general.ebook"}, + {".azw"}, + {"application/vnd.amazon.ebook"}, + "AZW ebook.", + REFERENCE_URL, + ""}, + {"com.amazon.azw3", + {"general.ebook"}, + {".azw3"}, + {"application/vnd.amazon.mobi8-ebook", "application/x-mobi8-ebook"}, + "AZW3 ebook.", + REFERENCE_URL, + ""}, + {"com.amazon.kfx", + {"general.ebook"}, + {".kfx"}, + {}, + "KFX ebook.", + REFERENCE_URL, + ""}, + {"com.amazon.mobi", + {"general.ebook"}, + {".mobi"}, + {"application/x-mobipocket-ebook"}, + "MOBI ebook.", + REFERENCE_URL, + ""}, + {"general.media", + {"general.object"}, + {}, + {}, + "Base type for media.", + REFERENCE_URL, + ""}, + {"general.image", + {"general.media"}, + {}, + {"image/*"}, + "Base type for images.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"general.jpeg", + {"general.image"}, + {".jpg", ".jpeg", ".jpe"}, + {"image/jpeg"}, + "JPEG image.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"general.png", + {"general.image"}, + {".png"}, + {"image/png"}, + "PNG image.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"general.raw-image", + {"general.image"}, + {}, + {}, + "Base type for digital camera raw image formats.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"general.tiff", + {"general.image"}, + {".tif", ".tiff"}, + {"image/tiff"}, + "TIFF image.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"com.microsoft.bmp", + {"general.image"}, + {".bmp", ".bm"}, + {"image/bmp", "image/x-ms-bmp"}, + "Windows bitmap image.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"com.microsoft.ico", + {"general.image"}, + {".ico"}, + {"image/ico", "image/x-icon"}, + "Windows icon image.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"com.adobe.photoshop-image", + {"general.image"}, + {".psd"}, + {"image/x-photoshop", "image/photoshop", "image/psd", "application/photoshop"}, + "Adobe Photoshop document.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"com.adobe.illustrator.ai-image", + {"general.image"}, + {".ai"}, + {}, + "Adobe Illustrator document.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"general.fax", + {"general.image"}, + {}, + {}, + "Base type for fax images.", + REFERENCE_URL, + ""}, + {"com.j2.jfx-fax", + {"general.fax"}, + {".jfx"}, + {}, + "J2 fax.", + REFERENCE_URL, + ""}, + {"com.js.efx-fax", + {"general.fax"}, + {".efx"}, + {"image/efax"}, + "eFax fax.", + REFERENCE_URL, + ""}, + {"general.xbitmap-image", + {"general.image"}, + {".xbm"}, + {"image/x-xbitmap", "image/x-xbm"}, + "X bitmap image.", + REFERENCE_URL, + ""}, + {"com.truevision.tga-image", + {"general.image"}, + {".tga"}, + {"image/targa", "image/tga", "application/tga"}, + "TGA image.", + REFERENCE_URL, + ""}, + {"com.sgi.sgi-image", + {"general.image"}, + {".sgi"}, + {"image/sgi"}, + "Silicon Graphics image.", + REFERENCE_URL, + ""}, + {"com.ilm.openexr-image", + {"general.image"}, + {".exr"}, + {}, + "OpenEXR image.", + REFERENCE_URL, + ""}, + {"com.kodak.flashpix.image", + {"general.image"}, + {".fpx"}, + {"image/fpx", "application/vnd.fpx"}, + "FlashPix image.", + REFERENCE_URL, + ""}, + {"com.microsoft.word.doc", + {"general.composite-object"}, + {".doc"}, + {"application/msword"}, + "Microsoft Word data.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_doc"}, + {"com.microsoft.excel.xls", + {"general.composite-object"}, + {".xls"}, + {"application/vnd.ms-excel"}, + "Microsoft Excel data.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_xls"}, + {"com.microsoft.powerpoint.ppt", + {"general.composite-object"}, + {".ppt"}, + {"application/vnd.ms-powerpoint"}, + "Microsoft PowerPoint presentation.", + REFERENCE_URL, + ""}, + {"com.adobe.pdf", + {"general.composite-object"}, + {".pdf"}, + {"application/pdf"}, + "PDF data.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_pdf"}, + {"com.adobe.postscript", + {"general.composite-object"}, + {".ps"}, + {"application/postscript"}, + "PostScript data.", + REFERENCE_URL, + ""}, + {"com.adobe.encapsulated-postscript", + {"com.adobe.postscript"}, + {".eps"}, + {}, + "Encapsulated PostScript.", + REFERENCE_URL, + ""}, + {"general.video", + {"general.media"}, + {}, + {"video/*"}, + "Base type for video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"general.avi", + {"general.video"}, + {".avi", ".vfw"}, + {"video/avi", "video/msvideo", "video/x-msvideo"}, + "AVI video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"general.mpeg", + {"general.video"}, + {".mpg", ".mpeg", ".m75", ".m15", ".mpe"}, + {"video/mpg", "video/mpeg", "video/x-mpg", "video/x-mpeg"}, + "MPEG-1 or MPEG-2 video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"general.mpeg-4", + {"general.video"}, + {".mp4", ".mp4v", ".mpeg4"}, + {"video/mp4", "video/mp4v"}, + "MPEG-4 video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"general.3gpp", + {"general.video"}, + {".3gp", ".3gpp"}, + {"video/3gpp"}, + "3GPP video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"general.3gpp2", + {"general.video"}, + {".3g2", ".3gp2", ".3gpp2"}, + {"video/3gpp2"}, + "3GPP2 video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.microsoft.windows-media-wm", + {"general.video", "com.microsoft.advanced-systems-format"}, + {".wm"}, + {"video/x-ms-wm"}, + "Windows WM video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.microsoft.windows-media-wmv", + {"general.video", "com.microsoft.advanced-systems-format"}, + {".wmv"}, + {"video/x-ms-wmv"}, + "Windows WMV video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.microsoft.windows-media-wmp", + {"general.video", "com.microsoft.advanced-systems-format"}, + {".wmp"}, + {"video/x-ms-wmp"}, + "Windows WMP video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.microsoft.windows-media-wvx", + {"general.video", "com.microsoft.advanced-systems-format"}, + {".wvx"}, + {"video/x-ms-wvx"}, + "Windows WVX video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.microsoft.windows-media-wmx", + {"general.video", "com.microsoft.advanced-systems-format"}, + {".wmx"}, + {"video/x-ms-wmx"}, + "Windows WMX video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.real.realmedia", + {"general.video"}, + {".rm"}, + {"application/vnd.rn-realmedia"}, + "RealMedia.", + REFERENCE_URL, + ""}, + {"general.audio", + {"general.media"}, + {}, + {"audio/*"}, + "Base type for audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.aac", + {"general.audio"}, + {".aac"}, + {"audio/aac"}, + "AAC audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.aiff", + {"general.audio"}, + {".aiff"}, + {"audio/aiff"}, + "AIFF audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.alac", + {"general.audio"}, + {".alac"}, + {"audio/alac"}, + "ALAC audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.flac", + {"general.audio"}, + {".flac"}, + {"audio/flac"}, + "FLAC audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_flac"}, + {"general.mp3", + {"general.audio"}, + {".mp3"}, + {"audio/mp3"}, + "MPEG-3 audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_mp3"}, + {"general.ogg", + {"general.audio"}, + {".ogg"}, + {"audio/ogg"}, + "OGG audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.pcm", + {"general.audio"}, + {".pcm"}, + {"audio/pcm"}, + "PCM audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"com.microsoft.advanced-systems-format", + {"general.media"}, + {".asf"}, + {"video/x-ms-asf", "application/vnd.ms-asf"}, + "Advanced Systems format", + REFERENCE_URL, + ""}, + {"com.microsoft.advanced-stream-redirector", + {"general.video"}, + {".asx"}, + {"video/x-ms-asf"}, + "Advanced stream redirector", + REFERENCE_URL, + ""}, + {"com.microsoft.windows-media-wma", + {"general.audio", "com.microsoft.advanced-systems-format"}, + {".wma"}, + {"audio/x-ms-wma"}, + "Windows WMA audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_wma"}, + {"com.microsoft.waveform-audio", + {"general.audio", "com.microsoft.advanced-systems-format"}, + {".wav", ".wave"}, + {"audio/wav", "audio/wave", "audio/x-wav"}, + "Waveform audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_wav"}, + {"com.microsoft.windows-media-wax", + {"general.audio", "com.microsoft.advanced-systems-format"}, + {".wax"}, + {"audio/x-ms-wax"}, + "Windows WAX audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.au-audio", + {"general.audio"}, + {".au", ".snd"}, + {"audio/basic", "audio/au", "audio/snd"}, + "Au file format.", + REFERENCE_URL, + ""}, + {"general.aifc-audio", + {"general.audio"}, + {".aifc", ".aif", ".aiff"}, + {"audio/x-aiff"}, + "Audio Interchange File Format.", + REFERENCE_URL, + ""}, + {"com.digidesign.sd2-audio", + {"general.audio"}, + {".sd2"}, + {"audio/x-sd2"}, + "Digidesign Sound Designer II audio.", + REFERENCE_URL, + ""}, + {"com.real.realaudio", + {"general.audio"}, + {".ram", ".ra"}, + {"audio/vnd.rn-realaudio", "audio/x-pn-realaudio"}, + "RealMedia audio.", + REFERENCE_URL, + ""}, + {"general.file", + {"general.entity"}, + {}, + {}, + "Base type for file.", + REFERENCE_URL, + ""}, + {"general.directory", + {"general.entity"}, + {}, + {}, + "Base type for directory.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_folder"}, + {"general.folder", + {"general.directory"}, + {}, + {}, + "Base type for folder.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_folder"}, + {"general.symlink", + {"general.entity"}, + {}, + {}, + "Base type for symlink.", + REFERENCE_URL, + ""}, + {"general.archive", + {"general.object"}, + {}, + {}, + "Base type for an archive of files and directories.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"general.bz2-archive", + {"general.archive"}, + {".bz2", ".bzip2"}, + {"application/x-bzip2"}, + "BZip2 archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"general.disk-image", + {"general.archive"}, + {}, + {}, + "Base type for items mountable as a volume.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"general.tar-archive", + {"general.archive"}, + {".tar"}, + {"application/x-tar", "application/tar"}, + "Tar archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"general.zip-archive", + {"general.archive"}, + {".zip"}, + {"application/zip"}, + "Zip archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_zip"}, + {"com.sun.java-archive", + {"general.archive", "general.executable"}, + {".jar"}, + {"application/java-archive"}, + "Java archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"org.gnu.gnu-tar-archive", + {"general.archive"}, + {".gtar"}, + {"application/x-gtar"}, + "GNU archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"org.gnu.gnu-zip-archive", + {"general.archive"}, + {".gz", ".gzip"}, + {"application/x-gzip", "application/gzip"}, + "Gzip archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"org.gnu.gnu-zip-tar-archive", + {"general.archive"}, + {".tgz"}, + {"application/x-gtar"}, + "Gzip tar archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"org.openxmlformats.openxml", + {"general.archive"}, + {}, + {}, + "Office Open XML.", + REFERENCE_URL, + ""}, + {"org.openxmlformats.wordprocessingml.document", + {"general.composite-object", "org.openxmlformats.openxml"}, + {".docx"}, + {"application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, + "Office Open XML Document.", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.sheet", + {"general.composite-object", "org.openxmlformats.openxml"}, + {".xlsx"}, + {"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, + "Office Open XML Workbook.", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.presentation", + {"general.composite-object", "org.openxmlformats.openxml"}, + {".pptx"}, + {"application/vnd.openxmlformats-officedocument.presentationml.presentation"}, + "Office Open XML Presentation.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument", + {"general.archive"}, + {}, + {}, + "Open Document Format for Office Applications.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument.text", + {"general.composite-object", "org.oasis.opendocument"}, + {".odt", ".fodt"}, + {"application/vnd.oasis.opendocument.text"}, + "OpenDocument Text.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument.spreadsheet", + {"general.composite-object", "org.oasis.opendocument"}, + {".ods", ".fods"}, + {"application/vnd.oasis.opendocument.spreadsheet"}, + "OpenDocument Spreadsheet.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument.presentation", + {"general.composite-object", "org.oasis.opendocument"}, + {".odp", ".fodp"}, + {"application/vnd.oasis.opendocument.presentation"}, + "OpenDocument Presentation.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument.graphics", + {"general.composite-object", "org.oasis.opendocument"}, + {".odg", ".fodg"}, + {"application/vnd.oasis.opendocument.graphics"}, + "OpenDocument Graphics.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument.formula", + {"org.oasis.opendocument"}, + {".odf"}, + {"application/vnd.oasis.opendocument.formula"}, + "OpenDocument Formulat.", + REFERENCE_URL, + ""}, + {"com.allume.stuffit-archive", + {"general.archive"}, + {".sit", ".sitx"}, + {"application/x-stuffit", "application/x-sit", "application/stuffit"}, + "Stuffit archive.", + REFERENCE_URL, + ""}, + {"general.calendar", + {"general.text"}, + {}, + {"text/calendar"}, + "Base type for scheduled events.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_calendar"}, + {"general.vcs", + {"general.calendar"}, + {".vcs"}, + {"text/calendar"}, + "vCalendar type.", + REFERENCE_URL, + ""}, + {"general.ics", + {"general.calendar"}, + {".ics"}, + {"text/calendar"}, + "iCalendar type.", + REFERENCE_URL, + ""}, + {"general.contact", + {"general.object"}, + {}, + {}, + "Base type for contact information.", + REFERENCE_URL, + ""}, + {"general.database", + {"general.object"}, + {}, + {}, + "Base type for databases.", + REFERENCE_URL, + ""}, + {"general.message", + {"general.object"}, + {}, + {}, + "Base type for messages.", + REFERENCE_URL, + ""}, + {"general.executable", + {"general.object"}, + {}, + {}, + "Base type for executable data.", + REFERENCE_URL, + ""}, + {"com.microsoft.portable-executable", + {"general.executable"}, + {".exe", ".dll"}, + {"application/vnd.microsoft.portable-executable"}, + "Microsoft Windows application.", + REFERENCE_URL, + ""}, + {"com.sun.java-class", + {"general.executable"}, + {".class"}, + {}, + "Java class.", + REFERENCE_URL, + ""}, + {"general.vcard", + {"general.object"}, + {".vcf", ".vcard"}, + {"text/vcard", "text/x-vcard"}, + "Base type for electronic business card.", + REFERENCE_URL, + ""}, + {"general.navigation", + {"general.object"}, + {}, + {}, + "Base type for navigation.", + REFERENCE_URL, + ""}, + {"general.location", + {"general.navigation"}, + {}, + {}, + "Navigation location.", + REFERENCE_URL, + ""}, + {"general.font", + {"general.object"}, + {}, + {}, + "Base type for fonts.", + REFERENCE_URL, + ""}, + {"general.truetype-font", + {"general.font"}, + {".ttf"}, + {"font/ttf"}, + "TrueType font.", + REFERENCE_URL, + ""}, + {"general.truetype-collection-font", + {"general.font"}, + {".ttc"}, + {"font/collection"}, + "TrueType collection font.", + REFERENCE_URL, + ""}, + {"general.opentype-font", + {"general.font"}, + {".otf"}, + {"font/otf"}, + "OpenType font.", + REFERENCE_URL, + ""}, + {"com.adobe.postscript-font", + {"general.font"}, + {}, + {}, + "PostScript font.", + REFERENCE_URL, + ""}, + {"openharmony.form", + {"general.object"}, + {}, + {}, + "OpenHarmony system defined form.", + REFERENCE_URL, + ""}, + {"openharmony.app-item", + {"general.object"}, + {}, + {}, + "OpenHarmony system defined app item.", + REFERENCE_URL, + ""}, + {"openharmony.pixel-map", + {"general.image"}, + {}, + {}, + "OpenHarmony system defined pixel map.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"openharmony.atomic-service", + {"general.object"}, + {}, + {}, + "OpenHarmony system defined atomic service.", + REFERENCE_URL, + ""}, + {"openharmony.package", + {"general.directory"}, + {}, + {}, + "OpenHarmony system defined package (that is, a directory presented to the user as a file).", + REFERENCE_URL, + ""}, + {"openharmony.hap", + {"openharmony.package"}, + {".hap"}, + {}, + "OpenHarmony system defined ability package.", + REFERENCE_URL, + ""}, + {"openharmony.hdoc", + {"general.composite-object"}, + {".hdoc"}, + {}, + "OpenHarmony system AppNotepad data format.", + REFERENCE_URL, + ""}, + {"openharmony.hinote", + {"general.composite-object"}, + {".hinote"}, + {}, + "OpenHarmony system Notes data format.", + REFERENCE_URL, + ""}, + {"openharmony.styled-string", + {"general.composite-object"}, + {}, + {}, + "OpenHarmony system defined styled string.", + REFERENCE_URL, + ""}, + {"openharmony.want", + {"general.object"}, + {}, + {}, + "OpenHarmony system defined Want.", + REFERENCE_URL, + ""}, + {"openharmony.moving-photo", + {"general.media"}, + {}, + {}, + "OpenHarmony system defined moving photo.", + REFERENCE_URL, + ""}, + {"macos.dmg", + {"general.disk-image"}, + {".dmg"}, + {"application/x-apple-diskimage"}, + "Apple Disk Image", + REFERENCE_URL, + ""}, + {"debian.deb", + {"general.archive"}, + {".deb", ".udeb"}, + {"application/x-debian-package", "application/vnd.debian.binary-package"}, + "OpenHarmony system defined Want.", + REFERENCE_URL, + ""}, + {"general.ofd", + {"general.composite-object"}, + {".ofd"}, + {}, + "Open fixed-layout document, a national standard for format documents", + REFERENCE_URL, + ""}, + {"general.opg", + {"general.archive"}, + {".opg"}, + {}, + "OPG archive", + REFERENCE_URL, + ""}, + {"general.tex", + {"general.source-code"}, + {}, + {}, + "Base type for TeX source code", + REFERENCE_URL, + ""}, + {"general.css", + {"general.script"}, + {".css"}, + {"text/css"}, + "Cascading style sheets", + REFERENCE_URL, + ""}, + {"general.vob", + {"general.video"}, + {".vob"}, + {"video/mpeg", "video/x-ms-vob"}, + "", + REFERENCE_URL, + ""}, + {"general.dif-video", + {"general.video"}, + {".dif"}, + {"video/dv"}, + "Digital interface format", + REFERENCE_URL, + ""}, + {"general.dv-video", + {"general.video"}, + {".dv"}, + {"video/dv"}, + "DV video", + REFERENCE_URL, + ""}, + {"general.flc-animation", + {"general.video"}, + {".fli", ".flc"}, + {"video/fli", "video/flc"}, + "FLIC file format", + REFERENCE_URL, + ""}, + {"general.mng", + {"general.video"}, + {".mng"}, + {"video/x-mng"}, + "Multiple-image network graphics", + REFERENCE_URL, + ""}, + {"general.mpegurl-video", + {"general.video"}, + {".mxu", ".m4u"}, + {"video/vnd.mpegurl"}, + "Video playlist", + REFERENCE_URL, + ""}, + {"general.ts", + {"general.video"}, + {".ts"}, + {"video/mp2ts", "video/mp2t"}, + "MPEG transport stream", + REFERENCE_URL, + ""}, + {"general.amr", + {"general.audio"}, + {".amr"}, + {"audio/amr"}, + "The adaptive multi-rate audio codecs", + REFERENCE_URL, + ""}, + {"general.amr-wb", + {"general.audio"}, + {".awb"}, + {"audio/amr-wb"}, + "Adaptive multi-rate wideband", + REFERENCE_URL, + ""}, + {"general.gsm", + {"general.audio"}, + {".gsm"}, + {"audio/x-gsm", "audio/gsm"}, + "Global system form mobile audio format", + REFERENCE_URL, + ""}, + {"general.imy", + {"general.audio"}, + {".imy"}, + {"audio/imelody"}, + "Non-polyphonic ringtone exchange object format", + REFERENCE_URL, + ""}, + {"general.kar", + {"general.audio"}, + {".kar"}, + {"audio/midi"}, + "Karaoke MIDI file format", + REFERENCE_URL, + ""}, + {"general.mpegurl-audio", + {"general.audio"}, + {".m3u"}, + {"audio/mpegurl", "audio/x-mpegurl"}, + "Audio playlist", + REFERENCE_URL, + ""}, + {"general.mpeg-4-audio", + {"general.audio"}, + {".m4a", ".m4b"}, + {"audio/mpeg"}, + "Audio-only MPEG-4 file", + REFERENCE_URL, + ""}, + {"general.midi-audio", + {"general.audio"}, + {".mid", ".midi"}, + {"audio/midi"}, + "MIDI audio", + REFERENCE_URL, + ""}, + {"general.mp2", + {"general.audio"}, + {".mp2"}, + {"audio/mpeg"}, + "MPEG-1 audio layer II or MPEG-2 audio layer II", + REFERENCE_URL, + ""}, + {"general.mpeg-audio", + {"general.audio"}, + {".mpga"}, + {"audio/mpeg"}, + "MPEG audio format", + REFERENCE_URL, + ""}, + {"general.mxmf", + {"general.audio"}, + {".mxmf"}, + {"audio/mobile-xmf"}, + "Mobile XMF audio format", + REFERENCE_URL, + ""}, + {"general.ota", + {"general.audio"}, + {".ota"}, + {"audio/midi"}, + "OTA ringtone file", + REFERENCE_URL, + ""}, + {"general.pls", + {"general.audio"}, + {".pls"}, + {"audio/x-scpls"}, + "Multimedia playlist format", + REFERENCE_URL, + ""}, + {"general.rtttl", + {"general.audio"}, + {".rtttl"}, + {"audio/midi"}, + "Ring tone transfer language file", + REFERENCE_URL, + ""}, + {"general.psid", + {"general.audio"}, + {".sid", ".psid"}, + {"audio/prs.sid"}, + "SID audio", + REFERENCE_URL, + ""}, + {"general.ulaw-audio", + {"general.audio"}, + {".au", ".ulw", ".snd"}, + {"audio/basic", "audio/au", "audio/snd"}, + "uLaw audio", + REFERENCE_URL, + ""}, + {"general.xmf", + {"general.audio"}, + {".xmf"}, + {"audio/midi"}, + "Extensible music file", + REFERENCE_URL, + ""}, + {"general.gif", + {"general.image"}, + {".gif"}, + {"image/gif"}, + "GIF image", + REFERENCE_URL, + ""}, + {"general.djvu-image", + {"general.image"}, + {".djv", ".djvu"}, + {"image/vnd.djvu"}, + "Djvu image", + REFERENCE_URL, + ""}, + {"general.jng-image", + {"general.image"}, + {".jng"}, + {"image/x-jng"}, + "JPEG network graphic", + REFERENCE_URL, + ""}, + {"general.pcx-image", + {"general.image"}, + {".pcx"}, + {"image/vnd.zbrush.pcx"}, + "Paintbrush bitmap image", + REFERENCE_URL, + ""}, + {"general.pbm-image", + {"general.image"}, + {".pbm"}, + {"image/x-portable-bitmap"}, + "Portable bitmap image", + REFERENCE_URL, + ""}, + {"general.pgm-image", + {"general.image"}, + {".pgm"}, + {"image/x-portable-graymap"}, + "Portable gray map image", + REFERENCE_URL, + ""}, + {"general.pnm-image", + {"general.image"}, + {".pnm"}, + {"image/x-portable-anymap"}, + "Portable any map image file", + REFERENCE_URL, + ""}, + {"general.ppm-image", + {"general.image"}, + {".ppm"}, + {"image/x-portable-pixmap"}, + "Portable pixmap image", + REFERENCE_URL, + ""}, + {"general.rgb-image", + {"general.image"}, + {".rgb"}, + {"image/x-rgb"}, + "RGB bitmap", + REFERENCE_URL, + ""}, + {"general.svg-image", + {"general.image"}, + {".svg", ".svgz"}, + {"image/svg+xml"}, + "Scalable vector graphic", + REFERENCE_URL, + ""}, + {"general.wbmp-image", + {"general.image"}, + {".wbmp"}, + {"image/vnd.wap.wbmp"}, + "Wireless bitmap image", + REFERENCE_URL, + ""}, + {"general.xpixmap-image", + {"general.image"}, + {".xpm"}, + {"image/x-xpixmap"}, + "X11 pixmap graphic", + REFERENCE_URL, + ""}, + {"general.xwindowdump-image", + {"general.image"}, + {".xwd"}, + {"image/x-xwindowdump"}, + "X windows dump image", + REFERENCE_URL, + ""}, + {"general.heif", + {"general.image"}, + {".heif", ".heifs", ".hif"}, + {"image/heif"}, + "High efficiency image format", + REFERENCE_URL, + ""}, + {"general.heic", + {"general.image"}, + {".heic", ".heics"}, + {"image/heic"}, + "High efficiency image format", + REFERENCE_URL, + ""}, + {"general.virtual-cd", + {"general.disk-image"}, + {".vcd"}, + {"application/x-cdlink"}, + "Virtual CD", + REFERENCE_URL, + ""}, + {"general.boo-source", + {"general.source-code"}, + {".boo"}, + {"text/x-boo"}, + "Boo source code", + REFERENCE_URL, + ""}, + {"general.d-source", + {"general.source-code"}, + {".d"}, + {"text/x-dsrc"}, + "D source code file", + REFERENCE_URL, + ""}, + {"general.html-component", + {"general.source-code"}, + {".htc"}, + {"text/x-component"}, + "HTML component", + REFERENCE_URL, + ""}, + {"general.pascal-source", + {"general.source-code"}, + {".p", ".pas"}, + {"text/x-pascal"}, + "Pascal source code", + REFERENCE_URL, + ""}, + {"general.haskell-script", + {"general.script"}, + {".hs"}, + {"text/x-haskell"}, + "Haskell script", + REFERENCE_URL, + ""}, + {"general.literate-haskell-script", + {"general.script"}, + {".lhs"}, + {"text/x-literate-haskell"}, + "Literate haskell script", + REFERENCE_URL, + ""}, + {"general.tcl-script", + {"general.script"}, + {".tcl"}, + {"text/x-tcl"}, + "Tcl script", + REFERENCE_URL, + ""}, + {"general.asc-text", + {"general.text"}, + {".asc"}, + {"text/plain"}, + "ASCII text file", + REFERENCE_URL, + ""}, + {"general.portable-object", + {"general.text"}, + {".po"}, + {"text/plain"}, + "Portable object", + REFERENCE_URL, + ""}, + {"general.rich-text", + {"general.text"}, + {".rtf", ".rtx"}, + {"text/rtf", "text/richtext"}, + "Rich text format file", + REFERENCE_URL, + ""}, + {"general.delimited-values-text", + {"general.text"}, + {}, + {}, + "Base type for delimited-values text", + REFERENCE_URL, + ""}, + {"general.comma-separated-values-text", + {"general.delimited-values-text"}, + {".csv"}, + {"text/csv"}, + "Comma-separated values file", + REFERENCE_URL, + ""}, + {"general.diff", + {"general.text"}, + {".diff"}, + {"text/plain"}, + "Patch file", + REFERENCE_URL, + ""}, + {"general.setext", + {"general.text"}, + {".etx"}, + {"text/x-setext"}, + "Structure enhanced Text", + REFERENCE_URL, + ""}, + {"general.gcd", + {"general.text"}, + {".gcd"}, + {"text/x-pcs-gcd"}, + "General content descriptor", + REFERENCE_URL, + ""}, + {"general.tab-separated-values-text", + {"general.delimited-values-text"}, + {".tsv"}, + {"text/tab-separated-values"}, + "Tab-Separated values file", + REFERENCE_URL, + ""}, + {"general.p7r", + {"general.text"}, + {".p7r"}, + {"application/x-pkcs7-certreqresp"}, + "Certificate request response file", + REFERENCE_URL, + ""}, + {"general.pem", + {"general.text"}, + {".pem"}, + {"application/x-pem-file"}, + "Privacy enhanced mail certificate", + REFERENCE_URL, + ""}, + {"general.chess-pgn", + {"general.plain-text"}, + {".pgn"}, + {"application/x-chess-pgn", "application/vnd.chess-pgn"}, + "Portable game notation file", + REFERENCE_URL, + ""}, + {"general.lha-archive", + {"general.archive"}, + {".lha"}, + {"application/x-lha"}, + "LHARC compressed archive", + REFERENCE_URL, + ""}, + {"general.lzh-archive", + {"general.archive"}, + {".lzh"}, + {"application/x-lzh"}, + "LZH compressed file", + REFERENCE_URL, + ""}, + {"general.lzx-archive", + {"general.archive"}, + {".lzx"}, + {"application/x-lzx"}, + "LZX compressed archive", + REFERENCE_URL, + ""}, + {"general.taz-archive", + {"general.tar-archive"}, + {".taz", ".tar.z", ".tz"}, + {"application/x-gtar"}, + "Tar zipped file", + REFERENCE_URL, + ""}, + {"general.shar-archive", + {"general.archive"}, + {".shar"}, + {"application/x-shar"}, + "Unix Shar archive", + REFERENCE_URL, + ""}, + {"general.cpio-archive", + {"general.archive"}, + {".cpio"}, + {"application/x-cpio"}, + "Unix CPIO archive", + REFERENCE_URL, + ""}, + {"general.web-archive", + {"general.archive"}, + {".mht", ".mhtml"}, + {"application/x-mimearchive"}, + "MHTML web archive", + REFERENCE_URL, + ""}, + {"general.ustar", + {"general.archive"}, + {".ustar"}, + {"application/x-ustar"}, + "Uniform standard tape archive format", + REFERENCE_URL, + ""}, + {"general.mathml", + {"general.xml"}, + {".mml"}, + {"text/mathml", "application/mathml+xml"}, + "Mathematical markup language file", + REFERENCE_URL, + ""}, + {"general.xhtml", + {"general.xml"}, + {".xhtml"}, + {"application/xhtml+xml"}, + "XHTML", + REFERENCE_URL, + ""}, + {"general.rss", + {"general.xml"}, + {".rss"}, + {"application/rss+xml"}, + "Rich site summary", + REFERENCE_URL, + ""}, + {"general.rdf", + {"general.xml"}, + {".rdf"}, + {"application/rdf+xml"}, + "Resource description framework file", + REFERENCE_URL, + ""}, + {"general.cad", + {"general.object"}, + {}, + {}, + "Base type for computer-aided design", + REFERENCE_URL, + ""}, + {"general.iges", + {"general.cad"}, + {".iges", ".igs"}, + {"model/iges"}, + "IGES drawing", + REFERENCE_URL, + ""}, + {"general.octet-stream", + {"general.object"}, + {}, + {"application/octet-stream"}, + "Arbitrary binary data", + REFERENCE_URL, + ""}, + {"general.iso", + {"general.disk-image"}, + {".iso"}, + {"application/x-iso9660-image"}, + "Disc image file", + REFERENCE_URL, + ""}, + {"general.mesh-model", + {"general.object"}, + {".msh", ".mesh", ".silo"}, + {"model/mesh"}, + "3D mesh model", + REFERENCE_URL, + ""}, + {"general.certificate", + {"general.object"}, + {}, + {}, + "Base type for security certificate", + REFERENCE_URL, + ""}, + {"general.c-object", + {"general.executable"}, + {".o"}, + {"application/x-object"}, + "Compiled C object file", + REFERENCE_URL, + ""}, + {"general.dvi", + {"general.tex"}, + {".dvi"}, + {"application/x-dvi"}, + "Device independent format file", + REFERENCE_URL, + ""}, + {"general.cer-certificate", + {"general.certificate"}, + {".cer"}, + {"application/pkix-cert"}, + "Internet security certificate", + REFERENCE_URL, + ""}, + {"general.crt-certificate", + {"general.certificate"}, + {".crt"}, + {"application/x-x509-ca-cert", "application/x-x509-server-cert", "application/x-x509-user-cert"}, + "Security Certificate", + REFERENCE_URL, + ""}, + {"general.crl-certificate", + {"general.certificate"}, + {".crl"}, + {"application/x-pkix-crl"}, + "Certificate revocation list file", + REFERENCE_URL, + ""}, + {"general.prn", + {"general.composite-object"}, + {".prn"}, + {}, + "Print to file", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.chart", + {"org.oasis.opendocument", "general.composite-object"}, + {".odc"}, + {"application/vnd.oasis.opendocument.chart"}, + "Open Document chart", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.text-master", + {"org.oasis.opendocument", "general.composite-object"}, + {".odm"}, + {"application/vnd.oasis.opendocument.text-master"}, + "Open Document text master", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.text-web", + {"org.oasis.opendocument", "general.composite-object"}, + {".oth"}, + {"application/vnd.oasis.opendocument.text-web"}, + "Open Document HTML template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.database", + {"org.oasis.opendocument", "general.database"}, + {".odb"}, + {"application/vnd.oasis.opendocument.database"}, + "Open Document database", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.image", + {"org.oasis.opendocument", "general.image"}, + {".odi"}, + {"application/vnd.oasis.opendocument.image"}, + "Open Document image", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.formula-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".otf"}, + {"application/vnd.oasis.opendocument.formula-template"}, + "Open Document formula template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.chart-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".otc"}, + {"application/vnd.oasis.opendocument.chart-template"}, + "Open Document chart template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.presentation-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".otp"}, + {"application/vnd.oasis.opendocument.presentation-template"}, + "Open Document presentation template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.image-template", + {"org.oasis.opendocument", "general.image"}, + {".oti"}, + {"application/vnd.oasis.opendocument.image-template"}, + "Open Document image template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.graphics-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".otg"}, + {"application/vnd.oasis.opendocument.graphics-template"}, + "Open Document graphics template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.spreadsheet-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".ots"}, + {"application/vnd.oasis.opendocument.spreadsheet-template"}, + "Open Document spreadsheet template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.text-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".ott"}, + {"application/vnd.oasis.opendocument.text-template"}, + "Open Document text template", + REFERENCE_URL, + ""}, + {"com.microsoft.word.dot", + {"general.composite-object"}, + {".dot"}, + {"application/msword"}, + "Microsoft Word document template", + REFERENCE_URL, + ""}, + {"com.microsoft.powerpoint.pps", + {"general.composite-object"}, + {".pps"}, + {"application/vnd.ms-powerpoint"}, + "Microsoft PowerPoint slide show", + REFERENCE_URL, + ""}, + {"com.microsoft.powerpoint.pot", + {"general.composite-object"}, + {".pot"}, + {"application/vnd.ms-powerpoint"}, + "Microsoft PowerPoint Template", + REFERENCE_URL, + ""}, + {"com.microsoft.excel.xlt", + {"general.composite-object"}, + {".xlt"}, + {"application/vnd.ms-excel"}, + "Microsoft Excel spreadsheet template", + REFERENCE_URL, + ""}, + {"com.microsoft.visio.vsd", + {"general.composite-object"}, + {".vsd"}, + {"application/vnd.visio"}, + "Microsoft Office Visio 2003-2010 drawing", + REFERENCE_URL, + ""}, + {"org.openxmlformats.drawingml.visio", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".vsdx"}, + {"application/vnd.openxmlformats-officedocument.drawingml.drawing"}, + "Microsoft Visio drawing", + REFERENCE_URL, + ""}, + {"org.openxmlformats.drawingml.template", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".vstx"}, + {}, + "Microsoft Visio drawing template", + REFERENCE_URL, + ""}, + {"org.openxmlformats.drawingml.visio.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".vsdm"}, + {}, + "Visio macro-enabled drawing", + REFERENCE_URL, + ""}, + {"org.openxmlformats.drawingml.template.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".vstm"}, + {}, + "Visio macro-enabled drawing template", + REFERENCE_URL, + ""}, + {"org.openxmlformats.wordprocessingml.template", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".dotx"}, + {"application/vnd.openxmlformats-officedocument.wordprocessingml.template"}, + "Office Open XML document template.", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.template", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".potx"}, + {"application/vnd.openxmlformats-officedocument.presentationml.template"}, + "Office Open XML presentation template", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.slideshow", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".ppsx"}, + {"application/vnd.openxmlformats-officedocument.presentationml.slideshow"}, + "Office Open XML slide show", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.template", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".xltx"}, + {"application/vnd.openxmlformats-officedocument.spreadsheetml.template"}, + "Office Open XML spreadsheet template", + REFERENCE_URL, + ""}, + {"org.openxmlformats.wordprocessingml.document.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".docm"}, + {"application/vnd.ms-word.document.macroEnabled.12"}, + "Office Open XML word processing document (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.wordprocessingml.template.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".dotm"}, + {"application/vnd.ms-word.template.macroEnabled.12"}, + "Office Open XML word processing template (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.template.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".xltm"}, + {"application/vnd.ms-excel.template.macroEnabled.12"}, + "Office Open XML spreadsheet template (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.addin.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".xlam"}, + {"application/vnd.ms-excel.addin.macroEnabled.12"}, + "Office Open XML spreadsheet addin (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.binary.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".xlsb"}, + {"application/vnd.ms-excel.sheet.binary.macroEnabled.12"}, + "Office Open XML spreadsheet binary (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.sheet.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".xlsm"}, + {"application/vnd.ms-excel.sheet.macroEnabled.12"}, + "Office Open XML spreadsheet (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.addin.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".ppam"}, + {"application/vnd.ms-powerpoint.addin.macroEnabled.12"}, + "Office Open XML presentation addin (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.presentation.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".pptm"}, + {"application/vnd.ms-powerpoint.presentation.macroEnabled.12"}, + "Office Open XML presentation (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.slideshow.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".ppsm"}, + {"application/vnd.ms-powerpoint.slideshow.macroEnabled.12"}, + "Office Open XML slide show (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.template.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".potm"}, + {"application/vnd.ms-powerpoint.template.macroEnabled.12"}, + "Office Open XML presentation template (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openoffice", + {"general.archive"}, + {}, + {}, + "OpenOffice document format for open-source office software suite", + REFERENCE_URL, + ""}, + {"org.openoffice.calc", + {"org.openoffice", "general.composite-object"}, + {".sxc"}, + {"application/vnd.sun.xml.calc"}, + "StarOffice Calc spreadsheet", + REFERENCE_URL, + ""}, + {"org.openoffice.draw", + {"org.openoffice", "general.composite-object"}, + {".sxd"}, + {"application/vnd.sun.xml.draw"}, + "StarOffice Drawing", + REFERENCE_URL, + ""}, + {"org.openoffice.writer-global", + {"org.openoffice", "general.composite-object"}, + {".sxg"}, + {"application/vnd.sun.xml.writer.global"}, + "Apache OpenOffice master document", + REFERENCE_URL, + ""}, + {"org.openoffice.impress", + {"org.openoffice", "general.composite-object"}, + {".sxi"}, + {"application/vnd.sun.xml.impress"}, + "StarOffice Impress presentation", + REFERENCE_URL, + ""}, + {"org.openoffice.math", + {"org.openoffice", "general.composite-object"}, + {".sxm"}, + {"application/vnd.sun.xml.math"}, + "StarMath Formula", + REFERENCE_URL, + ""}, + {"org.openoffice.writer", + {"org.openoffice", "general.composite-object"}, + {".sxw"}, + {"application/vnd.sun.xml.writer"}, + "StarOffice Writer document", + REFERENCE_URL, + ""}, + {"org.openoffice.calc.template", + {"org.openoffice", "general.composite-object"}, + {".stc"}, + {"application/vnd.sun.xml.calc.template"}, + "StarOffice Calc spreadsheet template", + REFERENCE_URL, + ""}, + {"org.openoffice.draw.template", + {"org.openoffice", "general.composite-object"}, + {".std"}, + {"application/vnd.sun.xml.draw.template"}, + "Apache OpenOffice Drawing template", + REFERENCE_URL, + ""}, + {"org.openoffice.impress.template", + {"org.openoffice", "general.composite-object"}, + {".sti"}, + {"application/vnd.sun.xml.impress.template"}, + "StarOffice Presentation template", + REFERENCE_URL, + ""}, + {"org.openoffice.writer.template", + {"org.openoffice", "general.composite-object"}, + {".stw"}, + {"application/vnd.sun.xml.writer.template"}, + "StarOffice Document template", + REFERENCE_URL, + ""}, + {"com.staroffice", + {"general.archive"}, + {}, + {}, + "StarOffice document format", + REFERENCE_URL, + ""}, + {"com.staroffice.draw", + {"com.staroffice", "general.composite-object"}, + {".sda"}, + {"application/vnd.stardivision.draw"}, + "StarOffice Drawing", + REFERENCE_URL, + ""}, + {"com.staroffice.calc", + {"com.staroffice", "general.composite-object"}, + {".sdc"}, + {"application/vnd.stardivision.calc"}, + "StarOffice Calc spreadsheet", + REFERENCE_URL, + ""}, + {"com.staroffice.impress", + {"com.staroffice", "general.composite-object"}, + {".sdd", ".sdp"}, + {"application/vnd.stardivision.impress"}, + "StarOffice Presentation", + REFERENCE_URL, + ""}, + {"com.staroffice.writer", + {"com.staroffice", "general.composite-object"}, + {".sdw"}, + {"application/vnd.stardivision.writer"}, + "StarOffice Writer text document", + REFERENCE_URL, + ""}, + {"com.staroffice.chart", + {"com.staroffice", "general.composite-object"}, + {".sds"}, + {"application/vnd.stardivision.chart"}, + "StarOffice Chart", + REFERENCE_URL, + ""}, + {"com.staroffice.mail", + {"com.staroffice", "general.composite-object"}, + {".sdm"}, + {"application/vnd.stardivision.mail"}, + "StarOffice Mail message", + REFERENCE_URL, + ""}, + {"com.staroffice.writer-global", + {"com.staroffice", "general.composite-object"}, + {".sgl"}, + {"application/vnd.stardivision.writer-global"}, + "StarOffice Master document", + REFERENCE_URL, + ""}, + {"com.staroffice.math", + {"com.staroffice", "general.composite-object"}, + {".smf"}, + {"application/vnd.stardivision.math"}, + "StarMath Formula file", + REFERENCE_URL, + ""}, + {"com.staroffice.template", + {"com.staroffice", "general.composite-object"}, + {".vor"}, + {"application/vnd.stardivision.template"}, + "StarOffice Template", + REFERENCE_URL, + ""}, + {"org.tug.bib", + {"general.tex"}, + {".bib"}, + {"text/x-bibtex"}, + "TeX Bibliography file", + REFERENCE_URL, + ""}, + {"org.tug.cls", + {"general.tex"}, + {".cls"}, + {"text/x-tex"}, + "TeX Class file", + REFERENCE_URL, + ""}, + {"org.tug.sty", + {"general.tex"}, + {".sty"}, + {"text/x-tex"}, + "TeX Style file", + REFERENCE_URL, + ""}, + {"org.tug.tex", + {"general.tex"}, + {".tex"}, + {"text/x-tex"}, + "TeX source document file", + REFERENCE_URL, + ""}, + {"org.latex-project.latex", + {"general.tex"}, + {".ltx", ".latex"}, + {"application/x-latex"}, + "LaTeX source document file", + REFERENCE_URL, + ""}, + {"org.matroska.mkv", + {"general.video"}, + {".mkv"}, + {"video/x-matroska"}, + "Matroska video", + REFERENCE_URL, + ""}, + {"org.matroska.mka", + {"general.audio"}, + {".mka"}, + {"audio/x-matroska"}, + "Matroska audio", + REFERENCE_URL, + ""}, + {"com.sgi.movie", + {"general.video"}, + {".movie"}, + {"video/x-sgi-movie"}, + "SGI movie", + REFERENCE_URL, + ""}, + {"com.apple.m4v", + {"general.video"}, + {".m4v"}, + {"video/m4v"}, + "M4V video", + REFERENCE_URL, + ""}, + {"org.webmproject.webm", + {"general.video"}, + {".webm"}, + {"video/webm"}, + "WebM is an audiovisual media file format", + REFERENCE_URL, + ""}, + {"com.apple.quicktime-movie", + {"general.video"}, + {".mov", ".qt", ".movie"}, + {"video/quicktime"}, + "QuickTime File Format", + REFERENCE_URL, + ""}, + {"com.coreldraw.cdr", + {"general.image"}, + {".cdr"}, + {"image/x-coreldraw"}, + "CorelDRAW file", + REFERENCE_URL, + ""}, + {"com.coreldraw.cdt", + {"general.image"}, + {".cdt"}, + {"image/x-coreldrawtemplate"}, + "CorelDRAW template", + REFERENCE_URL, + ""}, + {"com.coreldraw.cpt", + {"general.image"}, + {".cpt"}, + {"image/x-corelphotopaint"}, + "Corel PHOTO-PAINT image", + REFERENCE_URL, + ""}, + {"com.coreldraw.pat", + {"general.image"}, + {".pat"}, + {"image/x-coreldrawpattern"}, + "CorelDRAW pattern file", + REFERENCE_URL, + ""}, + {"com.microsoft.cur", + {"general.image"}, + {".cur"}, + {"image/ico"}, + "Microsoft Windows cursor image", + REFERENCE_URL, + ""}, + {"com.sun.raster", + {"general.image"}, + {".ras"}, + {"image/x-cmu-raster"}, + "Sun Raster Graphic", + REFERENCE_URL, + ""}, + {"com.google.webp", + {"general.image"}, + {".webp"}, + {"image/webp"}, + "WebP image", + REFERENCE_URL, + ""}, + {"com.sseyo.koan-audio", + {"general.audio"}, + {".skd", ".skm", ".skp", ".skt"}, + {"application/x-koan"}, + "Koan music files over the internet", + REFERENCE_URL, + ""}, + {"io.qt.moc", + {"general.source-code"}, + {".moc"}, + {"text/x-moc"}, + "Qt Meta-Object compiler file", + REFERENCE_URL, + ""}, + {"com.ghostscript.font", + {"general.font"}, + {".gsf"}, + {"application/x-font"}, + "Ghostscript font", + REFERENCE_URL, + ""}, + {"org.x.pcf-font", + {"general.font"}, + {".pcf"}, + {"application/x-font", "application/x-font-pcf"}, + "Portable compiled format", + REFERENCE_URL, + ""}, + {"com.microsoft.windows-media-wmd", + {"com.microsoft.advanced-systems-format", "general.zip-archive"}, + {".wmd"}, + {"application/x-ms-wmd"}, + "Windows media download package", + REFERENCE_URL, + ""}, + {"com.microsoft.windows-media-wmz", + {"com.microsoft.advanced-systems-format", "general.zip-archive"}, + {".wmz"}, + {"application/x-ms-wmz"}, + "Windows media player skin package", + REFERENCE_URL, + ""}, + {"com.microsoft.windows-installer", + {"general.executable"}, + {".msi"}, + {"application/x-msi"}, + "Windows installer package", + REFERENCE_URL, + ""}, + {"com.microsoft.publisher.pub", + {"general.composite-object"}, + {".pub"}, + {"application/x-mspublisher"}, + "Publisher document", + REFERENCE_URL, + ""}, + {"com.microsoft.windows-media-playlist", + {"general.xml", "general.media"}, + {".wpl"}, + {"application/vnd.ms-wpl"}, + "Windows media player playlist", + REFERENCE_URL, + ""}, + {"com.microsoft.access.mdb", + {"general.database"}, + {".mdb"}, + {"application/msaccess"}, + "Microsoft Access database", + REFERENCE_URL, + ""}, + {"com.3dsystems.stereolithography", + {"general.composite-object"}, + {".stl"}, + {"application/vnd.ms-pki.stl"}, + "Stereolithography file", + REFERENCE_URL, + ""}, + {"com.apple.media.playlist", + {"general.media"}, + {".m3u8"}, + {"application/vnd.apple.mpegurl"}, + "UTF-8 M3U playlist", + REFERENCE_URL, + ""}, + {"com.abisource.word", + {"general.composite-object"}, + {".abw"}, + {"application/x-abiword"}, + "AbiWord document", + REFERENCE_URL, + ""}, + {"com.adobe.framemaker", + {"general.composite-object"}, + {".book", ".fm", ".frame", ".maker"}, + {"application/x-maker"}, + "FrameMaker book file", + REFERENCE_URL, + ""}, + {"com.wolfram.cdf", + {"general.composite-object"}, + {".cdf"}, + {"application/x-cdf"}, + "Computable document format file", + REFERENCE_URL, + ""}, + {"de.cinderella.cdy", + {"general.composite-object"}, + {".cdy"}, + {"application/vnd.cinderella"}, + "Cinderella construction file", + REFERENCE_URL, + ""}, + {"com.adobe.dcr", + {"general.video"}, + {".dcr"}, + {"application/x-director"}, + "Shockwave media file", + REFERENCE_URL, + ""}, + {"com.adobe.dir", + {"general.video"}, + {".dir"}, + {"application/x-director"}, + "Adobe Director movie", + REFERENCE_URL, + ""}, + {"com.adobe.dxr", + {"general.video"}, + {".dxr"}, + {"application/x-director"}, + "Protected macromedia director movie", + REFERENCE_URL, + ""}, + {"org.gnumeric.spreadsheet", + {"general.xml"}, + {".gnumeric"}, + {"application/x-gnumeric"}, + "Gnumeric spreadsheet", + REFERENCE_URL, + ""}, + {"org.hdfgroup.hdf", + {"general.composite-object"}, + {".hdf"}, + {"application/x-hdf"}, + "Hierarchical data format", + REFERENCE_URL, + ""}, + {"com.apple.binhex-archive", + {"general.archive"}, + {".hqx"}, + {"application/mac-binhex40"}, + "BinHex 4.0 encoded file", + REFERENCE_URL, + ""}, + {"com.microsoft.hta", + {"general.archive", "general.executable"}, + {".hta"}, + {"application/hta"}, + "HTML application", + REFERENCE_URL, + ""}, + {"com.microsoft.internet.ins", + {"general.text"}, + {".ins"}, + {"application/x-internet-signup"}, + "Internet settings file", + REFERENCE_URL, + ""}, + {"com.microsoft.internet.isp", + {"general.text"}, + {".isp"}, + {"application/x-internet-signup"}, + "IIS internet service provider settings", + REFERENCE_URL, + ""}, + {"org.troff", + {"general.text"}, + {".man", ".t", ".roff"}, + {"text/troff"}, + "Unix troff format", + REFERENCE_URL, + ""}, + {"com.adobe.framemaker.mif", + {"general.composite-object"}, + {".mif"}, + {"application/vnd.mif"}, + "FrameMaker interchange format file", + REFERENCE_URL, + ""}, + {"io.sourceforge.freemind", + {"general.composite-object"}, + {".mm"}, + {"application/x-freemind"}, + "Mind Map file", + REFERENCE_URL, + ""}, + {"com.yamaha.smaf", + {"general.audio"}, + {".mmf"}, + {"application/vnd.smaf"}, + "Synthetic music mobile application file", + REFERENCE_URL, + ""}, + {"com.wolfram.mathematica.notebook", + {"general.text"}, + {".nb"}, + {"application/mathematica"}, + "Mathematica notebook", + REFERENCE_URL, + ""}, + {"org.xiph.ogg", + {"general.audio"}, + {".oga", ".ogg"}, + {"application/ogg"}, + "Ogg vorbis audio", + REFERENCE_URL, + ""}, + {"com.netscape.proxy-autoconfig", + {"general.plain-text"}, + {".pac"}, + {"application/x-ns-proxy-autoconfig"}, + "Proxy auto-config file", + REFERENCE_URL, + ""}, + {"com.rsa.pkcs-12", + {"general.archive"}, + {".pfx", ".p12"}, + {"application/x-pkcs12"}, + "PKCS #12 certificate file", + REFERENCE_URL, + ""}, + {"org.openpgp.signature", + {"general.object"}, + {".pgp"}, + {"application/pgp-signature"}, + "PGP security key", + REFERENCE_URL, + ""}, + {"com.apple.quicktime-link", + {"general.text"}, + {".qtl"}, + {"application/x-quicktimeplayer"}, + "QuickTime link file", + REFERENCE_URL, + ""}, + {"com.rarlab.rar-archive", + {"general.archive"}, + {".rar"}, + {"application/rar", "application/vnd.rar"}, + "WinRAR compressed archive", + REFERENCE_URL, + ""}, + {"org.7-zip.7-zip-archive", + {"general.archive"}, + {".7z"}, + {"application/x-7z-compressed"}, + "7-zip compressed archive", + REFERENCE_URL, + ""}, + {"com.red-bean.sgf", + {"general.text"}, + {".sgf"}, + {"application/x-go-sgf"}, + "Smart game format file", + REFERENCE_URL, + ""}, + {"com.stuffit.sit-archive", + {"general.archive"}, + {".sit"}, + {"application/x-stuffit"}, + "Stuffit archive", + REFERENCE_URL, + ""}, + {"com.adobe.futuresplash", + {"general.video"}, + {".spl"}, + {"application/futuresplash", "application/x-futuresplash"}, + "FutureSplash animation", + REFERENCE_URL, + ""}, + {"com.adobe.flash", + {"general.video"}, + {".swf", ".flv"}, + {"application/x-shockwave-flash", "video/x-flv"}, + "Shockwave flash movie", + REFERENCE_URL, + ""}, + {"org.gnu.texinfo", + {"general.source-code"}, + {".texinfo", ".texi"}, + {"application/x-texinfo"}, + "GNU Texinfo", + REFERENCE_URL, + ""}, + {"org.bittorrent.torrent", + {"general.text"}, + {".torrent"}, + {"application/x-bittorrent"}, + "BitTorrent file", + REFERENCE_URL, + ""}, + {"com.idsoftware.doom", + {"general.archive"}, + {".wad"}, + {"application/x-doom"}, + "Doom WAD file", + REFERENCE_URL, + ""}, + {"com.apple.webarchive", + {"general.archive"}, + {".webarchive"}, + {"application/x-webarchive"}, + "Safari web archive", + REFERENCE_URL, + ""}, + {"com.android.webarchive", + {"general.archive"}, + {".webarchivexml"}, + {"application/x-webarchive-xml"}, + "Android web browser archive", + REFERENCE_URL, + ""}, + {"org.gimp.xcf", + {"general.image"}, + {".xcf"}, + {"application/x-xcf", "image/x-xcf"}, + "eXperimental computing facility, GIMP image file", + REFERENCE_URL, + ""}, + {"com.edrawsoft.edrawmax", + {"general.composite-object"}, + {".eddx"}, + {"application/x-eddx"}, + "Edraw Max XML file", + REFERENCE_URL, + ""}, + {"com.edrawsoft.edrawmind", + {"general.composite-object"}, + {".emmx"}, + {"application/x-emmx"}, + "Edraw MindMaster XML file", + REFERENCE_URL, + ""}, + {"net.cnki.caj", + {"general.composite-object"}, + {".caj"}, + {"application/caj"}, + "Chinese academic journal file", + REFERENCE_URL, + ""}, + {"com.dbase.dbf", + {"general.database"}, + {".dbf"}, + {"application/dbf", "application/dbase"}, + "Database file", + REFERENCE_URL, + ""}, + {"com.autodesk.dwg", + {"general.composite-object"}, + {".dwg"}, + {"image/vnd.dwg"}, + "AutoCAD drawing", + REFERENCE_URL, + ""}, + {"com.autodesk.dxf", + {"general.composite-object"}, + {".dxf"}, + {"image/vnd.dxf"}, + "Drawing exchange format file", + REFERENCE_URL, + ""}, + {"com.autodesk.dws", + {"general.composite-object"}, + {".dws"}, + {}, + "AutoCAD drawing standards file", + REFERENCE_URL, + ""}, + {"com.autodesk.dwt", + {"general.composite-object"}, + {".dwt"}, + {}, + "AutoCAD drawing template", + REFERENCE_URL, + ""}, + {"com.autodesk.dwf", + {"general.composite-object"}, + {".dwf"}, + {"model/vnd.dwf"}, + "Design web format file", + REFERENCE_URL, + ""}, + {"com.autodesk.dwfx", + {"general.composite-object"}, + {".dwfx"}, + {}, + "Design web format XPS file", + REFERENCE_URL, + ""}, + {"com.autodesk.shp", + {"general.composite-object"}, + {".shp"}, + {}, + "3D studio shape", + REFERENCE_URL, + ""}, + {"com.autodesk.shx", + {"general.composite-object"}, + {".shx"}, + {}, + "AutoCAD compiled shape file", + REFERENCE_URL, + ""}, + {"com.autodesk.slide-library", + {"general.composite-object"}, + {".slb"}, + {}, + "AutoCAD slide library", + REFERENCE_URL, + ""}, + {"com.autodesk.line", + {"general.text"}, + {".lin"}, + {}, + "AutoCAD linetype file", + REFERENCE_URL, + ""}, + {"com.autodesk.plotter", + {"general.composite-object"}, + {".plt"}, + {}, + "AutoCAD plotter document", + REFERENCE_URL, + ""}, + {"com.hp.graphics-language", + {"general.composite-object"}, + {".hpgl"}, + {"application/vnd.hp-hpgl"}, + "HP graphics language plotter file", + REFERENCE_URL, + ""}, + {"com.microsoft.metafile", + {"general.composite-object"}, + {".wmf"}, + {}, + "Windows metafile", + REFERENCE_URL, + ""}, + {"com.spatial.acis.sat", + {"general.text"}, + {".sat"}, + {}, + "ACIS SAT 3D model", + REFERENCE_URL, + ""}, + {"org.aomedia.avif-image", + {"general.image"}, + {".avif"}, + {"image/avif"}, + "AVIF image", + REFERENCE_URL, + ""}, + {"com.microsoft.dds", + {"general.image"}, + {".dds"}, + {"image/vnd-ms.dds"}, + "DirectDraw surface image", + REFERENCE_URL, + ""}, + {"com.ea.iff-ilbm", + {"general.image"}, + {".ilbm"}, + {"image/x-ilbm"}, + "Interleaved bitmap image", + REFERENCE_URL, + ""}, + {"com.canon.cr2-raw-image", + {"general.raw-image"}, + {".cr2"}, + {"image/x-canon-cr2"}, + "Canon raw 2 image", + REFERENCE_URL, + ""}, + {"com.canon.cr3-raw-image", + {"general.raw-image"}, + {".cr3"}, + {"image/x-canon-cr3"}, + "Canon raw 3 image", + REFERENCE_URL, + ""}, + {"com.canon.crw-raw-image", + {"general.raw-image"}, + {".crw"}, + {"image/x-canon-crw"}, + "Canon raw CIFF image file", + REFERENCE_URL, + ""}, + {"com.adobe.dng-raw-image", + {"general.raw-image"}, + {".dng"}, + {"image/x-adobe-dng"}, + "Digital negative image", + REFERENCE_URL, + ""}, + {"com.sony.arw-raw-image", + {"general.raw-image"}, + {".arw"}, + {"image/x-sony-arw"}, + "Sony alpha raw digital camera image", + REFERENCE_URL, + ""}, + {"com.nikon.nef-raw-image", + {"general.raw-image"}, + {".nef"}, + {"image/x-nikon-nef"}, + "Nikon electronic format RAW image", + REFERENCE_URL, + ""}, + {"com.mindjet.mindmanager.mmap", + {"general.composite-object"}, + {".mmap"}, + {}, + "MindManager Map", + REFERENCE_URL, + ""}, + {"com.microsoft.email", + {"general.message"}, + {".eml"}, + {"message/rfc822"}, + "E-Mail message", + REFERENCE_URL, + ""}, + {"com.microsoft.message", + {"general.message"}, + {".msg"}, + {}, + "Outlook message item file", + REFERENCE_URL, + ""}, + {"com.microsoft.pst", + {"general.archive"}, + {".pst"}, + {}, + "Outlook personal information store", + REFERENCE_URL, + ""}, + {"com.kingsoft.office", + {"general.archive"}, + {}, + {}, + "Kingsoft office suite", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.writer.wps", + {"com.kingsoft.office", "general.composite-object"}, + {".wps"}, + {}, + "Kingsoft Writer document", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.writer.wpt", + {"com.kingsoft.office", "general.composite-object"}, + {".wpt"}, + {}, + "Kingsoft Writer template", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.presentation.dps", + {"com.kingsoft.office", "general.composite-object"}, + {".dps"}, + {}, + "Kingsoft Presentation file", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.presentation.template", + {"com.kingsoft.office", "general.composite-object"}, + {".dpt"}, + {}, + "Kingsoft Presentation template", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.spreadsheets.et", + {"com.kingsoft.office", "general.composite-object"}, + {".et"}, + {}, + "Kingsoft Spreadsheets tile", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.spreadsheets.template", + {"com.kingsoft.office", "general.composite-object"}, + {".ett"}, + {}, + "Kingsoft Spreadsheets template", + REFERENCE_URL, + ""}, + {"com.microsoft.ini", + {"general.text"}, + {".ini"}, + {}, + "Windows Initialization File", + REFERENCE_URL, + ""}, + {"general.json", + {"general.script"}, + {".json"}, + {"application/json"}, + "JavaScript Object Notation File", + REFERENCE_URL, + ""}, + {"general.yaml", + {"general.script"}, + {".yaml", ".yml"}, + {"application/yaml"}, + "YAML Document", + REFERENCE_URL, + ""}, + {"general.log", + {"general.text"}, + {".log"}, + {"text/plain"}, + "Log File", + REFERENCE_URL, + ""}, + {"general.uri", + {"general.object"}, + {}, + {}, + "Universal Resource Identifier", + REFERENCE_URL, + ""}, + {"general.file-uri", + {"general.uri"}, + {}, + {}, + "File URI", + REFERENCE_URL, + ""}, + {"general.text-lst", + {"general.plain-text"}, + {".lst"}, + {}, + "Data List", + REFERENCE_URL, + ""}, + {"com.android.apk", + {"general.archive"}, + {".apk", ".apks", ".aab", ".xapk", ".apkm", ".akp"}, + {"application/vnd.android.package-archive"}, + "Android Package File", + REFERENCE_URL, + ""}, + {"com.adobe.postscript-pfb-font", + {"com.adobe.postscript-font"}, + {".pfb"}, + {"application/x-font"}, + "Printer Font Binary, PostScript Type 1 outline font.", + REFERENCE_URL, + ""}, + {"com.adobe.postscript-pfa-font", + {"com.adobe.postscript-font"}, + {".pfa"}, + {"application/x-font"}, + "Printer Pont ASCII file, PostScript Type 1 outline font.", + REFERENCE_URL, + ""}, + {"general.bz-archive", + {"general.archive"}, + {".bz"}, + {"application/x-bzip"}, + "Bzip Compressed File", + REFERENCE_URL, + ""}, + {"general.tar-bzip-archive", + {"general.bz-archive"}, + {".tbz"}, + {"application/x-bzip-compressed-tar"}, + "Bzip Compressed Tar Archive", + REFERENCE_URL, + ""}, + {"general.tar-bzip2-archive", + {"general.bz2-archive"}, + {".tbz2"}, + {"application/x-bzip2-compressed-tar"}, + "Bzip2-Compressed TAR File", + REFERENCE_URL, + ""}, + {"org.tukaani.xz-archive", + {"general.archive"}, + {".xz"}, + {"application/x-xz"}, + "XZ Compressed Archive", + REFERENCE_URL, + ""}, + {"org.tukaani.tar-xz-archive", + {"org.tukaani.xz-archive"}, + {".txz"}, + {"application/x-xz-compressed-tar"}, + "XZ Compressed Tar Archive", + REFERENCE_URL, + ""}, + {"general.xar-archive", + {"general.archive"}, + {".xar"}, + {"application/x-xar"}, + "Extensible Archive Fromat", + REFERENCE_URL, + ""}, + {"com.microsoft.cab-archive", + {"general.archive"}, + {".cab"}, + {"application/vnd.ms-cab-compressed"}, + "Windows Cabinet File", + REFERENCE_URL, + ""}, + {"redhat.rpm-archive", + {"general.archive"}, + {".rpm"}, + {"application/x-rpm"}, + "RedHat Package Manager File", + REFERENCE_URL, + ""}, + {"org.godotengine.tpz-archive", + {"general.archive"}, + {".tpz"}, + {}, + "Godot Engine Export Template Archive", + REFERENCE_URL, + ""}, + {"general.lza-archive", + {"general.archive"}, + {".lza"}, + {"application/x-lzh-compressed"}, + "LZA Compressed Archive", + REFERENCE_URL, + ""}, + {"general.arj-archive", + {"general.archive"}, + {".arj"}, + {"application/x-arj"}, + "ARJ Compressed File Archive", + REFERENCE_URL, + ""}, + {"com.winzip.zipx", + {"general.archive"}, + {".zipx"}, + {}, + "Extended Zip Archive", + REFERENCE_URL, + ""}, + {"general.lzma-archive", + {"general.archive"}, + {".lzma"}, + {"application/x-lzma"}, + "LZMA Compressed File", + REFERENCE_URL, + ""}, + {"general.lzma86-archive", + {"general.archive"}, + {".lzma86"}, + {}, + "LZMA86 Compressed File", + REFERENCE_URL, + ""}, + {"org.mozilla.xpinstall", + {"general.archive"}, + {".xpi"}, + {"application/x-xpinstall"}, + "Cross-platform Installer Package", + REFERENCE_URL, + ""}, + {"general.hfs-disk-image", + {"general.disk-image"}, + {".hfs"}, + {}, + "HFS Disk Image File", + REFERENCE_URL, + ""}, + {"general.img-disk-image", + {"general.disk-image"}, + {".img"}, + {"application/x-raw-disk-image"}, + "Disc Image Data File", + REFERENCE_URL, + ""}, + {"com.ezbsystems.zipped-iso", + {"general.disk-image"}, + {".isz"}, + {}, + "Zipped ISO Disk Image", + REFERENCE_URL, + ""}, + {"com.microsoft.wim", + {"general.disk-image"}, + {".wim"}, + {"application/x-ms-wim"}, + "Windows Imaging Format File", + REFERENCE_URL, + ""}, + {"com.microsoft.swm", + {"general.disk-image"}, + {".swm"}, + {"application/x-ms-wim"}, + "Split Windows Imaging Format", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.spreadsheets.etx", + {"com.kingsoft.office", "general.composite-object"}, + {".etx"}, + {}, + "Kingsoft Spreadsheets File", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.spreadsheets.ettx", + {"com.kingsoft.office", "general.composite-object"}, + {".ettx"}, + {}, + "Kingsoft Spreadsheets Template", + REFERENCE_URL, + ""}, + {"com.microsoft.excel.dif", + {"general.composite-object"}, + {".dif"}, + {}, + "Data interchange format", + REFERENCE_URL, + ""}, + {"openharmony.app", + {"openharmony.package"}, + {".app"}, + {}, + "OpenHarmony system defined application package", + REFERENCE_URL, + ""}, + {"com.huawei.hmos.settings.wifi", + {"general.text"}, + {".hmoswifi"}, + {}, + "HarmonyOS WIFI sharing setting", + REFERENCE_URL, + ""}, + {"general.tel", + {"general.text"}, + {".tel"}, + {}, + "TEL schematic diagram file format", + REFERENCE_URL, + ""}, + {"general.ets", + {"general.script"}, + {".ets"}, + {}, + "Extended TypeScript source code", + REFERENCE_URL, + ""}, + {"general.json5", + {"general.script"}, + {".json5"}, + {}, + "JSON5 data interchange format", + REFERENCE_URL, + ""}, + {"com.monkeysaudio.ape-audio", + {"general.audio"}, + {".ape"}, + {"audio/x-monkeys-audio"}, + "Monkey's Audio", + REFERENCE_URL, + ""}, + {"org.xiph.opus-audio", + {"general.audio"}, + {".opus"}, + {"audio/opus"}, + "Opus Audio", + REFERENCE_URL, + ""}, + {"general.conf", + {"general.text"}, + {".conf"}, + {}, + "Generic Configuration File", + REFERENCE_URL, + ""}, + {"com.microsoft.dos-batch", + {"general.script"}, + {".bat"}, + {"application/x-bat"}, + "DOS Batch File", + REFERENCE_URL, + ""}, + {"com.microsoft.vbscript", + {"general.script"}, + {".vbs"}, + {"application/x-vbs"}, + "VBScript File", + REFERENCE_URL, + ""}, + {"general.ion", + {"general.text"}, + {".ion"}, + {}, + "File Description File", + REFERENCE_URL, + ""}, + {"com.microsoft.registry", + {"general.database"}, + {".reg"}, + {}, + "Registry File", + REFERENCE_URL, + ""}, + {"com.microsoft.catalog", + {"general.object"}, + {".cat"}, + {}, + "Windows Catalog File", + REFERENCE_URL, + ""}, + {"com.microsoft.powershell-script", + {"general.script"}, + {".ps1"}, + {}, + "Windows PowerShell Cmdlet File", + REFERENCE_URL, + ""}, + {"org.w3.woff", + {"general.font"}, + {".woff"}, + {"font/woff"}, + "Web Open Font Format File", + REFERENCE_URL, + ""}, + {"org.sqlite.database", + {"general.database"}, + {".sqlite", ".sqlite3", ".db", ".db3", ".s3db", ".sl3"}, + {"application/vnd.sqlite3"}, + "SQLite Database", + REFERENCE_URL, + ""}, + {"com.microsoft.sys", + {"general.object"}, + {".sys"}, + {}, + "Windows System File", + REFERENCE_URL, + ""}, + {"com.microsoft.inf", + {"general.text"}, + {".inf"}, + {"text/plain"}, + "Setup Information File", + REFERENCE_URL, + ""}, + {"com.microsoft.pdb", + {"general.database"}, + {".pdb"}, + {"application/x-ms-pdb"}, + "Program Database", + REFERENCE_URL, + ""}, + {"com.microsoft.tlb", + {"general.object"}, + {".tlb"}, + {}, + "OLE Type Library", + REFERENCE_URL, + ""}, + {"com.microsoft.sccd", + {"general.xml"}, + {".sccd"}, + {}, + "Signed Custom Capability Descriptor", + REFERENCE_URL, + ""}, + {"com.adobe.f4v", + {"general.video"}, + {".f4v"}, + {"video/mp4"}, + "Flash MP4 Video File", + REFERENCE_URL, + ""}, + {"general.mp2t", + {"general.video"}, + {".m2ts", ".mts", ".m2t"}, + {"video/mp2t"}, + "Blu-ray BDAV Video File Format", + REFERENCE_URL, + ""}, + {"com.youtube.video", + {"general.video"}, + {".yt", ".vt"}, + {"video/vnd.youtube.yt"}, + "Youtube Video format", + REFERENCE_URL, + ""}, + {"com.cisco.webex-video", + {"general.video"}, + {".wrf"}, + {"video/x-webex"}, + "WebEx Recording", + REFERENCE_URL, + ""}, + {"general.mpeg-2", + {"general.video"}, + {".mpeg2", ".mpv2", ".mp2v", ".m2v", ".mpv"}, + {"video/mpeg"}, + "MPEG-2 Video format", + REFERENCE_URL, + ""}, + {"general.mpeg-1", + {"general.video"}, + {".mpeg1", ".mpv1", ".mp1v", ".m1v"}, + {"video/mpeg"}, + "MPEG-1 Video format", + REFERENCE_URL, + ""}, + {"com.real.realmedia-vbr", + {"general.video"}, + {".rmvb"}, + {"application/vnd.rn-realmedia-vbr"}, + "RealMedia Variable Bit Rate Format", + REFERENCE_URL, + ""}, + {"com.real.realvideo", + {"general.video"}, + {".rv"}, + {"video/x-pn-realvideo"}, + "RealVideo Format", + REFERENCE_URL, + ""}, + {"general.divx-video", + {"general.video"}, + {".divx"}, + {"video/divx"}, + "DivX-Encoded Movie", + REFERENCE_URL, + ""}, + {"org.csiro.annodex", + {"general.video"}, + {".axv"}, + {"video/annodex"}, + "Annodex Video Format", + REFERENCE_URL, + ""}, + {"general.ogv", + {"general.video"}, + {".ogv"}, + {"video/ogg"}, + "Ogg Video Format", + REFERENCE_URL, + ""}, + {"com.microsoft.lsf-video", + {"general.video"}, + {".lsf", ".lsx"}, + {"video/x-la-asf"}, + "Streaming Media Format", + REFERENCE_URL, + ""}, + {"general.h264-video", + {"general.video"}, + {".h264"}, + {"video/H264"}, + "H.264 Encoded Video Format", + REFERENCE_URL, + ""}, + {"general.jpeg-2000", + {"general.image"}, + {".jp2", ".jpg2", ".jpx", ".jpf", ".jpm"}, + {"image/jp2", "image/jpx", "image/jpm"}, + "JPEG 2000 Image", + REFERENCE_URL, + ""}, + {"com.fujifilm.raf-raw-image", + {"general.raw-image"}, + {".raf"}, + {"image/x-fuji-raf"}, + "Fujifilm RAW Image", + REFERENCE_URL, + ""}, + {"com.nikon.nrw-raw-image", + {"general.raw-image"}, + {".nrw"}, + {"image/x-nikon-nrw"}, + "Nikon Raw Image", + REFERENCE_URL, + ""}, + {"com.panasonic.rw2-raw-image", + {"general.raw-image"}, + {".rw2", ".raw"}, + {"image/x-panasonic-raw"}, + "Panasonic RAW Image", + REFERENCE_URL, + ""}, + {"com.pentax.pef-raw-image", + {"general.raw-image"}, + {".pef"}, + {"image/x-pentax-pef"}, + "Pentax Electronic RAW Image", + REFERENCE_URL, + ""}, + {"com.sumsung.srw-raw-image", + {"general.raw-image"}, + {".srw"}, + {"image/x-samsung-srw"}, + "Samsung RAW Image", + REFERENCE_URL, + ""}, + {"com.epson.erf-raw-image", + {"general.raw-image"}, + {".erf"}, + {"image/x-epson-erf"}, + "Epson RAW Imager", + REFERENCE_URL, + ""}, + {"com.olympus.orf-raw-image", + {"general.raw-image"}, + {".orf"}, + {"image/x-olympus-orf"}, + "Olympus RAW Image", + REFERENCE_URL, + ""}, + {"general.ief-image", + {"general.image"}, + {".ief"}, + {"image/ief"}, + "Image Exchange Format", + REFERENCE_URL, + ""}, + {"com.aol.art-image", + {"general.image"}, + {".art"}, + {"image/x-jg"}, + "ART image format", + REFERENCE_URL, + ""}, + {"general.content-form", + {"general.object"}, + {}, + {}, + "Content form format", + REFERENCE_URL, + ""}, + {"com.apple.m4p-audio", + {"general.audio"}, + {".m4p"}, + {"audio/mp4"}, + "iTunes Music Store Audio File Format", + REFERENCE_URL, + ""}, + {"general.ac3-audio", + {"general.audio"}, + {".ac3"}, + {"audio/ac3"}, + "Audio Codec 3 File Format", + REFERENCE_URL, + ""}, + {"openharmony.hsp", + {"openharmony.package"}, + {".hsp"}, + {}, + "Harmony Shared Package", + REFERENCE_URL, + ""}, + {"openharmony.har", + {"openharmony.package"}, + {".har"}, + {}, + "Harmony Archive", + REFERENCE_URL, + ""}, + {"openharmony.gopaint", + {"general.archive"}, + {".gopaint"}, + {}, + "Gopaint file format defined for Openharmony", + REFERENCE_URL, + ""}, + {"openharmony.gobrush", + {"general.archive"}, + {".gobrush"}, + {}, + "Gobrush file format defined for Openharmony", + REFERENCE_URL, + ""}, + {"openharmony.gobrushes", + {"general.archive"}, + {".gobrushes"}, + {}, + "Gobrushes file format defined for Openharmony", + REFERENCE_URL, + ""}, + {"openharmony.gocolor", + {"general.archive"}, + {".gocolor"}, + {}, + "Gocolor file format defined for Openharmony", + REFERENCE_URL, + ""}, + {"openharmony.dlp", + {"general.composite-object"}, + {".dlp"}, + {}, + "Account identify encryption file format defined by OpenHarmony", + REFERENCE_URL, + ""} + }; +}; +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/adapter/framework/innerkitsimpl/client/utd_client.cpp b/udmf/adapter/framework/innerkitsimpl/client/utd_client.cpp index 5f40226516f9ce94d7fdf6399d30812cd7a2c722..25cca5920672db728f6c2534f1069d9cb4babb51 100644 --- a/udmf/adapter/framework/innerkitsimpl/client/utd_client.cpp +++ b/udmf/adapter/framework/innerkitsimpl/client/utd_client.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 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 @@ -12,9 +12,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#define LOG_TAG "UtdClient" +#include +#include +#include #include "utd_client.h" +#include "logger.h" +#include "utd_graph.h" +#include "custom_utd_store.h" + namespace OHOS { namespace UDMF { +constexpr const int MAX_UTD_LENGTH = 256; +constexpr const char *CUSTOM_UTD_HAP_DIR = "/data/utd/utd-adt.json"; + UtdClient::UtdClient() { Init(); @@ -30,61 +42,282 @@ UtdClient &UtdClient::GetInstance() return *instance; } +std::vector GetHapTypeCfgs() +{ + LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg, Path:%{public}s.", CUSTOM_UTD_HAP_DIR); + std::string jsonStr; + std::ifstream fin(CUSTOM_UTD_HAP_DIR); + while (fin.good()) { + std::string line; + std::getline(fin, line); + jsonStr += line; + } + std::vector customUtdTypes; + CustomUtdJsonParser utdJsonParser; + utdJsonParser.ParseStoredCustomUtdJson(jsonStr, customUtdTypes); + LOG_DEBUG(UDMF_CLIENT, "GetTypeCfgs, customUtdTypes total:%{public}zu.", customUtdTypes.size()); + return customUtdTypes; +} + void UtdClient::Init() { + std::unique_lock lock(utdMutex_); + descriptorCfgs_ = PresetTypeDescriptors::GetInstance().GetPresetTypes(); + std::vector customTypes; + customTypes = GetHapTypeCfgs(); + LOG_INFO(UDMF_CLIENT, "get customUtd, size:%{public}zu", customTypes.size()); + if (!customTypes.empty()) { + descriptorCfgs_.insert(descriptorCfgs_.end(), customTypes.begin(), customTypes.end()); + } + UtdGraph::GetInstance().InitUtdGraph(descriptorCfgs_); +} + +bool UtdClient::IsHapTokenType() +{ + return true; +} + +Status UtdClient::GetCurrentActiveUserId(int32_t &userId) +{ + return Status::E_OK; } Status UtdClient::GetTypeDescriptor(const std::string &typeId, std::shared_ptr &descriptor) { + { + std::shared_lock guard(utdMutex_); + for (const auto &utdTypeCfg : descriptorCfgs_) { + if (utdTypeCfg.typeId == typeId) { + descriptor = std::make_shared(utdTypeCfg); + return Status::E_OK; + } + } + } + if (typeId.find(FLEXIBLE_TYPE_FLAG) != typeId.npos) { + return GetFlexibleTypeDescriptor(typeId, descriptor); + } return Status::E_OK; } bool UtdClient::IsValidFileExtension(const std::string &fileExtension) { + if (fileExtension.empty()) { + return false; + } + if (fileExtension[0] != '.' || fileExtension.find("?") != fileExtension.npos || + fileExtension.find(":") != fileExtension.npos || fileExtension.find("=") != fileExtension.npos || + fileExtension.find("\\") != fileExtension.npos) { + return false; + } + return true; } bool UtdClient::IsValidMimeType(const std::string &mimeType) { + if (mimeType.empty()) { + return false; + } + if (mimeType.find("?") != mimeType.npos || mimeType.find(":") != mimeType.npos || + mimeType.find("=") != mimeType.npos || mimeType.find("\\") != mimeType.npos) { + return false; + } return true; } Status UtdClient::GetFlexibleTypeDescriptor(const std::string &typeId, std::shared_ptr &descriptor) { + TypeDescriptorCfg flexibleTypeDescriptorCfg; + if (!FlexibleType::ParseFlexibleUtd(typeId, flexibleTypeDescriptorCfg)) { + LOG_ERROR(UDMF_CLIENT, "ParseFlexibleUtd failed, invalid typeId"); + return Status::E_ERROR; + } + descriptor = std::make_shared(flexibleTypeDescriptorCfg); return Status::E_OK; } Status UtdClient::GetUniformDataTypeByFilenameExtension(const std::string &fileExtension, std::string &typeId, std::string belongsTo) { + std::string lowerFileExtension = fileExtension; + std::transform(lowerFileExtension.begin(), lowerFileExtension.end(), lowerFileExtension.begin(), ::tolower); + if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo."); + return Status::E_INVALID_PARAMETERS; + } + { + std::shared_lock guard(utdMutex_); + bool found = false; + for (const auto &utdTypeCfg : descriptorCfgs_) { + for (auto fileEx : utdTypeCfg.filenameExtensions) { + std::transform(fileEx.begin(), fileEx.end(), fileEx.begin(), ::tolower); + if (fileEx == lowerFileExtension) { + typeId = utdTypeCfg.typeId; + found = true; + break; + } + } + if (found) { + break; + } + } + } + // the find typeId is not belongsTo to the belongsTo. + if (!typeId.empty() && belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && + !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { + typeId = ""; + } + + if (typeId.empty()) { + if (!IsValidFileExtension(lowerFileExtension)) { + LOG_ERROR(UDMF_CLIENT, "invalid fileExtension."); + return Status::E_INVALID_PARAMETERS; + } + typeId = FlexibleType::GenFlexibleUtd("", lowerFileExtension, belongsTo); + } return Status::E_OK; } Status UtdClient::GetUniformDataTypeByMIMEType(const std::string &mimeType, std::string &typeId, std::string belongsTo) { + std::string lowerMimeType = mimeType; + std::transform(lowerMimeType.begin(), lowerMimeType.end(), lowerMimeType.begin(), ::tolower); + if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo."); + return Status::E_INVALID_PARAMETERS; + } + typeId = GetTypeIdFromCfg(lowerMimeType); + // the find typeId is not belongsTo to the belongsTo. + if (!typeId.empty() && belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && + !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { + typeId = ""; + } + if (typeId.empty()) { + if (!IsValidMimeType(mimeType)) { + LOG_ERROR(UDMF_CLIENT, "invalid mimeType."); + return Status::E_INVALID_PARAMETERS; + } + typeId = FlexibleType::GenFlexibleUtd(lowerMimeType, "", belongsTo); + } return Status::E_OK; } Status UtdClient::IsUtd(std::string typeId, bool &result) { + if (typeId.empty() || typeId.size() > MAX_UTD_LENGTH) { + result = false; + return Status::E_INVALID_PARAMETERS; + } + if (typeId[0] == '.' || find(typeId.begin(), typeId.end(), '/') != typeId.end()) { + result = false; + return Status::E_OK; + } + constexpr const char *preSetTypeIdRegexRule = + R"(^(general\.|openharmony\.|org\.|com\.|macos\.|debian\.|redhat\.|io\.|de\.|net\.)[a-z0-9-\.]+(\-[a-z0-9-]+)*$)"; + if (std::regex_match(typeId, std::regex(preSetTypeIdRegexRule))) { + result = true; + return Status::E_OK; + } + constexpr const char *customUtdRegexRule = + R"(^([A-Za-z]\w*)(\.\w+)+(\.[A-Za-z\d-]+)+)"; + if (std::regex_match(typeId, std::regex(customUtdRegexRule))) { + result = true; + return Status::E_OK; + } + result = false; + LOG_ERROR(UDMF_CLIENT, "is not utd"); return Status::E_OK; } Status UtdClient::GetUniformDataTypesByFilenameExtension(const std::string &fileExtension, std::vector &typeIds, const std::string &belongsTo) { + if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo."); + return Status::E_INVALID_PARAMETERS; + } + if (!IsValidFileExtension(fileExtension)) { + LOG_ERROR(UDMF_CLIENT, "invalid fileExtension."); + return Status::E_INVALID_PARAMETERS; + } + + std::string lowerFileExtension = fileExtension; + std::transform(lowerFileExtension.begin(), lowerFileExtension.end(), lowerFileExtension.begin(), ::tolower); + std::vector typeIdsInCfg; + { + std::shared_lock guard(utdMutex_); + for (const auto &utdTypeCfg : descriptorCfgs_) { + for (auto fileEx : utdTypeCfg.filenameExtensions) { + std::transform(fileEx.begin(), fileEx.end(), fileEx.begin(), ::tolower); + if (fileEx == lowerFileExtension) { + typeIdsInCfg.push_back(utdTypeCfg.typeId); + break; + } + } + } + } + typeIds.clear(); + for (const auto &typeId : typeIdsInCfg) { + // the find typeId is not belongsTo to the belongsTo. + if (belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && + !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { + continue; + } + typeIds.emplace_back(typeId); + } + if (typeIds.empty()) { + typeIds.emplace_back(FlexibleType::GenFlexibleUtd("", lowerFileExtension, belongsTo)); + } return Status::E_OK; } std::string UtdClient::GetTypeIdFromCfg(const std::string &mimeType) { + std::shared_lock guard(utdMutex_); + for (const auto &utdTypeCfg : descriptorCfgs_) { + for (auto mime : utdTypeCfg.mimeTypes) { + std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); + if (mime == mimeType) { + return utdTypeCfg.typeId; + } + } + } + if (mimeType.empty() || mimeType.back() != '*') { + return ""; + } + std::string prefixType = mimeType.substr(0, mimeType.length() - 1); + for (const auto &utdTypeCfg : descriptorCfgs_) { + for (auto mime : utdTypeCfg.mimeTypes) { + std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); + if (mime.rfind(prefixType, 0) == 0 && utdTypeCfg.belongingToTypes.size() > 0) { + return utdTypeCfg.belongingToTypes[0]; + } + } + } return ""; } std::vector UtdClient::GetTypeIdsFromCfg(const std::string &mimeType) { + bool prefixMatch = false; + std::string prefixType; + if (!mimeType.empty() && mimeType.back() == '*') { + prefixType = mimeType.substr(0, mimeType.length() - 1); + prefixMatch = true; + } std::vector typeIdsInCfg; + + std::shared_lock guard(utdMutex_); + for (const auto &utdTypeCfg : descriptorCfgs_) { + for (auto mime : utdTypeCfg.mimeTypes) { + std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); + if ((mime == mimeType) || (prefixMatch && mime.rfind(prefixType, 0) == 0)) { + typeIdsInCfg.push_back(utdTypeCfg.typeId); + break; + } + } + } return typeIdsInCfg; } @@ -95,6 +328,30 @@ void UtdClient::SubscribeUtdChange() Status UtdClient::GetUniformDataTypesByMIMEType(const std::string &mimeType, std::vector &typeIds, const std::string &belongsTo) { + if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo."); + return Status::E_INVALID_PARAMETERS; + } + if (!IsValidMimeType(mimeType)) { + LOG_ERROR(UDMF_CLIENT, "invalid mimeType."); + return Status::E_INVALID_PARAMETERS; + } + + std::string lowerMimeType = mimeType; + std::transform(lowerMimeType.begin(), lowerMimeType.end(), lowerMimeType.begin(), ::tolower); + std::vector typeIdsInCfg = GetTypeIdsFromCfg(lowerMimeType); + typeIds.clear(); + for (const auto &typeId : typeIdsInCfg) { + // the find typeId is not belongsTo to the belongsTo. + if (belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && + !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { + continue; + } + typeIds.emplace_back(typeId); + } + if (typeIds.empty()) { + typeIds.emplace_back(FlexibleType::GenFlexibleUtd(lowerMimeType, "", belongsTo)); + } return Status::E_OK; } } // namespace UDMF diff --git a/udmf/adapter/framework/innerkitsimpl/client/utd_client.h b/udmf/adapter/framework/innerkitsimpl/client/utd_client.h index 2da4ec4b23cc14fd4237f19f091dab1b379d127a..5f31a7d838943a357637563d0bde5e265380452b 100644 --- a/udmf/adapter/framework/innerkitsimpl/client/utd_client.h +++ b/udmf/adapter/framework/innerkitsimpl/client/utd_client.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 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 diff --git a/udmf/adapter/framework/innerkitsimpl/common/unified_meta.cpp b/udmf/adapter/framework/innerkitsimpl/common/unified_meta.cpp index 417432d18637153d1b8fa790f9bd17b62ae00cdf..578f3d6726b952b41a13e6d8f47cc482cbf7829b 100644 --- a/udmf/adapter/framework/innerkitsimpl/common/unified_meta.cpp +++ b/udmf/adapter/framework/innerkitsimpl/common/unified_meta.cpp @@ -648,6 +648,28 @@ bool UnifiedDataUtils::IsPersist(const std::string &intention) return IsPersist(GetIntentionByString(intention)); } +bool UnifiedDataUtils::IsPersist(const int32_t &visibility) +{ + return visibility >= static_cast(VISIBILITY_ALL) && visibility < static_cast(VISIBILITY_BUTT); +} + +bool UnifiedDataUtils::IsFileMangerIntention(const std::string &intention) +{ + Intention optionIntention = GetIntentionByString(intention); + if (optionIntention == UD_INTENTION_SYSTEM_SHARE || + optionIntention == UD_INTENTION_MENU || + optionIntention == UD_INTENTION_PICKER) { + return true; + } + return false; +} + +std::string UnifiedDataUtils::FindIntentionMap(const Intention &queryIntention) +{ + auto find = UD_INTENTION_MAP.find(queryIntention); + return find == UD_INTENTION_MAP.end() ? "" : find->second; +} + Intention UnifiedDataUtils::GetIntentionByString(const std::string &intention) { for (const auto &it : UD_INTENTION_MAP) { @@ -658,23 +680,85 @@ Intention UnifiedDataUtils::GetIntentionByString(const std::string &intention) return UD_INTENTION_BUTT; } -bool UnifiedDataUtils::IsValidOptions(const std::string &key, std::string &intention) +bool UnifiedDataUtils::IsValidOptions(UnifiedKey &key, const std::string &intention, + const std::string &validIntention) { - UnifiedKey unifiedKey(key); - auto isValidKey = unifiedKey.IsValid(); - if (key.empty() && IsPersist(intention)) { - return true; + if (key.key.empty() && intention.empty()) { + return false; } - if (intention.empty() && isValidKey && IsPersist(unifiedKey.intention)) { - return true; + bool isIntentionValid = intention.empty() || intention == validIntention; + if (!isIntentionValid) { + return false; } - if (isValidKey && unifiedKey.intention == intention && IsPersist(intention)) { - intention = ""; - return true; + bool isValidKey = key.key.empty() || (key.IsValid() && key.intention == validIntention); + if (!isValidKey) { + return false; + } + return true; +} + +bool UnifiedDataUtils::IsValidOptions(UnifiedKey &key, const std::string &intention) +{ + if (key.key.empty() && intention.empty()) { + return false; + } + + bool isIntentionValid = intention.empty() || IsPersist(intention); + if (!isIntentionValid) { + return false; + } + + bool isValidKey = key.key.empty() || (key.IsValid() && IsPersist(key.intention)); + if (!isValidKey) { + return false; + } + + if (!key.key.empty() && !intention.empty()) { + return key.intention == intention; + } + return true; +} + +bool UnifiedDataUtils::IsValidOptionsNonDrag(UnifiedKey &key, const std::string &intention) +{ + if (IsValidOptions(key, intention)) { + return !key.key.empty() || intention == UD_INTENTION_MAP.at(Intention::UD_INTENTION_DATA_HUB); } return false; } +std::string UnifiedDataUtils::GetBelongsToFileType(const std::string &utdId) +{ + if (utdId.empty() || utdId == "general.html" || utdId == "general.plain-text") { + LOG_ERROR(UDMF_FRAMEWORK, "The utdId is empty or the utdId is general.html or general.plain-text"); + return ""; + } + std::shared_ptr descriptor; + UtdClient::GetInstance().GetTypeDescriptor(utdId, descriptor); + if (descriptor == nullptr) { + LOG_INFO(UDMF_FRAMEWORK, "The descriptor is null"); + return ""; + } + for (const auto &type : FILE_SUB_TYPES) { + bool isSpecificType = false; + descriptor->BelongsTo(type, isSpecificType); + if (isSpecificType) { + return type; + } + } + if (!descriptor->GetFilenameExtensions().empty()) { + LOG_INFO(UDMF_FRAMEWORK, "The type descriptor has file extensions"); + return "general.file"; + } + LOG_INFO(UDMF_FRAMEWORK, "Return empty"); + return ""; +} + +bool UnifiedDataUtils::IsFilterFileType(const std::string &type) +{ + return std::find(FILE_SUB_TYPES.begin(), FILE_SUB_TYPES.end(), type) != FILE_SUB_TYPES.end(); +} + std::shared_ptr ObjectUtils::ConvertToObject(UDDetails &details) { Object object; diff --git a/udmf/bundle.json b/udmf/bundle.json index 742654f22937504b71adb3b378cdf6139ad0f9a7..531e200bbe0e138cf50033eeeb217bd0a16f850d 100644 --- a/udmf/bundle.json +++ b/udmf/bundle.json @@ -16,6 +16,7 @@ "SystemCapability.DistributedDataManager.UDMF.Core" ], "features": [ + "udmf_feature_upgrade_skia" ], "adapted_system_type": [ "standard" @@ -41,16 +42,17 @@ "samgr", "app_file_service", "os_account", - "selinux_adapter" - ], - "third_party": [ - "bounds_checking_function" + "selinux_adapter", + "libuv", + "runtime_core" ] }, "build": { "sub_component": [ "//foundation/distributeddatamgr/udmf:udmf_packages", - "//foundation/distributeddatamgr/udmf/interfaces/components:udmfcomponents" + "//foundation/distributeddatamgr/udmf/interfaces/components:udmfcomponents", + "//foundation/distributeddatamgr/udmf/conf:utd_conf", + "//foundation/distributeddatamgr/udmf/interfaces/ani:udmf_data_ani" ], "inner_kits": [ { @@ -165,11 +167,18 @@ }, { "name": "//foundation/distributeddatamgr/udmf/interfaces/jskits:intelligence_napi", + "header": { + "header_files": [], + "header_base":"//foundation/distributeddatamgr/udmf/interfaces/jskits/intelligence" + } + }, + { + "name": "//foundation/distributeddatamgr/udmf/interfaces/innerkits/aipcore:aip_core_mgr_static", "header": { "header_files": [ "i_aip_core_manager.h" ], - "header_base":"//foundation/distributeddatamgr/udmf/interfaces/jskits/intelligence" + "header_base":"//foundation/distributeddatamgr/udmf/interfaces/innerkits/aipcore" } }, { @@ -185,6 +194,24 @@ "header_files": [], "header_base":"//foundation/distributeddatamgr/udmf/interfaces/cj/include" } + }, + { + "name": "//foundation/distributeddatamgr/udmf/interfaces/ani:unifieddatachannel_ani", + "header": { + "header_files": [ + "unifieddatachannel_ani.h" + ], + "header_base":"//foundation/distributeddatamgr/udmf/interfaces/ani/native/include" + } + }, + { + "name": "//foundation/distributeddatamgr/udmf/interfaces/innerkits:pixelmap_wrapper", + "header": { + "header_files": [ + "pixelmap_wrapper.h" + ], + "header_base":"//foundation/distributeddatamgr/udmf/interfaces/innerkits/dynamic" + } } ], "test": [ diff --git a/udmf/conf/BUILD.gn b/udmf/conf/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..c1eda704cae69a413a908e8ee25ee812cfb8b8b9 --- /dev/null +++ b/udmf/conf/BUILD.gn @@ -0,0 +1,22 @@ +# Copyright (c) 2025 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("//build/ohos_var.gni") +import("//foundation/distributeddatamgr/udmf/udmf.gni") + +ohos_prebuilt_etc("utd_conf") { + source = "uniform_data_types.json" + relative_install_dir = "utd/conf" + subsystem_name = "distributeddatamgr" + part_name = "udmf" +} diff --git a/udmf/conf/uniform_data_types.json b/udmf/conf/uniform_data_types.json new file mode 100644 index 0000000000000000000000000000000000000000..519c1d01fbb6957568fa03dad4edf444a7caf264 --- /dev/null +++ b/udmf/conf/uniform_data_types.json @@ -0,0 +1,6580 @@ +{ + "UniformDataTypeDeclarations": [ + { + "typeId": "general.entity", + "belongingToTypes": [], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for physical hierarchy.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.object", + "belongingToTypes": [], + "filenameExtensions": [], + "mimeTypes": [ + "*/*" + ], + "description": "Base type for logical hierarchy.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.composite-object", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for mixed object. For example, a PDF file contains both text and special formatting data.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.text", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [ + "text/*" + ], + "description": "Base type for all text.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.plain-text", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".txt", + ".text" + ], + "mimeTypes": [ + "text/plain" + ], + "description": "Text of unspecified encoding, with no markup.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_txt" + }, + { + "typeId": "general.html", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".html", + ".htm" + ], + "mimeTypes": [ + "text/html" + ], + "description": "HTML text.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_html" + }, + { + "typeId": "general.hyperlink", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Hyperlink.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.xml", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".xml" + ], + "mimeTypes": [ + "text/xml" + ], + "description": "XML text.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_xml" + }, + { + "typeId": "com.real.smil", + "belongingToTypes": [ + "general.xml" + ], + "filenameExtensions": [ + ".smil" + ], + "mimeTypes": [ + "application/smil" + ], + "description": "Real synchronized multimedia integration language.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.source-code", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Generic source code.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.script", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for scripting language source code.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.shell-script", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".sh", + ".command" + ], + "mimeTypes": [ + "text/x-shellscript" + ], + "description": "Shell script.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.csh-script", + "belongingToTypes": [ + "general.shell-script" + ], + "filenameExtensions": [ + ".csh" + ], + "mimeTypes": [ + "text/x-csh" + ], + "description": "C-shell script.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.perl-script", + "belongingToTypes": [ + "general.shell-script" + ], + "filenameExtensions": [ + ".pl", + ".pm" + ], + "mimeTypes": [ + "text/x-perl-script" + ], + "description": "Perl script.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.php-script", + "belongingToTypes": [ + "general.shell-script" + ], + "filenameExtensions": [ + ".php", + ".php3", + ".php4", + ".ph3", + ".ph4", + ".phtml" + ], + "mimeTypes": [ + "text/x-php-script", + "text/php", + "application/php" + ], + "description": "PHP script.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.python-script", + "belongingToTypes": [ + "general.shell-script" + ], + "filenameExtensions": [ + ".py" + ], + "mimeTypes": [ + "text/x-python-script" + ], + "description": "Python script.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ruby-script", + "belongingToTypes": [ + "general.shell-script" + ], + "filenameExtensions": [ + ".rb", + ".rbw" + ], + "mimeTypes": [ + "text/ruby-script" + ], + "description": "Ruby script.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.type-script", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".ts" + ], + "mimeTypes": [], + "description": "TypeScript source code.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.java-script", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".js", + ".jscript", + ".javascript" + ], + "mimeTypes": [ + "text/javascript" + ], + "description": "JavaScript source code.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.c-header", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".h" + ], + "mimeTypes": [ + "text/x-chdr" + ], + "description": "C header file.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.c-source", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".c" + ], + "mimeTypes": [ + "text/x-csrc" + ], + "description": "C source code.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.c-plus-plus-header", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".hpp", + ".h++", + ".hxx", + ".hh" + ], + "mimeTypes": [ + "text/x-c++hdr" + ], + "description": "C++ header file.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.c-plus-plus-source", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".cp", + ".cpp", + ".c++", + ".cc", + ".cxx" + ], + "mimeTypes": [ + "text/x-c++src" + ], + "description": "C++ source code.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.java-source", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".java", + ".jav" + ], + "mimeTypes": [ + "text/x-java" + ], + "description": "Java source code.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.markdown", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".md", + ".markdown", + ".markdn", + ".mdown" + ], + "mimeTypes": [ + "text/markdown" + ], + "description": "Markdown format.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ebook", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for ebook.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.epub", + "belongingToTypes": [ + "general.ebook" + ], + "filenameExtensions": [ + ".epub" + ], + "mimeTypes": [ + "application/epub+zip" + ], + "description": "Electronic publication (EPUB) format.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.amazon.azw", + "belongingToTypes": [ + "general.ebook" + ], + "filenameExtensions": [ + ".azw" + ], + "mimeTypes": [ + "application/vnd.amazon.ebook" + ], + "description": "AZW ebook.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.amazon.azw3", + "belongingToTypes": [ + "general.ebook" + ], + "filenameExtensions": [ + ".azw3" + ], + "mimeTypes": [ + "application/vnd.amazon.mobi8-ebook", + "application/x-mobi8-ebook" + ], + "description": "AZW3 ebook.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.amazon.kfx", + "belongingToTypes": [ + "general.ebook" + ], + "filenameExtensions": [ + ".kfx" + ], + "mimeTypes": [], + "description": "KFX ebook.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.amazon.mobi", + "belongingToTypes": [ + "general.ebook" + ], + "filenameExtensions": [ + ".mobi" + ], + "mimeTypes": [ + "application/x-mobipocket-ebook" + ], + "description": "MOBI ebook.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.media", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for media.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.image", + "belongingToTypes": [ + "general.media" + ], + "filenameExtensions": [], + "mimeTypes": [ + "image/*" + ], + "description": "Base type for images.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "general.jpeg", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".jpg", + ".jpeg", + ".jpe" + ], + "mimeTypes": [ + "image/jpeg" + ], + "description": "JPEG image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "general.png", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".png" + ], + "mimeTypes": [ + "image/png" + ], + "description": "PNG image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "general.raw-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for digital camera raw image formats.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "general.tiff", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".tif", + ".tiff" + ], + "mimeTypes": [ + "image/tiff" + ], + "description": "TIFF image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "com.microsoft.bmp", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".bmp", + ".bm" + ], + "mimeTypes": [ + "image/bmp", + "image/x-ms-bmp" + ], + "description": "Windows bitmap image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "com.microsoft.ico", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".ico" + ], + "mimeTypes": [ + "image/ico", + "image/x-icon" + ], + "description": "Windows icon image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "com.adobe.photoshop-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".psd" + ], + "mimeTypes": [ + "image/x-photoshop", + "image/photoshop", + "image/psd", + "application/photoshop" + ], + "description": "Adobe Photoshop document.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "com.adobe.illustrator.ai-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".ai" + ], + "mimeTypes": [], + "description": "Adobe Illustrator document.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "general.fax", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for fax images.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.j2.jfx-fax", + "belongingToTypes": [ + "general.fax" + ], + "filenameExtensions": [ + ".jfx" + ], + "mimeTypes": [], + "description": "J2 fax.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.js.efx-fax", + "belongingToTypes": [ + "general.fax" + ], + "filenameExtensions": [ + ".efx" + ], + "mimeTypes": [ + "image/efax" + ], + "description": "eFax fax.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.xbitmap-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".xbm" + ], + "mimeTypes": [ + "image/x-xbitmap", + "image/x-xbm" + ], + "description": "X bitmap image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.truevision.tga-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".tga" + ], + "mimeTypes": [ + "image/targa", + "image/tga", + "application/tga" + ], + "description": "TGA image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.sgi.sgi-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".sgi" + ], + "mimeTypes": [ + "image/sgi" + ], + "description": "Silicon Graphics image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.ilm.openexr-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".exr" + ], + "mimeTypes": [], + "description": "OpenEXR image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kodak.flashpix.image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".fpx" + ], + "mimeTypes": [ + "image/fpx", + "application/vnd.fpx" + ], + "description": "FlashPix image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.word.doc", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".doc" + ], + "mimeTypes": [ + "application/msword" + ], + "description": "Microsoft Word data.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_doc" + }, + { + "typeId": "com.microsoft.excel.xls", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".xls" + ], + "mimeTypes": [ + "application/vnd.ms-excel" + ], + "description": "Microsoft Excel data.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_xls" + }, + { + "typeId": "com.microsoft.powerpoint.ppt", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".ppt" + ], + "mimeTypes": [ + "application/vnd.ms-powerpoint" + ], + "description": "Microsoft PowerPoint presentation.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.pdf", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".pdf" + ], + "mimeTypes": [ + "application/pdf" + ], + "description": "PDF data.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_pdf" + }, + { + "typeId": "com.adobe.postscript", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".ps" + ], + "mimeTypes": [ + "application/postscript" + ], + "description": "PostScript data.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.encapsulated-postscript", + "belongingToTypes": [ + "com.adobe.postscript" + ], + "filenameExtensions": [ + ".eps" + ], + "mimeTypes": [], + "description": "Encapsulated PostScript.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.video", + "belongingToTypes": [ + "general.media" + ], + "filenameExtensions": [], + "mimeTypes": [ + "video/*" + ], + "description": "Base type for video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "general.avi", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".avi", + ".vfw" + ], + "mimeTypes": [ + "video/avi", + "video/msvideo", + "video/x-msvideo" + ], + "description": "AVI video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "general.mpeg", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".mpg", + ".mpeg", + ".m75", + ".m15", + ".mpe" + ], + "mimeTypes": [ + "video/mpg", + "video/mpeg", + "video/x-mpg", + "video/x-mpeg" + ], + "description": "MPEG-1 or MPEG-2 video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "general.mpeg-4", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".mp4", + ".mp4v", + ".mpeg4" + ], + "mimeTypes": [ + "video/mp4", + "video/mp4v" + ], + "description": "MPEG-4 video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "general.3gpp", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".3gp", + ".3gpp" + ], + "mimeTypes": [ + "video/3gpp" + ], + "description": "3GPP video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "general.3gpp2", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".3g2", + ".3gp2", + ".3gpp2" + ], + "mimeTypes": [ + "video/3gpp2" + ], + "description": "3GPP2 video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "com.microsoft.windows-media-wm", + "belongingToTypes": [ + "general.video", + "com.microsoft.advanced-systems-format" + ], + "filenameExtensions": [ + ".wm" + ], + "mimeTypes": [ + "video/x-ms-wm" + ], + "description": "Windows WM video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "com.microsoft.windows-media-wmv", + "belongingToTypes": [ + "general.video", + "com.microsoft.advanced-systems-format" + ], + "filenameExtensions": [ + ".wmv" + ], + "mimeTypes": [ + "video/x-ms-wmv" + ], + "description": "Windows WMV video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "com.microsoft.windows-media-wmp", + "belongingToTypes": [ + "general.video", + "com.microsoft.advanced-systems-format" + ], + "filenameExtensions": [ + ".wmp" + ], + "mimeTypes": [ + "video/x-ms-wmp" + ], + "description": "Windows WMP video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "com.microsoft.windows-media-wvx", + "belongingToTypes": [ + "general.video", + "com.microsoft.advanced-systems-format" + ], + "filenameExtensions": [ + ".wvx" + ], + "mimeTypes": [ + "video/x-ms-wvx" + ], + "description": "Windows WVX video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "com.microsoft.windows-media-wmx", + "belongingToTypes": [ + "general.video", + "com.microsoft.advanced-systems-format" + ], + "filenameExtensions": [ + ".wmx" + ], + "mimeTypes": [ + "video/x-ms-wmx" + ], + "description": "Windows WMX video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "com.real.realmedia", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".rm" + ], + "mimeTypes": [ + "application/vnd.rn-realmedia" + ], + "description": "RealMedia.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.audio", + "belongingToTypes": [ + "general.media" + ], + "filenameExtensions": [], + "mimeTypes": [ + "audio/*" + ], + "description": "Base type for audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_audio" + }, + { + "typeId": "general.aac", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".aac" + ], + "mimeTypes": [ + "audio/aac" + ], + "description": "AAC audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_audio" + }, + { + "typeId": "general.aiff", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".aiff" + ], + "mimeTypes": [ + "audio/aiff" + ], + "description": "AIFF audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_audio" + }, + { + "typeId": "general.alac", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".alac" + ], + "mimeTypes": [ + "audio/alac" + ], + "description": "ALAC audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_audio" + }, + { + "typeId": "general.flac", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".flac" + ], + "mimeTypes": [ + "audio/flac" + ], + "description": "FLAC audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_flac" + }, + { + "typeId": "general.mp3", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".mp3" + ], + "mimeTypes": [ + "audio/mp3" + ], + "description": "MPEG-3 audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_mp3" + }, + { + "typeId": "general.ogg", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".ogg" + ], + "mimeTypes": [ + "audio/ogg" + ], + "description": "OGG audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_audio" + }, + { + "typeId": "general.pcm", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".pcm" + ], + "mimeTypes": [ + "audio/pcm" + ], + "description": "PCM audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_audio" + }, + { + "typeId": "com.microsoft.advanced-systems-format", + "belongingToTypes": [ + "general.media" + ], + "filenameExtensions": [ + ".asf" + ], + "mimeTypes": [ + "video/x-ms-asf", + "application/vnd.ms-asf" + ], + "description": "Advanced Systems format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.advanced-stream-redirector", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".asx" + ], + "mimeTypes": [ + "video/x-ms-asf" + ], + "description": "Advanced stream redirector", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.windows-media-wma", + "belongingToTypes": [ + "general.audio", + "com.microsoft.advanced-systems-format" + ], + "filenameExtensions": [ + ".wma" + ], + "mimeTypes": [ + "audio/x-ms-wma" + ], + "description": "Windows WMA audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_wma" + }, + { + "typeId": "com.microsoft.waveform-audio", + "belongingToTypes": [ + "general.audio", + "com.microsoft.advanced-systems-format" + ], + "filenameExtensions": [ + ".wav", + ".wave" + ], + "mimeTypes": [ + "audio/wav", + "audio/wave", + "audio/x-wav" + ], + "description": "Waveform audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_wav" + }, + { + "typeId": "com.microsoft.windows-media-wax", + "belongingToTypes": [ + "general.audio", + "com.microsoft.advanced-systems-format" + ], + "filenameExtensions": [ + ".wax" + ], + "mimeTypes": [ + "audio/x-ms-wax" + ], + "description": "Windows WAX audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_audio" + }, + { + "typeId": "general.au-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".au", + ".snd" + ], + "mimeTypes": [ + "audio/basic", + "audio/au", + "audio/snd" + ], + "description": "Au file format.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.aifc-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".aifc", + ".aif", + ".aiff" + ], + "mimeTypes": [ + "audio/x-aiff" + ], + "description": "Audio Interchange File Format.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.digidesign.sd2-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".sd2" + ], + "mimeTypes": [ + "audio/x-sd2" + ], + "description": "Digidesign Sound Designer II audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.real.realaudio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".ram", + ".ra" + ], + "mimeTypes": [ + "audio/vnd.rn-realaudio", + "audio/x-pn-realaudio" + ], + "description": "RealMedia audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.file", + "belongingToTypes": [ + "general.entity" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for file.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.directory", + "belongingToTypes": [ + "general.entity" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for directory.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_folder" + }, + { + "typeId": "general.folder", + "belongingToTypes": [ + "general.directory" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for folder.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_folder" + }, + { + "typeId": "general.symlink", + "belongingToTypes": [ + "general.entity" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for symlink.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.archive", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for an archive of files and directories.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_compress" + }, + { + "typeId": "general.bz2-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".bz2", + ".bzip2" + ], + "mimeTypes": [ + "application/x-bzip2" + ], + "description": "BZip2 archive.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_compress" + }, + { + "typeId": "general.disk-image", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for items mountable as a volume.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_compress" + }, + { + "typeId": "general.tar-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".tar" + ], + "mimeTypes": [ + "application/x-tar", + "application/tar" + ], + "description": "Tar archive.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_compress" + }, + { + "typeId": "general.zip-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".zip" + ], + "mimeTypes": [ + "application/zip" + ], + "description": "Zip archive.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_zip" + }, + { + "typeId": "com.sun.java-archive", + "belongingToTypes": [ + "general.archive", + "general.executable" + ], + "filenameExtensions": [ + ".jar" + ], + "mimeTypes": [ + "application/java-archive" + ], + "description": "Java archive.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_compress" + }, + { + "typeId": "org.gnu.gnu-tar-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".gtar" + ], + "mimeTypes": [ + "application/x-gtar" + ], + "description": "GNU archive.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_compress" + }, + { + "typeId": "org.gnu.gnu-zip-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".gz", + ".gzip" + ], + "mimeTypes": [ + "application/x-gzip", + "application/gzip" + ], + "description": "Gzip archive.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_compress" + }, + { + "typeId": "org.gnu.gnu-zip-tar-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".tgz" + ], + "mimeTypes": [ + "application/x-gtar" + ], + "description": "Gzip tar archive.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_compress" + }, + { + "typeId": "org.openxmlformats.openxml", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Office Open XML.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.wordprocessingml.document", + "belongingToTypes": [ + "general.composite-object", + "org.openxmlformats.openxml" + ], + "filenameExtensions": [ + ".docx" + ], + "mimeTypes": [ + "application/vnd.openxmlformats-officedocument.wordprocessingml.document" + ], + "description": "Office Open XML Document.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.spreadsheetml.sheet", + "belongingToTypes": [ + "general.composite-object", + "org.openxmlformats.openxml" + ], + "filenameExtensions": [ + ".xlsx" + ], + "mimeTypes": [ + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ], + "description": "Office Open XML Workbook.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.presentationml.presentation", + "belongingToTypes": [ + "general.composite-object", + "org.openxmlformats.openxml" + ], + "filenameExtensions": [ + ".pptx" + ], + "mimeTypes": [ + "application/vnd.openxmlformats-officedocument.presentationml.presentation" + ], + "description": "Office Open XML Presentation.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis.opendocument", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Open Document Format for Office Applications.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis.opendocument.text", + "belongingToTypes": [ + "general.composite-object", + "org.oasis.opendocument" + ], + "filenameExtensions": [ + ".odt", + ".fodt" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.text" + ], + "description": "OpenDocument Text.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis.opendocument.spreadsheet", + "belongingToTypes": [ + "general.composite-object", + "org.oasis.opendocument" + ], + "filenameExtensions": [ + ".ods", + ".fods" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.spreadsheet" + ], + "description": "OpenDocument Spreadsheet.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis.opendocument.presentation", + "belongingToTypes": [ + "general.composite-object", + "org.oasis.opendocument" + ], + "filenameExtensions": [ + ".odp", + ".fodp" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.presentation" + ], + "description": "OpenDocument Presentation.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis.opendocument.graphics", + "belongingToTypes": [ + "general.composite-object", + "org.oasis.opendocument" + ], + "filenameExtensions": [ + ".odg", + ".fodg" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.graphics" + ], + "description": "OpenDocument Graphics.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis.opendocument.formula", + "belongingToTypes": [ + "org.oasis.opendocument" + ], + "filenameExtensions": [ + ".odf" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.formula" + ], + "description": "OpenDocument Formulat.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.allume.stuffit-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".sit", + ".sitx" + ], + "mimeTypes": [ + "application/x-stuffit", + "application/x-sit", + "application/stuffit" + ], + "description": "Stuffit archive.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.calendar", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [], + "mimeTypes": [ + "text/calendar" + ], + "description": "Base type for scheduled events.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_calendar" + }, + { + "typeId": "general.vcs", + "belongingToTypes": [ + "general.calendar" + ], + "filenameExtensions": [ + ".vcs" + ], + "mimeTypes": [ + "text/calendar" + ], + "description": "vCalendar type.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ics", + "belongingToTypes": [ + "general.calendar" + ], + "filenameExtensions": [ + ".ics" + ], + "mimeTypes": [ + "text/calendar" + ], + "description": "iCalendar type.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.contact", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for contact information.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.database", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for databases.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.message", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for messages.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.executable", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for executable data.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.portable-executable", + "belongingToTypes": [ + "general.executable" + ], + "filenameExtensions": [ + ".exe", + ".dll" + ], + "mimeTypes": [ + "application/vnd.microsoft.portable-executable" + ], + "description": "Microsoft Windows application.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.sun.java-class", + "belongingToTypes": [ + "general.executable" + ], + "filenameExtensions": [ + ".class" + ], + "mimeTypes": [], + "description": "Java class.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.vcard", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [ + ".vcf", + ".vcard" + ], + "mimeTypes": [ + "text/vcard", + "text/x-vcard" + ], + "description": "Base type for electronic business card.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.navigation", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for navigation.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.location", + "belongingToTypes": [ + "general.navigation" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Navigation location.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.font", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for fonts.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.truetype-font", + "belongingToTypes": [ + "general.font" + ], + "filenameExtensions": [ + ".ttf" + ], + "mimeTypes": [ + "font/ttf" + ], + "description": "TrueType font.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.truetype-collection-font", + "belongingToTypes": [ + "general.font" + ], + "filenameExtensions": [ + ".ttc" + ], + "mimeTypes": [ + "font/collection" + ], + "description": "TrueType collection font.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.opentype-font", + "belongingToTypes": [ + "general.font" + ], + "filenameExtensions": [ + ".otf" + ], + "mimeTypes": [ + "font/otf" + ], + "description": "OpenType font.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.postscript-font", + "belongingToTypes": [ + "general.font" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "PostScript font.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.form", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenHarmony system defined form.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.app-item", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenHarmony system defined app item.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.pixel-map", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenHarmony system defined pixel map.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "openharmony.atomic-service", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenHarmony system defined atomic service.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.package", + "belongingToTypes": [ + "general.directory" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenHarmony system defined package (that is, a directory presented to the user as a file).", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.hap", + "belongingToTypes": [ + "openharmony.package" + ], + "filenameExtensions": [ + ".hap" + ], + "mimeTypes": [], + "description": "OpenHarmony system defined ability package.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.hdoc", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".hdoc" + ], + "mimeTypes": [], + "description": "OpenHarmony system AppNotepad data format.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.hinote", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".hinote" + ], + "mimeTypes": [], + "description": "OpenHarmony system Notes data format.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.styled-string", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenHarmony system defined styled string.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.want", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenHarmony system defined Want.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.moving-photo", + "belongingToTypes": [ + "general.media" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenHarmony system defined moving photo.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "macos.dmg", + "belongingToTypes": [ + "general.disk-image" + ], + "filenameExtensions": [ + ".dmg" + ], + "mimeTypes": [ + "application/x-apple-diskimage" + ], + "description": "Apple Disk Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "debian.deb", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".deb", + ".udeb" + ], + "mimeTypes": [ + "application/x-debian-package", + "application/vnd.debian.binary-package" + ], + "description": "OpenHarmony system defined Want.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ofd", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".ofd" + ], + "mimeTypes": [], + "description": "Open fixed-layout document, a national standard for format documents", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.opg", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".opg" + ], + "mimeTypes": [], + "description": "OPG archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.tex", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for TeX source code", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.css", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".css" + ], + "mimeTypes": [ + "text/css" + ], + "description": "Cascading style sheets", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.vob", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".vob" + ], + "mimeTypes": [ + "video/mpeg", + "video/x-ms-vob" + ], + "description": "", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.dif-video", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".dif" + ], + "mimeTypes": [ + "video/dv" + ], + "description": "Digital interface format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.dv-video", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".dv" + ], + "mimeTypes": [ + "video/dv" + ], + "description": "DV video", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.flc-animation", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".fli", + ".flc" + ], + "mimeTypes": [ + "video/fli", + "video/flc" + ], + "description": "FLIC file format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mng", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".mng" + ], + "mimeTypes": [ + "video/x-mng" + ], + "description": "Multiple-image network graphics", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mpegurl-video", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".mxu", + ".m4u" + ], + "mimeTypes": [ + "video/vnd.mpegurl" + ], + "description": "Video playlist", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ts", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".ts" + ], + "mimeTypes": [ + "video/mp2ts", + "video/mp2t" + ], + "description": "MPEG transport stream", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.amr", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".amr" + ], + "mimeTypes": [ + "audio/amr" + ], + "description": "The adaptive multi-rate audio codecs", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.amr-wb", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".awb" + ], + "mimeTypes": [ + "audio/amr-wb" + ], + "description": "Adaptive multi-rate wideband", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.gsm", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".gsm" + ], + "mimeTypes": [ + "audio/x-gsm", + "audio/gsm" + ], + "description": "Global system form mobile audio format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.imy", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".imy" + ], + "mimeTypes": [ + "audio/imelody" + ], + "description": "Non-polyphonic ringtone exchange object format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.kar", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".kar" + ], + "mimeTypes": [ + "audio/midi" + ], + "description": "Karaoke MIDI file format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mpegurl-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".m3u" + ], + "mimeTypes": [ + "audio/mpegurl", + "audio/x-mpegurl" + ], + "description": "Audio playlist", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mpeg-4-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".m4a", + ".m4b" + ], + "mimeTypes": [ + "audio/mpeg" + ], + "description": "Audio-only MPEG-4 file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.midi-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".mid", + ".midi" + ], + "mimeTypes": [ + "audio/midi" + ], + "description": "MIDI audio", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mp2", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".mp2" + ], + "mimeTypes": [ + "audio/mpeg" + ], + "description": "MPEG-1 audio layer II or MPEG-2 audio layer II", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mpeg-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".mpga" + ], + "mimeTypes": [ + "audio/mpeg" + ], + "description": "MPEG audio format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mxmf", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".mxmf" + ], + "mimeTypes": [ + "audio/mobile-xmf" + ], + "description": "Mobile XMF audio format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ota", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".ota" + ], + "mimeTypes": [ + "audio/midi" + ], + "description": "OTA ringtone file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.pls", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".pls" + ], + "mimeTypes": [ + "audio/x-scpls" + ], + "description": "Multimedia playlist format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.rtttl", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".rtttl" + ], + "mimeTypes": [ + "audio/midi" + ], + "description": "Ring tone transfer language file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.psid", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".sid", + ".psid" + ], + "mimeTypes": [ + "audio/prs.sid" + ], + "description": "SID audio", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ulaw-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".au", + ".ulw", + ".snd" + ], + "mimeTypes": [ + "audio/basic", + "audio/au", + "audio/snd" + ], + "description": "uLaw audio", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.xmf", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".xmf" + ], + "mimeTypes": [ + "audio/midi" + ], + "description": "Extensible music file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.gif", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".gif" + ], + "mimeTypes": [ + "image/gif" + ], + "description": "GIF image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.djvu-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".djv", + ".djvu" + ], + "mimeTypes": [ + "image/vnd.djvu" + ], + "description": "Djvu image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.jng-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".jng" + ], + "mimeTypes": [ + "image/x-jng" + ], + "description": "JPEG network graphic", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.pcx-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".pcx" + ], + "mimeTypes": [ + "image/vnd.zbrush.pcx" + ], + "description": "Paintbrush bitmap image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.pbm-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".pbm" + ], + "mimeTypes": [ + "image/x-portable-bitmap" + ], + "description": "Portable bitmap image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.pgm-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".pgm" + ], + "mimeTypes": [ + "image/x-portable-graymap" + ], + "description": "Portable gray map image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.pnm-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".pnm" + ], + "mimeTypes": [ + "image/x-portable-anymap" + ], + "description": "Portable any map image file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ppm-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".ppm" + ], + "mimeTypes": [ + "image/x-portable-pixmap" + ], + "description": "Portable pixmap image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.rgb-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".rgb" + ], + "mimeTypes": [ + "image/x-rgb" + ], + "description": "RGB bitmap", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.svg-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".svg", + ".svgz" + ], + "mimeTypes": [ + "image/svg+xml" + ], + "description": "Scalable vector graphic", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.wbmp-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".wbmp" + ], + "mimeTypes": [ + "image/vnd.wap.wbmp" + ], + "description": "Wireless bitmap image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.xpixmap-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".xpm" + ], + "mimeTypes": [ + "image/x-xpixmap" + ], + "description": "X11 pixmap graphic", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.xwindowdump-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".xwd" + ], + "mimeTypes": [ + "image/x-xwindowdump" + ], + "description": "X windows dump image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.heif", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".heif", + ".heifs", + ".hif" + ], + "mimeTypes": [ + "image/heif" + ], + "description": "High efficiency image format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.heic", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".heic", + ".heics" + ], + "mimeTypes": [ + "image/heic" + ], + "description": "High efficiency image format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.virtual-cd", + "belongingToTypes": [ + "general.disk-image" + ], + "filenameExtensions": [ + ".vcd" + ], + "mimeTypes": [ + "application/x-cdlink" + ], + "description": "Virtual CD", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.boo-source", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".boo" + ], + "mimeTypes": [ + "text/x-boo" + ], + "description": "Boo source code", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.d-source", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".d" + ], + "mimeTypes": [ + "text/x-dsrc" + ], + "description": "D source code file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.html-component", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".htc" + ], + "mimeTypes": [ + "text/x-component" + ], + "description": "HTML component", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.pascal-source", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".p", + ".pas" + ], + "mimeTypes": [ + "text/x-pascal" + ], + "description": "Pascal source code", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.haskell-script", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".hs" + ], + "mimeTypes": [ + "text/x-haskell" + ], + "description": "Haskell script", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.literate-haskell-script", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".lhs" + ], + "mimeTypes": [ + "text/x-literate-haskell" + ], + "description": "Literate haskell script", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.tcl-script", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".tcl" + ], + "mimeTypes": [ + "text/x-tcl" + ], + "description": "Tcl script", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.asc-text", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".asc" + ], + "mimeTypes": [ + "text/plain" + ], + "description": "ASCII text file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.portable-object", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".po" + ], + "mimeTypes": [ + "text/plain" + ], + "description": "Portable object", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.rich-text", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".rtf", + ".rtx" + ], + "mimeTypes": [ + "text/rtf", + "text/richtext" + ], + "description": "Rich text format file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.delimited-values-text", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for delimited-values text", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.comma-separated-values-text", + "belongingToTypes": [ + "general.delimited-values-text" + ], + "filenameExtensions": [ + ".csv" + ], + "mimeTypes": [ + "text/csv" + ], + "description": "Comma-separated values file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.diff", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".diff" + ], + "mimeTypes": [ + "text/plain" + ], + "description": "Patch file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.setext", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".etx" + ], + "mimeTypes": [ + "text/x-setext" + ], + "description": "Structure enhanced Text", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.gcd", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".gcd" + ], + "mimeTypes": [ + "text/x-pcs-gcd" + ], + "description": "General content descriptor", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.tab-separated-values-text", + "belongingToTypes": [ + "general.delimited-values-text" + ], + "filenameExtensions": [ + ".tsv" + ], + "mimeTypes": [ + "text/tab-separated-values" + ], + "description": "Tab-Separated values file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.p7r", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".p7r" + ], + "mimeTypes": [ + "application/x-pkcs7-certreqresp" + ], + "description": "Certificate request response file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.pem", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".pem" + ], + "mimeTypes": [ + "application/x-pem-file" + ], + "description": "Privacy enhanced mail certificate", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.chess-pgn", + "belongingToTypes": [ + "general.plain-text" + ], + "filenameExtensions": [ + ".pgn" + ], + "mimeTypes": [ + "application/x-chess-pgn", + "application/vnd.chess-pgn" + ], + "description": "Portable game notation file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.lha-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".lha" + ], + "mimeTypes": [ + "application/x-lha" + ], + "description": "LHARC compressed archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.lzh-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".lzh" + ], + "mimeTypes": [ + "application/x-lzh" + ], + "description": "LZH compressed file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.lzx-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".lzx" + ], + "mimeTypes": [ + "application/x-lzx" + ], + "description": "LZX compressed archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.taz-archive", + "belongingToTypes": [ + "general.tar-archive" + ], + "filenameExtensions": [ + ".taz", + ".tar.z", + ".tz" + ], + "mimeTypes": [ + "application/x-gtar" + ], + "description": "Tar zipped file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.shar-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".shar" + ], + "mimeTypes": [ + "application/x-shar" + ], + "description": "Unix Shar archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.cpio-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".cpio" + ], + "mimeTypes": [ + "application/x-cpio" + ], + "description": "Unix CPIO archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.web-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".mht", + ".mhtml" + ], + "mimeTypes": [ + "application/x-mimearchive" + ], + "description": "MHTML web archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ustar", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".ustar" + ], + "mimeTypes": [ + "application/x-ustar" + ], + "description": "Uniform standard tape archive format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mathml", + "belongingToTypes": [ + "general.xml" + ], + "filenameExtensions": [ + ".mml" + ], + "mimeTypes": [ + "text/mathml", + "application/mathml+xml" + ], + "description": "Mathematical markup language file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.xhtml", + "belongingToTypes": [ + "general.xml" + ], + "filenameExtensions": [ + ".xhtml" + ], + "mimeTypes": [ + "application/xhtml+xml" + ], + "description": "XHTML", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.rss", + "belongingToTypes": [ + "general.xml" + ], + "filenameExtensions": [ + ".rss" + ], + "mimeTypes": [ + "application/rss+xml" + ], + "description": "Rich site summary", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.rdf", + "belongingToTypes": [ + "general.xml" + ], + "filenameExtensions": [ + ".rdf" + ], + "mimeTypes": [ + "application/rdf+xml" + ], + "description": "Resource description framework file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.cad", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for computer-aided design", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.iges", + "belongingToTypes": [ + "general.cad" + ], + "filenameExtensions": [ + ".iges", + ".igs" + ], + "mimeTypes": [ + "model/iges" + ], + "description": "IGES drawing", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.octet-stream", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [ + "application/octet-stream" + ], + "description": "Arbitrary binary data", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.iso", + "belongingToTypes": [ + "general.disk-image" + ], + "filenameExtensions": [ + ".iso" + ], + "mimeTypes": [ + "application/x-iso9660-image" + ], + "description": "Disc image file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mesh-model", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [ + ".msh", + ".mesh", + ".silo" + ], + "mimeTypes": [ + "model/mesh" + ], + "description": "3D mesh model", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.certificate", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for security certificate", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.c-object", + "belongingToTypes": [ + "general.executable" + ], + "filenameExtensions": [ + ".o" + ], + "mimeTypes": [ + "application/x-object" + ], + "description": "Compiled C object file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.dvi", + "belongingToTypes": [ + "general.tex" + ], + "filenameExtensions": [ + ".dvi" + ], + "mimeTypes": [ + "application/x-dvi" + ], + "description": "Device independent format file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.cer-certificate", + "belongingToTypes": [ + "general.certificate" + ], + "filenameExtensions": [ + ".cer" + ], + "mimeTypes": [ + "application/pkix-cert" + ], + "description": "Internet security certificate", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.crt-certificate", + "belongingToTypes": [ + "general.certificate" + ], + "filenameExtensions": [ + ".crt" + ], + "mimeTypes": [ + "application/x-x509-ca-cert", + "application/x-x509-server-cert", + "application/x-x509-user-cert" + ], + "description": "Security Certificate", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.crl-certificate", + "belongingToTypes": [ + "general.certificate" + ], + "filenameExtensions": [ + ".crl" + ], + "mimeTypes": [ + "application/x-pkix-crl" + ], + "description": "Certificate revocation list file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.prn", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".prn" + ], + "mimeTypes": [], + "description": "Print to file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.chart", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".odc" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.chart" + ], + "description": "Open Document chart", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.text-master", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".odm" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.text-master" + ], + "description": "Open Document text master", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.text-web", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".oth" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.text-web" + ], + "description": "Open Document HTML template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.database", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.database" + ], + "filenameExtensions": [ + ".odb" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.database" + ], + "description": "Open Document database", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.image", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.image" + ], + "filenameExtensions": [ + ".odi" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.image" + ], + "description": "Open Document image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.formula-template", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".otf" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.formula-template" + ], + "description": "Open Document formula template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.chart-template", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".otc" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.chart-template" + ], + "description": "Open Document chart template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.presentation-template", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".otp" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.presentation-template" + ], + "description": "Open Document presentation template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.image-template", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.image" + ], + "filenameExtensions": [ + ".oti" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.image-template" + ], + "description": "Open Document image template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.graphics-template", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".otg" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.graphics-template" + ], + "description": "Open Document graphics template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.spreadsheet-template", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".ots" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.spreadsheet-template" + ], + "description": "Open Document spreadsheet template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.text-template", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".ott" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.text-template" + ], + "description": "Open Document text template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.word.dot", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dot" + ], + "mimeTypes": [ + "application/msword" + ], + "description": "Microsoft Word document template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.powerpoint.pps", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".pps" + ], + "mimeTypes": [ + "application/vnd.ms-powerpoint" + ], + "description": "Microsoft PowerPoint slide show", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.powerpoint.pot", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".pot" + ], + "mimeTypes": [ + "application/vnd.ms-powerpoint" + ], + "description": "Microsoft PowerPoint Template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.excel.xlt", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".xlt" + ], + "mimeTypes": [ + "application/vnd.ms-excel" + ], + "description": "Microsoft Excel spreadsheet template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.visio.vsd", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".vsd" + ], + "mimeTypes": [ + "application/vnd.visio" + ], + "description": "Microsoft Office Visio 2003-2010 drawing", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.drawingml.visio", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object" + ], + "filenameExtensions": [ + ".vsdx" + ], + "mimeTypes": [ + "application/vnd.openxmlformats-officedocument.drawingml.drawing" + ], + "description": "Microsoft Visio drawing", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.drawingml.template", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object" + ], + "filenameExtensions": [ + ".vstx" + ], + "mimeTypes": [], + "description": "Microsoft Visio drawing template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.drawingml.visio.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object" + ], + "filenameExtensions": [ + ".vsdm" + ], + "mimeTypes": [], + "description": "Visio macro-enabled drawing", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.drawingml.template.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object" + ], + "filenameExtensions": [ + ".vstm" + ], + "mimeTypes": [], + "description": "Visio macro-enabled drawing template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.wordprocessingml.template", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object" + ], + "filenameExtensions": [ + ".dotx" + ], + "mimeTypes": [ + "application/vnd.openxmlformats-officedocument.wordprocessingml.template" + ], + "description": "Office Open XML document template.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.presentationml.template", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object" + ], + "filenameExtensions": [ + ".potx" + ], + "mimeTypes": [ + "application/vnd.openxmlformats-officedocument.presentationml.template" + ], + "description": "Office Open XML presentation template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.presentationml.slideshow", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object" + ], + "filenameExtensions": [ + ".ppsx" + ], + "mimeTypes": [ + "application/vnd.openxmlformats-officedocument.presentationml.slideshow" + ], + "description": "Office Open XML slide show", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.spreadsheetml.template", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object" + ], + "filenameExtensions": [ + ".xltx" + ], + "mimeTypes": [ + "application/vnd.openxmlformats-officedocument.spreadsheetml.template" + ], + "description": "Office Open XML spreadsheet template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.wordprocessingml.document.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".docm" + ], + "mimeTypes": [ + "application/vnd.ms-word.document.macroEnabled.12" + ], + "description": "Office Open XML word processing document (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.wordprocessingml.template.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".dotm" + ], + "mimeTypes": [ + "application/vnd.ms-word.template.macroEnabled.12" + ], + "description": "Office Open XML word processing template (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.spreadsheetml.template.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".xltm" + ], + "mimeTypes": [ + "application/vnd.ms-excel.template.macroEnabled.12" + ], + "description": "Office Open XML spreadsheet template (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.spreadsheetml.addin.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".xlam" + ], + "mimeTypes": [ + "application/vnd.ms-excel.addin.macroEnabled.12" + ], + "description": "Office Open XML spreadsheet addin (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.spreadsheetml.binary.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".xlsb" + ], + "mimeTypes": [ + "application/vnd.ms-excel.sheet.binary.macroEnabled.12" + ], + "description": "Office Open XML spreadsheet binary (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.spreadsheetml.sheet.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".xlsm" + ], + "mimeTypes": [ + "application/vnd.ms-excel.sheet.macroEnabled.12" + ], + "description": "Office Open XML spreadsheet (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.presentationml.addin.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".ppam" + ], + "mimeTypes": [ + "application/vnd.ms-powerpoint.addin.macroEnabled.12" + ], + "description": "Office Open XML presentation addin (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.presentationml.presentation.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".pptm" + ], + "mimeTypes": [ + "application/vnd.ms-powerpoint.presentation.macroEnabled.12" + ], + "description": "Office Open XML presentation (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.presentationml.slideshow.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".ppsm" + ], + "mimeTypes": [ + "application/vnd.ms-powerpoint.slideshow.macroEnabled.12" + ], + "description": "Office Open XML slide show (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.presentationml.template.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".potm" + ], + "mimeTypes": [ + "application/vnd.ms-powerpoint.template.macroEnabled.12" + ], + "description": "Office Open XML presentation template (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenOffice document format for open-source office software suite", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.calc", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sxc" + ], + "mimeTypes": [ + "application/vnd.sun.xml.calc" + ], + "description": "StarOffice Calc spreadsheet", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.draw", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sxd" + ], + "mimeTypes": [ + "application/vnd.sun.xml.draw" + ], + "description": "StarOffice Drawing", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.writer-global", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sxg" + ], + "mimeTypes": [ + "application/vnd.sun.xml.writer.global" + ], + "description": "Apache OpenOffice master document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.impress", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sxi" + ], + "mimeTypes": [ + "application/vnd.sun.xml.impress" + ], + "description": "StarOffice Impress presentation", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.math", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sxm" + ], + "mimeTypes": [ + "application/vnd.sun.xml.math" + ], + "description": "StarMath Formula", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.writer", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sxw" + ], + "mimeTypes": [ + "application/vnd.sun.xml.writer" + ], + "description": "StarOffice Writer document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.calc.template", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".stc" + ], + "mimeTypes": [ + "application/vnd.sun.xml.calc.template" + ], + "description": "StarOffice Calc spreadsheet template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.draw.template", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".std" + ], + "mimeTypes": [ + "application/vnd.sun.xml.draw.template" + ], + "description": "Apache OpenOffice Drawing template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.impress.template", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sti" + ], + "mimeTypes": [ + "application/vnd.sun.xml.impress.template" + ], + "description": "StarOffice Presentation template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.writer.template", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".stw" + ], + "mimeTypes": [ + "application/vnd.sun.xml.writer.template" + ], + "description": "StarOffice Document template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "StarOffice document format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.draw", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sda" + ], + "mimeTypes": [ + "application/vnd.stardivision.draw" + ], + "description": "StarOffice Drawing", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.calc", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sdc" + ], + "mimeTypes": [ + "application/vnd.stardivision.calc" + ], + "description": "StarOffice Calc spreadsheet", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.impress", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sdd", + ".sdp" + ], + "mimeTypes": [ + "application/vnd.stardivision.impress" + ], + "description": "StarOffice Presentation", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.writer", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sdw" + ], + "mimeTypes": [ + "application/vnd.stardivision.writer" + ], + "description": "StarOffice Writer text document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.chart", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sds" + ], + "mimeTypes": [ + "application/vnd.stardivision.chart" + ], + "description": "StarOffice Chart", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.mail", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sdm" + ], + "mimeTypes": [ + "application/vnd.stardivision.mail" + ], + "description": "StarOffice Mail message", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.writer-global", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sgl" + ], + "mimeTypes": [ + "application/vnd.stardivision.writer-global" + ], + "description": "StarOffice Master document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.math", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".smf" + ], + "mimeTypes": [ + "application/vnd.stardivision.math" + ], + "description": "StarMath Formula file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.template", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".vor" + ], + "mimeTypes": [ + "application/vnd.stardivision.template" + ], + "description": "StarOffice Template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.tug.bib", + "belongingToTypes": [ + "general.tex" + ], + "filenameExtensions": [ + ".bib" + ], + "mimeTypes": [ + "text/x-bibtex" + ], + "description": "TeX Bibliography file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.tug.cls", + "belongingToTypes": [ + "general.tex" + ], + "filenameExtensions": [ + ".cls" + ], + "mimeTypes": [ + "text/x-tex" + ], + "description": "TeX Class file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.tug.sty", + "belongingToTypes": [ + "general.tex" + ], + "filenameExtensions": [ + ".sty" + ], + "mimeTypes": [ + "text/x-tex" + ], + "description": "TeX Style file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.tug.tex", + "belongingToTypes": [ + "general.tex" + ], + "filenameExtensions": [ + ".tex" + ], + "mimeTypes": [ + "text/x-tex" + ], + "description": "TeX source document file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.latex-project.latex", + "belongingToTypes": [ + "general.tex" + ], + "filenameExtensions": [ + ".ltx", + ".latex" + ], + "mimeTypes": [ + "application/x-latex" + ], + "description": "LaTeX source document file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.matroska.mkv", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".mkv" + ], + "mimeTypes": [ + "video/x-matroska" + ], + "description": "Matroska video", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.matroska.mka", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".mka" + ], + "mimeTypes": [ + "audio/x-matroska" + ], + "description": "Matroska audio", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.sgi.movie", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".movie" + ], + "mimeTypes": [ + "video/x-sgi-movie" + ], + "description": "SGI movie", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.apple.m4v", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".m4v" + ], + "mimeTypes": [ + "video/m4v" + ], + "description": "M4V video", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.webmproject.webm", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".webm" + ], + "mimeTypes": [ + "video/webm" + ], + "description": "WebM is an audiovisual media file format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.apple.quicktime-movie", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".mov", + ".qt", + ".movie" + ], + "mimeTypes": [ + "video/quicktime" + ], + "description": "QuickTime File Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.coreldraw.cdr", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".cdr" + ], + "mimeTypes": [ + "image/x-coreldraw" + ], + "description": "CorelDRAW file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.coreldraw.cdt", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".cdt" + ], + "mimeTypes": [ + "image/x-coreldrawtemplate" + ], + "description": "CorelDRAW template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.coreldraw.cpt", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".cpt" + ], + "mimeTypes": [ + "image/x-corelphotopaint" + ], + "description": "Corel PHOTO-PAINT image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.coreldraw.pat", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".pat" + ], + "mimeTypes": [ + "image/x-coreldrawpattern" + ], + "description": "CorelDRAW pattern file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.cur", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".cur" + ], + "mimeTypes": [ + "image/ico" + ], + "description": "Microsoft Windows cursor image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.sun.raster", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".ras" + ], + "mimeTypes": [ + "image/x-cmu-raster" + ], + "description": "Sun Raster Graphic", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.google.webp", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".webp" + ], + "mimeTypes": [ + "image/webp" + ], + "description": "WebP image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.sseyo.koan-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".skd", + ".skm", + ".skp", + ".skt" + ], + "mimeTypes": [ + "application/x-koan" + ], + "description": "Koan music files over the internet", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "io.qt.moc", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".moc" + ], + "mimeTypes": [ + "text/x-moc" + ], + "description": "Qt Meta-Object compiler file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.ghostscript.font", + "belongingToTypes": [ + "general.font" + ], + "filenameExtensions": [ + ".gsf" + ], + "mimeTypes": [ + "application/x-font" + ], + "description": "Ghostscript font", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.x.pcf-font", + "belongingToTypes": [ + "general.font" + ], + "filenameExtensions": [ + ".pcf" + ], + "mimeTypes": [ + "application/x-font", + "application/x-font-pcf" + ], + "description": "Portable compiled format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.windows-media-wmd", + "belongingToTypes": [ + "com.microsoft.advanced-systems-format", + "general.zip-archive" + ], + "filenameExtensions": [ + ".wmd" + ], + "mimeTypes": [ + "application/x-ms-wmd" + ], + "description": "Windows media download package", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.windows-media-wmz", + "belongingToTypes": [ + "com.microsoft.advanced-systems-format", + "general.zip-archive" + ], + "filenameExtensions": [ + ".wmz" + ], + "mimeTypes": [ + "application/x-ms-wmz" + ], + "description": "Windows media player skin package", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.windows-installer", + "belongingToTypes": [ + "general.executable" + ], + "filenameExtensions": [ + ".msi" + ], + "mimeTypes": [ + "application/x-msi" + ], + "description": "Windows installer package", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.publisher.pub", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".pub" + ], + "mimeTypes": [ + "application/x-mspublisher" + ], + "description": "Publisher document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.windows-media-playlist", + "belongingToTypes": [ + "general.xml", + "general.media" + ], + "filenameExtensions": [ + ".wpl" + ], + "mimeTypes": [ + "application/vnd.ms-wpl" + ], + "description": "Windows media player playlist", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.access.mdb", + "belongingToTypes": [ + "general.database" + ], + "filenameExtensions": [ + ".mdb" + ], + "mimeTypes": [ + "application/msaccess" + ], + "description": "Microsoft Access database", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.3dsystems.stereolithography", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".stl" + ], + "mimeTypes": [ + "application/vnd.ms-pki.stl" + ], + "description": "Stereolithography file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.apple.media.playlist", + "belongingToTypes": [ + "general.media" + ], + "filenameExtensions": [ + ".m3u8" + ], + "mimeTypes": [ + "application/vnd.apple.mpegurl" + ], + "description": "UTF-8 M3U playlist", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.abisource.word", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".abw" + ], + "mimeTypes": [ + "application/x-abiword" + ], + "description": "AbiWord document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.framemaker", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".book", + ".fm", + ".frame", + ".maker" + ], + "mimeTypes": [ + "application/x-maker" + ], + "description": "FrameMaker book file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.wolfram.cdf", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".cdf" + ], + "mimeTypes": [ + "application/x-cdf" + ], + "description": "Computable document format file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "de.cinderella.cdy", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".cdy" + ], + "mimeTypes": [ + "application/vnd.cinderella" + ], + "description": "Cinderella construction file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.dcr", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".dcr" + ], + "mimeTypes": [ + "application/x-director" + ], + "description": "Shockwave media file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.dir", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".dir" + ], + "mimeTypes": [ + "application/x-director" + ], + "description": "Adobe Director movie", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.dxr", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".dxr" + ], + "mimeTypes": [ + "application/x-director" + ], + "description": "Protected macromedia director movie", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.gnumeric.spreadsheet", + "belongingToTypes": [ + "general.xml" + ], + "filenameExtensions": [ + ".gnumeric" + ], + "mimeTypes": [ + "application/x-gnumeric" + ], + "description": "Gnumeric spreadsheet", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.hdfgroup.hdf", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".hdf" + ], + "mimeTypes": [ + "application/x-hdf" + ], + "description": "Hierarchical data format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.apple.binhex-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".hqx" + ], + "mimeTypes": [ + "application/mac-binhex40" + ], + "description": "BinHex 4.0 encoded file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.hta", + "belongingToTypes": [ + "general.archive", + "general.executable" + ], + "filenameExtensions": [ + ".hta" + ], + "mimeTypes": [ + "application/hta" + ], + "description": "HTML application", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.internet.ins", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".ins" + ], + "mimeTypes": [ + "application/x-internet-signup" + ], + "description": "Internet settings file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.internet.isp", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".isp" + ], + "mimeTypes": [ + "application/x-internet-signup" + ], + "description": "IIS internet service provider settings", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.troff", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".man", + ".t", + ".roff" + ], + "mimeTypes": [ + "text/troff" + ], + "description": "Unix troff format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.framemaker.mif", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".mif" + ], + "mimeTypes": [ + "application/vnd.mif" + ], + "description": "FrameMaker interchange format file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "io.sourceforge.freemind", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".mm" + ], + "mimeTypes": [ + "application/x-freemind" + ], + "description": "Mind Map file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.yamaha.smaf", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".mmf" + ], + "mimeTypes": [ + "application/vnd.smaf" + ], + "description": "Synthetic music mobile application file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.wolfram.mathematica.notebook", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".nb" + ], + "mimeTypes": [ + "application/mathematica" + ], + "description": "Mathematica notebook", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.xiph.ogg", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".oga", + ".ogg" + ], + "mimeTypes": [ + "application/ogg" + ], + "description": "Ogg vorbis audio", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.netscape.proxy-autoconfig", + "belongingToTypes": [ + "general.plain-text" + ], + "filenameExtensions": [ + ".pac" + ], + "mimeTypes": [ + "application/x-ns-proxy-autoconfig" + ], + "description": "Proxy auto-config file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.rsa.pkcs-12", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".pfx", + ".p12" + ], + "mimeTypes": [ + "application/x-pkcs12" + ], + "description": "PKCS #12 certificate file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openpgp.signature", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [ + ".pgp" + ], + "mimeTypes": [ + "application/pgp-signature" + ], + "description": "PGP security key", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.apple.quicktime-link", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".qtl" + ], + "mimeTypes": [ + "application/x-quicktimeplayer" + ], + "description": "QuickTime link file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.rarlab.rar-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".rar" + ], + "mimeTypes": [ + "application/rar", + "application/vnd.rar" + ], + "description": "WinRAR compressed archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.7-zip.7-zip-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".7z" + ], + "mimeTypes": [ + "application/x-7z-compressed" + ], + "description": "7-zip compressed archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.red-bean.sgf", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".sgf" + ], + "mimeTypes": [ + "application/x-go-sgf" + ], + "description": "Smart game format file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.stuffit.sit-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".sit" + ], + "mimeTypes": [ + "application/x-stuffit" + ], + "description": "Stuffit archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.futuresplash", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".spl" + ], + "mimeTypes": [ + "application/futuresplash", + "application/x-futuresplash" + ], + "description": "FutureSplash animation", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.flash", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".swf", + ".flv" + ], + "mimeTypes": [ + "application/x-shockwave-flash", + "video/x-flv" + ], + "description": "Shockwave flash movie", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.gnu.texinfo", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".texinfo", + ".texi" + ], + "mimeTypes": [ + "application/x-texinfo" + ], + "description": "GNU Texinfo", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.bittorrent.torrent", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".torrent" + ], + "mimeTypes": [ + "application/x-bittorrent" + ], + "description": "BitTorrent file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.idsoftware.doom", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".wad" + ], + "mimeTypes": [ + "application/x-doom" + ], + "description": "Doom WAD file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.apple.webarchive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".webarchive" + ], + "mimeTypes": [ + "application/x-webarchive" + ], + "description": "Safari web archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.android.webarchive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".webarchivexml" + ], + "mimeTypes": [ + "application/x-webarchive-xml" + ], + "description": "Android web browser archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.gimp.xcf", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".xcf" + ], + "mimeTypes": [ + "application/x-xcf", + "image/x-xcf" + ], + "description": "eXperimental computing facility, GIMP image file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.edrawsoft.edrawmax", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".eddx" + ], + "mimeTypes": [ + "application/x-eddx" + ], + "description": "Edraw Max XML file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.edrawsoft.edrawmind", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".emmx" + ], + "mimeTypes": [ + "application/x-emmx" + ], + "description": "Edraw MindMaster XML file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "net.cnki.caj", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".caj" + ], + "mimeTypes": [ + "application/caj" + ], + "description": "Chinese academic journal file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.dbase.dbf", + "belongingToTypes": [ + "general.database" + ], + "filenameExtensions": [ + ".dbf" + ], + "mimeTypes": [ + "application/dbf", + "application/dbase" + ], + "description": "Database file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.dwg", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dwg" + ], + "mimeTypes": [ + "image/vnd.dwg" + ], + "description": "AutoCAD drawing", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.dxf", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dxf" + ], + "mimeTypes": [ + "image/vnd.dxf" + ], + "description": "Drawing exchange format file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.dws", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dws" + ], + "mimeTypes": [], + "description": "AutoCAD drawing standards file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.dwt", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dwt" + ], + "mimeTypes": [], + "description": "AutoCAD drawing template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.dwf", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dwf" + ], + "mimeTypes": [ + "model/vnd.dwf" + ], + "description": "Design web format file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.dwfx", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dwfx" + ], + "mimeTypes": [], + "description": "Design web format XPS file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.shp", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".shp" + ], + "mimeTypes": [], + "description": "3D studio shape", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.shx", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".shx" + ], + "mimeTypes": [], + "description": "AutoCAD compiled shape file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.slide-library", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".slb" + ], + "mimeTypes": [], + "description": "AutoCAD slide library", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.line", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".lin" + ], + "mimeTypes": [], + "description": "AutoCAD linetype file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.plotter", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".plt" + ], + "mimeTypes": [], + "description": "AutoCAD plotter document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.hp.graphics-language", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".hpgl" + ], + "mimeTypes": [ + "application/vnd.hp-hpgl" + ], + "description": "HP graphics language plotter file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.metafile", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".wmf" + ], + "mimeTypes": [], + "description": "Windows metafile", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.spatial.acis.sat", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".sat" + ], + "mimeTypes": [], + "description": "ACIS SAT 3D model", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.aomedia.avif-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".avif" + ], + "mimeTypes": [ + "image/avif" + ], + "description": "AVIF image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.dds", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".dds" + ], + "mimeTypes": [ + "image/vnd-ms.dds" + ], + "description": "DirectDraw surface image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.ea.iff-ilbm", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".ilbm" + ], + "mimeTypes": [ + "image/x-ilbm" + ], + "description": "Interleaved bitmap image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.canon.cr2-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".cr2" + ], + "mimeTypes": [ + "image/x-canon-cr2" + ], + "description": "Canon raw 2 image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.canon.cr3-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".cr3" + ], + "mimeTypes": [ + "image/x-canon-cr3" + ], + "description": "Canon raw 3 image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.canon.crw-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".crw" + ], + "mimeTypes": [ + "image/x-canon-crw" + ], + "description": "Canon raw CIFF image file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.dng-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".dng" + ], + "mimeTypes": [ + "image/x-adobe-dng" + ], + "description": "Digital negative image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.sony.arw-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".arw" + ], + "mimeTypes": [ + "image/x-sony-arw" + ], + "description": "Sony alpha raw digital camera image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.nikon.nef-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".nef" + ], + "mimeTypes": [ + "image/x-nikon-nef" + ], + "description": "Nikon electronic format RAW image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.mindjet.mindmanager.mmap", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".mmap" + ], + "mimeTypes": [], + "description": "MindManager Map", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.email", + "belongingToTypes": [ + "general.message" + ], + "filenameExtensions": [ + ".eml" + ], + "mimeTypes": [ + "message/rfc822" + ], + "description": "E-Mail message", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.message", + "belongingToTypes": [ + "general.message" + ], + "filenameExtensions": [ + ".msg" + ], + "mimeTypes": [], + "description": "Outlook message item file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.pst", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".pst" + ], + "mimeTypes": [], + "description": "Outlook personal information store", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Kingsoft office suite", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office.writer.wps", + "belongingToTypes": [ + "com.kingsoft.office", + "general.composite-object" + ], + "filenameExtensions": [ + ".wps" + ], + "mimeTypes": [], + "description": "Kingsoft Writer document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office.writer.wpt", + "belongingToTypes": [ + "com.kingsoft.office", + "general.composite-object" + ], + "filenameExtensions": [ + ".wpt" + ], + "mimeTypes": [], + "description": "Kingsoft Writer template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office.presentation.dps", + "belongingToTypes": [ + "com.kingsoft.office", + "general.composite-object" + ], + "filenameExtensions": [ + ".dps" + ], + "mimeTypes": [], + "description": "Kingsoft Presentation file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office.presentation.template", + "belongingToTypes": [ + "com.kingsoft.office", + "general.composite-object" + ], + "filenameExtensions": [ + ".dpt" + ], + "mimeTypes": [], + "description": "Kingsoft Presentation template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office.spreadsheets.et", + "belongingToTypes": [ + "com.kingsoft.office", + "general.composite-object" + ], + "filenameExtensions": [ + ".et" + ], + "mimeTypes": [], + "description": "Kingsoft Spreadsheets tile", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office.spreadsheets.template", + "belongingToTypes": [ + "com.kingsoft.office", + "general.composite-object" + ], + "filenameExtensions": [ + ".ett" + ], + "mimeTypes": [], + "description": "Kingsoft Spreadsheets template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.ini", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".ini" + ], + "mimeTypes": [], + "description": "Windows Initialization File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.json", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".json" + ], + "mimeTypes": [ + "application/json" + ], + "description": "JavaScript Object Notation File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.yaml", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".yaml", + ".yml" + ], + "mimeTypes": [ + "application/yaml" + ], + "description": "YAML Document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.log", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".log" + ], + "mimeTypes": [ + "text/plain" + ], + "description": "Log File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.uri", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Universal Resource Identifier", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.file-uri", + "belongingToTypes": [ + "general.uri" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "File URI", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.text-lst", + "belongingToTypes": [ + "general.plain-text" + ], + "filenameExtensions": [ + ".lst" + ], + "mimeTypes": [], + "description": "Data List", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.android.apk", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".apk", + ".apks", + ".aab", + ".xapk", + ".apkm", + ".akp" + ], + "mimeTypes": [ + "application/vnd.android.package-archive" + ], + "description": "Android Package File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.postscript-pfb-font", + "belongingToTypes": [ + "com.adobe.postscript-font" + ], + "filenameExtensions": [ + ".pfb" + ], + "mimeTypes": [ + "application/x-font" + ], + "description": "Printer Font Binary, PostScript Type 1 outline font.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.postscript-pfa-font", + "belongingToTypes": [ + "com.adobe.postscript-font" + ], + "filenameExtensions": [ + ".pfa" + ], + "mimeTypes": [ + "application/x-font" + ], + "description": "Printer Pont ASCII file, PostScript Type 1 outline font.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.bz-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".bz" + ], + "mimeTypes": [ + "application/x-bzip" + ], + "description": "Bzip Compressed File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.tar-bzip-archive", + "belongingToTypes": [ + "general.bz-archive" + ], + "filenameExtensions": [ + ".tbz" + ], + "mimeTypes": [ + "application/x-bzip-compressed-tar" + ], + "description": "Bzip Compressed Tar Archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.tar-bzip2-archive", + "belongingToTypes": [ + "general.bz2-archive" + ], + "filenameExtensions": [ + ".tbz2" + ], + "mimeTypes": [ + "application/x-bzip2-compressed-tar" + ], + "description": "Bzip2-Compressed TAR File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.tukaani.xz-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".xz" + ], + "mimeTypes": [ + "application/x-xz" + ], + "description": "XZ Compressed Archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.tukaani.tar-xz-archive", + "belongingToTypes": [ + "org.tukaani.xz-archive" + ], + "filenameExtensions": [ + ".txz" + ], + "mimeTypes": [ + "application/x-xz-compressed-tar" + ], + "description": "XZ Compressed Tar Archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.xar-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".xar" + ], + "mimeTypes": [ + "application/x-xar" + ], + "description": "Extensible Archive Fromat", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.cab-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".cab" + ], + "mimeTypes": [ + "application/vnd.ms-cab-compressed" + ], + "description": "Windows Cabinet File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "redhat.rpm-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".rpm" + ], + "mimeTypes": [ + "application/x-rpm" + ], + "description": "RedHat Package Manager File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.godotengine.tpz-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".tpz" + ], + "mimeTypes": [], + "description": "Godot Engine Export Template Archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.lza-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".lza" + ], + "mimeTypes": [ + "application/x-lzh-compressed" + ], + "description": "LZA Compressed Archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.arj-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".arj" + ], + "mimeTypes": [ + "application/x-arj" + ], + "description": "ARJ Compressed File Archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.winzip.zipx", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".zipx" + ], + "mimeTypes": [], + "description": "Extended Zip Archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.lzma-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".lzma" + ], + "mimeTypes": [ + "application/x-lzma" + ], + "description": "LZMA Compressed File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.lzma86-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".lzma86" + ], + "mimeTypes": [], + "description": "LZMA86 Compressed File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.mozilla.xpinstall", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".xpi" + ], + "mimeTypes": [ + "application/x-xpinstall" + ], + "description": "Cross-platform Installer Package", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.hfs-disk-image", + "belongingToTypes": [ + "general.disk-image" + ], + "filenameExtensions": [ + ".hfs" + ], + "mimeTypes": [], + "description": "HFS Disk Image File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.img-disk-image", + "belongingToTypes": [ + "general.disk-image" + ], + "filenameExtensions": [ + ".img" + ], + "mimeTypes": [ + "application/x-raw-disk-image" + ], + "description": "Disc Image Data File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.ezbsystems.zipped-iso", + "belongingToTypes": [ + "general.disk-image" + ], + "filenameExtensions": [ + ".isz" + ], + "mimeTypes": [], + "description": "Zipped ISO Disk Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.wim", + "belongingToTypes": [ + "general.disk-image" + ], + "filenameExtensions": [ + ".wim" + ], + "mimeTypes": [ + "application/x-ms-wim" + ], + "description": "Windows Imaging Format File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.swm", + "belongingToTypes": [ + "general.disk-image" + ], + "filenameExtensions": [ + ".swm" + ], + "mimeTypes": [ + "application/x-ms-wim" + ], + "description": "Split Windows Imaging Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office.spreadsheets.etx", + "belongingToTypes": [ + "com.kingsoft.office", + "general.composite-object" + ], + "filenameExtensions": [ + ".etx" + ], + "mimeTypes": [], + "description": "Kingsoft Spreadsheets File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office.spreadsheets.ettx", + "belongingToTypes": [ + "com.kingsoft.office", + "general.composite-object" + ], + "filenameExtensions": [ + ".ettx" + ], + "mimeTypes": [], + "description": "Kingsoft Spreadsheets Template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.excel.dif", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dif" + ], + "mimeTypes": [], + "description": "Data interchange format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.app", + "belongingToTypes": [ + "openharmony.package" + ], + "filenameExtensions": [ + ".app" + ], + "mimeTypes": [], + "description": "OpenHarmony system defined application package", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.huawei.hmos.settings.wifi", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".hmoswifi" + ], + "mimeTypes": [], + "description": "HarmonyOS WIFI sharing setting", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.tel", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".tel" + ], + "mimeTypes": [], + "description": "TEL schematic diagram file format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ets", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".ets" + ], + "mimeTypes": [], + "description": "Extended TypeScript source code", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.json5", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".json5" + ], + "mimeTypes": [], + "description": "JSON5 data interchange format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.monkeysaudio.ape-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".ape" + ], + "mimeTypes": [ + "audio/x-monkeys-audio" + ], + "description": "Monkey's Audio", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.xiph.opus-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".opus" + ], + "mimeTypes": [ + "audio/opus" + ], + "description": "Opus Audio", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.conf", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".conf" + ], + "mimeTypes": [], + "description": "Generic Configuration File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.dos-batch", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".bat" + ], + "mimeTypes": [ + "application/x-bat" + ], + "description": "DOS Batch File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.vbscript", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".vbs" + ], + "mimeTypes": [ + "application/x-vbs" + ], + "description": "VBScript File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ion", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".ion" + ], + "mimeTypes": [], + "description": "File Description File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.registry", + "belongingToTypes": [ + "general.database" + ], + "filenameExtensions": [ + ".reg" + ], + "mimeTypes": [], + "description": "Registry File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.catalog", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [ + ".cat" + ], + "mimeTypes": [], + "description": "Windows Catalog File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.powershell-script", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".ps1" + ], + "mimeTypes": [], + "description": "Windows PowerShell Cmdlet File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.w3.woff", + "belongingToTypes": [ + "general.font" + ], + "filenameExtensions": [ + ".woff" + ], + "mimeTypes": [ + "font/woff" + ], + "description": "Web Open Font Format File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.sqlite.database", + "belongingToTypes": [ + "general.database" + ], + "filenameExtensions": [ + ".sqlite", + ".sqlite3", + ".db", + ".db3", + ".s3db", + ".sl3" + ], + "mimeTypes": [ + "application/vnd.sqlite3" + ], + "description": "SQLite Database", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.sys", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [ + ".sys" + ], + "mimeTypes": [], + "description": "Windows System File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.inf", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".inf" + ], + "mimeTypes": [ + "text/plain" + ], + "description": "Setup Information File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.pdb", + "belongingToTypes": [ + "general.database" + ], + "filenameExtensions": [ + ".pdb" + ], + "mimeTypes": [ + "application/x-ms-pdb" + ], + "description": "Program Database", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.tlb", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [ + ".tlb" + ], + "mimeTypes": [], + "description": "OLE Type Library", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.sccd", + "belongingToTypes": [ + "general.xml" + ], + "filenameExtensions": [ + ".sccd" + ], + "mimeTypes": [], + "description": "Signed Custom Capability Descriptor", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.f4v", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".f4v" + ], + "mimeTypes": [ + "video/mp4" + ], + "description": "Flash MP4 Video File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mp2t", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".m2ts", + ".mts", + ".m2t" + ], + "mimeTypes": [ + "video/mp2t" + ], + "description": "Blu-ray BDAV Video File Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.youtube.video", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".yt", + ".vt" + ], + "mimeTypes": [ + "video/vnd.youtube.yt" + ], + "description": "Youtube Video format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.cisco.webex-video", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".wrf" + ], + "mimeTypes": [ + "video/x-webex" + ], + "description": "WebEx Recording", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mpeg-2", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".mpeg2", + ".mpv2", + ".mp2v", + ".m2v", + ".mpv" + ], + "mimeTypes": [ + "video/mpeg" + ], + "description": "MPEG-2 Video format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mpeg-1", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".mpeg1", + ".mpv1", + ".mp1v", + ".m1v" + ], + "mimeTypes": [ + "video/mpeg" + ], + "description": "MPEG-1 Video format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.real.realmedia-vbr", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".rmvb" + ], + "mimeTypes": [ + "application/vnd.rn-realmedia-vbr" + ], + "description": "RealMedia Variable Bit Rate Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.real.realvideo", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".rv" + ], + "mimeTypes": [ + "video/x-pn-realvideo" + ], + "description": "RealVideo Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.divx-video", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".divx" + ], + "mimeTypes": [ + "video/divx" + ], + "description": "DivX-Encoded Movie", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.csiro.annodex", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".axv" + ], + "mimeTypes": [ + "video/annodex" + ], + "description": "Annodex Video Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ogv", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".ogv" + ], + "mimeTypes": [ + "video/ogg" + ], + "description": "Ogg Video Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.lsf-video", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".lsf", + ".lsx" + ], + "mimeTypes": [ + "video/x-la-asf" + ], + "description": "Streaming Media Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.h264-video", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".h264" + ], + "mimeTypes": [ + "video/H264" + ], + "description": "H.264 Encoded Video Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.jpeg-2000", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".jp2", + ".jpg2", + ".jpx", + ".jpf", + ".jpm" + ], + "mimeTypes": [ + "image/jp2", + "image/jpx", + "image/jpm" + ], + "description": "JPEG 2000 Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.fujifilm.raf-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".raf" + ], + "mimeTypes": [ + "image/x-fuji-raf" + ], + "description": "Fujifilm RAW Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.nikon.nrw-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".nrw" + ], + "mimeTypes": [ + "image/x-nikon-nrw" + ], + "description": "Nikon Raw Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.panasonic.rw2-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".rw2", + ".raw" + ], + "mimeTypes": [ + "image/x-panasonic-raw" + ], + "description": "Panasonic RAW Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.pentax.pef-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".pef" + ], + "mimeTypes": [ + "image/x-pentax-pef" + ], + "description": "Pentax Electronic RAW Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.sumsung.srw-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".srw" + ], + "mimeTypes": [ + "image/x-samsung-srw" + ], + "description": "Samsung RAW Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.epson.erf-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".erf" + ], + "mimeTypes": [ + "image/x-epson-erf" + ], + "description": "Epson RAW Imager", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.olympus.orf-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".orf" + ], + "mimeTypes": [ + "image/x-olympus-orf" + ], + "description": "Olympus RAW Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ief-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".ief" + ], + "mimeTypes": [ + "image/ief" + ], + "description": "Image Exchange Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.aol.art-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".art" + ], + "mimeTypes": [ + "image/x-jg" + ], + "description": "ART image format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.content-form", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Content form format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.apple.m4p-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".m4p" + ], + "mimeTypes": [ + "audio/mp4" + ], + "description": "iTunes Music Store Audio File Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ac3-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".ac3" + ], + "mimeTypes": [ + "audio/ac3" + ], + "description": "Audio Codec 3 File Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.hsp", + "belongingToTypes": [ + "openharmony.package" + ], + "filenameExtensions": [ + ".hsp" + ], + "mimeTypes": [], + "description": "Harmony Shared Package", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.har", + "belongingToTypes": [ + "openharmony.package" + ], + "filenameExtensions": [ + ".har" + ], + "mimeTypes": [], + "description": "Harmony Archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.gopaint", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".gopaint" + ], + "mimeTypes": [], + "description": "Gopaint file format defined for Openharmony", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.gobrush", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".gobrush" + ], + "mimeTypes": [], + "description": "Gobrush file format defined for Openharmony", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.gobrushes", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".gobrushes" + ], + "mimeTypes": [], + "description": "Gobrushes file format defined for Openharmony", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.gocolor", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".gocolor" + ], + "mimeTypes": [], + "description": "Gocolor file format defined for Openharmony", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.dlp", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dlp" + ], + "mimeTypes": [], + "description": "Account identify encryption file format defined by OpenHarmony", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + } + ] +} \ No newline at end of file diff --git a/udmf/framework/common/concurrent_map.h b/udmf/framework/common/concurrent_map.h new file mode 100644 index 0000000000000000000000000000000000000000..d0b2dbe8ae0c0f2700f410d64930a8dad6228543 --- /dev/null +++ b/udmf/framework/common/concurrent_map.h @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2025 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_CONCURRENT_MAP_H +#define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_CONCURRENT_MAP_H +#include +#include +#include +namespace OHOS { +template +class ConcurrentMap { + template + static _First First(); + +public: + using map_type = typename std::map<_Key, _Tp>; + using filter_type = typename std::function; + using key_type = typename std::map<_Key, _Tp>::key_type; + using mapped_type = typename std::map<_Key, _Tp>::mapped_type; + using value_type = typename std::map<_Key, _Tp>::value_type; + using size_type = typename std::map<_Key, _Tp>::size_type; + using reference = typename std::map<_Key, _Tp>::reference; + using const_reference = typename std::map<_Key, _Tp>::const_reference; + + ConcurrentMap() = default; + ~ConcurrentMap() + { + Clear(); + } + + ConcurrentMap(const ConcurrentMap &other) + { + operator=(std::move(other)); + } + + ConcurrentMap &operator=(const ConcurrentMap &other) noexcept + { + if (this == &other) { + return *this; + } + auto tmp = other.Clone(); + std::lock_guard lock(mutex_); + entries_ = std::move(tmp); + return *this; + } + + ConcurrentMap(ConcurrentMap &&other) noexcept + { + operator=(std::move(other)); + } + + ConcurrentMap &operator=(ConcurrentMap &&other) noexcept + { + if (this == &other) { + return *this; + } + auto tmp = other.Steal(); + std::lock_guard lock(mutex_); + entries_ = std::move(tmp); + return *this; + } + + bool Emplace() noexcept + { + std::lock_guard lock(mutex_); + auto it = entries_.emplace(); + return it.second; + } + + template + typename std::enable_if()), filter_type>, bool>::type + Emplace(_Args &&...args) noexcept + { + std::lock_guard lock(mutex_); + auto it = entries_.emplace(std::forward<_Args>(args)...); + return it.second; + } + + template + typename std::enable_if, bool>::type + Emplace(const _Filter &filter, _Args &&...args) noexcept + { + std::lock_guard lock(mutex_); + if (!filter(entries_)) { + return false; + } + auto it = entries_.emplace(std::forward<_Args>(args)...); + return it.second; + } + + std::pair Find(const key_type &key) const noexcept + { + std::lock_guard lock(mutex_); + auto it = entries_.find(key); + if (it == entries_.end()) { + return std::pair { false, mapped_type() }; + } + + return std::pair { true, it->second }; + } + + bool ContainIf(const key_type &key, const std::function &action) const noexcept + { + std::lock_guard lock(mutex_); + auto it = entries_.find(key); + if (it == entries_.end()) { + return false; + } + if (action) { + return action(it->second); + } + return true; + } + + bool Contains(const key_type &key) const noexcept + { + std::lock_guard lock(mutex_); + return (entries_.find(key) != entries_.end()); + } + + template + bool InsertOrAssign(const key_type &key, _Obj &&obj) noexcept + { + std::lock_guard lock(mutex_); + auto it = entries_.insert_or_assign(key, std::forward<_Obj>(obj)); + return it.second; + } + + bool Insert(const key_type &key, const mapped_type &value) noexcept + { + std::lock_guard lock(mutex_); + auto it = entries_.insert(value_type { key, value }); + return it.second; + } + + size_type Erase(const key_type &key) noexcept + { + std::lock_guard lock(mutex_); + return entries_.erase(key); + } + + void Clear() noexcept + { + std::lock_guard lock(mutex_); + return entries_.clear(); + } + + bool Empty() const noexcept + { + std::lock_guard lock(mutex_); + return entries_.empty(); + } + + size_type Size() const noexcept + { + std::lock_guard lock(mutex_); + return entries_.size(); + } + + // The action`s return true means meeting the erase condition + // The action`s return false means not meeting the erase condition + size_type EraseIf(const std::function &action) noexcept + { + if (action == nullptr) { + return 0; + } + std::lock_guard lock(mutex_); +#if __cplusplus > 201703L + auto count = std::erase_if(entries_, + [&action](value_type &value) -> bool { return action(value.first, value.second); }); +#else + auto count = entries_.size(); + for (auto it = entries_.begin(); it != entries_.end();) { + if (action((*it).first, (*it).second)) { + it = entries_.erase(it); + } else { + ++it; + } + } + count -= entries_.size(); +#endif + return count; + } + + void ForEach(const std::function &action) + { + if (action == nullptr) { + return; + } + std::lock_guard lock(mutex_); + for (auto &[key, value] : entries_) { + if (action(key, value)) { + break; + } + } + } + + void ForEachCopies(const std::function &action) + { + if (action == nullptr) { + return; + } + auto entries = Clone(); + for (auto &[key, value] : entries) { + if (action(key, value)) { + break; + } + } + } + + // The action's return value means that the element is keep in map or not; true means keeping, false means removing. + bool Compute(const key_type &key, const std::function &action) + { + if (action == nullptr) { + return false; + } + std::lock_guard lock(mutex_); + auto it = entries_.find(key); + if (it == entries_.end()) { + auto result = entries_.emplace(key, mapped_type()); + it = result.second ? result.first : entries_.end(); + } + if (it == entries_.end()) { + return false; + } + if (!action(it->first, it->second)) { + entries_.erase(key); + } + return true; + } + + // The action's return value means that the element is keep in map or not; true means keeping, false means removing. + bool ComputeIfPresent(const key_type &key, const std::function &action) + { + if (action == nullptr) { + return false; + } + std::lock_guard lock(mutex_); + auto it = entries_.find(key); + if (it == entries_.end()) { + return false; + } + if (!action(key, it->second)) { + entries_.erase(key); + } + return true; + } + + bool ComputeIfAbsent(const key_type &key, const std::function &action) + { + if (action == nullptr) { + return false; + } + std::lock_guard lock(mutex_); + auto it = entries_.find(key); + if (it != entries_.end()) { + return false; + } + entries_.emplace(key, action(key)); + return true; + } + + void DoActionIfEmpty(const std::function &action) + { + if (action == nullptr) { + return; + } + std::lock_guard lock(mutex_); + if (entries_.empty()) { + action(); + } + return; + } + +private: + std::map<_Key, _Tp> Steal() noexcept + { + std::lock_guard lock(mutex_); + return std::move(entries_); + } + + std::map<_Key, _Tp> Clone() const noexcept + { + std::lock_guard lock(mutex_); + return entries_; + } + +private: + mutable std::recursive_mutex mutex_; + std::map<_Key, _Tp> entries_; +}; +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_CONCURRENT_MAP_H diff --git a/udmf/framework/common/custom_utd_json_parser.cpp b/udmf/framework/common/custom_utd_json_parser.cpp index 4de2c31e9629f19f00a5a77519142f6e215d024b..cc43d21e19a94994e4d57d88f75a929035a47493 100644 --- a/udmf/framework/common/custom_utd_json_parser.cpp +++ b/udmf/framework/common/custom_utd_json_parser.cpp @@ -26,6 +26,7 @@ constexpr const char* REFERENCE_URL = "referenceURL"; constexpr const char* ICON_FILE = "iconFile"; constexpr const char* OWNER = "ownerBundle"; constexpr const char* INSTALLERS = "installerBundles"; +constexpr const int32_t MAX_UTD_CUSTOM_SIZE = 1024 * 1024; CustomUtdJsonParser::CustomUtdJsonParser() { @@ -43,8 +44,19 @@ bool CustomUtdJsonParser::ParseStoredCustomUtdJson(const std::string &jsonData, } cJSON* jsonRoot = cJSON_Parse(jsonData.c_str()); - if (jsonRoot != NULL && cJSON_IsObject(jsonRoot)) { - GetTypeDescriptors(*jsonRoot, UTD_CUSTOM, typesCfg); + if (jsonRoot == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Failed to parse JSON: invalid format"); + return false; + } + if (!cJSON_IsObject(jsonRoot)) { + LOG_ERROR(UDMF_CLIENT, "Parsed JSON root is not an object"); + cJSON_Delete(jsonRoot); + return false; + } + if (!GetTypeDescriptors(*jsonRoot, UTD_CUSTOM, typesCfg)) { + LOG_ERROR(UDMF_CLIENT, "Failed to get type descriptors"); + cJSON_Delete(jsonRoot); + return false; } cJSON_Delete(jsonRoot); return true; @@ -59,12 +71,23 @@ bool CustomUtdJsonParser::ParseUserCustomUtdJson(const std::string &jsonData, } // parse utd-adt.json to TypeDescriptorCfg obj cJSON* jsonRoot = cJSON_Parse(jsonData.c_str()); - if (jsonRoot != NULL && cJSON_IsObject(jsonRoot)) { - GetTypeDescriptors(*jsonRoot, UTD_CUSTOM_DECLAEEARION, typesDeclarations); - GetTypeDescriptors(*jsonRoot, UTD_CUSTOM_REFERENCE, typesReference); + if (jsonRoot == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Parse failed: invalid JSON format."); + return false; + } + if (!cJSON_IsObject(jsonRoot)) { + LOG_ERROR(UDMF_CLIENT, "Parsed JSON root is not an object"); + cJSON_Delete(jsonRoot); + return false; + } + if (!GetTypeDescriptors(*jsonRoot, UTD_CUSTOM_DECLARATION, typesDeclarations) || + !GetTypeDescriptors(*jsonRoot, UTD_CUSTOM_REFERENCE, typesReference)) { + LOG_ERROR(UDMF_CLIENT, "Failed to get type descriptors"); + cJSON_Delete(jsonRoot); + return false; } cJSON_Delete(jsonRoot); - LOG_DEBUG(UDMF_CLIENT, "DeclarationsSize:%{public}zu, ReferenceSize:%{public}zu", + LOG_INFO(UDMF_CLIENT, "DeclarationsSize:%{public}zu, ReferenceSize:%{public}zu", typesDeclarations.size(), typesReference.size()); return true; } @@ -122,18 +145,22 @@ bool CustomUtdJsonParser::GetTypeDescriptors(const json &jsonRoot, const std::st if (cJSON_HasObjectItem(&jsonRoot, nodeName.c_str())) { cJSON *subNode = cJSON_GetObjectItem(&jsonRoot, nodeName.c_str()); int itemNum = cJSON_GetArraySize(subNode); + if (itemNum > MAX_UTD_CUSTOM_SIZE) { + LOG_ERROR(UDMF_CLIENT, "itemNum is too large, itemNum:%{public}d", itemNum); + return false; + } for (int i = 0; i < itemNum; i++) { - cJSON *node = cJSON_GetArrayItem(subNode, i); + const cJSON *node = cJSON_GetArrayItem(subNode, i); TypeDescriptorCfg typeCfg; - typeCfg.typeId = GetStringValue(*node, TYPEID); - typeCfg.belongingToTypes = GetStringArrayValue(*node, BELONGINGTOTYPES); - typeCfg.filenameExtensions = GetStringArrayValue(*node, FILE_NAME_EXTENSTENSIONS); - typeCfg.mimeTypes = GetStringArrayValue(*node, MIME_TYPES); - typeCfg.description = GetStringValue(*node, DESCRIPTION); - typeCfg.referenceURL = GetStringValue(*node, REFERENCE_URL); - typeCfg.iconFile = GetStringValue(*node, ICON_FILE); - typeCfg.ownerBundle = GetStringValue(*node, OWNER); - std::vector installerBundles = GetStringArrayValue(*node, INSTALLERS); + typeCfg.typeId = GetStringValue(node, TYPEID); + typeCfg.belongingToTypes = GetStringArrayValue(node, BELONGINGTOTYPES); + typeCfg.filenameExtensions = GetStringArrayValue(node, FILE_NAME_EXTENSTENSIONS); + typeCfg.mimeTypes = GetStringArrayValue(node, MIME_TYPES); + typeCfg.description = GetStringValue(node, DESCRIPTION); + typeCfg.referenceURL = GetStringValue(node, REFERENCE_URL); + typeCfg.iconFile = GetStringValue(node, ICON_FILE); + typeCfg.ownerBundle = GetStringValue(node, OWNER); + std::vector installerBundles = GetStringArrayValue(node, INSTALLERS); typeCfg.installerBundles.insert(installerBundles.begin(), installerBundles.end()); typesCfg.push_back(typeCfg); } @@ -141,11 +168,11 @@ bool CustomUtdJsonParser::GetTypeDescriptors(const json &jsonRoot, const std::st return true; } -std::string CustomUtdJsonParser::GetStringValue(const json &node, const std::string &nodeName) +std::string CustomUtdJsonParser::GetStringValue(const json *node, const std::string &nodeName) { std::string value; - if (!cJSON_IsNull(&node) && cJSON_IsObject(&node) && cJSON_HasObjectItem(&node, nodeName.c_str())) { - cJSON *subNode = cJSON_GetObjectItem(&node, nodeName.c_str()); + if (!cJSON_IsNull(node) && cJSON_IsObject(node) && cJSON_HasObjectItem(node, nodeName.c_str())) { + cJSON *subNode = cJSON_GetObjectItem(node, nodeName.c_str()); if (cJSON_IsString(subNode)) { value = cJSON_GetStringValue(subNode); } @@ -153,11 +180,11 @@ std::string CustomUtdJsonParser::GetStringValue(const json &node, const std::str return value; } -std::vector CustomUtdJsonParser::GetStringArrayValue(const json &node, const std::string &nodeName) +std::vector CustomUtdJsonParser::GetStringArrayValue(const json *node, const std::string &nodeName) { std::vector values; - if (!cJSON_IsNull(&node) && cJSON_IsObject(&node) && cJSON_HasObjectItem(&node, nodeName.c_str())) { - cJSON *subNode = cJSON_GetObjectItem(&node, nodeName.c_str()); + if (!cJSON_IsNull(node) && cJSON_IsObject(node) && cJSON_HasObjectItem(node, nodeName.c_str())) { + cJSON *subNode = cJSON_GetObjectItem(node, nodeName.c_str()); if (cJSON_IsNull(subNode) || !cJSON_IsArray(subNode)) { return values; } diff --git a/udmf/framework/common/custom_utd_json_parser.h b/udmf/framework/common/custom_utd_json_parser.h index c7bd62642d85792f108c1564181cb54b1f28604d..71d41081a2e891ec9dec8d5e9c500b2a7985c918 100644 --- a/udmf/framework/common/custom_utd_json_parser.h +++ b/udmf/framework/common/custom_utd_json_parser.h @@ -33,13 +33,13 @@ public: bool ParseUserCustomUtdJson(const std::string &jsonData, std::vector &typesDeclarations, std::vector &typesReference); bool ConvertUtdCfgsToJson(const std::vector &typesCfg, std::string &jsonData); + bool GetTypeDescriptors(const json &jsonRoot, const std::string &nodeName, + std::vector &typesCfg); private: bool AddJsonStringArray(const std::vector &datas, const std::string &nodeName, json &node); - bool GetTypeDescriptors(const json &jsonRoot, const std::string &nodeName, - std::vector &typesCfg); - std::string GetStringValue(const json &node, const std::string &nodeName); - std::vector GetStringArrayValue(const json &node, const std::string &nodeName); + std::string GetStringValue(const json *node, const std::string &nodeName); + std::vector GetStringArrayValue(const json *node, const std::string &nodeName); }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/common/custom_utd_store.cpp b/udmf/framework/common/custom_utd_store.cpp index e7e11dbb9d077fafb565a28f18f2acc14a4956b0..af187ae6649f250b774ff0ed3a5310b3e9a3c7f2 100644 --- a/udmf/framework/common/custom_utd_store.cpp +++ b/udmf/framework/common/custom_utd_store.cpp @@ -15,6 +15,7 @@ #define LOG_TAG "CustomUtdStore" #include "custom_utd_store.h" #include +#include #include #include "logger.h" #include "preset_type_descriptors.h" @@ -46,73 +47,83 @@ CustomUtdStore &CustomUtdStore::GetInstance() return utdCustomPersistence; } -std::vector CustomUtdStore::GetHapTypeCfgs() +std::vector CustomUtdStore::GetCustomUtd(bool isHap, int32_t userId) { - LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg, Path:%{public}s.", CUSTOM_UTD_HAP_DIR); - std::string jsonStr; - std::ifstream fin(CUSTOM_UTD_HAP_DIR); - while (fin.good()) { - std::string line; - std::getline(fin, line); - jsonStr += line; - } - std::vector customUtdTypes; - utdJsonParser_.ParseStoredCustomUtdJson(jsonStr, customUtdTypes); - LOG_DEBUG(UDMF_CLIENT, "GetTypeCfgs, customUtdTypes total:%{public}zu.", customUtdTypes.size()); - return customUtdTypes; + std::string path = GetCustomUtdPath(isHap, userId); + LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg"); + + std::vector customUtd; + std::ifstream fin(path); + if (!fin.is_open()) { + LOG_ERROR(UDMF_CLIENT, "Failed to open custom utd file, errno=%{public}d", errno); + return customUtd; + } + + std::ostringstream buffer; + buffer << fin.rdbuf(); + if (fin.fail() && !fin.eof()) { + LOG_ERROR(UDMF_CLIENT, "Error reading file, errno=%{public}d", errno); + return customUtd; + } + + std::string jsonStr = buffer.str(); + if (!utdJsonParser_.ParseStoredCustomUtdJson(jsonStr, customUtd)) { + LOG_ERROR(UDMF_CLIENT, "Failed to parse custom utd json"); + customUtd.clear(); + } + LOG_DEBUG(UDMF_CLIENT, "CustomUtd total:%{public}zu.", customUtd.size()); + return customUtd; } -std::vector CustomUtdStore::GetTypeCfgs(int32_t userId) +std::string CustomUtdStore::GetCustomUtdPath(bool isHap, int32_t userId) { - std::string path = CUSTOM_UTD_SA_DIR + std::to_string(userId) + CUSTOM_UTD_SA_SUB_DIR; - std::string old_path = CUSTOM_UTD_SA_DIR + std::to_string(userId) + OLD_CUSTOM_UTD_SA_SUB_DIR; - std::string cfgFilePath = path; - if (access(path.c_str(), F_OK) != 0 && access(old_path.c_str(), F_OK) == 0) { - cfgFilePath = old_path; - } - cfgFilePath.append(UTD_CFG_FILE); - LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg, Path:%{public}s.", cfgFilePath.c_str()); - std::string jsonStr; - std::ifstream fin(cfgFilePath); - while (fin.good()) { - std::string line; - std::getline(fin, line); - jsonStr += line; - } - std::vector customUtdTypes; - utdJsonParser_.ParseStoredCustomUtdJson(jsonStr, customUtdTypes); - LOG_DEBUG(UDMF_CLIENT, "GetTypeCfgs, customUtdTypes total:%{public}zu.", customUtdTypes.size()); - return customUtdTypes; + if (isHap) { + return CUSTOM_UTD_HAP_DIR; + } + std::string userIdStr = std::to_string(userId); + std::string path = std::string(CUSTOM_UTD_SA_DIR).append(userIdStr).append(CUSTOM_UTD_SA_SUB_DIR); + std::string oldPath = std::string(CUSTOM_UTD_SA_DIR).append(userIdStr).append(OLD_CUSTOM_UTD_SA_SUB_DIR); + path = (access(path.c_str(), F_OK) != 0 && access(oldPath.c_str(), F_OK) == 0) ? oldPath : path; + path.append(UTD_CFG_FILE); + return path; } int32_t CustomUtdStore::SaveTypeCfgs(const std::vector &customUtdTypes, int32_t user) { LOG_DEBUG(UDMF_CLIENT, "customUtdTypes total:%{public}zu.", customUtdTypes.size()); std::string jsonData; + if (!utdJsonParser_.ConvertUtdCfgsToJson(customUtdTypes, jsonData)) { + LOG_ERROR(UDMF_CLIENT, "ConvertUtdCfgsToJson failed"); + return E_JSON_CONVERT_FAILED; + } std::string cfgFileDir = CUSTOM_UTD_SA_DIR + std::to_string(user) + CUSTOM_UTD_SA_SUB_DIR; - if (utdJsonParser_.ConvertUtdCfgsToJson(customUtdTypes, jsonData) && CreateDirectory(cfgFileDir)) { - SavaCfgFile(jsonData, cfgFileDir.append(UTD_CFG_FILE)); + if (!CreateDirectory(cfgFileDir)) { + LOG_ERROR(UDMF_CLIENT, "CreateDirectory failed"); + return E_FS_ERROR; } - return 0; + return SaveCfgFile(jsonData, cfgFileDir + UTD_CFG_FILE); } -int32_t CustomUtdStore::SavaCfgFile(const std::string &jsonData, const std::string &cfgFilePath) +int32_t CustomUtdStore::SaveCfgFile(const std::string &jsonData, const std::string &cfgFilePath) { std::ofstream ofs; - LOG_DEBUG(UDMF_CLIENT, "set cfg start, path:%{public}s ", cfgFilePath.c_str()); ofs.open(cfgFilePath, std::ios_base::ate); if (!ofs.is_open()) { - LOG_ERROR(UDMF_CLIENT, "open cfg failed, path:%{public}s", cfgFilePath.c_str()); + LOG_ERROR(UDMF_CLIENT, "open cfg failed"); + return E_FS_ERROR; } ofs << jsonData << std::endl; + if (!ofs.good()) { + LOG_ERROR(UDMF_CLIENT, "write cfg failed"); + return E_FS_ERROR; + } ofs.close(); LOG_DEBUG(UDMF_CLIENT, "set cfg end."); - return 0; + return E_OK; } bool CustomUtdStore::CreateDirectory(const std::string &path) const { - LOG_DEBUG(UDMF_CLIENT, "CreateDirectory start, path:%{public}s ", path.c_str()); if (access(path.c_str(), F_OK) == 0) { return true; } @@ -129,8 +140,7 @@ bool CustomUtdStore::CreateDirectory(const std::string &path) const if (access(subPath.c_str(), F_OK) != 0) { if (mkdir(subPath.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0) { - LOG_WARN(UDMF_CLIENT, "CreateDirectory, fail. path:%{public}s, subPath:%{public}s.", - path.c_str(), subPath.c_str()); + LOG_WARN(UDMF_CLIENT, "CreateDirectory, fail."); return false; } } @@ -142,7 +152,7 @@ bool CustomUtdStore::CreateDirectory(const std::string &path) const #endif return true; } - + LOG_ERROR(UDMF_CLIENT, "CreateDirectory fail."); return false; } @@ -227,5 +237,20 @@ void CustomUtdStore::ProcessUtdForSave(const CustomUtdCfgs &utdTypes, std::vecto } } } + +UtdFileInfo CustomUtdStore::GetCustomUtdInfo(bool isHap, int32_t userId) +{ + UtdFileInfo info = {0}; + std::string path = GetCustomUtdPath(isHap, userId); + struct stat fileStat; + if (stat(path.c_str(), &fileStat) != 0) { + LOG_WARN(UDMF_CLIENT, "custom utd file not exist"); + return info; + } + + info.lastTime = fileStat.st_mtime; + info.size = static_cast(fileStat.st_size); + return info; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/common/custom_utd_store.h b/udmf/framework/common/custom_utd_store.h index 4c20c40fea068c328b435cc5e82b2166280a74e8..57ca448fe8d2b3d30881897e1e7f269416feefcd 100644 --- a/udmf/framework/common/custom_utd_store.h +++ b/udmf/framework/common/custom_utd_store.h @@ -27,20 +27,23 @@ namespace UDMF { class CustomUtdStore { public: static CustomUtdStore &GetInstance(); - std::vector GetTypeCfgs(int32_t userId); - std::vector GetHapTypeCfgs(); + std::vector GetCustomUtd(bool isHap, int32_t userId); int32_t SaveTypeCfgs(const std::vector &customUtdTypes, int32_t user); bool InstallCustomUtds(const std::string &bundleName, const std::string &jsonStr, int32_t user, std::vector &customTyepCfgs); bool UninstallCustomUtds(const std::string &bundleName, int32_t user, std::vector &customTyepCfgs); + UtdFileInfo GetCustomUtdInfo(bool isHap, int32_t userId); + private: CustomUtdStore(); ~CustomUtdStore(); - int32_t SavaCfgFile(const std::string &jsonData, const std::string &cfgFilePath); + int32_t SaveCfgFile(const std::string &jsonData, const std::string &cfgFilePath); bool CreateDirectory(const std::string &path) const; static void ProcessUtdForSave(const CustomUtdCfgs &utdTypes, std::vector &customTyepCfgs, const std::string &bundleName); + std::string GetCustomUtdPath(bool isHap, int32_t userId); + CustomUtdJsonParser utdJsonParser_; }; } // namespace UDMF diff --git a/udmf/framework/common/graph.cpp b/udmf/framework/common/graph.cpp index ccc44b707c9c72b2381f8a86e32bef5977842084..077b8912c37083fec123e5f36fdb9fad35ae863e 100644 --- a/udmf/framework/common/graph.cpp +++ b/udmf/framework/common/graph.cpp @@ -53,7 +53,11 @@ void Graph::AddEdge(const std::string &startNode, const std::string &endNode) void Graph::AddEdge(uint32_t start, uint32_t end) { - EdgeNode *edge = new EdgeNode; // add new edge + EdgeNode *edge = new (std::nothrow) EdgeNode; // add new edge + if (edge == nullptr) { + LOG_ERROR(UDMF_CLIENT, "edge is nullptr"); + return; + } edge->adjIndex = end; edge->next = adjList_[start].firstEdge; adjList_[start].firstEdge = edge; @@ -111,7 +115,7 @@ bool Graph::DfsUnconnectedGraph(Action action) bool Graph::IsValidType(const std::string &node) { if (typeIdIndex_.find(node) == typeIdIndex_.end()) { - LOG_ERROR(UDMF_CLIENT, "invalid typeId. typeId:%{public}s ", node.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid typeId"); return false; } return true; diff --git a/udmf/framework/common/graph.h b/udmf/framework/common/graph.h index 4786bf086e6185b364cd2f081c35e4d820a708e1..4f086941e8c704e0e041bdb36c4ca9d68128851f 100644 --- a/udmf/framework/common/graph.h +++ b/udmf/framework/common/graph.h @@ -16,23 +16,23 @@ #ifndef UDMF_GRAPH_H #define UDMF_GRAPH_H -#include -#include #include +#include +#include #include #include -#include +#include namespace OHOS { namespace UDMF { struct EdgeNode { - uint32_t adjIndex; - EdgeNode *next; + uint32_t adjIndex {0}; + EdgeNode *next {nullptr}; }; struct VertexNode { - uint32_t value; - EdgeNode *firstEdge; + uint32_t value {0}; + EdgeNode *firstEdge {nullptr}; }; class Graph { public: @@ -46,12 +46,11 @@ public: bool IsValidType(const std::string &node); int32_t GetIndex(const std::string &node); bool IsDAG(); - private: - uint32_t vertexNum_; - std::vector adjList_; // Adjacency List - std::vector visited_; // Determine whether the vertex has been accessed, index=vertex value - std::map typeIdIndex_; + uint32_t vertexNum_ {0}; + std::vector adjList_ {}; // Adjacency List + std::vector visited_ {}; // Determine whether the vertex has been accessed, index=vertex value + std::map typeIdIndex_ {}; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/common/itypes_util.h b/udmf/framework/common/itypes_util.h new file mode 100644 index 0000000000000000000000000000000000000000..48fefb2aa122ff936a32f7441d59f401cfbb0c8d --- /dev/null +++ b/udmf/framework/common/itypes_util.h @@ -0,0 +1,603 @@ +/* + * Copyright (c) 2025 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 DISTRIBUTED_DATA_FRAMEWORKS_COMMON_ITYPES_UTIL_H +#define DISTRIBUTED_DATA_FRAMEWORKS_COMMON_ITYPES_UTIL_H +#include +#include +#include +#include +#include +#include +#include + +#include "iremote_object.h" +#include "message_parcel.h" +namespace OHOS { +template +struct is_container : std::false_type { +}; +template +struct is_container> : std::true_type { +}; +template +struct is_container> : std::true_type { +}; +namespace ITypesUtil { +inline constexpr size_t MAX_COUNT = 100000; +inline constexpr size_t MAX_SIZE = 1 * 1024 * 1024 * 1024; //1G +static inline bool Marshal(MessageParcel &data) +{ + return true; +} + +static inline bool Unmarshal(MessageParcel &data) +{ + return true; +} + +static inline bool Marshalling(int16_t input, MessageParcel &data) +{ + return data.WriteInt16(input); +} + +static inline bool Unmarshalling(int16_t &output, MessageParcel &data) +{ + return data.ReadInt16(output); +} + +static inline bool Marshalling(uint16_t input, MessageParcel &data) +{ + return data.WriteUint16(input); +} + +static inline bool Unmarshalling(uint16_t &output, MessageParcel &data) +{ + return data.ReadUint16(output); +} + +static inline bool Marshalling(uint32_t input, MessageParcel &data) +{ + return data.WriteUint32(input); +} + +static inline bool Unmarshalling(uint32_t &output, MessageParcel &data) +{ + return data.ReadUint32(output); +} + +static inline bool Marshalling(int32_t input, MessageParcel &data) +{ + return data.WriteInt32(input); +} + +static inline bool Unmarshalling(int32_t &output, MessageParcel &data) +{ + return data.ReadInt32(output); +} + +static inline bool Marshalling(uint64_t input, MessageParcel &data) +{ + return data.WriteUint64(input); +} + +static inline bool Unmarshalling(uint64_t &output, MessageParcel &data) +{ + return data.ReadUint64(output); +} + +static inline bool Marshalling(int64_t input, MessageParcel &data) +{ + return data.WriteInt64(input); +} + +static inline bool Unmarshalling(int64_t &output, MessageParcel &data) +{ + return data.ReadInt64(output); +} + +static inline bool Marshalling(double input, MessageParcel &data) +{ + return data.WriteDouble(input); +} + +static inline bool Unmarshalling(double &output, MessageParcel &data) +{ + return data.ReadDouble(output); +} + +static inline bool Marshalling(bool input, MessageParcel &data) +{ + return data.WriteBool(input); +} + +static inline bool Unmarshalling(bool &output, MessageParcel &data) +{ + return data.ReadBool(output); +} + +static inline bool Marshalling(const std::monostate &input, MessageParcel &data) +{ + return true; +} + +static inline bool Unmarshalling(std::monostate &output, MessageParcel &data) +{ + return true; +} + +static inline bool Marshalling(const std::vector &input, MessageParcel &data) +{ + return data.WriteFloatVector(input); +} + +static inline bool Unmarshalling(std::vector &output, MessageParcel &data) +{ + return data.ReadFloatVector(&output); +} + +static inline bool Marshalling(const std::string &input, MessageParcel &data) +{ + return data.WriteString(input); +} + +static inline bool Unmarshalling(std::string &output, MessageParcel &data) +{ + return data.ReadString(output); +} + +static inline bool Marshalling(const std::u16string &input, MessageParcel &data) +{ + return data.WriteString16(input); +} + +static inline bool Unmarshalling(std::u16string &output, MessageParcel &data) +{ + return data.ReadString16(output); +} + +static inline bool Marshalling(const std::vector &input, MessageParcel &data) +{ + return data.WriteUInt8Vector(input); +} + +static inline bool Unmarshalling(std::vector &output, MessageParcel &data) +{ + return data.ReadUInt8Vector(&output); +} + +static inline bool Marshalling(const sptr &input, MessageParcel &data) +{ + return data.WriteRemoteObject(input); +} + +static inline bool Unmarshalling(sptr &output, MessageParcel &data) +{ + output = data.ReadRemoteObject(); + return true; +} + +static inline bool Marshalling(IRemoteObject *input, MessageParcel &data) +{ + return data.WriteRemoteObject(input); +} + +template +bool ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data); +template +bool ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data); + +template +bool WriteVariant(uint32_t step, const _InTp &input, MessageParcel &data); +template +bool WriteVariant(uint32_t step, const _InTp &input, MessageParcel &data); + +template +bool Marshalling(const std::variant<_Types...> &input, MessageParcel &data); +template +bool Unmarshalling(std::variant<_Types...> &output, MessageParcel &data); + +template +bool Marshalling(const std::map &result, MessageParcel &parcel); +template +bool Unmarshalling(std::map &val, MessageParcel &parcel); + +template +bool Marshalling(const std::tuple &result, MessageParcel &parcel); +template +bool Unmarshalling(std::tuple &val, MessageParcel &parcel); + +template +bool Marshalling(const std::pair &result, MessageParcel &parcel); +template +bool Unmarshalling(std::pair &val, MessageParcel &parcel); + +template +bool Marshalling(const std::vector &val, MessageParcel &parcel); +template +bool Unmarshalling(std::vector &val, MessageParcel &parcel); + +template +bool Marshalling(const std::list &val, MessageParcel &parcel); +template +bool Unmarshalling(std::list &val, MessageParcel &parcel); + +template{}, int>::type = 0> +bool Marshalling(const T &input, MessageParcel &data) = delete; +template{}, int>::type = 0> +bool Unmarshalling(T &output, MessageParcel &data) = delete; + +template +bool Marshalling(const T &input, MessageParcel &data); +template +bool Unmarshalling(T &output, MessageParcel &data); + +template{}, int>::type = 0> +bool MarshalToContainer(const T &val, MessageParcel &parcel); +template{}, int>::type = 0> +bool UnmarshalFromContainer(T &val, MessageParcel &parcel); + +template +bool MarshalToBuffer(const T &input, int size, MessageParcel &data); +template +bool MarshalToBuffer(const std::vector &input, int size, MessageParcel &data); + +template +bool UnmarshalFromBuffer(MessageParcel &data, T &output); +template +bool UnmarshalFromBuffer(MessageParcel &data, std::vector &output); + +template +bool Marshal(MessageParcel &parcel, const T &first, const Types &...others); + +template +bool Unmarshal(MessageParcel &parcel, T &first, Types &...others); +} // namespace ITypesUtil + +template +bool ITypesUtil::ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data) +{ + return false; +} + +template +bool ITypesUtil::ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data) +{ + if (step == index) { + _First value{}; + auto success = ITypesUtil::Unmarshalling(value, data); + output = value; + return success; + } + return ITypesUtil::ReadVariant<_OutTp, _Rest...>(step + 1, index, output, data); +} + +template +bool ITypesUtil::WriteVariant(uint32_t step, const _InTp &input, MessageParcel &data) +{ + return false; +} + +template +bool ITypesUtil::WriteVariant(uint32_t step, const _InTp &input, MessageParcel &data) +{ + if (step == input.index()) { + return ITypesUtil::Marshalling(std::get<_First>(input), data); + } + return ITypesUtil::WriteVariant<_InTp, _Rest...>(step + 1, input, data); +} + +template +bool ITypesUtil::Marshalling(const std::variant<_Types...> &input, MessageParcel &data) +{ + uint32_t index = static_cast(input.index()); + if (!data.WriteUint32(index)) { + return false; + } + + return ITypesUtil::WriteVariant(0, input, data); +} + +template +bool ITypesUtil::Unmarshalling(std::variant<_Types...> &output, MessageParcel &data) +{ + uint32_t index = data.ReadUint32(); + if (index >= sizeof...(_Types)) { + return false; + } + + return ITypesUtil::ReadVariant(0, index, output, data); +} + +template +bool ITypesUtil::Marshalling(const std::map &result, MessageParcel &parcel) +{ + if (!parcel.WriteInt32(static_cast(result.size()))) { + return false; + } + for (const auto &entry : result) { + if ((!ITypesUtil::Marshalling(entry.first, parcel)) || (!ITypesUtil::Marshalling(entry.second, parcel))) { + return false; + } + } + return true; +} + +template +bool ITypesUtil::Unmarshalling(std::map &val, MessageParcel &parcel) +{ + int32_t size = 0; + if (!parcel.ReadInt32(size)) { + return false; + } + if (size < 0) { + return false; + } + + size_t readAbleSize = parcel.GetReadableBytes(); + if ((static_cast(size) > readAbleSize) || static_cast(size) > val.max_size()) { + return false; + } + + for (int32_t i = 0; i < size; i++) { + K key; + if ((!ITypesUtil::Unmarshalling(key, parcel)) || (!ITypesUtil::Unmarshalling(val[key], parcel))) { + return false; + } + } + return true; +} + +template +bool ITypesUtil::Marshalling(const std::tuple &result, MessageParcel &parcel) +{ + if (!ITypesUtil::Marshalling(std::get<0>(result), parcel)) { + return false; + } + if (!ITypesUtil::Marshalling(std::get<1>(result), parcel)) { + return false; + } + if (!ITypesUtil::Marshalling(std::get<2>(result), parcel)) { // 2 is the last element in tuple + return false; + } + return true; +} + +template +bool ITypesUtil::Unmarshalling(std::tuple &val, MessageParcel &parcel) +{ + F first; + if (!ITypesUtil::Unmarshalling(first, parcel)) { + return false; + } + S second; + if (!ITypesUtil::Unmarshalling(second, parcel)) { + return false; + } + T third; + if (!ITypesUtil::Unmarshalling(third, parcel)) { + return false; + } + val = { first, second, third }; + return true; +} + +template +bool ITypesUtil::Marshalling(const std::pair &result, MessageParcel &parcel) +{ + if (!ITypesUtil::Marshalling(result.first, parcel)) { + return false; + } + if (!ITypesUtil::Marshalling(result.second, parcel)) { + return false; + } + return true; +} + +template +bool ITypesUtil::Unmarshalling(std::pair &val, MessageParcel &parcel) +{ + F first; + if (!ITypesUtil::Unmarshalling(first, parcel)) { + return false; + } + S second; + if (!ITypesUtil::Unmarshalling(second, parcel)) { + return false; + } + val = { first, second }; + return true; +} + +template +bool ITypesUtil::Marshalling(const std::vector &val, MessageParcel &parcel) +{ + return ITypesUtil::MarshalToContainer(val, parcel); +} + +template +bool ITypesUtil::Unmarshalling(std::vector &val, MessageParcel &parcel) +{ + return ITypesUtil::UnmarshalFromContainer(val, parcel); +} + +template +bool ITypesUtil::Marshalling(const std::list &val, MessageParcel &parcel) +{ + return ITypesUtil::MarshalToContainer(val, parcel); +} + +template +bool ITypesUtil::Unmarshalling(std::list &val, MessageParcel &parcel) +{ + return ITypesUtil::UnmarshalFromContainer(val, parcel); +} + +template{}, int>::type> +bool ITypesUtil::MarshalToContainer(const T &val, MessageParcel &parcel) +{ + if (val.size() > INT_MAX) { + return false; + } + + if (!parcel.WriteInt32(static_cast(val.size()))) { + return false; + } + + for (auto &v : val) { + if (!ITypesUtil::Marshalling(v, parcel)) { + return false; + } + } + return true; +} + +template{}, int>::type> +bool ITypesUtil::UnmarshalFromContainer(T &val, MessageParcel &parcel) +{ + int32_t len = parcel.ReadInt32(); + if (len < 0) { + return false; + } + + size_t readAbleSize = parcel.GetReadableBytes(); + size_t size = static_cast(len); + if ((size > readAbleSize) || (size > val.max_size())) { + return false; + } + + val.clear(); + for (size_t i = 0; i < size; i++) { + typename T::value_type value; + if (!ITypesUtil::Unmarshalling(value, parcel)) { + return false; + } + val.emplace_back(std::move(value)); + } + return true; +} + +template +bool ITypesUtil::MarshalToBuffer(const T &input, int size, MessageParcel &data) +{ + if (size < 0 || static_cast(size) > MAX_SIZE || !data.WriteInt32(size)) { + return false; + } + if (size == 0) { + return true; + } + std::unique_ptr buffer = std::make_unique(size); + if (buffer == nullptr) { + return false; + } + + int leftSize = size; + uint8_t *cursor = buffer.get(); + if (!input.WriteToBuffer(cursor, leftSize)) { + return false; + } + return data.WriteRawData(buffer.get(), size); +} + +template +bool ITypesUtil::MarshalToBuffer(const std::vector &input, int size, MessageParcel &data) +{ + if (size < 0 || static_cast(size) > MAX_SIZE || input.size() > MAX_COUNT || !data.WriteInt32(size)) { + return false; + } + if (size == 0) { + return true; + } + if (!data.WriteInt32(input.size())) { + return false; + } + + std::unique_ptr buffer = std::make_unique(size); + if (buffer == nullptr) { + return false; + } + + uint8_t *cursor = buffer.get(); + int32_t left = size; + for (const auto &entry : input) { + if (!entry.WriteToBuffer(cursor, left)) { + return false; + } + } + return data.WriteRawData(buffer.get(), size); +} + +template +bool ITypesUtil::UnmarshalFromBuffer(MessageParcel &data, T &output) +{ + int32_t size = data.ReadInt32(); + if (size == 0) { + return true; + } + if (size < 0 || static_cast(size) > MAX_SIZE) { + return false; + } + const uint8_t *buffer = reinterpret_cast(data.ReadRawData(size)); + if (buffer == nullptr) { + return false; + } + return output.ReadFromBuffer(buffer, size); +} + +template +bool ITypesUtil::UnmarshalFromBuffer(MessageParcel &data, std::vector &output) +{ + int size = data.ReadInt32(); + if (size == 0) { + return true; + } + if (size < 0 || static_cast(size) > MAX_SIZE) { + return false; + } + int count = data.ReadInt32(); + const uint8_t *buffer = reinterpret_cast(data.ReadRawData(size)); + if (count < 0 || static_cast(count) > MAX_COUNT || buffer == nullptr) { + return false; + } + + output.resize(count); + for (auto &entry : output) { + if (!entry.ReadFromBuffer(buffer, size)) { + output.clear(); + return false; + } + } + return true; +} + +template +bool ITypesUtil::Marshal(MessageParcel &parcel, const T &first, const Types &...others) +{ + if (!ITypesUtil::Marshalling(first, parcel)) { + return false; + } + return ITypesUtil::Marshal(parcel, others...); +} + +template +bool ITypesUtil::Unmarshal(MessageParcel &parcel, T &first, Types &...others) +{ + if (!ITypesUtil::Unmarshalling(first, parcel)) { + return false; + } + return ITypesUtil::Unmarshal(parcel, others...); +} +} // namespace OHOS +#endif \ No newline at end of file diff --git a/udmf/framework/common/tlv_object.cpp b/udmf/framework/common/tlv_object.cpp index f68df376a5cd52501d2f0f09414445d844548f73..cbab4006674cfd811aa22bb34f8e5ed1c890fe96 100644 --- a/udmf/framework/common/tlv_object.cpp +++ b/udmf/framework/common/tlv_object.cpp @@ -131,8 +131,8 @@ size_t TLVObject::Count(const void *value) bool TLVObject::Write(TAG tag, const std::string &value) { if (!HasExpectBuffer(sizeof(TLVHead) + value.size())) { - LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv write. tag=%{public}hu, value=%{public}s", tag, - value.c_str()); + LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv write. tag=%{public}hu, value's size=%{public}zu", tag, + value.size()); return false; } auto tlvHead = reinterpret_cast(GetStartCursor()); @@ -141,8 +141,8 @@ bool TLVObject::Write(TAG tag, const std::string &value) if (!value.empty()) { auto err = memcpy_s(tlvHead->value, value.size(), value.c_str(), value.size()); if (err != EOK) { - LOG_ERROR(UDMF_FRAMEWORK, "memcpy error in tlv write. tag=%{public}hu, value=%{public}s", tag, - value.c_str()); + LOG_ERROR(UDMF_FRAMEWORK, "memcpy error in tlv write. tag=%{public}hu, value's size=%{public}zu", tag, + value.size()); return false; } } @@ -259,6 +259,7 @@ bool TLVObject::Read(OHOS::AAFwk::Want &value, const TLVHead &head) return false; } value = *want; + delete want; return true; } diff --git a/udmf/framework/common/tlv_object.h b/udmf/framework/common/tlv_object.h index 8a0f6f9b23b1c791eece31dddaf7f494531e9c1f..cb39dbc32a46e39127485bbfe7c3a53fb446aa19 100644 --- a/udmf/framework/common/tlv_object.h +++ b/udmf/framework/common/tlv_object.h @@ -26,8 +26,8 @@ namespace OHOS { namespace UDMF { #pragma pack(1) struct TLVHead { - uint16_t tag; - uint32_t len; + uint16_t tag {0}; + uint32_t len {0}; std::uint8_t value[0]; }; #pragma pack() @@ -83,10 +83,10 @@ private: void PrepareBufferForFile(size_t size); std::uint8_t *GetStartCursor(); - std::size_t total_ = 0; - std::size_t cursor_ = 0; - std::vector *buffer_; - std::FILE *file_ = nullptr; + std::size_t total_ {0}; + std::size_t cursor_ {0}; + std::vector *buffer_ {nullptr}; + std::FILE *file_ {nullptr}; }; template size_t TLVObject::CountBasic(const T &value) diff --git a/udmf/framework/common/tlv_tag.h b/udmf/framework/common/tlv_tag.h index 4511daa0ae4ce1a5bb278c335a38995a6496d88c..79bc09c2263cbb5b2268d9cf98a08f7b57a42933 100644 --- a/udmf/framework/common/tlv_tag.h +++ b/udmf/framework/common/tlv_tag.h @@ -90,6 +90,19 @@ enum class TAG : uint16_t { TAG_PROPERTIES_TIMESTAMP, TAG_PROPERTIES_SHARE_OPTIONS, TAG_PROPERTIES_EXTRAS, + TAG_RECORD_UTD_ID2, + TAG_SUMMARY_FILE_TYPES, + TAG_DATA_LOAD_INFO, + TAG_DATA_LOAD_KEY, + TAG_SET_TYPES, + TAG_RECORD_COUNT, + TAG_SET_ITEM, + TAG_SET_SIZE, + TAG_VISIBILITY, + TAG_APP_ID, + TAG_SUMMARY_SPECIFIC_SUMMARY, + TAG_SUMMARY_SUMMARY_FORMAT, + TAG_SUMMARY_VERSION, }; } #endif //UDMF_TLV_TAG_H diff --git a/udmf/framework/common/tlv_util.cpp b/udmf/framework/common/tlv_util.cpp index e67b7251e307926e403147e1fbc85f446c47734e..7dc72ebbfa0b96abcd7c9aaa9c532a08dd180cb6 100644 --- a/udmf/framework/common/tlv_util.cpp +++ b/udmf/framework/common/tlv_util.cpp @@ -18,6 +18,7 @@ #include "tlv_util.h" #include "udmf_utils.h" #include "logger.h" +#include "pixelmap_loader.h" #include "tlv_object.h" namespace OHOS { @@ -195,6 +196,10 @@ template <> bool Writing(const UnifiedKey &input, TLVObject &data, TAG tag) template <> bool Reading(UnifiedKey &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; @@ -254,6 +259,10 @@ template <> bool Writing(const UnifiedData &input, TLVObject &data, TAG tag) template <> bool Reading(UnifiedData &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; @@ -317,6 +326,10 @@ template <> bool Writing(const UnifiedDataProperties &input, TLVObject &data, TA template <> bool Reading(UnifiedDataProperties &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; @@ -418,12 +431,14 @@ template <> bool Reading(OHOS::AAFwk::WantParams &output, TLVObject &data, const free(buffer); return false; } + // The pointer returned by Unmarshalling needs to be manually deleted. auto wantParams = AAFwk::WantParams::Unmarshalling(*parcel); if (wantParams == nullptr) { LOG_ERROR(UDMF_FRAMEWORK, "Unmarshalling wantParams error in tlv read. tag=%{public}hu", head.tag); return false; } output = *wantParams; + delete wantParams; return true; } @@ -431,7 +446,8 @@ template <> size_t CountBufferSize(const UnifiedRecord &input, TLVObject &data) { return data.CountHead() + data.CountBasic(static_cast(input.GetType())) + data.Count(input.GetUid()) + CountBufferSize(input.GetOriginValue(), data) + data.Count(input.GetUtdId()) + - CountBufferSize(input.GetInnerEntries(), data) + CountBufferSize(input.GetUris(), data); + data.Count(input.GetUtdId2()) + CountBufferSize(input.GetInnerEntries(), data) + + CountBufferSize(input.GetUris(), data); } template <> bool Writing(const UnifiedRecord &input, TLVObject &data, TAG tag) @@ -451,6 +467,9 @@ template <> bool Writing(const UnifiedRecord &input, TLVObject &data, TAG tag) if (!data.Write(TAG::TAG_RECORD_UTD_ID, input.GetUtdId())) { return false; } + if (!data.Write(TAG::TAG_RECORD_UTD_ID2, input.GetUtdId2())) { + return false; + } if (!TLVUtil::Writing(input.GetInnerEntries(), data, TAG::TAG_RECORD_ENTRIES)) { return false; } @@ -462,6 +481,10 @@ template <> bool Writing(const UnifiedRecord &input, TLVObject &data, TAG tag) template <> bool Reading(UnifiedRecord &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } auto endCursor = data.GetCursor() + head.len; UDType dataType; std::string uid; @@ -472,6 +495,7 @@ template <> bool Reading(UnifiedRecord &output, TLVObject &data, const TLVHead & return false; } std::string utdId; + std::string utdId2; std::shared_ptr> entries; std::vector uriInfos; switch (headItem.tag) { @@ -499,6 +523,12 @@ template <> bool Reading(UnifiedRecord &output, TLVObject &data, const TLVHead & } output.SetUtdId(std::move(utdId)); break; + case static_cast(TAG::TAG_RECORD_UTD_ID2): + if (!data.Read(utdId2, headItem)) { + return false; + } + output.SetUtdId2(std::move(utdId2)); + break; case static_cast(TAG::TAG_RECORD_ENTRIES): if (!TLVUtil::Reading(entries, data, headItem)) { return false; @@ -526,7 +556,8 @@ template <> size_t CountBufferSize(const Runtime &input, TLVObject &data) data.CountBasic(static_cast(input.lastModifiedTime)) + data.CountBasic(static_cast(input.dataStatus)) + data.Count(input.sourcePackage) + data.Count(input.createPackage) + data.Count(input.deviceId) + TLVUtil::CountBufferSize(input.key, data) + - data.Count(input.sdkVersion) + TLVUtil::CountBufferSize(input.privileges, data); + data.Count(input.sdkVersion) + TLVUtil::CountBufferSize(input.privileges, data) + + data.CountBasic(static_cast(input.visibility)) + data.Count(input.appId); } template <> bool Writing(const Runtime &input, TLVObject &data, TAG tag) @@ -573,11 +604,21 @@ template <> bool Writing(const Runtime &input, TLVObject &data, TAG tag) if (!TLVUtil::Writing(input.sdkVersion, data, TAG::TAG_VERSION)) { return false; } + if (!data.WriteBasic(TAG::TAG_VISIBILITY, static_cast(input.visibility))) { + return false; + } + if (!TLVUtil::Writing(input.appId, data, TAG::TAG_APP_ID)) { + return false; + } return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); } template <> bool Reading(Runtime &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; @@ -587,6 +628,7 @@ template <> bool Reading(Runtime &output, TLVObject &data, const TLVHead &head) bool result = true; int64_t createTime = 0; int64_t lastModifiedTime = 0; + int32_t visibility = 0; switch (headItem.tag) { case static_cast(TAG::TAG_KEY): result = TLVUtil::Reading(output.key, data, headItem); @@ -629,6 +671,13 @@ template <> bool Reading(Runtime &output, TLVObject &data, const TLVHead &head) case static_cast(TAG::TAG_VERSION): result = data.Read(output.sdkVersion, headItem); break; + case static_cast(TAG::TAG_VISIBILITY): + result = data.ReadBasic(visibility, headItem); + output.visibility = static_cast(visibility); + break; + case static_cast(TAG::TAG_APP_ID): + result = data.Read(output.appId, headItem); + break; default: result = data.Skip(headItem); } @@ -664,6 +713,10 @@ template <> bool Writing(const Privilege &input, TLVObject &data, TAG tag) template <> bool Reading(Privilege &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; @@ -721,6 +774,10 @@ template <> bool Writing(const UriInfo &input, TLVObject &data, TAG tag) template <> bool Reading(UriInfo &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; @@ -754,7 +811,8 @@ template <> bool Reading(UriInfo &output, TLVObject &data, const TLVHead &head) template <> size_t CountBufferSize(const std::shared_ptr &input, TLVObject &data) { std::vector val; - if (!input->EncodeTlv(val)) { + PixelMapLoader loader; + if (!loader.EncodeTlv(input, val)) { LOG_ERROR(UDMF_FRAMEWORK, "Encode pixelMap error when CountBufferSize"); return 0; } @@ -765,7 +823,8 @@ template <> bool Writing(const std::shared_ptr &input, TL { InitWhenFirst(input, data); std::vector val; - if (!input->EncodeTlv(val)) { + PixelMapLoader loader; + if (!loader.EncodeTlv(input, val)) { LOG_ERROR(UDMF_FRAMEWORK, "Encode pixelMap error when Writing"); return false; } @@ -779,7 +838,8 @@ template <> bool Reading(std::shared_ptr &output, TLVObje LOG_ERROR(UDMF_FRAMEWORK, "Reading u8 vector error."); return false; } - output = std::shared_ptr(OHOS::Media::PixelMap::DecodeTlv(val)); + PixelMapLoader loader; + output = loader.DecodeTlv(val); if (output == nullptr) { LOG_ERROR(UDMF_FRAMEWORK, "DecodeTlv pixelMap error when Reading."); return false; @@ -882,7 +942,9 @@ template <> bool Reading(std::shared_ptr &output, TLVObject & template <> size_t CountBufferSize(const Summary &input, TLVObject &data) { - return data.CountHead() + CountBufferSize(input.summary, data) + data.CountBasic(input.totalSize); + return data.CountHead() + CountBufferSize(input.summary, data) + data.CountBasic(input.totalSize) + + CountBufferSize(input.specificSummary, data) + CountBufferSize(input.summaryFormat, data) + + data.CountBasic(input.version); } template <> bool Writing(const Summary &input, TLVObject &data, TAG tag) @@ -896,11 +958,24 @@ template <> bool Writing(const Summary &input, TLVObject &data, TAG tag) if (!data.WriteBasic(TAG::TAG_SUMMARY_SIZE, input.totalSize)) { return false; } + if (!TLVUtil::Writing(input.specificSummary, data, TAG::TAG_SUMMARY_SPECIFIC_SUMMARY)) { + return false; + } + if (!TLVUtil::Writing(input.summaryFormat, data, TAG::TAG_SUMMARY_SUMMARY_FORMAT)) { + return false; + } + if (!data.WriteBasic(TAG::TAG_SUMMARY_VERSION, input.version)) { + return false; + } return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); } template <> bool Reading(Summary &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; @@ -918,6 +993,79 @@ template <> bool Reading(Summary &output, TLVObject &data, const TLVHead &head) return false; } break; + case static_cast(TAG::TAG_SUMMARY_SPECIFIC_SUMMARY): + if (!TLVUtil::Reading(output.specificSummary, data, headItem)) { + return false; + } + break; + case static_cast(TAG::TAG_SUMMARY_SUMMARY_FORMAT): + if (!TLVUtil::Reading(output.summaryFormat, data, headItem)) { + return false; + } + break; + case static_cast(TAG::TAG_SUMMARY_VERSION): + if (!data.ReadBasic(output.version, headItem)) { + return false; + } + break; + default: + data.Skip(headItem); + } + } + return true; +} + +template <> size_t API_EXPORT CountBufferSize(const DataLoadInfo &input, TLVObject &data) +{ + return data.CountHead() + data.Count(input.sequenceKey) + CountBufferSize(input.types, data) + + data.CountBasic(input.recordCount); +} + +template <> bool API_EXPORT Writing(const DataLoadInfo &input, TLVObject &data, TAG tag) +{ + InitWhenFirst(input, data); + auto tagCursor = data.GetCursor(); + data.OffsetHead(); + if (!TLVUtil::Writing(input.sequenceKey, data, TAG::TAG_DATA_LOAD_KEY)) { + return false; + } + if (!TLVUtil::Writing(input.types, data, TAG::TAG_SET_TYPES)) { + return false; + } + if (!data.WriteBasic(TAG::TAG_RECORD_COUNT, input.recordCount)) { + return false; + } + return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); +} + +template <> bool API_EXPORT Reading(DataLoadInfo &output, TLVObject &data, const TLVHead &head) +{ + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } + auto endCursor = data.GetCursor() + head.len; + while (data.GetCursor() < endCursor) { + TLVHead headItem{}; + if (!data.ReadHead(headItem)) { + return false; + } + switch (headItem.tag) { + case static_cast(TAG::TAG_DATA_LOAD_KEY): + if (!TLVUtil::Reading(output.sequenceKey, data, headItem)) { + return false; + } + break; + case static_cast(TAG::TAG_SET_TYPES): + if (!TLVUtil::Reading(output.types, data, headItem)) { + return false; + } + break; + case static_cast(TAG::TAG_RECORD_COUNT): + if (!data.ReadBasic(output.recordCount, headItem)) { + return false; + } + break; default: data.Skip(headItem); } diff --git a/udmf/framework/common/tlv_util.h b/udmf/framework/common/tlv_util.h index 605ad4fe1b3e6e5472ce849045e0f564b174bef5..3bd9c85bc2bef4d28bcff78fb2ef3af199a3faec 100644 --- a/udmf/framework/common/tlv_util.h +++ b/udmf/framework/common/tlv_util.h @@ -52,6 +52,10 @@ template size_t API_EXPORT CountBufferSize(const std::m template bool API_EXPORT Writing(const std::map &input, TLVObject &data, TAG tag); template bool API_EXPORT Reading(std::map &output, TLVObject &data, const TLVHead &head); +template size_t API_EXPORT CountBufferSize(const std::set &input, TLVObject &data); +template bool API_EXPORT Writing(const std::set &input, TLVObject &data, TAG tag); +template bool API_EXPORT Reading(std::set &output, TLVObject &data, const TLVHead &head); + template <> size_t API_EXPORT CountBufferSize(const std::nullptr_t &input, TLVObject &data); template <> bool API_EXPORT Writing(const std::nullptr_t &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(std::nullptr_t &output, TLVObject &data, const TLVHead &head); @@ -135,6 +139,10 @@ template <> size_t API_EXPORT CountBufferSize(const Summary &input, TLVObject &d template <> bool API_EXPORT Writing(const Summary &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(Summary &output, TLVObject &data, const TLVHead &head); +template <> size_t API_EXPORT CountBufferSize(const DataLoadInfo &input, TLVObject &data); +template <> bool API_EXPORT Writing(const DataLoadInfo &input, TLVObject &data, TAG tag); +template <> bool API_EXPORT Reading(DataLoadInfo &output, TLVObject &data, const TLVHead &head); + template bool ReadTlv(T &output, TLVObject &data, TAG tag) { while (data.GetCursor() < data.GetTotal()) { @@ -231,6 +239,9 @@ template bool Writing(const std::vector &input, TLVObject &data, template bool Reading(std::vector &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead itemHead{}; @@ -287,6 +298,9 @@ template bool Writing(const std::map &input, TLVO template bool Reading(std::map &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headPair{}; @@ -389,6 +403,9 @@ bool ReadVariant(TLVObject &data, uint32_t step, uint32_t index, _OutTp &value, template bool Reading(std::variant<_Types...> &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + return false; + } uint32_t index = 0; auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { @@ -406,6 +423,57 @@ template bool Reading(std::variant<_Types...> &output, TLVO } return true; } + +template size_t CountBufferSize(const std::set &input, TLVObject &data) +{ + auto size = data.CountHead() + data.CountBasic(input.size()); + for (const auto &item : input) { + size += CountBufferSize(item, data); + } + return size; +} + +template bool Writing(const std::set &input, TLVObject &data, TAG tag) +{ + InitWhenFirst(input, data); + auto tagCursor = data.GetCursor(); + data.OffsetHead(); + if (!data.WriteBasic(TAG::TAG_SET_SIZE, input.size())) { + return false; + } + for (const auto &item : input) { + if (!Writing(item, data, TAG::TAG_SET_ITEM)) { + return false; + } + } + return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); +} + +template bool Reading(std::set &output, TLVObject &data, const TLVHead &head) +{ + if (head.len > data.GetTotal() - data.GetCursor()) { + return false; + } + auto endCursor = data.GetCursor() + head.len; + while (data.GetCursor() < endCursor) { + TLVHead itemHead{}; + if (!data.ReadHead(itemHead)) { + return false; + } + if (itemHead.tag == static_cast(TAG::TAG_SET_ITEM)) { + T item{}; + if (!Reading(item, data, itemHead)) { + return false; + } + output.insert(std::move(item)); + continue; + } + if (!data.Skip(itemHead)) { + return false; + } + } + return true; +} } // namespace TLVUtil } // namespace OHOS #endif // UDMF_TLV_UTIL_H diff --git a/udmf/framework/common/udmf_copy_file.cpp b/udmf/framework/common/udmf_copy_file.cpp index 827baebffc051121d2a8f96cdac282fdb7ccf9bc..b8d23290763c75ebc5a0f8b99245010af8279c3d 100644 --- a/udmf/framework/common/udmf_copy_file.cpp +++ b/udmf/framework/common/udmf_copy_file.cpp @@ -221,7 +221,7 @@ std::string UdmfCopyFile::GetFileName(const std::string &path) { std::string realSrc = path; if (IsRemote(path)) { - size_t index = path.rfind("?", 0); + size_t index = path.rfind("?"); realSrc = path.substr(0, index); } std::filesystem::path filePath(realSrc); diff --git a/udmf/framework/common/udmf_executor.cpp b/udmf/framework/common/udmf_executor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3a039ec442ef308ef29cca3ce9a7489a90b17e13 --- /dev/null +++ b/udmf/framework/common/udmf_executor.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 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 "udmf_executor.h" + +namespace OHOS::UDMF { +static constexpr const char *EXECUTOR_MASK = "TaskExecutor_UDMF"; + +UdmfExecutor::UdmfExecutor(size_t max, size_t min): executor_(max, min, EXECUTOR_MASK) {}; + +UdmfTaskId UdmfExecutor::Schedule(UdmfDuration delay, UdmfTask task) +{ + return executor_.Schedule(delay, task); +} + +bool UdmfExecutor::Remove(UdmfTaskId taskId, bool wait) +{ + return executor_.Remove(taskId, wait); +} + +UdmfTaskId UdmfExecutor::Execute(UdmfTask task) +{ + return executor_.Execute(std::move(task)); +} + +} // namespace OHOS::UDMF \ No newline at end of file diff --git a/udmf/framework/common/udmf_executor.h b/udmf/framework/common/udmf_executor.h new file mode 100644 index 0000000000000000000000000000000000000000..0f292fe9612d46deea9ec202ea95618cf0b42899 --- /dev/null +++ b/udmf/framework/common/udmf_executor.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 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 UDMF_EXECUTOR_H +#define UDMF_EXECUTOR_H + +#include "executor.h" +#include "executor_pool.h" + +namespace OHOS::UDMF { +using UdmfTaskId = Executor::TaskId; +using UdmfTask = std::function; +using UdmfDuration = std::chrono::steady_clock::duration; + +class UdmfExecutor { +public: + UdmfExecutor(size_t max, size_t min); + ~UdmfExecutor() = default; + UdmfTaskId Schedule(UdmfDuration delay, UdmfTask task); + bool Remove(UdmfTaskId taskId, bool wait = false); + UdmfTaskId Execute(UdmfTask task); +private: + ExecutorPool executor_; +}; + +} // namespace OHOS::UDMF +#endif // UDMF_EXECUTOR_H \ No newline at end of file diff --git a/udmf/framework/common/udmf_radar_reporter.cpp b/udmf/framework/common/udmf_radar_reporter.cpp index e90101f708e09e20593a93bc0140ad62a9e5b7e6..6a55a4c4e9a91dc4b59f56c2b0731bc231c703ff 100644 --- a/udmf/framework/common/udmf_radar_reporter.cpp +++ b/udmf/framework/common/udmf_radar_reporter.cpp @@ -90,6 +90,44 @@ void RadarReporterAdapter::ReportNormal(std::string func, int32_t scene, int32_t ); } +void RadarReporterAdapter::ReportNormal(std::string func, int32_t scene, int32_t stage, + int32_t stageRes, std::string &bundleName) +{ + 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 = { "APP_CALLER" }, + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(bundleName.c_str()) }, + .arraySize = 0 } + }; + OH_HiSysEvent_Write( + DOMAIN, + EVENT_NAME, + HISYSEVENT_BEHAVIOR, + params, + sizeof(params) / sizeof(params[0]) + ); +} + void RadarReporterAdapter::ReportFail( std::string func, int32_t scene, int32_t stage, int32_t stageRes, int32_t errorCode, int32_t state) { diff --git a/udmf/framework/common/udmf_radar_reporter.h b/udmf/framework/common/udmf_radar_reporter.h index 7591c0fd079d772c5028aed2c978b8f3607dc276..93baec2285d5f8e1f05575338c26139cb62e74ed 100644 --- a/udmf/framework/common/udmf_radar_reporter.h +++ b/udmf/framework/common/udmf_radar_reporter.h @@ -32,9 +32,10 @@ enum BizScene : int32_t { enum SetDataStage : int32_t { SET_DATA_BEGIN = 1, - VERIFY_SHARE_PERMISSIONS = 2, - GERERATE_DFS_URI = 3, - SET_DATA_END = 4 + SET_DATA_SERVICE_BEGIN = 2, + VERIFY_SHARE_PERMISSIONS = 3, + GERERATE_DFS_URI = 4, + SET_DATA_END = 5 }; enum SyncDataStage : int32_t { @@ -74,6 +75,7 @@ class API_EXPORT RadarReporterAdapter { public: static void ReportNormal(std::string func, int32_t scene, int32_t stage, int32_t stageRes, int32_t state); static void ReportNormal(std::string func, int32_t scene, int32_t stage, int32_t stageRes); + static void ReportNormal(std::string func, int32_t scene, int32_t stage, int32_t stageRes, std::string &bundleName); static void ReportFail( std::string func, int32_t scene, int32_t stage, int32_t stageRes, int32_t errorCode, int32_t state); static void ReportFail(std::string func, int32_t scene, int32_t stage, int32_t stageRes, int32_t errorCode); diff --git a/udmf/framework/common/udmf_types_util.cpp b/udmf/framework/common/udmf_types_util.cpp index 921f783b95a6649add9a0da2120756b4d78c6f97..fc9eedafdff71cda08039fbdde5147b6afd7a458 100644 --- a/udmf/framework/common/udmf_types_util.cpp +++ b/udmf/framework/common/udmf_types_util.cpp @@ -22,6 +22,7 @@ namespace OHOS { namespace ITypesUtil { using namespace UDMF; +static constexpr int32_t NORMAL_MAX_PARCEL_SIZE = 128 * 1024 * 1024; template<> bool Marshalling(const UnifiedData &input, MessageParcel &parcel) { @@ -42,9 +43,11 @@ bool Marshalling(const UnifiedData &input, MessageParcel &parcel) template<> bool Unmarshalling(UnifiedData &output, MessageParcel &parcel) { + auto dataSize = parcel.GetDataSize(); auto size = parcel.ReadInt32(); - if (size <= 0 || size > UnifiedData::MAX_DATA_SIZE) { - LOG_ERROR(UDMF_SERVICE, "UnifiedData is empty or too large!"); + if (size <= 0 || size > UnifiedData::MAX_DATA_SIZE || dataSize > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_SERVICE, + "UnifiedData is empty or too large, dataSize is %{public}zu, size is %{public}d", dataSize, size); return false; } auto rawData = parcel.ReadRawData(size); @@ -82,9 +85,11 @@ bool Marshalling(const std::vector &input, MessageParcel &parcel) template<> bool Unmarshalling(std::vector &output, MessageParcel &parcel) { + auto dataSize = parcel.GetDataSize(); auto size = parcel.ReadInt32(); - if (size <= 0 || size > UnifiedData::MAX_DATA_SIZE) { - LOG_ERROR(UDMF_SERVICE, "UnifiedDataSet is empty or too large!"); + if (size <= 0 || size > UnifiedData::MAX_DATA_SIZE || dataSize > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_SERVICE, + "UnifiedDataList is empty or too large, dataSize is %{public}zu, size is %{public}d", dataSize, size); return false; } const uint8_t *rawData = reinterpret_cast(parcel.ReadRawData(size)); @@ -104,13 +109,20 @@ bool Unmarshalling(std::vector &output, MessageParcel &parcel) template<> bool Marshalling(const Summary &input, MessageParcel &parcel) { - return ITypesUtil::Marshal(parcel, input.summary, input.totalSize); + return ITypesUtil::Marshal(parcel, input.summary, input.totalSize, input.specificSummary, + input.summaryFormat, input.version); } template<> bool Unmarshalling(Summary &output, MessageParcel &parcel) { - return ITypesUtil::Unmarshal(parcel, output.summary, output.totalSize); + auto dataSize = parcel.GetDataSize(); + if (dataSize <= 0 || dataSize > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_SERVICE, "UnifiedData is empty or too large, dataSize is %{public}zu", dataSize); + return false; + } + return ITypesUtil::Unmarshal(parcel, output.summary, output.totalSize, output.specificSummary, + output.summaryFormat, output.version); } template<> @@ -122,19 +134,29 @@ bool Marshalling(const Privilege &input, MessageParcel &parcel) template<> bool Unmarshalling(Privilege &output, MessageParcel &parcel) { + auto size = parcel.GetDataSize(); + if (size <= 0 || size > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_SERVICE, "Privilege is empty or too large, dataSize is %{public}zu", size); + return false; + } return ITypesUtil::Unmarshal(parcel, output.tokenId, output.readPermission, output.writePermission); } template<> bool Marshalling(const CustomOption &input, MessageParcel &parcel) { - return ITypesUtil::Marshal(parcel, input.intention); + return ITypesUtil::Marshal(parcel, input.intention, input.visibility); } template<> bool Unmarshalling(CustomOption &output, MessageParcel &parcel) { - return ITypesUtil::Unmarshal(parcel, output.intention); + auto size = parcel.GetDataSize(); + if (size <= 0 || size > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_SERVICE, "CustomOption is empty or too large, dataSize is %{public}zu", size); + return false; + } + return ITypesUtil::Unmarshal(parcel, output.intention, output.visibility); } template<> @@ -146,6 +168,11 @@ bool Marshalling(const QueryOption &input, MessageParcel &parcel) template<> bool Unmarshalling(QueryOption &output, MessageParcel &parcel) { + auto size = parcel.GetDataSize(); + if (size <= 0 || size > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_SERVICE, "QueryOption is empty or too large, dataSize is %{public}zu", size); + return false; + } return ITypesUtil::Unmarshal(parcel, output.key, output.intention); } @@ -159,6 +186,11 @@ bool Marshalling(const UDType &input, MessageParcel &parcel) template<> bool Unmarshalling(UDType &output, MessageParcel &parcel) { + auto size = parcel.GetDataSize(); + if (size <= 0 || size > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_FRAMEWORK, "UDType is empty or too large, dataSize is %{public}zu", size); + return false; + } int32_t type; if (!ITypesUtil::Unmarshal(parcel, type)) { LOG_ERROR(UDMF_FRAMEWORK, "Unmarshal UDType failed!"); @@ -182,6 +214,11 @@ bool Marshalling(const Intention &input, MessageParcel &parcel) template<> bool Unmarshalling(Intention &output, MessageParcel &parcel) { + auto size = parcel.GetDataSize(); + if (size <= 0 || size > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_FRAMEWORK, "Intention is empty or too large, dataSize is %{public}zu", size); + return false; + } int32_t intention; if (!ITypesUtil::Unmarshal(parcel, intention)) { LOG_ERROR(UDMF_FRAMEWORK, "Unmarshal Intention failed!"); @@ -195,6 +232,34 @@ bool Unmarshalling(Intention &output, MessageParcel &parcel) return true; } +template<> +bool Marshalling(const Visibility &input, MessageParcel &parcel) +{ + int32_t visibility = input; + return ITypesUtil::Marshal(parcel, visibility); +} + +template<> +bool Unmarshalling(Visibility &output, MessageParcel &parcel) +{ + auto size = parcel.GetDataSize(); + if (size <= 0 || size > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_FRAMEWORK, "Visibility is empty or too large, dataSize is %{public}zu", size); + return false; + } + int32_t visibility; + if (!ITypesUtil::Unmarshal(parcel, visibility)) { + LOG_ERROR(UDMF_FRAMEWORK, "Unmarshal Visibility failed!"); + return false; + } + if (visibility < VISIBILITY_ALL || visibility >= VISIBILITY_BUTT) { + LOG_ERROR(UDMF_FRAMEWORK, "invalid visibility : %{public}d", visibility); + return false; + } + output = static_cast(visibility); + return true; +} + template<> bool Marshalling(const AsyncProcessInfo &input, MessageParcel &parcel) { @@ -207,6 +272,11 @@ bool Marshalling(const AsyncProcessInfo &input, MessageParcel &parcel) template<> bool Unmarshalling(AsyncProcessInfo &output, MessageParcel &parcel) { + auto size = parcel.GetDataSize(); + if (size <= 0 || size > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_FRAMEWORK, "AsyncProcessInfo is empty or too large, dataSize is %{public}zu", size); + return false; + } uint32_t syncStatus; uint32_t permStatus; if (!ITypesUtil::Unmarshal(parcel, syncStatus, permStatus, output.srcDevName, output.syncFinished, output.syncTotal, @@ -223,5 +293,46 @@ bool Unmarshalling(AsyncProcessInfo &output, MessageParcel &parcel) output.permStatus = static_cast(permStatus); return true; } + +template<> +bool Marshalling(const DataLoadInfo &input, MessageParcel &parcel) +{ + std::vector dataSetBytes; + auto recordTlv = TLVObject(dataSetBytes); + if (!TLVUtil::Writing(input, recordTlv, TAG::TAG_DATA_LOAD_INFO)) { + LOG_ERROR(UDMF_SERVICE, "TLV writing failed!"); + return false; + } + if (!parcel.WriteInt32(static_cast(dataSetBytes.size())) + || !parcel.WriteRawData(dataSetBytes.data(), dataSetBytes.size())) { + LOG_ERROR(UDMF_SERVICE, "Marshall dataLoadInfo failed!"); + return false; + } + return true; +} + +template<> +bool Unmarshalling(DataLoadInfo &output, MessageParcel &parcel) +{ + auto size = parcel.ReadInt32(); + auto dataSize = parcel.GetDataSize(); + if (size <= 0 || size > NORMAL_MAX_PARCEL_SIZE || dataSize > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_SERVICE, + "DataLoadInfo is empty or too large, dataSize is %{public}zu, size is %{public}d", dataSize, size); + return false; + } + const uint8_t *rawData = reinterpret_cast(parcel.ReadRawData(size)); + if (rawData == nullptr) { + LOG_ERROR(UDMF_SERVICE, "RawData is null!"); + return false; + } + std::vector dataSetBytes(rawData, rawData + size); + auto dataTlv = TLVObject(dataSetBytes); + if (!TLVUtil::ReadTlv(output, dataTlv, TAG::TAG_DATA_LOAD_INFO)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshall dataLoadInfo failed!"); + return false; + } + return true; +} } // namespace ITypesUtil } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/common/udmf_types_util.h b/udmf/framework/common/udmf_types_util.h index f6293c989ee26fa89dc113e6d4dd8f597cdc7449..02d681908cfe442f7ab86e8e0271ee1fa6b3b754 100644 --- a/udmf/framework/common/udmf_types_util.h +++ b/udmf/framework/common/udmf_types_util.h @@ -21,6 +21,7 @@ #include "unified_data.h" #include "unified_meta.h" #include "unified_types.h" +#include "async_task_params.h" namespace OHOS { namespace ITypesUtil { @@ -31,7 +32,9 @@ using CustomOption = UDMF::CustomOption; using QueryOption = UDMF::QueryOption; using UDType = UDMF::UDType; using Intention = UDMF::Intention; +using Visibility = UDMF::Visibility; using AsyncProcessInfo = UDMF::AsyncProcessInfo; +using DataLoadInfo = UDMF::DataLoadInfo; template<> bool API_EXPORT Marshalling(const UnifiedData &input, MessageParcel &parcel); @@ -73,10 +76,20 @@ bool API_EXPORT Marshalling(const Intention &input, MessageParcel &parcel); template<> bool API_EXPORT Unmarshalling(Intention &output, MessageParcel &parcel); +template<> +bool API_EXPORT Marshalling(const Visibility &input, MessageParcel &parcel); +template<> +bool API_EXPORT Unmarshalling(Visibility &output, MessageParcel &parcel); + template<> bool API_EXPORT Marshalling(const AsyncProcessInfo &input, MessageParcel &parcel); template<> bool API_EXPORT Unmarshalling(AsyncProcessInfo &output, MessageParcel &parcel); + +template<> +bool API_EXPORT Marshalling(const DataLoadInfo &input, MessageParcel &parcel); +template<> +bool API_EXPORT Unmarshalling(DataLoadInfo &output, MessageParcel &parcel); } // namespace ITypesUtil } // namespace OHOS #endif // UDMF_TYPES_UTIL_H \ No newline at end of file diff --git a/udmf/framework/common/udmf_utils.cpp b/udmf/framework/common/udmf_utils.cpp index ac1f66f10a8a97e0c836504f40ff456258ca0a67..5ab66ec755f0c96a418c097c71e0d9fc72f461fb 100644 --- a/udmf/framework/common/udmf_utils.cpp +++ b/udmf/framework/common/udmf_utils.cpp @@ -29,20 +29,6 @@ static constexpr int MINIMUM = 48; static constexpr int MAXIMUM = 121; constexpr char SPECIAL = '^'; -std::vector StrSplit(const std::string &str, const std::string &delimiter) -{ - std::vector result; - size_t start = 0; - size_t end = str.find(delimiter); - while (end != std::string::npos) { - result.push_back(str.substr(start, end - start)); - start = end + delimiter.length(); - end = str.find(delimiter, start); - } - result.push_back(str.substr(start)); - return result; -} - std::vector Random(int32_t len, int32_t minimum, int32_t maximum) { std::random_device randomDevice; @@ -66,37 +52,36 @@ std::string GenerateId() return idStr.str(); } -std::string GetSdkVersionByToken(uint32_t tokenId) +bool IsTokenNative() { - if (Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId) != - Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) { - return ""; - } - Security::AccessToken::HapTokenInfo hapTokenInfo; - auto ret = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, hapTokenInfo); - if (ret != 0) { - return ""; + uint32_t tokenId = IPCSkeleton::GetSelfTokenID(); + if (tokenId == 0) { + return false; } - return std::to_string(hapTokenInfo.apiVersion); -} - -std::string GetCurrentSdkVersion() -{ - static const std::string sdkVersion = GetSdkVersionByToken(IPCSkeleton::GetSelfTokenID()); - return sdkVersion; + auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId); + return tokenType == Security::AccessToken::TypeATokenTypeEnum::TOKEN_NATIVE; } -bool IsTokenNative() +bool IsNativeCallingToken() { - uint32_t tokenId = IPCSkeleton::GetSelfTokenID(); + uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); if (tokenId == 0) { return false; } auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId); - LOG_DEBUG(UDMF_FRAMEWORK, "tokenId=%{public}u, tokenType=%{public}d", tokenId, tokenType); return tokenType == Security::AccessToken::TypeATokenTypeEnum::TOKEN_NATIVE; } +std::string GetSequenceKey(const std::string &udKey) +{ + auto pos = udKey.rfind('/'); + if (pos == std::string::npos || pos + 1 >= udKey.length()) { + LOG_ERROR(UDMF_FRAMEWORK, "Error udKey:%{public}s", udKey.c_str()); + return ""; + } + return udKey.substr(pos + 1); +} + } // namespace UTILS } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/common/udmf_utils.h b/udmf/framework/common/udmf_utils.h index 3d4fde6d507070837131f0afe566f4172a95bc18..9cc3f7c7a880f90d08282e9c3ce5d03d4fc8cc19 100644 --- a/udmf/framework/common/udmf_utils.h +++ b/udmf/framework/common/udmf_utils.h @@ -16,21 +16,21 @@ #ifndef UDMF_UTILS_H #define UDMF_UTILS_H +#include #include #include -#include #include "visibility.h" namespace OHOS { namespace UDMF { namespace UTILS { -std::vector StrSplit(const std::string &str, const std::string &delimiter); std::vector Random(int32_t len, int32_t minimum = 0, int32_t maximum = std::numeric_limits::max()); -std::string GenerateId(); +std::string API_EXPORT GenerateId(); std::string GetSdkVersionByToken(uint32_t tokenId); std::string GetCurrentSdkVersion(); - bool API_EXPORT IsTokenNative(); +bool API_EXPORT IsNativeCallingToken(); +std::string API_EXPORT GetSequenceKey(const std::string &udKey); } // namespace UTILS } // namespace UDMF diff --git a/udmf/framework/common/unittest/BUILD.gn b/udmf/framework/common/unittest/BUILD.gn index 8009d2c2d380137f132b9766f9c4b572383fb8c6..c9f842217a174276dd3c9c986d2042e5c167e35a 100644 --- a/udmf/framework/common/unittest/BUILD.gn +++ b/udmf/framework/common/unittest/BUILD.gn @@ -13,7 +13,7 @@ import("//build/test.gni") import("//foundation/distributeddatamgr/udmf/udmf.gni") -module_output_path = "udmf/common" +module_output_path = "udmf/udmf/common" ############################################################################### config("module_private_config") { @@ -25,6 +25,7 @@ config("module_private_config") { "${udmf_interfaces_path}/innerkits/data", "${udmf_framework_path}/common/unittest/mock/include", "${udmf_framework_path}/innerkitsimpl/client/", + "mock/", ] } @@ -36,12 +37,13 @@ common_deps = [ common_external_deps = [ "ability_base:want", "ability_base:zuri", + "ability_runtime:dataobs_manager", "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "access_token:libtoken_setproc", "bundle_framework:appexecfwk_core", "c_utils:utils", - "ffmpeg:libohosffmpeg", + "dfs_service:distributed_file_daemon_kit_inner", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", @@ -52,7 +54,6 @@ common_external_deps = [ "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", - "libexif:libexif", "samgr:samgr_proxy", ] @@ -69,7 +70,7 @@ ohos_unittest("UtdCfgsCheckerTest") { configs = [ ":module_private_config" ] deps = common_deps - + use_exceptions = true external_deps = common_external_deps } @@ -90,6 +91,31 @@ ohos_unittest("UdmfTypesUtilTest") { ] } +ohos_unittest("UdmfTypesUtilMockTest") { + module_out_path = module_output_path + + sources = [ + "mock/message_parcel_mock.cpp", + "udmf_types_util_mock_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = common_deps + + external_deps = common_external_deps + + external_deps += [ + "googletest:gmock_main", + "googletest:gtest_main", + ] + + defines = [ + "private=public", + "protected=public", + ] +} + ohos_unittest("UdmfTypesUtilAbnormalTest") { module_out_path = module_output_path @@ -118,12 +144,15 @@ ohos_unittest("UdmfTypesUtilAbnormalTest") { deps = [ "${udmf_interfaces_path}/innerkits:udmf_client", "${udmf_interfaces_path}/innerkits:utd_client", - "//third_party/googletest:gmock_main", - "//third_party/googletest:gtest_main", ] external_deps = common_external_deps + external_deps += [ + "googletest:gmock_main", + "googletest:gtest_main", + ] + defines = [ "private=public", "protected=public", @@ -152,6 +181,8 @@ ohos_unittest("TlvUtilTest") { "image_framework:image", "image_framework:image_native", "image_framework:pixelmap", + "ipc:ipc_single", + "kv_store:distributeddata_inner", ] defines = [ @@ -180,14 +211,54 @@ ohos_unittest("EndianConverterTest") { ] } +ohos_unittest("CopyFileTest") { + module_out_path = module_output_path + + sources = [ + "${udmf_framework_path}/common/udmf_copy_file.cpp", + "${udmf_framework_path}/common/udmf_executor.cpp", + "${udmf_framework_path}/common/udmf_utils.cpp", + "${udmf_framework_path}/common/unittest/mock/file_copy_manager_mock.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_async_client.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_client.cpp", + "${udmf_framework_path}/innerkitsimpl/common/progress_queue.cpp", + "${udmf_framework_path}/innerkitsimpl/common/unified_meta.cpp", + "${udmf_framework_path}/innerkitsimpl/convert/udmf_conversion.cpp", + "${udmf_framework_path}/innerkitsimpl/data/unified_data.cpp", + "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + "${udmf_framework_path}/innerkitsimpl/service/progress_callback.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_notifier_stub.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_service_client.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_service_proxy.cpp", + "udmf_copy_file_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = common_deps + + external_deps = common_external_deps + + external_deps += [ "app_file_service:fileuri_native" ] + + defines = [ + "private=public", + "protected=public", + ] + + use_exceptions = true +} + ############################################################################### group("unittest") { testonly = true deps = [ + ":CopyFileTest", ":EndianConverterTest", ":TlvUtilTest", ":UdmfTypesUtilAbnormalTest", + ":UdmfTypesUtilMockTest", ":UdmfTypesUtilTest", ":UtdCfgsCheckerTest", ] diff --git a/udmf/framework/common/unittest/mock/file_copy_manager_mock.cpp b/udmf/framework/common/unittest/mock/file_copy_manager_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..542c7eb8520984ec15ef93cd27b9792fe08945cc --- /dev/null +++ b/udmf/framework/common/unittest/mock/file_copy_manager_mock.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2025 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 "UdmfCopyFileMock" +#include "copy/file_copy_manager.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "logger.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +std::shared_ptr FileCopyManager::instance_ = nullptr; + +std::shared_ptr FileCopyManager::GetInstance() +{ + static auto instance = std::make_shared(); + return instance; +} + +int32_t FileCopyManager::Copy(const std::string &srcUri, const std::string &destUri, ProcessCallback &processCallback) +{ + return 0; +} + +int32_t FileCopyManager::ExecRemote(std::shared_ptr infos, ProcessCallback &processCallback) +{ + return 0; +} + +int32_t FileCopyManager::Cancel(const bool isKeepFiles) +{ + return 0; +} + +int32_t FileCopyManager::Cancel(const std::string &srcUri, const std::string &destUri, const bool isKeepFiles) +{ + return 0; +} + +void FileCopyManager::DeleteResFile(std::shared_ptr infos) +{ +} + +int32_t FileCopyManager::ExecLocal(std::shared_ptr infos) +{ + return 0; +} + +int32_t FileCopyManager::CopyFile(const std::string &src, const std::string &dest, std::shared_ptr infos) +{ + return 0; +} + +void fs_req_cleanup(uv_fs_t* req) +{ +} + +int32_t FileCopyManager::SendFileCore(std::shared_ptr srcFdg, + std::shared_ptr destFdg, std::shared_ptr infos) +{ + return 0; +} + +int32_t FileCopyManager::CopyDirFunc(const std::string &src, const std::string &dest, std::shared_ptr infos) +{ + return 0; +} + +int32_t FileCopyManager::CopySubDir(const std::string &srcPath, + const std::string &destPath, std::shared_ptr infos) +{ + return 0; +} + +int32_t FileCopyManager::RecurCopyDir(const std::string &srcPath, + const std::string &destPath, std::shared_ptr infos) +{ + return 0; +} + +void FileCopyManager::AddFileInfos(std::shared_ptr infos) +{ +} + +void FileCopyManager::RemoveFileInfos(std::shared_ptr infos) +{ +} + +int32_t FileCopyManager::CreateFileInfos(const std::string &srcUri, + const std::string &destUri, std::shared_ptr &infos) +{ + return 0; +} + +std::string GetModeFromFlags(unsigned int flags) +{ + return 0; +} + +int32_t FileCopyManager::OpenSrcFile(const std::string &srcPth, std::shared_ptr infos, int32_t &srcFd) +{ + return 0; +} + +int FileCopyManager::MakeDir(const std::string &path) +{ + return 0; +} + +bool FileCopyManager::IsRemoteUri(const std::string &uri) +{ + return true; +} + +bool FileCopyManager::IsMediaUri(const std::string &uriPath) +{ + return true; +} + +int32_t FileCopyManager::CheckOrCreatePath(const std::string &destPath) +{ + return 0; +} +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/common/unittest/mock/message_parcel_mock.cpp b/udmf/framework/common/unittest/mock/message_parcel_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ebf0ac6b19c3c4b60f3968e1c6b9126f44802358 --- /dev/null +++ b/udmf/framework/common/unittest/mock/message_parcel_mock.cpp @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2025 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 "iremote_broker.h" +#include "message_parcel_mock.h" + +namespace OHOS { +using namespace OHOS::UDMF; + +Parcelable::Parcelable() : Parcelable(false) +{} + +Parcelable::Parcelable(bool asRemote) +{ + asRemote_ = asRemote; + behavior_ = 0; +} + +bool MessageParcel::WriteInterfaceToken(std::u16string name) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteInterfaceToken(name); +} + +std::u16string MessageParcel::ReadInterfaceToken() +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return std::u16string(); + } + return UdmfMessageParcel::messageParcel->ReadInterfaceToken(); +} + +bool Parcel::WriteParcelable(const Parcelable *object) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteParcelable(object); +} + +bool Parcel::WriteInt32(int32_t value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteInt32(value); +} + +int32_t Parcel::ReadInt32() +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return -1; // -1: default err + } + return UdmfMessageParcel::messageParcel->ReadInt32(); +} + +bool Parcel::ReadInt32(int32_t &value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->ReadInt32(value); +} + +bool Parcel::WriteRemoteObject(const Parcelable *object) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteRemoteObject(object); +} + +bool MessageParcel::WriteRemoteObject(const sptr &object) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteRemoteObject(object); +} + +sptr MessageParcel::ReadRemoteObject() +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return nullptr; + } + return UdmfMessageParcel::messageParcel->ReadRemoteObject(); +} + +bool Parcel::ReadBool() +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->ReadBool(); +} + +bool Parcel::ReadBool(bool &value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->ReadBool(value); +} + +bool Parcel::WriteBool(bool value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteBool(value); +} + +bool Parcel::WriteString(const std::string &value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteString(value); +} + +bool Parcel::WriteCString(const char *value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteCString(value); +} + +bool Parcel::ReadString(std::string &value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->ReadString(value); +} + +bool Parcel::ReadStringVector(std::vector *value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->ReadStringVector(value); +} + +bool MessageParcel::WriteFileDescriptor(int fd) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteFileDescriptor(fd); +} + +int MessageParcel::ReadFileDescriptor() +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return -1; // -1: default err + } + return UdmfMessageParcel::messageParcel->ReadFileDescriptor(); +} + +bool Parcel::ReadUint32(uint32_t &value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->ReadUint32(value); +} + +bool Parcel::WriteUint64(uint64_t value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteUint64(value); +} + +bool Parcel::WriteUint16(uint16_t value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteUint16(value); +} + +bool Parcel::ReadUint64(uint64_t &value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->ReadUint64(value); +} + +bool Parcel::WriteStringVector(const std::vector &val) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteStringVector(val); +} + +bool Parcel::WriteUint32(uint32_t value) +{ + if (UdmfMessageParcel::messageParcel) { + return UdmfMessageParcel::messageParcel->WriteUint32(value); + } + return false; +} + +bool MessageParcel::WriteRawData(const void *data, size_t size) +{ + if (UdmfMessageParcel::messageParcel) { + return UdmfMessageParcel::messageParcel->WriteRawData(data, size); + } + return false; +} + +const void *MessageParcel::ReadRawData(size_t size) +{ + if (UdmfMessageParcel::messageParcel) { + return UdmfMessageParcel::messageParcel->ReadRawData(size); + } + return nullptr; +} + +uint32_t Parcel::ReadUint32() +{ + if (UdmfMessageParcel::messageParcel) { + return UdmfMessageParcel::messageParcel->ReadUint32(); + } + return 1; // : default value +} + +size_t Parcel::GetDataSize() const +{ + if (UdmfMessageParcel::messageParcel) { + return UdmfMessageParcel::messageParcel->GetDataSize(); + } + return 1; // : default value +} +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/common/unittest/mock/message_parcel_mock.h b/udmf/framework/common/unittest/mock/message_parcel_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..22bf9a6e480ce6385a2c58504c9ff8aaae0add9e --- /dev/null +++ b/udmf/framework/common/unittest/mock/message_parcel_mock.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2025 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 UDMF_MESSAGE_PARCEL_MOCK_H +#define UDMF_MESSAGE_PARCEL_MOCK_H + +#include +#include +#include + +#include "message_parcel.h" +#include "iremote_broker.h" + +namespace OHOS::UDMF { +class UdmfMessageParcel { +public: + virtual ~UdmfMessageParcel() = default; +public: + virtual bool WriteInterfaceToken(std::u16string name) = 0; + virtual std::u16string ReadInterfaceToken() = 0; + virtual bool WriteParcelable(const Parcelable *object) = 0; + virtual bool WriteInt32(int32_t value) = 0; + virtual int32_t ReadInt32() = 0; + virtual bool ReadInt32(int32_t &value) = 0; + virtual bool WriteRemoteObject(const Parcelable *object) = 0; + virtual bool WriteRemoteObject(const sptr &object) = 0; + virtual sptr ReadRemoteObject() = 0; + virtual bool ReadBool(); + virtual bool ReadBool(bool &value) = 0; + virtual bool WriteBool(bool value) = 0; + virtual bool WriteString(const std::string &value) = 0; + virtual bool WriteCString(const char *value) = 0; + virtual bool WriteFileDescriptor(int fd) = 0; + virtual bool ReadString(std::string &value) = 0; + virtual int ReadFileDescriptor() = 0; + virtual bool ReadStringVector(std::vector *value) = 0; + virtual bool ReadUint32(uint32_t &value) = 0; + virtual bool WriteUint64(uint64_t value) = 0; + virtual bool WriteUint16(uint16_t value) = 0; + virtual bool ReadUint64(uint64_t &value) = 0; + virtual bool WriteStringVector(const std::vector &val) = 0; + virtual bool WriteUint32(uint32_t value) = 0; + virtual bool WriteRawData(const void *data, size_t size) = 0; + virtual const void *ReadRawData(size_t size) = 0; + virtual uint32_t ReadUint32() = 0; + virtual size_t GetDataSize() = 0; +public: + static inline std::shared_ptr messageParcel = nullptr; +}; + +class MessageParcelMock : public UdmfMessageParcel { +public: + MOCK_METHOD1(WriteInterfaceToken, bool(std::u16string name)); + MOCK_METHOD0(ReadInterfaceToken, std::u16string()); + MOCK_METHOD1(WriteParcelable, bool(const Parcelable *object)); + MOCK_METHOD1(WriteInt32, bool(int32_t value)); + MOCK_METHOD0(ReadInt32, int32_t()); + MOCK_METHOD1(ReadInt32, bool(int32_t &value)); + MOCK_METHOD1(WriteRemoteObject, bool(const Parcelable *object)); + MOCK_METHOD1(WriteRemoteObject, bool(const sptr &object)); + MOCK_METHOD0(ReadRemoteObject, sptr()); + MOCK_METHOD0(ReadBool, bool()); + MOCK_METHOD1(ReadBool, bool(bool &value)); + MOCK_METHOD1(WriteBool, bool(bool value)); + MOCK_METHOD1(WriteString, bool(const std::string &value)); + MOCK_METHOD1(WriteCString, bool(const char *value)); + MOCK_METHOD1(WriteFileDescriptor, bool(int fd)); + MOCK_METHOD1(ReadString, bool(std::string &value)); + MOCK_METHOD0(ReadFileDescriptor, int()); + MOCK_METHOD1(ReadStringVector, bool(std::vector *value)); + MOCK_METHOD1(ReadUint32, bool(uint32_t &value)); + MOCK_METHOD1(WriteUint64, bool(uint64_t value)); + MOCK_METHOD1(WriteUint16, bool(uint16_t value)); + MOCK_METHOD1(ReadUint64, bool(uint64_t &value)); + MOCK_METHOD1(WriteStringVector, bool(const std::vector &val)); + MOCK_METHOD1(WriteUint32, bool(uint32_t value)); + MOCK_METHOD2(WriteRawData, bool(const void *data, size_t size)); + MOCK_METHOD1(ReadRawData, const void*(size_t size)); + MOCK_METHOD0(ReadUint32, uint32_t()); + MOCK_METHOD0(GetDataSize, size_t()); +}; +} +#endif // UDMF_MESSAGE_PARCEL_MOCK_H diff --git a/udmf/framework/common/unittest/mock/tlv_util_mock.cpp b/udmf/framework/common/unittest/mock/tlv_util_mock.cpp index 801a10165fa7bd86e431e0306117487283d40663..adff8a6e7af0791bc19eced40a08a965f29dd210 100644 --- a/udmf/framework/common/unittest/mock/tlv_util_mock.cpp +++ b/udmf/framework/common/unittest/mock/tlv_util_mock.cpp @@ -143,7 +143,10 @@ template <> size_t CountBufferSize(const UnifiedData &input, TLVObject &data) template <> bool Writing(const UnifiedData &input, TLVObject &data, TAG tag) { - return false; + if (input.dataId_ == 0) { + return false; + } + return true; } template <> bool Reading(UnifiedData &output, TLVObject &data, const TLVHead &head) @@ -227,6 +230,19 @@ template <> bool Reading(std::shared_ptr &output, TLVObject & return true; } +template <> size_t API_EXPORT CountBufferSize(const DataLoadInfo &input, TLVObject &data) +{ + return sizeof(TLVHead); +} + +template <> bool API_EXPORT Writing(const DataLoadInfo &input, TLVObject &data, TAG tag) +{ + return true; +} +template <> bool API_EXPORT Reading(DataLoadInfo &output, TLVObject &data, const TLVHead &head) +{ + return true; +} } // namespace TLVUtil } // namespace OHOS diff --git a/udmf/framework/common/unittest/tlv_util_test.cpp b/udmf/framework/common/unittest/tlv_util_test.cpp index 2079cda3a550ca1007dd81e5f64d40f217c1456f..9d657dcd56fe422744ad279fab3f780841fec5bc 100644 --- a/udmf/framework/common/unittest/tlv_util_test.cpp +++ b/udmf/framework/common/unittest/tlv_util_test.cpp @@ -179,7 +179,7 @@ HWTEST_F(TlvUtilTest, CountBufferSize_004, TestSize.Level1) EXPECT_EQ(4 * sizeof(TLVHead) + sizeof(int32_t), TLVUtil::CountBufferSize(privilege, tlvObject)); Runtime runtime; - EXPECT_EQ(19 * sizeof(TLVHead) + sizeof(bool) + sizeof(size_t) + 2 * sizeof(int64_t) + 2 * sizeof(int32_t) + + EXPECT_EQ(21 * sizeof(TLVHead) + sizeof(bool) + sizeof(size_t) + 2 * sizeof(int64_t) + 3 * sizeof(int32_t) + 2 * sizeof(uint32_t), TLVUtil::CountBufferSize(runtime, tlvObject)); LOG_INFO(UDMF_TEST, "CountBufferSize_004 end."); @@ -301,6 +301,7 @@ HWTEST_F(TlvUtilTest, WritingAndReading_002, TestSize.Level1) runtime.dataVersion = 3; runtime.createPackage = "package"; runtime.isPrivate = true; + runtime.appId = "appId"; std::vector dataBytes; auto tlvObject = TLVObject(dataBytes); @@ -320,6 +321,7 @@ HWTEST_F(TlvUtilTest, WritingAndReading_002, TestSize.Level1) EXPECT_EQ(runtime.privileges[0].tokenId, runtimeResult.privileges[0].tokenId); EXPECT_EQ(runtime.privileges[1].writePermission, runtimeResult.privileges[1].writePermission); EXPECT_EQ(runtime.privileges[1].tokenId, runtimeResult.privileges[1].tokenId); + EXPECT_EQ(runtime.appId, runtimeResult.appId); LOG_INFO(UDMF_TEST, "WritingAndReading_002 end."); } @@ -546,6 +548,56 @@ HWTEST_F(TlvUtilTest, WritingAndReading_005, TestSize.Level1) LOG_INFO(UDMF_TEST, "WritingAndReading_005 end."); } +/* * + * @tc.name: WritingAndReading_008 + * @tc.desc: test Runtime for Writing And Reading + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, WritingAndReading_008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "WritingAndReading_002 begin."); + UnifiedKey key; + key.key = "123456"; + Privilege privilege; + privilege.readPermission = "read"; + privilege.tokenId = 333; + Privilege privilege2; + privilege2.writePermission = "read"; + privilege2.tokenId = 444; + Runtime runtime; + runtime.dataStatus = DELETED; + runtime.key = key; + runtime.privileges.push_back(privilege); + runtime.privileges.push_back(privilege2); + runtime.createTime = 1; + runtime.dataVersion = 3; + runtime.createPackage = "package"; + runtime.isPrivate = true; + runtime.appId = "appId"; + + std::vector dataBytes; + auto tlvObject = TLVObject(dataBytes); + EXPECT_TRUE(TLVUtil::Writing(runtime, tlvObject, TAG::TAG_APP_ID)); + + tlvObject.ResetCursor(); + Runtime runtimeResult; + EXPECT_TRUE(TLVUtil::ReadTlv(runtimeResult, tlvObject, TAG::TAG_APP_ID)); + EXPECT_EQ(runtime.key.key, runtimeResult.key.key); + EXPECT_EQ(runtime.key.key, runtimeResult.key.key); + EXPECT_EQ(runtime.dataStatus, runtimeResult.dataStatus); + EXPECT_EQ(runtime.createTime, runtimeResult.createTime); + EXPECT_EQ(runtime.dataVersion, runtimeResult.dataVersion); + EXPECT_EQ(runtime.createPackage, runtimeResult.createPackage); + EXPECT_EQ(runtime.isPrivate, runtimeResult.isPrivate); + EXPECT_EQ(runtime.appId, runtimeResult.appId); + EXPECT_EQ(runtime.privileges[0].readPermission, runtimeResult.privileges[0].readPermission); + EXPECT_EQ(runtime.privileges[0].tokenId, runtimeResult.privileges[0].tokenId); + EXPECT_EQ(runtime.privileges[1].writePermission, runtimeResult.privileges[1].writePermission); + EXPECT_EQ(runtime.privileges[1].tokenId, runtimeResult.privileges[1].tokenId); + + LOG_INFO(UDMF_TEST, "WritingAndReading_008 end."); +} + /* * * @tc.name: WritingAndReadingFile_001 * @tc.desc: test Unified Data for Writing And Reading @@ -803,4 +855,398 @@ HWTEST_F(TlvUtilTest, WritingAndReading_007, TestSize.Level1) EXPECT_EQ(idValue, wantParamsResult.GetIntParam(idKey, 0)); LOG_INFO(UDMF_TEST, "WritingAndReading_007 end."); } + +/* * + * @tc.name: Reading_001 + * @tc.desc: Normal test of Reading + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_001, TestSize.Level1) +{ + std::nullptr_t output; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + TLVHead head; + bool ret = TLVUtil::Reading(output, data, head); + EXPECT_EQ(ret, data.Read(output, head)); +} + +/* * + * @tc.name: Reading_002 + * @tc.desc: Abnormal test of Reading, data is invalid + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_002, TestSize.Level1) +{ + DataStatus output; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + TLVHead head; + bool ret = TLVUtil::Reading(output, data, head); + EXPECT_FALSE(ret); +} + +/* * + * @tc.name: Reading_003 + * @tc.desc: Abnormal test of Reading, buffer_ is nullptr + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_003, TestSize.Level1) +{ + Object output; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + TLVHead head; + bool ret = TLVUtil::Reading(output, data, head); + EXPECT_FALSE(ret); +} + +/* * + * @tc.name: Reading_004 + * @tc.desc: Abnormal test of Reading, data is invalid + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_004, TestSize.Level1) +{ + OHOS::AAFwk::WantParams output; + TLVObject data; + TLVHead head; + bool ret = TLVUtil::Reading(output, data, head); + EXPECT_FALSE(ret); +} + +/* * + * @tc.name: Reading_005 + * @tc.desc: Test reading DataStatus with value below WORKING + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Reading_005 begin."); + int32_t invalidStatus = -1; + TLVHead head; + head.tag = static_cast(TAG::TAG_DATA_STATUS); + head.len = sizeof(invalidStatus); + + std::vector buffer; + buffer.resize(sizeof(head) + head.len); + + errno_t err = memcpy_s(buffer.data(), buffer.size(), &head, sizeof(head)); + ASSERT_EQ(err, EOK); + err = memcpy_s(buffer.data() + sizeof(head), buffer.size() - sizeof(head), + &invalidStatus, sizeof(invalidStatus)); + ASSERT_EQ(err, EOK); + TLVObject data(buffer); + TLVHead readHead; + ASSERT_TRUE(data.ReadHead(readHead)); + + DataStatus output; + EXPECT_FALSE(TLVUtil::Reading(output, data, readHead)); + LOG_INFO(UDMF_TEST, "Reading_005 end."); +} + +/* * + * @tc.name: Reading_006 + * @tc.desc: Test reading DataStatus with value at or above FADE + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Reading_006 begin."); + int32_t invalidStatus = 3; + TLVHead head; + head.tag = static_cast(TAG::TAG_DATA_STATUS); + head.len = sizeof(invalidStatus); + + std::vector buffer; + buffer.resize(sizeof(head) + head.len); + errno_t err = memcpy_s(buffer.data(), buffer.size(), &head, sizeof(head)); + ASSERT_EQ(err, EOK); + err = memcpy_s(buffer.data() + sizeof(head), buffer.size() - sizeof(head), + &invalidStatus, sizeof(invalidStatus)); + ASSERT_EQ(err, EOK); + TLVObject data(buffer); + TLVHead readHead; + ASSERT_TRUE(data.ReadHead(readHead)); + + DataStatus output; + EXPECT_FALSE(TLVUtil::Reading(output, data, readHead)); + LOG_INFO(UDMF_TEST, "Reading_006 end."); +} + +/* * + * @tc.name: Reading_007 + * @tc.desc: Test reading Object with incorrect inner tag + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_007, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Reading_007 begin."); + TLVHead outerHead; + outerHead.tag = static_cast(TAG::TAG_OBJECT_VALUE); + outerHead.len = sizeof(TLVHead) + 4; + + TLVHead innerHead; + innerHead.tag = static_cast(TAG::TAG_STRING); + innerHead.len = 4; + + const char* testData = "test"; + std::vector buffer; + buffer.resize(sizeof(outerHead) + sizeof(innerHead) + innerHead.len); + + errno_t err = memcpy_s(buffer.data(), buffer.size(), &outerHead, sizeof(outerHead)); + ASSERT_EQ(err, EOK); + err = memcpy_s(buffer.data() + sizeof(outerHead), buffer.size() - sizeof(outerHead), + &innerHead, sizeof(innerHead)); + ASSERT_EQ(err, EOK); + err = memcpy_s(buffer.data() + sizeof(outerHead) + sizeof(innerHead), + buffer.size() - sizeof(outerHead) - sizeof(innerHead), + testData, innerHead.len); + ASSERT_EQ(err, EOK); + + TLVObject data(buffer); + TLVHead readOuterHead; + ASSERT_TRUE(data.ReadHead(readOuterHead)); + + Object output; + bool result = TLVUtil::Reading(output, data, readOuterHead); + EXPECT_FALSE(result); + LOG_INFO(UDMF_TEST, "Reading_007 end."); +} + +/* * + * @tc.name: Writing_001 + * @tc.desc: Abnormal test of Writing, input.tag is invalid + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Writing_001, TestSize.Level1) +{ + UnifiedDataProperties input; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + TAG tag = TAG::TAG_NULL; + input.tag = "test"; + bool ret = TLVUtil::Writing(input, data, tag); + EXPECT_FALSE(ret); +} + +/* * + * @tc.name: Writing_002 + * @tc.desc: Abnormal test of Writing, input.timestamp is invalid + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Writing_002, TestSize.Level1) +{ + UnifiedDataProperties input; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + std::string dataFile = "demo1"; + std::vector dataBytes; + auto tlvObject = TLVObject(dataBytes); + std::FILE *file = fopen(dataFile.c_str(), "w+"); + tlvObject.SetFile(file); + TAG tag = TAG::TAG_NULL; + input.tag = "test"; + input.timestamp = 0; + bool ret = TLVUtil::Writing(input, data, tag); + EXPECT_FALSE(ret); + fclose(file); +} + +/* * + * @tc.name: Writing_003 + * @tc.desc: Abnormal test of Writing input is invalid + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Writing_003, TestSize.Level1) +{ + Privilege input; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + TAG tag = TAG::TAG_NULL; + bool ret = TLVUtil::Writing(input, data, tag); + EXPECT_FALSE(ret); +} + +/* * + * @tc.name: CountBufferSize_006 + * @tc.desc: Abnormal test of CountBufferSize, input is nullptr + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, CountBufferSize_006, TestSize.Level1) +{ + std::shared_ptr> input = nullptr; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + size_t ret = TLVUtil::CountBufferSize(input, data); + EXPECT_EQ(ret, data.CountHead()); +} + +/* * + * @tc.name: WritingSet001 + * @tc.desc: Normal test of Writing Set + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, WritingSet001, TestSize.Level1) { + LOG_INFO(UDMF_TEST, "WritingSet001 begin."); + std::set data = {"typeA", "typeB", "typeC"}; + + std::vector dataBytes; + auto tlvObject = TLVObject(dataBytes); + auto result = TLVUtil::Writing(data, tlvObject, TAG::TAG_SET_TYPES); + EXPECT_TRUE(result); + + tlvObject.ResetCursor(); + std::set dataResult; + result = TLVUtil::ReadTlv(dataResult, tlvObject, TAG::TAG_SET_TYPES); + EXPECT_TRUE(result); + ASSERT_EQ(data.size(), dataResult.size()); + for (auto &item : data) { + EXPECT_TRUE(dataResult.find(item) != dataResult.end()); + } + LOG_INFO(UDMF_TEST, "WritingSet001 end."); +} + +/* * + * @tc.name: WritingDataLoadInfo001 + * @tc.desc: Normal test of Writing DataLoadInfo + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, WritingDataLoadInfo001, TestSize.Level1) { + LOG_INFO(UDMF_TEST, "WritingDataLoadInfo001 begin."); + DataLoadInfo normalData; + normalData.sequenceKey = "seq_2023"; + normalData.types = {"typeA", "typeB", "typeC"}; + normalData.recordCount = 1000; + + std::vector dataBytes; + auto tlvObject = TLVObject(dataBytes); + auto result = TLVUtil::Writing(normalData, tlvObject, TAG::TAG_DATA_LOAD_INFO); + EXPECT_TRUE(result); + + tlvObject.ResetCursor(); + DataLoadInfo normalDataResult; + result = TLVUtil::ReadTlv(normalDataResult, tlvObject, TAG::TAG_DATA_LOAD_INFO); + EXPECT_TRUE(result); + EXPECT_EQ(normalData.sequenceKey, normalDataResult.sequenceKey); + EXPECT_EQ(normalData.recordCount, normalDataResult.recordCount); + ASSERT_EQ(normalData.types.size(), normalDataResult.types.size()); + for (auto &item : normalData.types) { + EXPECT_TRUE(normalDataResult.types.find(item) != normalDataResult.types.end()); + } + LOG_INFO(UDMF_TEST, "WritingDataLoadInfo001 end."); +} + +/* * + * @tc.name: WritingDataLoadInfo002 + * @tc.desc: Normal test of Writing boundary DataLoadInfo + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, WritingDataLoadInfo002, TestSize.Level1) { + DataLoadInfo boundaryData; + boundaryData.sequenceKey = ""; + boundaryData.types = {}; + boundaryData.recordCount = 0; + + std::vector dataBytes; + auto tlvObject = TLVObject(dataBytes); + auto result = TLVUtil::Writing(boundaryData, tlvObject, TAG::TAG_DATA_LOAD_INFO); + EXPECT_TRUE(result); + + tlvObject.ResetCursor(); + DataLoadInfo boundaryDataResult; + result = TLVUtil::ReadTlv(boundaryDataResult, tlvObject, TAG::TAG_DATA_LOAD_INFO); + EXPECT_TRUE(result); + EXPECT_EQ(boundaryData.sequenceKey, boundaryDataResult.sequenceKey); + EXPECT_EQ(boundaryData.recordCount, boundaryDataResult.recordCount); + ASSERT_EQ(boundaryData.types.size(), boundaryDataResult.types.size()); + for (auto &item : boundaryData.types) { + EXPECT_TRUE(boundaryDataResult.types.find(item) != boundaryDataResult.types.end()); + } + LOG_INFO(UDMF_TEST, "WritingDataLoadInfo002 end."); +} + +/* * + * @tc.name: Reading_008 + * @tc.desc: test Reading fun + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Reading_008 begin."); + UnifiedKey uKey; + UnifiedData uData; + UnifiedDataProperties uProperties; + UnifiedRecord uRecord; + Runtime rTime; + Privilege privilege; + UriInfo uInfo; + Summary summary; + DataLoadInfo loadInfo; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + TLVHead head; + head.len = data.GetTotal() - data.GetCursor() + 1; + auto result = TLVUtil::Reading(uKey, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(uData, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(uProperties, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(uRecord, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(rTime, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(privilege, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(uInfo, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(summary, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(loadInfo, data, head); + EXPECT_FALSE(result); + LOG_INFO(UDMF_TEST, "Reading_008 end."); +} + +/* * + * @tc.name: Reading_009 + * @tc.desc: test Reading fun + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_009, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Reading_009 begin."); + UnifiedKey uKey; + UnifiedData uData; + UnifiedDataProperties uProperties; + UnifiedRecord uRecord; + Runtime rTime; + Privilege privilege; + UriInfo uInfo; + Summary summary; + DataLoadInfo loadInfo; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + TLVHead head; + head.len = data.GetTotal() - data.GetCursor() - 1; + auto result = TLVUtil::Reading(uKey, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(uData, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(uProperties, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(uRecord, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(rTime, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(privilege, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(uInfo, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(summary, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(loadInfo, data, head); + EXPECT_FALSE(result); + LOG_INFO(UDMF_TEST, "Reading_009 end."); +} } diff --git a/udmf/framework/common/unittest/udmf_copy_file_test.cpp b/udmf/framework/common/unittest/udmf_copy_file_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a9245403311b09fad2a3c4bb8108e80bef5c09ce --- /dev/null +++ b/udmf/framework/common/unittest/udmf_copy_file_test.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2025 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 "CopyFileTest" + +#include +#include +#include + +#include "logger.h" +#include "udmf_copy_file.h" + +using namespace testing::ext; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { + +class CopyFileTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void CopyFileTest::SetUpTestCase() +{ +} + +void CopyFileTest::TearDownTestCase() +{ +} + +void CopyFileTest::SetUp() +{ +} + +void CopyFileTest::TearDown() +{ +} + +/** +* @tc.name: GetInstance +* @tc.desc: GetInstance Should Return Same Instance +* @tc.type: FUNC +*/ +HWTEST_F(CopyFileTest, GetInstance, TestSize.Level1) +{ + auto& instance1 = UdmfCopyFile::GetInstance(); + auto& instance2 = UdmfCopyFile::GetInstance(); + ASSERT_EQ(&instance1, &instance2); +} + +/** +* @tc.name: Copy001 +* @tc.desc: Copy Should Return Canceled When ProgressQueue Is Cancel +* @tc.type: FUNC +*/ +HWTEST_F(CopyFileTest, Copy001, TestSize.Level1) +{ + auto asyncHelper = std::make_unique(); + asyncHelper->progressQueue.Cancel(); + ASSERT_TRUE(asyncHelper->progressQueue.IsCancel()); + + auto result = UdmfCopyFile::GetInstance().Copy(asyncHelper); + ASSERT_EQ(result, E_COPY_CANCELED); +} + +/** +* @tc.name: Copy002 +* @tc.desc: normal copy test +* @tc.type: FUNC +*/ +HWTEST_F(CopyFileTest, Copy002, TestSize.Level1) +{ + std::string srcUri = "test_src.txt"; + std::string destUri = "test_dest.txt"; + auto record = std::make_shared(); + auto asyncHelper = std::make_unique(); + UdmfCopyFile::CopyContext context(asyncHelper); + + bool result = UdmfCopyFile::GetInstance().CopyFile(srcUri, destUri, record, context); + EXPECT_TRUE(result); + EXPECT_EQ(context.status, E_OK); +} + +/** +* @tc.name: ConstructDestUri +* @tc.desc: Construct DestUri Should Correctly Construct Destination Path +* @tc.type: FUNC +*/ +HWTEST_F(CopyFileTest, ConstructDestUri, TestSize.Level1) +{ + std::string destUri = "/destination"; + std::string srcUri = "/source/file.txt"; + auto result = UdmfCopyFile::GetInstance().ConstructDestUri(destUri, srcUri); + ASSERT_EQ(result, "/destination/file.txt"); +} + +/** +* @tc.name: GetFileName001 +* @tc.desc: GetFileName Should Handle Remote Files Correctly +* @tc.type: FUNC +*/ +HWTEST_F(CopyFileTest, GetFileName001, TestSize.Level1) +{ + std::string remoteFile = "file://data/storage/el2/distributedfiles/103.png"; + auto result = UdmfCopyFile::GetInstance().GetFileName(remoteFile); + ASSERT_EQ(result, "103.png"); +} + +/** +* @tc.name: GetFileName002 +* @tc.desc: GetFileName Should Handle Remote Files Correctly +* @tc.type: FUNC +*/ +HWTEST_F(CopyFileTest, GetFileName002, TestSize.Level1) +{ + std::string remoteFile = "file://data/storage/el2/distributedfiles/103.png?networkid=xxx"; + auto result = UdmfCopyFile::GetInstance().GetFileName(remoteFile); + ASSERT_EQ(result, "103.png"); +} + +/** +* @tc.name: HandleRecord +* @tc.desc: HandleRecord Should Add To Processed Data For Non FileType +* @tc.type: FUNC +*/ +HWTEST_F(CopyFileTest, HandleRecord, TestSize.Level1) +{ + auto record = std::make_shared(); + auto helper = std::make_unique(); + UdmfCopyFile::CopyContext context(helper); + bool result = UdmfCopyFile::GetInstance().HandleRecord(record, context); + ASSERT_TRUE(result); + ASSERT_EQ(context.processedData->GetRecords().size(), 1); +} + +} // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/common/unittest/udmf_types_util_abnormal_test.cpp b/udmf/framework/common/unittest/udmf_types_util_abnormal_test.cpp index 78b7b4de63bb0a40ac89527714a09d1cdaa6f531..e8908130fd40f8e9745022eac7cc0541a9acf2c6 100644 --- a/udmf/framework/common/unittest/udmf_types_util_abnormal_test.cpp +++ b/udmf/framework/common/unittest/udmf_types_util_abnormal_test.cpp @@ -66,7 +66,7 @@ void UdmfTypesUtilAbnormalTest::TearDown() /** * @tc.name: Marshalling001 -* @tc.desc: Abnrmal testcase of Marshalling, the return value of Writing() is nullptr +* @tc.desc: Abnrmal testcase of Marshalling, the return value of Writing() is false * @tc.type: FUNC */ HWTEST_F(UdmfTypesUtilAbnormalTest, Marshalling001, TestSize.Level1) @@ -91,7 +91,7 @@ HWTEST_F(UdmfTypesUtilAbnormalTest, Marshalling001, TestSize.Level1) /** * @tc.name: Marshalling002 -* @tc.desc: Abnrmal testcase of Marshalling, the return value of Writing() is nullptr +* @tc.desc: Abnrmal testcase of Marshalling, the return value of Writing() is false * @tc.type: FUNC */ HWTEST_F(UdmfTypesUtilAbnormalTest, Marshalling002, TestSize.Level1) @@ -107,23 +107,23 @@ HWTEST_F(UdmfTypesUtilAbnormalTest, Marshalling002, TestSize.Level1) /** * @tc.name: Marshalling003 -* @tc.desc: Abnrmal testcase of Marshalling, the return value of Reading() is nullptr +* @tc.desc: Abnrmal testcase of Marshalling, the return value of ReadTlv() is false * @tc.type: FUNC */ HWTEST_F(UdmfTypesUtilAbnormalTest, Marshalling003, TestSize.Level1) { LOG_INFO(UDMF_TEST, "Marshalling003 begin."); UnifiedData unifiedData; - std::vector input = {unifiedData}; + unifiedData.dataId_ = 1; MessageParcel parcel; - bool ret = ITypesUtil::Marshalling(input, parcel); + bool ret = ITypesUtil::Marshalling(unifiedData, parcel); EXPECT_FALSE(ret); LOG_INFO(UDMF_TEST, "Marshalling003 end."); } /** * @tc.name: Unmarshalling001 -* @tc.desc: Abnrmal testcase of Unmarshalling, the return value of Reading() is nullptr +* @tc.desc: Abnrmal testcase of Unmarshalling, the return value of ReadInt32() is 0 * @tc.type: FUNC */ HWTEST_F(UdmfTypesUtilAbnormalTest, Unmarshalling001, TestSize.Level1) @@ -136,4 +136,19 @@ HWTEST_F(UdmfTypesUtilAbnormalTest, Unmarshalling001, TestSize.Level1) EXPECT_FALSE(ret); LOG_INFO(UDMF_TEST, "Unmarshalling001 end."); } + +/** +* @tc.name: Unmarshalling002 +* @tc.desc: Abnrmal testcase of Unmarshalling, the return value of ReadInt32() is 0 +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilAbnormalTest, Unmarshalling002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Unmarshalling002 begin."); + UnifiedData output; + MessageParcel parcel; + bool ret = ITypesUtil::Unmarshalling(output, parcel); + EXPECT_FALSE(ret); + LOG_INFO(UDMF_TEST, "Unmarshalling002 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/common/unittest/udmf_types_util_mock_test.cpp b/udmf/framework/common/unittest/udmf_types_util_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b3ee3bcf6fc2c455ba9da7ba4647b838c92430a0 --- /dev/null +++ b/udmf/framework/common/unittest/udmf_types_util_mock_test.cpp @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2025 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 "UdmfTypesUtilMockTest" + +#include +#include +#include + +#include "logger.h" +#include "udmf_types_util.h" +#include "unified_meta.h" +#include "text.h" +#include "plain_text.h" +#include "file.h" +#include "image.h" +#include "system_defined_record.h" +#include "system_defined_form.h" +#include "application_defined_record.h" +#include "unified_types.h" +#include "udmf_client.h" +#include "message_parcel_mock.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { +using namespace std; +static constexpr int32_t NORMAL_MAX_PARCEL_SIZE = 128 * 1024 * 1024; +class UdmfTypesUtilMockTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + static inline shared_ptr messageParcelMock_ = nullptr; +}; + +void UdmfTypesUtilMockTest::SetUpTestCase() +{ + messageParcelMock_ = make_shared(); + MessageParcelMock::messageParcel = messageParcelMock_; +} + +void UdmfTypesUtilMockTest::TearDownTestCase() +{ +} + +void UdmfTypesUtilMockTest::SetUp() +{ +} + +void UdmfTypesUtilMockTest::TearDown() +{ +} + +/** +* @tc.name: Unmarshalling001 +* @tc.desc: Unmarshalling UnifiedData +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling001, TestSize.Level1) +{ + std::vector unifiedDataList; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(10)) + .WillOnce(Return(10)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + EXPECT_CALL(*messageParcelMock_, ReadInt32()).WillOnce(Return(-1)) + .WillOnce(Return(UnifiedData::MAX_DATA_SIZE + 1)) + .WillOnce(Return(10)); + bool ret = ITypesUtil::Unmarshalling(unifiedDataList, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(unifiedDataList, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(unifiedDataList, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling002 +* @tc.desc: Unmarshalling UnifiedData +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling002, TestSize.Level1) +{ + UnifiedData unifiedData; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(10)) + .WillOnce(Return(10)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + EXPECT_CALL(*messageParcelMock_, ReadInt32()).WillOnce(Return(-1)) + .WillOnce(Return(UnifiedData::MAX_DATA_SIZE + 1)) + .WillOnce(Return(10)); + bool ret = ITypesUtil::Unmarshalling(unifiedData, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(unifiedData, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(unifiedData, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling003 +* @tc.desc: Unmarshalling summary +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling003, TestSize.Level1) +{ + Summary summary; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + bool ret = ITypesUtil::Unmarshalling(summary, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(summary, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling004 +* @tc.desc: Unmarshalling privilege +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling004, TestSize.Level1) +{ + Privilege privileges; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + bool ret = ITypesUtil::Unmarshalling(privileges, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(privileges, parcel); + EXPECT_FALSE(ret); +} + + +/** +* @tc.name: Unmarshalling005 +* @tc.desc: Unmarshalling CustomOption +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling005, TestSize.Level1) +{ + CustomOption option; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + bool ret = ITypesUtil::Unmarshalling(option, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(option, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling006 +* @tc.desc: Unmarshalling QueryOption +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling006, TestSize.Level1) +{ + QueryOption queryOption; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + bool ret = ITypesUtil::Unmarshalling(queryOption, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(queryOption, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling007 +* @tc.desc: Unmarshalling UDType +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling007, TestSize.Level1) +{ + UDType type; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + bool ret = ITypesUtil::Unmarshalling(type, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(type, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling008 +* @tc.desc: Unmarshalling Intention +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling008, TestSize.Level1) +{ + Intention intention; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + bool ret = ITypesUtil::Unmarshalling(intention, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(intention, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling009 +* @tc.desc: Unmarshalling Visibility +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling009, TestSize.Level1) +{ + Visibility visibility; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + bool ret = ITypesUtil::Unmarshalling(visibility, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(visibility, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling010 +* @tc.desc: Unmarshalling AsyncProcessInfo +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling010, TestSize.Level1) +{ + AsyncProcessInfo asyncProcessInfo; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + bool ret = ITypesUtil::Unmarshalling(asyncProcessInfo, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(asyncProcessInfo, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling011 +* @tc.desc: Unmarshalling DataLoadInfo +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling011, TestSize.Level1) +{ + DataLoadInfo dataLoadInfo; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(10)) + .WillOnce(Return(10)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + EXPECT_CALL(*messageParcelMock_, ReadInt32()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)) + .WillOnce(Return(10)); + bool ret = ITypesUtil::Unmarshalling(dataLoadInfo, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(dataLoadInfo, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(dataLoadInfo, parcel); + EXPECT_FALSE(ret); +} +} \ No newline at end of file diff --git a/udmf/framework/common/unittest/udmf_types_util_test.cpp b/udmf/framework/common/unittest/udmf_types_util_test.cpp index 86e94996cd520dfc4715939c38d9f62c26f5d6a0..8d18ba05df13b20c23f761df78118b47de5da950 100644 --- a/udmf/framework/common/unittest/udmf_types_util_test.cpp +++ b/udmf/framework/common/unittest/udmf_types_util_test.cpp @@ -299,4 +299,31 @@ HWTEST_F(UdmfTypesUtilTest, Unmarshalling009, TestSize.Level1) EXPECT_TRUE(ret); LOG_INFO(UDMF_TEST, "Unmarshalling009 end."); } + +/** +* @tc.name: Unmarshalling010 +* @tc.desc: Normal testcase of Unmarshalling +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilTest, Unmarshalling010, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Unmarshalling010 begin."); + DataLoadInfo input; + input.sequenceKey = "seq_2023"; + input.types = {"typeA", "typeB", "typeC"}; + input.recordCount = 1000; + + MessageParcel parcel; + ITypesUtil::Marshalling(input, parcel); + DataLoadInfo output; + bool ret = ITypesUtil::Unmarshalling(output, parcel); + EXPECT_TRUE(ret); + EXPECT_EQ(input.sequenceKey, output.sequenceKey); + EXPECT_EQ(input.recordCount, output.recordCount); + ASSERT_EQ(input.types.size(), output.types.size()); + for (auto &item : input.types) { + EXPECT_TRUE(output.types.find(item) != output.types.end()); + } + LOG_INFO(UDMF_TEST, "Unmarshalling010 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/common/unittest/utd_cfgs_checker_test.cpp b/udmf/framework/common/unittest/utd_cfgs_checker_test.cpp index 2a727441db1442faad6c98fe4ba47846bb0ad75b..e9fa7b93a6a701d60017556dc60c087a2ee8bdae 100644 --- a/udmf/framework/common/unittest/utd_cfgs_checker_test.cpp +++ b/udmf/framework/common/unittest/utd_cfgs_checker_test.cpp @@ -269,7 +269,7 @@ HWTEST_F(UtdCfgsCheckerTest, CheckTypeDescriptors_005, TestSize.Level1) presetCfg2.belongingToTypes = {"com.demo.test.parent6"}; presetCfg2.mimeTypes = {"parent3/abc"}; std::vector presetCfgs = {presetCfg1, presetCfg2}; - + std::vector customCfgs = {tdc1, tdc3}; std::string bundleName("com.demo.test"); diff --git a/udmf/framework/common/utd_cfgs_checker.cpp b/udmf/framework/common/utd_cfgs_checker.cpp index 187b505f69069aa66d7bb674707eb752466adca1..b7eaa290126241b04abd89a7d8b3d74de40c6d7b 100644 --- a/udmf/framework/common/utd_cfgs_checker.cpp +++ b/udmf/framework/common/utd_cfgs_checker.cpp @@ -55,20 +55,32 @@ bool UtdCfgsChecker::CheckTypeDescriptors(CustomUtdCfgs &typeCfgs, const std::ve bool UtdCfgsChecker::CheckTypesFormat(CustomUtdCfgs &typeCfgs, const std::string &bundleName) { - for (auto declarationType: typeCfgs.first) { - if (!std::regex_match(declarationType.typeId, std::regex(bundleName + TYPE_ID_REGEX))) { - LOG_ERROR(UDMF_CLIENT, "Declaration typeId check failed, id: %{public}s, bundleName: %{public}s.", - declarationType.typeId.c_str(), bundleName.c_str()); - return false; +#ifndef CROSS_PLATFORM + try { +#endif + for (auto declarationType: typeCfgs.first) { + if (!std::regex_match(declarationType.typeId, std::regex(bundleName + TYPE_ID_REGEX))) { + LOG_ERROR(UDMF_CLIENT, "Declaration typeId check failed, bundleName: %{public}s", bundleName.c_str()); + return false; + } } - } - for (auto referenceTypes: typeCfgs.second) { - if (!std::regex_match(referenceTypes.typeId, std::regex(TYPE_ID_REGEX))) { - LOG_ERROR(UDMF_CLIENT, "Reference typeId check failed, id: %{public}s, bundleName: %{public}s.", - referenceTypes.typeId.c_str(), bundleName.c_str()); - return false; + for (auto referenceTypes: typeCfgs.second) { + if (!std::regex_match(referenceTypes.typeId, std::regex(TYPE_ID_REGEX))) { + LOG_ERROR(UDMF_CLIENT, "Reference typeId check failed, bundleName: %{public}s", bundleName.c_str()); + return false; + } } +#ifndef CROSS_PLATFORM + } catch (const std::regex_error& e) { + LOG_ERROR(UDMF_CLIENT, "catch regex_error, bundleName: %{public}s.", bundleName.c_str()); + return false; } +#endif + return CheckTypesOptions(typeCfgs, bundleName); +} + +bool UtdCfgsChecker::CheckTypesOptions(CustomUtdCfgs &typeCfgs, const std::string &bundleName) +{ std::vector inputTypeCfgs; if (!typeCfgs.first.empty()) { inputTypeCfgs.insert(inputTypeCfgs.end(), typeCfgs.first.begin(), typeCfgs.first.end()); @@ -79,8 +91,7 @@ bool UtdCfgsChecker::CheckTypesFormat(CustomUtdCfgs &typeCfgs, const std::string for (TypeDescriptorCfg &typeCfg : inputTypeCfgs) { for (std::string filenames : typeCfg.filenameExtensions) { if (filenames.size() <= 1 || filenames[0] != FILE_EXTENSION_PREFIX) { - LOG_ERROR(UDMF_CLIENT, "Extension not valid, extension: %{public}s, bundleName: %{public}s.", - filenames.c_str(), bundleName.c_str()); + LOG_ERROR(UDMF_CLIENT, "Extension not valid, bundleName: %{public}s.", bundleName.c_str()); return false; } } @@ -90,8 +101,7 @@ bool UtdCfgsChecker::CheckTypesFormat(CustomUtdCfgs &typeCfgs, const std::string } for (std::string mimeType : typeCfg.mimeTypes) { if (mimeType.empty()) { - LOG_ERROR(UDMF_CLIENT, "mimeType can not be an empty string, typeId: %{public}s.", - typeCfg.typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "mimeType can not be an empty string"); return false; } } @@ -148,13 +158,11 @@ bool UtdCfgsChecker::CheckBelongingToTypes(const std::vector for (auto &inputCfg : typeCfgs) { for (std::string belongingToType : inputCfg.belongingToTypes) { if (belongingToType.empty()) { - LOG_ERROR(UDMF_CLIENT, "BelongingToType can not be an empty string, typeId: %{public}s.", - inputCfg.typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "BelongingToType can not be an empty string"); return false; } if (inputCfg.typeId == belongingToType) { - LOG_ERROR(UDMF_CLIENT, "TypeId cannot equals belongingToType, typeId: %{public}s.", - inputCfg.typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "TypeId cannot equals belongingToType"); return false; } if (find(typeIds.begin(), typeIds.end(), belongingToType) == typeIds.end()) { diff --git a/udmf/framework/common/utd_cfgs_checker.h b/udmf/framework/common/utd_cfgs_checker.h index 13eab8670ff987b8bfc89efe023548dfee0169d3..de81b62e77d1e16c39643ba56041d74c9c84f968 100644 --- a/udmf/framework/common/utd_cfgs_checker.h +++ b/udmf/framework/common/utd_cfgs_checker.h @@ -33,6 +33,7 @@ private: UtdCfgsChecker(const UtdCfgsChecker &obj) = delete; UtdCfgsChecker &operator=(const UtdCfgsChecker &obj) = delete; bool CheckTypesFormat(CustomUtdCfgs &typeCfgs, const std::string &bundleName); + bool CheckTypesOptions(CustomUtdCfgs &typeCfgs, const std::string &bundleName); bool CheckTypesRelation(CustomUtdCfgs &typeCfgs, const std::vector &presetCfgs, const std::vector &customCfgs); bool CanConstructDAG(CustomUtdCfgs &typeCfgs, const std::vector &presetCfgs, diff --git a/udmf/framework/common/utd_common.h b/udmf/framework/common/utd_common.h index ac39da62cb8b33586f54fe5f4d2486804674b9b1..6322bd44cdbefb2a564580024d1ba3ba644d6a34 100644 --- a/udmf/framework/common/utd_common.h +++ b/udmf/framework/common/utd_common.h @@ -17,6 +17,7 @@ #include #include #include +#include #include "error_code.h" namespace OHOS { @@ -25,14 +26,14 @@ struct TypeDescriptorCfg; using CustomUtdCfgs = std::pair, std::vector>; struct TypeDescriptorCfg { std::string typeId; - std::vector belongingToTypes; - std::vector filenameExtensions; - std::vector mimeTypes; + std::vector belongingToTypes {}; + std::vector filenameExtensions {}; + std::vector mimeTypes {}; std::string description; std::string referenceURL; std::string iconFile; std::string ownerBundle; - std::set installerBundles; + std::set installerBundles {}; bool operator==(const TypeDescriptorCfg &typeDescriptor) const { @@ -40,8 +41,13 @@ struct TypeDescriptorCfg { } }; +struct UtdFileInfo { + uint64_t size = 0; + int64_t lastTime = 0; +}; + // UTD data category -constexpr const char* UTD_CUSTOM_DECLAEEARION = "UniformDataTypeDeclarations"; +constexpr const char* UTD_CUSTOM_DECLARATION = "UniformDataTypeDeclarations"; constexpr const char* UTD_CUSTOM_REFERENCE = "ReferenceUniformDataTypeDeclarations"; constexpr const char* UTD_CUSTOM = "CustomUTDs"; diff --git a/udmf/framework/common/utd_graph.cpp b/udmf/framework/common/utd_graph.cpp index 4203d9dc5a5b077ad41786d0b961f559b05d728c..3382c52455e3154f495a459c6b2f2e5f3f986f91 100644 --- a/udmf/framework/common/utd_graph.cpp +++ b/udmf/framework/common/utd_graph.cpp @@ -14,8 +14,6 @@ */ #define LOG_TAG "UtdGraph" #include "utd_graph.h" - -#include #include "logger.h" namespace OHOS { namespace UDMF { @@ -60,11 +58,11 @@ void UtdGraph::InitUtdGraph(const std::vector &descriptorCfgs bool UtdGraph::IsLowerLevelType(const std::string &lowerLevelType, const std::string &heigitLevelType) { + std::unique_lock lock(graphMutex_); if (graph_ == nullptr) { LOG_ERROR(UDMF_CLIENT, "graph_ is nullptr."); return false; } - std::unique_lock lock(graphMutex_); bool isFind = false; int32_t start = graph_->GetIndex(lowerLevelType); int32_t end = graph_->GetIndex(heigitLevelType); @@ -91,7 +89,7 @@ std::unique_ptr UtdGraph::ConstructNewGraph(const std::vector(descriptorsNum, typeIdIndex); - + for (const auto &descriptorCfg : descriptorCfgs) { std::vector belongsTo = descriptorCfg.belongingToTypes; for (auto belongsToType : belongsTo) { diff --git a/udmf/framework/common/utd_graph.h b/udmf/framework/common/utd_graph.h index 0c18584994328b6b758afed2b8ae1a21f7235b8a..7178f47dfcfb3a6653aac875ecfb92f135b81ab2 100644 --- a/udmf/framework/common/utd_graph.h +++ b/udmf/framework/common/utd_graph.h @@ -18,7 +18,6 @@ #include #include -#include #include #include #include diff --git a/udmf/framework/innerkitsimpl/client/udmf_async_client.cpp b/udmf/framework/innerkitsimpl/client/udmf_async_client.cpp index d7c1e65e76cfec04313c28a7982aae6bddea0738..c6de1b6f8dc13460eedda33faaabbcf7f9311292 100644 --- a/udmf/framework/innerkitsimpl/client/udmf_async_client.cpp +++ b/udmf/framework/innerkitsimpl/client/udmf_async_client.cpp @@ -16,12 +16,17 @@ #include "udmf_async_client.h" +#include #include "dataobs_mgr_client.h" #include "logger.h" #include "plain_text.h" #include "progress_callback.h" #include "udmf_client.h" #include "udmf_copy_file.h" +#ifndef IOS_PLATFORM +#include "udmf_executor.h" +#endif +#include "udmf_notifier_stub.h" #include "udmf_service_client.h" namespace OHOS::UDMF { @@ -30,8 +35,11 @@ static constexpr size_t MIN_THREADS = 0; static constexpr int32_t START_ABILITY_INTERVAL = 500; static constexpr int32_t READ_PROGRESS_INTERVAL = 100; +static constexpr int32_t UPDATA_TIMESTAMP_INTERVAL = 1000; static constexpr int32_t SYNC_INTERVAL = 200; static constexpr int32_t MAX_SYNC_TIMES = 14; +static constexpr uint64_t SEC_TO_MILLISEC = 1000; +static constexpr uint64_t MICROSEC_TO_MILLISEC = 1000; static std::unordered_map STATUS_MAP = { { E_INVALID_PARAMETERS, ListenerStatus::INVALID_PARAMETERS }, @@ -47,10 +55,10 @@ static constexpr int32_t PROGRESS_SYNC_FINSHED = 10; static constexpr int32_t PROGRESS_GET_DATA_FINISHED = 20; static constexpr int32_t PROGRESS_ALL_FINISHED = 100; -#ifdef IOS_PLATFORM -UdmfAsyncClient::UdmfAsyncClient() {} -#else -UdmfAsyncClient::UdmfAsyncClient() : executor_(MAX_THREADS, MIN_THREADS) {} +UdmfAsyncClient::UdmfAsyncClient() = default; + +#ifndef IOS_PLATFORM +static UdmfExecutor udmfExecutor(MAX_THREADS, MIN_THREADS); #endif UdmfAsyncClient &UdmfAsyncClient::GetInstance() @@ -69,14 +77,18 @@ Status UdmfAsyncClient::StartAsyncDataRetrieval(const GetDataParams ¶ms) if (status != E_OK) { return status; } + if (asyncHelperMap_.find(params.query.key) == asyncHelperMap_.end()) { + LOG_ERROR(UDMF_CLIENT, "RegisterAsyncHelper failed, key=%{public}s", params.query.key.c_str()); + return E_ERROR; + } auto &asyncHelper = asyncHelperMap_.at(params.query.key); if (params.progressIndicator == ProgressIndicator::DEFAULT) { asyncHelper->progressQueue.SetClearable(false); - asyncHelper->invokeHapTask = executor_.Schedule(std::chrono::milliseconds(START_ABILITY_INTERVAL), + asyncHelper->invokeHapTask = udmfExecutor.Schedule(std::chrono::milliseconds(START_ABILITY_INTERVAL), (std::bind(&UdmfAsyncClient::InvokeHapTask, this, params.query.key))); } - asyncHelper->getDataTask = executor_.Execute(std::bind(&UdmfAsyncClient::GetDataTask, this, params.query)); - asyncHelper->progressTask = executor_.Execute(std::bind(&UdmfAsyncClient::ProgressTask, this, params.query.key)); + asyncHelper->getDataTask = udmfExecutor.Execute(std::bind(&UdmfAsyncClient::GetDataTask, this, params.query)); + asyncHelper->progressTask = udmfExecutor.Execute(std::bind(&UdmfAsyncClient::ProgressTask, this, params.query.key)); #endif return E_OK; } @@ -119,6 +131,7 @@ Status UdmfAsyncClient::ProgressTask(const std::string &businessUdKey) return status; } } + auto lastUpdateTime = std::chrono::steady_clock::now(); while (asyncHelper->lastProgress >= PROGRESS_INIT && asyncHelper->lastProgress < PROGRESS_ALL_FINISHED) { auto pair = asyncHelper->progressQueue.Poll(); if (!pair.first) { @@ -126,13 +139,18 @@ Status UdmfAsyncClient::ProgressTask(const std::string &businessUdKey) continue; } auto progressInfo = pair.second; - if (progressInfo->progress >= PROGRESS_INIT && progressInfo->progress <= asyncHelper->lastProgress) { + if (progressInfo->progress >= PROGRESS_INIT && progressInfo->progress < asyncHelper->lastProgress) { continue; } - asyncHelper->lastProgress = progressInfo->progress; if (asyncHelper->progressIndicator == ProgressIndicator::DEFAULT) { - UpdateProgressData(asyncHelper->processKey, *progressInfo); + auto now = std::chrono::steady_clock::now(); + auto elapsedMs = std::chrono::duration_cast(now - lastUpdateTime).count(); + if (progressInfo->progress != asyncHelper->lastProgress || elapsedMs > UPDATA_TIMESTAMP_INTERVAL) { + UpdateProgressData(asyncHelper->processKey, *progressInfo); + lastUpdateTime = now; + } } + asyncHelper->lastProgress = progressInfo->progress; } Clear(businessUdKey); return E_OK; @@ -162,7 +180,12 @@ Status UdmfAsyncClient::InvokeHapTask(const std::string &businessUdKey) Clear(businessUdKey); return E_ERROR; } - sptr callback = new ProgressSignalCallback(); + sptr callback = new (std::nothrow) ProgressSignalCallback(); + if (callback == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Create ProgressSignalCallback failed"); + Clear(businessUdKey); + return E_ERROR; + } auto obsMgrClient = AAFwk::DataObsMgrClient::GetInstance(); if (obsMgrClient == nullptr) { LOG_ERROR(UDMF_CLIENT, "Get DataObsMgrClient failed"); @@ -193,6 +216,7 @@ Status UdmfAsyncClient::RegisterAsyncHelper(const GetDataParams ¶ms) asyncHelper->progressIndicator = params.progressIndicator; asyncHelper->fileConflictOptions = params.fileConflictOptions; asyncHelper->destUri = params.destUri; + asyncHelper->acceptableInfo = params.acceptableInfo; asyncHelperMap_.insert_or_assign(params.query.key, std::move(asyncHelper)); return E_OK; } @@ -233,7 +257,7 @@ Status UdmfAsyncClient::CheckSync(std::unique_ptr &asyncHelper, con return E_SYNC_FAILED; } (asyncHelper->sycnRetryTime)++; - asyncHelper->getDataTask = executor_.Schedule(std::chrono::milliseconds(SYNC_INTERVAL), + asyncHelper->getDataTask = udmfExecutor.Schedule(std::chrono::milliseconds(SYNC_INTERVAL), std::bind(&UdmfAsyncClient::GetDataTask, this, query)); #endif return E_OK; @@ -242,7 +266,23 @@ Status UdmfAsyncClient::CheckSync(std::unique_ptr &asyncHelper, con Status UdmfAsyncClient::GetDataFromDB(std::unique_ptr &asyncHelper, const QueryOption &query) { auto &data = *(asyncHelper->data); - auto status = static_cast(UdmfServiceClient::GetInstance()->GetData(query, data)); + auto delayDataCallback = [this](const std::string &key, const UnifiedData &unifiedData) { + if (asyncHelperMap_.find(key) == asyncHelperMap_.end()) { + LOG_ERROR(UDMF_CLIENT, "No task exist, key=%{public}s", key.c_str()); + return; + } + auto &asyncHelper = asyncHelperMap_.at(key); + *(asyncHelper->data) = unifiedData; + UdmfAsyncClient::GetInstance().ProcessUnifiedData(asyncHelper); + }; + sptr iUdmfNotifier = new (std::nothrow) DelayDataCallbackClient(delayDataCallback); + if (iUdmfNotifier == nullptr) { + LOG_ERROR(UDMF_CLIENT, "IUdmfNotifier unavailable"); + return E_ERROR; + } + std::shared_ptr dataPtr = std::make_shared(); + auto status = static_cast(UdmfClient::GetInstance().GetDataIfAvailable(query.key, + asyncHelper->acceptableInfo, iUdmfNotifier, dataPtr)); if (status != E_OK) { LOG_ERROR(UDMF_CLIENT, "GetData error, status = %{public}d", status); ProgressInfo progressInfo = { @@ -252,6 +292,11 @@ Status UdmfAsyncClient::GetDataFromDB(std::unique_ptr &asyncHelper, CallProgress(asyncHelper, progressInfo, nullptr); return status; } + if (dataPtr->IsEmpty()) { + LOG_INFO(UDMF_CLIENT, "Wait delay data"); + return E_OK; + } + data = *dataPtr; return ProcessUnifiedData(asyncHelper); } @@ -274,6 +319,7 @@ Status UdmfAsyncClient::SetProgressData(const std::string &businessUdKey) auto obj = std::make_shared(); auto progressRecord = std::make_shared(UDType::PLAIN_TEXT, obj); progressRecord->SetContent(std::to_string(PROGRESS_INIT)); + progressRecord->SetAbstract(std::to_string(GetCurrentTimeMillis())); UnifiedData progressData; progressData.AddRecord(progressRecord); auto status = serviceClient->SetData(cusomOption, progressData, progressKey); @@ -304,6 +350,7 @@ Status UdmfAsyncClient::UpdateProgressData(const std::string &progressUdKey, con } else { progressRecord->SetContent(std::to_string(progressInfo.progress)); } + progressRecord->SetAbstract(std::to_string(GetCurrentTimeMillis())); UnifiedData progressData; progressData.AddRecord(progressRecord); auto status = serviceClient->UpdateData(queryOption, progressData); @@ -365,10 +412,10 @@ Status UdmfAsyncClient::Clear(const std::string &businessUdKey) return E_OK; } if (asyncHelper->invokeHapTask != ExecutorPool::INVALID_TASK_ID) { - executor_.Remove(asyncHelper->invokeHapTask); + udmfExecutor.Remove(asyncHelper->invokeHapTask); } - executor_.Remove(asyncHelper->getDataTask); - executor_.Remove(asyncHelper->progressTask); + udmfExecutor.Remove(asyncHelper->getDataTask); + udmfExecutor.Remove(asyncHelper->progressTask); asyncHelperMap_.erase(businessUdKey); UdmfServiceClient::GetInstance()->ClearAsynProcessByKey(businessUdKey); LOG_INFO(UDMF_CLIENT, "Clear task success, key = %{public}s", businessUdKey.c_str()); @@ -408,4 +455,17 @@ bool UdmfAsyncClient::IsParamValid(const GetDataParams &params) } return true; } + +void UdmfAsyncClient::PushTaskToExecutor(UdmfTask task) +{ + udmfExecutor.Execute(std::move(task)); +} + +uint64_t UdmfAsyncClient::GetCurrentTimeMillis() +{ + struct timeval tv = { 0, 0 }; + gettimeofday(&tv, nullptr); + return (static_cast<uint64_t>(tv.tv_sec) * SEC_TO_MILLISEC + + static_cast<uint64_t>(tv.tv_usec) / MICROSEC_TO_MILLISEC); +} } // namespace OHOS::UDMF diff --git a/udmf/framework/innerkitsimpl/client/udmf_client.cpp b/udmf/framework/innerkitsimpl/client/udmf_client.cpp index dbaa7d3eef43315e31c6cf5577836b5cf31673b3..a064447130ea03d597a35c3ad8cf2366d941b328 100644 --- a/udmf/framework/innerkitsimpl/client/udmf_client.cpp +++ b/udmf/framework/innerkitsimpl/client/udmf_client.cpp @@ -24,12 +24,19 @@ #include "udmf_utils.h" #include "accesstoken_kit.h" #include "ipc_skeleton.h" +#include "udmf_notifier_stub.h" #include "unified_data_helper.h" #include "unified_html_record_process.h" +#include "utd_client.h" namespace OHOS { namespace UDMF { constexpr const char *TAG = "UdmfClient::"; +constexpr const char *BUNDLE_IN_APP = "udmf.inapp.data"; +static constexpr int KEY_LEN = 32; +static constexpr int FILE_TYPES_MAX_SIZE = 1024; +static const std::initializer_list<std::string_view> FILE_TOP_TYPES = { "general.file-uri", "general.file" }; +static constexpr int WITH_SUMMARY_FORMAT_VER = 1; using namespace OHOS::DistributedDataDfx; using namespace RadarReporter; UdmfClient &UdmfClient::GetInstance() @@ -38,12 +45,28 @@ UdmfClient &UdmfClient::GetInstance() return instance; } +void UdmfClient::ProcessDragIfInApp(UnifiedData &unifiedData, std::string &intentionDrag, std::string &key) +{ + std::string bundleName = BUNDLE_IN_APP; + UnifiedKey udKey = UnifiedKey(intentionDrag, bundleName, UTILS::GenerateId()); + key = udKey.GetUnifiedKey(); + dataCache_.Clear(); + dataCache_.Insert(key, unifiedData); + LOG_INFO(UDMF_CLIENT, "SetData in app success, bundleName:%{public}s.", bundleName.c_str()); + RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), + BizScene::SET_DATA, SetDataStage::SET_DATA_END, StageRes::SUCCESS, BizState::DFX_END); +} + Status UdmfClient::SetData(CustomOption &option, UnifiedData &unifiedData, std::string &key) { DdsTrace trace( std::string(TAG) + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), BizScene::SET_DATA, SetDataStage::SET_DATA_BEGIN, StageRes::IDLE, BizState::DFX_BEGIN); + if (!UnifiedDataUtils::IsValidIntention(option.intention)) { + LOG_ERROR(UDMF_SERVICE, "Invalid intention"); + return E_INVALID_PARAMETERS; + } auto service = UdmfServiceClient::GetInstance(); if (service == nullptr) { LOG_ERROR(UDMF_CLIENT, "Service unavailable"); @@ -55,23 +78,16 @@ Status UdmfClient::SetData(CustomOption &option, UnifiedData &unifiedData, std:: BizScene::SET_DATA, SetDataStage::SET_DATA_BEGIN, StageRes::SUCCESS); if (option.intention == UD_INTENTION_DRAG) { ShareOptions shareOption = SHARE_OPTIONS_BUTT; - auto status = GetAppShareOption(UD_INTENTION_MAP.at(option.intention), shareOption); + auto intentionDrag = UD_INTENTION_MAP.at(option.intention); + auto status = GetAppShareOption(intentionDrag, shareOption); if (status != E_NOT_FOUND && status != E_OK) { RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), BizScene::SET_DATA, SetDataStage::SET_DATA_END, StageRes::FAILED, status, BizState::DFX_END); - LOG_ERROR(UDMF_CLIENT, "get appShareOption fail, intention:%{public}s", - UD_INTENTION_MAP.at(option.intention).c_str()); + LOG_ERROR(UDMF_CLIENT, "get appShareOption fail, intention:%{public}s", intentionDrag.c_str()); return static_cast<Status>(status); } if (shareOption == ShareOptions::IN_APP) { - std::string bundleName = "udmf.inapp.data"; - UnifiedKey udKey = UnifiedKey(UD_INTENTION_MAP.at(option.intention), bundleName, UTILS::GenerateId()); - key = udKey.GetUnifiedKey(); - dataCache_.Clear(); - dataCache_.Insert(key, unifiedData); - LOG_INFO(UDMF_CLIENT, "SetData in app success, bundleName:%{public}s.", bundleName.c_str()); - RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), - BizScene::SET_DATA, SetDataStage::SET_DATA_END, StageRes::SUCCESS, BizState::DFX_END); + ProcessDragIfInApp(unifiedData, intentionDrag, key); return E_OK; } if (unifiedData.HasType(UtdUtils::GetUtdIdFromUtdEnum(UDType::HTML))) { @@ -324,5 +340,150 @@ Status UdmfClient::GetDataFromCache(const QueryOption &query, UnifiedData &unifi return E_NOT_FOUND; } +Status UdmfClient::GetParentType(Summary &oldSummary, Summary &newSummary) +{ + std::map<std::string, int64_t> tmpSummary; + for (const auto &[type, size] : oldSummary.summary) { + std::string fileType = UnifiedDataUtils::GetBelongsToFileType(type); + if (fileType.empty()) { + tmpSummary[type] = size; + continue; + } + if (tmpSummary.find(fileType) != tmpSummary.end()) { + tmpSummary[fileType] += size; + } else { + tmpSummary[fileType] = size; + } + } + newSummary.summary = std::move(tmpSummary); + newSummary.totalSize = oldSummary.totalSize; + return E_OK; +} + +Status UdmfClient::SetDelayInfo(const DataLoadParams &dataLoadParams, std::string &key) +{ + if (dataLoadParams.dataLoadInfo.sequenceKey.length() != KEY_LEN) { + LOG_ERROR(UDMF_CLIENT, "Invalid key=%{public}s", dataLoadParams.dataLoadInfo.sequenceKey.c_str()); + return E_INVALID_PARAMETERS; + } + auto service = UdmfServiceClient::GetInstance(); + if (service == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Service unavailable"); + return E_IPC; + } + sptr<IRemoteObject> iUdmfNotifier = new (std::nothrow) UdmfNotifierClient(dataLoadParams.loadHandler); + if (iUdmfNotifier == nullptr) { + LOG_ERROR(UDMF_CLIENT, "IUdmfNotifier unavailable"); + return E_IPC; + } + auto ret = service->SetDelayInfo(dataLoadParams.dataLoadInfo, iUdmfNotifier, key); + if (ret != E_OK) { + LOG_ERROR(UDMF_CLIENT, "Failed, ret = %{public}d, udkey = %{public}s.", ret, key.c_str()); + } + return static_cast<Status>(ret); +} + +Status UdmfClient::PushDelayData(const std::string &key, UnifiedData &unifiedData) +{ + if (key.empty()) { + LOG_ERROR(UDMF_CLIENT, "Empty key"); + return E_INVALID_PARAMETERS; + } + auto service = UdmfServiceClient::GetInstance(); + if (service == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Service unavailable"); + return E_IPC; + } + auto status = service->PushDelayData(key, unifiedData); + if (status != E_OK) { + LOG_ERROR(UDMF_CLIENT, "Failed, ret = %{public}d", status); + } + return static_cast<Status>(status); +} + +Status UdmfClient::GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr<IRemoteObject> iUdmfNotifier, std::shared_ptr<UnifiedData> unifiedData) +{ + if (key.empty() || iUdmfNotifier == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Empty key or notifier"); + return E_INVALID_PARAMETERS; + } + auto service = UdmfServiceClient::GetInstance(); + if (service == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Service unavailable"); + return E_IPC; + } + int32_t ret = service->GetDataIfAvailable(key, dataLoadInfo, iUdmfNotifier, unifiedData); + if (ret != E_OK) { + LOG_ERROR(UDMF_CLIENT, "Failed! ret = %{public}d", ret); + return static_cast<Status>(ret); + } + return E_OK; +} + +std::string UdmfClient::GetBundleNameByUdKey(const std::string &key) +{ + UnifiedKey udkey(key); + if (!udkey.IsValid()) { + LOG_ERROR(UDMF_CLIENT, "IsValid udkey:%{public}s", key.c_str()); + return ""; + } + return udkey.bundleName; +} + +bool UdmfClient::IsAppropriateType(const Summary &summary, const std::vector<std::string> &allowTypes) +{ + for (const auto &allowType : allowTypes) { + if (summary.summary.find(allowType) != summary.summary.end() + || summary.specificSummary.find(allowType) != summary.specificSummary.end()) { + return true; + } + } + if (summary.version < WITH_SUMMARY_FORMAT_VER) { + return false; + } + // when the summary format version is greater than 0, we need to check the file type + return CheckFileUtdType(summary, allowTypes); +} + +bool UdmfClient::CheckFileUtdType(const Summary &summary, const std::vector<std::string> &allowTypes) +{ + std::set<std::string> fileUtdTypes; + for (const auto &[type, formats] : summary.summaryFormat) { + if (!type.empty() && std::find(formats.begin(), formats.end(), Uds_Type::UDS_FILE_URI) != formats.end()) { + fileUtdTypes.emplace(type); + } + if (fileUtdTypes.size() > FILE_TYPES_MAX_SIZE) { + LOG_WARN(UDMF_CLIENT, "Exceeding the maximum size"); + break; + } + } + for (const auto &type : allowTypes) { + if (std::find(FILE_TOP_TYPES.begin(), FILE_TOP_TYPES.end(), type) != FILE_TOP_TYPES.end()) { + // If the supported file type falls into, return true when the file is included + if (!fileUtdTypes.empty()) { + return true; + } + continue; + } + if (!UnifiedDataUtils::IsFilterFileType(type)) { + continue; + } + for (const auto &fileUtdType : fileUtdTypes) { + std::shared_ptr<TypeDescriptor> descriptor; + UtdClient::GetInstance().GetTypeDescriptor(fileUtdType, descriptor); + if (descriptor == nullptr) { + continue; + } + bool isSpecificType = false; + descriptor->BelongsTo(type, isSpecificType); + if (isSpecificType) { + return true; + } + } + } + LOG_INFO(UDMF_CLIENT, "Not appropriate type"); + return false; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/client/utd_client.cpp b/udmf/framework/innerkitsimpl/client/utd_client.cpp index f4006efe50a7757e9cfcecdb571333229682fd1e..234b545a1e5871da67a5ac38f5283105e74b189d 100644 --- a/udmf/framework/innerkitsimpl/client/utd_client.cpp +++ b/udmf/framework/innerkitsimpl/client/utd_client.cpp @@ -15,6 +15,8 @@ #define LOG_TAG "UtdClient" #include <regex> #include <thread> +#include <chrono> +#include <cinttypes> #include "utd_client.h" #include "logger.h" #include "utd_graph.h" @@ -25,16 +27,8 @@ namespace OHOS { namespace UDMF { constexpr const int MAX_UTD_LENGTH = 256; -constexpr const int MAX_FILE_EXTENSION_LENGTH = 14; -constexpr const char *DEFAULT_ANONYMOUS = "******"; -std::string UtdClient::Anonymous(const std::string &fileExtension) -{ - if (fileExtension.length() <= MAX_FILE_EXTENSION_LENGTH) { - return fileExtension; - } - - return (fileExtension.substr(0, MAX_FILE_EXTENSION_LENGTH) + DEFAULT_ANONYMOUS); -} +constexpr const int64_t RELOAD_INTERVAL = 10; +using namespace std::chrono; UtdClient::UtdClient() { @@ -62,21 +56,27 @@ UtdClient &UtdClient::GetInstance() bool UtdClient::Init() { bool result = true; + int32_t userId = DEFAULT_USER_ID; + bool isHap = IsHapTokenType(); + if (!isHap && GetCurrentActiveUserId(userId) != Status::E_OK) { + result = false; + } + + std::vector<TypeDescriptorCfg> customUtd; + { + std::lock_guard<std::mutex> lock(customUtdMutex_); + utdFileInfo_ = CustomUtdStore::GetInstance().GetCustomUtdInfo(isHap, userId); + customUtd = CustomUtdStore::GetInstance().GetCustomUtd(isHap, userId); + lastLoadTime_ = duration_cast<seconds>(system_clock::now().time_since_epoch()).count(); + } + std::unique_lock<std::shared_mutex> lock(utdMutex_); descriptorCfgs_ = PresetTypeDescriptors::GetInstance().GetPresetTypes(); - std::vector<TypeDescriptorCfg> customTypes; - if (IsHapTokenType()) { - customTypes = CustomUtdStore::GetInstance().GetHapTypeCfgs(); - } else { - int32_t userId = DEFAULT_USER_ID; - if (GetCurrentActiveUserId(userId) != Status::E_OK) { - result = false; - } - customTypes = CustomUtdStore::GetInstance().GetTypeCfgs(userId); - } - LOG_INFO(UDMF_CLIENT, "get customUtd, size:%{public}zu", customTypes.size()); - if (!customTypes.empty()) { - descriptorCfgs_.insert(descriptorCfgs_.end(), customTypes.begin(), customTypes.end()); + + LOG_INFO(UDMF_CLIENT, "get customUtd size:%{public}zu, file size:%{public}" PRIu64, + customUtd.size(), utdFileInfo_.size); + if (!customUtd.empty()) { + descriptorCfgs_.insert(descriptorCfgs_.end(), customUtd.begin(), customUtd.end()); } UtdGraph::GetInstance().InitUtdGraph(descriptorCfgs_); return result; @@ -89,15 +89,16 @@ Status UtdClient::GetTypeDescriptor(const std::string &typeId, std::shared_ptr<T for (const auto &utdTypeCfg : descriptorCfgs_) { if (utdTypeCfg.typeId == typeId) { descriptor = std::make_shared<TypeDescriptor>(utdTypeCfg); - LOG_DEBUG(UDMF_CLIENT, "get descriptor success. %{public}s ", typeId.c_str()); return Status::E_OK; } } } if (typeId.find(FLEXIBLE_TYPE_FLAG) != typeId.npos) { - LOG_DEBUG(UDMF_CLIENT, "get flexible descriptor. %{public}s ", typeId.c_str()); return GetFlexibleTypeDescriptor(typeId, descriptor); } + if (TryReloadCustomUtd()) { + return GetTypeDescriptor(typeId, descriptor); + } return Status::E_OK; } @@ -131,7 +132,7 @@ Status UtdClient::GetFlexibleTypeDescriptor(const std::string &typeId, std::shar { TypeDescriptorCfg flexibleTypeDescriptorCfg; if (!FlexibleType::ParseFlexibleUtd(typeId, flexibleTypeDescriptorCfg)) { - LOG_ERROR(UDMF_CLIENT, "ParseFlexibleUtd failed, invalid typeId: %{public}s", typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "ParseFlexibleUtd failed, invalid typeId"); return Status::E_ERROR; } descriptor = std::make_shared<TypeDescriptor>(flexibleTypeDescriptorCfg); @@ -144,8 +145,10 @@ Status UtdClient::GetUniformDataTypeByFilenameExtension(const std::string &fileE std::string lowerFileExtension = fileExtension; std::transform(lowerFileExtension.begin(), lowerFileExtension.end(), lowerFileExtension.begin(), ::tolower); if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { - LOG_ERROR(UDMF_CLIENT, "invalid belongsTo. fileExtension:%{public}s, belongsTo:%{public}s ", - fileExtension.c_str(), belongsTo.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo."); + if (TryReloadCustomUtd()) { + return GetUniformDataTypeByFilenameExtension(fileExtension, typeId, belongsTo); + } return Status::E_INVALID_PARAMETERS; } { @@ -154,7 +157,7 @@ Status UtdClient::GetUniformDataTypeByFilenameExtension(const std::string &fileE for (const auto &utdTypeCfg : descriptorCfgs_) { for (auto fileEx : utdTypeCfg.filenameExtensions) { std::transform(fileEx.begin(), fileEx.end(), fileEx.begin(), ::tolower); - if (fileEx == lowerFileExtension) { + if (fileEx == lowerFileExtension && IsBelongingType(belongsTo, utdTypeCfg.typeId)) { typeId = utdTypeCfg.typeId; found = true; break; @@ -165,16 +168,12 @@ Status UtdClient::GetUniformDataTypeByFilenameExtension(const std::string &fileE } } } - // the find typeId is not belongsTo to the belongsTo. - if (!typeId.empty() && belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && - !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { - typeId = ""; + if (typeId.empty() && TryReloadCustomUtd()) { + return GetUniformDataTypeByFilenameExtension(fileExtension, typeId, belongsTo); } - if (typeId.empty()) { if (!IsValidFileExtension(lowerFileExtension)) { - LOG_ERROR(UDMF_CLIENT, "invalid fileExtension. fileExtension:%{public}s, belongsTo:%{public}s ", - fileExtension.c_str(), belongsTo.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid fileExtension."); return Status::E_INVALID_PARAMETERS; } typeId = FlexibleType::GenFlexibleUtd("", lowerFileExtension, belongsTo); @@ -186,13 +185,14 @@ Status UtdClient::GetUniformDataTypesByFilenameExtension(const std::string &file std::vector<std::string> &typeIds, const std::string &belongsTo) { if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { - LOG_ERROR(UDMF_CLIENT, "invalid belongsTo. fileExtension:%{public}s, belongsTo:%{public}s ", - fileExtension.c_str(), belongsTo.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo."); + if (TryReloadCustomUtd()) { + return GetUniformDataTypesByFilenameExtension(fileExtension, typeIds, belongsTo); + } return Status::E_INVALID_PARAMETERS; } if (!IsValidFileExtension(fileExtension)) { - LOG_ERROR(UDMF_CLIENT, "invalid fileExtension. fileExtension:%{public}s, belongsTo:%{public}s ", - Anonymous(fileExtension).c_str(), belongsTo.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid fileExtension."); return Status::E_INVALID_PARAMETERS; } @@ -211,11 +211,13 @@ Status UtdClient::GetUniformDataTypesByFilenameExtension(const std::string &file } } } + if (typeIdsInCfg.empty() && TryReloadCustomUtd()) { + return GetUniformDataTypesByFilenameExtension(fileExtension, typeIds, belongsTo); + } typeIds.clear(); for (const auto &typeId : typeIdsInCfg) { // the find typeId is not belongsTo to the belongsTo. - if (belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && - !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { + if (!IsBelongingType(belongsTo, typeId)) { continue; } typeIds.emplace_back(typeId); @@ -232,20 +234,16 @@ Status UtdClient::GetUniformDataTypeByMIMEType(const std::string &mimeType, std: std::string lowerMimeType = mimeType; std::transform(lowerMimeType.begin(), lowerMimeType.end(), lowerMimeType.begin(), ::tolower); if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { - LOG_ERROR(UDMF_CLIENT, "invalid belongsTo. mimeType:%{public}s, belongsTo:%{public}s ", - mimeType.c_str(), belongsTo.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo."); + if (TryReloadCustomUtd()) { + return GetUniformDataTypeByMIMEType(mimeType, typeId, belongsTo); + } return Status::E_INVALID_PARAMETERS; } - typeId = GetTypeIdFromCfg(lowerMimeType); - // the find typeId is not belongsTo to the belongsTo. - if (!typeId.empty() && belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && - !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { - typeId = ""; - } + typeId = GetTypeIdFromCfg(lowerMimeType, belongsTo); if (typeId.empty()) { if (!IsValidMimeType(mimeType)) { - LOG_ERROR(UDMF_CLIENT, "invalid mimeType. mimeType:%{public}s, belongsTo:%{public}s ", - mimeType.c_str(), belongsTo.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid mimeType."); return Status::E_INVALID_PARAMETERS; } typeId = FlexibleType::GenFlexibleUtd(lowerMimeType, "", belongsTo); @@ -253,29 +251,44 @@ Status UtdClient::GetUniformDataTypeByMIMEType(const std::string &mimeType, std: return Status::E_OK; } -std::string UtdClient::GetTypeIdFromCfg(const std::string &mimeType) +std::string UtdClient::GetTypeIdFromCfg(const std::string &mimeType, const std::string &belongsTo) { - std::shared_lock<std::shared_mutex> guard(utdMutex_); - for (const auto &utdTypeCfg : descriptorCfgs_) { - for (auto mime : utdTypeCfg.mimeTypes) { - std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); - if (mime == mimeType) { - return utdTypeCfg.typeId; + if (mimeType.empty()) { + return ""; + } + { + std::shared_lock<std::shared_mutex> guard(utdMutex_); + for (const auto &utdTypeCfg : descriptorCfgs_) { + for (auto mime : utdTypeCfg.mimeTypes) { + std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); + if (mime == mimeType && IsBelongingType(belongsTo, utdTypeCfg.typeId)) { + return utdTypeCfg.typeId; + } } } } - if (mimeType.empty() || mimeType.back() != '*') { + if (mimeType.back() != '*') { + if (TryReloadCustomUtd()) { + return GetTypeIdFromCfg(mimeType, belongsTo); + } return ""; } - std::string prefixType = mimeType.substr(0, mimeType.length() - 1); - for (const auto &utdTypeCfg : descriptorCfgs_) { - for (auto mime : utdTypeCfg.mimeTypes) { - std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); - if (mime.rfind(prefixType, 0) == 0 && utdTypeCfg.belongingToTypes.size() > 0) { - return utdTypeCfg.belongingToTypes[0]; + { + std::shared_lock<std::shared_mutex> guard(utdMutex_); + std::string prefixType = mimeType.substr(0, mimeType.length() - 1); + for (const auto &utdTypeCfg : descriptorCfgs_) { + for (auto mime : utdTypeCfg.mimeTypes) { + std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); + if (mime.rfind(prefixType, 0) == 0 && utdTypeCfg.belongingToTypes.size() > 0 + && IsBelongingType(belongsTo, utdTypeCfg.typeId)) { + return utdTypeCfg.belongingToTypes[0]; + } } } } + if (TryReloadCustomUtd()) { + return GetTypeIdFromCfg(mimeType); + } return ""; } @@ -283,13 +296,14 @@ Status UtdClient::GetUniformDataTypesByMIMEType(const std::string &mimeType, std const std::string &belongsTo) { if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { - LOG_ERROR(UDMF_CLIENT, "invalid belongsTo. mimeType:%{public}s, belongsTo:%{public}s ", - mimeType.c_str(), belongsTo.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo."); + if (TryReloadCustomUtd()) { + return GetUniformDataTypesByMIMEType(mimeType, typeIds, belongsTo); + } return Status::E_INVALID_PARAMETERS; } if (!IsValidMimeType(mimeType)) { - LOG_ERROR(UDMF_CLIENT, "invalid mimeType. mimeType:%{public}s, belongsTo:%{public}s ", - mimeType.c_str(), belongsTo.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid mimeType."); return Status::E_INVALID_PARAMETERS; } @@ -299,8 +313,7 @@ Status UtdClient::GetUniformDataTypesByMIMEType(const std::string &mimeType, std typeIds.clear(); for (const auto &typeId : typeIdsInCfg) { // the find typeId is not belongsTo to the belongsTo. - if (belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && - !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { + if (!IsBelongingType(belongsTo, typeId)) { continue; } typeIds.emplace_back(typeId); @@ -321,16 +334,21 @@ std::vector<std::string> UtdClient::GetTypeIdsFromCfg(const std::string &mimeTyp } std::vector<std::string> typeIdsInCfg; - std::shared_lock<std::shared_mutex> guard(utdMutex_); - for (const auto &utdTypeCfg : descriptorCfgs_) { - for (auto mime : utdTypeCfg.mimeTypes) { - std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); - if ((mime == mimeType) || (prefixMatch && mime.rfind(prefixType, 0) == 0)) { - typeIdsInCfg.push_back(utdTypeCfg.typeId); - break; + { + std::shared_lock<std::shared_mutex> guard(utdMutex_); + for (const auto &utdTypeCfg : descriptorCfgs_) { + for (auto mime : utdTypeCfg.mimeTypes) { + std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); + if ((mime == mimeType) || (prefixMatch && mime.rfind(prefixType, 0) == 0)) { + typeIdsInCfg.push_back(utdTypeCfg.typeId); + break; + } } } } + if (typeIdsInCfg.empty() && TryReloadCustomUtd()) { + return GetTypeIdsFromCfg(mimeType); + } return typeIdsInCfg; } @@ -358,11 +376,11 @@ Status UtdClient::IsUtd(std::string typeId, bool &result) } result = false; } catch (...) { - LOG_ERROR(UDMF_CLIENT, "exception, typeId:%{public}s", typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "throw error"); result = false; return Status::E_ERROR; } - LOG_ERROR(UDMF_CLIENT, "is not utd, typeId:%{public}s", typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "is not utd"); return Status::E_OK; } @@ -395,7 +413,8 @@ void UtdClient::InstallCustomUtds(const std::string &bundleName, const std::stri return; } LOG_INFO(UDMF_CLIENT, "start, bundleName:%{public}s, user:%{public}d", bundleName.c_str(), user); - std::vector<TypeDescriptorCfg> customTyepCfgs = CustomUtdStore::GetInstance().GetTypeCfgs(user); + std::lock_guard<std::mutex> lock(updateUtdMutex_); + std::vector<TypeDescriptorCfg> customTyepCfgs = CustomUtdStore::GetInstance().GetCustomUtd(false, user); if (!CustomUtdStore::GetInstance().UninstallCustomUtds(bundleName, user, customTyepCfgs)) { LOG_ERROR(UDMF_CLIENT, "custom utd installed failed. bundleName:%{public}s, user:%{public}d", bundleName.c_str(), user); @@ -418,7 +437,8 @@ void UtdClient::UninstallCustomUtds(const std::string &bundleName, int32_t user) return; } LOG_INFO(UDMF_CLIENT, "start, bundleName:%{public}s, user:%{public}d", bundleName.c_str(), user); - std::vector<TypeDescriptorCfg> customTyepCfgs = CustomUtdStore::GetInstance().GetTypeCfgs(user); + std::lock_guard<std::mutex> lock(updateUtdMutex_); + std::vector<TypeDescriptorCfg> customTyepCfgs = CustomUtdStore::GetInstance().GetCustomUtd(false, user); if (!CustomUtdStore::GetInstance().UninstallCustomUtds(bundleName, user, customTyepCfgs)) { LOG_ERROR(UDMF_CLIENT, "custom utd installed failed. bundleName:%{public}s, user:%{public}d", bundleName.c_str(), user); @@ -438,5 +458,48 @@ void UtdClient::UpdateGraph(const std::vector<TypeDescriptorCfg> &customTyepCfgs UtdGraph::GetInstance().Update(std::move(graph)); descriptorCfgs_ = allTypeCfgs; } + +bool UtdClient::TryReloadCustomUtd() +{ + { + std::lock_guard<std::mutex> lock(customUtdMutex_); + auto now = duration_cast<seconds>(system_clock::now().time_since_epoch()).count(); + auto delay = now - lastLoadTime_; + if (delay <= RELOAD_INTERVAL) { + LOG_DEBUG(UDMF_CLIENT, "interval time too short"); + return false; + } + lastLoadTime_ = now; + } + + bool isHap = IsHapTokenType(); + int32_t userId = DEFAULT_USER_ID; + if (!isHap) { + int32_t status = GetCurrentActiveUserId(userId); + LOG_DEBUG(UDMF_CLIENT, "get user id status=%{public}d", status); + if (status != Status::E_OK) { + return false; + } + } + UtdFileInfo info = CustomUtdStore::GetInstance().GetCustomUtdInfo(isHap, userId); + if (info.size == utdFileInfo_.size && info.lastTime == utdFileInfo_.lastTime) { + LOG_DEBUG(UDMF_CLIENT, "utd file not change"); + return false; + } + LOG_INFO(UDMF_CLIENT, "utd file has change, try reload custom utd info"); + if (Init()) { + std::lock_guard<std::mutex> lock(customUtdMutex_); + utdFileInfo_ = info; + return true; + } + return false; +} + +bool UtdClient::IsBelongingType(const std::string &belongsTo, const std::string &typeId) const +{ + return belongsTo == DEFAULT_TYPE_ID || + belongsTo == typeId || + UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId); +} } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/common/unified_key.cpp b/udmf/framework/innerkitsimpl/common/unified_key.cpp index 1aaf4cb6724ba0d265a4d9d76793db2c6b122015..7b6ee6d2931d055df9340bcf54f5e23c73c23550 100644 --- a/udmf/framework/innerkitsimpl/common/unified_key.cpp +++ b/udmf/framework/innerkitsimpl/common/unified_key.cpp @@ -24,10 +24,14 @@ static std::bitset<MAX_BIT_SIZE> g_ruleIntention; static std::bitset<MAX_BIT_SIZE> g_ruleBundleName; static std::bitset<MAX_BIT_SIZE> g_ruleGroupId; static constexpr const char *UNIFIED_KEY_SCHEMA = "udmf://"; -static constexpr const char *ALPHA_AGGREGATE = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; -static constexpr const char *DIGIT_AGGREGATE = "0123456789"; -static constexpr const char *SYMBOL_AGGREGATE = ":;<=>?@[\\]_`"; static constexpr const char SEPARATOR = '/'; +static constexpr std::string_view SCHEME_SEPARATOR = "://"; +#define ALPHA_AGGREGATE "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define DIGIT_AGGREGATE "0123456789" +#define SYMBOL_AGGREGATE ":;<=>?@[\\]_`" +static constexpr std::string_view INTENTION_AGGREGATE_VIEW = ALPHA_AGGREGATE "_"; +static constexpr std::string_view BUNDLE_AGGREGATE_VIEW = ALPHA_AGGREGATE DIGIT_AGGREGATE "._+-"; +static constexpr std::string_view GROUPID_AGGREGATE_VIEW = ALPHA_AGGREGATE DIGIT_AGGREGATE SYMBOL_AGGREGATE; static constexpr uint32_t PREFIX_LEN = 24; static constexpr uint32_t SUFIX_LEN = 8; static constexpr uint32_t INDEX_LEN = 32; @@ -59,7 +63,7 @@ std::string UnifiedKey::GetUnifiedKey() return this->key; } -std::string UnifiedKey::GetPropertyKey() const +std::string UnifiedKey::GetKeyCommonPrefix() const { if (this->key.size() > INDEX_LEN) { return this->key.substr(0, key.size() - SUFIX_LEN); @@ -77,60 +81,60 @@ std::string UnifiedKey::GetPropertyKey() const bool UnifiedKey::IsValid() { - if (this->key.empty()) { - LOG_DEBUG(UDMF_FRAMEWORK, "empty key"); + if (key.empty()) { + LOG_ERROR(UDMF_FRAMEWORK, "Empty key"); return false; } PreliminaryWork(); - - std::string data = this->key; // schema/intention/groupId - std::string separator = "://"; - size_t pos = data.find(separator); + std::string_view data = key; + size_t pos = data.find(SCHEME_SEPARATOR); if (pos == std::string::npos) { + LOG_ERROR(UDMF_FRAMEWORK, "Missing scheme separator. Key=%{public}s", this->key.c_str()); return false; } - std::string schema = data.substr(0, pos + separator.size()); // schema - if (UNIFIED_KEY_SCHEMA != schema) { - LOG_DEBUG(UDMF_FRAMEWORK, "wrong schema"); + auto schema = data.substr(0, pos + SCHEME_SEPARATOR.length()); + if (schema != UNIFIED_KEY_SCHEMA) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid key schema. Key=%{public}s", this->key.c_str()); return false; } - - data = data.substr(pos + separator.size()); // intention/bundleName/groupId - pos = data.find('/'); // intention - if (pos == std::string::npos) { + data = data.substr(pos + SCHEME_SEPARATOR.length()); // intention/bundle/group + if (!ExtractAndValidateSegment(data, this->intention, g_ruleIntention, "intention")) { return false; } - std::string intentionTmp = data.substr(0, pos); - if (!CheckCharacter(intentionTmp, g_ruleIntention)) { + if (!ExtractAndValidateSegment(data, this->bundleName, g_ruleBundleName, "bundleName")) { return false; } - this->intention = intentionTmp; - - data = data.substr(pos + 1); - pos = data.find('/'); // bundleName - if (pos == std::string::npos) { + if (data.empty()) { + LOG_ERROR(UDMF_FRAMEWORK, "Find groupId error. Key=%{public}s", this->key.c_str()); return false; } - std::string bundle = data.substr(0, pos); - if (!CheckCharacter(bundle, g_ruleBundleName)) { - LOG_DEBUG(UDMF_FRAMEWORK, "wrong bundle"); + if (!CheckCharacter(data, g_ruleGroupId)) { + LOG_ERROR(UDMF_FRAMEWORK, "Check groupId character error. Key=%{public}s", this->key.c_str()); return false; } - this->bundleName = bundle; + this->groupId = data; + return true; +} - data = data.substr(pos + 1); // groupId - if (data.empty()) { +bool UnifiedKey::ExtractAndValidateSegment(std::string_view& data, std::string& field, + const std::bitset<MAX_BIT_SIZE>& rule, const std::string& name) +{ + size_t pos = data.find(SEPARATOR); + if (pos == std::string_view::npos) { + LOG_ERROR(UDMF_FRAMEWORK, "Missing '/' for %{public}s", name.c_str()); return false; } - if (!CheckCharacter(data, g_ruleGroupId)) { - LOG_DEBUG(UDMF_FRAMEWORK, "wrong groupId"); + field = std::string(data.substr(0, pos)); + if (!CheckCharacter(field, rule)) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid character in %{public}s", name.c_str()); return false; } - this->groupId = data; + // Remove the prefix '/' + data = data.substr(pos + 1); return true; } -bool UnifiedKey::CheckCharacter(std::string data, std::bitset<MAX_BIT_SIZE> rule) +bool UnifiedKey::CheckCharacter(const std::string_view& data, const std::bitset<MAX_BIT_SIZE> &rule) { if (data.empty()) { LOG_DEBUG(UDMF_FRAMEWORK, "empty key"); @@ -152,22 +156,19 @@ void UnifiedKey::PreliminaryWork() { // All intentions are composed of uppercase and lowercase letters and underscores. if (g_ruleIntention.none()) { - std::string intentionTmp = std::string(ALPHA_AGGREGATE) + "_"; - for (char i : intentionTmp) { + for (char i : INTENTION_AGGREGATE_VIEW) { g_ruleIntention.set(i); } } // All bundle name are composed of uppercase and lowercase letters and dots. if (g_ruleBundleName.none()) { - std::string bundleAggregate = std::string(ALPHA_AGGREGATE) + DIGIT_AGGREGATE + "._"; - for (char i : bundleAggregate) { + for (char i : BUNDLE_AGGREGATE_VIEW) { g_ruleBundleName.set(i); } } // Characters of groupId are taken from Ascii codes 48 to 122. if (g_ruleGroupId.none()) { - std::string idAggregate = std::string(DIGIT_AGGREGATE) + ALPHA_AGGREGATE + SYMBOL_AGGREGATE; - for (char i : idAggregate) { + for (char i : GROUPID_AGGREGATE_VIEW) { g_ruleGroupId.set(i); } } diff --git a/udmf/framework/innerkitsimpl/common/unified_meta.cpp b/udmf/framework/innerkitsimpl/common/unified_meta.cpp index 0498962494250e64f320c9b50c4a6cb7f7de3914..cd4e4ff5548749060a45ea2c5a413d5e789a6e4f 100644 --- a/udmf/framework/innerkitsimpl/common/unified_meta.cpp +++ b/udmf/framework/innerkitsimpl/common/unified_meta.cpp @@ -507,16 +507,17 @@ static constexpr UtdType UTD_TYPES[] = { { OPENHARMONY_GOPAINT, "OPENHARMONY_GOPAINT", "openharmony.gopaint" }, { OPENHARMONY_GOBRUSH, "OPENHARMONY_GOBRUSH", "openharmony.gobrush" }, { OPENHARMONY_GOBRUSHES, "OPENHARMONY_GOBRUSHES", "openharmony.gobrushes" }, - { OPENHARMONY_GOCOLOR, "OPENHARMONY_GOCOLOR", "openharmony.gocolor" } + { OPENHARMONY_GOCOLOR, "OPENHARMONY_GOCOLOR", "openharmony.gocolor" }, + { OPENHARMONY_DLP, "OPENHARMONY_DLP", "openharmony.dlp"} }; -static const std::vector<std::string_view> NOT_NEED_COUNT_VALUE_LIST = { +static const std::initializer_list<std::string_view> NOT_NEED_COUNT_VALUE_LIST = { UNIFORM_DATA_TYPE, ARRAY_BUFFER_LENGTH, THUMB_DATA_LENGTH, APP_ICON_LENGTH, APPLICATION_DEFINED_RECORD_MARK, FILE_TYPE }; -static const std::set<std::string> FILE_SUB_TYPES = { - "general.image", "general.video", "general.audio", "general.folder" }; +static const std::initializer_list<std::string> FILE_SUB_TYPES = { + "general.image", "general.video", "general.audio", "general.folder", "general.file" }; namespace UtdUtils { bool IsValidUtdId(const std::string &utdId) @@ -648,6 +649,22 @@ bool UnifiedDataUtils::IsPersist(const std::string &intention) return IsPersist(GetIntentionByString(intention)); } +bool UnifiedDataUtils::IsPersist(const int32_t &visibility) +{ + return visibility >= static_cast<int32_t>(VISIBILITY_ALL) && visibility < static_cast<int32_t>(VISIBILITY_BUTT); +} + +bool UnifiedDataUtils::IsFileMangerIntention(const std::string &intention) +{ + Intention optionIntention = GetIntentionByString(intention); + if (optionIntention == UD_INTENTION_SYSTEM_SHARE || + optionIntention == UD_INTENTION_MENU || + optionIntention == UD_INTENTION_PICKER) { + return true; + } + return false; +} + Intention UnifiedDataUtils::GetIntentionByString(const std::string &intention) { for (const auto &it : UD_INTENTION_MAP) { @@ -658,23 +675,91 @@ Intention UnifiedDataUtils::GetIntentionByString(const std::string &intention) return UD_INTENTION_BUTT; } -bool UnifiedDataUtils::IsValidOptions(const std::string &key, std::string &intention) +std::string UnifiedDataUtils::FindIntentionMap(const Intention &queryIntention) { - UnifiedKey unifiedKey(key); - auto isValidKey = unifiedKey.IsValid(); - if (key.empty() && IsPersist(intention)) { - return true; + auto find = UD_INTENTION_MAP.find(queryIntention); + return find == UD_INTENTION_MAP.end() ? "" : find->second; +} + +bool UnifiedDataUtils::IsValidOptions(UnifiedKey &key, const std::string &intention, + const std::string &validIntention) +{ + if (key.key.empty() && intention.empty()) { + return false; } - if (intention.empty() && isValidKey && IsPersist(unifiedKey.intention)) { - return true; + bool isIntentionValid = intention.empty() || intention == validIntention; + if (!isIntentionValid) { + return false; } - if (isValidKey && unifiedKey.intention == intention && IsPersist(intention)) { - intention = ""; - return true; + bool isValidKey = key.key.empty() || (key.IsValid() && key.intention == validIntention); + if (!isValidKey) { + return false; + } + return true; +} + +bool UnifiedDataUtils::IsValidOptions(UnifiedKey &key, const std::string &intention) +{ + if (key.key.empty() && intention.empty()) { + return false; + } + + bool isIntentionValid = intention.empty() || IsPersist(intention); + if (!isIntentionValid) { + return false; + } + + bool isValidKey = key.key.empty() || (key.IsValid() && IsPersist(key.intention)); + if (!isValidKey) { + return false; + } + + if (!key.key.empty() && !intention.empty()) { + return key.intention == intention; + } + return true; +} + +bool UnifiedDataUtils::IsValidOptionsNonDrag(UnifiedKey &key, const std::string &intention) +{ + if (IsValidOptions(key, intention)) { + return !key.key.empty() || intention == UD_INTENTION_MAP.at(Intention::UD_INTENTION_DATA_HUB); } return false; } +std::string UnifiedDataUtils::GetBelongsToFileType(const std::string &utdId) +{ + if (utdId.empty() || utdId == "general.html" || utdId == "general.plain-text") { + LOG_ERROR(UDMF_FRAMEWORK, "The utdId is empty or the utdId is general.html or general.plain-text"); + return ""; + } + std::shared_ptr<TypeDescriptor> descriptor; + UtdClient::GetInstance().GetTypeDescriptor(utdId, descriptor); + if (descriptor == nullptr) { + LOG_INFO(UDMF_FRAMEWORK, "The descriptor is null"); + return ""; + } + for (const auto &type : FILE_SUB_TYPES) { + bool isSpecificType = false; + descriptor->BelongsTo(type, isSpecificType); + if (isSpecificType) { + return type; + } + } + if (!descriptor->GetFilenameExtensions().empty()) { + LOG_INFO(UDMF_FRAMEWORK, "The type descriptor has file extensions"); + return "general.file"; + } + LOG_INFO(UDMF_FRAMEWORK, "Return empty"); + return ""; +} + +bool UnifiedDataUtils::IsFilterFileType(const std::string &type) +{ + return std::find(FILE_SUB_TYPES.begin(), FILE_SUB_TYPES.end(), type) != FILE_SUB_TYPES.end(); +} + std::shared_ptr<Object> ObjectUtils::ConvertToObject(UDDetails &details) { Object object; @@ -781,20 +866,13 @@ void ObjectUtils::ProcessFileUriType(UDType &utdType, ValueType &value) utdType = FILE; std::string fileType; if (fileUri->GetValue(FILE_TYPE, fileType)) { - std::shared_ptr<TypeDescriptor> descriptor; - UtdClient::GetInstance().GetTypeDescriptor(fileType, descriptor); - if (descriptor == nullptr) { + std::string fileTypeStr = UnifiedDataUtils::GetBelongsToFileType(fileType); + if (fileTypeStr.empty()) { return; } - bool isFileType = false; - for (const auto &fileSub : FILE_SUB_TYPES) { - descriptor->BelongsTo(fileSub, isFileType); - if (isFileType) { - utdType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(fileSub)); - LOG_INFO(UDMF_FRAMEWORK, "Change type to %{public}s", fileSub.c_str()); - return; - } - } + utdType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(fileTypeStr)); + LOG_INFO(UDMF_FRAMEWORK, "Change type to %{public}s", fileTypeStr.c_str()); + return; } } } // namespace UDMF diff --git a/udmf/framework/innerkitsimpl/convert/data_params_conversion.cpp b/udmf/framework/innerkitsimpl/convert/data_params_conversion.cpp index 755b528199215d108a03116bced8a8bb6e52cccf..bb9003ab27aeaff0210c2db2f1ffa7060c949999 100644 --- a/udmf/framework/innerkitsimpl/convert/data_params_conversion.cpp +++ b/udmf/framework/innerkitsimpl/convert/data_params_conversion.cpp @@ -12,9 +12,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#define LOG_TAG "DataParamsConversion" #include "data_params_conversion.h" +#include "logger.h" #include "ndk_data_conversion.h" +#include "udmf_client.h" +#include "udmf_utils.h" namespace OHOS::UDMF { Status DataParamsConversion::GetInnerDataParams(OH_UdmfGetDataParams &ndkDataParams, QueryOption &query, @@ -42,6 +45,50 @@ Status DataParamsConversion::GetInnerDataParams(OH_UdmfGetDataParams &ndkDataPar ndkDataParams.dataProgressListener(&ndkProgrssInfo, ndkData); OH_UdmfData_Destroy(ndkData); }; + std::set<std::string> types; + for (size_t i = 0; i < ndkDataParams.acceptableInfo.typesCount; i++) { + types.insert(ndkDataParams.acceptableInfo.typesArray[i]); + } + dataParams.acceptableInfo = { + .types = std::move(types), + .recordCount = ndkDataParams.acceptableInfo.recordsCount, + }; + return Status::E_OK; +} + +Status DataParamsConversion::GetDataLoaderParams(const OH_UdmfDataLoadParams &ndkDataParams, + DataLoadParams &dataLoadParams) +{ + if (ndkDataParams.dataLoadHandler == nullptr) { + LOG_ERROR(UDMF_CAPI, "DataLoadHandler is null"); + return Status::E_INVALID_PARAMETERS; + } + std::set<std::string> types; + for (size_t i = 0; i < ndkDataParams.dataLoadInfo.typesCount; i++) { + types.insert(ndkDataParams.dataLoadInfo.typesArray[i]); + } + dataLoadParams.dataLoadInfo = { + .sequenceKey = UTILS::GenerateId(), + .types = std::move(types), + .recordCount = ndkDataParams.dataLoadInfo.recordsCount, + }; + dataLoadParams.loadHandler = [ndkDataParams](const std::string &udKey, const DataLoadInfo &dataLoadInfo) { + std::vector<std::string> types(dataLoadInfo.types.begin(), dataLoadInfo.types.end()); + OH_UdmfDataLoadInfo ndkDataLoadInfo { + .typesArray = NdkDataConversion::StrVectorToTypesArray(types), + .typesCount = types.size(), + .recordsCount = dataLoadInfo.recordCount, + }; + OH_UdmfData *data = ndkDataParams.dataLoadHandler(&ndkDataLoadInfo); + if (data == nullptr || data->unifiedData_ == nullptr) { + LOG_ERROR(UDMF_CAPI, "Data is null"); + return; + } + auto status = UdmfClient::GetInstance().PushDelayData(udKey, *data->unifiedData_); + if (status != Status::E_OK) { + LOG_ERROR(UDMF_CAPI, "Set delay data failed, status = %{public}d", status); + } + }; return Status::E_OK; } } diff --git a/udmf/framework/innerkitsimpl/convert/ndk_data_conversion.cpp b/udmf/framework/innerkitsimpl/convert/ndk_data_conversion.cpp index 00a105de0d14dc625337ef7a9dac5e0d09e2e29d..73b2fa9b18b0c5768cdc0ecfab80a998347c8ceb 100644 --- a/udmf/framework/innerkitsimpl/convert/ndk_data_conversion.cpp +++ b/udmf/framework/innerkitsimpl/convert/ndk_data_conversion.cpp @@ -12,25 +12,76 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#define LOG_TAG "NdkDataConversion" #include "ndk_data_conversion.h" +#include "logger.h" +#include "securec.h" namespace OHOS::UDMF { - Status NdkDataConversion::GetNativeUnifiedData(OH_UdmfData* ndkData, std::shared_ptr<UnifiedData>& data) - { - if (ndkData == nullptr || data == nullptr || ndkData->cid != NdkStructId::UDMF_UNIFIED_DATA_STRUCT_ID) { - return Status::E_INVALID_PARAMETERS; +static constexpr uint64_t MAX_RECORDS_COUNT = 4 * 1024 * 1024; +static constexpr uint64_t MAX_KEY_STRING_LEN = 1 * 1024 * 1024; + +Status NdkDataConversion::GetNativeUnifiedData(OH_UdmfData* ndkData, std::shared_ptr<UnifiedData>& data) +{ + if (ndkData == nullptr || data == nullptr || ndkData->cid != NdkStructId::UDMF_UNIFIED_DATA_STRUCT_ID) { + return Status::E_INVALID_PARAMETERS; + } + data = ndkData->unifiedData_; + return Status::E_OK; +} + +Status NdkDataConversion::GetNdkUnifiedData(std::shared_ptr<UnifiedData> data, OH_UdmfData* ndkData) +{ + if (data == nullptr || ndkData == nullptr || ndkData->cid != NdkStructId::UDMF_UNIFIED_DATA_STRUCT_ID) { + return Status::E_INVALID_PARAMETERS; + } + ndkData->unifiedData_ = data; + return Status::E_OK; +} + +char** NdkDataConversion::StrVectorToTypesArray(const std::vector<std::string>& strVector) +{ + unsigned int vectorSize = strVector.size(); + if (vectorSize == 0 || vectorSize > MAX_RECORDS_COUNT) { + return nullptr; + } + char** typesArray = new (std::nothrow) char* [vectorSize]; + if (typesArray == nullptr) { + LOG_ERROR(UDMF_CAPI, "create types array failed!, vectorSize: %{public}d, MAX_RECORDS_COUNT: %{public}" PRIu64, + vectorSize, MAX_RECORDS_COUNT); + return nullptr; + } + for (unsigned int i = 0; i < vectorSize; ++i) { + unsigned int strLen = strVector[i].length() + 1; + if (strLen > MAX_KEY_STRING_LEN) { + LOG_INFO(UDMF_CAPI, "string exceeds maximum length, length is %{public}d", strLen); + DestroyStringArray(typesArray, vectorSize); + return nullptr; + } + typesArray[i] = new (std::nothrow) char[strLen]; + if (typesArray[i] == nullptr || + (strcpy_s(typesArray[i], strLen, strVector[i].c_str())) != EOK) { + LOG_ERROR(UDMF_CAPI, "string copy failed"); + DestroyStringArray(typesArray, vectorSize); + return nullptr; } - data = ndkData->unifiedData_; - return Status::E_OK; } + return typesArray; +} - Status NdkDataConversion::GetNdkUnifiedData(std::shared_ptr<UnifiedData> data, OH_UdmfData* ndkData) - { - if (data == nullptr || ndkData == nullptr || ndkData->cid != NdkStructId::UDMF_UNIFIED_DATA_STRUCT_ID) { - return Status::E_INVALID_PARAMETERS; +void NdkDataConversion::DestroyStringArray(char**& bufArray, unsigned int& count) +{ + if (bufArray == nullptr) { + return; + } + for (unsigned int i = 0; i < count; i++) { + if (bufArray[i] != nullptr) { + delete[] bufArray[i]; + bufArray[i] = nullptr; } - ndkData->unifiedData_ = data; - return Status::E_OK; } + delete[] bufArray; + bufArray = nullptr; + count = 0; +} } \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/convert/udmf_conversion.cpp b/udmf/framework/innerkitsimpl/convert/udmf_conversion.cpp index f4d0ae621d355af4f26f2407abc15da4f34f8e13..94f68c1374d578892b494dc32e21245909d27326 100644 --- a/udmf/framework/innerkitsimpl/convert/udmf_conversion.cpp +++ b/udmf/framework/innerkitsimpl/convert/udmf_conversion.cpp @@ -58,6 +58,7 @@ void UdmfConversion::ConvertRecordToSubclass(std::shared_ptr<UnifiedRecord> &rec auto uid = record->GetUid(); auto entries = record->GetInnerEntries(); auto utdId = record->GetUtdId(); + auto utdId2 = record->GetUtdId2(); auto uris = record->GetUris(); switch (type) { case UDType::TEXT: { @@ -122,6 +123,7 @@ void UdmfConversion::ConvertRecordToSubclass(std::shared_ptr<UnifiedRecord> &rec } record->SetUid(uid); record->SetUtdId(utdId); + record->SetUtdId2(utdId2); record->SetInnerEntries(entries); record->SetUris(uris); SetValueWhenNotUds(record); diff --git a/udmf/framework/innerkitsimpl/data/application_defined_record.cpp b/udmf/framework/innerkitsimpl/data/application_defined_record.cpp index 219c1a1cbf468ceac35e40685fa54e08296675e7..15557072f7d9ed3d13cea07ceed78ec38e2f0c7a 100644 --- a/udmf/framework/innerkitsimpl/data/application_defined_record.cpp +++ b/udmf/framework/innerkitsimpl/data/application_defined_record.cpp @@ -45,7 +45,6 @@ ApplicationDefinedRecord::ApplicationDefinedRecord(UDType type, ValueType value) auto object = std::get<std::shared_ptr<Object>>(value); object->GetValue(UNIFORM_DATA_TYPE, applicationDefinedType); object->GetValue(ARRAY_BUFFER, rawData_); - hasObject_ = true; } if (applicationDefinedType.empty()) { applicationDefinedType = UtdUtils::GetUtdIdFromUtdEnum(type); diff --git a/udmf/framework/innerkitsimpl/data/audio.cpp b/udmf/framework/innerkitsimpl/data/audio.cpp index 41dafb6805db26dbdfe406e23e4dde088d6556b2..c308f0cdfc143e954b48378c435db6d4c66efa48 100644 --- a/udmf/framework/innerkitsimpl/data/audio.cpp +++ b/udmf/framework/innerkitsimpl/data/audio.cpp @@ -20,18 +20,30 @@ namespace UDMF { Audio::Audio() : Audio("") { SetType(AUDIO); - utdId_ = UtdUtils::GetUtdIdFromUtdEnum(AUDIO); + utdId2_ = GENERAL_FILE_URI; } Audio::Audio(const std::string &uri) : File(uri) { SetType(AUDIO); - utdId_ = UtdUtils::GetUtdIdFromUtdEnum(AUDIO); + utdId2_ = GENERAL_FILE_URI; } Audio::Audio(UDType type, ValueType value) : File(type, value) { SetType(AUDIO); + utdId2_ = GENERAL_FILE_URI; +} + +void Audio::InitObject() +{ + File::InitObject(); + auto object = std::get<std::shared_ptr<Object>>(value_); + if (!fileType_.empty()) { + object->value_[FILE_TYPE] = fileType_; + } else { + object->value_[FILE_TYPE] = "general.audio"; + } } } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/file.cpp b/udmf/framework/innerkitsimpl/data/file.cpp index cccc848723c7f159afd1ec2b516b9e94b9ffee02..c0cd19e1538c54a4fc15e147c491ae83e335cd20 100644 --- a/udmf/framework/innerkitsimpl/data/file.cpp +++ b/udmf/framework/innerkitsimpl/data/file.cpp @@ -18,16 +18,21 @@ namespace OHOS { namespace UDMF { File::File() : UnifiedRecord(FILE) { + SetType(FILE); + utdId2_ = GENERAL_FILE_URI; } File::File(const std::string &uri) : UnifiedRecord(FILE) { + SetType(FILE); this->oriUri_ = uri; + utdId2_ = GENERAL_FILE_URI; } File::File(UDType type, ValueType value) : UnifiedRecord(type, value) { - this->dataType_ = FILE; + SetType(FILE); + utdId2_ = GENERAL_FILE_URI; if (std::holds_alternative<std::string>(value)) { oriUri_ = std::get<std::string>(value); } else if (std::holds_alternative<std::shared_ptr<Object>>(value)) { @@ -35,23 +40,13 @@ File::File(UDType type, ValueType value) : UnifiedRecord(type, value) object->GetValue(ORI_URI, oriUri_); object->GetValue(REMOTE_URI, remoteUri_); object->GetValue(FILE_TYPE, fileType_); - std::string uniformDataType; - if (object->GetValue(UNIFORM_DATA_TYPE, uniformDataType) && uniformDataType == GENERAL_FILE_URI) { - utdId_ = std::move(uniformDataType); - } std::shared_ptr<Object> detailObj = nullptr; if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); } - hasObject_ = true; } } -void File::SetType(const UDType &type) -{ - this->dataType_ = type; -} - int64_t File::GetSize() { return static_cast<int64_t>(this->oriUri_.size() + this->remoteUri_.size() + @@ -109,7 +104,11 @@ void File::InitObject() object->value_[UNIFORM_DATA_TYPE] = GENERAL_FILE_URI; object->value_[ORI_URI] = oriUri_; object->value_[REMOTE_URI] = remoteUri_; - object->value_[FILE_TYPE] = fileType_; + if (!fileType_.empty()) { + object->value_[FILE_TYPE] = fileType_; + } else { + object->value_[FILE_TYPE] = "general.file"; + } object->value_[DETAILS] = ObjectUtils::ConvertToObject(details_); object->value_.insert_or_assign(VALUE_TYPE, std::move(value)); } diff --git a/udmf/framework/innerkitsimpl/data/flexible_type.cpp b/udmf/framework/innerkitsimpl/data/flexible_type.cpp index df90795277a41289214c0d4613b0c085de204770..d99153fe938bc128c709b210141fd902c4013abd 100644 --- a/udmf/framework/innerkitsimpl/data/flexible_type.cpp +++ b/udmf/framework/innerkitsimpl/data/flexible_type.cpp @@ -15,7 +15,6 @@ #define LOG_TAG "FlexibleType" #include "flexible_type.h" #include "logger.h" -#include "udmf_utils.h" #include "base32_utils.h" namespace OHOS { @@ -39,21 +38,19 @@ bool FlexibleType::ParseFlexibleUtd(const std::string &typeId, TypeDescriptorCfg std::string flexibleFlag = FLEXIBLE_TYPE_FLAG; flexibleUtd.erase(0, flexibleFlag.size()); std::string flexibleUtdDecode = Base32::Decode(flexibleUtd); - - LOG_DEBUG(UDMF_CLIENT, "The typeId be parsed, flexibleUtdDecode: %{public}s", flexibleUtdDecode.c_str()); if (flexibleUtdDecode.empty() || flexibleUtdDecode[0] != '?' || flexibleUtdDecode.find("=") == flexibleUtdDecode.npos) { - LOG_WARN(UDMF_CLIENT, "The typeId cannot be parsed, %{public}s ", typeId.c_str()); + LOG_WARN(UDMF_CLIENT, "The typeId cannot be parsed"); return false; } - std::vector<std::string> flexibleTypeAttrs = UTILS::StrSplit(flexibleUtdDecode, ":"); + std::vector<std::string> flexibleTypeAttrs = StrSplit(flexibleUtdDecode, ":"); for (auto attr : flexibleTypeAttrs) { - std::vector<std::string> attrkv = UTILS::StrSplit(attr, "="); + std::vector<std::string> attrkv = StrSplit(attr, "="); if (attrkv.size() != ATTRIBUTE_PAIR_SIZE) { continue; } if (attrkv[1].length() > MAX_TYPE_SIZE) { - LOG_ERROR(UDMF_CLIENT, "Attribute too long, attribute: %{public}s", attr.c_str()); + LOG_ERROR(UDMF_CLIENT, "Attribute too long"); return false; } std::string attrName = attrkv[0]; @@ -82,11 +79,23 @@ std::string FlexibleType::GenFlexibleUtd(const std::string &mimeType, const std: flexibleUtd += ":" + std::to_string(FILE_EXTENTSION) + "=" + fileExtension; } std::string encodeUtd = Base32::Encode(flexibleUtd); - LOG_DEBUG(UDMF_CLIENT, "FlexibleUtd typeId is: %{public}s, encodeUtd is: %{public}s", - flexibleUtd.c_str(), encodeUtd.c_str()); return FLEXIBLE_TYPE_FLAG + encodeUtd; } +std::vector<std::string> FlexibleType::StrSplit(const std::string &str, const std::string &delimiter) +{ + std::vector<std::string> result; + size_t start = 0; + size_t end = str.find(delimiter); + while (end != std::string::npos) { + result.push_back(str.substr(start, end - start)); + start = end + delimiter.length(); + end = str.find(delimiter, start); + } + result.push_back(str.substr(start)); + return result; +} + } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/folder.cpp b/udmf/framework/innerkitsimpl/data/folder.cpp index 2164cec3864b81e2b77b8d974ff062064f9b5f6d..52160d85eaac8f3fa2ef545e72c1ae0f7b8daa83 100644 --- a/udmf/framework/innerkitsimpl/data/folder.cpp +++ b/udmf/framework/innerkitsimpl/data/folder.cpp @@ -20,18 +20,30 @@ namespace UDMF { Folder::Folder() : Folder("") { SetType(FOLDER); - utdId_ = UtdUtils::GetUtdIdFromUtdEnum(FOLDER); + utdId2_ = GENERAL_FILE_URI; } Folder::Folder(const std::string &uri) : File(uri) { SetType(FOLDER); - utdId_ = UtdUtils::GetUtdIdFromUtdEnum(FOLDER); + utdId2_ = GENERAL_FILE_URI; } Folder::Folder(UDType type, ValueType value) : File(type, value) { SetType(FOLDER); + utdId2_ = GENERAL_FILE_URI; +} + +void Folder::InitObject() +{ + File::InitObject(); + auto object = std::get<std::shared_ptr<Object>>(value_); + if (!fileType_.empty()) { + object->value_[FILE_TYPE] = fileType_; + } else { + object->value_[FILE_TYPE] = "general.folder"; + } } } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/html.cpp b/udmf/framework/innerkitsimpl/data/html.cpp index 924634d22769a649094ad1bdde2d3e192aeba6af..a2f6d8496beb2cd444551e8e1075df4e6eab46e1 100644 --- a/udmf/framework/innerkitsimpl/data/html.cpp +++ b/udmf/framework/innerkitsimpl/data/html.cpp @@ -50,7 +50,6 @@ Html::Html(UDType type, ValueType value) : Text(type, value) if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); } - hasObject_ = true; } } diff --git a/udmf/framework/innerkitsimpl/data/image.cpp b/udmf/framework/innerkitsimpl/data/image.cpp index cf9067d61e7b6756a21fb1cf6ead810bf4682839..a9de01f1855031fa8cd2fe9730d3ccf2ba9bf8c5 100644 --- a/udmf/framework/innerkitsimpl/data/image.cpp +++ b/udmf/framework/innerkitsimpl/data/image.cpp @@ -20,18 +20,30 @@ namespace UDMF { Image::Image() : Image("") { SetType(IMAGE); - utdId_ = UtdUtils::GetUtdIdFromUtdEnum(IMAGE); + utdId2_ = GENERAL_FILE_URI; } Image::Image(const std::string &uri) : File(uri) { SetType(IMAGE); - utdId_ = UtdUtils::GetUtdIdFromUtdEnum(IMAGE); + utdId2_ = GENERAL_FILE_URI; } Image::Image(UDType type, ValueType value) : File(type, value) { SetType(IMAGE); + utdId2_ = GENERAL_FILE_URI; +} + +void Image::InitObject() +{ + File::InitObject(); + auto object = std::get<std::shared_ptr<Object>>(value_); + if (!fileType_.empty()) { + object->value_[FILE_TYPE] = fileType_; + } else { + object->value_[FILE_TYPE] = "general.image"; + } } } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/link.cpp b/udmf/framework/innerkitsimpl/data/link.cpp index 695730c671ceb3e508f06e5ab9d3416daedd4c75..2a2187305f4dc49ab34a6825b44752683e64b5b6 100644 --- a/udmf/framework/innerkitsimpl/data/link.cpp +++ b/udmf/framework/innerkitsimpl/data/link.cpp @@ -38,7 +38,6 @@ Link::Link(UDType type, ValueType value) : Text(type, value) if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); } - hasObject_ = true; } } diff --git a/udmf/framework/innerkitsimpl/data/plain_text.cpp b/udmf/framework/innerkitsimpl/data/plain_text.cpp index 7928a6da1a5ecbd12046c332f7e499134aacd29e..1ac1cc64c6a3e2226083323d0dad7cda1e20456e 100644 --- a/udmf/framework/innerkitsimpl/data/plain_text.cpp +++ b/udmf/framework/innerkitsimpl/data/plain_text.cpp @@ -48,7 +48,6 @@ PlainText::PlainText(UDType type, ValueType value) : Text(type, value) if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); } - hasObject_ = true; } } diff --git a/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp index adbd21febf44ae8afa2404ee6a70689e9faaec0d..b26bfba5f5b9de98765e46aa734eabd0c8993e0d 100644 --- a/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp +++ b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp @@ -12,11 +12,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define LOG_TAG "PresetTypeDescriptors" + #include "preset_type_descriptors.h" +#include <sstream> +#include <fstream> +#include "cJSON.h" +#include "custom_utd_json_parser.h" +#include "logger.h" + namespace OHOS { namespace UDMF { -constexpr const char *REFERENCE_URL = "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/"\ - "apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype"; +static constexpr const char *UTD_CONF_PATH = "/system/etc/utd/conf/"; +static constexpr const char *UNIFORM_DATA_TYPES_JSON_PATH = "uniform_data_types.json"; PresetTypeDescriptors::PresetTypeDescriptors() { @@ -37,3300 +45,39 @@ std::vector<TypeDescriptorCfg> &PresetTypeDescriptors::GetPresetTypes() { return typeDescriptors_; } + void PresetTypeDescriptors::InitDescriptors() { - typeDescriptors_ = { - {"general.entity", - {}, - {}, - {}, - "Base type for physical hierarchy.", - REFERENCE_URL, - ""}, - {"general.object", - {}, - {}, - {"*/*"}, - "Base type for logical hierarchy.", - REFERENCE_URL, - ""}, - {"general.composite-object", - {"general.object"}, - {}, - {}, - "Base type for mixed object. For example, a PDF file contains both text and special formatting data.", - REFERENCE_URL, - ""}, - {"general.text", - {"general.object"}, - {}, - {"text/*"}, - "Base type for all text.", - REFERENCE_URL, - ""}, - {"general.plain-text", - {"general.text"}, - {".txt", ".text"}, - {"text/plain"}, - "Text of unspecified encoding, with no markup.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_txt"}, - {"general.html", - {"general.text"}, - {".html", ".htm"}, - {"text/html"}, - "HTML text.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_html"}, - {"general.hyperlink", - {"general.text"}, - {}, - {}, - "Hyperlink.", - REFERENCE_URL, - ""}, - {"general.xml", - {"general.text"}, - {".xml"}, - {"text/xml"}, - "XML text.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_xml"}, - {"com.real.smil", - {"general.xml"}, - {".smil"}, - {"application/smil"}, - "Real synchronized multimedia integration language.", - REFERENCE_URL, - ""}, - {"general.source-code", - {"general.text"}, - {}, - {}, - "Generic source code.", - REFERENCE_URL, - ""}, - {"general.script", - {"general.source-code"}, - {}, - {}, - "Base type for scripting language source code.", - REFERENCE_URL, - ""}, - {"general.shell-script", - {"general.script"}, - {".sh", ".command"}, - {"text/x-shellscript"}, - "Shell script.", - REFERENCE_URL, - ""}, - {"general.csh-script", - {"general.shell-script"}, - {".csh"}, - {"text/x-csh"}, - "C-shell script.", - REFERENCE_URL, - ""}, - {"general.perl-script", - {"general.shell-script"}, - {".pl", ".pm"}, - {"text/x-perl-script"}, - "Perl script.", - REFERENCE_URL, - ""}, - {"general.php-script", - {"general.shell-script"}, - {".php", ".php3", ".php4", ".ph3", ".ph4", ".phtml"}, - {"text/x-php-script", "text/php", "application/php"}, - "PHP script.", - REFERENCE_URL, - ""}, - {"general.python-script", - {"general.shell-script"}, - {".py"}, - {"text/x-python-script"}, - "Python script.", - REFERENCE_URL, - ""}, - {"general.ruby-script", - {"general.shell-script"}, - {".rb", ".rbw"}, - {"text/ruby-script"}, - "Ruby script.", - REFERENCE_URL, - ""}, - {"general.type-script", - {"general.source-code"}, - {".ts"}, - {}, - "TypeScript source code.", - REFERENCE_URL, - ""}, - {"general.java-script", - {"general.source-code"}, - {".js", ".jscript", ".javascript"}, - {"text/javascript"}, - "JavaScript source code.", - REFERENCE_URL, - ""}, - {"general.c-header", - {"general.source-code"}, - {".h"}, - {"text/x-chdr"}, - "C header file.", - REFERENCE_URL, - ""}, - {"general.c-source", - {"general.source-code"}, - {".c"}, - {"text/x-csrc"}, - "C source code.", - REFERENCE_URL, - ""}, - {"general.c-plus-plus-header", - {"general.source-code"}, - {".hpp", ".h++", ".hxx", ".hh"}, - {"text/x-c++hdr"}, - "C++ header file.", - REFERENCE_URL, - ""}, - {"general.c-plus-plus-source", - {"general.source-code"}, - {".cp", ".cpp", ".c++", ".cc", ".cxx"}, - {"text/x-c++src"}, - "C++ source code.", - REFERENCE_URL, - ""}, - {"general.java-source", - {"general.source-code"}, - {".java", ".jav"}, - {"text/x-java"}, - "Java source code.", - REFERENCE_URL, - ""}, - {"general.markdown", - {"general.text"}, - {".md", ".markdown", ".markdn", ".mdown"}, - {"text/markdown"}, - "Markdown format.", - REFERENCE_URL, - ""}, - {"general.ebook", - {"general.composite-object"}, - {}, - {}, - "Base type for ebook.", - REFERENCE_URL, - ""}, - {"general.epub", - {"general.ebook"}, - {".epub"}, - {"application/epub+zip"}, - "Electronic publication (EPUB) format.", - REFERENCE_URL, - ""}, - {"com.amazon.azw", - {"general.ebook"}, - {".azw"}, - {"application/vnd.amazon.ebook"}, - "AZW ebook.", - REFERENCE_URL, - ""}, - {"com.amazon.azw3", - {"general.ebook"}, - {".azw3"}, - {"application/vnd.amazon.mobi8-ebook", "application/x-mobi8-ebook"}, - "AZW3 ebook.", - REFERENCE_URL, - ""}, - {"com.amazon.kfx", - {"general.ebook"}, - {".kfx"}, - {}, - "KFX ebook.", - REFERENCE_URL, - ""}, - {"com.amazon.mobi", - {"general.ebook"}, - {".mobi"}, - {"application/x-mobipocket-ebook"}, - "MOBI ebook.", - REFERENCE_URL, - ""}, - {"general.media", - {"general.object"}, - {}, - {}, - "Base type for media.", - REFERENCE_URL, - ""}, - {"general.image", - {"general.media"}, - {}, - {"image/*"}, - "Base type for images.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"general.jpeg", - {"general.image"}, - {".jpg", ".jpeg", ".jpe"}, - {"image/jpeg"}, - "JPEG image.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"general.png", - {"general.image"}, - {".png"}, - {"image/png"}, - "PNG image.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"general.raw-image", - {"general.image"}, - {}, - {}, - "Base type for digital camera raw image formats.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"general.tiff", - {"general.image"}, - {".tif", ".tiff"}, - {"image/tiff"}, - "TIFF image.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"com.microsoft.bmp", - {"general.image"}, - {".bmp", ".bm"}, - {"image/bmp", "image/x-ms-bmp"}, - "Windows bitmap image.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"com.microsoft.ico", - {"general.image"}, - {".ico"}, - {"image/ico", "image/x-icon"}, - "Windows icon image.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"com.adobe.photoshop-image", - {"general.image"}, - {".psd"}, - {"image/x-photoshop", "image/photoshop", "image/psd", "application/photoshop"}, - "Adobe Photoshop document.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"com.adobe.illustrator.ai-image", - {"general.image"}, - {".ai"}, - {}, - "Adobe Illustrator document.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"general.fax", - {"general.image"}, - {}, - {}, - "Base type for fax images.", - REFERENCE_URL, - ""}, - {"com.j2.jfx-fax", - {"general.fax"}, - {".jfx"}, - {}, - "J2 fax.", - REFERENCE_URL, - ""}, - {"com.js.efx-fax", - {"general.fax"}, - {".efx"}, - {"image/efax"}, - "eFax fax.", - REFERENCE_URL, - ""}, - {"general.xbitmap-image", - {"general.image"}, - {".xbm"}, - {"image/x-xbitmap", "image/x-xbm"}, - "X bitmap image.", - REFERENCE_URL, - ""}, - {"com.truevision.tga-image", - {"general.image"}, - {".tga"}, - {"image/targa", "image/tga", "application/tga"}, - "TGA image.", - REFERENCE_URL, - ""}, - {"com.sgi.sgi-image", - {"general.image"}, - {".sgi"}, - {"image/sgi"}, - "Silicon Graphics image.", - REFERENCE_URL, - ""}, - {"com.ilm.openexr-image", - {"general.image"}, - {".exr"}, - {}, - "OpenEXR image.", - REFERENCE_URL, - ""}, - {"com.kodak.flashpix.image", - {"general.image"}, - {".fpx"}, - {"image/fpx", "application/vnd.fpx"}, - "FlashPix image.", - REFERENCE_URL, - ""}, - {"com.microsoft.word.doc", - {"general.composite-object"}, - {".doc"}, - {"application/msword"}, - "Microsoft Word data.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_doc"}, - {"com.microsoft.excel.xls", - {"general.composite-object"}, - {".xls"}, - {"application/vnd.ms-excel"}, - "Microsoft Excel data.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_xls"}, - {"com.microsoft.powerpoint.ppt", - {"general.composite-object"}, - {".ppt"}, - {"application/vnd.ms-powerpoint"}, - "Microsoft PowerPoint presentation.", - REFERENCE_URL, - ""}, - {"com.adobe.pdf", - {"general.composite-object"}, - {".pdf"}, - {"application/pdf"}, - "PDF data.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_pdf"}, - {"com.adobe.postscript", - {"general.composite-object"}, - {".ps"}, - {"application/postscript"}, - "PostScript data.", - REFERENCE_URL, - ""}, - {"com.adobe.encapsulated-postscript", - {"com.adobe.postscript"}, - {".eps"}, - {}, - "Encapsulated PostScript.", - REFERENCE_URL, - ""}, - {"general.video", - {"general.media"}, - {}, - {"video/*"}, - "Base type for video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"general.avi", - {"general.video"}, - {".avi", ".vfw"}, - {"video/avi", "video/msvideo", "video/x-msvideo"}, - "AVI video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"general.mpeg", - {"general.video"}, - {".mpg", ".mpeg", ".m75", ".m15", ".mpe"}, - {"video/mpg", "video/mpeg", "video/x-mpg", "video/x-mpeg"}, - "MPEG-1 or MPEG-2 video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"general.mpeg-4", - {"general.video"}, - {".mp4", ".mp4v", ".mpeg4"}, - {"video/mp4", "video/mp4v"}, - "MPEG-4 video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"general.3gpp", - {"general.video"}, - {".3gp", ".3gpp"}, - {"video/3gpp"}, - "3GPP video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"general.3gpp2", - {"general.video"}, - {".3g2", ".3gp2", ".3gpp2"}, - {"video/3gpp2"}, - "3GPP2 video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.microsoft.windows-media-wm", - {"general.video", "com.microsoft.advanced-systems-format"}, - {".wm"}, - {"video/x-ms-wm"}, - "Windows WM video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.microsoft.windows-media-wmv", - {"general.video", "com.microsoft.advanced-systems-format"}, - {".wmv"}, - {"video/x-ms-wmv"}, - "Windows WMV video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.microsoft.windows-media-wmp", - {"general.video", "com.microsoft.advanced-systems-format"}, - {".wmp"}, - {"video/x-ms-wmp"}, - "Windows WMP video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.microsoft.windows-media-wvx", - {"general.video", "com.microsoft.advanced-systems-format"}, - {".wvx"}, - {"video/x-ms-wvx"}, - "Windows WVX video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.microsoft.windows-media-wmx", - {"general.video", "com.microsoft.advanced-systems-format"}, - {".wmx"}, - {"video/x-ms-wmx"}, - "Windows WMX video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.real.realmedia", - {"general.video"}, - {".rm"}, - {"application/vnd.rn-realmedia"}, - "RealMedia.", - REFERENCE_URL, - ""}, - {"general.audio", - {"general.media"}, - {}, - {"audio/*"}, - "Base type for audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.aac", - {"general.audio"}, - {".aac"}, - {"audio/aac"}, - "AAC audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.aiff", - {"general.audio"}, - {".aiff"}, - {"audio/aiff"}, - "AIFF audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.alac", - {"general.audio"}, - {".alac"}, - {"audio/alac"}, - "ALAC audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.flac", - {"general.audio"}, - {".flac"}, - {"audio/flac"}, - "FLAC audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_flac"}, - {"general.mp3", - {"general.audio"}, - {".mp3"}, - {"audio/mp3"}, - "MPEG-3 audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_mp3"}, - {"general.ogg", - {"general.audio"}, - {".ogg"}, - {"audio/ogg"}, - "OGG audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.pcm", - {"general.audio"}, - {".pcm"}, - {"audio/pcm"}, - "PCM audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"com.microsoft.advanced-systems-format", - {"general.media"}, - {".asf"}, - {"video/x-ms-asf", "application/vnd.ms-asf"}, - "Advanced Systems format", - REFERENCE_URL, - ""}, - {"com.microsoft.advanced-stream-redirector", - {"general.video"}, - {".asx"}, - {"video/x-ms-asf"}, - "Advanced stream redirector", - REFERENCE_URL, - ""}, - {"com.microsoft.windows-media-wma", - {"general.audio", "com.microsoft.advanced-systems-format"}, - {".wma"}, - {"audio/x-ms-wma"}, - "Windows WMA audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_wma"}, - {"com.microsoft.waveform-audio", - {"general.audio", "com.microsoft.advanced-systems-format"}, - {".wav", ".wave"}, - {"audio/wav", "audio/wave", "audio/x-wav"}, - "Waveform audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_wav"}, - {"com.microsoft.windows-media-wax", - {"general.audio", "com.microsoft.advanced-systems-format"}, - {".wax"}, - {"audio/x-ms-wax"}, - "Windows WAX audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.au-audio", - {"general.audio"}, - {".au", ".snd"}, - {"audio/basic", "audio/au", "audio/snd"}, - "Au file format.", - REFERENCE_URL, - ""}, - {"general.aifc-audio", - {"general.audio"}, - {".aifc", ".aif", ".aiff"}, - {"audio/x-aiff"}, - "Audio Interchange File Format.", - REFERENCE_URL, - ""}, - {"com.digidesign.sd2-audio", - {"general.audio"}, - {".sd2"}, - {"audio/x-sd2"}, - "Digidesign Sound Designer II audio.", - REFERENCE_URL, - ""}, - {"com.real.realaudio", - {"general.audio"}, - {".ram", ".ra"}, - {"audio/vnd.rn-realaudio", "audio/x-pn-realaudio"}, - "RealMedia audio.", - REFERENCE_URL, - ""}, - {"general.file", - {"general.entity"}, - {}, - {}, - "Base type for file.", - REFERENCE_URL, - ""}, - {"general.directory", - {"general.entity"}, - {}, - {}, - "Base type for directory.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_folder"}, - {"general.folder", - {"general.directory"}, - {}, - {}, - "Base type for folder.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_folder"}, - {"general.symlink", - {"general.entity"}, - {}, - {}, - "Base type for symlink.", - REFERENCE_URL, - ""}, - {"general.archive", - {"general.object"}, - {}, - {}, - "Base type for an archive of files and directories.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"general.bz2-archive", - {"general.archive"}, - {".bz2", ".bzip2"}, - {"application/x-bzip2"}, - "BZip2 archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"general.disk-image", - {"general.archive"}, - {}, - {}, - "Base type for items mountable as a volume.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"general.tar-archive", - {"general.archive"}, - {".tar"}, - {"application/x-tar", "application/tar"}, - "Tar archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"general.zip-archive", - {"general.archive"}, - {".zip"}, - {"application/zip"}, - "Zip archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_zip"}, - {"com.sun.java-archive", - {"general.archive", "general.executable"}, - {".jar"}, - {"application/java-archive"}, - "Java archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"org.gnu.gnu-tar-archive", - {"general.archive"}, - {".gtar"}, - {"application/x-gtar"}, - "GNU archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"org.gnu.gnu-zip-archive", - {"general.archive"}, - {".gz", ".gzip"}, - {"application/x-gzip", "application/gzip"}, - "Gzip archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"org.gnu.gnu-zip-tar-archive", - {"general.archive"}, - {".tgz"}, - {"application/x-gtar"}, - "Gzip tar archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"org.openxmlformats.openxml", - {"general.archive"}, - {}, - {}, - "Office Open XML.", - REFERENCE_URL, - ""}, - {"org.openxmlformats.wordprocessingml.document", - {"general.composite-object", "org.openxmlformats.openxml"}, - {".docx"}, - {"application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, - "Office Open XML Document.", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.sheet", - {"general.composite-object", "org.openxmlformats.openxml"}, - {".xlsx"}, - {"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, - "Office Open XML Workbook.", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.presentation", - {"general.composite-object", "org.openxmlformats.openxml"}, - {".pptx"}, - {"application/vnd.openxmlformats-officedocument.presentationml.presentation"}, - "Office Open XML Presentation.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument", - {"general.archive"}, - {}, - {}, - "Open Document Format for Office Applications.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument.text", - {"general.composite-object", "org.oasis.opendocument"}, - {".odt", ".fodt"}, - {"application/vnd.oasis.opendocument.text"}, - "OpenDocument Text.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument.spreadsheet", - {"general.composite-object", "org.oasis.opendocument"}, - {".ods", ".fods"}, - {"application/vnd.oasis.opendocument.spreadsheet"}, - "OpenDocument Spreadsheet.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument.presentation", - {"general.composite-object", "org.oasis.opendocument"}, - {".odp", ".fodp"}, - {"application/vnd.oasis.opendocument.presentation"}, - "OpenDocument Presentation.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument.graphics", - {"general.composite-object", "org.oasis.opendocument"}, - {".odg", ".fodg"}, - {"application/vnd.oasis.opendocument.graphics"}, - "OpenDocument Graphics.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument.formula", - {"org.oasis.opendocument"}, - {".odf"}, - {"application/vnd.oasis.opendocument.formula"}, - "OpenDocument Formulat.", - REFERENCE_URL, - ""}, - {"com.allume.stuffit-archive", - {"general.archive"}, - {".sit", ".sitx"}, - {"application/x-stuffit", "application/x-sit", "application/stuffit"}, - "Stuffit archive.", - REFERENCE_URL, - ""}, - {"general.calendar", - {"general.text"}, - {}, - {"text/calendar"}, - "Base type for scheduled events.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_calendar"}, - {"general.vcs", - {"general.calendar"}, - {".vcs"}, - {"text/calendar"}, - "vCalendar type.", - REFERENCE_URL, - ""}, - {"general.ics", - {"general.calendar"}, - {".ics"}, - {"text/calendar"}, - "iCalendar type.", - REFERENCE_URL, - ""}, - {"general.contact", - {"general.object"}, - {}, - {}, - "Base type for contact information.", - REFERENCE_URL, - ""}, - {"general.database", - {"general.object"}, - {}, - {}, - "Base type for databases.", - REFERENCE_URL, - ""}, - {"general.message", - {"general.object"}, - {}, - {}, - "Base type for messages.", - REFERENCE_URL, - ""}, - {"general.executable", - {"general.object"}, - {}, - {}, - "Base type for executable data.", - REFERENCE_URL, - ""}, - {"com.microsoft.portable-executable", - {"general.executable"}, - {".exe", ".dll"}, - {"application/vnd.microsoft.portable-executable"}, - "Microsoft Windows application.", - REFERENCE_URL, - ""}, - {"com.sun.java-class", - {"general.executable"}, - {".class"}, - {}, - "Java class.", - REFERENCE_URL, - ""}, - {"general.vcard", - {"general.object"}, - {".vcf", ".vcard"}, - {"text/vcard", "text/x-vcard"}, - "Base type for electronic business card.", - REFERENCE_URL, - ""}, - {"general.navigation", - {"general.object"}, - {}, - {}, - "Base type for navigation.", - REFERENCE_URL, - ""}, - {"general.location", - {"general.navigation"}, - {}, - {}, - "Navigation location.", - REFERENCE_URL, - ""}, - {"general.font", - {"general.object"}, - {}, - {}, - "Base type for fonts.", - REFERENCE_URL, - ""}, - {"general.truetype-font", - {"general.font"}, - {".ttf"}, - {"font/ttf"}, - "TrueType font.", - REFERENCE_URL, - ""}, - {"general.truetype-collection-font", - {"general.font"}, - {".ttc"}, - {"font/collection"}, - "TrueType collection font.", - REFERENCE_URL, - ""}, - {"general.opentype-font", - {"general.font"}, - {".otf"}, - {"font/otf"}, - "OpenType font.", - REFERENCE_URL, - ""}, - {"com.adobe.postscript-font", - {"general.font"}, - {}, - {}, - "PostScript font.", - REFERENCE_URL, - ""}, - {"openharmony.form", - {"general.object"}, - {}, - {}, - "OpenHarmony system defined form.", - REFERENCE_URL, - ""}, - {"openharmony.app-item", - {"general.object"}, - {}, - {}, - "OpenHarmony system defined app item.", - REFERENCE_URL, - ""}, - {"openharmony.pixel-map", - {"general.image"}, - {}, - {}, - "OpenHarmony system defined pixel map.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"openharmony.atomic-service", - {"general.object"}, - {}, - {}, - "OpenHarmony system defined atomic service.", - REFERENCE_URL, - ""}, - {"openharmony.package", - {"general.directory"}, - {}, - {}, - "OpenHarmony system defined package (that is, a directory presented to the user as a file).", - REFERENCE_URL, - ""}, - {"openharmony.hap", - {"openharmony.package"}, - {".hap"}, - {}, - "OpenHarmony system defined ability package.", - REFERENCE_URL, - ""}, - {"openharmony.hdoc", - {"general.composite-object"}, - {".hdoc"}, - {}, - "OpenHarmony system AppNotepad data format.", - REFERENCE_URL, - ""}, - {"openharmony.hinote", - {"general.composite-object"}, - {".hinote"}, - {}, - "OpenHarmony system Notes data format.", - REFERENCE_URL, - ""}, - {"openharmony.styled-string", - {"general.composite-object"}, - {}, - {}, - "OpenHarmony system defined styled string.", - REFERENCE_URL, - ""}, - {"openharmony.want", - {"general.object"}, - {}, - {}, - "OpenHarmony system defined Want.", - REFERENCE_URL, - ""}, - {"openharmony.moving-photo", - {"general.media"}, - {}, - {}, - "OpenHarmony system defined moving photo.", - REFERENCE_URL, - ""}, - {"macos.dmg", - {"general.disk-image"}, - {".dmg"}, - {"application/x-apple-diskimage"}, - "Apple Disk Image", - REFERENCE_URL, - ""}, - {"debian.deb", - {"general.archive"}, - {".deb", ".udeb"}, - {"application/x-debian-package", "application/vnd.debian.binary-package"}, - "OpenHarmony system defined Want.", - REFERENCE_URL, - ""}, - {"general.ofd", - {"general.composite-object"}, - {".ofd"}, - {}, - "Open fixed-layout document, a national standard for format documents", - REFERENCE_URL, - ""}, - {"general.opg", - {"general.archive"}, - {".opg"}, - {}, - "OPG archive", - REFERENCE_URL, - ""}, - {"general.tex", - {"general.source-code"}, - {}, - {}, - "Base type for TeX source code", - REFERENCE_URL, - ""}, - {"general.css", - {"general.script"}, - {".css"}, - {"text/css"}, - "Cascading style sheets", - REFERENCE_URL, - ""}, - {"general.vob", - {"general.video"}, - {".vob"}, - {"video/mpeg", "video/x-ms-vob"}, - "", - REFERENCE_URL, - ""}, - {"general.dif-video", - {"general.video"}, - {".dif"}, - {"video/dv"}, - "Digital interface format", - REFERENCE_URL, - ""}, - {"general.dv-video", - {"general.video"}, - {".dv"}, - {"video/dv"}, - "DV video", - REFERENCE_URL, - ""}, - {"general.flc-animation", - {"general.video"}, - {".fli", ".flc"}, - {"video/fli", "video/flc"}, - "FLIC file format", - REFERENCE_URL, - ""}, - {"general.mng", - {"general.video"}, - {".mng"}, - {"video/x-mng"}, - "Multiple-image network graphics", - REFERENCE_URL, - ""}, - {"general.mpegurl-video", - {"general.video"}, - {".mxu", ".m4u"}, - {"video/vnd.mpegurl"}, - "Video playlist", - REFERENCE_URL, - ""}, - {"general.ts", - {"general.video"}, - {".ts"}, - {"video/mp2ts", "video/mp2t"}, - "MPEG transport stream", - REFERENCE_URL, - ""}, - {"general.amr", - {"general.audio"}, - {".amr"}, - {"audio/amr"}, - "The adaptive multi-rate audio codecs", - REFERENCE_URL, - ""}, - {"general.amr-wb", - {"general.audio"}, - {".awb"}, - {"audio/amr-wb"}, - "Adaptive multi-rate wideband", - REFERENCE_URL, - ""}, - {"general.gsm", - {"general.audio"}, - {".gsm"}, - {"audio/x-gsm", "audio/gsm"}, - "Global system form mobile audio format", - REFERENCE_URL, - ""}, - {"general.imy", - {"general.audio"}, - {".imy"}, - {"audio/imelody"}, - "Non-polyphonic ringtone exchange object format", - REFERENCE_URL, - ""}, - {"general.kar", - {"general.audio"}, - {".kar"}, - {"audio/midi"}, - "Karaoke MIDI file format", - REFERENCE_URL, - ""}, - {"general.mpegurl-audio", - {"general.audio"}, - {".m3u"}, - {"audio/mpegurl", "audio/x-mpegurl"}, - "Audio playlist", - REFERENCE_URL, - ""}, - {"general.mpeg-4-audio", - {"general.audio"}, - {".m4a", ".m4b"}, - {"audio/mpeg"}, - "Audio-only MPEG-4 file", - REFERENCE_URL, - ""}, - {"general.midi-audio", - {"general.audio"}, - {".mid", ".midi"}, - {"audio/midi"}, - "MIDI audio", - REFERENCE_URL, - ""}, - {"general.mp2", - {"general.audio"}, - {".mp2"}, - {"audio/mpeg"}, - "MPEG-1 audio layer II or MPEG-2 audio layer II", - REFERENCE_URL, - ""}, - {"general.mpeg-audio", - {"general.audio"}, - {".mpga"}, - {"audio/mpeg"}, - "MPEG audio format", - REFERENCE_URL, - ""}, - {"general.mxmf", - {"general.audio"}, - {".mxmf"}, - {"audio/mobile-xmf"}, - "Mobile XMF audio format", - REFERENCE_URL, - ""}, - {"general.ota", - {"general.audio"}, - {".ota"}, - {"audio/midi"}, - "OTA ringtone file", - REFERENCE_URL, - ""}, - {"general.pls", - {"general.audio"}, - {".pls"}, - {"audio/x-scpls"}, - "Multimedia playlist format", - REFERENCE_URL, - ""}, - {"general.rtttl", - {"general.audio"}, - {".rtttl"}, - {"audio/midi"}, - "Ring tone transfer language file", - REFERENCE_URL, - ""}, - {"general.psid", - {"general.audio"}, - {".sid", ".psid"}, - {"audio/prs.sid"}, - "SID audio", - REFERENCE_URL, - ""}, - {"general.ulaw-audio", - {"general.audio"}, - {".au", ".ulw", ".snd"}, - {"audio/basic", "audio/au", "audio/snd"}, - "uLaw audio", - REFERENCE_URL, - ""}, - {"general.xmf", - {"general.audio"}, - {".xmf"}, - {"audio/midi"}, - "Extensible music file", - REFERENCE_URL, - ""}, - {"general.gif", - {"general.image"}, - {".gif"}, - {"image/gif"}, - "GIF image", - REFERENCE_URL, - ""}, - {"general.djvu-image", - {"general.image"}, - {".djv", ".djvu"}, - {"image/vnd.djvu"}, - "Djvu image", - REFERENCE_URL, - ""}, - {"general.jng-image", - {"general.image"}, - {".jng"}, - {"image/x-jng"}, - "JPEG network graphic", - REFERENCE_URL, - ""}, - {"general.pcx-image", - {"general.image"}, - {".pcx"}, - {"image/vnd.zbrush.pcx"}, - "Paintbrush bitmap image", - REFERENCE_URL, - ""}, - {"general.pbm-image", - {"general.image"}, - {".pbm"}, - {"image/x-portable-bitmap"}, - "Portable bitmap image", - REFERENCE_URL, - ""}, - {"general.pgm-image", - {"general.image"}, - {".pgm"}, - {"image/x-portable-graymap"}, - "Portable gray map image", - REFERENCE_URL, - ""}, - {"general.pnm-image", - {"general.image"}, - {".pnm"}, - {"image/x-portable-anymap"}, - "Portable any map image file", - REFERENCE_URL, - ""}, - {"general.ppm-image", - {"general.image"}, - {".ppm"}, - {"image/x-portable-pixmap"}, - "Portable pixmap image", - REFERENCE_URL, - ""}, - {"general.rgb-image", - {"general.image"}, - {".rgb"}, - {"image/x-rgb"}, - "RGB bitmap", - REFERENCE_URL, - ""}, - {"general.svg-image", - {"general.image"}, - {".svg", ".svgz"}, - {"image/svg+xml"}, - "Scalable vector graphic", - REFERENCE_URL, - ""}, - {"general.wbmp-image", - {"general.image"}, - {".wbmp"}, - {"image/vnd.wap.wbmp"}, - "Wireless bitmap image", - REFERENCE_URL, - ""}, - {"general.xpixmap-image", - {"general.image"}, - {".xpm"}, - {"image/x-xpixmap"}, - "X11 pixmap graphic", - REFERENCE_URL, - ""}, - {"general.xwindowdump-image", - {"general.image"}, - {".xwd"}, - {"image/x-xwindowdump"}, - "X windows dump image", - REFERENCE_URL, - ""}, - {"general.heif", - {"general.image"}, - {".heif", ".heifs", ".hif"}, - {"image/heif"}, - "High efficiency image format", - REFERENCE_URL, - ""}, - {"general.heic", - {"general.image"}, - {".heic", ".heics"}, - {"image/heic"}, - "High efficiency image format", - REFERENCE_URL, - ""}, - {"general.virtual-cd", - {"general.disk-image"}, - {".vcd"}, - {"application/x-cdlink"}, - "Virtual CD", - REFERENCE_URL, - ""}, - {"general.boo-source", - {"general.source-code"}, - {".boo"}, - {"text/x-boo"}, - "Boo source code", - REFERENCE_URL, - ""}, - {"general.d-source", - {"general.source-code"}, - {".d"}, - {"text/x-dsrc"}, - "D source code file", - REFERENCE_URL, - ""}, - {"general.html-component", - {"general.source-code"}, - {".htc"}, - {"text/x-component"}, - "HTML component", - REFERENCE_URL, - ""}, - {"general.pascal-source", - {"general.source-code"}, - {".p", ".pas"}, - {"text/x-pascal"}, - "Pascal source code", - REFERENCE_URL, - ""}, - {"general.haskell-script", - {"general.script"}, - {".hs"}, - {"text/x-haskell"}, - "Haskell script", - REFERENCE_URL, - ""}, - {"general.literate-haskell-script", - {"general.script"}, - {".lhs"}, - {"text/x-literate-haskell"}, - "Literate haskell script", - REFERENCE_URL, - ""}, - {"general.tcl-script", - {"general.script"}, - {".tcl"}, - {"text/x-tcl"}, - "Tcl script", - REFERENCE_URL, - ""}, - {"general.asc-text", - {"general.text"}, - {".asc"}, - {"text/plain"}, - "ASCII text file", - REFERENCE_URL, - ""}, - {"general.portable-object", - {"general.text"}, - {".po"}, - {"text/plain"}, - "Portable object", - REFERENCE_URL, - ""}, - {"general.rich-text", - {"general.text"}, - {".rtf", ".rtx"}, - {"text/rtf", "text/richtext"}, - "Rich text format file", - REFERENCE_URL, - ""}, - {"general.delimited-values-text", - {"general.text"}, - {}, - {}, - "Base type for delimited-values text", - REFERENCE_URL, - ""}, - {"general.comma-separated-values-text", - {"general.delimited-values-text"}, - {".csv"}, - {"text/csv"}, - "Comma-separated values file", - REFERENCE_URL, - ""}, - {"general.diff", - {"general.text"}, - {".diff"}, - {"text/plain"}, - "Patch file", - REFERENCE_URL, - ""}, - {"general.setext", - {"general.text"}, - {".etx"}, - {"text/x-setext"}, - "Structure enhanced Text", - REFERENCE_URL, - ""}, - {"general.gcd", - {"general.text"}, - {".gcd"}, - {"text/x-pcs-gcd"}, - "General content descriptor", - REFERENCE_URL, - ""}, - {"general.tab-separated-values-text", - {"general.delimited-values-text"}, - {".tsv"}, - {"text/tab-separated-values"}, - "Tab-Separated values file", - REFERENCE_URL, - ""}, - {"general.p7r", - {"general.text"}, - {".p7r"}, - {"application/x-pkcs7-certreqresp"}, - "Certificate request response file", - REFERENCE_URL, - ""}, - {"general.pem", - {"general.text"}, - {".pem"}, - {"application/x-pem-file"}, - "Privacy enhanced mail certificate", - REFERENCE_URL, - ""}, - {"general.chess-pgn", - {"general.plain-text"}, - {".pgn"}, - {"application/x-chess-pgn", "application/vnd.chess-pgn"}, - "Portable game notation file", - REFERENCE_URL, - ""}, - {"general.lha-archive", - {"general.archive"}, - {".lha"}, - {"application/x-lha"}, - "LHARC compressed archive", - REFERENCE_URL, - ""}, - {"general.lzh-archive", - {"general.archive"}, - {".lzh"}, - {"application/x-lzh"}, - "LZH compressed file", - REFERENCE_URL, - ""}, - {"general.lzx-archive", - {"general.archive"}, - {".lzx"}, - {"application/x-lzx"}, - "LZX compressed archive", - REFERENCE_URL, - ""}, - {"general.taz-archive", - {"general.tar-archive"}, - {".taz", ".tar.z", ".tz"}, - {"application/x-gtar"}, - "Tar zipped file", - REFERENCE_URL, - ""}, - {"general.shar-archive", - {"general.archive"}, - {".shar"}, - {"application/x-shar"}, - "Unix Shar archive", - REFERENCE_URL, - ""}, - {"general.cpio-archive", - {"general.archive"}, - {".cpio"}, - {"application/x-cpio"}, - "Unix CPIO archive", - REFERENCE_URL, - ""}, - {"general.web-archive", - {"general.archive"}, - {".mht", ".mhtml"}, - {"application/x-mimearchive"}, - "MHTML web archive", - REFERENCE_URL, - ""}, - {"general.ustar", - {"general.archive"}, - {".ustar"}, - {"application/x-ustar"}, - "Uniform standard tape archive format", - REFERENCE_URL, - ""}, - {"general.mathml", - {"general.xml"}, - {".mml"}, - {"text/mathml", "application/mathml+xml"}, - "Mathematical markup language file", - REFERENCE_URL, - ""}, - {"general.xhtml", - {"general.xml"}, - {".xhtml"}, - {"application/xhtml+xml"}, - "XHTML", - REFERENCE_URL, - ""}, - {"general.rss", - {"general.xml"}, - {".rss"}, - {"application/rss+xml"}, - "Rich site summary", - REFERENCE_URL, - ""}, - {"general.rdf", - {"general.xml"}, - {".rdf"}, - {"application/rdf+xml"}, - "Resource description framework file", - REFERENCE_URL, - ""}, - {"general.cad", - {"general.object"}, - {}, - {}, - "Base type for computer-aided design", - REFERENCE_URL, - ""}, - {"general.iges", - {"general.cad"}, - {".iges", ".igs"}, - {"model/iges"}, - "IGES drawing", - REFERENCE_URL, - ""}, - {"general.octet-stream", - {"general.object"}, - {}, - {"application/octet-stream"}, - "Arbitrary binary data", - REFERENCE_URL, - ""}, - {"general.iso", - {"general.disk-image"}, - {".iso"}, - {"application/x-iso9660-image"}, - "Disc image file", - REFERENCE_URL, - ""}, - {"general.mesh-model", - {"general.object"}, - {".msh", ".mesh", ".silo"}, - {"model/mesh"}, - "3D mesh model", - REFERENCE_URL, - ""}, - {"general.certificate", - {"general.object"}, - {}, - {}, - "Base type for security certificate", - REFERENCE_URL, - ""}, - {"general.c-object", - {"general.executable"}, - {".o"}, - {"application/x-object"}, - "Compiled C object file", - REFERENCE_URL, - ""}, - {"general.dvi", - {"general.tex"}, - {".dvi"}, - {"application/x-dvi"}, - "Device independent format file", - REFERENCE_URL, - ""}, - {"general.cer-certificate", - {"general.certificate"}, - {".cer"}, - {"application/pkix-cert"}, - "Internet security certificate", - REFERENCE_URL, - ""}, - {"general.crt-certificate", - {"general.certificate"}, - {".crt"}, - {"application/x-x509-ca-cert", "application/x-x509-server-cert", "application/x-x509-user-cert"}, - "Security Certificate", - REFERENCE_URL, - ""}, - {"general.crl-certificate", - {"general.certificate"}, - {".crl"}, - {"application/x-pkix-crl"}, - "Certificate revocation list file", - REFERENCE_URL, - ""}, - {"general.prn", - {"general.composite-object"}, - {".prn"}, - {}, - "Print to file", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.chart", - {"org.oasis.opendocument", "general.composite-object"}, - {".odc"}, - {"application/vnd.oasis.opendocument.chart"}, - "Open Document chart", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.text-master", - {"org.oasis.opendocument", "general.composite-object"}, - {".odm"}, - {"application/vnd.oasis.opendocument.text-master"}, - "Open Document text master", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.text-web", - {"org.oasis.opendocument", "general.composite-object"}, - {".oth"}, - {"application/vnd.oasis.opendocument.text-web"}, - "Open Document HTML template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.database", - {"org.oasis.opendocument", "general.database"}, - {".odb"}, - {"application/vnd.oasis.opendocument.database"}, - "Open Document database", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.image", - {"org.oasis.opendocument", "general.image"}, - {".odi"}, - {"application/vnd.oasis.opendocument.image"}, - "Open Document image", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.formula-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".otf"}, - {"application/vnd.oasis.opendocument.formula-template"}, - "Open Document formula template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.chart-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".otc"}, - {"application/vnd.oasis.opendocument.chart-template"}, - "Open Document chart template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.presentation-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".otp"}, - {"application/vnd.oasis.opendocument.presentation-template"}, - "Open Document presentation template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.image-template", - {"org.oasis.opendocument", "general.image"}, - {".oti"}, - {"application/vnd.oasis.opendocument.image-template"}, - "Open Document image template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.graphics-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".otg"}, - {"application/vnd.oasis.opendocument.graphics-template"}, - "Open Document graphics template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.spreadsheet-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".ots"}, - {"application/vnd.oasis.opendocument.spreadsheet-template"}, - "Open Document spreadsheet template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.text-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".ott"}, - {"application/vnd.oasis.opendocument.text-template"}, - "Open Document text template", - REFERENCE_URL, - ""}, - {"com.microsoft.word.dot", - {"general.composite-object"}, - {".dot"}, - {"application/msword"}, - "Microsoft Word document template", - REFERENCE_URL, - ""}, - {"com.microsoft.powerpoint.pps", - {"general.composite-object"}, - {".pps"}, - {"application/vnd.ms-powerpoint"}, - "Microsoft PowerPoint slide show", - REFERENCE_URL, - ""}, - {"com.microsoft.powerpoint.pot", - {"general.composite-object"}, - {".pot"}, - {"application/vnd.ms-powerpoint"}, - "Microsoft PowerPoint Template", - REFERENCE_URL, - ""}, - {"com.microsoft.excel.xlt", - {"general.composite-object"}, - {".xlt"}, - {"application/vnd.ms-excel"}, - "Microsoft Excel spreadsheet template", - REFERENCE_URL, - ""}, - {"com.microsoft.visio.vsd", - {"general.composite-object"}, - {".vsd"}, - {"application/vnd.visio"}, - "Microsoft Office Visio 2003-2010 drawing", - REFERENCE_URL, - ""}, - {"org.openxmlformats.drawingml.visio", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".vsdx"}, - {"application/vnd.openxmlformats-officedocument.drawingml.drawing"}, - "Microsoft Visio drawing", - REFERENCE_URL, - ""}, - {"org.openxmlformats.drawingml.template", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".vstx"}, - {}, - "Microsoft Visio drawing template", - REFERENCE_URL, - ""}, - {"org.openxmlformats.drawingml.visio.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".vsdm"}, - {}, - "Visio macro-enabled drawing", - REFERENCE_URL, - ""}, - {"org.openxmlformats.drawingml.template.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".vstm"}, - {}, - "Visio macro-enabled drawing template", - REFERENCE_URL, - ""}, - {"org.openxmlformats.wordprocessingml.template", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".dotx"}, - {"application/vnd.openxmlformats-officedocument.wordprocessingml.template"}, - "Office Open XML document template.", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.template", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".potx"}, - {"application/vnd.openxmlformats-officedocument.presentationml.template"}, - "Office Open XML presentation template", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.slideshow", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".ppsx"}, - {"application/vnd.openxmlformats-officedocument.presentationml.slideshow"}, - "Office Open XML slide show", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.template", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".xltx"}, - {"application/vnd.openxmlformats-officedocument.spreadsheetml.template"}, - "Office Open XML spreadsheet template", - REFERENCE_URL, - ""}, - {"org.openxmlformats.wordprocessingml.document.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".docm"}, - {"application/vnd.ms-word.document.macroEnabled.12"}, - "Office Open XML word processing document (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.wordprocessingml.template.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".dotm"}, - {"application/vnd.ms-word.template.macroEnabled.12"}, - "Office Open XML word processing template (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.template.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".xltm"}, - {"application/vnd.ms-excel.template.macroEnabled.12"}, - "Office Open XML spreadsheet template (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.addin.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".xlam"}, - {"application/vnd.ms-excel.addin.macroEnabled.12"}, - "Office Open XML spreadsheet addin (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.binary.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".xlsb"}, - {"application/vnd.ms-excel.sheet.binary.macroEnabled.12"}, - "Office Open XML spreadsheet binary (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.sheet.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".xlsm"}, - {"application/vnd.ms-excel.sheet.macroEnabled.12"}, - "Office Open XML spreadsheet (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.addin.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".ppam"}, - {"application/vnd.ms-powerpoint.addin.macroEnabled.12"}, - "Office Open XML presentation addin (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.presentation.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".pptm"}, - {"application/vnd.ms-powerpoint.presentation.macroEnabled.12"}, - "Office Open XML presentation (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.slideshow.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".ppsm"}, - {"application/vnd.ms-powerpoint.slideshow.macroEnabled.12"}, - "Office Open XML slide show (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.template.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".potm"}, - {"application/vnd.ms-powerpoint.template.macroEnabled.12"}, - "Office Open XML presentation template (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openoffice", - {"general.archive"}, - {}, - {}, - "OpenOffice document format for open-source office software suite", - REFERENCE_URL, - ""}, - {"org.openoffice.calc", - {"org.openoffice", "general.composite-object"}, - {".sxc"}, - {"application/vnd.sun.xml.calc"}, - "StarOffice Calc spreadsheet", - REFERENCE_URL, - ""}, - {"org.openoffice.draw", - {"org.openoffice", "general.composite-object"}, - {".sxd"}, - {"application/vnd.sun.xml.draw"}, - "StarOffice Drawing", - REFERENCE_URL, - ""}, - {"org.openoffice.writer-global", - {"org.openoffice", "general.composite-object"}, - {".sxg"}, - {"application/vnd.sun.xml.writer.global"}, - "Apache OpenOffice master document", - REFERENCE_URL, - ""}, - {"org.openoffice.impress", - {"org.openoffice", "general.composite-object"}, - {".sxi"}, - {"application/vnd.sun.xml.impress"}, - "StarOffice Impress presentation", - REFERENCE_URL, - ""}, - {"org.openoffice.math", - {"org.openoffice", "general.composite-object"}, - {".sxm"}, - {"application/vnd.sun.xml.math"}, - "StarMath Formula", - REFERENCE_URL, - ""}, - {"org.openoffice.writer", - {"org.openoffice", "general.composite-object"}, - {".sxw"}, - {"application/vnd.sun.xml.writer"}, - "StarOffice Writer document", - REFERENCE_URL, - ""}, - {"org.openoffice.calc.template", - {"org.openoffice", "general.composite-object"}, - {".stc"}, - {"application/vnd.sun.xml.calc.template"}, - "StarOffice Calc spreadsheet template", - REFERENCE_URL, - ""}, - {"org.openoffice.draw.template", - {"org.openoffice", "general.composite-object"}, - {".std"}, - {"application/vnd.sun.xml.draw.template"}, - "Apache OpenOffice Drawing template", - REFERENCE_URL, - ""}, - {"org.openoffice.impress.template", - {"org.openoffice", "general.composite-object"}, - {".sti"}, - {"application/vnd.sun.xml.impress.template"}, - "StarOffice Presentation template", - REFERENCE_URL, - ""}, - {"org.openoffice.writer.template", - {"org.openoffice", "general.composite-object"}, - {".stw"}, - {"application/vnd.sun.xml.writer.template"}, - "StarOffice Document template", - REFERENCE_URL, - ""}, - {"com.staroffice", - {"general.archive"}, - {}, - {}, - "StarOffice document format", - REFERENCE_URL, - ""}, - {"com.staroffice.draw", - {"com.staroffice", "general.composite-object"}, - {".sda"}, - {"application/vnd.stardivision.draw"}, - "StarOffice Drawing", - REFERENCE_URL, - ""}, - {"com.staroffice.calc", - {"com.staroffice", "general.composite-object"}, - {".sdc"}, - {"application/vnd.stardivision.calc"}, - "StarOffice Calc spreadsheet", - REFERENCE_URL, - ""}, - {"com.staroffice.impress", - {"com.staroffice", "general.composite-object"}, - {".sdd", ".sdp"}, - {"application/vnd.stardivision.impress"}, - "StarOffice Presentation", - REFERENCE_URL, - ""}, - {"com.staroffice.writer", - {"com.staroffice", "general.composite-object"}, - {".sdw"}, - {"application/vnd.stardivision.writer"}, - "StarOffice Writer text document", - REFERENCE_URL, - ""}, - {"com.staroffice.chart", - {"com.staroffice", "general.composite-object"}, - {".sds"}, - {"application/vnd.stardivision.chart"}, - "StarOffice Chart", - REFERENCE_URL, - ""}, - {"com.staroffice.mail", - {"com.staroffice", "general.composite-object"}, - {".sdm"}, - {"application/vnd.stardivision.mail"}, - "StarOffice Mail message", - REFERENCE_URL, - ""}, - {"com.staroffice.writer-global", - {"com.staroffice", "general.composite-object"}, - {".sgl"}, - {"application/vnd.stardivision.writer-global"}, - "StarOffice Master document", - REFERENCE_URL, - ""}, - {"com.staroffice.math", - {"com.staroffice", "general.composite-object"}, - {".smf"}, - {"application/vnd.stardivision.math"}, - "StarMath Formula file", - REFERENCE_URL, - ""}, - {"com.staroffice.template", - {"com.staroffice", "general.composite-object"}, - {".vor"}, - {"application/vnd.stardivision.template"}, - "StarOffice Template", - REFERENCE_URL, - ""}, - {"org.tug.bib", - {"general.tex"}, - {".bib"}, - {"text/x-bibtex"}, - "TeX Bibliography file", - REFERENCE_URL, - ""}, - {"org.tug.cls", - {"general.tex"}, - {".cls"}, - {"text/x-tex"}, - "TeX Class file", - REFERENCE_URL, - ""}, - {"org.tug.sty", - {"general.tex"}, - {".sty"}, - {"text/x-tex"}, - "TeX Style file", - REFERENCE_URL, - ""}, - {"org.tug.tex", - {"general.tex"}, - {".tex"}, - {"text/x-tex"}, - "TeX source document file", - REFERENCE_URL, - ""}, - {"org.latex-project.latex", - {"general.tex"}, - {".ltx", ".latex"}, - {"application/x-latex"}, - "LaTeX source document file", - REFERENCE_URL, - ""}, - {"org.matroska.mkv", - {"general.video"}, - {".mkv"}, - {"video/x-matroska"}, - "Matroska video", - REFERENCE_URL, - ""}, - {"org.matroska.mka", - {"general.audio"}, - {".mka"}, - {"audio/x-matroska"}, - "Matroska audio", - REFERENCE_URL, - ""}, - {"com.sgi.movie", - {"general.video"}, - {".movie"}, - {"video/x-sgi-movie"}, - "SGI movie", - REFERENCE_URL, - ""}, - {"com.apple.m4v", - {"general.video"}, - {".m4v"}, - {"video/m4v"}, - "M4V video", - REFERENCE_URL, - ""}, - {"org.webmproject.webm", - {"general.video"}, - {".webm"}, - {"video/webm"}, - "WebM is an audiovisual media file format", - REFERENCE_URL, - ""}, - {"com.apple.quicktime-movie", - {"general.video"}, - {".mov", ".qt", ".movie"}, - {"video/quicktime"}, - "QuickTime File Format", - REFERENCE_URL, - ""}, - {"com.coreldraw.cdr", - {"general.image"}, - {".cdr"}, - {"image/x-coreldraw"}, - "CorelDRAW file", - REFERENCE_URL, - ""}, - {"com.coreldraw.cdt", - {"general.image"}, - {".cdt"}, - {"image/x-coreldrawtemplate"}, - "CorelDRAW template", - REFERENCE_URL, - ""}, - {"com.coreldraw.cpt", - {"general.image"}, - {".cpt"}, - {"image/x-corelphotopaint"}, - "Corel PHOTO-PAINT image", - REFERENCE_URL, - ""}, - {"com.coreldraw.pat", - {"general.image"}, - {".pat"}, - {"image/x-coreldrawpattern"}, - "CorelDRAW pattern file", - REFERENCE_URL, - ""}, - {"com.microsoft.cur", - {"general.image"}, - {".cur"}, - {"image/ico"}, - "Microsoft Windows cursor image", - REFERENCE_URL, - ""}, - {"com.sun.raster", - {"general.image"}, - {".ras"}, - {"image/x-cmu-raster"}, - "Sun Raster Graphic", - REFERENCE_URL, - ""}, - {"com.google.webp", - {"general.image"}, - {".webp"}, - {"image/webp"}, - "WebP image", - REFERENCE_URL, - ""}, - {"com.sseyo.koan-audio", - {"general.audio"}, - {".skd", ".skm", ".skp", ".skt"}, - {"application/x-koan"}, - "Koan music files over the internet", - REFERENCE_URL, - ""}, - {"io.qt.moc", - {"general.source-code"}, - {".moc"}, - {"text/x-moc"}, - "Qt Meta-Object compiler file", - REFERENCE_URL, - ""}, - {"com.ghostscript.font", - {"general.font"}, - {".gsf"}, - {"application/x-font"}, - "Ghostscript font", - REFERENCE_URL, - ""}, - {"org.x.pcf-font", - {"general.font"}, - {".pcf"}, - {"application/x-font", "application/x-font-pcf"}, - "Portable compiled format", - REFERENCE_URL, - ""}, - {"com.microsoft.windows-media-wmd", - {"com.microsoft.advanced-systems-format", "general.zip-archive"}, - {".wmd"}, - {"application/x-ms-wmd"}, - "Windows media download package", - REFERENCE_URL, - ""}, - {"com.microsoft.windows-media-wmz", - {"com.microsoft.advanced-systems-format", "general.zip-archive"}, - {".wmz"}, - {"application/x-ms-wmz"}, - "Windows media player skin package", - REFERENCE_URL, - ""}, - {"com.microsoft.windows-installer", - {"general.executable"}, - {".msi"}, - {"application/x-msi"}, - "Windows installer package", - REFERENCE_URL, - ""}, - {"com.microsoft.publisher.pub", - {"general.composite-object"}, - {".pub"}, - {"application/x-mspublisher"}, - "Publisher document", - REFERENCE_URL, - ""}, - {"com.microsoft.windows-media-playlist", - {"general.xml", "general.media"}, - {".wpl"}, - {"application/vnd.ms-wpl"}, - "Windows media player playlist", - REFERENCE_URL, - ""}, - {"com.microsoft.access.mdb", - {"general.database"}, - {".mdb"}, - {"application/msaccess"}, - "Microsoft Access database", - REFERENCE_URL, - ""}, - {"com.3dsystems.stereolithography", - {"general.composite-object"}, - {".stl"}, - {"application/vnd.ms-pki.stl"}, - "Stereolithography file", - REFERENCE_URL, - ""}, - {"com.apple.media.playlist", - {"general.media"}, - {".m3u8"}, - {"application/vnd.apple.mpegurl"}, - "UTF-8 M3U playlist", - REFERENCE_URL, - ""}, - {"com.abisource.word", - {"general.composite-object"}, - {".abw"}, - {"application/x-abiword"}, - "AbiWord document", - REFERENCE_URL, - ""}, - {"com.adobe.framemaker", - {"general.composite-object"}, - {".book", ".fm", ".frame", ".maker"}, - {"application/x-maker"}, - "FrameMaker book file", - REFERENCE_URL, - ""}, - {"com.wolfram.cdf", - {"general.composite-object"}, - {".cdf"}, - {"application/x-cdf"}, - "Computable document format file", - REFERENCE_URL, - ""}, - {"de.cinderella.cdy", - {"general.composite-object"}, - {".cdy"}, - {"application/vnd.cinderella"}, - "Cinderella construction file", - REFERENCE_URL, - ""}, - {"com.adobe.dcr", - {"general.video"}, - {".dcr"}, - {"application/x-director"}, - "Shockwave media file", - REFERENCE_URL, - ""}, - {"com.adobe.dir", - {"general.video"}, - {".dir"}, - {"application/x-director"}, - "Adobe Director movie", - REFERENCE_URL, - ""}, - {"com.adobe.dxr", - {"general.video"}, - {".dxr"}, - {"application/x-director"}, - "Protected macromedia director movie", - REFERENCE_URL, - ""}, - {"org.gnumeric.spreadsheet", - {"general.xml"}, - {".gnumeric"}, - {"application/x-gnumeric"}, - "Gnumeric spreadsheet", - REFERENCE_URL, - ""}, - {"org.hdfgroup.hdf", - {"general.composite-object"}, - {".hdf"}, - {"application/x-hdf"}, - "Hierarchical data format", - REFERENCE_URL, - ""}, - {"com.apple.binhex-archive", - {"general.archive"}, - {".hqx"}, - {"application/mac-binhex40"}, - "BinHex 4.0 encoded file", - REFERENCE_URL, - ""}, - {"com.microsoft.hta", - {"general.archive", "general.executable"}, - {".hta"}, - {"application/hta"}, - "HTML application", - REFERENCE_URL, - ""}, - {"com.microsoft.internet.ins", - {"general.text"}, - {".ins"}, - {"application/x-internet-signup"}, - "Internet settings file", - REFERENCE_URL, - ""}, - {"com.microsoft.internet.isp", - {"general.text"}, - {".isp"}, - {"application/x-internet-signup"}, - "IIS internet service provider settings", - REFERENCE_URL, - ""}, - {"org.troff", - {"general.text"}, - {".man", ".t", ".roff"}, - {"text/troff"}, - "Unix troff format", - REFERENCE_URL, - ""}, - {"com.adobe.framemaker.mif", - {"general.composite-object"}, - {".mif"}, - {"application/vnd.mif"}, - "FrameMaker interchange format file", - REFERENCE_URL, - ""}, - {"io.sourceforge.freemind", - {"general.composite-object"}, - {".mm"}, - {"application/x-freemind"}, - "Mind Map file", - REFERENCE_URL, - ""}, - {"com.yamaha.smaf", - {"general.audio"}, - {".mmf"}, - {"application/vnd.smaf"}, - "Synthetic music mobile application file", - REFERENCE_URL, - ""}, - {"com.wolfram.mathematica.notebook", - {"general.text"}, - {".nb"}, - {"application/mathematica"}, - "Mathematica notebook", - REFERENCE_URL, - ""}, - {"org.xiph.ogg", - {"general.audio"}, - {".oga", ".ogg"}, - {"application/ogg"}, - "Ogg vorbis audio", - REFERENCE_URL, - ""}, - {"com.netscape.proxy-autoconfig", - {"general.plain-text"}, - {".pac"}, - {"application/x-ns-proxy-autoconfig"}, - "Proxy auto-config file", - REFERENCE_URL, - ""}, - {"com.rsa.pkcs-12", - {"general.archive"}, - {".pfx", ".p12"}, - {"application/x-pkcs12"}, - "PKCS #12 certificate file", - REFERENCE_URL, - ""}, - {"org.openpgp.signature", - {"general.object"}, - {".pgp"}, - {"application/pgp-signature"}, - "PGP security key", - REFERENCE_URL, - ""}, - {"com.apple.quicktime-link", - {"general.text"}, - {".qtl"}, - {"application/x-quicktimeplayer"}, - "QuickTime link file", - REFERENCE_URL, - ""}, - {"com.rarlab.rar-archive", - {"general.archive"}, - {".rar"}, - {"application/rar", "application/vnd.rar"}, - "WinRAR compressed archive", - REFERENCE_URL, - ""}, - {"org.7-zip.7-zip-archive", - {"general.archive"}, - {".7z"}, - {"application/x-7z-compressed"}, - "7-zip compressed archive", - REFERENCE_URL, - ""}, - {"com.red-bean.sgf", - {"general.text"}, - {".sgf"}, - {"application/x-go-sgf"}, - "Smart game format file", - REFERENCE_URL, - ""}, - {"com.stuffit.sit-archive", - {"general.archive"}, - {".sit"}, - {"application/x-stuffit"}, - "Stuffit archive", - REFERENCE_URL, - ""}, - {"com.adobe.futuresplash", - {"general.video"}, - {".spl"}, - {"application/futuresplash", "application/x-futuresplash"}, - "FutureSplash animation", - REFERENCE_URL, - ""}, - {"com.adobe.flash", - {"general.video"}, - {".swf", ".flv"}, - {"application/x-shockwave-flash", "video/x-flv"}, - "Shockwave flash movie", - REFERENCE_URL, - ""}, - {"org.gnu.texinfo", - {"general.source-code"}, - {".texinfo", ".texi"}, - {"application/x-texinfo"}, - "GNU Texinfo", - REFERENCE_URL, - ""}, - {"org.bittorrent.torrent", - {"general.text"}, - {".torrent"}, - {"application/x-bittorrent"}, - "BitTorrent file", - REFERENCE_URL, - ""}, - {"com.idsoftware.doom", - {"general.archive"}, - {".wad"}, - {"application/x-doom"}, - "Doom WAD file", - REFERENCE_URL, - ""}, - {"com.apple.webarchive", - {"general.archive"}, - {".webarchive"}, - {"application/x-webarchive"}, - "Safari web archive", - REFERENCE_URL, - ""}, - {"com.android.webarchive", - {"general.archive"}, - {".webarchivexml"}, - {"application/x-webarchive-xml"}, - "Android web browser archive", - REFERENCE_URL, - ""}, - {"org.gimp.xcf", - {"general.image"}, - {".xcf"}, - {"application/x-xcf", "image/x-xcf"}, - "eXperimental computing facility, GIMP image file", - REFERENCE_URL, - ""}, - {"com.edrawsoft.edrawmax", - {"general.composite-object"}, - {".eddx"}, - {"application/x-eddx"}, - "Edraw Max XML file", - REFERENCE_URL, - ""}, - {"com.edrawsoft.edrawmind", - {"general.composite-object"}, - {".emmx"}, - {"application/x-emmx"}, - "Edraw MindMaster XML file", - REFERENCE_URL, - ""}, - {"net.cnki.caj", - {"general.composite-object"}, - {".caj"}, - {"application/caj"}, - "Chinese academic journal file", - REFERENCE_URL, - ""}, - {"com.dbase.dbf", - {"general.database"}, - {".dbf"}, - {"application/dbf", "application/dbase"}, - "Database file", - REFERENCE_URL, - ""}, - {"com.autodesk.dwg", - {"general.composite-object"}, - {".dwg"}, - {"image/vnd.dwg"}, - "AutoCAD drawing", - REFERENCE_URL, - ""}, - {"com.autodesk.dxf", - {"general.composite-object"}, - {".dxf"}, - {"image/vnd.dxf"}, - "Drawing exchange format file", - REFERENCE_URL, - ""}, - {"com.autodesk.dws", - {"general.composite-object"}, - {".dws"}, - {}, - "AutoCAD drawing standards file", - REFERENCE_URL, - ""}, - {"com.autodesk.dwt", - {"general.composite-object"}, - {".dwt"}, - {}, - "AutoCAD drawing template", - REFERENCE_URL, - ""}, - {"com.autodesk.dwf", - {"general.composite-object"}, - {".dwf"}, - {"model/vnd.dwf"}, - "Design web format file", - REFERENCE_URL, - ""}, - {"com.autodesk.dwfx", - {"general.composite-object"}, - {".dwfx"}, - {}, - "Design web format XPS file", - REFERENCE_URL, - ""}, - {"com.autodesk.shp", - {"general.composite-object"}, - {".shp"}, - {}, - "3D studio shape", - REFERENCE_URL, - ""}, - {"com.autodesk.shx", - {"general.composite-object"}, - {".shx"}, - {}, - "AutoCAD compiled shape file", - REFERENCE_URL, - ""}, - {"com.autodesk.slide-library", - {"general.composite-object"}, - {".slb"}, - {}, - "AutoCAD slide library", - REFERENCE_URL, - ""}, - {"com.autodesk.line", - {"general.text"}, - {".lin"}, - {}, - "AutoCAD linetype file", - REFERENCE_URL, - ""}, - {"com.autodesk.plotter", - {"general.composite-object"}, - {".plt"}, - {}, - "AutoCAD plotter document", - REFERENCE_URL, - ""}, - {"com.hp.graphics-language", - {"general.composite-object"}, - {".hpgl"}, - {"application/vnd.hp-hpgl"}, - "HP graphics language plotter file", - REFERENCE_URL, - ""}, - {"com.microsoft.metafile", - {"general.composite-object"}, - {".wmf"}, - {}, - "Windows metafile", - REFERENCE_URL, - ""}, - {"com.spatial.acis.sat", - {"general.text"}, - {".sat"}, - {}, - "ACIS SAT 3D model", - REFERENCE_URL, - ""}, - {"org.aomedia.avif-image", - {"general.image"}, - {".avif"}, - {"image/avif"}, - "AVIF image", - REFERENCE_URL, - ""}, - {"com.microsoft.dds", - {"general.image"}, - {".dds"}, - {"image/vnd-ms.dds"}, - "DirectDraw surface image", - REFERENCE_URL, - ""}, - {"com.ea.iff-ilbm", - {"general.image"}, - {".ilbm"}, - {"image/x-ilbm"}, - "Interleaved bitmap image", - REFERENCE_URL, - ""}, - {"com.canon.cr2-raw-image", - {"general.raw-image"}, - {".cr2"}, - {"image/x-canon-cr2"}, - "Canon raw 2 image", - REFERENCE_URL, - ""}, - {"com.canon.cr3-raw-image", - {"general.raw-image"}, - {".cr3"}, - {"image/x-canon-cr3"}, - "Canon raw 3 image", - REFERENCE_URL, - ""}, - {"com.canon.crw-raw-image", - {"general.raw-image"}, - {".crw"}, - {"image/x-canon-crw"}, - "Canon raw CIFF image file", - REFERENCE_URL, - ""}, - {"com.adobe.dng-raw-image", - {"general.raw-image"}, - {".dng"}, - {"image/x-adobe-dng"}, - "Digital negative image", - REFERENCE_URL, - ""}, - {"com.sony.arw-raw-image", - {"general.raw-image"}, - {".arw"}, - {"image/x-sony-arw"}, - "Sony alpha raw digital camera image", - REFERENCE_URL, - ""}, - {"com.nikon.nef-raw-image", - {"general.raw-image"}, - {".nef"}, - {"image/x-nikon-nef"}, - "Nikon electronic format RAW image", - REFERENCE_URL, - ""}, - {"com.mindjet.mindmanager.mmap", - {"general.composite-object"}, - {".mmap"}, - {}, - "MindManager Map", - REFERENCE_URL, - ""}, - {"com.microsoft.email", - {"general.message"}, - {".eml"}, - {"message/rfc822"}, - "E-Mail message", - REFERENCE_URL, - ""}, - {"com.microsoft.message", - {"general.message"}, - {".msg"}, - {}, - "Outlook message item file", - REFERENCE_URL, - ""}, - {"com.microsoft.pst", - {"general.archive"}, - {".pst"}, - {}, - "Outlook personal information store", - REFERENCE_URL, - ""}, - {"com.kingsoft.office", - {"general.archive"}, - {}, - {}, - "Kingsoft office suite", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.writer.wps", - {"com.kingsoft.office", "general.composite-object"}, - {".wps"}, - {}, - "Kingsoft Writer document", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.writer.wpt", - {"com.kingsoft.office", "general.composite-object"}, - {".wpt"}, - {}, - "Kingsoft Writer template", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.presentation.dps", - {"com.kingsoft.office", "general.composite-object"}, - {".dps"}, - {}, - "Kingsoft Presentation file", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.presentation.template", - {"com.kingsoft.office", "general.composite-object"}, - {".dpt"}, - {}, - "Kingsoft Presentation template", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.spreadsheets.et", - {"com.kingsoft.office", "general.composite-object"}, - {".et"}, - {}, - "Kingsoft Spreadsheets tile", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.spreadsheets.template", - {"com.kingsoft.office", "general.composite-object"}, - {".ett"}, - {}, - "Kingsoft Spreadsheets template", - REFERENCE_URL, - ""}, - {"com.microsoft.ini", - {"general.text"}, - {".ini"}, - {}, - "Windows Initialization File", - REFERENCE_URL, - ""}, - {"general.json", - {"general.script"}, - {".json"}, - {"application/json"}, - "JavaScript Object Notation File", - REFERENCE_URL, - ""}, - {"general.yaml", - {"general.script"}, - {".yaml", ".yml"}, - {"application/yaml"}, - "YAML Document", - REFERENCE_URL, - ""}, - {"general.log", - {"general.text"}, - {".log"}, - {"text/plain"}, - "Log File", - REFERENCE_URL, - ""}, - {"general.uri", - {"general.object"}, - {}, - {}, - "Universal Resource Identifier", - REFERENCE_URL, - ""}, - {"general.file-uri", - {"general.uri"}, - {}, - {}, - "File URI", - REFERENCE_URL, - ""}, - {"general.text-lst", - {"general.plain-text"}, - {".lst"}, - {}, - "Data List", - REFERENCE_URL, - ""}, - {"com.android.apk", - {"general.archive"}, - {".apk", ".apks", ".aab", ".xapk", ".apkm", ".akp"}, - {"application/vnd.android.package-archive"}, - "Android Package File", - REFERENCE_URL, - ""}, - {"com.adobe.postscript-pfb-font", - {"com.adobe.postscript-font"}, - {".pfb"}, - {"application/x-font"}, - "Printer Font Binary, PostScript Type 1 outline font.", - REFERENCE_URL, - ""}, - {"com.adobe.postscript-pfa-font", - {"com.adobe.postscript-font"}, - {".pfa"}, - {"application/x-font"}, - "Printer Pont ASCII file, PostScript Type 1 outline font.", - REFERENCE_URL, - ""}, - {"general.bz-archive", - {"general.archive"}, - {".bz"}, - {"application/x-bzip"}, - "Bzip Compressed File", - REFERENCE_URL, - ""}, - {"general.tar-bzip-archive", - {"general.bz-archive"}, - {".tbz"}, - {"application/x-bzip-compressed-tar"}, - "Bzip Compressed Tar Archive", - REFERENCE_URL, - ""}, - {"general.tar-bzip2-archive", - {"general.bz2-archive"}, - {".tbz2"}, - {"application/x-bzip2-compressed-tar"}, - "Bzip2-Compressed TAR File", - REFERENCE_URL, - ""}, - {"org.tukaani.xz-archive", - {"general.archive"}, - {".xz"}, - {"application/x-xz"}, - "XZ Compressed Archive", - REFERENCE_URL, - ""}, - {"org.tukaani.tar-xz-archive", - {"org.tukaani.xz-archive"}, - {".txz"}, - {"application/x-xz-compressed-tar"}, - "XZ Compressed Tar Archive", - REFERENCE_URL, - ""}, - {"general.xar-archive", - {"general.archive"}, - {".xar"}, - {"application/x-xar"}, - "Extensible Archive Fromat", - REFERENCE_URL, - ""}, - {"com.microsoft.cab-archive", - {"general.archive"}, - {".cab"}, - {"application/vnd.ms-cab-compressed"}, - "Windows Cabinet File", - REFERENCE_URL, - ""}, - {"redhat.rpm-archive", - {"general.archive"}, - {".rpm"}, - {"application/x-rpm"}, - "RedHat Package Manager File", - REFERENCE_URL, - ""}, - {"org.godotengine.tpz-archive", - {"general.archive"}, - {".tpz"}, - {}, - "Godot Engine Export Template Archive", - REFERENCE_URL, - ""}, - {"general.lza-archive", - {"general.archive"}, - {".lza"}, - {"application/x-lzh-compressed"}, - "LZA Compressed Archive", - REFERENCE_URL, - ""}, - {"general.arj-archive", - {"general.archive"}, - {".arj"}, - {"application/x-arj"}, - "ARJ Compressed File Archive", - REFERENCE_URL, - ""}, - {"com.winzip.zipx", - {"general.archive"}, - {".zipx"}, - {}, - "Extended Zip Archive", - REFERENCE_URL, - ""}, - {"general.lzma-archive", - {"general.archive"}, - {".lzma"}, - {"application/x-lzma"}, - "LZMA Compressed File", - REFERENCE_URL, - ""}, - {"general.lzma86-archive", - {"general.archive"}, - {".lzma86"}, - {}, - "LZMA86 Compressed File", - REFERENCE_URL, - ""}, - {"org.mozilla.xpinstall", - {"general.archive"}, - {".xpi"}, - {"application/x-xpinstall"}, - "Cross-platform Installer Package", - REFERENCE_URL, - ""}, - {"general.hfs-disk-image", - {"general.disk-image"}, - {".hfs"}, - {}, - "HFS Disk Image File", - REFERENCE_URL, - ""}, - {"general.img-disk-image", - {"general.disk-image"}, - {".img"}, - {"application/x-raw-disk-image"}, - "Disc Image Data File", - REFERENCE_URL, - ""}, - {"com.ezbsystems.zipped-iso", - {"general.disk-image"}, - {".isz"}, - {}, - "Zipped ISO Disk Image", - REFERENCE_URL, - ""}, - {"com.microsoft.wim", - {"general.disk-image"}, - {".wim"}, - {"application/x-ms-wim"}, - "Windows Imaging Format File", - REFERENCE_URL, - ""}, - {"com.microsoft.swm", - {"general.disk-image"}, - {".swm"}, - {"application/x-ms-wim"}, - "Split Windows Imaging Format", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.spreadsheets.etx", - {"com.kingsoft.office", "general.composite-object"}, - {".etx"}, - {}, - "Kingsoft Spreadsheets File", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.spreadsheets.ettx", - {"com.kingsoft.office", "general.composite-object"}, - {".ettx"}, - {}, - "Kingsoft Spreadsheets Template", - REFERENCE_URL, - ""}, - {"com.microsoft.excel.dif", - {"general.composite-object"}, - {".dif"}, - {}, - "Data interchange format", - REFERENCE_URL, - ""}, - {"openharmony.app", - {"openharmony.package"}, - {".app"}, - {}, - "OpenHarmony system defined application package", - REFERENCE_URL, - ""}, - {"com.huawei.hmos.settings.wifi", - {"general.text"}, - {".hmoswifi"}, - {}, - "HarmonyOS WIFI sharing setting", - REFERENCE_URL, - ""}, - {"general.tel", - {"general.text"}, - {".tel"}, - {}, - "TEL schematic diagram file format", - REFERENCE_URL, - ""}, - {"general.ets", - {"general.script"}, - {".ets"}, - {}, - "Extended TypeScript source code", - REFERENCE_URL, - ""}, - {"general.json5", - {"general.script"}, - {".json5"}, - {}, - "JSON5 data interchange format", - REFERENCE_URL, - ""}, - {"com.monkeysaudio.ape-audio", - {"general.audio"}, - {".ape"}, - {"audio/x-monkeys-audio"}, - "Monkey's Audio", - REFERENCE_URL, - ""}, - {"org.xiph.opus-audio", - {"general.audio"}, - {".opus"}, - {"audio/opus"}, - "Opus Audio", - REFERENCE_URL, - ""}, - {"general.conf", - {"general.text"}, - {".conf"}, - {}, - "Generic Configuration File", - REFERENCE_URL, - ""}, - {"com.microsoft.dos-batch", - {"general.script"}, - {".bat"}, - {"application/x-bat"}, - "DOS Batch File", - REFERENCE_URL, - ""}, - {"com.microsoft.vbscript", - {"general.script"}, - {".vbs"}, - {"application/x-vbs"}, - "VBScript File", - REFERENCE_URL, - ""}, - {"general.ion", - {"general.text"}, - {".ion"}, - {}, - "File Description File", - REFERENCE_URL, - ""}, - {"com.microsoft.registry", - {"general.database"}, - {".reg"}, - {}, - "Registry File", - REFERENCE_URL, - ""}, - {"com.microsoft.catalog", - {"general.object"}, - {".cat"}, - {}, - "Windows Catalog File", - REFERENCE_URL, - ""}, - {"com.microsoft.powershell-script", - {"general.script"}, - {".ps1"}, - {}, - "Windows PowerShell Cmdlet File", - REFERENCE_URL, - ""}, - {"org.w3.woff", - {"general.font"}, - {".woff"}, - {"font/woff"}, - "Web Open Font Format File", - REFERENCE_URL, - ""}, - {"org.sqlite.database", - {"general.database"}, - {".sqlite", ".sqlite3", ".db", ".db3", ".s3db", ".sl3"}, - {"application/vnd.sqlite3"}, - "SQLite Database", - REFERENCE_URL, - ""}, - {"com.microsoft.sys", - {"general.object"}, - {".sys"}, - {}, - "Windows System File", - REFERENCE_URL, - ""}, - {"com.microsoft.inf", - {"general.text"}, - {".inf"}, - {"text/plain"}, - "Setup Information File", - REFERENCE_URL, - ""}, - {"com.microsoft.pdb", - {"general.database"}, - {".pdb"}, - {"application/x-ms-pdb"}, - "Program Database", - REFERENCE_URL, - ""}, - {"com.microsoft.tlb", - {"general.object"}, - {".tlb"}, - {}, - "OLE Type Library", - REFERENCE_URL, - ""}, - {"com.microsoft.sccd", - {"general.xml"}, - {".sccd"}, - {}, - "Signed Custom Capability Descriptor", - REFERENCE_URL, - ""}, - {"com.adobe.f4v", - {"general.video"}, - {".f4v"}, - {"video/mp4"}, - "Flash MP4 Video File", - REFERENCE_URL, - ""}, - {"general.mp2t", - {"general.video"}, - {".m2ts", ".mts", ".m2t"}, - {"video/mp2t"}, - "Blu-ray BDAV Video File Format", - REFERENCE_URL, - ""}, - {"com.youtube.video", - {"general.video"}, - {".yt", ".vt"}, - {"video/vnd.youtube.yt"}, - "Youtube Video format", - REFERENCE_URL, - ""}, - {"com.cisco.webex-video", - {"general.video"}, - {".wrf"}, - {"video/x-webex"}, - "WebEx Recording", - REFERENCE_URL, - ""}, - {"general.mpeg-2", - {"general.video"}, - {".mpeg2", ".mpv2", ".mp2v", ".m2v", ".mpv"}, - {"video/mpeg"}, - "MPEG-2 Video format", - REFERENCE_URL, - ""}, - {"general.mpeg-1", - {"general.video"}, - {".mpeg1", ".mpv1", ".mp1v", ".m1v"}, - {"video/mpeg"}, - "MPEG-1 Video format", - REFERENCE_URL, - ""}, - {"com.real.realmedia-vbr", - {"general.video"}, - {".rmvb"}, - {"application/vnd.rn-realmedia-vbr"}, - "RealMedia Variable Bit Rate Format", - REFERENCE_URL, - ""}, - {"com.real.realvideo", - {"general.video"}, - {".rv"}, - {"video/x-pn-realvideo"}, - "RealVideo Format", - REFERENCE_URL, - ""}, - {"general.divx-video", - {"general.video"}, - {".divx"}, - {"video/divx"}, - "DivX-Encoded Movie", - REFERENCE_URL, - ""}, - {"org.csiro.annodex", - {"general.video"}, - {".axv"}, - {"video/annodex"}, - "Annodex Video Format", - REFERENCE_URL, - ""}, - {"general.ogv", - {"general.video"}, - {".ogv"}, - {"video/ogg"}, - "Ogg Video Format", - REFERENCE_URL, - ""}, - {"com.microsoft.lsf-video", - {"general.video"}, - {".lsf", ".lsx"}, - {"video/x-la-asf"}, - "Streaming Media Format", - REFERENCE_URL, - ""}, - {"general.h264-video", - {"general.video"}, - {".h264"}, - {"video/H264"}, - "H.264 Encoded Video Format", - REFERENCE_URL, - ""}, - {"general.jpeg-2000", - {"general.image"}, - {".jp2", ".jpg2", ".jpx", ".jpf", ".jpm"}, - {"image/jp2", "image/jpx", "image/jpm"}, - "JPEG 2000 Image", - REFERENCE_URL, - ""}, - {"com.fujifilm.raf-raw-image", - {"general.raw-image"}, - {".raf"}, - {"image/x-fuji-raf"}, - "Fujifilm RAW Image", - REFERENCE_URL, - ""}, - {"com.nikon.nrw-raw-image", - {"general.raw-image"}, - {".nrw"}, - {"image/x-nikon-nrw"}, - "Nikon Raw Image", - REFERENCE_URL, - ""}, - {"com.panasonic.rw2-raw-image", - {"general.raw-image"}, - {".rw2", ".raw"}, - {"image/x-panasonic-raw"}, - "Panasonic RAW Image", - REFERENCE_URL, - ""}, - {"com.pentax.pef-raw-image", - {"general.raw-image"}, - {".pef"}, - {"image/x-pentax-pef"}, - "Pentax Electronic RAW Image", - REFERENCE_URL, - ""}, - {"com.sumsung.srw-raw-image", - {"general.raw-image"}, - {".srw"}, - {"image/x-samsung-srw"}, - "Samsung RAW Image", - REFERENCE_URL, - ""}, - {"com.epson.erf-raw-image", - {"general.raw-image"}, - {".erf"}, - {"image/x-epson-erf"}, - "Epson RAW Imager", - REFERENCE_URL, - ""}, - {"com.olympus.orf-raw-image", - {"general.raw-image"}, - {".orf"}, - {"image/x-olympus-orf"}, - "Olympus RAW Image", - REFERENCE_URL, - ""}, - {"general.ief-image", - {"general.image"}, - {".ief"}, - {"image/ief"}, - "Image Exchange Format", - REFERENCE_URL, - ""}, - {"com.aol.art-image", - {"general.image"}, - {".art"}, - {"image/x-jg"}, - "ART image format", - REFERENCE_URL, - ""}, - {"general.content-form", - {"general.object"}, - {}, - {}, - "Content form format", - REFERENCE_URL, - ""}, - {"com.apple.m4p-audio", - {"general.audio"}, - {".m4p"}, - {"audio/mp4"}, - "iTunes Music Store Audio File Format", - REFERENCE_URL, - ""}, - {"general.ac3-audio", - {"general.audio"}, - {".ac3"}, - {"audio/ac3"}, - "Audio Codec 3 File Format", - REFERENCE_URL, - ""}, - {"openharmony.hsp", - {"openharmony.package"}, - {".hsp"}, - {}, - "Harmony Shared Package", - REFERENCE_URL, - ""}, - {"openharmony.har", - {"openharmony.package"}, - {".har"}, - {}, - "Harmony Archive", - REFERENCE_URL, - ""}, - {"openharmony.gopaint", - {"general.archive"}, - {".gopaint"}, - {}, - "Gopaint file format defined for Openharmony", - REFERENCE_URL, - ""}, - {"openharmony.gobrush", - {"general.archive"}, - {".gobrush"}, - {}, - "Gobrush file format defined for Openharmony", - REFERENCE_URL, - ""}, - {"openharmony.gobrushes", - {"general.archive"}, - {".gobrushes"}, - {}, - "Gobrushes file format defined for Openharmony", - REFERENCE_URL, - ""}, - {"openharmony.gocolor", - {"general.archive"}, - {".gocolor"}, - {}, - "Gocolor file format defined for Openharmony", - REFERENCE_URL, - ""} - }; + if (!typeDescriptors_.empty()) { + LOG_INFO(UDMF_CLIENT, "Preset type descriptors already init, utd size is %{public}zu", + typeDescriptors_.size()); + return; + } + std::ifstream fin(std::string(UTD_CONF_PATH) + std::string(UNIFORM_DATA_TYPES_JSON_PATH)); + if (!fin.good()) { + LOG_ERROR(UDMF_CLIENT, "Failed to open uniform data types json file"); + return; + } + std::ostringstream oss; + std::string line; + while (std::getline(fin, line)) { + oss << line; + } + fin.close(); + CustomUtdJsonParser utdJsonParser; + cJSON* jsonRoot = cJSON_Parse(oss.str().c_str()); + if (jsonRoot != NULL && cJSON_IsObject(jsonRoot)) { + std::lock_guard<std::recursive_mutex> lock(mutex_); + if (!typeDescriptors_.empty()) { + LOG_INFO(UDMF_CLIENT, "Preset type descriptors already init, utd size is %{public}zu", + typeDescriptors_.size()); + cJSON_Delete(jsonRoot); + return; + } + utdJsonParser.GetTypeDescriptors(*jsonRoot, UTD_CUSTOM_DECLARATION, typeDescriptors_); + } + cJSON_Delete(jsonRoot); + LOG_INFO(UDMF_CLIENT, "Preset type descriptors init success, utd size is %{public}zu", typeDescriptors_.size()); }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/preset_type_descriptors.h b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.h index 6a57164c0df93d1d14b9de797a028f82f0c3ff00..546d03c4f43f771de89ff0e1f3727d4aa67c08b9 100644 --- a/udmf/framework/innerkitsimpl/data/preset_type_descriptors.h +++ b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.h @@ -15,6 +15,7 @@ #ifndef UDMF_PRESET_TYPE_DESCRIPTORS #define UDMF_PRESET_TYPE_DESCRIPTORS #include <string> +#include <mutex> #include "error_code.h" #include "utd_common.h" #include "visibility.h" @@ -30,7 +31,8 @@ private: PresetTypeDescriptors(const PresetTypeDescriptors &obj) = delete; PresetTypeDescriptors &operator=(const PresetTypeDescriptors &obj) = delete; void InitDescriptors(); - std::vector<TypeDescriptorCfg> typeDescriptors_; + std::vector<TypeDescriptorCfg> typeDescriptors_ {}; + mutable std::recursive_mutex mutex_; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/system_defined_appitem.cpp b/udmf/framework/innerkitsimpl/data/system_defined_appitem.cpp index 2aea430c306f23159105193c9d81f453359b1122..9bda129455057c97bda7b1fe5048ce06f9f60b44 100644 --- a/udmf/framework/innerkitsimpl/data/system_defined_appitem.cpp +++ b/udmf/framework/innerkitsimpl/data/system_defined_appitem.cpp @@ -37,7 +37,6 @@ SystemDefinedAppItem::SystemDefinedAppItem(UDType type, ValueType value) : Syste if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); } - hasObject_ = true; } } diff --git a/udmf/framework/innerkitsimpl/data/system_defined_form.cpp b/udmf/framework/innerkitsimpl/data/system_defined_form.cpp index d7d3c382746851455eceee7719a0bca507a705f7..0c7f5c6978f4bcc6243f51b4558b38ed77c6eb61 100644 --- a/udmf/framework/innerkitsimpl/data/system_defined_form.cpp +++ b/udmf/framework/innerkitsimpl/data/system_defined_form.cpp @@ -36,7 +36,6 @@ SystemDefinedForm::SystemDefinedForm(UDType type, ValueType value) : SystemDefin if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); } - hasObject_ = true; } } diff --git a/udmf/framework/innerkitsimpl/data/system_defined_pixelmap.cpp b/udmf/framework/innerkitsimpl/data/system_defined_pixelmap.cpp index e98789dff3748ecc12519d834db78b3531952b20..7f8cb41980ccecc045032cdf99260c89c68b113d 100644 --- a/udmf/framework/innerkitsimpl/data/system_defined_pixelmap.cpp +++ b/udmf/framework/innerkitsimpl/data/system_defined_pixelmap.cpp @@ -16,9 +16,15 @@ #include "system_defined_pixelmap.h" #include "logger.h" +#include "pixelmap_loader.h" namespace OHOS { namespace UDMF { +static constexpr size_t BYTES_PER_COLOR = sizeof(uint32_t); +static constexpr const char* PIXEL_MAP_WIDTH = "width"; +static constexpr const char* PIXEL_MAP_HEIGHT = "height"; +static constexpr const char* PIXEL_MAP_FORMAT = "pixel-format"; +static constexpr const char* PIXEL_MAP_ALPHA_TYPE = "alpha-type"; SystemDefinedPixelMap::SystemDefinedPixelMap() { SetType(SYSTEM_DEFINED_PIXEL_MAP); @@ -38,21 +44,16 @@ SystemDefinedPixelMap::SystemDefinedPixelMap(UDType type, ValueType value) : Sys return; } else if (std::holds_alternative<std::shared_ptr<OHOS::Media::PixelMap>>(value)) { auto pixelMap = std::get<std::shared_ptr<OHOS::Media::PixelMap>>(value); - if (!pixelMap->EncodeTlv(rawData_)) { - LOG_ERROR(UDMF_KITS_INNER, "pixelMap encode fail!"); - } + ParseInfoFromPixelMap(pixelMap); } else if (std::holds_alternative<std::shared_ptr<Object>>(value)) { auto object = std::get<std::shared_ptr<Object>>(value); auto it = object->value_.find(PIXEL_MAP); - hasObject_ = true; if (it == object->value_.end()) { return; } if (std::holds_alternative<std::shared_ptr<OHOS::Media::PixelMap>>(it->second)) { auto pixelMap = std::get<std::shared_ptr<OHOS::Media::PixelMap>>(it->second); - if (!pixelMap->EncodeTlv(rawData_)) { - LOG_ERROR(UDMF_KITS_INNER, "pixelMap encode fail!"); - } + ParseInfoFromPixelMap(pixelMap); } else if (std::holds_alternative<std::vector<uint8_t>>(it->second)) { rawData_ = std::get<std::vector<uint8_t>>(it->second); } @@ -75,9 +76,9 @@ void SystemDefinedPixelMap::SetRawData(const std::vector<uint8_t> &rawData) this->rawData_ = rawData; if (std::holds_alternative<std::shared_ptr<Object>>(value_)) { auto object = std::get<std::shared_ptr<Object>>(value_); - auto pixelMap = std::shared_ptr<OHOS::Media::PixelMap>(OHOS::Media::PixelMap::DecodeTlv(rawData_)); + auto pixelMap = GetPixelMapFromRawData(); if (pixelMap == nullptr) { - LOG_ERROR(UDMF_KITS_INNER, "pixelMap decode fail!"); + LOG_ERROR(UDMF_KITS_INNER, "Get pixelMap from rawData fail!"); object->value_[PIXEL_MAP] = rawData; return; } @@ -91,9 +92,9 @@ void SystemDefinedPixelMap::InitObject() auto value = value_; value_ = std::make_shared<Object>(); auto object = std::get<std::shared_ptr<Object>>(value_); - auto pixelMap = std::shared_ptr<OHOS::Media::PixelMap>(OHOS::Media::PixelMap::DecodeTlv(rawData_)); + auto pixelMap = GetPixelMapFromRawData(); if (pixelMap == nullptr) { - LOG_ERROR(UDMF_KITS_INNER, "pixelMap decode fail!"); + LOG_WARN(UDMF_KITS_INNER, "Get pixelMap from rawData fail!"); object->value_[PIXEL_MAP] = rawData_; } else { object->value_[PIXEL_MAP] = pixelMap; @@ -103,5 +104,53 @@ void SystemDefinedPixelMap::InitObject() object->value_.insert_or_assign(VALUE_TYPE, std::move(value)); } } + +std::shared_ptr<OHOS::Media::PixelMap> SystemDefinedPixelMap::GetPixelMapFromRawData() +{ + if (rawData_.empty()) { + LOG_WARN(UDMF_KITS_INNER, "No RawData"); + return nullptr; + } + if (rawData_.size() % BYTES_PER_COLOR != 0) { + LOG_ERROR(UDMF_KITS_INNER, "RawData size error, size = %{public}zu", rawData_.size()); + return nullptr; + } + auto details = ObjectUtils::ConvertToObject(details_); + if (details == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "No details"); + return nullptr; + } + PixelMapDetails pixelMapDetails; + pixelMapDetails.rawData = std::ref(rawData_); + pixelMapDetails.width = details->GetValue(PIXEL_MAP_WIDTH, pixelMapDetails.width) ? pixelMapDetails.width : -1; + pixelMapDetails.height = details->GetValue(PIXEL_MAP_HEIGHT, pixelMapDetails.height) ? pixelMapDetails.height : -1; + pixelMapDetails.pixelFormat = details->GetValue(PIXEL_MAP_FORMAT, pixelMapDetails.pixelFormat) + ? pixelMapDetails.pixelFormat : static_cast<int32_t>(OHOS::Media::PixelFormat::UNKNOWN); + PixelMapLoader loader; + return loader.GetPixelMapFromRawData(pixelMapDetails); +} + +void SystemDefinedPixelMap::ParseInfoFromPixelMap(std::shared_ptr<OHOS::Media::PixelMap> pixelMap) +{ + if (pixelMap == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "PixelMap is null"); + return; + } + PixelMapLoader loader; + auto details = loader.ParseInfoFromPixelMap(pixelMap); + if (details == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "Parse info failed"); + return; + } + details_[PIXEL_MAP_WIDTH] = details->width; + details_[PIXEL_MAP_HEIGHT] = details->height; + details_[PIXEL_MAP_FORMAT] = details->pixelFormat; + details_[PIXEL_MAP_ALPHA_TYPE] = details->alphaType; + if (!details->rawDataResult.has_value()) { + LOG_ERROR(UDMF_KITS_INNER, "No rawData"); + return; + } + rawData_ = std::move(*details->rawDataResult); +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/system_defined_record.cpp b/udmf/framework/innerkitsimpl/data/system_defined_record.cpp index 4da832b8026fb4152a5fe6f6b9a8999d3567dfc1..31f3345217eb1955238ce2d650233bacee6eff31 100644 --- a/udmf/framework/innerkitsimpl/data/system_defined_record.cpp +++ b/udmf/framework/innerkitsimpl/data/system_defined_record.cpp @@ -35,7 +35,6 @@ SystemDefinedRecord::SystemDefinedRecord(UDType type, ValueType value) : Unified if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); } - hasObject_ = true; } } diff --git a/udmf/framework/innerkitsimpl/data/text.cpp b/udmf/framework/innerkitsimpl/data/text.cpp index 55323253b2f4395ac9c995d171079a444a1657de..9554e06dd63c656e38f67b817d230c17e3790d13 100644 --- a/udmf/framework/innerkitsimpl/data/text.cpp +++ b/udmf/framework/innerkitsimpl/data/text.cpp @@ -35,7 +35,6 @@ Text::Text(UDType type, ValueType value) : UnifiedRecord(type, value) if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); } - hasObject_ = true; } } diff --git a/udmf/framework/innerkitsimpl/data/type_descriptor.cpp b/udmf/framework/innerkitsimpl/data/type_descriptor.cpp index 64f488bd71bafc866ec2cb4a248838a700d0ce80..19dffbf0484f10e7a823f3b69291a208655a13f9 100644 --- a/udmf/framework/innerkitsimpl/data/type_descriptor.cpp +++ b/udmf/framework/innerkitsimpl/data/type_descriptor.cpp @@ -59,33 +59,27 @@ bool TypeDescriptor::CmpFlexibleTypeLevel(const std::string higherLevelTypeId, b } } } - LOG_INFO(UDMF_CLIENT, "The current utd[%{public}s] belongings is not belong[] %{public}s,", - typeId_.c_str(), higherLevelTypeId.c_str()); return false; } Status TypeDescriptor::BelongsTo(const std::string &typeId, bool &checkResult) { + if (typeId_ == typeId) { + checkResult = true; + return Status::E_OK; + }; checkResult = false; bool isFlexibleType = typeId.find(FLEXIBLE_TYPE_FLAG) != typeId_.npos; if (!UtdGraph::GetInstance().IsValidType(typeId) && !isFlexibleType) { - LOG_ERROR(UDMF_CLIENT, "invalid para. %{public}s,", typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid para"); return Status::E_INVALID_PARAMETERS; } if (isFlexibleType_) { - if (typeId_ == typeId) { - checkResult = true; - return Status::E_OK; - }; checkResult = CmpFlexibleTypeLevel(typeId, isFlexibleType); return Status::E_OK; } - if (typeId_ == typeId) { - checkResult = true; - return Status::E_OK; - }; checkResult = UtdGraph::GetInstance().IsLowerLevelType(typeId, typeId_); return Status::E_OK; } @@ -95,7 +89,7 @@ Status TypeDescriptor::IsLowerLevelType(const std::string &typeId, bool &checkRe checkResult = false; bool isFlexibleType = typeId.find(FLEXIBLE_TYPE_FLAG) != typeId_.npos; if (!UtdGraph::GetInstance().IsValidType(typeId) && !isFlexibleType) { - LOG_ERROR(UDMF_CLIENT, "invalid para. %{public}s,", typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid para"); return Status::E_INVALID_PARAMETERS; } if (isFlexibleType_) { @@ -115,7 +109,7 @@ Status TypeDescriptor::IsHigherLevelType(const std::string &typeId, bool &checkR checkResult = false; bool isFlexibleType = typeId.find(FLEXIBLE_TYPE_FLAG) != typeId_.npos; if (!UtdGraph::GetInstance().IsValidType(typeId) && !isFlexibleType) { - LOG_ERROR(UDMF_CLIENT, "invalid para. %{public}s,", typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid para"); return Status::E_INVALID_PARAMETERS; } if (isFlexibleType_) { // flexibleType cannot be other type height level. diff --git a/udmf/framework/innerkitsimpl/data/unified_data.cpp b/udmf/framework/innerkitsimpl/data/unified_data.cpp index 77b50133cea60fee546805217dfc1ca5e6b75b99..eaa09096aedb669b3b1d6fd35688488731cc47f1 100644 --- a/udmf/framework/innerkitsimpl/data/unified_data.cpp +++ b/udmf/framework/innerkitsimpl/data/unified_data.cpp @@ -14,7 +14,6 @@ */ #define LOG_TAG "UnifiedData" #include "logger.h" -#include "udmf_utils.h" #include "unified_data.h" #include "utd_client.h" @@ -22,15 +21,12 @@ namespace OHOS { namespace UDMF { static const std::set<std::string> FILE_TYPES = { "general.file", "general.image", "general.video", "general.audio", "general.folder", "general.file-uri" }; -static const std::set<std::string> FILE_SUB_TYPES = { - "general.image", "general.video", "general.audio", "general.folder" }; static constexpr const char *RECORDS_TANSFER_TAG = "records_to_entries_data_format"; UnifiedData::UnifiedData() { properties_ = std::make_shared<UnifiedDataProperties>(); auto duration = std::chrono::system_clock::now().time_since_epoch(); properties_->timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); - sdkVersion_ = UTILS::GetCurrentSdkVersion(); } UnifiedData::UnifiedData(std::shared_ptr<UnifiedDataProperties> properties) @@ -42,7 +38,6 @@ UnifiedData::UnifiedData(std::shared_ptr<UnifiedDataProperties> properties) properties_ = properties; auto duration = std::chrono::system_clock::now().time_since_epoch(); properties_->timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); - sdkVersion_ = UTILS::GetCurrentSdkVersion(); } int64_t UnifiedData::GetSize() @@ -113,9 +108,7 @@ std::vector<std::string> UnifiedData::GetTypesLabels() const { std::vector<std::string> types; for (const std::shared_ptr<UnifiedRecord> &record : records_) { - std::vector<std::string> recordTypes = record->GetTypes(); - types.insert(types.end(), - std::make_move_iterator(recordTypes.begin()), std::make_move_iterator(recordTypes.end())); + types.push_back(UtdUtils::GetUtdIdFromUtdEnum(record->GetType())); } return types; } @@ -137,8 +130,7 @@ bool UnifiedData::HasHigherFileType(const std::string &type) const if (types.find(type) != types.end()) { return true; } - auto subTypesIter = FILE_SUB_TYPES.find(type); - if (subTypesIter == FILE_SUB_TYPES.end()) { + if (!UnifiedDataUtils::IsFilterFileType(type)) { return false; } for (auto it = types.begin(); it != types.end(); ++it) { @@ -278,7 +270,7 @@ std::set<std::string> UnifiedData::GetTypIds() const { std::set<std::string> types; for (const auto &record : records_) { - std::set<std::string> recordTypes = record->GetUtdIds(); + std::set<std::string> recordTypes = record->GetUtdIdsWithAddFileType(true); types.insert(recordTypes.begin(), recordTypes.end()); } return types; @@ -308,9 +300,9 @@ bool UnifiedData::IsNeedTransferToEntries() const return properties_->tag == RECORDS_TANSFER_TAG; } -void UnifiedData::TransferToEntries(UnifiedData &data) +void UnifiedData::ConvertRecordsToEntries() { - if (records_.size() <= 1) { + if (!IsNeedTransferToEntries()) { return; } std::shared_ptr<UnifiedRecord> recordFirst = records_[0]; @@ -323,10 +315,14 @@ void UnifiedData::TransferToEntries(UnifiedData &data) if (record == nullptr) { continue; } + if (record->GetUtdId2() == recordFirst->GetUtdId2()) { + continue; + } record->InitObject(); - recordFirst->AddEntry(record->GetUtdId(), record->GetValue()); + recordFirst->AddEntry(record->GetUtdId2(), record->GetValue()); } records_.erase(records_.begin() + 1, records_.end()); + LOG_INFO(UDMF_FRAMEWORK, "Convert records to entries finished"); } std::string UnifiedData::GetSdkVersion() const diff --git a/udmf/framework/innerkitsimpl/data/unified_data_helper.cpp b/udmf/framework/innerkitsimpl/data/unified_data_helper.cpp index 204127b27d81ec7b93206cb7c0fa4be0bf9c4b5f..2d804abc4010f241057c7bc053cfed78c5dd9936 100644 --- a/udmf/framework/innerkitsimpl/data/unified_data_helper.cpp +++ b/udmf/framework/innerkitsimpl/data/unified_data_helper.cpp @@ -26,6 +26,7 @@ #include "udmf_conversion.h" #include "udmf_meta.h" #include "udmf_utils.h" +#include "utd_client.h" namespace OHOS { namespace UDMF { @@ -36,7 +37,7 @@ static constexpr int64_t MAX_SA_DRAG_RECORD_SIZE = 15 * 1024 * 1024 + 512 * 102 constexpr const char *TEMP_UNIFIED_DATA_ROOT_PATH = "data/storage/el2/base/temp/udata"; constexpr const char *TEMP_UNIFIED_DATA_SUFFIX = ".ud"; constexpr const char *TEMP_UNIFIED_DATA_FLAG = "temp_udmf_file_flag"; - +static constexpr int WITH_SUMMARY_FORMAT_VER = 1; std::string UnifiedDataHelper::rootPath_ = ""; void UnifiedDataHelper::SetRootPath(const std::string &rootPath) @@ -88,13 +89,12 @@ void UnifiedDataHelper::CreateDirIfNotExist(const std::string& dirPath, const mo { if (OHOS::FileExists(dirPath)) { if (!OHOS::ForceRemoveDirectory(dirPath)) { - LOG_ERROR(UDMF_FRAMEWORK, "remove dir %{public}s failed, errno: %{public}d.", dirPath.c_str(), errno); + LOG_ERROR(UDMF_FRAMEWORK, "remove dir failed, errno: %{public}d.", errno); } } - LOG_DEBUG(UDMF_FRAMEWORK, "ForceCreateDirectory, dir: %{public}s", dirPath.c_str()); bool success = OHOS::ForceCreateDirectory(dirPath); if (!success) { - LOG_ERROR(UDMF_FRAMEWORK, "create dir %{public}s failed, errno: %{public}d.", dirPath.c_str(), errno); + LOG_ERROR(UDMF_FRAMEWORK, "create dir failed, errno: %{public}d.", errno); return; } if (mode != 0) { @@ -107,6 +107,15 @@ void UnifiedDataHelper::GetSummary(const UnifiedData &data, Summary &summary) for (const auto &record : data.GetRecords()) { CalRecordSummary(*record->GetEntries(), summary); } + summary.version = WITH_SUMMARY_FORMAT_VER; +} + +void UnifiedDataHelper::GetSummaryFromLoadInfo(const DataLoadInfo &dataLoadInfo, Summary &summary) +{ + summary.totalSize = dataLoadInfo.recordCount; + for (const auto &type : dataLoadInfo.types) { + summary.summary.emplace(type, 0); + } } bool UnifiedDataHelper::Pack(UnifiedData &data) @@ -166,20 +175,16 @@ bool UnifiedDataHelper::SaveUDataToFile(const std::string &dataFile, UnifiedData std::FILE *file = fopen(dataFile.c_str(), "w+"); if (file == nullptr) { - LOG_ERROR(UDMF_FRAMEWORK, "failed to open file: %{public}s, errno is %{public}d", dataFile.c_str(), errno); + LOG_ERROR(UDMF_FRAMEWORK, "failed to open file: errno is %{public}d", errno); return false; } recordTlv.SetFile(file); UdmfConversion::InitValueObject(data); if (!TLVUtil::Writing(data, recordTlv, TAG::TAG_UNIFIED_DATA)) { LOG_ERROR(UDMF_FRAMEWORK, "TLV Writing failed!"); - if (fclose(file) == EOF) { - LOG_ERROR(UDMF_FRAMEWORK, "fclose is failed"); - } - return false; + return FileClose(file, false); } - (void)fclose(file); - return true; + return FileClose(file, true); } bool UnifiedDataHelper::LoadUDataFromFile(const std::string &dataFile, UnifiedData &data) @@ -190,22 +195,29 @@ bool UnifiedDataHelper::LoadUDataFromFile(const std::string &dataFile, UnifiedDa std::string path = fileUri.GetRealPath(); std::FILE *file = fopen(path.c_str(), "r"); if (file == nullptr) { - LOG_ERROR(UDMF_FRAMEWORK, "failed to open file, error:%{public}s, srcdir:%{public}s, relPath:%{public}s", - std::strerror(errno), - dataFile.c_str(), - path.c_str()); + LOG_ERROR(UDMF_FRAMEWORK, "failed to open file, error:%{public}s", std::strerror(errno)); return false; } recordTlv.SetFile(file); - + if (!TLVUtil::ReadTlv(data, recordTlv, TAG::TAG_UNIFIED_DATA)) { LOG_ERROR(UDMF_FRAMEWORK, "TLV Reading failed!"); - (void)fclose(file); - return false; + return FileClose(file, false); } UdmfConversion::ConvertRecordToSubclass(data); - (void)fclose(file); - return true; + return FileClose(file, true); +} + +bool UnifiedDataHelper::FileClose(std::FILE *file, bool status) +{ + if (file == nullptr) { + return false; + } + if ((fclose(file) == EOF)) { + LOG_ERROR(UDMF_FRAMEWORK, "fclose is failed"); + return false; + } + return status; } std::string UnifiedDataHelper::GetRootPath() @@ -268,6 +280,16 @@ void UnifiedDataHelper::CalRecordSummary(std::map<std::string, ValueType> &entry auto typeId = utdId; auto valueSize = ObjectUtils::GetValueSize(value, false); ProcessTypeId(value, typeId); + auto specificIter = summary.specificSummary.find(typeId); + if (specificIter == summary.specificSummary.end()) { + summary.specificSummary[typeId] = valueSize; + } else { + summary.specificSummary[typeId] += valueSize; + } + FillSummaryFormat(typeId, utdId, summary); + if (utdId == GENERAL_FILE_URI) { + UpgradeToParentType(typeId); + } auto it = summary.summary.find(typeId); if (it == summary.summary.end()) { summary.summary[typeId] = valueSize; @@ -278,5 +300,29 @@ void UnifiedDataHelper::CalRecordSummary(std::map<std::string, ValueType> &entry } } +void UnifiedDataHelper::FillSummaryFormat(const std::string &type, const std::string &utdId, Summary &summary) +{ + Uds_Type udsType = Uds_Type::UDS_OTHER; + auto find = UDS_UTD_TYPE_MAP.find(utdId); + if (find != UDS_UTD_TYPE_MAP.end()) { + udsType = find->second; + } + if (summary.summaryFormat.find(type) != summary.summaryFormat.end()) { + summary.summaryFormat[type].emplace_back(udsType); + } else { + summary.summaryFormat[type] = { udsType }; + } +} + +void UnifiedDataHelper::UpgradeToParentType(std::string &typeId) +{ + std::string fileType = UnifiedDataUtils::GetBelongsToFileType(typeId); + if (!fileType.empty()) { + typeId = fileType; + return; + } + typeId = "general.file"; // When utdId is general.file-uri, the default parent type is general.file. +} + } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/unified_html_record_process.cpp b/udmf/framework/innerkitsimpl/data/unified_html_record_process.cpp index 10116871ece58282263010bc975a48846cb081d4..4defb59a330b82649beb8cb045e595359eddb09e 100644 --- a/udmf/framework/innerkitsimpl/data/unified_html_record_process.cpp +++ b/udmf/framework/innerkitsimpl/data/unified_html_record_process.cpp @@ -27,7 +27,6 @@ constexpr const char *IMG_TAG_PATTERN = "<img.*?>"; constexpr const char *IMG_TAG_SRC_PATTERN = "src=(['\"])(.*?)\\1"; constexpr const char *IMG_TAG_SRC_HEAD = "src=\""; constexpr const char *IMG_LOCAL_URI = "file:///"; -constexpr const char *IMG_LOCAL_PATH = "://"; constexpr const char *FILE_SCHEME_PREFIX = "file://"; struct Cmp { @@ -93,16 +92,14 @@ std::string UnifiedHtmlRecordProcess::RebuildHtmlContent(const std::string &str, std::map<uint32_t, std::pair<std::string, std::string>, Cmp> replaceUris; std::string strResult = str; for (auto &uri : uris) { - if (uri.dfsUri.empty()) { - continue; - } - std::string realUri = uri.dfsUri; - if (realUri.substr(0, strlen(FILE_SCHEME_PREFIX)) == FILE_SCHEME_PREFIX) { - AppFileService::ModuleFileUri::FileUri fileUri(uri.dfsUri); + std::string tmpUri = uri.dfsUri.empty() ? uri.authUri : uri.dfsUri; + std::string realUri = tmpUri; + if (tmpUri.substr(0, strlen(FILE_SCHEME_PREFIX)) == FILE_SCHEME_PREFIX) { + AppFileService::ModuleFileUri::FileUri fileUri(tmpUri); realUri = FILE_SCHEME_PREFIX; realUri += fileUri.GetRealPath(); + replaceUris[uri.position] = std::make_pair(std::move(uri.oriUri), std::move(realUri)); } - replaceUris[uri.position] = std::make_pair(std::move(uri.oriUri), std::move(realUri)); } if (replaceUris.empty()) { return ""; @@ -209,8 +206,7 @@ std::vector<UriInfo> UnifiedHtmlRecordProcess::SplitHtmlWithImgSrcLabel( bool UnifiedHtmlRecordProcess::IsLocalURI(const std::string &uri) noexcept { - return uri.substr(0, strlen(IMG_LOCAL_URI)) == std::string(IMG_LOCAL_URI) || - uri.find(IMG_LOCAL_PATH) == std::string::npos; + return uri.substr(0, strlen(IMG_LOCAL_URI)) == std::string(IMG_LOCAL_URI); } } // namespace UDMF diff --git a/udmf/framework/innerkitsimpl/data/unified_record.cpp b/udmf/framework/innerkitsimpl/data/unified_record.cpp index 5e6bb685bf96e32c87da0127ce31499f82f532f0..b95f9e1ac959748175cff8565096d8d01db93014 100644 --- a/udmf/framework/innerkitsimpl/data/unified_record.cpp +++ b/udmf/framework/innerkitsimpl/data/unified_record.cpp @@ -24,8 +24,6 @@ namespace OHOS { namespace UDMF { static constexpr UDType FILE_TYPES[] = {FILE, AUDIO, FOLDER, IMAGE, VIDEO}; static constexpr const char *FILE_SCHEME = "file"; -static const std::set<std::string> FILE_SUB_TYPES = { - "general.image", "general.video", "general.audio", "general.folder" }; static constexpr UDType UDC_RECORDS[] = {APPLICATION_DEFINED_RECORD, AUDIO, FILE, FOLDER, HTML, IMAGE, HYPERLINK, PLAIN_TEXT, SYSTEM_DEFINED_APP_ITEM, SYSTEM_DEFINED_FORM, SYSTEM_DEFINED_PIXEL_MAP, SYSTEM_DEFINED_RECORD, TEXT, VIDEO}; @@ -39,15 +37,16 @@ UnifiedRecord::UnifiedRecord(UDType type) { dataType_ = type; utdId_ = UtdUtils::GetUtdIdFromUtdEnum(type); + utdId2_ = utdId_; } UnifiedRecord::UnifiedRecord(UDType type, ValueType value) { dataType_ = type; utdId_ = UtdUtils::GetUtdIdFromUtdEnum(type); + utdId2_ = utdId_; value_ = value; if (std::holds_alternative<std::shared_ptr<Object>>(value_)) { - hasObject_ = true; if (utdId_ == GENERAL_FILE_URI) { ObjectUtils::ProcessFileUriType(dataType_, value_); } @@ -65,7 +64,7 @@ std::vector<std::string> UnifiedRecord::GetTypes() const for (auto it = entries_->begin(); it != entries_->end(); it++) { types.push_back(it->first); } - types.push_back(utdId_); + types.push_back(utdId2_); return types; } @@ -73,6 +72,7 @@ void UnifiedRecord::SetType(const UDType &type) { dataType_ = type; utdId_ = UtdUtils::GetUtdIdFromUtdEnum(type); + utdId2_ = utdId_; } int64_t UnifiedRecord::GetSize() @@ -116,16 +116,17 @@ bool UnifiedRecord::HasType(const std::string &utdId) const if (entries_->find(utdId) != entries_->end()) { return true; } - return utdId == utdId_; + return utdId == utdId2_; } void UnifiedRecord::AddEntry(const std::string &utdId, ValueType &&value) { std::lock_guard<std::recursive_mutex> lock(mutex_); - if (utdId == utdId_ || utdId_.empty()) { + if (utdId == utdId2_ || utdId2_.empty()) { utdId_ = utdId; + utdId2_ = utdId_; value_ = std::move(value); - auto udType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(utdId_)); + auto udType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(utdId2_)); if (udType == UD_BUTT) { dataType_ = APPLICATION_DEFINED_RECORD; return; @@ -142,19 +143,23 @@ void UnifiedRecord::AddEntry(const std::string &utdId, ValueType &&value) ValueType UnifiedRecord::GetEntry(const std::string &utdId) { std::lock_guard<std::recursive_mutex> lock(mutex_); - if (utdId_ == utdId && !(std::holds_alternative<std::monostate>(value_))) { + if (utdId2_ == utdId && !(std::holds_alternative<std::monostate>(value_))) { + auto value = value_; if (!std::holds_alternative<std::shared_ptr<Object>>(value_) && std::find(std::begin(UDC_RECORDS), std::end(UDC_RECORDS), dataType_) != std::end(UDC_RECORDS)) { InitObject(); + value = value_; + auto obj = std::get<std::shared_ptr<Object>>(value_); + value_ = obj->value_[VALUE_TYPE]; } - return value_; + return value; } auto it = entries_->find(utdId); if (it != entries_->end() && !(std::holds_alternative<std::monostate>(it->second))) { return it->second; } auto getter = GetterSystem::GetInstance().GetGetter(channelName_); - if (getter != nullptr && (utdId_ == utdId || it != entries_->end())) { + if (getter != nullptr && (utdId2_ == utdId || it != entries_->end())) { auto value = getter->GetValueByType(dataId_, recordId_, utdId); if (std::holds_alternative<std::monostate>(value)) { LOG_ERROR(UDMF_FRAMEWORK, "get value failed, utdId: %{public}s", utdId.c_str()); @@ -163,14 +168,15 @@ ValueType UnifiedRecord::GetEntry(const std::string &utdId) AddEntry(utdId, ValueType(value)); return value; } - if (utdId_ == utdId && std::holds_alternative<std::monostate>(value_)) { + if (utdId2_ == utdId && std::holds_alternative<std::monostate>(value_)) { InitObject(); + auto value = value_; auto obj = std::get<std::shared_ptr<Object>>(value_); + value_ = obj->value_[VALUE_TYPE]; if (obj->value_.size() == 1) { // value_ size equals 1 means there are no datas - value_ = obj->value_[VALUE_TYPE]; return std::monostate(); } else { - return value_; + return value; } } return std::monostate(); @@ -179,15 +185,15 @@ ValueType UnifiedRecord::GetEntry(const std::string &utdId) std::shared_ptr<std::map<std::string, ValueType>> UnifiedRecord::GetEntries() { auto res = std::make_shared<std::map<std::string, ValueType>>(*entries_); - if (!utdId_.empty()) { + if (!utdId2_.empty()) { if (!std::holds_alternative<std::shared_ptr<Object>>(value_)) { InitObject(); ValueType value = value_; - res->insert_or_assign(utdId_, std::move(value)); + res->insert_or_assign(utdId2_, std::move(value)); auto object = std::get<std::shared_ptr<Object>>(value_); value_ = object->value_[VALUE_TYPE]; // restore value_ } else { - res->insert_or_assign(utdId_, value_); + res->insert_or_assign(utdId2_, value_); } } return res; @@ -220,16 +226,28 @@ std::set<std::string> UnifiedRecord::GetUtdIds() const std::set<std::string> utdIds; if (!utdId_.empty()) { utdIds.emplace(utdId_); - if (utdId_ == GENERAL_FILE_URI && std::holds_alternative<std::shared_ptr<Object>>(value_)) { + } + for (const auto& [key, value] : *entries_) { + utdIds.emplace(key); + } + return utdIds; +} + +std::set<std::string> UnifiedRecord::GetUtdIdsWithAddFileType(bool isSpecific) const +{ + std::set<std::string> utdIds; + if (!utdId2_.empty()) { + utdIds.emplace(utdId2_); + if (utdId2_ == GENERAL_FILE_URI && std::holds_alternative<std::shared_ptr<Object>>(value_)) { auto fileUri = std::get<std::shared_ptr<Object>>(value_); - AddFileUriType(utdIds, fileUri); + AddFileUriType(utdIds, fileUri, isSpecific); } } for (const auto& [key, value] : *entries_) { utdIds.emplace(key); if (key == GENERAL_FILE_URI && std::holds_alternative<std::shared_ptr<Object>>(value)) { auto fileUri = std::get<std::shared_ptr<Object>>(value); - AddFileUriType(utdIds, fileUri); + AddFileUriType(utdIds, fileUri, isSpecific); } } return utdIds; @@ -238,6 +256,7 @@ std::set<std::string> UnifiedRecord::GetUtdIds() const void UnifiedRecord::SetUtdId(const std::string& utdId) { utdId_ = utdId; + utdId2_ = utdId; } std::string UnifiedRecord::GetUtdId() const @@ -245,6 +264,16 @@ std::string UnifiedRecord::GetUtdId() const return utdId_; } +void UnifiedRecord::SetUtdId2(const std::string& utdId) +{ + utdId2_ = utdId; +} + +std::string UnifiedRecord::GetUtdId2() const +{ + return utdId2_; +} + void UnifiedRecord::SetDataId(uint32_t dataId) { dataId_ = dataId; @@ -299,11 +328,6 @@ void UnifiedRecord::InitObject() } } -bool UnifiedRecord::HasObject() -{ - return hasObject_; -} - bool UnifiedRecord::HasFileType(std::string &fileUri) const { fileUri.clear(); @@ -372,7 +396,8 @@ void UnifiedRecord::ComputeUris(const std::function<bool(UriInfo &)> &action) } } -void UnifiedRecord::AddFileUriType(std::set<std::string> &utdIds, const std::shared_ptr<Object> &fileUri) const +void UnifiedRecord::AddFileUriType(std::set<std::string> &utdIds, + const std::shared_ptr<Object> &fileUri, bool isSpecific) const { if (fileUri == nullptr) { return; @@ -381,7 +406,14 @@ void UnifiedRecord::AddFileUriType(std::set<std::string> &utdIds, const std::sha if (fileUri->GetValue(UNIFORM_DATA_TYPE, uniformDataType) && uniformDataType == GENERAL_FILE_URI) { std::string fileType; if (fileUri->GetValue(FILE_TYPE, fileType) && !fileType.empty()) { - utdIds.emplace(fileType); + if (isSpecific) { + utdIds.emplace(fileType); + return; + } + std::string fileTypeStr = UnifiedDataUtils::GetBelongsToFileType(fileType); + if (!fileTypeStr.empty()) { + utdIds.emplace(fileTypeStr); + } } } } diff --git a/udmf/framework/innerkitsimpl/data/video.cpp b/udmf/framework/innerkitsimpl/data/video.cpp index 30dde4e3a799047723b4e17cfafe39cb8145c29a..69ca7230b6f68077e024a32b5475d21d0eb188b4 100644 --- a/udmf/framework/innerkitsimpl/data/video.cpp +++ b/udmf/framework/innerkitsimpl/data/video.cpp @@ -20,18 +20,30 @@ namespace UDMF { Video::Video() : Video("") { SetType(VIDEO); - utdId_ = UtdUtils::GetUtdIdFromUtdEnum(VIDEO); + utdId2_ = GENERAL_FILE_URI; } Video::Video(const std::string &uri) : File(uri) { SetType(VIDEO); - utdId_ = UtdUtils::GetUtdIdFromUtdEnum(VIDEO); + utdId2_ = GENERAL_FILE_URI; } Video::Video(UDType type, ValueType value) : File(type, value) { SetType(VIDEO); + utdId2_ = GENERAL_FILE_URI; +} + +void Video::InitObject() +{ + File::InitObject(); + auto object = std::get<std::shared_ptr<Object>>(value_); + if (!fileType_.empty()) { + object->value_[FILE_TYPE] = fileType_; + } else { + object->value_[FILE_TYPE] = "general.video"; + } } } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/dynamic/pixelmap_loader.cpp b/udmf/framework/innerkitsimpl/dynamic/pixelmap_loader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..121676cd182d90750948d0542581a51b1f9d658b --- /dev/null +++ b/udmf/framework/innerkitsimpl/dynamic/pixelmap_loader.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2025 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 "PixelmapLoader" + +#include "pixelmap_loader.h" + +#include <dlfcn.h> +#include <thread> +#include "logger.h" +#include "pixel_map.h" + +namespace OHOS { +namespace UDMF { + +static constexpr const char* PIXEL_MAP_WRAPPER_SO_NAME = "libpixelmap_wrapper.z.so"; +static constexpr const char* DECODE_TLV = "DecodeTlv"; +static constexpr const char* ENCODE_TLV = "EncodeTlv"; +static constexpr const char* GET_PIXEL_MAP_FROM_RAW_DATA = "GetPixelMapFromRawData"; +static constexpr const char* PARSE_INFO_FROM_PIXEL_MAP = "ParseInfoFromPixelMap"; + +std::weak_ptr<void> PixelMapLoader::SoAutoUnloadManager::weakHandler_; +std::mutex PixelMapLoader::SoAutoUnloadManager::mutex_; + +std::shared_ptr<void> PixelMapLoader::SoAutoUnloadManager::GetHandler() +{ + { + std::lock_guard<std::mutex> lock(mutex_); + if (auto real = weakHandler_.lock()) { + return real; + } + } + LOG_INFO(UDMF_KITS_INNER, "dlopen start"); + void *rawHandler = dlopen(PIXEL_MAP_WRAPPER_SO_NAME, RTLD_NOW); + if (rawHandler == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "dlopen error! msg=%{public}s", dlerror()); + return nullptr; + } + + auto deleter = [](void *h) { + if (h) dlclose(h); + }; + std::shared_ptr<void> sp(rawHandler, deleter); + + { + std::lock_guard<std::mutex> lock(mutex_); + if (auto existed = weakHandler_.lock()) { + return existed; + } + weakHandler_ = sp; + return sp; + } +} + +PixelMapLoader::PixelMapLoader() +{ + handler_ = SoAutoUnloadManager::GetHandler(); + if (handler_ == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "handler is null!"); + } +} + +std::shared_ptr<OHOS::Media::PixelMap> PixelMapLoader::DecodeTlv(std::vector<uint8_t> &buff) +{ + if (buff.empty()) { + LOG_ERROR(UDMF_KITS_INNER, "buff is empty!"); + return nullptr; + } + if (handler_ == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "handler is null!"); + return nullptr; + } + PixelMapDetails details; + details.rawData = std::ref(buff); + auto loadDecodeTlv = reinterpret_cast<LoadDecodeTlv>(dlsym(handler_.get(), DECODE_TLV)); + if (loadDecodeTlv == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "dlsym error! msg=%{public}s", dlerror()); + return nullptr; + } + + OHOS::Media::PixelMap *raw = loadDecodeTlv(details); + if (raw == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "pixelMap is null!"); + return nullptr; + } + auto deleter = [handler = handler_](OHOS::Media::PixelMap *p) { + delete p; + }; + return std::shared_ptr<OHOS::Media::PixelMap>(raw, deleter); +} + +bool PixelMapLoader::EncodeTlv(const std::shared_ptr<OHOS::Media::PixelMap> pixelMap, std::vector<uint8_t> &buff) +{ + if (pixelMap == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "pixelMap is nullptr!"); + return false; + } + if (handler_ == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "handler is null!"); + return false; + } + auto loadEncodeTlv = reinterpret_cast<LoadEncodeTlv>(dlsym(handler_.get(), ENCODE_TLV)); + if (loadEncodeTlv == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "dlsym error! msg=%{public}s", dlerror()); + return false; + } + auto details = std::make_shared<PixelMapDetails>(); + details->rawDataResult.emplace(); + auto result = loadEncodeTlv(pixelMap.get(), details.get()); + if (details->rawDataResult->empty()) { + LOG_ERROR(UDMF_KITS_INNER, "encodeTlv fail"); + return result; + } + buff = std::move(*details->rawDataResult); + return result; +} + +std::shared_ptr<OHOS::Media::PixelMap> PixelMapLoader::GetPixelMapFromRawData(const PixelMapDetails &details) +{ + if (!details.rawData.has_value()) { + LOG_ERROR(UDMF_KITS_INNER, "buff is empty!"); + return nullptr; + } + if (handler_ == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "handler is null!"); + return nullptr; + } + auto loadGetPixelMapFromRawData = reinterpret_cast<LoadGetPixelMapFromRawData>( + dlsym(handler_.get(), GET_PIXEL_MAP_FROM_RAW_DATA)); + if (loadGetPixelMapFromRawData == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "dlsym error! msg=%{public}s", dlerror()); + return nullptr; + } + OHOS::Media::PixelMap *raw = loadGetPixelMapFromRawData(details); + if (raw == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "pixelMap is null!"); + return nullptr; + } + auto deleter = [handler = handler_](OHOS::Media::PixelMap *p) { + delete p; + }; + return std::shared_ptr<OHOS::Media::PixelMap>(raw, deleter); +} + +std::shared_ptr<PixelMapDetails> PixelMapLoader::ParseInfoFromPixelMap( + const std::shared_ptr<OHOS::Media::PixelMap> pixelMap) +{ + if (pixelMap == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "pixelMap is nullptr!"); + return nullptr; + } + if (handler_ == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "handler is null!"); + return nullptr; + } + auto loadParseInfoFromPixelMap = reinterpret_cast<LoadParseInfoFromPixelMap>( + dlsym(handler_.get(), PARSE_INFO_FROM_PIXEL_MAP)); + if (loadParseInfoFromPixelMap == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "dlsym error! msg=%{public}s", dlerror()); + return nullptr; + } + return std::shared_ptr<PixelMapDetails>(loadParseInfoFromPixelMap(pixelMap.get())); +} + +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/dynamic/pixelmap_wrapper.cpp b/udmf/framework/innerkitsimpl/dynamic/pixelmap_wrapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dc858047ed6e7628c117ad098c34469edf3a3b4a --- /dev/null +++ b/udmf/framework/innerkitsimpl/dynamic/pixelmap_wrapper.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2025 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 "PixelmapWrapper" +#include "pixelmap_wrapper.h" + +#include "logger.h" +#include "media_errors.h" +#include "pixel_map.h" + +using namespace OHOS::UDMF; + +static constexpr size_t BYTES_PER_COLOR = sizeof(uint32_t); + +#ifdef __cplusplus +extern "C" { +#endif + +OHOS::Media::PixelMap *DecodeTlv(const PixelMapDetails details) +{ + return OHOS::Media::PixelMap::DecodeTlv(details.rawData->get()); +} + +bool EncodeTlv(const OHOS::Media::PixelMap *pixelMap, PixelMapDetails *details) +{ + if (details == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "details is null"); + return false; + } + auto &rawData = *(details->rawDataResult); + return pixelMap->EncodeTlv(rawData); +} + +OHOS::Media::PixelMap *GetPixelMapFromRawData(const PixelMapDetails details) +{ + OHOS::Media::InitializationOptions opts; + opts.size.width = details.width; + opts.size.height = details.height; + opts.pixelFormat = static_cast<OHOS::Media::PixelFormat>(details.pixelFormat); + if (!details.rawData.has_value()) { + return nullptr; + } + // This create does not do pre-multiplication. + opts.alphaType = OHOS::Media::AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL; + LOG_INFO(UDMF_KITS_INNER, + "PixelMap width = %{public}d, height = %{public}d, pixelFormat = %{public}d, rawData size = %{public}zu", + opts.size.width, opts.size.height, opts.pixelFormat, details. + rawData->get().size()); + opts.srcPixelFormat = opts.pixelFormat; + auto pixelMap = OHOS::Media::PixelMap::Create( + reinterpret_cast<const uint32_t *>(details.rawData->get().data()), + details.rawData->get().size() / BYTES_PER_COLOR, opts); + if (pixelMap == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "Create PixelMap from rawData failed"); + return nullptr; + } + return pixelMap.release(); +} + +PixelMapDetails *ParseInfoFromPixelMap(OHOS::Media::PixelMap *pixelMap) +{ + if (pixelMap == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "PixelMap is null"); + return nullptr; + } + auto details = new (std::nothrow) PixelMapDetails; + if (details == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "Apply memory for details failed"); + return nullptr; + } + details->width = pixelMap->GetWidth(); + details->height = pixelMap->GetHeight(); + details->pixelFormat = static_cast<int32_t>(pixelMap->GetPixelFormat()); + details->alphaType = static_cast<int32_t>(pixelMap->GetAlphaType()); + auto length = pixelMap->GetByteCount(); + if (length <= 0) { + LOG_ERROR(UDMF_KITS_INNER, "Has no length"); + return details; + } + std::vector<uint8_t> rawData; + rawData.resize(length); + auto status = pixelMap->ReadPixels(length, rawData.data()); + if (status != OHOS::Media::SUCCESS) { + LOG_ERROR(UDMF_KITS_INNER, "Get Pixels error, status = %{public}u", status); + return details; + } + details->rawDataResult.emplace(std::move(rawData)); + return details; +} + +#ifdef __cplusplus +}; +#endif \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/service/distributeddata_udmf_ipc_interface_code.h b/udmf/framework/innerkitsimpl/service/distributeddata_udmf_ipc_interface_code.h index 4d5e12374f05d639627c903d71ac50051fee093c..d3d0efb331f6c2a3883c613c0a779fdfd68c4f6c 100644 --- a/udmf/framework/innerkitsimpl/service/distributeddata_udmf_ipc_interface_code.h +++ b/udmf/framework/innerkitsimpl/service/distributeddata_udmf_ipc_interface_code.h @@ -34,6 +34,16 @@ enum class UdmfServiceInterfaceCode : uint32_t { REMOVE_APP_SHARE_OPTION, OBTAIN_ASYN_PROCESS, CLEAR_ASYN_PROCESS_BY_KEY, + SET_DELAY_INFO, + SET_DELAY_DATA, + GET_DELAY_DATA, + CODE_BUTT +}; + +enum class UdmfNotifierInterfaceCode : uint32_t { + CODE_HEAD = 0, + HANDLE_DELAY_OBSERVER = CODE_HEAD, + HANDLE_DELAY_DATA, CODE_BUTT }; } // namespace OHOS::UDMF diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.h b/udmf/framework/innerkitsimpl/service/iudmf_notifier.h similarity index 50% rename from datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.h rename to udmf/framework/innerkitsimpl/service/iudmf_notifier.h index f7ebd8f7cc9bda43bbb4bbae4c4e0d356b2608b4..1878dce53ba2f01a46618cb2150847376b5dcf53 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.h +++ b/udmf/framework/innerkitsimpl/service/iudmf_notifier.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 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 @@ -12,27 +12,28 @@ * 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" +#ifndef IUDMF_NOTIFIER_H +#define IUDMF_NOTIFIER_H + +#include <iremote_broker.h> +#include "unified_data.h" +#include "unified_types.h" + namespace OHOS { namespace UDMF { -class RuntimeStoreAccountObserver : public DistributedData::AccountDelegate::Observer { - void OnAccountChanged(const DistributedData::AccountEventInfo &eventInfo, int32_t timeout) override; - // must specify unique name for observer - std::string Name() override - { - return "UdmfRuntimeStore"; - } - - LevelType GetLevel() override - { - return LevelType::LOW; - } +class IUdmfNotifier : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"IUdmfNotifier descriptor"); + virtual void HandleDelayObserver(const std::string &key, const DataLoadInfo &dataLoadInfo) = 0; +}; + +class IDelayDataCallback : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"IDelayDataCallback descriptor"); + virtual void DelayDataCallback(const std::string &key, const UnifiedData &data) = 0; }; } // namespace UDMF } // namespace OHOS - -#endif // STORE_ACCOUNT_OBSERVER_H \ No newline at end of file +#endif // IUDMF_NOTIFIER_H \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/service/progress_callback.cpp b/udmf/framework/innerkitsimpl/service/progress_callback.cpp index f235e18d18211f86c4e353ffecd1d73a03c0f0ed..4562548ff74ca40f59c5be36de75ac1cad944cd8 100644 --- a/udmf/framework/innerkitsimpl/service/progress_callback.cpp +++ b/udmf/framework/innerkitsimpl/service/progress_callback.cpp @@ -23,6 +23,7 @@ namespace OHOS { namespace UDMF { +constexpr int CONVERSION_RULES = 10; int32_t ProgressSignalStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { @@ -33,8 +34,7 @@ int32_t ProgressSignalStub::OnRemoteRequest(uint32_t code, return E_ERROR; } pid_t pid = IPCSkeleton::GetCallingPid(); - pid_t uid = IPCSkeleton::GetCallingUid(); - LOG_INFO(UDMF_SERVICE, "CallingPid=%{public}d, CallingUid=%{public}d, code=%{public}u", pid, uid, code); + LOG_INFO(UDMF_SERVICE, "CallingPid=%{public}d, code=%{public}u", pid, code); HandleProgressSignalValue(data); return E_OK; } @@ -44,12 +44,14 @@ void ProgressSignalCallback::HandleProgressSignalValue(MessageParcel &data) int32_t cancelStatus = 0; std::string signalValue = data.ReadString(); - try { - cancelStatus = std::stoi(signalValue); - } catch (const std::exception& e) { - LOG_ERROR(UDMF_CLIENT, "Signal value error, signalValue=%{public}s", signalValue.c_str()); + char* end = nullptr; + errno = 0; + cancelStatus = std::strtoul(signalValue.c_str(), &end, CONVERSION_RULES); + if (errno == ERANGE || end == signalValue || *end != '\0') { + LOG_ERROR(UDMF_CLIENT, "Failed to convert signalValue, signalValue=%{public}s", signalValue.c_str()); return; } + switch (cancelStatus) { case NORMAL_PASTE: break; diff --git a/udmf/framework/innerkitsimpl/service/udmf_notifier_stub.cpp b/udmf/framework/innerkitsimpl/service/udmf_notifier_stub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dc7a720d5bde9309d9523755d5a902aaf192b1c9 --- /dev/null +++ b/udmf/framework/innerkitsimpl/service/udmf_notifier_stub.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2025 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 "UdmfNotifierStub" +#include "udmf_notifier_stub.h" + +#include "error_code.h" +#include "ipc_skeleton.h" +#include "logger.h" +#include "udmf_async_client.h" +#include "udmf_types_util.h" +#include "udmf_conversion.h" +#include "unified_html_record_process.h" + +namespace OHOS { +namespace UDMF { + +int32_t UdmfNotifierStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, + MessageOption &option) +{ + LOG_INFO(UDMF_SERVICE, "code:%{public}u callingPid:%{public}u", code, IPCSkeleton::GetCallingPid()); + std::u16string local = GetDescriptor(); + std::u16string remote = data.ReadInterfaceToken(); + if (local != remote) { + LOG_ERROR(UDMF_SERVICE, "local is not equal to remote"); + return -1; + } + + std::string key; + DataLoadInfo dataLoadInfo; + if (!ITypesUtil::Unmarshal(data, key, dataLoadInfo)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshal failed!"); + return E_READ_PARCEL_ERROR; + } + + HandleDelayObserver(key, dataLoadInfo); + return 0; +} + +UdmfNotifierClient::UdmfNotifierClient(LoadHandler loadHandler):loadHandler_(loadHandler) {} + +void UdmfNotifierClient::HandleDelayObserver(const std::string &key, const DataLoadInfo &dataLoadInfo) +{ + auto loadHandler = loadHandler_; + UdmfAsyncClient::GetInstance().PushTaskToExecutor( + [loadHandler, key, dataLoadInfo] { loadHandler(key, dataLoadInfo); }); +} + +int32_t DelayDataCallbackStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, + MessageOption &option) +{ + LOG_INFO(UDMF_SERVICE, "code:%{public}u callingPid:%{public}u", code, IPCSkeleton::GetCallingPid()); + std::u16string local = GetDescriptor(); + std::u16string remote = data.ReadInterfaceToken(); + if (local != remote) { + LOG_ERROR(UDMF_SERVICE, "local is not equal to remote"); + return -1; + } + + std::string key; + UnifiedData unifiedData; + if (!ITypesUtil::Unmarshal(data, key, unifiedData)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshal failed!"); + return E_READ_PARCEL_ERROR; + } + UdmfConversion::ConvertRecordToSubclass(unifiedData); + + if (unifiedData.HasType(UtdUtils::GetUtdIdFromUtdEnum(UDType::HTML))) { + UnifiedHtmlRecordProcess::RebuildHtmlRecord(unifiedData); + } + DelayDataCallback(key, unifiedData); + return 0; +} + +DelayDataCallbackClient::DelayDataCallbackClient(DataCallback dataCallback):dataCallback_(dataCallback) {} + +void DelayDataCallbackClient::DelayDataCallback(const std::string &key, const UnifiedData &unifiedData) +{ + auto dataCallback = dataCallback_; + UdmfAsyncClient::GetInstance().PushTaskToExecutor( + [dataCallback, key, unifiedData] { dataCallback(key, unifiedData); }); +} + +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/gdb/include/gdb_transaction.h b/udmf/framework/innerkitsimpl/service/udmf_notifier_stub.h similarity index 32% rename from relational_store/interfaces/inner_api/gdb/include/gdb_transaction.h rename to udmf/framework/innerkitsimpl/service/udmf_notifier_stub.h index 137ff7406c8dc4d7afcad812b9a43a7be60c7825..f9e79478cce95dcf371ba4ec3077f056207d4437 100644 --- a/relational_store/interfaces/inner_api/gdb/include/gdb_transaction.h +++ b/udmf/framework/innerkitsimpl/service/udmf_notifier_stub.h @@ -12,49 +12,52 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -#ifndef ARKDATA_INTELLIGENCE_PLATFORM_GDB_TRANSACTION_H -#define ARKDATA_INTELLIGENCE_PLATFORM_GDB_TRANSACTION_H - + +#ifndef UDMF_NOTIFIER_STUB_H +#define UDMF_NOTIFIER_STUB_H + #include <functional> -#include <tuple> -#include <utility> -#include <vector> - -#include "gdb_store_config.h" -#include "result.h" - -namespace OHOS::DistributedDataAip { -class Connection; -class Transaction { +#include <iremote_stub.h> +#include "iudmf_notifier.h" +#include "unified_data.h" + +namespace OHOS { +namespace UDMF { + +class UdmfNotifierStub : public IRemoteStub<IUdmfNotifier> { public: - using Creator = std::function<std::pair<int32_t, std::shared_ptr<Transaction>>(std::shared_ptr<Connection> conn)>; - - static std::pair<int32_t, std::shared_ptr<Transaction>> Create(std::shared_ptr<Connection> conn); - static int32_t RegisterCreator(Creator creator); - - API_EXPORT virtual ~Transaction() = default; - - API_EXPORT virtual int32_t Commit() = 0; - API_EXPORT virtual int32_t Rollback() = 0; - virtual int32_t Close() = 0; - - /** - * @brief Queries data in the database based on GQL statement. - * - * @param gql Indicates the GQL statement to execute. - */ - API_EXPORT virtual std::pair<int32_t, std::shared_ptr<Result>> Query(const std::string &gql) = 0; - - /** - * @brief Executes an GQL statement. - * - * @param gql Indicates the GQL statement to execute. - */ - API_EXPORT virtual std::pair<int32_t, std::shared_ptr<Result>> Execute(const std::string &gql) = 0; - + int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +}; + +class UdmfNotifierClient : public UdmfNotifierStub { +public: + explicit UdmfNotifierClient(LoadHandler loadHandler_); + virtual ~UdmfNotifierClient() = default; + + void HandleDelayObserver(const std::string &key, const DataLoadInfo &dataLoadInfo) override; + +private: + LoadHandler loadHandler_; +}; + +class DelayDataCallbackStub : public IRemoteStub<IDelayDataCallback> { +public: + int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +}; + +class DelayDataCallbackClient : public DelayDataCallbackStub { +public: + using DataCallback = std::function<void(const std::string &udKey, const UnifiedData &unifiedData)>; + + explicit DelayDataCallbackClient(DataCallback dataCallback); + virtual ~DelayDataCallbackClient() = default; + void DelayDataCallback(const std::string &key, const UnifiedData &data) override; + private: - static inline Creator creator_; + DataCallback dataCallback_; }; -} // namespace OHOS::DistributedDataAip -#endif + + +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_NOTIFIER_STUB_H \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/service/udmf_service.h b/udmf/framework/innerkitsimpl/service/udmf_service.h index 1f685fcf806a932d88a4f1965a4cda8927fb454a..70874cb212f828e02b7b727f3afb774c588646e1 100644 --- a/udmf/framework/innerkitsimpl/service/udmf_service.h +++ b/udmf/framework/innerkitsimpl/service/udmf_service.h @@ -25,6 +25,7 @@ #include "unified_data.h" #include "unified_meta.h" #include "unified_types.h" +#include "iudmf_notifier.h" namespace OHOS { namespace UDMF { @@ -51,6 +52,11 @@ public: virtual int32_t RemoveAppShareOption(const std::string &intention) = 0; virtual int32_t ObtainAsynProcess(AsyncProcessInfo &processInfo) = 0; virtual int32_t ClearAsynProcessByKey(const std::string &businessUdKey) = 0; + virtual int32_t SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptr<IRemoteObject> iUdmfNotifier, + std::string &key) = 0; + virtual int32_t PushDelayData(const std::string &key, UnifiedData &unifiedData) = 0; + virtual int32_t GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr<IRemoteObject> iUdmfNotifier, std::shared_ptr<UnifiedData> unifiedData) = 0; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/service/udmf_service_client.cpp b/udmf/framework/innerkitsimpl/service/udmf_service_client.cpp index 809e5816c141852167b0840deb39950b4e45d579..831cb9bc2498a076bfc3bcc77ef843ad6c0421aa 100644 --- a/udmf/framework/innerkitsimpl/service/udmf_service_client.cpp +++ b/udmf/framework/innerkitsimpl/service/udmf_service_client.cpp @@ -105,11 +105,12 @@ void UdmfServiceClient::ServiceDeathRecipient::OnRemoteDied(const wptr<IRemoteOb int32_t UdmfServiceClient::SetData(CustomOption &option, UnifiedData &unifiedData, std::string &key) { LOG_DEBUG(UDMF_SERVICE, "start, tag: %{public}d", option.intention); - if (!UnifiedDataUtils::IsValidIntention(option.intention)) { - LOG_ERROR(UDMF_SERVICE, "Invalid intention"); - return E_INVALID_PARAMETERS; + if (option.intention == UD_INTENTION_DATA_HUB) { + if (option.visibility != Visibility::VISIBILITY_ALL && + option.visibility != Visibility::VISIBILITY_OWN_PROCESS) { + option.visibility = Visibility::VISIBILITY_ALL; + } } - if (!unifiedData.IsValid()) { LOG_ERROR(UDMF_SERVICE, "UnifiedData is invalid."); return E_INVALID_PARAMETERS; @@ -155,7 +156,8 @@ int32_t UdmfServiceClient::GetBatchData(const QueryOption &query, std::vector<Un LOG_DEBUG(UDMF_SERVICE, "start, tag: intention = %{public}d, key = %{public}s", query.intention, query.key.c_str()); auto find = UD_INTENTION_MAP.find(query.intention); std::string intention = find == UD_INTENTION_MAP.end() ? intention : find->second; - if (!UnifiedDataUtils::IsValidOptions(query.key, intention)) { + UnifiedKey key(query.key); + if (!key.IsValid() && !UnifiedDataUtils::IsValidOptionsNonDrag(key, intention)) { LOG_ERROR(UDMF_SERVICE, "invalid option, query.key: %{public}s, intention: %{public}s", query.key.c_str(), intention.c_str()); return E_INVALID_PARAMETERS; @@ -185,7 +187,16 @@ int32_t UdmfServiceClient::UpdateData(const QueryOption &query, UnifiedData &uni LOG_ERROR(UDMF_SERVICE, "invalid key, key.intention: %{public}s", key.intention.c_str()); return E_INVALID_PARAMETERS; } - + std::string intention = UnifiedDataUtils::FindIntentionMap(query.intention); + if (!UnifiedDataUtils::IsValidOptionsNonDrag(key, intention)) { + LOG_ERROR(UDMF_SERVICE, "invalid option, query.key: %{public}s, intention: %{public}s", query.key.c_str(), + intention.c_str()); + return E_INVALID_PARAMETERS; + } + if (key.intention != UD_INTENTION_MAP.at(Intention::UD_INTENTION_DATA_HUB)) { + LOG_ERROR(UDMF_SERVICE, "key.intention: %{public}s is invalid.", key.intention.c_str()); + return E_INVALID_PARAMETERS; + } if (!unifiedData.IsValid()) { LOG_ERROR(UDMF_SERVICE, "UnifiedData is invalid."); return E_INVALID_PARAMETERS; @@ -204,7 +215,8 @@ int32_t UdmfServiceClient::DeleteData(const QueryOption &query, std::vector<Unif LOG_DEBUG(UDMF_SERVICE, "start, tag: intention = %{public}d, key = %{public}s", query.intention, query.key.c_str()); auto find = UD_INTENTION_MAP.find(query.intention); std::string intention = find == UD_INTENTION_MAP.end() ? intention : find->second; - if (!UnifiedDataUtils::IsValidOptions(query.key, intention)) { + UnifiedKey key(query.key); + if (!key.IsValid() && !UnifiedDataUtils::IsValidOptionsNonDrag(key, intention)) { LOG_ERROR(UDMF_SERVICE, "invalid option, query.key: %{public}s, intention: %{public}s", query.key.c_str(), intention.c_str()); return E_INVALID_PARAMETERS; @@ -296,5 +308,22 @@ int32_t UdmfServiceClient::ClearAsynProcessByKey(const std::string &businessUdKe { return udmfProxy_->ClearAsynProcessByKey(businessUdKey); } + +int32_t UdmfServiceClient::SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptr<IRemoteObject> iUdmfNotifier, + std::string &key) +{ + return udmfProxy_->SetDelayInfo(dataLoadInfo, iUdmfNotifier, key); +} + +int32_t UdmfServiceClient::PushDelayData(const std::string &key, UnifiedData &unifiedData) +{ + return udmfProxy_->PushDelayData(key, unifiedData); +} + +int32_t UdmfServiceClient::GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr<IRemoteObject> iUdmfNotifier, std::shared_ptr<UnifiedData> unifiedData) +{ + return udmfProxy_->GetDataIfAvailable(key, dataLoadInfo, iUdmfNotifier, unifiedData); +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/service/udmf_service_client.h b/udmf/framework/innerkitsimpl/service/udmf_service_client.h index 0996967671e1da5e7231766c9a29559037afc3d1..d0813bb4f2c2aef7c20ad09fc29a112ae4388031 100644 --- a/udmf/framework/innerkitsimpl/service/udmf_service_client.h +++ b/udmf/framework/innerkitsimpl/service/udmf_service_client.h @@ -46,6 +46,11 @@ public: int32_t RemoveAppShareOption(const std::string &intention) override; int32_t ObtainAsynProcess(AsyncProcessInfo& processInfo) override; int32_t ClearAsynProcessByKey(const std::string &businessUdKey) override; + int32_t SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptr<IRemoteObject> iUdmfNotifier, + std::string &key) override; + int32_t PushDelayData(const std::string &key, UnifiedData &unifiedData) override; + int32_t GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr<IRemoteObject> iUdmfNotifier, std::shared_ptr<UnifiedData> unifiedData) override; private: class ServiceDeathRecipient : public IRemoteObject::DeathRecipient { diff --git a/udmf/framework/innerkitsimpl/service/udmf_service_proxy.cpp b/udmf/framework/innerkitsimpl/service/udmf_service_proxy.cpp index b34f6cb5aa5796b38cddbe0e7d141ca11888f21d..29a7e269ac54b6f94464acd30031a00f2015990a 100644 --- a/udmf/framework/innerkitsimpl/service/udmf_service_proxy.cpp +++ b/udmf/framework/innerkitsimpl/service/udmf_service_proxy.cpp @@ -261,5 +261,57 @@ int32_t UdmfServiceProxy::ClearAsynProcessByKey(const std::string &businessUdKey } return E_OK; } + +int32_t UdmfServiceProxy::SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptr<IRemoteObject> iUdmfNotifier, + std::string &key) +{ + MessageParcel reply; + int32_t status = IPC_SEND(UdmfServiceInterfaceCode::SET_DELAY_INFO, reply, dataLoadInfo, iUdmfNotifier); + if (status != E_OK) { + LOG_ERROR(UDMF_SERVICE, "status:0x%{public}x", status); + return status; + } + if (!ITypesUtil::Unmarshal(reply, key)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshal status failed!"); + return E_READ_PARCEL_ERROR; + } + return E_OK; +} + +int32_t UdmfServiceProxy::PushDelayData(const std::string &key, UnifiedData &unifiedData) +{ + UdmfConversion::InitValueObject(unifiedData); + MessageParcel reply; + + int32_t status = IPC_SEND(UdmfServiceInterfaceCode::SET_DELAY_DATA, reply, key, unifiedData); + if (status != E_OK) { + LOG_ERROR(UDMF_SERVICE, "status:0x%{public}x", status); + return status; + } + return E_OK; +} + +int32_t UdmfServiceProxy::GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr<IRemoteObject> iUdmfNotifier, std::shared_ptr<UnifiedData> unifiedData) +{ + if (unifiedData == nullptr) { + LOG_ERROR(UDMF_SERVICE, "Data is null!"); + return E_INVALID_PARAMETERS; + } + MessageParcel reply; + int32_t status = IPC_SEND(UdmfServiceInterfaceCode::GET_DELAY_DATA, reply, key, dataLoadInfo, iUdmfNotifier); + if (status != E_OK) { + LOG_ERROR(UDMF_SERVICE, "status:0x%{public}x, key:%{public}s!", status, key.c_str()); + return status; + } + if (!ITypesUtil::Unmarshal(reply, *unifiedData)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshal UnifiedData failed!"); + return E_READ_PARCEL_ERROR; + } + if (!unifiedData->IsEmpty()) { + UdmfConversion::ConvertRecordToSubclass(*unifiedData); + } + return status; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/service/udmf_service_proxy.h b/udmf/framework/innerkitsimpl/service/udmf_service_proxy.h index 26d01fd970aea96d13696ebca46ef5ecab2e8161..f053a6b49f29e0d833defe1546f61f601229cb4d 100644 --- a/udmf/framework/innerkitsimpl/service/udmf_service_proxy.h +++ b/udmf/framework/innerkitsimpl/service/udmf_service_proxy.h @@ -49,6 +49,11 @@ public: int32_t RemoveAppShareOption(const std::string &intention) override; int32_t ObtainAsynProcess(AsyncProcessInfo &processInfo) override; int32_t ClearAsynProcessByKey(const std::string &businessUdKey) override; + int32_t SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptr<IRemoteObject> iUdmfNotifier, + std::string &key) override; + int32_t PushDelayData(const std::string &key, UnifiedData &unifiedData) override; + int32_t GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr<IRemoteObject> iUdmfNotifier, std::shared_ptr<UnifiedData> unifiedData) override; private: static inline BrokerDelegator<UdmfServiceProxy> delegator_; int32_t SendRequest(UdmfServiceInterfaceCode code, MessageParcel &data, diff --git a/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/BUILD.gn b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/BUILD.gn index bec6e4762ca5f71ad50990faa7cf54a60ebc59f0..4bd862a39c5bcf050fd87d7eb89afc58f036618d 100644 --- a/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/BUILD.gn +++ b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/BUILD.gn @@ -47,12 +47,14 @@ ohos_fuzztest("UdmfClientFuzzTest") { "access_token:libnativetoken", "access_token:libtoken_setproc", "bundle_framework:appexecfwk_core", + "cJSON:cjson", "c_utils:utils", "hilog:libhilog", "image_framework:image", "ipc:ipc_core", "kv_store:distributeddata_inner", "samgr:samgr_proxy", + "selinux_adapter:librestorecon", ] } diff --git a/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/udmf_client_fuzzer.cpp b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/udmf_client_fuzzer.cpp index 8100bc2a4bcdadd7fdcbe5aaf5ade15e4369d681..5ebbd15ee087ab3107afa56e7173a899350ca090 100644 --- a/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/udmf_client_fuzzer.cpp +++ b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/udmf_client_fuzzer.cpp @@ -16,6 +16,7 @@ #include "udmf_client_fuzzer.h" #include <unistd.h> +#include <fuzzer/FuzzedDataProvider.h> #include "accesstoken_kit.h" #include "nativetoken_kit.h" @@ -34,6 +35,7 @@ #include "system_defined_appitem.h" #include "system_defined_pixelmap.h" #include "udmf_async_client.h" +#include "udmf_executor.h" #include "unified_types.h" using namespace OHOS; @@ -114,10 +116,10 @@ void SetHapToken() SetSelfTokenID(tokenId); } -void SetDataTextFuzz(const uint8_t *data, size_t size) +void SetDataTextFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); UnifiedData unifiedData; CustomOption option = {.intention = Intention::UD_INTENTION_BUTT}; auto text = std::make_shared<Text>(); @@ -142,10 +144,10 @@ void SetDataTextFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataPlainTextFuzz(const uint8_t *data, size_t size) +void SetDataPlainTextFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; UDDetails details1; @@ -174,10 +176,10 @@ void SetDataPlainTextFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataHtmlFuzz(const uint8_t *data, size_t size) +void SetDataHtmlFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -206,10 +208,10 @@ void SetDataHtmlFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataLinkFuzz(const uint8_t *data, size_t size) +void SetDataLinkFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -238,9 +240,9 @@ void SetDataLinkFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataFileFuzz(const uint8_t *data, size_t size) +void SetDataFileFuzz(FuzzedDataProvider &provider) { - std::string svalue(data, data + size); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -267,9 +269,9 @@ void SetDataFileFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataImageFuzz(const uint8_t *data, size_t size) +void SetDataImageFuzz(FuzzedDataProvider &provider) { - std::string svalue(data, data + size); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -293,9 +295,9 @@ void SetDataImageFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataVideoFuzz(const uint8_t *data, size_t size) +void SetDataVideoFuzz(FuzzedDataProvider &provider) { - std::string svalue(data, data + size); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -319,10 +321,10 @@ void SetDataVideoFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataSystemDefinedRecordFuzz(const uint8_t *data, size_t size) +void SetDataSystemDefinedRecordFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -347,10 +349,10 @@ void SetDataSystemDefinedRecordFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataSystemDefinedFormFuzz(const uint8_t *data, size_t size) +void SetDataSystemDefinedFormFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -386,10 +388,10 @@ void SetDataSystemDefinedFormFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataSystemDefinedAppItemFuzz(const uint8_t *data, size_t size) +void SetDataSystemDefinedAppItemFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -426,10 +428,10 @@ void SetDataSystemDefinedAppItemFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataSystemDefinedPixelMapFuzz(const uint8_t *data, size_t size) +void SetDataSystemDefinedPixelMapFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -456,10 +458,10 @@ void SetDataSystemDefinedPixelMapFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void GetSummaryFuzz(const uint8_t *data, size_t size) +void GetSummaryFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData UData; std::string key; @@ -510,9 +512,9 @@ void GetSummaryFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void GetBatchDataByKeyFuzz(const uint8_t *data, size_t size) +void GetBatchDataByKeyFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; UnifiedData data1; std::string key; @@ -531,9 +533,9 @@ void GetBatchDataByKeyFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetBatchData(option3, dataSet3); } -void GetBatchDataByIntentionFuzz(const uint8_t *data, size_t size) +void GetBatchDataByIntentionFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; UnifiedData data1; std::string key; @@ -548,9 +550,9 @@ void GetBatchDataByIntentionFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetBatchData(option2, dataSet); } -void DeleteDataByKeyFuzz(const uint8_t *data, size_t size) +void DeleteDataByKeyFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; UnifiedData data1; std::string key; @@ -569,9 +571,9 @@ void DeleteDataByKeyFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().DeleteData(option3, dataSet3); } -void DeleteDataByIntentionFuzz(const uint8_t *data, size_t size) +void DeleteDataByIntentionFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; UnifiedData data1; std::string key; @@ -586,9 +588,9 @@ void DeleteDataByIntentionFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().DeleteData(option2, dataSet); } -void UpdateDataFuzz(const uint8_t *data, size_t size) +void UpdateDataFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; UnifiedData data1; std::string key; @@ -609,13 +611,15 @@ void UpdateDataFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().UpdateData(option3, data3); } -void StartAsyncDataRetrievalFuzz(const uint8_t *data, size_t size) +void StartAsyncDataRetrievalFuzz(FuzzedDataProvider &provider) { + size_t dataSize = provider.ConsumeIntegralInRange<size_t>(1, 50); + std::vector<uint8_t> data = provider.ConsumeBytes<uint8_t>(dataSize); CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; UnifiedData data1; std::string key; auto plainText = std::make_shared<PlainText>(); - std::string content(data, data + size); + std::string content = provider.ConsumeRandomLengthString(); plainText->SetContent(content); data1.AddRecord(plainText); UdmfClient::GetInstance().SetData(option1, data1, key); @@ -627,13 +631,15 @@ void StartAsyncDataRetrievalFuzz(const uint8_t *data, size_t size) UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); } -void CancelAsyncDataRetrievalFuzz(const uint8_t *data, size_t size) +void CancelAsyncDataRetrievalFuzz(FuzzedDataProvider &provider) { + size_t dataSize = provider.ConsumeIntegralInRange<size_t>(1, 50); + std::vector<uint8_t> data = provider.ConsumeBytes<uint8_t>(dataSize); CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; UnifiedData data1; std::string key; auto plainText = std::make_shared<PlainText>(); - std::string content(data, data + size); + std::string content = provider.ConsumeRandomLengthString(); plainText->SetContent(content); data1.AddRecord(plainText); UdmfClient::GetInstance().SetData(option1, data1, key); @@ -647,32 +653,161 @@ void CancelAsyncDataRetrievalFuzz(const uint8_t *data, size_t size) UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); UdmfAsyncClient::GetInstance().Cancel(key); } + +void SyncFuzz(FuzzedDataProvider &provider) +{ + QueryOption query; + query.key = provider.ConsumeRandomLengthString(); + query.intention = static_cast<Intention>( + provider.ConsumeIntegralInRange<int32_t>(UD_INTENTION_BASE + 1, UD_INTENTION_BUTT - 1)); + query.tokenId = provider.ConsumeIntegral<uint32_t>(); + + std::vector<std::string> devices; + size_t devicesSize = provider.ConsumeIntegralInRange<size_t>(0, 10); + for (size_t i = 0; i < devicesSize; ++i) { + devices.push_back(provider.ConsumeRandomLengthString()); + } + UdmfClient::GetInstance().Sync(query, devices); +} + +void IsRemoteDataFuzz(FuzzedDataProvider &provider) +{ + QueryOption query; + query.key = provider.ConsumeRandomLengthString(); + query.intention = static_cast<Intention>( + provider.ConsumeIntegralInRange<int32_t>(UD_INTENTION_BASE + 1, UD_INTENTION_BUTT - 1)); + query.tokenId = provider.ConsumeIntegral<uint32_t>(); + bool res = false; + UdmfClient::GetInstance().IsRemoteData(query, res); +} + +void SetAppShareOptionFuzz(FuzzedDataProvider &provider) +{ + Intention intention = static_cast<Intention>( + provider.ConsumeIntegralInRange<int32_t>(UD_INTENTION_BASE + 1, UD_INTENTION_BUTT - 1)); + std::string intentionStr = UD_INTENTION_MAP.at(intention); + + ShareOptions shareOption = static_cast<ShareOptions>( + provider.ConsumeIntegralInRange<int32_t>(IN_APP, SHARE_OPTIONS_BUTT)); + UdmfClient::GetInstance().SetAppShareOption(intentionStr, shareOption); +} + +void GetAppShareOptionFuzz(FuzzedDataProvider &provider) +{ + Intention intention = static_cast<Intention>( + provider.ConsumeIntegralInRange<int32_t>(UD_INTENTION_BASE + 1, UD_INTENTION_BUTT - 1)); + std::string intentionStr = UD_INTENTION_MAP.at(intention); + + ShareOptions shareOption; + UdmfClient::GetInstance().GetAppShareOption(intentionStr, shareOption); +} + +void RemoveAppShareOptionFuzz(FuzzedDataProvider &provider) +{ + Intention intention = static_cast<Intention>( + provider.ConsumeIntegralInRange<int32_t>(UD_INTENTION_BASE + 1, UD_INTENTION_BUTT - 1)); + std::string intentionStr = UD_INTENTION_MAP.at(intention); + UdmfClient::GetInstance().RemoveAppShareOption(intentionStr); +} + +void GetParentTypeFuzz(FuzzedDataProvider &provider) +{ + Summary oldSummary; + Summary newSummary; + + size_t summarySize = provider.ConsumeIntegralInRange<size_t>(0, 10); + for (size_t i = 0; i < summarySize; ++i) { + std::string key = provider.ConsumeRandomLengthString(); + int64_t value = provider.ConsumeIntegral<int64_t>(); + oldSummary.summary[key] = value; + } + oldSummary.totalSize = provider.ConsumeIntegral<int64_t>(); + UdmfClient::GetInstance().GetParentType(oldSummary, newSummary); +} + +void SetDelayInfoFuzz(FuzzedDataProvider &provider) +{ + DataLoadInfo dataLoadInfo1 { + .sequenceKey = provider.ConsumeRandomLengthString(), + .types{ provider.ConsumeRandomLengthString() }, + .recordCount = provider.ConsumeIntegral<uint32_t>(), + }; + auto loadHandler = [] (const std::string &udKey, const DataLoadInfo &dataLoadInfo) {}; + DataLoadParams dataLoadParams = { + .loadHandler = loadHandler, + .dataLoadInfo = dataLoadInfo1, + }; + std::string key = provider.ConsumeRandomLengthString(); + UdmfClient::GetInstance().SetDelayInfo(dataLoadParams, key); +} + +void PushDelayDataFuzz(FuzzedDataProvider &provider) +{ + DataLoadInfo dataLoadInfo1{ + .sequenceKey = provider.ConsumeRandomLengthString(), + .types{provider.ConsumeRandomLengthString()}, + .recordCount = provider.ConsumeIntegral<uint32_t>(), + }; + auto loadHandler = [] (const std::string &udKey, const DataLoadInfo &dataLoadInfo) {}; + DataLoadParams dataLoadParams = { + .loadHandler = loadHandler, + .dataLoadInfo = dataLoadInfo1, + }; + std::string key = provider.ConsumeRandomLengthString(); + UdmfClient::GetInstance().SetDelayInfo(dataLoadParams, key); + + auto text = std::make_shared<Text>(); + UDDetails details; + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); + details.insert({skey, svalue}); + text->SetDetails(details); + UnifiedData unifiedData; + unifiedData.AddRecord(text); + UdmfClient::GetInstance().PushDelayData(key, unifiedData); +} + +void GetBundleNameByUdKeyFuzz(FuzzedDataProvider &provider) +{ + std::string key = provider.ConsumeRandomLengthString(); + UdmfClient::GetInstance().GetBundleNameByUdKey(key); +} } /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Run your code on data */ + FuzzedDataProvider provider(data, size); OHOS::SetUpTestCase(); - OHOS::SetDataFileFuzz(data, size); - OHOS::SetDataHtmlFuzz(data, size); - OHOS::SetDataImageFuzz(data, size); - OHOS::SetDataLinkFuzz(data, size); - OHOS::SetDataPlainTextFuzz(data, size); - OHOS::SetDataSystemDefinedAppItemFuzz(data, size); - OHOS::SetDataSystemDefinedFormFuzz(data, size); - OHOS::SetDataSystemDefinedPixelMapFuzz(data, size); - OHOS::SetDataSystemDefinedRecordFuzz(data, size); - OHOS::SetDataTextFuzz(data, size); - OHOS::SetDataVideoFuzz(data, size); - OHOS::GetSummaryFuzz(data, size); - OHOS::GetBatchDataByKeyFuzz(data, size); - OHOS::GetBatchDataByIntentionFuzz(data, size); - OHOS::DeleteDataByKeyFuzz(data, size); - OHOS::DeleteDataByIntentionFuzz(data, size); - OHOS::UpdateDataFuzz(data, size); - OHOS::StartAsyncDataRetrievalFuzz(data, size); - OHOS::CancelAsyncDataRetrievalFuzz(data, size); + OHOS::SetDataFileFuzz(provider); + OHOS::SetDataHtmlFuzz(provider); + OHOS::SetDataImageFuzz(provider); + OHOS::SetDataLinkFuzz(provider); + OHOS::SetDataPlainTextFuzz(provider); + OHOS::SetDataSystemDefinedAppItemFuzz(provider); + OHOS::SetDataSystemDefinedFormFuzz(provider); + OHOS::SetDataSystemDefinedPixelMapFuzz(provider); + OHOS::SetDataSystemDefinedRecordFuzz(provider); + OHOS::SetDataTextFuzz(provider); + OHOS::SetDataVideoFuzz(provider); + OHOS::GetSummaryFuzz(provider); + OHOS::GetBatchDataByKeyFuzz(provider); + OHOS::GetBatchDataByIntentionFuzz(provider); + OHOS::DeleteDataByKeyFuzz(provider); + OHOS::DeleteDataByIntentionFuzz(provider); + OHOS::UpdateDataFuzz(provider); + OHOS::StartAsyncDataRetrievalFuzz(provider); + OHOS::CancelAsyncDataRetrievalFuzz(provider); + OHOS::SyncFuzz(provider); + OHOS::IsRemoteDataFuzz(provider); + OHOS::SetAppShareOptionFuzz(provider); + OHOS::GetAppShareOptionFuzz(provider); + OHOS::RemoveAppShareOptionFuzz(provider); + OHOS::GetParentTypeFuzz(provider); + OHOS::SetDelayInfoFuzz(provider); + OHOS::PushDelayDataFuzz(provider); + OHOS::GetBundleNameByUdKeyFuzz(provider); OHOS::TearDown(); return 0; } \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/fuzztest/utdclient_fuzzer/BUILD.gn b/udmf/framework/innerkitsimpl/test/fuzztest/utdclient_fuzzer/BUILD.gn index fffef2878ff29ea402b0f85ec4d45c1232bef6f8..04ce893cdd06e70c016818648d27e092f8ad3d66 100644 --- a/udmf/framework/innerkitsimpl/test/fuzztest/utdclient_fuzzer/BUILD.gn +++ b/udmf/framework/innerkitsimpl/test/fuzztest/utdclient_fuzzer/BUILD.gn @@ -36,7 +36,7 @@ ohos_fuzztest("UtdClientFuzzTest") { deps = [ "${udmf_interfaces_path}/innerkits:utd_client" ] - external_deps = [] + external_deps = [ "c_utils:utils" ] } ############################################################################### diff --git a/udmf/framework/innerkitsimpl/test/fuzztest/utdclient_fuzzer/utd_client_fuzzer.cpp b/udmf/framework/innerkitsimpl/test/fuzztest/utdclient_fuzzer/utd_client_fuzzer.cpp index 9e98e30bc82a3881de1184fe6e73a47d91703716..97d2b309084af60953a866e639081effe317d14f 100644 --- a/udmf/framework/innerkitsimpl/test/fuzztest/utdclient_fuzzer/utd_client_fuzzer.cpp +++ b/udmf/framework/innerkitsimpl/test/fuzztest/utdclient_fuzzer/utd_client_fuzzer.cpp @@ -16,6 +16,8 @@ #include "utd_client_fuzzer.h" #include "utd_client.h" +#include <fuzzer/FuzzedDataProvider.h> + using namespace OHOS; using namespace OHOS::UDMF; @@ -28,76 +30,76 @@ void TearDown() { } -void GetTypeDescriptorFuzz(const uint8_t *data, size_t size) +void GetTypeDescriptorFuzz(FuzzedDataProvider &provider) { - std::string typeId(data, data + size); + std::string typeId = provider.ConsumeRandomLengthString(); std::shared_ptr<TypeDescriptor> typeDescriptor; UtdClient::GetInstance().GetTypeDescriptor(typeId, typeDescriptor); } -void GetUniformDataTypeByFilenameExtensionDefaultBelongsFuzz(const uint8_t *data, size_t size) +void GetUniformDataTypeByFilenameExtensionDefaultBelongsFuzz(FuzzedDataProvider &provider) { - std::string fileExtension(data, data + size); + std::string fileExtension = provider.ConsumeRandomLengthString(); std::string typeId; UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(fileExtension, typeId); } -void GetUniformDataTypeByFilenameExtensionFuzz(const uint8_t *data, size_t size) +void GetUniformDataTypeByFilenameExtensionFuzz(FuzzedDataProvider &provider) { - std::string fileExtension(data, data + size); + std::string fileExtension = provider.ConsumeRandomLengthString(); std::string typeId; - std::string belongsTo(data, data + size); + std::string belongsTo = provider.ConsumeRandomLengthString(); UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(fileExtension, typeId, belongsTo); } -void GetUniformDataTypesByFilenameExtensionDefaultBelongsFuzz(const uint8_t *data, size_t size) +void GetUniformDataTypesByFilenameExtensionDefaultBelongsFuzz(FuzzedDataProvider &provider) { - std::string fileExtension(data, data + size); + std::string fileExtension = provider.ConsumeRandomLengthString(); std::vector<std::string> typeIds; UtdClient::GetInstance().GetUniformDataTypesByFilenameExtension(fileExtension, typeIds); } -void GetUniformDataTypesByFilenameExtensionFuzz(const uint8_t *data, size_t size) +void GetUniformDataTypesByFilenameExtensionFuzz(FuzzedDataProvider &provider) { - std::string fileExtension(data, data + size); + std::string fileExtension = provider.ConsumeRandomLengthString(); std::vector<std::string> typeIds; - std::string belongsTo(data, data + size); + std::string belongsTo = provider.ConsumeRandomLengthString(); UtdClient::GetInstance().GetUniformDataTypesByFilenameExtension(fileExtension, typeIds, belongsTo); } -void GetUniformDataTypeByMIMETypeDefaultBelongsFuzz(const uint8_t *data, size_t size) +void GetUniformDataTypeByMIMETypeDefaultBelongsFuzz(FuzzedDataProvider &provider) { - std::string mimeType(data, data + size); + std::string mimeType = provider.ConsumeRandomLengthString(); std::string typeId; UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, typeId); } -void GetUniformDataTypeByMIMETypeFuzz(const uint8_t *data, size_t size) +void GetUniformDataTypeByMIMETypeFuzz(FuzzedDataProvider &provider) { - std::string mimeType(data, data + size); + std::string mimeType = provider.ConsumeRandomLengthString(); std::string typeId; - std::string belongsTo(data, data + size); + std::string belongsTo = provider.ConsumeRandomLengthString(); UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, typeId, belongsTo); } -void GetUniformDataTypesByMIMETypeDefaultBelongsFuzz(const uint8_t *data, size_t size) +void GetUniformDataTypesByMIMETypeDefaultBelongsFuzz(FuzzedDataProvider &provider) { - std::string mimeType(data, data + size); + std::string mimeType = provider.ConsumeRandomLengthString(); std::vector<std::string> typeIds; UtdClient::GetInstance().GetUniformDataTypesByMIMEType(mimeType, typeIds); } -void GetUniformDataTypesByMIMETypeFuzz(const uint8_t *data, size_t size) +void GetUniformDataTypesByMIMETypeFuzz(FuzzedDataProvider &provider) { - std::string mimeType(data, data + size); + std::string mimeType = provider.ConsumeRandomLengthString(); std::vector<std::string> typeIds; - std::string belongsTo(data, data + size); + std::string belongsTo = provider.ConsumeRandomLengthString(); UtdClient::GetInstance().GetUniformDataTypesByMIMEType(mimeType, typeIds, belongsTo); } -void IsUtdFuzz(const uint8_t *data, size_t size) +void IsUtdFuzz(FuzzedDataProvider &provider) { - std::string typeId(data, data + size); + std::string typeId = provider.ConsumeRandomLengthString(); bool result; UtdClient::GetInstance().IsUtd(typeId, result); } @@ -107,16 +109,17 @@ void IsUtdFuzz(const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Run your code on data */ + FuzzedDataProvider provider(data, size); OHOS::SetUpTestCase(); - OHOS::GetTypeDescriptorFuzz(data, size); - OHOS::GetUniformDataTypeByFilenameExtensionDefaultBelongsFuzz(data, size); - OHOS::GetUniformDataTypeByFilenameExtensionFuzz(data, size); - OHOS::GetUniformDataTypesByFilenameExtensionDefaultBelongsFuzz(data, size); - OHOS::GetUniformDataTypesByFilenameExtensionFuzz(data, size); - OHOS::GetUniformDataTypeByMIMETypeDefaultBelongsFuzz(data, size); - OHOS::GetUniformDataTypeByMIMETypeFuzz(data, size); - OHOS::GetUniformDataTypesByMIMETypeDefaultBelongsFuzz(data, size); - OHOS::GetUniformDataTypesByMIMETypeFuzz(data, size); - OHOS::IsUtdFuzz(data, size); + OHOS::GetTypeDescriptorFuzz(provider); + OHOS::GetUniformDataTypeByFilenameExtensionDefaultBelongsFuzz(provider); + OHOS::GetUniformDataTypeByFilenameExtensionFuzz(provider); + OHOS::GetUniformDataTypesByFilenameExtensionDefaultBelongsFuzz(provider); + OHOS::GetUniformDataTypesByFilenameExtensionFuzz(provider); + OHOS::GetUniformDataTypeByMIMETypeDefaultBelongsFuzz(provider); + OHOS::GetUniformDataTypeByMIMETypeFuzz(provider); + OHOS::GetUniformDataTypesByMIMETypeDefaultBelongsFuzz(provider); + OHOS::GetUniformDataTypesByMIMETypeFuzz(provider); + OHOS::IsUtdFuzz(provider); return 0; } \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn b/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn index 6e4d149bd47dda92a9db9c623e8e50ea0065a1bc..8259e9e441342127cdf8be1c62552a9eea2d0517 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn +++ b/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn @@ -13,7 +13,7 @@ import("//build/test.gni") import("//foundation/distributeddatamgr/udmf/udmf.gni") -module_output_path = "udmf/innerkitsImpl" +module_output_path = "udmf/udmf/innerkitsImpl" ############################################################################### config("module_private_config") { @@ -21,11 +21,13 @@ config("module_private_config") { "${udmf_interfaces_path}/innerkits/client", "${udmf_interfaces_path}/innerkits/common", "${udmf_interfaces_path}/innerkits/data", + "${udmf_interfaces_path}/innerkits/dynamic", "${udmf_interfaces_path}/innerkits/convert", "${udmf_interfaces_path}/ndk/data", "${udmf_framework_path}/common", "${udmf_framework_path}/innerkitsimpl/data", "${udmf_framework_path}/innerkitsimpl/client/", + "${udmf_framework_path}/innerkitsimpl/service", "${udmf_framework_path}/innerkitsimpl/test/unittest/mock/include", "${udmf_framework_path}/ndkimpl/data", ] @@ -41,25 +43,24 @@ common_external_deps = [ "ability_base:base", "ability_base:want", "ability_base:zuri", + "ability_runtime:dataobs_manager", "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "access_token:libtoken_setproc", "app_file_service:fileuri_native", "bundle_framework:appexecfwk_core", "c_utils:utils", - "ffmpeg:libohosffmpeg", + "dfs_service:distributed_file_daemon_kit_inner", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", "hitrace:libhitracechain", "image_framework:image", - "image_framework:image", "image_framework:image_native", "image_framework:pixelmap", "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", - "libexif:libexif", "samgr:samgr_proxy", ] @@ -68,8 +69,12 @@ ohos_unittest("UdmfClientTest") { sources = [ "${udmf_framework_path}/common/graph.cpp", + "${udmf_framework_path}/common/udmf_copy_file.cpp", + "${udmf_framework_path}/common/udmf_executor.cpp", "${udmf_framework_path}/common/udmf_utils.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_async_client.cpp", "${udmf_framework_path}/innerkitsimpl/client/udmf_client.cpp", + "${udmf_framework_path}/innerkitsimpl/common/progress_queue.cpp", "${udmf_framework_path}/innerkitsimpl/convert/udmf_conversion.cpp", "${udmf_framework_path}/innerkitsimpl/data/application_defined_record.cpp", "${udmf_framework_path}/innerkitsimpl/data/audio.cpp", @@ -86,6 +91,9 @@ ohos_unittest("UdmfClientTest") { "${udmf_framework_path}/innerkitsimpl/data/text.cpp", "${udmf_framework_path}/innerkitsimpl/data/unified_data.cpp", "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", + "${udmf_framework_path}/innerkitsimpl/service/progress_callback.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_notifier_stub.cpp", "${udmf_framework_path}/innerkitsimpl/service/udmf_service_client.cpp", "${udmf_framework_path}/innerkitsimpl/service/udmf_service_proxy.cpp", "udmf_client_test.cpp", @@ -93,6 +101,56 @@ ohos_unittest("UdmfClientTest") { configs = [ ":module_private_config" ] + use_exceptions = true + + deps = common_deps + + external_deps = common_external_deps + + defines = [ + "private=public", + "protected=public", + ] +} + +ohos_unittest("UdmfClientFileMangerTest") { + module_out_path = module_output_path + + sources = [ + "${udmf_framework_path}/common/udmf_copy_file.cpp", + "${udmf_framework_path}/common/udmf_executor.cpp", + "${udmf_framework_path}/common/udmf_utils.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_async_client.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_client.cpp", + "${udmf_framework_path}/innerkitsimpl/common/progress_queue.cpp", + "${udmf_framework_path}/innerkitsimpl/convert/udmf_conversion.cpp", + "${udmf_framework_path}/innerkitsimpl/data/application_defined_record.cpp", + "${udmf_framework_path}/innerkitsimpl/data/audio.cpp", + "${udmf_framework_path}/innerkitsimpl/data/file.cpp", + "${udmf_framework_path}/innerkitsimpl/data/folder.cpp", + "${udmf_framework_path}/innerkitsimpl/data/html.cpp", + "${udmf_framework_path}/innerkitsimpl/data/image.cpp", + "${udmf_framework_path}/innerkitsimpl/data/link.cpp", + "${udmf_framework_path}/innerkitsimpl/data/plain_text.cpp", + "${udmf_framework_path}/innerkitsimpl/data/system_defined_appitem.cpp", + "${udmf_framework_path}/innerkitsimpl/data/system_defined_form.cpp", + "${udmf_framework_path}/innerkitsimpl/data/system_defined_pixelmap.cpp", + "${udmf_framework_path}/innerkitsimpl/data/system_defined_record.cpp", + "${udmf_framework_path}/innerkitsimpl/data/text.cpp", + "${udmf_framework_path}/innerkitsimpl/data/unified_data.cpp", + "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", + "${udmf_framework_path}/innerkitsimpl/service/progress_callback.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_notifier_stub.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_service_client.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_service_proxy.cpp", + "udmf_client_file_manger_test.cpp", + ] + + configs = [ ":module_private_config" ] + + use_exceptions = true + deps = common_deps external_deps = common_external_deps @@ -149,7 +207,42 @@ ohos_unittest("UdmfClientSaInvokeTest") { ohos_unittest("UdmfAsyncClientTest") { module_out_path = module_output_path - sources = [ "udmf_async_client_test.cpp" ] + configs = [ ":module_private_config" ] + + sources = [ + "udmf_async_client_test.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_async_client.cpp", + "${udmf_framework_path}/innerkitsimpl/common/progress_queue.cpp", + "${udmf_framework_path}/common/udmf_executor.cpp", + "${udmf_framework_path}/innerkitsimpl/service/progress_callback.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_client.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_service_client.cpp", + "${udmf_framework_path}/innerkitsimpl/data/unified_data.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_notifier_stub.cpp", + "${udmf_framework_path}/common/udmf_copy_file.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_service_proxy.cpp", + "${udmf_framework_path}/innerkitsimpl/convert/udmf_conversion.cpp", + "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + ] + + deps = [ + "${udmf_interfaces_path}/innerkits:udmf_client", + "${udmf_interfaces_path}/innerkits:utd_client", + "${udmf_interfaces_path}/ndk:libudmf" + ] + + external_deps = common_external_deps + + defines = [ + "private=public", + "protected=public", + ] +} + +ohos_unittest("UdmfDelayDataTest") { + module_out_path = module_output_path + + sources = [ "udmf_delay_data_test.cpp" ] deps = common_deps @@ -193,10 +286,50 @@ ohos_unittest("UtdClientTest") { ] } +ohos_unittest("UtdConcurrentUpdateTest") { + module_out_path = module_output_path + + sources = [ + "${udmf_framework_path}/common/base32_utils.cpp", + "${udmf_framework_path}/common/custom_utd_json_parser.cpp", + "${udmf_framework_path}/common/custom_utd_store.cpp", + "${udmf_framework_path}/common/graph.cpp", + "${udmf_framework_path}/common/udmf_utils.cpp", + "${udmf_framework_path}/common/utd_cfgs_checker.cpp", + "${udmf_framework_path}/common/utd_graph.cpp", + "${udmf_framework_path}/innerkitsimpl/client/utd_client.cpp", + "${udmf_framework_path}/innerkitsimpl/data/flexible_type.cpp", + "${udmf_framework_path}/innerkitsimpl/data/preset_type_descriptors.cpp", + "${udmf_framework_path}/innerkitsimpl/data/type_descriptor.cpp", + "utd_concurrent_update_test.cpp", + ] + + configs = [ ":module_private_config" ] + + use_exceptions = true + + external_deps = common_external_deps + external_deps += [ + "cJSON:cjson", + "os_account:os_account_innerkits", + ] + + defines = [ + "private=public", + "protected=public", + ] +} + ohos_unittest("NdkDataConversionTest") { module_out_path = module_output_path - sources = [ "ndk_data_conversion_test.cpp" ] + sources = [ + "${udmf_framework_path}/innerkitsimpl/data/system_defined_pixelmap.cpp", + "${udmf_framework_path}/innerkitsimpl/data/system_defined_record.cpp", + "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", + "ndk_data_conversion_test.cpp", + ] configs = [ ":module_private_config" ] @@ -399,6 +532,27 @@ ohos_unittest("PlainTextTest") { ] } +ohos_unittest("PresetTypeDescriptorsTest") { + module_out_path = module_output_path + + sources = [ + "${udmf_framework_path}/common/custom_utd_json_parser.cpp", + "${udmf_framework_path}/innerkitsimpl/data/preset_type_descriptors.cpp", + "preset_type_descriptor_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = common_deps + + external_deps = common_external_deps + + defines = [ + "private=public", + "protected=public", + ] +} + ohos_unittest("SystemDefinedAppitemTest") { module_out_path = module_output_path @@ -406,6 +560,7 @@ ohos_unittest("SystemDefinedAppitemTest") { "${udmf_framework_path}/innerkitsimpl/data/system_defined_appitem.cpp", "${udmf_framework_path}/innerkitsimpl/data/system_defined_record.cpp", "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", "system_defined_appitem_test.cpp", ] @@ -450,6 +605,7 @@ ohos_unittest("SystemDefinedPixelMapTest") { "${udmf_framework_path}/innerkitsimpl/data/system_defined_pixelmap.cpp", "${udmf_framework_path}/innerkitsimpl/data/system_defined_record.cpp", "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", "system_defined_pixelmap_test.cpp", ] @@ -600,17 +756,36 @@ ohos_unittest("UnifiedMetaTest") { ] } +ohos_unittest("UnifiedKeyTest") { + module_out_path = module_output_path + + sources = [ "unified_key_test.cpp" ] + + deps = common_deps + + external_deps = common_external_deps + + defines = [ + "private=public", + "protected=public", + ] +} + ohos_unittest("UdmfClientAbnormalTest") { module_out_path = module_output_path sources = [ "${udmf_framework_path}/common/endian_converter.cpp", "${udmf_framework_path}/common/tlv_util.cpp", + "${udmf_framework_path}/common/udmf_copy_file.cpp", + "${udmf_framework_path}/common/udmf_executor.cpp", "${udmf_framework_path}/common/udmf_radar_reporter.cpp", "${udmf_framework_path}/common/udmf_types_util.cpp", "${udmf_framework_path}/common/udmf_utils.cpp", "${udmf_framework_path}/innerkitsimpl/client/getter_system.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_async_client.cpp", "${udmf_framework_path}/innerkitsimpl/client/udmf_client.cpp", + "${udmf_framework_path}/innerkitsimpl/common/progress_queue.cpp", "${udmf_framework_path}/innerkitsimpl/common/unified_key.cpp", "${udmf_framework_path}/innerkitsimpl/common/unified_meta.cpp", "${udmf_framework_path}/innerkitsimpl/convert/udmf_conversion.cpp", @@ -630,6 +805,9 @@ ohos_unittest("UdmfClientAbnormalTest") { "${udmf_framework_path}/innerkitsimpl/data/unified_html_record_process.cpp", "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", "${udmf_framework_path}/innerkitsimpl/data/video.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", + "${udmf_framework_path}/innerkitsimpl/service/progress_callback.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_notifier_stub.cpp", "${udmf_framework_path}/innerkitsimpl/service/udmf_service_proxy.cpp", "${udmf_framework_path}/innerkitsimpl/test/unittest/mock/system_defined_pixelmap_mock.cpp", "${udmf_framework_path}/innerkitsimpl/test/unittest/mock/tlv_object_mock.cpp", @@ -639,14 +817,17 @@ ohos_unittest("UdmfClientAbnormalTest") { configs = [ ":module_private_config" ] - deps = [ - "${udmf_interfaces_path}/innerkits:utd_client", - "//third_party/googletest:gmock_main", - "//third_party/googletest:gtest_main", - ] + use_exceptions = true + + deps = [ "${udmf_interfaces_path}/innerkits:utd_client" ] external_deps = common_external_deps + external_deps += [ + "googletest:gmock_main", + "googletest:gtest_main", + ] + defines = [ "private=public", "protected=public", @@ -668,22 +849,27 @@ group("unittest") { ":LinkTest", ":NdkDataConversionTest", ":PlainTextTest", + ":PresetTypeDescriptorsTest", ":SystemDefinedAppitemTest", ":SystemDefinedFormTest", ":SystemDefinedPixelMapTest", ":SystemDefinedRecordTest", ":TextTest", + ":UnifiedKeyTest", ":UdmfAsyncClientTest", ":UdmfClientAbnormalTest", + ":UdmfClientFileMangerTest", ":UdmfClientHapPermissionTest", ":UdmfClientSaInvokeTest", ":UdmfClientSystemHapTest", ":UdmfClientTest", + ":UdmfDelayDataTest", ":UnifiedDataHelperTest", ":UnifiedDataTest", ":UnifiedMetaTest", ":UnifiedRecordTest", ":UtdClientTest", + ":UtdConcurrentUpdateTest", ":VideoTest", ] } diff --git a/udmf/framework/innerkitsimpl/test/unittest/custom_utd_store_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/custom_utd_store_test.cpp index 9cd67523b15c5a2cbe8b168f97d30b6a4a9ff52a..3931a2dc3ed02a2e85b8ba39f014d03e93c3ed09 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/custom_utd_store_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/custom_utd_store_test.cpp @@ -99,7 +99,7 @@ HWTEST_F(CustomUtdStoreTest, SaveTypeCfgs001, TestSize.Level1) EXPECT_EQ(status, E_OK); typesCfg.clear(); - typesCfg = CustomUtdStore::GetInstance().GetTypeCfgs(USERID); + typesCfg = CustomUtdStore::GetInstance().GetCustomUtd(false, USERID); TypeDescriptorCfg type1 = *(typesCfg.begin()); EXPECT_EQ(type1.typeId, "com.example.utdtest.document"); EXPECT_EQ(*(type1.belongingToTypes.begin()), "com.example.utdtest2.document"); @@ -113,4 +113,284 @@ HWTEST_F(CustomUtdStoreTest, SaveTypeCfgs001, TestSize.Level1) LOG_INFO(UDMF_TEST, "SaveTypeCfgs001 end."); } + +/** +* @tc.name: GetCustomUtdPathTest001 +* @tc.desc: GetCustomUtdPath +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, GetCustomUtdPathTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetCustomUtdPathTest001 begin."); + + std::string path = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + EXPECT_EQ(path, "/data/service/el1/1000000/utdtypes/utd/utd-adt.json"); + + LOG_INFO(UDMF_TEST, "GetCustomUtdPathTest001 end."); +} + +/** +* @tc.name: GetCustomUtdPathTest002 +* @tc.desc: GetCustomUtdPath +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, GetCustomUtdPathTest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetCustomUtdPathTest002 begin."); + + std::string path = CustomUtdStore::GetInstance().GetCustomUtdPath(true, USERID); + EXPECT_EQ(path, "/data/utd/utd-adt.json"); + + LOG_INFO(UDMF_TEST, "GetCustomUtdPathTest002 end."); +} + +/** +* @tc.name: GetCustomUtdInfoTest001 +* @tc.desc: GetCustomUtdInfo +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, GetCustomUtdInfoTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetCustomUtdInfoTest001 begin."); + + UtdFileInfo info = CustomUtdStore::GetInstance().GetCustomUtdInfo(true, USERID); + EXPECT_EQ(info.size, 0); + + LOG_INFO(UDMF_TEST, "GetCustomUtdInfoTest001 end."); +} + +/** +* @tc.name: GetCustomUtdInfoTest002 +* @tc.desc: GetCustomUtdInfo +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, GetCustomUtdInfoTest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetCustomUtdInfoTest002 begin."); + + UtdFileInfo info = CustomUtdStore::GetInstance().GetCustomUtdInfo(false, USERID); + EXPECT_EQ(info.size, strlen(TEST_DATA2) + 2); + auto customUtds = CustomUtdStore::GetInstance().GetCustomUtd(false, USERID); + EXPECT_EQ(customUtds.size(), 2); + + LOG_INFO(UDMF_TEST, "GetCustomUtdInfoTest002 end."); +} + +/** +* @tc.name: ParseStoredCustomUtdJson001 +* @tc.desc: empty json +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, ParseStoredCustomUtdJson001, TestSize.Level1) { + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson001 begin."); + CustomUtdJsonParser parser; + std::vector<TypeDescriptorCfg> typesCfg; + bool ret = parser.ParseStoredCustomUtdJson("", typesCfg); + + EXPECT_FALSE(ret); + EXPECT_TRUE(typesCfg.empty()); + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson001 end."); +} + +/** +* @tc.name: ParseStoredCustomUtdJson002 +* @tc.desc: Invalid Format +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, ParseStoredCustomUtdJson002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson002 begin."); + const std::string invalidJson = R"({ + "UniformDataTypeDeclarations": [] + )"; // syntax error + + CustomUtdJsonParser parser; + std::vector<TypeDescriptorCfg> typesCfg; + bool ret = parser.ParseStoredCustomUtdJson(invalidJson, typesCfg); + + EXPECT_FALSE(ret); + EXPECT_TRUE(typesCfg.empty()); + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson002 end."); +} + +/** +* @tc.name: ParseStoredCustomUtdJson003 +* @tc.desc: invalid json +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, ParseStoredCustomUtdJson003, TestSize.Level1) { + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson003 begin."); + CustomUtdJsonParser parser; + std::vector<TypeDescriptorCfg> typesCfg; + std::string invalidJson = "{invalid_json}"; + EXPECT_FALSE(parser.ParseStoredCustomUtdJson(invalidJson, typesCfg)); + EXPECT_TRUE(typesCfg.empty()); + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson003 end."); +} + +/** +* @tc.name: ParseStoredCustomUtdJson004 +* @tc.desc: root not object +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, ParseStoredCustomUtdJson004, TestSize.Level1) { + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson004 begin."); + const std::string rootArrayJson = R"([ + { "TypeId": "com.example.custom.image" } + ])"; + + CustomUtdJsonParser parser; + std::vector<TypeDescriptorCfg> typesCfg; + bool ret = parser.ParseStoredCustomUtdJson(rootArrayJson, typesCfg); + + EXPECT_FALSE(ret); + EXPECT_TRUE(typesCfg.empty()); + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson004 end."); +} + +/** +* @tc.name: ParseStoredCustomUtdJson005 +* @tc.desc: valid json +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, ParseStoredCustomUtdJson005, TestSize.Level1) { + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson005 begin."); + + const std::string validJson = R"({ + "CustomUTDs": [ + { + "TypeId": "com.example.custom.image", + "BelongingToTypes": ["general.image"], + "FilenameExtensions": [".img", ".pic"], + "MIMETypes": ["application/img", "application/pic"], + "Description": "Custom image type", + "ReferenceURL": "" + } + ] + })"; + + CustomUtdJsonParser parser; + std::vector<TypeDescriptorCfg> typesCfg; + bool ret = parser.ParseStoredCustomUtdJson(validJson, typesCfg); + + EXPECT_TRUE(ret); + ASSERT_EQ(typesCfg.size(), 1u); + EXPECT_EQ(typesCfg[0].typeId, "com.example.custom.image"); + EXPECT_EQ(typesCfg[0].belongingToTypes.size(), 1u); + EXPECT_EQ(typesCfg[0].belongingToTypes[0], "general.image"); + + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson005 end."); +} + +/** + * @tc.name: ParseUserCustomUtdJsonTest001 + * @tc.desc: parse a valid JSON containing declarations and references. + * @tc.type: FUNC + */ +HWTEST_F(CustomUtdStoreTest, ParseUserCustomUtdJsonTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ParseUserCustomUtdJsonTest001 begin."); + const char *testJson = R"({ + "UniformDataTypeDeclarations": [ + { + "TypeId": "com.example.thread.image", + "BelongingToTypes": ["general.image"], + "FilenameExtensions": [".myImage", ".khImage"], + "MIMETypes": ["application/myImage", "application/khImage"], + "Description": "My Image.", + "ReferenceURL": "" + } + ], + "ReferenceUniformDataTypeDeclarations": [ + { + "TypeId": "com.example.thread.audio", + "BelongingToTypes": ["general.audio"], + "FilenameExtensions": [".myAudio", ".khAudio"], + "MIMETypes": ["application/myAudio", "application/khAudio"], + "Description": "My audio.", + "ReferenceURL": "" + } + ] + })"; + + std::vector<TypeDescriptorCfg> declarations; + std::vector<TypeDescriptorCfg> references; + + CustomUtdJsonParser parser; + bool result = parser.ParseUserCustomUtdJson(testJson, declarations, references); + + EXPECT_TRUE(result); + EXPECT_EQ(declarations.size(), 1); + EXPECT_EQ(references.size(), 1); + + EXPECT_EQ(declarations[0].typeId, "com.example.thread.image"); + EXPECT_EQ(references[0].typeId, "com.example.thread.audio"); + LOG_INFO(UDMF_TEST, "ParseUserCustomUtdJsonTest001 end."); +} + +/** + * @tc.name: ParseUserCustomUtdJsonTest002 + * @tc.desc: Verify ParseUserCustomUtdJson returns false when given empty JSON string. + * @tc.type: FUNC + */ +HWTEST_F(CustomUtdStoreTest, ParseUserCustomUtdJsonTest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ParseUserCustomUtdJsonTest002 begin."); + std::vector<TypeDescriptorCfg> declarations; + std::vector<TypeDescriptorCfg> references; + + CustomUtdJsonParser parser; + bool result = parser.ParseUserCustomUtdJson("", declarations, references); + + EXPECT_FALSE(result); + EXPECT_TRUE(declarations.empty()); + EXPECT_TRUE(references.empty()); + LOG_INFO(UDMF_TEST, "ParseUserCustomUtdJsonTest002 end."); +} + +/** + * @tc.name: ParseUserCustomUtdJsonTest003 + * @tc.desc: Verify ParseUserCustomUtdJson returns false for invalid JSON format. + * @tc.type: FUNC + */ +HWTEST_F(CustomUtdStoreTest, ParseUserCustomUtdJsonTest003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ParseUserCustomUtdJsonTest003 begin."); + const char *invalidJson = R"({ "UniformDataTypeDeclarations": [ )"; + + std::vector<TypeDescriptorCfg> declarations; + std::vector<TypeDescriptorCfg> references; + + CustomUtdJsonParser parser; + bool result = parser.ParseUserCustomUtdJson(invalidJson, declarations, references); + + EXPECT_FALSE(result); + EXPECT_TRUE(declarations.empty()); + EXPECT_TRUE(references.empty()); + LOG_INFO(UDMF_TEST, "ParseUserCustomUtdJsonTest003 end."); +} + +/** + * @tc.name: ParseUserCustomUtdJsonTest004 + * @tc.desc: Verify ParseUserCustomUtdJson returns false for invalid JSON format. + * @tc.type: FUNC + */ +HWTEST_F(CustomUtdStoreTest, ParseUserCustomUtdJsonTest004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ParseUserCustomUtdJsonTest004 begin."); + const char *invalidJson = R"([ + { "TypeId": "com.example.custom.image" } + ])"; + + std::vector<TypeDescriptorCfg> declarations; + std::vector<TypeDescriptorCfg> references; + + CustomUtdJsonParser parser; + bool result = parser.ParseUserCustomUtdJson(invalidJson, declarations, references); + + EXPECT_FALSE(result); + EXPECT_TRUE(declarations.empty()); + EXPECT_TRUE(references.empty()); + LOG_INFO(UDMF_TEST, "ParseUserCustomUtdJsonTest004 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/graph_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/graph_test.cpp index b453d4635db14a1abbe162358beb44f915a56233..1b8c2935131e7fe8c11543f8e04233bc60062327 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/graph_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/graph_test.cpp @@ -282,7 +282,7 @@ HWTEST_F(GraphTest, DfsHasData001, TestSize.Level1) for (uint32_t i = 0; i < edges.size(); i++) { graph.AddEdge(edges[i][0], edges[i][1]); } - + bool isFind = false; graph.Dfs(TestNodes::POINT_A, [&](uint32_t currNode) -> bool { if (currNode == TestNodes::POINT_H) { diff --git a/udmf/framework/innerkitsimpl/test/unittest/mock/include/udmf_service_client_mock.h b/udmf/framework/innerkitsimpl/test/unittest/mock/include/udmf_service_client_mock.h index db9c45a508165d9a029e08b6b03b78afec7dc7fa..9326e2cfac2fa33c57bb509dd057cc58632028e1 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/mock/include/udmf_service_client_mock.h +++ b/udmf/framework/innerkitsimpl/test/unittest/mock/include/udmf_service_client_mock.h @@ -43,6 +43,10 @@ public: virtual int32_t RemoveAppShareOption(const std::string &) = 0; virtual int32_t ObtainAsynProcess(AsyncProcessInfo&) = 0; virtual int32_t ClearAsynProcessByKey(const std::string &businessUdKey) = 0; + virtual int32_t SetDelayInfo(const DataLoadInfo &, sptr<IRemoteObject>, std::string &) = 0; + virtual int32_t PushDelayData(const std::string &, const UnifiedData &) = 0; + virtual int32_t GetDataIfAvailable(const std::string &key, const DataLoadInfo &, sptr<IRemoteObject>, + std::shared_ptr<UnifiedData>) = 0; public: static inline std::shared_ptr<MUdmfServiceClient> udmfServiceClient = nullptr; }; @@ -64,6 +68,10 @@ public: MOCK_METHOD(int32_t, RemoveAppShareOption, (const std::string &)); MOCK_METHOD(int32_t, ObtainAsynProcess, (AsyncProcessInfo&)); MOCK_METHOD(int32_t, ClearAsynProcessByKey, (const std::string &)); + MOCK_METHOD(int32_t, SetDelayInfo, (const DataLoadInfo &, sptr<IRemoteObject>, std::string &)); + MOCK_METHOD(int32_t, PushDelayData, (const std::string &, const UnifiedData &)); + MOCK_METHOD(int32_t, GetDataIfAvailable, (const std::string &, const DataLoadInfo &, sptr<IRemoteObject>, + std::shared_ptr<UnifiedData>)); }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/test/unittest/mock/udmf_service_client_mock.cpp b/udmf/framework/innerkitsimpl/test/unittest/mock/udmf_service_client_mock.cpp index 9239fa589d56556085ec1de86f59fd6680042c7a..0dd88555db95360c9c39b36bb606068abf099e64 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/mock/udmf_service_client_mock.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/mock/udmf_service_client_mock.cpp @@ -152,4 +152,33 @@ int32_t UdmfServiceClient::ObtainAsynProcess(AsyncProcessInfo &processInfo) return MUdmfServiceClient::udmfServiceClient->ObtainAsynProcess(processInfo); } } + +int32_t UdmfServiceClient::SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptr<IRemoteObject> iUdmfNotifier, + std::string &key) +{ + if (MUdmfServiceClient::udmfServiceClient == nullptr) { + return -1; + } else { + return MUdmfServiceClient::udmfServiceClient->SetDelayInfo(dataLoadInfo, iUdmfNotifier, key); + } +} + +int32_t UdmfServiceClient::PushDelayData(const std::string &key, UnifiedData &unifiedData) +{ + if (MUdmfServiceClient::udmfServiceClient == nullptr) { + return -1; + } else { + return MUdmfServiceClient::udmfServiceClient->PushDelayData(key, unifiedData); + } +} + +int32_t UdmfServiceClient::GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr<IRemoteObject> iUdmfNotifier, std::shared_ptr<UnifiedData> unifiedData) +{ + if (MUdmfServiceClient::udmfServiceClient == nullptr) { + return -1; + } else { + return MUdmfServiceClient::udmfServiceClient->GetDataIfAvailable(key, dataLoadInfo, iUdmfNotifier, unifiedData); + } +} } // namespace OHOS::UDMF diff --git a/udmf/framework/innerkitsimpl/test/unittest/ndk_data_conversion_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/ndk_data_conversion_test.cpp index 082398dbe30d57a335d04c2a8f00172f8f11a42a..e09d58cd8fb1dd74680013bd36572ab7f1605cbd 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/ndk_data_conversion_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/ndk_data_conversion_test.cpp @@ -356,26 +356,21 @@ HWTEST_F(NdkDataConversionTest, ConvertPixelMap_002, TestSize.Level1) HWTEST_F(NdkDataConversionTest, ConvertPixelMap_003, TestSize.Level1) { LOG_INFO(UDMF_TEST, "ConvertPixelMap_003 begin."); - uint32_t color[100] = { 3, 7, 9, 9, 7, 6 }; + uint32_t color[35] = { 3, 7, 9, 9, 7, 6 }; OHOS::Media::InitializationOptions opts = { { 5, 7 }, Media::PixelFormat::ARGB_8888, Media::PixelFormat::ARGB_8888 }; std::unique_ptr<OHOS::Media::PixelMap> pixelMap = OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); std::shared_ptr<OHOS::Media::PixelMap> pixelMapIn = move(pixelMap); - std::vector<uint8_t> buff; - pixelMapIn->EncodeTlv(buff); + auto systemDefinedPixelMap = std::make_shared<SystemDefinedPixelMap>(UDType::SYSTEM_DEFINED_PIXEL_MAP, pixelMapIn); - std::shared_ptr<SystemDefinedPixelMap> systemDefinedPixelMap = - std::make_shared<SystemDefinedPixelMap>(UDType::SYSTEM_DEFINED_PIXEL_MAP, buff); UnifiedData data; - std::vector<std::shared_ptr<UnifiedRecord>> records = { systemDefinedPixelMap }; - data.SetRecords(records); + data.AddRecord(systemDefinedPixelMap); std::string key; CustomOption option = { .intention = UD_INTENTION_DRAG }; auto setRet = UdmfClient::GetInstance().SetData(option, data, key); EXPECT_EQ(setRet, E_OK); - std::shared_ptr<UnifiedData> readData = std::make_shared<UnifiedData>(); QueryOption query = { .key = key }; auto getRet = UdmfClient::GetInstance().GetData(query, *readData); @@ -392,16 +387,14 @@ HWTEST_F(NdkDataConversionTest, ConvertPixelMap_003, TestSize.Level1) auto type = OH_UdsPixelMap_GetType(pixelMapUds); EXPECT_EQ(std::string(type), std::string(UDMF_META_OPENHARMONY_PIXEL_MAP)); + uint32_t color2[100] = { 3, 7, 9, 9, 7, 6 }; OHOS::Media::InitializationOptions opts2 = { { 10, 10 }, Media::PixelFormat::ARGB_8888, Media::PixelFormat::ARGB_8888 }; - std::unique_ptr<OHOS::Media::PixelMap> pixelMap2 = - OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts2); - + auto pixelMap2 = OHOS::Media::PixelMap::Create(color2, sizeof(color) / sizeof(color[0]), opts2); OH_PixelmapNative *ohPixelmapNative = new OH_PixelmapNative(std::move(pixelMap2)); OH_UdsPixelMap_GetPixelMap(pixelMapUds, ohPixelmapNative); auto resultPixelMap = ohPixelmapNative->GetInnerPixelmap(); - auto height = resultPixelMap->GetHeight(); - EXPECT_EQ(height, 7); + EXPECT_EQ(resultPixelMap->GetHeight(), 7); OH_UdsPixelMap_Destroy(pixelMapUds); OH_UdmfData_Destroy(ndkData); @@ -409,6 +402,56 @@ HWTEST_F(NdkDataConversionTest, ConvertPixelMap_003, TestSize.Level1) LOG_INFO(UDMF_TEST, "ConvertPixelMap_003 end."); } +/* * + * @tc.name: ConvertPixelMap_004 + * @tc.desc: test pixel-map conversion between UDS and C-API + * @tc.type: FUNC + */ +HWTEST_F(NdkDataConversionTest, ConvertPixelMap_004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ConvertPixelMap_004 begin."); + uint32_t color[35] = { 3, 7, 9, 9, 7, 6 }; + OHOS::Media::InitializationOptions opts = { { 5, 7 }, + Media::PixelFormat::ARGB_8888, Media::PixelFormat::ARGB_8888 }; + std::unique_ptr<OHOS::Media::PixelMap> pixelMap = + OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr<OHOS::Media::PixelMap> pixelMapIn = move(pixelMap); + + auto pixelMapUds = OH_UdsPixelMap_Create(); + OH_PixelmapNative *ohPixelmapNative = new OH_PixelmapNative(pixelMapIn); + OH_UdsPixelMap_SetPixelMap(pixelMapUds, ohPixelmapNative); + auto record = OH_UdmfRecord_Create(); + OH_UdmfRecord_AddPixelMap(record, pixelMapUds); + auto data = OH_UdmfData_Create(); + OH_UdmfData_AddRecord(data, record); + std::shared_ptr<UnifiedData> unifiedData = std::make_shared<UnifiedData>(); + auto conversionStatus = NdkDataConversion::GetNativeUnifiedData(data, unifiedData); + EXPECT_EQ(conversionStatus, E_OK); + std::string key; + CustomOption option = {.intention = UD_INTENTION_DRAG}; + auto setRet = UdmfClient::GetInstance().SetData(option, *unifiedData, key); + EXPECT_EQ(setRet, E_OK); + std::shared_ptr<UnifiedData> readData = std::make_shared<UnifiedData>(); + QueryOption query = {.key = key}; + auto getRet = UdmfClient::GetInstance().GetData(query, *readData); + EXPECT_EQ(getRet, E_OK); + + auto readRecord = readData->GetRecordAt(0); + auto value = readRecord->GetEntry(UDMF_META_OPENHARMONY_PIXEL_MAP); + ASSERT_TRUE(std::holds_alternative<std::shared_ptr<Object>>(value)); + auto obj = std::get<std::shared_ptr<Object>>(value); + std::shared_ptr<Media::PixelMap> getPixelMap = nullptr; + ASSERT_TRUE(obj->GetValue(PIXEL_MAP, getPixelMap)); + ASSERT_NE(getPixelMap, nullptr); + ASSERT_EQ(getPixelMap->GetHeight(), pixelMapIn->GetHeight()); + ASSERT_EQ(getPixelMap->GetByteCount(), pixelMapIn->GetByteCount()); + OH_UdsPixelMap_Destroy(pixelMapUds); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(data); + delete ohPixelmapNative; + LOG_INFO(UDMF_TEST, "ConvertPixelMap_004 end."); +} + /* * * @tc.name: ConvertApplicationDefined_001 * @tc.desc: test application defined record conversion between JS and C-API diff --git a/udmf/framework/innerkitsimpl/test/unittest/preset_type_descriptor_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/preset_type_descriptor_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ce825ff005527e1ef9ffc3e9d8e86678bd91247 --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/unittest/preset_type_descriptor_test.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2025 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 "PlainTextTest" + +#include <gtest/gtest.h> +#include "preset_type_descriptors.h" +#include "logger.h" + +using namespace testing::ext; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { +using namespace std; + +class PresetTypeDescriptorsTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void PresetTypeDescriptorsTest::SetUpTestCase() +{ +} + +void PresetTypeDescriptorsTest::TearDownTestCase() +{ +} + +void PresetTypeDescriptorsTest::SetUp() +{ +} + +void PresetTypeDescriptorsTest::TearDown() +{ +} + +/** +* @tc.name: TestDoubleInit +* @tc.desc: Test double init utd list. +* @tc.type: FUNC +*/ +HWTEST_F(PresetTypeDescriptorsTest, TestDoubleInit, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "TestDoubleInit begin."); + PresetTypeDescriptors &instance = PresetTypeDescriptors::GetInstance(); + auto presetTypes = instance.GetPresetTypes(); + auto sizeFirst = presetTypes.size(); + EXPECT_GT(sizeFirst, 0); + instance.InitDescriptors(); + presetTypes = instance.GetPresetTypes(); + auto sizeSecond = presetTypes.size(); + EXPECT_EQ(sizeSecond, sizeFirst); + LOG_INFO(UDMF_TEST, "TestDoubleInit end."); +} +} // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/system_defined_form_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/system_defined_form_test.cpp index c8ffed727adeae19a4765d5c058dce12439c291f..3ac95fbc5b2f088f0fd069f9e5f513e2a0cc19e4 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/system_defined_form_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/system_defined_form_test.cpp @@ -65,4 +65,88 @@ HWTEST_F(SystemDefinedFormTest, SystemDefinedForm001, TestSize.Level1) EXPECT_EQ(systemDefinedForm.dataType_, SYSTEM_DEFINED_FORM); LOG_INFO(UDMF_TEST, "SystemDefinedForm001 end."); } + +/** +* @tc.name: SystemDefinedFormSetItem001 +* @tc.desc: Normal testcase of SystemDefinedForm +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedFormTest, SystemDefinedFormSetItem001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SystemDefinedFormSetItem001 begin."); + std::shared_ptr<Object> obj = std::make_shared<Object>(); + obj->value_[FORMID] = 1; + obj->value_[FORMNAME] = "formName"; + obj->value_[BUNDLE_NAME] = "bundleName"; + obj->value_[ABILITY_NAME] = "abilityName"; + obj->value_[MODULE] = "module"; + SystemDefinedForm systemDefinedForm(SYSTEM_DEFINED_FORM, obj); + UDDetails details; + details[FORMID] = 2; + details[FORMNAME] = "formName1"; + details[BUNDLE_NAME] = "bundleName1"; + details[ABILITY_NAME] = "abilityName1"; + details[MODULE] = "module1"; + systemDefinedForm.SetItems(details); + EXPECT_EQ(systemDefinedForm.GetFormId(), 2); + EXPECT_EQ(systemDefinedForm.GetFormName(), "formName1"); + EXPECT_EQ(systemDefinedForm.GetBundleName(), "bundleName1"); + EXPECT_EQ(systemDefinedForm.GetAbilityName(), "abilityName1"); + EXPECT_EQ(systemDefinedForm.GetModule(), "module1"); + LOG_INFO(UDMF_TEST, "SystemDefinedFormSetItem001 end."); +} + +/** +* @tc.name: SystemDefinedFormSetItem002 +* @tc.desc: Abnormal testcase of SystemDefinedForm +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedFormTest, SystemDefinedFormSetItem002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SystemDefinedFormSetItem002 begin."); + std::shared_ptr<Object> obj = std::make_shared<Object>(); + obj->value_[FORMID] = 1; + obj->value_[FORMNAME] = "formName"; + obj->value_[BUNDLE_NAME] = "bundleName"; + obj->value_[ABILITY_NAME] = "abilityName"; + obj->value_[MODULE] = "module"; + SystemDefinedForm systemDefinedForm(SYSTEM_DEFINED_FORM, obj); + UDDetails details; + details[FORMID] = true; + details[FORMNAME] = 2.1; + details[BUNDLE_NAME] = false; + details[ABILITY_NAME] = "abilityName1"; + details[MODULE] = "module1"; + systemDefinedForm.SetItems(details); + EXPECT_EQ(systemDefinedForm.GetFormId(), 1); + EXPECT_EQ(systemDefinedForm.GetFormName(), "formName"); + EXPECT_EQ(systemDefinedForm.GetBundleName(), "bundleName"); + EXPECT_EQ(systemDefinedForm.GetAbilityName(), "abilityName1"); + EXPECT_EQ(systemDefinedForm.GetModule(), "module1"); + LOG_INFO(UDMF_TEST, "SystemDefinedFormSetItem002 end."); +} + +/** +* @tc.name: SystemDefinedFormGetItem001 +* @tc.desc: Normal testcase of SystemDefinedForm GetItem +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedFormTest, SystemDefinedFormGetItem001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SystemDefinedForm001 begin."); + std::shared_ptr<Object> obj = std::make_shared<Object>(); + obj->value_[FORMID] = 1; + obj->value_[FORMNAME] = "formName"; + obj->value_[BUNDLE_NAME] = "bundleName"; + obj->value_[ABILITY_NAME] = "abilityName"; + obj->value_[MODULE] = "module"; + SystemDefinedForm systemDefinedForm(SYSTEM_DEFINED_FORM, obj); + UDDetails details = systemDefinedForm.GetItems(); + EXPECT_EQ(std::get<std::int32_t>(details[FORMID]), 1); + EXPECT_EQ(std::get<std::string>(details[FORMNAME]), "formName"); + EXPECT_EQ(std::get<std::string>(details[BUNDLE_NAME]), "bundleName"); + EXPECT_EQ(std::get<std::string>(details[ABILITY_NAME]), "abilityName"); + EXPECT_EQ(std::get<std::string>(details[MODULE]), "module"); + LOG_INFO(UDMF_TEST, "SystemDefinedFormGetItem001 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/system_defined_pixelmap_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/system_defined_pixelmap_test.cpp index 1b881c8cf0581296be61300e0539acef4a875621..95673c550e32cbacf413053216d729426de90ed3 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/system_defined_pixelmap_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/system_defined_pixelmap_test.cpp @@ -17,8 +17,10 @@ #include <unistd.h> #include <gtest/gtest.h> #include <string> +#include <sstream> #include "logger.h" +#include "pixelmap_loader.h" #include "system_defined_pixelmap.h" using namespace testing::ext; @@ -26,7 +28,10 @@ using namespace OHOS::UDMF; using namespace OHOS; namespace OHOS::Test { using namespace std; - +static constexpr const char* PIXEL_MAP_WIDTH = "width"; +static constexpr const char* PIXEL_MAP_HEIGHT = "height"; +static constexpr const char* PIXEL_MAP_FORMAT = "pixel-format"; +static constexpr const char* PIXEL_MAP_ALPHA_TYPE = "alpha-type"; class SystemDefinedPixelMapTest : public testing::Test { public: static void SetUpTestCase(); @@ -97,4 +102,249 @@ HWTEST_F(SystemDefinedPixelMapTest, SystemDefinedPixelMap003, TestSize.Level1) EXPECT_EQ(systemDefinedPixelMap.rawData_.size(), 0); LOG_INFO(UDMF_TEST, "SystemDefinedPixelMap003 end."); } + +/** +* @tc.name: GetPixelMapFromRawData001 +* @tc.desc: Abnormal testcase of GetPixelMapFromRawData, rawData_ is null +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, GetPixelMapFromRawData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetPixelMapFromRawData001 begin."); + SystemDefinedPixelMap systemDefinedPixelMap; + const std::vector<uint8_t> rawData; + systemDefinedPixelMap.SetRawData(rawData); + auto ret = systemDefinedPixelMap.GetPixelMapFromRawData(); + EXPECT_EQ(ret, nullptr); + LOG_INFO(UDMF_TEST, "GetPixelMapFromRawData001 end."); +} + +/** +* @tc.name: GetPixelMapFromRawData002 +* @tc.desc: Abnormal testcase of GetPixelMapFromRawData, rawData_ is wrong +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, GetPixelMapFromRawData002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetPixelMapFromRawData002 begin."); + + std::vector<uint8_t> rawData; + for (int i = 0; i < 4 * 1024 * 1024; i++) { + rawData.emplace_back(1); + } + SystemDefinedPixelMap systemDefinedPixelMap; + UDDetails details = { + {PIXEL_MAP_WIDTH, (int32_t)5}, + {PIXEL_MAP_HEIGHT, (int32_t)7}, + {PIXEL_MAP_FORMAT, (int32_t)Media::PixelFormat::ARGB_8888}, + {PIXEL_MAP_ALPHA_TYPE, (int32_t)Media::PixelFormat::ARGB_8888} + }; + systemDefinedPixelMap.SetRawData(rawData); + systemDefinedPixelMap.SetDetails(details); + auto ret = systemDefinedPixelMap.GetPixelMapFromRawData(); + EXPECT_EQ(ret, nullptr); + LOG_INFO(UDMF_TEST, "GetPixelMapFromRawData002 end."); +} + +/** +* @tc.name: GetPixelMapFromRawData003 +* @tc.desc: Abnormal testcase of GetPixelMapFromRawData, rawData_ is null +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, GetPixelMapFromRawData003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetPixelMapFromRawData002 begin."); + + uint32_t color[35] = { 3, 7, 9, 9, 7, 6 }; + OHOS::Media::InitializationOptions opts = { { 5, 7 }, + Media::PixelFormat::ARGB_8888, Media::PixelFormat::ARGB_8888 }; + std::unique_ptr<OHOS::Media::PixelMap> pixelMap = + OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + auto length = pixelMap->GetByteCount(); + std::vector<uint8_t> rawData; + rawData.resize(length); + pixelMap->ReadPixels(length, rawData.data()); + SystemDefinedPixelMap systemDefinedPixelMap; + UDDetails details = { + {PIXEL_MAP_WIDTH, (int32_t)5}, + {PIXEL_MAP_HEIGHT, (int32_t)7}, + {PIXEL_MAP_FORMAT, (int32_t)Media::PixelFormat::ARGB_8888}, + {PIXEL_MAP_ALPHA_TYPE, (int32_t)Media::PixelFormat::ARGB_8888} + }; + systemDefinedPixelMap.SetRawData(rawData); + systemDefinedPixelMap.SetDetails(details); + auto getPixelMap = systemDefinedPixelMap.GetPixelMapFromRawData(); + auto getLength = getPixelMap->GetByteCount(); + EXPECT_EQ(length, getLength); + std::vector<uint8_t> getRawData; + getPixelMap->ReadPixels(length, getRawData.data()); + for (int32_t i = 0; i < getLength; ++i) { + EXPECT_EQ(getRawData[i], rawData[i]); + } + LOG_INFO(UDMF_TEST, "GetPixelMapFromRawData003 end."); +} + +/** +* @tc.name: ParseInfoFromPixelMap001 +* @tc.desc: Abnormal testcase of ParseInfoFromPixelMap001, pixelMap is null +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, ParseInfoFromPixelMap001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ParseInfoFromPixelMap001 begin."); + SystemDefinedPixelMap systemDefinedPixelMap; + systemDefinedPixelMap.ParseInfoFromPixelMap(nullptr); + EXPECT_TRUE(systemDefinedPixelMap.details_.empty()); + LOG_INFO(UDMF_TEST, "ParseInfoFromPixelMap001 end."); +} + +/** +* @tc.name: PixelMapLoader001 +* @tc.desc: Abnormal testcase of PixelMapLoader001 +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, PixelMapLoader001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "PixelMapLoader001 begin."); + PixelMapLoader loader; + loader.handler_ = nullptr; + std::vector<uint8_t> buff(10); + auto ret = loader.DecodeTlv(buff); + EXPECT_EQ(ret, nullptr); + LOG_INFO(UDMF_TEST, "PixelMapLoader001 end."); +} + +/** +* @tc.name: PixelMapLoader002 +* @tc.desc: Abnormal testcase of PixelMapLoader002 +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, PixelMapLoader002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "PixelMapLoader002 begin."); + PixelMapLoader loader; + loader.handler_ = nullptr; + std::vector<uint8_t> buff; + + uint32_t color[35] = { 3, 7, 9, 9, 7, 6 }; + OHOS::Media::InitializationOptions opts = { { 5, 7 }, + Media::PixelFormat::ARGB_8888, Media::PixelFormat::ARGB_8888 }; + std::unique_ptr<OHOS::Media::PixelMap> pixelMap = + OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr<OHOS::Media::PixelMap> pixelMapIn = move(pixelMap); + + auto ret = loader.EncodeTlv(pixelMapIn, buff); + EXPECT_EQ(ret, false); + LOG_INFO(UDMF_TEST, "PixelMapLoader002 end."); +} + +/** +* @tc.name: PixelMapLoader003 +* @tc.desc: Abnormal testcase of PixelMapLoader003 +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, PixelMapLoader003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "PixelMapLoader003 begin."); + PixelMapLoader loader; + loader.handler_ = nullptr; + + PixelMapDetails details; + auto buff = std::vector<uint8_t>(10); + details.rawData = std::ref(buff); + auto ret = loader.GetPixelMapFromRawData(details); + EXPECT_EQ(ret, nullptr); + LOG_INFO(UDMF_TEST, "PixelMapLoader003 end."); +} + +/** +* @tc.name: PixelMapLoader004 +* @tc.desc: Abnormal testcase of PixelMapLoader004 +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, PixelMapLoader004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "PixelMapLoader004 begin."); + PixelMapLoader loader; + loader.handler_ = nullptr; + + uint32_t color[35] = { 3, 7, 9, 9, 7, 6 }; + OHOS::Media::InitializationOptions opts = { { 5, 7 }, + Media::PixelFormat::ARGB_8888, Media::PixelFormat::ARGB_8888 }; + std::unique_ptr<OHOS::Media::PixelMap> pixelMap = + OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr<OHOS::Media::PixelMap> pixelMapIn = move(pixelMap); + auto ret = loader.ParseInfoFromPixelMap(pixelMapIn); + EXPECT_EQ(ret, nullptr); + LOG_INFO(UDMF_TEST, "PixelMapLoader004 end."); +} + +/** +* @tc.name: PixelMapLoader005 +* @tc.desc: Abnormal testcase of PixelMapLoader005 +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, PixelMapLoader005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "PixelMapLoader005 begin."); + PixelMapLoader loader; + ASSERT_NE(loader.handler_, nullptr); + + std::vector<uint8_t> buff; + auto ret = loader.DecodeTlv(buff); + EXPECT_EQ(ret, nullptr); + LOG_INFO(UDMF_TEST, "PixelMapLoader005 end."); +} + +/** +* @tc.name: PixelMapLoader006 +* @tc.desc: Abnormal testcase of PixelMapLoader006 +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, PixelMapLoader006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "PixelMapLoader006 begin."); + PixelMapLoader loader; + ASSERT_NE(loader.handler_, nullptr); + std::vector<uint8_t> buff; + std::shared_ptr<OHOS::Media::PixelMap> pixelMapIn = nullptr; + + auto ret = loader.EncodeTlv(pixelMapIn, buff); + EXPECT_EQ(ret, false); + LOG_INFO(UDMF_TEST, "PixelMapLoader006 end."); +} + +/** +* @tc.name: PixelMapLoader007 +* @tc.desc: Abnormal testcase of PixelMapLoader007 +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, PixelMapLoader007, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "PixelMapLoader007 begin."); + PixelMapLoader loader; + ASSERT_NE(loader.handler_, nullptr); + + PixelMapDetails details; + details.rawData = std::nullopt; + auto ret = loader.GetPixelMapFromRawData(details); + EXPECT_EQ(ret, nullptr); + LOG_INFO(UDMF_TEST, "PixelMapLoader007 end."); +} + +/** +* @tc.name: PixelMapLoader008 +* @tc.desc: Abnormal testcase of PixelMapLoader008 +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, PixelMapLoader008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "PixelMapLoader008 begin."); + PixelMapLoader loader; + ASSERT_NE(loader.handler_, nullptr); + + auto ret = loader.ParseInfoFromPixelMap(nullptr); + EXPECT_EQ(ret, nullptr); + LOG_INFO(UDMF_TEST, "PixelMapLoader008 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/udmf_async_client_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/udmf_async_client_test.cpp index 9ad5e05d3abfc5c1bf672fbae748ce977b4deb85..3686c4886da95faf3667a3a65ee15b0ec0c73ffd 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/udmf_async_client_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/udmf_async_client_test.cpp @@ -13,20 +13,21 @@ * limitations under the License. */ #define LOG_TAG "UdmfAsyncClientTest" +#include "udmf_async_client.h" + #include <gtest/gtest.h> -#include "token_setproc.h" #include "accesstoken_kit.h" -#include "nativetoken_kit.h" - +#include "async_task_params.h" +#include "data_params_conversion.h" #include "image.h" #include "logger.h" +#include "nativetoken_kit.h" #include "plain_text.h" +#include "token_setproc.h" #include "udmf.h" -#include "udmf_async_client.h" #include "udmf_client.h" -#include "async_task_params.h" -#include "data_params_conversion.h" +#include "udmf_executor.h" using namespace testing::ext; using namespace OHOS::Security::AccessToken; @@ -56,9 +57,7 @@ void UdmfAsyncClientTest::TearDownTestCase() { std::this_thread::sleep_for(std::chrono::seconds(END_INTERVAL)); std::vector<UnifiedData> unifiedDataSet; - QueryOption query = { - .intention = UDMF::UD_INTENTION_DATA_HUB - }; + QueryOption query = { .intention = UDMF::UD_INTENTION_DATA_HUB }; auto status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); EXPECT_EQ(E_OK, status); auto tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.asyncdemo", 0); @@ -69,41 +68,29 @@ void UdmfAsyncClientTest::SetUp() {} void UdmfAsyncClientTest::TearDown() {} - void UdmfAsyncClientTest::AllocHapToken() { - HapInfoParams info = { - .userID = USER_ID, - .bundleName = "ohos.test.asyncdemo", - .instIndex = 0, - .appIDDesc = "ohos.test.asyncdemo", - .isSystemApp = false, - }; - HapPolicyParams policy = { - .apl = APL_SYSTEM_BASIC, + HapInfoParams info; + info.userID = USER_ID; + info.bundleName = "ohos.test.asyncdemo"; + info.instIndex = 0; + info.isSystemApp = false; + info.appIDDesc = "ohos.test.asyncdemo"; + HapPolicyParams policy = { .apl = APL_SYSTEM_BASIC, .domain = "test.domain", - .permList = { - { - .permissionName = "ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION", - .bundleName = "ohos.test.asyncdemo", - .grantMode = 1, - .availableLevel = APL_SYSTEM_BASIC, - .label = "label", - .labelId = 1, - .description = "test2", - .descriptionId = 1 - } - }, - .permStateList = { - { - .permissionName = "ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION", - .isGeneral = true, - .resDeviceID = { "local" }, - .grantStatus = { PermissionState::PERMISSION_GRANTED }, - .grantFlags = { 1 } - } - } - }; + .permList = { { .permissionName = "ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION", + .bundleName = "ohos.test.asyncdemo", + .grantMode = 1, + .availableLevel = APL_SYSTEM_BASIC, + .label = "label", + .labelId = 1, + .description = "test2", + .descriptionId = 1 } }, + .permStateList = { { .permissionName = "ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } } } }; auto tokenID = AccessTokenKit::AllocHapToken(info, policy); SetSelfTokenID(tokenID.tokenIDEx); } @@ -117,9 +104,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval001, TestSize.Level1) { LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval001 begin."); - CustomOption customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; UnifiedData data; auto obj = std::make_shared<Object>(); auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); @@ -130,10 +115,9 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval001, TestSize.Level1) ASSERT_EQ(E_OK, status); GetDataParams params; - QueryOption query = { - .key = key, - .intention = UD_INTENTION_DRAG, - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", progress.progressStatus, progress.progress, progress.srcDevName.c_str()); @@ -161,9 +145,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval002, TestSize.Level1) { LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval002 begin."); - CustomOption customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; UnifiedData data; auto obj = std::make_shared<Object>(); auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); @@ -191,10 +173,9 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval002, TestSize.Level1) LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval002 callback end."); }; OH_UdmfGetDataParams_SetDataProgressListener(&param, dataProgressListener); - QueryOption query = { - .key = key, - .intention = UD_INTENTION_DRAG, - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; GetDataParams dataParams; status = DataParamsConversion::GetInnerDataParams(param, query, dataParams); ASSERT_EQ(E_OK, status); @@ -214,9 +195,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval003, TestSize.Level1) auto status = UdmfClient::GetInstance().SetAppShareOption("drag", ShareOptions::IN_APP); ASSERT_EQ(E_OK, status); - CustomOption customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; UnifiedData data; auto obj = std::make_shared<Object>(); auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); @@ -227,10 +206,9 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval003, TestSize.Level1) ASSERT_EQ(E_OK, status); GetDataParams params; - QueryOption query = { - .key = key, - .intention = UD_INTENTION_DRAG, - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", progress.progressStatus, progress.progress, progress.srcDevName.c_str()); @@ -261,9 +239,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval004, TestSize.Level1) { LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval004 begin."); - CustomOption customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; UnifiedData data; auto obj = std::make_shared<Object>(); auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); @@ -274,10 +250,9 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval004, TestSize.Level1) ASSERT_EQ(E_OK, status); GetDataParams params; - QueryOption query = { - .key = key, - .intention = UD_INTENTION_DRAG, - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", progress.progressStatus, progress.progress, progress.srcDevName.c_str()); @@ -309,10 +284,9 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval005, TestSize.Level1) LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval005 begin."); GetDataParams params; - QueryOption query = { - .key = "udmf://drag/com.demo/NotFoundData", - .intention = UD_INTENTION_DRAG, - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = "udmf://drag/com.demo/NotFoundData"; auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", progress.progressStatus, progress.progress, progress.srcDevName.c_str()); @@ -339,10 +313,9 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval006, TestSize.Level1) LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval006 begin."); GetDataParams params; - QueryOption query = { - .key = "InvalidKey", - .intention = UD_INTENTION_DRAG, - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = "InvalidKey"; auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", progress.progressStatus, progress.progress, progress.srcDevName.c_str()); @@ -362,10 +335,9 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval006, TestSize.Level1) Status UdmfAsyncClientTest::SetDataTest(std::string key, ProgressIndicator progressIndicator) { GetDataParams params; - QueryOption query = { - .key = key, - .intention = UD_INTENTION_DRAG, - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", progress.progressStatus, progress.progress, progress.srcDevName.c_str()); @@ -389,9 +361,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval007, TestSize.Level1) { LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval007 begin."); - CustomOption customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; UnifiedData data; auto obj = std::make_shared<Object>(); auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); @@ -402,9 +372,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval007, TestSize.Level1) ASSERT_EQ(E_OK, status); std::string key2; - customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + customOption = { .intention = UDMF::UD_INTENTION_DRAG }; plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); plainText->SetContent("content1"); data.AddRecord(plainText); @@ -412,9 +380,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval007, TestSize.Level1) ASSERT_EQ(E_OK, status); std::string key3; - customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + customOption = { .intention = UDMF::UD_INTENTION_DRAG }; plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); plainText->SetContent("content1"); data.AddRecord(plainText); @@ -448,9 +414,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval008, TestSize.Level1) { LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval008 begin."); - CustomOption customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; UnifiedData data; auto obj = std::make_shared<Object>(); auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); @@ -490,9 +454,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval009, TestSize.Level1) { LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval009 begin."); - CustomOption customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; UnifiedData data; auto obj = std::make_shared<Object>(); auto file = std::make_shared<Image>(UDType::IMAGE, obj); @@ -504,10 +466,9 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval009, TestSize.Level1) ASSERT_EQ(E_OK, status); GetDataParams params; - QueryOption query = { - .key = key, - .intention = UD_INTENTION_DRAG, - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", progress.progressStatus, progress.progress, progress.srcDevName.c_str()); @@ -536,9 +497,8 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval010, TestSize.Level1) LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval010 begin."); GetDataParams params; - QueryOption query = { - .intention = UDMF::UD_INTENTION_DRAG - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; params.query = query; params.progressIndicator = ProgressIndicator::DEFAULT; auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) {}; @@ -546,20 +506,16 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval010, TestSize.Level1) auto status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); ASSERT_EQ(E_INVALID_PARAMETERS, status); - query = { - .key = "udmf://a/b/c", - .intention = UDMF::UD_INTENTION_DATA_HUB, - }; + query.intention = UDMF::UD_INTENTION_DATA_HUB; + query.key = "udmf://a/b/c"; params.query = query; params.progressIndicator = ProgressIndicator::DEFAULT; params.progressListener = callback; status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); ASSERT_EQ(E_INVALID_PARAMETERS, status); - query = { - .key = "udmf://a/b/c", - .intention = UDMF::UD_INTENTION_DRAG, - }; + query.intention = UDMF::UD_INTENTION_DRAG; + query.key = "udmf://a/b/c"; params.query = query; params.progressIndicator = ProgressIndicator::DEFAULT; params.progressListener = nullptr; @@ -567,4 +523,255 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval010, TestSize.Level1) ASSERT_EQ(E_INVALID_PARAMETERS, status); LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval010 end."); } -} // OHOS::Test \ No newline at end of file + +/** + * @tc.name: Cancel001 + * @tc.desc: Test Normal Cancel + * @tc.type: FUNC + */ +HWTEST_F(UdmfAsyncClientTest, Cancel001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Cancel001 begin."); + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; + UnifiedData data; + auto obj = std::make_shared<Object>(); + auto file = std::make_shared<Image>(UDType::IMAGE, obj); + file->SetUri("uri"); + file->SetRemoteUri("remoteUri"); + data.AddRecord(file); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(E_OK, status); + + GetDataParams params; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; + auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { + LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", + progress.progressStatus, progress.progress, progress.srcDevName.c_str()); + if (data == nullptr) { + ASSERT_TRUE(progress.progress != 0); + return; + } + ASSERT_EQ(1, data->GetRecords().size()); + LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval009 callback end."); + }; + params.query = query; + params.progressIndicator = ProgressIndicator::DEFAULT; + params.progressListener = callback; + status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); + ASSERT_EQ(E_OK, status); + std::string businessUdKey = "udmf://a/b/c"; + status = UdmfAsyncClient::GetInstance().Cancel(params.query.key); + ASSERT_EQ(E_OK, status); + + LOG_INFO(UDMF_TEST, "Cancel001 end."); +} + +/** + * @tc.name: Cancel002 + * @tc.desc: Test Invalid params. + * @tc.type: FUNC + */ +HWTEST_F(UdmfAsyncClientTest, Cancel002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Cancel002 begin."); + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; + UnifiedData data; + auto obj = std::make_shared<Object>(); + auto file = std::make_shared<Image>(UDType::IMAGE, obj); + file->SetUri("uri"); + file->SetRemoteUri("remoteUri"); + data.AddRecord(file); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(E_OK, status); + + GetDataParams params; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; + auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { + LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", + progress.progressStatus, progress.progress, progress.srcDevName.c_str()); + if (data == nullptr) { + ASSERT_TRUE(progress.progress != 0); + return; + } + ASSERT_EQ(1, data->GetRecords().size()); + LOG_INFO(UDMF_TEST, "Cancel002 callback end."); + }; + params.query = query; + params.progressIndicator = ProgressIndicator::DEFAULT; + params.progressListener = callback; + status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); + ASSERT_EQ(E_OK, status); + std::string businessUdKey = "udmf"; + status = UdmfAsyncClient::GetInstance().Cancel(businessUdKey); + ASSERT_EQ(E_ERROR, status); + + LOG_INFO(UDMF_TEST, "Cancel002 end."); +} + +/* * + * @tc.name: CancelOnSingleTask001 + * @tc.desc: Test one data + * @tc.type: FUNC + */ +HWTEST_F(UdmfAsyncClientTest, CancelOnSingleTask001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "CancelOnSingleTask001 begin."); + CustomOption customOption; + customOption.intention = UDMF::UD_INTENTION_DRAG; + UnifiedData data; + auto obj = std::make_shared<Object>(); + auto file = std::make_shared<Image>(UDType::IMAGE, obj); + file->SetUri("uri"); + file->SetRemoteUri("remoteUri"); + data.AddRecord(file); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(E_OK, status); + + GetDataParams params; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; + auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { + LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", + progress.progressStatus, progress.progress, progress.srcDevName.c_str()); + if (data == nullptr) { + ASSERT_TRUE(progress.progress != 0); + return; + } + ASSERT_EQ(1, data->GetRecords().size()); + LOG_INFO(UDMF_TEST, "CancelOnSingleTask001 callback end."); + }; + params.query = query; + params.progressIndicator = ProgressIndicator::DEFAULT; + params.progressListener = callback; + status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); + ASSERT_EQ(E_OK, status); + status = UdmfAsyncClient::GetInstance().CancelOnSingleTask(); + ASSERT_EQ(E_ERROR, status); + + LOG_INFO(UDMF_TEST, "CancelOnSingleTask001 end."); +} + +/* * + * @tc.name: CancelOnSingleTask002 + * @tc.desc: Test no data + * @tc.type: FUNC + */ +HWTEST_F(UdmfAsyncClientTest, CancelOnSingleTask002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "CancelOnSingleTask002 begin."); + auto status = UdmfAsyncClient::GetInstance().CancelOnSingleTask(); + ASSERT_EQ(E_ERROR, status); + + LOG_INFO(UDMF_TEST, "CancelOnSingleTask002 end."); +} + +/* * + * @tc.name: CancelOnSingleTask003 + * @tc.desc: Test two data + * @tc.type: FUNC + */ +HWTEST_F(UdmfAsyncClientTest, CancelOnSingleTask003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "CancelOnSingleTask003 begin."); + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; + UnifiedData data; + auto obj = std::make_shared<Object>(); + auto file = std::make_shared<Image>(UDType::IMAGE, obj); + file->SetUri("uri"); + file->SetRemoteUri("remoteUri"); + data.AddRecord(file); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(E_OK, status); + + GetDataParams params; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; + auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { + LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", + progress.progressStatus, progress.progress, progress.srcDevName.c_str()); + if (data == nullptr) { + ASSERT_TRUE(progress.progress != 0); + return; + } + ASSERT_EQ(1, data->GetRecords().size()); + LOG_INFO(UDMF_TEST, "CancelOnSingleTask001 callback end."); + }; + params.query = query; + params.progressIndicator = ProgressIndicator::DEFAULT; + params.progressListener = callback; + status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); + ASSERT_EQ(E_OK, status); + query.intention = UD_INTENTION_DRAG; + query.key = "key"; + params.query = query; + status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); + ASSERT_EQ(E_OK, status); + status = UdmfAsyncClient::GetInstance().CancelOnSingleTask(); + ASSERT_EQ(E_ERROR, status); + + LOG_INFO(UDMF_TEST, "CancelOnSingleTask003 end."); +} + +HWTEST_F(UdmfAsyncClientTest, UpdateOnSameProgressAfterInterval, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateOnSameProgressAfterInterval begin."); + std::string businessUdKey = "udmf://a/b/c"; + GetDataParams params; + params.progressIndicator = ProgressIndicator::DEFAULT; + params.query.key = businessUdKey; + UdmfAsyncClient::GetInstance().RegisterAsyncHelper(params); + std::thread pushThread([&]() { + auto &asyncHelper = UdmfAsyncClient::GetInstance().asyncHelperMap_.at(businessUdKey); + for (uint32_t i = 0; i < 10; ++i) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ProgressInfo sameProgress; + sameProgress.progress = 20; + asyncHelper->progressQueue.PushBack(sameProgress); + } + auto processKey = asyncHelper->processKey; + std::vector<UnifiedData> unifiedDataSet; + QueryOption query; + query.key = processKey; + auto ret = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(ret, E_OK); + ASSERT_EQ(unifiedDataSet.size(), 1); + auto record = unifiedDataSet[0].GetRecordAt(0); + EXPECT_EQ(record->GetType(), UDType::PLAIN_TEXT); + auto plainText = std::static_pointer_cast<PlainText>(record); + auto ts1 = plainText->GetAbstract(); + for (uint32_t i = 0; i < 30; ++i) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ProgressInfo sameProgress; + sameProgress.progress = 20; + asyncHelper->progressQueue.PushBack(sameProgress); + } + unifiedDataSet.clear(); + ret = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(ret, E_OK); + ASSERT_EQ(unifiedDataSet.size(), 1); + record = unifiedDataSet[0].GetRecordAt(0); + EXPECT_EQ(record->GetType(), UDType::PLAIN_TEXT); + plainText = std::static_pointer_cast<PlainText>(record); + auto ts2 = plainText->GetAbstract(); + EXPECT_TRUE(ts2 > ts1); + ProgressInfo sameProgress; + sameProgress.progress = 100; + asyncHelper->progressQueue.PushBack(sameProgress); + }); + auto ret = UdmfAsyncClient::GetInstance().ProgressTask(businessUdKey); + EXPECT_EQ(ret, E_OK); + pushThread.join(); + LOG_INFO(UDMF_TEST, "UpdateOnSameProgressAfterInterval end."); +} + +} // namespace OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_abnormal_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_abnormal_test.cpp index 36459f7ffc87583dfeb649cde8871c3fd9d218a7..5b02a8869e67f3b583cd0f263edd9c3adc8b48a5 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_abnormal_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_abnormal_test.cpp @@ -74,6 +74,7 @@ HWTEST_F(UdmfClientAbnormalTest, SetData001, TestSize.Level1) UdmfClient client; UnifiedData unifiedData; CustomOption option; + option.intention = Intention::UD_INTENTION_DATA_HUB; std::string key = "testKey"; Status ret = client.SetData(option, unifiedData, key); diff --git a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_file_manger_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_file_manger_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9087115081fb5b2168680209cef9b8a6e7bcdfcd --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_file_manger_test.cpp @@ -0,0 +1,2159 @@ +/* + * Copyright (c) 2025 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 "UdmfClientFileMangerTest" +#include <gtest/gtest.h> +#include <unistd.h> +#include <thread> +#include <chrono> + +#include "token_setproc.h" +#include "accesstoken_kit.h" +#include "directory_ex.h" +#include "nativetoken_kit.h" + +#include "logger.h" +#include "udmf_client.h" +#include "application_defined_record.h" +#include "audio.h" +#include "file.h" +#include "folder.h" +#include "html.h" +#include "image.h" +#include "link.h" +#include "plain_text.h" +#include "system_defined_appitem.h" +#include "system_defined_form.h" +#include "system_defined_pixelmap.h" +#include "system_defined_record.h" +#include "text.h" +#include "unified_data_helper.h" +#include "unified_html_record_process.h" +#include "video.h" + +using namespace testing::ext; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { +class UdmfClientFileMangerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + void SetNativeToken(const std::string &processName); + static void AllocHapToken1(); + static void AllocHapToken2(); + void SetHapToken1(); + void SetHapToken2(); + + void AddPrivilege(QueryOption &option); + void AddPrivilege1(QueryOption &option); + int64_t CountTime(); + + static constexpr int userId = 100; + static constexpr int instIndex = 0; +}; + +void UdmfClientFileMangerTest::SetUpTestCase() +{ + AllocHapToken1(); + AllocHapToken2(); +} + +void UdmfClientFileMangerTest::TearDownTestCase() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo1", instIndex); + AccessTokenKit::DeleteToken(tokenId); + tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + AccessTokenKit::DeleteToken(tokenId); +} + +void UdmfClientFileMangerTest::SetUp() +{ + SetHapToken1(); +} + +void UdmfClientFileMangerTest::TearDown() +{ + QueryOption query = { .intention = Intention::UD_INTENTION_PICKER }; + std::vector<UnifiedData> unifiedDataSet; + UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + query = { .intention = Intention::UD_INTENTION_MENU }; + UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + query = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); +} + +void UdmfClientFileMangerTest::SetNativeToken(const std::string &processName) +{ + auto tokenId = AccessTokenKit::GetNativeTokenId(processName); + SetSelfTokenID(tokenId); +} + +void UdmfClientFileMangerTest::AllocHapToken1() +{ + HapInfoParams info = { + .userID = userId, + .bundleName = "ohos.file.manger.test.demo1", + .instIndex = instIndex, + .appIDDesc = "ohos.file.manger.test.demo1" + }; + + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.file.manger.test.demo1", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "test1", + .descriptionId = 1 + } + }, + .permStateList = { + { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + } + } + }; + auto tokenID = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(tokenID.tokenIDEx); +} + +void UdmfClientFileMangerTest::AllocHapToken2() +{ + HapInfoParams info = { + .userID = userId, + .bundleName = "ohos.file.manger.test.demo2", + .instIndex = instIndex, + .appIDDesc = "ohos.file.manger.test.demo2" + }; + + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.file.manger.test.demo2", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "test2", + .descriptionId = 1 + } + }, + .permStateList = { + { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + } + } + }; + auto tokenID = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(tokenID.tokenIDEx); +} + +void UdmfClientFileMangerTest::SetHapToken1() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo1", instIndex); + SetSelfTokenID(tokenId); +} + +void UdmfClientFileMangerTest::SetHapToken2() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + SetSelfTokenID(tokenId); +} + +void UdmfClientFileMangerTest::AddPrivilege(QueryOption &option) +{ + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readAndKeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + + auto status = UdmfClient::GetInstance().AddPrivilege(option, privilege); + ASSERT_EQ(status, E_OK); +} + +void UdmfClientFileMangerTest::AddPrivilege1(QueryOption &option) +{ + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo1", instIndex); + privilege.readPermission = "readpermission"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + auto status = UdmfClient::GetInstance().AddPrivilege(option, privilege); + ASSERT_EQ(status, E_OK); +} + +int64_t UdmfClientFileMangerTest::CountTime() +{ + return std::chrono::duration_cast<std::chrono::milliseconds>( + std::chrono::system_clock::now().time_since_epoch()).count(); +} + +/** +* @tc.name: SetData001 +* @tc.desc: Set data with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData001 begin."); + + CustomOption option = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData data; + std::string key; + auto status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option = {}; + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option = { .intention = Intention::UD_INTENTION_BASE }; + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "SetData001 end."); +} + +/** +* @tc.name: SetData002 +* @tc.desc: Set data with valid params UD_INTENTION_PICKER +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData002 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_OK); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_OK); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData002 end."); +} + +/** +* @tc.name: SetData003 +* @tc.desc: Set data with invalid params UD_INTENTION_PICKER +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData003 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + AddPrivilege(query); + SetHapToken2(); + query.intention = Intention::UD_INTENTION_DATA_HUB; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption query1; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData003 end."); +} + +/** +* @tc.name: SetData004 +* @tc.desc: Set data with invalid params UD_INTENTION_PICKER +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData004 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + AddPrivilege(query); + SetHapToken2(); + + QueryOption query1; + query1.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_DATA_HUB; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData003 end."); +} + +/** +* @tc.name: SetData005 +* @tc.desc: one over 2MB record UD_INTENTION_PICKER +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData005 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData inputData; + std::string key; + UDDetails details; + std::string value; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "11"; + } + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string fileName = "file_" + value + ".txt"; + std::string uri = "file://" + fileName; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + int64_t start = CountTime(); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "picker setdata 1000 cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + start = CountTime(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + end = CountTime(); + LOG_INFO(UDMF_TEST, "picker getdata 2MB record cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData005 end."); +} + +/** +* @tc.name: SetData006 +* @tc.desc: two 2MB record UD_INTENTION_PICKER +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData006 begin."); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + std::string key; + std::string value; + UnifiedData inputData; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "11"; + } + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_" + value + ".txt"; + for (int i = 0; i < 2; ++i) { + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + } + inputData.SetRecords(inputRecords); + + int64_t start = CountTime(); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "picker setdata two 2MB record cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + start = CountTime(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + end = CountTime(); + LOG_INFO(UDMF_TEST, "picker getdata two 2MB record cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData006 end."); +} + +/** +* @tc.name: SetData007 +* @tc.desc: Set multiple record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData007, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData007 begin."); + + CustomOption customOption = {.intention = Intention::UD_INTENTION_PICKER}; + std::string key; + UnifiedData inputData; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords = { + std::make_shared<Text>(), + std::make_shared<PlainText>(), + std::make_shared<File>(), + std::make_shared<Image>(), + std::make_shared<SystemDefinedRecord>(), + std::make_shared<SystemDefinedForm>(), + std::make_shared<ApplicationDefinedRecord>() + }; + inputData.SetRecords(inputRecords); + + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + auto outputRecords = unifiedDataSet[0].GetRecords(); + ASSERT_EQ(inputRecords.size(), outputRecords.size()); + for (size_t i = 0; i < outputRecords.size(); ++i) { + ASSERT_EQ(outputRecords[i]->GetType(), inputRecords[i]->GetType()); + } + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData007 end."); +} + +/** +* @tc.name: SetData008 +* @tc.desc: Set data with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData008 begin."); + CustomOption option = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData data; + std::string key; + auto status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option = {}; + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option = { .intention = Intention::UD_INTENTION_BASE }; + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "SetData008 end."); +} + +/** +* @tc.name: SetData009 +* @tc.desc: Set data with valid params UD_INTENTION_MENU +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData009, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData009 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_OK); + + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_OK); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData009 end."); +} + +/** +* @tc.name: SetData010 +* @tc.desc: Set data with invalid params UD_INTENTION_MENU +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData010, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData010 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + AddPrivilege(query); + SetHapToken2(); + query.intention = Intention::UD_INTENTION_DATA_HUB; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption query1; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData010 end."); +} + +/** +* @tc.name: SetData011 +* @tc.desc: Set data with invalid params UD_INTENTION_MENU +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData011, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData011 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + AddPrivilege(query); + SetHapToken2(); + + QueryOption query1; + query1.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_DATA_HUB; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData011 end."); +} + +/** +* @tc.name: SetData012 +* @tc.desc: one over 2MB record UD_INTENTION_MENU +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData012, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData012 begin."); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData inputData; + std::string key; + UDDetails details; + std::string value; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "11"; + } + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string fileName = "file_" + value + ".txt"; + std::string uri = "file://" + fileName; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + + int64_t start = CountTime(); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "rightclick setdata 2MB record cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + start = CountTime(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + end = CountTime(); + LOG_INFO(UDMF_TEST, "rightclick getdata 2MB record cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + UnifiedDataHelper::SetRootPath(""); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData012 end."); +} + +/** +* @tc.name: SetData013 +* @tc.desc: two 2MB record UD_INTENTION_MENU +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData013, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData013 begin."); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData inputData; + std::string key; + UDDetails details; + std::string value; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "11"; + } + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_" + value + ".txt"; + for (int i = 0; i < 2; ++i) { + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + } + inputData.SetRecords(inputRecords); + + int64_t start = CountTime(); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "setdata 4MB cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + start = CountTime(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + end = CountTime(); + LOG_INFO(UDMF_TEST, "getdata 4MB cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData013 end."); +} + +/** +* @tc.name: SetData014 +* @tc.desc: Set multiple record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData014, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData014 begin."); + + CustomOption customOption = {.intention = Intention::UD_INTENTION_MENU}; + std::string key; + UnifiedData inputData; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords = { + std::make_shared<Text>(), + std::make_shared<PlainText>(), + std::make_shared<File>(), + std::make_shared<Image>(), + std::make_shared<SystemDefinedRecord>(), + std::make_shared<SystemDefinedForm>(), + std::make_shared<ApplicationDefinedRecord>() + }; + inputData.SetRecords(inputRecords); + + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + auto outputRecords = unifiedDataSet[0].GetRecords(); + ASSERT_EQ(inputRecords.size(), outputRecords.size()); + for (size_t i = 0; i < outputRecords.size(); ++i) { + ASSERT_EQ(outputRecords[i]->GetType(), inputRecords[i]->GetType()); + } + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData014 end."); +} + +/** +* @tc.name: SetData015 +* @tc.desc: Set data with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData015, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData015 begin."); + + CustomOption option = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + std::string key; + auto status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option = {}; + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option = { .intention = Intention::UD_INTENTION_BASE }; + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "SetData015 end."); +} + +/** +* @tc.name: SetData016 +* @tc.desc: Set data with valid params UD_INTENTION_SYSTEM_SHARE +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData016, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData016 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_OK); + + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_OK); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData016 end."); +} + +/** +* @tc.name: SetData017 +* @tc.desc: Set data with invalid params UD_INTENTION_SYSTEM_SHARE +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData017, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData017 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + AddPrivilege(query); + SetHapToken2(); + query.intention = Intention::UD_INTENTION_DATA_HUB; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption query1; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData017 end."); +} + +/** +* @tc.name: SetData018 +* @tc.desc: Set data with invalid params UD_INTENTION_SYSTEM_SHARE +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData018, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData018 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + AddPrivilege(query); + SetHapToken2(); + + QueryOption query1; + query1.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_DATA_HUB; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData018 end."); +} + +/** +* @tc.name: SetData019 +* @tc.desc: one over 2MB record UD_INTENTION_SYSTEM_SHARE +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData019, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData019 begin."); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData inputData; + std::string key; + UDDetails details; + std::string value; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "11"; + } + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string fileName = "file_" + value + ".txt"; + std::string uri = "file://" + fileName; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + + int64_t start = CountTime(); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "systemshare setdata one over 2MB record cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + start = CountTime(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + end = CountTime(); + LOG_INFO(UDMF_TEST, "systemshare getdata one over 2MB record cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + UnifiedDataHelper::SetRootPath(""); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData019 end."); +} + +/** +* @tc.name: SetData020 +* @tc.desc: two 2MB record UD_INTENTION_SYSTEM_SHARE +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData020, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData020 begin."); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData inputData; + std::string key; + UDDetails details; + std::string value; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "11"; + } + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_" + value + ".txt"; + for (int i = 0; i < 2; ++i) { + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + } + inputData.SetRecords(inputRecords); + + int64_t start = CountTime(); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "getdata 1 cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + start = CountTime(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + end = CountTime(); + LOG_INFO(UDMF_TEST, "getdata 1 cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + + LOG_INFO(UDMF_TEST, "SetData020 end."); +} + +/** +* @tc.name: SetData021 +* @tc.desc: Set multiple record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData021, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData021 begin."); + + CustomOption customOption = {.intention = Intention::UD_INTENTION_SYSTEM_SHARE}; + std::string key; + UnifiedData inputData; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords = { + std::make_shared<Text>(), + std::make_shared<PlainText>(), + std::make_shared<File>(), + std::make_shared<Image>(), + std::make_shared<SystemDefinedRecord>(), + std::make_shared<SystemDefinedForm>(), + std::make_shared<ApplicationDefinedRecord>() + }; + inputData.SetRecords(inputRecords); + + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + auto outputRecords = unifiedDataSet[0].GetRecords(); + ASSERT_EQ(inputRecords.size(), outputRecords.size()); + for (size_t i = 0; i < outputRecords.size(); ++i) { + ASSERT_EQ(outputRecords[i]->GetType(), inputRecords[i]->GetType()); + } + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData018 end."); +} + +/** +* @tc.name: AddPrivilege001 +* @tc.desc: Add privilege with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege001 begin."); + CustomOption option1 = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_OK); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + SetNativeToken("foundation"); + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + privilege.readPermission = "readpermission"; + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "AddPrivilege001 end."); +} + +/** +* @tc.name: AddPrivilege002 +* @tc.desc: Add privilege with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege002 begin."); + CustomOption option1 = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_OK); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + SetNativeToken("foundation"); + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + privilege.readPermission = "readpermission"; + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "AddPrivilege002 end."); +} + +/** +* @tc.name: AddPrivilege003 +* @tc.desc: Add privilege with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege003 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_OK); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + privilege.readPermission = "readpermission"; + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "AddPrivilege003 end."); +} + +/** +* @tc.name: AddPrivilege004 +* @tc.desc: Add privilege with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege004 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.key = key; + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_PICKER; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "AddPrivilege004 end."); +} + +/** +* @tc.name: AddPrivilege005 +* @tc.desc: Add privilege with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege005 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.key = key; + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_MENU; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "AddPrivilege005 end."); +} + +/** +* @tc.name: AddPrivilege006 +* @tc.desc: Add privilege with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege006 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.key = key; + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "AddPrivilege006 end."); +} + +/** +* @tc.name: AddPrivilege007 +* @tc.desc: Add privilege with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege007, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege007 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + + query.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + LOG_INFO(UDMF_TEST, "AddPrivilege007 end."); +} + +/** +* @tc.name: AddPrivilege008 +* @tc.desc: Add privilege with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege008 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + query.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + LOG_INFO(UDMF_TEST, "AddPrivilege008 end."); +} + +/** +* @tc.name: AddPrivilege009 +* @tc.desc: Add privilege with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege009, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege009 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + query.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + LOG_INFO(UDMF_TEST, "AddPrivilege009 end."); +} + +/** +* @tc.name: DeleteData001 +* @tc.desc: Delete data with UD_INTENTION_PICKER +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData001 begin."); + CustomOption customOption = { .intention = UD_INTENTION_PICKER }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + queryOption.key = key; + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData001 end."); +} + +/** +* @tc.name: DeleteData002 +* @tc.desc: Delete data with UD_INTENTION_PICKER +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData002 begin."); + CustomOption customOption = { .intention = UD_INTENTION_PICKER }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption queryOption1 = { .key = key }; + status = UdmfClient::GetInstance().DeleteData(queryOption1, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData002 end."); +} + +/** +* @tc.name: DeleteData003 +* @tc.desc: Delete data with UD_INTENTION_PICKER +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData003 begin."); + CustomOption customOption = { .intention = UD_INTENTION_PICKER }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + queryOption.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption queryOption1 = { .key = key }; + status = UdmfClient::GetInstance().DeleteData(queryOption1, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData003 end."); +} + +/** +* @tc.name: DeleteData004 +* @tc.desc: Delete data with UD_INTENTION_SYSTEM_SHARE +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData004 begin."); + CustomOption customOption = { .intention = UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + queryOption.key = key; + queryOption.intention = UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData004 end."); +} + +/** +* @tc.name: DeleteData005 +* @tc.desc: Delete data with UD_INTENTION_SYSTEM_SHARE +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData005 begin."); + CustomOption customOption = { .intention = UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption queryOption1 = { .key = key }; + status = UdmfClient::GetInstance().DeleteData(queryOption1, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData005 end."); +} + +/** +* @tc.name: DeleteData006 +* @tc.desc: Delete data with UD_INTENTION_SYSTEM_SHARE +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData006 begin."); + CustomOption customOption = { .intention = UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + queryOption.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption queryOption1 = { .key = key }; + status = UdmfClient::GetInstance().DeleteData(queryOption1, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData006 end."); +} + +/** +* @tc.name: DeleteData007 +* @tc.desc: Delete data with UD_INTENTION_MENU +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData007, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData007 begin."); + CustomOption customOption = { .intention = UD_INTENTION_MENU }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + queryOption.key = key; + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_MENU; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData007 end."); +} + +/** +* @tc.name: DeleteData008 +* @tc.desc: Delete data with UD_INTENTION_MENU +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData008 begin."); + CustomOption customOption = { .intention = UD_INTENTION_MENU }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_MENU; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption queryOption1 = { .key = key }; + status = UdmfClient::GetInstance().DeleteData(queryOption1, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData008 end."); +} + +/** +* @tc.name: DeleteData009 +* @tc.desc: Delete data with UD_INTENTION_MENU +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData009, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData009 begin."); + CustomOption customOption = { .intention = UD_INTENTION_MENU }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + queryOption.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_MENU; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption queryOption1 = { .key = key }; + status = UdmfClient::GetInstance().DeleteData(queryOption1, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData009 end."); +} + +/** +* @tc.name: UpdateData001 +* @tc.desc: test picker update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData001 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.key = key; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData001 end."); +} + +/** +* @tc.name: UpdateData002 +* @tc.desc: test picker update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData002 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + query.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.key = key; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData002 end."); +} + +/** +* @tc.name: UpdateData003 +* @tc.desc: test picker update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData003 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + query.key = key; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData003 end."); +} + +/** +* @tc.name: UpdateData004 +* @tc.desc: test picker update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData004 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.key = key; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData004 end."); +} + +/** +* @tc.name: UpdateData005 +* @tc.desc: test picker update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData005 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + query.key = key; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData005 end."); +} + +/** +* @tc.name: UpdateData006 +* @tc.desc: test systemshare update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData006 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.key = key; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData006 end."); +} + +/** +* @tc.name: UpdateData007 +* @tc.desc: test systemshare update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData007, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData007 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + query.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.key = key; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData007 end."); +} + +/** +* @tc.name: UpdateData008 +* @tc.desc: test menu update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData008 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.key = key; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData008 end."); +} + +/** +* @tc.name: UpdateData011 +* @tc.desc: test menu update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData011, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData011 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + query.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.key = key; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData011 end."); +} + +/** +* @tc.name: UpdateData012 +* @tc.desc: test menu update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData012, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData012 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + query.key = key; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData012 end."); +} +} diff --git a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_hap_permission_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_hap_permission_test.cpp index bbc76a3c51d6ba70204414d4730420b188585ff2..b86077c08c1160ced1df43271f3d61451034e7b3 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_hap_permission_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_hap_permission_test.cpp @@ -134,13 +134,12 @@ void UdmfClientHapPermissionTest::AllocHapToken1() void UdmfClientHapPermissionTest::AllocHapToken2() { - HapInfoParams info = { - .userID = USER_ID, - .bundleName = "ohos.test.demo22", - .instIndex = 0, - .appIDDesc = "ohos.test.demo22", - .isSystemApp = false, - }; + HapInfoParams info; + info.userID = USER_ID; + info.appIDDesc = "ohos.test.demo22"; + info.bundleName = "ohos.test.demo22"; + info.instIndex = 0; + info.isSystemApp = false; HapPolicyParams policy = { .apl = APL_SYSTEM_BASIC, .domain = "test.domain", @@ -352,4 +351,56 @@ HWTEST_F(UdmfClientHapPermissionTest, RemoveAppShareOption002, TestSize.Level1) EXPECT_EQ(status, E_NOT_FOUND); LOG_INFO(UDMF_TEST, "RemoveAppShareOption002 end."); } + +/** +* @tc.name: SetAppShareOption005 +* @tc.desc: SetAppShareOption CROSS_APP, set data success when CROSS_APP +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientHapPermissionTest, SetAppShareOption005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetAppShareOption005 begin."); + + CustomOption option = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data; + auto text1 = std::make_shared<Text>(); + data.AddRecord(text1); + std::string key; + std::string intention = "drag"; + ShareOptions shareOption = CROSS_APP; + SetHapToken2(); + Status status = UdmfClient::GetInstance().SetAppShareOption(intention, shareOption); + EXPECT_EQ(status, E_OK); + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_OK); + + LOG_INFO(UDMF_TEST, "SetAppShareOption005 end."); +} + +/** +* @tc.name: SetAppShareOption006 +* @tc.desc: SetAppShareOption IN_APP, set data success when IN_APP +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientHapPermissionTest, SetAppShareOption006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetAppShareOption006 begin."); + + CustomOption option = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data; + auto text1 = std::make_shared<Text>(); + data.AddRecord(text1); + std::string key; + std::string intention = "drag"; + ShareOptions shareOption = IN_APP; + SetHapToken2(); + Status status = UdmfClient::GetInstance().RemoveAppShareOption(intention); + EXPECT_EQ(status, E_OK); + status = UdmfClient::GetInstance().SetAppShareOption(intention, shareOption); + EXPECT_EQ(status, E_OK); + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_OK); + + LOG_INFO(UDMF_TEST, "SetAppShareOption006 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_test.cpp index c381634398f18ecb3aaf7c5a476714264ae766b7..ecc0220852efb10cf84534c354b79edf1f7076dd 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_test.cpp @@ -29,6 +29,7 @@ #include "application_defined_record.h" #include "audio.h" #include "file.h" +#include "file_uri.h" #include "folder.h" #include "html.h" #include "image.h" @@ -52,6 +53,7 @@ constexpr int SLEEP_TIME = 50; // 50 ms constexpr int BATCH_SIZE_2K = 2000; constexpr int BATCH_SIZE_5K = 5000; constexpr double BASE_CONVERSION = 1000.0; +constexpr const char *FILE_SCHEME_PREFIX = "file://"; class UdmfClientTest : public testing::Test { public: static void SetUpTestCase(); @@ -70,6 +72,7 @@ public: void CompareDetails(const UDDetails &details); void GetEmptyData(QueryOption &option); void GetFileUriUnifiedData(UnifiedData &data); + void ComparePixelMap(const UDDetails details, std::shared_ptr<OHOS::Media::PixelMap> pixelMapIn); static constexpr int USER_ID = 100; static constexpr int INST_INDEX = 0; @@ -230,6 +233,30 @@ void UdmfClientTest::CompareDetails(const UDDetails &details) } } +void UdmfClientTest::ComparePixelMap(const UDDetails details, std::shared_ptr<OHOS::Media::PixelMap> pixelMapIn) +{ + auto width = details.find("width"); + if (width != details.end()) { + EXPECT_EQ(std::get<int32_t>(width->second), pixelMapIn->GetWidth()); + } + auto height = details.find("height"); + if (height != details.end()) { + EXPECT_EQ(std::get<int32_t>(height->second), pixelMapIn->GetHeight()); + } + auto pixel_format = details.find("pixel-format"); + if (pixel_format != details.end()) { + EXPECT_EQ(std::get<int32_t>(pixel_format->second), static_cast<int32_t>(pixelMapIn->GetPixelFormat())); + } + auto alpha_type = details.find("alpha-type"); + if (alpha_type != details.end()) { + EXPECT_EQ(std::get<int32_t>(alpha_type->second), static_cast<int32_t>(pixelMapIn->GetAlphaType())); + } + auto udmf_key = details.find("udmf_key"); + if (udmf_key != details.end()) { + EXPECT_EQ(std::get<std::string>(udmf_key->second), "udmf_value"); + } +} + void UdmfClientTest::GetEmptyData(QueryOption &option) { UnifiedData data; @@ -905,7 +932,7 @@ HWTEST_F(UdmfClientTest, SetData014, TestSize.Level1) auto systemDefinedRecord2 = static_cast<SystemDefinedRecord *>(record2.get()); ASSERT_NE(systemDefinedRecord2, nullptr); - CompareDetails(systemDefinedRecord2->GetDetails()); + ComparePixelMap(systemDefinedRecord2->GetDetails(), pixelMapIn); auto systemDefinedPixelMap2 = static_cast<SystemDefinedPixelMap *>(record2.get()); ASSERT_NE(systemDefinedPixelMap2, nullptr); @@ -1280,12 +1307,12 @@ HWTEST_F(UdmfClientTest, GetSummary001, TestSize.Level1) EXPECT_EQ(summary.totalSize, size); EXPECT_EQ(summary.summary["general.text"], text->GetSize()); EXPECT_EQ(summary.summary["general.plain-text"], plainText->GetSize()); - EXPECT_EQ(summary.summary["general.file"], file->GetSize()); + EXPECT_EQ(summary.summary["general.file"], file->GetSize() + record8->GetSize()); EXPECT_EQ(summary.summary["general.image"], image->GetSize()); EXPECT_EQ(summary.summary["SystemDefinedType"], systemDefinedRecord->GetSize()); EXPECT_EQ(summary.summary["openharmony.form"], systemDefinedForm->GetSize()); EXPECT_EQ(summary.summary["ApplicationDefinedType"], applicationDefinedRecord->GetSize()); - EXPECT_EQ(summary.summary["abcdefg"], record8->GetSize()); + EXPECT_EQ(summary.summary["abcdefg"], 0); EXPECT_EQ(summary.summary["general.png"], record9->GetSize()); LOG_INFO(UDMF_TEST, "GetSummary001 end."); @@ -1635,7 +1662,8 @@ HWTEST_F(UdmfClientTest, SetData021, TestSize.Level1) unifiedDataSet.clear(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - ASSERT_TRUE(unifiedDataSet.empty()); + auto originSize = unifiedDataSet.size(); + unifiedDataSet.clear(); CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; UnifiedData data1; @@ -1654,8 +1682,7 @@ HWTEST_F(UdmfClientTest, SetData021, TestSize.Level1) SetHapToken2(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - auto size = static_cast<int32_t>(unifiedDataSet.size()); - ASSERT_EQ(size, 2); + ASSERT_EQ(unifiedDataSet.size(), originSize + 2); LOG_INFO(UDMF_TEST, "SetData021 end."); } @@ -1737,6 +1764,145 @@ HWTEST_F(UdmfClientTest, UpdateData002, TestSize.Level1) LOG_INFO(UDMF_TEST, "UpdateData002 end."); } +/** +* @tc.name: OH_Udmf_GetBatchData001 +* @tc.desc: GetBatchData data with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, OH_Udmf_GetBatchData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "OH_Udmf_GetBatchData001 begin."); + + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content"); + data.AddRecord(plainText); + CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB, + .visibility = Visibility::VISIBILITY_OWN_PROCESS }; + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption = { .key = key, .intention = UD_INTENTION_DATA_HUB }; + std::vector<UnifiedData> dataSet; + status = UdmfClient::GetInstance().GetBatchData(queryOption, dataSet); + std::shared_ptr<UnifiedRecord> record = dataSet[0].GetRecordAt(0); + ASSERT_NE(record, nullptr); + auto type = record->GetType(); + ASSERT_EQ(type, UDType::PLAIN_TEXT); + auto plainText2 = static_cast<PlainText *>(record.get()); + ASSERT_EQ(plainText2->GetContent(), "content"); + std::vector<UnifiedData> dataDelete; + status = UdmfClient::GetInstance().DeleteData(queryOption, dataDelete); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "OH_Udmf_GetBatchData001 end."); +} + +/** +* @tc.name: OH_Udmf_GetBatchData002 +* @tc.desc: GetBatchData data with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, OH_Udmf_GetBatchData002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "OH_Udmf_GetBatchData002 begin."); + SetHapToken1(); + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content"); + data.AddRecord(plainText); + CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB, + .visibility = Visibility::VISIBILITY_OWN_PROCESS }; + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + SetHapToken2(); + QueryOption queryOption = { .key = key, .intention = UD_INTENTION_DATA_HUB }; + std::vector<UnifiedData> dataSet; + status = UdmfClient::GetInstance().GetBatchData(queryOption, dataSet); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(dataSet.size(), 0); + SetHapToken1(); + std::vector<UnifiedData> dataDelete; + status = UdmfClient::GetInstance().DeleteData(queryOption, dataDelete); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(dataDelete.size(), 1); + LOG_INFO(UDMF_TEST, "OH_Udmf_GetBatchData002 end."); +} + +/** +* @tc.name: OH_Udmf_GetBatchData003 +* @tc.desc: GetBatchData data with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, OH_Udmf_GetBatchData003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "OH_Udmf_GetBatchData003 begin."); + + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content"); + data.AddRecord(plainText); + CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB, + .visibility = Visibility::VISIBILITY_ALL }; + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption = { .key = key, .intention = UD_INTENTION_DATA_HUB }; + std::vector<UnifiedData> dataSet; + status = UdmfClient::GetInstance().GetBatchData(queryOption, dataSet); + std::shared_ptr<UnifiedRecord> record = dataSet[0].GetRecordAt(0); + ASSERT_NE(record, nullptr); + auto type = record->GetType(); + ASSERT_EQ(type, UDType::PLAIN_TEXT); + auto plainText2 = static_cast<PlainText *>(record.get()); + ASSERT_EQ(plainText2->GetContent(), "content"); + std::vector<UnifiedData> dataDelete; + status = UdmfClient::GetInstance().DeleteData(queryOption, dataDelete); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(dataDelete.size(), 1); + LOG_INFO(UDMF_TEST, "OH_Udmf_GetBatchData003 end."); +} + +/** +* @tc.name: OH_Udmf_GetBatchData004 +* @tc.desc: GetBatchData data with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, OH_Udmf_GetBatchData004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "OH_Udmf_GetBatchData004 begin."); + SetHapToken1(); + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content"); + data.AddRecord(plainText); + CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB, + .visibility = Visibility::VISIBILITY_ALL }; + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + SetHapToken2(); + QueryOption queryOption = { .key = key, .intention = UD_INTENTION_DATA_HUB }; + std::vector<UnifiedData> dataSet; + status = UdmfClient::GetInstance().GetBatchData(queryOption, dataSet); + std::shared_ptr<UnifiedRecord> record = dataSet[0].GetRecordAt(0); + ASSERT_NE(record, nullptr); + auto type = record->GetType(); + ASSERT_EQ(type, UDType::PLAIN_TEXT); + auto plainText2 = static_cast<PlainText *>(record.get()); + ASSERT_EQ(plainText2->GetContent(), "content"); + SetHapToken1(); + std::vector<UnifiedData> dataDelete; + status = UdmfClient::GetInstance().DeleteData(queryOption, dataDelete); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(dataDelete.size(), 1); + LOG_INFO(UDMF_TEST, "OH_Udmf_GetBatchData004 end."); +} + /** * @tc.name: QueryData001 * @tc.desc: Query data with invalid params @@ -1784,7 +1950,8 @@ HWTEST_F(UdmfClientTest, QueryData002, TestSize.Level1) unifiedDataSet.clear(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - ASSERT_TRUE(unifiedDataSet.empty()); + auto originSize = unifiedDataSet.size(); + unifiedDataSet.clear(); CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; UnifiedData data; @@ -1831,8 +1998,7 @@ HWTEST_F(UdmfClientTest, QueryData002, TestSize.Level1) query = { .intention = UD_INTENTION_DATA_HUB }; status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - size = static_cast<int32_t>(unifiedDataSet.size()); - ASSERT_EQ(size, 2); + ASSERT_EQ(unifiedDataSet.size(), originSize + 2); LOG_INFO(UDMF_TEST, "QueryData002 end."); } @@ -1916,6 +2082,7 @@ HWTEST_F(UdmfClientTest, DeleteData002, TestSize.Level1) ASSERT_EQ(status, E_OK); unifiedDataSet.clear(); + queryOption = { .key = key }; status = UdmfClient::GetInstance().GetBatchData(queryOption, unifiedDataSet); ASSERT_TRUE(unifiedDataSet.empty()); LOG_INFO(UDMF_TEST, "DeleteData002 end."); @@ -2197,9 +2364,9 @@ HWTEST_F(UdmfClientTest, SetData028, TestSize.Level1) UnifiedData data; std::string key; std::string html = "<img data-ohos='clipboard' src=>" - "<img data-ohos='clipboard' src='https://data/storage/el2/distributedfiles/102.png'>" - "<img data-ohos='clipboard' src='file://data/storage/el2/distributedfiles/103.png'>" - "<img data-ohos='clipboard' src='file://data/storage/el2/distributedfiles/104.png'>"; + "<img data-ohos='clipboard' src='https://data/storage/el2/base/haps/102.png'>" + "<img data-ohos='clipboard' src='file://data/storage/el2/base/haps/103.png'>" + "<img data-ohos='clipboard' src='file://data/storage/el2/base/haps/104.png'>"; auto obj = std::make_shared<Object>(); obj->value_["uniformDataType"] = "general.html"; obj->value_["htmlContent"] = html; @@ -2242,10 +2409,8 @@ HWTEST_F(UdmfClientTest, SetData029, TestSize.Level1) CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; UnifiedData data; std::string key; - std::string html = "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/temp.png'><img " - "data-ohos='clipboard' " - "src=\"file:///data/storage/el2/distributedfiles/temp.png\"><img data-ohos='clipboard' " - "src='https://data/storage/el2/distributedfiles/202305301.png'>"; + std::string html = "<img data-ohos='clipboard' src='file:///data/storage/el2/base/haps/101.png'>" + "<img data-ohos='clipboard' src=\"file:///data/storage/el2/base/haps/102.png\">"; auto obj = std::make_shared<Object>(); obj->value_["uniformDataType"] = "general.html"; obj->value_["htmlContent"] = html; @@ -2265,11 +2430,17 @@ HWTEST_F(UdmfClientTest, SetData029, TestSize.Level1) UnifiedData readData; status = UdmfClient::GetInstance().GetData(option2, readData); ASSERT_EQ(status, E_OK); - + std::string tmpUri1 = "file://ohos.test.demo1/data/storage/el2/base/haps/101.png"; + std::string tmpUri2 = "file://ohos.test.demo1/data/storage/el2/base/haps/102.png"; + AppFileService::ModuleFileUri::FileUri fileUri1(tmpUri1); + AppFileService::ModuleFileUri::FileUri fileUri2(tmpUri2); + std::string readHtml = "<img data-ohos='clipboard' src='"; + readHtml += FILE_SCHEME_PREFIX + fileUri1.GetRealPath() + "'><img data-ohos='clipboard' src=\""; + readHtml += FILE_SCHEME_PREFIX + fileUri2.GetRealPath() + "\">"; std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); ASSERT_NE(readRecord, nullptr); auto readHtmlRecord = std::static_pointer_cast<Html>(readRecord); - EXPECT_EQ(readHtmlRecord->GetHtmlContent(), html); + EXPECT_EQ(readHtmlRecord->GetHtmlContent(), readHtml); auto uris = readRecord->GetUris(); EXPECT_EQ(uris.size(), 2); @@ -2288,10 +2459,10 @@ HWTEST_F(UdmfClientTest, SetData030, TestSize.Level1) CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; UnifiedData data; std::string key; - std::string html = "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/101.png'>" - "<img data-ohos='clipboard' src='https://data/storage/el2/distributedfiles/102.png'>" - "<img data-ohos='clipboard' src='file://data/storage/el2/distributedfiles/103.png'>"; - std::string uriSrc = "file:///data/storage/el2/distributedfiles/101.png"; + std::string html = "<img data-ohos='clipboard' src='file:///data/storage/el2/base/haps/101.png'>" + "<img data-ohos='clipboard' src='https://data/storage/el2/base/haps/102.png'>" + "<img data-ohos='clipboard' src='file://data/storage/el2/base/haps/103.png'>"; + std::string uriSrc = "file:///data/storage/el2/base/haps/101.png"; auto obj = std::make_shared<Object>(); obj->value_["uniformDataType"] = "general.html"; obj->value_["htmlContent"] = html; @@ -2311,11 +2482,16 @@ HWTEST_F(UdmfClientTest, SetData030, TestSize.Level1) UnifiedData readData; status = UdmfClient::GetInstance().GetData(option2, readData); ASSERT_EQ(status, E_OK); - + std::string tmpUri1 = "file://ohos.test.demo1/data/storage/el2/base/haps/101.png"; + AppFileService::ModuleFileUri::FileUri fileUri1(tmpUri1); + std::string readHtml = "<img data-ohos='clipboard' src='"; + readHtml += FILE_SCHEME_PREFIX + fileUri1.GetRealPath() + "'>"; + readHtml += "<img data-ohos='clipboard' src='https://data/storage/el2/base/haps/102.png'>" + "<img data-ohos='clipboard' src='file://data/storage/el2/base/haps/103.png'>"; std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); ASSERT_NE(readRecord, nullptr); auto readHtmlRecord = std::static_pointer_cast<Html>(readRecord); - EXPECT_EQ(readHtmlRecord->GetHtmlContent(), html); + EXPECT_EQ(readHtmlRecord->GetHtmlContent(), readHtml); auto uris = readRecord->GetUris(); EXPECT_EQ(uris.size(), 1); EXPECT_EQ(uris[0].oriUri, uriSrc); @@ -2326,7 +2502,7 @@ HWTEST_F(UdmfClientTest, SetData030, TestSize.Level1) /** * @tc.name: SetData031 -* @tc.desc: Set Html record add dfsUri and get uris data +* @tc.desc: Set Html entry is null str and get uris data * @tc.type: FUNC */ HWTEST_F(UdmfClientTest, SetData031, TestSize.Level1) @@ -2336,22 +2512,16 @@ HWTEST_F(UdmfClientTest, SetData031, TestSize.Level1) CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; UnifiedData data; std::string key; - std::string html = "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/101.png'>" - "<img data-ohos='clipboard' src='https://data/storage/el2/distributedfiles/101.png'>" - "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/102.png'>" - "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/101.png'>"; - std::string uriSrc1 = "file:///data/storage/el2/distributedfiles/101.png"; - std::string uriSrc2 = "file:///data/storage/el2/distributedfiles/102.png"; - auto obj = std::make_shared<Object>(); - obj->value_["uniformDataType"] = "general.html"; - obj->value_["htmlContent"] = html; - obj->value_["plainContent"] = "htmlPlainContent"; - auto obj2 = std::make_shared<Object>(); - obj2->value_["detail1"] = "detail1"; - obj2->value_["detail2"] = "detail2"; - obj->value_["details"] = obj2; - auto htmlRecord = std::make_shared<Html>(UDType::HTML, obj); - data.AddRecord(htmlRecord); + std::shared_ptr<Object> obj = std::make_shared<Object>(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = "http://demo.com"; + obj->value_[FILE_TYPE] = "abcdefg"; + auto record = std::make_shared<UnifiedRecord>(FILE_URI, obj); + std::string html = ""; + auto htmlRecord = Html(html, "abstract"); + htmlRecord.InitObject(); + record->AddEntry(htmlRecord.GetUtdId(), htmlRecord.GetOriginValue()); + data.AddRecord(record); auto status = UdmfClient::GetInstance().SetData(option1, data, key); ASSERT_EQ(status, E_OK); @@ -2364,41 +2534,23 @@ HWTEST_F(UdmfClientTest, SetData031, TestSize.Level1) std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); ASSERT_NE(readRecord, nullptr); + auto entryValue = readRecord->GetEntry(UtdUtils::GetUtdIdFromUtdEnum(UDType::HTML)); + auto object = std::get<std::shared_ptr<Object>>(entryValue); + ASSERT_NE(object, nullptr); + auto iter = object->value_.find(HTML_CONTENT); + ASSERT_TRUE(iter != object->value_.end()); + EXPECT_TRUE(std::holds_alternative<std::string>(iter->second)); + auto content = std::get<std::string>(iter->second); + EXPECT_EQ(content, html); auto uris = readRecord->GetUris(); - EXPECT_EQ(uris.size(), 3); - EXPECT_EQ(uris[0].oriUri, uriSrc1); - EXPECT_EQ(uris[1].oriUri, uriSrc2); - EXPECT_EQ(uris[2].oriUri, uriSrc1); - std::string strUri1 = "file:///data/1.png"; - std::string strUri2 = "file:///data/2.png"; - std::unordered_map<std::string, std::string> dfsUris; - dfsUris.insert(std::make_pair(uriSrc1, strUri1)); - dfsUris.insert(std::make_pair(uriSrc2, strUri2)); - readRecord->ComputeUris([&dfsUris] (UriInfo &uriInfo) { - auto iter = dfsUris.find(uriInfo.oriUri); - if (iter != dfsUris.end()) { - uriInfo.dfsUri = iter->second; - } - return true; - }); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(readData); - std::string htmlResult = "<img data-ohos='clipboard' src='file:///data/1.png'>" - "<img data-ohos='clipboard' src='https://data/storage/el2/distributedfiles/101.png'>" - "<img data-ohos='clipboard' src='file:///data/2.png'>" - "<img data-ohos='clipboard' src='file:///data/1.png'>"; - auto readHtmlRecord = std::static_pointer_cast<Html>(readRecord); - EXPECT_EQ(readHtmlRecord->GetHtmlContent(), htmlResult); - auto uris1 = readRecord->GetUris(); - EXPECT_EQ(uris1[0].dfsUri, strUri1); - EXPECT_EQ(uris1[1].dfsUri, strUri2); - EXPECT_EQ(uris1[2].dfsUri, strUri1); + EXPECT_EQ(uris.size(), 0); LOG_INFO(UDMF_TEST, "SetData031 end."); } /** * @tc.name: SetData032 -* @tc.desc: Set Html entry is null str and get uris data +* @tc.desc: Set Html entry include invalid value and get uris data * @tc.type: FUNC */ HWTEST_F(UdmfClientTest, SetData032, TestSize.Level1) @@ -2413,7 +2565,10 @@ HWTEST_F(UdmfClientTest, SetData032, TestSize.Level1) obj->value_[FILE_URI_PARAM] = "http://demo.com"; obj->value_[FILE_TYPE] = "abcdefg"; auto record = std::make_shared<UnifiedRecord>(FILE_URI, obj); - std::string html = ""; + std::string html = "<img data-ohos='clipboard' src=>" + "<img data-ohos='clipboard' src='https://data/storage/el2/base/haps/102.png'>" + "<img data-ohos='clipboard' src='file://data/storage/el2/base/haps/103.png'>" + "<img data-ohos='clipboard' src='file://data/storage/el2/base/haps/104.png'>"; auto htmlRecord = Html(html, "abstract"); htmlRecord.InitObject(); record->AddEntry(htmlRecord.GetUtdId(), htmlRecord.GetOriginValue()); @@ -2446,7 +2601,7 @@ HWTEST_F(UdmfClientTest, SetData032, TestSize.Level1) /** * @tc.name: SetData033 -* @tc.desc: Set Html entry include invalid value and get uris data +* @tc.desc: Set Html entry include valid value and get uris data * @tc.type: FUNC */ HWTEST_F(UdmfClientTest, SetData033, TestSize.Level1) @@ -2459,26 +2614,29 @@ HWTEST_F(UdmfClientTest, SetData033, TestSize.Level1) std::shared_ptr<Object> obj = std::make_shared<Object>(); obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; obj->value_[FILE_URI_PARAM] = "http://demo.com"; - obj->value_[FILE_TYPE] = "abcdefg"; auto record = std::make_shared<UnifiedRecord>(FILE_URI, obj); - std::string html = "<img data-ohos='clipboard' src=>" - "<img data-ohos='clipboard' src='https://data/storage/el2/distributedfiles/102.png'>" - "<img data-ohos='clipboard' src='file://data/storage/el2/distributedfiles/103.png'>" - "<img data-ohos='clipboard' src='file://data/storage/el2/distributedfiles/104.png'>"; + std::string html = "<img data-ohos='clipboard' src='file://data/storage/el2/base/haps/101.png'>" + "<img data-ohos='clipboard' src='https://data/storage/el2/base/haps/102.png'>" + "<img data-ohos='clipboard' src='file:///data/storage/el2/base/haps/103.png'>"; + std::string uriSrc = "file:///data/storage/el2/base/haps/103.png"; auto htmlRecord = Html(html, "abstract"); htmlRecord.InitObject(); record->AddEntry(htmlRecord.GetUtdId(), htmlRecord.GetOriginValue()); data.AddRecord(record); auto status = UdmfClient::GetInstance().SetData(option1, data, key); ASSERT_EQ(status, E_OK); - QueryOption option2 = { .key = key }; AddPrivilege1(option2); SetHapToken1(); UnifiedData readData; status = UdmfClient::GetInstance().GetData(option2, readData); ASSERT_EQ(status, E_OK); - + std::string tmpUri1 = "file://ohos.test.demo1/data/storage/el2/base/haps/103.png"; + AppFileService::ModuleFileUri::FileUri fileUri1(tmpUri1); + std::string readHtml = "<img data-ohos='clipboard' src='file://data/storage/el2/base/haps/101.png'>" + "<img data-ohos='clipboard' src='https://data/storage/el2/base/haps/102.png'>" + "<img data-ohos='clipboard' src='"; + readHtml += FILE_SCHEME_PREFIX + fileUri1.GetRealPath() + "'>"; std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); ASSERT_NE(readRecord, nullptr); auto entryValue = readRecord->GetEntry(UtdUtils::GetUtdIdFromUtdEnum(UDType::HTML)); @@ -2488,16 +2646,18 @@ HWTEST_F(UdmfClientTest, SetData033, TestSize.Level1) ASSERT_TRUE(iter != object->value_.end()); EXPECT_TRUE(std::holds_alternative<std::string>(iter->second)); auto content = std::get<std::string>(iter->second); - EXPECT_EQ(content, html); + EXPECT_EQ(content, readHtml); auto uris = readRecord->GetUris(); - EXPECT_EQ(uris.size(), 0); + EXPECT_EQ(uris.size(), 1); + EXPECT_EQ(uris[0].oriUri, uriSrc); + EXPECT_TRUE(uris[0].dfsUri.empty()); LOG_INFO(UDMF_TEST, "SetData033 end."); } /** * @tc.name: SetData034 -* @tc.desc: Set Html entry include valid value and get uris data +* @tc.desc: test html record process * @tc.type: FUNC */ HWTEST_F(UdmfClientTest, SetData034, TestSize.Level1) @@ -2505,23 +2665,28 @@ HWTEST_F(UdmfClientTest, SetData034, TestSize.Level1) LOG_INFO(UDMF_TEST, "SetData034 begin."); CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; - UnifiedData data; + UnifiedData data1; + std::shared_ptr<UnifiedRecord> record = std::make_shared<UnifiedRecord>(); + data1.AddRecord(record); std::string key; - std::shared_ptr<Object> obj = std::make_shared<Object>(); - obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; - obj->value_[FILE_URI_PARAM] = "http://demo.com"; - obj->value_[FILE_TYPE] = "abcdefg"; - auto record = std::make_shared<UnifiedRecord>(FILE_URI, obj); - std::string html = "<img data-ohos='clipboard' src='file://data/storage/el2/distributedfiles/101.png'>" - "<img data-ohos='clipboard' src='https://data/storage/el2/distributedfiles/102.png'>" - "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/103.png'>"; - std::string uriSrc = "file:///data/storage/el2/distributedfiles/103.png"; - auto htmlRecord = Html(html, "abstract"); - htmlRecord.InitObject(); - record->AddEntry(htmlRecord.GetUtdId(), htmlRecord.GetOriginValue()); - data.AddRecord(record); + UnifiedHtmlRecordProcess::RebuildHtmlRecord(data1); + UnifiedHtmlRecordProcess::GetUriFromHtmlRecord(data1); + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("plainContent"); + data.AddRecord(plainText); auto status = UdmfClient::GetInstance().SetData(option1, data, key); ASSERT_EQ(status, E_OK); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "this is a content"); + record1->ClearUris(); + data.AddRecord(record1); + auto file = std::make_shared<File>(); + file->SetRemoteUri("remoteUri"); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + file->SetDetails(details); + data.AddRecord(file); + UnifiedHtmlRecordProcess::RebuildHtmlRecord(data); QueryOption option2 = { .key = key }; AddPrivilege1(option2); @@ -2530,27 +2695,12 @@ HWTEST_F(UdmfClientTest, SetData034, TestSize.Level1) status = UdmfClient::GetInstance().GetData(option2, readData); ASSERT_EQ(status, E_OK); - std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); - ASSERT_NE(readRecord, nullptr); - auto entryValue = readRecord->GetEntry(UtdUtils::GetUtdIdFromUtdEnum(UDType::HTML)); - auto object = std::get<std::shared_ptr<Object>>(entryValue); - ASSERT_NE(object, nullptr); - auto iter = object->value_.find(HTML_CONTENT); - ASSERT_TRUE(iter != object->value_.end()); - EXPECT_TRUE(std::holds_alternative<std::string>(iter->second)); - auto content = std::get<std::string>(iter->second); - EXPECT_EQ(content, html); - auto uris = readRecord->GetUris(); - EXPECT_EQ(uris.size(), 1); - EXPECT_EQ(uris[0].oriUri, uriSrc); - EXPECT_TRUE(uris[0].dfsUri.empty()); - LOG_INFO(UDMF_TEST, "SetData034 end."); } /** * @tc.name: SetData035 -* @tc.desc: Set Html entry add dfsUri and get uris data +* @tc.desc: test html record process * @tc.type: FUNC */ HWTEST_F(UdmfClientTest, SetData035, TestSize.Level1) @@ -2559,27 +2709,31 @@ HWTEST_F(UdmfClientTest, SetData035, TestSize.Level1) CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; UnifiedData data; + auto text = std::make_shared<Text>(); + data.AddRecord(text); + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("plainContent"); + data.AddRecord(plainText); + auto html = std::make_shared<Html>(); + html->SetPlainContent("htmlContent"); + data.AddRecord(html); std::string key; - std::shared_ptr<Object> obj = std::make_shared<Object>(); - obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; - obj->value_[FILE_URI_PARAM] = "http://demo.com"; - obj->value_[FILE_TYPE] = "abcdefg"; - auto record = std::make_shared<UnifiedRecord>(FILE_URI, obj); - std::string html = "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/101.png'>" - "<img data-ohos='clipboard' src='https://data/storage/el2/distributedfiles/202305301.png'>" - "<img data-ohos='clipboard' src='file://data/storage/el2/distributedfiles/202305301.png'>" - "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/102.png'>" - "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/103.png'>"; - std::string uriSrc1 = "file:///data/storage/el2/distributedfiles/101.png"; - std::string uriSrc2 = "file:///data/storage/el2/distributedfiles/102.png"; - std::string uriSrc3 = "file:///data/storage/el2/distributedfiles/103.png"; - auto htmlRecord = Html(html, "abstract"); - htmlRecord.InitObject(); - record->AddEntry(htmlRecord.GetUtdId(), htmlRecord.GetOriginValue()); - data.AddRecord(record); auto status = UdmfClient::GetInstance().SetData(option1, data, key); ASSERT_EQ(status, E_OK); + UnifiedData data1; + std::shared_ptr<Object> obj = std::make_shared<Object>(); + obj->value_[PLAIN_CONTENT] = "http://demo.com"; + obj->value_[HTML_CONTENT] = 10; + plainText->AddEntry("general.html", obj); + data1.AddRecord(plainText); + UnifiedHtmlRecordProcess::GetUriFromHtmlRecord(data1); + UnifiedHtmlRecordProcess::RebuildHtmlRecord(data1); + UnifiedData data2; + text->AddEntry("general.html", ""); + data2.AddRecord(text); + UnifiedHtmlRecordProcess::GetUriFromHtmlRecord(data2); + UnifiedHtmlRecordProcess::RebuildHtmlRecord(data2); QueryOption option2 = { .key = key }; AddPrivilege1(option2); SetHapToken1(); @@ -2587,267 +2741,28 @@ HWTEST_F(UdmfClientTest, SetData035, TestSize.Level1) status = UdmfClient::GetInstance().GetData(option2, readData); ASSERT_EQ(status, E_OK); - std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); - ASSERT_NE(readRecord, nullptr); - auto uris = readRecord->GetUris(); - EXPECT_EQ(uris.size(), 3); - EXPECT_EQ(uris[0].oriUri, uriSrc1); - EXPECT_EQ(uris[1].oriUri, uriSrc2); - EXPECT_EQ(uris[2].oriUri, uriSrc3); - std::string strUri1 = "file:///data/201.png"; - std::string strUri2 = "file:///data/202.png"; - std::string strUri3 = "file:///data/203.png"; - std::unordered_map<std::string, std::string> dfsUris; - dfsUris.insert(std::make_pair(uriSrc1, strUri1)); - dfsUris.insert(std::make_pair(uriSrc2, strUri2)); - dfsUris.insert(std::make_pair(uriSrc3, strUri3)); - readRecord->ComputeUris([&dfsUris] (UriInfo &uriInfo) { - auto iter = dfsUris.find(uriInfo.oriUri); - if (iter != dfsUris.end()) { - uriInfo.dfsUri = iter->second; - } - return true; - }); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(readData); - std::shared_ptr<UnifiedRecord> rebuildRecord = readData.GetRecordAt(0); - std::string htmlResult = "<img data-ohos='clipboard' src='file:///data/201.png'>" - "<img data-ohos='clipboard' src='https://data/storage/el2/distributedfiles/202305301.png'>" - "<img data-ohos='clipboard' src='file://data/storage/el2/distributedfiles/202305301.png'>" - "<img data-ohos='clipboard' src='file:///data/202.png'>" - "<img data-ohos='clipboard' src='file:///data/203.png'>"; - auto entryValue = rebuildRecord->GetEntry(UtdUtils::GetUtdIdFromUtdEnum(UDType::HTML)); - auto object = std::get<std::shared_ptr<Object>>(entryValue); - ASSERT_NE(object, nullptr); - auto iter = object->value_.find(HTML_CONTENT); - ASSERT_TRUE(iter != object->value_.end()); - EXPECT_TRUE(std::holds_alternative<std::string>(iter->second)); - auto content = std::get<std::string>(iter->second); - EXPECT_EQ(content, htmlResult); - LOG_INFO(UDMF_TEST, "SetData035 end."); } /** -* @tc.name: SetData036 -* @tc.desc: split and rebuild html value performance test +* @tc.name: GetSummary003 +* @tc.desc: Get summary data * @tc.type: FUNC */ -HWTEST_F(UdmfClientTest, SetData036, TestSize.Level1) +HWTEST_F(UdmfClientTest, GetSummary003, TestSize.Level1) { - LOG_INFO(UDMF_TEST, "SetData036 begin."); + LOG_INFO(UDMF_TEST, "GetSummary003 begin."); CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; UnifiedData data; std::string key; - uint32_t kNumImages = 1000; - std::string html = ""; - for (uint32_t i = 0; i < kNumImages; i++) { - html += "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/101.png'>"; - } - auto obj = std::make_shared<Object>(); - obj->value_["uniformDataType"] = "general.html"; - obj->value_["htmlContent"] = html; - obj->value_["plainContent"] = "htmlPlainContent"; - auto obj2 = std::make_shared<Object>(); - obj2->value_["detail1"] = "detail1"; - obj2->value_["detail2"] = "detail2"; - obj->value_["details"] = obj2; - auto htmlRecord = std::make_shared<Html>(UDType::HTML, obj); - data.AddRecord(htmlRecord); - auto start = std::chrono::high_resolution_clock::now(); - auto status = UdmfClient::GetInstance().SetData(option1, data, key); - ASSERT_EQ(status, E_OK); - - QueryOption option2 = { .key = key }; - AddPrivilege1(option2); - SetHapToken1(); - UnifiedData readData; - status = UdmfClient::GetInstance().GetData(option2, readData); - ASSERT_EQ(status, E_OK); - - std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); - ASSERT_NE(readRecord, nullptr); - auto uris = readRecord->GetUris(); - EXPECT_EQ(uris.size(), kNumImages); - std::string strUri = "file:///data/1.png"; - readRecord->ComputeUris([&strUri] (UriInfo &uriInfo) { - uriInfo.dfsUri = strUri; - return true; - }); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(readData); - auto end = std::chrono::high_resolution_clock::now(); - auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); - LOG_INFO(UDMF_TEST, "SetData036 count duration=%{public}lld", duration.count()); - std::string htmlResult = ""; - for (uint32_t i = 0; i < kNumImages; i++) { - htmlResult += "<img data-ohos='clipboard' src='file:///data/1.png'>"; - } - auto readHtmlRecord = std::static_pointer_cast<Html>(readRecord); - EXPECT_EQ(readHtmlRecord->GetHtmlContent(), htmlResult); - - LOG_INFO(UDMF_TEST, "SetData036 end."); -} - -/** -* @tc.name: SetData037 -* @tc.desc: test html record process -* @tc.type: FUNC -*/ -HWTEST_F(UdmfClientTest, SetData037, TestSize.Level1) -{ - LOG_INFO(UDMF_TEST, "SetData037 begin."); - - CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; - UnifiedData data1; - std::shared_ptr<UnifiedRecord> record = std::make_shared<UnifiedRecord>(); - data1.AddRecord(record); - std::string key; - UnifiedHtmlRecordProcess::RebuildHtmlRecord(data1); - UnifiedHtmlRecordProcess::GetUriFromHtmlRecord(data1); - UnifiedData data; - auto plainText = std::make_shared<PlainText>(); - plainText->SetContent("plainContent"); - data.AddRecord(plainText); - auto status = UdmfClient::GetInstance().SetData(option1, data, key); - ASSERT_EQ(status, E_OK); - std::shared_ptr<UnifiedRecord> record1 = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "this is a content"); - record1->ClearUris(); - data.AddRecord(record1); - auto file = std::make_shared<File>(); - file->SetRemoteUri("remoteUri"); - UDDetails details; - details.insert({ "udmf_key", "udmf_value" }); - file->SetDetails(details); - data.AddRecord(file); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(data); - - QueryOption option2 = { .key = key }; - AddPrivilege1(option2); - SetHapToken1(); - UnifiedData readData; - status = UdmfClient::GetInstance().GetData(option2, readData); - ASSERT_EQ(status, E_OK); - - LOG_INFO(UDMF_TEST, "SetData037 end."); -} - -/** -* @tc.name: SetData038 -* @tc.desc: test html record process -* @tc.type: FUNC -*/ -HWTEST_F(UdmfClientTest, SetData038, TestSize.Level1) -{ - LOG_INFO(UDMF_TEST, "SetData038 begin."); - - CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; - UnifiedData data; - std::string key; - std::shared_ptr<Object> fileObj = std::make_shared<Object>(); - fileObj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; - fileObj->value_[FILE_URI_PARAM] = "http://demo.com"; - auto record = std::make_shared<UnifiedRecord>(FILE_URI, fileObj); - std::string html = "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/103.png'>"; - auto htmlRecord = Html(html, "abstract"); - htmlRecord.InitObject(); - record->AddEntry(htmlRecord.GetUtdId(), htmlRecord.GetOriginValue()); - data.AddRecord(record); - auto status = UdmfClient::GetInstance().SetData(option1, data, key); - ASSERT_EQ(status, E_OK); - - QueryOption option2 = { .key = key }; - AddPrivilege1(option2); - SetHapToken1(); - UnifiedData readData; - status = UdmfClient::GetInstance().GetData(option2, readData); - ASSERT_EQ(status, E_OK); - - std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); - ASSERT_NE(readRecord, nullptr); - std::shared_ptr<std::map<std::string, ValueType>> entries = std::make_shared<std::map<std::string, ValueType>>(); - std::string utd = "general.html"; - ValueType value = "htmlContent"; - std::shared_ptr<Object> obj = std::make_shared<Object>(); - obj->value_[HTML_CONTENT] = 10; - std::shared_ptr<Object> obj1 = std::make_shared<Object>(); - obj1->value_[HTML_CONTENT] = "file:///data/storage/el2/distributedfiles/103.png"; - readRecord->SetInnerEntries(entries); - readRecord->SetType(UDType::HTML); - entries->insert_or_assign(std::move(utd), std::move(value)); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(readData); - entries->insert_or_assign(std::move(utd), std::move(obj)); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(readData); - entries->insert_or_assign(std::move(utd), std::move(obj1)); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(readData); - - LOG_INFO(UDMF_TEST, "SetData038 end."); -} - -/** -* @tc.name: SetData039 -* @tc.desc: test html record process -* @tc.type: FUNC -*/ -HWTEST_F(UdmfClientTest, SetData039, TestSize.Level1) -{ - LOG_INFO(UDMF_TEST, "SetData039 begin."); - - CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; - UnifiedData data; - auto text = std::make_shared<Text>(); - data.AddRecord(text); - auto plainText = std::make_shared<PlainText>(); - plainText->SetContent("plainContent"); - data.AddRecord(plainText); - auto html = std::make_shared<Html>(); - html->SetPlainContent("htmlContent"); - data.AddRecord(html); - std::string key; - auto status = UdmfClient::GetInstance().SetData(option1, data, key); - ASSERT_EQ(status, E_OK); - - UnifiedData data1; - std::shared_ptr<Object> obj = std::make_shared<Object>(); - obj->value_[PLAIN_CONTENT] = "http://demo.com"; - obj->value_[HTML_CONTENT] = 10; - plainText->AddEntry("general.html", obj); - data1.AddRecord(plainText); - UnifiedHtmlRecordProcess::GetUriFromHtmlRecord(data1); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(data1); - UnifiedData data2; - text->AddEntry("general.html", ""); - data2.AddRecord(text); - UnifiedHtmlRecordProcess::GetUriFromHtmlRecord(data2); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(data2); - QueryOption option2 = { .key = key }; - AddPrivilege1(option2); - SetHapToken1(); - UnifiedData readData; - status = UdmfClient::GetInstance().GetData(option2, readData); - ASSERT_EQ(status, E_OK); - - LOG_INFO(UDMF_TEST, "SetData039 end."); -} - -/** -* @tc.name: GetSummary003 -* @tc.desc: Get summary data -* @tc.type: FUNC -*/ -HWTEST_F(UdmfClientTest, GetSummary003, TestSize.Level1) -{ - LOG_INFO(UDMF_TEST, "GetSummary003 begin."); - - CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; - UnifiedData data; - std::string key; - - UDDetails details; - details.insert({ "udmf_key", "udmf_value" }); - std::string value; - int64_t maxSize = 512 * 1024; - for (int64_t i = 0; i < maxSize; ++i) { - value += "11"; + + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + std::string value; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "11"; } details.insert({ value, value }); @@ -2961,7 +2876,7 @@ HWTEST_F(UdmfClientTest, QueryUDSData001, TestSize.Level1) unifiedDataSet.clear(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - ASSERT_TRUE(unifiedDataSet.empty()); + unifiedDataSet.clear(); CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; UnifiedData data; @@ -3000,7 +2915,7 @@ HWTEST_F(UdmfClientTest, QueryUDSData002, TestSize.Level1) unifiedDataSet.clear(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - ASSERT_TRUE(unifiedDataSet.empty()); + unifiedDataSet.clear(); CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; UnifiedData data; @@ -3064,7 +2979,7 @@ HWTEST_F(UdmfClientTest, QueryUDSData003, TestSize.Level1) unifiedDataSet.clear(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - ASSERT_TRUE(unifiedDataSet.empty()); + unifiedDataSet.clear(); CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; UnifiedData data; @@ -3128,7 +3043,7 @@ HWTEST_F(UdmfClientTest, QueryUDSData004, TestSize.Level1) unifiedDataSet.clear(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - ASSERT_TRUE(unifiedDataSet.empty()); + unifiedDataSet.clear(); CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; UnifiedData data; @@ -3192,7 +3107,7 @@ HWTEST_F(UdmfClientTest, QueryUDSData005, TestSize.Level1) unifiedDataSet.clear(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - ASSERT_TRUE(unifiedDataSet.empty()); + unifiedDataSet.clear(); CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; UnifiedData data; @@ -3274,82 +3189,66 @@ HWTEST_F(UdmfClientTest, GetSelfBundleName001, TestSize.Level1) HWTEST_F(UdmfClientTest, GetSummary004, TestSize.Level1) { LOG_INFO(UDMF_TEST, "GetSummary004 begin."); - CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; UnifiedData data; std::string key; - UDDetails details; details.insert({ "udmf_key", "udmf_value" }); - std::shared_ptr<Object> obj = std::make_shared<Object>(); obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; obj->value_[FILE_URI_PARAM] = "http://demo.com"; obj->value_[FILE_TYPE] = "abcdefg"; auto record = std::make_shared<UnifiedRecord>(FILE_URI, obj); - auto size0 = record->GetSize(); - auto plainText = PlainText("content", "abstract"); auto size1 = plainText.GetSize(); plainText.InitObject(); - record->AddEntry(plainText.GetUtdId(), plainText.GetOriginValue()); - + record->AddEntry(plainText.GetUtdId2(), plainText.GetOriginValue()); auto image = Image("uri"); image.SetDetails(details); auto size2 = image.GetSize(); image.InitObject(); - record->AddEntry(image.GetUtdId(), image.GetOriginValue()); - + record->AddEntry(image.GetUtdId2(), image.GetOriginValue()); std::vector<uint8_t> raw = {1, 2, 3, 4, 5}; SystemDefinedPixelMap pixelMap = SystemDefinedPixelMap(raw); pixelMap.SetDetails(details); auto size3 = pixelMap.GetSize(); pixelMap.InitObject(); - record->AddEntry(pixelMap.GetUtdId(), pixelMap.GetOriginValue()); - + record->AddEntry(pixelMap.GetUtdId2(), pixelMap.GetOriginValue()); raw = {1, 2, 3, 4, 5}; auto applicationDefinedRecord = ApplicationDefinedRecord("my.type", raw); auto size4 = applicationDefinedRecord.GetSize(); applicationDefinedRecord.InitObject(); - record->AddEntry(applicationDefinedRecord.GetUtdId(), applicationDefinedRecord.GetOriginValue()); - + record->AddEntry(applicationDefinedRecord.GetUtdId2(), applicationDefinedRecord.GetOriginValue()); data.AddRecord(record); - auto status = UdmfClient::GetInstance().SetData(option1, data, key); ASSERT_EQ(status, E_OK); - QueryOption option2 = { .key = key }; Summary summary; status = UdmfClient::GetInstance().GetSummary(option2, summary); - ASSERT_EQ(status, E_OK); - EXPECT_EQ(summary.summary["abcdefg"], size0); EXPECT_EQ(summary.summary["general.plain-text"], size1); EXPECT_EQ(summary.summary["general.image"], size2); EXPECT_EQ(summary.summary["openharmony.pixel-map"], size3); EXPECT_EQ(summary.summary["ApplicationDefinedType"], size4); - EXPECT_EQ(summary.totalSize, record->GetSize()); - UnifiedData readData; status = UdmfClient::GetInstance().GetData(option2, readData); ASSERT_EQ(E_OK, status); ASSERT_EQ(1, readData.GetRecords().size()); auto readRecord = readData.GetRecordAt(0); auto entries = readRecord->GetEntries(); - ASSERT_EQ(5, entries->size()); + ASSERT_EQ(4, entries->size()); auto readFileUri = std::get<std::shared_ptr<Object>>(entries->at("general.file-uri")); - EXPECT_EQ("abcdefg", std::get<std::string>(readFileUri->value_[FILE_TYPE])); + EXPECT_EQ("general.image", std::get<std::string>(readFileUri->value_[FILE_TYPE])); + EXPECT_EQ("uri", std::get<std::string>(readFileUri->value_[ORI_URI])); auto readPlainText = std::get<std::shared_ptr<Object>>(entries->at("general.plain-text")); EXPECT_EQ("abstract", std::get<std::string>(readPlainText->value_[ABSTRACT])); - auto readImage = std::get<std::shared_ptr<Object>>(entries->at("general.image")); - EXPECT_EQ("uri", std::get<std::string>(readImage->value_[ORI_URI])); auto readPixelMap = std::get<std::shared_ptr<Object>>(entries->at("openharmony.pixel-map")); EXPECT_EQ(5, std::get<std::vector<uint8_t>>(readPixelMap->value_[PIXEL_MAP]).size()); auto readDefinedRecord = std::get<std::shared_ptr<Object>>(entries->at("my.type")); EXPECT_EQ(5, std::get<std::vector<uint8_t>>(readDefinedRecord->value_[ARRAY_BUFFER]).size()); - auto value = std::get<std::shared_ptr<Object>>(readRecord->GetValue()); - EXPECT_EQ("abcdefg", std::get<std::string>(value->value_[FILE_TYPE])); + auto valueType = readRecord->GetValue(); + EXPECT_TRUE(std::holds_alternative<std::monostate>(readRecord->GetValue())); LOG_INFO(UDMF_TEST, "GetSummary004 end."); } @@ -3375,25 +3274,25 @@ HWTEST_F(UdmfClientTest, GetSummary005, TestSize.Level1) auto link = Link("url", "descritpion"); auto size1 = link.GetSize(); link.InitObject(); - record->AddEntry(link.GetUtdId(), link.GetOriginValue()); + record->AddEntry(link.GetUtdId2(), link.GetOriginValue()); auto folder = Folder("uri"); folder.SetDetails(details); auto size2 = folder.GetSize(); folder.InitObject(); - record->AddEntry(folder.GetUtdId(), folder.GetOriginValue()); + record->AddEntry(folder.GetUtdId2(), folder.GetOriginValue()); std::vector<uint8_t> raw = {1, 2, 3, 4, 5}; auto applicationDefinedRecord1 = ApplicationDefinedRecord("your.type", raw); auto size3 = applicationDefinedRecord1.GetSize(); applicationDefinedRecord1.InitObject(); - record->AddEntry(applicationDefinedRecord1.GetUtdId(), applicationDefinedRecord1.GetOriginValue()); + record->AddEntry(applicationDefinedRecord1.GetUtdId2(), applicationDefinedRecord1.GetOriginValue()); raw = {1, 2, 3, 4, 5}; auto applicationDefinedRecord2 = ApplicationDefinedRecord("my.type", raw); auto size4 = applicationDefinedRecord2.GetSize(); applicationDefinedRecord2.InitObject(); - record->AddEntry(applicationDefinedRecord2.GetUtdId(), applicationDefinedRecord2.GetOriginValue()); + record->AddEntry(applicationDefinedRecord2.GetUtdId2(), applicationDefinedRecord2.GetOriginValue()); auto form = SystemDefinedForm(); form.SetDetails(details); @@ -3405,7 +3304,7 @@ HWTEST_F(UdmfClientTest, GetSummary005, TestSize.Level1) form.SetBundleName("bundleName"); auto size5 = form.GetSize(); form.InitObject(); - record->AddEntry(form.GetUtdId(), form.GetOriginValue()); + record->AddEntry(form.GetUtdId2(), form.GetOriginValue()); raw = {1, 2, 3, 4, 5}; std::shared_ptr<Object> obj = std::make_shared<Object>(); @@ -3456,7 +3355,7 @@ HWTEST_F(UdmfClientTest, GetSummary005, TestSize.Level1) EXPECT_EQ("content1", std::get<std::string>(readHtml->value_[HTML_CONTENT])); auto readHyperlink = std::get<std::shared_ptr<Object>>(entries->at("general.hyperlink")); EXPECT_EQ("descritpion", std::get<std::string>(readHyperlink->value_[DESCRIPTION])); - auto readFolder = std::get<std::shared_ptr<Object>>(entries->at("general.folder")); + auto readFolder = std::get<std::shared_ptr<Object>>(entries->at("general.file-uri")); EXPECT_EQ("uri", std::get<std::string>(readFolder->value_[ORI_URI])); auto readDefinedRecord = std::get<std::shared_ptr<Object>>(entries->at("your.type")); EXPECT_EQ(5, std::get<std::vector<uint8_t>>(readDefinedRecord->value_[ARRAY_BUFFER]).size()); @@ -3690,7 +3589,7 @@ HWTEST_F(UdmfClientTest, GetBatchData001, TestSize.Level1) unifiedDataSet.clear(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - ASSERT_TRUE(unifiedDataSet.empty()); + unifiedDataSet.clear(); CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; UnifiedData data; @@ -3719,4 +3618,464 @@ HWTEST_F(UdmfClientTest, GetBatchData001, TestSize.Level1) LOG_INFO(UDMF_TEST, "GetBatchData001 end."); } + +/** +* @tc.name: UpdateData003 +* @tc.desc: test update data properties +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, UpdateData003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData003 begin."); + QueryOption query = { .intention = Intention::UD_INTENTION_DATA_HUB }; + std::vector<UnifiedData> unifiedDataSet; + auto status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + unifiedDataSet.clear(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + unifiedDataSet.clear(); + CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData003"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + query = { .key = key, .intention = Intention::UD_INTENTION_DATA_HUB }; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(unifiedDataSet.size(), 1); + auto readProperties = unifiedDataSet[0].GetProperties(); + ASSERT_NE(readProperties, nullptr); + EXPECT_EQ(readProperties->tag, tag); + std::shared_ptr<UnifiedDataProperties> properties1 = std::make_shared<UnifiedDataProperties>(); + std::string tag1 = "this is a tag of test UpdateData003test"; + properties1->tag = tag1; + data.SetProperties(std::move(properties1)); + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_OK); + unifiedDataSet.clear(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(unifiedDataSet.size(), 1); + auto readProperties1 = unifiedDataSet[0].GetProperties(); + ASSERT_NE(readProperties1, nullptr); + EXPECT_EQ(readProperties1->tag, tag1); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + unifiedDataSet.clear(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + ASSERT_TRUE(unifiedDataSet.empty()); + LOG_INFO(UDMF_TEST, "UpdateData003 end."); +} + +/** +* @tc.name: SetData036 +* @tc.desc: test set html type data image src is base64 format +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData036, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData036 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data; + std::string key; + std::shared_ptr<Object> obj = std::make_shared<Object>(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = "http://demo.com"; + auto record = std::make_shared<UnifiedRecord>(FILE_URI, obj); + std::string html = "<img data-ohos='clipboard' src='data:image/png;base64,IVBORw0KGgoAAAANSUhEUgAAAF'>"; + auto htmlRecord = Html(html, "abstract"); + htmlRecord.InitObject(); + record->AddEntry(htmlRecord.GetUtdId(), htmlRecord.GetOriginValue()); + data.AddRecord(record); + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + QueryOption option2 = { .key = key }; + AddPrivilege1(option2); + SetHapToken1(); + UnifiedData readData; + status = UdmfClient::GetInstance().GetData(option2, readData); + ASSERT_EQ(status, E_OK); + std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); + ASSERT_NE(readRecord, nullptr); + auto uris = readRecord->GetUris(); + EXPECT_EQ(uris.size(), 0); + + LOG_INFO(UDMF_TEST, "SetData036 end."); +} + +/** +* @tc.name: GetParentType001 +* @tc.desc: test Summary fileType +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, GetParentType001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetParentType001 begin."); + Summary oldSummary; + std::map<std::string, int64_t> sumMap = { + { "general.file", 10 }, + { "general.png", 10 }, + { "general.html", 10 }, + { "general.jpeg", 10 }, + { "general.avi", 10 }, + { "com.adobe.pdf", 10 }, + { "general.text", 10 }, + { "aabbcc", 10 } + }; + oldSummary.summary = std::move(sumMap); + oldSummary.totalSize = 80; + Summary newSummary; + auto ret = UdmfClient::GetInstance().GetParentType(oldSummary, newSummary); + ASSERT_EQ(ret, E_OK); + EXPECT_EQ(newSummary.totalSize, 80); + EXPECT_EQ(newSummary.summary["general.file"], 20); + EXPECT_EQ(newSummary.summary["general.image"], 20); + EXPECT_EQ(newSummary.summary["general.html"], 10); + EXPECT_EQ(newSummary.summary["general.video"], 10); + EXPECT_EQ(newSummary.summary["aabbcc"], 10); + EXPECT_EQ(newSummary.summary["general.text"], 10); +} + +/** + * @tc.name: GetBundleNameByUdKey001 + * @tc.desc: test GetBundleNameByUdKey with valid UD key + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, GetBundleNameByUdKey001, TestSize.Level1) +{ + std::string key = "udmf://drag/com.example.app/N]2fIEMbrJj@<hH7zpXzzQ>wp:jMuPa7"; + std::string expectedBundle = "com.example.app"; + + std::string actualBundle = UdmfClient::GetInstance().GetBundleNameByUdKey(key); + EXPECT_EQ(actualBundle, expectedBundle); +} + +/** + * @tc.name: GetBundleNameByUdKey002 + * @tc.desc: test GetBundleNameByUdKey with invalid UD key (missing schema) + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, GetBundleNameByUdKey002, TestSize.Level1) +{ + std::string key = "invalid://share/com.example.app/123"; + std::string actualBundle = UdmfClient::GetInstance().GetBundleNameByUdKey(key); + EXPECT_EQ(actualBundle, ""); +} + +/** + * @tc.name: GetBundleNameByUdKey003 + * @tc.desc: test GetBundleNameByUdKey with incomplete key (missing parts) + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, GetBundleNameByUdKey003, TestSize.Level1) +{ + std::string key = "udmf://share/com.example.app"; + std::string actualBundle = UdmfClient::GetInstance().GetBundleNameByUdKey(key); + EXPECT_EQ(actualBundle, ""); +} + +/** + * @tc.name: GetBundleNameByUdKey004 + * @tc.desc: test GetBundleNameByUdKey with empty key + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, GetBundleNameByUdKey004, TestSize.Level1) +{ + std::string key = ""; + std::string actualBundle = UdmfClient::GetInstance().GetBundleNameByUdKey(key); + EXPECT_EQ(actualBundle, ""); +} + +/** + * @tc.name: GetBundleNameByUdKey005 + * @tc.desc: test GetBundleNameByUdKey with valid UD key + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, GetBundleNameByUdKey005, TestSize.Level1) +{ + std::string key = "udmf://drag/+clone-1+com.example.app/N]2fIEMbrJj@<hH7zpXzzQ>wp:jMuPa7"; + std::string expectedBundle = "+clone-1+com.example.app"; + + std::string actualBundle = UdmfClient::GetInstance().GetBundleNameByUdKey(key); + EXPECT_EQ(actualBundle, expectedBundle); +} + +/** + * @tc.name: GetBundleNameByUdKey006 + * @tc.desc: test GetBundleNameByUdKey with valid UD key + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, GetBundleNameByUdKey006, TestSize.Level1) +{ + std::string key = "udmf://drag/+clone-5+com.example.app/N]2fIEMbrJj@<hH7zpXzzQ>wp:jMuPa7"; + std::string expectedBundle = "+clone-5+com.example.app"; + + std::string actualBundle = UdmfClient::GetInstance().GetBundleNameByUdKey(key); + EXPECT_EQ(actualBundle, expectedBundle); +} + +/** + * @tc.name: ProcessDragIfInApp001 + * @tc.desc: test ProcessDragIfInApp with valid shareOption + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, ProcessDragIfInApp001, TestSize.Level1) +{ + UnifiedData unifiedData; + std::string intentionDrag = "drag"; + std::string key = "test"; + + EXPECT_NO_FATAL_FAILURE(UdmfClient::GetInstance().ProcessDragIfInApp(unifiedData, intentionDrag, key)); +} + +/** + * @tc.name: SetData0024 + * @tc.desc: test SetData with invalid intention + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, SetData0024, TestSize.Level1) +{ + CustomOption option; + UnifiedData unifiedData; + std::string key = "test"; + + auto ret = UdmfClient::GetInstance().SetData(option, unifiedData, key); + EXPECT_EQ(ret, Status::E_INVALID_PARAMETERS); +} + +/** + * @tc.name: IsAppropriateType001 + * @tc.desc: test SetData with invalid intention + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, IsAppropriateType001, TestSize.Level1) +{ + Summary totalSummary; + std::map<std::string, int64_t> specificSummary = { + { "general.png", 10 }, + { "general.jpg", 10 }, + { "general.html", 10 } + }; + std::map<std::string, int64_t> summary = { + { "general.image", 20 }, + { "general.html", 10 } + }; + std::map<std::string, std::vector<int32_t>> summaryFormat = { + { "general.png", { Uds_Type::UDS_FILE_URI } }, + { "general.jpg", { Uds_Type::UDS_FILE_URI } }, + { "general.html", { Uds_Type::UDS_HTML } } + }; + totalSummary.summary = summary; + totalSummary.specificSummary = specificSummary; + totalSummary.summaryFormat = summaryFormat; + totalSummary.version = 1; + totalSummary.totalSize = 30; + + std::vector<std::string> allowTypes = { "general.image" }; + bool isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_TRUE(isAppropriate); + + allowTypes = { "general.hyperlink" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); + + allowTypes = { "general.html" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_TRUE(isAppropriate); +} + +/** + * @tc.name: IsAppropriateType002 + * @tc.desc: test SetData with invalid intention + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, IsAppropriateType002, TestSize.Level1) +{ + Summary totalSummary; + std::map<std::string, int64_t> specificSummary = { + { "general.html", 10 } + }; + std::map<std::string, int64_t> summary = { + { "general.html", 10 } + }; + std::map<std::string, std::vector<int32_t>> summaryFormat = { + { "general.html", { Uds_Type::UDS_FILE_URI } } + }; + totalSummary.summary = summary; + totalSummary.specificSummary = specificSummary; + totalSummary.summaryFormat = summaryFormat; + totalSummary.version = 1; + totalSummary.totalSize = 30; + + std::vector<std::string> allowTypes = { "general.html" }; + bool isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_TRUE(isAppropriate); + + allowTypes = { "general.file" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_TRUE(isAppropriate); + + allowTypes = { "general.file-uri" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_TRUE(isAppropriate); + + allowTypes = { "general.image" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); + + totalSummary.version = 0; + allowTypes = { "general.html" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_TRUE(isAppropriate); + + allowTypes = { "general.file-uri" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); + + allowTypes = { "general.image" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); +} + +/** + * @tc.name: IsAppropriateType002 + * @tc.desc: test SetData with invalid intention + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, IsAppropriateType003, TestSize.Level1) +{ + Summary totalSummary; + std::map<std::string, int64_t> specificSummary = { + { "general.html", 10 } + }; + std::map<std::string, int64_t> summary = { + { "general.html", 10 } + }; + std::map<std::string, std::vector<int32_t>> summaryFormat = { + { "general.html", { Uds_Type::UDS_HTML } } + }; + totalSummary.summary = summary; + totalSummary.specificSummary = specificSummary; + totalSummary.summaryFormat = summaryFormat; + totalSummary.version = 1; + totalSummary.totalSize = 30; + + std::vector<std::string> allowTypes = { "general.html" }; + bool isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_TRUE(isAppropriate); + + allowTypes = { "general.file" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); + + allowTypes = { "general.file-uri" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); + + allowTypes = { "general.image" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); + + totalSummary.version = 0; + allowTypes = { "general.html" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_TRUE(isAppropriate); + + allowTypes = { "general.file-uri" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); + + allowTypes = { "general.image" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); +} + +/** +* @tc.name: GetSummary006 +* @tc.desc: Get summary data for entries +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, GetSummary006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetSummary006 begin."); + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data; + std::string key; + + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + + auto record = std::make_shared<Html>("content1", "content2"); + auto size0 = record->GetSize(); + + auto folder = Folder("uri"); + folder.SetDetails(details); + folder.InitObject(); + record->AddEntry(folder.GetUtdId2(), folder.GetOriginValue()); + + std::shared_ptr<Object> obj = std::make_shared<Object>(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = "http://demo.com"; + obj->value_[FILE_TYPE] = "general.html"; + auto size3 = ObjectUtils::GetValueSize(obj, false); + record->AddEntry("general.file-uri", obj); + + data.AddRecord(record); + + std::shared_ptr<Object> obj1 = std::make_shared<Object>(); + obj1->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj1->value_[FILE_URI_PARAM] = "http://demo.com"; + obj1->value_[FILE_TYPE] = "general.plain-text"; + auto size4 = ObjectUtils::GetValueSize(obj1, false); + auto record1 = std::make_shared<UnifiedRecord>(FILE_URI, obj1); + data.AddRecord(record1); + + std::shared_ptr<Object> obj2 = std::make_shared<Object>(); + obj2->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj2->value_[FILE_URI_PARAM] = "http://demo.com"; + obj2->value_[FILE_TYPE] = "general.png"; + auto size5 = ObjectUtils::GetValueSize(obj2, false); + auto record2 = std::make_shared<UnifiedRecord>(FILE_URI, obj2); + data.AddRecord(record2); + + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + Summary summary; + status = UdmfClient::GetInstance().GetSummary(option2, summary); + + ASSERT_EQ(status, E_OK); + EXPECT_EQ(summary.summary["general.html"], size0); + EXPECT_EQ(summary.summary["general.folder"], 0); + EXPECT_EQ(summary.summary["general.file"], size3 + size4); + EXPECT_EQ(summary.summary["general.image"], size5); + + EXPECT_EQ(summary.specificSummary["general.html"], size0 + size3); + EXPECT_EQ(summary.specificSummary["general.folder"], 0); + EXPECT_EQ(summary.specificSummary["general.plain-text"], size4); + EXPECT_EQ(summary.specificSummary["general.png"], size5); + EXPECT_EQ(summary.totalSize, record->GetSize() + record1->GetSize() + record2->GetSize()); + + EXPECT_EQ(summary.version, 1); + auto htmlFormat = summary.summaryFormat["general.html"]; + EXPECT_TRUE(std::find(htmlFormat.begin(), htmlFormat.end(), Uds_Type::UDS_FILE_URI) != htmlFormat.end()); + EXPECT_TRUE(std::find(htmlFormat.begin(), htmlFormat.end(), Uds_Type::UDS_HTML) != htmlFormat.end()); + + auto textFormat = summary.summaryFormat["general.plain-text"]; + EXPECT_TRUE(std::find(textFormat.begin(), textFormat.end(), Uds_Type::UDS_FILE_URI) != textFormat.end()); + + auto pngFormat = summary.summaryFormat["general.png"]; + EXPECT_TRUE(std::find(pngFormat.begin(), pngFormat.end(), Uds_Type::UDS_FILE_URI) != pngFormat.end()); + LOG_INFO(UDMF_TEST, "GetSummary006 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/udmf_delay_data_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/udmf_delay_data_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..323aec900d686d704e20bc68f49b460d6f0ca4a7 --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/unittest/udmf_delay_data_test.cpp @@ -0,0 +1,717 @@ +/* + * Copyright (c) 2025 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 "UdmfDelayDataTest" +#include <gtest/gtest.h> + +#include "accesstoken_kit.h" +#include "nativetoken_kit.h" +#include "token_setproc.h" +#include "async_task_params.h" +#include "data_params_conversion.h" +#include "logger.h" +#include "plain_text.h" +#include "udmf.h" +#include "udmf_async_client.h" +#include "udmf_client.h" +#include "udmf_executor.h" +#include "udmf_utils.h" + +using namespace testing::ext; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { +static constexpr int USER_ID = 100; +static constexpr int END_INTERVAL = 3; +class UdmfDelayDataTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + static void AllocHapToken1(); + static void AllocHapToken2(); + static void SetHapToken1(); + static void SetHapToken2(); + static void AddPrivilege(QueryOption &option); + static void SetNativeToken(const std::string &processName); + static std::string SetDataInfoTest(const std::string &key); + static void GetDelayDataTest(const std::string &key); + static std::string NdkSetDataInfoTest(); + static void NdkGetDelayDataTest(const std::string &key); +}; + +void UdmfDelayDataTest::SetUpTestCase() +{ + AllocHapToken1(); + AllocHapToken2(); +} + +void UdmfDelayDataTest::TearDownTestCase() +{ + std::this_thread::sleep_for(std::chrono::seconds(END_INTERVAL)); + std::vector<UnifiedData> unifiedDataSet; + QueryOption query; + query.intention = UDMF::UD_INTENTION_DATA_HUB; + auto status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + EXPECT_EQ(E_OK, status); + + auto tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo1", 0); + AccessTokenKit::DeleteToken(tokenId); + auto tokenId2 = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo2", 0); + AccessTokenKit::DeleteToken(tokenId2); +} + +void UdmfDelayDataTest::SetUp() {} + +void UdmfDelayDataTest::TearDown() +{ + std::this_thread::sleep_for(std::chrono::seconds(END_INTERVAL)); +} + +void UdmfDelayDataTest::AllocHapToken1() +{ + HapInfoParams info = { + .userID = USER_ID, + .bundleName = "ohos.test.demo1", + .instIndex = 0, + .appIDDesc = "ohos.test.demo1", + .isSystemApp = false + }; + HapPolicyParams policy = { + .apl = APL_SYSTEM_BASIC, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION", + .bundleName = "ohos.test.demo1", + .grantMode = 1, + .availableLevel = APL_SYSTEM_BASIC, + .label = "label", + .labelId = 1, + .description = "test2", + .descriptionId = 1 + } + }, + .permStateList = { + { + .permissionName = "ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + } + } + }; + auto tokenID = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(tokenID.tokenIDEx); +} + +void UdmfDelayDataTest::AllocHapToken2() +{ + HapInfoParams info = { + .userID = USER_ID, + .bundleName = "ohos.test.demo2", + .instIndex = 0, + .appIDDesc = "ohos.test.demo2", + .isSystemApp = false + }; + + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.test.demo2", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "test2", + .descriptionId = 1 + } + }, + .permStateList = { + { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + } + } + }; + auto tokenID = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(tokenID.tokenIDEx); +} + +void UdmfDelayDataTest::SetHapToken1() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo1", 0); + SetSelfTokenID(tokenId); +} + +void UdmfDelayDataTest::SetHapToken2() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo2", 0); + SetSelfTokenID(tokenId); +} + +void UdmfDelayDataTest::SetNativeToken(const std::string &processName) +{ + auto tokenId = AccessTokenKit::GetNativeTokenId(processName); + SetSelfTokenID(tokenId); +} + +void UdmfDelayDataTest::AddPrivilege(QueryOption &option) +{ + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo2", 0); + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + SetNativeToken("msdp_sa"); + auto status = UdmfClient::GetInstance().AddPrivilege(option, privilege); + ASSERT_EQ(status, E_OK); +} + + +/* * + * @tc.name: UdmfDelayDataTest001 + * @tc.desc: Test get data success. + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, UdmfDelayDataTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest001 begin."); + + DataLoadInfo dataLoadInfo1; + dataLoadInfo1.sequenceKey = UTILS::GenerateId(); + dataLoadInfo1.types = {"general.plain-text", "general.html"}; + dataLoadInfo1.recordCount = 10; + DataLoadInfo dataLoadInfo2; + dataLoadInfo2.types = {"general.plain-text"}; + dataLoadInfo2.recordCount = 100; + + SetHapToken1(); + auto loadHandler = [dataLoadInfo2] (const std::string &udKey, const DataLoadInfo &dataLoadInfo) { + LOG_INFO(UDMF_TEST, "loadHandler begin udKey=%{public}s.", udKey.c_str()); + EXPECT_EQ(dataLoadInfo.recordCount, dataLoadInfo2.recordCount); + EXPECT_EQ(dataLoadInfo.types, dataLoadInfo2.types); + UnifiedData data; + auto obj = std::make_shared<Object>(); + auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); + plainText->SetContent("content1"); + data.AddRecord(plainText); + auto ret = UdmfClient::GetInstance().PushDelayData(udKey, data); + EXPECT_EQ(ret, E_OK); + }; + DataLoadParams dataLoadParams; + dataLoadParams.dataLoadInfo = dataLoadInfo1; + dataLoadParams.loadHandler = loadHandler; + std::string key = ""; + auto status = UdmfClient::GetInstance().SetDelayInfo(dataLoadParams, key); + EXPECT_EQ(status, E_OK); + + QueryOption option; + option.intention = UD_INTENTION_DRAG; + option.key = key; + Summary summary; + status = UdmfClient::GetInstance().GetSummary(option, summary); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(summary.totalSize, dataLoadInfo1.recordCount); + EXPECT_EQ(summary.summary.size(), dataLoadInfo1.types.size()); + for (auto item: summary.summary) { + EXPECT_NE(summary.summary.find(item.first), summary.summary.end()); + EXPECT_EQ(item.second, 0); + } + + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; + AddPrivilege(query); + + SetHapToken2(); + auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { + LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d", + progress.progressStatus, progress.progress); + if (data == nullptr) { + ASSERT_TRUE(progress.progress != 0); + return; + } + ASSERT_EQ(1, data->GetRecords().size()); + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest001 callback end."); + }; + GetDataParams params; + params.query = query; + params.progressIndicator = ProgressIndicator::DEFAULT; + params.progressListener = callback; + params.acceptableInfo = dataLoadInfo2; + status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); + EXPECT_EQ(status, E_OK); + + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest001 end."); +} + +/* * + * @tc.name: UdmfDelayDataTest002 + * @tc.desc: Test after waiting for 500ms, get data success. + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, UdmfDelayDataTest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest002 begin."); + + DataLoadInfo dataLoadInfo1; + dataLoadInfo1.recordCount = 10; + dataLoadInfo1.types = {"general.plain-text", "general.html"}; + dataLoadInfo1.sequenceKey = UTILS::GenerateId(); + DataLoadInfo dataLoadInfo2; + dataLoadInfo2.recordCount = 100; + dataLoadInfo2.types = {"general.plain-text"}; + + SetHapToken1(); + auto loadHandler = [dataLoadInfo2] (const std::string &udKey, const DataLoadInfo &dataLoadInfo) { + LOG_INFO(UDMF_TEST, "loadHandler begin udKey=%{public}s.", udKey.c_str()); + EXPECT_EQ(dataLoadInfo.recordCount, dataLoadInfo2.recordCount); + EXPECT_EQ(dataLoadInfo.types, dataLoadInfo2.types); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + UnifiedData data; + auto obj = std::make_shared<Object>(); + auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); + plainText->SetContent("content1"); + data.AddRecord(plainText); + auto ret = UdmfClient::GetInstance().PushDelayData(udKey, data); + EXPECT_EQ(ret, E_OK); + }; + DataLoadParams dataLoadParams; + dataLoadParams.dataLoadInfo = dataLoadInfo1; + dataLoadParams.loadHandler = loadHandler; + std::string key = ""; + auto status = UdmfClient::GetInstance().SetDelayInfo(dataLoadParams, key); + EXPECT_EQ(status, E_OK); + + QueryOption option; + option.intention = UD_INTENTION_DRAG; + option.key = key; + Summary summary; + status = UdmfClient::GetInstance().GetSummary(option, summary); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(summary.totalSize, dataLoadInfo1.recordCount); + EXPECT_EQ(summary.summary.size(), dataLoadInfo1.types.size()); + for (auto item: summary.summary) { + EXPECT_NE(summary.summary.find(item.first), summary.summary.end()); + EXPECT_EQ(item.second, 0); + } + + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; + AddPrivilege(query); + + SetHapToken2(); + auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { + LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d", + progress.progressStatus, progress.progress); + if (data == nullptr) { + ASSERT_TRUE(progress.progress != 0); + return; + } + ASSERT_EQ(1, data->GetRecords().size()); + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest002 callback end."); + }; + GetDataParams params; + params.query = query; + params.progressIndicator = ProgressIndicator::DEFAULT; + params.progressListener = callback; + params.acceptableInfo = dataLoadInfo2; + status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); + EXPECT_EQ(status, E_OK); + + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest002 end."); +} + +/* * + * @tc.name: UdmfDelayDataTest003 + * @tc.desc: Test invalid parameters + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, UdmfDelayDataTest003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest003 begin."); + + DataLoadInfo dataLoadInfo1; + dataLoadInfo1.recordCount = 10; + dataLoadInfo1.types = {"general.plain-text", "general.html"}; + + SetHapToken1(); + auto loadHandler = [] (const std::string &udKey, const DataLoadInfo &dataLoadInfo) { + LOG_INFO(UDMF_TEST, "loadHandler begin udKey=%{public}s.", udKey.c_str()); + }; + DataLoadParams dataLoadParams; + dataLoadParams.dataLoadInfo = dataLoadInfo1; + dataLoadParams.loadHandler = loadHandler; + std::string key = ""; + auto status = UdmfClient::GetInstance().SetDelayInfo(dataLoadParams, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest003 end."); +} + +/* * + * @tc.name: UdmfDelayDataTest004 + * @tc.desc: Test invalid parameters + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, UdmfDelayDataTest004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest004 begin."); + SetHapToken1(); + UnifiedData data; + auto obj = std::make_shared<Object>(); + auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string udKey = ""; + auto ret = UdmfClient::GetInstance().PushDelayData(udKey, data); + EXPECT_EQ(ret, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest004 end."); +} + +std::string UdmfDelayDataTest::SetDataInfoTest(const std::string &key) +{ + DataLoadInfo dataLoadInfo1; + dataLoadInfo1.recordCount = 10; + dataLoadInfo1.types = {"general.plain-text", "general.html"}; + dataLoadInfo1.sequenceKey = key; + DataLoadInfo dataLoadInfo2; + dataLoadInfo2.recordCount = 100; + dataLoadInfo2.types = {"general.plain-text"}; + auto loadHandler = [dataLoadInfo2] (const std::string &udKey, const DataLoadInfo &dataLoadInfo) { + LOG_INFO(UDMF_TEST, "loadHandler begin udKey=%{public}s.", udKey.c_str()); + EXPECT_EQ(dataLoadInfo.recordCount, dataLoadInfo2.recordCount); + EXPECT_EQ(dataLoadInfo.types, dataLoadInfo2.types); + UnifiedData data; + auto obj = std::make_shared<Object>(); + auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); + plainText->SetContent("content1"); + data.AddRecord(plainText); + auto ret = UdmfClient::GetInstance().PushDelayData(udKey, data); + EXPECT_EQ(ret, E_OK); + }; + DataLoadParams dataLoadParams; + dataLoadParams.dataLoadInfo = dataLoadInfo1; + dataLoadParams.loadHandler = loadHandler; + std::string udkey = ""; + auto status = UdmfClient::GetInstance().SetDelayInfo(dataLoadParams, udkey); + EXPECT_EQ(status, E_OK); + return udkey; +} + +void UdmfDelayDataTest::GetDelayDataTest(const std::string &key) +{ + DataLoadInfo dataLoadInfo2; + dataLoadInfo2.recordCount = 100; + dataLoadInfo2.types = {"general.plain-text"}; + auto callback = [](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { + LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d", + progress.progressStatus, progress.progress); + if (data == nullptr) { + ASSERT_TRUE(progress.progress != 0); + return; + } + ASSERT_EQ(1, data->GetRecords().size()); + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest002 callback end."); + }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; + GetDataParams params; + params.query = query; + params.progressIndicator = ProgressIndicator::NONE; + params.progressListener = callback; + params.acceptableInfo = dataLoadInfo2; + auto status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); + EXPECT_EQ(status, E_OK); +} + +/* * + * @tc.name: UdmfDelayDataTest005 + * @tc.desc: Test multi thread delay data + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, UdmfDelayDataTest005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest005 begin."); + SetHapToken1(); + std::string key1 = UTILS::GenerateId(); + std::string key2 = UTILS::GenerateId(); + std::string key3 = UTILS::GenerateId(); + + std::thread t1([&]() { + key1 = SetDataInfoTest(key1); + GetDelayDataTest(key1); + }); + std::thread t2([&]() { + key2 = SetDataInfoTest(key2); + GetDelayDataTest(key2); + }); + std::thread t3([&]() { + key3 = SetDataInfoTest(key3); + GetDelayDataTest(key3); + }); + EXPECT_NO_FATAL_FAILURE(t1.join()); + EXPECT_NO_FATAL_FAILURE(t2.join()); + EXPECT_NO_FATAL_FAILURE(t3.join()); + + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest005 end."); +} + +/* * + * @tc.name: GetSequenceKey001 + * @tc.desc: Test normal GetSequenceKey + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, GetSequenceKey001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest005 begin."); + EXPECT_EQ(UTILS::GetSequenceKey("abc/def"), "def"); + EXPECT_EQ(UTILS::GetSequenceKey("one/two/three"), "three"); + EXPECT_EQ(UTILS::GetSequenceKey("/abc/def/ghi"), "ghi"); + LOG_INFO(UDMF_TEST, "GetSequenceKey001 end."); +} + +/* * + * @tc.name: GetSequenceKey002 + * @tc.desc: Test abnormal GetSequenceKey + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, GetSequenceKey002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetSequenceKey002 begin."); + EXPECT_EQ(UTILS::GetSequenceKey("abc/"), ""); + EXPECT_EQ(UTILS::GetSequenceKey("abcdef"), ""); + EXPECT_EQ(UTILS::GetSequenceKey(""), ""); + EXPECT_EQ(UTILS::GetSequenceKey("/"), ""); + EXPECT_EQ(UTILS::GetSequenceKey("/abc/def/"), ""); + LOG_INFO(UDMF_TEST, "GetSequenceKey002 end."); +} + +std::string UdmfDelayDataTest::NdkSetDataInfoTest() +{ + DataLoadInfo dataLoadInfo1; + dataLoadInfo1.recordCount = 10; + dataLoadInfo1.types = {"general.plain-text", "general.html"}; + OH_UdmfDataLoadInfo *info1 = OH_UdmfDataLoadInfo_Create(); + OH_UdmfDataLoadInfo_SetType(info1, "general.plain-text"); + OH_UdmfDataLoadInfo_SetType(info1, "general.html"); + OH_UdmfDataLoadInfo_SetRecordCount(info1, dataLoadInfo1.recordCount); + + OH_Udmf_DataLoadHandler loadHandler = [] (OH_UdmfDataLoadInfo* acceptableInfo) { + LOG_INFO(UDMF_TEST, "loadHandler begin."); + auto recordCount = OH_UdmfDataLoadInfo_GetRecordCount(acceptableInfo); + EXPECT_EQ(recordCount, 100); + unsigned int typeCount = 0; + auto types = OH_UdmfDataLoadInfo_GetTypes(acceptableInfo, &typeCount); + EXPECT_EQ(typeCount, 1); + EXPECT_STREQ(types[0], "general.plain-text"); + + OH_UdmfData *unifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsPlainText *plainText = OH_UdsPlainText_Create(); + auto status = OH_UdsPlainText_SetContent(plainText, "content1"); + EXPECT_EQ(status, E_OK); + status = OH_UdmfRecord_AddPlainText(record, plainText); + EXPECT_EQ(status, E_OK); + status = OH_UdmfData_AddRecord(unifiedData, record); + EXPECT_EQ(status, E_OK); + return unifiedData; + }; + + OH_UdmfDataLoadParams *ndkParams = OH_UdmfDataLoadParams_Create(); + OH_UdmfDataLoadParams_SetDataLoadInfo(ndkParams, info1); + OH_UdmfDataLoadParams_SetLoadHandler(ndkParams, loadHandler); + DataLoadParams dataLoadParams; + auto status = DataParamsConversion::GetDataLoaderParams(*ndkParams, dataLoadParams); + EXPECT_EQ(status, E_OK); + + SetHapToken1(); + std::string udkey = ""; + status = UdmfClient::GetInstance().SetDelayInfo(dataLoadParams, udkey); + EXPECT_EQ(status, E_OK); + return udkey; +} + +void UdmfDelayDataTest::NdkGetDelayDataTest(const std::string &key) +{ + DataLoadInfo dataLoadInfo2; + dataLoadInfo2.recordCount = 100; + dataLoadInfo2.types = {"general.plain-text"}; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; + AddPrivilege(query); + + SetHapToken2(); + OH_UdmfDataLoadInfo *info2 = OH_UdmfDataLoadInfo_Create(); + OH_UdmfDataLoadInfo_SetType(info2, "general.plain-text"); + OH_UdmfDataLoadInfo_SetRecordCount(info2, dataLoadInfo2.recordCount); + + OH_UdmfGetDataParams *param = OH_UdmfGetDataParams_Create(); + OH_UdmfGetDataParams_SetProgressIndicator(param, Udmf_ProgressIndicator::UDMF_DEFAULT); + OH_UdmfGetDataParams_SetAcceptableInfo(param, info2); + OH_Udmf_DataProgressListener dataProgressListener = [](OH_Udmf_ProgressInfo *progressInfo, OH_UdmfData *data) { + auto progress = OH_UdmfProgressInfo_GetProgress(progressInfo); + auto status = OH_UdmfProgressInfo_GetStatus(progressInfo); + LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d.", status, progress); + if (data == nullptr) { + ASSERT_TRUE(progress != 0); + return; + } + unsigned int count = 0; + OH_UdmfData_GetRecords(data, &count); + ASSERT_EQ(1, count); + LOG_INFO(UDMF_TEST, "UdmfDelayDataNDKTest001 callback end."); + }; + OH_UdmfGetDataParams_SetDataProgressListener(param, dataProgressListener); + GetDataParams dataParams; + auto status = DataParamsConversion::GetInnerDataParams(*param, query, dataParams); + EXPECT_EQ(status, E_OK); + status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(dataParams); + EXPECT_EQ(status, E_OK); +} + +/* * + * @tc.name: UdmfDelayDataNDKTest001 + * @tc.desc: Test CAPI delay data + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, UdmfDelayDataNDKTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UdmfDelayDataNDKTest001 begin."); + DataLoadInfo dataLoadInfo1; + dataLoadInfo1.recordCount = 10; + dataLoadInfo1.types = {"general.plain-text", "general.html"}; + DataLoadInfo dataLoadInfo2; + dataLoadInfo2.recordCount = 100; + dataLoadInfo2.types = {"general.plain-text"}; + auto key = NdkSetDataInfoTest(); + + QueryOption option; + option.intention = UD_INTENTION_DRAG; + option.key = key; + Summary summary; + auto status = UdmfClient::GetInstance().GetSummary(option, summary); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(summary.totalSize, dataLoadInfo1.recordCount); + EXPECT_EQ(summary.summary.size(), dataLoadInfo1.types.size()); + for (auto &item: summary.summary) { + EXPECT_NE(summary.summary.find(item.first), summary.summary.end()); + EXPECT_EQ(item.second, 0); + } + NdkGetDelayDataTest(key); + + LOG_INFO(UDMF_TEST, "UdmfDelayDataNDKTest001 end."); +} + +/** + * @tc.name: OH_UdmfDataLoadParams_Create_Destroy_001 + * @tc.desc: Test create and destroy of OH_UdmfDataLoadParams + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, OH_UdmfDataLoadParams_Create_Destroy_001, TestSize.Level0) +{ + OH_UdmfDataLoadParams* params = OH_UdmfDataLoadParams_Create(); + EXPECT_NE(params, nullptr); + OH_UdmfDataLoadParams_Destroy(params); +} + +/** + * @tc.name: OH_UdmfDataLoadParams_Destroy_Null_001 + * @tc.desc: Test destroy OH_UdmfDataLoadParams with null pointer + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, OH_UdmfDataLoadParams_Destroy_Null_001, TestSize.Level0) +{ + OH_UdmfDataLoadParams_Destroy(nullptr); +} + +/** + * @tc.name: OH_UdmfDataLoadInfo_Create_Destroy_001 + * @tc.desc: Test create and destroy of OH_UdmfDataLoadInfo + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, OH_UdmfDataLoadInfo_Create_Destroy_001, TestSize.Level0) +{ + OH_UdmfDataLoadInfo* info = OH_UdmfDataLoadInfo_Create(); + EXPECT_NE(info, nullptr); + OH_UdmfDataLoadInfo_Destroy(info); +} + +/** + * @tc.name: OH_UdmfDataLoadInfo_GetTypes_Invalid_001 + * @tc.desc: GetTypes with null dataLoadInfo or count + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, OH_UdmfDataLoadInfo_GetTypes_Invalid_001, TestSize.Level0) +{ + unsigned int count = 0; + char** result1 = OH_UdmfDataLoadInfo_GetTypes(nullptr, &count); + EXPECT_EQ(result1, nullptr); + + OH_UdmfDataLoadInfo* info = OH_UdmfDataLoadInfo_Create(); + char** result2 = OH_UdmfDataLoadInfo_GetTypes(info, nullptr); + EXPECT_EQ(result2, nullptr); + OH_UdmfDataLoadInfo_Destroy(info); +} + +/** + * @tc.name: OH_UdmfDataLoadInfo_SetType_And_GetTypes_001 + * @tc.desc: Test SetType and GetTypes logic + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, OH_UdmfDataLoadInfo_SetType_And_GetTypes_001, TestSize.Level0) +{ + OH_UdmfDataLoadInfo* info = OH_UdmfDataLoadInfo_Create(); + EXPECT_NE(info, nullptr); + + OH_UdmfDataLoadInfo_SetType(info, "image"); + OH_UdmfDataLoadInfo_SetType(info, "text"); + OH_UdmfDataLoadInfo_SetType(info, "text"); // duplicate + + unsigned int count = 0; + OH_UdmfDataLoadInfo_GetTypes(info, &count); + EXPECT_EQ(count, 2); + + OH_UdmfDataLoadInfo_Destroy(info); +} + +/** + * @tc.name: OH_UdmfDataLoadInfo_SetRecordCount_GetRecordCount_001 + * @tc.desc: Test setting and getting record count + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, OH_UdmfDataLoadInfo_SetRecordCount_GetRecordCount_001, TestSize.Level0) +{ + OH_UdmfDataLoadInfo* info = OH_UdmfDataLoadInfo_Create(); + EXPECT_NE(info, nullptr); + + OH_UdmfDataLoadInfo_SetRecordCount(info, 10); + int count = OH_UdmfDataLoadInfo_GetRecordCount(info); + EXPECT_EQ(count, 10); + + OH_UdmfDataLoadInfo_Destroy(info); +} +} // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/unified_data_helper_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/unified_data_helper_test.cpp index 018e1b4fab1f3ac95cefc709c3f1615e892a12a4..5e569c92421f8afc954fdea1c587148b9281f5d5 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/unified_data_helper_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/unified_data_helper_test.cpp @@ -21,6 +21,7 @@ #include "logger.h" #include "udmf_capi_common.h" #include "unified_data_helper.h" +#include "file_uri.h" using namespace testing::ext; using namespace OHOS::UDMF; @@ -134,6 +135,22 @@ HWTEST_F(UnifiedDataHelperTest, SaveUDataToFile001, TestSize.Level1) LOG_INFO(UDMF_TEST, "SaveUDataToFile001 end."); } +/** +* @tc.name: SaveUDataToFile002 +* @tc.desc: Normal testcase of SaveUDataToFile +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedDataHelperTest, SaveUDataToFile002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SaveUDataToFile002 begin."); + const std::string dataFile = "data/test"; + UnifiedData data; + UnifiedDataHelper unifiedDataHelper; + bool ret = unifiedDataHelper.SaveUDataToFile(dataFile, data); + EXPECT_TRUE(ret); + LOG_INFO(UDMF_TEST, "SaveUDataToFile002 end."); +} + /** * @tc.name: LoadUDataFromFile001 * @tc.desc: Abnormal testcase of LoadUDataFromFile, the data is nullptr @@ -150,6 +167,22 @@ HWTEST_F(UnifiedDataHelperTest, LoadUDataFromFile001, TestSize.Level1) LOG_INFO(UDMF_TEST, "LoadUDataFromFile001 end."); } +/** +* @tc.name: LoadUDataFromFile002 +* @tc.desc: Abnormal testcase of LoadUDataFromFile, the data is nullptr +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedDataHelperTest, LoadUDataFromFile002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "LoadUDataFromFile002 begin."); + const std::string dataFile = "data/test"; + UnifiedData data; + UnifiedDataHelper unifiedDataHelper; + bool ret = unifiedDataHelper.LoadUDataFromFile(dataFile, data); + EXPECT_FALSE(ret); + LOG_INFO(UDMF_TEST, "LoadUDataFromFile002 end."); +} + /** * @tc.name: GetRootPath001 * @tc.desc: Abnormal testcase of GetRootPath, the rootPath_ is nullptr @@ -164,4 +197,37 @@ HWTEST_F(UnifiedDataHelperTest, GetRootPath001, TestSize.Level1) EXPECT_EQ(ret, TEMP_UNIFIED_DATA_ROOT_PATH); LOG_INFO(UDMF_TEST, "GetRootPath001 end."); } + +/** +* @tc.name: FileClose001 +* @tc.desc: Abnormal testcase of FileClose, the file is null +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedDataHelperTest, FileClose001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "FileClose001 begin."); + UnifiedDataHelper unifiedDataHelper; + const std::string dataFile = "data/test"; + AppFileService::ModuleFileUri::FileUri fileUri(dataFile); + std::string path = fileUri.GetRealPath(); + std::FILE *file = fopen(path.c_str(), "r"); + bool status = unifiedDataHelper.FileClose(file, true); + EXPECT_TRUE(status); + LOG_INFO(UDMF_TEST, "FileClose001 end."); +} + +/** +* @tc.name: FileClose002 +* @tc.desc: Abnormal testcase of FileClose, file is nullptr +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedDataHelperTest, FileClose002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "FileClose002 begin."); + UnifiedDataHelper unifiedDataHelper; + std::FILE *file = nullptr; + bool status = unifiedDataHelper.FileClose(file, true); + EXPECT_FALSE(status); + LOG_INFO(UDMF_TEST, "FileClose002 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/unified_data_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/unified_data_test.cpp index 89f6a988b5a41661ef1679a0b887da9130647368..a5d1e51ba7d73129d5bebbc7609ee1f4097fa1fc 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/unified_data_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/unified_data_test.cpp @@ -19,6 +19,7 @@ #include <string> #include "file.h" +#include "image.h" #include "logger.h" #include "plain_text.h" #include "udmf_capi_common.h" @@ -61,33 +62,26 @@ void UnifiedDataTest::TransferToEntriesCompareEntries(UnifiedRecord* recordFirst auto plainTextFirst = static_cast<PlainText*>(recordFirst); EXPECT_EQ(plainTextFirst->GetAbstract(), "abstract"); EXPECT_EQ(plainTextFirst->GetContent(), "http://1111/a.img"); - std::set<std::string> utdIds = recordFirst->GetUtdIds(); EXPECT_TRUE(utdIds.find("general.plain-text") != utdIds.end()); - EXPECT_TRUE(utdIds.find("general.file") != utdIds.end()); EXPECT_TRUE(utdIds.find("general.file-uri") != utdIds.end()); - EXPECT_TRUE(utdIds.find("general.img") == utdIds.end()); - EXPECT_TRUE(utdIds.find("general.media") != utdIds.end()); - - auto fileEntry = recordFirst->GetEntry("general.file"); + auto fileEntry = recordFirst->GetEntry("general.file-uri"); std::shared_ptr<Object> fileEntryObj = std::get<std::shared_ptr<Object>>(fileEntry); std::string getUri; fileEntryObj->GetValue(ORI_URI, getUri); - EXPECT_EQ(getUri, "http://1111/a.img"); - + EXPECT_EQ(getUri, "http://1111/a.mp4"); auto plainTextEntry = recordFirst->GetEntry("general.plain-text"); - EXPECT_TRUE(std::holds_alternative<std::monostate>(plainTextEntry)); - + std::shared_ptr<Object> plainTextEntryObj = std::get<std::shared_ptr<Object>>(plainTextEntry); + std::string getContent; + plainTextEntryObj->GetValue(CONTENT, getContent); + EXPECT_EQ(getContent, "http://1111/a.img"); + std::string getAbstract; + plainTextEntryObj->GetValue(ABSTRACT, getAbstract); + EXPECT_EQ(getAbstract, "abstract"); auto entries = recordFirst->GetEntries(); EXPECT_NE(entries, nullptr); - int entrySize = 3; + int entrySize = 2; EXPECT_EQ(entries->size(), entrySize); - auto fileEntry1 = (*entries)["general.file"]; - std::shared_ptr<Object> fileEntryObj1 = std::get<std::shared_ptr<Object>>(fileEntry1); - std::string getUri1; - fileEntryObj1->GetValue(ORI_URI, getUri1); - EXPECT_EQ(getUri1, "http://1111/a.img"); - auto plainTextEntry1 = (*entries)["general.plain-text"]; std::shared_ptr<Object> plainTextEntryObj1 = std::get<std::shared_ptr<Object>>(plainTextEntry1); std::string content; @@ -96,12 +90,11 @@ void UnifiedDataTest::TransferToEntriesCompareEntries(UnifiedRecord* recordFirst std::string abstract; plainTextEntryObj1->GetValue(ABSTRACT, abstract); EXPECT_EQ(abstract, "abstract"); - auto fileUriEntry1 = (*entries)["general.file-uri"]; std::shared_ptr<Object> fileUriEntryObj1 = std::get<std::shared_ptr<Object>>(fileUriEntry1); std::string oriUri; fileUriEntryObj1->GetValue(FILE_URI_PARAM, oriUri); - EXPECT_EQ(oriUri, "http://1111/a.img"); + EXPECT_EQ(oriUri, "http://1111/a.mp4"); std::string fileType; fileUriEntryObj1->GetValue(FILE_TYPE, fileType); EXPECT_EQ(fileType, "general.media"); @@ -219,8 +212,10 @@ HWTEST_F(UnifiedDataTest, GetRecordAt001, TestSize.Level1) */ HWTEST_F(UnifiedDataTest, TransferToEntries001, TestSize.Level1) { - LOG_INFO(UDMF_TEST, "TransferToEntries001 begin."); UnifiedData unifiedData; + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + properties->tag = "records_to_entries_data_format"; + unifiedData.SetProperties(properties); std::shared_ptr<PlainText> plainText = std::make_shared<PlainText>(); plainText->SetContent("http://1111/a.img"); plainText->SetAbstract("abstract"); @@ -228,7 +223,7 @@ HWTEST_F(UnifiedDataTest, TransferToEntries001, TestSize.Level1) file->SetUri("http://1111/a.img"); unifiedData.AddRecord(plainText); unifiedData.AddRecord(file); - unifiedData.TransferToEntries(unifiedData); + unifiedData.ConvertRecordsToEntries(); auto records = unifiedData.GetRecords(); int recordSize = 1; EXPECT_EQ(records.size(), recordSize); @@ -238,19 +233,23 @@ HWTEST_F(UnifiedDataTest, TransferToEntries001, TestSize.Level1) EXPECT_EQ(plainTextFirst->GetContent(), "http://1111/a.img"); std::set<std::string> utdIds = recordFirst->GetUtdIds(); EXPECT_TRUE(utdIds.find("general.plain-text") != utdIds.end()); - EXPECT_TRUE(utdIds.find("general.file") != utdIds.end()); - auto fileEntry = recordFirst->GetEntry("general.file"); + EXPECT_TRUE(utdIds.find("general.file-uri") != utdIds.end()); + auto fileEntry = recordFirst->GetEntry("general.file-uri"); std::shared_ptr<Object> fileEntryObj = std::get<std::shared_ptr<Object>>(fileEntry); std::string getUri; fileEntryObj->GetValue(ORI_URI, getUri); EXPECT_EQ(getUri, "http://1111/a.img"); auto plainTextEntry = recordFirst->GetEntry("general.plain-text"); - EXPECT_TRUE(std::holds_alternative<std::monostate>(plainTextEntry)); + EXPECT_FALSE(std::holds_alternative<std::monostate>(plainTextEntry)); + std::shared_ptr<Object> plainTextEntryObj = std::get<std::shared_ptr<Object>>(plainTextEntry); + std::string getContent; + plainTextEntryObj->GetValue(CONTENT, getContent); + EXPECT_EQ(getContent, "http://1111/a.img"); auto entries = recordFirst->GetEntries(); EXPECT_NE(entries, nullptr); int entrySize = 2; EXPECT_EQ(entries->size(), entrySize); - auto fileEntry1 = (*entries)["general.file"]; + auto fileEntry1 = (*entries)["general.file-uri"]; std::shared_ptr<Object> fileEntryObj1 = std::get<std::shared_ptr<Object>>(fileEntry1); std::string getUri1; fileEntryObj1->GetValue(ORI_URI, getUri1); @@ -263,7 +262,6 @@ HWTEST_F(UnifiedDataTest, TransferToEntries001, TestSize.Level1) std::string abstract; plainTextEntryObj1->GetValue(ABSTRACT, abstract); EXPECT_EQ(abstract, "abstract"); - LOG_INFO(UDMF_TEST, "TransferToEntries001 end."); } /** @@ -278,22 +276,18 @@ HWTEST_F(UnifiedDataTest, TransferToEntries002, TestSize.Level1) std::shared_ptr<PlainText> plainText = std::make_shared<PlainText>(); plainText->SetContent("http://1111/a.img"); plainText->SetAbstract("abstract"); - std::shared_ptr<File> file = std::make_shared<File>(); - file->SetUri("http://1111/a.img"); - + file->SetUri("http://1111/a.txt"); std::shared_ptr<Object> fileUriObj = std::make_shared<Object>(); fileUriObj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; fileUriObj->value_[FILE_URI_PARAM] = "http://1111/a.img"; fileUriObj->value_[FILE_TYPE] = "general.img"; std::shared_ptr<UnifiedRecord> fileUri = std::make_shared<UnifiedRecord>(FILE_URI, fileUriObj); - std::shared_ptr<Object> fileUriObj1 = std::make_shared<Object>(); fileUriObj1->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; - fileUriObj1->value_[FILE_URI_PARAM] = "http://1111/a.img"; + fileUriObj1->value_[FILE_URI_PARAM] = "http://1111/a.mp4"; fileUriObj1->value_[FILE_TYPE] = "general.media"; std::shared_ptr<UnifiedRecord> fileUri1 = std::make_shared<UnifiedRecord>(FILE_URI, fileUriObj1); - bool isNeed = unifiedData.IsNeedTransferToEntries(); EXPECT_FALSE(isNeed); unifiedData.AddRecord(plainText); @@ -309,14 +303,147 @@ HWTEST_F(UnifiedDataTest, TransferToEntries002, TestSize.Level1) unifiedData.SetProperties(properties); isNeed = unifiedData.IsNeedTransferToEntries(); EXPECT_TRUE(isNeed); - - unifiedData.TransferToEntries(unifiedData); + unifiedData.ConvertRecordsToEntries(); auto records = unifiedData.GetRecords(); int recordSize = 1; EXPECT_EQ(records.size(), recordSize); - auto recordFirst = records[0].get(); TransferToEntriesCompareEntries(recordFirst); LOG_INFO(UDMF_TEST, "TransferToEntries001 end."); } + +/** +* @tc.name: HasHigherFileTypeTest001 +* @tc.desc: Normal test of HasHigherFileType return true. +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedDataTest, HasHigherFileTypeTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "HasHigherFileTypeTest001 begin."); + std::shared_ptr<Object> fileObj = std::make_shared<Object>(); + fileObj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + fileObj->value_[FILE_URI_PARAM] = "file://1111/a.jpeg"; + fileObj->value_[FILE_TYPE] = "general.jpeg"; + std::shared_ptr<UnifiedRecord> file = std::make_shared<UnifiedRecord>(FILE_URI, fileObj); + + std::shared_ptr<Object> fileObj1 = std::make_shared<Object>(); + fileObj1->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + fileObj1->value_[FILE_URI_PARAM] = "file://1111/a.mp4"; + fileObj1->value_[FILE_TYPE] = "general.mpeg-4"; + std::shared_ptr<UnifiedRecord> file1 = std::make_shared<UnifiedRecord>(FILE_URI, fileObj1); + + std::shared_ptr<Object> fileObj2 = std::make_shared<Object>(); + fileObj2->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + fileObj2->value_[FILE_URI_PARAM] = "file://1111/a.txt"; + fileObj2->value_[FILE_TYPE] = "general.file"; + std::shared_ptr<UnifiedRecord> file2 = std::make_shared<UnifiedRecord>(FILE_URI, fileObj2); + UnifiedData unifiedData; + unifiedData.AddRecord(file); + unifiedData.AddRecord(file1); + unifiedData.AddRecord(file2); + EXPECT_TRUE(unifiedData.HasHigherFileType("general.file-uri")); + EXPECT_TRUE(unifiedData.HasHigherFileType("general.image")); + EXPECT_TRUE(unifiedData.HasHigherFileType("general.file")); + EXPECT_TRUE(unifiedData.HasHigherFileType("general.video")); + EXPECT_TRUE(unifiedData.HasHigherFileType("general.jpeg")); + EXPECT_TRUE(unifiedData.HasHigherFileType("general.mpeg-4")); + EXPECT_FALSE(unifiedData.HasHigherFileType("general.folder")); + EXPECT_FALSE(unifiedData.HasHigherFileType("general.audio")); + LOG_INFO(UDMF_TEST, "HasHigherFileTypeTest001 end."); +} + +/** +* @tc.name: IsCompleteTest001 +* @tc.desc: Normal test of HasHigherFileType return true. +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedDataTest, IsCompleteTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "IsCompleteTest001 begin."); + UnifiedData unifiedData; + EXPECT_FALSE(unifiedData.IsComplete()); + + Runtime runtime; + runtime.recordTotalNum = 1; + unifiedData.SetRuntime(runtime); + EXPECT_FALSE(unifiedData.IsComplete()); + + std::shared_ptr<Object> fileObj = std::make_shared<Object>(); + fileObj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + fileObj->value_[FILE_URI_PARAM] = "file://1111/a.jpeg"; + fileObj->value_[FILE_TYPE] = "general.jpeg"; + std::shared_ptr<UnifiedRecord> fileRecord = std::make_shared<UnifiedRecord>(FILE_URI, fileObj); + unifiedData.AddRecord(fileRecord); + EXPECT_TRUE(unifiedData.IsComplete()); + + std::shared_ptr<Object> plainTextObj = std::make_shared<Object>(); + plainTextObj->value_[UNIFORM_DATA_TYPE] = "general.plain-text"; + plainTextObj->value_[CONTENT] = "Hello, World!"; + plainTextObj->value_[ABSTRACT] = "This is a test."; + std::shared_ptr<UnifiedRecord> plainTextRecord = std::make_shared<UnifiedRecord>(PLAIN_TEXT, plainTextObj); + unifiedData.AddRecord(plainTextRecord); + EXPECT_FALSE(unifiedData.IsComplete()); + LOG_INFO(UDMF_TEST, "IsCompleteTest001 end."); +} + +/** +* @tc.name: GetFileUrisTest001 +* @tc.desc: Normal test of HasHigherFileType return true. +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedDataTest, GetFileUrisTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetFileUrisTest001 begin."); + UnifiedData unifiedData; + std::shared_ptr<Object> fileObj = std::make_shared<Object>(); + fileObj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + fileObj->value_[FILE_URI_PARAM] = "file://1111/a.jpeg"; + fileObj->value_[FILE_TYPE] = "general.jpeg"; + std::shared_ptr<UnifiedRecord> fileRecord = std::make_shared<UnifiedRecord>(FILE_URI, fileObj); + unifiedData.AddRecord(fileRecord); + + std::shared_ptr<Object> plainTextObj = std::make_shared<Object>(); + plainTextObj->value_[UNIFORM_DATA_TYPE] = "general.plain-text"; + plainTextObj->value_[CONTENT] = "Hello, World!"; + plainTextObj->value_[ABSTRACT] = "This is a test."; + std::shared_ptr<UnifiedRecord> plainTextRecord = std::make_shared<UnifiedRecord>(PLAIN_TEXT, plainTextObj); + unifiedData.AddRecord(plainTextRecord); + + std::shared_ptr<Image> image = std::make_shared<Image>(); + image->SetUri("file://1111/a.png"); + unifiedData.AddRecord(image); + + unifiedData.AddRecord(nullptr); + std::vector<std::string> fileUris = unifiedData.GetFileUris(); + EXPECT_EQ(fileUris.size(), 2); + EXPECT_TRUE(std::find(fileUris.begin(), fileUris.end(), "file://1111/a.jpeg") != fileUris.end()); + EXPECT_TRUE(std::find(fileUris.begin(), fileUris.end(), "file://1111/a.png") != fileUris.end()); + LOG_INFO(UDMF_TEST, "GetFileUrisTest001 end."); +} + +/** + * @tc.name: GetDataId_001 + * @tc.desc: Get dataId. + * @tc.type: FUNC + */ +HWTEST_F(UnifiedDataTest, GetDataId_001, TestSize.Level0) +{ + uint32_t dataId = 2; + UnifiedData unifiedData; + unifiedData.SetDataId(dataId); + auto getDataId = unifiedData.GetDataId(); + EXPECT_EQ(getDataId, dataId); +} + +/** + * @tc.name: SetChannelName_001 + * @tc.desc: Set channelName. + * @tc.type: FUNC + */ +HWTEST_F(UnifiedDataTest, SetChannelName_001, TestSize.Level0) +{ + const std::string name = "channelName"; + UnifiedData unifiedData; + EXPECT_NO_FATAL_FAILURE(unifiedData.SetChannelName(name)); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/unified_key_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/unified_key_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9abd6e0b9dc30bddb5670441f3d317d7d88a49e8 --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/unittest/unified_key_test.cpp @@ -0,0 +1,339 @@ +/* + * 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 "unifiedKeyTest" + +#include <unistd.h> +#include <gtest/gtest.h> +#include <string> +#include "unified_key.h" + +using namespace testing::ext; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { +using namespace std; + +class UnifiedKeyTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void UnifiedKeyTest::SetUpTestCase() +{ +} + +void UnifiedKeyTest::TearDownTestCase() +{ +} + +void UnifiedKeyTest::SetUp() +{ +} + +void UnifiedKeyTest::TearDown() +{ +} + +/** +* @tc.name: UnifiedKey001 +* @tc.desc: Normal testcase of UnifiedKey +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, UnifiedKey001, TestSize.Level1) +{ + std::string key = "general.text"; + UnifiedKey unifiedKey(key); + EXPECT_FALSE(unifiedKey.key.empty()); +} + +/** +* @tc.name: UnifiedKey002 +* @tc.desc: Normal testcase of UnifiedKey +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, UnifiedKey002, TestSize.Level1) +{ + std::string intention = "general.text"; + std::string bundle = "com.ohos.test"; + std::string groupId = "test"; + + UnifiedKey unifiedKey(intention, bundle, groupId); + EXPECT_FALSE(unifiedKey.intention.empty()); + EXPECT_FALSE(unifiedKey.bundleName.empty()); + EXPECT_FALSE(unifiedKey.groupId.empty()); +} + +/** +* @tc.name: GetUnifiedKey001 +* @tc.desc: Normal testcase of GetUnifiedKey, this->key is empty +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetUnifiedKey001, TestSize.Level1) +{ + std::string intention = "general.text"; + std::string bundle = "com.ohos.test"; + std::string groupId = "test"; + + UnifiedKey unifiedKey(intention, bundle, groupId); + EXPECT_NO_FATAL_FAILURE(unifiedKey.GetUnifiedKey()); +} + +/** +* @tc.name: GetUnifiedKey002 +* @tc.desc: Normal testcase of GetUnifiedKey +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetUnifiedKey002, TestSize.Level1) +{ + std::string key = "general.text"; + UnifiedKey unifiedKey(key); + std::string ret = unifiedKey.GetUnifiedKey(); + EXPECT_EQ(ret, key); +} + +/** +* @tc.name: GetUnifiedKey003 +* @tc.desc: Abnormal testcase of GetUnifiedKey, this->intention is empty +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetUnifiedKey003, TestSize.Level1) +{ + std::string intention; + std::string bundle = "com.ohos.test"; + std::string groupId = "group1"; + + UnifiedKey unifiedKey(intention, bundle, groupId); + std::string ret = unifiedKey.GetUnifiedKey(); + EXPECT_EQ(ret, ""); +} + +/** +* @tc.name: GetUnifiedKey004 +* @tc.desc: Abnormal testcase of GetUnifiedKey, this->groupId is empty +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetUnifiedKey004, TestSize.Level1) +{ + std::string intention = "intention1"; + std::string bundle; + std::string groupId; + + UnifiedKey unifiedKey(intention, bundle, groupId); + std::string ret = unifiedKey.GetUnifiedKey(); + EXPECT_EQ(ret, ""); +} + +/** +* @tc.name: GetUnifiedKey005 +* @tc.desc: Abnormal testcase of GetUnifiedKey, this->groupId and this->intention is empty +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetUnifiedKey005, TestSize.Level1) +{ + std::string intention; + std::string bundle; + std::string groupId; + + UnifiedKey unifiedKey(intention, bundle, groupId); + std::string ret = unifiedKey.GetUnifiedKey(); + EXPECT_EQ(ret, ""); +} + +/** +* @tc.name: GetKeyCommonPrefix001 +* @tc.desc: Abnormal testcase of GetKeyCommonPrefix, size of this->key is 33 +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetKeyCommonPrefix001, TestSize.Level1) +{ + std::string key('A', 33); + UnifiedKey unifiedKey(key); + + std::string ret = unifiedKey.GetKeyCommonPrefix(); + EXPECT_FALSE(ret.empty()); +} + +/** +* @tc.name: GetKeyCommonPrefix002 +* @tc.desc: Abnormal testcase of GetKeyCommonPrefix, size of this->key is 31, this->intention is empty +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetKeyCommonPrefix002, TestSize.Level1) +{ + std::string intention; + std::string bundle = "com.ohos.test"; + std::string groupId('A', 31); + UnifiedKey unifiedKey(intention, bundle, groupId); + + std::string ret = unifiedKey.GetKeyCommonPrefix(); + EXPECT_EQ(ret, ""); +} + +/** +* @tc.name: GetKeyCommonPrefix003 +* @tc.desc: Abnormal testcase of GetKeyCommonPrefix, this->groupId size < INDEX_LEN +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetKeyCommonPrefix003, TestSize.Level1) +{ + std::string intention = "general.text"; + std::string bundle = "com.ohos.test"; + std::string groupId = "test"; + + UnifiedKey unifiedKey(intention, bundle, groupId); + std::string ret = unifiedKey.GetKeyCommonPrefix(); + EXPECT_EQ(ret, ""); +} + +/** +* @tc.name: GetKeyCommonPrefix004 +* @tc.desc: Abnormal testcase of GetKeyCommonPrefix, this->groupId size < INDEX_LEN +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetKeyCommonPrefix004, TestSize.Level1) +{ + std::string intention = "general.text"; + std::string bundle = "com.ohos.test"; + std::string groupId('A', 33); + + UnifiedKey unifiedKey(intention, bundle, groupId); + std::string ret = unifiedKey.GetKeyCommonPrefix(); + EXPECT_FALSE(ret.empty()); +} + +/** +* @tc.name: IsValid001 +* @tc.desc: Normal testcase of IsValid, key is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, IsValid001, TestSize.Level1) +{ + std::string intention = "general.text"; + std::string bundle = "com.ohos.test"; + std::string groupId('A', 33); + + UnifiedKey unifiedKey(intention, bundle, groupId); + bool ret = unifiedKey.IsValid(); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: IsValid002 +* @tc.desc: Abnormal testcase of IsValid, key is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, IsValid002, TestSize.Level1) +{ + std::string key('A', 33); + UnifiedKey unifiedKey(key); + + bool ret = unifiedKey.IsValid(); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: IsValid003 +* @tc.desc: Abnormal testcase of IsValid, key is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, IsValid003, TestSize.Level1) +{ + std::string key = "udmf://"; + UnifiedKey unifiedKey(key); + + bool ret = unifiedKey.IsValid(); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: PreliminaryWork002 +* @tc.desc: Normal testcase of PreliminaryWork +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, PreliminaryWork002, TestSize.Level1) +{ + std::string key = "udmf://"; + UnifiedKey unifiedKey(key); + + EXPECT_NO_FATAL_FAILURE(unifiedKey.PreliminaryWork()); +} + +/** +* @tc.name: CheckCharacter001 +* @tc.desc: Abnormal testcase of CheckCharacter, data is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, CheckCharacter001, TestSize.Level1) +{ + std::string key = "udmf://"; + UnifiedKey unifiedKey(key); + std::string_view data; + std::bitset<MAX_BIT_SIZE> rule; + + EXPECT_FALSE(unifiedKey.CheckCharacter(data, rule)); +} + +/** +* @tc.name: CheckCharacter002 +* @tc.desc: Abnormal testcase of CheckCharacter, data is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, CheckCharacter002, TestSize.Level1) +{ + std::string key = "udmf://"; + UnifiedKey unifiedKey(key); + std::string_view data = "data"; + std::bitset<MAX_BIT_SIZE> rule; + + EXPECT_FALSE(unifiedKey.CheckCharacter(data, rule)); +} + +/** +* @tc.name: ExtractAndValidateSegment001 +* @tc.desc: Abnormal testcase of ExtractAndValidateSegment, data is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, ExtractAndValidateSegment001, TestSize.Level1) +{ + std::string key = "udmf://"; + UnifiedKey unifiedKey(key); + std::string_view data = "data"; + std::string field; + std::bitset<MAX_BIT_SIZE> rule; + std::string name; + + EXPECT_FALSE(unifiedKey.ExtractAndValidateSegment(data, field, rule, name)); +} + +/** +* @tc.name: ExtractAndValidateSegment002 +* @tc.desc: Abnormal testcase of ExtractAndValidateSegment, data is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, ExtractAndValidateSegment002, TestSize.Level1) +{ + std::string key = "udmf://"; + UnifiedKey unifiedKey(key); + std::string_view data = "udmf://"; + std::string field = "udmf://"; + std::bitset<MAX_BIT_SIZE> rule; + std::string name; + + EXPECT_FALSE(unifiedKey.ExtractAndValidateSegment(data, field, rule, name)); +} +} // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/unified_meta_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/unified_meta_test.cpp index 2d569086389fc2b86e0f3c1feaad73aa15af29e5..126c1d5c2aa1373bb8aa2853d1ae9c7b984fd6b9 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/unified_meta_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/unified_meta_test.cpp @@ -253,6 +253,15 @@ HWTEST_F(UnifiedMetaTest, IsValidIntention001, TestSize.Level1) bool ret1 = UnifiedDataUtils::IsValidIntention(Intention::UD_INTENTION_DATA_HUB); EXPECT_TRUE(ret1); + + bool ret2 = UnifiedDataUtils::IsValidIntention(Intention::UD_INTENTION_SYSTEM_SHARE); + EXPECT_TRUE(ret2); + + bool ret3 = UnifiedDataUtils::IsValidIntention(Intention::UD_INTENTION_PICKER); + EXPECT_TRUE(ret3); + + bool ret4 = UnifiedDataUtils::IsValidIntention(Intention::UD_INTENTION_MENU); + EXPECT_TRUE(ret4); } /** @@ -385,6 +394,15 @@ HWTEST_F(UnifiedMetaTest, IsPersistByIntention001, TestSize.Level1) bool ret3 = UnifiedDataUtils::IsPersist(Intention::UD_INTENTION_BASE); EXPECT_FALSE(ret3); + + bool ret4 = UnifiedDataUtils::IsPersist(Intention::UD_INTENTION_PICKER); + EXPECT_TRUE(ret4); + + bool ret5 = UnifiedDataUtils::IsPersist(Intention::UD_INTENTION_MENU); + EXPECT_TRUE(ret5); + + bool ret6 = UnifiedDataUtils::IsPersist(Intention::UD_INTENTION_SYSTEM_SHARE); + EXPECT_TRUE(ret6); } /** @@ -402,6 +420,15 @@ HWTEST_F(UnifiedMetaTest, IsPersistByStr001, TestSize.Level1) bool ret2 = UnifiedDataUtils::IsPersist("invalid param"); EXPECT_FALSE(ret2); + + bool ret3 = UnifiedDataUtils::IsPersist("Picker"); + EXPECT_TRUE(ret3); + + bool ret4 = UnifiedDataUtils::IsPersist("Menu"); + EXPECT_TRUE(ret4); + + bool ret5 = UnifiedDataUtils::IsPersist("SystemShare"); + EXPECT_TRUE(ret5); } /** @@ -419,35 +446,267 @@ HWTEST_F(UnifiedMetaTest, GetIntentionByString001, TestSize.Level1) Intention ret2 = UnifiedDataUtils::GetIntentionByString("invalid param"); EXPECT_EQ(ret2, UD_INTENTION_BUTT); + + Intention ret3 = UnifiedDataUtils::GetIntentionByString("Picker"); + EXPECT_EQ(ret3, Intention::UD_INTENTION_PICKER); + + Intention ret4 = UnifiedDataUtils::GetIntentionByString("Menu"); + EXPECT_EQ(ret4, Intention::UD_INTENTION_MENU); + + Intention ret5 = UnifiedDataUtils::GetIntentionByString("SystemShare"); + EXPECT_EQ(ret5, Intention::UD_INTENTION_SYSTEM_SHARE); } /** -* @tc.name: IsValidOptions001 +* @tc.name: IsValidOptionsNonDrag001 * @tc.desc: Normal testcase of IsPersist * @tc.type: FUNC */ -HWTEST_F(UnifiedMetaTest, IsValidOptions001, TestSize.Level1) +HWTEST_F(UnifiedMetaTest, IsValidOptionsNonDrag001, TestSize.Level1) { std::string keyDataHub = "udmf://DataHub/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; std::string keyDrag = "udmf://drag/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string keyPicker = "udmf://Picker/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string keyMenu = "udmf://Menu/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string keySystemShare = "udmf://SystemShare/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; std::string intentionDataHub = "DataHub"; std::string intentionDrag = "drag"; + std::string intentionPicker = "Picker"; + std::string intentionMenu = "Menu"; + std::string intentionSystemShare = "SystemShare"; std::string intentionEmpty = ""; + UnifiedKey key1(""); - bool ret = UnifiedDataUtils::IsValidOptions("", intentionDataHub); + bool ret = UnifiedDataUtils::IsValidOptionsNonDrag(key1, intentionDataHub); EXPECT_TRUE(ret); - bool ret1 = UnifiedDataUtils::IsValidOptions(keyDataHub, intentionEmpty); + UnifiedKey key2(keyDataHub); + bool ret1 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionEmpty); EXPECT_TRUE(ret1); + bool ret2 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionDataHub); + EXPECT_TRUE(ret2); + bool ret3 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionDrag); + EXPECT_FALSE(ret3); + bool ret4 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionPicker); + EXPECT_FALSE(ret4); + bool ret5 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionMenu); + EXPECT_FALSE(ret5); + bool ret6 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionSystemShare); + EXPECT_FALSE(ret6); + UnifiedKey key3(keyDrag); + bool ret7 = UnifiedDataUtils::IsValidOptionsNonDrag(key3, intentionDrag); + EXPECT_FALSE(ret7); + UnifiedKey key4(keyPicker); + bool ret8 = UnifiedDataUtils::IsValidOptionsNonDrag(key4, intentionPicker); + EXPECT_TRUE(ret8); + UnifiedKey key5(keyMenu); + bool ret9 = UnifiedDataUtils::IsValidOptionsNonDrag(key5, intentionMenu); + EXPECT_TRUE(ret9); + UnifiedKey key6(keySystemShare); + bool ret10 = UnifiedDataUtils::IsValidOptionsNonDrag(key6, intentionSystemShare); + EXPECT_TRUE(ret10); +} + +/** +* @tc.name: IsValidOptionsNonDrag +* @tc.desc: Normal testcase of key and intention +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, IsAllowedQuery, TestSize.Level1) +{ + std::string keyDataHub = "udmf://DataHub/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string keyDrag = "udmf://drag/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string keyPicker = "udmf://Picker/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string keyMenu = "udmf://Menu/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string keySystemShare = "udmf://SystemShare/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string intentionDataHub = "DataHub"; + std::string intentionDrag = "drag"; + std::string intentionPicker = "Picker"; + std::string intentionMenu = "Menu"; + std::string intentionSystemShare = "SystemShare"; + std::string intentionEmpty = ""; + UnifiedKey key1(""); - bool ret2 = UnifiedDataUtils::IsValidOptions(keyDataHub, intentionDataHub); + bool ret = UnifiedDataUtils::IsValidOptionsNonDrag(key1, intentionDataHub); + EXPECT_TRUE(ret); + bool ret1 = UnifiedDataUtils::IsValidOptionsNonDrag(key1, intentionPicker); + EXPECT_FALSE(ret1); + UnifiedKey key2(keyDataHub); + bool ret2 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionEmpty); EXPECT_TRUE(ret2); + bool ret3 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionDataHub); + EXPECT_TRUE(ret3); + bool ret4 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionDrag); + EXPECT_FALSE(ret4); + bool ret5 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionPicker); + EXPECT_FALSE(ret5); + bool ret6 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionMenu); + EXPECT_FALSE(ret6); + bool ret7 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionSystemShare); + EXPECT_FALSE(ret7); + UnifiedKey key3(keyDrag); + bool ret8 = UnifiedDataUtils::IsValidOptionsNonDrag(key3, intentionDrag); + EXPECT_FALSE(ret8); +} + +/** +* @tc.name: IsValidQuery001 +* @tc.desc: Normal testcase of key and intention +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, IsValidQuery001, TestSize.Level1) +{ + std::string keyPicker = "udmf://Picker/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string intentionDataHub = "DataHub"; + std::string intentionDrag = "drag"; + std::string intentionPicker = "Picker"; + std::string intentionMenu = "Menu"; + std::string intentionSystemShare = "SystemShare"; + std::string intentionEmpty = ""; + + UnifiedKey key(keyPicker); + bool ret = UnifiedDataUtils::IsValidOptionsNonDrag(key, intentionPicker); + EXPECT_TRUE(ret); + + bool ret1 = UnifiedDataUtils::IsValidOptionsNonDrag(key, intentionEmpty); + EXPECT_TRUE(ret1); + + bool ret2 = UnifiedDataUtils::IsValidOptionsNonDrag(key, intentionDataHub); + EXPECT_FALSE(ret2); - bool ret3 = UnifiedDataUtils::IsValidOptions(keyDataHub, intentionDrag); + bool ret3 = UnifiedDataUtils::IsValidOptionsNonDrag(key, intentionDrag); EXPECT_FALSE(ret3); - bool ret4 = UnifiedDataUtils::IsValidOptions(keyDrag, intentionDrag); + bool ret4 = UnifiedDataUtils::IsValidOptionsNonDrag(key, intentionMenu); EXPECT_FALSE(ret4); + + bool ret5 = UnifiedDataUtils::IsValidOptionsNonDrag(key, intentionSystemShare); + EXPECT_FALSE(ret5); +} + +/** +* @tc.name: IsValidOptions002 +* @tc.desc: Abnormal testcase of IsValidOptions, intention is empty +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, IsValidOptions002, TestSize.Level1) +{ + UnifiedKey key; + key.key = "key://"; + std::string intention; + std::string validIntention; + UnifiedDataUtils unifiedDataUtils; + bool ret = unifiedDataUtils.IsValidOptions(key, intention, validIntention); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: IsValidOptions003 +* @tc.desc: Abnormal testcase of IsValidOptions, intention != validIntention +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, IsValidOptions003, TestSize.Level1) +{ + UnifiedKey key; + key.key = "key://"; + std::string intention = "drag"; + std::string validIntention = "DataHub"; + UnifiedDataUtils unifiedDataUtils; + bool ret = unifiedDataUtils.IsValidOptions(key, intention, validIntention); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: IsValidOptions004 +* @tc.desc: Abnormal testcase of IsValidOptions, key.intention != validIntention +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, IsValidOptions004, TestSize.Level1) +{ + UnifiedKey key; + key.key = "key://"; + key.intention = "DataHub"; + std::string intention = "DataHub"; + std::string validIntention = "drag"; + UnifiedDataUtils unifiedDataUtils; + bool ret = unifiedDataUtils.IsValidOptions(key, intention, validIntention); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: ConvertToUDDetails001 +* @tc.desc: Abnormal testcase of ConvertToUDDetails, object is nullptr +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, ConvertToUDDetails001, TestSize.Level1) +{ + std::shared_ptr<Object> object = nullptr; + EXPECT_NO_FATAL_FAILURE(ObjectUtils::ConvertToUDDetails(object)); +} + +/** +* @tc.name: GetValueSize001 +* @tc.desc: Normal testcase of GetValueSize +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, GetValueSize001, TestSize.Level1) +{ + ValueType value = std::make_shared<OHOS::Media::PixelMap>(); + bool isCalValueType = true; + int64_t ret = ObjectUtils::GetValueSize(value, isCalValueType); + EXPECT_EQ(ret, (std::get<std::shared_ptr<OHOS::Media::PixelMap>>(value))->GetByteCount()); +} + +/** +* @tc.name: GetValueSize002 +* @tc.desc: Normal testcase of GetValueSize +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, GetValueSize002, TestSize.Level1) +{ + ValueType value = std::make_shared<OHOS::AAFwk::Want>(); + bool isCalValueType = true; + int64_t ret = ObjectUtils::GetValueSize(value, isCalValueType); + EXPECT_NE(ret, 0); +} + +/** +* @tc.name: GetValueSize003 +* @tc.desc: Abnormal testcase of GetValueSize, value is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, GetValueSize003, TestSize.Level1) +{ + ValueType value = true; + bool isCalValueType = true; + int64_t ret = ObjectUtils::GetValueSize(value, isCalValueType); + EXPECT_EQ(ret, std::visit([] (const auto &val) { return sizeof(val); }, value)); +} + +/* * +* @tc.name: GetObjectValueSize_001 +* @tc.desc: Abnormal test of GetObjectValueSize, key is DETAILS +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, GetObjectValueSize_001, TestSize.Level1) +{ + std::shared_ptr<Object> object = std::make_shared<Object>(); + bool isCalValueType = true; + object->value_["details"] = std::make_shared<OHOS::Media::PixelMap>(); + size_t ret = ObjectUtils::GetObjectValueSize(object, isCalValueType); + EXPECT_EQ(ret, 0); +} + +/* * +* @tc.name: GetAllObjectSize_001 +* @tc.desc: Abnormal test of GetAllObjectSize, object is nullptr +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, GetAllObjectSize_001, TestSize.Level1) +{ + std::shared_ptr<Object> object = nullptr; + int64_t ret = ObjectUtils::GetAllObjectSize(object); + EXPECT_EQ(ret, 0); } /** @@ -506,4 +765,73 @@ HWTEST_F(UnifiedMetaTest, GetValue002, TestSize.Level1) bool ret2 = object.GetValue("invalid key", valueEmpty); EXPECT_FALSE(ret2); } + +/** +* @tc.name: IsFileMangerIntention +* @tc.desc: IsFileMangerIntention testcase +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, IsFileMangerIntention, TestSize.Level1) +{ + std::string intentionDataHub = "DataHub"; + std::string intentionDrag = "drag"; + std::string intentionPicker = "Picker"; + std::string intentionMenu = "Menu"; + std::string intentionSystemShare = "SystemShare"; + + bool ret = UnifiedDataUtils::IsFileMangerIntention(intentionDataHub); + EXPECT_FALSE(ret); + bool ret1 = UnifiedDataUtils::IsFileMangerIntention(intentionDrag); + EXPECT_FALSE(ret1); + bool ret2 = UnifiedDataUtils::IsFileMangerIntention(intentionPicker); + EXPECT_TRUE(ret2); + bool ret3 = UnifiedDataUtils::IsFileMangerIntention(intentionMenu); + EXPECT_TRUE(ret3); + bool ret4 = UnifiedDataUtils::IsFileMangerIntention(intentionSystemShare); + EXPECT_TRUE(ret4); +} + +/** +* @tc.name: IsFileMangerIntention +* @tc.desc: IsFileMangerIntention testcase +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, GetBelongsToFileType, TestSize.Level1) +{ + std::string utdId = ""; + std::string fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_TRUE(fileType.empty()); + + utdId = "general.html"; + fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_TRUE(fileType.empty()); + + utdId = "general.plain-text"; + fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_TRUE(fileType.empty()); + + utdId = "general.text"; + fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_TRUE(fileType.empty()); + + utdId = "aaccss"; + fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_TRUE(fileType.empty()); + + utdId = "general.file"; + fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_EQ(fileType, "general.file"); + + utdId = "general.image"; + fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_EQ(fileType, "general.image"); + + utdId = "general.avi"; + fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_EQ(fileType, "general.video"); + + utdId = "com.adobe.pdf"; + fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_EQ(fileType, "general.file"); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/unified_record_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/unified_record_test.cpp index 05775c9efdba8e10204c79ac22868a09f0d51731..92ea1d92dfe6efa9885afa627c4caf65db997989 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/unified_record_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/unified_record_test.cpp @@ -88,7 +88,6 @@ HWTEST_F(UnifiedRecordTest, GetValue001, TestSize.Level1) LOG_INFO(UDMF_TEST, "GetValue001 end."); } - /** * @tc.name: Constructor_001 * @tc.desc: Verify the constructor. @@ -142,6 +141,32 @@ HWTEST_F(UnifiedRecordTest, Constructor_002, TestSize.Level0) EXPECT_TRUE(std::holds_alternative<std::shared_ptr<Object>>(it->second)); } +/** + * @tc.name: GetDataId_001 + * @tc.desc: Get dataId. + * @tc.type: FUNC + */ +HWTEST_F(UnifiedRecordTest, GetDataId_001, TestSize.Level0) +{ + UnifiedRecord record(TEXT); + uint32_t dataId = 1; + record.SetDataId(dataId); + auto data = record.GetDataId(); + EXPECT_EQ(data, 1); +} + +/** + * @tc.name: SetChannelName_001 + * @tc.desc: Set channelName. + * @tc.type: FUNC + */ +HWTEST_F(UnifiedRecordTest, SetChannelName_001, TestSize.Level0) +{ + UnifiedRecord record(TEXT); + std::string channelName = "channelName"; + EXPECT_NO_FATAL_FAILURE(record.SetChannelName(channelName);); +} + /** * @tc.name: Constructor_003 * @tc.desc: Verify the constructor. @@ -264,12 +289,12 @@ HWTEST_F(UnifiedRecordTest, GetEntryTest001, TestSize.Level1) UnifiedData readData; status = UdmfClient::GetInstance().GetData(option2, readData); auto recordFile = readData.GetRecordAt(0); - auto udsValue = recordFile->GetEntry("general.file"); + auto udsValue = recordFile->GetEntry("general.file-uri"); EXPECT_TRUE(std::holds_alternative<std::shared_ptr<Object>>(udsValue)); std::shared_ptr<Object> fileUds = std::get<std::shared_ptr<Object>>(udsValue); EXPECT_EQ(std::get<std::string>(fileUds->value_[ORI_URI]), "https://file/txt.txt"); auto recordImage = readData.GetRecordAt(1); - auto imageValue = recordImage->GetEntry("general.image"); + auto imageValue = recordImage->GetEntry("general.file-uri"); EXPECT_TRUE(std::holds_alternative<std::shared_ptr<Object>>(imageValue)); std::shared_ptr<Object> imageUds = std::get<std::shared_ptr<Object>>(imageValue); EXPECT_EQ(std::get<std::string>(imageUds->value_[ORI_URI]), "https://file/txt.txt"); @@ -307,12 +332,12 @@ HWTEST_F(UnifiedRecordTest, GetEntryTest002, TestSize.Level1) UnifiedData readData; status = UdmfClient::GetInstance().GetData(option2, readData); auto recordFile = readData.GetRecordAt(0); - auto udsValue = recordFile->GetEntry("general.file"); + auto udsValue = recordFile->GetEntry("general.file-uri"); EXPECT_TRUE(std::holds_alternative<std::shared_ptr<Object>>(udsValue)); std::shared_ptr<Object> fileUds = std::get<std::shared_ptr<Object>>(udsValue); EXPECT_EQ(std::get<std::string>(fileUds->value_[ORI_URI]), "https://file/txt.txt"); auto recordImage = readData.GetRecordAt(1); - auto imageValue = recordImage->GetEntry("general.image"); + auto imageValue = recordImage->GetEntry("general.file-uri"); EXPECT_TRUE(std::holds_alternative<std::shared_ptr<Object>>(imageValue)); std::shared_ptr<Object> imageUds = std::get<std::shared_ptr<Object>>(imageValue); EXPECT_EQ(std::get<std::string>(imageUds->value_[ORI_URI]), "https://file/txt.txt"); @@ -386,4 +411,16 @@ HWTEST_F(UnifiedRecordTest, GetEntryTest003, TestSize.Level1) EXPECT_TRUE(std::holds_alternative<std::monostate>( std::get<std::shared_ptr<Object>>(fifthValue)->value_[VALUE_TYPE])); } + +/** + * @tc.name: ComputeUris_001 + * @tc.desc: Compute uri + * @tc.type: FUNC + */ +HWTEST_F(UnifiedRecordTest, ComputeUris_001, TestSize.Level0) +{ + UnifiedRecord record(TEXT); + const std::function<bool(UriInfo &)> action; + EXPECT_NO_FATAL_FAILURE(record.ComputeUris(action)); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/utd_client_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/utd_client_test.cpp index 361ebd48c29d49f4d79e3b84f634f5c2d9a01514..99b5355bd7db3bcf6fab1da5906987ef4a849e05 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/utd_client_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/utd_client_test.cpp @@ -16,6 +16,7 @@ #include <gtest/gtest.h> #include <unistd.h> +#include <thread> #include "token_setproc.h" #include "accesstoken_kit.h" @@ -26,6 +27,7 @@ #include "type_descriptor.h" #include "preset_type_descriptors.h" #include "utd_graph.h" +#include "custom_utd_store.h" using namespace testing::ext; using namespace OHOS::Security::AccessToken; @@ -33,12 +35,16 @@ using namespace OHOS::UDMF; using namespace OHOS; namespace OHOS::Test { +constexpr const int64_t SLEEP_INTERVAL = 12; +constexpr const int32_t USERID = 100; +constexpr const char *FLEXIBLE_TYPE_FLAG = "flex.z"; class UtdClientTest : public testing::Test { public: static void SetUpTestCase(); static void TearDownTestCase(); void SetUp() override; void TearDown() override; + static bool TryReloadCustomUtdTest(); }; void UtdClientTest::SetUpTestCase() @@ -1830,6 +1836,451 @@ HWTEST_F(UtdClientTest, IsUtd005, TestSize.Level1) LOG_INFO(UDMF_TEST, "IsUtd005 end."); } +/** +* @tc.name: TryReloadCustomUtdTest001 +* @tc.desc: TryReloadCustomUtd +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, TryReloadCustomUtdTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest001 begin."); + UtdClient utdClient; + bool ret = utdClient.TryReloadCustomUtd(); + EXPECT_FALSE(ret); + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest001 end."); +} + +/** +* @tc.name: TryReloadCustomUtdTest002 +* @tc.desc: TryReloadCustomUtd +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, TryReloadCustomUtdTest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest002 begin."); + UtdClient utdClient; + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + bool ret = utdClient.TryReloadCustomUtd(); + EXPECT_FALSE(ret); + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest002 end."); +} + +/** +* @tc.name: TryReloadCustomUtdTest003 +* @tc.desc: TryReloadCustomUtd +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, TryReloadCustomUtdTest003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest003 begin."); + UtdClient utdClient; + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + bool ret = utdClient.TryReloadCustomUtd(); + EXPECT_TRUE(ret); + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest003 end."); +} + +/** +* @tc.name: TryReloadCustomUtdTest004 +* @tc.desc: TryReloadCustomUtd +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, TryReloadCustomUtdTest004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest004 begin."); + UtdClient utdClient; + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + std::filesystem::resize_file(filePath, USERID * USERID); + bool ret = utdClient.TryReloadCustomUtd(); + EXPECT_FALSE(ret); + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest004 end."); +} + +bool UtdClientTest::TryReloadCustomUtdTest() +{ + UtdClient utdClient; + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + std::filesystem::resize_file(filePath, USERID * USERID); + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + return utdClient.TryReloadCustomUtd(); +} + +/** + * @tc.name: TryReloadCustomUtdTest005 + * @tc.desc: TryReloadCustomUtd + * @tc.type: FUNC + */ +HWTEST_F(UtdClientTest, TryReloadCustomUtdTest005, TestSize.Level0) +{ + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest005 begin."); + std::thread t1([&]() { + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + auto ret = TryReloadCustomUtdTest(); + EXPECT_TRUE(ret); + }); + EXPECT_NO_FATAL_FAILURE(t1.join()); + std::thread t2([&]() { + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + auto ret = TryReloadCustomUtdTest(); + EXPECT_TRUE(ret); + }); + EXPECT_NO_FATAL_FAILURE(t2.join()); + std::thread t3([&]() { + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + auto ret = TryReloadCustomUtdTest(); + EXPECT_TRUE(ret); + }); + EXPECT_NO_FATAL_FAILURE(t3.join()); + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest005 end."); +} + +/** +* @tc.name: GetTypeDescriptorTest001 +* @tc.desc: GetTypeDescriptor +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeDescriptorTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeDescriptorTest001 begin."); + UtdClient utdClient; + std::string typeId("NotExist"); + std::shared_ptr<TypeDescriptor> descriptor = nullptr; + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + + auto ret = utdClient.GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(ret, 0); + LOG_INFO(UDMF_TEST, "GetTypeDescriptorTest001 end."); +} + +/** +* @tc.name: GetTypeDescriptorTest002 +* @tc.desc: GetTypeDescriptor +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeDescriptorTest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeDescriptorTest002 begin."); + UtdClient utdClient; + std::string typeId("NotExist"); + std::shared_ptr<TypeDescriptor> descriptor = nullptr; + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + auto ret = utdClient.GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(ret, 0); + LOG_INFO(UDMF_TEST, "GetTypeDescriptorTest002 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtensionTest001 +* @tc.desc: GetUniformDataTypeByFilenameExtension +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtensionTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionTest001 begin."); + UtdClient utdClient; + std::string extension = "NotExist"; + std::string blongsToType = "general.object"; + std::string currType; + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + auto ret = utdClient.GetUniformDataTypeByFilenameExtension(extension, currType, blongsToType); + EXPECT_EQ(ret, Status::E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionTest001 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtensionTest002 +* @tc.desc: GetUniformDataTypeByFilenameExtension +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtensionTest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionTest002 begin."); + UtdClient utdClient; + std::string extension = ".mp3"; + std::string blongsToType = "NotExist"; + std::string currType; + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + auto ret = utdClient.GetUniformDataTypeByFilenameExtension(extension, currType, blongsToType); + EXPECT_EQ(ret, Status::E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionTest002 end."); +} + +/** +* @tc.name: GetUniformDataTypesByFilenameExtensionTest007 +* @tc.desc: GetUniformDataTypesByFilenameExtension +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypesByFilenameExtensionTest007, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypesByFilenameExtensionTest007 begin."); + UtdClient utdClient; + std::string fileExtension = "fileExtension"; + std::vector<std::string> typeIds = std::vector<std::string>(); + std::string belongsTo = ""; + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + auto ret = utdClient.GetUniformDataTypesByFilenameExtension(fileExtension, typeIds, belongsTo); + EXPECT_EQ(ret, Status::E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypesByFilenameExtensionTest007 end."); +} + +/** +* @tc.name: GetUniformDataTypeByMIMETypeTest008 +* @tc.desc: GetUniformDataTypeByMIMEType +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMETypeTest008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeTest008 begin."); + UtdClient utdClient; + std::string mimeType = ""; + std::string blongsToType = "test02"; + std::string currType; + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + auto ret = utdClient.GetUniformDataTypeByMIMEType(mimeType, currType, blongsToType); + EXPECT_EQ(ret, Status::E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeTest008 end."); +} + +/** +* @tc.name: GetTypeIdFromCfgTest002 +* @tc.desc: GetTypeIdFromCfg +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeIdFromCfgTest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeIdFromCfgTest002 begin."); + std::string mimeType = "mimeType*"; + UtdClient utdClient; + utdClient.descriptorCfgs_ = std::vector<TypeDescriptorCfg>(); + + std::string ret = utdClient.GetTypeIdFromCfg(mimeType); + EXPECT_EQ(ret, ""); + LOG_INFO(UDMF_TEST, "GetTypeIdFromCfgTest002 end."); +} + +/** +* @tc.name: GetTypeIdFromCfgTest003 +* @tc.desc: GetTypeIdFromCfg +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeIdFromCfgTest003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeIdFromCfgTest003 begin."); + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + std::string mimeType = "mimeType*"; + UtdClient utdClient; + utdClient.descriptorCfgs_ = std::vector<TypeDescriptorCfg>(); + std::string ret = utdClient.GetTypeIdFromCfg(mimeType); + EXPECT_EQ(ret, ""); + LOG_INFO(UDMF_TEST, "GetTypeIdFromCfgTest003 end."); +} + +/** +* @tc.name: GetUniformDataTypesByMIMETypeTest005 +* @tc.desc: GetUniformDataTypesByMIMEType +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypesByMIMETypeTest005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypesByMIMETypeTest005 begin."); + UtdClient utdClient; + std::string mimeType = "video/x-ms-asf"; + std::vector<std::string> currTypes; + std::string blongsToType = "general.media"; + + auto ret = utdClient.GetUniformDataTypesByMIMEType(mimeType, currTypes, blongsToType); + EXPECT_EQ(ret, Status::E_OK); + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + ret = utdClient.GetUniformDataTypesByMIMEType(mimeType, currTypes, blongsToType); + EXPECT_EQ(ret, Status::E_OK); + LOG_INFO(UDMF_TEST, "GetUniformDataTypesByMIMETypeTest005 end."); +} + +/** +* @tc.name: GetUniformDataTypesByMIMETypeTest006 +* @tc.desc: GetUniformDataTypesByMIMEType +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypesByMIMETypeTest006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypesByMIMETypeTest006 begin."); + std::string mimeType = "mimeType"; + std::vector<std::string> typeIds = std::vector<std::string>(); + std::string belongsTo = ""; + UtdClient utdClient; + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + auto ret = utdClient.GetUniformDataTypesByMIMEType(mimeType, typeIds, belongsTo); + EXPECT_EQ(ret, Status::E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypesByMIMETypeTest006 end."); +} + +/** +* @tc.name: InitTest001 +* @tc.desc: Init +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, InitTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "InitTest001 begin."); + UtdClient utdClient; + utdClient.descriptorCfgs_ = std::vector<TypeDescriptorCfg>(); + TypeDescriptorCfg cfg; + cfg.typeId = "com.example.utdTest.document"; + cfg.filenameExtensions = { ".my-doc", ".my-document" }; + utdClient.descriptorCfgs_.push_back(cfg); + + auto ret = utdClient.Init(); + EXPECT_TRUE(ret); + LOG_INFO(UDMF_TEST, "InitTest001 end."); +} + +/** +* @tc.name: GetTypeIdsFromCfgtest001 +* @tc.desc: GetTypeIdsFromCfg +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeIdsFromCfgtest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeIdsFromCfgtest001 begin."); + UtdClient utdClient; + std::string mimeType = "application/my-doc"; + utdClient.descriptorCfgs_ = std::vector<TypeDescriptorCfg>(); + + auto ret = utdClient.GetTypeIdsFromCfg(mimeType); + EXPECT_TRUE(ret.empty()); + LOG_INFO(UDMF_TEST, "GetTypeIdsFromCfgtest001 end."); +} + +/** +* @tc.name: GetTypeIdsFromCfgtest002 +* @tc.desc: GetTypeIdsFromCfg +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeIdsFromCfgtest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeIdsFromCfgtest002 begin."); + UtdClient utdClient; + std::string mimeType = "application/my-doc"; + utdClient.descriptorCfgs_ = std::vector<TypeDescriptorCfg>(); + TypeDescriptorCfg cfg; + cfg.typeId = "com.example.utdTest.document"; + cfg.mimeTypes = { "application/my-doc", "application/my-document" }; + utdClient.descriptorCfgs_.push_back(cfg); + + auto ret = utdClient.GetTypeIdsFromCfg(mimeType); + EXPECT_FALSE(ret.empty()); + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + ret = utdClient.GetTypeIdsFromCfg(mimeType); + EXPECT_FALSE(ret.empty()); + LOG_INFO(UDMF_TEST, "GetTypeIdsFromCfgtest002 end."); +} + +/** +* @tc.name: GetTypeIdFromCfg002 +* @tc.desc: GetTypeIdFromCfg +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeIdFromCfg002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeIdFromCfg002 begin."); + std::string mimeType = ""; + UtdClient utdClient; + utdClient.descriptorCfgs_ = std::vector<TypeDescriptorCfg>(); + auto ret = utdClient.GetTypeIdFromCfg(mimeType); + EXPECT_EQ(ret, ""); + mimeType = "mimeType"; + ret = utdClient.GetTypeIdFromCfg(mimeType); + EXPECT_EQ(ret, ""); + mimeType = "mimeType*"; + ret = utdClient.GetTypeIdFromCfg(mimeType); + EXPECT_EQ(ret, ""); + LOG_INFO(UDMF_TEST, "GetTypeIdFromCfg002 end."); +} + +/** +* @tc.name: GetTypeIdFromCfg003 +* @tc.desc: GetTypeIdFromCfg +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeIdFromCfg003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeIdFromCfg003 begin."); + const std::string mimeType = "mimeType"; + UtdClient utdClient; + utdClient.descriptorCfgs_ = std::vector<TypeDescriptorCfg>(); + std::string ret = utdClient.GetTypeIdFromCfg(mimeType); + EXPECT_EQ(ret, ""); + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + ret = utdClient.GetTypeIdFromCfg(mimeType); + EXPECT_EQ(ret, ""); + LOG_INFO(UDMF_TEST, "GetTypeIdFromCfg003 end."); +} + /** * @tc.name: IsHapTokenType001 * @tc.desc: Normal testcase of IsHapTokenType @@ -1877,4 +2328,216 @@ HWTEST_F(UtdClientTest, IsHapTokenType001, TestSize.Level1) EXPECT_TRUE(ret); LOG_INFO(UDMF_TEST, "IsHapTokenType001 end."); } + +/** +* @tc.name: GetUniformDataTypeByMIMETypeWithBelongsTo001 +* @tc.desc: Abnormal testcase of GetUniformDataTypeByMIMEType with belongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMETypeWithBelongsTo001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeWithBelongsTo001 begin."); + std::string mimeType = "video/mp2ts"; + std::string utdType; + std::string blongsToType = "invalid_type"; + auto status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, utdType, blongsToType); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeWithBelongsTo001 end."); +} + +/** +* @tc.name: GetUniformDataTypeByMIMETypeWithBelongsTo002 +* @tc.desc: Normal testcase of GetUniformDataTypeByMIMEType with belongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMETypeWithBelongsTo002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeWithBelongsTo002 begin."); + std::string mimeType = "video/mp2ts"; + std::string utdType; + std::string blongsToType = "general.video"; + auto status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType, "general.ts"); + + mimeType = "video/mp2t"; + utdType = ""; + blongsToType = "general.video"; + status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType, "general.ts"); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeWithBelongsTo002 end."); +} + +/** +* @tc.name: GetUniformDataTypeByMIMETypeWithBelongsTo003 +* @tc.desc: Normal testcase of GetUniformDataTypeByMIMEType with higher belongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMETypeWithBelongsTo003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeWithBelongsTo003 begin."); + std::string mimeType = "video/mp2ts"; + std::string utdType; + std::string blongsToType = "general.media"; + auto status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType, "general.ts"); + + mimeType = "video/mp2t"; + utdType = ""; + blongsToType = "general.object"; + status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType, "general.ts"); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeWithBelongsTo003 end."); +} + +/** +* @tc.name: GetUniformDataTypeByMIMETypeWithBelongsTo004 +* @tc.desc: Abnormal testcase of GetUniformDataTypeByMIMEType with belongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMETypeWithBelongsTo004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeWithBelongsTo004 begin."); + std::string mimeType = "video/mp2ts"; + std::string utdType; + std::string blongsToType = "general.source-code"; + auto status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType.compare(0, std::string(FLEXIBLE_TYPE_FLAG).size(), FLEXIBLE_TYPE_FLAG), 0); + + mimeType = "video/mp2t"; + utdType = ""; + blongsToType = "general.source-code"; + status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType.compare(0, std::string(FLEXIBLE_TYPE_FLAG).size(), FLEXIBLE_TYPE_FLAG), 0); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeWithBelongsTo004 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtensionWithBelongsTo001 +* @tc.desc: Abnormal testcase of GetUniformDataTypeByFilenameExtension with belongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtensionWithBelongsTo001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionWithBelongsTo001 begin."); + std::string filenameExtension = ".ts"; + std::string utdType; + std::string blongsToType = "invalid_type"; + auto status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension( + filenameExtension, utdType, blongsToType); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionWithBelongsTo001 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtensionWithBelongsTo002 +* @tc.desc: Normal testcase of GetUniformDataTypeByFilenameExtension with belongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtensionWithBelongsTo002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionWithBelongsTo002 begin."); + std::string filenameExtension = ".ts"; + std::string utdType; + std::string blongsToType = "general.video"; + auto status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension( + filenameExtension, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType, "general.ts"); + + utdType = ""; + blongsToType = "general.source-code"; + status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType, "general.type-script"); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionWithBelongsTo002 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtensionWithBelongsTo003 +* @tc.desc: Normal testcase of GetUniformDataTypeByFilenameExtension with higher belongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtensionWithBelongsTo003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionWithBelongsTo003 begin."); + std::string filenameExtension = ".ts"; + std::string utdType; + std::string blongsToType = "general.media"; + auto status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension( + filenameExtension, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType, "general.ts"); + + utdType = ""; + blongsToType = "general.text"; + status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType, "general.type-script"); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionWithBelongsTo003 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtensionWithBelongsTo004 +* @tc.desc: Abnormal testcase of GetUniformDataTypeByFilenameExtension with belongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtensionWithBelongsTo004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionWithBelongsTo004 begin."); + std::string filenameExtension = ".ts"; + std::string utdType; + std::string blongsToType = "general.java-script"; + auto status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension( + filenameExtension, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType.compare(0, std::string(FLEXIBLE_TYPE_FLAG).size(), FLEXIBLE_TYPE_FLAG), 0); + + utdType = ""; + blongsToType = "general.audio"; + status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType.compare(0, std::string(FLEXIBLE_TYPE_FLAG).size(), FLEXIBLE_TYPE_FLAG), 0); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionWithBelongsTo004 end."); +} + +/** +* @tc.name: GetUniformDataTypeByMIMETypeByPrefix003 +* @tc.desc: normal testcase of GetUniformDataTypeByMIMEType by prefix. +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMETypeByPrefix003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeByPrefix003 begin."); + std::string mimeType = "application/vnd.*"; + std::string currType; + auto status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, currType); + EXPECT_EQ(status, E_OK); + std::shared_ptr<TypeDescriptor> descriptor; + status = UtdClient::GetInstance().GetTypeDescriptor(currType, descriptor); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(descriptor->GetTypeId(), "general.ebook"); + + currType = ""; + std::string blongsToType = "general.ebook"; + status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, currType, blongsToType); + EXPECT_EQ(status, E_OK); + status = UtdClient::GetInstance().GetTypeDescriptor(currType, descriptor); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(descriptor->GetTypeId(), "general.ebook"); + + currType = ""; + blongsToType = "general.media"; + status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, currType, blongsToType); + EXPECT_EQ(status, E_OK); + status = UtdClient::GetInstance().GetTypeDescriptor(currType, descriptor); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(descriptor->GetTypeId(), "general.image"); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeByPrefix003 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/utd_concurrent_update_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/utd_concurrent_update_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..59a479f8ece4342bd2020a59c11ddaab02b7090d --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/unittest/utd_concurrent_update_test.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2025 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 "UtdConcurrentUpdateTest" +#include <gtest/gtest.h> + +#include <unistd.h> +#include <thread> + +#include "token_setproc.h" +#include "accesstoken_kit.h" +#include "nativetoken_kit.h" + +#include "logger.h" +#include "utd_client.h" +#include "type_descriptor.h" +#include "preset_type_descriptors.h" +#include "utd_graph.h" +#include "custom_utd_store.h" + +using namespace testing::ext; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; +using namespace OHOS; + +namespace OHOS::Test { +constexpr const int32_t USERID = 100; + +class UtdConcurrentUpdateTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + void SetNativeToken(const std::string &processName); +}; + +void UtdConcurrentUpdateTest::SetUpTestCase() +{ +} + +void UtdConcurrentUpdateTest::TearDownTestCase() +{ +} + +void UtdConcurrentUpdateTest::SetUp() +{ + SetNativeToken("foundation"); +} + +void UtdConcurrentUpdateTest::TearDown() +{ +} + +static constexpr const char *K_TEST_JSON_STR = R"({ + "UniformDataTypeDeclarations": [ + { + "TypeId": "com.example.thread.image", + "BelongingToTypes": ["general.image"], + "FilenameExtensions": [".myImage", ".khImage"], + "MIMETypes": ["application/myImage", "application/khImage"], + "Description": "My Image.", + "ReferenceURL": "" + }, + { + "TypeId": "com.example.thread.audio", + "BelongingToTypes": ["general.audio"], + "FilenameExtensions": [".myAudio", ".khAudio"], + "MIMETypes": ["application/myAudio", "application/khAudio"], + "Description": "My audio.", + "ReferenceURL": "" + } + ] +})"; + +void UtdConcurrentUpdateTest::SetNativeToken(const std::string &processName) +{ + auto tokenId = AccessTokenKit::GetNativeTokenId(processName); + SetSelfTokenID(tokenId); +} + +std::string ReplaceThread(const std::string& jsonStr, const std::string& newThreadId) +{ + std::string result = jsonStr; + std::string target = "com.example.thread"; + size_t pos = 0; + while ((pos = result.find(target, pos)) != std::string::npos) { + result.replace(pos, target.length(), newThreadId); + pos += newThreadId.length(); + } + return result; +} + +/** +* @tc.name: MultiThreadUpdate001 +* @tc.desc: MultiThread Update +* @tc.type: FUNC +*/ +HWTEST_F(UtdConcurrentUpdateTest, MultiThreadUpdate001, TestSize.Level1) +{ + const int numThreads = 8; + for (int i = 1; i <= numThreads; ++i) { + UtdClient::GetInstance().UninstallCustomUtds("com.example.thread" + std::to_string(i), USERID); + } + std::vector<TypeDescriptorCfg> prevCustomTypeCfgs = CustomUtdStore::GetInstance().GetCustomUtd(false, USERID); + size_t prevSize = prevCustomTypeCfgs.size(); + + const int trials = 50; + for (int i = 0; i < trials; ++i) { + bool op = (i % 2 == 0); + auto worker = [op](int threadId) { + const std::string bundleName = "com.example.thread" + std::to_string(threadId); + auto jsonStr = ReplaceThread(K_TEST_JSON_STR, bundleName); + if (op) { + UtdClient::GetInstance().InstallCustomUtds(bundleName, jsonStr, USERID); + LOG_INFO(UDMF_CLIENT, "Thread %{public}d Install done", threadId); + } else { + UtdClient::GetInstance().UninstallCustomUtds(bundleName, USERID); + LOG_INFO(UDMF_CLIENT, "Thread %{public}d Uninstall done", threadId); + } + }; + std::vector<std::thread> threads; + for (int j = 1; j <= numThreads; ++j) { + threads.emplace_back(worker, j); + } + for (auto &t : threads) { + t.join(); + } + + auto customTypeCfgs = CustomUtdStore::GetInstance().GetCustomUtd(false, USERID); + if (op) { + EXPECT_EQ(customTypeCfgs.size(), numThreads * 2 + prevSize); + } else { + EXPECT_EQ(customTypeCfgs.size(), prevSize); + } + for (const auto &cfg : customTypeCfgs) { + if (std::find(prevCustomTypeCfgs.begin(), prevCustomTypeCfgs.end(), cfg) == prevCustomTypeCfgs.end()) { + EXPECT_TRUE(cfg.typeId.find("com.example.thread") != std::string::npos); + EXPECT_TRUE(cfg.belongingToTypes.size() > 0); + EXPECT_TRUE(cfg.filenameExtensions.size() > 0); + EXPECT_TRUE(cfg.mimeTypes.size() > 0); + } + } + } + for (int i = 1; i <= numThreads; ++i) { + UtdClient::GetInstance().UninstallCustomUtds("com.example.thread" + std::to_string(i), USERID); + } + auto customTypeCfgs = CustomUtdStore::GetInstance().GetCustomUtd(false, USERID); + EXPECT_EQ(customTypeCfgs.size(), prevSize); +}; +} // namespace OHOS::Test \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/common/napi_data_utils.cpp b/udmf/framework/jskitsimpl/common/napi_data_utils.cpp index 7d7cf89d99dd765d7ae37d39a63a6c287c99a781..602888f957f2d74520dbeab0036676649d2d2128 100644 --- a/udmf/framework/jskitsimpl/common/napi_data_utils.cpp +++ b/udmf/framework/jskitsimpl/common/napi_data_utils.cpp @@ -55,6 +55,19 @@ napi_status NapiDataUtils::SetValue(napi_env env, const int32_t &in, napi_value return napi_create_int32(env, in, &out); } +/* napi_value <-> uint32_t */ +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, uint32_t &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> int32_t"); + return napi_get_value_uint32(env, in, &out); +} + +napi_status NapiDataUtils::SetValue(napi_env env, const uint32_t &in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- int32_t"); + return napi_create_uint32(env, in, &out); +} + /* napi_value <-> int64_t */ napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, int64_t &out) { @@ -278,6 +291,58 @@ napi_status NapiDataUtils::SetValue(napi_env env, const std::map<std::string, in return status; } +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::set<std::string> &out) +{ + napi_value global; + napi_value iterator; + napi_value values_fn; + napi_get_global(env, &global); + napi_get_named_property(env, in, "values", &values_fn); + napi_call_function(env, in, values_fn, 0, nullptr, &iterator); + + napi_value next_fn; + napi_value result_obj; + napi_value done_val; + napi_value value_val; + bool done = false; + + while (!done) { + napi_get_named_property(env, iterator, "next", &next_fn); + napi_call_function(env, iterator, next_fn, 0, nullptr, &result_obj); + + napi_get_named_property(env, result_obj, "done", &done_val); + napi_get_value_bool(env, done_val, &done); + if (done) break; + + napi_get_named_property(env, result_obj, "value", &value_val); + + size_t str_len; + napi_get_value_string_utf8(env, value_val, nullptr, 0, &str_len); + std::string str(str_len, '\0'); + napi_get_value_string_utf8(env, value_val, &str[0], str_len + 1, nullptr); + + out.insert(str); + } + return napi_ok; +} + +napi_status NapiDataUtils::SetValue(napi_env env, const std::set<std::string> &in, napi_value &out) +{ + std::vector<std::string> vec(in.begin(), in.end()); + napi_value jsArray; + NapiDataUtils::SetValue(env, vec, jsArray); + + napi_value global; + napi_get_global(env, &global); + + napi_value setConstructor; + napi_get_named_property(env, global, "Set", &setConstructor); + + napi_value argv[1] = { jsArray }; + napi_new_instance(env, setConstructor, 1, argv, &out); + return napi_ok; +} + /* napi_value <-> UDVariant */ napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, UDVariant &out) { @@ -594,6 +659,50 @@ napi_status NapiDataUtils::SetValue(napi_env env, const ProgressInfo &in, napi_v return napi_ok; } +napi_status NapiDataUtils::SetValue(napi_env env, const DataLoadInfo &in, napi_value &out) +{ + LOG_ERROR(UDMF_KITS_NAPI, "napi_value <- DataLoadInfo"); + napi_create_object(env, &out); + + napi_value jsRecordCount = nullptr; + NAPI_CALL_BASE(env, SetValue(env, in.recordCount, jsRecordCount), napi_invalid_arg); + NAPI_CALL_BASE(env, napi_set_named_property(env, out, "recordCount", jsRecordCount), napi_invalid_arg); + + napi_value jsTypes = nullptr; + NAPI_CALL_BASE(env, SetValue(env, in.types, jsTypes), napi_invalid_arg); + NAPI_CALL_BASE(env, napi_set_named_property(env, out, "types", jsTypes), napi_invalid_arg); + return napi_ok; +} + +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, DataLoadInfo &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> DataLoadInfo"); + napi_value jsTypes = nullptr; + NAPI_CALL_BASE(env, GetOptionalNamedProperty(env, in, "types", jsTypes), napi_invalid_arg); + if (jsTypes != nullptr) { + NAPI_CALL_BASE(env, NapiDataUtils::GetValue(env, jsTypes, out.types), napi_invalid_arg); + } + + out.recordCount = 0; + napi_value jsRecordCount = nullptr; + NAPI_CALL_BASE(env, GetOptionalNamedProperty(env, in, "recordCount", jsRecordCount), napi_invalid_arg); + if (jsRecordCount != nullptr) { + double count = 0; + NAPI_CALL_BASE(env, NapiDataUtils::GetValue(env, jsRecordCount, count), napi_invalid_arg); + if (!std::isfinite(count)) { + LOG_WARN(UDMF_KITS_NAPI, "recordCount is not a finite number"); + return napi_ok; + } + count = std::floor(count); + if (count < 0 || count > static_cast<double>(UINT32_MAX)) { + LOG_WARN(UDMF_KITS_NAPI, "recordCount out of range: %{public}f", count); + return napi_ok; + } + out.recordCount = static_cast<uint32_t>(count); + } + return napi_ok; +} + bool NapiDataUtils::IsTypeForNapiValue(napi_env env, napi_value param, napi_valuetype expectType) { napi_valuetype valueType = napi_undefined; @@ -675,5 +784,30 @@ napi_value NapiDataUtils::DefineClass(napi_env env, const std::string &name, } return constructor; } + +napi_status NapiDataUtils::GetOptionalNamedProperty(napi_env env, napi_value &obj, const std::string &key, + napi_value &napiValue) +{ + bool hasKey = false; + napi_status status = napi_has_named_property(env, obj, key.c_str(), &hasKey); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_has_named_property failed, name = %{public}s", key.c_str()); + return status; + } + if (!hasKey) { + napiValue = nullptr; + return napi_ok; + } + status = napi_get_named_property(env, obj, key.c_str(), &napiValue); + if (status != napi_ok || napiValue == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_get_named_property failed, name = %{public}s", key.c_str()); + return napi_generic_failure; + } + if (IsNull(env, napiValue)) { + napiValue = nullptr; + return napi_ok; + } + return napi_ok; +} } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/jskitsimpl/common/napi_error_utils.cpp b/udmf/framework/jskitsimpl/common/napi_error_utils.cpp index 8567babe91477aaf621ca5c03430e35a4bf755ca..e17b997e10939cdb2ef6f1543444e3ba3f7942ba 100644 --- a/udmf/framework/jskitsimpl/common/napi_error_utils.cpp +++ b/udmf/framework/jskitsimpl/common/napi_error_utils.cpp @@ -22,7 +22,8 @@ using NapiErrorCode = OHOS::UDMF::NapiErrorCode; static constexpr NapiErrorCode JS_ERROR_CODE_MSGS[] = { { Status::E_NO_PERMISSION, 201, "Permission denied!" }, { Status::E_INVALID_PARAMETERS, 401, "Parameter error." }, - { Status::E_SETTINGS_EXISTED, 20400001, "Settings already exist." }, + { Status::E_SETTINGS_EXISTED, 20400001, + "Settings already exist. To reconfigure, remove the existing sharing options." }, { Status::E_NO_SYSTEM_PERMISSION, 202, "Permission denied, application which is not a system application uses system API." }, }; diff --git a/udmf/framework/jskitsimpl/common/napi_queue.cpp b/udmf/framework/jskitsimpl/common/napi_queue.cpp index 898ba6d80823f95bdb850c54cd94969528d9e5a9..0263e92304a7796dbcfea37318f08389ee9f0501 100644 --- a/udmf/framework/jskitsimpl/common/napi_queue.cpp +++ b/udmf/framework/jskitsimpl/common/napi_queue.cpp @@ -66,8 +66,11 @@ void ContextBase::GetCbInfo(napi_env envi, napi_callback_info info, NapiCbInfoPa napi_value NapiQueue::AsyncWork(napi_env env, std::shared_ptr<ContextBase> contextBase, const std::string &name, NapiAsyncExecute execute, NapiAsyncComplete complete) { - LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork name = %{public}s", name.c_str()); - AsyncContext *aCtx = new AsyncContext; + AsyncContext *aCtx = new (std::nothrow) AsyncContext; + if (aCtx == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "aCtx is nullptr"); + return nullptr; + } aCtx->ctxt = std::move(contextBase); aCtx->execute = std::move(execute); aCtx->complete = std::move(complete); diff --git a/udmf/framework/jskitsimpl/data/data_load_params_napi.cpp b/udmf/framework/jskitsimpl/data/data_load_params_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f3d0c157b378fa66a7ce32fedb1b6509bc5828d2 --- /dev/null +++ b/udmf/framework/jskitsimpl/data/data_load_params_napi.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2025 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 "DataLoadParamsNapi" +#include "data_load_params_napi.h" + +#include "logger.h" +#include "napi_data_utils.h" +#include "unified_data_napi.h" +#include "udmf_client.h" +#include "udmf_utils.h" + +namespace OHOS { +namespace UDMF { +ConcurrentMap<std::string, napi_threadsafe_function> DataLoadParamsNapi::tsfns_; + +bool DataLoadParamsNapi::Convert2NativeValue(napi_env env, napi_value in, DataLoadParams &dataLoadParams) +{ + napi_value jsDataLoadInfo = nullptr; + NAPI_CALL_BASE(env, napi_get_named_property(env, in, "dataLoadInfo", &jsDataLoadInfo), false); + NAPI_CALL_BASE(env, NapiDataUtils::GetValue(env, jsDataLoadInfo, dataLoadParams.dataLoadInfo), false); + napi_value jsLoadHandler = nullptr; + NAPI_CALL_BASE(env, napi_get_named_property(env, in, "loadHandler", &jsLoadHandler), false); + dataLoadParams.dataLoadInfo.sequenceKey = UTILS::GenerateId(); + tsfns_.Compute(dataLoadParams.dataLoadInfo.sequenceKey, [&](const std::string &k, napi_threadsafe_function &tsfn) { + if (tsfn != nullptr) { + LOG_WARN(UDMF_KITS_NAPI, "Listener has existed!"); + napi_release_threadsafe_function(tsfn, napi_tsfn_release); + tsfn = nullptr; + } + napi_value workName; + napi_create_string_utf8(env, "threadsafe_function", NAPI_AUTO_LENGTH, &workName); + auto status = napi_create_threadsafe_function(env, jsLoadHandler, nullptr, workName, 0, 1, nullptr, + nullptr, nullptr, CallDataLoadHandler, &tsfn); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_create_threadsafe_function failed, status=%{public}d", status); + return false; + } + return true; + }); + dataLoadParams.loadHandler = [](const std::string &udKey, const DataLoadInfo &dataLoadInfo) { + LOG_INFO(UDMF_KITS_NAPI, "Load handler Start."); + auto seqKey = UTILS::GetSequenceKey(udKey); + if (seqKey.empty()) { + LOG_ERROR(UDMF_KITS_NAPI, "Error udKey:%{public}s", udKey.c_str()); + return; + } + bool tsfnExist = tsfns_.ComputeIfPresent(seqKey, [&](const std::string &key, napi_threadsafe_function &tsfn) { + DataLoadArgs *infoArgs = new (std::nothrow) DataLoadArgs; + if (infoArgs == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "No space for dataLoadArgs, udKey=%{public}s", udKey.c_str()); + return false; + } + infoArgs->udKey = udKey; + infoArgs->dataLoadInfo = dataLoadInfo; + auto status = napi_call_threadsafe_function(tsfn, infoArgs, napi_tsfn_blocking); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "call func failed,status=%{public}d,udKey=%{public}s", status, udKey.c_str()); + } + napi_release_threadsafe_function(tsfn, napi_tsfn_release); + return false; + }); + if (!tsfnExist) { LOG_ERROR(UDMF_KITS_NAPI, "Tsfn not exist, udKey=%{public}s", udKey.c_str()); } + }; + return true; +} + +void DataLoadParamsNapi::CallDataLoadHandler(napi_env env, napi_value callback, void *context, void *data) +{ + DataLoadArgs* infoArgs = static_cast<DataLoadArgs*>(data); + std::string udKey = infoArgs->udKey; + napi_value param; + auto status = NapiDataUtils::SetValue(env, infoArgs->dataLoadInfo, param); + delete infoArgs; + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "SetValue dataLoadInfo failed, status=%{public}d", status); + return; + } + napi_value result = nullptr; + status = napi_call_function(env, nullptr, callback, 1, &param, &result); + if (status != napi_ok || result == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_call_function failed, status=%{public}d", status); + return; + } + LOG_INFO(UDMF_KITS_NAPI, "Call napi_call_function end."); + napi_valuetype type = napi_undefined; + napi_typeof(env, result, &type); + if (type == napi_null) { + LOG_ERROR(UDMF_KITS_NAPI, "DataLoad has no data"); + return; + } + UnifiedDataNapi *unifiedDataNapi = nullptr; + status = napi_unwrap(env, result, reinterpret_cast<void **>(&unifiedDataNapi)); + if (status != napi_ok || unifiedDataNapi == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_unwrap data failed, status=%{public}d", status); + return; + } + + auto ret = UdmfClient::GetInstance().PushDelayData(udKey, *unifiedDataNapi->value_); + if (ret != E_OK) { + LOG_ERROR(UDMF_KITS_NAPI, "SetData failed, status=%{public}d", ret); + } +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/get_data_params_napi.cpp b/udmf/framework/jskitsimpl/data/get_data_params_napi.cpp index 43794a97e908a39d32bdb283c8e8d64b65dc9593..288442a869c676200c714bce5570380aa39478e3 100644 --- a/udmf/framework/jskitsimpl/data/get_data_params_napi.cpp +++ b/udmf/framework/jskitsimpl/data/get_data_params_napi.cpp @@ -65,6 +65,13 @@ bool GetDataParamsNapi::Convert2NativeValue(napi_env env, napi_value in, getDataParams.fileConflictOptions = static_cast<FileConflictOptions>(fileConflictOptions); } + bool hasAcceptableInfo = false; + NAPI_CALL_BASE(env, napi_has_named_property(env, in, "acceptableInfo", &hasAcceptableInfo), false); + if (hasAcceptableInfo) { + napi_value jsDataLoadInfo = nullptr; + NAPI_CALL_BASE(env, napi_get_named_property(env, in, "acceptableInfo", &jsDataLoadInfo), false); + NAPI_CALL_BASE(env, NapiDataUtils::GetValue(env, jsDataLoadInfo, getDataParams.acceptableInfo), false); + } return true; } diff --git a/udmf/framework/jskitsimpl/data/unified_data_channel_napi.cpp b/udmf/framework/jskitsimpl/data/unified_data_channel_napi.cpp index d01cfbaeb7df9fbacaa284431a71f6a7dcef9c15..b3e6bef17939f28a4f17dc671cf45458d171e6ac 100644 --- a/udmf/framework/jskitsimpl/data/unified_data_channel_napi.cpp +++ b/udmf/framework/jskitsimpl/data/unified_data_channel_napi.cpp @@ -32,12 +32,14 @@ napi_value UnifiedDataChannelNapi::UnifiedDataChannelInit(napi_env env, napi_val DECLARE_NAPI_FUNCTION("updateData", UpdateData), DECLARE_NAPI_FUNCTION("queryData", QueryData), DECLARE_NAPI_FUNCTION("deleteData", DeleteData), + DECLARE_NAPI_FUNCTION("convertRecordsToEntries", ConvertRecordsToEntries), DECLARE_NAPI_GETTER("ShareOptions", CreateShareOptions), DECLARE_NAPI_FUNCTION("setAppShareOptions", SetAppShareOptions), DECLARE_NAPI_FUNCTION("removeAppShareOptions", RemoveAppShareOptions), DECLARE_NAPI_GETTER("FileConflictOptions", CreateFileConflictOptions), DECLARE_NAPI_GETTER("ProgressIndicator", CreateProgressIndicator), DECLARE_NAPI_GETTER("ListenerStatus", CreateListenerStatus), + DECLARE_NAPI_GETTER("Visibility", CreateVisibility), }; NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); @@ -56,10 +58,31 @@ napi_value UnifiedDataChannelNapi::CreateIntention(napi_env env) UD_INTENTION_MAP.at(UD_INTENTION_DATA_HUB)); SetNamedProperty(env, intention, JS_UD_INTENTION_NAME_MAP.at(UD_INTENTION_DRAG), UD_SYSTEM_INTENTION_MAP.at(UD_INTENTION_DRAG)); + SetNamedProperty(env, intention, JS_UD_INTENTION_NAME_MAP.at(UD_INTENTION_PICKER), + UD_INTENTION_MAP.at(UD_INTENTION_PICKER)); + SetNamedProperty(env, intention, JS_UD_INTENTION_NAME_MAP.at(UD_INTENTION_SYSTEM_SHARE), + UD_INTENTION_MAP.at(UD_INTENTION_SYSTEM_SHARE)); + SetNamedProperty(env, intention, JS_UD_INTENTION_NAME_MAP.at(UD_INTENTION_MENU), + UD_INTENTION_MAP.at(UD_INTENTION_MENU)); napi_object_freeze(env, intention); return intention; } +napi_value UnifiedDataChannelNapi::CreateVisibility(napi_env env, napi_callback_info info) +{ + napi_value jsVisibility = nullptr; + napi_create_object(env, &jsVisibility); + + napi_value jsALL; + NapiDataUtils::SetValue(env, static_cast<int32_t>(Visibility::VISIBILITY_ALL), jsALL); + NAPI_CALL(env, napi_set_named_property(env, jsVisibility, "ALL", jsALL)); + + napi_value jsOwnProcess; + NapiDataUtils::SetValue(env, static_cast<int32_t>(Visibility::VISIBILITY_OWN_PROCESS), jsOwnProcess); + NAPI_CALL(env, napi_set_named_property(env, jsVisibility, "OWN_PROCESS", jsOwnProcess)); + return jsVisibility; +} + napi_status UnifiedDataChannelNapi::SetNamedProperty(napi_env env, napi_value &obj, const std::string &name, const std::string &value) { @@ -78,29 +101,35 @@ napi_value UnifiedDataChannelNapi::InsertData(napi_env env, napi_callback_info i std::string key; Intention intention; std::shared_ptr<UnifiedData> unifiedData; + Visibility visibility; }; std::string intention; UnifiedDataNapi *unifiedDataNapi = nullptr; + int32_t visibility = static_cast<int32_t>(Visibility::VISIBILITY_ALL); auto ctxt = std::make_shared<InsertContext>(); - auto input = [env, ctxt, &intention, &unifiedDataNapi](size_t argc, napi_value *argv) { + auto input = [env, ctxt, &intention, &unifiedDataNapi, &visibility](size_t argc, napi_value *argv) { // require 2 arguments <options, unifiedData> ASSERT_BUSINESS_ERR(ctxt, argc >= 2, E_INVALID_PARAMETERS, "Parameter error: Mandatory parameters are left unspecified"); ctxt->status = GetNamedProperty(env, argv[0], "intention", intention); - ASSERT_BUSINESS_ERR(ctxt, UnifiedDataUtils::GetIntentionByString(intention) != UD_INTENTION_DRAG, - E_INVALID_PARAMETERS, "Parameter error: The intention parameter is invalid"); - ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok && UnifiedDataUtils::IsPersist(intention), + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok && + (UnifiedDataUtils::IsPersist(intention)), E_INVALID_PARAMETERS, "Parameter error: parameter options intention type must correspond to Intention"); ctxt->status = napi_unwrap(env, argv[1], reinterpret_cast<void **>(&unifiedDataNapi)); ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS, "Parameter error: parameter data type must be UnifiedData"); + ctxt->status = GetOptionalProperty(env, argv[0], "visibility", visibility); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok && + (UnifiedDataUtils::IsPersist(visibility)), + E_INVALID_PARAMETERS, "Parameter error: parameter options visibility type must correspond to Visibility"); }; ctxt->GetCbInfo(env, info, input); ASSERT_NULL(!ctxt->isThrowError, "Insert Exit"); ctxt->unifiedData = unifiedDataNapi->value_; ctxt->intention = UnifiedDataUtils::GetIntentionByString(intention); + ctxt->visibility = static_cast<Visibility>(visibility); auto execute = [ctxt]() { - CustomOption option = { .intention = ctxt->intention }; + CustomOption option = { .intention = ctxt->intention, .visibility = ctxt->visibility }; auto status = UdmfClient::GetInstance().SetData(option, *(ctxt->unifiedData), ctxt->key); ASSERT_WITH_ERRCODE(ctxt, status == E_OK, status, "InsertData failed!"); }; @@ -129,7 +158,8 @@ napi_value UnifiedDataChannelNapi::UpdateData(napi_env env, napi_callback_info i ctxt->status = GetNamedProperty(env, argv[0], "key", ctxt->key); UnifiedKey key(ctxt->key); ASSERT_BUSINESS_ERR(ctxt, - ctxt->status == napi_ok && key.IsValid() && UnifiedDataUtils::IsPersist(key.intention), + ctxt->status == napi_ok && key.IsValid() && + (key.intention == UD_INTENTION_MAP.at(Intention::UD_INTENTION_DATA_HUB)), E_INVALID_PARAMETERS, "Parameter error: parameter options intention type must correspond to Intention"); ctxt->status = napi_unwrap(env, argv[1], reinterpret_cast<void **>(&unifiedDataNapi)); ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS, @@ -168,15 +198,17 @@ napi_value UnifiedDataChannelNapi::QueryData(napi_env env, napi_callback_info in auto options = argv[0]; keyStatus = GetNamedProperty(env, options, "key", ctxt->key); intentionStatus = GetNamedProperty(env, options, "intention", intention); - ASSERT_BUSINESS_ERR(ctxt, UnifiedDataUtils::GetIntentionByString(intention) != UD_INTENTION_DRAG, - E_INVALID_PARAMETERS, "Parameter error: The intention parameter is invalid"); + UnifiedKey key(ctxt->key); ASSERT_BUSINESS_ERR(ctxt, (keyStatus == napi_ok || intentionStatus == napi_ok) && - UnifiedDataUtils::IsValidOptions(ctxt->key, intention), + IsValidOptionInfoNonDrag(key, intention), E_INVALID_PARAMETERS, "Parameter error: parameter options intention type must correspond to Intention"); }; ctxt->GetCbInfo(env, info, input); ASSERT_NULL(!ctxt->isThrowError, "Query Exit"); - ctxt->intention = UnifiedDataUtils::GetIntentionByString(intention); + Intention tempIntention = UnifiedDataUtils::GetIntentionByString(intention); + if (tempIntention != UD_INTENTION_BUTT) { + ctxt->intention = tempIntention; + } auto execute = [env, ctxt]() { QueryOption option = { .key = ctxt->key, @@ -212,17 +244,18 @@ napi_value UnifiedDataChannelNapi::DeleteData(napi_env env, napi_callback_info i napi_value options = argv[0]; keyStatus = GetNamedProperty(env, options, "key", ctxt->key); intentionStatus = GetNamedProperty(env, options, "intention", intention); - ASSERT_BUSINESS_ERR(ctxt, intention.empty() || - UnifiedDataUtils::GetIntentionByString(intention) == UD_INTENTION_DATA_HUB, - E_INVALID_PARAMETERS, "Parameter error: The intention parameter is invalid"); + UnifiedKey key(ctxt->key); ASSERT_BUSINESS_ERR(ctxt, (keyStatus == napi_ok || intentionStatus == napi_ok) && - UnifiedDataUtils::IsValidOptions(ctxt->key, intention), + (IsValidOptionInfoNonDrag(key, intention)), E_INVALID_PARAMETERS, "Parameter error: parameter options intention type must correspond to Intention"); }; ctxt->GetCbInfo(env, info, input); ASSERT_NULL(!ctxt->isThrowError, "Delete Exit"); - ctxt->intention = UnifiedDataUtils::GetIntentionByString(intention); + Intention tempIntention = UnifiedDataUtils::GetIntentionByString(intention); + if (tempIntention != UD_INTENTION_BUTT) { + ctxt->intention = tempIntention; + } auto execute = [env, ctxt]() { QueryOption option = { .key = ctxt->key, @@ -239,6 +272,28 @@ napi_value UnifiedDataChannelNapi::DeleteData(napi_env env, napi_callback_info i return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); } +napi_value UnifiedDataChannelNapi::ConvertRecordsToEntries(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ConvertRecordsToEntries is called!"); + struct ConvertContext : public ContextBase { + std::shared_ptr<UnifiedData> unifiedData; + }; + UnifiedDataNapi *unifiedDataNapi = nullptr; + auto ctxt = std::make_shared<ConvertContext>(); + auto input = [env, ctxt, &unifiedDataNapi](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc == 1, + E_INVALID_PARAMETERS, "Parameter error: Mandatory parameters are left unspecified"); + ctxt->status = napi_unwrap(env, argv[0], reinterpret_cast<void **>(&unifiedDataNapi)); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS, + "Parameter error: parameter data type must be UnifiedData"); + }; + ctxt->GetCbInfo(env, info, input); + ASSERT_NULL(!ctxt->isThrowError, "ConvertRecordsToEntries Exit"); + ctxt->unifiedData = unifiedDataNapi->value_; + ctxt->unifiedData->ConvertRecordsToEntries(); + return nullptr; +} + napi_status UnifiedDataChannelNapi::GetNamedProperty(napi_env env, napi_value &obj, const std::string &key, std::string &value) { @@ -271,6 +326,36 @@ napi_status UnifiedDataChannelNapi::GetNamedProperty(napi_env env, napi_value &o return status; } +napi_status UnifiedDataChannelNapi::GetOptionalProperty(napi_env env, napi_value &obj, const std::string &key, + int32_t &value) +{ + bool hasKey = false; + napi_status status = napi_has_named_property(env, obj, key.c_str(), &hasKey); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_has_named_property failed, name = %{public}s", key.c_str()); + return napi_generic_failure; + } + if (!hasKey) { + return napi_ok; + } + napi_value napiValue = nullptr; + status = napi_get_named_property(env, obj, key.c_str(), &napiValue); + if (status != napi_ok || napiValue == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_get_named_property failed, name = %{public}s", key.c_str()); + return napi_generic_failure; + } + if (NapiDataUtils::IsNull(env, napiValue)) { + LOG_ERROR(UDMF_KITS_NAPI, "The property value is null, name = %{public}s", key.c_str()); + return napi_generic_failure; + } + status = NapiDataUtils::GetValue(env, napiValue, value); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "NapiDataUtils::GetValue failed, name = %{public}s", key.c_str()); + return status; + } + return status; +} + napi_value UnifiedDataChannelNapi::CreateShareOptions(napi_env env, napi_callback_info info) { napi_value jsShareOptions = nullptr; @@ -313,7 +398,8 @@ napi_value UnifiedDataChannelNapi::SetAppShareOptions(napi_env env, napi_callbac E_INVALID_PARAMETERS, "Parameter error: The shareOptions parameter is invalid!"); std::transform(intention.begin(), intention.end(), intention.begin(), ::tolower); // js : Drag --> drag status = UdmfClient::GetInstance().SetAppShareOption(intention, static_cast<ShareOptions>(shareOptionValue)); - ASSERT_BUSINESS_ERR_VOID(ctxt, !(status == E_SETTINGS_EXISTED), E_SETTINGS_EXISTED, "Settings already exist!"); + ASSERT_BUSINESS_ERR_VOID(ctxt, !(status == E_SETTINGS_EXISTED), E_SETTINGS_EXISTED, + "Settings already exist. To reconfigure, remove the existing sharing options."); ASSERT_BUSINESS_ERR_VOID(ctxt, status != E_NO_PERMISSION, E_NO_PERMISSION, "Permission denied!"); ASSERT_ERR(ctxt->env, status == E_OK, status, "invalid arguments!"); return nullptr; @@ -429,5 +515,13 @@ napi_value UnifiedDataChannelNapi::CreateListenerStatus(napi_env env, napi_callb NAPI_CALL(env, napi_set_named_property(env, jsListenerStatus, "COPY_FILE_FAILED", jsCopyFail)); return jsListenerStatus; } + +bool UnifiedDataChannelNapi::IsValidOptionInfoNonDrag(UnifiedKey &key, const std::string &intention) +{ + if (UnifiedDataUtils::IsValidOptions(key, intention)) { + return !key.key.empty() || intention == UD_INTENTION_MAP.at(Intention::UD_INTENTION_DATA_HUB); + } + return false; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/unified_data_napi.cpp b/udmf/framework/jskitsimpl/data/unified_data_napi.cpp index 38714dbe854d9b0cb049aa0b466e8c939806443f..214036bc1510c35773378584fbfe48a927bb3650 100644 --- a/udmf/framework/jskitsimpl/data/unified_data_napi.cpp +++ b/udmf/framework/jskitsimpl/data/unified_data_napi.cpp @@ -88,10 +88,89 @@ napi_value UnifiedDataNapi::New(napi_env env, napi_callback_info info) if (uRecord) { uData->value_->AddRecord(uRecord->value_); } + auto status = napi_coerce_to_native_binding_object( + env, ctxt->self, DetachUnifiedData, AttachUnifiedData, uData, nullptr); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_coerce_to_native_binding_object failed!"); + } ASSERT_CALL(env, napi_wrap(env, ctxt->self, uData, Destructor, nullptr, nullptr), uData); return ctxt->self; } +napi_value UnifiedDataNapi::AttachUnifiedData(napi_env env, void *value, void *) +{ + if (value == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "Invalid value."); + return nullptr; + } + auto *data = static_cast<UnifiedDataNapi *>(value); + napi_value jsData = nullptr; + auto status = napi_create_object(env, &jsData); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_create_object failed!"); + delete data; + return nullptr; + } + napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("addRecord", AddRecord), + DECLARE_NAPI_FUNCTION("getRecords", GetRecords), + DECLARE_NAPI_FUNCTION("hasType", HasType), + DECLARE_NAPI_FUNCTION("getTypes", GetTypes), + DECLARE_NAPI_GETTER_SETTER("properties", GetProperties, SetProperties), + }; + status = napi_define_properties(env, jsData, sizeof(properties) / sizeof(properties[0]), properties); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_define_properties failed!"); + delete data; + return nullptr; + } + status = napi_coerce_to_native_binding_object( + env, jsData, DetachUnifiedData, AttachUnifiedData, value, nullptr); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_coerce_to_native_binding_object failed!"); + delete data; + return nullptr; + } + status = napi_wrap(env, jsData, value, Destructor, nullptr, nullptr); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_wrap failed!"); + delete data; + return nullptr; + } + return jsData; +} + +void* UnifiedDataNapi::DetachUnifiedData(napi_env env, void *value, void *) +{ + if (value == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "Invalid value."); + return nullptr; + } + auto *origin = static_cast<UnifiedDataNapi *>(value); + auto result = new (std::nothrow) UnifiedDataNapi(); + if (result == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "Memory allocation failed."); + return nullptr; + } + result->value_ = origin->value_; + + int argc = 0; + napi_value argv[0] = {}; + UnifiedDataPropertiesNapi* propertiesNapi = nullptr; + result->propertyRef_ = NewWithRef(env, argc, argv, reinterpret_cast<void **>(&propertiesNapi), + UnifiedDataPropertiesNapi::Constructor(env)); + if (propertiesNapi == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "new UnifiedDataPropertiesNapi failed!"); + if (result->propertyRef_ != nullptr) { + napi_delete_reference(env, result->propertyRef_); + } + delete result; + return nullptr; + } + propertiesNapi->value_ = origin->value_->GetProperties(); + return result; +} + void UnifiedDataNapi::Destructor(napi_env env, void *data, void *hint) { LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi finalize."); @@ -107,10 +186,28 @@ napi_status UnifiedDataNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedDa { LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi"); ASSERT_CALL_STATUS(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); - auto *unifiedData = new (std::nothrow) UnifiedDataNapi(); - ASSERT_ERR_STATUS(env, unifiedData != nullptr, Status::E_ERROR, "no memory for unified data!"); + + UnifiedDataNapi* unifiedData = nullptr; + napi_status status = napi_unwrap(env, out, reinterpret_cast<void **>(&unifiedData)); + if (status != napi_ok || unifiedData == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_unwrap unifiedData failed, status=%{public}d", status); + return status; + } unifiedData->value_ = in; - ASSERT_CALL_DELETE_STATUS(env, napi_wrap(env, out, unifiedData, Destructor, nullptr, nullptr), unifiedData); + + napi_value value; + status = napi_get_reference_value(env, unifiedData->propertyRef_, &value); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_get_reference_value propertyRef failed, status=%{public}d", status); + return status; + } + UnifiedDataPropertiesNapi* propertiesNapi = nullptr; + status = napi_unwrap(env, value, reinterpret_cast<void **>(&propertiesNapi)); + if (status != napi_ok || propertiesNapi == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_unwrap propertiesNapi failed, status=%{public}d", status); + return status; + } + propertiesNapi->value_ = in->GetProperties(); return napi_ok; } diff --git a/udmf/framework/jskitsimpl/intelligence/aip_napi_error.cpp b/udmf/framework/jskitsimpl/intelligence/aip_napi_error.cpp index 9cdf24ba37e305dee20abb515051d05274fdb7dc..faa611da947f9a4ce61bfa4f5b7328af6fdc5246 100644 --- a/udmf/framework/jskitsimpl/intelligence/aip_napi_error.cpp +++ b/udmf/framework/jskitsimpl/intelligence/aip_napi_error.cpp @@ -34,12 +34,13 @@ constexpr ErrCodeMapping NATIVE_ERR_CODE2TS_ERR_CODE[] = { { NATIVE_DATABASE_ALREADY_CLOSED, DATABASE_ALREADY_CLOSED }, { NATIVE_DATABASE_IS_BUSY, DATABASE_IS_BUSY }, { NATIVE_DATABASE_WAL_FILE_EXCEEDS_LIMIT, DATABASE_WAL_FILE_EXCEEDS_LIMIT }, - { NATIVE_DATABASE_GENERIC_ERROD, DATABASE_GENERIC_ERROD }, + { NATIVE_DATABASE_GENERIC_ERROR, DATABASE_GENERIC_ERROR }, { NATIVE_DATABASE_CORRUPTED, DATABASE_CORRUPTED }, { NATIVE_DATABASE_PERMISSION_DENIED, DATABASE_PERMISSION_DENIED }, { NATIVE_DATABASE_FILE_IS_LOCKED, DATABASE_FILE_IS_LOCKED }, { NATIVE_DATABASE_OUT_OF_MEMORY, DATABASE_OUT_OF_MEMORY }, { NATIVE_DATABASE_IO_ERROR, DATABASE_IO_ERROR }, + { NATIVE_E_RECALL_FAILURE, RETRIEVAL_E_RECALL_FAILURE }, { NATIVE_E_RERANK_FAILURE, RETRIEVAL_E_RERANK_FAILURE }, { NATIVE_E_INVALID_NUMBER, RETRIEVAL_E_INVALID_NUMBER }, @@ -50,7 +51,32 @@ constexpr ErrCodeMapping NATIVE_ERR_CODE2TS_ERR_CODE[] = { { NATIVE_E_INVALID_RECALL_FIELD, RETRIEVAL_E_INVALID_RECALL_FIELD }, { NATIVE_E_HIGH_VECTOR_SIMILARITY_THRESHOLD, RETRIEVAL_E_HIGH_VECTOR_SIMILARITY_THRESHOLD }, { NATIVE_E_RERANK_METHOD_MISMATCH, RETRIEVAL_E_RERANK_METHOD_MISMATCH }, - { NATIVE_E_EMPTY_PARAMETER, RETRIEVAL_E_EMPTY_PARAMETER } + { NATIVE_E_EMPTY_PARAMETER, RETRIEVAL_E_EMPTY_PARAMETER }, + + { NATIVE_SUMMARY_E_INVALID_PARAMETERS, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_SUMMARY_E_INVALID_RESULT, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_SUMMARY_E_INVALID_OUTPUT, RAG_E_RAG_COMMON_ERROR }, + + { NATIVE_RAG_E_CONFIG_ERROR, PARAM_EXCEPTION }, + { NATIVE_RAG_E_INSTANCE_EXIST, RAG_E_RAG_ALREADY_EXISTS }, + { NATIVE_RAG_E_INVALID_INPUT, PARAM_EXCEPTION }, + { NATIVE_RAG_E_QUERY_LENGTH_EXCEED, PARAM_EXCEPTION }, + { NATIVE_RAG_E_STREAM_BUSY, RAG_E_RAG_BUSY }, + { NATIVE_RAG_E_INSTANCE_NOT_EXIST, RAG_E_RAG_ALREADY_CLOSED }, + { NATIVE_RAG_E_PROMPT_ERROR, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_RAG_E_LLM_ERROR, RAG_E_LLM_LOAD_FAILED }, + { NATIVE_RAG_E_LLM_OCCUPIED, RAG_E_LLM_BUSY }, + { NATIVE_RAG_E_LLM_TIMEOUT, RAG_E_LLM_TIMEOUT }, + { NATIVE_RAG_E_LLM_OUTPUT_INVALID, RAG_E_LLM_OUTPUT_INVALID }, + { NATIVE_RAG_E_RETRIEVER_TIMEOUT, RAG_E_RAG_TIMEOUT }, + + { NATIVE_LLM_E_PARSER_JSON_PARSE, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_LLM_E_PARSER_JSON_MEMBER, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_LLM_E_REQUEST_MALLOC, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_PROMPT_E_PLACEHOLDER_JSON_PARSE, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_PROMPT_E_CHAT_TEMP_JSON_TYPE, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_PROMPT_E_CHAT_TEMP_EMPTY_MSG, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_PROMPT_E_CHAT_TEMP_UPDATE_SYS, RAG_E_RAG_COMMON_ERROR }, }; struct ErrMessage { @@ -66,7 +92,7 @@ constexpr ErrMessage ERROR_MESSAGES [] = { { DATABASE_ALREADY_CLOSED, "Already closed." }, { DATABASE_IS_BUSY, "The database is busy." }, { DATABASE_OUT_OF_MEMORY, "The database is out of memory." }, - { DATABASE_GENERIC_ERROD, "SQLite: Generic error." }, + { DATABASE_GENERIC_ERROR, "SQLite: Generic error." }, { DATABASE_PERMISSION_DENIED, "SQLite: Access permission denied." }, { DATABASE_FILE_IS_LOCKED, "SQLite: The database file is locked." }, { DATABASE_IO_ERROR, "SQLite: Some kind of disk I/O error occurred." }, @@ -86,7 +112,17 @@ constexpr ErrMessage ERROR_MESSAGES [] = { "higher than the tiered threshold in VectorRerankParameter." }, { RETRIEVAL_E_RERANK_METHOD_MISMATCH, "Retrieval: RerankMethod parameters do not match the channel type." }, { RETRIEVAL_E_EMPTY_PARAMETER, - "Retrieval: There exists a parameter value that should not be empty but is actually empty." } + "Retrieval: There exists a parameter value that should not be empty but is actually empty." }, + { RAG_E_RAG_COMMON_ERROR, "Inner error." }, + { RAG_E_LLM_TIMEOUT, "A timeout occurred when calling the LLM." }, + { RAG_E_LLM_LOAD_FAILED, "A loading failure occurred when calling the LLM." }, + { RAG_E_LLM_BUSY, "The LLM chat is busy." }, + { RAG_E_LLM_OUTPUT_INVALID, "The output of LLM chat is invalid." }, + { RAG_E_RAG_ALREADY_EXISTS, "The RAG session is already exists." }, + { RAG_E_RAG_BUSY, "The RAG session is busy." }, + { RAG_E_RAG_ALREADY_CLOSED, "Already closed." }, + { RAG_E_RAG_USER_CANCEL, "User has canceled the stream run." }, + { RAG_E_RAG_TIMEOUT, "A timeout occurred in the session." }, }; int32_t ConvertErrCodeNative2Ts(int32_t nativeErrCode) @@ -103,7 +139,7 @@ int32_t ConvertErrCodeNative2Ts(int32_t nativeErrCode) right = mid - 1; } } - return DATABASE_GENERIC_ERROD; + return DATABASE_GENERIC_ERROR; } diff --git a/udmf/framework/jskitsimpl/intelligence/aip_napi_utils.cpp b/udmf/framework/jskitsimpl/intelligence/aip_napi_utils.cpp index e46bbbc6edc807bed1cf0e558cdaae234e37f2ac..ef1ec834817745fa86aca1e9ac9610a0ef561299 100644 --- a/udmf/framework/jskitsimpl/intelligence/aip_napi_utils.cpp +++ b/udmf/framework/jskitsimpl/intelligence/aip_napi_utils.cpp @@ -15,12 +15,15 @@ #include "aip_napi_utils.h" +#include <charconv> #include <dlfcn.h> +#include <memory> #include "js_ability.h" #include "aip_log.h" #include "hilog/log_c.h" #include "js_native_api_types.h" +#include "rag_chatllm_impl.h" #undef LOG_TAG #define LOG_TAG "AipNapiUtils" @@ -706,7 +709,7 @@ napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, Reca if (isFiltersPresent) { napi_value filtersNapi; napi_get_named_property(env, in, "filters", &filtersNapi); - napi_status status = AipNapiUtils::Convert2Value(env, filtersNapi, out.filters); + status = AipNapiUtils::Convert2Value(env, filtersNapi, out.filters); LOG_ERROR_RETURN(status == napi_ok, "Failed to convert the field filter.", napi_invalid_arg); } return napi_ok; @@ -862,6 +865,47 @@ napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, Inve return napi_ok; } +napi_status AipNapiUtils::Convert2Value(napi_env env, napi_value in, napi_ref &out) +{ + napi_status status = napi_create_reference(env, in, 1, &out); + if (status != napi_ok) { + AIP_HILOGE("Failed to convert the chat2."); + } + return status; +} + +napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, std::shared_ptr<IChatLLM> &out) +{ + napi_value streamChatNapi; + napi_ref streamChatRef = nullptr; + napi_status status = napi_get_named_property(env, in, "streamChat", &streamChatNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to get the field streamChat.", napi_invalid_arg); + + status = Convert2Value(env, streamChatNapi, streamChatRef); + if (status != napi_ok) { + AIP_HILOGW("Failed to convert the streamChat."); + return napi_ok; + } + out = std::make_shared<ChatLLM>(env, streamChatRef); + return napi_ok; +} + +napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, LLMStreamAnswer &out) +{ + napi_value isFinishedNapi; + napi_status status = napi_get_named_property(env, in, "isFinished", &isFinishedNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to get the field isFinished.", napi_invalid_arg); + status = Convert2Value(env, isFinishedNapi, out.isFinished); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert the field isFinished.", napi_invalid_arg); + + napi_value chunkNapi; + status = napi_get_named_property(env, in, "chunk", &chunkNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to get the field chunk.", napi_invalid_arg); + status = Convert2Value(env, chunkNapi, out.chunk); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert the field chunk.", napi_invalid_arg); + return napi_ok; +} + static napi_status ConvertRerankChannelParams(napi_env env, const napi_value &in, RerankParamsStruct &out) { napi_value parametersNapi; @@ -878,12 +922,12 @@ static napi_status ConvertRerankChannelParams(napi_env env, const napi_value &in std::string keyStr; status = AipNapiUtils::Convert2Value(env, keyNapi, keyStr); LOG_ERROR_RETURN(status == napi_ok, "Failed to convert the channelType in parameters.", napi_invalid_arg); - int32_t keyInt = std::stoi(keyStr); - LOG_ERROR_RETURN(keyInt >= TsChannelType::VECTOR_DATABASE && keyInt <= TsChannelType::INVERTED_INDEX_DATABASE, - "channelType is ileagl.", napi_invalid_arg); + int32_t keyInt; + auto result = std::from_chars(keyStr.data(), keyStr.data() + keyStr.size(), keyInt); + LOG_ERROR_RETURN(result.ec == std::errc() && keyInt >= TsChannelType::VECTOR_DATABASE && + keyInt <= TsChannelType::INVERTED_INDEX_DATABASE, "channelType is ileagl.", napi_invalid_arg); napi_value valueNapi; napi_get_property(env, parametersNapi, keyNapi, &valueNapi); - std::shared_ptr<ChannelRerankParamsStruct> channelParams; bool isVectorWeightsPresent = false; napi_has_named_property(env, valueNapi, "vectorWeights", &isVectorWeightsPresent); if (isVectorWeightsPresent) { @@ -1033,6 +1077,7 @@ napi_status GetCurrentAbilityParam(napi_env env, napi_value in, ContextParam &pa param.area = context->GetArea(); param.bundleName = context->GetBundleName(); param.isSystemApp = context->IsSystemAppCalled(); + param.cacheDir = context->GetCacheDir(); return napi_ok; } @@ -1053,6 +1098,10 @@ napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, Cont AIP_HILOGD("Stage mode branch"); status = GetNamedProperty(env, in, "databaseDir", context.baseDir); LOG_ERROR_RETURN(status == napi_ok, "get databaseDir failed.", napi_invalid_arg); + + status = GetNamedProperty(env, in, "cacheDir", context.cacheDir); + LOG_ERROR_RETURN(status == napi_ok, "get cacheDir failed.", napi_invalid_arg); + status = GetNamedProperty(env, in, "area", context.area, true); LOG_ERROR_RETURN(status == napi_ok, "get area failed.", napi_invalid_arg); @@ -1151,6 +1200,42 @@ napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, napi return napi_ok; } +napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, OptionStruct &out) +{ + napi_value answerWithRetrievalItemNapi; + napi_status status = napi_get_named_property(env, in, "answerWithRetrievalItem", &answerWithRetrievalItemNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to get the field answerWithRetrievalItem.", napi_invalid_arg); + + status = Convert2Value(env, answerWithRetrievalItemNapi, out.answerWithRetrievalItem); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert the field answerWithRetrievalItem.", napi_invalid_arg); + return napi_ok; +} + +napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, ConfigStruct &out) +{ + napi_value llmNapi; + napi_status status = napi_get_named_property(env, in, "llm", &llmNapi); + if (status == napi_ok) { + status = Convert2Value(env, llmNapi, out.chatLLM); + if (status != napi_ok) { + AIP_HILOGW("Failed to convert the field llm. status: %{public}d", status); + } + } + napi_value retrieverNapi; + status = napi_get_named_property(env, in, "retrievalConfig", &retrieverNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to get the field retrievalConfig.", napi_invalid_arg); + status = Convert2Value(env, retrieverNapi, out.retriever); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert the field retriever.", napi_invalid_arg); + napi_value conditionNapi; + status = napi_get_named_property(env, in, "retrievalCondition", &conditionNapi); + if (status == napi_ok) { + status = Convert2Value(env, conditionNapi, out.condition); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert the field condition.", napi_invalid_arg); + } + + return napi_ok; +} + napi_status AipNapiUtils::Convert2JSValue(napi_env env, const std::vector<uint8_t> &in, napi_value &out) { void *native = nullptr; @@ -1260,6 +1345,49 @@ napi_status AipNapiUtils::Convert2JSValue(napi_env env, const DataIntelligence:: return napi_ok; } +napi_status AipNapiUtils::Convert2JSValue(napi_env env, const AnswerStruct &in, napi_value &out) +{ + napi_status status = napi_create_object(env, &out); + LOG_ERROR_RETURN(status == napi_ok, "Failed to create napi object of AnswerStruct.", napi_invalid_arg); + + napi_value answerStr = nullptr; + status = Convert2JSValue(env, in.chunk, answerStr); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert chunk to napi_value.", napi_invalid_arg); + + status = napi_set_named_property(env, out, "chunk", answerStr); + LOG_ERROR_RETURN(status == napi_ok, "Failed to set chunk to object of AnswerStruct.", napi_invalid_arg); + + napi_value data = nullptr; + status = Convert2JSValue(env, in.data, data); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert data to napi_value.", napi_invalid_arg); + + status = napi_set_named_property(env, out, "data", data); + LOG_ERROR_RETURN(status == napi_ok, "Failed to set data to object of AnswerStruct.", napi_invalid_arg); + + return napi_ok; +} + +napi_status AipNapiUtils::Convert2JSValue(napi_env env, const StreamStruct &in, napi_value &out) +{ + napi_status status = napi_create_object(env, &out); + LOG_ERROR_RETURN(status == napi_ok, "Failed to get create napi object of StreamStruct.", napi_invalid_arg); + + napi_value isFinishedNapi; + status = Convert2JSValue(env, in.isFinished, isFinishedNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert isFinished to napi_value.", napi_invalid_arg); + + status = napi_set_named_property(env, out, "isFinished", isFinishedNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to set isFinished to object of StreamStruct.", napi_invalid_arg); + + napi_value answerNapi; + status = Convert2JSValue(env, in.answer, answerNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert answer to napi_value.", napi_invalid_arg); + + status = napi_set_named_property(env, out, "answer", answerNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to set answer to object of StreamStruct.", napi_invalid_arg); + return napi_ok; +} + napi_status AipNapiUtils::Convert2JSValue(napi_env env, const std::map<std::string, FieldType> &in, napi_value &out) { napi_create_object(env, &out); diff --git a/udmf/framework/jskitsimpl/intelligence/i_aip_core_manager_impl.cpp b/udmf/framework/jskitsimpl/intelligence/i_aip_core_manager_impl.cpp index 8866a390dc1b01b450a71e512b16f78a4d99c96b..aac1ccf3e2f238f1af2ecc998f2c41f100105a49 100644 --- a/udmf/framework/jskitsimpl/intelligence/i_aip_core_manager_impl.cpp +++ b/udmf/framework/jskitsimpl/intelligence/i_aip_core_manager_impl.cpp @@ -17,22 +17,8 @@ #include "aip_napi_error.h" -#undef LOG_TAG -#define LOG_TAG "IAipCoreManagerImpl" - namespace OHOS { namespace DataIntelligence { -int32_t IAipCoreManagerImpl::InitRetriever(const RetrievalConfigStruct &retrievalConfig) -{ - return DEVICE_EXCEPTION; -} - -int32_t IAipCoreManagerImpl::Retrieve(const std::string query, const RetrievalConditionStruct &condition, - RetrievalResponseStruct &retrievalResponse) -{ - return DEVICE_EXCEPTION; -} - int32_t IAipCoreManagerImpl::InitTextModel(const ModelConfigData &config) { return DEVICE_EXCEPTION; @@ -84,5 +70,33 @@ int32_t IAipCoreManagerImpl::SplitText(std::string text, int32_t size, float ove { return DEVICE_EXCEPTION; } + +int32_t IAipCoreManagerImpl::CreateRAGSession(const ContextParam &contex, const ConfigStruct &config) +{ + return DEVICE_EXCEPTION; +} + +int32_t IAipCoreManagerImpl::RAGSessionStreamRun(const std::string &question, const OptionStruct &option, + std::function<void(const StreamStruct&, int32_t)> callback) +{ + return DEVICE_EXCEPTION; +} + +int32_t IAipCoreManagerImpl::ReleaseRAGSession() +{ + return DEVICE_EXCEPTION; +} + +int32_t IAipCoreManagerImpl::RAGSessionRun(const std::string &query, const OptionStruct &runOption, + AnswerStruct &answer) +{ + return DEVICE_EXCEPTION; +} + +bool IAipCoreManagerImpl::CheckDeviceType() +{ + return false; +} + } // namespace DataIntelligence } // namespace OHOS diff --git a/udmf/framework/jskitsimpl/intelligence/image_embedding_napi.cpp b/udmf/framework/jskitsimpl/intelligence/image_embedding_napi.cpp index cbe74806b95dab5105f4b8c9a4c84af14ec348da..001a271b2515d393e1d7707df4290767c99e4f02 100644 --- a/udmf/framework/jskitsimpl/intelligence/image_embedding_napi.cpp +++ b/udmf/framework/jskitsimpl/intelligence/image_embedding_napi.cpp @@ -79,8 +79,8 @@ ImageEmbeddingNapi::ImageEmbeddingNapi() : env_(nullptr) {} ImageEmbeddingNapi::~ImageEmbeddingNapi() { AipNapiUtils::UnLoadAlgoLibrary(imgAipCoreMgrHandle_); - imageAipCoreManager_ = nullptr; delete imageAipCoreManager_; + imageAipCoreManager_ = nullptr; } static napi_value StartInit(napi_env env, napi_value exports, struct ImageEmbeddingConstructorInfo info) @@ -130,7 +130,7 @@ napi_value ImageEmbeddingNapi::Init(napi_env env, napi_value exports) if (imgAipCoreMgrHandle_.pAipManager != nullptr) { imageAipCoreManager_ = AipNapiUtils::GetAlgoObj(imgAipCoreMgrHandle_); } else { - imageAipCoreManager_ = new IAipCoreManagerImpl(); + imageAipCoreManager_ = new (std::nothrow) IAipCoreManagerImpl(); } if (imageAipCoreManager_ == nullptr) { @@ -230,11 +230,16 @@ napi_value ImageEmbeddingNapi::GetImageEmbeddingModel(napi_env env, napi_callbac return nullptr; } - auto asyncGetImgEmbeddingModelData = new AsyncGetImageEmbeddingModelData{ + auto asyncGetImgEmbeddingModelData = new (std::nothrow) AsyncGetImageEmbeddingModelData{ .asyncWork = nullptr, .deferred = deferred, .config = imgModelConfig, }; + if (asyncGetImgEmbeddingModelData == nullptr) { + AIP_HILOGE("new asyncGetImgEmbeddingModelData error."); + ThrowIntelligenceErr(env, INNER_ERROR, "new asyncGetImgEmbeddingModelData failed"); + return nullptr; + } if (!CreateAsyncImgModelExecution(env, asyncGetImgEmbeddingModelData)) { AIP_HILOGE("create AsyncTextModelExecution failed"); @@ -258,7 +263,9 @@ bool ImageEmbeddingNapi::ParseModelConfig(napi_env env, napi_value *args, size_t return false; } - napi_value version, isNPUAvailable, cachePath; + napi_value version; + napi_value isNPUAvailable; + napi_value cachePath; napi_status status = napi_get_named_property(env, args[ARG_0], "version", &version); if (status != napi_ok) { AIP_HILOGE("napi get version property failed"); @@ -369,6 +376,7 @@ void ImageEmbeddingNapi::GetImgEmbeddingModelCompleteCB(napi_env env, napi_statu if (status != napi_ok) { AIP_HILOGE("napi_new_instance failed"); napi_get_undefined(env, &result); + delete modelData; return; } @@ -428,11 +436,15 @@ napi_value ImageEmbeddingNapi::GetEmbedding(napi_env env, napi_callback_info inf bool ImageEmbeddingNapi::GetEmbeddingAsyncExecution(napi_env env, napi_deferred deferred, std::string strArg) { AIP_HILOGD("Enter"); - auto imageCallbackData = new ImageCallbackData{ + auto imageCallbackData = new (std::nothrow) ImageCallbackData{ .asyncWork = nullptr, .deferred = deferred, .strArg = strArg, }; + if (imageCallbackData == nullptr) { + AIP_HILOGE("new imageCallbackData error."); + return false; + } napi_value resourceName; napi_status status = napi_create_string_utf8(env, "ImageGetEmbedding", NAPI_AUTO_LENGTH, &resourceName); @@ -550,10 +562,14 @@ napi_value ImageEmbeddingNapi::LoadModel(napi_env env, napi_callback_info info) bool ImageEmbeddingNapi::LoadAsyncExecution(napi_env env, napi_deferred deferred) { AIP_HILOGD("Enter"); - auto loadCallbackData = new LoadCallbackData{ + auto loadCallbackData = new (std::nothrow) LoadCallbackData{ .asyncWork = nullptr, .deferred = deferred, }; + if (loadCallbackData == nullptr) { + AIP_HILOGE("new loadCallbackData error."); + return false; + } napi_value resourceName; napi_status status = napi_create_string_utf8(env, "imageLoad", NAPI_AUTO_LENGTH, &resourceName); @@ -661,10 +677,14 @@ napi_value ImageEmbeddingNapi::ReleaseModel(napi_env env, napi_callback_info inf bool ImageEmbeddingNapi::ReleaseAsyncExecution(napi_env env, napi_deferred deferred) { AIP_HILOGD("Enter"); - auto releaseCallbackData = new ReleaseCallbackData{ + auto releaseCallbackData = new (std::nothrow) ReleaseCallbackData{ .asyncWork = nullptr, .deferred = deferred, }; + if (releaseCallbackData == nullptr) { + AIP_HILOGE("new releaseCallbackData error."); + return false; + } napi_value resourceName; napi_status status = napi_create_string_utf8(env, "textLoad", NAPI_AUTO_LENGTH, &resourceName); diff --git a/udmf/framework/jskitsimpl/intelligence/js_ability.cpp b/udmf/framework/jskitsimpl/intelligence/js_ability.cpp index 5c36d68106ce52c86e9ea3875da7ad1c5dbdee67..8653083ee496df08bf2ec141a9df473a53d73db2 100644 --- a/udmf/framework/jskitsimpl/intelligence/js_ability.cpp +++ b/udmf/framework/jskitsimpl/intelligence/js_ability.cpp @@ -14,6 +14,8 @@ */ #define LOG_TAG "JSAbility" +#include <memory> + #include "aip_log.h" #include "extension_context.h" #include "js_ability.h" @@ -27,6 +29,7 @@ Context::Context(std::shared_ptr<AbilityRuntime::Context> stageContext) isStageMode_ = true; databaseDir_ = stageContext->GetDatabaseDir(); bundleName_ = stageContext->GetBundleName(); + cacheDir_ = stageContext->GetCacheDir(); area_ = stageContext->GetArea(); auto hapInfo = stageContext->GetHapModuleInfo(); if (hapInfo != nullptr) { @@ -57,6 +60,7 @@ Context::Context(std::shared_ptr<AbilityRuntime::Context> stageContext) Context::Context(std::shared_ptr<AbilityRuntime::AbilityContext> abilityContext) { databaseDir_ = abilityContext->GetDatabaseDir(); + cacheDir_ = abilityContext->GetCacheDir(); bundleName_ = abilityContext->GetBundleName(); area_ = abilityContext->GetArea(); auto abilityInfo = abilityContext->GetAbilityInfo(); @@ -70,6 +74,11 @@ std::string Context::GetDatabaseDir() return databaseDir_; } +std::string Context::GetCacheDir() +{ + return cacheDir_; +} + int Context::GetSystemDatabaseDir(const std::string &dataGroupId, std::string &databaseDir) { return stageContext_->GetSystemDatabaseDir(dataGroupId, false, databaseDir); diff --git a/udmf/framework/jskitsimpl/intelligence/native_module_intelligence.cpp b/udmf/framework/jskitsimpl/intelligence/native_module_intelligence.cpp index daf2b026f3ba80b902bbc78dd67628eb7ff3b8c1..9d92b1ca14488a6a09ed15f730a22406758fdd86 100644 --- a/udmf/framework/jskitsimpl/intelligence/native_module_intelligence.cpp +++ b/udmf/framework/jskitsimpl/intelligence/native_module_intelligence.cpp @@ -27,7 +27,6 @@ static napi_value Export(napi_env env, napi_value exports) AIP_HILOGD("NativeModuleIntelligence call"); TextEmbeddingNapi::Init(env, exports); ImageEmbeddingNapi::Init(env, exports); - RetrievalNapi::Init(env, exports); return exports; } diff --git a/udmf/framework/jskitsimpl/intelligence/native_module_rag.cpp b/udmf/framework/jskitsimpl/intelligence/native_module_rag.cpp new file mode 100644 index 0000000000000000000000000000000000000000..453e3af15ef89340453c7c83f192f5a4a716b8b1 --- /dev/null +++ b/udmf/framework/jskitsimpl/intelligence/native_module_rag.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 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 "native_module_rag.h" + +#include "aip_log.h" +#include "rag_agent_chatllm_napi.h" +#include "rag_session_napi.h" + +#undef LOG_TAG +#define LOG_TAG "NativeModuleRAG" + +namespace OHOS { +namespace DataIntelligence { +static napi_value Export(napi_env env, napi_value exports) +{ + AIP_HILOGD("NativeModuleRAG call"); + RAGSessionNapi::Init(env, exports); + RAGAgentChatLLMNapi::Init(env, exports); + return exports; +} + +static napi_module DataRAGModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Export, + .nm_modname = "data.rag", + .nm_priv = ((void *)0), + .reserved = { 0 } +}; + +extern "C" __attribute__((constructor)) void RegisterRagModule() +{ + napi_module_register(&DataRAGModule); +} +} // namespace DataIntelligence +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/intelligence/rag_agent_chatllm_napi.cpp b/udmf/framework/jskitsimpl/intelligence/rag_agent_chatllm_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..478a4ba536fc12af9f00c16c3afe5372cc80a10e --- /dev/null +++ b/udmf/framework/jskitsimpl/intelligence/rag_agent_chatllm_napi.cpp @@ -0,0 +1,63 @@ +/* +* Copyright (c) 2025 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 "rag_agent_chatllm_napi.h" + +#include "aip_log.h" +#include "aip_napi_utils.h" + +#undef LOG_TAG +#define LOG_TAG "ChatLLMNNapi" + +namespace OHOS { +namespace DataIntelligence { + +napi_value RAGAgentChatLLMNapi::Constructor(napi_env env, napi_callback_info info) +{ + napi_value args; + napi_get_cb_info(env, info, nullptr, nullptr, &args, nullptr); + return args; +} + +napi_value RAGAgentChatLLMNapi::Init(napi_env env, napi_value exports) +{ + if (const napi_status status = InitEnum(env, exports); status != napi_ok) { + AIP_HILOGI("InitEnum fail."); + return nullptr; + } + napi_value chatLLMClass; + napi_define_class(env, "ChatLlm", NAPI_AUTO_LENGTH, Constructor, nullptr, 0, nullptr, &chatLLMClass); + napi_set_named_property(env, exports, "ChatLlm", chatLLMClass); + return exports; +} + +napi_status RAGAgentChatLLMNapi::InitEnum(napi_env env, napi_value exports) +{ + napi_value llmRequestStatus; + if (const napi_status status = napi_create_object(env, &llmRequestStatus); status != napi_ok) { + AIP_HILOGE("create napi object fail."); + return status; + } + AipNapiUtils::SetInt32Property(env, llmRequestStatus, LLM_SUCCESS, "LLM_SUCCESS"); + AipNapiUtils::SetInt32Property(env, llmRequestStatus, LLM_ERROR, "LLM_ERROR"); + AipNapiUtils::SetInt32Property(env, llmRequestStatus, LLM_LOAD_FAILED, "LLM_LOAD_FAILED"); + AipNapiUtils::SetInt32Property(env, llmRequestStatus, LLM_TIMEOUT, "LLM_TIMEOUT"); + AipNapiUtils::SetInt32Property(env, llmRequestStatus, LLM_BUSY, "LLM_BUSY"); + AipNapiUtils::SetPropertyName(env, exports, "LlmRequestStatus", llmRequestStatus); + return napi_ok; +} + +} +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/intelligence/rag_chatllm_impl.cpp b/udmf/framework/jskitsimpl/intelligence/rag_chatllm_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2e35081ac2c2ded6900de85832024e88667afc61 --- /dev/null +++ b/udmf/framework/jskitsimpl/intelligence/rag_chatllm_impl.cpp @@ -0,0 +1,356 @@ +/* +* Copyright (c) 2025 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 "rag_chatllm_impl.h" + +#include <future> +#include <uv.h> + +#include "aip_log.h" +#include "aip_napi_error.h" +#include "aip_napi_utils.h" +#include "napi_trace.h" + +#undef LOG_TAG +#define LOG_TAG "CreateRAGNapi" + +namespace OHOS { +namespace DataIntelligence { +std::shared_ptr<LLMStreamCallback> ChatLLM::llmStreamCallback_ = nullptr; +constexpr int STREAM_CHAT_WORK_DEFAULT_WAIT = 2; +constexpr int JS_STREAM_CHAT_ARGS_COUNT = 2; + +ChatLLM::ChatLLM(napi_env env, napi_ref streamChatRef) : env_(env), streamChatRef_(streamChatRef) +{ +} + +ChatLLM::~ChatLLM() +{ + napi_delete_reference(env_, streamChatRef_); +} + +TsLLMRequestStatus ChatLLM::StreamChat(const std::string &query, const LLMStreamCallback &streamCallback) +{ + DATA_INTELLIGENCE_HITRACE(std::string(__FUNCTION__)); + AIP_HILOGD("Enter. queryLength: %{public}zu", query.length()); + if (streamChatRef_ == nullptr) { + AIP_HILOGE("streamChatRef_ is nullptr"); + return LLM_ERROR; + } + llmStreamCallback_ = std::make_shared<LLMStreamCallback>(streamCallback); + + auto *param = new (std::nothrow) WorkParam { + query, + std::make_shared<LLMStreamCallback>(streamCallback), + env_, + streamChatRef_, + napi_ok, + 0, + std::make_shared<ThreadLockInfo>(), + }; + if (param == nullptr) { + AIP_HILOGE("WorkParam is nullptr"); + return LLM_ERROR; + } + + napi_status status = napi_send_event(env_, [param] { + StreamChatCallbackEventFunc(param); + }, napi_eprio_high); + if (status != napi_ok) { + AIP_HILOGE("napi_send_event running failed, status: %{public}d", status); + delete param; + param = nullptr; + return LLM_ERROR; + } + + std::unique_lock<std::mutex> lock(param->lockInfo->mutex); + if (param->lockInfo->condition.wait_for(lock, std::chrono::seconds(STREAM_CHAT_WORK_DEFAULT_WAIT), + [param] { return param->lockInfo->ready; })) { + AIP_HILOGE("call js callback not complete."); + } + AIP_HILOGD("llmStreamChatWorker end, ready: %{public}d, result: %{public}d", param->lockInfo->ready, param->result); + int32_t retInt = param->result; + + delete param; + param = nullptr; + + return static_cast<TsLLMRequestStatus>(retInt); +} + +void ChatLLM::SetRef(napi_ref streamChatRef) +{ + streamChatRef_ = streamChatRef; +} + +napi_ref ChatLLM::GetRef() +{ + return streamChatRef_; +} + +void ChatLLM::NativeCallbackAsync(napi_env env, const LLMStreamAnswer &answer) +{ + uv_loop_s *loop = nullptr; + napi_get_uv_event_loop(env, &loop); + if (loop == nullptr) { + AIP_HILOGE("loop instance is nullptr"); + return; + } + auto *work = new (std::nothrow) uv_work_t; + if (work == nullptr) { + AIP_HILOGE("work is nullptr"); + return; + } + auto *param = new (std::nothrow) StreamCallbackWorkParam { answer, env }; + if (param == nullptr) { + delete work; + work = nullptr; + AIP_HILOGE("WorkParam is nullptr"); + return; + } + work->data = reinterpret_cast<void *>(param); + int ret = uv_queue_work(loop, work, [](uv_work_t *work) { + if (work == nullptr || work->data == nullptr) { + AIP_HILOGE("invalid parameter"); + return; + } + auto *workParam = reinterpret_cast<StreamCallbackWorkParam *>(work->data); + llmStreamCallback_->operator()(workParam->answer); + }, [](uv_work_t *work, int32_t status) { + if (work == nullptr) { + AIP_HILOGE("invalid parameter"); + return; + } + auto *workParam = reinterpret_cast<StreamCallbackWorkParam *>(work->data); + delete workParam; + workParam = nullptr; + delete work; + work = nullptr; + }); + if (ret != 0) { + AIP_HILOGE("uv_queue_work running failed, ret: %{public}d", ret); + delete param; + param = nullptr; + delete work; + work = nullptr; + } +} + +napi_value ChatLLM::StreamCallbackFunc(napi_env env, napi_callback_info info) +{ + napi_value result = nullptr; + napi_get_null(env, &result); + + napi_value args[] = { nullptr }; + size_t size = 1; + napi_value jsFunction; + napi_status status = napi_get_cb_info(env, info, &size, args, nullptr, reinterpret_cast<void**>(&jsFunction)); + if (status != napi_ok) { + AIP_HILOGE("napi_get_cb_info failed. status: %{public}d", status); + return result; + } + + if (llmStreamCallback_ == nullptr) { + AIP_HILOGE("streamCallback is nullptr."); + return result; + } + + LLMStreamAnswer answer = { + .isFinished = false, + .chunk = "", + }; + status = AipNapiUtils::Convert2Value(env, args[0], answer); + if (status != napi_ok) { + AIP_HILOGE("Failed to convert the LLMStreamAnswer. status: %{public}d", status); + return result; + } + + NativeCallbackAsync(env, answer); + + return result; +} + +void ChatLLM::StreamChatCallbackEventFunc(WorkParam *param) +{ + if (param == nullptr) { + AIP_HILOGE("param is nullptr"); + return; + } + + if (param->query.empty() || param->llmStreamCallback == nullptr || param->ref == nullptr) { + AIP_HILOGE("param of llmWorkParam is null"); + return; + } + + napi_handle_scope scope = nullptr; + napi_open_handle_scope(param->env, &scope); + if (scope == nullptr) { + AIP_HILOGE("scope open failed. scope is nullptr"); + return; + } + + CallJSStreamChat(param->env, param->ref, param); + + napi_close_handle_scope(param->env, scope); +} + +void ChatLLM::CallJSStreamChat(napi_env env, napi_ref ref, WorkParam *llmWorkParam) +{ + napi_value callback = nullptr; + auto ret = napi_get_reference_value(env, ref, &callback); + if (ret != napi_ok) { + AIP_HILOGE("get js callback failed. ret: %{public}d", ret); + return; + } + + napi_value queryArg; + napi_status status = napi_create_string_utf8(env, llmWorkParam->query.c_str(), NAPI_AUTO_LENGTH, &queryArg); + if (status != napi_ok) { + AIP_HILOGE("Failed to napi_create_string_utf8 for query. ret: %{public}d", status); + return; + } + + napi_value jsCallbackArg; + status = napi_create_function(env, "callback", NAPI_AUTO_LENGTH, StreamCallbackFunc, nullptr, &jsCallbackArg); + if (status != napi_ok) { + AIP_HILOGE("Failed to napi_create_function for callback. ret: %{public}d", status); + return; + } + + napi_value jsStreamChat; + status = napi_get_reference_value(env, ref, &jsStreamChat); + if (status != napi_ok) { + AIP_HILOGE("Failed to napi_get_reference_value for jsStreamChat. ret: %{public}d", status); + return; + } + + napi_value global; + status = napi_get_global(env, &global); + if (status != napi_ok) { + AIP_HILOGE("Failed to napi_get_global from env. ret: %{public}d", status); + return; + } + + const napi_value args[JS_STREAM_CHAT_ARGS_COUNT] = { queryArg, jsCallbackArg }; + + AIP_HILOGI("Begin call js."); + napi_value promiseResult; // promise + status = napi_call_function(env, global, jsStreamChat, JS_STREAM_CHAT_ARGS_COUNT, args, &promiseResult); + if (status != napi_ok) { + AIP_HILOGE("Failed to napi_call_function for jsStreamChat. ret: %{public}d", status); + return; + } + + HandlePromiseValue(env, promiseResult, llmWorkParam); +} + +void ChatLLM::HandlePromiseValue(napi_env env, napi_value promiseResult, WorkParam *llmWorkParam) +{ + auto isPromise = false; + napi_status status = napi_is_promise(env, promiseResult, &isPromise); + if (status != napi_ok || !isPromise) { + AIP_HILOGE("resultType is not promise. isPromise: %{public}d, ret: %{public}d", isPromise, status); + return; + } + + napi_value thenCallback; + status = napi_create_function(env, nullptr, 0, PromiseThenCallback, llmWorkParam, &thenCallback); + if (status != napi_ok) { + AIP_HILOGE("Failed to create then callback. ret: %{public}d", status); + return; + } + + napi_value catchCallback; + status = napi_create_function(env, nullptr, 0, PromiseCatchCallback, llmWorkParam, &catchCallback); + if (status != napi_ok) { + AIP_HILOGE("Failed to create catch callback. ret: %{public}d", status); + return; + } + + napi_value thenMethod; + status = napi_get_named_property(env, promiseResult, "then", &thenMethod); + if (status != napi_ok) { + AIP_HILOGE("Failed to get then method. ret: %{public}d", status); + return; + } + + napi_value catchMethod; + status = napi_get_named_property(env, promiseResult, "catch", &catchMethod); + if (status != napi_ok) { + AIP_HILOGE("Failed to get catch method. ret: %{public}d", status); + return; + } + + napi_value argsPromise[1] = { thenCallback }; + napi_value thenResult; + status = napi_call_function(env, promiseResult, thenMethod, 1, argsPromise, &thenResult); + if (status != napi_ok) { + AIP_HILOGE("Failed to call then method. ret: %{public}d", status); + return; + } + + argsPromise[0] = catchCallback; + napi_value catchResult; + status = napi_call_function(env, promiseResult, catchMethod, 1, argsPromise, &catchResult); + if (status != napi_ok) { + AIP_HILOGE("Failed to call catch method. ret: %{public}d", status); + } +} + +napi_value ChatLLM::PromiseThenCallback(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + void *paramIn = nullptr; + napi_get_cb_info(env, info, &argc, args, nullptr, &paramIn); + + auto *callbackParam = static_cast<WorkParam*>(paramIn); + if (callbackParam == nullptr) { + AIP_HILOGE("callbackParam is null"); + return nullptr; + } + + napi_valuetype resultType; + napi_typeof(env, args[0], &resultType); + if (resultType == napi_object) { + napi_value statusNapi; + napi_status status = napi_get_named_property(env, args[0], "status", &statusNapi); + if (status == napi_ok) { + int32_t number = 0; + napi_get_value_int32(env, statusNapi, &number); + if (number != TsLLMRequestStatus::LLM_SUCCESS) { + AIP_HILOGE("LLM return error. errCode: %{public}d", number); + } + callbackParam->result = number; + } else { + AIP_HILOGE("cannot get prperty status"); + } + } else { + AIP_HILOGE("The resolved value is not a object, type: %{public}d", resultType); + } + + std::unique_lock<std::mutex> lock(callbackParam->lockInfo->mutex); + callbackParam->lockInfo->ready = true; + AIP_HILOGD("begin notify_all"); + callbackParam->lockInfo->condition.notify_all(); + return nullptr; +} + +napi_value ChatLLM::PromiseCatchCallback(napi_env env, napi_callback_info info) +{ + AIP_HILOGE("The promise function catch exception."); + return nullptr; +} + +} +} diff --git a/udmf/framework/jskitsimpl/intelligence/rag_session_napi.cpp b/udmf/framework/jskitsimpl/intelligence/rag_session_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..62902b85d6aa613d40665d882ec2d14f2633dec6 --- /dev/null +++ b/udmf/framework/jskitsimpl/intelligence/rag_session_napi.cpp @@ -0,0 +1,625 @@ +/* + * Copyright (c) 2025 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 "rag_session_napi.h" +#include <dlfcn.h> +#include <functional> +#include <node_api.h> +#include <string> +#include <utility> +#include <uv.h> + +#include "aip_log.h" +#include "aip_napi_error.h" +#include "aip_napi_utils.h" +#include "i_aip_core_manager_impl.h" +#include "napi_trace.h" + +#undef LOG_TAG +#define LOG_TAG "RAGSessionNapi" + +namespace OHOS { +namespace DataIntelligence { +namespace { +const int32_t ERR_OK = 0; +constexpr const char *AIP_MANAGER_PATH = "libaip_core.z.so"; +} // namespace +AipCoreManagerHandle RAGSessionNapi::aipAipCoreMgrHandle_{}; +constexpr int STREAM_RUN_ARG_COUNT = 3; +constexpr int STREAM_RUN_QUESTION_ARG = 0; +constexpr int STREAM_RUN_OPTION_ARG = 1; +constexpr int STREAM_RUN_CALLBACK_ARG = 2; +constexpr int CREATE_SESSION_ARG_COUNT = 2; +constexpr int CREATE_SESSION_CONTEXT_ARG = 0; +constexpr int CREATE_SESSION_CONFIG_ARG = 1; + +RAGSessionNapi::RAGSessionNapi(IAipCoreManager *aipAipCoreManager) : aipAipCoreManager_(aipAipCoreManager) +{ +} + +RAGSessionNapi::~RAGSessionNapi() +{ + if (env_ == nullptr) { + AIP_HILOGE("env_ is nullptr."); + return; + } + if (ref_ != nullptr) { + napi_delete_reference(env_, ref_); + } + + if (thisJsRef_ != nullptr) { + napi_delete_reference(env_, thisJsRef_); + } +} + +napi_value RAGSessionNapi::Init(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + DECLARE_NAPI_FUNCTION("createRagSession", CreateRAGSession), + }; + napi_status status = napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + if (status != napi_ok) { + AIP_HILOGE("define properties fail, status = %{public}d", status); + return nullptr; + } + return exports; +} + +napi_value RAGSessionNapi::WrapAipCoreManager(napi_env env, IAipCoreManager* ragAipCoreManager) +{ + if (ragAipCoreManager == nullptr) { + AIP_HILOGE("ragAipCoreManager is nullptr."); + return nullptr; + } + napi_value result; + napi_status status = napi_create_object(env, &result); + if (status != napi_ok) { + return nullptr; + } + auto *sessionNapi = new (std::nothrow) RAGSessionNapi(ragAipCoreManager); + if (sessionNapi == nullptr) { + AIP_HILOGE("sessionNapi new failed"); + return nullptr; + } + status = napi_wrap(env, result, static_cast<void *>(sessionNapi), [](napi_env env, void *data, void *hint) { + delete static_cast<RAGSessionNapi *>(data); + }, nullptr, nullptr); + if (status != napi_ok) { + AIP_HILOGE("napi_wrap aipCoreMangager failed, erroCode is %{public}d", status); + delete sessionNapi; + return nullptr; + } + napi_value streamRunFn; + status = napi_create_function(env, nullptr, NAPI_AUTO_LENGTH, StreamRun, nullptr, &streamRunFn); + if (status != napi_ok) { + delete sessionNapi; + return nullptr; + } + status = napi_set_named_property(env, result, "streamRun", streamRunFn); + if (status != napi_ok) { + delete sessionNapi; + return nullptr; + } + napi_value closeFn; + status = napi_create_function(env, nullptr, NAPI_AUTO_LENGTH, Close, nullptr, &closeFn); + if (status != napi_ok) { + AIP_HILOGE("napi_create_function Close failed, erroCode is %{public}d", status); + delete sessionNapi; + return nullptr; + } + status = napi_set_named_property(env, result, "close", closeFn); + if (status != napi_ok) { + AIP_HILOGE("napi_set_named_property close failed, erroCode is %{public}d", status); + delete sessionNapi; + return nullptr; + } + AIP_HILOGI("Build rag session success."); + return result; +} + +napi_value RAGSessionNapi::CreateRAGSession(napi_env env, napi_callback_info info) +{ + napi_value args[CREATE_SESSION_ARG_COUNT] = { nullptr }; + size_t argc = CREATE_SESSION_ARG_COUNT; + napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (status != napi_ok) { + ThrowIntelligenceErr(env, INNER_ERROR, "napi_get_cb_info failed."); + return nullptr; + } + ContextParam context; + status = AipNapiUtils::Convert2Value(env, args[CREATE_SESSION_CONTEXT_ARG], context); + if (status != napi_ok) { + ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Parse context failed."); + return nullptr; + } + ConfigStruct config; + status = AipNapiUtils::Convert2Value(env, args[CREATE_SESSION_CONFIG_ARG], config); + if (status != napi_ok) { + ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Parse config failed."); + return nullptr; + } + napi_value promise = nullptr; + napi_deferred deferred = nullptr; + status = napi_create_promise(env, &deferred, &promise); + if (status != napi_ok) { + ThrowIntelligenceErr(env, INNER_ERROR, "create promise failed"); + return nullptr; + } + auto asyncCreateRAGSession = new (std::nothrow) AsyncCreateRAGSession{ + .asyncWork = nullptr, + .deferred = deferred, + .context = context, + .config = config + }; + if (asyncCreateRAGSession == nullptr) { + ThrowIntelligenceErr(env, INNER_ERROR, "Allocate memory failed."); + return nullptr; + } + if (!CreateAsyncCreateRAGSession(env, asyncCreateRAGSession)) { + delete asyncCreateRAGSession; + ThrowIntelligenceErr(env, INNER_ERROR, "create CreateAsyncCreateRAGSession failed"); + return nullptr; + } + return promise; +} + +bool RAGSessionNapi::CreateAsyncCreateRAGSession(napi_env env, AsyncCreateRAGSession *asyncCreateRAGSession) +{ + napi_value resourceName; + napi_status status = napi_create_string_utf8(env, "CreateRAGSession", NAPI_AUTO_LENGTH, &resourceName); + if (status != napi_ok) { + AIP_HILOGE(" napi_create_string_utf8 failed."); + return false; + } + status = napi_create_async_work(env, nullptr, resourceName, CreateRAGSessionExecutionCB, CreateRAGSessionCompleteCB, + static_cast<void *>(asyncCreateRAGSession), &asyncCreateRAGSession->asyncWork); + if (status != napi_ok) { + AIP_HILOGE("napi_create_async_work failed. status: %{public}d", status); + return false; + } + status = napi_queue_async_work_with_qos(env, asyncCreateRAGSession->asyncWork, napi_qos_default); + if (status != napi_ok) { + AIP_HILOGE("napi_queue_async_work_with_qos failed. status: %{public}d", status); + napi_delete_async_work(env, asyncCreateRAGSession->asyncWork); + return false; + } + return true; +} + +void RAGSessionNapi::CreateRAGSessionExecutionCB(napi_env env, void *data) +{ + AsyncCreateRAGSession *asyncCreateRAGSession = static_cast<AsyncCreateRAGSession *>(data); + auto config = asyncCreateRAGSession->config; + auto context = asyncCreateRAGSession->context; + IAipCoreManager *aipAipCoreManager = nullptr; + if (aipAipCoreMgrHandle_.create == nullptr) { + AipNapiUtils::LoadAlgoLibrary(AIP_MANAGER_PATH, aipAipCoreMgrHandle_, false); + } + if (aipAipCoreMgrHandle_.create != nullptr) { + aipAipCoreManager = aipAipCoreMgrHandle_.create(); + } + if (aipAipCoreManager == nullptr) { + AIP_HILOGW("Init RAGSession success by new."); + aipAipCoreManager = new (std::nothrow) IAipCoreManagerImpl(); + } + if (aipAipCoreManager == nullptr) { + AIP_HILOGE("Allocate memory failed."); + return; + } + int32_t ret = aipAipCoreManager->CreateRAGSession(context, config); + asyncCreateRAGSession->ret = ret; + if (ret != ERR_OK) { + AIP_HILOGE("init RAGSession failed, erroCode is %{public}d", ret); + delete aipAipCoreManager; + return; + } + asyncCreateRAGSession->ragAipCoreManagerPtr = aipAipCoreManager; +} + +void RAGSessionNapi::CreateRAGSessionCompleteCB(napi_env env, napi_status status, void *data) +{ + AsyncCreateRAGSession *asyncCreateRAGSession = static_cast<AsyncCreateRAGSession *>(data); + if (asyncCreateRAGSession == nullptr) { + AIP_HILOGE("asyncCreateRAGSession is nullptr."); + return; + } + auto ret = asyncCreateRAGSession->ret; + napi_value result = nullptr; + if (ret != ERR_OK) { + if (ret == DEVICE_EXCEPTION) { + ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "CreateRAGSessionCompleteCB failed", result); + } else { + ThrowIntelligenceErrByPromise(env, + ConvertErrCodeNative2Ts(ret), "CreateRAGSessionCompleteCB failed", result); + } + napi_reject_deferred(env, asyncCreateRAGSession->deferred, result); + } else { + result = WrapAipCoreManager(env, asyncCreateRAGSession->ragAipCoreManagerPtr); + if (result == nullptr) { + delete asyncCreateRAGSession->ragAipCoreManagerPtr; + ThrowIntelligenceErrByPromise(env, INNER_ERROR, "CreateRAGSessionCompleteCB failed", result); + napi_reject_deferred(env, asyncCreateRAGSession->deferred, result); + } + status = napi_resolve_deferred(env, asyncCreateRAGSession->deferred, result); + if (status != napi_ok) { + AIP_HILOGE("napi_resolve_deferred failed. status: %{public}d", status); + } + } + status = napi_delete_async_work(env, asyncCreateRAGSession->asyncWork); + if (status != napi_ok) { + AIP_HILOGE("napi_delete_async_work failed. status: %{public}d", status); + } + delete asyncCreateRAGSession; +} + +napi_value RAGSessionNapi::Close(napi_env env, napi_callback_info info) +{ + napi_value argv[1] = { nullptr }; + size_t argc = 1; + napi_value jsThis = nullptr; + napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr); + if (status != napi_ok) { + ThrowIntelligenceErr(env, INNER_ERROR, "napi_get_cb_info failed."); + return nullptr; + } + + napi_value promise = nullptr; + napi_deferred deferred = nullptr; + status = napi_create_promise(env, &deferred, &promise); + if (status != napi_ok) { + ThrowIntelligenceErr(env, INNER_ERROR, "create promise failed."); + return nullptr; + } + RAGSessionNapi *sessionNapi; + status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&sessionNapi)); + if (status != napi_ok || sessionNapi == nullptr || sessionNapi->aipAipCoreManager_ == nullptr) { + ThrowIntelligenceErr(env, RAG_E_RAG_ALREADY_CLOSED, "RAG session napi has already closed."); + return nullptr; + } + auto asyncClose = new (std::nothrow) AsyncStreamRun { + .asyncWork = nullptr, + .deferred = deferred, + .sessionNapi = sessionNapi + }; + if (asyncClose == nullptr) { + ThrowIntelligenceErr(env, INNER_ERROR, "Allocate memory failed."); + return nullptr; + } + if (!CreateAsyncCloseExecution(env, asyncClose)) { + delete asyncClose; + ThrowIntelligenceErr(env, INNER_ERROR, "CreateAsyncCloseExecution failed"); + return nullptr; + } + return promise; +} + +bool RAGSessionNapi::CreateAsyncCloseExecution(napi_env env, AsyncStreamRun *asyncClose) +{ + napi_value resourceName; + napi_status status = napi_create_string_utf8(env, "Close", NAPI_AUTO_LENGTH, &resourceName); + if (status != napi_ok) { + AIP_HILOGE(" napi_create_string_utf8 failed. status: %{public}d", status); + return false; + } + status = napi_create_async_work(env, nullptr, resourceName, CloseExecutionCB, CloseCompleteCB, + static_cast<void *>(asyncClose), &asyncClose->asyncWork); + if (status != napi_ok) { + AIP_HILOGE("napi_create_async_work failed. status: %{public}d", status); + return false; + } + status = napi_queue_async_work_with_qos(env, asyncClose->asyncWork, napi_qos_default); + if (status != napi_ok) { + AIP_HILOGE("napi_queue_async_work_with_qos failed. status: %{public}d", status); + napi_delete_async_work(env, asyncClose->asyncWork); + return false; + } + return true; +} + +void RAGSessionNapi::CloseExecutionCB(napi_env env, void *data) +{ + auto *asyncClose = static_cast<AsyncStreamRun *>(data); + auto runAipCoreManagerPtr = asyncClose->sessionNapi->aipAipCoreManager_; + int32_t result = runAipCoreManagerPtr->ReleaseRAGSession(); + asyncClose->ret = result; + AIP_HILOGD("ReleaseRAGAgent result: %{public}d", asyncClose->ret); +} + +void RAGSessionNapi::CloseCompleteCB(napi_env env, napi_status status, void *data) +{ + AsyncStreamRun *asyncClose = static_cast<AsyncStreamRun *>(data); + auto ret = asyncClose->ret; + if (ret != ERR_OK) { + napi_value result = nullptr; + if (ret == DEVICE_EXCEPTION) { + ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "CloseCompleteCB failed", result); + } else { + int32_t errCode = ConvertErrCodeNative2Ts(ret); + ThrowIntelligenceErrByPromise(env, errCode, "CloseCompleteCB failed", result); + } + napi_reject_deferred(env, asyncClose->deferred, result); + } else { + napi_value undefined; + napi_get_undefined(env, &undefined); + napi_resolve_deferred(env, asyncClose->deferred, undefined); + } + status = napi_delete_async_work(env, asyncClose->asyncWork); + if (status != napi_ok) { + AIP_HILOGE("napi_delete_async_work failed. status: %{public}d", status); + } + if (asyncClose->sessionNapi != nullptr) { + delete asyncClose->sessionNapi->aipAipCoreManager_; + } + delete asyncClose->sessionNapi; + delete asyncClose; + AIP_HILOGI("Rag session close success."); +} + +napi_status RAGSessionNapi::ParseStreamRunArgs(napi_env env, napi_callback_info info, std::string &question, + OptionStruct &option, RAGSessionNapi **sessionNapi) +{ + napi_value argv[STREAM_RUN_ARG_COUNT] = { nullptr }; + size_t argc = STREAM_RUN_ARG_COUNT; + napi_value jsThis = nullptr; + napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr); + if (status != napi_ok) { + ThrowIntelligenceErr(env, INNER_ERROR, "napi_get_cb_info failed."); + return status; + } + if (argc != STREAM_RUN_ARG_COUNT) { + ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Param count error."); + return napi_invalid_arg; + } + status = AipNapiUtils::Convert2Value(env, argv[STREAM_RUN_QUESTION_ARG], question); + if (status != napi_ok) { + ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Parse question failed."); + return status; + } + status = AipNapiUtils::Convert2Value(env, argv[STREAM_RUN_OPTION_ARG], option); + if (status != napi_ok) { + ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Parse option failed."); + return status; + } + napi_valuetype valueType = napi_undefined; + napi_typeof(env, argv[STREAM_RUN_CALLBACK_ARG], &valueType); + napi_ref callbackRef = nullptr; + if (valueType == napi_function) { + napi_create_reference(env, argv[STREAM_RUN_CALLBACK_ARG], 1, &callbackRef); + } else { + ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Parse callback failed."); + } + status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(sessionNapi)); + if (status != napi_ok || (*sessionNapi) == nullptr || (*sessionNapi)->aipAipCoreManager_ == nullptr) { + ThrowIntelligenceErr(env, RAG_E_RAG_ALREADY_CLOSED, "Session is already closed."); + return napi_invalid_arg; + } + napi_ref thisJsRef = nullptr; + status = napi_create_reference(env, jsThis, 1, &thisJsRef); + if (status != napi_ok) { + return status; + } + (*sessionNapi)->env_ = env; + (*sessionNapi)->ref_ = callbackRef; + (*sessionNapi)->thisJsRef_ = thisJsRef; + return napi_ok; +} + +napi_value RAGSessionNapi::StreamRun(napi_env env, napi_callback_info info) +{ + DATA_INTELLIGENCE_HITRACE(std::string(__FUNCTION__)); + std::string question; + OptionStruct option = { .answerWithRetrievalItem = false }; + RAGSessionNapi *sessionNapi = {0}; + + napi_status status = ParseStreamRunArgs(env, info, question, option, &sessionNapi); + if (status != napi_ok) { + return nullptr; + } + + napi_value promise = nullptr; + napi_deferred deferred = nullptr; + status = napi_create_promise(env, &deferred, &promise); + if (status != napi_ok) { + ThrowIntelligenceErr(env, INNER_ERROR, "create promise failed."); + return nullptr; + } + + auto asyncStreamRun = new (std::nothrow) AsyncStreamRun { + .asyncWork = nullptr, + .deferred = deferred, + .sessionNapi = sessionNapi, + .question = question, + .option = option, + }; + if (asyncStreamRun == nullptr) { + ThrowIntelligenceErr(env, INNER_ERROR, "Allocate memory failed."); + return nullptr; + } + if (!CreateAsyncStreamRunExecution(env, asyncStreamRun)) { + delete asyncStreamRun; + ThrowIntelligenceErr(env, INNER_ERROR, "CreateAsyncStreamRunExecution failed"); + } + return promise; +} + +bool RAGSessionNapi::CreateAsyncStreamRunExecution(napi_env env, AsyncStreamRun *asyncStreamRun) +{ + napi_value resourceName; + napi_status status = napi_create_string_utf8(env, "StreamRun", NAPI_AUTO_LENGTH, &resourceName); + if (status != napi_ok) { + AIP_HILOGE(" napi_create_string_utf8 failed. status: %{public}d", status); + return false; + } + status = napi_create_async_work(env, nullptr, resourceName, StreamRunExecutionCB, StreamRunCompleteCB, + static_cast<void *>(asyncStreamRun), &asyncStreamRun->asyncWork); + if (status != napi_ok) { + AIP_HILOGE("napi_create_async_work failed"); + return false; + } + status = napi_queue_async_work_with_qos(env, asyncStreamRun->asyncWork, napi_qos_default); + if (status != napi_ok) { + AIP_HILOGE("napi_queue_async_work_with_qos failed. status: %{public}d", status); + napi_delete_async_work(env, asyncStreamRun->asyncWork); + return false; + } + return true; +} + +void RAGSessionNapi::StreamRunExecutionCB(napi_env env, void *data) +{ + AsyncStreamRun *asyncStreamRun = static_cast<AsyncStreamRun *>(data); + auto question = asyncStreamRun->question; + auto option = asyncStreamRun->option; + auto sessionNapi = asyncStreamRun->sessionNapi; + std::function<void(StreamStruct, int32_t)> callBackFunction = + [sessionNapi](const StreamStruct &stream, const int32_t errorCode) { + AIP_HILOGD("streamRun callback result: %{public}d", errorCode); + StreamRunCallbackExecute(sessionNapi, stream, errorCode); + }; + int32_t result = sessionNapi->aipAipCoreManager_->RAGSessionStreamRun(question, option, callBackFunction); + AIP_HILOGD("runAipCoreManagerPtr->StreamRun result: %{public}d", result); + asyncStreamRun->ret = result; +} + +void RAGSessionNapi::StreamRunCompleteCB(napi_env env, napi_status status, void *data) +{ + AsyncStreamRun *asyncStreamRun = static_cast<AsyncStreamRun *>(data); + auto ret = asyncStreamRun->ret; + if (ret != ERR_OK) { + napi_value result = nullptr; + if (ret == DEVICE_EXCEPTION) { + ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "StreamRunCompleteCB failed", result); + } else { + int32_t errCode = ConvertErrCodeNative2Ts(ret); + ThrowIntelligenceErrByPromise(env, errCode, "StreamRunCompleteCB failed", result); + } + napi_reject_deferred(env, asyncStreamRun->deferred, result); + } else { + napi_value undefined; + napi_get_undefined(env, &undefined); + napi_resolve_deferred(env, asyncStreamRun->deferred, undefined); + } + status = napi_delete_async_work(env, asyncStreamRun->asyncWork); + if (status != napi_ok) { + AIP_HILOGE("napi_delete_async_work failed."); + } + delete asyncStreamRun; +} + +void RAGSessionNapi::StreamRunCallbackJSExecute(StreamRunCallbackWorkParam *workParam) +{ + auto env = workParam->env; + auto ref = workParam->ref; + auto thisJsRef = workParam->thisJsRef; + auto errCode = workParam->errCode; + napi_value thisJs; + if (thisJsRef == nullptr) { + AIP_HILOGE("thisJs is nullptr"); + napi_get_undefined(env, &thisJs); + } else { + napi_status refStatus = napi_get_reference_value(env, thisJsRef, &thisJs); + if (refStatus != napi_ok) { + AIP_HILOGE("js this get failed. ret: %{public}d", refStatus); + napi_get_undefined(env, &thisJs); + } + } + napi_value errorNapi; + napi_value streamNapi; + if (errCode == 0) { + napi_get_undefined(env, &errorNapi); + napi_status status = AipNapiUtils::Convert2JSValue(env, workParam->stream, streamNapi); + if (status != napi_ok) { + AIP_HILOGE("stream struct Convert2JSValue failed. ret: %{public}d", status); + return; + } + } else { + ThrowIntelligenceErrByPromise(env, ConvertErrCodeNative2Ts(errCode), + "streamRunCallbackWorkerFunc failed", errorNapi); + napi_get_undefined(env, &streamNapi); + } + + const napi_value argv[] = { errorNapi, streamNapi }; + size_t argc = 2; + + napi_value callback; + napi_status status = napi_get_reference_value(env, ref, &callback); + if (status != napi_ok) { + AIP_HILOGE("js callback function get failed. ret: %{public}d", status); + return; + } + status = napi_call_function(env, thisJs, callback, argc, argv, nullptr); + if (status != napi_ok) { + AIP_HILOGE("js callback function call failed. ret: %{public}d", status); + } +} + +void RAGSessionNapi::StreamRunCallbackEventFunc(StreamRunCallbackWorkParam *workParam) +{ + if (workParam == nullptr) { + AIP_HILOGE("workParam is nullptr"); + return; + } + if (workParam->env == nullptr || workParam->ref == nullptr) { + AIP_HILOGE("streamRun callback work param is null"); + delete workParam; + workParam = nullptr; + return; + } + napi_handle_scope scope = nullptr; + napi_open_handle_scope(workParam->env, &scope); + if (scope == nullptr) { + AIP_HILOGE("scope open failed. scope is nullptr"); + return; + } + + StreamRunCallbackJSExecute(workParam); + + napi_close_handle_scope(workParam->env, scope); + delete workParam; + workParam = nullptr; +} + +void RAGSessionNapi::StreamRunCallbackExecute(RAGSessionNapi *sessionNapi, StreamStruct stream, int32_t errCode) +{ + if (sessionNapi == nullptr || sessionNapi->env_ == nullptr || sessionNapi->ref_ == nullptr) { + AIP_HILOGE("sessionNapi is nullptr: %{public}d", sessionNapi == nullptr); + return; + } + auto env = sessionNapi->env_; + auto ref = sessionNapi->ref_; + auto thisJs = sessionNapi->thisJsRef_; + auto *workParam = new (std::nothrow) StreamRunCallbackWorkParam { + std::move(stream), + errCode, + env, + ref, + thisJs, + std::make_shared<ThreadLockInfo>(), + }; + if (workParam == nullptr) { + AIP_HILOGE("WorkParam is nullptr"); + return; + } + napi_status status = napi_send_event(env, [workParam] { + StreamRunCallbackEventFunc(workParam); + }, napi_eprio_high); + if (status != napi_ok) { + AIP_HILOGE("napi_send_event running failed, status: %{public}d", status); + delete workParam; + workParam = nullptr; + } +} +} // namespace DataIntelligence +} // namespace OHOS diff --git a/udmf/framework/jskitsimpl/intelligence/retrieval_napi.cpp b/udmf/framework/jskitsimpl/intelligence/retrieval_napi.cpp deleted file mode 100644 index a442ebd5826b7e4eae8d340e669aff1cc3f37758..0000000000000000000000000000000000000000 --- a/udmf/framework/jskitsimpl/intelligence/retrieval_napi.cpp +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (c) 2025 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 "retrieval_napi.h" - -#include <dlfcn.h> -#include <memory> -#include <node_api.h> -#include <string> - -#include "aip_log.h" -#include "aip_napi_error.h" -#include "aip_napi_utils.h" -#include "i_aip_core_manager_impl.h" - -#undef LOG_TAG -#define LOG_TAG "RetrievalNapi" - -namespace OHOS { -namespace DataIntelligence { -namespace { -const int32_t ERR_OK = 0; -constexpr const char *AIP_MANAGER_PATH = "libaip_core.z.so"; -} // namespace - -AipCoreManagerHandle RetrievalNapi::retrievalAipCoreMgrHandle_{}; - -RetrievalNapi::RetrievalNapi() : env_(nullptr) {} - -RetrievalNapi::~RetrievalNapi() -{ - AipNapiUtils::UnLoadAlgoLibrary(retrievalAipCoreMgrHandle_); -} - -napi_status InitEnum(napi_env env, napi_value exports) -{ - napi_value channelTypeEnum; - napi_status status = napi_create_object(env, &channelTypeEnum); - LOG_ERROR_RETURN(status == napi_ok, "create napi object fail.", napi_invalid_arg); - AipNapiUtils::SetInt32Property(env, channelTypeEnum, TsChannelType::VECTOR_DATABASE, "VECTOR_DATABASE"); - AipNapiUtils::SetInt32Property(env, channelTypeEnum, TsChannelType::INVERTED_INDEX_DATABASE, - "INVERTED_INDEX_DATABASE"); - AipNapiUtils::SetPropertyName(env, exports, "ChannelType", channelTypeEnum); - - napi_value operatorEnum; - status = napi_create_object(env, &operatorEnum); - LOG_ERROR_RETURN(status == napi_ok, "create napi object fail.", napi_invalid_arg); - AipNapiUtils::SetStringProperty(env, operatorEnum, "=", "OP_EQ"); - AipNapiUtils::SetStringProperty(env, operatorEnum, "!=", "OP_NE"); - AipNapiUtils::SetStringProperty(env, operatorEnum, "<", "OP_LT"); - AipNapiUtils::SetStringProperty(env, operatorEnum, "<=", "OP_LE"); - AipNapiUtils::SetStringProperty(env, operatorEnum, ">", "OP_GT"); - AipNapiUtils::SetStringProperty(env, operatorEnum, ">=", "OP_GE"); - AipNapiUtils::SetStringProperty(env, operatorEnum, "IN", "OP_IN"); - AipNapiUtils::SetStringProperty(env, operatorEnum, "NOT_IN", "OP_NOT_IN"); - AipNapiUtils::SetStringProperty(env, operatorEnum, "BETWEEN", "OP_BETWEEN"); - AipNapiUtils::SetStringProperty(env, operatorEnum, "LIKE", "OP_LIKE"); - AipNapiUtils::SetStringProperty(env, operatorEnum, "NOT_LIKE", "OP_NOT_LIKE"); - AipNapiUtils::SetPropertyName(env, exports, "Operator", operatorEnum); - - napi_value rerankTypeEnum; - status = napi_create_object(env, &rerankTypeEnum); - LOG_ERROR_RETURN(status == napi_ok, "create napi object fail.", napi_invalid_arg); - AipNapiUtils::SetInt32Property(env, rerankTypeEnum, TsRerankType::RRF, "RRF"); - AipNapiUtils::SetInt32Property(env, rerankTypeEnum, TsRerankType::FUSION_SCORE, "FUSION_SCORE"); - AipNapiUtils::SetPropertyName(env, exports, "RerankType", rerankTypeEnum); - - napi_value similarityLevelEnum; - status = napi_create_object(env, &similarityLevelEnum); - LOG_ERROR_RETURN(status == napi_ok, "create napi object fail.", napi_invalid_arg); - AipNapiUtils::SetInt32Property(env, similarityLevelEnum, TsSimilarityLevel::LOW, "LOW"); - AipNapiUtils::SetInt32Property(env, similarityLevelEnum, TsSimilarityLevel::MEDIUM, "MEDIUM"); - AipNapiUtils::SetInt32Property(env, similarityLevelEnum, TsSimilarityLevel::HIGH, "HIGH"); - AipNapiUtils::SetPropertyName(env, exports, "SimilarityLevel", similarityLevelEnum); - return napi_ok; -} - -napi_value RetrievalNapi::Init(napi_env env, napi_value exports) -{ - AIP_HILOGI("Init retrieval start."); - napi_property_descriptor desc[] = { - DECLARE_NAPI_FUNCTION("getRetriever", GetRetriever), - }; - napi_status status = napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); - if (status != napi_ok) { - AIP_HILOGE("define properties fail, status = %{public}d", status); - return nullptr; - } - status = InitEnum(env, exports); - LOG_ERROR_RETURN(status == napi_ok, "InitEnum fail.", nullptr); - return exports; -} - -napi_value RetrievalNapi::GetRetriever(napi_env env, napi_callback_info info) -{ - AIP_HILOGD("Enter"); - napi_value args[1] = { nullptr }; - size_t argc = 1; - napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - if (status != napi_ok) { - ThrowIntelligenceErr(env, INNER_ERROR, "napi_get_cb_info failed."); - return nullptr; - } - RetrievalConfigStruct retrievalConfig; - status = AipNapiUtils::Convert2Value(env, args[0], retrievalConfig); - if (status != napi_ok) { - ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Parse RetrievalConfig type failed."); - return nullptr; - } - napi_value promise = nullptr; - napi_deferred deferred = nullptr; - status = napi_create_promise(env, &deferred, &promise); - if (status != napi_ok) { - ThrowIntelligenceErr(env, INNER_ERROR, "create promise failed"); - return nullptr; - } - auto asyncGetRetriever = new AsyncGetRetriever{ - .asyncWork = nullptr, - .deferred = deferred, - .config = retrievalConfig, - }; - if (!CreateAsyncGetRetrieverExecution(env, asyncGetRetriever)) { - ThrowIntelligenceErr(env, INNER_ERROR, "create AsyncGetRetrieverExecution failed"); - delete asyncGetRetriever; - return nullptr; - } - return promise; -} - -bool RetrievalNapi::CreateAsyncGetRetrieverExecution(napi_env env, AsyncGetRetriever *asyncGetRetriever) -{ - AIP_HILOGD("Enter"); - napi_value resourceName; - napi_status status = napi_create_string_utf8(env, "GetRetriever", NAPI_AUTO_LENGTH, &resourceName); - if (status != napi_ok) { - AIP_HILOGE(" napi_create_string_utf8 failed."); - return false; - } - status = napi_create_async_work(env, nullptr, resourceName, GetRetrieverExecutionCB, GetRetrieverCompleteCB, - static_cast<void *>(asyncGetRetriever), &asyncGetRetriever->asyncWork); - if (status != napi_ok) { - AIP_HILOGE("napi_create_async_work failed."); - return false; - } - status = napi_queue_async_work_with_qos(env, asyncGetRetriever->asyncWork, napi_qos_default); - if (status != napi_ok) { - AIP_HILOGE("napi_queue_async_work_with_qos failed"); - return false; - } - return true; -} - -napi_value RetrievalNapi::WrapAipCoreManager(napi_env env, IAipCoreManager *retrievalAipCoreManager) -{ - napi_value result; - napi_status status = napi_create_object(env, &result); - if (status != napi_ok) { - return nullptr; - } - status = napi_wrap( - env, result, static_cast<void *>(retrievalAipCoreManager), - [](napi_env env, void *data, void *hint) { delete static_cast<IAipCoreManager *>(data); }, nullptr, nullptr); - if (status != napi_ok) { - AIP_HILOGE("napi_wrap aipCoreMangager failed, erroCode is %{public}d", status); - delete retrievalAipCoreManager; - return nullptr; - } - // 为 Retriever 对象添加 retrieve 方法 - napi_value retrieveFn; - status = napi_create_function(env, nullptr, NAPI_AUTO_LENGTH, Retrieve, nullptr, &retrieveFn); - if (status != napi_ok) { - return nullptr; - } - status = napi_set_named_property(env, result, "retrieveRdb", retrieveFn); - if (status != napi_ok) { - return nullptr; - } - return result; -} - -void RetrievalNapi::GetRetrieverExecutionCB(napi_env env, void *data) -{ - AIP_HILOGD("Enter"); - AsyncGetRetriever *asyncGetRetrieverdata = static_cast<AsyncGetRetriever *>(data); - auto config = asyncGetRetrieverdata->config; - IAipCoreManager *retrievalAipCoreManager = nullptr; - if (retrievalAipCoreMgrHandle_.create == nullptr) { - AipNapiUtils::LoadAlgoLibrary(AIP_MANAGER_PATH, retrievalAipCoreMgrHandle_, false); - } - if (retrievalAipCoreMgrHandle_.create != nullptr) { - AIP_HILOGI("Init retrieval by dlopen."); - retrievalAipCoreManager = retrievalAipCoreMgrHandle_.create(); - } - if (retrievalAipCoreManager == nullptr) { - AIP_HILOGI("Init retrieval by new."); - retrievalAipCoreManager = new IAipCoreManagerImpl(); - } - int32_t ret = retrievalAipCoreManager->InitRetriever(config); - asyncGetRetrieverdata->ret = ret; - if (ret != ERR_OK) { - AIP_HILOGE("init Retriever failed, erroCode is %{public}d", ret); - delete retrievalAipCoreManager; - return; - } - asyncGetRetrieverdata->retrievalAipCoreManagerPtr = retrievalAipCoreManager; -} - -void RetrievalNapi::GetRetrieverCompleteCB(napi_env env, napi_status status, void *data) -{ - AIP_HILOGD("Enter"); - AsyncGetRetriever *asyncGetRetrieverdata = static_cast<AsyncGetRetriever *>(data); - auto ret = asyncGetRetrieverdata->ret; - napi_value result = nullptr; - if (ret != ERR_OK) { - if (ret == DEVICE_EXCEPTION) { - ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "GetRetrieverCompleteCB failed", result); - } else { - ThrowIntelligenceErrByPromise(env, INNER_ERROR, "GetRetrieverCompleteCB failed", result); - } - napi_reject_deferred(env, asyncGetRetrieverdata->deferred, result); - } else { - result = WrapAipCoreManager(env, asyncGetRetrieverdata->retrievalAipCoreManagerPtr); - if (result == nullptr) { - ThrowIntelligenceErrByPromise(env, INNER_ERROR, "GetRetrieverCompleteCB failed", result); - napi_reject_deferred(env, asyncGetRetrieverdata->deferred, result); - } - status = napi_resolve_deferred(env, asyncGetRetrieverdata->deferred, result); - if (status != napi_ok) { - AIP_HILOGE(" napi_resolve_deferred failed"); - } - } - status = napi_delete_async_work(env, asyncGetRetrieverdata->asyncWork); - if (status != napi_ok) { - AIP_HILOGE("napi_delete_async_work failed"); - } - delete asyncGetRetrieverdata; -} - -bool RetrievalNapi::CreateAsyncRetrieveExecution(napi_env env, AsyncRetrieve *asyncRetrieve) -{ - AIP_HILOGD("Enter"); - napi_value resourceName; - napi_status status = napi_create_string_utf8(env, "Retrieve", NAPI_AUTO_LENGTH, &resourceName); - if (status != napi_ok) { - AIP_HILOGE(" napi_create_string_utf8 failed."); - return false; - } - - status = napi_create_async_work(env, nullptr, resourceName, RetrieveExecutionCB, RetrieveCompleteCB, - static_cast<void *>(asyncRetrieve), &asyncRetrieve->asyncWork); - if (status != napi_ok) { - AIP_HILOGE("napi_create_async_work failed"); - return false; - } - - status = napi_queue_async_work_with_qos(env, asyncRetrieve->asyncWork, napi_qos_default); - if (status != napi_ok) { - AIP_HILOGE("napi_queue_async_work_with_qos failed"); - return false; - } - return true; -} - -void RetrievalNapi::RetrieveExecutionCB(napi_env env, void *data) -{ - AIP_HILOGD("Enter"); - AsyncRetrieve *asyncRetrieve = static_cast<AsyncRetrieve *>(data); - auto retrievalCondition = asyncRetrieve->retrievalCondition; - auto query = asyncRetrieve->query; - auto retrievalAipCoreManagerPtr = asyncRetrieve->retrievalAipCoreManagerPtr; - RetrievalResponseStruct retrievalResponse; - int32_t result = retrievalAipCoreManagerPtr->Retrieve(query, retrievalCondition, retrievalResponse); - AIP_HILOGI("execute retrieve."); - asyncRetrieve->ret = result; - asyncRetrieve->retrievalResponse = retrievalResponse; -} - -void RetrievalNapi::RetrieveCompleteCB(napi_env env, napi_status status, void *data) -{ - AIP_HILOGD("Enter"); - AsyncRetrieve *asyncRetrieve = static_cast<AsyncRetrieve *>(data); - auto ret = asyncRetrieve->ret; - napi_value result = nullptr; - if (ret != ERR_OK) { - if (ret == DEVICE_EXCEPTION) { - ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "GetRetrieverCompleteCB failed", result); - } else { - int32_t errCode = ConvertErrCodeNative2Ts(ret); - ThrowIntelligenceErrByPromise(env, errCode, "GetRetrieverCompleteCB failed", result); - } - napi_reject_deferred(env, asyncRetrieve->deferred, result); - } else { - status = AipNapiUtils::Convert2JSValue(env, asyncRetrieve->retrievalResponse, result); - if (status != napi_ok) { - ThrowIntelligenceErrByPromise(env, INNER_ERROR, "convert RetrievalResponse to js value failed.", result); - napi_reject_deferred(env, asyncRetrieve->deferred, result); - } else { - napi_resolve_deferred(env, asyncRetrieve->deferred, result); - } - } - status = napi_delete_async_work(env, asyncRetrieve->asyncWork); - if (status != napi_ok) { - AIP_HILOGE("napi_delete_async_work failed."); - } - delete asyncRetrieve; -} - - -napi_value RetrievalNapi::Retrieve(napi_env env, napi_callback_info info) -{ - AIP_HILOGI("Retrieve being call."); - napi_value args[2] = { nullptr }; - size_t argc = 2; - napi_value jsThis = nullptr; - napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr); - if (status != napi_ok) { - ThrowIntelligenceErr(env, INNER_ERROR, "napi_get_cb_info failed."); - return nullptr; - } - std::string query; - status = AipNapiUtils::Convert2Value(env, args[0], query); - if (status != napi_ok) { - ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Failed to convert the field query."); - return nullptr; - } - RetrievalConditionStruct retrievalCondition; - status = AipNapiUtils::Convert2Value(env, args[1], retrievalCondition); - if (status != napi_ok) { - ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Parse RetrievalCondition failed."); - return nullptr; - } - napi_value promise = nullptr; - napi_deferred deferred = nullptr; - status = napi_create_promise(env, &deferred, &promise); - if (status != napi_ok) { - ThrowIntelligenceErr(env, INNER_ERROR, "create promise failed."); - return nullptr; - } - IAipCoreManager *retrievalAipCoreManagerPtr; - status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&retrievalAipCoreManagerPtr)); - if (status != napi_ok) { - return nullptr; - } - auto asyncRetrieve = new AsyncRetrieve{ - .asyncWork = nullptr, - .deferred = deferred, - .query = query, - .retrievalCondition = retrievalCondition, - .retrievalAipCoreManagerPtr = retrievalAipCoreManagerPtr - }; - if (!CreateAsyncRetrieveExecution(env, asyncRetrieve)) { - ThrowIntelligenceErr(env, INNER_ERROR, "CreateAsyncRetrieveExecution failed"); - delete asyncRetrieve; - } - return promise; -} -} // namespace DataIntelligence -} // namespace OHOS diff --git a/udmf/framework/jskitsimpl/intelligence/text_embedding_napi.cpp b/udmf/framework/jskitsimpl/intelligence/text_embedding_napi.cpp index 4c7080739c15cff10ce0a884bf81e98c75401f82..fd0b961e186a2cdc5ba49ede8bd2b0d8fbf13f67 100644 --- a/udmf/framework/jskitsimpl/intelligence/text_embedding_napi.cpp +++ b/udmf/framework/jskitsimpl/intelligence/text_embedding_napi.cpp @@ -102,6 +102,7 @@ TextEmbeddingNapi::~TextEmbeddingNapi() AIP_HILOGI("Enter"); AipNapiUtils::UnLoadAlgoLibrary(textAipCoreMgrHandle_); delete textAipCoreManager_; + textAipCoreManager_ = nullptr; } static napi_value StartInit(napi_env env, napi_value exports, struct TextEmbeddingConstructorInfo info) @@ -151,7 +152,7 @@ napi_value TextEmbeddingNapi::Init(napi_env env, napi_value exports) if (textAipCoreMgrHandle_.pAipManager != nullptr) { textAipCoreManager_ = AipNapiUtils::GetAlgoObj(textAipCoreMgrHandle_); } else { - textAipCoreManager_ = new IAipCoreManagerImpl(); + textAipCoreManager_ = new (std::nothrow) IAipCoreManagerImpl(); } if (textAipCoreManager_ == nullptr) { @@ -258,11 +259,16 @@ napi_value TextEmbeddingNapi::GetTextEmbeddingModel(napi_env env, napi_callback_ return nullptr; } - auto asyncGetTextEmbeddingModelData = new AsyncGetTextEmbeddingModelData{ + auto asyncGetTextEmbeddingModelData = new (std::nothrow) AsyncGetTextEmbeddingModelData{ .asyncWork = nullptr, .deferred = deferred, .config = textModelConfig, }; + if (asyncGetTextEmbeddingModelData == nullptr) { + AIP_HILOGE("new asyncGetTextEmbeddingModelData error."); + ThrowIntelligenceErr(env, INNER_ERROR, "new asyncGetTextEmbeddingModelData failed"); + return nullptr; + } if (!CreateAsyncTextModelExecution(env, asyncGetTextEmbeddingModelData)) { ThrowIntelligenceErr(env, PARAM_EXCEPTION, "create AsyncTextModelExecution failed"); @@ -285,7 +291,9 @@ bool TextEmbeddingNapi::ParseModelConfig(napi_env env, napi_value *args, size_t return false; } - napi_value version, isNPUAvailable, cachePath; + napi_value version; + napi_value isNPUAvailable; + napi_value cachePath; napi_status status = napi_get_named_property(env, args[ARG_0], "version", &version); if (status != napi_ok) { AIP_HILOGE("napi get version property failed"); @@ -397,6 +405,7 @@ void TextEmbeddingNapi::GetTextEmbeddingModelCompleteCB(napi_env env, napi_statu if (status != napi_ok) { AIP_HILOGE("napi_new_instance failed"); napi_get_undefined(env, &result); + delete modelData; return; } @@ -451,10 +460,6 @@ napi_value TextEmbeddingNapi::SplitText(napi_env env, napi_callback_info info) AipNapiUtils::TransJsToDouble(env, cfgOverlap, configOverlap); AIP_HILOGD("string strArg: %{public}d", configSize); AIP_HILOGD("string strArg: %{public}f", configOverlap); - if (configSize <= NUM_0 || configOverlap < NUM_0 || configOverlap >= NUM_1) { - ThrowIntelligenceErr(env, PARAM_EXCEPTION, "The parameter value range is incorrect"); - return nullptr; - } napi_value promise = nullptr; napi_deferred deferred = nullptr; @@ -464,6 +469,17 @@ napi_value TextEmbeddingNapi::SplitText(napi_env env, napi_callback_info info) return nullptr; } + if (!textAipCoreManager_->CheckDeviceType()) { + napi_value value = nullptr; + ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "SplitText failed", value); + napi_reject_deferred(env, deferred, value); + return promise; + } + if (configSize <= NUM_0 || configOverlap < NUM_0 || configOverlap >= NUM_1) { + ThrowIntelligenceErr(env, PARAM_EXCEPTION, "The parameter value range is incorrect"); + return nullptr; + } + if (!SplitTextAsyncExecution(env, deferred, strArg, configSize, configOverlap)) { ThrowIntelligenceErr(env, PARAM_EXCEPTION, "create split text async execution failed"); return nullptr; @@ -476,13 +492,17 @@ bool TextEmbeddingNapi::SplitTextAsyncExecution(napi_env env, napi_deferred defe int32_t configSize, double configOverlap) { AIP_HILOGD("Enter"); - auto splitTextCallbackData = new SplitTextCallbackData{ + auto splitTextCallbackData = new (std::nothrow) SplitTextCallbackData{ .asyncWork = nullptr, .deferred = deferred, .strArg = strArg, .configSize = configSize, .configOverlap = configOverlap, }; + if (splitTextCallbackData == nullptr) { + AIP_HILOGE("new splitTextCallbackData error."); + return false; + } napi_value resourceName; napi_status status = napi_create_string_utf8(env, "SplitText", NAPI_AUTO_LENGTH, &resourceName); @@ -610,6 +630,10 @@ napi_value TextEmbeddingNapi::GetEmbedding(napi_env env, napi_callback_info info ThrowIntelligenceErr(env, INNER_ERROR, "napi_get_cb_info failed"); return nullptr; } + if (valueType == napi_undefined || valueType == napi_null) { + ThrowIntelligenceErr(env, PARAM_EXCEPTION, "param is error"); + return nullptr; + } if (valueType == napi_string) { StringType(env, args[ARG_0], promise, deferred); } @@ -627,8 +651,6 @@ napi_value TextEmbeddingNapi::StringType(napi_env env, napi_value args, napi_val ThrowIntelligenceErr(env, PARAM_EXCEPTION, "TransJsToStr failed"); return nullptr; } - - AIP_HILOGI("string Arg: %{public}s", strArg.c_str()); if (!GetEmbeddingStringAsyncExecution(env, deferred, strArg)) { ThrowIntelligenceErr(env, INNER_ERROR, "GetEmbeddingStringAsyncExecution failed"); return nullptr; @@ -640,11 +662,15 @@ napi_value TextEmbeddingNapi::StringType(napi_env env, napi_value args, napi_val bool TextEmbeddingNapi::GetEmbeddingStringAsyncExecution(napi_env env, napi_deferred deferred, std::string strArg) { AIP_HILOGD("Enter"); - auto textStringCallbackData = new TextStringCallbackData{ + auto textStringCallbackData = new (std::nothrow) TextStringCallbackData{ .asyncWork = nullptr, .deferred = deferred, .strArg = strArg, }; + if (textStringCallbackData == nullptr) { + AIP_HILOGE("new textStringCallbackData error."); + return false; + } napi_value resourceName; napi_status status = napi_create_string_utf8(env, "textStringEmbedding", NAPI_AUTO_LENGTH, &resourceName); @@ -786,11 +812,15 @@ bool TextEmbeddingNapi::GetEmbeddingArrayAsyncExecution(napi_env env, napi_defer std::vector<std::string> text) { AIP_HILOGD("Enter"); - auto textArrayCallbackData = new TextArrayCallbackData{ + auto textArrayCallbackData = new (std::nothrow) TextArrayCallbackData{ .asyncWork = nullptr, .deferred = deferred, .text = text, }; + if (textArrayCallbackData == nullptr) { + AIP_HILOGE("new textArrayCallbackData error."); + return false; + } napi_value resourceName; napi_status status = napi_create_string_utf8(env, "textArrayEmbedding", NAPI_AUTO_LENGTH, &resourceName); @@ -919,10 +949,14 @@ napi_value TextEmbeddingNapi::LoadModel(napi_env env, napi_callback_info info) bool TextEmbeddingNapi::LoadAsyncExecution(napi_env env, napi_deferred deferred) { AIP_HILOGD("Enter"); - auto loadCallbackData = new LoadCallbackData{ + auto loadCallbackData = new (std::nothrow) LoadCallbackData{ .asyncWork = nullptr, .deferred = deferred, }; + if (loadCallbackData == nullptr) { + AIP_HILOGE("new loadCallbackData error."); + return false; + } napi_value resourceName; napi_status status = napi_create_string_utf8(env, "textLoad", NAPI_AUTO_LENGTH, &resourceName); @@ -1030,10 +1064,14 @@ napi_value TextEmbeddingNapi::ReleaseModel(napi_env env, napi_callback_info info bool TextEmbeddingNapi::ReleaseAsyncExecution(napi_env env, napi_deferred deferred) { AIP_HILOGD("Enter"); - auto releaseCallbackData = new ReleaseCallbackData{ + auto releaseCallbackData = new (std::nothrow) ReleaseCallbackData{ .asyncWork = nullptr, .deferred = deferred, }; + if (releaseCallbackData == nullptr) { + AIP_HILOGE("new releaseCallbackData error."); + return false; + } napi_value resourceName; napi_status status = napi_create_string_utf8(env, "textLoad", NAPI_AUTO_LENGTH, &resourceName); diff --git a/relational_store/test/js/gdb/performance/src/BUILD.gn b/udmf/framework/jskitsimpl/test/BUILD.gn similarity index 68% rename from relational_store/test/js/gdb/performance/src/BUILD.gn rename to udmf/framework/jskitsimpl/test/BUILD.gn index f5bc4ca201bf1b47cb57519d85c422544732a4b7..7863903bbddbdc5c4873c82888e4eb98b2b8d452 100644 --- a/relational_store/test/js/gdb/performance/src/BUILD.gn +++ b/udmf/framework/jskitsimpl/test/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (C) 2024 Huawei Device Co., Ltd. +# Copyright (c) 2025 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,12 +13,8 @@ import("//build/test.gni") -module_output_path = "relational_store/relational_store/gdb_perf" - -ohos_js_unittest("GdbPerfJsTest") { - module_out_path = module_output_path - - hap_profile = "../config.json" - - certificate_profile = "../openharmony_sx.p7b" +group("stage_unittest") { + testonly = true + deps = [ "unittest/stage_unittest/udmf/src:stage_unittest" ] } +############################################################################### diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/AppScope/app.json b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/AppScope/app.json new file mode 100644 index 0000000000000000000000000000000000000000..af96a2e6eecb67f1ea378637246c5f0fa93180e6 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/AppScope/app.json @@ -0,0 +1,21 @@ +{ + "app":{ + "bundleName":"com.example.myapplication", + "vendor":"huawei", + "versionCode":1000000, + "versionName":"1.0.0", + "debug":false, + "icon":"", + "label":"$string:app_name", + "description":"$string:description_application", + "distributedNotificationEnabled":true, + "keepAlive":true, + "singleUser":true, + "minAPIVersion":8, + "targetAPIVersion":8, + "car":{ + "apiCompatibleVersion":8, + "singleUser":false + } + } +} diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/AppScope/resources/base/element/string.json b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..ee69f9a861d9dc269ed6638735d52674583498e1 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string":[ + { + "name":"app_name", + "value":"ohosProject" + } + ] +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/BUILD.gn b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..1fb56c20d6d2452884a9b70672cf7def421110b6 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/BUILD.gn @@ -0,0 +1,48 @@ +# Copyright (c) 2025 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/test.gni") + +ohos_js_stage_unittest("stageUdmfJsTest") { + hap_profile = "entry/src/main/module.json" + deps = [ + ":stageprejstest_js_assets", + ":stageprejstest_resources", + ] + ets2abc = true + certificate_profile = "signature/openharmony_sx.p7b" + hap_name = "stageUdmfJsTest" + subsystem_name = "distributeddatamgr" + part_name = "udmf" + module_out_path = "udmf/udmf/jsStage" +} + +ohos_app_scope("stageprejstest_app_profile") { + app_profile = "AppScope/app.json" + sources = [ "AppScope/resources" ] +} + +ohos_js_assets("stageprejstest_js_assets") { + source_dir = "entry/src/main/ets" +} + +ohos_resources("stageprejstest_resources") { + sources = [ "entry/src/main/resources" ] + deps = [ ":stageprejstest_app_profile" ] + hap_profile = "entry/src/main/module.json" +} + +group("stage_unittest") { + testonly = true + deps = [ ":stageUdmfJsTest" ] +} diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/Test.json b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/Test.json new file mode 100644 index 0000000000000000000000000000000000000000..4d5f8f18846720517f8e8905edd68f2ddac68376 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/Test.json @@ -0,0 +1,27 @@ +{ + "description": "Configuration for hjunit demo Tests", + "driver": { + "type": "OHJSUnitTest", + "test-timeout": "180000", + "bundle-name": "com.example.myapplication", + "module-name": "testModule", + "shell-timeout": "600000", + "testcase-timeout": 70000 + }, + "kits": [ + { + "test-file-name": [ + "stageUdmfJsTest.hap" + ], + "type": "AppInstallKit", + "cleanup-apps": true + }, + { + "type": "ShellKit", + "teardown-command":[ + "bm uninstall -n com.example.myapplication" + ] + } + ] +} + diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/Application/AbilityStage.ts b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/Application/AbilityStage.ts new file mode 100644 index 0000000000000000000000000000000000000000..13d01e2400b7afc26a0ff81d609390ee234269ab --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/Application/AbilityStage.ts @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 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 AbilityStage from "@ohos.app.ability.AbilityStage" + +export default class MyAbilityStage extends AbilityStage { + onCreate() { + console.log('[Demo] MyAbilityStage onCreate'); + globalThis.stageOnCreateRun = 1; + globalThis.stageContext = this.context; + } +} diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/MainAbility.ts b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/MainAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..1bb07abb4fd1ea24405be97a6cdd02b2e33a467a --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/MainAbility.ts @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 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 UIAbilit from '@ohos.app.ability.UIAbility' + +export default class MainAbility extends UIAbilit { + onCreate(want, launchParam){ + // Ability is creating, initialize resources for this ability + console.log('[Demo] MainAbility onCreate'); + globalThis.abilityWant = want; + } + + onDestroy() { + // Ability is destroying, release resources for this ability + console.log('[Demo] MainAbility onDestroy'); + } + + onWindowStageCreate(windowStage) { + // Main window is created, set main page for this ability + console.log('[Demo] MainAbility onWindowStageCreate'); + globalThis.abilityContext = this.context; + windowStage.setUIContent(this.context, "MainAbility/pages/index/index", null); + } + + onWindowStageDestroy() { + //Main window is destroyed, release UI related resources + console.log('[Demo] MainAbility onWindowStageDestroy'); + } + + onForeground() { + // Ability has brought to foreground + console.log('[Demo] MainAbility onForeground'); + } + + onBackground() { + // Ability has back to background + console.log('[Demo] MainAbility onBackground'); + } +}; \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/pages/index/index.ets b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/pages/index/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..bfe98b75da6a5dcd6b9c488c5b9d8d3e1a237af7 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/pages/index/index.ets @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025 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 router from '@ohos.router'; + +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' +import { Hypium } from '@ohos/hypium' +import testsuite from '../../../test/List.test' + + +@Entry +@Component +struct Index { + + aboutToAppear(){ + console.info("start run testcase!!!!") + var abilityDelegator: any + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var abilityDelegatorArguments: any + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + console.info('start run testcase!!!') + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) + } + + build() { + Flex({ direction:FlexDirection.Column, alignItems:ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('Hello World') + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(25) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(() => {}) + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/pages/second/second.ets b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/pages/second/second.ets new file mode 100644 index 0000000000000000000000000000000000000000..d2571b129880ecd8dd18552726bb3971c71f9f5c --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/pages/second/second.ets @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 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 router from '@system.router'; + +@Entry +@Component +struct Second { + private content: string = "Second Page" + + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text(`${this.content}`) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('back to index') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(() => { + router.back() + }) + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestAbility/TestAbility.ts b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestAbility/TestAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..97971945848414ef50f7e1afa57d38c049f02a16 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestAbility/TestAbility.ts @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 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. + */ +//OpenHarmary\vendor\unionman\unionpi_tiger\sample\app\distra-game\entry\src\ohosTest\ets\testability\TestAbility.ets +import UIAbility from '@ohos.app.ability.UIAbility' + +export default class TestAbility extends UIAbility { + onCreate(want, launchParam) { + console.log('TestAbility context' + this.context); + } + + onDestroy() { + console.log('TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage) { + console.log('TestAbility onWindowStageCreate'); + windowStage.setUIContent(this.context, 'TestAbility/pages/index', null); + } + + onWindowStageDestroy() { + console.log('TestAbility onWindowStageDestroy'); + } + + onForeground() { + console.log('TestAbility onForeground'); + } + + onBackground() { + console.log('TestAbility onBackground'); + } +}; \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestAbility/pages/index.ets b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestAbility/pages/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..84a0667e0a652c68289cb2aea6859f4bb4f52d29 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestAbility/pages/index.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 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 router from '@ohos.router'; + +@Entry +@Component +struct Index { + aboutToAppear() { + console.info('TestAbility index aboutToAppear') + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + } + .type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ }) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts new file mode 100644 index 0000000000000000000000000000000000000000..cc360f1a2d816b324efc9bba982d171d5c0a7b89 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2025 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 TestRunner from '@ohos.application.testRunner' +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +function translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s it', + '-s level', '-s testType', '-s size', '-s timeout' + ]) + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams = `${targetParams} ${key} ${parameters[key]}` + } + } + return targetParams.trim() +} + +async function onAbilityCreateCallback() { + console.log('onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + console.info('addAbilityMonitorCallback : ' + JSON.stringify(err)); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + console.info("OpenHarmonyTestRunner OnPrepare "); + } + + async onRun() { + console.log('OpenHarmonyTestRunner onRun run') + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.MainAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a com.example.myapplication.MainAbility' + ' -b ' + abilityDelegatorArguments.bundleName + cmd += ' '+translateParamsToString(abilityDelegatorArguments.parameters) + console.info('cmd : '+ cmd) + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + console.info('executeShellCommand : err : ' + JSON.stringify(err)); + console.info('executeShellCommand : data : ' + d.stdResult); + console.info('executeShellCommand : data : ' + d.exitCode); + }) + console.info('OpenHarmonyTestRunner onRun end'); + } +}; \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/List.test.ets b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..59fd8ce7c290874ac422521850b873aa32c579d4 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/List.test.ets @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2025 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 stageUdmfCallBackTest from './StageUdmfCallBacktest.ets'; +import stageUdmfPromiseTest from './StageUdmfPromisetest.ets'; +import StageUdmfFileMangerTest from './StageUdmfFileMangertest.ets'; + +export default function testsuite() { + stageUdmfCallBackTest(); + stageUdmfPromiseTest(); + StageUdmfFileMangerTest(); +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfCallBacktest.ets b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfCallBacktest.ets new file mode 100644 index 0000000000000000000000000000000000000000..228cc65ef2e708195e416d01e9aadeab7434ab60 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfCallBacktest.ets @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' +import unifiedDataChannel from '@ohos.data.unifiedDataChannel'; +import uniformTypeDescriptor from '@ohos.data.uniformTypeDescriptor'; + +const TAG = "[udmfStageTest]" + +export default function stageUdmfCallbackJsTest() { + describe('stageUdmfCallbackJsTest', ():void =>{ + console.log(TAG + "*************Unit Test Begin*************"); + beforeAll(():void => { + console.log('stageUdmfCallbackJsTest TestAbility context' + globalThis.abilityContext); + console.info('beforeAll') + }) + afterAll(():void =>{ + console.info('afterAll') + }) + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_UnifiedDataCallbackJsAPITest_0100 + * @tc.name : unifiedDataChannel insertData callback interface test + * @tc.desc : unifiedDataChannel insertData callback interface test. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_UnifiedDataCallbackJsAPITest_0100', 0, (done) => { + let options: unifiedDataChannel.Options = {} + let plainText = new unifiedDataChannel.PlainText(); + plainText.textContent = 'this is textContent'; + let unifiedData = new unifiedDataChannel.UnifiedData(plainText); + try { + unifiedDataChannel.insertData(options, unifiedData, (err, data) => { + if (err === undefined) { + console.info(TAG + `data = ${data}, options = ${options}`); + expect(err === undefined).assertFail(); + done(); + } else { + console.error(TAG, `Failed, code is ${err.code},message is ${err.message} `); + expect(err !== null).assertFail(); + done(); + } + }) + } catch (error) { + console.error(TAG, `Failed to insertData0100 code is ${error.code},message is ${error.message} `); + expect(error.code).assertEqual('401'); + done(); + } + }); + + /** + * @tc.name UdmfTestVisibilityOwn + * @tc.desc insertData with visibility Own + * @tc.type: Function + * @tc.require: issueNumber + */ + it('UdmfTestVisibilityOwn', 1, (done) { + const TAG = 'UdmfTestVisibilityOwn:'; + console.info(TAG, 'start'); + try { + let options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.DATA_HUB, + visibility : unifiedDataChannel.Visibility.OWN_PROCESS }; + let content = "content"; + let plainText = new unifiedDataChannel.PlainText(); + plainText.textContent = content; + let unifiedData = new unifiedDataChannel.UnifiedData(plainText); + unifiedDataChannel.insertData(options, unifiedData).then((data) => { + console.info(TAG, `insert success. The key: ${data}`); + let options = { key: data }; + console.info(TAG, `query start. The options: ${JSON.stringify(options)}`); + unifiedDataChannel.queryData(options).then((data) => { + console.info(TAG, 'query success.'); + expect(data.length).assertEqual(1); + expect(data[0].getRecords()[0].textContent).assertEqual(content); + unifiedDataChannel.deleteData(options).then((data) => { + console.info(TAG, 'delete success.'); + expect(data.length).assertEqual(1); + done(); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfTestVisibilityAll + * @tc.desc insertData with visibility All + * @tc.type: Function + * @tc.require: issueNumber + */ + it('UdmfTestVisibilityAll', 1, (done) { + const TAG = 'UdmfTestVisibilityAll:'; + console.info(TAG, 'start'); + try { + let options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.DATA_HUB, + visibility : unifiedDataChannel.Visibility.ALL }; + let content = "content"; + let plainText = new unifiedDataChannel.PlainText(); + plainText.textContent = content; + let unifiedData = new unifiedDataChannel.UnifiedData(plainText); + unifiedDataChannel.insertData(options, unifiedData).then((data) => { + console.info(TAG, `insert success. The key: ${data}`); + let options = { key: data }; + console.info(TAG, `query start. The options: ${JSON.stringify(options)}`); + unifiedDataChannel.queryData(options).then((data) => { + console.info(TAG, 'query success.'); + expect(data.length).assertEqual(1); + expect(data[0].getRecords()[0].textContent).assertEqual(content); + unifiedDataChannel.deleteData(options).then((data) => { + console.info(TAG, 'delete success.'); + expect(data.length).assertEqual(1); + done(); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfTestVisibilityOther + * @tc.desc insertData with visibility other + * @tc.type: Function + * @tc.require: issueNumber + */ + it('UdmfTestVisibilityOther', 1, (done) { + const TAG = 'UdmfTestVisibilityOther:'; + console.info(TAG, 'start'); + try { + let reVisibility:unifiedDataChannel.Visibility = 5; + let options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.DATA_HUB, + visibility : reVisibility }; + let content = "content"; + let plainText = new unifiedDataChannel.PlainText(); + plainText.textContent = content; + let unifiedData = new unifiedDataChannel.UnifiedData(plainText); + unifiedDataChannel.insertData(options, unifiedData).then((data) => { + console.info(TAG, `insert success. The key: ${data}`); + let options = { key: data }; + console.info(TAG, `query start. The options: ${JSON.stringify(options)}`); + unifiedDataChannel.queryData(options).then((data) => { + console.info(TAG, 'query success.'); + expect(data.length).assertEqual(1); + expect(data[0].getRecords()[0].textContent).assertEqual(content); + unifiedDataChannel.deleteData(options).then((data) => { + console.info(TAG, 'delete success.'); + expect(data.length).assertEqual(1); + done(); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (err: BusinessError) { + console.error(TAG , err.code + err.message); + expect(err.code).assertEqual("401"); + done(); + } + console.info(TAG, 'end'); + }); + }) + console.log(TAG + "*************Unit Test End*************"); +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfFileMangertest.ets b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfFileMangertest.ets new file mode 100644 index 0000000000000000000000000000000000000000..ed5dc311afc092e1ea36b46f25ff6b615e136808 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfFileMangertest.ets @@ -0,0 +1,1348 @@ +/* + * Copyright (C) 2025 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 { describe, beforeAll, afterAll, it, expect } from '@ohos/hypium'; +import unifiedDataChannel from '@ohos.data.unifiedDataChannel'; + +const TAG = "[udmfStageTest]" + +export default function StageUdmfFileMangerTest() { + describe('StageUdmfFileMangerTest', () => { + beforeAll(() => { + console.log("*************StageUdmfFileMangerTest Test Begin*************"); + }); + + afterAll(() => { + console.log("*************StageUdmfFileMangerTest Test end*************"); + }); + + const createUnifiedData = (recordCount = 1) => { + const file = new unifiedDataChannel.File(); + file.details = { name: 'test', type: 'txt' }; + file.uri = 'schema://com.samples.test/files/test.txt'; + const unifiedData = new unifiedDataChannel.UnifiedData(file); + + for (let i = 0; i < recordCount; i++) { + const fileRecord = new unifiedDataChannel.File(); + fileRecord.details = { name: `test${i}`, type: 'txt' }; + fileRecord.uri = `schema://com.samples.test/files/test${i}.txt`; + unifiedData.addRecord(fileRecord); + } + + return unifiedData; + }; + + const testInsertData = (intention: unifiedDataChannel.Intention, testId: number, usePromise: boolean, done: Function) => { + const options: unifiedDataChannel.Options = { intention }; + const unifiedData = createUnifiedData(); + + const startTime = Date.now(); + if (usePromise) { + unifiedDataChannel.insertData(options, unifiedData) + .then(data => { + const endTime = Date.now(); + console.log(`${intention} insertData promise time: ${endTime - startTime}ms`); + console.info(`insertData succeeded, key = ${data}, testId = ${testId}`); + expect().assertTrue(); + done(); + }) + .catch(() => { + console.error(`Failed to insertData, testId = ${testId}`); + expect().assertFail(); + done(); + }); + } else { + unifiedDataChannel.insertData(options, unifiedData, (err, data) => { + const endTime = Date.now(); + console.log(`${intention} insertData callback time: ${endTime - startTime}ms`); + if (err === undefined) { + console.info(`insertData succeeded, key = ${data}, testId = ${testId}`); + expect().assertTrue(); + done(); + } else { + console.error(`Failed to insertData, testId = ${testId}, code is ${err.code}, message is ${err.message}`); + expect().assertFail(); + done(); + } + }); + } + }; + + const testQueryData = (options: unifiedDataChannel.Options, testId: number, usePromise: boolean, done: Function) => { + const startTime = Date.now(); + if (usePromise) { + unifiedDataChannel.queryData(options) + .then(data => { + const endTime = Date.now(); + console.log(`queryData promise time: ${endTime - startTime}ms`); + console.info(`queryData succeeded, size = ${data.length}, testId = ${testId}`); + expect().assertTrue(); + done(); + }) + .catch(() => { + console.error(`Failed to queryData, testId = ${testId}`); + expect().assertFail(); + done(); + }); + } else { + unifiedDataChannel.queryData(options, (err, data) => { + const endTime = Date.now(); + console.log(`queryData callback time: ${endTime - startTime}ms`); + if (err === undefined) { + console.info(`queryData succeeded, size = ${data.length}, testId = ${testId}`); + expect().assertTrue(); + done(); + } else { + console.error(`Failed to queryData, testId = ${testId}, code is ${err.code}, message is ${err.message}`); + expect().assertFail(); + done(); + } + }); + } + }; + + const testDeleteData = (options: unifiedDataChannel.Options, testId: number, usePromise: boolean, done: Function) => { + const startTime = Date.now(); + if (usePromise) { + unifiedDataChannel.deleteData(options) + .then(deletedData => { + const endTime = Date.now(); + console.log(`deleteData promise time: ${endTime - startTime}ms`); + console.info(`deleteData succeeded, testId = ${testId}, deleted ${deletedData.length} items`); + expect(deletedData.length > 0).assertTrue(); + done(); + }) + .catch(() => { + console.error(`Failed to deleteData, testId = ${testId}`); + expect().assertFail(); + done(); + }); + } else { + unifiedDataChannel.deleteData(options, (err, deletedData) => { + const endTime = Date.now(); + console.log(`deleteData callback time: ${endTime - startTime}ms`); + if (err === undefined) { + console.info(`deleteData succeeded, testId = ${testId}, deleted ${deletedData.length} items`); + expect(deletedData.length > 0).assertTrue(); + done(); + } else { + console.error(`Failed to deleteData, testId = ${testId}, code is ${err.code}, message is ${err.message}`); + expect().assertFail(); + done(); + } + }); + } + }; + + let validKey: string = ''; + const insertDataAndGetKey = (intention: unifiedDataChannel.Intention, recordCount: number, done: Function) => { + const options: unifiedDataChannel.Options = { intention }; + const unifiedData = createUnifiedData(recordCount); + + unifiedDataChannel.insertData(options, unifiedData) + .then(data => { + validKey = data; + console.info(`insertData succeeded, key = ${data}`); + done(); + }) + .catch(() => { + console.error('Failed to insertData'); + done(); + }); + }; + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_100 + * @tc.name : queryData with valid key and valid intention + * @tc.desc : Test queryData with valid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_100', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1000); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_200 + * @tc.name : queryData with valid key and invalid intention + * @tc.desc : Test queryData with valid key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_200', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: 'InvalidIntention' as unifiedDataChannel.Intention }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 200'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_300 + * @tc.name : queryData with valid key and no intention + * @tc.desc : Test queryData with valid key and no intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_300', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention : unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 300'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_400 + * @tc.name : queryData with invalid key and valid intention + * @tc.desc : Test queryData with invalid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_400', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: 'invalidKey', intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: 'invalidKey', intention : unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 400'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_InvalidKey_InvalidIntention_Test_500 + * @tc.name : queryData with invalid key and invalid intention + * @tc.desc : Test queryData with invalid key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_InvalidKey_InvalidIntention_Test_500', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: 'invalidKey', intention: 'InvalidIntention' as unifiedDataChannel.Intention }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: 'invalidKey', intention : unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 500'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_InvalidKey_NoIntention_Test_600 + * @tc.name : queryData with invalid key and no intention + * @tc.desc : Test queryData with invalid key and no intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_InvalidKey_NoIntention_Test_600', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: 'invalidKey' }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: 'invalidKey' , intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 600'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_700 + * @tc.name : queryData with no key and valid intention + * @tc.desc : Test queryData with no key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_700', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = {key:key , intention : unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 700'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_InvalidIntention_Test_800 + * @tc.name : queryData with no key and invalid intention + * @tc.desc : Test queryData with no key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_InvalidIntention_Test_800', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { intention: 'InvalidIntention' as unifiedDataChannel.Intention }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = {key:key, intention : unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 800'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_NoIntention_Test_900 + * @tc.name : queryData with no key and no intention + * @tc.desc : Test queryData with no key and no intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_NoIntention_Test_900', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = {}; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = {key:key, intention : unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 900'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_1000 + * @tc.name : queryData with valid key and valid intention + * @tc.desc : Test queryData with valid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_1000', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key:key, intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 1000'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 1000'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_1100 + * @tc.name : queryData with valid key and invalid intention + * @tc.desc : Test queryData with valid key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_1100', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key:key, intention: 'InvalidIntention' as unifiedDataChannel.Intention }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 1100'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 1100'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_1200 + * @tc.name : queryData with valid key and no intention + * @tc.desc : Test queryData with valid key and no intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_1200', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key:key }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 1200'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 1200'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_1300 + * @tc.name : queryData with invalid key and valid intention + * @tc.desc : Test queryData with invalid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_1300', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: 'invalidKey', intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + console.info('130000'); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 1300'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 1300'); + done(); + }); + }); + + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_1600 + * @tc.name : queryData with no key and valid intention + * @tc.desc : Test queryData with no key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_1600', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.DATA_HUB }; + const unifiedData = createUnifiedData(1000); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { intention: unifiedDataChannel.Intention.DATA_HUB }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length >= 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.DATA_HUB }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 1600 '); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 1600'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_InvalidIntention_Test_1700 + * @tc.name : queryData with no key and invalid intention + * @tc.desc : Test queryData with no key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_InvalidIntention_Test_1700', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.DATA_HUB }; + const unifiedData = createUnifiedData(1000); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { intention: 'InvalidIntention' as unifiedDataChannel.Intention }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.DATA_HUB }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 1700'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 1700'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_1800 + * @tc.name : queryData with valid key and valid intention + * @tc.desc : Test queryData with valid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_1800', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1000); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: validKey, intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 1800'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 1800'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_1900 + * @tc.name : queryData with valid key and invalid intention + * @tc.desc : Test queryData with valid key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_1900', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1000); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 1900'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 1900'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_2000 + * @tc.name : queryData with valid key and no intention + * @tc.desc : Test queryData with valid key and no intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_2000', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const queryOptions: unifiedDataChannel.Options = { key: key }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2000'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2000'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_2100 + * @tc.name : queryData with invalid key and valid intention + * @tc.desc : Test queryData with invalid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_2100', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: 'invalidKey', intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2100'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2100'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_2200 + * @tc.name : queryData with no key and valid intention + * @tc.desc : Test queryData with no key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_2200', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2200'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2200'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_2300 + * @tc.name : queryData with valid key and valid intention + * @tc.desc : Test queryData with valid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_2300', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2300'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2300'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_2400 + * @tc.name : queryData with valid key and invalid intention + * @tc.desc : Test queryData with valid key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_2400', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: 'InvalidIntention' as unifiedDataChannel.Intention }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2400'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2400'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_2500 + * @tc.name : queryData with valid key and no intention + * @tc.desc : Test queryData with valid key and no intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_2500', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2500'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2500'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_2600 + * @tc.name : queryData with invalid key and valid intention + * @tc.desc : Test queryData with invalid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_2600', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: 'invalidKey', intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2600'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2600'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_2700 + * @tc.name : queryData with no key and valid intention + * @tc.desc : Test queryData with no key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_2700', 0, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = {intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2700'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2700'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_2800 + * @tc.name : queryData with valid key and valid intention + * @tc.desc : Test queryData with valid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_2800', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1000); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2800'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2800'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_2900 + * @tc.name : queryData with valid key and invalid intention + * @tc.desc : Test queryData with valid key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_2900', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: 'InvalidIntention' as unifiedDataChannel.Intention }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2900'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2900'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_3000 + * @tc.name : queryData with valid key and no intention + * @tc.desc : Test queryData with valid key and no intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_3000', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 3000'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 3000'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_3100 + * @tc.name : queryData with invalid key and valid intention + * @tc.desc : Test queryData with invalid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_3100', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: 'invalidKey', intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 3100'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 3100'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_3200 + * @tc.name : queryData with no key and valid intention + * @tc.desc : Test queryData with no key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_3200', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 3200'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 3200'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_3300 + * @tc.name : queryData with valid key and valid intention + * @tc.desc : Test queryData with valid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_3300', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 3300'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 3300'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_3400 + * @tc.name : queryData with valid key and invalid intention + * @tc.desc : Test queryData with valid key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_3400', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: 'InvalidIntention' as unifiedDataChannel.Intention }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 3400'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 3400'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_3500 + * @tc.name : queryData with valid key and no intention + * @tc.desc : Test queryData with valid key and no intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_3500', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 3500'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 3500'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_3600 + * @tc.name : queryData with invalid key and valid intention + * @tc.desc : Test queryData with invalid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_3600', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: 'invalidKey', intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 3600'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 3600'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_3700 + * @tc.name : queryData with no key and valid intention + * @tc.desc : Test queryData with no key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_3700', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 3700'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 3700'); + done(); + }); + }); + }); +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfPromisetest.ets b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfPromisetest.ets new file mode 100644 index 0000000000000000000000000000000000000000..c11271f0d9ff009eb3010ad725214f21483512a2 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfPromisetest.ets @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' +import unifiedDataChannel from '@ohos.data.unifiedDataChannel'; +import uniformTypeDescriptor from '@ohos.data.uniformTypeDescriptor'; + +const TAG = "[udmfStageTest]" + +export default function stageUdmfPromiseJsTest() { + describe('stageUdmfPromiseJsTest', function () { + console.log(TAG + "*************Unit Test Begin*************"); + beforeAll(function() { + console.log('stageUdmfPromiseJsTest TestAbility context' + globalThis.abilityContext); + console.info('beforeAll') + }) + afterAll(async function () { + console.info('afterAll'); + }) + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_UnifiedDataPromiseJsAPITest_0100 + * @tc.name : unifiedDataChannel insertData promise interface test + * @tc.desc : unifiedDataChannel insertData promise interface test. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_UnifiedDataPromiseJsAPITest_0100', 0, (done) => { + let options: unifiedDataChannel.Options = {} + let plainText = new unifiedDataChannel.PlainText(); + plainText.textContent = 'this is textContent'; + let unifiedData = new unifiedDataChannel.UnifiedData(plainText); + try { + unifiedDataChannel.insertData(options, unifiedData).then((data) => { + console.info(TAG + `data = ${data}, options = ${options}`); + expect().assertFail(); + done(); + }).catch((err:BusinessError) => { + console.error(TAG, `Failed, code is ${err.code},message is ${err.message} `); + expect(err !== null).assertFail(); + done(); + }) + } catch (error) { + console.error(TAG, `Failed to insertData0100 code is ${error.code},message is ${error.message} `); + expect(error.code).assertEqual('401'); + done(); + } + }) + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/js/gdb/performance/config.json b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/module.json similarity index 34% rename from relational_store/test/js/gdb/performance/config.json rename to udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/module.json index 2f09d1d4672a27ca6a23a2398a27cccebc1612ed..f61b9af00556711eeb0a9ba08be44cd493d9f4c2 100644 --- a/relational_store/test/js/gdb/performance/config.json +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/module.json @@ -1,62 +1,51 @@ { - "app": { - "bundleName": "com.example.myapplication", - "vendor": "example", - "version": { - "code": 1, - "name": "1.0" - }, - "apiVersion": { - "compatible": 4, - "target": 5 - } - }, - "deviceConfig": {}, "module": { - "package": "com.example.myapplication", - "name": ".MyApplication", - "deviceType": [ + "name": "testModule", + "type": "entry", + "srcEntrance": "./ets/Application/AbilityStage.ts", + "description": "$string:testModule_entry_dsc", + "mainElement": "com.example.myapplication.MainAbility", + "deviceTypes": [ + "default", "tablet", "2in1", - "default", "phone" ], - "distro": { - "deliveryWithInstall": true, - "moduleName": "entry", - "moduleType": "entry" - }, + "deliveryWithInstall": true, + "installationFree": false, + "uiSyntax": "ets", + "pages": "$profile:main_pages", + "metadata": [ + { + "name": "ArkTSPartialUpdate", + "value": "false" + }, + { + "name": "MetaData1", + "value": "MetaDataValue", + "resource": "$profile:shortcuts_config" + } + ], "abilities": [ { + "name": "com.example.myapplication.MainAbility", + "srcEntrance": "./ets/MainAbility/MainAbility.ts", + "description": "$string:testModule_entry_main", + "icon": "", + "label": "$string:entry_label", "visible": true, + "launchType": "singleton", + "orientation": "portrait", "skills": [ { - "entities": [ - "entity.system.home" - ], "actions": [ "action.system.home" + ], + "entities":[ + "entity.system.home" ] } - ], - "name": "com.example.myapplication.MainAbility", - "icon": "$media:icon", - "description": "$string:mainability_description", - "label": "MyApplication", - "type": "page", - "launchType": "standard" - } - ], - "js": [ - { - "pages": [ - "pages/index/index" - ], - "name": "default", - "window": { - "designWidth": 720, - "autoDesignWidth": false - } + ] } ] } diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/element/string.json b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..fe90aac09d200757fe4a6d4a0f4a109ae47719cb --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/element/string.json @@ -0,0 +1,24 @@ +{ + "string": [ + { + "name": "testModule_entry_dsc", + "value": "i am an entry for testModule" + }, + { + "name": "testModule_entry_main", + "value": "the testModule entry ability" + }, + { + "name": "entry_label", + "value": "stagePreferencesJsTest" + }, + { + "name": "description_application", + "value": "demo for test" + }, + { + "name": "app_name", + "value": "Demo" + } + ] +} diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/form_config.json b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/form_config.json new file mode 100644 index 0000000000000000000000000000000000000000..e892d44722d9e5b09ff78cb069ccc15d1fac872e --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/form_config.json @@ -0,0 +1,6 @@ +{ + "src": [ + "MainAbility/pages/index/index", + "MainAbility/pages/second/second" + ] +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/form_config1.txt b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/form_config1.txt new file mode 100644 index 0000000000000000000000000000000000000000..32f9ff7dc213b28017875b2e4679071350a74d1d --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/form_config1.txt @@ -0,0 +1 @@ +{"src": ["MainAbility/pages/index/index","MainAbility/pages/second/second"]} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/main_pages.json b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..02221db61d317863114ff0ca4dd2b33586abff12 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,6 @@ +{ + "src": [ + "MainAbility/pages/index/index", + "MainAbility/pages/second/second" + ] +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/shortcuts_config.json b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/shortcuts_config.json new file mode 100644 index 0000000000000000000000000000000000000000..02221db61d317863114ff0ca4dd2b33586abff12 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/shortcuts_config.json @@ -0,0 +1,6 @@ +{ + "src": [ + "MainAbility/pages/index/index", + "MainAbility/pages/second/second" + ] +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/signature/openharmony_sx.p7b b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/signature/openharmony_sx.p7b new file mode 100644 index 0000000000000000000000000000000000000000..2fac054162b97eb332cb3074f30f216db6701d27 Binary files /dev/null and b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/signature/openharmony_sx.p7b differ diff --git a/udmf/framework/jskitsimpl/unittest/AipRdbJsTest.js b/udmf/framework/jskitsimpl/unittest/AipRdbJsTest.js deleted file mode 100644 index aac1fe6b04e4205619dac8d7d0f429cc22072e82..0000000000000000000000000000000000000000 --- a/udmf/framework/jskitsimpl/unittest/AipRdbJsTest.js +++ /dev/null @@ -1,981 +0,0 @@ -/* - * Copyright (c) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index'; -import intelligence from '@ohos.data.intelligence'; -import deviceInfo from '@ohos.deviceInfo'; -import relationalStore from '@ohos.data.relationalStore'; -import featureAbility from '@ohos.ability.featureAbility'; - -const TAG = '[AipIntelligenceJSTest]'; - -let currentDeviceIsPc = false; -let context = featureAbility.getContext(); -let rdbStore1 = undefined; -let rdbStore2 = undefined; - -let storeConfigInvalid = { - name: '', - securityLevel: relationalStore.SecurityLevel.S1 -}; - -let channelConfigInvalid = { - channelType: 0, - context:context, - dbConfig:storeConfigInvalid -}; - -let storeConfigVector = { - name: 'rdb_store_test.db', - encrypt: false, - securityLevel: relationalStore.SecurityLevel.S3, - autoCleanDirtyData: false, - isSearchable: false, - vector: true, - allowRebuild: false -}; - -let storeConfigInvIdx = { - name: 'sqlite_store_test.db', - encrypt: false, - securityLevel: relationalStore.SecurityLevel.S3, - autoCleanDirtyData: false, - isSearchable: false, - allowRebuild: false, - tokenizer: 2 -}; - -let channelConfigVector = { - channelType: intelligence.ChannelType.VECTOR_DATABASE, - context:context, - dbConfig:storeConfigVector -}; - -let channelConfigInvIdx = { - channelType: intelligence.ChannelType.INVERTED_INDEX_DATABASE, - context:context, - dbConfig:storeConfigInvIdx -}; - -describe('AipJSTest', function () { - - beforeAll(async function () { - console.info(TAG + 'beforeAll'); - let deviceTypeInfo = deviceInfo.deviceType; - currentDeviceIsPc = deviceTypeInfo === '2in1' ? true : false; - console.info(TAG + 'the value of the deviceType is : ' + deviceInfo.deviceType); - relationalStore.deleteRdbStore(context, 'rdb_store_test.db', (err) => { - if (err) { - console.error(`Delete RdbStore failed, code is ${err.code},message is ${err.message}`); - return; - } - console.info(TAG + 'Delete RdbStore successfully.'); - }); - rdbStore1 = await relationalStore.getRdbStore(context, storeConfigVector); - if (rdbStore1 !== undefined) { - let createSql = 'CREATE TABLE IF NOT EXISTS vector_table(fileid TEXT PRIMARY KEY, filename_text TEXT, filename FLOATVECTOR(128), keywords_text TEXT, keywords FLOATVECTOR(128), chapter FLOATVECTOR(128), abstract FLOATVECTOR(128));'; - await rdbStore1.execute(createSql, 0, undefined); - await insertVectorDB(); - }; - rdbStore2 = await relationalStore.getRdbStore(context, storeConfigInvIdx); - if (rdbStore2 !== undefined) { - let createSql = 'CREATE VIRTUAL TABLE IF NOT EXISTS invidx_table USING fts5(fileid, filename, keywords, chapter, abstract, content, tokenize = "customtokenizer");'; - await rdbStore2.executeSql(createSql); - await insertInvIdxDB(); - }; - }); - beforeEach(async function () { - console.info(TAG + 'beforeEach'); - }); - afterEach(async function () { - console.info(TAG + 'afterEach'); - }); - afterAll(async function () { - console.info(TAG + 'afterAll'); - }); - - async function insertVectorDB() { - let insertSQL; - for (let i = 0; i < 5; i++) { - let array = new Array(128); - for (let j = 0; j < array.length; j++) { - let randomNumber = Math.random(); - array[j] = randomNumber; - } - let data = array.toString(); - insertSQL = "INSERT INTO vector_table VALUES('" + i + "', '大模型系统概述', '[" + data + "]', '生成式AI, 人工智能, 大模型', '[" + data + "]', '[" + data + "]', '[" + data + "]');"; - console.info(TAG + 'insertVectorDB insertSQL::' + insertSQL); - await rdbStore1.execute(insertSQL, 0, undefined); - } - let arraySpecial = new Array(128).fill(0.1); - let dataSpecial = arraySpecial.toString(); - let insertSQLSpecial = "INSERT INTO vector_table VALUES('5', '大模型系统概述', '[" + dataSpecial + "]', '生成式AI, 人工智能, 大模型', '[" + dataSpecial + "]', '[" + dataSpecial + "]', '[" + dataSpecial + "]');"; - console.info(TAG + 'insertVectorDB insertSQL::' + insertSQLSpecial); - await rdbStore1.execute(insertSQLSpecial, 0, undefined); - } - - async function insertInvIdxDB() { - let insertSQL = 'INSERT INTO invidx_table VALUES("1", "大模型系统概述", "生成式AI, 人工智能, 大模型", "人工智能导论", "这是一篇关于大模型的综述文章", "这是一篇关于大模型的综述文章");'; - console.info(TAG + 'insertInvIdxDB insertSQL::' + insertSQL); - await rdbStore2.executeSql(insertSQL); - insertSQL = 'INSERT INTO invidx_table VALUES("2", "数据库在大模型时代下的发展", "数据库, 内核, 向量", "数据库导论", "这是一篇关于数据库和大模型交叉的综述文章", "这是一篇关于数据库和大模型交叉的综述文章");'; - console.info(TAG + 'insertInvIdxDB insertSQL::' + insertSQL); - await rdbStore2.executeSql(insertSQL); - insertSQL = 'INSERT INTO invidx_table VALUES("3", "社会发展报告", "旅游, 民生, 交通", "社会发展", "这是一篇关于社会发展的综述文章", "这是一篇关于社会发展的综述文章");'; - console.info(TAG + 'insertInvIdxDB insertSQL::' + insertSQL); - await rdbStore2.executeSql(insertSQL); - insertSQL = 'INSERT INTO invidx_table VALUES("4", "鸿蒙", "鸿蒙, 生态, 遥遥领先", "鸿蒙系统", "这是一篇关于鸿蒙系统的综述文章", "这是一篇关于鸿蒙系统的综述文章");'; - console.info(TAG + 'insertInvIdxDB insertSQL::' + insertSQL); - await rdbStore2.executeSql(insertSQL); - insertSQL = 'INSERT INTO invidx_table VALUES("5", "AI系统", "鸿蒙, 生态, 大模型", "AI系统", "这是一篇关于AI系统的综述文章", "这是一篇关于AI系统的综述文章");'; - console.info(TAG + 'insertInvIdxDB insertSQL::' + insertSQL); - await rdbStore2.executeSql(insertSQL); - console.info(TAG + 'insertInvIdxDB end'); - } - - async function sleep(time) { - return new Promise((resolve, reject) => { - setTimeout(() => { - resolve(); - }, time); - }).then(() => { - console.info(`sleep ${time} over...`); - }); - } - - console.log('******************************Aip API Test Begin******************************'); - - /** - * @tc.name Aip_001 - * @tc.desc Test getRetriever. rdbStoreName is empty. - * @tc.type: FUNC - */ - it('Aip_001', 0, async function (done) { - console.info(TAG, 'Aip_001 start'); - let retrievalConfig = { - channelConfigs: [channelConfigInvalid] - }; - if (currentDeviceIsPc) { - try { - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - expect(data != null).assertEqual(true); - done(); - }); - } catch (err) { - console.info(TAG, 'Aip_001 catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_002 - * @tc.desc Test getRetriever. channelConfigs is empty. - * @tc.type: FUNC - */ - it('Aip_002', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [] - }; - if (currentDeviceIsPc) { - try { - await intelligence.getRetriever(retrievalConfig); - } catch (err) { - console.info(TAG, 'Aip_002 catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - }); - - /** - * @tc.name Aip_003 - * @tc.desc Test retrieveRdb. The value of deepSize is too large. - * @tc.type: FUNC - */ - it('Aip_003', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigVector] - }; - if (currentDeviceIsPc) { - try { - let floatArray = new Float32Array(128).fill(0.1); - let vectorQuery = { - column: 'filename', - value: floatArray, - similarityThreshold: 0.1 - }; - let recallCondition = { - vectorQuery: vectorQuery, - fromClause: 'vector_table', - primaryKey: ['fileid'], - responseColumns: ['filename_text'], - filters: [], - deepSize: 1000000 - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '软件设计与建模'; - data.retrieveRdb(query, retrievalCondition) - .then((rdbdata) => { - let length = rdbdata.records.length; - console.info(TAG, 'Aip_003 get result::' + length); - let ret = length >= 0; - expect(ret).assertEqual(true); - done(); - }); - } catch (err) { - console.info(TAG, 'catch::' + err.code); - done(); - } - }); - } catch (err) { - console.info(TAG, 'catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_004 - * @tc.desc Test retrieveRdb.fromClause is empty. - * @tc.type: FUNC - */ - it('Aip_004', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigVector] - }; - if (currentDeviceIsPc) { - try { - let floatArray = new Float32Array(128).fill(0.1); - let vectorQuery = { - column: 'filename', - value: floatArray, - similarityThreshold: 0.1 - }; - let recallCondition = { - vectorQuery: vectorQuery, - fromClause: '', - primaryKey: ['fileid'], - responseColumns: ['filename_text'], - deepSize: 500 - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '软件设计与建模'; - data.retrieveRdb(query, retrievalCondition); - } catch (err) { - console.info(TAG, 'Aip_004 catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - }); - } catch (err) { - console.info(TAG, 'Aip_004 catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'catch11::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_005 - * @tc.desc Test retrieveRdb. primaryKey is empty. - * @tc.type: FUNC - */ - it('Aip_005', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigVector] - }; - if (currentDeviceIsPc) { - try { - let floatArray = new Float32Array(128).fill(0.1); - let vectorQuery = { - column: 'filename', - value: floatArray, - similarityThreshold: 0.1 - }; - let recallCondition = { - vectorQuery: vectorQuery, - fromClause: 'vector_table', - primaryKey: [], - responseColumns: ['filename_text'], - deepSize: 500 - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '软件设计与建模'; - data.retrieveRdb(query, retrievalCondition); - } catch (err) { - console.info(TAG, 'catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - }); - } catch (err) { - console.info(TAG, 'Aip_005 catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'catch11::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_006 - * @tc.desc Test retrieveRdb. responseColumns is empty. - * @tc.type: FUNC - */ - it('Aip_006', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigVector] - }; - if (currentDeviceIsPc) { - try { - let floatArray = new Float32Array(128).fill(0.1); - let vectorQuery = { - column: 'filename', - value: floatArray, - similarityThreshold: 0.1 - }; - let recallCondition = { - vectorQuery: vectorQuery, - fromClause: 'vector_table', - primaryKey: ['fileid'], - responseColumns: [], - deepSize: 500 - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '软件设计与建模'; - data.retrieveRdb(query, retrievalCondition); - } catch (err) { - console.info(TAG, 'Aip_006 catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - }); - } catch (err) { - console.info(TAG, 'catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_007 - * @tc.desc Test retrieveRdb. column is invalid. - * @tc.type: FUNC - */ - it('Aip_007', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigVector] - }; - if (currentDeviceIsPc) { - try { - let floatArray = new Float32Array(128).fill(0.1); - let vectorQuery = { - column: 'invalidField', - value: floatArray, - similarityThreshold: 0.1 - }; - let recallCondition = { - vectorQuery: vectorQuery, - fromClause: 'vector_table', - primaryKey: ['fileid'], - responseColumns: ['filename_text'], - deepSize: 500 - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '软件设计与建模'; - data.retrieveRdb(query, retrievalCondition) - .catch((err) => { - console.info(TAG, 'Aip_007 catch::' + err.code); - expect(err.code).assertEqual(31300100); - done(); - }); - } catch (err) { - console.info(TAG, 'Aip_007 catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - }); - } catch (err) { - console.info(TAG, 'catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_008 - * @tc.desc Test retrieveRdb. One-way vector normal recall. - * @tc.type: FUNC - */ - it('Aip_008', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigVector] - }; - if (currentDeviceIsPc) { - try { - let floatArray = new Float32Array(128).fill(0.1); - const str = floatArray.toString(); - console.log(TAG, str); - let vectorQuery = { - column: 'filename', - value: floatArray, - similarityThreshold: 0.1 - }; - let recallCondition = { - vectorQuery: vectorQuery, - fromClause: 'vector_table', - primaryKey: ['fileid'], - responseColumns: ['filename_text'], - deepSize: 500 - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '软件设计与建模'; - data.retrieveRdb(query, retrievalCondition) - .then((rdbdata) => { - let length = rdbdata.records.length; - console.info(TAG, 'Aip_008 get result length::' + length); - expect(length > 0).assertEqual(true); - done(); - }); - } catch (err) { - console.info(TAG, 'Aip_008 catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - }); - } catch (err) { - console.info(TAG, 'Aip_008 catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'Aip_008 catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_009 - * @tc.desc Test retrieveRdb. One-way invertedindex normal recall. - * @tc.type: FUNC - */ - it('Aip_009', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigInvIdx] - }; - if (currentDeviceIsPc) { - try { - let fieldWeight = { - 'filename': 4.0 - }; - let fieldSlops = { - 'filename': 5 - }; - let bm25Strategy = { - bm25Weight: 1.5, - columnWeight: fieldWeight - }; - let exactStrategy = { - exactMatchingWeight: 1.2, - columnWeight: fieldWeight - }; - let outOfOrderStrategy = { - proximityWeight: 1.2, - columnWeight: fieldWeight, - columnSlops: fieldSlops - }; - let invertedIndexStrategies = [bm25Strategy, exactStrategy, outOfOrderStrategy]; - let recallCondition = { - ftsTableName: 'invidx_table', - fromClause: 'invidx_table', - primaryKey: ['fileid'], - responseColumns: ['filename', 'keywords'], - deepSize: 500, - invertedIndexStrategies: invertedIndexStrategies - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - console.info(TAG, 'Aip_009 get result::' + data); - try { - let query = '数据库'; - data.retrieveRdb(query, retrievalCondition) - .then((rdbdata) => { - let length = rdbdata.records.length; - console.info(TAG, 'Aip_009 get result::' + length); - expect(length).assertEqual(1); - done(); - }); - } catch (err) { - console.info(TAG, 'Aip_009 catch::' + err.code); - done(); - } - }); - } catch (err) { - console.info(TAG, 'Aip_009 catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'Aip_009 catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_010 - * @tc.desc Test retrieveRdb. ftsTableName is empty. - * @tc.type: FUNC - */ - it('Aip_010', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigInvIdx] - }; - if (currentDeviceIsPc) { - try { - let fieldWeight = { - 'filename': 4.0 - }; - let fieldSlops = { - 'filename': 5 - }; - let bm25Strategy = { - bm25Weight: 1.5, - columnWeight: fieldWeight - }; - let exactStrategy = { - exactMatchingWeight: 1.2, - columnWeight: fieldWeight - }; - let outOfOrderStrategy = { - proximityWeight: 1.2, - columnWeight: fieldWeight, - columnSlops: fieldSlops - }; - let invertedIndexStrategies = [bm25Strategy, exactStrategy, outOfOrderStrategy]; - let recallCondition = { - ftsTableName: '', - fromClause: 'invidx_table', - primaryKey: ['fileid'], - responseColumns: ['filename', 'keywords'], - deepSize: 500, - invertedIndexStrategies: invertedIndexStrategies - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '数据库'; - data.retrieveRdb(query, retrievalCondition); - } catch (err) { - console.info(TAG, 'Aip_010 catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - }); - } catch (err) { - console.info(TAG, 'Aip_010 catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'Aip_010 catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_011 - * @tc.desc Test retrieveRdb. invertedindex match field is invalid. - * @tc.type: FUNC - */ - it('Aip_011', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigInvIdx] - }; - if (currentDeviceIsPc) { - try { - let fieldWeight = { - 'invalid': 4.0 - }; - let fieldSlops = { - 'filename': 5 - }; - let bm25Strategy = { - bm25Weight: 1.5, - columnWeight: fieldWeight - }; - let exactStrategy = { - exactMatchingWeight: 1.2, - columnWeight: fieldWeight - }; - let outOfOrderStrategy = { - proximityWeight: 1.2, - columnWeight: fieldWeight, - columnSlops: fieldSlops - }; - let invertedIndexStrategies = [bm25Strategy, exactStrategy, outOfOrderStrategy]; - let recallCondition = { - ftsTableName: 'invidx_table', - fromClause: 'invidx_table', - primaryKey: ['fileid'], - responseColumns: ['filename', 'keywords'], - deepSize: 500, - invertedIndexStrategies: invertedIndexStrategies - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '数据库'; - data.retrieveRdb(query, retrievalCondition) - .catch((err) => { - console.info(TAG, 'Aip_011 catch::' + err.code); - expect(err.code).assertEqual(31301010); - done(); - }); - } catch (err) { - console.info(TAG, 'Aip_011 catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - }); - } catch (err) { - console.info(TAG, 'Aip_011 catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'Aip_011 catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - - /** - * @tc.name Aip_012 - * @tc.desc Test retrieveRdb. Two-way normal recall. - * @tc.type: FUNC - */ - it('Aip_012', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigInvIdx, channelConfigVector] - }; - if (currentDeviceIsPc) { - try { - let fieldWeight = { - 'filename': 4.0 - }; - - let fieldSlops = { - 'filename': 5 - }; - let bm25Strategy = { - bm25Weight: 1.5, - columnWeight: fieldWeight - }; - let exactStrategy = { - exactMatchingWeight: 1.2, - columnWeight: fieldWeight - }; - let outOfOrderStrategy = { - proximityWeight: 1.2, - columnWeight: fieldWeight, - columnSlops: fieldSlops - }; - let invertedIndexStrategies = [bm25Strategy, exactStrategy, outOfOrderStrategy]; - let recallConditionInvIdx = { - ftsTableName: 'invidx_table', - fromClause: 'invidx_table', - primaryKey: ['fileid'], - responseColumns: ['filename', 'keywords'], - deepSize: 500, - invertedIndexStrategies: invertedIndexStrategies - }; - let floatArray = new Float32Array(128).fill(0.1); - let vectorQuery = { - column: 'filename', - value: floatArray, - similarityThreshold: 0.1 - }; - let recallConditionVector = { - vectorQuery: vectorQuery, - fromClause: 'vector_table', - primaryKey: ['fileid'], - responseColumns: ['filename_text'], - deepSize: 500 - }; - let retrievalCondition = { - recallConditions : [recallConditionInvIdx, recallConditionVector] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '数据库'; - data.retrieveRdb(query, retrievalCondition) - .then((rdbdata) => { - let length = rdbdata.records.length; - console.info(TAG, 'Aip_012 get result::' + length); - expect(length >= 2).assertEqual(true); - done(); - }); - } catch (err) { - console.info(TAG, 'Aip_012 catch::' + err.code); - done(); - } - }); - } catch (err) { - console.info(TAG, 'Aip_012 catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'Aip_012 catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_013 - * @tc.desc Test retrieveRdb. Two-way normal recall and configing rerankMethod. - * @tc.type: FUNC - */ - it('Aip_013', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigInvIdx, channelConfigVector] - }; - if (currentDeviceIsPc) { - try { - let fieldWeight = { - 'filename': 4.0, - 'keywords':4.0 - }; - let fieldSlops = { - 'filename': 5, - 'keywords':5 - }; - let bm25Strategy = { - bm25Weight: 1.5, - columnWeight: fieldWeight - }; - let exactStrategy = { - exactMatchingWeight: 1.2, - columnWeight: fieldWeight - }; - let outOfOrderStrategy = { - proximityWeight: 1.2, - columnWeight: fieldWeight, - columnSlops: fieldSlops - }; - let invertedIndexStrategies = [bm25Strategy, exactStrategy, outOfOrderStrategy]; - let recallConditionInvIdx = { - ftsTableName: 'invidx_table', - fromClause: 'invidx_table', - primaryKey: ['fileid'], - responseColumns: ['filename', 'keywords'], - deepSize: 500, - invertedIndexStrategies: invertedIndexStrategies - }; - let floatArray = new Float32Array(128).fill(0.1); - let vectorQuery = { - column: 'filename', - value: floatArray, - similarityThreshold: 0.1 - }; - let recallConditionVector = { - vectorQuery: vectorQuery, - fromClause: 'vector_table', - primaryKey: ['fileid'], - responseColumns: ['filename_text'], - recallName: 'vectorRecall', - deepSize: 500 - }; - let vectorWeights = { - 'vectorRecall': 1 - }; - let numberInspector = { - 'vector_query':'filename_text' - }; - let vectorRerankParameter = { - vectorWeights:vectorWeights, - thresholds: [0.55, 0.45, 0.35], - numberInspector: numberInspector - }; - let parameters = { - 0: vectorRerankParameter - }; - let rerankMethod = { - rerankType: 1, - parameters: parameters, - isSoftmaxNormalized: true, - }; - let retrievalCondition = { - rerankMethod: rerankMethod, - recallConditions : [recallConditionInvIdx, recallConditionVector] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '数据库'; - data.retrieveRdb(query, retrievalCondition) - .then((rdbdata) => { - let length = rdbdata.records.length; - console.info(TAG, 'Aip_013 get result::' + length); - expect(length >= 2).assertEqual(true); - done(); - }); - } catch (err) { - console.info(TAG, 'Aip_013 catch::' + err.code); - done(); - } - }); - } catch (err) { - console.info(TAG, 'Aip_013 catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'Aip_013 catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); -}); \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/unittest/BUILD.gn b/udmf/framework/jskitsimpl/unittest/BUILD.gn index 75bf5b1128706c64bafffdb9a724e7aba1ff3af7..0872196bfa98592bee0918efe0e5d39c0734e2c3 100644 --- a/udmf/framework/jskitsimpl/unittest/BUILD.gn +++ b/udmf/framework/jskitsimpl/unittest/BUILD.gn @@ -14,7 +14,7 @@ import("//build/test.gni") import("//foundation/distributeddatamgr/udmf/udmf.gni") -module_output_path = "udmf/jskitsimpl" +module_output_path = "udmf/udmf/jskitsimpl" ohos_js_unittest("UDMFJsTest") { module_out_path = module_output_path diff --git a/udmf/framework/jskitsimpl/unittest/UdmfIntelligenceJsTest.js b/udmf/framework/jskitsimpl/unittest/UdmfIntelligenceJsTest.js new file mode 100644 index 0000000000000000000000000000000000000000..996291a84ac0821389ac929fcded9849fd8d7b48 --- /dev/null +++ b/udmf/framework/jskitsimpl/unittest/UdmfIntelligenceJsTest.js @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2025 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index'; +import intelligence from '@ohos.data.intelligence'; +import deviceInfo from '@ohos.deviceInfo'; + +const TAG = ['Intelligence_Test']; + +let textConfig = { + version: intelligence.ModelVersion.BASIC_MODEL, + isNpuAvailable: false, + cachePath: 'test' +}; + +let imageConfig = { + version: intelligence.ModelVersion.BASIC_MODEL, + isNpuAvailable: false, + cachePath: 'image' +}; + +let currentDeviceIsPc = false; + +describe('UdmfIntelligenceJsTest', function () { + + beforeAll(async () => { + console.info(TAG + 'beforeAll'); + let deviceTypeInfo = deviceInfo.deviceType; + currentDeviceIsPc = deviceTypeInfo === '2in1' ? true : false; + console.info(TAG + 'the value of the deviceType is : ' + deviceInfo.deviceType); + }); + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + }); + afterEach(async () => { + console.info(TAG + 'afterEach'); + }); + afterAll(async () => { + console.info(TAG + 'afterAll'); + }); + + console.info('*************intelligence Test begin**************'); + let retArray = [401, 801, 313000000]; + + + /** + * @tc.name intelligenceApiTest0100 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0100 + * @tc.desc splitText interface test + * @tc.type Function + */ + it('intelligenceApiTest0100', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0100 start'); + let text = + '日常生活中,我们对接触到的事物,会产生一个不假思索地看法,或者说直觉性的认知.百科全书里这样解释道“ 认知包括感觉、知觉、记忆、思维、想象和语言等。'; + let config = { + size: 50, + overlapRatio: 0.5 + }; + if (currentDeviceIsPc) { + await intelligence.splitText(text, config) + .then((data) => { + console.info(TAG + 'get result:' + data); + let dataSize = data.length; + let ret = dataSize > 0; + expect(ret).assertEqual(true); + done(); + }); + } else { + await intelligence.splitText(text, config) + .then((data) => { + console.info(TAG + 'get result:' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'get promise result:' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest0200 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0100 + * @tc.desc getTextEmbeddingModel promise interface test + * @tc.type Function + */ + it('intelligenceApiTest0200', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0200 start'); + if (currentDeviceIsPc) { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result' + data); + let ret = false; + if (data != null) { + ret = true; + } + expect(ret).assertEqual(true); + done(); + }); + } else { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'get promise result:' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest0300 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0300 + * @tc.desc getImageEmbeddingModel promise interface test + * @tc.type Function + */ + it('intelligenceApiTest0300', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0300 start'); + if (currentDeviceIsPc) { + intelligence.getImageEmbeddingModel(imageConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + let ret = false; + if (data != null) { + ret = true; + } + expect(ret).assertEqual(true); + done(); + }); + } else { + intelligence.getImageEmbeddingModel(imageConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'get promise result:' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest0400 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0400 + * @tc.desc getTextEmbeddingModel loadModel interface test + * @tc.type Function + */ + it('intelligenceApiTest0400', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0400 start'); + if (currentDeviceIsPc) { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + data.loadModel() + .then(() => { + console.info(TAG + 'get loadMldel result 0400:'); + done(); + }); + }); + } else { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + expect().assertFail(); + }) + .catch((err) => { + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest0500 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0500 + * @tc.desc getTextEmbeddingModel loadModel interface test + * @tc.type Function + */ + it('intelligenceApiTest0500', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0500 start'); + if (currentDeviceIsPc) { + try { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + data.loadModel() + .then(() => { + console.info(TAG + 'loadModel success result 0500:'); + data.releaseModel(); + done(); + }); + }); + } catch (err) { + console.info(TAG + 'intelligenceApiTest0500 is fail:'); + expect().assertFail(); + done(); + } + } else { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'get result' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest0600 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0600 + * @tc.desc getTextEmbeddingModel releaseModel abnormal interface test + * @tc.type Function + */ + it('intelligenceApiTest0600', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0600 start'); + if (currentDeviceIsPc) { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + data.releaseModel() + .then(() => { + console.info(TAG + 'releaseModel result 0600:'); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'getEmbedding result' + err.code); + expect(err.code).assertEqual(31300000); + done(); + }); + }); + } else { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + expect().assertFail(); + }) + .catch((err) => { + console.info(TAG + 'loadModel promise result:' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest0700 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0700 + * @tc.desc getTextEmbeddingModel getEmbedding interface test + * @tc.type Function + */ + it('intelligenceApiTest0700', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0700 start'); + if (currentDeviceIsPc) { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + data.getEmbedding('123') + .then((loadData) => { + console.info(TAG + 'getEmbedding result:' + loadData); + let dataSize = loadData.length; + let ret = dataSize > 0; + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'getEmbedding result' + err.code); + expect(err.code).assertEqual(31300000); + done(); + }); + }); + } else { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + expect().assertFail(); + }) + .catch((err) => { + console.info(TAG + 'getEmbedding promise result:' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest0800 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0800 + * @tc.desc getTextEmbeddingModel getEmbedding abnormal interface test + * @tc.type Function + */ + it('intelligenceApiTest0800', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0800 start'); + if (currentDeviceIsPc) { + intelligence.getTextEmbeddingModel(textConfig) + .then(async (data) => { + console.info(TAG + 'get result:' + data); + await data.loadModel(); + let text = 'text'; + data.getEmbedding(text) + .then((loadData) => { + console.info(TAG + 'getEmbedding result 0800 :' + loadData); + let dataSize = loadData.length; + let ret = dataSize > 0; + expect(ret).assertEqual(true); + done(); + }); + }); + } else { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'getEmbedding promise result:' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest0900 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0900 + * @tc.desc getTextEmbeddingModel getEmbedding batchTexts interface test + * @tc.type Function + */ + it('intelligenceApiTest0900', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0900 start'); + if (currentDeviceIsPc) { + intelligence.getTextEmbeddingModel(textConfig) + .then(async (data) => { + console.info(TAG + 'get result: ' + data); + await data.loadModel(); + let batchTexts = ['11', '22', '33']; + data.getEmbedding(batchTexts) + .then((loadData) => { + console.info(TAG + 'getEmbedding result 0900: ' + loadData); + let dataSize = loadData.length; + let ret = dataSize > 0; + expect(ret).assertEqual(true); + done(); + }); + }); + } else { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result: ' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'getEmbedding promise result: ' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest1000 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_1000 + * @tc.desc getImageEmbeddingModel loadModel interface test + * @tc.type Function + */ + it('intelligenceApiTest1000', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest1000 start'); + if (currentDeviceIsPc) { + try { + intelligence.getImageEmbeddingModel(imageConfig) + .then((data) => { + console.info(TAG + 'get result :' + data); + data.loadModel() + .then(() => { + console.info(TAG + 'loadModel result 1000 :'); + data.releaseModel(); + done(); + }); + }); + } catch (err) { + console.info(TAG + 'intelligenceApiTest1000 is fail:'); + expect().assertFail(); + done(); + } + } else { + intelligence.getImageEmbeddingModel(imageConfig) + .then((data) => { + console.info(TAG + 'get result :' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'get promise result' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest1100 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_1100 + * @tc.desc getImageEmbeddingModel(imageConfig) releaseModel interface test + * @tc.type Function + */ + it('intelligenceApiTest1100', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest1100 start'); + if (currentDeviceIsPc) { + intelligence.getImageEmbeddingModel(imageConfig) + .then((data) => { + console.info(TAG + 'get result :' + data); + data.releaseModel() + .then(() => { + console.info(TAG + 'releaseModel result 1100 :'); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'getEmbedding result' + err.code); + expect(err.code).assertEqual(31300000); + done(); + }); + }); + } else { + intelligence.getImageEmbeddingModel(imageConfig) + .then((data) => { + console.info(TAG + 'get result :' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'get promise result' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest1200 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_1200 + * @tc.desc getImageEmbeddingModel(imageConfig) getEmbedding test interface test + * @tc.type Function + */ + it('intelligenceApiTest1200', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest1200 start'); + if (currentDeviceIsPc) { + intelligence.getImageEmbeddingModel(imageConfig) + .then(async (data) => { + console.info(TAG + 'get result :' + data); + await data.loadModel(); + data.getEmbedding('111.jpg') + .then((loadData) => { + console.info(TAG + 'getEmbedding result 1200 :' + loadData); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.error('Failed to get Embedding and code is ' + err.code); + expect(err.code).assertEqual(31300000); + done(); + }); + }); + } else { + intelligence.getImageEmbeddingModel(imageConfig) + .then((data) => { + console.info(TAG + 'get result :' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'get promise result' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); +}); \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/unittest/UdmfJsTest.js b/udmf/framework/jskitsimpl/unittest/UdmfJsTest.js index dce53307057f4b6726098fc80fb16bbe57bf14f2..9d38d15c309cb7f0983d7f21c7a476ca15a86464 100644 --- a/udmf/framework/jskitsimpl/unittest/UdmfJsTest.js +++ b/udmf/framework/jskitsimpl/unittest/UdmfJsTest.js @@ -1106,10 +1106,10 @@ describe('UdmfJSTest', function () { expect(unifiedData.hasType(UTD.UniformDataType.HYPERLINK)).assertEqual(true); expect(unifiedData.hasType('openharmony.app-item')).assertEqual(true); let types = unifiedData.getTypes(); - expect(types.length).assertEqual(3); + expect(types.length).assertEqual(1); expect(types.includes(textType)).assertTrue(); - expect(types.includes(UTD.UniformDataType.HYPERLINK)).assertTrue(); - expect(types.includes('openharmony.app-item')).assertTrue(); + expect(types.includes(UTD.UniformDataType.HYPERLINK)).assertFalse(); + expect(types.includes('openharmony.app-item')).assertFalse(); let html = new UDC.HTML(); unifiedData.addRecord(html); @@ -1117,12 +1117,12 @@ describe('UdmfJSTest', function () { expect(unifiedData.hasType(htmlType)).assertEqual(true); expect(unifiedData.hasType(plaintextType)).assertEqual(false); types = unifiedData.getTypes(); - expect(types.length).assertEqual(4); + expect(types.length).assertEqual(2); expect(types.includes(textType)).assertTrue(); expect(types.includes(htmlType)).assertTrue(); expect(types.includes(textType)).assertTrue(); - expect(types.includes(UTD.UniformDataType.HYPERLINK)).assertTrue(); - expect(types.includes('openharmony.app-item')).assertTrue(); + expect(types.includes(UTD.UniformDataType.HYPERLINK)).assertFalse(); + expect(types.includes('openharmony.app-item')).assertFalse(); }); /** @@ -2293,8 +2293,8 @@ describe('UdmfJSTest', function () { let unifiedData = new UDC.UnifiedData(record); let rawDataTypes = unifiedData.getTypes(); - expect(rawDataTypes.includes('general.file-uri')).assertTrue(); - expect(rawDataTypes.includes('openharmony.pixel-map')).assertTrue(); + expect(rawDataTypes.includes('general.image')).assertTrue(); + expect(rawDataTypes.includes('openharmony.pixel-map')).assertFalse(); expect(unifiedData.hasType('general.file-uri')).assertTrue(); expect(unifiedData.hasType('general.image')).assertTrue(); expect(unifiedData.hasType('general.jpeg')).assertTrue(); @@ -2312,7 +2312,7 @@ describe('UdmfJSTest', function () { expect(getRecordTypes.includes('openharmony.pixel-map')).assertTrue(); let getDataTypes = data[0].getTypes(); - expect(getDataTypes.includes('general.file-uri')).assertTrue(); + expect(getDataTypes.includes('general.image')).assertTrue(); for (let i = 0; i < records.length; i++) { if (records[i].getType() === 'general.image') { let getImageUri = records[i].imageUri; @@ -2399,7 +2399,7 @@ describe('UdmfJSTest', function () { let unifiedData = new UDC.UnifiedData(record); let rawDataTypes = unifiedData.getTypes(); - expect(rawDataTypes.includes('general.file-uri')).assertTrue(); + expect(rawDataTypes.includes('general.image')).assertTrue(); expect(unifiedData.hasType('general.file-uri')).assertTrue(); expect(unifiedData.hasType('general.image')).assertTrue(); try { @@ -2417,7 +2417,7 @@ describe('UdmfJSTest', function () { expect(rawRecordTypes.includes('general.file-uri')).assertTrue(); let rawDataTypes = data[0].getTypes(); - expect(rawDataTypes.includes('general.file-uri')).assertTrue(); + expect(rawDataTypes.includes('general.image')).assertTrue(); for (let i = 0; i < records.length; i++) { if (records[i].getType() === 'general.image') { let getImageUri = records[i].imageUri; @@ -2506,17 +2506,17 @@ describe('UdmfJSTest', function () { record.addEntry('openharmony.pixel-map', pixelMap); record.addEntry('general.file-uri', fileUri); let rawType = record.getType(); - expect(rawType).assertEqual('general.file'); + expect(rawType).assertEqual('general.image'); let rawRecordTypes = record.getTypes(); - expect(rawRecordTypes.includes('general.file')).assertTrue(); + expect(rawRecordTypes.includes('general.file')).assertFalse(); expect(rawRecordTypes.includes('general.file-uri')).assertTrue(); expect(rawRecordTypes.includes('openharmony.pixel-map')).assertTrue(); let unifiedData = new UDC.UnifiedData(record); let rawDataTypes = unifiedData.getTypes(); - expect(rawDataTypes.includes('general.file')).assertTrue(); - expect(rawDataTypes.includes('general.file-uri')).assertTrue(); - expect(rawDataTypes.includes('openharmony.pixel-map')).assertTrue(); + expect(rawDataTypes.includes('general.image')).assertTrue(); + expect(rawDataTypes.includes('general.file-uri')).assertFalse(); + expect(rawDataTypes.includes('openharmony.pixel-map')).assertFalse(); expect(unifiedData.hasType('general.file-uri')).assertTrue(); expect(unifiedData.hasType('general.image')).assertTrue(); expect(unifiedData.hasType('general.jpeg')).assertTrue(); @@ -2528,16 +2528,16 @@ describe('UdmfJSTest', function () { console.info(TAG, 'query success.'); let records = data[0].getRecords(); let rawType = records[0].getType(); - expect(rawType).assertEqual('general.file'); + expect(rawType).assertEqual('general.image'); let getRecordTypes = records[0].getTypes(); - expect(getRecordTypes.includes('general.file')).assertTrue(); + expect(getRecordTypes.includes('general.file')).assertFalse(); expect(getRecordTypes.includes('general.file-uri')).assertTrue(); expect(getRecordTypes.includes('openharmony.pixel-map')).assertTrue(); let getDataTypes = data[0].getTypes(); - expect(rawDataTypes.includes('general.file')).assertTrue(); - expect(getDataTypes.includes('general.file-uri')).assertTrue(); - expect(getDataTypes.includes('openharmony.pixel-map')).assertTrue(); + expect(getDataTypes.includes('general.image')).assertTrue(); + expect(getDataTypes.includes('general.file-uri')).assertFalse(); + expect(getDataTypes.includes('openharmony.pixel-map')).assertFalse(); for (let i = 0; i < records.length; i++) { if (records[i].getType() === 'general.file') { let getUri = records[i].uri; @@ -2545,7 +2545,10 @@ describe('UdmfJSTest', function () { } } let getValue = records[0].getValue(); - expect(getValue).assertEqual(undefined); + expect(getValue.uniformDataType).assertEqual('general.file-uri'); + expect(getValue.oriUri).assertEqual('www.xx.com'); + expect(getValue.fileType).assertEqual('general.jpeg'); + expect(getValue.details.fileUriKey1).assertEqual(123); let getEntryFileUri = records[0].getEntry('general.file-uri'); expect(getEntryFileUri.uniformDataType).assertEqual('general.file-uri'); @@ -2633,8 +2636,8 @@ describe('UdmfJSTest', function () { expect(rawRecordTypes.includes('openharmony.pixel-map')).assertTrue(); let unifiedData = new UDC.UnifiedData(record); let rawDataTypes = unifiedData.getTypes(); - expect(rawDataTypes.includes('general.file-uri')).assertTrue(); - expect(rawDataTypes.includes('openharmony.pixel-map')).assertTrue(); + expect(rawDataTypes.includes('general.video')).assertTrue(); + expect(rawDataTypes.includes('openharmony.pixel-map')).assertFalse(); expect(unifiedData.hasType('general.file-uri')).assertTrue(); expect(unifiedData.hasType('general.video')).assertTrue(); expect(unifiedData.hasType('general.vob')).assertTrue(); @@ -2654,8 +2657,8 @@ describe('UdmfJSTest', function () { expect(getRecordTypes.includes('openharmony.pixel-map')).assertTrue(); let getDataTypes = data[0].getTypes(); - expect(getDataTypes.includes('general.file-uri')).assertTrue(); - expect(getDataTypes.includes('openharmony.pixel-map')).assertTrue(); + expect(getDataTypes.includes('general.video')).assertTrue(); + expect(getDataTypes.includes('openharmony.pixel-map')).assertFalse(); for (let i = 0; i < records.length; i++) { if (records[i].getType() === 'general.video') { let getUri = records[i].videoUri; @@ -2755,8 +2758,8 @@ describe('UdmfJSTest', function () { expect(rawRecordTypes.includes('openharmony.pixel-map')).assertTrue(); let unifiedData = new UDC.UnifiedData(record); let rawDataTypes = unifiedData.getTypes(); - expect(rawDataTypes.includes('general.file-uri')).assertFalse(); - expect(rawDataTypes.includes('openharmony.pixel-map')).assertTrue(); + expect(rawDataTypes.includes('general.vob')).assertTrue(); + expect(rawDataTypes.includes('openharmony.pixel-map')).assertFalse(); expect(unifiedData.hasType('general.file-uri')).assertFalse(); expect(unifiedData.hasType('general.video')).assertTrue(); expect(unifiedData.hasType('general.vob')).assertTrue(); @@ -2777,7 +2780,7 @@ describe('UdmfJSTest', function () { let getDataTypes = data[0].getTypes(); expect(getDataTypes.includes('general.vob')).assertTrue(); expect(getDataTypes.includes('general.file-uri')).assertFalse(); - expect(getDataTypes.includes('openharmony.pixel-map')).assertTrue(); + expect(getDataTypes.includes('openharmony.pixel-map')).assertFalse(); let getValue = records[0].getValue(); expect(getValue.uniformDataType).assertEqual('general.file-uri'); @@ -2876,7 +2879,7 @@ describe('UdmfJSTest', function () { let unifiedData = new UDC.UnifiedData(record); let rawDataTypes = unifiedData.getTypes(); expect(rawDataTypes.includes('general.vob')).assertFalse(); - expect(rawDataTypes.includes('general.file-uri')).assertTrue(); + expect(rawDataTypes.includes('general.file-uri')).assertFalse(); expect(rawDataTypes.includes('openharmony.pixel-map')).assertTrue(); expect(unifiedData.hasType('general.file-uri')).assertTrue(); expect(unifiedData.hasType('general.video')).assertTrue(); @@ -2898,7 +2901,7 @@ describe('UdmfJSTest', function () { let getDataTypes = data[0].getTypes(); expect(getDataTypes.includes('general.vob')).assertFalse(); - expect(getDataTypes.includes('general.file-uri')).assertTrue(); + expect(getDataTypes.includes('general.file-uri')).assertFalse(); expect(getDataTypes.includes('openharmony.pixel-map')).assertTrue(); let getValue = records[0].getValue(); @@ -3069,7 +3072,7 @@ describe('UdmfJSTest', function () { let records = data[0].getRecords(); let firstEntry1 = records[0].getEntry(UTD.UniformDataType.PLAIN_TEXT); expect(firstEntry1.textContent).assertEqual('plaintextValue'); - let firstEntry2 = records[1].getEntry(UTD.UniformDataType.FILE); + let firstEntry2 = records[1].getEntry(UTD.UniformDataType.FILE_URI); expect(firstEntry2.oriUri).assertEqual('schema://com.samples.test/files/test.txt'); let firstEntry3 = records[2].getEntry('ApplicationDefinedType'); expect(firstEntry3.arrayBuffer.length).assertEqual(u8Array.length); @@ -3102,4 +3105,229 @@ describe('UdmfJSTest', function () { done(); } }); + + /** + * @tc.name toEntriesTest001 + * @tc.desc test toEntries function normal + * @tc.type: FUNC + * @tc.require: + */ + it('toEntriesTest001', 0, async function (done) { + const TAG = 'toEntriesTest001'; + console.info(TAG, 'start'); + let file = new UDC.File(); + file.uri = 'schema://com.samples.test/files/test.txt'; + let plainText = new UDC.PlainText(); + plainText.textContent = 'this is textContent'; + plainText.abstract = 'this is abstract'; + let link = new UDC.Hyperlink(); + link.url = 'www.XXX.com'; + link.description = 'this is description'; + let html = new UDC.HTML(); + html.htmlContent = '<div><p>标题</p></div>'; + html.plainContent = 'this is plainContent'; + let form = new UDC.SystemDefinedForm(); + form.formId = 123456; + form.formName = 'MyFormName'; + form.bundleName = 'MyBundleName'; + form.abilityName = 'MyAbilityName'; + form.module = 'MyModule'; + form.details = { + 'formKey1': 123, + 'formKey2': 'formValue', + 'formKey3': U8_ARRAY, + }; + let applicationDefinedRecord = new UDC.ApplicationDefinedRecord(); + applicationDefinedRecord.applicationDefinedType = 'ApplicationDefinedType'; + applicationDefinedRecord.rawData = U8_ARRAY; + let unifiedData = new UDC.UnifiedData(); + unifiedData.addRecord(file); + unifiedData.addRecord(plainText); + unifiedData.addRecord(link); + unifiedData.addRecord(html); + unifiedData.addRecord(form); + unifiedData.addRecord(applicationDefinedRecord); + unifiedData.properties.tag = 'records_to_entries_data_format'; + expect(unifiedData.getRecords().length).assertEqual(6); + UDC.convertRecordsToEntries(unifiedData); + expect(unifiedData.getRecords().length).assertEqual(1); + let records = unifiedData.getRecords(); + let recordEntries = records[0]; + expect(recordEntries.uri).assertEqual('schema://com.samples.test/files/test.txt'); + expect(recordEntries.getType()).assertEqual('general.file'); + expect(recordEntries.getValue()).assertEqual(undefined); + let fileEntry = recordEntries.getEntry('general.file-uri'); + expect(fileEntry.uniformDataType).assertEqual('general.file-uri'); + expect(fileEntry.oriUri).assertEqual('schema://com.samples.test/files/test.txt'); + expect(fileEntry.fileType).assertEqual('general.file'); + let plainTextEntry = recordEntries.getEntry('general.plain-text'); + expect(plainTextEntry.textContent).assertEqual('this is textContent'); + expect(plainTextEntry.abstract).assertEqual('this is abstract'); + let linkEntry = recordEntries.getEntry('general.hyperlink'); + expect(linkEntry.url).assertEqual('www.XXX.com'); + expect(linkEntry.description).assertEqual('this is description'); + let htmlEntry = recordEntries.getEntry('general.html'); + expect(htmlEntry.htmlContent).assertEqual('<div><p>标题</p></div>'); + expect(htmlEntry.plainContent).assertEqual('this is plainContent'); + let formEntry = recordEntries.getEntry('openharmony.form'); + expect(formEntry.formId).assertEqual(123456); + expect(formEntry.formName).assertEqual('MyFormName'); + expect(formEntry.bundleName).assertEqual('MyBundleName'); + expect(formEntry.abilityName).assertEqual('MyAbilityName'); + expect(formEntry.module).assertEqual('MyModule'); + expect(formEntry.details.formKey1).assertEqual(123); + expect(formEntry.details.formKey2).assertEqual('formValue'); + let applicationDefinedEntry = recordEntries.getEntry('ApplicationDefinedType'); + for (let i = 0; i < U8_ARRAY.length; i++) { + expect(applicationDefinedEntry.arrayBuffer[i]).assertEqual(U8_ARRAY[i]); + } + expect(applicationDefinedEntry.uniformDataType).assertEqual('ApplicationDefinedType'); + let entries = recordEntries.getEntries(); + expect(entries['general.file-uri'].uniformDataType).assertEqual('general.file-uri'); + expect(entries['general.file-uri'].oriUri).assertEqual('schema://com.samples.test/files/test.txt'); + expect(entries['general.file-uri'].fileType).assertEqual('general.file'); + expect(entries['general.plain-text'].uniformDataType).assertEqual('general.plain-text'); + expect(entries['general.plain-text'].textContent).assertEqual('this is textContent'); + expect(entries['general.plain-text'].abstract).assertEqual('this is abstract'); + expect(entries['general.hyperlink'].uniformDataType).assertEqual('general.hyperlink'); + expect(entries['general.hyperlink'].url).assertEqual('www.XXX.com'); + expect(entries['general.hyperlink'].description).assertEqual('this is description'); + expect(entries['general.html'].uniformDataType).assertEqual('general.html'); + expect(entries['general.html'].htmlContent).assertEqual('<div><p>标题</p></div>'); + expect(entries['general.html'].plainContent).assertEqual('this is plainContent'); + expect(entries['openharmony.form'].uniformDataType).assertEqual('openharmony.form'); + expect(entries['openharmony.form'].formId).assertEqual(123456); + expect(entries['openharmony.form'].formName).assertEqual('MyFormName'); + expect(entries['openharmony.form'].bundleName).assertEqual('MyBundleName'); + expect(entries['openharmony.form'].abilityName).assertEqual('MyAbilityName'); + expect(entries['openharmony.form'].module).assertEqual('MyModule'); + expect(entries['openharmony.form'].details.formKey1).assertEqual(123); + expect(entries['openharmony.form'].details.formKey2).assertEqual('formValue'); + for (let i = 0; i < U8_ARRAY.length; i++) { + expect(entries.ApplicationDefinedType.arrayBuffer[i]).assertEqual(U8_ARRAY[i]); + } + expect(entries.ApplicationDefinedType.uniformDataType).assertEqual('ApplicationDefinedType'); + done(); + }); + + /** + * @tc.name toEntriesTest002 + * @tc.desc test toEntries function with duplicate type + * @tc.type: FUNC + * @tc.require: + */ + it('toEntriesTest002', 0, async function (done) { + const TAG = 'toEntriesTest002'; + console.info(TAG, 'start'); + let image = new UDC.Image(); + image.uri = 'schema://com.samples.test/files/test.jpg'; + let plainText = new UDC.PlainText(); + plainText.textContent = 'this is textContent'; + plainText.abstract = 'this is abstract'; + let video = new UDC.Video(); + video.uri = 'schema://com.samples.test/files/test.mp4'; + let unifiedData = new UDC.UnifiedData(); + unifiedData.addRecord(image); + unifiedData.addRecord(plainText); + unifiedData.addRecord(video); + unifiedData.properties.tag = 'records_to_entries_data_format'; + expect(unifiedData.getRecords().length).assertEqual(3); + UDC.convertRecordsToEntries(unifiedData); + expect(unifiedData.getRecords().length).assertEqual(1); + let records = unifiedData.getRecords(); + let recordEntries = records[0]; + expect(recordEntries.uri).assertEqual('schema://com.samples.test/files/test.jpg'); + expect(recordEntries.getType()).assertEqual('general.image'); + expect(recordEntries.getValue()).assertEqual(undefined); + let entries = recordEntries.getEntries(); + expect(entries['general.file-uri'].uniformDataType).assertEqual('general.file-uri'); + expect(entries['general.file-uri'].oriUri).assertEqual('schema://com.samples.test/files/test.jpg'); + expect(entries['general.file-uri'].fileType).assertEqual('general.image'); + expect(entries['general.plain-text'].uniformDataType).assertEqual('general.plain-text'); + expect(entries['general.plain-text'].textContent).assertEqual('this is textContent'); + expect(entries['general.plain-text'].abstract).assertEqual('this is abstract'); + expect(entries['general.video']).assertEqual(undefined); + done(); + }); + + /** + * @tc.name toEntriesTest003 + * @tc.desc test toEntries function with duplicate type + * @tc.type: FUNC + * @tc.require: + */ + it('toEntriesTest003', 0, async function (done) { + const TAG = 'toEntriesTest003'; + console.info(TAG, 'start'); + let recordFile = new UDC.UnifiedRecord('general.file', 'schema://com.samples.test/files/test.txt'); + let recordVideo = new UDC.UnifiedRecord('general.video', 'schema://com.samples.test/files/test.mp4'); + let recordPlainText = new UDC.UnifiedRecord('general.plain-text', 'this is textContent'); + let unifiedData = new UDC.UnifiedData(); + unifiedData.addRecord(recordFile); + unifiedData.addRecord(recordVideo); + unifiedData.addRecord(recordPlainText); + unifiedData.properties.tag = 'records_to_entries_data_format'; + expect(unifiedData.getRecords().length).assertEqual(3); + UDC.convertRecordsToEntries(unifiedData); + expect(unifiedData.getRecords().length).assertEqual(1); + let records = unifiedData.getRecords(); + let recordEntries = records[0]; + expect(recordEntries.uri).assertEqual('schema://com.samples.test/files/test.txt'); + expect(recordEntries.getType()).assertEqual('general.file'); + expect(recordEntries.getValue()).assertEqual('schema://com.samples.test/files/test.txt'); + let videoEntry = recordEntries.getEntry('general.file-uri'); + expect(videoEntry.oriUri).assertEqual('schema://com.samples.test/files/test.txt'); + expect(videoEntry.fileType).assertEqual('general.file'); + let plainTextEntry = recordEntries.getEntry('general.plain-text'); + expect(plainTextEntry.textContent).assertEqual('this is textContent'); + let entries = recordEntries.getEntries(); + expect(entries['general.file-uri'].uniformDataType).assertEqual('general.file-uri'); + expect(entries['general.file-uri'].oriUri).assertEqual('schema://com.samples.test/files/test.txt'); + expect(entries['general.file-uri'].fileType).assertEqual('general.file'); + expect(entries['general.plain-text'].uniformDataType).assertEqual('general.plain-text'); + expect(entries['general.plain-text'].textContent).assertEqual('this is textContent'); + expect(entries['general.video']).assertEqual(undefined); + expect(entries['general.file']).assertEqual(undefined); + done(); + }); + + /** + * @tc.name toEntriesTest004 + * @tc.desc test toEntries function with invalid data + * @tc.type: FUNC + * @tc.require: + */ + it('toEntriesTest004', 0, function () { + const TAG = 'toEntriesTest004'; + console.info(TAG, 'start'); + try { + UDC.convertRecordsToEntries(); + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + } catch (e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name toEntriesTest005 + * @tc.desc test toEntries function with invalid data + * @tc.type: FUNC + * @tc.require: + */ + it('toEntriesTest005', 0, function () { + const TAG = 'toEntriesTest005'; + console.info(TAG, 'start'); + try { + UDC.convertRecordsToEntries(1); + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + } catch (e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); }); \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/unittest/UdmfPromiseJsTest.js b/udmf/framework/jskitsimpl/unittest/UdmfPromiseJsTest.js index 8b8ab2ca8609e106d34f158399ca44957a5d207c..1993594aacda98c8d4fe98d1fa31d90586f89153 100644 --- a/udmf/framework/jskitsimpl/unittest/UdmfPromiseJsTest.js +++ b/udmf/framework/jskitsimpl/unittest/UdmfPromiseJsTest.js @@ -437,4 +437,55 @@ describe('UdmfPromiseJSTest', function () { } console.info(TAG, 'end'); }); + + /** + * @tc.name UdmfPropertiesMarshallTest + * @tc.desc Test udmf properties Marshall successful + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfPropertiesMarshallTest', 0, async function (done) { + const TAG = 'UdmfPropertiesMarshallTest:'; + console.info(TAG, 'start'); + try { + let person = {fname: 'John', lname: 'Doe', age: 25}; + let props = new UDC.UnifiedDataProperties(); + props.tag = 'DataTag'; + props.shareOptions = UDC.ShareOptions.CROSS_APP; + props.extras = person; + unifiedData01.properties = props; + UDC.insertData(optionsValid, unifiedData01).then((data) => { + console.info(TAG, `insert success. The key: ${data}`); + let options = { key: data }; + console.info(TAG, `query start. The options: ${JSON.stringify(options)}`); + UDC.queryData(options).then((data) => { + console.info(TAG, 'query success.'); + console.info(TAG, `data.length = ${data.length}.`); + expect(data.length).assertEqual(1); + let readProps = data[0].properties; + console.info(TAG, `readProps.tag = ${readProps.tag}.`); + console.info(TAG, `readProps.shareOptions = ${readProps.shareOptions}.`); + console.info(TAG, `readProps.extras = ${JSON.stringify(readProps.extras)}.`); + expect(readProps.tag).assertEqual('DataTag'); + expect(readProps.shareOptions).assertEqual(UDC.ShareOptions.CROSS_APP); + expect(Object.keys(readProps.extras).length).assertEqual(3); + expect(readProps.extras.fname).assertEqual(person.fname); + done(); + }).catch(() => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); }); \ No newline at end of file diff --git a/udmf/framework/ndkimpl/data/data_provider_impl.cpp b/udmf/framework/ndkimpl/data/data_provider_impl.cpp index cbef6db323a71495269276a8c574e4a94a36835d..3f392685fc949218de88aeddb61a1b9507420fa7 100644 --- a/udmf/framework/ndkimpl/data/data_provider_impl.cpp +++ b/udmf/framework/ndkimpl/data/data_provider_impl.cpp @@ -42,12 +42,13 @@ ValueType DataProviderImpl::GetValueByType(const std::string &utdId) auto value = (innerProvider_->callback)(innerProvider_->context, utdId.c_str()); if (value == nullptr) { LOG_ERROR( - UDMF_CAPI, "get empty data when execute custom callback function, utdId is %{public}s", utdId.c_str()); + UDMF_CAPI, "get empty data when execute custom callback function"); return std::monostate(); } UdsObject* object = static_cast<UdsObject *>(value); if (IsInvalidUdsObjectByType(object, static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(utdId)))) { LOG_ERROR(UDMF_CAPI, "data type mismatch"); + delete object; return std::monostate(); } std::shared_ptr<OHOS::UDMF::Object> obj = std::move(object->obj); diff --git a/udmf/framework/ndkimpl/data/udmf.cpp b/udmf/framework/ndkimpl/data/udmf.cpp index 1e857a4f3b6525df49c1c59b29bb975c9ba96d42..6f8ef8d5bb3f3e6c75ef9a9b665d25bad39e9cc5 100644 --- a/udmf/framework/ndkimpl/data/udmf.cpp +++ b/udmf/framework/ndkimpl/data/udmf.cpp @@ -14,34 +14,36 @@ */ #define LOG_TAG "Udmf" #include "udmf.h" -#include "udmf_err_code.h" +#include "application_defined_record.h" +#include "audio.h" #include "data_provider_impl.h" -#include "udmf_client.h" -#include "securec.h" -#include "udmf_capi_common.h" +#include "file.h" +#include "folder.h" +#include "html.h" +#include "image.h" #include "int_wrapper.h" -#include "string_wrapper.h" -#include "unified_meta.h" -#include "udmf_meta.h" +#include "link.h" #include "logger.h" +#include "ndk_data_conversion.h" #include "plain_text.h" -#include "link.h" -#include "html.h" +#include "securec.h" +#include "string_wrapper.h" #include "system_defined_appitem.h" -#include "application_defined_record.h" #include "system_defined_pixelmap.h" -#include "file.h" -#include "audio.h" -#include "folder.h" -#include "image.h" -#include "video.h" +#include "udmf_capi_common.h" +#include "udmf_client.h" +#include "udmf_err_code.h" +#include "udmf_meta.h" +#include "unified_meta.h" #include "utd.h" #include "utd_client.h" +#include "video.h" using namespace OHOS::UDMF; static constexpr uint64_t MAX_RECORDS_COUNT = 4 * 1024 * 1024; static constexpr uint64_t MAX_KEY_STRING_LEN = 1 * 1024 * 1024; +static constexpr uint64_t MAX_TYPES_COUNT = 10 * 1024; static const std::map<std::string, UDType> FILE_TYPES = { { UDMF_META_GENERAL_FILE, UDType::FILE }, { UDMF_META_AUDIO, UDType::AUDIO }, @@ -49,24 +51,13 @@ static const std::map<std::string, UDType> FILE_TYPES = { { UDMF_META_IMAGE, UDType::IMAGE }, { UDMF_META_VIDEO, UDType::VIDEO } }; -static const std::set<std::string> FILE_SUB_TYPES = { - "general.image", "general.video", "general.audio", "general.folder" }; -static void DestroyStringArray(char**& bufArray, unsigned int& count) -{ - if (bufArray == nullptr) { - return; - } - for (unsigned int i = 0; i < count; i++) { - if (bufArray[i] != nullptr) { - delete[] bufArray[i]; - bufArray[i] = nullptr; - } - } - delete[] bufArray; - bufArray = nullptr; - count = 0; -} +static const std::map<Udmf_Intention, Intention> VAILD_INTENTIONS = { + { UDMF_INTENTION_DRAG, Intention::UD_INTENTION_DRAG }, + { UDMF_INTENTION_SYSTEM_SHARE, Intention::UD_INTENTION_SYSTEM_SHARE }, + { UDMF_INTENTION_PICKER, Intention::UD_INTENTION_PICKER }, + { UDMF_INTENTION_MENU, Intention::UD_INTENTION_MENU } +}; static void DestroyUnifiedRecordArray(OH_UdmfRecord**& records, unsigned int& count) { @@ -75,6 +66,11 @@ static void DestroyUnifiedRecordArray(OH_UdmfRecord**& records, unsigned int& co } for (unsigned int i = 0; i < count; i++) { if (records[i] != nullptr) { + if (records[i]->recordData != nullptr) { + delete records[i]->recordData; + records[i]->recordData = nullptr; + } + NdkDataConversion::DestroyStringArray(records[i]->typesArray, records[i]->typesCount); delete records[i]; records[i] = nullptr; } @@ -84,36 +80,6 @@ static void DestroyUnifiedRecordArray(OH_UdmfRecord**& records, unsigned int& co count = 0; } -static char** StrVectorToTypesArray(const std::vector<std::string>& strVector) -{ - unsigned int vectorSize = strVector.size(); - if (vectorSize == 0 || vectorSize > MAX_RECORDS_COUNT) { - return nullptr; - } - char** typesArray = new (std::nothrow) char* [vectorSize]; - if (typesArray == nullptr) { - LOG_ERROR(UDMF_CAPI, "create types array failed!, vectorSize: %{public}d, MAX_RECORDS_COUNT: %{public}" PRIu64, - vectorSize, MAX_RECORDS_COUNT); - return nullptr; - } - for (unsigned int i = 0; i < vectorSize; ++i) { - unsigned int strLen = strVector[i].length() + 1; - if (strLen > MAX_KEY_STRING_LEN) { - LOG_INFO(UDMF_CAPI, "string exceeds maximum length, length is %{public}d", strLen); - DestroyStringArray(typesArray, vectorSize); - return nullptr; - } - typesArray[i] = new (std::nothrow) char[strLen]; - if (typesArray[i] == nullptr || - (strcpy_s(typesArray[i], strLen, strVector[i].c_str())) != EOK) { - LOG_ERROR(UDMF_CAPI, "string copy failed"); - DestroyStringArray(typesArray, vectorSize); - return nullptr; - } - } - return typesArray; -} - static OH_UdmfRecord** CreateUnifiedDataRecordsArray(OH_UdmfData* unifiedData, std::vector<std::shared_ptr<UnifiedRecord>>& records) { @@ -158,6 +124,9 @@ static bool IsUnifiedPropertiesValid(OH_UdmfProperty* properties) static void AddFileUriTypeIfContains(std::vector<std::string>& types) { + if (std::find(types.begin(), types.end(), UDMF_META_GENERAL_FILE_URI) != types.end()) { + return; + } for (auto type : types) { if (FILE_TYPES.find(type) != FILE_TYPES.end()) { types.push_back(UDMF_META_GENERAL_FILE_URI); @@ -182,8 +151,11 @@ void OH_UdmfData_Destroy(OH_UdmfData* data) if (data == nullptr) { return; } - DestroyStringArray(data->typesArray, data->typesCount); - DestroyUnifiedRecordArray(data->records, data->recordsCount); + { + std::lock_guard<std::mutex> lock(data->mutex); + NdkDataConversion::DestroyStringArray(data->typesArray, data->typesCount); + DestroyUnifiedRecordArray(data->records, data->recordsCount); + } delete data; } @@ -214,7 +186,7 @@ char** OH_UdmfData_GetTypes(OH_UdmfData* unifiedData, unsigned int* count) } std::vector<std::string> typeLabels = unifiedData->unifiedData_->GetEntriesTypes(); AddFileUriTypeIfContains(typeLabels); - unifiedData->typesArray = StrVectorToTypesArray(typeLabels); + unifiedData->typesArray = NdkDataConversion::StrVectorToTypesArray(typeLabels); unifiedData->typesArray == nullptr ? unifiedData->typesCount = 0 : unifiedData->typesCount = typeLabels.size(); *count = unifiedData->typesCount; return unifiedData->typesArray; @@ -231,10 +203,10 @@ char** OH_UdmfRecord_GetTypes(OH_UdmfRecord* record, unsigned int* count) *count = record->typesCount; return record->typesArray; } - auto types = record->record_->GetUtdIds(); + auto types = record->record_->GetUtdIdsWithAddFileType(false); std::vector<std::string> typeLabels {types.begin(), types.end()}; AddFileUriTypeIfContains(typeLabels); - record->typesArray = StrVectorToTypesArray(typeLabels); + record->typesArray = NdkDataConversion::StrVectorToTypesArray(typeLabels); record->typesArray == nullptr ? record->typesCount = 0 : record->typesCount = typeLabels.size(); *count = record->typesCount; return record->typesArray; @@ -365,24 +337,178 @@ bool OH_UdmfData_IsLocal(OH_UdmfData* data) return !isRemote; } +OH_UdmfOptions* OH_UdmfOptions_Create() +{ + OH_UdmfOptions* options = new (std::nothrow) OH_UdmfOptions; + if (options == nullptr) { + LOG_ERROR(UDMF_CAPI, "The OH_UdmfOptions create error"); + return nullptr; + } + return options; +} + +void OH_UdmfOptions_Destroy(OH_UdmfOptions* pThis) +{ + if (pThis != nullptr) { + delete pThis; + pThis = nullptr; + } +} + +const char* OH_UdmfOptions_GetKey(OH_UdmfOptions* pThis) +{ + if (pThis == nullptr) { + LOG_ERROR(UDMF_CAPI, "The OH_UdmfOptions get key error, invaild params!"); + return nullptr; + } + return pThis->key.c_str(); +} + +int OH_UdmfOptions_SetKey(OH_UdmfOptions* pThis, const char* key) +{ + if (pThis == nullptr || key == nullptr) { + LOG_ERROR(UDMF_CAPI, "The OH_UdmfOptions set key error, invaild params!"); + return UDMF_E_INVALID_PARAM; + } + std::string keyStr(key); + if (keyStr.length() > UDMF_KEY_BUFFER_LEN) { + LOG_ERROR(UDMF_CAPI, "key length exceeds maximum length, length is %{public}zu", keyStr.length()); + return UDMF_E_INVALID_PARAM; + } + pThis->key = keyStr; + return UDMF_E_OK; +} + +Udmf_Intention OH_UdmfOptions_GetIntention(OH_UdmfOptions* pThis) +{ + if (pThis == nullptr) { + LOG_ERROR(UDMF_CAPI, "The OH_UdmfOptions get intention error, invaild params!"); + return Udmf_Intention {}; + } + return pThis->intention; +} + +int OH_UdmfOptions_SetIntention(OH_UdmfOptions* pThis, Udmf_Intention intention) +{ + if (pThis == nullptr) { + LOG_ERROR(UDMF_CAPI, "The OH_UdmfOptions set intention error, invaild params!"); + return UDMF_E_INVALID_PARAM; + } + + pThis->intention = intention; + return UDMF_E_OK; +} + +int OH_UdmfOptions_Reset(OH_UdmfOptions* pThis) +{ + if (pThis == nullptr) { + LOG_ERROR(UDMF_CAPI, "The OH_UdmfOptions reset error, invaild params!"); + return UDMF_E_INVALID_PARAM; + } + pThis->key.clear(); + pThis->intention = Udmf_Intention {}; + return UDMF_E_OK; +} + +Udmf_Visibility OH_UdmfOptions_GetVisibility(OH_UdmfOptions* pThis) +{ + if (pThis == nullptr) { + LOG_ERROR(UDMF_CAPI, "The Udmf_Visibility get visibility error, invaild params!"); + return Udmf_Visibility::UDMF_ALL; + } + return pThis->visibility; +} + +int OH_UdmfOptions_SetVisibility(OH_UdmfOptions* pThis, Udmf_Visibility visibility) +{ + if (pThis == nullptr) { + LOG_ERROR(UDMF_CAPI, "The Udmf_Visibility set visibility error, invaild params!"); + return UDMF_E_INVALID_PARAM; + } + pThis->visibility = visibility; + return UDMF_E_OK; +} + int OH_Udmf_GetUnifiedData(const char* key, Udmf_Intention intention, OH_UdmfData* data) { if (!IsUnifiedDataValid(data) || key == nullptr) { return UDMF_E_INVALID_PARAM; } Intention queryOptIntent; - switch (intention) { - case UDMF_INTENTION_DRAG: - queryOptIntent = Intention::UD_INTENTION_DRAG; + auto it = VAILD_INTENTIONS.find(intention); + if (it != VAILD_INTENTIONS.end()) { + queryOptIntent = it->second; + } else { + return UDMF_E_INVALID_PARAM; + } + QueryOption query = {.key = std::string(key), .intention = queryOptIntent}; + if (Intention::UD_INTENTION_DRAG == queryOptIntent) { + if (UdmfClient::GetInstance().GetData(query, *(data->unifiedData_)) != E_OK) { + LOG_ERROR(UDMF_CAPI, "get data error"); + return UDMF_ERR; + } + return UDMF_E_OK; + } + if (UnifiedDataUtils::IsFileMangerIntention(UD_INTENTION_MAP.at(queryOptIntent))) { + std::vector<UnifiedData> unifiedDataSet; + auto ret = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + if (ret != E_OK) { + LOG_ERROR(UDMF_CAPI, "get batchdata error:%{public}d", ret); + return UDMF_ERR; + } + if (unifiedDataSet.empty()) { + return UDMF_E_OK; + } else { + data->unifiedData_ = std::make_shared<OHOS::UDMF::UnifiedData>(unifiedDataSet[0]); + } + } + return UDMF_E_OK; +} + +int OH_Udmf_GetUnifiedDataByOptions(OH_UdmfOptions* options, OH_UdmfData** dataArray, unsigned int* dataSize) +{ + if (options == nullptr || dataSize == nullptr || dataArray == nullptr) { + LOG_ERROR(UDMF_CAPI, "The input param error"); + return UDMF_E_INVALID_PARAM; + } + Intention queryOptIntent; + switch (options->intention) { + case UDMF_INTENTION_DATA_HUB: + queryOptIntent = Intention::UD_INTENTION_DATA_HUB; + break; + case UDMF_INTENTION_SYSTEM_SHARE: + queryOptIntent = Intention::UD_INTENTION_SYSTEM_SHARE; + break; + case UDMF_INTENTION_PICKER: + queryOptIntent = Intention::UD_INTENTION_PICKER; + break; + case UDMF_INTENTION_MENU: + queryOptIntent = Intention::UD_INTENTION_MENU; break; default: + LOG_ERROR(UDMF_CAPI, "Intention error, it's not one of the above enumerations"); return UDMF_E_INVALID_PARAM; } - QueryOption query = {.key = std::string(key), .intention = queryOptIntent}; - if (UdmfClient::GetInstance().GetData(query, *(data->unifiedData_)) != E_OK) { - LOG_ERROR(UDMF_CAPI, "get data error"); + QueryOption query = {.key = std::string(options->key), .intention = queryOptIntent}; + + std::vector<UnifiedData> unifiedData; + int32_t ret = UdmfClient::GetInstance().GetBatchData(query, unifiedData); + if (ret != E_OK) { + LOG_ERROR(UDMF_CAPI, "Get batch data error,ret = %{public}d", ret); return UDMF_ERR; } + *dataSize = unifiedData.size(); + if (*dataSize == 0) { + return E_OK; + } + *dataArray = new (std::nothrow) OH_UdmfData[*dataSize]; + if (*dataArray == nullptr) { + LOG_ERROR(UDMF_CAPI, "New dataArray error"); + return UDMF_ERR; + } + for (unsigned int i = 0; i < *dataSize; i++) { + (*dataArray)[i].unifiedData_ = std::make_shared<UnifiedData>(unifiedData[i]); + } return UDMF_E_OK; } @@ -391,27 +517,154 @@ int OH_Udmf_SetUnifiedData(Udmf_Intention intention, OH_UdmfData* unifiedData, c if (!IsUnifiedDataValid(unifiedData) || key == nullptr || keyLen < UDMF_KEY_BUFFER_LEN) { return UDMF_E_INVALID_PARAM; } - enum Intention customOptIntent; - switch (intention) { - case UDMF_INTENTION_DRAG: - customOptIntent = Intention::UD_INTENTION_DRAG; - break; - default: - return UDMF_E_INVALID_PARAM; + Intention customOptIntent; + auto it = VAILD_INTENTIONS.find(intention); + if (it != VAILD_INTENTIONS.end()) { + customOptIntent = it->second; + } else { + LOG_ERROR(UDMF_CAPI, "The intention is invalid"); + return UDMF_E_INVALID_PARAM; } CustomOption option = {.intention = customOptIntent}; std::string keyStr; if ((UdmfClient::GetInstance().SetData(option, *(unifiedData->unifiedData_), keyStr)) != E_OK) { - LOG_ERROR(UDMF_CAPI, "set data error"); + LOG_ERROR(UDMF_CAPI, "Set data error"); return UDMF_ERR; } if (strcpy_s(key, keyLen, keyStr.c_str()) != EOK) { - LOG_ERROR(UDMF_CAPI, "string copy failed"); + LOG_ERROR(UDMF_CAPI, "String copy failed"); + return UDMF_ERR; + } + return UDMF_E_OK; +} + +int OH_Udmf_SetUnifiedDataByOptions(OH_UdmfOptions* options, OH_UdmfData* unifiedData, char* key, unsigned int keyLen) +{ + if (!IsUnifiedDataValid(unifiedData) || key == nullptr || keyLen < UDMF_KEY_BUFFER_LEN || options == nullptr) { + LOG_ERROR(UDMF_CAPI, "The set param invalid"); + return UDMF_E_INVALID_PARAM; + } + Intention customOptIntent; + switch (options->intention) { + case UDMF_INTENTION_DATA_HUB: + customOptIntent = Intention::UD_INTENTION_DATA_HUB; + break; + case UDMF_INTENTION_SYSTEM_SHARE: + customOptIntent = Intention::UD_INTENTION_SYSTEM_SHARE; + break; + case UDMF_INTENTION_PICKER: + customOptIntent = Intention::UD_INTENTION_PICKER; + break; + case UDMF_INTENTION_MENU: + customOptIntent = Intention::UD_INTENTION_MENU; + break; + default: + LOG_ERROR(UDMF_CAPI, "Intention error, it's not one of the above enumerations"); + return UDMF_E_INVALID_PARAM; + } + Visibility customOptVisibility; + switch (options->visibility) { + case UDMF_ALL: + customOptVisibility = Visibility::VISIBILITY_ALL; + break; + case UDMF_OWN_PROCESS: + customOptVisibility = Visibility::VISIBILITY_OWN_PROCESS; + break; + default: + LOG_ERROR(UDMF_CAPI, "Invalid visibility value: %{public}d", options->visibility); + return UDMF_E_INVALID_PARAM; + } + CustomOption option = {.intention = customOptIntent, .visibility = customOptVisibility}; + std::string keyStr; + int32_t ret = UdmfClient::GetInstance().SetData(option, *(unifiedData->unifiedData_), keyStr); + if (ret != E_OK) { + LOG_ERROR(UDMF_CAPI, "Set data error,ret = %{public}d", ret); + return UDMF_ERR; + } + if (strcpy_s(key, keyLen, keyStr.c_str()) != E_OK) { + LOG_ERROR(UDMF_CAPI, "String copy failed"); return UDMF_ERR; } return UDMF_E_OK; } +int OH_Udmf_UpdateUnifiedData(OH_UdmfOptions* options, OH_UdmfData* unifiedData) +{ + if (!IsUnifiedDataValid(unifiedData) || options == nullptr || options->key.empty()) { + LOG_ERROR(UDMF_CAPI, "The update error, lnvaild params!"); + return UDMF_E_INVALID_PARAM; + } + if (options->intention != UDMF_INTENTION_DATA_HUB) { + LOG_ERROR(UDMF_CAPI, "Intention error, Intention is %{public}d", options->intention); + return UDMF_E_INVALID_PARAM; + } + QueryOption query = {.key = options->key}; + int32_t ret = UdmfClient::GetInstance().UpdateData(query, *(unifiedData->unifiedData_)); + if (ret != E_OK) { + LOG_ERROR(UDMF_CAPI, "Updata error,ret = %{public}d", ret); + return UDMF_ERR; + } + return UDMF_E_OK; +} + +int OH_Udmf_DeleteUnifiedData(OH_UdmfOptions* options, OH_UdmfData** dataArray, unsigned int* dataSize) +{ + if (options == nullptr || dataSize == nullptr || dataArray == nullptr) { + LOG_ERROR(UDMF_CAPI, "The delete param invalid"); + return UDMF_E_INVALID_PARAM; + } + Intention queryOptIntent; + switch (options->intention) { + case UDMF_INTENTION_DATA_HUB: + queryOptIntent = Intention::UD_INTENTION_DATA_HUB; + break; + case UDMF_INTENTION_SYSTEM_SHARE: + queryOptIntent = Intention::UD_INTENTION_SYSTEM_SHARE; + break; + case UDMF_INTENTION_PICKER: + queryOptIntent = Intention::UD_INTENTION_PICKER; + break; + case UDMF_INTENTION_MENU: + queryOptIntent = Intention::UD_INTENTION_MENU; + break; + default: + LOG_ERROR(UDMF_CAPI, "Intention error, it's not one of the above enumerations"); + return UDMF_E_INVALID_PARAM; + } + QueryOption query = {.key = options->key, .intention = queryOptIntent}; + std::vector<UnifiedData> unifiedData; + int32_t ret = UdmfClient::GetInstance().DeleteData(query, unifiedData); + if (ret != E_OK) { + LOG_ERROR(UDMF_CAPI, "Delete data error,key is %{public}s, ret = %{public}d", + query.key.c_str(), ret); + return UDMF_ERR; + } + *dataSize = unifiedData.size(); + *dataArray = new (std::nothrow) OH_UdmfData[*dataSize]; + if (*dataArray == nullptr) { + LOG_ERROR(UDMF_CAPI, "New dataArray error"); + return UDMF_ERR; + } + for (unsigned int i = 0; i < *dataSize; i++) { + (*dataArray)[i].unifiedData_ = std::make_shared<UnifiedData>(unifiedData[i]); + } + return UDMF_E_OK; +} + +void OH_Udmf_DestroyDataArray(OH_UdmfData** dataArray, unsigned int dataSize) +{ + if (dataArray == nullptr || *dataArray == nullptr) { + LOG_ERROR(UDMF_CAPI, "The DestroyDataArray error, invaild params!"); + return; + } + for (unsigned int i = 0; i < dataSize; ++i) { + NdkDataConversion::DestroyStringArray((*dataArray)[i].typesArray, (*dataArray)[i].typesCount); + DestroyUnifiedRecordArray((*dataArray)[i].records, (*dataArray)[i].recordsCount); + } + delete[] *dataArray; + *dataArray = nullptr; +} + OH_UdmfRecord* OH_UdmfRecord_Create() { OH_UdmfRecord* record = new (std::nothrow) OH_UdmfRecord; @@ -427,11 +680,14 @@ void OH_UdmfRecord_Destroy(OH_UdmfRecord* record) if (record == nullptr) { return; } - if (record->recordData != nullptr) { - delete[] record->recordData; - record->recordData = nullptr; + { + std::lock_guard<std::mutex> lock(record->mutex); + if (record->recordData != nullptr) { + delete[] record->recordData; + record->recordData = nullptr; + } + NdkDataConversion::DestroyStringArray(record->typesArray, record->typesCount); } - DestroyStringArray(record->typesArray, record->typesCount); delete record; } @@ -483,7 +739,7 @@ static int GetValueFromUint8Array(OH_UdmfRecord *record, const char *typeId, Val } auto err = memcpy_s(record->recordData, record->recordDataLen, recordValue.data(), record->recordDataLen); if (err != EOK) { - LOG_ERROR(UDMF_CAPI, "memcpy error! type:%{public}s", typeId); + LOG_ERROR(UDMF_CAPI, "memcpy error!"); return UDMF_ERR; } record->lastType = const_cast<char*>(typeId); @@ -497,7 +753,7 @@ int OH_UdmfRecord_GetGeneralEntry(OH_UdmfRecord* record, const char* typeId, uns } std::lock_guard<std::mutex> lock(record->mutex); if (!record->record_->HasType(typeId)) { - LOG_ERROR(UDMF_CAPI, "no type:%{public}s", typeId); + LOG_ERROR(UDMF_CAPI, "not has typeId"); return UDMF_E_INVALID_PARAM; } if (record->lastType == typeId && record->recordData != nullptr) { @@ -514,7 +770,7 @@ int OH_UdmfRecord_GetGeneralEntry(OH_UdmfRecord* record, const char* typeId, uns } auto result = GetValueFromUint8Array(record, typeId, value); if (result != UDMF_E_OK) { - LOG_ERROR(UDMF_CAPI, "Get value from valueType failed. typeId: %{public}s, result: %{public}d", typeId, result); + LOG_ERROR(UDMF_CAPI, "Get value from valueType failed. result: %{public}d", result); return result; } *count = record->recordDataLen; @@ -590,17 +846,9 @@ int OH_UdmfRecord_AddFileUri(OH_UdmfRecord* record, OH_UdsFileUri* fileUri) { AddUds<Folder>(record, fileUri, UDType::FOLDER); }}, }; int32_t utdId = UDType::FILE; - std::shared_ptr<TypeDescriptor> descriptor; - UtdClient::GetInstance().GetTypeDescriptor(*fileType, descriptor); - if (descriptor != nullptr) { - bool isFileType = false; - for (const auto &fileSub : FILE_SUB_TYPES) { - descriptor->BelongsTo(fileSub, isFileType); - if (isFileType) { - utdId = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(*fileType)); - break; - } - } + std::string subFileType = UnifiedDataUtils::GetBelongsToFileType(*fileType); + if (!subFileType.empty()) { + utdId = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(subFileType)); } addFileUriFuncs[static_cast<UDType>(utdId)](record, fileUri); return UDMF_E_OK; @@ -887,7 +1135,8 @@ int OH_UdmfRecordProvider_SetData(OH_UdmfRecordProvider* provider, void* context int OH_UdmfRecord_SetProvider(OH_UdmfRecord* record, const char* const* types, unsigned int count, OH_UdmfRecordProvider* provider) { - if (!IsUnifiedRecordValid(record) || types == nullptr || count == 0 || provider == nullptr) { + if (!IsUnifiedRecordValid(record) || types == nullptr || count == 0 + || count > MAX_TYPES_COUNT || provider == nullptr) { return UDMF_E_INVALID_PARAM; } std::shared_ptr<DataProviderImpl> providerBox = std::make_shared<DataProviderImpl>(); @@ -968,4 +1217,114 @@ void OH_UdmfGetDataParams_SetDataProgressListener(OH_UdmfGetDataParams* params, return; } params->dataProgressListener = dataProgressListener; +} + +void OH_UdmfGetDataParams_SetAcceptableInfo(OH_UdmfGetDataParams* params, OH_UdmfDataLoadInfo* acceptableInfo) +{ + if (params == nullptr || acceptableInfo == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return; + } + params->acceptableInfo = *acceptableInfo; +} + +OH_UdmfDataLoadParams* OH_UdmfDataLoadParams_Create() +{ + OH_UdmfDataLoadParams *params = new (std::nothrow) OH_UdmfDataLoadParams; + if (params == nullptr) { + LOG_ERROR(UDMF_CAPI, "Allocate OH_UdmfDataLoadParams memory failed."); + return nullptr; + } + return params; +} + +void OH_UdmfDataLoadParams_Destroy(OH_UdmfDataLoadParams* pThis) +{ + if (pThis == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return; + } + delete pThis; +} + +void OH_UdmfDataLoadParams_SetLoadHandler(OH_UdmfDataLoadParams* params, const OH_Udmf_DataLoadHandler dataLoadHandler) +{ + if (params == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return; + } + params->dataLoadHandler = dataLoadHandler; +} + +void OH_UdmfDataLoadParams_SetDataLoadInfo(OH_UdmfDataLoadParams* params, OH_UdmfDataLoadInfo* dataLoadInfo) +{ + if (params == nullptr || dataLoadInfo == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return; + } + params->dataLoadInfo = *dataLoadInfo; +} + +OH_UdmfDataLoadInfo* OH_UdmfDataLoadInfo_Create() +{ + OH_UdmfDataLoadInfo *params = new (std::nothrow) OH_UdmfDataLoadInfo; + if (params == nullptr) { + LOG_ERROR(UDMF_CAPI, "Allocate OH_UdmfDataLoadInfo memory failed."); + return nullptr; + } + return params; +} + +void OH_UdmfDataLoadInfo_Destroy(OH_UdmfDataLoadInfo* dataLoadInfo) +{ + if (dataLoadInfo == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return; + } + NdkDataConversion::DestroyStringArray(dataLoadInfo->typesArray, dataLoadInfo->typesCount); + delete dataLoadInfo; +} + +char** OH_UdmfDataLoadInfo_GetTypes(OH_UdmfDataLoadInfo* dataLoadInfo, unsigned int* count) +{ + if (dataLoadInfo == nullptr || count == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return nullptr; + } + *count = dataLoadInfo->typesCount; + return dataLoadInfo->typesArray; +} + +void OH_UdmfDataLoadInfo_SetType(OH_UdmfDataLoadInfo* dataLoadInfo, const char* type) +{ + if (dataLoadInfo == nullptr || type == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return; + } + std::set<std::string> types; + for (unsigned int i = 0; i < dataLoadInfo->typesCount; ++i) { + types.insert(dataLoadInfo->typesArray[i]); + } + types.insert(type); + std::vector<std::string> typeLabels {types.begin(), types.end()}; + dataLoadInfo->typesArray = NdkDataConversion::StrVectorToTypesArray(typeLabels); + dataLoadInfo->typesCount = typeLabels.size(); +} + +int OH_UdmfDataLoadInfo_GetRecordCount(OH_UdmfDataLoadInfo* dataLoadInfo) +{ + if (dataLoadInfo == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return 0; + } + return static_cast<int>(dataLoadInfo->recordsCount); +} + +void OH_UdmfDataLoadInfo_SetRecordCount(OH_UdmfDataLoadInfo* dataLoadInfo, unsigned int recordCount) +{ + if (dataLoadInfo == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return; + } + dataLoadInfo->recordsCount = recordCount; } \ No newline at end of file diff --git a/udmf/framework/ndkimpl/data/udmf_capi_common.h b/udmf/framework/ndkimpl/data/udmf_capi_common.h index d22d2ccfd40598cbb53f29de6dee060dd9958634..0720075100d417cce96aad802a738dee94b7d481 100644 --- a/udmf/framework/ndkimpl/data/udmf_capi_common.h +++ b/udmf/framework/ndkimpl/data/udmf_capi_common.h @@ -29,9 +29,10 @@ struct UdsObject { std::shared_ptr<OHOS::UDMF::Object> obj; std::mutex mutex; explicit UdsObject(int cid); - template<typename T> bool HasObjectKey(const char* paramName); template<typename T> T* GetUdsValue(const char* paramName); template<typename T> int SetUdsValue(const char* paramName, const T &pramValue); +private: + template<typename T> bool HasObjectKey(const char* paramName); }; enum NdkStructId : std::int64_t { @@ -53,12 +54,12 @@ struct OH_Utd { const int64_t cid = UTD_STRUCT_ID; std::mutex mutex; std::string typeId; - const char** belongingToTypes{nullptr}; - unsigned int belongingToTypesCount{0}; - const char** filenameExtensions{nullptr}; - unsigned int filenameExtensionsCount{0}; - const char** mimeTypes{nullptr}; - unsigned int mimeTypeCount{0}; + const char **belongingToTypes {nullptr}; + unsigned int belongingToTypesCount {0}; + const char **filenameExtensions {nullptr}; + unsigned int filenameExtensionsCount {0}; + const char **mimeTypes {nullptr}; + unsigned int mimeTypeCount {0}; std::string description; std::string referenceURL; std::string iconFile; @@ -92,21 +93,21 @@ struct OH_UdsContentForm : public UdsObject { struct OH_UdmfRecord { const int64_t cid = UDMF_UNIFIED_RECORD_STRUCT_ID; std::shared_ptr<OHOS::UDMF::UnifiedRecord> record_; - unsigned char *recordData{nullptr}; - unsigned int recordDataLen{0}; - char **typesArray{nullptr}; - unsigned int typesCount{0}; - char *lastType{nullptr}; + unsigned char *recordData {nullptr}; + unsigned int recordDataLen {0}; + char **typesArray {nullptr}; + unsigned int typesCount {0}; + char *lastType {nullptr}; std::mutex mutex; }; struct OH_UdmfData { const int64_t cid = UDMF_UNIFIED_DATA_STRUCT_ID; std::shared_ptr<OHOS::UDMF::UnifiedData> unifiedData_; - char **typesArray{nullptr}; - unsigned int typesCount{0}; - OH_UdmfRecord **records{nullptr}; - unsigned int recordsCount{0}; + char **typesArray {nullptr}; + unsigned int typesCount {0}; + OH_UdmfRecord **records {nullptr}; + unsigned int recordsCount {0}; std::mutex mutex; }; @@ -122,12 +123,29 @@ struct OH_Udmf_ProgressInfo { int status; }; +struct OH_UdmfDataLoadInfo { + char **typesArray {nullptr}; + unsigned int typesCount {0}; + unsigned int recordsCount {0}; +}; struct OH_UdmfGetDataParams { std::string destUri; Udmf_FileConflictOptions fileConflictOptions; Udmf_ProgressIndicator progressIndicator; OH_Udmf_DataProgressListener dataProgressListener; + OH_UdmfDataLoadInfo acceptableInfo; +}; + +struct OH_UdmfDataLoadParams { + OH_UdmfDataLoadInfo dataLoadInfo; + OH_Udmf_DataLoadHandler dataLoadHandler; +}; + +struct OH_UdmfOptions { + std::string key; + Udmf_Intention intention {}; + Udmf_Visibility visibility {}; }; bool IsInvalidUdsObjectPtr(const UdsObject* pThis, int cid); diff --git a/udmf/framework/ndkimpl/data/uds.cpp b/udmf/framework/ndkimpl/data/uds.cpp index 08094efdd1bfb4f6a151a641c2afaa93781af909..be484930263e4865801142875db10b55ddcf19ac 100644 --- a/udmf/framework/ndkimpl/data/uds.cpp +++ b/udmf/framework/ndkimpl/data/uds.cpp @@ -26,6 +26,8 @@ using namespace OHOS::UDMF; +constexpr const int32_t MAX_PARAM_NAME = 1024; + static const char* GetUdsStrValue(UdsObject* pThis, NdkStructId ndkStructId, const char* paramName) { if (IsInvalidUdsObjectPtr(pThis, ndkStructId)) { @@ -107,9 +109,13 @@ OH_UdsContentForm::OH_UdsContentForm() : UdsObject(NdkStructId::UDS_CONTENT_FORM template <typename T> bool UdsObject::HasObjectKey(const char* paramName) { + if (strlen(paramName) > MAX_PARAM_NAME) { + LOG_ERROR(UDMF_CAPI, "paramName too long! paramName size = %{public}zu.", strlen(paramName)); + return false; + } auto it = obj->value_.find(paramName); if (it == obj->value_.end() || !std::holds_alternative<T>(it->second)) { - LOG_ERROR(UDMF_CAPI, "Don't have property %{public}s.", paramName); + LOG_ERROR(UDMF_CAPI, "Don't have property paramName"); return false; } return true; @@ -481,6 +487,10 @@ void OH_UdsPixelMap_GetPixelMap(OH_UdsPixelMap* pThis, OH_PixelmapNative* pixelm if (IsInvalidUdsObjectPtr(pThis, NdkStructId::UDS_PIXEL_MAP_STRUCT_ID)) { return; } + if (pixelmapNative == nullptr) { + LOG_ERROR(UDMF_CAPI, "pixelmapNative is nullptr."); + return; + } auto pixelMap = pThis->GetUdsValue<std::shared_ptr<OHOS::Media::PixelMap>>(PIXEL_MAP); if (pixelMap == nullptr) { LOG_ERROR(UDMF_CAPI, "Get pixelMap value is null."); diff --git a/udmf/framework/ndkimpl/data/utd.cpp b/udmf/framework/ndkimpl/data/utd.cpp index b0969a7d760eec4ede47fa9791381be400250419..73f4be1d7a30356a520703c7c039ae3a1f138827 100644 --- a/udmf/framework/ndkimpl/data/utd.cpp +++ b/udmf/framework/ndkimpl/data/utd.cpp @@ -118,15 +118,14 @@ OH_Utd* OH_Utd_Create(const char* typeId) if (typeId == nullptr) { return nullptr; } - auto pThis = new (std::nothrow) OH_Utd(); - if (pThis == nullptr) { - LOG_ERROR(UDMF_CAPI, "Failed to apply for memory."); - return nullptr; - } auto typeDescriptor = GetTypeDescriptorByUtdClient(typeId); if (typeDescriptor == nullptr) { LOG_ERROR(UDMF_CAPI, "Failed to create by invoking the native function."); - delete pThis; + return nullptr; + } + auto pThis = new (std::nothrow) OH_Utd(); + if (pThis == nullptr) { + LOG_ERROR(UDMF_CAPI, "Failed to apply for memory."); return nullptr; } pThis->typeId = typeDescriptor->GetTypeId(); diff --git a/udmf/framework/ndkimpl/udmf_fuzzer/BUILD.gn b/udmf/framework/ndkimpl/udmf_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..2110f03b83a3017b3eb4458b28549e4718b49187 --- /dev/null +++ b/udmf/framework/ndkimpl/udmf_fuzzer/BUILD.gn @@ -0,0 +1,68 @@ +# Copyright (c) 2023 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/config/features.gni") + +#####################hydra-fuzz################### +import("//build/test.gni") +import("//foundation/distributeddatamgr/udmf/udmf.gni") + +##############################fuzztest########################################## +ohos_fuzztest("UdmfFuzzTest") { + module_out_path = "udmf/udmf" + + include_dirs = [ + "${udmf_interfaces_path}/ndk/data", + "${udmf_root_path}/framework/ndkimpl/data", + ] + + fuzz_config_file = + "${udmf_framework_path}/ndkimpl/udmf_fuzzer" + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ "udmf_fuzzer.cpp" ] + + deps = [ + "${udmf_interfaces_path}/ndk:libudmf", + "${udmf_interfaces_path}/innerkits:udmf_client" , + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "access_token:libtoken_setproc", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "hilog:libhilog", + "image_framework:image", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "samgr:samgr_proxy", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":UdmfFuzzTest", + ] +} +############################################################################### diff --git a/kv_store/test/fuzztest/kvsync_fuzzer/kvsync_fuzzer.h b/udmf/framework/ndkimpl/udmf_fuzzer/corpus/init similarity index 83% rename from kv_store/test/fuzztest/kvsync_fuzzer/kvsync_fuzzer.h rename to udmf/framework/ndkimpl/udmf_fuzzer/corpus/init index 77a42ea30656fe03b593db536c1ee6f3b4bd4c4d..2b595da0c26af63ffb2d5f4132c086b2e5986fce 100644 --- a/kv_store/test/fuzztest/kvsync_fuzzer/kvsync_fuzzer.h +++ b/udmf/framework/ndkimpl/udmf_fuzzer/corpus/init @@ -13,9 +13,4 @@ * limitations under the License. */ -#ifndef KV_SYNC_FUZZER_H -#define KV_SYNC_FUZZER_H - -#define FUZZ_PROJECT_NAME "KvSync_fuzzer" - -#endif // KV_SYNC_FUZZER_H \ No newline at end of file +FUZZ \ No newline at end of file diff --git a/udmf/framework/ndkimpl/udmf_fuzzer/project.xml b/udmf/framework/ndkimpl/udmf_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..4fdbc407f205680885fa42663163b5c987f123a6 --- /dev/null +++ b/udmf/framework/ndkimpl/udmf_fuzzer/project.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (c) 2023 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. +--> +<fuzz_config> + <fuzztest> + <!-- maximum length of a test input --> + <max_len>1000</max_len> + <!-- maximum total time in seconds to run the fuzzer --> + <max_total_time>300</max_total_time> + <!-- memory usage limit in Mb --> + <rss_limit_mb>4096</rss_limit_mb> + </fuzztest> +</fuzz_config> diff --git a/udmf/framework/ndkimpl/udmf_fuzzer/udmf_fuzzer.cpp b/udmf/framework/ndkimpl/udmf_fuzzer/udmf_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f9b860c45a2371b6f756b5f26fb378e68fb50a6f --- /dev/null +++ b/udmf/framework/ndkimpl/udmf_fuzzer/udmf_fuzzer.cpp @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2023 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 <unistd.h> +#include <thread> + +#include "accesstoken_kit.h" +#include "nativetoken_kit.h" +#include "token_setproc.h" + +#include "link.h" + +#include "udmf_fuzzer.h" +#include "udmf.h" +#include "udmf_capi_common.h" +#include "udmf_meta.h" + +using namespace OHOS; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; + +namespace OHOS { +static constexpr int END_INTERVAL = 3; + +void AllocHapToken() +{ + HapInfoParams info = { + .userID = 100, + .bundleName = "ohos.test.demo", + .instIndex = 0, + .appIDDesc = "ohos.test.demo" + }; + + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.test.demo", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "test", + .descriptionId = 1 + } + }, + .permStateList = { + { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = {"local"}, + .grantStatus = {PermissionState::PERMISSION_GRANTED}, + .grantFlags = {1} + } + } + }; + auto tokenID = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(tokenID.tokenIDEx); +} + +void SetUpTestCase() +{ + AllocHapToken(); +} + +void TearDown() +{ + std::this_thread::sleep_for(std::chrono::seconds(END_INTERVAL)); +} + +void SetNativeToken() +{ + NativeTokenInfoParams infoInstance = { + .dcapsNum = 0, + .permsNum = 0, + .aclsNum = 0, + .dcaps = nullptr, + .perms = nullptr, + .acls = nullptr, + .processName = "msdp_sa", + .aplStr = "system_core", + }; + auto tokenId = GetAccessTokenId(&infoInstance); + SetSelfTokenID(tokenId); + AccessTokenKit::ReloadNativeTokenInfo(); +} + +void SetHapToken() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(100, "ohos.test.demo", 0); + SetSelfTokenID(tokenId); +} + +void SetUnifiedDataFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, skey.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + char key[UDMF_KEY_BUFFER_LEN]; + OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + OH_UdmfOptions_Destroy(options); + OH_UdsFileUri_Destroy(fileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +void GetUnifiedDataFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, skey.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + char key[UDMF_KEY_BUFFER_LEN]; + OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + OH_Udmf_GetUnifiedDataByOptions(options, &dataArray, &dataSize); + OH_UdmfOptions_Destroy(options); + OH_UdsFileUri_Destroy(fileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_Udmf_DestroyDataArray(&dataArray, dataSize); +} + +void UpdataUnifiedDataFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, skey.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + char key[UDMF_KEY_BUFFER_LEN]; + OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + + std::string svalue(data, data + size); + OH_UdmfData *udmfUnifiedData2 = OH_UdmfData_Create(); + OH_UdmfRecord *record2 = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri2 = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri2, svalue.c_str()); + OH_UdsFileUri_SetFileType(fileUri2, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record2, fileUri2); + OH_UdmfData_AddRecord(udmfUnifiedData2, record2); + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_DATA_HUB; + options2->key = key; + OH_Udmf_UpdateUnifiedData(options2, udmfUnifiedData2); + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options2); + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(fileUri2); + OH_UdmfRecord_Destroy(record); + OH_UdmfRecord_Destroy(record2); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(udmfUnifiedData2); +} + +void DeleteUnifiedDataFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, skey.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + char key[UDMF_KEY_BUFFER_LEN]; + OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + OH_Udmf_DeleteUnifiedData(options, &dataArray, &dataSize); + OH_UdmfOptions_Destroy(options); + OH_UdsFileUri_Destroy(fileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_Udmf_DestroyDataArray(&dataArray, dataSize); +} + +void SetAndGetVisibilityFuzz(const uint8_t *data, size_t size) +{ + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + Udmf_Visibility testVisibility = Udmf_Visibility::UDMF_ALL; + OH_UdmfOptions_SetVisibility(options, testVisibility); + OH_UdmfOptions_GetVisibility(options); + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions* options1 = OH_UdmfOptions_Create(); + testVisibility = Udmf_Visibility::UDMF_OWN_PROCESS; + OH_UdmfOptions_SetVisibility(options1, testVisibility); + OH_UdmfOptions_GetVisibility(options1); + OH_UdmfOptions_Destroy(options1); +} +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + /* Run your code on data */ + OHOS::SetUpTestCase(); + OHOS::SetUnifiedDataFuzz(data, size); + OHOS::GetUnifiedDataFuzz(data, size); + OHOS::UpdataUnifiedDataFuzz(data, size); + OHOS::DeleteUnifiedDataFuzz(data, size); + OHOS::SetAndGetVisibilityFuzz(data, size); + OHOS::TearDown(); + return 0; +} \ No newline at end of file diff --git a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/gdbstore_fuzzer.h b/udmf/framework/ndkimpl/udmf_fuzzer/udmf_fuzzer.h similarity index 76% rename from relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/gdbstore_fuzzer.h rename to udmf/framework/ndkimpl/udmf_fuzzer/udmf_fuzzer.h index 05581d1a77661046a98d3ea69f4c3a08e07ec893..1b27bab097243f9bbab81c10d36318333d1d3bdf 100644 --- a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/gdbstore_fuzzer.h +++ b/udmf/framework/ndkimpl/udmf_fuzzer/udmf_fuzzer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2023 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,9 +13,9 @@ * limitations under the License. */ -#ifndef GDBSTORE_FUZZER_H -#define GDBSTORE_FUZZER_H +#ifndef UDMF_UDMF_FUZZER_H +#define UDMF_UDMF_FUZZER_H -#define FUZZ_PROJECT_NAME "gdbstore_fuzzer" +#define FUZZ_PROJECT_NAME "udmf_fuzzer" -#endif // GDBSTORE_FUZZER_H \ No newline at end of file +#endif // UDMF_UDMF_FUZZER_H diff --git a/udmf/framework/ndkimpl/unittest/BUILD.gn b/udmf/framework/ndkimpl/unittest/BUILD.gn index ad8ece29e79f35c6d2a4330d4df09b926a2cd161..589ed026548a9eb148c4863e80d8e711ac8e1012 100644 --- a/udmf/framework/ndkimpl/unittest/BUILD.gn +++ b/udmf/framework/ndkimpl/unittest/BUILD.gn @@ -13,13 +13,14 @@ import("//build/test.gni") import("//foundation/distributeddatamgr/udmf/udmf.gni") -module_output_path = "udmf/ndkimpl" +module_output_path = "udmf/udmf/ndkimpl" ############################################################################### config("module_private_config") { include_dirs = [ "${udmf_interfaces_path}/ndk/data", "${udmf_interfaces_path}/innerkits/data", + "${udmf_interfaces_path}/innerkits/dynamic", "${udmf_interfaces_path}/innerkits/common", "${udmf_framework_path}/common", "${udmf_framework_path}/ndkimpl/data", @@ -38,9 +39,11 @@ common_external_deps = [ "access_token:libnativetoken", "access_token:libtoken_setproc", "c_utils:utils", + "hilog:libhilog", "image_framework:image", "image_framework:image_native", "image_framework:pixelmap", + "ipc:ipc_single", "samgr:samgr_proxy", ] @@ -86,6 +89,7 @@ ohos_unittest("UdmfTest") { "${udmf_framework_path}/innerkitsimpl/data/system_defined_record.cpp", "${udmf_framework_path}/innerkitsimpl/data/text.cpp", "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", "udmf_test.cpp", ] @@ -94,6 +98,8 @@ ohos_unittest("UdmfTest") { deps = common_deps external_deps = common_external_deps + + external_deps += [ "kv_store:distributeddata_inner" ] } ohos_unittest("DataProviderImplTest") { diff --git a/udmf/framework/ndkimpl/unittest/udmf_test.cpp b/udmf/framework/ndkimpl/unittest/udmf_test.cpp index a1f9a601d21ddc347f5ff26b8a9db3fc2ed2f056..f93f597bd9a82e169f034005b25440bfc45ee9c7 100644 --- a/udmf/framework/ndkimpl/unittest/udmf_test.cpp +++ b/udmf/framework/ndkimpl/unittest/udmf_test.cpp @@ -43,6 +43,7 @@ using namespace OHOS::Security::AccessToken; using namespace OHOS::UDMF; namespace OHOS::Test { +static constexpr uint64_t MAX_TYPES_COUNT = 10 * 1024; class UDMFTest : public testing::Test { public: static void SetUpTestCase(void); @@ -52,11 +53,13 @@ public: static void AllocHapToken1(); static void AllocHapToken2(); void SetHapToken1(); + void SetHapToken2(); bool CheckUnsignedChar(unsigned char* dst, unsigned char* src, int size); static void FinalizeFunc(void* context); static void* GetDataCallbackFunc(void* context, const char* type); static constexpr int USER_ID = 100; static constexpr int INST_INDEX = 0; + int64_t CountTime(); }; void UDMFTest::SetUpTestCase() @@ -164,6 +167,12 @@ void UDMFTest::SetHapToken1() SetSelfTokenID(tokenId); } +void UDMFTest::SetHapToken2() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo2", INST_INDEX); + SetSelfTokenID(tokenId); +} + bool UDMFTest::CheckUnsignedChar(unsigned char* dst, unsigned char* src, int size) { EXPECT_NE(dst, nullptr); @@ -186,11 +195,16 @@ void* UDMFTest::GetDataCallbackFunc(void* context, const char* type) return plainText; } +int64_t UDMFTest::CountTime() +{ + return std::chrono::duration_cast<std::chrono::milliseconds>( + std::chrono::system_clock::now().time_since_epoch()).count(); +} + /** * @tc.name: OH_Udmf_CreateUnifiedData001 * @tc.desc: test OH_UdmfData_Create * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_CreateUnifiedData001, TestSize.Level0) { @@ -204,7 +218,6 @@ HWTEST_F(UDMFTest, OH_Udmf_CreateUnifiedData001, TestSize.Level0) * @tc.name: OH_Udmf_AddRecordToUnifiedData001 * @tc.desc: OH_UdmfData_AddRecord with return UDMF_E_INVALID_PARAM * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_AddRecordToUnifiedData001, TestSize.Level0) { @@ -232,7 +245,6 @@ HWTEST_F(UDMFTest, OH_Udmf_AddRecordToUnifiedData001, TestSize.Level0) * @tc.name: OH_Udmf_AddRecordToUnifiedData002 * @tc.desc: OH_UdmfData_AddRecord with return UDMF_E_OK * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_AddRecordToUnifiedData002, TestSize.Level0) { @@ -249,7 +261,6 @@ HWTEST_F(UDMFTest, OH_Udmf_AddRecordToUnifiedData002, TestSize.Level0) * @tc.name: OH_Udmf_HasUnifiedDataType001 * @tc.desc: OH_UdmfData_HasType with return UDMF_E_INVALID_PARAM * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_HasUnifiedDataType001, TestSize.Level0) { @@ -276,7 +287,6 @@ HWTEST_F(UDMFTest, OH_Udmf_HasUnifiedDataType001, TestSize.Level0) * @tc.name: OH_Udmf_HasUnifiedDataType002 * @tc.desc: OH_UdmfData_HasType with return whether has type, number 1 represent true, number 0 represent false * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_HasUnifiedDataType002, TestSize.Level0) { @@ -303,7 +313,6 @@ HWTEST_F(UDMFTest, OH_Udmf_HasUnifiedDataType002, TestSize.Level0) * @tc.name: OH_Udmf_GetUnifiedDataTypes001 * @tc.desc: OH_UdmfData_GetTypes with invalid params * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedDataTypes001, TestSize.Level0) { @@ -327,7 +336,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedDataTypes001, TestSize.Level0) * @tc.name: OH_Udmf_GetUnifiedDataTypes002 * @tc.desc: OH_UdmfData_GetTypes with valid params * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedDataTypes002, TestSize.Level0) { @@ -359,7 +367,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedDataTypes002, TestSize.Level0) * @tc.name: OH_Udmf_GetUnifiedRecordTypes001 * @tc.desc: OH_UdmfRecord_GetTypes with invalid params * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedRecordTypes001, TestSize.Level0) { @@ -382,7 +389,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedRecordTypes001, TestSize.Level0) * @tc.name: OH_Udmf_GetUnifiedRecordTypes002 * @tc.desc: OH_UdmfRecord_GetTypes with valid params * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedRecordTypes002, TestSize.Level0) { @@ -407,7 +413,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedRecordTypes002, TestSize.Level0) * @tc.name: OH_Udmf_GetRecords001 * @tc.desc: OH_UdmfRecord_GetTypes with invalid params * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetRecords001, TestSize.Level0) { @@ -431,7 +436,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetRecords001, TestSize.Level0) * @tc.name: OH_Udmf_GetRecords002 * @tc.desc: OH_UdmfRecord_GetTypes with valid params * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetRecords002, TestSize.Level0) { @@ -466,7 +470,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetRecords002, TestSize.Level0) * @tc.name: OH_Udmf_SetUnifiedData001 * @tc.desc: OH_Udmf_SetUnifiedData with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, UdmfTest006, TestSize.Level0) { @@ -497,7 +500,6 @@ HWTEST_F(UDMFTest, UdmfTest006, TestSize.Level0) * @tc.name: OH_Udmf_GetUnifiedData001 * @tc.desc: OH_Udmf_GetUnifiedData with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedData001, TestSize.Level0) { @@ -523,7 +525,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedData001, TestSize.Level0) * @tc.name: OH_Udmf_SetAndGetUnifiedData001 * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with valid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData001, TestSize.Level0) { @@ -563,7 +564,6 @@ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData001, TestSize.Level0) * @tc.name: OH_Udmf_SetAndGetUnifiedData002 * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with valid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData002, TestSize.Level0) { @@ -599,7 +599,6 @@ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData002, TestSize.Level0) * @tc.name: OH_Udmf_CreateUnifiedRecord001 * @tc.desc: OH_Udmf_CreateUnifiedRecord001 * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_CreateUnifiedRecord001, TestSize.Level0) { @@ -613,7 +612,6 @@ HWTEST_F(UDMFTest, OH_Udmf_CreateUnifiedRecord001, TestSize.Level0) * @tc.name: OH_Udmf_AddGeneralEntry001 * @tc.desc: test OH_UdmfRecord_AddGeneralEntry with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_AddGeneralEntry001, TestSize.Level0) { @@ -639,7 +637,6 @@ HWTEST_F(UDMFTest, OH_Udmf_AddGeneralEntry001, TestSize.Level0) * @tc.name: OH_Udmf_GetGeneralEntry001 * @tc.desc: test OH_UdmfRecord_GetGeneralEntry with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetGeneralEntry001, TestSize.Level0) { @@ -664,7 +661,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetGeneralEntry001, TestSize.Level0) * @tc.name: OH_Udmf_AddAndGetGeneralEntry002 * @tc.desc: test OH_UdmfRecord_AddGeneralEntry and OH_UdmfRecord_GetGeneralEntry with valid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_AddAndGetGeneralEntry002, TestSize.Level0) { @@ -741,7 +737,6 @@ HWTEST_F(UDMFTest, OH_Udmf_AddAndGetGeneralEntry004, TestSize.Level0) * @tc.name: OH_Udmf_BuildRecordByPlainText001 * @tc.desc: test OH_UdmfRecord_AddPlainText with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_BuildRecordByPlainText001, TestSize.Level0) { @@ -767,7 +762,6 @@ HWTEST_F(UDMFTest, OH_Udmf_BuildRecordByPlainText001, TestSize.Level0) * @tc.name: OH_Udmf_GetPlainTextFromRecord001 * @tc.desc: test OH_UdmfRecord_GetPlainText with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetPlainTextFromRecord001, TestSize.Level0) { @@ -793,7 +787,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetPlainTextFromRecord001, TestSize.Level0) * @tc.name: OH_Udmf_BuildAndGetPlainTextFromRecord001 * @tc.desc: test OH_UdmfRecord_GetPlainText and OH_Udmf_BuildPlainTextFromRecord with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_BuildAndGetPlainTextFromRecord001, TestSize.Level0) { @@ -820,7 +813,6 @@ HWTEST_F(UDMFTest, OH_Udmf_BuildAndGetPlainTextFromRecord001, TestSize.Level0) * @tc.name: OH_Udmf_BuildRecordByHyperlink001 * @tc.desc: test OH_UdmfRecord_AddHyperlink with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_BuildRecordByHyperlink001, TestSize.Level0) { @@ -846,7 +838,6 @@ HWTEST_F(UDMFTest, OH_Udmf_BuildRecordByHyperlink001, TestSize.Level0) * @tc.name: OH_Udmf_GetHyperlinkFromRecord001 * @tc.desc: test OH_UdmfRecord_GetHyperlink with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetHyperlinkFromRecord001, TestSize.Level0) { @@ -872,7 +863,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetHyperlinkFromRecord001, TestSize.Level0) * @tc.name: OH_Udmf_BuildAndGetHyperlinkFromRecord001 * @tc.desc: test OH_Udmf_BuildAndGetHyperlinkFromRecord with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_BuildAndGetHyperlinkFromRecord001, TestSize.Level0) { @@ -899,7 +889,6 @@ HWTEST_F(UDMFTest, OH_Udmf_BuildAndGetHyperlinkFromRecord001, TestSize.Level0) * @tc.name: OH_Udmf_BuildRecordByHtml001 * @tc.desc: test OH_UdmfRecord_AddHtml with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_BuildRecordByHtml001, TestSize.Level0) { @@ -925,7 +914,6 @@ HWTEST_F(UDMFTest, OH_Udmf_BuildRecordByHtml001, TestSize.Level0) * @tc.name: OH_Udmf_GetHtmlFromRecord001 * @tc.desc: test OH_UdmfRecord_GetHtml with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetHtmlFromRecord001, TestSize.Level0) { @@ -951,7 +939,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetHtmlFromRecord001, TestSize.Level0) * @tc.name: OH_Udmf_BuildAndGetHtmlFromRecord001 * @tc.desc: test OH_Udmf_BuildAndGetHtmlFromRecord with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_BuildAndGetHtmlFromRecord001, TestSize.Level0) { @@ -978,7 +965,6 @@ HWTEST_F(UDMFTest, OH_Udmf_BuildAndGetHtmlFromRecord001, TestSize.Level0) * @tc.name: OH_Udmf_BuildRecordByOpenHarmonyAppItem001 * @tc.desc: test OH_UdmfRecord_AddAppItem with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_BuildRecordByOpenHarmonyAppItem001, TestSize.Level0) { @@ -1004,7 +990,6 @@ HWTEST_F(UDMFTest, OH_Udmf_BuildRecordByOpenHarmonyAppItem001, TestSize.Level0) * @tc.name: OH_Udmf_GetOpenHarmonyAppItemFromRecord001 * @tc.desc: test OH_UdmfRecord_GetAppItem with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetOpenHarmonyAppItemFromRecord001, TestSize.Level0) { @@ -1030,7 +1015,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetOpenHarmonyAppItemFromRecord001, TestSize.Level0) * @tc.name: OH_Udmf_BuildAndGetAppItemFromRecord001 * @tc.desc: test OH_Udmf_BuildAndGetAppItemFromRecord with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_BuildAndGetAppItemFromRecord001, TestSize.Level0) { @@ -1416,7 +1400,7 @@ HWTEST_F(UDMFTest, OH_UdmfRecord_SetProvider001, TestSize.Level1) /** * @tc.name: OH_UdmfRecord_SetProvider002 - * @tc.desc: invalid parameters testcase of OH_UdmfRecord_SetProvider + * @tc.desc: valid parameters testcase of OH_UdmfRecord_SetProvider * @tc.type: FUNC */ HWTEST_F(UDMFTest, OH_UdmfRecord_SetProvider002, TestSize.Level1) @@ -1438,6 +1422,39 @@ HWTEST_F(UDMFTest, OH_UdmfRecord_SetProvider002, TestSize.Level1) OH_UdmfRecordProvider_Destroy(provider); } +/** + * @tc.name: OH_UdmfRecord_SetProvider003 + * @tc.desc: invalid parameters testcase of OH_UdmfRecord_SetProvider + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_UdmfRecord_SetProvider003, TestSize.Level1) +{ + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsPlainText *plainText = OH_UdsPlainText_Create(); + char content[] = "hello world"; + OH_UdsPlainText_SetContent(plainText, content); + OH_UdmfRecord_AddPlainText(record, plainText); + OH_UdmfRecordProvider* provider = OH_UdmfRecordProvider_Create(); + EXPECT_NE(provider, nullptr); + int num = 1; + void* context = &num; + OH_UdmfRecordProvider_SetData(provider, context, GetDataCallbackFunc, FinalizeFunc); + const char* types[3] = { "general.plain-text", "general.hyperlink", "general.html" }; + + int res = OH_UdmfRecord_SetProvider(record, types, MAX_TYPES_COUNT + 1, provider); + EXPECT_EQ(res, UDMF_E_INVALID_PARAM); + + res = OH_UdmfRecord_SetProvider(record, types, 0, provider); + EXPECT_EQ(res, UDMF_E_INVALID_PARAM); + + res = OH_UdmfRecord_SetProvider(record, nullptr, MAX_TYPES_COUNT + 1, provider); + EXPECT_EQ(res, UDMF_E_INVALID_PARAM); + + res = OH_UdmfRecord_SetProvider(record, types, 3, nullptr); + EXPECT_EQ(res, UDMF_E_INVALID_PARAM); + OH_UdmfRecordProvider_Destroy(provider); +} + /** * @tc.name: OH_Udmf_BuildRecordByOpenHarmonyArrayBuffer001 * @tc.desc: test OH_UdmfRecord_AddArrayBuffer with invalid param @@ -1986,10 +2003,9 @@ HWTEST_F(UDMFTest, FileUriTest001, TestSize.Level1) for (unsigned int idx = 0; idx < recordCount; ++idx) { unsigned int recordTypeCount; char** recordTypes = OH_UdmfRecord_GetTypes(records[idx], &recordTypeCount); - EXPECT_EQ(recordTypeCount, 2); + EXPECT_EQ(recordTypeCount, 1); EXPECT_NE(recordTypes, nullptr); - EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_IMAGE), 0); - EXPECT_EQ(strcmp(recordTypes[1], UDMF_META_GENERAL_FILE_URI), 0); + EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_GENERAL_FILE_URI), 0); for (unsigned int recordIdx = 0; recordIdx < recordTypeCount; ++recordIdx) { if (strcmp(recordTypes[recordIdx], UDMF_META_GENERAL_FILE_URI) == 0) { OH_UdsFileUri* fileUri = OH_UdsFileUri_Create(); @@ -2041,34 +2057,24 @@ HWTEST_F(UDMFTest, FileUriTest002, TestSize.Level1) EXPECT_EQ(recordCount, 2); EXPECT_NE(records, nullptr); - for (unsigned int idx = 0; idx < recordCount; idx++) { - unsigned int recordTypeCount; - char** recordTypes = OH_UdmfRecord_GetTypes(records[idx], &recordTypeCount); - EXPECT_NE(recordTypes, nullptr); - if (recordTypeCount == 1) { - EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_PLAIN_TEXT), 0); - for (unsigned int recordIdx = 0; recordIdx < recordTypeCount; ++recordIdx) { - OH_UdsPlainText* text = OH_UdsPlainText_Create(); - int getPlaintextRet = OH_UdmfRecord_GetPlainText(records[idx], text); - EXPECT_EQ(getPlaintextRet, UDMF_E_OK); - const char* getContent = OH_UdsPlainText_GetContent(text); - EXPECT_EQ(strcmp(getContent, content.c_str()), 0); - } - } - if (recordTypeCount == 2) { - EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_IMAGE), 0); - EXPECT_EQ(strcmp(recordTypes[1], UDMF_META_GENERAL_FILE_URI), 0); - for (unsigned int recordIdx = 0; recordIdx < recordTypeCount; ++recordIdx) { - if (strcmp(recordTypes[recordIdx], UDMF_META_GENERAL_FILE_URI) == 0) { - OH_UdsFileUri* fileUri = OH_UdsFileUri_Create(); - int getFileUriRet = OH_UdmfRecord_GetFileUri(records[idx], fileUri); - EXPECT_EQ(getFileUriRet, UDMF_E_OK); - const char* getFileUri = OH_UdsFileUri_GetFileUri(fileUri); - EXPECT_EQ(strcmp(getFileUri, uri.c_str()), 0); - } - } - } - } + unsigned int recordTypeCount; + char** recordTypes = OH_UdmfRecord_GetTypes(records[0], &recordTypeCount); + EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_GENERAL_FILE_URI), 0); + EXPECT_EQ(recordTypeCount, 1); + OH_UdsFileUri* fileUri = OH_UdsFileUri_Create(); + int getFileUriRet = OH_UdmfRecord_GetFileUri(records[0], fileUri); + EXPECT_EQ(getFileUriRet, UDMF_E_OK); + const char* getFileUri = OH_UdsFileUri_GetFileUri(fileUri); + EXPECT_EQ(strcmp(getFileUri, uri.c_str()), 0); + + recordTypes = OH_UdmfRecord_GetTypes(records[1], &recordTypeCount); + EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_PLAIN_TEXT), 0); + EXPECT_EQ(recordTypeCount, 1); + OH_UdsPlainText* text = OH_UdsPlainText_Create(); + int getPlaintextRet = OH_UdmfRecord_GetPlainText(records[1], text); + EXPECT_EQ(getPlaintextRet, UDMF_E_OK); + const char* getContent = OH_UdsPlainText_GetContent(text); + EXPECT_EQ(strcmp(getContent, content.c_str()), 0); } /** @@ -2108,10 +2114,9 @@ HWTEST_F(UDMFTest, FileUriTest003, TestSize.Level1) for (unsigned int idx = 0; idx < recordCount; ++idx) { unsigned int recordTypeCount; char** recordTypes = OH_UdmfRecord_GetTypes(records[idx], &recordTypeCount); - EXPECT_EQ(recordTypeCount, 2); + EXPECT_EQ(recordTypeCount, 1); EXPECT_NE(recordTypes, nullptr); - EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_AUDIO), 0); - EXPECT_EQ(strcmp(recordTypes[1], UDMF_META_GENERAL_FILE_URI), 0); + EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_GENERAL_FILE_URI), 0); for (unsigned int recordIdx = 0; recordIdx < recordTypeCount; ++recordIdx) { if (strcmp(recordTypes[recordIdx], UDMF_META_GENERAL_FILE_URI) == 0) { OH_UdsFileUri* fileUri = OH_UdsFileUri_Create(); @@ -2161,10 +2166,9 @@ HWTEST_F(UDMFTest, FileUriTest004, TestSize.Level1) for (unsigned int idx = 0; idx < recordCount; ++idx) { unsigned int recordTypeCount; char** recordTypes = OH_UdmfRecord_GetTypes(records[idx], &recordTypeCount); - EXPECT_EQ(recordTypeCount, 2); + EXPECT_EQ(recordTypeCount, 1); EXPECT_NE(recordTypes, nullptr); - EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_GENERAL_FILE), 0); - EXPECT_EQ(strcmp(recordTypes[1], UDMF_META_GENERAL_FILE_URI), 0); + EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_GENERAL_FILE_URI), 0); for (unsigned int recordIdx = 0; recordIdx < recordTypeCount; ++recordIdx) { if (strcmp(recordTypes[recordIdx], UDMF_META_GENERAL_FILE_URI) == 0) { OH_UdsFileUri* fileUri = OH_UdsFileUri_Create(); @@ -2270,10 +2274,9 @@ HWTEST_F(UDMFTest, FileUriTest006, TestSize.Level1) for (unsigned int idx = 0; idx < recordCount; ++idx) { unsigned int recordTypeCount; char** recordTypes = OH_UdmfRecord_GetTypes(records[idx], &recordTypeCount); - EXPECT_EQ(recordTypeCount, 2); + EXPECT_EQ(recordTypeCount, 1); EXPECT_NE(recordTypes, nullptr); - EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_VIDEO), 0); - EXPECT_EQ(strcmp(recordTypes[1], UDMF_META_GENERAL_FILE_URI), 0); + EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_GENERAL_FILE_URI), 0); for (unsigned int recordIdx = 0; recordIdx < recordTypeCount; ++recordIdx) { if (strcmp(recordTypes[recordIdx], UDMF_META_GENERAL_FILE_URI) == 0) { OH_UdsFileUri* fileUri = OH_UdsFileUri_Create(); @@ -2347,7 +2350,6 @@ HWTEST_F(UDMFTest, FileUriTest007, TestSize.Level1) * @tc.name: OH_Udmf_SetAndGetUnifiedData003 * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with file uri * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData003, TestSize.Level1) { @@ -2388,7 +2390,6 @@ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData003, TestSize.Level1) * @tc.name: OH_Udmf_SetAndGetUnifiedData004 * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with file uri * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData004, TestSize.Level1) { @@ -2428,7 +2429,6 @@ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData004, TestSize.Level1) * @tc.name: OH_Udmf_SetAndGetUnifiedData005 * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with file uri * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData005, TestSize.Level1) { @@ -2509,4 +2509,1351 @@ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData006, TestSize.Level1) OH_UdsContentForm_Destroy(getContentForm); OH_UdmfData_Destroy(readUnifiedData); } + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData007 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with invlid params + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData007, TestSize.Level1) +{ + std::string uri = "file://file_010.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_MENU; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + Udmf_Intention intention1 = UDMF_INTENTION_SYSTEM_SHARE; + int getRes = OH_Udmf_GetUnifiedData(key, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + char key1[UDMF_KEY_BUFFER_LEN]; + getRes = OH_Udmf_GetUnifiedData(key1, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + getRes = OH_Udmf_GetUnifiedData(key1, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData008 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with invlid params + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData008, TestSize.Level1) +{ + std::string uri = "file://file_011.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_SYSTEM_SHARE; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + Udmf_Intention intention1 = UDMF_INTENTION_MENU; + int getRes = OH_Udmf_GetUnifiedData(key, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + char key1[UDMF_KEY_BUFFER_LEN]; + getRes = OH_Udmf_GetUnifiedData(key1, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + getRes = OH_Udmf_GetUnifiedData(key1, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData009 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with UDMF_ERR + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData009, TestSize.Level1) +{ + std::string uri = "file://file_009.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_PICKER; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + Udmf_Intention intention1 = UDMF_INTENTION_MENU; + int getRes = OH_Udmf_GetUnifiedData(key, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + char key1[UDMF_KEY_BUFFER_LEN]; + getRes = OH_Udmf_GetUnifiedData(key1, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + getRes = OH_Udmf_GetUnifiedData(key1, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData010 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with file uri + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData010, TestSize.Level1) +{ + std::string uri = "file://file_010.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_PICKER; + char key[UDMF_KEY_BUFFER_LEN]; + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + SetHapToken2(); + int getRes = OH_Udmf_GetUnifiedData(key, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData011 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with file uri + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData011, TestSize.Level1) +{ + std::string uri = "file://file_011.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_MENU; + char key[UDMF_KEY_BUFFER_LEN]; + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + SetHapToken2(); + int getRes = OH_Udmf_GetUnifiedData(key, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData012 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with file uri + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData012, TestSize.Level1) +{ + std::string uri = "file://file_012.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_SYSTEM_SHARE; + char key[UDMF_KEY_BUFFER_LEN]; + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + SetHapToken2(); + int getRes = OH_Udmf_GetUnifiedData(key, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData013 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData013, TestSize.Level1) +{ + std::string uri = "file://file_007.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdsContentForm *contentForm = OH_UdsContentForm_Create(); + unsigned char thumbData[] = {0, 1, 2, 3, 4}; + OH_UdsContentForm_SetThumbData(contentForm, thumbData, 5); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_SYSTEM_SHARE; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + Udmf_Intention intention1 = UDMF_INTENTION_PICKER; + int getRes = OH_Udmf_GetUnifiedData(key, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + char key1[UDMF_KEY_BUFFER_LEN] = "udmf://aaabbbccc/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + getRes = OH_Udmf_GetUnifiedData(key1, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + getRes = OH_Udmf_GetUnifiedData(key1, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData014 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData014, TestSize.Level1) +{ + std::string uri = "file://file_008.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_PICKER; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + Udmf_Intention intention1 = UDMF_INTENTION_SYSTEM_SHARE; + int getRes = OH_Udmf_GetUnifiedData(key, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + char key1[UDMF_KEY_BUFFER_LEN] = "udmf://aaabbbccc/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + getRes = OH_Udmf_GetUnifiedData(key1, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + getRes = OH_Udmf_GetUnifiedData(key1, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData015 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData015, TestSize.Level1) +{ + std::string uri = "file://file_009.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_MENU; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + Udmf_Intention intention1 = UDMF_INTENTION_SYSTEM_SHARE; + int getRes = OH_Udmf_GetUnifiedData(key, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + char key1[UDMF_KEY_BUFFER_LEN] = "udmf://aaabbbccc/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + getRes = OH_Udmf_GetUnifiedData(key1, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + intention = UDMF_INTENTION_MENU; + getRes = OH_Udmf_GetUnifiedData(key1, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData016 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData016, TestSize.Level1) +{ + std::string uri = "file://file_010.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + for (int32_t i = 0; i < 1000; i++) { + OH_UdmfRecord_AddFileUri(record, fileUri); + } + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_SYSTEM_SHARE; + char key[UDMF_KEY_BUFFER_LEN]; + int64_t start = CountTime(); + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "systemshare setdata 1000 cost timet:%{public}" PRIi64, (end - start)); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + start = CountTime(); + int getRes = OH_Udmf_GetUnifiedData(key, intention, readUnifiedData); + end = CountTime(); + LOG_INFO(UDMF_TEST, "systemshare setdata 1000 cost timet:%{public}" PRIi64, (end - start)); + EXPECT_EQ(getRes, UDMF_E_OK); + + OH_UdsFileUri_Destroy(fileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData017 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData017, TestSize.Level1) +{ + std::string uri = "file://file_008.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + for (int32_t i = 0; i < 1000; i++) { + OH_UdmfRecord_AddFileUri(record, fileUri); + } + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_PICKER; + char key[UDMF_KEY_BUFFER_LEN]; + + int64_t start = CountTime(); + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "picker setdata 1000 cost timet:%{public}" PRIi64, (end - start)); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + start = CountTime(); + int getRes = OH_Udmf_GetUnifiedData(key, intention, readUnifiedData); + end = CountTime(); + LOG_INFO(UDMF_TEST, "picker setdata 1000 cost timet:%{public}" PRIi64, (end - start)); + EXPECT_EQ(getRes, UDMF_E_OK); + + OH_UdsFileUri_Destroy(fileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData018 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData018, TestSize.Level1) +{ + std::string uri = "file://file_010.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + for (int32_t i = 0; i < 1000; i++) { + OH_UdmfRecord_AddFileUri(record, fileUri); + } + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_MENU; + char key[UDMF_KEY_BUFFER_LEN]; + int64_t start = CountTime(); + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "menu setdata 1000 cost timet:%{public}" PRIi64, (end - start)); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + start = CountTime(); + int getRes = OH_Udmf_GetUnifiedData(key, intention, readUnifiedData); + end = CountTime(); + LOG_INFO(UDMF_TEST, "menu setdata 1000 cost timet:%{public}" PRIi64, (end - start)); + EXPECT_EQ(getRes, UDMF_E_OK); + + OH_UdsFileUri_Destroy(fileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +static OH_UdmfData* CreateImageDataWithFileUri(const std::string& uriStr) +{ + std::string uri = uriStr; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + return udmfUnifiedData; +} + +/** + * @tc.name: OH_UdmfOptions001 + * @tc.desc: OH_UdmfOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_UdmfOptions001, TestSize.Level1) +{ + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + ASSERT_TRUE(options != nullptr); + const char* testKey = "testKey"; + int result = OH_UdmfOptions_SetKey(options, testKey); + EXPECT_EQ(result, UDMF_E_OK); + const char* getKey = OH_UdmfOptions_GetKey(options); + EXPECT_STREQ(getKey, testKey); + Udmf_Intention testIntention = UDMF_INTENTION_DRAG; + int setResult = OH_UdmfOptions_SetIntention(options, testIntention); + EXPECT_EQ(setResult, UDMF_E_OK); + Udmf_Intention getIntention = OH_UdmfOptions_GetIntention(options); + EXPECT_EQ(getIntention, testIntention); + int resetResult = OH_UdmfOptions_Reset(options); + EXPECT_EQ(resetResult, UDMF_E_OK); + EXPECT_EQ(options->key.empty(), true); + EXPECT_EQ(options->intention, Udmf_Intention {}); + OH_UdmfOptions_Destroy(options); +} + +/** + * @tc.name: OH_UdmfOptions002 + * @tc.desc: OH_UdmfOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_UdmfOptions002, TestSize.Level1) +{ + OH_UdmfOptions* options1 = nullptr; + const char * key = nullptr; + int setRes = OH_UdmfOptions_SetKey(options1, key); + EXPECT_EQ(setRes, UDMF_E_INVALID_PARAM); + const char* getRes = OH_UdmfOptions_GetKey(options1); + EXPECT_EQ(getRes, nullptr); + Udmf_Intention testIntention = UDMF_INTENTION_DRAG; + OH_UdmfOptions_GetIntention(options1); + int setIntention = OH_UdmfOptions_SetIntention(options1, testIntention); + EXPECT_EQ(setIntention, UDMF_E_INVALID_PARAM); + int reSet = OH_UdmfOptions_Reset(options1); + EXPECT_EQ(reSet, UDMF_E_INVALID_PARAM); + OH_UdmfOptions_Destroy(options1); +} + +/** + * @tc.name: OH_Udmf_SetUnifiedDataByOptions001 + * @tc.desc: OH_Udmf_SetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetUnifiedDataByOptions001, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DRAG; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_INVALID_PARAM); + + OH_UdmfOptions_Destroy(options); + OH_UdsFileUri_Destroy(fileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedDataByOptions001 + * @tc.desc: OH_Udmf_SetUnifiedDataByOptions and OH_Udmf_GetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedDataByOptions001, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + std::string uri2 = "https://new/uri/path.jpg"; + OH_UdmfData *udmfUnifiedData2 = OH_UdmfData_Create(); + OH_UdmfRecord *record2 = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri2 = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri2, uri2.c_str()); + OH_UdsFileUri_SetFileType(fileUri2, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record2, fileUri2); + OH_UdmfData_AddRecord(udmfUnifiedData2, record2); + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_DATA_HUB; + char key2[UDMF_KEY_BUFFER_LEN]; + int setRes2 = OH_Udmf_SetUnifiedDataByOptions(options2, udmfUnifiedData2, key2, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes2, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options, &dataArray, &dataSize); + EXPECT_EQ(getRes, UDMF_E_OK); + EXPECT_NE(dataArray, nullptr); + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options2, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + EXPECT_NE(dataArray2, nullptr); + EXPECT_EQ(dataSize2, 2); + OH_Udmf_DestroyDataArray(&dataArray, dataSize); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options2); + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(fileUri2); + OH_UdmfRecord_Destroy(record); + OH_UdmfRecord_Destroy(record2); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(udmfUnifiedData2); +} + +/** + * @tc.name: OH_Udmf_UpdateUnifiedData001 + * @tc.desc: OH_Udmf_UpdateUnifiedData001 with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_UpdateUnifiedData001, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + char key[UDMF_KEY_BUFFER_LEN]; + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + std::string uri2 = "https://new/uri/path.jpg"; + OH_UdmfData *udmfUnifiedData2 = OH_UdmfData_Create(); + OH_UdmfRecord *record2 = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri2 = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri2, uri2.c_str()); + OH_UdsFileUri_SetFileType(fileUri2, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record2, fileUri2); + OH_UdmfData_AddRecord(udmfUnifiedData2, record2); + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_DATA_HUB; + options2->key = key; + int updataRes = OH_Udmf_UpdateUnifiedData(options2, udmfUnifiedData2); + EXPECT_EQ(updataRes, UDMF_E_OK); + + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options2, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + EXPECT_NE(dataArray2, nullptr); + EXPECT_EQ(dataSize2, 1); + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options2); + + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(fileUri2); + OH_UdmfRecord_Destroy(record); + OH_UdmfRecord_Destroy(record2); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(udmfUnifiedData2); +} + +/** + * @tc.name: OH_Udmf_GetUnifiedDataByOptions001 + * @tc.desc: OH_Udmf_GetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedDataByOptions001, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_PICKER; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + OH_UdmfOptions* options1 = OH_UdmfOptions_Create(); + options1->intention = UDMF_INTENTION_PICKER; + options1->key = key; + unsigned dataSize1 = 0; + OH_UdmfData* dataArray1 = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options1, &dataArray1, &dataSize1); + EXPECT_EQ(getRes, UDMF_E_OK); + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray1[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + OH_Udmf_DestroyDataArray(&dataArray1, dataSize1); + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options1); + + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_GetUnifiedDataByOptions002 + * @tc.desc: OH_Udmf_GetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedDataByOptions002, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_MENU; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + OH_UdmfOptions* options1 = OH_UdmfOptions_Create(); + options1->intention = UDMF_INTENTION_MENU; + options1->key = key; + unsigned dataSize1 = 0; + OH_UdmfData* dataArray1 = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options1, &dataArray1, &dataSize1); + EXPECT_EQ(getRes, UDMF_E_OK); + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray1[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + OH_Udmf_DestroyDataArray(&dataArray1, dataSize1); + + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options1); + + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_DeleteUnifiedData001 + * @tc.desc: OH_Udmf_DeleteUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_DeleteUnifiedData001, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + int dateleRes = OH_Udmf_DeleteUnifiedData(options, &dataArray, &dataSize); + EXPECT_EQ(dateleRes, UDMF_E_OK); + EXPECT_NE(dataArray, nullptr); + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + OH_Udmf_DestroyDataArray(&dataArray, dataSize); + + OH_UdmfOptions_Destroy(options); + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_DeleteUnifiedData002 + * @tc.desc: OH_Udmf_DeleteUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_DeleteUnifiedData002, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_SYSTEM_SHARE; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + OH_UdmfOptions* options1 = OH_UdmfOptions_Create(); + options1->intention = UDMF_INTENTION_SYSTEM_SHARE; + options1->key = key; + unsigned int dataSize1 = 0; + OH_UdmfData* dataArray1 = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options1, &dataArray1, &dataSize1); + EXPECT_EQ(getRes, UDMF_E_OK); + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray1[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_SYSTEM_SHARE; + options2->key = key; + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options2, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + + OH_Udmf_DestroyDataArray(&dataArray1, dataSize1); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options1); + OH_UdmfOptions_Destroy(options2); + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_DeleteUnifiedData003 + * @tc.desc: OH_Udmf_DeleteUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_DeleteUnifiedData003, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_PICKER; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_PICKER; + options2->key = key; + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options2, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + EXPECT_NE(dataArray2, nullptr); + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray2[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options2); + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_DeleteUnifiedData004 + * @tc.desc: OH_Udmf_DeleteUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_DeleteUnifiedData004, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_MENU; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_MENU; + options2->key = key; + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options2, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + EXPECT_NE(dataArray2, nullptr); + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray2[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options2); + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_GetUnifiedDataByOptions003 + * @tc.desc: OH_Udmf_GetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedDataByOptions003, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = nullptr; + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options, &dataArray, &dataSize); + EXPECT_EQ(getRes, UDMF_E_INVALID_PARAM); + + OH_UdmfOptions* options1 = OH_UdmfOptions_Create(); + options1->intention = UDMF_INTENTION_DRAG; + unsigned int dataSize1 = 0; + OH_UdmfData* dataArray1 = nullptr; + int getRes1 = OH_Udmf_GetUnifiedDataByOptions(options1, &dataArray1, &dataSize1); + EXPECT_EQ(getRes1, UDMF_E_INVALID_PARAM); + + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_MENU; + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int getRes2 = OH_Udmf_GetUnifiedDataByOptions(options2, &dataArray2, &dataSize2); + EXPECT_EQ(getRes2, UDMF_ERR); + + OH_UdmfOptions_Destroy(options1); + OH_UdmfOptions_Destroy(options2); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + OH_Udmf_DestroyDataArray(&dataArray1, dataSize1); + OH_UdsFileUri_Destroy(fileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_UpdateUnifiedData002 + * @tc.desc: OH_Udmf_UpdateUnifiedData001 with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_UpdateUnifiedData002, TestSize.Level1) +{ + OH_UdmfData *udmfUnifiedData = nullptr; + OH_UdmfOptions* options = nullptr; + int updataRes = OH_Udmf_UpdateUnifiedData(options, udmfUnifiedData); + EXPECT_EQ(updataRes, UDMF_E_INVALID_PARAM); + + std::string uri2 = "https://new/uri/path.jpg"; + OH_UdmfData *udmfUnifiedData2 = OH_UdmfData_Create(); + OH_UdmfRecord *record2 = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri2 = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri2, uri2.c_str()); + OH_UdsFileUri_SetFileType(fileUri2, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record2, fileUri2); + OH_UdmfData_AddRecord(udmfUnifiedData2, record2); + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_DRAG; + options2->key = "testKey"; + int updataRes1 = OH_Udmf_UpdateUnifiedData(options2, udmfUnifiedData2); + EXPECT_EQ(updataRes1, UDMF_E_INVALID_PARAM); + + OH_UdmfOptions_Destroy(options2); + OH_UdsFileUri_Destroy(fileUri2); + OH_UdmfRecord_Destroy(record2); + OH_UdmfData_Destroy(udmfUnifiedData2); +} + +/** + * @tc.name: OH_Udmf_UpdateUnifiedData003 + * @tc.desc: OH_Udmf_UpdateUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_UpdateUnifiedData003, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx4.jpg"; + OH_UdmfData *udmfUnifiedData = CreateImageDataWithFileUri(uri); + OH_UdmfOptions* options = nullptr; + int upDataRes = OH_Udmf_UpdateUnifiedData(options, udmfUnifiedData); + EXPECT_EQ(upDataRes, UDMF_E_INVALID_PARAM); + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + upDataRes = OH_Udmf_UpdateUnifiedData(options, udmfUnifiedData); + EXPECT_EQ(upDataRes, UDMF_E_INVALID_PARAM); + OH_UdmfOptions_Destroy(options2); +} + +/** + * @tc.name: OH_Udmf_DeleteUnifiedData005 + * @tc.desc: OH_Udmf_DeleteUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_DeleteUnifiedData005, TestSize.Level1) +{ + unsigned int* dataSize = nullptr; + OH_UdmfData* dataArray = nullptr; + OH_UdmfOptions* options = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options, &dataArray, dataSize); + EXPECT_EQ(deleteRes, UDMF_E_INVALID_PARAM); + + unsigned int dataSize2 = 0 ; + OH_UdmfData* dataArray2 = nullptr; + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_DRAG; + options2->key = "testKey"; + int deleteRes2 = OH_Udmf_DeleteUnifiedData(options2, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes2, UDMF_E_INVALID_PARAM); + + OH_UdmfOptions_Destroy(options2); + OH_UdmfData* dataArray1 = nullptr; + OH_Udmf_DestroyDataArray(&dataArray1, dataSize2); +} + +/** + * @tc.name: OH_UdmfOptions_GetVisibility001 + * @tc.desc: OH_UdmfOptions_GetVisibility with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_UdmfOptions_GetVisibility001, TestSize.Level1) +{ + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->visibility = UDMF_OWN_PROCESS; + Udmf_Visibility getVisibility = OH_UdmfOptions_GetVisibility(options); + EXPECT_EQ(getVisibility, UDMF_OWN_PROCESS); + OH_UdmfOptions_Destroy(options); +} + +/** + * @tc.name: OH_UdmfOptions_GetVisibility002 + * @tc.desc: OH_UdmfOptions_GetVisibility with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_UdmfOptions_GetVisibility002, TestSize.Level1) +{ + OH_UdmfOptions* options = nullptr; + Udmf_Visibility getVisibility = OH_UdmfOptions_GetVisibility(options); + EXPECT_EQ(getVisibility, UDMF_ALL); +} + +/** + * @tc.name: OH_UdmfOptions_SetVisibility001 + * @tc.desc: OH_UdmfOptions_SetVisibility with content form + * @tc.type: FUNCF + */ +HWTEST_F(UDMFTest, OH_UdmfOptions_SetVisibility001, TestSize.Level1) +{ + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + Udmf_Visibility testVisibility = UDMF_ALL; + int setRes = OH_UdmfOptions_SetVisibility(options, testVisibility); + EXPECT_EQ(setRes, UDMF_E_OK); + OH_UdmfOptions_Destroy(options); +} + +/** + * @tc.name: OH_UdmfOptions_SetVisibility002 + * @tc.desc: OH_UdmfOptions_SetVisibility with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_UdmfOptions_SetVisibility002, TestSize.Level1) +{ + Udmf_Visibility testVisibility = UDMF_ALL; + OH_UdmfOptions* options = nullptr; + int setRes2 = OH_UdmfOptions_SetVisibility(options, testVisibility); + EXPECT_EQ(setRes2, UDMF_E_INVALID_PARAM); +} + +/** + * @tc.name: SetVisibilityAndGetVisibility001 + * @tc.desc: OH_UdmfOptions_SetVisibility and OH_UdmfOptions_GetVisibility with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, SetVisibilityAndGetVisibility001, TestSize.Level1) +{ + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + Udmf_Visibility testVisibility = UDMF_ALL; + int setRes = OH_UdmfOptions_SetVisibility(options, testVisibility); + EXPECT_EQ(setRes, UDMF_E_OK); + Udmf_Visibility getVisibility = OH_UdmfOptions_GetVisibility(options); + EXPECT_EQ(getVisibility, testVisibility); + OH_UdmfOptions_Destroy(options); +} + +/** + * @tc.name: SetVisibilityAndGetVisibility002 + * @tc.desc: OH_UdmfOptions_SetVisibility and OH_UdmfOptions_GetVisibility with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, SetVisibilityAndGetVisibility002, TestSize.Level1) +{ + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + Udmf_Visibility testVisibility = Udmf_Visibility::UDMF_OWN_PROCESS; + int setRes = OH_UdmfOptions_SetVisibility(options, testVisibility); + EXPECT_EQ(setRes, UDMF_E_OK); + Udmf_Visibility getVisibility = OH_UdmfOptions_GetVisibility(options); + EXPECT_EQ(getVisibility, testVisibility); + OH_UdmfOptions_Destroy(options); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedDataByOptions002 + * @tc.desc: OH_Udmf_SetUnifiedDataByOptions and OH_Udmf_GetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedDataByOptions002, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx2.jpg"; + OH_UdmfData *udmfUnifiedData = CreateImageDataWithFileUri(uri); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + options->visibility = UDMF_OWN_PROCESS; + char key[UDMF_KEY_BUFFER_LEN]; + unsigned int dataSize3 = 0; + OH_UdmfData* dataArray3 = nullptr; + OH_Udmf_DeleteUnifiedData(options, &dataArray3, &dataSize3); + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_DATA_HUB; + options2->key = key; + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options2, &dataArray, &dataSize); + EXPECT_EQ(getRes, UDMF_E_OK); + EXPECT_NE(dataArray, nullptr); + + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + EXPECT_NE(dataArray2, nullptr); + + OH_Udmf_DestroyDataArray(&dataArray, dataSize); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + OH_Udmf_DestroyDataArray(&dataArray3, dataSize3); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfOptions_Destroy(options); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedDataByOptions003 + * @tc.desc: OH_Udmf_SetUnifiedDataByOptions and OH_Udmf_GetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedDataByOptions003, TestSize.Level1) +{ + SetHapToken1(); + std::string uri = "https://xxx/xx/xx3.jpg"; + OH_UdmfData *udmfUnifiedData = CreateImageDataWithFileUri(uri); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + options->visibility = UDMF_OWN_PROCESS; + char key[UDMF_KEY_BUFFER_LEN]; + unsigned int dataSize3 = 0; + OH_UdmfData* dataArray3 = nullptr; + OH_Udmf_DeleteUnifiedData(options, &dataArray3, &dataSize3); + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + SetHapToken2(); + OH_UdmfOptions* options1 = OH_UdmfOptions_Create(); + options1->intention = UDMF_INTENTION_DATA_HUB; + options1->key = key; + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options1, &dataArray, &dataSize); + EXPECT_EQ(getRes, UDMF_E_OK); + EXPECT_EQ(dataArray, nullptr); + + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + EXPECT_NE(dataArray2, nullptr); + + OH_Udmf_DestroyDataArray(&dataArray, dataSize); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + OH_Udmf_DestroyDataArray(&dataArray3, dataSize3); + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options1); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedDataByOptions004 + * @tc.desc: OH_Udmf_SetUnifiedDataByOptions and OH_Udmf_GetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedDataByOptions004, TestSize.Level1) +{ + SetHapToken1(); + std::string uri = "https://xxx/xx/xx4.jpg"; + OH_UdmfData *udmfUnifiedData = CreateImageDataWithFileUri(uri); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + options->visibility = UDMF_ALL; + char key[UDMF_KEY_BUFFER_LEN]; + + unsigned int dataSize3 = 0; + OH_UdmfData* dataArray3 = nullptr; + OH_Udmf_DeleteUnifiedData(options, &dataArray3, &dataSize3); + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + SetHapToken2(); + OH_UdmfOptions* options1 = OH_UdmfOptions_Create(); + options1->intention = UDMF_INTENTION_DATA_HUB; + options1->key = key; + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options1, &dataArray, &dataSize); + EXPECT_EQ(getRes, UDMF_E_OK); + EXPECT_NE(dataArray, nullptr); + + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + EXPECT_NE(dataArray2, nullptr); + + OH_Udmf_DestroyDataArray(&dataArray, dataSize); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + OH_Udmf_DestroyDataArray(&dataArray3, dataSize3); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options1); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedDataByOptions005 + * @tc.desc: OH_Udmf_SetUnifiedDataByOptions and OH_Udmf_GetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedDataByOptions005, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx5.jpg"; + OH_UdmfData *udmfUnifiedData = CreateImageDataWithFileUri(uri); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + options->visibility = UDMF_ALL; + char key[UDMF_KEY_BUFFER_LEN]; + + unsigned int dataSize3 = 0; + OH_UdmfData* dataArray3 = nullptr; + OH_Udmf_DeleteUnifiedData(options, &dataArray3, &dataSize3); + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + OH_UdmfOptions* options1 = OH_UdmfOptions_Create(); + options1->intention = UDMF_INTENTION_DATA_HUB; + options1->key = key; + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options1, &dataArray, &dataSize); + EXPECT_EQ(getRes, UDMF_E_OK); + EXPECT_NE(dataArray, nullptr); + + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + EXPECT_NE(dataArray2, nullptr); + + OH_Udmf_DestroyDataArray(&dataArray, dataSize); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + OH_Udmf_DestroyDataArray(&dataArray3, dataSize3); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options1); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: DestroyUnifiedRecordArray001 + * @tc.desc: test DestroyUnifiedRecordArray + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, DestroyUnifiedRecordArray001, TestSize.Level1) +{ + OH_UdmfData *unifiedData = OH_UdmfData_Create(); + EXPECT_NE(unifiedData, nullptr); + std::shared_ptr<Object> object = std::make_shared<Object>(); + std::map<std::string, ValueType> map; + map["uniformDataType"] = UtdUtils::GetUtdIdFromUtdEnum(UDType::PLAIN_TEXT); + map["textContent"] = "content"; + map["abstract"] = "abstract"; + object->value_ = map; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(PLAIN_TEXT, object); + std::vector<std::shared_ptr<UnifiedRecord>> recordVec = { record }; + unifiedData->records = nullptr; + unifiedData->unifiedData_->SetRecords(recordVec); + unsigned int recordCount = 0; + OH_UdmfRecord **getRecords = OH_UdmfData_GetRecords(unifiedData, &recordCount); + EXPECT_EQ(recordCount, 1); + EXPECT_EQ(unifiedData->recordsCount, 1); + EXPECT_NE(getRecords[0], nullptr); + getRecords[0]->recordDataLen = 1; + getRecords[0]->recordData = new (std::nothrow) unsigned char[getRecords[0]->recordDataLen]; + unifiedData->records = getRecords; + OH_UdmfData_Destroy(unifiedData); + EXPECT_EQ(unifiedData->recordsCount, 0); +} } diff --git a/udmf/interfaces/ani/BUILD.gn b/udmf/interfaces/ani/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..657f9e78cacb4cb78aded9edf32672654c3479b7 --- /dev/null +++ b/udmf/interfaces/ani/BUILD.gn @@ -0,0 +1,131 @@ +# Copyright (c) 2021-2022 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/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/distributeddatamgr/udmf/udmf.gni") + +config("ani_config") { + include_dirs = [ + "native/include", + "${udmf_interfaces_path}/cj/include", + "${udmf_interfaces_path}/innerkits/data/", + "${udmf_interfaces_path}/innerkits/common", + ] +} + +group("udmf_data_ani") { + deps = [ + ":unifiedDataChannel_abc_etc", + ":unifieddatachannel_ani", + ":uniformTypeDescriptor_abc_etc", + ":uniformTypeDescriptor_ani", + ] +} + +ohos_shared_library("unifieddatachannel_ani") { + branch_protector_ret = "pac_ret" + sanitize = { + oundary_sanitize = true + ubsan = true + cfi = true + cfi_cross_dso = true + debug = false + } + sources = [ "native/src/unifieddatachannel_ani.cpp" ] + + public_configs = [ ":ani_config" ] + + deps = [ "${udmf_interfaces_path}/innerkits:udmf_client" ] + + external_deps = [ + "ability_base:want", + "ability_runtime:abilitykit_native", + "ability_runtime:ani_common", + "ability_runtime:appkit_native", + "ability_runtime:napi_common", + "c_utils:utils", + "hilog:libhilog", + "image_framework:image_ani", + "ipc:ipc_single", + "runtime_core:ani", + ] + + subsystem_name = "distributeddatamgr" + part_name = "udmf" + output_extension = "so" +} + +generate_static_abc("unifiedDataChannel_abc") { + base_url = "./ets" + files = [ "./ets/@ohos.data.unifiedDataChannel.ets" ] + dst_file = "$target_out_dir/data_unifiedDataChannel.abc" + out_puts = [ "$target_out_dir/data_unifiedDataChannel.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/data_unifiedDataChannel.abc" +} + +ohos_prebuilt_etc("unifiedDataChannel_abc_etc") { + source = "$target_out_dir/data_unifiedDataChannel.abc" + module_install_dir = "framework" + subsystem_name = "distributeddatamgr" + part_name = "udmf" + deps = [ ":unifiedDataChannel_abc" ] +} + +ohos_shared_library("uniformTypeDescriptor_ani") { + branch_protector_ret = "pac_ret" + sanitize = { + oundary_sanitize = true + ubsan = true + cfi = true + cfi_cross_dso = true + debug = false + } + public_configs = [ ":ani_config" ] + sources = [ "native/src/uniformTypeDescriptor_ani.cpp" ] + + deps = [ + "../innerkits:udmf_client", + "../innerkits:utd_client", + "../jskits:udmf_js_common", + ] + + external_deps = [ + "ability_runtime:abilitykit_native", + "c_utils:utils", + "hilog:libhilog", + "runtime_core:ani", + ] + + subsystem_name = "distributeddatamgr" + part_name = "udmf" + output_extension = "so" +} + +generate_static_abc("uniformTypeDescriptor_abc") { + base_url = "./ets" + files = [ "./ets/@ohos.data.uniformTypeDescriptor.ets" ] + dst_file = "$target_out_dir/data_uniformTypeDescriptor.abc" + out_puts = [ "$target_out_dir/data_uniformTypeDescriptor.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/data_uniformTypeDescriptor.abc" +} + +ohos_prebuilt_etc("uniformTypeDescriptor_abc_etc") { + source = "$target_out_dir/data_uniformTypeDescriptor.abc" + module_install_dir = "framework" + subsystem_name = "distributeddatamgr" + part_name = "udmf" + deps = [ ":uniformTypeDescriptor_abc" ] +} diff --git a/udmf/interfaces/ani/ets/@ohos.data.unifiedDataChannel.ets b/udmf/interfaces/ani/ets/@ohos.data.unifiedDataChannel.ets new file mode 100644 index 0000000000000000000000000000000000000000..cecc89942645e89e55ca1d5f9db374811e4a5e88 --- /dev/null +++ b/udmf/interfaces/ani/ets/@ohos.data.unifiedDataChannel.ets @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2025 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 image from "@ohos.multimedia.image"; +import Want from "@ohos.app.ability.Want"; + +type ValueType = number | string | boolean | image.PixelMap | Want | ArrayBuffer | object | null | undefined; + + export default namespace unifiedDataChannel { + export class Cleaner { + static { loadLibrary("unifieddatachannel_ani") } + static callback(cleaner: Cleaner): void { + cleaner.clean() + } + constructor(targetPtr: long) { + this.targetPtr = targetPtr + } + + native clean(): void + + private targetPtr: long = 0 + } + class FinalizationAgent<T extends Object> { + constructor(obj: T, ptr: long) { + this.register(obj, ptr); + } + + register(obj: T, ptr: long): void { + this.unregisterToken = {}; + this.cleaner = new Cleaner(ptr); + finalizer.register(obj, this.cleaner!, this.unregisterToken); + } + + unregister(): void { + finalizer.unregister(this.unregisterToken); + } + + private cleaner: Cleaner | null = null; + private unregisterToken: object; + } + + let finalizer = new FinalizationRegistry<Cleaner>(Cleaner.callback) + export class UnifiedRecord { + static { loadLibrary("unifieddatachannel_ani") } + + constructor(type?: string, value?: ValueType) { + if (type == undefined) { + this.initRecordWithOutTypeValue(); + } else { + this.init(type, value); + } + this.registerCleaner(); + } + + registerCleaner(): void { + this.fzAgent = new FinalizationAgent<UnifiedRecord>(this, this.nativePtr); + } + + unregisterCleaner(): void { + this.fzAgent.unregister(); + } + setNativePtr(context: long) { + this.nativePtr = context; + } + + private fzAgent: FinalizationAgent<UnifiedRecord>; + native init(type: string, value: ValueType): void; + native initRecordWithOutTypeValue(): void; + private nativePtr: long = 0; + } + + export class UnifiedData { + static { loadLibrary("unifieddatachannel_ani") } + constructor(record?: UnifiedRecord) { + if (record == undefined) { + this.initDataWithOutRecord(); + } else { + this.initData(record); + } + this.registerCleaner(); + } + + registerCleaner(): void { + this.fzAgent = new FinalizationAgent<UnifiedData>(this, this.nativePtr); + } + + unregisterCleaner(): void { + this.fzAgent.unregister(); + } + native initData(record: UnifiedRecord): void; + native initDataWithOutRecord(): void; + native getRecords(): Array<UnifiedRecord>; + + getNativePtr(): long { + return this.nativePtr; + } + + private fzAgent: FinalizationAgent<UnifiedData>; + private nativePtr: long = 0; + } +} \ No newline at end of file diff --git a/udmf/interfaces/ani/ets/@ohos.data.uniformTypeDescriptor.ets b/udmf/interfaces/ani/ets/@ohos.data.uniformTypeDescriptor.ets new file mode 100644 index 0000000000000000000000000000000000000000..cfb6872017aaf6961edd22000858cd76fed716bd --- /dev/null +++ b/udmf/interfaces/ani/ets/@ohos.data.uniformTypeDescriptor.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 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. + */ + + export default namespace uniformTypeDescriptor { + loadLibrary("uniformTypeDescriptor_ani") + export native function getUniformDataTypeByFilenameExtension(filenameExtension: string, belongsTo?: string): string; + } \ No newline at end of file diff --git a/udmf/interfaces/ani/native/include/ani_util_class.h b/udmf/interfaces/ani/native/include/ani_util_class.h new file mode 100644 index 0000000000000000000000000000000000000000..33fa53c8736975d3f7f16c5c15e185d90cfb6ff7 --- /dev/null +++ b/udmf/interfaces/ani/native/include/ani_util_class.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2025 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 ANI_UTIL_CLASS_H +#define ANI_UTIL_CLASS_H + +#include <ani.h> +#include <cstdarg> + +#include "ani_util_common.h" + +class AniTypeFinder { +public: + AniTypeFinder(ani_env *env) : env_(env) {} + + expected<ani_namespace, ani_status> FindNamespace(const char *nsName) + { + ani_namespace ns; + ani_status status = env_->FindNamespace(nsName, &ns); + if (ANI_OK != status) { + return status; + } + return ns; + } + + template <typename... Names> + expected<ani_namespace, ani_status> FindNamespace(const char *firstNs, const char *nextNs, Names... restNs) + { + ani_namespace ns; + ani_status status = env_->FindNamespace(firstNs, &ns); + if (ANI_OK != status) { + return status; + } + return FindNamespace(ns, nextNs, restNs...); + } + + expected<ani_class, ani_status> FindClass(const char *clsName) + { + ani_class cls; + ani_status status = env_->FindClass(clsName, &cls); + if (ANI_OK != status) { + return status; + } + return cls; + } + + expected<ani_class, ani_status> FindClass(const char *nsName, const char *clsName) + { + auto ns = FindNamespace(nsName, clsName); + if (!ns.has_value()) { + return ns.error(); + } + return FindClass(ns.value(), clsName); + } + + template <typename... Names> + expected<ani_class, ani_status> FindClass(const char *firstNs, + const char *secondNs, + Names... restNs, + const char *clsName) + { + auto ns = FindNamespace(firstNs, secondNs, restNs...); + if (!ns.has_value()) { + return ns.error(); + } + return FindClass(ns.value(), clsName); + } + + expected<ani_class, ani_status> FindClass(ani_namespace ns, const char *clsName) + { + ani_class cls; + ani_status status = env_->Namespace_FindClass(ns, clsName, &cls); + if (ANI_OK != status) { + return status; + } + return cls; + } + + expected<ani_enum, ani_status> FindEnum(ani_namespace ns, const char *enumName) + { + ani_enum aniEnum {}; + ani_status status = env_->Namespace_FindEnum(ns, enumName, &aniEnum); + if (ANI_OK != status) { + return status; + } + return aniEnum; + } + +private: + template <typename... Names> + expected<ani_namespace, ani_status> FindNamespace(ani_namespace currentNs, const char *nextNs, Names... restNs) + { + ani_namespace ns; + ani_status status = env_->Namespace_FindNamespace(currentNs, nextNs, &ns); + if (ANI_OK != status) { + return status; + } + return FindNamespace(ns, restNs...); + } + + expected<ani_namespace, ani_status> FindNamespace(ani_namespace currentNs) + { + return currentNs; + } + +private: + ani_env *env_ = nullptr; +}; + +#endif diff --git a/udmf/interfaces/ani/native/include/ani_util_common.h b/udmf/interfaces/ani/native/include/ani_util_common.h new file mode 100644 index 0000000000000000000000000000000000000000..5b5cb55412949a8265baa41c858544eb473d1f3c --- /dev/null +++ b/udmf/interfaces/ani/native/include/ani_util_common.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2025 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 ANI_UTIL_COMMON_H +#define ANI_UTIL_COMMON_H + +#include <exception> +#include <memory> +#include <type_traits> +#include <utility> +#include <variant> + +template <typename T, typename E> +class expected { +private: + std::variant<T, E> data_; + bool has_value_; + +public: + expected(const T &value) : data_(value), has_value_(true) {} + + expected(T &&value) : data_(std::move(value)), has_value_(true) {} + + expected(const E &error) : data_(error), has_value_(false) {} + + expected(E &&error) : data_(std::move(error)), has_value_(false) {} + + bool has_value() const noexcept + { + return has_value_; + } + + explicit operator bool() const noexcept + { + return has_value(); + } + + T &value() & + { + if (!has_value()) { + std::terminate(); + } + return std::get<T>(data_); + } + + const T &value() const & + { + if (!has_value()) { + std::terminate(); + } + return std::get<T>(data_); + } + + T &&value() && + { + if (!has_value()) { + std::terminate(); + } + return std::get<T>(std::move(data_)); + } + + E &error() & + { + if (has_value()) { + std::terminate(); + } + return std::get<E>(data_); + } + + const E &error() const & + { + if (has_value()) { + std::terminate(); + } + return std::get<E>(data_); + } + + E &&error() && + { + if (has_value()) { + std::terminate(); + } + return std::get<E>(std::move(data_)); + } + + T &operator*() & + { + return value(); + } + + const T &operator*() const & + { + return value(); + } + + T &&operator*() && + { + return std::move(*this).value(); + } + + T *operator->() + { + return &value(); + } + + const T *operator->() const + { + return &value(); + } + + template <typename U> + T value_or(U &&default_value) const & + { + return has_value() ? value() : static_cast<T>(std::forward<U>(default_value)); + } + + template <typename U> + T value_or(U &&default_value) && + { + return has_value() ? std::move(*this).value() : static_cast<T>(std::forward<U>(default_value)); + } +}; + +template <typename F> +class FinalAction { +public: + explicit FinalAction(F func) : func_(std::move(func)) {} + + ~FinalAction() noexcept(noexcept(func_())) + { + if (!dismissed_) { + func_(); + } + } + + FinalAction(const FinalAction &) = delete; + FinalAction &operator=(const FinalAction &) = delete; + + FinalAction(FinalAction &&other) noexcept : func_(std::move(other.func_)), dismissed_(other.dismissed_) + { + other.dismissed_ = true; + } + + void dismiss() noexcept + { + dismissed_ = true; + } + +private: + F func_; + bool dismissed_ = false; +}; + +template <typename F> +inline FinalAction<F> finally(F &&func) +{ + return FinalAction<F>(std::forward<F>(func)); +} + +#endif diff --git a/udmf/interfaces/ani/native/include/ani_util_native_ptr.h b/udmf/interfaces/ani/native/include/ani_util_native_ptr.h new file mode 100644 index 0000000000000000000000000000000000000000..1ba4c34048a9a7f8dfdd4db89e36d459b82eddba --- /dev/null +++ b/udmf/interfaces/ani/native/include/ani_util_native_ptr.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2025 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 ANI_UTIL_OBJECT_H +#define ANI_UTIL_OBJECT_H + +#include <ani.h> +#include <memory> +#include <string> + +class NativeObject { +public: + virtual ~NativeObject() = default; +}; + +template <typename T> +class StdSharedPtrHolder : public NativeObject { +public: + StdSharedPtrHolder(const std::shared_ptr<T> &sptr) : sptr_(sptr) {} + + std::shared_ptr<T> Get() + { + return sptr_; + } + + std::shared_ptr<T> GetOrDefault() + { + if (!sptr_) { + sptr_ = std::make_shared<T>(); + } + return sptr_; + } + +private: + std::shared_ptr<T> sptr_; +}; + +class NativePtrCleaner { +public: + static void Clean([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) + { + ani_long ptr = 0; + if (ANI_OK != env->Object_GetFieldByName_Long(object, "targetPtr", &ptr)) { + return; + } + delete reinterpret_cast<NativeObject *>(ptr); + } + + NativePtrCleaner(ani_env *env) : env_(env) {} + + ani_status Bind(ani_class cls) + { + std::array methods = { + ani_native_function {"clean", nullptr, reinterpret_cast<void *>(NativePtrCleaner::Clean)}, + }; + + if (ANI_OK != env_->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + return (ani_status)ANI_ERROR; + }; + + return ANI_OK; + } + +private: + ani_env *env_ = nullptr; +}; +#endif diff --git a/udmf/interfaces/ani/native/include/ani_utils.h b/udmf/interfaces/ani/native/include/ani_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..41102f0122f681533b136c5395a77e4b0a4afde4 --- /dev/null +++ b/udmf/interfaces/ani/native/include/ani_utils.h @@ -0,0 +1,455 @@ +/* + * Copyright (c) 2025 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 ANI_UTILS_H +#define ANI_UTILS_H + +#include <ani.h> + +#include <cstdarg> +#include <memory> +#include <mutex> +#include <optional> +#include <string> +#include <unordered_map> +#include <vector> +#include <iostream> +#include "ani_util_native_ptr.h" +#include "ani_util_class.h" + +class AniObjectUtils { +public: + static ani_object Create(ani_env *env, const char* nsName, const char* clsName, ...) + { + ani_object nullobj{}; + + ani_namespace ns; + if (ANI_OK != env->FindNamespace(nsName, &ns)) { + std::cerr << "[ANI] Not found namespace " << nsName << std::endl; + return nullobj; + } + + ani_class cls; + if (ANI_OK != env->Namespace_FindClass(ns, clsName, &cls)) { + std::cerr << "[ANI] Not found class " << clsName << std::endl; + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) { + std::cerr << "[ANI] Not found <ctor> for class " << clsName << std::endl; + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + std::cerr << "[ANI] Failed to Object_New for class " << cls << std::endl; + return nullobj; + } + return obj; + } + + static ani_object Create(ani_env *env, const char* clsName, ...) + { + ani_object nullobj{}; + + ani_class cls; + if (ANI_OK != env->FindClass(clsName, &cls)) { + std::cerr << "[ANI] Not found class " << clsName << std::endl; + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) { + std::cerr << "[ANI] Not found <ctor> for class " << clsName << std::endl; + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + std::cerr << "[ANI] Failed to Object_New for class " << cls << std::endl; + return nullobj; + } + return obj; + } + + static ani_object Create(ani_env *env, ani_class cls, ...) + { + ani_object nullobj{}; + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) { + std::cerr << "[ANI] Not found <ctor> for class" << std::endl; + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, cls); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + std::cerr << "[ANI] Failed to Object_New for class " << cls << std::endl; + return nullobj; + } + return obj; + } + + static ani_object From(ani_env *env, bool value) + { + return Create(env, "Lstd/core/Boolean;", static_cast<ani_boolean>(value)); + } + + template<typename T> + static ani_status Wrap(ani_env *env, ani_object object, T* nativePtr, const char* propName = "nativePtr") + { + return env->Object_SetFieldByName_Long(object, propName, reinterpret_cast<ani_long>(nativePtr)); + } + + template<typename T> + static T* Unwrap(ani_env *env, ani_object object, const char* propName = "nativePtr") + { + ani_long nativePtr; + if (ANI_OK != env->Object_GetFieldByName_Long(object, propName, &nativePtr)) { + return nullptr; + } + return reinterpret_cast<T*>(nativePtr); + } +}; + +class AniStringUtils { +public: + static std::string ToStd(ani_env *env, ani_string ani_str) + { + ani_size strSize; + env->String_GetUTF8Size(ani_str, &strSize); + + std::vector<char> buffer(strSize + 1); // +1 for null terminator + char* utf8_buffer = buffer.data(); + + //String_GetUTF8 Supportted by https://gitee.com/openharmony/arkcompiler_runtime_core/pulls/3416 + ani_size bytes_written = 0; + env->String_GetUTF8(ani_str, utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + return content; + } + + static ani_string ToAni(ani_env* env, const std::string& str) + { + ani_string aniStr = nullptr; + if (ANI_OK != env->String_NewUTF8(str.data(), str.size(), &aniStr)) { + std::cerr << "[ANI] Unsupported ANI_VERSION_1" << std::endl; + return nullptr; + } + return aniStr; + } +}; + +class UnionAccessor { +public: + UnionAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) + { + } + + bool IsInstanceOf(const std::string& cls_name) + { + ani_class cls; + env_->FindClass(cls_name.c_str(), &cls); + + ani_boolean ret; + env_->Object_InstanceOf(obj_, cls, &ret); + return ret; + } + + template<typename T> + bool IsInstanceOfType(); + + template<typename T> + bool TryConvert(T &value); + + template<typename T> + bool TryConvertArray(std::vector<T> &value); + +private: + ani_env *env_; + ani_object obj_; +}; + +template<> +bool UnionAccessor::IsInstanceOfType<bool>() +{ + return IsInstanceOf("Lstd/core/Boolean;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType<int>() +{ + return IsInstanceOf("Lstd/core/Int;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType<double>() +{ + return IsInstanceOf("Lstd/core/Double;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType<std::string>() +{ + return IsInstanceOf("Lstd/core/String;"); +} + +template<> +bool UnionAccessor::TryConvert<bool>(bool &value) +{ + if (!IsInstanceOfType<bool>()) { + return false; + } + + ani_boolean aniValue; + auto ret = env_->Object_CallMethodByName_Boolean(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast<bool>(aniValue); + return true; +} + +template<> +bool UnionAccessor::TryConvert<int>(int &value) +{ + if (!IsInstanceOfType<int>()) { + return false; + } + + ani_int aniValue; + auto ret = env_->Object_CallMethodByName_Int(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast<int>(aniValue); + return true; +} + +template<> +bool UnionAccessor::TryConvert<double>(double &value) +{ + if (!IsInstanceOfType<double>()) { + return false; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast<double>(aniValue); + return true; +} + +template<> +bool UnionAccessor::TryConvert<std::string>(std::string &value) +{ + if (!IsInstanceOfType<std::string>()) { + return false; + } + + value = AniStringUtils::ToStd(env_, static_cast<ani_string>(obj_)); + return true; +} + +template<> +bool UnionAccessor::TryConvertArray<bool>(std::vector<bool> &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + std::cerr << "Object_GetPropertyByName_Double length failed" << std::endl; + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + std::cerr << "Object_GetPropertyByName_Ref failed" << std::endl; + return false; + } + ani_boolean val; + if (ANI_OK != env_->Object_CallMethodByName_Boolean(static_cast<ani_object>(ref), "unboxed", nullptr, &val)) { + std::cerr << "Object_CallMethodByName_Double unbox failed" << std::endl; + return false; + } + value.push_back(static_cast<bool>(val)); + } + return true; +} + +template<> +bool UnionAccessor::TryConvertArray<int>(std::vector<int> &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + std::cerr << "Object_GetPropertyByName_Double length failed" << std::endl; + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + std::cerr << "Object_GetPropertyByName_Ref failed" << std::endl; + return false; + } + ani_int intValue; + if (ANI_OK != env_->Object_CallMethodByName_Int(static_cast<ani_object>(ref), "unboxed", nullptr, &intValue)) { + std::cerr << "Object_CallMethodByName_Double unbox failed" << std::endl; + return false; + } + value.push_back(static_cast<int>(intValue)); + } + return true; +} + +template<> +bool UnionAccessor::TryConvertArray<double>(std::vector<double> &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + std::cerr << "Object_GetPropertyByName_Double length failed" << std::endl; + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + std::cerr << "Object_GetPropertyByName_Ref failed" << std::endl; + return false; + } + ani_double val; + if (ANI_OK != env_->Object_CallMethodByName_Double(static_cast<ani_object>(ref), "unboxed", nullptr, &val)) { + std::cerr << "Object_CallMethodByName_Double unbox failed" << std::endl; + return false; + } + value.push_back(static_cast<double>(val)); + } + return true; +} + +template<> +bool UnionAccessor::TryConvertArray<uint8_t>(std::vector<uint8_t> &value) +{ + std::cout << "TryConvertArray std::vector<uint8_t>" << std::endl; + ani_ref buffer; + if (ANI_OK != env_->Object_GetFieldByName_Ref(obj_, "buffer", &buffer)) { + std::cout << "Object_GetFieldByName_Ref failed" << std::endl; + return false; + } + void* data; + size_t length; + if (ANI_OK != env_->ArrayBuffer_GetInfo(static_cast<ani_arraybuffer>(buffer), &data, &length)) { + std::cerr << "ArrayBuffer_GetInfo failed" << std::endl; + return false; + } + std::cout << "Length of buffer is " << length << std::endl; + for (size_t i = 0; i < length; i++) { + value.push_back(static_cast<uint8_t*>(data)[i]); + } + return true; +} + +template<> +bool UnionAccessor::TryConvertArray<std::string>(std::vector<std::string> &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + std::cerr << "Object_GetPropertyByName_Double length failed" << std::endl; + return false; + } + + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + std::cerr << "Object_GetPropertyByName_Double length failed" << std::endl; + return false; + } + value.push_back(AniStringUtils::ToStd(env_, static_cast<ani_string>(ref))); + } + return true; +} + +class OptionalAccessor { +public: + OptionalAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) + { + } + + bool IsUndefined() + { + ani_boolean isUndefined; + env_->Reference_IsUndefined(obj_, &isUndefined); + return isUndefined; + } + + template<typename T> + std::optional<T> Convert(); + +private: + ani_env *env_; + ani_object obj_; +}; + +template<> +std::optional<double> OptionalAccessor::Convert<double>() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "doubleValue", nullptr, &aniValue); + if (ret != ANI_OK) { + return std::nullopt; + } + auto value = static_cast<double>(aniValue); + return value; +} + +template<> +std::optional<std::string> OptionalAccessor::Convert<std::string>() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_size strSize; + env_->String_GetUTF8Size(static_cast<ani_string>(obj_), &strSize); + + std::vector<char> buffer(strSize + 1); + char* utf8_buffer = buffer.data(); + + ani_size bytes_written = 0; + env_->String_GetUTF8(static_cast<ani_string>(obj_), utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + return content; +} + +#endif diff --git a/relational_store/frameworks/native/gdb/include/trans_db.h b/udmf/interfaces/ani/native/include/unifieddatachannel_ani.h similarity index 43% rename from relational_store/frameworks/native/gdb/include/trans_db.h rename to udmf/interfaces/ani/native/include/unifieddatachannel_ani.h index 2694aa129e739af590aaddb1b12ebbdc23ea93fd..c6e500a0cb9e52f0d267cc19c2818832bcaf8836 100644 --- a/relational_store/frameworks/native/gdb/include/trans_db.h +++ b/udmf/interfaces/ani/native/include/unifieddatachannel_ani.h @@ -13,27 +13,46 @@ * limitations under the License. */ -#ifndef ARKDATA_INTELLIGENCE_PLATFORM_TRANS_DB_H -#define ARKDATA_INTELLIGENCE_PLATFORM_TRANS_DB_H +#ifndef UNIFIEDDATACHANNEL_H +#define UNIFIEDDATACHANNEL_H + +#include <ani.h> #include <memory> +#include <string> + +#include "unified_data.h" +#include "unified_record.h" -#include "connection.h" -#include "gdb_store.h" -#include "graph_statement.h" -namespace OHOS::DistributedDataAip { -class TransDB : public DBStore { +namespace OHOS { +namespace UDMF { +class UnifiedRecordHolder { public: - TransDB(std::shared_ptr<Connection> connection); - std::pair<int32_t, std::shared_ptr<Result>> QueryGql(const std::string &gql) override; - std::pair<int32_t, std::shared_ptr<Result>> ExecuteGql(const std::string &gql) override; + explicit UnifiedRecordHolder(ani_env *env, const std::string type, ani_object unionValue); + + const std::shared_ptr<UnifiedRecord> Get(); - std::pair<int32_t, std::shared_ptr<Transaction>> CreateTransaction() override; - int32_t Close() override; + void Set(ani_ref saveRemote); + + ~UnifiedRecordHolder(); private: - std::pair<int32_t, std::shared_ptr<Statement>> GetStatement(const std::string &gql) const; + ani_ref saveRemote_ = nullptr; + std::shared_ptr<UnifiedRecord> object_; +}; - std::weak_ptr<Connection> conn_; +class UnifiedDataHolder { +public: + explicit UnifiedDataHolder(UnifiedRecordHolder* recordHolder); + + std::shared_ptr<UnifiedData> Get(); + + void Set(ani_ref saveRemote); + ~UnifiedDataHolder(); + +private: + ani_ref saveRemote_ = nullptr; + std::shared_ptr<UnifiedData> object_; }; -} // namespace OHOS::DistributedDataAip -#endif // ARKDATA_INTELLIGENCE_PLATFORM_TRANS_DB_H \ No newline at end of file +} // namespace UDMF +} // namespace OHOS +#endif // UNIFIEDDATACHANNEL_H \ No newline at end of file diff --git a/udmf/interfaces/ani/native/src/unifieddatachannel_ani.cpp b/udmf/interfaces/ani/native/src/unifieddatachannel_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..52271da1ae6a687d205924f7a8ed9eefeb8d1b0b --- /dev/null +++ b/udmf/interfaces/ani/native/src/unifieddatachannel_ani.cpp @@ -0,0 +1,423 @@ + /* + * Copyright (c) 2025 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 "unifiedDataChannelANI" +#include "unifieddatachannel_ani.h" +#include "ani_utils.h" +#include "logger.h" +#include "ani_common_want.h" +#include "image_ani_utils.h" + +#include "unified_types.h" +#include "unified_meta.h" + +#include "plain_text.h" +#include "html.h" +#include "link.h" +#include "image.h" +#include "video.h" +#include "audio.h" +#include "folder.h" +#include "system_defined_appitem.h" +#include "system_defined_form.h" +#include "system_defined_pixelmap.h" +#include "application_defined_record.h" + +using namespace OHOS; +using namespace OHOS::UDMF; + +static UDMF::ValueType ParseANIRecordValueType(ani_env *env, const std::string type, ani_object unionValue) +{ + UnionAccessor unionAccessor(env, unionValue); + + double doubleValue = 0.0; + if (unionAccessor.TryConvert<double>(doubleValue)) { + return doubleValue; + } + + std::string stringValue; + if (unionAccessor.TryConvert<std::string>(stringValue)) { + return stringValue; + } + + bool boolValue = false; + if (unionAccessor.TryConvert<bool>(boolValue)) { + return boolValue; + } + + int intValue = 0; + if (unionAccessor.TryConvert<int>(intValue)) { + return intValue; + } + + std::vector<uint8_t> arrayVect; + if (unionAccessor.TryConvertArray<uint8_t>(arrayVect)) { + return arrayVect; + } + + if (!unionAccessor.IsInstanceOf("Lstd/core/Object;")) { + LOG_DEBUG(UDMF_KITS_NAPI, "ParseANIRecordValueType default std::monostate"); + return std::monostate(); + } + + if (type == "openharmony.pixel-map") { + auto pixelMap = Media::ImageAniUtils::GetPixelMapFromEnv(env, unionValue); + if (pixelMap == nullptr) { + return std::shared_ptr<Media::PixelMap>(nullptr); + } + std::shared_ptr<Media::PixelMap> pixelMapSpr(pixelMap); + return pixelMapSpr; + } else if (type == "openharmony.want") { + AAFwk::Want wantObj; + AppExecFwk::UnwrapWant(env, unionValue, wantObj); + return std::make_shared<AAFwk::Want>(wantObj); + } else { + return std::make_shared<Object>(); + } +} + +UnifiedRecordHolder::UnifiedRecordHolder(ani_env *env, const std::string type, ani_object unionValue) +{ + if (type.empty() && unionValue == nullptr) { + object_ = std::make_shared<UnifiedRecord>(); + return; + } + + UDType utdType = ENTITY; + if (UtdUtils::IsValidUtdId(type)) { + utdType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(type)); + } + + UDMF::ValueType value = ParseANIRecordValueType(env, type, unionValue); + + std::map<UDType, std::function<std::shared_ptr<UnifiedRecord>(UDType, ValueType)>> constructors = { + {TEXT, [](UDType type, ValueType value) { return std::make_shared<Text>(type, value); }}, + {PLAIN_TEXT, [](UDType type, ValueType value) { return std::make_shared<PlainText>(type, value); }}, + {HTML, [](UDType type, ValueType value) { return std::make_shared<Html>(type, value); }}, + {HYPERLINK, [](UDType type, ValueType value) { return std::make_shared<Link>(type, value); }}, + {UDType::FILE, [](UDType type, ValueType value) { return std::make_shared<File>(type, value); }}, + {IMAGE, [](UDType type, ValueType value) { return std::make_shared<Image>(type, value); }}, + {VIDEO, [](UDType type, ValueType value) { return std::make_shared<Video>(type, value); }}, + {AUDIO, [](UDType type, ValueType value) { return std::make_shared<Audio>(type, value); }}, + {FOLDER, [](UDType type, ValueType value) { return std::make_shared<Folder>(type, value); }}, + {SYSTEM_DEFINED_RECORD, [](UDType type, ValueType value) + { return std::make_shared<SystemDefinedRecord>(type, value); }}, + {SYSTEM_DEFINED_APP_ITEM, [](UDType type, ValueType value) + { return std::make_shared<SystemDefinedAppItem>(type, value); }}, + {SYSTEM_DEFINED_FORM, [](UDType type, ValueType value) + { return std::make_shared<SystemDefinedForm>(type, value); }}, + {SYSTEM_DEFINED_PIXEL_MAP, [](UDType type, ValueType value) + { return std::make_shared<SystemDefinedPixelMap>(type, value); }}, + {APPLICATION_DEFINED_RECORD, [](UDType type, ValueType value) + { return std::make_shared<ApplicationDefinedRecord>(type, value); }}, + }; + + auto constructor = constructors.find(utdType); + if (constructor == constructors.end()) { + object_ = std::make_shared<UnifiedRecord>(); + return; + } + + object_ = constructor->second(utdType, value); + if (utdType == APPLICATION_DEFINED_RECORD) { + std::shared_ptr<ApplicationDefinedRecord> applicationDefinedRecord = + std::static_pointer_cast<ApplicationDefinedRecord>(object_); + applicationDefinedRecord->SetApplicationDefinedType(type); + } +} + +const std::shared_ptr<UnifiedRecord> UnifiedRecordHolder::Get() +{ + if (object_ == nullptr) { + object_ = std::make_shared<UnifiedRecord>(); + } + return object_; +} + +void UnifiedRecordHolder::Set(ani_ref saveRemote) +{ + saveRemote_ = saveRemote; +} + +UnifiedRecordHolder::~UnifiedRecordHolder() +{ + LOG_DEBUG(UDMF_KITS_NAPI, "[ANI] enter UnifiedRecordHolder dtor "); +} + + +UnifiedDataHolder::UnifiedDataHolder(UnifiedRecordHolder* recordHolder) +{ + object_ = std::make_shared<UnifiedData>(); + + if (recordHolder != nullptr) { + auto recordPtr = recordHolder->Get(); + if (recordPtr != nullptr) { + object_->AddRecord(recordPtr); + } + } +} + +std::shared_ptr<UnifiedData> UnifiedDataHolder::Get() +{ + return object_; +} + +void UnifiedDataHolder::Set(ani_ref saveRemote) +{ + saveRemote_ = saveRemote; +} + +UnifiedDataHolder::~UnifiedDataHolder() +{ + LOG_DEBUG(UDMF_KITS_NAPI, "[ANI] enter UnifiedDataHolder dtor "); +} + +static void UnifiedRecodeValueTypeConstructor([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_string descriptor, ani_object unionValue) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "[ANI] enter UnifiedRecodeValueTypeConstructor"); + + ani_ref saveRemote = nullptr; + env->GlobalReference_Create(reinterpret_cast<ani_ref>(object), &saveRemote); + + auto type = AniStringUtils::ToStd(env, static_cast<ani_string>(descriptor)); + auto objectRemoteHolder = new UnifiedRecordHolder(env, type, unionValue); + objectRemoteHolder->Set(saveRemote); + AniObjectUtils::Wrap<UnifiedRecordHolder>(env, object, objectRemoteHolder); +} + +static void UnifiedRecodeConstructor([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "[ANI] enter UnifiedRecodeConstructor"); + if (env == nullptr) { + return; + } + ani_ref saveRemote = nullptr; + env->GlobalReference_Create(reinterpret_cast<ani_ref>(object), &saveRemote); + + auto objectRemoteHolder = new UnifiedRecordHolder(env, "", nullptr); + if (objectRemoteHolder == nullptr) { + return; + } + objectRemoteHolder->Set(saveRemote); + AniObjectUtils::Wrap<UnifiedRecordHolder>(env, object, objectRemoteHolder); +} + +static void UnifiedDataConstructor([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_object recordObj) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "[ANI] enter UnifiedDataConstructor "); + auto recoderHolder = AniObjectUtils::Unwrap<UnifiedRecordHolder>(env, recordObj); + + ani_ref saveRemote = nullptr; + env->GlobalReference_Create(reinterpret_cast<ani_ref>(object), &saveRemote); + + auto objectHolder = new UnifiedDataHolder(recoderHolder); + objectHolder->Set(saveRemote); + AniObjectUtils::Wrap<UnifiedDataHolder>(env, object, objectHolder); +} + +static void initDataWithOutRecordConstructor([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "[ANI] enter initDataWithOutRecordConstructor"); + if (env == nullptr) { + return; + } + ani_ref saveRemote = nullptr; + env->GlobalReference_Create(reinterpret_cast<ani_ref>(object), &saveRemote); + + auto objectHolder = new UnifiedDataHolder(nullptr); + if (objectHolder == nullptr) { + return; + } + objectHolder->Set(saveRemote); + AniObjectUtils::Wrap<UnifiedDataHolder>(env, object, objectHolder); +} + +static ani_object UnifiedRecordToObject(ani_env *env, std::shared_ptr<UnifiedRecord> record) +{ + ani_object aniObject = nullptr; + + static const char *nameSpaceName = "L@ohos/data/unifiedDataChannel/unifiedDataChannel;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(nameSpaceName, &ns)) { + LOG_ERROR(UDMF_KITS_NAPI, "Not found namespace %{public}s", nameSpaceName); + return aniObject; + } + + static const char *recordclsName = "LUnifiedRecord;"; + ani_class aniClass; + if (ANI_OK != env->Namespace_FindClass(ns, recordclsName, &aniClass)) { + LOG_ERROR(UDMF_KITS_NAPI, "Not found class %{public}s", recordclsName); + return aniObject; + } + + ani_method personInfoCtor; + if (ANI_OK != env->Class_FindMethod(aniClass, "setNativePtr", nullptr, &personInfoCtor)) { + LOG_ERROR(UDMF_KITS_NAPI, "Not found func setNativePtr"); + return aniObject; + } + + if (ANI_OK != env->Object_New(aniClass, personInfoCtor, &aniObject, reinterpret_cast<ani_long>(record.get()))) { + LOG_ERROR(UDMF_KITS_NAPI, "Object_New Failed"); + return aniObject; + } + return aniObject; +} + +static ani_object GetRecords([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj) +{ + ani_object arrayObj = nullptr; + ani_class arrayCls = nullptr; + if (ANI_OK != env->FindClass("Lescompat/Array;", &arrayCls)) { + LOG_ERROR(UDMF_KITS_NAPI, "FindClass Lescompat/Array; Failed"); + return arrayObj; + } + + ani_method arrayCtor; + if (ANI_OK != env->Class_FindMethod(arrayCls, "<ctor>", "I:V", &arrayCtor)) { + LOG_ERROR(UDMF_KITS_NAPI, "Class_FindMethod <ctor> Failed"); + return arrayObj; + } + + auto dataHolder = AniObjectUtils::Unwrap<UnifiedDataHolder>(env, obj); + if (dataHolder == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "UnifiedData unwrapp failed"); + return arrayObj; + } + + auto dataObj = dataHolder->Get(); + if (dataObj == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "dataHolder get empty..."); + return arrayObj; + } + + std::vector<std::shared_ptr<UnifiedRecord>> records = dataObj->GetRecords(); + if (ANI_OK != env->Object_New(arrayCls, arrayCtor, &arrayObj, records.size())) { + LOG_ERROR(UDMF_KITS_NAPI, "Object_New Array Faild"); + return arrayObj; + } + + ani_size index = 0; + for (const std::shared_ptr<UnifiedRecord> &recordPtr : records) { + auto aniRecord = UnifiedRecordToObject(env, recordPtr); + if (ANI_OK != env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, aniRecord)) { + LOG_ERROR(UDMF_KITS_NAPI, "Object_CallMethodByName_Void $_set Faild"); + break; + } + index++; + } + + LOG_DEBUG(UDMF_KITS_NAPI, "getRecords index:%{public}u", static_cast<uint32_t>(index)); + return arrayObj; +} + +static ani_status BindCleanerclassMethods(ani_env *env, ani_namespace &ns) +{ + auto cleanerCls = AniTypeFinder(env).FindClass(ns, "LCleaner;"); + return NativePtrCleaner(env).Bind(cleanerCls.value()); +} + +static ani_status LoadUnifiedRecord(ani_env *env, ani_namespace &ns) +{ + if (env == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "env is nullptr"); + return ANI_ERROR; + } + static const char *recordclsName = "LUnifiedRecord;"; + ani_class unifiedRecordClass; + if (ANI_OK != env->Namespace_FindClass(ns, recordclsName, &unifiedRecordClass)) { + LOG_ERROR(UDMF_KITS_NAPI, "Not found class %{public}s", recordclsName); + return ANI_NOT_FOUND; + } + + std::array methods = { + ani_native_function {"init", nullptr, reinterpret_cast<void *>(UnifiedRecodeValueTypeConstructor)}, + ani_native_function {"initRecordWithOutTypeValue", nullptr, reinterpret_cast<void *>(UnifiedRecodeConstructor)}, + }; + + if (ANI_OK != env->Class_BindNativeMethods(unifiedRecordClass, methods.data(), methods.size())) { + LOG_ERROR(UDMF_KITS_NAPI, "Cannot bind native methods to %{public}s", recordclsName); + return ANI_ERROR; + } + return ANI_OK; +} + +static ani_status LoadUnifiedData(ani_env *env, ani_namespace &ns) +{ + if (env == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "env is nullptr"); + return ANI_ERROR; + } + static const char *dataclsName = "LUnifiedData;"; + ani_class unifiedDataClass; + if (ANI_OK != env->Namespace_FindClass(ns, dataclsName, &unifiedDataClass)) { + LOG_ERROR(UDMF_KITS_NAPI, "Cannot find class %{public}s", dataclsName); + return ANI_NOT_FOUND; + } + + std::array datamethods = { + ani_native_function {"initData", nullptr, reinterpret_cast<void *>(UnifiedDataConstructor)}, + ani_native_function {"initDataWithOutRecord", nullptr, + reinterpret_cast<void *>(initDataWithOutRecordConstructor)}, + ani_native_function {"getRecords", nullptr, reinterpret_cast<void *>(GetRecords)}, + }; + + if (ANI_OK != env->Class_BindNativeMethods(unifiedDataClass, datamethods.data(), datamethods.size())) { + LOG_ERROR(UDMF_KITS_NAPI, "Cannot bind native methods to %{public}s", dataclsName); + return ANI_ERROR; + } + return ANI_OK; +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ANI_Constructor start..."); + + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + LOG_ERROR(UDMF_KITS_NAPI, "[ANI] Unsupported ANI_VERSION_1"); + return ANI_ERROR; + } + + static const char *nameSpaceName = "L@ohos/data/unifiedDataChannel/unifiedDataChannel;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(nameSpaceName, &ns)) { + LOG_ERROR(UDMF_KITS_NAPI, "Not found namespace %{public}s", nameSpaceName); + return ANI_NOT_FOUND; + } + + if (ANI_OK != LoadUnifiedRecord(env, ns)) { + LOG_ERROR(UDMF_KITS_NAPI, "LoadUnifiedRecord ERROR"); + return ANI_NOT_FOUND; + } + + if (ANI_OK != LoadUnifiedData(env, ns)) { + LOG_ERROR(UDMF_KITS_NAPI, "LoadUnifiedData ERROR"); + return ANI_NOT_FOUND; + } + + if (result == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "param result is null"); + return ANI_ERROR; + } + + if (ANI_OK != BindCleanerclassMethods(env, ns)) { + LOG_ERROR(UDMF_KITS_NAPI, "[ANI] BindCleanerclassMethods failed"); + return ANI_ERROR; + } + *result = ANI_VERSION_1; + LOG_DEBUG(UDMF_KITS_NAPI, "ANI_Constructor end..."); + return ANI_OK; +} diff --git a/udmf/interfaces/ani/native/src/uniformTypeDescriptor_ani.cpp b/udmf/interfaces/ani/native/src/uniformTypeDescriptor_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d819353b519dfc6a7b811a36b365de97acd2b554 --- /dev/null +++ b/udmf/interfaces/ani/native/src/uniformTypeDescriptor_ani.cpp @@ -0,0 +1,135 @@ + /* + * Copyright (c) 2025 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 "UniformTypeDescriptorAni" + +#include "ani_utils.h" +#include "logger.h" +#include "error_code.h" +#include "utd_client.h" +#include <ani.h> + +using namespace OHOS::UDMF; + +static uint32_t paramsCheckError = 401; + +static void ThrowBusinessError(ani_env *env, int errCode, std::string&& errMsg) +{ + LOG_INFO(UDMF_KITS_NAPI, "Begin ThrowBusinessError."); + static const char *errorClsName = "L@ohos/base/BusinessError;"; + ani_class cls {}; + if (ANI_OK != env->FindClass(errorClsName, &cls)) { + LOG_ERROR(UDMF_KITS_NAPI, "find class BusinessError %{public}s failed", errorClsName); + return; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", ":V", &ctor)) { + LOG_ERROR(UDMF_KITS_NAPI, "find method BusinessError.constructor failed"); + return; + } + ani_object errorObject; + if (ANI_OK != env->Object_New(cls, ctor, &errorObject)) { + LOG_ERROR(UDMF_KITS_NAPI, "create BusinessError object failed"); + return; + } + ani_double aniErrCode = static_cast<ani_double>(errCode); + ani_string errMsgStr; + if (ANI_OK != env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &errMsgStr)) { + LOG_ERROR(UDMF_KITS_NAPI, "convert errMsg to ani_string failed"); + return; + } + if (ANI_OK != env->Object_SetFieldByName_Double(errorObject, "code", aniErrCode)) { + LOG_ERROR(UDMF_KITS_NAPI, "set error code failed"); + return; + } + if (ANI_OK != env->Object_SetPropertyByName_Ref(errorObject, "message", errMsgStr)) { + LOG_ERROR(UDMF_KITS_NAPI, "set error message failed"); + return; + } + env->ThrowError(static_cast<ani_error>(errorObject)); + return; +} + +static ani_string GetUniformDataTypeByFilenameExtension(ani_env *env, ani_string filenameExtension, + ani_object belongsTo) +{ + LOG_INFO(UDMF_KITS_NAPI, "GetUniformDataTypeByFilenameExtension is called!"); + if (filenameExtension == nullptr) { + ThrowBusinessError(env, paramsCheckError, "ParserParam failed!"); + return nullptr; + } + std::string filenameExtension_ = AniStringUtils::ToStd(env, filenameExtension); + if (filenameExtension_.empty()) { + ThrowBusinessError(env, paramsCheckError, "ParserParam failed!"); + return nullptr; + } + ani_boolean isUndefined; + if (ANI_OK != env->Reference_IsUndefined(belongsTo, &isUndefined)) { + LOG_ERROR(UDMF_KITS_NAPI, "Object_GetFieldByName_Ref isRepeat failed."); + return nullptr; + } + std::string typeId; + auto status = E_OK; + if (isUndefined) { + status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension_, typeId); + } else { + std::string belongsTo_ = AniStringUtils::ToStd(env, static_cast<ani_string>(belongsTo)); + status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension_, typeId, belongsTo_); + } + + if (status != E_OK) { + LOG_ERROR(UDMF_KITS_NAPI, "invalid arguments!"); + return nullptr; + } + + if (!typeId.empty()) { + return AniStringUtils::ToAni(env, typeId); + } + return nullptr; +} + + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + LOG_ERROR(UDMF_KITS_NAPI, "Unsupported ANI_VERSION_1"); + return ANI_ERROR; + } + + static const char *nsName = "L@ohos/data/uniformTypeDescriptor/uniformTypeDescriptor;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(nsName, &ns)) { + LOG_ERROR(UDMF_KITS_NAPI, "Not found %{public}s", nsName); + return ANI_ERROR; + } + + std::array methods = { + ani_native_function {"getUniformDataTypeByFilenameExtension", nullptr, + reinterpret_cast<void *>(GetUniformDataTypeByFilenameExtension) }, + }; + + if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) { + LOG_ERROR(UDMF_KITS_NAPI, "Cannot bind native methods to %{public}s", nsName); + return ANI_ERROR; + }; + + if (result == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "param result is null"); + return ANI_ERROR; + } + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/udmf/interfaces/cj/BUILD.gn b/udmf/interfaces/cj/BUILD.gn index 5546b5b48520aed007966a7d6b6faa719b4135d8..44e5b75c68588ae680bcf048da85d62d5341878d 100644 --- a/udmf/interfaces/cj/BUILD.gn +++ b/udmf/interfaces/cj/BUILD.gn @@ -40,6 +40,8 @@ ohos_shared_library("cj_unified_data_channel_ffi") { "${udmf_interfaces_path}/cj/src/unified_data_impl.cpp", "${udmf_interfaces_path}/cj/src/unified_record_ffi.cpp", "${udmf_interfaces_path}/cj/src/unified_record_impl.cpp", + "${udmf_interfaces_path}/cj/src/unified_data_channel_ffi.cpp", + "${udmf_interfaces_path}/cj/src/unified_data_parameter_parse.cpp", "${udmf_interfaces_path}/cj/src/utils.cpp", ] @@ -50,6 +52,7 @@ ohos_shared_library("cj_unified_data_channel_ffi") { "ability_base:want", "ability_runtime:abilitykit_native", "ability_runtime:napi_common", + "ability_runtime:napi_base_context", "c_utils:utils", "hilog:libhilog", "image_framework:cj_image_ffi", diff --git a/udmf/interfaces/cj/include/unified_data_ffi.h b/udmf/interfaces/cj/include/unified_data_ffi.h index 489fd8e7ff9fb20aa5c0afa4e6242dc408b39b78..cf178bc7de67b4eb23f6d7a788deaf273e7fb204 100644 --- a/udmf/interfaces/cj/include/unified_data_ffi.h +++ b/udmf/interfaces/cj/include/unified_data_ffi.h @@ -17,6 +17,7 @@ #define UDMF_UNIFIED_DATA_FFI_H #include <cstdint> + #include "ffi_remote_data.h" #include "cj_common_ffi.h" @@ -25,14 +26,16 @@ namespace OHOS { namespace UDMF { extern "C" { - FFI_EXPORT int64_t FfiUDMFUnifiedDataConstructor(); - FFI_EXPORT int64_t FfiUDMFUnifiedDataConstructorwWithRecord(int64_t unifiedRecordId); - FFI_EXPORT void FfiUDMFUnifiedDataAddRecord(int64_t unifiedDataId, int64_t unifiedRecordId); - FFI_EXPORT CArrUnifiedRecord FfiUDMFUnifiedDataGetRecords(int64_t unifiedDataId); - FFI_EXPORT bool FfiUDMFUnifiedDataHasType(int64_t unifiedDataId, const char *type); - FFI_EXPORT CArrString FfiUDMFUnifiedDataGetTypes(int64_t unifiedDataId); -} -} +FFI_EXPORT int64_t FfiUDMFUnifiedDataConstructor(); +FFI_EXPORT int64_t FfiUDMFUnifiedDataConstructorWithRecord(int64_t unifiedRecordId); +FFI_EXPORT void FfiUDMFUnifiedDataAddRecord(int64_t unifiedDataId, int64_t unifiedRecordId); +FFI_EXPORT CArrUnifiedRecord FfiUDMFUnifiedDataGetRecords(int64_t unifiedDataId); +FFI_EXPORT bool FfiUDMFUnifiedDataHasType(int64_t unifiedDataId, const char *type); +FFI_EXPORT CArrString FfiUDMFUnifiedDataGetTypes(int64_t unifiedDataId); +FFI_EXPORT CUnifiedDataProperties FfiUDMFGetProperties(int64_t unifiedDataId); +FFI_EXPORT void FfiUDMFSetProperties(int64_t unifiedDataId, CUnifiedDataProperties properties); } +} // namespace UDMF +} // namespace OHOS #endif \ No newline at end of file diff --git a/udmf/interfaces/cj/include/unified_data_impl.h b/udmf/interfaces/cj/include/unified_data_impl.h index 0ccd94342978b58f5cc3852e20e8f4834e9a7545..ef073c3d44f4526ee9bc1f7a0a7151b6e2df812c 100644 --- a/udmf/interfaces/cj/include/unified_data_impl.h +++ b/udmf/interfaces/cj/include/unified_data_impl.h @@ -18,33 +18,51 @@ #include <memory> +#include "cj_common_ffi.h" #include "unified_data.h" #include "unified_record_impl.h" -#include "cj_common_ffi.h" namespace OHOS { namespace UDMF { - using namespace OHOS::UDMF; +using namespace OHOS::UDMF; + +typedef CArrI64 CArrUnifiedRecord; - typedef CArrI64 CArrUnifiedRecord; +struct CParameters { + int8_t valueType; + char *key; + void *value; + int64_t size; +}; - class CUnifiedData : public OHOS::FFI::FFIData { - DECL_TYPE(CUnifiedData, OHOS::FFI::FFIData) - public: - CUnifiedData(); - CUnifiedData(UDMF::CUnifiedRecord *record); +struct CArrParameters { + CParameters *head; + int64_t size; +}; - void AddRecord(UDMF::CUnifiedRecord *record); - CArrUnifiedRecord GetRecords(); - bool HasType(const char *type); - CArrString GetTypes(); +struct CUnifiedDataProperties { + CArrParameters extras; + char *tag; + int64_t timestamp; + int32_t shareOptions; +}; - private: - std::shared_ptr<UDMF::UnifiedData> unifiedData_; - std::vector<UDMF::CUnifiedRecord *> records_; - }; +class CUnifiedData : public OHOS::FFI::FFIData { + DECL_TYPE(CUnifiedData, OHOS::FFI::FFIData) +public: + CUnifiedData(); + CUnifiedData(sptr<UDMF::CUnifiedRecord> record); -} -} // namespace OHOS::UDMF + void AddRecord(sptr<UDMF::CUnifiedRecord> record); + CArrUnifiedRecord GetRecords(); + bool HasType(const char *type); + CArrString GetTypes(); + std::shared_ptr<UDMF::UnifiedData> unifiedData_; + +private: + std::vector<sptr<UDMF::CUnifiedRecord>> records_; +}; +} // namespace UDMF +} // namespace OHOS #endif \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_store_helper.h b/udmf/interfaces/cj/include/unified_data_parameter_parse.h similarity index 54% rename from relational_store/frameworks/js/napi/graphstore/include/napi_gdb_store_helper.h rename to udmf/interfaces/cj/include/unified_data_parameter_parse.h index 5190235094fc6a8e807db900135a3f9463bf84d5..b5806bb4485da244199b0acc3c0db68f2cd8c996 100644 --- a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_store_helper.h +++ b/udmf/interfaces/cj/include/unified_data_parameter_parse.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 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,22 +13,18 @@ * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_DB_STORE_HELPER_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_DB_STORE_HELPER_H +#ifndef UDMF_UNIFIED_DATA_PARAMETER_PARSE_H +#define UDMF_UNIFIED_DATA_PARAMETER_PARSE_H -#include <memory> -#include <string> -#include <vector> - -#include "napi/native_api.h" -#include "napi/native_common.h" -#include "napi/native_node_api.h" -#include "napi_gdb_error.h" - - -namespace OHOS::GraphStoreJsKit { -napi_value InitGdbHelper(napi_env env, napi_value exports); -} // namespace OHOS::GraphStoreJsKit +#include "unified_data_impl.h" +#include "want.h" +namespace OHOS { +namespace UDMF { +using WantParams = OHOS::AAFwk::WantParams; +void SetDataParameters(CArrParameters parameters, WantParams &wantP); +void ParseParameters(WantParams &wantP, CArrParameters &parameters, int32_t &code); +} // namespace UDMF +} // namespace OHOS #endif \ No newline at end of file diff --git a/udmf/interfaces/cj/include/unified_record_ffi.h b/udmf/interfaces/cj/include/unified_record_ffi.h index 11cdecd7980d9551b32de81236c378f245925111..48bd3941d9eb19f5bcdedc689db1b03738b8a010 100644 --- a/udmf/interfaces/cj/include/unified_record_ffi.h +++ b/udmf/interfaces/cj/include/unified_record_ffi.h @@ -18,20 +18,46 @@ #include <cstdint> -#include "ffi_remote_data.h" #include "cj_common_ffi.h" - +#include "ffi_remote_data.h" #include "unified_record_impl.h" namespace OHOS { namespace UDMF { extern "C" { - FFI_EXPORT int64_t FfiUDMFUnifiedRecordConstructor(); - FFI_EXPORT int64_t FfiUDMFUnifiedRecordConstructorwithType(const char *type, CJValueType value); - FFI_EXPORT char *FfiUDMFUnifiedRecordGetType(int64_t unifiedId); - FFI_EXPORT CJValueType FfiUDMFUnifiedRecordGetValue(int64_t unifiedId); -} -} +FFI_EXPORT int64_t FfiUDMFUnifiedRecordConstructor(); +FFI_EXPORT int64_t FfiUDMFUnifiedRecordConstructorwithOnlyType(const char *type); +FFI_EXPORT int64_t FfiUDMFUnifiedRecordConstructorwithType(const char *type, CJValueType value); +FFI_EXPORT char *FfiUDMFUnifiedRecordGetType(int64_t unifiedId); +FFI_EXPORT CJValueType FfiUDMFUnifiedRecordGetValue(int64_t unifiedId); + +FFI_EXPORT int64_t FfiUDMFFileSetUri(int64_t id, const char *uri); +FFI_EXPORT char *FfiUDMFFileGetUri(int64_t id); +FFI_EXPORT CRecord FfiUDMFFileGetDetails(int64_t id); +FFI_EXPORT int64_t FfiUDMFFileSetDetails(int64_t id, CRecord record); + +FFI_EXPORT char *FfiUDMFImageGetImageUri(int64_t id); +FFI_EXPORT int64_t FfiUDMFImageSetImageUri(int64_t id, const char *uri); + +FFI_EXPORT char *FfiUDMFVideoGetVideoUri(int64_t id); +FFI_EXPORT int64_t FfiUDMFVideoSetVideoUri(int64_t id, const char *uri); + +FFI_EXPORT CRecord FfiUDMFTextGetDetails(int64_t id); +FFI_EXPORT int64_t FfiUDMFTextSetDetails(int64_t id, CRecord record); + +FFI_EXPORT char *FfiUDMFHyperLinkGetUrl(int64_t id); +FFI_EXPORT int64_t FfiUDMFHyperLinkSetUrl(int64_t id, const char *url); + +FFI_EXPORT char *FfiUDMFHyperLinkGetDescription(int64_t id); +FFI_EXPORT int64_t FfiUDMFHyperLinkSetDescription(int64_t id, const char *description); + +FFI_EXPORT char *FfiUDMFPlainTextGetTextContent(int64_t id); +FFI_EXPORT int64_t FfiUDMFPlainTextSetTextContent(int64_t id, const char *text); + +FFI_EXPORT char *FfiUDMFPlainTextGetAbstract(int64_t id); +FFI_EXPORT int64_t FfiUDMFPlainTextSetAbstract(int64_t id, const char *abstr); } +} // namespace UDMF +} // namespace OHOS #endif \ No newline at end of file diff --git a/udmf/interfaces/cj/include/unified_record_impl.h b/udmf/interfaces/cj/include/unified_record_impl.h index d2bb331a2e0ede9b5087a0ca35c53531a8d5330e..d5c1a1f62715c271f2d3fea100b34d3eecdc60bd 100644 --- a/udmf/interfaces/cj/include/unified_record_impl.h +++ b/udmf/interfaces/cj/include/unified_record_impl.h @@ -16,55 +16,85 @@ #ifndef UDMF_UNIFIED_RECORD_IMPL_H #define UDMF_UNIFIED_RECORD_IMPL_H -#include "unified_record.h" #include "cj_common_ffi.h" +#include "ffi_remote_data.h" +#include "unified_record.h" namespace OHOS { namespace UDMF { - using namespace OHOS::UDMF; +struct CRecord { + CArrString keys; + CArrString values; +}; - struct CJValueType { - int32_t integer32; - int64_t integer64; - double dou; - bool boolean; - char *string; - CArrUI8 byteArray; - int64_t pixelMapId; - - uint8_t tag; - }; - - enum TypeSymbol { - INTEGER32 = 0, - INTEGER64 = 1, - DOUBLE = 2, - BOOLEAN = 3, - STRING = 4, - BYTEARRAY = 5, - PIXELMAP = 6, - NULLTAG = 7, - UNDEFINED = 8 - }; - - class CUnifiedRecord : public OHOS::FFI::FFIData { - DECL_TYPE(CUnifiedRecord, OHOS::FFI::FFIData) - public: - CUnifiedRecord(); - CUnifiedRecord(const char *type, CJValueType value); - CJValueType ValueType2CJValueType(ValueType value); - ValueType CJValueType2ValueType(CJValueType value); - char *GetType(); - CJValueType GetValue(); - - const std::shared_ptr<UDMF::UnifiedRecord> &GetUnifiedRecord() const; - - private: - std::shared_ptr<UDMF::UnifiedRecord> unifiedRecord_; - int64_t pixelMapId_ = 0; - }; - -} -} // namespace OHOS::UDMF +struct CJValueType { + int32_t integer32; + int64_t integer64; + double dou; + bool boolean; + char *string; + CArrUI8 byteArray; + int64_t pixelMapId; + uint8_t tag; +}; + +enum TypeSymbol { + INTEGER32 = 0, + INTEGER64 = 1, + DOUBLE = 2, + BOOLEAN = 3, + STRING = 4, + BYTEARRAY = 5, + PIXELMAP = 6, + NULLTAG = 7, + UNDEFINED = 8 +}; + +class CUnifiedRecord : public OHOS::FFI::FFIData { + DECL_TYPE(CUnifiedRecord, OHOS::FFI::FFIData) +public: + CUnifiedRecord(); + CUnifiedRecord(const char *type); + CUnifiedRecord(const char *type, CJValueType value); + CJValueType ValueType2CJValueType(ValueType value); + ValueType CJValueType2ValueType(CJValueType value); + char *GetType(); + CJValueType GetValue(); + + const std::shared_ptr<UDMF::UnifiedRecord> &GetUnifiedRecord() const; + + char *GetFileUri(); + void SetFileUri(const char *uri); + CRecord GetFileDetails(); + void SetFileDetails(const std::map<std::string, std::string> &details); + + char *GetImageUri(); + void SetImageUri(const char *uri); + + char *GetVideoUri(); + void SetVideoUri(const char *uri); + + CRecord GetTextDetails(); + void SetTextDetails(const std::map<std::string, std::string> &details); + + char *GetHyperLinkUrl(); + void SetHyperLinkUrl(const char *url); + + char *GetHyperLinkDescription(); + void SetHyperLinkDescription(const char *description); + + char *GetPlainTextContent(); + void SetPlainTextContent(const char *text); + + char *GetPlainTextAbstract(); + void SetPlainTextAbstract(const char *abstr); +private: + std::shared_ptr<UDMF::UnifiedRecord> unifiedRecord_; + int64_t pixelMapId_ = 0; +}; + +char *CreateCStringFromString(const std::string &source); +} // namespace UDMF +} // namespace OHOS #endif \ No newline at end of file diff --git a/udmf/interfaces/cj/include/utils.h b/udmf/interfaces/cj/include/utils.h index 727d426e5ba3331ff9edc3d1030005199b42040e..798293adc344586cf1b37847048870cd7ceac2a4 100644 --- a/udmf/interfaces/cj/include/utils.h +++ b/udmf/interfaces/cj/include/utils.h @@ -28,5 +28,6 @@ class FFI_EXPORT Utils { public: static char *MallocCString(const std::string &origin); static CArrString StringVectorToArray(std::vector<std::string> vector); + static void FreeCArrString(CArrString &arrStr); }; #endif // OHOS_UDMF_UTILS_H \ No newline at end of file diff --git a/udmf/interfaces/cj/src/unified_data_channel_ffi.cpp b/udmf/interfaces/cj/src/unified_data_channel_ffi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b7372df7a4699fe4bcf5c0d2066b6f08f086fc69 --- /dev/null +++ b/udmf/interfaces/cj/src/unified_data_channel_ffi.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2025 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 "cj_common_ffi.h" +#include "udmf_client.h" +#include "udmf_log.h" +#include "unified_data.h" +#include "unified_data_impl.h" +#include "unified_meta.h" +#include "unified_record_impl.h" +#include "utils.h" + +using namespace OHOS::FFI; +using namespace OHOS::UDMF; + +using ErrCode = int; + +namespace OHOS { +namespace UDMF { +extern "C" { + +FFI_EXPORT char *FfiUDMFInsertData(const char *intention, int64_t unifiedDataId, int32_t *errCode) +{ + *errCode = E_INVALID_PARAMETERS; + std::string key; + auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); + if (data == nullptr || data->unifiedData_ == nullptr) { + LOGE("Get unified data failed!"); + return nullptr; + } + Intention it = UnifiedDataUtils::GetIntentionByString(intention); + if (it == UD_INTENTION_DRAG) { + LOGE("Parameter error: The intention parameter is invalid"); + return nullptr; + } + CustomOption option = { .intention = it }; + auto status = UdmfClient::GetInstance().SetData(option, *(data->unifiedData_), key); + *errCode = status; + if (status != E_OK) { + LOGE("Insert data failed!"); + } + return Utils::MallocCString(key); +} + +FFI_EXPORT int32_t FfiUDMFUpdateData(const char *key, int64_t unifiedDataId) +{ + auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); + if (data == nullptr || data->unifiedData_ == nullptr) { + LOGE("Get unified data failed!"); + return E_INVALID_PARAMETERS; + } + UnifiedKey verifyKey(key); + if (!verifyKey.IsValid()) { + LOGE("Parameter error: parameter key is invalid"); + return E_INVALID_PARAMETERS; + } + QueryOption option = { .key = key }; + auto status = UdmfClient::GetInstance().UpdateData(option, *(data->unifiedData_)); + if (status != E_OK) { + LOGE("Update unified data failed!"); + } + return status; +} + +FFI_EXPORT CArrI64 FfiUDMFQueryData(const char *intention, const char *key, int32_t *errCode) +{ + *errCode = E_INVALID_PARAMETERS; + CArrI64 queryData = { .head = nullptr, .size = 0 }; + Intention it = UnifiedDataUtils::GetIntentionByString(intention); + if (it == UD_INTENTION_DRAG) { + LOGE("Parameter error: the intention parameter is invalid"); + return queryData; + } + QueryOption option = { .key = key, .intention = it }; + std::vector<UnifiedData> unifiedDataSet; + auto status = UdmfClient::GetInstance().GetBatchData(option, unifiedDataSet); + *errCode = status; + if (status != E_OK) { + LOGE("Query unified data failed!"); + return queryData; + } + auto arr = static_cast<int64_t*>(malloc(sizeof(int64_t) * unifiedDataSet.size())); + if (arr == nullptr) { + LOGE("malloc error in queryData"); + return queryData; + } + for (uint64_t i = 0; i < unifiedDataSet.size(); i++) { + std::shared_ptr<UnifiedData> unifiedDataItem = std::make_shared<UnifiedData>(); + auto cUnifiedData = FFIData::Create<CUnifiedData>(); + if (unifiedDataItem == nullptr || cUnifiedData == nullptr) { + LOGE("Create unifiedData failed. Instance is null."); + free(arr); + arr = nullptr; + return queryData; + } + unifiedDataItem->SetRecords(unifiedDataSet[i].GetRecords()); + unifiedDataItem->SetProperties(unifiedDataSet[i].GetProperties()); + cUnifiedData->unifiedData_ = unifiedDataItem; + arr[i] = cUnifiedData->GetID(); + } + queryData.head = arr; + queryData.size = static_cast<int64_t>(unifiedDataSet.size()); + return queryData; +} + +FFI_EXPORT CArrI64 FfiUDMFDeleteData(const char *intention, const char *key, int32_t *errCode) +{ + *errCode = E_INVALID_PARAMETERS; + CArrI64 deleteData = { .head = nullptr, .size = 0 }; + Intention it = UnifiedDataUtils::GetIntentionByString(intention); + if (it == UD_INTENTION_DRAG) { + LOGE("Parameter error: the intention parameter is invalid"); + return deleteData; + } + QueryOption option = { .key = key, .intention = it }; + std::vector<UnifiedData> unifiedDataSet; + auto status = UdmfClient::GetInstance().DeleteData(option, unifiedDataSet); + *errCode = status; + if (status != E_OK) { + LOGE("Query unified data failed!"); + return deleteData; + } + auto arr = static_cast<int64_t*>(malloc(sizeof(int64_t) * unifiedDataSet.size())); + if (arr == nullptr) { + LOGE("malloc error in deleteData"); + return deleteData; + } + for (uint64_t i = 0; i < unifiedDataSet.size(); i++) { + std::shared_ptr<UnifiedData> unifiedDataItem = std::make_shared<UnifiedData>(); + auto cUnifiedData = FFIData::Create<CUnifiedData>(); + if (unifiedDataItem == nullptr || cUnifiedData == nullptr) { + LOGE("Create unifiedData failed. Instance is null."); + free(arr); + arr = nullptr; + return deleteData; + } + unifiedDataItem->SetRecords(unifiedDataSet[i].GetRecords()); + unifiedDataItem->SetProperties(unifiedDataSet[i].GetProperties()); + cUnifiedData->unifiedData_ = unifiedDataItem; + arr[i] = cUnifiedData->GetID(); + } + deleteData.head = arr; + deleteData.size = static_cast<int64_t>(unifiedDataSet.size()); + return deleteData; +} + +FFI_EXPORT void FfiUDMFFreeStringData(char *str) +{ + free(str); +} + +FFI_EXPORT void FfiUDMFFreeArrI64Data(CArrI64* ptr) +{ + if (ptr == nullptr || ptr->head == nullptr) { + return; + } + free(ptr->head); + ptr->head = nullptr; +} +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/interfaces/cj/src/unified_data_ffi.cpp b/udmf/interfaces/cj/src/unified_data_ffi.cpp index 6cf4c5191cefca86a3ec6319d9ecb1f57f40a2e0..bcb4381ff9c06007b1d159daa6a00abdadc66cac 100644 --- a/udmf/interfaces/cj/src/unified_data_ffi.cpp +++ b/udmf/interfaces/cj/src/unified_data_ffi.cpp @@ -14,11 +14,16 @@ * limitations under the License. */ +#include "securec.h" + #include "unified_data_ffi.h" #include "unified_data_impl.h" #include "unified_record_impl.h" +#include "unified_data_parameter_parse.h" #include "cj_common_ffi.h" +#include "utils.h" + using namespace OHOS::FFI; using namespace OHOS::UDMF; @@ -26,73 +31,130 @@ namespace OHOS { namespace UDMF { extern "C" { - int64_t FfiUDMFUnifiedDataConstructor() - { - auto nativeCJUnifiedData = FFIData::Create<CUnifiedData>(); - if (nativeCJUnifiedData == nullptr) { - return -1; - } - return nativeCJUnifiedData->GetID(); +int64_t FfiUDMFUnifiedDataConstructor() +{ + auto nativeCJUnifiedData = FFIData::Create<CUnifiedData>(); + if (nativeCJUnifiedData == nullptr) { + return -1; + } + return nativeCJUnifiedData->GetID(); +} + +int64_t FfiUDMFUnifiedDataConstructorWithRecord(int64_t unifiedRecordId) +{ + auto record = FFIData::GetData<CUnifiedRecord>(unifiedRecordId); + if (record == nullptr) { + return -1; } - int64_t FfiUDMFUnifiedDataConstructorWithRecord(int64_t unifiedRecordId) - { - auto record = FFIData::GetData<CUnifiedRecord>(unifiedRecordId); - if (record == nullptr) { - return -1; - } - - auto nativeCJUnifiedData = FFIData::Create<CUnifiedData>(record); - if (nativeCJUnifiedData == nullptr) { - return -1; - } - return nativeCJUnifiedData->GetID(); + auto nativeCJUnifiedData = FFIData::Create<CUnifiedData>(record); + if (nativeCJUnifiedData == nullptr) { + return -1; } + return nativeCJUnifiedData->GetID(); +} + +void FfiUDMFUnifiedDataAddRecord(int64_t unifiedDataId, int64_t unifiedRecordId) +{ + auto record = FFIData::GetData<CUnifiedRecord>(unifiedRecordId); + if (record == nullptr) { + return; + } + + auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); + if (data == nullptr) { + return; + } + + data->AddRecord(record); +} - void FfiUDMFUnifiedDataAddRecord(int64_t unifiedDataId, int64_t unifiedRecordId) - { - auto record = FFIData::GetData<CUnifiedRecord>(unifiedRecordId); - if (record == nullptr) { - return; - } +CArrUnifiedRecord FfiUDMFUnifiedDataGetRecords(int64_t unifiedDataId) +{ + auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); + if (data == nullptr) { + return CArrUnifiedRecord {}; + } - auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); - if (data == nullptr) { - return; - } + return data->GetRecords(); +} - data->AddRecord(record); +bool FfiUDMFUnifiedDataHasType(int64_t unifiedDataId, const char *type) +{ + auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); + if (data == nullptr) { + return false; } - CArrUnifiedRecord FfiUDMFUnifiedDataGetRecords(int64_t unifiedDataId) - { - auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); - if (data == nullptr) { - return CArrUnifiedRecord{}; - } + return data->HasType(type); +} - return data->GetRecords(); +CArrString FfiUDMFUnifiedDataGetTypes(int64_t unifiedDataId) +{ + auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); + if (data == nullptr) { + return CArrString {}; } - bool FfiUDMFUnifiedDataHasType(int64_t unifiedDataId, const char *type) - { - auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); - if (data == nullptr) { - return false; - } + return data->GetTypes(); +} - return data->HasType(type); +CUnifiedDataProperties FfiUDMFGetProperties(int64_t unifiedDataId) +{ + auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); + CUnifiedDataProperties ret = { .extras = {}, .tag = nullptr, .timestamp = 0, .shareOptions = 1 }; + if (data == nullptr) { + return ret; + } + std::shared_ptr<UDMF::UnifiedDataProperties> uni = data->unifiedData_->GetProperties(); + int32_t code = NO_ERROR; + ParseParameters(uni->extras, ret.extras, code); + if (code != NO_ERROR) { + return ret; } + ret.tag = Utils::MallocCString(uni->tag); + ret.timestamp = uni->timestamp; + // In arkts initial enum value is not public ,so use public initial value CROSS_APP. + if (uni->shareOptions == IN_APP || uni->shareOptions == CROSS_APP) { + ret.shareOptions = uni->shareOptions; + } + return ret; +} - CArrString FfiUDMFUnifiedDataGetTypes(int64_t unifiedDataId) - { - auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); - if (data == nullptr) { - return CArrString{}; - } +void FfiUDMFSetProperties(int64_t unifiedDataId, CUnifiedDataProperties properties) +{ + auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); + if (data == nullptr) { + return; + } + auto prop = data->unifiedData_->GetProperties(); + AAFwk::WantParams wantP; + SetDataParameters(properties.extras, wantP); + prop->extras = wantP; + prop->tag = Utils::MallocCString(properties.tag); + prop->shareOptions = UDMF::ShareOptions(properties.shareOptions); + data->unifiedData_->SetProperties(prop); +} - return data->GetTypes(); +FFI_EXPORT void FfiUDMFFreeDataProperties(CUnifiedDataProperties *properties) +{ + CParameters *p = properties->extras.head; + for (int64_t i = 0; i < properties->extras.size; i++) { + free(p[i].key); + free(p[i].value); + p[i].key = nullptr; + p[i].value = nullptr; } + free(p); + free(properties->tag); + p = nullptr; + properties->tag = nullptr; } + +FFI_EXPORT void FfiUDMFFreeCArrString(CArrString *arrStr) +{ + Utils::FreeCArrString(*arrStr); } } +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/interfaces/cj/src/unified_data_impl.cpp b/udmf/interfaces/cj/src/unified_data_impl.cpp index 47ebd4db55e7537cef30872fb992979f45c9d3c9..a4e7e41666ed373e091ce8377aa4e6cb0c820208 100644 --- a/udmf/interfaces/cj/src/unified_data_impl.cpp +++ b/udmf/interfaces/cj/src/unified_data_impl.cpp @@ -14,10 +14,8 @@ * limitations under the License. */ -#include "unified_data_ffi.h" #include "unified_data_impl.h" -#include "unified_record_impl.h" -#include "cj_common_ffi.h" + #include <cstdlib> #include <string> #include <variant> @@ -25,7 +23,11 @@ #include <map> #include <iomanip> +#include "cj_common_ffi.h" #include "ffi_remote_data.h" +#include "unified_data_ffi.h" +#include "unified_record_impl.h" +#include "utils.h" #include "application_defined_record_napi.h" #include "audio_napi.h" @@ -46,93 +48,90 @@ #include "unified_record_napi.h" #include "video_napi.h" -#include "utils.h" - using namespace OHOS::FFI; using namespace OHOS::UDMF; namespace OHOS { namespace UDMF { - CUnifiedData::CUnifiedData() - { - unifiedData_ = std::make_shared<UnifiedData>(); - } +CUnifiedData::CUnifiedData() +{ + unifiedData_ = std::make_shared<UnifiedData>(); +} - CUnifiedData::CUnifiedData(UDMF::CUnifiedRecord *record) - { - unifiedData_ = std::make_shared<UnifiedData>(); +CUnifiedData::CUnifiedData(sptr<UDMF::CUnifiedRecord> record) +{ + unifiedData_ = std::make_shared<UnifiedData>(); - if (record == nullptr) { - return; - } - unifiedData_->AddRecord(record->GetUnifiedRecord()); - this->records_.push_back(record); + if (record == nullptr) { + return; } + unifiedData_->AddRecord(record->GetUnifiedRecord()); + this->records_.push_back(record); +} - void CUnifiedData::AddRecord(UDMF::CUnifiedRecord *record) - { - if (record == nullptr) { - return; - } - this->records_.push_back(record); - unifiedData_->AddRecord(record->GetUnifiedRecord()); +void CUnifiedData::AddRecord(sptr<UDMF::CUnifiedRecord> record) +{ + if (record == nullptr) { + return; } + this->records_.push_back(record); + unifiedData_->AddRecord(record->GetUnifiedRecord()); +} - static CArrUnifiedRecord VectorToArray(std::vector<int64_t> vector) - { - if (vector.size() == 0) { - return CArrUnifiedRecord{}; - } - int64_t *head = static_cast<int64_t *>(malloc(vector.size() * sizeof(int64_t))); - if (head == nullptr) { - return CArrUnifiedRecord{}; - } - for (unsigned long i = 0; i < vector.size(); i++) { - head[i] = vector[i]; - } - CArrUnifiedRecord int64Array = {head, vector.size()}; - return int64Array; +static CArrUnifiedRecord VectorToArray(std::vector<int64_t> vector) +{ + if (vector.size() == 0) { + return CArrUnifiedRecord {}; } - - CArrUnifiedRecord CUnifiedData::GetRecords() - { - std::vector<int64_t> recordIds; - for (auto record : this->records_) { - if (record == nullptr) { - break; - } - recordIds.push_back(record->GetID()); - } - return VectorToArray(recordIds); + int64_t *head = static_cast<int64_t*>(malloc(vector.size() * sizeof(int64_t))); + if (head == nullptr) { + return CArrUnifiedRecord {}; } - - bool CUnifiedData::HasType(const char *type) - { - return unifiedData_->HasType(type); + for (size_t i = 0; i < vector.size(); i++) { + head[i] = vector[i]; } + CArrUnifiedRecord int64Array = {head, vector.size()}; + return int64Array; +} - static CArrString StringVectorToArray(std::vector<std::string> vector) - { - if (vector.size() == 0) { - return CArrString{}; - } - char **head = static_cast<char **>(malloc(vector.size() * sizeof(char *))); - if (head == nullptr) { - return CArrString{}; - } - for (unsigned long i = 0; i < vector.size(); i++) { - head[i] = Utils::MallocCString(vector[i]); +CArrUnifiedRecord CUnifiedData::GetRecords() +{ + std::vector<int64_t> recordIds; + for (auto record : this->records_) { + if (record == nullptr) { + break; } - CArrString stringArray = {head, vector.size()}; - return stringArray; + recordIds.push_back(record->GetID()); } + return VectorToArray(recordIds); +} - CArrString CUnifiedData::GetTypes() - { - std::vector<std::string> types = unifiedData_->GetTypesLabels(); - return StringVectorToArray(types); - } +bool CUnifiedData::HasType(const char *type) +{ + return unifiedData_->HasType(type); +} +static CArrString StringVectorToArray(std::vector<std::string> vector) +{ + if (vector.size() == 0) { + return CArrString {}; + } + char **head = static_cast<char**>(malloc(vector.size() * sizeof(char*))); + if (head == nullptr) { + return CArrString {}; + } + for (unsigned long i = 0; i < vector.size(); i++) { + head[i] = Utils::MallocCString(vector[i]); + } + CArrString stringArray = {head, vector.size()}; + return stringArray; } + +CArrString CUnifiedData::GetTypes() +{ + std::vector<std::string> types = unifiedData_->GetTypesLabels(); + return StringVectorToArray(types); } +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/interfaces/cj/src/unified_data_parameter_parse.cpp b/udmf/interfaces/cj/src/unified_data_parameter_parse.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e98df09816173012edfb156b8905701e61b50af --- /dev/null +++ b/udmf/interfaces/cj/src/unified_data_parameter_parse.cpp @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2025 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 "unified_data_parameter_parse.h" + +#include <cinttypes> + +#include "array_wrapper.h" +#include "bool_wrapper.h" +#include "byte_wrapper.h" +#include "double_wrapper.h" +#include "int_wrapper.h" +#include "long_wrapper.h" +#include "string_wrapper.h" +#include "udmf_log.h" +#include "utils.h" +#include "want_params_wrapper.h" + +namespace OHOS { +namespace UDMF { + +const int8_t I32_TYPE = 0; +const int8_t I64_TYPE = 1; +const int8_t DOUBLE_TYPE = 2; +const int8_t BOOL_TYPE = 3; +const int8_t STR_TYPE = 4; +const int8_t UINT8_ARRAY_TYPE = 5; + +constexpr int32_t NO_ERROR = 0; +constexpr int32_t ERR_UDMF_FAILED = -1; +constexpr int32_t ERR_NO_MEMORY = -2; + +const int32_t NONE_VALUE = 1; +using WantParams = OHOS::AAFwk::WantParams; + +void ClearParametersPtr(CParameters **ptr, int count, bool isKey) +{ + CParameters *p = *ptr; + for (int i = 0; i < count; i++) { + free(p[i].key); + free(p[i].value); + p[i].key = nullptr; + p[i].value = nullptr; + } + if (!isKey) { + free(p[count].key); + p[count].key = nullptr; + } + free(*ptr); + *ptr = nullptr; +} + +// WantParameters -> CArrParameters +int32_t InnerWrapWantParamsString(WantParams &wantParams, CParameters *p) +{ + auto value = wantParams.GetParam(p->key); + AAFwk::IString *ao = AAFwk::IString::Query(value); + if (ao == nullptr) { + LOGE("No value"); + return NONE_VALUE; + } + std::string natValue = OHOS::AAFwk::String::Unbox(ao); + p->value = Utils::MallocCString(natValue); + p->size = static_cast<int64_t>(natValue.length()) + 1; + p->valueType = STR_TYPE; + return NO_ERROR; +} + +template <class TBase, class T, class NativeT> +int32_t InnerWrapWantParamsT(WantParams &wantParams, CParameters *p) +{ + auto value = wantParams.GetParam(p->key); + TBase *ao = TBase::Query(value); + if (ao == nullptr) { + LOGE("No value"); + return NONE_VALUE; + } + NativeT natValue = T::Unbox(ao); + NativeT *ptr = static_cast<NativeT*>(malloc(sizeof(NativeT))); + if (ptr == nullptr) { + return ERR_NO_MEMORY; + } + *ptr = natValue; + p->value = static_cast<void*>(ptr); + p->size = sizeof(NativeT); + return NO_ERROR; +} + +template <class TBase, class T, class NativeT> +int32_t InnerWrapWantParamsArrayT(sptr<AAFwk::IArray> &ao, CParameters*p) +{ + long size = 0; + if (ao->GetLength(size) != ERR_OK) { + LOGE("fail to get length"); + return ERR_UDMF_FAILED; + } + if (size == 0) { + return ERR_UDMF_FAILED; + } + NativeT *arrP = static_cast<NativeT*>(malloc(sizeof(NativeT) * size)); + if (arrP == nullptr) { + LOGE("fail to malloc"); + return ERR_NO_MEMORY; + } + for (long i = 0; i < size; i++) { + sptr<AAFwk::IInterface> iface = nullptr; + if (ao->Get(i, iface) == ERR_OK) { + TBase *iValue = TBase::Query(iface); + if (iValue != nullptr) { + arrP[i] = T::Unbox(iValue); + } + } + } + p->size = size; + p->value = static_cast<void*>(arrP); + return NO_ERROR; +} + +bool InnerSetWantParamsArrayByte(const std::string &key, const std::vector<uint8_t> &value, + AAFwk::WantParams &wantParams) +{ + size_t size = value.size(); + sptr<AAFwk::IArray> ao = new (std::nothrow) AAFwk::Array(size, AAFwk::g_IID_IByte); + if (ao != nullptr) { + for (size_t i = 0; i < size; i++) { + ao->Set(i, AAFwk::Integer::Box(value[i])); + } + wantParams.SetParam(key, ao); + return true; + } else { + return false; + } +} + +int32_t InnerWrapWantParamsArray(WantParams &wantParams, sptr<AAFwk::IArray> &ao, CParameters *p) +{ + LOGI("%{public}s called, key=%{public}s", __func__, p->key); + if (AAFwk::Array::IsByteArray(ao)) { + p->valueType = UINT8_ARRAY_TYPE; + return InnerWrapWantParamsArrayT<AAFwk::IByte, AAFwk::Byte, uint8_t>(ao, p); + } + return ERR_UDMF_FAILED; +} + +void SetDataParameters(CArrParameters parameters, WantParams &wantP) +{ + for (int i = 0; i < parameters.size; i++) { + auto head = parameters.head + i; + auto key = std::string(head->key); + if (head->valueType == I32_TYPE) { + wantP.SetParam(key, OHOS::AAFwk::Integer::Box(*static_cast<int32_t*>(head->value))); + } else if (head->valueType == I64_TYPE) { + wantP.SetParam(key, OHOS::AAFwk::Integer::Box(*static_cast<int64_t*>(head->value))); + } else if (head->valueType == DOUBLE_TYPE) { + wantP.SetParam(key, OHOS::AAFwk::Double::Box(*static_cast<double*>(head->value))); + } else if (head->valueType == STR_TYPE) { + wantP.SetParam(key, OHOS::AAFwk::String::Box(std::string(static_cast<char*>(head->value)))); + } else if (head->valueType == BOOL_TYPE) { + wantP.SetParam(key, OHOS::AAFwk::Boolean::Box(*static_cast<bool*>(head->value))); + } else if (head->valueType == UINT8_ARRAY_TYPE) { + uint8_t *intArr = static_cast<uint8_t*>(head->value); + std::vector<uint8_t> intVec(intArr, intArr + head->size); + InnerSetWantParamsArrayByte(key, intVec, wantP); + } else { + LOGE("wrong type!"); + } + } +} + +void ParseParameters(WantParams &wantP, CArrParameters &parameters, int32_t &code) +{ + if (code != NO_ERROR) { + return; + } + std::map<std::string, sptr<OHOS::AAFwk::IInterface>> paramsMap = wantP.GetParams(); + int count = 0; + auto size = static_cast<int64_t>(paramsMap.size()); + if (size == 0) { + return; + } + parameters.head = static_cast<CParameters*>(malloc(sizeof(CParameters) * size)); + if (parameters.head == nullptr) { + code = ERR_NO_MEMORY; + return; + } + parameters.size = size; + for (auto iter = paramsMap.begin(); iter != paramsMap.end(); iter++) { + auto ptr = parameters.head + count; + ptr->key = Utils::MallocCString(iter->first); + if (ptr->key == nullptr) { + code = ERR_NO_MEMORY; + return ClearParametersPtr(&parameters.head, count, true); + } + ptr->value = nullptr; + ptr->size = 0; + if (AAFwk::IString::Query(iter->second) != nullptr) { + code = InnerWrapWantParamsString(wantP, ptr); + } else if (AAFwk::IBoolean::Query(iter->second) != nullptr) { + ptr->valueType = BOOL_TYPE; + code = InnerWrapWantParamsT<AAFwk::IBoolean, AAFwk::Boolean, bool>(wantP, ptr); + } else if (AAFwk::IInteger::Query(iter->second) != nullptr) { + ptr->valueType = I32_TYPE; + code = InnerWrapWantParamsT<AAFwk::IInteger, AAFwk::Integer, int>(wantP, ptr); + } else if (AAFwk::ILong::Query(iter->second) != nullptr) { + ptr->valueType = I64_TYPE; + code = InnerWrapWantParamsT<AAFwk::ILong, AAFwk::Long, long>(wantP, ptr); + } else if (AAFwk::IDouble::Query(iter->second) != nullptr) { + ptr->valueType = DOUBLE_TYPE; + code = InnerWrapWantParamsT<AAFwk::IDouble, AAFwk::Double, double>(wantP, ptr); + } else if (AAFwk::IArray::Query(iter->second) != nullptr) { + AAFwk::IArray *ao = AAFwk::IArray::Query(iter->second); + sptr<AAFwk::IArray> array(ao); + code = InnerWrapWantParamsArray(wantP, array, ptr); + } + if (code == ERR_NO_MEMORY || code == ERR_UDMF_FAILED) { + return ClearParametersPtr(&parameters.head, count, false); + } + count++; + } +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/interfaces/cj/src/unified_record_ffi.cpp b/udmf/interfaces/cj/src/unified_record_ffi.cpp index c2ab6baab722c49ee274edf8488ec133a6f22fdc..19dc3cac6508739cd5016113cbc7d8ae6d3f9c99 100644 --- a/udmf/interfaces/cj/src/unified_record_ffi.cpp +++ b/udmf/interfaces/cj/src/unified_record_ffi.cpp @@ -15,50 +15,298 @@ */ #include "unified_record_ffi.h" + +#include "udmf_log.h" #include "unified_record_impl.h" +#include "utils.h" using namespace OHOS::FFI; using namespace OHOS::UDMF; namespace OHOS { namespace UDMF { +constexpr int64_t NO_ERROR = 0; +constexpr int64_t ERR_INIT_FAILED = -1; + extern "C" { +int64_t FfiUDMFUnifiedRecordConstructor() +{ + auto nativeCJUnifiedRecord = FFIData::Create<CUnifiedRecord>(); + if (nativeCJUnifiedRecord == nullptr) { + return -1; + } + return nativeCJUnifiedRecord->GetID(); +} + +int64_t FfiUDMFUnifiedRecordConstructorwithOnlyType(const char *type) +{ + auto nativeCJUnifiedRecord = FFIData::Create<CUnifiedRecord>(type); + if (nativeCJUnifiedRecord == nullptr) { + return -1; + } + return nativeCJUnifiedRecord->GetID(); +} + +int64_t FfiUDMFUnifiedRecordConstructorwithType(const char *type, CJValueType value) +{ + auto nativeCJUnifiedRecord = FFIData::Create<CUnifiedRecord>(type, value); + if (nativeCJUnifiedRecord == nullptr) { + return -1; + } + return nativeCJUnifiedRecord->GetID(); +} + +char *FfiUDMFUnifiedRecordGetType(int64_t unifiedId) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(unifiedId); + if (instance == nullptr) { + return nullptr; + } + return instance->GetType(); +} + +CJValueType FfiUDMFUnifiedRecordGetValue(int64_t unifiedId) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(unifiedId); + if (instance == nullptr) { + return CJValueType {}; + } + return instance->GetValue(); +} + +char *FfiUDMFFileGetUri(int64_t id) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return nullptr; + } + return instance->GetFileUri(); +} + +int64_t FfiUDMFFileSetUri(int64_t id, const char *uri) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; + } + instance->SetFileUri(uri); + return NO_ERROR; +} + +CRecord FfiUDMFFileGetDetails(int64_t id) +{ + CRecord ret = { .keys = { .head = nullptr, .size = 0 }, .values = { .head = nullptr, .size = 0 } }; + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ret; + } + return instance->GetFileDetails(); +} + +int64_t FfiUDMFFileSetDetails(int64_t id, CRecord record) +{ + if (record.keys.size != record.values.size) { + LOGE("Param error. The number of key and value mismatch."); + return ERR_INIT_FAILED; + } + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; + } + std::map<std::string, std::string> details; + for (int64_t i = 0; i < record.keys.size; i++) { + std::string key{record.keys.head[i]}; + std::string value{record.values.head[i]}; + details[key] = value; + } + instance->SetFileDetails(details); + return NO_ERROR; +} + +char *FfiUDMFImageGetImageUri(int64_t id) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return nullptr; + } + return instance->GetImageUri(); +} + +int64_t FfiUDMFImageSetImageUri(int64_t id, const char *uri) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; + } + instance->SetImageUri(uri); + return NO_ERROR; +} + +char *FfiUDMFVideoGetVideoUri(int64_t id) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return nullptr; + } + return instance->GetVideoUri(); +} + +int64_t FfiUDMFVideoSetVideoUri(int64_t id, const char *uri) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; + } + instance->SetVideoUri(uri); + return NO_ERROR; +} + +CRecord FfiUDMFTextGetDetails(int64_t id) +{ + CRecord ret = { .keys = { .head = nullptr, .size = 0 }, .values = { .head = nullptr, .size = 0 } }; + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ret; + } + return instance->GetTextDetails(); +} - int64_t FfiUDMFUnifiedRecordConstructor() - { - auto nativeCJUnifiedRecord = FFIData::Create<CUnifiedRecord>(); - if (nativeCJUnifiedRecord == nullptr) { - return -1; - } - return nativeCJUnifiedRecord->GetID(); +int64_t FfiUDMFTextSetDetails(int64_t id, CRecord record) +{ + if (record.keys.size != record.values.size) { + LOGE("Param error. The number of key and value mismatch."); + return ERR_INIT_FAILED; + } + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; + } + std::map<std::string, std::string> details; + for (int64_t i = 0; i < record.keys.size; i++) { + std::string key{record.keys.head[i]}; + std::string value{record.values.head[i]}; + details[key] = value; } + instance->SetTextDetails(details); + return NO_ERROR; +} - int64_t FfiUDMFUnifiedRecordConstructorwithType(const char *type, CJValueType value) - { - auto nativeCJUnifiedRecord = FFIData::Create<CUnifiedRecord>(type, value); - if (nativeCJUnifiedRecord == nullptr) { - return -1; - } - return nativeCJUnifiedRecord->GetID(); +char *FfiUDMFHyperLinkGetUrl(int64_t id) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return nullptr; } + return instance->GetHyperLinkUrl(); +} - char *FfiUDMFUnifiedRecordGetType(int64_t unifiedId) - { - auto instance = FFIData::GetData<CUnifiedRecord>(unifiedId); - if (instance == nullptr) { - return nullptr; - } - return instance->GetType(); +int64_t FfiUDMFHyperLinkSetUrl(int64_t id, const char *url) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; } + instance->SetHyperLinkUrl(url); + return NO_ERROR; +} + +char *FfiUDMFHyperLinkGetDescription(int64_t id) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return nullptr; + } + return instance->GetHyperLinkDescription(); +} - CJValueType FfiUDMFUnifiedRecordGetValue(int64_t unifiedId) - { - auto instance = FFIData::GetData<CUnifiedRecord>(unifiedId); - if (instance == nullptr) { - return CJValueType{}; - } - return instance->GetValue(); +int64_t FfiUDMFHyperLinkSetDescription(int64_t id, const char *description) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; } + instance->SetHyperLinkDescription(description); + return NO_ERROR; } + +char *FfiUDMFPlainTextGetTextContent(int64_t id) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return nullptr; + } + return instance->GetPlainTextContent(); +} + +int64_t FfiUDMFPlainTextSetTextContent(int64_t id, const char *text) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; + } + instance->SetPlainTextContent(text); + return NO_ERROR; +} + +char *FfiUDMFPlainTextGetAbstract(int64_t id) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return nullptr; + } + return instance->GetPlainTextAbstract(); +} + +int64_t FfiUDMFPlainTextSetAbstract(int64_t id, const char *abstr) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; + } + instance->SetPlainTextAbstract(abstr); + return NO_ERROR; +} + +FFI_EXPORT void FfiUDMFFreeCjValueType(CJValueType *val) +{ + if (val->string != nullptr) { + free(val->string); + val->string = nullptr; + } + if (val->byteArray.head != nullptr) { + free(val->byteArray.head); + val->byteArray.head = nullptr; + val->byteArray.size = 0; + } +} + +FFI_EXPORT void FfiUDMFFreeCRecord(CRecord *record) +{ + Utils::FreeCArrString(record->keys); + Utils::FreeCArrString(record->values); + record->keys.head = nullptr; + record->keys.size = 0; + record->values.head = nullptr; + record->values.size = 0; } } +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/interfaces/cj/src/unified_record_impl.cpp b/udmf/interfaces/cj/src/unified_record_impl.cpp index 3bdbe41e3a7979b777cc4ad2b71846e37de06635..743277caaf36fc0764a9a86ac3660901e0dc4058 100644 --- a/udmf/interfaces/cj/src/unified_record_impl.cpp +++ b/udmf/interfaces/cj/src/unified_record_impl.cpp @@ -14,203 +14,435 @@ * limitations under the License. */ -#include "unified_record_ffi.h" #include "unified_record_impl.h" #include <cstdlib> +#include <iomanip> +#include <map> #include <string> #include <variant> #include <vector> -#include <map> -#include <iomanip> + #include "ffi_remote_data.h" +#include "securec.h" +#include "unified_record_ffi.h" -#include "plain_text.h" +#include "application_defined_record.h" +#include "audio.h" +#include "folder.h" #include "html.h" -#include "link.h" #include "image.h" +#include "link.h" #include "pixel_map_impl.h" #include "pixel_map.h" - -#include "video.h" -#include "audio.h" -#include "folder.h" +#include "plain_text.h" #include "system_defined_appitem.h" #include "system_defined_form.h" #include "system_defined_pixelmap.h" -#include "application_defined_record.h" #include "utils.h" +#include "video.h" using namespace OHOS::FFI; using namespace OHOS::UDMF; namespace OHOS { namespace UDMF { - static CArrUI8 VectorToByteArray(std::vector<uint8_t> bytes) - { - if (bytes.size() == 0) { - return CArrUI8{}; - } - uint8_t *head = static_cast<uint8_t *>(malloc(bytes.size() * sizeof(uint8_t))); - if (head == nullptr) { - return CArrUI8{}; - } - for (unsigned long i = 0; i < bytes.size(); i++) { - head[i] = bytes[i]; - } - CArrUI8 byteArray = {head, bytes.size()}; - return byteArray; - } - - CJValueType CUnifiedRecord::ValueType2CJValueType(ValueType value) - { - CJValueType cjvalue; - if (std::holds_alternative<std::monostate>(value)) { - cjvalue.tag = UNDEFINED; - } else if (std::holds_alternative<nullptr_t>(value)) { - cjvalue.tag = NULLTAG; - } else if (auto p = std::get_if<int32_t>(&value)) { - cjvalue.integer32 = *p; - cjvalue.tag = INTEGER32; - } else if (auto p = std::get_if<int64_t>(&value)) { - cjvalue.integer64 = *p; - cjvalue.tag = INTEGER64; - } else if (auto p = std::get_if<double>(&value)) { - cjvalue.dou = *p; - cjvalue.tag = DOUBLE; - } else if (auto p = std::get_if<bool>(&value)) { - cjvalue.boolean = *p; - cjvalue.tag = BOOLEAN; - } else if (auto p = std::get_if<std::string>(&value)) { - cjvalue.string = Utils::MallocCString(*p); - cjvalue.tag = STRING; - } else if (auto p = std::get_if<std::vector<uint8_t>>(&value)) { - cjvalue.byteArray = VectorToByteArray(*p); - cjvalue.tag = BYTEARRAY; - } else if (auto p = std::get_if<std::shared_ptr<OHOS::Media::PixelMap>>(&value)) { - cjvalue.pixelMapId = this->pixelMapId_; - cjvalue.tag = PIXELMAP; - } +static CArrUI8 VectorToByteArray(std::vector<uint8_t> bytes) +{ + if (bytes.size() == 0) { + return CArrUI8 {}; + } + uint8_t *head = static_cast<uint8_t*>(malloc(bytes.size() * sizeof(uint8_t))); + if (head == nullptr) { + return CArrUI8 {}; + } + for (size_t i = 0; i < bytes.size(); i++) { + head[i] = bytes[i]; + } + CArrUI8 byteArray = {head, bytes.size()}; + return byteArray; +} - return cjvalue; +CJValueType CUnifiedRecord::ValueType2CJValueType(ValueType value) +{ + CJValueType cjvalue; + if (std::holds_alternative<std::monostate>(value)) { + cjvalue.tag = UNDEFINED; + } else if (std::holds_alternative<nullptr_t>(value)) { + cjvalue.tag = NULLTAG; + } else if (auto p = std::get_if<int32_t>(&value)) { + cjvalue.integer32 = *p; + cjvalue.tag = INTEGER32; + } else if (auto p = std::get_if<int64_t>(&value)) { + cjvalue.integer64 = *p; + cjvalue.tag = INTEGER64; + } else if (auto p = std::get_if<double>(&value)) { + cjvalue.dou = *p; + cjvalue.tag = DOUBLE; + } else if (auto p = std::get_if<bool>(&value)) { + cjvalue.boolean = *p; + cjvalue.tag = BOOLEAN; + } else if (auto p = std::get_if<std::string>(&value)) { + cjvalue.string = Utils::MallocCString(*p); + cjvalue.tag = STRING; + } else if (auto p = std::get_if<std::vector<uint8_t>>(&value)) { + cjvalue.byteArray = VectorToByteArray(*p); + cjvalue.tag = BYTEARRAY; + } else if (auto p = std::get_if<std::shared_ptr<OHOS::Media::PixelMap>>(&value)) { + cjvalue.pixelMapId = this->pixelMapId_; + cjvalue.tag = PIXELMAP; } - ValueType CUnifiedRecord::CJValueType2ValueType(CJValueType cjvalue) - { - ValueType value; - switch (cjvalue.tag) { - case INTEGER32: - value = cjvalue.integer32; - break; - case INTEGER64: - value = cjvalue.integer64; - break; - case DOUBLE: - value = cjvalue.dou; - break; - case BOOLEAN: - value = cjvalue.boolean; - break; - case STRING: - value = cjvalue.string; - break; - case BYTEARRAY: { - std::vector<uint8_t> bytes = std::vector<uint8_t>(); - for (int64_t i = 0; i < cjvalue.byteArray.size; i++) { - bytes.push_back(cjvalue.byteArray.head[i]); - } - value = bytes; - break; - } + return cjvalue; +} - case PIXELMAP: { - auto instance = FFIData::GetData<OHOS::Media::PixelMapImpl>(cjvalue.pixelMapId); - if (instance == nullptr) { - value = -1; - break; - } - value = instance->GetRealPixelMap(); - break; +ValueType CUnifiedRecord::CJValueType2ValueType(CJValueType cjvalue) +{ + ValueType value; + switch (cjvalue.tag) { + case INTEGER32: + value = cjvalue.integer32; + break; + case INTEGER64: + value = cjvalue.integer64; + break; + case DOUBLE: + value = cjvalue.dou; + break; + case BOOLEAN: + value = cjvalue.boolean; + break; + case STRING: + value = cjvalue.string; + break; + case BYTEARRAY: { + std::vector<uint8_t> bytes = std::vector<uint8_t>(); + for (int64_t i = 0; i < cjvalue.byteArray.size; i++) { + bytes.push_back(cjvalue.byteArray.head[i]); } + value = bytes; + break; + } - case NULLTAG: { - value = nullptr; + case PIXELMAP: { + auto instance = FFIData::GetData<OHOS::Media::PixelMapImpl>(cjvalue.pixelMapId); + if (instance == nullptr) { + value = -1; break; } + value = instance->GetRealPixelMap(); + break; + } - case UNDEFINED: { - value = std::monostate(); - break; - } - - default: - value = -1; - break; + case NULLTAG: { + value = nullptr; + break; } - return value; + case UNDEFINED: { + value = std::monostate(); + break; + } + + default: + value = -1; + break; } - CUnifiedRecord::CUnifiedRecord() - { - unifiedRecord_ = std::make_shared<UnifiedRecord>(); + return value; +} + +CUnifiedRecord::CUnifiedRecord() +{ + unifiedRecord_ = std::make_shared<UnifiedRecord>(); +} + +CUnifiedRecord::CUnifiedRecord(const char *type) +{ + UDType utdType = APPLICATION_DEFINED_RECORD; + if (UtdUtils::IsValidUtdId(type)) { + utdType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(type)); + } + static const std::map<UDType, std::function<std::shared_ptr<UnifiedRecord>()>> constructors = { + {TEXT, []() { return std::make_shared<Text>(); }}, + {PLAIN_TEXT, []() { return std::make_shared<PlainText>(); }}, + {HTML, []() { return std::make_shared<Html>(); }}, + {HYPERLINK, []() { return std::make_shared<Link>(); }}, + {FILE, []() { return std::make_shared<File>(); }}, + {IMAGE, []() { return std::make_shared<Image>(); }}, + {VIDEO, []() { return std::make_shared<Video>(); }}, + {AUDIO, []() { return std::make_shared<Audio>(); }}, + {FOLDER, []() { return std::make_shared<Folder>(); }}, + {SYSTEM_DEFINED_RECORD, []() + { return std::make_shared<SystemDefinedRecord>(); }}, + {SYSTEM_DEFINED_APP_ITEM, []() + { return std::make_shared<SystemDefinedAppItem>(); }}, + {SYSTEM_DEFINED_FORM, []() + { return std::make_shared<SystemDefinedForm>(); }}, + {SYSTEM_DEFINED_PIXEL_MAP, []() + { return std::make_shared<SystemDefinedPixelMap>(); }}, + {APPLICATION_DEFINED_RECORD, []() + { return std::make_shared<ApplicationDefinedRecord>(); }}, + }; + auto constructor = constructors.find(utdType); + if (constructor == constructors.end()) { + unifiedRecord_ = std::make_shared<UnifiedRecord>(utdType); + return; } + unifiedRecord_ = constructor->second(); +} - CUnifiedRecord::CUnifiedRecord(const char *type, CJValueType cjvalue) - { - UDType utdType = APPLICATION_DEFINED_RECORD; - if (UtdUtils::IsValidUtdId(type)) { - utdType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(type)); - } - ValueType value = CJValueType2ValueType(cjvalue); - if (cjvalue.tag == PIXELMAP) { - this->pixelMapId_ = cjvalue.pixelMapId; - } - std::map<UDType, std::function<std::shared_ptr<UnifiedRecord>(UDType, ValueType)>> constructors = { - {TEXT, [](UDType type, ValueType value) { return std::make_shared<Text>(type, value); }}, - {PLAIN_TEXT, [](UDType type, ValueType value) { return std::make_shared<PlainText>(type, value); }}, - {HTML, [](UDType type, ValueType value) { return std::make_shared<Html>(type, value); }}, - {HYPERLINK, [](UDType type, ValueType value) { return std::make_shared<Link>(type, value); }}, - {FILE, [](UDType type, ValueType value) { return std::make_shared<File>(type, value); }}, - {IMAGE, [](UDType type, ValueType value) { return std::make_shared<Image>(type, value); }}, - {VIDEO, [](UDType type, ValueType value) { return std::make_shared<Video>(type, value); }}, - {AUDIO, [](UDType type, ValueType value) { return std::make_shared<Audio>(type, value); }}, - {FOLDER, [](UDType type, ValueType value) { return std::make_shared<Folder>(type, value); }}, - {SYSTEM_DEFINED_RECORD, [](UDType type, ValueType value) - { return std::make_shared<SystemDefinedRecord>(type, value); }}, - {SYSTEM_DEFINED_APP_ITEM, [](UDType type, ValueType value) - { return std::make_shared<SystemDefinedAppItem>(type, value); }}, - {SYSTEM_DEFINED_FORM, [](UDType type, ValueType value) - { return std::make_shared<SystemDefinedForm>(type, value); }}, - {SYSTEM_DEFINED_PIXEL_MAP, [](UDType type, ValueType value) - { return std::make_shared<SystemDefinedPixelMap>(type, value); }}, - {APPLICATION_DEFINED_RECORD, [](UDType type, ValueType value) - { return std::make_shared<ApplicationDefinedRecord>(type, value); }}, - }; - auto constructor = constructors.find(utdType); - if (constructor == constructors.end()) { - unifiedRecord_ = std::make_shared<UnifiedRecord>(utdType, value); - return; +CUnifiedRecord::CUnifiedRecord(const char *type, CJValueType cjvalue) +{ + UDType utdType = APPLICATION_DEFINED_RECORD; + if (UtdUtils::IsValidUtdId(type)) { + utdType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(type)); + } + ValueType value = CJValueType2ValueType(cjvalue); + if (cjvalue.tag == PIXELMAP) { + this->pixelMapId_ = cjvalue.pixelMapId; + } + static const std::map<UDType, std::function<std::shared_ptr<UnifiedRecord>(UDType, ValueType)>> constructors = { + {TEXT, [](UDType type, ValueType value) { return std::make_shared<Text>(type, value); }}, + {PLAIN_TEXT, [](UDType type, ValueType value) { return std::make_shared<PlainText>(type, value); }}, + {HTML, [](UDType type, ValueType value) { return std::make_shared<Html>(type, value); }}, + {HYPERLINK, [](UDType type, ValueType value) { return std::make_shared<Link>(type, value); }}, + {FILE, [](UDType type, ValueType value) { return std::make_shared<File>(type, value); }}, + {IMAGE, [](UDType type, ValueType value) { return std::make_shared<Image>(type, value); }}, + {VIDEO, [](UDType type, ValueType value) { return std::make_shared<Video>(type, value); }}, + {AUDIO, [](UDType type, ValueType value) { return std::make_shared<Audio>(type, value); }}, + {FOLDER, [](UDType type, ValueType value) { return std::make_shared<Folder>(type, value); }}, + {SYSTEM_DEFINED_RECORD, [](UDType type, ValueType value) + { return std::make_shared<SystemDefinedRecord>(type, value); }}, + {SYSTEM_DEFINED_APP_ITEM, [](UDType type, ValueType value) + { return std::make_shared<SystemDefinedAppItem>(type, value); }}, + {SYSTEM_DEFINED_FORM, [](UDType type, ValueType value) + { return std::make_shared<SystemDefinedForm>(type, value); }}, + {SYSTEM_DEFINED_PIXEL_MAP, [](UDType type, ValueType value) + { return std::make_shared<SystemDefinedPixelMap>(type, value); }}, + {APPLICATION_DEFINED_RECORD, [](UDType type, ValueType value) + { return std::make_shared<ApplicationDefinedRecord>(type, value); }}, + }; + auto constructor = constructors.find(utdType); + if (constructor == constructors.end()) { + unifiedRecord_ = std::make_shared<UnifiedRecord>(utdType, value); + return; + } + unifiedRecord_ = constructor->second(utdType, value); +} + +char *CUnifiedRecord::GetType() +{ + std::string ret = UtdUtils::GetUtdIdFromUtdEnum(this->unifiedRecord_->GetType()); + return Utils::MallocCString(ret); +} + +CJValueType CUnifiedRecord::GetValue() +{ + ValueType value = this->unifiedRecord_->GetValue(); + CJValueType cjvalue = ValueType2CJValueType(value); + return cjvalue; +} + +const std::shared_ptr<UDMF::UnifiedRecord> &CUnifiedRecord::GetUnifiedRecord() const +{ + return unifiedRecord_; +} + +char *CUnifiedRecord::GetFileUri() +{ + std::shared_ptr<UDMF::File> resFile = std::reinterpret_pointer_cast<UDMF::File>(this->unifiedRecord_); + std::string res = resFile->GetUri(); + return Utils::MallocCString(res); +} + +void CUnifiedRecord::SetFileUri(const char *uri) +{ + std::shared_ptr<UDMF::File> resFile = std::reinterpret_pointer_cast<UDMF::File>(this->unifiedRecord_); + resFile->SetUri(uri); +} + +CRecord CUnifiedRecord::GetFileDetails() +{ + CRecord ret = { .keys = { .head = nullptr, .size = 0 }, .values = { .head = nullptr, .size = 0 } }; + std::shared_ptr<UDMF::File> resFile = std::reinterpret_pointer_cast<UDMF::File>(this->unifiedRecord_); + OHOS::UDMF::UDDetails resDetails = resFile->GetDetails(); + std::map<std::string, std::string> params; + for (auto it : resDetails) { + if (std::holds_alternative<std::string>(it.second)) { + const std::string &strValue = std::get<std::string>(it.second); + params.emplace(it.first, strValue); } - unifiedRecord_ = constructor->second(utdType, value); } + char **keysHead = static_cast<char**>(malloc(sizeof(char*) * params.size())); + if (keysHead == nullptr) { + return ret; + } + char **valuesHead = static_cast<char**>(malloc(sizeof(char*) * params.size())); + if (valuesHead == nullptr) { + free(keysHead); + return ret; + } + int64_t i = 0; + for (auto &param : params) { + keysHead[i] = CreateCStringFromString(param.first); + valuesHead[i] = CreateCStringFromString(param.second); + i++; + } + ret.keys.size = static_cast<int64_t>(params.size()); + ret.keys.head = keysHead; + ret.values.size = static_cast<int64_t>(params.size()); + ret.values.head = valuesHead; + return ret; +} - char *CUnifiedRecord::GetType() - { - std::string ret = UtdUtils::GetUtdIdFromUtdEnum(this->unifiedRecord_->GetType()); - return Utils::MallocCString(ret); +void CUnifiedRecord::SetFileDetails(const std::map<std::string, std::string> &details) +{ + std::shared_ptr<UDMF::File> resFile = std::reinterpret_pointer_cast<UDMF::File>(this->unifiedRecord_); + OHOS::UDMF::UDDetails udDetails; + for (auto &param : details) { + udDetails[param.first] = param.second; } + resFile->SetDetails(udDetails); +} - CJValueType CUnifiedRecord::GetValue() - { - ValueType value = this->unifiedRecord_->GetValue(); - CJValueType cjvalue = ValueType2CJValueType(value); - return cjvalue; +char *CUnifiedRecord::GetImageUri() +{ + std::shared_ptr<UDMF::Image> resImage = std::reinterpret_pointer_cast<UDMF::Image>(this->unifiedRecord_); + std::string res = resImage->GetUri(); + return Utils::MallocCString(res); +} + +void CUnifiedRecord::SetImageUri(const char *uri) +{ + std::shared_ptr<UDMF::Image> resImage = std::reinterpret_pointer_cast<UDMF::Image>(this->unifiedRecord_); + resImage->SetUri(uri); +} + +char *CUnifiedRecord::GetVideoUri() +{ + std::shared_ptr<UDMF::Video> resVideo = std::reinterpret_pointer_cast<UDMF::Video>(this->unifiedRecord_); + std::string res = resVideo->GetUri(); + return Utils::MallocCString(res); +} + +void CUnifiedRecord::SetVideoUri(const char *uri) +{ + std::shared_ptr<UDMF::Video> resVideo = std::reinterpret_pointer_cast<UDMF::Video>(this->unifiedRecord_); + resVideo->SetUri(uri); +} + +CRecord CUnifiedRecord::GetTextDetails() +{ + CRecord ret = { .keys = { .head = nullptr, .size = 0 }, .values = { .head = nullptr, .size = 0 } }; + std::shared_ptr<UDMF::Text> resText = std::reinterpret_pointer_cast<UDMF::Text>(this->unifiedRecord_); + OHOS::UDMF::UDDetails resDetails = resText->GetDetails(); + std::map<std::string, std::string> params; + for (auto it : resDetails) { + if (std::holds_alternative<std::string>(it.second)) { + const std::string &strValue = std::get<std::string>(it.second); + params.emplace(it.first, strValue); + } + } + char **keysHead = static_cast<char**>(malloc(sizeof(char*) * params.size())); + if (keysHead == nullptr) { + return ret; + } + char **valuesHead = static_cast<char**>(malloc(sizeof(char*) * params.size())); + if (valuesHead == nullptr) { + free(keysHead); + return ret; } + int64_t i = 0; + for (auto &param : params) { + keysHead[i] = CreateCStringFromString(param.first); + valuesHead[i] = CreateCStringFromString(param.second); + i++; + } + ret.keys.size = static_cast<int64_t>(params.size()); + ret.keys.head = keysHead; + ret.values.size = static_cast<int64_t>(params.size()); + ret.values.head = valuesHead; + return ret; +} - const std::shared_ptr<UDMF::UnifiedRecord> &CUnifiedRecord::GetUnifiedRecord() const - { - return unifiedRecord_; +void CUnifiedRecord::SetTextDetails(const std::map<std::string, std::string> &details) +{ + std::shared_ptr<UDMF::Text> resText = std::reinterpret_pointer_cast<UDMF::Text>(this->unifiedRecord_); + OHOS::UDMF::UDDetails udDetails; + for (auto &param : details) { + udDetails[param.first] = param.second; } + resText->SetDetails(udDetails); +} + +char *CUnifiedRecord::GetHyperLinkUrl() +{ + std::shared_ptr<UDMF::Link> resLink = std::reinterpret_pointer_cast<UDMF::Link>(this->unifiedRecord_); + std::string res = resLink->GetUrl(); + return Utils::MallocCString(res); +} + +void CUnifiedRecord::SetHyperLinkUrl(const char *url) +{ + std::shared_ptr<UDMF::Link> resLink = std::reinterpret_pointer_cast<UDMF::Link>(this->unifiedRecord_); + resLink->SetUrl(url); +} + +char *CUnifiedRecord::GetHyperLinkDescription() +{ + std::shared_ptr<UDMF::Link> resLink = std::reinterpret_pointer_cast<UDMF::Link>(this->unifiedRecord_); + std::string res = resLink->GetDescription(); + return Utils::MallocCString(res); +} + +void CUnifiedRecord::SetHyperLinkDescription(const char *description) +{ + std::shared_ptr<UDMF::Link> resLink = std::reinterpret_pointer_cast<UDMF::Link>(this->unifiedRecord_); + resLink->SetDescription(description); +} + +char *CUnifiedRecord::GetPlainTextContent() +{ + std::shared_ptr<UDMF::PlainText> resText = std::reinterpret_pointer_cast<UDMF::PlainText>(this->unifiedRecord_); + std::string res = resText->GetContent(); + return Utils::MallocCString(res); +} + +void CUnifiedRecord::SetPlainTextContent(const char *text) +{ + std::shared_ptr<UDMF::PlainText> resText = std::reinterpret_pointer_cast<UDMF::PlainText>(this->unifiedRecord_); + resText->SetContent(text); +} + +char *CUnifiedRecord::GetPlainTextAbstract() +{ + std::shared_ptr<UDMF::PlainText> resText = std::reinterpret_pointer_cast<UDMF::PlainText>(this->unifiedRecord_); + std::string res = resText->GetAbstract(); + return Utils::MallocCString(res); } + +void CUnifiedRecord::SetPlainTextAbstract(const char *abstr) +{ + std::shared_ptr<UDMF::PlainText> resText = std::reinterpret_pointer_cast<UDMF::PlainText>(this->unifiedRecord_); + resText->SetAbstract(abstr); +} + +char *CreateCStringFromString(const std::string &source) +{ + if (source.size() == 0) { + return nullptr; + } + size_t length = source.size() + 1; + auto res = static_cast<char*>(malloc(length)); + if (res == nullptr) { + return nullptr; + } + if (strcpy_s(res, length, source.c_str()) != 0) { + free(res); + return nullptr; + } + return res; } +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/interfaces/cj/src/utils.cpp b/udmf/interfaces/cj/src/utils.cpp index ce763896edc5d3f95a2d7b20a9f3296037bd026e..06df669fa356fa1d9a6b5f2b52df8f7eab3d2dcd 100644 --- a/udmf/interfaces/cj/src/utils.cpp +++ b/udmf/interfaces/cj/src/utils.cpp @@ -15,13 +15,13 @@ #include "utils.h" -char* Utils::MallocCString(const std::string& origin) +char *Utils::MallocCString(const std::string &origin) { if (origin.empty()) { return nullptr; } auto len = origin.length() + 1; - char* res = static_cast<char*>(malloc(sizeof(char) * len)); + char *res = static_cast<char*>(malloc(sizeof(char) * len)); if (res == nullptr) { return nullptr; } @@ -31,15 +31,28 @@ char* Utils::MallocCString(const std::string& origin) CArrString Utils::StringVectorToArray(std::vector<std::string> vector) { if (vector.size() == 0) { - return CArrString{}; + return CArrString {}; } - char **head = static_cast<char **>(malloc(vector.size() * sizeof(char *))); + char **head = static_cast<char**>(malloc(vector.size() * sizeof(char *))); if (head == nullptr) { - return CArrString{}; + return CArrString {}; } for (unsigned long i = 0; i < vector.size(); i++) { head[i] = Utils::MallocCString(vector[i]); } - CArrString stringArray = {head, vector.size()}; + CArrString stringArray = { head, vector.size() }; return stringArray; +} + +void Utils::FreeCArrString(CArrString &arrStr) +{ + if (arrStr.head == nullptr) { + return; + } + for (int64_t i = 0; i < arrStr.size; i++) { + free(arrStr.head[i]); + arrStr.head[i] = nullptr; + } + free(arrStr.head); + arrStr.head = nullptr; } \ No newline at end of file diff --git a/udmf/interfaces/components/UdmfComponents.js b/udmf/interfaces/components/UdmfComponents.js index 7fddb8e27eca022f1dddaa781149ecb7dd8ca045..0e2411247f908c6b55808d6d4a1f35cfde90a08a 100644 --- a/udmf/interfaces/components/UdmfComponents.js +++ b/udmf/interfaces/components/UdmfComponents.js @@ -18,8 +18,7 @@ if (!("finalizeConstruction" in ViewPU.prototype)) { } let image = requireNapi('multimedia.image'); -let j = requireNapi('i18n'); -let display = requireNapi('display'); +let i = requireNapi('i18n'); export var FormType; (function (FormType) { @@ -33,8 +32,8 @@ var TextType; TextType[TextType["DESCRIPTION"] = 1] = "DESCRIPTION"; TextType[TextType["APP_NAME"] = 2] = "APP_NAME"; })(TextType || (TextType = {})); -const m = 'udmf.ContentFormCard'; -const o = +const j = 'udmf.ContentFormCard'; +const m = '82,73,70,70,60,3,0,0,87,69,66,80,86,80,56,32,48,3,0,0,144,67,0,157,1,42,36,2,76,1,62,145,72,161,76,37,164,163,34,3' + '4,151,40,24,176,18,9,105,110,225,117,81,27,243,141,167,87,231,251,1,151,228,76,129,74,56,124,143,240,134,221,17,24' + '5,145,49,195,251,155,103,15,145,254,16,219,162,62,178,38,56,127,115,108,225,242,63,194,27,116,71,214,68,199,15,238' + @@ -61,21 +60,22 @@ const o = '38,70,81,93,158,178,96,58,63,135,99,61,33,123,114,106,17,205,205,245,73,209,248,208,230,67,84,83,67,62,174,199,125' + ',7,42,68,205,119,254,54,95,35,146,246,87,229,105,194,49,134,23,113,205,13,105,146,10,231,32,0,26,210,69,47,127,104' + ',73,141,205,245,214,23,231,110,132,188,27,13,88,8,43,145,225,60,68,0,42,15,95,85,238,25,204,75,166,163,127,0,0'; -const t = 1.2; -const u = 0.8; -const a1 = 0.6; +const o = 1.2; +const t = 0.8; +const u = 0.4; +const a1 = 200; const b1 = 200; -const c1 = 200; -const d1 = 100; -const e1 = 137; -const f1 = 83; -const g1 = 70; -const h1 = 40; -const i1 = 50; -const j1 = 30; -const l1 = 2; -const m1 = '100%'; -const n1 = '#E6FFFFFF'; +const c1 = 100; +const d1 = 137; +const e1 = 83; +const f1 = 70; +const g1 = 40; +const h1 = 50; +const i1 = 30; +const j1 = 2; +const l1 = '100%'; +const m1 = '#E6FFFFFF'; +const n1 = '#00000000'; const o1 = '#99182431'; const q1 = '#CCCCCC'; const s1 = '#55CCCCCC'; @@ -83,69 +83,69 @@ const t1 = '#ff182431'; const u1 = '#99182431'; const v1 = 72; const w1 = 59; -const q3 = 3.25; -const z1 = { - c2: 200, - d2: 120, - e2: 14, - f2: 16, - g2: 10, - h2: 14, - i2: 16, - j2: 4, - l2: 5, - m2: 10, - n2: 14, - o2: 12, - q2: 16, - s2: 6.5, - t2: 12, - u2: 10, - v2: 5 -}; +const z1 = 3.25; const a2 = { - c2: 36, - d2: 48, - w2: 14, + d2: 200, + e2: 120, + f2: 14, + g2: 16, h2: 10, - i2: 12, - z2: 14, - a3: 16, - j2: 10, - e2: 14, - f2: 16, - g2: 14, - l2: 5, - m2: 10, - n2: 14, - o2: 12, - q2: 16, - s2: 6.5, - t2: 12, - u2: 10, - v2: 5 + i2: 14, + j2: 16, + l2: 4, + m2: 5, + n2: 10, + o2: 14, + q2: 12, + s2: 16, + t2: 6.5, + u2: 12, + v2: 10, + w2: 5 }; const b2 = { - c2: 24, - d2: 24, - w2: 8, - e2: 12, - f2: 14, - g2: 9, - h2: 10, - i2: 12, - z2: 12, + d2: 36, + e2: 48, + z2: 14, + i2: 10, + j2: 12, a3: 14, - j2: 4, - l2: 5, - m2: 10, - o2: 12, + b3: 16, + l2: 10, + f2: 14, + g2: 16, + h2: 14, + m2: 5, + n2: 10, + o2: 14, q2: 12, - s2: 4, - n2: 12, - t2: 8, + s2: 16, + t2: 6.5, + u2: 12, + v2: 10, + w2: 5 +}; +const c2 = { + d2: 24, + e2: 24, + z2: 8, + f2: 12, + g2: 14, + h2: 9, + i2: 10, + j2: 12, + a3: 12, + b3: 14, + l2: 4, + m2: 5, + n2: 10, + q2: 12, + s2: 12, + t2: 4, + o2: 12, u2: 8, - v2: 4 + v2: 8, + w2: 4 }; export class ContentFormCard extends ViewPU { @@ -154,32 +154,32 @@ export class ContentFormCard extends ViewPU { if (typeof paramsLambda === "function") { this.paramsGenerator_ = paramsLambda; } - this.b3 = new SynchedPropertySimpleOneWayPU(params.formType, this, 'formType'); + this.__formType = new SynchedPropertySimpleOneWayPU(params.formType, this, "formType"); this.contentFormData = undefined; - this.formStyle = a2; + this.formStyle = b2; this.controller = new TextController(); - this.c3 = new ObservedPropertySimplePU(1, this, 'cardScale'); - this.d3 = new SynchedPropertySimpleOneWayPU(params.formWidth, this, 'formWidth'); - this.e3 = new SynchedPropertySimpleOneWayPU(params.formHeight, this, 'formHeight'); - this.f3 = new ObservedPropertySimplePU(0, this, 'cardWidth'); - this.g3 = new ObservedPropertySimplePU(0, this, 'cardHeight'); - this.h3 = new ObservedPropertyObjectPU(undefined, this, 'defaultThumbImage'); - this.i3 = new ObservedPropertyObjectPU(undefined, this, 'thumbImage'); - this.j3 = new ObservedPropertyObjectPU(undefined, this, 'appImage'); - this.l3 = new ObservedPropertySimplePU(1, this, 'lineCount'); - this.m3 = new ObservedPropertySimplePU(false, this, 'isMirrorLanguageType'); + this.__cardScale = new ObservedPropertySimplePU(1, this, "cardScale"); + this.__formWidth = new SynchedPropertySimpleOneWayPU(params.formWidth, this, "formWidth"); + this.__formHeight = new SynchedPropertySimpleOneWayPU(params.formHeight, this, "formHeight"); + this.__cardWidth = new ObservedPropertySimplePU(0, this, "cardWidth"); + this.__cardHeight = new ObservedPropertySimplePU(0, this, "cardHeight"); + this.__defaultThumbImage = new ObservedPropertyObjectPU(undefined, this, "defaultThumbImage"); + this.__thumbImage = new ObservedPropertyObjectPU(undefined, this, "thumbImage"); + this.__appImage = new ObservedPropertyObjectPU(undefined, this, "appImage"); + this.__lineCount = new ObservedPropertySimplePU(1, this, "lineCount"); + this.__isMirrorLanguageType = new ObservedPropertySimplePU(false, this, "isMirrorLanguageType"); this.handleOnClick = () => { }; this.setInitiallyProvidedValue(params); - this.declareWatch('formType', this.formTypeChange); - this.declareWatch('formWidth', this.formSizeChange); - this.declareWatch('formHeight', this.formSizeChange); + this.declareWatch("formType", this.formTypeChange); + this.declareWatch("formWidth", this.formSizeChange); + this.declareWatch("formHeight", this.formSizeChange); this.finalizeConstruction(); } setInitiallyProvidedValue(params) { if (params.formType === undefined) { - this.b3.set(FormType.TYPE_MID); + this.__formType.set(FormType.TYPE_MID); } if (params.contentFormData !== undefined) { this.contentFormData = params.contentFormData; @@ -194,10 +194,10 @@ export class ContentFormCard extends ViewPU { this.cardScale = params.cardScale; } if (params.formWidth === undefined) { - this.d3.set(0); + this.__formWidth.set(0); } if (params.formHeight === undefined) { - this.e3.set(0); + this.__formHeight.set(0); } if (params.cardWidth !== undefined) { this.cardWidth = params.cardWidth; @@ -226,127 +226,127 @@ export class ContentFormCard extends ViewPU { } updateStateVars(params) { - this.b3.reset(params.formType); - this.d3.reset(params.formWidth); - this.e3.reset(params.formHeight); + this.__formType.reset(params.formType); + this.__formWidth.reset(params.formWidth); + this.__formHeight.reset(params.formHeight); } purgeVariableDependenciesOnElmtId(rmElmtId) { - this.b3.purgeDependencyOnElmtId(rmElmtId); - this.c3.purgeDependencyOnElmtId(rmElmtId); - this.d3.purgeDependencyOnElmtId(rmElmtId); - this.e3.purgeDependencyOnElmtId(rmElmtId); - this.f3.purgeDependencyOnElmtId(rmElmtId); - this.g3.purgeDependencyOnElmtId(rmElmtId); - this.h3.purgeDependencyOnElmtId(rmElmtId); - this.i3.purgeDependencyOnElmtId(rmElmtId); - this.j3.purgeDependencyOnElmtId(rmElmtId); - this.l3.purgeDependencyOnElmtId(rmElmtId); - this.m3.purgeDependencyOnElmtId(rmElmtId); + this.__formType.purgeDependencyOnElmtId(rmElmtId); + this.__cardScale.purgeDependencyOnElmtId(rmElmtId); + this.__formWidth.purgeDependencyOnElmtId(rmElmtId); + this.__formHeight.purgeDependencyOnElmtId(rmElmtId); + this.__cardWidth.purgeDependencyOnElmtId(rmElmtId); + this.__cardHeight.purgeDependencyOnElmtId(rmElmtId); + this.__defaultThumbImage.purgeDependencyOnElmtId(rmElmtId); + this.__thumbImage.purgeDependencyOnElmtId(rmElmtId); + this.__appImage.purgeDependencyOnElmtId(rmElmtId); + this.__lineCount.purgeDependencyOnElmtId(rmElmtId); + this.__isMirrorLanguageType.purgeDependencyOnElmtId(rmElmtId); } aboutToBeDeleted() { - this.b3.aboutToBeDeleted(); - this.c3.aboutToBeDeleted(); - this.d3.aboutToBeDeleted(); - this.e3.aboutToBeDeleted(); - this.f3.aboutToBeDeleted(); - this.g3.aboutToBeDeleted(); - this.h3.aboutToBeDeleted(); - this.i3.aboutToBeDeleted(); - this.j3.aboutToBeDeleted(); - this.l3.aboutToBeDeleted(); - this.m3.aboutToBeDeleted(); + this.__formType.aboutToBeDeleted(); + this.__cardScale.aboutToBeDeleted(); + this.__formWidth.aboutToBeDeleted(); + this.__formHeight.aboutToBeDeleted(); + this.__cardWidth.aboutToBeDeleted(); + this.__cardHeight.aboutToBeDeleted(); + this.__defaultThumbImage.aboutToBeDeleted(); + this.__thumbImage.aboutToBeDeleted(); + this.__appImage.aboutToBeDeleted(); + this.__lineCount.aboutToBeDeleted(); + this.__isMirrorLanguageType.aboutToBeDeleted(); SubscriberManager.Get().delete(this.id__()); this.aboutToBeDeletedInternal(); } get formType() { - return this.b3.get(); + return this.__formType.get(); } set formType(newValue) { - this.b3.set(newValue); + this.__formType.set(newValue); } get cardScale() { - return this.c3.get(); + return this.__cardScale.get(); } set cardScale(newValue) { - this.c3.set(newValue); + this.__cardScale.set(newValue); } get formWidth() { - return this.d3.get(); + return this.__formWidth.get(); } set formWidth(newValue) { - this.d3.set(newValue); + this.__formWidth.set(newValue); } get formHeight() { - return this.e3.get(); + return this.__formHeight.get(); } set formHeight(newValue) { - this.e3.set(newValue); + this.__formHeight.set(newValue); } get cardWidth() { - return this.f3.get(); + return this.__cardWidth.get(); } set cardWidth(newValue) { - this.f3.set(newValue); + this.__cardWidth.set(newValue); } get cardHeight() { - return this.g3.get(); + return this.__cardHeight.get(); } set cardHeight(newValue) { - this.g3.set(newValue); + this.__cardHeight.set(newValue); } get defaultThumbImage() { - return this.h3.get(); + return this.__defaultThumbImage.get(); } set defaultThumbImage(newValue) { - this.h3.set(newValue); + this.__defaultThumbImage.set(newValue); } get thumbImage() { - return this.i3.get(); + return this.__thumbImage.get(); } set thumbImage(newValue) { - this.i3.set(newValue); + this.__thumbImage.set(newValue); } get appImage() { - return this.j3.get(); + return this.__appImage.get(); } set appImage(newValue) { - this.j3.set(newValue); + this.__appImage.set(newValue); } get lineCount() { - return this.l3.get(); + return this.__lineCount.get(); } set lineCount(newValue) { - this.l3.set(newValue); + this.__lineCount.set(newValue); } get isMirrorLanguageType() { - return this.m3.get(); + return this.__isMirrorLanguageType.get(); } set isMirrorLanguageType(newValue) { - this.m3.set(newValue); + this.__isMirrorLanguageType.set(newValue); } aboutToAppear() { @@ -364,13 +364,13 @@ export class ContentFormCard extends ViewPU { formTypeChange() { switch (this.formType) { case FormType.TYPE_BIG: - this.formWidth = b1; + this.formWidth = a1; break; case FormType.TYPE_MID: - this.formWidth = c1; + this.formWidth = b1; break; default: - this.formWidth = e1; + this.formWidth = d1; break; } this.initCardStyle(); @@ -380,39 +380,40 @@ export class ContentFormCard extends ViewPU { this.initCardStyle(); } - initCardScale(n2, o2, q2) { - let r2 = this.formType === FormType.TYPE_SMALL ? a1 : u; - if (n2 > t) { - this.cardScale = t; - } else if (n2 < r2) { - this.cardScale = r2; + initCardScale(o2, q2, r2) { + let s2 = this.formType === FormType.TYPE_SMALL ? u : t; + if (o2 > o) { + this.cardScale = o; + } else if (o2 < s2) { + this.cardScale = s2; } else { - this.cardScale = n2; + this.cardScale = o2; } - this.cardWidth = o2 * this.cardScale; + this.cardWidth = q2 * this.cardScale; this.cardHeight = - (this.contentFormData?.title === '' && this.formHeight > 0) ? this.formHeight : q2 * this.cardScale; - console.info(`${m}, widthScale:${this.cardScale}, cardScale: ${this.cardScale}, ` + + (this.contentFormData?.title === '' && this.formHeight > 0) ? this.formHeight : r2 * this.cardScale; + console.info(`${j}, widthScale:${this.cardScale}, cardScale: ${this.cardScale}, ` + `cardWidth: ${this.cardWidth}, cardHeight: ${this.cardHeight}`); } initCardStyle() { - let m2 = 1; + let n2 = 1; + this.lineCount = 2; switch (this.formType) { case FormType.TYPE_BIG: - this.formStyle = z1; - m2 = this.formWidth ? this.formWidth / b1 : 1; - this.initCardScale(m2, b1, b1); + this.formStyle = a2; + n2 = this.formWidth ? this.formWidth / a1 : 1; + this.initCardScale(n2, a1, a1); break; case FormType.TYPE_MID: - this.formStyle = a2; - m2 = this.formWidth ? this.formWidth / c1 : 1; - this.initCardScale(m2, c1, d1); + this.formStyle = b2; + n2 = this.formWidth ? this.formWidth / b1 : 1; + this.initCardScale(n2, b1, c1); break; default: - this.formStyle = b2; - m2 = this.formWidth ? this.formWidth / e1 : 1; - this.initCardScale(m2, e1, f1); + this.formStyle = c2; + n2 = this.formWidth ? this.formWidth / d1 : 1; + this.initCardScale(n2, d1, e1); break; } } @@ -422,29 +423,35 @@ export class ContentFormCard extends ViewPU { Column.create(); Column.size({ width: '100%' }); Column.layoutWeight(this.formHeight > 0 ? 1 : 0); - Column.backgroundColor(this.thumbImage ? n1 : q1); + Column.backgroundColor(this.thumbImage ? m1 : q1); }, Column); this.observeComponentCreation2((elmtId, isInitialRender) => { If.create(); if (this.formHeight > 0) { this.ifElseBranchUpdateFunction(0, () => { - this.observeComponentCreation2((elmtId, isInitialRender) => { - Image.create(this.thumbImage ? this.thumbImage : this.defaultThumbImage); - Image.objectFit(ImageFit.Contain); - Image.width('100%'); - Image.layoutWeight(1); - Image.draggable(false); - }, Image); + if (!If.canRetake('cardThumbImage')) { + this.observeComponentCreation2((elmtId, isInitialRender) => { + Image.create(this.thumbImage ? this.thumbImage : this.defaultThumbImage); + Image.objectFit(ImageFit.Contain); + Image.width('100%'); + Image.layoutWeight(1); + Image.draggable(false); + Image.id('cardThumbImage'); + }, Image); + } }); } else { this.ifElseBranchUpdateFunction(1, () => { - this.observeComponentCreation2((elmtId, isInitialRender) => { - Image.create(this.thumbImage ? this.thumbImage : this.defaultThumbImage); - Image.objectFit(ImageFit.Contain); - Image.width('100%'); - Image.aspectRatio(this.getAspectRatio()); - Image.draggable(false); - }, Image); + if (!If.canRetake('cardThumbImage')) { + this.observeComponentCreation2((elmtId, isInitialRender) => { + Image.create(this.thumbImage ? this.thumbImage : this.defaultThumbImage); + Image.objectFit(ImageFit.Contain); + Image.width('100%'); + Image.aspectRatio(this.getAspectRatio()); + Image.draggable(false); + Image.id('cardThumbImage'); + }, Image); + } }); } }, If); @@ -458,26 +465,26 @@ export class ContentFormCard extends ViewPU { Divider.height(1); Divider.opacity(0.5); Divider.padding({ - left: this.formStyle.t2 * this.cardScale, - right: this.formStyle.t2 * this.cardScale + left: this.formStyle.u2 * this.cardScale, + right: this.formStyle.u2 * this.cardScale }); }, Divider); } AppView(parent = null) { this.observeComponentCreation2((elmtId, isInitialRender) => { - Row.create({ space: this.formStyle.s2 * this.cardScale }); + Row.create({ space: this.formStyle.t2 * this.cardScale }); Row.padding({ - left: this.formStyle.t2 * this.cardScale, - right: this.formStyle.t2 * this.cardScale, - top: this.formStyle.v2 * this.cardScale, - bottom: this.formStyle.u2 * this.cardScale, + left: this.formStyle.u2 * this.cardScale, + right: this.formStyle.u2 * this.cardScale, + top: this.formStyle.w2 * this.cardScale, + bottom: this.formStyle.v2 * this.cardScale, }); }, Row); this.observeComponentCreation2((elmtId, isInitialRender) => { Image.create(this.appImage); - Image.width(this.formStyle.o2 * this.cardScale); - Image.height(this.formStyle.o2 * this.cardScale); + Image.width(this.formStyle.q2 * this.cardScale); + Image.height(this.formStyle.q2 * this.cardScale); Image.objectFit(ImageFit.Fill); Image.alt({ "id": -1, @@ -494,21 +501,23 @@ export class ContentFormCard extends ViewPU { "moduleName": "__harDefaultModuleName__" }); Image.draggable(false); + Image.id('cardAppIcon'); }, Image); this.observeComponentCreation2((elmtId, isInitialRender) => { Text.create(this.contentFormData?.appName ? this.contentFormData?.appName : ' '); - Text.fontSize(this.formStyle.m2 * this.cardScale); + Text.fontSize(this.formStyle.n2 * this.cardScale); Text.fontColor(o1); Text.maxLines(1); - Text.lineHeight(this.formStyle.n2 * this.cardScale); + Text.lineHeight(this.formStyle.o2 * this.cardScale); Text.textOverflow({ overflow: TextOverflow.Ellipsis }); Text.constraintSize({ minWidth: this.getTextSize(TextType.APP_NAME, this.contentFormData?.appName) }); Text.backgroundColor(this.getTextBackground(this.contentFormData?.appName)); Text.fontWeight(FontWeight.Regular); - Text.borderRadius(this.contentFormData?.title === '' ? 0 : l1); + Text.borderRadius(this.contentFormData?.title === '' ? 0 : j1); Text.direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr); Text.maxFontScale(1); Text.layoutWeight(1); + Text.id('cardAppName'); }, Text); Text.pop(); Row.pop(); @@ -517,18 +526,19 @@ export class ContentFormCard extends ViewPU { TitleText(parent = null) { this.observeComponentCreation2((elmtId, isInitialRender) => { Text.create(this.contentFormData?.title); - Text.fontSize(this.formStyle.e2 * this.cardScale); + Text.fontSize(this.formStyle.f2 * this.cardScale); Text.fontColor(t1); Text.fontWeight(FontWeight.Bold); Text.maxLines(1); Text.textOverflow({ overflow: TextOverflow.Ellipsis }); - Text.height(this.formStyle.f2 * this.cardScale); - Text.margin({ top: this.formStyle.g2 * this.cardScale }); + Text.height(this.formStyle.g2 * this.cardScale); + Text.margin({ top: this.formStyle.h2 * this.cardScale }); Text.constraintSize({ minWidth: this.getTextSize(TextType.TITLE, this.contentFormData?.title) }); Text.backgroundColor(this.getTextBackground(this.contentFormData?.title)); - Text.borderRadius(this.contentFormData?.title === '' ? 0 : l1); + Text.borderRadius(this.contentFormData?.title === '' ? 0 : j1); Text.direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr); Text.maxFontScale(1); + Text.id('cardTitleText'); }, Text); Text.pop(); } @@ -542,25 +552,26 @@ export class ContentFormCard extends ViewPU { Image.create(this.thumbImage ? this.thumbImage : this.defaultThumbImage); Image.objectFit(ImageFit.Cover); Image.width('100%'); - Image.height(this.formStyle.d2 * this.cardScale); - Image.backgroundColor(this.thumbImage ? n1 : q1); + Image.height(this.formStyle.e2 * this.cardScale); + Image.backgroundColor(this.thumbImage ? m1 : q1); Image.draggable(false); + Image.id('cardThumbImage'); }, Image); this.observeComponentCreation2((elmtId, isInitialRender) => { Column.create(); Column.alignItems(HorizontalAlign.Start); Column.width('100%'); Column.padding({ - left: this.formStyle.t2 * this.cardScale, - right: this.formStyle.t2 * this.cardScale + left: this.formStyle.u2 * this.cardScale, + right: this.formStyle.u2 * this.cardScale }); - Column.margin({ bottom: this.formStyle.l2 * this.cardScale }); + Column.margin({ bottom: this.formStyle.m2 * this.cardScale }); Column.justifyContent(FlexAlign.Center); }, Column); this.TitleText.bind(this)(); this.observeComponentCreation2((elmtId, isInitialRender) => { Text.create(this.contentFormData?.description); - Text.fontSize(this.formStyle.h2 * this.cardScale); + Text.fontSize(this.formStyle.i2 * this.cardScale); Text.fontColor(u1); Text.fontWeight(FontWeight.Regular); Text.maxLines(1); @@ -568,13 +579,14 @@ export class ContentFormCard extends ViewPU { Text.constraintSize({ minWidth: this.getTextSize(TextType.DESCRIPTION, this.contentFormData?.description) }); - Text.height(this.formStyle.i2 * this.cardScale); - Text.margin({ top: this.formStyle.j2 * this.cardScale }); + Text.height(this.formStyle.j2 * this.cardScale); + Text.margin({ top: this.formStyle.l2 * this.cardScale }); Text.backgroundColor(this.getTextBackground(this.contentFormData?.description)); Text.fontWeight(FontWeight.Regular); - Text.borderRadius(this.contentFormData?.description ? 0 : l1); + Text.borderRadius(this.contentFormData?.description ? 0 : j1); Text.direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr); Text.maxFontScale(1); + Text.id('cardDescription'); }, Text); Text.pop(); Column.pop(); @@ -593,20 +605,23 @@ export class ContentFormCard extends ViewPU { Text.fontWeight(FontWeight.Regular); Text.textOverflow({ overflow: TextOverflow.Ellipsis }); Text.lineHeight((this.lineCount === 1 ? - (this.formStyle.a3 ? this.formStyle.a3 : - this.formStyle.i2) : this.formStyle.i2) * this.cardScale); - Text.fontSize(this.getDescriptionFontSize()); + (this.formStyle.b3 ? this.formStyle.b3 : + this.formStyle.j2) : this.formStyle.j2) * this.cardScale); + Text.fontSize(this.getDescriptionFontSize() * this.cardScale); Text.constraintSize({ minWidth: this.getTextSize(TextType.DESCRIPTION, this.contentFormData?.description) }); Text.backgroundColor(this.getTextBackground(this.contentFormData?.description)); - Text.borderRadius(this.contentFormData?.description ? 0 : l1); + Text.borderRadius(this.contentFormData?.description ? 0 : j1); Text.onAreaChange(() => { - let l2 = this.controller.getLayoutManager(); - this.lineCount = l2.getLineCount(); + let m2 = this.controller.getLayoutManager(); + if (m2.getLineCount() === 2) { + this.lineCount = 2; + } }); Text.direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr); Text.maxFontScale(1); + Text.id('cardDescription'); }, Text); Text.pop(); } @@ -629,15 +644,15 @@ export class ContentFormCard extends ViewPU { Row.create(); Row.width('100%'); Row.padding({ - left: this.formStyle.t2 * this.cardScale, - right: this.formStyle.t2 * this.cardScale + left: this.formStyle.u2 * this.cardScale, + right: this.formStyle.u2 * this.cardScale }); Row.layoutWeight(1); - Row.margin({ bottom: this.formStyle.l2 * this.cardScale }); + Row.margin({ bottom: this.formStyle.m2 * this.cardScale }); Row.alignItems(VerticalAlign.Top); }, Row); this.observeComponentCreation2((elmtId, isInitialRender) => { - Column.create({ space: this.formStyle.j2 * this.cardScale }); + Column.create({ space: this.formStyle.l2 * this.cardScale }); Column.layoutWeight(1); Column.alignItems(HorizontalAlign.Start); }, Column); @@ -648,19 +663,22 @@ export class ContentFormCard extends ViewPU { If.create(); if (this.thumbImage) { this.ifElseBranchUpdateFunction(0, () => { - this.observeComponentCreation2((elmtId, isInitialRender) => { - Image.create(this.thumbImage); - Image.width(this.formStyle.c2 * this.cardScale); - Image.height(this.formStyle.d2 * this.cardScale); - Image.objectFit(this.thumbImage ? ImageFit.Cover : ImageFit.Contain); - Image.borderRadius(4); - Image.draggable(false); - Image.margin({ - right: this.isMirrorLanguageType ? (this.formStyle.w2 * this.cardScale) : 0, - left: this.isMirrorLanguageType ? 0 : (this.formStyle.w2 * this.cardScale), - top: this.formStyle.g2 * this.cardScale - }); - }, Image); + if (!If.canRetake('cardThumbImage')) { + this.observeComponentCreation2((elmtId, isInitialRender) => { + Image.create(this.thumbImage); + Image.width(this.formStyle.d2 * this.cardScale); + Image.height(this.formStyle.e2 * this.cardScale); + Image.objectFit(this.thumbImage ? ImageFit.Cover : ImageFit.Contain); + Image.borderRadius(4); + Image.draggable(false); + Image.margin({ + right: this.isMirrorLanguageType ? (this.formStyle.z2 * this.cardScale) : 0, + left: this.isMirrorLanguageType ? 0 : (this.formStyle.z2 * this.cardScale), + top: this.formStyle.h2 * this.cardScale + }); + Image.id('cardThumbImage'); + }, Image); + } }); } else { this.ifElseBranchUpdateFunction(1, () => { @@ -696,17 +714,17 @@ export class ContentFormCard extends ViewPU { Column.create(); Column.width('100%'); Column.padding({ - left: this.formStyle.t2 * this.cardScale, - right: this.formStyle.t2 * this.cardScale + left: this.formStyle.u2 * this.cardScale, + right: this.formStyle.u2 * this.cardScale }); Column.layoutWeight(1); Column.alignItems(HorizontalAlign.Start); - Column.margin({ bottom: this.formStyle.l2 * this.cardScale }); + Column.margin({ bottom: this.formStyle.m2 * this.cardScale }); }, Column); this.TitleText.bind(this)(); this.observeComponentCreation2((elmtId, isInitialRender) => { Row.create(); - Row.margin({ top: this.formStyle.j2 * this.cardScale }); + Row.margin({ top: this.formStyle.l2 * this.cardScale }); Row.layoutWeight(1); }, Row); this.observeComponentCreation2((elmtId, isInitialRender) => { @@ -720,24 +738,27 @@ export class ContentFormCard extends ViewPU { If.create(); if (this.thumbImage) { this.ifElseBranchUpdateFunction(0, () => { - this.observeComponentCreation2((elmtId, isInitialRender) => { - Image.create(this.thumbImage); - Image.objectFit(ImageFit.Cover); - Image.borderRadius({ - "id": -1, - "type": 10002, - params: ['sys.float.corner_radius_level2'], - "bundleName": "__harDefaultBundleName__", - "moduleName": "__harDefaultModuleName__" - }); - Image.width(this.formStyle.c2 * this.cardScale); - Image.height(this.formStyle.d2 * this.cardScale); - Image.draggable(false); - Image.margin({ - left: this.isMirrorLanguageType ? 0 : (this.formStyle.w2 * this.cardScale), - right: this.isMirrorLanguageType ? (this.formStyle.w2 * this.cardScale) : 0 - }); - }, Image); + if (!If.canRetake('cardThumbImage')) { + this.observeComponentCreation2((elmtId, isInitialRender) => { + Image.create(this.thumbImage); + Image.objectFit(ImageFit.Cover); + Image.borderRadius({ + "id": -1, + "type": 10002, + params: ['sys.float.corner_radius_level2'], + "bundleName": "__harDefaultBundleName__", + "moduleName": "__harDefaultModuleName__" + }); + Image.width(this.formStyle.d2 * this.cardScale); + Image.height(this.formStyle.e2 * this.cardScale); + Image.draggable(false); + Image.margin({ + left: this.isMirrorLanguageType ? 0 : (this.formStyle.z2 * this.cardScale), + right: this.isMirrorLanguageType ? (this.formStyle.z2 * this.cardScale) : 0 + }); + Image.id('cardThumbImage'); + }, Image); + } }); } else { this.ifElseBranchUpdateFunction(1, () => { @@ -759,25 +780,25 @@ export class ContentFormCard extends ViewPU { initialRender() { this.observeComponentCreation2((elmtId, isInitialRender) => { Column.create(); - Column.borderRadius(this.formStyle.q2 * this.cardScale); + Column.borderRadius(this.formStyle.s2 * this.cardScale); Column.clip(true); - Column.backgroundColor(n1); - Column.backgroundBlurStyle(BlurStyle.COMPONENT_ULTRA_THICK, { colorMode: ThemeColorMode.LIGHT, adaptiveColor: AdaptiveColor.DEFAULT, scale: 1.0 }); + Column.backgroundColor(m1); + Column.backgroundBlurStyle(BlurStyle.COMPONENT_ULTRA_THICK, + { colorMode: ThemeColorMode.LIGHT, adaptiveColor: AdaptiveColor.DEFAULT, scale: 1.0 }); Column.shadow(ShadowStyle.OUTER_DEFAULT_SM); Column.width(this.cardWidth); Column.onClick(() => { + this.handleOnClick(); if (!this.contentFormData?.linkUri) { - console.warn(`${m}, linkUri is null`); + console.warn(`${j}, linkUri is null`); return; } - this.handleOnClick(); try { let context = getContext(this); context.openLink(this.contentFormData?.linkUri, { appLinkingOnly: false, parameters: {} }); - } - catch (err) { + } catch (err) { let error = err; - console.error(`${m}, Failed to openLink, code is ${error.code}, message is ${error.message}`); + console.error(`${j}, Failed to openLink, code is ${error.code}, message is ${error.message}`); } }); }, Column); @@ -787,13 +808,11 @@ export class ContentFormCard extends ViewPU { this.ifElseBranchUpdateFunction(0, () => { this.Card4x4.bind(this)(); }); - } - else if (this.formType === FormType.TYPE_MID) { + } else if (this.formType === FormType.TYPE_MID) { this.ifElseBranchUpdateFunction(1, () => { this.Card4x2.bind(this)(); }); - } - else { + } else { this.ifElseBranchUpdateFunction(2, () => { this.Card2x1.bind(this)(); }); @@ -805,44 +824,44 @@ export class ContentFormCard extends ViewPU { initSystemLanguage() { try { - this.isMirrorLanguageType = j.isRTL(j.System.getSystemLanguage()); + this.isMirrorLanguageType = i.isRTL(i.System.getSystemLanguage()); } catch (err) { let error = err; - console.error(`${m}, Failed to init system language, code is ${error.code}, message is ${error.message}`); + console.error(`${j}, Failed to init system language, code is ${error.code}, message is ${error.message}`); } return true; } - async getPixelMap(i2, callback) { - let j2 = undefined; + async getPixelMap(j2, callback) { + let k2 = undefined; try { - j2 = image.createImageSource(i2.buffer); - let k2 = await j2?.createPixelMap(); - callback(k2); - j2.release(); + k2 = image.createImageSource(j2.buffer); + let l2 = await k2?.createPixelMap(); + callback(l2); + k2.release(); } catch (err) { let error = err; - console.error(`${m}, Failed to create pixelMap, code is ${error.code}, message is ${error.message}`); + console.error(`${j}, Failed to create pixelMap, code is ${error.code}, message is ${error.message}`); } } - transStringToUint8Array(g2) { - const arr = g2.split(','); - const h2 = new Uint8Array(arr.length); + transStringToUint8Array(h2) { + const arr = h2.split(','); + const i2 = new Uint8Array(arr.length); arr.forEach((value, index) => { - h2[index] = parseInt(value); + i2[index] = parseInt(value); }); - return h2; + return i2; } createPixelMap() { - let f2 = this.transStringToUint8Array(o); - this.getPixelMap(f2, (pixelMap) => { + let g2 = this.transStringToUint8Array(m); + this.getPixelMap(g2, (pixelMap) => { this.defaultThumbImage = pixelMap; }); if (this.contentFormData && this.contentFormData?.thumbData) { if (!(this.contentFormData?.thumbData instanceof Uint8Array)) { - console.error(`${m}, thumbData is not Uint8Array`); + console.error(`${j}, thumbData is not Uint8Array`); return; } this.getPixelMap(this.contentFormData?.thumbData, (pixelMap) => { @@ -851,7 +870,7 @@ export class ContentFormCard extends ViewPU { } if (this.contentFormData && this.contentFormData?.appIcon) { if (!(this.contentFormData?.appIcon instanceof Uint8Array)) { - console.error(`${m}, appIcon is not Uint8Array`); + console.error(`${j}, appIcon is not Uint8Array`); return; } this.getPixelMap(this.contentFormData?.appIcon, (pixelMap) => { @@ -861,19 +880,19 @@ export class ContentFormCard extends ViewPU { } getAspectRatio() { - let c2 = this.thumbImage?.getImageInfoSync().size; - let d2 = this.formType === FormType.TYPE_MID ? c1 : e1; - let e2 = this.formType === FormType.TYPE_MID ? v1 : w1; - if (c2 && this.thumbImage) { - if ((c2.width / c2.height) > (d2 / (e2 * u))) { - return d2 / (e2 * u); + let d2 = this.thumbImage?.getImageInfoSync().size; + let e2 = this.formType === FormType.TYPE_MID ? b1 : d1; + let f2 = this.formType === FormType.TYPE_MID ? v1 : w1; + if (d2 && this.thumbImage) { + if ((d2.width / d2.height) > (e2 / (f2 * t))) { + return e2 / (f2 * t); } - if ((c2.width / c2.height) < (d2 / (e2 * t))) { - return d2 / (e2 * t); + if ((d2.width / d2.height) < (e2 / (f2 * o))) { + return e2 / (f2 * o); } - return c2.width / c2.height; + return d2.width / d2.height; } - return d2 / e2; + return e2 / f2; } getTextBackground(text) { @@ -887,20 +906,20 @@ export class ContentFormCard extends ViewPU { if (textType === TextType.TITLE) { if (text === '' || text === undefined || text === null) { if (this.formType === FormType.TYPE_SMALL) { - return i1; + return h1; } - return g1; + return f1; } - return m1; + return l1; } if (textType === TextType.APP_NAME) { if (text === '' || text === undefined || text === null) { if (this.formType === FormType.TYPE_SMALL) { - return j1; + return i1; } - return h1; + return g1; } - return m1; + return l1; } return '100%'; } @@ -916,15 +935,15 @@ export class ContentFormCard extends ViewPU { }; } return { - maxHeight: this.cardHeight * t, - minHeight: this.cardHeight * u + maxHeight: this.cardHeight * o, + minHeight: this.cardHeight * t }; } } getDescriptionFontSize() { - return this.lineCount === 1 ? (this.formStyle.z2 ? this.formStyle.z2 : - this.formStyle.h2) : (this.formStyle.h2 * this.cardScale); + return this.lineCount === 1 ? (this.formStyle.a3 ? this.formStyle.a3 : + this.formStyle.i2) : this.formStyle.i2; } rerender() { diff --git a/udmf/interfaces/components/source/UdmfComponents.ets b/udmf/interfaces/components/source/UdmfComponents.ets index 0377f35f0cc44afb3059657264d16e567da20b58..a2ced7c9bfa2dfaf2bdb548e307af068933a703b 100644 --- a/udmf/interfaces/components/source/UdmfComponents.ets +++ b/udmf/interfaces/components/source/UdmfComponents.ets @@ -61,7 +61,7 @@ const defaultIcon: string = ',73,141,205,245,214,23,231,110,132,188,27,13,88,8,43,145,225,60,68,0,42,15,95,85,238,25,204,75,166,163,127,0,0'; const MAX_CARD_SCALE: number = 1.2; const MIN_CARD_SCALE: number = 0.8; -const SMALL_MIN_CARD_SCALE: number = 0.6; +const SMALL_MIN_CARD_SCALE: number = 0.4; const DEFAULT_BIG_CARD_SIZE: number = 200; const DEFAULT_MID_CARD_WIDTH: number = 200; const DEFAULT_MID_CARD_HEIGHT: number = 100; @@ -74,6 +74,7 @@ const SMALL_EMPTY_APPNAME_WIDTH: number = 30; const DEFAULT_EMPTY_TEXT_RADIUS: number = 2; const DEFAULT_EMPTY_DESCRIPTION_WIDTH: string = '100%'; const CARD_BACKGROUND: string = '#E6FFFFFF'; +const TRANSLATE_BACKGROUND: string = '#00000000'; const APP_NAME_COLOR: string = '#99182431'; const DEFAULT_THUMB_BACKGROUND: string = '#CCCCCC'; const DEFAULT_FONT_BACKGROUND: string = '#55CCCCCC'; @@ -241,6 +242,7 @@ export struct ContentFormCard { initCardStyle(): void { let widthScale = 1; + this.lineCount = 1; switch (this.formType) { case FormType.TYPE_BIG: this.formStyle = BIG_CARD_STYLE; @@ -279,12 +281,14 @@ export struct ContentFormCard { .width('100%') .layoutWeight(1) .draggable(false) + .id('cardThumbImage') } else { Image(this.thumbImage ? this.thumbImage : this.defaultThumbImage) .objectFit(ImageFit.Contain) .width('100%') .aspectRatio(this.getAspectRatio()) .draggable(false) + .id('cardThumbImage') } } .size({ width: '100%' }) @@ -313,6 +317,7 @@ export struct ContentFormCard { .alt($r('sys.media.ohos_app_icon')) .borderRadius($r('sys.float.corner_radius_level1')) .draggable(false) + .id('cardAppIcon') Text(this.contentFormData?.appName ? this.contentFormData?.appName : ' ') .fontSize(this.formStyle.appNameFontSize * this.cardScale) .fontColor(APP_NAME_COLOR) @@ -326,6 +331,7 @@ export struct ContentFormCard { .direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr) .maxFontScale(1) .layoutWeight(1) + .id('cardAppName') } .padding({ @@ -351,6 +357,7 @@ export struct ContentFormCard { .borderRadius(this.contentFormData?.title === '' ? 0 : DEFAULT_EMPTY_TEXT_RADIUS) .direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr) .maxFontScale(1) + .id('cardTitleText') } @Builder @@ -362,6 +369,7 @@ export struct ContentFormCard { .height(this.formStyle.thumbHeight * this.cardScale) .backgroundColor(this.thumbImage ? CARD_BACKGROUND : DEFAULT_THUMB_BACKGROUND) .draggable(false) + .id('cardThumbImage') Column() { this.TitleText() Text(this.contentFormData?.description) @@ -378,6 +386,7 @@ export struct ContentFormCard { .borderRadius(this.contentFormData?.description ? 0 : DEFAULT_EMPTY_TEXT_RADIUS) .direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr) .maxFontScale(1) + .id('cardDescription') } .alignItems(HorizontalAlign.Start) .width('100%') @@ -405,16 +414,20 @@ export struct ContentFormCard { .lineHeight((this.lineCount === 1 ? (this.formStyle.maxDescriptionLineHeight ? this.formStyle.maxDescriptionLineHeight : this.formStyle.descriptionLineHeight) : this.formStyle.descriptionLineHeight) * this.cardScale) - .fontSize(this.getDescriptionFontSize()) + .fontSize(this.getDescriptionFontSize() * this.cardScale) .constraintSize({ minWidth: this.getTextSize(TextType.DESCRIPTION, this.contentFormData?.description) }) .backgroundColor(this.getTextBackground(this.contentFormData?.description)) .borderRadius(this.contentFormData?.description ? 0 : DEFAULT_EMPTY_TEXT_RADIUS) .onAreaChange(() => { let layoutManager: LayoutManager = this.controller.getLayoutManager(); this.lineCount = layoutManager.getLineCount(); + if (layoutManager.getLineCount() === 2) { + this.lineCount = 2; + } }) .direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr) .maxFontScale(1) + .id('cardDescription') } @Builder @@ -443,6 +456,7 @@ export struct ContentFormCard { left: this.isMirrorLanguageType ? 0 : (this.formStyle.thumbMarginLeft as number * this.cardScale), top: this.formStyle.titleFontMarginTop * this.cardScale }) + .id('cardThumbImage') } } .thumbStyle() @@ -483,6 +497,7 @@ export struct ContentFormCard { left: this.isMirrorLanguageType ? 0 : (this.formStyle.thumbMarginLeft as number * this.cardScale), right: this.isMirrorLanguageType ? (this.formStyle.thumbMarginLeft as number * this.cardScale) : 0 }) + .id('cardThumbImage') } } .margin({ top: this.formStyle.descriptionMarginTop * this.cardScale }) @@ -517,11 +532,11 @@ export struct ContentFormCard { .shadow(ShadowStyle.OUTER_DEFAULT_SM) .width(this.cardWidth) .onClick(() => { + this.handleOnClick(); if (!this.contentFormData?.linkUri) { console.warn(`${TAG}, linkUri is null`); return; } - this.handleOnClick(); try { let context = getContext(this) as common.UIAbilityContext; context.openLink(this.contentFormData?.linkUri, { appLinkingOnly: false, parameters: {} }); @@ -609,7 +624,7 @@ export struct ContentFormCard { getTextBackground(text: string | undefined): string { if (text && text.length > 0) { - return CARD_BACKGROUND; + return TRANSLATE_BACKGROUND; } return DEFAULT_FONT_BACKGROUND; } @@ -655,6 +670,6 @@ export struct ContentFormCard { getDescriptionFontSize(): number { return this.lineCount === 1 ? (this.formStyle.maxDescriptionFontSize ? this.formStyle.maxDescriptionFontSize : - this.formStyle.descriptionFontSize) : (this.formStyle.descriptionFontSize * this.cardScale); + this.formStyle.descriptionFontSize) : this.formStyle.descriptionFontSize; } } \ No newline at end of file diff --git a/udmf/interfaces/components/udmfcomponents.cpp b/udmf/interfaces/components/udmfcomponents.cpp index d4897a019e0183c411b67a730441fb81b416442b..760b879c739fe706578979c0e8d03a1f5383bce1 100644 --- a/udmf/interfaces/components/udmfcomponents.cpp +++ b/udmf/interfaces/components/udmfcomponents.cpp @@ -20,7 +20,8 @@ extern const char _binary_udmfcomponents_abc_start[]; extern const char _binary_udmfcomponents_abc_end[]; -extern "C" __attribute__((visibility("default"))) void NAPI_data_udmfComponents_GetABCCode(const char **buf, int *buflen) +extern "C" __attribute__((visibility("default"))) void NAPI_data_UdmfComponents_GetABCCode(const char **buf, + int *buflen) { if (buf != nullptr) { *buf = _binary_udmfcomponents_abc_start; @@ -33,13 +34,13 @@ extern "C" __attribute__((visibility("default"))) void NAPI_data_udmfComponents_ extern "C" __attribute__((constructor)) void UdmfComponentsRegisterModule(void) { - static napi_module udmfComponentsModule = { + static napi_module UdmfComponentsModule = { .nm_version = 1, .nm_flags = 0, .nm_filename = nullptr, - .nm_modname = "data.udmfComponents", + .nm_modname = "data.UdmfComponents", .nm_priv = ((void *)0), .reserved = { 0 }, }; - napi_module_register(&udmfComponentsModule); + napi_module_register(&UdmfComponentsModule); } \ No newline at end of file diff --git a/udmf/interfaces/innerkits/BUILD.gn b/udmf/interfaces/innerkits/BUILD.gn index 1e69192a3895ffee01aa70ba8a8a143f2194e523..d1a4824b7d85e6df0c2196bf1b6a5fa587082671 100644 --- a/udmf/interfaces/innerkits/BUILD.gn +++ b/udmf/interfaces/innerkits/BUILD.gn @@ -18,6 +18,7 @@ config("udmf_client_config") { "${udmf_interfaces_path}/innerkits/client", "${udmf_interfaces_path}/innerkits/common", "${udmf_interfaces_path}/innerkits/data", + "${udmf_interfaces_path}/innerkits/dynamic", "${udmf_interfaces_path}/innerkits/convert", "${udmf_interfaces_path}/ndk/data", "${udmf_framework_path}/common", @@ -26,15 +27,6 @@ config("udmf_client_config") { "${udmf_framework_path}/innerkitsimpl/service", "${udmf_framework_path}/innerkitsimpl/convert", "${udmf_framework_path}/ndkimpl/data", - "${kv_store_path}/frameworks/common", - "//third_party/libuv/include", - "//third_party/node/src", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/src", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/interfaces/innerkits/distributeddata/include", - "${file_service_path}/interfaces/common/include", - "${file_service_path}/interfaces/innerkits/native/file_uri/include", ] } @@ -52,6 +44,7 @@ ohos_shared_library("udmf_client") { "${udmf_framework_path}/common/tlv_object.cpp", "${udmf_framework_path}/common/tlv_util.cpp", "${udmf_framework_path}/common/udmf_copy_file.cpp", + "${udmf_framework_path}/common/udmf_executor.cpp", "${udmf_framework_path}/common/udmf_radar_reporter.cpp", "${udmf_framework_path}/common/udmf_types_util.cpp", "${udmf_framework_path}/common/udmf_utils.cpp", @@ -80,7 +73,9 @@ ohos_shared_library("udmf_client") { "${udmf_framework_path}/innerkitsimpl/data/unified_html_record_process.cpp", "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", "${udmf_framework_path}/innerkitsimpl/data/video.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", "${udmf_framework_path}/innerkitsimpl/service/progress_callback.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_notifier_stub.cpp", "${udmf_framework_path}/innerkitsimpl/service/udmf_service_client.cpp", "${udmf_framework_path}/innerkitsimpl/service/udmf_service_proxy.cpp", ] @@ -102,9 +97,9 @@ ohos_shared_library("udmf_client") { "hisysevent:libhisysevent", "hitrace:hitrace_meter", "hitrace:libhitracechain", - "image_framework:image_native", "ipc:ipc_core", "kv_store:distributeddata_mgr", + "libuv:uv", "samgr:samgr_proxy", ] @@ -149,7 +144,6 @@ ohos_shared_library("utd_client") { "${udmf_framework_path}/common/custom_utd_json_parser.cpp", "${udmf_framework_path}/common/custom_utd_store.cpp", "${udmf_framework_path}/common/graph.cpp", - "${udmf_framework_path}/common/udmf_utils.cpp", "${udmf_framework_path}/common/utd_cfgs_checker.cpp", "${udmf_framework_path}/common/utd_graph.cpp", "${udmf_framework_path}/innerkitsimpl/client/utd_client.cpp", @@ -187,3 +181,35 @@ ohos_shared_library("utd_client") { external_deps += [ "selinux_adapter:librestorecon" ] } } + +ohos_shared_library("pixelmap_wrapper") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + + include_dirs = [ + "${udmf_interfaces_path}/innerkits/dynamic", + "${udmf_framework_path}/common", + ] + sources = [ + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_wrapper.cpp", + ] + + defines = [ "API_EXPORT=__attribute__((visibility (\"default\")))" ] + + deps = [] + + external_deps = [ + "image_framework:image_native", + "ipc:ipc_single", + "hilog:libhilog", + ] + + relative_install_dir = "platformsdk" + innerapi_tags = [ "platformsdk" ] + part_name = "udmf" + subsystem_name = "distributeddatamgr" +} diff --git a/udmf/interfaces/innerkits/aipcore/BUILD.gn b/udmf/interfaces/innerkits/aipcore/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..75cfe6369a77c90290befe319df36e0e2d2a6cd0 --- /dev/null +++ b/udmf/interfaces/innerkits/aipcore/BUILD.gn @@ -0,0 +1,35 @@ +# Copyright (c) 2025 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/udmf/udmf.gni") + +config("aip_core_manager_config") { + visibility = [ ":*" ] + include_dirs = [ "${udmf_interfaces_path}/innerkits/aipcore" ] +} + +ohos_static_library("aip_core_mgr_static") { + branch_protector_ret = "pac_ret" + sanitize = { + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + cflags = [ "-Wno-c99-designator" ] + public_configs = [ ":aip_core_manager_config" ] + + subsystem_name = "distributeddatamgr" + part_name = "udmf" +} diff --git a/udmf/interfaces/jskits/intelligence/i_aip_core_manager.h b/udmf/interfaces/innerkits/aipcore/i_aip_core_manager.h similarity index 84% rename from udmf/interfaces/jskits/intelligence/i_aip_core_manager.h rename to udmf/interfaces/innerkits/aipcore/i_aip_core_manager.h index 5770829e4a2429bb2bba53159972bcf0ac252790..a91b7dbc89f4f4d78e3233274f82510fbf885fe1 100644 --- a/udmf/interfaces/jskits/intelligence/i_aip_core_manager.h +++ b/udmf/interfaces/innerkits/aipcore/i_aip_core_manager.h @@ -15,10 +15,13 @@ #ifndef I_AIP_CORE_MANAGER_H #define I_AIP_CORE_MANAGER_H -#include <stdint.h> +#include <cstdint> +#include <functional> +#include <map> +#include <memory> #include <string> +#include <variant> #include <vector> -#include <map> namespace OHOS { namespace DataIntelligence { @@ -60,6 +63,7 @@ struct ContextParam { std::string bundleName; std::string moduleName; std::string baseDir; + std::string cacheDir; int32_t area; bool isSystemApp = false; bool isStageMode = true; @@ -248,14 +252,52 @@ enum TsSimilarityLevel { HIGH }; +struct OptionStruct { + bool answerWithRetrievalItem; +}; + +struct AnswerStruct { + std::string chunk; + std::vector<ItemInfoStruct> data; +}; + +struct StreamStruct { + bool isFinished; + AnswerStruct answer; +}; + +enum TsLLMRequestStatus { + LLM_SUCCESS = 0, + LLM_ERROR, + LLM_LOAD_FAILED, + LLM_TIMEOUT, + LLM_BUSY, +}; +struct LLMStreamAnswer { + bool isFinished; + std::string chunk; +}; + +typedef std::function<void(const LLMStreamAnswer &)> LLMStreamCallback; + +class IChatLLM { +public: + IChatLLM() = default; + virtual ~IChatLLM() = default; + virtual TsLLMRequestStatus StreamChat(const std::string &query, const LLMStreamCallback &streamCallback); +}; + +struct ConfigStruct { + std::shared_ptr<IChatLLM> chatLLM; + RetrievalConfigStruct retriever; + RetrievalConditionStruct condition; +}; + class IAipCoreManager { public: IAipCoreManager() = default; virtual ~IAipCoreManager() = default; - virtual int32_t InitRetriever(const RetrievalConfigStruct& retrievalConfig) = 0; - virtual int32_t Retrieve(const std::string query, const RetrievalConditionStruct &condition, - RetrievalResponseStruct &retrievalResponse) = 0; virtual int32_t InitTextModel(const ModelConfigData &config) = 0; virtual int32_t InitImageModel(const ModelConfigData &config) = 0; virtual int32_t LoadTextModel() = 0; @@ -267,6 +309,14 @@ public: virtual int32_t ReleaseImageModel() = 0; virtual int32_t GetImageEmbedding(std::string uri, std::vector<float> &results) = 0; virtual int32_t SplitText(std::string text, int32_t size, float overlap, std::vector<std::string> &results) = 0; + + virtual int32_t CreateRAGSession(const ContextParam &contex, const ConfigStruct &config) = 0; + virtual int32_t RAGSessionStreamRun(const std::string &question, const OptionStruct &option, + std::function<void(const StreamStruct&, int32_t)> callback) = 0; + virtual int32_t ReleaseRAGSession() = 0; + virtual int32_t RAGSessionRun(const std::string &query, const OptionStruct &runOption, AnswerStruct &answer) = 0; + + virtual bool CheckDeviceType() = 0; }; struct AipCoreManagerHandle { diff --git a/udmf/interfaces/innerkits/client/udmf_async_client.h b/udmf/interfaces/innerkits/client/udmf_async_client.h index b997be0967b76b02c486a922de869cc78915d9d3..6223f0d14be6bcee19fab69747a3e7713a5f2036 100644 --- a/udmf/interfaces/innerkits/client/udmf_async_client.h +++ b/udmf/interfaces/innerkits/client/udmf_async_client.h @@ -21,11 +21,13 @@ namespace OHOS::UDMF { class UdmfAsyncClient { public: + using UdmfTask = std::function<void()>; friend class UdmfCopyFile; static UdmfAsyncClient API_EXPORT &GetInstance(); Status API_EXPORT StartAsyncDataRetrieval(const GetDataParams &params); Status API_EXPORT Cancel(std::string businessUdKey); Status CancelOnSingleTask(); + void PushTaskToExecutor(UdmfTask task); private: UdmfAsyncClient(); ~UdmfAsyncClient() = default; @@ -49,11 +51,9 @@ private: Status Clear(const std::string &businessUdKey); Status ProcessUnifiedData(std::unique_ptr<AsyncHelper> &asyncHelper); bool IsParamValid(const GetDataParams &params); + uint64_t GetCurrentTimeMillis(); -#ifndef IOS_PLATFORM - ExecutorPool executor_; -#endif - std::map<std::string, std::unique_ptr<AsyncHelper>> asyncHelperMap_; + std::map<std::string, std::unique_ptr<AsyncHelper>> asyncHelperMap_ {}; std::mutex mutex_; }; } // namespace diff --git a/udmf/interfaces/innerkits/client/udmf_client.h b/udmf/interfaces/innerkits/client/udmf_client.h index b1b20bd20129e3096c3891a8190e55a73c89d10e..26dd2c647041771099092b26b175d4cacb9fcc64 100644 --- a/udmf/interfaces/innerkits/client/udmf_client.h +++ b/udmf/interfaces/innerkits/client/udmf_client.h @@ -47,6 +47,13 @@ public: Status API_EXPORT RemoveAppShareOption(const std::string &intention); Status API_EXPORT GetAppShareOption(const std::string &intention, enum ShareOptions &shareOption); Status GetDataFromCache(const QueryOption &query, UnifiedData &unifiedData); + Status API_EXPORT GetParentType(Summary &oldSummary, Summary &newSummary); + Status API_EXPORT SetDelayInfo(const DataLoadParams &dataLoadParams, std::string &key); + Status API_EXPORT PushDelayData(const std::string &key, UnifiedData &unifiedData); + Status GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr<IRemoteObject> iUdmfNotifier, std::shared_ptr<UnifiedData> unifiedData); + std::string API_EXPORT GetBundleNameByUdKey(const std::string &key); + bool API_EXPORT IsAppropriateType(const Summary &summary, const std::vector<std::string> &allowTypes); private: UdmfClient() = default; @@ -54,8 +61,10 @@ private: UdmfClient(const UdmfClient &obj) = delete; UdmfClient &operator=(const UdmfClient &obj) = delete; std::string GetSelfBundleName(); + void ProcessDragIfInApp(UnifiedData &unifiedData, std::string &intentionDrag, std::string &key); + bool CheckFileUtdType(const Summary &summary, const std::vector<std::string> &allowTypes); - ConcurrentMap<std::string, UnifiedData> dataCache_; + ConcurrentMap<std::string, UnifiedData> dataCache_ {}; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/client/utd_client.h b/udmf/interfaces/innerkits/client/utd_client.h index 71a7515c3121975678cd0d6004d463465b5732e6..0d063edf577d97da30bb0dcbc7311b7a5f1d2cb3 100644 --- a/udmf/interfaces/innerkits/client/utd_client.h +++ b/udmf/interfaces/innerkits/client/utd_client.h @@ -20,9 +20,9 @@ #include <string> #include <vector> #include <map> +#include <mutex> #include "utd_common.h" #include "preset_type_descriptors.h" -#include "preset_type_descriptors.h" #include "flexible_type.h" #include "type_descriptor.h" #include "error_code.h" @@ -52,19 +52,26 @@ private: ~UtdClient(); UtdClient(const UtdClient &obj) = delete; UtdClient &operator=(const UtdClient &obj) = delete; - std::string Anonymous(const std::string &fileExtension); bool Init(); bool IsHapTokenType(); Status GetCurrentActiveUserId(int32_t& userId); bool IsValidFileExtension(const std::string &fileExtension); bool IsValidMimeType(const std::string &mimeType); Status GetFlexibleTypeDescriptor(const std::string &typeId, std::shared_ptr<TypeDescriptor> &descriptor); - std::string GetTypeIdFromCfg(const std::string &mimeType); + std::string GetTypeIdFromCfg(const std::string &mimeType, const std::string &belongsTo = DEFAULT_TYPE_ID); std::vector<std::string> GetTypeIdsFromCfg(const std::string &mimeType); void UpdateGraph(const std::vector<TypeDescriptorCfg> &customTyepCfgs); + bool TryReloadCustomUtd(); + bool IsBelongingType(const std::string &belongsTo, const std::string &typeId) const; - std::vector<TypeDescriptorCfg> descriptorCfgs_; + std::vector<TypeDescriptorCfg> descriptorCfgs_ {}; std::shared_mutex utdMutex_; + + std::mutex customUtdMutex_; + UtdFileInfo utdFileInfo_; + int64_t lastLoadTime_ {0}; + + std::mutex updateUtdMutex_; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/common/async_task_params.h b/udmf/interfaces/innerkits/common/async_task_params.h index a5ac1c308c6de13848bd496116a6b5ed9b14945b..84255cb0b8838c739e2ab2bc0979f4cbef6cc3c7 100644 --- a/udmf/interfaces/innerkits/common/async_task_params.h +++ b/udmf/interfaces/innerkits/common/async_task_params.h @@ -20,9 +20,6 @@ #include <mutex> #include <string> -#ifndef IOS_PLATFORM -#include "executor_pool.h" -#endif #include "progress_queue.h" #include "unified_types.h" #include "unified_data.h" @@ -47,6 +44,7 @@ public: ProgressListener progressListener; std::string destUri; QueryOption query; + DataLoadInfo acceptableInfo; }; struct AsyncHelper { @@ -54,9 +52,9 @@ struct AsyncHelper { int32_t lastProgress = 0; ProgressIndicator progressIndicator; #ifndef IOS_PLATFORM - ExecutorPool::TaskId invokeHapTask = ExecutorPool::INVALID_TASK_ID; - ExecutorPool::TaskId getDataTask = ExecutorPool::INVALID_TASK_ID; - ExecutorPool::TaskId progressTask = ExecutorPool::INVALID_TASK_ID; + uint64_t invokeHapTask = 0; + uint64_t getDataTask = 0; + uint64_t progressTask = 0; #endif ProgressListener progressListener; FileConflictOptions fileConflictOptions; @@ -66,6 +64,7 @@ struct AsyncHelper { std::string destUri; std::shared_ptr<UnifiedData> data = std::make_shared<UnifiedData>(); ProgressQueue progressQueue; + DataLoadInfo acceptableInfo; }; enum ListenerStatus: int32_t { diff --git a/udmf/interfaces/innerkits/common/error_code.h b/udmf/interfaces/innerkits/common/error_code.h index 6d2e9b0f0cb175d7209ae4ade5021a0892859368..bdc8c58c4fbbcf6c48e5e17ac58ee01ff6e2eec0 100644 --- a/udmf/interfaces/innerkits/common/error_code.h +++ b/udmf/interfaces/innerkits/common/error_code.h @@ -17,17 +17,26 @@ #define UDMF_ERROR_CODE_H #include <cstdint> -#include <errors.h> -#include <map> #include <string> #include <unordered_map> namespace OHOS { namespace UDMF { +using ErrCode = int; +constexpr int ERR_OK = 0; +constexpr int SUBSYS_DISTRIBUTEDDATAMNG = 13; + enum UdmfModule { UDMF_MODULE_SERVICE_ID = 0x07, }; +constexpr ErrCode ErrCodeOffset(unsigned int subsystem, unsigned int module = 0) +{ + constexpr int SUBSYTSTEM_BIT_NUM = 21; + constexpr int MODULE_BIT_NUM = 16; + return (subsystem << SUBSYTSTEM_BIT_NUM) | (module << MODULE_BIT_NUM); +} + // UDMF error offset, used only in this file. constexpr ErrCode UDMF_ERR_OFFSET = ErrCodeOffset(SUBSYS_DISTRIBUTEDDATAMNG, UDMF_MODULE_SERVICE_ID); @@ -48,6 +57,8 @@ enum Status : int32_t { E_COPY_FILE_FAILED, E_IDEMPOTENT_ERROR, E_COPY_CANCELED, + E_DB_CORRUPTED, + E_JSON_CONVERT_FAILED, E_BUTT, }; diff --git a/udmf/interfaces/innerkits/common/progress_queue.h b/udmf/interfaces/innerkits/common/progress_queue.h index 506630f01927eedcfd996e062afbcc2acbefed5d..995d75952c3d1c4d8c9c90dfe3e8be94d26a4cf4 100644 --- a/udmf/interfaces/innerkits/common/progress_queue.h +++ b/udmf/interfaces/innerkits/common/progress_queue.h @@ -39,7 +39,7 @@ public: private: bool cancelFlag_ = false; bool clearableFlag_ = true; - std::queue<ProgressInfo> queue_; + std::queue<ProgressInfo> queue_ {}; mutable std::mutex mutex_; }; diff --git a/udmf/interfaces/innerkits/common/unified_key.h b/udmf/interfaces/innerkits/common/unified_key.h index dcff9fb996f457035c1762e1b54b4f0f600a72f3..abef9183bab7e16d49b54030592394794e372f0f 100644 --- a/udmf/interfaces/innerkits/common/unified_key.h +++ b/udmf/interfaces/innerkits/common/unified_key.h @@ -31,10 +31,12 @@ struct API_EXPORT UnifiedKey { std::string bundleName; std::string groupId; std::string GetUnifiedKey(); - std::string GetPropertyKey() const; + std::string GetKeyCommonPrefix() const; bool IsValid(); void PreliminaryWork(); - bool CheckCharacter(std::string data, std::bitset<MAX_BIT_SIZE> rule); + bool CheckCharacter(const std::string_view& data, const std::bitset<MAX_BIT_SIZE> &rule); + bool ExtractAndValidateSegment(std::string_view& data, std::string& field, + const std::bitset<MAX_BIT_SIZE>& rule, const std::string& name); }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/common/unified_meta.h b/udmf/interfaces/innerkits/common/unified_meta.h index 6c7e692e97946593f05b5869bf62f21856ac7c96..3b185f08b6c8130a684be834fa8f18ff0bd97afc 100644 --- a/udmf/interfaces/innerkits/common/unified_meta.h +++ b/udmf/interfaces/innerkits/common/unified_meta.h @@ -28,6 +28,7 @@ #include "pixel_map.h" #include "string_ex.h" #include "want.h" +#include "unified_key.h" namespace OHOS { namespace UDMF { @@ -535,13 +536,14 @@ enum UDType : int32_t { OPENHARMONY_GOBRUSH, OPENHARMONY_GOBRUSHES, OPENHARMONY_GOCOLOR, + OPENHARMONY_DLP, UD_BUTT }; struct UtdType { - int32_t UtdEnum; - const char *UtdEnumName; - const char *UtdId; + int32_t UtdEnum {0}; + const char *UtdEnumName {nullptr}; + const char *UtdId {nullptr}; }; namespace UtdUtils { @@ -563,33 +565,77 @@ enum Intention : int32_t { UD_INTENTION_BASE = 0, UD_INTENTION_DRAG, UD_INTENTION_DATA_HUB, + UD_INTENTION_SYSTEM_SHARE, + UD_INTENTION_PICKER, + UD_INTENTION_MENU, UD_INTENTION_BUTT, }; -static const std::unordered_map<int32_t, std::string> UD_INTENTION_MAP { +static const std::map<int32_t, std::string> UD_INTENTION_MAP { { UD_INTENTION_DRAG, "drag" }, { UD_INTENTION_DATA_HUB, "DataHub" }, + { UD_INTENTION_SYSTEM_SHARE, "SystemShare" }, + { UD_INTENTION_PICKER, "Picker" }, + { UD_INTENTION_MENU, "Menu" }, }; -static const std::unordered_map<int32_t, std::string> UD_SYSTEM_INTENTION_MAP { +static const std::map<int32_t, std::string> UD_SYSTEM_INTENTION_MAP { { UD_INTENTION_DRAG, "Drag" }, }; -static const std::unordered_map<int32_t, std::string> JS_UD_INTENTION_NAME_MAP { +static const std::map<int32_t, std::string> JS_UD_INTENTION_NAME_MAP { { UD_INTENTION_DATA_HUB, "DATA_HUB" }, { UD_INTENTION_DRAG, "DRAG" }, + { UD_INTENTION_SYSTEM_SHARE, "SYSTEM_SHARE" }, + { UD_INTENTION_PICKER, "PICKER" }, + { UD_INTENTION_MENU, "MENU" }, + +}; + +enum Visibility : int32_t { + VISIBILITY_ALL = 0, + VISIBILITY_OWN_PROCESS, + VISIBILITY_BUTT, +}; + +static const std::map<int32_t, std::string> UD_VISIBILITY_MAP { + { VISIBILITY_ALL, "ALL" }, + { VISIBILITY_OWN_PROCESS, "OWN_PROCESS" }, +}; + +enum Uds_Type : int32_t { + UDS_PLAIN_TEXT = 0, + UDS_HYPERLINK, + UDS_HTML, + UDS_APP_ITEM, + UDS_CONTENT_FORM, + UDS_FORM, + UDS_FILE_URI, + UDS_PIXEL_MAP, + UDS_OTHER +}; + +static const std::map<std::string, Uds_Type> UDS_UTD_TYPE_MAP { + { "general.plain-text", Uds_Type::UDS_PLAIN_TEXT }, + { "general.hyperlink", Uds_Type::UDS_HYPERLINK }, + { "general.html", Uds_Type::UDS_HTML }, + { "openharmony.app-item", Uds_Type::UDS_APP_ITEM }, + { "general.content-form", Uds_Type::UDS_CONTENT_FORM }, + { "openharmony.form", Uds_Type::UDS_FORM }, + { "general.file-uri", Uds_Type::UDS_FILE_URI }, + { "openharmony.pixel-map", Uds_Type::UDS_PIXEL_MAP }, }; enum ShareOptions : int32_t { - IN_APP, + IN_APP = 0, CROSS_APP, CROSS_DEVICE, SHARE_OPTIONS_BUTT, }; struct AppShareOption { - int32_t enumNum; - const char *enumStr; + int32_t enumNum {0}; + const char *enumStr {nullptr}; }; namespace ShareOptionsUtil { @@ -606,8 +652,16 @@ public: static size_t GetDetailsSize(UDDetails &details); static bool API_EXPORT IsPersist(const Intention &intention); static bool API_EXPORT IsPersist(const std::string &intention); + static bool API_EXPORT IsPersist(const int32_t &visibility); static Intention API_EXPORT GetIntentionByString(const std::string &intention); - static bool API_EXPORT IsValidOptions(const std::string &key, std::string &intention); + static bool API_EXPORT IsValidOptions(UnifiedKey &key, const std::string &intention); + static bool API_EXPORT IsValidOptions(UnifiedKey &key, const std::string &intention, + const std::string &validIntention); + static bool IsFileMangerIntention(const std::string &intention); + static std::string FindIntentionMap(const Intention &queryintention); + static bool IsValidOptionsNonDrag(UnifiedKey &key, const std::string &intention); + static std::string GetBelongsToFileType(const std::string &utdId); + static bool IsFilterFileType(const std::string &type); }; struct Object; @@ -626,7 +680,7 @@ struct Object { return false; } - std::map<std::string, ValueType> value_; + std::map<std::string, ValueType> value_ {}; }; namespace ObjectUtils { diff --git a/udmf/interfaces/innerkits/common/unified_types.h b/udmf/interfaces/innerkits/common/unified_types.h index 18ddc287ef29c5ac9e6b062991586a8c16e68f6f..58329b76b73c8e9e2ed6f61bc60e650789839f17 100644 --- a/udmf/interfaces/innerkits/common/unified_types.h +++ b/udmf/interfaces/innerkits/common/unified_types.h @@ -33,20 +33,25 @@ enum DataStatus : int32_t { }; struct Summary { - std::map<std::string, int64_t> summary; - int64_t totalSize; + std::map<std::string, int64_t> summary {}; + std::map<std::string, int64_t> specificSummary {}; + std::map<std::string, std::vector<int32_t>> summaryFormat {}; + // If version value is 1, it means it contains the format variable; + // otherwise(not set or 0), it means it does not contain. + int32_t version {1}; + int64_t totalSize {0}; }; struct Privilege { - uint32_t tokenId; + uint32_t tokenId {0}; std::string readPermission; std::string writePermission; }; struct Runtime { UnifiedKey key; - bool isPrivate {}; - std::vector<Privilege> privileges; + bool isPrivate {false}; + std::vector<Privilege> privileges{}; // time when the data is created time_t createTime {}; // name of the package for creating data @@ -54,16 +59,18 @@ struct Runtime { // current data status DataStatus dataStatus { WORKING }; // current data version - std::int32_t dataVersion {}; + std::int32_t dataVersion {0}; // time when the data is last modified time_t lastModifiedTime {}; // time when data is written to the udmf std::string createPackage; // device ID of the data source std::string deviceId; - std::uint32_t recordTotalNum {}; - uint32_t tokenId; + std::uint32_t recordTotalNum {0}; + uint32_t tokenId {0}; std::string sdkVersion; + Visibility visibility {}; + std::string appId; }; /* @@ -72,6 +79,7 @@ struct Runtime { struct CustomOption { Intention intention {}; uint32_t tokenId {}; + Visibility visibility {}; }; /* @@ -80,7 +88,7 @@ struct CustomOption { struct QueryOption { std::string key; Intention intention {}; - uint32_t tokenId {}; + uint32_t tokenId {0}; }; enum AsyncTaskStatus : uint32_t { @@ -103,8 +111,8 @@ struct AsyncProcessInfo { }; struct ProgressInfo { - int32_t progress = 0; - int32_t progressStatus; + int32_t progress {0}; + int32_t progressStatus {0}; Status errorCode; std::string srcDevName; }; @@ -115,6 +123,26 @@ struct UriInfo { std::string dfsUri; uint32_t position; }; + +struct DataLoadInfo { + std::string sequenceKey; + std::set<std::string> types {}; + uint32_t recordCount {0}; +}; + +using LoadHandler = std::function<void(const std::string &udKey, const DataLoadInfo &dataLoadInfo)>; + +struct DataLoadParams { + LoadHandler loadHandler; + DataLoadInfo dataLoadInfo; +}; + +struct DelayGetDataInfo { + uint32_t tokenId {0}; +#ifndef CROSS_PLATFORM + sptr<IRemoteObject> dataCallback; +#endif +}; } // namespace UDMF } // namespace OHOS #endif // UDMF_UNIFIED_TYPES_H \ No newline at end of file diff --git a/udmf/interfaces/innerkits/convert/data_params_conversion.h b/udmf/interfaces/innerkits/convert/data_params_conversion.h index 3427c07db636f1c401d4082b1c99e42744393858..fedf27c9c47870939788a081ecbe08828781c172 100644 --- a/udmf/interfaces/innerkits/convert/data_params_conversion.h +++ b/udmf/interfaces/innerkits/convert/data_params_conversion.h @@ -24,6 +24,8 @@ class DataParamsConversion { public: static Status API_EXPORT GetInnerDataParams(OH_UdmfGetDataParams &ndkDataParams, QueryOption &query, GetDataParams &dataParams); + static Status API_EXPORT GetDataLoaderParams(const OH_UdmfDataLoadParams &ndkDataParams, + DataLoadParams &dataLoadParams); }; } diff --git a/udmf/interfaces/innerkits/convert/ndk_data_conversion.h b/udmf/interfaces/innerkits/convert/ndk_data_conversion.h index 9be036038d542cb938aeb644eace0eb5dab5c589..931a7ff9f41f7f8999bfe7699390311e60f67f6a 100644 --- a/udmf/interfaces/innerkits/convert/ndk_data_conversion.h +++ b/udmf/interfaces/innerkits/convert/ndk_data_conversion.h @@ -22,11 +22,13 @@ #include "error_code.h" namespace OHOS::UDMF { - class NdkDataConversion { - public: - static Status API_EXPORT GetNativeUnifiedData(OH_UdmfData* ndkData, std::shared_ptr<UnifiedData>& data); - static Status API_EXPORT GetNdkUnifiedData(std::shared_ptr<UnifiedData> data, OH_UdmfData* ndkData); - }; +class NdkDataConversion { +public: + static Status API_EXPORT GetNativeUnifiedData(OH_UdmfData* ndkData, std::shared_ptr<UnifiedData>& data); + static Status API_EXPORT GetNdkUnifiedData(std::shared_ptr<UnifiedData> data, OH_UdmfData* ndkData); + static char** StrVectorToTypesArray(const std::vector<std::string>& strVector); + static void DestroyStringArray(char**& bufArray, unsigned int& count); +}; } #endif // UDMF_DATA_CONVERSION_H \ No newline at end of file diff --git a/udmf/interfaces/innerkits/data/application_defined_record.h b/udmf/interfaces/innerkits/data/application_defined_record.h index 6d0bf0308b43a0d9b7ab9fdfc06aa165123cabec..d0d83f65060fa7425d402ebff0eb6cb70c67b2ba 100644 --- a/udmf/interfaces/innerkits/data/application_defined_record.h +++ b/udmf/interfaces/innerkits/data/application_defined_record.h @@ -38,7 +38,7 @@ public: void InitObject() override; protected: std::string applicationDefinedType; - std::vector<uint8_t> rawData_; + std::vector<uint8_t> rawData_ {}; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/audio.h b/udmf/interfaces/innerkits/data/audio.h index 5dff5eaa8cba5b6a80941f8bda73cedd5ccd5065..84aec6359bccfb3c576e45fe495b55bb25e5e6e4 100644 --- a/udmf/interfaces/innerkits/data/audio.h +++ b/udmf/interfaces/innerkits/data/audio.h @@ -25,6 +25,7 @@ public: API_EXPORT Audio(); explicit API_EXPORT Audio(const std::string &uri); API_EXPORT Audio(UDType type, ValueType value); + void InitObject() override; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/file.h b/udmf/interfaces/innerkits/data/file.h index f533990b82cbd1f547811ab540a0049c4e2ad1d6..5b72fce8971912265f11fc3de67a80b6109e024e 100644 --- a/udmf/interfaces/innerkits/data/file.h +++ b/udmf/interfaces/innerkits/data/file.h @@ -25,7 +25,6 @@ public: API_EXPORT File(); explicit API_EXPORT File(const std::string &uri); API_EXPORT File(UDType type, ValueType value); - void API_EXPORT SetType(const UDType &type); int64_t API_EXPORT GetSize() override; std::string API_EXPORT GetUri() const; @@ -41,7 +40,7 @@ public: protected: std::string oriUri_; std::string remoteUri_; - UDDetails details_; + UDDetails details_ {}; std::string fileType_; }; } // namespace UDMF diff --git a/udmf/interfaces/innerkits/data/flexible_type.h b/udmf/interfaces/innerkits/data/flexible_type.h index b5b9303f9a577cddc3bc6fa431c5c7a5383aaef5..b5bfd8e14ab4b7e0ffc0e72bb7998d2962a16106 100644 --- a/udmf/interfaces/innerkits/data/flexible_type.h +++ b/udmf/interfaces/innerkits/data/flexible_type.h @@ -36,6 +36,8 @@ public: const std::string &belongsTo); static constexpr size_t MAX_TYPE_SIZE = 128; static constexpr size_t ATTRIBUTE_PAIR_SIZE = 2; +private: + static std::vector<std::string> StrSplit(const std::string &str, const std::string &delimiter); }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/folder.h b/udmf/interfaces/innerkits/data/folder.h index d8df86043161a1159fa0790d3100afb5b7f4d78b..9ff7fb34f285ccddf9d0b740324b51dedb446c1f 100644 --- a/udmf/interfaces/innerkits/data/folder.h +++ b/udmf/interfaces/innerkits/data/folder.h @@ -25,6 +25,7 @@ public: API_EXPORT Folder(); explicit API_EXPORT Folder(const std::string &uri); API_EXPORT Folder(UDType type, ValueType value); + void InitObject() override; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/html.h b/udmf/interfaces/innerkits/data/html.h index f3bd188c07e700dbe4978319772f135f7f0bdcba..4f2b995a6d0b13826dc617069381904e98e2210e 100644 --- a/udmf/interfaces/innerkits/data/html.h +++ b/udmf/interfaces/innerkits/data/html.h @@ -35,7 +35,6 @@ public: void API_EXPORT SetPlainContent(const std::string &htmlContent); void InitObject() override; - static bool CheckValue(const ValueType &value); private: std::string htmlContent_; std::string plainContent_; diff --git a/udmf/interfaces/innerkits/data/image.h b/udmf/interfaces/innerkits/data/image.h index d76525d4d744ac117817c8b8443207189c686323..f8adb61088492bc227d364f6985722a4a5eeabaa 100644 --- a/udmf/interfaces/innerkits/data/image.h +++ b/udmf/interfaces/innerkits/data/image.h @@ -26,6 +26,7 @@ public: API_EXPORT Image(); explicit API_EXPORT Image(const std::string &uri); API_EXPORT Image(UDType type, ValueType value); + void InitObject() override; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/link.h b/udmf/interfaces/innerkits/data/link.h index 79aaaef7b49f9e8a38d661ef5b51056f54b4e128..cd69542ce60930f1a0352356c824ae59377c5466 100644 --- a/udmf/interfaces/innerkits/data/link.h +++ b/udmf/interfaces/innerkits/data/link.h @@ -36,7 +36,6 @@ public: void API_EXPORT SetDescription(const std::string &description); void InitObject() override; - static bool CheckValue(const ValueType &value); private: std::string url_; std::string description_; diff --git a/udmf/interfaces/innerkits/data/plain_text.h b/udmf/interfaces/innerkits/data/plain_text.h index cbfbd4df9e9014ae5c925e7ba6da79559dcd04d7..f13eebe99f2188beb2a9fbde0853da8943eaea63 100644 --- a/udmf/interfaces/innerkits/data/plain_text.h +++ b/udmf/interfaces/innerkits/data/plain_text.h @@ -34,7 +34,6 @@ public: void API_EXPORT SetAbstract(const std::string &abstract); void InitObject() override; - static bool CheckValue(const ValueType &value); private: std::string content_; std::string abstract_; diff --git a/udmf/interfaces/innerkits/data/system_defined_appitem.h b/udmf/interfaces/innerkits/data/system_defined_appitem.h index 61b3dc3546b5486db55dce40ac46566b76ccd1dd..5b8ec87275622131e57e9369e83e8abeac5160fe 100644 --- a/udmf/interfaces/innerkits/data/system_defined_appitem.h +++ b/udmf/interfaces/innerkits/data/system_defined_appitem.h @@ -44,7 +44,6 @@ public: UDDetails API_EXPORT GetItems(); void InitObject() override; - static bool CheckValue(const ValueType &value); private: std::string appId_; std::string appName_; diff --git a/udmf/interfaces/innerkits/data/system_defined_pixelmap.h b/udmf/interfaces/innerkits/data/system_defined_pixelmap.h index b37dc05d8088903e1a30c134fdbe71f62a354865..74d48541182d3f10a858ef58dfa1503cd9d11ab4 100644 --- a/udmf/interfaces/innerkits/data/system_defined_pixelmap.h +++ b/udmf/interfaces/innerkits/data/system_defined_pixelmap.h @@ -33,7 +33,10 @@ public: void InitObject() override; private: - std::vector<uint8_t> rawData_; + std::shared_ptr<Media::PixelMap> GetPixelMapFromRawData(); + void ParseInfoFromPixelMap(std::shared_ptr<OHOS::Media::PixelMap> pixelMap); + + std::vector<uint8_t> rawData_ {}; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/system_defined_record.h b/udmf/interfaces/innerkits/data/system_defined_record.h index 14a6b881e1e1ffe1abcc318735c5e038473c3232..72b0923521153f96fb2f9f2703bd347e2a5ce489 100644 --- a/udmf/interfaces/innerkits/data/system_defined_record.h +++ b/udmf/interfaces/innerkits/data/system_defined_record.h @@ -35,7 +35,7 @@ public: void InitObject() override; protected: - UDDetails details_; + UDDetails details_ {}; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/text.h b/udmf/interfaces/innerkits/data/text.h index ec3a678ef0c19500cabeb67e61f0d0b2721f61d0..2aea3bf534c7b2b1e8c76594b9340c688e26a355 100644 --- a/udmf/interfaces/innerkits/data/text.h +++ b/udmf/interfaces/innerkits/data/text.h @@ -35,7 +35,7 @@ public: void InitObject() override; protected: - UDDetails details_; + UDDetails details_ {}; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/type_descriptor.h b/udmf/interfaces/innerkits/data/type_descriptor.h index 27652dcc48b12377c9c6b289e471aff1834cc0fb..da87ab710890b8844284c990edb62427e09bf8c6 100644 --- a/udmf/interfaces/innerkits/data/type_descriptor.h +++ b/udmf/interfaces/innerkits/data/type_descriptor.h @@ -20,7 +20,6 @@ #include <set> #include <vector> #include <map> -#include <memory> #include "error_code.h" #include "utd_common.h" #include "visibility.h" @@ -50,9 +49,9 @@ private: bool CmpFlexibleTypeLevel(const std::string higherLevelTypeId, bool isFlexibleType); std::string typeId_; - std::vector<std::string> belongingToTypes_; - std::vector<std::string> filenameExtensions_; - std::vector<std::string> mimeTypes_; + std::vector<std::string> belongingToTypes_ {}; + std::vector<std::string> filenameExtensions_ {}; + std::vector<std::string> mimeTypes_ {}; std::string description_; std::string referenceURL_; std::string iconFile_; diff --git a/udmf/interfaces/innerkits/data/unified_data.h b/udmf/interfaces/innerkits/data/unified_data.h index f0f369175dc7d06671461aaa0bc5e70b6133254f..ca59d320a6a862695a34aa8debb7db63ba480b0e 100644 --- a/udmf/interfaces/innerkits/data/unified_data.h +++ b/udmf/interfaces/innerkits/data/unified_data.h @@ -59,7 +59,7 @@ public: void SetChannelName(const std::string &name); std::vector<std::string> GetFileUris() const; bool API_EXPORT IsNeedTransferToEntries() const; - void API_EXPORT TransferToEntries(UnifiedData &data); + void API_EXPORT ConvertRecordsToEntries(); std::string API_EXPORT GetSdkVersion() const; void API_EXPORT SetSdkVersion(const std::string &version); @@ -72,7 +72,7 @@ private: uint32_t recordId_ = 0; std::string channelName_; std::shared_ptr<Runtime> runtime_; - std::vector<std::shared_ptr<UnifiedRecord>> records_; + std::vector<std::shared_ptr<UnifiedRecord>> records_ {}; std::shared_ptr<UnifiedDataProperties> properties_; std::string sdkVersion_; }; diff --git a/udmf/interfaces/innerkits/data/unified_data_helper.h b/udmf/interfaces/innerkits/data/unified_data_helper.h index 1b90cb4ce2fa9ac7cd6a4b4f77ad0fc0f63df624..5d76a3e426813bc563e3331a55766651e4a4cf62 100644 --- a/udmf/interfaces/innerkits/data/unified_data_helper.h +++ b/udmf/interfaces/innerkits/data/unified_data_helper.h @@ -30,13 +30,17 @@ public: static bool Unpack(UnifiedData &data); static void GetSummary(const UnifiedData &data, Summary &summary); static int32_t ProcessBigData(UnifiedData &data, Intention intention, bool isSaInvoke); + static void GetSummaryFromLoadInfo(const DataLoadInfo &dataLoadInfo, Summary &summary); private: static void CreateDirIfNotExist(const std::string& dirPath, const mode_t& mode); static bool SaveUDataToFile(const std::string &dataFile, UnifiedData &data); static bool LoadUDataFromFile(const std::string &dataFile, UnifiedData &data); static void CalRecordSummary(std::map<std::string, ValueType> &entries, Summary &summary); + static void FillSummaryFormat(const std::string &utdId, const std::string &specificType, Summary &summary); static void ProcessTypeId(const ValueType &value, std::string &typeId); static std::string GetRootPath(); + static bool FileClose(std::FILE *file, bool status); + static void UpgradeToParentType(std::string &typeId); private: static std::string rootPath_; diff --git a/udmf/interfaces/innerkits/data/unified_data_properties.h b/udmf/interfaces/innerkits/data/unified_data_properties.h index 565faf125d14d9c0c990604738fd36bf524c11ef..b75fd9033b2cac98019de288cd6cc73649e16155 100644 --- a/udmf/interfaces/innerkits/data/unified_data_properties.h +++ b/udmf/interfaces/innerkits/data/unified_data_properties.h @@ -24,8 +24,8 @@ public: std::string tag; AAFwk::WantParams extras; ShareOptions shareOptions = CROSS_DEVICE; - std::int64_t timestamp; - bool isRemote; + std::int64_t timestamp {0}; + bool isRemote {false}; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/unified_record.h b/udmf/interfaces/innerkits/data/unified_record.h index cbb1347332492ba96aca8e19db722921e23c1750..1d09889d34df85c13ae623fe090067efb461dbf4 100644 --- a/udmf/interfaces/innerkits/data/unified_record.h +++ b/udmf/interfaces/innerkits/data/unified_record.h @@ -52,7 +52,10 @@ public: void API_EXPORT SetUtdId(const std::string &utdId); std::set<std::string> API_EXPORT GetUtdIds() const; + std::set<std::string> API_EXPORT GetUtdIdsWithAddFileType(bool isSpecific) const; std::string API_EXPORT GetUtdId() const; + void API_EXPORT SetUtdId2(const std::string &utdId); + std::string API_EXPORT GetUtdId2() const; bool API_EXPORT HasType(const std::string &utdId) const; void API_EXPORT AddEntry(const std::string &utdId, ValueType &&value); @@ -72,7 +75,6 @@ public: void API_EXPORT SetChannelName(const std::string &channelName); virtual void InitObject(); - bool HasObject(); bool HasFileType(std::string &fileUri) const; void SetFileUri(const std::string &fileUri); @@ -83,14 +85,14 @@ public: protected: UDType dataType_; std::string utdId_; + std::string utdId2_; ValueType value_; - bool hasObject_ = false; private: - void AddFileUriType(std::set<std::string> &utdIds, const std::shared_ptr<Object> &fileUri) const; + void AddFileUriType(std::set<std::string> &utdIds, const std::shared_ptr<Object> &fileUri, bool isSpecific) const; std::string uid_; // unique identifier std::shared_ptr<std::map<std::string, ValueType>> entries_ = std::make_shared<std::map<std::string, ValueType>>(); - std::vector<UriInfo> uris_; + std::vector<UriInfo> uris_ {}; uint32_t dataId_ = 0; uint32_t recordId_ = 0; std::string channelName_; diff --git a/udmf/interfaces/innerkits/data/video.h b/udmf/interfaces/innerkits/data/video.h index a6d623a51bb2a34febfcb48ce0904bd49736813d..fe59e837cb1b62bbb30f1b853e21983caaa9a74f 100644 --- a/udmf/interfaces/innerkits/data/video.h +++ b/udmf/interfaces/innerkits/data/video.h @@ -25,6 +25,7 @@ public: Video(); explicit Video(const std::string &uri); Video(UDType type, ValueType value); + void InitObject() override; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/dynamic/pixelmap_loader.h b/udmf/interfaces/innerkits/dynamic/pixelmap_loader.h new file mode 100644 index 0000000000000000000000000000000000000000..c6c7e9d9283a65ffcabd0487c0cfd37b804d89cb --- /dev/null +++ b/udmf/interfaces/innerkits/dynamic/pixelmap_loader.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025 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 PIXELMAP_LOADER +#define PIXELMAP_LOADER + +#include <functional> +#include <memory> +#include <optional> +#include "pixel_map.h" + +namespace OHOS::UDMF { + +struct PixelMapDetails { + int32_t width = 0; + int32_t height = 0; + int32_t pixelFormat = 0; + int32_t alphaType = 0; + // Use as an input parameter. To avoid copying, pass a reference. + std::optional<std::reference_wrapper<std::vector<uint8_t>>> rawData; + // Use as an output parameter. + std::optional<std::vector<uint8_t>> rawDataResult; +}; + +typedef OHOS::Media::PixelMap *(*LoadDecodeTlv)(const PixelMapDetails); +typedef bool (*LoadEncodeTlv)(const OHOS::Media::PixelMap *, PixelMapDetails *); +typedef OHOS::Media::PixelMap *(*LoadGetPixelMapFromRawData)(const PixelMapDetails); +typedef PixelMapDetails *(*LoadParseInfoFromPixelMap)(OHOS::Media::PixelMap *); + +class PixelMapLoader { +public: + PixelMapLoader(); + + std::shared_ptr<OHOS::Media::PixelMap> DecodeTlv(std::vector<uint8_t> &buff); + bool EncodeTlv(const std::shared_ptr<OHOS::Media::PixelMap> pixelmap, std::vector<uint8_t> &buff); + std::shared_ptr<OHOS::Media::PixelMap> GetPixelMapFromRawData(const PixelMapDetails &details); + std::shared_ptr<PixelMapDetails> ParseInfoFromPixelMap(const std::shared_ptr<OHOS::Media::PixelMap> pixelMap); + +private: + class SoAutoUnloadManager { + public: + static std::shared_ptr<void> GetHandler(); + private: + static std::weak_ptr<void> weakHandler_; + static std::mutex mutex_; + }; + + std::shared_ptr<void> handler_; +}; + +} // namespace OHOS::UDMF + +#endif // PIXELMAP_LOADER \ No newline at end of file diff --git a/udmf/interfaces/innerkits/dynamic/pixelmap_wrapper.h b/udmf/interfaces/innerkits/dynamic/pixelmap_wrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..1e2bce12b08ea4eb0106065497cbeb138c1228e6 --- /dev/null +++ b/udmf/interfaces/innerkits/dynamic/pixelmap_wrapper.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 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 PIXELMAP_WRAPPER +#define PIXELMAP_WRAPPER + +#include "pixel_map.h" +#include "pixelmap_loader.h" + +namespace OHOS::UDMF { +#ifdef __cplusplus +extern "C" { +#endif + +OHOS::Media::PixelMap *DecodeTlv(const PixelMapDetails details); +bool EncodeTlv(const OHOS::Media::PixelMap *pixelMap, PixelMapDetails *details); +OHOS::Media::PixelMap *GetPixelMapFromRawData(const PixelMapDetails details); +PixelMapDetails *ParseInfoFromPixelMap(OHOS::Media::PixelMap *pixelMap); + +#ifdef __cplusplus +}; +#endif +} // OHOS::UDMF + +#endif \ No newline at end of file diff --git a/udmf/interfaces/jskits/BUILD.gn b/udmf/interfaces/jskits/BUILD.gn index 12a5c2e726845294e465011d3edc336d53177b1c..3f24f25392b6baf2185475d5711a367235508518 100644 --- a/udmf/interfaces/jskits/BUILD.gn +++ b/udmf/interfaces/jskits/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2022-2025 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 @@ -18,28 +18,14 @@ config("udmf_napi_config") { "${udmf_interfaces_path}/innerkits/client", "${udmf_interfaces_path}/innerkits/common", "${udmf_interfaces_path}/innerkits/data", + "${udmf_interfaces_path}/innerkits/include", "${udmf_interfaces_path}/jskits/common", "${udmf_interfaces_path}/jskits/data", - "${udmf_framework_path}/common", "${udmf_framework_path}/innerkits/service", - - "//third_party/libuv/include", - "//third_party/node/src", - - "${aafwk_inner_api_path}/ability_manager/include", - "${aafwk_kits_path}/appkit/native/app/include/", - "${aafwk_kits_path}/ability/native/include", - "${aafwk_napi_path}/inner/napi_common", - "${aafwk_service_path}/abilitymgr/include", - "${aafwk_service_path}/common/include", ] } -config("aip_core_napi_config") { - include_dirs = [ "${udmf_interfaces_path}/jskits/intelligence" ] -} - ohos_shared_library("unifieddatachannel_napi") { branch_protector_ret = "pac_ret" sanitize = { @@ -52,6 +38,7 @@ ohos_shared_library("unifieddatachannel_napi") { sources = [ "${udmf_framework_path}/jskitsimpl/data/application_defined_record_napi.cpp", "${udmf_framework_path}/jskitsimpl/data/audio_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/data_load_params_napi.cpp", "${udmf_framework_path}/jskitsimpl/data/file_napi.cpp", "${udmf_framework_path}/jskitsimpl/data/folder_napi.cpp", "${udmf_framework_path}/jskitsimpl/data/get_data_params_napi.cpp", @@ -78,7 +65,6 @@ ohos_shared_library("unifieddatachannel_napi") { public_configs = [ ":udmf_napi_config" ] deps = [ - "${third_party_path}/bounds_checking_function:libsec_shared", "../innerkits:udmf_client", "../innerkits:utd_client", "../jskits:udmf_js_common", @@ -125,7 +111,6 @@ ohos_shared_library("uniformtypedescriptor_napi") { public_configs = [ ":udmf_napi_config" ] deps = [ - "${third_party_path}/bounds_checking_function:libsec_shared", "../innerkits:udmf_client", "../innerkits:utd_client", "../jskits:udmf_js_common", @@ -133,6 +118,7 @@ ohos_shared_library("uniformtypedescriptor_napi") { external_deps = [ "ability_runtime:abilitykit_native", + "ability_runtime:napi_common", "hilog:libhilog", "ipc:ipc_core", "napi:ace_napi", @@ -160,6 +146,7 @@ ohos_shared_library("udmf_data_napi") { sources = [ "${udmf_framework_path}/jskitsimpl/data/application_defined_record_napi.cpp", "${udmf_framework_path}/jskitsimpl/data/audio_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/data_load_params_napi.cpp", "${udmf_framework_path}/jskitsimpl/data/file_napi.cpp", "${udmf_framework_path}/jskitsimpl/data/folder_napi.cpp", "${udmf_framework_path}/jskitsimpl/data/get_data_params_napi.cpp", @@ -186,7 +173,6 @@ ohos_shared_library("udmf_data_napi") { public_configs = [ ":udmf_napi_config" ] deps = [ - "${third_party_path}/bounds_checking_function:libsec_shared", "../innerkits:udmf_client", "../innerkits:utd_client", "../jskits:udmf_js_common", @@ -237,7 +223,9 @@ ohos_static_library("udmf_js_common") { public_configs = [ ":udmf_napi_config" ] external_deps = [ "ability_runtime:abilitykit_native", + "ability_runtime:napi_common", "hilog:libhilog", + "ipc:ipc_single", "napi:ace_napi", ] public_external_deps = [ "image_framework:image" ] @@ -264,19 +252,59 @@ ohos_shared_library("intelligence_napi") { "${udmf_framework_path}/jskitsimpl/intelligence/image_embedding_napi.cpp", "${udmf_framework_path}/jskitsimpl/intelligence/js_ability.cpp", "${udmf_framework_path}/jskitsimpl/intelligence/native_module_intelligence.cpp", - "${udmf_framework_path}/jskitsimpl/intelligence/retrieval_napi.cpp", "${udmf_framework_path}/jskitsimpl/intelligence/text_embedding_napi.cpp", ] - public_configs = [ ":aip_core_napi_config" ] + include_dirs = [ "${udmf_interfaces_path}/jskits/intelligence" ] - deps = [] + deps = [ "../innerkits/aipcore:aip_core_mgr_static" ] external_deps = [ "ability_runtime:abilitykit_native", "ability_runtime:napi_base_context", "c_utils:utils", "hilog:libhilog", + "ipc:ipc_single", + "napi:ace_napi", + ] + + defines = [ "LOG_DOMAIN = 0xD001660" ] + relative_install_dir = "module/data" + subsystem_name = "distributeddatamgr" + part_name = "udmf" +} + +ohos_shared_library("rag_napi") { + branch_protector_ret = "pac_ret" + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + sources = [ + "${udmf_framework_path}/jskitsimpl/intelligence/aip_napi_error.cpp", + "${udmf_framework_path}/jskitsimpl/intelligence/aip_napi_utils.cpp", + "${udmf_framework_path}/jskitsimpl/intelligence/i_aip_core_manager_impl.cpp", + "${udmf_framework_path}/jskitsimpl/intelligence/js_ability.cpp", + "${udmf_framework_path}/jskitsimpl/intelligence/native_module_rag.cpp", + "${udmf_framework_path}/jskitsimpl/intelligence/rag_agent_chatllm_napi.cpp", + "${udmf_framework_path}/jskitsimpl/intelligence/rag_chatllm_impl.cpp", + "${udmf_framework_path}/jskitsimpl/intelligence/rag_session_napi.cpp", + ] + include_dirs = [ "${udmf_interfaces_path}/jskits/intelligence" ] + deps = [ "../innerkits/aipcore:aip_core_mgr_static" ] + cflags_cc = [ "-fvisibility=hidden" ] + external_deps = [ + "ability_runtime:abilitykit_native", + "ability_runtime:extensionkit_native", + "ability_runtime:napi_base_context", + "c_utils:utils", + "hilog:libhilog", "napi:ace_napi", ] diff --git a/udmf/interfaces/jskits/common/napi_data_utils.h b/udmf/interfaces/jskits/common/napi_data_utils.h index eefad858b9abb0100253af330cc8b98892672fd1..d126070e8a73e89cfedb0c6f203d12f8f2603edf 100644 --- a/udmf/interfaces/jskits/common/napi_data_utils.h +++ b/udmf/interfaces/jskits/common/napi_data_utils.h @@ -48,6 +48,10 @@ public: static napi_status GetValue(napi_env env, napi_value in, int32_t &out); static napi_status SetValue(napi_env env, const int32_t &in, napi_value &out); + /* napi_value <-> uint32_t */ + static napi_status GetValue(napi_env env, napi_value in, uint32_t &out); + static napi_status SetValue(napi_env env, const uint32_t &in, napi_value &out); + /* napi_value <-> int64_t */ static napi_status GetValue(napi_env env, napi_value in, int64_t &out); static napi_status SetValue(napi_env env, const int64_t &in, napi_value &out); @@ -80,6 +84,10 @@ public: static napi_status GetValue(napi_env env, napi_value in, std::map<std::string, int64_t> &out); static napi_status SetValue(napi_env env, const std::map<std::string, int64_t> &in, napi_value &out); + /* napi_value <-> std::set<std::string> */ + static napi_status GetValue(napi_env env, napi_value in, std::set<std::string> &out); + static napi_status SetValue(napi_env env, const std::set<std::string> &in, napi_value &out); + /* napi_value <-> UDVariant */ static napi_status GetValue(napi_env env, napi_value in, UDVariant &out); static napi_status SetValue(napi_env env, const UDVariant &in, napi_value &out); @@ -113,6 +121,10 @@ public: /* napi_value <- ProgressInfo */ static napi_status SetValue(napi_env env, const ProgressInfo &in, napi_value &out); + /* napi_value <-> DataLoadInfo */ + static napi_status GetValue(napi_env env, napi_value in, DataLoadInfo &out); + static napi_status SetValue(napi_env env, const DataLoadInfo &in, napi_value &out); + static bool IsTypeForNapiValue(napi_env env, napi_value param, napi_valuetype expectType); static bool IsNull(napi_env env, napi_value value); @@ -123,6 +135,9 @@ public: static napi_value DefineClass(napi_env env, const std::string &name, const napi_property_descriptor *properties, size_t count, napi_callback newcb); + static napi_status GetOptionalNamedProperty(napi_env env, napi_value &obj, const std::string &key, + napi_value &napiValue); + private: enum { /* std::map<key, value> to js::tuple<key, value> */ diff --git a/relational_store/frameworks/js/napi/rdb/include/napi_uv_queue.h b/udmf/interfaces/jskits/data/data_load_params_napi.h similarity index 44% rename from relational_store/frameworks/js/napi/rdb/include/napi_uv_queue.h rename to udmf/interfaces/jskits/data/data_load_params_napi.h index b59c1cb28473b11368aec3d4bacee02b7c6c5634..9a339860263a47022de3ebeab1da5f9dbf8ba7b2 100644 --- a/relational_store/frameworks/js/napi/rdb/include/napi_uv_queue.h +++ b/udmf/interfaces/jskits/data/data_load_params_napi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2025 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,35 +13,34 @@ * limitations under the License. */ -#ifndef NAPI_UV_QUEUE_H -#define NAPI_UV_QUEUE_H - -#include <functional> +#ifndef DATA_LOAD_PARAMS_NAPI_H +#define DATA_LOAD_PARAMS_NAPI_H +#include "async_task_params.h" +#include "concurrent_map.h" #include "napi/native_api.h" -#include "napi/native_common.h" #include "napi/native_node_api.h" +#include "visibility.h" +#include <string> -namespace OHOS::RdbJsKit { -class NapiUvQueue { - using NapiArgsGenerator = std::function<void(napi_env env, int &argc, napi_value *argv)>; +namespace OHOS { +namespace UDMF { +class DataLoadParamsNapi { public: - NapiUvQueue(napi_env env, napi_value callback); - - virtual ~NapiUvQueue(); - - bool operator==(napi_value value); - - void CallFunction(NapiArgsGenerator genArgs = NapiArgsGenerator()); + API_EXPORT static bool Convert2NativeValue(napi_env env, napi_value in, DataLoadParams &dataLoadParams); private: - napi_env env_ = nullptr; - napi_ref callback_ = nullptr; - NapiArgsGenerator args; - uv_loop_s *loop_ = nullptr; - - static constexpr int MAX_CALLBACK_ARG_NUM = 6; + struct DataLoadArgs { + std::string udKey; + DataLoadInfo dataLoadInfo; + }; + static napi_value CreateDataLoadInfo(napi_env env, const DataLoadInfo &dataLoadInfo); + static void CallDataLoadHandler(napi_env env, napi_value callback, void *context, void *data); + + static ConcurrentMap<std::string, napi_threadsafe_function> tsfns_; }; -} // namespace OHOS::RdbJsKit -#endif \ No newline at end of file + +} // namespace UDMF +} // namespace OHOS +#endif // DATA_LOAD_PARAMS_NAPI_H \ No newline at end of file diff --git a/udmf/interfaces/jskits/data/unified_data_channel_napi.h b/udmf/interfaces/jskits/data/unified_data_channel_napi.h index 31575669ce607d4144e8c74d2bbbd86c1a9899d3..5664ce9fd371f54b9cc6442283d4961624be582f 100644 --- a/udmf/interfaces/jskits/data/unified_data_channel_napi.h +++ b/udmf/interfaces/jskits/data/unified_data_channel_napi.h @@ -21,6 +21,7 @@ #include "napi/native_api.h" #include "napi/native_node_api.h" #include "udmf_client.h" +#include "unified_key.h" namespace OHOS { namespace UDMF { @@ -36,7 +37,9 @@ private: static napi_value UpdateData(napi_env env, napi_callback_info info); static napi_value QueryData(napi_env env, napi_callback_info info); static napi_value DeleteData(napi_env env, napi_callback_info info); + static napi_value ConvertRecordsToEntries(napi_env env, napi_callback_info info); static napi_status GetNamedProperty(napi_env env, napi_value &obj, const std::string &key, std::string &value); + static napi_status GetOptionalProperty(napi_env env, napi_value &obj, const std::string &key, int32_t &value); static napi_value CreateShareOptions(napi_env env, napi_callback_info info); static napi_value SetAppShareOptions(napi_env env, napi_callback_info info); static napi_value RemoveAppShareOptions(napi_env env, napi_callback_info info); @@ -45,6 +48,8 @@ private: static napi_value CreateFileConflictOptions(napi_env env, napi_callback_info info); static napi_value CreateProgressIndicator(napi_env env, napi_callback_info info); static napi_value CreateListenerStatus(napi_env env, napi_callback_info info); + static bool IsValidOptionInfoNonDrag(UnifiedKey &key, const std::string &intention); + static napi_value CreateVisibility(napi_env env, napi_callback_info info); }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/jskits/data/unified_data_napi.h b/udmf/interfaces/jskits/data/unified_data_napi.h index a3e2d2c4a9f981bb5264f0383f31f62d0e147847..b8043821626d302076f4b2a8ec5ff1b9f4c7b23f 100644 --- a/udmf/interfaces/jskits/data/unified_data_napi.h +++ b/udmf/interfaces/jskits/data/unified_data_napi.h @@ -46,6 +46,8 @@ private: static napi_value SetProperties(napi_env env, napi_callback_info info); static napi_ref NewWithRef(napi_env env, size_t argc, napi_value *argv, void **out, napi_value constructor); static napi_status Unwrap(napi_env env, napi_value in, void **out, napi_value constructor); + static napi_value AttachUnifiedData(napi_env env, void *value, void *); + static void *DetachUnifiedData(napi_env env, void *value, void *); }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/jskits/intelligence/aip_napi_error.h b/udmf/interfaces/jskits/intelligence/aip_napi_error.h index 1dc8bb07c6fbc4c4e12fee4d327479970e7800b5..abe39cf0a269a57d4e1714e7c3580213d7203192 100644 --- a/udmf/interfaces/jskits/intelligence/aip_napi_error.h +++ b/udmf/interfaces/jskits/intelligence/aip_napi_error.h @@ -17,6 +17,8 @@ #define AIP_NAPI_ERROR_H #include <map> +#include <optional> + #include "napi/native_api.h" #include "napi/native_node_api.h" @@ -27,23 +29,57 @@ enum NativeErrCode : int32_t { NATIVE_DATABASE_ALREADY_CLOSED = 27394078, NATIVE_DATABASE_IS_BUSY = 27394082, NATIVE_DATABASE_WAL_FILE_EXCEEDS_LIMIT = 27394095, - NATIVE_DATABASE_GENERIC_ERROD = 27394103, + NATIVE_DATABASE_GENERIC_ERROR = 27394103, NATIVE_DATABASE_CORRUPTED = 27394104, NATIVE_DATABASE_PERMISSION_DENIED = 27394107, NATIVE_DATABASE_FILE_IS_LOCKED = 27394109, NATIVE_DATABASE_OUT_OF_MEMORY = 27394110, NATIVE_DATABASE_IO_ERROR = 27394112, + NATIVE_E_RECALL_FAILURE = 28114948, - NATIVE_E_RERANK_FAILURE = 28114949, - NATIVE_E_INVALID_NUMBER = 28114950, - NATIVE_E_INVALID_PRIMARY_KEY = 28114951, - NATIVE_E_UNSUPPORTED_COMPOSITE_PRIMARY_KEY = 28114952, - NATIVE_E_EMPTY_STRING_FIELD = 28114953, - NATIVE_E_INVALID_FILTER_INPUT = 28114954, - NATIVE_E_INVALID_RECALL_FIELD = 28114955, - NATIVE_E_HIGH_VECTOR_SIMILARITY_THRESHOLD = 28114956, - NATIVE_E_RERANK_METHOD_MISMATCH = 28114957, - NATIVE_E_EMPTY_PARAMETER = 28114958, + NATIVE_E_RERANK_FAILURE, + NATIVE_E_INVALID_NUMBER, + NATIVE_E_INVALID_PRIMARY_KEY, + NATIVE_E_UNSUPPORTED_COMPOSITE_PRIMARY_KEY, + NATIVE_E_EMPTY_STRING_FIELD, + NATIVE_E_INVALID_FILTER_INPUT, + NATIVE_E_INVALID_RECALL_FIELD, + NATIVE_E_HIGH_VECTOR_SIMILARITY_THRESHOLD, + NATIVE_E_RERANK_METHOD_MISMATCH, + NATIVE_E_EMPTY_PARAMETER, + + GRAPH_RETRIEVAL_E_GDB_NOT_INIT, + GRAPH_RETRIEVAL_E_RDB_NOT_INIT, + GRAPH_RETRIEVAL_E_MEMORY_ALLOC_FAILURE, + GRAPH_RETRIEVAL_E_ALGORITHM_NOT_INIT, + GRAPH_RETRIEVAL_E_RDB_QUERY_FAILURE, + GRAPH_RETRIEVAL_E_GDB_QUERY_FAILURE, + DATABASE_E_GDB_INVALID, + + NATIVE_SUMMARY_E_INVALID_PARAMETERS, + NATIVE_SUMMARY_E_INVALID_RESULT, + NATIVE_SUMMARY_E_INVALID_OUTPUT, + + NATIVE_RAG_E_CONFIG_ERROR, + NATIVE_RAG_E_INSTANCE_EXIST, + NATIVE_RAG_E_INVALID_INPUT, + NATIVE_RAG_E_QUERY_LENGTH_EXCEED, + NATIVE_RAG_E_STREAM_BUSY, + NATIVE_RAG_E_INSTANCE_NOT_EXIST, + NATIVE_RAG_E_PROMPT_ERROR, + NATIVE_RAG_E_LLM_ERROR, + NATIVE_RAG_E_LLM_OCCUPIED, + NATIVE_RAG_E_LLM_TIMEOUT, + NATIVE_RAG_E_LLM_OUTPUT_INVALID, + NATIVE_RAG_E_RETRIEVER_TIMEOUT, + + NATIVE_LLM_E_PARSER_JSON_PARSE, + NATIVE_LLM_E_PARSER_JSON_MEMBER, + NATIVE_LLM_E_REQUEST_MALLOC, + NATIVE_PROMPT_E_PLACEHOLDER_JSON_PARSE, + NATIVE_PROMPT_E_CHAT_TEMP_JSON_TYPE, + NATIVE_PROMPT_E_CHAT_TEMP_EMPTY_MSG, + NATIVE_PROMPT_E_CHAT_TEMP_UPDATE_SYS, }; enum TsErrCode : int32_t { @@ -54,7 +90,7 @@ enum TsErrCode : int32_t { DATABASE_ALREADY_CLOSED = 31300002, DATABASE_IS_BUSY = 31300003, DATABASE_OUT_OF_MEMORY = 31300004, - DATABASE_GENERIC_ERROD = 31300100, + DATABASE_GENERIC_ERROR = 31300100, DATABASE_PERMISSION_DENIED = 31300101, DATABASE_FILE_IS_LOCKED = 31300102, DATABASE_IO_ERROR = 31300103, @@ -71,6 +107,16 @@ enum TsErrCode : int32_t { RETRIEVAL_E_HIGH_VECTOR_SIMILARITY_THRESHOLD = 31301008, RETRIEVAL_E_RERANK_METHOD_MISMATCH = 31301009, RETRIEVAL_E_EMPTY_PARAMETER = 31301010, + RAG_E_RAG_COMMON_ERROR = 32800000, + RAG_E_LLM_TIMEOUT = 32800001, + RAG_E_LLM_LOAD_FAILED = 32800002, + RAG_E_LLM_BUSY = 32800003, + RAG_E_LLM_OUTPUT_INVALID = 32800004, + RAG_E_RAG_ALREADY_EXISTS = 32800005, + RAG_E_RAG_BUSY = 32800006, + RAG_E_RAG_ALREADY_CLOSED = 32800007, + RAG_E_RAG_USER_CANCEL = 32800008, + RAG_E_RAG_TIMEOUT = 32800009, }; int32_t ConvertErrCodeNative2Ts(int32_t nativeErrCode); diff --git a/udmf/interfaces/jskits/intelligence/aip_napi_utils.h b/udmf/interfaces/jskits/intelligence/aip_napi_utils.h index 03565a4e1f4ccc0e1f3f1a720e5ce6bb4a9fac46..2e7367793b7b00d6a55047ebda759c4dd6508530 100644 --- a/udmf/interfaces/jskits/intelligence/aip_napi_utils.h +++ b/udmf/interfaces/jskits/intelligence/aip_napi_utils.h @@ -17,8 +17,10 @@ #define AIP_NAPI_UTILS_H #include <type_traits> +#include <variant> #include "i_aip_core_manager.h" +#include "rag_chatllm_impl.h" #include "napi/native_api.h" #include "napi/native_node_api.h" @@ -59,6 +61,7 @@ public: static napi_status Convert2Value(napi_env env, napi_value in, double &out); static napi_status Convert2Value(napi_env env, napi_value in, std::string &out); static napi_status Convert2Value(napi_env env, napi_value in, std::vector<float> &out); + static napi_status Convert2Value(napi_env env, napi_value in, napi_ref &out); template <typename T> struct is_shared_ptr : std::false_type {}; @@ -119,6 +122,10 @@ public: static napi_status Convert2Value(napi_env env, const napi_value &in, CryptoParam &cryptoParam); static napi_status Convert2Value(napi_env env, const napi_value &in, ContextParam &context); static napi_status Convert2Value(napi_env env, const napi_value &in, napi_value &out); + static napi_status Convert2Value(napi_env env, const napi_value &in, OptionStruct &out); + static napi_status Convert2Value(napi_env env, const napi_value &in, ConfigStruct &out); + static napi_status Convert2Value(napi_env env, const napi_value &in, std::shared_ptr<IChatLLM> &out); + static napi_status Convert2Value(napi_env env, const napi_value &in, LLMStreamAnswer &out); static napi_status Convert2JSValue(napi_env env, const std::vector<uint8_t> &in, napi_value &out); static napi_status Convert2JSValue(napi_env env, const std::vector<float> &in, napi_value &out); @@ -131,6 +138,8 @@ public: static napi_status Convert2JSValue(napi_env env, const DataIntelligence::RetrievalResponseStruct &in, napi_value &out); static napi_status Convert2JSValue(napi_env env, const DataIntelligence::ItemInfoStruct &in, napi_value &out); + static napi_status Convert2JSValue(napi_env env, const AnswerStruct &in, napi_value &out); + static napi_status Convert2JSValue(napi_env env, const StreamStruct &in, napi_value &out); static napi_status Convert2JSValue(napi_env env, const std::map<std::string, FieldType> &in, napi_value &out); static napi_status Convert2JSValue(napi_env env, const std::map<int32_t, std::map<std::string, RecallScoreStruct>> &in, napi_value &out); diff --git a/relational_store/frameworks/native/gdb/include/hitrace.h b/udmf/interfaces/jskits/intelligence/hitrace.h similarity index 71% rename from relational_store/frameworks/native/gdb/include/hitrace.h rename to udmf/interfaces/jskits/intelligence/hitrace.h index a1bdebd64ba738f6f16d5ed184c407e62e152f1f..44c2cf7a7e929e58f8d6226ce4d9bb68c8c8ec05 100644 --- a/relational_store/frameworks/native/gdb/include/hitrace.h +++ b/udmf/interfaces/jskits/intelligence/hitrace.h @@ -13,28 +13,28 @@ * limitations under the License. */ -#ifndef DISTRIBUTEDDATAMGR_NATIVEGDB_HITRACE_H -#define DISTRIBUTEDDATAMGR_NATIVEGDB_HITRACE_H +#ifndef DATA_INTELLIGENCE_HITRACE_H +#define DATA_INTELLIGENCE_HITRACE_H #include <string> #include "hitrace_meter.h" namespace OHOS { -namespace DistributedDataAip { +namespace DataIntelligence { class HiTrace final { public: inline HiTrace(const std::string &value) { - StartTrace(HITRACE_TAG_DISTRIBUTEDDATA, value); + StartTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_TAG_DISTRIBUTEDDATA, value.c_str(), ""); } inline ~HiTrace() { - FinishTrace(HITRACE_TAG_DISTRIBUTEDDATA); + FinishTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_TAG_DISTRIBUTEDDATA); } }; -} // namespace DistributedDataAip +} // namespace DataIntelligence } // namespace OHOS #endif \ No newline at end of file diff --git a/udmf/interfaces/jskits/intelligence/i_aip_core_manager_impl.h b/udmf/interfaces/jskits/intelligence/i_aip_core_manager_impl.h index 00ef61ea224898f6b084cfc554633c064a6c8b7d..b26ccfec8fc3db483cc94673f897ef2b1741ded3 100644 --- a/udmf/interfaces/jskits/intelligence/i_aip_core_manager_impl.h +++ b/udmf/interfaces/jskits/intelligence/i_aip_core_manager_impl.h @@ -27,9 +27,7 @@ class IAipCoreManagerImpl : public IAipCoreManager { public: IAipCoreManagerImpl() = default; ~IAipCoreManagerImpl() = default; - int32_t InitRetriever(const RetrievalConfigStruct& retrievalConfig) override; - int32_t Retrieve(const std::string query, const RetrievalConditionStruct &condition, - RetrievalResponseStruct &retrievalResponse) override; + int32_t InitTextModel(const ModelConfigData &config) override; int32_t InitImageModel(const ModelConfigData &config) override; int32_t LoadTextModel() override; @@ -40,6 +38,14 @@ public: int32_t ReleaseImageModel() override; int32_t GetImageEmbedding(std::string uri, std::vector<float> &results) override; int32_t SplitText(std::string text, int32_t size, float overlap, std::vector<std::string> &results) override; + + int32_t CreateRAGSession(const ContextParam &contex, const ConfigStruct &config) override; + int32_t RAGSessionStreamRun(const std::string &question, const OptionStruct &option, + std::function<void(const StreamStruct&, int32_t)> callback) override; + int32_t ReleaseRAGSession() override; + int32_t RAGSessionRun(const std::string &query, const OptionStruct &runOption, AnswerStruct &answer) override; + + bool CheckDeviceType() override; }; } // namespace DataIntelligence } // namespace OHOS diff --git a/udmf/interfaces/jskits/intelligence/js_ability.h b/udmf/interfaces/jskits/intelligence/js_ability.h index 0e1602d19449003d02c96a6588fe67ca5ac77610..a381ec12ee786ddf2853e3c7726fa26faba7c7c1 100644 --- a/udmf/interfaces/jskits/intelligence/js_ability.h +++ b/udmf/interfaces/jskits/intelligence/js_ability.h @@ -32,6 +32,7 @@ public: explicit Context(std::shared_ptr<AbilityRuntime::AbilityContext> abilityContext); std::string GetDatabaseDir(); + std::string GetCacheDir(); int GetSystemDatabaseDir(const std::string &dataGroupId, std::string &databaseDir); std::string GetBundleName(); std::string GetModuleName(); @@ -46,6 +47,7 @@ public: private: int32_t area_ = 0; std::string databaseDir_; + std::string cacheDir_; std::string bundleName_; std::string moduleName_; std::string uri_; diff --git a/relational_store/frameworks/native/gdb/include/db_trace.h b/udmf/interfaces/jskits/intelligence/napi_trace.h similarity index 70% rename from relational_store/frameworks/native/gdb/include/db_trace.h rename to udmf/interfaces/jskits/intelligence/napi_trace.h index b8aea61efd393da3bbefc9e8a5532c73cee30324..e3d4b599e64226c1561e5cf187e6b3a38d5f4121 100644 --- a/relational_store/frameworks/native/gdb/include/db_trace.h +++ b/udmf/interfaces/jskits/intelligence/napi_trace.h @@ -12,20 +12,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef NATIVE_GDB_TRACE_H -#define NATIVE_GDB_TRACE_H +#ifndef DATA_INTELLIGENCE_NAPI_TRACE_H +#define DATA_INTELLIGENCE_NAPI_TRACE_H #define DO_NOTHING -#ifdef DB_TRACE_ON +#ifdef DATA_INTELLIGENCE_TRACE_ON #include "hitrace.h" -#ifndef DISTRIBUTED_DATA_HITRACE -#define DISTRIBUTED_DATA_HITRACE(trace) OHOS::DistributedDataAip::HiTrace hitrace(trace) +#ifndef DATA_INTELLIGENCE_HITRACE +#define DATA_INTELLIGENCE_HITRACE(trace) OHOS::DataIntelligence::HiTrace hitrace(trace) #endif #else -#define DISTRIBUTED_DATA_HITRACE(trace) DO_NOTHING +#define DATA_INTELLIGENCE_HITRACE(trace) DO_NOTHING #endif #endif \ No newline at end of file diff --git a/udmf/interfaces/jskits/intelligence/native_module_intelligence.h b/udmf/interfaces/jskits/intelligence/native_module_intelligence.h index 92826f90236f04ecf653297207a16df6331b3452..747a6306210f22a6f48f9513bfc520a51ea84d5f 100644 --- a/udmf/interfaces/jskits/intelligence/native_module_intelligence.h +++ b/udmf/interfaces/jskits/intelligence/native_module_intelligence.h @@ -19,6 +19,5 @@ #include "image_embedding_napi.h" #include "napi/native_node_api.h" #include "text_embedding_napi.h" -#include "retrieval_napi.h" #endif // NATIVE_MODULE_INTELLIGENCE_H \ No newline at end of file diff --git a/udmf/interfaces/jskits/intelligence/native_module_rag.h b/udmf/interfaces/jskits/intelligence/native_module_rag.h new file mode 100644 index 0000000000000000000000000000000000000000..7493bfbbabd207b246bd4228992d87695b70eea1 --- /dev/null +++ b/udmf/interfaces/jskits/intelligence/native_module_rag.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 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 NATIVE_MODULE_RAG_H + #define NATIVE_MODULE_RAG_H + + #include "napi/native_node_api.h" + #include "rag_session_napi.h" + + #endif // NATIVE_MODULE_RAG_H \ No newline at end of file diff --git a/preferences/frameworks/native/include/hitrace.h b/udmf/interfaces/jskits/intelligence/rag_agent_chatllm_napi.h similarity index 55% rename from preferences/frameworks/native/include/hitrace.h rename to udmf/interfaces/jskits/intelligence/rag_agent_chatllm_napi.h index 50b8412243f9daa46f39084c8a7c2b7b13932e95..ceb24582993424963b107136ad95d2a806275e80 100644 --- a/preferences/frameworks/native/include/hitrace.h +++ b/udmf/interfaces/jskits/intelligence/rag_agent_chatllm_napi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2025 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,28 +13,20 @@ * limitations under the License. */ -#ifndef DISTRIBUTEDDATAMGR_PREFERENCES_HITRACE_H -#define DISTRIBUTEDDATAMGR_PREFERENCES_HITRACE_H - -#include <string> - -#include "hitrace_meter.h" +#ifndef RAG_AGENT_CHATLLM_NAPI_H +#define RAG_AGENT_CHATLLM_NAPI_H +#include "napi/native_node_api.h" namespace OHOS { -namespace NativePreferences { -class HiTrace final { -public: - inline HiTrace(const std::string &value) - { - StartTrace(HITRACE_TAG_DISTRIBUTEDDATA, value); - } +namespace DataIntelligence { - inline ~HiTrace() - { - FinishTrace(HITRACE_TAG_DISTRIBUTEDDATA); - } +class RAGAgentChatLLMNapi { +public: + static napi_value Init(napi_env env, napi_value exports); +private: + static napi_value Constructor(napi_env env, napi_callback_info info); + static napi_status InitEnum(napi_env env, napi_value exports); }; -} // namespace NativePreferences +} // namespace DataIntelligence } // namespace OHOS - -#endif \ No newline at end of file +#endif //RAG_AGENT_CHATLLM_NAPI_H diff --git a/udmf/interfaces/jskits/intelligence/rag_chatllm_impl.h b/udmf/interfaces/jskits/intelligence/rag_chatllm_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..9cb524b094aff258b791e24c21ac3e9ded58e3be --- /dev/null +++ b/udmf/interfaces/jskits/intelligence/rag_chatllm_impl.h @@ -0,0 +1,76 @@ +/* +* Copyright (c) 2025 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 RAG_CHATLLM_IMPL_H +#define RAG_CHATLLM_IMPL_H +#include <condition_variable> +#include <uv.h> + +#include "napi/native_node_api.h" +#include "i_aip_core_manager.h" + +namespace OHOS { +namespace DataIntelligence { +using ThreadLockInfo = struct ThreadLockInfo { + std::mutex mutex; + std::condition_variable condition; + bool ready = false; +}; + +using WorkParam = struct WorkParam { + // input + std::string query; + std::shared_ptr<LLMStreamCallback> llmStreamCallback; + napi_env env; + napi_ref ref; + // output + napi_status status; + int32_t result; + // lock + std::shared_ptr<ThreadLockInfo> lockInfo; +}; +using StreamCallbackWorkParam = struct StreamCallbackWorkParam { + // input + LLMStreamAnswer answer; + napi_env env; +}; + +class ChatLLM final : public IChatLLM { +public: + ChatLLM(napi_env env, napi_ref streamChatRef); + ~ChatLLM() override; + TsLLMRequestStatus StreamChat(const std::string &query, const LLMStreamCallback &streamCallback) override; + + void SetRef(napi_ref streamChatRef); + napi_ref GetRef(); +private: + static napi_value StreamCallbackFunc(napi_env env, napi_callback_info info); + static void StreamChatCallbackEventFunc(WorkParam *param); + static void CallJSStreamChat(napi_env env, napi_ref ref, WorkParam *llmWorkParam); + static void HandlePromiseValue(napi_env env, napi_value promiseResult, WorkParam *llmWorkParam); + static napi_value PromiseThenCallback(napi_env env, napi_callback_info info); + static napi_value PromiseCatchCallback(napi_env env, napi_callback_info info); + static void NativeCallbackAsync(napi_env env, const LLMStreamAnswer &answer); + + napi_env env_; + napi_ref streamChatRef_; + + static std::shared_ptr<LLMStreamCallback> llmStreamCallback_; + LLMStreamCallback streamCallback_; +}; + +} +} +#endif //RAG_CHATLLM_IMPL_H diff --git a/udmf/interfaces/jskits/intelligence/retrieval_napi.h b/udmf/interfaces/jskits/intelligence/rag_session_napi.h similarity index 31% rename from udmf/interfaces/jskits/intelligence/retrieval_napi.h rename to udmf/interfaces/jskits/intelligence/rag_session_napi.h index 3074714c2299cdd58f17a70643c1cef3fed3bf8a..7c703508e496e710e26c17662278caee85776a88 100644 --- a/udmf/interfaces/jskits/intelligence/retrieval_napi.h +++ b/udmf/interfaces/jskits/intelligence/rag_session_napi.h @@ -13,60 +13,82 @@ * limitations under the License. */ -#ifndef RETRIEVAL_NAPI_H -#define RETRIEVAL_NAPI_H +#ifndef RAG_SESSION_NAPI_H +#define RAG_SESSION_NAPI_H #include <string> -#include <map> #include <uv.h> -#include <refbase.h> #include "i_aip_core_manager.h" +#include "rag_chatllm_impl.h" #include "napi/native_api.h" -#include "napi/native_node_api.h" namespace OHOS { namespace DataIntelligence { -class RetrievalNapi; -struct AsyncGetRetriever { +class RAGSessionNapi; +struct AsyncCreateRAGSession { napi_async_work asyncWork; napi_deferred deferred; - RetrievalConfigStruct config; - IAipCoreManager* retrievalAipCoreManagerPtr; + IAipCoreManager* ragAipCoreManagerPtr; + ContextParam context; + ConfigStruct config; int32_t ret; + napi_value result; }; -struct AsyncRetrieve { + +struct AsyncStreamRun { napi_async_work asyncWork; napi_deferred deferred; - std::string query; - RetrievalConditionStruct retrievalCondition; - IAipCoreManager* retrievalAipCoreManagerPtr; - RetrievalResponseStruct retrievalResponse; - napi_value res; + RAGSessionNapi* sessionNapi; + std::string question; + OptionStruct option; + StreamStruct stream; int32_t ret; }; -class RetrievalNapi { -public: - RetrievalNapi(); - ~RetrievalNapi(); - static napi_value Init(napi_env env, napi_value exports); - static napi_value GetRetriever(napi_env env, napi_callback_info info); - static napi_value Retrieve(napi_env env, napi_callback_info info); - static napi_value RetrieverConstructor(napi_env env, napi_callback_info info); - static napi_value WrapAipCoreManager(napi_env env, IAipCoreManager* retrievalAipCoreManager); +using StreamRunCallbackWorkParam = struct StreamRunCallbackWorkParam { + StreamStruct stream; + int32_t errCode; + napi_env env; + napi_ref ref; + napi_ref thisJsRef; + std::shared_ptr<ThreadLockInfo> lockInfo; +}; +class RAGSessionNapi { +public: + explicit RAGSessionNapi(IAipCoreManager *aipAipCoreManager); + ~RAGSessionNapi(); + static napi_value Init(napi_env env, napi_value exports); private: - static bool LoadAsyncExecution(napi_env env, napi_deferred deferred); - static bool CreateAsyncGetRetrieverExecution(napi_env env, AsyncGetRetriever *asyncGetRetriever); - static bool CreateAsyncRetrieveExecution(napi_env env, AsyncRetrieve *asyncRetrieve); - static void GetRetrieverExecutionCB(napi_env env, void *data); - static void GetRetrieverCompleteCB(napi_env env, napi_status status, void *data); - static void RetrieveExecutionCB(napi_env env, void *data); - static void RetrieveCompleteCB(napi_env env, napi_status status, void *data); - napi_env env_; - static AipCoreManagerHandle retrievalAipCoreMgrHandle_; + static napi_value CreateRAGSession(napi_env env, napi_callback_info info); + static napi_value StreamRun(napi_env env, napi_callback_info info); + static napi_value Close(napi_env env, napi_callback_info info); + static napi_value WrapAipCoreManager(napi_env env, IAipCoreManager* ragAipCoreManager); + static void CreateRAGSessionExecutionCB(napi_env env, void *data); + static void CreateRAGSessionCompleteCB(napi_env env, napi_status status, void *data); + static bool CreateAsyncCreateRAGSession(napi_env env, AsyncCreateRAGSession *asyncCreateRAGSession); + static bool CreateAsyncStreamRunExecution(napi_env env, AsyncStreamRun *asyncStreamRun); + static bool CreateAsyncCloseExecution(napi_env env, AsyncStreamRun *asyncClose); + static void CloseExecutionCB(napi_env env, void *data); + static void CloseCompleteCB(napi_env env, napi_status status, void *data); + static napi_status ParseStreamRunArgs(napi_env env, napi_callback_info info, std::string &question, + OptionStruct &option, RAGSessionNapi **sessionNapi); + static void StreamRunExecutionCB(napi_env env, void *data); + static void StreamRunCompleteCB(napi_env env, napi_status status, void *data); + static void StreamRunCallbackExecute(RAGSessionNapi *session_napi, StreamStruct stream, int32_t errCode); + static void StreamRunCallbackEventFunc(StreamRunCallbackWorkParam *workParam); + static void StreamRunCallbackJSExecute (StreamRunCallbackWorkParam *workParam); + static AipCoreManagerHandle aipAipCoreMgrHandle_; + static napi_ref callbackRef_; + static napi_threadsafe_function tsfn_; + + napi_env env_ = nullptr; + napi_ref ref_ = nullptr; + napi_ref thisJsRef_ = nullptr; + IAipCoreManager *aipAipCoreManager_; }; } // namespace DataIntelligence } // namespace OHOS -#endif // RETRIEVAL_NAPI_H +#endif // RAG_SESSION_NAPI_H + \ No newline at end of file diff --git a/udmf/interfaces/ndk/BUILD.gn b/udmf/interfaces/ndk/BUILD.gn index edf268c8aaa25b01909eca4833f088dccec88c6d..50520e9d39fce3faead2281048c99e1bc5e61a60 100644 --- a/udmf/interfaces/ndk/BUILD.gn +++ b/udmf/interfaces/ndk/BUILD.gn @@ -54,6 +54,8 @@ ohos_shared_library("libudmf") { "image_framework:image", "image_framework:image_native", "image_framework:pixelmap", + "ipc:ipc_single", + "kv_store:distributeddata_inner", ] relative_install_dir = "ndk" diff --git a/udmf/interfaces/ndk/data/data_provider_impl.h b/udmf/interfaces/ndk/data/data_provider_impl.h index d3830dc4d764fd94fd0753180078ddcbdbbea2ad..9126067d4959282553766e04c27133ea1476bc0b 100644 --- a/udmf/interfaces/ndk/data/data_provider_impl.h +++ b/udmf/interfaces/ndk/data/data_provider_impl.h @@ -33,7 +33,7 @@ public: OH_UdmfRecordProvider* GetInnerProvider(); ValueType GetValueByType(const std::string &utdId) override; private: - OH_UdmfRecordProvider* innerProvider_; + OH_UdmfRecordProvider* innerProvider_ {nullptr}; }; } // namespace UDMF diff --git a/udmf/interfaces/ndk/data/udmf.h b/udmf/interfaces/ndk/data/udmf.h index 84638d3aec5d6ad766d6167788aa9022f126ecbf..155f791612572c5da5ce0ff772742e21737a77aa 100644 --- a/udmf/interfaces/ndk/data/udmf.h +++ b/udmf/interfaces/ndk/data/udmf.h @@ -63,11 +63,35 @@ typedef enum Udmf_Intention { /** * @brief The intention is drag. */ - UDMF_INTENTION_DRAG, + UDMF_INTENTION_DRAG = 0, /** * @brief The intention is pasteboard. */ UDMF_INTENTION_PASTEBOARD, + /** + * @brief The intention is data hub. + * + * @since 20 + */ + UDMF_INTENTION_DATA_HUB, + /** + * @brief The intention is system share. + * + * @since 20 + */ + UDMF_INTENTION_SYSTEM_SHARE, + /** + * @brief The intention is picker. + * + * @since 20 + */ + UDMF_INTENTION_PICKER, + /** + * @brief The intention is menu. + * + * @since 20 + */ + UDMF_INTENTION_MENU, } Udmf_Intention; /** @@ -79,7 +103,7 @@ typedef enum Udmf_ShareOption { /** * @brief Invalid share option. */ - SHARE_OPTIONS_INVALID, + SHARE_OPTIONS_INVALID = 0, /** * @brief Allowed to be used in the same application on this device. */ @@ -122,6 +146,23 @@ typedef enum Udmf_ProgressIndicator { UDMF_DEFAULT = 1 } Udmf_ProgressIndicator; +/** + * @brief Describe the visibility range of data + * + * @since 20 + */ +typedef enum Udmf_Visibility { + /** + * @brief The visibility level that specifies that any hap or native can be obtained. + */ + UDMF_ALL = 0, + + /** + * @brief The visibility level that specifies that only data providers can be obtained. + */ + UDMF_OWN_PROCESS +} Udmf_Visibility; + /** * @brief Describes the unified data type. * @@ -173,6 +214,35 @@ typedef struct OH_UdmfGetDataParams OH_UdmfGetDataParams; */ typedef void (*OH_Udmf_DataProgressListener)(OH_Udmf_ProgressInfo* progressInfo, OH_UdmfData* data); +/** + * @brief Describes the optional arguments of data operation + * + * @since 20 + */ +typedef struct OH_UdmfOptions OH_UdmfOptions; + +/** + * @brief Indicates data loading params. + * + * @since 20 + */ +typedef struct OH_UdmfDataLoadParams OH_UdmfDataLoadParams; + +/** + * @brief Indicates data loading information. + * + * @since 20 + */ +typedef struct OH_UdmfDataLoadInfo OH_UdmfDataLoadInfo; + +/** + * @brief Indicates the callback function for loading data. + * + * @param acceptableInfo Indicates the type and number of data that can be accepted by the receiver. + * @return Returns the data to be loaded. + * @since 20 + */ +typedef OH_UdmfData* (*OH_Udmf_DataLoadHandler)(OH_UdmfDataLoadInfo* acceptableInfo); /** * @brief Creation a pointer to the instance of the {@link OH_UdmfData}. @@ -774,6 +844,106 @@ int OH_UdmfProperty_SetExtrasIntParam(OH_UdmfProperty* pThis, const char* key, i int OH_UdmfProperty_SetExtrasStringParam(OH_UdmfProperty* pThis, const char* key, const char* param); +/** + * @brief Creation a pointer to the instance of the {@link OH_UdmfOptions}. + * + * @return If the operation is successful, a pointer to the instance of the {@link OH_UdmfOptions} + * structure is returned. If the operation is failed, nullptr is returned. + * @see OH_UdmfOptions. + * @since 20 + */ +OH_UdmfOptions* OH_UdmfOptions_Create(); + +/** + * @brief Destroy a pointer that points to an instance of {@link OH_UdmfOptions}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @see OH_UdmfOptions. + * @since 20 + */ +void OH_UdmfOptions_Destroy(OH_UdmfOptions* pThis); + +/** + * @brief Get key from the {@link OH_UdmfOptions}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @return Returns a pointer of the value string when input args normally, otherwise return nullptr. + * @see OH_UdmfOptions + * @since 20 + */ +const char* OH_UdmfOptions_GetKey(OH_UdmfOptions* pThis); + +/** + * @brief Set the key to the {@link OH_UdmfOptions}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @param key Represents a new string value of the key. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * @see OH_UdmfOptions Udmf_ErrCode + * @since 20 + */ +int OH_UdmfOptions_SetKey(OH_UdmfOptions* pThis, const char* key); + +/** + * @brief Get intention from the {@link OH_UdmfOptions}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @return Returns {@link Udmf_Intention} value. + * @see OH_UdmfOptions Udmf_Intention + * @since 20 + */ +Udmf_Intention OH_UdmfOptions_GetIntention(OH_UdmfOptions* pThis); + +/** + * @brief Set intention value to {@link OH_UdmfOptions}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @param intention Represents new {@link Udmf_Intention} param. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * @see OH_UdmfOptions Udmf_Intention Udmf_ErrCode. + * @since 20 + */ +int OH_UdmfOptions_SetIntention(OH_UdmfOptions* pThis, Udmf_Intention intention); + +/** + * @brief Reset {@link OH_UdmfOptions} to default. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * @see OH_UdmfOptions Udmf_ErrCode. + * @since 20 + */ +int OH_UdmfOptions_Reset(OH_UdmfOptions* pThis); + +/** + * @brief Get visibility from the {@link OH_UdmfOptions}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @return Returns {@link Udmf_Visibility} value. + * @see OH_UdmfOptions Udmf_Visibility + * @since 20 + */ +Udmf_Visibility OH_UdmfOptions_GetVisibility(OH_UdmfOptions* pThis); + +/** + * @brief Set visibility value to {@link OH_UdmfOptions}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @param visibility Represents new {@link Udmf_Visibility} param. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * @see OH_UdmfOptions Udmf_Visibility Udmf_ErrCode. + * @since 20 + */ +int OH_UdmfOptions_SetVisibility(OH_UdmfOptions* pThis, Udmf_Visibility visibility); + /** * @brief Get {@link OH_UdmfData} data from udmf database. * @@ -788,6 +958,22 @@ int OH_UdmfProperty_SetExtrasStringParam(OH_UdmfProperty* pThis, */ int OH_Udmf_GetUnifiedData(const char* key, Udmf_Intention intention, OH_UdmfData* unifiedData); +/** + * @brief Get {@link OH_UdmfData} data array from udmf database by intention. + * + * @param options Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @param dataArray Represents output params of {@link OH_UdmfData}. + * This pointer needs to be released using the {@link OH_Udmf_DestroyDataArray} function. + * @param dataSize Represents the data count of output params. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * {@link UDMF_ERR} Internal data error. + * @see OH_UdmfData Udmf_Intention Udmf_ErrCode. + * @since 20 + */ +int OH_Udmf_GetUnifiedDataByOptions(OH_UdmfOptions* options, OH_UdmfData** dataArray, unsigned int* dataSize); + /** * @brief Set {@link OH_UdmfData} data to database. * @@ -805,6 +991,63 @@ int OH_Udmf_GetUnifiedData(const char* key, Udmf_Intention intention, OH_UdmfDat int OH_Udmf_SetUnifiedData(Udmf_Intention intention, OH_UdmfData* unifiedData, char* key, unsigned int keyLen); +/** + * @brief Set {@link OH_UdmfData} data to database with options. + * + * @param options Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @param unifiedData Represents a pointer to an instance of {@link OH_UdmfData}. + * @param key Represents return value after set data to database successfully, + * it's memory size not less than {@link UDMF_KEY_BUFFER_LEN}. + * @param keyLen Represents size of key param. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * {@link UDMF_ERR} Internal data error. + * @see OH_UdmfOptions OH_UdmfData Udmf_ErrCode. + * @since 20 + */ +int OH_Udmf_SetUnifiedDataByOptions(OH_UdmfOptions* options, OH_UdmfData *unifiedData, char *key, unsigned int keyLen); + +/** + * @brief Update {@link OH_UdmfData} data to database with options. + * + * @param options Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @param unifiedData Represents a pointer to an instance of {@link OH_UdmfData}. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * {@link UDMF_ERR} Internal data error. + * @see OH_UdmfOptions OH_UdmfData Udmf_ErrCode. + * @since 20 + */ +int OH_Udmf_UpdateUnifiedData(OH_UdmfOptions* options, OH_UdmfData* unifiedData); + +/** + * @brief Delete {@link OH_UdmfData} data of database with options. + * + * @param options Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @param dataArray Represents output params of {@link OH_UdmfData}. + * This pointer needs to be released using the {@link OH_Udmf_DestroyDataArray} function. + * @param dataSize Represents the data count of output params. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * {@link UDMF_ERR} Internal data error. + * @see OH_UdmfData Udmf_Intention Udmf_ErrCode. + * @since 20 + */ +int OH_Udmf_DeleteUnifiedData(OH_UdmfOptions* options, OH_UdmfData** dataArray, unsigned int* dataSize); + +/** + * @brief Destroy data array memory. + * + * @param dataArray Represents a point to {@link OH_UdmfData}. + * @param dataSize Represents data size in list. + * @see OH_UdmfData + * @since 20 + */ +void OH_Udmf_DestroyDataArray(OH_UdmfData** dataArray, unsigned int dataSize); + /** * @brief Gets the progress from the {@OH_Udmf_ProgressInfo}. * @@ -886,6 +1129,115 @@ void OH_UdmfGetDataParams_SetProgressIndicator(OH_UdmfGetDataParams* params, void OH_UdmfGetDataParams_SetDataProgressListener(OH_UdmfGetDataParams* params, const OH_Udmf_DataProgressListener dataProgressListener); +/** + * @brief Sets the acceptable info to the {@OH_UdmfGetDataParams}. + * + * @param params Represents a pointer to an instance of {@link OH_UdmfGetDataParams}. + * @param acceptableInfo Represents a pointer to an instance of {@link OH_UdmfDataLoadInfo}. + * @see OH_UdmfGetDataParams OH_UdmfDataLoadInfo + * @since 20 + */ +void OH_UdmfGetDataParams_SetAcceptableInfo(OH_UdmfGetDataParams* params, OH_UdmfDataLoadInfo* acceptableInfo); + +/** + * @brief Creation a pointer to the instance of the {@link OH_UdmfDataLoadParams}. + * + * @return If the operation is successful, a pointer to the instance of the {@link OH_UdmfDataLoadParams} + * structure is returned. If the operation is failed, nullptr is returned. + * @see OH_UdmfDataLoadParams + * @since 20 + */ +OH_UdmfDataLoadParams* OH_UdmfDataLoadParams_Create(); + +/** + * @brief Destroy a pointer that points to an instance of {@link OH_UdmfDataLoadParams}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfDataLoadParams}. + * @see OH_UdmfDataLoadParams + * @since 20 + */ +void OH_UdmfDataLoadParams_Destroy(OH_UdmfDataLoadParams* pThis); + +/** + * @brief Sets the data load handler to the {@OH_UdmfDataLoadParams}. + * + * @param params Represents a pointer to an instance of {@link OH_UdmfDataLoadParams}. + * @param dataLoadHandler Represents to the data load handler. + * @see OH_UdmfDataLoadParams OH_Udmf_DataLoadHandler + * @since 20 + */ +void OH_UdmfDataLoadParams_SetLoadHandler(OH_UdmfDataLoadParams* params, const OH_Udmf_DataLoadHandler dataLoadHandler); + +/** + * @brief Sets the data load info to the {@OH_UdmfDataLoadParams}. + * + * @param params Represents a pointer to an instance of {@link OH_UdmfDataLoadParams}. + * @param dataLoadInfo Represents a pointer to an instance of {@link OH_UdmfDataLoadInfo}. + * @see OH_UdmfDataLoadParams OH_UdmfDataLoadInfo + * @since 20 + */ +void OH_UdmfDataLoadParams_SetDataLoadInfo(OH_UdmfDataLoadParams* params, OH_UdmfDataLoadInfo* dataLoadInfo); + +/** + * @brief Creation a pointer to the instance of the {@link OH_UdmfDataLoadInfo}. + * + * @return If the operation is successful, a pointer to the instance of the {@link OH_UdmfDataLoadInfo} + * structure is returned. If the operation is failed, nullptr is returned. + * @see OH_UdmfDataLoadInfo + * @since 20 + */ +OH_UdmfDataLoadInfo* OH_UdmfDataLoadInfo_Create(); + +/** + * @brief Destroy a pointer that points to an instance of {@link OH_UdmfDataLoadInfo}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfDataLoadInfo}. + * @see OH_UdmfDataLoadInfo + * @since 20 + */ +void OH_UdmfDataLoadInfo_Destroy(OH_UdmfDataLoadInfo* dataLoadInfo); + +/** + * @brief Gets the types from the {@OH_UdmfDataLoadInfo}. + * + * @param dataLoadInfo Represents a pointer to an instance of {@link OH_UdmfDataLoadInfo}. + * @param count the types count of data. + * @return Returns the types of data. + * @see OH_UdmfDataLoadInfo + * @since 20 + */ +char** OH_UdmfDataLoadInfo_GetTypes(OH_UdmfDataLoadInfo* dataLoadInfo, unsigned int* count); + +/** + * @brief Sets the data load info to the {@OH_UdmfDataLoadInfo}. + * + * @param dataLoadInfo Represents a pointer to an instance of {@link OH_UdmfDataLoadInfo}. + * @param types Represents the type of data. + * @see OH_UdmfDataLoadInfo + * @since 20 + */ +void OH_UdmfDataLoadInfo_SetType(OH_UdmfDataLoadInfo* dataLoadInfo, const char* type); + +/** + * @brief Gets the record count from the {@OH_UdmfDataLoadInfo}. + * + * @param dataLoadInfo Represents a pointer to an instance of {@link OH_UdmfDataLoadInfo}. + * @return Returns the record count. + * @see OH_UdmfDataLoadInfo + * @since 20 + */ +int OH_UdmfDataLoadInfo_GetRecordCount(OH_UdmfDataLoadInfo* dataLoadInfo); + +/** + * @brief Sets the record count to the {@OH_UdmfDataLoadInfo}. + * + * @param dataLoadInfo Represents a pointer to an instance of {@link OH_UdmfDataLoadInfo}. + * @param recordCount Represents the types of data. + * @see OH_UdmfDataLoadInfo + * @since 20 + */ +void OH_UdmfDataLoadInfo_SetRecordCount(OH_UdmfDataLoadInfo* dataLoadInfo, unsigned int recordCount); + #ifdef __cplusplus }; #endif diff --git a/utils_native/CMakeLists.txt b/utils_native/CMakeLists.txt index 18e577b16ff2844a50da836c3d16365c7b8c82c5..b1e80791060b61972732136e600417b20e508861 100644 --- a/utils_native/CMakeLists.txt +++ b/utils_native/CMakeLists.txt @@ -4,6 +4,7 @@ project(secure) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -fno-rtti -fvisibility=default -D_GNU_SOURCE") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections -D_GLIBC_MOCK") +add_definitions(-D__CJSON_USE_INT64) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/base/src secureSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/base/src/securec secureSrc) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/base/include) diff --git a/utils_native/base/include/cJSON.h b/utils_native/base/include/cJSON.h index 92907a2cd38b1e1f2e099e5cbe2f5c557b70b07b..e763d3acd3a359d35a5c85c43242a51d74ef54aa 100644 --- a/utils_native/base/include/cJSON.h +++ b/utils_native/base/include/cJSON.h @@ -1,11 +1,11 @@ /* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors +Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal +Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is + copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in @@ -17,15 +17,14 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ + THE SOFTWARE. + */ #ifndef cJSON__h #define cJSON__h #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif #if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) @@ -61,18 +60,18 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ #endif #if defined(CJSON_HIDE_SYMBOLS) -#define CJSON_PUBLIC(type) type CJSON_STDCALL +#define CJSON_PUBLIC(type) type CJSON_STDCALL #elif defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL +#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL #elif defined(CJSON_IMPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL +#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL #endif #else /* !__WINDOWS__ */ #define CJSON_CDECL #define CJSON_STDCALL -#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) -#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type +#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) +#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type #else #define CJSON_PUBLIC(type) type #endif @@ -81,27 +80,26 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ /* project version */ #define CJSON_VERSION_MAJOR 1 #define CJSON_VERSION_MINOR 7 -#define CJSON_VERSION_PATCH 15 +#define CJSON_VERSION_PATCH 17 #include <stddef.h> /* cJSON Types: */ #define cJSON_Invalid (0) -#define cJSON_False (1 << 0) -#define cJSON_True (1 << 1) -#define cJSON_NULL (1 << 2) +#define cJSON_False (1 << 0) +#define cJSON_True (1 << 1) +#define cJSON_NULL (1 << 2) #define cJSON_Number (1 << 3) #define cJSON_String (1 << 4) -#define cJSON_Array (1 << 5) +#define cJSON_Array (1 << 5) #define cJSON_Object (1 << 6) -#define cJSON_Raw (1 << 7) /* raw json */ +#define cJSON_Raw (1 << 7) /* raw json */ #define cJSON_IsReference 256 #define cJSON_StringIsConst 512 /* The cJSON structure: */ -typedef struct cJSON -{ +typedef struct cJSON { /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ struct cJSON *next; struct cJSON *prev; @@ -122,26 +120,25 @@ typedef struct cJSON char *string; } cJSON; -typedef struct cJSON_Hooks -{ - /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ - void *(CJSON_CDECL *malloc_fn)(size_t sz); - void (CJSON_CDECL *free_fn)(void *ptr); +typedef struct cJSON_Hooks { + /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ + void *(CJSON_CDECL *malloc_fn)(size_t sz); + void(CJSON_CDECL *free_fn)(void *ptr); } cJSON_Hooks; typedef int cJSON_bool; /* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. - * This is to prevent stack overflows. */ +* This is to prevent stack overflows. */ #ifndef CJSON_NESTING_LIMIT #define CJSON_NESTING_LIMIT 1000 #endif /* returns the version of cJSON as a string */ -CJSON_PUBLIC(const char*) cJSON_Version(void); +CJSON_PUBLIC(const char *) cJSON_Version(void); /* Supply malloc, realloc and free functions to cJSON */ -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks *hooks); /* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ /* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ @@ -149,8 +146,11 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length); /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ /* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ -CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); -CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated); +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, + cJSON_bool require_null_terminated); /* Render a cJSON entity to text for transfer/storage. */ CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); @@ -169,27 +169,27 @@ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); /* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); /* Get item "string" from object. Case insensitive. */ -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *const object, const char *const string); +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON *const object, const char *const string); CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); /* Check item type and return its value */ -CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item); -CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item); +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON *const item); +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON *const item); /* These functions check the type of an item */ -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON *const item); /* These calls create a cJSON item of the appropriate type. */ CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); @@ -204,15 +204,15 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); /* Create a string where valuestring references a string so - * it will not be freed by cJSON_Delete */ +* it will not be freed by cJSON_Delete */ CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); /* Create an object/array that only references it's elements so - * they will not be freed by cJSON_Delete */ +* they will not be freed by cJSON_Delete */ CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); /* These utilities create an Array of count items. - * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ +* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); @@ -222,15 +222,15 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int co CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. - * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before - * writing to `item->string` */ +* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before +* writing to `item->string` */ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); /* Remove/Detach items from Arrays/Objects. */ -CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item); CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); @@ -239,48 +239,58 @@ CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); /* Update array items. */ -CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); +CJSON_PUBLIC(cJSON_bool) +cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement); CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem); /* Duplicate a cJSON item */ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will - * need to be released. With recurse!=0, it will duplicate any children connected to the item. - * The item->next and ->prev pointers are always zero on return from Duplicate. */ +* need to be released. With recurse!=0, it will duplicate any children connected to the item. +* The item->next and ->prev pointers are always zero on return from Duplicate. */ /* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. - * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ -CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); +* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive); /* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings. - * The input pointer json cannot point to a read-only address area, such as a string constant, - * but should point to a readable and writable address area. */ +* The input pointer json cannot point to a read-only address area, such as a string constant, +* but should point to a readable and writable address area. */ CJSON_PUBLIC(void) cJSON_Minify(char *json); /* Helper functions for creating and adding items to an object at the same time. - * They return the added item or NULL on failure. */ -CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); -CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); -CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); -CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); -CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); +* They return the added item or NULL on failure. */ +CJSON_PUBLIC(cJSON *) cJSON_AddNullToObject(cJSON *const object, const char *const name); +CJSON_PUBLIC(cJSON *) cJSON_AddTrueToObject(cJSON *const object, const char *const name); +CJSON_PUBLIC(cJSON *) cJSON_AddFalseToObject(cJSON *const object, const char *const name); +CJSON_PUBLIC(cJSON *) cJSON_AddBoolToObject(cJSON *const object, const char *const name, const cJSON_bool boolean); +CJSON_PUBLIC(cJSON *) cJSON_AddNumberToObject(cJSON *const object, const char *const name, const double number); +CJSON_PUBLIC(cJSON *) cJSON_AddStringToObject(cJSON *const object, const char *const name, const char *const string); +CJSON_PUBLIC(cJSON *) cJSON_AddRawToObject(cJSON *const object, const char *const name, const char *const raw); +CJSON_PUBLIC(cJSON *) cJSON_AddObjectToObject(cJSON *const object, const char *const name); +CJSON_PUBLIC(cJSON *) cJSON_AddArrayToObject(cJSON *const object, const char *const name); /* When assigning an integer value, it needs to be propagated to valuedouble too. */ #define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) /* helper for the cJSON_SetNumberValue macro */ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); -#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) +#define cJSON_SetNumberValue(object, number) \ + ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) /* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */ -CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring); +CJSON_PUBLIC(char *) cJSON_SetValuestring(cJSON *object, const char *valuestring); + +/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/ +#define cJSON_SetBoolValue(object, boolValue) \ + ((object != NULL && ((object)->type & (cJSON_False | cJSON_True))) \ + ? (object)->type = ((object)->type & (~(cJSON_False | cJSON_True))) | \ + ((boolValue) ? cJSON_True : cJSON_False) \ + : cJSON_Invalid) /* Macro for iterating over an array or object */ -#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) +#define cJSON_ArrayForEach(element, array) \ + for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) /* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ CJSON_PUBLIC(void *) cJSON_malloc(size_t size); diff --git a/utils_native/base/src/cJSON.c b/utils_native/base/src/cJSON.c index 3063f74e9864b29839928800f1cfb0469ee74990..3b2b76a73c94213567d0f5ecd345c28d30941774 100644 --- a/utils_native/base/src/cJSON.c +++ b/utils_native/base/src/cJSON.c @@ -1,11 +1,11 @@ /* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors +Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal +Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is + copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in @@ -17,8 +17,8 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ + THE SOFTWARE. + */ /* cJSON */ /* JSON parser in C. */ @@ -32,25 +32,25 @@ #pragma GCC visibility push(default) #endif #if defined(_MSC_VER) -#pragma warning (push) +#pragma warning(push) /* disable warning about single line comments in system headers */ -#pragma warning (disable : 4001) +#pragma warning(disable : 4001) #endif -#include <string.h> -#include <stdio.h> -#include <math.h> -#include <stdlib.h> -#include <limits.h> #include <ctype.h> #include <float.h> +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> #ifdef ENABLE_LOCALES #include <locale.h> #endif #if defined(_MSC_VER) -#pragma warning (pop) +#pragma warning(pop) #endif #ifdef __GNUC__ #pragma GCC visibility pop @@ -81,7 +81,7 @@ #ifdef _WIN32 #define NAN sqrt(-1.0) #else -#define NAN 0.0/0.0 +#define NAN 0.0 / 0.0 #endif #endif @@ -93,35 +93,33 @@ static error global_error = { NULL, 0 }; CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) { - return (const char*) (global_error.json + global_error.position); + return (const char *)(global_error.json + global_error.position); } -CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON *const item) { - if (!cJSON_IsString(item)) - { + if (!cJSON_IsString(item)) { return NULL; } return item->valuestring; } -CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON *const item) { - if (!cJSON_IsNumber(item)) - { - return (double) NAN; + if (!cJSON_IsNumber(item)) { + return (double)NAN; } return item->valuedouble; } /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ -#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 15) - #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 17) +#error cJSON.h and cJSON.c have different versions. Make sure that both have the same. #endif -CJSON_PUBLIC(const char*) cJSON_Version(void) +CJSON_PUBLIC(const char *) cJSON_Version(void) { static char version[15]; sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); @@ -132,20 +130,16 @@ CJSON_PUBLIC(const char*) cJSON_Version(void) /* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) { - if ((string1 == NULL) || (string2 == NULL)) - { + if ((string1 == NULL) || (string2 == NULL)) { return 1; } - if (string1 == string2) - { + if (string1 == string2) { return 0; } - for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) - { - if (*string1 == '\0') - { + for (; tolower(*string1) == tolower(*string2); (void)string1++, string2++) { + if (*string1 == '\0') { return 0; } } @@ -153,16 +147,15 @@ static int case_insensitive_strcmp(const unsigned char *string1, const unsigned return tolower(*string1) - tolower(*string2); } -typedef struct internal_hooks -{ +typedef struct internal_hooks { void *(CJSON_CDECL *allocate)(size_t size); - void (CJSON_CDECL *deallocate)(void *pointer); + void(CJSON_CDECL *deallocate)(void *pointer); void *(CJSON_CDECL *reallocate)(void *pointer, size_t size); } internal_hooks; #if defined(_MSC_VER) /* work around MSVC error C2322: '...' address of dllimport '...' is not static */ -static void * CJSON_CDECL internal_malloc(size_t size) +static void *CJSON_CDECL internal_malloc(size_t size) { return malloc(size); } @@ -170,7 +163,7 @@ static void CJSON_CDECL internal_free(void *pointer) { free(pointer); } -static void * CJSON_CDECL internal_realloc(void *pointer, size_t size) +static void *CJSON_CDECL internal_realloc(void *pointer, size_t size) { return realloc(pointer, size); } @@ -185,20 +178,18 @@ static void * CJSON_CDECL internal_realloc(void *pointer, size_t size) static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; -static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) +static unsigned char *cJSON_strdup(const unsigned char *string, const internal_hooks *const hooks) { size_t length = 0; unsigned char *copy = NULL; - if (string == NULL) - { + if (string == NULL) { return NULL; } - length = strlen((const char*)string) + sizeof(""); - copy = (unsigned char*)hooks->allocate(length); - if (copy == NULL) - { + length = strlen((const char *)string) + sizeof(""); + copy = (unsigned char *)hooks->allocate(length); + if (copy == NULL) { return NULL; } memcpy(copy, string, length); @@ -206,10 +197,9 @@ static unsigned char* cJSON_strdup(const unsigned char* string, const internal_h return copy; } -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks *hooks) { - if (hooks == NULL) - { + if (hooks == NULL) { /* Reset hooks */ global_hooks.allocate = malloc; global_hooks.deallocate = free; @@ -218,31 +208,27 @@ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) } global_hooks.allocate = malloc; - if (hooks->malloc_fn != NULL) - { + if (hooks->malloc_fn != NULL) { global_hooks.allocate = hooks->malloc_fn; } global_hooks.deallocate = free; - if (hooks->free_fn != NULL) - { + if (hooks->free_fn != NULL) { global_hooks.deallocate = hooks->free_fn; } /* use realloc only if both free and malloc are used */ global_hooks.reallocate = NULL; - if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) - { + if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) { global_hooks.reallocate = realloc; } } /* Internal constructor. */ -static cJSON *cJSON_New_Item(const internal_hooks * const hooks) +static cJSON *cJSON_New_Item(const internal_hooks *const hooks) { - cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); - if (node) - { + cJSON *node = (cJSON *)hooks->allocate(sizeof(cJSON)); + if (node) { memset(node, '\0', sizeof(cJSON)); } @@ -253,20 +239,21 @@ static cJSON *cJSON_New_Item(const internal_hooks * const hooks) CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) { cJSON *next = NULL; - while (item != NULL) - { + while (item != NULL) { next = item->next; - if (!(item->type & cJSON_IsReference) && (item->child != NULL)) - { + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) { cJSON_Delete(item->child); } - if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) - { + if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) { global_hooks.deallocate(item->valuestring); + item->valuestring = NULL; } - if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) - { + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { global_hooks.deallocate(item->string); + item->string = NULL; + } + if (next == item) { + break; } global_hooks.deallocate(item); item = next; @@ -278,14 +265,13 @@ static unsigned char get_decimal_point(void) { #ifdef ENABLE_LOCALES struct lconv *lconv = localeconv(); - return (unsigned char) lconv->decimal_point[0]; + return (unsigned char)lconv->decimal_point[0]; #else return '.'; #endif } -typedef struct -{ +typedef struct { const unsigned char *content; size_t length; size_t offset; @@ -302,26 +288,25 @@ typedef struct #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) /* Parse the input text to generate a number, and populate the result into item. */ -static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) +static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) { double number = 0; unsigned char *after_end = NULL; - unsigned char number_c_string[64]; + unsigned char *number_c_string; unsigned char decimal_point = get_decimal_point(); size_t i = 0; + size_t number_string_length = 0; + cJSON_bool has_decimal_point = false; - if ((input_buffer == NULL) || (input_buffer->content == NULL)) - { + if ((input_buffer == NULL) || (input_buffer->content == NULL)) { return false; } /* copy the number into a temporary buffer and replace '.' with the decimal point - * of the current locale (for strtod) - * This also takes care of '\0' not necessarily being available for marking the end of the input */ - for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) - { - switch (buffer_at_offset(input_buffer)[i]) - { + * of the current locale (for strtod) + * This also takes care of '\0' not necessarily being available for marking the end of the input */ + for (i = 0; can_access_at_index(input_buffer, i); i++) { + switch (buffer_at_offset(input_buffer)[i]) { case '0': case '1': case '2': @@ -336,11 +321,12 @@ static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_bu case '-': case 'e': case 'E': - number_c_string[i] = buffer_at_offset(input_buffer)[i]; + number_string_length++; break; case '.': - number_c_string[i] = decimal_point; + number_string_length++; + has_decimal_point = true; break; default: @@ -348,75 +334,85 @@ static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_bu } } loop_end: + /* malloc for temporary buffer, add 1 for '\0' */ + number_c_string = (unsigned char *)input_buffer->hooks.allocate(number_string_length + 1); + if (number_c_string == NULL) { + return false; /* allocation failure */ + } + + memcpy(number_c_string, buffer_at_offset(input_buffer), number_string_length); + number_c_string[number_string_length] = '\0'; + + if (has_decimal_point) { + for (i = 0; i < number_string_length; i++) { + if (number_c_string[i] == '.') { + /* replace '.' with the decimal point of the current locale (for strtod) */ + number_c_string[i] = decimal_point; + } + } + } number_c_string[i] = '\0'; - number = strtod((const char*)number_c_string, (char**)&after_end); - if (number_c_string == after_end) - { + number = strtod((const char *)number_c_string, (char **)&after_end); + if (number_c_string == after_end) { + /* free the temporary buffer */ + input_buffer->hooks.deallocate(number_c_string); return false; /* parse_error */ } item->valuedouble = number; /* use saturation in case of overflow */ - if (number >= INT_MAX) - { + if (number >= INT_MAX) { item->valueint = INT_MAX; - } - else if (number <= (double)INT_MIN) - { + } else if (number <= (double)INT_MIN) { item->valueint = INT_MIN; - } - else - { + } else { item->valueint = (int)number; } item->type = cJSON_Number; input_buffer->offset += (size_t)(after_end - number_c_string); + /* free the temporary buffer */ + input_buffer->hooks.deallocate(number_c_string); return true; } /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) { - if (number >= INT_MAX) - { + if (number >= INT_MAX) { object->valueint = INT_MAX; - } - else if (number <= (double)INT_MIN) - { + } else if (number <= (double)INT_MIN) { object->valueint = INT_MIN; - } - else - { + } else { object->valueint = (int)number; } return object->valuedouble = number; } -CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring) +CJSON_PUBLIC(char *) cJSON_SetValuestring(cJSON *object, const char *valuestring) { char *copy = NULL; /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */ - if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference)) - { + if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference)) { return NULL; } - if (strlen(valuestring) <= strlen(object->valuestring)) - { + /* return NULL if the object is corrupted */ + if (object->valuestring == NULL || valuestring == NULL) { + return NULL; + } + if (strlen(valuestring) <= strlen(object->valuestring)) { strcpy(object->valuestring, valuestring); return object->valuestring; } - copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks); - if (copy == NULL) - { + copy = (char *)cJSON_strdup((const unsigned char *)valuestring, &global_hooks); + if (copy == NULL) { return NULL; } - if (object->valuestring != NULL) - { + if (object->valuestring != NULL) { cJSON_free(object->valuestring); } object->valuestring = copy; @@ -424,8 +420,7 @@ CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring) return copy; } -typedef struct -{ +typedef struct { unsigned char *buffer; size_t length; size_t offset; @@ -436,31 +431,27 @@ typedef struct } printbuffer; /* realloc printbuffer if necessary to have at least "needed" bytes more */ -static unsigned char* ensure(printbuffer * const p, size_t needed) +static unsigned char *ensure(printbuffer *const p, size_t needed) { unsigned char *newbuffer = NULL; size_t newsize = 0; - if ((p == NULL) || (p->buffer == NULL)) - { + if ((p == NULL) || (p->buffer == NULL)) { return NULL; } - if ((p->length > 0) && (p->offset >= p->length)) - { + if ((p->length > 0) && (p->offset >= p->length)) { /* make sure that offset is valid */ return NULL; } - if (needed > INT_MAX) - { + if (needed > INT_MAX) { /* sizes bigger than INT_MAX are currently not supported */ return NULL; } needed += p->offset + 1; - if (needed <= p->length) - { + if (needed <= p->length) { return p->buffer + p->offset; } @@ -469,49 +460,38 @@ static unsigned char* ensure(printbuffer * const p, size_t needed) } /* calculate new buffer size */ - if (needed > (INT_MAX / 2)) - { + if (needed > (INT_MAX / 2)) { /* overflow of int, use INT_MAX if possible */ - if (needed <= INT_MAX) - { + if (needed <= INT_MAX) { newsize = INT_MAX; - } - else - { + } else { return NULL; } - } - else - { + } else { newsize = needed * 2; } - if (p->hooks.reallocate != NULL) - { + if (p->hooks.reallocate != NULL) { /* reallocate with realloc if available */ - newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); - if (newbuffer == NULL) - { + newbuffer = (unsigned char *)p->hooks.reallocate(p->buffer, newsize); + if (newbuffer == NULL) { p->hooks.deallocate(p->buffer); p->length = 0; p->buffer = NULL; return NULL; } - } - else - { + } else { /* otherwise reallocate manually */ - newbuffer = (unsigned char*)p->hooks.allocate(newsize); - if (!newbuffer) - { + newbuffer = (unsigned char *)p->hooks.allocate(newsize); + if (!newbuffer) { p->hooks.deallocate(p->buffer); p->length = 0; p->buffer = NULL; return NULL; } - + memcpy(newbuffer, p->buffer, p->offset + 1); p->hooks.deallocate(p->buffer); } @@ -522,16 +502,15 @@ static unsigned char* ensure(printbuffer * const p, size_t needed) } /* calculate the new length of the string in a printbuffer and update the offset */ -static void update_offset(printbuffer * const buffer) +static void update_offset(printbuffer *const buffer) { const unsigned char *buffer_pointer = NULL; - if ((buffer == NULL) || (buffer->buffer == NULL)) - { + if ((buffer == NULL) || (buffer->buffer == NULL)) { return; } buffer_pointer = buffer->buffer + buffer->offset; - buffer->offset += strlen((const char*)buffer_pointer); + buffer->offset += strlen((const char *)buffer_pointer); } /* securely comparison of floating-point variables */ @@ -542,58 +521,51 @@ static cJSON_bool compare_double(double a, double b) } /* Render the number nicely from the given item into a string. */ -static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) +static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer) { unsigned char *output_pointer = NULL; double d = item->valuedouble; int length = 0; size_t i = 0; - unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */ + unsigned char number_buffer[26] = { 0 }; /* temporary buffer to print the number into */ unsigned char decimal_point = get_decimal_point(); double test = 0.0; - if (output_buffer == NULL) - { + if (output_buffer == NULL) { return false; } /* This checks for NaN and Infinity */ - if (isnan(d) || isinf(d)) - { - length = sprintf((char*)number_buffer, "null"); - } - else - { + if (isnan(d) || isinf(d)) { + length = sprintf((char *)number_buffer, "null"); + } else if (d == (double)item->valueint) { + length = sprintf((char *)number_buffer, "%d", item->valueint); + } else { /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ - length = sprintf((char*)number_buffer, "%1.15g", d); + length = sprintf((char *)number_buffer, "%1.15g", d); /* Check whether the original double can be recovered */ - if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) - { + if ((sscanf((char *)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) { /* If not, print with 17 decimal places of precision */ - length = sprintf((char*)number_buffer, "%1.17g", d); + length = sprintf((char *)number_buffer, "%1.17g", d); } } /* sprintf failed or buffer overrun occurred */ - if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) - { + if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) { return false; } /* reserve appropriate space in the output */ output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } /* copy the printed number to the output and replace locale - * dependent decimal point with '.' */ - for (i = 0; i < ((size_t)length); i++) - { - if (number_buffer[i] == decimal_point) - { + * dependent decimal point with '.' */ + for (i = 0; i < ((size_t)length); i++) { + if (number_buffer[i] == decimal_point) { output_pointer[i] = '.'; continue; } @@ -608,33 +580,25 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out } /* parse 4 digit hexadecimal number */ -static unsigned parse_hex4(const unsigned char * const input) +static unsigned parse_hex4(const unsigned char *const input) { unsigned int h = 0; size_t i = 0; - for (i = 0; i < 4; i++) - { + for (i = 0; i < 4; i++) { /* parse digit */ - if ((input[i] >= '0') && (input[i] <= '9')) - { - h += (unsigned int) input[i] - '0'; - } - else if ((input[i] >= 'A') && (input[i] <= 'F')) - { - h += (unsigned int) 10 + input[i] - 'A'; - } - else if ((input[i] >= 'a') && (input[i] <= 'f')) - { - h += (unsigned int) 10 + input[i] - 'a'; - } - else /* invalid */ + if ((input[i] >= '0') && (input[i] <= '9')) { + h += (unsigned int)input[i] - '0'; + } else if ((input[i] >= 'A') && (input[i] <= 'F')) { + h += (unsigned int)10 + input[i] - 'A'; + } else if ((input[i] >= 'a') && (input[i] <= 'f')) { + h += (unsigned int)10 + input[i] - 'a'; + } else /* invalid */ { return 0; } - if (i < 3) - { + if (i < 3) { /* shift left to make place for the next nibble */ h = h << 4; } @@ -644,8 +608,9 @@ static unsigned parse_hex4(const unsigned char * const input) } /* converts a UTF-16 literal to UTF-8 - * A literal can be one or two sequences of the form \uXXXX */ -static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) +* A literal can be one or two sequences of the form \uXXXX */ +static unsigned char utf16_literal_to_utf8(const unsigned char *const input_pointer, + const unsigned char *const input_end, unsigned char **output_pointer) { long unsigned int codepoint = 0; unsigned int first_code = 0; @@ -655,8 +620,7 @@ static unsigned char utf16_literal_to_utf8(const unsigned char * const input_poi unsigned char sequence_length = 0; unsigned char first_byte_mark = 0; - if ((input_end - first_sequence) < 6) - { + if ((input_end - first_sequence) < 6) { /* input ends unexpectedly */ goto fail; } @@ -665,26 +629,22 @@ static unsigned char utf16_literal_to_utf8(const unsigned char * const input_poi first_code = parse_hex4(first_sequence + 2); /* check that the code is valid */ - if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) - { + if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) { goto fail; } /* UTF16 surrogate pair */ - if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) - { + if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) { const unsigned char *second_sequence = first_sequence + 6; unsigned int second_code = 0; sequence_length = 12; /* \uXXXX\uXXXX */ - if ((input_end - second_sequence) < 6) - { + if ((input_end - second_sequence) < 6) { /* input ends unexpectedly */ goto fail; } - if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) - { + if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) { /* missing second half of the surrogate pair */ goto fail; } @@ -692,68 +652,51 @@ static unsigned char utf16_literal_to_utf8(const unsigned char * const input_poi /* get the second utf16 sequence */ second_code = parse_hex4(second_sequence + 2); /* check that the code is valid */ - if ((second_code < 0xDC00) || (second_code > 0xDFFF)) - { + if ((second_code < 0xDC00) || (second_code > 0xDFFF)) { /* invalid second half of the surrogate pair */ goto fail; } - /* calculate the unicode codepoint from the surrogate pair */ codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); - } - else - { + } else { sequence_length = 6; /* \uXXXX */ codepoint = first_code; } /* encode as UTF-8 - * takes at maximum 4 bytes to encode: - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ - if (codepoint < 0x80) - { + * takes at maximum 4 bytes to encode: + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + if (codepoint < 0x80) { /* normal ascii, encoding 0xxxxxxx */ utf8_length = 1; - } - else if (codepoint < 0x800) - { + } else if (codepoint < 0x800) { /* two bytes, encoding 110xxxxx 10xxxxxx */ utf8_length = 2; first_byte_mark = 0xC0; /* 11000000 */ - } - else if (codepoint < 0x10000) - { + } else if (codepoint < 0x10000) { /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ utf8_length = 3; first_byte_mark = 0xE0; /* 11100000 */ - } - else if (codepoint <= 0x10FFFF) - { + } else if (codepoint <= 0x10FFFF) { /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ utf8_length = 4; first_byte_mark = 0xF0; /* 11110000 */ - } - else - { + } else { /* invalid unicode codepoint */ goto fail; } /* encode as utf8 */ - for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) - { + for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) { /* 10xxxxxx */ (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); codepoint >>= 6; } /* encode first byte */ - if (utf8_length > 1) - { + if (utf8_length > 1) { (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); - } - else - { + } else { (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); } @@ -766,7 +709,7 @@ fail: } /* Parse the input text into an unescaped cinput, and populate item. */ -static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) +static cJSON_bool parse_string(cJSON *const item, parse_buffer *const input_buffer) { const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; @@ -774,8 +717,7 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu unsigned char *output = NULL; /* not a string */ - if (buffer_at_offset(input_buffer)[0] != '\"') - { + if (buffer_at_offset(input_buffer)[0] != '\"') { goto fail; } @@ -783,13 +725,10 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu /* calculate approximate size of the output (overestimate) */ size_t allocation_length = 0; size_t skipped_bytes = 0; - while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) - { + while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) { /* is escape sequence */ - if (input_end[0] == '\\') - { - if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) - { + if (input_end[0] == '\\') { + if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) { /* prevent buffer overflow when last input character is a backslash */ goto fail; } @@ -798,39 +737,32 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu } input_end++; } - if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) - { + if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) { goto fail; /* string ended unexpectedly */ } /* This is at most how much we need for the output */ - allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; - output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); - if (output == NULL) - { + allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes; + output = (unsigned char *)input_buffer->hooks.allocate(allocation_length + sizeof("")); + if (output == NULL) { goto fail; /* allocation failure */ } } output_pointer = output; /* loop through the string literal */ - while (input_pointer < input_end) - { - if (*input_pointer != '\\') - { + while (input_pointer < input_end) { + if (*input_pointer != '\\') { *output_pointer++ = *input_pointer++; } /* escape sequence */ - else - { + else { unsigned char sequence_length = 2; - if ((input_end - input_pointer) < 1) - { + if ((input_end - input_pointer) < 1) { goto fail; } - switch (input_pointer[1]) - { + switch (input_pointer[1]) { case 'b': *output_pointer++ = '\b'; break; @@ -855,8 +787,7 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu /* UTF-16 literal */ case 'u': sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); - if (sequence_length == 0) - { + if (sequence_length == 0) { /* failed to convert UTF16-literal to UTF-8 */ goto fail; } @@ -873,21 +804,19 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu *output_pointer = '\0'; item->type = cJSON_String; - item->valuestring = (char*)output; + item->valuestring = (char *)output; - input_buffer->offset = (size_t) (input_end - input_buffer->content); + input_buffer->offset = (size_t)(input_end - input_buffer->content); input_buffer->offset++; return true; fail: - if (output != NULL) - { + if (output != NULL) { input_buffer->hooks.deallocate(output); } - if (input_pointer != NULL) - { + if (input_pointer != NULL) { input_buffer->offset = (size_t)(input_pointer - input_buffer->content); } @@ -895,7 +824,7 @@ fail: } /* Render the cstring provided to an escaped version that can be printed. */ -static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) +static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer) { const unsigned char *input_pointer = NULL; unsigned char *output = NULL; @@ -904,29 +833,24 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe /* numbers of additional characters needed for escaping */ size_t escape_characters = 0; - if (output_buffer == NULL) - { + if (output_buffer == NULL) { return false; } /* empty string */ - if (input == NULL) - { + if (input == NULL) { output = ensure(output_buffer, sizeof("\"\"")); - if (output == NULL) - { + if (output == NULL) { return false; } - strcpy((char*)output, "\"\""); + strcpy((char *)output, "\"\""); return true; } /* set "flag" to 1 if something needs to be escaped */ - for (input_pointer = input; *input_pointer; input_pointer++) - { - switch (*input_pointer) - { + for (input_pointer = input; *input_pointer; input_pointer++) { + switch (*input_pointer) { case '\"': case '\\': case '\b': @@ -938,8 +862,7 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe escape_characters++; break; default: - if (*input_pointer < 32) - { + if (*input_pointer < 32) { /* UTF-16 escape sequence uXXXX */ escape_characters += 5; } @@ -949,14 +872,12 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe output_length = (size_t)(input_pointer - input) + escape_characters; output = ensure(output_buffer, output_length + sizeof("\"\"")); - if (output == NULL) - { + if (output == NULL) { return false; } /* no characters have to be escaped */ - if (escape_characters == 0) - { + if (escape_characters == 0) { output[0] = '\"'; memcpy(output + 1, input, output_length); output[output_length + 1] = '\"'; @@ -968,19 +889,14 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe output[0] = '\"'; output_pointer = output + 1; /* copy the string */ - for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) - { - if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) - { + for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) { + if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) { /* normal character, copy */ *output_pointer = *input_pointer; - } - else - { + } else { /* character needs to be escaped */ *output_pointer++ = '\\'; - switch (*input_pointer) - { + switch (*input_pointer) { case '\\': *output_pointer = '\\'; break; @@ -1004,7 +920,7 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe break; default: /* escape and print as unicode codepoint */ - sprintf((char*)output_pointer, "u%04x", *input_pointer); + sprintf((char *)output_pointer, "u%04x", *input_pointer); output_pointer += 4; break; } @@ -1017,39 +933,35 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe } /* Invoke print_string_ptr (which is useful) on an item. */ -static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) +static cJSON_bool print_string(const cJSON *const item, printbuffer *const p) { - return print_string_ptr((unsigned char*)item->valuestring, p); + return print_string_ptr((unsigned char *)item->valuestring, p); } /* Predeclare these prototypes. */ -static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); -static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); -static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer); +static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer); +static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer); +static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer); +static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer); +static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer); /* Utility to jump whitespace and cr/lf */ -static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) +static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) { - if ((buffer == NULL) || (buffer->content == NULL)) - { + if ((buffer == NULL) || (buffer->content == NULL)) { return NULL; } - if (cannot_access_at_index(buffer, 0)) - { + if (cannot_access_at_index(buffer, 0)) { return buffer; } - while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) - { - buffer->offset++; + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) { + buffer->offset++; } - if (buffer->offset == buffer->length) - { + if (buffer->offset == buffer->length) { buffer->offset--; } @@ -1057,27 +969,25 @@ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) } /* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ -static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) +static parse_buffer *skip_utf8_bom(parse_buffer *const buffer) { - if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) - { + if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) { return NULL; } - if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) - { + if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) { buffer->offset += 3; } return buffer; } -CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) { size_t buffer_length; - if (NULL == value) - { + if (NULL == value) { return NULL; } @@ -1088,7 +998,9 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return } /* Parse an object - create a new root, and populate. */ -CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated) +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, + cJSON_bool require_null_terminated) { parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; cJSON *item = NULL; @@ -1097,13 +1009,12 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer global_error.json = NULL; global_error.position = 0; - if (value == NULL || 0 == buffer_length) - { + if (value == NULL || 0 == buffer_length) { goto fail; } - buffer.content = (const unsigned char*)value; - buffer.length = buffer_length; + buffer.content = (const unsigned char *)value; + buffer.length = buffer_length; buffer.offset = 0; buffer.hooks = global_hooks; @@ -1113,52 +1024,42 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer goto fail; } - if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) - { + if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) { /* parse failure. ep is set. */ goto fail; } /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ - if (require_null_terminated) - { + if (require_null_terminated) { buffer_skip_whitespace(&buffer); - if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') - { + if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') { goto fail; } } - if (return_parse_end) - { - *return_parse_end = (const char*)buffer_at_offset(&buffer); + if (return_parse_end) { + *return_parse_end = (const char *)buffer_at_offset(&buffer); } return item; fail: - if (item != NULL) - { + if (item != NULL) { cJSON_Delete(item); } - if (value != NULL) - { + if (value != NULL) { error local_error; - local_error.json = (const unsigned char*)value; + local_error.json = (const unsigned char *)value; local_error.position = 0; - if (buffer.offset < buffer.length) - { + if (buffer.offset < buffer.length) { local_error.position = buffer.offset; - } - else if (buffer.length > 0) - { + } else if (buffer.length > 0) { local_error.position = buffer.length - 1; } - if (return_parse_end != NULL) - { - *return_parse_end = (const char*)local_error.json + local_error.position; + if (return_parse_end != NULL) { + *return_parse_end = (const char *)local_error.json + local_error.position; } global_error = local_error; @@ -1180,7 +1081,7 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_len #define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) -static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) +static unsigned char *print(const cJSON *const item, cJSON_bool format, const internal_hooks *const hooks) { static const size_t default_buffer_size = 256; printbuffer buffer[1]; @@ -1189,36 +1090,31 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i memset(buffer, 0, sizeof(buffer)); /* create buffer */ - buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); + buffer->buffer = (unsigned char *)hooks->allocate(default_buffer_size); buffer->length = default_buffer_size; buffer->format = format; buffer->hooks = *hooks; - if (buffer->buffer == NULL) - { + if (buffer->buffer == NULL) { goto fail; } /* print the value */ - if (!print_value(item, buffer)) - { + if (!print_value(item, buffer)) { goto fail; } update_offset(buffer); /* check if reallocate is available */ - if (hooks->reallocate != NULL) - { - printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); + if (hooks->reallocate != NULL) { + printed = (unsigned char *)hooks->reallocate(buffer->buffer, buffer->offset + 1); if (printed == NULL) { goto fail; } buffer->buffer = NULL; - } - else /* otherwise copy the JSON over to a new buffer */ + } else /* otherwise copy the JSON over to a new buffer */ { - printed = (unsigned char*) hooks->allocate(buffer->offset + 1); - if (printed == NULL) - { + printed = (unsigned char *)hooks->allocate(buffer->offset + 1); + if (printed == NULL) { goto fail; } memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); @@ -1231,13 +1127,11 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i return printed; fail: - if (buffer->buffer != NULL) - { + if (buffer->buffer != NULL) { hooks->deallocate(buffer->buffer); } - if (printed != NULL) - { + if (printed != NULL) { hooks->deallocate(printed); } @@ -1247,26 +1141,24 @@ fail: /* Render a cJSON item/entity/structure to text. */ CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) { - return (char*)print(item, true, &global_hooks); + return (char *)print(item, true, &global_hooks); } CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) { - return (char*)print(item, false, &global_hooks); + return (char *)print(item, false, &global_hooks); } CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) { printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - if (prebuffer < 0) - { + if (prebuffer < 0) { return NULL; } - p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); - if (!p.buffer) - { + p.buffer = (unsigned char *)global_hooks.allocate((size_t)prebuffer); + if (!p.buffer) { return NULL; } @@ -1276,25 +1168,23 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON p.format = fmt; p.hooks = global_hooks; - if (!print_value(item, &p)) - { + if (!print_value(item, &p)) { global_hooks.deallocate(p.buffer); return NULL; } - return (char*)p.buffer; + return (char *)p.buffer; } CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) { printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - if ((length < 0) || (buffer == NULL)) - { + if ((length < 0) || (buffer == NULL)) { return false; } - p.buffer = (unsigned char*)buffer; + p.buffer = (unsigned char *)buffer; p.length = (size_t)length; p.offset = 0; p.noalloc = true; @@ -1305,54 +1195,48 @@ CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, cons } /* Parser core - when encountering text, process appropriately. */ -static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) +static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer) { - if ((input_buffer == NULL) || (input_buffer->content == NULL)) - { + if ((input_buffer == NULL) || (input_buffer->content == NULL)) { return false; /* no input */ } /* parse the different types of values */ /* null */ - if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) - { + if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) { item->type = cJSON_NULL; input_buffer->offset += 4; return true; } /* false */ - if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) - { + if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) { item->type = cJSON_False; input_buffer->offset += 5; return true; } /* true */ - if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) - { + if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) { item->type = cJSON_True; item->valueint = 1; input_buffer->offset += 4; return true; } /* string */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) - { + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) { return parse_string(item, input_buffer); } /* number */ - if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) - { + if (can_access_at_index(input_buffer, 0) && + ((buffer_at_offset(input_buffer)[0] == '-') || + ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) { return parse_number(item, input_buffer); } /* array */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) - { + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) { return parse_array(item, input_buffer); } /* object */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) - { + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) { return parse_object(item, input_buffer); } @@ -1360,59 +1244,51 @@ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buf } /* Render a value to text. */ -static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) +static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer) { unsigned char *output = NULL; - if ((item == NULL) || (output_buffer == NULL)) - { + if ((item == NULL) || (output_buffer == NULL)) { return false; } - switch ((item->type) & 0xFF) - { + switch ((item->type) & 0xFF) { case cJSON_NULL: output = ensure(output_buffer, 5); - if (output == NULL) - { + if (output == NULL) { return false; } - strcpy((char*)output, "null"); + strcpy((char *)output, "null"); return true; case cJSON_False: output = ensure(output_buffer, 6); - if (output == NULL) - { + if (output == NULL) { return false; } - strcpy((char*)output, "false"); + strcpy((char *)output, "false"); return true; case cJSON_True: output = ensure(output_buffer, 5); - if (output == NULL) - { + if (output == NULL) { return false; } - strcpy((char*)output, "true"); + strcpy((char *)output, "true"); return true; case cJSON_Number: return print_number(item, output_buffer); - case cJSON_Raw: - { + case cJSON_Raw: { size_t raw_length = 0; - if (item->valuestring == NULL) - { + if (item->valuestring == NULL) { return false; } raw_length = strlen(item->valuestring) + sizeof(""); output = ensure(output_buffer, raw_length); - if (output == NULL) - { + if (output == NULL) { return false; } memcpy(output, item->valuestring, raw_length); @@ -1434,34 +1310,30 @@ static cJSON_bool print_value(const cJSON * const item, printbuffer * const outp } /* Build an array from input text. */ -static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) +static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer) { cJSON *head = NULL; /* head of the linked list */ cJSON *current_item = NULL; - if (input_buffer->depth >= CJSON_NESTING_LIMIT) - { + if (input_buffer->depth >= CJSON_NESTING_LIMIT) { return false; /* to deeply nested */ } input_buffer->depth++; - if (buffer_at_offset(input_buffer)[0] != '[') - { + if (buffer_at_offset(input_buffer)[0] != '[') { /* not an array */ goto fail; } input_buffer->offset++; buffer_skip_whitespace(input_buffer); - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) - { + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) { /* empty array */ goto success; } /* check if we skipped to the end of the buffer */ - if (cannot_access_at_index(input_buffer, 0)) - { + if (cannot_access_at_index(input_buffer, 0)) { input_buffer->offset--; goto fail; } @@ -1469,23 +1341,18 @@ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buf /* step back to character in front of the first element */ input_buffer->offset--; /* loop through the comma separated array elements */ - do - { + do { /* allocate next item */ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); - if (new_item == NULL) - { + if (new_item == NULL) { goto fail; /* allocation failure */ } /* attach next item to list */ - if (head == NULL) - { + if (head == NULL) { /* start the linked list */ current_item = head = new_item; - } - else - { + } else { /* add to the end and advance */ current_item->next = new_item; new_item->prev = current_item; @@ -1495,16 +1362,13 @@ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buf /* parse next value */ input_buffer->offset++; buffer_skip_whitespace(input_buffer); - if (!parse_value(current_item, input_buffer)) - { + if (!parse_value(current_item, input_buffer)) { goto fail; /* failed to parse value */ } buffer_skip_whitespace(input_buffer); - } - while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); - if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') - { + if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') { goto fail; /* expected end of array */ } @@ -1523,8 +1387,7 @@ success: return true; fail: - if (head != NULL) - { + if (head != NULL) { cJSON_Delete(head); } @@ -1532,22 +1395,20 @@ fail: } /* Render an array to text */ -static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) +static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer) { unsigned char *output_pointer = NULL; size_t length = 0; cJSON *current_element = item->child; - if (output_buffer == NULL) - { + if (output_buffer == NULL) { return false; } /* Compose the output array. */ /* opening square bracket */ output_pointer = ensure(output_buffer, 1); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } @@ -1555,24 +1416,19 @@ static cJSON_bool print_array(const cJSON * const item, printbuffer * const outp output_buffer->offset++; output_buffer->depth++; - while (current_element != NULL) - { - if (!print_value(current_element, output_buffer)) - { + while (current_element != NULL) { + if (!print_value(current_element, output_buffer)) { return false; } update_offset(output_buffer); - if (current_element->next) - { - length = (size_t) (output_buffer->format ? 2 : 1); + if (current_element->next) { + length = (size_t)(output_buffer->format ? 2 : 1); output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } *output_pointer++ = ','; - if(output_buffer->format) - { + if (output_buffer->format) { *output_pointer++ = ' '; } *output_pointer = '\0'; @@ -1582,8 +1438,7 @@ static cJSON_bool print_array(const cJSON * const item, printbuffer * const outp } output_pointer = ensure(output_buffer, 2); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } *output_pointer++ = ']'; @@ -1594,32 +1449,28 @@ static cJSON_bool print_array(const cJSON * const item, printbuffer * const outp } /* Build an object from the text. */ -static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) +static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer) { cJSON *head = NULL; /* linked list head */ cJSON *current_item = NULL; - if (input_buffer->depth >= CJSON_NESTING_LIMIT) - { + if (input_buffer->depth >= CJSON_NESTING_LIMIT) { return false; /* to deeply nested */ } input_buffer->depth++; - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) - { + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) { goto fail; /* not an object */ } input_buffer->offset++; buffer_skip_whitespace(input_buffer); - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) - { + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) { goto success; /* empty object */ } /* check if we skipped to the end of the buffer */ - if (cannot_access_at_index(input_buffer, 0)) - { + if (cannot_access_at_index(input_buffer, 0)) { input_buffer->offset--; goto fail; } @@ -1627,34 +1478,32 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu /* step back to character in front of the first element */ input_buffer->offset--; /* loop through the comma separated array elements */ - do - { + do { /* allocate next item */ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); - if (new_item == NULL) - { + if (new_item == NULL) { goto fail; /* allocation failure */ } /* attach next item to list */ - if (head == NULL) - { + if (head == NULL) { /* start the linked list */ current_item = head = new_item; - } - else - { + } else { /* add to the end and advance */ current_item->next = new_item; new_item->prev = current_item; current_item = new_item; } + if (cannot_access_at_index(input_buffer, 1)) { + goto fail; /* nothing comes after the comma */ + } + /* parse the name of the child */ input_buffer->offset++; buffer_skip_whitespace(input_buffer); - if (!parse_string(current_item, input_buffer)) - { + if (!parse_string(current_item, input_buffer)) { goto fail; /* failed to parse name */ } buffer_skip_whitespace(input_buffer); @@ -1663,24 +1512,20 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu current_item->string = current_item->valuestring; current_item->valuestring = NULL; - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) - { + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) { goto fail; /* invalid object */ } /* parse the value */ input_buffer->offset++; buffer_skip_whitespace(input_buffer); - if (!parse_value(current_item, input_buffer)) - { + if (!parse_value(current_item, input_buffer)) { goto fail; /* failed to parse value */ } buffer_skip_whitespace(input_buffer); - } - while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) - { + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) { goto fail; /* expected end of object */ } @@ -1698,8 +1543,7 @@ success: return true; fail: - if (head != NULL) - { + if (head != NULL) { cJSON_Delete(head); } @@ -1707,73 +1551,62 @@ fail: } /* Render an object to text. */ -static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) +static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer) { unsigned char *output_pointer = NULL; size_t length = 0; cJSON *current_item = item->child; - if (output_buffer == NULL) - { + if (output_buffer == NULL) { return false; } /* Compose the output: */ - length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ + length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */ output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } *output_pointer++ = '{'; output_buffer->depth++; - if (output_buffer->format) - { + if (output_buffer->format) { *output_pointer++ = '\n'; } output_buffer->offset += length; - while (current_item) - { - if (output_buffer->format) - { + while (current_item) { + if (output_buffer->format) { size_t i; output_pointer = ensure(output_buffer, output_buffer->depth); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } - for (i = 0; i < output_buffer->depth; i++) - { + for (i = 0; i < output_buffer->depth; i++) { *output_pointer++ = '\t'; } output_buffer->offset += output_buffer->depth; } /* print key */ - if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) - { + if (!print_string_ptr((unsigned char *)current_item->string, output_buffer)) { return false; } update_offset(output_buffer); - length = (size_t) (output_buffer->format ? 2 : 1); + length = (size_t)(output_buffer->format ? 2 : 1); output_pointer = ensure(output_buffer, length); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } *output_pointer++ = ':'; - if (output_buffer->format) - { + if (output_buffer->format) { *output_pointer++ = '\t'; } output_buffer->offset += length; /* print value */ - if (!print_value(current_item, output_buffer)) - { + if (!print_value(current_item, output_buffer)) { return false; } update_offset(output_buffer); @@ -1781,17 +1614,14 @@ static cJSON_bool print_object(const cJSON * const item, printbuffer * const out /* print comma if not last */ length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0)); output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } - if (current_item->next) - { + if (current_item->next) { *output_pointer++ = ','; } - if (output_buffer->format) - { + if (output_buffer->format) { *output_pointer++ = '\n'; } *output_pointer = '\0'; @@ -1801,15 +1631,12 @@ static cJSON_bool print_object(const cJSON * const item, printbuffer * const out } output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } - if (output_buffer->format) - { + if (output_buffer->format) { size_t i; - for (i = 0; i < (output_buffer->depth - 1); i++) - { + for (i = 0; i < (output_buffer->depth - 1); i++) { *output_pointer++ = '\t'; } } @@ -1826,15 +1653,13 @@ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) cJSON *child = NULL; size_t size = 0; - if (array == NULL) - { + if (array == NULL) { return 0; } child = array->child; - while(child != NULL) - { + while (child != NULL) { size++; child = child->next; } @@ -1844,18 +1669,16 @@ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) return (int)size; } -static cJSON* get_array_item(const cJSON *array, size_t index) +static cJSON *get_array_item(const cJSON *array, size_t index) { cJSON *current_child = NULL; - if (array == NULL) - { + if (array == NULL) { return NULL; } current_child = array->child; - while ((current_child != NULL) && (index > 0)) - { + while ((current_child != NULL) && (index > 0)) { index--; current_child = current_child->next; } @@ -1865,35 +1688,30 @@ static cJSON* get_array_item(const cJSON *array, size_t index) CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) { - if (index < 0) - { + if (index < 0) { return NULL; } return get_array_item(array, (size_t)index); } -static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) +static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) { cJSON *current_element = NULL; - if ((object == NULL) || (name == NULL)) - { + if ((object == NULL) || (name == NULL)) { return NULL; } current_element = object->child; - if (case_sensitive) - { - while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) - { + if (case_sensitive) { + while ((current_element != NULL) && (current_element->string != NULL) && + (strcmp(name, current_element->string) != 0)) { current_element = current_element->next; } - } - else - { - while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) - { + } else { + while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char *)name, + (const unsigned char *)(current_element->string)) != 0)) { current_element = current_element->next; } } @@ -1905,12 +1723,12 @@ static cJSON *get_object_item(const cJSON * const object, const char * const nam return current_element; } -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *const object, const char *const string) { return get_object_item(object, string, false); } -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON *const object, const char *const string) { return get_object_item(object, string, true); } @@ -1928,17 +1746,15 @@ static void suffix_object(cJSON *prev, cJSON *item) } /* Utility for handling references. */ -static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) +static cJSON *create_reference(const cJSON *item, const internal_hooks *const hooks) { cJSON *reference = NULL; - if (item == NULL) - { + if (item == NULL) { return NULL; } reference = cJSON_New_Item(hooks); - if (reference == NULL) - { + if (reference == NULL) { return NULL; } @@ -1953,27 +1769,22 @@ static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) { cJSON *child = NULL; - if ((item == NULL) || (array == NULL) || (array == item)) - { + if ((item == NULL) || (array == NULL) || (array == item)) { return false; } child = array->child; /* - * To find the last item in array quickly, we use prev in array - */ - if (child == NULL) - { + * To find the last item in array quickly, we use prev in array + */ + if (child == NULL) { /* list is empty, start new one */ array->child = item; item->prev = item; item->next = NULL; - } - else - { + } else { /* append to the end */ - if (child->prev) - { + if (child->prev) { suffix_object(child->prev, item); array->child->prev = item; } @@ -1988,50 +1799,44 @@ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item) return add_item_to_array(array, item); } -#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) - #pragma GCC diagnostic push +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) +#pragma GCC diagnostic push #endif #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wcast-qual" #endif /* helper function to cast away const */ -static void* cast_away_const(const void* string) +static void *cast_away_const(const void *string) { - return (void*)string; + return (void *)string; } -#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) - #pragma GCC diagnostic pop +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) +#pragma GCC diagnostic pop #endif - -static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) +static cJSON_bool add_item_to_object(cJSON *const object, const char *const string, cJSON *const item, + const internal_hooks *const hooks, const cJSON_bool constant_key) { char *new_key = NULL; int new_type = cJSON_Invalid; - if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) - { + if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) { return false; } - if (constant_key) - { - new_key = (char*)cast_away_const(string); + if (constant_key) { + new_key = (char *)cast_away_const(string); new_type = item->type | cJSON_StringIsConst; - } - else - { - new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); - if (new_key == NULL) - { + } else { + new_key = (char *)cJSON_strdup((const unsigned char *)string, hooks); + if (new_key == NULL) { return false; } new_type = item->type & ~cJSON_StringIsConst; } - if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) - { + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { hooks->deallocate(item->string); } @@ -2054,8 +1859,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *stri CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) { - if (array == NULL) - { + if (array == NULL) { return false; } @@ -2064,19 +1868,17 @@ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) { - if ((object == NULL) || (string == NULL)) - { + if ((object == NULL) || (string == NULL)) { return false; } return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); } -CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) +CJSON_PUBLIC(cJSON *) cJSON_AddNullToObject(cJSON *const object, const char *const name) { cJSON *null = cJSON_CreateNull(); - if (add_item_to_object(object, name, null, &global_hooks, false)) - { + if (add_item_to_object(object, name, null, &global_hooks, false)) { return null; } @@ -2084,11 +1886,10 @@ CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * co return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) +CJSON_PUBLIC(cJSON *) cJSON_AddTrueToObject(cJSON *const object, const char *const name) { cJSON *true_item = cJSON_CreateTrue(); - if (add_item_to_object(object, name, true_item, &global_hooks, false)) - { + if (add_item_to_object(object, name, true_item, &global_hooks, false)) { return true_item; } @@ -2096,11 +1897,10 @@ CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * co return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) +CJSON_PUBLIC(cJSON *) cJSON_AddFalseToObject(cJSON *const object, const char *const name) { cJSON *false_item = cJSON_CreateFalse(); - if (add_item_to_object(object, name, false_item, &global_hooks, false)) - { + if (add_item_to_object(object, name, false_item, &global_hooks, false)) { return false_item; } @@ -2108,11 +1908,10 @@ CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * c return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) +CJSON_PUBLIC(cJSON *) cJSON_AddBoolToObject(cJSON *const object, const char *const name, const cJSON_bool boolean) { cJSON *bool_item = cJSON_CreateBool(boolean); - if (add_item_to_object(object, name, bool_item, &global_hooks, false)) - { + if (add_item_to_object(object, name, bool_item, &global_hooks, false)) { return bool_item; } @@ -2120,11 +1919,10 @@ CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * co return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) +CJSON_PUBLIC(cJSON *) cJSON_AddNumberToObject(cJSON *const object, const char *const name, const double number) { cJSON *number_item = cJSON_CreateNumber(number); - if (add_item_to_object(object, name, number_item, &global_hooks, false)) - { + if (add_item_to_object(object, name, number_item, &global_hooks, false)) { return number_item; } @@ -2132,11 +1930,10 @@ CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) +CJSON_PUBLIC(cJSON *) cJSON_AddStringToObject(cJSON *const object, const char *const name, const char *const string) { cJSON *string_item = cJSON_CreateString(string); - if (add_item_to_object(object, name, string_item, &global_hooks, false)) - { + if (add_item_to_object(object, name, string_item, &global_hooks, false)) { return string_item; } @@ -2144,11 +1941,10 @@ CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) +CJSON_PUBLIC(cJSON *) cJSON_AddRawToObject(cJSON *const object, const char *const name, const char *const raw) { cJSON *raw_item = cJSON_CreateRaw(raw); - if (add_item_to_object(object, name, raw_item, &global_hooks, false)) - { + if (add_item_to_object(object, name, raw_item, &global_hooks, false)) { return raw_item; } @@ -2156,11 +1952,10 @@ CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * con return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) +CJSON_PUBLIC(cJSON *) cJSON_AddObjectToObject(cJSON *const object, const char *const name) { cJSON *object_item = cJSON_CreateObject(); - if (add_item_to_object(object, name, object_item, &global_hooks, false)) - { + if (add_item_to_object(object, name, object_item, &global_hooks, false)) { return object_item; } @@ -2168,11 +1963,10 @@ CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) +CJSON_PUBLIC(cJSON *) cJSON_AddArrayToObject(cJSON *const object, const char *const name) { cJSON *array = cJSON_CreateArray(); - if (add_item_to_object(object, name, array, &global_hooks, false)) - { + if (add_item_to_object(object, name, array, &global_hooks, false)) { return array; } @@ -2180,31 +1974,25 @@ CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * c return NULL; } -CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item) { - if ((parent == NULL) || (item == NULL)) - { + if ((parent == NULL) || (item == NULL) || (item != parent->child && item->prev == NULL)) { return NULL; } - if (item != parent->child) - { + if (item != parent->child) { /* not the first element */ item->prev->next = item->next; } - if (item->next != NULL) - { + if (item->next != NULL) { /* not the last element */ item->next->prev = item->prev; } - if (item == parent->child) - { + if (item == parent->child) { /* first element */ parent->child = item->next; - } - else if (item->next == NULL) - { + } else if (item->next == NULL) { /* last element */ parent->child->prev = item->prev; } @@ -2218,8 +2006,7 @@ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const it CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) { - if (which < 0) - { + if (which < 0) { return NULL; } @@ -2260,69 +2047,60 @@ CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON { cJSON *after_inserted = NULL; - if (which < 0) - { + if (which < 0 || newitem == NULL) { return false; } after_inserted = get_array_item(array, (size_t)which); - if (after_inserted == NULL) - { + if (after_inserted == NULL) { return add_item_to_array(array, newitem); } + if (after_inserted != array->child && after_inserted->prev == NULL) { + /* return false if after_inserted is a corrupted array item */ + return false; + } + newitem->next = after_inserted; newitem->prev = after_inserted->prev; after_inserted->prev = newitem; - if (after_inserted == array->child) - { + if (after_inserted == array->child) { array->child = newitem; - } - else - { + } else { newitem->prev->next = newitem; } return true; } -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement) { - if ((parent == NULL) || (replacement == NULL) || (item == NULL)) - { + if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL)) { return false; } - if (replacement == item) - { + if (replacement == item) { return true; } replacement->next = item->next; replacement->prev = item->prev; - if (replacement->next != NULL) - { + if (replacement->next != NULL) { replacement->next->prev = replacement; } - if (parent->child == item) - { - if (parent->child->prev == parent->child) - { + if (parent->child == item) { + if (parent->child->prev == parent->child) { replacement->prev = replacement; } parent->child = replacement; - } - else - { /* - * To find the last item in array quickly, we use prev in array. - * We can't modify the last item's next pointer where this item was the parent's child - */ - if (replacement->prev != NULL) - { + } else { /* + * To find the last item in array quickly, we use prev in array. + * We can't modify the last item's next pointer where this item was the parent's child + */ + if (replacement->prev != NULL) { replacement->prev->next = replacement; } - if (replacement->next == NULL) - { + if (replacement->next == NULL) { parent->child->prev = replacement; } } @@ -2336,27 +2114,29 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) { - if (which < 0) - { + if (which < 0) { return false; } return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); } -static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) +static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, + cJSON_bool case_sensitive) { - if ((replacement == NULL) || (string == NULL)) - { + if ((replacement == NULL) || (string == NULL)) { return false; } /* replace the name in the replacement */ - if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) - { + if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) { cJSON_free(replacement->string); } - replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + replacement->string = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); + if (replacement->string == NULL) { + return false; + } + replacement->type &= ~cJSON_StringIsConst; return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); @@ -2376,8 +2156,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, c CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) { cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { + if (item) { item->type = cJSON_NULL; } @@ -2387,8 +2166,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) { cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { + if (item) { item->type = cJSON_True; } @@ -2398,8 +2176,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) { cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { + if (item) { item->type = cJSON_False; } @@ -2409,8 +2186,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) { cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { + if (item) { item->type = boolean ? cJSON_True : cJSON_False; } @@ -2420,22 +2196,16 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) { cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { + if (item) { item->type = cJSON_Number; item->valuedouble = num; /* use saturation in case of overflow */ - if (num >= INT_MAX) - { + if (num >= INT_MAX) { item->valueint = INT_MAX; - } - else if (num <= (double)INT_MIN) - { + } else if (num <= (double)INT_MIN) { item->valueint = INT_MIN; - } - else - { + } else { item->valueint = (int)num; } } @@ -2446,12 +2216,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) { cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { + if (item) { item->type = cJSON_String; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - if(!item->valuestring) - { + item->valuestring = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); + if (!item->valuestring) { cJSON_Delete(item); return NULL; } @@ -2463,10 +2231,9 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) { cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) - { + if (item != NULL) { item->type = cJSON_String | cJSON_IsReference; - item->valuestring = (char*)cast_away_const(string); + item->valuestring = (char *)cast_away_const(string); } return item; @@ -2477,17 +2244,18 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) cJSON *item = cJSON_New_Item(&global_hooks); if (item != NULL) { item->type = cJSON_Object | cJSON_IsReference; - item->child = (cJSON*)cast_away_const(child); + item->child = (cJSON *)cast_away_const(child); } return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) +{ cJSON *item = cJSON_New_Item(&global_hooks); if (item != NULL) { item->type = cJSON_Array | cJSON_IsReference; - item->child = (cJSON*)cast_away_const(child); + item->child = (cJSON *)cast_away_const(child); } return item; @@ -2496,12 +2264,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) { cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { + if (item) { item->type = cJSON_Raw; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); - if(!item->valuestring) - { + item->valuestring = (char *)cJSON_strdup((const unsigned char *)raw, &global_hooks); + if (!item->valuestring) { cJSON_Delete(item); return NULL; } @@ -2513,9 +2279,8 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) { cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type=cJSON_Array; + if (item) { + item->type = cJSON_Array; } return item; @@ -2524,8 +2289,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) { cJSON *item = cJSON_New_Item(&global_hooks); - if (item) - { + if (item) { item->type = cJSON_Object; } @@ -2540,27 +2304,21 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) cJSON *p = NULL; cJSON *a = NULL; - if ((count < 0) || (numbers == NULL)) - { + if ((count < 0) || (numbers == NULL)) { return NULL; } a = cJSON_CreateArray(); - for(i = 0; a && (i < (size_t)count); i++) - { + for (i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateNumber(numbers[i]); - if (!n) - { + if (!n) { cJSON_Delete(a); return NULL; } - if(!i) - { + if (!i) { a->child = n; - } - else - { + } else { suffix_object(p, n); } p = n; @@ -2580,27 +2338,21 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) cJSON *p = NULL; cJSON *a = NULL; - if ((count < 0) || (numbers == NULL)) - { + if ((count < 0) || (numbers == NULL)) { return NULL; } a = cJSON_CreateArray(); - for(i = 0; a && (i < (size_t)count); i++) - { + for (i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateNumber((double)numbers[i]); - if(!n) - { + if (!n) { cJSON_Delete(a); return NULL; } - if(!i) - { + if (!i) { a->child = n; - } - else - { + } else { suffix_object(p, n); } p = n; @@ -2620,27 +2372,21 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) cJSON *p = NULL; cJSON *a = NULL; - if ((count < 0) || (numbers == NULL)) - { + if ((count < 0) || (numbers == NULL)) { return NULL; } a = cJSON_CreateArray(); - for(i = 0; a && (i < (size_t)count); i++) - { + for (i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateNumber(numbers[i]); - if(!n) - { + if (!n) { cJSON_Delete(a); return NULL; } - if(!i) - { + if (!i) { a->child = n; - } - else - { + } else { suffix_object(p, n); } p = n; @@ -2660,28 +2406,22 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int co cJSON *p = NULL; cJSON *a = NULL; - if ((count < 0) || (strings == NULL)) - { + if ((count < 0) || (strings == NULL)) { return NULL; } a = cJSON_CreateArray(); - for (i = 0; a && (i < (size_t)count); i++) - { + for (i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateString(strings[i]); - if(!n) - { + if (!n) { cJSON_Delete(a); return NULL; } - if(!i) - { + if (!i) { a->child = n; - } - else - { - suffix_object(p,n); + } else { + suffix_object(p, n); } p = n; } @@ -2689,7 +2429,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int co if (a && a->child) { a->child->prev = n; } - + return a; } @@ -2702,75 +2442,63 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) cJSON *newchild = NULL; /* Bail on bad ptr */ - if (!item) - { + if (!item) { goto fail; } /* Create new item */ newitem = cJSON_New_Item(&global_hooks); - if (!newitem) - { + if (!newitem) { goto fail; } /* Copy over all vars */ newitem->type = item->type & (~cJSON_IsReference); newitem->valueint = item->valueint; newitem->valuedouble = item->valuedouble; - if (item->valuestring) - { - newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); - if (!newitem->valuestring) - { + if (item->valuestring) { + newitem->valuestring = (char *)cJSON_strdup((unsigned char *)item->valuestring, &global_hooks); + if (!newitem->valuestring) { goto fail; } } - if (item->string) - { - newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); - if (!newitem->string) - { + if (item->string) { + newitem->string = (item->type & cJSON_StringIsConst) + ? item->string + : (char *)cJSON_strdup((unsigned char *)item->string, &global_hooks); + if (!newitem->string) { goto fail; } } /* If non-recursive, then we're done! */ - if (!recurse) - { + if (!recurse) { return newitem; } /* Walk the ->next chain for the child. */ child = item->child; - while (child != NULL) - { + while (child != NULL) { newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ - if (!newchild) - { + if (!newchild) { goto fail; } - if (next != NULL) - { + if (next != NULL) { /* If newitem->child already set, then crosswire ->prev and ->next and move on */ next->next = newchild; newchild->prev = next; next = newchild; - } - else - { + } else { /* Set newitem->child and move to it */ newitem->child = newchild; next = newchild; } child = child->next; } - if (newitem && newitem->child) - { + if (newitem && newitem->child) { newitem->child->prev = newchild; } return newitem; fail: - if (newitem != NULL) - { + if (newitem != NULL) { cJSON_Delete(newitem); } @@ -2781,8 +2509,7 @@ static void skip_oneline_comment(char **input) { *input += static_strlen("//"); - for (; (*input)[0] != '\0'; ++(*input)) - { + for (; (*input)[0] != '\0'; ++(*input)) { if ((*input)[0] == '\n') { *input += static_strlen("\n"); return; @@ -2794,22 +2521,20 @@ static void skip_multiline_comment(char **input) { *input += static_strlen("/*"); - for (; (*input)[0] != '\0'; ++(*input)) - { - if (((*input)[0] == '*') && ((*input)[1] == '/')) - { + for (; (*input)[0] != '\0'; ++(*input)) { + if (((*input)[0] == '*') && ((*input)[1] == '/')) { *input += static_strlen("*/"); return; } } } -static void minify_string(char **input, char **output) { +static void minify_string(char **input, char **output) +{ (*output)[0] = (*input)[0]; *input += static_strlen("\""); *output += static_strlen("\""); - for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { (*output)[0] = (*input)[0]; @@ -2830,15 +2555,12 @@ CJSON_PUBLIC(void) cJSON_Minify(char *json) { char *into = json; - if (json == NULL) - { + if (json == NULL) { return; } - while (json[0] != '\0') - { - switch (json[0]) - { + while (json[0] != '\0') { + switch (json[0]) { case ' ': case '\t': case '\r': @@ -2847,12 +2569,9 @@ CJSON_PUBLIC(void) cJSON_Minify(char *json) break; case '/': - if (json[1] == '/') - { + if (json[1] == '/') { skip_oneline_comment(&json); - } - else if (json[1] == '*') - { + } else if (json[1] == '*') { skip_multiline_comment(&json); } else { json++; @@ -2860,7 +2579,7 @@ CJSON_PUBLIC(void) cJSON_Minify(char *json) break; case '\"': - minify_string(&json, (char**)&into); + minify_string(&json, (char **)&into); break; default: @@ -2874,116 +2593,103 @@ CJSON_PUBLIC(void) cJSON_Minify(char *json) *into = '\0'; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_Invalid; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_False; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xff) == cJSON_True; } - -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & (cJSON_True | cJSON_False)) != 0; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_NULL; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_Number; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_String; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_Array; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_Object; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_Raw; } -CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive) { - if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) - { + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) { return false; } /* check if type is valid */ - switch (a->type & 0xFF) - { + switch (a->type & 0xFF) { case cJSON_False: case cJSON_True: case cJSON_NULL: @@ -2999,13 +2705,11 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons } /* identical objects are equal */ - if (a == b) - { + if (a == b) { return true; } - switch (a->type & 0xFF) - { + switch (a->type & 0xFF) { /* in these cases and equal type is enough */ case cJSON_False: case cJSON_True: @@ -3013,34 +2717,28 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons return true; case cJSON_Number: - if (compare_double(a->valuedouble, b->valuedouble)) - { + if (compare_double(a->valuedouble, b->valuedouble)) { return true; } return false; case cJSON_String: case cJSON_Raw: - if ((a->valuestring == NULL) || (b->valuestring == NULL)) - { + if ((a->valuestring == NULL) || (b->valuestring == NULL)) { return false; } - if (strcmp(a->valuestring, b->valuestring) == 0) - { + if (strcmp(a->valuestring, b->valuestring) == 0) { return true; } return false; - case cJSON_Array: - { + case cJSON_Array: { cJSON *a_element = a->child; cJSON *b_element = b->child; - for (; (a_element != NULL) && (b_element != NULL);) - { - if (!cJSON_Compare(a_element, b_element, case_sensitive)) - { + for (; (a_element != NULL) && (b_element != NULL);) { + if (!cJSON_Compare(a_element, b_element, case_sensitive)) { return false; } @@ -3056,37 +2754,32 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons return true; } - case cJSON_Object: - { + case cJSON_Object: { cJSON *a_element = NULL; cJSON *b_element = NULL; cJSON_ArrayForEach(a_element, a) { /* TODO This has O(n^2) runtime, which is horrible! */ b_element = get_object_item(b, a_element->string, case_sensitive); - if (b_element == NULL) - { + if (b_element == NULL) { return false; } - if (!cJSON_Compare(a_element, b_element, case_sensitive)) - { + if (!cJSON_Compare(a_element, b_element, case_sensitive)) { return false; } } /* doing this twice, once on a and b to prevent true comparison if a subset of b - * TODO: Do this the proper way, this is just a fix for now */ + * TODO: Do this the proper way, this is just a fix for now */ cJSON_ArrayForEach(b_element, b) { a_element = get_object_item(a, b_element->string, case_sensitive); - if (a_element == NULL) - { + if (a_element == NULL) { return false; } - if (!cJSON_Compare(b_element, a_element, case_sensitive)) - { + if (!cJSON_Compare(b_element, a_element, case_sensitive)) { return false; } }